Files
sides/docs/08-CONFIGURATION.md
root 6863f39a24 docs: rewrite all documentation to reflect current state
- 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)
2026-05-21 02:59:32 +08:00

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 both app and web)
  • ./docker/nginx/default.conf:/etc/nginx/conf.d/default.conf -- Nginx config (on web)
  • ./backup:/backups -- Backup directory (on pgadmin)

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:

  1. Copies .env.example to .env if no .env exists
  2. Runs composer install if vendor/ is missing
  3. Runs npm install if node_modules/ is missing
  4. Runs npm run build if public/build/ is missing
  5. Runs database migrations if RUN_MIGRATIONS=true
  6. Runs database seeder if RUN_SEEDER=true
  7. 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 the app service)
  • 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 in AppServiceProvider::boot() (src/app/Providers/AppServiceProvider.php)
  • Timezone: Asia/Kuala_Lumpur (set in src/config/app.php)
  • Locale: en (default), with fallback locale also en

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.

Mail

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 ID
  • FIREBASE_CREDENTIALS -- Path to the service account JSON key file (stored in storage/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}).