What the load consists of
Owncast takes one RTMP stream from OBS or any other encoder, cuts it into HLS segments with FFmpeg, and serves the segments, the web page, the chat and the admin from one process. Its documentation splits the cost cleanly: the CPU does the transcoding, the network carries the viewers. Zero viewers or a hundred, the encoder works just as hard; only the outbound traffic grows.
| Output configuration | CPU, per the Owncast docs |
|---|---|
| Single passthrough quality | Minimal |
| Single transcoded quality | Light |
| Two qualities (high + low) | Moderate |
| Three qualities or heavy compression | Heavy |
The docs label these as rough measured examples, not guarantees. Their rule of thumb is that one core can often handle one transcoded quality at 30 fps; 60 fps costs about twice the 30 fps baseline and 24 fps about 0.8 of it. Owncast defaults to 24 fps and to a single output variant, and the video guide says to start with one, test it, and add variants while the CPU has headroom.
Disk is small. HLS segments are written temporarily and cleaned up as the stream runs; what grows is the data/ directory, which holds the database, its hourly backups, custom emoji, public files and viewer metrics. FFmpeg must be present: the installer fetches a copy if none is installed.
Passthrough against transcoding
Passthrough copies the inbound video untouched, so bitrate, resolution, frame rate and CPU-level settings for that output are ignored and nearly all of its encoding CPU is saved. The project marks it as an advanced setting most people should not use: viewers get exactly what the encoder sends, a source some players cannot decode stays unplayable, and long keyframe intervals raise latency because Owncast cannot segment video it is not re-encoding.
Transcoding buys an adaptive ladder. The docs' own worked example sends 5,000 kbit/s in and offers 5,000 and 1,500 kbit/s out; with passthrough only, a fifth of that example audience could not watch at all. Each extra rendition is another FFmpeg encode, so the core count scales with the ladder you choose.
Hardware encoding moves that work off the cores, and Owncast's codec guide states the precondition plainly: it does not work on a VPS, because a shared virtual server gives no direct access to the hardware. On a whole machine it does. Intel Quick Sync is on the processors with Intel graphics on the chip, which on our Intel processor list are the Xeon E3-1284L v3 and v4, the E3-1585L v5, the E-2286M and the Core i5-9500. Owncast lists an encoder whenever ffmpeg -encoders advertises it, so confirm that your FFmpeg build really drives the iGPU before relying on it. Past a handful of channels, a GPU belongs on a video transcoding server instead.
Sizing the port
Owncast's formula for the peak the server must sustain is bitrate in kbit/s times viewers, divided by 1,000, in Mbit/s; with several qualities, compute each and add them. The docs note that a 1 Gbit/s port carries roughly 200 viewers at 5,000 kbit/s. Our streaming page sizes with a fifth of the port held back, which gives the figures below. The arithmetic is ours, from those two rules.
| Viewer bitrate | 1 Gbit/s, 80% used | 10 Gbit/s, 80% used |
|---|---|---|
| 1,500 kbit/s | 533 viewers | 5,333 viewers |
| 3,000 kbit/s | 266 viewers | 2,666 viewers |
| 5,000 kbit/s | 160 viewers | 1,600 viewers |
The Owncast examples also count the month's transfer against a hosting plan's allowance. On a dedicated streaming server here that column does not exist: the port is unmetered, no allowance is attached to it and no overage price exists. A gigabit is included on 10 of our 18 lines and 500 Mbit/s on the other 8; 2 to 100 Gbit/s are chosen on the order form, on fewer lines as the speed rises.
Setting it up on Ubuntu
Owncast publishes release archives for Linux and macOS only, so install a Linux image from the panel. The project advises against running the installer as root and against piping a script you have not read, so it runs below as a dedicated system user, after you inspect it.
sudo apt install -y curl unzip
sudo useradd --system --create-home --home-dir /opt/owncast --shell /usr/sbin/nologin owncast
sudo -u owncast bash -c 'cd /opt/owncast && curl -fsSLo install.sh https://owncast.online/install.sh'
sudo -u owncast less /opt/owncast/install.sh # read it before running it
sudo -u owncast bash -c 'cd /opt/owncast && bash install.sh' # installs into /opt/owncast/owncast
Then run it under systemd. The unit is the one in Owncast's background-service guide with the paths adjusted to the installer's directory; the --webserverip 127.0.0.1 flag is our addition, so port 8080 answers only on loopback and the proxy is the sole public path. Owncast otherwise listens on every interface.
# /etc/systemd/system/owncast.service
[Unit]
Description=Owncast
After=network.target
[Service]
Type=simple
WorkingDirectory=/opt/owncast/owncast
ExecStart=/opt/owncast/owncast/owncast --webserverip 127.0.0.1
User=owncast
Group=owncast
Restart=always
RestartSec=5
[Install]
WantedBy=multi-user.target
- Close everything but SSH first:
sudo ufw allow OpenSSH, followed bysudo ufw enable. Owncast's RTMP listener binds to every interface and still accepts the default key. - Load the unit with
sudo systemctl daemon-reload, thensudo systemctl enable --now owncast; watch the log withjournalctl -u owncast -f. - Before opening any port, reach the admin through an SSH tunnel:
ssh -L 8080:127.0.0.1:8080 you@your-server, then browse tohttp://localhost:8080/adminand sign in asadminwithabc123. - Under Configuration > Server Setup, set a new admin password (8 to 192 characters, upper and lower case, a digit, one of
!@#$%^&*, no dash). On the Stream Keys tab, add a generated 30-character key and deleteabc123. - Only now open the public ports:
sudo ufw allow 1935/tcpfor the encoder, plussudo ufw allow 80,443/tcpfor the proxy. Port 8080 stays closed. - Point a DNS name at the server, install Caddy from its official apt repository (Owncast's Caddy page lists the commands) and give it the Caddyfile below. RTMP does not go through the proxy: the encoder publishes straight to
rtmp://your-host/livewith the new key.
# /etc/caddy/Caddyfile (then: sudo systemctl reload caddy)
owncast.example.com {
encode gzip
reverse_proxy 127.0.0.1:8080
tls webmaster@example.com
}
If you lose the admin password, stop the service (sudo systemctl stop owncast), then run the binary once as the service user: sudo -u owncast bash -c 'cd /opt/owncast/owncast && exec ./owncast --webserverip 127.0.0.1 --adminpassword Owncast#2026Pw', choosing your own value that meets the password rules. When it has started, stop it with Ctrl+C and run sudo systemctl start owncast; the new value is saved to the database. A password passed this way is visible in ps and in your shell history: run it once, then clear the history line.
When viewers outgrow the port: S3 offload
Owncast can upload its segments to any S3-compatible bucket and let viewers fetch them from there. The server then uploads one copy of each quality, which in the docs' example of 5,000 plus 1,500 kbit/s is 6.5 Mbit/s whatever the audience, while it still serves the master playlist, the APIs and the chat. The bucket must be publicly readable, usually needs a CORS policy, and every field in the Object Storage tab (bucket, keys, endpoint, region) is required. It keeps only the last few minutes of segments, so it is not a recording archive.
On an unmetered port the reason to offload is capacity or geography, not a transfer bill. The streaming page puts the ceiling of one origin at its port: one city and one port carry most audiences, and when they do not, a CDN goes in front of the machine rather than replacing it. If you do front Owncast with a CDN, its docs ask for a separate public name for the origin, entered as the Websocket host override under Server Setup; without it, chat breaks on any CDN that cannot carry websockets.
Running it
- Backups. Owncast writes
data/backup/owncastdb.bakevery hour, covering configuration, users, chat history and access tokens. Emoji, public files and plugins live elsewhere indata/, so back up the whole directory. To restore, stop the service and runsudo -u owncast bash -c 'cd /opt/owncast/owncast && ./owncast --restoreDatabase data/backup/owncastdb.bak', then start it again. - Upgrades. Re-run the installer as the same
owncastuser from/opt/owncast; it archivesdata/intoowncast-install-backupsbefore replacing the binary, and refuses to run as a different user from the one that owns the install. - Latency. The default buffer level gives about 10 seconds behind live, the lowest about 5, at the price of less tolerance for network blips.
- Chat at scale. Chat is limited by open connections on the one server; if the log shows
too many open files, raise the service's open-file limit with aLimitNOFILE=line in the [Service] section (for exampleLimitNOFILE=65535), thensudo systemctl daemon-reloadand restart owncast. - Out-of-band access. The rack and blade lines and the m510 and m710x cartridges carry a console on HPE iLO, Dell iDRAC or a Supermicro BMC, and any machine can be reinstalled from the panel.
When this is the wrong machine
Owncast's own scaling guide says you cannot run more copies of it for scale, and that a larger deployment expects basic system administration. If nobody on your side wants to patch an operating system, a managed live video plan runs the ingest and the player for you. If the job is a ladder of renditions for many channels, the CPU is the wrong tool and a GPU server is the right one.
Questions
Do I need a GPU for Owncast?
No. Passthrough needs almost no CPU and a single transcoded variant fits on roughly one core at 30 fps, by the project's rule of thumb. Hardware encoding helps when you add variants; Owncast supports Intel Quick Sync, VA-API and NVIDIA NVENC, but only with direct access to the hardware and an FFmpeg built for it.
Which ports must be open?
TCP 1935 for RTMP from your encoder and, with a proxy, TCP 80 and 443 for viewers. Owncast's own web port, 8080 by default, should stay closed to the internet once Caddy or another proxy forwards to it on loopback. Do not route 1935 through the web proxy.
Can I run Owncast in Docker instead?
Yes. The project publishes owncast/owncast:latest and a compose file that mounts ./data at /app/data. Docker's -p flag publishes on every interface and bypasses ufw rules, so map the web port as 127.0.0.1:8080:8080 when a proxy sits in front, and still change the defaults through a tunnel first.
Does Owncast run on Windows Server?
The release archives cover Linux and macOS. Windows notes exist in the project's contrib directory, but the project calls those files community-contributed and not officially supported, so on our machines install Ubuntu or another Linux image.
How far behind live will viewers be?
At the default latency buffer, about 10 seconds; at the lowest level, about 5, with less room for errors. Passthrough tends to make latency worse, because Owncast cannot cut segments optimally from video it does not re-encode.
Does S3 storage keep my past streams?
No. Owncast deletes objects older than the playlist depth plus a buffer of about 20 segments, so the bucket holds only the last few minutes of the live stream. Record locally in your encoder if you need an archive.