feat(config): TZ + NTP_SERVER in .env mit sinnvollen Defaults

- .env / .env.example: TZ=Europe/Berlin und NTP_SERVER=ptbtime1.ptb.de
  (offizielle deutsche Zeitreferenz, hohe Verfuegbarkeit)
- app/__init__.py setzt prozessweite Zeitzone frueh via os.environ+tzset
- Leichtgewichtiger SNTP-Client (pure socket, keine deps) prueft den
  Uhr-Offset beim Start im Hintergrund-Thread und warnt bei Abweichung >5s
- Dockerfile installiert tzdata und ENV TZ=Europe/Berlin als Fallback

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
Stefan Hacker
2026-04-14 15:15:57 +02:00
parent ba3e619963
commit dca064427e
5 changed files with 104 additions and 0 deletions
+29
View File
@@ -1,4 +1,5 @@
import os
import time
from pathlib import Path
from flask import Flask, Response, redirect, send_from_directory
@@ -8,6 +9,20 @@ from app.config import Config
from app.extensions import db, bcrypt, migrate
def _configure_timezone(tz_name: str) -> None:
"""Prozess-Zeitzone setzen, sodass datetime.now(), strftime %Z etc.
die konfigurierte TZ verwenden. Sichere no-op wenn tzdata fehlt."""
if not tz_name:
return
os.environ['TZ'] = tz_name
tzset = getattr(time, 'tzset', None)
if tzset:
try:
tzset()
except Exception:
pass
def _auto_migrate(db):
"""Add missing columns to existing tables by comparing model definitions
with actual database schema. This handles the case where new columns are
@@ -61,6 +76,9 @@ def _auto_migrate(db):
def create_app(config_class=Config):
# Zeitzone moeglichst frueh setzen - vor allen datetime.now()-Aufrufen
_configure_timezone(getattr(config_class, 'TIMEZONE', None) or os.environ.get('TZ'))
# Check if static frontend build exists (Docker production mode)
static_dir = Path(__file__).resolve().parent.parent / 'static'
if static_dir.exists():
@@ -171,4 +189,15 @@ def create_app(config_class=Config):
from app.services.backup_scheduler import start_backup_scheduler
start_backup_scheduler(app)
# NTP-Offset gegen den konfigurierten Zeitserver pruefen (nicht fatal).
ntp_server = app.config.get('NTP_SERVER') or ''
if ntp_server.strip():
import threading
from app.services.ntp_check import check_and_log
threading.Thread(
target=check_and_log,
args=(ntp_server.strip(), app.logger),
daemon=True,
).start()
return app