Skip to content

How to Deploy Sonarr on a VPS

Updated Sep 2026

verified on Ubuntu 26.04 · Sep 2026
We earn commissions when you shop through the links below. Full disclosure →

Self-host Sonarr on a VPS with Docker Compose and HTTPS, using the single /data folder layout the Servarr wiki recommends so imports are instant hardlinks instead of slow copies.

Before you start
  • A VPS with 1 vCPU / 1 GB RAM or more (Sonarr itself needs about 512 MB)
  • Enough disk for downloads and the finished TV library, on one filesystem
  • A fresh Ubuntu 24.04 or 26.04 server with root/sudo SSH access
  • A domain you can point at the server
  • Docker Engine + Compose installed (see the base guide below)
  • An indexer and a download client (Usenet or BitTorrent) to connect it to
Need a box for this guide? Kamatera's free tier lets you spin one up now.Start free on Kamatera → (opens in new tab)

What Sonarr is

Sonarr is a TV series library manager. You tell it which shows you follow; it watches your indexers' RSS feeds for new episodes, sends a matching release to your Usenet or BitTorrent download client, and when the download finishes it renames the files and moves them into your library, where a media server such as Jellyfin, Plex or Emby picks them up. It is GPL-3.0, written in C# / .NET with a React web UI.

Sonarr doesn't download anything by itself. It sits between two things you also need: an indexer (usually managed through Prowlarr) and a download client. Use it for content you have the right to download.

The install is one container. What decides whether the setup works well is the folder layout, which gets most of this guide.

Server sizing

On our test box (a GCP e2-standard-2 on Ubuntu 26.04), idle Sonarr used about 95 MB of RAM and 286 MB of disk. The catalog's floor is 512 MB of RAM, which covers library refreshes and imports.

  • 1 GB RAM / 1 vCPU — Sonarr alone, or with Prowlarr.
  • 2–4 GB RAM / 2 vCPU — Sonarr, Radarr, Prowlarr and a download client on the same box.

Disk decides the plan. Downloads and the finished library must live on the same filesystem (see the next section), and TV libraries are large. Storage-heavy plans or attached block storage are the usual answer on a VPS.

The folder layout that makes imports instant

This is the part most Sonarr guides get wrong, and the Servarr wiki spends a whole page on it.

Most Docker images, including the one used here, suggest separate mounts such as /tv and /downloads. Inside the container those look like two different filesystems, even when they're one disk on the host. That has two consequences:

  1. No hardlinks, no instant moves. Every import becomes a full copy and delete — slow, twice the disk I/O, and, for torrents you're still seeding, twice the disk space.
  2. Path mismatches. The download client reports a path such as /torrents/Show.S01E01/, which doesn't exist inside the Sonarr container, and you end up configuring Remote Path Mappings to patch over it.

The wiki's fix is one common volume, /data, mounted identically in every container, with downloads and media as subfolders:

/srv/data
├── torrents/tv      ← the torrent client saves here
├── usenet/tv        ← the Usenet client saves here
└── media/tv         ← Sonarr's root folder, what the media server reads

Sonarr gets the whole of /srv/data as /data. The download client gets /srv/data (or just its own subfolder) as /data too, so a path reported by one container means the same thing in the other. Create it now:

sudo mkdir -p /srv/data/torrents/tv /srv/data/usenet/tv /srv/data/media/tv
sudo chown -R $(id -u):$(id -g) /srv/data
sudo chmod -R 775 /srv/data

775 plus a UMASK of 002 is the wiki's recommendation when several containers share a group and each needs to write the others' files.

Where to host itaffiliate disclosure
Hetzner Cloudrun it on
2 vCPU · 4 GB RAM · 80 GB SSD · $23.59/mo
Get Hetzner Cloud (opens in new tab)
Contaboalso works on
4 vCPU · 8 GB RAM · 100 GB SSD · $4.95/mo
Get Contabo (opens in new tab)
Kamaterafree trial
1 vCPU · 1 GB RAM · 20 GB SSD · $4.00/mo
Start free on Kamatera → (opens in new tab)

Paid link — we earn a commission if you shop through it.

Prepare the server

This guide assumes Docker Engine and the Compose plugin are installed, along with a non-root user and a ufw firewall. If not, work through Docker & Compose on Ubuntu first.

sudo ufw allow OpenSSH
sudo ufw allow 80
sudo ufw allow 443
sudo ufw --force enable
sudo ufw status verbose

Install Sonarr (Docker Compose)

This guide uses the linuxserver.io image, one of the two images the Servarr wiki lists. It takes PUID/PGID to run as your user; record your IDs in a .env file:

mkdir -p ~/sonarr && cd ~/sonarr
mkdir -p config
printf 'PUID=%s\nPGID=%s\n' "$(id -u)" "$(id -g)" > .env
cd ~/sonarr
cat > docker-compose.yml <<'YAML'
services:
  sonarr:
    image: lscr.io/linuxserver/sonarr:latest
    container_name: sonarr
    environment:
      - PUID=${PUID}
      - PGID=${PGID}
      - UMASK=002
      - TZ=Etc/UTC
    volumes:
      - ./config:/config
      # One volume for downloads AND library, so imports are hardlinks.
      - /srv/data:/data
    ports:
      # Loopback only — Caddy is the sole route in from outside.
      - "127.0.0.1:8989:8989"
    restart: unless-stopped
YAML
docker compose up -d

Wait for it and check it's up:

cd ~/sonarr
for i in $(seq 1 60); do curl -fsS -o /dev/null http://127.0.0.1:8989/ping && break; sleep 2; done
curl -s http://127.0.0.1:8989/ping; echo
docker compose ps

When you add your download client later, give it the same - /srv/data:/data mount (or /srv/data/torrents:/data/torrents) and point its save folder at /data/torrents/tv. If you put it in this compose file, Sonarr reaches it by service name.

HTTPS + domain

Point an A record for sonarr.example.com at the server's public IP, wait for it to resolve, then put Caddy in front — see Automatic HTTPS with Caddy:

sonarr.example.com {
    reverse_proxy 127.0.0.1:8989
}

If Caddy runs as a container, share a compose file and use reverse_proxy sonarr:8989 instead of 127.0.0.1.

First run

Open https://sonarr.example.com. A new install asks you to set up authentication before anything else. Choose Forms (Login Page), create the username and password, and leave Authentication Required on Enabled. The wiki notes that None is no longer selectable for new installs.

Then, in order:

  1. Settings → Media Management → Root Folders — add /data/media/tv.
  2. Settings → Download Clients — add your client, using the path it sees (/data/torrents/tv or /data/usenet/tv). With the single-volume layout you don't need a Remote Path Mapping.
  3. Indexers — add them here, or let Prowlarr sync them into Sonarr.
  4. Series → Add New — add a show and watch it search.

Securing it

  • Keep Authentication Required on Enabled. The alternative, Disabled for Local Addresses, trusts requests that look local. The wiki documents a high-severity issue (CVE-2026-30975, fixed in v4.0.16.2944) where a spoofed X-Forwarded-For header could make a remote request look local. If you ever use that mode, list your proxy under Trusted Networks.
  • Treat the API key as a password. Prowlarr and other tools use it, and it gives full control of Sonarr. It's under Settings → General.
  • Keep port 8989 on loopback. The compose file never publishes it.

Backups

Sonarr makes its own database backups — by default every 7 days, kept for 28 days — and System → Backup → Backup Now makes one on demand. Those backups are stored with the config on the same disk, so also take a copy of the whole config folder and move it off the box:

cd ~/sonarr
docker compose stop
sudo tar czf sonarr-config-$(date +%F).tar.gz config docker-compose.yml .env
docker compose start

Stopping the container first gives a consistent copy of the SQLite database. To restore, use System → Backup → Restore Backup with a Sonarr zip, or put the config folder back before starting the container. The media library is separate and should be backed up like any other large files.

Upgrades

cd ~/sonarr
docker compose pull
docker compose up -d

Sonarr's in-app updater doesn't apply to Docker; the wiki notes that a container update needs a new image. Back up first, since database migrations run on startup.

Troubleshooting

Imports are slow, or disk use doubles. Hardlinks aren't happening. Check that Sonarr and the download client both see the files under /data and that the root folder is /data/media/tv. Separate /tv and /downloads mounts cause exactly this.

"Path does not exist" on import. The download client reports a path Sonarr can't see. Mount /srv/data the same way in both containers, instead of adding a Remote Path Mapping.

Permission denied on import. Files were created by a different user or with a restrictive umask. Check with ls -ln /srv/data/torrents/tv that the IDs match .env, and set UMASK=002 on the download client as well.

Sonarr won't start after an upgrade. Read the log:

cd ~/sonarr
docker compose logs --tail 50 sonarr

Verification + next steps

You're done when you can load https://sonarr.example.com over a valid certificate, sign in on the login page, add a series, see a release grabbed by your download client, and find the renamed episode under /srv/data/media/tv afterwards — with ls -li showing the same inode number as the downloaded file.

Next: Radarr does the same for films on the same /data layout, Bazarr adds subtitles, and Jellyfin serves the result. Mount /srv/data/media into the media server, read-only.

Next steps

How to self-host Sonarr →More self-hosted media automation tools →Automatic HTTPS with Caddy →Run Claude Code with Ollama on Your Own VPS →Deploy Coolify on a VPS →How to Deploy Actual Budget on a VPS →How to Deploy AnythingLLM on a VPS →How to Deploy Appwrite on a VPS →How to Deploy Audiobookshelf on a VPS →How to Deploy Authelia on a VPS →How to Deploy authentik on a VPS →How to Deploy Baserow on a VPS →How to Deploy Beszel on a VPS →How to Deploy Bitwarden on a VPS →How to Deploy BookStack on a VPS →How to Deploy CapRover on a VPS →How to Deploy Checkmate on a VPS →How to Deploy Directus on a VPS →How to Deploy docker-mailserver on a VPS →How to Deploy Docmost on a VPS →How to Deploy Dokku on a VPS →How to Deploy Dokploy on a VPS →How to Deploy Firefly III on a VPS →How to Deploy Forgejo on a VPS →How to Deploy Gatus on a VPS →How to Deploy Ghostfolio on a VPS →How to Deploy Gitea on a VPS →How to Deploy GitLab on a VPS →How to Deploy GlitchTip on a VPS →How to Deploy Grafana on a VPS →How to Deploy Graylog on a VPS →How to Deploy Headscale on a VPS →How to Deploy Healthchecks on a VPS →How to Deploy Home Assistant on a VPS →How to Deploy Immich on a VPS →How to Deploy Jan on a VPS →How to Deploy Jellyfin on a VPS →How to Deploy Karakeep on a VPS →How to Deploy Keycloak on a VPS →How to Deploy Leantime on a VPS →How to Deploy LibreChat on a VPS →How to Deploy Linkwarden on a VPS →How to Deploy LocalAI on a VPS →How to Deploy Mailcow on a VPS →How to Deploy Mailu on a VPS →How to Deploy Matomo on a VPS →How to Deploy Mattermost on a VPS →How to Deploy Meilisearch on a VPS →How to Deploy Memos on a VPS →How to Deploy n8n on a VPS →How to Deploy Navidrome on a VPS →How to Deploy NetBird on a VPS →How to Deploy Netdata on a VPS →How to Deploy Nextcloud on a VPS →How to Deploy Next.js to a VPS →How to Deploy Nginx Proxy Manager on a VPS →How to Deploy NocoDB on a VPS →How to Deploy ntfy on a VPS →How to Deploy Ollama on a VPS →How to Deploy Open WebUI on a VPS →How to Deploy OpenHands on a VPS →How to Deploy OpenObserve on a VPS →How to Deploy OpenProject on a VPS →How to Deploy Outline on a VPS →How to Deploy Pangolin on a VPS →How to Deploy Paperless-ngx on a VPS →How to Deploy Passbolt on a VPS →How to Deploy Plane on a VPS →How to Deploy Plausible Analytics on a VPS →How to Deploy Pocket ID on a VPS →How to Deploy PocketBase on a VPS →How to Deploy Prometheus on a VPS →How to Deploy Psono on a VPS →How to Deploy Radarr on a VPS →How to Deploy Rocket.Chat on a VPS →How to Deploy SigNoz on a VPS →How to Deploy Stalwart on a VPS →How to Deploy Stirling-PDF on a VPS →How to Deploy Supabase on a VPS →How to Deploy Synapse on a VPS →How to Deploy Taiga on a VPS →How to Deploy TeamPass on a VPS →How to Deploy Tinyauth on a VPS →How to Deploy Traefik on a VPS →How to Deploy Trilium on a VPS →How to Deploy Twenty CRM on a VPS →How to Deploy Umami on a VPS →How to Deploy Uptime Kuma on a VPS →How to Deploy Vaultwarden on a VPS →How to Deploy Vikunja on a VPS →How to Deploy wg-easy on a VPS →How to Deploy Wiki.js on a VPS →How to Deploy Zabbix on a VPS →How to Deploy Zitadel on a VPS →How to Deploy Zulip on a VPS →Docker & Compose on Ubuntu 26.04 →Building AI Workflows with n8n →Install Open WebUI with Ollama →Adding AI-Powered Insights to Plausible Analytics →Building AI-Powered Apps with Supabase and pgvector →

We use analytics cookies (Google Analytics, PostHog) to see which guides are useful. No ad networks, no cross-site tracking. See our privacy policy.