Skip to content

Configuration Management ​

PGRestify CLI provides comprehensive configuration management for PostgREST deployments and Docker setups. This includes environment-specific configurations, security hardening, and deployment optimization.

Overview ​

Configuration management helps you:

  • Generate optimized PostgREST configuration files
  • Set up Docker Compose for development and production
  • Configure environment-specific settings
  • Apply security best practices
  • Manage database connections and authentication

PostgREST Configuration ​

Generate PostgREST Config ​

Create PostgREST configuration files optimized for different environments:

bash
# Interactive configuration generation
pgrestify api config postgrest

# Generate for specific environment
pgrestify api config postgrest --env production

# Generate with custom settings
pgrestify api config postgrest \
  --env staging \
  --port 3001 \
  --schema api \
  --output ./config/postgrest.conf

PostgREST Config Options ​

bash
pgrestify api config postgrest [options]

Options:
  --output <file>         Output file (default: ./postgrest.conf)
  --env <environment>     Environment (development|staging|production)
  --port <port>           Server port (default: 3000)
  --schema <schema>       API schema
  --db-uri <uri>          Database URI (will prompt if not provided)

Environment Configurations ​

Development Environment ​

Optimized for local development with debug features:

ini
# postgrest.conf (Development)
db-uri = "postgresql://postgres:postgres@localhost:5432/myapp_dev"
db-schema = "api"
db-anon-role = "anon"
db-pool = 10
db-pool-timeout = 10

server-host = "0.0.0.0"
server-port = 3000
server-cors-allowed-origins = "*"

jwt-secret = "development-jwt-secret-min-32-chars"
jwt-aud = "authenticated"

log-level = "info"
openapi-server-proxy-uri = "http://localhost:3000"

# Development optimizations
db-prepared-statements = false
db-tx-end = "commit"
db-tx-isolation = "read-committed"
db-max-rows = 1000

Staging Environment ​

Testing environment with production-like settings:

ini
# postgrest.conf (Staging)
db-uri = "postgresql://staginguser:stagingpass@staging-db:5432/myapp_staging"
db-schema = "api"
db-anon-role = "anon"
db-pool = 20
db-pool-timeout = 10

server-host = "0.0.0.0"  
server-port = 3000
server-cors-allowed-origins = "https://staging.myapp.com"

jwt-secret = "staging-jwt-secret-very-secure-32-chars"
jwt-aud = "authenticated"
jwt-role-claim-key = ".role"

log-level = "warn"
openapi-server-proxy-uri = "https://staging-api.myapp.com"

# Staging security
db-prepared-statements = true
db-tx-end = "commit"
db-max-rows = 500

Production Environment ​

Production environment with security hardening:

ini
# postgrest.conf (Production)
db-uri = "postgresql://produser:securepass@prod-db:5432/myapp_prod"
db-schema = "api"
db-anon-role = "anon"
db-pool = 100
db-pool-timeout = 10

server-host = "0.0.0.0"
server-port = 3000
server-cors-allowed-origins = "https://myapp.com,https://www.myapp.com"

jwt-secret = "production-jwt-secret-very-secure-minimum-32-chars"
jwt-aud = "authenticated"
jwt-role-claim-key = ".role"
jwt-secret-is-base64 = false

log-level = "error"
openapi-server-proxy-uri = "https://api.myapp.com"

# Production security hardening
db-prepared-statements = true
db-tx-end = "rollback-allow-override"
db-tx-isolation = "read-committed"
db-max-rows = 100

# Rate limiting and security
server-request-timeout = "10"

Interactive Configuration ​

When running without all options, the CLI guides you through configuration:

bash
$ pgrestify api config postgrest

⚙️  Generating PostgREST Configuration

? Target environment:
❯ Development - Local development with debug features
  Staging - Testing environment with production-like settings  
  Production - Production environment with security hardening

? Server configuration:
  Port: (3000)
  Schema: (api)
  Host: (0.0.0.0)

? Database configuration:
  Database URI: postgresql://user:pass@host:5432/database
  Anonymous role: (anon)
  Authenticated role: (authenticated)
  Connection pool size: (10)

? Security configuration:
  JWT secret: (will be generated)
  CORS origins: (*)
  Request timeout: (10s)

? Performance settings:
  Max rows per request: (1000)
  Enable prepared statements: (Y/n)
  Transaction isolation: (read-committed)

Docker Configuration ​

Generate Docker Setup ​

Create Docker Compose configurations for different deployment scenarios:

bash
# Generate Docker setup
pgrestify api config docker

# Generate with specific services
pgrestify api config docker --services postgres,postgrest,nginx

# Generate for production
pgrestify api config docker --env production --output docker-compose.prod.yml

# Generate with custom networks
pgrestify api config docker --network custom_network

Docker Config Options ​

bash
pgrestify api config docker [options]

Options:
  --output <file>         Output file (default: docker-compose.yml)
  --env <environment>     Environment (development|staging|production)  
  --services <list>       Services to include (postgres,postgrest,nginx,redis)
  --network <name>        Custom network name
  --postgres-version      PostgreSQL version (default: 15-alpine)
  --postgrest-version     PostgREST version (default: latest)

Generated Docker Configurations ​

Development Docker Compose ​

yaml
# docker-compose.yml (Development)
version: '3.8'

services:
  postgres:
    image: postgres:15-alpine
    container_name: pgrestify_postgres_dev
    environment:
      POSTGRES_DB: ${POSTGRES_DB:-myapp_dev}
      POSTGRES_USER: ${POSTGRES_USER:-postgres}
      POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:-postgres}
    ports:
      - "${POSTGRES_PORT:-5432}:5432"
    volumes:
      - postgres_data:/var/lib/postgresql/data
      - ./sql:/docker-entrypoint-initdb.d:ro
    networks:
      - pgrestify_network
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U $POSTGRES_USER -d $POSTGRES_DB"]
      interval: 10s
      timeout: 5s
      retries: 5

  postgrest:
    image: postgrest/postgrest:latest
    container_name: pgrestify_postgrest_dev
    depends_on:
      postgres:
        condition: service_healthy
    environment:
      PGRST_DB_URI: postgresql://${POSTGRES_USER:-postgres}:${POSTGRES_PASSWORD:-postgres}@postgres:5432/${POSTGRES_DB:-myapp_dev}
      PGRST_DB_SCHEMA: ${POSTGREST_SCHEMA:-api}
      PGRST_DB_ANON_ROLE: ${POSTGREST_ANON_ROLE:-anon}
      PGRST_JWT_SECRET: ${JWT_SECRET:-development-jwt-secret-min-32-chars}
      PGRST_OPENAPI_SERVER_PROXY_URI: http://localhost:${POSTGREST_PORT:-3000}
    ports:
      - "${POSTGREST_PORT:-3000}:3000"
    networks:
      - pgrestify_network
    restart: unless-stopped

volumes:
  postgres_data:

networks:
  pgrestify_network:
    driver: bridge

Production Docker Compose ​

yaml
# docker-compose.prod.yml (Production)
version: '3.8'

services:
  postgres:
    image: postgres:15-alpine
    container_name: pgrestify_postgres_prod
    environment:
      POSTGRES_DB: ${POSTGRES_DB}
      POSTGRES_USER: ${POSTGRES_USER}
      POSTGRES_PASSWORD_FILE: /run/secrets/postgres_password
    secrets:
      - postgres_password
    volumes:
      - postgres_data:/var/lib/postgresql/data
      - postgres_backup:/backup
    networks:
      - internal_network
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U $POSTGRES_USER -d $POSTGRES_DB"]
      interval: 30s
      timeout: 10s
      retries: 3
    deploy:
      resources:
        limits:
          memory: 1G
          cpus: "0.5"
        reservations:
          memory: 512M
          cpus: "0.25"

  postgrest:
    image: postgrest/postgrest:v11.2.0  # Pinned version for production
    container_name: pgrestify_postgrest_prod
    depends_on:
      postgres:
        condition: service_healthy
    environment:
      PGRST_DB_URI: postgresql://${POSTGRES_USER}:${POSTGRES_PASSWORD}@postgres:5432/${POSTGRES_DB}
      PGRST_DB_SCHEMA: ${POSTGREST_SCHEMA:-api}
      PGRST_DB_ANON_ROLE: ${POSTGREST_ANON_ROLE:-anon}
      PGRST_JWT_SECRET_FILE: /run/secrets/jwt_secret
      PGRST_LOG_LEVEL: error
      PGRST_DB_POOL: 100
      PGRST_DB_MAX_ROWS: 100
      PGRST_DB_PREPARED_STATEMENTS: true
    secrets:
      - jwt_secret
    networks:
      - internal_network
      - web_network
    restart: unless-stopped
    deploy:
      resources:
        limits:
          memory: 512M
          cpus: "0.5"
        reservations:
          memory: 256M
          cpus: "0.25"

  nginx:
    image: nginx:alpine
    container_name: pgrestify_nginx_prod
    depends_on:
      - postgrest
    ports:
      - "80:80"
      - "443:443"
    volumes:
      - ./nginx/nginx.conf:/etc/nginx/nginx.conf:ro
      - ./nginx/ssl:/etc/nginx/ssl:ro
      - nginx_cache:/var/cache/nginx
    networks:
      - web_network
    restart: unless-stopped

secrets:
  postgres_password:
    file: ./secrets/postgres_password.txt
  jwt_secret:
    file: ./secrets/jwt_secret.txt

volumes:
  postgres_data:
  postgres_backup:
  nginx_cache:

networks:
  internal_network:
    driver: bridge
    internal: true
  web_network:
    driver: bridge

Environment Variables ​

PostgREST Environment Variables ​

Generated configurations use environment variables for flexibility:

bash
# .env.example
# Database Configuration
POSTGRES_DB=myapp_db
POSTGRES_USER=postgres
POSTGRES_PASSWORD=secure-password
POSTGRES_PORT=5432

# PostgREST Configuration  
POSTGREST_PORT=3000
POSTGREST_SCHEMA=api
POSTGREST_ANON_ROLE=anon
JWT_SECRET=your-jwt-secret-minimum-32-characters

# Optional Configuration
POSTGREST_DB_POOL=20
POSTGREST_MAX_ROWS=1000
CORS_ORIGINS=*

# SSL Configuration (Production)
SSL_CERT_PATH=/path/to/cert.pem
SSL_KEY_PATH=/path/to/key.pem

Security Environment Variables ​

bash
# Security-focused variables
JWT_SECRET_FILE=/run/secrets/jwt_secret
POSTGRES_PASSWORD_FILE=/run/secrets/postgres_password
ADMIN_PASSWORD_FILE=/run/secrets/admin_password

# CORS and security headers
CORS_ALLOWED_ORIGINS=https://myapp.com,https://www.myapp.com
RATE_LIMIT_PER_MINUTE=100
REQUEST_TIMEOUT=10

# Monitoring and logging
LOG_LEVEL=error
METRICS_ENABLED=true
HEALTH_CHECK_ENABLED=true

Configuration Validation ​

Validate Configurations ​

Check configuration files for common issues:

bash
# Validate PostgREST config
pgrestify validate --config postgrest.conf

# Validate Docker setup
pgrestify validate --docker docker-compose.yml

# Comprehensive validation
pgrestify validate --all

Validation Checks ​

The validator checks for:

  1. PostgREST Configuration:

    • Valid database URI format
    • Proper JWT secret length (minimum 32 characters)
    • Correct role configuration
    • Security settings validation
  2. Docker Configuration:

    • Service dependencies
    • Network configuration
    • Volume mounts
    • Health checks
  3. Environment Variables:

    • Required variables present
    • Secure defaults
    • Production readiness

Validation Output ​

bash
$ pgrestify validate --config postgrest.conf

✅ Configuration Validation Results

PostgREST Configuration:
  ✅ Database URI format valid
  ✅ JWT secret length adequate (32+ characters)
  ✅ Roles configured correctly
  ❌ CORS origins too permissive for production
  ⚠️  Log level set to 'info' (recommend 'error' for production)

Security Checks:
  ✅ No hardcoded passwords found
  ✅ Environment variables used properly
  ❌ JWT secret should use environment variable
  
Recommendations:
  - Set CORS origins to specific domains
  - Move JWT secret to environment variable
  - Consider using JWT secret file in production

Issues Found: 2 errors, 1 warning

Configuration Templates ​

Custom Configuration Templates ​

Create reusable configuration templates:

bash
# Create template from existing config
pgrestify api config template create my-template --from postgrest.conf

# Use template for new projects
pgrestify api config postgrest --template my-template

# List available templates
pgrestify api config template list

Best Practices ​

Security Configuration ​

  1. Never hardcode secrets in configuration files
  2. Use environment variables or secret files
  3. Set restrictive CORS origins in production
  4. Use minimum required permissions for database roles
  5. Enable prepared statements for performance and security

Performance Configuration ​

  1. Tune connection pool size based on expected load
  2. Set appropriate max rows limits
  3. Use read-committed isolation for most use cases
  4. Enable request timeout to prevent hanging requests
  5. Configure proper logging levels

Production Configuration ​

  1. Pin Docker image versions for reproducible deployments
  2. Use secrets management for sensitive data
  3. Configure resource limits for containers
  4. Set up proper health checks and monitoring
  5. Use SSL/TLS termination at load balancer or reverse proxy

Troubleshooting Configuration ​

Common Issues ​

Connection Issues ​

bash
# Error: Connection refused
# Check database URI and network configuration
PGRST_DB_URI=postgresql://user:pass@correct-host:5432/database

Authentication Issues ​

bash
# Error: JWT validation failed
# Ensure JWT secret matches between client and server
JWT_SECRET=same-secret-on-both-sides-min-32-chars

CORS Issues ​

bash
# Error: CORS policy blocked
# Add client domain to allowed origins
server-cors-allowed-origins = "https://client-domain.com"

Testing Configuration ​

Test generated configurations:

bash
# Test PostgREST config
postgrest postgrest.conf

# Test Docker setup
docker-compose up --dry-run

# Test environment variables
env | grep POSTGREST

Integration with Other Commands ​

Complete Workflow ​

bash
# 1. Initialize project
pgrestify api init --template blog

# 2. Generate configuration
pgrestify api config postgrest --env production
pgrestify api config docker --env production

# 3. Set up environment
cp .env.example .env
# Edit .env with production values

# 4. Start services
docker-compose -f docker-compose.prod.yml up -d

# 5. Validate deployment
pgrestify validate --all
curl http://localhost:3000

Summary ​

PGRestify's configuration management provides comprehensive tools for setting up PostgREST deployments with proper security, performance optimization, and environment-specific configurations. The generated configurations follow best practices and can be easily customized for different deployment scenarios.

Released under the MIT License.