diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..3f7c734 --- /dev/null +++ b/.editorconfig @@ -0,0 +1,13 @@ +# EditorConfig is awesome: https://editorconfig.org + +root = true + +[*] +end_of_line = lf +insert_final_newline = true +charset = utf-8 + +[*.nix] +indent_style = space +indent_size = 2 + diff --git a/.gitignore b/.gitignore index fef1ed0..58b0104 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,5 @@ +result + # Created by https://www.toptal.com/developers/gitignore/api/linux,windows,macos,vim,direnv # Edit at https://www.toptal.com/developers/gitignore?templates=linux,windows,macos,vim,direnv,nix diff --git a/README.md b/README.md index 629c2e3..1169c52 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,9 @@ +# Tarball + +```bash +nix build .#nixosConfigurations.matrix.config.system.build.image +``` + # HTTP Configure `berlin.ccc.de` web server to send federation traffic to the matrix server: @@ -5,22 +11,32 @@ Configure `berlin.ccc.de` web server to send federation traffic to the matrix se ```nginx server { hostname berlin.ccc.de; - location "/.well-known/matrix/server" { + location = /.well-known/matrix/server { default_type application/json; + add_header Access-Control-Allow-Origin "*"; return 200 '{"m.server":"matrix.berlin.ccc.de:443"}'; } + location = /.well-known/matrix/client { + default_type application/json; + add_header Access-Control-Allow-Origin "*"; + return 200 '{"m.homeserver": {"base_url": "https://matrix.berlin.ccc.de"}}'; + } } ``` # DNS -``` -_matrix-fed._tcp.matrix.berlin.ccc.de. IN SRV 10 0 443 matrix.berlin.ccc.de. -#_matrix._tcp.matrix.berlin.ccc.de. IN SRV 10 0 443 matrix.berlin.ccc.de. -#_matrix._tcp.berlin.ccc.de. IN SRV 10 0 443 matrix.berlin.ccc.de. -_matrix-fed._tcp.berlin.ccc.de. IN SRV 10 0 443 matrix.berlin.ccc.de. -matrix.berlin.ccc.de. IN A -matrix.berlin.ccc.de. IN AAAA +```dns +_matrix-fed._tcp.berlin.ccc.de. IN SRV 10 0 443 matrix.berlin.ccc.de. +_matrix-fed._tcp.berlin.ccc.de. IN SRV 10 0 443 matrix.berlin.ccc.de. +matrix.berlin.ccc.de. IN A 195.160.173.25 +matrix.berlin.ccc.de. IN AAAA 2001:678:760:cccb::25 +matrix.berlin.ccc.de. IN CAA 0 issue "letsencrypt.org;validationmethods=http-01" +matrix.berlin.ccc.de. IN CAA 0 iodef "mailto:caa@xengi.de" +matrix.berlin.ccc.de. IN SSHFP 1 1 f40e117b002957939a454070adbbafe42d6f5842 +matrix.berlin.ccc.de. IN SSHFP 1 2 8ba0c605a365ef5369e91c531dd86fabfe4ce6dbd5e8280093ec2672d67c329b +matrix.berlin.ccc.de. IN SSHFP 4 1 62d10fa57f8a1aa7469cd9b00621e4ce89261d91 +matrix.berlin.ccc.de. IN SSHFP 4 2 ca80a6685984da140ac850e4951fa31e70b616e87f62f46437af3bfd215af887 ``` # Bots @@ -33,3 +49,16 @@ register_new_matrix_user \ --password ``` +# Draupnir + +Remove rate limit for account: + +```bash +curl -X DELETE https://matrix.berlin.ccc.de/_synapse/admin/v1/users/@admin:berlin.ccc.de/override_ratelimit +``` +Set rate limit for account: + +```bash +curl -X POST -d '{"messages_per_second":0,"burst_count":0}' https://matrix.berlin.ccc.de/_synapse/admin/v1/users/@admin:berlin.ccc.de/override_ratelimit +``` + diff --git a/configuration.nix b/configuration.nix index f99d39a..0f7677a 100644 --- a/configuration.nix +++ b/configuration.nix @@ -9,6 +9,12 @@ { imports = [ (modulesPath + "/virtualisation/proxmox-lxc.nix") ]; + systemd.suppressedSystemUnits = [ + "dev-mqueue.mount" + "sys-kernel-debug.mount" + "sys-fs-fuse-connections.mount" + ]; + nix = { optimise = { automatic = true; @@ -17,18 +23,19 @@ settings = { auto-optimise-store = true; sandbox = false; + # Allow remote updates trusted-users = [ "root" "@wheel" - ]; # Allow remote updates + ]; experimental-features = [ "nix-command" "flakes" - ]; # Enable flakes + ]; }; gc = { automatic = true; - options = "--delete-older-then 14d"; + options = "--delete-older-than 14d"; }; }; @@ -42,13 +49,13 @@ proxmoxLXC = { manageNetwork = false; manageHostName = false; - privileged = true; + privileged = false; }; users.users.root = { packages = with pkgs; [ kitty # for terminfo - neofetch # for shits and giggles + fastfetch # for shits and giggles ]; openssh.authorizedKeys.keys = [ "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAICW1+Ml8R9x1LCJaZ8bIZ1qIV4HCuZ6x7DziFW+0Nn5T xengi@kanae_2022-12-09" @@ -62,9 +69,17 @@ }; networking = { + hostName = "matrix"; + domain = "berlin.ccc.de"; + nameservers = [ + "2606:4700:4700::1111#one.one.one.one" + "2620:fe::fe#dns.quad9.net" + ]; + useDHCP = false; useNetworkd = true; - nftables.enable = true; dhcpcd.enable = false; + nftables.enable = true; + tempAddresses = "disabled"; firewall = { enable = true; allowedTCPPorts = [ @@ -87,7 +102,6 @@ fstrim.enable = false; # Let Proxmox host handle fstrim openssh = { enable = true; - openFirewall = true; settings = { PermitEmptyPasswords = "no"; PermitRootLogin = "prohibit-password"; @@ -104,6 +118,10 @@ \/_/\/_/\/_/\/__/\/_/ \/__/ \/_/ \/_/\//\/_/ \/____/\/____/\/____/ \/___/ ''; }; + sshguard = { + enable = true; + services = [ "sshd" ]; + }; # Cache DNS lookups to improve performance resolved = { enable = true; @@ -125,6 +143,16 @@ enable = true; defaultEditor = true; }; + htop = { + enable = true; + }; + tmux = { + enable = true; + terminal = "screen-256color"; + shortcut = "a"; + newSession = true; + clock24 = true; + }; ssh.startAgent = true; }; @@ -136,7 +164,6 @@ renewInterval = "daily"; email = "acme@xengi.de"; group = "nginx"; - webroot = "/var/lib/acme/acme-challenge"; }; }; }; diff --git a/flake.lock b/flake.lock index b001316..811cfc3 100644 --- a/flake.lock +++ b/flake.lock @@ -68,16 +68,16 @@ }, "nixpkgs": { "locked": { - "lastModified": 1763622513, - "narHash": "sha256-1jQnuyu82FpiSxowrF/iFK6Toh9BYprfDqfs4BB+19M=", + "lastModified": 1764677808, + "narHash": "sha256-H3lC7knbXOBrHI9hITQ7modLuX20mYJVhZORL5ioms0=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "c58bc7f5459328e4afac201c5c4feb7c818d604b", + "rev": "1aab89277eb2d87823d5b69bae631a2496cff57a", "type": "github" }, "original": { "owner": "NixOS", - "ref": "nixos-25.05", + "ref": "nixos-25.11", "repo": "nixpkgs", "type": "github" } diff --git a/flake.nix b/flake.nix index 3fa8a5c..a0d506b 100644 --- a/flake.nix +++ b/flake.nix @@ -1,7 +1,7 @@ { description = "Matrix server for CCCB"; inputs = { - nixpkgs.url = "github:NixOS/nixpkgs/nixos-25.05"; + nixpkgs.url = "github:NixOS/nixpkgs/nixos-25.11"; #flake-utils.url = "github:numtide/flake-utils"; agenix = { url = "github:ryantm/agenix"; @@ -25,6 +25,12 @@ in { formatter.${system} = pkgs.nixfmt-tree; + apps.${system}.connect = { + type = "app"; + program = "${pkgs.writeShellScript "connect.sh" '' + ${pkgs.openssh}/bin/ssh root@matrix.berlin.ccc.de -L 3000:[::1]:3000 -L 9090:[::1]:9090 -N + ''}"; + }; devShells.${system}.default = pkgs.mkShell { packages = [ (agenix.packages.${system}.default) @@ -34,6 +40,7 @@ nixosConfigurations."matrix" = nixpkgs.lib.nixosSystem { #system = "x86_64-linux"; #pkgs = import nixpkgs { inherit system; }; + inherit system; modules = [ agenix.nixosModules.default { environment.systemPackages = [ (agenix.packages.${system}.default) ]; } @@ -51,12 +58,42 @@ owner = "root"; group = "root"; }; + matrix_registration_shared_secret = { + file = ./secrets/matrix_registration_shared_secret.age; + mode = "440"; + owner = "matrix-synapse"; + group = "matrix-synapse"; + }; + matrix_signing_key = { + file = ./secrets/matrix_signing_key.age; + mode = "440"; + owner = "matrix-synapse"; + group = "matrix-synapse"; + }; + grafana_secret_key = { + file = ./secrets/grafana_secret_key.age; + mode = "440"; + owner = "grafana"; + group = "grafana"; + }; + grafana_admin_password = { + file = ./secrets/grafana_admin_password.age; + mode = "440"; + owner = "grafana"; + group = "grafana"; + }; }; } ./configuration.nix + ./services/nginx.nix ./services/postgres.nix + ./services/synapse.nix + ./services/draupnir.nix + + ./services/prometheus.nix + ./services/grafana.nix ]; }; }; diff --git a/secrets/grafana_admin_password.age b/secrets/grafana_admin_password.age new file mode 100644 index 0000000..1ac13ca Binary files /dev/null and b/secrets/grafana_admin_password.age differ diff --git a/secrets/grafana_secret_key.age b/secrets/grafana_secret_key.age new file mode 100644 index 0000000..031c51f --- /dev/null +++ b/secrets/grafana_secret_key.age @@ -0,0 +1,17 @@ +age-encryption.org/v1 +-> ssh-ed25519 uH+n1w 55Lrc+d1ob+lncF+9PeowOUk6pfN5H8pYcKze8Yh9Ts +hrIsGn3VbmTatB41953JkzKpsFy1ClaDzV3dDDHd/mg +-> ssh-ed25519 EvLbWw Zvm46/ZMQa2bELLpS/sg/gUejfeh6HhF9C/hF4W5+Q4 +Y7ibiWUZAGJ3CLSa1n0qQ0EfYlXJ1TSIL/n/S6xxM2k +-> ssh-ed25519 dM+fLQ Y40HHJlJBSmrmiLU7uSr6M8GGxiIQ6MrLTBLHtx+cA8 +dQlUrZmO4WySeAyo1a7ZAd9r/uU1dCMdk72Wxr4Lu1s +-> ssh-ed25519 jxWM2Q 7/C5lcAq1AuuydbQPBD/hFmbXHyL6/lxqfAW8IDvm0g +Wj8GgA0/fhNPnLTUFMuBo/qvBMsx9f27nrS8BwLUHLo +-> ssh-ed25519 /yCUCg XUJ0s52LivXboJ4EeMGamFvzTlSfQKBB8GG3Hbv43Cw +SnWMJ9TnOjFLsHhXNusiT9OInmyICsrJVceVUEF4USA +-> ssh-ed25519 FGp51g qZrVsdh4binpAi42bk3s8PhykxkS76xY901grBeDyjk +Pneymp2y1kljGodCk/OIiBJeWNG86ZeXUwo3KqJ4AAE +-> ssh-ed25519 yoCmaA R4J9TeYunLSrLnbyz00VoKcGJNR84YLusoKGgxjuiCk +G+zmtvQaYWcVPwuD+jZKBcs0yzR9LSpCxjNOpt/hGQ8 +--- mXNr0c7WoNFuGQ2tPiwYpEJFYB+7S8VYrdKeSHwrhWU +8N ~ eݠ$JM]N=xI^f;&e9r4hy+G]^34<|8hOuE \ No newline at end of file diff --git a/secrets/matrix-registration-shared-secret.age b/secrets/matrix-registration-shared-secret.age deleted file mode 100644 index 533179a..0000000 Binary files a/secrets/matrix-registration-shared-secret.age and /dev/null differ diff --git a/secrets/matrix_registration_shared_secret.age b/secrets/matrix_registration_shared_secret.age new file mode 100644 index 0000000..67bf0e7 --- /dev/null +++ b/secrets/matrix_registration_shared_secret.age @@ -0,0 +1,18 @@ +age-encryption.org/v1 +-> ssh-ed25519 uH+n1w iJTC0uBAjAY8yR/2RUbHqrVlx+Lxo+biVre9vl2IeV0 +VjXPsBklJZ1jxnNlgl/GQS0aaMBjj4+UhIjoGGoBCkk +-> ssh-ed25519 EvLbWw NnI9yniKw2QMwzPh5jDQPUiv1XYHyo8fGpgJMyIslgs +vvVahqlbvOWozsBK/4fOMmH+IhUuBcOadK2rYiuYGgI +-> ssh-ed25519 dM+fLQ lkMOaDtiDHWFRJFTOejZEZLFiOv238xkeMP8ap7WJ1Y +VTJig9b1c8z7KGleyYChzoehjwy6uZ/bInBhY8vE1o0 +-> ssh-ed25519 jxWM2Q gpIbb13+QOC5fyA2QcTpB+DgrV3CgcESxRXZT/vWrQE +bVVxbpKfN1Uzky85kMabnDrl8/E1ZquS+FRFzuzujG8 +-> ssh-ed25519 /yCUCg yR0+oUP7sn60oufmJcUljTAeIGfAPm0+nQ2kMeIIlA4 +TCnXv2zhEJ77lpX4wyPsmdRhNb3brh/Hx69/bl8aVSk +-> ssh-ed25519 FGp51g OL/y1UueVo8L5L6KWU63h/kokeoM7tNiYjuHeHkupV4 +kY7cKDj9xMssTGNmSL+VWJbaaW4Bideb6ZHWQ2S8zLc +-> ssh-ed25519 yoCmaA mrzkQsx0MVJjcGp57WdU7cTqab0PsTLiZ/JcHrjnnEc +uoZqidxPeuwskj+6zyXzYA7umucbBuy8ImrcRXWFSZ0 +--- kXz0VBP8kJ0Ca11r6owy8QAKAyXw5PU00LLgnGQR/EA +A%zkqgPƒWHg@4 +ò{r胕vmm\&I`ϥ0)YL:NuYԄAg+F9M΋,drv?-"  \ No newline at end of file diff --git a/secrets/matrix_signing_key.age b/secrets/matrix_signing_key.age new file mode 100644 index 0000000..cebe8d5 --- /dev/null +++ b/secrets/matrix_signing_key.age @@ -0,0 +1,17 @@ +age-encryption.org/v1 +-> ssh-ed25519 uH+n1w 4o87n9J5BB5e/X5sQM+8HOczgSye/WijcvOrCUM6d3I +Ye8imH528eWpCJ7SSxf9eogBzoNYdYGfYHZaZLzUKB4 +-> ssh-ed25519 EvLbWw E8bQjHPE783T5Q6fYjCd4dlVGK5CgGUjHBn+tXz9Qmg +PQArA8KnQ2xB8JvCN0CNtBZZe0xiHf4p3cHwJ+qEzjw +-> ssh-ed25519 dM+fLQ fbA5v7Et6b11JIeDzl1d/Nff1FPNVT07ISL9ap4TehE +/SG8ePRf0GXrqT7bEvwpf2wa31J31d5Di2rgeQcdRwk +-> ssh-ed25519 jxWM2Q uClXpHlke1YRyJhye5twdSwUNI8JpQSz3eGkFEFHKGc +XF5DiSO4cZLIaLl04y2zmPguIpufcw+yAx7L8UbudV8 +-> ssh-ed25519 /yCUCg MDYtCl4FvqBLb/xC+7Rt3tYeQ2Mi5fbOWl2aKdPSJQI +8iQSqlMMj+VCOBBKcyTvS3p4lJsN5h6MPDM3mnaWNlE +-> ssh-ed25519 FGp51g 6lALHIQk3kpc/9rrXEwuG2HXAHGP4sGBTZNO50jMRkI ++GbZjITsBCDzOPEHgp945knlYlsYC8ObNbUQmA/DsME +-> ssh-ed25519 yoCmaA G2n3ZtZ5gyDSABy0wgyy9feImhprTFOZpEIwNJLJjBs +P99b4Q1ghNW9slWE9wVGgQX9j9vDZUP6Lumnwc+EWw4 +--- NCjPsR2/qrlWPaHya7ucG9xFuPAMVwJjSCC40HixNhY +(E`%Fv.ԧ-bGzSʴHjO{3EchnlYs'LAI8NbnϽoe"jX gp]e `Q2ϛ$ \ No newline at end of file diff --git a/secrets/pushover_app_token.age b/secrets/pushover_app_token.age index 1fe3ef2..7a675c7 100644 --- a/secrets/pushover_app_token.age +++ b/secrets/pushover_app_token.age @@ -1,17 +1,17 @@ age-encryption.org/v1 --> ssh-ed25519 uH+n1w EMOmmGlZ2rnqAaqcHHQ9conaa8YH/3TBFRpUlssNuGw -jyXUxitYHc/vNpab9winTCqCWBQYtmDGdZortYYlMAI --> ssh-ed25519 EvLbWw K+NOnJui0ASn3lPsP1xZ2X4fdfSBQ1woOnD3c4Zk/xE -FDYbrduCSWvo5NSzyAgwNa7tU4c3r7Fcoizfph3fqF4 --> ssh-ed25519 dM+fLQ Ji3jw0haPByWaQ68rHxFmj1xjSG9EVfyYTtZZpAFYFg -cHPTEfHWjwIVUBaDB85vGCfatd4Wtuq7QT3mIcdaF7M --> ssh-ed25519 jxWM2Q ZTbjGk18JyognAJwUQIfwy3YlHALXsfyUICiGrG/ij0 -/eyD/UoQZ33s2geZ6212ZMOLhyzKCbryR1HDYW02dfg --> ssh-ed25519 /yCUCg cM7meOfoTt4UlsODZeSrLFkMtIAInASm0uDrMHDDnXY -LCdZCjhp+/i7bGkXhHJ4Jv6C2ikcPsL3i7W/tap7AMs --> ssh-ed25519 FGp51g zZFF/qLQDbKpkBQiEJJQrtoJVxrdrWeqziwNq/rP2jY -jJ/ivlZIfn6/oh7yZSCNmQGikvwdSVAzxkLj/tc2Eys --> ssh-ed25519 alMFaA y5NuhEOK3lijncBscuSCfOTpepiIkAYW/W5kG+wscRE -a/z+2jHk1ERmNXFv+h1B7BpavjbemqOON5ruHP5U6dY ---- 6e7V59HtYHOi9koxczT0hwL6wk1/QkmDOkUGGlZCmo8 -[5̓rl*X*_'-`|3A3N> \ No newline at end of file +-> ssh-ed25519 uH+n1w CpismpignW6KyCMQzoag+R8oimzZHES+0yGksCcUMho +sDwfn3wJrFC9IDenrh8eXgfHoqTlJNb+vyF8xyJrjZ8 +-> ssh-ed25519 EvLbWw 7HOXQ9JHK0wRtmW8wipPQoQU7Hl2mzuEJR3yhSQ8v1M +ju2NYTnCUapa9XIq9mF1ydItVa2GSE/aBhep8+4WxqQ +-> ssh-ed25519 dM+fLQ gTVxxgX+4FROshLyPkU98DWcXg0vsra/37JzS8tSRGM +454qvkc89sxBQeP/xtTA/g6YsKnPYkpFD1JQshCcWQ0 +-> ssh-ed25519 jxWM2Q UNp42zqLcZT1E3/CfzyNdE74gQJmq1NcLjj83m0pAg8 +HghuogwHIJ1PTYbdtzhSREOxBoItUAb0yA9aMff1Ha4 +-> ssh-ed25519 /yCUCg nDHhp+yPDpRKlpJSx5I3BR4R3My1ivoCNbSCGeFM8lw +JCfjM/9x3vFdOtQAQDGvdPhUnCD3ztIrK8BN9nafnKI +-> ssh-ed25519 FGp51g WJA1Z5O3yxtypMLG9m4l0mjQrw6XMe8/JDvY4QGFgRQ +TlzGrdk3A0tNyY0ZkDORqe90x7Jnrna3emCXOHIIg4I +-> ssh-ed25519 yoCmaA BCwjqZS92x24+UThVDbEqPopfQnKthAXkOA1uxQjiDo +zX+u2YP/lXJOvPvG30HLNAOLsJv7QT5IU9d3w6aSXeU +--- I9YP9v5qBtGoN7epTH7gLqFqFPml3THjnE0y7H5f17g +giyT`!|80!YȤMy` \ No newline at end of file diff --git a/secrets/pushover_user_key.age b/secrets/pushover_user_key.age index 1fe3ef2..828cd88 100644 --- a/secrets/pushover_user_key.age +++ b/secrets/pushover_user_key.age @@ -1,17 +1,17 @@ age-encryption.org/v1 --> ssh-ed25519 uH+n1w EMOmmGlZ2rnqAaqcHHQ9conaa8YH/3TBFRpUlssNuGw -jyXUxitYHc/vNpab9winTCqCWBQYtmDGdZortYYlMAI --> ssh-ed25519 EvLbWw K+NOnJui0ASn3lPsP1xZ2X4fdfSBQ1woOnD3c4Zk/xE -FDYbrduCSWvo5NSzyAgwNa7tU4c3r7Fcoizfph3fqF4 --> ssh-ed25519 dM+fLQ Ji3jw0haPByWaQ68rHxFmj1xjSG9EVfyYTtZZpAFYFg -cHPTEfHWjwIVUBaDB85vGCfatd4Wtuq7QT3mIcdaF7M --> ssh-ed25519 jxWM2Q ZTbjGk18JyognAJwUQIfwy3YlHALXsfyUICiGrG/ij0 -/eyD/UoQZ33s2geZ6212ZMOLhyzKCbryR1HDYW02dfg --> ssh-ed25519 /yCUCg cM7meOfoTt4UlsODZeSrLFkMtIAInASm0uDrMHDDnXY -LCdZCjhp+/i7bGkXhHJ4Jv6C2ikcPsL3i7W/tap7AMs --> ssh-ed25519 FGp51g zZFF/qLQDbKpkBQiEJJQrtoJVxrdrWeqziwNq/rP2jY -jJ/ivlZIfn6/oh7yZSCNmQGikvwdSVAzxkLj/tc2Eys --> ssh-ed25519 alMFaA y5NuhEOK3lijncBscuSCfOTpepiIkAYW/W5kG+wscRE -a/z+2jHk1ERmNXFv+h1B7BpavjbemqOON5ruHP5U6dY ---- 6e7V59HtYHOi9koxczT0hwL6wk1/QkmDOkUGGlZCmo8 -[5̓rl*X*_'-`|3A3N> \ No newline at end of file +-> ssh-ed25519 uH+n1w HTqQauCW1UsrG02sXuh6+d81ccDXxuICmLgXp+EJxUE +wRo53sJ4nECI17A1QHJPycecvv9Vv8e0J+PS/sAyqIw +-> ssh-ed25519 EvLbWw RRqLwCd1NgUCRXcEF5k3+Gp3xeI0wscX8dYfYdisJTU +u2m4/DpD16jgO0mDu09/CekJK/uAS3ufQcQYDsay8AA +-> ssh-ed25519 dM+fLQ SgDFIxeGQxv72Bo+hgxFRBnW6bD0pAoP2Tqz4D3d/Ec +Emi7INrfeimLilF/Dtb2twmgedtyCq+Fp/sTB+NeBtE +-> ssh-ed25519 jxWM2Q 27h3w7OD9Mv8Pd4O1eAc6e2pzRD6R1TPeyALnzh2r3A +PvRdyDvHYMEEhGobaZPsNl80hcfMX4QBJI0Xmt/QXds +-> ssh-ed25519 /yCUCg SIKJiDq+ibPUOQjcjMCFuH53LhBjKjcrb9k3DZs3xQM +ZeHS04Pcdykau8AHQr/U1IAmd4j15CZvSGJ8sC3H3po +-> ssh-ed25519 FGp51g VIF1TFzuPNVhEjF3jnBpte9m3VF1Z7IaHrvO+3Rr9i0 +QszHp1w4AxfqVr2/h9RU546sFyik6DTSg0qY9ItZtCU +-> ssh-ed25519 yoCmaA cZd7lZ4MAvBqnEgLhk1cJAgvbI7lR4zmXcLla3GKoUE +s4rWNU4yFRdnTfDLVAG6JupNe7PyVx3wZKaOKsycff0 +--- n/y1v04doS7QVo+ZepIgG3YBMXcaKm4h9y3wPMjeupU +Gƶj!!YA'cF=XЌ!YUWٞ \ No newline at end of file diff --git a/secrets/secrets.nix b/secrets/secrets.nix index 01a4cec..4329c66 100644 --- a/secrets/secrets.nix +++ b/secrets/secrets.nix @@ -14,11 +14,14 @@ let nyu ]; - _matrix = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIM7AZkepRXoY+DJeSLOU+GR60S62p6+0X/PDeEUZ0yHx root@matrix"; + _matrix = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIApAkkhHLj918co/wUGuyW8WCPYHxsNM4uo32XDEu7VV root@matrix"; in { - "matrix-registration-shared-secret.age".publicKeys = users ++ [ _matrix ]; "matrix_admin_password.age".publicKeys = users; + "matrix_signing_key.age".publicKeys = users ++ [ _matrix ]; + "matrix_registration_shared_secret.age".publicKeys = users ++ [ _matrix ]; "pushover_app_token.age".publicKeys = users ++ [ _matrix ]; "pushover_user_key.age".publicKeys = users ++ [ _matrix ]; + "grafana_admin_password.age".publicKeys = users ++ [ _matrix ]; + "grafana_secret_key.age".publicKeys = users ++ [ _matrix ]; } diff --git a/services/draupnir.nix b/services/draupnir.nix new file mode 100644 index 0000000..8564d39 --- /dev/null +++ b/services/draupnir.nix @@ -0,0 +1,16 @@ +{ config, ... }: + +{ + services.draupnir = { + enable = false; + settings = { + homeserverUrl = "https://matrix.berlin.ccc.de"; + managementRoom = "!ZYWNuaQBkkenNklCSm:matrix.org"; # #cccb-moderators:berlin.ccc.de + autojoinOnlyIfManager = true; + recordIgnoredInvites = true; + roomStateBackingStore.enabled = true; + displayReports = true; + }; + secrets.accessToken = config.age.secrets.draupnir_access_token.path; + }; +} diff --git a/services/grafana.nix b/services/grafana.nix new file mode 100644 index 0000000..b14e43c --- /dev/null +++ b/services/grafana.nix @@ -0,0 +1,58 @@ +{ config, ... }: + +# Dashboards: +# - Synapse: https://github.com/element-hq/synapse/tree/master/contrib/grafana + +{ + services = { + grafana = { + enable = true; + settings = { + server.http_addr = "::1"; + database = { + type = "postgres"; + name = "grafana"; + user = "grafana"; + host = "/run/postgresql"; + }; + security = { + secret_key = "$__file{${config.age.secrets.grafana_secret_key.path}}"; + admin_user = "xengi"; + admin_password = "$__file{${config.age.secrets.grafana_admin_password.path}}"; + admin_email = "grafana@xengi.de"; + }; + analytics = { + reporting_enabled = false; + feedback_links_enabled = false; + }; + }; + provision = { + enable = true; + datasources.settings.datasources = [ + { + name = "Prometheus"; + type = "prometheus"; + url = "http://${config.services.prometheus.listenAddress}:${toString config.services.prometheus.port}"; + jsonData = { + httpMethod = "GET"; + prometheusType = "Prometheus"; + cacheLevel = "High"; + }; + } + ]; + }; + }; + + postgresql = { + ensureUsers = [ + { + name = config.services.grafana.settings.database.user; + ensureDBOwnership = true; + } + ]; + ensureDatabases = [ + config.services.grafana.settings.database.name + ]; + }; + }; +} diff --git a/services/nginx.nix b/services/nginx.nix index b334e5c..eff02e6 100644 --- a/services/nginx.nix +++ b/services/nginx.nix @@ -4,41 +4,41 @@ let fqdn = "matrix.berlin.ccc.de"; in { + users.users.nginx.extraGroups = [ "acme" ]; + services.nginx = { enable = true; - package = pkgs.nginxQuic; - resolver.addresses = ["[2606:4700:4700::1111]" "[2620:fe::fe]" "1.1.1.1" "9.9.9.9"]; + resolver.addresses = [ + "[2606:4700:4700::1111]" + "[2620:fe::fe]" + "1.1.1.1" + "9.9.9.9" + ]; statusPage = true; # http://127.0.0.1/nginx_status sslProtocols = "TLSv1.3"; recommendedTlsSettings = true; recommendedOptimisation = true; - recommendedZstdSettings = true; recommendedGzipSettings = true; recommendedBrotliSettings = true; virtualHosts."${fqdn}" = { + default = true; quic = true; kTLS = true; forceSSL = true; - useACMEHost = fqdn; + enableACME = true; locations = { - "/.well-known/matrix/client" = { - return = "200 '{\"m.homeserver\": {\"base_url\": \"https://matrix.berlin.ccc.de\"}}'"; + #"/.well-known/acme-challenge".root = config.security.acme.defaults.webroot; + "/".return = "418 \"🫖\""; + "~ ^(/_matrix|/_synapse/client)" = { + recommendedProxySettings = true; + proxyPass = "http://[::1]:8008"; extraConfig = '' - default_type application/json; - add_header Access-Control-Allow-Origin "*"; + client_max_body_size 64M; + proxy_set_header X-Request-ID $request_id; + proxy_http_version 1.1; ''; }; - "/" = { - recommendedProxySettings = true; - proxyPass = "unix:/run/matrix-synapse.sock"; - }; }; - extraConfig = '' - ''; }; }; - - security.acme.certs."${fqdn}" = { - reloadServices = ["nginx"]; - }; } diff --git a/services/postgres.nix b/services/postgres.nix index 2c78756..8753953 100644 --- a/services/postgres.nix +++ b/services/postgres.nix @@ -1,15 +1,12 @@ -{ config, ... }: +{ ... }: { services.postgresql = { enable = true; enableJIT = true; - ensureUsers = [ - { - name = config.services.matrix-synapse.settings.database.args.user; - ensureDBOwnership = true; - } + initdbArgs = [ + "--locale=C" + "--encoding=UTF8" ]; - ensureDatabases = [ config.services.matrix-synapse.settings.database.args.database ]; }; } diff --git a/services/prometheus.nix b/services/prometheus.nix new file mode 100644 index 0000000..2c56280 --- /dev/null +++ b/services/prometheus.nix @@ -0,0 +1,79 @@ +{ config, pkgs, lib, ... }: + +{ + services.prometheus = { + enable = true; + retentionTime = "14d"; + listenAddress = "[::1]"; + exporters = { + node = { + enable = true; + listenAddress = config.services.prometheus.listenAddress; + }; + #nginx = {}; + #postgres = {}; + }; + scrapeConfigs = [ + { + job_name = "synapse"; + scrape_interval = "15s"; + static_configs = [ + { + targets = lib.pipe config.services.matrix-synapse.settings.listeners [ + (lib.filter (l: l.type == "metrics")) + builtins.head + (l: [ "[${builtins.head l.bind_addresses}]:${toString l.port}" ]) + ]; + } + ]; + } + { + job_name = "node"; + scrape_interval = "15s"; + static_configs = [ + { targets = [ "${config.services.prometheus.exporters.node.listenAddress}:${toString config.services.prometheus.exporters.node.port}" ]; } + ]; + } + ]; + ruleFiles = [ + # https://github.com/element-hq/synapse/tree/master/contrib/prometheus + (pkgs.writeText "prom-synapse-rules.yaml" '' + groups: + - name: synapse + rules: + - record: 'synapse_federation_client_sent' + labels: + type: "EDU" + expr: 'synapse_federation_client_sent_edus_total + 0' + - record: 'synapse_federation_client_sent' + labels: + type: "PDU" + expr: 'synapse_federation_client_sent_pdu_destinations_count_total + 0' + - record: 'synapse_federation_client_sent' + labels: + type: "Query" + expr: 'sum(synapse_federation_client_sent_queries) by (job)' + - record: 'synapse_federation_server_received' + labels: + type: "EDU" + expr: 'synapse_federation_server_received_edus_total + 0' + - record: 'synapse_federation_server_received' + labels: + type: "PDU" + expr: 'synapse_federation_server_received_pdus_total + 0' + - record: 'synapse_federation_server_received' + labels: + type: "Query" + expr: 'sum(synapse_federation_server_received_queries) by (job)' + - record: 'synapse_federation_transaction_queue_pending' + labels: + type: "EDU" + expr: 'synapse_federation_transaction_queue_pending_edus + 0' + - record: 'synapse_federation_transaction_queue_pending' + labels: + type: "PDU" + expr: 'synapse_federation_transaction_queue_pending_pdus + 0' + '') + ]; + }; +} diff --git a/services/synapse.nix b/services/synapse.nix index 3e7e9b8..e0fa15e 100644 --- a/services/synapse.nix +++ b/services/synapse.nix @@ -4,45 +4,81 @@ let domain = "berlin.ccc.de"; in { - services.matrix-synapse = { - enable = false; - settings = { - server_name = domain; - public_baseurl = "https://matrix.${domain}:443/"; - #signing_key_path = config.age.secrets.signing_key.path; # "/var/lib/matrix-synapse/homeserver.signing.key" - database.name = "psycopg2"; - listeners = [ + services = { + matrix-synapse = { + enable = true; + settings = { + server_name = domain; + public_baseurl = "https://matrix.${domain}:443/"; + # "/var/lib/matrix-synapse/homeserver.signing.key" + signing_key_path = config.age.secrets.matrix_signing_key.path; + registration_shared_secret_path = config.age.secrets.matrix_registration_shared_secret.path; + database = { + name = "psycopg2"; + args = { + user = "matrix-synapse"; + database = "matrix-synapse"; + }; + }; + listeners = [ + { + type = "http"; + tls = false; + x_forwarded = true; + port = 8008; + bind_addresses = [ "::1" ]; + #request_id_header = "X-Request-ID"; + resources = [ + { + compress = false; + names = [ + "client" + "federation" + ]; + } + ]; + } + { + type = "metrics"; + tls = false; + port = 9009; + bind_addresses = [ "::1" ]; + resources = [ + { + compress = false; + names = [ "metrics" ]; + } + ]; + } + ]; + enable_metrics = true; + dynamic_thumbnails = true; + max_upload_size = "128M"; + max_image_pixels = "64M"; + + retention = { + enabled = true; + default_policy = { + min_lifetime = "1d"; + max_lifetime = "1y"; + }; + allowed_lifetime_min = "1d"; + allowed_lifetime_max = "1y"; + }; + }; + enableRegistrationScript = true; + }; + + postgresql = { + ensureUsers = [ { - path = "/run/matrix-synapse.sock"; - x_forwarded = true; - resources = [ - { - compress = false; - names = [ - "client" - "federation" - ]; - } - ]; + name = config.services.matrix-synapse.settings.database.args.user; + ensureDBOwnership = true; } ]; - dynamic_thumbnails = true; - max_upload_size = "128M"; - max_image_pixels = "64M"; - - retention = { - enabled = true; - default_policy = { - min_lifetime = "1d"; - max_lifetime = "1y"; - }; - allowed_lifetime_min = "1d"; - allowed_lifetime_max = "1y"; - }; + ensureDatabases = [ + config.services.matrix-synapse.settings.database.args.database + ]; }; - extraConfigFiles = [ - config.age.secrets.matrix-registration-shared-secret.path - ]; - enableRegistrationScript = true; }; }