Installation

Torqvoice is designed to be self-hosted. Choose the setup that fits your needs:

Prerequisites

  • A Linux server (Ubuntu 22.04+ recommended), VPS, or local machine
  • Docker installed
  • At least 1 GB of RAM and 2 GB of disk space

Quick Start

This is the fastest way to get Torqvoice up and running.

1. Create your project directory

mkdir torqvoice && cd torqvoice

2. Create .env

This generates a secure auth secret and writes the .env file in one step:

echo "BETTER_AUTH_SECRET=$(openssl rand -hex 32)" > .env
echo 'NEXT_PUBLIC_APP_URL=http://localhost:3000' >> .env

If you are deploying on a remote server, replace localhost with your server's IP address or domain name (e.g. http://192.168.1.100:3000).

3. Create docker-compose.yml

services:
  app:
    container_name: torqvoice
    image: ghcr.io/torqvoice/torqvoice:latest
    restart: unless-stopped
    ports:
      - "3000:3000"
    environment:
      - DATABASE_URL=postgresql://torqvoice:torqvoice@db:5432/torqvoice
      - BETTER_AUTH_SECRET=${BETTER_AUTH_SECRET}
      - NEXT_PUBLIC_APP_URL=${NEXT_PUBLIC_APP_URL:-http://localhost:3000}
    volumes:
      - uploads:/app/data/uploads
    depends_on:
      db:
        condition: service_healthy

  db:
    image: postgres:16-alpine
    container_name: torqvoice-db
    restart: unless-stopped
    volumes:
      - postgres-data:/var/lib/postgresql/data
    environment:
      POSTGRES_USER: torqvoice
      POSTGRES_PASSWORD: torqvoice
      POSTGRES_DB: torqvoice
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U torqvoice"]
      interval: 5s
      timeout: 5s
      retries: 5

volumes:
  postgres-data:
  uploads:

5. Start and visit

docker compose up -d

Visit http://localhost:3000 and create your first admin account.


Production with SSL

For production deployments you need a reverse proxy in front of Torqvoice to handle HTTPS. Pick either Nginx or Caddy — both provide automatic Let's Encrypt certificates.

A domain name pointed at your server is required for SSL to work.

Nginx + acme-companion

Uses nginx-proxy and acme-companion for automatic certificate provisioning and renewal.

Create a .env file:

echo "BETTER_AUTH_SECRET=$(openssl rand -hex 32)" > .env

Create a docker-compose.yml:

services:
  nginx-proxy:
    image: nginxproxy/nginx-proxy
    container_name: nginx-proxy
    restart: unless-stopped
    ports:
      - "80:80"
      - "443:443"
    volumes:
      - certs:/etc/nginx/certs
      - html:/usr/share/nginx/html
      - /var/run/docker.sock:/tmp/docker.sock:ro
    environment:
      - TRUST_DOWNSTREAM_PROXY=false

  acme-companion:
    image: nginxproxy/acme-companion
    container_name: acme-companion
    restart: unless-stopped
    volumes_from:
      - nginx-proxy
    volumes:
      - acme:/etc/acme.sh
      - /var/run/docker.sock:/var/run/docker.sock:ro
    environment:
      - DEFAULT_EMAIL=your-email@example.com

  app:
    container_name: torqvoice
    image: ghcr.io/torqvoice/torqvoice:latest
    restart: unless-stopped
    expose:
      - "3000"
    environment:
      - DATABASE_URL=postgresql://torqvoice:torqvoice@db:5432/torqvoice
      - BETTER_AUTH_SECRET=${BETTER_AUTH_SECRET}
      - NEXT_PUBLIC_APP_URL=https://torqvoice.example.com
      - VIRTUAL_HOST=torqvoice.example.com
      - VIRTUAL_PORT=3000
      - LETSENCRYPT_HOST=torqvoice.example.com
    volumes:
      - uploads:/app/data/uploads
    depends_on:
      db:
        condition: service_healthy

  db:
    image: postgres:16-alpine
    container_name: torqvoice-db
    restart: unless-stopped
    volumes:
      - postgres-data:/var/lib/postgresql/data
    environment:
      POSTGRES_USER: torqvoice
      POSTGRES_PASSWORD: torqvoice
      POSTGRES_DB: torqvoice
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U torqvoice"]
      interval: 5s
      timeout: 5s
      retries: 5

volumes:
  certs:
  html:
  acme:
  postgres-data:
  uploads:

Replace torqvoice.example.com with your domain and your-email@example.com with your email for Let's Encrypt notifications. The nginx-proxy container automatically discovers the Torqvoice container via the VIRTUAL_HOST variable, and acme-companion handles certificate provisioning and renewal.

Caddy

Caddy provides automatic HTTPS with zero configuration.

Create a .env file:

echo "BETTER_AUTH_SECRET=$(openssl rand -hex 32)" > .env

Create a Caddyfile:

torqvoice.example.com {
    reverse_proxy app:3000
}

Create a docker-compose.yml:

services:
  caddy:
    image: caddy:2-alpine
    container_name: caddy
    restart: unless-stopped
    ports:
      - "80:80"
      - "443:443"
      - "443:443/udp"
    volumes:
      - ./Caddyfile:/etc/caddy/Caddyfile
      - caddy-data:/data
      - caddy-config:/config

  app:
    container_name: torqvoice
    image: ghcr.io/torqvoice/torqvoice:latest
    restart: unless-stopped
    expose:
      - "3000"
    environment:
      - DATABASE_URL=postgresql://torqvoice:torqvoice@db:5432/torqvoice
      - BETTER_AUTH_SECRET=${BETTER_AUTH_SECRET}
      - NEXT_PUBLIC_APP_URL=https://torqvoice.example.com
    volumes:
      - uploads:/app/data/uploads
    depends_on:
      db:
        condition: service_healthy

  db:
    image: postgres:16-alpine
    container_name: torqvoice-db
    restart: unless-stopped
    volumes:
      - postgres-data:/var/lib/postgresql/data
    environment:
      POSTGRES_USER: torqvoice
      POSTGRES_PASSWORD: torqvoice
      POSTGRES_DB: torqvoice
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U torqvoice"]
      interval: 5s
      timeout: 5s
      retries: 5

volumes:
  caddy-data:
  caddy-config:
  postgres-data:
  uploads:

Replace torqvoice.example.com with your domain in both the Caddyfile and docker-compose.yml. Caddy will automatically obtain and renew SSL certificates.


Docker without Compose

If you already have a PostgreSQL database running, you can run the Torqvoice container directly:

docker run -d \
  --name torqvoice \
  -p 3000:3000 \
  -e DATABASE_URL="postgresql://user:pass@your-db-host:5432/torqvoice" \
  -e BETTER_AUTH_SECRET="your-secret-here" \
  -e NEXT_PUBLIC_APP_URL="http://localhost:3000" \
  -v torqvoice-uploads:/app/public/uploads \
  ghcr.io/torqvoice/torqvoice:latest

Manual Setup

Run Torqvoice directly with Node.js — useful for custom deployments without Docker.

Requirements: Node.js 20+ with npm, PostgreSQL 15+

git clone https://github.com/Torqvoice/torqvoice.git
cd torqvoice
npm install
cp .env.example .env
# Edit .env with your database URL and secrets
npx prisma generate
npx prisma db push
npm run build
npm start

The application will be available at http://localhost:3000.


Development

The recommended way to develop Torqvoice is to open the project in a Dev Container. The repository includes a .devcontainer configuration that sets up the full development environment with PostgreSQL and all required tooling, ensuring proper linting and consistent editor settings out of the box.

In VS Code, install the Dev Containers extension, then open the command palette and select Dev Containers: Reopen in Container. The container will build automatically and start the database alongside the development server.


Updating

docker compose pull
docker compose up -d

Your data is stored in Docker volumes and will persist across updates.

Environment Variables

VariableRequiredDescription
DATABASE_URLYesPostgreSQL connection string
BETTER_AUTH_SECRETYesAuth secret (generate with openssl rand -hex 32)
NEXT_PUBLIC_APP_URLYesPublic URL of your Torqvoice instance

Next Steps

After installation, head to the Configuration guide to set up email notifications, payment integrations, and other settings.