Use case · Live video

An Owncast server on a dedicated machine: CPU, port and setup

An Owncast server needs CPU in proportion to the number of video variants it encodes and outbound bandwidth in proportion to its viewers; the two are independent, because Owncast encodes each variant once and sends the same segments to everyone. A passthrough output costs almost no CPU, one transcoded variant at 30 fps takes roughly a core by the project's own rule of thumb, and the port divides by the bitrate. This page sizes both, installs Owncast under systemd behind Caddy, and closes the default credentials before anything is public.

See the streaming servers

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 configurationCPU, per the Owncast docs
Single passthrough qualityMinimal
Single transcoded qualityLight
Two qualities (high + low)Moderate
Three qualities or heavy compressionHeavy

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 bitrate1 Gbit/s, 80% used10 Gbit/s, 80% used
1,500 kbit/s533 viewers5,333 viewers
3,000 kbit/s266 viewers2,666 viewers
5,000 kbit/s160 viewers1,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
  1. Close everything but SSH first: sudo ufw allow OpenSSH, followed by sudo ufw enable. Owncast's RTMP listener binds to every interface and still accepts the default key.
  2. Load the unit with sudo systemctl daemon-reload, then sudo systemctl enable --now owncast; watch the log with journalctl -u owncast -f.
  3. Before opening any port, reach the admin through an SSH tunnel: ssh -L 8080:127.0.0.1:8080 you@your-server, then browse to http://localhost:8080/admin and sign in as admin with abc123.
  4. 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 delete abc123.
  5. Only now open the public ports: sudo ufw allow 1935/tcp for the encoder, plus sudo ufw allow 80,443/tcp for the proxy. Port 8080 stays closed.
  6. 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/live with 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.bak every hour, covering configuration, users, chat history and access tokens. Emoji, public files and plugins live elsewhere in data/, so back up the whole directory. To restore, stop the service and run sudo -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 owncast user from /opt/owncast; it archives data/ into owncast-install-backups before 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 a LimitNOFILE= line in the [Service] section (for example LimitNOFILE=65535), then sudo systemctl daemon-reload and 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.

Put Owncast on a whole machine

Root, an unshared unmetered port, five cities on our own network, and a racked machine live about 30 minutes after the order is approved.

See the streaming servers

Related on Server Room

Other use cases