restic: Use storage box and restic-rest-server

While this setup complicates things, it also should protect me against
(malicious) deletion of old backups.
This commit is contained in:
Simon Bruder 2022-08-25 17:18:43 +02:00
parent 19eab9411c
commit 4e78d87bde
Signed by: simon
GPG key ID: 8D3C82F9F309F8EC
6 changed files with 85 additions and 13 deletions

View file

@ -1,3 +1,4 @@
restic-ssh-key: ENC[AES256_GCM,data:wA7JCg6Y900s6+1JoevMzbr6fKRN6jbfUuX166VS+TUFhFbn0npz5gKkAQpC8h1io1WaSCPJkJMzr+viOLlnVwqe8zFGm3ZJlKSEqKKK+CatZ95+zKACOZuBAC/2E6rep6JnL/C3/gKMKibVmAL+9TkTX6nA83xwhM65JPLN/+bP29bq0Cr2FopgZgNPQjb6ANB4POy+MUktet63DZ4dJwKvndiCRg4EMLIOqFopbQei6Pxc1F/lC3yBu71YgB4TSGQp/6tXjfFOuXQpI0nFrZCmLYcW03ZqOBQbKg3w4rwlqtnl25/23jpT0kqWp99wHUGMCib5+iywPUMSNDwAsz0fq04JGpTEM9cuxkLWZVfCpguNlgaiwCObyJkA2CHXlIn6KYsDOa6U/Uy9mNRPae52j/E+JdLQycOwT5+n78j0vqtvS69blUC/E7j2IWe17SI8JVCiYFbZXPqVm43jdEiQ9jU4gXMsu6NKppnBhFSrMVUHScS3gR/xnTfrabrr2FWJwIOjdGdJb4pr+nfZ,iv:ow+hzt5YGGD0FDvN+XkZtW74k4mwW+6HqWZMtOwAWDg=,tag:HXogIkcSTq6Ep4M2MXEMew==,type:str]
wg-home-private-key: ENC[AES256_GCM,data:6l3CgB4qCsPuyYOWuwU2vNiEeC0D1wl6yZvXGGYVsZfYvdPjRz8j5yV7ekQ=,iv:slB/qr+cxi8r7cnTuZAd8CuzWVnvp24Li6A/AnZaFzo=,tag:ynh1Z2+IELAJcgBbHwFC0A==,type:str]
wg-qbittorrent-private-key: ENC[AES256_GCM,data:9sjqTCMXqN0oWS95RQOmfLK0/2dH6V4Rs2LX8ydnYl+7zR55PG5pW3kROH8=,iv:m+4xKthKNCQBOEP9ExOHY5Dg3i+yTgREwrAci4zhqUk=,tag:L0vnwyiGOAoarr7FZFE91A==,type:str]
sops:
@ -6,8 +7,8 @@ sops:
azure_kv: []
hc_vault: []
age: []
lastmodified: "2022-06-09T21:32:26Z"
mac: ENC[AES256_GCM,data:96T1CeXtmu98I0pHrg3tZ7LNOk2O9NkIzGXm0HfbPa2D0JJa5oNpkaW3pxY9mF+CNz3zBb8RaDLoeFPhcJ7i5eGtGwL/yqAKJsoZZ2VmBUbgjKhYQMP2A4vxk2NCKjgeicAUjXzkbyhPQP411hGNuZWjjcQtUZRa8ErSXZ4LHEw=,iv:SJLSvQCnIMiPJh4ysUOQLv1O0cySFcT2Z+vfrq2E3C4=,tag:wT4t23H7UG2qZR//j3biOQ==,type:str]
lastmodified: "2022-08-25T14:39:59Z"
mac: ENC[AES256_GCM,data:3Z1f1DobOU1RHT25TM0FI9fUUtZxrFhKeGTmXaxC+vDE2j9url28XVDesiMmj2Vairapk5krf31hV47K62Q+YvVyYrNw0a3hn+v7/2kBrbdU1SqZNajVwb7/3F5YKYNcsF/tHLClJrwYOIrSWBWsky7gim2ohItm6eKuG9ED+wg=,iv:zqMw8Q4c3EOI9AEUjx148/X2VTF1UMTdacgjxyYuiyk=,tag:H72VN77/SzHMBqys8ZONGw==,type:str]
pgp:
- created_at: "2021-04-06T11:27:21Z"
enc: |

View file

@ -6,6 +6,7 @@
../../modules
./services/media.nix
./services/restic.nix
];
sbruder = {

View file

@ -1,13 +1,15 @@
wg-home-private-key: ENC[AES256_GCM,data:/RHNF6Zw6CTWa9ahUhGWRfkR8KIj+HdqUIojA1w6HQBFbZ/+Vo+CcYTYO5I=,iv:2sDH1P3VRjmLw6Ilkq0rw/hossHrNWP5uRvX9yr5fLE=,tag:KIT5GCfXuhg6RjA8+Nmtnw==,type:str]
media-sb-proxy-auth: ENC[AES256_GCM,data:hYKmrpIMotRaf47bt8LSyXT2FEUHu26SLtKCt2zh/ziFtH2empD2NTlpf+l5Q6VHW1r1RUyE0KdmNM4nZRumJ/NuP3Aa9ErGTI3qozjQk9Kl,iv:pLYZv8X76XQGBd36PjQPkiUNPR08PkIKuTqJ+mmaMcw=,tag:3PMAO3lOfT+y+1s8yJLvhA==,type:str]
restic-rclone-ssh-key: ENC[AES256_GCM,data:IOVEsH7DcrX4Lcb5Vv8Qxshyoc5jOudRbLnc+iZ2aL05wGo2aUbtDusPrZ9QeIhw/09UAdJUXW6HudtVWPnmL9UJVr1Sm+JYMUS50QCE4DcX0kVV9u5DXiESwfJ+WHAQimShQEvjJ6SCgNBoZNTHcsr95H9G6Tn0XyAM3VYcm69+rzzBN3E0ohb06SOV6JOvtgLLN1BVB+dt6p1UlBuWt5XNc6YPd2T4Erf4FkiPHVneg66hcFFFMX453Qzv/z14aKM0NlEMhMKqLTGt0fsIlwoX4Wdq1KDWGtsf6oVZygCbGiOi57Sy5PjUDys8FmCdkV5PjnRQc4c0E1ynHk79stwbQzqJr/RVe2Tmo3KFgoOOrWYENXztQ+rewYnhsJKF2eVVMtBKf9CAbcrw7UTuVnyxzb9K/NpebAugo00w+4M95lv2Y/MxKf85xdCqGAtfgCJ9eOH3ZW2MUx4m9e5TrBzcS/ewyeXvzd69SBknyvdQ7GXqht5Nf6Ed2a1zj3LUYiLy3H/0/GLZVmoAlJ86,iv:rwqEopfSJJ66yPKgrbVD8Id/CWCfIQi6FLByJZJbJUI=,tag:71J3OFgGNeJUyIZCNrFbqw==,type:str]
restic-htpasswd: ENC[AES256_GCM,data:hqZxZ1KXDUqaJ4rsz58l6Jqmhmatm65aZx7aEBlDyBUm3NQFNjyjZlK570lfOdOfJhj0ZZPFRiCENBHTpMt8sdjvsQ4M+g==,iv:Sw/7MBrOy0nIHjF+v8qP7cF1vwfwWiCicl4yl0tOBJc=,tag:3RFktMbo/oETuqVzvjzGwA==,type:str]
sops:
kms: []
gcp_kms: []
azure_kv: []
hc_vault: []
age: []
lastmodified: "2022-08-21T15:55:45Z"
mac: ENC[AES256_GCM,data:qtMmv0BfPmgoLrlIxfED7vXoIU+lU6SOXGsh1EPLQUjSnDEaWJpj3gDTEWVskgwHoBdt+jFaCw1j+nI36+6F+KQDwD58sV1/Oiw/J7J5QwePGeU1iyXmq/JwPNU4wYfe3O15tNRXkpFfv4tV/rdeFqbbh0++V4nQ5ZnDE0MlUJA=,iv:NOOSGauhsWhMrMXL81syzSpcvgGk4LVKwQ840/78MWg=,tag:GbMzBSlcSvMRJojGy6/0BA==,type:str]
lastmodified: "2022-08-25T14:16:49Z"
mac: ENC[AES256_GCM,data:e/9RK7hHX0Jft/27J5ImLxeYS9w7gdLM06/yoHOsgIdeKAzTqCUxVxyAK2JCmTA65iHybY0k8UkrjO73eC4fLUNjNOUIfWJPnEbgs4Ms0BSzRKHoEQ+OZesnaTpzg3BC8z+Y7Uq3PJ/btEFyap1sY4DR84q0oRU4og4/C+1lL7c=,iv:T8EM0HzzxIqdrl8rgfnc0edkr7QpZJWevZxHzo7HwVc=,tag:eS3bX6D0VL7HVFcXFLdk6Q==,type:str]
pgp:
- created_at: "2021-04-06T11:13:54Z"
enc: |

View file

@ -0,0 +1,61 @@
{ config, pkgs, ... }:
{
sops.secrets = {
restic-rclone-ssh-key = {
sopsFile = ../secrets.yaml;
owner = "restic-rclone";
};
restic-htpasswd = {
sopsFile = ../secrets.yaml;
owner = "restic-rclone";
};
};
users.users.restic-rclone = {
isSystemUser = true;
group = "restic-rclone";
};
users.groups.restic-rclone = { };
systemd.services."rclone-restic-server" = {
after = [ "network.target" ];
wantedBy = [ "multi-user.target" ];
serviceConfig = {
User = "restic-rclone";
SupplementaryGroups = [ "keys" ];
ExecStart = "${pkgs.rclone}/bin/rclone serve restic :sftp,user=u313368-sub4,host=u313368-sub4.your-storagebox.de,port=23,key_file=${config.sops.secrets.restic-rclone-ssh-key.path}: --private-repos --htpasswd ${config.sops.secrets.restic-htpasswd.path} --append-only";
Restart = "on-failure";
CapabilityBoundingSet = null;
LockPersonality = true;
MemoryDenyWriteExecute = true;
PrivateDevices = true;
PrivateUsers = true;
ProtectClock = true;
ProtectControlGroups = true;
ProtectHome = true;
ProtectHostname = true;
ProtectKernelLogs = true;
ProtectKernelModules = true;
ProtectKernelTunables = true;
RestrictAddressFamilies = [ "AF_INET" "AF_INET6" ];
RestrictNamespaces = true;
RestrictRealtime = true;
SystemCallArchitectures = "native";
SystemCallFilter = "@system-service";
};
};
services.nginx.virtualHosts."restic.sbruder.de" = {
enableACME = true;
forceSSL = true;
locations."/".proxyPass = "http://127.0.0.1:8080/";
extraConfig = ''
client_max_body_size 20M;
'';
};
}

View file

@ -2,7 +2,9 @@
let
cfg = config.sbruder.restic.system;
repository = "s3:https://s3.eu-central-1.wasabisys.com/sbruder-restic";
sftpTarget = "u313368-sub4@u313368-sub4.your-storagebox.de";
sftpPort = 23;
repository = "sftp://${sftpTarget}:${toString sftpPort}/personal";
excludes = [
# Caches
"/home/*/Downloads/"
@ -31,7 +33,6 @@ let
# script to use restic as user without dealing with authentication
authScript = pkgs.writeShellScriptBin "restic-auth" ''
. <(pass data/wasabi/restic-nixos | sed 's/^/export /')
${pkgs.restic}/bin/restic \
--password-command="pass data/backup/restic-nixos" \
--repo "${repository}" \
@ -67,14 +68,17 @@ in
config = lib.mkIf cfg.enable {
sops.secrets = {
restic-password = { };
restic-s3 = { };
restic-repository = { };
} // lib.optionalAttrs cfg.prune {
restic-ssh-key = {
sopsFile = ../../machines/${config.networking.hostName}/secrets.yaml;
};
};
services.restic.backups.system = {
inherit repository;
inherit (cfg) timerConfig;
repositoryFile = config.sops.secrets.restic-repository.path;
passwordFile = config.sops.secrets.restic-password.path;
environmentFile = config.sops.secrets.restic-s3.path;
paths = [
"/etc"
"/home"
@ -99,12 +103,15 @@ in
services.restic.backups.system-prune = lib.mkIf cfg.prune {
inherit repository;
passwordFile = config.sops.secrets.restic-password.path;
environmentFile = config.sops.secrets.restic-s3.path;
timerConfig = {
OnCalendar = "*-1/2-07 03:00:00";
RandomizedDelaySec = "4h";
};
paths = [ ];
extraOptions = [
"-o"
"sftp.command='ssh -i ${config.sops.secrets.restic-ssh-key.path} -p ${toString sftpPort} ${sftpTarget} -s sftp'"
];
pruneOpts = [
"--keep-daily 7"
"--keep-monthly 12"

View file

@ -2,7 +2,7 @@ media-htpasswd: ENC[AES256_GCM,data:8o+MBYaH+OoPrK2FtDzxCLXCz8oGDezIALl2KkoVlj/Z
media-proxy-auth: ENC[AES256_GCM,data:OcmYZq/tyzMB61NfyYZ8gAlEE+8w2IhlPlZ+dfedtfqVlPHk3iJsd9mvsXHf5ODTtuy00ll0MF4KYNePZkz7TeuaIdBgGlshFyE4gwsJdPXZNYnhcg==,iv:qo6SOaHrWsXfvRwgSKDTSnreOcO9xy3RKrfE2k+VLEg=,tag:14DT86PQdEuK9zyZzcAohA==,type:str]
media-ssh-key: ENC[AES256_GCM,data:cT5Jp5asgF2GZL4nn0rS4+tmli5adZjDa/G6WD/QXbOLtAjquytX63LKrLYUoTjOa7rNAjxDBIYEi90uvubKxOI0QbXACj0MSt6WbkxmosYResnFl9/WefpROctpGcDvn60fzer0K75IRBAtpAogVU7VynOkOuPa0xhTyAU8ZPOmij456UjpbtIgSg4yKVDn14jj/OZ1Oz+qd3bHC8FSQvp0jSKD9xfIizc2kb6ca3LRdR7VtJtTnJOOADRKaLC+rBywVyTOlCQBLiZ6LE9i6SmgFOdI+l6z9jE1Vi3vZ3BAe8Q/wWQ6Kjts+3+RkjPbgdjdWzxyHly/dr8lU1HcwtMHgKBV84asJBghCm6B1o48AEqd4oF9W039rCRQkR/VMb/ser0ifEjwnpDnDskrFYxWzidMKsfHGOtZxm7rzvOxSRA+Rcx9vxwa90gRsU4mBdx7QG0y3f/AbxRvVCuLLZW/y0JpCtE2B/mcObRvjsZP3RXQIS4vGAeTerd18RwsrsWO,iv:+ASa0hhWXmQ2hgJ9UuRFjnf/fA65kxWXiC+rDI6Lnx8=,tag:LDYSsN0DXAFiW0w+YBcopA==,type:str]
torrent-proxy-auth: ENC[AES256_GCM,data:4oi4uZCgslTvmso1SCedu3gKsOTCtYIAf3g1mBS6/ta3d/hd6GJ0Ns+/9w51WrhcyJQRLSR7jLlzxRzKFp6JvKXlNAeflXDqOKNfk0LXY1GKTZynOA==,iv:26d+hQ9yn5CzDGNZvi9A5bvzgo87IrJHz67xTac4UA4=,tag:e8fO5Xpu7wpDiSC4CBsaaQ==,type:str]
restic-s3: ENC[AES256_GCM,data:RXRvwIwR7EqZSKxoqSYhGIWGH3GEBagPYCdwkRh0CDSTTRHQYN280gpgQA7ef2NkWnkrwQK4FCwCu2CBaPSMO0X6OcSVNJsmBySDQqZAb8SCs6pOSn2J+kHP2n8K9Fgy9/7OeX2i,iv:yrp2QZLXJypWh5XjsAHcpiXEPUcYF8A+mQZ+W2w7zpU=,tag:XhktIlDqXeq/tLMPZpQuLA==,type:str]
restic-repository: ENC[AES256_GCM,data:5LDzTrzcNDLHvNNMGaW4C2P6fTvnushyGX/ghLP47GGktnqLUff4r+dxR0o+xebhOu/g3Rku/F0vUDPy6ajAJ8+jCfzh9Kj16SzZXESvuqlX,iv:0y7S1Y8TR/XIh57etoVl7NEW+IO1kiu0M7dnFrAP+Lw=,tag:EKZcyTJz1lYGrFUXt4AAGA==,type:str]
restic-password: ENC[AES256_GCM,data:nzbUoZgK+XP99/hPlIBm83hIDqRWlmNNNHwq0TXE9cQGTJyEmLfB6qlUdEtateG3,iv:8/WPCuGfLkd0LkLTEr7pjpT8kb/P64VICppDeEcKDIE=,tag:eytBikegC2fzCtUFh84qIw==,type:str]
sops:
kms: []
@ -10,8 +10,8 @@ sops:
azure_kv: []
hc_vault: []
age: []
lastmodified: "2022-08-22T14:22:50Z"
mac: ENC[AES256_GCM,data:jeon/GqCA40VJogcR0jBtkZyLvRvEf3dhMfGl0NdLKEQhbH1a7xWSCe+riyszv4/UU6qkm/mIbrqLY4Tjaqg++f1AO9ZbSVleahik397cdVgfxaFBYrD2Ia7rvRqNSncHbK7Kc93GV/XzB6yIJTKcEKddNLxMvSnJtlaVaETECE=,iv:irJR+d+mxp6L9bZyTRjnTl42rEZS5u5awic2uR2DLLU=,tag:H0aWDkz0hTKkR/QXb7cvzQ==,type:str]
lastmodified: "2022-08-25T14:27:39Z"
mac: ENC[AES256_GCM,data:75hpB3gQ5WhqdSG4q1w08dQ1g9QGK2PA3hqXHnRz7cosjAERyldIG9TmOATrUGLULUy+E8fnOaACCatY5aMXVL/wmn77GkI4EA658D9j3Fhm1+k/Tv+rE8+4icb+9YNVZijLpHzSlMKZVOdYyg+CZlAC/xDz6ggdZOO6Ks29N+Q=,iv:0NKHdZxKmcUNiraoBW4WldO2hHkaTDVH0sUk/lh1Xg8=,tag:mRfDetmVh0Nv/4nHjCs/5g==,type:str]
pgp:
- created_at: "2022-06-09T21:22:41Z"
enc: |