- Remove adminer references (service was removed) - Remove mermaid diagrams (ASCII only) - Remove hardcoded credentials (use env var references) - Update all Docker references to 4-container setup (app, postgres, web, pgadmin) - Document env-based admin credentials (ADMIN_EMAIL/ADMIN_PASSWORD) - Document parameterized queries (SQL injection fixed) - Document FCM topic routing by stationtype+level - Document siren stationtype=3 fix in sidesdecode.py - Document idempotent seeder (firstOrCreate) - Document reverse proxy setup in deployment guide - Remove Makefile references (Docker Compose only)
7.9 KiB
Configuration
SIDES uses a layered configuration approach: a root .env for Docker Compose infrastructure, and a separate src/.env for the Laravel application. This document covers both.
Environment Variables Overview
Root .env (Docker Compose)
Located at the project root. Controls container-level configuration for PostgreSQL, pgAdmin, Firebase, admin seeding, and FTP access. See .env.example for the full list.
| Variable | Required | Default | Description |
|---|---|---|---|
POSTGRES_DB |
Yes | — | PostgreSQL database name |
POSTGRES_USER |
Yes | — | PostgreSQL user |
POSTGRES_PASSWORD |
Yes | — | PostgreSQL password |
PGADMIN_EMAIL |
Yes | — | pgAdmin login email |
PGADMIN_PASSWORD |
Yes | — | pgAdmin login password |
FIREBASE_PROJECT_ID |
Yes | — | Firebase project identifier |
FIREBASE_CREDENTIALS |
Yes | — | Path to Firebase credentials JSON file |
FCM_TOPIC_RAINFALL_WARNING |
No | rainfall_warning |
FCM topic for rainfall warnings |
FCM_TOPIC_RAINFALL_DANGER |
No | rainfall_danger |
FCM topic for rainfall danger alerts |
FCM_TOPIC_WATERLEVEL_ALERT |
No | waterlevel_alert |
FCM topic for water level alerts |
FCM_TOPIC_WATERLEVEL_DANGER |
No | waterlevel_danger |
FCM topic for water level danger alerts |
ADMIN_EMAIL |
No | admin@example.com |
Admin email used by DatabaseSeeder |
ADMIN_PASSWORD |
No | admin123 |
Admin password used by DatabaseSeeder |
FTP_SERVER |
No | — | FTP server hostname for sidesdecode.py |
FTP_USERNAME |
No | — | FTP username |
FTP_PASSWORD |
No | — | FTP password |
App .env (Laravel)
Located at src/.env. Controls Laravel framework and application settings. See src/.env.example for the full list.
| Variable | Required | Default | Description |
|---|---|---|---|
APP_NAME |
Yes | SIDES |
Application name |
APP_ENV |
Yes | local |
Environment: local, production |
APP_KEY |
Yes | — | Encryption key (generated via php artisan key:generate) |
APP_DEBUG |
Yes | true |
Enable debug mode (false in production) |
APP_URL |
Yes | http://localhost |
Application URL |
DB_CONNECTION |
Yes | pgsql |
Database driver |
DB_HOST |
Yes | postgres |
Database host (Docker service name) |
DB_PORT |
Yes | 5432 |
Database port |
DB_DATABASE |
Yes | ${POSTGRES_DB} |
Database name (references root .env) |
DB_USERNAME |
Yes | ${POSTGRES_USER} |
Database user (references root .env) |
DB_PASSWORD |
Yes | ${POSTGRES_PASSWORD} |
Database password (references root .env) |
SESSION_DRIVER |
No | database |
Session storage driver |
CACHE_STORE |
No | database |
Cache storage driver |
QUEUE_CONNECTION |
No | database |
Queue driver |
MAIL_MAILER |
No | log |
Mail driver (smtp for production) |
MAIL_HOST |
No | 127.0.0.1 |
SMTP server hostname |
MAIL_PORT |
No | 2525 |
SMTP port |
MAIL_USERNAME |
No | null |
SMTP username |
MAIL_PASSWORD |
No | null |
SMTP password |
MAIL_FROM_ADDRESS |
No | hello@example.com |
Sender email address |
MAIL_FROM_NAME |
No | ${APP_NAME} |
Sender display name |
FIREBASE_PROJECT_ID |
Yes | — | Firebase project identifier |
FIREBASE_CREDENTIALS |
Yes | — | Path to Firebase credentials JSON |
FCM_TOPIC_* |
No | See defaults | FCM notification topic names |
Docker Compose Configuration
The stack is defined in docker-compose.yml and consists of four services on a shared tckdev_net network:
Services
| Service | Image | Container | Port | Description |
|---|---|---|---|---|
app |
Custom (Dockerfile) |
tckdev-app |
9000 (internal) | PHP-FPM 8.2 application |
postgres |
postgres:16 |
tckdev-db |
5432:5432 |
PostgreSQL database |
web |
nginx:stable-alpine |
tckdev-web |
80:80 |
Nginx reverse proxy |
pgadmin |
dpage/pgadmin4 |
tckdev-pgAdmin |
5050:80 |
pgAdmin database manager |
Volumes
Named volumes:
pgdata-- PostgreSQL data persistence (/var/lib/postgresql/data)pgadmin_data-- pgAdmin session and settings
Bind mounts:
./src:/var/www/html-- Application source (mounted on bothappandweb)./docker/nginx/default.conf:/etc/nginx/conf.d/default.conf-- Nginx config (onweb)./backup:/backups-- Backup directory (onpgadmin)
App Container Environment
The app service passes these environment variables to control startup behavior:
| Variable | Default | Description |
|---|---|---|
RUN_MIGRATIONS |
true |
Run php artisan migrate --force on boot |
RUN_SEEDER |
true |
Run php artisan db:seed --force on boot |
ADMIN_EMAIL |
${ADMIN_EMAIL:-admin@example.com} |
Admin email for DatabaseSeeder |
ADMIN_PASSWORD |
${ADMIN_PASSWORD:-admin123} |
Admin password for DatabaseSeeder |
Entrypoint
The custom entrypoint (docker/entrypoint.sh) runs on every container start and performs:
- Copies
.env.exampleto.envif no.envexists - Runs
composer installifvendor/is missing - Runs
npm installifnode_modules/is missing - Runs
npm run buildifpublic/build/is missing - Runs database migrations if
RUN_MIGRATIONS=true - Runs database seeder if
RUN_SEEDER=true - Caches config, routes, and views
Health Check
PostgreSQL has a health check (pg_isready) with 5-second intervals. Both app and pgadmin wait for PostgreSQL to be healthy before starting (depends_on with condition: service_healthy).
Nginx Configuration
Located at docker/nginx/default.conf. Key settings:
- Document root:
/var/www/html/public - FastCGI pass:
app:9000(PHP-FPM on theappservice) - Security headers:
X-Frame-Options: SAMEORIGIN,X-XSS-Protection: 1; mode=block,X-Content-Type-Options: nosniff - Laravel rewriting:
try_files $uri $uri/ /index.php?$query_string(standard Laravel URL rewriting) - Hidden files: Access to dotfiles (except
.well-known) is denied
Laravel Configuration
Application Settings
- HTTPS enforcement:
URL::forceScheme('https')is called inAppServiceProvider::boot()(src/app/Providers/AppServiceProvider.php) - Timezone:
Asia/Kuala_Lumpur(set insrc/config/app.php) - Locale:
en(default), with fallback locale alsoen
Middleware
Registered in src/bootstrap/app.php:
| Alias | Class | Group | Description |
|---|---|---|---|
admin |
AdminMiddleware |
Alias | Protects admin-only routes |
| — | LocalizationMiddleware |
web (appended) |
Handles language/locale switching |
Session, Cache, and Queue
All three subsystems use the database driver by default, storing data in the PostgreSQL database. No external cache or queue server is required.
In production, mail is sent via SMTP through Gmail (smtp.gmail.com:587). In local development, the log mailer is used (emails are written to the log file instead of being sent).
External Services
Firebase Cloud Messaging (FCM)
Used for push notifications (rainfall warnings, rainfall danger, water level alerts, water level danger). Configuration requires:
FIREBASE_PROJECT_ID-- The Firebase project IDFIREBASE_CREDENTIALS-- Path to the service account JSON key file (stored instorage/app/firebase/)FCM_TOPIC_*variables -- Topic names for each notification type
FTP (sidesdecode.py)
The autoscript/sidesdecode.py script connects to an external FTP server to download station data files. It reads FTP_SERVER, FTP_USERNAME, and FTP_PASSWORD from environment variables, falling back to defaults if not set.
PostgreSQL
Runs as a Docker container using the official postgres:16 image. Connection credentials are shared between the root .env and src/.env via variable interpolation (${POSTGRES_DB}, ${POSTGRES_USER}, ${POSTGRES_PASSWORD}).