# Deploy ARCHI on any provider

ARCHI is a **Node.js + PostgreSQL** app. It runs anywhere that can run Docker
or `npm run build && npm start` with a Postgres database and persistent disk
(or S3/R2 for media).

## What you need

| Piece | Options |
|-------|---------|
| Runtime | Docker **or** Node.js 22+ |
| Database | Managed Postgres (Render, Neon, Supabase, RDS, …) **or** Compose Postgres |
| Media | Local volume (`STORAGE_PROVIDER=local`) **or** S3/R2 |
| Domain | Apex + wildcard `*.yourdomain` for tenant studios |
| TLS | Caddy / Nginx / Cloudflare / provider load balancer |

## 1. Environment

```bash
cp .env.production.example .env.production
```

Set at minimum:

- `APP_URL` / `NEXT_PUBLIC_APP_URL` / `AUTH_URL` → your public `https://…` origin  
- `AUTH_SECRET` → `openssl rand -base64 32`  
- `PLATFORM_ROOT_DOMAIN` (+ app/admin/api hosts)  
- `DATABASE_URL` **or** discrete `DB_HOST` / `DB_USER` / `DB_PASSWORD` / `DB_NAME` / `DB_SSL=true`  
- `EMAIL_PROVIDER=resend` + `EMAIL_API_KEY` for real verification emails  

Discrete DB vars are supported so the same app works on panels that do not
give a single `DATABASE_URL` (common on Render-style hosts).

## 2. Deploy with Docker (recommended — any VPS)

Works on Hetzner, DigitalOcean, Contabo, AWS EC2, Azure VM, bare metal, etc.

```bash
# On the server
git clone <your-repo> archi && cd archi
cp .env.production.example .env.production
# edit .env.production — also set POSTGRES_PASSWORD for the Compose DB

docker compose -f docker-compose.prod.yml --env-file .env.production up -d --build
```

Checks:

- Liveness: `https://your-domain/health`  
- Readiness: `https://your-domain/ready`  

Media uploads persist in the `archi_media_data` volume when
`STORAGE_PROVIDER=local`.

### HTTPS with Caddy

1. Point DNS A/AAAA (and `*.yourdomain`) at the server.  
2. Uncomment the `caddy` service in `docker-compose.prod.yml`.  
3. Set `PLATFORM_ROOT_DOMAIN` / `DOMAIN` to your apex domain.  
4. `docker compose -f docker-compose.prod.yml --env-file .env.production up -d`

## 3. Deploy without Docker (Node host)

```bash
cp .env.production.example .env.production
# fill secrets + DATABASE_URL

npm ci
npm run build
npm run db:migrate          # applies ./drizzle
npm start                   # listens on PORT (default 3000)
```

Put Nginx/Caddy/Cloudflare in front for TLS. Keep a persistent directory for
`.data/storage` if using local storage.

## 4. Provider notes

### Render / Railway / Fly / Coolify

- Build: Docker (`Dockerfile`) **or** `npm run build`  
- Start: container entrypoint **or** `npm start`  
- Attach managed Postgres → paste `DATABASE_URL` (add `?sslmode=require` if needed)  
- For ephemeral disks, set `STORAGE_PROVIDER=s3` or `r2` and fill S3 env vars  
- Set health check path to `/health`

### Vercel

Not ideal until object storage is fully wired for every media path: Vercel
filesystem is ephemeral. Prefer a VPS/Docker host for the current local-storage
default, or configure S3/R2 first.

### External managed Postgres only

If Postgres lives outside Compose, remove/override the Compose `DATABASE_URL`
injection and set your managed URL in `.env.production`. You can run only the
`app` service:

```bash
docker build -t archi-app .
docker run -d --env-file .env.production -p 3000:3000 \
  -v archi_media:/app/.data/storage archi-app
```

## 5. DNS for multi-tenant studios

| Record | Value |
|--------|--------|
| `A` / `AAAA` `@` | Server IP |
| `CNAME` or `A` `*` | Same target (wildcard tenants) |
| Optional `app` / `admin` | Same origin or dedicated hosts |

Local LAN preview stays path-based (`/studio/{slug}`). Online tenants use
`https://{slug}.{PLATFORM_ROOT_DOMAIN}`.

## 6. First login after deploy

```bash
# optional seed (dev fixtures — avoid on real production data)
SEED_ON_BOOT=true docker compose -f docker-compose.prod.yml --env-file .env.production up -d
# or
npm run db:seed
```

Or register a new studio from the landing page.

## 7. Security checklist

- [ ] No secrets in git (`.env.production` is gitignored)  
- [ ] `AUTH_SECRET` unique and ≥ 32 chars  
- [ ] `AUTH_URL` / `APP_URL` are `https://`  
- [ ] Postgres not exposed publicly (Compose binds internally only)  
- [ ] Rotate any credentials that were ever pasted into `.env.example`  
- [ ] Email provider is not `console` in production  

## Scripts

| Command | Purpose |
|---------|---------|
| `npm run db:migrate` | Apply SQL migrations |
| `npm run db:push` | Push Drizzle schema (dev) |
| `npm run start:prod` | `next start` bound to `0.0.0.0` |
| `npm run docker:prod` | Build & start production Compose stack |
