MicProtocol / docs /deploy-all-services.md
Benaah's picture
Upload folder using huggingface_hub
b17baae verified
|
Raw History Blame Contribute Delete
17.9 kB
# MicProtocol – Full Deployment Guide (All Services)
This guide covers deploying the complete MicProtocol stack β€” core platform, real-time engine, and all self-hosted integrations β€” on a single server using Docker Compose.
## Prerequisites
| Requirement | Minimum | Recommended |
|---|---|---|
| OS | Ubuntu 22.04 / Debian 12 | Ubuntu 24.04 LTS |
| CPU | 8 cores | 16+ cores |
| RAM | 16 GB | 32+ GB |
| Disk | 80 GB SSD | 200+ GB NVMe |
| Docker | 24.0+ | 27+ |
| Docker Compose | v2.20+ | v2.29+ |
| Domain | 1 root domain | Wildcard DNS (`*.yourdomain.com`) |
## Architecture Overview
```
Caddy (TLS + Reverse Proxy)
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ *.yourdomain.com β†’ :3000 β”‚
β”‚ api.* β†’ :4000 β”‚
β”‚ realtime.* β†’ :4001 (WS) β”‚
β”‚ admin.* β†’ :3006 β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
β”‚
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ β”‚ β”‚
β”Œβ”€β”€β”€β”€β–Όβ”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”
β”‚ Web β”‚ β”‚ API β”‚ β”‚ Admin β”‚
β”‚ :3000 │────▢│ :4000 │◀───────│ :3006 β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
β”‚
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ β”‚ β”‚
β”Œβ”€β”€β”€β”€β–Όβ”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β–Όβ”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”
β”‚ Postgres β”‚ β”‚ Redis β”‚ β”‚ Meilisearchβ”‚
β”‚ :5432 β”‚ β”‚ :6379 β”‚ β”‚ :7700 β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
β”‚
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ β”‚ β”‚ β”‚ β”‚ β”‚
β”Œβ”€β”€β”€β–Όβ”€β”€β”€β” β”Œβ”€β”€β–Όβ”€β”€β” β”Œβ”€β”€β”€β”€β–Όβ”€β”€β”€β” β”Œβ”€β”€β–Όβ”€β”€β” β”Œβ”€β”€β–Όβ”€β”€β” β”Œβ”€β”€β–Όβ”€β”€β”
β”‚Cal.comβ”‚ β”‚Chat-β”‚ β”‚Form- β”‚ β”‚Docu-β”‚ β”‚List-β”‚ β”‚Umamiβ”‚
β”‚ :3002 β”‚ β”‚woot β”‚ β”‚bricks β”‚ β”‚mensoβ”‚ β”‚monk β”‚ β”‚:3003β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚:3005β”‚ β”‚ :3001 β”‚ β”‚:3004β”‚ β”‚:9000β”‚ β””β”€β”€β”€β”€β”€β”˜
β””β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”˜
```
## Step 1: Generate Secrets
Run the secrets generator to produce strong random values for every service:
```bash
cd /path/to/MicProtocol
bash scripts/generate-secrets.sh > .env.secrets
```
Review the output, then merge it into your `.env` file. **Never commit `.env` to git.**
## Step 2: Configure Environment
Copy the example and fill in your values:
```bash
cp .env.example .env
```
### Required Variables
At minimum, set these before the first boot:
| Variable | Where to get it |
|---|---|
| `POSTGRES_PASSWORD` | Generated by `generate-secrets.sh` |
| `REDIS_PASSWORD` | Generated by `generate-secrets.sh` |
| `COOKIE_SECRET` | Generated by `generate-secrets.sh` |
| `CLERK_SECRET_KEY` | Clerk Dashboard β†’ API Keys |
| `NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY` | Clerk Dashboard β†’ API Keys |
| `WEB_URL` | Your public web app URL (e.g. `https://yourdomain.com`) |
| `API_URL` | Your public API URL (e.g. `https://api.yourdomain.com`) |
| `RESEND_API_KEY` | Resend Dashboard (or your SMTP relay) |
| `R2_ACCESS_KEY_ID` | Cloudflare R2 dashboard |
| `R2_SECRET_ACCESS_KEY` | Cloudflare R2 dashboard |
| `R2_ENDPOINT` | Cloudflare R2 endpoint |
| `R2_BUCKET` | R2 bucket name |
### Self-Hosted Integration Variables
Each integration needs its own secrets (all generated by `generate-secrets.sh`):
| Integration | Key Variables |
|---|---|
| **Cal.com** | `CALCOM_NEXTAUTH_SECRET`, `CALCOM_ENCRYPTION_KEY`, `CALCOM_WEBHOOK_SECRET`, `CALCOM_API_KEY` |
| **Chatwoot** | `CHATWOOT_SECRET_KEY_BASE`, `CHATWOOT_WEBHOOK_SECRET`, `CHATWOOT_API_KEY` |
| **Formbricks** | `FORMBRICKS_NEXTAUTH_SECRET`, `FORMBRICKS_ENCRYPTION_KEY`, `FORMBRICKS_CRON_SECRET`, `FORMBRICKS_HUB_API_KEY`, `FORMBRICKS_CUBE_API_SECRET`, `FORMBRICKS_WEBHOOK_SECRET` |
| **Documenso** | `DOCUMENSO_NEXTAUTH_SECRET`, `DOCUMENSO_ENCRYPTION_KEY`, `DOCUMENSO_ENCRYPTION_SECONDARY_KEY`, `DOCUMENSO_SIGNING_PASSPHRASE` |
| **Listmonk** | `LISTMONK_ADMIN_PASSWORD`, `LISTMONK_API_TOKEN`, `LISTMONK_WEBHOOK_SECRET` |
| **Umami** | `UMAMI_APP_SECRET` |
| **LiveKit** | `LIVEKIT_API_KEY`, `LIVEKIT_API_SECRET` |
| **mic-realtime** | `MIC_REALTIME_INTERNAL_TOKEN`, `MIC_REALTIME_SHARED_SECRET`, `MIC_REALTIME_PUBLIC_URL` |
### Production URLs
Replace all `http://localhost:*` URLs with your actual domain:
```bash
# Public-facing
WEB_URL=https://yourdomain.com
API_URL=https://api.yourdomain.com
NEXT_PUBLIC_API_URL=https://api.yourdomain.com
# Self-hosted integration public URLs
CALCOM_URL=https://cal.yourdomain.com
CHATWOOT_URL=https://support.yourdomain.com
DOCUMENSO_URL=https://sign.yourdomain.com
FORMBRICKS_URL=https://surveys.yourdomain.com
LISTMONK_URL=https://mail.yourdomain.com
NEXT_PUBLIC_UMAMI_URL=https://analytics.yourdomain.com
# Real-time (MUST be wss:// in production)
MIC_REALTIME_PUBLIC_URL=wss://realtime.yourdomain.com
NEXT_PUBLIC_MIC_REALTIME_URL=wss://realtime.yourdomain.com
```
## Step 3: Configure DNS
For wildcard TLS to work, you need a DNS-01 challenge. Add these DNS records:
| Record | Type | Value |
|---|---|---|
| `@` | A | Your server IP |
| `*` | A | Your server IP |
Or use CNAME records if your DNS provider supports wildcard CNAMEs.
## Step 4: Generate Documenso Signing Certificate
Documenso requires a PKCS#12 signing certificate:
```bash
mkdir -p scripts/documenso-cert
# Generate self-signed cert (replace with your details)
openssl req -x509 -newkey rsa:4096 -keyout key.pem -out cert.pem -days 3650 -nodes \
-subj "/CN=Documenso Signing/O=MicProtocol"
# Convert to PKCS#12
openssl pkcs12 -export -out cert.p12 -inkey key.pem -in cert.pem \
-passout pass:${DOCUMENSO_SIGNING_PASSPHRASE}
# Move to the expected location
mv cert.p12 scripts/documenso-cert/
rm -f key.pem cert.pem
```
## Step 5: Start Core Infrastructure
Start the shared infrastructure first β€” these must be healthy before anything else:
```bash
# Start Postgres, Redis, Meilisearch, MinIO
docker compose up -d postgres redis meilisearch minio minio-createbuckets
# Wait for health checks to pass
docker compose ps # All should show "healthy"
```
### Verify Postgres is ready:
```bash
docker exec -it micprotocol-postgres pg_isready -U micprotocol
```
The `init-databases.sql` script runs automatically on first boot, creating databases for: `chatwoot`, `calcom`, `documenso`, `formbricks`, `listmonk`, `umami`.
## Step 6: Start the API and Worker
```bash
docker compose up -d api worker
```
The API will:
1. Run Prisma migrations against the `micprotocol` database
2. Start the NestJS server on `:4000`
3. Expose tRPC, REST, and webhook endpoints
Verify:
```bash
curl -s http://localhost:4000/health
```
## Step 7: Start the Real-Time Engine
```bash
docker compose up -d mic-realtime
```
Verify:
```bash
curl -s http://localhost:4001/healthz
```
**Important:** `MIC_REALTIME_INTERNAL_TOKEN` and `MIC_REALTIME_SHARED_SECRET` must be strong random strings. The service fails closed at startup if they are missing or set to defaults.
## Step 8: Start Web and Admin
```bash
docker compose up -d web admin
```
Verify:
```bash
curl -s -o /dev/null -w "%{http_code}" http://localhost:3000 # Web
curl -s -o /dev/null -w "%{http_code}" http://localhost:3006 # Admin
```
## Step 9: Start Self-Hosted Integrations
Start all integrations (or selectively enable ones you need):
```bash
# Start everything at once
docker compose up -d
# OR start individual services:
docker compose up -d calcom # Scheduling
docker compose up -d chatwoot-web chatwoot-worker # Live chat
docker compose up -d formbricks-migrate formbricks-hub-migrate formbricks formbricks-hub formbricks-cube # Surveys
docker compose up -d documenso # E-signatures
docker compose up -d listmonk # Email marketing
docker compose up -d umami # Analytics
docker compose up -d livekit # WebRTC recording
```
### Integration Startup Order
Some services have dependencies that Docker Compose handles automatically:
```
Postgres (healthy)
β”œβ”€β”€ formbricks-migrate (runs once)
β”‚ └── formbricks-hub-migrate (runs once)
β”‚ └── formbricks-cube (healthy)
β”‚ └── formbricks-hub (healthy)
β”‚ └── formbricks (healthy)
β”œβ”€β”€ calcom (depends on Postgres + Redis)
β”œβ”€β”€ chatwoot-web + chatwoot-worker (depends on Postgres + Redis)
β”œβ”€β”€ documenso (depends on Postgres)
β”œβ”€β”€ listmonk (depends on Postgres)
└── umami (depends on Postgres)
```
## Step 10: Start Dev SMTP (Optional)
For local development, Mailhog captures all outbound email:
```bash
docker compose up -d mailhog
```
- SMTP server: `localhost:1025`
- Web UI: `http://localhost:8025`
In production, replace with your transactional SMTP relay (Resend, SES, Postmark, etc.) by setting `SMTP_HOST`, `SMTP_PORT`, `SMTP_USER`, `SMTP_PASSWORD`.
## Step 11: Start CLIP Scorer (Optional)
The CLIP scoring engine is CPU/GPU intensive. Start it only if you need AI-powered clip scoring:
```bash
docker compose up -d clip-scorer
```
Resource requirements:
- CPU: 2 cores minimum
- Memory: 2 GB minimum
- Optional GPU: Cuts inference time by 5-10x
## Step 12: Configure Caddy (TLS + Reverse Proxy)
The `Caddyfile` handles TLS termination and routing. Set the `ROOT_DOMAIN` and `CLOUDFLARE_API_TOKEN` environment variables:
```bash
export ROOT_DOMAIN=yourdomain.com
export CLOUDFLARE_API_TOKEN=your_cloudflare_api_token
```
Start Caddy:
```bash
docker compose up -d caddy
```
Or install Caddy on the host and run it with the provided `Caddyfile`:
```bash
# Install Caddy
sudo apt install -y caddy
# Copy the Caddyfile
sudo cp Caddyfile /etc/caddy/Caddyfile
# Set environment
export ROOT_DOMAIN=yourdomain.com
export CLOUDFLARE_API_TOKEN=your_token
# Start
sudo systemctl restart caddy
```
### Caddy Routing Table
| Host | Upstream | Protocol |
|---|---|---|
| `yourdomain.com` / `*.yourdomain.com` | web:3000 | HTTPS |
| `api.yourdomain.com` | api:4000 | HTTPS |
| `realtime.yourdomain.com` | mic-realtime:4001 | WSS |
| `admin.yourdomain.com` | admin:3006 | HTTPS |
## Step 13: Run Database Migrations
If this is a fresh deployment, run Prisma migrations:
```bash
docker exec -it micprotocol-api npx prisma migrate deploy
```
Or generate the Prisma client and push the schema:
```bash
docker exec -it micprotocol-api npx prisma generate
docker exec -it micprotocol-api npx prisma db push
```
## Step 14: Post-Deployment Setup
### Cal.com
1. Open `https://cal.yourdomain.com`
2. Create admin account
3. Go to Settings β†’ API Keys β†’ generate a key
4. Set `CALCOM_API_KEY` in `.env`
5. Restart the API: `docker compose restart api`
### Chatwoot
1. Open `https://support.yourdomain.com`
2. Complete the setup wizard
3. Go to Settings β†’ Agents β†’ create an agent
4. Go to Settings β†’ Inboxes β†’ create a website inbox
5. Copy the inbox ID to `CHATWOOT_INBOX_ID`
6. Copy the website token to `NEXT_PUBLIC_CHATWOOT_WEBSITE_TOKEN`
7. Restart the API
### Formbricks
1. Open `https://surveys.yourdomain.com`
2. Create admin account
3. Go to Settings β†’ Environments β†’ copy the environment ID
4. Set `NEXT_PUBLIC_FORMBRICKS_ENVIRONMENT_ID`
5. Go to Settings β†’ API Keys β†’ create a key
6. Set `FORMBRICKS_API_KEY`
7. Restart the API
### Documenso
1. Open `https://sign.yourdomain.com`
2. Create admin account
3. Go to Settings β†’ API β†’ create a key
4. Set `DOCUMENSO_API_KEY`
5. Restart the API
### Listmonk
1. Open `https://mail.yourdomain.com`
2. Log in with `LISTMONK_ADMIN_USER` / `LISTMONK_ADMIN_PASSWORD`
3. Go to Settings β†’ API β†’ generate a token
4. Set `LISTMONK_API_TOKEN`
5. Create a mailing list and copy its UUID to `NEXT_PUBLIC_LISTMONK_LIST_UUID`
6. Configure webhooks: POST to `http://api:4000/integrations/webhooks/listmonk` with header `x-listmonk-secret: <LISTMONK_WEBHOOK_SECRET>`
7. Restart the API
### Umami
1. Open `https://analytics.yourdomain.com`
2. Log in with default credentials (admin/umami)
3. Change the admin password
4. Add a website and copy the website ID to `NEXT_PUBLIC_UMAMI_WEBSITE_ID`
5. Restart the web app
### LiveKit
1. The recording studio connects to LiveKit on port 7880
2. For internet-facing deployments, ensure UDP port 7882 is open
3. If behind a firewall, configure a TURN server or set `rtc.use_external_ip: true`
## Health Checks
Verify all services are running:
```bash
# Core
curl -s http://localhost:4000/health # API
curl -s http://localhost:4001/healthz # mic-realtime
curl -s http://localhost:3000 # Web
curl -s http://localhost:3006 # Admin
# Integrations
curl -s http://localhost:3002/api/health # Cal.com
curl -s http://localhost:3005/health # Chatwoot
curl -s http://localhost:3001/api/health # Formbricks
curl -s http://localhost:3004/api/health # Documenso
curl -s http://localhost:9000/health # Listmonk
curl -s http://localhost:3003/api/health # Umami
curl -s http://localhost:7880/health # LiveKit
# Consolidated check
curl -s http://localhost:4000/integrations/health | jq
```
## Port Reference
| Port | Service | Protocol |
|---|---|---|
| 3000 | Web (Next.js) | HTTP |
| 3001 | Formbricks | HTTP |
| 3002 | Cal.com | HTTP |
| 3003 | Umami | HTTP |
| 3004 | Documenso | HTTP |
| 3005 | Chatwoot | HTTP |
| 3006 | Admin | HTTP |
| 4000 | API (NestJS) | HTTP |
| 4001 | mic-realtime | HTTP/WS |
| 5432 | PostgreSQL | TCP |
| 6379 | Redis | TCP |
| 7700 | Meilisearch | HTTP |
| 7880 | LiveKit | HTTP |
| 7881 | LiveKit | TCP |
| 7882 | LiveKit | UDP |
| 8025 | Mailhog UI | HTTP |
| 9000 | Listmonk | HTTP |
| 9001 | MinIO API | HTTP |
| 9090 | MinIO Console | HTTP |
| 1025 | Mailhog SMTP | TCP |
## Resource Limits
Default limits from `docker-compose.yml`:
| Service | CPUs | Memory |
|---|---|---|
| API | 2 | 2 GB |
| Worker | 1 | 1 GB |
| CLIP Scorer | 2 | 2 GB |
| mic-realtime | 1.5 | 1 GB |
Other services have no explicit limits. Tune based on your hardware.
## Common Operations
### Stop everything
```bash
docker compose down # Keep data
docker compose down -v # Wipe all data (destructive)
```
### Update a single service
```bash
docker compose pull <service>
docker compose up -d --no-deps <service>
```
### Update Formbricks (requires migration re-run)
```bash
docker compose up formbricks-migrate
docker compose up formbricks-hub-migrate
docker compose up -d --no-deps formbricks formbricks-hub formbricks-cube
```
### View logs
```bash
docker compose logs -f api # API logs
docker compose logs -f mic-realtime # Real-time logs
docker compose logs -f chatwoot-web # Chatwoot logs
```
### Restart a service
```bash
docker compose restart api
```
### Enter a container
```bash
docker exec -it micprotocol-api sh
docker exec -it micprotocol-postgres psql -U micprotocol
```
## Troubleshooting
### Service won't start
1. Check logs: `docker compose logs <service>`
2. Verify env vars are set in `.env`
3. Check that dependent services are healthy: `docker compose ps`
### Database connection refused
1. Ensure Postgres is healthy: `docker exec micprotocol-postgres pg_isready`
2. Verify `DATABASE_URL` uses the container hostname (`postgres`), not `localhost`
### Real-time WebSocket not connecting
1. Ensure `MIC_REALTIME_PUBLIC_URL` is a `wss://` URL in production
2. Check that `MIC_REALTIME_INTERNAL_TOKEN` and `MIC_REALTIME_SHARED_SECRET` are set
3. Verify Caddy is routing `realtime.*` correctly
### Formbricks won't start
1. Ensure all 5 Formbricks containers start in order
2. Check that `SKIP_STARTUP_MIGRATION=true` is set on the web container
3. Verify Cube.js is healthy before Formbricks web starts
### Outbound email not working
1. Check `SMTP_HOST`, `SMTP_PORT`, `SMTP_USER`, `SMTP_PASSWORD` in `.env`
2. In dev, ensure Mailhog is running: `docker compose up -d mailhog`
3. Check Mailhog UI at `http://localhost:8025`
## Disabling Services
Any integration can be removed by deleting its block from `docker-compose.yml` and omitting its env vars from `.env`. The API degrades gracefully β€” missing integrations return `false` from health checks and log warnings rather than crashing.
## Security Checklist
- [ ] All default passwords changed
- [ ] `.env` not committed to git
- [ ] Firewall configured (only ports 80, 443, and SSH open)
- [ ] TLS working via Caddy
- [ ] `MIC_REALTIME_INTERNAL_TOKEN` and `MIC_REALTIME_SHARED_SECRET` are strong random values
- [ ] Encryption keys (`*_ENCRYPTION_KEY`) generated and backed up (never rotate after first use)
- [ ] Webhook secrets configured on both sides
- [ ] SMTP relay configured (not Mailhog) in production
- [ ] `DEV_AUTH_BYPASS_ENABLED=false` in production