diff options
Diffstat (limited to 'nixos/modules/services/admin')
-rw-r--r-- | nixos/modules/services/admin/meshcentral.nix | 53 | ||||
-rw-r--r-- | nixos/modules/services/admin/oxidized.nix | 118 | ||||
-rw-r--r-- | nixos/modules/services/admin/pgadmin.nix | 127 | ||||
-rw-r--r-- | nixos/modules/services/admin/salt/master.nix | 63 | ||||
-rw-r--r-- | nixos/modules/services/admin/salt/minion.nix | 67 |
5 files changed, 428 insertions, 0 deletions
diff --git a/nixos/modules/services/admin/meshcentral.nix b/nixos/modules/services/admin/meshcentral.nix new file mode 100644 index 00000000000..92762d2037c --- /dev/null +++ b/nixos/modules/services/admin/meshcentral.nix @@ -0,0 +1,53 @@ +{ config, pkgs, lib, ... }: +let + cfg = config.services.meshcentral; + configFormat = pkgs.formats.json {}; + configFile = configFormat.generate "meshcentral-config.json" cfg.settings; +in with lib; { + options.services.meshcentral = with types; { + enable = mkEnableOption "MeshCentral computer management server"; + package = mkOption { + description = "MeshCentral package to use. Replacing this may be necessary to add dependencies for extra functionality."; + type = types.package; + default = pkgs.meshcentral; + defaultText = literalExpression "pkgs.meshcentral"; + }; + settings = mkOption { + description = '' + Settings for MeshCentral. Refer to upstream documentation for details: + + <itemizedlist> + <listitem><para><link xlink:href="https://github.com/Ylianst/MeshCentral/blob/master/meshcentral-config-schema.json">JSON Schema definition</link></para></listitem> + <listitem><para><link xlink:href="https://github.com/Ylianst/MeshCentral/blob/master/sample-config.json">simple sample configuration</link></para></listitem> + <listitem><para><link xlink:href="https://github.com/Ylianst/MeshCentral/blob/master/sample-config-advanced.json">complex sample configuration</link></para></listitem> + <listitem><para><link xlink:href="https://www.meshcommander.com/meshcentral2">Old homepage) with documentation link</link></para></listitem> + </itemizedlist> + ''; + type = types.submodule { + freeformType = configFormat.type; + }; + example = { + settings = { + WANonly = true; + Cert = "meshcentral.example.com"; + TlsOffload = "10.0.0.2,fd42::2"; + Port = 4430; + }; + domains."".certUrl = "https://meshcentral.example.com/"; + }; + }; + }; + config = mkIf cfg.enable { + services.meshcentral.settings.settings.autoBackup.backupPath = lib.mkDefault "/var/lib/meshcentral/backups"; + systemd.services.meshcentral = { + wantedBy = ["multi-user.target"]; + serviceConfig = { + ExecStart = "${cfg.package}/bin/meshcentral --datapath /var/lib/meshcentral --configfile ${configFile}"; + DynamicUser = true; + StateDirectory = "meshcentral"; + CacheDirectory = "meshcentral"; + }; + }; + }; + meta.maintainers = [ maintainers.lheckemann ]; +} diff --git a/nixos/modules/services/admin/oxidized.nix b/nixos/modules/services/admin/oxidized.nix new file mode 100644 index 00000000000..49ea3ced76a --- /dev/null +++ b/nixos/modules/services/admin/oxidized.nix @@ -0,0 +1,118 @@ +{ config, pkgs, lib, ... }: + +with lib; + +let + cfg = config.services.oxidized; +in +{ + options.services.oxidized = { + enable = mkEnableOption "the oxidized configuration backup service"; + + user = mkOption { + type = types.str; + default = "oxidized"; + description = '' + User under which the oxidized service runs. + ''; + }; + + group = mkOption { + type = types.str; + default = "oxidized"; + description = '' + Group under which the oxidized service runs. + ''; + }; + + dataDir = mkOption { + type = types.path; + default = "/var/lib/oxidized"; + description = "State directory for the oxidized service."; + }; + + configFile = mkOption { + type = types.path; + example = literalExpression '' + pkgs.writeText "oxidized-config.yml" ''' + --- + debug: true + use_syslog: true + input: + default: ssh + ssh: + secure: true + interval: 3600 + model_map: + dell: powerconnect + hp: procurve + source: + default: csv + csv: + delimiter: !ruby/regexp /:/ + file: "/var/lib/oxidized/.config/oxidized/router.db" + map: + name: 0 + model: 1 + username: 2 + password: 3 + pid: "/var/lib/oxidized/.config/oxidized/pid" + rest: 127.0.0.1:8888 + retries: 3 + # ... additional config + '''; + ''; + description = '' + Path to the oxidized configuration file. + ''; + }; + + routerDB = mkOption { + type = types.path; + example = literalExpression '' + pkgs.writeText "oxidized-router.db" ''' + hostname-sw1:powerconnect:username1:password2 + hostname-sw2:procurve:username2:password2 + # ... additional hosts + ''' + ''; + description = '' + Path to the file/database which contains the targets for oxidized. + ''; + }; + }; + + config = mkIf cfg.enable { + users.groups.${cfg.group} = { }; + users.users.${cfg.user} = { + description = "Oxidized service user"; + group = cfg.group; + home = cfg.dataDir; + createHome = true; + isSystemUser = true; + }; + + systemd.services.oxidized = { + wantedBy = [ "multi-user.target" ]; + after = [ "network.target" ]; + + preStart = '' + mkdir -p ${cfg.dataDir}/.config/oxidized + ln -f -s ${cfg.routerDB} ${cfg.dataDir}/.config/oxidized/router.db + ln -f -s ${cfg.configFile} ${cfg.dataDir}/.config/oxidized/config + ''; + + serviceConfig = { + ExecStart = "${pkgs.oxidized}/bin/oxidized"; + User = cfg.user; + Group = cfg.group; + UMask = "0077"; + NoNewPrivileges = true; + Restart = "always"; + WorkingDirectory = cfg.dataDir; + KillSignal = "SIGKILL"; + PIDFile = "${cfg.dataDir}/.config/oxidized/pid"; + }; + }; + }; +} diff --git a/nixos/modules/services/admin/pgadmin.nix b/nixos/modules/services/admin/pgadmin.nix new file mode 100644 index 00000000000..80b68145410 --- /dev/null +++ b/nixos/modules/services/admin/pgadmin.nix @@ -0,0 +1,127 @@ +{ config, lib, pkgs, ... }: + +with lib; + +let + pkg = pkgs.pgadmin4; + cfg = config.services.pgadmin; + + _base = with types; [ int bool str ]; + base = with types; oneOf ([ (listOf (oneOf _base)) (attrsOf (oneOf _base)) ] ++ _base); + + formatAttrset = attr: + "{${concatStringsSep "\n" (mapAttrsToList (key: value: "${builtins.toJSON key}: ${formatPyValue value},") attr)}}"; + + formatPyValue = value: + if builtins.isString value then builtins.toJSON value + else if value ? _expr then value._expr + else if builtins.isInt value then toString value + else if builtins.isBool value then (if value then "True" else "False") + else if builtins.isAttrs value then (formatAttrset value) + else if builtins.isList value then "[${concatStringsSep "\n" (map (v: "${formatPyValue v},") value)}]" + else throw "Unrecognized type"; + + formatPy = attrs: + concatStringsSep "\n" (mapAttrsToList (key: value: "${key} = ${formatPyValue value}") attrs); + + pyType = with types; attrsOf (oneOf [ (attrsOf base) (listOf base) base ]); +in +{ + options.services.pgadmin = { + enable = mkEnableOption "PostgreSQL Admin 4"; + + port = mkOption { + description = "Port for pgadmin4 to run on"; + type = types.port; + default = 5050; + }; + + initialEmail = mkOption { + description = "Initial email for the pgAdmin account."; + type = types.str; + }; + + initialPasswordFile = mkOption { + description = '' + Initial password file for the pgAdmin account. + NOTE: Should be string not a store path, to prevent the password from being world readable. + ''; + type = types.path; + }; + + openFirewall = mkEnableOption "firewall passthrough for pgadmin4"; + + settings = mkOption { + description = '' + Settings for pgadmin4. + <link xlink:href="https://www.pgadmin.org/docs/pgadmin4/development/config_py.html">Documentation</link>. + ''; + type = pyType; + default= {}; + }; + }; + + config = mkIf (cfg.enable) { + networking.firewall.allowedTCPPorts = mkIf (cfg.openFirewall) [ cfg.port ]; + + services.pgadmin.settings = { + DEFAULT_SERVER_PORT = cfg.port; + SERVER_MODE = true; + } // (optionalAttrs cfg.openFirewall { + DEFAULT_SERVER = mkDefault "::"; + }); + + systemd.services.pgadmin = { + wantedBy = [ "multi-user.target" ]; + after = [ "network.target" ]; + requires = [ "network.target" ]; + # we're adding this optionally so just in case there's any race it'll be caught + # in case postgres doesn't start, pgadmin will just start normally + wants = [ "postgresql.service" ]; + + path = [ config.services.postgresql.package pkgs.coreutils pkgs.bash ]; + + preStart = '' + # NOTE: this is idempotent (aka running it twice has no effect) + ( + # Email address: + echo ${escapeShellArg cfg.initialEmail} + + # file might not contain newline. echo hack fixes that. + PW=$(cat ${escapeShellArg cfg.initialPasswordFile}) + + # Password: + echo "$PW" + # Retype password: + echo "$PW" + ) | ${pkg}/bin/pgadmin4-setup + ''; + + restartTriggers = [ + "/etc/pgadmin/config_system.py" + ]; + + serviceConfig = { + User = "pgadmin"; + DynamicUser = true; + LogsDirectory = "pgadmin"; + StateDirectory = "pgadmin"; + ExecStart = "${pkg}/bin/pgadmin4"; + }; + }; + + users.users.pgadmin = { + isSystemUser = true; + group = "pgadmin"; + }; + + users.groups.pgadmin = {}; + + environment.etc."pgadmin/config_system.py" = { + text = formatPy cfg.settings; + mode = "0600"; + user = "pgadmin"; + group = "pgadmin"; + }; + }; +} diff --git a/nixos/modules/services/admin/salt/master.nix b/nixos/modules/services/admin/salt/master.nix new file mode 100644 index 00000000000..a3069c81c19 --- /dev/null +++ b/nixos/modules/services/admin/salt/master.nix @@ -0,0 +1,63 @@ +{ config, pkgs, lib, ... }: + +with lib; + +let + + cfg = config.services.salt.master; + + fullConfig = lib.recursiveUpdate { + # Provide defaults for some directories to allow an immutable config dir + + # Default is equivalent to /etc/salt/master.d/*.conf + default_include = "/var/lib/salt/master.d/*.conf"; + # Default is in /etc/salt/pki/master + pki_dir = "/var/lib/salt/pki/master"; + } cfg.configuration; + +in + +{ + options = { + services.salt.master = { + enable = mkEnableOption "Salt master service"; + configuration = mkOption { + type = types.attrs; + default = {}; + description = "Salt master configuration as Nix attribute set."; + }; + }; + }; + + config = mkIf cfg.enable { + environment = { + # Set this up in /etc/salt/master so `salt`, `salt-key`, etc. work. + # The alternatives are + # - passing --config-dir to all salt commands, not just the master unit, + # - setting a global environment variable, + etc."salt/master".source = pkgs.writeText "master" ( + builtins.toJSON fullConfig + ); + systemPackages = with pkgs; [ salt ]; + }; + systemd.services.salt-master = { + description = "Salt Master"; + wantedBy = [ "multi-user.target" ]; + after = [ "network.target" ]; + path = with pkgs; [ + util-linux # for dmesg + ]; + serviceConfig = { + ExecStart = "${pkgs.salt}/bin/salt-master"; + LimitNOFILE = 16384; + Type = "notify"; + NotifyAccess = "all"; + }; + restartTriggers = [ + config.environment.etc."salt/master".source + ]; + }; + }; + + meta.maintainers = with lib.maintainers; [ Flakebi ]; +} diff --git a/nixos/modules/services/admin/salt/minion.nix b/nixos/modules/services/admin/salt/minion.nix new file mode 100644 index 00000000000..ac124c570d8 --- /dev/null +++ b/nixos/modules/services/admin/salt/minion.nix @@ -0,0 +1,67 @@ +{ config, pkgs, lib, ... }: + +with lib; + +let + + cfg = config.services.salt.minion; + + fullConfig = lib.recursiveUpdate { + # Provide defaults for some directories to allow an immutable config dir + # NOTE: the config dir being immutable prevents `minion_id` caching + + # Default is equivalent to /etc/salt/minion.d/*.conf + default_include = "/var/lib/salt/minion.d/*.conf"; + # Default is in /etc/salt/pki/minion + pki_dir = "/var/lib/salt/pki/minion"; + } cfg.configuration; + +in + +{ + options = { + services.salt.minion = { + enable = mkEnableOption "Salt minion service"; + configuration = mkOption { + type = types.attrs; + default = {}; + description = '' + Salt minion configuration as Nix attribute set. + See <link xlink:href="https://docs.saltstack.com/en/latest/ref/configuration/minion.html"/> + for details. + ''; + }; + }; + }; + + config = mkIf cfg.enable { + environment = { + # Set this up in /etc/salt/minion so `salt-call`, etc. work. + # The alternatives are + # - passing --config-dir to all salt commands, not just the minion unit, + # - setting aglobal environment variable. + etc."salt/minion".source = pkgs.writeText "minion" ( + builtins.toJSON fullConfig + ); + systemPackages = with pkgs; [ salt ]; + }; + systemd.services.salt-minion = { + description = "Salt Minion"; + wantedBy = [ "multi-user.target" ]; + after = [ "network.target" ]; + path = with pkgs; [ + util-linux + ]; + serviceConfig = { + ExecStart = "${pkgs.salt}/bin/salt-minion"; + LimitNOFILE = 8192; + Type = "notify"; + NotifyAccess = "all"; + }; + restartTriggers = [ + config.environment.etc."salt/minion".source + ]; + }; + }; +} + |