Skip to content

Deployment

Logan Rickert edited this page Feb 21, 2026 · 1 revision

Deployment

Short guides for installing and running HarborFM. For full variable reference and advanced options, see the main README and the Terraform docs linked below.

Quick reference: The main README has a "Quick Start" (Docker one-liner), "Deploy with Terraform" (AWS and Vultr), "Docker Compose Quick Start (Curl)" (install.sh), and "Running without Docker" (PM2, manual build). Use this wiki for an overview; use the README and infrastructure/terraform/QUICKSTART.md for step-by-step and all variables.

Docker and Compose

Single container (Docker)

The app needs writable data and optionally secrets directories. You can pass secrets via environment variables instead of mounting /secrets.

HARBORFM_SECRETS_KEY=$(openssl rand -base64 32)
JWT_SECRET=$(openssl rand -base64 32)

docker run --name harborfm -p 3001:3001 \
  -v harborfm-data:/data \
  -e HARBORFM_SECRETS_KEY="$HARBORFM_SECRETS_KEY" \
  -e JWT_SECRET="$JWT_SECRET" \
  ghcr.io/loganrickert/harborfm:latest

Open http://localhost:3001 (or your host and port). Get the one-time setup URL from docker logs harborfm. Use nginx or Caddy on the host for HTTPS. If you use plain http, set COOKIE_SECURE=false.

Build from source: From repo root, docker build -t harborfm . (or pnpm run docker:build).

Docker Compose (full stack)

The repo's docker-compose can run the app with nginx or Caddy, Let's Encrypt, optional WebRTC, Whisper, Fail2Ban. Quick start without cloning the repo:

curl -fsSL https://raw.githubusercontent.com/loganrickert/harborfm/main/install.sh | bash

Follow prompts for domain and cert email. For WebRTC, use the webrtc profile:

docker compose --profile nginx --profile webrtc up -d

Required .env for WebRTC: WEBRTC_ENABLED, WEBRTC_SERVICE_URL, WEBRTC_PUBLIC_WS_URL, WEBRTC_SERVICE_SECRET, RECORDING_CALLBACK_SECRET, and behind NAT, MEDIASOUP_ANNOUNCED_IP. See main README "WebRTC (group calls)."

Certificate renewal is typically done via cron (e.g. docker compose run --rm --entrypoint certbot certbot renew). Run docker compose from the install directory so paths in .env (e.g. INSTALL_DIR) are correct.

See also

Terraform (AWS / Vultr)

Terraform can provision a VM (AWS EC2 or Vultr) that runs HarborFM via user-data (PM2, nginx, optional WebRTC and Let's Encrypt).

Prerequisites

  • Terraform installed. See infrastructure/terraform/QUICKSTART.md for macOS, Debian, and CentOS.
  • AWS: AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY (or aws configure).
  • Vultr: VULTR_API_KEY in .env (copy from infrastructure/terraform/.env.example).

AWS (EC2)

  1. cd infrastructure/terraform/aws
  2. cp terraform.tfvars.example terraform.tfvars
  3. Edit terraform.tfvars: deploy_type, ami_id (Debian 12 for your region), domain, admin_email, admin_password, etc.
  4. ./run.sh init then ./run.sh apply
  5. Use the url output to open the app. If you set admin_email and admin_password, the admin is created on first boot.

AMI lookup (Debian 12): Owner 136693071363. Example for us-east-2:

aws ec2 describe-images --region us-east-2 --owners 136693071363 \
  --filters "Name=name,Values=debian-12-*" "Name=state,Values=available" \
  --query "sort_by(Images, &CreationDate)[-1].ImageId" --output text

Vultr

  1. cd infrastructure/terraform/vultr
  2. cp terraform.tfvars.example terraform.tfvars
  3. Edit terraform.tfvars: deploy_type, region, os_id, plan, domain, etc.
  4. ./run.sh init then ./run.sh apply

OS IDs: List with curl -s -H "Authorization: Bearer $VULTR_API_KEY" https://api.vultr.com/v2/os | jq '.os[] | {id, name}'. Common: Debian 12 2136, Ubuntu 22 1743, etc.

Full variable reference and options

See also

Environment variables

HarborFM is configured mainly via environment variables. Below is a short overview; the full table is in the main README ("Docker environment variables").

Essential for production

  • JWT_SECRET - Required for signing sessions; use a long random string (e.g. openssl rand -base64 32).
  • HARBORFM_SECRETS_KEY - Optional; used to encrypt export credentials (base64/base64url). If you use Podcast Delivery, set this.
  • DATA_DIR - Where the DB, uploads, processed audio, RSS, artwork, and library live (Docker often /data).
  • SECRETS_DIR - Where JWT and secrets key files are stored (Docker often /secrets). Can be omitted if you pass secrets via env.

Server and paths

  • PORT (default 3001), HOST (default 0.0.0.0).
  • PUBLIC_DIR - Static web app (e.g. ./public). Built app is usually copied here.
  • NODE_ENV - Set to production in production; affects CORS and cookie Secure default.

Cookies and HTTPS

  • COOKIE_SECURE - Set to true when using HTTPS. For http only, set COOKIE_SECURE=false.

WebRTC (group calls)

  • WEBRTC_ENABLED - 1 or true to enable.
  • WEBRTC_SERVICE_URL - Internal URL to webrtc service (e.g. http://webrtc:3002).
  • WEBRTC_PUBLIC_WS_URL - Public WebSocket URL for clients (e.g. wss://example.com/webrtc-ws).
  • WEBRTC_SERVICE_SECRET, RECORDING_CALLBACK_SECRET - For app ↔ webrtc auth.
  • MEDIASOUP_ANNOUNCED_IP - Set to the server's public IP when behind NAT.

Upload limits, binaries, and more

The README table includes: upload size limits (episode, segment, library, artwork), FFMPEG_PATH, FFPROBE_PATH, AUDIOWAVEFORM_PATH, GeoIP, Whisper, LLM, email, captcha, rate limits, and many optional tuning vars. Use the README as the canonical reference.

See also

Clone this wiki locally