feat: auto restart foundry-vtt

This commit is contained in:
2025-09-09 10:39:45 +02:00
parent 97b6874258
commit 58089e558e
2 changed files with 89 additions and 2 deletions

View File

@@ -3,6 +3,54 @@ let
foundry-vtt = pkgs.callPackage ../pkgs/foundry-vtt {}; foundry-vtt = pkgs.callPackage ../pkgs/foundry-vtt {};
cids = import ../modules/staticids.nix; cids = import ../modules/staticids.nix;
hostConfig = config; hostConfig = config;
url = "https://foundry-vtt.cloonar.com"; # URL to check
targetService = "container@foundry-vtt.service"; # systemd unit to restart (e.g. "docker-container@myapp.service")
threshold = 3; # consecutive failures before restart
interval = "1min"; # how often to run
timeoutSeconds = 10; # curl timeout
checkUrlScript = pkgs.writeShellScript "check-foundry-up" ''
#!/usr/bin/env bash
set -euo pipefail
URL="$1"
TARGET="$2"
THRESHOLD="$3"
TIMEOUT="$4"
STATE_DIR="/run/url-watchdog"
mkdir -p "$STATE_DIR"
SAFE_TARGET="$(systemd-escape --path "$TARGET")"
STATE_FILE="$STATE_DIR/$SAFE_TARGET.count"
TMP="$(mktemp)"
# Get HTTP status; "000" if curl fails.
status="$(curl -sS -m "$TIMEOUT" -o "$TMP" -w "%{http_code}" "$URL" || echo "000")"
fail=0
if [[ "$status" == "502" || "$status" == "504" || "$status" == "000" ]]; then
fail=1
fi
count=0
if [[ -f "$STATE_FILE" ]]; then
count="$(cat "$STATE_FILE" 2>/dev/null || echo 0)"
fi
if [[ "$fail" -eq 1 ]]; then
count=$((count+1))
else
count=0
fi
if [[ "$count" -ge "$THRESHOLD" ]]; then
printf '[%s] %s failing (%s) %sx -> restarting %s\n' "$(date -Is)" "$URL" "$status" "$count" "$TARGET"
systemctl restart "$TARGET"
count=0
fi
echo "$count" > "$STATE_FILE"
rm -f "$TMP"
'';
in { in {
users.users.foundry-vtt = { users.users.foundry-vtt = {
isSystemUser = true; isSystemUser = true;
@@ -70,4 +118,45 @@ in {
system.stateVersion = "24.05"; system.stateVersion = "24.05";
}; };
}; };
systemd.services."restart-foundry-vtt" = {
description = "Restart foundry-vtt container";
serviceConfig = {
Type = "oneshot";
ExecStart = "${pkgs.systemd}/bin/systemctl restart container@foundry-vtt.service";
};
};
systemd.timers."restart-foundry-vtt" = {
wantedBy = [ "timers.target" ];
timerConfig = {
# 03:00 local time (Europe/Vienna for you)
OnCalendar = "03:00";
# If the machine was off at 03:00, run once at next boot
Persistent = true;
Unit = "restart-foundry-vtt.service";
};
};
systemd.services.foundry-vtt-watchdog = {
description = "Foundry VTT watchdog: restart ${targetService} on Nginx gateway errors";
serviceConfig = {
Type = "oneshot";
ExecStart = "${checkUrlScript} ${url} ${targetService} ${toString threshold} ${toString timeoutSeconds}";
};
# Ensure needed tools are on PATH inside the unit
path = [ pkgs.curl pkgs.coreutils pkgs.systemd ];
# Wait until networking is really up
wants = [ "network-online.target" ];
after = [ "network-online.target" ];
};
systemd.timers.foundry-vtt-watchdog = {
wantedBy = [ "timers.target" ];
timerConfig = {
OnBootSec = interval;
OnUnitActiveSec = interval;
AccuracySec = "10s";
};
};
} }

View File

@@ -41,8 +41,6 @@
service = "wake_on_lan.send_magic_packet"; service = "wake_on_lan.send_magic_packet";
data = { data = {
mac = "04:7c:16:d5:63:5e"; mac = "04:7c:16:d5:63:5e";
broadcast_address = "${config.networkPrefix}.96.5";
broadcast_port = 9;
}; };
} }
]; ];