Release Workflow

Use test branches, test GHCR images, and stable tags without moving latest too early.

Release Workflow

Use this workflow to keep stable releases and nightly builds in separate GHCR packages while still getting automatic nightly and branch images for testing.

v0.2.2 Release Notes

v0.2.2 is a security and deployment-focused release. It adds the single-binary build and loopback-only development mode, refactors browsing/streaming and uploads, fixes upload finalization races, and adds stronger mount, job, preview, authentication, and container isolation.

Before upgrading, read the security guide and update deployment configuration:

  • Configure every user with a bcrypt password hash.
  • Set a non-placeholder BOXBOX_JWT_SECRET of at least 32 bytes.
  • Ensure bind mounts are accessible to the default UID/GID 10001:10001, or set PUID and PGID.
  • Do not expect the old host-root mount; it is removed by default and requires explicit allow_root_mount: true.
  • Existing browser sessions must authenticate again because refresh tokens moved to an HttpOnly cookie.

The stable Docker workflow runs from the v0.2.2 tag and publishes:

ghcr.io/jr4dh3y/boxbox:v0.2.2
ghcr.io/jr4dh3y/boxbox:latest

To update an existing deployment after the image is published:

BOXBOX_IMAGE=ghcr.io/jr4dh3y/boxbox:v0.2.2 docker compose pull
BOXBOX_IMAGE=ghcr.io/jr4dh3y/boxbox:v0.2.2 docker compose up -d

v0.2.0 Upgrade Notes

BoxBox v0.2.0 keeps old FileManager deployment names working so upgrades do not hard-break existing servers. The old names are deprecated and should be renamed before a future breaking release.

Environment variables using the old FM_ prefix still work in v0.2.0, but the matching BOXBOX_ variable always takes precedence when both are set:

Deprecated Use instead
FM_JWT_SECRET BOXBOX_JWT_SECRET
FM_USERS_<username> BOXBOX_USERS_<username>
FM_RATE_LIMIT_RPS BOXBOX_RATE_LIMIT_RPS
FM_ALLOWED_ORIGINS BOXBOX_ALLOWED_ORIGINS
FM_PORT BOXBOX_PORT
FM_HOST BOXBOX_HOST
FM_MAX_UPLOAD_MB BOXBOX_MAX_UPLOAD_MB
FM_CHUNK_SIZE_MB BOXBOX_CHUNK_SIZE_MB

The old /etc/filemanager/config.yaml path also still works as a fallback, but move it to /etc/boxbox/config.yaml.

Run the check-only migration helper from a repository checkout to inspect a deployment directory:

scripts/check-0.2-migration.sh

The script does not edit .env, rewrite Compose files, stop containers, or change Docker volumes. It exits 0 when no legacy settings are found, 2 when migration work is detected, and 1 only for script/runtime errors.

If you used old Docker named volumes, copy them manually only when you are ready to switch Compose to the new names. Docker Compose may prefix volume names with the project name; use scripts/check-0.2-migration.sh to print the actual volume names on your host.

docker compose down

docker volume create boxbox-data
docker run --rm \
  -v filemanager-data:/from:ro \
  -v boxbox-data:/to \
  alpine sh -c 'cd /from && cp -a . /to'

docker volume create boxbox-temp
docker run --rm \
  -v filemanager-temp:/from:ro \
  -v boxbox-temp:/to \
  alpine sh -c 'cd /from && cp -a . /to'

docker compose up -d

Old filemanager-* volumes are not deleted. Do not start with the new Compose volume names unless every needed copy command succeeds. If a copy fails, the old filemanager-* volume remains the source of truth; the new boxbox-* target may be partial, so remove and recreate the partial target or copy into a fresh target before starting the new Compose config.

Rollback is still changing BOXBOX_IMAGE to the last known-good tag, then pulling and restarting.

Test Branch Model

  • Do normal development on a branch, not on master.
  • Use test/* when you want GitHub to build a clearly unstable test image for that branch.
  • The nightly workflow checks master once per day and publishes only when it changed since the last successful nightly.
  • Public releases come from v* tags. Stable tags such as v0.2.0 update latest; optional prerelease tags such as v0.2.0-rc.1 do not.
  • Keep master protected in GitHub so changes land through pull requests after CI passes.

Nightly Channel

At 02:00 Asia/Kolkata each day, the nightly workflow checks the newest commit on master. If that commit has not already had a successful nightly run, it publishes these multi-platform images:

ghcr.io/jr4dh3y/boxbox-nightly:latest
ghcr.io/jr4dh3y/boxbox-nightly:<full-commit-sha>

Nightly is a dedicated GHCR package, not a tag in the stable ghcr.io/jr4dh3y/boxbox package. Use boxbox-nightly:latest to follow the newest development build. Use the commit-specific tag when you need a reproducible deployment or want to roll back after a later nightly breaks. The Nightly workflow does not update the stable package, and the release workflow does not update the Nightly package.

BOXBOX_IMAGE=ghcr.io/jr4dh3y/boxbox-nightly:latest docker compose pull
BOXBOX_IMAGE=ghcr.io/jr4dh3y/boxbox-nightly:latest docker compose up -d

The workflow can also be run manually for master from the GitHub Actions page. Manual runs always rebuild, even when the commit has already been published. Concurrent runs are cancelled so the rolling tag converges on a single build.

1. Work on a Test Branch

git switch -c test/my-change
# edit, commit, and push as usual
git push -u origin test/my-change

Pushing a test/* branch runs:

  • CI Validation: Go tests, Svelte check/build, website build, and Docker build validation.
  • Branch Test Docker Image: publishes GHCR tags for that branch and commit without touching latest.

For test/my-change, the branch image tag is:

ghcr.io/jr4dh3y/boxbox-branch:branch-test-my-change

Branch images are a dedicated GHCR package, like nightly, so test builds never touch the stable boxbox package.

The workflow also publishes a sha-<short-sha> tag for immutable testing.

2. Test the GitHub-built Image on Your Server

On the server, point Compose at the branch image:

BOXBOX_IMAGE=ghcr.io/jr4dh3y/boxbox-branch:branch-test-my-change docker compose pull
BOXBOX_IMAGE=ghcr.io/jr4dh3y/boxbox-branch:branch-test-my-change docker compose up -d

Or edit .env and keep the tag there while testing:

BOXBOX_IMAGE=ghcr.io/jr4dh3y/boxbox-branch:branch-test-my-change

Then run:

docker compose pull
docker compose up -d
docker compose ps
docker compose logs -f boxbox

Rollback is just changing BOXBOX_IMAGE back to ghcr.io/jr4dh3y/boxbox:latest or the last known-good version tag, then pulling and restarting.

3. Merge Through a Pull Request

Open a pull request into master. The PR template asks for the release-safety checks that matter for a self-hosted app: upgrade impact, rollback, storage, permissions, Docker image behavior, docs, and verification.

Recommended GitHub branch protection for master after these workflows are on the default branch:

  • Require a pull request before merging.
  • Require the CI Validation checks to pass.
  • Require branches to be up to date before merging.
  • Block force pushes and branch deletion.
  • Include administrators if you want the same rules for maintainers.

4. Ship a Stable Release

When the tested change is merged into master, tag the release:

git switch master
git pull
git tag v0.2.0
git push origin v0.2.0

The release workflow runs the preflight again, publishes the version tags, and updates:

ghcr.io/jr4dh3y/boxbox:latest

Use a new patch tag if you need a hotfix. Do not retag an already-published version.

Optional: Versioned Prerelease

You do not need prerelease tags for normal testing because test/* branch images already cover that. Use a prerelease only if you want a named image for other people to test before a stable release:

git tag v0.2.0-rc.1
git push origin v0.2.0-rc.1

That publishes ghcr.io/jr4dh3y/boxbox:v0.2.0-rc.1 but does not update latest.