Lidarr next to an existing media pod

Lidarr as a standalone quadlet that joins an existing media stack without touching the pod.

  • Standalone container
  • Rootless: systemctl --user
  • Tested with podman 5.0 and newer

Last updated

In short: Adding a port to a running podman pod means recreating the pod and restarting every app in it. A new *arr app such as Lidarr can run as its own container instead: it publishes port 8686 itself, mounts the same /srv/media folder as /data, and reaches Prowlarr and NZBGet at host.containers.internal. On a fresh install, you can put it in the pod instead, as the media stack example shows.

The quadlet files

Every quadlet file below passes podman's quadlet generator and systemd-analyze verify on podman 5.0 and the current release. Personal values are placeholders: replace example.com, /srv/... paths and the time zone with your own.

lidarr.container

Save as ~/.config/containers/systemd/lidarr.container

[Unit]
Description=Lidarr music manager
StartLimitIntervalSec=0
After=network-online.target

[Container]
Image=lscr.io/linuxserver/lidarr:latest
ContainerName=lidarr
AutoUpdate=registry
Environment=TZ=Etc/UTC
# Standalone next to an existing media pod: adding a port to a running pod means
# recreating the pod. Lidarr reaches Prowlarr and NZBGet via host.containers.internal.
PublishPort=8686:8686
Volume=lidarr.volume:/config
# The same /data layout as the media pod, so download paths match and imports are
# instant moves or hardlinks.
Volume=/srv/media:/data
HealthCmd=curl -fsS -o /dev/null http://127.0.0.1:8686/ping
HealthInterval=1m
HealthTimeout=10s
HealthRetries=3
HealthStartPeriod=3m
HealthOnFailure=kill

[Service]
Restart=always
RestartSec=30
TimeoutStartSec=900

[Install]
WantedBy=default.target

lidarr.volume

Save as ~/.config/containers/systemd/lidarr.volume

[Unit]
Description=Lidarr config and database

[Volume]
VolumeName=lidarr

Caddyfile

Save as /etc/caddy/Caddyfile

lidarr.example.com {
	reverse_proxy 10.0.0.10:8686
}

Why is it built this way?

What it is. Lidarr does for music what Radarr does for films: it follows artists, finds releases through Prowlarr, sends them to NZBGet and files the result into your library.

Pod or standalone. The media stack pod shares one network namespace, so its apps talk over localhost. That is tidy until you add an app to a running stack: pod ports are fixed when the pod is created. This quadlet keeps Lidarr outside and uses host.containers.internal to reach the pod's published ports instead. Both shapes work; pick the one that fits your stack.

Same folders, same paths. Lidarr mounts /srv/media as /data, exactly like the apps in the pod. NZBGet reports a finished download as /data/downloads/..., and Lidarr finds it at that path and moves it within one filesystem, without copying.

Caddy in front of Lidarr

The *arr apps need nothing special behind Caddy. Keep their own login on (Settings, General, Authentication) because the page can start downloads. The Caddyfile generator writes the site block.

Check that it works

systemctl --user status lidarr.service
curl -s http://127.0.0.1:8686/ping; echo
# can Lidarr reach Prowlarr in the pod?
podman exec lidarr curl -fsS -o /dev/null -w '%{http_code}\n' http://host.containers.internal:9696/ping

See quadlet basics for how the generated lidarr.service works.

How do I start it?

Run these as your normal user, not as root. Quadlet reads ~/.config/containers/systemd/ for user services.

mkdir -p ~/.config/containers/systemd /srv/media/music
podman unshare chown 911:911 /srv/media/music
systemctl --user daemon-reload
systemctl --user start lidarr.service
# open http://<server>:8686: root folder /data/music
# download client NZBGet: host host.containers.internal, port 6789
# in Prowlarr: add Lidarr at http://host.containers.internal:8686 with Lidarr's API key

Check the result with systemctl --user status and the logs with journalctl --user -u followed by the service name. To turn a docker-compose file of your own into files like these, use the compose to quadlet converter.

Common mistakes

Lidarr cannot import: the download path does not exist

Lidarr must see finished downloads at the same path as NZBGet. Both mount /srv/media as /data here, so /data/downloads is the same folder in both. Do not add a separate /downloads mount.

Prowlarr cannot reach Lidarr at localhost:8686

Prowlarr runs in the media pod, where localhost means the pod. Lidarr is outside it, so use http://host.containers.internal:8686 in Prowlarr, and host.containers.internal:9696 for Prowlarr in Lidarr.

PublishPort= is refused when I add Lidarr to the pod

A container inside a pod cannot publish ports; the pod does. Add PublishPort=8686:8686 to media.pod and recreate the pod with systemctl --user restart media-pod.service, or run Lidarr standalone as shown here.

Frequently asked questions

Why not add Lidarr to the media pod?

You can, and on a new install that is the neater shape. On a running stack, a new port on the pod means recreating it, which restarts every download and import in progress. A standalone container joins without touching the others.

Does the same approach work for Readarr or other *arr apps?

Yes. Copy the quadlet, change the image, container name, port, volume name and health check path, and keep the shared /srv/media:/data mount so imports stay instant.