dockerDocker setup

Run CrossWatch in Docker and persist state by mounting /config.

Run CrossWatch (CW) in Docker. Always persist /config.

Expose 8787.

Use either a Docker volume or a bind mount for /config.

Both options work fine.

If you use Portainer or a NAS container UI, use these same values.

circle-info

We do not provide support for installing or troubleshooting container runtimes.

These pages assume Docker (or your NAS container manager) is already installed and working.

If Docker itself is broken, use your platform docs first.

Which should I use?

Both options are perfectly fine.

Pick the one that fits your setup.

Pick a Docker volume if you want:

  • the simplest setup

  • Docker to manage storage for you

Pick a bind mount if you want:

  • files in a known host path

  • a NAS share or fixed folder layout

circle-info

Quick rule:

  • Use a Docker volume for simpler Docker-managed storage

  • Use a bind mount for a specific host folder

circle-exclamation

Before you run

  • Pick one storage type for /config.

    • Docker volume: crosswatch_config

    • Bind mount: /srv/crosswatch/config

  • Decide which port to expose.

    • Default UI port: 8787

  • Set your timezone.

    • Example: TZ=Europe/Amsterdam

circle-exclamation

Health check

CW exposes GET /healthz.

Expected response:

It returns success when the app is ready.

The default examples below stay minimal.

If you want container health status, use the separate examples later on this page.

Option A: Docker volume

Create the volume once:

Run CW:

Open http://localhost:8787.

Option B: Bind mount

Create a host directory first (below is just an example!):

circle-exclamation

Run CW:

Open http://localhost:8787.

Optional: Docker health check

Use this if you want Docker to mark the container as healthy or unhealthy.

It polls http://127.0.0.1:8787/healthz.

Defaults used below:

  • interval: 30s

  • timeout: 5s

  • retries: 3

  • start period: 20s

Docker volume + health check

Bind mount + health check

Optional environment variables

You normally only need TZ.

Override these only if you know why:

  • TZ — container timezone (used for timestamps in logs and the UI).

  • CONFIG_BASE — base path for config.json, state.json, statistics.json, etc.

    • Default: /config (leave as-is)

  • WEB_HOST — bind address for the web UI inside the container.

    • Default: 0.0.0.0

  • WEB_PORT — port for the web UI inside the container.

    • Default: 8787

  • APP_USER — username created inside the container that runs CW.

    • Default: appuser

  • APP_GROUP — group name created inside the container.

    • Default: appuser

  • APP_UID — numeric UID used for APP_USER (helps match your host user).

    • Default: 1000

  • APP_GID — numeric GID used for APP_GROUP.

    • Default: 1000

  • APP_DIR — application directory inside the container.

    • Default: /app (leave as-is)

  • RUNTIME_DIR — runtime/config directory used by the entrypoint.

    • Default: /config (leave as-is)

  • CW_RESET_AUTH_ONCE — one-time UI auth recovery flag.

    • Set to 1 to clear stored auth and sessions on next start.

    • Remove it after the reset completes.

  • RELOAD — enable Python auto-reload for development.

    • Default: no (set to yes for dev only)

circle-info

Use an IANA timezone name (like Europe/Amsterdam), not a GMT offset.

Troubleshooting

UI does not load

  • Confirm the container is running: docker ps

  • Check logs: docker logs crosswatch --tail 200

  • Confirm the port mapping matches the URL you open.

    • Example: -p 8787:8787 -> http://localhost:8787

/config is not writable

This happens most often with bind mounts.

  • Check the host directory exists.

  • Check the container user can write to it.

  • Align the host directory owner with APP_UID and APP_GID.

  • On NAS platforms, also verify the shared folder ACLs.

Next steps

Last updated

Was this helpful?