beep
This commit is contained in:
parent
ffd17fe123
commit
e359ba8711
|
@ -6,13 +6,13 @@ _: {
|
||||||
|
|
||||||
# needed so quassel can access SSL certs
|
# needed so quassel can access SSL certs
|
||||||
# TODO: set up SSL
|
# TODO: set up SSL
|
||||||
users.groups.acme.members = [ "quassel" ];
|
# users.groups.acme.members = [ "quassel" ];
|
||||||
|
|
||||||
# Not gonna serve anything there but shrug.
|
# Not gonna serve anything there but shrug.
|
||||||
services.nginx.virtualHosts."quassel.owo.monster" = {
|
#services.nginx.virtualHosts."quassel.owo.monster" = {
|
||||||
forceSSL = true;
|
# forceSSL = true;
|
||||||
enableACME = true;
|
# enableACME = true;
|
||||||
};
|
#};
|
||||||
|
|
||||||
services.postgresql.ensureDatabases = [ "quassel" ];
|
services.postgresql.ensureDatabases = [ "quassel" ];
|
||||||
services.postgresql.ensureUsers = [{
|
services.postgresql.ensureUsers = [{
|
||||||
|
|
|
@ -35,7 +35,9 @@ let
|
||||||
};
|
};
|
||||||
repos = {
|
repos = {
|
||||||
Chaos-Backups-HetznerVM = {
|
Chaos-Backups-HetznerVM = {
|
||||||
repository = "b2:Chaos-Backups:HetznerVM";
|
# repository is overrided in environmentFile to contain auth
|
||||||
|
# make sure to keep up to date when changing repository
|
||||||
|
repository = "rest:https://storage-restic.owo.monster/HetznerVM";
|
||||||
passwordFile = "/secrets/restic-Chaos-Backups-HetznerVM-password";
|
passwordFile = "/secrets/restic-Chaos-Backups-HetznerVM-password";
|
||||||
environmentFile = "/secrets/restic-Chaos-Backups-HetznerVM-env";
|
environmentFile = "/secrets/restic-Chaos-Backups-HetznerVM-env";
|
||||||
};
|
};
|
||||||
|
@ -51,9 +53,9 @@ let
|
||||||
# nya
|
# nya
|
||||||
pkgs.writeShellScriptBin "restic-${repoName}" ''
|
pkgs.writeShellScriptBin "restic-${repoName}" ''
|
||||||
env \
|
env \
|
||||||
$(cat ${repoInfo.environmentFile}) \
|
|
||||||
RESTIC_PASSWORD_FILE=${repoInfo.passwordFile} \
|
RESTIC_PASSWORD_FILE=${repoInfo.passwordFile} \
|
||||||
RESTIC_REPOSITORY=${repoInfo.repository} \
|
RESTIC_REPOSITORY=${repoInfo.repository} \
|
||||||
|
$(cat ${repoInfo.environmentFile}) \
|
||||||
${pkgs.restic}/bin/restic $@
|
${pkgs.restic}/bin/restic $@
|
||||||
'')) repos;
|
'')) repos;
|
||||||
in {
|
in {
|
||||||
|
|
|
@ -47,7 +47,11 @@ in {
|
||||||
storage = nixosUnstableSystem {
|
storage = nixosUnstableSystem {
|
||||||
specialArgs = defaultSpecialArgs;
|
specialArgs = defaultSpecialArgs;
|
||||||
system = "x86_64-linux";
|
system = "x86_64-linux";
|
||||||
modules = defaultModules ++ [ ./storage/modules/rclone-serve.nix ./storage/storage.nix ];
|
modules = defaultModules ++ [
|
||||||
|
./storage/modules/rclone-serve.nix
|
||||||
|
./storage/modules/rclone-sync.nix
|
||||||
|
./storage/storage.nix
|
||||||
|
];
|
||||||
};
|
};
|
||||||
|
|
||||||
# nix --no-sandbox build .#nixosConfigurations.raspberry.config.system.build.sdImage
|
# nix --no-sandbox build .#nixosConfigurations.raspberry.config.system.build.sdImage
|
||||||
|
|
|
@ -7,9 +7,9 @@ let
|
||||||
|
|
||||||
daemonService = serve_config: {
|
daemonService = serve_config: {
|
||||||
enable = true;
|
enable = true;
|
||||||
requires = [ "network.target" ];
|
after = [ "network.target" ];
|
||||||
after = [ "network.target" ]
|
wants = [ "network.target" ]
|
||||||
++ (if serve_config.after != null then serve_config.after else [ ]);
|
++ (if serve_config.wants != null then serve_config.wants else [ ]);
|
||||||
wantedBy = [ "multi-user.target" ];
|
wantedBy = [ "multi-user.target" ];
|
||||||
serviceConfig = {
|
serviceConfig = {
|
||||||
Type = "simple";
|
Type = "simple";
|
||||||
|
@ -21,7 +21,7 @@ let
|
||||||
|
|
||||||
ExecStart =
|
ExecStart =
|
||||||
"${pkgs.rclone}/bin/rclone serve ${serve_config.type} ${serve_config.remote} ${
|
"${pkgs.rclone}/bin/rclone serve ${serve_config.type} ${serve_config.remote} ${
|
||||||
lib.concatStrings serve_config.extraArgs
|
lib.concatStringsSep " " serve_config.extraArgs
|
||||||
}";
|
}";
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
@ -39,7 +39,7 @@ in {
|
||||||
remote = mkOption { type = types.str; };
|
remote = mkOption { type = types.str; };
|
||||||
type = mkOption { type = types.str; };
|
type = mkOption { type = types.str; };
|
||||||
user = mkOption { type = types.str; };
|
user = mkOption { type = types.str; };
|
||||||
after = mkOption { type = types.listOf types.str; };
|
wants = mkOption { type = types.listOf types.str; };
|
||||||
|
|
||||||
extraArgs = mkOption { type = types.listOf types.str; };
|
extraArgs = mkOption { type = types.listOf types.str; };
|
||||||
};
|
};
|
||||||
|
|
73
hosts/storage/modules/rclone-sync.nix
Normal file
73
hosts/storage/modules/rclone-sync.nix
Normal file
|
@ -0,0 +1,73 @@
|
||||||
|
{ config, lib, pkgs, ... }:
|
||||||
|
with lib;
|
||||||
|
let
|
||||||
|
cfg = config.services.rclone-sync;
|
||||||
|
|
||||||
|
makeNameSafe = name: builtins.replaceStrings [ "/" ":" ] [ "-" "-" ] name;
|
||||||
|
|
||||||
|
daemonService = sync_config: {
|
||||||
|
serviceConfig = {
|
||||||
|
Type = "oneshot";
|
||||||
|
|
||||||
|
User = if cfg.user != null then "${cfg.user}" else "root";
|
||||||
|
|
||||||
|
ExecStart =
|
||||||
|
"${pkgs.rclone}/bin/rclone sync ${sync_config.source} ${sync_config.dest} -P";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
in {
|
||||||
|
options = {
|
||||||
|
services.rclone-sync = {
|
||||||
|
enable = mkOption {
|
||||||
|
type = types.bool;
|
||||||
|
default = false;
|
||||||
|
};
|
||||||
|
|
||||||
|
user = mkOption {
|
||||||
|
type = types.str;
|
||||||
|
default = null;
|
||||||
|
};
|
||||||
|
|
||||||
|
sync_jobs = mkOption {
|
||||||
|
type = types.listOf (types.submodule {
|
||||||
|
options = {
|
||||||
|
source = mkOption { type = types.str; };
|
||||||
|
dest = mkOption { type = types.str; };
|
||||||
|
|
||||||
|
timerConfig = mkOption { type = types.attrs; };
|
||||||
|
|
||||||
|
wants = mkOption {
|
||||||
|
type = types.listOf types.str;
|
||||||
|
default = [ ];
|
||||||
|
};
|
||||||
|
};
|
||||||
|
});
|
||||||
|
default = [ ];
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
config = mkMerge [
|
||||||
|
(mkIf (cfg.enable && cfg.sync_jobs != [ ]) {
|
||||||
|
systemd.services = listToAttrs (map (job: {
|
||||||
|
name =
|
||||||
|
"rclone-sync-${makeNameSafe job.source}-${makeNameSafe job.dest}";
|
||||||
|
value = daemonService job;
|
||||||
|
}) cfg.sync_jobs);
|
||||||
|
systemd.timers = listToAttrs (map (job: {
|
||||||
|
name =
|
||||||
|
"rclone-sync-${makeNameSafe job.source}-${makeNameSafe job.dest}";
|
||||||
|
value = {
|
||||||
|
wantedBy = [ "timers.target" ];
|
||||||
|
wants = job.wants;
|
||||||
|
partOf = [
|
||||||
|
"rclone-sync-${makeNameSafe job.source}-${
|
||||||
|
makeNameSafe job.dest
|
||||||
|
}.service"
|
||||||
|
];
|
||||||
|
timerConfig = job.timerConfig;
|
||||||
|
};
|
||||||
|
}) cfg.sync_jobs);
|
||||||
|
})
|
||||||
|
];
|
||||||
|
}
|
|
@ -30,9 +30,15 @@ STORAGEBOX_PASSWORD=$(simple_get_obscure /api-keys/hetzner/storagebox .password)
|
||||||
sed -i "s/STORAGEBOX_PASSWORD/${STORAGEBOX_PASSWORD}/" ./template
|
sed -i "s/STORAGEBOX_PASSWORD/${STORAGEBOX_PASSWORD}/" ./template
|
||||||
|
|
||||||
B2_CHAOS_BACKUPS_ACCOUNT=$(simple_get /api-keys/backblaze/Chaos-Backups .keyID)
|
B2_CHAOS_BACKUPS_ACCOUNT=$(simple_get /api-keys/backblaze/Chaos-Backups .keyID)
|
||||||
B2_CHAOS_BACKUPS_KEY=$(simple_get /api-keys/backblaze/Chaos-Backups .applicationKey)
|
B2_CHAOS_BACKUPS_KEY=$(simple_get /api-keys/backblaze/Chaos-Backups .applicationKey | sed "s#/#\\\/#")
|
||||||
sed -i "s/B2_CHAOS_BACKUPS_ACCOUNT/${B2_CHAOS_BACKUPS_ACCOUNT}/" ./template
|
sed -i "s/B2_CHAOS_BACKUPS_ACCOUNT/${B2_CHAOS_BACKUPS_ACCOUNT}/" ./template
|
||||||
sed -i "s/B2_CHAOS_BACKUPS_KEY/${B2_CHAOS_BACKUPS_KEY}/" ./template
|
sed -i "s/B2_CHAOS_BACKUPS_KEY/${B2_CHAOS_BACKUPS_KEY}/" ./template
|
||||||
|
|
||||||
|
B2_CHAOS_PHOTOS_ACCOUNT=$(simple_get /api-keys/backblaze/Chaos-Photos .keyID)
|
||||||
|
B2_CHAOS_PHOTOS_KEY=$(simple_get /api-keys/backblaze/Chaos-Photos .applicationKey | sed "s#/#\\\/#")
|
||||||
|
sed -i "s/B2_CHAOS_PHOTOS_ACCOUNT/${B2_CHAOS_PHOTOS_ACCOUNT}/" ./template
|
||||||
|
sed -i "s/B2_CHAOS_PHOTOS_KEY/${B2_CHAOS_PHOTOS_KEY}/" ./template
|
||||||
|
|
||||||
popd
|
popd
|
||||||
|
|
||||||
cat "${TMP_DIR}/template" > "${OUTPUT_FILE}"
|
cat "${TMP_DIR}/template" > "${OUTPUT_FILE}"
|
||||||
|
|
|
@ -17,3 +17,13 @@ hard_delete = true
|
||||||
[B2-Chaos-Backups]
|
[B2-Chaos-Backups]
|
||||||
type = alias
|
type = alias
|
||||||
remote = B2-Chaos-Backups-Source:Chaos-Backups
|
remote = B2-Chaos-Backups-Source:Chaos-Backups
|
||||||
|
|
||||||
|
[B2-Chaos-Photos-Source]
|
||||||
|
type = b2
|
||||||
|
account = B2_CHAOS_PHOTOS_ACCOUNT
|
||||||
|
key = B2_CHAOS_PHOTOS_KEY
|
||||||
|
hard_delete = true
|
||||||
|
|
||||||
|
[B2-Chaos-Photos]
|
||||||
|
type = alias
|
||||||
|
remote = B2-Chaos-Photos-Source:Chaos-Photos
|
|
@ -23,7 +23,6 @@
|
||||||
|
|
||||||
systemd.services.populate-rclone-config = {
|
systemd.services.populate-rclone-config = {
|
||||||
wantedBy = [ "multi-user.target" ];
|
wantedBy = [ "multi-user.target" ];
|
||||||
requires = [ "network.target" ];
|
|
||||||
after = [ "network.target" ];
|
after = [ "network.target" ];
|
||||||
path = with pkgs; [ bash rclone vault getent jq ];
|
path = with pkgs; [ bash rclone vault getent jq ];
|
||||||
script = let
|
script = let
|
||||||
|
@ -42,24 +41,17 @@
|
||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
|
|
||||||
systemd.tmpfiles.rules = [ "d /storage 0755 storage storage -" ];
|
|
||||||
systemd.services.storage-mount = {
|
systemd.services.storage-mount = {
|
||||||
wantedBy = [ "multi-user.target" ];
|
wantedBy = [ "multi-user.target" ];
|
||||||
requires = [
|
after = [ "network.target" ];
|
||||||
"network.target"
|
wants = [ "populate-rclone-config.service" ];
|
||||||
"populate-rclone-config.service"
|
|
||||||
"systemd-tmpfiles-setup.service"
|
path = with pkgs; [ bash rclone mount umount ];
|
||||||
];
|
|
||||||
after = [
|
|
||||||
"network.target"
|
|
||||||
"populate-rclone-config.service"
|
|
||||||
"systemd-tmpfiles-setup.service"
|
|
||||||
];
|
|
||||||
path = with pkgs; [ bash rclone mount ];
|
|
||||||
script = ''
|
script = ''
|
||||||
set -e
|
set -e
|
||||||
umount /storage || true
|
umount /storage -fl || true
|
||||||
rclone --config /home/storage/.config/rclone/rclone.conf mount StorageBox: /storage
|
sleep 2
|
||||||
|
rclone --config /home/storage/.config/rclone/rclone.conf mount StorageBox: /storage --allow-non-empty
|
||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -81,22 +73,85 @@
|
||||||
|
|
||||||
services.rclone-serve = {
|
services.rclone-serve = {
|
||||||
enable = true;
|
enable = true;
|
||||||
remotes = [{
|
remotes = [
|
||||||
user = "storage";
|
{
|
||||||
remote = "StorageBox:Chaos-Backups/DNS";
|
user = "storage";
|
||||||
type = "webdav";
|
remote = "StorageBox:";
|
||||||
after = [ "populate-rclone-config.service" ];
|
type = "webdav";
|
||||||
extraArgs = [ "--addr=:4242" ];
|
wants = [ "populate-rclone-config.service" ];
|
||||||
}];
|
extraArgs = [ "--addr=:4242" "--htpasswd=/secrets/webdav_htpasswd" ];
|
||||||
|
}
|
||||||
|
{
|
||||||
|
user = "storage";
|
||||||
|
remote = "StorageBox:Chaos-Backups/HetznerVM";
|
||||||
|
type = "restic";
|
||||||
|
wants = [ "populate-rclone-config.service" ];
|
||||||
|
extraArgs = [
|
||||||
|
"--addr=:4243"
|
||||||
|
"--htpasswd=/secrets/restic_hetznervm_htpasswd"
|
||||||
|
"--baseurl=/HetznerVM/"
|
||||||
|
];
|
||||||
|
}
|
||||||
|
{
|
||||||
|
user = "storage";
|
||||||
|
remote = "StorageBox:Chaos-Backups/Music";
|
||||||
|
type = "restic";
|
||||||
|
wants = [ "populate-rclone-config.service" ];
|
||||||
|
extraArgs = [
|
||||||
|
"--addr=:4244"
|
||||||
|
"--htpasswd=/secrets/restic_music_htpasswd"
|
||||||
|
"--baseurl=/Music/"
|
||||||
|
];
|
||||||
|
}
|
||||||
|
];
|
||||||
};
|
};
|
||||||
|
|
||||||
services.nginx.virtualHosts."storage-web.owo.monster" = {
|
services.nginx.virtualHosts."storage-webdav.owo.monster" = {
|
||||||
forceSSL = true;
|
forceSSL = true;
|
||||||
enableACME = true;
|
enableACME = true;
|
||||||
#locations = { "/".proxyPass = "http://localhost:4242"; };
|
locations = { "/".proxyPass = "http://localhost:4242"; };
|
||||||
};
|
};
|
||||||
|
|
||||||
environment.systemPackages = with pkgs; [ rclone cifs-utils ];
|
services.nginx.virtualHosts."storage-restic.owo.monster" = {
|
||||||
|
forceSSL = true;
|
||||||
|
enableACME = true;
|
||||||
|
locations = {
|
||||||
|
"/HetznerVM/".proxyPass = "http://localhost:4243";
|
||||||
|
"/Music/".proxyPass = "http://localhost:4244";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
services.rclone-sync = {
|
||||||
|
enable = true;
|
||||||
|
user = "storage";
|
||||||
|
sync_jobs = [
|
||||||
|
{
|
||||||
|
source = "StorageBox:Chaos-Backups";
|
||||||
|
dest = "B2-Chaos-Backups:";
|
||||||
|
wants = [ "populate-rclone-config.service" ];
|
||||||
|
timerConfig = {
|
||||||
|
OnStartupSec = "60";
|
||||||
|
OnCalendar = "4h";
|
||||||
|
};
|
||||||
|
}
|
||||||
|
{
|
||||||
|
source = "StorageBox:Chaos-Photos";
|
||||||
|
dest = "B2-Chaos-Photos:";
|
||||||
|
wants = [ "populate-rclone-config.service" ];
|
||||||
|
timerConfig = {
|
||||||
|
OnStartupSec = "60";
|
||||||
|
OnCalendar = "4h";
|
||||||
|
};
|
||||||
|
}
|
||||||
|
];
|
||||||
|
};
|
||||||
|
|
||||||
|
environment.systemPackages = with pkgs; [
|
||||||
|
rclone
|
||||||
|
cifs-utils
|
||||||
|
apacheHttpd
|
||||||
|
restic
|
||||||
|
];
|
||||||
|
|
||||||
home-manager.users.root = {
|
home-manager.users.root = {
|
||||||
imports = with tree; [ home.base home.dev.small ];
|
imports = with tree; [ home.base home.dev.small ];
|
||||||
|
|
Loading…
Reference in a new issue