move some modules to my nur repo
This commit is contained in:
parent
4fa2ec5f78
commit
02f9916be6
@ -1,4 +1,6 @@
|
||||
{ config, inputs, ... }: {
|
||||
imports = [ inputs.ataraxiasjel-nur.nixosModules.rustic ];
|
||||
|
||||
sops.secrets.rustic-nas-pass.sopsFile = inputs.self.secretsDir + /rustic.yaml;
|
||||
sops.secrets.rclone-rustic-backups.sopsFile = inputs.self.secretsDir + /rustic.yaml;
|
||||
services.rustic.backups = rec {
|
||||
|
@ -1,4 +1,6 @@
|
||||
{ config, inputs, ... }: {
|
||||
imports = [ inputs.ataraxiasjel-nur.nixosModules.rustic ];
|
||||
|
||||
sops.secrets.rustic-vps-pass.sopsFile = inputs.self.secretsDir + /rustic.yaml;
|
||||
sops.secrets.rclone-rustic-backups.sopsFile = inputs.self.secretsDir + /rustic.yaml;
|
||||
services.rustic.backups = rec {
|
||||
@ -31,7 +33,7 @@
|
||||
ignore-devid = true;
|
||||
group-by = "label";
|
||||
sources = [{
|
||||
source = "/srv/marzban /srv/nextcloud/config /srv/nextcloud/data";
|
||||
source = "/srv/marzban";
|
||||
}];
|
||||
};
|
||||
forget = {
|
||||
|
@ -1,320 +0,0 @@
|
||||
# Thanks for original module, anpin! https://gist.github.com/anpin/ecbdb6625400908856ef9482eca3380c
|
||||
{ config, pkgs, lib, ... }:
|
||||
let
|
||||
cfg = config.services.authentik;
|
||||
databaseActuallyCreateLocally = cfg.database.createLocally
|
||||
&& cfg.database.host == "/run/postgresql";
|
||||
|
||||
inherit (lib)
|
||||
mkIf mkEnableOption mkOption types mdDoc literalExpression optional attrsets;
|
||||
inherit (attrsets) optionalAttrs;
|
||||
inherit (types) str bool port submodule package nullOr path enum;
|
||||
|
||||
hostWithPort = h: p: "${h}:${toString p}";
|
||||
|
||||
authentikBaseService = {
|
||||
after = [ "network.target" ]
|
||||
++ optional databaseActuallyCreateLocally "postgresql.service";
|
||||
wantedBy = [ "multi-user.target" ];
|
||||
path = [ cfg.package ];
|
||||
environment = let
|
||||
listenAddress = hostWithPort cfg.listen.address;
|
||||
in {
|
||||
AUTHENTIK_REDIS__HOST = cfg.redis.host;
|
||||
AUTHENTIK_REDIS__PORT = toString cfg.redis.port;
|
||||
|
||||
AUTHENTIK_POSTGRESQL__HOST = cfg.database.host;
|
||||
AUTHENTIK_POSTGRESQL__PORT = mkIf (cfg.database.port != null) "${toString cfg.database.port}";
|
||||
AUTHENTIK_POSTGRESQL__USER = cfg.database.user;
|
||||
AUTHENTIK_POSTGRESQL__NAME = cfg.database.name;
|
||||
|
||||
AUTHENTIK_LISTEN__HTTP = listenAddress cfg.listen.http;
|
||||
AUTHENTIK_LISTEN__HTTPS = listenAddress cfg.listen.https;
|
||||
|
||||
# initial password for admin user
|
||||
AUTHENTIK_BOOTSTRAP_PASSWORD = cfg.defaultPassword;
|
||||
|
||||
# disable outbound connections
|
||||
AUTHENTIK_DISABLE_UPDATE_CHECK = "true";
|
||||
AUTHENTIK_ERROR_REPORTING__ENABLED = "false";
|
||||
AUTHENTIK_DISABLE_STARTUP_ANALYTICS = "true";
|
||||
AUTHENTIK_AVATARS = "initials";
|
||||
|
||||
AUTHENTIK_LOG_LEVEL = cfg.logLevel;
|
||||
};
|
||||
serviceConfig = {
|
||||
User = "authentik";
|
||||
Group = "authentik";
|
||||
EnvironmentFile = cfg.environmentFile;
|
||||
WorkingDirectory = cfg.package;
|
||||
DynamicUser = true;
|
||||
RuntimeDirectory = "authentik";
|
||||
NoNewPrivileges = true;
|
||||
PrivateTmp = true;
|
||||
ProtectHome = true;
|
||||
ProtectSystem = "strict";
|
||||
ProtectKernelTunables = true;
|
||||
ProtectKernelModules = true;
|
||||
ProtectControlGroups = true;
|
||||
SystemCallFilter= "~@cpu-emulation @keyring @module @obsolete @raw-io @reboot @swap @sync";
|
||||
ConfigurationDirectory = "authentik";
|
||||
StateDirectoryMode = "0750";
|
||||
};
|
||||
};
|
||||
in {
|
||||
options.services.authentik = {
|
||||
enable = mkEnableOption "Enables Authentik service";
|
||||
|
||||
package = mkOption {
|
||||
type = package;
|
||||
default = pkgs.authentik;
|
||||
defaultText = literalExpression "pkgs.authentik";
|
||||
description = mdDoc "Authentik package to use.";
|
||||
};
|
||||
|
||||
defaultPassword = mkOption {
|
||||
description = mdDoc "Default admin password. Only read on first startup.";
|
||||
type = str;
|
||||
default = "change-me";
|
||||
};
|
||||
|
||||
logLevel = mkOption {
|
||||
description = mdDoc
|
||||
"Log level for the server and worker containers. Setting the log level to trace will include sensitive details in logs, so it shouldn't be used in most cases.";
|
||||
type = enum [ "trace" "debug" "info" "warning" "error" ];
|
||||
default = "info";
|
||||
};
|
||||
|
||||
listen = mkOption {
|
||||
description = mdDoc "Listen ports";
|
||||
default = { };
|
||||
type = submodule {
|
||||
options = {
|
||||
http = mkOption {
|
||||
description = mdDoc "HTTP port.";
|
||||
type = port;
|
||||
default = 9000;
|
||||
};
|
||||
https = mkOption {
|
||||
description = mdDoc "HTTPS port.";
|
||||
type = port;
|
||||
default = 9443;
|
||||
};
|
||||
address = mkOption {
|
||||
description = mdDoc "Address to listen on.";
|
||||
type = str;
|
||||
default = "0.0.0.0";
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
redis = {
|
||||
createLocally = mkOption {
|
||||
description = mdDoc "Configure local Redis server for Authentik.";
|
||||
type = bool;
|
||||
default = true;
|
||||
};
|
||||
|
||||
host = mkOption {
|
||||
description = mdDoc "Redis host.";
|
||||
type = str;
|
||||
default = "127.0.0.1";
|
||||
};
|
||||
|
||||
port = mkOption {
|
||||
description = mdDoc "Redis port.";
|
||||
type = port;
|
||||
default = 31637;
|
||||
};
|
||||
};
|
||||
ssl = {
|
||||
cert = mkOption {
|
||||
type = nullOr path;
|
||||
default = null;
|
||||
};
|
||||
|
||||
key = mkOption {
|
||||
type = nullOr path;
|
||||
default = null;
|
||||
};
|
||||
|
||||
name = mkOption {
|
||||
type = str;
|
||||
default = "SSL from NIXOS";
|
||||
};
|
||||
};
|
||||
|
||||
environmentFile = mkOption {
|
||||
type = nullOr path;
|
||||
default = null;
|
||||
example = "/var/lib/authentik/secrets/db-password";
|
||||
description = mdDoc ''
|
||||
Environment variables including :
|
||||
- Secret key used for cookie signing and unique user IDs, don't change this after the first install.
|
||||
'';
|
||||
};
|
||||
|
||||
database = {
|
||||
createLocally = mkOption {
|
||||
description =
|
||||
mdDoc "Configure local PostgreSQL database server for authentik.";
|
||||
type = bool;
|
||||
default = true;
|
||||
};
|
||||
|
||||
host = mkOption {
|
||||
type = str;
|
||||
default = "/run/postgresql";
|
||||
example = "192.168.23.42";
|
||||
description = mdDoc "Database host address or unix socket.";
|
||||
};
|
||||
|
||||
port = mkOption {
|
||||
type = nullOr port;
|
||||
default = if cfg.database.createLocally then null else 5432;
|
||||
defaultText = literalExpression ''
|
||||
if config.database.createLocally then null else 5432
|
||||
'';
|
||||
description = mdDoc "Database host port.";
|
||||
};
|
||||
|
||||
name = mkOption {
|
||||
type = str;
|
||||
default = "authentik";
|
||||
description = mdDoc "Database name.";
|
||||
};
|
||||
|
||||
user = mkOption {
|
||||
type = str;
|
||||
default = "authentik";
|
||||
description = mdDoc "Database user.";
|
||||
};
|
||||
};
|
||||
|
||||
outposts = mkOption {
|
||||
type = submodule {
|
||||
options = {
|
||||
ldap = mkOption {
|
||||
type = submodule {
|
||||
options = {
|
||||
enable =
|
||||
mkEnableOption (lib.mdDoc "the authentik ldap outpost");
|
||||
package = mkOption {
|
||||
type = path;
|
||||
default = pkgs.authentik-outposts.ldap;
|
||||
};
|
||||
host = mkOption {
|
||||
type = str;
|
||||
default = if cfg.outposts.ldap.insecure then
|
||||
"http://127.0.0.1:${toString cfg.listen.http}"
|
||||
else
|
||||
"https://127.0.0.1:${toString cfg.listen.https}";
|
||||
};
|
||||
insecure = mkOption {
|
||||
type = bool;
|
||||
default = false;
|
||||
};
|
||||
environmentFile = mkOption {
|
||||
type = nullOr path;
|
||||
default = null;
|
||||
example = "/var/lib/authentik-ldap/secrets/env";
|
||||
description = mdDoc ''
|
||||
Environment variables including :
|
||||
- API TOKEN
|
||||
'';
|
||||
};
|
||||
listen = mkOption {
|
||||
description = mdDoc "Listen ports";
|
||||
default = { };
|
||||
type = submodule {
|
||||
options = {
|
||||
ldap = mkOption {
|
||||
description = mdDoc "LDAP port.";
|
||||
type = port;
|
||||
default = 3389;
|
||||
};
|
||||
ldaps = mkOption {
|
||||
description = mdDoc "LDAPS port.";
|
||||
type = port;
|
||||
default = 6636;
|
||||
};
|
||||
address = mkOption {
|
||||
description = mdDoc "Address to listen on.";
|
||||
type = str;
|
||||
default = "0.0.0.0";
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
default = { ldap = { enable = false; }; };
|
||||
};
|
||||
};
|
||||
|
||||
config = mkIf cfg.enable {
|
||||
users.users.authentik = {
|
||||
isSystemUser = true;
|
||||
home = cfg.package;
|
||||
group = "authentik";
|
||||
};
|
||||
users.groups.authentik = { };
|
||||
|
||||
services.postgresql = mkIf databaseActuallyCreateLocally {
|
||||
enable = true;
|
||||
ensureUsers = [{
|
||||
name = cfg.database.name;
|
||||
ensureDBOwnership = true;
|
||||
}];
|
||||
ensureDatabases = [ cfg.database.name ];
|
||||
};
|
||||
|
||||
services.redis.servers.authentik =
|
||||
mkIf (cfg.redis.createLocally && cfg.redis.host == "127.0.0.1") {
|
||||
enable = true;
|
||||
port = cfg.redis.port;
|
||||
bind = "127.0.0.1";
|
||||
};
|
||||
|
||||
systemd.services.authentik-server = authentikBaseService // {
|
||||
serviceConfig = authentikBaseService.serviceConfig // {
|
||||
ExecStart = "${cfg.package}/bin/ak server";
|
||||
};
|
||||
};
|
||||
|
||||
systemd.services.authentik-worker = authentikBaseService // {
|
||||
serviceConfig = authentikBaseService.serviceConfig // {
|
||||
ExecStart = "${cfg.package}/bin/ak worker";
|
||||
};
|
||||
};
|
||||
|
||||
# systemd.services.authentik-ssl-import = authentikBaseService // {
|
||||
# before = [ "authentik-server.service" ];
|
||||
# serviceConfig = authentikBaseService.serviceConfig // {
|
||||
# Type = "oneshot";
|
||||
# RemainAfterExit = true;
|
||||
# ExecStart = ''
|
||||
# ${cfg.package}/bin/ak import_certificate --name "${cfg.ssl.name}" --certificate "${cfg.ssl.cert}" --private-key "${cfg.ssl.key}"'';
|
||||
# };
|
||||
# };
|
||||
|
||||
systemd.services.authentik-ldap-outpost = let
|
||||
ldapCfg = cfg.outposts.ldap;
|
||||
in mkIf ldapCfg.enable (authentikBaseService // {
|
||||
description = "authentik ldap outpost";
|
||||
environment = let listenAddress = hostWithPort ldapCfg.listen.address;
|
||||
in {
|
||||
AUTHENTIK_HOST = ldapCfg.host;
|
||||
AUTHENTIK_LISTEN__LDAP = listenAddress ldapCfg.listen.ldap;
|
||||
AUTHENTIK_LISTEN__LDAPS = listenAddress ldapCfg.listen.ldaps;
|
||||
} // optionalAttrs ldapCfg.insecure { AUTHENTIK_INSECURE = "true"; };
|
||||
serviceConfig = authentikBaseService.serviceConfig // {
|
||||
ExecStart = "${cfg.outposts.ldap.package}/bin/ldap";
|
||||
EnvironmentFile = ldapCfg.environmentFile;
|
||||
};
|
||||
});
|
||||
};
|
||||
}
|
@ -1,80 +0,0 @@
|
||||
{ config, lib, pkgs, ... }:
|
||||
with lib;
|
||||
let
|
||||
cfg = config.services.kes;
|
||||
format = pkgs.formats.yaml { };
|
||||
configFile = format.generate "config.yaml" cfg.settings;
|
||||
port = strings.toInt (lists.last (strings.splitString ":" cfg.settings.address));
|
||||
in
|
||||
{
|
||||
options.services.kes = {
|
||||
enable = mkEnableOption (mdDoc "Minio's Key Managament Server");
|
||||
package = mkOption {
|
||||
type = types.package;
|
||||
description = mdDoc "Which package to use for the kes instance.";
|
||||
default = pkgs.minio-kes;
|
||||
};
|
||||
environmentFile = mkOption {
|
||||
type = with types; nullOr str;
|
||||
default = null;
|
||||
description = lib.mdDoc ''
|
||||
File in the format of an EnvironmentFile as described by systemd.exec(5).
|
||||
'';
|
||||
};
|
||||
settings = mkOption {
|
||||
type = format.type;
|
||||
default = { address = "0.0.0.0:7373"; };
|
||||
example = literalExpression ''
|
||||
{
|
||||
address = "0.0.0.0:7373";
|
||||
cache = {
|
||||
expiry = {
|
||||
any = "5m0s";
|
||||
unused = "20s";
|
||||
};
|
||||
};
|
||||
}
|
||||
'';
|
||||
description = mdDoc ''
|
||||
KES Configuration.
|
||||
Refer to <https://github.com/minio/kes/blob/master/server-config.yaml>
|
||||
for details on supported values.
|
||||
'';
|
||||
};
|
||||
};
|
||||
config = mkIf cfg.enable {
|
||||
systemd.services.kes = {
|
||||
description = "KES";
|
||||
wantedBy = [ "multi-user.target" ];
|
||||
wants = [ "network-online.target" ];
|
||||
after = [ "network-online.target" ];
|
||||
path = [ cfg.package ];
|
||||
serviceConfig = {
|
||||
Type = "simple";
|
||||
Restart = "always";
|
||||
ExecStart = "${cfg.package}/bin/kes server --config ${configFile}";
|
||||
User = "kes";
|
||||
Group = "kes";
|
||||
# WorkingDirectory = "/etc/kes";
|
||||
|
||||
AmbientCapabilities = mkIf (port < 1024) ["CAP_NET_BIND_SERVICE"];
|
||||
LimitNOFILE = 65536;
|
||||
ProtectProc = "invisible";
|
||||
SendSIGKILL = "no";
|
||||
TasksMax = "infinity";
|
||||
TimeoutStopSec = "infinity";
|
||||
} // optionalAttrs (cfg.environmentFile != null) {
|
||||
EnvironmentFile = cfg.environmentFile;
|
||||
};
|
||||
};
|
||||
|
||||
environment.systemPackages = [ cfg.package ];
|
||||
|
||||
users.groups.kes = { };
|
||||
users.users.kes = {
|
||||
description = "KES user";
|
||||
group = "kes";
|
||||
isSystemUser = true;
|
||||
};
|
||||
};
|
||||
}
|
159
modules/ocis.nix
159
modules/ocis.nix
@ -1,159 +0,0 @@
|
||||
{ config, lib, pkgs, ... }:
|
||||
with lib;
|
||||
let
|
||||
cfg = config.services.ocis;
|
||||
format = pkgs.formats.yaml { };
|
||||
|
||||
linkConfigs = confDir: lib.pipe cfg.settings [
|
||||
(lib.attrsets.mapAttrs (n: v: format.generate "${n}.yaml" v))
|
||||
(lib.mapAttrsToList (n: v: "ln -sf ${v} ${confDir}/${n}.yaml"))
|
||||
(lib.concatStringsSep "\n")
|
||||
];
|
||||
|
||||
mkExport = { arg, value }: "export ${arg}=${value}";
|
||||
adminpass = {
|
||||
arg = "ADMIN_PASSWORD";
|
||||
value = ''"$(<"${toString cfg.adminpassFile}")"'';
|
||||
};
|
||||
in
|
||||
{
|
||||
options.services.ocis = {
|
||||
enable = mkEnableOption (lib.mdDoc "ownCloud Infinite Scale Stack");
|
||||
package = mkOption {
|
||||
type = types.package;
|
||||
description = lib.mdDoc "Which package to use for the ocis instance.";
|
||||
default = pkgs.ocis-bin;
|
||||
};
|
||||
configDir = mkOption {
|
||||
default = "/var/lib/ocis/.config";
|
||||
type = types.path;
|
||||
description = lib.mdDoc "The config directory. Set OCIS_CONFIG_DIR env variable.";
|
||||
};
|
||||
baseDataPath = mkOption {
|
||||
default = "/var/lib/ocis";
|
||||
type = types.path;
|
||||
description = lib.mdDoc "The base data directory. Set OCIS_BASE_DATA_PATH env variable.";
|
||||
};
|
||||
environment = lib.mkOption {
|
||||
type = lib.types.attrsOf lib.types.str;
|
||||
default = { };
|
||||
example = lib.literalExpression ''
|
||||
{
|
||||
OCIS_URL = "https://localhost:9200";
|
||||
}
|
||||
'';
|
||||
description = lib.mdDoc "Environment variables to pass to ocis instance.";
|
||||
};
|
||||
environmentFile = mkOption {
|
||||
type = with types; nullOr str;
|
||||
default = null;
|
||||
description = lib.mdDoc ''
|
||||
File in the format of an EnvironmentFile as described by systemd.exec(5).
|
||||
'';
|
||||
};
|
||||
adminpassFile = mkOption {
|
||||
type = with types; nullOr str;
|
||||
default = null;
|
||||
description = lib.mdDoc ''
|
||||
The full path to a file that contains the admin's password. Must be
|
||||
readable by user `ocis`. The password is set only in the initial
|
||||
setup of Ocis by the systemd service `ocis-init.service`.
|
||||
'';
|
||||
};
|
||||
settings = mkOption {
|
||||
type = with types; attrsOf format.type;
|
||||
default = { };
|
||||
example = lib.literalExpression ''
|
||||
{
|
||||
auth-bearer = {
|
||||
tracing = {
|
||||
enabled = true;
|
||||
};
|
||||
};
|
||||
proxy = {
|
||||
user_oidc_claim = "preferred_username";
|
||||
user_cs3_claim = "username";
|
||||
};
|
||||
}
|
||||
'';
|
||||
description = lib.mdDoc ''
|
||||
OCIS configuration. Refer to
|
||||
<https://doc.owncloud.com/ocis/next/deployment/services/services.html>
|
||||
for details on supported values.
|
||||
'';
|
||||
};
|
||||
};
|
||||
config = mkIf cfg.enable {
|
||||
systemd.tmpfiles.rules = [
|
||||
"d '${cfg.configDir}' - ocis ocis - -"
|
||||
"d '${cfg.baseDataPath}' - ocis ocis - -"
|
||||
];
|
||||
systemd.services.ocis-init = rec {
|
||||
before = [ "ocis-server.service" ];
|
||||
requiredBy = [ "ocis-server.service" ];
|
||||
path = [ cfg.package ];
|
||||
environment = {
|
||||
OCIS_CONFIG_DIR = cfg.configDir;
|
||||
OCIS_BASE_DATA_PATH = cfg.baseDataPath;
|
||||
} // cfg.environment;
|
||||
script = ''
|
||||
${lib.optionalString (cfg.settings != { }) "${linkConfigs environment.OCIS_CONFIG_DIR}"}
|
||||
if [ ! -f "$OCIS_CONFIG_DIR/ocis.yaml" ]; then
|
||||
${
|
||||
lib.optionalString (cfg.adminpassFile != null) ''
|
||||
if [ ! -r "${cfg.adminpassFile}" ]; then
|
||||
echo "adminpassFile ${cfg.adminpassFile} is not readable by ocis:ocis! Aborting..."
|
||||
exit 1
|
||||
fi
|
||||
if [ -z "$(<${cfg.adminpassFile})" ]; then
|
||||
echo "adminpassFile ${cfg.adminpassFile} is empty!"
|
||||
exit 1
|
||||
fi
|
||||
${mkExport adminpass}
|
||||
''
|
||||
}
|
||||
ocis init
|
||||
fi
|
||||
'';
|
||||
serviceConfig = {
|
||||
Type = "simple";
|
||||
StateDirectory = "ocis";
|
||||
User = "ocis";
|
||||
Group = "ocis";
|
||||
} // optionalAttrs (cfg.environmentFile != null) {
|
||||
EnvironmentFile = cfg.environmentFile;
|
||||
};
|
||||
};
|
||||
|
||||
systemd.services.ocis-server = {
|
||||
description = "ownCloud Infinite Scale Stack";
|
||||
wantedBy = [ "multi-user.target" ];
|
||||
path = [ cfg.package ];
|
||||
environment = {
|
||||
OCIS_CONFIG_DIR = cfg.configDir;
|
||||
OCIS_BASE_DATA_PATH = cfg.baseDataPath;
|
||||
OCIS_URL = "https://localhost:9200";
|
||||
PROXY_HTTP_ADDR = "127.0.0.1:9200";
|
||||
} // cfg.environment;
|
||||
serviceConfig = {
|
||||
Type = "simple";
|
||||
Restart = "always";
|
||||
ExecStart = "${cfg.package}/bin/ocis server";
|
||||
User = "ocis";
|
||||
Group = "ocis";
|
||||
LimitNOFILE = 65536;
|
||||
} // optionalAttrs (cfg.environmentFile != null) {
|
||||
EnvironmentFile = cfg.environmentFile;
|
||||
};
|
||||
};
|
||||
|
||||
environment.systemPackages = [ cfg.package ];
|
||||
|
||||
users.groups.ocis = { };
|
||||
users.users.ocis = {
|
||||
description = "Ocis Daemon User";
|
||||
group = "ocis";
|
||||
isSystemUser = true;
|
||||
};
|
||||
};
|
||||
}
|
@ -19,6 +19,7 @@ with lib;
|
||||
}));
|
||||
default = { };
|
||||
};
|
||||
imports = [ inputs.ataraxiasjel-nur.nixosModules.rustic ];
|
||||
config = mkIf (config.backups.postgresql != { }) {
|
||||
sops.secrets.rclone-postgresql-backups.sopsFile = inputs.self.secretsDir + /rustic.yaml;
|
||||
sops.secrets.rustic-postgresql-pass.sopsFile = inputs.self.secretsDir + /rustic.yaml;
|
||||
|
@ -1,324 +0,0 @@
|
||||
{ config, lib, pkgs, utils, ... }:
|
||||
|
||||
with lib;
|
||||
|
||||
let
|
||||
# Type for a valid systemd unit option. Needed for correctly passing "timerConfig" to "systemd.timers"
|
||||
inherit (utils.systemdUtils.unitOptions) unitOption;
|
||||
settingsFormat = pkgs.formats.toml {};
|
||||
in
|
||||
{
|
||||
options.services.rustic.backups = mkOption {
|
||||
description = lib.mdDoc ''
|
||||
Periodic backups to create with Rustic.
|
||||
'';
|
||||
type = types.attrsOf (types.submodule ({ config, name, ... }: {
|
||||
options = {
|
||||
settings = mkOption {
|
||||
type = settingsFormat.type;
|
||||
default = {};
|
||||
description = lib.mdDoc ''
|
||||
'';
|
||||
};
|
||||
|
||||
environmentFile = mkOption {
|
||||
type = with types; nullOr str;
|
||||
default = null;
|
||||
description = lib.mdDoc ''
|
||||
file containing the credentials to access the repository, in the
|
||||
format of an EnvironmentFile as described by systemd.exec(5)
|
||||
'';
|
||||
};
|
||||
|
||||
extraEnvironment = lib.mkOption {
|
||||
type = lib.types.attrsOf lib.types.str;
|
||||
default = { };
|
||||
example = lib.literalExpression ''
|
||||
{
|
||||
http_proxy = "http://server:12345";
|
||||
}
|
||||
'';
|
||||
description = lib.mdDoc "Environment variables to pass to rustic.";
|
||||
};
|
||||
|
||||
rcloneOptions = mkOption {
|
||||
type = with types; nullOr (attrsOf (oneOf [ str bool ]));
|
||||
default = null;
|
||||
description = lib.mdDoc ''
|
||||
Options to pass to rclone to control its behavior.
|
||||
See <https://rclone.org/docs/#options> for
|
||||
available options. When specifying option names, strip the
|
||||
leading `--`. To set a flag such as
|
||||
`--drive-use-trash`, which does not take a value,
|
||||
set the value to the Boolean `true`.
|
||||
'';
|
||||
example = {
|
||||
bwlimit = "10M";
|
||||
drive-use-trash = "true";
|
||||
};
|
||||
};
|
||||
|
||||
rcloneConfigFile = mkOption {
|
||||
type = with types; nullOr path;
|
||||
default = null;
|
||||
description = lib.mdDoc ''
|
||||
Path to the file containing rclone configuration. This file
|
||||
must contain configuration for the remote specified in this backup
|
||||
set and also must be readable by root. Options set in
|
||||
`rcloneConfig` will override those set in this
|
||||
file.
|
||||
'';
|
||||
};
|
||||
|
||||
timerConfig = mkOption {
|
||||
type = types.attrsOf unitOption;
|
||||
default = {
|
||||
OnCalendar = "daily";
|
||||
Persistent = true;
|
||||
};
|
||||
description = lib.mdDoc ''
|
||||
When to run the backup. See {manpage}`systemd.timer(5)` for details.
|
||||
'';
|
||||
example = {
|
||||
OnCalendar = "00:05";
|
||||
RandomizedDelaySec = "5h";
|
||||
Persistent = true;
|
||||
};
|
||||
};
|
||||
|
||||
user = mkOption {
|
||||
type = types.str;
|
||||
default = "root";
|
||||
description = lib.mdDoc ''
|
||||
As which user the backup should run.
|
||||
'';
|
||||
example = "postgresql";
|
||||
};
|
||||
|
||||
extraBackupArgs = mkOption {
|
||||
type = types.listOf types.str;
|
||||
default = [ ];
|
||||
description = lib.mdDoc ''
|
||||
Extra arguments passed to rustic backup.
|
||||
'';
|
||||
example = [
|
||||
"--exclude-file=/etc/nixos/rustic-ignore"
|
||||
];
|
||||
};
|
||||
|
||||
extraOptions = mkOption {
|
||||
type = types.listOf types.str;
|
||||
default = [ ];
|
||||
description = lib.mdDoc ''
|
||||
Extra extended options to be passed to the rustic --option flag.
|
||||
'';
|
||||
example = [
|
||||
"sftp.command='ssh backup@192.168.1.100 -i /home/user/.ssh/id_rsa -s sftp'"
|
||||
];
|
||||
};
|
||||
|
||||
backup = mkOption {
|
||||
type = types.bool;
|
||||
default = true;
|
||||
description = lib.mdDoc ''
|
||||
Start backup.
|
||||
'';
|
||||
};
|
||||
|
||||
prune = mkOption {
|
||||
type = types.bool;
|
||||
default = true;
|
||||
description = lib.mdDoc ''
|
||||
Start prune.
|
||||
'';
|
||||
};
|
||||
|
||||
initialize = mkOption {
|
||||
type = types.bool;
|
||||
default = false;
|
||||
description = lib.mdDoc ''
|
||||
Create the repository if it doesn't exist.
|
||||
'';
|
||||
};
|
||||
|
||||
initializeOpts = mkOption {
|
||||
type = types.listOf types.str;
|
||||
default = [ ];
|
||||
description = lib.mdDoc ''
|
||||
A list of options for 'rustic init'.
|
||||
'';
|
||||
example = [
|
||||
"--set-version 2"
|
||||
];
|
||||
};
|
||||
|
||||
checkOpts = mkOption {
|
||||
type = types.listOf types.str;
|
||||
default = [ ];
|
||||
description = lib.mdDoc ''
|
||||
A list of options for 'rustic check', which is run after
|
||||
pruning.
|
||||
'';
|
||||
example = [
|
||||
"--with-cache"
|
||||
];
|
||||
};
|
||||
|
||||
pruneOpts = mkOption {
|
||||
type = types.listOf types.str;
|
||||
default = [ ];
|
||||
description = lib.mdDoc ''
|
||||
A list of options for 'rustic prune', which is run before
|
||||
pruning.
|
||||
'';
|
||||
example = [
|
||||
"--repack-cacheable-only=false"
|
||||
];
|
||||
};
|
||||
|
||||
backupCommandPrefix = mkOption {
|
||||
type = types.str;
|
||||
default = "";
|
||||
description = lib.mdDoc ''
|
||||
Prefix for backup command.
|
||||
'';
|
||||
};
|
||||
|
||||
backupCommandSuffix = mkOption {
|
||||
type = types.str;
|
||||
default = "";
|
||||
description = lib.mdDoc ''
|
||||
Suffix for backup command.
|
||||
'';
|
||||
};
|
||||
|
||||
backupPrepareCommand = mkOption {
|
||||
type = with types; nullOr str;
|
||||
default = null;
|
||||
description = lib.mdDoc ''
|
||||
A script that must run before starting the backup process.
|
||||
'';
|
||||
};
|
||||
|
||||
backupCleanupCommand = mkOption {
|
||||
type = with types; nullOr str;
|
||||
default = null;
|
||||
description = lib.mdDoc ''
|
||||
A script that must run after finishing the backup process.
|
||||
'';
|
||||
};
|
||||
|
||||
package = mkOption {
|
||||
type = types.package;
|
||||
default = pkgs.rustic-rs;
|
||||
defaultText = literalExpression "pkgs.rustic-rs";
|
||||
description = lib.mdDoc ''
|
||||
Rustic package to use.
|
||||
'';
|
||||
};
|
||||
|
||||
createWrapper = lib.mkOption {
|
||||
type = lib.types.bool;
|
||||
default = true;
|
||||
description = ''
|
||||
Whether to generate and add a script to the system path, that has the same environment variables set
|
||||
as the systemd service. This can be used to e.g. mount snapshots or perform other opterations, without
|
||||
having to manually specify most options.
|
||||
'';
|
||||
};
|
||||
};
|
||||
}));
|
||||
default = { };
|
||||
};
|
||||
|
||||
config = {
|
||||
systemd.services =
|
||||
mapAttrs'
|
||||
(name: backup:
|
||||
let
|
||||
profile = settingsFormat.generate "${name}.toml" backup.settings;
|
||||
extraOptions = concatMapStrings (arg: " -o ${arg}") backup.extraOptions;
|
||||
rusticCmd = "${backup.package}/bin/rustic -P ${lib.strings.removeSuffix ".toml" profile}${extraOptions}";
|
||||
# Helper functions for rclone remotes
|
||||
rcloneAttrToOpt = v: "RCLONE_" + toUpper (builtins.replaceStrings [ "-" ] [ "_" ] v);
|
||||
toRcloneVal = v: if lib.isBool v then lib.boolToString v else v;
|
||||
in
|
||||
nameValuePair "rustic-backups-${name}" ({
|
||||
environment = backup.extraEnvironment // {
|
||||
# not %C, because that wouldn't work in the wrapper script
|
||||
RUSTIC_CACHE_DIR = "/var/cache/rustic-backups-${name}";
|
||||
} // optionalAttrs (backup.rcloneConfigFile != null) {
|
||||
RCLONE_CONFIG = backup.rcloneConfigFile;
|
||||
} // optionalAttrs (backup.rcloneOptions != null) (mapAttrs'
|
||||
(name: value:
|
||||
nameValuePair (rcloneAttrToOpt name) (toRcloneVal value)
|
||||
)
|
||||
backup.rcloneOptions);
|
||||
path = [ config.programs.ssh.package pkgs.rclone ];
|
||||
restartIfChanged = false;
|
||||
wants = [ "network-online.target" ];
|
||||
after = [ "network-online.target" ];
|
||||
script = ''
|
||||
${optionalString (backup.backup) ''
|
||||
${backup.backupCommandPrefix} ${rusticCmd} backup ${concatStringsSep " " backup.extraBackupArgs} ${backup.backupCommandSuffix}
|
||||
''}
|
||||
${optionalString (backup.prune) ''
|
||||
${rusticCmd} forget --prune ${concatStringsSep " " backup.pruneOpts}
|
||||
${rusticCmd} check ${concatStringsSep " " backup.checkOpts}
|
||||
''}
|
||||
'';
|
||||
serviceConfig = {
|
||||
Type = "oneshot";
|
||||
User = backup.user;
|
||||
RuntimeDirectory = "rustic-backups-${name}";
|
||||
CacheDirectory = "rustic-backups-${name}";
|
||||
CacheDirectoryMode = "0700";
|
||||
PrivateTmp = true;
|
||||
} // optionalAttrs (backup.environmentFile != null) {
|
||||
EnvironmentFile = backup.environmentFile;
|
||||
};
|
||||
} // optionalAttrs (backup.initialize || backup.backupPrepareCommand != null) {
|
||||
preStart = ''
|
||||
${optionalString (backup.backupPrepareCommand != null) ''
|
||||
${pkgs.writeScript "backupPrepareCommand" backup.backupPrepareCommand}
|
||||
''}
|
||||
${optionalString (backup.initialize) ''
|
||||
${rusticCmd} init ${concatStringsSep " " backup.initializeOpts} || true
|
||||
''}
|
||||
'';
|
||||
} // optionalAttrs (backup.backupCleanupCommand != null) {
|
||||
postStop = ''
|
||||
${optionalString (backup.backupCleanupCommand != null) ''
|
||||
${pkgs.writeScript "backupCleanupCommand" backup.backupCleanupCommand}
|
||||
''}
|
||||
'';
|
||||
})
|
||||
)
|
||||
config.services.rustic.backups;
|
||||
systemd.timers =
|
||||
mapAttrs'
|
||||
(name: backup: nameValuePair "rustic-backups-${name}" {
|
||||
wantedBy = [ "timers.target" ];
|
||||
timerConfig = backup.timerConfig;
|
||||
})
|
||||
config.services.rustic.backups;
|
||||
|
||||
# generate wrapper scripts, as described in the createWrapper option
|
||||
environment.systemPackages = lib.mapAttrsToList (name: backup: let
|
||||
profile = settingsFormat.generate "${name}.toml" backup.settings;
|
||||
extraOptions = concatMapStrings (arg: " -o ${arg}") backup.extraOptions;
|
||||
rusticCmd = "${backup.package}/bin/rustic -P ${lib.strings.removeSuffix ".toml" profile}${extraOptions}";
|
||||
in pkgs.writeShellScriptBin "rustic-${name}" ''
|
||||
set -a # automatically export variables
|
||||
${lib.optionalString (backup.environmentFile != null) "source ${backup.environmentFile}"}
|
||||
# set same environment variables as the systemd service
|
||||
${lib.pipe config.systemd.services."rustic-backups-${name}".environment [
|
||||
(lib.filterAttrs (_: v: v != null))
|
||||
(lib.mapAttrsToList (n: v: "${n}=${v}"))
|
||||
(lib.concatStringsSep "\n")
|
||||
]}
|
||||
|
||||
exec ${rusticCmd} $@
|
||||
'') (lib.filterAttrs (_: v: v.createWrapper) config.services.rustic.backups);
|
||||
};
|
||||
}
|
@ -1,4 +1,6 @@
|
||||
{ config, inputs, ... }: {
|
||||
imports = [ inputs.ataraxiasjel-nur.nixosModules.authentik ];
|
||||
|
||||
sops.secrets.authentik-env.sopsFile = inputs.self.secretsDir + /home-hypervisor/authentik.yaml;
|
||||
sops.secrets.authentik-ldap.sopsFile = inputs.self.secretsDir + /home-hypervisor/authentik.yaml;
|
||||
sops.secrets.authentik-env.restartUnits = [ "authentik-server.service" "authentik-worker.service" ];
|
||||
|
@ -13,6 +13,8 @@ let
|
||||
restartUnits = [ "kes.service" ];
|
||||
};
|
||||
in {
|
||||
imports = [ inputs.ataraxiasjel-nur.nixosModules.kes ];
|
||||
|
||||
sops.secrets.minio-credentials = minio-secret;
|
||||
sops.secrets.kes-vault-env = kes-secret;
|
||||
sops.secrets.kes-key = kes-secret;
|
||||
|
@ -5,6 +5,8 @@
|
||||
sopsFile = inputs.self.secretsDir + /home-hypervisor/ocis.yaml;
|
||||
restartUnits = [ "ocis-server.service" ];
|
||||
};
|
||||
imports = [ inputs.ataraxiasjel-nur.nixosModules.ocis ];
|
||||
|
||||
services.ocis = {
|
||||
enable = true;
|
||||
configDir = "/var/lib/ocis";
|
||||
|
Loading…
x
Reference in New Issue
Block a user