at 16.09-beta 7.2 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 platform"; 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.extraUsers = 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.extraGroups = 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 platform 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,webapp} ${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 ${config.services.postgresql.package}/bin/psql postgres -c \ 188 "CREATE ROLE ${cfg.localDatabaseUser} WITH LOGIN NOCREATEDB NOCREATEROLE NOCREATEUSER ENCRYPTED PASSWORD '${cfg.localDatabasePassword}'" 189 ${config.services.postgresql.package}/bin/createdb \ 190 --owner ${cfg.localDatabaseUser} ${cfg.localDatabaseName} 191 touch ${cfg.statePath}/.db-created 192 fi 193 '' + '' 194 chown ${cfg.user}:${cfg.group} -R ${cfg.statePath} 195 chmod u+rw,g+r,o-rwx -R ${cfg.statePath} 196 ''; 197 198 serviceConfig = { 199 PermissionsStartOnly = true; 200 User = cfg.user; 201 Group = cfg.group; 202 ExecStart = "${pkgs.mattermost}/bin/mattermost-platform"; 203 WorkingDirectory = "${cfg.statePath}"; 204 PrivateTmp = true; 205 Restart = "always"; 206 RestartSec = "10"; 207 LimitNOFILE = "49152"; 208 }; 209 }; 210 }) 211 (mkIf cfg.matterircd.enable { 212 systemd.services.matterircd = { 213 description = "Mattermost IRC bridge service"; 214 wantedBy = [ "multi-user.target" ]; 215 serviceConfig = { 216 User = "nobody"; 217 Group = "nogroup"; 218 ExecStart = "${pkgs.matterircd.bin}/bin/matterircd ${concatStringsSep " " cfg.matterircd.parameters}"; 219 WorkingDirectory = "/tmp"; 220 PrivateTmp = true; 221 Restart = "always"; 222 RestartSec = "5"; 223 }; 224 }; 225 }) 226 ]; 227} 228