diff --git a/machines/biotite/default.nix b/machines/biotite/default.nix index a507675..cf652c8 100644 --- a/machines/biotite/default.nix +++ b/machines/biotite/default.nix @@ -1,4 +1,5 @@ { + pkgs, lib, ... }: @@ -7,6 +8,8 @@ imports = [ ./hardware-configurations.nix ./services/gotosocial.nix + ./services/synapse.nix + ./services/restic.nix ]; networking.hostName = "biotite"; @@ -43,6 +46,37 @@ services.caddy.enable = true; services.tailscale.enable = true; + services.postgresql = { + enable = true; + package = pkgs.postgresql_17; + settings = { + allow_alter_system = false; + # DB Version: 17 + # OS Type: linux + # DB Type: mixed + # Total Memory (RAM): 8 GB + # CPUs num: 4 + # Data Storage: ssd + max_connections = 100; + shared_buffers = "2GB"; + effective_cache_size = "6GB"; + maintenance_work_mem = "512MB"; + checkpoint_completion_target = 0.9; + wal_buffers = "16MB"; + default_statistics_target = 100; + random_page_cost = 1.1; + effective_io_concurrency = 200; + work_mem = "5242kB"; + huge_pages = "off"; + min_wal_size = "1GB"; + max_wal_size = "4GB"; + max_worker_processes = 4; + max_parallel_workers_per_gather = 2; + max_parallel_workers = 4; + max_parallel_maintenance_workers = 2; + }; + }; + users.users.root.hashedPassword = "$y$j9T$NToEZWJBONjSgRnMd9Ur9/$o6n7a9b8eUILQz4d37oiHCCVnDJ8hZTZt.c.37zFfU."; system.stateVersion = "24.11"; diff --git a/machines/biotite/secrets.yaml b/machines/biotite/secrets.yaml index 5d8f181..b2ed748 100644 --- a/machines/biotite/secrets.yaml +++ b/machines/biotite/secrets.yaml @@ -1,5 +1,10 @@ gotosocial: oidc_client_secret: ENC[AES256_GCM,data:KVQxzs67sohax2h0Y/jjhnbY4fetrdVvWhBGbqgDSGgBC7QazrOmTA++BSRzMmVv,iv:HIRMc56aLanqQRTWH9E0wzzXymImi0pxK/ccPEP8Fcc=,tag:PMhOLeE3mKIIQveRdfpgpA==,type:str] +synapse: + oidc_client_secret: ENC[AES256_GCM,data:TdZF8Bo+h34fn03sPpt7JEqmP8Cwm8V++q9VDvaapMBc3rlkrVu3iDUhQE2DvJri,iv:/QNX+aYUPpDKIqWZ13TLAznR3ZpUPI8rQHrJuqv7R+g=,tag:lcBIpeWiIXK/NV84uuxNiA==,type:str] +restic: + repo_url: ENC[AES256_GCM,data:ZcBMqwEsyc7zyEftJZj4XkKBzUHwlqd6cjX8xVDn9m26jBL7aP5atpnXDRE9FXY4CuAllFyQZyAOQ2L61Nfx+iplL2ADbSoH,iv:fhNODiyoOlZEqYR2O/GsH2IWTPDr3rXSJgWC/EFDLSA=,tag:nZdKKnpiszSiXxdZI1KQ/A==,type:str] + repo_password: ENC[AES256_GCM,data:9YDOz1tiyykz6zSXboWtIg==,iv:j96mRLXGuD4NZcC0Nv1yXFbtOlr6UborqclefZ7J94w=,tag:MqhSewK2NuckTJBf7xu+lA==,type:str] sops: kms: [] gcp_kms: [] @@ -24,8 +29,8 @@ sops: RzBMVDNjS29SUkdRK3dIV01sU0hYR3cK1SbvKAM6Gpsffv3HIi/WtWnCZUBic0AT ZRv4pvJBx1oxWsKIHW0t6VrqWMQ+suup8p6dW+h5HE8Z4ciIMrXLEg== -----END AGE ENCRYPTED FILE----- - lastmodified: "2024-12-02T05:10:32Z" - mac: ENC[AES256_GCM,data:ZAdFsjVuk1Fiv+DKmHrc1yu1XQpRDmRHaQhu5hduSZUa1W1cXdTlChvIW5vADFg5tVCjuYptuLvCMW+ZSQeqqG2ntHHZ+IkuovZzKFuc+BIiL/jF2ZzbyJ7X4Wj1GziCScHVxx98dgbpFoufHe6N3wCaHmngo1RYsY5N1RRbRdU=,iv:5IMQ0kOX9UAOm8bcsQRyu6zu8GJjvnHFufCNjY0s9UI=,tag:zBEPSR9DZDpwbCaIka8mXA==,type:str] + lastmodified: "2024-12-03T07:38:24Z" + mac: ENC[AES256_GCM,data:KMKdwgu9+3DjG1lrQYQEz/jYWsHUBK6RgHRyRKzWG0jTDg30owRpCgnSnX5gHzygmSYSnVRtcTOWzqm5bI7/KJkXBivaqkLqCh6EHnTj+pnAHmeEOAjoOVLOMSCEYvHMf/EuJIL199Hf2G12LtulDJV7Wi5r5Jy8L9odVlYuM9g=,iv:WTeqWdIztScZnXc2hzI7JHO/4ySgqycOp2eN9EPTQpw=,tag:lTMrE5JVVFCIDehXCxJZoQ==,type:str] pgp: [] unencrypted_suffix: _unencrypted version: 3.9.1 diff --git a/machines/biotite/services/gotosocial.nix b/machines/biotite/services/gotosocial.nix index fb26a69..e410a7c 100644 --- a/machines/biotite/services/gotosocial.nix +++ b/machines/biotite/services/gotosocial.nix @@ -27,6 +27,7 @@ oidc-client-id = "gotosocial"; oidc-link-existing = true; }; + setupPostgresqlDB = true; environmentFile = config.sops.templates."gotosocial.env".path; }; diff --git a/machines/biotite/services/restic.nix b/machines/biotite/services/restic.nix new file mode 100644 index 0000000..2e53c46 --- /dev/null +++ b/machines/biotite/services/restic.nix @@ -0,0 +1,55 @@ +{ + config, + lib, + pkgs, + ... +}: +let + sqliteBackup = fromPath: toPath: file: '' + mkdir -p ${toPath} + ${lib.getExe pkgs.sqlite} ${fromPath} ".backup '${toPath}/${file}'" + ''; +in +{ + sops.secrets = { + "restic/repo_url" = { + sopsFile = ../secrets.yaml; + }; + "restic/repo_password" = { + sopsFile = ../secrets.yaml; + }; + }; + + custom.restic = { + enable = true; + paths = [ + "/backup/db" + "/backup/var/lib" + ]; + backupPrepareCommand = [ + '' + mkdir -p /backup/var + ${pkgs.btrfs-progs}/bin/btrfs subvolume snapshot -r /var/lib /backup/var/lib + '' + ]; + backupCleanupCommand = [ + '' + ${pkgs.btrfs-progs}/bin/btrfs subvolume delete /backup/var/lib + '' + ]; + btrfsRoots = [ ]; + }; + + services.postgresqlBackup = { + enable = true; + compression = "zstd"; + compressionLevel = 9; + location = "/backup/db/postgresql"; + }; + + services.restic.backups.${config.networking.hostName} = { + extraBackupArgs = [ + "--limit-upload=1024" + ]; + }; +} diff --git a/machines/biotite/services/synapse.nix b/machines/biotite/services/synapse.nix new file mode 100644 index 0000000..7d4712b --- /dev/null +++ b/machines/biotite/services/synapse.nix @@ -0,0 +1,113 @@ +{ config, pkgs, ... }: +let + port-synapse = 6823; +in +{ + sops.secrets."synapse/oidc_client_secret" = { + owner = "matrix-synapse"; + }; + + nixpkgs.config.permittedInsecurePackages = [ + "olm-3.2.16" + ]; + + services.postgresql = { + # Not using ensure here because LC_COLLATE and LC_CTYPE must be provided + # at db creation + initialScript = pkgs.writeText "synapse-init.sql" '' + CREATE ROLE "matrix-synapse" WITH LOGIN PASSWORD 'synapse'; + CREATE DATABASE "matrix-synapse" WITH OWNER "matrix-synapse" + TEMPLATE template0 + LC_COLLATE = "C" + LC_CTYPE = "C"; + ''; + }; + + services.matrix-synapse = { + enable = true; + settings = { + server_name = "xiny.li"; + public_baseurl = "https://synapse.xiny.li"; + database = { + name = "psycopg2"; + args = { + user = "matrix-synapse"; + }; + }; + listeners = [ + { + bind_addresses = [ + "127.0.0.1" + ]; + port = port-synapse; + resources = [ + { + compress = true; + names = [ + "client" + "federation" + ]; + } + ]; + tls = false; + type = "http"; + x_forwarded = true; + } + ]; + experimental_features = { + # Room summary api + msc3266_enabled = true; + # Removing account data + msc3391_enabled = true; + # Thread notifications + msc3773_enabled = true; + # Remotely toggle push notifications for another client + msc3881_enabled = true; + # Remotely silence local notifications + msc3890_enabled = true; + # Remove legacy mentions + msc4210_enabled = true; + }; + oidc_providers = [ + { + idp_id = "Kanidm"; + idp_name = "auth.xinyang.life"; + issuer = "https://auth.xinyang.life/oauth2/openid/synapse"; + authorization_endpoint = "https://auth.xinyang.life/ui/oauth2"; + token_endpoint = "https://auth.xinyang.life/oauth2/token"; + userinfo_endpoint = "https://auth.xinyang.life/oauth2/openid/synapse/userinfo"; + client_id = "synapse"; + client_secret_path = config.sops.secrets."synapse/oidc_client_secret".path; + scopes = [ + "openid" + "profile" + ]; + allow_existing_users = true; + backchannel_logout_enabled = true; + user_mapping_provider.config = { + confirm_localpart = true; + localpart_template = "{{ user.preferred_username }}"; + display_name_template = "{{ user.name }}"; + }; + } + ]; + }; + }; + + services.caddy = { + virtualHosts."https://xiny.li".extraConfig = '' + header /.well-known/matrix/* Content-Type application/json + header /.well-known/matrix/* Access-Control-Allow-Origin * + respond /.well-known/matrix/server `{"m.server":"synapse.xiny.li:443"}` + respond /.well-known/matrix/client `{"m.homeserver":{"base_url":"https://synapse.xiny.li/"}}` + ''; + virtualHosts."https://synapse.xiny.li".extraConfig = '' + reverse_proxy /_matrix/* 127.0.0.1:${toString port-synapse} + reverse_proxy /_synapse/client/* 127.0.0.1:${toString port-synapse} + ''; + }; + + networking.firewall.allowedTCPPorts = [ + 443 + ]; +} diff --git a/machines/massicot/kanidm-provision.nix b/machines/massicot/kanidm-provision.nix index 8a95a99..1e6927a 100644 --- a/machines/massicot/kanidm-provision.nix +++ b/machines/massicot/kanidm-provision.nix @@ -45,6 +45,9 @@ miniflux-users = { members = [ "xin" ]; }; + synapse-users = { + members = [ "xin" ]; + }; idm_people_self_mail_write = { members = [ ]; }; @@ -211,6 +214,17 @@ }; }; }; + synapse = { + displayName = "Synapse"; + originUrl = "https://synapse.xiny.li/_synapse/client/oidc/callback"; + originLanding = "https://synapse.xiny.li/"; + scopeMaps = { + synapse-users = [ + "openid" + "profile" + ]; + }; + }; }; }; }