Skip to main content
The ADMA Cloud URL Shortener uses environment variables to configure both the backend (Spring Boot) and frontend (React + Vite) components. This page provides a complete reference of all configuration options.

Backend Environment Variables

Backend environment variables are injected at runtime via the ECS Task Definition or Docker Compose configuration.

Database Configuration

These variables configure the PostgreSQL database connection. In production, they should point to your AWS RDS instance.
VariableRequiredDefaultDescription
DB_HOSTYeslocalhostPostgreSQL server hostname or IP address. In AWS, use your RDS endpoint (e.g., my-rds.xxxxx.eu-west-1.rds.amazonaws.com)
DB_PORTYes5432PostgreSQL server port
DB_NAMEYesurlshortenerName of the database to connect to
DB_USERNAMEYespostgresDatabase user for authentication
DB_PASSWORDYeschangemeDatabase password for authentication
Security Best Practice: Never hardcode DB_PASSWORD in your configuration files. In AWS, store it in AWS Systems Manager Parameter Store or Secrets Manager as a SecureString and reference it in your ECS Task Definition.
Example (Production - AWS RDS):
DB_HOST=adma-postgres.c12ab3xyz456.eu-west-1.rds.amazonaws.com
DB_PORT=5432
DB_NAME=urlshortener
DB_USERNAME=appuser
DB_PASSWORD=<stored-in-ssm-parameter-store>

JWT Configuration

JSON Web Tokens (JWT) are used for stateless authentication. The secret key must be at least 32 characters for HS256 signing.
VariableRequiredDefaultDescription
JWT_SECRETYeschangeme-this-must-be-at-least-32-chars-long!!Secret key used to sign and verify JWT tokens. Must be at least 32 characters for HS256 algorithm
JWT_EXPIRATION_MSNo86400000Token expiration time in milliseconds. Default is 24 hours (86400000 ms)
Critical Security Requirement:
  • JWT_SECRET must be a strong, randomly generated string of at least 32 characters
  • Store it in AWS SSM Parameter Store as a SecureString in production
  • Never commit the production secret to version control
  • Generate a new secret: openssl rand -base64 48
Example (Production):
JWT_SECRET=<stored-in-ssm-parameter-store>
JWT_EXPIRATION_MS=86400000  # 24 hours

Application URLs

VariableRequiredDefaultDescription
APP_BASE_URLYes"" (empty string)Base URL used when constructing fully-qualified short URLs returned in API responses. Must include protocol (e.g., https://go.yourdomain.com). If empty, falls back to the request’s context path
FRONTEND_URLNohttp://localhostFrontend application URL, used by the backend to construct redirect URLs to the SPA error pages
When APP_BASE_URL is not set, the backend will dynamically resolve the base URL from the incoming HTTP request. In production behind an ALB, you should explicitly set this to ensure consistent short URLs.
Example (Production):
APP_BASE_URL=https://go.yourdomain.com
FRONTEND_URL=https://yourdomain.com

CORS Configuration

Cross-Origin Resource Sharing (CORS) must be configured to allow the frontend to communicate with the backend API.
VariableRequiredDefaultDescription
CORS_ALLOWED_ORIGINSYeshttp://localhost,http://localhost:3000,http://localhost:5173Comma-separated list of allowed origins for CORS requests. In production, set this to your frontend domain(s) only
Example (Development):
CORS_ALLOWED_ORIGINS=http://localhost,http://localhost:3000,http://localhost:5173
Example (Production):
CORS_ALLOWED_ORIGINS=https://yourdomain.com,https://www.yourdomain.com
Security Warning: Never use wildcard * in production. Only whitelist your actual frontend domain(s).

Server Configuration

VariableRequiredDefaultDescription
SERVER_PORTNo8080Port on which the Spring Boot application listens for HTTP requests
Example:
SERVER_PORT=8080

Connection Pool Settings

HikariCP connection pool settings are configured in application.yml and can be overridden via environment variables if needed.
SettingDefaultDescription
Maximum Pool Size10Maximum number of connections in the pool
Minimum Idle2Minimum number of idle connections maintained
Connection Timeout30000 msMaximum time to wait for a connection from the pool
These are currently hardcoded in application.yml but can be externalized if needed for production tuning.

Frontend Environment Variables

Critical Difference: Frontend environment variables are build-time only. They are baked into the JavaScript bundle during the Docker image build and cannot be changed at runtime.

Build-Time Configuration

VariableRequiredDefaultDescription
VITE_API_BASE_URLYes"" (empty string)Base URL of the backend API. This value is embedded into the compiled JavaScript bundle at build time. Must include protocol (e.g., https://api.yourdomain.com)
How It Works:
  • Vite reads VITE_API_BASE_URL from the environment during the build process
  • The value is replaced in the code via import.meta.env.VITE_API_BASE_URL
  • The final JavaScript bundle contains the hardcoded URL
  • This is accessed in frontend/src/lib/api.ts:32

Setting Frontend Environment Variables

Local Development

Create a .env.local file in the frontend/ directory:
# frontend/.env.local
VITE_API_BASE_URL=http://localhost:8080

Docker Build

Pass as a build argument when building the Docker image:
docker build \
  --build-arg VITE_API_BASE_URL=https://api.yourdomain.com \
  -t frontend:latest \
  ./frontend

Docker Compose

Specified in the docker-compose.yml file:
services:
  frontend:
    build:
      context: ./frontend
      args:
        VITE_API_BASE_URL: ${VITE_API_BASE_URL:-http://localhost:8080}

AWS ECS / CI/CD

In your GitHub Actions or CI/CD pipeline:
- name: Build frontend image
  run: |
    docker build \
      --build-arg VITE_API_BASE_URL=${{ secrets.VITE_API_BASE_URL }} \
      -t $ECR_REGISTRY/frontend:latest \
      ./frontend
Important: You must know your production backend URL before building the frontend image. If you need to change the API URL, you must rebuild and redeploy the frontend image.

Environment Variable Summary

Backend (Runtime Configuration)

# Database
DB_HOST=my-rds.xxxxx.eu-west-1.rds.amazonaws.com
DB_PORT=5432
DB_NAME=urlshortener
DB_USERNAME=appuser
DB_PASSWORD=<secret>

# JWT
JWT_SECRET=<secret-at-least-32-chars>
JWT_EXPIRATION_MS=86400000

# Application URLs
APP_BASE_URL=https://go.yourdomain.com
FRONTEND_URL=https://yourdomain.com

# CORS
CORS_ALLOWED_ORIGINS=https://yourdomain.com

# Server
SERVER_PORT=8080

Frontend (Build-Time Configuration)

# API Base URL (embedded at build time)
VITE_API_BASE_URL=https://api.yourdomain.com

AWS ECS Task Definition Example

{
  "family": "adma-backend",
  "containerDefinitions": [
    {
      "name": "backend",
      "image": "ACCOUNT_ID.dkr.ecr.eu-west-1.amazonaws.com/adma/backend:latest",
      "environment": [
        { "name": "DB_HOST", "value": "adma-postgres.xxxxx.eu-west-1.rds.amazonaws.com" },
        { "name": "DB_PORT", "value": "5432" },
        { "name": "DB_NAME", "value": "urlshortener" },
        { "name": "DB_USERNAME", "value": "appuser" },
        { "name": "APP_BASE_URL", "value": "https://go.yourdomain.com" },
        { "name": "CORS_ALLOWED_ORIGINS", "value": "https://yourdomain.com" },
        { "name": "SERVER_PORT", "value": "8080" },
        { "name": "JWT_EXPIRATION_MS", "value": "86400000" }
      ],
      "secrets": [
        {
          "name": "DB_PASSWORD",
          "valueFrom": "arn:aws:ssm:eu-west-1:ACCOUNT:parameter/adma/prod/DB_PASSWORD"
        },
        {
          "name": "JWT_SECRET",
          "valueFrom": "arn:aws:ssm:eu-west-1:ACCOUNT:parameter/adma/prod/JWT_SECRET"
        }
      ]
    }
  ]
}

Validation and Troubleshooting

Backend Startup Validation

The backend validates critical environment variables on startup:
Error: The specified key byte array is X bits which is not secure enough for any JWT HMAC-SHA algorithmCause: JWT_SECRET is shorter than 32 characters (256 bits required for HS256)Solution: Generate a stronger secret:
openssl rand -base64 48
Error: Connection refused or could not connect to serverCause: Database connection parameters are incorrect or database is unreachableSolution: Verify DB_HOST, DB_PORT, DB_NAME, DB_USERNAME, and DB_PASSWORDError: Access denied for userCause: Invalid database credentialsSolution: Check DB_USERNAME and DB_PASSWORD

Frontend Build Validation

Issue: API calls fail with CORS errorsCause: CORS_ALLOWED_ORIGINS on backend doesn’t include frontend originSolution: Add frontend URL to backend’s CORS_ALLOWED_ORIGINSIssue: API calls go to wrong URLCause: VITE_API_BASE_URL was set incorrectly during buildSolution: Rebuild the frontend image with correct VITE_API_BASE_URLIssue: VITE_API_BASE_URL is undefinedCause: Build argument wasn’t passed to Docker buildSolution: Add --build-arg VITE_API_BASE_URL=<url> to docker build command

Security Best Practices

Production Security Checklist:
  • Store JWT_SECRET and DB_PASSWORD in AWS SSM Parameter Store or Secrets Manager
  • Use IAM roles for ECS tasks to access secrets (principle of least privilege)
  • Rotate JWT_SECRET periodically (requires invalidating all existing tokens)
  • Use strong, randomly generated passwords for database
  • Enable RDS encryption at rest
  • Never log sensitive environment variables
  • Use HTTPS for all production URLs
  • Restrict CORS_ALLOWED_ORIGINS to production frontend domain only
  • Enable VPC security groups to isolate RDS from internet

Build docs developers (and LLMs) love