117 lines
		
	
	
		
			3.6 KiB
		
	
	
	
		
			Nix
		
	
	
	
	
	
			
		
		
	
	
			117 lines
		
	
	
		
			3.6 KiB
		
	
	
	
		
			Nix
		
	
	
	
	
	
{ config, pkgs, lib, ... }:
 | 
						|
let
 | 
						|
  cfg = config.environment.robots-txt;
 | 
						|
 | 
						|
  robots-txt-format = {
 | 
						|
    type = let
 | 
						|
      coercedStrToNonEmptyListOfStr = lib.types.coercedTo lib.types.str lib.singleton (lib.types.nonEmptyListOf lib.types.str);
 | 
						|
    in lib.types.listOf (lib.types.submodule {
 | 
						|
      freeformType = lib.types.attrsOf coercedStrToNonEmptyListOfStr;
 | 
						|
      options = {
 | 
						|
        pre_comment = lib.mkOption {
 | 
						|
          description = "Comment to add before the rule";
 | 
						|
          type = lib.types.lines;
 | 
						|
          default = "";
 | 
						|
        };
 | 
						|
        post_comment = lib.mkOption {
 | 
						|
          description = "Comment to add after the rule";
 | 
						|
          type = lib.types.lines;
 | 
						|
          default = "";
 | 
						|
        };
 | 
						|
      };
 | 
						|
    });
 | 
						|
 | 
						|
    generate = name: value: let
 | 
						|
      makeComment = comment: lib.pipe comment [
 | 
						|
        (lib.splitString "\n")
 | 
						|
        (lib.map (line: if line == "" then "#" else "# ${line}"))
 | 
						|
        (lib.concatStringsSep "\n")
 | 
						|
      ];
 | 
						|
 | 
						|
      ruleToString = rule: let
 | 
						|
        user_agent = rule.User-agent or [];
 | 
						|
        pre_comment = rule.pre_comment;
 | 
						|
        post_comment = rule.post_comment;
 | 
						|
        rest = builtins.removeAttrs rule [ "User-agent" "pre_comment" "post_comment" ];
 | 
						|
      in lib.concatStringsSep "\n" (lib.filter (x: x != null) [
 | 
						|
        (if (pre_comment != "") then makeComment pre_comment else null)
 | 
						|
        (let
 | 
						|
          user-agents = lib.concatMapStringsSep "\n" (value: "User-agent: ${value}") user_agent;
 | 
						|
        in
 | 
						|
          if user_agent == [] then null else user-agents
 | 
						|
        )
 | 
						|
        (lib.pipe rest [
 | 
						|
          (lib.mapAttrsToList (ruleName: map (value: "${ruleName}: ${value}")))
 | 
						|
          lib.concatLists
 | 
						|
          (lib.concatStringsSep "\n")
 | 
						|
        ])
 | 
						|
        (if (post_comment != "") then makeComment post_comment else null)
 | 
						|
      ]);
 | 
						|
 | 
						|
      content = lib.concatMapStringsSep "\n\n" ruleToString value;
 | 
						|
    in pkgs.writeText name content;
 | 
						|
  };
 | 
						|
in
 | 
						|
{
 | 
						|
  options.environment.robots-txt = lib.mkOption {
 | 
						|
    default = { };
 | 
						|
    description = ''
 | 
						|
      Different instances of robots.txt to use with web services.
 | 
						|
    '';
 | 
						|
    type = lib.types.attrsOf (lib.types.submodule ({ name, ... }: {
 | 
						|
      options = {
 | 
						|
        enable = lib.mkEnableOption "this instance of robots.txt" // {
 | 
						|
          default = true;
 | 
						|
        };
 | 
						|
 | 
						|
        path = lib.mkOption {
 | 
						|
          description = "The resulting path of the dir containing the robots.txt file";
 | 
						|
          type = lib.types.path;
 | 
						|
          readOnly = true;
 | 
						|
          default = "/etc/robots-txt/${name}";
 | 
						|
        };
 | 
						|
 | 
						|
        rules = lib.mkOption {
 | 
						|
          description = "Rules to include in robots.txt";
 | 
						|
          default = [ ];
 | 
						|
          example = [
 | 
						|
            { User-agent = "Googlebot"; Disallow = "/no-googlebot"; }
 | 
						|
            { User-agent = "Bingbot"; Disallow = [ "/no-bingbot" "/no-bingbot2" ]; }
 | 
						|
          ];
 | 
						|
          type = robots-txt-format.type;
 | 
						|
        };
 | 
						|
 | 
						|
        virtualHost = lib.mkOption {
 | 
						|
          description = "An nginx virtual host to add the robots.txt to";
 | 
						|
          type = lib.types.nullOr lib.types.str;
 | 
						|
          default = null;
 | 
						|
        };
 | 
						|
      };
 | 
						|
    }));
 | 
						|
  };
 | 
						|
 | 
						|
  config = {
 | 
						|
    environment.etc = lib.mapAttrs' (name: value: {
 | 
						|
      name = "robots-txt/${name}/robots.txt";
 | 
						|
      value.source = robots-txt-format.generate name value.rules;
 | 
						|
    }) cfg;
 | 
						|
 | 
						|
    services.nginx.virtualHosts = lib.pipe cfg [
 | 
						|
      (lib.filterAttrs (_: value: value.virtualHost != null))
 | 
						|
      (lib.mapAttrs' (name: value: {
 | 
						|
        name = value.virtualHost;
 | 
						|
        value = {
 | 
						|
          locations = {
 | 
						|
            "= /robots.txt" = {
 | 
						|
              extraConfig = ''
 | 
						|
                add_header Content-Type text/plain;
 | 
						|
              '';
 | 
						|
              root = cfg.${name}.path;
 | 
						|
            };
 | 
						|
          };
 | 
						|
        };
 | 
						|
      }))
 | 
						|
    ];
 | 
						|
  };
 | 
						|
}
 |