Environment Variables
Everything is environment variables. There is no config file. Pin images with ACTANA_TAG — one tag, x.y.z (the current release; npm view @actana/cli version prints it), because Panel and Core are version-locked.
Panel
| Env | Default | Meaning |
|---|---|---|
AC_PANEL_PORT / PORT |
7420 |
Listen port |
AC_PANEL_HOST / HOST |
0.0.0.0 |
Bind address. 127.0.0.1 keeps a shared host on loopback |
AC_PANEL_DATA_DIR |
/data in the image; platform data dir otherwise |
The one directory all Panel state lives in |
AC_SECRETS_KEY |
generated at <data dir>/secrets.key |
32-byte key (hex or base64) sealing stored Core credentials |
ACTANA_UPDATE_CHECK |
on | 0, false, or off stops the daily release check |
Generate a secrets key with openssl rand -hex 32. Set AC_SECRETS_KEY to keep it out of the data volume, so a copied volume or backup alone cannot open fleet credentials. Losing whichever key is in use means re-pairing every Core. The update check reads GitHub releases/latest, caches 24h, and only ever shows a banner.
Compose
Copy deploy/.env.example to .env beside docker-compose.yml. All values optional. ACTANA_TAG (default latest) is the image tag both services pull — one variable, because Panel and Core are version-locked. ACTANA_IMAGE_NAMESPACE defaults to actana. AC_SECRETS_KEY and ACTANA_UPDATE_CHECK are the same as the Panel table, applied to both services.
ACTANA_PUBLIC_HOST is not in .env. It lives in docker-compose.yml beside the Core service it names — a second Core needs a second value.
Core in a container
Only ACTANA_PUBLIC_HOST is required. The image never guesses it: a container hostname is its ID, and a guessed SAN would change the certificate on every recreation.
| Variable | Default | What it does |
|---|---|---|
ACTANA_PUBLIC_HOST |
— required | Comma-separated list of dial addresses; every entry becomes a SAN on the server cert; a pairing hands back one of them as the endpoint |
ACTANA_PORT |
8443 |
Core-link port, and the port the image exposes |
ACTANA_LABEL |
first public host | Name the Panel shows for this Core |
ACTANA_UPDATE_CHECK |
on | Same daily check; actana status and docker compose logs core |
Since 0.4.2 the value is a comma-separated list — localhost,host.docker.internal,core,192.168.1.50 — and the certificate carries every name in it. Typical entries:
- the compose service name (
core) — what the Panel dials over the network localhost— a CLI on the same machine, dialling the published porthost.docker.internal— a CLI inside another container (Docker Desktop resolves it to the host; it does not resolve on the host itself)- a LAN IP — reserved as static in the router, for machines elsewhere on the network
actana pair new --public-host <addr> chooses which entry a code's redemption hands back; it selects from the list and can never extend it. Changing the list re-signs the certificate, but clients dialling a name that stays in the list keep working. On Cores older than 0.4.2 the value is one address, and every change re-signs it for the new name only — every paired client, Panel included, re-pairs. Rename the service and update the matching entry to keep them agreeing.
Core on metal
ACTANA_HOME, ACTANA_BIN_DIR, ACTANA_CONFIG_DIR, ACTANA_DATA_DIR, plus XDG_DATA_HOME / XDG_CONFIG_HOME (macOS included, if set), move where things land. install.sh does not read them — the CLI does. Public host is actana setup --public-host, stored in actana.json.
| Path | Contents |
|---|---|
~/.local/share/actana/versions/<version>/ |
Bundle (bin/actana, app/, node/). current points at it |
~/.local/share/actana/data/missioncontrol.db |
SQLite: projects, tasks, sessions, event log |
~/.config/actana/material.json |
CA, certs, bearer, coreId. chmod 0600 |
~/.config/actana/actana.json |
Version, port, host, public host, label. No secrets |
~/.local/bin/actana |
Symlink to current/bin/actana |
Linux unit: ~/.config/systemd/user/actana-core.service. macOS: ~/Library/LaunchAgents/com.actana.core.plist and ~/Library/Logs/Actana/core.log. Those two service paths are fixed; everything else honours XDG.