cpns / deploy /COOLIFY.md
pramudya-yb
Rename project from Labas to Pram
2b62b0c
|
Raw
History Blame Contribute Delete
7.66 kB
ο»Ώ# Deploying Pram on Coolify
Pram is a Turborepo monorepo with separate **web** (Vite SPA) and **server** (Hono API) apps. Deploy them as **two Coolify applications** from the same Git repository, plus **PostgreSQL** and **Redis**.
```
User β†’ app.example.com (Web) β†’ api.example.com (Server) β†’ PostgreSQL + Redis
```
## Resources overview
| Coolify resource | Public URL | Purpose |
|------------------|------------|---------|
| Web application | `https://app.example.com` | Frontend (static SPA) |
| Server application | `https://api.example.com` | API, auth, tRPC, job queue |
| PostgreSQL | internal only | Drizzle ORM |
| Redis | internal only | BullMQ AI generation queue |
Both applications use the **repository root** as Base Directory. They differ only in Nixpacks config and environment variables.
---
## 1. PostgreSQL
1. In Coolify, create a **PostgreSQL** database service.
2. Note the **internal hostname**, port, username, and password.
3. Create a database named `pram` (or adjust `DATABASE_URL` accordingly).
4. Keep the service in the same Coolify project/network as the server app.
Example internal connection (hostname varies by Coolify):
```env
DATABASE_URL=postgresql://postgres:YOUR_PASSWORD@YOUR_POSTGRES_HOST:5432/pram
```
---
## 2. Redis
1. Create a **Redis** service in Coolify (or use a managed Redis instance).
2. Note the internal hostname.
```env
REDIS_URL=redis://YOUR_REDIS_HOST:6379
```
Redis is **required** β€” AI question generation uses BullMQ.
---
## 3. Server application (API)
### Coolify settings
| Setting | Value |
|---------|-------|
| Source | Your Git repository |
| Base Directory | `/` (repository root) |
| Build Pack | Nixpacks |
| Nixpacks config | Set env `NIXPACKS_CONFIG_FILE=deploy/server.nixpacks.toml` |
| Port | `3000` |
| Domain | `api.example.com` |
| HTTPS | Enabled (required for auth cookies) |
Equivalent build/start commands if configuring manually in Coolify UI:
```bash
# Install
bun install --frozen-lockfile
# Build
bunx turbo build -F server
# Start
bun run --cwd apps/server start
```
### Environment variables (runtime)
Set these on the **server** application. All are validated at startup in `packages/env/src/server.ts`.
```env
NODE_ENV=production
DATABASE_URL=postgresql://postgres:YOUR_PASSWORD@YOUR_POSTGRES_HOST:5432/pram
REDIS_URL=redis://YOUR_REDIS_HOST:6379
BETTER_AUTH_SECRET=YOUR_RANDOM_SECRET_MIN_32_CHARS
BETTER_AUTH_URL=https://api.example.com
CORS_ORIGIN=https://app.example.com
API_KEY_ENCRYPTION_KEY=YOUR_ENCRYPTION_KEY_MIN_32_CHARS
SMTP_HOST=smtp.example.com
SMTP_PORT=587
SMTP_USER=your-smtp-user
SMTP_PASS=your-smtp-password
SMTP_FROM=Pram <noreply@example.com>
```
Generate secrets:
```bash
openssl rand -base64 32
```
**URL correlation (critical):**
| Variable | Must match |
|----------|------------|
| `BETTER_AUTH_URL` | Public URL of this server app (`https://api.example.com`) |
| `CORS_ORIGIN` | Public URL of the web app (`https://app.example.com`) |
| `VITE_SERVER_URL` (on web app) | Same value as `BETTER_AUTH_URL` |
`CORS_ORIGIN` is also used as Better Auth `trustedOrigins`. Use exact URLs including `https://` and no trailing slash mismatch.
Optional:
```env
PLATFORM_AI_API_KEY=
PLATFORM_AI_BASE_URL=
PLATFORM_AI_MODEL=
FREE_CREDITS_ENABLED=false
```
### Database migrations
Migrations run automatically on container start (see [`deploy/server.nixpacks.toml`](./server.nixpacks.toml)). **Remove any Post-deployment Command** for `db:migrate` β€” it often runs without runtime env vars in Coolify.
**`DATABASE_URL` must be set on the server application** (not on the PostgreSQL resource). The container does not have `apps/server/.env` (gitignored).
1. Open **server application** β†’ **Environment Variables**
2. Add `DATABASE_URL` with **Available at Runtime** enabled (default)
3. Do **not** set it as Build-only
To get the connection string:
1. Open your **PostgreSQL** resource β†’ **Connect** / **Configuration**
2. Copy the **internal** URL (Docker hostname, not `localhost`)
3. Paste into the **server app** env:
```env
DATABASE_URL=postgresql://postgres:YOUR_PASSWORD@YOUR_POSTGRES_HOST:5432/pram
```
Verify in the server app **Terminal**:
```bash
echo $DATABASE_URL
```
If empty, the variable is missing or not marked as runtime β€” fix and redeploy.
Alternative for local-style sync (not recommended in production): `bun run db:push`.
Optional seed (run once via **Terminal** on the server app):
```bash
bun run db:seed
```
### Verify
After deploy, open `https://api.example.com/` β€” it should return `OK`.
---
## 4. Web application (frontend)
### Option A β€” Static Site (recommended)
Lightweight: no long-running Node process.
| Setting | Value |
|---------|-------|
| Resource type | Static Site |
| Base Directory | `/` |
| Build command | `bun install --frozen-lockfile && bunx turbo build -F web` |
| Publish directory | `apps/web/dist` |
| Domain | `app.example.com` |
### Option B β€” Nixpacks application
Use when you need a containerized static server (e.g. SPA fallback via `serve`).
| Setting | Value |
|---------|-------|
| Build Pack | Nixpacks |
| Nixpacks config | `NIXPACKS_CONFIG_FILE=deploy/web.nixpacks.toml` |
| Port | `3001` |
| Domain | `app.example.com` |
Config file: [`deploy/web.nixpacks.toml`](./web.nixpacks.toml)
### Environment variables (build time)
```env
VITE_SERVER_URL=https://api.example.com
```
**Enable "Available at Buildtime"** in Coolify. Vite embeds `VITE_*` variables during `vite build`; runtime env changes have no effect.
Rebuild the web app whenever the API URL changes.
### Verify
1. Open `https://app.example.com` β€” app loads.
2. Sign up / sign in works (requires valid SMTP on server).
3. Client-side routes work on refresh (Static Site on Coolify handles this; Nixpacks uses `serve -s` for SPA fallback).
---
## First deploy checklist
1. [ ] Deploy PostgreSQL and Redis; confirm both are healthy.
2. [ ] Create server app, set all runtime env vars.
3. [ ] Set `DATABASE_URL` on **server app** env (Runtime). Remove Post-deployment migrate command.
4. [ ] Deploy server; confirm `https://api.example.com/` returns `OK`.
5. [ ] Create web app, set `VITE_SERVER_URL` as **buildtime** env.
6. [ ] Deploy web; confirm app loads and API calls reach the server.
7. [ ] Test sign-up (email verification needs SMTP).
8. [ ] Add an AI API key in Settings and test question generation (needs Redis).
---
## Troubleshooting
| Symptom | Likely cause | Fix |
|---------|--------------|-----|
| Migrate fails: `url: ''` / `Please provide required params` | `DATABASE_URL` not set in Coolify env | Add internal Postgres URL to server app Environment Variables, redeploy |
| API calls go to `localhost:3000` | `VITE_SERVER_URL` not set at build time | Rebuild web with buildtime env |
| CORS or auth errors | `CORS_ORIGIN` β‰  web URL | Match exact public web URL on server |
| Server crashes on start | Missing or invalid env (SMTP, secrets) | Check Coolify logs; compare with `apps/server/.env.example` |
| AI generation stuck | Redis unreachable | Verify `REDIS_URL` and network |
| Email sign-up fails | Invalid SMTP credentials | Test SMTP vars independently |
| SPA 404 on page refresh | Missing SPA fallback | Use Coolify Static Site, or Nixpacks with `serve -s` (see `start:prod` in `apps/web`) |
---
## Nixpacks config files
| File | Service |
|------|---------|
| [`deploy/server.nixpacks.toml`](./server.nixpacks.toml) | API server |
| [`deploy/web.nixpacks.toml`](./web.nixpacks.toml) | Web app (Option B) |
Both run `bun install` from the monorepo root so workspace packages (`@pram/*`) resolve correctly.