commit 0692663ee842e266a24ff97830ef33efe77bb4c0
parent 25ac1cfd0cce6266a85f61118db044c50d3cc935
Author: Katja (zaphyra) <git@ctu.cx>
Date: Tue, 27 May 2025 00:05:35 +0200
parent 25ac1cfd0cce6266a85f61118db044c50d3cc935
Author: Katja (zaphyra) <git@ctu.cx>
Date: Tue, 27 May 2025 00:05:35 +0200
config/nixos/modules/websites: add `fedi.ctu.cx` (and `ctu.cx`) (and enable on host `novus`)
4 files changed, 286 insertions(+), 16 deletions(-)
A
|
204
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
diff --git a/config/nixos/modules/websites/ctu.cx.nix b/config/nixos/modules/websites/ctu.cx.nix @@ -0,0 +1,42 @@ +{ + povSelf, + hostConfig, + config, + lib, + dnsNix, + ... +}: + +let + inherit (lib) types; + cfg = lib.getAttrFromPath povSelf config; + +in +{ + + options = { + enable = { + type = types.bool; + default = false; + }; + domain = { + type = types.str; + default = "ctu.cx"; + }; + }; + + config = lib.mkIf cfg.enable { + dns.zones."${cfg.domain}" = + dnsNix.combinators.host hostConfig.networking.ip4Address hostConfig.networking.ip6Address; + + services.nginx = { + enable = true; + virtualHosts."${cfg.domain}" = { + useACMEHost = "${config.networking.fqdn}"; + forceSSL = true; + kTLS = true; + }; + }; + }; + +}
diff --git a/config/nixos/modules/websites/fedi.ctu.cx.nix b/config/nixos/modules/websites/fedi.ctu.cx.nix @@ -0,0 +1,204 @@ +{ + name, + povSelf, + hostConfig, + config, + pkgs, + lib, + ... +}: + +let + inherit (lib) types; + cfg = lib.getAttrFromPath povSelf config; + cfgWebsites = lib.getAttrFromPath (lib.remove name povSelf) config; + +in +{ + + options = { + enable = { + type = types.bool; + default = false; + }; + domain = { + type = types.str; + default = "ctu.cx"; + }; + subdomain = { + type = types.str; + default = "fedi"; + }; + }; + + config = lib.mkIf cfg.enable { + assertions = [ + { + assertion = cfgWebsites."${cfg.domain}".enable == true; + message = "The option 'modules.websites.\"${cfg.domain}\"' must be enabled in order to use this module."; + } + ]; + + dns.zones."${cfg.domain}".subdomains."${cfg.subdomain}".CNAME = [ "${config.networking.fqdn}." ]; + + sops.secrets = { + "resticPasswords/gotosocial" = { }; + "environments/gotosocial" = { + restartUnits = [ "gotosocial.service" ]; + }; + }; + + systemd.tmpfiles.settings.gotosocial = { + "/var/lib/gotosocial/storage".d = { + user = config.modules.services.gotosocial.user; + group = config.modules.services.gotosocial.group; + mode = "750"; + age = "-"; + }; + }; + + modules.services = { + resticBackup.paths = { + gotosocial = { + enable = true; + user = config.modules.services.gotosocial.user; + passwordFile = config.sops.secrets."resticPasswords/gotosocial".path; + sqliteDatabases = [ + (lib.mkIf ( + config.modules.services.gotosocial.settings.db-type == "sqlite" + ) config.modules.services.gotosocial.settings.db-address) + ]; + paths = [ + (lib.mkIf ( + config.modules.services.gotosocial.settings.storage-backend == "local" + ) config.modules.services.gotosocial.settings.storage-local-base-path) + "${config.modules.services.gotosocial.stateDir}/backup.json" + ]; + runBeforeBackup = ''${pkgs.gotosocial}/bin/gotosocial --config-path /etc/gotosocial.yaml admin export --path ${config.modules.services.gotosocial.stateDir}/backup.json''; + }; + }; + gotosocial = { + enable = true; + group = config.services.nginx.group; + environmentFile = config.sops.secrets."environments/gotosocial".path; + settings = { + protocol = lib.mkDefault "https"; + + bind-address = lib.mkDefault "[::1]"; + port = lib.mkDefault 8085; + + trusted-proxies = lib.mkDefault [ + "::1/128" + "172.17.0.0/24" + ]; + + db-type = lib.mkDefault "sqlite"; + db-address = lib.mkDefault "${config.modules.services.gotosocial.stateDir}/db.sqlite"; + + storage-backend = lib.mkDefault "local"; + storage-local-base-path = "${config.modules.services.gotosocial.stateDir}/storage"; + + host = "${cfg.subdomain}.${cfg.domain}"; + account-domain = cfg.domain; + + landing-page-user = "katja"; + + accounts-allow-custom-css = true; + accounts-registration-open = false; + + instance-expose-peers = true; + instance-expose-suspended = true; + instance-expose-suspended-web = true; + + instance-languages = [ + "de" + "en-us" + ]; + + media-local-max-size = "50MiB"; + media-remote-max-size = "50MiB"; + + media-remote-cache-days = 3; + media-cleanup-from = "01:00"; + }; + }; + }; + + services.nginx = { + appendHttpConfig = '' + proxy_cache_path /var/cache/nginx keys_zone=gotosocial_ap_public_responses:10m inactive=1w; + ''; + virtualHosts = + { + "${config.modules.services.gotosocial.settings.host}" = { + useACMEHost = lib.mkDefault "${config.networking.fqdn}"; + forceSSL = lib.mkDefault true; + kTLS = lib.mkDefault true; + locations = { + "/" = { + proxyPass = "http://${toString config.modules.services.gotosocial.settings.bind-address}:${toString config.modules.services.gotosocial.settings.port}"; + proxyWebsockets = true; + }; + + "~ /.well-known/(webfinger|host-meta)$" = { + proxyPass = "http://${toString config.modules.services.gotosocial.settings.bind-address}:${toString config.modules.services.gotosocial.settings.port}"; + extraConfig = '' + proxy_cache gotosocial_ap_public_responses; + proxy_cache_background_update on; + proxy_cache_key $scheme://$host$uri$is_args$query_string; + proxy_cache_valid 200 10m; + proxy_cache_use_stale error timeout updating http_500 http_502 http_503 http_504 http_429; + proxy_cache_lock on; + add_header X-Cache-Status $upstream_cache_status; + ''; + }; + + "~ ^\/users\/(?:[a-z0-9_\.]+)\/main-key$" = { + proxyPass = "http://${toString config.modules.services.gotosocial.settings.bind-address}:${toString config.modules.services.gotosocial.settings.port}"; + extraConfig = '' + proxy_cache gotosocial_ap_public_responses; + proxy_cache_background_update on; + proxy_cache_key $scheme://$host$uri; + proxy_cache_valid 200 604800s; + proxy_cache_use_stale error timeout updating http_500 http_502 http_503 http_504 http_429; + proxy_cache_lock on; + + add_header X-Cache-Status $upstream_cache_status; + ''; + }; + + "/assets/".extraConfig = '' + alias ${config.modules.services.gotosocial.package}/share/web/assets/; + autoindex off; + expires max; + add_header Cache-Control "public, immutable"; + ''; + }; + }; + } + // ( + if + ( + config.modules.services.gotosocial.settings.account-domain + != config.modules.services.gotosocial.settings.host + ) + then + { + "${config.modules.services.gotosocial.settings.account-domain}" = { + locations = { + "= /.well-known/host-meta".extraConfig = + "return 301 https://${config.modules.services.gotosocial.settings.host}$request_uri;"; + "= /.well-known/webfinger".extraConfig = + "return 301 https://${config.modules.services.gotosocial.settings.host}$request_uri;"; + "= /.well-known/nodeinfo".extraConfig = + "return 301 https://${config.modules.services.gotosocial.settings.host}$request_uri;"; + }; + }; + } + else + { } + ); + }; + }; + +}
diff --git a/hosts/novus/default.nix b/hosts/novus/default.nix @@ -13,26 +13,37 @@ }; networking = { - ip4IsPrivate = false; - ip4Address = "194.36.145.49"; + ip4IsPrivate = false; + ip4Address = "194.36.145.49"; ip4PrefixLength = 22; defaultGateway4 = "194.36.144.1"; - ip6IsPrivate = false; - ip6Address = "2a03:4000:4d:5e::1"; + ip6IsPrivate = false; + ip6Address = "2a03:4000:4d:5e::1"; ip6PrefixLength = 64; defaultGateway6 = "fe80::1"; }; configuration = - { config, pkgs, ... }: { + inputs, + config, + pkgs, + ... + }: + { + + boot.initrd.systemd.emergencyAccess = true; + boot.kernelPackages = pkgs.linuxPackages_latest; - boot.initrd.systemd.emergencyAccess = true; - boot.kernelPackages = pkgs.linuxPackages_latest; + sops.secrets = { + "resticEnv/novus" = { + sopsFile = inputs.self.sopsSecrets.common; + }; + }; - modules = { - filesystem.rootDisk = { + modules = { + filesystem.rootDisk = { enable = true; encrypt = true; type = "ext4"; @@ -53,10 +64,23 @@ }; }; + services = { + resticBackup.targets = { + novus = { + repository = "rest:https://restic.novus.infra.zaphyra.eu"; + environmentFile = config.sops.secrets."resticEnv/novus".path; + }; + }; + }; + websites = { "restic.novus.infra.zaphyra.eu".enable = true; "flauschehorn.zaphyra.eu".enable = true; "ip.zaphyra.eu".enable = true; + + #old fedi-instance + "ctu.cx".enable = true; + "fedi.ctu.cx".enable = true; }; users.katja.enable = true;
diff --git a/secrets/novus.yaml b/secrets/novus.yaml @@ -1,11 +1,11 @@ acmeTSIGKey: ENC[AES256_GCM,data:a34wyBRoW3Mo6Mep66wi99xfuZLecCrDgpH4EFy4T8PpHYnhR/pLubXVzZpwouKrC+g0E+3hyBR6Bmc/1arKmQ==,iv:938iHOR2NwCjZEBQpjhnCEG11DcxtfeBLGmRh06LaRg=,tag:uhMkBrc9G7inEBg7ddWvZg==,type:str] resticServerHtpasswd: ENC[AES256_GCM,data:cjva4AXQw37feKs1wFl5o0pLJjfkW5sh5U8jZ2gWUYBlMQgBmdhYAuUwcR8jvismBafL6gSW4esvxPnBpcZC5yTP7TwQh/f18pouaTVH,iv:LJkvhOgTNt065K5kQNlP6zQUTK0bqd9smTIt7meUA4c=,tag:CkzAqsoKOXIdtTgqdOxORA==,type:str] rcloneConfig: ENC[AES256_GCM,data:ELWBEt1akcyQkL+bZN6HfkSvaARMEVKqwN0gZuzJv7zrdnd35nLJu/aAU2tSqsuPK8T7B+J3VqpLYuKZALHTOwm6dzOLnM8tBuBEO/Qy0Fb2wzj/U4/LHo1XBwAZC4pO4seyWi07IxfiafcPQ2YdZyoJcGzLXnmpOCTOn3C09C6foaIaOGBlh8weBIyKpCNM9YhjljyID9MoWFAc3+PCuASrHssSapTSX8gIgylgD37YiFY2s6ICZKCsa+TxXF6DD2qfnnf3zGNpozTMcH4bThaGB2BcqUPspylApAEIbig4jxFb/jb7PLy63E5WGpsskGYF5CT3zbzaNgYzaFZZdlZcBUcX3BUU37qXPAaRZg2f7NJopAdFlG0u8SPqetIrOikwSdL157+0WuixhPqHFC0S0erQ3fSSrXyhbhrt5kG+MO1LK34CS1aB/UZEnd2LYIJtGscH9QQMd6J7I1pW3Lgq6onS5/hE77G5mGXAKiVdLKu9E65C6X1PnUl2PwkvnioAPtMJ6bfzELEdfuD79kPq9P4HnDG1geP7Sv+BUCKzdZ+mTct7LNqXlA7hd18tAgYvt1LFumq7KV0lX3JqUGZdqSrhDJU6SYudN/BYRaPrvWCabCxJ1HzjM6lKynEuXuq41Y9RrEaekJv4/yJA33x5G+rq2CPnQEHjMu05rwXRGiCrOHCiPtPioxPFvAn5nZsZruPCZII8hKhC8Bno/aAgnVA3Ud29Ddvl9a3Rh8XCTKXpeg==,iv:Zq7DGFKxBw5tmEXXK8W7Aun1Gk78iwgju6NJJZcwBe0=,tag:3a0hn76gMiEX1imuQT0qaQ==,type:str] +resticPasswords: + gotosocial: ENC[AES256_GCM,data:e2r/4Ok5XIZgHy+vGkNYVDxidRGCt8ZuwkNZsPTvta4=,iv:yQnBoEXPQ9XxrohIFCZgQo7gG6m/20lTMQBiGmR94rw=,tag:MSvgOsNs1X5Ij1rwf+xsZA==,type:str] +environments: + gotosocial: "" sops: - kms: [] - gcp_kms: [] - azure_kv: [] - hc_vault: [] age: - recipient: age1tud4lvpmpx5nqceyp09ls9ej8l80zlh29d8cpjxcajfnnyy85fvqs63snm enc: | @@ -16,8 +16,8 @@ sops: N0dBZExjdWpSVDJmYlFmOHluZEJUWkUKhkWONhK0LiVhAY+pdemXOBHtBALV65ZP EClQs/bns2HUF4E5Lc6mv8WvogFNhm/TLGYX/sOWSvAYExRNiHtssQ== -----END AGE ENCRYPTED FILE----- - lastmodified: "2025-05-22T07:59:22Z" - mac: ENC[AES256_GCM,data:KVDR3eVJJM8y/aD3+EFGkyiM4T1W06PQeufmk8j1TMp71KuZVw/xqxCKiIUiDN9OC4fQ5EI7+WXfVgsPrcSQXnjx8J9CRlSyzNMa+99bMt4jms98c5QU1Jf4PFfqQ9FxBy+AIEyEjcPHKs458oMVaoOROjkIpWMc0hSGfZZha/A=,iv:XoiYFlCoqEiTmhkwLJ3bVjO2xnhukea3AzRXZJ8dkUY=,tag:oyb538WsxNAy/DxThJ4leQ==,type:str] + lastmodified: "2025-05-26T18:01:04Z" + mac: ENC[AES256_GCM,data:3lgJQkz7IFQdPNnPvjBc10/DoUVjulGLgqzZC2M90WpNWcJfM2I84CCRzPNHGhmPK7EtIJWYnYIFiXiCNhQuPVQnSRo6rabVpfy3XgAwJhVNKtFg6nyoA0kCnnqsj8bAm0KBh5Okb1rz00YbA13CmNWJnDFAhI980qOhQ37GiPk=,iv:FaJvZ6QPryry1zX5jCbe171+CNj3/+rLNZZoZ3TAK8I=,tag:BVFUrFuOwY6sBAJ3TUCjsQ==,type:str] pgp: - created_at: "2025-05-21T10:26:58Z" enc: |- @@ -40,4 +40,4 @@ sops: -----END PGP MESSAGE----- fp: 9D7CACD7039E5AD616FD25879F935DB630A167E7 unencrypted_suffix: _unencrypted - version: 3.9.4 + version: 3.10.2