vibecircle dev

VibeCircle Deployment Runbook

Reference for managing the VibeCircle production infrastructure.

Overview

VibeCircle is a Next.js 16 app. The frontend is deployed on Vercel. All backend services (PostgreSQL, PgBouncer, Redis, Soketi, MinIO) are self-hosted on Proxmox VMs and managed through Coolify (self-hosted PaaS).

Architecture

Internet → Cloudflare (SSL, Full mode)
    → 59.127.230.236 (cht.infra.esgltc.com)
    → Cisco Router NAT (ports 80/443)
    → 10.25.11.10 (nginx reverse proxy, Certbot SSL)
    ├── 10.25.13.11 (backend: Coolify, Postgres, Redis, Soketi, PgBouncer)
    └── 10.25.13.12 (storage: MinIO, 20TB)

Domains

| Domain | Purpose | Route | |---|---|---| | pg-me.know.tw | VibeCircle production | Cloudflare → nginx → backend services | | pg-coolify.know.tw | Coolify management UI | Cloudflare → nginx → Coolify (port 8000) |

Repo

  • GitHub: github.com/know-book/vibeCircle
  • Branch: main
  • GitHub App: knowbook-github connected to Coolify

Machine Inventory

10.25.11.10 — Nginx Reverse Proxy

  • Role: SSL termination + reverse proxy
  • User: max
  • Nginx sites (/etc/nginx/sites-enabled/):
    • vibecirclepg-me.know.tw:
      • /10.25.13.11:80 (Traefik → app)
      • /ws/10.25.13.11:7001 (Soketi WebSocket)
      • /storage/10.25.13.12:9000 (MinIO S3 API)
      • /minio-console/10.25.13.12:9001 (MinIO Console)
    • coolifypg-coolify.know.tw:
      • /10.25.13.11:8000 (Coolify UI)
      • /app/10.25.13.11:6001 (Coolify realtime WebSocket)
  • SSL: Certbot with Let's Encrypt, cert at /etc/letsencrypt/live/pg-coolify.know.tw/ (covers both domains), auto-renews

10.25.13.11 — Backend VM (Coolify Host)

  • Specs: 20 cores, 20GB RAM, 58GB disk
  • User: max
  • Coolify services (all managed via dashboard):

| Service | Port | Notes | |---|---|---| | PostgreSQL 16 | 5432 | Primary database | | PgBouncer | 6432 (host) → 5432 (container) | Connection pooling, transaction mode | | Redis 7 | 6379 | Cache + Soketi adapter | | Soketi | 7001 (host) → 6001 (container) | WebSocket server (Pusher-compatible) |

  • Coolify infra: port 8000 (UI), 6001/6002 (realtime), 80/443 (Traefik)
  • Note: Soketi mapped to host port 7001 to avoid conflict with Coolify's own realtime service on 6001

10.25.13.12 — Storage VM (Coolify Remote Server)

  • Specs: 8 cores, 16GB RAM, 20TB disk (LVM extended)
  • User: max
  • Coolify-managed MinIO: ports 9000 (S3 API), 9001 (Console)
  • Bucket: vibecircle with public read on /public path

Cloudflare Configuration

  • SSL/TLS mode: Full (origin has Certbot certs on 10.25.11.10)
  • DNS records (proxied):
    • pg-me.know.tw → A → 59.127.230.236
    • pg-coolify.know.tw → A → 59.127.230.236

Use pg- prefix (3rd-level subdomain) because Cloudflare universal SSL doesn't cover 4th-level subdomains like *.me.know.tw.


Coolify Management

Dashboard: https://pg-coolify.know.tw

Servers

| Name | IP | Role | |---|---|---| | localhost | 10.25.13.11 | Backend (Coolify host) | | vibecircle-storage | 10.25.13.12 | Storage (remote) |

Services in Coolify

All backend services are managed as individual Coolify resources under the VibeCircle project, production environment.

To restart a service: Dashboard → Projects → VibeCircle → production → select service → Restart.

GitHub App (CI/CD)

  • GitHub App knowbook-github is connected under Sources
  • Provides webhook access to know-book/vibeCircle

Running Prisma Migrations

From a machine on the Proxmox internal network that can reach Postgres:

# Set the direct connection (not PgBouncer) for migrations
export DIRECT_DATABASE_URL="postgresql://vibecircle:<password>@10.25.13.11:5432/vibecircle"
export DATABASE_URL="postgresql://vibecircle:<password>@10.25.13.11:6432/vibecircle"

pnpm prisma migrate deploy

Or from inside the backend VM:

cd /tmp
git clone https://github.com/know-book/vibeCircle.git
cd vibeCircle
pnpm install --frozen-lockfile
DIRECT_DATABASE_URL="postgresql://vibecircle:<password>@localhost:5432/vibecircle" pnpm prisma migrate deploy
rm -rf /tmp/vibeCircle

Environment Variables (Vercel / Next.js)

All NEXT_PUBLIC_* vars are needed at build time. Service URLs use internal IPs when deployed on Coolify, or public endpoints when on Vercel.

DATABASE_URL=postgresql://vibecircle:<password>@10.25.13.11:6432/vibecircle
DIRECT_DATABASE_URL=postgresql://vibecircle:<password>@10.25.13.11:5432/vibecircle
AUTH_SECRET=<managed in Coolify>
AUTH_URL=https://pg-me.know.tw
MAILGUN_API_KEY=<managed in Coolify>
MAILGUN_DOMAIN=nomie.know.tw
MAILGUN_FROM_EMAIL=knowme@nomie.know.tw
NEXT_PUBLIC_SOKETI_HOST=pg-me.know.tw
NEXT_PUBLIC_SOKETI_PORT=443
NEXT_PUBLIC_SOKETI_APP_KEY=<managed in Coolify>
NEXT_PUBLIC_SOKETI_FORCE_TLS=true
SOKETI_APP_ID=vibecircle
SOKETI_APP_KEY=<managed in Coolify>
SOKETI_APP_SECRET=<managed in Coolify>
MINIO_ENDPOINT=http://10.25.13.12:9000
MINIO_ACCESS_KEY=<managed in Coolify>
MINIO_SECRET_KEY=<managed in Coolify>
MINIO_BUCKET=vibecircle
REDIS_URL=redis://10.25.13.11:6379

Note: If deploying on Vercel, TCP services (Postgres, Redis) are not reachable through Cloudflare. Either NAT the ports on the Cisco router, use a tunnel, or deploy the Next.js app on Coolify instead.


Troubleshooting

Coolify realtime not connecting

  • Coolify's realtime uses port 6001 on the backend VM
  • Nginx at 10.25.11.10 proxies /app/ on pg-coolify.know.tw to port 6001
  • Ensure PUSHER_HOST=pg-coolify.know.tw and PUSHER_PORT=443 are in /data/coolify/source/.env

Build fails at pnpm build

  • Ensure prisma generate runs before next build (add to package.json build script: "build": "prisma generate && next build")
  • Check that all NEXT_PUBLIC_* vars are set in Coolify

Container can't connect to DB

  • All Coolify services share the coolify Docker network
  • PgBouncer must be on the coolify network to reach Postgres by container name
  • Verify: docker exec <container> ping <postgres-container-name>

SSL not working

  • Cloudflare SSL mode must be Full (not Flexible, not Full Strict)
  • Certbot certs on 10.25.11.10 must be valid: sudo certbot certificates
  • Renew manually if needed: sudo certbot renew

Soketi WebSocket not connecting

  • Soketi is on host port 7001 (not 6001, which is Coolify realtime)
  • Nginx proxies /ws/ on pg-me.know.tw to 10.25.13.11:7001
  • Browser connects via wss://pg-me.know.tw/ws/

MinIO not accessible

  • MinIO is on 10.25.13.12 (storage VM), not the backend VM
  • Nginx proxies /storage/ to 10.25.13.12:9000 and /minio-console/ to 10.25.13.12:9001

Credentials

All credentials are managed in Coolify environment variables. Do not store plaintext secrets in this file.

| Secret | Where | |---|---| | Postgres password | Coolify → vibecircle-postgres → Environment | | Soketi keys | Coolify → vibecircle-soketi → Environment (auto-generated) | | MinIO keys | Coolify → vibecircle-minio → Environment | | AUTH_SECRET | Coolify → app environment variables | | Mailgun API key | Coolify → app environment variables |


Deprecated

  • /opt/vibecircle-infra/ on 10.25.13.11 — old docker-compose stack, replaced by Coolify-managed services
  • /opt/minio/ on 10.25.13.12 — old MinIO docker-compose, replaced by Coolify-managed service
  • Domain me.know.tw — replaced by pg-me.know.tw