lol

Merge pull request #266702 from nh2/plausible-listen-address-no-distributed-erlang

plausible, nixos/plausible: Add `listenAddress` option

authored by

Niklas Hambüchen and committed by
GitHub
f9c7c12d 9290bb56

+47 -14
+2
nixos/doc/manual/release-notes/rl-2311.section.md
··· 323 323 324 324 - Package `pash` was removed due to being archived upstream. Use `powershell` as an alternative. 325 325 326 + - The option `services.plausible.releaseCookiePath` has been removed: Plausible does not use any distributed Erlang features, and does not plan to (see [discussion](https://github.com/NixOS/nixpkgs/pull/130297#issuecomment-1805851333)), so NixOS now disables them, and the Erlang cookie becomes unnecessary. You may delete the file that `releaseCookiePath` was set to. 327 + 326 328 - `security.sudo.extraRules` now includes `root`'s default rule, with ordering 327 329 priority 400. This is functionally identical for users not specifying rule 328 330 order, or relying on `mkBefore` and `mkAfter`, but may impact users calling
+41 -11
nixos/modules/services/web-apps/plausible.nix
··· 11 11 12 12 package = mkPackageOptionMD pkgs "plausible" { }; 13 13 14 - releaseCookiePath = mkOption { 15 - type = with types; either str path; 16 - description = lib.mdDoc '' 17 - The path to the file with release cookie. (used for remote connection to the running node). 18 - ''; 19 - }; 20 - 21 14 adminUser = { 22 15 name = mkOption { 23 16 default = "admin"; ··· 92 85 framework docs](https://hexdocs.pm/phoenix/Mix.Tasks.Phx.Gen.Secret.html#content). 93 86 ''; 94 87 }; 88 + listenAddress = mkOption { 89 + default = "127.0.0.1"; 90 + type = types.str; 91 + description = lib.mdDoc '' 92 + The IP address on which the server is listening. 93 + ''; 94 + }; 95 95 port = mkOption { 96 96 default = 8000; 97 97 type = types.port; ··· 162 162 }; 163 163 }; 164 164 165 + imports = [ 166 + (mkRemovedOptionModule [ "services" "plausible" "releaseCookiePath" ] "Plausible uses no distributed Erlang features, so this option is no longer necessary and was removed") 167 + ]; 168 + 165 169 config = mkIf cfg.enable { 166 170 assertions = [ 167 171 { assertion = cfg.adminUser.activate -> cfg.database.postgres.setup; ··· 179 183 services.clickhouse = mkIf cfg.database.clickhouse.setup { 180 184 enable = true; 181 185 }; 182 - 183 - services.epmd.enable = true; 184 186 185 187 environment.systemPackages = [ cfg.package ]; 186 188 ··· 209 211 # Configuration options from 210 212 # https://plausible.io/docs/self-hosting-configuration 211 213 PORT = toString cfg.server.port; 214 + LISTEN_IP = cfg.server.listenAddress; 215 + 216 + # Note [plausible-needs-no-erlang-distributed-features]: 217 + # Plausible does not use, and does not plan to use, any of 218 + # Erlang's distributed features, see: 219 + # https://github.com/plausible/analytics/pull/1190#issuecomment-1018820934 220 + # Thus, disable distribution for improved simplicity and security: 221 + # 222 + # When distribution is enabled, 223 + # Elixir spwans the Erlang VM, which will listen by default on all 224 + # interfaces for messages between Erlang nodes (capable of 225 + # remote code execution); it can be protected by a cookie; see 226 + # https://erlang.org/doc/reference_manual/distributed.html#security). 227 + # 228 + # It would be possible to restrict the interface to one of our choice 229 + # (e.g. localhost or a VPN IP) similar to how we do it with `listenAddress` 230 + # for the Plausible web server; if distribution is ever needed in the future, 231 + # https://github.com/NixOS/nixpkgs/pull/130297 shows how to do it. 232 + # 233 + # But since Plausible does not use this feature in any way, 234 + # we just disable it. 235 + RELEASE_DISTRIBUTION = "none"; 236 + # Additional safeguard, in case `RELEASE_DISTRIBUTION=none` ever 237 + # stops disabling the start of EPMD. 238 + ERL_EPMD_ADDRESS = "127.0.0.1"; 239 + 212 240 DISABLE_REGISTRATION = if isBool cfg.server.disableRegistration then boolToString cfg.server.disableRegistration else cfg.server.disableRegistration; 213 241 214 242 RELEASE_TMP = "/var/lib/plausible/tmp"; ··· 238 266 path = [ cfg.package ] 239 267 ++ optional cfg.database.postgres.setup config.services.postgresql.package; 240 268 script = '' 241 - export RELEASE_COOKIE="$(< $CREDENTIALS_DIRECTORY/RELEASE_COOKIE )" 269 + # Elixir does not start up if `RELEASE_COOKIE` is not set, 270 + # even though we set `RELEASE_DISTRIBUTION=none` so the cookie should be unused. 271 + # Thus, make a random one, which should then be ignored. 272 + export RELEASE_COOKIE=$(tr -dc A-Za-z0-9 < /dev/urandom | head -c 20) 242 273 export ADMIN_USER_PWD="$(< $CREDENTIALS_DIRECTORY/ADMIN_USER_PWD )" 243 274 export SECRET_KEY_BASE="$(< $CREDENTIALS_DIRECTORY/SECRET_KEY_BASE )" 244 275 ··· 265 296 LoadCredential = [ 266 297 "ADMIN_USER_PWD:${cfg.adminUser.passwordFile}" 267 298 "SECRET_KEY_BASE:${cfg.server.secretKeybaseFile}" 268 - "RELEASE_COOKIE:${cfg.releaseCookiePath}" 269 299 ] ++ lib.optionals (cfg.mail.smtp.passwordFile != null) [ "SMTP_USER_PWD:${cfg.mail.smtp.passwordFile}"]; 270 300 }; 271 301 };
+4 -3
nixos/tests/plausible.nix
··· 8 8 virtualisation.memorySize = 4096; 9 9 services.plausible = { 10 10 enable = true; 11 - releaseCookiePath = "${pkgs.runCommand "cookie" { } '' 12 - ${pkgs.openssl}/bin/openssl rand -base64 64 >"$out" 13 - ''}"; 14 11 adminUser = { 15 12 email = "admin@example.org"; 16 13 passwordFile = "${pkgs.writeText "pwd" "foobar"}"; ··· 27 24 start_all() 28 25 machine.wait_for_unit("plausible.service") 29 26 machine.wait_for_open_port(8000) 27 + 28 + # Ensure that the software does not make not make the machine 29 + # listen on any public interfaces by default. 30 + machine.fail("ss -tlpn 'src = 0.0.0.0 or src = [::]' | grep LISTEN") 30 31 31 32 machine.succeed("curl -f localhost:8000 >&2") 32 33