A photo gallery for the HKFree community network. Galleries are organized by area and access point (AP). Each AP has a public gallery (open to everyone) and a private "Dokumentace" gallery (signed-in users only). Members with the right role can upload and remove photos directly in the browser.
- Single sign-on via Keycloak / OIDC — no local accounts.
- Role-based management — uploading and deleting is restricted to configured Keycloak
realm roles (e.g.
SO,ZSO,PREDSTAVENSTVO,VV). - Area / AP data is pulled live from the HKFree Userdb API.
- Images stream through the application from a private disk, so private documentation is never directly reachable; thumbnails are generated on demand.
- PHP 8.3 · Laravel 13
- Laravel Socialite + Keycloak provider for OIDC login
- Intervention Image for thumbnails
- Tailwind CSS 4 + Vite for the frontend
- SQLite (default) for sessions, cache, queue and app data
- Pest for tests
The most important environment variables (see .env.example for the full list):
| Variable | Purpose |
|---|---|
APP_URL | Public base URL. The Keycloak redirect URI is derived from it ({APP_URL}/auth/callback). |
KEYCLOAK_BASE_URL | Keycloak server, e.g. https://sso.hkfree.org. |
KEYCLOAK_REALM | Keycloak realm. |
KEYCLOAK_CLIENT_ID / KEYCLOAK_CLIENT_SECRET | OIDC client credentials for this app. |
USERDB_AREAS_URL | Userdb API endpoint that lists areas and APs. |
USERDB_API_USERNAME / USERDB_API_PASSWORD | Credentials for the Userdb API. |
GALLERY_ADMIN_ROLES | Comma-separated Keycloak realm roles allowed to manage galleries (OR-ed), e.g. SO,ZSO,PREDSTAVENSTVO,VV. |
composer install
cp .env.example .env
php artisan key:generate
# SQLite database
touch database/database.sqlite
php artisan migrate
npm installFill in the KEYCLOAK_* and USERDB_* values in .env, then start everything (PHP
server, queue worker, log tail and Vite) with a single command:
composer run devRun the test suite with:
php artisan testThis guide deploys the app into a Linux user's home directory at
~/websites/hkfree-gallery and serves it from galerie.hkfree.org over HTTPS, with
Apache running as www-data. Replace <user> with the account that owns the code.
# Apache modules
sudo a2enmod rewrite ssl headers
# PHP 8.3 + extensions
sudo apt install php8.3 php8.3-cli libapache2-mod-php8.3 \
php8.3-gd php8.3-sqlite3 php8.3-mbstring php8.3-xml \
php8.3-curl php8.3-zip php8.3-intl
# Let's Encrypt
sudo apt install certbot python3-certbot-apacheYou also need Composer and Node.js
(used only to build the frontend assets). This guide assumes mod_php; if you use
PHP-FPM instead, configure the handler accordingly.
git clone <repo-url>~/websites/hkfree-gallery
cd~/websites/hkfree-gallerycomposer install --no-dev --optimize-autoloader
npm ci
npm run buildcp .env.example .env
php artisan key:generateEdit .env for production:
APP_NAME="HKFree galerie"APP_ENV=productionAPP_DEBUG=falseAPP_URL=https://galerie.hkfree.orgDB_CONNECTION=sqliteKEYCLOAK_BASE_URL=https://sso.hkfree.orgKEYCLOAK_REALM=...KEYCLOAK_CLIENT_ID=...KEYCLOAK_CLIENT_SECRET=...USERDB_AREAS_URL=https://userdb.hkfree.org/userdb/api/areasUSERDB_API_USERNAME=...USERDB_API_PASSWORD=...GALLERY_ADMIN_ROLES=SO,ZSO,PREDSTAVENSTVO,VVtouch database/database.sqlite
php artisan migrate --force
php artisan config:cache
php artisan route:cache
php artisan view:cache
php artisan storage:linkis not required — gallery images stream through the application from the private disk. Only run it if you later add public-disk assets.
Two things must work: Apache needs to traverse into the home directory to reach
public/, and it needs to write to storage/, bootstrap/cache/ and the SQLite
database (SQLite also writes a journal in the database/ directory).
# Let www-data traverse the path to the app's public/ directory
sudo chmod o+x /home/<user>
sudo chmod o+x /home/<user>/websites
# Own the code as <user>, with www-data as the group
sudo chown -R <user>:www-data /home/<user>/websites/hkfree-gallery
# Make the runtime directories and the SQLite database group-writable.# The setgid bit makes newly created files inherit the www-data group.cd~/websites/hkfree-gallery
sudo chmod -R ug+rwX storage bootstrap/cache database
sudo find storage bootstrap/cache -type d -exec chmod g+s {} \;
sudo chmod 664 database/database.sqliteInstead of
chmod o+xon the home path, you may addwww-datato<user>'s group:sudo usermod -aG <user> www-data(requires the home directory to be group-readable and executable). Re-run the permission and cache commands after every deploy that creates new files.
Create /etc/apache2/sites-available/galerie.hkfree.org.conf:
<VirtualHost*:80>
ServerName galerie.hkfree.org
DocumentRoot /home/<user>/websites/hkfree-gallery/public
<Directory/home/<user>/websites/hkfree-gallery/public>
AllowOverride All
Require all granted
Options FollowSymLinks
</Directory>
ErrorLog ${APACHE_LOG_DIR}/galerie.hkfree.org-error.log
CustomLog ${APACHE_LOG_DIR}/galerie.hkfree.org-access.log combined
</VirtualHost>Enable it and reload Apache:
sudo a2ensite galerie.hkfree.org
sudo apache2ctl configtest
sudo systemctl reload apache2Let Certbot obtain the certificate, create the :443 SSL virtual host, and add the
HTTP → HTTPS redirect to the port-80 vhost automatically:
sudo certbot --apache -d galerie.hkfree.org --redirectCertificate renewal runs automatically via Certbot's systemd timer — check it with
systemctl status certbot.timer.
If you are not using certbot --apache, add the redirect to the port-80 vhost
manually:
<VirtualHost*:80>
ServerName galerie.hkfree.org
RewriteEngineOnRewriteCond%{HTTPS}offRewriteRule^https://%{HTTP_HOST}%{REQUEST_URI} [R=301,L]
</VirtualHost>cd~/websites/hkfree-gallery
git pull
composer install --no-dev --optimize-autoloader
source~/.bashrc
nvm use --lts
npm ci && npm run build
php artisan migrate --force
php artisan config:cache && php artisan route:cache && php artisan view:cache
# Re-apply group ownership if new files were created (see step 6).