Files
UmbraTrans/systemd/umbratrans.env.example
umbra audio ef6bf1e6a3 Add first-run setup so a deployment can be finished in the browser
The gap this closes: the operator command that creates the first
administrator refuses to run in production, and production refuses to
start without SMTP credentials that only the operator has. So a real
deployment could not be brought up at all. Everything else already worked.

Setup is offered only when both of these hold, checked against the store
on every request rather than cached at boot:

* no platform administrator exists, and
* the token generated at that boot is presented.

The token is what keeps this from being first-requester-wins: anyone who
reached the URL before the operator would otherwise become the platform
administrator. It is written to the journal, so control of the service is
still what authorises the first administrator, and it is regenerated on
restart.

It is spent when it authorises rather than when the account is created, so
a password the policy rejects cannot leave a shown token usable. Five
failed attempts burn it. Comparison is constant-time. The status endpoint
never returns it, and there is no endpoint that would.

One deliberate exception to the log filter: the announcement uses no
key=value shape, so redact_text leaves it alone, and a test pins both
halves — the setup code still gets through, and `setup_token=` still does
not. The filter is not weakened, disabled, or special-cased.

Also:

- a `staging` environment, so a deployment can be brought up before SMTP
  exists. It holds every production rule except that one, and the waiver
  that permits it is refused in production outright, reported by
  /api/health as mail_deliverable, and shown as a standing banner in the
  control panel, which then refuses to create accounts. A staging
  deployment cannot become a convenient way to run something production
  would not allow.
- `serve` accepts `--allow-lan-bind` for a named private address, because
  the reverse proxy runs on another host. It refuses a wildcard and a
  public address, so the flag cannot open the port to the internet. AF_UNIX
  was added to the unit's address-family set, without which the PostgreSQL
  socket connection cannot be made.
- `count_users_with_role` on the repository, counting active assignments
  rather than profile rows, because a suspended administrator is not one.
- setup.html and the sign-in link that appears only while setup is
  outstanding, plus the deployment runbook and a rootless unit.

A test of mine was asserting over every credential row in the shared
scratch database rather than the one it created, so it passed only while
no account had replaced its one-time password. Scoped it, and added the
other half of the property.

279 pass without a database, 288 against one.
2026-09-27 06:13:58 -07:00

80 lines
3.8 KiB
Plaintext

# UmbraTrans service environment.
#
# Install to ~/.config/umbratrans/umbratrans.env with mode 0600, owned by the
# service user:
#
# install -d -m 700 ~/.config/umbratrans
# install -m 600 umbratrans.env.example ~/.config/umbratrans/umbratrans.env
# $EDITOR ~/.config/umbratrans/umbratrans.env
#
# This file holds the database DSN and the SMTP password, so it must not be world
# readable and must not be committed. It is read by systemd's EnvironmentFile,
# which is why the values are not on the ExecStart line: that is visible in /proc
# to every process on the machine.
#
# Values are read with no shell expansion, so quote only if the value itself
# contains a space. Do not add `export`.
# --- Which deployment this is -------------------------------------------
# staging real database, real hostname, but mail may be unconfigured.
# production identical, and refuses to start without working SMTP.
UMBRA_ENV=staging
# --- Storage -------------------------------------------------------------
# Must be the PostgreSQL adapter. Both public environments refuse to start
# without a DSN, and refuse a file-backed repository outright.
UMBRATRANS_REPOSITORY=postgres
# Peer authentication over the local socket: no password, because the service
# runs as the same operating-system user as the database role. If the role is
# reached over TCP instead, put the password in the DSN and set the file to 0600
# (it already is) — but prefer the socket.
UMBRATRANS_DATABASE_DSN=postgresql:///umbratrans?host=/run/postgresql&user=umbra
# --- Public exposure -----------------------------------------------------
# Secure cookies require TLS. The reverse proxy terminates it, so the cookie
# flag is on even though this process speaks plain HTTP to the proxy.
UMBRATRANS_COOKIE_SECURE=true
UMBRATRANS_REQUIRE_CSRF=true
# The host the proxy answers on. Used to build the link in a confirmation email,
# so it must be the address a person will actually open, with no trailing slash.
UMBRATRANS_VERIFICATION_BASE_URL=https://umbratrans.bdmurphy.me
# Must match the Host header the proxy sends, or the request is refused.
UMBRATRANS_ALLOWED_HOSTS=umbratrans.bdmurphy.me
# The frontend is served by this process so the pages and the API share an
# origin. There is no CORS middleware, and none should be added.
UMBRATRANS_STATIC_ROOT=/home/umbra/src/UmbraTrans/web
# --- Outbound mail -------------------------------------------------------
# Required in production. A deployment cannot be brought up without it, because
# every new account needs a confirmation link and a link that never arrives
# leaves the account permanently unusable.
UMBRATRANS_MAILER=smtp
UMBRATRANS_SMTP_HOST=
UMBRATRANS_SMTP_PORT=587
UMBRATRANS_SMTP_USERNAME=
UMBRATRANS_SMTP_PASSWORD=
# STARTTLS is on unless this says otherwise. Turning it off sends credentials
# and mail in the clear; only do that for a relay on the same host.
UMBRATRANS_SMTP_STARTTLS=true
# "PLAIN" is the usual choice over an implicitly encrypted port. "LOGIN" exists
# for servers that do not offer PLAIN.
UMBRATRANS_SMTP_AUTH_MECHANISM=PLAIN
# --- Bring-up only -------------------------------------------------------
# Lets a staging deployment start with no SMTP configured. It is refused in
# production, reported by /api/health as mail_deliverable=false, and shown as a
# standing banner in the control panel, which then refuses to create accounts.
#
# Set this to 1 only to reach first-run setup before credentials exist. Remove it
# as soon as SMTP is configured, and set UMBRA_ENV=production at the same time.
UMBRATRANS_MAIL_DELIVERY_WAIVED=1
# Note: this file is read by systemd's EnvironmentFile, which does not use shell
# syntax. Do not `source` it in a shell to inspect the values: an unquoted `&` in
# a connection string (host=...&user=...) is a command separator to a shell and
# will silently truncate the DSN. Read it with `systemctl --user show` instead.