+40
-81
@@ -1,97 +1,56 @@
|
||||
# KoolTap Production Deployment
|
||||
# Production on Coolify
|
||||
|
||||
## Option A: Docker (recommended)
|
||||
KoolTap is deployed with Coolify's Docker Compose build pack, from `docker-compose.coolify.yml`.
|
||||
|
||||
The production setup uses PostgreSQL and configurable secrets.
|
||||
## Once
|
||||
|
||||
### 1. Set environment variables
|
||||
1. Create a **PostgreSQL** database resource in Coolify and turn on its scheduled backups.
|
||||
2. Create a **Docker Compose** resource from this repository with `docker-compose.coolify.yml`.
|
||||
3. Give the services their domains, on one site so the session cookie reaches the API:
|
||||
- `api` → `https://api.example.com:3001`
|
||||
- `dashboard` → `https://example.com:3000`
|
||||
4. Set the environment variables:
|
||||
|
||||
Create `.env` in the project root:
|
||||
| Variable | |
|
||||
|---|---|
|
||||
| `DATABASE_URL` | The database resource's internal connection URL |
|
||||
| `API_URL` | `https://api.example.com` (baked into the dashboard at build time) |
|
||||
| `DASHBOARD_URL` | `https://example.com` (CORS and links) |
|
||||
| `RESEND_API_KEY`, `RESEND_FROM_EMAIL` | Email; without a key nothing is sent |
|
||||
| `TRUST_PROXY` | 1 behind Coolify's proxy, 2 with Cloudflare proxying too |
|
||||
| `MIN_APP_VERSION` | Optional: make older terminal apps update |
|
||||
|
||||
```env
|
||||
# Database
|
||||
DB_PASSWORD=<generate-a-strong-password>
|
||||
`JWT_SECRET` is generated by Coolify (`SERVICE_BASE64_64_JWT`).
|
||||
5. Deploy. The API applies the database migrations before it starts.
|
||||
6. Create the first venue and its admin, in the API container's terminal:
|
||||
|
||||
# JWT secret — generate with: openssl rand -hex 64
|
||||
JWT_SECRET=<64-char-hex-string>
|
||||
```bash
|
||||
node dist/cli/setup.js "My Venue" admin@myvenue.com '<a strong password>'
|
||||
```
|
||||
|
||||
# URLs — set your actual domain/port
|
||||
DASHBOARD_URL=https://dashboard.yourdomain.com
|
||||
API_URL=https://api.yourdomain.com
|
||||
DASHBOARD_PORT=3000
|
||||
API_PORT=3001
|
||||
```
|
||||
It does nothing when there is a venue already. Superadmins belong to no venue:
|
||||
`node dist/cli/superadmin.js <email> --create "<name>" <password>` adds one, `superadmin.js <email>` promotes a user,
|
||||
and `--revoke <venue id>` makes a superadmin an admin of that venue.
|
||||
|
||||
### 2. Build and start
|
||||
## Switching over from 1.x
|
||||
|
||||
```bash
|
||||
docker compose -f docker-compose.prod.yml up --build -d
|
||||
```
|
||||
2.0 starts with an empty database: nothing comes over from the 1.x backoffice.
|
||||
|
||||
### 3. Create the venue and admin (first time only)
|
||||
1. Before switching, let every tablet sync and settle (or write down) the open tabs. Export what you want to keep.
|
||||
2. Deploy 2.0 on a new, empty database and set up the venues, users and products.
|
||||
3. A 1.x tablet that syncs with it gets `426` and shows "update the app"; its unsent sales stay on the tablet.
|
||||
4. Update the app on each tablet to 2.0. It keeps its settings (PIN, theme, language, rows) and starts unpaired, with
|
||||
empty tabs and history: pair it with a code from Settings and it loads the venue's catalog and open tabs.
|
||||
|
||||
Migrations run automatically when the API container starts.
|
||||
## Backups
|
||||
|
||||
```bash
|
||||
docker compose -f docker-compose.prod.yml exec api node prisma/setup.js "My Venue" admin@myvenue.com '<strong password>'
|
||||
```
|
||||
Back up the database (Coolify does this) **and** the `images` volume, which holds the product pictures.
|
||||
|
||||
`setup.js` does nothing when a venue already exists. `--force` wipes ALL data and starts over.
|
||||
## Every deploy
|
||||
|
||||
### 4. Set up a reverse proxy (nginx/Caddy)
|
||||
Push; Coolify builds both images and restarts. Migrations run on start. If one fails the API doesn't start and the
|
||||
superadmin page's System tab lists it; fix it and redeploy.
|
||||
|
||||
Example Caddyfile:
|
||||
```
|
||||
dashboard.yourdomain.com {
|
||||
reverse_proxy dashboard:3000
|
||||
}
|
||||
## Health
|
||||
|
||||
api.yourdomain.com {
|
||||
reverse_proxy api:3001
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Option B: Manual (Node.js + PostgreSQL)
|
||||
|
||||
### 1. Install PostgreSQL
|
||||
|
||||
Create database and user:
|
||||
```sql
|
||||
CREATE DATABASE kooltap;
|
||||
CREATE USER kooltap WITH PASSWORD 'your-password';
|
||||
GRANT ALL PRIVILEGES ON DATABASE kooltap TO kooltap;
|
||||
```
|
||||
|
||||
### 2. Configure environment
|
||||
|
||||
```env
|
||||
DATABASE_URL="postgresql://kooltap:your-password@localhost:5432/kooltap"
|
||||
JWT_SECRET="<random-64-char-string>"
|
||||
PORT=3001
|
||||
CORS_ORIGIN="https://dashboard.yourdomain.com"
|
||||
```
|
||||
|
||||
### 3. Build and run
|
||||
|
||||
```bash
|
||||
cd apps/api
|
||||
pnpm install
|
||||
npx prisma generate
|
||||
npx prisma migrate deploy
|
||||
pnpm build
|
||||
node dist/main
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Security Checklist
|
||||
|
||||
- [ ] JWT secrets are 64+ random hex characters
|
||||
- [ ] DB_PASSWORD is strong and unique
|
||||
- [ ] HTTPS is terminated at reverse proxy
|
||||
- [ ] CORS_ORIGIN is set to the exact dashboard URL (no wildcard)
|
||||
- [ ] API is not exposed directly to the internet (reverse proxy only)
|
||||
- [ ] Rate limiting is configured
|
||||
- [ ] Audit logs are monitored
|
||||
`GET /api/v1/health` answers 503 when the database is unreachable; the compose file uses it as the healthcheck.
|
||||
|
||||
Reference in New Issue
Block a user