feat: Update CI/CD workflow to trigger separate backend and dashboard deployments; enhance deployment documentation with Nginx proxy details and OAuth callback URLs
This commit is contained in:
+31
-10
@@ -66,23 +66,44 @@ jobs:
|
||||
- dashboard-checks
|
||||
if: ${{ github.event_name == 'push' && github.ref == 'refs/heads/main' }}
|
||||
steps:
|
||||
- name: Trigger Coolify deploy hook
|
||||
- name: Trigger backend deploy
|
||||
env:
|
||||
COOLIFY_DEPLOY_HOOK_URL: ${{ secrets.COOLIFY_DEPLOY_HOOK_URL }}
|
||||
COOLIFY_DEPLOY_TOKEN: ${{ secrets.COOLIFY_DEPLOY_TOKEN }}
|
||||
HOOK_URL: ${{ secrets.COOLIFY_DEPLOY_HOOK_URL_BOT }}
|
||||
HOOK_TOKEN: ${{ secrets.COOLIFY_DEPLOY_TOKEN_BOT }}
|
||||
run: |
|
||||
if [ -z "$COOLIFY_DEPLOY_HOOK_URL" ]; then
|
||||
echo "Missing COOLIFY_DEPLOY_HOOK_URL secret"
|
||||
if [ -z "$HOOK_URL" ]; then
|
||||
echo "Missing COOLIFY_DEPLOY_HOOK_URL_BOT"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ -n "$COOLIFY_DEPLOY_TOKEN" ]; then
|
||||
if [ -n "$HOOK_TOKEN" ]; then
|
||||
curl --fail --show-error --silent \
|
||||
-X POST \
|
||||
-H "Authorization: Bearer $COOLIFY_DEPLOY_TOKEN" \
|
||||
"$COOLIFY_DEPLOY_HOOK_URL"
|
||||
-H "Authorization: Bearer $HOOK_TOKEN" \
|
||||
"$HOOK_URL"
|
||||
else
|
||||
curl --fail --show-error --silent -X POST "$COOLIFY_DEPLOY_HOOK_URL"
|
||||
curl --fail --show-error --silent -X POST "$HOOK_URL"
|
||||
fi
|
||||
|
||||
echo "Coolify deploy triggered"
|
||||
echo "Backend deploy triggered"
|
||||
|
||||
- name: Trigger dashboard deploy
|
||||
env:
|
||||
HOOK_URL: ${{ secrets.COOLIFY_DEPLOY_HOOK_URL_DASHBOARD }}
|
||||
HOOK_TOKEN: ${{ secrets.COOLIFY_DEPLOY_TOKEN_DASHBOARD }}
|
||||
run: |
|
||||
if [ -z "$HOOK_URL" ]; then
|
||||
echo "Missing COOLIFY_DEPLOY_HOOK_URL_DASHBOARD"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ -n "$HOOK_TOKEN" ]; then
|
||||
curl --fail --show-error --silent \
|
||||
-X POST \
|
||||
-H "Authorization: Bearer $HOOK_TOKEN" \
|
||||
"$HOOK_URL"
|
||||
else
|
||||
curl --fail --show-error --silent -X POST "$HOOK_URL"
|
||||
fi
|
||||
|
||||
echo "Dashboard deploy triggered"
|
||||
|
||||
+105
-61
@@ -9,12 +9,17 @@ This document covers production deployment for the `omo-bot` Coolify project wit
|
||||
|
||||
Recommended domains:
|
||||
|
||||
- `api.yourdomain.com` -> `omo-bot-backend`
|
||||
- `admin.yourdomain.com` -> `omo-bot-dashboard`
|
||||
- `api.openmicodyssey.com` -> `omo-bot-backend`
|
||||
- `admin.openmicodyssey.com` -> `omo-bot-dashboard`
|
||||
|
||||
Recommended edge topology:
|
||||
|
||||
- Internet -> Nginx reverse proxy -> Coolify resources
|
||||
- Nginx routes by hostname to backend/dashboard resource domains or internal ports
|
||||
|
||||
Optional same-origin pattern:
|
||||
|
||||
- `admin.yourdomain.com` serves dashboard and reverse-proxies `/admin/*` + `/health` to backend.
|
||||
- `admin.openmicodyssey.com` serves dashboard and reverse-proxies `/admin/*` + `/health` to backend.
|
||||
|
||||
## 1. Create Coolify Project and Resources
|
||||
|
||||
@@ -22,13 +27,80 @@ Optional same-origin pattern:
|
||||
2. Add resource `omo-bot-backend` from this repository:
|
||||
- Build context: repository root
|
||||
- Start command: `npm start`
|
||||
- Port: `8787` (Admin API) if exposed
|
||||
- Internal port: `8787` (Admin API)
|
||||
3. Add resource `omo-bot-dashboard` from this repository:
|
||||
- Base directory: `admin-dashboard`
|
||||
- Build command: `npm run build`
|
||||
- Publish directory: `dist`
|
||||
- Internal port: `80` (typical static web port behind Coolify)
|
||||
4. Configure domains for each resource and enable TLS certificates.
|
||||
|
||||
## 1.1 Nginx Reverse Proxy in Front of Coolify
|
||||
|
||||
Use this pattern when you want one public edge server in front of Coolify-managed services.
|
||||
|
||||
Recommended flow:
|
||||
|
||||
1. Public DNS for `api.openmicodyssey.com` and `admin.openmicodyssey.com` points to Nginx host.
|
||||
2. Nginx terminates TLS and forwards traffic to Coolify resource domains or private IP:port targets.
|
||||
3. Coolify resources stay private or restricted to internal network where possible.
|
||||
|
||||
Example host-based routing:
|
||||
|
||||
```nginx
|
||||
server {
|
||||
listen 80;
|
||||
server_name api.openmicodyssey.com;
|
||||
return 301 https://$host$request_uri;
|
||||
}
|
||||
|
||||
server {
|
||||
listen 443 ssl http2;
|
||||
server_name api.openmicodyssey.com;
|
||||
|
||||
ssl_certificate /etc/letsencrypt/live/api.openmicodyssey.com/fullchain.pem;
|
||||
ssl_certificate_key /etc/letsencrypt/live/api.openmicodyssey.com/privkey.pem;
|
||||
|
||||
location / {
|
||||
proxy_pass http://coolify-backend.internal:8787;
|
||||
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 https;
|
||||
}
|
||||
}
|
||||
|
||||
server {
|
||||
listen 80;
|
||||
server_name admin.openmicodyssey.com;
|
||||
return 301 https://$host$request_uri;
|
||||
}
|
||||
|
||||
server {
|
||||
listen 443 ssl http2;
|
||||
server_name admin.openmicodyssey.com;
|
||||
|
||||
ssl_certificate /etc/letsencrypt/live/admin.openmicodyssey.com/fullchain.pem;
|
||||
ssl_certificate_key /etc/letsencrypt/live/admin.openmicodyssey.com/privkey.pem;
|
||||
|
||||
location / {
|
||||
proxy_pass http://coolify-dashboard.internal:80;
|
||||
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 https;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
If you prefer same-origin routing for dashboard + API through one public domain, proxy `location /admin/` and `location /health` to backend while keeping `/` on dashboard.
|
||||
|
||||
Recommended OAuth callback route:
|
||||
|
||||
- `https://admin.openmicodyssey.com/oauth/discord/callback`
|
||||
|
||||
If you use this callback path, make sure dashboard hosting serves the SPA entrypoint for that route instead of returning `404`.
|
||||
|
||||
## 2. Configure Runtime Variables
|
||||
|
||||
Backend (`omo-bot-backend`) minimum:
|
||||
@@ -39,14 +111,21 @@ Backend (`omo-bot-backend`) minimum:
|
||||
|
||||
Dashboard (`omo-bot-dashboard`) minimum:
|
||||
|
||||
- `VITE_ADMIN_API_BASE_URL` (for split-domain deployment, set to `https://api.yourdomain.com`)
|
||||
- `VITE_ADMIN_API_BASE_URL` (for split-domain deployment, set to `https://api.openmicodyssey.com`)
|
||||
- `VITE_DISCORD_CLIENT_ID`
|
||||
- `VITE_DISCORD_REDIRECT_URI` (must match Discord OAuth2 redirect list)
|
||||
- `VITE_DISCORD_REDIRECT_URI` (recommended: `https://admin.openmicodyssey.com/oauth/discord/callback`)
|
||||
|
||||
OAuth alignment:
|
||||
|
||||
- Discord Developer Portal redirect URI must match dashboard redirect domain.
|
||||
- Config DB key `OAUTH_BRIDGE_REDIRECT_URI` must match the same URI.
|
||||
- Discord Developer Portal redirect URI must exactly match the dashboard callback URL.
|
||||
- Config DB key `OAUTH_BRIDGE_REDIRECT_URI` must match the same callback URL.
|
||||
- Dashboard env `VITE_DISCORD_REDIRECT_URI` must match the same callback URL.
|
||||
|
||||
Discord OAuth authorize URL shape:
|
||||
|
||||
```text
|
||||
https://discord.com/oauth2/authorize?client_id=YOUR_CLIENT_ID&response_type=code&redirect_uri=https%3A%2F%2Fadmin.openmicodyssey.com%2Foauth%2Fdiscord%2Fcallback&scope=identify%20guilds&prompt=consent
|
||||
```
|
||||
|
||||
## 3. Get Coolify Deployment Hooks and Tokens
|
||||
|
||||
@@ -71,68 +150,33 @@ In Gitea repository settings, add Actions secrets:
|
||||
- `COOLIFY_DEPLOY_HOOK_URL_DASHBOARD`
|
||||
- `COOLIFY_DEPLOY_TOKEN_DASHBOARD` (optional)
|
||||
|
||||
Current workflow in `.gitea/workflows/ci-cd.yml` uses a single pair:
|
||||
Current workflow in `.gitea/workflows/ci-cd.yml` triggers backend and dashboard deploys separately using these four secrets.
|
||||
|
||||
- `COOLIFY_DEPLOY_HOOK_URL`
|
||||
- `COOLIFY_DEPLOY_TOKEN`
|
||||
## 5. Domain and DNS Checklist
|
||||
|
||||
If you use separate resources with separate hooks, update workflow deploy step to call both hooks.
|
||||
1. Create DNS records to Nginx edge host (or directly to Coolify if no edge proxy):
|
||||
|
||||
## 5. Example Deploy Step for Two Coolify Resources
|
||||
- `A` record for root/subdomain targets
|
||||
- `CNAME` where appropriate
|
||||
|
||||
```yaml
|
||||
deploy-coolify:
|
||||
name: Deploy to Coolify
|
||||
runs-on: ubuntu-latest
|
||||
needs:
|
||||
- bot-checks
|
||||
- dashboard-checks
|
||||
if: ${{ github.event_name == 'push' && github.ref == 'refs/heads/main' }}
|
||||
steps:
|
||||
- name: Trigger backend deploy
|
||||
env:
|
||||
HOOK_URL: ${{ secrets.COOLIFY_DEPLOY_HOOK_URL_BOT }}
|
||||
HOOK_TOKEN: ${{ secrets.COOLIFY_DEPLOY_TOKEN_BOT }}
|
||||
run: |
|
||||
if [ -z "$HOOK_URL" ]; then
|
||||
echo "Missing COOLIFY_DEPLOY_HOOK_URL_BOT"
|
||||
exit 1
|
||||
fi
|
||||
if [ -n "$HOOK_TOKEN" ]; then
|
||||
curl --fail --show-error --silent -X POST -H "Authorization: Bearer $HOOK_TOKEN" "$HOOK_URL"
|
||||
else
|
||||
curl --fail --show-error --silent -X POST "$HOOK_URL"
|
||||
fi
|
||||
2. Verify certificates issued on Nginx or Coolify, depending on TLS termination point.
|
||||
3. Verify Nginx upstreams match deployed ports:
|
||||
|
||||
- name: Trigger dashboard deploy
|
||||
env:
|
||||
HOOK_URL: ${{ secrets.COOLIFY_DEPLOY_HOOK_URL_DASHBOARD }}
|
||||
HOOK_TOKEN: ${{ secrets.COOLIFY_DEPLOY_TOKEN_DASHBOARD }}
|
||||
run: |
|
||||
if [ -z "$HOOK_URL" ]; then
|
||||
echo "Missing COOLIFY_DEPLOY_HOOK_URL_DASHBOARD"
|
||||
exit 1
|
||||
fi
|
||||
if [ -n "$HOOK_TOKEN" ]; then
|
||||
curl --fail --show-error --silent -X POST -H "Authorization: Bearer $HOOK_TOKEN" "$HOOK_URL"
|
||||
else
|
||||
curl --fail --show-error --silent -X POST "$HOOK_URL"
|
||||
fi
|
||||
```
|
||||
- backend -> `8787`
|
||||
- dashboard -> `80`
|
||||
|
||||
## 6. Domain and DNS Checklist
|
||||
4. Verify OAuth callback route resolves through dashboard hosting:
|
||||
|
||||
1. Create DNS records to Coolify host:
|
||||
- `A` record for root/subdomain targets
|
||||
- `CNAME` where appropriate
|
||||
2. Verify certificates issued for both domains.
|
||||
3. Verify dashboard can call API at configured `VITE_ADMIN_API_BASE_URL`.
|
||||
4. Verify API health endpoint over TLS:
|
||||
- `GET https://api.yourdomain.com/health`
|
||||
- `https://admin.openmicodyssey.com/oauth/discord/callback`
|
||||
|
||||
## 7. Post-Deploy Verification
|
||||
5. Verify dashboard can call API at configured `VITE_ADMIN_API_BASE_URL`.
|
||||
6. Verify API health endpoint over TLS:
|
||||
- `GET https://api.openmicodyssey.com/health`
|
||||
|
||||
## 6. Post-Deploy Verification
|
||||
|
||||
1. `npm run register:commands` (if bot app/guild IDs changed).
|
||||
2. Confirm bot online in Discord and slash commands visible.
|
||||
3. Open dashboard URL and run OAuth login flow.
|
||||
4. Validate Admin API auth behavior with and without bearer token.
|
||||
4. Confirm Discord redirects back to `https://admin.openmicodyssey.com/oauth/discord/callback` without `404`.
|
||||
5. Validate Admin API auth behavior with and without bearer token.
|
||||
|
||||
@@ -92,6 +92,7 @@ This project uses the arc42 template. Chapters are in `docs/`.
|
||||
3. Copy these values for runtime config (`bot_settings`):
|
||||
- `DISCORD_TOKEN` from Bot tab (Reset Token if needed)
|
||||
- `DISCORD_CLIENT_ID` from OAuth2 > General
|
||||
- `OAUTH_BRIDGE_REDIRECT_URI` as exact callback URL, recommended: `https://admin.openmicodyssey.com/oauth/discord/callback`
|
||||
4. In `Bot` > `Privileged Gateway Intents`, enable only:
|
||||
- `Server Members Intent` (required by current code)
|
||||
5. Keep these disabled unless code changes require them:
|
||||
@@ -171,6 +172,16 @@ npm run dev
|
||||
|
||||
Dashboard environment template: `admin-dashboard/.env.example`.
|
||||
|
||||
Recommended production OAuth callback URL:
|
||||
|
||||
- `https://admin.openmicodyssey.com/oauth/discord/callback`
|
||||
|
||||
This same URL must match:
|
||||
|
||||
- Discord OAuth2 redirect whitelist
|
||||
- `VITE_DISCORD_REDIRECT_URI`
|
||||
- `OAUTH_BRIDGE_REDIRECT_URI`
|
||||
|
||||
### Validation Commands
|
||||
|
||||
```bash
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
VITE_ADMIN_API_BASE_URL=http://localhost:8787
|
||||
VITE_DISCORD_CLIENT_ID=
|
||||
# Must match Discord OAuth2 redirect URI whitelist.
|
||||
VITE_DISCORD_REDIRECT_URI=http://localhost:5173
|
||||
# Must exactly match Discord OAuth2 redirect URI whitelist and OAUTH_BRIDGE_REDIRECT_URI.
|
||||
# Recommended production route: https://admin.openmicodyssey.com/oauth/discord/callback
|
||||
VITE_DISCORD_REDIRECT_URI=http://localhost:5173/oauth/discord/callback
|
||||
|
||||
+29
-15
@@ -3,15 +3,13 @@
|
||||
## Infrastructure Overview
|
||||
|
||||
```txt
|
||||
┌──────────────┐ HTTPS/WSS ┌───────────────────────────────────┐
|
||||
│ Discord APIs │◄───────────────────►│ Coolify deployment │
|
||||
└──────────────┘ │ ┌───────────────────────────────┐ │
|
||||
│ │ Backend container │ │
|
||||
│ │ - Discord gateway runtime │ │
|
||||
│ │ - Admin API (Express) │ │
|
||||
│ │ - Dailies pollers │ │
|
||||
│ └──────────────┬────────────────┘ │
|
||||
└─────────────────│──────────────────┘
|
||||
┌──────────────┐ HTTPS/WSS ┌──────────────────────────────┐
|
||||
│ Discord APIs │◄───────────────────►│ Coolify backend resource │
|
||||
└──────────────┘ │ port 8787 │
|
||||
│ - Discord gateway runtime │
|
||||
│ - Admin API (Express) │
|
||||
│ - Dailies pollers │
|
||||
└──────────────┬───────────────┘
|
||||
│
|
||||
▼
|
||||
┌───────────────────┐
|
||||
@@ -19,10 +17,23 @@
|
||||
│ mileage + config │
|
||||
└───────────────────┘
|
||||
|
||||
┌──────────────────────────┐ HTTPS ┌─────────────────────────────┐
|
||||
│ Admin Dashboard (SPA) │◄───────────►│ Admin API + OAuth bridge │
|
||||
│ React/Vite static deploy │ │ │
|
||||
└──────────────────────────┘ └─────────────────────────────┘
|
||||
Internet
|
||||
│
|
||||
▼
|
||||
┌──────────────────────────┐
|
||||
│ Nginx edge reverse proxy │
|
||||
│ - TLS termination │
|
||||
│ - Host/path routing │
|
||||
└─────────────┬────────────┘
|
||||
│
|
||||
┌────────┴───────────┐
|
||||
▼ ▼
|
||||
┌───────────────┐ ┌──────────────────────────┐
|
||||
│ Coolify │ │ Coolify dashboard │
|
||||
│ backend │ │ resource │
|
||||
│ port 8787 │ │ port 80 │
|
||||
└───────────────┘ │ React/Vite static deploy │
|
||||
└──────────────────────────┘
|
||||
```
|
||||
|
||||
## CI/CD Pipeline
|
||||
@@ -32,14 +43,15 @@ Source file: `.gitea/workflows/ci-cd.yml`
|
||||
1. Bot job: install dependencies, run lint, build, and test.
|
||||
2. Dashboard job: install dependencies in `admin-dashboard`, run lint/build.
|
||||
3. Deploy job: on `main`, trigger Coolify webhook (optionally authenticated with token).
|
||||
4. In two-resource production setup, deploy webhooks can independently trigger backend and dashboard resources.
|
||||
|
||||
## Environment Matrix
|
||||
|
||||
| Environment | Runtime | Database | Notes |
|
||||
| ----------------- | --------------------------------- | -------------------------------------- | ------------------------------------------- |
|
||||
| ----------------- | ------------------------------------------------ | -------------------------------------- | ---------------------------------------------------------------------------- |
|
||||
| Local development | Node.js process via `npm run dev` | Local/Postgres dev instance | Fast iteration, manual command registration |
|
||||
| CI | Ephemeral runner | Test/dev DB or mocked integration path | Quality gates before deployment |
|
||||
| Production | Coolify-managed container(s) | Managed PostgreSQL | Webhook-triggered deployment from Gitea |
|
||||
| Production | Nginx edge + Coolify backend/dashboard resources | Managed PostgreSQL | Host-based routing, TLS termination, webhook-triggered deployment from Gitea |
|
||||
|
||||
## Deployment Risks and Mitigations
|
||||
|
||||
@@ -47,3 +59,5 @@ Source file: `.gitea/workflows/ci-cd.yml`
|
||||
Mitigation: dashboard re-auth flow and short-lived session design.
|
||||
- Risk: DB connectivity interruptions.
|
||||
Mitigation: startup validation + retry behavior on mileage writes.
|
||||
- Risk: edge proxy misroutes dashboard/API traffic.
|
||||
Mitigation: verify upstream hostnames/ports and health checks after deploy.
|
||||
|
||||
Reference in New Issue
Block a user