12 cfg = config.services.privoxy;
17 concatMapStrings (serialise name) val
18 else if isBool val then
19 serialise name (if val then "1" else "0")
21 "${name} ${toString val}\n";
33 attrsOf (either atom (listOf atom))
36 privoxy configuration type. The format consists of an attribute
37 set of settings. Each setting can be either a value (integer, string,
38 boolean or path) or a list of such values.
42 ageType = types.str // {
43 check = x: isString x && (builtins.match "([0-9]+([smhdw]|min|ms|us)*)+" x != null);
44 description = "tmpfiles.d(5) age format";
47 configFile = pkgs.writeText "privoxy.conf" (
49 # Relative paths in some options are relative to confdir. Privoxy seems
50 # to parse the options in order of appearance, so this must come first.
51 # Nix however doesn't preserve the order in attrsets, so we have to
52 # hardcode confdir here.
53 [ "confdir ${pkgs.privoxy}/etc\n" ] ++ mapAttrsToList serialise cfg.settings
57 inspectAction = pkgs.writeText "inspect-all-https.action" ''
58 # Enable HTTPS inspection for all requests
69 options.services.privoxy = {
71 enable = mkEnableOption "Privoxy, non-caching filtering proxy";
73 enableTor = mkOption {
77 Whether to configure Privoxy to use Tor's faster SOCKS port,
82 inspectHttps = mkOption {
86 Whether to configure Privoxy to inspect HTTPS requests, meaning all
87 encrypted traffic will be filtered as well. This works by decrypting
88 and re-encrypting the requests using a per-domain generated certificate.
90 To issue per-domain certificates, Privoxy must be provided with a CA
91 certificate, using the `ca-cert-file`,
92 `ca-key-file` settings.
95 The CA certificate must also be added to the system trust roots,
96 otherwise browsers will reject all Privoxy certificates as invalid.
97 You can do so by using the option
98 {option}`security.pki.certificateFiles`.
103 certsLifetime = mkOption {
108 If `inspectHttps` is enabled, the time generated HTTPS
109 certificates will be stored in a temporary directory for reuse. Once
110 the lifetime has expired the directory will cleared and the certificate
111 will have to be generated again, on-demand.
113 Depending on the traffic, you may want to reduce the lifetime to limit
114 the disk usage, since Privoxy itself never deletes the certificates.
117 The format is that of the `tmpfiles.d(5)`
123 userActions = mkOption {
127 Actions to be included in a `user.action` file. This
128 will have a higher priority and can be used to override all other
133 userFilters = mkOption {
137 Filters to be included in a `user.filter` file. This
138 will have a higher priority and can be used to override all other
143 settings = mkOption {
144 type = types.submodule {
145 freeformType = configType;
147 options.listen-address = mkOption {
149 default = "127.0.0.1:8118";
150 description = "Pair of address:port the proxy server is listening to.";
153 options.enable-edit-actions = mkOption {
156 description = "Whether the web-based actions file editor may be used.";
159 options.actionsfile = mkOption {
160 type = types.listOf types.str;
161 # This must come after all other entries, in order to override the
162 # other actions/filters installed by Privoxy or the user.
164 x: x ++ optional (cfg.userActions != "") (toString (pkgs.writeText "user.actions" cfg.userActions));
170 List of paths to Privoxy action files. These paths may either be
171 absolute or relative to the privoxy configuration directory.
175 options.filterfile = mkOption {
176 type = types.listOf types.str;
177 default = [ "default.filter" ];
179 x: x ++ optional (cfg.userFilters != "") (toString (pkgs.writeText "user.filter" cfg.userFilters));
181 List of paths to Privoxy filter files. These paths may either be
182 absolute or relative to the privoxy configuration directory.
187 example = literalExpression ''
188 { # Listen on IPv6 only
189 listen-address = "[::]:8118";
191 # Forward .onion requests to Tor
192 forward-socks5 = ".onion localhost:9050 .";
194 # Log redirects and filters
196 # This is equivalent to writing these lines
197 # in the Privoxy configuration file:
203 This option is mapped to the main Privoxy configuration file.
204 Check out the Privoxy user manual at
205 <https://www.privoxy.org/user-manual/config.html>
206 for available settings and documentation.
209 Repeated settings can be represented by using a list.
216 ###### implementation
218 config = mkIf cfg.enable {
220 users.users.privoxy = {
221 description = "Privoxy daemon user";
226 users.groups.privoxy = { };
228 systemd.tmpfiles.rules = optional cfg.inspectHttps "d ${cfg.settings.certificate-directory} 0770 privoxy privoxy ${cfg.certsLifetime}";
230 systemd.services.privoxy = {
231 description = "Filtering web proxy";
236 wantedBy = [ "multi-user.target" ];
240 ExecStart = "${pkgs.privoxy}/bin/privoxy --no-daemon ${configFile}";
241 PrivateDevices = true;
244 ProtectSystem = "full";
246 unitConfig = mkIf cfg.inspectHttps {
247 ConditionPathExists = with cfg.settings; [
254 services.tor.settings.SOCKSPort = mkIf cfg.enableTor [
255 # Route HTTP traffic over a faster port (without IsolateDestAddr).
259 IsolateDestAddr = false;
263 services.privoxy.settings =
265 user-manual = "${pkgs.privoxy}/share/doc/privoxy/user-manual";
266 # This is needed for external filters
267 temporary-directory = "/tmp";
268 filterfile = [ "default.filter" ];
272 ] ++ optional cfg.inspectHttps (toString inspectAction);
274 // (optionalAttrs cfg.enableTor {
275 forward-socks5 = "/ 127.0.0.1:9063 .";
277 enable-remote-toggle = false;
278 enable-edit-actions = false;
279 enable-remote-http-toggle = false;
281 // (optionalAttrs cfg.inspectHttps {
282 # This allows setting absolute key/crt paths
283 ca-directory = "/var/empty";
284 certificate-directory = "/run/privoxy/certs";
285 trusted-cas-file = "/etc/ssl/certs/ca-certificates.crt";
305 (mkRenamedOptionModule (top "enableEditActions") (setting "enable-edit-actions"))
306 (mkRenamedOptionModule (top "listenAddress") (setting "listen-address"))
307 (mkRenamedOptionModule (top "actionsFiles") (setting "actionsfile"))
308 (mkRenamedOptionModule (top "filterFiles") (setting "filterfile"))
309 (mkRemovedOptionModule (top "extraConfig") ''
310 Use services.privoxy.settings instead.
311 This is part of the general move to use structured settings instead of raw
312 text for config as introduced by RFC0042:
313 https://github.com/NixOS/rfcs/blob/master/rfcs/0042-config-option.md
317 meta.maintainers = with lib.maintainers; [ rnhmjoj ];