Update #151

Manually merged
tlater merged 2 commits from tlater/update into master 2025-08-02 11:35:01 +01:00
5 changed files with 138 additions and 141 deletions

View file

@ -20,22 +20,21 @@
''; '';
}; };
logrotate.settings = logrotate.settings = {
{ # Override the default, just keep fewer logs
# Override the default, just keep fewer logs nginx.rotate = 6;
nginx.rotate = 6; }
// lib.mapAttrs' (
virtualHost: _:
lib.nameValuePair "/var/log/nginx/${virtualHost}/access.log" {
frequency = "daily";
rotate = 2;
compress = true;
delaycompress = true;
su = "${config.services.nginx.user} ${config.services.nginx.group}";
postrotate = "[ ! -f /var/run/nginx/nginx.pid ] || kill -USR1 `cat /var/run/nginx/nginx.pid`";
} }
// lib.mapAttrs' ( ) config.services.nginx.virtualHosts;
virtualHost: _:
lib.nameValuePair "/var/log/nginx/${virtualHost}/access.log" {
frequency = "daily";
rotate = 2;
compress = true;
delaycompress = true;
su = "${config.services.nginx.user} ${config.services.nginx.group}";
postrotate = "[ ! -f /var/run/nginx/nginx.pid ] || kill -USR1 `cat /var/run/nginx/nginx.pid`";
}
) config.services.nginx.virtualHosts;
backups.acme = { backups.acme = {
user = "acme"; user = "acme";

View file

@ -140,123 +140,121 @@ in
}; };
config = lib.mkIf (config.services.backups != { }) { config = lib.mkIf (config.services.backups != { }) {
systemd.services = systemd.services = {
{ restic-prune = {
restic-prune = { # Doesn't hurt to finish the ongoing prune
# Doesn't hurt to finish the ongoing prune restartIfChanged = false;
restartIfChanged = false;
environment = resticEnv; environment = resticEnv;
path = with pkgs; [ path = with pkgs; [
openssh openssh
rclone rclone
restic restic
];
script = ''
# TODO(tlater): In an append-only setup, we should be
# careful with this; an attacker could delete backups by
# simply appending ad infinitum:
# https://restic.readthedocs.io/en/stable/060_forget.html#security-considerations-in-append-only-mode
restic forget --keep-last 3 --prune
restic check
'';
serviceConfig = {
DynamicUser = true;
Group = "backup";
CacheDirectory = "restic-prune";
CacheDirectoryMode = "0700";
};
};
}
// lib.mapAttrs' (
name: backup:
lib.nameValuePair "backup-${name}" {
# Don't want to restart mid-backup
restartIfChanged = false;
environment = resticEnv // {
RESTIC_CACHE_DIR = "%C/backup-${name}";
};
path = with pkgs; [
coreutils
openssh
rclone
restic
];
# TODO(tlater): If I ever add more than one repo, service
# shutdown/restarting will potentially break if multiple
# backups for the same service overlap. A more clever
# sentinel file with reference counts would probably solve
# this.
serviceConfig = {
User = backup.user;
Group = "backup";
RuntimeDirectory = "backup-${name}";
CacheDirectory = "backup-${name}";
CacheDirectoryMode = "0700";
PrivateTmp = true;
ExecStart = [
(lib.concatStringsSep " " (
[
"${pkgs.restic}/bin/restic"
"backup"
"--tag"
name
]
++ backup.paths
))
]; ];
script = '' ExecStartPre =
# TODO(tlater): In an append-only setup, we should be map (service: "+${mkShutdownScript service}") backup.pauseServices
# careful with this; an attacker could delete backups by ++ singleton (
# simply appending ad infinitum: writeScript "backup-${name}-repo-init" [ ] ''
# https://restic.readthedocs.io/en/stable/060_forget.html#security-considerations-in-append-only-mode restic snapshots || restic init
restic forget --keep-last 3 --prune ''
restic check )
''; ++ optional (backup.preparation.text != null) (
writeScript "backup-${name}-prepare" backup.preparation.packages backup.preparation.text
);
serviceConfig = { # TODO(tlater): Add repo pruning/checking
DynamicUser = true; ExecStopPost =
Group = "backup"; map (service: "+${mkRestartScript service}") backup.pauseServices
++ optional (backup.cleanup.text != null) (
CacheDirectory = "restic-prune"; writeScript "backup-${name}-cleanup" backup.cleanup.packages backup.cleanup.text
CacheDirectoryMode = "0700"; );
};
}; };
} }
// lib.mapAttrs' ( ) config.services.backups;
name: backup:
lib.nameValuePair "backup-${name}" {
# Don't want to restart mid-backup
restartIfChanged = false;
environment = resticEnv // { systemd.timers = {
RESTIC_CACHE_DIR = "%C/backup-${name}"; restic-prune = {
}; wantedBy = [ "timers.target" ];
timerConfig.OnCalendar = "Thursday 03:00:00 UTC";
path = with pkgs; [ # Don't make this persistent, in case the server was offline
coreutils # for a while. This job cannot run at the same time as any
openssh # of the backup jobs.
rclone };
restic }
]; // lib.mapAttrs' (
name: _:
# TODO(tlater): If I ever add more than one repo, service lib.nameValuePair "backup-${name}" {
# shutdown/restarting will potentially break if multiple wantedBy = [ "timers.target" ];
# backups for the same service overlap. A more clever timerConfig = {
# sentinel file with reference counts would probably solve OnCalendar = "Wednesday 02:30:00 UTC";
# this. RandomizedDelaySec = "1h";
serviceConfig = { FixedRandomDelay = true;
User = backup.user; Persistent = true;
Group = "backup";
RuntimeDirectory = "backup-${name}";
CacheDirectory = "backup-${name}";
CacheDirectoryMode = "0700";
PrivateTmp = true;
ExecStart = [
(lib.concatStringsSep " " (
[
"${pkgs.restic}/bin/restic"
"backup"
"--tag"
name
]
++ backup.paths
))
];
ExecStartPre =
map (service: "+${mkShutdownScript service}") backup.pauseServices
++ singleton (
writeScript "backup-${name}-repo-init" [ ] ''
restic snapshots || restic init
''
)
++ optional (backup.preparation.text != null) (
writeScript "backup-${name}-prepare" backup.preparation.packages backup.preparation.text
);
# TODO(tlater): Add repo pruning/checking
ExecStopPost =
map (service: "+${mkRestartScript service}") backup.pauseServices
++ optional (backup.cleanup.text != null) (
writeScript "backup-${name}-cleanup" backup.cleanup.packages backup.cleanup.text
);
};
}
) config.services.backups;
systemd.timers =
{
restic-prune = {
wantedBy = [ "timers.target" ];
timerConfig.OnCalendar = "Thursday 03:00:00 UTC";
# Don't make this persistent, in case the server was offline
# for a while. This job cannot run at the same time as any
# of the backup jobs.
}; };
} }
// lib.mapAttrs' ( ) config.services.backups;
name: _:
lib.nameValuePair "backup-${name}" {
wantedBy = [ "timers.target" ];
timerConfig = {
OnCalendar = "Wednesday 02:30:00 UTC";
RandomizedDelaySec = "1h";
FixedRandomDelay = true;
Persistent = true;
};
}
) config.services.backups;
users = { users = {
# This user is only used to own the ssh key, because apparently # This user is only used to own the ssh key, because apparently

View file

@ -30,11 +30,12 @@
{ {
labels.type = "nginx"; labels.type = "nginx";
filenames = filenames = [
[ "/var/log/nginx/*.log" ] "/var/log/nginx/*.log"
++ lib.mapAttrsToList ( ]
vHost: _: "/var/log/nginx/${vHost}/access.log" ++ lib.mapAttrsToList (
) config.services.nginx.virtualHosts; vHost: _: "/var/log/nginx/${vHost}/access.log"
) config.services.nginx.virtualHosts;
} }
]; ];

View file

@ -154,8 +154,7 @@ in
lib.recursiveUpdate { lib.recursiveUpdate {
inherit (scrape) job_name; inherit (scrape) job_name;
static_configs = static_configs =
scrape.static_configs scrape.static_configs ++ lib.optional (scrape.targets != [ ]) { inherit (scrape) targets; };
++ lib.optional (scrape.targets != [ ]) { inherit (scrape) targets; };
} scrape.extraSettings } scrape.extraSettings
) config.services.victoriametrics.scrapeConfigs; ) config.services.victoriametrics.scrapeConfigs;
}; };

24
flake.lock generated
View file

@ -300,11 +300,11 @@
] ]
}, },
"locked": { "locked": {
"lastModified": 1750903843, "lastModified": 1753140376,
"narHash": "sha256-Ng9+f0H5/dW+mq/XOKvB9uwvGbsuiiO6HrPdAcVglCs=", "narHash": "sha256-7lrVrE0jSvZHrxEzvnfHFE/Wkk9DDqb+mYCodI5uuB8=",
"owner": "nix-community", "owner": "nix-community",
"repo": "disko", "repo": "disko",
"rev": "83c4da299c1d7d300f8c6fd3a72ac46cb0d59aae", "rev": "545aba02960caa78a31bd9a8709a0ad4b6320a5c",
"type": "github" "type": "github"
}, },
"original": { "original": {
@ -595,11 +595,11 @@
] ]
}, },
"locked": { "locked": {
"lastModified": 1748450994, "lastModified": 1752975459,
"narHash": "sha256-BWdJ+3lPmK99kjWfBlppKSRIH0sBlT1fpUkSvlgmvoA=", "narHash": "sha256-nOr9FfazId66oneIeeH6e5eALWcu0/zPn19DqbeFGME=",
"owner": "reckenrode", "owner": "reckenrode",
"repo": "nix-foundryvtt", "repo": "nix-foundryvtt",
"rev": "d5fe29ab69176aa0c7727fa7c57889a2aa577355", "rev": "924f814523ea8c8792178ec5171ea055abaae0e4",
"type": "github" "type": "github"
}, },
"original": { "original": {
@ -746,11 +746,11 @@
}, },
"nixpkgs_2": { "nixpkgs_2": {
"locked": { "locked": {
"lastModified": 1751230698, "lastModified": 1754108423,
"narHash": "sha256-ANWE9dHPeACz3SIbUhbWZforTgfAvOS5Tg1l4yYa/B0=", "narHash": "sha256-0AhuEljFdqvY4894RArZH+mzd1Y0Wojmfq8znh0ireg=",
"owner": "nixos", "owner": "nixos",
"repo": "nixpkgs", "repo": "nixpkgs",
"rev": "e410afb41ba16a2ceeaeff85c536d35f10bbbdcf", "rev": "a41340f34fa59485a7c2017af3506b2ee1b216d8",
"type": "github" "type": "github"
}, },
"original": { "original": {
@ -1079,11 +1079,11 @@
] ]
}, },
"locked": { "locked": {
"lastModified": 1750119275, "lastModified": 1752544651,
"narHash": "sha256-Rr7Pooz9zQbhdVxux16h7URa6mA80Pb/G07T4lHvh0M=", "narHash": "sha256-GllP7cmQu7zLZTs9z0J2gIL42IZHa9CBEXwBY9szT0U=",
"owner": "Mic92", "owner": "Mic92",
"repo": "sops-nix", "repo": "sops-nix",
"rev": "77c423a03b9b2b79709ea2cb63336312e78b72e2", "rev": "2c8def626f54708a9c38a5861866660395bb3461",
"type": "github" "type": "github"
}, },
"original": { "original": {