You are reading the documentation of Guestroll v0.3.0. The latest version is v0.5.0. Latest docs · What changed · Changelog
Skip to content

Configuration ​

Guestroll is configured with environment variables only. Every variable is optional: an empty instance starts with safe defaults. A complete template is in .env.example.

Invalid values stop the server at startup with a message naming the variable, instead of running with a silent fallback.

Docker and network ​

These are read by the container or by docker-compose.yml, not by the app itself.

VariableDefaultDescription
PORT3000Port the server listens on inside the container (or on the machine without Docker). The health check follows it.
HOSTNAME0.0.0.0Interface the server binds to inside the container.
HOST_PORT3000Compose only: port published on the host.
HOST_BIND0.0.0.0Compose only: host interface to publish on. 127.0.0.1 keeps Guestroll reachable only through a local reverse proxy.
DATA_PATHguestroll-dataCompose only: named volume or host path mounted on /data.
PUID / PGID1001User and group that own the data folder and run the server. Match your host user for bind mounts.
TZUTCTime zone of the stats (hourly and daily buckets), e.g. Europe/Paris.
GUESTROLL_IMAGEghcr.io/achedon12/guestroll:latestCompose only: image to run. Pin a version in production.
CONTAINER_NAMEguestrollCompose only: lets you run several instances side by side.

Instance ​

VariableDefaultDescription
APP_NAMEGuestrollShown in page titles, the admin header and social cards.
PUBLIC_URL(request host)Public origin encoded in QR codes and social cards, e.g. https://photos.example.com. Set it: behind a proxy, the request host may be an internal name.
DATA_DIR./data (/data in Docker)Where the SQLite database and photos live.

Languages ​

Guestroll speaks English (en), French (fr), Italian (it) and Spanish (es). Each visitor gets, in this order:

  1. the language they picked with the language menu (kept in their browser);
  2. the album's language, if the hosts set one in the event settings;
  3. their browser's language, if supported and DETECT_BROWSER_LOCALE is on;
  4. DEFAULT_LOCALE.
VariableDefaultDescription
DEFAULT_LOCALEenLanguage used when nothing more specific applies.
DETECT_BROWSER_LOCALEtruefalse skips step 3: everyone without a choice gets the album's language or DEFAULT_LOCALE.

Security ​

VariableDefaultDescription
ADMIN_USERNAMEadminUsername of the owner account created on first start.
ADMIN_PASSWORD(generated)Password of that owner account. When set, it wins on every start (and the account stays an owner): it is the way back in if every other password is lost. When empty, a password is generated on first start and printed once in the logs; change it in Admin → Settings. Other accounts are created from the admin.
SESSION_SECRET(generated)Key that signs and encrypts cookies, 32+ characters. When empty, one is generated and stored in DATA_DIR/.session-secret. Changing it signs everyone out.
TRUST_PROXYfalseRead the client IP from X-Forwarded-For and the host from X-Forwarded-Host. Turn it on only behind a reverse proxy you control, or rate limits can be dodged with a forged header.
SECURE_COOKIEStrue in productionCookies only travel over HTTPS. Set to false only to test over plain HTTP on a local network.

Uploads ​

VariableDefaultDescription
MAX_UPLOAD_MB25Largest accepted photo. Phones resize before sending, so most uploads weigh 1–4 MB. Raise your reverse proxy's body limit above this.
MAX_IMAGE_MEGAPIXELS80Images above this are refused before decoding, which protects memory from "decompression bombs".
DEFAULT_CAPTURE_MODEcameraCapture mode preselected for new events: camera, picker or both.

Rate limits ​

Per minute. Upload limits apply per guest, login limits per client IP.

VariableDefaultDescription
RATE_LIMIT_UPLOADS_PER_MINUTE30Photos one guest can send per minute.
RATE_LIMIT_LOGIN_PER_MINUTE5Admin login attempts per IP.
RATE_LIMIT_UNLOCK_PER_MINUTE10Access-code attempts per guest; three times this value is the ceiling for wrong codes on one event, across all guests.

Storage ​

Photos, logos and voice messages go to a folder under DATA_DIR by default. Set STORAGE_DRIVER=s3 to keep them in any S3-compatible bucket instead (AWS S3, Backblaze B2, Cloudflare R2, Wasabi, Garage, RustFS, SeaweedFS…). The SQLite database always stays in DATA_DIR, so keep the volume either way.

VariableDefaultDescription
STORAGE_DRIVERlocallocal or s3.
S3_ENDPOINT(none)e.g. https://s3.eu-west-3.amazonaws.com, https://<account>.r2.cloudflarestorage.com, http://garage:3900.
S3_REGIONus-east-1Region used to sign requests. Most self-hosted servers accept the default.
S3_BUCKET(none)The bucket must exist. Keep it private: Guestroll serves every file itself, after checking access.
S3_ACCESS_KEY_ID / S3_SECRET_ACCESS_KEY(none)Credentials allowed to read, write, list and delete in the bucket.
S3_PREFIX(none)Folder inside the bucket, to share one bucket between instances.
S3_FORCE_PATH_STYLEtruetrue sends endpoint/bucket/key; false sends bucket.endpoint/key (AWS virtual-hosted style).

At startup Guestroll writes, reads back and deletes a small probe file, and logs [storage] S3 bucket NOT usable with the reason if that fails. Files are never served from the bucket directly, so photos stay private even with a bucket on a public endpoint. To move existing photos to a bucket, make a backup (Admin → Settings → Backup), switch the driver, then restore it.

Email ​

Optional. Without SMTP, everything else works and no email is ever sent. SMTP can also be set in Admin → Settings → Email, where the password is stored encrypted (AES-256-GCM, key derived from SESSION_SECRET). When SMTP_HOST is set, the environment wins and the admin form is read-only.

VariableDefaultDescription
SMTP_HOST(none)SMTP server, e.g. smtp.fastmail.com. Setting it turns email on.
SMTP_PORT587587 (STARTTLS) or 465 (TLS).
SMTP_SECUREfalsetrue for implicit TLS on port 465.
SMTP_USER / SMTP_PASSWORD(none)Credentials, when the server asks for them.
SMTP_FROMSMTP_USERSender, e.g. Guestroll <photos@example.com>.
ADMIN_EMAIL(none)Where alerts and event summaries go. Settable in the admin when empty.
SCHEDULER_INTERVAL_SECONDS60How often the background worker sends queued mail, closes scheduled events and checks alerts. 0 turns it off.

Emails wait in a queue in the database and are retried after 1, 5, 15 minutes, 1 and 6 hours, then marked failed (Admin → Settings shows them, with a retry button). Set PUBLIC_URL: links in emails are built from it, since a background job has no request to read the host from.

Released under the MIT License.