curl and openssl extensions
(both are standard), and Apache .htaccess support.fsn1). Set visibility to private — visitors get
access only through short-lived presigned URLs.Configure CORS on the bucket so the admin browser may upload directly
to S3 and so gallery images load on your domain. Hetzner supports the
standard S3 CORS API; using s3cmd, aws s3api, or any S3 GUI client
(e.g. Cyberduck), apply:
{
"CORSRules": [
{
"AllowedOrigins": ["https://www.your-domain.com"],
"AllowedMethods": ["GET", "PUT"],
"AllowedHeaders": ["*"],
"MaxAgeSeconds": 3600
}
]
}
With aws CLI:
aws s3api put-bucket-cors \
--endpoint-url https://fsn1.your-objectstorage.com \
--bucket my-photo-galleries \
--cors-configuration file://cors.json
Replace the origin with your real domain (and add http://localhost:8080
temporarily if you want to test uploads locally).
cp config/config.sample.php config/config.php
cp config/credentials.sample.php config/credentials.php
Edit config/config.php:
| Key | Meaning |
|---|---|
site.name |
Fallback site title |
site.base_url |
Public base URL, used for gallery share links |
site.timezone |
Timezone for expiry checks, e.g. Europe/Berlin |
s3.endpoint |
https://<location>.your-objectstorage.com |
s3.region |
The location, e.g. fsn1 |
s3.bucket |
Bucket name |
s3.access_key / s3.secret_key |
S3 credentials |
s3.url_ttl |
Lifetime of presigned view URLs in seconds |
uploads.thumb_size |
Longest edge of grid thumbnails (browser-generated) |
The default admin login is admin / changeme — change it in the admin
Settings page immediately after the first login.
Upload the contents of this folder into your account's document root
(usually public_html/, htdocs/ or www/) via FTP/SFTP. The site's home
page, index.php, sits directly in the document root — there is no separate
web-root subfolder to configure.
The application internals (app/, config/, data/, docs/) live inside
the document root but are blocked from the web by the root .htaccess (plus a
deny-all .htaccess inside each of app/, config/, data/ as a fallback).
Verify after deploying — each of these must return 403 Forbidden, never their contents:
https://your-domain.com/config/config.phphttps://your-domain.com/config/credentials.phphttps://your-domain.com/data/site.jsonIf they don't, your host ignores .htaccess — move app/, config/ and
data/ above the document root and adjust the paths, or contact support.
The PHP process must be able to write to:
data/ (and data/galleries/) — flat-file contentmedia/ — hero + showreel imagesconfig/ — only for the online password changeOn typical shared hosting (suEXEC/FPM running as your user) this already
works; otherwise chmod 755 the directories (or 775/777 as a last resort).
/admin/, log in, change the password (Settings)./showreel.php, scroll behavior, and
that navigation hides when scrolling down.your-objectstorage.com, not from your domain,php -S localhost:8080 router.php
router.php reproduces the .htaccess protection for the PHP built-in server
(which does not read .htaccess); it is only used locally.
Everything except real S3 traffic works without credentials; gallery pages render presigned URLs that simply won't resolve until real keys are configured.