<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/">
  <channel>
    <title>Docker on kunat.dev</title>
    <link>https://kunat.dev/tags/docker/</link>
    <description>Recent content in Docker on kunat.dev</description>
    <generator>Hugo -- 0.147.5</generator>
    <language>en-us</language>
    <copyright>2025 kunat.dev</copyright>
    <lastBuildDate>Mon, 14 Jul 2025 18:34:57 +0200</lastBuildDate>
    <atom:link href="https://kunat.dev/tags/docker/index.xml" rel="self" type="application/rss+xml" />
    <item>
      <title>Configuring Tailscale Subnet Routing to Access Docker Containers by LAN IP</title>
      <link>https://kunat.dev/notes/tailscale-subnet-routers/</link>
      <pubDate>Mon, 14 Jul 2025 18:34:57 +0200</pubDate>
      <guid>https://kunat.dev/notes/tailscale-subnet-routers/</guid>
      <description>&lt;p&gt;I&amp;rsquo;ve been running various Docker containers on my Synology NAS for years, and while Tailscale has been excellent for accessing the NAS itself remotely, I found myself frustrated by one specific limitation: I could &lt;strong&gt;only&lt;/strong&gt; access my Docker containers by their LAN IP addresses when I was actually connected to my home network.&lt;/p&gt;
&lt;p&gt;When I was away from home, even though I could reach my Synology via Tailscale address or Magic DNS, trying to access something like &lt;code&gt;192.168.1.144:7878&lt;/code&gt; for Radarr would just time out.&lt;/p&gt;</description>
      <content:encoded><![CDATA[<p>I&rsquo;ve been running various Docker containers on my Synology NAS for years, and while Tailscale has been excellent for accessing the NAS itself remotely, I found myself frustrated by one specific limitation: I could <strong>only</strong> access my Docker containers by their LAN IP addresses when I was actually connected to my home network.</p>
<p>When I was away from home, even though I could reach my Synology via Tailscale address or Magic DNS, trying to access something like <code>192.168.1.144:7878</code> for Radarr would just time out.</p>
<p>That&rsquo;s where <a href="https://tailscale.com/kb/1019/subnets" target="_blank" >Tailscale&rsquo;s subnet routers</a> come in. This feature allows you to access all devices on your home network—including your Docker containers—using their actual LAN IP addresses.</p>
<h2 id="what-were-solving">What We&rsquo;re Solving</h2>
<p>We want to access our Docker containers using their LAN IP addresses consistently, regardless of whether we&rsquo;re connected to our home network or accessing remotely through Tailscale.</p>
<h2 id="prerequisites">Prerequisites</h2>
<ul>
<li>Tailscale already set up on your machine. You can use <a href="https://www.youtube.com/watch?v=qulWDpzdY1E" target="_blank" >this guide</a> to set it up.</li>
</ul>
<h2 id="setting-up-subnet-routing">Setting Up Subnet Routing</h2>
<h3 id="step-1-configure-your-synology-as-a-subnet-router">Step 1: Configure Your Synology as a Subnet Router</h3>
<p>First, you&rsquo;ll need to SSH into your Synology. Once you&rsquo;re connected, run this command:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>sudo tailscale up --advertise-routes<span style="color:#f92672">=</span>192.168.1.0/24 --advertise-exit-node --reset
</span></span></code></pre></div><p><strong>Important:</strong> Make sure to replace <code>192.168.1.0/24</code> with the correct subnet for your network. In my case, my Synology has the IP address <code>192.168.1.144</code>, so I use <code>192.168.1.0/24</code>. You can find your network&rsquo;s subnet by checking your router&rsquo;s configuration or running <code>ip route</code> on your Synology.</p>
<h3 id="step-2-enable-subnet-routing-in-tailscale-admin-console">Step 2: Enable Subnet Routing in Tailscale Admin Console</h3>
<p>The command above advertises your local network routes to Tailscale, but you need to explicitly enable them in the admin console:</p>
<ol>
<li>Go to the Tailscale admin console at <a href="https://login.tailscale.com/admin/machines" target="_blank" >https://login.tailscale.com/admin/machines</a></li>
<li>Find your Synology device in the machines list</li>
<li>Click on the device and select &ldquo;Edit route settings&rdquo;</li>
<li>In the &ldquo;Subnet routers&rdquo; section, check the box next to your advertised route (e.g., <code>192.168.1.0/24</code>)</li>
</ol>
<p><img alt="Xcode build timeline" loading="lazy" src="/notes/images/tailscale-subnet-routers/tailscale-subnet-routers.jpg"></p>
<h2 id="testing-your-setup">Testing Your Setup</h2>
<p>With that configuration complete, you should now be able to access all your Docker containers using their LAN IP addresses, regardless of whether you&rsquo;re connected to your home network or not.</p>
<p>For example, if you have a container running on <code>192.168.1.144:7878</code>, you can access it from anywhere by simply navigating to that address in your browser while connected to Tailscale.</p>
<h2 id="taking-it-further-reverse-proxy-setup">Taking It Further: Reverse Proxy Setup</h2>
<p>You can make this setup even more elegant by implementing a reverse proxy. This allows you to access your services using clean subdomains like <code>radarr.kunat.dev</code> instead of remembering IP addresses and port numbers. You can read more about it <a href="/notes/synology-caddy-reverse-proxy/" >here.</a></p>
<h2 id="resources">Resources</h2>
<ul>
<li><a href="https://tailscale.com/kb/1019/subnets" target="_blank" >Tailscale documentation on subnet routers</a></li>
<li><a href="https://www.youtube.com/watch?v=qulWDpzdY1E" target="_blank" >How To Install And Configure Tailscale On Your Synology Nas</a></li>
<li><a href="/notes/synology-caddy-reverse-proxy/" >Setting Up Caddy as a Reverse Proxy on Synology NAS</a></li>
</ul>
]]></content:encoded>
    </item>
    <item>
      <title>Setting Up Caddy as a Reverse Proxy on Synology NAS</title>
      <link>https://kunat.dev/notes/synology-caddy-reverse-proxy/</link>
      <pubDate>Wed, 09 Jul 2025 15:28:57 +0200</pubDate>
      <guid>https://kunat.dev/notes/synology-caddy-reverse-proxy/</guid>
      <description>&lt;p&gt;Setting up a reverse proxy on your Synology NAS can dramatically improve how you access your Docker containers. Instead of remembering ports for each service, you can use clean subdomains like &lt;code&gt;plex.yourdomain.com&lt;/code&gt; or &lt;code&gt;radarr.yourdomain.com&lt;/code&gt;.&lt;/p&gt;
&lt;h2 id=&#34;whats-caddy&#34;&gt;What&amp;rsquo;s Caddy?&lt;/h2&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;a href=&#34;https://github.com/caddyserver/caddy&#34; target=&#34;_blank&#34; &gt;Caddy&lt;/a&gt; is a modern, open-source web server that excels at reverse proxying. It&amp;rsquo;s lightweight, easy to configure, and handles HTTPS automatically. What sets it apart is its human-readable configuration format and automatic certificate management capabilities.&lt;/p&gt;</description>
      <content:encoded><![CDATA[<p>Setting up a reverse proxy on your Synology NAS can dramatically improve how you access your Docker containers. Instead of remembering ports for each service, you can use clean subdomains like <code>plex.yourdomain.com</code> or <code>radarr.yourdomain.com</code>.</p>
<h2 id="whats-caddy">What&rsquo;s Caddy?</h2>
<blockquote>
<p><a href="https://github.com/caddyserver/caddy" target="_blank" >Caddy</a> is a modern, open-source web server that excels at reverse proxying. It&rsquo;s lightweight, easy to configure, and handles HTTPS automatically. What sets it apart is its human-readable configuration format and automatic certificate management capabilities.</p></blockquote>
<h2 id="why-i-chose-caddy-over-synologys-built-in-solution">Why I Chose Caddy Over Synology&rsquo;s Built-in Solution</h2>
<p>Synology does include a reverse proxy feature, but it has some limitations:</p>
<p><strong>Platform Agnostic</strong>: Caddy runs in Docker, which means it&rsquo;s not tied to Synology&rsquo;s ecosystem. If I ever migrate to a different NAS or server setup, my configuration comes with me.</p>
<p><strong>File-Based Configuration</strong>: This is the big one for me. Synology&rsquo;s reverse proxy requires you to configure each service through their GUI interface. When you&rsquo;re running more than a few containers, this becomes time-consuming. With Caddy, I can define all my services in a single configuration file that&rsquo;s easy to version control and backup.</p>
<p><strong>Better HTTPS Handling</strong>: Caddy&rsquo;s automatic HTTPS capabilities are far superior to what Synology offers out of the box. We won&rsquo;t use those, but I listed it for completeness&rsquo; sake.</p>
<h2 id="goals">Goals</h2>
<p>Access your Docker containers using clean subdomains instead of remembering port numbers. Instead of typing <code>192.168.1.100:9696</code> to reach Prowlarr, you&rsquo;ll use <code>prowlarr.yourdomain.com</code>.</p>
<h2 id="prerequisites">Prerequisites</h2>
<p>Before we dive in, you&rsquo;ll need a few things in place:</p>
<p><strong>Docker Setup</strong>: I&rsquo;m assuming you have Docker set up and running using the <a href="https://trash-guides.info/File-and-Folder-Structure/How-to-set-up/Synology/" target="_blank" >Trash Guides</a>. This isn&rsquo;t strictly required, but I&rsquo;ll assume your directory structure and permissions match what&rsquo;s described in their guide.</p>
<p><strong>Cloudflare Domain Management</strong>: This guide assumes your domain is managed through Cloudflare&rsquo;s dashboard. The DNS records must have the <strong>proxy status enabled</strong> (orange cloud icon). This is crucial for the HTTPS setup we&rsquo;ll implement later.</p>
<p><strong>Local DNS Server</strong>: You&rsquo;ll need to be running your own DNS server like AdGuard Home or Pi-hole. This is required to add a wildcard DNS rewrite rule that points <code>*.yourdomain.com</code> to your Synology&rsquo;s IP address.</p>
<h2 id="setup">Setup</h2>
<h3 id="adding-caddy-to-your-docker-compose">Adding Caddy to Your Docker Compose</h3>
<p>First, let&rsquo;s add Caddy to your existing <code>docker-compose.yml</code> file. Here&rsquo;s the configuration I use:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-yaml" data-lang="yaml"><span style="display:flex;"><span>  <span style="color:#f92672">caddy</span>:
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">container_name</span>: <span style="color:#ae81ff">caddy</span>
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">image</span>: <span style="color:#ae81ff">caddy:latest</span>
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">restart</span>: <span style="color:#ae81ff">unless-stopped</span>
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">network_mode</span>: <span style="color:#ae81ff">host</span>
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">environment</span>:
</span></span><span style="display:flex;"><span>      - <span style="color:#ae81ff">TZ=${TZ}</span>
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">volumes</span>:
</span></span><span style="display:flex;"><span>      - <span style="color:#ae81ff">/volume1/docker/appdata/caddy/Caddyfile:/etc/caddy/Caddyfile:ro</span>
</span></span><span style="display:flex;"><span>      - <span style="color:#ae81ff">/volume1/docker/appdata/caddy/data:/data</span>
</span></span><span style="display:flex;"><span>      - <span style="color:#ae81ff">/volume1/docker/appdata/caddy/config:/config</span>
</span></span><span style="display:flex;"><span>      - <span style="color:#ae81ff">/volume1/docker/appdata/caddy/certs:/caddy/certs:ro</span>
</span></span></code></pre></div><h3 id="creating-the-folder-structure">Creating the Folder Structure</h3>
<p>In your <code>appdata</code> directory (<code>/volume1/docker/appdata</code>), create the necessary Caddy directories:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>mkdir -p caddy/<span style="color:#f92672">{</span>certs,config,data<span style="color:#f92672">}</span> <span style="color:#f92672">&amp;&amp;</span> touch caddy/Caddyfile
</span></span></code></pre></div><p>This creates the directory structure that Caddy needs, including directories for certificates, configuration, and data storage, plus the main Caddyfile.</p>
<h3 id="freeing-up-ports-443-and-80">Freeing Up Ports 443 and 80</h3>
<p>Here&rsquo;s something that caught me off guard: Synology automatically binds to ports 443 and 80 even if you&rsquo;re not using their built-in reverse proxy. Since Caddy needs these ports to handle HTTPS and HTTP traffic, we need to free them up.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-shell" data-lang="shell"><span style="display:flex;"><span>sed -i -e <span style="color:#e6db74">&#39;s/80/82/&#39;</span> -e <span style="color:#e6db74">&#39;s/443/444/&#39;</span> /usr/syno/share/nginx/server.mustache /usr/syno/share/nginx/DSM.mustache /usr/syno/share/nginx/WWWService.mustache
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>synosystemctl restart nginx
</span></span></code></pre></div><p>I set up a boot script to handle this automatically on each reboot (Control Panel -&gt; Task Scheduler). While I&rsquo;ve found that this override typically persists between reboots, there&rsquo;s no harm in ensuring it runs at startup. System updates might reset these settings to their defaults, and I&rsquo;d rather be safe than sorry.</p>
<p><img alt="Xcode build timeline" loading="lazy" src="notes/images/synology-caddy-reverse-proxy/scheduled-task.jpg"></p>
<h3 id="setting-up-https-optional-but-recommended">Setting Up HTTPS (Optional but Recommended)</h3>
<p>HTTPS isn&rsquo;t technically required for local-only access, but it eliminates browser warnings. However, there&rsquo;s an important caveat with Caddy&rsquo;s automatic HTTPS feature.</p>
<p><img alt="Xcode build timeline" loading="lazy" src="notes/images/synology-caddy-reverse-proxy/connection-not-private.png"></p>
<p><strong>Why Caddy&rsquo;s Built-in Auto HTTPS Won&rsquo;t Work</strong>: Caddy&rsquo;s automatic HTTPS uses Let&rsquo;s Encrypt, which requires ACME challenges to verify domain ownership. These challenges need your server to be accessible from the internet. If your containers are only accessible through Tailscale or similar private networks (like mine), the ACME validation will fail.</p>
<p><strong>The Solution: Cloudflare Origin CA Certificates</strong>: Since I use Tailscale to access my containers outside my home network, I opted for Cloudflare&rsquo;s Origin CA certificates. These certificates are valid for 15 years and don&rsquo;t require internet accessibility for validation.</p>
<h4 id="generating-cloudflare-origin-certificates">Generating Cloudflare Origin Certificates</h4>
<p>Your domain needs to be using Cloudflare for this to work. Navigate to the Cloudflare Origin CA dashboard and generate a wildcard certificate for your domain. See <a href="https://developers.cloudflare.com/ssl/origin-configuration/origin-ca/" target="_blank" >Cloudflare Docs</a> for step-by-step instructions.</p>
<p>Save the public and private keys to these files:</p>
<ul>
<li><code>cert.pem</code> (public key)</li>
<li><code>key.pem</code> (private key)</li>
</ul>
<p>Move both files to your <code>caddy/certs</code> directory.</p>
<h4 id="adding-the-certificate-to-your-devices">Adding the Certificate to Your Devices</h4>
<p>To eliminate browser security warnings, you&rsquo;ll need to add the public certificate (<code>cert.pem</code>) to your device&rsquo;s trusted certificate store. On macOS, this means adding it to your keychain and marking it as trusted. You&rsquo;ll need to repeat this process for each device you want to use to access your containers.</p>
<p><img alt="Xcode build timeline" loading="lazy" src="/notes/images/synology-caddy-reverse-proxy/cloudflare-origin-cert.jpg"></p>
<h3 id="setting-proper-permissions">Setting Proper Permissions</h3>
<p>Following the Trash Guides approach, set the correct permissions for the docker user:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-shell" data-lang="shell"><span style="display:flex;"><span>sudo chown -R docker:users /volume1/docker/appdata/caddy
</span></span><span style="display:flex;"><span>sudo chmod -R a<span style="color:#f92672">=</span>,a+rX,u+w,g+w /volume1/docker/appdata/caddy
</span></span></code></pre></div><h3 id="configuring-the-caddyfile">Configuring the Caddyfile</h3>
<p>Here&rsquo;s a sample Caddyfile configuration. This is where the magic happens:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-yaml" data-lang="yaml"><span style="display:flex;"><span><span style="color:#75715e"># Global options</span>
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>	<span style="color:#75715e"># Disable automatic HTTPS since we&#39;re using Cloudflare Origin CA certs</span>
</span></span><span style="display:flex;"><span>	<span style="color:#ae81ff">auto_https off</span>
</span></span><span style="display:flex;"><span>}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#75715e"># Prowlarr</span>
</span></span><span style="display:flex;"><span><span style="color:#ae81ff">prowlarr.kunat.dev {</span>
</span></span><span style="display:flex;"><span>	<span style="color:#ae81ff">reverse_proxy localhost:9696</span>
</span></span><span style="display:flex;"><span>	<span style="color:#ae81ff">tls /caddy/certs/cert.pem /caddy/certs/key.pem</span>
</span></span><span style="display:flex;"><span>}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#75715e"># Plex</span>
</span></span><span style="display:flex;"><span><span style="color:#ae81ff">plex.kunat.dev {</span>
</span></span><span style="display:flex;"><span>	<span style="color:#ae81ff">reverse_proxy localhost:32400</span>
</span></span><span style="display:flex;"><span>	<span style="color:#ae81ff">tls /caddy/certs/cert.pem /caddy/certs/key.pem</span>
</span></span><span style="display:flex;"><span>}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#75715e"># AdGuard</span>
</span></span><span style="display:flex;"><span><span style="color:#ae81ff">adguard.kunat.dev {</span>
</span></span><span style="display:flex;"><span>	<span style="color:#ae81ff">reverse_proxy localhost:3000</span>
</span></span><span style="display:flex;"><span>	<span style="color:#ae81ff">tls /caddy/certs/cert.pem /caddy/certs/key.pem</span>
</span></span><span style="display:flex;"><span>}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#75715e"># Synology Dashboard (HTTPS backend)</span>
</span></span><span style="display:flex;"><span><span style="color:#ae81ff">synology.kunat.dev {</span>
</span></span><span style="display:flex;"><span>	<span style="color:#ae81ff">reverse_proxy https://localhost:5001 {</span>
</span></span><span style="display:flex;"><span>		<span style="color:#ae81ff">transport http {</span>
</span></span><span style="display:flex;"><span>			<span style="color:#ae81ff">tls_insecure_skip_verify</span>
</span></span><span style="display:flex;"><span>		}
</span></span><span style="display:flex;"><span>	}
</span></span><span style="display:flex;"><span>	<span style="color:#ae81ff">tls /caddy/certs/cert.pem /caddy/certs/key.pem</span>
</span></span><span style="display:flex;"><span>}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#75715e"># Homarr</span>
</span></span><span style="display:flex;"><span><span style="color:#ae81ff">homarr.kunat.dev {</span>
</span></span><span style="display:flex;"><span>	<span style="color:#ae81ff">reverse_proxy localhost:7575</span>
</span></span><span style="display:flex;"><span>	<span style="color:#ae81ff">tls /caddy/certs/cert.pem /caddy/certs/key.pem</span>
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>Each service follows the same pattern: define the subdomain, specify the reverse proxy target (localhost:port), and point to our TLS certificates.</p>
<h3 id="running-caddy">Running Caddy</h3>
<p>Start Caddy with:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>sudo docker-compose up -d caddy
</span></span></code></pre></div><p>If everything is configured correctly, you should see logs similar to these:</p>
<pre tabindex="0"><code>caddy  | {&#34;level&#34;:&#34;warn&#34;,&#34;ts&#34;:1752004979.244892,&#34;msg&#34;:&#34;failed to set GOMAXPROCS&#34;,&#34;error&#34;:&#34;open /sys/fs/cgroup/cpu/cpu.cfs_quota_us: no such file or directory&#34;}
caddy  | {&#34;level&#34;:&#34;info&#34;,&#34;ts&#34;:1752004979.2452004,&#34;msg&#34;:&#34;GOMEMLIMIT is updated&#34;,&#34;package&#34;:&#34;github.com/KimMachineGun/automemlimit/memlimit&#34;,&#34;GOMEMLIMIT&#34;:18851998924,&#34;previous&#34;:9223372036854775807}
caddy  | {&#34;level&#34;:&#34;info&#34;,&#34;ts&#34;:1752004979.2452545,&#34;msg&#34;:&#34;using config from file&#34;,&#34;file&#34;:&#34;/etc/caddy/Caddyfile&#34;}
caddy  | {&#34;level&#34;:&#34;info&#34;,&#34;ts&#34;:1752004979.247973,&#34;msg&#34;:&#34;adapted config to JSON&#34;,&#34;adapter&#34;:&#34;caddyfile&#34;}
caddy  | {&#34;level&#34;:&#34;info&#34;,&#34;ts&#34;:1752004979.2502022,&#34;logger&#34;:&#34;admin&#34;,&#34;msg&#34;:&#34;admin endpoint started&#34;,&#34;address&#34;:&#34;localhost:2019&#34;,&#34;enforce_origin&#34;:false,&#34;origins&#34;:[&#34;//localhost:2019&#34;,&#34;//[::1]:2019&#34;,&#34;//127.0.0.1:2019&#34;]}
caddy  | {&#34;level&#34;:&#34;info&#34;,&#34;ts&#34;:1752004979.2507207,&#34;logger&#34;:&#34;tls.cache.maintenance&#34;,&#34;msg&#34;:&#34;started background certificate maintenance&#34;,&#34;cache&#34;:&#34;0xc00079c480&#34;}
caddy  | {&#34;level&#34;:&#34;warn&#34;,&#34;ts&#34;:1752004979.2785668,&#34;logger&#34;:&#34;tls&#34;,&#34;msg&#34;:&#34;stapling OCSP&#34;,&#34;error&#34;:&#34;no OCSP stapling for [cloudflare origin certificate *.kunat.dev]: no URL to issuing certificate&#34;}
caddy  | {&#34;level&#34;:&#34;info&#34;,&#34;ts&#34;:1752004979.278835,&#34;logger&#34;:&#34;http.auto_https&#34;,&#34;msg&#34;:&#34;automatic HTTPS is completely disabled for server&#34;,&#34;server_name&#34;:&#34;srv0&#34;}
caddy  | {&#34;level&#34;:&#34;info&#34;,&#34;ts&#34;:1752004979.2799113,&#34;logger&#34;:&#34;http&#34;,&#34;msg&#34;:&#34;enabling HTTP/3 listener&#34;,&#34;addr&#34;:&#34;:443&#34;}
caddy  | {&#34;level&#34;:&#34;info&#34;,&#34;ts&#34;:1752004979.2799726,&#34;msg&#34;:&#34;failed to sufficiently increase receive buffer size (was: 208 kiB, wanted: 7168 kiB, got: 416 kiB). See https://github.com/quic-go/quic-go/wiki/UDP-Buffer-Sizes for details.&#34;}
caddy  | {&#34;level&#34;:&#34;info&#34;,&#34;ts&#34;:1752004979.2800903,&#34;logger&#34;:&#34;http.log&#34;,&#34;msg&#34;:&#34;server running&#34;,&#34;name&#34;:&#34;srv0&#34;,&#34;protocols&#34;:[&#34;h1&#34;,&#34;h2&#34;,&#34;h3&#34;]}
caddy  | {&#34;level&#34;:&#34;info&#34;,&#34;ts&#34;:1752004979.280308,&#34;msg&#34;:&#34;autosaved config (load with --resume flag)&#34;,&#34;file&#34;:&#34;/config/caddy/autosave.json&#34;}
caddy  | {&#34;level&#34;:&#34;info&#34;,&#34;ts&#34;:1752004979.2811198,&#34;msg&#34;:&#34;serving initial configuration&#34;}
caddy  | {&#34;level&#34;:&#34;info&#34;,&#34;ts&#34;:1752004979.38889,&#34;logger&#34;:&#34;tls&#34;,&#34;msg&#34;:&#34;finished cleaning storage units&#34;}
</code></pre><p>The key things to look for are &ldquo;server running&rdquo; and &ldquo;serving initial configuration&rdquo; messages. These indicate that Caddy has successfully started and is ready to handle requests.</p>
<p>Now try accessing one of your Docker containers using its subdomain. If everything is working correctly, you should be able to reach your services through clean URLs like <code>https://prowlarr.yourdomain.com</code>.</p>
<h2 id="troubleshooting">Troubleshooting</h2>
<p><strong>Clean Your DNS Cache</strong>: If you&rsquo;re having trouble accessing your services after setup, try clearing your DNS cache. On macOS, run:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>sudo dscacheutil -flushcache; sudo killall -HUP mDNSResponder
</span></span></code></pre></div><p><strong>Check Your Wildcard DNS</strong>: Make sure your local DNS server (AdGuard Home or Pi-hole) has the wildcard rewrite rule in place. Without <code>*.yourdomain.com -&gt; your_synology_ip</code>, your subdomains won&rsquo;t resolve locally.</p>
<p><img alt="Xcode build timeline" loading="lazy" src="/notes/images/synology-caddy-reverse-proxy/dns-override.jpg"></p>
<p><strong>Verify Certificate Trust</strong>: If you&rsquo;re seeing browser security warnings, double-check that you&rsquo;ve properly installed and trusted the Cloudflare Origin CA certificate on your client devices.</p>
<h2 id="resources">Resources</h2>
<ul>
<li><a href="https://3os.org/infrastructure/synology/disable-dms-listening-on-80-443-ports/#disable-the-synology-nas-dsm-to-listen-on-80-443-ports" target="_blank" >Free 80,443 Ports - 3os</a></li>
<li><a href="https://caddyserver.com/docs/" target="_blank" >Caddy Documentation</a></li>
<li><a href="https://developers.cloudflare.com/ssl/origin-configuration/origin-ca/" target="_blank" >Cloudflare Origin CA Documentation</a></li>
</ul>
<h2 id="conclusion">Conclusion</h2>
<p>Setting up Caddy as a reverse proxy on Synology has been a game-changer for my homelab. The ability to access all my services through clean subdomains makes everything feel more professional and easier to remember. While the initial setup requires some work, especially with the certificate configuration, the long-term benefits are worth it.</p>
<blockquote>
<p><strong>Update 14/07/25:</strong> If you want to access your Docker containers using their LAN IP addresses consistently, regardless of whether we’re connected to our home network or accessing remotely through Tailscale check out <a href="/notes/tailscale-subnet-routers/" >this aritcle</a> on Tailscale subnet routers.</p></blockquote>
]]></content:encoded>
    </item>
    <item>
      <title>Automate YouTube Downloads on Synology with MeTube and Docker</title>
      <link>https://kunat.dev/notes/metube-synology-setup/</link>
      <pubDate>Thu, 05 Jun 2025 18:38:36 +0200</pubDate>
      <guid>https://kunat.dev/notes/metube-synology-setup/</guid>
      <description>Learn how to install MeTube, a web GUI for youtube-dl, on your Synology NAS using Docker. Follow this step-by-step guide to automate downloading YouTube videos directly to your Plex media library.</description>
      <content:encoded><![CDATA[<p><img alt="hello there" loading="lazy" src="/notes/images/metube-synology-setup-header.jpg"></p>
<blockquote>
<p><strong><a href="https://github.com/alexta69/metube" target="_blank" >MeTube</a></strong> is a web GUI for <code>youtube-dl</code>, a command-line tool for downloading videos from YouTube and several hundred other sites.</p></blockquote>
<p>My goal for this project was to set up automation for downloading YouTube videos directly to my Plex library.</p>
<p>The primary reason is that I can&rsquo;t trust myself with YouTube Shorts. Once I open YouTube, I&rsquo;m likely to spend at least a few minutes browsing through them. The simplest solution was to add friction to the process: I removed the YouTube app from all my devices and blocked the domain using my local DNS server.</p>
<p>This worked like a charm. Now, I only visit YouTube every few days to add content that interests me to my Plex library.</p>
<blockquote>
<p>You can read more about setting up your own DNS server <a href="/notes/adguard-home-synology-tailscale/" >here</a>.</p></blockquote>
<h2 id="prerequisites">Prerequisites</h2>
<ul>
<li>‼️ Docker must be installed and set up on your system by following the <a href="https://trash-guides.info/File-and-Folder-Structure/How-to-set-up/Synology/" target="_blank" >TrashGuides setup for Synology</a>.</li>
</ul>
<blockquote>
<p>This guide assumes you have configured common environment variables like <code>PUID</code>, <code>PGID</code>, <code>TZ</code>, <code>DOCKERSTORAGEDIR</code>, and <code>DOCKERCONFDIR</code> as outlined in the TrashGuides.</p></blockquote>
<h2 id="installation-steps">Installation Steps</h2>
<h3 id="1-create-required-directories">1. Create Required Directories</h3>
<p>First, we need to create folders for MeTube&rsquo;s configuration and downloads. One folder will store MeTube&rsquo;s application data, and the other will be the destination for your downloaded videos.</p>
<p>SSH into your Synology NAS and execute the following commands:</p>
<blockquote>
<p>The commands below assume you&rsquo;ve followed the linked guide exactly. Adjust paths like <code>/volume1/data/media/youtube</code> and <code>/volume1/docker/appdata/metube</code> if your storage volume or directory structure differs.</p></blockquote>
<ul>
<li><strong>Folder for video downloads (e.g., your Plex library):</strong>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>sudo mkdir -p /volume1/data/media/youtube
</span></span></code></pre></div></li>
<li><strong>Folder for the MeTube container&rsquo;s configuration:</strong>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>sudo mkdir -p /volume1/docker/appdata/metube
</span></span></code></pre></div></li>
</ul>
<h3 id="2-set-permissions">2. Set Permissions</h3>
<p>Next, execute the following commands via SSH to configure the correct permissions for the newly created directories:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>sudo chown -R docker:users /volume1/data/media/youtube /volume1/docker/appdata/metube
</span></span><span style="display:flex;"><span>sudo chmod -R a<span style="color:#f92672">=</span>,a+rX,u+w,g+w /volume1/data/media/youtube /volume1/docker/appdata/metube
</span></span></code></pre></div><p>This command ensures the <code>docker</code> user has the necessary ownership and read/write permissions.</p>
<h3 id="3-configure-docker-compose">3. Configure Docker Compose</h3>
<p>Append the following service configuration to your main <code>docker-compose.yml</code> file. If you followed the TrashGuides setup, this file is located at <code>/volume1/docker/</code>.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-yaml" data-lang="yaml"><span style="display:flex;"><span><span style="color:#f92672">services</span>:
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">metube</span>:
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">container_name</span>: <span style="color:#ae81ff">metube</span>
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">image</span>: <span style="color:#ae81ff">ghcr.io/alexta69/metube:latest</span>
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">restart</span>: <span style="color:#ae81ff">unless-stopped</span>
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">logging</span>:
</span></span><span style="display:flex;"><span>      <span style="color:#f92672">driver</span>: <span style="color:#ae81ff">json-file</span>
</span></span><span style="display:flex;"><span>      <span style="color:#f92672">options</span>:
</span></span><span style="display:flex;"><span>        <span style="color:#f92672">max-file</span>: <span style="color:#ae81ff">${DOCKERLOGGING_MAXFILE:-10}</span>
</span></span><span style="display:flex;"><span>        <span style="color:#f92672">max-size</span>: <span style="color:#ae81ff">${DOCKERLOGGING_MAXSIZE:-200m}</span>
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">ports</span>:
</span></span><span style="display:flex;"><span>      - <span style="color:#e6db74">&#34;8081:8081&#34;</span>
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">environment</span>:
</span></span><span style="display:flex;"><span>      - <span style="color:#ae81ff">PUID=${PUID}</span>
</span></span><span style="display:flex;"><span>      - <span style="color:#ae81ff">PGID=${PGID}</span>
</span></span><span style="display:flex;"><span>      - <span style="color:#ae81ff">TZ=${TZ}</span>
</span></span><span style="display:flex;"><span>      - <span style="color:#ae81ff">UMASK=002</span>
</span></span><span style="display:flex;"><span>      - <span style="color:#ae81ff">DOWNLOAD_DIR=/downloads</span>
</span></span><span style="display:flex;"><span>      - <span style="color:#ae81ff">AUDIO_DOWNLOAD_DIR=/downloads</span>
</span></span><span style="display:flex;"><span>      - <span style="color:#ae81ff">STATE_DIR=/config/.metube</span>
</span></span><span style="display:flex;"><span>      - <span style="color:#ae81ff">TEMP_DIR=/downloads/.temp</span>
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">volumes</span>:
</span></span><span style="display:flex;"><span>      - <span style="color:#ae81ff">/etc/localtime:/etc/localtime:ro</span>
</span></span><span style="display:flex;"><span>      - <span style="color:#ae81ff">${DOCKERSTORAGEDIR}/media/youtube:/downloads</span>
</span></span><span style="display:flex;"><span>      - <span style="color:#ae81ff">${DOCKERCONFDIR}/metube:/config</span>
</span></span></code></pre></div><p><strong>Note on Environment Variables and Volumes:</strong></p>
<ul>
<li><code>${DOCKERSTORAGEDIR}/media/youtube</code> maps your Synology&rsquo;s media download folder to the <code>/downloads</code> directory inside the container. Ensure <code>DOCKERSTORAGEDIR</code> is correctly defined (e.g., <code>DOCKERSTORAGEDIR=/volume1/data</code>).</li>
<li><code>${DOCKERCONFDIR}/metube</code> maps your Synology&rsquo;s MeTube appdata folder to the <code>/config</code> directory inside the container. Ensure <code>DOCKERCONFDIR</code> is correctly defined (e.g., <code>DOCKERCONFDIR=/volume1/docker/appdata</code>).</li>
</ul>
<h3 id="4-start-the-container">4. Start the Container</h3>
<p>Navigate to the directory containing your <code>docker-compose.yml</code> file via SSH and run the following command:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>docker compose up -d metube
</span></span></code></pre></div><p>The container will now download the image and start. You can then access the MeTube web interface by navigating to <code>http://&lt;your-synology-ip&gt;:8081</code> in a web browser.</p>
<p>Check out MeTube&rsquo;s <a href="https://github.com/alexta69/metube?tab=readme-ov-file#ios-shortcut" target="_blank" >README</a> for a handy iOS shortcut that allows you share video URLs without opening MeTube!</p>
<h2 id="troubleshooting">Troubleshooting</h2>
<ul>
<li><strong>Port Conflicts:</strong> If port <code>8081</code> is already in use, change the host port in the <code>ports</code> section of your <code>docker-compose.yml</code>. For example, to use port <code>8082</code>, modify the line to <code>- &quot;8082:8081&quot;</code>.</li>
<li><strong>Permission Issues:</strong> If MeTube reports that it cannot write to the download or config directories, double-check the permissions set in Step 2. Also, verify that the <code>PUID</code> and <code>PGID</code> environment variables correspond to a user with write access to those folders.</li>
<li><strong>Container Logs:</strong> If the container fails to start or you encounter other issues, check its logs with this command:
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>docker compose logs metube
</span></span></code></pre></div></li>
</ul>
<h2 id="resources">Resources</h2>
<ul>
<li><a href="https://github.com/alexta69/metube" target="_blank" >MeTube GitHub Repository</a></li>
<li><a href="https://trash-guides.info/File-and-Folder-Structure/How-to-set-up/Synology/" target="_blank" >TrashGuides for Synology Docker Setup</a></li>
</ul>
]]></content:encoded>
    </item>
    <item>
      <title>Changedetection.io &#43; Chrome Synology Setup with Docker Compose</title>
      <link>https://kunat.dev/notes/changedetection-synology-setup/</link>
      <pubDate>Thu, 22 May 2025 19:04:18 +0200</pubDate>
      <guid>https://kunat.dev/notes/changedetection-synology-setup/</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;Note: This article was originally published 05/2025. Last update 08/2025. Changes:&lt;/p&gt;&lt;/blockquote&gt;
&lt;ul&gt;
&lt;li&gt;Added &lt;code&gt;sockpuppetbrowser&lt;/code&gt; to enable Playwright Chromium/Javascript fetch method&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Changedetection.io&lt;/strong&gt; is a powerful open-source tool that monitors websites for changes. It&amp;rsquo;s incredibly useful for tracking updates on pages that don&amp;rsquo;t offer their own notification systems. This guide will walk you through setting it up on your Synology NAS using Docker Compose.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&#34;changedetection&#34; loading=&#34;lazy&#34; src=&#34;https://kunat.dev/notes/images/changedetection.jpg&#34;&gt;&lt;/p&gt;
&lt;h2 id=&#34;prerequisites&#34;&gt;Prerequisites&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Docker installed on your system by following the &lt;a href=&#34;https://trash-guides.info/File-and-Folder-Structure/How-to-set-up/Synology/&#34; target=&#34;_blank&#34; &gt;TrashGuides setup for Synology&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;installation&#34;&gt;Installation&lt;/h2&gt;
&lt;p&gt;Append this configuration to your &lt;code&gt;docker-compose.yml&lt;/code&gt; file. If you&amp;rsquo;ve followed the guide mentioned above, this file should be located in your Docker application data directory (e.g., &lt;code&gt;/volume1/docker/appdata&lt;/code&gt;).&lt;/p&gt;</description>
      <content:encoded><![CDATA[<blockquote>
<p>Note: This article was originally published 05/2025. Last update 08/2025. Changes:</p></blockquote>
<ul>
<li>Added <code>sockpuppetbrowser</code> to enable Playwright Chromium/Javascript fetch method</li>
</ul>
<p><strong>Changedetection.io</strong> is a powerful open-source tool that monitors websites for changes. It&rsquo;s incredibly useful for tracking updates on pages that don&rsquo;t offer their own notification systems. This guide will walk you through setting it up on your Synology NAS using Docker Compose.</p>
<p><img alt="changedetection" loading="lazy" src="/notes/images/changedetection.jpg"></p>
<h2 id="prerequisites">Prerequisites</h2>
<ul>
<li>Docker installed on your system by following the <a href="https://trash-guides.info/File-and-Folder-Structure/How-to-set-up/Synology/" target="_blank" >TrashGuides setup for Synology</a>.</li>
</ul>
<h2 id="installation">Installation</h2>
<p>Append this configuration to your <code>docker-compose.yml</code> file. If you&rsquo;ve followed the guide mentioned above, this file should be located in your Docker application data directory (e.g., <code>/volume1/docker/appdata</code>).</p>
<p>This configuration sets up a changedetection container along with sockpuppetbrowser, which enables you to use the <code>Playwright Chromium/Javascript</code> fetch method. It&rsquo;s handy in cases where a site requires JavaScript to load. It&rsquo;s still best to use <code>Basic fast Plaintext/HTTP Client</code> as the default for your change detection watch entries.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-yaml" data-lang="yaml"><span style="display:flex;"><span>  <span style="color:#f92672">changedetection</span>:
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">image</span>: <span style="color:#ae81ff">lscr.io/linuxserver/changedetection.io:latest</span>
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">container_name</span>: <span style="color:#ae81ff">changedetection</span>
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">restart</span>: <span style="color:#ae81ff">unless-stopped</span>
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">logging</span>:
</span></span><span style="display:flex;"><span>      <span style="color:#f92672">driver</span>: <span style="color:#ae81ff">json-file</span>
</span></span><span style="display:flex;"><span>      <span style="color:#f92672">options</span>:
</span></span><span style="display:flex;"><span>        <span style="color:#f92672">max-file</span>: <span style="color:#ae81ff">${DOCKERLOGGING_MAXFILE}</span>
</span></span><span style="display:flex;"><span>        <span style="color:#f92672">max-size</span>: <span style="color:#ae81ff">${DOCKERLOGGING_MAXSIZE}</span>
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">environment</span>:
</span></span><span style="display:flex;"><span>      - <span style="color:#ae81ff">PUID=${PUID}</span>
</span></span><span style="display:flex;"><span>      - <span style="color:#ae81ff">PGID=${PGID}</span>
</span></span><span style="display:flex;"><span>      - <span style="color:#ae81ff">TZ=${TZ}</span>
</span></span><span style="display:flex;"><span>      - <span style="color:#ae81ff">PLAYWRIGHT_DRIVER_URL=ws://browser-sockpuppet-chrome:3000</span>
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">volumes</span>:
</span></span><span style="display:flex;"><span>      - <span style="color:#ae81ff">${DOCKERCONFDIR}/changedetection:/config</span>
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">ports</span>:
</span></span><span style="display:flex;"><span>      - <span style="color:#ae81ff">5555</span>:<span style="color:#ae81ff">5000</span>
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">depends_on</span>:
</span></span><span style="display:flex;"><span>      - <span style="color:#ae81ff">browser-sockpuppet-chrome</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">browser-sockpuppet-chrome</span>:
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">hostname</span>: <span style="color:#ae81ff">browser-sockpuppet-chrome</span>
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">image</span>: <span style="color:#ae81ff">dgtlmoon/sockpuppetbrowser:latest</span>
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">container_name</span>: <span style="color:#ae81ff">browser-sockpuppet-chrome</span>
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">cap_add</span>:
</span></span><span style="display:flex;"><span>      - <span style="color:#ae81ff">SYS_ADMIN</span>
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">restart</span>: <span style="color:#ae81ff">unless-stopped</span>
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">logging</span>:
</span></span><span style="display:flex;"><span>      <span style="color:#f92672">driver</span>: <span style="color:#ae81ff">json-file</span>
</span></span><span style="display:flex;"><span>      <span style="color:#f92672">options</span>:
</span></span><span style="display:flex;"><span>        <span style="color:#f92672">max-file</span>: <span style="color:#ae81ff">${DOCKERLOGGING_MAXFILE}</span>
</span></span><span style="display:flex;"><span>        <span style="color:#f92672">max-size</span>: <span style="color:#ae81ff">${DOCKERLOGGING_MAXSIZE}</span>
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">environment</span>:
</span></span><span style="display:flex;"><span>      - <span style="color:#ae81ff">SCREEN_WIDTH=1920</span>
</span></span><span style="display:flex;"><span>      - <span style="color:#ae81ff">SCREEN_HEIGHT=1024</span>
</span></span><span style="display:flex;"><span>      - <span style="color:#ae81ff">SCREEN_DEPTH=16</span>
</span></span><span style="display:flex;"><span>      - <span style="color:#ae81ff">MAX_CONCURRENT_CHROME_PROCESSES=10</span>
</span></span></code></pre></div><p><strong>Note on Environment Variables:</strong></p>
<ul>
<li>The <code>PUID</code>, <code>PGID</code>, and <code>TZ</code> environment variables above are set consistently with your other containers.</li>
</ul>
<p>Start the container by running this command in the directory containing your <code>docker-compose.yml</code> file:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>docker compose up -d
</span></span></code></pre></div><p>This command launches Changedetection.io in detached mode, meaning it runs in the background. You should then be able to access it by navigating to <code>http://&lt;your-synology-ip&gt;:5000</code> in your web browser.</p>
<h2 id="troubleshooting">Troubleshooting</h2>
<p>If you encounter issues accessing Changedetection.io, try running the container without the <code>-d</code> flag (e.g., <code>docker compose up</code>) to view the live logs directly.</p>
<p>During my initial setup, I discovered that the default host port (<code>5000</code>) was already in use on my Synology. You can resolve such a port conflict by updating the <code>host</code> port (the first number in the <code>ports</code> section) like so:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-yaml" data-lang="yaml"><span style="display:flex;"><span><span style="color:#f92672">ports</span>:
</span></span><span style="display:flex;"><span>  - <span style="color:#f92672">NEW_PORT:5000 # Example</span>: <span style="color:#ae81ff">5001</span>:<span style="color:#ae81ff">5000</span>
</span></span></code></pre></div><blockquote>
<p>The <strong>Container Port</strong> (the right-hand side of the colon, e.g., <code>5000</code> in <code>NEW_PORT:5000</code>) is the port that the application <em>inside</em> the Docker container is programmed to listen on. The Changedetection.io application is configured by its developers to listen on port 5000 within its isolated container environment. Changing this internal container port would require modifying the application&rsquo;s internal configuration, which is generally more complex and unnecessary for resolving a host port conflict.</p></blockquote>
<h2 id="resources">Resources</h2>
<ul>
<li><a href="https://github.com/dgtlmoon/changedetection.io" target="_blank" >Changedetection.io GitHub Repository (includes documentation)</a></li>
<li><a href="https://hub.docker.com/r/linuxserver/changedetection.io" target="_blank" >LinuxServer.io Changedetection.io on Docker Hub</a></li>
</ul>
]]></content:encoded>
    </item>
    <item>
      <title>Setting Up qBittorrent with Private Internet Access (PIA) VPN on Synology NAS</title>
      <link>https://kunat.dev/notes/synology-qbitorrent-vpn-pia/</link>
      <pubDate>Sat, 12 Apr 2025 20:43:57 +0200</pubDate>
      <guid>https://kunat.dev/notes/synology-qbitorrent-vpn-pia/</guid>
      <description>&lt;h2 id=&#34;prerequisites&#34;&gt;Prerequisites&lt;/h2&gt;
&lt;p&gt;Before you start, you should have qBittorrent up and running using &lt;a href=&#34;https://trash-guides.info/File-and-Folder-Structure/How-to-set-up/Synology/&#34; target=&#34;_blank&#34; &gt;this&lt;/a&gt; guide.&lt;/p&gt;
&lt;h2 id=&#34;implementation&#34;&gt;Implementation&lt;/h2&gt;
&lt;p&gt;If you&amp;rsquo;ve used the guide linked above, the qBittorrent container is already running. There are two configuration files that we&amp;rsquo;ll need to edit: &lt;code&gt;.env&lt;/code&gt; and &lt;code&gt;docker-compose.yml&lt;/code&gt;.&lt;/p&gt;
&lt;h3 id=&#34;env&#34;&gt;.env&lt;/h3&gt;
&lt;p&gt;Make sure the &lt;code&gt;LAN_NETWORK&lt;/code&gt; variable is set properly. If you haven&amp;rsquo;t modified it after the initial setup, it should be set to &lt;code&gt;192.168.x.0/24&lt;/code&gt;. Update it so that your Synology&amp;rsquo;s LAN IP is within the address range. Example: since my Synology&amp;rsquo;s LAN IP address is 192.168.1.110, I&amp;rsquo;ve replaced &lt;code&gt;x&lt;/code&gt; with &lt;code&gt;1&lt;/code&gt;: &lt;code&gt;192.168.1.0/24&lt;/code&gt;.&lt;/p&gt;</description>
      <content:encoded><![CDATA[<h2 id="prerequisites">Prerequisites</h2>
<p>Before you start, you should have qBittorrent up and running using <a href="https://trash-guides.info/File-and-Folder-Structure/How-to-set-up/Synology/" target="_blank" >this</a> guide.</p>
<h2 id="implementation">Implementation</h2>
<p>If you&rsquo;ve used the guide linked above, the qBittorrent container is already running. There are two configuration files that we&rsquo;ll need to edit: <code>.env</code> and <code>docker-compose.yml</code>.</p>
<h3 id="env">.env</h3>
<p>Make sure the <code>LAN_NETWORK</code> variable is set properly. If you haven&rsquo;t modified it after the initial setup, it should be set to <code>192.168.x.0/24</code>. Update it so that your Synology&rsquo;s LAN IP is within the address range. Example: since my Synology&rsquo;s LAN IP address is 192.168.1.110, I&rsquo;ve replaced <code>x</code> with <code>1</code>: <code>192.168.1.0/24</code>.</p>
<p>Set <code>VPN_ENABLED</code> to <code>true</code></p>
<p>Set <code>VPN_PROVIDER</code> to <code>pia</code></p>
<blockquote>
<p>Hotio&rsquo;s qBittorrent image also supports Proton VPN out of the box. You should be able to use it with any provider that supports the WireGuard protocol.</p></blockquote>
<p>If you&rsquo;re using PIA or Proton, set <code>PORT_FORWARD</code> to true.</p>
<p>Add the following variables:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-shell" data-lang="shell"><span style="display:flex;"><span>VPN_PIA_USER<span style="color:#f92672">=</span>YOUR_PIA_USERNAME
</span></span><span style="display:flex;"><span>VPN_PIA_PASS<span style="color:#f92672">=</span>YOUR_PIA_PASSWORD
</span></span><span style="display:flex;"><span>VPN_PIA_PREFERRED_REGION<span style="color:#f92672">=</span>belgium <span style="color:#75715e"># optional</span>
</span></span></code></pre></div><p>Since port forwarding is disabled in some of the regions supported by PIA VPN, you might want to also set <code>VPN_PIA_PREFERRED_REGION</code>. You can see all available regions in <code>docker/appdata/qbittorrent/wireguard/pia-regions.json</code>. This file will be created the first time you run the container after setting your PIA username and password.</p>
<h3 id="docker-composeyml">docker-compose.yml</h3>
<p>Uncomment the <code>devices</code> section in <code>qbittorrent</code>:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-yml" data-lang="yml"><span style="display:flex;"><span><span style="color:#f92672">devices</span>:
</span></span><span style="display:flex;"><span>  - <span style="color:#ae81ff">/dev/net/tun:/dev/net/tun</span>
</span></span></code></pre></div><p>Add the following variables to the <code>environment</code> section:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-shell" data-lang="shell"><span style="display:flex;"><span>VPN_PIA_USER<span style="color:#f92672">=</span><span style="color:#e6db74">${</span>VPN_PIA_USER<span style="color:#e6db74">}</span>
</span></span><span style="display:flex;"><span>VPN_PIA_PASS<span style="color:#f92672">=</span><span style="color:#e6db74">${</span>VPN_PIA_PASS<span style="color:#e6db74">}</span>
</span></span><span style="display:flex;"><span>VPN_PIA_PREFERRED_REGION<span style="color:#f92672">=</span><span style="color:#e6db74">${</span>VPN_PIA_PREFERRED_REGION<span style="color:#e6db74">}</span>
</span></span></code></pre></div><p>Here&rsquo;s how your qBittorrent container definition should look:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-shell" data-lang="shell"><span style="display:flex;"><span>qbittorrent:
</span></span><span style="display:flex;"><span>  container_name: qbittorrent
</span></span><span style="display:flex;"><span>  image: hotio/qbittorrent:latest
</span></span><span style="display:flex;"><span>  restart: unless-stopped
</span></span><span style="display:flex;"><span>  logging:
</span></span><span style="display:flex;"><span>    driver: json-file
</span></span><span style="display:flex;"><span>    options:
</span></span><span style="display:flex;"><span>      max-file: <span style="color:#e6db74">${</span>DOCKERLOGGING_MAXFILE<span style="color:#e6db74">}</span>
</span></span><span style="display:flex;"><span>      max-size: <span style="color:#e6db74">${</span>DOCKERLOGGING_MAXSIZE<span style="color:#e6db74">}</span>
</span></span><span style="display:flex;"><span>  labels:
</span></span><span style="display:flex;"><span>    - org.hotio.pullio.update<span style="color:#f92672">=</span><span style="color:#e6db74">${</span>PULLIO_UPDATE<span style="color:#e6db74">}</span>
</span></span><span style="display:flex;"><span>    - org.hotio.pullio.notify<span style="color:#f92672">=</span><span style="color:#e6db74">${</span>PULLIO_NOTIFY<span style="color:#e6db74">}</span>
</span></span><span style="display:flex;"><span>    - org.hotio.pullio.discord.webhook<span style="color:#f92672">=</span><span style="color:#e6db74">${</span>PULLIO_DISCORD_WEBHOOK<span style="color:#e6db74">}</span>
</span></span><span style="display:flex;"><span>  ports:
</span></span><span style="display:flex;"><span>    - <span style="color:#e6db74">${</span>QBITTORRENT_WEBUI_PORT<span style="color:#e6db74">}</span>:<span style="color:#e6db74">${</span>QBITTORRENT_WEBUI_PORT<span style="color:#e6db74">}</span>
</span></span><span style="display:flex;"><span>    - <span style="color:#e6db74">${</span>QBITTORRENT_PRIVOXY_PORT<span style="color:#e6db74">}</span>:<span style="color:#e6db74">${</span>QBITTORRENT_PRIVOXY_PORT<span style="color:#e6db74">}</span>
</span></span><span style="display:flex;"><span>  cap_add:
</span></span><span style="display:flex;"><span>    - NET_ADMIN
</span></span><span style="display:flex;"><span>  devices:                              
</span></span><span style="display:flex;"><span>    - /dev/net/tun:/dev/net/tun         
</span></span><span style="display:flex;"><span>  sysctls:
</span></span><span style="display:flex;"><span>    - net.ipv4.conf.all.src_valid_mark<span style="color:#f92672">=</span><span style="color:#ae81ff">1</span>
</span></span><span style="display:flex;"><span>    - net.ipv6.conf.all.disable_ipv6<span style="color:#f92672">=</span><span style="color:#ae81ff">1</span>  
</span></span><span style="display:flex;"><span>  environment:
</span></span><span style="display:flex;"><span>    - PUID<span style="color:#f92672">=</span><span style="color:#e6db74">${</span>PUID<span style="color:#e6db74">}</span>
</span></span><span style="display:flex;"><span>    - PGID<span style="color:#f92672">=</span><span style="color:#e6db74">${</span>PGID<span style="color:#e6db74">}</span>
</span></span><span style="display:flex;"><span>    - TZ<span style="color:#f92672">=</span><span style="color:#e6db74">${</span>TZ<span style="color:#e6db74">}</span>
</span></span><span style="display:flex;"><span>    - UMASK<span style="color:#f92672">=</span><span style="color:#ae81ff">002</span>
</span></span><span style="display:flex;"><span>    - VPN_ENABLED<span style="color:#f92672">=</span><span style="color:#e6db74">${</span>VPN_ENABLED<span style="color:#e6db74">}</span>
</span></span><span style="display:flex;"><span>    - VPN_FIREWALL_TYPE<span style="color:#f92672">=</span>legacy
</span></span><span style="display:flex;"><span>    - VPN_PROVIDER<span style="color:#f92672">=</span><span style="color:#e6db74">${</span>VPN_PROVIDER<span style="color:#e6db74">}</span>
</span></span><span style="display:flex;"><span>    - VPN_LAN_NETWORK<span style="color:#f92672">=</span><span style="color:#e6db74">${</span>LAN_NETWORK<span style="color:#e6db74">}</span>
</span></span><span style="display:flex;"><span>    - VPN_CONF<span style="color:#f92672">=</span>wg0-fix
</span></span><span style="display:flex;"><span>    - VPN_AUTO_PORT_FORWARD<span style="color:#f92672">=</span><span style="color:#e6db74">${</span>PORT_FORWARD<span style="color:#e6db74">}</span>
</span></span><span style="display:flex;"><span>    - VPN_PIA_USER<span style="color:#f92672">=</span><span style="color:#e6db74">${</span>VPN_PIA_USER<span style="color:#e6db74">}</span>
</span></span><span style="display:flex;"><span>    - VPN_PIA_PASS<span style="color:#f92672">=</span><span style="color:#e6db74">${</span>VPN_PIA_PASS<span style="color:#e6db74">}</span>
</span></span><span style="display:flex;"><span>    - VPN_PIA_PREFERRED_REGION<span style="color:#f92672">=</span><span style="color:#e6db74">${</span>VPN_PIA_PREFERRED_REGION<span style="color:#e6db74">}</span>
</span></span><span style="display:flex;"><span>    - VPN_HEALTHCHECK_ENABLED<span style="color:#f92672">=</span>false
</span></span><span style="display:flex;"><span>    - PRIVOXY_ENABLED<span style="color:#f92672">=</span><span style="color:#e6db74">${</span>QBITTORRENT_ENABLE_PRIVOXY<span style="color:#e6db74">}</span>
</span></span><span style="display:flex;"><span>    - WEBUI_PORTS<span style="color:#f92672">=</span><span style="color:#e6db74">${</span>QBITTORRENT_WEBUI_PORT<span style="color:#e6db74">}</span>/tcp,<span style="color:#e6db74">${</span>QBITTORRENT_WEBUI_PORT<span style="color:#e6db74">}</span>/udp 
</span></span><span style="display:flex;"><span>  dns:
</span></span><span style="display:flex;"><span>    - 1.1.1.1
</span></span><span style="display:flex;"><span>    - 8.8.8.8
</span></span><span style="display:flex;"><span>  volumes:
</span></span><span style="display:flex;"><span>    - /etc/localtime:/etc/localtime:ro
</span></span><span style="display:flex;"><span>    - <span style="color:#e6db74">${</span>DOCKERCONFDIR<span style="color:#e6db74">}</span>/qbittorrent:/config:rw
</span></span><span style="display:flex;"><span>    - <span style="color:#e6db74">${</span>DOCKERSTORAGEDIR<span style="color:#e6db74">}</span>/torrents:/data/torrents:rw
</span></span></code></pre></div><h3 id="setting-up-tun-service">Setting up tun service</h3>
<blockquote>
<p><code>/dev/net/tun</code> is a kernel module that provides a network tunnel interface. On Synology NAS systems, it&rsquo;s used by VPN applications and other networking tools like qBittorrent with VPN functionality.</p></blockquote>
<p><a href="https://amoklauf.ch/posts/synology/tunservice/" target="_blank" >Installing the Tun Service for Synology and VPN</a></p>
<h2 id="testing-changes">Testing Changes</h2>
<p>With everything done, you need to try running the container with the latest changes:
<code>sudo docker-compose up --force-recreate qbittorrent</code></p>
<p>Here&rsquo;s a sample output from a successful startup:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-shell" data-lang="shell"><span style="display:flex;"><span>qbittorrent  | s6-rc: info: service init-wireguard successfully started
</span></span><span style="display:flex;"><span>qbittorrent  | s6-rc: info: service service-qbittorrent: starting
</span></span><span style="display:flex;"><span>qbittorrent  | s6-rc: info: service service-pia: starting
</span></span><span style="display:flex;"><span>qbittorrent  | s6-rc: info: service service-forwarder: starting
</span></span><span style="display:flex;"><span>qbittorrent  | s6-rc: info: service service-qbittorrent successfully started
</span></span><span style="display:flex;"><span>qbittorrent  | s6-rc: info: service service-pia successfully started
</span></span><span style="display:flex;"><span>qbittorrent  | s6-rc: info: service service-forwarder successfully started
</span></span><span style="display:flex;"><span>qbittorrent  | s6-rc: info: service legacy-services: starting
</span></span><span style="display:flex;"><span>qbittorrent  | <span style="color:#f92672">[</span>INF<span style="color:#f92672">]</span> <span style="color:#f92672">[</span>2025-04-12 20:23:44<span style="color:#f92672">]</span> <span style="color:#f92672">[</span>PIA<span style="color:#f92672">]</span> Fetching new forwarded port...
</span></span><span style="display:flex;"><span>qbittorrent  | s6-rc: info: service legacy-services successfully started
</span></span><span style="display:flex;"><span>qbittorrent  | <span style="color:#f92672">[</span>INF<span style="color:#f92672">]</span> <span style="color:#f92672">[</span>2025-04-12 20:23:44<span style="color:#f92672">]</span> <span style="color:#f92672">[</span>PIA<span style="color:#f92672">]</span> Forwarded port will expire at <span style="color:#f92672">[</span>2025-06-14T06:23:44.166007524Z<span style="color:#f92672">]</span>.
</span></span><span style="display:flex;"><span>qbittorrent  | 
</span></span><span style="display:flex;"><span>qbittorrent  | *** Legal Notice ***
</span></span><span style="display:flex;"><span>qbittorrent  | qBittorrent is a file sharing program. When you run a torrent, its data will be made available to others by means of upload. Any content you share is your sole responsibility.
</span></span><span style="display:flex;"><span>qbittorrent  | 
</span></span><span style="display:flex;"><span>qbittorrent  | If you have read the legal notice, you can use command line option <span style="color:#e6db74">`</span>--confirm-legal-notice<span style="color:#e6db74">`</span> to suppress this message.
</span></span><span style="display:flex;"><span>qbittorrent  | 
</span></span><span style="display:flex;"><span>qbittorrent  | WebUI will be started shortly after internal preparations. Please wait...
</span></span><span style="display:flex;"><span>qbittorrent  | 
</span></span><span style="display:flex;"><span>qbittorrent  | <span style="color:#f92672">[</span>INF<span style="color:#f92672">]</span> <span style="color:#f92672">[</span>2025-04-12 20:23:54<span style="color:#f92672">]</span> <span style="color:#f92672">[</span>VPN<span style="color:#f92672">]</span> Forwarded port is <span style="color:#f92672">[</span>REDACTED<span style="color:#f92672">]</span>.
</span></span><span style="display:flex;"><span>qbittorrent  | 
</span></span><span style="display:flex;"><span>qbittorrent  | ******** Information ********
</span></span><span style="display:flex;"><span>qbittorrent  | To control qBittorrent, access the WebUI at: http://localhost:8080
</span></span><span style="display:flex;"><span>qbittorrent  | 
</span></span><span style="display:flex;"><span>qbittorrent  | <span style="color:#f92672">[</span>INF<span style="color:#f92672">]</span> <span style="color:#f92672">[</span>2025-04-12 20:24:04<span style="color:#f92672">]</span> <span style="color:#f92672">[</span>QBITTORRENT<span style="color:#f92672">]</span> Updated forwarded port to <span style="color:#f92672">[</span>REDACTED<span style="color:#f92672">]</span>.
</span></span></code></pre></div><h2 id="troubleshooting">Troubleshooting</h2>
<p>The only issue I&rsquo;ve encountered was with the <code>/dev/net/tun</code> module. It had overly restrictive permission settings:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-shell" data-lang="shell"><span style="display:flex;"><span>ls -al /dev/net/tun
</span></span><span style="display:flex;"><span><span style="color:#75715e"># Overly restrictive; should return `crw-rw---- root root`</span>
</span></span><span style="display:flex;"><span>crw------- <span style="color:#ae81ff">1</span> root root 10, <span style="color:#ae81ff">200</span> Feb <span style="color:#ae81ff">13</span> 02:14 /dev/net/tun
</span></span></code></pre></div><p>The qBittorrent container needs at least <strong>660</strong> permission. You can fix that by executing:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-shell" data-lang="shell"><span style="display:flex;"><span>sudo chmod <span style="color:#ae81ff">660</span> /dev/net/tun  <span style="color:#75715e"># Allow root group access</span>
</span></span></code></pre></div><h2 id="verifying-vpn-works">Verifying VPN Works</h2>
<p>To verify that the qBittorrent container is hidden behind a VPN, you can use <a href="https://ipleak.net/" target="_blank" >IP/DNS Detect</a> (<code>Torrent Address detection</code>).</p>
<h2 id="resources">Resources</h2>
<ul>
<li><a href="https://hotio.dev/containers/qbittorrent/" target="_blank" >hotio/qbittorrent</a></li>
</ul>
]]></content:encoded>
    </item>
    <item>
      <title>Homarr Synology Setup with Docker Compose</title>
      <link>https://kunat.dev/notes/homarr-synology-setup/</link>
      <pubDate>Sat, 04 Jan 2025 19:00:37 +0100</pubDate>
      <guid>https://kunat.dev/notes/homarr-synology-setup/</guid>
      <description>&lt;p&gt;Homarr creates a customizable browser homepage that lets you manage and interact with Docker containers running on your homeserver. Here&amp;rsquo;s my dashboard setup:&lt;/p&gt;
&lt;p&gt;&lt;img alt=&#34;hello there&#34; loading=&#34;lazy&#34; src=&#34;https://kunat.dev/notes/images/homarr-dashboard.png&#34;&gt;&lt;/p&gt;
&lt;h2 id=&#34;prerequisites&#34;&gt;Prerequisites&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Docker installed on your system (follow &lt;a href=&#34;https://trash-guides.info/File-and-Folder-Structure/How-to-set-up/Synology/&#34; target=&#34;_blank&#34; &gt;this Synology setup guide&lt;/a&gt;)&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;installation&#34;&gt;Installation&lt;/h2&gt;
&lt;p&gt;Append this configuration to your &lt;code&gt;docker-compose.yml&lt;/code&gt; file:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-yaml&#34; data-lang=&#34;yaml&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;homarr&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#f92672&#34;&gt;container_name&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;homarr&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#f92672&#34;&gt;image&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;ghcr.io/ajnart/homarr:latest&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#f92672&#34;&gt;restart&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;unless-stopped&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#f92672&#34;&gt;logging&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f92672&#34;&gt;driver&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;json-file&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f92672&#34;&gt;options&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          &lt;span style=&#34;color:#f92672&#34;&gt;max-file&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;${DOCKERLOGGING_MAXFILE}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          &lt;span style=&#34;color:#f92672&#34;&gt;max-size&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;${DOCKERLOGGING_MAXSIZE}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#f92672&#34;&gt;environment&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        - &lt;span style=&#34;color:#ae81ff&#34;&gt;PUID=${PUID}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        - &lt;span style=&#34;color:#ae81ff&#34;&gt;PGID=${PGID}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        - &lt;span style=&#34;color:#ae81ff&#34;&gt;TZ=${TZ}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#f92672&#34;&gt;volumes&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        - &lt;span style=&#34;color:#ae81ff&#34;&gt;${DOCKERCONFDIR}/homarr/configs:/app/data/configs&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        - &lt;span style=&#34;color:#ae81ff&#34;&gt;${DOCKERCONFDIR}/homarr/icons:/app/public/icons&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        - &lt;span style=&#34;color:#ae81ff&#34;&gt;${DOCKERCONFDIR}/homarr/data:/data&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#f92672&#34;&gt;ports&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        - &lt;span style=&#34;color:#ae81ff&#34;&gt;7575&lt;/span&gt;:&lt;span style=&#34;color:#ae81ff&#34;&gt;7575&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Start the container by running this command in your docker directory (typically &lt;code&gt;/volume1/docker/appdata&lt;/code&gt;):&lt;/p&gt;</description>
      <content:encoded><![CDATA[<p>Homarr creates a customizable browser homepage that lets you manage and interact with Docker containers running on your homeserver. Here&rsquo;s my dashboard setup:</p>
<p><img alt="hello there" loading="lazy" src="/notes/images/homarr-dashboard.png"></p>
<h2 id="prerequisites">Prerequisites</h2>
<ul>
<li>Docker installed on your system (follow <a href="https://trash-guides.info/File-and-Folder-Structure/How-to-set-up/Synology/" target="_blank" >this Synology setup guide</a>)</li>
</ul>
<h2 id="installation">Installation</h2>
<p>Append this configuration to your <code>docker-compose.yml</code> file:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-yaml" data-lang="yaml"><span style="display:flex;"><span>  <span style="color:#f92672">homarr</span>:
</span></span><span style="display:flex;"><span>      <span style="color:#f92672">container_name</span>: <span style="color:#ae81ff">homarr</span>
</span></span><span style="display:flex;"><span>      <span style="color:#f92672">image</span>: <span style="color:#ae81ff">ghcr.io/ajnart/homarr:latest</span>
</span></span><span style="display:flex;"><span>      <span style="color:#f92672">restart</span>: <span style="color:#ae81ff">unless-stopped</span>
</span></span><span style="display:flex;"><span>      <span style="color:#f92672">logging</span>:
</span></span><span style="display:flex;"><span>        <span style="color:#f92672">driver</span>: <span style="color:#ae81ff">json-file</span>
</span></span><span style="display:flex;"><span>        <span style="color:#f92672">options</span>:
</span></span><span style="display:flex;"><span>          <span style="color:#f92672">max-file</span>: <span style="color:#ae81ff">${DOCKERLOGGING_MAXFILE}</span>
</span></span><span style="display:flex;"><span>          <span style="color:#f92672">max-size</span>: <span style="color:#ae81ff">${DOCKERLOGGING_MAXSIZE}</span>
</span></span><span style="display:flex;"><span>      <span style="color:#f92672">environment</span>:
</span></span><span style="display:flex;"><span>        - <span style="color:#ae81ff">PUID=${PUID}</span>
</span></span><span style="display:flex;"><span>        - <span style="color:#ae81ff">PGID=${PGID}</span>
</span></span><span style="display:flex;"><span>        - <span style="color:#ae81ff">TZ=${TZ}</span>
</span></span><span style="display:flex;"><span>      <span style="color:#f92672">volumes</span>:
</span></span><span style="display:flex;"><span>        - <span style="color:#ae81ff">${DOCKERCONFDIR}/homarr/configs:/app/data/configs</span>
</span></span><span style="display:flex;"><span>        - <span style="color:#ae81ff">${DOCKERCONFDIR}/homarr/icons:/app/public/icons</span>
</span></span><span style="display:flex;"><span>        - <span style="color:#ae81ff">${DOCKERCONFDIR}/homarr/data:/data</span>
</span></span><span style="display:flex;"><span>      <span style="color:#f92672">ports</span>:
</span></span><span style="display:flex;"><span>        - <span style="color:#ae81ff">7575</span>:<span style="color:#ae81ff">7575</span>
</span></span></code></pre></div><p>Start the container by running this command in your docker directory (typically <code>/volume1/docker/appdata</code>):</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>docker compose up -d
</span></span></code></pre></div><p>This launches Homarr in detached mode (running in the background).</p>
<h2 id="resources">Resources</h2>
<ul>
<li><a href="https://homarr.dev/docs/getting-started/installation" target="_blank" >Official Homarr Installation Guide</a></li>
</ul>
]]></content:encoded>
    </item>
    <item>
      <title>Verifying VPN Status for Docker qBittorrent on Synology</title>
      <link>https://kunat.dev/notes/check-torrent-client-vpn-ip/</link>
      <pubDate>Sat, 30 Nov 2024 22:09:34 +0100</pubDate>
      <guid>https://kunat.dev/notes/check-torrent-client-vpn-ip/</guid>
      <description>&lt;p&gt;I run &lt;code&gt;qbittorrent&lt;/code&gt; in a Docker container on my Synology NAS, with VPN configured at the Synology system level (Control Panel -&amp;gt; Network -&amp;gt; Network Interface) rather than the container level. For setup instructions, you can follow &lt;a href=&#34;https://blog.held.codes/how-to-use-mullvad-vpn-on-synology-nas-ed7a2ceb9595&#34; target=&#34;_blank&#34; &gt;this guide&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Even with killswitch enabled, I wanted to verify beyond the UI&amp;rsquo;s &amp;ldquo;Firewalled&amp;rdquo; status that my torrent traffic was actually routing through the VPN.&lt;/p&gt;
&lt;p&gt;To check this, SSH into your Synology NAS and run:&lt;/p&gt;</description>
      <content:encoded><![CDATA[<p>I run <code>qbittorrent</code> in a Docker container on my Synology NAS, with VPN configured at the Synology system level (Control Panel -&gt; Network -&gt; Network Interface) rather than the container level. For setup instructions, you can follow <a href="https://blog.held.codes/how-to-use-mullvad-vpn-on-synology-nas-ed7a2ceb9595" target="_blank" >this guide</a>.</p>
<p>Even with killswitch enabled, I wanted to verify beyond the UI&rsquo;s &ldquo;Firewalled&rdquo; status that my torrent traffic was actually routing through the VPN.</p>
<p>To check this, SSH into your Synology NAS and run:</p>
<pre tabindex="0"><code>sudo docker exec qbittorrent curl ifconfig.me
</code></pre><p>This command retrieves the container&rsquo;s public IP address. If it matches your VPN IP address rather than your real IP, you&rsquo;ve confirmed that the container&rsquo;s traffic is properly routing through the VPN.</p>
]]></content:encoded>
    </item>
    <item>
      <title>Setting up AdGuard Home on Synology NAS with Tailscale</title>
      <link>https://kunat.dev/notes/adguard-home-synology-tailscale/</link>
      <pubDate>Thu, 08 Aug 2024 22:06:39 +0200</pubDate>
      <guid>https://kunat.dev/notes/adguard-home-synology-tailscale/</guid>
      <description>&lt;h1 id=&#34;setting-up-adguard-home-as-a-docker-container-on-synology-nas&#34;&gt;Setting up AdGuard Home as a Docker Container on Synology NAS&lt;/h1&gt;
&lt;p&gt;In this guide, I&amp;rsquo;ll walk you through the steps to set up AdGuard Home (AGH) as a Docker container on a Synology NAS. This setup will allow you to use AGH both inside and outside of your home network.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;a href=&#34;https://github.com/AdguardTeam/AdGuardSDNSFilter&#34; target=&#34;_blank&#34; &gt;AdGuard Home&lt;/a&gt; is a network-wide DNS server that blocks ads and trackers for all devices on your network. It filters unwanted content before it reaches your devices, eliminating the need for individual ad blockers. With customizable rules and open-source flexibility, it offers comprehensive protection and can be installed on various platforms, including Raspberry Pi.&lt;/p&gt;</description>
      <content:encoded><![CDATA[<h1 id="setting-up-adguard-home-as-a-docker-container-on-synology-nas">Setting up AdGuard Home as a Docker Container on Synology NAS</h1>
<p>In this guide, I&rsquo;ll walk you through the steps to set up AdGuard Home (AGH) as a Docker container on a Synology NAS. This setup will allow you to use AGH both inside and outside of your home network.</p>
<blockquote>
<p><a href="https://github.com/AdguardTeam/AdGuardSDNSFilter" target="_blank" >AdGuard Home</a> is a network-wide DNS server that blocks ads and trackers for all devices on your network. It filters unwanted content before it reaches your devices, eliminating the need for individual ad blockers. With customizable rules and open-source flexibility, it offers comprehensive protection and can be installed on various platforms, including Raspberry Pi.</p></blockquote>
<h2 id="prerequisites">Prerequisites</h2>
<ul>
<li>Basic Docker setup running on your Synology NAS (users, permissions, folders)
<ul>
<li>I highly recommend following the <a href="https://trash-guides.info/Hardlinks/How-to-setup-for/Synology/" target="_blank" >Synology | TRaSH Guides</a></li>
</ul>
</li>
</ul>
<p>The following steps assume you have a setup similar (ideally identical) to the one from the article linked above. The most important aspects are user permissions and folder structure.</p>
<h2 id="configuration">Configuration</h2>
<h3 id="env">.env:</h3>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-yml" data-lang="yml"><span style="display:flex;"><span><span style="color:#75715e">## Edit/update your settings that will be used for your docker-compose</span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">## This will only work if you follow exactly the path structure in the Guide!</span>
</span></span><span style="display:flex;"><span><span style="color:#ae81ff">COMPOSE_PROJECT_NAME=trash-guides</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">## Global Settings</span>
</span></span><span style="display:flex;"><span><span style="color:#75715e"># Change &#34;/volume1/docker/appdata&#34; to your config path</span>
</span></span><span style="display:flex;"><span><span style="color:#ae81ff">DOCKERCONFDIR=/volume1/docker/appdata</span>
</span></span><span style="display:flex;"><span><span style="color:#75715e"># Change &#34;/volume1/data&#34; to your library + torrent/usenet downloads path</span>
</span></span><span style="display:flex;"><span><span style="color:#ae81ff">DOCKERSTORAGEDIR=/volume1/data</span>
</span></span><span style="display:flex;"><span><span style="color:#75715e"># Find your PUID/PGID through SSH, run in terminal: id $user</span>
</span></span><span style="display:flex;"><span><span style="color:#75715e"># Change $user to the user you created if needed</span>
</span></span><span style="display:flex;"><span><span style="color:#ae81ff">PUID=XXXX</span>
</span></span><span style="display:flex;"><span><span style="color:#ae81ff">PGID=YYY</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#75715e"># Other app-specific settings and variables</span>
</span></span><span style="display:flex;"><span><span style="color:#75715e"># ...</span>
</span></span></code></pre></div><p>This setup doesn&rsquo;t use any environment variables specific to AGH. The key thing is to set PUID and PGID correctly.</p>
<h3 id="docker-composeyml">docker-compose.yml:</h3>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-yml" data-lang="yml"><span style="display:flex;"><span><span style="color:#f92672">version</span>: <span style="color:#e6db74">&#34;3.2&#34;</span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">services</span>:
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">adguardhome</span>:
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">image</span>: <span style="color:#ae81ff">adguard/adguardhome:latest</span>
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">container_name</span>: <span style="color:#ae81ff">adguardhome</span>
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">network_mode</span>: <span style="color:#ae81ff">host</span>
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">volumes</span>:
</span></span><span style="display:flex;"><span>      - <span style="color:#ae81ff">${DOCKERCONFDIR}/adguardhome/work:/opt/adguardhome/work</span>
</span></span><span style="display:flex;"><span>      - <span style="color:#ae81ff">${DOCKERCONFDIR}/adguardhome/conf:/opt/adguardhome/conf</span>
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">restart</span>: <span style="color:#ae81ff">unless-stopped</span>
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">environment</span>:
</span></span><span style="display:flex;"><span>      - <span style="color:#ae81ff">PUID=${PUID}</span>
</span></span><span style="display:flex;"><span>      - <span style="color:#ae81ff">PGID=${PGID}</span>
</span></span><span style="display:flex;"><span>      - <span style="color:#ae81ff">TZ=${TZ}</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#75715e"># Other containers</span>
</span></span><span style="display:flex;"><span><span style="color:#75715e"># ...</span>
</span></span></code></pre></div><h3 id="folder-structure">Folder structure</h3>
<p><img alt="Folder structure" loading="lazy" src="/notes/images/adguard-home-synology-tailscale/folder-structure.png"></p>
<h2 id="initial-setup">Initial Setup</h2>
<p>After running the container for the first time, complete the initial AGH setup:</p>
<ol>
<li>When asked to choose the network interface for DNS requests, select &ldquo;All Interfaces&rdquo;.</li>
<li>Switch the Web Interface port to 3000 if it&rsquo;s not already set.</li>
<li>Set credentials for your admin account.</li>
</ol>
<p>If you encounter issues, refer to <a href="https://drfrankenstein.co.uk/adguard-home-in-container-manager-on-a-synology-nas/" target="_blank" >this guide</a>.</p>
<h2 id="local-network-setup">Local Network Setup</h2>
<p>To use AGH as your DNS server:</p>
<ol>
<li>Set it on your router (preferred method).</li>
<li>If router modification isn&rsquo;t possible, set it manually for each device on your home WiFi network. Here&rsquo;s a <a href="https://support.nordvpn.com/hc/en-us/articles/20398776567313-Change-your-DNS-servers-on-iOS" target="_blank" >guide for iOS</a>.</li>
</ol>
<p>Use your Synology&rsquo;s local network IP address. Update your DHCP settings to ensure your Synology&rsquo;s local IP address doesn&rsquo;t expire.</p>
<p>With this setup, you&rsquo;ll see the benefits of AGH whenever you&rsquo;re connected to your home network.</p>
<h2 id="remote-setup">Remote Setup</h2>
<p>To use AGH when not on your home network, there are several options:</p>
<ul>
<li>Dynamic DNS (DDNS) and port forwarding</li>
<li>Setting up a VPN server on your NAS</li>
<li>Using Cloudflare Tunnel</li>
<li>Tailscale (the method used in this guide)</li>
</ul>
<blockquote>
<p>Tailscale is a modern, user-friendly virtual private network (VPN) solution that leverages the WireGuard protocol to create secure, peer-to-peer connections between devices. It simplifies network configuration by eliminating the need for traditional VPN servers and complex firewall rules.</p></blockquote>
<p>To set up Tailscale:</p>
<ol>
<li>Set custom DNS in Tailscale admin panel (your Synology&rsquo;s tailnet IP address)</li>
<li>Enable &ldquo;override local DNS&rdquo;
<img alt="Tailscale DNS settings" loading="lazy" src="/notes/images/adguard-home-synology-tailscale/tailscale-admin-panel.png"></li>
<li>Set up Tailscale on all devices you plan to use outside your home network</li>
<li><a href="/notes/adguard-home-advanced-data-protection/" >Set up VPN On-Demand</a></li>
</ol>
<p>With these steps, your device will automatically connect to your Tailscale mesh network, which will use AGH as a DNS server.</p>
<h2 id="cleanup">Cleanup</h2>
<p>For Safari users: Consider disabling Advanced Tracking and Fingerprinting Protection, as it can override local DNS settings and interfere with AGH. More details on this issue can be found <a href="/notes/adguard-home-advanced-data-protection/" >here</a>.</p>
<p>Note: Client names may not resolve properly due to Docker&rsquo;s host network mode. If you find a solution to this issue, please share!
<img alt="Client resolution issue" loading="lazy" src="/notes/images/adguard-home-synology-tailscale/adguard-home-dashboard.png"></p>
<h2 id="resources">Resources</h2>
<ul>
<li><a href="https://nicolaslouge.com/post/install-adguard-home-raspberry-pi-enable-remote-acces-via-tailscale/" target="_blank" >Install Adguard Home on a Raspberry Pi 4 and enable remote access with Tailscale | Senior Project Manager in Toronto, Ontario | Nicolas Louge</a></li>
<li><a href="https://akashrajpurohit.com/blog/adguard-home-tailscale-erase-ads-on-the-go/?ref=reddit" target="_blank" >AdGuard Home + Tailscale = Erase Ads on the Go</a></li>
<li><a href="https://drfrankenstein.co.uk/adguard-home-in-container-manager-on-a-synology-nas/" target="_blank" >AdGuard Home in Container Manager on a Synology NAS</a></li>
</ul>
]]></content:encoded>
    </item>
    <item>
      <title>Secure Remote Access to Your Synology Plex Server via Tailscale</title>
      <link>https://kunat.dev/notes/synology-plex-tailscale/</link>
      <pubDate>Wed, 03 Jul 2024 14:40:04 +0200</pubDate>
      <guid>https://kunat.dev/notes/synology-plex-tailscale/</guid>
      <description>&lt;p&gt;In this article, I’ll describe how to set up your Plex server so you can access it remotely through Tailscale, with Remote Access completely disabled in Plex server settings.&lt;/p&gt;
&lt;h2 id=&#34;prerequisites&#34;&gt;Prerequisites&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Have a Plex server running as a Docker container using &lt;a href=&#34;https://trash-guides.info/Hardlinks/How-to-setup-for/Synology/&#34; target=&#34;_blank&#34; &gt;this guide&lt;/a&gt;. When you’re done, you should have a &lt;code&gt;docker-compose.yml&lt;/code&gt; and a &lt;code&gt;.env&lt;/code&gt; file with all your environment variables.&lt;/li&gt;
&lt;li&gt;Have Tailscale set up and running on your Synology. You can use &lt;a href=&#34;https://www.youtube.com/watch?v=qulWDpzdY1E&#34; target=&#34;_blank&#34; &gt;this guide&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote&gt;
&lt;p&gt;Make sure to disable the expiry for the IP address assigned to your Synology NAS in the Tailscale dashboard.&lt;/p&gt;</description>
      <content:encoded><![CDATA[<p>In this article, I’ll describe how to set up your Plex server so you can access it remotely through Tailscale, with Remote Access completely disabled in Plex server settings.</p>
<h2 id="prerequisites">Prerequisites</h2>
<ul>
<li>Have a Plex server running as a Docker container using <a href="https://trash-guides.info/Hardlinks/How-to-setup-for/Synology/" target="_blank" >this guide</a>. When you’re done, you should have a <code>docker-compose.yml</code> and a <code>.env</code> file with all your environment variables.</li>
<li>Have Tailscale set up and running on your Synology. You can use <a href="https://www.youtube.com/watch?v=qulWDpzdY1E" target="_blank" >this guide</a>.</li>
</ul>
<blockquote>
<p>Make sure to disable the expiry for the IP address assigned to your Synology NAS in the Tailscale dashboard.</p></blockquote>
<h2 id="steps">Steps</h2>
<ol>
<li>Set <code>PLEX_ADVERTISE_URL</code> (in the <code>.env</code> file) to your Synology IP address in the Tailscale dashboard and your local network IP address:</li>
</ol>
<pre tabindex="0"><code>## PLEX
# ... other keys
PLEX_ADVERTISE_URL=&#34;http://ds1512p:32400,http://192.168.0.186:32400&#34;
</code></pre><blockquote>
<p>Remember to include port numbers in both IP addresses!</p></blockquote>
<ol start="2">
<li>Restart the Plex container using the latest changes:</li>
</ol>
<pre tabindex="0"><code>sudo docker-compose up --force-recreate plex
</code></pre><ol start="3">
<li>Check if the changes have been applied successfully. “Custom server access URLs” should be set to <code>$PLEX_ADVERTISE_URL</code>.</li>
</ol>
<p><img alt="Plex Server dashboard" loading="lazy" src="/notes/images/synology-plex-tailscale.png"></p>
<h2 id="summary">Summary</h2>
<p>That’s it! With the above setup, you should be able to connect to your Plex server from your local network as well as from anywhere, as long as you’re connected to Tailscale.</p>
<h2 id="resources">Resources</h2>
<ul>
<li><a href="https://community.umbrel.com/t/how-to-run-plex-through-tailscale/14595" target="_blank" >How to run Plex through Tailscale</a></li>
</ul>
]]></content:encoded>
    </item>
  </channel>
</rss>
