fix(docker): skip locally built images on update; auto-update switch moves to env #74

Manually merged
julian merged 0 commits from fix/docker-buildable-and-autoupdate-ui into main 2026-10-28 01:06:46 +01:00
Owner

Problem

  1. Stack update fails on a service that is built locally. Paperless has sftp: { build: ./sftp, image: paperless-sftp:local }. The update ran docker compose up -d --pull always, which asks Docker Hub for paperless-sftp:local, so the whole stack failed with pull access denied for paperless-sftp, repository does not exist. pull_policy: build does not help, because the CLI flag overrides it.
  2. Auto-update was off, and nothing on the page said so. A service labelled opsdeck.auto-update: "true" showed a green "auto 02:00-05:00" badge, but the docker:auto-update schedule was disabled and had never run. That is why caddy was never updated. On top of that, the schedule was redeclared with enabled: false on every boot, so turning it on in the UI only lasted until the next restart.

Commits

  • 27abb0b fix(docker): an image built here no longer fails the stack update
  • 970e442 feat(docker): show when auto-update is opted in but switched off
  • e569376 feat(docker)!: turn auto-update on from the deployment, not the page

Changes

  • composeUp with pull now runs compose pull --ignore-buildable [-- service] first, then compose up -d without --pull. Stack updates, single-container updates and auto-update all go through this path. composeArgs no longer emits --pull always.
  • The master switch for auto-update is now the env var OPSDECK_MOD_DOCKER_AUTO_UPDATE.
    • true, 1, yes or on turns it on. Anything else, or unset, means off.
    • The schedule is redeclared from the env var on every boot, so the env var is the only source of truth.
    • POST /auto-update and the on/off actions in the UI schema are removed.
  • Stacks page:
    • A read-only "auto-update on/off" badge replaces the checkbox.
    • When auto-update is on, the page shows "last run X ago · status" or "never ran".
    • When it is off, opted-in services show a neutral badge reading "· globally off", with a tooltip that names the env var.
    • The help modal has a new step 1 that explains how to set the env var in OpsDeck's compose file.
  • Docs: AUTO_UPDATE is added to docs/configuration.md, and CLAUDE.md and the code comments are updated.

⚠️ Breaking change

Set OPSDECK_MOD_DOCKER_AUTO_UPDATE=true in the deployment to keep auto-update running.

Notes

  • pull --ignore-buildable needs compose v2.12 or newer.
  • A service-scoped update no longer pulls the service's dependencies. They still start, but they are not refreshed.
  • The prune schedules (/storage/schedules/:name) and core's /schedules/:id/enabled still store their enabled flag in the app's database. They are candidates for the same move to env vars in a follow-up.

Verification

  • deno task test for the docker module: 1049 tests passed, 0 failed.
  • deno task check, check:svelte, deno lint and deno fmt are clean.
  • Checked the off state and the on state (with the env var set) in a browser using fake data.

🤖 Generated with Claude Code

## Problem 1. **Stack update fails on a service that is built locally.** Paperless has `sftp: { build: ./sftp, image: paperless-sftp:local }`. The update ran `docker compose up -d --pull always`, which asks Docker Hub for `paperless-sftp:local`, so the whole stack failed with `pull access denied for paperless-sftp, repository does not exist`. `pull_policy: build` does not help, because the CLI flag overrides it. 2. **Auto-update was off, and nothing on the page said so.** A service labelled `opsdeck.auto-update: "true"` showed a green "auto 02:00-05:00" badge, but the `docker:auto-update` schedule was disabled and had never run. That is why caddy was never updated. On top of that, the schedule was redeclared with `enabled: false` on every boot, so turning it on in the UI only lasted until the next restart. ## Commits - `27abb0b` fix(docker): an image built here no longer fails the stack update - `970e442` feat(docker): show when auto-update is opted in but switched off - `e569376` feat(docker)!: turn auto-update on from the deployment, not the page ## Changes - `composeUp` with `pull` now runs `compose pull --ignore-buildable [-- service]` first, then `compose up -d` without `--pull`. Stack updates, single-container updates and auto-update all go through this path. `composeArgs` no longer emits `--pull always`. - **The master switch for auto-update is now the env var `OPSDECK_MOD_DOCKER_AUTO_UPDATE`.** - `true`, `1`, `yes` or `on` turns it on. Anything else, or unset, means off. - The schedule is redeclared from the env var on every boot, so the env var is the only source of truth. - `POST /auto-update` and the on/off actions in the UI schema are removed. - Stacks page: - A read-only "auto-update on/off" badge replaces the checkbox. - When auto-update is on, the page shows "last run X ago · status" or "never ran". - When it is off, opted-in services show a neutral badge reading "· globally off", with a tooltip that names the env var. - The help modal has a new step 1 that explains how to set the env var in OpsDeck's compose file. - Docs: `AUTO_UPDATE` is added to `docs/configuration.md`, and CLAUDE.md and the code comments are updated. ## ⚠️ Breaking change Set `OPSDECK_MOD_DOCKER_AUTO_UPDATE=true` in the deployment to keep auto-update running. ## Notes - `pull --ignore-buildable` needs compose v2.12 or newer. - A service-scoped update no longer pulls the service's dependencies. They still start, but they are not refreshed. - The prune schedules (`/storage/schedules/:name`) and core's `/schedules/:id/enabled` still store their enabled flag in the app's database. They are candidates for the same move to env vars in a follow-up. ## Verification - `deno task test` for the docker module: 1049 tests passed, 0 failed. - `deno task check`, `check:svelte`, `deno lint` and `deno fmt` are clean. - Checked the off state and the on state (with the env var set) in a browser using fake data. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
`docker compose up -d --pull always` has no way to skip a service whose
image comes from a `build:` section with a local tag (`app:local`). It
asks a registry for that tag and the whole project update dies on
"pull access denied for paperless-sftp, repository does not exist".
`pull_policy: build` in the compose file does not help either: the CLI
flag overrides it.

The pull is now its own step, `compose pull --ignore-buildable`, followed
by `compose up -d` without `--pull`. Same images pulled for every other
service, same recreate, and a built service is left as it is. Applies to
stack and container updates and therefore to auto-update.
feat(docker): show when auto-update is opted in but switched off
All checks were successful
Build and Deploy / verify (pull_request) Successful in 1m49s
Build and Deploy / build (pull_request) Has been skipped
Dependency Check / dependencies (pull_request) Successful in 1m16s
970e442a30
A service labelled `opsdeck.auto-update` got a green "auto 02:00-05:00"
badge whether or not the master switch was on. The switch ships off, so
a server could carry the label for weeks, look enrolled on every visit,
and never run once.

With the switch off the badge turns neutral, reads "· switch off" and
says on hover why nothing runs. With it on, the toggle now also says
when the schedule last ran and how that ended, or "never ran".
feat(docker)!: turn auto-update on from the deployment, not the page
All checks were successful
Build and Deploy / verify (pull_request) Successful in 1m49s
Build and Deploy / build (pull_request) Has been skipped
Dependency Check / dependencies (pull_request) Successful in 1m11s
e5693767a8
The master switch for unattended updates is now the env var
OPSDECK_MOD_DOCKER_AUTO_UPDATE (true/1/yes/on; anything else is off).
Settings belong in the deployment, where they are reviewed and survive
a lost data dir, not in a row the UI can flip.

The schedule was already redeclared with `enabled: false` on every boot,
so the page toggle never survived a restart anyway. Declaring it with
the env value makes the env the single source of truth.

- drop POST /auto-update and the schema's on/off actions
- the Stacks page shows a read-only "auto-update on/off" badge; its
  tooltip and the help modal name the env var
- the per-service badge reads "globally off" when the env is unset
- document AUTO_UPDATE in docs/configuration.md

BREAKING CHANGE: an install that had auto-update switched on in the UI
must set OPSDECK_MOD_DOCKER_AUTO_UPDATE=true in its deployment.
thisilike changed title from fix(docker): skip locally built images on update; show when auto-update is switched off to fix(docker): skip locally built images on update; auto-update switch moves to env 2026-10-19 08:49:31 +02:00
Merge branch 'main' into fix/docker-buildable-and-autoupdate-ui
All checks were successful
Build and Deploy / verify (pull_request) Successful in 1m31s
Build and Deploy / build (pull_request) Has been skipped
Dependency Check / dependencies (pull_request) Successful in 1m11s
cc178ef9b5
#73 added a busy guard to toggleAuto in StacksPage.svelte; this branch
deletes toggleAuto along with POST /auto-update, so the deletion stands.
Author
Owner

Merged main into this branch (cc178ef) to resolve a conflict caused by #73 landing.

The conflict was in StacksPage.svelte. #73 added a busy guard to toggleAuto, but this PR deletes toggleAuto together with POST /auto-update, so I kept the deletion. Nothing else conflicted.

After the merge:

  • Docker module: 658 passed, 0 failed
  • packages/server/tests: 188 passed
  • deno task check, check:svelte (0 errors), deno lint and deno fmt --check: clean

The review request to @julian still stands.

Merged `main` into this branch (`cc178ef`) to resolve a conflict caused by #73 landing. The conflict was in `StacksPage.svelte`. #73 added a busy guard to `toggleAuto`, but this PR deletes `toggleAuto` together with `POST /auto-update`, so I kept the deletion. Nothing else conflicted. After the merge: - Docker module: 658 passed, 0 failed - `packages/server/tests`: 188 passed - `deno task check`, `check:svelte` (0 errors), `deno lint` and `deno fmt --check`: clean The review request to @julian still stands.
fix(docker): log when the env turns off a page-enabled auto-update
All checks were successful
Build and Deploy / verify (pull_request) Successful in 1m22s
Build and Deploy / build (pull_request) Has been skipped
Dependency Check / dependencies (pull_request) Successful in 55s
2577d3c49d
An operator who switched auto-update on from the page finds it off after
this release unless OPSDECK_MOD_DOCKER_AUTO_UPDATE is set. Read the
remembered row before the declaration overwrites it and warn, so the log
says why updates stopped.

Also list every value the AUTO_UPDATE switch accepts in the docs.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
julian manually merged commit a3abacf7f7 into main 2026-10-28 01:06:46 +01:00
Sign in to join this conversation.
No reviewers
No labels
No milestone
No assignees
2 participants
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
OpsDeck/core!74
No description provided.