If your Indian VPS reboots, a systemd service can start your FFmpeg playlist stream again without you logging in to launch it. That restarts the encoder process; it does not prove that YouTube has received the video or that viewers see it advancing.
Treat boot startup, process recovery and stream verification as separate jobs. The reliable workflow is to keep the command, media paths, service account and credentials consistent, then check both the server and YouTube after a planned reboot.
Decide what needs to restart
The thing systemd should manage is a foreground FFmpeg process that reads your playlist and sends output to YouTube. systemd can launch that process when the VPS reaches its normal boot target, and it can start the process again after certain exits if you configure a restart policy. Those are related settings, but they solve different problems.
Enabling a unit arranges for it to start during boot. Restart= describes what systemd does if the running process exits or times out. A service can be enabled yet fail to start because its command, files or credentials are wrong. Conversely, a command started manually can run now but not return after a reboot unless you arrange boot activation.
First establish what your playlist command actually does. If it is a repeating loop of local videos, systemd can manage the one FFmpeg process that runs the loop. If your workflow also schedules, creates or ends a YouTube broadcast, do not assume restarting FFmpeg handles those separate actions. Google describes live streams and live broadcasts as separate API resources in its broadcasts and streams documentation.
For an existing setup, write down the exact FFmpeg command, the playlist file location, the account that currently runs it, and where the stream key is stored. If you are still assembling the command, the FFmpeg setup for a 24/7 education stream is a relevant companion. This is also a good point to check that the media format and output settings suit your files; the encoding preset guide for a large YouTube loop playlist covers that separate concern.
Create a systemd unit for FFmpeg
A unit file gives systemd a durable description of how to run your command. The example below is a starting point, not a drop-in configuration: replace the account, paths, command and target for your VPS. It assumes FFmpeg runs in the foreground and that your playlist command already loops its media inputs.
[Unit]
Description=YouTube playlist stream
Wants=network-online.target
After=network-online.target
[Service]
Type=simple
User=streamer
WorkingDirectory=/srv/youtube-radio
ExecStart=/usr/bin/ffmpeg -re -stream_loop -1 -i /srv/youtube-radio/programme.mp4 -c:v copy -c:a copy -f flv rtmp://YOUR_INGEST_URL/YOUR_STREAM_KEY
Restart=on-failure
RestartSec=10
[Install]
WantedBy=multi-user.target
The command here illustrates the unit shape, not a universal FFmpeg recipe. -stream_loop -1 is suitable for a single input in this example; a playlist assembled with concat-demuxer lists needs a command and looping arrangement appropriate to that input. The output URL and protocol must match the current configuration in YouTube Live Control Room. Do not copy an example ingest address or assume RTMP, RTMPS and HLS settings are interchangeable.
User= selects the unprivileged Linux account that runs FFmpeg. WorkingDirectory= sets its starting directory, though using absolute file paths in the command makes file references easier to audit. ExecStart= should name the actual FFmpeg binary and command, with no shell-only shortcuts unless you deliberately invoke a shell and understand the implications.
Save the file under /etc/systemd/system/youtube-playlist.service if that name and location fit your system. Then ask systemd to reread unit files and enable and start the service:
sudo systemctl daemon-reload
sudo systemctl enable --now youtube-playlist.service
sudo systemctl status youtube-playlist.service
The --now option starts it immediately as well as enabling it for boot. The systemctl documentation explains the distinction between enabling a unit and starting it; check the systemctl reference for the installed systemd version and available commands. If the service fails, status gives a first clue and journalctl -u youtube-playlist.service shows its logs.
Choose a restart policy deliberately
For a long-running stream, Restart=on-failure is a reasonable starting policy: systemd tries to restart the process when it exits unsuccessfully, rather than treating an intentional clean exit as an error. RestartSec=10 adds a pause before a retry in this example. Adjust the delay and policy to your operating needs, and check the unit’s start-rate settings so a persistent configuration error does not turn into a rapid restart loop.
A reboot and a process failure are different events. The boot relationship in the [Install] section works with systemctl enable; Restart= does not itself make a service start at boot. Likewise, enabling a service does not automatically fix a process that exits after boot. Read systemd’s service unit reference before relying on a policy, since the installed version and other unit settings affect how it behaves.
There is another recovery layer inside FFmpeg. Its network output options can attempt recovery from some output failures while the process remains alive. That is not the same as systemd restarting an exited process, and neither mechanism proves the remote stream is healthy. The FFmpeg documentation describes options such as attempt_recovery and recovery wait settings; validate their syntax and compatibility against the FFmpeg build installed on your VPS.
| Layer | What it can do | What it cannot establish |
|---|---|---|
| Boot activation | Start the enabled unit as the machine boots | That FFmpeg can read its files or publish successfully |
| systemd restart policy | Relaunch the service after qualifying process exits | That a still-running process is sending advancing media |
| FFmpeg output recovery | Retry some network-output failures | That YouTube is displaying the intended broadcast |
| YouTube-side checks | Show ingest or playback state in YouTube’s interface | That your monitoring will catch every future failure |
Use the layers together where they suit your workflow, but do not treat any one of them as a complete health check. If a stream repeatedly fails and restarts, investigate the logs and cause rather than only increasing retries.
Check the user, paths and permissions
A command that worked in an interactive shell can fail as a service because systemd runs it as the account named in User= with that account’s permissions and environment. This is a common point of failure when a playlist lives in a home directory or on a mounted data volume. The service user must be able to traverse every parent directory and read the playlist and media files. It may also need permission to read a credentials file or write logs, depending on your configuration.
Use stable, explicit locations for a long-running setup. For example, if your media is under /srv/youtube-radio, ensure the streamer account can read that directory and its files. Avoid relying on a path such as /home/yourname/Videos unless you have deliberately granted the service user access and verified that the directory exists at boot. Check that any separate media disk is mounted before FFmpeg starts; an empty mount point can exist even when the expected files are not available.
You can test access as the service user rather than guessing from your own shell:
sudo -u streamer test -r /srv/youtube-radio/programme.mp4 && echo readable
sudo -u streamer test -r /srv/youtube-radio/playlist.txt && echo playlist-readable
Change these paths to your actual files. If you use a concat-demuxer file list, inspect its entries too: relative paths may be resolved from a different working directory than you expect. Prefer a stable working directory and paths that remain valid after reboot. A file list containing a typo may still let the service process start, while FFmpeg logs errors instead of publishing the expected sequence.
Check the service logs after a start and after a reboot. Messages about permission denied, missing files, invalid input or unavailable output are operational evidence, not noise to suppress. The guide to monitoring an unattended YouTube stream offers ideas for separating a running application from a stream that is actually progressing.
Keep credentials and playlist configuration consistent
The stream key is a credential. YouTube’s Live Control Room provides the stream URL and key for an encoder setup; consult the current YouTube encoder setup guidance rather than relying on a saved URL from an old setup. The key should be treated like a password: do not paste it into a public repository, a screenshot, or a public troubleshooting post.
Putting a key directly in ExecStart= is convenient but can expose it to people with permission to inspect unit files or process details. A more careful setup stores sensitive configuration in a root-owned file with restricted permissions, then references it using an appropriate systemd mechanism or a protected script. Do not assume that moving the key to an environment file makes it secret from every local administrator. Restrict access to the file and avoid printing its contents into logs.
Whatever storage method you choose, keep the configured ingest URL, protocol and key aligned with the stream you intend to use. A changed or revoked key can leave a healthy-looking FFmpeg process unable to publish. When YouTube shows a fresh stream configuration, update the service’s protected configuration, reload systemd if the unit changed, restart the service, and then check YouTube’s receipt status.
Playlist configuration needs the same discipline. Keep the list file at a stable path, ensure every referenced media file remains present and readable, and test the exact command under the service account. If you use a concat list, remember that changing a filename or moving a folder can break later entries even when the first file still plays. For workflows using different channels or programmes, keep their keys and files clearly separated; the article on separate YouTube live streams for multiple podcasts is useful context for that kind of separation.
Verify YouTube receipt after a restart
A successful systemctl status tells you about the local unit’s state. It is not a receipt from YouTube. After initial setup, and after a planned reboot, check the unit status and recent journal output, then open YouTube Live Control Room and confirm that it reports incoming media for the intended stream. Check the public playback separately if the broadcast is meant to be visible to viewers.
YouTube’s stream setup help explains the configuration choices in its interface. The available protocol and ingest settings may change, so verify the current values there rather than assuming a configuration from a previous session remains valid. If the interface reports no incoming data, review the key, URL, protocol, firewall or network path, and FFmpeg’s output errors.
Then verify that the video advances, not merely that a player opens. A page may load while the picture is frozen, or the stream may be delayed. Compare a changing scene, a visible clock in the source, or a known transition in the playlist with what the public player displays. For audio-led content, confirm the expected audio continues as well. This is a practical check, not proof that every viewer or device sees identical playback.
If your intended workflow expects an already-created broadcast to continue, distinguish that lifecycle from re-establishing encoder output. Restarting FFmpeg sends media again; it may not create, schedule, start or end the broadcast on your behalf. Confirm the broadcast state in YouTube’s own controls, especially if your process includes unattended scheduling.
Watch for failures that uptime misses
The hardest failure to notice is a process that remains active while useful media stops progressing. FFmpeg can remain present in the process list even if an input stalls, output has stopped advancing, or YouTube is no longer showing current frames. A systemd restart policy generally reacts to process exits and timeouts; it does not infer that the image has frozen.
The implementation report linked in the research notes describes one operator’s silent-freeze experience, in which local indicators continued while the YouTube stream appeared frozen. That account is a report from one setup, not evidence of a universal failure rate or a general cause. Its practical lesson is to check media progress independently of process uptime.
For a more robust arrangement, add a watchdog or external check that measures whether media is advancing and raises an alert when it is not. The exact signal depends on your command and content: a frame counter, a changing timestamp, a known playlist transition, or a remote player check may be useful, but none is universally suitable. A counter that increments locally may still not prove YouTube is displaying the frames, so pair local progress checks with YouTube-side receipt and playback checks.
Some operators schedule a preventive restart, but that is an operational choice rather than a guarantee. A scheduled restart can interrupt a healthy output, and it can reproduce the same configuration failure. Prefer evidence-led alerts and a tested recovery procedure. If you need remote checks because no one is watching the stream at night, the article about keeping a 24/7 YouTube stream running during power cuts in India provides related operational context, though power continuity and media-progress checks are separate issues.
Before relying on the service, test it during a planned maintenance window: stop it deliberately, observe how the chosen policy behaves, and reboot the VPS when interruption is acceptable. After it comes back, confirm the unit ran, the files were readable, YouTube received media, and the playback advanced. Keep a note of the last successful check and how to inspect the journal so another operator can follow the same sequence.
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 Restart=on-failure start FFmpeg after a VPS reboot?
No. Boot activation and failure restart are separate settings. Enable the service for the appropriate boot target, then use a restart policy for qualifying process exits.
If systemd says the service is active, is YouTube receiving the stream?
Not necessarily. Check the service logs, YouTube’s incoming-media status and the public playback, including whether the picture or audio advances.
Should I put my stream key in the unit file?
Avoid exposing it in a public repository or places accessible to people who should not have it. Use a protected configuration method with restricted permissions, and verify the current key and ingest details in YouTube Live Control Room.
Will restarting FFmpeg start the YouTube broadcast as well?
It restarts encoder output, not necessarily the broadcast lifecycle. YouTube treats stream and broadcast resources separately, so check the broadcast state and manage scheduling or start actions separately where your workflow requires them.