Deployment · s5w

Operations

Updates, backups, monitoring and troubleshooting — everything you need after the first start.

Updating

An update is a new image on the same volume. Data, tokens and links are kept.

bash
docker compose pull
docker compose up -d

Or without compose:

bash
docker pull flytachi/s5w:latest
docker stop -t 45 s5w && docker rm s5w
docker run -d --name s5w … flytachi/s5w:latest   # the same command, the same volume
  • Make a backup before updating — see below.
  • Pin the version in production (flytachi/s5w:<version>, not latest): that way an update happens when you decide, not on an accidental pull.
  • Read the release notes — they describe what changes for those who update. For moving from 1.0.x there is a separate page.

Schema migrations

Tables are created on the first start, when the database is empty. An update does not change the schema by itself: call db migrate creates missing tables but does not alter existing ones. If a release needs a schema change, its notes will include the exact command.

Backup

The whole state of the service is in the /var/lib/s5w volume: the database, the files and the signing key. A copy of the volume is a complete copy of the service.

  1. Stop the container
    bash
    docker stop -t 45 s5w

    A copy of a running volume may be inconsistent: the database and the files on disk change independently. Stopping takes a few seconds.

  2. Copy the volume into an archive
    bash
    docker run --rm \
      -v s5w_data:/data:ro \
      -v "$PWD":/backup \
      --entrypoint tar flytachi/s5w:latest \
      czf /backup/s5w-$(date +%F).tar.gz -C /data .
  3. Start the container
    bash
    docker start s5w

If the volume is mounted as a host directory (/srv/s5w), any directory copying tool works instead of the second step — tar, rsync, a filesystem snapshot — while the container is stopped.

The archive is everything

The archive holds every file of every bucket and the WINTER_KEY signing key. Keep it as safely as the data itself, and not next to the server.

Database copy without stopping

As an extra safeguard, the metadata can be dumped on the fly:

bash
docker exec s5w pg_dump -U s5w -h /run/postgresql -Fc s5w > s5w-db-$(date +%F).dump

This is a copy of the database only. A full restore is done from a copy of the volume.

Restore

  1. Create a volume and unpack the archive into it
    bash
    docker volume create s5w_data
    docker run --rm \
      -v s5w_data:/data \
      -v "$PWD":/backup:ro \
      --entrypoint tar flytachi/s5w:latest \
      xzpf /backup/s5w-2026-11-08.tar.gz -C /data

    The p flag keeps owners and permissions: the database directory requires them.

  2. Start the container on this volume

    With the same command as usual. The service comes up with the same buckets, files, tokens and temporary links: the signing key is restored together with the volume.

Moving to another server is the same: an archive from one server, a restore on the other.

Healthcheck

There is no dedicated health endpoint. The sign that the application accepts requests is that GET /v1/check without a token answers 401.

docker-compose.yml
services:
  s5w:
    # …
    healthcheck:
      test: ["CMD-SHELL", "test \"$$(curl -s -o /dev/null -w %{http_code} http://127.0.0.1:9090/v1/check)\" = 401"]
      interval: 30s
      timeout: 5s
      start_period: 30s
      retries: 3

Do not use curl -f

curl -f treats 401 as an error, and the healthcheck will always be red. Compare the response code instead.

Database readiness separately:

bash
docker exec s5w pg_isready -h /run/postgresql -U s5w

Monitoring

What to watch How Why
The container is alive the healthcheck above the API and delivery respond
Free space on the volume host disk metric when it fills up, uploads get 507 and the database stops
Application parts call app status crashes and restarts are visible
Errors in the log docker logs, level error processing failures, disk problems
Bucket quotas the panel, “Overview” a bucket at its limit starts rejecting uploads (413)
bash
docker exec s5w su-exec winter php call app status

The command shows every part — HTTP, scheduler, panel — with its state, PID, uptime and restart count. A growing restart count is a reason to look at the log.

Logs

bash
docker logs -f s5w              # everything: application, PostgreSQL, supervisor
docker logs --since 1h s5w      # the last hour

Every part writes to the container output, which Docker and any log collector pick up. The level is set by LOG_LEVEL — see Configuration.

Maintenance commands

bash
docker exec -it s5w sh                                     # shell in the container
docker exec s5w su-exec winter php call app status        # state of the parts
docker exec -it s5w psql -U s5w -h /run/postgresql s5w     # psql into the bundled database
docker exec s5w su-exec winter php call db migrate         # create missing tables

Application commands run as the winter user — hence su-exec winter.

Scheduled maintenance (retention, cleanup, space recalculation) runs inside the container by itself — no separate cron is needed. The list of tasks is in the architecture.

Common problems

Symptom Cause What to do
Cannot sign in to the panel, login fails with the right password ADMIN_LOGIN / ADMIN_PASSWORD are not set Set both variables and recreate the container
Login answers 429 Five failed attempts within 15 minutes Wait 5 minutes (Retry-After)
/admin/… answers 404 from outside The admin API is in local mode That is by design; for scripts — ADMIN_API=public
Links in the panel point to the panel domain PUBLIC_BASE_URL is not set Set the address of the API domain
Upload through the proxy — 413 with an HTML page The proxy’s request body limit Raise the limit to 32 MiB
Upload — 413 with JSON The bucket quota, or a file over 32 MiB in one request Raise the quota or upload in chunks
Chunked upload — 507 Less than 512 MiB of reserve on disk Free up space
After a stop the database takes long to start Docker killed it too early --stop-timeout 45 / stop_grace_period: 45s
Temporary links suddenly stopped working WINTER_KEY changed, or a new volume Bring back the key or the volume; otherwise issue the links again
All data is gone after an update The volume was not mounted Restore from a backup; mount the volume