at 18.09-beta 6.9 kB view raw
1{ config, lib, pkgs, ... }: 2 3with lib; 4 5let 6 cfg = config.services.redmine; 7 8 bundle = "${pkgs.redmine}/share/redmine/bin/bundle"; 9 10 databaseYml = pkgs.writeText "database.yml" '' 11 production: 12 adapter: ${cfg.database.type} 13 database: ${cfg.database.name} 14 host: ${cfg.database.host} 15 port: ${toString cfg.database.port} 16 username: ${cfg.database.user} 17 password: #dbpass# 18 ''; 19 20 configurationYml = pkgs.writeText "configuration.yml" '' 21 default: 22 scm_subversion_command: ${pkgs.subversion}/bin/svn 23 scm_mercurial_command: ${pkgs.mercurial}/bin/hg 24 scm_git_command: ${pkgs.gitAndTools.git}/bin/git 25 scm_cvs_command: ${pkgs.cvs}/bin/cvs 26 scm_bazaar_command: ${pkgs.bazaar}/bin/bzr 27 scm_darcs_command: ${pkgs.darcs}/bin/darcs 28 29 ${cfg.extraConfig} 30 ''; 31 32in 33 34{ 35 options = { 36 services.redmine = { 37 enable = mkOption { 38 type = types.bool; 39 default = false; 40 description = "Enable the Redmine service."; 41 }; 42 43 user = mkOption { 44 type = types.str; 45 default = "redmine"; 46 description = "User under which Redmine is ran."; 47 }; 48 49 group = mkOption { 50 type = types.str; 51 default = "redmine"; 52 description = "Group under which Redmine is ran."; 53 }; 54 55 stateDir = mkOption { 56 type = types.str; 57 default = "/var/lib/redmine"; 58 description = "The state directory, logs and plugins are stored here."; 59 }; 60 61 extraConfig = mkOption { 62 type = types.lines; 63 default = ""; 64 description = '' 65 Extra configuration in configuration.yml. 66 67 See https://guides.rubyonrails.org/action_mailer_basics.html#action-mailer-configuration 68 ''; 69 }; 70 71 database = { 72 type = mkOption { 73 type = types.enum [ "mysql2" "postgresql" ]; 74 example = "postgresql"; 75 default = "mysql2"; 76 description = "Database engine to use."; 77 }; 78 79 host = mkOption { 80 type = types.str; 81 default = "127.0.0.1"; 82 description = "Database host address."; 83 }; 84 85 port = mkOption { 86 type = types.int; 87 default = 3306; 88 description = "Database host port."; 89 }; 90 91 name = mkOption { 92 type = types.str; 93 default = "redmine"; 94 description = "Database name."; 95 }; 96 97 user = mkOption { 98 type = types.str; 99 default = "redmine"; 100 description = "Database user."; 101 }; 102 103 password = mkOption { 104 type = types.str; 105 default = ""; 106 description = '' 107 The password corresponding to <option>database.user</option>. 108 Warning: this is stored in cleartext in the Nix store! 109 Use <option>database.passwordFile</option> instead. 110 ''; 111 }; 112 113 passwordFile = mkOption { 114 type = types.nullOr types.path; 115 default = null; 116 example = "/run/keys/redmine-dbpassword"; 117 description = '' 118 A file containing the password corresponding to 119 <option>database.user</option>. 120 ''; 121 }; 122 }; 123 }; 124 }; 125 126 config = mkIf cfg.enable { 127 128 assertions = [ 129 { assertion = cfg.database.passwordFile != null || cfg.database.password != ""; 130 message = "either services.redmine.database.passwordFile or services.redmine.database.password must be set"; 131 } 132 ]; 133 134 environment.systemPackages = [ pkgs.redmine ]; 135 136 systemd.services.redmine = { 137 after = [ "network.target" (if cfg.database.type == "mysql2" then "mysql.service" else "postgresql.service") ]; 138 wantedBy = [ "multi-user.target" ]; 139 environment.HOME = "${pkgs.redmine}/share/redmine"; 140 environment.RAILS_ENV = "production"; 141 environment.RAILS_CACHE = "${cfg.stateDir}/cache"; 142 environment.REDMINE_LANG = "en"; 143 environment.SCHEMA = "${cfg.stateDir}/cache/schema.db"; 144 path = with pkgs; [ 145 imagemagickBig 146 bazaar 147 cvs 148 darcs 149 gitAndTools.git 150 mercurial 151 subversion 152 ]; 153 preStart = '' 154 # start with a fresh config directory every time 155 rm -rf ${cfg.stateDir}/config 156 cp -r ${pkgs.redmine}/share/redmine/config.dist ${cfg.stateDir}/config 157 158 # create the basic state directory layout pkgs.redmine expects 159 mkdir -p /run/redmine 160 161 for i in config files log plugins tmp; do 162 mkdir -p ${cfg.stateDir}/$i 163 ln -fs ${cfg.stateDir}/$i /run/redmine/$i 164 done 165 166 # ensure cache directory exists for db:migrate command 167 mkdir -p ${cfg.stateDir}/cache 168 169 # link in the application configuration 170 ln -fs ${configurationYml} ${cfg.stateDir}/config/configuration.yml 171 172 chmod -R ug+rwX,o-rwx+x ${cfg.stateDir}/ 173 174 # handle database.passwordFile 175 DBPASS=$(head -n1 ${cfg.database.passwordFile}) 176 cp -f ${databaseYml} ${cfg.stateDir}/config/database.yml 177 sed -e "s,#dbpass#,$DBPASS,g" -i ${cfg.stateDir}/config/database.yml 178 chmod 440 ${cfg.stateDir}/config/database.yml 179 180 # generate a secret token if required 181 if ! test -e "${cfg.stateDir}/config/initializers/secret_token.rb"; then 182 ${bundle} exec rake generate_secret_token 183 chmod 440 ${cfg.stateDir}/config/initializers/secret_token.rb 184 fi 185 186 # ensure everything is owned by ${cfg.user} 187 chown -R ${cfg.user}:${cfg.group} ${cfg.stateDir} 188 189 ${bundle} exec rake db:migrate 190 ${bundle} exec rake redmine:load_default_data 191 ''; 192 193 serviceConfig = { 194 PermissionsStartOnly = true; # preStart must be run as root 195 Type = "simple"; 196 User = cfg.user; 197 Group = cfg.group; 198 TimeoutSec = "300"; 199 WorkingDirectory = "${pkgs.redmine}/share/redmine"; 200 ExecStart="${bundle} exec rails server webrick -e production -P ${cfg.stateDir}/redmine.pid"; 201 }; 202 203 }; 204 205 users.extraUsers = optionalAttrs (cfg.user == "redmine") (singleton 206 { name = "redmine"; 207 group = cfg.group; 208 home = cfg.stateDir; 209 createHome = true; 210 uid = config.ids.uids.redmine; 211 }); 212 213 users.extraGroups = optionalAttrs (cfg.group == "redmine") (singleton 214 { name = "redmine"; 215 gid = config.ids.gids.redmine; 216 }); 217 218 warnings = optional (cfg.database.password != "") 219 ''config.services.redmine.database.password will be stored as plaintext 220 in the Nix store. Use database.passwordFile instead.''; 221 222 # Create database passwordFile default when password is configured. 223 services.redmine.database.passwordFile = 224 (mkDefault (toString (pkgs.writeTextFile { 225 name = "redmine-database-password"; 226 text = cfg.database.password; 227 }))); 228 229 }; 230 231}