chore(deploy): simplify docker-compose and add Forgejo CI/CD
- Remove Convex from docker-compose (runs separately) - Add .forgejo/workflows/ci.yml with auto-deploy to Coolify - Update DEVELOPMENT.md with dev/prod architecture diagram - Rename branch from develop to dev in all workflows
This commit is contained in:
parent
374bba1a93
commit
1c2adc1f1e
4 changed files with 150 additions and 64 deletions
49
.forgejo/workflows/ci.yml
Normal file
49
.forgejo/workflows/ci.yml
Normal file
|
|
@ -0,0 +1,49 @@
|
||||||
|
name: CI
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches: [main, dev]
|
||||||
|
pull_request:
|
||||||
|
branches: [main, dev]
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
lint:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
|
||||||
|
- uses: pnpm/action-setup@v4
|
||||||
|
with:
|
||||||
|
version: 9
|
||||||
|
|
||||||
|
- uses: actions/setup-node@v4
|
||||||
|
with:
|
||||||
|
node-version: 20
|
||||||
|
cache: 'pnpm'
|
||||||
|
|
||||||
|
- name: Install dependencies
|
||||||
|
run: pnpm install --frozen-lockfile
|
||||||
|
|
||||||
|
- name: Lint
|
||||||
|
run: pnpm lint
|
||||||
|
|
||||||
|
- name: Build
|
||||||
|
run: pnpm build
|
||||||
|
|
||||||
|
deploy-dev:
|
||||||
|
if: github.ref == 'refs/heads/dev'
|
||||||
|
needs: lint
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- name: Deploy to Coolify (Dev)
|
||||||
|
run: |
|
||||||
|
curl -X POST "${{ secrets.COOLIFY_DEV_WEBHOOK }}"
|
||||||
|
|
||||||
|
deploy-prod:
|
||||||
|
if: github.ref == 'refs/heads/main'
|
||||||
|
needs: lint
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- name: Deploy to Coolify (Prod)
|
||||||
|
run: |
|
||||||
|
curl -X POST "${{ secrets.COOLIFY_PROD_WEBHOOK }}"
|
||||||
4
.github/workflows/lint.yml
vendored
4
.github/workflows/lint.yml
vendored
|
|
@ -2,9 +2,9 @@ name: CI
|
||||||
|
|
||||||
on:
|
on:
|
||||||
push:
|
push:
|
||||||
branches: [main, develop]
|
branches: [main, dev]
|
||||||
pull_request:
|
pull_request:
|
||||||
branches: [main, develop]
|
branches: [main, dev]
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
lint:
|
lint:
|
||||||
|
|
|
||||||
115
DEVELOPMENT.md
115
DEVELOPMENT.md
|
|
@ -42,11 +42,44 @@ npx convex dev
|
||||||
|
|
||||||
This connects to your self-hosted Convex instance. Ensure CLI version matches your backend image version.
|
This connects to your self-hosted Convex instance. Ensure CLI version matches your backend image version.
|
||||||
|
|
||||||
## Coolify Deployment (Convex Self-Hosted)
|
## Architecture Overview
|
||||||
|
|
||||||
### 1. Deploy Convex Backend
|
```
|
||||||
|
┌─────────────────────────────────────────────────────────────┐
|
||||||
|
│ LOCAL DEV │
|
||||||
|
│ pnpm dev --webpack → npx convex dev → DEV CONVEX DB │
|
||||||
|
└─────────────────────────────────────────────────────────────┘
|
||||||
|
│
|
||||||
|
▼
|
||||||
|
┌─────────────────────────────────────────────────────────────┐
|
||||||
|
│ FORGEJO / GIT │
|
||||||
|
│ main branch ──► PROD DEPLOY │
|
||||||
|
│ dev branch ──► DEV DEPLOY │
|
||||||
|
└─────────────────────────────────────────────────────────────┘
|
||||||
|
│
|
||||||
|
┌───────────────┴───────────────┐
|
||||||
|
▼ ▼
|
||||||
|
┌─────────────────────────────┐ ┌─────────────────────────────┐
|
||||||
|
│ COOLIFY (PROD) │ │ COOLIFY (DEV) │
|
||||||
|
│ Next.js Docker Container │ │ Next.js Docker Container │
|
||||||
|
│ (frontend) │ │ (frontend) │
|
||||||
|
└─────────────────────────────┘ └─────────────────────────────┘
|
||||||
|
│ │
|
||||||
|
▼ ▼
|
||||||
|
┌─────────────────────────────┐ ┌─────────────────────────────┐
|
||||||
|
│ CONVEX (PROD DB) │ │ CONVEX (DEV DB) │
|
||||||
|
│ Self-hosted on Coolify │ │ Self-hosted on Coolify │
|
||||||
|
│ or Convex Cloud │ │ or Convex Cloud │
|
||||||
|
└─────────────────────────────┘ └─────────────────────────────┘
|
||||||
|
```
|
||||||
|
|
||||||
On Coolify, create a new service using this docker-compose:
|
### Convex Backend
|
||||||
|
|
||||||
|
Convex runs **separately** from the Next.js frontend. You need two instances:
|
||||||
|
- **Dev**: for local development + dev environment testing
|
||||||
|
- **Prod**: for production
|
||||||
|
|
||||||
|
On Coolify, create a new service for each Convex backend using the official docker-compose:
|
||||||
|
|
||||||
```yaml
|
```yaml
|
||||||
services:
|
services:
|
||||||
|
|
@ -66,7 +99,6 @@ services:
|
||||||
CONVEX_SITE_ORIGIN: '${SERVICE_URL_BACKEND_SITE}'
|
CONVEX_SITE_ORIGIN: '${SERVICE_URL_BACKEND_SITE}'
|
||||||
DO_NOT_REQUIRE_SSL: '${DO_NOT_REQUIRE_SSL:-true}'
|
DO_NOT_REQUIRE_SSL: '${DO_NOT_REQUIRE_SSL:-true}'
|
||||||
DATABASE_URL: '${DATABASE_URL:-}'
|
DATABASE_URL: '${DATABASE_URL:-}'
|
||||||
# ... (see README.md for full config)
|
|
||||||
healthcheck:
|
healthcheck:
|
||||||
test: ['CMD-SHELL', 'curl -f http://localhost:3210/version']
|
test: ['CMD-SHELL', 'curl -f http://localhost:3210/version']
|
||||||
interval: 5s
|
interval: 5s
|
||||||
|
|
@ -91,7 +123,7 @@ volumes:
|
||||||
|
|
||||||
> **Best practice**: Copy the [official self-hosted config](https://github.com/get-convex/convex-backend/blob/main/self-hosted/docker/docker-compose.yml) and adapt env vars for Coolify.
|
> **Best practice**: Copy the [official self-hosted config](https://github.com/get-convex/convex-backend/blob/main/self-hosted/docker/docker-compose.yml) and adapt env vars for Coolify.
|
||||||
|
|
||||||
### 2. Generate Admin Key
|
### Generate Admin Key
|
||||||
|
|
||||||
SSH into the server and run:
|
SSH into the server and run:
|
||||||
|
|
||||||
|
|
@ -291,11 +323,11 @@ docker run -p 3000:3000 --env-file .env.local my-app
|
||||||
|
|
||||||
### Docker Compose
|
### Docker Compose
|
||||||
|
|
||||||
Full-stack deployment with Convex backend:
|
Frontend-only deployment:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
# Start everything (Next.js + Convex backend + Convex dashboard)
|
# Build and start Next.js app
|
||||||
docker compose up
|
docker compose up --build
|
||||||
```
|
```
|
||||||
|
|
||||||
Services:
|
Services:
|
||||||
|
|
@ -303,8 +335,8 @@ Services:
|
||||||
| Service | Port | Description |
|
| Service | Port | Description |
|
||||||
|---------|------|-------------|
|
|---------|------|-------------|
|
||||||
| `app` | 3000 | Next.js application |
|
| `app` | 3000 | Next.js application |
|
||||||
| `backend` | 3210 | Convex backend API |
|
|
||||||
| `dashboard` | 6791 | Convex admin dashboard |
|
> **Note**: Convex backend runs separately. See [Coolify Deployment](#coolify-deployment) for Convex setup.
|
||||||
|
|
||||||
### Server Components in Docker
|
### Server Components in Docker
|
||||||
|
|
||||||
|
|
@ -339,17 +371,66 @@ CONVEX_SELF_HOSTED_ADMIN_KEY=your-admin-key
|
||||||
|
|
||||||
### Coolify Deployment
|
### Coolify Deployment
|
||||||
|
|
||||||
1. Push code to your Forgejo repo
|
#### 1. Setup Two Environments
|
||||||
2. In Coolify, create a new service from your repo
|
|
||||||
3. Select `docker-compose.yml` as the deployment method
|
|
||||||
4. Set environment variables in Coolify UI
|
|
||||||
5. Deploy
|
|
||||||
|
|
||||||
> **Note**: The `app` service depends on `backend` (Convex). Make sure your Convex backend is accessible from the Coolify server.
|
Create two services in Coolify:
|
||||||
|
|
||||||
|
| Service | Branch | Convex DB | Domain |
|
||||||
|
|---------|--------|-----------|--------|
|
||||||
|
| `my-app-prod` | `main` | Prod | `app.example.com` |
|
||||||
|
| `my-app-dev` | `dev` | Dev | `dev-app.example.com` |
|
||||||
|
|
||||||
|
#### 2. Configure Webhooks (Auto-Deploy)
|
||||||
|
|
||||||
|
In each Coolify service, copy the **Deploy Webhook URL** and add it to Forgejo Secrets:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Forgejo → Repo Settings → Secrets
|
||||||
|
COOLIFY_PROD_WEBHOOK=https://coolify.example.com/webhooks/...
|
||||||
|
COOLIFY_DEV_WEBHOOK=https://coolify.example.com/webhooks/...
|
||||||
|
```
|
||||||
|
|
||||||
|
The `.forgejo/workflows/ci.yml` automatically triggers deploy on push:
|
||||||
|
- `main` branch → Prod webhook
|
||||||
|
- `dev` branch → Dev webhook
|
||||||
|
|
||||||
|
#### 3. Set Environment Variables
|
||||||
|
|
||||||
|
In each Coolify service, set env vars:
|
||||||
|
|
||||||
|
**Prod**:
|
||||||
|
```bash
|
||||||
|
NEXT_PUBLIC_SITE_URL=https://app.example.com
|
||||||
|
NEXT_PUBLIC_CONVEX_URL=https://convex-prod.example.com
|
||||||
|
NEXT_PUBLIC_CONVEX_SITE_URL=https://convex-site-prod.example.com
|
||||||
|
CONVEX_SELF_HOSTED_URL=https://convex-prod.example.com
|
||||||
|
CONVEX_SELF_HOSTED_ADMIN_KEY=prod-admin-key
|
||||||
|
```
|
||||||
|
|
||||||
|
**Dev**:
|
||||||
|
```bash
|
||||||
|
NEXT_PUBLIC_SITE_URL=https://dev-app.example.com
|
||||||
|
NEXT_PUBLIC_CONVEX_URL=https://convex-dev.example.com
|
||||||
|
NEXT_PUBLIC_CONVEX_SITE_URL=https://convex-site-dev.example.com
|
||||||
|
CONVEX_SELF_HOSTED_URL=https://convex-dev.example.com
|
||||||
|
CONVEX_SELF_HOSTED_ADMIN_KEY=dev-admin-key
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 4. Local Development Connects to Dev
|
||||||
|
|
||||||
|
Your `.env.local` should point to the **dev** Convex:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
CONVEX_SELF_HOSTED_URL='https://convex-dev.example.com'
|
||||||
|
CONVEX_SELF_HOSTED_ADMIN_KEY='dev-admin-key'
|
||||||
|
NEXT_PUBLIC_SITE_URL=http://localhost:3000
|
||||||
|
NEXT_PUBLIC_CONVEX_URL=https://convex-dev.example.com
|
||||||
|
NEXT_PUBLIC_CONVEX_SITE_URL=https://convex-site-dev.example.com
|
||||||
|
```
|
||||||
|
|
||||||
### Health Check
|
### Health Check
|
||||||
|
|
||||||
The Next.js app exposes a health endpoint at `/api/health` (add if needed) or you can check if the app is running:
|
Verify the app is running:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
curl http://localhost:3000
|
curl http://localhost:3000
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,4 @@
|
||||||
services:
|
services:
|
||||||
# Next.js Application
|
|
||||||
app:
|
app:
|
||||||
build:
|
build:
|
||||||
context: .
|
context: .
|
||||||
|
|
@ -7,52 +6,9 @@ services:
|
||||||
ports:
|
ports:
|
||||||
- '${PORT:-3000}:3000'
|
- '${PORT:-3000}:3000'
|
||||||
environment:
|
environment:
|
||||||
NODE_ENV: production
|
NODE_ENV: '${NODE_ENV:-production}'
|
||||||
NEXT_PUBLIC_SITE_URL: '${NEXT_PUBLIC_SITE_URL}'
|
NEXT_PUBLIC_SITE_URL: '${NEXT_PUBLIC_SITE_URL}'
|
||||||
NEXT_PUBLIC_CONVEX_URL: '${NEXT_PUBLIC_CONVEX_URL}'
|
NEXT_PUBLIC_CONVEX_URL: '${NEXT_PUBLIC_CONVEX_URL}'
|
||||||
NEXT_PUBLIC_CONVEX_SITE_URL: '${NEXT_PUBLIC_CONVEX_SITE_URL}'
|
NEXT_PUBLIC_CONVEX_SITE_URL: '${NEXT_PUBLIC_CONVEX_SITE_URL}'
|
||||||
CONVEX_SELF_HOSTED_URL: '${CONVEX_SELF_HOSTED_URL}'
|
CONVEX_SELF_HOSTED_URL: '${CONVEX_SELF_HOSTED_URL}'
|
||||||
CONVEX_SELF_HOSTED_ADMIN_KEY: '${CONVEX_SELF_HOSTED_ADMIN_KEY}'
|
CONVEX_SELF_HOSTED_ADMIN_KEY: '${CONVEX_SELF_HOSTED_ADMIN_KEY}'
|
||||||
depends_on:
|
|
||||||
- backend
|
|
||||||
|
|
||||||
# Convex Backend
|
|
||||||
backend:
|
|
||||||
image: 'ghcr.io/get-convex/convex-backend:latest'
|
|
||||||
stop_grace_period: 10s
|
|
||||||
stop_signal: SIGINT
|
|
||||||
ports:
|
|
||||||
- '${PORT:-3210}:3210'
|
|
||||||
- '${SITE_PROXY_PORT:-3211}:3211'
|
|
||||||
volumes:
|
|
||||||
- 'data:/convex/data'
|
|
||||||
environment:
|
|
||||||
INSTANCE_NAME: '${INSTANCE_NAME}'
|
|
||||||
INSTANCE_SECRET: '${INSTANCE_SECRET}'
|
|
||||||
CONVEX_CLOUD_ORIGIN: '${SERVICE_URL_BACKEND}'
|
|
||||||
CONVEX_SITE_ORIGIN: '${SERVICE_URL_BACKEND_SITE}'
|
|
||||||
DO_NOT_REQUIRE_SSL: '${DO_NOT_REQUIRE_SSL:-true}'
|
|
||||||
DATABASE_URL: '${DATABASE_URL:-}'
|
|
||||||
healthcheck:
|
|
||||||
test: ['CMD-SHELL', 'curl -f http://localhost:3210/version']
|
|
||||||
interval: 5s
|
|
||||||
start_period: 10s
|
|
||||||
timeout: 5s
|
|
||||||
retries: 10
|
|
||||||
|
|
||||||
# Convex Dashboard
|
|
||||||
dashboard:
|
|
||||||
image: 'ghcr.io/get-convex/convex-dashboard:latest'
|
|
||||||
stop_grace_period: 10s
|
|
||||||
stop_signal: SIGINT
|
|
||||||
ports:
|
|
||||||
- '${DASHBOARD_PORT:-6791}:6791'
|
|
||||||
environment:
|
|
||||||
PORT: '6791'
|
|
||||||
NEXT_PUBLIC_DEPLOYMENT_URL: '${SERVICE_URL_BACKEND}'
|
|
||||||
depends_on:
|
|
||||||
backend:
|
|
||||||
condition: service_healthy
|
|
||||||
|
|
||||||
volumes:
|
|
||||||
data: null
|
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue