feat(koi): backups

This commit is contained in:
alina 🌸 2024-12-29 00:06:33 +03:00
parent 04c20be5b8
commit 5bf0d327c3
Signed by: teidesu
SSH key fingerprint: SHA256:uNeCpw6aTSU4aIObXLvHfLkDa82HWH9EiOj9AXOIRpI
11 changed files with 194 additions and 5 deletions

View file

@ -23,6 +23,7 @@
./services/landing ./services/landing
./services/geesefs.nix ./services/geesefs.nix
./services/actions-runner ./services/actions-runner
./services/autorestic
./containers/torrent.nix ./containers/torrent.nix
./containers/soulseek ./containers/soulseek

View file

@ -9,7 +9,9 @@ sentry_traces_sample_rate = 0.01
sentry_attach_stacktrace = false sentry_attach_stacktrace = false
database_path = "/data" database_path = "/data/db"
database_backup_path = "/data/backup"
database_backups_to_keep = 1
database_backend = "rocksdb" database_backend = "rocksdb"
port = 6167 port = 6167

View file

@ -0,0 +1,87 @@
version: 2
global:
forget:
keep-daily: 30
keep-weekly: 52
backends:
rclone:
type: rclone
path: backups:backups/koi
requireKey: true
# todo: move this to `options.desu.autorestic.locations`
locations:
conduwuit:
# while conduwuit does support online backups, it's not really useful
# since it needs to be invoked manually from the management room via "!admin server backup-database"
from: /srv/conduwuit/db
to: rclone
hooks:
prevalidate:
- systemctl stop docker-conduwuit
after:
- systemctl start docker-conduwuit
cron: '0 6 * * *'
options:
backup:
exclude:
- /srv/conduwuit/db/media
# media is safe to backup online, so we do this as a separate location to avoid too much downtime
conduwuit-media:
from: /srv/conduwuit/db/media
to: rclone
cron: '0 6 * * *'
mautrix-telegram:
from: /srv/mautrix-telegram/
to: rclone
cron: '0 6 * * *'
postgres:
from: /tmp/pg-backup/
to: rclone
cron: '0 6,18 * * *'
hooks:
prevalidate:
- mkdir -p /tmp/pg-backup
- chown postgres:postgres /tmp/pg-backup
- sudo -u postgres pg_dumpall -f /tmp/pg-backup/backup.sql
after:
- rm -rf /tmp/pg-backup
navidrome-db:
from: /srv/navidrome/navidrome.db.bak
to: rclone
hooks:
prevalidate:
- sqlite3 /srv/navidrome/navidrome.db ".backup /srv/navidrome/navidrome.db.bak"
after:
- rm /srv/navidrome/navidrome.db.bak
cron: '0 6 * * *'
bluesky-pds:
from: /srv/bluesky-pds/data/
to: rclone
cron: '0 6 * * *'
sftpgo:
from: /srv/sftpgo/
to: rclone
cron: '0 6 * * *'
siyuan-teidesu:
from: /srv/siyuan-teidesu
to: rclone
cron: '0 6 * * *'
slskd:
from: /srv/slskd/
to: rclone
cron: '0 6 * * *'
verdaccio:
from: /srv/verdaccio/
to: rclone
cron: '0 6 * * *'
teisu:
from: /srv/teisu/
to: rclone
cron: '0 6 * * *'
vaultwarden:
from: /srv/vaultwarden/
to: rclone
cron: '0 6 * * *'

View file

@ -0,0 +1,33 @@
{ pkgs, config, lib, ... }:
let
autoresticWrapped = pkgs.writeShellScriptBin "autorestic" ''
set -euo pipefail
set -o allexport
source ${config.desu.secrets.autorestic-env.path}
set +o allexport
export PATH="${lib.makeBinPath [ pkgs.restic pkgs.rclone pkgs.sqlite ]}:$PATH"
# crutch: autorestic requires a lockfile to be beside the config file
mkdir -p /etc/autorestic
chmod -R 700 /etc/autorestic
cp ${./config.yaml} /etc/autorestic/config.yaml
exec ${pkgs.autorestic}/bin/autorestic -c /etc/autorestic/config.yaml $@
'';
in {
desu.secrets.autorestic-env.owner = "root";
systemd.services.autorestic = {
serviceConfig = {
Type = "oneshot";
User = "root";
ExecStart = "${autoresticWrapped}/bin/autorestic --ci cron";
};
startAt = "*:0/5";
};
environment.systemPackages = [ autoresticWrapped ];
}

View file

@ -3,6 +3,7 @@
{ {
imports = [ imports = [
(abs "services/geesefs.nix") (abs "services/geesefs.nix")
(abs "services/rclone-mount.nix")
(abs "services/gocryptfs.nix") (abs "services/gocryptfs.nix")
]; ];
@ -35,11 +36,11 @@
"--max-parallel-parts" "32" "--max-parallel-parts" "32"
"--part-sizes" "25" "--part-sizes" "25"
"--large-read-cutoff" "40960" "--large-read-cutoff" "40960"
"--enable-patch"
]; ];
bucket = "desu-priv"; bucket = "desu-priv";
mountPoint = "/mnt/s3-desu-priv"; mountPoint = "/mnt/s3-desu-priv";
}; };
systemd.services.geesefs.after = [ "coredns.service" ]; systemd.services.geesefs.after = [ "coredns.service" ];
services.gocryptfs = { services.gocryptfs = {

View file

@ -19,6 +19,7 @@ note to self on what needs to be installed on the host manually:
- `/etc/vms/bnuuy.img` - qcow2 image of an ubuntu cloud image (e.g. `https://cloud-images.ubuntu.com/noble/current/noble-server-cloudimg-amd64.img`) - `/etc/vms/bnuuy.img` - qcow2 image of an ubuntu cloud image (e.g. `https://cloud-images.ubuntu.com/noble/current/noble-server-cloudimg-amd64.img`)
- `/etc/secureboot/keys` - secure boot keys, generated with `sudo nix-shell -p sbctl --run "sbctl create-keys"` - `/etc/secureboot/keys` - secure boot keys, generated with `sudo nix-shell -p sbctl --run "sbctl create-keys"`
- to enroll fde onto tpm: `sudo systemd-cryptenroll /dev/nvme0n1p2 --tpm2-device=auto --tpm2-pcrs=0+2+7` - to enroll fde onto tpm: `sudo systemd-cryptenroll /dev/nvme0n1p2 --tpm2-device=auto --tpm2-pcrs=0+2+7`
- rclone config (for backups): `sudo nix-shell -p rclone --run "rclone config"` you need to set up a remote called `backups`, which will be used as the destination for all backups
### teidesu-osx ### teidesu-osx
`cp /var/run/current-system/Library/Fonts/* /Library/Fonts` - copy nix-managed fonts to system fonts (waiting for [this PR](https://github.com/LnL7/nix-darwin/pull/754)) `cp /var/run/current-system/Library/Fonts/* /Library/Fonts` - copy nix-managed fonts to system fonts (waiting for [this PR](https://github.com/LnL7/nix-darwin/pull/754))

BIN
secrets/autorestic-env.age Normal file

Binary file not shown.

Binary file not shown.

View file

@ -36,7 +36,7 @@
cfg.bucket cfg.bucket
cfg.mountPoint cfg.mountPoint
]; ];
in { in lib.mkIf cfg.enable {
systemd.services.${cfg.serviceName} = { systemd.services.${cfg.serviceName} = {
description = "${cfg.serviceName} Daemon"; description = "${cfg.serviceName} Daemon";
after = [ "network.target" ]; after = [ "network.target" ];
@ -48,7 +48,7 @@
Type = "forking"; Type = "forking";
GuessMainPID = true; GuessMainPID = true;
ExecStart = "${cfg.package}/bin/geesefs ${builtins.concatStringsSep " " (map lib.escapeShellArg allArgs)}"; ExecStart = "${cfg.package}/bin/geesefs ${builtins.concatStringsSep " " (map lib.escapeShellArg allArgs)}";
ExecStop = "fusermount -uz ${lib.escapeShellArg cfg.mountPoint}"; ExecStop = "${pkgs.fuse}/bin/fusermount -uz ${lib.escapeShellArg cfg.mountPoint}";
Restart = "on-failure"; Restart = "on-failure";
}; };
}; };

View file

@ -46,7 +46,7 @@
config = let config = let
cfg = config.services.gocryptfs; cfg = config.services.gocryptfs;
in { in lib.mkIf cfg.enable {
systemd.services.${cfg.serviceName} = { systemd.services.${cfg.serviceName} = {
description = "${cfg.serviceName} daemon"; description = "${cfg.serviceName} daemon";
wantedBy = [ "multi-user.target" ]; wantedBy = [ "multi-user.target" ];

64
services/rclone-mount.nix Normal file
View file

@ -0,0 +1,64 @@
{ config, lib, pkgs, ... }:
{
options.services.rclone-mount = with lib; {
enable = mkEnableOption "rclone";
package = mkOption {
type = types.package;
default = pkgs.rclone;
defaultText = "pkgs.rclone";
description = "rclone package";
};
config = mkOption {
type = types.attrs;
description = "rclone config";
};
remote = mkOption {
type = types.str;
description = "rclone remote path to mount";
};
mountPoint = mkOption {
type = types.str;
description = "rclone mount point";
};
extraArgs = mkOption {
type = types.listOf types.str;
default = [ ];
description = "extra rclone arguments";
};
serviceName = mkOption {
type = types.str;
default = "rclone-mount";
description = "rclone service name";
};
};
config = let
cfg = config.services.rclone-mount;
allArgs = cfg.extraArgs ++ [
cfg.remote
cfg.mountPoint
];
rcloneConfig = (pkgs.formats.ini {}).generate "rclone.conf" cfg.config;
in lib.mkIf cfg.enable {
systemd.services.${cfg.serviceName} = {
description = "rclone-mount Daemon";
after = [ "network.target" ];
wantedBy = [ "multi-user.target" ];
path = [ pkgs.fuse ];
serviceConfig = {
User = "root";
Group = "root";
ExecStart = "${cfg.package}/bin/rclone --config ${rcloneConfig} mount ${builtins.concatStringsSep " " (map lib.escapeShellArg allArgs)}";
ExecStop = "${pkgs.fuse}/bin/fusermount -uz ${lib.escapeShellArg cfg.mountPoint}";
Restart = "on-failure";
};
};
systemd.tmpfiles.rules = [
"d ${cfg.mountPoint} 0777 root root -"
];
};
}