diff --git a/.envrc b/.envrc new file mode 100644 index 0000000..3550a30 --- /dev/null +++ b/.envrc @@ -0,0 +1 @@ +use flake diff --git a/.gitignore b/.gitignore index 6d12da4..d9b4996 100644 --- a/.gitignore +++ b/.gitignore @@ -10,3 +10,4 @@ dkim_private.pem !secrets/secrets.nix.example install.log +.direnv diff --git a/README.md b/README.md index 956da57..51dede9 100644 --- a/README.md +++ b/README.md @@ -17,6 +17,7 @@ This repository uses **untracked secrets**, so you must build the system locally ### 1. Setup Secrets 1. `cp secrets/secrets.nix.example secrets/secrets.nix` 2. Fill in the values (generate random keys, etc). + - `openssl rand -base64 32` is a good way to make a new key - `tailscaleKey` must be a **Reusable** key from the Tailscale admin console. ### 2. Verify Configuration Locally @@ -39,14 +40,14 @@ nix run github:nix-community/nixos-anywhere -- --store-paths \ ``` ### 3. Update Existing Server (No Wipe) -Once the server is running NixOS, use `nixos-rebuild` to push updates. This is faster and doesn't wipe data. +Once the server is running NixOS, use `nh` to push updates. This repository provides `nh` via `direnv` (loaded from `flake.nix` devShell), so just run `direnv allow` first. ```bash # Update via IP -nixos-rebuild switch --flake path:.#extremist-software --target-host root@ --impure +nh os switch --hostname extremist-software --target-host root@ --impure path:. # Update via Tailscale (Once tailored up) -nixos-rebuild switch --flake path:.#extremist-software --target-host root@extremist-software --impure +nh os switch --hostname extremist-software --target-host root@extremist-software --impure path:. ``` repo uses `impure` build to load `secrets/secrets.nix` directly. no encrypted secrets in git. diff --git a/configuration.nix b/configuration.nix index 415f677..6ad6d2e 100644 --- a/configuration.nix +++ b/configuration.nix @@ -9,6 +9,7 @@ ./modules/searx.nix ./modules/matrix.nix ./modules/monitoring.nix + ./modules/ntfy.nix ./secrets/secrets-scheme.nix # Impure Secrets ./secrets/secrets.nix @@ -25,7 +26,7 @@ # Networking networking.hostName = "extremist-software"; 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 @@ -43,6 +44,14 @@ settings.PermitRootLogin = "prohibit-password"; }; + # nh (yet another nix helper) + programs.nh = { + enable = true; + clean.enable = true; + clean.extraArgs = "--keep 2"; + flake = "/home/jet/Documents/extremist-software"; + }; + # System system.stateVersion = "24.05"; nix.settings.experimental-features = [ "nix-command" "flakes" ]; diff --git a/flake.lock b/flake.lock index 25350a6..abf2aea 100644 --- a/flake.lock +++ b/flake.lock @@ -7,11 +7,11 @@ ] }, "locked": { - "lastModified": 1771469470, - "narHash": "sha256-GnqdqhrguKNN3HtVfl6z+zbV9R9jhHFm3Z8nu7R6ml0=", + "lastModified": 1771881364, + "narHash": "sha256-A5uE/hMium5of/QGC6JwF5TGoDAfpNtW00T0s9u/PN8=", "owner": "nix-community", "repo": "disko", - "rev": "4707eec8d1d2db5182ea06ed48c820a86a42dc13", + "rev": "a4cb7bf73f264d40560ba527f9280469f1f081c6", "type": "github" }, "original": { @@ -22,11 +22,11 @@ }, "nixpkgs": { "locked": { - "lastModified": 1771369470, - "narHash": "sha256-0NBlEBKkN3lufyvFegY4TYv5mCNHbi5OmBDrzihbBMQ=", + "lastModified": 1771848320, + "narHash": "sha256-0MAd+0mun3K/Ns8JATeHT1sX28faLII5hVLq0L3BdZU=", "owner": "nixos", "repo": "nixpkgs", - "rev": "0182a361324364ae3f436a63005877674cf45efb", + "rev": "2fc6539b481e1d2569f25f8799236694180c0993", "type": "github" }, "original": { diff --git a/flake.nix b/flake.nix index 2308773..fd6d838 100644 --- a/flake.nix +++ b/flake.nix @@ -21,5 +21,11 @@ ./configuration.nix ]; }; + + devShells.x86_64-linux.default = let + pkgs = nixpkgs.legacyPackages.x86_64-linux; + in pkgs.mkShell { + packages = [ pkgs.nh ]; + }; }; } diff --git a/modules/caddy.nix b/modules/caddy.nix index 7c8c621..14e6635 100644 --- a/modules/caddy.nix +++ b/modules/caddy.nix @@ -12,8 +12,23 @@ root * /var/lib/acme/acme-challenge file_server } + handle /.well-known/matrix/server { + header Access-Control-Allow-Origin "*" + header Content-Type "application/json" + respond `{"m.server": "matrix.extremist.software:443"}` + } + handle /.well-known/matrix/client { + header Access-Control-Allow-Origin "*" + header Content-Type "application/json" + respond `{"m.homeserver": {"base_url": "https://matrix.extremist.software"}}` + } + handle /.well-known/matrix/support { + header Access-Control-Allow-Origin "*" + header Content-Type "application/json" + respond `{"admins": [{"matrix_id": "@jet:extremist.software","role": "admin"}]}` + } handle { - respond "Hi" + redir https://jetpham.com{uri} } ''; }; @@ -49,10 +64,17 @@ ''; }; + "ntfy.extremist.software" = { + extraConfig = '' + reverse_proxy localhost:2586 + ''; + }; + "matrix.extremist.software" = { extraConfig = '' - reverse_proxy /_matrix/* localhost:6167 - reverse_proxy /_synapse/client/* localhost:6167 + reverse_proxy /_matrix/* 127.0.0.1:8008 + reverse_proxy /_synapse/client/* 127.0.0.1:8008 + reverse_proxy /.well-known/matrix/* 127.0.0.1:8008 ''; }; }; diff --git a/modules/matrix.nix b/modules/matrix.nix index 3ba7954..9b45778 100644 --- a/modules/matrix.nix +++ b/modules/matrix.nix @@ -1,16 +1,52 @@ { config, pkgs, ... }: { - services.matrix-conduit = { + services.matrix-synapse = { enable = true; settings = { - global = { - server_name = "matrix.extremist.software"; - allow_registration = true; # Disable after creating first user - port = 6167; + server_name = "extremist.software"; + public_baseurl = "https://matrix.extremist.software"; + + listeners = [ + { + port = 8008; + bind_addresses = [ "127.0.0.1" ]; + type = "http"; + tls = false; + x_forwarded = true; + resources = [ + { + names = [ "client" "federation" ]; + compress = false; + } + ]; + } + ]; + + enable_registration = false; + registration_shared_secret = "extremist_software_admin_creation"; + macaroon_secret_key = config.mySecrets.matrixMacaroon; + database = { + name = "psycopg2"; + allow_unsafe_locale = true; + args = { + user = "matrix-synapse"; + database = "matrix-synapse"; + host = "/run/postgresql"; + cp_min = 5; + cp_max = 10; + }; }; }; }; - networking.firewall.allowedTCPPorts = [ 6167 8448 ]; + services.postgresql = { + enable = true; + ensureDatabases = [ "matrix-synapse" ]; + ensureUsers = [{ + name = "matrix-synapse"; + ensureDBOwnership = true; + }]; + }; } + diff --git a/modules/monitoring.nix b/modules/monitoring.nix index e7e2260..2fb7ab4 100644 --- a/modules/monitoring.nix +++ b/modules/monitoring.nix @@ -34,5 +34,28 @@ secret_key = config.mySecrets.grafanaSecret; }; }; + provision = { + enable = true; + datasources.settings.datasources = [ + { + name = "Prometheus"; + type = "prometheus"; + access = "proxy"; + url = "http://127.0.0.1:9090"; + isDefault = true; + } + ]; + dashboards.settings.providers = [ + { + name = "Node Exporter Full"; + options.path = "/etc/grafana-dashboards"; + } + ]; + }; + }; + + environment.etc."grafana-dashboards/node-exporter-full.json".source = pkgs.fetchurl { + url = "https://grafana.com/api/dashboards/1860/revisions/37/download"; + sha256 = "0qza4j8lywrj08bqbww52dgh2p2b9rkhq5p313g72i57lrlkacfl"; }; } diff --git a/modules/ntfy.nix b/modules/ntfy.nix new file mode 100644 index 0000000..a7a1407 --- /dev/null +++ b/modules/ntfy.nix @@ -0,0 +1,21 @@ +{ config, pkgs, ... }: + +{ + services.ntfy-sh = { + enable = true; + settings = { + base-url = "https://ntfy.extremist.software"; + listen-http = ":2586"; + behind-proxy = true; + auth-file = "/var/lib/ntfy-sh/user.db"; + auth-default-access = "deny-all"; + enable-login = true; + auth-users = [ + "jet:${config.mySecrets.ntfyAdminHash}:admin" + ]; + auth-access = [ + "*:up*:write-only" + ]; + }; + }; +} diff --git a/modules/searx.nix b/modules/searx.nix index 3881960..bca9cae 100644 --- a/modules/searx.nix +++ b/modules/searx.nix @@ -4,16 +4,28 @@ services.searx = { enable = true; package = pkgs.searxng; + redisCreateLocally = true; settings = { server = { port = 8082; bind_address = "127.0.0.1"; secret_key = config.mySecrets.searxKey; }; + search = { + request_timeout = 1.5; + }; + use_default_settings = { + engines = { + keep_only = [ + "google" + "wikipedia" + ]; + }; + }; + engines = [ + { name = "google"; engine = "google"; disabled = false; } + { name = "wikipedia"; engine = "wikipedia"; disabled = false; } + ]; }; }; - - # Inject secret via env vars or file substitution if possible - # Or use `environment.etc` to place config file if service allows. - # For now, simplistic setup. } diff --git a/secrets/secrets-scheme.nix b/secrets/secrets-scheme.nix index 25a43c4..1bb690e 100644 --- a/secrets/secrets-scheme.nix +++ b/secrets/secrets-scheme.nix @@ -29,5 +29,13 @@ with lib; type = types.str; description = "Grafana Secret Key for security"; }; + matrixMacaroon = mkOption { + type = types.str; + description = "Macaroon Secret Key for Matrix Synapse"; + }; + ntfyAdminHash = mkOption { + type = types.str; + description = "Bcrypt hash for ntfy admin user"; + }; }; } diff --git a/secrets/secrets.nix.example b/secrets/secrets.nix.example index 4b59392..a5d3e55 100644 --- a/secrets/secrets.nix.example +++ b/secrets/secrets.nix.example @@ -9,5 +9,7 @@ minecraftRcon = "changeme_rcon"; tailscaleKey = "tskey-auth-PLACEHOLDER"; sshPublicKey = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAA..."; + matrixMacaroon = "changeme_matrix_macaroon_secret_key"; + ntfyAdminHash = "changeme_bcrypt_hash_from_ntfy_user_hash"; }; }