Deployment
Deploy Dirework to production
This guide covers deploying Dirework to a production environment. Dirework is a Next.js application backed by PostgreSQL, so it can run anywhere that supports Node.js.
Prerequisites
- A server or hosting platform that supports Node.js 20+
- A production PostgreSQL 17+ database
- A domain name (required for Twitch OAuth redirect URLs over HTTPS)
- Your Twitch application credentials
Environment Variables
Set all required environment variables for production:
DATABASE_URL="postgresql://user:password@host:5432/dirework"
BETTER_AUTH_SECRET="<generate-with-openssl-rand-base64-32>"
BETTER_AUTH_URL="https://your-domain.com"
CORS_ORIGIN="https://your-domain.com"
TWITCH_CLIENT_ID="<your_client_id>"
TWITCH_CLIENT_SECRET="<your_client_secret>"
NODE_ENV="production"
# Optional: restrict login to specific Twitch accounts
ALLOWED_TWITCH_IDS=""
# Optional: show legal links in footer (set URL to enable)
# PRIVACY_POLICY_URL="https://your-domain.com/privacy"
# TERMS_OF_SERVICE_URL="https://your-domain.com/terms"Use a strong, unique BETTER_AUTH_SECRET in production. Generate one with openssl rand -base64 32. Never reuse your development secret.
See Environment Variables for the full reference.
Update Twitch Redirect URLs
In the Twitch Developer Console, add your production redirect URLs:
https://your-domain.com/api/auth/callback/twitch
https://your-domain.com/api/bot/callbackYou can keep the localhost URLs alongside the production ones for local development.
Build
Build the web application from the repository root:
pnpm install
pnpm buildThis runs Turborepo to build all packages and the Next.js app with output: "standalone". The standalone output is in apps/web/.next/standalone/.
Option 1: Coolify (Recommended)
Coolify is an open-source, self-hosted PaaS that makes deployment simple. Dirework is configured for Coolify with the included nixpacks.toml.
Setup
-
Install Coolify on your server (see Coolify docs)
-
In Coolify, create a new Service with two resources:
- PostgreSQL 17 Alpine — as the database
- Application — connected to your Dirework Git repository
-
Configure the application:
- Build Pack: Nixpacks (auto-detected from
nixpacks.toml) - Base Directory:
/(repository root) - Port:
3001
- Build Pack: Nixpacks (auto-detected from
-
Set the environment variables in the Coolify dashboard:
- All required variables from the section above
DATABASE_URLshould point to the Coolify PostgreSQL service (use the internal hostname Coolify provides)SKIP_ENV_VALIDATION="true"for the build phase (runtime secrets aren't available during build)
-
Add your domain in Coolify and enable HTTPS
-
Deploy — Coolify will build using Nixpacks, run Prisma migrations, and start the server
How Nixpacks Builds
The nixpacks.toml configures the build pipeline:
- Install — Enables corepack/pnpm, installs dependencies, rebuilds native modules (Prisma, esbuild, sharp)
- Build — Generates Prisma client, runs database migrations, builds Next.js standalone output, copies static assets
- Start — Runs
node apps/web/.next/standalone/apps/web/server.js
Updating
Push to your Git branch and Coolify will automatically rebuild and redeploy. Database migrations run automatically during the build phase.
Option 2: Docker
You can containerize Dirework with Docker. Here's a production-ready Dockerfile:
FROM node:20-slim AS base
RUN corepack enable && corepack prepare pnpm@latest --activate
RUN apt-get update && apt-get install -y openssl && rm -rf /var/lib/apt/lists/*
WORKDIR /app
# Install dependencies
COPY package.json pnpm-lock.yaml pnpm-workspace.yaml ./
COPY apps/web/package.json apps/web/package.json
COPY packages/api/package.json packages/api/package.json
COPY packages/auth/package.json packages/auth/package.json
COPY packages/db/package.json packages/db/package.json
COPY packages/env/package.json packages/env/package.json
COPY packages/config/package.json packages/config/package.json
RUN pnpm install --frozen-lockfile
# Copy source and build
COPY . .
RUN pnpm --filter @dirework/db exec prisma generate
RUN SKIP_ENV_VALIDATION=true pnpm --filter web build
# Copy static assets to standalone output
RUN cp -r apps/web/.next/static apps/web/.next/standalone/apps/web/.next/static
RUN [ -d apps/web/public ] && cp -r apps/web/public apps/web/.next/standalone/apps/web/public || true
EXPOSE 3001
CMD ["node", "apps/web/.next/standalone/apps/web/server.js"]Build and run
docker build -t dirework .
docker run -d \
--name dirework \
-p 3001:3001 \
--env-file apps/web/.env \
direworkDocker Compose
For a complete setup with PostgreSQL:
services:
db:
image: postgres:17-alpine
restart: unless-stopped
environment:
POSTGRES_USER: dirework
POSTGRES_PASSWORD: your-secure-password
POSTGRES_DB: dirework
volumes:
- postgres_data:/var/lib/postgresql/data
ports:
- "5432:5432"
web:
build: .
restart: unless-stopped
depends_on:
- db
ports:
- "3001:3001"
environment:
DATABASE_URL: "postgresql://dirework:your-secure-password@db:5432/dirework"
BETTER_AUTH_SECRET: "<generate-with-openssl-rand-base64-32>"
BETTER_AUTH_URL: "https://your-domain.com"
CORS_ORIGIN: "https://your-domain.com"
TWITCH_CLIENT_ID: "<your_client_id>"
TWITCH_CLIENT_SECRET: "<your_client_secret>"
NODE_ENV: "production"
volumes:
postgres_data:Run with:
docker compose up -dAfter the first start, run migrations: docker compose exec web npx prisma db push or include a migration step in your entrypoint script.
Option 3: VPS / Bare Metal
Setup
-
Clone the repository on your server:
git clone https://github.com/mrdemonwolf/dirework.git cd dirework -
Install dependencies:
pnpm install -
Create and configure
apps/web/.envwith your production values. -
Set up PostgreSQL. You can use the included Docker Compose or connect to an external database:
# Using included Docker Compose pnpm db:start # Or point DATABASE_URL to your external PostgreSQL instance -
Push the database schema:
pnpm db:push -
Build the application:
pnpm build -
Start the production server:
node apps/web/.next/standalone/apps/web/server.jsThe app runs on port 3001 by default.
Reverse Proxy
Use Nginx or Caddy to proxy traffic to the Node.js server and handle HTTPS.
Caddy (recommended — handles HTTPS automatically):
your-domain.com {
reverse_proxy 127.0.0.1:3001
}Nginx:
server {
listen 443 ssl;
server_name your-domain.com;
ssl_certificate /path/to/cert.pem;
ssl_certificate_key /path/to/key.pem;
location / {
proxy_pass http://127.0.0.1:3001;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}Process Manager
Use a process manager to keep the app running:
# Using PM2
npm install -g pm2
pm2 start "node apps/web/.next/standalone/apps/web/server.js" --name dirework
pm2 save
pm2 startupOption 4: Railway / Render / Fly.io
These platforms support Node.js applications. General steps:
- Connect your Git repository
- Set the build command:
pnpm install && pnpm build - Set the start command:
node apps/web/.next/standalone/apps/web/server.js - Add all environment variables
- Provision a PostgreSQL database and set
DATABASE_URL - Set
SKIP_ENV_VALIDATION=trueas a build-time variable - Deploy
Make sure your platform supports Node.js 20+ and that you set SKIP_ENV_VALIDATION=true during the build phase, since runtime secrets aren't available at build time.
Database
Production PostgreSQL
For production, use a managed PostgreSQL service or a dedicated PostgreSQL server instead of the development Docker container:
- Managed services: Neon, Supabase, Railway, AWS RDS, DigitalOcean Managed Databases
- Self-hosted: Install PostgreSQL directly or use Docker with a persistent volume
Update DATABASE_URL to point to your production database.
Migrations
After updating Dirework, push any schema changes:
pnpm db:pushOr if using Docker, run migrations as part of your deployment:
docker compose exec web npx prisma db pushDocumentation Site
The documentation site (apps/fumadocs) is a static site that can be deployed separately:
cd apps/fumadocs
pnpm buildThe static output is in apps/fumadocs/out/. Deploy it to any static hosting service (GitHub Pages, Netlify, Vercel, Cloudflare Pages, etc.).
Checklist
Before going live, verify:
-
BETTER_AUTH_SECRETis a strong, unique value -
BETTER_AUTH_URLandCORS_ORIGINmatch your production domain (withhttps://) - Twitch redirect URLs are added for your production domain
- PostgreSQL is accessible and schema is pushed
- HTTPS is configured (required for Twitch OAuth in production)
-
ALLOWED_TWITCH_IDSis set if you want to restrict access - Application starts and you can sign in with Twitch
- Bot account connects and responds to chat commands
- Timer overlay works in OBS
- Task list overlay works in OBS