This repository has no description
0

Configure Feed

Select the types of activity you want to include in your feed.

superconfig / modules / parley.nix
4.9 kB 156 lines
1{ 2 self, 3 config, 4 lib, 5 pkgs, 6 ... 7}: 8let 9 cfg = config.lass.parley; 10 generators = config.clan.core.vars.generators; 11in 12{ 13 options.lass.parley = { 14 enable = lib.mkEnableOption "parley, federated chat that speaks plain IRC"; 15 16 package = lib.mkOption { 17 type = lib.types.package; 18 default = self.packages.${pkgs.stdenv.hostPlatform.system}.parley; 19 }; 20 21 settings = lib.mkOption { 22 type = lib.types.attrsOf lib.types.str; 23 default = { }; 24 example = { 25 PARLEY_DOMAIN = "example.com"; 26 PARLEY_ENDPOINT = "https://chat.example.com"; 27 }; 28 description = "PARLEY_* environment variables for parleyd (upstream README, Configuration)."; 29 }; 30 31 users = lib.mkOption { 32 default = { }; 33 description = '' 34 Local accounts. Each gets a generated password 35 (`clan vars get <machine> parley-user-<nick>/password`); after every 36 start the account is created, or reset to its declared role and 37 password. Accounts not listed here are left alone. 38 ''; 39 type = lib.types.attrsOf ( 40 lib.types.submodule { 41 options.role = lib.mkOption { 42 type = lib.types.enum [ 43 "admin" 44 "user" 45 "bot" 46 ]; 47 default = "user"; 48 }; 49 } 50 ); 51 }; 52 }; 53 54 config = lib.mkIf cfg.enable { 55 lass.parley.settings = { 56 PARLEY_DATA_DIR = "/var/lib/parley"; 57 PARLEY_IRC_LISTEN = lib.mkDefault "127.0.0.1:6667"; 58 PARLEY_HTTP_LISTEN = lib.mkDefault "127.0.0.1:8443"; 59 }; 60 61 clan.core.vars.generators = { 62 parley = { 63 # The instance key is the domain's identity: peers cache its public 64 # half, so regenerating it is a key rotation every peer has to re-learn. 65 files."identity.key" = { }; 66 files."env" = { }; 67 runtimeInputs = [ pkgs.openssl ]; 68 script = '' 69 # parley's key format: base64 of a 32-byte ed25519 seed 70 openssl rand -base64 32 > "$out/identity.key" 71 echo "PARLEY_ADMIN_TOKEN=$(openssl rand -hex 32)" > "$out/env" 72 ''; 73 }; 74 } 75 // lib.mapAttrs' ( 76 nick: _: 77 lib.nameValuePair "parley-user-${nick}" { 78 files."password" = { }; 79 runtimeInputs = [ pkgs.openssl ]; 80 script = '' 81 openssl rand -hex 24 > "$out/password" 82 ''; 83 } 84 ) cfg.users; 85 86 users.users.parley = { 87 isSystemUser = true; 88 group = "parley"; 89 }; 90 users.groups.parley = { }; 91 92 environment.systemPackages = [ cfg.package ]; 93 94 systemd.services.parley = { 95 wantedBy = [ "multi-user.target" ]; 96 after = [ "network-online.target" ]; 97 wants = [ "network-online.target" ]; 98 environment = cfg.settings; 99 path = [ 100 cfg.package 101 pkgs.curl 102 ]; 103 preStart = '' 104 install -m 0600 "$CREDENTIALS_DIRECTORY/identity.key" identity.key 105 ''; 106 postStart = lib.optionalString (cfg.users != { }) '' 107 export PARLEY_ENDPOINT=http://$PARLEY_HTTP_LISTEN 108 until curl -fs -o /dev/null "$PARLEY_ENDPOINT/healthz"; do sleep 1; done 109 ${lib.concatStrings ( 110 lib.mapAttrsToList (nick: user: '' 111 pw="$CREDENTIALS_DIRECTORY/user-${nick}" 112 parleyctl accounts update ${nick} -role ${user.role} -password-stdin < "$pw" > /dev/null \ 113 || parleyctl accounts create ${nick} -role ${user.role} -password-stdin < "$pw" > /dev/null 114 '') cfg.users 115 )} 116 ''; 117 serviceConfig = { 118 ExecStart = lib.getExe' cfg.package "parleyd"; 119 User = "parley"; 120 Group = "parley"; 121 StateDirectory = "parley"; 122 StateDirectoryMode = "0700"; 123 WorkingDirectory = "/var/lib/parley"; 124 UMask = "0077"; 125 EnvironmentFile = generators.parley.files."env".path; 126 LoadCredential = [ 127 "identity.key:${generators.parley.files."identity.key".path}" 128 ] 129 ++ lib.mapAttrsToList ( 130 nick: _: "user-${nick}:${generators."parley-user-${nick}".files."password".path}" 131 ) cfg.users; 132 Restart = "on-failure"; 133 NoNewPrivileges = true; 134 ProtectSystem = "strict"; 135 ProtectHome = true; 136 PrivateTmp = true; 137 PrivateDevices = true; 138 }; 139 }; 140 141 # identity.key also lives in clan vars; the SQLite databases are dumped 142 # consistently instead of copied. 143 lass.backup.state.parley = { 144 folders = [ "/var/lib/parley" ]; 145 exclude = [ "/var/lib/parley/*.db*" ]; 146 preBackup = '' 147 mkdir -p /var/backup/parley 148 for db in parley history; do 149 ${pkgs.sqlite}/bin/sqlite3 -cmd ".timeout 60000" "/var/lib/parley/$db.db" ".backup /var/backup/parley/$db.db" 150 done 151 ''; 152 # WAL-mode SQLite readers need to write the -shm file 153 readWritePaths = [ "/var/lib/parley" ]; 154 }; 155 }; 156}