# Deployment Short guides for installing and running HarborFM. For full variable reference and advanced options, see the main [README](../blob/main/README.md) 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](../blob/main/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`. ```bash 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 **Caddy** (default) or **nginx**, Let's Encrypt, optional **WebRTC**, Whisper, and Fail2Ban. Quick start without cloning the repo: ```bash curl -fsSL https://raw.githubusercontent.com/loganrickert/harborfm/main/install.sh | bash ``` Follow prompts for domain and reverse proxy. **`install.sh` defaults to Caddy**; nginx is optional (with Let's Encrypt or a self-signed cert). For **WebRTC**, enable it during install or use the `webrtc` compose profile with your proxy profile, for example: ```bash docker compose --profile caddy --profile webrtc up -d # or, if you chose nginx: 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`. After Hostname is set in **Settings**, WebRTC Settings values take precedence over `WEBRTC_*` env vars (env still seeds empty settings). See main [README](../blob/main/README.md) "WebRTC (group calls)." ### Updating an install.sh deploy `install.sh` also installs **`update.sh`** in the install directory. Run it from that directory to refresh compose configs and images. Configs and images are fetched while the stack stays up; downtime is only the brief recreate step. When `WEBRTC_ENABLED=1`, `update.sh` passes the `webrtc` profile to `down` / `pull` / `up` so the webrtc image is pulled and the container is recreated. Always run `docker compose` from the install directory so paths in `.env` (e.g. `INSTALL_DIR`) resolve correctly. Certificate renewal for nginx+certbot is typically done via cron (e.g. `docker compose run --rm --entrypoint certbot certbot renew`). Caddy renews certificates itself. ### Stripe webhooks (payments) If show owners use [Stripe payments](Stripe-payments.md), each credential pack needs a webhook URL pointed at your public host. See that page and the main [README](../blob/main/README.md) "Stripe payments" section. Locally you can use `pnpm stripe:listen`. ### See also - [Terraform (AWS / Vultr)](#terraform-aws--vultr) - [Environment variables](#environment-variables) - [Stripe payments](Stripe-payments.md) - Main [README](../blob/main/README.md) - Docker, Docker Compose Quick Start, WebRTC ## 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](../blob/main/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`: ```bash 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 - **[infrastructure/terraform/README.md](../blob/main/infrastructure/terraform/README.md)** - Variables, optional persistent data volume, multi-environment (dev/prod). - **[infrastructure/terraform/QUICKSTART.md](../blob/main/infrastructure/terraform/QUICKSTART.md)** - Step-by-step Terraform install and first apply. ### See also - [Docker and Compose](#docker-and-compose) - [Environment variables](#environment-variables) - Main [README](../blob/main/README.md) - Deploy with Terraform If you want to manage multiple instances from a web UI instead of running Terraform manually, use the **[Instance manager](Instance-manager.md)**. ## Environment variables HarborFM is configured mainly via **environment variables**. Below is a short overview; the full table is in the main [README](../blob/main/README.md) ("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 and Stripe credential packs (base64/base64url). Set this if you use Podcast Delivery or [Stripe payments](Stripe-payments.md). - **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 - [Docker and Compose](#docker-and-compose) - [Terraform (AWS / Vultr)](#terraform-aws--vultr) - [Instance manager](Instance-manager.md) - Managing multiple instances and its own env vars - Main [README](../blob/main/README.md) - Docker environment variables (full table)