Files
red/teressa-copeland-homes/DEPLOYMENT.md
Chandler Copeland 9117dc4c02 initial install
2026-04-08 12:54:58 -06:00

6.7 KiB

Deployment Guide — Self-Hosted (Unraid + Gitea)

Overview

This app runs as two Docker containers:

  • app — Next.js server (port 3000)
  • db — PostgreSQL 16 (port 5432)

Required Secrets

All of these must be set in .env.production before starting.

Variable What it is How to get it
DATABASE_URL Internal postgres URL postgresql://postgres:POSTGRES_PASSWORD@db:5432/teressa
POSTGRES_PASSWORD Postgres superuser password Generate: openssl rand -base64 32
SIGNING_JWT_SECRET Signs document signing tokens Generate: openssl rand -base64 32
AUTH_SECRET NextAuth session encryption Generate: openssl rand -base64 32
AUTH_TRUST_HOST Required for reverse proxy Set to true
AGENT_EMAIL Your login email for the portal Your email address
AGENT_PASSWORD Your login password for the portal Choose a strong password
CONTACT_EMAIL_USER SMTP username See SMTP section below
CONTACT_EMAIL_PASS SMTP password/API key See SMTP section below
CONTACT_SMTP_HOST SMTP server hostname See SMTP section below
CONTACT_SMTP_PORT SMTP port 587 (STARTTLS) or 465 (SSL)
OPENAI_API_KEY OpenAI API key for AI field placement platform.openai.com → API keys
APP_BASE_URL Public URL of the app (no trailing slash) e.g. https://teressa.yourdomain.com

SMTP Options

  • Resend (recommended): host=smtp.resend.com, port=465, user=resend, pass=Resend API key
  • Gmail: host=smtp.gmail.com, port=587, user=your Gmail, pass=App Password (not your regular password)

Part 1: Push Repo to Gitea

On your local machine

# Add your Gitea instance as a remote
git remote add gitea http://YOUR_UNRAID_IP:3000/YOUR_GITEA_USERNAME/teressa-copeland-homes.git

# Push
git push gitea main

Create the repo in Gitea first (via the Gitea web UI) before pushing.


Part 2: Build and Push Docker Image to Gitea Registry

Gitea includes a built-in OCI container registry. Replace YOUR_UNRAID_IP, YOUR_GITEA_USERNAME, and YOUR_GITEA_PORT with your values.

# Log in to Gitea's container registry
docker login YOUR_UNRAID_IP:YOUR_GITEA_PORT

# Build the image (from the project root)
docker build -t YOUR_UNRAID_IP:YOUR_GITEA_PORT/YOUR_GITEA_USERNAME/teressa-copeland-homes:latest .

# Push to Gitea registry
docker push YOUR_UNRAID_IP:YOUR_GITEA_PORT/YOUR_GITEA_USERNAME/teressa-copeland-homes:latest

Gitea registry port is usually the same as the Gitea web port (e.g. 3000 or 10880 depending on your setup). Check your Gitea container settings in Unraid.

HTTP registry: If Gitea is HTTP (not HTTPS), add the registry to Docker's insecure registries. On Unraid, go to Settings → Docker → Insecure Registries and add YOUR_UNRAID_IP:PORT.


Part 3: Deploy on Unraid

Unraid supports docker-compose via the Compose Manager community app.

  1. Install Compose Manager from Community Apps if not already installed
  2. SSH into Unraid and create the app directory:
    mkdir -p /mnt/user/appdata/teressa-copeland-homes
    cd /mnt/user/appdata/teressa-copeland-homes
    
  3. Copy docker-compose.yml and .env.production.example to this directory:
    cp docker-compose.yml .env.production.example /mnt/user/appdata/teressa-copeland-homes/
    
  4. Create .env.production from the example and fill in all values:
    cp .env.production.example .env.production
    nano .env.production
    
  5. Set APP_IMAGE to your Gitea registry URL in .env.production:
    APP_IMAGE=YOUR_UNRAID_IP:YOUR_GITEA_PORT/YOUR_GITEA_USERNAME/teressa-copeland-homes:latest
    
  6. In Compose Manager, add the compose file and start it

Option B: Unraid Docker UI (manual containers)

Add two containers via Docker → Add Container:

Container 1 — postgres

  • Repository: postgres:16-alpine
  • Name: teressa-db
  • Port: 5432:5432
  • Environment variables:
    • POSTGRES_USER=postgres
    • POSTGRES_PASSWORD=YOUR_STRONG_PASSWORD
    • POSTGRES_DB=teressa
  • Path: /mnt/user/appdata/teressa-db/var/lib/postgresql/data

Container 2 — app

  • Repository: YOUR_UNRAID_IP:YOUR_GITEA_PORT/YOUR_GITEA_USERNAME/teressa-copeland-homes:latest
  • Name: teressa-app
  • Port: 3000:3000
  • Network: Same as teressa-db (so it can reach teressa-db by name, or use Unraid IP)
  • Environment variables: All 13 from the table above
    • Note: DATABASE_URL should use the Unraid host IP or container name instead of db
  • Path: /mnt/user/appdata/teressa-uploads/app/uploads

Part 4: Run Migrations and Seed

These must run after the database container is healthy, before the app is usable.

Run migrations

# From your local machine (requires node + npx)
DATABASE_URL="postgresql://postgres:YOUR_PASSWORD@YOUR_UNRAID_IP:5432/teressa" npx drizzle-kit migrate

# Or SSH into Unraid and run from the project directory
docker exec -it teressa-app npx drizzle-kit migrate

Seed agent account + form templates

# SSH into Unraid
docker exec \
  -e DATABASE_URL="postgresql://postgres:YOUR_PASSWORD@db:5432/teressa" \
  -e AGENT_EMAIL="your@email.com" \
  -e AGENT_PASSWORD="your-password" \
  teressa-app npx tsx scripts/seed.ts

# Seed the 140 real estate form templates
docker exec \
  -e DATABASE_URL="postgresql://postgres:YOUR_PASSWORD@db:5432/teressa" \
  teressa-app npx tsx scripts/seed-forms.ts

Both seed scripts are idempotent — safe to re-run.


Part 5: Verify

curl http://YOUR_UNRAID_IP:3000/api/health
# Expected: {"ok":true,"db":"connected"}

Then open http://YOUR_UNRAID_IP:3000 in a browser and log in with AGENT_EMAIL / AGENT_PASSWORD.


Updating

When you push a new version:

# On local machine — rebuild and push image
docker build -t YOUR_UNRAID_IP:PORT/YOUR_GITEA_USERNAME/teressa-copeland-homes:latest .
docker push YOUR_UNRAID_IP:PORT/YOUR_GITEA_USERNAME/teressa-copeland-homes:latest

# On Unraid — pull new image and restart
docker pull YOUR_UNRAID_IP:PORT/YOUR_GITEA_USERNAME/teressa-copeland-homes:latest
docker restart teressa-app

# If schema changed, run migrations first:
DATABASE_URL="postgresql://postgres:YOUR_PASSWORD@YOUR_UNRAID_IP:5432/teressa" npx drizzle-kit migrate

Reverse Proxy (optional)

If you want HTTPS via a domain name, put a reverse proxy in front on port 443:

  • Nginx Proxy Manager (available in Unraid Community Apps) — easiest GUI option
  • Caddy — automatic HTTPS with Let's Encrypt
  • Traefik — label-based routing

Point the proxy at http://YOUR_UNRAID_IP:3000. Make sure APP_BASE_URL in .env.production matches the public HTTPS URL, and ensure AUTH_TRUST_HOST=true is set.