diff --git a/agenix.nix b/agenix.nix index c8acf14..e3da3a4 100644 --- a/agenix.nix +++ b/agenix.nix @@ -1,13 +1,38 @@ let server = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAING219cDKTDLaZefmqvOHfXvYloA/ErsCGE0pM022vlB"; jet = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIE40ISu3ydCqfdpb26JYD5cIN0Fu0id/FDS+xjB5zpqu"; -in { - "secrets/forgejo-db.age".publicKeys = [ server jet ]; - "secrets/stalwart-admin.age".publicKeys = [ server jet ]; - "secrets/searx-env.age".publicKeys = [ server jet ]; - "secrets/tailscale-key.age".publicKeys = [ server jet ]; - "secrets/grafana-secret.age".publicKeys = [ server jet ]; - "secrets/matrix-macaroon.age".publicKeys = [ server jet ]; - "secrets/ntfy-admin-hash.age".publicKeys = [ server jet ]; - "secrets/mymx-webhook.age".publicKeys = [ server jet ]; +in +{ + "secrets/forgejo-db.age".publicKeys = [ + server + jet + ]; + "secrets/stalwart-admin.age".publicKeys = [ + server + jet + ]; + "secrets/searx-env.age".publicKeys = [ + server + jet + ]; + "secrets/tailscale-key.age".publicKeys = [ + server + jet + ]; + "secrets/grafana-secret.age".publicKeys = [ + server + jet + ]; + "secrets/matrix-macaroon.age".publicKeys = [ + server + jet + ]; + "secrets/ntfy-admin-hash.age".publicKeys = [ + server + jet + ]; + "secrets/mymx-webhook.age".publicKeys = [ + server + jet + ]; } diff --git a/configuration.nix b/configuration.nix index e8cfe9a..0565de2 100644 --- a/configuration.nix +++ b/configuration.nix @@ -1,4 +1,9 @@ -{ config, pkgs, modulesPath, ... }: +{ + config, + pkgs, + modulesPath, + ... +}: { imports = [ @@ -19,13 +24,25 @@ # Agenix secrets age.secrets = { forgejo-db.file = ./secrets/forgejo-db.age; - stalwart-admin = { file = ./secrets/stalwart-admin.age; owner = "stalwart-mail"; }; + stalwart-admin = { + file = ./secrets/stalwart-admin.age; + owner = "stalwart-mail"; + }; searx-env.file = ./secrets/searx-env.age; tailscale-key.file = ./secrets/tailscale-key.age; - grafana-secret = { file = ./secrets/grafana-secret.age; owner = "grafana"; }; - matrix-macaroon = { file = ./secrets/matrix-macaroon.age; owner = "matrix-synapse"; }; + grafana-secret = { + file = ./secrets/grafana-secret.age; + owner = "grafana"; + }; + matrix-macaroon = { + file = ./secrets/matrix-macaroon.age; + owner = "matrix-synapse"; + }; ntfy-admin-hash.file = ./secrets/ntfy-admin-hash.age; - mymx-webhook = { file = ./secrets/mymx-webhook.age; owner = "mymx"; }; + mymx-webhook = { + file = ./secrets/mymx-webhook.age; + owner = "mymx"; + }; }; # Bootloader @@ -35,13 +52,16 @@ # Networking networking.hostName = "extremist-software"; - networking.firewall.allowedTCPPorts = [ 22 80 443 ]; # SSH, HTTP, HTTPS - + networking.firewall.allowedTCPPorts = [ + 22 + 80 + 443 + ]; # SSH, HTTP, HTTPS # Tailscale services.tailscale.enable = true; # We assume the user will authenticate manually or via a one-time key service # For now, let's enable it and allow the user to run `tailscale up` or provision via key - + # Users users.users.root.openssh.authorizedKeys.keys = [ "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIE40ISu3ydCqfdpb26JYD5cIN0Fu0id/FDS+xjB5zpqu" @@ -52,10 +72,12 @@ enable = true; settings.PasswordAuthentication = false; settings.PermitRootLogin = "prohibit-password"; - hostKeys = [{ - path = "/etc/ssh/ssh_host_ed25519_key"; - type = "ed25519"; - }]; + hostKeys = [ + { + path = "/etc/ssh/ssh_host_ed25519_key"; + type = "ed25519"; + } + ]; }; # Fail2ban @@ -94,7 +116,10 @@ # System system.stateVersion = "24.05"; - nix.settings.experimental-features = [ "nix-command" "flakes" ]; + nix.settings.experimental-features = [ + "nix-command" + "flakes" + ]; nix.settings.max-jobs = "auto"; nix.settings.cores = 0; services.postgresql.package = pkgs.postgresql_15; @@ -105,19 +130,19 @@ # ZRAM for limited RAM zramSwap.enable = true; - zramSwap.memoryPercent = 50; + zramSwap.memoryPercent = 50; services.tailscale.authKeyFile = config.age.secrets.tailscale-key.path; # MyMX - services.jetpham-website.enable = true; - services.jetpham-website.tor.enable = true; + services.jetpham-website.enable = false; + services.jetpham-website.tor.enable = false; services.mymx = { enable = true; webhookSecretFile = config.age.secrets.mymx-webhook.path; }; - + # Allow Tailscale traffic networking.firewall.trustedInterfaces = [ "tailscale0" ]; # Required for Tailscale subnet routing and exit nodes, and often helpful for connectivity diff --git a/flake.nix b/flake.nix index ca021ce..f2f7ca1 100644 --- a/flake.nix +++ b/flake.nix @@ -23,50 +23,59 @@ agenix.inputs.nixpkgs.follows = "nixpkgs"; }; - outputs = { self, nixpkgs, disko, ... }@inputs: { - nixosConfigurations.extremist-software = nixpkgs.lib.nixosSystem { - system = "x86_64-linux"; - specialArgs = { inherit inputs; }; - modules = [ - disko.nixosModules.disko - inputs.mymx.nixosModules.default - inputs.website.nixosModules.default - inputs.agenix.nixosModules.default - inputs.noisebell.nixosModules.default - inputs.noisepics.nixosModules.default + outputs = + { + self, + nixpkgs, + disko, + ... + }@inputs: + { + nixosConfigurations.extremist-software = nixpkgs.lib.nixosSystem { + system = "x86_64-linux"; + specialArgs = { inherit inputs; }; + modules = [ + disko.nixosModules.disko + inputs.mymx.nixosModules.default + inputs.website.nixosModules.default + inputs.agenix.nixosModules.default + inputs.noisebell.nixosModules.default + inputs.noisepics.nixosModules.default - ./disk-config.nix - ./configuration.nix - ]; - }; + ./disk-config.nix + ./configuration.nix + ]; + }; - devShells.x86_64-linux.default = let - pkgs = nixpkgs.legacyPackages.x86_64-linux; - deploy = pkgs.writeShellScriptBin "nhs" '' - nh os switch --hostname extremist-software --target-host root@extremist-software path:. "$@" - ''; - check-secrets = pkgs.writeShellScriptBin "check-secrets" '' - set -euo pipefail - failed=0 - for f in secrets/*.age; do - last=$(agenix -d "$f" | tail -c 1 | od -An -tx1 | tr -d ' \n') - if [ "$last" = "0a" ]; then - echo "FAIL: $f has trailing newline" - failed=1 - fi - done - if [ "$failed" -eq 0 ]; then - echo "All secrets OK: no trailing newlines" - fi - exit $failed - ''; - in pkgs.mkShell { - packages = [ - pkgs.nh - inputs.agenix.packages.x86_64-linux.default - deploy - check-secrets - ]; + devShells.x86_64-linux.default = + let + pkgs = nixpkgs.legacyPackages.x86_64-linux; + deploy = pkgs.writeShellScriptBin "nhs" '' + nh os switch --hostname extremist-software --target-host root@extremist-software path:. "$@" + ''; + check-secrets = pkgs.writeShellScriptBin "check-secrets" '' + set -euo pipefail + failed=0 + for f in secrets/*.age; do + last=$(agenix -d "$f" | tail -c 1 | od -An -tx1 | tr -d ' \n') + if [ "$last" = "0a" ]; then + echo "FAIL: $f has trailing newline" + failed=1 + fi + done + if [ "$failed" -eq 0 ]; then + echo "All secrets OK: no trailing newlines" + fi + exit $failed + ''; + in + pkgs.mkShell { + packages = [ + pkgs.nh + inputs.agenix.packages.x86_64-linux.default + deploy + check-secrets + ]; + }; }; - }; } diff --git a/modules/caddy.nix b/modules/caddy.nix index 3047747..2fa121f 100644 --- a/modules/caddy.nix +++ b/modules/caddy.nix @@ -43,7 +43,7 @@ } ''; }; - + "git.extremist.software" = { extraConfig = '' rate_limit { @@ -102,7 +102,7 @@ reverse_proxy localhost:3001 # Grafana ''; }; - + "uptime.extremist.software" = { extraConfig = '' rate_limit { @@ -129,7 +129,6 @@ ''; }; - "matrix.extremist.software" = { extraConfig = '' rate_limit { diff --git a/modules/mail.nix b/modules/mail.nix index 124393a..d3c373e 100644 --- a/modules/mail.nix +++ b/modules/mail.nix @@ -5,7 +5,7 @@ enable = true; # Let stalwart open its own ports if needed for the main services openFirewall = true; - + settings = { server = { hostname = "extremist.software"; @@ -40,7 +40,7 @@ cert = "%{file:/var/lib/acme/extremist.software/fullchain.pem}%"; private-key = "%{file:/var/lib/acme/extremist.software/key.pem}%"; }; - + authentication.fallback-admin = { user = "admin"; secret = "%{file:/run/agenix/stalwart-admin}%"; diff --git a/modules/matrix.nix b/modules/matrix.nix index eb7db69..630cece 100644 --- a/modules/matrix.nix +++ b/modules/matrix.nix @@ -7,7 +7,7 @@ settings = { server_name = "extremist.software"; public_baseurl = "https://matrix.extremist.software"; - + listeners = [ { port = 8008; @@ -17,13 +17,16 @@ x_forwarded = true; resources = [ { - names = [ "client" "federation" ]; + names = [ + "client" + "federation" + ]; compress = false; } ]; } ]; - + enable_registration = false; database = { name = "psycopg2"; @@ -42,10 +45,11 @@ services.postgresql = { enable = true; ensureDatabases = [ "matrix-synapse" ]; - ensureUsers = [{ - name = "matrix-synapse"; - ensureDBOwnership = true; - }]; + ensureUsers = [ + { + name = "matrix-synapse"; + ensureDBOwnership = true; + } + ]; }; } - diff --git a/modules/monitoring.nix b/modules/monitoring.nix index 68b5bc8..9f79c44 100644 --- a/modules/monitoring.nix +++ b/modules/monitoring.nix @@ -15,9 +15,11 @@ scrapeConfigs = [ { job_name = "node"; - static_configs = [{ - targets = [ "127.0.0.1:9100" ]; - }]; + static_configs = [ + { + targets = [ "127.0.0.1:9100" ]; + } + ]; } ]; }; diff --git a/modules/noisebell.nix b/modules/noisebell.nix index 8f09ba6..eccf8fc 100644 --- a/modules/noisebell.nix +++ b/modules/noisebell.nix @@ -1,4 +1,4 @@ -{ ... }: +{ config, ... }: { services.noisebell-cache = { @@ -6,6 +6,12 @@ port = 3005; domain = "noisebell.extremist.software"; piAddress = "http://noisebell-pi"; + outboundWebhooks = [ + { + url = "http://127.0.0.1:3004/webhook"; + secretFile = config.age.secrets.noisebell-discord-webhook-secret.path; + } + ]; }; services.noisebell-discord = { diff --git a/modules/ntfy.nix b/modules/ntfy.nix index f4668f7..a79a416 100644 --- a/modules/ntfy.nix +++ b/modules/ntfy.nix @@ -1,4 +1,9 @@ -{ config, pkgs, lib, ... }: +{ + config, + pkgs, + lib, + ... +}: { services.ntfy-sh = { @@ -19,13 +24,15 @@ # Patch the generated config at runtime to inject the admin bcrypt hash systemd.services.ntfy-sh = { serviceConfig.RuntimeDirectory = "ntfy-sh"; - serviceConfig.ExecStartPre = let - script = pkgs.writeShellScript "ntfy-patch-config" '' - cp /etc/ntfy/server.yml /run/ntfy-sh/server.yml - HASH=$(cat ${config.age.secrets.ntfy-admin-hash.path}) - printf '\nauth-users:\n - "jet:%s:admin"\n' "$HASH" >> /run/ntfy-sh/server.yml - ''; - in [ "+${script}" ]; + serviceConfig.ExecStartPre = + let + script = pkgs.writeShellScript "ntfy-patch-config" '' + cp /etc/ntfy/server.yml /run/ntfy-sh/server.yml + HASH=$(cat ${config.age.secrets.ntfy-admin-hash.path}) + printf '\nauth-users:\n - "jet:%s:admin"\n' "$HASH" >> /run/ntfy-sh/server.yml + ''; + in + [ "+${script}" ]; serviceConfig.ExecStart = lib.mkForce "${pkgs.ntfy-sh}/bin/ntfy serve --config /run/ntfy-sh/server.yml"; }; } diff --git a/modules/searx.nix b/modules/searx.nix index f9d1125..ffefad9 100644 --- a/modules/searx.nix +++ b/modules/searx.nix @@ -16,15 +16,48 @@ request_timeout = 1.5; }; ui = { - categories_as_tabs = [ "general" "images" ]; + categories_as_tabs = [ + "general" + "images" + ]; }; engines = [ - { name = "google"; engine = "google"; categories = "general"; disabled = false; } - { name = "wikipedia"; engine = "wikipedia"; categories = "general"; disabled = false; } - { name = "google images"; engine = "google_images"; categories = "images"; disabled = false; } - { name = "duckduckgo images"; engine = "duckduckgo_images"; categories = "images"; disabled = false; } - { name = "bing images"; engine = "bing_images"; categories = "images"; disabled = false; } - { name = "qwant images"; engine = "qwant_images"; categories = "images"; disabled = false; } + { + name = "google"; + engine = "google"; + categories = "general"; + disabled = false; + } + { + name = "wikipedia"; + engine = "wikipedia"; + categories = "general"; + disabled = false; + } + { + name = "google images"; + engine = "google_images"; + categories = "images"; + disabled = false; + } + { + name = "duckduckgo images"; + engine = "duckduckgo_images"; + categories = "images"; + disabled = false; + } + { + name = "bing images"; + engine = "bing_images"; + categories = "images"; + disabled = false; + } + { + name = "qwant images"; + engine = "qwant_images"; + categories = "images"; + disabled = false; + } ]; }; };