Spaces:
Running
Running
|
Download docs/deploy-all-services.md from Benaah/MicProtocol: direct link, hf CLI and curl.
- Browser
- Download file 17.9 kB
-
https://huggingface.co/spaces/Benaah/MicProtocol/resolve/main/docs/deploy-all-services.md
- Command line
-
hf download hf://spaces/Benaah/MicProtocol/docs/deploy-all-services.md
-
curl -L -o deploy-all-services.md https://huggingface.co/spaces/Benaah/MicProtocol/resolve/main/docs/deploy-all-services.md
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 | |