# Launchpad Gateway A production-ready Traefik-based reverse proxy gateway with automatic SSL/TLS, analytics, monitoring, and container management. ## 🚀 Features - **Automatic SSL/TLS** certificates via Let's Encrypt - **Reverse Proxy** with Traefik v3.1 - **Web Analytics** with Umami and PostgreSQL - **Container Management** via Portainer - **Uptime Monitoring** with Uptime Kuma - **Security Headers** and Basic Authentication - **Flexible Domain Routing** (subdomains, paths, custom rules) ## 🏗️ Architecture ``` Internet → Traefik (Port 80/443) → Internal Services (traefik_proxy network) ``` ### Current Services - **Traefik Dashboard**: `traefik.gate.${DOMAIN}` - Reverse proxy management - **Portainer**: `portainer.gate.${DOMAIN}` - Docker container management - **Uptime Kuma**: `uptime.gate.${DOMAIN}` - Service monitoring - **Umami Analytics**: `umami.gate.${DOMAIN}` - Web analytics dashboard ## 🛠️ Quick Start ### Prerequisites - Docker and Docker Compose V2 installed (using `docker compose` command) - Domain name with DNS pointing to your server - Ports 80 and 443 open ### 1. Setup Environment ```bash # Clone the repository git clone https://github.com/elfateh4/launchpad-gateway.git cd launchpad-gateway # Copy environment file cp .env.example .env # Edit your configuration nano .env ``` ### 2. Configure Environment Variables Update `.env` with your settings: ```bash # Domain and timezone DOMAIN=your-domain.com TZ=Your/Timezone # Let's Encrypt email ACME_EMAIL=admin@your-domain.com # Basic auth (generate with: htpasswd -nB admin) BASIC_AUTH_USERS=admin:$$2y$$05$$your_hashed_password # Database credentials UMAMI_DB_USER=umami UMAMI_DB_PASS=your_secure_password UMAMI_DB_NAME=umami UMAMI_APP_SECRET=your_64_character_secret ``` ### 3. Deploy the Gateway ```bash docker compose up -d ``` ### 4. Access Services - **Traefik Dashboard**: `https://traefik.gate.your-domain.com` - **Portainer**: `https://portainer.gate.your-domain.com` - **Uptime Kuma**: `https://uptime.gate.your-domain.com` - **Umami Analytics**: `https://umami.gate.your-domain.com` ## 📋 Adding New Services ### Domain Pattern Options Choose the best domain pattern for your service: | Pattern | Example | Best For | |---------|---------|----------| | **Root Domain** | `example.com` | Main application | | **Direct Subdomain** | `app.example.com` | Standalone services | | **Functional Subdomain** | `api.example.com`, `admin.example.com` | Role-based access | | **Path-Based** | `example.com/api` | Microservices, APIs | | **Environment-Based** | `staging.example.com` | Dev/staging environments | ### Basic Service Template 1. **Add volumes** (if needed) to the top of `docker-compose.yml`: ```yaml volumes: your_service_data: ``` 2. **Add service** to the services section: ```yaml your-service: image: your-service:latest container_name: your-service restart: unless-stopped networks: [traefik_proxy] volumes: - your_service_data:/app/data # if persistent storage needed labels: - traefik.enable=true - traefik.docker.network=traefik_proxy - traefik.http.routers.your-service.rule=Host(`app.${DOMAIN}`) - traefik.http.routers.your-service.entrypoints=websecure - traefik.http.routers.your-service.tls.certresolver=le - traefik.http.routers.your-service.middlewares=security-headers - traefik.http.services.your-service.loadbalancer.server.port=3000 ``` 3. **Deploy the changes**: ```bash docker compose up -d ``` ## 🔧 Service Examples ### WordPress Blog **Add to networks:** ```yaml networks: traefik_proxy: name: traefik_proxy external: true wordpress_network: name: wordpress_network ``` **Add to volumes:** ```yaml volumes: wordpress_data: wordpress_db_data: ``` **Add to services:** ```yaml wordpress: image: wordpress:latest container_name: wordpress restart: unless-stopped networks: - traefik_proxy # For Traefik access - wordpress_network # For database access environment: WORDPRESS_DB_HOST: wordpress-db WORDPRESS_DB_USER: ${WP_DB_USER} WORDPRESS_DB_PASSWORD: ${WP_DB_PASS} WORDPRESS_DB_NAME: ${WP_DB_NAME} depends_on: [wordpress-db] volumes: - wordpress_data:/var/www/html labels: - traefik.enable=true - traefik.docker.network=traefik_proxy - traefik.http.routers.wordpress.rule=Host(`blog.${DOMAIN}`) - traefik.http.routers.wordpress.entrypoints=websecure - traefik.http.routers.wordpress.tls.certresolver=le - traefik.http.routers.wordpress.middlewares=umami-analytics,security-headers - traefik.http.services.wordpress.loadbalancer.server.port=80 wordpress-db: image: mysql:8.0 container_name: wordpress-db restart: unless-stopped networks: - wordpress_network # Only on internal network environment: MYSQL_DATABASE: ${WP_DB_NAME} MYSQL_USER: ${WP_DB_USER} MYSQL_PASSWORD: ${WP_DB_PASS} MYSQL_ROOT_PASSWORD: ${WP_DB_ROOT_PASS} volumes: - wordpress_db_data:/var/lib/mysql ``` ### API Service with Path Routing ```yaml api-service: image: your-api:latest container_name: api-service restart: unless-stopped networks: [traefik_proxy] labels: - traefik.enable=true - traefik.docker.network=traefik_proxy - traefik.http.routers.api.rule=Host(`${DOMAIN}`) && PathPrefix(`/api`) - traefik.http.routers.api.entrypoints=websecure - traefik.http.routers.api.tls.certresolver=le - traefik.http.routers.api.middlewares=security-headers - traefik.http.services.api.loadbalancer.server.port=8000 ``` ## 🔒 Security Features ### Network Security Best Practices - **Separate networks** for different service stacks - **Only expose application containers** to `traefik_proxy` network - **Keep databases isolated** on internal networks - **Use multiple networks** for services that need both external and internal access ### Network Architecture Example ```yaml networks: traefik_proxy: external: true # For Traefik routing app_network: name: app_network # For app-specific services db_network: name: db_network # For database isolation services: frontend: networks: [traefik_proxy, app_network] # Accessible via Traefik + internal backend: networks: [app_network, db_network] # Internal only + database access database: networks: [db_network] # Database network only - not exposed ``` ### Available Middlewares - **`security-headers`**: HSTS, XSS protection, content type sniffing prevention - **`basic-auth`**: HTTP Basic Authentication for admin interfaces - **`umami-analytics`**: Automatic web analytics tracking ### Usage Examples ```yaml # Public application with analytics - traefik.http.routers.app.middlewares=umami-analytics,security-headers # Admin interface with authentication - traefik.http.routers.admin.middlewares=basic-auth,security-headers # API endpoint (security headers only) - traefik.http.routers.api.middlewares=security-headers ``` ## 🌐 Advanced Routing ### Multiple Domains ```yaml # Main app on root domain - traefik.http.routers.main.rule=Host(`${DOMAIN}`) # API on subdomain - traefik.http.routers.api.rule=Host(`api.${DOMAIN}`) # Admin with path - traefik.http.routers.admin.rule=Host(`${DOMAIN}`) && PathPrefix(`/admin`) ``` ### Environment-Based Routing ```yaml # Production - traefik.http.routers.app-prod.rule=Host(`app.${DOMAIN}`) # Staging (with basic auth) - traefik.http.routers.app-staging.rule=Host(`staging.${DOMAIN}`) - traefik.http.routers.app-staging.middlewares=basic-auth,security-headers ``` ## 📊 Monitoring & Analytics ### Built-in Monitoring - **Uptime Kuma**: Service availability monitoring - **Traefik Dashboard**: Traffic and routing metrics - **Umami Analytics**: Web traffic analytics (privacy-focused) ### Adding Services to Uptime Kuma Uptime Kuma requires manual configuration through its web interface. After deploying a new service: 1. **Access Uptime Kuma**: `https://uptime.gate.${DOMAIN}` 2. **Add New Monitor**: Click "Add New Monitor" 3. **Configure Monitor**: - **Monitor Type**: HTTP(s) - **Friendly Name**: Your Service Name - **URL**: `https://your-service.${DOMAIN}` - **Heartbeat Interval**: 60 seconds (recommended) - **Max Retries**: 3 4. **Save**: Click "Save" **Note**: The standard Uptime Kuma image does not support Docker label auto-discovery. All monitors must be configured manually through the web interface. ## 🔧 Troubleshooting ### Common Issues #### Service Not Accessible (404/502/503) ```bash # Check service status docker compose ps # Check service logs docker compose logs your-service # Check Traefik logs docker compose logs traefik # Verify network connectivity docker exec traefik ping your-service ``` #### SSL Certificate Issues ```bash # Check Let's Encrypt logs docker compose logs traefik | grep -i acme # Verify DNS records nslookup your-domain.com # Check certificate status curl -I https://your-domain.com ``` #### Network Issues ```bash # List networks docker network ls # Create external network if missing docker network create traefik_proxy # Inspect network docker network inspect traefik_proxy ``` ### Useful Commands ```bash # View all services docker compose ps # Follow logs for specific service docker compose logs -f service-name # Restart specific service docker compose restart service-name # Update and restart all services docker compose pull && docker compose up -d # Check Traefik configuration docker exec traefik traefik version ``` ## 📚 Documentation ### Key Files - `docker-compose.yml`: Main service configuration - `.env.example`: Environment variables - `README.md`: This documentation ### External Resources - [Traefik Documentation](https://doc.traefik.io/traefik/) - [Docker Compose Documentation](https://docs.docker.com/compose/) - [Let's Encrypt Documentation](https://letsencrypt.org/docs/) ## 🤝 Contributing 1. Fork the repository 2. Create a feature branch 3. Make your changes 4. Test thoroughly 5. Submit a pull request