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