at 21.11-pre 7.6 kB view raw
1{ config, pkgs, lib, ... }: 2 3with lib; 4 5let 6 7 cfg = config.services.mattermost; 8 9 defaultConfig = builtins.fromJSON (builtins.replaceStrings [ "\\u0026" ] [ "&" ] 10 (readFile "${pkgs.mattermost}/config/config.json") 11 ); 12 13 database = "postgres://${cfg.localDatabaseUser}:${cfg.localDatabasePassword}@localhost:5432/${cfg.localDatabaseName}?sslmode=disable&connect_timeout=10"; 14 15 mattermostConf = foldl recursiveUpdate defaultConfig 16 [ { ServiceSettings.SiteURL = cfg.siteUrl; 17 ServiceSettings.ListenAddress = cfg.listenAddress; 18 TeamSettings.SiteName = cfg.siteName; 19 SqlSettings.DriverName = "postgres"; 20 SqlSettings.DataSource = database; 21 } 22 cfg.extraConfig 23 ]; 24 25 mattermostConfJSON = pkgs.writeText "mattermost-config-raw.json" (builtins.toJSON mattermostConf); 26 27in 28 29{ 30 options = { 31 services.mattermost = { 32 enable = mkEnableOption "Mattermost chat server"; 33 34 statePath = mkOption { 35 type = types.str; 36 default = "/var/lib/mattermost"; 37 description = "Mattermost working directory"; 38 }; 39 40 siteUrl = mkOption { 41 type = types.str; 42 example = "https://chat.example.com"; 43 description = '' 44 URL this Mattermost instance is reachable under, without trailing slash. 45 ''; 46 }; 47 48 siteName = mkOption { 49 type = types.str; 50 default = "Mattermost"; 51 description = "Name of this Mattermost site."; 52 }; 53 54 listenAddress = mkOption { 55 type = types.str; 56 default = ":8065"; 57 example = "[::1]:8065"; 58 description = '' 59 Address and port this Mattermost instance listens to. 60 ''; 61 }; 62 63 mutableConfig = mkOption { 64 type = types.bool; 65 default = false; 66 description = '' 67 Whether the Mattermost config.json is writeable by Mattermost. 68 69 Most of the settings can be edited in the system console of 70 Mattermost if this option is enabled. A template config using 71 the options specified in services.mattermost will be generated 72 but won't be overwritten on changes or rebuilds. 73 74 If this option is disabled, changes in the system console won't 75 be possible (default). If an config.json is present, it will be 76 overwritten! 77 ''; 78 }; 79 80 extraConfig = mkOption { 81 type = types.attrs; 82 default = { }; 83 description = '' 84 Addtional configuration options as Nix attribute set in config.json schema. 85 ''; 86 }; 87 88 localDatabaseCreate = mkOption { 89 type = types.bool; 90 default = true; 91 description = '' 92 Create a local PostgreSQL database for Mattermost automatically. 93 ''; 94 }; 95 96 localDatabaseName = mkOption { 97 type = types.str; 98 default = "mattermost"; 99 description = '' 100 Local Mattermost database name. 101 ''; 102 }; 103 104 localDatabaseUser = mkOption { 105 type = types.str; 106 default = "mattermost"; 107 description = '' 108 Local Mattermost database username. 109 ''; 110 }; 111 112 localDatabasePassword = mkOption { 113 type = types.str; 114 default = "mmpgsecret"; 115 description = '' 116 Password for local Mattermost database user. 117 ''; 118 }; 119 120 user = mkOption { 121 type = types.str; 122 default = "mattermost"; 123 description = '' 124 User which runs the Mattermost service. 125 ''; 126 }; 127 128 group = mkOption { 129 type = types.str; 130 default = "mattermost"; 131 description = '' 132 Group which runs the Mattermost service. 133 ''; 134 }; 135 136 matterircd = { 137 enable = mkEnableOption "Mattermost IRC bridge"; 138 parameters = mkOption { 139 type = types.listOf types.str; 140 default = [ ]; 141 example = [ "-mmserver chat.example.com" "-bind [::]:6667" ]; 142 description = '' 143 Set commandline parameters to pass to matterircd. See 144 https://github.com/42wim/matterircd#usage for more information. 145 ''; 146 }; 147 }; 148 }; 149 }; 150 151 config = mkMerge [ 152 (mkIf cfg.enable { 153 users.users = optionalAttrs (cfg.user == "mattermost") { 154 mattermost = { 155 group = cfg.group; 156 uid = config.ids.uids.mattermost; 157 home = cfg.statePath; 158 }; 159 }; 160 161 users.groups = optionalAttrs (cfg.group == "mattermost") { 162 mattermost.gid = config.ids.gids.mattermost; 163 }; 164 165 services.postgresql.enable = cfg.localDatabaseCreate; 166 167 # The systemd service will fail to execute the preStart hook 168 # if the WorkingDirectory does not exist 169 system.activationScripts.mattermost = '' 170 mkdir -p ${cfg.statePath} 171 ''; 172 173 systemd.services.mattermost = { 174 description = "Mattermost chat service"; 175 wantedBy = [ "multi-user.target" ]; 176 after = [ "network.target" "postgresql.service" ]; 177 178 preStart = '' 179 mkdir -p ${cfg.statePath}/{data,config,logs} 180 ln -sf ${pkgs.mattermost}/{bin,fonts,i18n,templates,client} ${cfg.statePath} 181 '' + lib.optionalString (!cfg.mutableConfig) '' 182 rm -f ${cfg.statePath}/config/config.json 183 cp ${mattermostConfJSON} ${cfg.statePath}/config/config.json 184 ${pkgs.mattermost}/bin/mattermost config migrate ${cfg.statePath}/config/config.json ${database} 185 '' + lib.optionalString cfg.mutableConfig '' 186 if ! test -e "${cfg.statePath}/config/.initial-created"; then 187 rm -f ${cfg.statePath}/config/config.json 188 cp ${mattermostConfJSON} ${cfg.statePath}/config/config.json 189 touch ${cfg.statePath}/config/.initial-created 190 fi 191 '' + lib.optionalString cfg.localDatabaseCreate '' 192 if ! test -e "${cfg.statePath}/.db-created"; then 193 ${pkgs.sudo}/bin/sudo -u ${config.services.postgresql.superUser} \ 194 ${config.services.postgresql.package}/bin/psql postgres -c \ 195 "CREATE ROLE ${cfg.localDatabaseUser} WITH LOGIN NOCREATEDB NOCREATEROLE ENCRYPTED PASSWORD '${cfg.localDatabasePassword}'" 196 ${pkgs.sudo}/bin/sudo -u ${config.services.postgresql.superUser} \ 197 ${config.services.postgresql.package}/bin/createdb \ 198 --owner ${cfg.localDatabaseUser} ${cfg.localDatabaseName} 199 touch ${cfg.statePath}/.db-created 200 fi 201 '' + '' 202 chown ${cfg.user}:${cfg.group} -R ${cfg.statePath} 203 chmod u+rw,g+r,o-rwx -R ${cfg.statePath} 204 ''; 205 206 serviceConfig = { 207 PermissionsStartOnly = true; 208 User = cfg.user; 209 Group = cfg.group; 210 ExecStart = "${pkgs.mattermost}/bin/mattermost" + 211 (lib.optionalString (!cfg.mutableConfig) " -c ${database}"); 212 WorkingDirectory = "${cfg.statePath}"; 213 Restart = "always"; 214 RestartSec = "10"; 215 LimitNOFILE = "49152"; 216 }; 217 unitConfig.JoinsNamespaceOf = mkIf cfg.localDatabaseCreate "postgresql.service"; 218 }; 219 }) 220 (mkIf cfg.matterircd.enable { 221 systemd.services.matterircd = { 222 description = "Mattermost IRC bridge service"; 223 wantedBy = [ "multi-user.target" ]; 224 serviceConfig = { 225 User = "nobody"; 226 Group = "nogroup"; 227 ExecStart = "${pkgs.matterircd}/bin/matterircd ${concatStringsSep " " cfg.matterircd.parameters}"; 228 WorkingDirectory = "/tmp"; 229 PrivateTmp = true; 230 Restart = "always"; 231 RestartSec = "5"; 232 }; 233 }; 234 }) 235 ]; 236}