2023-06-23 22:52:31 +00:00
|
|
|
# nodes is all the nodes
|
2023-09-17 19:51:08 +00:00
|
|
|
{
|
|
|
|
lib,
|
|
|
|
config,
|
|
|
|
nodes,
|
|
|
|
pkgs,
|
|
|
|
...
|
|
|
|
}:
|
|
|
|
with lib; let
|
2024-05-30 12:56:40 +00:00
|
|
|
name = "backup";
|
|
|
|
cfg = config.services.skynet."${name}";
|
2023-09-17 19:51:08 +00:00
|
|
|
|
2024-02-28 14:12:05 +00:00
|
|
|
enable_client = cfg.normal.backups != null && cfg.normal.backups != [];
|
|
|
|
|
2023-09-17 19:51:08 +00:00
|
|
|
# since they should all have the same config we can do this
|
|
|
|
base = {
|
|
|
|
paths = cfg.normal.backups;
|
|
|
|
exclude = cfg.normal.exclude;
|
|
|
|
initialize = true;
|
|
|
|
passwordFile = config.age.secrets.restic.path;
|
|
|
|
|
|
|
|
pruneOpts = [
|
|
|
|
#"--keep-within 0y2m0d0h"
|
|
|
|
#"--keep-monthly 2"
|
|
|
|
];
|
|
|
|
|
|
|
|
timerConfig = {
|
|
|
|
OnCalendar = "daily";
|
|
|
|
Persistent = true;
|
|
|
|
RandomizedDelaySec = "5h";
|
2023-06-23 22:52:31 +00:00
|
|
|
};
|
2023-09-17 19:51:08 +00:00
|
|
|
};
|
2023-06-23 22:52:31 +00:00
|
|
|
|
2023-09-17 19:51:08 +00:00
|
|
|
# takes nodes,
|
|
|
|
# for each check if iut has teh abckup attribute,
|
|
|
|
# then if the server is enabled,
|
|
|
|
# then pull relevant dtails
|
|
|
|
ownServers = builtins.listToAttrs (builtins.concatLists (
|
|
|
|
lib.attrsets.mapAttrsToList (
|
|
|
|
key: value: let
|
2024-05-30 12:56:40 +00:00
|
|
|
backup = value.config.services.skynet.backup;
|
2024-05-30 16:55:29 +00:00
|
|
|
backup_host = value.config.services.skynet.host;
|
2023-09-17 19:51:08 +00:00
|
|
|
in
|
|
|
|
if
|
|
|
|
(
|
2024-05-30 12:56:40 +00:00
|
|
|
(builtins.hasAttr "backup" value.config.services.skynet)
|
2023-09-17 19:51:08 +00:00
|
|
|
&& backup.server.enable
|
2024-05-30 16:55:29 +00:00
|
|
|
# chgeck that its not itself
|
|
|
|
&& backup_host.name != config.services.skynet.host.name
|
2023-09-17 19:51:08 +00:00
|
|
|
&& !backup.server.appendOnly
|
|
|
|
)
|
2023-06-23 22:52:31 +00:00
|
|
|
then [
|
|
|
|
{
|
2024-05-30 16:55:29 +00:00
|
|
|
name = backup_host.name;
|
2023-09-17 19:51:08 +00:00
|
|
|
value =
|
|
|
|
base
|
|
|
|
// {
|
2024-05-30 16:55:29 +00:00
|
|
|
repositoryFile = "/etc/skynet/restic/${backup_host.name}";
|
2023-06-24 00:34:45 +00:00
|
|
|
|
2023-09-17 19:51:08 +00:00
|
|
|
backupPrepareCommand = ''
|
|
|
|
#!${pkgs.stdenv.shell}
|
|
|
|
set -euo pipefail
|
2023-06-24 00:34:45 +00:00
|
|
|
|
2023-09-17 19:51:08 +00:00
|
|
|
baseDir="/etc/skynet/restic"
|
2023-06-24 00:34:45 +00:00
|
|
|
|
2023-09-17 19:51:08 +00:00
|
|
|
mkdir -p $baseDir
|
|
|
|
cd $baseDir
|
2023-06-24 00:34:45 +00:00
|
|
|
|
2024-05-30 16:55:29 +00:00
|
|
|
echo -n "rest:http://root:password@${backup_host.ip}:${toString backup.server.port}/root/${config.services.skynet.host.name}" > ${backup_host.name}
|
2023-06-24 00:34:45 +00:00
|
|
|
|
2023-09-17 19:51:08 +00:00
|
|
|
# read in teh password
|
|
|
|
#PW = `cat ${config.age.secrets.restic.path}`
|
|
|
|
line=$(head -n 1 ${config.age.secrets.restic.path})
|
2023-06-24 00:34:45 +00:00
|
|
|
|
2024-05-30 16:55:29 +00:00
|
|
|
sed -i "s/password/$line/g" ${backup_host.name}
|
2023-09-17 19:51:08 +00:00
|
|
|
'';
|
|
|
|
};
|
2023-06-23 22:52:31 +00:00
|
|
|
}
|
|
|
|
]
|
2023-09-17 19:51:08 +00:00
|
|
|
else []
|
|
|
|
)
|
|
|
|
nodes
|
|
|
|
));
|
|
|
|
in {
|
|
|
|
imports = [
|
2024-06-06 22:33:54 +00:00
|
|
|
./dns.nix
|
|
|
|
./nginx.nix
|
|
|
|
./acme.nix
|
2023-09-17 19:51:08 +00:00
|
|
|
];
|
|
|
|
|
|
|
|
# using https://github.com/greaka/ops/blob/818be4c4dea9129abe0f086d738df4cb0bb38288/apps/restic/options.nix as a base
|
|
|
|
# https://git.hrnz.li/Ulli/nixos/src/commit/5edca2dfdab3ce52208e4dfd2b92951e500f8418/profiles/server/restic.nix
|
|
|
|
# will eb enabled on every server
|
2024-05-30 12:56:40 +00:00
|
|
|
options.services.skynet."${name}" = {
|
2024-05-30 16:55:29 +00:00
|
|
|
enable = mkEnableOption "Skynet backup";
|
2023-09-17 19:51:08 +00:00
|
|
|
|
|
|
|
# what folders to backup
|
|
|
|
normal = {
|
|
|
|
backups = lib.mkOption {
|
|
|
|
default = [];
|
|
|
|
type = lib.types.listOf lib.types.str;
|
|
|
|
description = ''
|
|
|
|
A list of paths to backup.
|
|
|
|
'';
|
|
|
|
};
|
2023-06-23 22:52:31 +00:00
|
|
|
|
2023-09-17 19:51:08 +00:00
|
|
|
exclude = lib.mkOption {
|
|
|
|
default = [];
|
|
|
|
type = lib.types.listOf lib.types.str;
|
|
|
|
description = ''
|
|
|
|
A list of paths to exclide .
|
|
|
|
'';
|
2023-06-23 22:52:31 +00:00
|
|
|
};
|
2023-09-17 19:51:08 +00:00
|
|
|
};
|
2023-06-23 22:52:31 +00:00
|
|
|
|
2023-09-17 19:51:08 +00:00
|
|
|
# append only data so space limited
|
|
|
|
secure = {
|
|
|
|
backups = lib.mkOption {
|
|
|
|
default = [];
|
|
|
|
type = lib.types.listOf lib.types.str;
|
|
|
|
description = ''
|
|
|
|
A list of paths to backup.
|
|
|
|
'';
|
2023-06-23 22:52:31 +00:00
|
|
|
};
|
|
|
|
|
2023-09-17 19:51:08 +00:00
|
|
|
exclude = lib.mkOption {
|
|
|
|
default = [];
|
|
|
|
type = lib.types.listOf lib.types.str;
|
|
|
|
description = ''
|
|
|
|
A list of paths to exclide .
|
|
|
|
'';
|
|
|
|
};
|
|
|
|
};
|
2023-06-23 22:52:31 +00:00
|
|
|
|
2023-09-17 19:51:08 +00:00
|
|
|
server = {
|
|
|
|
enable = mkEnableOption "Skynet backup Server";
|
2023-06-23 22:52:31 +00:00
|
|
|
|
2023-09-17 19:51:08 +00:00
|
|
|
port = mkOption {
|
|
|
|
type = types.port;
|
|
|
|
default = 8765;
|
2023-06-23 22:52:31 +00:00
|
|
|
};
|
|
|
|
|
2023-09-17 19:51:08 +00:00
|
|
|
appendOnly = mkOption {
|
|
|
|
type = types.bool;
|
|
|
|
default = false;
|
|
|
|
};
|
2023-06-23 22:52:31 +00:00
|
|
|
};
|
2024-06-06 22:33:54 +00:00
|
|
|
|
|
|
|
nuked = {
|
|
|
|
enable = mkEnableOption "Nuked Backup server";
|
|
|
|
|
|
|
|
port = mkOption {
|
|
|
|
type = types.port;
|
|
|
|
default = 8765;
|
|
|
|
};
|
|
|
|
|
|
|
|
appendOnly = mkOption {
|
|
|
|
type = types.bool;
|
|
|
|
default = false;
|
|
|
|
};
|
|
|
|
};
|
2023-09-17 19:51:08 +00:00
|
|
|
};
|
2023-06-23 22:52:31 +00:00
|
|
|
|
2024-06-06 20:35:35 +00:00
|
|
|
config = mkMerge [
|
2024-02-28 14:12:05 +00:00
|
|
|
{
|
|
|
|
# these values are anabled for every client
|
|
|
|
environment.systemPackages = with pkgs; [
|
|
|
|
restic
|
|
|
|
];
|
|
|
|
}
|
2024-06-06 20:35:35 +00:00
|
|
|
|
|
|
|
(mkIf cfg.server.enable {
|
2024-02-28 14:12:05 +00:00
|
|
|
networking.firewall.allowedTCPPorts = [
|
|
|
|
cfg.server.port
|
|
|
|
];
|
|
|
|
|
|
|
|
age.secrets.restic_pw = {
|
|
|
|
file = ../secrets/backup/restic_pw.age;
|
|
|
|
path = "${config.services.restic.server.dataDir}/.htpasswd";
|
|
|
|
symlink = false;
|
|
|
|
mode = "770";
|
|
|
|
owner = "restic";
|
|
|
|
group = "restic";
|
2023-09-17 19:51:08 +00:00
|
|
|
};
|
2023-06-23 22:52:31 +00:00
|
|
|
|
2024-02-28 14:12:05 +00:00
|
|
|
services.restic.server = {
|
|
|
|
enable = true;
|
2024-05-30 16:55:29 +00:00
|
|
|
listenAddress = "${config.services.skynet.host.ip}:${toString cfg.server.port}";
|
2024-02-28 14:12:05 +00:00
|
|
|
appendOnly = cfg.server.appendOnly;
|
|
|
|
privateRepos = true;
|
|
|
|
};
|
2024-06-06 20:35:35 +00:00
|
|
|
})
|
|
|
|
|
|
|
|
(mkIf enable_client {
|
2024-02-28 14:12:05 +00:00
|
|
|
# client stuff here
|
|
|
|
|
|
|
|
# A list of all login accounts. To create the password hashes, use
|
|
|
|
# nix-shell -p apacheHttpd
|
|
|
|
# htpasswd -nbB "" "password" | cut -d: -f2
|
|
|
|
|
|
|
|
age.secrets.restic.file = ../secrets/backup/restic.age;
|
|
|
|
|
2024-06-06 20:35:35 +00:00
|
|
|
services.restic.backups = mkMerge [
|
2024-02-28 14:12:05 +00:00
|
|
|
ownServers
|
2024-06-06 20:35:35 +00:00
|
|
|
{
|
2024-02-28 14:12:05 +00:00
|
|
|
# merge teh two configs together
|
|
|
|
# backblaze = base // {
|
|
|
|
# # backupos for each server are stored in a folder under their name
|
2024-05-30 16:55:29 +00:00
|
|
|
# repository = "b2:NixOS-Main2:/${config.services.skynet.host.name}";
|
2024-02-28 14:12:05 +00:00
|
|
|
# #environmentFile = config.age.secrets.backblaze.path;
|
|
|
|
# };
|
2024-06-06 20:35:35 +00:00
|
|
|
}
|
|
|
|
];
|
|
|
|
})
|
2024-06-06 22:33:54 +00:00
|
|
|
|
|
|
|
# restic -r rest:https://skynet:testing@nuked.skynet.ie/ init
|
|
|
|
(mkIf cfg.nuked.enable {
|
|
|
|
assertions = [
|
|
|
|
{
|
|
|
|
assertion = !cfg.server.enable;
|
|
|
|
message = "Our backup and Nuked backup cannot co-exist";
|
|
|
|
}
|
|
|
|
];
|
|
|
|
|
|
|
|
services.skynet.acme.domains = [
|
|
|
|
"nuked.skynet.ie"
|
|
|
|
];
|
|
|
|
|
|
|
|
services.skynet.dns.records = [
|
|
|
|
{
|
|
|
|
record = "nuked";
|
|
|
|
r_type = "CNAME";
|
|
|
|
value = config.services.skynet.host.name;
|
|
|
|
}
|
|
|
|
];
|
|
|
|
|
|
|
|
services.nginx.virtualHosts = {
|
|
|
|
"nuked.skynet.ie" = {
|
|
|
|
forceSSL = true;
|
|
|
|
useACMEHost = "skynet";
|
|
|
|
locations."/" = {
|
|
|
|
proxyPass = "http://${config.services.restic.server.listenAddress}";
|
|
|
|
proxyWebsockets = true;
|
|
|
|
};
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
|
|
|
networking.firewall.allowedTCPPorts = [
|
|
|
|
cfg.nuked.port
|
|
|
|
];
|
|
|
|
|
|
|
|
age.secrets.restic_pw = {
|
|
|
|
file = ../secrets/backup/nuked.age;
|
|
|
|
path = "${config.services.restic.server.dataDir}/.htpasswd";
|
|
|
|
symlink = false;
|
|
|
|
mode = "770";
|
|
|
|
owner = "restic";
|
|
|
|
group = "restic";
|
|
|
|
};
|
|
|
|
|
|
|
|
services.restic.server = {
|
|
|
|
enable = true;
|
|
|
|
listenAddress = "${config.services.skynet.host.ip}:${toString cfg.server.port}";
|
|
|
|
appendOnly = cfg.nuked.appendOnly;
|
|
|
|
privateRepos = true;
|
|
|
|
};
|
|
|
|
})
|
2024-06-06 20:35:35 +00:00
|
|
|
];
|
2023-06-23 22:52:31 +00:00
|
|
|
}
|