From b016d83c2f251ce6d035c5d5ccb3cf886d939499 Mon Sep 17 00:00:00 2001 From: Markus Busche Date: Mon, 25 Aug 2025 20:28:41 +0000 Subject: [PATCH] Add Caddy server configuration for domain markov.elpatron.me with Let's Encrypt SSL and WebSocket support. Includes: - Caddy service in docker-compose.yml - Caddyfile with SSL and WebSocket configuration - Enhanced Flask app for proxy compatibility - Documentation files (CADDY.md, updated README.md) --- CADDY.md | 49 ++++++++++++++++++++++++++++ Caddyfile | 31 ++++++++++++++++++ README.md | 81 ++++++++++++++++++++++++++++++++++++++++++++++ app/__init__.py | 13 ++++++-- docker-compose.yml | 26 ++++++++++++--- 5 files changed, 194 insertions(+), 6 deletions(-) create mode 100644 CADDY.md create mode 100644 Caddyfile create mode 100644 README.md diff --git a/CADDY.md b/CADDY.md new file mode 100644 index 0000000..c1f92c5 --- /dev/null +++ b/CADDY.md @@ -0,0 +1,49 @@ +# Caddy Server Configuration + +This project uses Caddy as a reverse proxy to handle SSL termination with Let's Encrypt and WebSocket support for the domain `markov.elpatron.me`. + +## Configuration + +The Caddy configuration is defined in the [Caddyfile](Caddyfile) and includes: + +1. Automatic SSL certificate management with Let's Encrypt +2. Reverse proxy to the Flask application +3. Proper WebSocket support for real-time updates +4. Proxy header forwarding for client IP and protocol information + +## Setup Instructions + +1. Update the email address in the [Caddyfile](Caddyfile) to your actual email for Let's Encrypt notifications: + ``` + markov.elpatron.me { + tls your-email@example.com + # ... rest of configuration + } + ``` + +2. Ensure your DNS is properly configured to point `markov.elpatron.me` to your server's IP address. + +3. Start the services with Docker Compose: + ```bash + docker-compose up -d + ``` + +## How It Works + +- Caddy automatically obtains and renews SSL certificates from Let's Encrypt +- All HTTP traffic is automatically redirected to HTTPS +- WebSocket connections are properly handled and forwarded to the Flask-SocketIO application +- Proxy headers are forwarded to preserve client IP and protocol information + +## WebSocket Support + +The configuration includes specific handling for WebSocket upgrade requests to ensure real-time features work correctly: + +``` +@websockets { + header Connection *Upgrade* + header Upgrade websocket +} +``` + +This ensures that SocketIO connections can be established and maintained properly through the proxy. \ No newline at end of file diff --git a/Caddyfile b/Caddyfile new file mode 100644 index 0000000..3cee675 --- /dev/null +++ b/Caddyfile @@ -0,0 +1,31 @@ +markov.elpatron.me { + # Use Let's Encrypt for SSL certificates + elpatron@mailbox.org + + # Proxy all requests to the Flask application + reverse_proxy markov-economics:5000 { + # WebSocket support + header_up Upgrade {header.Upgrade} + header_up Connection {header.Connection} + header_up Host {host} + header_up X-Real-IP {remote_host} + header_up X-Forwarded-For {remote_host} + header_up X-Forwarded-Proto {scheme} + } + + # Handle WebSocket upgrade requests specifically + @websockets { + header Connection *Upgrade* + header Upgrade websocket + } + + reverse_proxy @websockets markov-economics:5000 { + # Ensure WebSocket headers are properly forwarded + header_up Upgrade {header.Upgrade} + header_up Connection {header.Connection} + header_up Host {host} + header_up X-Real-IP {remote_host} + header_up X-Forwarded-For {remote_host} + header_up X-Forwarded-Proto {scheme} + } +} \ No newline at end of file diff --git a/README.md b/README.md new file mode 100644 index 0000000..f7628c6 --- /dev/null +++ b/README.md @@ -0,0 +1,81 @@ +# Capitalism Eats the World + +A simulation-based web application that models economic systems using Markov chains to demonstrate how wealth distribution evolves over time. + +## Overview + +This project provides an interactive simulation of economic dynamics, particularly focusing on how wealth inequality can emerge and persist in market economies. The simulation uses Markov chain models to represent economic mobility and wealth accumulation patterns. + +## Features + +- Interactive web interface for running economic simulations +- Real-time visualization of wealth distribution using Plotly and Matplotlib +- RESTful API endpoints for programmatic access +- WebSocket support for real-time updates during simulations +- Docker containerization for easy deployment + +## Prerequisites + +- Docker and Docker Compose +- A domain name (for production deployment with SSL) + +## Quick Start + +1. Clone the repository: + ```bash + git clone https://github.com/[user]/capitalism-eats-the-world.git + cd capitalism-eats-the-world + ``` + +2. Build and run with Docker Compose: + ```bash + docker-compose up --build + ``` + +3. Access the application at `http://localhost:5000` + +## Production Deployment with Caddy and Let's Encrypt + +For production deployment with automatic SSL certificates, the project includes a Caddy configuration: + +1. Update the [Caddyfile](Caddyfile) with your email address for Let's Encrypt notifications +2. Ensure your domain points to your server's IP address +3. Run with Caddy: + ```bash + docker-compose up -d + ``` + +The application will be available at `https://markov.elpatron.me` with automatic SSL certificate management. + +## Documentation + +- [Docker Configuration](DOCKER.md) - Docker setup and deployment +- [Caddy Configuration](CADDY.md) - Caddy server setup with Let's Encrypt +- [Nginx Configuration](NGINX_CONFIG.md) - Alternative Nginx setup (if applicable) + +## API Endpoints + +- `GET /` - Main simulation interface +- `POST /api/simulation` - Create a new simulation +- `POST /api/simulation//start` - Start a simulation +- `POST /api/simulation//stop` - Stop a simulation +- `GET /api/simulation//data` - Get simulation data +- `GET /api/simulations` - List all simulations + +## WebSocket Events + +- `simulation_progress` - Real-time updates during simulation +- `simulation_complete` - Notification when simulation finishes +- `simulation_error` - Error notifications + +## Technology Stack + +- Backend: Python, Flask, Flask-SocketIO +- Frontend: HTML, CSS, JavaScript +- Visualization: Plotly, Matplotlib +- Containerization: Docker, Docker Compose +- Reverse Proxy: Caddy (for SSL) + +## License + +[MIT License](LICENSE) \ No newline at end of file diff --git a/app/__init__.py b/app/__init__.py index cad546f..b59029d 100644 --- a/app/__init__.py +++ b/app/__init__.py @@ -21,7 +21,10 @@ socketio = SocketIO( transports=['websocket', 'polling'], # Ping settings for better connection detection ping_timeout=60, - ping_interval=25 + ping_interval=25, + # Proxy compatibility settings + allow_upgrades=True, + upgrade_timeout=30 ) # Global simulation manager instance @@ -44,6 +47,10 @@ def create_app(config_name=None): app = Flask(__name__) app.config.from_object(config[config_name]) + # Configure for reverse proxy + from werkzeug.middleware.proxy_fix import ProxyFix + app.wsgi_app = ProxyFix(app.wsgi_app, x_for=1, x_proto=1, x_host=1, x_prefix=1) + # Initialize extensions with proxy-friendly settings socketio.init_app( app, @@ -52,7 +59,9 @@ def create_app(config_name=None): allow_upgrades=True, transports=['websocket', 'polling'], ping_timeout=60, - ping_interval=25 + ping_interval=25, + upgrade_timeout=30, + manage_session=False # Important for proxy compatibility ) # Register blueprints diff --git a/docker-compose.yml b/docker-compose.yml index 12194e2..ebeb3c4 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -1,10 +1,9 @@ -version: '3.8' - services: markov-economics: build: . - ports: - - "5000:5000" + # Remove direct port mapping since Caddy will handle external access + # ports: + # - "5000:5000" environment: - FLASK_ENV=production - FLASK_APP=run.py @@ -22,10 +21,29 @@ services: networks: - markov-network + caddy: + image: caddy:2-alpine + ports: + - "80:80" + - "443:443" + volumes: + - ./Caddyfile:/etc/caddy/Caddyfile + - caddy_data:/data + - caddy_config:/config + depends_on: + - markov-economics + restart: unless-stopped + networks: + - markov-network + networks: markov-network: driver: bridge volumes: markov-data: + driver: local + caddy_data: + driver: local + caddy_config: driver: local \ No newline at end of file