Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.techulus.cloud/llms.txt

Use this file to discover all available pages before exploring further.

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 --remove-orphans
To use the bundled PostgreSQL instead of an external database:
docker compose -f compose.postgres.yml up -d --pull always --remove-orphans
Production hosts should also cap Docker container logs. The installer creates /etc/docker/daemon.json with json-file rotation on fresh hosts. If Docker is already configured, keep your existing daemon settings and add equivalent log rotation manually. The Compose files include container health checks for visibility. Plain Docker Compose reports unhealthy containers but does not restart them automatically, so use the common commands below when investigating a self-hosted service.

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

Control Plane Replicas

VariableDescription
WEB_REPLICASNumber of control plane web containers to run (default: 1)
When WEB_REPLICAS is greater than 1, Traefik discovers the replicated web containers through Docker and load balances requests for <ROOT_DOMAIN> across them. Startup schema sync still runs from each web container, so simultaneous replica starts may run drizzle-kit push concurrently during upgrades.

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 --remove-orphans

# Update to the configured image references
docker compose -f compose.production.yml up -d --pull always --remove-orphans
Use versioned or digest-pinned image references for production updates when possible. Mutable tags such as latest and tip are convenient, but they can move between pulls.