Dirework

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/callback

You can keep the localhost URLs alongside the production ones for local development.

Build

Build the web application from the repository root:

pnpm install
pnpm build

This runs Turborepo to build all packages and the Next.js app with output: "standalone". The standalone output is in apps/web/.next/standalone/.


Coolify is an open-source, self-hosted PaaS that makes deployment simple. Dirework is configured for Coolify with the included nixpacks.toml.

Setup

  1. Install Coolify on your server (see Coolify docs)

  2. In Coolify, create a new Service with two resources:

    • PostgreSQL 17 Alpine — as the database
    • Application — connected to your Dirework Git repository
  3. Configure the application:

    • Build Pack: Nixpacks (auto-detected from nixpacks.toml)
    • Base Directory: / (repository root)
    • Port: 3001
  4. Set the environment variables in the Coolify dashboard:

    • All required variables from the section above
    • DATABASE_URL should 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)
  5. Add your domain in Coolify and enable HTTPS

  6. Deploy — Coolify will build using Nixpacks, run Prisma migrations, and start the server

How Nixpacks Builds

The nixpacks.toml configures the build pipeline:

  1. Install — Enables corepack/pnpm, installs dependencies, rebuilds native modules (Prisma, esbuild, sharp)
  2. Build — Generates Prisma client, runs database migrations, builds Next.js standalone output, copies static assets
  3. 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 \
  dirework

Docker 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 -d

After 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

  1. Clone the repository on your server:

    git clone https://github.com/mrdemonwolf/dirework.git
    cd dirework
  2. Install dependencies:

    pnpm install
  3. Create and configure apps/web/.env with your production values.

  4. 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
  5. Push the database schema:

    pnpm db:push
  6. Build the application:

    pnpm build
  7. Start the production server:

    node apps/web/.next/standalone/apps/web/server.js

    The 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 startup

Option 4: Railway / Render / Fly.io

These platforms support Node.js applications. General steps:

  1. Connect your Git repository
  2. Set the build command: pnpm install && pnpm build
  3. Set the start command: node apps/web/.next/standalone/apps/web/server.js
  4. Add all environment variables
  5. Provision a PostgreSQL database and set DATABASE_URL
  6. Set SKIP_ENV_VALIDATION=true as a build-time variable
  7. 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:push

Or if using Docker, run migrations as part of your deployment:

docker compose exec web npx prisma db push

Documentation Site

The documentation site (apps/fumadocs) is a static site that can be deployed separately:

cd apps/fumadocs
pnpm build

The 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_SECRET is a strong, unique value
  • BETTER_AUTH_URL and CORS_ORIGIN match your production domain (with https://)
  • 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_IDS is 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

On this page