mirror of
https://github.com/RGBCube/ncc
synced 2025-07-30 11:37:44 +00:00
Set up restic on all hosts
This commit is contained in:
parent
f5da41b495
commit
fefb810d97
15 changed files with 100 additions and 82 deletions
2
.gitignore
vendored
2
.gitignore
vendored
|
@ -10,7 +10,6 @@
|
||||||
!hosts/cube/grafana/
|
!hosts/cube/grafana/
|
||||||
!hosts/cube/matrix/
|
!hosts/cube/matrix/
|
||||||
!hosts/cube/nextcloud/
|
!hosts/cube/nextcloud/
|
||||||
!hosts/cube/restic/
|
|
||||||
|
|
||||||
!hosts/disk/
|
!hosts/disk/
|
||||||
!hosts/disk/mail/
|
!hosts/disk/mail/
|
||||||
|
@ -22,6 +21,7 @@
|
||||||
!modules/
|
!modules/
|
||||||
!modules/hyprland/
|
!modules/hyprland/
|
||||||
!modules/nushell/
|
!modules/nushell/
|
||||||
|
!modules/restic/
|
||||||
!modules/ssh/
|
!modules/ssh/
|
||||||
|
|
||||||
!lib/
|
!lib/
|
||||||
|
|
|
@ -15,6 +15,12 @@
|
||||||
openssh.authorizedKeys.keys = [ keys.enka ];
|
openssh.authorizedKeys.keys = [ keys.enka ];
|
||||||
hashedPasswordFile = config.secrets.rgbPassword.path;
|
hashedPasswordFile = config.secrets.rgbPassword.path;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
backup = normalUser {
|
||||||
|
description = "Backup";
|
||||||
|
openssh.authorizedKeys.keys = keys.all;
|
||||||
|
hashedPasswordFile = config.secrets.rgbPassword.path;
|
||||||
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
services.openssh = {
|
services.openssh = {
|
||||||
|
|
|
@ -24,6 +24,10 @@ in systemConfiguration {
|
||||||
}];
|
}];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
services.restic.backups = genAttrs config.resticHosts (_: {
|
||||||
|
paths = [ "/var/lib/gitea-runner" "/var/lib/forgejo" ];
|
||||||
|
});
|
||||||
|
|
||||||
users.groups.gitea-runner = {};
|
users.groups.gitea-runner = {};
|
||||||
users.users.gitea-runner = systemUser {
|
users.users.gitea-runner = systemUser {
|
||||||
extraGroups = [ "docker" ];
|
extraGroups = [ "docker" ];
|
||||||
|
|
|
@ -24,6 +24,10 @@ in systemConfiguration {
|
||||||
}];
|
}];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
services.restic.backups = genAttrs config.resticHosts (_: {
|
||||||
|
paths = [ "/var/lib/grafana" ];
|
||||||
|
});
|
||||||
|
|
||||||
systemd.services.grafana = {
|
systemd.services.grafana = {
|
||||||
after = [ "postgresql.service" ];
|
after = [ "postgresql.service" ];
|
||||||
requires = [ "postgresql.service" ];
|
requires = [ "postgresql.service" ];
|
||||||
|
|
|
@ -59,6 +59,10 @@ in serverSystemConfiguration {
|
||||||
];
|
];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
services.restic.backups = genAttrs config.resticHosts (_: {
|
||||||
|
paths = [ "/var/lib/matrix-synapse" "/var/lib/matrix-sliding-sync" ];
|
||||||
|
});
|
||||||
|
|
||||||
services.matrix-synapse = enabled {
|
services.matrix-synapse = enabled {
|
||||||
withJemalloc = true;
|
withJemalloc = true;
|
||||||
|
|
||||||
|
|
|
@ -32,6 +32,10 @@ in systemConfiguration {
|
||||||
}];
|
}];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
services.restic.backups = genAttrs config.resticHosts (_: {
|
||||||
|
paths = [ "/var/lib/nextcloud" ];
|
||||||
|
});
|
||||||
|
|
||||||
systemd.services.nextcloud-setup = {
|
systemd.services.nextcloud-setup = {
|
||||||
after = [ "postgresql.service" ];
|
after = [ "postgresql.service" ];
|
||||||
requires = [ "postgresql.service" ];
|
requires = [ "postgresql.service" ];
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
{ lib, pkgs, ... }: with lib; merge
|
{ config, lib, pkgs, ... }: with lib; merge
|
||||||
|
|
||||||
(systemConfiguration {
|
(systemConfiguration {
|
||||||
services.prometheus.exporters.postgres = enabled {
|
services.prometheus.exporters.postgres = enabled {
|
||||||
|
@ -6,6 +6,20 @@
|
||||||
runAsLocalSuperUser = true;
|
runAsLocalSuperUser = true;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
services.restic.backups = genAttrs config.resticHosts (_: {
|
||||||
|
paths = [ "/tmp/postgresql-dump.sql.gz" ];
|
||||||
|
|
||||||
|
backupPrepareCommand = ''
|
||||||
|
${config.services.postgresql.package}/bin/pg_dumpall --clean \
|
||||||
|
| ${lib.getExe pkgs.gzip} --rsyncable \
|
||||||
|
> /tmp/postgresql-dump.sql.gz
|
||||||
|
'';
|
||||||
|
|
||||||
|
backupCleanupCommand = ''
|
||||||
|
rm /tmp/postgresql-dump.sql.gz
|
||||||
|
'';
|
||||||
|
});
|
||||||
|
|
||||||
services.postgresql = enabled {
|
services.postgresql = enabled {
|
||||||
package = pkgs.postgresql_14;
|
package = pkgs.postgresql_14;
|
||||||
|
|
||||||
|
|
|
@ -1,44 +0,0 @@
|
||||||
{ config, lib, pkgs, ... }: with lib;
|
|
||||||
|
|
||||||
systemConfiguration {
|
|
||||||
secrets.resticPassword.file = ./password.age;
|
|
||||||
|
|
||||||
services.restic.backups.disk = {
|
|
||||||
repository = "sftp:backup@disk:${config.networking.hostName}-backup";
|
|
||||||
passwordFile = config.secrets.resticPassword.path;
|
|
||||||
initialize = true;
|
|
||||||
|
|
||||||
pruneOpts = [
|
|
||||||
"--keep-daily unlimited"
|
|
||||||
"--keep-weekly unlimited"
|
|
||||||
"--keep-monthly 6"
|
|
||||||
"--keep-yearly 12"
|
|
||||||
];
|
|
||||||
|
|
||||||
timerConfig = {
|
|
||||||
OnCalendar = "daily";
|
|
||||||
Persistent = true;
|
|
||||||
};
|
|
||||||
|
|
||||||
paths = [
|
|
||||||
"/tmp/postgresql-dump.sql.gz"
|
|
||||||
] ++ map (dir: "/var/lib/${dir}") [
|
|
||||||
"forgejo"
|
|
||||||
"gitea-runner"
|
|
||||||
"grafana"
|
|
||||||
"matrix-sliding-sync"
|
|
||||||
"matrix-synapse"
|
|
||||||
"nextcloud"
|
|
||||||
];
|
|
||||||
|
|
||||||
backupPrepareCommand = ''
|
|
||||||
${config.services.postgresql.package}/bin/pg_dumpall --clean \
|
|
||||||
| ${lib.getExe pkgs.gzip} --rsyncable \
|
|
||||||
> /tmp/postgresql-dump.sql.gz
|
|
||||||
'';
|
|
||||||
|
|
||||||
backupCleanupCommand = ''
|
|
||||||
rm /tmp/postgresql-dump.sql.gz
|
|
||||||
'';
|
|
||||||
};
|
|
||||||
}
|
|
|
@ -1,9 +0,0 @@
|
||||||
age-encryption.org/v1
|
|
||||||
-> ssh-ed25519 +rZ0Tw JhqOkh+PwYHVBthp3sK8ObXpilu/Fn8sDelDyk9ShkI
|
|
||||||
Q93HHN68Sq3g+dvPLi/uw/w6Uzsqi39rPwV8hitl1dM
|
|
||||||
-> ssh-ed25519 CzqbPQ R+z/ARbQuV0B4fZ/f/4Z7LQCofg0VbagNymI2VkRv38
|
|
||||||
/WEmH+UdUQ3u3IACisaYIhJ0u8fiJP/hjPd6UkN5c8k
|
|
||||||
-> ssh-ed25519 f5VzMA FrgY7EJzi5ZtdxA8bIZZG5Q1L7Abrx0wWyVKOGreRgU
|
|
||||||
OWTnpJl9Yt14H9tzLxFxZqksADe4fAESWQ2ebZt/vMg
|
|
||||||
--- jjnpTS1CXY89cYNu90SL5kVJ8ddo7Twabb9TWIyaYMw
|
|
||||||
}©<>,À<>=‹"±T/y¶Ø:߈Œ¾l‡;/°èõ¸[„jÃÐe@¸šÉe²³¬`
|
|
|
@ -18,7 +18,7 @@
|
||||||
|
|
||||||
backup = normalUser {
|
backup = normalUser {
|
||||||
description = "Backup";
|
description = "Backup";
|
||||||
openssh.authorizedKeys.keys = [ keys.cube keys.enka ];
|
openssh.authorizedKeys.keys = keys.all;
|
||||||
hashedPasswordFile = config.secrets.floppyPassword.path;
|
hashedPasswordFile = config.secrets.floppyPassword.path;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
|
@ -13,6 +13,10 @@ in systemConfiguration {
|
||||||
listenAddress = "[::]";
|
listenAddress = "[::]";
|
||||||
};
|
};
|
||||||
|
|
||||||
|
services.restic.backups = genAttrs config.resticHosts (_: {
|
||||||
|
paths = [ config.mailserver.dkimKeyDirectory config.mailserver.mailDirectory ];
|
||||||
|
});
|
||||||
|
|
||||||
mailserver = enabled {
|
mailserver = enabled {
|
||||||
fqdn = mkDefault fqdn;
|
fqdn = mkDefault fqdn;
|
||||||
|
|
||||||
|
|
|
@ -15,6 +15,12 @@
|
||||||
openssh.authorizedKeys.keys = [ keys.enka ];
|
openssh.authorizedKeys.keys = [ keys.enka ];
|
||||||
hashedPasswordFile = config.secrets.sevenPassword.path;
|
hashedPasswordFile = config.secrets.sevenPassword.path;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
backup = normalUser {
|
||||||
|
description = "Backup";
|
||||||
|
openssh.authorizedKeys.keys = keys.all;
|
||||||
|
hashedPasswordFile = config.secrets.sevenPassword.path;
|
||||||
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
services.openssh.hostKeys = [{
|
services.openssh.hostKeys = [{
|
||||||
|
|
7
keys.nix
7
keys.nix
|
@ -1,7 +1,12 @@
|
||||||
{
|
let
|
||||||
|
keys = {
|
||||||
cube = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAINMkCJeHcD0SIOZ4HkyF6rqUmbvlKhSha3HWMZ0hbIjp rgb@cube";
|
cube = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAINMkCJeHcD0SIOZ4HkyF6rqUmbvlKhSha3HWMZ0hbIjp rgb@cube";
|
||||||
disk = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIItpYQ3Pz6zFifKXvFX7xAC8aby9RW/m5PkW8T9SOee4 floppy@disk";
|
disk = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIItpYQ3Pz6zFifKXvFX7xAC8aby9RW/m5PkW8T9SOee4 floppy@disk";
|
||||||
enka = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIBVkWUQ6Z4OK539tore/R5wnueNPPaX532RUAld8UOCo said@enka";
|
enka = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIBVkWUQ6Z4OK539tore/R5wnueNPPaX532RUAld8UOCo said@enka";
|
||||||
pala = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIEXXxaxhkIMy0UyLOOnvwkNjzypS7D9kElHGKw8pZuFb said@pala";
|
pala = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIEXXxaxhkIMy0UyLOOnvwkNjzypS7D9kElHGKw8pZuFb said@pala";
|
||||||
nine = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAILJDqnItmvXZMTSwzbalr+9jzS4kSJm5PWEpI8GOpebF seven@nine";
|
nine = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAILJDqnItmvXZMTSwzbalr+9jzS4kSJm5PWEpI8GOpebF seven@nine";
|
||||||
|
};
|
||||||
|
in keys // {
|
||||||
|
admins = [ keys.enka keys.pala ];
|
||||||
|
all = builtins.attrValues keys;
|
||||||
}
|
}
|
||||||
|
|
27
modules/restic/default.nix
Normal file
27
modules/restic/default.nix
Normal file
|
@ -0,0 +1,27 @@
|
||||||
|
{ config, lib, ... }: with lib;
|
||||||
|
|
||||||
|
serverSystemConfiguration {
|
||||||
|
options.resticHosts = mkConst (remove config.networking.hostName [ "cube" "disk" "nine" ]);
|
||||||
|
|
||||||
|
config = {
|
||||||
|
secrets.resticPassword.file = ./password.age;
|
||||||
|
|
||||||
|
services.restic.backups = genAttrs config.resticHosts (host: {
|
||||||
|
repository = "sftp:backup@${host}:${config.networking.hostName}-backup";
|
||||||
|
passwordFile = config.secrets.resticPassword.path;
|
||||||
|
initialize = true;
|
||||||
|
|
||||||
|
pruneOpts = [
|
||||||
|
"--keep-daily unlimited"
|
||||||
|
"--keep-weekly unlimited"
|
||||||
|
"--keep-monthly 6"
|
||||||
|
"--keep-yearly 12"
|
||||||
|
];
|
||||||
|
|
||||||
|
timerConfig = {
|
||||||
|
OnCalendar = "daily";
|
||||||
|
Persistent = true;
|
||||||
|
};
|
||||||
|
});
|
||||||
|
};
|
||||||
|
}
|
33
secrets.nix
33
secrets.nix
|
@ -1,31 +1,24 @@
|
||||||
let
|
with import ./keys.nix; {
|
||||||
keys = import ./keys.nix;
|
|
||||||
|
|
||||||
all = builtins.attrValues keys;
|
|
||||||
|
|
||||||
admins = with keys; [ enka pala ];
|
|
||||||
withAdmins = key: [ key ] ++ admins;
|
|
||||||
in with keys; {
|
|
||||||
# cube
|
# cube
|
||||||
"hosts/cube/id.age".publicKeys = withAdmins cube;
|
"hosts/cube/id.age".publicKeys = [ cube ] ++ admins;
|
||||||
"hosts/cube/password.rgb.age".publicKeys = withAdmins cube;
|
"hosts/cube/password.rgb.age".publicKeys = [ cube ] ++ admins;
|
||||||
|
|
||||||
"hosts/cube/acme/environment.age".publicKeys = all;
|
"hosts/cube/acme/environment.age".publicKeys = all;
|
||||||
|
|
||||||
"hosts/cube/forgejo/password.runner.age".publicKeys = withAdmins cube;
|
"hosts/cube/forgejo/password.runner.age".publicKeys = [ cube ] ++ admins;
|
||||||
|
|
||||||
"hosts/cube/grafana/password.age".publicKeys = withAdmins cube;
|
"hosts/cube/grafana/password.age".publicKeys = [ cube ] ++ admins;
|
||||||
|
|
||||||
"hosts/cube/matrix/password.secret.age".publicKeys = withAdmins cube;
|
"hosts/cube/matrix/password.secret.age".publicKeys = [ cube ] ++ admins;
|
||||||
"hosts/cube/matrix/password.sync.age".publicKeys = withAdmins cube;
|
"hosts/cube/matrix/password.sync.age".publicKeys = [ cube ] ++ admins;
|
||||||
|
|
||||||
"hosts/cube/nextcloud/password.age".publicKeys = withAdmins cube;
|
"hosts/cube/nextcloud/password.age".publicKeys = [ cube ] ++ admins;
|
||||||
|
|
||||||
"hosts/cube/restic/password.age".publicKeys = withAdmins cube;
|
"hosts/cube/restic/password.age".publicKeys = [ cube ] ++ admins;
|
||||||
|
|
||||||
# disk
|
# disk
|
||||||
"hosts/disk/id.age".publicKeys = withAdmins disk;
|
"hosts/disk/id.age".publicKeys = [ disk ] ++ admins;
|
||||||
"hosts/disk/password.floppy.age".publicKeys = withAdmins disk;
|
"hosts/disk/password.floppy.age".publicKeys = [ disk ] ++ admins;
|
||||||
|
|
||||||
"hosts/disk/mail/password.plain.age".publicKeys = all;
|
"hosts/disk/mail/password.plain.age".publicKeys = all;
|
||||||
"hosts/disk/mail/password.hash.age".publicKeys = [ disk nine ] ++ admins;
|
"hosts/disk/mail/password.hash.age".publicKeys = [ disk nine ] ++ admins;
|
||||||
|
@ -36,8 +29,8 @@ in with keys; {
|
||||||
"hosts/enka/password.said.age".publicKeys = admins;
|
"hosts/enka/password.said.age".publicKeys = admins;
|
||||||
|
|
||||||
# nine
|
# nine
|
||||||
"hosts/nine/id.age".publicKeys = withAdmins nine;
|
"hosts/nine/id.age".publicKeys = [ nine ] ++ admins;
|
||||||
"hosts/nine/password.seven.age".publicKeys = withAdmins nine;
|
"hosts/nine/password.seven.age".publicKeys = [ nine ] ++ admins;
|
||||||
|
|
||||||
# shared
|
# shared
|
||||||
"modules/ssh/config.age".publicKeys = all;
|
"modules/ssh/config.age".publicKeys = all;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue