summaryrefslogtreecommitdiffstats
path: root/nixos
diff options
context:
space:
mode:
authorJörg Thalheim <joerg@thalheim.io>2020-12-31 07:31:38 +0100
committerJörg Thalheim <joerg@thalheim.io>2020-12-31 07:31:38 +0100
commitf19b7b03a03b7f1d5beb44471eb9298de4b9e186 (patch)
tree2bb5fabe03cff0c2058f69921315ab3ff724f9d0 /nixos
parent572a864d024b0c91ac39133f35364362b2376c07 (diff)
parent7a580a12196e63eb665de6eb4db8bb3b6da142f5 (diff)
Merge branch 'master' into staging-next
Diffstat (limited to 'nixos')
-rw-r--r--nixos/doc/manual/man-nixos-rebuild.xml37
-rw-r--r--nixos/modules/programs/command-not-found/command-not-found.nix11
-rw-r--r--nixos/modules/programs/command-not-found/command-not-found.pl51
-rw-r--r--nixos/modules/programs/command-not-found/default.nix18
-rw-r--r--nixos/modules/programs/command-not-found/rust/Cargo.lock131
-rw-r--r--nixos/modules/programs/command-not-found/rust/Cargo.toml10
-rw-r--r--nixos/modules/programs/command-not-found/rust/src/main.rs52
-rw-r--r--nixos/modules/services/databases/redis.nix6
-rw-r--r--nixos/modules/services/misc/home-assistant.nix28
-rw-r--r--nixos/modules/services/misc/nix-daemon.nix7
-rw-r--r--nixos/modules/services/networking/privoxy.nix7
-rw-r--r--nixos/modules/services/security/tor.nix1390
-rw-r--r--nixos/modules/services/system/nscd.nix41
-rw-r--r--nixos/modules/services/web-servers/nginx/default.nix21
-rw-r--r--nixos/modules/system/activation/switch-to-configuration.pl11
-rw-r--r--nixos/modules/system/boot/stage-1.nix2
-rw-r--r--nixos/modules/tasks/filesystems.nix9
-rw-r--r--nixos/modules/virtualisation/amazon-image.nix2
-rw-r--r--nixos/tests/tor.nix2
19 files changed, 1182 insertions, 654 deletions
diff --git a/nixos/doc/manual/man-nixos-rebuild.xml b/nixos/doc/manual/man-nixos-rebuild.xml
index d0ff81c1dbb3..4510fdd44225 100644
--- a/nixos/doc/manual/man-nixos-rebuild.xml
+++ b/nixos/doc/manual/man-nixos-rebuild.xml
@@ -113,6 +113,18 @@
<replaceable>path</replaceable>
</arg>
<arg>
+ <option>-L</option>
+ </arg>
+ <arg>
+ <option>--refresh</option>
+ </arg>
+ <arg>
+ <option>--no-net</option>
+ </arg>
+ <arg>
+ <option>--impure</option>
+ </arg>
+ <arg>
<group choice='req'>
<arg choice='plain'><option>--verbose</option></arg>
<arg choice='plain'><option>-v</option></arg>
@@ -131,6 +143,18 @@
<replaceable>number</replaceable>
</arg>
<arg>
+ <option>--fallback</option>
+ </arg>
+ <arg>
+ <option>--repair</option>
+ </arg>
+ <arg>
+ <group choice='req'>
+ <arg choice='plain'><option>--no-build-output</option></arg>
+ <arg choice='plain'><option>-Q</option></arg>
+ </group>
+ </arg>
+ <arg>
<group choice='req'>
<arg choice='plain'><option>--keep-failed</option></arg>
<arg choice='plain'><option>-K</option></arg>
@@ -567,10 +591,19 @@
<para>
In addition, <command>nixos-rebuild</command> accepts various Nix-related
- flags, including <option>--max-jobs</option> / <option>-j</option>,
+ flags: <option>-I</option>, <option>--max-jobs</option> / <option>-j</option>,
<option>--show-trace</option>, <option>--keep-failed</option>,
- <option>--keep-going</option>, <option>--impure</option>, and <option>--verbose</option> /
+ <option>--keep-going</option>, <option>--impure</option>, and <option>--verbose</option> /
+ <option>--builders</option>, <option>--show-trace</option>,
+ <option>--fallback</option>, <option>--repair</option>,
+ <option>--no-build-output</option> / <option>-Q</option>,
+ <option>--keep-failed</option> / <option>-K</option>,
+ <option>--keep-going</option> / <option>-k</option> and <option>--verbose</option> /
<option>-v</option>. See the Nix manual for details.
+
+ The following Nix flags that are support by the upcoming nix 2.4 version:
+ <option>-L</option>, <option>--refresh</option>, <option>--no-net</option>,
+ <option>--no-net</option>, <option>--impure</option>. See <command>nix --help</command> or <command>nix build --help</command> for details.
</para>
</refsection>
diff --git a/nixos/modules/programs/command-not-found/command-not-found.nix b/nixos/modules/programs/command-not-found/command-not-found.nix
index 656c255fcb18..da09488d82c7 100644
--- a/nixos/modules/programs/command-not-found/command-not-found.nix
+++ b/nixos/modules/programs/command-not-found/command-not-found.nix
@@ -9,17 +9,9 @@ with lib;
let
cfg = config.programs.command-not-found;
- commandNotFound = pkgs.substituteAll {
- name = "command-not-found";
- dir = "bin";
- src = ./command-not-found.pl;
- isExecutable = true;
- inherit (pkgs) perl;
+ commandNotFound = pkgs.callPackage ./. {
inherit (cfg) dbPath;
- perlFlags = concatStrings (map (path: "-I ${path}/${pkgs.perl.libPrefix} ")
- [ pkgs.perlPackages.DBI pkgs.perlPackages.DBDSQLite pkgs.perlPackages.StringShellQuote ]);
};
-
in
{
@@ -91,5 +83,4 @@ in
environment.systemPackages = [ commandNotFound ];
};
-
}
diff --git a/nixos/modules/programs/command-not-found/command-not-found.pl b/nixos/modules/programs/command-not-found/command-not-found.pl
deleted file mode 100644
index ab7aa204653c..000000000000
--- a/nixos/modules/programs/command-not-found/command-not-found.pl
+++ /dev/null
@@ -1,51 +0,0 @@
-#! @perl@/bin/perl -w @perlFlags@
-
-use strict;
-use DBI;
-use DBD::SQLite;
-use String::ShellQuote;
-use Config;
-
-my $program = $ARGV[0];
-
-my $dbPath = "@dbPath@";
-
-my $dbh = DBI->connect("dbi:SQLite:dbname=$dbPath", "", "")
- or die "cannot open database `$dbPath'";
-$dbh->{RaiseError} = 0;
-$dbh->{PrintError} = 0;
-
-my $system = $ENV{"NIX_SYSTEM"} // $Config{myarchname};
-
-my $res = $dbh->selectall_arrayref(
- "select package from Programs where system = ? and name = ?",
- { Slice => {} }, $system, $program);
-
-if (!defined $res || scalar @$res == 0) {
- print STDERR "$program: command not found\n";
-} elsif (scalar @$res == 1) {
- my $package = @$res[0]->{package};
- if ($ENV{"NIX_AUTO_INSTALL"} // "") {
- print STDERR <<EOF;
-The program ‘$program’ is currently not installed. It is provided by
-the package ‘$package’, which I will now install for you.
-EOF
- ;
- exit 126 if system("nix-env", "-iA", "nixos.$package") == 0;
- } elsif ($ENV{"NIX_AUTO_RUN"} // "") {
- exec("nix-shell", "-p", $package, "--run", shell_quote("exec", @ARGV));
- } else {
- print STDERR <<EOF;
-The program ‘$program’ is currently not installed. You can install it by typing:
- nix-env -iA nixos.$package
-EOF
- }
-} else {
- print STDERR <<EOF;
-The program ‘$program’ is currently not installed. It is provided by
-several packages. You can install it by typing one of the following:
-EOF
- print STDERR " nix-env -iA nixos.$_->{package}\n" foreach @$res;
-}
-
-exit 127;
diff --git a/nixos/modules/programs/command-not-found/default.nix b/nixos/modules/programs/command-not-found/default.nix
new file mode 100644
index 000000000000..bbe949fa86a3
--- /dev/null
+++ b/nixos/modules/programs/command-not-found/default.nix
@@ -0,0 +1,18 @@
+{ stdenv, rustPlatform, pkgconfig, sqlite
+, dbPath ? "/nix/var/nix/profiles/per-user/root/channels/nixos/programs.sqlite" }:
+
+rustPlatform.buildRustPackage {
+ name = "command-not-found";
+ src = ./rust;
+
+ DB_PATH = dbPath;
+ NIX_SYSTEM = stdenv.system;
+
+ postInstall = ''
+ strip $out/bin/command-not-found
+ '';
+
+ buildInputs = [ sqlite ];
+ nativeBuildInputs = [ pkgconfig ];
+ cargoSha256 = "13q61bb4b1q40g424pbssyp3ln79q1a33vmyz9s9wlqnac34cibd";
+}
diff --git a/nixos/modules/programs/command-not-found/rust/Cargo.lock b/nixos/modules/programs/command-not-found/rust/Cargo.lock
new file mode 100644
index 000000000000..ce3a9358c5c2
--- /dev/null
+++ b/nixos/modules/programs/command-not-found/rust/Cargo.lock
@@ -0,0 +1,131 @@
+# This file is automatically @generated by Cargo.
+# It is not intended for manual editing.
+[[package]]
+name = "bitflags"
+version = "1.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
+name = "command-not-found"
+version = "0.1.0"
+dependencies = [
+ "rusqlite 0.23.1 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "fallible-iterator"
+version = "0.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
+name = "fallible-streaming-iterator"
+version = "0.1.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
+name = "libc"
+version = "0.2.70"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
+name = "libsqlite3-sys"
+version = "0.18.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "pkg-config 0.3.17 (registry+https://github.com/rust-lang/crates.io-index)",
+ "vcpkg 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "linked-hash-map"
+version = "0.5.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
+name = "lru-cache"
+version = "0.1.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "linked-hash-map 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "memchr"
+version = "2.3.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
+name = "pkg-config"
+version = "0.3.17"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
+name = "rusqlite"
+version = "0.23.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "fallible-iterator 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "fallible-streaming-iterator 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libsqlite3-sys 0.18.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "lru-cache 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "memchr 2.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
+ "smallvec 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "time 0.1.43 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "smallvec"
+version = "1.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
+name = "time"
+version = "0.1.43"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "libc 0.2.70 (registry+https://github.com/rust-lang/crates.io-index)",
+ "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "vcpkg"
+version = "0.2.8"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
+name = "winapi"
+version = "0.3.8"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "winapi-i686-pc-windows-gnu"
+version = "0.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
+name = "winapi-x86_64-pc-windows-gnu"
+version = "0.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[metadata]
+"checksum bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693"
+"checksum fallible-iterator 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4443176a9f2c162692bd3d352d745ef9413eec5782a80d8fd6f8a1ac692a07f7"
+"checksum fallible-streaming-iterator 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "7360491ce676a36bf9bb3c56c1aa791658183a54d2744120f27285738d90465a"
+"checksum libc 0.2.70 (registry+https://github.com/rust-lang/crates.io-index)" = "3baa92041a6fec78c687fa0cc2b3fae8884f743d672cf551bed1d6dac6988d0f"
+"checksum libsqlite3-sys 0.18.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1e704a02bcaecd4a08b93a23f6be59d0bd79cd161e0963e9499165a0a35df7bd"
+"checksum linked-hash-map 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)" = "8dd5a6d5999d9907cda8ed67bbd137d3af8085216c2ac62de5be860bd41f304a"
+"checksum lru-cache 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "31e24f1ad8321ca0e8a1e0ac13f23cb668e6f5466c2c57319f6a5cf1cc8e3b1c"
+"checksum memchr 2.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "3728d817d99e5ac407411fa471ff9800a778d88a24685968b36824eaf4bee400"
+"checksum pkg-config 0.3.17 (registry+https://github.com/rust-lang/crates.io-index)" = "05da548ad6865900e60eaba7f589cc0783590a92e940c26953ff81ddbab2d677"
+"checksum rusqlite 0.23.1 (registry+https://github.com/rust-lang/crates.io-index)" = "45d0fd62e1df63d254714e6cb40d0a0e82e7a1623e7a27f679d851af092ae58b"
+"checksum smallvec 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c7cb5678e1615754284ec264d9bb5b4c27d2018577fd90ac0ceb578591ed5ee4"
+"checksum time 0.1.43 (registry+https://github.com/rust-lang/crates.io-index)" = "ca8a50ef2360fbd1eeb0ecd46795a87a19024eb4b53c5dc916ca1fd95fe62438"
+"checksum vcpkg 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "3fc439f2794e98976c88a2a2dafce96b930fe8010b0a256b3c2199a773933168"
+"checksum winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)" = "8093091eeb260906a183e6ae1abdba2ef5ef2257a21801128899c3fc699229c6"
+"checksum winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
+"checksum winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
diff --git a/nixos/modules/programs/command-not-found/rust/Cargo.toml b/nixos/modules/programs/command-not-found/rust/Cargo.toml
new file mode 100644
index 000000000000..f965c7df76a5
--- /dev/null
+++ b/nixos/modules/programs/command-not-found/rust/Cargo.toml
@@ -0,0 +1,10 @@
+[package]
+name = "command-not-found"
+version = "0.1.0"
+edition = "2018"
+
+[dependencies]
+rusqlite = "0.*.*"
+
+[profile.release]
+lto = true
diff --git a/nixos/modules/programs/command-not-found/rust/src/main.rs b/nixos/modules/programs/command-not-found/rust/src/main.rs
new file mode 100644
index 000000000000..b0af2871cc29
--- /dev/null
+++ b/nixos/modules/programs/command-not-found/rust/src/main.rs
@@ -0,0 +1,52 @@
+use rusqlite::{params, Connection, Result};
+use std::env;
+use std::process::exit;
+
+const NIX_SYSTEM: &str = env!("NIX_SYSTEM");
+const DB_PATH: &str = env!("DB_PATH");
+
+fn query_packages(system: &str, program: &str) -> Result<Vec<String>> {
+ Ok(Connection::open(DB_PATH)?
+ .prepare("select package from Programs where system = ? and name = ?;")?
+ .query_map(params![system, program], |row| row.get("package"))?
+ .collect::<Result<Vec<String>>>()?)
+}
+
+fn run_app() -> i32 {
+ let args: Vec<_> = env::args().collect();
+ if args.len() < 2 {
+ eprintln!("USAGE: {} PROGRAMNAME", args[0]);
+ return 1;
+ }
+ let program = &args[1];
+ let system = env::var("NIX_SYSTEM").unwrap_or_else(|_| NIX_SYSTEM.to_string());
+ let packages = match query_packages(&system, program) {
+ Ok(packages) => packages,
+ Err(err) => {
+ eprintln!("Failed to query package database: {}", err);
+ return 1;
+ }
+ };
+ if packages.is_empty() {
+ eprintln!("{}: command not found", program);
+ } else {
+ let advice = if packages.len() > 1 {
+ "It is provided by several packages. You can install it by typing on of the of following commands:"
+ } else {
+ "You can install it by typing:"
+ };
+ eprintln!(
+ "The program '{}' is currently not installed. {}",
+ program, advice
+ );
+ for pkg in packages {
+ eprintln!(" nix-env -iA nixos.{}", pkg);
+ }
+ }
+
+ 127
+}
+
+fn main() {
+ exit(run_app());
+}
diff --git a/nixos/modules/services/databases/redis.nix b/nixos/modules/services/databases/redis.nix
index 6b8853ae390b..9988f382a1b1 100644
--- a/nixos/modules/services/databases/redis.nix
+++ b/nixos/modules/services/databases/redis.nix
@@ -12,7 +12,7 @@ let
${condOption "bind" cfg.bind}
${condOption "unixsocket" cfg.unixSocket}
daemonize no
- supervised systemd
+ #supervised systemd
loglevel ${cfg.logLevel}
logfile ${cfg.logfile}
syslog-enabled ${redisBool cfg.syslog}
@@ -242,7 +242,9 @@ in
ExecStart = "${cfg.package}/bin/redis-server /run/redis/redis.conf";
RuntimeDirectory = "redis";
StateDirectory = "redis";
- Type = "notify";
+ TimeoutStartSec = "infinity";
+ TimeoutStopSec = "infinity";
+ Type = "simple";
User = "redis";
Group = "redis";
};
diff --git a/nixos/modules/services/misc/home-assistant.nix b/nixos/modules/services/misc/home-assistant.nix
index 1f2e13f37325..16fff215e616 100644
--- a/nixos/modules/services/misc/home-assistant.nix
+++ b/nixos/modules/services/misc/home-assistant.nix
@@ -62,6 +62,17 @@ let
lovelace.mode = "yaml";
};
+ #pythonScripts = pkgs.runCommand "python_scripts" {
+ # nativeBuildInputs = [ pkgs.python3 ];
+ # scripts = cfg.pythonScripts;
+ #} ''
+ # mkdir $out
+ # for s in $scripts; do
+ # echo "checking syntax of $s"
+ # python -m py_compile "$s"
+ # ln -s "$s" "$out/$(basename $s"
+ # done
+ #'';
in {
meta.maintainers = with maintainers; [ dotlambda ];
@@ -214,6 +225,17 @@ in {
'';
};
+ pythonScripts = mkOption {
+ #default = [];
+ #type = types.listOf types.path;
+ default = null;
+ type = types.nullOr types.path;
+ description = ''
+ List of python scripts to use in the <literal>python_scripts</literal> integration.
+ Also see in the <link xlink:href="https://www.home-assistant.io/integrations/python_script">Homeassistant documentation</link>
+ '';
+ };
+
openFirewall = mkOption {
default = false;
type = types.bool;
@@ -224,6 +246,12 @@ in {
config = mkIf cfg.enable {
networking.firewall.allowedTCPPorts = mkIf cfg.openFirewall [ cfg.port ];
+ systemd.tmpfiles.rules = mkIf (cfg.pythonScripts != null) [
+ "L+ ${cfg.configDir}/python_scripts - - - - ${cfg.pythonScripts}"
+ ];
+
+ services.home-assistant.config.python_script = mkIf (cfg.pythonScripts != null) {};
+
systemd.services.home-assistant = {
description = "Home Assistant";
after = [ "network.target" ];
diff --git a/nixos/modules/services/misc/nix-daemon.nix b/nixos/modules/services/misc/nix-daemon.nix
index 0eeff31d6c4d..b0763c8d0de4 100644
--- a/nixos/modules/services/misc/nix-daemon.nix
+++ b/nixos/modules/services/misc/nix-daemon.nix
@@ -11,6 +11,7 @@ let
nixVersion = getVersion nix;
isNix23 = versionAtLeast nixVersion "2.3pre";
+ isNix24 = versionAtLeast nixVersion "2.4pre";
makeNixBuildUser = nr: {
name = "nixbld${toString nr}";
@@ -40,7 +41,11 @@ let
max-jobs = ${toString (cfg.maxJobs)}
cores = ${toString (cfg.buildCores)}
sandbox = ${if (builtins.isBool cfg.useSandbox) then boolToString cfg.useSandbox else cfg.useSandbox}
- extra-sandbox-paths = ${toString cfg.sandboxPaths}
+
+ ${optionalString (!isNix24) ''
+ extra-sandbox-paths = ${toString cfg.sandboxPaths}
+ ''}
+
substituters = ${toString cfg.binaryCaches}
trusted-substituters = ${toString cfg.trustedBinaryCaches}
trusted-public-keys = ${toString cfg.binaryCachePublicKeys}
diff --git a/nixos/modules/services/networking/privoxy.nix b/nixos/modules/services/networking/privoxy.nix
index e3b34cb0c616..7caae3282032 100644
--- a/nixos/modules/services/networking/privoxy.nix
+++ b/nixos/modules/services/networking/privoxy.nix
@@ -16,7 +16,7 @@ let
${concatMapStrings (f: "actionsfile ${f}\n") cfg.actionsFiles}
${concatMapStrings (f: "filterfile ${f}\n") cfg.filterFiles}
'' + optionalString cfg.enableTor ''
- forward-socks4a / ${config.services.tor.client.socksListenAddressFaster} .
+ forward-socks5t / 127.0.0.1:9063 .
toggle 1
enable-remote-toggle 0
enable-edit-actions 0
@@ -123,6 +123,11 @@ in
serviceConfig.ProtectSystem = "full";
};
+ services.tor.settings.SOCKSPort = mkIf cfg.enableTor [
+ # Route HTTP traffic over a faster port (without IsolateDestAddr).
+ { addr = "127.0.0.1"; port = 9063; IsolateDestAddr = false; }
+ ];
+
};
meta.maintainers = with lib.maintainers; [ rnhmjoj ];
diff --git a/nixos/modules/services/security/tor.nix b/nixos/modules/services/security/tor.nix
index 1cceee065b1b..ececb633983c 100644
--- a/nixos/modules/services/security/tor.nix
+++ b/nixos/modules/services/security/tor.nix
@@ -1,297 +1,300 @@
{ config, lib, pkgs, ... }:
+with builtins;
with lib;
let
cfg = config.services.tor;
- torDirectory = "/var/lib/tor";
- torRunDirectory = "/run/tor";
-
- opt = name: value: optionalString (value != null) "${name} ${value}";
- optint = name: value: optionalString (value != null && value != 0) "${name} ${toString value}";
-
- isolationOptions = {
- type = types.listOf (types.enum [
- "IsolateClientAddr"
- "IsolateSOCKSAuth"
- "IsolateClientProtocol"
- "IsolateDestPort"
- "IsolateDestAddr"
+ stateDir = "/var/lib/tor";
+ runDir = "/run/tor";
+ descriptionGeneric = option: ''
+ See <link xlink:href="https://2019.www.torproject.org/docs/tor-manual.html.en#${option}">torrc manual</link>.
+ '';
+ bindsPrivilegedPort =
+ any (p0:
+ let p1 = if p0 ? "port" then p0.port else p0; in
+ if p1 == "auto" then false
+ else let p2 = if isInt p1 then p1 else toInt p1; in
+ p1 != null && 0 < p2 && p2 < 1024)
+ (flatten [
+ cfg.settings.ORPort
+ cfg.settings.DirPort
+ cfg.settings.DNSPort
+ cfg.settings.ExtORPort
+ cfg.settings.HTTPTunnelPort
+ cfg.settings.NATDPort
+ cfg.settings.SOCKSPort
+ cfg.settings.TransPort
]);
+ optionBool = optionName: mkOption {
+ type = with types; nullOr bool;
+ default = null;
+ description = descriptionGeneric optionName;
+ };
+ optionInt = optionName: mkOption {
+ type = with types; nullOr int;
+ default = null;
+ description = descriptionGeneric optionName;
+ };
+ optionString = optionName: mkOption {
+ type = with types; nullOr str;
+ default = null;
+ description = descriptionGeneric optionName;
+ };
+ optionStrings = optionName: mkOption {
+ type = with types; listOf str;
default = [];
- example = [
- "IsolateClientAddr"
- "IsolateSOCKSAuth"
- "IsolateClientProtocol"
- "IsolateDestPort"
- "IsolateDestAddr"
+ description = descriptionGeneric optionName;
+ };
+ optionAddress = mkOption {
+ type = with types; nullOr str;
+ default = null;
+ example = "0.0.0.0";
+ description = ''
+ IPv4 or IPv6 (if between brackets) address.
+ '';
+ };
+ optionUnix = mkOption {
+ type = with types; nullOr path;
+ default = null;
+ description = ''
+ Unix domain socket path to use.
+ '';
+ };
+ optionPort = mkOption {
+ type = with types; nullOr (oneOf [port (enum ["auto"])]);
+ default = null;
+ };
+ optionPorts = optionName: mkOption {
+ type = with types; listOf port;
+ default = [];
+ description = descriptionGeneric optionName;
+ };
+ optionIsolablePort = with types; oneOf [
+ port (enum ["auto"])
+ (submodule ({config, ...}: {
+ options = {
+ addr = optionAddress;
+ port = optionPort;
+ flags = optionFlags;
+ SessionGroup = mkOption { type = nullOr int; default = null; };
+ } // genAttrs isolateFlags (name: mkOption { type = types.bool; default = false; });
+ config = {
+ flags = filter (name: config.${name} == true) isolateFlags ++
+ optional (config.SessionGroup != null) "SessionGroup=${toString config.SessionGroup}";
+ };
+ }))
+ ];
+ optionIsolablePorts = optionName: mkOption {
+ default = [];
+ type = with types; either optionIsolablePort (listOf optionIsolablePort);
+ description = descriptionGeneric optionName;
+ };
+ isolateFlags = [
+ "IsolateClientAddr"
+ "IsolateClientProtocol"
+ "IsolateDestAddr"
+ "IsolateDestPort"
+ "IsolateSOCKSAuth"
+ "KeepAliveIsolateSOCKSAuth"
+ ];
+ optionSOCKSPort = doConfig: let
+ flags = [
+ "CacheDNS" "CacheIPv4DNS" "CacheIPv6DNS" "GroupWritable" "IPv6Traffic"
+ "NoDNSRequest" "NoIPv4Traffic" "NoOnionTraffic" "OnionTrafficOnly"
+ "PreferIPv6" "PreferIPv6Automap" "PreferSOCKSNoAuth" "UseDNSCache"
+ "UseIPv4Cache" "UseIPv6Cache" "WorldWritable"
+ ] ++ isolateFlags;
+ in with types; oneOf [
+ port (submodule ({config, ...}: {
+ options = {
+ unix = optionUnix;
+ addr = optionAddress;
+ port = optionPort;
+ flags = optionFlags;
+ SessionGroup = mkOption { type = nullOr int; default = null; };
+ } // genAttrs flags (name: mkOption { type = types.bool; default = false; });
+ config = mkIf doConfig { # Only add flags in SOCKSPort to avoid duplicates
+ flags = filter (name: config.${name} == true) flags ++
+ optional (config.SessionGroup != null) "SessionGroup=${toString config.SessionGroup}";
+ };
+ }))
];
- description = "Tor isolation options";
+ optionFlags = mkOption {
+ type = with types; listOf str;
+ default = [];
+ };
+ optionORPort = optionName: mkOption {
+ default = [];
+ example = 443;
+ type = with types; oneOf [port (enum ["auto"]) (listOf (oneOf [
+ port
+ (enum ["auto"])
+ (submodule ({config, ...}:
+ let flags = [ "IPv4Only" "IPv6Only" "NoAdvertise" "NoListen" ];
+ in {
+ options = {
+ addr = optionAddress;
+ port = optionPort;
+ flags = optionFlags;
+ } // genAttrs flags (name: mkOption { type = types.bool; default = false; });
+ config = {
+ flags = filter (name: config.${name} == true) flags;
+ };
+ }))
+ ]))];
+ description = descriptionGeneric optionName;
+ };
+ optionBandwith = optionName: mkOption {
+ type = with types; nullOr (either int str);
+ default = null;
+ description = descriptionGeneric optionName;
+ };
+ optionPath = optionName: mkOption {
+ type = with types; nullOr path;
+ default = null;
+ description = descriptionGeneric optionName;
};
-
- torRc = ''
- User tor
- DataDirectory ${torDirectory}
- ${optionalString cfg.enableGeoIP ''
- GeoIPFile ${cfg.package.geoip}/share/tor/geoip
- GeoIPv6File ${cfg.package.geoip}/share/tor/geoip6
- ''}
-
- ${optint "ControlPort" cfg.controlPort}
- ${optionalString cfg.controlSocket.enable "ControlPort unix:${torRunDirectory}/control GroupWritable RelaxDirModeCheck"}
- ''
- # Client connection config
- + optionalString cfg.client.enable ''
- SOCKSPort ${cfg.client.socksListenAddress} ${toString cfg.client.socksIsolationOptions}
- SOCKSPort ${cfg.client.socksListenAddressFaster}
- ${opt "SocksPolicy" cfg.client.socksPolicy}
-
- ${optionalString cfg.client.transparentProxy.enable ''
- TransPort ${cfg.client.transparentProxy.listenAddress} ${toString cfg.client.transparentProxy.isolationOptions}
- ''}
-
- ${optionalString cfg.client.dns.enable ''
- DNSPort ${cfg.client.dns.listenAddress} ${toString cfg.client.dns.isolationOptions}
- AutomapHostsOnResolve 1
- AutomapHostsSuffixes ${concatStringsSep "," cfg.client.dns.automapHostsSuffixes}
- ''}
- ''
- # Explicitly disable the SOCKS server if the client is disabled. In
- # particular, this makes non-anonymous hidden services possible.
- + optionalString (! cfg.client.enable) ''
- SOCKSPort 0
- ''
- # Relay config
- + optionalString cfg.relay.enable ''
- ORPort ${toString cfg.relay.port}
- ${opt "Address" cfg.relay.address}
- ${opt "Nickname" cfg.relay.nickname}
- ${opt "ContactInfo" cfg.relay.contactInfo}
-
- ${optint "RelayBandwidthRate" cfg.relay.bandwidthRate}
- ${optint "RelayBandwidthBurst" cfg.relay.bandwidthBurst}
- ${opt "AccountingMax" cfg.relay.accountingMax}
- ${opt "AccountingStart" cfg.relay.accountingStart}
-
- ${if (cfg.relay.role == "exit") then
- opt "ExitPolicy" cfg.relay.exitPolicy
- else
- "ExitPolicy reject *:*"}
-
- ${optionalString (elem cfg.relay.role ["bridge" "private-bridge"]) ''
- BridgeRelay 1
- ServerTransportPlugin ${concatStringsSep "," cfg.relay.bridgeTransports} exec ${pkgs.obfs4}/bin/obfs4proxy managed
- ExtORPort auto
- ${optionalString (cfg.relay.role == "private-bridge") ''
- ExtraInfoStatistics 0
- PublishServerDescriptor 0
- ''}
- ''}
- ''
- # Hidden services
- + concatStrings (flip mapAttrsToList cfg.hiddenServices (n: v: ''
- HiddenServiceDir ${torDirectory}/onion/${v.name}
- ${optionalString (v.version != null) "HiddenServiceVersion ${toString v.version}"}
- ${flip concatMapStrings v.map (p: ''
- HiddenServicePort ${toString p.port} ${p.destination}
- '')}
- ${optionalString (v.authorizeClient != null) ''
- HiddenServiceAuthorizeClient ${v.authorizeClient.authType} ${concatStringsSep "," v.authorizeClient.clientNames}
- ''}
- ''))
- + cfg.extraConfig;
-
- torRcFile = pkgs.writeText "torrc" torRc;
-
+ mkValueString = k: v:
+ if v == null then ""
+ else if isBool v then
+ (if v then "1" else "0")
+ else if v ? "unix" && v.unix != null then
+ "unix:"+v.unix +
+ optionalString (v ? "flags") (" " + concatStringsSep " " v.flags)
+ else if v ? "port" && v.port != null then
+ optionalString (v ? "addr" && v.addr != null) "${v.addr}:" +