diff --git a/README.md b/README.md index 0ff8f1a..8a31590 100644 --- a/README.md +++ b/README.md @@ -55,6 +55,7 @@ Common overrides: ``` sudo scripts/install-systemd \ --backup-root /mnt/backups/pobsync \ + --time-zone Europe/Amsterdam \ --allowed-hosts backup.example.com,localhost,127.0.0.1 \ --csrf-trusted-origins https://backup.example.com ``` @@ -64,6 +65,9 @@ installer to rewrite an existing `/etc/pobsync/pobsync.env`. Use `--non-interactive` for scripted installs. Use `--verbose` when you want to see the underlying apt, pip, Django, and systemd output. +Schedules are evaluated in `POBSYNC_TIME_ZONE`. The installer defaults this to the server timezone when it can detect +one, otherwise `UTC`; override it with `--time-zone Europe/Amsterdam` or by editing `/etc/pobsync/pobsync.env`. + For MariaDB support, add: ``` diff --git a/scripts/install-systemd b/scripts/install-systemd index e16fd2c..938d947 100755 --- a/scripts/install-systemd +++ b/scripts/install-systemd @@ -17,6 +17,7 @@ if [ -n "${POBSYNC_BACKUP_ROOT:-}" ]; then BACKUP_ROOT_EXPLICIT=1 fi WEB_BIND=${POBSYNC_WEB_BIND:-127.0.0.1:8010} +TIME_ZONE=${POBSYNC_TIME_ZONE:-} FORCE_ENV=0 INSTALL_OS_PACKAGES=1 WITH_NGINX=0 @@ -74,6 +75,10 @@ while [ "$#" -gt 0 ]; do WEB_BIND=$2 shift 2 ;; + --time-zone) + TIME_ZONE=$2 + shift 2 + ;; --force-env) FORCE_ENV=1 shift @@ -148,6 +153,38 @@ if [ -f "$ENV_FILE" ] && [ "$FORCE_ENV" -ne 1 ] && [ "$BACKUP_ROOT_EXPLICIT" -ne fi fi +detect_time_zone() { + if [ -n "$TIME_ZONE" ]; then + printf '%s\n' "$TIME_ZONE" + return + fi + + if [ -n "${POBSYNC_TIME_ZONE:-}" ]; then + printf '%s\n' "$POBSYNC_TIME_ZONE" + return + fi + + if command -v timedatectl >/dev/null 2>&1; then + detected=$(timedatectl show -p Timezone --value 2>/dev/null || true) + if [ -n "$detected" ]; then + printf '%s\n' "$detected" + return + fi + fi + + if [ -f /etc/timezone ]; then + detected=$(sed -n '1p' /etc/timezone | tr -d '[:space:]') + if [ -n "$detected" ]; then + printf '%s\n' "$detected" + return + fi + fi + + printf 'UTC\n' +} + +TIME_ZONE=$(detect_time_zone) + run_step() { label=$1 shift @@ -261,6 +298,7 @@ if [ "$INTERACTIVE" -eq 1 ]; then SERVICE_GROUP=$(prompt_value "Service group" "$SERVICE_GROUP") BACKUP_ROOT=$(prompt_value "Backup storage path" "$BACKUP_ROOT") WEB_BIND=$(prompt_value "Gunicorn bind address" "$WEB_BIND") + TIME_ZONE=$(prompt_value "Scheduler time zone" "$TIME_ZONE") ALLOWED_HOSTS=$(prompt_value "Allowed hosts" "$ALLOWED_HOSTS") CSRF_TRUSTED_ORIGINS=$(prompt_value "CSRF trusted origins, comma-separated or blank" "$CSRF_TRUSTED_ORIGINS") INSTALL_OS_PACKAGES=$(prompt_yes_no "Install required OS packages with apt-get" "$INSTALL_OS_PACKAGES") @@ -331,6 +369,12 @@ if ! command -v python3 >/dev/null 2>&1; then exit 1 fi +if ! env POBSYNC_INSTALL_TIME_ZONE="$TIME_ZONE" python3 -c "import os; from zoneinfo import ZoneInfo; ZoneInfo(os.environ['POBSYNC_INSTALL_TIME_ZONE'])" >/dev/null 2>&1; then + echo "Invalid time zone: $TIME_ZONE" >&2 + echo "Use an IANA timezone such as UTC or Europe/Amsterdam." >&2 + exit 1 +fi + if ! command -v rsync >/dev/null 2>&1; then echo "rsync is required." >&2 exit 1 @@ -416,6 +460,7 @@ POBSYNC_DJANGO_CSRF_TRUSTED_ORIGINS=$CSRF_TRUSTED_ORIGINS POBSYNC_HOME=/var/lib/pobsync POBSYNC_BACKUP_ROOT=$BACKUP_ROOT +POBSYNC_TIME_ZONE=$TIME_ZONE POBSYNC_SQLITE_PATH=/var/lib/pobsync/pobsync.sqlite3 POBSYNC_STATIC_ROOT=/var/lib/pobsync/static