diff --git a/.env.example b/.env.example index 8a6bee7..ec69a37 100644 --- a/.env.example +++ b/.env.example @@ -48,6 +48,11 @@ BASE_URL=http://localhost:5000 # value: BASE_PATH=/dockpull docker compose build. Leave unset for root. # BASE_PATH=/dockpull +# Timezone for the daily scan's clock. The container runs in UTC by default, so +# a "09:00" scheduled scan would fire at 09:00 UTC. Set your zone so it fires at +# your local time. Find yours at https://en.wikipedia.org/wiki/List_of_tz_database_time_zones +# TZ=Europe/London + # --- Background checks & notifications (all optional; also editable in the UI) --- # Whether the server checks for updates on a schedule. Default: true. # BACKGROUND_CHECK_ENABLED=true diff --git a/README.md b/README.md index 371dfd0..f151155 100644 --- a/README.md +++ b/README.md @@ -113,6 +113,7 @@ All config is via environment variables (see [`.env.example`](./.env.example)). | `DISCORD_WEBHOOK_URL` | — | | Discord webhook for notifications (also editable in Settings). | | `GITHUB_TOKEN` | — | | Optional read-only token; raises GitHub's 60/hr changelog/version API limit to 5000/hr. | | `SCHEDULED_CHECK_TIME` | `09:00` | | Daily local time (HH:MM) for the background scan. | +| `TZ` | `UTC` | | Container timezone the scan clock uses (e.g. `Europe/London`); UTC by default. | | `BACKGROUND_CHECK_ENABLED` | `true` | | Whether the scheduled scan runs. | | `SELF_CONTAINER_NAME` | `dockpull` | | This app's container, excluded so it can't update itself. | diff --git a/client/src/pages/SettingsPage.jsx b/client/src/pages/SettingsPage.jsx index 6758b05..81d5579 100644 --- a/client/src/pages/SettingsPage.jsx +++ b/client/src/pages/SettingsPage.jsx @@ -43,7 +43,7 @@ export default function SettingsPage() { const [testStatus, setTestStatus] = useState(''); const [health, setHealth] = useState(null); // null = unknown, true/false once checked - const [version, setVersion] = useState(''); + const [status, setStatus] = useState(null); // { version, serverLocalTime, timeZone } const loadPinned = useCallback(async () => { setPinnedError(''); @@ -82,7 +82,7 @@ export default function SettingsPage() { useEffect(() => { getStatus() - .then((s) => setVersion(s?.version || '')) + .then((s) => setStatus(s || null)) .catch(() => {}); }, []); @@ -241,8 +241,16 @@ export default function SettingsPage() {
TZ (e.g. TZ=Europe/London).
+ >
+ ) : (
+ '.'
+ )}
- DockPull{version ? v{version} : null} + DockPull{status?.version ? v{status.version} : null}
A small dashboard for checking your containers' images for updates and applying diff --git a/docker-compose.yml b/docker-compose.yml index 050d215..9480189 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -11,6 +11,10 @@ services: - ADMIN_PASSWORD=${ADMIN_PASSWORD} - SESSION_SECRET=${SESSION_SECRET} - STACKS_DIR=${STACKS_DIR} + # Timezone for the daily scan's clock. The container is UTC by default, + # so a "09:00" scan would otherwise run at 09:00 UTC. Set TZ in your .env, + # e.g. TZ=Europe/London. + - TZ=${TZ:-UTC} volumes: # Required so dockerode/the docker CLI inside the container can talk # to the host's Docker daemon. diff --git a/server/src/routes/api.js b/server/src/routes/api.js index faf829f..cd3c637 100644 --- a/server/src/routes/api.js +++ b/server/src/routes/api.js @@ -35,9 +35,24 @@ const APP_VERSION = (() => { } })(); -// App status: version + last check summary (for "last checked" + error count). +// App status: version, last check summary, and the server's current time + +// timezone (the daily scan runs on this clock — helps diagnose UTC offsets). apiRouter.get('/api/status', (req, res) => { - return res.status(200).json({ version: APP_VERSION, lastCheck: db.getMeta('lastCheck') }); + const now = new Date(); + let timeZone = 'UTC'; + try { + timeZone = Intl.DateTimeFormat().resolvedOptions().timeZone || 'UTC'; + } catch { + // fall back to UTC label + } + return res.status(200).json({ + version: APP_VERSION, + lastCheck: db.getMeta('lastCheck'), + serverTime: now.toISOString(), + timeZone, + // Local HH:MM as the server sees it (what the scheduled scan compares to). + serverLocalTime: `${String(now.getHours()).padStart(2, '0')}:${String(now.getMinutes()).padStart(2, '0')}`, + }); }); /**