HarborFM

HarborFM

Open source podcast creation. Build episodes from segments - record, trim, reorder - then export audio and RSS.

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

When prompted, choose nginx and enter your domain and Let's Encrypt email. Best for a single domain: nginx, certbot for SSL, optional Fail2Ban. After install, run certbot once to get the cert; use a cron job to renew.

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

When prompted, choose Caddy. Best for automatic HTTPS and dynamic or multiple hostnames - Caddy obtains and renews TLS certificates with no certbot. Ideal if you want custom subdomains per show or user.

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

Runs HarborFM as a single container. Use nginx or Caddy on the host for HTTPS. Open http://localhost:3001 and complete the one-time setup from the container logs.

git clone https://github.com/LoganRickert/harborfm.git
cd harborfm
pnpm install
pnpm run db:migrate
pnpm run dev

Requires Node.js 22+, pnpm, ffmpeg, and audiowaveform. Open the URL shown in the terminal; use the one-time setup link from the server logs to create the admin account.

About

HarborFM is free and open source - a modern replacement for Anchor.fm. Create shows, add episodes, and build each episode from segments: record or upload clips, pull intros and bumpers from a library, trim and reorder, then export a single audio file and RSS feed. The app has PWA support - add it to your home screen and connect to your server.

Optional: transcripts via Whisper ASR, LLM helpers (Ollama or OpenAI) for copy suggestions, and public feed pages for discovery. Deploy feeds and audio to S3, R2, FTP, SFTP, WebDAV, IPFS, or SMB.

Features

Podcasts & episodesCreate shows with metadata, artwork, categories. Add episodes with title, description, season/episode numbers.
SegmentsBuild each episode from segments: recorded clips or library assets. Trim, split, remove silence; ffmpeg concatenates to final audio.
LibraryUpload reusable audio (intros, outros, bumpers). Tag and insert into any episode.
TranscriptsGenerate transcripts via Whisper ASR. Optional LLM integration for summaries and copy suggestions.
RSS & exportRSS feed per podcast. Deploy to S3, R2, FTP, SFTP, WebDAV, IPFS, SMB. Only changed files are uploaded.
Auth & usersFirst-user setup, registration, login, password reset. Optional admin and user management. Public feed pages when enabled.
API keysCreate API keys for programmatic access. Keys are hashed; raw key shown only once on create. Use from Profile.
Subscription tokensPer-podcast tokenized RSS for private or subscriber-only feeds. Optional validity window and limits per show.
Automatic DNSOptional Cloudflare integration: managed domains and subdomains so listeners can use custom URLs for your feeds.
CollaboratorsShare shows with view, editor, or manager roles. Invite by email; optional platform invites for new users.
Contact pageBuilt-in contact form; messages stored and optionally emailed to admins. Configurable from settings.
Analytics & GeoIPPodcast stats: RSS hits, episode requests, listens by location. Optional GeoLite2 for country/city.
Email & captchaEmail verification, password reset, and optional captcha (reCAPTCHA or hCaptcha) for registration and reset.
Read-only accountsUser limits and read-only accounts. Per-user limits for podcasts, episodes, and storage.

Screenshots

Dashboard, episode editor, recording, and podcast delivery. Click any image to open in a lightbox; click again to close.

Dashboard - your shows
Episodes - build from segments
Record a segment
Podcast delivery - S3, FTP, etc.
Library - intros, bumpers
Transcripts & LLM help

Tech stack

Monorepo (pnpm workspaces): shared (Zod schemas, types), server (Fastify API, SQLite with better-sqlite3, ffmpeg for audio), web (React, Vite, TanStack Query). Single Node process serves the API and static web app; no separate database server.

Project structure

harborfm/
├── server/     # API and app entry
├── web/        # React frontend
├── shared/     # Shared schemas and types
├── Dockerfile  # Multi-stage build, Node + ffmpeg
└── pnpm-workspace.yaml

Requirements

For local dev: Node.js 22+, pnpm, ffmpeg, audiowaveform (e.g. brew install audiowaveform on macOS; on Linux, build from bbc/audiowaveform or use a package if available). The Docker image includes ffmpeg.

Open API docs (Swagger) GitHub