Registry credentials for updates

How the in-app updater authenticates to ghcr.io, and what to do when the token expires or the registry refuses it.

For: Administrators (the admin ability) · Last updated

The application images are private packages on ghcr.io. The Docker daemon stores no registry credentials of its own. Each client sends them with every request, taken from its own Docker config file.

For the in-app updater, that file is the host's. The compose file mounts the host's Docker config directory, /root/.docker by default, read-only into the app container at /run/host-docker-config and points DOCKER_CONFIG at it. The login that install.sh made with sudo docker login ghcr.io is therefore the login that Check for updates and Install update use. If you keep the config elsewhere, set WI_DOCKER_CONFIG_DIR in .env.

Renew or replace the login#

When the token expires or is revoked, the update check and the image pull fail with an unauthorized message from the registry (the check shows it as "docker registry inspection failed for image ..."; a pull shows "failed to pull ...").

  1. Create a new classic personal access token with the read:packages scope. Fine-grained tokens do not work with GHCR.

  2. Log in on the host, always with sudo:

    echo "<your-token>" | sudo docker login ghcr.io -u <your-github-username> --password-stdin
    

    Do not log in as a different user. The login must land in /root/.docker/config.json (or in the directory WI_DOCKER_CONFIG_DIR names), because that is the directory the application reads.

  3. Restart the application so it picks up the new login:

    sudo docker compose -p wi-prod restart app
    
  4. Return to Settings → Updates and select Check for updates.

Notes#

  • The mount is a directory, not the single config.json file. docker login replaces the file by renaming it, which a single-file mount would miss.
  • The application reads plain auths entries in config.json. A host configured with a credential helper (credsStore) keeps the login outside that file, and the app container has no copy of the helper, so it cannot use that login.
  • The login also serves install.sh when you re-run it on the host. See Day-two operations.