migrate
This commit is contained in:
@@ -0,0 +1,65 @@
|
||||
# =============================================================================
|
||||
# Nginx Proxy Manager Platform — Environment Variables
|
||||
# =============================================================================
|
||||
|
||||
MYSQL_ROOT_PASSWORD=rhDGjilZm6XEMJ
|
||||
MYSQL_DATABASE=npm
|
||||
MYSQL_USER=npm
|
||||
MYSQL_PASSWORD=rhDGjilZm6XEMJ
|
||||
|
||||
# TZ for container timezone
|
||||
TZ=America/New_York
|
||||
|
||||
|
||||
# =============================================================================
|
||||
# WAF Management Platform — Environment Variables
|
||||
# Copy this file to .env and fill in all CHANGE_ME values before first run.
|
||||
# Never commit .env to source control.
|
||||
# =============================================================================
|
||||
|
||||
# --- Image version -------------------------------------------------------
|
||||
# Pin a release tag (e.g. v1.0.0) for reproducible deploys. "latest" tracks
|
||||
# the newest published image.
|
||||
WAF_IMAGE_TAG=latest
|
||||
|
||||
# --- GeoIP (MaxMind GeoLite2) --------------------------------------------
|
||||
# Host path to your own GeoLite2-City.mmdb. MaxMind licensing prevents us
|
||||
# from bundling it. See the README "GeoIP setup" section to obtain one free.
|
||||
GEOIP_DB_PATH=./GeoLite2-City.mmdb
|
||||
|
||||
# --- PostgreSQL ----------------------------------------------------------
|
||||
POSTGRES_DB=wafdb
|
||||
POSTGRES_USER=wafuser
|
||||
POSTGRES_PASSWORD=ioGjIVo4zu4b6Bj
|
||||
POSTGRES_HOST=postgres
|
||||
POSTGRES_PORT=5432
|
||||
|
||||
# --- Redis ---------------------------------------------------------------
|
||||
REDIS_URL=redis://redis:6379/0
|
||||
|
||||
# --- API Security --------------------------------------------------------
|
||||
# Generate with: python3 -c "import secrets; print(secrets.token_hex(32))"
|
||||
SECRET_KEY=ef210e8acc8c0ecdafe3b2096c8923fed5b766d2e86885fa387f3ad600e2de0e
|
||||
|
||||
# Comma-separated list of allowed CORS origins (no wildcard).
|
||||
# For the default local deploy, use the UI's HTTPS URL:
|
||||
ALLOWED_ORIGINS=https://localhost:8443
|
||||
|
||||
# TOTP encryption key — generate with:
|
||||
# python3 -c "from cryptography.fernet import Fernet; print(Fernet.generate_key().decode())"
|
||||
TOTP_ENCRYPTION_KEY=G1WN75rpulrIprSgn56Ctb8qiXdZM7K2m2FjksRsmu8=
|
||||
|
||||
# --- Caddy Admin API (container-internal) --------------------------------
|
||||
CADDY_ADMIN_URL=http://caddy-waf:2019
|
||||
|
||||
# --- SMTP (for alert notifications) --------------------------------------
|
||||
SMTP_HOST=mail.mmcfetridge.net
|
||||
SMTP_PORT=465
|
||||
SMTP_USER=miker@mmcfetridge.net
|
||||
SMTP_PASSWORD="!Sucyetat123"
|
||||
SMTP_FROM=miker@mmcfetridge.net
|
||||
|
||||
# --- Bootstrap superadmin (seeded on first run only) ---------------------
|
||||
# Change the password immediately after first login.
|
||||
BOOTSTRAP_ADMIN_EMAIL=miker@mmcfetridge.net
|
||||
BOOTSTRAP_ADMIN_PASSWORD=PVGpjJOId5djMO5
|
||||
@@ -0,0 +1,252 @@
|
||||
---
|
||||
services:
|
||||
db:
|
||||
image: 'jc21/mariadb-aria:latest'
|
||||
container_name: npm-db
|
||||
restart: unless-stopped
|
||||
env_file: .env
|
||||
environment:
|
||||
- MYSQL_ROOT_PASSWORD=${MYSQL_ROOT_PASSWORD}
|
||||
- MYSQL_DATABASE=${MYSQL_DATABASE}
|
||||
- MYSQL_USER=${MYSQL_USER}
|
||||
- MYSQL_PASSWORD=${MYSQL_PASSWORD}
|
||||
- MARIADB_AUTO_UPGRADE=1
|
||||
volumes:
|
||||
- ./npm/data/mysql:/var/lib/mysql
|
||||
networks:
|
||||
# - proxydb
|
||||
- waf-internal
|
||||
healthcheck:
|
||||
test: ["CMD", "mysqladmin", "ping", "-h", "localhost", "-u${MYSQL_USER}", "-p${MYSQL_PASSWORD}"]
|
||||
interval: 20s
|
||||
timeout: 5s
|
||||
retries: 5
|
||||
start_period: 30s
|
||||
|
||||
app:
|
||||
image: 'jc21/nginx-proxy-manager:latest'
|
||||
container_name: nginx-proxy-manager
|
||||
restart: unless-stopped
|
||||
env_file: .env
|
||||
environment:
|
||||
- TZ=${TZ}
|
||||
- DB_MYSQL_HOST=db
|
||||
- DB_MYSQL_PORT=3306
|
||||
- DB_MYSQL_USER=${MYSQL_USER}
|
||||
- DB_MYSQL_PASSWORD=${MYSQL_PASSWORD}
|
||||
- DB_MYSQL_NAME=${MYSQL_DATABASE}
|
||||
ports:
|
||||
- '81:81' # Kept so you can access the NPM dashboard on host-ip:81
|
||||
# '80:80' and '443:443' REMOVED here. They are reachable internally via the network.
|
||||
volumes:
|
||||
- ./npm/data/npm:/data
|
||||
- ./npm/data/letsencrypt:/etc/letsencrypt
|
||||
depends_on:
|
||||
- db
|
||||
networks:
|
||||
# - proxy
|
||||
# - proxydb
|
||||
- waf-internal
|
||||
healthcheck:
|
||||
test: ["CMD", "curl", "-f", "http://localhost:81/api/status"]
|
||||
interval: 20s
|
||||
timeout: 5s
|
||||
retries: 5
|
||||
start_period: 40s
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Caddy + Coraza: WAF engine and reverse proxy
|
||||
# ---------------------------------------------------------------------------
|
||||
caddy-waf:
|
||||
image: ghcr.io/socfortress/waf-caddy:${WAF_IMAGE_TAG:-latest}
|
||||
container_name: caddy-waf
|
||||
ports:
|
||||
- "80:80"
|
||||
- "443:443"
|
||||
# Lets the WAF proxy to apps running on the Docker host (e.g. an nginx
|
||||
# upstream) via http://host.docker.internal:<port>. See demo/README.md.
|
||||
extra_hosts:
|
||||
- "host.docker.internal:host-gateway"
|
||||
volumes:
|
||||
- coraza-rules:/etc/coraza/rules
|
||||
- caddy-config:/etc/caddy
|
||||
- coraza-custom:/etc/coraza/custom
|
||||
- crs-data:/etc/coraza/crs-rules # live CRS dir (seeded by admin-api)
|
||||
- coraza-logs:/var/log/coraza
|
||||
networks:
|
||||
- waf-internal
|
||||
depends_on:
|
||||
http-echo:
|
||||
condition: service_started
|
||||
healthcheck:
|
||||
test: ["CMD", "wget", "-q", "-O-", "http://localhost:2019/config/"]
|
||||
interval: 30s
|
||||
timeout: 10s
|
||||
retries: 3
|
||||
start_period: 20s
|
||||
deploy:
|
||||
resources:
|
||||
limits:
|
||||
cpus: "1.0"
|
||||
memory: 512M
|
||||
restart: unless-stopped
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Dummy upstream — replace with your real protected app(s)
|
||||
# ---------------------------------------------------------------------------
|
||||
http-echo:
|
||||
image: hashicorp/http-echo:0.2.3
|
||||
container_name: http-echo
|
||||
command: ["-text=upstream-ok"]
|
||||
user: "65534:65534"
|
||||
networks:
|
||||
- waf-internal
|
||||
healthcheck:
|
||||
test: ["NONE"]
|
||||
deploy:
|
||||
resources:
|
||||
limits:
|
||||
cpus: "0.25"
|
||||
memory: 64M
|
||||
restart: unless-stopped
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# FastAPI Admin API
|
||||
# ---------------------------------------------------------------------------
|
||||
admin-api:
|
||||
image: ghcr.io/socfortress/waf-admin-api:${WAF_IMAGE_TAG:-latest}
|
||||
container_name: admin-api
|
||||
env_file: .env
|
||||
volumes:
|
||||
- tls-certs:/certs # shared TLS cert volume (see admin-ui)
|
||||
# GeoLite2 DB is user-supplied — MaxMind licensing forbids redistribution.
|
||||
# Point GEOIP_DB_PATH at your downloaded GeoLite2-City.mmdb (see README).
|
||||
- ./GeoLite2-City/GeoLite2-City.mmdb:/etc/geoip-bundle/GeoLite2-City.mmdb:ro
|
||||
- geoip-data:/etc/geoip
|
||||
- coraza-rules:/etc/coraza/rules
|
||||
- caddy-config:/etc/caddy
|
||||
- coraza-custom:/etc/coraza/custom
|
||||
- crs-data:/etc/coraza/crs-rules # live CRS dir (seeded from image bundle)
|
||||
- coraza-logs:/var/log/coraza
|
||||
networks:
|
||||
- waf-internal
|
||||
depends_on:
|
||||
postgres:
|
||||
condition: service_healthy
|
||||
redis:
|
||||
condition: service_healthy
|
||||
healthcheck:
|
||||
test: ["CMD", "wget", "-q", "-O-", "http://localhost:8000/health"]
|
||||
interval: 30s
|
||||
timeout: 10s
|
||||
retries: 3
|
||||
start_period: 30s
|
||||
deploy:
|
||||
resources:
|
||||
limits:
|
||||
cpus: "1.0"
|
||||
memory: 512M
|
||||
restart: unless-stopped
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# React Admin UI (served by Nginx, HTTPS on 8443)
|
||||
# ---------------------------------------------------------------------------
|
||||
admin-ui:
|
||||
image: ghcr.io/socfortress/waf-admin-ui:${WAF_IMAGE_TAG:-latest}
|
||||
container_name: admin-ui
|
||||
ports:
|
||||
- "8443:8080"
|
||||
volumes:
|
||||
- tls-certs:/etc/nginx/certs # shared with admin-api for cert upload + reload
|
||||
networks:
|
||||
- waf-internal
|
||||
depends_on:
|
||||
admin-api:
|
||||
condition: service_healthy
|
||||
healthcheck:
|
||||
test: ["CMD", "wget", "-q", "--no-check-certificate", "-O-", "https://localhost:8080/"]
|
||||
interval: 30s
|
||||
timeout: 10s
|
||||
retries: 3
|
||||
start_period: 30s
|
||||
deploy:
|
||||
resources:
|
||||
limits:
|
||||
cpus: "0.5"
|
||||
memory: 128M
|
||||
restart: unless-stopped
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# PostgreSQL 16
|
||||
# ---------------------------------------------------------------------------
|
||||
postgres:
|
||||
image: postgres:16.3-alpine
|
||||
container_name: postgres
|
||||
env_file: .env
|
||||
volumes:
|
||||
- postgres-data:/var/lib/postgresql/data
|
||||
networks:
|
||||
- waf-internal
|
||||
healthcheck:
|
||||
test: ["CMD-SHELL", "pg_isready -U $$POSTGRES_USER -d $$POSTGRES_DB"]
|
||||
interval: 10s
|
||||
timeout: 5s
|
||||
retries: 5
|
||||
start_period: 10s
|
||||
deploy:
|
||||
resources:
|
||||
limits:
|
||||
cpus: "1.0"
|
||||
memory: 512M
|
||||
restart: unless-stopped
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Redis 7
|
||||
# ---------------------------------------------------------------------------
|
||||
redis:
|
||||
image: redis:7.2.5-alpine
|
||||
container_name: redis
|
||||
user: redis
|
||||
command: ["redis-server", "--appendonly", "yes"]
|
||||
volumes:
|
||||
- redis-data:/data
|
||||
networks:
|
||||
- waf-internal
|
||||
healthcheck:
|
||||
test: ["CMD", "redis-cli", "ping"]
|
||||
interval: 10s
|
||||
timeout: 5s
|
||||
retries: 5
|
||||
start_period: 5s
|
||||
deploy:
|
||||
resources:
|
||||
limits:
|
||||
cpus: "0.5"
|
||||
memory: 256M
|
||||
restart: unless-stopped
|
||||
|
||||
# =============================================================================
|
||||
# Networks
|
||||
# =============================================================================
|
||||
networks:
|
||||
proxy:
|
||||
external: true
|
||||
proxydb:
|
||||
external: true
|
||||
waf-internal:
|
||||
driver: bridge
|
||||
|
||||
# =============================================================================
|
||||
# Named volumes
|
||||
# =============================================================================
|
||||
volumes:
|
||||
coraza-rules:
|
||||
coraza-custom:
|
||||
coraza-logs:
|
||||
caddy-config:
|
||||
crs-data:
|
||||
geoip-data:
|
||||
postgres-data:
|
||||
redis-data:
|
||||
tls-certs:
|
||||
@@ -0,0 +1,3 @@
|
||||
Account ID: 1370812
|
||||
License key: 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
|
||||
Download link: https://download.maxmind.com/app/geoip_download_by_token?date=20260630&edition_id=GeoLite2-City&suffix=tar.gz&token=v2.local.tR9DihzEGIIYMbcbukGNpnBXVsi6EAxtwhQu147OaPcWj_fvkcboMf5hMqL3Wqn0rD8KpW6ujxku8yNaaL3Ylr9LsshJdIHWns1V14pzm82AKrQ9oldDCS-yR7a4kRow8Ofmhr4KBxo1DxoHfTiI8JJB_5qRDwI5ugbmiJr65lzkZKxfpQGCr9kMcM4ueZJzWlJqyQQ
|
||||
@@ -0,0 +1,7 @@
|
||||
MYSQL_ROOT_PASSWORD=rhDGjilZm6XEMJ
|
||||
MYSQL_DATABASE=npm
|
||||
MYSQL_USER=npm
|
||||
MYSQL_PASSWORD=rhDGjilZm6XEMJ
|
||||
|
||||
# TZ for container timezone
|
||||
TZ=America/New_York
|
||||
@@ -0,0 +1,101 @@
|
||||
# Docker Compose File Guide
|
||||
|
||||
## Overview
|
||||
The Docker Compose file is a YAML file defining services, networks, and volumes. This file is used to spin up multiple containers at once using docker-compose CLI tool. It's designed to be a part of your development process rather than being deployed on its own.
|
||||
|
||||
In this guide, we will explore the `docker-compose.yml` file in detail and provide steps for its installation and usage.
|
||||
|
||||
## Understanding Docker Compose File
|
||||
|
||||
Let's take a look at an example of a docker compose file:
|
||||
```yaml
|
||||
version: '3'
|
||||
services:
|
||||
db:
|
||||
image: 'jc21/mariadb-aria:latest'
|
||||
container_name: npm-db
|
||||
restart: unless-stopped
|
||||
env_file: .env
|
||||
environment:
|
||||
- MYSQL_ROOT_PASSWORD=${MYSQL_ROOT_PASSWORD}
|
||||
- MYSQL_DATABASE=${MYSQL_DATABASE}
|
||||
- MYSQL_USER=${MYSQL_USER}
|
||||
- MYSQL_PASSWORD=${MYSQL_PASSWORD}
|
||||
- MARIADB_AUTO_UPGRADE=1
|
||||
volumes:
|
||||
- ./data/mysql:/var/lib/mysql
|
||||
networks:
|
||||
- proxy
|
||||
- proxydb
|
||||
healthcheck:
|
||||
test: ["CMD", "mysqladmin", "ping", "-h", "localhost", "-u${MYSQL_USER}", "-p${MYSQL_PASSWORD}"]
|
||||
interval: 20s
|
||||
timeout: 5s
|
||||
retries: 5
|
||||
start_period: 30s
|
||||
|
||||
app:
|
||||
image: 'jc21/nginx-proxy-manager:latest'
|
||||
container_name: nginx-proxy-manager
|
||||
restart: unless-stopped
|
||||
env_file: .env
|
||||
environment:
|
||||
- TZ=${TZ}
|
||||
- DB_MYSQL_HOST=db
|
||||
- DB_MYSQL_PORT=3306
|
||||
- DB_MYSQL_USER=${MYSQL_USER}
|
||||
- DB_MYSQL_PASSWORD=${MYSQL_PASSWORD}
|
||||
- DB_MYSQL_NAME=${MYSQL_DATABASE}
|
||||
ports:
|
||||
- '80:80'
|
||||
- '81:81'
|
||||
- '443:443'
|
||||
volumes:
|
||||
- ./data/npm:/data
|
||||
- ./data/letsencrypt:/etc/letsencrypt
|
||||
depends_on:
|
||||
- db
|
||||
networks:
|
||||
- proxy
|
||||
- proxydb
|
||||
healthcheck:
|
||||
test: ["CMD", "curl", "-f", "http://localhost:81/api/status"]
|
||||
interval: 20s
|
||||
timeout: 5s
|
||||
retries: 5
|
||||
start_period: 40s
|
||||
|
||||
networks:
|
||||
proxy:
|
||||
external: true
|
||||
proxydb:
|
||||
external: true
|
||||
```
|
||||
This Docker Compose file defines two services, `db` and `app`. Each service is defined with its own configuration such as the image to use, ports to expose, volumes to mount, etc. It also has a network section where it lists the networks that these services should connect to.
|
||||
|
||||
.env
|
||||
```yaml
|
||||
MYSQL_ROOT_PASSWORD=rhDGjilZm6XEMJ
|
||||
MYSQL_DATABASE=npm
|
||||
MYSQL_USER=npm
|
||||
MYSQL_PASSWORD=rhDGjilZm6XEMJ
|
||||
|
||||
# TZ for container timezone
|
||||
TZ=America/New_York
|
||||
```
|
||||
## Installation Guide
|
||||
1. **Install Docker**: Follow instructions on the official [Docker website](https://docs.docker.com/get-docker/) for your specific operating system.
|
||||
|
||||
2. **Install Docker Compose**: On Linux, run `sudo curl -L "https://github.com/docker/compose/releases/download/1.29.2/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose` followed by `sudo chmod +x /usr/local/bin/docker-compose`. On Windows or MacOS, follow the instructions on [Docker Compose's Github page](https://github.com/docker/compose).
|
||||
|
||||
3. **Pull Docker Images**: Before running docker-compose up, make sure to pull all necessary images with `docker-compose pull` command.
|
||||
|
||||
## Running the Services
|
||||
4. **Running the services**: In your terminal, navigate to the directory containing your docker-compose file and run `docker-compose up -d`. This will start all the services defined in the compose file.
|
||||
|
||||
5. **Checking the running status of services**: You can check the status of running services with `docker-compose ps` command.
|
||||
|
||||
Remember to replace placeholders like `${MYSQL_ROOT_PASSWORD}`, `${MYSQL_DATABASE}`, and `${MYSQL_USER}`, etc., in your environment variables files (.env) with actual values before starting the services. Also, ensure all paths mentioned in volumes section exist on your system or adjust them accordingly.
|
||||
|
||||
## Conclusion
|
||||
With this guide you should now have a solid understanding of Docker Compose file and how to use it for running multi-container applications. It's worth noting that Docker Compose is just one tool among many, each having its own strengths and weaknesses depending on the specific use case.
|
||||
@@ -0,0 +1,61 @@
|
||||
---
|
||||
services:
|
||||
db:
|
||||
image: 'jc21/mariadb-aria:latest'
|
||||
container_name: npm-db
|
||||
restart: unless-stopped
|
||||
env_file: .env
|
||||
environment:
|
||||
- MYSQL_ROOT_PASSWORD=${MYSQL_ROOT_PASSWORD}
|
||||
- MYSQL_DATABASE=${MYSQL_DATABASE}
|
||||
- MYSQL_USER=${MYSQL_USER}
|
||||
- MYSQL_PASSWORD=${MYSQL_PASSWORD}
|
||||
- MARIADB_AUTO_UPGRADE=1
|
||||
volumes:
|
||||
- ./data/mysql:/var/lib/mysql
|
||||
networks:
|
||||
- proxy
|
||||
- proxydb
|
||||
healthcheck:
|
||||
test: ["CMD", "mysqladmin", "ping", "-h", "localhost", "-u${MYSQL_USER}", "-p${MYSQL_PASSWORD}"]
|
||||
interval: 20s
|
||||
timeout: 5s
|
||||
retries: 5
|
||||
start_period: 30s
|
||||
|
||||
app:
|
||||
image: 'jc21/nginx-proxy-manager:latest'
|
||||
container_name: nginx-proxy-manager
|
||||
restart: unless-stopped
|
||||
env_file: .env
|
||||
environment:
|
||||
- TZ=${TZ}
|
||||
- DB_MYSQL_HOST=db
|
||||
- DB_MYSQL_PORT=3306
|
||||
- DB_MYSQL_USER=${MYSQL_USER}
|
||||
- DB_MYSQL_PASSWORD=${MYSQL_PASSWORD}
|
||||
- DB_MYSQL_NAME=${MYSQL_DATABASE}
|
||||
ports:
|
||||
- '80:80'
|
||||
- '81:81'
|
||||
- '443:443'
|
||||
volumes:
|
||||
- ./data/npm:/data
|
||||
- ./data/letsencrypt:/etc/letsencrypt
|
||||
depends_on:
|
||||
- db
|
||||
networks:
|
||||
- proxy
|
||||
- proxydb
|
||||
healthcheck:
|
||||
test: ["CMD", "curl", "-f", "http://localhost:81/api/status"]
|
||||
interval: 20s
|
||||
timeout: 5s
|
||||
retries: 5
|
||||
start_period: 40s
|
||||
|
||||
networks:
|
||||
proxy:
|
||||
external: true
|
||||
proxydb:
|
||||
external: true
|
||||
@@ -0,0 +1,19 @@
|
||||
services:
|
||||
zoraxy:
|
||||
image: zoraxydocker/zoraxy:latest
|
||||
container_name: zoraxy
|
||||
restart: unless-stopped
|
||||
ports:
|
||||
- "80:80"
|
||||
- "443:443"
|
||||
- "8000:8000"
|
||||
environment:
|
||||
FASTGEOIP: "true"
|
||||
TZ: "America/New_York"
|
||||
volumes:
|
||||
- ./config:/opt/zoraxy/config
|
||||
- ./plugin:/opt/zoraxy/plugin
|
||||
- /var/run/docker.sock:/var/run/docker.sock
|
||||
- /etc/localtime:/etc/localtime:ro
|
||||
extra_hosts:
|
||||
- "host.docker.internal:host-gateway"
|
||||
@@ -0,0 +1,31 @@
|
||||
# To see all available options, please visit the docs:
|
||||
# https://docs.digpangolin.com/self-host/advanced/config-file
|
||||
|
||||
gerbil:
|
||||
start_port: 51820
|
||||
base_endpoint: "pangolin.mmcfetridge.net"
|
||||
|
||||
app:
|
||||
dashboard_url: "https://pangolin.mmcfetridge.net"
|
||||
log_level: "info"
|
||||
telemetry:
|
||||
anonymous_usage: true
|
||||
|
||||
domains:
|
||||
domain1:
|
||||
base_domain: "mmcfetridge.net"
|
||||
cert_resolver: "letsencrypt"
|
||||
|
||||
server:
|
||||
secret: "D0fDlOKHBRlaA7c88a9O89yd4anznpZd"
|
||||
cors:
|
||||
origins: [ "https://pangolin.mmcfetridge.net" ]
|
||||
methods: [ "GET", "POST", "PUT", "DELETE", "PATCH" ]
|
||||
allowed_headers: [ "X-CSRF-Token", "Content-Type" ]
|
||||
credentials: false
|
||||
|
||||
flags:
|
||||
require_email_verification: false
|
||||
disable_signup_without_invite: true
|
||||
disable_user_create_org: false
|
||||
allow_raw_resources: true
|
||||
@@ -0,0 +1,53 @@
|
||||
http:
|
||||
middlewares:
|
||||
redirect-to-https:
|
||||
redirectScheme:
|
||||
scheme: https
|
||||
|
||||
routers:
|
||||
# HTTP to HTTPS redirect router
|
||||
main-app-router-redirect:
|
||||
rule: "Host(`pangolin.mmcfetridge.net`)"
|
||||
service: next-service
|
||||
entryPoints:
|
||||
- web
|
||||
middlewares:
|
||||
- redirect-to-https
|
||||
|
||||
# Next.js router (handles everything except API and WebSocket paths)
|
||||
next-router:
|
||||
rule: "Host(`pangolin.mmcfetridge.net`) && !PathPrefix(`/api/v1`)"
|
||||
service: next-service
|
||||
entryPoints:
|
||||
- websecure
|
||||
tls:
|
||||
certResolver: letsencrypt
|
||||
|
||||
# API router (handles /api/v1 paths)
|
||||
api-router:
|
||||
rule: "Host(`pangolin.mmcfetridge.net`) && PathPrefix(`/api/v1`)"
|
||||
service: api-service
|
||||
entryPoints:
|
||||
- websecure
|
||||
tls:
|
||||
certResolver: letsencrypt
|
||||
|
||||
# WebSocket router
|
||||
ws-router:
|
||||
rule: "Host(`pangolin.mmcfetridge.net`)"
|
||||
service: api-service
|
||||
entryPoints:
|
||||
- websecure
|
||||
tls:
|
||||
certResolver: letsencrypt
|
||||
|
||||
services:
|
||||
next-service:
|
||||
loadBalancer:
|
||||
servers:
|
||||
- url: "http://pangolin:3002" # Next.js server
|
||||
|
||||
api-service:
|
||||
loadBalancer:
|
||||
servers:
|
||||
- url: "http://pangolin:3000" # API/WebSocket server
|
||||
@@ -0,0 +1,53 @@
|
||||
api:
|
||||
insecure: true
|
||||
dashboard: true
|
||||
|
||||
providers:
|
||||
|
||||
http:
|
||||
endpoint: "http://pangolin:3001/api/v1/traefik-config"
|
||||
pollInterval: "5s"
|
||||
file:
|
||||
filename: "/etc/traefik/dynamic_config.yml"
|
||||
|
||||
experimental:
|
||||
plugins:
|
||||
badger:
|
||||
moduleName: "github.com/fosrl/badger"
|
||||
version: "v1.2.0"
|
||||
|
||||
log:
|
||||
level: "INFO"
|
||||
format: "common"
|
||||
maxSize: 100
|
||||
maxBackups: 3
|
||||
maxAge: 3
|
||||
compress: true
|
||||
|
||||
certificatesResolvers:
|
||||
letsencrypt:
|
||||
acme:
|
||||
httpChallenge:
|
||||
entryPoint: web
|
||||
email: "mmcfetridg@aol.com"
|
||||
storage: "/letsencrypt/acme.json"
|
||||
caServer: "https://acme-v02.api.letsencrypt.org/directory"
|
||||
|
||||
entryPoints:
|
||||
web:
|
||||
address: ":80"
|
||||
websecure:
|
||||
address: ":443"
|
||||
|
||||
transport:
|
||||
respondingTimeouts:
|
||||
readTimeout: "30m"
|
||||
http:
|
||||
tls:
|
||||
certResolver: "letsencrypt"
|
||||
|
||||
serversTransport:
|
||||
insecureSkipVerify: true
|
||||
|
||||
ping:
|
||||
entryPoint: "web"
|
||||
@@ -0,0 +1,65 @@
|
||||
name: pangolin
|
||||
services:
|
||||
pangolin:
|
||||
image: docker.io/fosrl/pangolin:latest
|
||||
container_name: pangolin
|
||||
restart: unless-stopped
|
||||
volumes:
|
||||
- ./config:/app/config
|
||||
- pangolin-data:/var/certificates
|
||||
- pangolin-data:/var/dynamic
|
||||
healthcheck:
|
||||
test: ["CMD", "curl", "-f", "http://localhost:3001/api/v1/"]
|
||||
interval: "10s"
|
||||
timeout: "10s"
|
||||
retries: 15
|
||||
|
||||
gerbil:
|
||||
image: docker.io/fosrl/gerbil:latest
|
||||
container_name: gerbil
|
||||
restart: unless-stopped
|
||||
depends_on:
|
||||
pangolin:
|
||||
condition: service_healthy
|
||||
command:
|
||||
- --reachableAt=http://gerbil:3003
|
||||
- --generateAndSaveKeyTo=/var/config/key
|
||||
- --remoteConfig=http://pangolin:3001/api/v1/
|
||||
volumes:
|
||||
- ./config/:/var/config
|
||||
cap_add:
|
||||
- NET_ADMIN
|
||||
- SYS_MODULE
|
||||
ports:
|
||||
- 51820:51820/udp
|
||||
- 21820:21820/udp
|
||||
- 443:443
|
||||
- 80:80
|
||||
|
||||
traefik:
|
||||
image: docker.io/traefik:latest
|
||||
container_name: traefik
|
||||
restart: unless-stopped
|
||||
|
||||
network_mode: service:gerbil # Ports appear on the gerbil service
|
||||
|
||||
depends_on:
|
||||
pangolin:
|
||||
condition: service_healthy
|
||||
command:
|
||||
- --configFile=/etc/traefik/traefik_config.yml
|
||||
volumes:
|
||||
- ./config/traefik:/etc/traefik:ro # Volume to store the Traefik configuration
|
||||
- ./config/letsencrypt:/letsencrypt # Volume to store the Let's Encrypt certificates
|
||||
- ./config/traefik/logs:/var/log/traefik # Volume to store Traefik logs
|
||||
# Shared volume for certificates and dynamic config in file mode
|
||||
- pangolin-data:/var/certificates:ro
|
||||
- pangolin-data:/var/dynamic:ro
|
||||
|
||||
networks:
|
||||
default:
|
||||
driver: bridge
|
||||
name: pangolin
|
||||
|
||||
volumes:
|
||||
pangolin-data:
|
||||
@@ -0,0 +1 @@
|
||||
mkdir -p config/traefik config/db config/letsencrypt config/logs
|
||||
Reference in New Issue
Block a user