pages/posts/docker-arr-stack-guide/index.html
2024-03-16 03:43:34 +00:00

750 lines
39 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<!DOCTYPE html>
<html lang="en" dir="auto">
<head><meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<meta name="robots" content="index, follow">
<title>Docker Compose Arr Stack Guide | Mafyuh&#39;s Blog</title>
<meta name="keywords" content="Homelab">
<meta name="description" content="This guide is for someone who is looking to setup an Arr Stack for media organization and downloading. This guide requires no remote path mappings, follows Trash-Guides recommendations and every command needed is copy-pasteable. The VM&rsquo;s in this guide are hosted on Proxmox 8.1.4, but you can use any Ubuntu environment (WSL-2, VirtualBox, etc.)
Arr VM Specs:
2 core host 8GB RAM 100GB Storage Downloader VM Specs:
2 core host 4GB RAM 250GB Storage (can download up to this limit at a time, be careful when mass downloading or give plenty of space) Prerequisites Ubuntu 22.">
<meta name="author" content="Matt">
<link rel="canonical" href="https://mafyuh.com/posts/docker-arr-stack-guide/">
<link crossorigin="anonymous" href="/assets/css/stylesheet.b609c58d5c11bb90b1a54e04005d74ad1ddf22165eb79f5533967e57df9c3b50.css" integrity="sha256-tgnFjVwRu5CxpU4EAF10rR3fIhZet59VM5Z&#43;V9&#43;cO1A=" rel="preload stylesheet" as="style">
<link rel="icon" href="https://mafyuh.com/assets/favicon/favicon.ico">
<link rel="icon" type="image/png" sizes="16x16" href="https://mafyuh.com/assets/favicon/favicon-16x16.png">
<link rel="icon" type="image/png" sizes="32x32" href="https://mafyuh.com/assets/favicon/favicon-32x32.png">
<link rel="apple-touch-icon" href="https://mafyuh.com/assets/favicon/apple-touch-icon.png">
<link rel="mask-icon" href="https://mafyuh.com/safari-pinned-tab.svg">
<meta name="theme-color" content="#2e2e33">
<meta name="msapplication-TileColor" content="#2e2e33">
<link rel="alternate" hreflang="en" href="https://mafyuh.com/posts/docker-arr-stack-guide/">
<noscript>
<style>
#theme-toggle,
.top-link {
display: none;
}
</style>
<style>
@media (prefers-color-scheme: dark) {
:root {
--theme: rgb(29, 30, 32);
--entry: rgb(46, 46, 51);
--primary: rgb(218, 218, 219);
--secondary: rgb(155, 156, 157);
--tertiary: rgb(65, 66, 68);
--content: rgb(196, 196, 197);
--code-block-bg: rgb(46, 46, 51);
--code-bg: rgb(55, 56, 62);
--border: rgb(51, 51, 51);
}
.list {
background: var(--theme);
}
.list:not(.dark)::-webkit-scrollbar-track {
background: 0 0;
}
.list:not(.dark)::-webkit-scrollbar-thumb {
border-color: var(--theme);
}
}
</style>
</noscript><script defer data-domain="mafyuh.com" src="https://stats.mafyuh.com/js/script.js"></script>
<meta property="og:title" content="Docker Compose Arr Stack Guide" />
<meta property="og:description" content="This guide is for someone who is looking to setup an Arr Stack for media organization and downloading. This guide requires no remote path mappings, follows Trash-Guides recommendations and every command needed is copy-pasteable. The VM&rsquo;s in this guide are hosted on Proxmox 8.1.4, but you can use any Ubuntu environment (WSL-2, VirtualBox, etc.)
Arr VM Specs:
2 core host 8GB RAM 100GB Storage Downloader VM Specs:
2 core host 4GB RAM 250GB Storage (can download up to this limit at a time, be careful when mass downloading or give plenty of space) Prerequisites Ubuntu 22." />
<meta property="og:type" content="article" />
<meta property="og:url" content="https://mafyuh.com/posts/docker-arr-stack-guide/" /><meta property="article:section" content="posts" />
<meta property="article:published_time" content="2024-02-23T00:13:40+00:00" />
<meta property="article:modified_time" content="2024-02-23T00:13:40+00:00" /><meta property="og:site_name" content="Mafyuh&#39;s Blog" />
<meta name="twitter:card" content="summary"/>
<meta name="twitter:title" content="Docker Compose Arr Stack Guide"/>
<meta name="twitter:description" content="This guide is for someone who is looking to setup an Arr Stack for media organization and downloading. This guide requires no remote path mappings, follows Trash-Guides recommendations and every command needed is copy-pasteable. The VM&rsquo;s in this guide are hosted on Proxmox 8.1.4, but you can use any Ubuntu environment (WSL-2, VirtualBox, etc.)
Arr VM Specs:
2 core host 8GB RAM 100GB Storage Downloader VM Specs:
2 core host 4GB RAM 250GB Storage (can download up to this limit at a time, be careful when mass downloading or give plenty of space) Prerequisites Ubuntu 22."/>
<script type="application/ld+json">
{
"@context": "https://schema.org",
"@type": "BreadcrumbList",
"itemListElement": [
{
"@type": "ListItem",
"position": 1 ,
"name": "Posts",
"item": "https://mafyuh.com/posts/"
},
{
"@type": "ListItem",
"position": 2 ,
"name": "Docker Compose Arr Stack Guide",
"item": "https://mafyuh.com/posts/docker-arr-stack-guide/"
}
]
}
</script>
<script type="application/ld+json">
{
"@context": "https://schema.org",
"@type": "BlogPosting",
"headline": "Docker Compose Arr Stack Guide",
"name": "Docker Compose Arr Stack Guide",
"description": "This guide is for someone who is looking to setup an Arr Stack for media organization and downloading. This guide requires no remote path mappings, follows Trash-Guides recommendations and every command needed is copy-pasteable. The VM\u0026rsquo;s in this guide are hosted on Proxmox 8.1.4, but you can use any Ubuntu environment (WSL-2, VirtualBox, etc.)\nArr VM Specs:\n2 core host 8GB RAM 100GB Storage Downloader VM Specs:\n2 core host 4GB RAM 250GB Storage (can download up to this limit at a time, be careful when mass downloading or give plenty of space) Prerequisites Ubuntu 22.",
"keywords": [
"Homelab"
],
"articleBody": "This guide is for someone who is looking to setup an Arr Stack for media organization and downloading. This guide requires no remote path mappings, follows Trash-Guides recommendations and every command needed is copy-pasteable. The VMs in this guide are hosted on Proxmox 8.1.4, but you can use any Ubuntu environment (WSL-2, VirtualBox, etc.)\nArr VM Specs:\n2 core host 8GB RAM 100GB Storage Downloader VM Specs:\n2 core host 4GB RAM 250GB Storage (can download up to this limit at a time, be careful when mass downloading or give plenty of space) Prerequisites Ubuntu 22.04 Any Usenet Server Subscription (preferred) Any Usenet Indexer Subscription (preferred) Real-Debrid Subscription (if you like torrents being fast) VPN Subscription (Bare minimum needed to download torrents) Folder Structure Setup Run this command to make all folders, following TRASH-guides recommended naming scheme:\nsudo mkdir -p /data/torrents/{books,movies,music,tv} /data/usenet/{incomplete,complete/{books,movies,music,tv}} /data/media/{books,movies,music,tv} Mounting NAS I use my NAS for storing all my content, this allows me to have 1 spot to have everything saved too, and not getting tripped up with different file systems. You do not need a NAS, and can just skip this part of guide and use the local filesystem. I use TrueNAS Scale with SMB. In order to mount SMB shares to Linux filesystem we need to install CIFS:\nsudo apt install cifs-utils -y then we need to tell the system which directory to map it to, to do this:\nsudo nano /etc/fstab at the end of the file, add an entry for your NAS as such:\n/// /data/media cifs username=,password=,uid=1000,gid=1000,auto,nofail 0 0 be sure to replace your credentials.\nTo mount your NAS, you can run:\nsudo mount -a then run the following to make sure your NAS is mounted:\nls /data/media Everything in your NAS should be showing now, but we need to set permissions, to do that run:\nsudo chown -R $USER:$USER /data sudo chmod -R a=,a+rX,u+w,g+w /data Install Docker Now we have to install Docker, I use this command to install Docker and Docker Engine:\ncurl -fsSL https://get.docker.com | sudo sh Now that docker is installed, we can add our user to the docker group so we dont have to use sudo every command:\nsudo usermod -aG docker $USER Now I would make a docker directory to store all your appdata, you can use your home directory if you want, but trash-guides recommend not doing so:\nsudo mkdir -p /docker/appdata/{radarr,sonarr,bazarr,prowlarr,lidarr,sabnzbd,qbitty,rdt} Then set permissions on the docker directory:\nsudo chown -R $USER:$USER /docker sudo chmod -R a=,a+rX,u+w,g+w /docker 2 VM Setup I have my downloaders (Sab, Qbitty, Rdt-client) on a different VM than my ARRs, this is cause when I had everything on 1 docker host, I would have constant HTTP errors from Sab mainly, and as Sab is where I get most of my media, I decided to move to another VM, and then SMB share the download directories over to my ARRs VM.\nYou do not have to do this, you can just have 1 docker host, up to you. It is alot less work to do all in one 1 VM.\nIf you do this, you need to replicate the origin setup, making all the same directories, then run:\nsudo apt update sudo apt install samba We need to configure Samba to tell it what we are sharing:\nsudo nano /etc/samba/smb.conf Add the following at the end of this file:\n[usenet] path = /data/usenet read only = no guest ok = no create mask = 0755 [torrents] path = /data/torrents read only = no guest ok = no create mask = 0755 To create your username and password, replace your_username with your actual username:\nsudo smbpasswd -a your_username Then restart samba with:\nsudo systemctl restart smbd Go back to your Arr VM and add the following to your /etc/fstab:\n///usenet /data/usenet cifs username=,password=,uid=1000,gid=1000,auto,nofail 0 0 ///torrents /data/torrents cifs username=,password=,uid=1000,gid=1000,auto,nofail 0 0 Mount them with:\nsudo mount -a Then re-run our permissions command:\nsudo chown -R $USER:$USER /data sudo chmod -R a=,a+rX,u+w,g+w /data I would reboot this VM at this point, this will make sure it auto connects to our SMB shares at boot.\nDocker Compose Files Now that everything is setup, we can actually install the services:\nOne VM This is a full docker compose file for pretty much all major Arrs and downloaders I use. I threw Lidarr in here as well, as I run Lidarr for music, but if you dont care about music you can remove lidarr:\nversion: \"3.9\" services: sabnzbd: image: lscr.io/linuxserver/sabnzbd:latest container_name: sabnzbd environment: - PUID=1000 - PGID=1000 - TZ=Etc/UTC volumes: - /etc/localtime:/etc/localtime:ro - /docker/appdata/sabnzbd:/config - /data/usenet:/data/usenet:rw ports: - 8080:8080 restart: unless-stopped arch-qbittorrentvpn: image: binhex/arch-qbittorrentvpn:latest container_name: qbittorrentvpn volumes: - '/docker/appdata/qbitty:/config' - '/data/torrents/:/data/torrents' - '/etc/localtime:/etc/localtime:ro' ports: - '49550:49550' - '49551:8118' environment: - VPN_ENABLED=yes - VPN_PROV=protonvpn - VPN_CLIENT=wireguard - VPN_USER=username+pmp - VPN_PASS= - STRICT_PORT_FORWARD=yes - LAN_NETWORK=10.0.0.0/24 - ENABLE_PRIVOXY=yes - PUID=1000 - PGID=1000 - WEBUI_PORT=49550 - UMASK=1000 - DEBUG=false cap_add: - NET_ADMIN sysctls: - net.ipv4.conf.all.src_valid_mark=1 privileged: true network_mode: bridge restart: unless-stopped rdtclient: container_name: rdtclient volumes: - '/data/torrents:/data/torrents' - '/docker/appdata/rdt:/data/db' image: rogerfar/rdtclient restart: always logging: driver: json-file options: max-size: 10m ports: - '6500:6500' bazarr: image: lscr.io/linuxserver/bazarr:latest ports: - \"6767:6767\" volumes: - /etc/localtime:/etc/localtime:ro - /docker/appdata/bazarr:/config - /data/media:/data/media restart: unless-stopped environment: - PUID=1000 - PGID=1000 lidarr: image: lscr.io/linuxserver/lidarr:latest ports: - \"8686:8686\" volumes: - /etc/localtime:/etc/localtime:ro - /docker/appdata/lidarr:/config - /data:/data restart: unless-stopped environment: - PUID=1000 - PGID=1000 prowlarr: image: lscr.io/linuxserver/prowlarr:latest ports: - \"9696:9696\" volumes: - /docker/appdata/prowlarr:/config restart: unless-stopped environment: - PUID=1000 - PGID=1000 radarr: image: lscr.io/linuxserver/radarr:latest ports: - \"7878:7878\" volumes: - /etc/localtime:/etc/localtime:ro - /docker/appdata/radarr:/config - /data:/data restart: unless-stopped environment: - PUID=1000 - PGID=1000 sonarr: image: lscr.io/linuxserver/sonarr:latest ports: - \"8989:8989\" volumes: - /etc/localtime:/etc/localtime:ro - /docker/appdata/sonarr:/config - /data:/data restart: unless-stopped environment: - PUID=1000 - PGID=1000 networks: default: name: arrs_default 2 VM Arrs:\nversion: \"3.7\" services: bazarr: image: lscr.io/linuxserver/bazarr:latest ports: - \"6767:6767\" volumes: - /etc/localtime:/etc/localtime:ro - /docker/appdata/bazarr:/config - /data/media:/data/media restart: unless-stopped environment: - PUID=1000 - PGID=1000 lidarr: image: lscr.io/linuxserver/lidarr:latest ports: - \"8686:8686\" volumes: - /etc/localtime:/etc/localtime:ro - /docker/appdata/lidarr:/config - /data:/data restart: unless-stopped environment: - PUID=1000 - PGID=1000 prowlarr: image: lscr.io/linuxserver/prowlarr:latest ports: - \"9696:9696\" volumes: - /docker/appdata/prowlarr:/config restart: unless-stopped environment: - PUID=1000 - PGID=1000 radarr: image: lscr.io/linuxserver/radarr:latest ports: - \"7878:7878\" volumes: - /etc/localtime:/etc/localtime:ro - /docker/appdata/radarr:/config - /data:/data restart: unless-stopped environment: - PUID=1000 - PGID=1000 sonarr: image: lscr.io/linuxserver/sonarr:latest ports: - \"8989:8989\" volumes: - /etc/localtime:/etc/localtime:ro - /docker/appdata/sonarr:/config - /data:/data restart: unless-stopped environment: - PUID=1000 - PGID=1000 networks: default: name: arrs_default Downloaders: As stated previously, Sab downloads most of my content (95%), you do not need all 3 of these, you can just copy the Sab part and just use Usenet with Sab. But I like to have a variety.\nversion: '3.9' services: sabnzbd: image: lscr.io/linuxserver/sabnzbd:latest container_name: sabnzbd environment: - PUID=1000 - PGID=1000 - TZ=Etc/UTC volumes: - /etc/localtime:/etc/localtime:ro - /docker/appdata/sabnzbd:/config - /data/usenet:/data/usenet:rw ports: - 8080:8080 restart: unless-stopped arch-qbittorrentvpn: image: binhex/arch-qbittorrentvpn:latest container_name: qbittorrentvpn volumes: - '/docker/appdata/qbitty:/config' - '/data/torrents/:/data/torrents' - '/etc/localtime:/etc/localtime:ro' ports: - '49550:49550' - '49551:8118' environment: - VPN_ENABLED=yes - VPN_PROV=protonvpn - VPN_CLIENT=wireguard - VPN_USER=username+pmp - VPN_PASS= - STRICT_PORT_FORWARD=yes - LAN_NETWORK=10.0.0.0/24 - ENABLE_PRIVOXY=yes - PUID=1000 - PGID=1000 - WEBUI_PORT=49550 - UMASK=1000 - DEBUG=false cap_add: - NET_ADMIN sysctls: - net.ipv4.conf.all.src_valid_mark=1 privileged: true network_mode: bridge restart: unless-stopped rdtclient: container_name: rdtclient volumes: - '/data/torrents:/data/torrents' - '/docker/appdata/rdt:/data/db' image: rogerfar/rdtclient restart: always logging: driver: json-file options: max-size: 10m ports: - '6500:6500' Running Docker Compose Files In order to run these files, it depends on which option you chose, if 1 VM setup, just copy the compose file and create a new docker-compose.yml file with:\nnano docker-compose.yml Paste in the content, CTRL + X to exit nano, Y to save, ENTER to keep filename. Then run:\ndocker compose up -d If you are using 2 VMs, you need to do this 2x. One for each docker-compose file.\nConclusion Congratulations on setting up your media library backend! We now have to go and configure all these services to work together, which I have another full blog post on which you can find here.\n",
"wordCount" : "1305",
"inLanguage": "en",
"datePublished": "2024-02-23T00:13:40Z",
"dateModified": "2024-02-23T00:13:40Z",
"author":{
"@type": "Person",
"name": "Matt"
},
"mainEntityOfPage": {
"@type": "WebPage",
"@id": "https://mafyuh.com/posts/docker-arr-stack-guide/"
},
"publisher": {
"@type": "Organization",
"name": "Mafyuh's Blog",
"logo": {
"@type": "ImageObject",
"url": "https://mafyuh.com/assets/favicon/favicon.ico"
}
}
}
</script>
</head>
<body class="" id="top">
<script>
if (localStorage.getItem("pref-theme") === "dark") {
document.body.classList.add('dark');
} else if (localStorage.getItem("pref-theme") === "light") {
document.body.classList.remove('dark')
} else if (window.matchMedia('(prefers-color-scheme: dark)').matches) {
document.body.classList.add('dark');
}
</script>
<header class="header">
<nav class="nav">
<div class="logo">
<a href="https://mafyuh.com/" accesskey="h" title="Mafyuh&#39;s Blog (Alt + H)">
<img src="https://mafyuh.com/assets/favicon/favicon.svg" alt="" aria-label="logo"
height="35">Mafyuh&#39;s Blog</a>
<div class="logo-switches">
<button id="theme-toggle" accesskey="t" title="(Alt + T)">
<svg id="moon" xmlns="http://www.w3.org/2000/svg" width="24" height="18" viewBox="0 0 24 24"
fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"
stroke-linejoin="round">
<path d="M21 12.79A9 9 0 1 1 11.21 3 7 7 0 0 0 21 12.79z"></path>
</svg>
<svg id="sun" xmlns="http://www.w3.org/2000/svg" width="24" height="18" viewBox="0 0 24 24"
fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"
stroke-linejoin="round">
<circle cx="12" cy="12" r="5"></circle>
<line x1="12" y1="1" x2="12" y2="3"></line>
<line x1="12" y1="21" x2="12" y2="23"></line>
<line x1="4.22" y1="4.22" x2="5.64" y2="5.64"></line>
<line x1="18.36" y1="18.36" x2="19.78" y2="19.78"></line>
<line x1="1" y1="12" x2="3" y2="12"></line>
<line x1="21" y1="12" x2="23" y2="12"></line>
<line x1="4.22" y1="19.78" x2="5.64" y2="18.36"></line>
<line x1="18.36" y1="5.64" x2="19.78" y2="4.22"></line>
</svg>
</button>
<ul class="lang-switch"><li>|</li>
</ul>
</div>
</div>
<ul id="menu">
<li>
<a href="https://mafyuh.com/tags/" title="Tags">
<span>Tags</span>
</a>
</li>
<li>
<a href="https://mafyuh.com/archives/" title="Archives">
<span>Archives</span>
</a>
</li>
<li>
<a href="https://mafyuh.com/search/" title="Search (Alt &#43; /)" accesskey=/>
<span>Search</span>
</a>
</li>
</ul>
</nav>
</header>
<main class="main">
<article class="post-single">
<header class="post-header">
<div class="breadcrumbs"><a href="https://mafyuh.com/">Home</a>&nbsp;»&nbsp;<a href="https://mafyuh.com/posts/">Posts</a></div>
<h1 class="post-title entry-hint-parent">
Docker Compose Arr Stack Guide
</h1>
<div class="post-meta"><span title='2024-02-23 00:13:40 +0000 UTC'>February 23, 2024</span>&nbsp;·&nbsp;7 min&nbsp;·&nbsp;1305 words&nbsp;·&nbsp;Matt
</div>
</header> <div class="toc">
<details >
<summary accesskey="c" title="(Alt + C)">
<span class="details">Table of Contents</span>
</summary>
<div class="inner"><nav id="TableOfContents">
<ul>
<li>
<ul>
<li><a href="#prerequisites">Prerequisites</a></li>
</ul>
</li>
<li><a href="#folder-structure-setup">Folder Structure Setup</a></li>
<li><a href="#mounting-nas">Mounting NAS</a>
<ul>
<li><a href="#install-docker">Install Docker</a></li>
</ul>
</li>
<li><a href="#2-vm-setup">2 VM Setup</a></li>
<li><a href="#docker-compose-files">Docker Compose Files</a>
<ul>
<li><a href="#one-vm">One VM</a></li>
<li><a href="#2-vm">2 VM</a></li>
</ul>
</li>
<li><a href="#running-docker-compose-files">Running Docker Compose Files</a></li>
<li><a href="#conclusion">Conclusion</a></li>
</ul>
</nav>
</div>
</details>
</div>
<div class="post-content"><p>This guide is for someone who is looking to setup an Arr Stack for media organization and downloading. This guide requires no remote path mappings, follows Trash-Guides recommendations and every command needed is copy-pasteable. The VM&rsquo;s in this guide are hosted on Proxmox 8.1.4, but you can use any Ubuntu environment (WSL-2, VirtualBox, etc.)</p>
<p>Arr VM Specs:</p>
<ul>
<li>2 core host</li>
<li>8GB RAM</li>
<li>100GB Storage</li>
</ul>
<p>Downloader VM Specs:</p>
<ul>
<li>2 core host</li>
<li>4GB RAM</li>
<li>250GB Storage (can download up to this limit at a time, be careful when mass downloading or give plenty of space)</li>
</ul>
<h3 id="prerequisites">Prerequisites<a hidden class="anchor" aria-hidden="true" href="#prerequisites">#</a></h3>
<ul>
<li>Ubuntu 22.04</li>
<li>Any Usenet Server Subscription (preferred)</li>
<li>Any Usenet Indexer Subscription (preferred)</li>
<li>Real-Debrid Subscription (if you like torrents being fast)</li>
<li>VPN Subscription (Bare minimum needed to download torrents)</li>
</ul>
<h2 id="folder-structure-setup">Folder Structure Setup<a hidden class="anchor" aria-hidden="true" href="#folder-structure-setup">#</a></h2>
<p>Run this command to make all folders, following <a href="https://trash-guides.info/Hardlinks/How-to-setup-for/Docker/">TRASH-guides recommended naming scheme</a>:</p>
<pre tabindex="0"><code>sudo mkdir -p /data/torrents/{books,movies,music,tv} /data/usenet/{incomplete,complete/{books,movies,music,tv}} /data/media/{books,movies,music,tv}
</code></pre><h2 id="mounting-nas">Mounting NAS<a hidden class="anchor" aria-hidden="true" href="#mounting-nas">#</a></h2>
<p>I use my NAS for storing all my content, this allows me to have 1 spot to have everything saved too, and not getting tripped up with different file systems. You do not need a NAS, and can just skip this part of guide and use the local filesystem. I use TrueNAS Scale with SMB. In order to mount SMB shares to Linux filesystem we need to install CIFS:</p>
<pre tabindex="0"><code>sudo apt install cifs-utils -y
</code></pre><p>then we need to tell the system which directory to map it to, to do this:</p>
<pre tabindex="0"><code>sudo nano /etc/fstab
</code></pre><p>at the end of the file, add an entry for your NAS as such:</p>
<pre tabindex="0"><code>//&lt;NAS IP&gt;/&lt;NAS Share&gt; /data/media cifs username=&lt;user&gt;,password=&lt;pass&gt;,uid=1000,gid=1000,auto,nofail 0 0
</code></pre><p>be sure to replace your credentials.</p>
<p>To mount your NAS, you can run:</p>
<pre tabindex="0"><code>sudo mount -a
</code></pre><p>then run the following to make sure your NAS is mounted:</p>
<pre tabindex="0"><code>ls /data/media
</code></pre><p>Everything in your NAS should be showing now, but we need to set permissions, to do that run:</p>
<pre tabindex="0"><code>sudo chown -R $USER:$USER /data
sudo chmod -R a=,a+rX,u+w,g+w /data
</code></pre><h3 id="install-docker">Install Docker<a hidden class="anchor" aria-hidden="true" href="#install-docker">#</a></h3>
<p>Now we have to install Docker, I use this command to install Docker and Docker Engine:</p>
<pre tabindex="0"><code>curl -fsSL https://get.docker.com | sudo sh
</code></pre><p>Now that docker is installed, we can add our user to the docker group so we dont have to use sudo every command:</p>
<pre tabindex="0"><code>sudo usermod -aG docker $USER
</code></pre><p>Now I would make a docker directory to store all your appdata, you can use your home directory if you want, but trash-guides recommend not doing so:</p>
<pre tabindex="0"><code>sudo mkdir -p /docker/appdata/{radarr,sonarr,bazarr,prowlarr,lidarr,sabnzbd,qbitty,rdt}
</code></pre><p>Then set permissions on the docker directory:</p>
<pre tabindex="0"><code>sudo chown -R $USER:$USER /docker
sudo chmod -R a=,a+rX,u+w,g+w /docker
</code></pre><h2 id="2-vm-setup">2 VM Setup<a hidden class="anchor" aria-hidden="true" href="#2-vm-setup">#</a></h2>
<p>I have my downloaders (Sab, Qbitty, Rdt-client) on a different VM than my ARR&rsquo;s, this is cause when I had everything on 1 docker host, I would have constant HTTP errors from Sab mainly, and as Sab is where I get most of my media, I decided to move to another VM, and then SMB share the download directories over to my ARR&rsquo;s VM.</p>
<p>You do not have to do this, you can just have 1 docker host, up to you. It is alot less work to do all in one 1 VM.</p>
<p>If you do this, you need to replicate the origin setup, making all the same directories, then run:</p>
<pre tabindex="0"><code>sudo apt update
sudo apt install samba
</code></pre><p>We need to configure Samba to tell it what we are sharing:</p>
<pre tabindex="0"><code>sudo nano /etc/samba/smb.conf
</code></pre><p>Add the following at the end of this file:</p>
<pre tabindex="0"><code>[usenet]
path = /data/usenet
read only = no
guest ok = no
create mask = 0755
[torrents]
path = /data/torrents
read only = no
guest ok = no
create mask = 0755
</code></pre><p>To create your username and password, replace your_username with your actual username:</p>
<pre tabindex="0"><code>sudo smbpasswd -a your_username
</code></pre><p>Then restart samba with:</p>
<pre tabindex="0"><code>sudo systemctl restart smbd
</code></pre><p>Go back to your Arr VM and add the following to your /etc/fstab:</p>
<pre tabindex="0"><code>//&lt;nas-ip&gt;/usenet /data/usenet cifs username=&lt;username&gt;,password=&lt;password&gt;,uid=1000,gid=1000,auto,nofail 0 0
//&lt;nas-ip&gt;/torrents /data/torrents cifs username=&lt;username&gt;,password=&lt;password&gt;,uid=1000,gid=1000,auto,nofail 0 0
</code></pre><p>Mount them with:</p>
<pre tabindex="0"><code>sudo mount -a
</code></pre><p>Then re-run our permissions command:</p>
<pre tabindex="0"><code>sudo chown -R $USER:$USER /data
sudo chmod -R a=,a+rX,u+w,g+w /data
</code></pre><p>I would reboot this VM at this point, this will make sure it auto connects to our SMB shares at boot.</p>
<h2 id="docker-compose-files">Docker Compose Files<a hidden class="anchor" aria-hidden="true" href="#docker-compose-files">#</a></h2>
<p>Now that everything is setup, we can actually install the services:</p>
<h3 id="one-vm">One VM<a hidden class="anchor" aria-hidden="true" href="#one-vm">#</a></h3>
<p>This is a full docker compose file for pretty much all major Arr&rsquo;s and downloaders I use. I threw Lidarr in here as well, as I run Lidarr for music, but if you dont care about music you can remove lidarr:</p>
<pre tabindex="0"><code>version: &#34;3.9&#34;
services:
sabnzbd:
image: lscr.io/linuxserver/sabnzbd:latest
container_name: sabnzbd
environment:
- PUID=1000
- PGID=1000
- TZ=Etc/UTC
volumes:
- /etc/localtime:/etc/localtime:ro
- /docker/appdata/sabnzbd:/config
- /data/usenet:/data/usenet:rw
ports:
- 8080:8080
restart: unless-stopped
arch-qbittorrentvpn:
image: binhex/arch-qbittorrentvpn:latest
container_name: qbittorrentvpn
volumes:
- &#39;/docker/appdata/qbitty:/config&#39;
- &#39;/data/torrents/:/data/torrents&#39;
- &#39;/etc/localtime:/etc/localtime:ro&#39;
ports:
- &#39;49550:49550&#39;
- &#39;49551:8118&#39;
environment:
- VPN_ENABLED=yes
- VPN_PROV=protonvpn
- VPN_CLIENT=wireguard
- VPN_USER=username+pmp
- VPN_PASS=
- STRICT_PORT_FORWARD=yes
- LAN_NETWORK=10.0.0.0/24
- ENABLE_PRIVOXY=yes
- PUID=1000
- PGID=1000
- WEBUI_PORT=49550
- UMASK=1000
- DEBUG=false
cap_add:
- NET_ADMIN
sysctls:
- net.ipv4.conf.all.src_valid_mark=1
privileged: true
network_mode: bridge
restart: unless-stopped
rdtclient:
container_name: rdtclient
volumes:
- &#39;/data/torrents:/data/torrents&#39;
- &#39;/docker/appdata/rdt:/data/db&#39;
image: rogerfar/rdtclient
restart: always
logging:
driver: json-file
options:
max-size: 10m
ports:
- &#39;6500:6500&#39;
bazarr:
image: lscr.io/linuxserver/bazarr:latest
ports:
- &#34;6767:6767&#34;
volumes:
- /etc/localtime:/etc/localtime:ro
- /docker/appdata/bazarr:/config
- /data/media:/data/media
restart: unless-stopped
environment:
- PUID=1000
- PGID=1000
lidarr:
image: lscr.io/linuxserver/lidarr:latest
ports:
- &#34;8686:8686&#34;
volumes:
- /etc/localtime:/etc/localtime:ro
- /docker/appdata/lidarr:/config
- /data:/data
restart: unless-stopped
environment:
- PUID=1000
- PGID=1000
prowlarr:
image: lscr.io/linuxserver/prowlarr:latest
ports:
- &#34;9696:9696&#34;
volumes:
- /docker/appdata/prowlarr:/config
restart: unless-stopped
environment:
- PUID=1000
- PGID=1000
radarr:
image: lscr.io/linuxserver/radarr:latest
ports:
- &#34;7878:7878&#34;
volumes:
- /etc/localtime:/etc/localtime:ro
- /docker/appdata/radarr:/config
- /data:/data
restart: unless-stopped
environment:
- PUID=1000
- PGID=1000
sonarr:
image: lscr.io/linuxserver/sonarr:latest
ports:
- &#34;8989:8989&#34;
volumes:
- /etc/localtime:/etc/localtime:ro
- /docker/appdata/sonarr:/config
- /data:/data
restart: unless-stopped
environment:
- PUID=1000
- PGID=1000
networks:
default:
name: arrs_default
</code></pre><h3 id="2-vm">2 VM<a hidden class="anchor" aria-hidden="true" href="#2-vm">#</a></h3>
<p>Arrs:</p>
<pre tabindex="0"><code>version: &#34;3.7&#34;
services:
bazarr:
image: lscr.io/linuxserver/bazarr:latest
ports:
- &#34;6767:6767&#34;
volumes:
- /etc/localtime:/etc/localtime:ro
- /docker/appdata/bazarr:/config
- /data/media:/data/media
restart: unless-stopped
environment:
- PUID=1000
- PGID=1000
lidarr:
image: lscr.io/linuxserver/lidarr:latest
ports:
- &#34;8686:8686&#34;
volumes:
- /etc/localtime:/etc/localtime:ro
- /docker/appdata/lidarr:/config
- /data:/data
restart: unless-stopped
environment:
- PUID=1000
- PGID=1000
prowlarr:
image: lscr.io/linuxserver/prowlarr:latest
ports:
- &#34;9696:9696&#34;
volumes:
- /docker/appdata/prowlarr:/config
restart: unless-stopped
environment:
- PUID=1000
- PGID=1000
radarr:
image: lscr.io/linuxserver/radarr:latest
ports:
- &#34;7878:7878&#34;
volumes:
- /etc/localtime:/etc/localtime:ro
- /docker/appdata/radarr:/config
- /data:/data
restart: unless-stopped
environment:
- PUID=1000
- PGID=1000
sonarr:
image: lscr.io/linuxserver/sonarr:latest
ports:
- &#34;8989:8989&#34;
volumes:
- /etc/localtime:/etc/localtime:ro
- /docker/appdata/sonarr:/config
- /data:/data
restart: unless-stopped
environment:
- PUID=1000
- PGID=1000
networks:
default:
name: arrs_default
</code></pre><p>Downloaders:
As stated previously, Sab downloads most of my content (95%), you do not need all 3 of these, you can just copy the Sab part and just use Usenet with Sab. But I like to have a variety.</p>
<pre tabindex="0"><code>version: &#39;3.9&#39;
services:
sabnzbd:
image: lscr.io/linuxserver/sabnzbd:latest
container_name: sabnzbd
environment:
- PUID=1000
- PGID=1000
- TZ=Etc/UTC
volumes:
- /etc/localtime:/etc/localtime:ro
- /docker/appdata/sabnzbd:/config
- /data/usenet:/data/usenet:rw
ports:
- 8080:8080
restart: unless-stopped
arch-qbittorrentvpn:
image: binhex/arch-qbittorrentvpn:latest
container_name: qbittorrentvpn
volumes:
- &#39;/docker/appdata/qbitty:/config&#39;
- &#39;/data/torrents/:/data/torrents&#39;
- &#39;/etc/localtime:/etc/localtime:ro&#39;
ports:
- &#39;49550:49550&#39;
- &#39;49551:8118&#39;
environment:
- VPN_ENABLED=yes
- VPN_PROV=protonvpn
- VPN_CLIENT=wireguard
- VPN_USER=username+pmp
- VPN_PASS=
- STRICT_PORT_FORWARD=yes
- LAN_NETWORK=10.0.0.0/24
- ENABLE_PRIVOXY=yes
- PUID=1000
- PGID=1000
- WEBUI_PORT=49550
- UMASK=1000
- DEBUG=false
cap_add:
- NET_ADMIN
sysctls:
- net.ipv4.conf.all.src_valid_mark=1
privileged: true
network_mode: bridge
restart: unless-stopped
rdtclient:
container_name: rdtclient
volumes:
- &#39;/data/torrents:/data/torrents&#39;
- &#39;/docker/appdata/rdt:/data/db&#39;
image: rogerfar/rdtclient
restart: always
logging:
driver: json-file
options:
max-size: 10m
ports:
- &#39;6500:6500&#39;
</code></pre><h2 id="running-docker-compose-files">Running Docker Compose Files<a hidden class="anchor" aria-hidden="true" href="#running-docker-compose-files">#</a></h2>
<p>In order to run these files, it depends on which option you chose, if 1 VM setup, just copy the compose file and create a new docker-compose.yml file with:</p>
<pre tabindex="0"><code>nano docker-compose.yml
</code></pre><p>Paste in the content, CTRL + X to exit nano, Y to save, ENTER to keep filename. Then run:</p>
<pre tabindex="0"><code>docker compose up -d
</code></pre><p>If you are using 2 VM&rsquo;s, you need to do this 2x. One for each docker-compose file.</p>
<h2 id="conclusion">Conclusion<a hidden class="anchor" aria-hidden="true" href="#conclusion">#</a></h2>
<p>Congratulations on setting up your media library backend! We now have to go and configure all these services to work together, which I have another full blog post on which you can find here.</p>
</div>
<footer class="post-footer">
<ul class="post-tags">
<li><a href="https://mafyuh.com/tags/homelab/">Homelab</a></li>
</ul>
<nav class="paginav">
<a class="prev" href="https://mafyuh.com/posts/spl-token-cli/">
<span class="title">« Prev</span>
<br>
<span>How to create a Solana Token (SPL) from CLI with metadata</span>
</a>
<a class="next" href="https://mafyuh.com/posts/selfhosted-game-servers/">
<span class="title">Next »</span>
<br>
<span>Selfhosted Game Servers</span>
</a>
</nav>
</footer><script src="https://utteranc.es/client.js"
repo="Mafyuh/mafyuh.com"
issue-term="pathname"
label="✨💬✨"
theme="photon-dark"
crossorigin="anonymous"
async>
</script>
</article>
</main>
<footer class="footer">
<span>&copy; 2024 <a href="https://mafyuh.com/">Mafyuh&#39;s Blog</a></span>
<span>
Powered by
<a href="https://gohugo.io/" rel="noopener noreferrer" target="_blank">Hugo</a> &
<a href="https://github.com/adityatelange/hugo-PaperMod/" rel="noopener" target="_blank">PaperMod</a>
</span>
</footer>
<a href="#top" aria-label="go to top" title="Go to Top (Alt + G)" class="top-link" id="top-link" accesskey="g">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 12 6" fill="currentColor">
<path d="M12 6H0l6-6z" />
</svg>
</a>
<script>
let menu = document.getElementById('menu')
if (menu) {
menu.scrollLeft = localStorage.getItem("menu-scroll-position");
menu.onscroll = function () {
localStorage.setItem("menu-scroll-position", menu.scrollLeft);
}
}
document.querySelectorAll('a[href^="#"]').forEach(anchor => {
anchor.addEventListener("click", function (e) {
e.preventDefault();
var id = this.getAttribute("href").substr(1);
if (!window.matchMedia('(prefers-reduced-motion: reduce)').matches) {
document.querySelector(`[id='${decodeURIComponent(id)}']`).scrollIntoView({
behavior: "smooth"
});
} else {
document.querySelector(`[id='${decodeURIComponent(id)}']`).scrollIntoView();
}
if (id === "top") {
history.replaceState(null, null, " ");
} else {
history.pushState(null, null, `#${id}`);
}
});
});
</script>
<script>
var mybutton = document.getElementById("top-link");
window.onscroll = function () {
if (document.body.scrollTop > 800 || document.documentElement.scrollTop > 800) {
mybutton.style.visibility = "visible";
mybutton.style.opacity = "1";
} else {
mybutton.style.visibility = "hidden";
mybutton.style.opacity = "0";
}
};
</script>
<script>
document.getElementById("theme-toggle").addEventListener("click", () => {
if (document.body.className.includes("dark")) {
document.body.classList.remove('dark');
localStorage.setItem("pref-theme", 'light');
} else {
document.body.classList.add('dark');
localStorage.setItem("pref-theme", 'dark');
}
})
</script>
<script>
document.querySelectorAll('pre > code').forEach((codeblock) => {
const container = codeblock.parentNode.parentNode;
const copybutton = document.createElement('button');
copybutton.classList.add('copy-code');
copybutton.innerHTML = 'copy';
function copyingDone() {
copybutton.innerHTML = 'copied!';
setTimeout(() => {
copybutton.innerHTML = 'copy';
}, 2000);
}
copybutton.addEventListener('click', (cb) => {
if ('clipboard' in navigator) {
navigator.clipboard.writeText(codeblock.textContent);
copyingDone();
return;
}
const range = document.createRange();
range.selectNodeContents(codeblock);
const selection = window.getSelection();
selection.removeAllRanges();
selection.addRange(range);
try {
document.execCommand('copy');
copyingDone();
} catch (e) { };
selection.removeRange(range);
});
if (container.classList.contains("highlight")) {
container.appendChild(copybutton);
} else if (container.parentNode.firstChild == container) {
} else if (codeblock.parentNode.parentNode.parentNode.parentNode.parentNode.nodeName == "TABLE") {
codeblock.parentNode.parentNode.parentNode.parentNode.parentNode.appendChild(copybutton);
} else {
codeblock.parentNode.appendChild(copybutton);
}
});
</script>
</body>
</html>