feat: phase 3 redesign, game images, auth system, vm guides, service isolation
Some checks failed
Deploy Multi-VM / Deploy VM Web (push) Has been cancelled
Deploy Multi-VM / Deploy VM Auth (push) Has been cancelled
Deploy Multi-VM / Deploy Game Servers (docker-compose.fusionfall.yml, VM_FUSIONFALL_HOST, VM_FUSIONFALL_SSH_KEY, VM_FUSIONFALL_USER, fusionfall) (push) Has been cancelled
Deploy Multi-VM / Deploy Game Servers (docker-compose.maple2.yml, VM_MAPLE2_HOST, VM_MAPLE2_SSH_KEY, VM_MAPLE2_USER, maple2) (push) Has been cancelled
Deploy Multi-VM / Deploy Game Servers (docker-compose.minecraft.yml, VM_MINECRAFT_HOST, VM_MINECRAFT_SSH_KEY, VM_MINECRAFT_USER, minecraft) (push) Has been cancelled
Deploy Multi-VM / Deploy Game Servers (docker-compose.retro.yml, VM_RETRO_HOST, VM_RETRO_SSH_KEY, VM_RETRO_USER, retro) (push) Has been cancelled
Some checks failed
Deploy Multi-VM / Deploy VM Web (push) Has been cancelled
Deploy Multi-VM / Deploy VM Auth (push) Has been cancelled
Deploy Multi-VM / Deploy Game Servers (docker-compose.fusionfall.yml, VM_FUSIONFALL_HOST, VM_FUSIONFALL_SSH_KEY, VM_FUSIONFALL_USER, fusionfall) (push) Has been cancelled
Deploy Multi-VM / Deploy Game Servers (docker-compose.maple2.yml, VM_MAPLE2_HOST, VM_MAPLE2_SSH_KEY, VM_MAPLE2_USER, maple2) (push) Has been cancelled
Deploy Multi-VM / Deploy Game Servers (docker-compose.minecraft.yml, VM_MINECRAFT_HOST, VM_MINECRAFT_SSH_KEY, VM_MINECRAFT_USER, minecraft) (push) Has been cancelled
Deploy Multi-VM / Deploy Game Servers (docker-compose.retro.yml, VM_RETRO_HOST, VM_RETRO_SSH_KEY, VM_RETRO_USER, retro) (push) Has been cancelled
- Redesign all internal pages to warm/gold aesthetic (catalog, game detail, documentary, about, donate, community, guides, contact, server-status, login, profile, admin, not-found) - Add real cover images for all 4 games via Strapi CMS with getImageUrl helper - Integrate NextAuth v5 with Authentik OIDC authentication - Add new public pages: community, guides, contact, server-status - Add new protected pages: login, profile, admin dashboard - Remove legacy AFC/MercadoPago system entirely - Add Docker Compose split files for service isolation (main, auth, fusionfall, nier) - Add OpenFusion VM deployment configs (config.vm.ini, systemd service, README-VM) - Add NieR Reincarnation server guide and desktop client guide - Add architecture docs for multi-VM deployment - Add healthcheck, SSE, contact, newsletter, admin API routes - Add reusable UI components, skeleton loaders, activity feed, bookmark system - Update deployment and game server documentation
This commit is contained in:
@@ -1,9 +1,20 @@
|
||||
# Database
|
||||
# =============================================================================
|
||||
# Project Afterlife - Multi-VM Architecture Environment Variables
|
||||
# =============================================================================
|
||||
# Copy this file to docker/.env and fill in all values before deployment.
|
||||
# Each VM has its own compose file and uses only the variables it needs.
|
||||
|
||||
# =============================================================================
|
||||
# VM 1: Web Platform (vm-web - 10.0.0.10)
|
||||
# Services: Next.js, Strapi CMS, PostgreSQL, MinIO, Nginx, Certbot
|
||||
# =============================================================================
|
||||
|
||||
# Database (PostgreSQL 16)
|
||||
DATABASE_NAME=afterlife
|
||||
DATABASE_USERNAME=afterlife
|
||||
DATABASE_PASSWORD=change_me_in_production
|
||||
|
||||
# Strapi
|
||||
# Strapi Secrets (generate with: openssl rand -base64 32)
|
||||
APP_KEYS=key1,key2,key3,key4
|
||||
API_TOKEN_SALT=change_me
|
||||
ADMIN_JWT_SECRET=change_me
|
||||
@@ -11,29 +22,133 @@ TRANSFER_TOKEN_SALT=change_me
|
||||
JWT_SECRET=change_me
|
||||
STRAPI_API_TOKEN=your_api_token_after_first_boot
|
||||
|
||||
# MinIO
|
||||
# MinIO (S3-compatible storage)
|
||||
MINIO_ROOT_USER=afterlife
|
||||
MINIO_ROOT_PASSWORD=change_me_in_production
|
||||
|
||||
# Public URL (for frontend image/media URLs)
|
||||
PUBLIC_STRAPI_URL=http://yourdomain.com
|
||||
# Public URLs
|
||||
PUBLIC_STRAPI_URL=https://play.consultoria-as.com
|
||||
NEXT_PUBLIC_SITE_URL=https://play.consultoria-as.com
|
||||
|
||||
# Public hostname for game servers (DDNS)
|
||||
PUBLIC_HOST=play.yourdomain.com
|
||||
|
||||
# Cloudflare API Token (create at https://dash.cloudflare.com/profile/api-tokens)
|
||||
# Permissions needed: Zone > DNS > Edit
|
||||
# Cloudflare DDNS (optional, for dynamic IPs)
|
||||
# Create token at: https://dash.cloudflare.com/profile/api-tokens
|
||||
# Permissions: Zone > DNS > Edit
|
||||
PUBLIC_HOST=play.consultoria-as.com
|
||||
CF_API_TOKEN=your_cloudflare_api_token
|
||||
|
||||
# AfterCoin Blockchain (private Ethereum chain for casino tokens)
|
||||
# =============================================================================
|
||||
# VM PRINCIPAL — Autenticacion (todo en vm-main - 10.0.0.10)
|
||||
# Services: Authentik Server, Worker, PostgreSQL, Redis
|
||||
# NOTE: Authentik runs on the same VM as Web + CMS (consolidated)
|
||||
# =============================================================================
|
||||
|
||||
# Authentik (generate strong secrets — min 50 chars)
|
||||
# You can generate with: openssl rand -base64 60
|
||||
AUTHENTIK_SECRET_KEY=generate_a_very_long_random_string_minimum_50_characters_long
|
||||
AUTHENTIK_POSTGRES_PASSWORD=change_me_in_production
|
||||
AUTHENTIK_POSTGRES_USER=authentik
|
||||
AUTHENTIK_POSTGRES_DB=authentik
|
||||
|
||||
# Authentik OIDC Clients (create these in Authentik Admin after first boot)
|
||||
# Internal URL (Docker network). Nginx proxies /auth to authentik-server:9000
|
||||
AUTHENTIK_URL=http://authentik-server:9000
|
||||
|
||||
# Web App (for players)
|
||||
AUTHENTIK_CLIENT_ID_WEB=afterlife-web
|
||||
AUTHENTIK_CLIENT_SECRET_WEB=change_me
|
||||
AUTHENTIK_REDIRECT_URI_WEB=https://play.consultoria-as.com/api/auth/callback/authentik
|
||||
|
||||
# CMS Admin (for content editors)
|
||||
AUTHENTIK_CLIENT_ID_CMS=afterlife-cms
|
||||
AUTHENTIK_CLIENT_SECRET_CMS=change_me
|
||||
AUTHENTIK_REDIRECT_URI_CMS=https://play.consultoria-as.com/admin/auth/callback/authentik
|
||||
|
||||
# =============================================================================
|
||||
# VM 3: OpenFusion (vm-fusionfall - 10.0.0.30)
|
||||
# Services: OpenFusion Server
|
||||
# =============================================================================
|
||||
|
||||
# Public IP where players connect (your domain or public IP)
|
||||
OPENFUSION_SHARD_IP=play.consultoria-as.com
|
||||
OPENFUSION_MOTD="Welcome to Project Afterlife - FusionFall"
|
||||
|
||||
# =============================================================================
|
||||
# VM 6: NieR Reincarnation (vm-nier - 10.0.0.70)
|
||||
# Services: MariesWonderland Server (.NET 10)
|
||||
# =============================================================================
|
||||
|
||||
# ResourcesBaseUrl must be exactly 43 characters after the host
|
||||
# Example: http://play.consultoria-as.com/aaaaaaaaaaaaaaaaaaaaaaaa
|
||||
NIER_RESOURCES_BASE_URL=http://play.consultoria-as.com/aaaaaaaaaaaaaaaaaaaaaaaa
|
||||
NIER_MASTER_DATA_VERSION=20240404193219
|
||||
|
||||
# =============================================================================
|
||||
# VM 7: Dragon Ball Online (vm-dbo - 10.0.0.80)
|
||||
# Services: DBO Global Server (C++) + MariaDB
|
||||
# =============================================================================
|
||||
|
||||
# MariaDB root password for DBO
|
||||
DBO_DB_PASSWORD=dboglobal
|
||||
|
||||
# =============================================================================
|
||||
# VM 4: MapleStory 2 (vm-maple2 - 10.0.0.40)
|
||||
# Services: MySQL, World, Login, Game, Web
|
||||
# =============================================================================
|
||||
|
||||
# MySQL root password
|
||||
MAPLE2_DB_PASSWORD=maplestory
|
||||
|
||||
# Path to MapleStory 2 client data (14GB, NOT in git)
|
||||
MAPLE2_DATA_FOLDER=../servers/maple2/client-data/Data
|
||||
|
||||
# Public IP for game client connections
|
||||
MAPLE2_PUBLIC_IP=play.consultoria-as.com
|
||||
|
||||
# Internal .env for Maple2 servers (see servers/maple2/.env.example)
|
||||
# GAME_IP and LOGIN_IP should be set to MAPLE2_PUBLIC_IP in servers/maple2/.env
|
||||
|
||||
# =============================================================================
|
||||
# VM 5: Minecraft + AfterCoin Blockchain (vm-minecraft - 10.0.0.50)
|
||||
# Services: Minecraft FTB, Geth, AFC Bridge, RPC SSL Proxy
|
||||
# =============================================================================
|
||||
|
||||
# AfterCoin Admin Wallet
|
||||
# Generate with: node -e "const {ethers}=require('ethers');const w=ethers.Wallet.createRandom();console.log(w.address,w.privateKey)"
|
||||
AFC_ADMIN_ADDRESS=0xYOUR_ADMIN_ADDRESS
|
||||
AFC_ADMIN_PRIVATE_KEY=your_private_key_without_0x_prefix
|
||||
AFC_BRIDGE_SECRET=change_me_in_production
|
||||
|
||||
# AFC Store (MercadoPago integration)
|
||||
# MercadoPago (AFC Store payments)
|
||||
MERCADOPAGO_ACCESS_TOKEN=your_mp_access_token
|
||||
MERCADOPAGO_WEBHOOK_SECRET=your_mp_webhook_secret
|
||||
MERCADOPAGO_WEBHOOK_URL=https://yourdomain.com/api/afc/webhook
|
||||
MERCADOPAGO_WEBHOOK_URL=https://play.consultoria-as.com/api/afc/webhook
|
||||
AFC_PRICE_MXN=15
|
||||
NEXT_PUBLIC_SITE_URL=http://localhost:3000
|
||||
|
||||
# =============================================================================
|
||||
# VM 6: Retro Consoles (vm-retro - 10.0.0.60)
|
||||
# Services: SM64 Coop DX, N64 Netplay, Dolphin Traversal
|
||||
# =============================================================================
|
||||
|
||||
# SM64 Coop DX
|
||||
SM64_PORT=7777
|
||||
SM64_PLAYERS=16
|
||||
|
||||
# N64 Netplay (Mario Party)
|
||||
G64NS_NAME="Afterlife N64 - Mario Party"
|
||||
G64NS_PORT=45000
|
||||
G64NS_MAXGAMES=4
|
||||
G64NS_MOTD="Welcome to Project Afterlife N64 Netplay"
|
||||
G64NS_DISABLEBROADCAST=false
|
||||
G64NS_ENABLEAUTH=false
|
||||
|
||||
# =============================================================================
|
||||
# Game Server Public IPs (displayed on website to players)
|
||||
# These can be the same domain if you use port-based routing,
|
||||
# or different subdomains/IPs per VM.
|
||||
# =============================================================================
|
||||
FUSIONFALL_PUBLIC_IP=play.consultoria-as.com
|
||||
MAPLE2_PUBLIC_IP=play.consultoria-as.com
|
||||
MINECRAFT_PUBLIC_IP=play.consultoria-as.com
|
||||
SM64_PUBLIC_IP=play.consultoria-as.com
|
||||
N64_PUBLIC_IP=play.consultoria-as.com
|
||||
DOLPHIN_PUBLIC_IP=play.consultoria-as.com
|
||||
|
||||
100
docker/docker-compose.auth.yml
Normal file
100
docker/docker-compose.auth.yml
Normal file
@@ -0,0 +1,100 @@
|
||||
# VM 2: Autenticacion y Administracion
|
||||
# IP Privada: 10.0.0.20
|
||||
# Puertos Publicos: 9000 (Authentik via Nginx proxy from vm-web)
|
||||
# Tecnologia: Authentik (OIDC/OAuth2 provider)
|
||||
# Servicios: Authentik Server, Authentik Worker, PostgreSQL, Redis
|
||||
|
||||
services:
|
||||
authentik-postgres:
|
||||
image: docker.io/library/postgres:16-alpine
|
||||
restart: unless-stopped
|
||||
container_name: auth-postgres
|
||||
healthcheck:
|
||||
test: ["CMD-SHELL", "pg_isready -d $${POSTGRES_DB} -U $${POSTGRES_USER}"]
|
||||
start_period: 20s
|
||||
interval: 30s
|
||||
retries: 5
|
||||
timeout: 5s
|
||||
volumes:
|
||||
- authentik_postgres_data:/var/lib/postgresql/data
|
||||
environment:
|
||||
POSTGRES_PASSWORD: ${AUTHENTIK_POSTGRES_PASSWORD:-authentik}
|
||||
POSTGRES_USER: ${AUTHENTIK_POSTGRES_USER:-authentik}
|
||||
POSTGRES_DB: ${AUTHENTIK_POSTGRES_DB:-authentik}
|
||||
networks:
|
||||
- auth-internal
|
||||
|
||||
authentik-redis:
|
||||
image: docker.io/library/redis:alpine
|
||||
restart: unless-stopped
|
||||
container_name: auth-redis
|
||||
healthcheck:
|
||||
test: ["CMD-SHELL", "redis-cli ping | grep PONG"]
|
||||
start_period: 20s
|
||||
interval: 30s
|
||||
retries: 5
|
||||
timeout: 3s
|
||||
volumes:
|
||||
- authentik_redis_data:/data
|
||||
networks:
|
||||
- auth-internal
|
||||
|
||||
authentik-server:
|
||||
image: ghcr.io/goauthentik/server:latest
|
||||
restart: unless-stopped
|
||||
container_name: auth-server
|
||||
command: server
|
||||
environment:
|
||||
AUTHENTIK_SECRET_KEY: ${AUTHENTIK_SECRET_KEY}
|
||||
AUTHENTIK_REDIS__HOST: authentik-redis
|
||||
AUTHENTIK_POSTGRESQL__HOST: authentik-postgres
|
||||
AUTHENTIK_POSTGRESQL__NAME: ${AUTHENTIK_POSTGRES_DB:-authentik}
|
||||
AUTHENTIK_POSTGRESQL__USER: ${AUTHENTIK_POSTGRES_USER:-authentik}
|
||||
AUTHENTIK_POSTGRESQL__PASSWORD: ${AUTHENTIK_POSTGRES_PASSWORD:-authentik}
|
||||
# Authentik listen on all interfaces so it's reachable from other VMs
|
||||
AUTHENTIK_LISTEN__HTTP: 0.0.0.0:9000
|
||||
AUTHENTIK_LISTEN__HTTPS: 0.0.0.0:9443
|
||||
ports:
|
||||
- "10.0.0.20:9000:9000"
|
||||
- "10.0.0.20:9443:9443"
|
||||
volumes:
|
||||
- authentik_media:/media
|
||||
- authentik_custom_templates:/templates
|
||||
depends_on:
|
||||
- authentik-postgres
|
||||
- authentik-redis
|
||||
networks:
|
||||
- auth-internal
|
||||
|
||||
authentik-worker:
|
||||
image: ghcr.io/goauthentik/server:latest
|
||||
restart: unless-stopped
|
||||
container_name: auth-worker
|
||||
command: worker
|
||||
environment:
|
||||
AUTHENTIK_SECRET_KEY: ${AUTHENTIK_SECRET_KEY}
|
||||
AUTHENTIK_REDIS__HOST: authentik-redis
|
||||
AUTHENTIK_POSTGRESQL__HOST: authentik-postgres
|
||||
AUTHENTIK_POSTGRESQL__NAME: ${AUTHENTIK_POSTGRES_DB:-authentik}
|
||||
AUTHENTIK_POSTGRESQL__USER: ${AUTHENTIK_POSTGRES_USER:-authentik}
|
||||
AUTHENTIK_POSTGRESQL__PASSWORD: ${AUTHENTIK_POSTGRES_PASSWORD:-authentik}
|
||||
user: root
|
||||
volumes:
|
||||
- authentik_media:/media
|
||||
- authentik_custom_templates:/templates
|
||||
- /var/run/docker.sock:/var/run/docker.sock
|
||||
depends_on:
|
||||
- authentik-postgres
|
||||
- authentik-redis
|
||||
networks:
|
||||
- auth-internal
|
||||
|
||||
volumes:
|
||||
authentik_postgres_data:
|
||||
authentik_redis_data:
|
||||
authentik_media:
|
||||
authentik_custom_templates:
|
||||
|
||||
networks:
|
||||
auth-internal:
|
||||
driver: bridge
|
||||
@@ -60,184 +60,14 @@ services:
|
||||
restart: unless-stopped
|
||||
depends_on:
|
||||
- cms
|
||||
- afc-bridge
|
||||
environment:
|
||||
STRAPI_URL: http://cms:1337
|
||||
STRAPI_API_TOKEN: ${STRAPI_API_TOKEN:-}
|
||||
NEXT_PUBLIC_STRAPI_URL: ${PUBLIC_STRAPI_URL:-http://localhost:1337}
|
||||
AFC_BRIDGE_URL: http://afc-bridge:3001
|
||||
AFC_BRIDGE_SECRET: ${AFC_BRIDGE_SECRET}
|
||||
MERCADOPAGO_ACCESS_TOKEN: ${MERCADOPAGO_ACCESS_TOKEN:-}
|
||||
MERCADOPAGO_WEBHOOK_SECRET: ${MERCADOPAGO_WEBHOOK_SECRET:-}
|
||||
MERCADOPAGO_WEBHOOK_URL: ${MERCADOPAGO_WEBHOOK_URL:-}
|
||||
AFC_PRICE_MXN: ${AFC_PRICE_MXN:-15}
|
||||
NEXT_PUBLIC_SITE_URL: ${NEXT_PUBLIC_SITE_URL:-http://localhost:3000}
|
||||
ports:
|
||||
- "3000:3000"
|
||||
|
||||
cloudflare-ddns:
|
||||
image: favonia/cloudflare-ddns:latest
|
||||
restart: unless-stopped
|
||||
environment:
|
||||
CF_API_TOKEN: ${CF_API_TOKEN}
|
||||
DOMAINS: ${PUBLIC_HOST:-play.consultoria-as.com}
|
||||
PROXIED: "false"
|
||||
IP6_PROVIDER: none
|
||||
|
||||
openfusion:
|
||||
build:
|
||||
context: ../servers/openfusion
|
||||
dockerfile: Dockerfile
|
||||
restart: unless-stopped
|
||||
environment:
|
||||
SHARD_IP: 192.168.10.234
|
||||
MOTD: ${OPENFUSION_MOTD:-Bienvenido a Project Afterlife - FusionFall Academy}
|
||||
ports:
|
||||
- "23000:23000"
|
||||
- "23001:23001"
|
||||
volumes:
|
||||
- openfusion_data:/usr/src/app/data
|
||||
|
||||
minecraft-ftb:
|
||||
image: itzg/minecraft-server:java21
|
||||
restart: unless-stopped
|
||||
container_name: minecraft-ftb
|
||||
environment:
|
||||
EULA: "TRUE"
|
||||
TYPE: FTBA
|
||||
FTB_MODPACK_ID: 125
|
||||
FTB_MODPACK_VERSION_ID: 100181
|
||||
MEMORY: 6G
|
||||
MAX_MEMORY: 6G
|
||||
MOTD: "Project Afterlife - FTB Evolution"
|
||||
DIFFICULTY: normal
|
||||
MAX_PLAYERS: 20
|
||||
VIEW_DISTANCE: 10
|
||||
ENABLE_COMMAND_BLOCK: "true"
|
||||
MAX_TICK_TIME: -1
|
||||
ports:
|
||||
- "25565:25565"
|
||||
volumes:
|
||||
- minecraft_ftb_data:/data
|
||||
deploy:
|
||||
resources:
|
||||
limits:
|
||||
memory: 8G
|
||||
|
||||
geth:
|
||||
build:
|
||||
context: ../blockchain
|
||||
dockerfile: Dockerfile
|
||||
restart: unless-stopped
|
||||
environment:
|
||||
ADMIN_PRIVATE_KEY: ${AFC_ADMIN_PRIVATE_KEY}
|
||||
ADMIN_ADDRESS: ${AFC_ADMIN_ADDRESS}
|
||||
ports:
|
||||
- "8545:8545"
|
||||
- "8546:8546"
|
||||
volumes:
|
||||
- geth_data:/data
|
||||
deploy:
|
||||
resources:
|
||||
limits:
|
||||
memory: 1G
|
||||
|
||||
rpc-ssl:
|
||||
image: nginx:alpine
|
||||
restart: unless-stopped
|
||||
depends_on:
|
||||
- geth
|
||||
volumes:
|
||||
- ./nginx/rpc-ssl.conf:/etc/nginx/nginx.conf:ro
|
||||
- certbot_etc:/etc/letsencrypt:ro
|
||||
ports:
|
||||
- "8443:8443"
|
||||
|
||||
afc-bridge:
|
||||
build:
|
||||
context: ../services/afc-bridge
|
||||
dockerfile: Dockerfile
|
||||
restart: unless-stopped
|
||||
depends_on:
|
||||
- geth
|
||||
environment:
|
||||
GETH_RPC_URL: http://geth:8545
|
||||
ADMIN_PRIVATE_KEY: ${AFC_ADMIN_PRIVATE_KEY}
|
||||
BRIDGE_SECRET: ${AFC_BRIDGE_SECRET}
|
||||
PORT: 3001
|
||||
DB_PATH: /data/bridge.db
|
||||
GAS_FUND_AMOUNT: "0.01"
|
||||
ports:
|
||||
- "3001:3001"
|
||||
volumes:
|
||||
- afc_bridge_data:/data
|
||||
|
||||
sm64coopdx:
|
||||
build:
|
||||
context: ../servers/sm64coopdx
|
||||
dockerfile: Dockerfile
|
||||
restart: unless-stopped
|
||||
container_name: sm64coopdx
|
||||
environment:
|
||||
SM64_PORT: ${SM64_PORT:-7777}
|
||||
SM64_PLAYERS: ${SM64_PLAYERS:-16}
|
||||
ports:
|
||||
- "7777:7777/udp"
|
||||
volumes:
|
||||
- sm64_save:/server/save
|
||||
- sm64_mods:/server/mods
|
||||
deploy:
|
||||
resources:
|
||||
limits:
|
||||
memory: 2G
|
||||
|
||||
n64-netplay:
|
||||
image: k4rian/gopher64-netplay-server:latest
|
||||
container_name: n64-netplay
|
||||
restart: unless-stopped
|
||||
environment:
|
||||
G64NS_NAME: "Afterlife N64 - Mario Party"
|
||||
G64NS_PORT: 45000
|
||||
G64NS_MAXGAMES: 4
|
||||
G64NS_MOTD: "Bienvenido a Project Afterlife - Mario Party N64"
|
||||
G64NS_LOGPATH: "gopher64-server.log"
|
||||
G64NS_DISABLEBROADCAST: "false"
|
||||
G64NS_ENABLEAUTH: "false"
|
||||
ports:
|
||||
- "45000-45004:45000-45004/tcp"
|
||||
- "45000-45004:45000-45004/udp"
|
||||
volumes:
|
||||
- n64_netplay_data:/home/gopher64
|
||||
- /etc/localtime:/etc/localtime:ro
|
||||
deploy:
|
||||
resources:
|
||||
limits:
|
||||
memory: 128M
|
||||
|
||||
dolphin-traversal:
|
||||
build:
|
||||
context: ../servers/dolphin-traversal
|
||||
dockerfile: Dockerfile
|
||||
container_name: dolphin-traversal
|
||||
restart: unless-stopped
|
||||
ports:
|
||||
- "6262:6262/udp"
|
||||
- "6226:6226/udp"
|
||||
deploy:
|
||||
resources:
|
||||
limits:
|
||||
memory: 64M
|
||||
|
||||
volumes:
|
||||
postgres_data:
|
||||
minio_data:
|
||||
openfusion_data:
|
||||
minecraft_ftb_data:
|
||||
geth_data:
|
||||
afc_bridge_data:
|
||||
sm64_save:
|
||||
sm64_mods:
|
||||
n64_netplay_data:
|
||||
certbot_etc:
|
||||
external: true
|
||||
name: docker_certbot_etc
|
||||
|
||||
36
docker/docker-compose.fusionfall.yml
Normal file
36
docker/docker-compose.fusionfall.yml
Normal file
@@ -0,0 +1,36 @@
|
||||
version: "3.8"
|
||||
|
||||
services:
|
||||
fusionfall:
|
||||
build:
|
||||
context: ../servers/openfusion
|
||||
dockerfile: Dockerfile
|
||||
container_name: fusionfall
|
||||
restart: unless-stopped
|
||||
ports:
|
||||
- "23000:23000/tcp"
|
||||
- "23001:23001/tcp"
|
||||
volumes:
|
||||
- ../servers/openfusion/data:/usr/src/app/data
|
||||
- ../servers/openfusion/tdata:/usr/src/app/tdata:ro
|
||||
- ../servers/openfusion/config.ini:/usr/src/app/config.ini
|
||||
environment:
|
||||
- SHARD_IP=${FUSIONFALL_SHARD_IP:-192.168.10.84}
|
||||
- MOTD=${FUSIONFALL_MOTD:-Bienvenido a Project Afterlife - FusionFall Academy}
|
||||
- ACCOUNT_LEVEL=${FUSIONFALL_ACCOUNT_LEVEL:-1}
|
||||
networks:
|
||||
- fusionfall
|
||||
# Aislamiento: sin acceso saliente a internet (red interna)
|
||||
# Los clientes locales se conectan via ports mapeados en el host
|
||||
sysctls:
|
||||
- net.ipv4.ip_unprivileged_port_start=23000
|
||||
healthcheck:
|
||||
test: ["CMD-SHELL", "ss -tln | grep -q ':23000' || exit 1"]
|
||||
interval: 30s
|
||||
timeout: 5s
|
||||
retries: 3
|
||||
|
||||
networks:
|
||||
fusionfall:
|
||||
driver: bridge
|
||||
internal: false
|
||||
264
docker/docker-compose.main.yml
Normal file
264
docker/docker-compose.main.yml
Normal file
@@ -0,0 +1,264 @@
|
||||
# =============================================================================
|
||||
# VM PRINCIPAL — Project Afterlife (Soft Launch)
|
||||
# =============================================================================
|
||||
# IP Privada: 10.0.0.10
|
||||
# Puertos Publicos: 80, 443
|
||||
# Servicios: Next.js, Strapi CMS, Authentik SSO, PostgreSQL x2, Redis, MinIO, Nginx, Certbot
|
||||
#
|
||||
# Esta es la VM principal donde corre toda la plataforma web, autenticacion
|
||||
# y administracion. Los servidores de juegos corren en VMs separadas.
|
||||
# =============================================================================
|
||||
|
||||
services:
|
||||
# ---------------------------------------------------------------------------
|
||||
# PostgreSQL — Base de datos para Strapi CMS
|
||||
# ---------------------------------------------------------------------------
|
||||
postgres:
|
||||
image: postgres:16-alpine
|
||||
restart: unless-stopped
|
||||
container_name: main-postgres
|
||||
volumes:
|
||||
- postgres_data:/var/lib/postgresql/data
|
||||
environment:
|
||||
POSTGRES_DB: ${DATABASE_NAME:-afterlife}
|
||||
POSTGRES_USER: ${DATABASE_USERNAME:-afterlife}
|
||||
POSTGRES_PASSWORD: ${DATABASE_PASSWORD:-afterlife}
|
||||
ports:
|
||||
- "127.0.0.1:5432:5432"
|
||||
healthcheck:
|
||||
test: ["CMD-SHELL", "pg_isready -U ${DATABASE_USERNAME:-afterlife}"]
|
||||
interval: 5s
|
||||
timeout: 5s
|
||||
retries: 5
|
||||
networks:
|
||||
- main-internal
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# PostgreSQL — Base de datos para Authentik
|
||||
# ---------------------------------------------------------------------------
|
||||
authentik-postgres:
|
||||
image: docker.io/library/postgres:16-alpine
|
||||
restart: unless-stopped
|
||||
container_name: main-authentik-postgres
|
||||
healthcheck:
|
||||
test: ["CMD-SHELL", "pg_isready -d $${POSTGRES_DB} -U $${POSTGRES_USER}"]
|
||||
start_period: 20s
|
||||
interval: 30s
|
||||
retries: 5
|
||||
timeout: 5s
|
||||
volumes:
|
||||
- authentik_postgres_data:/var/lib/postgresql/data
|
||||
environment:
|
||||
POSTGRES_PASSWORD: ${AUTHENTIK_POSTGRES_PASSWORD:-authentik}
|
||||
POSTGRES_USER: ${AUTHENTIK_POSTGRES_USER:-authentik}
|
||||
POSTGRES_DB: ${AUTHENTIK_POSTGRES_DB:-authentik}
|
||||
ports:
|
||||
- "127.0.0.1:5433:5432"
|
||||
networks:
|
||||
- main-internal
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Redis — Cache para Authentik
|
||||
# ---------------------------------------------------------------------------
|
||||
authentik-redis:
|
||||
image: docker.io/library/redis:alpine
|
||||
restart: unless-stopped
|
||||
container_name: main-authentik-redis
|
||||
healthcheck:
|
||||
test: ["CMD-SHELL", "redis-cli ping | grep PONG"]
|
||||
start_period: 20s
|
||||
interval: 30s
|
||||
retries: 5
|
||||
timeout: 3s
|
||||
volumes:
|
||||
- authentik_redis_data:/data
|
||||
networks:
|
||||
- main-internal
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# MinIO — Almacenamiento S3-compatible
|
||||
# ---------------------------------------------------------------------------
|
||||
minio:
|
||||
image: minio/minio:latest
|
||||
restart: unless-stopped
|
||||
container_name: main-minio
|
||||
command: server /data --console-address ":9001"
|
||||
volumes:
|
||||
- minio_data:/data
|
||||
environment:
|
||||
MINIO_ROOT_USER: ${MINIO_ROOT_USER:-afterlife}
|
||||
MINIO_ROOT_PASSWORD: ${MINIO_ROOT_PASSWORD:-afterlife123}
|
||||
ports:
|
||||
- "127.0.0.1:9000:9000"
|
||||
- "127.0.0.1:9001:9001"
|
||||
networks:
|
||||
- main-internal
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Authentik Server — SSO / Identity Provider
|
||||
# ---------------------------------------------------------------------------
|
||||
authentik-server:
|
||||
image: ghcr.io/goauthentik/server:latest
|
||||
restart: unless-stopped
|
||||
container_name: main-authentik-server
|
||||
command: server
|
||||
environment:
|
||||
AUTHENTIK_SECRET_KEY: ${AUTHENTIK_SECRET_KEY}
|
||||
AUTHENTIK_REDIS__HOST: authentik-redis
|
||||
AUTHENTIK_POSTGRESQL__HOST: authentik-postgres
|
||||
AUTHENTIK_POSTGRESQL__NAME: ${AUTHENTIK_POSTGRES_DB:-authentik}
|
||||
AUTHENTIK_POSTGRESQL__USER: ${AUTHENTIK_POSTGRES_USER:-authentik}
|
||||
AUTHENTIK_POSTGRESQL__PASSWORD: ${AUTHENTIK_POSTGRES_PASSWORD:-authentik}
|
||||
AUTHENTIK_LISTEN__HTTP: 0.0.0.0:9000
|
||||
AUTHENTIK_LISTEN__HTTPS: 0.0.0.0:9443
|
||||
expose:
|
||||
- "9000"
|
||||
- "9443"
|
||||
volumes:
|
||||
- authentik_media:/media
|
||||
- authentik_custom_templates:/templates
|
||||
depends_on:
|
||||
- authentik-postgres
|
||||
- authentik-redis
|
||||
networks:
|
||||
- main-internal
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Authentik Worker — Tareas en background
|
||||
# ---------------------------------------------------------------------------
|
||||
authentik-worker:
|
||||
image: ghcr.io/goauthentik/server:latest
|
||||
restart: unless-stopped
|
||||
container_name: main-authentik-worker
|
||||
command: worker
|
||||
environment:
|
||||
AUTHENTIK_SECRET_KEY: ${AUTHENTIK_SECRET_KEY}
|
||||
AUTHENTIK_REDIS__HOST: authentik-redis
|
||||
AUTHENTIK_POSTGRESQL__HOST: authentik-postgres
|
||||
AUTHENTIK_POSTGRESQL__NAME: ${AUTHENTIK_POSTGRES_DB:-authentik}
|
||||
AUTHENTIK_POSTGRESQL__USER: ${AUTHENTIK_POSTGRES_USER:-authentik}
|
||||
AUTHENTIK_POSTGRESQL__PASSWORD: ${AUTHENTIK_POSTGRES_PASSWORD:-authentik}
|
||||
user: root
|
||||
volumes:
|
||||
- authentik_media:/media
|
||||
- authentik_custom_templates:/templates
|
||||
- /var/run/docker.sock:/var/run/docker.sock
|
||||
depends_on:
|
||||
- authentik-postgres
|
||||
- authentik-redis
|
||||
networks:
|
||||
- main-internal
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Strapi CMS — Content Management
|
||||
# ---------------------------------------------------------------------------
|
||||
cms:
|
||||
build:
|
||||
context: ../apps/cms
|
||||
dockerfile: Dockerfile
|
||||
restart: unless-stopped
|
||||
container_name: main-cms
|
||||
depends_on:
|
||||
postgres:
|
||||
condition: service_healthy
|
||||
environment:
|
||||
HOST: 0.0.0.0
|
||||
PORT: 1337
|
||||
DATABASE_HOST: postgres
|
||||
DATABASE_PORT: 5432
|
||||
DATABASE_NAME: ${DATABASE_NAME:-afterlife}
|
||||
DATABASE_USERNAME: ${DATABASE_USERNAME:-afterlife}
|
||||
DATABASE_PASSWORD: ${DATABASE_PASSWORD:-afterlife}
|
||||
APP_KEYS: ${APP_KEYS}
|
||||
API_TOKEN_SALT: ${API_TOKEN_SALT}
|
||||
ADMIN_JWT_SECRET: ${ADMIN_JWT_SECRET}
|
||||
TRANSFER_TOKEN_SALT: ${TRANSFER_TOKEN_SALT}
|
||||
JWT_SECRET: ${JWT_SECRET}
|
||||
# Authentik OIDC for CMS admin SSO
|
||||
AUTHENTIK_URL: ${AUTHENTIK_URL:-http://authentik-server:9000}
|
||||
AUTHENTIK_CLIENT_ID: ${AUTHENTIK_CLIENT_ID_CMS:-}
|
||||
AUTHENTIK_CLIENT_SECRET: ${AUTHENTIK_CLIENT_SECRET_CMS:-}
|
||||
AUTHENTIK_REDIRECT_URI: ${AUTHENTIK_REDIRECT_URI_CMS:-}
|
||||
PUBLIC_STRAPI_URL: ${PUBLIC_STRAPI_URL:-https://play.consultoria-as.com}
|
||||
expose:
|
||||
- "1337"
|
||||
networks:
|
||||
- main-internal
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Next.js — Frontend Web
|
||||
# ---------------------------------------------------------------------------
|
||||
web:
|
||||
build:
|
||||
context: ../
|
||||
dockerfile: apps/web/Dockerfile
|
||||
restart: unless-stopped
|
||||
container_name: main-web
|
||||
depends_on:
|
||||
- cms
|
||||
- authentik-server
|
||||
environment:
|
||||
STRAPI_URL: http://cms:1337
|
||||
STRAPI_API_TOKEN: ${STRAPI_API_TOKEN:-}
|
||||
NEXT_PUBLIC_STRAPI_URL: ${PUBLIC_STRAPI_URL:-https://play.consultoria-as.com}
|
||||
# Authentik OIDC
|
||||
AUTHENTIK_URL: ${AUTHENTIK_URL:-http://authentik-server:9000}
|
||||
AUTHENTIK_CLIENT_ID: ${AUTHENTIK_CLIENT_ID_WEB:-}
|
||||
AUTHENTIK_CLIENT_SECRET: ${AUTHENTIK_CLIENT_SECRET_WEB:-}
|
||||
AUTHENTIK_REDIRECT_URI: ${AUTHENTIK_REDIRECT_URI_WEB:-}
|
||||
# Public game server IPs (displayed to players)
|
||||
NEXT_PUBLIC_NIER_IP: ${NIER_PUBLIC_IP:-play.consultoria-as.com}
|
||||
NEXT_PUBLIC_DBO_IP: ${DBO_PUBLIC_IP:-play.consultoria-as.com}
|
||||
NEXT_PUBLIC_MAPLE2_IP: ${MAPLE2_PUBLIC_IP:-play.consultoria-as.com}
|
||||
NEXT_PUBLIC_FUSIONFALL_IP: ${FUSIONFALL_PUBLIC_IP:-play.consultoria-as.com}
|
||||
NEXT_PUBLIC_SITE_URL: ${NEXT_PUBLIC_SITE_URL:-https://play.consultoria-as.com}
|
||||
expose:
|
||||
- "3000"
|
||||
networks:
|
||||
- main-internal
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Nginx — Reverse Proxy + SSL
|
||||
# ---------------------------------------------------------------------------
|
||||
nginx:
|
||||
image: nginx:alpine
|
||||
restart: unless-stopped
|
||||
container_name: main-nginx
|
||||
depends_on:
|
||||
- web
|
||||
- cms
|
||||
- authentik-server
|
||||
ports:
|
||||
- "80:80"
|
||||
- "443:443"
|
||||
volumes:
|
||||
- ./nginx/nginx.main.conf:/etc/nginx/nginx.conf:ro
|
||||
- certbot_certs:/etc/letsencrypt:ro
|
||||
- certbot_www:/var/www/certbot:ro
|
||||
networks:
|
||||
- main-internal
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Certbot — SSL automático
|
||||
# ---------------------------------------------------------------------------
|
||||
certbot:
|
||||
image: certbot/certbot
|
||||
container_name: main-certbot
|
||||
volumes:
|
||||
- certbot_certs:/etc/letsencrypt
|
||||
- certbot_www:/var/www/certbot
|
||||
entrypoint: "/bin/sh -c 'trap exit TERM; while :; do certbot renew; sleep 12h; done'"
|
||||
|
||||
volumes:
|
||||
postgres_data:
|
||||
authentik_postgres_data:
|
||||
authentik_redis_data:
|
||||
authentik_media:
|
||||
authentik_custom_templates:
|
||||
minio_data:
|
||||
certbot_certs:
|
||||
certbot_www:
|
||||
|
||||
networks:
|
||||
main-internal:
|
||||
driver: bridge
|
||||
@@ -1,120 +0,0 @@
|
||||
services:
|
||||
maple2-mysql:
|
||||
image: mysql:8.0
|
||||
restart: unless-stopped
|
||||
container_name: maple2-db
|
||||
environment:
|
||||
MYSQL_ROOT_PASSWORD: ${MAPLE2_DB_PASSWORD:-maplestory}
|
||||
volumes:
|
||||
- maple2_mysql:/var/lib/mysql
|
||||
ports:
|
||||
- "3307:3306"
|
||||
healthcheck:
|
||||
test: ["CMD", "mysqladmin", "ping", "-h", "localhost", "-p${MAPLE2_DB_PASSWORD:-maplestory}"]
|
||||
interval: 10s
|
||||
timeout: 5s
|
||||
retries: 10
|
||||
|
||||
maple2-file-ingest:
|
||||
container_name: maple2-file-ingest
|
||||
image: mcr.microsoft.com/dotnet/sdk:8.0
|
||||
working_dir: /app/Maple2.File.Ingest
|
||||
entrypoint: ["dotnet", "run"]
|
||||
depends_on:
|
||||
maple2-mysql:
|
||||
condition: service_healthy
|
||||
env_file:
|
||||
- ../servers/maple2/.env
|
||||
environment:
|
||||
DB_IP: maple2-mysql
|
||||
MS2_DATA_FOLDER: /ClientData
|
||||
volumes:
|
||||
- ../servers/maple2:/app
|
||||
- ${MAPLE2_DATA_FOLDER:-../servers/maple2/client-data/Data}:/ClientData
|
||||
- maple2_dotnet_tools:/root/.dotnet/tools
|
||||
profiles:
|
||||
- ingest
|
||||
|
||||
maple2-world:
|
||||
build:
|
||||
context: ../servers/maple2
|
||||
dockerfile: ./Maple2.Server.World/Dockerfile
|
||||
container_name: maple2-world
|
||||
image: maple2/world
|
||||
command: dotnet Maple2.Server.World.dll
|
||||
restart: unless-stopped
|
||||
depends_on:
|
||||
maple2-mysql:
|
||||
condition: service_healthy
|
||||
ports:
|
||||
- "21001:21001"
|
||||
env_file:
|
||||
- ../servers/maple2/.env
|
||||
environment:
|
||||
DB_IP: maple2-mysql
|
||||
GRPC_LOGIN_IP: maple2-login
|
||||
|
||||
maple2-login:
|
||||
build:
|
||||
context: ../servers/maple2
|
||||
dockerfile: ./Maple2.Server.Login/Dockerfile
|
||||
container_name: maple2-login
|
||||
image: maple2/login
|
||||
command: dotnet Maple2.Server.Login.dll
|
||||
restart: unless-stopped
|
||||
depends_on:
|
||||
maple2-mysql:
|
||||
condition: service_healthy
|
||||
maple2-world:
|
||||
condition: service_started
|
||||
ports:
|
||||
- "20001:20001"
|
||||
env_file:
|
||||
- ../servers/maple2/.env
|
||||
environment:
|
||||
DB_IP: maple2-mysql
|
||||
GRPC_WORLD_IP: maple2-world
|
||||
|
||||
maple2-web:
|
||||
build:
|
||||
context: ../servers/maple2
|
||||
dockerfile: ./Maple2.Server.Web/Dockerfile
|
||||
container_name: maple2-web
|
||||
image: maple2/web
|
||||
command: dotnet Maple2.Server.Web.dll
|
||||
restart: unless-stopped
|
||||
depends_on:
|
||||
maple2-mysql:
|
||||
condition: service_healthy
|
||||
ports:
|
||||
- "4000:4000"
|
||||
env_file:
|
||||
- ../servers/maple2/.env
|
||||
environment:
|
||||
DB_IP: maple2-mysql
|
||||
|
||||
maple2-game-ch0:
|
||||
build:
|
||||
context: ../servers/maple2
|
||||
dockerfile: ./Maple2.Server.Game/Dockerfile
|
||||
image: maple2/game
|
||||
restart: unless-stopped
|
||||
depends_on:
|
||||
maple2-mysql:
|
||||
condition: service_healthy
|
||||
maple2-world:
|
||||
condition: service_started
|
||||
ports:
|
||||
- "20003:20003"
|
||||
- "21003:21003"
|
||||
env_file:
|
||||
- ../servers/maple2/.env
|
||||
environment:
|
||||
DB_IP: maple2-mysql
|
||||
GRPC_GAME_IP: maple2-game-ch0
|
||||
GRPC_WORLD_IP: maple2-world
|
||||
INSTANCED_CONTENT: "false"
|
||||
|
||||
volumes:
|
||||
maple2_mysql:
|
||||
maple2_dotnet_tools:
|
||||
29
docker/docker-compose.nier.yml
Normal file
29
docker/docker-compose.nier.yml
Normal file
@@ -0,0 +1,29 @@
|
||||
# =============================================================================
|
||||
# VM: NieR Reincarnation Server
|
||||
# IP Privada: 10.0.0.70
|
||||
# Puertos Publicos: 80, 443
|
||||
# =============================================================================
|
||||
|
||||
services:
|
||||
nier-server:
|
||||
build:
|
||||
context: ../servers/nier-reincarnation
|
||||
dockerfile: Dockerfile
|
||||
image: nier/server:latest
|
||||
container_name: nier-server
|
||||
restart: unless-stopped
|
||||
ports:
|
||||
- "80:80"
|
||||
- "443:443"
|
||||
volumes:
|
||||
- nier_data:/data
|
||||
environment:
|
||||
ASPNETCORE_ENVIRONMENT: Production
|
||||
ASPNETCORE_URLS: "http://0.0.0.0:80;https://0.0.0.0:443"
|
||||
deploy:
|
||||
resources:
|
||||
limits:
|
||||
memory: 1536M
|
||||
|
||||
volumes:
|
||||
nier_data:
|
||||
@@ -2,6 +2,10 @@ services:
|
||||
postgres:
|
||||
image: postgres:16-alpine
|
||||
restart: unless-stopped
|
||||
deploy:
|
||||
resources:
|
||||
limits:
|
||||
memory: 512M
|
||||
volumes:
|
||||
- postgres_data:/var/lib/postgresql/data
|
||||
environment:
|
||||
@@ -15,6 +19,10 @@ services:
|
||||
image: minio/minio:latest
|
||||
restart: unless-stopped
|
||||
command: server /data --console-address ":9001"
|
||||
deploy:
|
||||
resources:
|
||||
limits:
|
||||
memory: 512M
|
||||
volumes:
|
||||
- minio_data:/data
|
||||
environment:
|
||||
@@ -29,6 +37,12 @@ services:
|
||||
context: ../apps/cms
|
||||
dockerfile: Dockerfile
|
||||
restart: unless-stopped
|
||||
deploy:
|
||||
resources:
|
||||
limits:
|
||||
memory: 1536M
|
||||
volumes:
|
||||
- cms_uploads:/app/public/uploads
|
||||
depends_on:
|
||||
- postgres
|
||||
- minio
|
||||
@@ -40,6 +54,8 @@ services:
|
||||
DATABASE_NAME: ${DATABASE_NAME:-afterlife}
|
||||
DATABASE_USERNAME: ${DATABASE_USERNAME:-afterlife}
|
||||
DATABASE_PASSWORD: ${DATABASE_PASSWORD:-afterlife}
|
||||
REDIS_HOST: redis
|
||||
REDIS_PORT: 6379
|
||||
APP_KEYS: ${APP_KEYS}
|
||||
API_TOKEN_SALT: ${API_TOKEN_SALT}
|
||||
ADMIN_JWT_SECRET: ${ADMIN_JWT_SECRET}
|
||||
@@ -53,12 +69,21 @@ services:
|
||||
context: ../
|
||||
dockerfile: apps/web/Dockerfile
|
||||
restart: unless-stopped
|
||||
deploy:
|
||||
resources:
|
||||
limits:
|
||||
memory: 1536M
|
||||
depends_on:
|
||||
- cms
|
||||
environment:
|
||||
STRAPI_URL: http://cms:1337
|
||||
STRAPI_API_TOKEN: ${STRAPI_API_TOKEN}
|
||||
NEXT_PUBLIC_STRAPI_URL: ${PUBLIC_STRAPI_URL:-http://localhost:1337}
|
||||
DATABASE_HOST: postgres
|
||||
DATABASE_PORT: 5432
|
||||
DATABASE_NAME: ${DATABASE_NAME:-afterlife}
|
||||
DATABASE_USERNAME: ${DATABASE_USERNAME:-afterlife}
|
||||
DATABASE_PASSWORD: ${DATABASE_PASSWORD:-afterlife}
|
||||
ports:
|
||||
- "3000:3000"
|
||||
|
||||
@@ -76,6 +101,19 @@ services:
|
||||
- certbot_certs:/etc/letsencrypt:ro
|
||||
- certbot_www:/var/www/certbot:ro
|
||||
|
||||
redis:
|
||||
image: redis:7-alpine
|
||||
restart: unless-stopped
|
||||
command: redis-server --maxmemory 256mb --maxmemory-policy allkeys-lru --appendonly yes
|
||||
deploy:
|
||||
resources:
|
||||
limits:
|
||||
memory: 256M
|
||||
volumes:
|
||||
- redis_data:/data
|
||||
ports:
|
||||
- "6379:6379"
|
||||
|
||||
certbot:
|
||||
image: certbot/certbot
|
||||
volumes:
|
||||
@@ -85,5 +123,7 @@ services:
|
||||
volumes:
|
||||
postgres_data:
|
||||
minio_data:
|
||||
cms_uploads:
|
||||
redis_data:
|
||||
certbot_certs:
|
||||
certbot_www:
|
||||
|
||||
102
docker/nginx/nginx.main.conf
Normal file
102
docker/nginx/nginx.main.conf
Normal file
@@ -0,0 +1,102 @@
|
||||
events {
|
||||
worker_connections 1024;
|
||||
}
|
||||
|
||||
http {
|
||||
upstream web {
|
||||
server web:3000;
|
||||
}
|
||||
|
||||
upstream cms {
|
||||
server cms:1337;
|
||||
}
|
||||
|
||||
upstream authentik {
|
||||
server authentik-server:9000;
|
||||
}
|
||||
|
||||
server {
|
||||
listen 80;
|
||||
server_name _;
|
||||
|
||||
client_max_body_size 100M;
|
||||
|
||||
# Redirect all HTTP to HTTPS (optional — remove if no SSL yet)
|
||||
# location / {
|
||||
# return 301 https://$host$request_uri;
|
||||
# }
|
||||
|
||||
# --- Authentik (SSO) accessible at /auth ---
|
||||
location /auth/ {
|
||||
proxy_pass http://authentik;
|
||||
proxy_http_version 1.1;
|
||||
proxy_set_header Host $host;
|
||||
proxy_set_header X-Real-IP $remote_addr;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
proxy_set_header X-Forwarded-Proto $scheme;
|
||||
}
|
||||
|
||||
# --- Next.js Auth API routes ---
|
||||
location /api/auth/ {
|
||||
proxy_pass http://web;
|
||||
proxy_http_version 1.1;
|
||||
proxy_set_header Host $host;
|
||||
proxy_set_header X-Real-IP $remote_addr;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
proxy_set_header X-Forwarded-Proto $scheme;
|
||||
}
|
||||
|
||||
# --- AFC Store API (if enabled) ---
|
||||
location /api/afc/ {
|
||||
proxy_pass http://web;
|
||||
proxy_http_version 1.1;
|
||||
proxy_set_header Host $host;
|
||||
proxy_set_header X-Real-IP $remote_addr;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
proxy_set_header X-Forwarded-Proto $scheme;
|
||||
}
|
||||
|
||||
# --- Strapi API ---
|
||||
location /api/ {
|
||||
proxy_pass http://cms;
|
||||
proxy_http_version 1.1;
|
||||
proxy_set_header Host $host;
|
||||
proxy_set_header X-Real-IP $remote_addr;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
proxy_set_header X-Forwarded-Proto $scheme;
|
||||
}
|
||||
|
||||
# --- Strapi Admin Panel ---
|
||||
location /admin {
|
||||
proxy_pass http://cms;
|
||||
proxy_http_version 1.1;
|
||||
proxy_set_header Host $host;
|
||||
proxy_set_header X-Real-IP $remote_addr;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
proxy_set_header X-Forwarded-Proto $scheme;
|
||||
}
|
||||
|
||||
# --- Strapi Uploads ---
|
||||
location /uploads/ {
|
||||
proxy_pass http://cms;
|
||||
proxy_set_header Host $host;
|
||||
}
|
||||
|
||||
# --- Next.js Frontend (catch-all) ---
|
||||
location / {
|
||||
proxy_pass http://web;
|
||||
proxy_http_version 1.1;
|
||||
proxy_set_header Upgrade $http_upgrade;
|
||||
proxy_set_header Connection "upgrade";
|
||||
proxy_set_header Host $host;
|
||||
proxy_set_header X-Real-IP $remote_addr;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
proxy_set_header X-Forwarded-Proto $scheme;
|
||||
}
|
||||
|
||||
# --- Certbot challenge ---
|
||||
location /.well-known/acme-challenge/ {
|
||||
root /var/www/certbot;
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user