feat: add backup for server

This commit is contained in:
danny 2025-09-28 12:37:26 +08:00
parent 20ee47caa2
commit f7409e0537
14 changed files with 256 additions and 165 deletions

View file

@ -35,6 +35,12 @@ in
./sops-conf.nix # Secret
./nginx.nix
./mail.nix
# (import ./netbird.nix {
# domain = "pre7780.dn";
# coturnPassFile = config.sops.secrets."netbird/coturn/password".path;
# idpSecret = config.sops.secrets."netbird/oidc/secret".path;
# dataStoreEncryptionKey = config.sops.secrets."netbird/dataStoreKey".path;
# })
./hardware-configuration.nix
../../modules/presets/basic.nix
@ -63,8 +69,8 @@ in
(import ../../modules/nextcloud.nix {
hostname = "nextcloud.pre7780.dn";
configureACME = false;
https = false;
configureACME = true;
https = true;
adminpassFile = config.sops.secrets."nextcloud/adminPassword".path;
trusted = [ "nextcloud.daccc.info" ];
})

View file

@ -0,0 +1,65 @@
{
domain,
idpSecret,
dataStoreEncryptionKey,
coturnPassFile,
...
}:
let
port = 51820;
in
{
services.netbird = {
server = {
enable = true;
domain = "netbird.${domain}";
enableNginx = true;
management = {
oidcConfigEndpoint = "https://keycloak.net.dn/realms/master/.well-known/openid-configuration";
settings = {
DataStoreEncryptionKey = {
_secret = dataStoreEncryptionKey;
};
TURNConfig = {
Secret = {
_secret = idpSecret;
};
};
IdpManagerConfig = {
ClientConfig = {
ClientID = "netbird-backend";
ClientSecret = {
_secret = idpSecret;
};
};
};
};
};
coturn = {
user = "netbird";
passwordFile = coturnPassFile;
enable = true;
};
dashboard.settings = {
USE_AUTH0 = false;
AUTH_AUTHORITY = "https://keycloak.net.dn/realms/master";
AUTH_CLIENT_ID = "netbird";
AUTH_AUDIENCE = "netbird";
AUTH_SUPPORTED_SCOPES = "openid profile email offline_access api";
};
};
clients.default = {
inherit port;
openFirewall = true;
name = "netbird";
interface = "wt0";
hardened = true;
dns-resolver.address = "10.0.0.1";
};
};
services.nginx.virtualHosts."netbird.${domain}" = {
enableACME = true;
forceSSL = true;
};
}

View file

@ -14,7 +14,7 @@
email = "danny@net.dn";
dnsProvider = "pdns";
dnsPropagationCheck = false;
# environmentFile = config.sops.secrets."acme/pdns".path;
environmentFile = config.sops.secrets."acme/pdns".path;
};
};

View file

@ -18,6 +18,10 @@ acme:
pdns: ENC[AES256_GCM,data:+InGSnaGIFVtDRlVltzWbZfquzodHUQrPeMRBnVNB9mrajlKr5dFK6DD8dXAvN7UjZFBfrgZefOPkmLR2ncLXGOV2Kl7jorVw50Y0f0iKl7mqwHaZKaQdk7cpGDkCrt/LvfbP9x7gVrs6pQpsU+c/P5rbBLRyejchh/WtiyzgowYIJxYohggeG09+l7YI3FR6U5wiymIRISpNBGEhwG0q17qdAhdtc49qP/K,iv:JcSlxAwHwU528S7iSpAnSbUZw7iO+LMjR3qGwRHp+Zk=,tag:twf2WOQb/yZ3GtN/hlikMA==,type:str]
cloudflare:
secret: ENC[AES256_GCM,data:tritGdt3bWm/YtfdF2kO8qIBisa2rGF9/Dpl8R79e6REe//YKZFqFg==,iv:UG53JZ55+gDCPJzKjbVaWnpgOdvqcRoDUg8ef9xOV9A=,tag:JD3s28dsA9G2fqtz4soATA==,type:str]
netbird:
oidc:
secret: ENC[AES256_GCM,data:hSVMUEBL0kCvRLD3zd57SLhNIAFOR4eaJPcIIIIUJng=,iv:VhfseftQNlXSDCWuaYQUIklMUCkUbChyWbJl3qgD75M=,tag:vbqov0VgA0XNZfzcr3FZgA==,type:str]
dataStoreKey: ENC[AES256_GCM,data:vV2wgo5qFS+DC1NmOjVddZW9HAsRMpUFH+t/70iQ3A5YXkhbWoCeSxZDyAg=,iv:tKqh28qj8gqHfcb44Ej731w6NKi29X4iEwIOQ4ZcCzA=,tag:ObAxVrUctm6pbmXSQw7j5w==,type:str]
sops:
age:
- recipient: age1uvsvf5ljaezh5wze32p685kfentyle0l2mvysc67yvgct2h4850qqph9lv
@ -29,7 +33,7 @@ sops:
MEdmWkFwNXZoR1ZVRnQ0aWlkYzZwSmsK0EFecUIdqlDKX08oRCoDQQ3QCX1wzb8w
lghDJhWlfuKr+X24GoE4UK04aJVLqVMRRI4BJW+LQXeHS+dWKu3mQA==
-----END AGE ENCRYPTED FILE-----
lastmodified: "2025-09-22T14:30:13Z"
mac: ENC[AES256_GCM,data:Ak9QKKRWDFQk9GNkk2yiN+42DB/Gj7dXmiNOna0BKRwI7gkVl+ie4Iis6jhZ2aEe1vO8rgBurcSQd9xVyFOIJa16p7L1GD1doZWn0Gq3yerIwzjtaQMoS84e/cTTiWnj9shAe+Sm7vhk3ZJzJzbpYtBTspVE+iyZ+LafIE3XSCc=,iv:j53phA/h5cqWEiEviIjgbLxcPPOGWUq+UHFG1tCWkrw=,tag:Z5fnbnE2hfeHQ74Li3EVVw==,type:str]
lastmodified: "2025-09-26T14:45:30Z"
mac: ENC[AES256_GCM,data:RAxzEJsfAY9UA15ln+uqEGoVli2oQEVP/8DrPEluQCfMYjMacbTlhIWfGXvUhFHZbY1/M0Q1IC/elY7iWqKn7Qc2VE+elTNHj+MTzp23pHUaHRo2h0kqcqnjdU1SeLNLJ5CDMp/wYyKKSeqde1UcQkhpE2sa5gnpVOd+JAJxCas=,iv:uD0qIHrI5uecUPGfOMvvcgr0NrbtTbHHxbdOX9dfDfw=,tag:FmnDi3opIobtIFI2rl+kWw==,type:str]
unencrypted_suffix: _unencrypted
version: 3.10.2

View file

@ -1,32 +1,41 @@
{ config, lib, ... }:
let
inherit (lib) optionalAttrs;
inherit (lib) optionalAttrs mkIf hasAttr;
in
{
sops = {
secrets = {
"wireguard/conf" = { };
"nextcloud/adminPassword" = lib.mkIf config.services.nextcloud.enable {
"nextcloud/adminPassword" = mkIf config.services.nextcloud.enable {
owner = "nextcloud";
group = "nextcloud";
};
"openldap/adminPassword" = lib.mkIf config.services.openldap.enable {
"openldap/adminPassword" = mkIf config.services.openldap.enable {
owner = config.users.users.openldap.name;
group = config.users.users.openldap.group;
mode = "0660";
};
"lam/env" = { };
"dovecot/openldap" = lib.mkIf (config.services.postfix.enable && config.services.openldap.enable) {
"dovecot/openldap" = mkIf (config.services.postfix.enable && config.services.openldap.enable) {
owner = config.services.dovecot2.user;
group = config.services.dovecot2.group;
mode = "0660";
};
# "acme/pdns" = {
# mode = "0660";
# owner = "acme";
# group = "acme";
# };
"netbird/oidc/secret" = mkIf config.services.netbird.server.dashboard.enable {
owner = "netbird";
};
"netbird/coturn/password" = mkIf config.services.netbird.server.coturn.enable {
owner = "turnserver";
key = "netbird/oidc/secret";
};
"netbird/dataStoreKey" = mkIf config.services.netbird.server.management.enable {
owner = "netbird";
};
"acme/pdns" = mkIf (hasAttr "acme" config.users.users) {
owner = "acme";
};
}
// (optionalAttrs config.services.stalwart-mail.enable (
let

View file

@ -0,0 +1,92 @@
{
lib,
config,
pkgs,
...
}:
let
inherit (lib) mkIf;
backupAt = "*-*-* 03:00:00";
backupPath = "/mnt/backup_dn";
backupScript = pkgs.writeShellScript "backup-nextcloud.sh" ''
nextcloudPath="${config.services.nextcloud.datadir}"
if [ ! -d "$nextcloudPath" ]; then
echo "nextcloud path not found: $nextcloudPath"
exit 1
fi
backupPath="${backupPath}"
nextcloudBakPath="$backupPath"
if [ ! -d "$backupPath" ]; then
echo "Backup device is not mounted: $backupPath"
exit 1
fi
echo "Start syncing..."
${pkgs.rsync}/bin/rsync -rh --delete "$nextcloudPath" "$nextcloudBakPath"
echo "Data dir backup completed."
'';
in
{
fileSystems."/mnt/backup_dn" = {
device = "/dev/disk/by-uuid/FBD9-F625";
fsType = "exfat";
options = [
"x-systemd.automount"
"noauto"
"x-systemd.idle-timeout=600"
"nofail"
"user"
"x-gvfs-show"
"gid=1000"
"uid=1000"
"dmask=000"
"fmask=000"
];
};
# ==== Advance Backup ==== #
# services.pgbackrest = {
# enable = true;
# repos.localhost.path = "${backupPath}/postgresql";
# };
services.postgresqlBackup = {
enable = true;
startAt = backupAt;
pgdumpOptions = "--no-owner";
databases = [
"nextcloud"
"vaultwarden"
"paperless"
];
location = "${backupPath}/postgresql";
};
systemd = mkIf config.services.nextcloud.enable {
timers = {
"nextcloud-backup" = {
enable = true;
description = "Nextcloud backup";
timerConfig = {
OnCalendar = backupAt;
Persistent = true;
OnUnitActiveSec = "1d";
AccuracySec = "1h";
Unit = "nextcloud-backup.service";
};
wantedBy = [ "timers.target" ];
};
};
services."nextcloud-backup" = {
enable = true;
serviceConfig = {
User = "nextcloud";
ExecStart = "${backupScript}";
};
};
};
}

View file

@ -1,23 +1,6 @@
{ pkgs, ... }:
{
fileSystems."/mnt/backup_dn" = {
device = "/dev/disk/by-uuid/FBD9-F625";
fsType = "exfat";
options = [
"x-systemd.automount"
"noauto"
"x-systemd.idle-timeout=600"
"nofail"
"user"
"x-gvfs-show"
"gid=1000"
"uid=1000"
"dmask=000"
"fmask=000"
];
};
boot.kernelPackages = pkgs.linuxPackages;
boot.loader.systemd-boot.enable = true;

View file

@ -18,6 +18,7 @@ in
intel-bus-id = "PCI:0:2:0";
nvidia-bus-id = "PCI:1:0:0";
})
./backup.nix
./security.nix
./sops-conf.nix
./boot.nix
@ -56,8 +57,6 @@ in
})
(import ../../modules/nextcloud.nix {
hostname = "nextcloud.net.dn";
dataBackupPath = "/mnt/backup_dn";
dbBackupPath = "/mnt/backup_dn";
adminpassFile = config.sops.secrets."nextcloud/adminPassword".path;
trusted = [ "nextcloud.daccc.info" ];
})

View file

@ -386,7 +386,7 @@ in
virtualisation = {
oci-containers = {
backend = "docker";
backend = "podman";
containers = {
uptime-kuma = {
extraOptions = [ "--network=host" ];