From 55eaa559223da5b6cfd5bd6cd0e51b667d6865c9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rg=20Thalheim?= Date: Wed, 20 May 2020 16:39:39 +0100 Subject: [PATCH 01/28] nixos/redis: set TimeoutStartSec/TimeoutStopSec --- nixos/modules/services/databases/redis.nix | 2 ++ 1 file changed, 2 insertions(+) diff --git a/nixos/modules/services/databases/redis.nix b/nixos/modules/services/databases/redis.nix index 6b8853ae390..aeb1a0c22a4 100644 --- a/nixos/modules/services/databases/redis.nix +++ b/nixos/modules/services/databases/redis.nix @@ -242,6 +242,8 @@ in ExecStart = "${cfg.package}/bin/redis-server /run/redis/redis.conf"; RuntimeDirectory = "redis"; StateDirectory = "redis"; + TimeoutStartSec = "infinity"; + TimeoutStopSec = "infinity"; Type = "notify"; User = "redis"; Group = "redis"; From 8a6c765832bfa23b42e3baa7b6a3802aa805cea3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rg=20Thalheim?= Date: Sat, 14 Dec 2019 08:01:00 +0000 Subject: [PATCH 02/28] command-not-found: rewrite in Rust - drops perl + libraries dependencies --- .../command-not-found/command-not-found.nix | 11 +- .../command-not-found/command-not-found.pl | 51 ------- .../programs/command-not-found/default.nix | 18 +++ .../command-not-found/rust/Cargo.lock | 131 ++++++++++++++++++ .../command-not-found/rust/Cargo.toml | 10 ++ .../command-not-found/rust/src/main.rs | 52 +++++++ 6 files changed, 212 insertions(+), 61 deletions(-) delete mode 100644 nixos/modules/programs/command-not-found/command-not-found.pl create mode 100644 nixos/modules/programs/command-not-found/default.nix create mode 100644 nixos/modules/programs/command-not-found/rust/Cargo.lock create mode 100644 nixos/modules/programs/command-not-found/rust/Cargo.toml create mode 100644 nixos/modules/programs/command-not-found/rust/src/main.rs 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 656c255fcb1..da09488d82c 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 ab7aa204653..00000000000 --- 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 <{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 00000000000..bbe949fa86a --- /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 00000000000..ce3a9358c5c --- /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 00000000000..f965c7df76a --- /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 00000000000..b0af2871cc2 --- /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> { + Ok(Connection::open(DB_PATH)? + .prepare("select package from Programs where system = ? and name = ?;")? + .query_map(params![system, program], |row| row.get("package"))? + .collect::>>()?) +} + +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()); +} From 9c6f9c4068a883727aa3d52acd3745b724ec03f8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rg=20Thalheim?= Date: Sat, 30 May 2020 10:32:17 +0100 Subject: [PATCH 03/28] redis: fix redis service --- nixos/modules/services/databases/redis.nix | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/nixos/modules/services/databases/redis.nix b/nixos/modules/services/databases/redis.nix index aeb1a0c22a4..9988f382a1b 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} @@ -244,7 +244,7 @@ in StateDirectory = "redis"; TimeoutStartSec = "infinity"; TimeoutStopSec = "infinity"; - Type = "notify"; + Type = "simple"; User = "redis"; Group = "redis"; }; From 8420dc923e7076eb94fb4bf2c3e1eb9aa337af87 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rg=20Thalheim?= Date: Fri, 29 May 2020 22:55:38 +0100 Subject: [PATCH 04/28] homeassistant: support for python_script automation --- .../modules/services/misc/home-assistant.nix | 28 +++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/nixos/modules/services/misc/home-assistant.nix b/nixos/modules/services/misc/home-assistant.nix index 1f2e13f3732..16fff215e61 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 python_scripts integration. + Also see in the Homeassistant documentation + ''; + }; + 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" ]; From ce025026ac145680ed06a77ef9b20fbfb60e4953 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rg=20Thalheim?= Date: Mon, 22 Jun 2020 11:51:00 +0100 Subject: [PATCH 05/28] homeassistant: add package substitute for feedparser --- pkgs/servers/home-assistant/component-packages.nix | 2 +- pkgs/servers/home-assistant/parse-requirements.py | 6 ++++++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/pkgs/servers/home-assistant/component-packages.nix b/pkgs/servers/home-assistant/component-packages.nix index 9135ea549f3..429f140f738 100644 --- a/pkgs/servers/home-assistant/component-packages.nix +++ b/pkgs/servers/home-assistant/component-packages.nix @@ -243,7 +243,7 @@ "familyhub" = ps: with ps; [ ]; # missing inputs: python-family-hub-local "fan" = ps: with ps; [ ]; "fastdotcom" = ps: with ps; [ ]; # missing inputs: fastdotcom - "feedreader" = ps: with ps; [ ]; # missing inputs: feedparser-homeassistant + "feedreader" = ps: with ps; [ feedparser]; "ffmpeg" = ps: with ps; [ ha-ffmpeg ]; "ffmpeg_motion" = ps: with ps; [ ha-ffmpeg ]; "ffmpeg_noise" = ps: with ps; [ ha-ffmpeg ]; diff --git a/pkgs/servers/home-assistant/parse-requirements.py b/pkgs/servers/home-assistant/parse-requirements.py index 4fa4b8a48ee..3d25dfeaf84 100755 --- a/pkgs/servers/home-assistant/parse-requirements.py +++ b/pkgs/servers/home-assistant/parse-requirements.py @@ -41,6 +41,10 @@ PKG_PREFERENCES = { "tensorflow-build_2": "tensorflow", } +# packages we have a different name for or we want to replace +PKG_SUBSTITUTES = { + "feedparser-homeassistant": "feedparser" +} def run_mypy() -> None: cmd = ["mypy", "--ignore-missing-imports", __file__] @@ -156,6 +160,8 @@ def main() -> None: # Therefore, if there's a "#" in the line, only take the part after it req = req[req.find("#") + 1 :] name = req.split("==")[0] + name = PKG_SUBSTITUTES.get(name, name) + attr_path = name_to_attr_path(name, packages) if attr_path is not None: # Add attribute path without "python3Packages." prefix From 2ed6fbfaf12454b596e8b0a8b3ede28e3a88a798 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rg=20Thalheim?= Date: Sat, 30 May 2020 03:32:55 +0100 Subject: [PATCH 06/28] iina: init at 1.1.2 --- pkgs/applications/video/iina/default.nix | 26 ++++++++++++++++++++++++ pkgs/top-level/all-packages.nix | 2 ++ 2 files changed, 28 insertions(+) create mode 100644 pkgs/applications/video/iina/default.nix diff --git a/pkgs/applications/video/iina/default.nix b/pkgs/applications/video/iina/default.nix new file mode 100644 index 00000000000..f0abed2d93d --- /dev/null +++ b/pkgs/applications/video/iina/default.nix @@ -0,0 +1,26 @@ +{ stdenv, fetchurl, undmg }: + +stdenv.mkDerivation { + pname = "iina"; + version = "1.1.2"; + + src = fetchurl { + url = "https://github.com/iina/iina/releases/download/v1.0.7-beta2/IINA.v1.0.7-beta2.dmg"; + sha256 = "1w0l3b1kar9zglqkildcqhlwara6zy2p3x79kqa2d0b43nqka82n"; + }; + + buildInputs = [ undmg ]; + installPhase = '' + mkdir -p "$out/Applications/IINA.app" + cp -R . "$out/Applications/IINA.app" + chmod +x "$out/Applications/IINA.app/Contents/MacOS/IINA" + ''; + + meta = with stdenv.lib; { + description = "The modern video player for macOS."; + homepage = "http://https://iina.io/"; + license = licenses.gpl3; + platforms = platforms.darwin; + maintainers = with maintainers; [ mic92 ]; + }; +} diff --git a/pkgs/top-level/all-packages.nix b/pkgs/top-level/all-packages.nix index 312b1292245..1a24d918e0a 100644 --- a/pkgs/top-level/all-packages.nix +++ b/pkgs/top-level/all-packages.nix @@ -21236,6 +21236,8 @@ in icesl = callPackage ../applications/misc/icesl { }; + iina = callPackage ../applications/video/iina { }; + keepassx = callPackage ../applications/misc/keepassx { }; keepassx2 = callPackage ../applications/misc/keepassx/2.0.nix { }; keepassxc = libsForQt5.callPackage ../applications/misc/keepassx/community.nix { }; From e1e412215df70c45063f5c1bc6afcff7d3c1c0ce Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rg=20Thalheim?= Date: Wed, 12 Aug 2020 06:52:05 +0100 Subject: [PATCH 07/28] nixos-rebuild: document all nix flags --- nixos/doc/manual/man-nixos-rebuild.xml | 30 ++++++++++++++++++++++++-- 1 file changed, 28 insertions(+), 2 deletions(-) diff --git a/nixos/doc/manual/man-nixos-rebuild.xml b/nixos/doc/manual/man-nixos-rebuild.xml index d0ff81c1dbb..2ab5f006b06 100644 --- a/nixos/doc/manual/man-nixos-rebuild.xml +++ b/nixos/doc/manual/man-nixos-rebuild.xml @@ -112,6 +112,15 @@ path + + + + + + + + + @@ -130,6 +139,18 @@ number + + + + + + + + + + + + @@ -567,9 +588,14 @@ In addition, nixos-rebuild accepts various Nix-related - flags, including / , + flags: , / , , , - , , and / + , , and / + , , + , , + / , + / , + / and / . See the Nix manual for details. From b8a19ca2bcff1de182bc7d161afe54de8985b31f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rg=20Thalheim?= Date: Wed, 12 Aug 2020 06:52:32 +0100 Subject: [PATCH 08/28] nixos-rebuild: add --impure flag There are two use case for this flag: 1. NixOS developer usually use a nixpkgs checkout for development. Copying nixpkgs everytime when rebuilding NixOS is way to slow, even with NVME disks. 2. Folks migrating from impure configuration in a sufficient complex infrastructure need this flag to gradually migrate to NixOS flakes. --- nixos/doc/manual/man-nixos-rebuild.xml | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/nixos/doc/manual/man-nixos-rebuild.xml b/nixos/doc/manual/man-nixos-rebuild.xml index 2ab5f006b06..4510fdd4422 100644 --- a/nixos/doc/manual/man-nixos-rebuild.xml +++ b/nixos/doc/manual/man-nixos-rebuild.xml @@ -121,6 +121,9 @@ + + + @@ -597,6 +600,10 @@ / , / and / . See the Nix manual for details. + + The following Nix flags that are support by the upcoming nix 2.4 version: + , , , + , . See nix --help or nix build --help for details. From 19bf53f143040b87d39538e265ccc0933d7c1929 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rg=20Thalheim?= Date: Fri, 14 Aug 2020 07:25:07 +0100 Subject: [PATCH 09/28] nixos/filesystems: faster nonEmtpyStr check regexes should be faster than nix functions --- nixos/modules/tasks/filesystems.nix | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nixos/modules/tasks/filesystems.nix b/nixos/modules/tasks/filesystems.nix index a055072f9c9..96f57fc80b0 100644 --- a/nixos/modules/tasks/filesystems.nix +++ b/nixos/modules/tasks/filesystems.nix @@ -8,7 +8,7 @@ let addCheckDesc = desc: elemType: check: types.addCheck elemType check // { description = "${elemType.description} (with check: ${desc})"; }; nonEmptyStr = addCheckDesc "non-empty" types.str - (x: x != "" && ! (all (c: c == " " || c == "\t") (stringToCharacters x))); + (s: (builtins.match ".*[^ \t]+.*" s) != null); fileSystems' = toposort fsBefore (attrValues config.fileSystems); From f536901693ef6128cc61030ee74eb4433793b174 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rg=20Thalheim?= Date: Fri, 14 Aug 2020 07:25:50 +0100 Subject: [PATCH 10/28] nixos/filesystems: don't allow mountpoints with trailing slash They are semantically the same as the non-slash version and therefore are potential source of duplicates. Also fixes https://github.com/NixOS/nixpkgs/issues/78951 --- nixos/modules/tasks/filesystems.nix | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/nixos/modules/tasks/filesystems.nix b/nixos/modules/tasks/filesystems.nix index 96f57fc80b0..5388fc738e3 100644 --- a/nixos/modules/tasks/filesystems.nix +++ b/nixos/modules/tasks/filesystems.nix @@ -7,8 +7,9 @@ let addCheckDesc = desc: elemType: check: types.addCheck elemType check // { description = "${elemType.description} (with check: ${desc})"; }; - nonEmptyStr = addCheckDesc "non-empty" types.str - (s: (builtins.match ".*[^ \t]+.*" s) != null); + + isNonEmpty = s: (builtins.match ".*[^ \t]+.*" s) != null; + nonEmptyStr = addCheckDesc "non-empty" types.str isNonEmpty; fileSystems' = toposort fsBefore (attrValues config.fileSystems); @@ -28,10 +29,10 @@ let coreFileSystemOpts = { name, config, ... }: { options = { - mountPoint = mkOption { example = "/mnt/usb"; - type = nonEmptyStr; + type = addCheckDesc "non-empty without trailing slash" types.str + (s: isNonEmpty s && (builtins.match "(/|/.*[^/])" s) != null); description = "Location of the mounted the file system."; }; From a34aa811bdd00312409f875bd3483528dc7dbcc9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rg=20Thalheim?= Date: Sun, 20 Sep 2020 22:00:49 +0200 Subject: [PATCH 11/28] sysdig: enable aarch64 --- pkgs/os-specific/linux/sysdig/default.nix | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkgs/os-specific/linux/sysdig/default.nix b/pkgs/os-specific/linux/sysdig/default.nix index 0f8702eb6e0..5f4d638dfec 100644 --- a/pkgs/os-specific/linux/sysdig/default.nix +++ b/pkgs/os-specific/linux/sysdig/default.nix @@ -65,7 +65,7 @@ stdenv.mkDerivation rec { description = "A tracepoint-based system tracing tool for Linux (with clients for other OSes)"; license = with licenses; [ asl20 gpl2 mit ]; maintainers = [maintainers.raskin]; - platforms = ["x86_64-linux"] ++ platforms.darwin; + platforms = [ "x86_64-linux" "aarch64-linux" ] ++ platforms.darwin; broken = kernel != null && versionOlder kernel.version "4.14"; homepage = "https://sysdig.com/opensource/"; downloadPage = "https://github.com/draios/sysdig/releases"; From f84f71e1e0a51f3693be019f069149ef05b7b1ca Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rg=20Thalheim?= Date: Sun, 25 Oct 2020 07:21:00 +0100 Subject: [PATCH 12/28] nixos/nginx: add streamConfig option --- .../services/web-servers/nginx/default.nix | 21 +++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/nixos/modules/services/web-servers/nginx/default.nix b/nixos/modules/services/web-servers/nginx/default.nix index 62671e9d748..2bde2a68a6b 100644 --- a/nixos/modules/services/web-servers/nginx/default.nix +++ b/nixos/modules/services/web-servers/nginx/default.nix @@ -179,6 +179,12 @@ let ${cfg.httpConfig} }''} + ${optionalString (cfg.streamConfig != "") '' + stream { + ${cfg.streamConfig} + } + ''} + ${cfg.appendConfig} ''; @@ -452,6 +458,21 @@ in "; }; + streamConfig = mkOption { + type = types.lines; + default = ""; + example = '' + server { + listen 127.0.0.1:53 udp reuseport; + proxy_timeout 20s; + proxy_pass 192.168.0.1:53535; + } + ''; + description = " + Configuration lines to be set inside the stream block. + "; + }; + eventsConfig = mkOption { type = types.lines; default = ""; From 003c48411a02cc3083e2073508189599952d17fd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rg=20Thalheim?= Date: Thu, 12 Nov 2020 14:14:24 +0100 Subject: [PATCH 13/28] weechatScripts.wee-slack: switch to master --- .../0001-hardcode-json-file-path.patch | 35 +++++++++++++++++++ .../irc/weechat/scripts/wee-slack/default.nix | 8 ++--- .../wee-slack/hardcode-json-file-path.patch | 12 ------- 3 files changed, 39 insertions(+), 16 deletions(-) create mode 100644 pkgs/applications/networking/irc/weechat/scripts/wee-slack/0001-hardcode-json-file-path.patch delete mode 100644 pkgs/applications/networking/irc/weechat/scripts/wee-slack/hardcode-json-file-path.patch diff --git a/pkgs/applications/networking/irc/weechat/scripts/wee-slack/0001-hardcode-json-file-path.patch b/pkgs/applications/networking/irc/weechat/scripts/wee-slack/0001-hardcode-json-file-path.patch new file mode 100644 index 00000000000..45e620db258 --- /dev/null +++ b/pkgs/applications/networking/irc/weechat/scripts/wee-slack/0001-hardcode-json-file-path.patch @@ -0,0 +1,35 @@ +From 5dd2593369645b11a9dc03e1930617d2f5dbd039 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?J=C3=B6rg=20Thalheim?= +Date: Wed, 11 Nov 2020 11:48:49 +0100 +Subject: [PATCH] hardcode json file path +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Signed-off-by: Jörg Thalheim +--- + wee_slack.py | 8 +------- + 1 file changed, 1 insertion(+), 7 deletions(-) + +diff --git a/wee_slack.py b/wee_slack.py +index a3d779c..5942289 100644 +--- a/wee_slack.py ++++ b/wee_slack.py +@@ -5136,13 +5136,7 @@ def create_slack_debug_buffer(): + + def load_emoji(): + try: +- weechat_dir = w.info_get('weechat_dir', '') +- weechat_sharedir = w.info_get('weechat_sharedir', '') +- local_weemoji, global_weemoji = ('{}/weemoji.json'.format(path) +- for path in (weechat_dir, weechat_sharedir)) +- path = (global_weemoji if os.path.exists(global_weemoji) and +- not os.path.exists(local_weemoji) else local_weemoji) +- with open(path, 'r') as ef: ++ with open('@out@/share/wee-slack/weemoji.json', 'r') as ef: + emojis = json.loads(ef.read()) + if 'emoji' in emojis: + print_error('The weemoji.json file is in an old format. Please update it.') +-- +2.29.0 + diff --git a/pkgs/applications/networking/irc/weechat/scripts/wee-slack/default.nix b/pkgs/applications/networking/irc/weechat/scripts/wee-slack/default.nix index 9650f903ed6..4be611eb71f 100644 --- a/pkgs/applications/networking/irc/weechat/scripts/wee-slack/default.nix +++ b/pkgs/applications/networking/irc/weechat/scripts/wee-slack/default.nix @@ -2,13 +2,13 @@ stdenv.mkDerivation rec { pname = "wee-slack"; - version = "2.6.0"; + version = "8bd734c8e9a6b133a65548672f8a11ee3b3ce677"; src = fetchFromGitHub { repo = "wee-slack"; owner = "wee-slack"; - rev = "v${version}"; - sha256 = "0s4qd1z40c1bczkvc840jwjmzbv7nyj06xqs1si9v54qmkh4gaq4"; + rev = version; + sha256 = "0p48cpaqfqja9i68dqyladwif7x8c19ii8v27p9cxz5y9impc9qk"; }; patches = [ @@ -19,7 +19,7 @@ stdenv.mkDerivation rec { paths = with python3Packages; [ websocket_client six ]; }}/${python3Packages.python.sitePackages}"; }) - ./hardcode-json-file-path.patch + ./0001-hardcode-json-file-path.patch ]; postPatch = '' diff --git a/pkgs/applications/networking/irc/weechat/scripts/wee-slack/hardcode-json-file-path.patch b/pkgs/applications/networking/irc/weechat/scripts/wee-slack/hardcode-json-file-path.patch deleted file mode 100644 index 7413a9229ce..00000000000 --- a/pkgs/applications/networking/irc/weechat/scripts/wee-slack/hardcode-json-file-path.patch +++ /dev/null @@ -1,12 +0,0 @@ ---- a/wee_slack.py -+++ b/wee_slack.py -@@ -4560,8 +4560,7 @@ - - def load_emoji(): - try: -- DIR = w.info_get('weechat_dir', '') -- with open('{}/weemoji.json'.format(DIR), 'r') as ef: -+ with open('@out@/share/wee-slack/weemoji.json', 'r') as ef: - emojis = json.loads(ef.read()) - if 'emoji' in emojis: - print_error('The weemoji.json file is in an old format. Please update it.') From 2070c6a11b8799db25d105c4826ba6f1249faaf1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rg=20Thalheim?= Date: Sun, 15 Nov 2020 03:06:46 +0100 Subject: [PATCH 14/28] openafs_1_8: add version constraints --- pkgs/servers/openafs/1.8/default.nix | 1 + 1 file changed, 1 insertion(+) diff --git a/pkgs/servers/openafs/1.8/default.nix b/pkgs/servers/openafs/1.8/default.nix index c26f8d3a23c..1f475d7440f 100644 --- a/pkgs/servers/openafs/1.8/default.nix +++ b/pkgs/servers/openafs/1.8/default.nix @@ -100,6 +100,7 @@ in stdenv.mkDerivation { homepage = "https://www.openafs.org"; license = licenses.ipl10; platforms = platforms.linux; + broken = with kernel; kernelOlder "3.18" || isHardened; maintainers = [ maintainers.maggesi maintainers.spacefrogg ]; }; } From 64a7e509d7569de376f5446991f543e3344f37b7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rg=20Thalheim?= Date: Thu, 19 Nov 2020 11:47:29 +0100 Subject: [PATCH 15/28] nixos/nix-daemon: fix unknown sandbox warnings --- nixos/modules/services/misc/nix-daemon.nix | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/nixos/modules/services/misc/nix-daemon.nix b/nixos/modules/services/misc/nix-daemon.nix index 0eeff31d6c4..b0763c8d0de 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} From f438013ac4d1c064d3a3c88bd6401c8dcff1c851 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rg=20Thalheim?= Date: Sat, 5 Dec 2020 10:28:11 +0100 Subject: [PATCH 16/28] python3.pkgs.pyworld: init at 0.2.12 --- .../python-modules/pyworld/default.nix | 31 +++++++++++++++++++ pkgs/top-level/python-packages.nix | 2 ++ 2 files changed, 33 insertions(+) create mode 100644 pkgs/development/python-modules/pyworld/default.nix diff --git a/pkgs/development/python-modules/pyworld/default.nix b/pkgs/development/python-modules/pyworld/default.nix new file mode 100644 index 00000000000..92a91f766be --- /dev/null +++ b/pkgs/development/python-modules/pyworld/default.nix @@ -0,0 +1,31 @@ +{ lib +, buildPythonPackage +, fetchPypi +, numpy +, cython +}: + +buildPythonPackage rec { + pname = "pyworld"; + version = "0.2.12"; + + src = fetchPypi { + inherit pname version; + sha256 = "896c910696975855578d855f490f94d7a57119e0a75f7f15e11fdf58ba891627"; + }; + + nativeBuildInputs = [ + cython + ]; + + propagatedBuildInputs = [ + numpy + ]; + + meta = with lib; { + description = "PyWorld is a Python wrapper for WORLD vocoder"; + homepage = https://github.com/JeremyCCHsu/Python-Wrapper-for-World-Vocoder; + license = licenses.mit; + maintainers = [ maintainers.mic92 ]; + }; +} diff --git a/pkgs/top-level/python-packages.nix b/pkgs/top-level/python-packages.nix index 80f5f6cab1c..46ebc85dd00 100644 --- a/pkgs/top-level/python-packages.nix +++ b/pkgs/top-level/python-packages.nix @@ -6208,6 +6208,8 @@ in { }); in if isPy3k then pyxattr' else pyxattr_2; + pyworld = callPackage ../development/python-modules/pyworld { }; + pyx = callPackage ../development/python-modules/pyx { }; pyxdg = callPackage ../development/python-modules/pyxdg { }; From f730926a6c23139c99f0614ba2b1e5b900bb07f3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rg=20Thalheim?= Date: Sat, 5 Dec 2020 10:28:31 +0100 Subject: [PATCH 17/28] tts: better text expansion patches --- pkgs/tools/audio/tts/default.nix | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/pkgs/tools/audio/tts/default.nix b/pkgs/tools/audio/tts/default.nix index 770e898f2ee..338bbad19e4 100644 --- a/pkgs/tools/audio/tts/default.nix +++ b/pkgs/tools/audio/tts/default.nix @@ -61,6 +61,18 @@ python3Packages.buildPythonApplication rec { url = "https://github.com/mozilla/TTS/commit/36fee428b9f3f4ec1914b090a2ec9d785314d9aa.patch"; sha256 = "sha256-pP0NxiyrsvQ0A7GEleTdT87XO08o7WxPEpb6Bmj66dc="; }) + (fetchpatch { + url = "https://github.com/Mic92/TTS/commit/5bf62009e8c19e8c1627d1f7aa54e11bc5fa91d7.patch"; + sha256 = "sha256-ZxDytieD0zoP0/RXzG0bbVnl0oE+DF8iUVpHb8+2TqM="; + }) + (fetchpatch { + url = "https://github.com/mozilla/TTS/commit/3000647e542fce9773f4c5da082630befa5525f1.patch"; + sha256 = "sha256-dl8Zy0dEw9z4ZZFcuP1WHzCVh2+nn0jDKOncoCK+syM="; + }) + (fetchpatch { + url = "https://github.com/mozilla/TTS/commit/fe86a076bb1c7e18078718be0aa36da427f325bd.patch"; + sha256 = "sha256-cT5HYkLFzmSMwAHLOHgpG+v9HGKIbUxwS8Dt9SKHm+8="; + }) ]; preBuild = '' From 7a86a9505c06e7020f072463b343f0a83262f0eb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rg=20Thalheim?= Date: Sat, 5 Dec 2020 10:28:54 +0100 Subject: [PATCH 18/28] tts: add pyworld dependency this will become a dependency in the next version --- pkgs/tools/audio/tts/default.nix | 1 + 1 file changed, 1 insertion(+) diff --git a/pkgs/tools/audio/tts/default.nix b/pkgs/tools/audio/tts/default.nix index 338bbad19e4..1634bfa5b30 100644 --- a/pkgs/tools/audio/tts/default.nix +++ b/pkgs/tools/audio/tts/default.nix @@ -107,6 +107,7 @@ python3Packages.buildPythonApplication rec { inflect gdown pysbd + pyworld ]; postInstall = '' From 4caaec36ddbc9f12a91c4b01c1f4924ede2e0c4f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rg=20Thalheim?= Date: Sun, 6 Dec 2020 06:04:58 +0100 Subject: [PATCH 19/28] amazon-ec2-utils: 0.5.1 -> 1.3 --- nixos/modules/virtualisation/amazon-image.nix | 2 +- .../amazon-ec2-utils/default.nix | 42 +++++++++++++++++ .../virtualization/ec2-utils/default.nix | 47 ------------------- pkgs/top-level/aliases.nix | 1 + pkgs/top-level/all-packages.nix | 2 +- 5 files changed, 45 insertions(+), 49 deletions(-) create mode 100644 pkgs/tools/virtualization/amazon-ec2-utils/default.nix delete mode 100644 pkgs/tools/virtualization/ec2-utils/default.nix diff --git a/nixos/modules/virtualisation/amazon-image.nix b/nixos/modules/virtualisation/amazon-image.nix index 26297a7d0f1..4f83d72901c 100644 --- a/nixos/modules/virtualisation/amazon-image.nix +++ b/nixos/modules/virtualisation/amazon-image.nix @@ -137,7 +137,7 @@ in services.openssh.permitRootLogin = "prohibit-password"; # Creates symlinks for block device names. - services.udev.packages = [ pkgs.ec2-utils ]; + services.udev.packages = [ pkgs.amazon-ec2-utils ]; # Force getting the hostname from EC2. networking.hostName = mkDefault ""; diff --git a/pkgs/tools/virtualization/amazon-ec2-utils/default.nix b/pkgs/tools/virtualization/amazon-ec2-utils/default.nix new file mode 100644 index 00000000000..d7dd6ad0b1e --- /dev/null +++ b/pkgs/tools/virtualization/amazon-ec2-utils/default.nix @@ -0,0 +1,42 @@ +{ stdenv, lib, fetchFromGitHub, python3, installShellFiles }: + +stdenv.mkDerivation rec { + pname = "amazon-ec2-utils"; + version = "1.3"; + + src = fetchFromGitHub { + owner = "aws"; + repo = "amazon-ec2-utils"; + rev = version; + sha256 = "sha256-uxKnbdKGhS32kY3mA7YYtDRwKcEjNZPJUYQExZTqtxE="; + }; + + buildInputs = [ python3 ]; + # TODO next version will have manpages + #nativeBuildInputs = [ installShellFiles ]; + + installPhase = '' + # https://github.com/aws/amazon-ec2-utils/blob/8eb2effb1aea2280264d66ae58b3e156e6d429f9/amazon-ec2-utils.spec#L74 + install -D --target $out/etc/udev/rules.d *.rules + install -D --target $out/bin ec2-metadata ebsnvme-id ec2udev-vbd ec2udev-vcpu + install -D --target $out/lib/udev/ ec2nvme-nsid + # TODO next version will have manpages + #installManPage doc/* + ''; + + postFixup = '' + for i in $out/etc/udev/rules.d/*.rules; do + substituteInPlace "$i" \ + --replace '/sbin' "$out/bin" + done + substituteInPlace "$out/etc/udev/rules.d/70-ec2-nvme-devices.rules" \ + --replace 'ec2nvme-nsid' "$out/lib/udev/ec2nvme-nsid" + ''; + + meta = { + description = "A set of tools for running in EC2"; + homepage = "https://aws.amazon.com/amazon-linux-ami/"; + license = lib.licenses.asl20; + maintainers = with lib.maintainers; [ thefloweringash ]; + }; +} diff --git a/pkgs/tools/virtualization/ec2-utils/default.nix b/pkgs/tools/virtualization/ec2-utils/default.nix deleted file mode 100644 index 1605bcfa43b..00000000000 --- a/pkgs/tools/virtualization/ec2-utils/default.nix +++ /dev/null @@ -1,47 +0,0 @@ -{ stdenv, lib, rpmextract, fetchurl, python2, tree }: - -stdenv.mkDerivation { - name = "ec2-utils"; - version = "0.5.1"; - - # The url can be determined by booting an "Amazon Linux 2" and running: - # > yumdownloader --urls ec2-utils - src = fetchurl { - url = "http://amazonlinux.ap-northeast-1.amazonaws.com/blobstore/a3b4d2c35c2300518fe10381a05b3bd7936ff5cdd3d351143a11bf84073d9e00/ec2-utils-0.5-1.amzn2.0.1.noarch.rpm"; - sha256 = "004y7l3q9gqi78a53lykrpsnz4yp7dds1083w67m2013bk1x5d53"; - }; - - nativeBuildInputs = [ rpmextract ]; - - buildInputs = [ python2 ]; - - unpackPhase = '' - mkdir source - cd source - rpmextract "$src" - ''; - - installPhase = '' - mkdir $out - - mv --target-directory $out \ - etc sbin usr/bin usr/lib - ''; - - postFixup = '' - for i in $out/etc/udev/rules.d/*.rules; do - substituteInPlace "$i" \ - --replace '/sbin' "$out/bin" - done - - substituteInPlace "$out/etc/udev/rules.d/70-ec2-nvme-devices.rules" \ - --replace 'ec2nvme-nsid' "$out/lib/udev/ec2nvme-nsid" - ''; - - meta = { - description = "A set of tools for running in EC2"; - homepage = "https://aws.amazon.com/amazon-linux-ami/"; - license = lib.licenses.asl20; - maintainers = with lib.maintainers; [ thefloweringash ]; - }; -} diff --git a/pkgs/top-level/aliases.nix b/pkgs/top-level/aliases.nix index 6e5da1bf34e..793b58ac46d 100644 --- a/pkgs/top-level/aliases.nix +++ b/pkgs/top-level/aliases.nix @@ -138,6 +138,7 @@ mapAliases ({ draftsight = throw "draftsight has been removed, no longer available as freeware"; # added 2020-08-14 dvb_apps = throw "dvb_apps has been removed."; # added 2020-11-03 dwarf_fortress = dwarf-fortress; # added 2016-01-23 + ec2-utils = amazon-ec2-utils; # added 2020-12-06 emacsPackagesGen = emacsPackagesFor; # added 2018-08-18 emacsPackagesNgGen = emacsPackagesFor; # added 2018-08-18 emacsPackagesNgFor = emacsPackagesFor; # added 2019-08-07 diff --git a/pkgs/top-level/all-packages.nix b/pkgs/top-level/all-packages.nix index 1a24d918e0a..c77170369aa 100644 --- a/pkgs/top-level/all-packages.nix +++ b/pkgs/top-level/all-packages.nix @@ -997,7 +997,7 @@ in ec2_ami_tools = callPackage ../tools/virtualization/ec2-ami-tools { }; - ec2-utils = callPackage ../tools/virtualization/ec2-utils { }; + amazon-ec2-utils = callPackage ../tools/virtualization/amazon-ec2-utils { }; exoscale-cli = callPackage ../tools/admin/exoscale-cli { }; From d55bd2de7005b505debffe6f262e99869a0838b7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rg=20Thalheim?= Date: Sun, 6 Dec 2020 12:19:36 +0100 Subject: [PATCH 20/28] rubyPackages: remove problematic packages Those packages block regenerating the lock file. Bundler loops forever --- pkgs/development/ruby-modules/with-packages/Gemfile | 13 ------------- 1 file changed, 13 deletions(-) diff --git a/pkgs/development/ruby-modules/with-packages/Gemfile b/pkgs/development/ruby-modules/with-packages/Gemfile index 3454ce3df74..dda0f69c35c 100644 --- a/pkgs/development/ruby-modules/with-packages/Gemfile +++ b/pkgs/development/ruby-modules/with-packages/Gemfile @@ -14,13 +14,9 @@ source 'https://rubygems.org' do gem 'cocoapods' gem 'cocoapods-acknowledgements' gem 'cocoapods-art' - gem 'cocoapods-bin' gem 'cocoapods-browser' - gem 'cocoapods-bugsnag' - gem 'cocoapods-check' gem 'cocoapods-clean' gem 'cocoapods-clean_build_phases_scripts' - gem 'cocoapods-core' gem 'cocoapods-coverage' gem 'cocoapods-deintegrate' gem 'cocoapods-dependencies' @@ -31,18 +27,9 @@ source 'https://rubygems.org' do gem 'cocoapods-generate' gem 'cocoapods-git_url_rewriter' gem 'cocoapods-keys' - gem 'cocoapods-no-dev-schemes' gem 'cocoapods-open' - gem 'cocoapods-packager' - gem 'cocoapods-playgrounds' gem 'cocoapods-plugins' - gem 'cocoapods-prune-localizations' - gem 'cocoapods-rome' gem 'cocoapods-search' - gem 'cocoapods-sorted-search' - gem 'cocoapods-static-swift-framework' - gem 'cocoapods-stats' - gem 'cocoapods-tdfire-binary' gem 'cocoapods-testing' gem 'cocoapods-trunk' gem 'cocoapods-try' From 6722232b96cae9d56e90ecfdc02572ca460da67f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rg=20Thalheim?= Date: Sun, 6 Dec 2020 12:31:18 +0100 Subject: [PATCH 21/28] rubyPackages: update --- pkgs/top-level/ruby-packages.nix | 930 +++++++++++++++---------------- 1 file changed, 454 insertions(+), 476 deletions(-) diff --git a/pkgs/top-level/ruby-packages.nix b/pkgs/top-level/ruby-packages.nix index ef82be30b62..33a50e232d0 100644 --- a/pkgs/top-level/ruby-packages.nix +++ b/pkgs/top-level/ruby-packages.nix @@ -1,14 +1,36 @@ { + actioncable = { + dependencies = ["actionpack" "nio4r" "websocket-driver"]; + groups = ["default"]; + platforms = []; + source = { + remotes = ["https://rubygems.org"]; + sha256 = "0y3aa0965cdsqamxk8ac6brcvijl1zv4pvqils6xy3pbcrv0ljid"; + type = "gem"; + }; + version = "6.0.3.4"; + }; + actionmailbox = { + dependencies = ["actionpack" "activejob" "activerecord" "activestorage" "activesupport" "mail"]; + groups = ["default"]; + platforms = []; + source = { + remotes = ["https://rubygems.org"]; + sha256 = "10vb9s4frq22h5j6gyw2598k1jc29lg2czm95hf284l3mi4qly6a"; + type = "gem"; + }; + version = "6.0.3.4"; + }; actionmailer = { dependencies = ["actionpack" "actionview" "activejob" "mail" "rails-dom-testing"]; groups = ["default"]; platforms = []; source = { remotes = ["https://rubygems.org"]; - sha256 = "18wwlj4f7jffv3vxm80d2z36nwza95l5xfcqc401hvvrls4xzhsy"; + sha256 = "1ykn5qkwdlcv5aa1gjhhmrxpjccwa7df6n4amvkmvxv5lggyma52"; type = "gem"; }; - version = "4.2.11.1"; + version = "6.0.3.4"; }; actionpack = { dependencies = ["actionview" "activesupport" "rack" "rack-test" "rails-dom-testing" "rails-html-sanitizer"]; @@ -16,21 +38,32 @@ platforms = []; source = { remotes = ["https://rubygems.org"]; - sha256 = "0rmldsk3a4lwxk0lrp6x1nz1v1r2xmbm3300l4ghgfygv3grdwjh"; + sha256 = "0fbjpnh5hrihc9l35q9why6ip0hcdj42axzbp6b4j1xcy1v1bicj"; type = "gem"; }; - version = "4.2.11.1"; + version = "6.0.3.4"; }; - actionview = { - dependencies = ["activesupport" "builder" "erubis" "rails-dom-testing" "rails-html-sanitizer"]; + actiontext = { + dependencies = ["actionpack" "activerecord" "activestorage" "activesupport" "nokogiri"]; groups = ["default"]; platforms = []; source = { remotes = ["https://rubygems.org"]; - sha256 = "0x7vjn8q6blzyf7j3kwg0ciy7vnfh28bjdkd1mp9k4ghp9jn0g9p"; + sha256 = "0r0j0m76ynjspmvj5qbzl06kl9i920v269iz62y62009xydv6rqz"; type = "gem"; }; - version = "4.2.11.1"; + version = "6.0.3.4"; + }; + actionview = { + dependencies = ["activesupport" "builder" "erubi" "rails-dom-testing" "rails-html-sanitizer"]; + groups = ["default"]; + platforms = []; + source = { + remotes = ["https://rubygems.org"]; + sha256 = "0gdz31cq08nrqq6bxqim2qcbzv0fr34z6ycl73dmawpafj33wdkj"; + type = "gem"; + }; + version = "6.0.3.4"; }; activejob = { dependencies = ["activesupport" "globalid"]; @@ -38,43 +71,54 @@ platforms = []; source = { remotes = ["https://rubygems.org"]; - sha256 = "0jy1c1r6syjqpa0sh9f1p4iaxzvp6qg4n6zs774j9z27q7h407mj"; + sha256 = "0d0p8gjplrgym38dmchyzhv7lrrxngz0yrxl6xyvwxfxm1hgdk2k"; type = "gem"; }; - version = "4.2.11.1"; + version = "6.0.3.4"; }; activemodel = { - dependencies = ["activesupport" "builder"]; + dependencies = ["activesupport"]; groups = ["default"]; platforms = []; source = { remotes = ["https://rubygems.org"]; - sha256 = "1c1x0rd6wnk1f0gsmxs6x3gx7yf6fs9qqkdv7r4hlbcdd849in33"; + sha256 = "00jj8namy5niq7grl5lrsr4y351rxpj1b69k1i9gvb1hnpghl099"; type = "gem"; }; - version = "4.2.11.1"; + version = "6.0.3.4"; }; activerecord = { - dependencies = ["activemodel" "activesupport" "arel"]; + dependencies = ["activemodel" "activesupport"]; groups = ["default"]; platforms = []; source = { remotes = ["https://rubygems.org"]; - sha256 = "07ixiwi0zzs9skqarvpfamsnay7npfswymrn28ngxaf8hi279q5p"; + sha256 = "06qvvp73z8kq9sd2mhw6p9124q5pfkswjga2fidz4c73zbr79r3g"; type = "gem"; }; - version = "4.2.11.1"; + version = "6.0.3.4"; + }; + activestorage = { + dependencies = ["actionpack" "activejob" "activerecord" "marcel"]; + groups = ["default"]; + platforms = []; + source = { + remotes = ["https://rubygems.org"]; + sha256 = "0q734331wb7cfsh4jahj3lphpxvglzb17yvibwss1ml4g01xxm52"; + type = "gem"; + }; + version = "6.0.3.4"; }; activesupport = { - dependencies = ["i18n" "minitest" "thread_safe" "tzinfo"]; + dependencies = ["concurrent-ruby" "i18n" "minitest" "tzinfo" "zeitwerk"]; groups = ["default"]; platforms = []; source = { remotes = ["https://rubygems.org"]; - sha256 = "1vbq7a805bfvyik2q3kl9s3r418f5qzvysqbz2cwy4hr7m2q4ir6"; + sha256 = "1axidc4mikgi4yxs0ynw2c54jyrs5lxprxmzv6m3aayi9rg6rk5j"; type = "gem"; }; - version = "4.2.11.1"; + version = "6.0.3.4"; }; addressable = { dependencies = ["public_suffix"]; @@ -87,36 +131,15 @@ }; version = "2.7.0"; }; - algoliasearch = { - dependencies = ["httpclient" "json"]; - groups = ["default"]; - platforms = []; - source = { - remotes = ["https://rubygems.org"]; - sha256 = "1ayg8j3819ay2d8618jv32ca16fh8qsgjsiq9j32yd016c170nkj"; - type = "gem"; - }; - version = "1.27.1"; - }; - arel = { - groups = ["default"]; - platforms = []; - source = { - remotes = ["https://rubygems.org"]; - sha256 = "0nfcrdiys6q6ylxiblky9jyssrw2xj96fmxmal7f4f0jj3417vj4"; - type = "gem"; - }; - version = "6.0.4"; - }; ast = { groups = ["default"]; platforms = []; source = { remotes = ["https://rubygems.org"]; - sha256 = "184ssy3w93nkajlz2c70ifm79jp3j737294kbc5fjw69v1w0n9x7"; + sha256 = "1l3468czzjmxl93ap40hp7z94yxp4nbag0bxqs789bm30md90m2a"; type = "gem"; }; - version = "2.4.0"; + version = "2.4.1"; }; atk = { dependencies = ["glib2"]; @@ -124,10 +147,10 @@ platforms = []; source = { remotes = ["https://rubygems.org"]; - sha256 = "0a8q9a1f6x4gy55p8cf52a22bnpjgn18ad9n959x0f4gybbhs948"; + sha256 = "05brc25pfvak610mdwgjsc64di29yff9i9g72m6hyc21pdjwfy3n"; type = "gem"; }; - version = "3.4.1"; + version = "3.4.3"; }; atomos = { groups = ["default"]; @@ -174,10 +197,10 @@ platforms = []; source = { remotes = ["https://rubygems.org"]; - sha256 = "1mmkls9n56l4gx2k0dnyianwz36z2zgpxli5bpsbr7jbw7hn2x6j"; + sha256 = "0nx3yjf4xzdgb8jkmk2344081gqr22pgjqnmjg2q64mj5d6r9194"; type = "gem"; }; - version = "11.0.1"; + version = "11.1.3"; }; cairo = { dependencies = ["native-package-installer" "pkg-config"]; @@ -185,10 +208,10 @@ platforms = []; source = { remotes = ["https://rubygems.org"]; - sha256 = "0yvv2lcbsybzbw1nrmfivmln23da4rndrs3av6ymjh0x3ww5h7p8"; + sha256 = "00hiy6anibkjq9w77hg0lpgnkkbcxrfbz8wxv44jfzqbab8910wb"; type = "gem"; }; - version = "1.16.4"; + version = "1.16.6"; }; cairo-gobject = { dependencies = ["cairo" "glib2"]; @@ -196,10 +219,10 @@ platforms = []; source = { remotes = ["https://rubygems.org"]; - sha256 = "0gkxdfslcvrwrs48giilji3bgxd5bwijwq33p9h00r10jzfg2028"; + sha256 = "136aa800dgq6bmr0lb59mfj5q72r712wwp5wy5qxnp48adjw1k2h"; type = "gem"; }; - version = "3.4.1"; + version = "3.4.3"; }; camping = { dependencies = ["mab" "rack"]; @@ -217,10 +240,10 @@ platforms = []; source = { remotes = ["https://rubygems.org"]; - sha256 = "1825ll26p28swjiw8n3x2pnh5ygsmg83spf82fnzcjn2p87vc5lf"; + sha256 = "0ia09r8bj3bjhcfiyr3vlk9zx7vahfypbs2lyrxix9x1jx3lfzq4"; type = "gem"; }; - version = "3.0.2"; + version = "3.0.3"; }; charlock_holmes = { groups = ["default"]; @@ -247,10 +270,10 @@ platforms = []; source = { remotes = ["https://rubygems.org"]; - sha256 = "0dka8f3hwzz7p558kiyyrdabljvwp71cbzk46akb3kvnvhcyjx89"; + sha256 = "08m0syh06bhx8dqn560ivjg96l5cs5s3l9jh2szsnlcdcyl9jsjg"; type = "gem"; }; - version = "1.3.1"; + version = "1.3.2"; }; cld3 = { dependencies = ["ffi"]; @@ -258,53 +281,42 @@ platforms = []; source = { remotes = ["https://rubygems.org"]; - sha256 = "06p4jgrr0zixqnflmg5dcrbmhlnmll85j7vxkrjmnng293cwvzgw"; + sha256 = "04hwr44m7x7vv55lc4vk5zcd6zq98c2asvzl3dh2adg1fhpk29nr"; type = "gem"; }; - version = "3.2.4"; + version = "3.3.0"; }; cocoapods = { - dependencies = ["activesupport" "claide" "cocoapods-core" "cocoapods-deintegrate" "cocoapods-downloader" "cocoapods-plugins" "cocoapods-search" "cocoapods-stats" "cocoapods-trunk" "cocoapods-try" "colored2" "escape" "fourflusher" "gh_inspector" "molinillo" "nap" "ruby-macho" "xcodeproj"]; + dependencies = ["activesupport" "claide" "cocoapods-core" "cocoapods-deintegrate" "cocoapods-downloader" "cocoapods-plugins" "cocoapods-search" "cocoapods-stats" "cocoapods-trunk" "cocoapods-try" "colored" "escape" "fourflusher" "molinillo" "nap" "xcodeproj"]; groups = ["default"]; platforms = []; source = { remotes = ["https://rubygems.org"]; - sha256 = "007ssx75588ji2d8l8s6c95dng1c7b6yacng8nngpy7maijzjgzc"; + sha256 = "0rnxjwrfk3yz34xx11hh61j7p57l6vwh8b86jvjivzlgrj4a025r"; type = "gem"; }; - version = "1.8.4"; + version = "1.0.1"; }; cocoapods-acknowledgements = { - dependencies = ["activesupport" "redcarpet"]; + dependencies = ["cocoapods" "redcarpet" "xcodeproj"]; groups = ["default"]; platforms = []; source = { remotes = ["https://rubygems.org"]; - sha256 = "07n638ijlc4y5vfzs5ykzhmwwsng7njb2nnwn4ravydqqxqgv13m"; + sha256 = "04gaijs4djjkynan06wyaxxz48db0czzfrhh95jn3r201k2ypa7k"; type = "gem"; }; - version = "1.1.3"; + version = "1.3.0"; }; cocoapods-art = { groups = ["default"]; platforms = []; source = { remotes = ["https://rubygems.org"]; - sha256 = "0vkcpwjp7hzby60hq0pxn9zdiz7snf7siq02bckkmd84n27hlz3w"; + sha256 = "0ljsx1inbbzj8njpk4sb40kdis6pjwpgcpy3677dm45bxw21dmkv"; type = "gem"; }; - version = "1.0.4"; - }; - cocoapods-bin = { - dependencies = ["cocoapods" "cocoapods-generate" "parallel"]; - groups = ["default"]; - platforms = []; - source = { - remotes = ["https://rubygems.org"]; - sha256 = "0dzbv7bfyw8a0iyi4nqw8a74wrdhf3absnpdb3i46rpbkanxw7hy"; - type = "gem"; - }; - version = "0.1.24"; + version = "1.0.5"; }; cocoapods-browser = { dependencies = ["cocoapods"]; @@ -317,28 +329,6 @@ }; version = "0.1.5"; }; - cocoapods-bugsnag = { - dependencies = ["cocoapods"]; - groups = ["default"]; - platforms = []; - source = { - remotes = ["https://rubygems.org"]; - sha256 = "1r34h66rqswsyhanx69qnhhr02xsqy2y1zp5265gl6m76nyqq5wa"; - type = "gem"; - }; - version = "2.0.1"; - }; - cocoapods-check = { - dependencies = ["cocoapods"]; - groups = ["default"]; - platforms = []; - source = { - remotes = ["https://rubygems.org"]; - sha256 = "17wb5xzhjvrqllsjqqbm00w8gnsrwcb6k7wsb36ykbcp0aiagvaf"; - type = "gem"; - }; - version = "1.1.0"; - }; cocoapods-clean = { groups = ["default"]; platforms = []; @@ -360,15 +350,15 @@ version = "0.0.2"; }; cocoapods-core = { - dependencies = ["activesupport" "algoliasearch" "concurrent-ruby" "fuzzy_match" "nap"]; + dependencies = ["activesupport" "fuzzy_match" "nap"]; groups = ["default"]; platforms = []; source = { remotes = ["https://rubygems.org"]; - sha256 = "0zcisqb404828n5d3lbk9y2yyx8v2yr6rk1l8y9a4i1hp743fiad"; + sha256 = "1bh69sbljlf3hvg98y2zssx0ch51lllz1k1lc8xysn43dm3ahaa5"; type = "gem"; }; - version = "1.8.4"; + version = "1.0.1"; }; cocoapods-coverage = { dependencies = ["cocoapods-testing" "slather"]; @@ -427,10 +417,10 @@ platforms = []; source = { remotes = ["https://rubygems.org"]; - sha256 = "08vn0pgcyn6w6fq5xjd7szv2h9s5rzl17kyidnd7fl5qdmzc9c54"; + sha256 = "1j03hxvz3m82fwgx3jayw0y2iqm7zpacn88r6nfj2arkbjxmvjwz"; type = "gem"; }; - version = "1.3.0"; + version = "1.4.0"; }; cocoapods-expert-difficulty = { groups = ["default"]; @@ -458,10 +448,10 @@ platforms = []; source = { remotes = ["https://rubygems.org"]; - sha256 = "17nqdhdjjg3919h3sz7jkqqhxsi6nyqgfyd7y4ci6fvb7pz79pdh"; + sha256 = "0324y1fm93ri54c5015rh81zqakjmzh15v969ipg0p0xinfpv7ki"; type = "gem"; }; - version = "1.6.0"; + version = "2.0.1"; }; cocoapods-git_url_rewriter = { groups = ["default"]; @@ -479,20 +469,10 @@ platforms = []; source = { remotes = ["https://rubygems.org"]; - sha256 = "14jmfibzvhqxhvhphj3g83d70ya16p7s4i43wir48hnaxkaqrm85"; + sha256 = "153cxxsi77dygc4qrij6qs44dbvc7dw31jx06cmf0ajrhv9qjnxl"; type = "gem"; }; - version = "2.1.0"; - }; - cocoapods-no-dev-schemes = { - groups = ["default"]; - platforms = []; - source = { - remotes = ["https://rubygems.org"]; - sha256 = "14w8yqs3r6pg06zpv58mc9vzfxhp3ka4mfhnc2p7vmyhy4nmcdza"; - type = "gem"; - }; - version = "1.0.1"; + version = "2.2.1"; }; cocoapods-open = { groups = ["default"]; @@ -504,39 +484,6 @@ }; version = "0.0.8"; }; - cocoapods-packager = { - dependencies = ["cocoapods"]; - groups = ["default"]; - platforms = []; - source = { - remotes = ["https://rubygems.org"]; - sha256 = "1083zv9pyqyqal6dk3kvfxdmylbll6078z5zw03m4j5jcz3m8nbm"; - type = "gem"; - }; - version = "1.5.0"; - }; - cocoapods-packager-pro = { - dependencies = ["cocoapods"]; - groups = ["default"]; - platforms = []; - source = { - remotes = ["https://rubygems.org"]; - sha256 = "1sjnlnqrc3fvc33c3lg3h6y8n969isjswxg2jdc1kfc3x0cakawl"; - type = "gem"; - }; - version = "1.5.4"; - }; - cocoapods-playgrounds = { - dependencies = ["cocoapods"]; - groups = ["default"]; - platforms = []; - source = { - remotes = ["https://rubygems.org"]; - sha256 = "0jsc489j6dh3mczzs880vc6jvzd8yjqrszmbbnkz9azndak3mhln"; - type = "gem"; - }; - version = "1.2.2"; - }; cocoapods-plugins = { dependencies = ["nap"]; groups = ["default"]; @@ -548,27 +495,6 @@ }; version = "1.0.0"; }; - cocoapods-prune-localizations = { - groups = ["default"]; - platforms = []; - source = { - remotes = ["https://rubygems.org"]; - sha256 = "1hvpl56rnblmdbj40sysvk56j5hx5kdpqry00raw2p184sb5k4cf"; - type = "gem"; - }; - version = "0.3.1"; - }; - cocoapods-rome = { - dependencies = ["cocoapods" "fourflusher"]; - groups = ["default"]; - platforms = []; - source = { - remotes = ["https://rubygems.org"]; - sha256 = "1z5z49m5aww7q301bn5dzb6fzq6lcj6fvqibpg5ys1r0c41lsj0l"; - type = "gem"; - }; - version = "1.0.1"; - }; cocoapods-search = { groups = ["default"]; platforms = []; @@ -579,28 +505,6 @@ }; version = "1.0.0"; }; - cocoapods-sorted-search = { - dependencies = ["cocoapods" "hashie" "osx_keychain" "ruby-progressbar" "typhoeus"]; - groups = ["default"]; - platforms = []; - source = { - remotes = ["https://rubygems.org"]; - sha256 = "1da86mjq4spfsx6xjk7qylvj5423ai9y39g9xxfl9r6h8i54dmpp"; - type = "gem"; - }; - version = "0.2.4"; - }; - cocoapods-static-swift-framework = { - dependencies = ["cocoapods"]; - groups = ["default"]; - platforms = []; - source = { - remotes = ["https://rubygems.org"]; - sha256 = "12hhh25bj5dyz6rwc5jgarlld35vmgn43qk5lq9kfrpcli2ynhp2"; - type = "gem"; - }; - version = "0.5"; - }; cocoapods-stats = { groups = ["default"]; platforms = []; @@ -611,17 +515,6 @@ }; version = "1.1.0"; }; - cocoapods-tdfire-binary = { - dependencies = ["cocoapods" "cocoapods-bin" "cocoapods-packager-pro"]; - groups = ["default"]; - platforms = []; - source = { - remotes = ["https://rubygems.org"]; - sha256 = "10idp7yr2zni6zhpj1pqkj4wkk5g48f5iizjb20i8minj52l64m0"; - type = "gem"; - }; - version = "2.0.9"; - }; cocoapods-testing = { dependencies = ["xctasks"]; groups = ["default"]; @@ -639,20 +532,20 @@ platforms = []; source = { remotes = ["https://rubygems.org"]; - sha256 = "0vrwsgaq3nf7v3pwksgqy0mhswrp3ipczrc96vl3ii2pcc9ilwkw"; + sha256 = "12c6028bmdwrbqcb49mr5qj1p3vcijnjqbsbzywfx1isp44j9mv5"; type = "gem"; }; - version = "1.4.1"; + version = "1.5.0"; }; cocoapods-try = { groups = ["default"]; platforms = []; source = { remotes = ["https://rubygems.org"]; - sha256 = "1gf2zjmcjhh9psq15yfy82wz5jnlihf5bcw79f8hlv4cnqyspncj"; + sha256 = "1znyp625rql37ivb5rk9fk9564cmax8icxfr041ysivpdrn98nql"; type = "gem"; }; - version = "1.1.0"; + version = "1.2.0"; }; cocoapods-try-release-fix = { groups = ["default"]; @@ -700,10 +593,10 @@ platforms = []; source = { remotes = ["https://rubygems.org"]; - sha256 = "15vav4bhcc2x3jmi3izb11l4d9f3xv8hp2fszb7iqmpsccv1pz4y"; + sha256 = "0jvxqxzply1lwp7ysn94zjhh57vc14mcshw1ygw14ib8lhc00lyw"; type = "gem"; }; - version = "1.1.2"; + version = "1.1.3"; }; colorator = { groups = ["default"]; @@ -715,6 +608,16 @@ }; version = "1.1.0"; }; + colored = { + groups = ["default"]; + platforms = []; + source = { + remotes = ["https://rubygems.org"]; + sha256 = "0b0x5jmsyi0z69bm6sij1k89z7h0laag3cb4mdn7zkl9qmxb90lx"; + type = "gem"; + }; + version = "1.2"; + }; colored2 = { groups = ["default"]; platforms = []; @@ -730,30 +633,30 @@ platforms = []; source = { remotes = ["https://rubygems.org"]; - sha256 = "1x07r23s7836cpp5z9yrlbpljcxpax14yw4fy4bnp6crhr6x24an"; + sha256 = "1vnxrbhi7cq3p4y2v9iwd10v1c7l15is4var14hwnb2jip4fyjzz"; type = "gem"; }; - version = "1.1.5"; + version = "1.1.7"; }; crass = { groups = ["default"]; platforms = []; source = { remotes = ["https://rubygems.org"]; - sha256 = "030sc98kjrb36rh7g21qsbdfxrj6knsjkx0mn3b7gig8zknwhp2f"; + sha256 = "0pfl5c0pyqaparxaqxi6s4gfl21bdldwiawrc0aknyvflli60lfw"; type = "gem"; }; - version = "1.0.5"; + version = "1.0.6"; }; curb = { groups = ["default"]; platforms = []; source = { remotes = ["https://rubygems.org"]; - sha256 = "0s27g4nkdf8wipzyxx87nnw43ps8xqg30sqz86ay7dvmmpkd786k"; + sha256 = "1q7kqswm780vx1fannnrprbfbsp166smgyszgip5q7b859mk89wp"; type = "gem"; }; - version = "0.9.10"; + version = "0.9.11"; }; curses = { groups = ["default"]; @@ -791,20 +694,20 @@ platforms = []; source = { remotes = ["https://rubygems.org"]; - sha256 = "1nff0nai8h8786xix92f3k5wjb51gqd9gkibmah2bvrcwyn9qiw5"; + sha256 = "09frwp3np5c64y8g5rnbl46n7riknmdjprhndsh6zzajkjr9m3xj"; type = "gem"; }; - version = "1.3.1"; + version = "1.3.5"; }; diff-lcs = { groups = ["default"]; platforms = []; source = { remotes = ["https://rubygems.org"]; - sha256 = "18w22bjz424gzafv6nzv98h0aqkwz3d9xhm7cbr1wfbyas8zayza"; + sha256 = "0m925b8xc6kbpnif9dldna24q1szg4mk0fvszrki837pfn46afmz"; type = "gem"; }; - version = "1.3"; + version = "1.4.4"; }; digest-sha3 = { groups = ["default"]; @@ -853,10 +756,10 @@ platforms = []; source = { remotes = ["https://rubygems.org"]; - sha256 = "17hkd62ig9b0czv192kqdfq7gw0a8hgq07yclri6myc8y5lmfin5"; + sha256 = "0iym172c5337sm1x2ykc2i3f961vj3wdclbyg1x6sxs3irgfsl94"; type = "gem"; }; - version = "2.7.5"; + version = "2.7.6"; }; em-websocket = { dependencies = ["eventmachine" "http_parser.rb"]; @@ -864,20 +767,20 @@ platforms = []; source = { remotes = ["https://rubygems.org"]; - sha256 = "1bsw8vjz0z267j40nhbmrvfz7dvacq4p0pagvyp17jif6mj6v7n3"; + sha256 = "1mg1mx735a0k1l8y14ps2mxdwhi5r01ikydf34b0sp60v66nvbkb"; type = "gem"; }; - version = "0.5.1"; + version = "0.5.2"; }; - erubis = { + erubi = { groups = ["default"]; platforms = []; source = { remotes = ["https://rubygems.org"]; - sha256 = "1fj827xqjs91yqsydf0zmfyw9p4l2jz5yikg3mppz6d7fi8kyrb3"; + sha256 = "09l8lz3j00m898li0yfsnb6ihc63rdvhw3k5xczna5zrjk104f2l"; type = "gem"; }; - version = "2.7.0"; + version = "1.10.0"; }; escape = { groups = ["default"]; @@ -915,31 +818,31 @@ platforms = []; source = { remotes = ["https://rubygems.org"]; - sha256 = "0nn8wk7j22ly4lzdp5pnm7qsrjxbgspiyxkw70g1qf9bn6pslmxr"; + sha256 = "16ij8617v3js03yj1zd32mmrf7kpi9l96bid5mpqk30c4mzai55r"; type = "gem"; }; - version = "0.71.1"; + version = "0.78.1"; }; faraday = { - dependencies = ["multipart-post"]; + dependencies = ["multipart-post" "ruby2_keywords"]; groups = ["default"]; platforms = []; source = { remotes = ["https://rubygems.org"]; - sha256 = "1gggz3vvvkdrxil2fwpaaslv1z5bxzwra4wnybf20np58v1iv9w8"; + sha256 = "16dapwi5pivrl25r4lkr1mxjrzkznj4wlcb08fzkmxnj4g5c6y35"; type = "gem"; }; - version = "0.17.1"; + version = "1.1.0"; }; ffi = { groups = ["default"]; platforms = []; source = { remotes = ["https://rubygems.org"]; - sha256 = "0j8pzj8raxbir5w5k6s7a042sb5k02pg0f8s4na1r5lan901j00p"; + sha256 = "10ay35dm0lkcqprsiya6q2kwvyid884102ryipr4vrk790yfp8kd"; type = "gem"; }; - version = "1.10.0"; + version = "1.11.3"; }; ffi-compiler = { dependencies = ["ffi" "rake"]; @@ -969,10 +872,10 @@ platforms = []; source = { remotes = ["https://rubygems.org"]; - sha256 = "1s1jxlrbq4jhwkiy5gq429v87m1l602b2gppw0ikbax7rnv30s9x"; + sha256 = "0bwqm9n69y5y0a5iickr358z7w4hml3flqwfz8b7cnj1ldabhnjn"; type = "gem"; }; - version = "2.2.0"; + version = "2.2.3"; }; fog-dnsimple = { dependencies = ["fog-core" "fog-json"]; @@ -1021,10 +924,10 @@ platforms = []; source = { remotes = ["https://rubygems.org"]; - sha256 = "1afabh3g3gwj0ad53fs62waks815xcckf7pkci76l6vrghffcg8v"; + sha256 = "0yp0pxj6xsd84h2barwh3z5w289p1a6lqib309m7sbzh643qx3zz"; type = "gem"; }; - version = "2.3.1"; + version = "0.3.2"; }; fuzzy_match = { groups = ["default"]; @@ -1042,20 +945,10 @@ platforms = []; source = { remotes = ["https://rubygems.org"]; - sha256 = "0194gzn0kialfh0j7crllvp808r64sg6dh297x69b0av21ar5pam"; + sha256 = "0hslcfns2ysvjyj21hjvp4hghrafw1sdl627fm0nj0wsncs94m67"; type = "gem"; }; - version = "3.4.1"; - }; - gh_inspector = { - groups = ["default"]; - platforms = []; - source = { - remotes = ["https://rubygems.org"]; - sha256 = "0f8r9byajj3bi2c7c5sqrc7m0zrv3nblfcd4782lw5l73cbsgk04"; - type = "gem"; - }; - version = "1.1.3"; + version = "3.4.3"; }; gio2 = { dependencies = ["gobject-introspection"]; @@ -1063,20 +956,20 @@ platforms = []; source = { remotes = ["https://rubygems.org"]; - sha256 = "1l3jpgbdvb55xhcmpkcqgwx5068dfyi8kijfvzhbqh96ng0p1m7g"; + sha256 = "1l30xsr1dgnzqfmln17arnqi8iga97ldf6zgbqrfby6a94v3ammd"; type = "gem"; }; - version = "3.4.1"; + version = "3.4.3"; }; gitlab-markup = { groups = ["default"]; platforms = []; source = { remotes = ["https://rubygems.org"]; - sha256 = "0rqf3jmyn78r3ysy3bjyx7s4yv3xipxlmqlmbyrbksna19rrx08d"; + sha256 = "0xnlra517pfj3hx07kasbqlcw51ix4xajr6bsd3mwg8bc92dlwy7"; type = "gem"; }; - version = "1.7.0"; + version = "1.7.1"; }; glib2 = { dependencies = ["native-package-installer" "pkg-config"]; @@ -1084,10 +977,10 @@ platforms = []; source = { remotes = ["https://rubygems.org"]; - sha256 = "18clyn0fp0h5alnkf9i2bqd6wvl78h468pdbzs1csqnba8vw4q1c"; + sha256 = "0l46ymdf7azpd137xq4rarbaq54hxs9rgfry0r6b0ywj74rmw9ih"; type = "gem"; }; - version = "3.4.1"; + version = "3.4.3"; }; globalid = { dependencies = ["activesupport"]; @@ -1106,10 +999,10 @@ platforms = []; source = { remotes = ["https://rubygems.org"]; - sha256 = "1a3x8qiisbax3x0izj8l5w66r53ba5ma53ax2jhdbhbvaxx3d02n"; + sha256 = "11gas9hzq36a2bwqi7h5c6p6jihanbhsarwhv5fw53dxap4iwj25"; type = "gem"; }; - version = "3.4.1"; + version = "3.4.3"; }; gpgme = { dependencies = ["mini_portile2"]; @@ -1117,10 +1010,10 @@ platforms = []; source = { remotes = ["https://rubygems.org"]; - sha256 = "0jbqajngi5ndqfarw9dxkhbphva0j71jav5wfym3fsiisvk5gg6p"; + sha256 = "0xbgh9d8nbvsvyzqnd0mzhz0nr9hx4qn025kmz6d837lry4lc6gw"; type = "gem"; }; - version = "2.0.19"; + version = "2.0.20"; }; gtk2 = { dependencies = ["atk" "gdk_pixbuf2" "pango"]; @@ -1128,20 +1021,20 @@ platforms = []; source = { remotes = ["https://rubygems.org"]; - sha256 = "17az8g0n1yzz90kdbjg2hpabi04qccda7v6lin76bs637ivfg2md"; + sha256 = "0v1ag6irp52asm0yaxa7s533czy7yzhanhgn1v0cndqpzqk8icfz"; type = "gem"; }; - version = "3.4.1"; + version = "3.4.3"; }; hashie = { groups = ["default"]; platforms = []; source = { remotes = ["https://rubygems.org"]; - sha256 = "0drkv8a70akprcnbxvd08hzp2bgd5g4s5g752f8599ks1g6a7wj1"; + sha256 = "02bsx12ihl78x0vdm37byp78jjw2ff6035y7rrmbd90qxjwxr43q"; type = "gem"; }; - version = "4.0.0"; + version = "4.1.0"; }; highline = { groups = ["default"]; @@ -1230,10 +1123,10 @@ platforms = []; source = { remotes = ["https://rubygems.org"]; - sha256 = "038qvz7kd3cfxk8bvagqhakx68pfbnmghpdkx7573wbf0maqp9a3"; + sha256 = "153sx77p16vawrs4qpkv7qlzf9v5fks4g7xqcj1dwk40i6g7rfzk"; type = "gem"; }; - version = "0.9.5"; + version = "1.8.5"; }; iconv = { groups = ["default"]; @@ -1255,26 +1148,16 @@ }; version = "0.1.0"; }; - jaro_winkler = { - groups = ["default"]; - platforms = []; - source = { - remotes = ["https://rubygems.org"]; - sha256 = "1y8l6k34svmdyqxya3iahpwbpvmn3fswhwsvrz0nk1wyb8yfihsh"; - type = "gem"; - }; - version = "1.5.4"; - }; jbuilder = { dependencies = ["activesupport"]; groups = ["default"]; platforms = []; source = { remotes = ["https://rubygems.org"]; - sha256 = "03adzsc2hfd0lvprm45s52bkxpnpnw8r9prcx8zx1aw2a8lzp9r7"; + sha256 = "02llgsg30jz9kpxs8jzv6rvzaylw7948xj2grp4vsfg54z20cwbm"; type = "gem"; }; - version = "2.9.1"; + version = "2.10.1"; }; jekyll = { dependencies = ["addressable" "colorator" "em-websocket" "i18n" "jekyll-sass-converter" "jekyll-watch" "kramdown" "kramdown-parser-gfm" "liquid" "mercenary" "pathutil" "rouge" "safe_yaml" "terminal-table"]; @@ -1282,10 +1165,10 @@ platforms = []; source = { remotes = ["https://rubygems.org"]; - sha256 = "0fpckw5nf4hfr5vhhdlmaxxp5lkdmc1vyqnmijwvy9fmjn4c87aa"; + sha256 = "192k1ggw99slpqpxb4xamcvcm2pdahgnmygl746hmkrar0i3xa5r"; type = "gem"; }; - version = "4.0.0"; + version = "4.1.1"; }; jekyll-sass-converter = { dependencies = ["sassc"]; @@ -1293,10 +1176,10 @@ platforms = []; source = { remotes = ["https://rubygems.org"]; - sha256 = "0xjzqpp35qr2vnf2zpak0srn773mp21glcq81a0iqpnrva7h80m3"; + sha256 = "04ncr44wrilz26ayqwlg7379yjnkb29mvx4j04i62b7czmdrc9dv"; type = "gem"; }; - version = "2.0.1"; + version = "2.1.0"; }; jekyll-watch = { dependencies = ["listen"]; @@ -1324,30 +1207,31 @@ platforms = []; source = { remotes = ["https://rubygems.org"]; - sha256 = "0nrmw2r4nfxlfgprfgki3hjifgrcrs3l5zvm3ca3gb4743yr25mn"; + sha256 = "158fawfwmv2sq4whqqaksfykkiad2xxrrj0nmpnc6vnlzi1bp7iz"; type = "gem"; }; - version = "2.3.0"; + version = "2.3.1"; }; jwt = { groups = ["default"]; platforms = []; source = { remotes = ["https://rubygems.org"]; - sha256 = "01zg1vp3lyl3flyjdkrcc93ghf833qgfgh2p1biqfhkzz11r129c"; + sha256 = "14ynyq1q483spj20ffl4xayfqx1a8qr761mqjfxczf8lwlap392n"; type = "gem"; }; - version = "2.2.1"; + version = "2.2.2"; }; kramdown = { + dependencies = ["rexml"]; groups = ["default"]; platforms = []; source = { remotes = ["https://rubygems.org"]; - sha256 = "1dl840bvx8d9nq6lg3mxqyvbiqnr6lk3jfsm6r8zhz7p5srmd688"; + sha256 = "1vmw752c26ny2jwl0npn0gbyqwgz4hdmlpxnsld9qi9xhk5b1qh7"; type = "gem"; }; - version = "2.1.0"; + version = "2.3.0"; }; kramdown-parser-gfm = { dependencies = ["kramdown"]; @@ -1365,20 +1249,20 @@ platforms = []; source = { remotes = ["https://rubygems.org"]; - sha256 = "1jivcckillfvd4n2jnsnnlf93z3gpvqbwsczs0fvv9hc90zpj7yh"; + sha256 = "0317sr3nrl51sp844bps71smkrwim3fjn47wdfpbycixnbxspivm"; type = "gem"; }; - version = "7.3.492.27.1"; + version = "8.4.255.0"; }; libxml-ruby = { groups = ["default"]; platforms = []; source = { remotes = ["https://rubygems.org"]; - sha256 = "1r7m7zipkpam8ns4ys4qyh7yj3is3dy7ky6qwnw557pvpgx0aqrd"; + sha256 = "0w2pw08b6pc9pm51ix7413jcllaisc06dvwzq0191ag1jsysv220"; type = "gem"; }; - version = "3.1.0"; + version = "3.2.1"; }; liquid = { groups = ["default"]; @@ -1396,10 +1280,10 @@ platforms = []; source = { remotes = ["https://rubygems.org"]; - sha256 = "1w923wmdi3gyiky0asqdw5dnh3gcjs2xyn82ajvjfjwh6sn0clgi"; + sha256 = "1zpcgha7g33wvy2xbbc663cbjyvg9l1325lg3gzgcn3baydr9rha"; type = "gem"; }; - version = "3.2.1"; + version = "3.3.3"; }; loofah = { dependencies = ["crass" "nokogiri"]; @@ -1407,10 +1291,10 @@ platforms = []; source = { remotes = ["https://rubygems.org"]; - sha256 = "1g7ps9m3s14cajhxrfgbzahv9i3gy47s4hqrv3mpybpj5cyr0srn"; + sha256 = "0ndimir6k3kfrh8qrb7ir1j836l4r3qlwyclwjh88b86clblhszh"; type = "gem"; }; - version = "2.4.0"; + version = "2.8.0"; }; mab = { groups = ["default"]; @@ -1444,6 +1328,17 @@ }; version = "2.7.1"; }; + marcel = { + dependencies = ["mimemagic"]; + groups = ["default"]; + platforms = []; + source = { + remotes = ["https://rubygems.org"]; + sha256 = "1nxbjmcyg8vlw6zwagf17l9y2mwkagmmkg95xybpn4bmf3rfnksx"; + type = "gem"; + }; + version = "0.3.3"; + }; markaby = { dependencies = ["builder"]; groups = ["default"]; @@ -1460,20 +1355,20 @@ platforms = []; source = { remotes = ["https://rubygems.org"]; - sha256 = "10la0xw82dh5mqab8bl0dk21zld63cqxb1g16fk8cb39ylc4n21a"; + sha256 = "0f2i827w4lmsizrxixsrv2ssa3gk1b7lmqh8brk8ijmdb551wnmj"; type = "gem"; }; - version = "0.3.6"; + version = "0.4.0"; }; method_source = { groups = ["default"]; platforms = []; source = { remotes = ["https://rubygems.org"]; - sha256 = "1pviwzvdqd90gn6y7illcdd9adapw8fczml933p5vl739dkvl3lq"; + sha256 = "1pnyh44qycnf9mzi1j6fywd5fkskv3x7nmsqrrws0rjn5dd4ayfp"; type = "gem"; }; - version = "0.9.2"; + version = "1.0.0"; }; mime-types = { dependencies = ["mime-types-data"]; @@ -1491,20 +1386,30 @@ platforms = []; source = { remotes = ["https://rubygems.org"]; - sha256 = "18x61fc36951vw7f74gq8cyybdpxvyg5d0azvqhrs82ddw3v16xh"; + sha256 = "0ipjyfwn9nlvpcl8knq3jk4g5f12cflwdbaiqxcq1s7vwfwfxcag"; type = "gem"; }; - version = "3.2019.1009"; + version = "3.2020.1104"; + }; + mimemagic = { + groups = ["default"]; + platforms = []; + source = { + remotes = ["https://rubygems.org"]; + sha256 = "1qfqb9w76kmpb48frbzbyvjc0dfxh5qiw1kxdbv2y2kp6fxpa1kf"; + type = "gem"; + }; + version = "0.3.5"; }; mini_magick = { groups = ["default"]; platforms = []; source = { remotes = ["https://rubygems.org"]; - sha256 = "0qy09qrd5bwh8mkbj514n5vcw9ni73218h9s3zmvbpmdwrnzi8j4"; + sha256 = "1aj604x11d9pksbljh0l38f70b558rhdgji1s9i763hiagvvx2hs"; type = "gem"; }; - version = "4.9.5"; + version = "4.11.0"; }; mini_mime = { groups = ["default"]; @@ -1531,40 +1436,40 @@ platforms = []; source = { remotes = ["https://rubygems.org"]; - sha256 = "0w16p7cvslh3hxd3cia8jg4pd85z7rz7xqb16vh42gj4rijn8rmi"; + sha256 = "170y2cvx51gm3cm3nhdf7j36sxnkh6vv8ls36p90ric7w8w16h4v"; type = "gem"; }; - version = "5.13.0"; + version = "5.14.2"; }; molinillo = { groups = ["default"]; platforms = []; source = { remotes = ["https://rubygems.org"]; - sha256 = "1hh40z1adl4lw16dj4hxgabx4rr28mgqycih1y1d91bwww0jjdg6"; + sha256 = "0msabpxiyhlbgayrvr01316alaxrxwh6h8yzqz6p36v1zhqgddw4"; type = "gem"; }; - version = "0.6.6"; + version = "0.4.5"; }; msgpack = { groups = ["default"]; platforms = []; source = { remotes = ["https://rubygems.org"]; - sha256 = "1qr2mkm2i3m76zarvy7qgjl9596hmvjrg7x6w42vx8cfsbf5p0y1"; + sha256 = "1lva6bkvb4mfa0m3bqn4lm4s4gi81c40jvdcsrxr6vng49q9daih"; type = "gem"; }; - version = "1.3.1"; + version = "1.3.3"; }; multi_json = { groups = ["default"]; platforms = []; source = { remotes = ["https://rubygems.org"]; - sha256 = "0xy54mjf7xg41l8qrg1bqri75agdqmxap9z466fjismc1rn2jwfr"; + sha256 = "0pb1g1y3dsiahavspyzkdy39j4q377009f6ix0bh1ag4nqw43l0z"; type = "gem"; }; - version = "1.14.1"; + version = "1.15.0"; }; multipart-post = { groups = ["default"]; @@ -1576,6 +1481,17 @@ }; version = "2.1.1"; }; + mustermann = { + dependencies = ["ruby2_keywords"]; + groups = ["default"]; + platforms = []; + source = { + remotes = ["https://rubygems.org"]; + sha256 = "0ccm54qgshr1lq3pr1dfh7gphkilc19dp63rw6fcx7460pjwy88a"; + type = "gem"; + }; + version = "1.1.1"; + }; mysql2 = { groups = ["default"]; platforms = []; @@ -1591,10 +1507,10 @@ platforms = []; source = { remotes = ["https://rubygems.org"]; - sha256 = "0ajfyaqjw3dzykk612yw8sm21savfqy292hgps8h8l4lvxww1lz6"; + sha256 = "0xi36h3f7nm8bc2k0b6svpda1lyank2gf872lxjbhw3h95hdrbma"; type = "gem"; }; - version = "0.2.6"; + version = "0.3.0"; }; nap = { groups = ["default"]; @@ -1632,20 +1548,20 @@ platforms = []; source = { remotes = ["https://rubygems.org"]; - sha256 = "0nkf3my587f0izqw0dl3zl24c3lnrw9y5xrq9vb0lhgymmgcav9g"; + sha256 = "0b4h3ip8d1gkrc0znnw54hbxillk73mdnaf5pz330lmrcl1wiilg"; type = "gem"; }; - version = "2.0.0"; + version = "3.0.0"; }; net-ssh = { groups = ["default"]; platforms = []; source = { remotes = ["https://rubygems.org"]; - sha256 = "101wd2px9lady54aqmkibvy4j62zk32w0rjz4vnigyg974fsga40"; + sha256 = "0jp3jgcn8cij407xx9ldb5h9c6jv13jc4cf6kk2idclz43ww21c9"; type = "gem"; }; - version = "5.2.0"; + version = "6.1.0"; }; netrc = { groups = ["default"]; @@ -1662,10 +1578,10 @@ platforms = []; source = { remotes = ["https://rubygems.org"]; - sha256 = "0gnmvbryr521r135yz5bv8354m7xn6miiapfgpg1bnwsvxz8xj6c"; + sha256 = "1cbwp1kbv6b2qfxv8sarv0d0ilb257jihlvdqj8f5pdm0ksq1sgk"; type = "gem"; }; - version = "2.5.2"; + version = "2.5.4"; }; nokogiri = { dependencies = ["mini_portile2"]; @@ -1673,10 +1589,10 @@ platforms = []; source = { remotes = ["https://rubygems.org"]; - sha256 = "0r0qpgf80h764k176yr63gqbs2z0xbsp8vlvs2a79d5r9vs83kln"; + sha256 = "0xmf60nj5kg9vaj5bysy308687sgmkasgx06vbbnf94p52ih7si2"; type = "gem"; }; - version = "1.10.7"; + version = "1.10.10"; }; opus-ruby = { dependencies = ["ffi"]; @@ -1706,10 +1622,10 @@ platforms = []; source = { remotes = ["https://rubygems.org"]; - sha256 = "09lb0a9y4q7946jaf53li1v4cb6ksfb5bq5wb15yn8ja6wf9n427"; + sha256 = "1zlk3bksiwrdvb7j0r5av7w280kigl7947wa7w4kbwqz3snaxl3m"; type = "gem"; }; - version = "4.3.0"; + version = "4.4.0"; }; pango = { dependencies = ["cairo-gobject" "gobject-introspection"]; @@ -1717,20 +1633,20 @@ platforms = []; source = { remotes = ["https://rubygems.org"]; - sha256 = "1d0cn50qgpifrcv8qx72wi6l9xalw3ryngbfmm9xpg9vx5rl1qbp"; + sha256 = "05smxn2jank7wqih59lhr30ab8f4qxdsdiiag5v7a0gjgzkmbi7f"; type = "gem"; }; - version = "3.4.1"; + version = "3.4.3"; }; parallel = { groups = ["default"]; platforms = []; source = { remotes = ["https://rubygems.org"]; - sha256 = "12jijkap4akzdv11lm08dglsc8jmc87xcgq6947i1s3qb69f4zn2"; + sha256 = "0055br0mibnqz0j8wvy20zry548dhkakws681bhj3ycb972awkzd"; type = "gem"; }; - version = "1.19.1"; + version = "1.20.1"; }; parser = { dependencies = ["ast"]; @@ -1738,10 +1654,10 @@ platforms = []; source = { remotes = ["https://rubygems.org"]; - sha256 = "10siyp14d88jwcfj45kkk3nwl4wyr2r5ajb7vy4iwh1gxmhvi727"; + sha256 = "1f7gmm60yla325wlnd3qkxs59qm2y0aan8ljpg6k18rwzrrfil6z"; type = "gem"; }; - version = "2.7.0.0"; + version = "2.7.2.0"; }; pathutil = { dependencies = ["forwardable-extended"]; @@ -1779,20 +1695,20 @@ platforms = []; source = { remotes = ["https://rubygems.org"]; - sha256 = "15pa9qy7ngig21zgnvzwaxiy4rc7wbibna5050jjpgal9drgvpyy"; + sha256 = "13mfrysrdrh8cka1d96zm0lnfs59i5x2g6ps49r2kz5p3q81xrzj"; type = "gem"; }; - version = "1.2.0"; + version = "1.2.3"; }; pkg-config = { groups = ["default"]; platforms = []; source = { remotes = ["https://rubygems.org"]; - sha256 = "1cxdpr2wlz9b587avlq04a1da5fz1vdw8jvr6lx23mcq7mqh2xcx"; + sha256 = "068sf963n2zk47kqcckj624g5pxmk68mm76h02piphfyh9x4zmi3"; type = "gem"; }; - version = "1.4.0"; + version = "1.4.4"; }; polyglot = { groups = ["default"]; @@ -1810,10 +1726,10 @@ platforms = []; source = { remotes = ["https://rubygems.org"]; - sha256 = "00rm71x0r1jdycwbs83lf9l6p494m99asakbvqxh8rz7zwnlzg69"; + sha256 = "0iyw4q4an2wmk8v5rn2ghfy2jaz9vmw2nk8415nnpx2s866934qk"; type = "gem"; }; - version = "0.12.2"; + version = "0.13.1"; }; pry-byebug = { dependencies = ["byebug" "pry"]; @@ -1821,10 +1737,10 @@ platforms = []; source = { remotes = ["https://rubygems.org"]; - sha256 = "1aqz4gz8z44k6svpvcsfrqbigcpjd2kwvfm77yq3v8yzkhjrx0zi"; + sha256 = "096y5vmzpyy4x9h4ky4cs4y7d19vdq9vbwwrqafbh5gagzwhifiv"; type = "gem"; }; - version = "3.7.0"; + version = "3.9.0"; }; pry-doc = { dependencies = ["pry" "yard"]; @@ -1832,20 +1748,20 @@ platforms = []; source = { remotes = ["https://rubygems.org"]; - sha256 = "14lwb5dxfibcqbjygzvnf8ry0mayx48fk20qhg06214sll0sp0kv"; + sha256 = "1xrf2whjycv4sd7qvf5m6zdpk0lhf1p63v66w9ha146fc7rcjkc1"; type = "gem"; }; - version = "1.0.0"; + version = "1.1.0"; }; public_suffix = { groups = ["default"]; platforms = []; source = { remotes = ["https://rubygems.org"]; - sha256 = "0ww6577yhgszvc0p33qg9nb7n03fyadvl14v2kbpm4rpf0q4i6gz"; + sha256 = "1xqcgkl7bwws1qrlnmxgh8g4g9m10vg60bhlw40fplninb3ng6d9"; type = "gem"; }; - version = "4.0.2"; + version = "4.0.6"; }; puma = { dependencies = ["nio4r"]; @@ -1853,20 +1769,20 @@ platforms = []; source = { remotes = ["https://rubygems.org"]; - sha256 = "0v6zai6sinw5r1lchm278mm3dr8x5vi8pwmybwv9lz1kz02fk2g3"; + sha256 = "1fl2bgw1lh1712qpzl5m5vi4cc1bcw336bh1dbp28fkmss9yysma"; type = "gem"; }; - version = "4.3.1"; + version = "5.1.0"; }; rack = { groups = ["default"]; platforms = []; source = { remotes = ["https://rubygems.org"]; - sha256 = "1riq0z408dwvqcqrpq05bp2w879l4sjxzb4cbrbx55kpi6h2g1cj"; + sha256 = "0i5vs0dph9i5jn8dfc6aqd6njcafmb20rwqngrf759c9cvmyff16"; type = "gem"; }; - version = "1.6.12"; + version = "2.2.3"; }; rack-protection = { dependencies = ["rack"]; @@ -1874,10 +1790,10 @@ platforms = []; source = { remotes = ["https://rubygems.org"]; - sha256 = "0my0wlw4a5l3hs79jkx2xzv7djhajgf8d28k8ai1ddlnxxb0v7ss"; + sha256 = "159a4j4kragqh0z0z8vrpilpmaisnlz3n7kgiyf16bxkwlb3qlhz"; type = "gem"; }; - version = "1.5.5"; + version = "2.1.0"; }; rack-test = { dependencies = ["rack"]; @@ -1885,43 +1801,32 @@ platforms = []; source = { remotes = ["https://rubygems.org"]; - sha256 = "0h6x5jq24makgv2fq5qqgjlrk74dxfy62jif9blk43llw8ib2q7z"; + sha256 = "0rh8h376mx71ci5yklnpqqn118z3bl67nnv5k801qaqn1zs62h8m"; type = "gem"; }; - version = "0.6.3"; + version = "1.1.0"; }; rails = { - dependencies = ["actionmailer" "actionpack" "actionview" "activejob" "activemodel" "activerecord" "activesupport" "railties" "sprockets-rails"]; + dependencies = ["actioncable" "actionmailbox" "actionmailer" "actionpack" "actiontext" "actionview" "activejob" "activemodel" "activerecord" "activestorage" "activesupport" "railties" "sprockets-rails"]; groups = ["default"]; platforms = []; source = { remotes = ["https://rubygems.org"]; - sha256 = "1ywvis59dd3v8qapi9ix6743zgk07l21x1cd6nb1ddpahxhm7dml"; + sha256 = "0vs4kfgp5pr5032nnhdapq60ga6karann06ilq1yjx8qck87cfxg"; type = "gem"; }; - version = "4.2.11.1"; - }; - rails-deprecated_sanitizer = { - dependencies = ["activesupport"]; - groups = ["default"]; - platforms = []; - source = { - remotes = ["https://rubygems.org"]; - sha256 = "0qxymchzdxww8bjsxj05kbf86hsmrjx40r41ksj0xsixr2gmhbbj"; - type = "gem"; - }; - version = "1.0.3"; + version = "6.0.3.4"; }; rails-dom-testing = { - dependencies = ["activesupport" "nokogiri" "rails-deprecated_sanitizer"]; + dependencies = ["activesupport" "nokogiri"]; groups = ["default"]; platforms = []; source = { remotes = ["https://rubygems.org"]; - sha256 = "0wssfqpn00byhvp2372p99mphkcj8qx6pf6646avwr9ifvq0q1x6"; + sha256 = "1lfq2a7kp2x64dzzi5p4cjcbiv62vxh9lyqk2f0rqq3fkzrw8h5i"; type = "gem"; }; - version = "1.0.9"; + version = "2.0.3"; }; rails-html-sanitizer = { dependencies = ["loofah"]; @@ -1935,15 +1840,15 @@ version = "1.3.0"; }; railties = { - dependencies = ["actionpack" "activesupport" "rake" "thor"]; + dependencies = ["actionpack" "activesupport" "method_source" "rake" "thor"]; groups = ["default"]; platforms = []; source = { remotes = ["https://rubygems.org"]; - sha256 = "1bjf21z9maiiazc1if56nnh9xmgbkcqlpznv34f40a1hsvgk1d1m"; + sha256 = "0x28620cvfja8r06lk6f90pw5lvijz9qi4bjsa4z1d1rkr3v4r3w"; type = "gem"; }; - version = "4.2.11.1"; + version = "6.0.3.4"; }; rainbow = { groups = ["default"]; @@ -1970,10 +1875,10 @@ platforms = []; source = { remotes = ["https://rubygems.org"]; - sha256 = "1lm1k7wpz69jx7jrc92w3ggczkjyjbfziq5mg62vjnxmzs383xx8"; + sha256 = "1k9bsj7ni0g2fd7scyyy1sk9dy2pg9akniahab0iznvjmhn54h87"; type = "gem"; }; - version = "0.10.3"; + version = "0.10.4"; }; rb-inotify = { dependencies = ["ffi"]; @@ -2002,20 +1907,20 @@ platforms = []; source = { remotes = ["https://rubygems.org"]; - sha256 = "0lvz1vk2l3chnz6zdp4xmh6w2z75rndhgbravbxgvw8ff4snsxa7"; + sha256 = "0y8yzianlkc9w6sbqy8iy8l0yym0y6x7p5rjflkfixq76fqmhvzk"; type = "gem"; }; - version = "7.1.0"; + version = "7.1.1"; }; re2 = { groups = ["default"]; platforms = []; source = { remotes = ["https://rubygems.org"]; - sha256 = "00wf9k1hkv3z3nfkrnfyyfq9ah0l7k14awqys3h2hqz4c21pqd2i"; + sha256 = "16q71cc9wx342c697q18pkz19ym4ncjd97hcw4v6f1mgflkdv400"; type = "gem"; }; - version = "1.1.1"; + version = "1.2.0"; }; redcarpet = { groups = ["default"]; @@ -2032,10 +1937,10 @@ platforms = []; source = { remotes = ["https://rubygems.org"]; - sha256 = "08v2y91q1pmv12g9zsvwj66w3s8j9d82yrmxgyv4y4gz380j3wyh"; + sha256 = "15x2sr6h094rjbvg8pkq6m3lcd5abpyx93aifvfdz3wv6x55xa48"; type = "gem"; }; - version = "4.1.3"; + version = "4.2.5"; }; redis-rack = { dependencies = ["rack" "redis-store"]; @@ -2043,10 +1948,10 @@ platforms = []; source = { remotes = ["https://rubygems.org"]; - sha256 = "1pa19ydbk0l6wilwbxcjn6knfs4ffgj0rhaaldrlhf76pjgkaiqb"; + sha256 = "1nblbxg1f051dn83jp92lz3lc1wxm18nviglrabv2l0vz6rd0pkb"; type = "gem"; }; - version = "2.0.6"; + version = "2.1.3"; }; redis-store = { dependencies = ["redis"]; @@ -2054,10 +1959,20 @@ platforms = []; source = { remotes = ["https://rubygems.org"]; - sha256 = "1isqzzds9kszc2nn8jiy8ikry01qspn7637ba9z2k6sk7vky46d9"; + sha256 = "0cpzbf2svnk4j5awb24ncl0mih45zkbdrd7q23jdg1r8k3q7mdg6"; type = "gem"; }; - version = "1.8.1"; + version = "1.9.0"; + }; + regexp_parser = { + groups = ["default"]; + platforms = []; + source = { + remotes = ["https://rubygems.org"]; + sha256 = "1racz3w9s4w0ls32bvjypfifk4a7qxngm2cv1rh16jyz0c1wjd70"; + type = "gem"; + }; + version = "2.0.0"; }; rest-client = { dependencies = ["http-accept" "http-cookie" "mime-types" "netrc"]; @@ -2070,25 +1985,35 @@ }; version = "2.1.0"; }; + rexml = { + groups = ["default"]; + platforms = []; + source = { + remotes = ["https://rubygems.org"]; + sha256 = "1mkvkcw9fhpaizrhca0pdgjcrbns48rlz4g6lavl5gjjq3rk2sq3"; + type = "gem"; + }; + version = "3.2.4"; + }; rmagick = { groups = ["default"]; platforms = []; source = { remotes = ["https://rubygems.org"]; - sha256 = "06ya2zpz2g3g4c90bmd1z11qkajls3srq5b7cswrjq8ima568ja0"; + sha256 = "0ajn6aisf9hh3x5zrs7n02pg5xy3m8x38gh9cn7b3klzgp3djla5"; type = "gem"; }; - version = "4.0.0"; + version = "4.1.2"; }; rouge = { groups = ["default"]; platforms = []; source = { remotes = ["https://rubygems.org"]; - sha256 = "0k5jrp0qc9p61mfcwyn1a7dajmkw04z6y76wa8a0axh1v2wrw8ld"; + sha256 = "0yvcv901lrh5rfnk1h4h56hf2m6n9pd6w8n96vag74aakgz3gaxn"; type = "gem"; }; - version = "3.14.0"; + version = "3.25.0"; }; rpam2 = { groups = ["default"]; @@ -2106,10 +2031,10 @@ platforms = []; source = { remotes = ["https://rubygems.org"]; - sha256 = "1hzsig4pi9ybr0xl5540m1swiyxa74c8h09225y5sdh2rjkkg84h"; + sha256 = "1dwai7jnwmdmd7ajbi2q0k0lx1dh88knv5wl7c34wjmf94yv8w5q"; type = "gem"; }; - version = "3.9.0"; + version = "3.10.0"; }; rspec-core = { dependencies = ["rspec-support"]; @@ -2117,10 +2042,10 @@ platforms = []; source = { remotes = ["https://rubygems.org"]; - sha256 = "0gppalb2ynj0xk7vp8kk5pwzihmiqc8l4prpy4n9spclq7iqkspq"; + sha256 = "0n2rdv8f26yw8c6asymc0mgddyr5d2b5n6mfvpd3n6lnpf1jdyv2"; type = "gem"; }; - version = "3.9.0"; + version = "3.10.0"; }; rspec-expectations = { dependencies = ["diff-lcs" "rspec-support"]; @@ -2128,10 +2053,10 @@ platforms = []; source = { remotes = ["https://rubygems.org"]; - sha256 = "1gjqfb39da6gywdcp4h77738r7khbrn2v4y45589z25bj4z9paf0"; + sha256 = "0j37dvnvfbjwj8dqx27yfvz0frl7f2jc1abqg99h0ppriz9za6dc"; type = "gem"; }; - version = "3.9.0"; + version = "3.10.0"; }; rspec-mocks = { dependencies = ["diff-lcs" "rspec-support"]; @@ -2139,52 +2064,64 @@ platforms = []; source = { remotes = ["https://rubygems.org"]; - sha256 = "0q9f8nrxhs4k2vl3bnm3pi5s44v9pnvjwirjnwji3sxzf68c2xjf"; + sha256 = "1pz89y1522i6f8wzrg72ykmch3318ih87nlpl0y1ghsrs5hqymw3"; type = "gem"; }; - version = "3.9.0"; + version = "3.10.0"; }; rspec-support = { groups = ["default"]; platforms = []; source = { remotes = ["https://rubygems.org"]; - sha256 = "18080h06kqayyr6dpw4c62l0wav09ihkd6skinsln13kmq0cv0mx"; + sha256 = "0j0n28i6zci5j7gg370bdy87dy43hlwx6dw428d9kamf5a0i2klz"; type = "gem"; }; - version = "3.9.0"; + version = "3.10.0"; }; rubocop = { - dependencies = ["jaro_winkler" "parallel" "parser" "rainbow" "ruby-progressbar" "unicode-display_width"]; + dependencies = ["parallel" "parser" "rainbow" "regexp_parser" "rexml" "rubocop-ast" "ruby-progressbar" "unicode-display_width"]; groups = ["default"]; platforms = []; source = { remotes = ["https://rubygems.org"]; - sha256 = "1p1bhsfscasp57l5di9hsx8jl325kfjswhd2mlzq74hj3gdws4x0"; - type = "gem"; - }; - version = "0.78.0"; - }; - rubocop-performance = { - dependencies = ["rubocop"]; - groups = ["default"]; - platforms = []; - source = { - remotes = ["https://rubygems.org"]; - sha256 = "1fk9nd3b24avgsqp726hy2pl1iyfjrh6jni97wkky6kqy0lq6zq2"; + sha256 = "0k246mahr4737rlvazll5vfvq1307b0z9pmhlnp5ynknl31fclp5"; type = "gem"; }; version = "1.5.2"; }; - ruby-graphviz = { + rubocop-ast = { + dependencies = ["parser"]; groups = ["default"]; platforms = []; source = { remotes = ["https://rubygems.org"]; - sha256 = "1jzbs0jhaz77azsc30gsfg89fy44vsr565jcj4axhc65n1fmhs90"; + sha256 = "1z9253d7hwdlqr3g7rwx6x6n0qwv8niq6r2ppgry2lbfvb4czypm"; type = "gem"; }; - version = "1.2.4"; + version = "1.3.0"; + }; + rubocop-performance = { + dependencies = ["rubocop" "rubocop-ast"]; + groups = ["default"]; + platforms = []; + source = { + remotes = ["https://rubygems.org"]; + sha256 = "0zfc0wvx4jw0apn86jbz5za8pjmb7k0j58ndap3kwarkznxk2ad1"; + type = "gem"; + }; + version = "1.9.1"; + }; + ruby-graphviz = { + dependencies = ["rexml"]; + groups = ["default"]; + platforms = []; + source = { + remotes = ["https://rubygems.org"]; + sha256 = "010m283gk4qgzxkgrldlnrglh8d5fn6zvrzm56wf5abd7x7b8aqw"; + type = "gem"; + }; + version = "1.2.5"; }; ruby-libvirt = { groups = ["default"]; @@ -2206,16 +2143,6 @@ }; version = "1.2.3"; }; - ruby-macho = { - groups = ["default"]; - platforms = []; - source = { - remotes = ["https://rubygems.org"]; - sha256 = "0lhdjn91jkifsy2hzq2hgcm0pp8pbik87m58zmw1ifh6hkp9adjb"; - type = "gem"; - }; - version = "1.4.0"; - }; ruby-progressbar = { groups = ["default"]; platforms = []; @@ -2242,10 +2169,20 @@ platforms = []; source = { remotes = ["https://rubygems.org"]; - sha256 = "14hzfsbx7n0jsm6bxif99kbhlmxr4s7g6xvml6xbqphlqbmy5d43"; + sha256 = "0lk124dixshf8mmrjpsy9avnaygni3cwki25g8nm5py4d2f5fwwa"; type = "gem"; }; - version = "2.0.16"; + version = "2.0.17"; + }; + ruby2_keywords = { + groups = ["default"]; + platforms = []; + source = { + remotes = ["https://rubygems.org"]; + sha256 = "17pcc0wgvh3ikrkr7bm3nx0qhyiqwidd13ij0fa50k7gsbnr2p0l"; + type = "gem"; + }; + version = "0.0.2"; }; RubyInline = { dependencies = ["ZenTest"]; @@ -2263,20 +2200,20 @@ platforms = []; source = { remotes = ["https://rubygems.org"]; - sha256 = "1gz0ri0pa2xr7b6bf66yjc2wfvk51f4gi6yk7bklwl1nr65zc4gz"; + sha256 = "0590m2pr9i209pp5z4mx0nb1961ishdiqb28995hw1nln1d1b5ji"; type = "gem"; }; - version = "2.0.0"; + version = "2.3.0"; }; rugged = { groups = ["default"]; platforms = []; source = { remotes = ["https://rubygems.org"]; - sha256 = "0rdidxgpk1b6y1jq9v77lcx5khq0s9q0s253lr8x57d3hk43iskx"; + sha256 = "04aq913plcxjw71l5r62qgz3bx3466p0wvgyfqahg5n3nybmcwqy"; type = "gem"; }; - version = "0.28.4.1"; + version = "1.1.0"; }; safe_yaml = { groups = ["default"]; @@ -2294,10 +2231,10 @@ platforms = []; source = { remotes = ["https://rubygems.org"]; - sha256 = "09bnid7r5z5hcin5hykvpvv8xig27wbbckxwis60z2aaxq4j9siz"; + sha256 = "0gpqv48xhl8mb8qqhcifcp0pixn206a7imc07g48armklfqa4q2c"; type = "gem"; }; - version = "2.2.1"; + version = "2.4.0"; }; scrypt = { dependencies = ["ffi-compiler"]; @@ -2315,20 +2252,20 @@ platforms = []; source = { remotes = ["https://rubygems.org"]; - sha256 = "0wxkmgjnb8nskvqqwxihhbc1x8dhbbrcq70zxwqbyy5hvf4dh88f"; + sha256 = "1yz6pqdr8p5dv5qkza5kqn6il6m4vcl5hvry6k108axc12zf6hrb"; type = "gem"; }; - version = "0.10.0"; + version = "0.10.6"; }; sequel = { groups = ["default"]; platforms = []; source = { remotes = ["https://rubygems.org"]; - sha256 = "0vrbwwxvmdb7q1sdc0jnhlf826l74n9880xy5li1qabr0hyrmf1j"; + sha256 = "0k4ybmzrf79j9hgcl4m0hiaibf6m8apll99hml9rdjxvkprw51in"; type = "gem"; }; - version = "5.27.0"; + version = "5.39.0"; }; sequel_pg = { dependencies = ["pg" "sequel"]; @@ -2336,42 +2273,52 @@ platforms = []; source = { remotes = ["https://rubygems.org"]; - sha256 = "1y010rfdgpkw1yspqchjqdp7n8yahscyw98g3l2pw56nzbqipjb8"; + sha256 = "0mkbnc96bfpl5wqacblzwiwqywbx4vqrvkz57fj1h2f0bn635nk6"; type = "gem"; }; - version = "1.12.2"; + version = "1.14.0"; }; simplecov = { - dependencies = ["docile" "json" "simplecov-html"]; + dependencies = ["docile" "simplecov-html" "simplecov_json_formatter"]; groups = ["default"]; platforms = []; source = { remotes = ["https://rubygems.org"]; - sha256 = "1135k46nik05sdab30yxb8264lqiz01c8v000g16cl9pjc4mxrdw"; + sha256 = "1mm20dvd64w46l5k11il9z5sjgdpp0bknml76glcngvl2w03k3cb"; type = "gem"; }; - version = "0.17.1"; + version = "0.20.0"; }; simplecov-html = { groups = ["default"]; platforms = []; source = { remotes = ["https://rubygems.org"]; - sha256 = "1lihraa4rgxk8wbfl77fy9sf0ypk31iivly8vl3w04srd7i0clzn"; + sha256 = "0yx01bxa8pbf9ip4hagqkp5m0mqfnwnw2xk8kjraiywz4lrss6jb"; type = "gem"; }; - version = "0.10.2"; + version = "0.12.3"; }; - sinatra = { - dependencies = ["rack" "rack-protection" "tilt"]; + simplecov_json_formatter = { groups = ["default"]; platforms = []; source = { remotes = ["https://rubygems.org"]; - sha256 = "0byxzl7rx3ki0xd7aiv1x8mbah7hzd8f81l65nq8857kmgzj1jqq"; + sha256 = "0cl3j7p3b5q7sxsx1va63c8imc5x6g99xablz08qrmqhpi0d6g6j"; type = "gem"; }; - version = "1.4.8"; + version = "0.1.2"; + }; + sinatra = { + dependencies = ["mustermann" "rack" "rack-protection" "tilt"]; + groups = ["default"]; + platforms = []; + source = { + remotes = ["https://rubygems.org"]; + sha256 = "0dd53rzpkxgs697pycbhhgc9vcnxra4ly4xar8ni6aiydx2f88zk"; + type = "gem"; + }; + version = "2.1.0"; }; slather = { dependencies = ["CFPropertyList" "activesupport" "clamp" "nokogiri" "xcodeproj"]; @@ -2379,30 +2326,30 @@ platforms = []; source = { remotes = ["https://rubygems.org"]; - sha256 = "0v4wll10mwmynj2v2g71kgr1psck3qglhz2mnrw2n281v30jxyyn"; + sha256 = "0nqyam74izmbczwb406bsmgdzjz5r91d4lywlvdbxx5sl4g4256a"; type = "gem"; }; - version = "2.4.7"; + version = "2.6.0"; }; slop = { groups = ["default"]; platforms = []; source = { remotes = ["https://rubygems.org"]; - sha256 = "0hv64fpbdwyswqhnq8bia66vlsz72yjqm00lvlhh4dnjjivdjcy5"; + sha256 = "05d1xv8r9cmd0mmlqpa853yzd7xhcyha063w1g8dpf84scxbxmd3"; type = "gem"; }; - version = "4.7.0"; + version = "4.8.2"; }; snappy = { groups = ["default"]; platforms = []; source = { remotes = ["https://rubygems.org"]; - sha256 = "00zzs25sm78zs3rifc02z54cp3f03r9dq5ilzykyq1ykvbv65vw4"; + sha256 = "1x0r1dnavg3skyp7b1nkiwd5qrrkvp9zwgfls3i2rzybq8ahx4lb"; type = "gem"; }; - version = "0.0.17"; + version = "0.1.0"; }; sprockets = { dependencies = ["concurrent-ruby" "rack"]; @@ -2410,10 +2357,10 @@ platforms = []; source = { remotes = ["https://rubygems.org"]; - sha256 = "0jm37zpvvm1arxjwrd6am0wrdbfhrhc5y0l4p2i3p11z04bsvgap"; + sha256 = "0ikgwbl6jv3frfiy3xhg5yxw9d0064rgzghar1rg391xmrc4gm38"; type = "gem"; }; - version = "4.0.0"; + version = "4.0.2"; }; sprockets-rails = { dependencies = ["actionpack" "activesupport" "sprockets"]; @@ -2421,10 +2368,10 @@ platforms = []; source = { remotes = ["https://rubygems.org"]; - sha256 = "0ab42pm8p5zxpv3sfraq45b9lj39cz9mrpdirm30vywzrwwkm5p1"; + sha256 = "0mwmz36265646xqfyczgr1mhkm1hfxgxxvgdgr4xfcbf2g72p1k2"; type = "gem"; }; - version = "3.2.1"; + version = "3.2.2"; }; sqlite3 = { groups = ["default"]; @@ -2441,10 +2388,10 @@ platforms = []; source = { remotes = ["https://rubygems.org"]; - sha256 = "0r8g7zdncc6243d000jn0grc1n70rn9mx16vggy3q7c4wgsa37xi"; + sha256 = "1g7398sn8syybz3nbf3dqwa8q8v3s3s444i24xl5q9pzx4g4nkf1"; type = "gem"; }; - version = "0.7.1"; + version = "1.0.1"; }; terminal-table = { dependencies = ["unicode-display_width"]; @@ -2482,10 +2429,10 @@ platforms = []; source = { remotes = ["https://rubygems.org"]; - sha256 = "02p107kwx7jnkh6fpdgvaji0xdg6xkaarngkqjml6s4zny4m8slv"; + sha256 = "08076cmdx0g51yrkd7dlxlr45nflink3jhdiq7006ljc2pc3212q"; type = "gem"; }; - version = "0.11.0.0"; + version = "0.13.0"; }; tilt = { groups = ["default"]; @@ -2502,10 +2449,10 @@ platforms = []; source = { remotes = ["https://rubygems.org"]; - sha256 = "0z2n1qwad86zkcmmq883bw8rgidjsqjphrbqf1mwyfi5y22jhxfp"; + sha256 = "0hy3kbcb6nwydy312rhjm4b30yavmayszzzyjpfdv6p0s8d9mfvb"; type = "gem"; }; - version = "2.1.2"; + version = "2.1.3"; }; treetop = { dependencies = ["polyglot"]; @@ -2513,10 +2460,10 @@ platforms = []; source = { remotes = ["https://rubygems.org"]; - sha256 = "0g31pijhnv7z960sd09lckmw9h8rs3wmc8g4ihmppszxqm99zpv7"; + sha256 = "0697qz1akblf8r3wi0s2dsjh468hfsd57fb0mrp93z35y2ni6bhh"; type = "gem"; }; - version = "1.6.10"; + version = "1.6.11"; }; typhoeus = { dependencies = ["ethon"]; @@ -2524,10 +2471,10 @@ platforms = []; source = { remotes = ["https://rubygems.org"]; - sha256 = "0cni8b1idcp0dk8kybmxydadhfpaj3lbs99w5kjibv8bsmip2zi5"; + sha256 = "1m22yrkmbj81rzhlny81j427qdvz57yk5wbcf3km0nf3bl6qiygz"; type = "gem"; }; - version = "1.3.1"; + version = "1.4.0"; }; tzinfo = { dependencies = ["thread_safe"]; @@ -2535,10 +2482,10 @@ platforms = []; source = { remotes = ["https://rubygems.org"]; - sha256 = "04f18jdv6z3zn3va50rqq35nj3izjpb72fnf21ixm7vanq6nc4fp"; + sha256 = "0skr6ih9cr3pwp8l84f0z7fy3q9kiq8hw0sg3zqw0hpbbyj05743"; type = "gem"; }; - version = "1.2.6"; + version = "1.2.8"; }; unf = { dependencies = ["unf_ext"]; @@ -2556,20 +2503,20 @@ platforms = []; source = { remotes = ["https://rubygems.org"]; - sha256 = "1ll6w64ibh81qwvjx19h8nj7mngxgffg7aigjx11klvf5k2g4nxf"; + sha256 = "0wc47r23h063l8ysws8sy24gzh74mks81cak3lkzlrw4qkqb3sg4"; type = "gem"; }; - version = "0.0.7.6"; + version = "0.0.7.7"; }; unicode-display_width = { groups = ["default"]; platforms = []; source = { remotes = ["https://rubygems.org"]; - sha256 = "08kfiniak1pvg3gn5k6snpigzvhvhyg7slmm0s2qx5zkj62c1z2w"; + sha256 = "06i3id27s60141x6fdnjn5rar1cywdwy64ilc59cz937303q3mna"; type = "gem"; }; - version = "1.6.0"; + version = "1.7.0"; }; uuid4r = { groups = ["default"]; @@ -2581,15 +2528,36 @@ }; version = "0.2.0"; }; + websocket-driver = { + dependencies = ["websocket-extensions"]; + groups = ["default"]; + platforms = []; + source = { + remotes = ["https://rubygems.org"]; + sha256 = "1i3rs4kcj0jba8idxla3s6xd1xfln3k8b4cb1dik2lda3ifnp3dh"; + type = "gem"; + }; + version = "0.7.3"; + }; + websocket-extensions = { + groups = ["default"]; + platforms = []; + source = { + remotes = ["https://rubygems.org"]; + sha256 = "0hc2g9qps8lmhibl5baa91b4qx8wqw872rgwagml78ydj8qacsqw"; + type = "gem"; + }; + version = "0.1.5"; + }; whois = { groups = ["default"]; platforms = []; source = { remotes = ["https://rubygems.org"]; - sha256 = "177qbah62yhy2q7znlrs49jwabw7vpd9frv6hw6mm0bxj5fn7prg"; + sha256 = "0ch19amq0spj5dc240mv6s8hh245w7nis2h070qr3jm15r4jb21m"; type = "gem"; }; - version = "5.0.0"; + version = "5.0.1"; }; xcodeproj = { dependencies = ["CFPropertyList" "atomos" "claide" "colored2" "nanaimo"]; @@ -2597,10 +2565,10 @@ platforms = []; source = { remotes = ["https://rubygems.org"]; - sha256 = "1h9iba53mrb663qdqzpfbdwkwzqv7hndd0df71yr2kj2hzwjmkvb"; + sha256 = "1411j6sfnz0cx4fiw52f0yqx4bgcn8cmpgi3i5rwmmahayyjz2fn"; type = "gem"; }; - version = "1.14.0"; + version = "1.19.0"; }; xctasks = { dependencies = ["nokogiri" "rake"]; @@ -2618,10 +2586,20 @@ platforms = []; source = { remotes = ["https://rubygems.org"]; - sha256 = "0rxqwry3h2hjz069f0kfr140wgx1khgljnqf112dk5x9rm4l0xny"; + sha256 = "126m49mvh4lbvlvrprq7xj2vjixbq3xqr8dwr089vadvs0rkn4rd"; type = "gem"; }; - version = "0.9.20"; + version = "0.9.25"; + }; + zeitwerk = { + groups = ["default"]; + platforms = []; + source = { + remotes = ["https://rubygems.org"]; + sha256 = "1746czsjarixq0x05f7p3hpzi38ldg6wxnxxw74kbjzh1sdjgmpl"; + type = "gem"; + }; + version = "2.4.2"; }; ZenTest = { groups = ["default"]; From c56fbe4e095ee71e557b56993c591088bc3d2118 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rg=20Thalheim?= Date: Tue, 8 Dec 2020 12:10:47 +0100 Subject: [PATCH 22/28] buildFhsUserenv: don't downgrade root user --- .../build-fhs-userenv/chrootenv/chrootenv.c | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/pkgs/build-support/build-fhs-userenv/chrootenv/chrootenv.c b/pkgs/build-support/build-fhs-userenv/chrootenv/chrootenv.c index dcb2e97aa93..a438b80e182 100644 --- a/pkgs/build-support/build-fhs-userenv/chrootenv/chrootenv.c +++ b/pkgs/build-support/build-fhs-userenv/chrootenv/chrootenv.c @@ -43,6 +43,7 @@ const gchar *create_tmpdir() { void pivot_host(const gchar *guest) { g_autofree gchar *point = g_build_filename(guest, "host", NULL); fail_if(g_mkdir(point, 0755)); + fail_if(mount(0, "/", 0, MS_PRIVATE | MS_REC, 0)); fail_if(pivot_root(guest, point)); } @@ -56,6 +57,7 @@ void bind_mount_item(const gchar *host, const gchar *guest, const gchar *name) { void bind(const gchar *host, const gchar *guest) { mount_tmpfs(guest); + pivot_host(guest); g_autofree gchar *host_dir = g_build_filename("/host", host, NULL); @@ -105,7 +107,11 @@ int main(gint argc, gchar **argv) { uid_t uid = getuid(); gid_t gid = getgid(); - if (unshare(CLONE_NEWNS | CLONE_NEWUSER) < 0) { + int namespaces = CLONE_NEWNS; + if (uid != 0) { + namespaces |= CLONE_NEWUSER; + } + if (unshare(namespaces) < 0) { int unshare_errno = errno; g_message("Requires Linux version >= 3.19 built with CONFIG_USER_NS"); @@ -116,9 +122,11 @@ int main(gint argc, gchar **argv) { fail("unshare", unshare_errno); } - spit("/proc/self/setgroups", "deny"); - spit("/proc/self/uid_map", "%d %d 1", uid, uid); - spit("/proc/self/gid_map", "%d %d 1", gid, gid); + if (uid != 0) { + spit("/proc/self/setgroups", "deny"); + spit("/proc/self/uid_map", "%d %d 1", uid, uid); + spit("/proc/self/gid_map", "%d %d 1", gid, gid); + } // If there is a /host directory, assume this is nested chrootenv and use it as host instead. gboolean nested_host = g_file_test("/host", G_FILE_TEST_EXISTS | G_FILE_TEST_IS_DIR); From 330218e69abaec3377cfe6537827542610a18069 Mon Sep 17 00:00:00 2001 From: h0m1 Date: Tue, 19 Nov 2019 20:41:56 +0100 Subject: [PATCH 23/28] stage-1: create temporary secrets directory in /tmp and not in cwd --- nixos/modules/system/boot/stage-1.nix | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nixos/modules/system/boot/stage-1.nix b/nixos/modules/system/boot/stage-1.nix index 86bfde6349c..e133a357bb7 100644 --- a/nixos/modules/system/boot/stage-1.nix +++ b/nixos/modules/system/boot/stage-1.nix @@ -366,7 +366,7 @@ let } trap cleanup EXIT - tmp=$(mktemp -d initrd-secrets.XXXXXXXXXX) + tmp=$(mktemp -d ''${TMPDIR:-/tmp}/initrd-secrets.XXXXXXXXXX) ${lib.concatStringsSep "\n" (mapAttrsToList (dest: source: let source' = if source == null then dest else toString source; in From 1024571d35ac1d3329e8475c7b5e78c345230dab Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rg=20Thalheim?= Date: Mon, 7 Dec 2020 20:59:03 +0100 Subject: [PATCH 24/28] nixos/nscd: start in early boot Services that have dynamic users require nscd to resolve users via pam_systemd. Those services might not even create their own dynamic users itself i.e. iptables. To make sure nscd is always started when this is happening we move nscd to sysinit.target and make sure that it is always started before starting/reloading/restarting any other service. --- nixos/modules/services/system/nscd.nix | 41 +++++++++++-------- .../activation/switch-to-configuration.pl | 11 ++++- 2 files changed, 35 insertions(+), 17 deletions(-) diff --git a/nixos/modules/services/system/nscd.nix b/nixos/modules/services/system/nscd.nix index d720f254b81..43b05c5b14d 100644 --- a/nixos/modules/services/system/nscd.nix +++ b/nixos/modules/services/system/nscd.nix @@ -50,10 +50,20 @@ in systemd.services.nscd = { description = "Name Service Cache Daemon"; - wantedBy = [ "nss-lookup.target" "nss-user-lookup.target" ]; - environment = { LD_LIBRARY_PATH = nssModulesPath; }; + # We need system users to be resolveable in late-boot. nscd is the proxy between + # nss-modules in NixOS and thus if you have nss-modules providing system users + # (e.g. when using DynamicUser) then nscd needs to be available before late-boot is ready + # We add a dependency of sysinit.target to nscd to ensure + # these units are started after nscd is fully started. + unitConfig.DefaultDependencies = false; + wantedBy = [ "sysinit.target" ]; + before = [ "sysinit.target" "shutdown.target" ]; + conflicts = [ "shutdown.target" ]; + wants = [ "local-fs.target" ]; + after = [ "local-fs.target" ]; + restartTriggers = [ config.environment.etc.hosts.source config.environment.etc."nsswitch.conf".source @@ -66,20 +76,19 @@ in # privileges after all the NSS modules have read their configuration # files. So prefix the ExecStart command with "!" to prevent systemd # from dropping privileges early. See ExecStart in systemd.service(5). - serviceConfig = - { ExecStart = "!@${nscd}/sbin/nscd nscd"; - Type = "forking"; - DynamicUser = true; - RuntimeDirectory = "nscd"; - PIDFile = "/run/nscd/nscd.pid"; - Restart = "always"; - ExecReload = - [ "${nscd}/sbin/nscd --invalidate passwd" - "${nscd}/sbin/nscd --invalidate group" - "${nscd}/sbin/nscd --invalidate hosts" - ]; - }; + serviceConfig = { + ExecStart = "!@${nscd}/sbin/nscd nscd"; + Type = "forking"; + DynamicUser = true; + RuntimeDirectory = "nscd"; + PIDFile = "/run/nscd/nscd.pid"; + Restart = "always"; + ExecReload = [ + "${nscd}/sbin/nscd --invalidate passwd" + "${nscd}/sbin/nscd --invalidate group" + "${nscd}/sbin/nscd --invalidate hosts" + ]; + }; }; - }; } diff --git a/nixos/modules/system/activation/switch-to-configuration.pl b/nixos/modules/system/activation/switch-to-configuration.pl index b82d69b3bb8..c774be2ec54 100644 --- a/nixos/modules/system/activation/switch-to-configuration.pl +++ b/nixos/modules/system/activation/switch-to-configuration.pl @@ -346,10 +346,11 @@ sub filterUnits { return @res; } +my $startNscd = delete $unitsToStart{"nscd.service"}; + my @unitsToStopFiltered = filterUnits(\%unitsToStop); my @unitsToStartFiltered = filterUnits(\%unitsToStart); - # Show dry-run actions. if ($action eq "dry-activate") { print STDERR "would stop the following units: ", join(", ", @unitsToStopFiltered), "\n" @@ -359,6 +360,7 @@ if ($action eq "dry-activate") { print STDERR "would restart systemd\n" if $restartSystemd; print STDERR "would restart the following units: ", join(", ", sort(keys %unitsToRestart)), "\n" if scalar(keys %unitsToRestart) > 0; + print STDERR "would start nscd\n" if $startNscd; print STDERR "would start the following units: ", join(", ", @unitsToStartFiltered), "\n" if scalar @unitsToStartFiltered; print STDERR "would reload the following units: ", join(", ", sort(keys %unitsToReload)), "\n" @@ -418,6 +420,13 @@ close $listActiveUsers; print STDERR "setting up tmpfiles\n"; system("@systemd@/bin/systemd-tmpfiles", "--create", "--remove", "--exclude-prefix=/dev") == 0 or $res = 3; +# We need to start nscd before any other service, since they might need +# to resolve users/groups only exposed by nss modules (i.e. DynamicUser via nss_systemd) +if ($startNscd) { + print STDERR "starting nscd\n"; + system("@systemd@/bin/systemctl", "start", "nscd.service") == 0 or $res = 4; +} + # Reload units that need it. This includes remounting changed mount # units. if (scalar(keys %unitsToReload) > 0) { From 54f104bf25cefd2bc3c132e36d8b536232526c7d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rg=20Thalheim?= Date: Thu, 17 Dec 2020 16:57:52 +0100 Subject: [PATCH 25/28] python3.pkgs.keystone: init at 0.9.2 This is used in a couple of reverse engineering tools i.e. [gef](https://github.com/hugsy/gef). --- .../python-modules/keystone/default.nix | 16 ++++++++++++++++ pkgs/top-level/python-packages.nix | 4 ++++ 2 files changed, 20 insertions(+) create mode 100644 pkgs/development/python-modules/keystone/default.nix diff --git a/pkgs/development/python-modules/keystone/default.nix b/pkgs/development/python-modules/keystone/default.nix new file mode 100644 index 00000000000..c98af6ea4d7 --- /dev/null +++ b/pkgs/development/python-modules/keystone/default.nix @@ -0,0 +1,16 @@ +{ lib +, buildPythonPackage +, keystone +}: + +buildPythonPackage rec { + inherit (keystone) pname src version buildInputs nativeBuildInputs; + + dontUseCmakeConfigure = 1; + preBuild = "cd bindings/python"; + + meta = with lib; { + inherit (keystone.meta) description license homepage; + maintainers = [ maintainers.mic92 ]; + }; +} diff --git a/pkgs/top-level/python-packages.nix b/pkgs/top-level/python-packages.nix index 46ebc85dd00..0e0e075171e 100644 --- a/pkgs/top-level/python-packages.nix +++ b/pkgs/top-level/python-packages.nix @@ -3308,6 +3308,10 @@ in { keyrings-alt = callPackage ../development/python-modules/keyrings-alt { }; + keystone = callPackage ../development/python-modules/keystone { + inherit (pkgs) keystone; + }; + keyutils = callPackage ../development/python-modules/keyutils { inherit (pkgs) keyutils; }; kicad = disabledIf isPy27 (toPythonModule (pkgs.kicad.override { python3 = python; }).src); From 35c4d1d0795ed02cec20849765a00db1475ff241 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rg=20Thalheim?= Date: Thu, 17 Dec 2020 21:51:10 +0100 Subject: [PATCH 26/28] texlive: use python3 by default There is one python helper script still written for: Utility for writing Bengali in Rapid Roman Format. But this one does not seem super relevant --- pkgs/tools/typesetting/tex/texlive/bin.nix | 6 +++--- pkgs/tools/typesetting/tex/texlive/combine.nix | 2 +- pkgs/tools/typesetting/tex/texlive/default.nix | 6 +++--- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/pkgs/tools/typesetting/tex/texlive/bin.nix b/pkgs/tools/typesetting/tex/texlive/bin.nix index 030ac1b43aa..4df486a2511 100644 --- a/pkgs/tools/typesetting/tex/texlive/bin.nix +++ b/pkgs/tools/typesetting/tex/texlive/bin.nix @@ -2,7 +2,7 @@ , texlive , zlib, libiconv, libpng, libX11 , freetype, gd, libXaw, icu, ghostscript, libXpm, libXmu, libXext -, perl, perlPackages, python2Packages, pkgconfig +, perl, perlPackages, python3Packages, pkgconfig , poppler, libpaper, graphite2, zziplib, harfbuzz, potrace, gmp, mpfr , brotli, cairo, pixman, xorg, clisp, biber, woff2, xxHash , makeWrapper, shortenPerlShebang @@ -321,13 +321,13 @@ latexindent = perlPackages.buildPerlPackage rec { }; -pygmentex = python2Packages.buildPythonApplication rec { +pygmentex = python3Packages.buildPythonApplication rec { pname = "pygmentex"; inherit (src) version; src = stdenv.lib.head (builtins.filter (p: p.tlType == "run") texlive.pygmentex.pkgs); - propagatedBuildInputs = with python2Packages; [ pygments chardet ]; + propagatedBuildInputs = with python3Packages; [ pygments chardet ]; dontBuild = true; diff --git a/pkgs/tools/typesetting/tex/texlive/combine.nix b/pkgs/tools/typesetting/tex/texlive/combine.nix index 0625fe16090..33633433575 100644 --- a/pkgs/tools/typesetting/tex/texlive/combine.nix +++ b/pkgs/tools/typesetting/tex/texlive/combine.nix @@ -27,7 +27,7 @@ let [ "de-macro" "pythontex" "dviasm" "texliveonfly" ]; pkgNeedsRuby = pkg: pkg.tlType == "run" && pkg.pname == "match-parens"; extraInputs = - lib.optional (lib.any pkgNeedsPython splitBin.wrong) python + lib.optional (lib.any pkgNeedsPython splitBin.wrong) python3 ++ lib.optional (lib.any pkgNeedsRuby splitBin.wrong) ruby; }; diff --git a/pkgs/tools/typesetting/tex/texlive/default.nix b/pkgs/tools/typesetting/tex/texlive/default.nix index c2e6399ab86..0c7dadc150b 100644 --- a/pkgs/tools/typesetting/tex/texlive/default.nix +++ b/pkgs/tools/typesetting/tex/texlive/default.nix @@ -4,7 +4,7 @@ */ { stdenv, lib, fetchurl, runCommand, writeText, buildEnv , callPackage, ghostscriptX, harfbuzz, poppler_min -, makeWrapper, python, ruby, perl +, makeWrapper, python3, ruby, perl , useFixedHashes ? true , recurseIntoAttrs }: @@ -25,7 +25,7 @@ let # function for creating a working environment from a set of TL packages combine = import ./combine.nix { inherit bin combinePkgs buildEnv lib makeWrapper writeText - stdenv python ruby perl; + stdenv python3 ruby perl; ghostscript = ghostscriptX; # could be without X, probably, but we use X above }; @@ -110,7 +110,7 @@ let #"ftp://tug.org/texlive/historic/2019/tlnet-final/archive" # Daily snapshots hosted by one of the texlive release managers - https://texlive.info/tlnet-archive/2020/10/09/tlnet/archive + "https://texlive.info/tlnet-archive/2020/10/09/tlnet/archive" ]; src = fetchurl { inherit urls sha512; }; From 88665763001b1e3b2a7bce8b4c89f2d94c5fead1 Mon Sep 17 00:00:00 2001 From: Julien Moutinho Date: Fri, 11 Sep 2020 07:46:59 +0200 Subject: [PATCH 27/28] nixos/tor: improve type-checking and hardening Fixes #77395. Fixes #82790. --- nixos/modules/services/networking/privoxy.nix | 7 +- nixos/modules/services/security/tor.nix | 1392 ++++++++++------- nixos/tests/tor.nix | 2 +- pkgs/tools/security/tor/default.nix | 16 + 4 files changed, 851 insertions(+), 566 deletions(-) diff --git a/nixos/modules/services/networking/privoxy.nix b/nixos/modules/services/networking/privoxy.nix index e3b34cb0c61..7caae328203 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 1cceee065b1..ececb633983 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 torrc manual. + ''; + 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}:" + + toString v.port + + optionalString (v ? "flags") (" " + concatStringsSep " " v.flags) + else if k == "ServerTransportPlugin" then + optionalString (v.transports != []) "${concatStringsSep "," v.transports} exec ${v.exec}" + else if k == "HidServAuth" then + concatMapStringsSep "\n${k} " (settings: settings.onion + " " settings.auth) v + else generators.mkValueStringDefault {} v; + genTorrc = settings: + generators.toKeyValue { + listsAsDuplicateKeys = true; + mkKeyValue = k: generators.mkKeyValueDefault { mkValueString = mkValueString k; } " " k; + } + (lib.mapAttrs (k: v: + # Not necesssary, but prettier rendering + if elem k [ "AutomapHostsSuffixes" "DirPolicy" "ExitPolicy" "SocksPolicy" ] + && v != [] + then concatStringsSep "," v + else v) + (lib.filterAttrs (k: v: !(v == null || v == "")) + settings)); + torrc = pkgs.writeText "torrc" ( + genTorrc cfg.settings + + concatStrings (mapAttrsToList (name: onion: + "HiddenServiceDir ${onion.path}\n" + + genTorrc onion.settings) cfg.relay.onionServices) + ); in { imports = [ - (mkRemovedOptionModule [ "services" "tor" "client" "privoxy" "enable" ] '' - Use services.privoxy.enable and services.privoxy.enableTor instead. - '') - (mkRenamedOptionModule [ "services" "tor" "relay" "portSpec" ] [ "services" "tor" "relay" "port" ]) + (mkRenamedOptionModule [ "services" "tor" "client" "dns" "automapHostsSuffixes" ] [ "services" "tor" "settings" "AutomapHostsSuffixes" ]) + (mkRemovedOptionModule [ "services" "tor" "client" "dns" "isolationOptions" ] "Use services.tor.settings.DNSPort instead.") + (mkRemovedOptionModule [ "services" "tor" "client" "dns" "listenAddress" ] "Use services.tor.settings.DNSPort instead.") + (mkRemovedOptionModule [ "services" "tor" "client" "privoxy" "enable" ] "Use services.privoxy.enable and services.privoxy.enableTor instead.") + (mkRemovedOptionModule [ "services" "tor" "client" "socksIsolationOptions" ] "Use services.tor.settings.SOCKSPort instead.") + (mkRemovedOptionModule [ "services" "tor" "client" "socksListenAddressFaster" ] "Use services.tor.settings.SOCKSPort instead.") + (mkRenamedOptionModule [ "services" "tor" "client" "socksPolicy" ] [ "services" "tor" "settings" "SocksPolicy" ]) + (mkRemovedOptionModule [ "services" "tor" "client" "transparentProxy" "isolationOptions" ] "Use services.tor.settings.TransPort instead.") + (mkRemovedOptionModule [ "services" "tor" "client" "transparentProxy" "listenAddress" ] "Use services.tor.settings.TransPort instead.") + (mkRenamedOptionModule [ "services" "tor" "controlPort" ] [ "services" "tor" "settings" "ControlPort" ]) + (mkRemovedOptionModule [ "services" "tor" "extraConfig" ] "Plese use services.tor.settings instead.") + (mkRenamedOptionModule [ "services" "tor" "hiddenServices" ] [ "services" "tor" "relay" "onionServices" ]) + (mkRenamedOptionModule [ "services" "tor" "relay" "accountingMax" ] [ "services" "tor" "settings" "AccountingMax" ]) + (mkRenamedOptionModule [ "services" "tor" "relay" "accountingStart" ] [ "services" "tor" "settings" "AccountingStart" ]) + (mkRenamedOptionModule [ "services" "tor" "relay" "address" ] [ "services" "tor" "settings" "Address" ]) + (mkRenamedOptionModule [ "services" "tor" "relay" "bandwidthBurst" ] [ "services" "tor" "settings" "BandwidthBurst" ]) + (mkRenamedOptionModule [ "services" "tor" "relay" "bandwidthRate" ] [ "services" "tor" "settings" "BandwidthRate" ]) + (mkRenamedOptionModule [ "services" "tor" "relay" "bridgeTransports" ] [ "services" "tor" "settings" "ServerTransportPlugin" "transports" ]) + (mkRenamedOptionModule [ "services" "tor" "relay" "contactInfo" ] [ "services" "tor" "settings" "ContactInfo" ]) + (mkRenamedOptionModule [ "services" "tor" "relay" "exitPolicy" ] [ "services" "tor" "settings" "ExitPolicy" ]) (mkRemovedOptionModule [ "services" "tor" "relay" "isBridge" ] "Use services.tor.relay.role instead.") (mkRemovedOptionModule [ "services" "tor" "relay" "isExit" ] "Use services.tor.relay.role instead.") + (mkRenamedOptionModule [ "services" "tor" "relay" "nickname" ] [ "services" "tor" "settings" "Nickname" ]) + (mkRenamedOptionModule [ "services" "tor" "relay" "port" ] [ "services" "tor" "settings" "ORPort" ]) + (mkRenamedOptionModule [ "services" "tor" "relay" "portSpec" ] [ "services" "tor" "settings" "ORPort" ]) ]; options = { services.tor = { - enable = mkOption { - type = types.bool; - default = false; - description = '' - Enable the Tor daemon. By default, the daemon is run without - relay, exit, bridge or client connectivity. - ''; - }; + enable = mkEnableOption ''Tor daemon. + By default, the daemon is run without + relay, exit, bridge or client connectivity''; + + openFirewall = mkEnableOption "opening of the relay port(s) in the firewall"; package = mkOption { type = types.package; default = pkgs.tor; defaultText = "pkgs.tor"; example = literalExample "pkgs.tor"; - description = '' - Tor package to use - ''; + description = "Tor package to use."; }; - enableGeoIP = mkOption { - type = types.bool; - default = true; - description = '' - Whenever to configure Tor daemon to use GeoIP databases. + enableGeoIP = mkEnableOption ''use of GeoIP databases. + Disabling this will disable by-country statistics for bridges and relays + and some client and third-party software functionality'' // { default = true; }; - Disabling this will disable by-country statistics for - bridges and relays and some client and third-party software - functionality. - ''; - }; - - extraConfig = mkOption { - type = types.lines; - default = ""; - description = '' - Extra configuration. Contents will be added verbatim to the - configuration file at the end. - ''; - }; - - controlPort = mkOption { - type = types.nullOr (types.either types.int types.str); - default = null; - example = 9051; - description = '' - If set, Tor will accept connections on the specified port - and allow them to control the tor process. - ''; - }; - - controlSocket = { - enable = mkOption { - type = types.bool; - default = false; - description = '' - Whether to enable Tor control socket. Control socket is created - in ${torRunDirectory}/control - ''; - }; - }; + controlSocket.enable = mkEnableOption ''control socket, + created in ${runDir}/control''; client = { - enable = mkOption { - type = types.bool; - default = false; - description = '' - Whether to enable Tor daemon to route application - connections. You might want to disable this if you plan - running a dedicated Tor relay. - ''; - }; + enable = mkEnableOption ''the routing of application connections. + You might want to disable this if you plan running a dedicated Tor relay''; + + transparentProxy.enable = mkEnableOption "transparent proxy"; + dns.enable = mkEnableOption "DNS resolver"; socksListenAddress = mkOption { - type = types.str; - default = "127.0.0.1:9050"; - example = "192.168.0.1:9100"; + type = optionSOCKSPort false; + default = {addr = "127.0.0.1"; port = 9050; IsolateDestAddr = true;}; + example = {addr = "192.168.0.1"; port = 9090; IsolateDestAddr = true;}; description = '' Bind to this address to listen for connections from - Socks-speaking applications. Provides strong circuit - isolation, separate circuit per IP address. + Socks-speaking applications. ''; }; - socksListenAddressFaster = mkOption { - type = types.str; - default = "127.0.0.1:9063"; - example = "192.168.0.1:9101"; - description = '' - Bind to this address to listen for connections from - Socks-speaking applications. Same as - but uses weaker - circuit isolation to provide performance suitable for a - web browser. - ''; - }; - - socksPolicy = mkOption { - type = types.nullOr types.str; - default = null; - example = "accept 192.168.0.0/16, reject *"; - description = '' - Entry policies to allow/deny SOCKS requests based on IP - address. First entry that matches wins. If no SocksPolicy - is set, we accept all (and only) requests from - . - ''; - }; - - socksIsolationOptions = mkOption (isolationOptions // { - default = ["IsolateDestAddr"]; - }); - - transparentProxy = { - enable = mkOption { - type = types.bool; - default = false; - description = "Whether to enable tor transparent proxy"; - }; - - listenAddress = mkOption { - type = types.str; - default = "127.0.0.1:9040"; - example = "192.168.0.1:9040"; - description = '' - Bind transparent proxy to this address. - ''; - }; - - isolationOptions = mkOption isolationOptions; - }; - - dns = { - enable = mkOption { - type = types.bool; - default = false; - description = "Whether to enable tor dns resolver"; - }; - - listenAddress = mkOption { - type = types.str; - default = "127.0.0.1:9053"; - example = "192.168.0.1:9053"; - description = '' - Bind tor dns to this address. - ''; - }; - - isolationOptions = mkOption isolationOptions; - - automapHostsSuffixes = mkOption { - type = types.listOf types.str; - default = [".onion" ".exit"]; - example = [".onion"]; - description = "List of suffixes to use with automapHostsOnResolve"; + onionServices = mkOption { + description = descriptionGeneric "HiddenServiceDir"; + default = {}; + example = { + "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" = { + clientAuthorizations = ["/run/keys/tor/alice.prv.x25519"]; + }; }; + type = types.attrsOf (types.submodule ({name, config, ...}: { + options.clientAuthorizations = mkOption { + description = '' + Clients' authorizations for a v3 hidden service, + as a list of files containing each one private key, in the format: + descriptor:x25519:<base32-private-key> + '' + descriptionGeneric "_client_authorization"; + type = with types; listOf path; + default = []; + example = ["/run/keys/tor/alice.prv.x25519"]; + }; + })); }; }; relay = { - enable = mkOption { - type = types.bool; - default = false; - description = '' - Whether to enable relaying TOR traffic for others. + enable = mkEnableOption ''relaying of Tor traffic for others. - See - for details. + See + for details. - Setting this to true requires setting - - and - - options. - ''; - }; + Setting this to true requires setting + + and + + options''; role = mkOption { type = types.enum [ "exit" "relay" "bridge" "private-bridge" ]; @@ -310,13 +313,13 @@ in Running an exit relay may expose you to abuse complaints. See - + for more info. You can specify which services Tor users may access via - your exit relay using option. + your exit relay using option. @@ -369,15 +372,14 @@ in WARNING: THE FOLLOWING PARAGRAPH IS NOT LEGAL ADVICE. - Consult with your lawer when in doubt. + Consult with your lawyer when in doubt. This role should be safe to use in most situations (unless the act of forwarding traffic for others is a punishable offence under your local laws, which - would be pretty insane as it would make ISP - illegal). + would be pretty insane as it would make ISP illegal). @@ -404,7 +406,7 @@ in Use this if you want to run a private bridge, for - example because you'll give out your bridge address + example because you'll give out your bridge addr manually to your friends. @@ -426,269 +428,393 @@ in ''; }; - bridgeTransports = mkOption { - type = types.listOf types.str; - default = ["obfs4"]; - example = ["obfs2" "obfs3" "obfs4" "scramblesuit"]; - description = "List of pluggable transports"; - }; - - nickname = mkOption { - type = types.str; - default = "anonymous"; - description = '' - A unique handle for your TOR relay. - ''; - }; - - contactInfo = mkOption { - type = types.nullOr types.str; - default = null; - example = "admin@relay.com"; - description = '' - Contact information for the relay owner (e.g. a mail - address and GPG key ID). - ''; - }; - - accountingMax = mkOption { - type = types.nullOr types.str; - default = null; - example = "450 GBytes"; - description = '' - Specify maximum bandwidth allowed during an accounting period. This - allows you to limit overall tor bandwidth over some time period. - See the AccountingMax option by looking at the - tor manual tor - 1 for more. - - Note this limit applies individually to upload and - download; if you specify "500 GBytes" - here, then you may transfer up to 1 TBytes of overall - bandwidth (500 GB upload, 500 GB download). - ''; - }; - - accountingStart = mkOption { - type = types.nullOr types.str; - default = null; - example = "month 1 1:00"; - description = '' - Specify length of an accounting period. This allows you to limit - overall tor bandwidth over some time period. See the - AccountingStart option by looking at the tor - manual tor - 1 for more. - ''; - }; - - bandwidthRate = mkOption { - type = types.nullOr types.int; - default = null; - example = 100; - description = '' - Specify this to limit the bandwidth usage of relayed (server) - traffic. Your own traffic is still unthrottled. Units: bytes/second. - ''; - }; - - bandwidthBurst = mkOption { - type = types.nullOr types.int; - default = cfg.relay.bandwidthRate; - example = 200; - description = '' - Specify this to allow bursts of the bandwidth usage of relayed (server) - traffic. The average usage will still be as specified in relayBandwidthRate. - Your own traffic is still unthrottled. Units: bytes/second. - ''; - }; - - address = mkOption { - type = types.nullOr types.str; - default = null; - example = "noname.example.com"; - description = '' - The IP address or full DNS name for advertised address of your relay. - Leave unset and Tor will guess. - ''; - }; - - port = mkOption { - type = types.either types.int types.str; - example = 143; - description = '' - What port to advertise for Tor connections. This corresponds to the - ORPort section in the Tor manual; see - tor - 1 for more details. - - At a minimum, you should just specify the port for the - relay to listen on; a common one like 143, 22, 80, or 443 - to help Tor users who may have very restrictive port-based - firewalls. - ''; - }; - - exitPolicy = mkOption { - type = types.nullOr types.str; - default = null; - example = "accept *:6660-6667,reject *:*"; - description = '' - A comma-separated list of exit policies. They're - considered first to last, and the first match wins. If you - want to _replace_ the default exit policy, end this with - either a reject *:* or an accept *:*. Otherwise, you're - _augmenting_ (prepending to) the default exit policy. - Leave commented to just use the default, which is - available in the man page or at - . - - Look at - - for issues you might encounter if you use the default - exit policy. - - If certain IPs and ports are blocked externally, e.g. by - your firewall, you should update your exit policy to - reflect this -- otherwise Tor users will be told that - those destinations are down. - ''; + onionServices = mkOption { + description = descriptionGeneric "HiddenServiceDir"; + default = {}; + example = { + "example.org/www" = { + map = [ 80 ]; + authorizedClients = [ + "descriptor:x25519:XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX" + ]; + }; + }; + type = types.attrsOf (types.submodule ({name, config, ...}: { + options.path = mkOption { + type = types.path; + description = '' + Path where to store the data files of the hidden service. + If the is null + this defaults to ${stateDir}/onion/$onion, + otherwise to ${runDir}/onion/$onion. + ''; + }; + options.secretKey = mkOption { + type = with types; nullOr path; + default = null; + example = "/run/keys/tor/onion/expyuzz4wqqyqhjn/hs_ed25519_secret_key"; + description = '' + Secret key of the onion service. + If null, Tor reuses any preexisting secret key (in ) + or generates a new one. + The associated public key and hostname are deterministically regenerated + from this file if they do not exist. + ''; + }; + options.authorizeClient = mkOption { + description = descriptionGeneric "HiddenServiceAuthorizeClient"; + default = null; + type = types.nullOr (types.submodule ({...}: { + options = { + authType = mkOption { + type = types.enum [ "basic" "stealth" ]; + description = '' + Either "basic" for a general-purpose authorization protocol + or "stealth" for a less scalable protocol + that also hides service activity from unauthorized clients. + ''; + }; + clientNames = mkOption { + type = with types; nonEmptyListOf (strMatching "[A-Za-z0-9+-_]+"); + description = '' + Only clients that are listed here are authorized to access the hidden service. + Generated authorization data can be found in ${stateDir}/onion/$name/hostname. + Clients need to put this authorization data in their configuration file using + . + ''; + }; + }; + })); + }; + options.authorizedClients = mkOption { + description = '' + Authorized clients for a v3 hidden service, + as a list of public key, in the format: + descriptor:x25519:<base32-public-key> + '' + descriptionGeneric "_client_authorization"; + type = with types; listOf str; + default = []; + example = ["descriptor:x25519:XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"]; + }; + options.map = mkOption { + description = descriptionGeneric "HiddenServicePort"; + type = with types; listOf (oneOf [ + port (submodule ({...}: { + options = { + port = optionPort; + target = mkOption { + default = null; + type = nullOr (submodule ({...}: { + options = { + unix = optionUnix; + addr = optionAddress; + port = optionPort; + }; + })); + }; + }; + })) + ]); + apply = map (v: if isInt v then {port=v; target=null;} else v); + }; + options.version = mkOption { + description = descriptionGeneric "HiddenServiceVersion"; + type = with types; nullOr (enum [2 3]); + default = null; + }; + options.settings = mkOption { + description = '' + Settings of the onion service. + '' + descriptionGeneric "_hidden_service_options"; + default = {}; + type = types.submodule { + freeformType = with types; + (attrsOf (nullOr (oneOf [str int bool (listOf str)]))) // { + description = "settings option"; + }; + options.HiddenServiceAllowUnknownPorts = optionBool "HiddenServiceAllowUnknownPorts"; + options.HiddenServiceDirGroupReadable = optionBool "HiddenServiceDirGroupReadable"; + options.HiddenServiceExportCircuitID = mkOption { + description = descriptionGeneric "HiddenServiceExportCircuitID"; + type = with types; nullOr (enum ["haproxy"]); + default = null; + }; + options.HiddenServiceMaxStreams = mkOption { + description = descriptionGeneric "HiddenServiceMaxStreams"; + type = with types; nullOr (ints.between 0 65535); + default = null; + }; + options.HiddenServiceMaxStreamsCloseCircuit = optionBool "HiddenServiceMaxStreamsCloseCircuit"; + options.HiddenServiceNumIntroductionPoints = mkOption { + description = descriptionGeneric "HiddenServiceNumIntroductionPoints"; + type = with types; nullOr (ints.between 0 20); + default = null; + }; + options.HiddenServiceSingleHopMode = optionBool "HiddenServiceSingleHopMode"; + options.RendPostPeriod = optionString "RendPostPeriod"; + }; + }; + config = { + path = mkDefault ((if config.secretKey == null then stateDir else runDir) + "/onion/${name}"); + settings.HiddenServiceVersion = config.version; + settings.HiddenServiceAuthorizeClient = + if config.authorizeClient != null then + config.authorizeClient.authType + " " + + concatStringsSep "," config.authorizeClient.clientNames + else null; + settings.HiddenServicePort = map (p: mkValueString "" p.port + " " + mkValueString "" p.target) config.map; + }; + })); }; }; - hiddenServices = mkOption { + settings = mkOption { description = '' - A set of static hidden services that terminate their Tor - circuits at this node. - - Every element in this set declares a virtual onion host. - - You can specify your onion address by putting corresponding - private key to an appropriate place in ${torDirectory}. - - For services without private keys in ${torDirectory} Tor - daemon will generate random key pairs (which implies random - onion addresses) on restart. The latter could take a while, - please be patient. - - - Hidden services can be useful even if you don't intend to - actually hide them, since they can - also be seen as a kind of NAT traversal mechanism. - - E.g. the example will make your sshd, whatever runs on - "8080" and your mail server available from anywhere where - the Tor network is available (which, with the help from - bridges, is pretty much everywhere), even if both client - and server machines are behind NAT you have no control - over. - + See torrc manual + for documentation. ''; default = {}; - example = literalExample '' - { "my-hidden-service-example".map = [ - { port = 22; } # map ssh port to this machine's ssh - { port = 80; toPort = 8080; } # map http port to whatever runs on 8080 - { port = "sip"; toHost = "mail.example.com"; toPort = "imap"; } # because we can - ]; - } - ''; - type = types.attrsOf (types.submodule ({name, ...}: { - options = { - - name = mkOption { - type = types.str; - description = '' - Name of this tor hidden service. - - This is purely descriptive. - - After restarting Tor daemon you should be able to - find your .onion address in - ${torDirectory}/onion/$name/hostname. - ''; - }; - - map = mkOption { - default = []; - description = "Port mapping for this hidden service."; - type = types.listOf (types.submodule ({config, ...}: { - options = { - - port = mkOption { - type = types.either types.int types.str; - example = 80; - description = '' - Hidden service port to "bind to". - ''; - }; - - destination = mkOption { - internal = true; - type = types.str; - description = "Forward these connections where?"; - }; - - toHost = mkOption { - type = types.str; - default = "127.0.0.1"; - description = "Mapping destination host."; - }; - - toPort = mkOption { - type = types.either types.int types.str; - example = 8080; - description = "Mapping destination port."; - }; - - }; - - config = { - toPort = mkDefault config.port; - destination = mkDefault "${config.toHost}:${toString config.toPort}"; - }; - })); - }; - - authorizeClient = mkOption { - default = null; - description = "If configured, the hidden service is accessible for authorized clients only."; - type = types.nullOr (types.submodule ({...}: { - - options = { - - authType = mkOption { - type = types.enum [ "basic" "stealth" ]; - description = '' - Either "basic" for a general-purpose authorization protocol - or "stealth" for a less scalable protocol - that also hides service activity from unauthorized clients. - ''; - }; - - clientNames = mkOption { - type = types.nonEmptyListOf (types.strMatching "[A-Za-z0-9+-_]+"); - description = '' - Only clients that are listed here are authorized to access the hidden service. - Generated authorization data can be found in ${torDirectory}/onion/$name/hostname. - Clients need to put this authorization data in their configuration file using HidServAuth. - ''; - }; - }; - })); - }; - - version = mkOption { - default = null; - description = "Rendezvous service descriptor version to publish for the hidden service. Currently, versions 2 and 3 are supported. (Default: 2)"; - type = types.nullOr (types.enum [ 2 3 ]); - }; + type = types.submodule { + freeformType = with types; + (attrsOf (nullOr (oneOf [str int bool (listOf str)]))) // { + description = "settings option"; + }; + options.Address = optionString "Address"; + options.AssumeReachable = optionBool "AssumeReachable"; + options.AccountingMax = optionBandwith "AccountingMax"; + options.AccountingStart = optionString "AccountingStart"; + options.AuthDirHasIPv6Connectivity = optionBool "AuthDirHasIPv6Connectivity"; + options.AuthDirListBadExits = optionBool "AuthDirListBadExits"; + options.AuthDirPinKeys = optionBool "AuthDirPinKeys"; + options.AuthDirSharedRandomness = optionBool "AuthDirSharedRandomness"; + options.AuthDirTestEd25519LinkKeys = optionBool "AuthDirTestEd25519LinkKeys"; + options.AuthoritativeDirectory = optionBool "AuthoritativeDirectory"; + options.AutomapHostsOnResolve = optionBool "AutomapHostsOnResolve"; + options.AutomapHostsSuffixes = optionStrings "AutomapHostsSuffixes" // { + default = [".onion" ".exit"]; + example = [".onion"]; }; - - config = { - name = mkDefault name; + options.BandwidthBurst = optionBandwith "BandwidthBurst"; + options.BandwidthRate = optionBandwith "BandwidthRate"; + options.BridgeAuthoritativeDir = optionBool "BridgeAuthoritativeDir"; + options.BridgeRecordUsageByCountry = optionBool "BridgeRecordUsageByCountry"; + options.BridgeRelay = optionBool "BridgeRelay" // { default = false; }; + options.CacheDirectory = optionPath "CacheDirectory"; + options.CacheDirectoryGroupReadable = optionBool "CacheDirectoryGroupReadable"; # default is null and like "auto" + options.CellStatistics = optionBool "CellStatistics"; + options.ClientAutoIPv6ORPort = optionBool "ClientAutoIPv6ORPort"; + options.ClientDNSRejectInternalAddresses = optionBool "ClientDNSRejectInternalAddresses"; + options.ClientOnionAuthDir = mkOption { + description = descriptionGeneric "ClientOnionAuthDir"; + default = null; + type = with types; nullOr path; }; - })); + options.ClientPreferIPv6DirPort = optionBool "ClientPreferIPv6DirPort"; # default is null and like "auto" + options.ClientPreferIPv6ORPort = optionBool "ClientPreferIPv6ORPort"; # default is null and like "auto" + options.ClientRejectInternalAddresses = optionBool "ClientRejectInternalAddresses"; + options.ClientUseIPv4 = optionBool "ClientUseIPv4"; + options.ClientUseIPv6 = optionBool "ClientUseIPv6"; + options.ConnDirectionStatistics = optionBool "ConnDirectionStatistics"; + options.ConstrainedSockets = optionBool "ConstrainedSockets"; + options.ContactInfo = optionString "ContactInfo"; + options.ControlPort = mkOption rec { + description = descriptionGeneric "ControlPort"; + default = []; + example = [{port = 9051;}]; + type = with types; oneOf [port (enum ["auto"]) (listOf (oneOf [ + port (enum ["auto"]) (submodule ({config, ...}: let + flags = ["GroupWritable" "RelaxDirModeCheck" "WorldWritable"]; + in { + options = { + unix = optionUnix; + flags = optionFlags; + addr = optionAddress; + port = optionPort; + } // genAttrs flags (name: mkOption { type = types.bool; default = false; }); + config = { + flags = filter (name: config.${name} == true) flags; + }; + })) + ]))]; + }; + options.ControlPortFileGroupReadable= optionBool "ControlPortFileGroupReadable"; + options.ControlPortWriteToFile = optionPath "ControlPortWriteToFile"; + options.ControlSocket = optionPath "ControlSocket"; + options.ControlSocketsGroupWritable = optionBool "ControlSocketsGroupWritable"; + options.CookieAuthFile = optionPath "CookieAuthFile"; + options.CookieAuthFileGroupReadable = optionBool "CookieAuthFileGroupReadable"; + options.CookieAuthentication = optionBool "CookieAuthentication"; + options.DataDirectory = optionPath "DataDirectory" // { default = stateDir; }; + options.DataDirectoryGroupReadable = optionBool "DataDirectoryGroupReadable"; + options.DirPortFrontPage = optionPath "DirPortFrontPage"; + options.DirAllowPrivateAddresses = optionBool "DirAllowPrivateAddresses"; + options.DormantCanceledByStartup = optionBool "DormantCanceledByStartup"; + options.DormantOnFirstStartup = optionBool "DormantOnFirstStartup"; + options.DormantTimeoutDisabledByIdleStreams = optionBool "DormantTimeoutDisabledByIdleStreams"; + options.DirCache = optionBool "DirCache"; + options.DirPolicy = mkOption { + description = descriptionGeneric "DirPolicy"; + type = with types; listOf str; + default = []; + example = ["accept *:*"]; + }; + options.DirPort = optionORPort "DirPort"; + options.DirReqStatistics = optionBool "DirReqStatistics"; + options.DisableAllSwap = optionBool "DisableAllSwap"; + options.DisableDebuggerAttachment = optionBool "DisableDebuggerAttachment"; + options.DisableNetwork = optionBool "DisableNetwork"; + options.DisableOOSCheck = optionBool "DisableOOSCheck"; + options.DNSPort = optionIsolablePorts "DNSPort"; + options.DoSCircuitCreationEnabled = optionBool "DoSCircuitCreationEnabled"; + options.DoSConnectionEnabled = optionBool "DoSConnectionEnabled"; # default is null and like "auto" + options.DoSRefuseSingleHopClientRendezvous = optionBool "DoSRefuseSingleHopClientRendezvous"; + options.DownloadExtraInfo = optionBool "DownloadExtraInfo"; + options.EnforceDistinctSubnets = optionBool "EnforceDistinctSubnets"; + options.EntryStatistics = optionBool "EntryStatistics"; + options.ExitPolicy = optionStrings "ExitPolicy" // { + default = ["reject *:*"]; + example = ["accept *:*"]; + }; + options.ExitPolicyRejectLocalInterfaces = optionBool "ExitPolicyRejectLocalInterfaces"; + options.ExitPolicyRejectPrivate = optionBool "ExitPolicyRejectPrivate"; + options.ExitPortStatistics = optionBool "ExitPortStatistics"; + options.ExitRelay = optionBool "ExitRelay"; # default is null and like "auto" + options.ExtORPort = mkOption { + description = descriptionGeneric "ExtORPort"; + default = null; + type = with types; nullOr (oneOf [ + port (enum ["auto"]) (submodule ({...}: { + options = { + addr = optionAddress; + port = optionPort; + }; + })) + ]); + apply = p: if isInt p || isString p then { port = p; } else p; + }; + options.ExtORPortCookieAuthFile = optionPath "ExtORPortCookieAuthFile"; + options.ExtORPortCookieAuthFileGroupReadable = optionBool "ExtORPortCookieAuthFileGroupReadable"; + options.ExtendAllowPrivateAddresses = optionBool "ExtendAllowPrivateAddresses"; + options.ExtraInfoStatistics = optionBool "ExtraInfoStatistics"; + options.FascistFirewall = optionBool "FascistFirewall"; + options.FetchDirInfoEarly = optionBool "FetchDirInfoEarly"; + options.FetchDirInfoExtraEarly = optionBool "FetchDirInfoExtraEarly"; + options.FetchHidServDescriptors = optionBool "FetchHidServDescriptors"; + options.FetchServerDescriptors = optionBool "FetchServerDescriptors"; + options.FetchUselessDescriptors = optionBool "FetchUselessDescriptors"; + options.ReachableAddresses = optionStrings "ReachableAddresses"; + options.ReachableDirAddresses = optionStrings "ReachableDirAddresses"; + options.ReachableORAddresses = optionStrings "ReachableORAddresses"; + options.GeoIPFile = optionPath "GeoIPFile"; + options.GeoIPv6File = optionPath "GeoIPv6File"; + options.GuardfractionFile = optionPath "GuardfractionFile"; + options.HidServAuth = mkOption { + description = descriptionGeneric "HidServAuth"; + default = []; + type = with types; listOf (oneOf [ + (submodule { + options = { + onion = mkOption { + type = strMatching "[a-z2-7]{16}(\\.onion)?"; + description = "Onion address."; + example = "xxxxxxxxxxxxxxxx.onion"; + }; + auth = mkOption { + type = strMatching "[A-Za-z0-9+/]{22}"; + description = "Authentication cookie."; + }; + }; + }) + ]); + }; + options.HiddenServiceNonAnonymousMode = optionBool "HiddenServiceNonAnonymousMode"; + options.HiddenServiceStatistics = optionBool "HiddenServiceStatistics"; + options.HSLayer2Nodes = optionStrings "HSLayer2Nodes"; + options.HSLayer3Nodes = optionStrings "HSLayer3Nodes"; + options.HTTPTunnelPort = optionIsolablePorts "HTTPTunnelPort"; + options.IPv6Exit = optionBool "IPv6Exit"; + options.KeyDirectory = optionPath "KeyDirectory"; + options.KeyDirectoryGroupReadable = optionBool "KeyDirectoryGroupReadable"; + options.LogMessageDomains = optionBool "LogMessageDomains"; + options.LongLivedPorts = optionPorts "LongLivedPorts"; + options.MainloopStats = optionBool "MainloopStats"; + options.MaxAdvertisedBandwidth = optionBandwith "MaxAdvertisedBandwidth"; + options.MaxCircuitDirtiness = optionInt "MaxCircuitDirtiness"; + options.MaxClientCircuitsPending = optionInt "MaxClientCircuitsPending"; + options.NATDPort = optionIsolablePorts "NATDPort"; + options.NewCircuitPeriod = optionInt "NewCircuitPeriod"; + options.Nickname = optionString "Nickname"; + options.ORPort = optionORPort "ORPort"; + options.OfflineMasterKey = optionBool "OfflineMasterKey"; + options.OptimisticData = optionBool "OptimisticData"; # default is null and like "auto" + options.PaddingStatistics = optionBool "PaddingStatistics"; + options.PerConnBWBurst = optionBandwith "PerConnBWBurst"; + options.PerConnBWRate = optionBandwith "PerConnBWRate"; + options.PidFile = optionPath "PidFile"; + options.ProtocolWarnings = optionBool "ProtocolWarnings"; + options.PublishHidServDescriptors = optionBool "PublishHidServDescriptors"; + options.PublishServerDescriptor = mkOption { + description = descriptionGeneric "PublishServerDescriptor"; + type = with types; nullOr (enum [false true 0 1 "0" "1" "v3" "bridge"]); + default = null; + }; + options.ReducedExitPolicy = optionBool "ReducedExitPolicy"; + options.RefuseUnknownExits = optionBool "RefuseUnknownExits"; # default is null and like "auto" + options.RejectPlaintextPorts = optionPorts "RejectPlaintextPorts"; + options.RelayBandwidthBurst = optionBandwith "RelayBandwidthBurst"; + options.RelayBandwidthRate = optionBandwith "RelayBandwidthRate"; + #options.RunAsDaemon + options.Sandbox = optionBool "Sandbox"; + options.ServerDNSAllowBrokenConfig = optionBool "ServerDNSAllowBrokenConfig"; + options.ServerDNSAllowNonRFC953Hostnames = optionBool "ServerDNSAllowNonRFC953Hostnames"; + options.ServerDNSDetectHijacking = optionBool "ServerDNSDetectHijacking"; + options.ServerDNSRandomizeCase = optionBool "ServerDNSRandomizeCase"; + options.ServerDNSResolvConfFile = optionPath "ServerDNSResolvConfFile"; + options.ServerDNSSearchDomains = optionBool "ServerDNSSearchDomains"; + options.ServerTransportPlugin = mkOption { + description = descriptionGeneric "ServerTransportPlugin"; + default = null; + type = with types; nullOr (submodule ({...}: { + options = { + transports = mkOption { + description = "List of pluggable transports."; + type = listOf str; + example = ["obfs2" "obfs3" "obfs4" "scramblesuit"]; + }; + exec = mkOption { + type = types.str; + description = "Command of pluggable transport."; + }; + }; + })); + }; + options.SocksPolicy = optionStrings "SocksPolicy" // { + example = ["accept *:*"]; + }; + options.SOCKSPort = mkOption { + description = descriptionGeneric "SOCKSPort"; + default = if cfg.settings.HiddenServiceNonAnonymousMode == true then [{port = 0;}] else []; + example = [{port = 9090;}]; + type = types.listOf (optionSOCKSPort true); + }; + options.TestingTorNetwork = optionBool "TestingTorNetwork"; + options.TransPort = optionIsolablePorts "TransPort"; + options.TransProxyType = mkOption { + description = descriptionGeneric "TransProxyType"; + type = with types; nullOr (enum ["default" "TPROXY" "ipfw" "pf-divert"]); + default = null; + }; + #options.TruncateLogFile + options.UnixSocksGroupWritable = optionBool "UnixSocksGroupWritable"; + options.UseDefaultFallbackDirs = optionBool "UseDefaultFallbackDirs"; + options.UseMicrodescriptors = optionBool "UseMicrodescriptors"; + options.V3AuthUseLegacyKey = optionBool "V3AuthUseLegacyKey"; + options.V3AuthoritativeDirectory = optionBool "V3AuthoritativeDirectory"; + options.VersioningAuthoritativeDirectory = optionBool "VersioningAuthoritativeDirectory"; + options.VirtualAddrNetworkIPv4 = optionString "VirtualAddrNetworkIPv4"; + options.VirtualAddrNetworkIPv6 = optionString "VirtualAddrNetworkIPv6"; + options.WarnPlaintextPorts = optionPorts "WarnPlaintextPorts"; + }; }; }; }; @@ -696,79 +822,217 @@ in config = mkIf cfg.enable { # Not sure if `cfg.relay.role == "private-bridge"` helps as tor # sends a lot of stats - warnings = optional (cfg.relay.enable && cfg.hiddenServices != {}) + warnings = optional (cfg.settings.BridgeRelay && + flatten (mapAttrsToList (n: o: o.map) cfg.relay.onionServices) != []) '' Running Tor hidden services on a public relay makes the presence of hidden services visible through simple statistical analysis of publicly available data. + See https://trac.torproject.org/projects/tor/ticket/8742 You can safely ignore this warning if you don't intend to actually hide your hidden services. In either case, you can always create a container/VM with a separate Tor daemon instance. - ''; + '' ++ + flatten (mapAttrsToList (n: o: + optional (o.settings.HiddenServiceVersion == 2) [ + (optional (o.settings.HiddenServiceExportCircuitID != null) '' + HiddenServiceExportCircuitID is used in the HiddenService: ${n} + but this option is only for v3 hidden services. + '') + ] ++ + optional (o.settings.HiddenServiceVersion != 2) [ + (optional (o.settings.HiddenServiceAuthorizeClient != null) '' + HiddenServiceAuthorizeClient is used in the HiddenService: ${n} + but this option is only for v2 hidden services. + '') + (optional (o.settings.RendPostPeriod != null) '' + RendPostPeriod is used in the HiddenService: ${n} + but this option is only for v2 hidden services. + '') + ] + ) cfg.relay.onionServices); users.groups.tor.gid = config.ids.gids.tor; users.users.tor = { description = "Tor Daemon User"; createHome = true; - home = torDirectory; + home = stateDir; group = "tor"; uid = config.ids.uids.tor; }; - # We have to do this instead of using RuntimeDirectory option in - # the service below because systemd has no way to set owners of - # RuntimeDirectory and putting this into the service below - # requires that service to relax it's sandbox since this needs - # writable /run - systemd.services.tor-init = - { description = "Tor Daemon Init"; - wantedBy = [ "tor.service" ]; - script = '' - install -m 0700 -o tor -g tor -d ${torDirectory} ${torDirectory}/onion - install -m 0750 -o tor -g tor -d ${torRunDirectory} - ''; - serviceConfig = { - Type = "oneshot"; - RemainAfterExit = true; - }; - }; - - systemd.services.tor = - { description = "Tor Daemon"; - path = [ pkgs.tor ]; - - wantedBy = [ "multi-user.target" ]; - after = [ "tor-init.service" "network.target" ]; - restartTriggers = [ torRcFile ]; - - serviceConfig = - { Type = "simple"; - # Translated from the upstream contrib/dist/tor.service.in - ExecStartPre = "${cfg.package}/bin/tor -f ${torRcFile} --verify-config"; - ExecStart = "${cfg.package}/bin/tor -f ${torRcFile}"; - ExecReload = "${pkgs.coreutils}/bin/kill -HUP $MAINPID"; - KillSignal = "SIGINT"; - TimeoutSec = 30; - Restart = "on-failure"; - LimitNOFILE = 32768; - - # Hardening - # this seems to unshare /run despite what systemd.exec(5) says - PrivateTmp = mkIf (!cfg.controlSocket.enable) "yes"; - PrivateDevices = "yes"; - ProtectHome = "yes"; - ProtectSystem = "strict"; - InaccessiblePaths = "/home"; - ReadOnlyPaths = "/"; - ReadWritePaths = [ torDirectory torRunDirectory ]; - NoNewPrivileges = "yes"; - - # tor.service.in has this in, but this line it fails to spawn a namespace when using hidden services - #CapabilityBoundingSet = "CAP_SETUID CAP_SETGID CAP_NET_BIND_SERVICE"; - }; + services.tor.settings = mkMerge [ + (mkIf cfg.enableGeoIP { + GeoIPFile = "${cfg.package.geoip}/share/tor/geoip"; + GeoIPv6File = "${cfg.package.geoip}/share/tor/geoip6"; + }) + (mkIf cfg.controlSocket.enable { + ControlPort = [ { unix = runDir + "/control"; GroupWritable=true; RelaxDirModeCheck=true; } ]; + }) + (mkIf cfg.relay.enable ( + optionalAttrs (cfg.relay.role != "exit") { + ExitPolicy = mkForce ["reject *:*"]; + } // + optionalAttrs (elem cfg.relay.role ["bridge" "private-bridge"]) { + BridgeRelay = true; + ExtORPort.port = mkDefault "auto"; + ServerTransportPlugin.transports = mkDefault ["obfs4"]; + ServerTransportPlugin.exec = mkDefault "${pkgs.obfs4}/bin/obfs4proxy managed"; + } // optionalAttrs (cfg.relay.role == "private-bridge") { + ExtraInfoStatistics = false; + PublishServerDescriptor = false; + } + )) + (mkIf (!cfg.relay.enable) { + # Avoid surprises when leaving ORPort/DirPort configurations in cfg.settings, + # because it would still enable Tor as a relay, + # which can trigger all sort of problems when not carefully done, + # like the blocklisting of the machine's IP addresses + # by some hosting providers... + DirPort = mkForce []; + ORPort = mkForce []; + PublishServerDescriptor = mkForce false; + }) + (mkIf cfg.client.enable ( + { SOCKSPort = [ cfg.client.socksListenAddress ]; + } // optionalAttrs cfg.client.transparentProxy.enable { + TransPort = [{ addr = "127.0.0.1"; port = 9040; }]; + } // optionalAttrs cfg.client.dns.enable { + DNSPort = [{ addr = "127.0.0.1"; port = 9053; }]; + AutomapHostsOnResolve = true; + AutomapHostsSuffixes = cfg.client.dns.automapHostsSuffixes; + } // optionalAttrs (flatten (mapAttrsToList (n: o: o.clientAuthorizations) cfg.client.onionServices) != []) { + ClientOnionAuthDir = runDir + "/ClientOnionAuthDir"; + } + )) + ]; + + networking.firewall = mkIf cfg.openFirewall { + allowedTCPPorts = + concatMap (o: optional (isInt o && o > 0 || o ? "port" && isInt o.port && o.port > 0) o.port) + (flatten [ + cfg.settings.ORPort + cfg.settings.DirPort + ]); + }; + + systemd.services.tor = { + description = "Tor Daemon"; + path = [ pkgs.tor ]; + + wantedBy = [ "multi-user.target" ]; + after = [ "network.target" ]; + restartTriggers = [ torrc ]; + + serviceConfig = { + Type = "simple"; + User = "tor"; + Group = "tor"; + ExecStartPre = [ + "${cfg.package}/bin/tor -f ${torrc} --verify-config" + # DOC: Appendix G of https://spec.torproject.org/rend-spec-v3 + ("+" + pkgs.writeShellScript "ExecStartPre" (concatStringsSep "\n" (flatten (["set -eu"] ++ + mapAttrsToList (name: onion: + optional (onion.authorizedClients != []) '' + rm -rf ${escapeShellArg onion.path}/authorized_clients + install -d -o tor -g tor -m 0700 ${escapeShellArg onion.path} ${escapeShellArg onion.path}/authorized_clients + '' ++ + imap0 (i: pubKey: '' + echo ${pubKey} | + install -o tor -g tor -m 0400 /dev/stdin ${escapeShellArg onion.path}/authorized_clients/${toString i}.auth + '') onion.authorizedClients ++ + optional (onion.secretKey != null) '' + install -d -o tor -g tor -m 0700 ${escapeShellArg onion.path} + key="$(cut -f1 -d: ${escapeShellArg onion.secretKey})" + case "$key" in + ("== ed25519v"*"-secret") + install -o tor -g tor -m 0400 ${escapeShellArg onion.secretKey} ${escapeShellArg onion.path}/hs_ed25519_secret_key;; + (*) echo >&2 "NixOS does not (yet) support secret key type for onion: ${name}"; exit 1;; + esac + '' + ) cfg.relay.onionServices ++ + mapAttrsToList (name: onion: imap0 (i: prvKeyPath: + let hostname = removeSuffix ".onion" name; in '' + printf "%s:" ${escapeShellArg hostname} | cat - ${escapeShellArg prvKeyPath} | + install -o tor -g tor -m 0700 /dev/stdin \ + ${runDir}/ClientOnionAuthDir/${escapeShellArg hostname}.${toString i}.auth_private + '') onion.clientAuthorizations) + cfg.client.onionServices + )))) + ]; + ExecStart = "${cfg.package}/bin/tor -f ${torrc}"; + ExecReload = "${pkgs.coreutils}/bin/kill -HUP $MAINPID"; + KillSignal = "SIGINT"; + TimeoutSec = 30; + Restart = "on-failure"; + LimitNOFILE = 32768; + RuntimeDirectory = [ + # g+x allows access to the control socket + "tor" + "tor/root" + # g+x can't be removed in ExecStart=, but will be removed by Tor + "tor/ClientOnionAuthDir" + ]; + RuntimeDirectoryMode = "0710"; + StateDirectoryMode = "0700"; + StateDirectory = [ + "tor" + "tor/onion" + ] ++ + flatten (mapAttrsToList (name: onion: + optional (onion.secretKey == null) "tor/onion/${name}" + ) cfg.relay.onionServices); + # The following options are only to optimize: + # systemd-analyze security tor + RootDirectory = runDir + "/root"; + RootDirectoryStartOnly = true; + #InaccessiblePaths = [ "-+${runDir}/root" ]; + UMask = "0066"; + BindPaths = [ stateDir ]; + BindReadOnlyPaths = [ storeDir "/etc" ]; + AmbientCapabilities = [""] ++ lib.optional bindsPrivilegedPort "CAP_NET_BIND_SERVICE"; + CapabilityBoundingSet = [""] ++ lib.optional bindsPrivilegedPort "CAP_NET_BIND_SERVICE"; + # ProtectClock= adds DeviceAllow=char-rtc r + DeviceAllow = ""; + LockPersonality = true; + MemoryDenyWriteExecute = true; + NoNewPrivileges = true; + PrivateDevices = true; + PrivateMounts = true; + PrivateNetwork = mkDefault false; + PrivateTmp = true; + # Tor cannot currently bind privileged port when PrivateUsers=true, + # see https://gitlab.torproject.org/legacy/trac/-/issues/20930 + PrivateUsers = !bindsPrivilegedPort; + ProtectClock = true; + ProtectControlGroups = true; + ProtectHome = true; + ProtectHostname = true; + ProtectKernelLogs = true; + ProtectKernelModules = true; + ProtectKernelTunables = true; + ProtectSystem = "strict"; + RemoveIPC = true; + RestrictAddressFamilies = [ "AF_UNIX" "AF_INET" "AF_INET6" ]; + RestrictNamespaces = true; + RestrictRealtime = true; + RestrictSUIDSGID = true; + # See also the finer but experimental option settings.Sandbox + SystemCallFilter = [ + "@system-service" + # Groups in @system-service which do not contain a syscall listed by: + # perf stat -x, 2>perf.log -e 'syscalls:sys_enter_*' tor + # in tests, and seem likely not necessary for tor. + "~@aio" "~@chown" "~@keyring" "~@memlock" "~@resources" "~@setuid" "~@timer" + ]; + SystemCallArchitectures = "native"; + SystemCallErrorNumber = "EPERM"; }; + }; environment.systemPackages = [ cfg.package ]; }; + + meta.maintainers = with lib.maintainers; [ julm ]; } diff --git a/nixos/tests/tor.nix b/nixos/tests/tor.nix index ad07231557c..c061f59226c 100644 --- a/nixos/tests/tor.nix +++ b/nixos/tests/tor.nix @@ -17,7 +17,7 @@ rec { environment.systemPackages = with pkgs; [ netcat ]; services.tor.enable = true; services.tor.client.enable = true; - services.tor.controlPort = 9051; + services.tor.settings.ControlPort = 9051; }; testScript = '' diff --git a/pkgs/tools/security/tor/default.nix b/pkgs/tools/security/tor/default.nix index 04bf598d132..e46fd4790a3 100644 --- a/pkgs/tools/security/tor/default.nix +++ b/pkgs/tools/security/tor/default.nix @@ -1,5 +1,6 @@ { stdenv, fetchurl, pkgconfig, libevent, openssl, zlib, torsocks , libseccomp, systemd, libcap, lzma, zstd, scrypt, nixosTests +, writeShellScript # for update.nix , writeScript @@ -12,7 +13,21 @@ , gnused , nix }: +let + tor-client-auth-gen = writeShellScript "tor-client-auth-gen" '' + PATH="${stdenv.lib.makeBinPath [coreutils gnugrep openssl]}" + pem="$(openssl genpkey -algorithm x25519)" + printf private_key=descriptor:x25519: + echo "$pem" | grep -v " PRIVATE KEY" | + base64 -d | tail --bytes=32 | base32 | tr -d = + + printf public_key=descriptor:x25519: + echo "$pem" | openssl pkey -in /dev/stdin -pubout | + grep -v " PUBLIC KEY" | + base64 -d | tail --bytes=32 | base32 | tr -d = + ''; +in stdenv.mkDerivation rec { pname = "tor"; version = "0.4.4.6"; @@ -52,6 +67,7 @@ stdenv.mkDerivation rec { mkdir -p $geoip/share/tor mv $out/share/tor/geoip{,6} $geoip/share/tor rm -rf $out/share/tor + ln -s ${tor-client-auth-gen} $out/bin/tor-client-auth-gen ''; passthru = { From 7a580a12196e63eb665de6eb4db8bb3b6da142f5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rg=20Thalheim?= Date: Wed, 30 Dec 2020 06:58:57 +0100 Subject: [PATCH 28/28] cntr: 1.2.1 -> 1.4.1 --- pkgs/applications/virtualization/cntr/default.nix | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/pkgs/applications/virtualization/cntr/default.nix b/pkgs/applications/virtualization/cntr/default.nix index e3ab1c6c2f8..ab9b63eb79b 100644 --- a/pkgs/applications/virtualization/cntr/default.nix +++ b/pkgs/applications/virtualization/cntr/default.nix @@ -2,23 +2,22 @@ rustPlatform.buildRustPackage rec { pname = "cntr"; - version = "1.2.1"; + version = "1.4.1"; src = fetchFromGitHub { owner = "Mic92"; repo = "cntr"; rev = version; - sha256 = "0dhfz7aj3cqi974ybf0axchih40rzrs9m8bxhwz1hgig57aisfc0"; + sha256 = "sha256-4ogyOKuz6702/sOQNvE+UP+cvQrPPU3VjL4b0FUfRNw="; }; - cargoSha256 = "088drkpkgq8psv5j6igxyhfvvbalzg6nd98r9z0nxkawck5i2clz"; + cargoSha256 = "sha256-lblvun2T1qpFiowld77Ti2MFPzhs5pOWWRbErORXYCM="; meta = with stdenv.lib; { description = "A container debugging tool based on FUSE"; homepage = "https://github.com/Mic92/cntr"; license = licenses.mit; - # aarch64 support will be fixed soon - platforms = [ "x86_64-linux" ]; + platforms = platforms.linux; maintainers = [ maintainers.mic92 ]; }; }