Skip to content
streamneo.
Setup Guides12 min read

How to Restart an FFmpeg YouTube Stream After a VPS Reboot Using systemd

Configure systemd to start FFmpeg at boot, restart it after failures and check whether YouTube is receiving healthy media.

sn.
StreamNeoPublished 4 October 2026
Worth sharing?

A systemd service can start FFmpeg when your VPS boots and relaunch it after qualifying process failures. To know whether the stream has actually recovered, check both the service and YouTube Studio: a running FFmpeg process is not proof that YouTube is receiving healthy media.

This guide sets up that process supervision, explains when to wait for network readiness, and gives you checks for a planned reboot. Adapt the example to your host, input and current YouTube Live Control Room settings; no unit file can resolve a bad key, missing source or failed network path on its own.

Check the FFmpeg command and stream prerequisites

Before creating a unit, make sure your existing FFmpeg command works when run manually under the same account that will run the service. A command that succeeds in your interactive shell may depend on a shell alias, an unqualified executable in your personal PATH, or a file that the service user cannot read. systemd does not automatically inherit your shell’s environment.

Check the executable path with command -v ffmpeg, then record the absolute path it returns. Check the input file or source URL, any referenced configuration, and the working directory. If a video lives under /home/channel/media, for example, the service account needs permission to read that directory and the file. If a playlist uses relative paths, either convert them to absolute paths or set WorkingDirectory= deliberately.

Keep the ingest endpoint and stream key aligned with the intended broadcast in YouTube’s current Live Control Room. Do not paste the key into a publicly shared unit file, a support ticket or a command you expect to preserve in shell history. A restricted environment file can separate credentials from the unit, but set restrictive ownership and permissions; environment variables can still be visible to privileged diagnostics. Depending on your systemd version, credentials support or another dedicated secret mechanism may be more suitable. Avoid printing secrets in diagnostic output.

Your FFmpeg command must also produce media that YouTube can accept. YouTube’s encoder guidance covers current protocols, codecs and settings, and recommends RTMPS. Use the encoder table and the settings shown for your intended stream rather than treating one bitrate as universal. Test the exact command and monitor stream health before relying on it for a continuous channel.

FFmpeg options are version- and protocol-dependent. Check ffmpeg -version, then inspect the installed build’s help or documentation before copying reconnect or output-recovery options from an online example. In particular, HTTP reconnect options concern HTTP input behaviour; they do not automatically repair a stalled RTMP/RTMPS output. The FFmpeg command and protocol references are useful background, but the local build is the one your VPS will run.

For a channel built around a repeating video file, confirm that the input and loop behaviour are intentional before you make the unit persistent. The practical decisions involved in choosing a format for a 24/7 YouTube stream also apply here: systemd can relaunch a command, but it cannot make an unsuitable or unavailable input produce the programme you expect.

Create a systemd service unit

Create a unit file such as /etc/systemd/system/youtube-ffmpeg.service using a text editor with administrative privileges. The following is a template, not a universal ready-to-run command. Replace every placeholder, including the service account, working directory, input, output configuration and FFmpeg arguments.

[Unit]
Description=FFmpeg YouTube live stream

[Service]
Type=simple
User=streamer
WorkingDirectory=/home/streamer/live
ExecStart=/usr/bin/ffmpeg -re -stream_loop -1 -i /home/streamer/media/programme.mp4 -c:v libx264 -c:a aac -f flv [OUTPUT_ARGUMENTS]
Restart=on-failure
RestartSec=10

[Install]
WantedBy=multi-user.target

ExecStart= should point directly to FFmpeg and pass its arguments directly, so systemd supervises the encoder process rather than a shell wrapper. Replace [OUTPUT_ARGUMENTS] with the appropriate output options and destination from your own secure configuration. Do not leave the bracketed placeholder in the file or place a real key in this public example. The illustrative codecs and input behaviour may not suit your media, available CPU or YouTube configuration.

Use the absolute executable path and absolute input paths. If you rely on an environment file, add an EnvironmentFile= entry only after creating that file with appropriate access permissions, and make sure it does not appear in a world-readable directory. Consult the manual for the systemd version installed on the VPS before using features such as systemd credentials.

The User= field runs the process without making it root, which limits the impact of mistakes. Create a dedicated account if appropriate, and verify it can read the media and configuration and write any required logs or temporary files. WorkingDirectory= is optional if all paths are absolute, but it makes the service’s starting directory explicit when your command needs one.

A fixed-video channel and a radio-style stream can have different input needs. If your source is a station feed, for instance, compare this service design with the source and host considerations in streaming a Bengali radio station from an Indian VPS. The unit still supervises a process; source-specific reconnect behaviour belongs in the tested FFmpeg command, not in assumptions about systemd.

Configure boot startup and restart behaviour

WantedBy=multi-user.target tells systemd which normal boot target should pull in the service when enabled. The systemctl enable command creates the relationship that makes that happen at boot. It does not, by itself, start the service in your current session; use enable --now or run start separately.

Restart=on-failure asks systemd to restart the service when it exits in a way classified as failure, rather than restarting it after every clean exit. This is a common policy for long-running services, but it is not a promise to retry every possible issue indefinitely. Consult the locally installed systemd.service manual for exact exit-status semantics, restart timing and interactions with start limits. The systemd project’s service unit documentation describes the available controls.

RestartSec=10 in the sample gives a short pause before a restart attempt. It is an example, not a prescribed value for every host. A delay helps avoid a tight restart loop, but a longer delay may be appropriate if a source or network dependency needs time to recover. If the command has a bad stream key or a missing file, repeated attempts will not fix the cause. Inspect the logs and any start-limit message before repeatedly forcing a restart.

There are two separate recovery layers to keep in view. systemd can start FFmpeg at boot and relaunch it if the process exits as a failure. FFmpeg may also have options that attempt to recover particular input or output conditions while the process remains alive. They cover different failure modes; an FFmpeg process that has not exited may still be sending no useful media, so systemd’s process restart policy may never trigger. Validate any recovery option against the installed FFmpeg build and test the behaviour with your actual input and destination.

Do not add aggressive restart settings simply because a stream has dropped once. A retry policy is useful when a transient fault causes an exit; it can also repeatedly invoke a broken command. Your useful signal is not merely that systemd restarted something, but that the expected broadcast receives media again.

Add appropriate network ordering

If FFmpeg needs a working network connection as soon as it starts, add these lines under [Unit]:

Wants=network-online.target
After=network-online.target

After= expresses ordering: systemd should start this unit after the named target is reached. Wants= pulls the target into the transaction as a wanted dependency. Neither line makes a disconnected network work, and network-online.target is not a universal test that DNS, routing and YouTube ingest access are all usable.

The host’s network stack needs to provide the relevant wait-online behaviour for this ordering to be useful. How that is configured varies by distribution and network manager. Check the VPS operating system’s documentation and service state rather than assuming the target has waited for a usable connection. The systemd boot and network ordering documentation explains why network.target alone does not mean the network is operational.

If the network is still unavailable when FFmpeg starts, FFmpeg may exit and the restart policy may try again after the configured delay. That is one possible path to recovery, not a guarantee: DNS, firewall egress, routing, credentials or the selected ingest endpoint can remain broken. After a reboot, distinguish a failed initial connection from an FFmpeg command error by reading the service journal and testing network reachability from the VPS.

Do not add network ordering blindly if your service does not depend on network availability at startup. The important point is to express the real dependency and verify the system actually waits as you expect. When planning a wider always-on workflow, the VPS setup considerations for a 24/7 YouTube story stream can help frame the host and media assumptions that sit around this unit.

Enable and start the service

After saving the unit, ask systemd to reload unit definitions, then enable and start the service:

sudo systemctl daemon-reload
sudo systemctl enable --now youtube-ffmpeg.service

This explicitly does both jobs: enablement arranges boot startup, while --now starts the unit now. If you prefer separate steps, run sudo systemctl enable youtube-ffmpeg.service and then sudo systemctl start youtube-ffmpeg.service. Enabling alone is not evidence that FFmpeg has started.

Check the first result before testing a reboot:

sudo systemctl status youtube-ffmpeg.service
sudo journalctl -u youtube-ffmpeg.service -n 50 --no-pager

If systemd reports a syntax or execution error, correct the unit and reload it. Look for a missing executable, inaccessible input, an invalid FFmpeg option, permission errors, a failed connection or authentication problems. The journal can include command arguments, so avoid putting secrets directly into a command line that will be captured there.

Test in a planned maintenance window, particularly if the channel is already serving viewers. A reboot interrupts the host process while the machine shuts down and comes back; neither enable nor Restart=on-failure makes that interval disappear. If an interruption is unacceptable for a particular programme, plan around it rather than treating a reboot test as invisible to viewers.

Before the test, record the intended YouTube broadcast and confirm that the manual service start sends the expected media. Then reboot, reconnect to the VPS, and carry out both the host checks and the Studio checks below. A successful test tells you how this host behaved under that test; it does not guarantee recovery from a later outage or a different failure.

Verify service status after reboot

Once the VPS is reachable again, first check whether systemd considers the unit active and whether it is enabled for future boots:

sudo systemctl is-enabled youtube-ffmpeg.service
sudo systemctl status youtube-ffmpeg.service
sudo journalctl -b -u youtube-ffmpeg.service --no-pager

is-enabled checks the boot relationship. status shows the current state and recent details, while the journal query for the current boot helps you see what happened after startup. An enabled service can still fail to launch; an active service can still be producing the wrong output. Read the exit reason and timestamps instead of treating either word as a health verdict.

If it did not start, check that the unit file is in the expected location, that you reloaded systemd after editing it, and that the unit is enabled. Confirm that every executable and media path exists and that the configured user has access. Compare the command in ExecStart= with the working manual command, including any environment values that an interactive shell supplied implicitly.

If it starts and exits repeatedly, inspect the latest journal lines and the status output for the actual failure and any start-limit state. A failed key, an unavailable input or an FFmpeg option unsupported by the installed build needs a correction, not a faster restart interval. Once corrected, restart deliberately and watch the new journal entries.

If status says the process is active but the broadcast has no picture or sound, the problem may be downstream of process supervision. FFmpeg can remain alive while its input stalls or its output stops delivering useful media. Check the input and output behaviour separately; adding a watchdog or external monitor introduces another mechanism to configure and test, and it still needs a definition of what counts as healthy media.

Confirm broadcast and stream health in YouTube Studio

Open YouTube Studio’s Live Control Room and check the intended broadcast, not simply any live item on the channel. Confirm that YouTube is receiving the expected stream and that its stream-health indicators show usable media. YouTube recommends testing before an event and monitoring stream health; see its current encoder settings and stream-health guidance.

The two checks answer different questions. systemd status and logs tell you whether it launched and supervised an FFmpeg process. Studio tells you whether the expected broadcast is receiving media that YouTube can assess. If the process is active but Studio shows no incoming media, investigate the destination URL, key association, network path and FFmpeg output rather than concluding that recovery succeeded.

Check that the stream key is current, private and attached to the broadcast you expect. Verify the selected ingest endpoint in Live Control Room, then review FFmpeg’s output for connection or authentication errors. Do not share a full key or unredacted command in a public forum while troubleshooting. YouTube’s recommended encoder settings can change, so check the official page and your own Live Control Room configuration at the time you configure the stream.

If the broadcast appears connected but health is poor, look at the media as well as the connection: input audio and video, encoder load, output settings and the stream-health details. A green-looking service state cannot identify a frozen source or incompatible output. Keep a short record of the reboot time, service journal result and Studio observation; that makes it easier to separate a boot-order problem from an ingest or source problem next time.

For a video-loop channel, scheduling and media preparation are part of the same operating decision. A VPS service gives you control over the encoder process, while a workflow built around prepared uploads can remove the need to keep your own machine running. StreamNeo removes that specific always-on computer burden by turning an uploaded video into a YouTube live stream that continues with your computer switched off; it does not replace checking whether the intended broadcast and media are healthy.

Before committing, compare the operating options on the pricing page. When the file and channel are ready, start free — 24-hour trial, no card.

FAQ

Does systemctl enable start FFmpeg immediately?

No. It configures the service to be started during the relevant boot target. Use systemctl start as a separate command, or systemctl enable --now to enable and start it together.

Does an active service mean YouTube has recovered the stream?

No. Active means systemd sees the service process running; it does not confirm that YouTube is receiving decodable media on the intended broadcast. Check FFmpeg’s journal and the stream-health view in YouTube Studio.

Should I use network.target or network-online.target?

If FFmpeg needs a usable connection at startup, order it after network-online.target and ensure the host has a working wait-online mechanism. network.target alone does not mean routing, DNS and ingest access are ready.

What if FFmpeg stays active but the stream freezes?

systemd usually reacts to process exits, not to media that has stalled while the process remains alive. Diagnose the input and output separately, then consider tested FFmpeg recovery options or a health-check design that can detect the particular failure you experience.

YOU’VE REACHED THE END

Keep the ideas coming.

More guides, useful tools and a little help for your next broadcast.

Back to the journal ↗
YOUR NEXT READ

A little more to explore.

More Setup Guides guides ↗ · All topics ↗