<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>Kit Roed</title>
    <description></description>
    <link>https://kitroed.com/</link>
    <atom:link href="https://kitroed.com/feed.xml" rel="self" type="application/rss+xml"/>
    <pubDate>Fri, 08 May 2026 03:54:07 +0000</pubDate>
    <lastBuildDate>Fri, 08 May 2026 03:54:07 +0000</lastBuildDate>
    <generator>Jekyll v3.10.0</generator>
    
      <item>
        <title>Home Server Setup Notes</title>
        <description>&lt;ul id=&quot;markdown-toc&quot;&gt;
  &lt;li&gt;&lt;a href=&quot;#key-preparations&quot; id=&quot;markdown-toc-key-preparations&quot;&gt;Key preparations&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#disable-ip-forwarding&quot; id=&quot;markdown-toc-disable-ip-forwarding&quot;&gt;Disable IP forwarding&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#configure-interfaces-separately&quot; id=&quot;markdown-toc-configure-interfaces-separately&quot;&gt;Configure interfaces separately&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#firewall-with-iptables&quot; id=&quot;markdown-toc-firewall-with-iptables&quot;&gt;Firewall with iptables&lt;/a&gt;    &lt;ul&gt;
      &lt;li&gt;&lt;a href=&quot;#install-and-configure-iptables&quot; id=&quot;markdown-toc-install-and-configure-iptables&quot;&gt;Install and configure iptables&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#disable-nftables&quot; id=&quot;markdown-toc-disable-nftables&quot;&gt;Disable nftables&lt;/a&gt;&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#set-up-nginx-proxy-manager&quot; id=&quot;markdown-toc-set-up-nginx-proxy-manager&quot;&gt;Set up Nginx Proxy Manager:&lt;/a&gt;    &lt;ul&gt;
      &lt;li&gt;&lt;a href=&quot;#create-directories-for-npm&quot; id=&quot;markdown-toc-create-directories-for-npm&quot;&gt;Create directories for NPM&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#create-npm-docker-composeyml&quot; id=&quot;markdown-toc-create-npm-docker-composeyml&quot;&gt;Create NPM docker-compose.yml&lt;/a&gt;&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#default-landing-page&quot; id=&quot;markdown-toc-default-landing-page&quot;&gt;Default Landing Page&lt;/a&gt;    &lt;ul&gt;
      &lt;li&gt;&lt;a href=&quot;#create-landing-page-directory&quot; id=&quot;markdown-toc-create-landing-page-directory&quot;&gt;Create landing page directory&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#create-indexhtml&quot; id=&quot;markdown-toc-create-indexhtml&quot;&gt;Create index.html&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#create-robotstxt-deny-crawlers&quot; id=&quot;markdown-toc-create-robotstxt-deny-crawlers&quot;&gt;Create robots.txt (deny crawlers)&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#create-default-page-docker-composeyml&quot; id=&quot;markdown-toc-create-default-page-docker-composeyml&quot;&gt;Create default-page docker-compose.yml&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#start-the-service&quot; id=&quot;markdown-toc-start-the-service&quot;&gt;Start the service&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#configure-npm-proxy-hosts&quot; id=&quot;markdown-toc-configure-npm-proxy-hosts&quot;&gt;Configure NPM proxy hosts&lt;/a&gt;&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#dynamic-dns-with-namecheap&quot; id=&quot;markdown-toc-dynamic-dns-with-namecheap&quot;&gt;Dynamic DNS with Namecheap&lt;/a&gt;    &lt;ul&gt;
      &lt;li&gt;&lt;a href=&quot;#enable-dynamic-dns-in-namecheap&quot; id=&quot;markdown-toc-enable-dynamic-dns-in-namecheap&quot;&gt;Enable Dynamic DNS in Namecheap&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#configure-ddns-with-ddclient&quot; id=&quot;markdown-toc-configure-ddns-with-ddclient&quot;&gt;Configure DDNS with ddclient&lt;/a&gt;&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#wireguard-vpn-with-wg-easy&quot; id=&quot;markdown-toc-wireguard-vpn-with-wg-easy&quot;&gt;WireGuard VPN with wg-easy&lt;/a&gt;    &lt;ul&gt;
      &lt;li&gt;&lt;a href=&quot;#create-wireguard-directory&quot; id=&quot;markdown-toc-create-wireguard-directory&quot;&gt;Create WireGuard directory&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#create-wireguard-docker-composeyml&quot; id=&quot;markdown-toc-create-wireguard-docker-composeyml&quot;&gt;Create WireGuard docker-compose.yml&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#start-wireguard&quot; id=&quot;markdown-toc-start-wireguard&quot;&gt;Start WireGuard&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#access-web-ui&quot; id=&quot;markdown-toc-access-web-ui&quot;&gt;Access Web UI&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#add-and-download-client-configurations&quot; id=&quot;markdown-toc-add-and-download-client-configurations&quot;&gt;Add and download client configurations&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#connect-clients&quot; id=&quot;markdown-toc-connect-clients&quot;&gt;Connect clients&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#check-connected-peers&quot; id=&quot;markdown-toc-check-connected-peers&quot;&gt;Check connected peers&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#expose-wireguard-web-ui-via-npm-optional&quot; id=&quot;markdown-toc-expose-wireguard-web-ui-via-npm-optional&quot;&gt;Expose WireGuard Web UI via NPM (Optional)&lt;/a&gt;&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#external-usb-drive-as-samba-share-storage&quot; id=&quot;markdown-toc-external-usb-drive-as-samba-share-storage&quot;&gt;External USB Drive as Samba Share Storage&lt;/a&gt;    &lt;ul&gt;
      &lt;li&gt;&lt;a href=&quot;#identify-and-format-the-drive&quot; id=&quot;markdown-toc-identify-and-format-the-drive&quot;&gt;Identify and format the drive&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#mount-the-drive&quot; id=&quot;markdown-toc-mount-the-drive&quot;&gt;Mount the drive&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#install-and-configure-samba&quot; id=&quot;markdown-toc-install-and-configure-samba&quot;&gt;Install and configure Samba&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#create-samba-user&quot; id=&quot;markdown-toc-create-samba-user&quot;&gt;Create Samba user&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#configure-firewall&quot; id=&quot;markdown-toc-configure-firewall&quot;&gt;Configure firewall&lt;/a&gt;&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#plex-media-server&quot; id=&quot;markdown-toc-plex-media-server&quot;&gt;Plex Media Server&lt;/a&gt;    &lt;ul&gt;
      &lt;li&gt;&lt;a href=&quot;#create-plex-directory-structure&quot; id=&quot;markdown-toc-create-plex-directory-structure&quot;&gt;Create Plex directory structure&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#create-docker-composeyml-for-plex&quot; id=&quot;markdown-toc-create-docker-composeyml-for-plex&quot;&gt;Create docker-compose.yml for Plex&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#start-plex&quot; id=&quot;markdown-toc-start-plex&quot;&gt;Start Plex&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#allow-plex-through-firewall&quot; id=&quot;markdown-toc-allow-plex-through-firewall&quot;&gt;Allow Plex through firewall&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#access-plex&quot; id=&quot;markdown-toc-access-plex&quot;&gt;Access Plex&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#enable-remote-access&quot; id=&quot;markdown-toc-enable-remote-access&quot;&gt;Enable Remote Access&lt;/a&gt;        &lt;ul&gt;
          &lt;li&gt;&lt;a href=&quot;#method-1-direct-connection-recommended-for-streaming&quot; id=&quot;markdown-toc-method-1-direct-connection-recommended-for-streaming&quot;&gt;Method 1: Direct Connection (Recommended for streaming)&lt;/a&gt;&lt;/li&gt;
          &lt;li&gt;&lt;a href=&quot;#method-2-reverse-proxy-via-npm&quot; id=&quot;markdown-toc-method-2-reverse-proxy-via-npm&quot;&gt;Method 2: Reverse Proxy via NPM&lt;/a&gt;&lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#ntfy---push-notification-service&quot; id=&quot;markdown-toc-ntfy---push-notification-service&quot;&gt;ntfy - Push Notification Service&lt;/a&gt;    &lt;ul&gt;
      &lt;li&gt;&lt;a href=&quot;#create-ntfy-directory&quot; id=&quot;markdown-toc-create-ntfy-directory&quot;&gt;Create ntfy directory&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#create-ntfy-docker-composeyml&quot; id=&quot;markdown-toc-create-ntfy-docker-composeyml&quot;&gt;Create ntfy docker-compose.yml&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#start-ntfy&quot; id=&quot;markdown-toc-start-ntfy&quot;&gt;Start ntfy&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#access-ntfy&quot; id=&quot;markdown-toc-access-ntfy&quot;&gt;Access ntfy&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#send-a-test-notification&quot; id=&quot;markdown-toc-send-a-test-notification&quot;&gt;Send a test notification&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#mobile-apps&quot; id=&quot;markdown-toc-mobile-apps&quot;&gt;Mobile apps&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#expose-ntfy-via-npm&quot; id=&quot;markdown-toc-expose-ntfy-via-npm&quot;&gt;Expose ntfy via NPM&lt;/a&gt;&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#nextcloud-with-dedicated-drive&quot; id=&quot;markdown-toc-nextcloud-with-dedicated-drive&quot;&gt;Nextcloud with Dedicated Drive&lt;/a&gt;    &lt;ul&gt;
      &lt;li&gt;&lt;a href=&quot;#format-and-mount-the-drive&quot; id=&quot;markdown-toc-format-and-mount-the-drive&quot;&gt;Format and mount the drive&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#give-your-user-read-access&quot; id=&quot;markdown-toc-give-your-user-read-access&quot;&gt;Give your user read access&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#create-nextcloud-directory&quot; id=&quot;markdown-toc-create-nextcloud-directory&quot;&gt;Create Nextcloud directory&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#create-nextcloud-docker-composeyml&quot; id=&quot;markdown-toc-create-nextcloud-docker-composeyml&quot;&gt;Create Nextcloud docker-compose.yml&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#start-nextcloud&quot; id=&quot;markdown-toc-start-nextcloud&quot;&gt;Start Nextcloud&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#access-nextcloud&quot; id=&quot;markdown-toc-access-nextcloud&quot;&gt;Access Nextcloud&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#expose-nextcloud-via-npm&quot; id=&quot;markdown-toc-expose-nextcloud-via-npm&quot;&gt;Expose Nextcloud via NPM&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#configure-trusted-domains&quot; id=&quot;markdown-toc-configure-trusted-domains&quot;&gt;Configure trusted domains&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#add-samba-share-for-direct-file-access&quot; id=&quot;markdown-toc-add-samba-share-for-direct-file-access&quot;&gt;Add Samba share for direct file access&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#access-the-share&quot; id=&quot;markdown-toc-access-the-share&quot;&gt;Access the share&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#sync-changes-to-nextcloud&quot; id=&quot;markdown-toc-sync-changes-to-nextcloud&quot;&gt;Sync changes to Nextcloud&lt;/a&gt;&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#wallabag---read-it-later-service&quot; id=&quot;markdown-toc-wallabag---read-it-later-service&quot;&gt;Wallabag - Read It Later Service&lt;/a&gt;    &lt;ul&gt;
      &lt;li&gt;&lt;a href=&quot;#create-wallabag-directory&quot; id=&quot;markdown-toc-create-wallabag-directory&quot;&gt;Create Wallabag directory&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#create-wallabag-docker-composeyml&quot; id=&quot;markdown-toc-create-wallabag-docker-composeyml&quot;&gt;Create Wallabag docker-compose.yml&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#start-wallabag&quot; id=&quot;markdown-toc-start-wallabag&quot;&gt;Start Wallabag&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#allow-wallabag-through-firewall&quot; id=&quot;markdown-toc-allow-wallabag-through-firewall&quot;&gt;Allow Wallabag through firewall&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#expose-wallabag-via-npm&quot; id=&quot;markdown-toc-expose-wallabag-via-npm&quot;&gt;Expose Wallabag via NPM&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#access-wallabag&quot; id=&quot;markdown-toc-access-wallabag&quot;&gt;Access Wallabag&lt;/a&gt;&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#rustdesk---self-hosted-remote-desktop&quot; id=&quot;markdown-toc-rustdesk---self-hosted-remote-desktop&quot;&gt;RustDesk - Self-Hosted Remote Desktop&lt;/a&gt;    &lt;ul&gt;
      &lt;li&gt;&lt;a href=&quot;#create-rustdesk-directory&quot; id=&quot;markdown-toc-create-rustdesk-directory&quot;&gt;Create RustDesk directory&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#create-rustdesk-docker-composeyml&quot; id=&quot;markdown-toc-create-rustdesk-docker-composeyml&quot;&gt;Create RustDesk docker-compose.yml&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#start-rustdesk&quot; id=&quot;markdown-toc-start-rustdesk&quot;&gt;Start RustDesk&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#get-the-public-key&quot; id=&quot;markdown-toc-get-the-public-key&quot;&gt;Get the public key&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#configure-rustdesk-clients&quot; id=&quot;markdown-toc-configure-rustdesk-clients&quot;&gt;Configure RustDesk clients&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#usage&quot; id=&quot;markdown-toc-usage&quot;&gt;Usage&lt;/a&gt;&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#immich---self-hosted-photo--video-backup&quot; id=&quot;markdown-toc-immich---self-hosted-photo--video-backup&quot;&gt;Immich - Self-Hosted Photo &amp;amp; Video Backup&lt;/a&gt;    &lt;ul&gt;
      &lt;li&gt;&lt;a href=&quot;#create-immich-directory&quot; id=&quot;markdown-toc-create-immich-directory&quot;&gt;Create Immich directory&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#download-configuration-files&quot; id=&quot;markdown-toc-download-configuration-files&quot;&gt;Download configuration files&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#configure-environment&quot; id=&quot;markdown-toc-configure-environment&quot;&gt;Configure environment&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#start-immich&quot; id=&quot;markdown-toc-start-immich&quot;&gt;Start Immich&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#expose-immich-via-npm&quot; id=&quot;markdown-toc-expose-immich-via-npm&quot;&gt;Expose Immich via NPM&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#access-immich&quot; id=&quot;markdown-toc-access-immich&quot;&gt;Access Immich&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#mobile-apps-1&quot; id=&quot;markdown-toc-mobile-apps-1&quot;&gt;Mobile Apps&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#troubleshooting-system-freeze-optional-i-didnt-do-this&quot; id=&quot;markdown-toc-troubleshooting-system-freeze-optional-i-didnt-do-this&quot;&gt;Troubleshooting: System Freeze (optional, I didn’t do this)&lt;/a&gt;&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#calibre-web---ebook-library-access&quot; id=&quot;markdown-toc-calibre-web---ebook-library-access&quot;&gt;Calibre-Web - Ebook Library Access&lt;/a&gt;    &lt;ul&gt;
      &lt;li&gt;&lt;a href=&quot;#create-library-directory&quot; id=&quot;markdown-toc-create-library-directory&quot;&gt;Create library directory&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#deploy-calibre-web&quot; id=&quot;markdown-toc-deploy-calibre-web&quot;&gt;Deploy Calibre-Web&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#access-calibre-web&quot; id=&quot;markdown-toc-access-calibre-web&quot;&gt;Access Calibre-Web&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#sync-from-desktop-calibre&quot; id=&quot;markdown-toc-sync-from-desktop-calibre&quot;&gt;Sync from desktop Calibre&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#optional-sync-script&quot; id=&quot;markdown-toc-optional-sync-script&quot;&gt;Optional sync script&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#lan-firewall-rule&quot; id=&quot;markdown-toc-lan-firewall-rule&quot;&gt;LAN firewall rule&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#optional-reverse-proxy-via-npm&quot; id=&quot;markdown-toc-optional-reverse-proxy-via-npm&quot;&gt;Optional reverse proxy via NPM&lt;/a&gt;&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#copyparty---easy-file-browsing--sharing&quot; id=&quot;markdown-toc-copyparty---easy-file-browsing--sharing&quot;&gt;Copyparty - Easy File Browsing &amp;amp; Sharing&lt;/a&gt;    &lt;ul&gt;
      &lt;li&gt;&lt;a href=&quot;#create-copyparty-directory&quot; id=&quot;markdown-toc-create-copyparty-directory&quot;&gt;Create Copyparty directory&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#create-the-sandbox-share-directory&quot; id=&quot;markdown-toc-create-the-sandbox-share-directory&quot;&gt;Create the sandbox share directory&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#create-copyparty-docker-composeyml&quot; id=&quot;markdown-toc-create-copyparty-docker-composeyml&quot;&gt;Create Copyparty docker-compose.yml&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#create-configuration-file&quot; id=&quot;markdown-toc-create-configuration-file&quot;&gt;Create configuration file&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#start-copyparty&quot; id=&quot;markdown-toc-start-copyparty&quot;&gt;Start Copyparty&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#access-copyparty&quot; id=&quot;markdown-toc-access-copyparty&quot;&gt;Access Copyparty&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#lan-firewall-rule-1&quot; id=&quot;markdown-toc-lan-firewall-rule-1&quot;&gt;LAN firewall rule&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#optional-expose-via-npm&quot; id=&quot;markdown-toc-optional-expose-via-npm&quot;&gt;Optional: Expose via NPM&lt;/a&gt;&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#openspeedtest---network-speed-testing&quot; id=&quot;markdown-toc-openspeedtest---network-speed-testing&quot;&gt;OpenSpeedTest - Network Speed Testing&lt;/a&gt;    &lt;ul&gt;
      &lt;li&gt;&lt;a href=&quot;#create-openspeedtest-directory&quot; id=&quot;markdown-toc-create-openspeedtest-directory&quot;&gt;Create OpenSpeedTest directory&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#create-openspeedtest-docker-composeyml&quot; id=&quot;markdown-toc-create-openspeedtest-docker-composeyml&quot;&gt;Create OpenSpeedTest docker-compose.yml&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#start-openspeedtest&quot; id=&quot;markdown-toc-start-openspeedtest&quot;&gt;Start OpenSpeedTest&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#access-openspeedtest&quot; id=&quot;markdown-toc-access-openspeedtest&quot;&gt;Access OpenSpeedTest&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#lan-firewall-rule-2&quot; id=&quot;markdown-toc-lan-firewall-rule-2&quot;&gt;LAN firewall rule&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#optional-expose-via-npm-1&quot; id=&quot;markdown-toc-optional-expose-via-npm-1&quot;&gt;Optional: Expose via NPM&lt;/a&gt;&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#netdata---real-time-performance-monitoring&quot; id=&quot;markdown-toc-netdata---real-time-performance-monitoring&quot;&gt;Netdata - Real-time Performance Monitoring&lt;/a&gt;    &lt;ul&gt;
      &lt;li&gt;&lt;a href=&quot;#create-netdata-directory&quot; id=&quot;markdown-toc-create-netdata-directory&quot;&gt;Create Netdata directory&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#create-netdata-docker-composeyml&quot; id=&quot;markdown-toc-create-netdata-docker-composeyml&quot;&gt;Create Netdata docker-compose.yml&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#start-netdata&quot; id=&quot;markdown-toc-start-netdata&quot;&gt;Start Netdata&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#lan-firewall-rule-3&quot; id=&quot;markdown-toc-lan-firewall-rule-3&quot;&gt;LAN firewall rule&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#access-netdata&quot; id=&quot;markdown-toc-access-netdata&quot;&gt;Access Netdata&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#optional-expose-via-npm-securely&quot; id=&quot;markdown-toc-optional-expose-via-npm-securely&quot;&gt;Optional: Expose via NPM (Securely)&lt;/a&gt;&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#watchtower---container-update-monitoring&quot; id=&quot;markdown-toc-watchtower---container-update-monitoring&quot;&gt;Watchtower - Container Update Monitoring&lt;/a&gt;    &lt;ul&gt;
      &lt;li&gt;&lt;a href=&quot;#create-watchtower-directory&quot; id=&quot;markdown-toc-create-watchtower-directory&quot;&gt;Create Watchtower directory&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#create-watchtower-docker-composeyml&quot; id=&quot;markdown-toc-create-watchtower-docker-composeyml&quot;&gt;Create Watchtower docker-compose.yml&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#start-watchtower&quot; id=&quot;markdown-toc-start-watchtower&quot;&gt;Start Watchtower&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#triggering-a-manual-check&quot; id=&quot;markdown-toc-triggering-a-manual-check&quot;&gt;Triggering a Manual Check&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#subscribe-to-notifications&quot; id=&quot;markdown-toc-subscribe-to-notifications&quot;&gt;Subscribe to notifications&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#optional-enable-auto-update-for-specific-containers&quot; id=&quot;markdown-toc-optional-enable-auto-update-for-specific-containers&quot;&gt;Optional: Enable auto-update for specific containers&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#manual-update-workflow&quot; id=&quot;markdown-toc-manual-update-workflow&quot;&gt;Manual update workflow&lt;/a&gt;&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#final-firewall-configuration&quot; id=&quot;markdown-toc-final-firewall-configuration&quot;&gt;Final Firewall Configuration&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#moving-docker-data-to-srv&quot; id=&quot;markdown-toc-moving-docker-data-to-srv&quot;&gt;Moving Docker Data to /srv&lt;/a&gt;    &lt;ul&gt;
      &lt;li&gt;&lt;a href=&quot;#1-stop-docker&quot; id=&quot;markdown-toc-1-stop-docker&quot;&gt;1. Stop Docker&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#2-create-new-directory&quot; id=&quot;markdown-toc-2-create-new-directory&quot;&gt;2. Create new directory&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#3-configure-docker-to-use-new-path&quot; id=&quot;markdown-toc-3-configure-docker-to-use-new-path&quot;&gt;3. Configure Docker to use new path&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#4-move-existing-data&quot; id=&quot;markdown-toc-4-move-existing-data&quot;&gt;4. Move existing data&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#5-start-docker&quot; id=&quot;markdown-toc-5-start-docker&quot;&gt;5. Start Docker&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#6-verify-and-clean-up&quot; id=&quot;markdown-toc-6-verify-and-clean-up&quot;&gt;6. Verify and clean up&lt;/a&gt;&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#verifying-system-health&quot; id=&quot;markdown-toc-verifying-system-health&quot;&gt;Verifying System Health&lt;/a&gt;    &lt;ul&gt;
      &lt;li&gt;&lt;a href=&quot;#check-docker-containers&quot; id=&quot;markdown-toc-check-docker-containers&quot;&gt;Check Docker Containers&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#monitor-resource-usage&quot; id=&quot;markdown-toc-monitor-resource-usage&quot;&gt;Monitor Resource Usage&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#check-system-logs&quot; id=&quot;markdown-toc-check-system-logs&quot;&gt;Check System Logs&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#verify-network--firewall&quot; id=&quot;markdown-toc-verify-network--firewall&quot;&gt;Verify Network &amp;amp; Firewall&lt;/a&gt;&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;key-preparations&quot;&gt;Key preparations&lt;/h2&gt;

&lt;ul&gt;
  &lt;li&gt;internal network is &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;enp2s0&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;external network is &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;eno1&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I want to have the external network set up for internet access only, and the internal network for LAN access only. The server should not route traffic between the two networks. Effectively, the server acts as a client on both networks, but does not forward traffic between them, a reverse proxy appliance, and VPN endpoint.&lt;/p&gt;

&lt;h2 id=&quot;disable-ip-forwarding&quot;&gt;Disable IP forwarding&lt;/h2&gt;

&lt;p&gt;check that IP forwarding isn’t enabled:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;sysctl net.ipv4.ip_forward
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;it returned&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;net.ipv4.ip_forward = 1&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;created a new file&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;nano /etc/sysctl.d/99-network-hardening.conf
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;and added&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-code&quot;&gt;# Disable IPv4 packet forwarding (no gateway duties)
net.ipv4.ip_forward = 0

# Disable IPv6 forwarding unless explicitly needed
net.ipv6.conf.all.forwarding = 0

# Ignore ICMP broadcast requests (mitigate smurf attacks)
net.ipv4.icmp_echo_ignore_broadcasts = 1

# Ignore bogus ICMP error responses
net.ipv4.icmp_ignore_bogus_error_responses = 1

# Do not accept source-routed packets
net.ipv4.conf.all.accept_source_route = 0
net.ipv4.conf.default.accept_source_route = 0

# Do not accept ICMP redirects (prevent malicious route injection)
net.ipv4.conf.all.accept_redirects = 0
net.ipv4.conf.default.accept_redirects = 0
net.ipv6.conf.all.accept_redirects = 0
net.ipv6.conf.default.accept_redirects = 0

# Do not send ICMP redirects (stay quiet as a router)
net.ipv4.conf.all.send_redirects = 0
net.ipv4.conf.default.send_redirects = 0

# Enable SYN cookies (protect against SYN flood DoS)
net.ipv4.tcp_syncookies = 1

# Log suspicious packets
net.ipv4.conf.all.log_martians = 1
net.ipv4.conf.default.log_martians = 1

# Reverse path filtering (helps prevent IP spoofing)
net.ipv4.conf.all.rp_filter = 1
net.ipv4.conf.default.rp_filter = 1
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;reload&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;sysctl &lt;span class=&quot;nt&quot;&gt;--system&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;configure-interfaces-separately&quot;&gt;Configure interfaces separately&lt;/h2&gt;

&lt;p&gt;using systemd networkd&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;vim /etc/systemd/network/20-enp2s0-lan.network
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;div class=&quot;language-ini highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nn&quot;&gt;[Match]&lt;/span&gt;
&lt;span class=&quot;py&quot;&gt;Name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;enp2s0&lt;/span&gt;

&lt;span class=&quot;nn&quot;&gt;[Network]&lt;/span&gt;
&lt;span class=&quot;py&quot;&gt;DHCP&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;yes&lt;/span&gt;

&lt;span class=&quot;nn&quot;&gt;[DHCPv4]&lt;/span&gt;
&lt;span class=&quot;py&quot;&gt;RouteMetric&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;2000&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;vim /etc/systemd/network/10-eno1-external.network
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;div class=&quot;language-ini highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nn&quot;&gt;[Match]&lt;/span&gt;
&lt;span class=&quot;py&quot;&gt;Name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;eno1&lt;/span&gt;

&lt;span class=&quot;nn&quot;&gt;[Network]&lt;/span&gt;
&lt;span class=&quot;py&quot;&gt;DHCP&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;yes&lt;/span&gt;
&lt;span class=&quot;py&quot;&gt;DNS&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;1.1.1.1 8.8.8.8   # optional: override ISP DNS with public resolvers&lt;/span&gt;

&lt;span class=&quot;nn&quot;&gt;[DHCPv4]&lt;/span&gt;
&lt;span class=&quot;py&quot;&gt;RouteMetric&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;10       # Low metric = high priority - ensures eno1&apos;s default route wins&lt;/span&gt;
&lt;span class=&quot;py&quot;&gt;UseRoutes&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;yes&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;enable and start:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;systemctl &lt;span class=&quot;nb&quot;&gt;enable&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;--now&lt;/span&gt; systemd-networkd
&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;systemctl restart systemd-networkd
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;NOTE&lt;/strong&gt;: If &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;systemctl restart systemd-networkd&lt;/code&gt; hangs and doesn’t return, you may need to reboot the server. This can happen when changing DHCP settings. To avoid SSH lockout in the future:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;# Check config syntax before applying&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;networkctl reload
&lt;span class=&quot;c&quot;&gt;# Or test with a timeout that auto-reverts&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;systemctl restart systemd-networkd &amp;amp; &lt;span class=&quot;nb&quot;&gt;sleep &lt;/span&gt;10 &lt;span class=&quot;o&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; ip route show
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;After reboot, verify the routes:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;ip route show
&lt;span class=&quot;c&quot;&gt;# Should only see default via public IP address (eno1), NOT via 192.168.0.1&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;works!&lt;/p&gt;

&lt;h2 id=&quot;firewall-with-iptables&quot;&gt;Firewall with iptables&lt;/h2&gt;

&lt;p&gt;Since Docker doesn’t work properly with nftables, use iptables-legacy instead.&lt;/p&gt;

&lt;h3 id=&quot;install-and-configure-iptables&quot;&gt;Install and configure iptables&lt;/h3&gt;

&lt;p&gt;Install iptables-legacy:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;apt update
&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;apt &lt;span class=&quot;nb&quot;&gt;install &lt;/span&gt;iptables iptables-persistent
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Switch to iptables-legacy:&lt;/p&gt;

&lt;p&gt;Debian provides two “flavors” of iptables binaries: iptables-nft and iptables-legacy. You can select which one is active:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;update-alternatives &lt;span class=&quot;nt&quot;&gt;--set&lt;/span&gt; iptables /usr/sbin/iptables-legacy
&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;update-alternatives &lt;span class=&quot;nt&quot;&gt;--set&lt;/span&gt; ip6tables /usr/sbin/ip6tables-legacy
&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;update-alternatives &lt;span class=&quot;nt&quot;&gt;--set&lt;/span&gt; arptables /usr/sbin/arptables-legacy
&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;update-alternatives &lt;span class=&quot;nt&quot;&gt;--set&lt;/span&gt; ebtables /usr/sbin/ebtables-legacy
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;disable-nftables&quot;&gt;Disable nftables&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;IMPORTANT&lt;/strong&gt;: If nftables is installed, it must be completely disabled:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;# Stop and disable nftables service&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;systemctl stop nftables
&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;systemctl disable nftables

&lt;span class=&quot;c&quot;&gt;# Clear any active nftables rules&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;nft flush ruleset
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;You can optionally delete &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/etc/nftables.conf&lt;/code&gt; or rename it to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.bak&lt;/code&gt; for reference. Since the service is disabled, the file won’t be loaded on boot anyway.&lt;/p&gt;

&lt;p&gt;This makes it so that:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Docker manages firewall rules via iptables-legacy&lt;/li&gt;
  &lt;li&gt;eno1: Docker/NPM handles 80/443 from internet&lt;/li&gt;
  &lt;li&gt;enp2s0: LAN access to NPM admin UI (port 81) works&lt;/li&gt;
  &lt;li&gt;No forwarding: box won’t act as a router&lt;/li&gt;
  &lt;li&gt;Minimal attack surface&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;set-up-nginx-proxy-manager&quot;&gt;Set up Nginx Proxy Manager:&lt;/h2&gt;

&lt;p&gt;(install Docker and Docker Compose)&lt;/p&gt;

&lt;h3 id=&quot;create-directories-for-npm&quot;&gt;Create directories for NPM&lt;/h3&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nb&quot;&gt;sudo mkdir&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-p&lt;/span&gt; /opt/npm/data /opt/npm/letsencrypt
&lt;span class=&quot;nb&quot;&gt;sudo chown&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-R&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$USER&lt;/span&gt;:&lt;span class=&quot;nv&quot;&gt;$USER&lt;/span&gt; /opt/npm
&lt;span class=&quot;nb&quot;&gt;cd&lt;/span&gt; /opt/npm
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;create-npm-docker-composeyml&quot;&gt;Create NPM docker-compose.yml&lt;/h3&gt;

&lt;div class=&quot;language-yaml highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;na&quot;&gt;services&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;app&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;image&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;jc21/nginx-proxy-manager:latest&apos;&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;restart&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;unless-stopped&lt;/span&gt;

    &lt;span class=&quot;na&quot;&gt;ports&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
      &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;80:80&apos;&lt;/span&gt;              &lt;span class=&quot;c1&quot;&gt;# Public HTTP Port&lt;/span&gt;
      &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;443:443&apos;&lt;/span&gt;            &lt;span class=&quot;c1&quot;&gt;# Public HTTPS Port&lt;/span&gt;
      &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;192.168.0.101:81:81&apos;&lt;/span&gt;  &lt;span class=&quot;c1&quot;&gt;# Admin Web Port (LAN only)&lt;/span&gt;

    &lt;span class=&quot;c1&quot;&gt;# Use host&apos;s DNS for proper LAN service resolution&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;dns&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
      &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;192.168.0.2&lt;/span&gt;          &lt;span class=&quot;c1&quot;&gt;# LAN DNS&lt;/span&gt;
      &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;1.1.1.1&lt;/span&gt;              &lt;span class=&quot;c1&quot;&gt;# Cloudflare fallback&lt;/span&gt;

    &lt;span class=&quot;na&quot;&gt;environment&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
      &lt;span class=&quot;na&quot;&gt;DISABLE_IPV6&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;true&apos;&lt;/span&gt;
      &lt;span class=&quot;na&quot;&gt;TZ&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;America/Chicago&apos;&lt;/span&gt;

    &lt;span class=&quot;na&quot;&gt;volumes&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
      &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;./data:/data&lt;/span&gt;
      &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;./letsencrypt:/etc/letsencrypt&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;dns&lt;/code&gt; configuration is critical - it allows NPM to resolve and reach internal LAN services properly while still accessing the internet.&lt;/p&gt;

&lt;h2 id=&quot;default-landing-page&quot;&gt;Default Landing Page&lt;/h2&gt;

&lt;p&gt;Set up a simple default page for &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;yourdomain.com&lt;/code&gt; and catch-all subdomains.&lt;/p&gt;

&lt;h3 id=&quot;create-landing-page-directory&quot;&gt;Create landing page directory&lt;/h3&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nb&quot;&gt;sudo mkdir&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-p&lt;/span&gt; /opt/default-page
&lt;span class=&quot;nb&quot;&gt;sudo chown&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-R&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$USER&lt;/span&gt;:&lt;span class=&quot;nv&quot;&gt;$USER&lt;/span&gt; /opt/default-page
&lt;span class=&quot;nb&quot;&gt;cd&lt;/span&gt; /opt/default-page
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;create-indexhtml&quot;&gt;Create index.html&lt;/h3&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;vim index.html
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;div class=&quot;language-html highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;cp&quot;&gt;&amp;lt;!DOCTYPE html&amp;gt;&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;html&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;lang=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;en&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;head&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;meta&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;charset=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;UTF-8&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;meta&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;name=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;viewport&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;content=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;width=device-width, initial-scale=1.0&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;title&amp;gt;&lt;/span&gt;yourdomain.com&lt;span class=&quot;nt&quot;&gt;&amp;lt;/title&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;style&amp;gt;&lt;/span&gt;
        &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;nl&quot;&gt;margin&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
            &lt;span class=&quot;nl&quot;&gt;padding&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
            &lt;span class=&quot;nl&quot;&gt;box-sizing&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;border-box&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
        &lt;span class=&quot;nt&quot;&gt;body&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;nl&quot;&gt;font-family&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;-apple-system&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;BlinkMacSystemFont&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&quot;Segoe UI&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Roboto&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&quot;Helvetica Neue&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Arial&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;sans-serif&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
            &lt;span class=&quot;nl&quot;&gt;background&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;linear-gradient&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;m&quot;&gt;135deg&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;#667eea&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;0%&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;#764ba2&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;100%&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
            &lt;span class=&quot;nl&quot;&gt;color&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;white&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
            &lt;span class=&quot;nl&quot;&gt;display&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;flex&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
            &lt;span class=&quot;nl&quot;&gt;justify-content&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;center&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
            &lt;span class=&quot;nl&quot;&gt;align-items&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;center&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
            &lt;span class=&quot;nl&quot;&gt;min-height&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;100vh&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
            &lt;span class=&quot;nl&quot;&gt;padding&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;20px&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
        &lt;span class=&quot;nc&quot;&gt;.container&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;nl&quot;&gt;text-align&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;center&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
            &lt;span class=&quot;nl&quot;&gt;max-width&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;600px&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
        &lt;span class=&quot;nt&quot;&gt;h1&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;nl&quot;&gt;font-size&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;4rem&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
            &lt;span class=&quot;nl&quot;&gt;margin-bottom&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;1rem&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
            &lt;span class=&quot;nl&quot;&gt;text-shadow&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;2px&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;2px&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;4px&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;rgba&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;m&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;m&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;m&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;m&quot;&gt;0.3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
        &lt;span class=&quot;nt&quot;&gt;p&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;nl&quot;&gt;font-size&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;1.5rem&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
            &lt;span class=&quot;nl&quot;&gt;opacity&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;0.9&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
            &lt;span class=&quot;nl&quot;&gt;line-height&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;1.6&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
        &lt;span class=&quot;nc&quot;&gt;.subdomain&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;nl&quot;&gt;margin-top&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;2rem&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
            &lt;span class=&quot;nl&quot;&gt;padding&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;1rem&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
            &lt;span class=&quot;nl&quot;&gt;background&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;rgba&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;m&quot;&gt;255&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;m&quot;&gt;255&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;m&quot;&gt;255&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;m&quot;&gt;0.1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
            &lt;span class=&quot;nl&quot;&gt;border-radius&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;8px&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
            &lt;span class=&quot;nl&quot;&gt;font-size&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;1rem&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
            &lt;span class=&quot;nl&quot;&gt;opacity&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;0.7&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;/style&amp;gt;&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;/head&amp;gt;&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;body&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;div&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;container&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
        &lt;span class=&quot;nt&quot;&gt;&amp;lt;h1&amp;gt;&lt;/span&gt;👋&lt;span class=&quot;nt&quot;&gt;&amp;lt;/h1&amp;gt;&lt;/span&gt;
        &lt;span class=&quot;nt&quot;&gt;&amp;lt;p&amp;gt;&lt;/span&gt;Nothing to see here.&lt;span class=&quot;nt&quot;&gt;&amp;lt;/p&amp;gt;&lt;/span&gt;
        &lt;span class=&quot;nt&quot;&gt;&amp;lt;div&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;subdomain&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;yourdomain.com&lt;span class=&quot;nt&quot;&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;/body&amp;gt;&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;/html&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;create-robotstxt-deny-crawlers&quot;&gt;Create robots.txt (deny crawlers)&lt;/h3&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;vim robots.txt
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;div class=&quot;language-text highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;User-agent: *
Disallow: /
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;create-default-page-docker-composeyml&quot;&gt;Create default-page docker-compose.yml&lt;/h3&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;vim docker-compose.yml
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;div class=&quot;language-yaml highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;na&quot;&gt;services&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;default-page&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;image&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;nginx:alpine&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;container_name&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;default-page&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;volumes&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
      &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;./index.html:/usr/share/nginx/html/index.html:ro&lt;/span&gt;
      &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;./robots.txt:/usr/share/nginx/html/robots.txt:ro&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;ports&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
      &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;192.168.0.101:8090:80&quot;&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;restart&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;unless-stopped&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;start-the-service&quot;&gt;Start the service&lt;/h3&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;docker compose up &lt;span class=&quot;nt&quot;&gt;-d&lt;/span&gt;

&lt;span class=&quot;c&quot;&gt;# Check logs&lt;/span&gt;
docker logs &lt;span class=&quot;nt&quot;&gt;-f&lt;/span&gt; default-page
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;configure-npm-proxy-hosts&quot;&gt;Configure NPM proxy hosts&lt;/h3&gt;

&lt;ol&gt;
  &lt;li&gt;Open NPM at &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;http://192.168.0.101:81&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;Add two proxy hosts:&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;For root domain:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;Domain Names: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;yourdomain.com&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;Scheme: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;http&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;Forward Hostname/IP: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;192.168.0.101&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;Forward Port: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;8090&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;SSL: Request new certificate, Force SSL&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;For catch-all subdomains:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;Domain Names: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;*.yourdomain.com&lt;/code&gt; (type the literal &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;*.&lt;/code&gt; prefix, then press Enter to commit the entry)&lt;/li&gt;
  &lt;li&gt;Scheme: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;http&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;Forward Hostname/IP: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;192.168.0.101&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;Forward Port: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;8090&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;SSL: &lt;strong&gt;None&lt;/strong&gt; (see “Wildcard SSL” note below)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Now any undefined subdomain will show the default page over HTTP. Confirm with:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;http://anything.yourdomain.com   # → default page
https://anything.yourdomain.com  # → cert error (expected, see below)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;This is fine for a generic “nothing here” landing page that exposes no data. Your defined subdomains (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;plex.yourdomain.com&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;nextcloud.yourdomain.com&lt;/code&gt;, etc.) still get individual Let’s Encrypt certs via the standard HTTP-01 challenge — only the wildcard catch-all needs special handling.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Optional: Wildcard SSL via DNS-01&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;A wildcard Let’s Encrypt certificate (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;*.yourdomain.com&lt;/code&gt;) can only be issued via the DNS-01 challenge — NPM’s default HTTP-01 challenge will fail because it can’t prove ownership of a name that doesn’t resolve to anything specific. On the catch-all proxy host’s SSL tab, switch to “Use a DNS Challenge” and select &lt;strong&gt;Namecheap&lt;/strong&gt; from the provider list, then:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;In Namecheap, go to Profile → Tools → Namecheap API Access and enable API access. Eligibility requires 20+ domains on the account, $50 spent in the past two years, or $50 in account balance.&lt;/li&gt;
  &lt;li&gt;Whitelist your server’s public IP in Namecheap’s API settings (the form is on the same page).&lt;/li&gt;
  &lt;li&gt;Back in NPM, paste your Namecheap API username (same as your account username) and API key into the credentials form.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Once provisioned, NPM renews the wildcard via DNS-01 automatically. To verify the cert is actually a wildcard:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nb&quot;&gt;echo&lt;/span&gt; | openssl s_client &lt;span class=&quot;nt&quot;&gt;-connect&lt;/span&gt; anything.yourdomain.com:443 &lt;span class=&quot;nt&quot;&gt;-servername&lt;/span&gt; anything.yourdomain.com 2&amp;gt;/dev/null &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
  | openssl x509 &lt;span class=&quot;nt&quot;&gt;-noout&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-text&lt;/span&gt; &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
  | &lt;span class=&quot;nb&quot;&gt;grep&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-A1&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;Subject Alternative Name&quot;&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# Look for: DNS:*.yourdomain.com&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;dynamic-dns-with-namecheap&quot;&gt;Dynamic DNS with Namecheap&lt;/h2&gt;

&lt;p&gt;To keep your domain pointing to your external IP address, set up dynamic DNS updates.&lt;/p&gt;

&lt;h3 id=&quot;enable-dynamic-dns-in-namecheap&quot;&gt;Enable Dynamic DNS in Namecheap&lt;/h3&gt;

&lt;ol&gt;
  &lt;li&gt;Log in to Namecheap&lt;/li&gt;
  &lt;li&gt;Go to Domain List → Manage → Advanced DNS&lt;/li&gt;
  &lt;li&gt;Enable “Dynamic DNS” toggle&lt;/li&gt;
  &lt;li&gt;Note the Dynamic DNS Password (you’ll need this)&lt;/li&gt;
&lt;/ol&gt;

&lt;h3 id=&quot;configure-ddns-with-ddclient&quot;&gt;Configure DDNS with ddclient&lt;/h3&gt;

&lt;p&gt;Install ddclient:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;apt update
&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;apt &lt;span class=&quot;nb&quot;&gt;install &lt;/span&gt;ddclient
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;During installation, you can skip the configuration prompts or configure for Namecheap directly.&lt;/p&gt;

&lt;p&gt;Edit the configuration:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;vim /etc/ddclient.conf
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Replace contents with:&lt;/p&gt;

&lt;div class=&quot;language-ini highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;# Configuration for Namecheap
&lt;/span&gt;&lt;span class=&quot;py&quot;&gt;daemon&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;600                   # Check every 10 minutes&lt;/span&gt;
&lt;span class=&quot;py&quot;&gt;syslog&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;yes                   # Log via syslog&lt;/span&gt;
&lt;span class=&quot;py&quot;&gt;pid&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;/var/run/ddclient.pid    # PID file location&lt;/span&gt;
&lt;span class=&quot;py&quot;&gt;ssl&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;yes                      # Use SSL&lt;/span&gt;

&lt;span class=&quot;c&quot;&gt;# Get IP from interface
&lt;/span&gt;&lt;span class=&quot;py&quot;&gt;use&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;if, if=eno1&lt;/span&gt;

&lt;span class=&quot;c&quot;&gt;# Namecheap settings
&lt;/span&gt;&lt;span class=&quot;py&quot;&gt;protocol&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;namecheap&lt;/span&gt;
&lt;span class=&quot;py&quot;&gt;server&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;dynamicdns.park-your-domain.com&lt;/span&gt;
&lt;span class=&quot;py&quot;&gt;login&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;yourdomain.com&lt;/span&gt;
&lt;span class=&quot;py&quot;&gt;password&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&apos;your-dynamic-dns-password&apos;&lt;/span&gt;
&lt;span class=&quot;err&quot;&gt;@,*&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Note&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Replace &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;your-dynamic-dns-password&lt;/code&gt; with the password from Namecheap’s Dynamic DNS settings&lt;/li&gt;
  &lt;li&gt;The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;@,*&lt;/code&gt; syntax updates both the root domain (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;yourdomain.com&lt;/code&gt; — &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;@&lt;/code&gt; is the zone-file shorthand for the bare apex, not a literal subdomain) and the wildcard (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;*.yourdomain.com&lt;/code&gt;)&lt;/li&gt;
  &lt;li&gt;Make sure both the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;@&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;*&lt;/code&gt; A-records are enabled for Dynamic DNS in Namecheap’s Advanced DNS panel&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Restart and enable:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;systemctl restart ddclient
&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;systemctl &lt;span class=&quot;nb&quot;&gt;enable &lt;/span&gt;ddclient
&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;systemctl status ddclient

&lt;span class=&quot;c&quot;&gt;# Check the logs&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;journalctl &lt;span class=&quot;nt&quot;&gt;-u&lt;/span&gt; ddclient &lt;span class=&quot;nt&quot;&gt;-f&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Test the update:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;ddclient &lt;span class=&quot;nt&quot;&gt;-daemon&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;0 &lt;span class=&quot;nt&quot;&gt;-debug&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-verbose&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-noquiet&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;wireguard-vpn-with-wg-easy&quot;&gt;WireGuard VPN with wg-easy&lt;/h2&gt;

&lt;p&gt;Set up WireGuard VPN with a web UI for easy client management.&lt;/p&gt;

&lt;h3 id=&quot;create-wireguard-directory&quot;&gt;Create WireGuard directory&lt;/h3&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nb&quot;&gt;sudo mkdir&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-p&lt;/span&gt; /opt/wireguard
&lt;span class=&quot;nb&quot;&gt;sudo chown&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-R&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$USER&lt;/span&gt;:&lt;span class=&quot;nv&quot;&gt;$USER&lt;/span&gt; /opt/wireguard
&lt;span class=&quot;nb&quot;&gt;cd&lt;/span&gt; /opt/wireguard
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;create-wireguard-docker-composeyml&quot;&gt;Create WireGuard docker-compose.yml&lt;/h3&gt;

&lt;p&gt;First, generate a password hash:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;docker run &lt;span class=&quot;nt&quot;&gt;-it&lt;/span&gt; ghcr.io/wg-easy/wg-easy wgpw &lt;span class=&quot;s1&quot;&gt;&apos;YourSecurePasswordHere&apos;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;This will output a bcrypt hash. Copy it for the next step.&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;vim docker-compose.yml
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;div class=&quot;language-yaml highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;na&quot;&gt;services&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;wg-easy&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;image&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;ghcr.io/wg-easy/wg-easy&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;container_name&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;wg-easy&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;environment&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
      &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;LANG=en&lt;/span&gt;
      &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;WG_HOST=yourdomain.com&lt;/span&gt;          &lt;span class=&quot;c1&quot;&gt;# Your dynamic DNS domain&lt;/span&gt;
      &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;PASSWORD_HASH=$$2a$$12$$xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx&lt;/span&gt;  &lt;span class=&quot;c1&quot;&gt;# Paste your hash here (escape $ with $$)&lt;/span&gt;
      &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;PORT=51821&lt;/span&gt;                   &lt;span class=&quot;c1&quot;&gt;# Web UI port&lt;/span&gt;
      &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;WG_PORT=51820&lt;/span&gt;                &lt;span class=&quot;c1&quot;&gt;# WireGuard VPN port&lt;/span&gt;
      &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;WG_DEFAULT_ADDRESS=10.13.13.x&lt;/span&gt;
      &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;WG_DEFAULT_DNS=192.168.0.2&lt;/span&gt;   &lt;span class=&quot;c1&quot;&gt;# Your LAN DNS&lt;/span&gt;
      &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;WG_ALLOWED_IPS=192.168.0.0/24, 10.13.13.0/24&lt;/span&gt;  &lt;span class=&quot;c1&quot;&gt;# LAN + VPN subnet&lt;/span&gt;
      &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;WG_PERSISTENT_KEEPALIVE=25&lt;/span&gt;
      &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;WG_MTU=1420&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;volumes&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
      &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;/opt/wireguard:/etc/wireguard&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;ports&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
      &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;51820:51820/udp&quot;&lt;/span&gt;            &lt;span class=&quot;c1&quot;&gt;# WireGuard port&lt;/span&gt;
      &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;192.168.0.101:51821:51821/tcp&quot;&lt;/span&gt;  &lt;span class=&quot;c1&quot;&gt;# Web UI (LAN only)&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;cap_add&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
      &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;NET_ADMIN&lt;/span&gt;
      &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;SYS_MODULE&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;sysctls&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
      &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;net.ipv4.conf.all.src_valid_mark=1&lt;/span&gt;
      &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;net.ipv4.ip_forward=1&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;restart&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;unless-stopped&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Important&lt;/strong&gt;: In docker-compose.yml, escape each &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;$&lt;/code&gt; in the hash by doubling it (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;$$&lt;/code&gt;).&lt;/p&gt;

&lt;h3 id=&quot;start-wireguard&quot;&gt;Start WireGuard&lt;/h3&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;docker compose up &lt;span class=&quot;nt&quot;&gt;-d&lt;/span&gt;

&lt;span class=&quot;c&quot;&gt;# Check logs&lt;/span&gt;
docker logs &lt;span class=&quot;nt&quot;&gt;-f&lt;/span&gt; wg-easy
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Docker will automatically handle the necessary iptables rules for WireGuard.&lt;/p&gt;

&lt;h3 id=&quot;access-web-ui&quot;&gt;Access Web UI&lt;/h3&gt;

&lt;p&gt;Open &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;http://192.168.0.101:51821&lt;/code&gt; from your LAN and log in with the password you set.&lt;/p&gt;

&lt;p&gt;From the web interface you can:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;Add/remove clients&lt;/li&gt;
  &lt;li&gt;Generate QR codes&lt;/li&gt;
  &lt;li&gt;Download config files&lt;/li&gt;
  &lt;li&gt;See connected clients&lt;/li&gt;
  &lt;li&gt;Enable/disable clients&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;add-and-download-client-configurations&quot;&gt;Add and download client configurations&lt;/h3&gt;

&lt;p&gt;Unlike &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;linuxserver/wireguard&lt;/code&gt;, wg-easy does &lt;strong&gt;not&lt;/strong&gt; generate per-peer files on disk — clients are created and managed entirely through the web UI:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Open &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;http://192.168.0.101:51821&lt;/code&gt; and log in&lt;/li&gt;
  &lt;li&gt;Click “New Client”, give it a name, and save&lt;/li&gt;
  &lt;li&gt;For each client, use the icons on its row to:
    &lt;ul&gt;
      &lt;li&gt;Show the &lt;strong&gt;QR code&lt;/strong&gt; (scan from a phone)&lt;/li&gt;
      &lt;li&gt;Download the &lt;strong&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.conf&lt;/code&gt; file&lt;/strong&gt; (for desktop clients)&lt;/li&gt;
      &lt;li&gt;Enable/disable or delete the client&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The underlying state is kept in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/opt/wireguard/wg0.conf&lt;/code&gt; (live interface config) and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/opt/wireguard/wg0.json&lt;/code&gt; (wg-easy’s metadata). You generally shouldn’t edit these by hand.&lt;/p&gt;

&lt;h3 id=&quot;connect-clients&quot;&gt;Connect clients&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Mobile (iOS/Android):&lt;/strong&gt;&lt;/p&gt;
&lt;ol&gt;
  &lt;li&gt;Install the WireGuard app&lt;/li&gt;
  &lt;li&gt;In the wg-easy web UI, click the QR-code icon next to the client and scan it&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;Desktop:&lt;/strong&gt;&lt;/p&gt;
&lt;ol&gt;
  &lt;li&gt;Install the WireGuard client&lt;/li&gt;
  &lt;li&gt;In the wg-easy web UI, click the download icon next to the client to grab its &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.conf&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;Import that file into the WireGuard client&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Once connected, you’ll have access to your entire LAN (192.168.0.0/24) through the VPN.&lt;/p&gt;

&lt;h3 id=&quot;check-connected-peers&quot;&gt;Check connected peers&lt;/h3&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;docker &lt;span class=&quot;nb&quot;&gt;exec &lt;/span&gt;wg-easy wg show
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;expose-wireguard-web-ui-via-npm-optional&quot;&gt;Expose WireGuard Web UI via NPM (Optional)&lt;/h3&gt;

&lt;p&gt;For remote management of WireGuard clients, expose the web UI through NPM:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Open NPM at &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;http://192.168.0.101:81&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;Go to “Proxy Hosts” → “Add Proxy Host”&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Details tab:&lt;/strong&gt;
    &lt;ul&gt;
      &lt;li&gt;Domain Names: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;wireguard.yourdomain.com&lt;/code&gt;&lt;/li&gt;
      &lt;li&gt;Scheme: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;http&lt;/code&gt;&lt;/li&gt;
      &lt;li&gt;Forward Hostname/IP: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;192.168.0.101&lt;/code&gt;&lt;/li&gt;
      &lt;li&gt;Forward Port: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;51821&lt;/code&gt;&lt;/li&gt;
      &lt;li&gt;Enable “Websockets Support”&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;SSL tab:&lt;/strong&gt;
    &lt;ul&gt;
      &lt;li&gt;SSL Certificate: “Request a new SSL Certificate”&lt;/li&gt;
      &lt;li&gt;Enable “Force SSL”&lt;/li&gt;
      &lt;li&gt;Accept Let’s Encrypt Terms&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;Save&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Now you can manage WireGuard clients remotely at &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;https://wireguard.yourdomain.com&lt;/code&gt; using your password.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Security note&lt;/strong&gt;: The web UI is already protected with bcrypt password hashing. Make sure you used a strong password when generating the hash.&lt;/p&gt;

&lt;h2 id=&quot;external-usb-drive-as-samba-share-storage&quot;&gt;External USB Drive as Samba Share Storage&lt;/h2&gt;

&lt;p&gt;Mount an external USB drive at &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/srv/share&lt;/code&gt; for Samba shares and Plex library.&lt;/p&gt;

&lt;h3 id=&quot;identify-and-format-the-drive&quot;&gt;Identify and format the drive&lt;/h3&gt;

&lt;p&gt;Plug in the USB drive and identify it:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;lsblk
&lt;span class=&quot;c&quot;&gt;# Should show sdb as 14T (with or without an existing sdb1 partition)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;If &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;lsblk&lt;/code&gt; only shows &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;sdb&lt;/code&gt; (no &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;sdb1&lt;/code&gt; underneath), the drive has no partition table yet — create one first:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;parted /dev/sdb &lt;span class=&quot;nt&quot;&gt;--&lt;/span&gt; mklabel gpt mkpart primary ext4 1MiB 100%
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Then format the partition with ext4:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;mkfs.ext4 /dev/sdb1
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;mount-the-drive&quot;&gt;Mount the drive&lt;/h3&gt;

&lt;p&gt;Create mount point and get UUID:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nb&quot;&gt;sudo mkdir&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-p&lt;/span&gt; /srv/share
&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;blkid /dev/sdb1
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Add to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/etc/fstab&lt;/code&gt; for automatic mounting:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The Recommended Change: x-systemd.automount&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Instead of a “static” mount that stays active forever, you should use systemd automount. This tells Linux: “Don’t worry about this drive right now, but the second any program (like Plex) tries to look inside &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/srv/share&lt;/code&gt;, mount it immediately.”&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nv&quot;&gt;UUID&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx /srv/share ext4 defaults,nofail,x-systemd.automount,x-systemd.idle-timeout&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;300 0 2
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Mount and set permissions:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;mount &lt;span class=&quot;nt&quot;&gt;-a&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;sudo chown&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-R&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$USER&lt;/span&gt;:&lt;span class=&quot;nv&quot;&gt;$USER&lt;/span&gt; /srv/share
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Verify it’s mounted:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nb&quot;&gt;df&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-h&lt;/span&gt; | &lt;span class=&quot;nb&quot;&gt;grep&lt;/span&gt; /srv/share
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;install-and-configure-samba&quot;&gt;Install and configure Samba&lt;/h3&gt;

&lt;p&gt;Install Samba to share &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/srv/share&lt;/code&gt;:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;apt &lt;span class=&quot;nb&quot;&gt;install &lt;/span&gt;samba
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Edit Samba config:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;vim /etc/samba/smb.conf
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Add the following share definition at the end of the file:&lt;/p&gt;

&lt;div class=&quot;language-ini highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nn&quot;&gt;[share]&lt;/span&gt;
   &lt;span class=&quot;py&quot;&gt;path&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;/srv/share&lt;/span&gt;
   &lt;span class=&quot;py&quot;&gt;browseable&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;yes&lt;/span&gt;
   &lt;span class=&quot;py&quot;&gt;writable&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;yes&lt;/span&gt;
   &lt;span class=&quot;err&quot;&gt;guest&lt;/span&gt; &lt;span class=&quot;py&quot;&gt;ok&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;no&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;create-samba-user&quot;&gt;Create Samba user&lt;/h3&gt;

&lt;p&gt;Create Samba user:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;smbpasswd &lt;span class=&quot;nt&quot;&gt;-a&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$USER&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;configure-firewall&quot;&gt;Configure firewall&lt;/h3&gt;

&lt;p&gt;Adjust firewall to allow Samba:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;# Allow Samba on LAN&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;iptables &lt;span class=&quot;nt&quot;&gt;-A&lt;/span&gt; INPUT &lt;span class=&quot;nt&quot;&gt;-i&lt;/span&gt; enp2s0 &lt;span class=&quot;nt&quot;&gt;-p&lt;/span&gt; udp &lt;span class=&quot;nt&quot;&gt;-m&lt;/span&gt; multiport &lt;span class=&quot;nt&quot;&gt;--dports&lt;/span&gt; 137,138 &lt;span class=&quot;nt&quot;&gt;-j&lt;/span&gt; ACCEPT
&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;iptables &lt;span class=&quot;nt&quot;&gt;-A&lt;/span&gt; INPUT &lt;span class=&quot;nt&quot;&gt;-i&lt;/span&gt; enp2s0 &lt;span class=&quot;nt&quot;&gt;-p&lt;/span&gt; tcp &lt;span class=&quot;nt&quot;&gt;-m&lt;/span&gt; multiport &lt;span class=&quot;nt&quot;&gt;--dports&lt;/span&gt; 139,445 &lt;span class=&quot;nt&quot;&gt;-j&lt;/span&gt; ACCEPT

&lt;span class=&quot;c&quot;&gt;# Block Samba externally&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;iptables &lt;span class=&quot;nt&quot;&gt;-A&lt;/span&gt; INPUT &lt;span class=&quot;nt&quot;&gt;-i&lt;/span&gt; eno1 &lt;span class=&quot;nt&quot;&gt;-p&lt;/span&gt; udp &lt;span class=&quot;nt&quot;&gt;-m&lt;/span&gt; multiport &lt;span class=&quot;nt&quot;&gt;--dports&lt;/span&gt; 137,138 &lt;span class=&quot;nt&quot;&gt;-j&lt;/span&gt; DROP
&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;iptables &lt;span class=&quot;nt&quot;&gt;-A&lt;/span&gt; INPUT &lt;span class=&quot;nt&quot;&gt;-i&lt;/span&gt; eno1 &lt;span class=&quot;nt&quot;&gt;-p&lt;/span&gt; tcp &lt;span class=&quot;nt&quot;&gt;-m&lt;/span&gt; multiport &lt;span class=&quot;nt&quot;&gt;--dports&lt;/span&gt; 139,445 &lt;span class=&quot;nt&quot;&gt;-j&lt;/span&gt; DROP
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Make it persistent across reboots:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;netfilter-persistent save
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;plex-media-server&quot;&gt;Plex Media Server&lt;/h2&gt;

&lt;p&gt;Restore Plex Media Server with your existing library at &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/srv/share/Library&lt;/code&gt;.&lt;/p&gt;

&lt;h3 id=&quot;create-plex-directory-structure&quot;&gt;Create Plex directory structure&lt;/h3&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nb&quot;&gt;sudo mkdir&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-p&lt;/span&gt; /opt/plex/config
&lt;span class=&quot;nb&quot;&gt;sudo chown&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-R&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$USER&lt;/span&gt;:&lt;span class=&quot;nv&quot;&gt;$USER&lt;/span&gt; /opt/plex
&lt;span class=&quot;nb&quot;&gt;cd&lt;/span&gt; /opt/plex
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;create-docker-composeyml-for-plex&quot;&gt;Create docker-compose.yml for Plex&lt;/h3&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;vim docker-compose.yml
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;div class=&quot;language-yaml highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;na&quot;&gt;services&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;plex&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;image&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;plexinc/pms-docker:latest&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;container_name&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;plex&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;network_mode&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;host&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;environment&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
      &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;TZ=America/Chicago&lt;/span&gt;
      &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;PLEX_UID=1000&lt;/span&gt;
      &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;PLEX_GID=1000&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;volumes&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
      &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;/opt/plex/config:/config&lt;/span&gt;
      &lt;span class=&quot;c1&quot;&gt;# :rslave ensures the container follows the host&apos;s mount/unmount events&lt;/span&gt;
      &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;/srv/share/Library:/data:rslave&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;devices&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
      &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;/dev/dri:/dev/dri&lt;/span&gt;  &lt;span class=&quot;c1&quot;&gt;# Intel QuickSync hardware transcoding (i5-8500T)&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;restart&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;unless-stopped&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:rslave&lt;/code&gt; option on the data volume is included because &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/srv/share&lt;/code&gt; is an external mount point. This ensures that if the drive is remounted on the host, the change propagates to the container.&lt;/li&gt;
  &lt;li&gt;Using &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;network_mode: host&lt;/code&gt; allows Plex to properly discover clients on your LAN and makes DLNA work correctly&lt;/li&gt;
  &lt;li&gt;The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/dev/dri&lt;/code&gt; device passthrough enables Intel QuickSync hardware transcoding on the i5-8500T’s UHD Graphics 630&lt;/li&gt;
  &lt;li&gt;After starting Plex, enable hardware acceleration in Settings → Transcoder&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;start-plex&quot;&gt;Start Plex&lt;/h3&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;docker compose up &lt;span class=&quot;nt&quot;&gt;-d&lt;/span&gt;

&lt;span class=&quot;c&quot;&gt;# Check logs&lt;/span&gt;
docker logs &lt;span class=&quot;nt&quot;&gt;-f&lt;/span&gt; plex
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;allow-plex-through-firewall&quot;&gt;Allow Plex through firewall&lt;/h3&gt;

&lt;p&gt;Since Plex uses &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;host&lt;/code&gt; networking mode, Docker doesn’t automatically manage firewall rules. Add an iptables rule to allow access from the LAN:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;iptables &lt;span class=&quot;nt&quot;&gt;-I&lt;/span&gt; INPUT &lt;span class=&quot;nt&quot;&gt;-i&lt;/span&gt; enp2s0 &lt;span class=&quot;nt&quot;&gt;-p&lt;/span&gt; tcp &lt;span class=&quot;nt&quot;&gt;--dport&lt;/span&gt; 32400 &lt;span class=&quot;nt&quot;&gt;-j&lt;/span&gt; ACCEPT
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Make it persistent across reboots (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;iptables-persistent&lt;/code&gt; was already installed in the &lt;a href=&quot;#firewall-with-iptables&quot;&gt;Firewall with iptables&lt;/a&gt; section above):&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;netfilter-persistent save
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;access-plex&quot;&gt;Access Plex&lt;/h3&gt;

&lt;p&gt;Open &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;http://192.168.0.101:32400/web&lt;/code&gt; from your LAN to set up Plex.&lt;/p&gt;

&lt;p&gt;During setup:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Sign in with your Plex account&lt;/li&gt;
  &lt;li&gt;Name your server&lt;/li&gt;
  &lt;li&gt;Add library pointing to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/data&lt;/code&gt; (which maps to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/srv/share/Library&lt;/code&gt;)&lt;/li&gt;
  &lt;li&gt;Plex should recognize your existing library structure&lt;/li&gt;
&lt;/ol&gt;

&lt;h3 id=&quot;enable-remote-access&quot;&gt;Enable Remote Access&lt;/h3&gt;

&lt;p&gt;Plex supports two methods for remote access: direct connection (better performance) and reverse proxy (uses existing SSL setup).&lt;/p&gt;

&lt;h4 id=&quot;method-1-direct-connection-recommended-for-streaming&quot;&gt;Method 1: Direct Connection (Recommended for streaming)&lt;/h4&gt;

&lt;p&gt;Allow Plex through the external interface:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;iptables &lt;span class=&quot;nt&quot;&gt;-I&lt;/span&gt; INPUT &lt;span class=&quot;nt&quot;&gt;-i&lt;/span&gt; eno1 &lt;span class=&quot;nt&quot;&gt;-p&lt;/span&gt; tcp &lt;span class=&quot;nt&quot;&gt;--dport&lt;/span&gt; 32400 &lt;span class=&quot;nt&quot;&gt;-j&lt;/span&gt; ACCEPT
&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;netfilter-persistent save
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Since &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;eno1&lt;/code&gt; has a public IP, no router port forwarding is needed — the iptables rule above is sufficient.&lt;/p&gt;

&lt;p&gt;In Plex Settings:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Go to Settings → Remote Access&lt;/li&gt;
  &lt;li&gt;Click “Enable Remote Access”&lt;/li&gt;
  &lt;li&gt;Manually specify port: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;32400&lt;/code&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h4 id=&quot;method-2-reverse-proxy-via-npm&quot;&gt;Method 2: Reverse Proxy via NPM&lt;/h4&gt;

&lt;p&gt;Add Plex to Nginx Proxy Manager for SSL access:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Open NPM at &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;http://192.168.0.101:81&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;Go to “Proxy Hosts” → “Add Proxy Host”&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Details tab:&lt;/strong&gt;
    &lt;ul&gt;
      &lt;li&gt;Domain Names: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;plex.yourdomain.com&lt;/code&gt;&lt;/li&gt;
      &lt;li&gt;Scheme: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;http&lt;/code&gt;&lt;/li&gt;
      &lt;li&gt;Forward Hostname/IP: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;192.168.0.101&lt;/code&gt;&lt;/li&gt;
      &lt;li&gt;Forward Port: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;32400&lt;/code&gt;&lt;/li&gt;
      &lt;li&gt;Enable “Websockets Support”&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;SSL tab:&lt;/strong&gt;
    &lt;ul&gt;
      &lt;li&gt;SSL Certificate: “Request a new SSL Certificate”&lt;/li&gt;
      &lt;li&gt;Enable “Force SSL”&lt;/li&gt;
      &lt;li&gt;Accept Let’s Encrypt Terms&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;Save&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;In Plex Settings → Network:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Add &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;https://plex.yourdomain.com:443&lt;/code&gt; to “Custom server access URLs”&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Note&lt;/strong&gt;: Both methods can be used simultaneously. Direct connection will be preferred for local network and external streaming, while the reverse proxy provides additional SSL access.&lt;/p&gt;

&lt;h2 id=&quot;ntfy---push-notification-service&quot;&gt;ntfy - Push Notification Service&lt;/h2&gt;

&lt;p&gt;Set up ntfy for simple push notifications to your devices.&lt;/p&gt;

&lt;h3 id=&quot;create-ntfy-directory&quot;&gt;Create ntfy directory&lt;/h3&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nb&quot;&gt;sudo mkdir&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-p&lt;/span&gt; /opt/ntfy
&lt;span class=&quot;nb&quot;&gt;sudo chown&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-R&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$USER&lt;/span&gt;:&lt;span class=&quot;nv&quot;&gt;$USER&lt;/span&gt; /opt/ntfy
&lt;span class=&quot;nb&quot;&gt;cd&lt;/span&gt; /opt/ntfy
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;create-ntfy-docker-composeyml&quot;&gt;Create ntfy docker-compose.yml&lt;/h3&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;vim docker-compose.yml
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;div class=&quot;language-yaml highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;na&quot;&gt;services&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;ntfy&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;image&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;binwiederhier/ntfy:latest&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;container_name&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;ntfy&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;command&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
      &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;serve&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;environment&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
      &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;TZ=America/Chicago&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;volumes&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
      &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;/opt/ntfy/cache:/var/cache/ntfy&lt;/span&gt;
      &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;/opt/ntfy/etc:/etc/ntfy&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;ports&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
      &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;192.168.0.101:8080:80&quot;&lt;/span&gt;  &lt;span class=&quot;c1&quot;&gt;# Web UI and API (LAN only)&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;restart&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;unless-stopped&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;start-ntfy&quot;&gt;Start ntfy&lt;/h3&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;docker compose up &lt;span class=&quot;nt&quot;&gt;-d&lt;/span&gt;

&lt;span class=&quot;c&quot;&gt;# Check logs&lt;/span&gt;
docker logs &lt;span class=&quot;nt&quot;&gt;-f&lt;/span&gt; ntfy
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;access-ntfy&quot;&gt;Access ntfy&lt;/h3&gt;

&lt;p&gt;Open &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;http://192.168.0.101:8080&lt;/code&gt; from your LAN.&lt;/p&gt;

&lt;h3 id=&quot;send-a-test-notification&quot;&gt;Send a test notification&lt;/h3&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;curl &lt;span class=&quot;nt&quot;&gt;-d&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;Hello from ntfy!&quot;&lt;/span&gt; http://192.168.0.101:8080/test
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Then subscribe to the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;test&lt;/code&gt; topic in the web UI or mobile app to see the notification.&lt;/p&gt;

&lt;h3 id=&quot;mobile-apps&quot;&gt;Mobile apps&lt;/h3&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;Android&lt;/strong&gt;: Install from Play Store or F-Droid&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;iOS&lt;/strong&gt;: Install from App Store&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In the app, add your server: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;http://192.168.0.101:8080&lt;/code&gt;&lt;/p&gt;

&lt;h3 id=&quot;expose-ntfy-via-npm&quot;&gt;Expose ntfy via NPM&lt;/h3&gt;

&lt;p&gt;For external access, add ntfy to Nginx Proxy Manager:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Open NPM at &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;http://192.168.0.101:81&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;Go to “Proxy Hosts” → “Add Proxy Host”&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Details tab:&lt;/strong&gt;
    &lt;ul&gt;
      &lt;li&gt;Domain Names: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ntfy.yourdomain.com&lt;/code&gt;&lt;/li&gt;
      &lt;li&gt;Scheme: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;http&lt;/code&gt;&lt;/li&gt;
      &lt;li&gt;Forward Hostname/IP: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;192.168.0.101&lt;/code&gt;&lt;/li&gt;
      &lt;li&gt;Forward Port: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;8080&lt;/code&gt;&lt;/li&gt;
      &lt;li&gt;Enable “Websockets Support”&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;SSL tab:&lt;/strong&gt;
    &lt;ul&gt;
      &lt;li&gt;SSL Certificate: “Request a new SSL Certificate”&lt;/li&gt;
      &lt;li&gt;Enable “Force SSL”&lt;/li&gt;
      &lt;li&gt;Accept Let’s Encrypt Terms&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;Save&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Then you can send notifications from anywhere:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;curl &lt;span class=&quot;nt&quot;&gt;-d&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;External notification&quot;&lt;/span&gt; https://ntfy.yourdomain.com/alerts
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Update your mobile apps to use &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;https://ntfy.yourdomain.com&lt;/code&gt; instead of the local IP.&lt;/p&gt;

&lt;h2 id=&quot;nextcloud-with-dedicated-drive&quot;&gt;Nextcloud with Dedicated Drive&lt;/h2&gt;

&lt;p&gt;Set up Nextcloud with a dedicated 1.9TB drive for data storage.&lt;/p&gt;

&lt;h3 id=&quot;format-and-mount-the-drive&quot;&gt;Format and mount the drive&lt;/h3&gt;

&lt;p&gt;First, identify the drive:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;lsblk
&lt;span class=&quot;c&quot;&gt;# Should show sda as 1.9T&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Format the drive with ext4. Here we format the whole disk (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/dev/sda&lt;/code&gt;) directly, no partition table — simpler when the drive is dedicated to a single purpose and won’t be moved between systems. If you’d prefer the partitioned approach used for the Samba drive above, run &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;sudo parted /dev/sda -- mklabel gpt mkpart primary ext4 1MiB 100%&lt;/code&gt; first and then &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;mkfs.ext4 /dev/sda1&lt;/code&gt; (and use &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/dev/sda1&lt;/code&gt; everywhere &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/dev/sda&lt;/code&gt; appears below).&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;mkfs.ext4 /dev/sda
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Create mount point and get UUID:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nb&quot;&gt;sudo mkdir&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-p&lt;/span&gt; /srv/nextcloud
&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;blkid /dev/sda
&lt;span class=&quot;c&quot;&gt;# Note the UUID value&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Add to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/etc/fstab&lt;/code&gt; for automatic mounting:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;vim /etc/fstab
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Add this line (replace YOUR-UUID with the actual UUID):&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-fstab&quot;&gt;UUID=YOUR-UUID  /srv/nextcloud  ext4  defaults,nofail  0  2
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;&lt;strong&gt;Why eager mount instead of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;x-systemd.automount&lt;/code&gt; (which we used for &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/srv/share&lt;/code&gt;)&lt;/strong&gt;: the Nextcloud Docker container bind-mounts &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/srv/nextcloud&lt;/code&gt; into &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/var/www/html/data&lt;/code&gt; &lt;em&gt;without&lt;/em&gt; &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:rslave&lt;/code&gt; propagation (unlike Plex’s &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/srv/share/Library&lt;/code&gt; mount). With automount, the drive only appears on first access — if Nextcloud’s container starts before any process touches &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/srv/nextcloud&lt;/code&gt;, the bind-mount sees the empty mount-point directory instead of the real data, and Nextcloud silently writes to the system disk. Eager-mounting at boot avoids that race entirely. If you’d rather mirror the Samba drive’s &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;x-systemd.automount&lt;/code&gt; setup, also add &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:rslave&lt;/code&gt; to the data volume in Nextcloud’s &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;docker-compose.yml&lt;/code&gt;:&lt;/p&gt;

&lt;div class=&quot;language-yaml highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;/srv/nextcloud:/var/www/html/data:rslave&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Mount and set permissions:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;mount &lt;span class=&quot;nt&quot;&gt;-a&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;systemctl daemon-reload  &lt;span class=&quot;c&quot;&gt;# Reload systemd if you see the fstab modified hint&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;sudo chown&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-R&lt;/span&gt; 33:33 /srv/nextcloud  &lt;span class=&quot;c&quot;&gt;# www-data user for Nextcloud&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Verify it’s mounted:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nb&quot;&gt;df&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-h&lt;/span&gt; | &lt;span class=&quot;nb&quot;&gt;grep &lt;/span&gt;nextcloud
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;give-your-user-read-access&quot;&gt;Give your user read access&lt;/h3&gt;

&lt;p&gt;Add your user to the www-data group to access the Nextcloud drive:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;usermod &lt;span class=&quot;nt&quot;&gt;-a&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-G&lt;/span&gt; www-data &lt;span class=&quot;nv&quot;&gt;$USER&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Then log out and back in, or run:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;newgrp www-data
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;This allows you to read files on the Nextcloud drive. The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;force user/group&lt;/code&gt; settings in the Samba configuration ensure any files created via SMB are properly owned by &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;www-data&lt;/code&gt; for Nextcloud to use.&lt;/p&gt;

&lt;h3 id=&quot;create-nextcloud-directory&quot;&gt;Create Nextcloud directory&lt;/h3&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nb&quot;&gt;sudo mkdir&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-p&lt;/span&gt; /opt/nextcloud
&lt;span class=&quot;nb&quot;&gt;sudo chown&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-R&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$USER&lt;/span&gt;:&lt;span class=&quot;nv&quot;&gt;$USER&lt;/span&gt; /opt/nextcloud
&lt;span class=&quot;nb&quot;&gt;cd&lt;/span&gt; /opt/nextcloud
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;create-nextcloud-docker-composeyml&quot;&gt;Create Nextcloud docker-compose.yml&lt;/h3&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;vim docker-compose.yml
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;div class=&quot;language-yaml highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;na&quot;&gt;services&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;db&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;image&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;mariadb:latest&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;container_name&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;nextcloud-db&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;command&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;--transaction-isolation=READ-COMMITTED --log-bin=binlog --binlog-format=ROW&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;restart&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;unless-stopped&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;volumes&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
      &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;/opt/nextcloud/db:/var/lib/mysql&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;environment&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
      &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;MYSQL_ROOT_PASSWORD=CHANGEME_ROOT_PASSWORD&lt;/span&gt;
      &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;MYSQL_PASSWORD=CHANGEME_NEXTCLOUD_PASSWORD&lt;/span&gt;
      &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;MYSQL_DATABASE=nextcloud&lt;/span&gt;
      &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;MYSQL_USER=nextcloud&lt;/span&gt;
      &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;TZ=America/Chicago&lt;/span&gt;

  &lt;span class=&quot;na&quot;&gt;app&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;image&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;nextcloud:latest&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;container_name&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;nextcloud&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;restart&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;unless-stopped&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;ports&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
      &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;192.168.0.101:8081:80&quot;&lt;/span&gt;  &lt;span class=&quot;c1&quot;&gt;# Web interface (LAN only)&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;links&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
      &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;db&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;volumes&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
      &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;/opt/nextcloud/html:/var/www/html&lt;/span&gt;
      &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;/srv/nextcloud:/var/www/html/data&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;environment&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
      &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;MYSQL_PASSWORD=CHANGEME_NEXTCLOUD_PASSWORD&lt;/span&gt;   &lt;span class=&quot;c1&quot;&gt;# must match the db service&apos;s MYSQL_PASSWORD above&lt;/span&gt;
      &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;MYSQL_DATABASE=nextcloud&lt;/span&gt;
      &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;MYSQL_USER=nextcloud&lt;/span&gt;
      &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;MYSQL_HOST=db&lt;/span&gt;
      &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;TZ=America/Chicago&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;depends_on&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
      &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;db&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Important&lt;/strong&gt;: Change the passwords to secure values before starting.&lt;/p&gt;

&lt;p&gt;(Optionally, run &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;openssl rand -base64 32&lt;/code&gt; twice to generate two secure passwords — one for &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;MYSQL_ROOT_PASSWORD&lt;/code&gt; and one shared between the db service’s &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;MYSQL_PASSWORD&lt;/code&gt; and the app service’s &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;MYSQL_PASSWORD&lt;/code&gt;.)&lt;/p&gt;

&lt;h3 id=&quot;start-nextcloud&quot;&gt;Start Nextcloud&lt;/h3&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;docker compose up &lt;span class=&quot;nt&quot;&gt;-d&lt;/span&gt;

&lt;span class=&quot;c&quot;&gt;# Watch the initialization (takes a few minutes)&lt;/span&gt;
docker logs &lt;span class=&quot;nt&quot;&gt;-f&lt;/span&gt; nextcloud
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;access-nextcloud&quot;&gt;Access Nextcloud&lt;/h3&gt;

&lt;p&gt;Open &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;http://192.168.0.101:8081&lt;/code&gt; from your LAN.&lt;/p&gt;

&lt;p&gt;During first setup:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Create admin account&lt;/li&gt;
  &lt;li&gt;Data folder should already be set to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/var/www/html/data&lt;/code&gt; (the 1.9TB drive)&lt;/li&gt;
  &lt;li&gt;Database settings are already configured via environment variables&lt;/li&gt;
  &lt;li&gt;Click “Install”&lt;/li&gt;
&lt;/ol&gt;

&lt;h3 id=&quot;expose-nextcloud-via-npm&quot;&gt;Expose Nextcloud via NPM&lt;/h3&gt;

&lt;p&gt;Add Nextcloud to Nginx Proxy Manager for external access:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Open NPM at &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;http://192.168.0.101:81&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;Go to “Proxy Hosts” → “Add Proxy Host”&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Details tab:&lt;/strong&gt;
    &lt;ul&gt;
      &lt;li&gt;Domain Names: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;nextcloud.yourdomain.com&lt;/code&gt;&lt;/li&gt;
      &lt;li&gt;Scheme: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;http&lt;/code&gt;&lt;/li&gt;
      &lt;li&gt;Forward Hostname/IP: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;192.168.0.101&lt;/code&gt;&lt;/li&gt;
      &lt;li&gt;Forward Port: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;8081&lt;/code&gt;&lt;/li&gt;
      &lt;li&gt;Enable “Websockets Support”&lt;/li&gt;
      &lt;li&gt;Scroll down to &lt;strong&gt;Advanced&lt;/strong&gt; section&lt;/li&gt;
      &lt;li&gt;
        &lt;p&gt;In “Custom Nginx Configuration” box, add:&lt;/p&gt;

        &lt;div class=&quot;language-nginx highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;client_max_body_size&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;10G&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;proxy_request_buffering&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;off&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;        &lt;/div&gt;
      &lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;SSL tab:&lt;/strong&gt;
    &lt;ul&gt;
      &lt;li&gt;SSL Certificate: “Request a new SSL Certificate”&lt;/li&gt;
      &lt;li&gt;Enable “Force SSL”&lt;/li&gt;
      &lt;li&gt;Accept Let’s Encrypt Terms&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;Save&lt;/li&gt;
&lt;/ol&gt;

&lt;h3 id=&quot;configure-trusted-domains&quot;&gt;Configure trusted domains&lt;/h3&gt;

&lt;p&gt;After setting up the reverse proxy, add the domain to Nextcloud’s trusted domains.&lt;/p&gt;

&lt;p&gt;Edit the config file on the host:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;vim /opt/nextcloud/html/config/config.php
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Find the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;trusted_domains&lt;/code&gt; array and add your domain, plus the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;overwriteprotocol&lt;/code&gt; setting:&lt;/p&gt;

&lt;div class=&quot;language-php highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;s1&quot;&gt;&apos;trusted_domains&apos;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;array&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
  &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;192.168.0.101:8081&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;nextcloud.yourdomain.com&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt;
&lt;span class=&quot;s1&quot;&gt;&apos;overwriteprotocol&apos;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;https&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;overwriteprotocol&lt;/code&gt; setting tells Nextcloud to generate HTTPS URLs even though NPM forwards to it via HTTP internally.&lt;/p&gt;

&lt;p&gt;Restart Nextcloud:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nb&quot;&gt;cd&lt;/span&gt; /opt/nextcloud
docker restart nextcloud
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Now you can access Nextcloud at &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;https://nextcloud.yourdomain.com&lt;/code&gt; with all your data stored on the 1.9TB drive.&lt;/p&gt;

&lt;h3 id=&quot;add-samba-share-for-direct-file-access&quot;&gt;Add Samba share for direct file access&lt;/h3&gt;

&lt;p&gt;For native file system access to Nextcloud data, add another share to the existing Samba configuration.&lt;/p&gt;

&lt;p&gt;Edit the Samba config:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;vim /etc/samba/smb.conf
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Add the Nextcloud share definition at the end of the file:&lt;/p&gt;

&lt;div class=&quot;language-ini highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nn&quot;&gt;[nextcloud]&lt;/span&gt;
&lt;span class=&quot;py&quot;&gt;path&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;/srv/nextcloud&lt;/span&gt;
&lt;span class=&quot;py&quot;&gt;browseable&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;yes&lt;/span&gt;
&lt;span class=&quot;py&quot;&gt;writable&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;yes&lt;/span&gt;
&lt;span class=&quot;err&quot;&gt;guest&lt;/span&gt; &lt;span class=&quot;py&quot;&gt;ok&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;no&lt;/span&gt;
&lt;span class=&quot;err&quot;&gt;valid&lt;/span&gt; &lt;span class=&quot;py&quot;&gt;users&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;nextcloud&lt;/span&gt;
&lt;span class=&quot;err&quot;&gt;force&lt;/span&gt; &lt;span class=&quot;py&quot;&gt;user&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;www-data&lt;/span&gt;
&lt;span class=&quot;err&quot;&gt;force&lt;/span&gt; &lt;span class=&quot;py&quot;&gt;group&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;www-data&lt;/span&gt;
&lt;span class=&quot;err&quot;&gt;create&lt;/span&gt; &lt;span class=&quot;py&quot;&gt;mask&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;0664&lt;/span&gt;
&lt;span class=&quot;err&quot;&gt;directory&lt;/span&gt; &lt;span class=&quot;py&quot;&gt;mask&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;0775&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Create a system user and Samba user for Nextcloud access:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;# Create a system user (no login, no home directory)&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;useradd &lt;span class=&quot;nt&quot;&gt;-r&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-s&lt;/span&gt; /usr/sbin/nologin &lt;span class=&quot;nt&quot;&gt;-M&lt;/span&gt; nextcloud

&lt;span class=&quot;c&quot;&gt;# Create Samba password for the nextcloud user&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;smbpasswd &lt;span class=&quot;nt&quot;&gt;-a&lt;/span&gt; nextcloud
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Important&lt;/strong&gt;: Set a secure password when prompted.&lt;/p&gt;

&lt;p&gt;Restart Samba to apply changes:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;systemctl restart smbd
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;access-the-share&quot;&gt;Access the share&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Windows:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Open File Explorer&lt;/li&gt;
  &lt;li&gt;Type in address bar: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;\\192.168.0.101\nextcloud&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;Username: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;nextcloud&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;Password: (the one you set)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Mac:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Finder → Go → Connect to Server&lt;/li&gt;
  &lt;li&gt;Server: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;smb://192.168.0.101/nextcloud&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;Username: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;nextcloud&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;Password: (the one you set)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Linux:&lt;/strong&gt;&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;apt &lt;span class=&quot;nb&quot;&gt;install &lt;/span&gt;cifs-utils
&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;mount &lt;span class=&quot;nt&quot;&gt;-t&lt;/span&gt; cifs //192.168.0.101/nextcloud /mnt/share &lt;span class=&quot;nt&quot;&gt;-o&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;username&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;nextcloud,uid&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;1000,gid&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;1000
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;sync-changes-to-nextcloud&quot;&gt;Sync changes to Nextcloud&lt;/h3&gt;

&lt;p&gt;After making changes via SMB, tell Nextcloud to rescan for new files:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;docker &lt;span class=&quot;nb&quot;&gt;exec&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-u&lt;/span&gt; www-data nextcloud php occ files:scan &lt;span class=&quot;nt&quot;&gt;--all&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Or for a specific user:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;docker &lt;span class=&quot;nb&quot;&gt;exec&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-u&lt;/span&gt; www-data nextcloud php occ files:scan username
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Note&lt;/strong&gt;: Files added/modified via SMB won’t immediately appear in Nextcloud web interface until a scan is run. Consider setting up a cron job for periodic scans if you frequently use SMB.&lt;/p&gt;

&lt;h2 id=&quot;wallabag---read-it-later-service&quot;&gt;Wallabag - Read It Later Service&lt;/h2&gt;

&lt;p&gt;Self-hosted application for saving web pages to read later (like Pocket or Instapaper).&lt;/p&gt;

&lt;h3 id=&quot;create-wallabag-directory&quot;&gt;Create Wallabag directory&lt;/h3&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nb&quot;&gt;sudo mkdir&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-p&lt;/span&gt; /opt/wallabag
&lt;span class=&quot;nb&quot;&gt;sudo chown&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-R&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$USER&lt;/span&gt;:&lt;span class=&quot;nv&quot;&gt;$USER&lt;/span&gt; /opt/wallabag
&lt;span class=&quot;nb&quot;&gt;cd&lt;/span&gt; /opt/wallabag
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;create-wallabag-docker-composeyml&quot;&gt;Create Wallabag docker-compose.yml&lt;/h3&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;vim docker-compose.yml
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;div class=&quot;language-yaml highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;na&quot;&gt;services&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;wallabag&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;image&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;wallabag/wallabag&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;container_name&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;wallabag&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;environment&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
      &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;SYMFONY__ENV__DATABASE_DRIVER=pdo_sqlite&lt;/span&gt;
      &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;SYMFONY__ENV__DATABASE_NAME=wallabag&lt;/span&gt;
      &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;SYMFONY__ENV__DOMAIN_NAME=https://wallabag.yourdomain.com&lt;/span&gt;
      &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;SYMFONY__ENV__SERVER_NAME=My Wallabag&lt;/span&gt;   &lt;span class=&quot;c1&quot;&gt;# no inner quotes — YAML&apos;s `- &quot;key=value&quot;` form already passes the value verbatim, so quoting &quot;My Wallabag&quot; inside would propagate the literal quotes to the container&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;ports&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
      &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;192.168.0.101:8082:80&quot;&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;volumes&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
      &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;./data:/var/www/wallabag/data&lt;/span&gt;
      &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;./images:/var/www/wallabag/web/assets/images&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;restart&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;unless-stopped&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Important&lt;/strong&gt;: Replace &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;https://wallabag.yourdomain.com&lt;/code&gt; with your actual domain.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Note&lt;/strong&gt;: Using SQLite keeps everything simple—just one container, and the database is a single file in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;./data&lt;/code&gt;. Perfect for personal use.&lt;/p&gt;

&lt;h3 id=&quot;start-wallabag&quot;&gt;Start Wallabag&lt;/h3&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;docker compose up &lt;span class=&quot;nt&quot;&gt;-d&lt;/span&gt;

&lt;span class=&quot;c&quot;&gt;# Check logs&lt;/span&gt;
docker logs &lt;span class=&quot;nt&quot;&gt;-f&lt;/span&gt; wallabag
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;allow-wallabag-through-firewall&quot;&gt;Allow Wallabag through firewall&lt;/h3&gt;

&lt;p&gt;The consolidated firewall script in the &lt;a href=&quot;#final-firewall-configuration&quot;&gt;Final Firewall Configuration&lt;/a&gt; section below already includes port 8082. If you’re setting Wallabag up first and haven’t reached that section yet, add the rule manually:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;iptables &lt;span class=&quot;nt&quot;&gt;-A&lt;/span&gt; INPUT &lt;span class=&quot;nt&quot;&gt;-i&lt;/span&gt; enp2s0 &lt;span class=&quot;nt&quot;&gt;-p&lt;/span&gt; tcp &lt;span class=&quot;nt&quot;&gt;--dport&lt;/span&gt; 8082 &lt;span class=&quot;nt&quot;&gt;-j&lt;/span&gt; ACCEPT
&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;netfilter-persistent save
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;expose-wallabag-via-npm&quot;&gt;Expose Wallabag via NPM&lt;/h3&gt;

&lt;ol&gt;
  &lt;li&gt;Open NPM at &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;http://192.168.0.101:81&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;Go to “Proxy Hosts” → “Add Proxy Host”&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Details tab:&lt;/strong&gt;
    &lt;ul&gt;
      &lt;li&gt;Domain Names: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;wallabag.yourdomain.com&lt;/code&gt;&lt;/li&gt;
      &lt;li&gt;Scheme: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;http&lt;/code&gt;&lt;/li&gt;
      &lt;li&gt;Forward Hostname/IP: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;192.168.0.101&lt;/code&gt;&lt;/li&gt;
      &lt;li&gt;Forward Port: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;8082&lt;/code&gt;&lt;/li&gt;
      &lt;li&gt;Enable “Websockets Support”&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;SSL tab:&lt;/strong&gt;
    &lt;ul&gt;
      &lt;li&gt;SSL Certificate: “Request a new SSL Certificate”&lt;/li&gt;
      &lt;li&gt;Enable “Force SSL”&lt;/li&gt;
      &lt;li&gt;Accept Let’s Encrypt Terms&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;Save&lt;/li&gt;
&lt;/ol&gt;

&lt;h3 id=&quot;access-wallabag&quot;&gt;Access Wallabag&lt;/h3&gt;

&lt;p&gt;Open &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;https://wallabag.yourdomain.com&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Default credentials:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;Username: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;wallabag&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;Password: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;wallabag&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Security note&lt;/strong&gt;: Change the password immediately after logging in.&lt;/p&gt;

&lt;h2 id=&quot;rustdesk---self-hosted-remote-desktop&quot;&gt;RustDesk - Self-Hosted Remote Desktop&lt;/h2&gt;

&lt;p&gt;Set up RustDesk server for secure, self-hosted remote desktop access.&lt;/p&gt;

&lt;p&gt;For more details, see the &lt;a href=&quot;https://rustdesk.com/docs/en/self-host/&quot;&gt;official RustDesk server documentation&lt;/a&gt;.&lt;/p&gt;

&lt;h3 id=&quot;create-rustdesk-directory&quot;&gt;Create RustDesk directory&lt;/h3&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nb&quot;&gt;sudo mkdir&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-p&lt;/span&gt; /opt/rustdesk
&lt;span class=&quot;nb&quot;&gt;sudo chown&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-R&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$USER&lt;/span&gt;:&lt;span class=&quot;nv&quot;&gt;$USER&lt;/span&gt; /opt/rustdesk
&lt;span class=&quot;nb&quot;&gt;cd&lt;/span&gt; /opt/rustdesk
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;create-rustdesk-docker-composeyml&quot;&gt;Create RustDesk docker-compose.yml&lt;/h3&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;vim docker-compose.yml
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;div class=&quot;language-yaml highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;na&quot;&gt;services&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;hbbs&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;container_name&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;rustdesk-hbbs&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;image&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;rustdesk/rustdesk-server:latest&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;command&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;hbbs -r rustdesk.yourdomain.com:21117&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;volumes&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
      &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;./data:/root&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;network_mode&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;host&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;restart&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;unless-stopped&lt;/span&gt;

  &lt;span class=&quot;na&quot;&gt;hbbr&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;container_name&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;rustdesk-hbbr&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;image&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;rustdesk/rustdesk-server:latest&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;command&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;hbbr&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;volumes&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
      &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;./data:/root&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;network_mode&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;host&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;restart&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;unless-stopped&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Note&lt;/strong&gt;: Replace &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;rustdesk.yourdomain.com&lt;/code&gt; with your actual domain.&lt;/p&gt;

&lt;h3 id=&quot;start-rustdesk&quot;&gt;Start RustDesk&lt;/h3&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;docker compose up &lt;span class=&quot;nt&quot;&gt;-d&lt;/span&gt;

&lt;span class=&quot;c&quot;&gt;# Check logs&lt;/span&gt;
docker logs &lt;span class=&quot;nt&quot;&gt;-f&lt;/span&gt; rustdesk-hbbs
docker logs &lt;span class=&quot;nt&quot;&gt;-f&lt;/span&gt; rustdesk-hbbr
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;get-the-public-key&quot;&gt;Get the public key&lt;/h3&gt;

&lt;p&gt;After starting, retrieve the public key needed for client configuration:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nb&quot;&gt;cat&lt;/span&gt; /opt/rustdesk/data/id_ed25519.pub
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Save this key - you’ll need it when configuring RustDesk clients.&lt;/p&gt;

&lt;h3 id=&quot;configure-rustdesk-clients&quot;&gt;Configure RustDesk clients&lt;/h3&gt;

&lt;p&gt;On each device you want to control or connect from:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Download and install RustDesk from &lt;a href=&quot;https://rustdesk.com&quot;&gt;https://rustdesk.com&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;Open RustDesk settings&lt;/li&gt;
  &lt;li&gt;Click “Network” → “ID Server”&lt;/li&gt;
  &lt;li&gt;Set ID Server to: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;rustdesk.yourdomain.com&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;Set Relay Server to: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;rustdesk.yourdomain.com&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;Click “Key” and paste the public key from earlier&lt;/li&gt;
  &lt;li&gt;Click “Apply”&lt;/li&gt;
&lt;/ol&gt;

&lt;h3 id=&quot;usage&quot;&gt;Usage&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;To allow someone to connect to you:&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Open RustDesk&lt;/li&gt;
  &lt;li&gt;Share your ID and password with the remote user&lt;/li&gt;
  &lt;li&gt;They enter your ID and password in their RustDesk client&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;To connect to another device:&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Open RustDesk&lt;/li&gt;
  &lt;li&gt;Enter the remote device’s ID&lt;/li&gt;
  &lt;li&gt;Click “Connect”&lt;/li&gt;
  &lt;li&gt;Enter the password when prompted&lt;/li&gt;
&lt;/ol&gt;

&lt;h2 id=&quot;immich---self-hosted-photo--video-backup&quot;&gt;Immich - Self-Hosted Photo &amp;amp; Video Backup&lt;/h2&gt;

&lt;p&gt;High performance self-hosted photo and video management solution.&lt;/p&gt;

&lt;h3 id=&quot;create-immich-directory&quot;&gt;Create Immich directory&lt;/h3&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nb&quot;&gt;sudo mkdir&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-p&lt;/span&gt; /opt/immich
&lt;span class=&quot;nb&quot;&gt;sudo chown&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-R&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$USER&lt;/span&gt;:&lt;span class=&quot;nv&quot;&gt;$USER&lt;/span&gt; /opt/immich
&lt;span class=&quot;nb&quot;&gt;cd&lt;/span&gt; /opt/immich
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;download-configuration-files&quot;&gt;Download configuration files&lt;/h3&gt;

&lt;p&gt;Download the recommended &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;docker-compose.yml&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.env&lt;/code&gt; files:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;wget &lt;span class=&quot;nt&quot;&gt;-O&lt;/span&gt; docker-compose.yml https://github.com/immich-app/immich/releases/latest/download/docker-compose.yml
wget &lt;span class=&quot;nt&quot;&gt;-O&lt;/span&gt; .env https://github.com/immich-app/immich/releases/latest/download/example.env
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;configure-environment&quot;&gt;Configure environment&lt;/h3&gt;

&lt;p&gt;Edit the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.env&lt;/code&gt; file to configure your settings:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;vim .env
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Key settings to adjust:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;UPLOAD_LOCATION&lt;/code&gt;: Set this to a path with plenty of storage. Since we have a large external drive mounted at &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/srv/share&lt;/code&gt;, let’s use that.&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;DB_PASSWORD&lt;/code&gt;: Set a secure password for the database.&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;TZ&lt;/code&gt;: Set your timezone (e.g., &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;America/Chicago&lt;/code&gt;).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Create the upload directory:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nb&quot;&gt;sudo mkdir&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-p&lt;/span&gt; /srv/share/Immich
&lt;span class=&quot;nb&quot;&gt;sudo chown&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-R&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$USER&lt;/span&gt;:&lt;span class=&quot;nv&quot;&gt;$USER&lt;/span&gt; /srv/share/Immich
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Then update &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.env&lt;/code&gt;:&lt;/p&gt;

&lt;div class=&quot;language-ini highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;py&quot;&gt;UPLOAD_LOCATION&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;/srv/share/Immich&lt;/span&gt;
&lt;span class=&quot;py&quot;&gt;DB_PASSWORD&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;YourSecurePassword&lt;/span&gt;
&lt;span class=&quot;py&quot;&gt;TZ&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;America/Chicago&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;start-immich&quot;&gt;Start Immich&lt;/h3&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;docker compose up &lt;span class=&quot;nt&quot;&gt;-d&lt;/span&gt;

&lt;span class=&quot;c&quot;&gt;# Check logs&lt;/span&gt;
docker logs &lt;span class=&quot;nt&quot;&gt;-f&lt;/span&gt; immich_server
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;expose-immich-via-npm&quot;&gt;Expose Immich via NPM&lt;/h3&gt;

&lt;ol&gt;
  &lt;li&gt;Open NPM at &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;http://192.168.0.101:81&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;Go to “Proxy Hosts” → “Add Proxy Host”&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Details tab:&lt;/strong&gt;
    &lt;ul&gt;
      &lt;li&gt;Domain Names: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;photos.yourdomain.com&lt;/code&gt;&lt;/li&gt;
      &lt;li&gt;Scheme: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;http&lt;/code&gt;&lt;/li&gt;
      &lt;li&gt;Forward Hostname/IP: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;192.168.0.101&lt;/code&gt;&lt;/li&gt;
      &lt;li&gt;Forward Port: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;2283&lt;/code&gt;&lt;/li&gt;
      &lt;li&gt;Enable “Websockets Support”&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Advanced tab:&lt;/strong&gt;
    &lt;ul&gt;
      &lt;li&gt;In “Custom Nginx Configuration” box, add:
        &lt;div class=&quot;language-nginx highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;client_max_body_size&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;proxy_read_timeout&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;600s&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;proxy_send_timeout&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;600s&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;send_timeout&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;600s&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;        &lt;/div&gt;
      &lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;SSL tab:&lt;/strong&gt;
    &lt;ul&gt;
      &lt;li&gt;SSL Certificate: “Request a new SSL Certificate”&lt;/li&gt;
      &lt;li&gt;Enable “Force SSL”&lt;/li&gt;
      &lt;li&gt;Accept Let’s Encrypt Terms&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;Save&lt;/li&gt;
&lt;/ol&gt;

&lt;h3 id=&quot;access-immich&quot;&gt;Access Immich&lt;/h3&gt;

&lt;p&gt;Open &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;https://photos.yourdomain.com&lt;/code&gt; or &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;http://192.168.0.101:2283&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Create the admin account on first login.&lt;/p&gt;

&lt;h3 id=&quot;mobile-apps-1&quot;&gt;Mobile Apps&lt;/h3&gt;

&lt;p&gt;Download the Immich app for iOS or Android and connect to your server URL (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;https://photos.yourdomain.com&lt;/code&gt;).&lt;/p&gt;

&lt;h3 id=&quot;troubleshooting-system-freeze-optional-i-didnt-do-this&quot;&gt;Troubleshooting: System Freeze (optional, I didn’t do this)&lt;/h3&gt;

&lt;p&gt;If the system locks up during &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;docker compose up -d&lt;/code&gt;, it’s likely the &lt;strong&gt;Machine Learning&lt;/strong&gt; container consuming all CPU resources. The i5-8500T has 6 cores, and Immich may try to use them all.&lt;/p&gt;

&lt;p&gt;To fix this, add resource limits to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;docker-compose.yml&lt;/code&gt;:&lt;/p&gt;

&lt;div class=&quot;language-yaml highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;  &lt;span class=&quot;na&quot;&gt;immich-machine-learning&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;# ... existing config ...&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;deploy&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
      &lt;span class=&quot;na&quot;&gt;resources&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;na&quot;&gt;limits&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
          &lt;span class=&quot;na&quot;&gt;cpus&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;4&apos;&lt;/span&gt;  &lt;span class=&quot;c1&quot;&gt;# Leave 2 cores for the system&lt;/span&gt;
          &lt;span class=&quot;na&quot;&gt;memory&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;8G&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;calibre-web---ebook-library-access&quot;&gt;Calibre-Web - Ebook Library Access&lt;/h2&gt;

&lt;p&gt;Use desktop Calibre for editing/conversion; use Calibre-Web here for browsing/downloading. Sync the library from your desktop to the server; treat the server copy as read-mostly.&lt;/p&gt;

&lt;h3 id=&quot;create-library-directory&quot;&gt;Create library directory&lt;/h3&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nb&quot;&gt;sudo mkdir&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-p&lt;/span&gt; /srv/share/CalibreLibrary
&lt;span class=&quot;nb&quot;&gt;sudo chown&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-R&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$USER&lt;/span&gt;:&lt;span class=&quot;nv&quot;&gt;$USER&lt;/span&gt; /srv/share/CalibreLibrary
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;deploy-calibre-web&quot;&gt;Deploy Calibre-Web&lt;/h3&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nb&quot;&gt;sudo mkdir&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-p&lt;/span&gt; /opt/calibre-web
&lt;span class=&quot;nb&quot;&gt;sudo chown&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-R&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$USER&lt;/span&gt;:&lt;span class=&quot;nv&quot;&gt;$USER&lt;/span&gt; /opt/calibre-web
&lt;span class=&quot;nb&quot;&gt;cd&lt;/span&gt; /opt/calibre-web
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Create compose file:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;vim docker-compose.yml
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;div class=&quot;language-yaml highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;na&quot;&gt;services&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;calibre-web&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;image&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;lscr.io/linuxserver/calibre-web:latest&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;container_name&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;calibre-web&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;environment&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
      &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;PUID=1000&lt;/span&gt;
      &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;PGID=1000&lt;/span&gt;
      &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;TZ=America/Chicago&lt;/span&gt;
      &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;DOCKER_MODS=linuxserver/mods:universal-calibre&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;volumes&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
      &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;/opt/calibre-web/config:/config&lt;/span&gt;
      &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;/srv/share/CalibreLibrary:/books&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;ports&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
      &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;192.168.0.101:8083:8083&quot;&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;restart&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;unless-stopped&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Start:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;docker compose up &lt;span class=&quot;nt&quot;&gt;-d&lt;/span&gt;

&lt;span class=&quot;c&quot;&gt;# Check logs&lt;/span&gt;
docker logs &lt;span class=&quot;nt&quot;&gt;-f&lt;/span&gt; calibre-web
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;access-calibre-web&quot;&gt;Access Calibre-Web&lt;/h3&gt;

&lt;p&gt;Open &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;http://192.168.0.101:8083&lt;/code&gt; from your LAN.&lt;/p&gt;

&lt;p&gt;First-run setup:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;Set library path to: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/books&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;Create admin user&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;sync-from-desktop-calibre&quot;&gt;Sync from desktop Calibre&lt;/h3&gt;

&lt;p&gt;On your desktop (after closing Calibre), run:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;rsync &lt;span class=&quot;nt&quot;&gt;-avz&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;--delete&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;/path/to/DesktopCalibreLibrary/&quot;&lt;/span&gt; user@yourserver:/srv/share/CalibreLibrary/
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Important:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;--delete&lt;/code&gt; removes books deleted locally (omit if you want to keep server copies)&lt;/li&gt;
  &lt;li&gt;Run only when Calibre desktop is closed to avoid database corruption&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;After sync, refresh the database in Calibre-Web (Settings → Re-scan Library).&lt;/p&gt;

&lt;h3 id=&quot;optional-sync-script&quot;&gt;Optional sync script&lt;/h3&gt;

&lt;p&gt;Create &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;sync-calibre.sh&lt;/code&gt; on your desktop:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;#!/usr/bin/env bash&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;set&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-e&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;SRC&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;/path/to/DesktopCalibreLibrary/&quot;&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;DEST&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;user@yourserver:/srv/share/CalibreLibrary/&quot;&lt;/span&gt;
rsync &lt;span class=&quot;nt&quot;&gt;-avz&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;--delete&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$SRC&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$DEST&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;Sync complete. Refresh Calibre-Web database.&quot;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Make executable:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nb&quot;&gt;chmod&lt;/span&gt; +x sync-calibre.sh
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Run manually after editing books in desktop Calibre.&lt;/p&gt;

&lt;h3 id=&quot;lan-firewall-rule&quot;&gt;LAN firewall rule&lt;/h3&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;iptables &lt;span class=&quot;nt&quot;&gt;-A&lt;/span&gt; INPUT &lt;span class=&quot;nt&quot;&gt;-i&lt;/span&gt; enp2s0 &lt;span class=&quot;nt&quot;&gt;-p&lt;/span&gt; tcp &lt;span class=&quot;nt&quot;&gt;--dport&lt;/span&gt; 8083 &lt;span class=&quot;nt&quot;&gt;-j&lt;/span&gt; ACCEPT
&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;netfilter-persistent save
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;optional-reverse-proxy-via-npm&quot;&gt;Optional reverse proxy via NPM&lt;/h3&gt;

&lt;p&gt;For external access:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Open NPM at &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;http://192.168.0.101:81&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;Go to “Proxy Hosts” → “Add Proxy Host”&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Details tab:&lt;/strong&gt;
    &lt;ul&gt;
      &lt;li&gt;Domain Names: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;books.yourdomain.com&lt;/code&gt;&lt;/li&gt;
      &lt;li&gt;Scheme: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;http&lt;/code&gt;&lt;/li&gt;
      &lt;li&gt;Forward Hostname/IP: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;192.168.0.101&lt;/code&gt;&lt;/li&gt;
      &lt;li&gt;Forward Port: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;8083&lt;/code&gt;&lt;/li&gt;
      &lt;li&gt;Enable “Websockets Support”&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;SSL tab:&lt;/strong&gt;
    &lt;ul&gt;
      &lt;li&gt;SSL Certificate: “Request a new SSL Certificate”&lt;/li&gt;
      &lt;li&gt;Enable “Force SSL”&lt;/li&gt;
      &lt;li&gt;Accept Let’s Encrypt Terms&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;Save&lt;/li&gt;
&lt;/ol&gt;

&lt;h2 id=&quot;copyparty---easy-file-browsing--sharing&quot;&gt;Copyparty - Easy File Browsing &amp;amp; Sharing&lt;/h2&gt;

&lt;p&gt;Lightweight file server for browsing and uploading files to your shared drives via web interface.&lt;/p&gt;

&lt;h3 id=&quot;create-copyparty-directory&quot;&gt;Create Copyparty directory&lt;/h3&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nb&quot;&gt;sudo mkdir&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-p&lt;/span&gt; /opt/copyparty
&lt;span class=&quot;nb&quot;&gt;sudo chown&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-R&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$USER&lt;/span&gt;:&lt;span class=&quot;nv&quot;&gt;$USER&lt;/span&gt; /opt/copyparty
&lt;span class=&quot;nb&quot;&gt;cd&lt;/span&gt; /opt/copyparty
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;create-the-sandbox-share-directory&quot;&gt;Create the sandbox share directory&lt;/h3&gt;

&lt;p&gt;Rather than exposing the entirety of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/srv/share&lt;/code&gt; (which holds Plex &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Library/&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;CalibreLibrary/&lt;/code&gt;, and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Immich/&lt;/code&gt; photo backups) through copyparty, create a dedicated subfolder that copyparty will be the only thing reading or writing:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nb&quot;&gt;sudo mkdir&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-p&lt;/span&gt; /srv/share/copyparty
&lt;span class=&quot;nb&quot;&gt;sudo chown&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-R&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$USER&lt;/span&gt;:&lt;span class=&quot;nv&quot;&gt;$USER&lt;/span&gt; /srv/share/copyparty
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;This way the blast radius of any copyparty misconfiguration is bounded to that one directory.&lt;/p&gt;

&lt;h3 id=&quot;create-copyparty-docker-composeyml&quot;&gt;Create Copyparty docker-compose.yml&lt;/h3&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;vim docker-compose.yml
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;div class=&quot;language-yaml highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;na&quot;&gt;services&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;copyparty&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;image&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;copyparty/ac:latest&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;container_name&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;copyparty&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;user&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;1000:1000&quot;&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;ports&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
      &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;192.168.0.101:3923:3923&quot;&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;volumes&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
      &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;/srv/share/copyparty:/mnt/share&lt;/span&gt;   &lt;span class=&quot;c1&quot;&gt;# sandbox — NOT /srv/share itself&lt;/span&gt;
      &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;/opt/copyparty/config:/cfg&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;environment&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
      &lt;span class=&quot;na&quot;&gt;LD_PRELOAD&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;/usr/lib/libmimalloc-secure.so.NOPE&lt;/span&gt;
      &lt;span class=&quot;c1&quot;&gt;# enable mimalloc by replacing &quot;NOPE&quot; with &quot;2&quot; for a nice speed-boost (will use twice as much ram)&lt;/span&gt;

      &lt;span class=&quot;na&quot;&gt;PYTHONUNBUFFERED&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;1&lt;/span&gt;
      &lt;span class=&quot;c1&quot;&gt;# ensures log-messages are not delayed (but can reduce speed a tiny bit)&lt;/span&gt;

    &lt;span class=&quot;na&quot;&gt;stop_grace_period&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;15s&lt;/span&gt;  &lt;span class=&quot;c1&quot;&gt;# thumbnailer is allowed to continue finishing up for 10s after the shutdown signal&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;healthcheck&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
      &lt;span class=&quot;c1&quot;&gt;# hide it from logs with &quot;/._&quot; so it matches the default --lf-url filter &lt;/span&gt;
      &lt;span class=&quot;na&quot;&gt;test&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;pi&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;CMD-SHELL&quot;&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;wget&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;--spider&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;-q&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;127.0.0.1:3923/?reset=/._&quot;&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;]&lt;/span&gt;
      &lt;span class=&quot;na&quot;&gt;interval&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;1m&lt;/span&gt;
      &lt;span class=&quot;na&quot;&gt;timeout&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;2s&lt;/span&gt;
      &lt;span class=&quot;na&quot;&gt;retries&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;5&lt;/span&gt;
      &lt;span class=&quot;na&quot;&gt;start_period&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;15s&lt;/span&gt;

    &lt;span class=&quot;na&quot;&gt;restart&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;unless-stopped&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;create-configuration-file&quot;&gt;Create configuration file&lt;/h3&gt;

&lt;p&gt;Create the configuration file to define your shares and settings:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;vim /opt/copyparty/config/copyparty.conf
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;div class=&quot;language-ini highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;# not actually YAML but lets pretend:
# -*- mode: yaml -*-
# vim: ft=yaml:
&lt;/span&gt;

&lt;span class=&quot;nn&quot;&gt;[global]&lt;/span&gt;
  &lt;span class=&quot;err&quot;&gt;e2dsa&lt;/span&gt;  &lt;span class=&quot;c&quot;&gt;# enable file indexing and filesystem scanning
&lt;/span&gt;  &lt;span class=&quot;err&quot;&gt;e2ts&lt;/span&gt;   &lt;span class=&quot;c&quot;&gt;# enable multimedia indexing
&lt;/span&gt;  &lt;span class=&quot;err&quot;&gt;ansi&lt;/span&gt;   &lt;span class=&quot;c&quot;&gt;# enable colors in log messages (both in logfiles and stdout)
&lt;/span&gt;  &lt;span class=&quot;err&quot;&gt;name:&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;File&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;Server&lt;/span&gt;  &lt;span class=&quot;c&quot;&gt;# name displayed in browser title/header
&lt;/span&gt;  &lt;span class=&quot;err&quot;&gt;xff-src:&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;lan&lt;/span&gt;  &lt;span class=&quot;c&quot;&gt;# trust X-Forwarded-For headers from private IPs (Docker/LAN)
&lt;/span&gt;  &lt;span class=&quot;err&quot;&gt;rproxy:&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;1&lt;/span&gt;     &lt;span class=&quot;c&quot;&gt;# 1 hop behind reverse proxy
&lt;/span&gt;  &lt;span class=&quot;err&quot;&gt;no-robots&lt;/span&gt;     &lt;span class=&quot;c&quot;&gt;# discourage search engines from indexing if you ever NPM-expose this
&lt;/span&gt;
  &lt;span class=&quot;c&quot;&gt;# q, lo: /cfg/log/%Y-%m%d.log   # log to file instead of docker
&lt;/span&gt;
  &lt;span class=&quot;c&quot;&gt;# p: 3939          # listen on another port
&lt;/span&gt;  &lt;span class=&quot;c&quot;&gt;# ipa: 10.89.      # only allow connections from 10.89.*
&lt;/span&gt;  &lt;span class=&quot;c&quot;&gt;# df: 16           # stop accepting uploads if less than 16 GB free disk space
&lt;/span&gt;  &lt;span class=&quot;c&quot;&gt;# ver              # show copyparty version in the controlpanel
&lt;/span&gt;  &lt;span class=&quot;c&quot;&gt;# grid             # show thumbnails/grid-view by default
&lt;/span&gt;  &lt;span class=&quot;c&quot;&gt;# theme: 2         # monokai
&lt;/span&gt;  &lt;span class=&quot;c&quot;&gt;# stats, nos-dup   # enable the prometheus endpoint, but disable the dupes counter (too slow)
&lt;/span&gt;  &lt;span class=&quot;c&quot;&gt;# force-js         # make it harder for search engines to read your server
&lt;/span&gt;

&lt;span class=&quot;nn&quot;&gt;[accounts]&lt;/span&gt;
  &lt;span class=&quot;err&quot;&gt;yourname:&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;REPLACE_WITH_STRONG_PASSWORD&lt;/span&gt;   &lt;span class=&quot;c&quot;&gt;# username: password (use `openssl rand -base64 24` for the password)
&lt;/span&gt;

&lt;span class=&quot;nn&quot;&gt;[/]&lt;/span&gt;              &lt;span class=&quot;c&quot;&gt;# create a volume at the webroot which will
&lt;/span&gt;  &lt;span class=&quot;err&quot;&gt;/mnt/share&lt;/span&gt;     &lt;span class=&quot;c&quot;&gt;# share /mnt/share (host&apos;s /srv/share/copyparty sandbox)
&lt;/span&gt;  &lt;span class=&quot;err&quot;&gt;accs:&lt;/span&gt;
    &lt;span class=&quot;err&quot;&gt;rw:&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;*&lt;/span&gt;             &lt;span class=&quot;c&quot;&gt;# anyone can read (browse/download) and write (upload).
&lt;/span&gt;                      &lt;span class=&quot;c&quot;&gt;# `rw` does NOT include move (`m`), delete (`d`), or admin (`a`)
&lt;/span&gt;                      &lt;span class=&quot;c&quot;&gt;# — anonymous users can drop files in but can&apos;t alter or remove
&lt;/span&gt;                      &lt;span class=&quot;c&quot;&gt;# what&apos;s there. Good fit for a LAN drop-box.
&lt;/span&gt;    &lt;span class=&quot;err&quot;&gt;rwmda:&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;yourname&lt;/span&gt;   &lt;span class=&quot;c&quot;&gt;# `yourname` additionally gets move/delete/admin
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Security note on &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;rw: *&lt;/code&gt;&lt;/strong&gt;: anon &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;rw&lt;/code&gt; is read + upload only — destructive ops (move, delete) require the named-account permissions on the second line. That’s the intentional shape of this share. Two things to keep in mind anyway:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;The mount is &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/srv/share/copyparty&lt;/code&gt;, not all of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/srv/share&lt;/code&gt;, so the blast radius is bounded to that subfolder regardless of ACL.&lt;/li&gt;
  &lt;li&gt;Be more deliberate before NPM-exposing this. An internet-facing anonymous upload endpoint is abusable as a free file dump (warez, malware staging, etc.) — even without delete rights, attackers can fill the drive with arbitrary content under your domain. If you do expose it externally, see the layered Access List recommendation below, or drop the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;*&lt;/code&gt; and keep public access login-only via the proxy host.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;start-copyparty&quot;&gt;Start Copyparty&lt;/h3&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;docker compose up &lt;span class=&quot;nt&quot;&gt;-d&lt;/span&gt;

&lt;span class=&quot;c&quot;&gt;# Check logs&lt;/span&gt;
docker logs &lt;span class=&quot;nt&quot;&gt;-f&lt;/span&gt; copyparty
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;access-copyparty&quot;&gt;Access Copyparty&lt;/h3&gt;

&lt;p&gt;Open &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;http://192.168.0.101:3923&lt;/code&gt; from your LAN.&lt;/p&gt;

&lt;p&gt;You’ll see your &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/srv/share&lt;/code&gt; drive mounted as &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/mnt/share&lt;/code&gt; with full browsing and download capabilities.&lt;/p&gt;

&lt;h3 id=&quot;lan-firewall-rule-1&quot;&gt;LAN firewall rule&lt;/h3&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;iptables &lt;span class=&quot;nt&quot;&gt;-A&lt;/span&gt; INPUT &lt;span class=&quot;nt&quot;&gt;-i&lt;/span&gt; enp2s0 &lt;span class=&quot;nt&quot;&gt;-p&lt;/span&gt; tcp &lt;span class=&quot;nt&quot;&gt;--dport&lt;/span&gt; 3923 &lt;span class=&quot;nt&quot;&gt;-j&lt;/span&gt; ACCEPT
&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;netfilter-persistent save
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;optional-expose-via-npm&quot;&gt;Optional: Expose via NPM&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Before exposing&lt;/strong&gt;: anonymous &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;rw: *&lt;/code&gt; is fine on the LAN as a drop-box, but treat NPM exposure as a different threat model. With the proxy host below, anyone on the internet can hit the URL — and anon upload (even without delete) means strangers can fill &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/srv/share/copyparty&lt;/code&gt; with arbitrary content under your domain. Either drop &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;rw: *&lt;/code&gt; from the share before exposing, or layer an NPM Access List on top (see below) so basic-auth gates the proxy host before any request reaches copyparty.&lt;/p&gt;

&lt;p&gt;For external access:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Open NPM at &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;http://192.168.0.101:81&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;Go to “Proxy Hosts” → “Add Proxy Host”&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Details tab:&lt;/strong&gt;
    &lt;ul&gt;
      &lt;li&gt;Domain Names: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;files.yourdomain.com&lt;/code&gt;&lt;/li&gt;
      &lt;li&gt;Scheme: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;http&lt;/code&gt;&lt;/li&gt;
      &lt;li&gt;Forward Hostname/IP: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;192.168.0.101&lt;/code&gt;&lt;/li&gt;
      &lt;li&gt;Forward Port: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;3923&lt;/code&gt;&lt;/li&gt;
      &lt;li&gt;Enable “Websockets Support”&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;SSL tab:&lt;/strong&gt;
    &lt;ul&gt;
      &lt;li&gt;SSL Certificate: “Request a new SSL Certificate”&lt;/li&gt;
      &lt;li&gt;Enable “Force SSL”&lt;/li&gt;
      &lt;li&gt;Accept Let’s Encrypt Terms&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;Save&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;For an even stronger setup, add an NPM &lt;strong&gt;Access List&lt;/strong&gt; (Username/Password basic-auth) on top of copyparty’s own login, so an attacker would need to clear two layers before reaching the file UI.&lt;/p&gt;

&lt;h2 id=&quot;openspeedtest---network-speed-testing&quot;&gt;OpenSpeedTest - Network Speed Testing&lt;/h2&gt;

&lt;p&gt;Self-hosted HTML5 network speed test server. No Flash or Java required.&lt;/p&gt;

&lt;h3 id=&quot;create-openspeedtest-directory&quot;&gt;Create OpenSpeedTest directory&lt;/h3&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nb&quot;&gt;sudo mkdir&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-p&lt;/span&gt; /opt/openspeedtest
&lt;span class=&quot;nb&quot;&gt;sudo chown&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-R&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$USER&lt;/span&gt;:&lt;span class=&quot;nv&quot;&gt;$USER&lt;/span&gt; /opt/openspeedtest
&lt;span class=&quot;nb&quot;&gt;cd&lt;/span&gt; /opt/openspeedtest
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;create-openspeedtest-docker-composeyml&quot;&gt;Create OpenSpeedTest docker-compose.yml&lt;/h3&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;vim docker-compose.yml
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;div class=&quot;language-yaml highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;na&quot;&gt;services&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;openspeedtest&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;image&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;openspeedtest/latest&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;container_name&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;openspeedtest&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;ports&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
      &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;192.168.0.101:3000:3000&quot;&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;restart&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;unless-stopped&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;start-openspeedtest&quot;&gt;Start OpenSpeedTest&lt;/h3&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;docker compose up &lt;span class=&quot;nt&quot;&gt;-d&lt;/span&gt;

&lt;span class=&quot;c&quot;&gt;# Check logs&lt;/span&gt;
docker logs &lt;span class=&quot;nt&quot;&gt;-f&lt;/span&gt; openspeedtest
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;access-openspeedtest&quot;&gt;Access OpenSpeedTest&lt;/h3&gt;

&lt;p&gt;Open &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;http://192.168.0.101:3000&lt;/code&gt; from your LAN.&lt;/p&gt;

&lt;h3 id=&quot;lan-firewall-rule-2&quot;&gt;LAN firewall rule&lt;/h3&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;iptables &lt;span class=&quot;nt&quot;&gt;-A&lt;/span&gt; INPUT &lt;span class=&quot;nt&quot;&gt;-i&lt;/span&gt; enp2s0 &lt;span class=&quot;nt&quot;&gt;-p&lt;/span&gt; tcp &lt;span class=&quot;nt&quot;&gt;--dport&lt;/span&gt; 3000 &lt;span class=&quot;nt&quot;&gt;-j&lt;/span&gt; ACCEPT
&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;netfilter-persistent save
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;optional-expose-via-npm-1&quot;&gt;Optional: Expose via NPM&lt;/h3&gt;

&lt;p&gt;For external access (to test speed from outside):&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Open NPM at &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;http://192.168.0.101:81&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;Go to “Proxy Hosts” → “Add Proxy Host”&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Details tab:&lt;/strong&gt;
    &lt;ul&gt;
      &lt;li&gt;Domain Names: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;speed.yourdomain.com&lt;/code&gt;&lt;/li&gt;
      &lt;li&gt;Scheme: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;http&lt;/code&gt;&lt;/li&gt;
      &lt;li&gt;Forward Hostname/IP: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;192.168.0.101&lt;/code&gt;&lt;/li&gt;
      &lt;li&gt;Forward Port: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;3000&lt;/code&gt;&lt;/li&gt;
      &lt;li&gt;Enable “Websockets Support”&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;SSL tab:&lt;/strong&gt;
    &lt;ul&gt;
      &lt;li&gt;SSL Certificate: “Request a new SSL Certificate”&lt;/li&gt;
      &lt;li&gt;Enable “Force SSL”&lt;/li&gt;
      &lt;li&gt;Accept Let’s Encrypt Terms&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;Save&lt;/li&gt;
&lt;/ol&gt;

&lt;h2 id=&quot;netdata---real-time-performance-monitoring&quot;&gt;Netdata - Real-time Performance Monitoring&lt;/h2&gt;

&lt;p&gt;Real-time health monitoring and performance troubleshooting.&lt;/p&gt;

&lt;h3 id=&quot;create-netdata-directory&quot;&gt;Create Netdata directory&lt;/h3&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nb&quot;&gt;sudo mkdir&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-p&lt;/span&gt; /opt/netdata
&lt;span class=&quot;nb&quot;&gt;sudo chown&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-R&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$USER&lt;/span&gt;:&lt;span class=&quot;nv&quot;&gt;$USER&lt;/span&gt; /opt/netdata
&lt;span class=&quot;nb&quot;&gt;cd&lt;/span&gt; /opt/netdata
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;create-netdata-docker-composeyml&quot;&gt;Create Netdata docker-compose.yml&lt;/h3&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;vim docker-compose.yml
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;div class=&quot;language-yaml highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;na&quot;&gt;services&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;netdata&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;image&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;netdata/netdata&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;container_name&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;netdata&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;pid&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;host&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;network_mode&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;host&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;restart&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;unless-stopped&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;cap_add&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
      &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;SYS_PTRACE&lt;/span&gt;
      &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;SYS_ADMIN&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;security_opt&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
      &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;apparmor:unconfined&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;volumes&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
      &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;netdataconfig:/etc/netdata&lt;/span&gt;
      &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;netdatalib:/var/lib/netdata&lt;/span&gt;
      &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;netdatacache:/var/cache/netdata&lt;/span&gt;
      &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;/etc/passwd:/host/etc/passwd:ro&lt;/span&gt;
      &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;/etc/group:/host/etc/group:ro&lt;/span&gt;
      &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;/proc:/host/proc:ro&lt;/span&gt;
      &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;/sys:/host/sys:ro&lt;/span&gt;
      &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;/etc/os-release:/host/etc/os-release:ro&lt;/span&gt;
      &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;/var/log:/host/var/log:ro&lt;/span&gt;
      &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;/var/run/docker.sock:/var/run/docker.sock:ro&lt;/span&gt;

&lt;span class=&quot;na&quot;&gt;volumes&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;netdataconfig&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;netdatalib&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;netdatacache&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;start-netdata&quot;&gt;Start Netdata&lt;/h3&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;docker compose up &lt;span class=&quot;nt&quot;&gt;-d&lt;/span&gt;

&lt;span class=&quot;c&quot;&gt;# Check logs&lt;/span&gt;
docker logs &lt;span class=&quot;nt&quot;&gt;-f&lt;/span&gt; netdata
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;lan-firewall-rule-3&quot;&gt;LAN firewall rule&lt;/h3&gt;

&lt;p&gt;Since Netdata uses &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;host&lt;/code&gt; networking, we must explicitly allow the port in iptables. We need to allow access from the LAN (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;enp2s0&lt;/code&gt;) for direct access, and from Docker (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;br+&lt;/code&gt;) so NPM can reach it.&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;iptables &lt;span class=&quot;nt&quot;&gt;-A&lt;/span&gt; INPUT &lt;span class=&quot;nt&quot;&gt;-i&lt;/span&gt; enp2s0 &lt;span class=&quot;nt&quot;&gt;-p&lt;/span&gt; tcp &lt;span class=&quot;nt&quot;&gt;--dport&lt;/span&gt; 19999 &lt;span class=&quot;nt&quot;&gt;-j&lt;/span&gt; ACCEPT
&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;iptables &lt;span class=&quot;nt&quot;&gt;-A&lt;/span&gt; INPUT &lt;span class=&quot;nt&quot;&gt;-i&lt;/span&gt; br+ &lt;span class=&quot;nt&quot;&gt;-p&lt;/span&gt; tcp &lt;span class=&quot;nt&quot;&gt;--dport&lt;/span&gt; 19999 &lt;span class=&quot;nt&quot;&gt;-j&lt;/span&gt; ACCEPT
&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;netfilter-persistent save
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;access-netdata&quot;&gt;Access Netdata&lt;/h3&gt;

&lt;p&gt;Open &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;http://192.168.0.101:19999&lt;/code&gt; from your LAN.&lt;/p&gt;

&lt;h3 id=&quot;optional-expose-via-npm-securely&quot;&gt;Optional: Expose via NPM (Securely)&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Security Warning&lt;/strong&gt;: Netdata has no default password. Do not expose it to the internet without adding authentication via NPM Access Lists.&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;&lt;strong&gt;Create an Access List in NPM:&lt;/strong&gt;
    &lt;ul&gt;
      &lt;li&gt;Open NPM at &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;http://192.168.0.101:81&lt;/code&gt;&lt;/li&gt;
      &lt;li&gt;Go to &lt;strong&gt;Access Lists&lt;/strong&gt; → “Add Access List”&lt;/li&gt;
      &lt;li&gt;Name: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Admin Access&lt;/code&gt;&lt;/li&gt;
      &lt;li&gt;&lt;strong&gt;Authorization&lt;/strong&gt; tab: Add a Username and Password&lt;/li&gt;
      &lt;li&gt;Save&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Create Proxy Host:&lt;/strong&gt;
    &lt;ul&gt;
      &lt;li&gt;Go to “Proxy Hosts” → “Add Proxy Host”&lt;/li&gt;
      &lt;li&gt;&lt;strong&gt;Details tab:&lt;/strong&gt;
        &lt;ul&gt;
          &lt;li&gt;Domain Names: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;monitor.yourdomain.com&lt;/code&gt;&lt;/li&gt;
          &lt;li&gt;Scheme: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;http&lt;/code&gt;&lt;/li&gt;
          &lt;li&gt;Forward Hostname/IP: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;192.168.0.101&lt;/code&gt;&lt;/li&gt;
          &lt;li&gt;Forward Port: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;19999&lt;/code&gt;&lt;/li&gt;
          &lt;li&gt;&lt;strong&gt;Access List&lt;/strong&gt;: Select &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Admin Access&lt;/code&gt; (This is critical!)&lt;/li&gt;
          &lt;li&gt;Enable “Websockets Support”&lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
      &lt;li&gt;&lt;strong&gt;SSL tab:&lt;/strong&gt;
        &lt;ul&gt;
          &lt;li&gt;SSL Certificate: “Request a new SSL Certificate”&lt;/li&gt;
          &lt;li&gt;Enable “Force SSL”&lt;/li&gt;
          &lt;li&gt;Accept Let’s Encrypt Terms&lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
      &lt;li&gt;Save&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Now, when you visit &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;https://monitor.yourdomain.com&lt;/code&gt;, you’ll be prompted for the username and password you set up in the Access List.&lt;/p&gt;

&lt;h2 id=&quot;watchtower---container-update-monitoring&quot;&gt;Watchtower - Container Update Monitoring&lt;/h2&gt;

&lt;p&gt;Watchtower monitors your Docker containers for updates and can optionally apply them automatically. We’ll use &lt;strong&gt;monitor-only mode&lt;/strong&gt; to get notifications without automatic updates, giving you control over when to update critical services.&lt;/p&gt;

&lt;h3 id=&quot;create-watchtower-directory&quot;&gt;Create Watchtower directory&lt;/h3&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nb&quot;&gt;sudo mkdir&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-p&lt;/span&gt; /opt/watchtower
&lt;span class=&quot;nb&quot;&gt;sudo chown&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-R&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$USER&lt;/span&gt;:&lt;span class=&quot;nv&quot;&gt;$USER&lt;/span&gt; /opt/watchtower
&lt;span class=&quot;nb&quot;&gt;cd&lt;/span&gt; /opt/watchtower
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;create-watchtower-docker-composeyml&quot;&gt;Create Watchtower docker-compose.yml&lt;/h3&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;vim docker-compose.yml
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;div class=&quot;language-yaml highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;na&quot;&gt;services&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;watchtower&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;image&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;containrrr/watchtower:latest&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;container_name&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;watchtower&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;environment&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
      &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;TZ=America/Chicago&lt;/span&gt;
      &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;DOCKER_API_VERSION=1.44&lt;/span&gt;
      &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;WATCHTOWER_MONITOR_ONLY=true&lt;/span&gt;
      &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;WATCHTOWER_NOTIFICATION_URL=ntfy://192.168.0.101:8080/watchtower?scheme=http&amp;amp;title=Watchtower&lt;/span&gt;
      &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;WATCHTOWER_NOTIFICATIONS=shoutrrr&lt;/span&gt;
      &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;WATCHTOWER_NOTIFICATIONS_LEVEL=info&lt;/span&gt;
      &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;WATCHTOWER_SCHEDULE=0 0 17 * * *&lt;/span&gt;  &lt;span class=&quot;c1&quot;&gt;# Check daily at 5 PM&lt;/span&gt;
      &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;WATCHTOWER_CLEANUP=true&lt;/span&gt;
      &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;WATCHTOWER_DISABLE_CONTAINERS=immich_postgres,immich_machine_learning,immich_redis&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;volumes&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
      &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;/var/run/docker.sock:/var/run/docker.sock&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;restart&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;unless-stopped&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Configuration explained:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;WATCHTOWER_MONITOR_ONLY=true&lt;/code&gt;: Only notify, don’t update&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;WATCHTOWER_NOTIFICATIONS&lt;/code&gt;: Send notifications via ntfy&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;WATCHTOWER_NOTIFICATIONS_LEVEL=info&lt;/code&gt;: Notify when updates are found (standard log level for findings)&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;WATCHTOWER_DISABLE_CONTAINERS&lt;/code&gt;: Exclude dependency containers (Immich’s postgres and machine-learning) from monitoring. &lt;strong&gt;Verify the names match your installation&lt;/strong&gt; — recent Immich releases sometimes use hyphens (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;immich-postgres&lt;/code&gt;) instead of underscores. Run &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;docker ps --format &apos;&apos; | grep immich&lt;/code&gt; and update this list to match what’s actually running.&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;WATCHTOWER_SCHEDULE&lt;/code&gt;: Cron schedule (5 PM daily)&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;WATCHTOWER_CLEANUP=true&lt;/code&gt;: Remove old images after updates (if you enable auto-update later)&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;start-watchtower&quot;&gt;Start Watchtower&lt;/h3&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;docker compose up &lt;span class=&quot;nt&quot;&gt;-d&lt;/span&gt;

&lt;span class=&quot;c&quot;&gt;# Check logs&lt;/span&gt;
docker logs &lt;span class=&quot;nt&quot;&gt;-f&lt;/span&gt; watchtower
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;triggering-a-manual-check&quot;&gt;Triggering a Manual Check&lt;/h3&gt;

&lt;p&gt;If you want to run Watchtower immediately to check for updates without waiting for the schedule:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nb&quot;&gt;cd&lt;/span&gt; /opt/watchtower
docker compose run &lt;span class=&quot;nt&quot;&gt;--rm&lt;/span&gt; watchtower &lt;span class=&quot;nt&quot;&gt;--run-once&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;This will start a temporary instance that runs a single check, outputs the results to your terminal, and then exits. The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;--rm&lt;/code&gt; flag ensures the temporary container is automatically deleted after it finishes, so there is no cleanup required.&lt;/p&gt;

&lt;h3 id=&quot;subscribe-to-notifications&quot;&gt;Subscribe to notifications&lt;/h3&gt;

&lt;p&gt;In ntfy (web or mobile app), subscribe to the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;watchtower&lt;/code&gt; topic to receive update notifications.&lt;/p&gt;

&lt;h3 id=&quot;optional-enable-auto-update-for-specific-containers&quot;&gt;Optional: Enable auto-update for specific containers&lt;/h3&gt;

&lt;p&gt;If you want to auto-update only certain containers, modify the Watchtower config:&lt;/p&gt;

&lt;div class=&quot;language-yaml highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;na&quot;&gt;environment&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
  &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;WATCHTOWER_LABEL_ENABLE=true&lt;/span&gt;  &lt;span class=&quot;c1&quot;&gt;# Only update labeled containers&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Then add labels to containers you trust to auto-update (in their docker-compose.yml):&lt;/p&gt;

&lt;div class=&quot;language-yaml highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;na&quot;&gt;services&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;ntfy&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;image&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;binwiederhier/ntfy:latest&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;labels&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
      &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;com.centurylinklabs.watchtower.enable=true&quot;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Recommended for auto-update:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;ntfy&lt;/li&gt;
  &lt;li&gt;Wallabag&lt;/li&gt;
  &lt;li&gt;Calibre-Web&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;NOT recommended for auto-update:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;Nextcloud (database migrations need testing)&lt;/li&gt;
  &lt;li&gt;Plex (library compatibility)&lt;/li&gt;
  &lt;li&gt;Immich (breaking changes common)&lt;/li&gt;
  &lt;li&gt;NPM (reverse proxy config changes)&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;manual-update-workflow&quot;&gt;Manual update workflow&lt;/h3&gt;

&lt;p&gt;When you receive a notification:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Check the container’s changelog/release notes&lt;/li&gt;
  &lt;li&gt;Test the update on LAN first&lt;/li&gt;
  &lt;li&gt;Update manually:
    &lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nb&quot;&gt;cd&lt;/span&gt; /opt/service-name
docker compose pull
docker compose up &lt;span class=&quot;nt&quot;&gt;-d&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;
  &lt;/li&gt;
  &lt;li&gt;Verify the service still works&lt;/li&gt;
  &lt;li&gt;Clean up old images:
    &lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;docker image prune &lt;span class=&quot;nt&quot;&gt;-a&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;h2 id=&quot;final-firewall-configuration&quot;&gt;Final Firewall Configuration&lt;/h2&gt;

&lt;p&gt;Since the current firewall rules are messy and contain duplicates, use this script to safely reset them. This method sets the default policy to ACCEPT first to ensure you don’t get locked out of SSH when flushing rules.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Important&lt;/strong&gt;: This script flushes ALL rules. It includes lines to restore access for SSH, Samba, Plex, and the Web UIs mentioned in this guide. It also restarts Docker to ensure Docker-managed rules (like WireGuard and NPM public ports) are correctly recreated.&lt;/p&gt;

&lt;p&gt;You can copy and paste the commands below, or save them to a file (e.g., &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;firewall.sh&lt;/code&gt;) and run it with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;sudo bash firewall.sh&lt;/code&gt;.&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;# 1. Set default policy to ACCEPT to prevent lockout during flush&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;iptables &lt;span class=&quot;nt&quot;&gt;-P&lt;/span&gt; INPUT ACCEPT
&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;iptables &lt;span class=&quot;nt&quot;&gt;-P&lt;/span&gt; FORWARD ACCEPT
&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;iptables &lt;span class=&quot;nt&quot;&gt;-P&lt;/span&gt; OUTPUT ACCEPT

&lt;span class=&quot;c&quot;&gt;# 2. Flush all existing rules and delete custom chains&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;iptables &lt;span class=&quot;nt&quot;&gt;-F&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;iptables &lt;span class=&quot;nt&quot;&gt;-X&lt;/span&gt;

&lt;span class=&quot;c&quot;&gt;# 3. Add base rules&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# Allow loopback&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;iptables &lt;span class=&quot;nt&quot;&gt;-A&lt;/span&gt; INPUT &lt;span class=&quot;nt&quot;&gt;-i&lt;/span&gt; lo &lt;span class=&quot;nt&quot;&gt;-j&lt;/span&gt; ACCEPT
&lt;span class=&quot;c&quot;&gt;# Allow established connections&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;iptables &lt;span class=&quot;nt&quot;&gt;-A&lt;/span&gt; INPUT &lt;span class=&quot;nt&quot;&gt;-m&lt;/span&gt; conntrack &lt;span class=&quot;nt&quot;&gt;--ctstate&lt;/span&gt; ESTABLISHED,RELATED &lt;span class=&quot;nt&quot;&gt;-j&lt;/span&gt; ACCEPT
&lt;span class=&quot;c&quot;&gt;# Allow Docker containers to communicate with host (Required for NPM -&amp;gt; Netdata)&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;iptables &lt;span class=&quot;nt&quot;&gt;-A&lt;/span&gt; INPUT &lt;span class=&quot;nt&quot;&gt;-i&lt;/span&gt; docker0 &lt;span class=&quot;nt&quot;&gt;-j&lt;/span&gt; ACCEPT
&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;iptables &lt;span class=&quot;nt&quot;&gt;-A&lt;/span&gt; INPUT &lt;span class=&quot;nt&quot;&gt;-i&lt;/span&gt; br+ &lt;span class=&quot;nt&quot;&gt;-j&lt;/span&gt; ACCEPT
&lt;span class=&quot;c&quot;&gt;# Allow SSH (LAN only)&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;iptables &lt;span class=&quot;nt&quot;&gt;-A&lt;/span&gt; INPUT &lt;span class=&quot;nt&quot;&gt;-i&lt;/span&gt; enp2s0 &lt;span class=&quot;nt&quot;&gt;-p&lt;/span&gt; tcp &lt;span class=&quot;nt&quot;&gt;--dport&lt;/span&gt; 22 &lt;span class=&quot;nt&quot;&gt;-j&lt;/span&gt; ACCEPT

&lt;span class=&quot;c&quot;&gt;# 4. Add LAN Services (enp2s0)&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# Samba (File Sharing)&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;iptables &lt;span class=&quot;nt&quot;&gt;-A&lt;/span&gt; INPUT &lt;span class=&quot;nt&quot;&gt;-i&lt;/span&gt; enp2s0 &lt;span class=&quot;nt&quot;&gt;-p&lt;/span&gt; udp &lt;span class=&quot;nt&quot;&gt;-m&lt;/span&gt; multiport &lt;span class=&quot;nt&quot;&gt;--dports&lt;/span&gt; 137,138 &lt;span class=&quot;nt&quot;&gt;-j&lt;/span&gt; ACCEPT
&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;iptables &lt;span class=&quot;nt&quot;&gt;-A&lt;/span&gt; INPUT &lt;span class=&quot;nt&quot;&gt;-i&lt;/span&gt; enp2s0 &lt;span class=&quot;nt&quot;&gt;-p&lt;/span&gt; tcp &lt;span class=&quot;nt&quot;&gt;-m&lt;/span&gt; multiport &lt;span class=&quot;nt&quot;&gt;--dports&lt;/span&gt; 139,445 &lt;span class=&quot;nt&quot;&gt;-j&lt;/span&gt; ACCEPT
&lt;span class=&quot;c&quot;&gt;# Plex (Media Server)&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;iptables &lt;span class=&quot;nt&quot;&gt;-A&lt;/span&gt; INPUT &lt;span class=&quot;nt&quot;&gt;-i&lt;/span&gt; enp2s0 &lt;span class=&quot;nt&quot;&gt;-p&lt;/span&gt; tcp &lt;span class=&quot;nt&quot;&gt;--dport&lt;/span&gt; 32400 &lt;span class=&quot;nt&quot;&gt;-j&lt;/span&gt; ACCEPT
&lt;span class=&quot;c&quot;&gt;# RustDesk (Remote Desktop)&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;iptables &lt;span class=&quot;nt&quot;&gt;-A&lt;/span&gt; INPUT &lt;span class=&quot;nt&quot;&gt;-i&lt;/span&gt; enp2s0 &lt;span class=&quot;nt&quot;&gt;-p&lt;/span&gt; tcp &lt;span class=&quot;nt&quot;&gt;-m&lt;/span&gt; multiport &lt;span class=&quot;nt&quot;&gt;--dports&lt;/span&gt; 21115,21116,21117,21118,21119 &lt;span class=&quot;nt&quot;&gt;-j&lt;/span&gt; ACCEPT
&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;iptables &lt;span class=&quot;nt&quot;&gt;-A&lt;/span&gt; INPUT &lt;span class=&quot;nt&quot;&gt;-i&lt;/span&gt; enp2s0 &lt;span class=&quot;nt&quot;&gt;-p&lt;/span&gt; udp &lt;span class=&quot;nt&quot;&gt;--dport&lt;/span&gt; 21116 &lt;span class=&quot;nt&quot;&gt;-j&lt;/span&gt; ACCEPT
&lt;span class=&quot;c&quot;&gt;# Web UIs (NPM:81, ntfy:8080, Nextcloud:8081, Wallabag:8082, WG:51821, Immich:2283, Calibre-Web:8083, Copyparty:3923, OpenSpeedTest:3000, Netdata:19999)&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;iptables &lt;span class=&quot;nt&quot;&gt;-A&lt;/span&gt; INPUT &lt;span class=&quot;nt&quot;&gt;-i&lt;/span&gt; enp2s0 &lt;span class=&quot;nt&quot;&gt;-p&lt;/span&gt; tcp &lt;span class=&quot;nt&quot;&gt;-m&lt;/span&gt; multiport &lt;span class=&quot;nt&quot;&gt;--dports&lt;/span&gt; 81,8080,8081,8082,51821,2283,8083,3923,3000,19999 &lt;span class=&quot;nt&quot;&gt;-j&lt;/span&gt; ACCEPT

&lt;span class=&quot;c&quot;&gt;# 5. Add External Services (eno1)&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# Plex (Remote Access)&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;iptables &lt;span class=&quot;nt&quot;&gt;-A&lt;/span&gt; INPUT &lt;span class=&quot;nt&quot;&gt;-i&lt;/span&gt; eno1 &lt;span class=&quot;nt&quot;&gt;-p&lt;/span&gt; tcp &lt;span class=&quot;nt&quot;&gt;--dport&lt;/span&gt; 32400 &lt;span class=&quot;nt&quot;&gt;-j&lt;/span&gt; ACCEPT
&lt;span class=&quot;c&quot;&gt;# RustDesk (Remote Access)&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;iptables &lt;span class=&quot;nt&quot;&gt;-A&lt;/span&gt; INPUT &lt;span class=&quot;nt&quot;&gt;-i&lt;/span&gt; eno1 &lt;span class=&quot;nt&quot;&gt;-p&lt;/span&gt; tcp &lt;span class=&quot;nt&quot;&gt;-m&lt;/span&gt; multiport &lt;span class=&quot;nt&quot;&gt;--dports&lt;/span&gt; 21115,21116,21117,21118,21119 &lt;span class=&quot;nt&quot;&gt;-j&lt;/span&gt; ACCEPT
&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;iptables &lt;span class=&quot;nt&quot;&gt;-A&lt;/span&gt; INPUT &lt;span class=&quot;nt&quot;&gt;-i&lt;/span&gt; eno1 &lt;span class=&quot;nt&quot;&gt;-p&lt;/span&gt; udp &lt;span class=&quot;nt&quot;&gt;--dport&lt;/span&gt; 21116 &lt;span class=&quot;nt&quot;&gt;-j&lt;/span&gt; ACCEPT

&lt;span class=&quot;c&quot;&gt;# 6. Restart Docker to recreate Docker chains and rules&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# This handles WireGuard (51820) and NPM (80/443) automatically&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;systemctl restart docker

&lt;span class=&quot;c&quot;&gt;# 7. Set default policy back to DROP&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;iptables &lt;span class=&quot;nt&quot;&gt;-P&lt;/span&gt; INPUT DROP

&lt;span class=&quot;c&quot;&gt;# 8. Save rules&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;netfilter-persistent save
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Note&lt;/strong&gt;: Since your server has a direct internet connection via &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;eno1&lt;/code&gt;, no router port forwarding is needed. The firewall rules above allow direct access from the internet.&lt;/p&gt;

&lt;h2 id=&quot;moving-docker-data-to-srv&quot;&gt;Moving Docker Data to /srv&lt;/h2&gt;

&lt;p&gt;If like me, you used Debian’s default “Server” partitioning scheme on a 1TB drive, your &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/var&lt;/code&gt; partition is small (22GB) and filling up (100% usage), while &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/srv&lt;/code&gt; has plenty of space (800GB+). Since Docker stores images and containers in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/var/lib/docker&lt;/code&gt; by default, we should move this to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/srv&lt;/code&gt;.&lt;/p&gt;

&lt;h3 id=&quot;1-stop-docker&quot;&gt;1. Stop Docker&lt;/h3&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;systemctl stop docker
&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;systemctl stop docker.socket
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;2-create-new-directory&quot;&gt;2. Create new directory&lt;/h3&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nb&quot;&gt;sudo mkdir&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-p&lt;/span&gt; /srv/docker
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;3-configure-docker-to-use-new-path&quot;&gt;3. Configure Docker to use new path&lt;/h3&gt;

&lt;p&gt;Create or edit the daemon config:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;vim /etc/docker/daemon.json
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Add the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;data-root&lt;/code&gt; configuration. If the file is empty, paste this:&lt;/p&gt;

&lt;div class=&quot;language-json highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
  &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;data-root&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;/srv/docker&quot;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;If the file already exists, just add the line inside the brackets (don’t forget the comma if needed).&lt;/p&gt;

&lt;h3 id=&quot;4-move-existing-data&quot;&gt;4. Move existing data&lt;/h3&gt;

&lt;p&gt;Copy all existing Docker data to the new location:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;rsync &lt;span class=&quot;nt&quot;&gt;-aqxP&lt;/span&gt; /var/lib/docker/ /srv/docker/
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;5-start-docker&quot;&gt;5. Start Docker&lt;/h3&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;systemctl start docker
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;6-verify-and-clean-up&quot;&gt;6. Verify and clean up&lt;/h3&gt;

&lt;p&gt;Check that Docker is using the new path:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;docker info | &lt;span class=&quot;nb&quot;&gt;grep&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;Docker Root Dir&quot;&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# Should output: Docker Root Dir: /srv/docker&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Check that your containers are running:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;docker ps
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Only after verifying everything works&lt;/strong&gt;, remove the old data to free up space in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/var&lt;/code&gt;:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nb&quot;&gt;sudo rm&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-rf&lt;/span&gt; /var/lib/docker
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;verifying-system-health&quot;&gt;Verifying System Health&lt;/h2&gt;

&lt;p&gt;If the system freezes or reboots, use these commands to verify everything is back up and running correctly.&lt;/p&gt;

&lt;h3 id=&quot;check-docker-containers&quot;&gt;Check Docker Containers&lt;/h3&gt;

&lt;p&gt;Ensure all containers are running and healthy:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;docker ps &lt;span class=&quot;nt&quot;&gt;--format&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;table &lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\t\t&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;monitor-resource-usage&quot;&gt;Monitor Resource Usage&lt;/h3&gt;

&lt;p&gt;Check if any container (specifically &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;immich_machine_learning&lt;/code&gt;) is consuming excessive resources:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;docker stats
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;If &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;immich_machine_learning&lt;/code&gt; is using 100% of multiple cores for extended periods, consider applying the resource limits mentioned in the Immich section.&lt;/p&gt;

&lt;h3 id=&quot;check-system-logs&quot;&gt;Check System Logs&lt;/h3&gt;

&lt;p&gt;Look for any system-level errors that might have occurred during the freeze:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;journalctl &lt;span class=&quot;nt&quot;&gt;-p&lt;/span&gt; 3 &lt;span class=&quot;nt&quot;&gt;-xb&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;verify-network--firewall&quot;&gt;Verify Network &amp;amp; Firewall&lt;/h3&gt;

&lt;p&gt;Ensure network interfaces are up and firewall rules are loaded:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;networkctl status
&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;iptables &lt;span class=&quot;nt&quot;&gt;-L&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-v&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-n&lt;/span&gt; | &lt;span class=&quot;nb&quot;&gt;head&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

</description>
        <pubDate>Sat, 22 Nov 2025 00:00:00 +0000</pubDate>
        <link>https://kitroed.com/2025/11/22/home-server-setup-notes.html</link>
        <guid isPermaLink="true">https://kitroed.com/2025/11/22/home-server-setup-notes.html</guid>
        
        
      </item>
    
      <item>
        <title>Arch Linux WiFi Hotspot Notes [Arch Linux]</title>
        <description>&lt;p&gt;Wanting to set up a WiFi hotspot on Arch Linux that used the 5 GHz band, it was necessary to set the country code for the wireless interface. This is required for regulatory compliance and to access all available channels in your region.&lt;/p&gt;

&lt;p&gt;The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;iw&lt;/code&gt; command can be used to check the current setting:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;iw reg get
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;iw&lt;/code&gt; can be installed by running the following command:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;pacman &lt;span class=&quot;nt&quot;&gt;-S&lt;/span&gt; iw
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;In Arch Linux, to permanently set the domain, install wireless-regdb if not already installed:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;pacman &lt;span class=&quot;nt&quot;&gt;-S&lt;/span&gt; wireless-regdb
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Then create or edit the file &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/etc/conf.d/wireless-regdom&lt;/code&gt; to include the desired country code, for example for the United States:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nv&quot;&gt;WIRELESS_REGDOM&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;US&quot;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;After setting the country code, restart the system.&lt;/p&gt;

&lt;p&gt;To verify the change, use the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;iw reg get&lt;/code&gt; command again to ensure the country code is correctly set.&lt;/p&gt;

&lt;p&gt;To find the available channels for 5 GHz, run:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;iw list
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Refer to the output under “Frequencies” in the “Band 2” section (Band 1 is 2.4 GHz, Band 2 is 5 GHz).&lt;/p&gt;

&lt;p&gt;Once you’ve identified an available channel, create the hotspot with:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;nmcli dev wifi hotspot ifname wlp6s0 ssid my-hotspot password &lt;span class=&quot;s2&quot;&gt;&quot;mypassword&quot;&lt;/span&gt; band a channel 36
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;band a&lt;/code&gt; specifies the 5 GHz band, and channel &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;36&lt;/code&gt; is one of the available channels in that band.&lt;/p&gt;

&lt;p&gt;Replace &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;wlp6s0&lt;/code&gt; with the appropriate wireless interface name, which can be found using the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ip link&lt;/code&gt; command.
Make sure to replace &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&quot;mypassword&quot;&lt;/code&gt; with a secure password of your choice.&lt;/p&gt;

&lt;p&gt;To list previously created connections, use:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;nmcli connection show
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;To remove a hotspot connection when it’s no longer needed, use the delete command with the connection name (usually the SSID):&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;nmcli connection delete &lt;span class=&quot;s2&quot;&gt;&quot;my-hotspot&quot;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
</description>
        <pubDate>Thu, 13 Nov 2025 00:00:00 +0000</pubDate>
        <link>https://kitroed.com/2025/11/13/arch-linux-wifi-hotspot-notes.html</link>
        <guid isPermaLink="true">https://kitroed.com/2025/11/13/arch-linux-wifi-hotspot-notes.html</guid>
        
        
      </item>
    
      <item>
        <title>Start Steam minimized [Linux]</title>
        <description>&lt;p&gt;Auto start paths:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;/usr/share/applications/ 
/usr/local/share/applications/
~/.local/share/applications/
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;In KDE Plasma, go to System Settings &amp;gt; Startup and Shutdown &amp;gt; Autostart, and add an entry for Steam. In the application menu, use &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-silent %U&lt;/code&gt; as arguments. (Note, it’s &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-silent&lt;/code&gt; and not &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;--silent&lt;/code&gt;).&lt;/p&gt;
</description>
        <pubDate>Sun, 09 Jun 2024 00:00:00 +0000</pubDate>
        <link>https://kitroed.com/2024/06/09/start-steam-minimzed.html</link>
        <guid isPermaLink="true">https://kitroed.com/2024/06/09/start-steam-minimzed.html</guid>
        
        
      </item>
    
      <item>
        <title>Uninstall Windows Web Experience Pack (Windows 11) [powershell]</title>
        <description>&lt;p&gt;The reintroduced Windows Widget Panel and shortcut (&lt;kbd&gt;Win&lt;/kbd&gt; + W) can be completely disabled and removed from Windows 11 using the following command in PowerShell.&lt;/p&gt;

&lt;div class=&quot;language-powershell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;winget&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;uninstall&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;Windows Web Experience Pack&quot;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
</description>
        <pubDate>Mon, 25 Sep 2023 00:00:00 +0000</pubDate>
        <link>https://kitroed.com/2023/09/25/uninstall-windows-web-experience-pack.html</link>
        <guid isPermaLink="true">https://kitroed.com/2023/09/25/uninstall-windows-web-experience-pack.html</guid>
        
        
      </item>
    
      <item>
        <title>Keyboard shortcuts in Windows [Windows]</title>
        <description>&lt;h1 id=&quot;keyboard-shortcuts-in-windows&quot;&gt;Keyboard shortcuts in Windows&lt;/h1&gt;

&lt;h2 id=&quot;copy-paste-and-other-general-keyboard-shortcuts&quot;&gt;Copy, paste, and other general keyboard shortcuts&lt;/h2&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;Press this key&lt;/th&gt;
      &lt;th&gt;To do this&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;kbd&gt;Ctrl&lt;/kbd&gt; + X&lt;/td&gt;
      &lt;td&gt;Cut the selected item.&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;kbd&gt;Ctrl&lt;/kbd&gt; + C (or &lt;kbd&gt;Ctrl&lt;/kbd&gt; + &lt;kbd&gt;Insert&lt;/kbd&gt;)&lt;/td&gt;
      &lt;td&gt;Copy the selected item.&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;kbd&gt;Ctrl&lt;/kbd&gt; + V (or &lt;kbd&gt;Shift&lt;/kbd&gt; + &lt;kbd&gt;Insert&lt;/kbd&gt;)&lt;/td&gt;
      &lt;td&gt;Paste the selected item.&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;kbd&gt;Ctrl&lt;/kbd&gt; + Z&lt;/td&gt;
      &lt;td&gt;Undo an action.&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;kbd&gt;Alt&lt;/kbd&gt; + &lt;kbd&gt;Tab&lt;/kbd&gt;&lt;/td&gt;
      &lt;td&gt;Switch between open apps.&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;kbd&gt;Alt&lt;/kbd&gt; + &lt;kbd&gt;F4&lt;/kbd&gt;&lt;/td&gt;
      &lt;td&gt;Close the active item, or exit the active app.&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;kbd&gt;Win&lt;/kbd&gt; + L&lt;/td&gt;
      &lt;td&gt;Lock your PC.&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;kbd&gt;Win&lt;/kbd&gt; + D&lt;/td&gt;
      &lt;td&gt;Display and hide the desktop.&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;kbd&gt;F2&lt;/kbd&gt;&lt;/td&gt;
      &lt;td&gt;Rename the selected item.&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;kbd&gt;F3&lt;/kbd&gt;&lt;/td&gt;
      &lt;td&gt;Search for a file or folder in File Explorer.&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;kbd&gt;F4&lt;/kbd&gt;&lt;/td&gt;
      &lt;td&gt;Display the address bar list in File Explorer.&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;kbd&gt;F5&lt;/kbd&gt;&lt;/td&gt;
      &lt;td&gt;Refresh the active window.&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;kbd&gt;F6&lt;/kbd&gt;&lt;/td&gt;
      &lt;td&gt;Cycle through screen elements in a window or on the desktop.&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;kbd&gt;F10&lt;/kbd&gt;&lt;/td&gt;
      &lt;td&gt;Activate the Menu bar in the active app.&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;kbd&gt;Alt&lt;/kbd&gt; + A&lt;/td&gt;
      &lt;td&gt;Set focus to the first icon in the Suggested actions menu.&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;kbd&gt;Alt&lt;/kbd&gt; + &lt;kbd&gt;F8&lt;/kbd&gt;&lt;/td&gt;
      &lt;td&gt;Show your password on the sign-in screen.&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;kbd&gt;Alt&lt;/kbd&gt; + &lt;kbd&gt;Esc&lt;/kbd&gt;&lt;/td&gt;
      &lt;td&gt;Cycle through items in the order in which they were opened.&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;kbd&gt;Alt&lt;/kbd&gt; + underlined letter&lt;/td&gt;
      &lt;td&gt;Perform the command for that letter.&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;kbd&gt;Alt&lt;/kbd&gt; + &lt;kbd&gt;Enter&lt;/kbd&gt;&lt;/td&gt;
      &lt;td&gt;Display properties for the selected item.&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;kbd&gt;Alt&lt;/kbd&gt; + &lt;kbd&gt;Spacebar&lt;/kbd&gt;&lt;/td&gt;
      &lt;td&gt;Open the shortcut menu for the active window.&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;kbd&gt;Alt&lt;/kbd&gt; + Left arrow&lt;/td&gt;
      &lt;td&gt;Go back.&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;kbd&gt;Alt&lt;/kbd&gt; + Right arrow&lt;/td&gt;
      &lt;td&gt;Go forward.&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;kbd&gt;Alt&lt;/kbd&gt; + Page Up&lt;/td&gt;
      &lt;td&gt;Move up one screen.&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;kbd&gt;Alt&lt;/kbd&gt; + Page Down&lt;/td&gt;
      &lt;td&gt;Move down one screen.&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;kbd&gt;Ctrl&lt;/kbd&gt; + &lt;kbd&gt;F4&lt;/kbd&gt;&lt;/td&gt;
      &lt;td&gt;Close the active document (in apps that are full-screen and let you have multiple documents open at the same time).&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;kbd&gt;Ctrl&lt;/kbd&gt; + A&lt;/td&gt;
      &lt;td&gt;Select all items in a document or window.&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;kbd&gt;Ctrl&lt;/kbd&gt; + D (or Delete)&lt;/td&gt;
      &lt;td&gt;Delete the selected item and move it to the Recycle Bin.&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;kbd&gt;Ctrl&lt;/kbd&gt; + E&lt;/td&gt;
      &lt;td&gt;Open Search (in most apps).&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;kbd&gt;Ctrl&lt;/kbd&gt; + R (or &lt;kbd&gt;F5&lt;/kbd&gt;)&lt;/td&gt;
      &lt;td&gt;Refresh the active window.&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;kbd&gt;Ctrl&lt;/kbd&gt; + Y&lt;/td&gt;
      &lt;td&gt;Redo an action.&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;kbd&gt;Ctrl&lt;/kbd&gt; + Right arrow&lt;/td&gt;
      &lt;td&gt;Move the cursor to the beginning of the next word.&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;kbd&gt;Ctrl&lt;/kbd&gt; + Left arrow&lt;/td&gt;
      &lt;td&gt;Move the cursor to the beginning of the previous word.&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;kbd&gt;Ctrl&lt;/kbd&gt; + Down arrow&lt;/td&gt;
      &lt;td&gt;Move the cursor to the beginning of the next paragraph.&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;kbd&gt;Ctrl&lt;/kbd&gt; + Up arrow&lt;/td&gt;
      &lt;td&gt;Move the cursor to the beginning of the previous paragraph.&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;kbd&gt;Ctrl&lt;/kbd&gt; + &lt;kbd&gt;Alt&lt;/kbd&gt; + &lt;kbd&gt;Tab&lt;/kbd&gt;&lt;/td&gt;
      &lt;td&gt;Use the arrow keys to switch between all open apps.&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;kbd&gt;Alt&lt;/kbd&gt; + &lt;kbd&gt;Shift&lt;/kbd&gt; + arrow keys&lt;/td&gt;
      &lt;td&gt;When a group or tile is in focus on the Start menu, move it in the direction specified.&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;kbd&gt;Ctrl&lt;/kbd&gt; + &lt;kbd&gt;Shift&lt;/kbd&gt; + arrow keys&lt;/td&gt;
      &lt;td&gt;When a tile is in focus on the Start menu, move it into another tile to create a folder.&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;kbd&gt;Ctrl&lt;/kbd&gt; + arrow keys&lt;/td&gt;
      &lt;td&gt;Resize the Start menu when it’s open.&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;kbd&gt;Ctrl&lt;/kbd&gt; + arrow key (to move to an item) + &lt;kbd&gt;Spacebar&lt;/kbd&gt;&lt;/td&gt;
      &lt;td&gt;Select multiple individual items in a window or on the desktop.&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;kbd&gt;Ctrl&lt;/kbd&gt; + &lt;kbd&gt;Shift&lt;/kbd&gt; with an arrow key&lt;/td&gt;
      &lt;td&gt;Select a block of text.&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;kbd&gt;Ctrl&lt;/kbd&gt; + &lt;kbd&gt;Esc&lt;/kbd&gt;&lt;/td&gt;
      &lt;td&gt;Open Start.&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;kbd&gt;Ctrl&lt;/kbd&gt; + &lt;kbd&gt;Shift&lt;/kbd&gt; + &lt;kbd&gt;Esc&lt;/kbd&gt;&lt;/td&gt;
      &lt;td&gt;Open Task Manager.&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;kbd&gt;Ctrl&lt;/kbd&gt; + &lt;kbd&gt;Shift&lt;/kbd&gt;&lt;/td&gt;
      &lt;td&gt;Switch the keyboard layout when multiple keyboard layouts are available.&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;kbd&gt;Ctrl&lt;/kbd&gt; + &lt;kbd&gt;Spacebar&lt;/kbd&gt;&lt;/td&gt;
      &lt;td&gt;Turn the Chinese input method editor (IME) on or off.&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;kbd&gt;Shift&lt;/kbd&gt; + &lt;kbd&gt;F10&lt;/kbd&gt;&lt;/td&gt;
      &lt;td&gt;Display the shortcut menu for the selected item.&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;kbd&gt;Shift&lt;/kbd&gt; with any arrow key&lt;/td&gt;
      &lt;td&gt;Select more than one item in a window or on the desktop, or select text in a document.&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;kbd&gt;Shift&lt;/kbd&gt; + Delete&lt;/td&gt;
      &lt;td&gt;Delete the selected item without moving it to the Recycle Bin first.&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Right arrow&lt;/td&gt;
      &lt;td&gt;Open the next menu to the right, or open a submenu.&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Left arrow&lt;/td&gt;
      &lt;td&gt;Open the next menu to the left, or close a submenu.&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;kbd&gt;Esc&lt;/kbd&gt;&lt;/td&gt;
      &lt;td&gt;Stop or leave the current task.&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;kbd&gt;PrtScn&lt;/kbd&gt;&lt;/td&gt;
      &lt;td&gt;Take a screenshot of your whole screen and copy it to the clipboard. (Note: You can change this shortcut so it also opens screen snipping, which lets you edit your screenshot. Select Start &amp;gt; Settings &amp;gt; Accessibility &amp;gt; Keyboard , and set Use the Print Screen button to open screen snipping to On.)&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;h2 id=&quot;windows-logo-key-keyboard-shortcuts&quot;&gt;Windows logo key keyboard shortcuts&lt;/h2&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;Press this key&lt;/th&gt;
      &lt;th&gt;To do this&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;kbd&gt;Win&lt;/kbd&gt;&lt;/td&gt;
      &lt;td&gt;Open or close Start.&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;kbd&gt;Win&lt;/kbd&gt; + A&lt;/td&gt;
      &lt;td&gt;Open Quick Settings. Updated in Windows 11.&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;kbd&gt;Win&lt;/kbd&gt; + B&lt;/td&gt;
      &lt;td&gt;Set focus to the first icon in the Taskbar corner.&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;kbd&gt;Win&lt;/kbd&gt; + C&lt;/td&gt;
      &lt;td&gt;Open Chat from Microsoft Teams. Updated in Windows 11.&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;kbd&gt;Win&lt;/kbd&gt; + &lt;kbd&gt;Shift&lt;/kbd&gt; + C&lt;/td&gt;
      &lt;td&gt;Open the charms menu.&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;kbd&gt;Win&lt;/kbd&gt; + &lt;kbd&gt;Ctrl&lt;/kbd&gt; + C&lt;/td&gt;
      &lt;td&gt;Turn on color filters (enable this shortcut first in Color Filter settings).&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;kbd&gt;Win&lt;/kbd&gt; + D&lt;/td&gt;
      &lt;td&gt;Display and hide the desktop.&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;kbd&gt;Win&lt;/kbd&gt; + E&lt;/td&gt;
      &lt;td&gt;Open File Explorer.&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;kbd&gt;Win&lt;/kbd&gt; + F&lt;/td&gt;
      &lt;td&gt;Open Feedback Hub and take a screenshot.&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;kbd&gt;Win&lt;/kbd&gt; + G&lt;/td&gt;
      &lt;td&gt;Open Xbox Game Bar when a game is open.&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;kbd&gt;Win&lt;/kbd&gt; + &lt;kbd&gt;Alt&lt;/kbd&gt; + B&lt;/td&gt;
      &lt;td&gt;Turn HDR on or off.&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;kbd&gt;Win&lt;/kbd&gt; + H&lt;/td&gt;
      &lt;td&gt;Launch voice typing. Updated in Windows 11.&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;kbd&gt;Win&lt;/kbd&gt; + I&lt;/td&gt;
      &lt;td&gt;Open Settings.&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;kbd&gt;Win&lt;/kbd&gt; + J&lt;/td&gt;
      &lt;td&gt;Set focus to a Windows tip when one is available. (When a Windows tip appears, bring focus to the Tip.  Pressing the keyboard shortcuts again to bring focus to the element on the screen to which the Windows tip is anchored.)&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;kbd&gt;Win&lt;/kbd&gt; + K&lt;/td&gt;
      &lt;td&gt;Open Cast from Quick Settings. Updated in Windows 11.&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;kbd&gt;Win&lt;/kbd&gt; + &lt;kbd&gt;Alt&lt;/kbd&gt; + K&lt;/td&gt;
      &lt;td&gt;Toggle microphone mute in apps that support Call Mute. Available starting in Windows 11, version 22H2.&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;kbd&gt;Win&lt;/kbd&gt; + L&lt;/td&gt;
      &lt;td&gt;Lock your PC or switch accounts.&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;kbd&gt;Win&lt;/kbd&gt; + M&lt;/td&gt;
      &lt;td&gt;Minimize all windows.&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;kbd&gt;Win&lt;/kbd&gt; + &lt;kbd&gt;Shift&lt;/kbd&gt; + M&lt;/td&gt;
      &lt;td&gt;Restore minimized windows on the desktop.&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;kbd&gt;Win&lt;/kbd&gt; + N&lt;/td&gt;
      &lt;td&gt;Open notification center and calendar. Updated in Windows 11.&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;kbd&gt;Win&lt;/kbd&gt; + O&lt;/td&gt;
      &lt;td&gt;Lock device orientation.&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;kbd&gt;Win&lt;/kbd&gt; + P&lt;/td&gt;
      &lt;td&gt;Choose a presentation display mode.&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;kbd&gt;Win&lt;/kbd&gt; + &lt;kbd&gt;Ctrl&lt;/kbd&gt; + Q&lt;/td&gt;
      &lt;td&gt;Open Quick Assist.&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;kbd&gt;Win&lt;/kbd&gt; + R&lt;/td&gt;
      &lt;td&gt;Open the Run dialog box.&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;kbd&gt;Win&lt;/kbd&gt; + &lt;kbd&gt;Alt&lt;/kbd&gt; + R&lt;/td&gt;
      &lt;td&gt;Record video of game window in focus (using Xbox Game Bar).&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;kbd&gt;Win&lt;/kbd&gt; + S&lt;/td&gt;
      &lt;td&gt;Open search.&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;kbd&gt;Win&lt;/kbd&gt; + &lt;kbd&gt;Shift&lt;/kbd&gt; + S&lt;/td&gt;
      &lt;td&gt;Take a screenshot of part of your screen.&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;kbd&gt;Win&lt;/kbd&gt; + T&lt;/td&gt;
      &lt;td&gt;Cycle through apps on the taskbar.&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;kbd&gt;Win&lt;/kbd&gt; + U&lt;/td&gt;
      &lt;td&gt;Open Accessibility Settings.&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;kbd&gt;Win&lt;/kbd&gt; + V&lt;/td&gt;
      &lt;td&gt;Open the clipboard history.&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;kbd&gt;Win&lt;/kbd&gt; + &lt;kbd&gt;Shift&lt;/kbd&gt; + V&lt;/td&gt;
      &lt;td&gt;Set focus to a notification.&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;kbd&gt;Win&lt;/kbd&gt; + W&lt;/td&gt;
      &lt;td&gt;Open Widgets. Updated in Windows 11.&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;kbd&gt;Win&lt;/kbd&gt; + X&lt;/td&gt;
      &lt;td&gt;Open the Quick Link menu.&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;kbd&gt;Win&lt;/kbd&gt; + Y&lt;/td&gt;
      &lt;td&gt;Switch input between Windows Mixed Reality and your desktop.&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;kbd&gt;Win&lt;/kbd&gt; + Z&lt;/td&gt;
      &lt;td&gt;Open the snap layouts. Updated in Windows 11.&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;kbd&gt;Win&lt;/kbd&gt; + period (.) or semicolon (;)&lt;/td&gt;
      &lt;td&gt;Open emoji panel.&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;kbd&gt;Win&lt;/kbd&gt; + comma (,)&lt;/td&gt;
      &lt;td&gt;Temporarily peek at the desktop.&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;kbd&gt;Win&lt;/kbd&gt; + &lt;kbd&gt;Pause&lt;/kbd&gt;&lt;/td&gt;
      &lt;td&gt;Opens Start &amp;gt; Settings &amp;gt; System &amp;gt; About .&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;kbd&gt;Win&lt;/kbd&gt; + &lt;kbd&gt;Ctrl&lt;/kbd&gt; + F&lt;/td&gt;
      &lt;td&gt;Search for PCs (if you’re on a network).&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;kbd&gt;Win&lt;/kbd&gt; + number&lt;/td&gt;
      &lt;td&gt;Open the desktop and start the app pinned to the taskbar in the position indicated by the number. If the app is already running, switch to that app.&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;kbd&gt;Win&lt;/kbd&gt; + &lt;kbd&gt;Shift&lt;/kbd&gt; + number&lt;/td&gt;
      &lt;td&gt;Open the desktop and start a new instance of the app pinned to the taskbar in the position indicated by the number.&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;kbd&gt;Win&lt;/kbd&gt; + &lt;kbd&gt;Ctrl&lt;/kbd&gt; + number&lt;/td&gt;
      &lt;td&gt;Open the desktop and switch to the last active window of the app pinned to the taskbar in the position indicated by the number.&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;kbd&gt;Win&lt;/kbd&gt; + &lt;kbd&gt;Alt&lt;/kbd&gt; + number&lt;/td&gt;
      &lt;td&gt;Open the desktop and open the Jump List for the app pinned to the taskbar in the position indicated by the number.&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;kbd&gt;Win&lt;/kbd&gt; + &lt;kbd&gt;Ctrl&lt;/kbd&gt; + &lt;kbd&gt;Shift&lt;/kbd&gt; + number&lt;/td&gt;
      &lt;td&gt;Open the desktop and open a new instance of the app located at the given position on the taskbar as an administrator.&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;kbd&gt;Win&lt;/kbd&gt; + &lt;kbd&gt;Tab&lt;/kbd&gt;&lt;/td&gt;
      &lt;td&gt;Open Task view.&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;kbd&gt;Win&lt;/kbd&gt; + Up arrow&lt;/td&gt;
      &lt;td&gt;Maximize the window.&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;kbd&gt;Win&lt;/kbd&gt; + &lt;kbd&gt;Alt&lt;/kbd&gt; + Up arrow&lt;/td&gt;
      &lt;td&gt;Snap window in focus to top half of screen. New with Windows 11.&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;kbd&gt;Win&lt;/kbd&gt; + Down arrow&lt;/td&gt;
      &lt;td&gt;Remove current app from screen or minimize the desktop window.&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;kbd&gt;Win&lt;/kbd&gt; + &lt;kbd&gt;Alt&lt;/kbd&gt; + Down arrow&lt;/td&gt;
      &lt;td&gt;Snap window in focus to bottom half of screen. New with Windows 11.&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;kbd&gt;Win&lt;/kbd&gt; + Left arrow&lt;/td&gt;
      &lt;td&gt;Maximize the app or desktop window to the left side of the screen.&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;kbd&gt;Win&lt;/kbd&gt; + Right arrow&lt;/td&gt;
      &lt;td&gt;Maximize the app or desktop window to the right side of the screen.&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;kbd&gt;Win&lt;/kbd&gt; + &lt;kbd&gt;Home&lt;/kbd&gt;&lt;/td&gt;
      &lt;td&gt;Minimize all except the active desktop window (restores all windows on second stroke).&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;kbd&gt;Win&lt;/kbd&gt; + &lt;kbd&gt;Shift&lt;/kbd&gt; + Up arrow&lt;/td&gt;
      &lt;td&gt;Stretch the desktop window to the top and bottom of the screen.&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;kbd&gt;Win&lt;/kbd&gt; + &lt;kbd&gt;Shift&lt;/kbd&gt; + Down arrow&lt;/td&gt;
      &lt;td&gt;Restore/minimize active desktop windows vertically, maintaining width.&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;kbd&gt;Win&lt;/kbd&gt; + &lt;kbd&gt;Shift&lt;/kbd&gt; + Left arrow or Right arrow&lt;/td&gt;
      &lt;td&gt;Move an app or window in the desktop from one monitor to another.&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;kbd&gt;Win&lt;/kbd&gt; + &lt;kbd&gt;Shift&lt;/kbd&gt; + &lt;kbd&gt;Spacebar&lt;/kbd&gt;&lt;/td&gt;
      &lt;td&gt;Cycle backwards through language and keyboard layout.&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;kbd&gt;Win&lt;/kbd&gt;+ &lt;kbd&gt;Spacebar&lt;/kbd&gt;&lt;/td&gt;
      &lt;td&gt;Switch input language and keyboard layout.&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;kbd&gt;Win&lt;/kbd&gt;+ &lt;kbd&gt;Ctrl&lt;/kbd&gt; + &lt;kbd&gt;Spacebar&lt;/kbd&gt;&lt;/td&gt;
      &lt;td&gt;Change to a previously selected input.&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;kbd&gt;Win&lt;/kbd&gt; + &lt;kbd&gt;Ctrl&lt;/kbd&gt; + &lt;kbd&gt;Enter&lt;/kbd&gt;&lt;/td&gt;
      &lt;td&gt;Turn on Narrator.&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;kbd&gt;Win&lt;/kbd&gt; + Plus (+)&lt;/td&gt;
      &lt;td&gt;Open Magnifier and zoom in.&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;kbd&gt;Win&lt;/kbd&gt; + Minus (-)&lt;/td&gt;
      &lt;td&gt;Zoom out in Magnifier.&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;kbd&gt;Win&lt;/kbd&gt; + &lt;kbd&gt;Esc&lt;/kbd&gt;&lt;/td&gt;
      &lt;td&gt;Close Magnifier.&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;kbd&gt;Win&lt;/kbd&gt; + forward slash (/)&lt;/td&gt;
      &lt;td&gt;Begin IME reconversion.&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;kbd&gt;Win&lt;/kbd&gt; + &lt;kbd&gt;Ctrl&lt;/kbd&gt; + &lt;kbd&gt;Shift&lt;/kbd&gt; + B&lt;/td&gt;
      &lt;td&gt;Wake PC from blank or black screen.&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;kbd&gt;Win&lt;/kbd&gt; + &lt;kbd&gt;PrtScn&lt;/kbd&gt;&lt;/td&gt;
      &lt;td&gt;Save full screen screenshot to file.&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;kbd&gt;Win&lt;/kbd&gt; + &lt;kbd&gt;Alt&lt;/kbd&gt; + &lt;kbd&gt;PrtScn&lt;/kbd&gt;&lt;/td&gt;
      &lt;td&gt;Save screenshot of game window in focus to file (using Xbox Game Bar).&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;kbd&gt;Win&lt;/kbd&gt; + &lt;kbd&gt;Alt&lt;/kbd&gt; + &lt;kbd&gt;Enter&lt;/kbd&gt; (on taskbar item focus)&lt;/td&gt;
      &lt;td&gt;Open taskbar settings.&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;h2 id=&quot;command-prompt-keyboard-shortcuts&quot;&gt;Command Prompt keyboard shortcuts&lt;/h2&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;Press this key&lt;/th&gt;
      &lt;th&gt;To do this&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;kbd&gt;Ctrl&lt;/kbd&gt; + C (or &lt;kbd&gt;Ctrl&lt;/kbd&gt; + &lt;kbd&gt;Insert&lt;/kbd&gt;)&lt;/td&gt;
      &lt;td&gt;Copy the selected text.&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;kbd&gt;Ctrl&lt;/kbd&gt; + V (or &lt;kbd&gt;Shift&lt;/kbd&gt; + &lt;kbd&gt;Insert&lt;/kbd&gt;)&lt;/td&gt;
      &lt;td&gt;Paste the selected text.&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;kbd&gt;Ctrl&lt;/kbd&gt; + M&lt;/td&gt;
      &lt;td&gt;&lt;kbd&gt;Enter&lt;/kbd&gt; Mark mode.&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;kbd&gt;Alt&lt;/kbd&gt; + selection key&lt;/td&gt;
      &lt;td&gt;Begin selection in block mode.&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Arrow keys&lt;/td&gt;
      &lt;td&gt;Move the cursor in the direction specified.&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Page up&lt;/td&gt;
      &lt;td&gt;Move the cursor by one page up.&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Page down&lt;/td&gt;
      &lt;td&gt;Move the cursor by one page down.&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;kbd&gt;Ctrl&lt;/kbd&gt; + &lt;kbd&gt;Home&lt;/kbd&gt; (Mark mode)&lt;/td&gt;
      &lt;td&gt;Move the cursor to the beginning of the buffer.&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;kbd&gt;Ctrl&lt;/kbd&gt; + &lt;kbd&gt;End&lt;/kbd&gt; (Mark mode)&lt;/td&gt;
      &lt;td&gt;Move the cursor to the end of the buffer.&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;kbd&gt;Ctrl&lt;/kbd&gt; + Up arrow&lt;/td&gt;
      &lt;td&gt;Move up one line in the output history.&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;kbd&gt;Ctrl&lt;/kbd&gt; + Down arrow&lt;/td&gt;
      &lt;td&gt;Move down one line in the output history.&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;kbd&gt;Ctrl&lt;/kbd&gt; + &lt;kbd&gt;Home&lt;/kbd&gt; (History navigation)&lt;/td&gt;
      &lt;td&gt;If the command line is empty, move the viewport to the top of the buffer. Otherwise, delete all the characters to the left of the cursor in the command line.&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;kbd&gt;Ctrl&lt;/kbd&gt; + &lt;kbd&gt;End&lt;/kbd&gt; (History navigation)&lt;/td&gt;
      &lt;td&gt;If the command line is empty, move the viewport to the command line. Otherwise, delete all the characters to the right of the cursor in the command line.&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;h2 id=&quot;dialog-box-keyboard-shortcuts&quot;&gt;Dialog box keyboard shortcuts&lt;/h2&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;Press this key&lt;/th&gt;
      &lt;th&gt;To do this&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;kbd&gt;F4&lt;/kbd&gt;&lt;/td&gt;
      &lt;td&gt;Display the items in the active list.&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;kbd&gt;Ctrl&lt;/kbd&gt; + &lt;kbd&gt;Tab&lt;/kbd&gt;&lt;/td&gt;
      &lt;td&gt;Move forward through tabs.&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;kbd&gt;Ctrl&lt;/kbd&gt; + &lt;kbd&gt;Shift&lt;/kbd&gt; + &lt;kbd&gt;Tab&lt;/kbd&gt;&lt;/td&gt;
      &lt;td&gt;Move back through tabs.&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;kbd&gt;Ctrl&lt;/kbd&gt; + 1, 2, 3,…&lt;/td&gt;
      &lt;td&gt;Move to that tab number.&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;kbd&gt;Tab&lt;/kbd&gt;&lt;/td&gt;
      &lt;td&gt;Move forward through options.&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;kbd&gt;Shift&lt;/kbd&gt; + &lt;kbd&gt;Tab&lt;/kbd&gt;&lt;/td&gt;
      &lt;td&gt;Move back through options.&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;kbd&gt;Alt&lt;/kbd&gt; + underlined letter&lt;/td&gt;
      &lt;td&gt;Perform the command (or select the option) that is used with that letter.&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;kbd&gt;Spacebar&lt;/kbd&gt;&lt;/td&gt;
      &lt;td&gt;Select or clear the check box if the active option is a check box.&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;kbd&gt;Backspace&lt;/kbd&gt;&lt;/td&gt;
      &lt;td&gt;Open a folder one level up if a folder is selected in the Save As or Open dialog box.&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Arrow keys&lt;/td&gt;
      &lt;td&gt;Select a button if the active option is a group of option buttons.&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;h2 id=&quot;file-explorer-keyboard-shortcuts&quot;&gt;File Explorer keyboard shortcuts&lt;/h2&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;Press this key&lt;/th&gt;
      &lt;th&gt;To do this&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;kbd&gt;Alt&lt;/kbd&gt; + D&lt;/td&gt;
      &lt;td&gt;Select the address bar.&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;kbd&gt;Ctrl&lt;/kbd&gt; + E&lt;/td&gt;
      &lt;td&gt;Select the search box.&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;kbd&gt;Ctrl&lt;/kbd&gt; + F&lt;/td&gt;
      &lt;td&gt;Select the search box.&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;kbd&gt;Ctrl&lt;/kbd&gt; + N&lt;/td&gt;
      &lt;td&gt;Open a new window.&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;kbd&gt;Ctrl&lt;/kbd&gt; + T&lt;/td&gt;
      &lt;td&gt;Open a new tab and switch to it.&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;kbd&gt;Ctrl&lt;/kbd&gt; + W&lt;/td&gt;
      &lt;td&gt;Closes the active tab. Closes the window if there’s only one tab open.&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;kbd&gt;Ctrl&lt;/kbd&gt; + &lt;kbd&gt;Tab&lt;/kbd&gt;&lt;/td&gt;
      &lt;td&gt;Move to the next tab.&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;kbd&gt;Ctrl&lt;/kbd&gt; + &lt;kbd&gt;Shift&lt;/kbd&gt; + &lt;kbd&gt;Tab&lt;/kbd&gt;&lt;/td&gt;
      &lt;td&gt;Move to the previous tab.&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;kbd&gt;Ctrl&lt;/kbd&gt; + 1, 2, 3,…&lt;/td&gt;
      &lt;td&gt;Move to that tab number.&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;kbd&gt;Ctrl&lt;/kbd&gt; + mouse scroll wheel&lt;/td&gt;
      &lt;td&gt;Change the size and appearance of file and folder icons.&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;kbd&gt;Ctrl&lt;/kbd&gt; + &lt;kbd&gt;Shift&lt;/kbd&gt; + E&lt;/td&gt;
      &lt;td&gt;Display all folders above the selected folder.&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;kbd&gt;Ctrl&lt;/kbd&gt; + &lt;kbd&gt;Shift&lt;/kbd&gt; + N&lt;/td&gt;
      &lt;td&gt;Create a new folder.&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;kbd&gt;Num Lock&lt;/kbd&gt; + asterisk (*)&lt;/td&gt;
      &lt;td&gt;Display all subfolders under the selected folder.&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;kbd&gt;Num Lock&lt;/kbd&gt; + plus (+)&lt;/td&gt;
      &lt;td&gt;Display the contents of the selected folder.&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;kbd&gt;Num Lock&lt;/kbd&gt; + minus (-)&lt;/td&gt;
      &lt;td&gt;Collapse the selected folder.&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;kbd&gt;Alt&lt;/kbd&gt; + P&lt;/td&gt;
      &lt;td&gt;Display the preview panel.&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;kbd&gt;Alt&lt;/kbd&gt; + &lt;kbd&gt;Enter&lt;/kbd&gt;&lt;/td&gt;
      &lt;td&gt;Open the Properties dialog box for the selected item.&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;kbd&gt;Alt&lt;/kbd&gt; + Right arrow&lt;/td&gt;
      &lt;td&gt;View the next folder.&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;kbd&gt;Alt&lt;/kbd&gt; + Up arrow&lt;/td&gt;
      &lt;td&gt;View the folder that the folder was in.&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;kbd&gt;Alt&lt;/kbd&gt; + Left arrow&lt;/td&gt;
      &lt;td&gt;View the previous folder.&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;kbd&gt;Backspace&lt;/kbd&gt;&lt;/td&gt;
      &lt;td&gt;View the previous folder.&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Right arrow&lt;/td&gt;
      &lt;td&gt;Display the current selection (if it’s collapsed), or select the first subfolder.&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Left arrow&lt;/td&gt;
      &lt;td&gt;Collapse the current selection (if it’s expanded), or select the folder that the folder was in.&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;kbd&gt;End&lt;/kbd&gt;&lt;/td&gt;
      &lt;td&gt;Display the bottom of the active window.&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;kbd&gt;Home&lt;/kbd&gt;&lt;/td&gt;
      &lt;td&gt;Display the top of the active window.&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;kbd&gt;F11&lt;/kbd&gt;&lt;/td&gt;
      &lt;td&gt;Maximize or minimize the active window.&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;h2 id=&quot;virtual-desktops-keyboard-shortcuts&quot;&gt;Virtual desktops keyboard shortcuts&lt;/h2&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;Press this key&lt;/th&gt;
      &lt;th&gt;To do this&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;kbd&gt;Win&lt;/kbd&gt; + &lt;kbd&gt;Tab&lt;/kbd&gt;&lt;/td&gt;
      &lt;td&gt;Open Task view.&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;kbd&gt;Win&lt;/kbd&gt; + &lt;kbd&gt;Ctrl&lt;/kbd&gt; + D&lt;/td&gt;
      &lt;td&gt;Add a virtual desktop.&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;kbd&gt;Win&lt;/kbd&gt; + &lt;kbd&gt;Ctrl&lt;/kbd&gt; + Right arrow&lt;/td&gt;
      &lt;td&gt;Switch between virtual desktops you’ve created on the right.&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;kbd&gt;Win&lt;/kbd&gt; + &lt;kbd&gt;Ctrl&lt;/kbd&gt; + Left arrow&lt;/td&gt;
      &lt;td&gt;Switch between virtual desktops you’ve created on the left.&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;kbd&gt;Win&lt;/kbd&gt; + &lt;kbd&gt;Ctrl&lt;/kbd&gt; + &lt;kbd&gt;F4&lt;/kbd&gt;&lt;/td&gt;
      &lt;td&gt;Close the virtual desktop you’re using.&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;h2 id=&quot;taskbar-keyboard-shortucts&quot;&gt;Taskbar keyboard shortucts&lt;/h2&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;Press this key&lt;/th&gt;
      &lt;th&gt;To do this&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;kbd&gt;Shift&lt;/kbd&gt; + click a taskbar button&lt;/td&gt;
      &lt;td&gt;Open an app or quickly open another instance of an app.&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;kbd&gt;Ctrl&lt;/kbd&gt; + &lt;kbd&gt;Shift&lt;/kbd&gt; + click a taskbar button&lt;/td&gt;
      &lt;td&gt;Open an app as an administrator.&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;kbd&gt;Shift&lt;/kbd&gt; + right-click a taskbar button&lt;/td&gt;
      &lt;td&gt;Show the window menu for the app.&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;kbd&gt;Shift&lt;/kbd&gt; + right-click a grouped taskbar button&lt;/td&gt;
      &lt;td&gt;Show the window menu for the group.&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;kbd&gt;Ctrl&lt;/kbd&gt; + click a grouped taskbar button&lt;/td&gt;
      &lt;td&gt;Cycle through the windows of the group.&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;h2 id=&quot;settings-keyboard-shortcuts&quot;&gt;Settings keyboard shortcuts&lt;/h2&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;Press this key&lt;/th&gt;
      &lt;th&gt;To do this&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;kbd&gt;Win&lt;/kbd&gt; + I&lt;/td&gt;
      &lt;td&gt;Open settings.&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;kbd&gt;Backspace&lt;/kbd&gt;&lt;/td&gt;
      &lt;td&gt;Go back to the settings home page.&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Type on any page with search box&lt;/td&gt;
      &lt;td&gt;Search settings.&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;
</description>
        <pubDate>Mon, 04 Sep 2023 00:00:00 +0000</pubDate>
        <link>https://kitroed.com/2023/09/04/keyboard-shortcuts-in-windows.html</link>
        <guid isPermaLink="true">https://kitroed.com/2023/09/04/keyboard-shortcuts-in-windows.html</guid>
        
        
      </item>
    
      <item>
        <title>Resize active window to 1080p or 720p with Win+\ or Win+Shift+\ respectively [AutoHotKey]</title>
        <description>&lt;h2 id=&quot;autohotkey-resize-window-to-1080p-or-720p-with-win-or-winshift-respectively&quot;&gt;AutoHotKey resize window to 1080p or 720p with Win+\ or Win+Shift+\ respectively&lt;/h2&gt;

&lt;p&gt;Create ahk file with the following two entries:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-ahk&quot;&gt;#\:: ; [Win]+[\]
    WinGet, window, ID, A
    WinMove, ahk_id %window%, , , , 1920, 1080
    return
#+\:: ; [Win]+[Shift]+[\]
    WinGet, window, ID, A
    WinMove, ahk_id %window%, , , , 1280, 720
    return
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Update for AHK v2&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-ahk&quot;&gt;#\:: ; [Win]+[\]
{
    WinMove(, , 1920, 1080, &quot;A&quot;)
}

#+\:: ; [Win]+[Shift]+[\]
{
    WinMove(, , 1280, 720, &quot;A&quot;)
}

&lt;/code&gt;&lt;/pre&gt;
</description>
        <pubDate>Wed, 09 Mar 2022 00:00:00 +0000</pubDate>
        <link>https://kitroed.com/2022/03/09/resize-active-window-to-1080p-or-720p-with-win-or-winshift-respectively.html</link>
        <guid isPermaLink="true">https://kitroed.com/2022/03/09/resize-active-window-to-1080p-or-720p-with-win-or-winshift-respectively.html</guid>
        
        
      </item>
    
      <item>
        <title>Disable Web Search in Windows 10 Start Menu [powershell]</title>
        <description>&lt;h2 id=&quot;disable-the-bing-search-results-in-windows-10-search&quot;&gt;Disable the Bing search results in Windows 10 search&lt;/h2&gt;

&lt;p&gt;Annoyingly, this requires adding a new 0-value DWORD registry entry. In PowerShell:&lt;/p&gt;

&lt;div class=&quot;language-powershell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;Set-ItemProperty&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;-Path&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;HKCU:\Software\Microsoft\Windows\CurrentVersion\Search&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;-Name&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;BingSearchEnabled&quot;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;-Value&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;-Type&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;DWord&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
</description>
        <pubDate>Sun, 07 Mar 2021 00:00:00 +0000</pubDate>
        <link>https://kitroed.com/2021/03/07/disable-web-search-in-win10-start.html</link>
        <guid isPermaLink="true">https://kitroed.com/2021/03/07/disable-web-search-in-win10-start.html</guid>
        
        
      </item>
    
      <item>
        <title>Kit&apos;s Git Cheat Sheet [git]</title>
        <description>&lt;h2 id=&quot;repo-creation&quot;&gt;Repo Creation&lt;/h2&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;cd&lt;/code&gt; to directory&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;git init
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;or&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;git init repo_dir
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;“Bare” repository creation (e.g. for use in network file-based share)&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;git init --bare
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Clone an existing repository (default name of first remote is &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;origin&lt;/code&gt;)&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;git clone repo_url
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;changes&quot;&gt;Changes&lt;/h2&gt;

&lt;p&gt;State of changed files in working directory&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;git status
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Changes to tracked files&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;git diff
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Changes to files that are added to index&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;git diff --cached
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Add all current changes&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;git add .
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Add some changes in &amp;lt;file&amp;gt; to the next commit&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;git add -p &amp;lt;file&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Commit all local changes in tracked files (quick-add and commit)&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;git commit -a
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Commit staged&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;git commit
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Change last commit with staged&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;git commit --amend
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;history&quot;&gt;History&lt;/h2&gt;

&lt;p&gt;List commits, newest to oldest&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;git log
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;List commits within a range of revisions (rev identifiers can be branches, revision id’s, tags, etc.)&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;git log &amp;lt;from&amp;gt;..&amp;lt;to&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Show changes to a file&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;git log -p &amp;lt;file&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Show changes, excluding merge commits&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;git log --no-merged
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Show changes&lt;/p&gt;

&lt;p&gt;Kit’s “tab-separated changes we’re about to release with author name” one-liner&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;git log prod..test --pretty=format:&quot;%h%x09%an%x09%s&quot; --no-merges
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Annotate file&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;git blame &amp;lt;file&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;branches--tags&quot;&gt;Branches &amp;amp; Tags&lt;/h2&gt;

&lt;p&gt;List all branches with last commit message, and tracking branch info&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;git branch -avv
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Switch &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;HEAD&lt;/code&gt; to a branch (note that this will check out remote branch and track if ref matches)&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;git checkout &amp;lt;branch&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Create new branch based on current &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;HEAD&lt;/code&gt; and check it out&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;git checkout -b &amp;lt;new-branch&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Delete local branch (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-D&lt;/code&gt; to force)&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;git branch -d &amp;lt;branch&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Delete branch on remote &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;origin&lt;/code&gt;&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;git push origin --delete &amp;lt;branch&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;List branches on remote that are not merged into specified branch on remote&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;git branch -r --no-merged origin/&amp;lt;branch&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Create a (lightweight) tag on the current commit&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;git tag &amp;lt;tag-name&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Push a specific tag to remote &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;origin&lt;/code&gt;&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;git push origin &amp;lt;tag-name&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Push all tags to current default remote (not usually recommended)&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;git push --tags
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Get a cool “tag plus number of commits plus short revision id” value for current head (e.g. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;3.2.1-14-g3ef206ca&lt;/code&gt;)&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;git describe --tags
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;update--publish&quot;&gt;Update &amp;amp; Publish&lt;/h2&gt;

&lt;p&gt;Get latest branch info from remote and delete tracking branches no longer present on remote&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;git fetch --prune
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Push local branch to remote and track (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;--set-upstream&lt;/code&gt;) (Note, no need to checkout branch you’re pushing if specified in the command)&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;git push -u origin &amp;lt;branch&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;merge--rebase&quot;&gt;Merge &amp;amp; Rebase&lt;/h2&gt;

&lt;p&gt;Merge &amp;lt;branch&amp;gt; into your current &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;HEAD&lt;/code&gt;&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;git merge &amp;lt;branch&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Rebase your current &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;HEAD&lt;/code&gt; into &amp;lt;branch&amp;gt; (think opposite order of operations)&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;git rebase &amp;lt;branch&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;After rebase is complete, stage changes and commit&lt;/p&gt;

&lt;p&gt;In the event of merge conflicts, abort with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;git rebase --abort&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;git rebase --continue&lt;/code&gt; after resolving.&lt;/p&gt;

&lt;h2 id=&quot;advancedmiscellaneous&quot;&gt;Advanced/Miscellaneous&lt;/h2&gt;

&lt;p&gt;Get a short revision identifier for the currently checked out commit&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;git rev-parse --short HEAD
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Move last commit intended for a &lt;strong&gt;new&lt;/strong&gt; branch from current branch to &amp;lt;new-branch&amp;gt;&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;git branch &amp;lt;new-branch&amp;gt;
git reset HEAD~ --hard
git checkout &amp;lt;new-branch&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Move last commit to another existing branch&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;# undo the last commit, but leave the changes available
git reset HEAD~ --soft
git stash
# move to the correct branch
git checkout name-of-the-correct-branch
git stash pop
git add . # or add individual files
git commit -m &quot;your message here&quot;
# now your changes are on the correct branch
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;or use cherry-pick&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;git checkout name-of-the-correct-branch
# grab the last commit to master
git cherry-pick master
# delete it from master
git checkout master
git reset HEAD~ --hard
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Duplicate (mirror) an existing repository from one location to another&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;git clone --mirror &amp;lt;source-repository-url&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;(This makes a bare repository with the config &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;mirror = true&lt;/code&gt; set.) To set the push location&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;cd &amp;lt;repository-to-mirror&amp;gt;.git
git remote set-url --push origin &amp;lt;mirror-dest-repostiory-url&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Like bare clone, the mirror clone includes all branches and tags, but they’ll be overwritten each time you fetch. To update from the mirror source, fetch then push:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;git fetch --prune origin
git push --mirror
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
</description>
        <pubDate>Wed, 12 Jun 2019 00:00:00 +0000</pubDate>
        <link>https://kitroed.com/2019/06/12/kits-git-cheat-sheet.html</link>
        <guid isPermaLink="true">https://kitroed.com/2019/06/12/kits-git-cheat-sheet.html</guid>
        
        
      </item>
    
      <item>
        <title>Switching to, and making PowerShell work on Arch [bash]</title>
        <description>&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;env TERM=xterm pwsh
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Yep, that’s it.&lt;/p&gt;
</description>
        <pubDate>Tue, 10 Jul 2018 00:00:00 +0000</pubDate>
        <link>https://kitroed.com/2018/07/10/getting-pwsh-to-work-on-arch.html</link>
        <guid isPermaLink="true">https://kitroed.com/2018/07/10/getting-pwsh-to-work-on-arch.html</guid>
        
        
      </item>
    
      <item>
        <title>touch command (update Date Modified) in Windows [powershell]</title>
        <description>&lt;h2 id=&quot;how-to-update-the-date-modified-value-for-a-given-file-in-windows&quot;&gt;How to update the “Date Modified” value for a given file in Windows&lt;/h2&gt;

&lt;p&gt;Known simply as the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;touch&lt;/code&gt; command in *nix, the same can be accomplished using PowerShell:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;PS&amp;gt; (ls your-file-name-here).LastWriteTime = Get-Date
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;(note that &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;PS&amp;gt;&lt;/code&gt; is the prompt, not part of the command.)&lt;/p&gt;

&lt;p&gt;(with thanks to &lt;a href=&quot;https://superuser.com/questions/10426/windows-equivalent-of-the-linux-command-touch&quot;&gt;superuser.com&lt;/a&gt;)&lt;/p&gt;
</description>
        <pubDate>Tue, 08 May 2018 00:00:00 +0000</pubDate>
        <link>https://kitroed.com/2018/05/08/touch-command-in-windows.html</link>
        <guid isPermaLink="true">https://kitroed.com/2018/05/08/touch-command-in-windows.html</guid>
        
        
      </item>
    
  </channel>
</rss>
