diff options
Diffstat (limited to 'nixos/modules/services')
-rw-r--r-- | nixos/modules/services/games/terraria.nix | 16 | ||||
-rw-r--r-- | nixos/modules/services/hardware/undervolt.nix | 134 | ||||
-rw-r--r-- | nixos/modules/services/misc/redmine.nix | 294 | ||||
-rw-r--r-- | nixos/modules/services/networking/dhcpcd.nix | 3 | ||||
-rw-r--r-- | nixos/modules/services/security/cfssl.nix | 4 |
5 files changed, 303 insertions, 148 deletions
diff --git a/nixos/modules/services/games/terraria.nix b/nixos/modules/services/games/terraria.nix index ddf17599296a..31f8edca20ce 100644 --- a/nixos/modules/services/games/terraria.nix +++ b/nixos/modules/services/games/terraria.nix @@ -18,6 +18,16 @@ let (boolFlag "secure" cfg.secure) (boolFlag "noupnp" cfg.noUPnP) ]; + stopScript = pkgs.writeScript "terraria-stop" '' + #!${pkgs.runtimeShell} + + if ! [ -d "/proc/$1" ]; then + exit 0 + fi + + ${getBin pkgs.tmux}/bin/tmux -S /var/lib/terraria/terraria.sock send-keys Enter exit Enter + ${getBin pkgs.coreutils}/bin/tail --pid="$1" -f /dev/null + ''; in { options = { @@ -124,10 +134,10 @@ in serviceConfig = { User = "terraria"; - Type = "oneshot"; - RemainAfterExit = true; + Type = "forking"; + GuessMainPID = true; ExecStart = "${getBin pkgs.tmux}/bin/tmux -S /var/lib/terraria/terraria.sock new -d ${pkgs.terraria-server}/bin/TerrariaServer ${concatStringsSep " " flags}"; - ExecStop = "${getBin pkgs.tmux}/bin/tmux -S /var/lib/terraria/terraria.sock send-keys Enter \"exit\" Enter"; + ExecStop = "${stopScript} $MAINPID"; }; postStart = '' diff --git a/nixos/modules/services/hardware/undervolt.nix b/nixos/modules/services/hardware/undervolt.nix new file mode 100644 index 000000000000..e5ef0601de3c --- /dev/null +++ b/nixos/modules/services/hardware/undervolt.nix @@ -0,0 +1,134 @@ +{ config, pkgs, lib, ... }: + +with lib; + +let + cfg = config.services.undervolt; +in { + options.services.undervolt = { + enable = mkOption { + type = types.bool; + default = false; + description = '' + Whether to undervolt intel cpus. + ''; + }; + + verbose = mkOption { + type = types.bool; + default = false; + description = '' + Whether to enable verbose logging. + ''; + }; + + package = mkOption { + type = types.package; + default = pkgs.undervolt; + defaultText = "pkgs.undervolt"; + description = '' + undervolt derivation to use. + ''; + }; + + coreOffset = mkOption { + type = types.nullOr types.str; + default = null; + description = '' + The amount of voltage to offset the CPU cores by. Accepts a floating point number. + ''; + }; + + gpuOffset = mkOption { + type = types.nullOr types.str; + default = null; + description = '' + The amount of voltage to offset the GPU by. Accepts a floating point number. + ''; + }; + + uncoreOffset = mkOption { + type = types.nullOr types.str; + default = null; + description = '' + The amount of voltage to offset uncore by. Accepts a floating point number. + ''; + }; + + analogioOffset = mkOption { + type = types.nullOr types.str; + default = null; + description = '' + The amount of voltage to offset analogio by. Accepts a floating point number. + ''; + }; + + temp = mkOption { + type = types.nullOr types.str; + default = null; + description = '' + The temperature target. Accepts a floating point number. + ''; + }; + + tempAc = mkOption { + type = types.nullOr types.str; + default = null; + description = '' + The temperature target on AC power. Accepts a floating point number. + ''; + }; + + tempBat = mkOption { + type = types.nullOr types.str; + default = null; + description = '' + The temperature target on battery power. Accepts a floating point number. + ''; + }; + }; + + config = mkIf cfg.enable { + boot.kernelModules = [ "msr" ]; + + environment.systemPackages = [ cfg.package ]; + + systemd.services.undervolt = { + path = [ pkgs.undervolt ]; + + description = "Intel Undervolting Service"; + serviceConfig = { + Type = "oneshot"; + Restart = "no"; + + # `core` and `cache` are both intentionally set to `cfg.coreOffset` as according to the undervolt docs: + # + # Core or Cache offsets have no effect. It is not possible to set different offsets for + # CPU Core and Cache. The CPU will take the smaller of the two offsets, and apply that to + # both CPU and Cache. A warning message will be displayed if you attempt to set different offsets. + ExecStart = '' + ${pkgs.undervolt}/bin/undervolt \ + ${optionalString cfg.verbose "--verbose"} \ + ${optionalString (cfg.coreOffset != null) "--core ${cfg.coreOffset}"} \ + ${optionalString (cfg.coreOffset != null) "--cache ${cfg.coreOffset}"} \ + ${optionalString (cfg.gpuOffset != null) "--gpu ${cfg.gpuOffset}"} \ + ${optionalString (cfg.uncoreOffset != null) "--uncore ${cfg.uncoreOffset}"} \ + ${optionalString (cfg.analogioOffset != null) "--analogio ${cfg.analogioOffset}"} \ + ${optionalString (cfg.temp != null) "--temp ${cfg.temp}"} \ + ${optionalString (cfg.tempAc != null) "--temp-ac ${cfg.tempAc}"} \ + ${optionalString (cfg.tempBat != null) "--temp-bat ${cfg.tempBat}"} + ''; + }; + }; + + systemd.timers.undervolt = { + description = "Undervolt timer to ensure voltage settings are always applied"; + partOf = [ "undervolt.service" ]; + wantedBy = [ "multi-user.target" ]; + timerConfig = { + OnBootSec = "2min"; + OnUnitActiveSec = "30"; + }; + }; + }; +} diff --git a/nixos/modules/services/misc/redmine.nix b/nixos/modules/services/misc/redmine.nix index 9a9424449f80..f763ba21d0b2 100644 --- a/nixos/modules/services/misc/redmine.nix +++ b/nixos/modules/services/misc/redmine.nix @@ -1,121 +1,124 @@ { config, lib, pkgs, ... }: -# TODO: support non-postgresql - with lib; let cfg = config.services.redmine; - ruby = pkgs.ruby; + bundle = "${pkgs.redmine}/share/redmine/bin/bundle"; - databaseYml = '' + databaseYml = pkgs.writeText "database.yml" '' production: - adapter: postgresql - database: ${cfg.databaseName} - host: ${cfg.databaseHost} - password: ${cfg.databasePassword} - username: ${cfg.databaseUsername} - encoding: utf8 + adapter: ${cfg.database.type} + database: ${cfg.database.name} + host: ${cfg.database.host} + port: ${toString cfg.database.port} + username: ${cfg.database.user} + password: #dbpass# ''; - configurationYml = '' + configurationYml = pkgs.writeText "configuration.yml" '' default: - # Absolute path to the directory where attachments are stored. - # The default is the 'files' directory in your Redmine instance. - # Your Redmine instance needs to have write permission on this - # directory. - # Examples: - # attachments_storage_path: /var/redmine/files - # attachments_storage_path: D:/redmine/files - attachments_storage_path: ${cfg.stateDir}/files - - # Absolute path to the SCM commands errors (stderr) log file. - # The default is to log in the 'log' directory of your Redmine instance. - # Example: - # scm_stderr_log_file: /var/log/redmine_scm_stderr.log - scm_stderr_log_file: ${cfg.stateDir}/redmine_scm_stderr.log - - ${cfg.extraConfig} + scm_subversion_command: ${pkgs.subversion}/bin/svn + scm_mercurial_command: ${pkgs.mercurial}/bin/hg + scm_git_command: ${pkgs.gitAndTools.git}/bin/git + scm_cvs_command: ${pkgs.cvs}/bin/cvs + scm_bazaar_command: ${pkgs.bazaar}/bin/bzr + scm_darcs_command: ${pkgs.darcs}/bin/darcs + + ${cfg.extraConfig} ''; - unpackTheme = unpack "theme"; - unpackPlugin = unpack "plugin"; - unpack = id: (name: source: - pkgs.stdenv.mkDerivation { - name = "redmine-${id}-${name}"; - buildInputs = [ pkgs.unzip ]; - buildCommand = '' - mkdir -p $out - cd $out - unpackFile ${source} - ''; - }); - -in { +in +{ options = { services.redmine = { enable = mkOption { type = types.bool; default = false; - description = '' - Enable the redmine service. - ''; + description = "Enable the Redmine service."; }; - stateDir = mkOption { + user = mkOption { type = types.str; - default = "/var/redmine"; - description = "The state directory, logs and plugins are stored here"; - }; - - extraConfig = mkOption { - type = types.lines; - default = ""; - description = "Extra configuration in configuration.yml"; - }; - - themes = mkOption { - type = types.attrsOf types.path; - default = {}; - description = "Set of themes"; + default = "redmine"; + description = "User under which Redmine is ran."; }; - plugins = mkOption { - type = types.attrsOf types.path; - default = {}; - description = "Set of plugins"; + group = mkOption { + type = types.str; + default = "redmine"; + description = "Group under which Redmine is ran."; }; - #databaseType = mkOption { - # type = types.str; - # default = "postgresql"; - # description = "Type of database"; - #}; - - databaseHost = mkOption { + stateDir = mkOption { type = types.str; - default = "127.0.0.1"; - description = "Database hostname"; + default = "/var/lib/redmine"; + description = "The state directory, logs and plugins are stored here."; }; - databasePassword = mkOption { - type = types.str; + extraConfig = mkOption { + type = types.lines; default = ""; - description = "Database user password"; - }; + description = '' + Extra configuration in configuration.yml. - databaseName = mkOption { - type = types.str; - default = "redmine"; - description = "Database name"; + See https://guides.rubyonrails.org/action_mailer_basics.html#action-mailer-configuration + ''; }; - databaseUsername = mkOption { - type = types.str; - default = "redmine"; - description = "Database user"; + database = { + type = mkOption { + type = types.enum [ "mysql2" "postgresql" ]; + example = "postgresql"; + default = "mysql2"; + description = "Database engine to use."; + }; + + host = mkOption { + type = types.str; + default = "127.0.0.1"; + description = "Database host address."; + }; + + port = mkOption { + type = types.int; + default = 3306; + description = "Database host port."; + }; + + name = mkOption { + type = types.str; + default = "redmine"; + description = "Database name."; + }; + + user = mkOption { + type = types.str; + default = "redmine"; + description = "Database user."; + }; + + password = mkOption { + type = types.str; + default = ""; + description = '' + The password corresponding to <option>database.user</option>. + Warning: this is stored in cleartext in the Nix store! + Use <option>database.passwordFile</option> instead. + ''; + }; + + passwordFile = mkOption { + type = types.nullOr types.path; + default = null; + example = "/run/keys/redmine-dbpassword"; + description = '' + A file containing the password corresponding to + <option>database.user</option>. + ''; + }; }; }; }; @@ -123,99 +126,106 @@ in { config = mkIf cfg.enable { assertions = [ - { assertion = cfg.databasePassword != ""; - message = "services.redmine.databasePassword must be set"; + { assertion = cfg.database.passwordFile != null || cfg.database.password != ""; + message = "either services.redmine.database.passwordFile or services.redmine.database.password must be set"; } ]; - users.users = [ - { name = "redmine"; - group = "redmine"; - uid = config.ids.uids.redmine; - } ]; - - users.groups = [ - { name = "redmine"; - gid = config.ids.gids.redmine; - } ]; + environment.systemPackages = [ pkgs.redmine ]; systemd.services.redmine = { - after = [ "network.target" "postgresql.service" ]; + after = [ "network.target" (if cfg.database.type == "mysql2" then "mysql.service" else "postgresql.service") ]; wantedBy = [ "multi-user.target" ]; + environment.HOME = "${pkgs.redmine}/share/redmine"; environment.RAILS_ENV = "production"; - environment.RAILS_ETC = "${cfg.stateDir}/config"; - environment.RAILS_LOG = "${cfg.stateDir}/log"; - environment.RAILS_VAR = "${cfg.stateDir}/var"; environment.RAILS_CACHE = "${cfg.stateDir}/cache"; - environment.RAILS_PLUGINS = "${cfg.stateDir}/plugins"; - environment.RAILS_PUBLIC = "${cfg.stateDir}/public"; - environment.RAILS_TMP = "${cfg.stateDir}/tmp"; - environment.SCHEMA = "${cfg.stateDir}/cache/schema.db"; - environment.HOME = "${pkgs.redmine}/share/redmine"; environment.REDMINE_LANG = "en"; - environment.GEM_HOME = "${pkgs.redmine}/share/redmine/vendor/bundle/ruby/1.9.1"; - environment.GEM_PATH = "${pkgs.bundler}/${pkgs.bundler.ruby.gemPath}"; + environment.SCHEMA = "${cfg.stateDir}/cache/schema.db"; path = with pkgs; [ imagemagickBig - subversion - mercurial - cvs - config.services.postgresql.package bazaar + cvs + darcs gitAndTools.git - # once we build binaries for darc enable it - #darcs + mercurial + subversion ]; preStart = '' - # TODO: use env vars - for i in plugins public/plugin_assets db files log config cache var/files tmp; do + # start with a fresh config directory every time + rm -rf ${cfg.stateDir}/config + cp -r ${pkgs.redmine}/share/redmine/config.dist ${cfg.stateDir}/config + + # create the basic state directory layout pkgs.redmine expects + mkdir -p /run/redmine + + for i in config files log plugins tmp; do mkdir -p ${cfg.stateDir}/$i + ln -fs ${cfg.stateDir}/$i /run/redmine/$i done - chown -R redmine:redmine ${cfg.stateDir} - chmod -R 755 ${cfg.stateDir} + # ensure cache directory exists for db:migrate command + mkdir -p ${cfg.stateDir}/cache - rm -rf ${cfg.stateDir}/public/* - cp -R ${pkgs.redmine}/share/redmine/public/* ${cfg.stateDir}/public/ - for theme in ${concatStringsSep " " (mapAttrsToList unpackTheme cfg.themes)}; do - ln -fs $theme/* ${cfg.stateDir}/public/themes/ - done + # link in the application configuration + ln -fs ${configurationYml} ${cfg.stateDir}/config/configuration.yml - rm -rf ${cfg.stateDir}/plugins/* - for plugin in ${concatStringsSep " " (mapAttrsToList unpackPlugin cfg.plugins)}; do - ln -fs $plugin/* ${cfg.stateDir}/plugins/''${plugin##*-redmine-plugin-} - done + chmod -R ug+rwX,o-rwx+x ${cfg.stateDir}/ - ln -fs ${pkgs.writeText "database.yml" databaseYml} ${cfg.stateDir}/config/database.yml - ln -fs ${pkgs.writeText "configuration.yml" configurationYml} ${cfg.stateDir}/config/configuration.yml + # handle database.passwordFile + DBPASS=$(head -n1 ${cfg.database.passwordFile}) + cp -f ${databaseYml} ${cfg.stateDir}/config/database.yml + sed -e "s,#dbpass#,$DBPASS,g" -i ${cfg.stateDir}/config/database.yml + chmod 440 ${cfg.stateDir}/config/database.yml - if [ "${cfg.databaseHost}" = "127.0.0.1" ]; then - if ! test -e "${cfg.stateDir}/db-created"; then - psql postgres -c "CREATE ROLE redmine WITH LOGIN NOCREATEDB NOCREATEROLE ENCRYPTED PASSWORD '${cfg.databasePassword}'" - ${config.services.postgresql.package}/bin/createdb --owner redmine redmine || true - touch "${cfg.stateDir}/db-created" - fi + # generate a secret token if required + if ! test -e "${cfg.stateDir}/config/initializers/secret_token.rb"; then + ${bundle} exec rake generate_secret_token + chmod 440 ${cfg.stateDir}/config/initializers/secret_token.rb fi - cd ${pkgs.redmine}/share/redmine/ - ${ruby}/bin/rake db:migrate - ${ruby}/bin/rake redmine:plugins:migrate - ${ruby}/bin/rake redmine:load_default_data - ${ruby}/bin/rake generate_secret_token + # ensure everything is owned by ${cfg.user} + chown -R ${cfg.user}:${cfg.group} ${cfg.stateDir} + + ${bundle} exec rake db:migrate + ${bundle} exec rake redmine:load_default_data ''; serviceConfig = { PermissionsStartOnly = true; # preStart must be run as root Type = "simple"; - User = "redmine"; - Group = "redmine"; + User = cfg.user; + Group = cfg.group; TimeoutSec = "300"; WorkingDirectory = "${pkgs.redmine}/share/redmine"; - ExecStart="${ruby}/bin/ruby ${pkgs.redmine}/share/redmine/script/rails server webrick -e production -P ${cfg.stateDir}/redmine.pid"; + ExecStart="${bundle} exec rails server webrick -e production -P ${cfg.stateDir}/redmine.pid"; }; }; + users.extraUsers = optionalAttrs (cfg.user == "redmine") (singleton + { name = "redmine"; + group = cfg.group; + home = cfg.stateDir; + createHome = true; + uid = config.ids.uids.redmine; + }); + + users.extraGroups = optionalAttrs (cfg.group == "redmine") (singleton + { name = "redmine"; + gid = config.ids.gids.redmine; + }); + + warnings = optional (cfg.database.password != "") + ''config.services.redmine.database.password will be stored as plaintext + in the Nix store. Use database.passwordFile instead.''; + + # Create database passwordFile default when password is configured. + services.redmine.database.passwordFile = + (mkDefault (toString (pkgs.writeTextFile { + name = "redmine-database-password"; + text = cfg.database.password; + }))); + }; } diff --git a/nixos/modules/services/networking/dhcpcd.nix b/nixos/modules/services/networking/dhcpcd.nix index 019c8fd9ec48..efdbca5d52e8 100644 --- a/nixos/modules/services/networking/dhcpcd.nix +++ b/nixos/modules/services/networking/dhcpcd.nix @@ -161,8 +161,9 @@ in { description = "DHCP Client"; wantedBy = [ "multi-user.target" ] ++ optional (!hasDefaultGatewaySet) "network-online.target"; - wants = [ "network.target" ]; + wants = [ "network.target" "systemd-udev-settle.service" ]; before = [ "network.target" ]; + after = [ "systemd-udev-settle.service" ]; # Stopping dhcpcd during a reconfiguration is undesirable # because it brings down the network interfaces configured by diff --git a/nixos/modules/services/security/cfssl.nix b/nixos/modules/services/security/cfssl.nix index 1eb2f65ba602..ee6d5d91fe15 100644 --- a/nixos/modules/services/security/cfssl.nix +++ b/nixos/modules/services/security/cfssl.nix @@ -146,7 +146,7 @@ in { }; }; - config = { + config = mkIf cfg.enable { users.extraGroups.cfssl = { gid = config.ids.gids.cfssl; }; @@ -159,7 +159,7 @@ in { uid = config.ids.uids.cfssl; }; - systemd.services.cfssl = mkIf cfg.enable { + systemd.services.cfssl = { description = "CFSSL CA API server"; wantedBy = [ "multi-user.target" ]; after = [ "network.target" ]; |