at 15.09-beta 11 kB view raw
1{ config, lib, pkgs, ... }: 2 3# TODO: support non-postgresql 4 5with lib; 6 7let 8 cfg = config.services.gitlab; 9 10 ruby = pkgs.gitlab.ruby; 11 bundler = pkgs.bundler; 12 13 gemHome = "${pkgs.gitlab.env}/${ruby.gemPath}"; 14 15 databaseYml = '' 16 production: 17 adapter: postgresql 18 database: ${cfg.databaseName} 19 host: ${cfg.databaseHost} 20 password: ${cfg.databasePassword} 21 username: ${cfg.databaseUsername} 22 encoding: utf8 23 ''; 24 gitlabShellYml = '' 25 user: gitlab 26 gitlab_url: "http://${cfg.host}:${toString cfg.port}/" 27 http_settings: 28 self_signed_cert: false 29 repos_path: "${cfg.stateDir}/repositories" 30 log_file: "${cfg.stateDir}/log/gitlab-shell.log" 31 redis: 32 bin: ${pkgs.redis}/bin/redis-cli 33 host: 127.0.0.1 34 port: 6379 35 database: 0 36 namespace: resque:gitlab 37 ''; 38 39 unicornConfig = builtins.readFile ./defaultUnicornConfig.rb; 40 41 gitlab-runner = pkgs.stdenv.mkDerivation rec { 42 name = "gitlab-runner"; 43 buildInputs = [ pkgs.gitlab pkgs.bundler pkgs.makeWrapper ]; 44 phases = "installPhase fixupPhase"; 45 buildPhase = ""; 46 installPhase = '' 47 mkdir -p $out/bin 48 makeWrapper ${bundler}/bin/bundle $out/bin/gitlab-runner\ 49 --set RAKEOPT '"-f ${pkgs.gitlab}/share/gitlab/Rakefile"'\ 50 --set GEM_HOME '${gemHome}'\ 51 --set UNICORN_PATH "${cfg.stateDir}/"\ 52 --set GITLAB_PATH "${pkgs.gitlab}/share/gitlab/"\ 53 --set GITLAB_APPLICATION_LOG_PATH "${cfg.stateDir}/log/application.log"\ 54 --set GITLAB_SATELLITES_PATH "${cfg.stateDir}/satellites"\ 55 --set GITLAB_SHELL_PATH "${pkgs.gitlab-shell}"\ 56 --set GITLAB_REPOSITORIES_PATH "${cfg.stateDir}/repositories"\ 57 --set GITLAB_SHELL_HOOKS_PATH "${cfg.stateDir}/shell/hooks"\ 58 --set BUNDLE_GEMFILE "${pkgs.gitlab}/share/gitlab/Gemfile"\ 59 --set GITLAB_EMAIL_FROM "${cfg.emailFrom}"\ 60 --set GITLAB_SHELL_CONFIG_PATH "${cfg.stateDir}/shell/config.yml"\ 61 --set GITLAB_SHELL_SECRET_PATH "${cfg.stateDir}/config/gitlab_shell_secret"\ 62 --set GITLAB_HOST "${cfg.host}"\ 63 --set GITLAB_PORT "${toString cfg.port}"\ 64 --set GITLAB_BACKUP_PATH "${cfg.backupPath}"\ 65 --set RAILS_ENV "production" 66 ''; 67 }; 68 69in { 70 71 options = { 72 services.gitlab = { 73 enable = mkOption { 74 type = types.bool; 75 default = false; 76 description = '' 77 Enable the gitlab service. 78 ''; 79 }; 80 81 satelliteDir = mkOption { 82 type = types.str; 83 default = "/var/gitlab/git-satellites"; 84 description = "Gitlab directory to store checked out git trees requires for operation."; 85 }; 86 87 stateDir = mkOption { 88 type = types.str; 89 default = "/var/gitlab/state"; 90 description = "Gitlab state directory, logs are stored here."; 91 }; 92 93 backupPath = mkOption { 94 type = types.str; 95 default = cfg.stateDir + "/backup"; 96 description = "Gitlab path for backups."; 97 }; 98 99 databaseHost = mkOption { 100 type = types.str; 101 default = "127.0.0.1"; 102 description = "Gitlab database hostname."; 103 }; 104 105 databasePassword = mkOption { 106 type = types.str; 107 default = ""; 108 description = "Gitlab database user password."; 109 }; 110 111 databaseName = mkOption { 112 type = types.str; 113 default = "gitlab"; 114 description = "Gitlab database name."; 115 }; 116 117 databaseUsername = mkOption { 118 type = types.str; 119 default = "gitlab"; 120 description = "Gitlab database user."; 121 }; 122 123 emailFrom = mkOption { 124 type = types.str; 125 default = "example@example.org"; 126 description = "The source address for emails sent by gitlab."; 127 }; 128 129 host = mkOption { 130 type = types.str; 131 default = config.networking.hostName; 132 description = "Gitlab host name. Used e.g. for copy-paste URLs."; 133 }; 134 135 port = mkOption { 136 type = types.int; 137 default = 8080; 138 description = "Gitlab server listening port."; 139 }; 140 }; 141 }; 142 143 config = mkIf cfg.enable { 144 145 environment.systemPackages = [ gitlab-runner pkgs.gitlab-shell ]; 146 147 assertions = [ 148 { assertion = cfg.databasePassword != ""; 149 message = "databasePassword must be set"; 150 } 151 ]; 152 153 # Redis is required for the sidekiq queue runner. 154 services.redis.enable = mkDefault true; 155 # We use postgres as the main data store. 156 services.postgresql.enable = mkDefault true; 157 services.postgresql.package = mkDefault pkgs.postgresql; 158 # Use postfix to send out mails. 159 services.postfix.enable = mkDefault true; 160 161 users.extraUsers = [ 162 { name = "gitlab"; 163 group = "gitlab"; 164 home = "${cfg.stateDir}/home"; 165 shell = "${pkgs.bash}/bin/bash"; 166 uid = config.ids.uids.gitlab; 167 } ]; 168 169 users.extraGroups = [ 170 { name = "gitlab"; 171 gid = config.ids.gids.gitlab; 172 } ]; 173 174 systemd.services.gitlab-sidekiq = { 175 after = [ "network.target" "redis.service" ]; 176 wantedBy = [ "multi-user.target" ]; 177 environment.HOME = "${cfg.stateDir}/home"; 178 environment.GEM_HOME = gemHome; 179 environment.UNICORN_PATH = "${cfg.stateDir}/"; 180 environment.GITLAB_PATH = "${pkgs.gitlab}/share/gitlab/"; 181 environment.GITLAB_APPLICATION_LOG_PATH = "${cfg.stateDir}/log/application.log"; 182 environment.GITLAB_SATELLITES_PATH = "${cfg.stateDir}/satellites"; 183 environment.GITLAB_SHELL_PATH = "${pkgs.gitlab-shell}"; 184 environment.GITLAB_REPOSITORIES_PATH = "${cfg.stateDir}/repositories"; 185 environment.GITLAB_SHELL_HOOKS_PATH = "${cfg.stateDir}/shell/hooks"; 186 environment.BUNDLE_GEMFILE = "${pkgs.gitlab}/share/gitlab/Gemfile"; 187 environment.GITLAB_EMAIL_FROM = "${cfg.emailFrom}"; 188 environment.GITLAB_SHELL_CONFIG_PATH = "${cfg.stateDir}/shell/config.yml"; 189 environment.GITLAB_SHELL_SECRET_PATH = "${cfg.stateDir}/config/gitlab_shell_secret"; 190 environment.GITLAB_HOST = "${cfg.host}"; 191 environment.GITLAB_PORT = "${toString cfg.port}"; 192 environment.GITLAB_DATABASE_HOST = "${cfg.databaseHost}"; 193 environment.GITLAB_DATABASE_PASSWORD = "${cfg.databasePassword}"; 194 environment.RAILS_ENV = "production"; 195 path = with pkgs; [ 196 config.services.postgresql.package 197 gitAndTools.git 198 ruby 199 openssh 200 nodejs 201 ]; 202 serviceConfig = { 203 Type = "simple"; 204 User = "gitlab"; 205 Group = "gitlab"; 206 TimeoutSec = "300"; 207 WorkingDirectory = "${pkgs.gitlab}/share/gitlab"; 208 ExecStart="${bundler}/bin/bundle exec \"sidekiq -q post_receive -q mailer -q system_hook -q project_web_hook -q gitlab_shell -q common -q default -e production -P ${cfg.stateDir}/tmp/sidekiq.pid\""; 209 }; 210 }; 211 212 systemd.services.gitlab = { 213 after = [ "network.target" "postgresql.service" "redis.service" ]; 214 wantedBy = [ "multi-user.target" ]; 215 environment.HOME = "${cfg.stateDir}/home"; 216 environment.GEM_HOME = gemHome; 217 environment.UNICORN_PATH = "${cfg.stateDir}/"; 218 environment.GITLAB_PATH = "${pkgs.gitlab}/share/gitlab/"; 219 environment.GITLAB_APPLICATION_LOG_PATH = "${cfg.stateDir}/log/application.log"; 220 environment.GITLAB_SATELLITES_PATH = "${cfg.stateDir}/satellites"; 221 environment.GITLAB_SHELL_PATH = "${pkgs.gitlab-shell}"; 222 environment.GITLAB_REPOSITORIES_PATH = "${cfg.stateDir}/repositories"; 223 environment.GITLAB_SHELL_HOOKS_PATH = "${cfg.stateDir}/shell/hooks"; 224 environment.BUNDLE_GEMFILE = "${pkgs.gitlab}/share/gitlab/Gemfile"; 225 environment.GITLAB_EMAIL_FROM = "${cfg.emailFrom}"; 226 environment.GITLAB_HOST = "${cfg.host}"; 227 environment.GITLAB_PORT = "${toString cfg.port}"; 228 environment.GITLAB_DATABASE_HOST = "${cfg.databaseHost}"; 229 environment.GITLAB_DATABASE_PASSWORD = "${cfg.databasePassword}"; 230 environment.RAILS_ENV = "production"; 231 path = with pkgs; [ 232 config.services.postgresql.package 233 gitAndTools.git 234 ruby 235 openssh 236 nodejs 237 ]; 238 preStart = '' 239 # TODO: use env vars 240 mkdir -p ${cfg.stateDir} 241 mkdir -p ${cfg.stateDir}/log 242 mkdir -p ${cfg.stateDir}/satellites 243 mkdir -p ${cfg.stateDir}/repositories 244 mkdir -p ${cfg.stateDir}/shell/hooks 245 mkdir -p ${cfg.stateDir}/tmp/pids 246 mkdir -p ${cfg.stateDir}/tmp/sockets 247 rm -rf ${cfg.stateDir}/config 248 mkdir -p ${cfg.stateDir}/config 249 # TODO: What exactly is gitlab-shell doing with the secret? 250 head -c 20 /dev/urandom > ${cfg.stateDir}/config/gitlab_shell_secret 251 mkdir -p ${cfg.stateDir}/home/.ssh 252 touch ${cfg.stateDir}/home/.ssh/authorized_keys 253 254 cp -rf ${pkgs.gitlab}/share/gitlab/config ${cfg.stateDir}/ 255 cp ${pkgs.gitlab}/share/gitlab/VERSION ${cfg.stateDir}/VERSION 256 257 ln -fs ${pkgs.writeText "database.yml" databaseYml} ${cfg.stateDir}/config/database.yml 258 ln -fs ${pkgs.writeText "unicorn.rb" unicornConfig} ${cfg.stateDir}/config/unicorn.rb 259 260 chown -R gitlab:gitlab ${cfg.stateDir}/ 261 chmod -R 755 ${cfg.stateDir}/ 262 263 if [ "${cfg.databaseHost}" = "127.0.0.1" ]; then 264 if ! test -e "${cfg.stateDir}/db-created"; then 265 psql postgres -c "CREATE ROLE gitlab WITH LOGIN NOCREATEDB NOCREATEROLE NOCREATEUSER ENCRYPTED PASSWORD '${cfg.databasePassword}'" 266 ${config.services.postgresql.package}/bin/createdb --owner gitlab gitlab || true 267 touch "${cfg.stateDir}/db-created" 268 269 # force=yes disables the manual-interaction yes/no prompt 270 # which breaks without an stdin. 271 force=yes ${bundler}/bin/bundle exec rake -f ${pkgs.gitlab}/share/gitlab/Rakefile gitlab:setup RAILS_ENV=production 272 fi 273 fi 274 275 # Install the shell required to push repositories 276 ln -fs ${pkgs.writeText "config.yml" gitlabShellYml} ${cfg.stateDir}/shell/config.yml 277 export GITLAB_SHELL_CONFIG_PATH=""${cfg.stateDir}/shell/config.yml 278 ${pkgs.gitlab-shell}/bin/install 279 280 # Change permissions in the last step because some of the 281 # intermediary scripts like to create directories as root. 282 chown -R gitlab:gitlab ${cfg.stateDir}/ 283 chmod -R 755 ${cfg.stateDir}/ 284 ''; 285 286 serviceConfig = { 287 PermissionsStartOnly = true; # preStart must be run as root 288 Type = "simple"; 289 User = "gitlab"; 290 Group = "gitlab"; 291 TimeoutSec = "300"; 292 WorkingDirectory = "${pkgs.gitlab}/share/gitlab"; 293 ExecStart="${bundler}/bin/bundle exec \"unicorn -c ${cfg.stateDir}/config/unicorn.rb -E production\""; 294 }; 295 296 }; 297 298 }; 299 300}