Skip to content
Go back

Owncast vs PeerTube vs nginx-rtmp

By SumGuy 10 min read
Owncast vs PeerTube vs nginx-rtmp

You want to stream. Not to Twitch — to your server. But when you start looking at self-hosted options, you’ll find three very different paths, and picking the wrong one will either bury you in complexity or leave you wishing you’d had chat.

Let’s sort this out.

The Three Lanes

Owncast is Twitch in a box. Single binary, live streaming, built-in chat, viewer directory, integrations. You point your OBS at it and go live. It’s the “I want all the features” play.

PeerTube is YouTube on a budget, but federated. It’s a full video platform with upload/VOD storage, transcoding pipelines, and federation with other PeerTube instances via ActivityPub. It can stream live, but that’s an add-on. This is for “I’m building a video archive” energy.

nginx-rtmp is the “I’ll do it myself” module. It’s RTMP ingest + HLS output with no UI, no auth, no chat. You configure it and connect OBS directly. This is the minimal pipeline — and sometimes minimal is exactly what you need.

The question isn’t “which is best.” It’s “what are you actually doing?”

Owncast: The Twitch Replacement

Owncast is built for one thing: live streaming with an audience. You get RTMP ingest (point OBS at it), HLS playback, chat, follower notifications, webhooks, and a nice web UI out of the box.

Install and Run

Terminal window
curl -s https://owncast.online/install.sh | bash
./owncast

That’s it. Head to http://localhost:8080/admin, set a password, and you’re done. No database, no dependencies. The whole thing is a single binary.

Want it in Docker?

docker-compose.yml
services:
owncast:
image: owncast/owncast:latest
ports:
- "1935:1935" # RTMP ingest
- "8080:8080" # HTTP
volumes:
- owncast-data:/home/owncast/data
environment:
TZ: UTC
volumes:
owncast-data:

Connect OBS

In OBS, go to Settings → Stream:

Hit “Start Streaming” and you’re live. Viewers go to https://your-domain.com and they see your stream + chat.

What Owncast Does Well

Chat is first-class. Built-in moderator tools, emotes, user registration optional. This matters for live events.

Audience discovery. Owncast has a public directory where you can list your stream. It’s not huge, but people find streams there.

Webhooks. Want to ring a Discord bell when you go live? Post to a webhook. Shout-outs, follower notifications, raid integrations — all there.

Single server, single binary. No Postgres. No Redis. No object storage dance. Deploy, run, done.

The Catch

No federation. Your Owncast instance is an island. You can’t discover or interact with other Owncast instances.

Transcoding is your problem. Owncast does not transcode. Whatever bitrate you send, viewers receive. Send 6 Mbps H.264 at 1080p, viewers need 6 Mbps. If you want bitrate ladders (720p, 480p, 360p), you transcode on your hardware before ingest or use an external service.

Storage is local disk. VOD recordings (if enabled) go to your server’s storage. Scale to 100 hours of archives and you’re buying disks.

Audience is small. It’s a fantastic piece of software, but most people have never heard of it. You’ll drive your own traffic.

PeerTube: Federated Video Platform

PeerTube is not a live streaming tool first. It’s a YouTube alternative — upload videos, host them, transcode them, and federate them across a network of PeerTube instances that can see and share each other’s content.

Live streaming is an optional feature on top of that architecture.

Install: Prepare Yourself

PeerTube requires:

This is not a one-binary situation.

Terminal window
# Create a PeerTube user
sudo useradd -m -d /home/peertube peertube
# Install Node.js and ffmpeg
curl -fsSL https://deb.nodesource.com/setup_20.x | sudo -E bash -
sudo apt install nodejs ffmpeg postgresql redis-server
# Clone PeerTube
cd /home/peertube
git clone https://github.com/Chocobozzz/PeerTube.git peertube
cd peertube
npm install
npm run build
# Configure
cp server/config/production.yaml.example server/config/production.yaml
# Edit production.yaml — set hostname, database, Redis, storage paths

Or use Docker Compose — the official docker-compose.yml is 200+ lines with Postgres, Redis, and a PeerTube service.

Federation: The Secret Sauce

Once your PeerTube instance is live, it announces itself to the fediverse. Other PeerTube instances can see your videos, comment on them (via ActivityPub), and vice versa. You can browse the Peertube Index and discover other instances.

This is powerful for discoverability — but it requires serious uptime, HTTPS, and a stable domain. Spin up a PeerTube instance and abandon it after 6 months, and you’ve left dead links and broken video references across the fediverse.

Live Streaming (Optional Feature)

PeerTube live is a built-in feature (introduced in v3.0). You enable it in the admin settings, configure RTMP ingest, and streamers on your instance can go live. Live streams generate VOD archives automatically.

But here’s the thing: the live experience is minimal. There’s a chat plugin (peertube-plugin-chat), but the UI is barebones compared to Owncast. If live streaming is your primary goal, PeerTube will feel over-engineered.

Storage Reality

PeerTube transcodes uploads into multiple bitrates (1080p, 720p, 480p, etc.). Storage adds up fast. Most deployments push all of that to S3 or Wasabi (cheap S3-compatible storage). Local disk becomes the staging area only.

What PeerTube Does Well

Discoverability via federation. Your videos appear on other instances. People find you through the fediverse.

VOD-first architecture. Transcoding pipeline, automatic quality ladders, storage abstraction. If you’re building a video library, this is the platform.

Community. An active development community, plugin ecosystem, and federation network.

Open source ethics. It’s built by humans who believe in decentralization.

The Catch

Operational overhead. Postgres, Redis, ffmpeg workers, object storage orchestration. You’re running a platform, not a service.

Overkill for live-only. If you just want to stream, you’ve installed 90% of features you won’t use.

Bandwidth costs. Transcoding and serving multiple bitrates to multiple viewers multiplies bandwidth. Cheap S3 storage doesn’t mean cheap egress.

Moderation at scale. More federation = more abuse vectors. You’ll need instance rules, moderation tools, and federation policies.

nginx-rtmp: Roll Your Own

nginx-rtmp is a module that turns nginx into an RTMP server. RTMP ingest, HLS output, no UI, no database, no auth. It’s a plumbing tool.

This is for people who want to:

Install the Module

Most distros don’t package nginx with RTMP. You’ll compile it yourself or use a pre-built image:

Terminal window
# Debian/Ubuntu — build from source
sudo apt install build-essential libpcre3 libpcre3-dev zlib1g zlib1g-dev libssl-dev
# Download nginx and rtmp module
cd /tmp
wget http://nginx.org/download/nginx-1.27.0.tar.gz
wget https://github.com/arut/nginx-rtmp-module/archive/master.zip
tar xzf nginx-1.27.0.tar.gz
unzip master.zip
cd nginx-1.27.0
./configure \
--prefix=/etc/nginx \
--sbin-path=/usr/sbin/nginx \
--modules-path=/usr/lib64/nginx/modules \
--with-http_ssl_module \
--with-http_v2_module \
--add-module=../nginx-rtmp-module-master
make && sudo make install

Or use a Docker image with RTMP pre-built — tiangolo/nginx-rtmp or similar.

Configure nginx-rtmp

Here’s the minimal config:

nginx.conf
rtmp {
server {
listen 1935;
chunk_size 4096;
application live {
live on;
record off;
# Push to HLS
push rtmp://localhost/hls;
}
application hls {
live on;
# HLS output
hls on;
hls_path /tmp/hls;
hls_fragment 3;
hls_playlist_length 60;
# Bitrate: no transcoding, direct from source
}
}
}
http {
server {
listen 8080;
location /hls {
types {
application/vnd.apple.mpegurl m3u8;
video/mp2t ts;
}
alias /tmp/hls;
expires -1;
}
}
}

Point OBS at rtmp://your-server:1935/live and it will:

  1. Ingest RTMP on port 1935
  2. Push to the local hls application
  3. Generate HLS playlists in /tmp/hls
  4. Serve them over HTTP on port 8080

Play the Stream

<video controls width="800" height="600">
<source src="http://your-server:8080/hls/stream.m3u8" type="application/vnd.apple.mpegurl">
</video>

Done. No transcoding, no chat, no UI. Just RTMP in, HLS out.

What nginx-rtmp Does Well

Minimal footprint. A few MB of memory, no database, no external services.

Standards-based. RTMP is industry standard for ingest. HLS is universal playback. Stack them with anything.

CPU efficient. No transcoding = low CPU. Direct bitrate passthrough.

DIY-friendly. You control the entire pipeline. Add your own auth, chat, overlays via a custom front-end.

The Catch

No UI. Viewers see a bare HTML5 video player. No chat, no follower buttons, no integrations.

No transcoding. Your viewers need the bandwidth you send. 6 Mbps source = 6 Mbps for all viewers. No adaptive bitrate.

No redundancy. Single nginx process dies, stream dies. No failover, no clustering.

DIY hosting. You’re building a streaming platform from scratch. Chat, moderation, recording, VOD archive — you write that layer.

No federation or discovery. Your stream is completely private unless you tell people about it.

The Real Differences

Live vs VOD

Chat and Community

Federation

Transcoding

Operational Burden

Audience Discovery

The Decision Matrix

You should use Owncast if:

You should use PeerTube if:

You should use nginx-rtmp if:

The Honest Take

Most people think they want to build a streaming platform and actually just want to go live and have their friends watch. Owncast is the answer. Install it on a $5 VPS, point OBS at it, and you’re done.

If you’re serious about building a video library and want the fediverse to help distribute it, PeerTube is the long-term play. But you’re signing up for Postgres, Redis, object storage, and federation moderation.

nginx-rtmp is for people who know what they’re building. You’re not learning streaming; you’re already competent enough to add the parts you need.

Start with Owncast. You can always upgrade to PeerTube later if you need federation. Or drop down to nginx-rtmp if you want to strip away features. But honestly? Owncast is where most people should stop.


Share this post on:

Send a Webmention

Written about this post on your own site? Send a webmention and it'll show up above once verified.


Previous Post
Borgmatic: Borg Backup, Done Right
Next Post
PostgreSQL on ZFS: Tuning, Snapshots, Pitfalls

Discussion

Powered by Garrul . Sign in with GitHub or Google, or post anonymously.

Related Posts