Skip to main content

Prerequisites

  • Docker and Docker Compose
  • A domain name with DNS configured
  • Ports 80 and 443 available
You need three DNS records pointing to your server:
RecordPurpose
your-domain.comControl plane web UI
registry.your-domain.comContainer image registry
logs.your-domain.comLog aggregation (Victoria Logs)

Quick Start

Run the automated install script on a fresh server:
curl -fsSL https://raw.githubusercontent.com/techulus/cloud/main/deployment/install.sh | bash
The script detects your OS, installs Docker, walks you through DNS and environment configuration, and starts all services.

Manual Setup

Clone the repository and configure your environment:
cd deployment
cp .env.example .env
Edit .env with your values (see below), then start the stack:
docker compose -f compose.production.yml up -d --pull always
To use the bundled PostgreSQL instead of an external database:
docker compose -f compose.postgres.yml up -d --pull always

Environment Variables

Required

VariableDescription
ROOT_DOMAINYour domain (e.g., cloud.example.com)
ACME_EMAILEmail for Let’s Encrypt certificates
DATABASE_URLPostgreSQL connection string (e.g., postgres://user:pass@postgres:5432/techulus)
BETTER_AUTH_SECRETSecret key for authentication
ENCRYPTION_KEY32 bytes as a 64-character hex string

Victoria Logs

VariableDescription
VL_USERNAMELogs service username
VL_PASSWORDLogs service password
VL_RETENTIONLog retention period (default: 7d)

Registry

VariableDescription
REGISTRY_USERNAMERegistry username for agents
REGISTRY_PASSWORDRegistry password for agents
REGISTRY_HTTP_SECRETInternal registry secret

Inngest

VariableDescription
INNGEST_SIGNING_KEYRequest verification key (prefix with signkey-prod-)
INNGEST_EVENT_KEYEvent API key

GitHub Integration (Optional)

VariableDescription
GITHUB_APP_IDGitHub App ID
GITHUB_APP_PRIVATE_KEYGitHub App private key (base64-encoded)
GITHUB_WEBHOOK_SECRETWebhook secret

Generating Secrets

# Encryption key (64 hex characters)
openssl rand -hex 32

# Auth secret
openssl rand -hex 32

# Inngest signing key
echo "signkey-prod-$(openssl rand -hex 32)"

# Inngest event key
openssl rand -hex 16

Services

Once running, the following services are available:
ServiceEndpoint
Webhttps://<ROOT_DOMAIN>
Registryhttps://registry.<ROOT_DOMAIN>
Logshttps://logs.<ROOT_DOMAIN>
PostgreSQLInternal only
InngestInternal only
Traefik handles TLS termination and automatic certificate renewal via Let’s Encrypt.

Database Migrations

The schema is synced automatically on container startup via drizzle-kit push. Non-destructive changes (adding tables, columns, indexes) are applied automatically. Destructive changes like dropping columns require manual intervention.

Common Commands

# Check service status
docker compose -f compose.production.yml ps

# View logs
docker compose -f compose.production.yml logs -f

# Stop all services
docker compose -f compose.production.yml down

# Update to latest version
docker compose -f compose.production.yml up -d --pull always