Sign inSign up

achedon12/guestroll

By achedon12

•Updated about 21 hours ago

Self-hosted QR-code photo sharing for events. Guests scan, shoot, done.

Image
1

703

achedon12/guestroll repository overview

Guestroll

⁠Guestroll

Every guest's photos, in one place.
Guests scan a QR code on the table, their phone's camera opens, and every photo lands in your private album.
Self-hosted. No app to install, no account to create.

Website⁠ | GitHub⁠ | Documentation⁠ | Video tour⁠

Guest page on a phone next to the admin dashboard

⁠Quick start

docker run -d --name guestroll \
  --restart unless-stopped \
  -p 3000:3000 \
  -v guestroll-data:/data \
  -e ADMIN_PASSWORD='choose-a-long-password' \
  -e PUBLIC_URL='https://photos.example.com' \
  achedon12/guestroll:latest

Open /admin, sign in, create an event and print its QR code.

HTTPS is required on the day. Phone browsers only open the camera on HTTPS pages: put Guestroll behind a reverse proxy with a certificate (Caddy, Traefik, nginx: ready-made configs in the deployment guide⁠).

No ADMIN_PASSWORD? One is generated on first start and printed once in docker logs guestroll.

⁠Docker Compose

services:
  guestroll:
    image: achedon12/guestroll:latest
    restart: unless-stopped
    ports:
      - "127.0.0.1:3000:3000"   # reachable through your reverse proxy only
    environment:
      PUBLIC_URL: https://photos.example.com
      ADMIN_PASSWORD: change-me-please
      TRUST_PROXY: "true"       # only behind a proxy you control
      TZ: Europe/Paris
    volumes:
      - ./data:/data

The repository ships a docker-compose.yml⁠ driven entirely by a .env file.

⁠What it does

For guests: the camera opens straight from the QR code; uploads survive a crowded room's 4G (resized on the phone, queued, retried, resumed offline); they see their own photos, and the others' only if the hosts share the album; English, French, Italian and Spanish; light and dark themes.

For hosts: as many events as you like, each with its own link, QR code, color and logo; optional access code; moderation (publish then hide, or approve first); a live wall for a projector; a QR code designer whose presets are all scan-tested; a printable A4 table card; one-click ZIP of the whole album; stats; gallery links protected by a password; automatic emails at the end of an event (summary for you, album link for guests who opted in) and admin alerts, through your own SMTP server.

Guest pageContact sheetQR code designer
Guest pageModerationQR designer

⁠Tags

TagMeaning
latestNewest release
0, 0.4Newest release in that major / minor line
0.4.0An exact release: pin this in production

Every tag is multi-arch: linux/amd64 and linux/arm64 (a Raspberry Pi 4/5 works). Images carry provenance and an SBOM. The same tags are published on GHCR as ghcr.io/achedon12/guestroll.

⁠Configuration

Everything is an environment variable; all are optional.

VariableDefault
PUBLIC_URLrequest hostAddress encoded in QR codes, e.g. https://photos.example.com
ADMIN_PASSWORDgeneratedPassword of the admin owner account (printed once in the logs when generated)
PORT3000Listening port inside the container; the health check follows it
PUID / PGID1001Owner of /data: match your host user for bind mounts
TZUTCTime zone of the stats, e.g. Europe/Paris
DEFAULT_LOCALEenen, fr, it or es, when the browser's language isn't supported
DETECT_BROWSER_LOCALEtruefalse to always start in DEFAULT_LOCALE
TRUST_PROXYfalsetrue behind a reverse proxy you control
MAX_UPLOAD_MB25Largest accepted photo
SESSION_SECRETgenerated32+ characters; stored in /data when generated
SMTP_HOST / SMTP_PORTnone / 587Your SMTP server; turns email on (also settable in the admin)
SMTP_USER / SMTP_PASSWORD / SMTP_FROMnoneCredentials and sender
ADMIN_EMAILnoneWhere alerts and event summaries go
STORAGE_DRIVERlocals3 to keep photos in an S3-compatible bucket (S3_ENDPOINT, S3_BUCKET, S3_ACCESS_KEY_ID, S3_SECRET_ACCESS_KEY)

Full reference: Configuration⁠.

⁠Volume, port, health

  • /data: the SQLite database and every photo. Back it up.
  • Port 3000 (or PORT): HTTP.
  • Health check: GET /api/health returns 200 {"status":"ok"}; the image declares it as its HEALTHCHECK.
  • The server runs as an unprivileged user (PUID:PGID) on Alpine, with only the Node.js binary and the app in the image.

⁠Privacy

Photos are never public files: every request is checked against the guest's own cookie, guests never see each other's photos, and GPS and camera metadata are stripped from every upload. Details: Security⁠.

⁠License

MIT. Source, issues and contributions: github.com/achedon12/guestroll⁠.

Tag summary

Content type

Image

Digest

sha256:8356cd52f…

Size

78.4 MB

Last updated

about 21 hours ago

docker pull achedon12/guestroll