Installation

Quick Start

git clone https://github.com/Wachhund/S3-image-gallery.git
cd S3-image-gallery

cp .env.example .env
# Optional: .env anpassen (Ports, Credentials, OTP)

docker compose up --build -d

Load Test Data

# Bucket scannen und Bilder katalogisieren
docker compose exec php php bin/scan.php

# Thumbnails erzeugen
docker compose exec php php bin/thumbs.php

Set Up Passkey

  1. Set a one-time password at.env

:S3G_REGISTRATION_OTP=mein-geheimes-passwort

  1. Recreate the container:docker compose up -d --force-recreate php

  2. Create the passkey using the OTP at/register

  3. Log in with the passkey at/login

Docker Services

Service Base Port Description
nginx Alpine 8080 Reverse proxy, security headers, Gzip
php PHP 8.4 FPM — Application (GD, EXIF, PDO)
db MariaDB 11 3306 Database (persistent volume)
storage RustFS 9001 (Console) S3-compatible object storage
storage-init AWS CLI — Bucket creation (one-time)
battle-php PHP 8.4 FPM — FotoBattle application
battle-nginx Alpine 8081 FotoBattle frontend

Enable FotoBattle

FotoBattle must be located as a sibling directory next to the Gallery:

├── S3-image-gallery/
└── photo_battles/
# FotoBattle-Container starten
docker compose up -d --build battle-php battle-nginx

First admin account:

  1. Register athttp://localhost:8081/register

  2. In the database:UPDATE users SET role='admin' WHERE email='...'

Environment Variables

Gallery

Variable Default Description
PHP_VERSION

| 8.5 | Docker image tag | |DB_HOST

| db | MariaDB hostname | |DB_NAME

| s3gallery | Database name | |DB_USER

| s3gallery | DB user | |DB_PASSWORD

| changeme | DB password | |S3_ENDPOINT

| http://storage:9000 | RustFS API endpoint | |S3_ACCESS_KEY

| rustfsadmin | RustFS credentials | |S3_SECRET_KEY

| rustfsadmin | RustFS credentials | |S3_BUCKET

| gallery | S3 bucket name | |NGINX_PORT

| 8080 | Host port for Gallery | |RUSTFS_CONSOLE_PORT

| 9001 | Host port for RustFS console | |APP_DEBUG

| false | Show error details | |APP_SECURE_COOKIES

| true | HTTPS-only session cookies | |S3G_REGISTRATION_OTP

| (empty) | One-time password for Passkey registration | |S3G_RP_ID

| localhost | WebAuthn Relying Party ID |

FotoBattle

Variable Default Description
BATTLE_PORT

| 8081 | Host port for FotoBattle | |BATTLE_URL

| http://localhost:8081 | FotoBattle base URL | |BATTLE_SUBMIT_SECRET

| changeme | Shared HMAC secret (min. 32 characters) |

DB and S3 variables are shared by the Gallery.

Quality Gates

# Tests
docker compose exec php composer test

# Statische Analyse (PHPStan Level 6)
docker compose exec php composer analyse

# Code Style
docker compose exec php composer cs-check

Constraints

  • Demo Project — Not intended for production
  • Single Node — Docker Compose, no Kubernetes
  • No CDN — Images served directly from RustFS via PHP proxy
  • No WebSocket — No live battle feed
  • Synchronous Projections — No message broker in the MVP