diff options
author | Vladimír Čunát <vcunat@gmail.com> | 2016-03-08 09:57:58 +0100 |
---|---|---|
committer | Vladimír Čunát <vcunat@gmail.com> | 2016-03-08 09:58:19 +0100 |
commit | 09af15654f0c8091f1b9e0bbb2e523cdee194442 (patch) | |
tree | e648edef1ce4c64c533f2593aa22b8015cf0e506 /nixos/modules/services/misc | |
parent | f306e67e15bdbe9a8358c9f81319fc4fcbadc2eb (diff) | |
parent | 0ee75214f336474e127c2e3546c0406a0c4d5fa7 (diff) | |
download | nixpkgs-09af15654f0c8091f1b9e0bbb2e523cdee194442.tar nixpkgs-09af15654f0c8091f1b9e0bbb2e523cdee194442.tar.gz nixpkgs-09af15654f0c8091f1b9e0bbb2e523cdee194442.tar.bz2 nixpkgs-09af15654f0c8091f1b9e0bbb2e523cdee194442.tar.lz nixpkgs-09af15654f0c8091f1b9e0bbb2e523cdee194442.tar.xz nixpkgs-09af15654f0c8091f1b9e0bbb2e523cdee194442.tar.zst nixpkgs-09af15654f0c8091f1b9e0bbb2e523cdee194442.zip |
Merge master into closure-size
The kde-5 stuff still didn't merge well. I hand-fixed what I saw, but there may be more problems.
Diffstat (limited to 'nixos/modules/services/misc')
-rw-r--r-- | nixos/modules/services/misc/bepasty.nix | 8 | ||||
-rw-r--r-- | nixos/modules/services/misc/cfdyndns.nix | 70 | ||||
-rw-r--r-- | nixos/modules/services/misc/defaultUnicornConfig.rb | 1 | ||||
-rw-r--r-- | nixos/modules/services/misc/gammu-smsd.nix | 253 | ||||
-rw-r--r-- | nixos/modules/services/misc/gitlab.nix | 390 | ||||
-rw-r--r-- | nixos/modules/services/misc/gitlab.xml | 103 | ||||
-rw-r--r-- | nixos/modules/services/misc/matrix-synapse.nix | 1 | ||||
-rw-r--r-- | nixos/modules/services/misc/nix-daemon.nix | 2 | ||||
-rw-r--r-- | nixos/modules/services/misc/nixos-manual.nix | 38 | ||||
-rw-r--r-- | nixos/modules/services/misc/octoprint.nix | 120 | ||||
-rw-r--r-- | nixos/modules/services/misc/plex.nix | 1 | ||||
-rw-r--r-- | nixos/modules/services/misc/spice-vdagentd.nix | 30 | ||||
-rw-r--r-- | nixos/modules/services/misc/subsonic.nix | 4 |
13 files changed, 878 insertions, 143 deletions
diff --git a/nixos/modules/services/misc/bepasty.nix b/nixos/modules/services/misc/bepasty.nix index 12671cb1b6c..5bda73ab64f 100644 --- a/nixos/modules/services/misc/bepasty.nix +++ b/nixos/modules/services/misc/bepasty.nix @@ -103,9 +103,13 @@ in after = [ "network.target" ]; restartIfChanged = true; - environment = { + environment = let + penv = python.buildEnv.override { + extraLibs = [ bepasty gevent ]; + }; + in { BEPASTY_CONFIG = "${server.workDir}/bepasty-${name}.conf"; - PYTHONPATH= "${bepasty}/lib/${python.libPrefix}/site-packages:${gevent}/lib/${python.libPrefix}/site-packages"; + PYTHONPATH= "${penv}/${python.sitePackages}/"; }; serviceConfig = { diff --git a/nixos/modules/services/misc/cfdyndns.nix b/nixos/modules/services/misc/cfdyndns.nix new file mode 100644 index 00000000000..69a33d0b8c1 --- /dev/null +++ b/nixos/modules/services/misc/cfdyndns.nix @@ -0,0 +1,70 @@ +{ config, pkgs, lib, ... }: + +with lib; + +let + cfg = config.services.cfdyndns; +in +{ + options = { + services.cfdyndns = { + enable = mkEnableOption "Cloudflare Dynamic DNS Client"; + + email = mkOption { + type = types.str; + description = '' + The email address to use to authenticate to CloudFlare. + ''; + }; + + apikey = mkOption { + type = types.str; + description = '' + The API Key to use to authenticate to CloudFlare. + ''; + }; + + records = mkOption { + default = []; + example = [ "host.tld" ]; + type = types.listOf types.str; + description = '' + The records to update in CloudFlare. + ''; + }; + }; + }; + + config = mkIf cfg.enable { + systemd.services.cfdyndns = { + description = "CloudFlare Dynamic DNS Client"; + after = [ "network.target" ]; + wantedBy = [ "multi-user.target" ]; + startAt = "5 minutes"; + serviceConfig = { + Type = "simple"; + User = config.ids.uids.cfdyndns; + Group = config.ids.gids.cfdyndns; + ExecStart = "/bin/sh -c '${pkgs.cfdyndns}/bin/cfdyndns'"; + }; + environment = { + CLOUDFLARE_EMAIL="${cfg.email}"; + CLOUDFLARE_APIKEY="${cfg.apikey}"; + CLOUDFLARE_RECORDS="${concatStringsSep "," cfg.records}"; + }; + }; + + users.extraUsers = { + cfdyndns = { + group = "cfdyndns"; + uid = config.ids.uids.cfdyndns; + }; + }; + + users.extraGroups = { + cfdyndns = { + gid = config.ids.gids.cfdyndns; + }; + }; + }; +} diff --git a/nixos/modules/services/misc/defaultUnicornConfig.rb b/nixos/modules/services/misc/defaultUnicornConfig.rb index 81abaf336dc..84622622db7 100644 --- a/nixos/modules/services/misc/defaultUnicornConfig.rb +++ b/nixos/modules/services/misc/defaultUnicornConfig.rb @@ -187,7 +187,6 @@ working_directory ENV["GITLAB_PATH"] pid ENV["UNICORN_PATH"] + "/tmp/pids/unicorn.pid" listen ENV["UNICORN_PATH"] + "/tmp/sockets/gitlab.socket", :backlog => 1024 -listen "127.0.0.1:8080", :tcp_nopush => true timeout 60 diff --git a/nixos/modules/services/misc/gammu-smsd.nix b/nixos/modules/services/misc/gammu-smsd.nix new file mode 100644 index 00000000000..91047ead436 --- /dev/null +++ b/nixos/modules/services/misc/gammu-smsd.nix @@ -0,0 +1,253 @@ +{ pkgs, lib, config, ... }: + +with lib; +let + cfg = config.services.gammu-smsd; + + configFile = pkgs.writeText "gammu-smsd.conf" '' + [gammu] + Device = ${cfg.device.path} + Connection = ${cfg.device.connection} + SynchronizeTime = ${if cfg.device.synchronizeTime then "yes" else "no"} + LogFormat = ${cfg.log.format} + ${if (cfg.device.pin != null) then "PIN = ${cfg.device.pin}" else ""} + ${cfg.extraConfig.gammu} + + + [smsd] + LogFile = ${cfg.log.file} + Service = ${cfg.backend.service} + + ${optionalString (cfg.backend.service == "files") '' + InboxPath = ${cfg.backend.files.inboxPath} + OutboxPath = ${cfg.backend.files.outboxPath} + SentSMSPath = ${cfg.backend.files.sentSMSPath} + ErrorSMSPath = ${cfg.backend.files.errorSMSPath} + ''} + + ${optionalString (cfg.backend.service == "sql" && cfg.backend.sql.driver == "sqlite") '' + Driver = ${cfg.backend.sql.driver} + DBDir = ${cfg.backend.sql.database} + ''} + + ${optionalString (cfg.backend.service == "sql" && cfg.backend.sql.driver == "native_pgsql") ( + with cfg.backend; '' + Driver = ${sql.driver} + ${if (sql.database!= null) then "Database = ${sql.database}" else ""} + ${if (sql.host != null) then "Host = ${sql.host}" else ""} + ${if (sql.user != null) then "User = ${sql.user}" else ""} + ${if (sql.password != null) then "Password = ${sql.password}" else ""} + '')} + + ${cfg.extraConfig.smsd} + ''; + + initDBDir = "share/doc/gammu/examples/sql"; + + gammuPackage = with cfg.backend; (pkgs.gammu.override { + dbiSupport = (service == "sql" && sql.driver == "sqlite"); + postgresSupport = (service == "sql" && sql.driver == "native_pgsql"); + }); + +in { + options = { + services.gammu-smsd = { + + enable = mkEnableOption "gammu-smsd daemon"; + + user = mkOption { + type = types.str; + default = "smsd"; + description = "User that has access to the device"; + }; + + device = { + path = mkOption { + type = types.path; + description = "Device node or address of the phone"; + example = "/dev/ttyUSB2"; + }; + + group = mkOption { + type = types.str; + default = "root"; + description = "Owner group of the device"; + example = "dialout"; + }; + + connection = mkOption { + type = types.str; + default = "at"; + description = "Protocol which will be used to talk to the phone"; + }; + + synchronizeTime = mkOption { + type = types.bool; + default = true; + description = "Whether to set time from computer to the phone during starting connection"; + }; + + pin = mkOption { + type = types.nullOr types.str; + default = null; + description = "PIN code for the simcard"; + }; + }; + + + log = { + file = mkOption { + type = types.str; + default = "syslog"; + description = "Path to file where information about communication will be stored"; + }; + + format = mkOption { + type = types.enum [ "nothing" "text" "textall" "textalldate" "errors" "errorsdate" "binary" ]; + default = "errors"; + description = "Determines what will be logged to the LogFile"; + }; + }; + + + extraConfig = { + gammu = mkOption { + type = types.lines; + default = ""; + description = "Extra config lines to be added into [gammu] section"; + }; + + + smsd = mkOption { + type = types.lines; + default = ""; + description = "Extra config lines to be added into [smsd] section"; + }; + }; + + + backend = { + service = mkOption { + type = types.enum [ "null" "files" "sql" ]; + default = "null"; + description = "Service to use to store sms data."; + }; + + files = { + inboxPath = mkOption { + type = types.path; + default = "/var/spool/sms/inbox/"; + description = "Where the received SMSes are stored"; + }; + + outboxPath = mkOption { + type = types.path; + default = "/var/spool/sms/outbox/"; + description = "Where SMSes to be sent should be placed"; + }; + + sentSMSPath = mkOption { + type = types.path; + default = "/var/spool/sms/sent/"; + description = "Where the transmitted SMSes are placed"; + }; + + errorSMSPath = mkOption { + type = types.path; + default = "/var/spool/sms/error/"; + description = "Where SMSes with error in transmission is placed"; + }; + }; + + sql = { + driver = mkOption { + type = types.enum [ "native_mysql" "native_pgsql" "odbc" "dbi" ]; + description = "DB driver to use"; + }; + + sqlDialect = mkOption { + type = types.nullOr types.str; + default = null; + description = "SQL dialect to use (odbc driver only)"; + }; + + database = mkOption { + type = types.str; + default = null; + description = "Database name to store sms data"; + }; + + host = mkOption { + type = types.str; + default = "localhost"; + description = "Database server address"; + }; + + user = mkOption { + type = types.nullOr types.str; + default = null; + description = "User name used for connection to the database"; + }; + + password = mkOption { + type = types.nullOr types.str; + default = null; + description = "User password used for connetion to the database"; + }; + }; + }; + }; + }; + + config = mkIf cfg.enable { + users.extraUsers.${cfg.user} = { + description = "gammu-smsd user"; + uid = config.ids.uids.gammu-smsd; + extraGroups = [ "${cfg.device.group}" ]; + }; + + environment.systemPackages = with cfg.backend; [ gammuPackage ] + ++ optionals (service == "sql" && sql.driver == "sqlite") [ pkgs.sqlite ]; + + systemd.services.gammu-smsd = { + description = "gammu-smsd daemon"; + + wantedBy = [ "multi-user.target" ]; + + wants = with cfg.backend; [ ] + ++ optionals (service == "sql" && sql.driver == "native_pgsql") [ "postgresql.service" ]; + + preStart = with cfg.backend; + + optionalString (service == "files") (with files; '' + mkdir -m 755 -p ${inboxPath} ${outboxPath} ${sentSMSPath} ${errorSMSPath} + chown ${cfg.user} -R ${inboxPath} + chown ${cfg.user} -R ${outboxPath} + chown ${cfg.user} -R ${sentSMSPath} + chown ${cfg.user} -R ${errorSMSPath} + '') + + optionalString (service == "sql" && sql.driver == "sqlite") '' + cat "${gammuPackage}/${initDBDir}/sqlite.sql" \ + | ${pkgs.sqlite}/bin/sqlite3 ${sql.database} + '' + + (let execPsql = extraArgs: concatStringsSep " " [ + (optionalString (sql.password != null) "PGPASSWORD=${sql.password}") + "${config.services.postgresql.package}/bin/psql" + (optionalString (sql.host != null) "-h ${sql.host}") + (optionalString (sql.user != null) "-U ${sql.user}") + "$extraArgs" + "${sql.database}" + ]; in optionalString (service == "sql" && sql.driver == "native_pgsql") '' + echo '\i '"${gammuPackage}/${initDBDir}/pgsql.sql" | ${execPsql ""} + ''); + + serviceConfig = { + User = "${cfg.user}"; + Group = "${cfg.device.group}"; + PermissionsStartOnly = true; + ExecStart = "${gammuPackage}/bin/gammu-smsd -c ${configFile}"; + }; + + }; + }; +} diff --git a/nixos/modules/services/misc/gitlab.nix b/nixos/modules/services/misc/gitlab.nix index 949357ab20f..cc50bfbea53 100644 --- a/nixos/modules/services/misc/gitlab.nix +++ b/nixos/modules/services/misc/gitlab.nix @@ -7,10 +7,13 @@ with lib; let cfg = config.services.gitlab; - ruby = pkgs.gitlab.ruby; + ruby = cfg.packages.gitlab.ruby; bundler = pkgs.bundler; - gemHome = "${pkgs.gitlab.env}/${ruby.gemPath}"; + gemHome = "${cfg.packages.gitlab.env}/${ruby.gemPath}"; + + gitlabSocket = "${cfg.statePath}/tmp/sockets/gitlab.socket"; + pathUrlQuote = url: replaceStrings ["/"] ["%2F"] url; databaseYml = '' production: @@ -21,14 +24,15 @@ let username: ${cfg.databaseUsername} encoding: utf8 ''; + gitlabShellYml = '' - user: gitlab - gitlab_url: "http://${cfg.host}:${toString cfg.port}/" + user: ${cfg.user} + gitlab_url: "http+unix://${pathUrlQuote gitlabSocket}" http_settings: self_signed_cert: false - repos_path: "${cfg.stateDir}/repositories" - secret_file: "${cfg.stateDir}/config/gitlab_shell_secret" - log_file: "${cfg.stateDir}/log/gitlab-shell.log" + repos_path: "${cfg.statePath}/repositories" + secret_file: "${cfg.statePath}/config/gitlab_shell_secret" + log_file: "${cfg.statePath}/log/gitlab-shell.log" redis: bin: ${pkgs.redis}/bin/redis-cli host: 127.0.0.1 @@ -37,33 +41,102 @@ let namespace: resque:gitlab ''; + gitlabConfig = { + # These are the default settings from config/gitlab.example.yml + production = flip recursiveUpdate cfg.extraConfig { + gitlab = { + host = cfg.host; + port = cfg.port; + https = cfg.https; + user = cfg.user; + email_enabled = true; + email_display_name = "GitLab"; + email_reply_to = "noreply@localhost"; + default_theme = 2; + default_projects_features = { + issues = true; + merge_requests = true; + wiki = true; + snippets = false; + builds = true; + }; + }; + artifacts = { + enabled = true; + }; + lfs = { + enabled = true; + }; + gravatar = { + enabled = true; + }; + cron_jobs = { + stuck_ci_builds_worker = { + cron = "0 0 * * *"; + }; + }; + gitlab_ci = { + builds_path = "${cfg.statePath}/builds"; + }; + ldap = { + enabled = false; + }; + omniauth = { + enabled = false; + }; + shared = { + path = "${cfg.statePath}/shared"; + }; + backup = { + path = "${cfg.backupPath}"; + }; + gitlab_shell = { + path = "${cfg.packages.gitlab-shell}"; + repos_path = "${cfg.statePath}/repositories"; + hooks_path = "${cfg.statePath}/shell/hooks"; + secret_file = "${cfg.statePath}/config/gitlab_shell_secret"; + upload_pack = true; + receive_pack = true; + }; + git = { + bin_path = "git"; + max_size = 20971520; # 20MB + timeout = 10; + }; + extra = {}; + }; + }; + + gitlabEnv = { + HOME = "${cfg.statePath}/home"; + GEM_HOME = gemHome; + BUNDLE_GEMFILE = "${cfg.packages.gitlab}/share/gitlab/Gemfile"; + UNICORN_PATH = "${cfg.statePath}/"; + GITLAB_PATH = "${cfg.packages.gitlab}/share/gitlab/"; + GITLAB_STATE_PATH = "${cfg.statePath}"; + GITLAB_UPLOADS_PATH = "${cfg.statePath}/uploads"; + GITLAB_LOG_PATH = "${cfg.statePath}/log"; + GITLAB_SHELL_PATH = "${cfg.packages.gitlab-shell}"; + 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"; + RAILS_ENV = "production"; + }; + unicornConfig = builtins.readFile ./defaultUnicornConfig.rb; gitlab-runner = pkgs.stdenv.mkDerivation rec { name = "gitlab-runner"; - buildInputs = [ pkgs.gitlab pkgs.bundler pkgs.makeWrapper ]; + buildInputs = [ cfg.packages.gitlab bundler pkgs.makeWrapper ]; phases = "installPhase fixupPhase"; buildPhase = ""; installPhase = '' mkdir -p $out/bin - makeWrapper ${bundler}/bin/bundle $out/bin/gitlab-runner\ - --set RAKEOPT '"-f ${pkgs.gitlab}/share/gitlab/Rakefile"'\ - --set GEM_HOME '${gemHome}'\ - --set UNICORN_PATH "${cfg.stateDir}/"\ - --set GITLAB_PATH "${pkgs.gitlab}/share/gitlab/"\ - --set GITLAB_APPLICATION_LOG_PATH "${cfg.stateDir}/log/application.log"\ - --set GITLAB_SATELLITES_PATH "${cfg.stateDir}/satellites"\ - --set GITLAB_SHELL_PATH "${pkgs.gitlab-shell}"\ - --set GITLAB_REPOSITORIES_PATH "${cfg.stateDir}/repositories"\ - --set GITLAB_SHELL_HOOKS_PATH "${cfg.stateDir}/shell/hooks"\ - --set BUNDLE_GEMFILE "${pkgs.gitlab}/share/gitlab/Gemfile"\ - --set GITLAB_EMAIL_FROM "${cfg.emailFrom}"\ - --set GITLAB_SHELL_CONFIG_PATH "${cfg.stateDir}/shell/config.yml"\ - --set GITLAB_SHELL_SECRET_PATH "${cfg.stateDir}/config/gitlab_shell_secret"\ - --set GITLAB_HOST "${cfg.host}"\ - --set GITLAB_PORT "${toString cfg.port}"\ - --set GITLAB_BACKUP_PATH "${cfg.backupPath}"\ - --set RAILS_ENV "production" + makeWrapper ${bundler}/bin/bundle $out/bin/gitlab-runner \ + ${concatStrings (mapAttrsToList (name: value: "--set ${name} '\"${value}\"' ") gitlabEnv)} \ + --set GITLAB_CONFIG_PATH '"${cfg.statePath}/config"' \ + --set PATH '"${pkgs.nodejs}/bin:${pkgs.gzip}/bin:${config.services.postgresql.package}/bin:$PATH"' \ + --set RAKEOPT '"-f ${cfg.packages.gitlab}/share/gitlab/Rakefile"' ''; }; @@ -79,13 +152,25 @@ in { ''; }; - satelliteDir = mkOption { - type = types.str; - default = "/var/gitlab/git-satellites"; - description = "Gitlab directory to store checked out git trees requires for operation."; + packages.gitlab = mkOption { + type = types.package; + default = pkgs.gitlab; + description = "Reference to the gitlab package"; + }; + + packages.gitlab-shell = mkOption { + type = types.package; + default = pkgs.gitlab-shell; + description = "Reference to the gitlab-shell package"; + }; + + packages.gitlab-workhorse = mkOption { + type = types.package; + default = pkgs.gitlab-workhorse; + description = "Reference to the gitlab-workhorse package"; }; - stateDir = mkOption { + statePath = mkOption { type = types.str; default = "/var/gitlab/state"; description = "Gitlab state directory, logs are stored here."; @@ -93,7 +178,7 @@ in { backupPath = mkOption { type = types.str; - default = cfg.stateDir + "/backup"; + default = cfg.statePath + "/backup"; description = "Gitlab path for backups."; }; @@ -136,14 +221,67 @@ in { port = mkOption { type = types.int; default = 8080; - description = "Gitlab server listening port."; + description = '' + Gitlab server port for copy-paste URLs, e.g. 80 or 443 if you're + service over https. + ''; + }; + + https = mkOption { + type = types.bool; + default = false; + description = "Whether gitlab prints URLs with https as scheme."; + }; + + user = mkOption { + type = types.str; + default = "gitlab"; + description = "User to run gitlab and all related services."; + }; + + group = mkOption { + type = types.str; + default = "gitlab"; + description = "Group to run gitlab and all related services."; + }; + + initialRootEmail = mkOption { + type = types.str; + default = "admin@local.host"; + description = '' + Initial email address of the root account if this is a new install. + ''; + }; + + initialRootPassword = mkOption { + type = types.str; + default = "UseNixOS!"; + description = '' + Initial password of the root account if this is a new install. + ''; + }; + + extraConfig = mkOption { + type = types.attrs; + default = {}; + example = { + gitlab = { + default_projects_features = { + builds = false; + }; + }; + }; + description = '' + Extra options to be merged into config/gitlab.yml as nix + attribute set. + ''; }; }; }; config = mkIf cfg.enable { - environment.systemPackages = [ pkgs.git gitlab-runner pkgs.gitlab-shell ]; + environment.systemPackages = [ pkgs.git gitlab-runner cfg.packages.gitlab-shell ]; assertions = [ { assertion = cfg.databasePassword != ""; @@ -159,39 +297,24 @@ in { services.postfix.enable = mkDefault true; users.extraUsers = [ - { name = "gitlab"; - group = "gitlab"; - home = "${cfg.stateDir}/home"; + { name = cfg.user; + group = cfg.group; + home = "${cfg.statePath}/home"; shell = "${pkgs.bash}/bin/bash"; uid = config.ids.uids.gitlab; - } ]; + } + ]; users.extraGroups = [ - { name = "gitlab"; + { name = cfg.group; gid = config.ids.gids.gitlab; - } ]; + } + ]; systemd.services.gitlab-sidekiq = { after = [ "network.target" "redis.service" ]; wantedBy = [ "multi-user.target" ]; - environment.HOME = "${cfg.stateDir}/home"; - environment.GEM_HOME = gemHome; - environment.UNICORN_PATH = "${cfg.stateDir}/"; - environment.GITLAB_PATH = "${pkgs.gitlab}/share/gitlab/"; - environment.GITLAB_APPLICATION_LOG_PATH = "${cfg.stateDir}/log/application.log"; - environment.GITLAB_SATELLITES_PATH = "${cfg.stateDir}/satellites"; - environment.GITLAB_SHELL_PATH = "${pkgs.gitlab-shell}"; - environment.GITLAB_REPOSITORIES_PATH = "${cfg.stateDir}/repositories"; - environment.GITLAB_SHELL_HOOKS_PATH = "${cfg.stateDir}/shell/hooks"; - environment.BUNDLE_GEMFILE = "${pkgs.gitlab}/share/gitlab/Gemfile"; - environment.GITLAB_EMAIL_FROM = "${cfg.emailFrom}"; - environment.GITLAB_SHELL_CONFIG_PATH = "${cfg.stateDir}/shell/config.yml"; - environment.GITLAB_SHELL_SECRET_PATH = "${cfg.stateDir}/config/gitlab_shell_secret"; - environment.GITLAB_HOST = "${cfg.host}"; - environment.GITLAB_PORT = "${toString cfg.port}"; - environment.GITLAB_DATABASE_HOST = "${cfg.databaseHost}"; - environment.GITLAB_DATABASE_PASSWORD = "${cfg.databasePassword}"; - environment.RAILS_ENV = "production"; + environment = gitlabEnv; path = with pkgs; [ config.services.postgresql.package gitAndTools.git @@ -201,116 +324,131 @@ in { ]; serviceConfig = { Type = "simple"; - User = "gitlab"; - Group = "gitlab"; + User = cfg.user; + Group = cfg.group; TimeoutSec = "300"; - WorkingDirectory = "${pkgs.gitlab}/share/gitlab"; - 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\""; + WorkingDirectory = "${cfg.packages.gitlab}/share/gitlab"; + 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.statePath}/tmp/sidekiq.pid\""; }; }; - systemd.services.gitlab-git-http-server = { + systemd.services.gitlab-workhorse = { after = [ "network.target" "gitlab.service" ]; wantedBy = [ "multi-user.target" ]; - environment.HOME = "${cfg.stateDir}/home"; + environment.HOME = gitlabEnv.HOME; + environment.GITLAB_SHELL_CONFIG_PATH = gitlabEnv.GITLAB_SHELL_CONFIG_PATH; path = with pkgs; [ gitAndTools.git openssh ]; + preStart = '' + mkdir -p /run/gitlab + chown ${cfg.user}:${cfg.group} /run/gitlab + ''; serviceConfig = { + PermissionsStartOnly = true; # preStart must be run as root Type = "simple"; - User = "gitlab"; - Group = "gitlab"; + User = cfg.user; + Group = cfg.group; TimeoutSec = "300"; - ExecStart = "${pkgs.gitlab-git-http-server}/bin/gitlab-git-http-server -listenUmask 0 -listenNetwork unix -listenAddr ${cfg.stateDir}/tmp/sockets/gitlab-git-http-server.socket -authBackend http://localhost:8080 ${cfg.stateDir}/repositories"; + ExecStart = + "${cfg.packages.gitlab-workhorse}/bin/gitlab-workhorse " + + "-listenUmask 0 " + + "-listenNetwork unix " + + "-listenAddr /run/gitlab/gitlab-workhorse.socket " + + "-authSocket ${gitlabSocket} " + + "-documentRoot ${cfg.packages.gitlab}/share/gitlab/public"; }; }; systemd.services.gitlab = { after = [ "network.target" "postgresql.service" "redis.service" ]; wantedBy = [ "multi-user.target" ]; - environment.HOME = "${cfg.stateDir}/home"; - environment.GEM_HOME = gemHome; - environment.UNICORN_PATH = "${cfg.stateDir}/"; - environment.GITLAB_PATH = "${pkgs.gitlab}/share/gitlab/"; - environment.GITLAB_APPLICATION_LOG_PATH = "${cfg.stateDir}/log/application.log"; - environment.GITLAB_SATELLITES_PATH = "${cfg.stateDir}/satellites"; - environment.GITLAB_SHELL_PATH = "${pkgs.gitlab-shell}"; - environment.GITLAB_SHELL_CONFIG_PATH = "${cfg.stateDir}/shell/config.yml"; - environment.GITLAB_SHELL_SECRET_PATH = "${cfg.stateDir}/config/gitlab_shell_secret"; - environment.GITLAB_REPOSITORIES_PATH = "${cfg.stateDir}/repositories"; - environment.GITLAB_SHELL_HOOKS_PATH = "${cfg.stateDir}/shell/hooks"; - environment.BUNDLE_GEMFILE = "${pkgs.gitlab}/share/gitlab/Gemfile"; - environment.GITLAB_EMAIL_FROM = "${cfg.emailFrom}"; - environment.GITLAB_HOST = "${cfg.host}"; - environment.GITLAB_PORT = "${toString cfg.port}"; - environment.GITLAB_DATABASE_HOST = "${cfg.databaseHost}"; - environment.GITLAB_DATABASE_PASSWORD = "${cfg.databasePassword}"; - environment.RAILS_ENV = "production"; + environment = gitlabEnv; path = with pkgs; [ config.services.postgresql.package gitAndTools.git - ruby openssh nodejs ]; preStart = '' - # TODO: use env vars - mkdir -p ${cfg.stateDir} - mkdir -p ${cfg.stateDir}/log - mkdir -p ${cfg.stateDir}/satellites - mkdir -p ${cfg.stateDir}/repositories - mkdir -p ${cfg.stateDir}/shell/hooks - mkdir -p ${cfg.stateDir}/tmp/pids - mkdir -p ${cfg.stateDir}/tmp/sockets - rm -rf ${cfg.stateDir}/config - mkdir -p ${cfg.stateDir}/config - # TODO: What exactly is gitlab-shell doing with the secret? - tr -dc _A-Z-a-z-0-9 < /dev/urandom | head -c 20 > ${cfg.stateDir}/config/gitlab_shell_secret - mkdir -p ${cfg.stateDir}/home/.ssh - touch ${cfg.stateDir}/home/.ssh/authorized_keys - - cp -rf ${pkgs.gitlab}/share/gitlab/config ${cfg.stateDir}/ - cp ${pkgs.gitlab}/share/gitlab/VERSION ${cfg.stateDir}/VERSION + 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 ${cfg.statePath}/log + mkdir -p ${cfg.statePath}/shell + mkdir -p ${cfg.statePath}/tmp/pids + mkdir -p ${cfg.statePath}/tmp/sockets + + rm -rf ${cfg.statePath}/config ${cfg.statePath}/shell/hooks + mkdir -p ${cfg.statePath}/config ${cfg.statePath}/shell - ln -fs ${pkgs.writeText "database.yml" databaseYml} ${cfg.stateDir}/config/database.yml - ln -fs ${pkgs.writeText "unicorn.rb" unicornConfig} ${cfg.stateDir}/config/unicorn.rb - - chown -R gitlab:gitlab ${cfg.stateDir}/ - chmod -R 755 ${cfg.stateDir}/ + # TODO: What exactly is gitlab-shell doing with the secret? + tr -dc _A-Z-a-z-0-9 < /dev/urandom | head -c 20 > ${cfg.statePath}/config/gitlab_shell_secret + + # The uploads directory is hardcoded somewhere deep in rails. It is + # symlinked in the gitlab package to /run/gitlab/uploads to make it + # configurable + mkdir -p /run/gitlab + mkdir -p ${cfg.statePath}/uploads + ln -sf ${cfg.statePath}/uploads /run/gitlab/uploads + 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}/ + chmod -R u+rwX,go-rwx+X ${gitlabEnv.HOME}/ + + cp -rf ${cfg.packages.gitlab}/share/gitlab/config.dist/* ${cfg.statePath}/config + ln -sf ${cfg.statePath}/config /run/gitlab/config + 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 "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}/ + + # 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" + ${cfg.packages.gitlab-shell}/bin/install if [ "${cfg.databaseHost}" = "127.0.0.1" ]; then - if ! test -e "${cfg.stateDir}/db-created"; then + if ! test -e "${cfg.statePath}/db-created"; then psql postgres -c "CREATE ROLE gitlab WITH LOGIN NOCREATEDB NOCREATEROLE NOCREATEUSER ENCRYPTED PASSWORD '${cfg.databasePassword}'" ${config.services.postgresql.package}/bin/createdb --owner gitlab gitlab || true - touch "${cfg.stateDir}/db-created" + touch "${cfg.statePath}/db-created" - # force=yes disables the manual-interaction yes/no prompt - # which breaks without an stdin. - force=yes ${bundler}/bin/bundle exec rake -f ${pkgs.gitlab}/share/gitlab/Rakefile gitlab:setup RAILS_ENV=production + # The gitlab:setup task is horribly broken somehow, these two tasks will do the same for setting up the initial database + ${gitlab-runner}/bin/gitlab-runner exec rake db:migrate RAILS_ENV=production + ${gitlab-runner}/bin/gitlab-runner exec rake db:seed_fu RAILS_ENV=production \ + GITLAB_ROOT_PASSWORD="${cfg.initialRootPassword}" GITLAB_ROOT_EMAIL="${cfg.initialRootEmail}"; fi fi - ${bundler}/bin/bundle exec rake -f ${pkgs.gitlab}/share/gitlab/Rakefile db:migrate RAILS_ENV=production - # Install the shell required to push repositories - ln -fs ${pkgs.writeText "config.yml" gitlabShellYml} ${cfg.stateDir}/shell/config.yml - export GITLAB_SHELL_CONFIG_PATH=""${cfg.stateDir}/shell/config.yml - ${pkgs.gitlab-shell}/bin/install + # Always do the db migrations just to be sure the database is up-to-date + ${gitlab-runner}/bin/gitlab-runner exec rake db:migrate RAILS_ENV=production - # Change permissions in the last step because some of the - # intermediary scripts like to create directories as root. - chown -R gitlab:gitlab ${cfg.stateDir}/ - chmod -R 755 ${cfg.stateDir}/ + # 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 u+rwX,go-rwx+X ${cfg.statePath} ''; serviceConfig = { PermissionsStartOnly = true; # preStart must be run as root Type = "simple"; - User = "gitlab"; - Group = "gitlab"; + User = cfg.user; + Group = cfg.group; TimeoutSec = "300"; - WorkingDirectory = "${pkgs.gitlab}/share/gitlab"; - ExecStart="${bundler}/bin/bundle exec \"unicorn -c ${cfg.stateDir}/config/unicorn.rb -E production\""; + WorkingDirectory = "${cfg.packages.gitlab}/share/gitlab"; + ExecStart="${bundler}/bin/bundle exec \"unicorn -c ${cfg.statePath}/config/unicorn.rb -E production\""; }; }; diff --git a/nixos/modules/services/misc/gitlab.xml b/nixos/modules/services/misc/gitlab.xml new file mode 100644 index 00000000000..b630fe42113 --- /dev/null +++ b/nixos/modules/services/misc/gitlab.xml @@ -0,0 +1,103 @@ +<chapter xmlns="http://docbook.org/ns/docbook" + xmlns:xlink="http://www.w3.org/1999/xlink" + xmlns:xi="http://www.w3.org/2001/XInclude" + version="5.0" + xml:id="module-services-gitlab"> + +<title>Gitlab</title> + +<para>Gitlab is a feature-rich git hosting service.</para> + +<section><title>Prerequisites</title> + +<para>The gitlab service exposes only an Unix socket at +<literal>/run/gitlab/gitlab-workhorse.socket</literal>. You need to configure a +webserver to proxy HTTP requests to the socket.</para> + +<para>For instance, this could be used for Nginx: + +<programlisting> +services.nginx.httpConfig = '' + server { + server_name git.example.com; + listen 443 ssl spdy; + listen [::]:443 ssl spdy; + + ssl_certificate /var/lib/acme/git.example.com/fullchain.pem; + ssl_certificate_key /var/lib/acme/git.example.com/key.pem; + + location / { + proxy_http_version 1.1; + proxy_set_header Host $http_host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-Ssl on; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto $scheme; + + proxy_pass http://unix:/run/gitlab/gitlab-workhorse.socket; + } + } +''; +</programlisting> +</para> + +</section> + +<section><title>Configuring</title> + +<para>Gitlab depends on both PostgreSQL and Redis and will automatically enable +both services. In the case of PostgreSQL, a database and a role will be created. +</para> + +<para>The default state dir is /var/gitlab/state. This is where all data like +the repositories and uploads will be stored.</para> + +<para>A basic configuration could look like this: + +<programlisting> +services.gitlab = { + enable = true; + databasePassword = "eXaMpl3"; + initialRootPassword = "UseNixOS!"; + https = true; + host = "git.example.com"; + port = 443; + user = "git"; + group = "git"; + extraConfig = { + gitlab = { + default_projects_features = { builds = false; }; + }; + }; +}; +</programlisting> +</para> + +<para>Refer to <xref linkend="ch-options" /> for all available configuration +options for the <literal>services.gitlab</literal> module.</para> + +</section> + +<section><title>Maintenance</title> + +<para>You can run all Gitlab related commands like rake tasks with +<literal>gitlab-runner</literal> which will be available on the system +when gitlab is enabled. You will have to run the commands as the user that +you configured to run gitlab.</para> + +<para>For instance, to backup a Gitlab instance: + +<programlisting> +$ sudo -u git -H gitlab-runner exec rake gitlab:backup:create +</programlisting> + +A list of all availabe rake tasks can be obtained by running: + +<programlisting> +$ sudo -u git -H gitlab-runner exec rake -T +</programlisting> +</para> + +</section> + +</chapter> diff --git a/nixos/modules/services/misc/matrix-synapse.nix b/nixos/modules/services/misc/matrix-synapse.nix index 27c5a38e6b8..0ae0516769c 100644 --- a/nixos/modules/services/misc/matrix-synapse.nix +++ b/nixos/modules/services/misc/matrix-synapse.nix @@ -61,6 +61,7 @@ in { package = mkOption { type = types.package; default = pkgs.matrix-synapse; + defaultText = "pkgs.matrix-synapse"; description = '' Overridable attribute of the matrix synapse server package to use. ''; diff --git a/nixos/modules/services/misc/nix-daemon.nix b/nixos/modules/services/misc/nix-daemon.nix index 24ae515a6b8..b0e4bf106d3 100644 --- a/nixos/modules/services/misc/nix-daemon.nix +++ b/nixos/modules/services/misc/nix-daemon.nix @@ -367,6 +367,8 @@ in // { CURL_CA_BUNDLE = "/etc/ssl/certs/ca-certificates.crt"; } // config.networking.proxy.envVars; + unitConfig.RequiresMountsFor = "/nix/store"; + serviceConfig = { Nice = cfg.daemonNiceLevel; IOSchedulingPriority = cfg.daemonIONiceLevel; diff --git a/nixos/modules/services/misc/nixos-manual.nix b/nixos/modules/services/misc/nixos-manual.nix index 3e1f53e79f3..37ea339300d 100644 --- a/nixos/modules/services/misc/nixos-manual.nix +++ b/nixos/modules/services/misc/nixos-manual.nix @@ -17,16 +17,32 @@ let nixpkgs.system = config.nixpkgs.system; }; - eval = evalModules { - modules = [ versionModule ] ++ baseModules; - args = (config._module.args) // { modules = [ ]; }; - }; - + /* For the purpose of generating docs, evaluate options with each derivation + in `pkgs` (recursively) replaced by a fake with path "\${pkgs.attribute.path}". + It isn't perfect, but it seems to cover a vast majority of use cases. + Caveat: even if the package is reached by a different means, + the path above will be shown and not e.g. `${config.services.foo.package}`. */ manual = import ../../../doc/manual { inherit pkgs; version = config.system.nixosVersion; revision = config.system.nixosRevision; - options = eval.options; + options = + let + scrubbedEval = evalModules { + modules = [ versionModule ] ++ baseModules; + args = (config._module.args) // { modules = [ ]; }; + specialArgs = { pkgs = scrubDerivations "pkgs" pkgs; }; + }; + scrubDerivations = namePrefix: pkgSet: mapAttrs + (name: value: + let wholeName = "${namePrefix}.${name}"; in + if isAttrs value then + scrubDerivations wholeName value + // (optionalAttrs (isDerivation value) { outPath = "\${${wholeName}}"; }) + else value + ) + pkgSet; + in scrubbedEval.options; }; entry = "${manual.manual}/share/doc/nixos/index.html"; @@ -72,7 +88,8 @@ in }; services.nixosManual.ttyNumber = mkOption { - default = "8"; + type = types.int; + default = 8; description = '' Virtual console on which to show the manual. ''; @@ -80,6 +97,7 @@ in services.nixosManual.browser = mkOption { type = types.path; + default = "${pkgs.w3m-nox}/bin/w3m"; description = '' Browser used to show the manual. ''; @@ -96,7 +114,7 @@ in [ manual.manual help ] ++ optional config.programs.man.enable manual.manpages; - boot.extraTTYs = mkIf cfg.showManual ["tty${cfg.ttyNumber}"]; + boot.extraTTYs = mkIf cfg.showManual ["tty${toString cfg.ttyNumber}"]; systemd.services = optionalAttrs cfg.showManual { "nixos-manual" = @@ -106,7 +124,7 @@ in { ExecStart = "${cfg.browser} ${entry}"; StandardInput = "tty"; StandardOutput = "tty"; - TTYPath = "/dev/tty${cfg.ttyNumber}"; + TTYPath = "/dev/tty${toString cfg.ttyNumber}"; TTYReset = true; TTYVTDisallocate = true; Restart = "always"; @@ -117,8 +135,6 @@ in services.mingetty.helpLine = mkIf cfg.showManual "\nPress <Alt-F${toString cfg.ttyNumber}> for the NixOS manual."; - services.nixosManual.browser = mkDefault "${pkgs.w3m-nox}/bin/w3m"; - }; } diff --git a/nixos/modules/services/misc/octoprint.nix b/nixos/modules/services/misc/octoprint.nix new file mode 100644 index 00000000000..9cf46345c22 --- /dev/null +++ b/nixos/modules/services/misc/octoprint.nix @@ -0,0 +1,120 @@ +{ config, lib, pkgs, ... }: + +with lib; + +let + + cfg = config.services.octoprint; + + cfgUpdate = pkgs.writeText "octoprint-config.yaml" (builtins.toJSON { + plugins.cura.cura_engine = "${pkgs.curaengine}/bin/CuraEngine"; + server.host = cfg.host; + server.port = cfg.port; + webcam.ffmpeg = "${pkgs.ffmpeg}/bin/ffmpeg"; + }); + + pluginsEnv = pkgs.python.buildEnv.override { + extraLibs = cfg.plugins pkgs.octoprint-plugins; + }; + +in +{ + ##### interface + + options = { + + services.octoprint = { + + enable = mkEnableOption "OctoPrint, web interface for 3D printers"; + + host = mkOption { + type = types.str; + default = "0.0.0.0"; + description = '' + Host to bind OctoPrint to. + ''; + }; + + port = mkOption { + type = types.int; + default = 5000; + description = '' + Port to bind OctoPrint to. + ''; + }; + + user = mkOption { + type = types.str; + default = "octoprint"; + description = "User for the daemon."; + }; + + group = mkOption { + type = types.str; + default = "octoprint"; + description = "Group for the daemon."; + }; + + stateDir = mkOption { + type = types.path; + default = "/var/lib/octoprint"; + description = "State directory of the daemon."; + }; + + plugins = mkOption { + #type = types.functionTo (types.listOf types.package); + default = plugins: []; + defaultText = "plugins: []"; + example = literalExample "plugins: [ m3d-fio ]"; + description = "Additional plugins."; + }; + + }; + + }; + + ##### implementation + + config = mkIf cfg.enable { + + users.extraUsers = optionalAttrs (cfg.user == "octoprint") (singleton + { name = "octoprint"; + group = cfg.group; + uid = config.ids.uids.octoprint; + }); + + users.extraGroups = optionalAttrs (cfg.group == "octoprint") (singleton + { name = "octoprint"; + gid = config.ids.gids.octoprint; + }); + + systemd.services.octoprint = { + description = "OctoPrint, web interface for 3D printers"; + wantedBy = [ "multi-user.target" ]; + after = [ "network.target" ]; + path = [ pluginsEnv ]; + environment.PYTHONPATH = makeSearchPath pkgs.python.sitePackages [ pluginsEnv ]; + + preStart = '' + mkdir -p "${cfg.stateDir}" + if [ -e "${cfg.stateDir}/config.yaml" ]; then + ${pkgs.yaml-merge}/bin/yaml-merge "${cfg.stateDir}/config.yaml" "${cfgUpdate}" > "${cfg.stateDir}/config.yaml.tmp" + mv "${cfg.stateDir}/config.yaml.tmp" "${cfg.stateDir}/config.yaml" + else + cp "${cfgUpdate}" "${cfg.stateDir}/config.yaml" + chmod 600 "${cfg.stateDir}/config.yaml" + fi + chown -R ${cfg.user}:${cfg.group} "${cfg.stateDir}" + ''; + + serviceConfig = { + ExecStart = "${pkgs.octoprint}/bin/octoprint -b ${cfg.stateDir}"; + User = cfg.user; + Group = cfg.group; + PermissionsStartOnly = true; + }; + }; + + }; + +} diff --git a/nixos/modules/services/misc/plex.nix b/nixos/modules/services/misc/plex.nix index fb62351365e..875771dfa37 100644 --- a/nixos/modules/services/misc/plex.nix +++ b/nixos/modules/services/misc/plex.nix @@ -58,6 +58,7 @@ in package = mkOption { type = types.package; default = pkgs.plex; + defaultText = "pkgs.plex"; description = '' The Plex package to use. Plex subscribers may wish to use their own package here, pointing to subscriber-only server versions. diff --git a/nixos/modules/services/misc/spice-vdagentd.nix b/nixos/modules/services/misc/spice-vdagentd.nix new file mode 100644 index 00000000000..f8133394ffd --- /dev/null +++ b/nixos/modules/services/misc/spice-vdagentd.nix @@ -0,0 +1,30 @@ +{ config, pkgs, lib, ... }: + +with lib; +let + cfg = config.services.spice-vdagentd; +in +{ + options = { + services.spice-vdagentd = { + enable = mkEnableOption "Spice guest vdagent daemon"; + }; + }; + + config = mkIf cfg.enable { + + environment.systemPackages = [ pkgs.spice-vdagent ]; + + systemd.services.spice-vdagentd = { + description = "spice-vdagent daemon"; + wantedBy = [ "graphical.target" ]; + preStart = '' + mkdir -p "/var/run/spice-vdagentd/" + ''; + serviceConfig = { + Type = "forking"; + ExecStart = "/bin/sh -c '${pkgs.spice-vdagent}/bin/spice-vdagentd'"; + }; + }; + }; +} diff --git a/nixos/modules/services/misc/subsonic.nix b/nixos/modules/services/misc/subsonic.nix index 5a33aa33b26..c1ebe418f72 100644 --- a/nixos/modules/services/misc/subsonic.nix +++ b/nixos/modules/services/misc/subsonic.nix @@ -97,6 +97,7 @@ in transcoders = mkOption { type = types.listOf types.path; + default = [ "${pkgs.ffmpeg.bin}/bin/ffmpeg" ]; description = '' List of paths to transcoder executables that should be accessible from Subsonic. Symlinks will be created to each executable inside @@ -152,8 +153,5 @@ in }; users.extraGroups.subsonic.gid = config.ids.gids.subsonic; - - services.subsonic.transcoders = mkDefault [ "${pkgs.ffmpeg.bin}/bin/ffmpeg" ]; - }; } |