nixos/varnish: turn listen addresses into structured config
Introduces `services.varnish.listen` as a list of structured listen addresses with all allowed variations of arguments documented in the man page. Deprecates `services.varnish.http_address`.
This commit is contained in:
		
							parent
							
								
									3016b4b15d
								
							
						
					
					
						commit
						8046e4a6f8
					
				| @ -103,4 +103,7 @@ | ||||
| - `amdgpu` kernel driver overdrive mode can now be enabled by setting [hardware.amdgpu.overdrive.enable](#opt-hardware.amdgpu.overdrive.enable) and customized through [hardware.amdgpu.overdrive.ppfeaturemask](#opt-hardware.amdgpu.overdrive.ppfeaturemask). | ||||
|   This allows for fine-grained control over the GPU's performance and maybe required by overclocking softwares like Corectrl and Lact. These new options replace old options such as {option}`programs.corectrl.gpuOverclock.enable` and {option}`programs.tuxclocker.enableAMD`. | ||||
| 
 | ||||
| - `services.varnish.http_address` has been superseeded by `services.varnish.listen` which is now | ||||
|   structured config for all of varnish's `-a` variations. | ||||
| 
 | ||||
| - [](#opt-services.gnome.gnome-keyring.enable) does not ship with an SSH agent anymore, as this is now handled by the `gcr_4` package instead of `gnome-keyring`. A new module has been added to support this, under [](#opt-services.gnome.gcr-ssh-agent.enable) (its default value has been set to [](#opt-services.gnome.gnome-keyring.enable) to ensure a smooth transition). See the [relevant upstream PR](https://gitlab.gnome.org/GNOME/gcr/-/merge_requests/67) for more details. | ||||
|  | ||||
| @ -6,6 +6,16 @@ | ||||
| }: | ||||
| 
 | ||||
| let | ||||
|   inherit (lib) | ||||
|     types | ||||
|     mkOption | ||||
|     hasPrefix | ||||
|     concatMapStringsSep | ||||
|     optionalString | ||||
|     concatMap | ||||
|     ; | ||||
|   inherit (builtins) isNull; | ||||
| 
 | ||||
|   cfg = config.services.varnish; | ||||
| 
 | ||||
|   # Varnish has very strong opinions and very complicated code around handling | ||||
| @ -26,6 +36,91 @@ let | ||||
|     else | ||||
|       "/var/run/varnishd"; | ||||
| 
 | ||||
|   # from --help: | ||||
|   #   -a [<name>=]address[:port][,proto] # HTTP listen address and port | ||||
|   #      [,user=<u>][,group=<g>]   # Can be specified multiple times. | ||||
|   #      [,mode=<m>]               #   default: ":80,HTTP" | ||||
|   #                                # Proto can be "PROXY" or "HTTP" (default) | ||||
|   #                                # user, group and mode set permissions for | ||||
|   #                                #   a Unix domain socket. | ||||
|   commandLineAddresses = | ||||
|     (concatMapStringsSep " " ( | ||||
|       a: | ||||
|       "-a " | ||||
|       + optionalString (!isNull a.name) "${a.name}=" | ||||
|       + a.address | ||||
|       + optionalString (!isNull a.port) ":${toString a.port}" | ||||
|       + optionalString (!isNull a.proto) ",${a.proto}" | ||||
|       + optionalString (!isNull a.user) ",user=${a.user}" | ||||
|       + optionalString (!isNull a.group) ",group=${a.group}" | ||||
|       + optionalString (!isNull a.mode) ",mode=${a.mode}" | ||||
|     ) cfg.listen) | ||||
|     + lib.optionalString (!isNull cfg.http_address) " -a ${cfg.http_address}"; | ||||
|   addressSubmodule = types.submodule { | ||||
|     options = { | ||||
|       name = mkOption { | ||||
|         description = "Name is referenced in logs. If name is not specified, 'a0', 'a1', etc. is used."; | ||||
|         default = null; | ||||
|         type = with types; nullOr str; | ||||
|       }; | ||||
|       address = mkOption { | ||||
|         description = '' | ||||
|           If given an IP address, it can be a host name ("localhost"), an IPv4 dotted-quad | ||||
|           ("127.0.0.1") or an IPv6  address enclosed in square brackets ("[::1]"). | ||||
| 
 | ||||
|           (VCL4.1 and higher) If given an absolute Path ("/path/to/listen.sock") or "@" | ||||
|           followed by the name of an abstract socket ("@myvarnishd") accept connections | ||||
|           on a Unix domain socket. | ||||
| 
 | ||||
|           The user, group and mode sub-arguments may be used to specify the permissions | ||||
|           of the socket file. These sub-arguments do not apply to  abstract sockets. | ||||
|         ''; | ||||
|         type = types.str; | ||||
|       }; | ||||
|       port = mkOption { | ||||
|         description = "The port to use for IP sockets. If port is not specified, port 80 (http) is used."; | ||||
|         default = null; | ||||
|         type = with types; nullOr int; | ||||
|       }; | ||||
|       proto = mkOption { | ||||
|         description = "PROTO can be 'HTTP' (the default) or 'PROXY'.  Both version 1 and 2 of the proxy protocol can be used."; | ||||
|         type = types.enum [ | ||||
|           "HTTP" | ||||
|           "PROXY" | ||||
|         ]; | ||||
|         default = "HTTP"; | ||||
|       }; | ||||
|       user = mkOption { | ||||
|         description = "User name who owns the socket file."; | ||||
|         default = null; | ||||
|         type = with lib.types; nullOr str; | ||||
|       }; | ||||
|       group = mkOption { | ||||
|         description = "Group name who owns the socket file."; | ||||
|         default = null; | ||||
|         type = with lib.types; nullOr str; | ||||
|       }; | ||||
|       mode = mkOption { | ||||
|         description = "Permission of the socket file (3-digit octal value)."; | ||||
|         default = null; | ||||
|         type = with types; nullOr str; | ||||
|       }; | ||||
|     }; | ||||
|   }; | ||||
|   checkedAddressModule = types.addCheck addressSubmodule ( | ||||
|     m: | ||||
|     ( | ||||
|       if ((hasPrefix "@" m.address) || (hasPrefix "/" m.address)) then | ||||
|         # this is a unix socket | ||||
|         (m.port != null) | ||||
|       else | ||||
|       # this is not a path-based unix socket | ||||
|       if !(hasPrefix "/" m.address) && (m.group != null) || (m.user != null) || (m.mode != null) then | ||||
|         false | ||||
|       else | ||||
|         true | ||||
|     ) | ||||
|   ); | ||||
|   commandLine = | ||||
|     "-f ${pkgs.writeText "default.vcl" cfg.config}" | ||||
|     + | ||||
| @ -54,13 +149,23 @@ in | ||||
|       package = lib.mkPackageOption pkgs "varnish" { }; | ||||
| 
 | ||||
|       http_address = lib.mkOption { | ||||
|         type = lib.types.str; | ||||
|         default = "*:6081"; | ||||
|         type = with lib.types; nullOr str; | ||||
|         default = null; | ||||
|         description = '' | ||||
|           HTTP listen address and port. | ||||
|         ''; | ||||
|       }; | ||||
| 
 | ||||
|       listen = lib.mkOption { | ||||
|         description = "Accept for client requests on the specified listen addresses."; | ||||
|         type = lib.types.listOf checkedAddressModule; | ||||
|         defaultText = lib.literalExpression ''[ { address="*"; port=6081; } ]''; | ||||
|         default = lib.optional (isNull cfg.http_address) { | ||||
|           address = "*"; | ||||
|           port = 6081; | ||||
|         }; | ||||
|       }; | ||||
| 
 | ||||
|       config = lib.mkOption { | ||||
|         type = lib.types.lines; | ||||
|         description = '' | ||||
| @ -97,7 +202,7 @@ in | ||||
|       serviceConfig = { | ||||
|         Type = "simple"; | ||||
|         PermissionsStartOnly = true; | ||||
|         ExecStart = "${cfg.package}/sbin/varnishd -a ${cfg.http_address} -n ${stateDir} -F ${cfg.extraCommandLine} ${commandLine}"; | ||||
|         ExecStart = "${cfg.package}/sbin/varnishd ${commandLineAddresses} -n ${stateDir} -F ${cfg.extraCommandLine} ${commandLine}"; | ||||
|         Restart = "always"; | ||||
|         RestartSec = "5s"; | ||||
|         User = "varnish"; | ||||
| @ -118,6 +223,21 @@ in | ||||
|       '') | ||||
|     ]; | ||||
| 
 | ||||
|     assertions = concatMap (m: [ | ||||
|       { | ||||
|         assertion = (hasPrefix "/" m.address) || (hasPrefix "@" m.address) -> m.port == null; | ||||
|         message = "Listen ports must not be specified with UNIX sockets: ${builtins.toJSON m}"; | ||||
|       } | ||||
|       { | ||||
|         assertion = !(hasPrefix "/" m.address) -> m.user == null && m.group == null && m.mode == null; | ||||
|         message = "Abstract UNIX sockets or IP sockets can not be used with user, group, and mode settings: ${builtins.toJSON m}"; | ||||
|       } | ||||
|     ]) cfg.listen; | ||||
| 
 | ||||
|     warnings = | ||||
|       lib.optional (!isNull cfg.http_address) | ||||
|         "The option `services.varnish.http_address` is deprecated. Use `services.varnish.listen` instead."; | ||||
| 
 | ||||
|     users.users.varnish = { | ||||
|       group = "varnish"; | ||||
|       uid = config.ids.uids.varnish; | ||||
|  | ||||
| @ -10,7 +10,12 @@ in | ||||
| 
 | ||||
|   nodes = { | ||||
|     varnish = | ||||
|       { config, pkgs, ... }: | ||||
|       { | ||||
|         config, | ||||
|         pkgs, | ||||
|         lib, | ||||
|         ... | ||||
|       }: | ||||
|       { | ||||
|         services.nix-serve = { | ||||
|           enable = true; | ||||
| @ -19,9 +24,29 @@ in | ||||
|         services.varnish = { | ||||
|           inherit package; | ||||
|           enable = true; | ||||
|           http_address = "0.0.0.0:80"; | ||||
|           http_address = "0.0.0.0:81"; | ||||
|           listen = [ | ||||
|             { | ||||
|               address = "0.0.0.0"; | ||||
|               port = 80; | ||||
|               proto = "HTTP"; | ||||
|             } | ||||
|             { | ||||
|               name = "proxyport"; | ||||
|               address = "0.0.0.0"; | ||||
|               port = 8080; | ||||
|               proto = "PROXY"; | ||||
|             } | ||||
|             { address = "@asdf"; } | ||||
|             { | ||||
|               address = "/run/varnishd/client.http.sock"; | ||||
|               user = "varnish"; | ||||
|               group = "varnish"; | ||||
|               mode = "660"; | ||||
|             } | ||||
|           ]; | ||||
|           config = '' | ||||
|             vcl 4.0; | ||||
|             vcl 4.1; | ||||
| 
 | ||||
|             backend nix-serve { | ||||
|               .host = "127.0.0.1"; | ||||
| @ -32,6 +57,26 @@ in | ||||
| 
 | ||||
|         networking.firewall.allowedTCPPorts = [ 80 ]; | ||||
|         system.extraDependencies = [ testPath ]; | ||||
| 
 | ||||
|         assertions = | ||||
|           map | ||||
|             ( | ||||
|               pattern: | ||||
|               let | ||||
|                 cmdline = config.systemd.services.varnish.serviceConfig.ExecStart; | ||||
|               in | ||||
|               { | ||||
|                 assertion = lib.hasInfix pattern cmdline; | ||||
|                 message = "Address argument `${pattern}` missing in commandline `${cmdline}`."; | ||||
|               } | ||||
|             ) | ||||
|             [ | ||||
|               " -a 0.0.0.0:80,HTTP " | ||||
|               " -a proxyport=0.0.0.0:8080,PROXY " | ||||
|               " -a @asdf,HTTP " | ||||
|               " -a /run/varnishd/client.http.sock,HTTP,user=varnish,group=varnish,mode=660 " | ||||
|               " -a 0.0.0.0:81 " | ||||
|             ]; | ||||
|       }; | ||||
| 
 | ||||
|     client = | ||||
| @ -48,6 +93,7 @@ in | ||||
|     start_all() | ||||
|     varnish.wait_for_open_port(80) | ||||
| 
 | ||||
| 
 | ||||
|     client.wait_until_succeeds("curl -f http://varnish/nix-cache-info"); | ||||
| 
 | ||||
|     client.wait_until_succeeds("nix-store -r ${testPath}") | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user
	 Christian Theune
						Christian Theune