Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
114 changes: 91 additions & 23 deletions .env.example
Original file line number Diff line number Diff line change
@@ -1,20 +1,69 @@
# =============================================================================
# WINDMAR Environment Configuration
# Copy this file to .env and adjust values for your environment
# =============================================================================
#
# Copy this file to .env and configure for your environment:
# cp .env.example .env
#
# IMPORTANT: Never commit .env to version control!
#
# =============================================================================

# =============================================================================
# API Configuration
# REQUIRED SETTINGS - Must be configured before deployment
# =============================================================================
API_HOST=0.0.0.0
API_PORT=8000
API_RELOAD=false
API_LOG_LEVEL=info

# CORS origins (comma-separated)
CORS_ORIGINS=http://localhost:3000,http://localhost:3001
# Database Configuration
DB_USER=windmar
DB_PASSWORD=CHANGE_THIS_TO_A_SECURE_PASSWORD
DB_NAME=windmar
DB_HOST=db
DB_PORT=5432
DATABASE_URL=postgresql://${DB_USER}:${DB_PASSWORD}@${DB_HOST}:${DB_PORT}/${DB_NAME}

# Redis Configuration
REDIS_PASSWORD=CHANGE_THIS_TO_A_SECURE_PASSWORD
REDIS_URL=redis://:${REDIS_PASSWORD}@redis:6379/0

# API Security - CRITICAL: Generate a unique secret key!
# Generate with: openssl rand -hex 32
API_SECRET_KEY=CHANGE_THIS_GENERATE_WITH_OPENSSL_RAND_HEX_32

# CORS Origins - Comma-separated list of allowed origins
# Remove localhost entries for production!
CORS_ORIGINS=https://yourdomain.com,https://www.yourdomain.com

# =============================================================================
# APPLICATION SETTINGS
# =============================================================================

# Environment: development, staging, production
ENVIRONMENT=production

# Logging level: debug, info, warning, error
LOG_LEVEL=info

# Authentication (MUST be true in production)
AUTH_ENABLED=true

# Rate limiting (recommended for production)
RATE_LIMIT_ENABLED=true
RATE_LIMIT_PER_MINUTE=60
RATE_LIMIT_PER_HOUR=1000

# =============================================================================
# SERVICE PORTS (for docker-compose)
# =============================================================================

API_PORT=8000
FRONTEND_PORT=3000
# DB_PORT=5432 # Uncomment only if you need external DB access
# REDIS_PORT=6379 # Uncomment only if you need external Redis access

# =============================================================================
# Live Data Configuration
# WEATHER DATA CONFIGURATION
# =============================================================================

# Use mock data (true) or real Copernicus data (false)
COPERNICUS_MOCK_MODE=true

Expand All @@ -24,33 +73,52 @@ COPERNICUS_USERNAME=
COPERNICUS_PASSWORD=

# =============================================================================
# Calibration Configuration
# MONITORING & OBSERVABILITY
# =============================================================================

# Sentry DSN for error tracking (optional but recommended)
SENTRY_DSN=

# Enable Prometheus metrics endpoint
METRICS_ENABLED=true

# =============================================================================
# CALIBRATION & SIMULATION
# =============================================================================

# Learning rate for coefficient updates (0.001 - 0.1)
CALIBRATION_LEARNING_RATE=0.01

# Path to persist calibration state (optional)
# Path to persist calibration state
CALIBRATION_PERSISTENCE_PATH=data/calibration.json

# =============================================================================
# Simulation Defaults
# =============================================================================
# Default wave parameters for simulation mode
# Simulation defaults
SIM_WAVE_HEIGHT_M=2.5
SIM_WAVE_PERIOD_S=8.0
SIM_START_LAT=43.5
SIM_START_LON=7.0
SIM_SPEED_KTS=12.0
SIM_HEADING_DEG=270.0

# =============================================================================
# Data Storage
# DATA STORAGE
# =============================================================================

GRIB_CACHE_DIR=data/grib_cache
DATA_DIR=data

# =============================================================================
# Logging
# PRODUCTION CHECKLIST
# =============================================================================
#
# Before deploying to production, ensure:
#
# [ ] DB_PASSWORD is a strong, unique password
# [ ] REDIS_PASSWORD is a strong, unique password
# [ ] API_SECRET_KEY is generated with: openssl rand -hex 32
# [ ] CORS_ORIGINS contains only your production domains (no localhost)
# [ ] AUTH_ENABLED=true
# [ ] RATE_LIMIT_ENABLED=true
# [ ] ENVIRONMENT=production
# [ ] SENTRY_DSN is configured for error tracking
# [ ] SSL/TLS is configured via reverse proxy
# [ ] Database backups are scheduled
# [ ] Log aggregation is configured
#
# =============================================================================
LOG_LEVEL=INFO
LOG_FORMAT=%(asctime)s - %(name)s - %(levelname)s - %(message)s
100 changes: 82 additions & 18 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -1,15 +1,26 @@
# Multi-stage build for WINDMAR backend
FROM python:3.11-slim as base
# =============================================================================
# WINDMAR API - Production Dockerfile
# =============================================================================
# Multi-stage build optimized for security and performance
#
# Build: docker build -t windmar-api:latest .
# Run: docker run -p 8000:8000 windmar-api:latest
# =============================================================================

# Set environment variables
# -----------------------------------------------------------------------------
# Stage 1: Build dependencies
# -----------------------------------------------------------------------------
FROM python:3.11-slim AS builder

# Set build-time environment variables
ENV PYTHONUNBUFFERED=1 \
PYTHONDONTWRITEBYTECODE=1 \
PIP_NO_CACHE_DIR=1 \
PIP_DISABLE_PIP_VERSION_CHECK=1

WORKDIR /app
WORKDIR /build

# Install system dependencies for scientific libraries
# Install build dependencies
RUN apt-get update && apt-get install -y --no-install-recommends \
gcc \
g++ \
Expand All @@ -19,26 +30,79 @@ RUN apt-get update && apt-get install -y --no-install-recommends \
libproj-dev \
&& rm -rf /var/lib/apt/lists/*

# Copy requirements first for better caching
# Copy requirements and install dependencies
COPY requirements.txt .
RUN pip install --no-cache-dir --target=/build/deps -r requirements.txt

# -----------------------------------------------------------------------------
# Stage 2: Production runtime
# -----------------------------------------------------------------------------
FROM python:3.11-slim AS runtime

# Labels for container metadata
LABEL org.opencontainers.image.title="WINDMAR API" \
org.opencontainers.image.description="Maritime Route Optimization API" \
org.opencontainers.image.vendor="SL Mar" \
org.opencontainers.image.version="2.1.0" \
org.opencontainers.image.licenses="Commercial"

# Install Python dependencies
RUN pip install --no-cache-dir -r requirements.txt
# Security: Run as non-root user
RUN groupadd --gid 1000 windmar \
&& useradd --uid 1000 --gid windmar --shell /bin/bash --create-home windmar

# Set runtime environment variables
ENV PYTHONUNBUFFERED=1 \
PYTHONDONTWRITEBYTECODE=1 \
PYTHONPATH=/app \
PATH="/app/deps/bin:$PATH" \
# Application defaults (override via environment)
API_HOST=0.0.0.0 \
API_PORT=8000 \
LOG_LEVEL=info \
ENVIRONMENT=production

WORKDIR /app

# Install runtime system dependencies only
RUN apt-get update && apt-get install -y --no-install-recommends \
libeccodes0 \
libgeos-c1v5 \
libproj25 \
curl \
&& rm -rf /var/lib/apt/lists/* \
&& apt-get clean

# Copy Python dependencies from builder
COPY --from=builder /build/deps /app/deps

# Copy application code
COPY src/ ./src/
COPY api/ ./api/
COPY data/ ./data/
COPY --chown=windmar:windmar src/ ./src/
COPY --chown=windmar:windmar api/ ./api/
COPY --chown=windmar:windmar LICENSE ./

# Create necessary directories with correct permissions
RUN mkdir -p data/grib data/vessel_database data/calibration data/weather_cache logs \
&& chown -R windmar:windmar /app

# Create data directories
RUN mkdir -p data/grib data/vessel_database data/calibration
# Switch to non-root user
USER windmar

# Expose API port
EXPOSE 8000

# Health check
HEALTHCHECK --interval=30s --timeout=10s --start-period=5s --retries=3 \
CMD python -c "import requests; requests.get('http://localhost:8000/api/health')" || exit 1
# Health check with curl (more reliable than Python in minimal image)
HEALTHCHECK --interval=30s --timeout=10s --start-period=40s --retries=3 \
CMD curl -f http://localhost:8000/api/health || exit 1

# Run the API server
CMD ["uvicorn", "api.main:app", "--host", "0.0.0.0", "--port", "8000", "--workers", "4"]
# Run the API server with production settings
# - Workers based on CPU cores (2 * cores + 1 is recommended)
# - Access log disabled for performance (structured logging handles this)
# - Proxy headers enabled for load balancer compatibility
CMD ["python", "-m", "uvicorn", "api.main:app", \
"--host", "0.0.0.0", \
"--port", "8000", \
"--workers", "4", \
"--proxy-headers", \
"--forwarded-allow-ips", "*", \
"--access-log", \
"--log-level", "info"]
Loading
Loading