To start an FFmpeg YouTube stream after a Linux server reboots, create a systemd service that runs your tested FFmpeg command, then enable that service for boot. A restart policy can relaunch FFmpeg after the process exits, but it cannot guarantee an uninterrupted stream or repair every YouTube, network or playback problem.
The distinction matters: systemd supervises a process on your host, while YouTube receives the stream separately. You still need a working command, a usable network connection, valid stream credentials and a source that FFmpeg can read. Treat the unit as one part of recovery, then test each failure mode you care about.
What systemd can and cannot recover
A system-level service gives FFmpeg a defined place in the host's boot sequence. Once enabled, systemd can start the unit when the relevant boot target is reached. If the managed FFmpeg process exits, a configured restart policy can ask systemd to start it again after a delay.
That covers two useful cases: a server reboot and a process termination. It does not mean the stream itself is continuously healthy. If FFmpeg remains alive but stops sending usable media, a basic restart-on-exit rule may see no exit to act on. Likewise, systemd cannot make an invalid command valid, restore a missing input file, fix an expired key or ensure that YouTube is reachable.
Think in terms of separate layers. The service manager can launch a process; FFmpeg must open its input and publish its output; the host must have working connectivity; and YouTube must accept the incoming stream. A green service state confirms only that systemd considers the process active, not that viewers can watch a healthy live broadcast.
If your failure is tied to a virtual machine reboot rather than a hand-built Linux service, the steps may differ by provider. The Compute Engine reboot troubleshooting guide is a useful comparison for that case. If viewers report buffering despite a healthy ingest indication, consider the separate checks in YouTube Live connection and viewer buffering.
Confirm the FFmpeg command works manually
Before writing a unit, run the exact command in a shell on the server under the account that will run the service, or under a comparable account with the same file and network access. Confirm the FFmpeg executable path with command -v ffmpeg, and check the installed version with ffmpeg -version. A package update, custom build or different service account can change what is available.
Use the same input file, loop or playlist behaviour, encoding options and YouTube destination that you intend to use in production. FFmpeg documents its general command shape as options followed by an input, then output options and an output destination. Option placement matters: input-specific options belong before the relevant -i; output options belong before the output URL. Consult the FFmpeg command-line documentation for the options supported by your installed build.
For example, an illustrative command might look like this, with placeholders replaced by your own values:
/usr/bin/ffmpeg -re -stream_loop -1 -i /srv/video/loop.mp4 \
-c:v libx264 -c:a aac -f flv \
'rtmps://YOUR_YOUTUBE_INGEST_URL/YOUR_STREAM_KEY'
This is not a universal command: your source, codecs, resolution, ingest address and stream key may differ. Test it interactively and confirm that FFmpeg can read the media, encode it and connect to the chosen destination. YouTube provides the current stream URL and key through Live Control Room; its RTMPS guidance describes copying the key into the encoder and using the RTMPS server URL when selecting encrypted streaming.
Do not infer settings from this example if the stream already works with a different command. Preserve your known-good command, including quoting and option order, before changing it for systemd. If the source is a playlist or a remote file, confirm that it behaves the same way at the time the service starts, rather than only after you have logged in and warmed up the connection.
A stream that repeatedly disconnects may also need different output settings or a closer look at the route to YouTube. For video-rate planning, see the 24/7 FFmpeg ingest bitrate guide. This does not replace testing your actual command; bitrate is only one part of a working output.
Create a service unit with the correct command
A system service typically has [Unit], [Service] and [Install] sections. Create a file such as /etc/systemd/system/youtube-ffmpeg.service with administrator privileges. The name is yours to choose, but use it consistently in commands that start, inspect or enable the unit.
A basic unit might be:
[Unit]
Description=FFmpeg YouTube live stream
[Service]
Type=simple
User=streamer
WorkingDirectory=/srv/video
ExecStart=/usr/bin/ffmpeg -re -stream_loop -1 -i /srv/video/loop.mp4 -c:v libx264 -c:a aac -f flv rtmps://INGEST_URL/STREAM_KEY
Restart=on-failure
RestartSec=10
[Install]
WantedBy=multi-user.target
Replace the account, working directory, input, destination and options with values from your tested setup. ExecStart should contain the executable and arguments directly, not a shell command copied with interactive shell conveniences. If your working command depends on shell expansion, pipelines or environment variables, handle those deliberately and check the local systemd service manual for the supported approach.
The example puts a key on the command line only to show where the output destination sits. In a real unit, do not leave a live credential readable in a world-readable file. Prefer a protected configuration method appropriate to your distribution and service design, and restrict access to the unit and any environment file. The exact environment-file mechanism and permissions should be verified against the installed systemd version.
Use a dedicated, unprivileged service account where practical. Ensure that account can read the media and any configuration it needs, and can write logs or temporary files if the command requires them. A command that succeeds as root but cannot read its input as streamer will fail after service start, even though the FFmpeg syntax is otherwise correct.
Set a restart policy and delay
The restart directive determines which process exits prompt another attempt. Restart=on-failure is a reasonable starting point when you want recovery after an unsuccessful exit but do not intend a deliberate clean stop to launch the process again. Restart=always is a different choice: it also treats a clean exit as a reason to restart, which may suit a stream intended to run continuously but can be surprising during maintenance.
Choose according to how your command exits and how you stop it. A playlist that reaches its end successfully may exit cleanly; on-failure would not necessarily restart it. A loop intended to run indefinitely may be expected to stay active, so an unexpected exit should be treated as a fault. Check systemd.service(5) on the host for exact semantics and any distribution-specific limits rather than treating a sample unit as a guarantee.
Set a non-zero RestartSec to leave a pause before another attempt. This avoids an immediate retry cycle if, for example, the input file is missing or the network is unavailable at startup. A delay does not diagnose or fix the fault. Repeated failures can still fill logs and leave the stream down, so inspect why the process exited before assuming retries are recovery.
An FFmpeg-user service example illustrates the use of Restart=always and a restart delay, but it is an operational example, not a normative specification for every systemd release. The appropriate directive depends on the desired clean-exit behaviour, and the installed manual is the authority for the host's version.
| Choice | Useful when | Trade-off |
|---|---|---|
Restart=on-failure |
An unexpected or unsuccessful exit should trigger another attempt | A clean exit may leave the stream stopped |
Restart=always |
The process is expected to run until explicitly stopped | A clean exit can cause another launch, including after command behaviour you may want to investigate |
| No explicit network wait | FFmpeg can start before connectivity is fully configured, or handles initial connection attempts itself | Startup may race with network configuration |
network-online.target dependency |
The host has a functioning wait-online provider and the process needs configured connectivity first | Boot can take longer, and the signal does not prove YouTube is reachable |
| Key embedded in unit | Convenient for a short test, if the file is tightly restricted | Easy to expose through file access or copied diagnostics |
| Protected configuration | The unit can refer to credentials stored with restricted access | Requires careful permissions and correct loading by the service |
Configure boot ordering and network-online dependencies
If FFmpeg needs a configured network connection when it starts, you can add Wants=network-online.target and After=network-online.target under [Unit]. Wants= pulls the target into the start transaction; After= specifies ordering. A unit with only an ordering relationship does not necessarily cause the other target to be started.
For example:
[Unit]
Description=FFmpeg YouTube live stream
Wants=network-online.target
After=network-online.target
Do not assume that adding these lines means the server has a working path to YouTube. The systemd networking guidance explains that network-online.target is meaningful through the host's network management setup. The matching wait-online service for that manager must be installed and active for the wait to represent configured connectivity. Review the systemd network target guidance and identify which network manager your server actually uses.
network.target and network-online.target are not interchangeable. The former is primarily a point for ordering network-related startup and shutdown; it does not assert that external connectivity is ready. The latter is intended as a wait point, but the host's network manager and wait-online provider determine what it actually waits for. A wait can also add time to boot, particularly where the manager is waiting for an address or route that never arrives.
Even a successful wait does not establish that DNS resolution works, the YouTube ingest endpoint is reachable, or a remote media source is available. Keep the restart behaviour and logs useful for later failures. If the stream only needs to start and FFmpeg already retries or exits clearly when disconnected, you may decide not to hold up boot for a network wait; test the behaviour rather than adding dependencies by habit.
Enable the service and verify startup
After saving a new or edited unit, ask systemd to reload unit definitions, then enable and start the service:
sudo systemctl daemon-reload
sudo systemctl enable --now youtube-ffmpeg.service
enable arranges for the unit to be started through its install target at boot; --now starts it in the current session as well. Enabling alone is not a test of the command. Watch the first start and confirm that the service account, input and credential configuration all work as expected.
Check the unit state with:
sudo systemctl status youtube-ffmpeg.service
Also check YouTube Live Control Room for incoming data and the expected preview. These are distinct checks: systemd can show an active process while YouTube has not accepted a usable stream. If you are running a live channel from a home connection, the practical routing considerations in running a YouTube podcast stream on JioFiber without drops may help you separate local connectivity from service startup.
When you update the unit later, reload it again before restarting the service. Keep a note of the known-good command and the change made, so that if a new option breaks startup you can roll back to the prior version. Avoid editing a unit while assuming systemd automatically adopts the new definition.
Inspect service status and logs after a failure
When the stream stops, begin with systemd's view of the process and the recent journal entries:
sudo systemctl status youtube-ffmpeg.service
sudo journalctl -u youtube-ffmpeg.service -b
The status output can show whether the process is active, failed or restarting, along with an exit status. The journal can reveal command parsing errors, missing files, permission problems, rejected connections or codec failures. Add --since with an appropriate time window or -f to follow new entries while reproducing a failure. Do not share raw logs publicly until you have checked for credentials and private paths.
An active state is not a health check for the media output. FFmpeg may remain running while its input is stalled or the output connection is no longer useful. Look for changing timestamps, output progress and connection messages, then compare them with the receiving status in Live Control Room. If the FFmpeg process never exits, a simple Restart= policy may not trigger. That limitation is why a process supervisor should not be described as a complete stream monitor.
For repeated restarts, fix the cause rather than merely shortening the delay. A bad input path will fail on every launch. An invalid key or destination can repeatedly fail to publish. A network outage may recover later, but the exact outcome depends on FFmpeg's behaviour and build. Consult the FFmpeg protocol documentation for the protocols and options your installed binary supports; do not assume HTTP reconnection switches apply to RTMP output.
Test reboot recovery and protect credentials
Once the service starts correctly by hand and through systemd, plan a controlled reboot. Warn anyone relying on the channel, choose a suitable window, and verify after boot that the unit started and YouTube is receiving data. A test on the same host and configuration is more useful than assuming that an enabled unit guarantees the result on every distribution.
Test other failure modes separately. Stop or terminate FFmpeg in a controlled way and observe whether the configured policy behaves as expected. Then test the network path separately if that is important to your channel. A process-exit test asks whether systemd relaunches FFmpeg; a network-loss test asks how FFmpeg and the connection behave; a reboot test asks whether the boot integration and ordering work. Passing one does not establish the others.
Keep the YouTube key private. YouTube describes the key as the value copied from Live Control Room into the encoder; anyone with access to it may be able to publish to that stream. Use the RTMPS destination where selected in Live Control Room, keep configuration readable only by the administrator and required service account, and avoid pasting credentials into tickets, shell history or unredacted journal excerpts. If you believe a key has been exposed, review its status and replace it through YouTube's current controls.
Finally, document the service name, account, media path, command source and recovery checks for whoever maintains the channel next. Do not record the secret itself in that handover. If you do not need a Linux host under your own administration, an approach that runs an uploaded video as a YouTube live stream without leaving your computer on may remove the specific burden of maintaining a server-side FFmpeg process.
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
Will systemd restart FFmpeg after every server reboot?
If the unit is enabled for an appropriate boot target, systemd should start it as part of boot. Whether the stream returns depends on the command, credentials, input and network being usable; confirm the receiving status in YouTube after a controlled reboot.
Does network-online.target guarantee a connection to YouTube?
No. It is a wait point whose behaviour depends on the host's network manager and its matching wait-online service. It cannot prove that DNS, an external route, the YouTube ingest endpoint or your input source is available.
Should I use Restart=always or Restart=on-failure?
Choose based on whether a clean FFmpeg exit should lead to another launch. on-failure focuses on unsuccessful exits, while always also requests a restart after a clean exit; check the installed systemd.service(5) manual for the exact behaviour on your host.
What if the service is active but YouTube is not receiving the stream?
An active service means the process is running, not that it is producing a healthy output. Inspect the journal and FFmpeg progress, check the source and destination, and compare with Live Control Room; a restart policy may not act if FFmpeg remains alive but stalled.