Dashboard-enabled container

Copy Markdown View Source

The tay image is the operational runtime with the optional web UI included. It owns the Store and starts exactly one Tay Engine. It also exposes the same Executor Protocol v1 Unix socket as the headless image, so external workers connect in the same way.

browser -> HTTP :4000 -> Phoenix LiveView -> Tay public API
                                               |
worker  -> /run/tay/tay.sock -> Executor API -> Engine -> /var/lib/tay/store

It is not a dashboard sidecar. Set TAY_ENABLE_DASHBOARD=true on the one Tay container that owns /var/lib/tay; Tay is deliberately single-writer.

Compose quick start

The repository example starts the dashboard-enabled runtime. A local Python socket worker is available through the local-worker profile:

TAY_ENABLE_DASHBOARD=true docker compose up --build

Open http://localhost:4000/tay. The example binds HTTP to host loopback and does not enable application-level authentication. Set TAY_DASHBOARD_HTTP_PORT to change only the published host port in this Compose example; the container continues listening on port 4000.

TAY_DASHBOARD_SECRET_KEY_BASE remains required because Phoenix uses it to sign browser sessions. Supply a random value without editing the Compose file:

export TAY_DASHBOARD_SECRET_KEY_BASE="$(openssl rand -base64 48)"
TAY_ENABLE_DASHBOARD=true docker compose up -d

To additionally enable built-in HTTP Basic authentication, provide both credentials:

export TAY_DASHBOARD_USERNAME=operator
export TAY_DASHBOARD_PASSWORD='replace-with-a-long-random-password'
TAY_ENABLE_DASHBOARD=true docker compose up -d

Pin TAY_IMAGE to an immutable release tag in production. Local workers can share the taysocket volume; remote workers use the mTLS HTTP endpoint.

Run without Compose

Create the two volumes once:

docker volume create taydata
docker volume create taysocket

Then start the release:

docker run --name tay \
  --read-only \
  --tmpfs /tmp:rw,noexec,nosuid,size=64m,uid=10001,gid=10001,mode=0700 \
  --cap-drop ALL \
  --security-opt no-new-privileges \
  -p 127.0.0.1:4000:4000 \
  -e TAY_DATA_DIR=/var/lib/tay/store \
  -e TAY_INITIALIZE_IF_MISSING=true \
  -e TAY_ENABLE_DASHBOARD=true \
  -e TAY_DASHBOARD_SECRET_KEY_BASE='replace-with-at-least-64-random-bytes------------------------' \
  -v taydata:/var/lib/tay \
  -v taysocket:/run/tay \
  ghcr.io/andriisydorenko1904/tay:1.3.1

On subsequent starts, set TAY_INITIALIZE_IF_MISSING=false. Initialization is only for a genuinely missing Store and is never a repair operation.

Configuration

The image accepts the runtime and dashboard settings below. The Bandit API's TAY_HTTP_* and capacity settings are listed in the standalone configuration reference.

VariableDefaultRequiredMeaning
TAY_DATA_DIR/var/lib/taynoAuthoritative Store root. Use /var/lib/tay/store with a named volume.
TAY_SOCKET_PATH/run/tay/tay.socknoExecutor Protocol v1 Unix socket.
TAY_INITIALIZE_IF_MISSINGfalsenoInitialize only a genuinely absent Store.
TAY_DEFAULT_QUEUE_CONCURRENCY10noMaximum concurrently executing jobs in the standalone default queue (1..65536).
TAY_CALLER_TIMEOUT_MS5000noEngine call timeout in milliseconds; submitted timeouts have an unknown outcome and require same-ID reconciliation.
TAY_GROUP_COMMIT_INTERVAL_MS0noStrict-durability enqueue batching window (0..1000 ms); invalid values fail startup.
TAY_CHECKPOINT_INTERVAL_MS60000noCrash-safe Store-v2 semantic checkpoint interval (0..4294967295 ms); 0 disables it.
TAY_TERMINAL_RETENTION24hnoInitial terminal retention such as 30m, 1h, 24h, or 7d. Dashboard/API zero is a one-shot full terminal-history purge and persists 1h afterward. A retention saved by successful Dashboard compaction takes priority on restart.
TAY_ENABLE_DASHBOARDfalsenoEnable the bundled HTTP dashboard.
TAY_DASHBOARD_HOSTlocalhostnoPublic hostname accepted for LiveView origin checks; no scheme, port, or path.
TAY_DASHBOARD_PORT4000noContainer HTTP listen port.
TAY_DASHBOARD_USERNAMEnonenoOptional HTTP Basic authentication username; must be paired with the password.
TAY_DASHBOARD_PASSWORDnonenoOptional HTTP Basic authentication password; must be paired with the username.
TAY_DASHBOARD_SECRET_KEY_BASEnonewhen enabledRandom Phoenix signing secret of at least 64 bytes.

Basic Auth is disabled when neither credential is set. Supplying only one, or supplying a blank value, fails startup. Other invalid or missing required configuration also fails startup. The HTTP listener binds all container interfaces so Docker port publishing works; TAY_DASHBOARD_HOST controls URL generation and LiveView origin validation, not the bind address.

If users access the UI as https://jobs.example.com/tay, set TAY_DASHBOARD_HOST=jobs.example.com. Keep the internal port at 4000 and let the reverse proxy terminate TLS. For nonstandard public ports, configure the proxy to preserve the browser Host header.

Security boundary

The dashboard can display job arguments and perform Retry, Cancel, Pause, and Resume operations. Treat network access to it as administrator access. The default security boundary is the deployment network: the image publishes no port by itself, and the Compose example binds HTTP only to 127.0.0.1.

  • Bind to 127.0.0.1 when accessing it locally.
  • For remote access, prefer a private network, VPN, SSH tunnel, or trusted ingress. Terminate TLS before traffic crosses an untrusted network.
  • Enable the built-in Basic Auth when deployment-level access control is not sufficient or when an additional protection layer is desired.
  • Store the Phoenix secret and any optional credentials in the platform secret manager. Do not reuse the signing secret as the dashboard password.

The embedded Hex package intentionally does not impose authentication because the host Phoenix application owns its identity and authorization policy.

Persistence, health, and upgrades

/var/lib/tay is durable state; /run/tay is ephemeral worker IPC. Deleting the socket volume is safe while Tay and workers are stopped. Deleting the data volume deletes job history.

The OCI health check succeeds only after the Engine is ready and the selected transport accepts connections. The container smoke test separately exercises the default unauthenticated HTTP page and its LiveView assets; host tests cover the optional Basic Auth path. Startup has a 15-minute health-check grace period to match Tay's bounded recovery deadline; this does not weaken steady-state health checks.

Use the same cold backup and restore process as the headless runtime. Stop the old container before starting a new image against its volume. Never use a rolling deployment with two replicas sharing the Store.

Choosing a mode

Use tay:<version> without TAY_ENABLE_DASHBOARD for headless operation, or set TAY_ENABLE_DASHBOARD=true when the official UI is needed. In an existing Phoenix application, mount the dashboard included in the tay Hex package instead of the standalone web host.