style: reformat with nixfmt-rfc-style

This commit is contained in:
Felix Schröter 2024-05-26 16:45:38 +02:00
parent 5ad8bc1d56
commit 1c5d83d81e
Signed by: felschr
GPG key ID: 671E39E6744C807D
99 changed files with 2247 additions and 1334 deletions

View file

@ -1,4 +1,9 @@
{ config, pkgs, lib, ... }:
{
config,
pkgs,
lib,
...
}:
let
domain = "auth.felschr.com";
@ -8,48 +13,56 @@ let
redis = config.services.redis.servers.authelia;
cfg = config.services.authelia.instances.main;
mkWebfinger = config: file:
pkgs.writeTextDir file (lib.generators.toJSON { } config);
mkWebfingers = { subject, ... }@config:
map (mkWebfinger config) [ subject (lib.escapeURL subject) ];
mkWebfinger = config: file: pkgs.writeTextDir file (lib.generators.toJSON { } config);
mkWebfingers =
{ subject, ... }@config:
map (mkWebfinger config) [
subject
(lib.escapeURL subject)
];
webfingerRoot = pkgs.symlinkJoin {
name = "felschr.com-webfinger";
paths = lib.flatten (builtins.map mkWebfingers [
{
subject = "acct:me@felschr.com";
links = [{
rel = "http://openid.net/specs/connect/1.0/issuer";
href = "https://auth.felschr.com";
}];
}
{
subject = "acct:felschr@fosstodon.org";
aliases = [
"https://fosstodon.org/@felschr"
"https://fosstodon.org/users/felschr"
];
links = [
{
rel = "http://webfinger.net/rel/profile-page";
type = "text/html";
href = "https://fosstodon.org/@felschr";
}
{
rel = "self";
type = "application/activity+json";
href = "https://fosstodon.org/users/felschr";
}
{
rel = "http://ostatus.org/schema/1.0/subscribe";
template = "https://fosstodon.org/authorize_interaction?uri={uri}";
}
];
}
]);
paths = lib.flatten (
builtins.map mkWebfingers [
{
subject = "acct:me@felschr.com";
links = [
{
rel = "http://openid.net/specs/connect/1.0/issuer";
href = "https://auth.felschr.com";
}
];
}
{
subject = "acct:felschr@fosstodon.org";
aliases = [
"https://fosstodon.org/@felschr"
"https://fosstodon.org/users/felschr"
];
links = [
{
rel = "http://webfinger.net/rel/profile-page";
type = "text/html";
href = "https://fosstodon.org/@felschr";
}
{
rel = "self";
type = "application/activity+json";
href = "https://fosstodon.org/users/felschr";
}
{
rel = "http://ostatus.org/schema/1.0/subscribe";
template = "https://fosstodon.org/authorize_interaction?uri={uri}";
}
];
}
]
);
};
smtpAccount = config.programs.msmtp.accounts.default;
in {
in
{
age.secrets.authelia-jwt = {
file = ../secrets/authelia/jwt.age;
owner = cfg.user;
@ -81,8 +94,7 @@ in {
oidcIssuerPrivateKeyFile = config.age.secrets.authelia-oidc-issuer.path;
};
environmentVariables = {
AUTHELIA_AUTHENTICATION_BACKEND_LDAP_PASSWORD_FILE =
config.age.secrets.lldap-password.path;
AUTHELIA_AUTHENTICATION_BACKEND_LDAP_PASSWORD_FILE = config.age.secrets.lldap-password.path;
AUTHELIA_NOTIFIER_SMTP_PASSWORD_FILE = config.age.secrets.smtp.path;
};
settings = {
@ -105,8 +117,7 @@ in {
base_dn = "dc=felschr,dc=com";
username_attribute = "uid";
additional_users_dn = "ou=people";
users_filter =
"(&({username_attribute}={input})(objectClass=person))";
users_filter = "(&({username_attribute}={input})(objectClass=person))";
additional_groups_dn = "ou=groups";
groups_filter = "(member={dn})";
group_name_attribute = "cn";
@ -117,10 +128,12 @@ in {
};
access_control = {
default_policy = "deny";
rules = [{
domain = [ "*.felschr.com" ];
policy = "two_factor";
}];
rules = [
{
domain = [ "*.felschr.com" ];
policy = "two_factor";
}
];
};
session = {
domain = "felschr.com";
@ -152,43 +165,59 @@ in {
{
id = "miniflux";
description = "Miniflux RSS";
secret =
"$pbkdf2-sha512$310000$uDoutefLT0wyfye.kBEyZw$tX7nwcRVo0LpPPS63Oh9MIeOLkdPRnXX/0JBwMd.aitFIxKDxU.rlywn/WqLVgpIllyFttMl5OnZzjMTbGKZ0A";
secret = "$pbkdf2-sha512$310000$uDoutefLT0wyfye.kBEyZw$tX7nwcRVo0LpPPS63Oh9MIeOLkdPRnXX/0JBwMd.aitFIxKDxU.rlywn/WqLVgpIllyFttMl5OnZzjMTbGKZ0A";
redirect_uris = [ "https://news.felschr.com/oauth2/oidc/callback" ];
scopes = [ "openid" "email" "profile" ];
scopes = [
"openid"
"email"
"profile"
];
}
{
id = "tailscale";
description = "Tailscale";
# The digest of "insecure_secret"
secret =
"$pbkdf2-sha512$310000$c8p78n7pUMln0jzvd4aK4Q$JNRBzwAo0ek5qKn50cFzzvE9RXV88h1wJn5KGiHrD0YKtZaR/nCb2CJPOsKaPK0hjf.9yHxzQGZziziccp6Yng";
secret = "$pbkdf2-sha512$310000$c8p78n7pUMln0jzvd4aK4Q$JNRBzwAo0ek5qKn50cFzzvE9RXV88h1wJn5KGiHrD0YKtZaR/nCb2CJPOsKaPK0hjf.9yHxzQGZziziccp6Yng";
redirect_uris = [ "https://login.tailscale.com/a/oauth_response" ];
scopes = [ "openid" "email" "profile" ];
scopes = [
"openid"
"email"
"profile"
];
}
{
id = "jellyfin";
description = "Jellyfin";
secret =
"$pbkdf2-sha512$310000$X7amOzLsURvZSwdLmSstlQ$/WK4lZ9KvEEuotOxUJkeTo0ZAa.rD7VVdkAPFcUQmr2WzkCXmXXJbYYy7vx0hc4nqLgBVeo8q/71R3rvfl9BFQ";
redirect_uris =
[ "https://media.felschr.com/sso/OID/redirect/Authelia" ];
scopes = [ "openid" "email" "profile" ];
secret = "$pbkdf2-sha512$310000$X7amOzLsURvZSwdLmSstlQ$/WK4lZ9KvEEuotOxUJkeTo0ZAa.rD7VVdkAPFcUQmr2WzkCXmXXJbYYy7vx0hc4nqLgBVeo8q/71R3rvfl9BFQ";
redirect_uris = [ "https://media.felschr.com/sso/OID/redirect/Authelia" ];
scopes = [
"openid"
"email"
"profile"
];
}
];
};
};
systemd.services.authelia.requires = [ "postgresql.service" "lldap.service" ];
systemd.services.authelia.after = [ "postgresql.service" "lldap.service" ];
systemd.services.authelia.requires = [
"postgresql.service"
"lldap.service"
];
systemd.services.authelia.after = [
"postgresql.service"
"lldap.service"
];
services.postgresql = {
enable = true;
ensureDatabases = [ cfg.user ];
ensureUsers = [{
name = cfg.user;
ensureDBOwnership = true;
}];
ensureUsers = [
{
name = cfg.user;
ensureDBOwnership = true;
}
];
};
services.redis.servers.authelia = {
@ -220,5 +249,8 @@ in {
};
};
users.users.${cfg.user}.extraGroups = [ "smtp" "ldap" ];
users.users.${cfg.user}.extraGroups = [
"smtp"
"ldap"
];
}

View file

@ -1,7 +1,9 @@
{ config, pkgs, ... }:
let port = 8088;
in {
let
port = 8088;
in
{
age.secrets.calibre-web-htpasswd = {
file = ../secrets/calibre-web/htpasswd.age;
owner = config.services.nginx.user;

View file

@ -3,20 +3,21 @@
let
inherit (config.users.users.collabora-office) uid;
inherit (config.users.groups.collabora-office) gid;
in {
in
{
virtualisation.oci-containers.containers.collabora-office = {
image = "docker.io/collabora/code";
ports = [ "9980:9980" ];
environment = let
mkAlias = domain:
"https://" + (builtins.replaceStrings [ "." ] [ "\\." ] domain)
+ ":443";
in {
server_name = "office.felschr.com";
aliasgroup1 = mkAlias "office.felschr.com";
aliasgroup2 = mkAlias "cloud.felschr.com";
extra_params = "--o:ssl.enable=false --o:ssl.termination=true";
};
environment =
let
mkAlias = domain: "https://" + (builtins.replaceStrings [ "." ] [ "\\." ] domain) + ":443";
in
{
server_name = "office.felschr.com";
aliasgroup1 = mkAlias "office.felschr.com";
aliasgroup2 = mkAlias "cloud.felschr.com";
extra_params = "--o:ssl.enable=false --o:ssl.termination=true";
};
extraOptions = [
"--runtime=crun"
"--uidmap=0:65534:1"
@ -50,5 +51,7 @@ in {
uid = 982;
};
users.groups.collabora-office = { gid = 982; };
users.groups.collabora-office = {
gid = 982;
};
}

View file

@ -1,7 +1,9 @@
{ config, pkgs, ... }:
let etebaseHost = "etebase.felschr.com";
in {
let
etebaseHost = "etebase.felschr.com";
in
{
# TODO etebase-server doesn't support newer django version yet
nixpkgs.config.permittedInsecurePackages = [ "python3.11-django-3.2.25" ];
@ -14,8 +16,12 @@ in {
services.etebase-server.enable = true;
services.etebase-server.openFirewall = true;
services.etebase-server.settings = {
global = { secret_file = config.age.secrets.etebase-server.path; };
allowed_hosts = { allowed_host1 = etebaseHost; };
global = {
secret_file = config.age.secrets.etebase-server.path;
};
allowed_hosts = {
allowed_host1 = etebaseHost;
};
};
services.nginx = {

View file

@ -1,7 +1,14 @@
{ config, pkgs, inputs, ... }:
{
config,
pkgs,
inputs,
...
}:
let port = config.services.home-assistant.config.http.server_port;
in {
let
port = config.services.home-assistant.config.http.server_port;
in
{
disabledModules = [ "services/home-automation/home-assistant.nix" ];
imports = [
@ -29,8 +36,9 @@ in {
services.home-assistant = {
enable = true;
package = pkgs.unstable.home-assistant.overrideAttrs
(oldAttrs: { doInstallCheck = false; });
package = pkgs.unstable.home-assistant.overrideAttrs (oldAttrs: {
doInstallCheck = false;
});
openFirewall = true;
extraComponents = [
"default_config"
@ -53,8 +61,8 @@ in {
"local_todo"
"shopping_list"
];
extraPackages = ps:
with ps; [
extraPackages =
ps: with ps; [
pyqrcode
# HACS
@ -72,7 +80,10 @@ in {
external_url = "https://home.felschr.com";
internal_url = "http://192.168.1.102:8123";
media_dirs.media = "/media";
allowlist_external_dirs = [ "/tmp" "/media" ];
allowlist_external_dirs = [
"/tmp"
"/media"
];
};
default_config = { };
http = {
@ -86,8 +97,7 @@ in {
zha = {
database_path = "/var/lib/hass/zigbee.db";
enable_quirks = true;
custom_quirks_path =
"${config.services.home-assistant.configDir}/zha_quirks/";
custom_quirks_path = "${config.services.home-assistant.configDir}/zha_quirks/";
zigpy_config.ota = {
ikea_provider = true;
sonoff_provider = true;
@ -95,7 +105,9 @@ in {
};
};
zha_toolkit = { };
conversation = { intents = { }; };
conversation = {
intents = { };
};
};
# configWritable = true; # doesn't work atm
};

View file

@ -6,7 +6,8 @@ let
port = 6052;
inherit (config.services.home-assistant) configDir;
passwordFile = config.age.secrets.esphome-password.path;
in {
in
{
age.secrets.esphome-password.file = ../../secrets/esphome/password.age;
services.nginx = {

View file

@ -27,6 +27,5 @@
};
# needs access to /proc/cpuinfo
systemd.services."wyoming-faster-whisper-en".serviceConfig.ProcSubset =
lib.mkForce "all";
systemd.services."wyoming-faster-whisper-en".serviceConfig.ProcSubset = lib.mkForce "all";
}

View file

@ -50,7 +50,8 @@ let
"--label=io.containers.autoupdate=registry"
];
};
in {
in
{
age.secrets.immich-env.file = ../secrets/immich/.env.age;
age.secrets.immich-db-password.file = ../secrets/immich/db-password.age;
age.secrets.immich-typesense-env.file = ../secrets/immich/typesense/.env.age;
@ -59,10 +60,12 @@ in {
enable = true;
enableTCPIP = true;
ensureDatabases = [ dbname ];
ensureUsers = [{
name = dbuser;
ensureDBOwnership = true;
}];
ensureUsers = [
{
name = dbuser;
ensureDBOwnership = true;
}
];
};
services.redis.servers.immich = {
@ -134,13 +137,25 @@ in {
systemd.services = {
"${ociBackend}-immich-server" = {
requires = [ "postgresql.service" "redis-immich.service" ];
after = [ "postgresql.service" "redis-immich.service" ];
requires = [
"postgresql.service"
"redis-immich.service"
];
after = [
"postgresql.service"
"redis-immich.service"
];
};
"${ociBackend}-immich-microservices" = {
requires = [ "postgresql.service" "redis-immich.service" ];
after = [ "postgresql.service" "redis-immich.service" ];
requires = [
"postgresql.service"
"redis-immich.service"
];
after = [
"postgresql.service"
"redis-immich.service"
];
};
"${ociBackend}-immich-machine-learning" = {
@ -166,5 +181,7 @@ in {
uid = 980;
};
users.groups.immich = { gid = 977; };
users.groups.immich = {
gid = 977;
};
}

View file

@ -6,14 +6,16 @@
services.jellyfin.openFirewall = true;
# for hardware acceleration
users.users.${config.services.jellyfin.user}.extraGroups =
[ "video" "render" ];
users.users.${config.services.jellyfin.user}.extraGroups = [
"video"
"render"
];
systemd.services.jellyfin.serviceConfig = {
DeviceAllow = lib.mkForce [ "/dev/dri/renderD128" ];
};
services.nginx = {
virtualHosts."media.felschr.com" = {
services.nginx.virtualHosts = {
"media.felschr.com" = {
enableACME = true;
forceSSL = true;
locations."/".proxyPass = "http://localhost:8096";

View file

@ -4,7 +4,8 @@ let
domain = "ldap.felschr.com";
cfg = config.services.lldap;
port = cfg.settings.http_port;
in {
in
{
age.secrets.lldap-key-seed.file = ../secrets/lldap/key-seed.age;
age.secrets.lldap-jwt.file = ../secrets/lldap/jwt.age;
age.secrets.lldap-password = {
@ -34,13 +35,15 @@ in {
];
};
services.nginx = {
virtualHosts.${domain} = {
services.nginx.virtualHosts = {
${domain} = {
enableACME = true;
forceSSL = true;
locations."/".proxyPass = "http://[::1]:${toString port}";
};
};
users.groups.ldap = { gid = 979; };
users.groups.ldap = {
gid = 979;
};
}

View file

@ -25,5 +25,7 @@
};
};
users.groups.smtp = { gid = 983; };
users.groups.smtp = {
gid = 983;
};
}

View file

@ -15,7 +15,8 @@ let
allow_key_sharing = true;
delete_keys.delete_outdated_inbound = false;
};
in {
in
{
# Mautrix-signal settings
services.signald.enable = true;
systemd.services.matrix-as-signal = {

View file

@ -3,14 +3,19 @@
let
server_name = "felschr.com";
domain = "matrix.${server_name}";
in {
in
{
services.matrix-conduit = {
enable = true;
package = pkgs.unstable.matrix-conduit;
settings.global = {
inherit server_name;
database_backend = "rocksdb";
trusted_servers = [ "matrix.org" "libera.chat" "nixos.org" ];
trusted_servers = [
"matrix.org"
"libera.chat"
"nixos.org"
];
};
};
@ -18,9 +23,7 @@ in {
enableACME = true;
forceSSL = true;
locations."/_matrix/" = {
proxyPass = "http://[::1]:${
toString config.services.matrix-conduit.settings.global.port
}";
proxyPass = "http://[::1]:${toString config.services.matrix-conduit.settings.global.port}";
proxyWebsockets = true;
extraConfig = ''
proxy_buffering off;
@ -31,23 +34,27 @@ in {
services.nginx.virtualHosts.${server_name} = {
enableACME = true;
forceSSL = true;
locations = let
server = { "m.server" = "${domain}:443"; };
client = {
"m.homeserver"."base_url" = "https://${domain}";
"org.matrix.msc3575.proxy"."url" = "https://${domain}";
"m.identity_server"."base_url" = "https://vector.im";
locations =
let
server = {
"m.server" = "${domain}:443";
};
client = {
"m.homeserver"."base_url" = "https://${domain}";
"org.matrix.msc3575.proxy"."url" = "https://${domain}";
"m.identity_server"."base_url" = "https://vector.im";
};
in
{
"= /.well-known/matrix/server".extraConfig = ''
add_header Content-Type application/json;
return 200 '${builtins.toJSON server}';
'';
"= /.well-known/matrix/client".extraConfig = ''
add_header Content-Type application/json;
add_header Access-Control-Allow-Origin *;
return 200 '${builtins.toJSON client}';
'';
};
in {
"= /.well-known/matrix/server".extraConfig = ''
add_header Content-Type application/json;
return 200 '${builtins.toJSON server}';
'';
"= /.well-known/matrix/client".extraConfig = ''
add_header Content-Type application/json;
add_header Access-Control-Allow-Origin *;
return 200 '${builtins.toJSON client}';
'';
};
};
}

View file

@ -1,5 +1,9 @@
{ ... }:
{
imports = [ ./conduit.nix ./element.nix ./appservices.nix ];
imports = [
./conduit.nix
./element.nix
./appservices.nix
];
}

View file

@ -9,7 +9,8 @@ let
max_idle_conns = 2;
conn_max_lifetime = -1;
};
in {
in
{
age.secrets.dendrite-private-key = {
file = ../../secrets/dendrite/privateKey.age;
mode = "755";
@ -41,19 +42,21 @@ in {
"msc2946" # space summaries
];
federation_api.key_perspectives = [{
server_name = "matrix.org";
keys = [
{
key_id = "ed25519:auto";
public_key = "Noi6WqcDj0QmPxCNQqgezwTlBKrfqehY1u2FyWP9uYw";
}
{
key_id = "ed25519:a_RXGa";
public_key = "l8Hft5qXKn1vfHrg3p4+W8gELQVo8N13JkluMfmn2sQ";
}
];
}];
federation_api.key_perspectives = [
{
server_name = "matrix.org";
keys = [
{
key_id = "ed25519:auto";
public_key = "Noi6WqcDj0QmPxCNQqgezwTlBKrfqehY1u2FyWP9uYw";
}
{
key_id = "ed25519:a_RXGa";
public_key = "l8Hft5qXKn1vfHrg3p4+W8gELQVo8N13JkluMfmn2sQ";
}
];
}
];
global = {
inherit server_name;
@ -69,10 +72,12 @@ in {
};
services.postgresql = {
ensureUsers = [{
name = "dendrite";
ensureDBOwnership = true;
}];
ensureUsers = [
{
name = "dendrite";
ensureDBOwnership = true;
}
];
ensureDatabases = [ "dendrite" ];
};
@ -82,24 +87,28 @@ in {
${server_name} = {
enableACME = true;
forceSSL = true;
locations = let
server = { "m.server" = "${domain}:443"; };
client = {
"m.homeserver"."base_url" = "https://${domain}";
"org.matrix.msc3575.proxy"."url" = "https://${domain}";
"m.identity_server"."base_url" = "https://vector.im";
locations =
let
server = {
"m.server" = "${domain}:443";
};
client = {
"m.homeserver"."base_url" = "https://${domain}";
"org.matrix.msc3575.proxy"."url" = "https://${domain}";
"m.identity_server"."base_url" = "https://vector.im";
};
in
{
"= /.well-known/matrix/server".extraConfig = ''
add_header Content-Type application/json;
return 200 '${builtins.toJSON server}';
'';
"= /.well-known/matrix/client".extraConfig = ''
add_header Content-Type application/json;
add_header Access-Control-Allow-Origin *;
return 200 '${builtins.toJSON client}';
'';
};
in {
"= /.well-known/matrix/server".extraConfig = ''
add_header Content-Type application/json;
return 200 '${builtins.toJSON server}';
'';
"= /.well-known/matrix/client".extraConfig = ''
add_header Content-Type application/json;
add_header Access-Control-Allow-Origin *;
return 200 '${builtins.toJSON client}';
'';
};
};
"${domain}" = {
enableACME = true;
@ -108,8 +117,7 @@ in {
"/".extraConfig = ''
return 404;
'';
"/_matrix".proxyPass =
"http://127.0.0.1:${toString config.services.dendrite.httpPort}";
"/_matrix".proxyPass = "http://127.0.0.1:${toString config.services.dendrite.httpPort}";
};
};
};

View file

@ -3,7 +3,8 @@
let
inherit (config.services.matrix-conduit.settings.global) server_name;
matrix_host = "matrix.${server_name}";
in {
in
{
services.nginx.virtualHosts."element.felschr.com" = {
forceSSL = true;
enableACME = true;

View file

@ -3,7 +3,8 @@
let
domain = "news.felschr.com";
port = 8002;
in {
in
{
age.secrets.miniflux.file = ../secrets/miniflux/admin.age;
age.secrets.miniflux-oidc = {
file = ../secrets/miniflux/oidc.age;
@ -26,8 +27,7 @@ in {
};
};
systemd.services.miniflux.serviceConfig.SupplementaryGroups =
[ "miniflux-secrets" ];
systemd.services.miniflux.serviceConfig.SupplementaryGroups = [ "miniflux-secrets" ];
services.nginx = {
virtualHosts."news.felschr.com" = {

View file

@ -1,7 +1,9 @@
{ config, pkgs, ... }:
let host = "cloud.felschr.com";
in {
let
host = "cloud.felschr.com";
in
{
age.secrets.nextcloud-admin = {
file = ../secrets/nextcloud/admin.age;
owner = "nextcloud";
@ -31,10 +33,12 @@ in {
services.postgresql = with config.services.nextcloud.config; {
enable = true;
ensureDatabases = [ dbname ];
ensureUsers = [{
name = dbuser;
ensureDBOwnership = true;
}];
ensureUsers = [
{
name = dbuser;
ensureDBOwnership = true;
}
];
};
# ensure that postgres is running *before* running the setup

View file

@ -1,7 +1,9 @@
{ config, pkgs, ... }:
let port = 28981;
in {
let
port = 28981;
in
{
age.secrets.paperless = {
file = ../secrets/paperless.age;
owner = config.services.paperless.user;
@ -28,5 +30,4 @@ in {
};
};
};
}

View file

@ -3,5 +3,8 @@
{
# for reader used with AusweisApp2
services.pcscd.enable = true;
services.pcscd.plugins = with pkgs; [ ccid pcsc-cyberjack ];
services.pcscd.plugins = with pkgs; [
ccid
pcsc-cyberjack
];
}

View file

@ -1,4 +1,9 @@
{ config, pkgs, lib, ... }:
{
config,
pkgs,
lib,
...
}:
{
imports = [ ../../modules/restic.nix ];

View file

@ -1,4 +1,9 @@
{ config, lib, pkgs, ... }:
{
config,
lib,
pkgs,
...
}:
# using the restic cli:
# load credentials into shell by adding B2 secrets to .env (see .env.example).
@ -6,15 +11,21 @@
with lib;
with builtins;
let resticLib = import ./lib.nix { inherit config lib pkgs; };
in {
let
resticLib = import ./lib.nix { inherit config lib pkgs; };
in
{
imports = [ ./common.nix ];
environment.systemPackages = with pkgs; [ restic ];
services.restic.backups.full = resticLib.resticConfig {
name = "home-pc";
paths = [ "/etc/nixos" "/var/lib" "/home" ];
paths = [
"/etc/nixos"
"/var/lib"
"/home"
];
# inspiration: https://github.com/rubo77/rsync-homedir-excludes
ignorePatterns = [
"/var/lib/systemd"

View file

@ -1,4 +1,9 @@
{ config, lib, pkgs, ... }:
{
config,
lib,
pkgs,
...
}:
# using the restic cli:
# load credentials into shell by adding B2 secrets to .env (see .env.example).
@ -6,15 +11,21 @@
with lib;
with builtins;
let resticLib = import ./lib.nix { inherit config lib pkgs; };
in {
let
resticLib = import ./lib.nix { inherit config lib pkgs; };
in
{
imports = [ ./common.nix ];
environment.systemPackages = with pkgs; [ restic ];
services.restic.backups.full = resticLib.resticConfig {
name = "home-server";
paths = [ "/etc/nixos" "/var/lib" "/home" ];
paths = [
"/etc/nixos"
"/var/lib"
"/home"
];
ignorePatterns = [
"/var/lib/systemd"
"/var/lib/containers"

View file

@ -1,4 +1,9 @@
{ config, lib, pkgs, ... }:
{
config,
lib,
pkgs,
...
}:
# using the restic cli:
# load credentials into shell by adding B2 secrets to .env (see .env.example).
@ -6,17 +11,27 @@
with lib;
with builtins;
let hasAnyAttr = flip (attrset: any (flip hasAttr attrset));
in {
resticConfig = args@{ name, paths ? [ ], ignorePatterns ? [ ]
, extraBackupArgs ? [ ], extraPruneOpts ? [ ], ... }:
assert !hasAnyAttr [
"initialize"
"repository"
"s3CredentialsFile"
"passwordFile"
"pruneOpts"
] args;
let
hasAnyAttr = flip (attrset: any (flip hasAttr attrset));
in
{
resticConfig =
args@{
name,
paths ? [ ],
ignorePatterns ? [ ],
extraBackupArgs ? [ ],
extraPruneOpts ? [ ],
...
}:
assert
!hasAnyAttr [
"initialize"
"repository"
"s3CredentialsFile"
"passwordFile"
"pruneOpts"
] args;
assert (args ? paths);
{
initialize = true;
@ -25,10 +40,11 @@ in {
passwordFile = config.age.secrets.restic-password.path;
timerConfig.OnCalendar = "daily";
inherit paths;
extraBackupArgs = let
ignoreFile = builtins.toFile "ignore"
(foldl (a: b: a + "\n" + b) "" ignorePatterns);
in [ "--exclude-file=${ignoreFile}" ] ++ extraBackupArgs;
extraBackupArgs =
let
ignoreFile = builtins.toFile "ignore" (foldl (a: b: a + "\n" + b) "" ignorePatterns);
in
[ "--exclude-file=${ignoreFile}" ] ++ extraBackupArgs;
pruneOpts = [
"--keep-daily 7"
"--keep-weekly 4"
@ -38,7 +54,8 @@ in {
"--max-unused 10%"
"--repack-cacheable-only"
] ++ extraPruneOpts;
} // (removeAttrs args [
}
// (removeAttrs args [
"name"
"paths"
"ignorePatterns"

View file

@ -1,4 +1,9 @@
{ config, lib, pkgs, ... }:
{
config,
lib,
pkgs,
...
}:
{
age.secrets.samba.file = ../../secrets/samba.age;