diff options
Diffstat (limited to 'nixos')
20 files changed, 482 insertions, 139 deletions
diff --git a/nixos/doc/manual/release-notes/rl-1903.xml b/nixos/doc/manual/release-notes/rl-1903.xml index 1d9b6ecc0e2e..fb5d475f693a 100644 --- a/nixos/doc/manual/release-notes/rl-1903.xml +++ b/nixos/doc/manual/release-notes/rl-1903.xml @@ -97,6 +97,16 @@ start org.nixos.nix-daemon</command>. </para> </listitem> + <listitem> + <para> + The Syncthing state and configuration data has been moved from + <varname>services.syncthing.dataDir</varname> to the newly defined + <varname>services.syncthing.configDir</varname>, which default to + <literal>/var/lib/syncthing/.config/syncthing</literal>. + This change makes possible to share synced directories using ACLs + without Syncthing resetting the permission on every start. + </para> + </listitem> </itemizedlist> </listitem> <listitem> @@ -154,6 +164,14 @@ </listitem> <listitem> <para> + Package <literal>consul-ui</literal> and passthrough <literal>consul.ui</literal> have been removed. + The package <literal>consul</literal> now uses upstream releases that vendor the UI into the binary. + See <link xlink:href="https://github.com/NixOS/nixpkgs/pull/48714#issuecomment-433454834">#48714</link> + for details. + </para> + </listitem> + <listitem> + <para> Slurm introduces the new option <literal>services.slurm.stateSaveLocation</literal>, which is now set to <literal>/var/spool/slurm</literal> by default diff --git a/nixos/modules/misc/ids.nix b/nixos/modules/misc/ids.nix index a32e4fe3f7c8..16737efb1856 100644 --- a/nixos/modules/misc/ids.nix +++ b/nixos/modules/misc/ids.nix @@ -332,6 +332,7 @@ lirc = 305; lidarr = 306; slurm = 307; + kapacitor = 308; # When adding a uid, make sure it doesn't match an existing gid. And don't use uids above 399! @@ -624,6 +625,7 @@ lirc = 305; lidarr = 306; slurm = 307; + kapacitor = 308; # When adding a gid, make sure it doesn't match an existing # uid. Users and groups with the same name should have equal diff --git a/nixos/modules/module-list.nix b/nixos/modules/module-list.nix index 660644eade8d..37e90232da2a 100644 --- a/nixos/modules/module-list.nix +++ b/nixos/modules/module-list.nix @@ -433,6 +433,7 @@ ./services/monitoring/hdaps.nix ./services/monitoring/heapster.nix ./services/monitoring/incron.nix + ./services/monitoring/kapacitor.nix ./services/monitoring/longview.nix ./services/monitoring/monit.nix ./services/monitoring/munin.nix diff --git a/nixos/modules/services/databases/postgresql.nix b/nixos/modules/services/databases/postgresql.nix index 6edb1503c233..f592be0e768b 100644 --- a/nixos/modules/services/databases/postgresql.nix +++ b/nixos/modules/services/databases/postgresql.nix @@ -271,5 +271,5 @@ in }; meta.doc = ./postgresql.xml; - + meta.maintainers = with lib.maintainers; [ thoughtpolice ]; } diff --git a/nixos/modules/services/misc/gitlab.nix b/nixos/modules/services/misc/gitlab.nix index 8ea831afb7c1..ce1cb6ad37f2 100644 --- a/nixos/modules/services/misc/gitlab.nix +++ b/nixos/modules/services/misc/gitlab.nix @@ -14,15 +14,16 @@ let pathUrlQuote = url: replaceStrings ["/"] ["%2F"] url; pgSuperUser = config.services.postgresql.superUser; - databaseYml = '' - production: - adapter: postgresql - database: ${cfg.databaseName} - host: ${cfg.databaseHost} - password: ${cfg.databasePassword} - username: ${cfg.databaseUsername} - encoding: utf8 - ''; + databaseConfig = { + production = { + adapter = "postgresql"; + database = cfg.databaseName; + host = cfg.databaseHost; + password = cfg.databasePassword; + username = cfg.databaseUsername; + encoding = "utf8"; + }; + }; gitalyToml = pkgs.writeText "gitaly.toml" '' socket_path = "${lib.escape ["\""] gitalySocket}" @@ -45,35 +46,31 @@ let '') gitlabConfig.production.repositories.storages))} ''; - gitlabShellYml = '' - user: ${cfg.user} - gitlab_url: "http+unix://${pathUrlQuote gitlabSocket}" - http_settings: - self_signed_cert: false - repos_path: "${cfg.statePath}/repositories" - secret_file: "${cfg.statePath}/config/gitlab_shell_secret" - log_file: "${cfg.statePath}/log/gitlab-shell.log" - custom_hooks_dir: "${cfg.statePath}/custom_hooks" - redis: - bin: ${pkgs.redis}/bin/redis-cli - host: 127.0.0.1 - port: 6379 - database: 0 - namespace: resque:gitlab - ''; + gitlabShellConfig = { + user = cfg.user; + gitlab_url = "http+unix://${pathUrlQuote gitlabSocket}"; + http_settings.self_signed_cert = false; + repos_path = "${cfg.statePath}/repositories"; + secret_file = "${cfg.statePath}/config/gitlab_shell_secret"; + log_file = "${cfg.statePath}/log/gitlab-shell.log"; + custom_hooks_dir = "${cfg.statePath}/custom_hooks"; + redis = { + bin = "${pkgs.redis}/bin/redis-cli"; + host = "127.0.0.1"; + port = 6379; + database = 0; + namespace = "resque:gitlab"; + }; + }; - redisYml = '' - production: - url: redis://localhost:6379/ - ''; + redisConfig.production.url = "redis://localhost:6379/"; - secretsYml = '' - production: - secret_key_base: ${cfg.secrets.secret} - otp_key_base: ${cfg.secrets.otp} - db_key_base: ${cfg.secrets.db} - openid_connect_signing_key: ${builtins.toJSON cfg.secrets.jws} - ''; + secretsConfig.production = { + secret_key_base = cfg.secrets.secret; + otp_key_base = cfg.secrets.otp; + db_key_base = cfg.secrets.db; + openid_connect_signing_key = cfg.secrets.jws; + }; gitlabConfig = { # These are the default settings from config/gitlab.example.yml @@ -115,12 +112,8 @@ let upload_pack = true; receive_pack = true; }; - workhorse = { - secret_file = "${cfg.statePath}/.gitlab_workhorse_secret"; - }; - git = { - bin_path = "git"; - }; + workhorse.secret_file = "${cfg.statePath}/.gitlab_workhorse_secret"; + git.bin_path = "git"; monitoring = { ip_whitelist = [ "127.0.0.0/8" "::1/128" ]; sidekiq_exporter = { @@ -138,7 +131,7 @@ let HOME = "${cfg.statePath}/home"; UNICORN_PATH = "${cfg.statePath}/"; GITLAB_PATH = "${cfg.packages.gitlab}/share/gitlab/"; - GITLAB_STATE_PATH = "${cfg.statePath}"; + GITLAB_STATE_PATH = cfg.statePath; GITLAB_UPLOADS_PATH = "${cfg.statePath}/uploads"; SCHEMA = "${cfg.statePath}/db/schema.rb"; GITLAB_LOG_PATH = "${cfg.statePath}/log"; @@ -146,13 +139,11 @@ let GITLAB_SHELL_CONFIG_PATH = "${cfg.statePath}/shell/config.yml"; GITLAB_SHELL_SECRET_PATH = "${cfg.statePath}/config/gitlab_shell_secret"; GITLAB_SHELL_HOOKS_PATH = "${cfg.statePath}/shell/hooks"; - GITLAB_REDIS_CONFIG_FILE = pkgs.writeText "gitlab-redis.yml" redisYml; + GITLAB_REDIS_CONFIG_FILE = pkgs.writeText "redis.yml" (builtins.toJSON redisConfig); prometheus_multiproc_dir = "/run/gitlab"; RAILS_ENV = "production"; }; - unicornConfig = builtins.readFile ./defaultUnicornConfig.rb; - gitlab-rake = pkgs.stdenv.mkDerivation rec { name = "gitlab-rake"; buildInputs = [ pkgs.makeWrapper ]; @@ -162,7 +153,6 @@ let mkdir -p $out/bin makeWrapper ${cfg.packages.gitlab.rubyEnv}/bin/rake $out/bin/gitlab-rake \ ${concatStrings (mapAttrsToList (name: value: "--set ${name} '${value}' ") gitlabEnv)} \ - --set GITLAB_CONFIG_PATH '${cfg.statePath}/config' \ --set PATH '${lib.makeBinPath [ pkgs.nodejs pkgs.gzip pkgs.git pkgs.gnutar config.services.postgresql.package pkgs.coreutils pkgs.procps ]}:$PATH' \ --set RAKEOPT '-f ${cfg.packages.gitlab}/share/gitlab/Rakefile' \ --run 'cd ${cfg.packages.gitlab}/share/gitlab' @@ -306,7 +296,6 @@ in { initialRootPassword = mkOption { type = types.str; - default = "UseNixOS!"; description = '' Initial password of the root account if this is a new install. ''; @@ -461,10 +450,30 @@ in { } ]; + systemd.tmpfiles.rules = [ + "d /run/gitlab 0755 ${cfg.user} ${cfg.group} -" + "d ${gitlabEnv.HOME} 0750 ${cfg.user} ${cfg.group} -" + "d ${cfg.backupPath} 0750 ${cfg.user} ${cfg.group} -" + "d ${cfg.statePath}/builds 0750 ${cfg.user} ${cfg.group} -" + "d ${cfg.statePath}/config 0750 ${cfg.user} ${cfg.group} -" + "d ${cfg.statePath}/db 0750 ${cfg.user} ${cfg.group} -" + "d ${cfg.statePath}/log 0750 ${cfg.user} ${cfg.group} -" + "d ${cfg.statePath}/repositories 2770 ${cfg.user} ${cfg.group} -" + "d ${cfg.statePath}/shell 0750 ${cfg.user} ${cfg.group} -" + "d ${cfg.statePath}/tmp/pids 0750 ${cfg.user} ${cfg.group} -" + "d ${cfg.statePath}/tmp/sockets 0750 ${cfg.user} ${cfg.group} -" + "d ${cfg.statePath}/uploads 0700 ${cfg.user} ${cfg.group} -" + "d ${cfg.statePath}/custom_hooks/pre-receive.d 0700 ${cfg.user} ${cfg.group} -" + "d ${cfg.statePath}/custom_hooks/post-receive.d 0700 ${cfg.user} ${cfg.group} -" + "d ${cfg.statePath}/custom_hooks/update.d 0700 ${cfg.user} ${cfg.group} -" + "d ${gitlabConfig.production.shared.path}/artifacts 0750 ${cfg.user} ${cfg.group} -" + "d ${gitlabConfig.production.shared.path}/lfs-objects 0750 ${cfg.user} ${cfg.group} -" + "d ${gitlabConfig.production.shared.path}/pages 0750 ${cfg.user} ${cfg.group} -" + ]; + systemd.services.gitlab-sidekiq = { - after = [ "network.target" "redis.service" ]; + after = [ "network.target" "redis.service" "gitlab.service" ]; wantedBy = [ "multi-user.target" ]; - partOf = [ "gitlab.service" ]; environment = gitlabEnv; path = with pkgs; [ config.services.postgresql.package @@ -486,10 +495,8 @@ in { }; systemd.services.gitaly = { - after = [ "network.target" "gitlab.service" ]; + after = [ "network.target" ]; wantedBy = [ "multi-user.target" ]; - environment.HOME = gitlabEnv.HOME; - environment.GITLAB_SHELL_CONFIG_PATH = gitlabEnv.GITLAB_SHELL_CONFIG_PATH; path = with pkgs; [ gitAndTools.git cfg.packages.gitaly.rubyEnv cfg.packages.gitaly.rubyEnv.wrappedRuby ]; serviceConfig = { Type = "simple"; @@ -505,8 +512,6 @@ in { systemd.services.gitlab-workhorse = { after = [ "network.target" ]; wantedBy = [ "multi-user.target" ]; - environment.HOME = gitlabEnv.HOME; - environment.GITLAB_SHELL_CONFIG_PATH = gitlabEnv.GITLAB_SHELL_CONFIG_PATH; path = with pkgs; [ gitAndTools.git gnutar @@ -514,10 +519,6 @@ in { openssh gitlab-workhorse ]; - preStart = '' - mkdir -p /run/gitlab - chown ${cfg.user}:${cfg.group} /run/gitlab - ''; serviceConfig = { PermissionsStartOnly = true; # preStart must be run as root Type = "simple"; @@ -538,7 +539,7 @@ in { }; systemd.services.gitlab = { - after = [ "network.target" "postgresql.service" "redis.service" ]; + after = [ "gitlab-workhorse.service" "gitaly.service" "network.target" "postgresql.service" "redis.service" ]; requires = [ "gitlab-sidekiq.service" ]; wantedBy = [ "multi-user.target" ]; environment = gitlabEnv; @@ -551,102 +552,75 @@ in { gnupg ]; preStart = '' - mkdir -p ${cfg.backupPath} - mkdir -p ${cfg.statePath}/builds - mkdir -p ${cfg.statePath}/repositories - mkdir -p ${gitlabConfig.production.shared.path}/artifacts - mkdir -p ${gitlabConfig.production.shared.path}/lfs-objects - mkdir -p ${gitlabConfig.production.shared.path}/pages - mkdir -p ${cfg.statePath}/log - mkdir -p ${cfg.statePath}/tmp/pids - mkdir -p ${cfg.statePath}/tmp/sockets - mkdir -p ${cfg.statePath}/shell - mkdir -p ${cfg.statePath}/db - mkdir -p ${cfg.statePath}/uploads - mkdir -p ${cfg.statePath}/custom_hooks/pre-receive.d - mkdir -p ${cfg.statePath}/custom_hooks/post-receive.d - mkdir -p ${cfg.statePath}/custom_hooks/update.d - - rm -rf ${cfg.statePath}/config ${cfg.statePath}/shell/hooks - mkdir -p ${cfg.statePath}/config - ${pkgs.openssl}/bin/openssl rand -hex 32 > ${cfg.statePath}/config/gitlab_shell_secret - mkdir -p /run/gitlab - mkdir -p ${cfg.statePath}/log - [ -d /run/gitlab/log ] || ln -sf ${cfg.statePath}/log /run/gitlab/log - [ -d /run/gitlab/tmp ] || ln -sf ${cfg.statePath}/tmp /run/gitlab/tmp - [ -d /run/gitlab/uploads ] || ln -sf ${cfg.statePath}/uploads /run/gitlab/uploads - ln -sf $GITLAB_SHELL_CONFIG_PATH /run/gitlab/shell-config.yml - chown -R ${cfg.user}:${cfg.group} /run/gitlab - - # Prepare home directory - mkdir -p ${gitlabEnv.HOME}/.ssh - touch ${gitlabEnv.HOME}/.ssh/authorized_keys - chown -R ${cfg.user}:${cfg.group} ${gitlabEnv.HOME}/ - cp -rf ${cfg.packages.gitlab}/share/gitlab/db/* ${cfg.statePath}/db cp -rf ${cfg.packages.gitlab}/share/gitlab/config.dist/* ${cfg.statePath}/config - ${optionalString cfg.smtp.enable '' - ln -sf ${smtpSettings} ${cfg.statePath}/config/initializers/smtp_settings.rb - ''} - ln -sf ${cfg.statePath}/config /run/gitlab/config if [ -e ${cfg.statePath}/lib ]; then rm ${cfg.statePath}/lib fi - ln -sf ${pkgs.gitlab}/share/gitlab/lib ${cfg.statePath}/lib + + ln -sf ${cfg.packages.gitlab}/share/gitlab/lib ${cfg.statePath}/lib + [ -L /run/gitlab/config ] || ln -sf ${cfg.statePath}/config /run/gitlab/config + [ -L /run/gitlab/log ] || ln -sf ${cfg.statePath}/log /run/gitlab/log + [ -L /run/gitlab/tmp ] || ln -sf ${cfg.statePath}/tmp /run/gitlab/tmp + [ -L /run/gitlab/uploads ] || ln -sf ${cfg.statePath}/uploads /run/gitlab/uploads + ${optionalString cfg.smtp.enable '' + ln -sf ${smtpSettings} ${cfg.statePath}/config/initializers/smtp_settings.rb + ''} cp ${cfg.packages.gitlab}/share/gitlab/VERSION ${cfg.statePath}/VERSION # JSON is a subset of YAML - ln -fs ${pkgs.writeText "gitlab.yml" (builtins.toJSON gitlabConfig)} ${cfg.statePath}/config/gitlab.yml - ln -fs ${pkgs.writeText "database.yml" databaseYml} ${cfg.statePath}/config/database.yml - ln -fs ${pkgs.writeText "secrets.yml" secretsYml} ${cfg.statePath}/config/secrets.yml - ln -fs ${pkgs.writeText "unicorn.rb" unicornConfig} ${cfg.statePath}/config/unicorn.rb - - chown -R ${cfg.user}:${cfg.group} ${cfg.statePath}/ - chmod -R ug+rwX,o-rwx+X ${cfg.statePath}/ + ln -sf ${pkgs.writeText "gitlab.yml" (builtins.toJSON gitlabConfig)} ${cfg.statePath}/config/gitlab.yml + ln -sf ${pkgs.writeText "database.yml" (builtins.toJSON databaseConfig)} ${cfg.statePath}/config/database.yml + ln -sf ${pkgs.writeText "secrets.yml" (builtins.toJSON secretsConfig)} ${cfg.statePath}/config/secrets.yml + ln -sf ${./defaultUnicornConfig.rb} ${cfg.statePath}/config/unicorn.rb # Install the shell required to push repositories - ln -fs ${pkgs.writeText "config.yml" gitlabShellYml} "$GITLAB_SHELL_CONFIG_PATH" - ln -fs ${cfg.packages.gitlab-shell}/hooks "$GITLAB_SHELL_HOOKS_PATH" + ln -sf ${pkgs.writeText "config.yml" (builtins.toJSON gitlabShellConfig)} /run/gitlab/shell-config.yml + [ -L ${cfg.statePath}/shell/hooks ] || ln -sf ${cfg.packages.gitlab-shell}/hooks ${cfg.statePath}/shell/hooks ${cfg.packages.gitlab-shell}/bin/install - if [ "${cfg.databaseHost}" = "127.0.0.1" ]; then - if ! test -e "${cfg.statePath}/db-created"; then + chown -R ${cfg.user}:${cfg.group} ${cfg.statePath}/ + chmod -R ug+rwX,o-rwx+X ${cfg.statePath}/ + chown -R ${cfg.user}:${cfg.group} /run/gitlab + + if ! test -e "${cfg.statePath}/db-created"; then + if [ "${cfg.databaseHost}" = "127.0.0.1" ]; then ${pkgs.sudo}/bin/sudo -u ${pgSuperUser} psql postgres -c "CREATE ROLE ${cfg.databaseUsername} WITH LOGIN NOCREATEDB NOCREATEROLE ENCRYPTED PASSWORD '${cfg.databasePassword}'" ${pkgs.sudo}/bin/sudo -u ${pgSuperUser} ${config.services.postgresql.package}/bin/createdb --owner ${cfg.databaseUsername} ${cfg.databaseName} - touch "${cfg.statePath}/db-created" + + # enable required pg_trgm extension for gitlab + ${pkgs.sudo}/bin/sudo -u ${pgSuperUser} psql ${cfg.databaseName} -c "CREATE EXTENSION IF NOT EXISTS pg_trgm" fi - # enable required pg_trgm extension for gitlab - ${pkgs.sudo}/bin/sudo -u ${pgSuperUser} psql ${cfg.databaseName} -c "CREATE EXTENSION IF NOT EXISTS pg_trgm" + ${pkgs.sudo}/bin/sudo -u ${cfg.user} -H ${gitlab-rake}/bin/gitlab-rake db:schema:load + + touch "${cfg.statePath}/db-created" fi # Always do the db migrations just to be sure the database is up-to-date - ${gitlab-rake}/bin/gitlab-rake db:migrate RAILS_ENV=production + ${pkgs.sudo}/bin/sudo -u ${cfg.user} -H ${gitlab-rake}/bin/gitlab-rake db:migrate - # The gitlab:setup task is horribly broken somehow, the db:migrate - # task above and the db:seed_fu below will do the same for setting - # up the initial database if ! test -e "${cfg.statePath}/db-seeded"; then - ${gitlab-rake}/bin/gitlab-rake db:seed_fu RAILS_ENV=production \ + ${pkgs.sudo}/bin/sudo -u ${cfg.user} ${gitlab-rake}/bin/gitlab-rake db:seed_fu \ GITLAB_ROOT_PASSWORD='${cfg.initialRootPassword}' GITLAB_ROOT_EMAIL='${cfg.initialRootEmail}' touch "${cfg.statePath}/db-seeded" fi # The gitlab:shell:setup regenerates the authorized_keys file so that # the store path to the gitlab-shell in it gets updated - ${pkgs.sudo}/bin/sudo -u ${cfg.user} force=yes ${gitlab-rake}/bin/gitlab-rake gitlab:shell:setup RAILS_ENV=production + ${pkgs.sudo}/bin/sudo -u ${cfg.user} -H force=yes ${gitlab-rake}/bin/gitlab-rake gitlab:shell:setup # The gitlab:shell:create_hooks task seems broken for fixing links # so we instead delete all the hooks and create them anew rm -f ${cfg.statePath}/repositories/**/*.git/hooks - ${gitlab-rake}/bin/gitlab-rake gitlab:shell:create_hooks RAILS_ENV=production + ${pkgs.sudo}/bin/sudo -u ${cfg.user} -H ${gitlab-rake}/bin/gitlab-rake gitlab:shell:create_hooks + + ${pkgs.sudo}/bin/sudo -u ${cfg.user} -H ${pkgs.git}/bin/git config --global core.autocrlf "input" # Change permissions in the last step because some of the # intermediary scripts like to create directories as root. - chown -R ${cfg.user}:${cfg.group} ${cfg.statePath} - chmod -R ug+rwX,o-rwx+X ${cfg.statePath} chmod -R u+rwX,go-rwx+X ${gitlabEnv.HOME} chmod -R ug+rwX,o-rwx ${cfg.statePath}/repositories chmod -R ug-s ${cfg.statePath}/repositories diff --git a/nixos/modules/services/monitoring/kapacitor.nix b/nixos/modules/services/monitoring/kapacitor.nix new file mode 100644 index 000000000000..1de0a8d5af2f --- /dev/null +++ b/nixos/modules/services/monitoring/kapacitor.nix @@ -0,0 +1,154 @@ +{ options, config, lib, pkgs, ... }: + +with lib; + +let + cfg = config.services.kapacitor; + + kapacitorConf = pkgs.writeTextFile { + name = "kapacitord.conf"; + text = '' + hostname="${config.networking.hostName}" + data_dir="${cfg.dataDir}" + + [http] + bind-address = "${cfg.bind}:${toString cfg.port}" + log-enabled = false + auth-enabled = false + + [task] + dir = "${cfg.dataDir}/tasks" + snapshot-interval = "${cfg.taskSnapshotInterval}" + + [replay] + dir = "${cfg.dataDir}/replay" + + [storage] + boltdb = "${cfg.dataDir}/kapacitor.db" + + ${optionalString (cfg.loadDirectory != null) '' + [load] + enabled = true + dir = "${cfg.loadDirectory}" + ''} + + ${optionalString (cfg.defaultDatabase.enable) '' + [[influxdb]] + name = "default" + enabled = true + default = true + urls = [ "${cfg.defaultDatabase.url}" ] + username = "${cfg.defaultDatabase.username}" + password = "${cfg.defaultDatabase.password}" + ''} + + ${cfg.extraConfig} + ''; + }; +in +{ + options.services.kapacitor = { + enable = mkEnableOption "kapacitor"; + + dataDir = mkOption { + type = types.path; + example = "/var/lib/kapacitor"; + default = "/var/lib/kapacitor"; + description = "Location where Kapacitor stores its state"; + }; + + port = mkOption { + type = types.int; + default = 9092; + description = "Port of Kapacitor"; + }; + + bind = mkOption { + type = types.str; + default = ""; + example = literalExample "0.0.0.0"; + description = "Address to bind to. The default is to bind to all addresses"; + }; + + extraConfig = mkOption { + description = "These lines go into kapacitord.conf verbatim."; + default = ""; + type = types.lines; + }; + + user = mkOption { + type = types.str; + default = "kapacitor"; + description = "User account under which Kapacitor runs"; + }; + + group = mkOption { + type = types.str; + default = "kapacitor"; + description = "Group under which Kapacitor runs"; + }; + + taskSnapshotInterval = mkOption { + type = types.str; + description = "Specifies how often to snapshot the task state (in InfluxDB time units)"; + default = "1m0s"; + example = "1m0s"; + }; + + loadDirectory = mkOption { + type = types.nullOr types.path; + description = "Directory where to load services from, such as tasks, templates and handlers (or null to disable service loading on startup)"; + default = null; + }; + + defaultDatabase = { + enable = mkEnableOption "kapacitor.defaultDatabase"; + + url = mkOption { + description = "The URL to an InfluxDB server that serves as the default database"; + example = "http://localhost:8086"; + type = types.string; + }; + + username = mkOption { + description = "The username to connect to the remote InfluxDB server"; + type = types.string; + }; + + password = mkOption { + description = "The password to connect to the remote InfluxDB server"; + type = types.string; + }; + }; + }; + + config = mkIf cfg.enable { + environment.systemPackages = [ pkgs.kapacitor ]; + + systemd.services.kapacitor = { + description = "Kapacitor Real-Time Stream Processing Engine"; + wantedBy = [ "multi-user.target" ]; + after = [ "networking.target" ]; + serviceConfig = { + ExecStart = "${pkgs.kapacitor}/bin/kapacitord -config ${kapacitorConf}"; + User = "kapacitor"; + Group = "kapacitor"; + PermissionsStartOnly = true; + }; + preStart = '' + mkdir -p ${cfg.dataDir} + chown ${cfg.user}:${cfg.group} ${cfg.dataDir} + ''; + }; + + users.users.kapacitor = { + uid = config.ids.uids.kapacitor; + description = "Kapacitor user"; + home = cfg.dataDir; + }; + + users.groups.kapacitor = { + gid = config.ids.gids.kapacitor; + }; + }; +} diff --git a/nixos/modules/services/networking/chrony.nix b/nixos/modules/services/networking/chrony.nix index a363b545d649..9b8005e706ae 100644 --- a/nixos/modules/services/networking/chrony.nix +++ b/nixos/modules/services/networking/chrony.nix @@ -93,6 +93,8 @@ in services.timesyncd.enable = mkForce false; + systemd.services.systemd-timedated.environment = { SYSTEMD_TIMEDATED_NTP_SERVICES = "chronyd.service"; }; + systemd.services.chronyd = { description = "chrony NTP daemon"; diff --git a/nixos/modules/services/networking/consul.nix b/nixos/modules/services/networking/consul.nix index ab3f81037681..0e90fed788b9 100644 --- a/nixos/modules/services/networking/consul.nix +++ b/nixos/modules/services/networking/consul.nix @@ -6,9 +6,10 @@ let dataDir = "/var/lib/consul"; cfg = config.services.consul; - configOptions = { data_dir = dataDir; } // - (if cfg.webUi then { ui_dir = "${cfg.package.ui}"; } else { }) // - cfg.extraConfig; + configOptions = { + data_dir = dataDir; + ui = cfg.webUi; + } // cfg.extraConfig; configFiles = [ "/etc/consul.json" "/etc/consul-addrs.json" ] ++ cfg.extraConfigFiles; diff --git a/nixos/modules/services/networking/ntpd.nix b/nixos/modules/services/networking/ntpd.nix index 342350d49ab3..32174100b0f7 100644 --- a/nixos/modules/services/networking/ntpd.nix +++ b/nixos/modules/services/networking/ntpd.nix @@ -67,6 +67,8 @@ in environment.systemPackages = [ pkgs.ntp ]; services.timesyncd.enable = mkForce false; + systemd.services.systemd-timedated.environment = { SYSTEMD_TIMEDATED_NTP_SERVICES = "ntpd.service"; }; + users.users = singleton { name = ntpUser; uid = config.ids.uids.ntp; diff --git a/nixos/modules/services/networking/syncthing.nix b/nixos/modules/services/networking/syncthing.nix index fd31b2a67687..b2ef1885a955 100644 --- a/nixos/modules/services/networking/syncthing.nix +++ b/nixos/modules/services/networking/syncthing.nix @@ -63,8 +63,20 @@ in { type = types.path; default = "/var/lib/syncthing"; description = '' + Path where synced directories will exist. + ''; + }; + + configDir = mkOption { + type = types.path; + description = '' Path where the settings and keys will exist. ''; + default = + let + nixos = config.system.stateVersion; + cond = versionAtLeast nixos "19.03"; + in cfg.dataDir + (optionalString cond "/.config/syncthing"); }; openDefaultPorts = mkOption { @@ -144,7 +156,7 @@ in { ${cfg.package}/bin/syncthing \ -no-browser \ -gui-address=${cfg.guiAddress} \ - -home=${cfg.dataDir} + -home=${cfg.configDir} ''; }; }; diff --git a/nixos/modules/services/networking/zerotierone.nix b/nixos/modules/services/networking/zerotierone.nix index a4cd368397e7..764af3846fe5 100644 --- a/nixos/modules/services/networking/zerotierone.nix +++ b/nixos/modules/services/networking/zerotierone.nix @@ -39,7 +39,8 @@ in systemd.services.zerotierone = { description = "ZeroTierOne"; path = [ cfg.package ]; - after = [ "network.target" ]; + bindsTo = [ "network-online.target" ]; + after = [ "network-online.target" ]; wantedBy = [ "multi-user.target" ]; preStart = '' mkdir -p /var/lib/zerotier-one/networks.d diff --git a/nixos/modules/system/activation/activation-script.nix b/nixos/modules/system/activation/activation-script.nix index 0ed7c0f53eb9..74c150a848d1 100644 --- a/nixos/modules/system/activation/activation-script.nix +++ b/nixos/modules/system/activation/activation-script.nix @@ -22,6 +22,7 @@ let gnugrep findutils getent + stdenv.cc.libc # nscd in update-users-groups.pl shadow nettools # needed for hostname utillinux # needed for mount and mountpoint diff --git a/nixos/modules/virtualisation/amazon-image.nix b/nixos/modules/virtualisation/amazon-image.nix index c92570582f20..9015200beead 100644 --- a/nixos/modules/virtualisation/amazon-image.nix +++ b/nixos/modules/virtualisation/amazon-image.nix @@ -53,7 +53,7 @@ let cfg = config.ec2; in # Mount all formatted ephemeral disks and activate all swap devices. # We cannot do this with the ‘fileSystems’ and ‘swapDevices’ options # because the set of devices is dependent on the instance type - # (e.g. "m1.large" has one ephemeral filesystem and one swap device, + # (e.g. "m1.small" has one ephemeral filesystem and one swap device, # while "m1.large" has two ephemeral filesystems and no swap # devices). Also, put /tmp and /var on /disk0, since it has a lot # more space than the root device. Similarly, "move" /nix to /disk0 diff --git a/nixos/modules/virtualisation/docker-preloader.nix b/nixos/modules/virtualisation/docker-preloader.nix new file mode 100644 index 000000000000..faa94f53d98f --- /dev/null +++ b/nixos/modules/virtualisation/docker-preloader.nix @@ -0,0 +1,135 @@ +{ config, lib, pkgs, ... }: + +with lib; +with builtins; + +let + cfg = config.virtualisation; + + sanitizeImageName = image: replaceStrings ["/"] ["-"] image.imageName; + hash = drv: head (split "-" (baseNameOf drv.outPath)); + # The label of an ext4 FS is limited to 16 bytes + labelFromImage = image: substring 0 16 (hash image); + + # The Docker image is loaded and some files from /var/lib/docker/ + # are written into a qcow image. + preload = image: pkgs.vmTools.runInLinuxVM ( + pkgs.runCommand "docker-preload-image-${sanitizeImageName image}" { + buildInputs = with pkgs; [ docker e2fsprogs utillinux curl kmod ]; + preVM = pkgs.vmTools.createEmptyImage { + size = cfg.dockerPreloader.qcowSize; + fullName = "docker-deamon-image.qcow2"; + }; + } + '' + mkfs.ext4 /dev/vda + e2label /dev/vda ${labelFromImage image} + mkdir -p /var/lib/docker + mount -t ext4 /dev/vda /var/lib/docker + + modprobe overlay + + # from https://github.com/tianon/cgroupfs-mount/blob/master/cgroupfs-mount + mount -t tmpfs -o uid=0,gid=0,mode=0755 cgroup /sys/fs/cgroup + cd /sys/fs/cgroup + for sys in $(awk '!/^#/ { if ($4 == 1) print $1 }' /proc/cgroups); do + mkdir -p $sys + if ! mountpoint -q $sys; then + if ! mount -n -t cgroup -o $sys cgroup $sys; then + rmdir $sys || true + fi + fi + done + + dockerd -H tcp://127.0.0.1:5555 -H unix:///var/run/docker.sock & + + until $(curl --output /dev/null --silent --connect-timeout 2 http://127.0.0.1:5555); do + printf '.' + sleep 1 + done + + docker load -i ${image} + + kill %1 + find /var/lib/docker/ -maxdepth 1 -mindepth 1 -not -name "image" -not -name "overlay2" | xargs rm -rf + ''); + + preloadedImages = map preload cfg.dockerPreloader.images; + +in + +{ + options.virtualisation.dockerPreloader = { + images = mkOption { + default = [ ]; + type = types.listOf types.package; + description = + '' + A list of Docker images to preload (in the /var/lib/docker directory). + ''; + }; + qcowSize = mkOption { + default = 1024; + type = types.int; + description = + '' + The size (MB) of qcow files. + ''; + }; + }; + + config = { + assertions = [{ + # If docker.storageDriver is null, Docker choose the storage + # driver. So, in this case, we cannot be sure overlay2 is used. + assertion = cfg.dockerPreloader.images == [] + || cfg.docker.storageDriver == "overlay2" + || cfg.docker.storageDriver == "overlay" + || cfg.docker.storageDriver == null; + message = "The Docker image Preloader only works with overlay2 storage driver!"; + }]; + + virtualisation.qemu.options = + map (path: "-drive if=virtio,file=${path}/disk-image.qcow2,readonly,media=cdrom,format=qcow2") + preloadedImages; + + + # All attached QCOW files are mounted and their contents are linked + # to /var/lib/docker/ in order to make image available. + systemd.services.docker-preloader = { + description = "Preloaded Docker images"; + wantedBy = ["docker.service"]; + after = ["network.target"]; + path = with pkgs; [ mount rsync jq ]; + script = '' + mkdir -p /var/lib/docker/overlay2/l /var/lib/docker/image/overlay2 + echo '{}' > /tmp/repositories.json + + for i in ${concatStringsSep " " (map labelFromImage cfg.dockerPreloader.images)}; do + mkdir -p /mnt/docker-images/$i + + # The ext4 label is limited to 16 bytes + mount /dev/disk/by-label/$(echo $i | cut -c1-16) -o ro,noload /mnt/docker-images/$i + + find /mnt/docker-images/$i/overlay2/ -maxdepth 1 -mindepth 1 -not -name l\ + -exec ln -s '{}' /var/lib/docker/overlay2/ \; + cp -P /mnt/docker-images/$i/overlay2/l/* /var/lib/docker/overlay2/l/ + + rsync -a /mnt/docker-images/$i/image/ /var/lib/docker/image/ + + # Accumulate image definitions + cp /tmp/repositories.json /tmp/repositories.json.tmp + jq -s '.[0] * .[1]' \ + /tmp/repositories.json.tmp \ + /mnt/docker-images/$i/image/overlay2/repositories.json \ + > /tmp/repositories.json + done + + mv /tmp/repositories.json /var/lib/docker/image/overlay2/repositories.json + ''; + serviceConfig = { + Type = "oneshot"; + }; + }; + }; +} diff --git a/nixos/modules/virtualisation/google-compute-image.nix b/nixos/modules/virtualisation/google-compute-image.nix index caaf6c0aa59d..795858e5eae2 100644 --- a/nixos/modules/virtualisation/google-compute-image.nix +++ b/nixos/modules/virtualisation/google-compute-image.nix @@ -144,7 +144,6 @@ in path = with pkgs; [ iproute ]; serviceConfig = { ExecStart = "${gce}/bin/google_network_daemon --debug"; - Type = "oneshot"; }; }; diff --git a/nixos/modules/virtualisation/qemu-vm.nix b/nixos/modules/virtualisation/qemu-vm.nix index 4e9c87222d0a..ed3431554be4 100644 --- a/nixos/modules/virtualisation/qemu-vm.nix +++ b/nixos/modules/virtualisation/qemu-vm.nix @@ -185,7 +185,10 @@ let in { - imports = [ ../profiles/qemu-guest.nix ]; + imports = [ + ../profiles/qemu-guest.nix + ./docker-preloader.nix + ]; options = { diff --git a/nixos/release.nix b/nixos/release.nix index 51505d6aab9d..c3a10c9d3300 100644 --- a/nixos/release.nix +++ b/nixos/release.nix @@ -283,6 +283,7 @@ in rec { tests.docker-tools = callTestOnMatchingSystems ["x86_64-linux"] tests/docker-tools.nix {}; tests.docker-tools-overlay = callTestOnMatchingSystems ["x86_64-linux"] tests/docker-tools-overlay.nix {}; tests.docker-edge = callTestOnMatchingSystems ["x86_64-linux"] tests/docker-edge.nix {}; + tests.docker-preloader = callTestOnMatchingSystems ["x86_64-linux"] tests/docker-preloader.nix {}; tests.docker-registry = callTest tests/docker-registry.nix {}; tests.dovecot = callTest tests/dovecot.nix {}; tests.dnscrypt-proxy = callTestOnMatchingSystems ["x86_64-linux"] tests/dnscrypt-proxy.nix {}; @@ -300,7 +301,7 @@ in rec { tests.fsck = callTest tests/fsck.nix {}; tests.fwupd = callTest tests/fwupd.nix {}; tests.gdk-pixbuf = callTest tests/gdk-pixbuf.nix {}; - #tests.gitlab = callTest tests/gitlab.nix {}; + tests.gitlab = callTest tests/gitlab.nix {}; tests.gitolite = callTest tests/gitolite.nix {}; tests.gjs = callTest tests/gjs.nix {}; tests.gocd-agent = callTest tests/gocd-agent.nix {}; diff --git a/nixos/tests/chromium.nix b/nixos/tests/chromium.nix index c341e83961a8..e5097609fb27 100644 --- a/nixos/tests/chromium.nix +++ b/nixos/tests/chromium.nix @@ -12,8 +12,10 @@ with pkgs.lib; mapAttrs (channel: chromiumPkg: makeTest rec { name = "chromium-${channel}"; - meta = with pkgs.stdenv.lib.maintainers; { - maintainers = [ aszlig ]; + meta = { + maintainers = with maintainers; [ aszlig ]; + # https://github.com/NixOS/hydra/issues/591#issuecomment-435125621 + inherit (chromiumPkg.meta) timeout; }; enableOCR = true; @@ -166,7 +168,7 @@ mapAttrs (channel: chromiumPkg: makeTest rec { my $clipboard = $machine->succeed(ru "${pkgs.xclip}/bin/xclip -o"); die "sandbox not working properly: $clipboard" - unless $clipboard =~ /namespace sandbox.*yes/mi + unless $clipboard =~ /layer 1 sandbox.*namespace/mi && $clipboard =~ /pid namespaces.*yes/mi && $clipboard =~ /network namespaces.*yes/mi && $clipboard =~ /seccomp.*sandbox.*yes/mi @@ -184,7 +186,7 @@ mapAttrs (channel: chromiumPkg: makeTest rec { my $clipboard = $machine->succeed(ru "${pkgs.xclip}/bin/xclip -o"); die "copying twice in a row does not work properly: $clipboard" - unless $clipboard =~ /namespace sandbox.*yes/mi + unless $clipboard =~ /layer 1 sandbox.*namespace/mi && $clipboard =~ /pid namespaces.*yes/mi && $clipboard =~ /network namespaces.*yes/mi && $clipboard =~ /seccomp.*sandbox.*yes/mi diff --git a/nixos/tests/docker-preloader.nix b/nixos/tests/docker-preloader.nix new file mode 100644 index 000000000000..eeedec9a392e --- /dev/null +++ b/nixos/tests/docker-preloader.nix @@ -0,0 +1,27 @@ +import ./make-test.nix ({ pkgs, ...} : { + name = "docker-preloader"; + meta = with pkgs.stdenv.lib.maintainers; { + maintainers = [ lewo ]; + }; + + nodes = { + docker = + { pkgs, ... }: + { + virtualisation.docker.enable = true; + virtualisation.dockerPreloader.images = [ pkgs.dockerTools.examples.nix pkgs.dockerTools.examples.bash ]; + + services.openssh.enable = true; + services.openssh.permitRootLogin = "yes"; + services.openssh.extraConfig = "PermitEmptyPasswords yes"; + users.extraUsers.root.password = ""; + }; + }; + testScript = '' + startAll; + + $docker->waitForUnit("sockets.target"); + $docker->succeed("docker run nix nix-store --version"); + $docker->succeed("docker run bash bash --version"); + ''; +}) diff --git a/nixos/tests/gitlab.nix b/nixos/tests/gitlab.nix index 3af2cbcd0988..53675c375e31 100644 --- a/nixos/tests/gitlab.nix +++ b/nixos/tests/gitlab.nix @@ -1,14 +1,18 @@ # This test runs gitlab and checks if it works -import ./make-test.nix ({ pkgs, ...} : { +import ./make-test.nix ({ pkgs, lib, ...} : with lib; { name = "gitlab"; meta = with pkgs.stdenv.lib.maintainers; { - maintainers = [ domenkozar offline ]; + maintainers = [ globin ]; }; nodes = { gitlab = { ... }: { - virtualisation.memorySize = 768; + virtualisation.memorySize = 4096; + systemd.services.gitlab.serviceConfig.Restart = mkForce "no"; + systemd.services.gitlab-workhorse.serviceConfig.Restart = mkForce "no"; + systemd.services.gitaly.serviceConfig.Restart = mkForce "no"; + systemd.services.gitlab-sidekiq.serviceConfig.Restart = mkForce "no"; services.nginx = { enable = true; @@ -19,10 +23,10 @@ import ./make-test.nix ({ pkgs, ...} : { }; }; - systemd.services.gitlab.serviceConfig.TimeoutStartSec = "10min"; services.gitlab = { enable = true; databasePassword = "dbPassword"; + initialRootPassword = "notproduction"; secrets = { secret = "secret"; otp = "otpsecret"; @@ -65,8 +69,12 @@ import ./make-test.nix ({ pkgs, ...} : { testScript = '' $gitlab->start(); + $gitlab->waitForUnit("gitaly.service"); + $gitlab->waitForUnit("gitlab-workhorse.service"); $gitlab->waitForUnit("gitlab.service"); $gitlab->waitForUnit("gitlab-sidekiq.service"); - $gitlab->waitUntilSucceeds("curl http://localhost:80/users/sign_in"); + $gitlab->waitForFile("/var/gitlab/state/tmp/sockets/gitlab.socket"); + $gitlab->waitUntilSucceeds("curl -sSf http://localhost/users/sign_in"); + $gitlab->succeed("${pkgs.sudo}/bin/sudo -u gitlab -H gitlab-rake gitlab:check 1>&2") ''; }) |