diff --git a/nixos/doc/manual/release-notes/rl-2511.section.md b/nixos/doc/manual/release-notes/rl-2511.section.md index 983537f73ede..fa41d887a18d 100644 --- a/nixos/doc/manual/release-notes/rl-2511.section.md +++ b/nixos/doc/manual/release-notes/rl-2511.section.md @@ -40,6 +40,8 @@ - [postfix-tlspol](https://github.com/Zuplu/postfix-tlspol), MTA-STS and DANE resolver and TLS policy server for Postfix. Available as [services.postfix-tlspol](#opt-services.postfix-tlspol.enable). +- [Newt](https://github.com/fosrl/newt), a fully user space WireGuard tunnel client and TCP/UDP proxy, designed to securely expose private resources controlled by Pangolin. Available as [services.newt](options.html#opt-services.newt.enable). + - [Szurubooru](https://github.com/rr-/szurubooru), an image board engine inspired by services such as Danbooru, dedicated for small and medium communities. Available as [services.szurubooru](#opt-services.szurubooru.enable). - The [Neat IP Address Planner](https://spritelink.github.io/NIPAP/) (NIPAP) can now be enabled through [services.nipap.enable](#opt-services.nipap.enable). diff --git a/nixos/modules/module-list.nix b/nixos/modules/module-list.nix index 5eb40adc5647..2b93d0a3c84c 100644 --- a/nixos/modules/module-list.nix +++ b/nixos/modules/module-list.nix @@ -1241,6 +1241,7 @@ ./services/networking/netclient.nix ./services/networking/networkd-dispatcher.nix ./services/networking/networkmanager.nix + ./services/networking/newt.nix ./services/networking/nextdns.nix ./services/networking/nftables.nix ./services/networking/nghttpx/default.nix diff --git a/nixos/modules/services/networking/newt.nix b/nixos/modules/services/networking/newt.nix new file mode 100644 index 000000000000..e001dd85ffdd --- /dev/null +++ b/nixos/modules/services/networking/newt.nix @@ -0,0 +1,165 @@ +{ + config, + lib, + pkgs, + ... +}: +let + cfg = config.services.newt; +in +{ + options = { + services.newt = { + enable = lib.mkEnableOption "Newt, user space tunnel client for Pangolin"; + # needs to be changed when newt-go changes to fosrl-newt + package = lib.mkPackageOption pkgs "newt-go" { }; + + id = lib.mkOption { + type = with lib.types; nullOr str; + default = null; + description = '' + The Newt Id that will be used to communicate to Pangolin. This is generated on site creation in the dashboard. + ''; + }; + endpoint = lib.mkOption { + type = with lib.types; nullOr str; + default = null; + description = '' + The endpoint where both Gerbil and Pangolin reside in order to connect to the websocket. The url of your Pangolin dashboard. + ''; + }; + logLevel = lib.mkOption { + type = lib.types.enum [ + "DEBUG" + "INFO" + "WARN" + "ERROR" + "FATAL" + ]; + default = "INFO"; + description = "The log level to use."; + }; + # provide path to file to keep secrets out of the nix store + environmentFile = lib.mkOption { + type = with lib.types; nullOr path; + default = null; + description = '' + Path to a file containing sensitive environment variables for Newt. See https://docs.fossorial.io/Newt/overview#cli-args + These will overwrite anything defined in the config. + The file should contain environment-variable assignments like: + NEWT_ID=2ix2t8xk22ubpfy + NEWT_SECRET=nnisrfsdfc7prqsp9ewo1dvtvci50j5uiqotez00dgap0ii2 + ''; + }; + }; + }; + + config = lib.mkIf cfg.enable { + + assertions = [ + { + assertion = cfg.environmentFile != null; + message = "services.newt.environmentFile must be provided when Newt is enabled."; + } + ]; + + systemd.services.newt = { + description = "Newt, user space tunnel client for Pangolin"; + wantedBy = [ "multi-user.target" ]; + after = [ "network.target" ]; + + environment = { + HOME = "/var/lib/private/newt"; + }; + # the flag values will all be overwritten if also defined in the env file + script = " + exec ${lib.getExe pkgs.newt-go} \\\n + ${lib.optionalString ( + !isNull cfg.id + ) "--id ${cfg.id} \\\n"} + ${lib.optionalString ( + !isNull cfg.endpoint + ) "--endpoint ${cfg.endpoint} \\\n"} + --log-level ${cfg.logLevel} + "; + serviceConfig = { + DynamicUser = true; + StateDirectory = "newt"; + StateDirectoryMode = "0700"; + Restart = "always"; + RestartSec = "10s"; + EnvironmentFile = cfg.environmentFile; + # hardening + ProtectSystem = "strict"; + ProtectHome = true; + PrivateTmp = "disconnected"; + PrivateDevices = true; + PrivateUsers = true; + PrivateMounts = true; + ProtectKernelTunables = true; + ProtectKernelModules = true; + ProtectKernelLogs = true; + ProtectControlGroups = true; + LockPersonality = true; + RestrictRealtime = true; + ProtectClock = true; + ProtectProc = "noaccess"; + ProtectHostname = true; + RemoveIPC = true; + NoNewPrivileges = true; + RestrictSUIDSGID = true; + MemoryDenyWriteExecute = true; + SystemCallArchitectures = "native"; + UMask = "0077"; + RestrictAddressFamilies = [ + "AF_INET" + "AF_INET6" + "AF_NETLINK" + "AF_UNIX" + ]; + CapabilityBoundingSet = [ + "~CAP_BLOCK_SUSPEND" + "~CAP_BPF" + "~CAP_CHOWN" + "~CAP_MKNOD" + "~CAP_NET_RAW" + "~CAP_PERFMON" + "~CAP_SYS_BOOT" + "~CAP_SYS_CHROOT" + "~CAP_SYS_MODULE" + "~CAP_SYS_NICE" + "~CAP_SYS_PACCT" + "~CAP_SYS_PTRACE" + "~CAP_SYS_TIME" + "~CAP_SYS_TTY_CONFIG" + "~CAP_SYSLOG" + "~CAP_WAKE_ALARM" + ]; + SystemCallFilter = [ + "~@aio:EPERM" + "~@chown:EPERM" + "~@clock:EPERM" + "~@cpu-emulation:EPERM" + "~@debug:EPERM" + "~@keyring:EPERM" + "~@memlock:EPERM" + "~@module:EPERM" + "~@mount:EPERM" + "~@obsolete:EPERM" + "~@pkey:EPERM" + "~@privileged:EPERM" + "~@raw-io:EPERM" + "~@reboot:EPERM" + "~@resources:EPERM" + "~@sandbox:EPERM" + "~@setuid:EPERM" + "~@swap:EPERM" + "~@sync:EPERM" + "~@timer:EPERM" + ]; + }; + }; + }; + + meta.maintainers = with lib.maintainers; [ jackr ]; +}