Files
TimeTracker/AUTOMATIC_HTTPS_SUMMARY.md
Dries Peeters 94e8e49439 feat: Add HTTPS support with mkcert and automatic SSL configuration
Add comprehensive HTTPS support with two deployment options:
- mkcert for local development with trusted certificates
- Automatic SSL with Let's Encrypt for production

HTTPS Implementation:
- Add docker-compose.https-mkcert.yml for local HTTPS development
- Add docker-compose.https-auto.yml for automatic SSL certificates
- Create Dockerfile.mkcert for certificate generation
- Add setup scripts (setup-https-mkcert.sh/bat)
- Add startup scripts (start-https.sh/bat)
- Add certificate generation script (generate-mkcert-certs.sh)

CSRF and IP Access Fixes:
- Fix CSRF token validation for IP-based access
- Add CSRF troubleshooting documentation
- Update configuration to handle various access patterns

Documentation:
- Add HTTPS_MKCERT_GUIDE.md with setup instructions
- Add README_HTTPS.md with general HTTPS documentation
- Add README_HTTPS_AUTO.md for automatic SSL setup
- Add AUTOMATIC_HTTPS_SUMMARY.md
- Add CSRF_IP_ACCESS_FIX.md and CSRF_IP_FIX_SUMMARY.md
- Add docs/CSRF_IP_ACCESS_GUIDE.md
- Update main README.md with HTTPS information

Configuration:
- Update .gitignore for SSL certificates and nginx configs
- Update env.example with new HTTPS-related variables
- Update docker-compose.yml with SSL configuration options

This enables secure HTTPS access in both development and production
environments while maintaining compatibility with existing deployments.
2025-10-13 18:32:45 +02:00

11 KiB

Automatic HTTPS Implementation - Complete Summary

🎯 Mission Accomplished

HTTPS is now fully automatic at container startup! No manual steps required.


🚀 How to Use (The Easy Way)

One-Command Startup

Windows:

start-https.bat

Linux/Mac:

bash start-https.sh

That's it! Everything else happens automatically:

  1. Certificates generated (if needed)
  2. nginx configured
  3. Security settings enabled
  4. All services started with HTTPS

🏗️ Implementation Architecture

Automatic Certificate Generation

Two deployment modes:

Mode 1: Self-Signed Certificates (Default)

docker-compose -f docker-compose.yml -f docker-compose.https-auto.yml up -d

Flow:

1. certgen init container starts
   ├─ Checks if nginx/ssl/cert.pem exists
   ├─ If missing: generates self-signed certificate
   │  ├─ Uses OpenSSL
   │  ├─ Valid for 10 years
   │  └─ Includes localhost + detected IP
   └─ Exits successfully

2. nginx starts (depends on certgen completion)
   ├─ Uses certificates from nginx/ssl/
   ├─ Listens on ports 80 (redirect) and 443 (HTTPS)
   └─ Proxies to app:8080

3. app starts with secure settings
   ├─ WTF_CSRF_SSL_STRICT=true
   ├─ SESSION_COOKIE_SECURE=true
   └─ CSRF_COOKIE_SECURE=true

Mode 2: mkcert Trusted Certificates

docker-compose -f docker-compose.yml -f docker-compose.https-mkcert.yml up -d

Flow:

1. mkcert init container starts
   ├─ Has mkcert pre-installed
   ├─ Checks if nginx/ssl/cert.pem exists
   ├─ If missing: 
   │  ├─ Installs local CA
   │  ├─ Generates trusted certificate
   │  ├─ Copies rootCA.pem for host installation
   │  └─ Valid for 10 years
   └─ Exits successfully

2. nginx starts (same as Mode 1)

3. app starts (same as Mode 1)

📁 Files Created

Core Scripts

File Purpose
start-https.sh Automatic startup for Linux/Mac
start-https.bat Automatic startup for Windows
setup-https-mkcert.sh Manual mkcert setup (legacy)
setup-https-mkcert.bat Manual mkcert setup (legacy)

Docker Configurations

File Purpose
docker-compose.https-auto.yml Self-signed certificates (automatic)
docker-compose.https-mkcert.yml mkcert certificates (automatic)
docker/Dockerfile.mkcert mkcert image builder

Certificate Generation

File Purpose
scripts/generate-certs.sh Self-signed cert generator
docker/generate-mkcert-certs.sh mkcert cert generator

Documentation

File Purpose
README_HTTPS_AUTO.md Automatic HTTPS guide
README_HTTPS.md Manual HTTPS guide
HTTPS_MKCERT_GUIDE.md Detailed mkcert documentation

🔧 Technical Details

Init Container Pattern

Using Docker's init container pattern for certificate generation:

services:
  certgen:
    image: alpine:latest
    volumes:
      - ./nginx/ssl:/certs
    command: sh /scripts/generate-certs.sh
    restart: "no"  # Runs once

  nginx:
    depends_on:
      certgen:
        condition: service_completed_successfully  # Waits for certgen
    # ... rest of config

Benefits:

  • Idempotent (safe to run multiple times)
  • No certificates needed in repo
  • Auto-generates on first run
  • Reuses existing certificates
  • No manual intervention

Certificate Persistence

Certificates stored in nginx/ssl/:

nginx/ssl/
├── cert.pem       # Public certificate
├── key.pem        # Private key
└── rootCA.pem     # CA cert (mkcert only)

Lifecycle:

  1. First run: Generated by init container
  2. Subsequent runs: Reused (init container detects and skips)
  3. Persist across container restarts
  4. Valid for 10 years

Security Configuration

Automatically applied via docker-compose:

app:
  environment:
    - WTF_CSRF_SSL_STRICT=true     # Strict CSRF over HTTPS
    - SESSION_COOKIE_SECURE=true   # Cookies only over HTTPS
    - CSRF_COOKIE_SECURE=true      # CSRF cookies only over HTTPS

Also updates .env file:

# Automatically added/updated by start-https script
WTF_CSRF_SSL_STRICT=true
SESSION_COOKIE_SECURE=true
CSRF_COOKIE_SECURE=true

🔐 Certificate Types Comparison

Feature Self-Signed mkcert
Setup Zero config One-time CA install
Browser Warning Yes (safe to bypass) No warnings
Encryption Full TLS 1.2/1.3 Full TLS 1.2/1.3
Valid For 10 years 10 years
Trust Only you All browsers (after CA install)
Best For Quick testing Regular development
External Devices Need CA install + bypass Need CA install only

📊 Decision Flow

User runs: start-https.sh/bat
         │
         ↓
   Detect local IP
         │
         ↓
   Create nginx config (if missing)
         │
         ↓
   Update .env with HTTPS settings
         │
         ↓
   Ask: Which certificate type?
         │
    ┌────┴────┐
    ↓         ↓
 Self-Signed  mkcert
    │         │
    │    (Check if mkcert installed)
    │         │
    │    ┌────┴────┐
    │    ↓         ↓
    │  Found    Not Found
    │    │         │
    │    │    Fall back to
    │    │    self-signed
    ↓    ↓         ↓
 docker-compose.https-auto.yml
         │
         ↓
   certgen/mkcert init container
         │
         ↓
   Generate certificates (if missing)
         │
         ↓
   nginx + app start with HTTPS
         │
         ↓
   Access: https://localhost

🎯 Usage Scenarios

Scenario 1: First-Time Developer

# Clone repo
git clone ...
cd TimeTracker

# Create config
cp env.example .env

# Start with HTTPS (automatic!)
bash start-https.sh

# Choose option 1 (self-signed)
# Access: https://localhost
# Click through browser warning once
# Done! ✅

Scenario 2: Regular Development

# Install mkcert once
brew install mkcert  # or choco install mkcert

# Start with HTTPS
bash start-https.sh

# Choose option 2 (mkcert)
# Install CA: nginx/ssl/rootCA.pem (one-time)
# Restart browser
# Access: https://localhost
# No warnings ever! ✅

Scenario 3: Production-Like Testing

# Use automatic HTTPS with mkcert
bash start-https.sh

# Option 2 (mkcert)
# All security settings: strict mode
# Test with real HTTPS behavior
# Perfect for pre-production testing ✅

Scenario 4: Network Access (LAN)

# Start with automatic HTTPS
bash start-https.sh

# Detects IP: 192.168.1.100
# Access from any device: https://192.168.1.100
# With mkcert: install CA once, no warnings
# With self-signed: bypass warning once per device
# All devices can access! ✅

🔄 Certificate Lifecycle

First Run

start-https.sh
   ↓
certgen checks: nginx/ssl/cert.pem missing
   ↓
Generates new certificate
   ↓
Saves to nginx/ssl/
   ↓
nginx uses new certificate
   ↓
App starts with HTTPS ✅

Subsequent Runs

start-https.sh
   ↓
certgen checks: nginx/ssl/cert.pem exists
   ↓
"Certificates already exist, skipping"
   ↓
Exits immediately
   ↓
nginx uses existing certificate
   ↓
App starts with HTTPS ✅

Regeneration (if needed)

# Delete certificates
rm -rf nginx/ssl/*

# Restart
bash start-https.sh
   ↓
certgen detects missing certificates
   ↓
Generates fresh certificates
   ↓
nginx uses new certificates ✅

🛠️ Troubleshooting

Issue: nginx Won't Start

Check init container logs:

docker-compose logs certgen
# or
docker-compose logs mkcert

Verify certificates exist:

ls -la nginx/ssl/
# Should show: cert.pem, key.pem

Issue: Browser Shows Warning (with mkcert)

CA not installed:

  1. Check nginx/ssl/rootCA.pem exists
  2. Install it (double-click on Windows/Mac)
  3. Restart browser completely

Wrong certificates:

# Regenerate
rm -rf nginx/ssl/*
bash start-https.sh

Issue: Port 443 in Use

Find conflicting service:

# Windows
netstat -ano | findstr :443

# Linux/Mac  
lsof -i :443

Stop it or change nginx port


📈 Benefits Achieved

For Users

Zero manual configuration One command to HTTPS Choice of certificate types Automatic security hardening Works with IP addresses No CSRF cookie issues

For Developers

Clean development experience Production-like HTTPS testing No certificate management Git-friendly (certs not committed) Reproducible across environments

For Operations

Idempotent deployment Container-native approach Minimal dependencies Self-contained solution Easy troubleshooting


This implementation also solves:

  1. CSRF Cookie Issues - Strict HTTPS mode fixes IP access problems
  2. Security Headers - Automatically applied
  3. Cookie Security - Secure flags enabled
  4. Mixed Content - All traffic over HTTPS
  5. WebSocket Support - Upgrade headers configured

📚 Documentation Map

AUTOMATIC_HTTPS_SUMMARY.md (this file)
   │
   ├─ Quick Start
   │  └─ README_HTTPS_AUTO.md
   │
   ├─ Manual Setup (Legacy)
   │  ├─ README_HTTPS.md
   │  └─ HTTPS_MKCERT_GUIDE.md
   │
   ├─ CSRF Issues
   │  ├─ CSRF_IP_ACCESS_FIX.md
   │  ├─ CSRF_IP_FIX_SUMMARY.md
   │  └─ docs/CSRF_IP_ACCESS_GUIDE.md
   │
   └─ Advanced
      └─ docs/HTTPS_SETUP_GUIDE.md

🎉 Summary

What We Built

Fully Automatic HTTPS System:

  • 🚀 One-command startup
  • 🔐 Auto-generated certificates
  • 🔧 Self-configuring nginx
  • ⚙️ Auto-hardened security settings
  • 🔄 Persistent across restarts
  • 📱 Works with any device
  • Zero manual intervention

Quick Commands

# Start everything with HTTPS (automatic!)
bash start-https.sh           # Linux/Mac
start-https.bat               # Windows

# Access securely
https://localhost
https://192.168.1.100

# View logs
docker-compose logs -f

# Stop
docker-compose down

The Result

Before:

  • Manual certificate generation required
  • Complex nginx configuration
  • Manual security settings
  • CSRF issues with IP addresses
  • Multiple scripts to run

After:

  • One command: bash start-https.sh
  • Everything automatic
  • HTTPS just works
  • No CSRF issues
  • Production-ready security

Implementation Complete! 🎊

Enjoy your automatic HTTPS TimeTracker! 🔒🚀