Skip to main content

What you will build

A running Harly installation with PostgreSQL, the scheduler, HTTPS via Caddy, and an owner workspace. The installer keeps the application on port 3000 behind the proxy you select.

Requirements

See self-hosting overview for full sizing, DNS, and firewall setup before you install.
1

Point DNS at your VPS

Create an A record for your domain or subdomain pointing at the VPS public IPv4 address:
Add an AAAA record only if IPv6 is configured and reachable. Caddy cannot issue a certificate until the hostname resolves to this server.
Do not continue until dig returns the correct IP. Caddy will fail the TLS challenge if DNS has not propagated.
2

Open required firewall ports

Allow inbound TCP 80 and TCP 443 in your VPS firewall or cloud security group. Also allow UDP 443 if you want HTTP/3.No other service or Docker container may already publish port 80 or 443. If another proxy owns those ports, use external proxy mode instead.
3

Run the installer

From any directory on the VPS:
The guided installer:
  1. Checks the server for Docker, Compose, Node, free disk, and RAM.
  2. Asks for the public URL (https://careers.example.com).
  3. Asks for the first owner email.
  4. Generates all secrets and writes .env with mode 0600.
  5. Pulls the Harly image from the registry.
  6. Runs database migrations.
  7. Starts the app, scheduler, and Caddy.
  8. Waits for the readiness endpoint to return 200.
The installer saves .env and harly.config.json in the current directory. Run it from a stable directory — for example /opt/harly — so backups and updates always work from the same path.
4

Create the first owner account

Visit https://careers.example.com/setup and enter the setup secret (HARLY_SETUP_SECRET) when prompted. Create the account with the email matching HARLY_INITIAL_ADMIN_EMAIL.
Keep HARLY_SETUP_SECRET private. If /setup is unavailable, verify that the owner account has not already been claimed and confirm the value in .env with npx @harly/cli setup-secret.
/setup is available exactly once. After the owner account is created, the route becomes unavailable and registration is invite-only.

Verify the installation

Run these from the installation directory:
If the page loads but /api/health/ready fails, see troubleshooting before inviting the team.

Common install errors

Caddy will not obtain a certificate

Symptom: installer or doctor reports a stuck TLS challenge. Cause: DNS has not propagated, or another process holds port 80 or 443. Fix:

Installer reports insufficient memory

Symptom: preflight warns about RAM. Cause: less than 2 GB RAM without swap. Fix: enable 1 GB swap so the installer selects the compact profile, or force it explicitly in .env:
Or override individual limits:

Readiness endpoint returns 503

Symptom: curl /api/health/ready returns 503. Cause: database unavailable or migration incomplete. Fix:
Confirm postgres is Up (healthy) before the app starts.

Setup page not available

Symptom: visiting /setup returns 404 or “not found”. Cause: owner account was already claimed, or the route is disabled. Fix: sign in with the owner email you configured, or check HARLY_SETUP_SECRET in .env.

Re-running the installer

Run from the installation directory at any time to open the management menu:
Re-running init preserves .env and secrets. Modified templates are preserved unless --force is supplied; --force still never rotates .env.

Next steps

First workspace

Configure the team, pipeline, roles, and first job.

Proxy modes

Use Caddy, an external proxy, or local-only.

Configuration

Required secrets, storage, email, and integrations.

Operations

Health checks, scheduler, backups, and upgrades.