Configuration
Everything is an environment variable. There is nothing to configure in a file, and no settings page for any of these — config is validated at startup and fails loudly if wrong.
Required
Section titled “Required”| Variable | What it’s for |
|---|---|
PUBLIC_BASE_URL |
The URL this instance is reachable at. It’s baked into your QR codes, so it must be the URL a phone can reach. |
ADMIN_EMAIL |
Your login. |
ADMIN_PASSWORD |
Your password. Applied on every start — change it in .env and restart to rotate. |
SESSION_SECRET |
Signs the login cookie. openssl rand -hex 32 |
VOTE_SALT |
Salts the anonymous-vote hash. openssl rand -hex 32 |
There is deliberately no first-run setup page: the single admin account is (re)applied from
ADMIN_EMAIL / ADMIN_PASSWORD every time the container starts.
Optional
Section titled “Optional”| Variable | Default | What it’s for |
|---|---|---|
DATA_DIR |
/data |
Where the SQLite database and photos live. One volume, everything in it. |
SITE_TITLE |
the instance’s hostname | Your site name, shown in the persistent nav on every public page. |
SITE_TAGLINE |
— | The line under it on the public index. Write your own. |
TZ |
UTC |
Set it — lot codes use your local month. |
TRUST_PROXY |
unset | Set to 1 when Mash sits behind your reverse proxy: rate limits then key on the client address your proxy reports (the last X-Forwarded-For entry) instead of the proxy’s own — otherwise every visitor shares one rate-limit bucket. Leave unset when the app is directly reachable: the header would be forgeable. |
ANALYTICS_SCRIPT_URL |
unset | Loads an analytics snippet on public bottle pages. Unset = Mash phones nobody. |
ANALYTICS_WEBSITE_ID |
unset | Rendered as data-website-id (Umami). |
ANALYTICS_DOMAIN |
unset | Rendered as data-domain (Plausible). |
SMTP_URL |
unset | smtp:// or smtps:// endpoint for outbound email. Unset = no email, and every email feature hides itself. |
MAIL_FROM |
— | The From address, e.g. Mash <mash@example.com>. Required together with SMTP_URL. |
BACKUP_TOKEN |
unset | Bearer token for scripted backup downloads (GET /api/backup). Unset = backups are admin-only. openssl rand -hex 32 |
PHOTO_S3_ENDPOINT |
unset | S3-compatible endpoint for the photo mirror. All four PHOTO_S3_* credentials must be set together; all unset = no mirror. |
PHOTO_S3_BUCKET |
— | The bucket the mirror writes to. |
PHOTO_S3_ACCESS_KEY / PHOTO_S3_SECRET_KEY |
— | Credentials. Put/delete on objects is all the mirror ever does. |
PHOTO_S3_REGION |
auto |
Region, if your provider cares. |
PHOTO_S3_PREFIX |
photos/ |
Key prefix inside the bucket. |
MIGRATIONS_DIR |
./drizzle |
Where the bundled database migrations live, relative to the working directory. Only needed if you start the app from somewhere other than its own directory. |
PUBLIC_BASE_URLmatters twice: it’s printed into QR codes and used for CSRF origin checks, so it must match what browsers actually see. Behind a reverse proxy, set it to the public URL (Operations).- Analytics load only on public bottle pages, never in the admin, and degrade to nothing if blocked. Details in Public pages & sharing.
- Email is optional and queued through an outbox; if
SMTP_URLis unset the features that would send mail simply don’t appear. - The mail queue shows up on Admin → Settings, beside the photo mirror, once email is configured. It reports how many messages are queued, sent, and given up, and lists any message that has failed to send along with its error — each can be retried or discarded from there. A Run queue now button sends any due mail immediately instead of waiting for the background drainer. Sent history is kept for 90 days and pruned automatically after that.
- The photo mirror copies every photo to an S3-compatible bucket (AWS, MinIO, R2, B2) as
it is saved, and removes it when you delete it — a durability copy, never used for serving.
It is queued like the email outbox, so a bucket outage never blocks an upload. Enabling it
on an instance that already has photos? Press Reconcile on Admin → Settings once.
Restore after a disaster with
aws s3 sync s3://your-bucket/photos/ ./data/photos/.