Files
platform/.env.example
T
pastilhasandClaude Opus 5 ff73e86983 move the wallet's chain source out of env and into the ui
WALLET_ESPLORA_URL was the one wallet setting an owner actually has to change — off a
public explorer that rate-limits and sees every address, onto their own indexer — and it
was the one they could only change with a shell and a restart. It now lives in
service_connections under 'esplora' and is edited at Wallet -> Settings -> Chain source,
probed against /blocks/tip/height before it is stored.

The URL joins the backend fingerprint, so re-pointing rebuilds every on-chain backend and
drops the gap-limit scan taken through the old endpoint. /_health probes what the wallets
actually use rather than the built-in default, and /_officer/config no longer reports a URL
it cannot know.

Also two receive-screen defects the Blockstream 429 exposed: a query error rendered as
"No address available", and the "new address" button called refetch() on the ?peek=true
query, so it re-fetched the same address instead of advancing the index.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-03 22:59:00 +00:00

71 lines
4.3 KiB
Bash

PORT=9000
JWT_SECRET="<generate with: openssl rand -base64 32>"
POSTGRES_URL="postgres://postgres:password@localhost:5432/officer"
MAIL_TRANSPORT="smtp://localhost:1025"
PUBLIC_URL=http://localhost:9000
# Guards (CORS origin checks, rate limits, password-strength rules) are ON unless this is set to
# "dev" or "development". Leave it unset or set it to "production" for a real deployment; only set
# it to "dev" on a local machine you trust, since that disables all three.
PUBLIC_BUILD_ENV=production
DATA_PATH=/path/to/data
OFFICER_ITEMS_DIR=/path/to/officer-items
HOME_DIR=/home/user
BROWSER_RELAY_PORT=18792
# ── Sidecars ────────────────────────────────────────────────────────────────────────────────────
# Each sidecar owns its upstream's credentials; the platform API is only a thin auth+forward proxy
# and never sees them. An unset upstream URL is not fatal — the sidecar logs a warning at boot and
# answers 503 until it is set, so you can run Officer with any subset of these configured.
# Transmission (officer-transmission) is configured from the app, not from here — Transmission →
# Connection. The daemon URL, the optional RPC auth and the RPC path live in `service_connections`,
# with the password encrypted, so nothing outside the sidecar can read it.
# InvoiceShelf (officer-invoiceshelf) is configured from the app, not from here — Invoices → Connection.
# Instances, their Sanctum tokens and the company each one is pinned to live encrypted in
# `invoiceshelf_accounts`, so nothing outside the sidecar can read a token.
# slskd (officer-slskd) is configured from the app, not from here — Soulseek → Connection. The
# daemon URL and its API key live encrypted in `service_connections`; the sidecar injects the key as
# X-API-Key on every forwarded request.
# Vaultwarden (officer-vault). VAULT_STORE_KEY encrypts stored secrets at rest — any strong secret
# of 16+ chars works, and CHANGING IT MAKES EXISTING STORED SECRETS UNREADABLE.
VAULTWARDEN_URL=http://127.0.0.1:8222
VAULT_STORE_KEY="<generate with: openssl rand -base64 32>"
# Anthropic proxy (officer-anthropic-proxy). Defaults to 5051; it holds the API credential, which
# lives in the host env rather than here.
# ANTHROPIC_PROXY_PORT=5051
# ReClip — the self-hosted yt-dlp service the download-media capability talks to. Defaults to
# http://localhost:8899.
# RECLIP_URL=http://localhost:8899
# ── Headscale (/api/vpn) ────────────────────────────────────────────────────────────────────────
# These drive the /api/vpn router, NOT the officer-headscale sidecar. The sidecar deliberately reads
# neither, keeping its registered servers and their keys in Postgres so host env can never shadow
# one. Set these only if you use /api/vpn.
# HEADSCALE_URL=https://headscale.example.com
# HEADSCALE_API_KEY="<headscale admin api key>"
# HEADSCALE_USER=officer
# ── Bitcoin wallet (officer-wallet) ─────────────────────────────────────────────────────────────
# The chain data source is NOT here — it is configured from the app, at Wallet → Settings → Chain
# source, and stored per owner. Any Esplora-compatible API works (electrs, esplora, mempool.space);
# it defaults to the public mempool.space until you set one.
# WALLET_NETWORK=bitcoin # bitcoin | testnet | signet | regtest
#
# How long an unlocked wallet stays unlocked, in seconds. Default 900 (15 min). The root key is held
# in the sidecar's memory for exactly this long after an unlock, then wiped. Shorter is safer.
# WALLET_UNLOCK_TTL_SEC=900
#
# NOTE: seed material is encrypted with VAULT_STORE_KEY (above) on top of the owner passphrase that
# seals it. Both are required to spend. If you lose VAULT_STORE_KEY, every stored seed is
# unrecoverable — back up the mnemonics separately, offline.
# Immich (officer-photos) is configured from the app, not from here — Photos → Connection. Instances and
# their API keys live encrypted in `photos_config`, so the platform never sees a key.