backup: init as a reusable module
This commit is contained in:
parent
691c180ac1
commit
fefc7bd20d
15
flake.nix
15
flake.nix
|
@ -102,6 +102,21 @@
|
||||||
"qenya@shaw".imports = [ ./hosts/shaw/home.nix ];
|
"qenya@shaw".imports = [ ./hosts/shaw/home.nix ];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
fountain.backup = {
|
||||||
|
keys = {
|
||||||
|
elucredassa = [ "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIOFa3hjej6KGmS2aQ4s46Y7U8pN4yyR2FuMofpHRwXNk syncoid@elucredassa" ];
|
||||||
|
};
|
||||||
|
sync = {
|
||||||
|
"orm-state" = {
|
||||||
|
dataset = "state";
|
||||||
|
sourceHost = "orm";
|
||||||
|
targetHost = "elucredassa";
|
||||||
|
source = "rpool_orm";
|
||||||
|
target = "rpool_elucredassa/backup/orm";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
flake.colmena = {
|
flake.colmena = {
|
||||||
meta = {
|
meta = {
|
||||||
nixpkgs = import nixpkgs-unstable {
|
nixpkgs = import nixpkgs-unstable {
|
||||||
|
|
126
flake/backup.nix
Normal file
126
flake/backup.nix
Normal file
|
@ -0,0 +1,126 @@
|
||||||
|
{ config, lib, pkgs, ... }:
|
||||||
|
let
|
||||||
|
cfg = config.fountain.backup;
|
||||||
|
|
||||||
|
syncOptions = {
|
||||||
|
dataset = lib.mkOption {
|
||||||
|
type = lib.types.str;
|
||||||
|
description = ''
|
||||||
|
The name of the dataset to be synced (not including its parent
|
||||||
|
datasets, if any). This will be the same on the source and target.
|
||||||
|
It must already exist on the source, defined with the
|
||||||
|
{option}`randomcat.services.zfs` module, and not exist on the target.
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
sourceHost = lib.mkOption {
|
||||||
|
type = lib.types.str;
|
||||||
|
description = ''
|
||||||
|
The host from which the dataset should be synced. Must be an entry in
|
||||||
|
{option}`flake.colmena`.
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
targetHost = lib.mkOption {
|
||||||
|
type = lib.types.str;
|
||||||
|
description = ''
|
||||||
|
The host to which the dataset should be synced. Must be an entry in
|
||||||
|
{option}`flake.colmena`.
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
source = lib.mkOption {
|
||||||
|
type = lib.types.str;
|
||||||
|
description = ''
|
||||||
|
The path to the synced dataset in the ZFS namespace on the source host,
|
||||||
|
excluding the component that is the name of the dataset itself.
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
target = lib.mkOption {
|
||||||
|
type = lib.types.str;
|
||||||
|
description = ''
|
||||||
|
The path to the synced dataset in the ZFS namespace on the target host,
|
||||||
|
excluding the component that is the name of the dataset itself. It must
|
||||||
|
already exist, defined with the {option}`randomcat.services.zfs`
|
||||||
|
module.
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
};
|
||||||
|
in
|
||||||
|
{
|
||||||
|
options.fountain.backup = {
|
||||||
|
keys = lib.mkOption {
|
||||||
|
type = lib.types.attrsOf (lib.types.listOf lib.types.singleLineStr);
|
||||||
|
default = { };
|
||||||
|
description = ''
|
||||||
|
Lists of verbatim OpenSSH public keys that may be used to identify the
|
||||||
|
syncoid user on each target host. The key to each list must be the
|
||||||
|
host's hostname, as listed in {option}`flake.colmena`.
|
||||||
|
'';
|
||||||
|
example = {
|
||||||
|
host = [ "ssh-rsa AAAAB3NzaC1yc2etc/etc/etcjwrsh8e596z6J0l7 example@host" ];
|
||||||
|
bar = [ "ssh-ed25519 AAAAC3NzaCetcetera/etceteraJZMfk3QPfQ foo@bar" ];
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
sync = lib.mkOption {
|
||||||
|
type = lib.types.attrsOf (lib.types.submodule { options = syncOptions; });
|
||||||
|
default = { };
|
||||||
|
description = ''
|
||||||
|
Details of ZFS datasets whose snapshots should be synced from machine
|
||||||
|
to machine using syncoid. Syncoid will run hourly at 15 past the hour
|
||||||
|
and copy all ZFS snapshots from the source dataset to the target
|
||||||
|
dataset (recursing into child datasets).
|
||||||
|
|
||||||
|
See descriptions for the individual options for more details. The name
|
||||||
|
of each attribute in this set is arbitrary and used to generate systemd
|
||||||
|
unit names.
|
||||||
|
|
||||||
|
This module does not actually cause snapshots to be taken; sanoid must
|
||||||
|
be configured separately to do this.
|
||||||
|
'';
|
||||||
|
example = {
|
||||||
|
"orm-state" = {
|
||||||
|
dataset = "state";
|
||||||
|
sourceHost = "orm";
|
||||||
|
targetHost = "elucredassa";
|
||||||
|
source = "rpool_orm";
|
||||||
|
target = "rpool_elucredassa/backup/orm";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
# TODO: add some assertions to verify the options
|
||||||
|
|
||||||
|
config.flake.colmena = lib.mkMerge (lib.mapAttrsToList
|
||||||
|
(name: sync: {
|
||||||
|
${sync.sourceHost} = { pkgs, ... }: {
|
||||||
|
randomcat.services.zfs.datasets."${sync.source}/${sync.dataset}".zfsPermissions.users.backup = [ "hold" "send" ];
|
||||||
|
users.users.backup = {
|
||||||
|
group = "backup";
|
||||||
|
isSystemUser = true;
|
||||||
|
useDefaultShell = true;
|
||||||
|
openssh.authorizedKeys.keys = cfg.keys.${sync.targetHost};
|
||||||
|
packages = with pkgs; [ mbuffer lzop ]; # syncoid uses these if available but doesn't pull them in automatically
|
||||||
|
};
|
||||||
|
users.groups.backup = { };
|
||||||
|
};
|
||||||
|
|
||||||
|
${sync.targetHost} = {
|
||||||
|
randomcat.services.zfs.datasets."${sync.target}".zfsPermissions.users.syncoid = [ "mount" "create" "receive" "recordsize" ];
|
||||||
|
services.syncoid = {
|
||||||
|
enable = true;
|
||||||
|
interval = "*-*-* *:15:00";
|
||||||
|
commonArgs = [ "--no-sync-snap" ];
|
||||||
|
commands = {
|
||||||
|
${name} = {
|
||||||
|
source = "backup@${config.flake.nixosConfigurations.${sync.sourceHost}.config.networking.fqdn}:${sync.source}/${sync.dataset}";
|
||||||
|
target = "${sync.target}/${sync.dataset}";
|
||||||
|
recursive = true;
|
||||||
|
recvOptions = "ux recordsize o compression=lz4";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
})
|
||||||
|
cfg.sync
|
||||||
|
);
|
||||||
|
}
|
|
@ -1,5 +1,6 @@
|
||||||
{
|
{
|
||||||
imports = [
|
imports = [
|
||||||
|
./backup.nix
|
||||||
./colmena.nix
|
./colmena.nix
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,26 +23,10 @@ in
|
||||||
console.keyMap = "uk";
|
console.keyMap = "uk";
|
||||||
services.xserver.xkb.layout = "gb";
|
services.xserver.xkb.layout = "gb";
|
||||||
|
|
||||||
# TODO: modularise this
|
# These are populated by fountain.backup
|
||||||
randomcat.services.zfs.datasets = {
|
randomcat.services.zfs.datasets = {
|
||||||
"rpool_elucredassa/backup" = { mountpoint = "none"; };
|
"rpool_elucredassa/backup" = { mountpoint = "none"; };
|
||||||
"rpool_elucredassa/backup/orm" = {
|
"rpool_elucredassa/backup/orm" = { mountpoint = "none"; };
|
||||||
mountpoint = "none";
|
|
||||||
zfsPermissions.users.syncoid = [ "mount" "create" "receive" "recordsize" ];
|
|
||||||
};
|
|
||||||
};
|
|
||||||
services.syncoid = {
|
|
||||||
enable = true;
|
|
||||||
interval = "*-*-* *:15:00";
|
|
||||||
commonArgs = [ "--no-sync-snap" ];
|
|
||||||
commands = {
|
|
||||||
"testing1" = {
|
|
||||||
source = "backup@10.127.1.2:rpool_orm/state";
|
|
||||||
target = "rpool_elucredassa/backup/orm/state";
|
|
||||||
recursive = true;
|
|
||||||
recvOptions = "ux recordsize o compression=lz4";
|
|
||||||
};
|
|
||||||
};
|
|
||||||
};
|
};
|
||||||
|
|
||||||
qenya.services.distributed-builds = {
|
qenya.services.distributed-builds = {
|
||||||
|
|
|
@ -32,19 +32,6 @@
|
||||||
recursive = "zfs";
|
recursive = "zfs";
|
||||||
};
|
};
|
||||||
|
|
||||||
# TODO: modularise this
|
|
||||||
randomcat.services.zfs.datasets."rpool_orm/state".zfsPermissions.users.backup = [ "hold" "send" ];
|
|
||||||
users.users.backup = {
|
|
||||||
group = "backup";
|
|
||||||
isSystemUser = true;
|
|
||||||
useDefaultShell = true;
|
|
||||||
openssh.authorizedKeys.keys = [
|
|
||||||
"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIOFa3hjej6KGmS2aQ4s46Y7U8pN4yyR2FuMofpHRwXNk syncoid@elucredassa"
|
|
||||||
];
|
|
||||||
packages = with pkgs; [ mbuffer lzop ]; # syncoid uses these if available but doesn't pull them in automatically
|
|
||||||
};
|
|
||||||
users.groups.backup = { };
|
|
||||||
|
|
||||||
qenya.services.actual = {
|
qenya.services.actual = {
|
||||||
enable = true;
|
enable = true;
|
||||||
domain = "actual.qenya.tel";
|
domain = "actual.qenya.tel";
|
||||||
|
|
Loading…
Reference in a new issue