This commit is contained in:
28
.woodpecker.yml
Normal file
28
.woodpecker.yml
Normal file
@@ -0,0 +1,28 @@
|
||||
pipeline:
|
||||
build:
|
||||
image: woodpeckerci/plugin-docker
|
||||
settings:
|
||||
registry: gitea.infra.mintel.me
|
||||
repo: gitea.infra.mintel.me/mintel/mb-grid-solutions
|
||||
username:
|
||||
from_secret: GITEA_USER
|
||||
password:
|
||||
from_secret: GITEA_TOKEN
|
||||
when:
|
||||
event: push
|
||||
branch: main
|
||||
|
||||
deploy:
|
||||
image: alpine
|
||||
commands:
|
||||
- apk add --no-cache openssh
|
||||
- mkdir -p ~/.ssh
|
||||
- echo "$ALPHA_SSH_KEY" > ~/.ssh/id_ed25519
|
||||
- chmod 600 ~/.ssh/id_ed25519
|
||||
- ssh -o StrictHostKeyChecking=no deploy@alpha.mintel.me "mkdir -p /opt/alpha/sites/mb-grid-solutions"
|
||||
- scp -o StrictHostKeyChecking=no docker-compose.yaml deploy@alpha.mintel.me:/opt/alpha/sites/mb-grid-solutions/docker-compose.yaml
|
||||
- ssh -o StrictHostKeyChecking=no deploy@alpha.mintel.me "cd /opt/alpha/sites/mb-grid-solutions && docker compose pull && docker compose up -d"
|
||||
secrets: [ ALPHA_SSH_KEY ]
|
||||
when:
|
||||
event: push
|
||||
branch: main
|
||||
26
docker-compose.yaml
Normal file
26
docker-compose.yaml
Normal file
@@ -0,0 +1,26 @@
|
||||
services:
|
||||
app:
|
||||
build: .
|
||||
image: gitea.infra.mintel.me/mintel/mb-grid-solutions:latest
|
||||
restart: always
|
||||
expose:
|
||||
- "3000"
|
||||
labels:
|
||||
- "traefik.enable=true"
|
||||
- "traefik.http.routers.mb-grid-solutions.rule=Host(`mb-grid-solutions.com`, `www.mb-grid-solutions.com`)"
|
||||
- "traefik.http.routers.mb-grid-solutions.entrypoints=websecure"
|
||||
- "traefik.http.routers.mb-grid-solutions.tls.certresolver=le"
|
||||
- "traefik.http.services.mb-grid-solutions.loadbalancer.server.port=3000"
|
||||
healthcheck:
|
||||
test: ["CMD", "wget", "-q", "-O", "-", "http://localhost:3000/health"]
|
||||
interval: 5s
|
||||
timeout: 2s
|
||||
retries: 10
|
||||
deploy:
|
||||
replicas: 2
|
||||
networks:
|
||||
- alpha
|
||||
|
||||
networks:
|
||||
alpha:
|
||||
external: true
|
||||
227
docs/PLATFORM.md
Normal file
227
docs/PLATFORM.md
Normal file
@@ -0,0 +1,227 @@
|
||||
# Mintel Alpha Platform — Developer Cheat Sheet
|
||||
|
||||
This platform runs real customer websites on their own domains
|
||||
(e.g. klz-cables.com, shop.customer.de, example.org).
|
||||
|
||||
You do not manage servers.
|
||||
You ship Docker containers.
|
||||
Mintel runs the platform.
|
||||
|
||||
---
|
||||
|
||||
## Control Plane (Infra)
|
||||
|
||||
These are for developers only (not customers):
|
||||
|
||||
Git
|
||||
https://git.infra.mintel.me
|
||||
|
||||
CI
|
||||
https://ci.infra.mintel.me
|
||||
|
||||
Errors (GlitchTip)
|
||||
https://errors.infra.mintel.me
|
||||
|
||||
Analytics (Umami)
|
||||
https://analytics.infra.mintel.me
|
||||
|
||||
Uptime
|
||||
https://status.infra.mintel.me
|
||||
|
||||
Logs
|
||||
https://logs.infra.mintel.me
|
||||
|
||||
---
|
||||
|
||||
## Production Platform (Alpha)
|
||||
|
||||
Alpha runs all customer websites and listens on ports 80 and 443 for the entire internet.
|
||||
|
||||
Customer domains point their DNS A records to the Alpha server IP.
|
||||
|
||||
Traefik on Alpha routes domains to the correct containers.
|
||||
|
||||
---
|
||||
|
||||
## How routing works
|
||||
|
||||
Each web service declares which domains it owns via Traefik labels.
|
||||
|
||||
Example domains:
|
||||
- klz-cables.com
|
||||
- www.klz-cables.com
|
||||
|
||||
Traefik routes traffic by Host header.
|
||||
|
||||
---
|
||||
|
||||
## Directory layout on Alpha
|
||||
|
||||
Each app lives in:
|
||||
|
||||
/opt/alpha/sites/APP_NAME
|
||||
|
||||
This directory contains:
|
||||
- docker-compose.yml
|
||||
- .env (optional)
|
||||
- persistent volumes
|
||||
|
||||
---
|
||||
|
||||
## Databases
|
||||
|
||||
### Postgres (shared)
|
||||
|
||||
All apps share one Postgres server but use separate databases.
|
||||
|
||||
Connection format:
|
||||
|
||||
postgres://infra:infra@postgres:5432/APP_DB
|
||||
|
||||
Example:
|
||||
|
||||
postgres://infra:infra@postgres:5432/klz_site
|
||||
|
||||
Each app must use its own database.
|
||||
|
||||
---
|
||||
|
||||
### Redis (shared)
|
||||
|
||||
All apps share one Redis server but use separate DB indexes.
|
||||
|
||||
Connection format:
|
||||
|
||||
redis://redis:6379/N
|
||||
|
||||
Example:
|
||||
|
||||
redis://redis:6379/1
|
||||
redis://redis:6379/2
|
||||
|
||||
Each app must use its own Redis DB number.
|
||||
|
||||
---
|
||||
|
||||
## Traefik labels (required)
|
||||
|
||||
Every public web service must define these labels:
|
||||
|
||||
traefik.enable=true
|
||||
traefik.http.routers.app.rule=Host(klz-cables.com,www.klz-cables.com)
|
||||
traefik.http.routers.app.entrypoints=websecure
|
||||
traefik.http.routers.app.tls.certresolver=le
|
||||
traefik.http.services.app.loadbalancer.server.port=YOUR_INTERNAL_PORT
|
||||
|
||||
Traefik automatically provides HTTPS.
|
||||
|
||||
---
|
||||
|
||||
## Zero-downtime deployments
|
||||
|
||||
All web services must support health checks.
|
||||
|
||||
Your app must expose:
|
||||
|
||||
GET /health
|
||||
returns HTTP 200 when ready.
|
||||
|
||||
Docker Compose example:
|
||||
|
||||
healthcheck:
|
||||
test: wget -q -O - http://localhost:3000/health
|
||||
interval: 5s
|
||||
timeout: 2s
|
||||
retries: 10
|
||||
|
||||
Run multiple replicas:
|
||||
|
||||
deploy:
|
||||
replicas: 2
|
||||
|
||||
During deploy:
|
||||
- New containers start
|
||||
- They become healthy
|
||||
- Traefik switches traffic
|
||||
- Old containers are removed
|
||||
|
||||
No downtime.
|
||||
|
||||
---
|
||||
|
||||
## Error tracking (GlitchTip)
|
||||
|
||||
Each project gets a DSN, similar to Sentry.
|
||||
|
||||
Example:
|
||||
|
||||
https://PUBLIC_KEY@errors.infra.mintel.me/PROJECT_ID
|
||||
|
||||
Use as SENTRY_DSN in your app.
|
||||
|
||||
All errors appear in GlitchTip.
|
||||
|
||||
---
|
||||
|
||||
## Analytics (Umami)
|
||||
|
||||
Each site gets a website ID.
|
||||
|
||||
Include this script in your site:
|
||||
|
||||
https://analytics.infra.mintel.me/script.js
|
||||
data-website-id=YOUR_ID
|
||||
|
||||
Traffic is visible in Umami.
|
||||
|
||||
---
|
||||
|
||||
## Deployment via Woodpecker
|
||||
|
||||
Woodpecker deploys to Alpha via SSH.
|
||||
|
||||
Target:
|
||||
deploy@alpha.mintel.me
|
||||
|
||||
Auth:
|
||||
ALPHA_SSH_KEY is provided as a CI secret.
|
||||
|
||||
---
|
||||
|
||||
## Woodpecker pipeline example
|
||||
|
||||
Every repo must contain .woodpecker.yml:
|
||||
|
||||
pipeline:
|
||||
deploy:
|
||||
image: alpine
|
||||
commands:
|
||||
- apk add --no-cache openssh
|
||||
- mkdir -p ~/.ssh
|
||||
- echo "$ALPHA_SSH_KEY" > ~/.ssh/id_ed25519
|
||||
- chmod 600 ~/.ssh/id_ed25519
|
||||
- ssh -o StrictHostKeyChecking=no deploy@alpha.mintel.me "cd /opt/alpha/sites/APP_NAME && docker compose pull && docker compose up -d"
|
||||
|
||||
---
|
||||
|
||||
## Monitoring
|
||||
|
||||
Errors: GlitchTip
|
||||
Traffic: Umami
|
||||
Uptime: Uptime-Kuma
|
||||
Logs: Dozzle
|
||||
|
||||
Infra monitors all services automatically.
|
||||
|
||||
---
|
||||
|
||||
## Summary
|
||||
|
||||
You push code.
|
||||
Woodpecker deploys.
|
||||
Traefik routes domains.
|
||||
Postgres and Redis are shared but isolated.
|
||||
Zero-downtime updates are automatic.
|
||||
Errors, traffic and uptime are tracked.
|
||||
|
||||
This is a real production platform.
|
||||
Reference in New Issue
Block a user