1 { config, lib, pkgs, ... }:
6 cfg = config.services.tor;
7 torDirectory = "/var/lib/tor";
8 torRunDirectory = "/run/tor";
10 opt = name: value: optionalString (value != null) "${name} ${value}";
11 optint = name: value: optionalString (value != null && value != 0) "${name} ${toString value}";
14 type = types.listOf (types.enum [
17 "IsolateClientProtocol"
25 "IsolateClientProtocol"
29 description = "Tor isolation options";
35 DataDirectory ${torDirectory}
36 ${optionalString cfg.enableGeoIP ''
37 GeoIPFile ${cfg.package.geoip}/share/tor/geoip
38 GeoIPv6File ${cfg.package.geoip}/share/tor/geoip6
41 ${optint "ControlPort" cfg.controlPort}
42 ${optionalString cfg.controlSocket.enable "ControlPort unix:${torRunDirectory}/control GroupWritable RelaxDirModeCheck"}
44 # Client connection config
45 + optionalString cfg.client.enable ''
46 SOCKSPort ${cfg.client.socksListenAddress} ${toString cfg.client.socksIsolationOptions}
47 SOCKSPort ${cfg.client.socksListenAddressFaster}
48 ${opt "SocksPolicy" cfg.client.socksPolicy}
50 ${optionalString cfg.client.transparentProxy.enable ''
51 TransPort ${cfg.client.transparentProxy.listenAddress} ${toString cfg.client.transparentProxy.isolationOptions}
54 ${optionalString cfg.client.dns.enable ''
55 DNSPort ${cfg.client.dns.listenAddress} ${toString cfg.client.dns.isolationOptions}
56 AutomapHostsOnResolve 1
57 AutomapHostsSuffixes ${concatStringsSep "," cfg.client.dns.automapHostsSuffixes}
60 # Explicitly disable the SOCKS server if the client is disabled. In
61 # particular, this makes non-anonymous hidden services possible.
62 + optionalString (! cfg.client.enable) ''
66 + optionalString cfg.relay.enable ''
67 ORPort ${toString cfg.relay.port}
68 ${opt "Address" cfg.relay.address}
69 ${opt "Nickname" cfg.relay.nickname}
70 ${opt "ContactInfo" cfg.relay.contactInfo}
72 ${optint "RelayBandwidthRate" cfg.relay.bandwidthRate}
73 ${optint "RelayBandwidthBurst" cfg.relay.bandwidthBurst}
74 ${opt "AccountingMax" cfg.relay.accountingMax}
75 ${opt "AccountingStart" cfg.relay.accountingStart}
77 ${if (cfg.relay.role == "exit") then
78 opt "ExitPolicy" cfg.relay.exitPolicy
80 "ExitPolicy reject *:*"}
82 ${optionalString (elem cfg.relay.role ["bridge" "private-bridge"]) ''
84 ServerTransportPlugin ${concatStringsSep "," cfg.relay.bridgeTransports} exec ${pkgs.obfs4}/bin/obfs4proxy managed
86 ${optionalString (cfg.relay.role == "private-bridge") ''
88 PublishServerDescriptor 0
93 + concatStrings (flip mapAttrsToList cfg.hiddenServices (n: v: ''
94 HiddenServiceDir ${torDirectory}/onion/${v.name}
95 ${optionalString (v.version != null) "HiddenServiceVersion ${toString v.version}"}
96 ${flip concatMapStrings v.map (p: ''
97 HiddenServicePort ${toString p.port} ${p.destination}
99 ${optionalString (v.authorizeClient != null) ''
100 HiddenServiceAuthorizeClient ${v.authorizeClient.authType} ${concatStringsSep "," v.authorizeClient.clientNames}
105 torRcFile = pkgs.writeText "torrc" torRc;
110 (mkRenamedOptionModule [ "services" "tor" "relay" "portSpec" ] [ "services" "tor" "relay" "port" ])
111 (mkRemovedOptionModule [ "services" "tor" "relay" "isBridge" ] "Use services.tor.relay.role instead.")
112 (mkRemovedOptionModule [ "services" "tor" "relay" "isExit" ] "Use services.tor.relay.role instead.")
121 Enable the Tor daemon. By default, the daemon is run without
122 relay, exit, bridge or client connectivity.
127 type = types.package;
129 defaultText = "pkgs.tor";
130 example = literalExample "pkgs.tor";
136 enableGeoIP = mkOption {
140 Whenever to configure Tor daemon to use GeoIP databases.
142 Disabling this will disable by-country statistics for
143 bridges and relays and some client and third-party software
148 extraConfig = mkOption {
152 Extra configuration. Contents will be added verbatim to the
153 configuration file at the end.
157 controlPort = mkOption {
158 type = types.nullOr (types.either types.int types.str);
162 If set, Tor will accept connections on the specified port
163 and allow them to control the tor process.
172 Whether to enable Tor control socket. Control socket is created
173 in <literal>${torRunDirectory}/control</literal>
183 Whether to enable Tor daemon to route application
184 connections. You might want to disable this if you plan
185 running a dedicated Tor relay.
189 socksListenAddress = mkOption {
191 default = "127.0.0.1:9050";
192 example = "192.168.0.1:9100";
194 Bind to this address to listen for connections from
195 Socks-speaking applications. Provides strong circuit
196 isolation, separate circuit per IP address.
200 socksListenAddressFaster = mkOption {
202 default = "127.0.0.1:9063";
203 example = "192.168.0.1:9101";
205 Bind to this address to listen for connections from
206 Socks-speaking applications. Same as
207 <option>socksListenAddress</option> but uses weaker
208 circuit isolation to provide performance suitable for a
213 socksPolicy = mkOption {
214 type = types.nullOr types.str;
216 example = "accept 192.168.0.0/16, reject *";
218 Entry policies to allow/deny SOCKS requests based on IP
219 address. First entry that matches wins. If no SocksPolicy
220 is set, we accept all (and only) requests from
221 <option>socksListenAddress</option>.
225 socksIsolationOptions = mkOption (isolationOptions // {
226 default = ["IsolateDestAddr"];
233 description = "Whether to enable tor transparent proxy";
236 listenAddress = mkOption {
238 default = "127.0.0.1:9040";
239 example = "192.168.0.1:9040";
241 Bind transparent proxy to this address.
245 isolationOptions = mkOption isolationOptions;
252 description = "Whether to enable tor dns resolver";
255 listenAddress = mkOption {
257 default = "127.0.0.1:9053";
258 example = "192.168.0.1:9053";
260 Bind tor dns to this address.
264 isolationOptions = mkOption isolationOptions;
266 automapHostsSuffixes = mkOption {
267 type = types.listOf types.str;
268 default = [".onion" ".exit"];
269 example = [".onion"];
270 description = "List of suffixes to use with automapHostsOnResolve";
274 privoxy.enable = mkOption {
278 Whether to enable and configure the system Privoxy to use Tor's
279 faster port, suitable for HTTP.
281 To have anonymity, protocols need to be scrubbed of identifying
282 information, and this can be accomplished for HTTP by Privoxy.
284 Privoxy can also be useful for KDE torification. A good setup would be:
285 setting SOCKS proxy to the default Tor port, providing maximum
286 circuit isolation where possible; and setting HTTP proxy to Privoxy
287 to route HTTP traffic over faster, but less isolated port.
297 Whether to enable relaying TOR traffic for others.
299 See <link xlink:href="https://www.torproject.org/docs/tor-doc-relay" />
302 Setting this to true requires setting
303 <option>services.tor.relay.role</option>
305 <option>services.tor.relay.port</option>
311 type = types.enum [ "exit" "relay" "bridge" "private-bridge" ];
313 Your role in Tor network. There're several options:
317 <term><literal>exit</literal></term>
320 An exit relay. This allows Tor users to access regular
321 Internet services through your public IP.
325 Running an exit relay may expose you to abuse
327 <link xlink:href="https://www.torproject.org/faq.html.en#ExitPolicies" />
332 You can specify which services Tor users may access via
333 your exit relay using <option>exitPolicy</option> option.
339 <term><literal>relay</literal></term>
342 Regular relay. This allows Tor users to relay onion
343 traffic to other Tor nodes, but not to public
348 Note that some misconfigured and/or disrespectful
349 towards privacy sites will block you even if your
350 relay is not an exit relay. That is, just being listed
351 in a public relay directory can have unwanted
354 Which means you might not want to use
355 this role if you browse public Internet from the same
356 network as your relay, unless you want to write
357 e-mails to those sites (you should!).
362 <link xlink:href="https://www.torproject.org/docs/tor-doc-relay.html.en" />
369 <term><literal>bridge</literal></term>
372 Regular bridge. Works like a regular relay, but
373 doesn't list you in the public relay directory and
374 hides your Tor node behind obfs4proxy.
378 Using this option will make Tor advertise your bridge
379 to users through various mechanisms like
380 <link xlink:href="https://bridges.torproject.org/" />, though.
385 WARNING: THE FOLLOWING PARAGRAPH IS NOT LEGAL ADVICE.
386 Consult with your lawer when in doubt.
390 This role should be safe to use in most situations
391 (unless the act of forwarding traffic for others is
392 a punishable offence under your local laws, which
393 would be pretty insane as it would make ISP
399 See <link xlink:href="https://www.torproject.org/docs/bridges.html.en" />
406 <term><literal>private-bridge</literal></term>
409 Private bridge. Works like regular bridge, but does
410 not advertise your node in any way.
414 Using this role means that you won't contribute to Tor
415 network in any way unless you advertise your node
416 yourself in some way.
420 Use this if you want to run a private bridge, for
421 example because you'll give out your bridge address
422 manually to your friends.
426 Switching to this role after measurable time in
427 "bridge" role is pretty useless as some Tor users
428 would have learned about your node already. In the
429 latter case you can still change
430 <option>port</option> option.
434 See <link xlink:href="https://www.torproject.org/docs/bridges.html.en" />
443 bridgeTransports = mkOption {
444 type = types.listOf types.str;
446 example = ["obfs2" "obfs3" "obfs4" "scramblesuit"];
447 description = "List of pluggable transports";
450 nickname = mkOption {
452 default = "anonymous";
454 A unique handle for your TOR relay.
458 contactInfo = mkOption {
459 type = types.nullOr types.str;
461 example = "admin@relay.com";
463 Contact information for the relay owner (e.g. a mail
464 address and GPG key ID).
468 accountingMax = mkOption {
469 type = types.nullOr types.str;
471 example = "450 GBytes";
473 Specify maximum bandwidth allowed during an accounting period. This
474 allows you to limit overall tor bandwidth over some time period.
475 See the <literal>AccountingMax</literal> option by looking at the
476 tor manual <citerefentry><refentrytitle>tor</refentrytitle>
477 <manvolnum>1</manvolnum></citerefentry> for more.
479 Note this limit applies individually to upload and
480 download; if you specify <literal>"500 GBytes"</literal>
481 here, then you may transfer up to 1 TBytes of overall
482 bandwidth (500 GB upload, 500 GB download).
486 accountingStart = mkOption {
487 type = types.nullOr types.str;
489 example = "month 1 1:00";
491 Specify length of an accounting period. This allows you to limit
492 overall tor bandwidth over some time period. See the
493 <literal>AccountingStart</literal> option by looking at the tor
494 manual <citerefentry><refentrytitle>tor</refentrytitle>
495 <manvolnum>1</manvolnum></citerefentry> for more.
499 bandwidthRate = mkOption {
500 type = types.nullOr types.int;
504 Specify this to limit the bandwidth usage of relayed (server)
505 traffic. Your own traffic is still unthrottled. Units: bytes/second.
509 bandwidthBurst = mkOption {
510 type = types.nullOr types.int;
511 default = cfg.relay.bandwidthRate;
514 Specify this to allow bursts of the bandwidth usage of relayed (server)
515 traffic. The average usage will still be as specified in relayBandwidthRate.
516 Your own traffic is still unthrottled. Units: bytes/second.
521 type = types.nullOr types.str;
523 example = "noname.example.com";
525 The IP address or full DNS name for advertised address of your relay.
526 Leave unset and Tor will guess.
531 type = types.either types.int types.str;
534 What port to advertise for Tor connections. This corresponds to the
535 <literal>ORPort</literal> section in the Tor manual; see
536 <citerefentry><refentrytitle>tor</refentrytitle>
537 <manvolnum>1</manvolnum></citerefentry> for more details.
539 At a minimum, you should just specify the port for the
540 relay to listen on; a common one like 143, 22, 80, or 443
541 to help Tor users who may have very restrictive port-based
546 exitPolicy = mkOption {
547 type = types.nullOr types.str;
549 example = "accept *:6660-6667,reject *:*";
551 A comma-separated list of exit policies. They're
552 considered first to last, and the first match wins. If you
553 want to _replace_ the default exit policy, end this with
554 either a reject *:* or an accept *:*. Otherwise, you're
555 _augmenting_ (prepending to) the default exit policy.
556 Leave commented to just use the default, which is
557 available in the man page or at
558 <link xlink:href="https://www.torproject.org/documentation.html" />.
561 <link xlink:href="https://www.torproject.org/faq-abuse.html#TypicalAbuses" />
562 for issues you might encounter if you use the default
565 If certain IPs and ports are blocked externally, e.g. by
566 your firewall, you should update your exit policy to
567 reflect this -- otherwise Tor users will be told that
568 those destinations are down.
573 hiddenServices = mkOption {
575 A set of static hidden services that terminate their Tor
576 circuits at this node.
578 Every element in this set declares a virtual onion host.
580 You can specify your onion address by putting corresponding
581 private key to an appropriate place in ${torDirectory}.
583 For services without private keys in ${torDirectory} Tor
584 daemon will generate random key pairs (which implies random
585 onion addresses) on restart. The latter could take a while,
589 Hidden services can be useful even if you don't intend to
590 actually <emphasis>hide</emphasis> them, since they can
591 also be seen as a kind of NAT traversal mechanism.
593 E.g. the example will make your sshd, whatever runs on
594 "8080" and your mail server available from anywhere where
595 the Tor network is available (which, with the help from
596 bridges, is pretty much everywhere), even if both client
597 and server machines are behind NAT you have no control
602 example = literalExample ''
603 { "my-hidden-service-example".map = [
604 { port = 22; } # map ssh port to this machine's ssh
605 { port = 80; toPort = 8080; } # map http port to whatever runs on 8080
606 { port = "sip"; toHost = "mail.example.com"; toPort = "imap"; } # because we can
610 type = types.loaOf (types.submodule ({name, ...}: {
616 Name of this tor hidden service.
618 This is purely descriptive.
620 After restarting Tor daemon you should be able to
621 find your .onion address in
622 <literal>${torDirectory}/onion/$name/hostname</literal>.
628 description = "Port mapping for this hidden service.";
629 type = types.listOf (types.submodule ({config, ...}: {
633 type = types.either types.int types.str;
636 Hidden service port to "bind to".
640 destination = mkOption {
643 description = "Forward these connections where?";
648 default = "127.0.0.1";
649 description = "Mapping destination host.";
653 type = types.either types.int types.str;
655 description = "Mapping destination port.";
661 toPort = mkDefault config.port;
662 destination = mkDefault "${config.toHost}:${toString config.toPort}";
667 authorizeClient = mkOption {
669 description = "If configured, the hidden service is accessible for authorized clients only.";
670 type = types.nullOr (types.submodule ({...}: {
674 authType = mkOption {
675 type = types.enum [ "basic" "stealth" ];
677 Either <literal>"basic"</literal> for a general-purpose authorization protocol
678 or <literal>"stealth"</literal> for a less scalable protocol
679 that also hides service activity from unauthorized clients.
683 clientNames = mkOption {
684 type = types.nonEmptyListOf (types.strMatching "[A-Za-z0-9+-_]+");
686 Only clients that are listed here are authorized to access the hidden service.
687 Generated authorization data can be found in <filename>${torDirectory}/onion/$name/hostname</filename>.
688 Clients need to put this authorization data in their configuration file using <literal>HidServAuth</literal>.
697 description = "Rendezvous service descriptor version to publish for the hidden service. Currently, versions 2 and 3 are supported. (Default: 2)";
698 type = types.nullOr (types.enum [ 2 3 ]);
703 name = mkDefault name;
710 config = mkIf cfg.enable {
711 # Not sure if `cfg.relay.role == "private-bridge"` helps as tor
712 # sends a lot of stats
713 warnings = optional (cfg.relay.enable && cfg.hiddenServices != {})
715 Running Tor hidden services on a public relay makes the
716 presence of hidden services visible through simple statistical
717 analysis of publicly available data.
719 You can safely ignore this warning if you don't intend to
720 actually hide your hidden services. In either case, you can
721 always create a container/VM with a separate Tor daemon instance.
724 users.groups.tor.gid = config.ids.gids.tor;
726 { description = "Tor Daemon User";
730 uid = config.ids.uids.tor;
733 # We have to do this instead of using RuntimeDirectory option in
734 # the service below because systemd has no way to set owners of
735 # RuntimeDirectory and putting this into the service below
736 # requires that service to relax it's sandbox since this needs
738 systemd.services.tor-init =
739 { description = "Tor Daemon Init";
740 wantedBy = [ "tor.service" ];
742 install -m 0700 -o tor -g tor -d ${torDirectory} ${torDirectory}/onion
743 install -m 0750 -o tor -g tor -d ${torRunDirectory}
747 RemainAfterExit = true;
751 systemd.services.tor =
752 { description = "Tor Daemon";
755 wantedBy = [ "multi-user.target" ];
756 after = [ "tor-init.service" "network.target" ];
757 restartTriggers = [ torRcFile ];
761 # Translated from the upstream contrib/dist/tor.service.in
762 ExecStartPre = "${cfg.package}/bin/tor -f ${torRcFile} --verify-config";
763 ExecStart = "${cfg.package}/bin/tor -f ${torRcFile}";
764 ExecReload = "${pkgs.coreutils}/bin/kill -HUP $MAINPID";
765 KillSignal = "SIGINT";
767 Restart = "on-failure";
771 # this seems to unshare /run despite what systemd.exec(5) says
772 PrivateTmp = mkIf (!cfg.controlSocket.enable) "yes";
773 PrivateDevices = "yes";
775 ProtectSystem = "strict";
776 InaccessiblePaths = "/home";
778 ReadWritePaths = [ torDirectory torRunDirectory ];
779 NoNewPrivileges = "yes";
781 # tor.service.in has this in, but this line it fails to spawn a namespace when using hidden services
782 #CapabilityBoundingSet = "CAP_SETUID CAP_SETGID CAP_NET_BIND_SERVICE";
786 environment.systemPackages = [ cfg.package ];
788 services.privoxy = mkIf (cfg.client.enable && cfg.client.privoxy.enable) {
791 forward-socks4a / ${cfg.client.socksListenAddressFaster} .
793 enable-remote-toggle 0
794 enable-edit-actions 0
795 enable-remote-http-toggle 0