diff --git a/nixos/module/hectic/service/element.nix b/nixos/module/hectic/service/element.nix index cf29873..c56042c 100644 --- a/nixos/module/hectic/service/element.nix +++ b/nixos/module/hectic/service/element.nix @@ -20,9 +20,14 @@ in { conf = { default_server_config = { "m.homeserver".base_url = "https://${cfg.matrixDomain}"; + "m.homeserver".server_name = cfg.matrixDomain; "m.identity_server".base_url = "https://vector.im"; }; + room_directory.servers = [ + cfg.matrixDomain + ]; + default_theme = "dark"; show_labs_settings = true; }; diff --git a/nixos/module/hectic/service/matrix.nix b/nixos/module/hectic/service/matrix.nix index 5e1c0fa..d843fd8 100644 --- a/nixos/module/hectic/service/matrix.nix +++ b/nixos/module/hectic/service/matrix.nix @@ -10,6 +10,23 @@ ... }: let cfg = config.hectic.services.matrix; + matrixUsers = builtins.attrNames cfg.users; + mkUserRegistration = name: let + user = cfg.users.${name}; + adminFlag = if user.admin then "--admin" else "--no-admin"; + in '' + if [ ! -r "${user.passwordFile}" ]; then + printf 'Missing Matrix password file for %s: %s\n' '${name}' '${user.passwordFile}' >&2 + exit 1 + fi + + ${pkgs.matrix-synapse}/bin/register_new_matrix_user \ + -u '${name}' \ + -p "$(tr -d '\n' < "${user.passwordFile}")" \ + -k "$REGISTRATION_SHARED_SECRET" \ + ${adminFlag} \ + http://127.0.0.1:8008 || true + ''; in { options = { hectic.services.matrix = { @@ -49,13 +66,39 @@ in { domain to matrix ''; }; + users = lib.mkOption { + type = lib.types.attrsOf (lib.types.submodule { + options = { + passwordFile = lib.mkOption { + type = lib.types.str; + description = '' + Full path to a file containing the Matrix user's password. + ''; + }; + admin = lib.mkOption { + type = lib.types.bool; + default = false; + description = '' + Whether to create the Matrix user as an admin. + ''; + }; + }; + }); + default = {}; + description = '' + Declarative Matrix users to provision after Synapse starts. + ''; + }; }; }; config = lib.mkIf cfg.enable { services.matrix-synapse = { enable = true; - settings = { - server_name = cfg.matrixDomain; + extraConfigFiles = [ + cfg.secretsFile + ]; + settings = { + server_name = cfg.matrixDomain; public_baseurl = "https://${cfg.matrixDomain}"; experimental_features = { msc3266_enabled = true; @@ -95,9 +138,6 @@ in { enable_registration = true; enable_registration_without_verification = true; - extraConfigFiles = [ - cfg.secretsFile - ]; }; }; @@ -183,5 +223,30 @@ in { enableDebugLogs = true; }; }; + systemd.services.matrix-synapse-users = lib.mkIf (matrixUsers != []) { + description = "Provision Matrix Synapse users"; + wantedBy = [ "multi-user.target" ]; + after = [ config.services.matrix-synapse.serviceUnit ]; + requires = [ config.services.matrix-synapse.serviceUnit ]; + path = with pkgs; [ curl coreutils gawk ]; + serviceConfig = { + Type = "oneshot"; + User = "matrix-synapse"; + }; + script = '' + until curl -sf http://127.0.0.1:8008/_matrix/client/versions >/dev/null; do + sleep 2 + done + + REGISTRATION_SHARED_SECRET="$(awk -F': *' '$1 == "registration_shared_secret" { print $2; exit }' "${cfg.secretsFile}")" + + if [ -z "$REGISTRATION_SHARED_SECRET" ]; then + printf 'registration_shared_secret not found in %s\n' '${cfg.secretsFile}' >&2 + exit 1 + fi + +${builtins.concatStringsSep "\n" (map mkUserRegistration matrixUsers)} + ''; + }; }; } diff --git a/nixos/system/hectic-lab/hectic-lab.nix b/nixos/system/hectic-lab/hectic-lab.nix index e10cec6..95b0d92 100644 --- a/nixos/system/hectic-lab/hectic-lab.nix +++ b/nixos/system/hectic-lab/hectic-lab.nix @@ -63,6 +63,15 @@ in { port = 5432; initialEnvFile = config.sops.secrets."init-postgresql".path; }; + users = { + yukkop = { + passwordFile = config.sops.secrets."matrix/users/yukkop/password".path; + admin = true; + }; + liquiz = { + passwordFile = config.sops.secrets."matrix/users/liquiz/password".path; + }; + }; inherit matrixDomain; }; }; @@ -137,6 +146,7 @@ in { }; sops.secrets."matrix/secrets" = { key = "matrix/secrets"; + owner = "matrix-synapse"; }; sops.secrets."matrix/turn-secret" = { key = "matrix/turn-secret"; @@ -144,6 +154,14 @@ in { group = "turnserver"; mode = "0400"; }; + sops.secrets."matrix/users/yukkop/password" = { + key = "matrix/users/yukkop/password"; + owner = "matrix-synapse"; + }; + sops.secrets."matrix/users/liquiz/password" = { + key = "matrix/users/liquiz/password"; + owner = "matrix-synapse"; + }; services.mailserver = { enable = true; diff --git a/sus/hectic-lab.yaml b/sus/hectic-lab.yaml index 3f8a8be..ff2ac98 100644 --- a/sus/hectic-lab.yaml +++ b/sus/hectic-lab.yaml @@ -14,6 +14,11 @@ mailserver: init-postgresql: ENC[AES256_GCM,data:Iw8M2P1QoqPVaEdM8Zo0qlHrYgop0iknDY4NtgDo,iv:RWj9AFnh4/KWCm3UH4RoCdM2lzsXGY7A7qko8xCxjp8=,tag:l8acSq8+NBXB4L1rVzG6kw==,type:str] matrix: secrets: ENC[AES256_GCM,data:ivXp2YSiMI4hgL6122Ex+fGW0lsZvGD6XmiRvNgFgvzLH5yDv9uLsYcGCTYfQSL3X5VyIMGvsdRF+4pbIjBZMuQKrjvXv74E7aFBLQ2Qk98N3IIrznUFR3KXbHR6xXy5ILd7Bmw5JI/ZHULbmITahXUBt2kEJvfh4eAtqShNA4vsJrabHX9A8Q+2Ddp16w0cWftV5++WXzlNpvIc2Py6BwvfroNAjpSaO+ILYDOIL7XjPvF83fTt64pxZ9nsi3hCzcDtBgGkqc8=,iv:wvt9V2uYQUwivSwEIYZwcHjXr5WwMw19lgFDIa1CcVw=,tag:/22UZvp7+1hLbt+kV+wokQ==,type:str] + users: + yukkop: + password: ENC[AES256_GCM,data:2JUc8U87HVrJIDc9j2InZKgTRQBP,iv:0tuM7TFENbiVi7aM0nTgvRJrK0vGLewsmWJz2MUi62g=,tag:RL61PCXzQFLObBwXthpk5Q==,type:str] + liquiz: + password: ENC[AES256_GCM,data:6y3eFrfAZ88=,iv:yEIr1Oq4x3jnWcymHwrLDioKqapzaiOfNPvkgiNIOiw=,tag:CJ3gWTRpQtEEaMkYUOb8Mg==,type:str] turn-secret: ENC[AES256_GCM,data:2RerKgYNFXEVM/YVmXt2l+t3BqduS+FlmjBWTA==,iv:6odb0HB9mntsceNaJtU2kwEVAiF0O88u47eDPLZVJbs=,tag:BJXAvK8abcnCLi96Kra5zA==,type:str] wg-bfs: private-key: ENC[AES256_GCM,data:/J02asiesrQcsO7Xbq66HQIQeSPmFEMkM2q/z+9Y42K8SYEQP0OYQz+8fXI=,iv:PdGhPWgGxhe0a7C6CaVM/ePKABT+y8HRFOAPzNwQk+c=,tag:9AI30JFh6uyaXXVjMBJ1zg==,type:str] @@ -76,7 +81,7 @@ sops: Yk43ZmlTc09aNFV1VjdjN2RWQlFWTDQKcYSvA2lHP8GS0lkYY19Tm8RXmFHQX5Ck qV2Fn22Fic4M5FVKDEMfaO6WmeXgki9a8dGeO9LlC+Phf16SOq7eLw== -----END AGE ENCRYPTED FILE----- - lastmodified: "2026-05-22T20:03:30Z" - mac: ENC[AES256_GCM,data:L59emZfOoFtisno0/yYVRtutaJAClIDStt6aWUzCI+WPU2g4XX5/pKGr3Lhd5bhyq7v+GWQJ6D94AfmeyVIIr2aJVQNlPlRKc+1Tn7VKDdqP2Seb4erkMmmxrmG6b7qCTTR7llF6zaqXXsnRav1JrTX1B5GFSgRjmIaVpM2Ik64=,iv:3u+LMlOdTYgXgqnFMamwlAJhqixB+P/cvyYyPlzqjjs=,tag:WyGkpArTk4r/nq+WA2vgPQ==,type:str] + lastmodified: "2026-05-22T20:46:03Z" + mac: ENC[AES256_GCM,data:IE3N17kJDlgoIp4kYSpWqLRC1wA61OEBB/vz3wCEmZuQpO4uPd+ymSjGtTHXSc+Ppie5mFv9t+mHbhqsDjw33yts7FDdMB8OFxSO4qBQu4itLHWA+lSylknn/a/aZg6YZO9ppYjD4NQVZhFVJUl+7oBuuHlaEofB9i7c1lIkXts=,iv:X3nLOMhpZaba/NBl2vAIX0TXQp0k99N7y+gVRXVNbiM=,tag:RHB3a4yYaSgsJ5atrREf9g==,type:str] unencrypted_suffix: _unencrypted version: 3.10.2