[{"content":"","date":"16 May 2026","externalUrl":null,"permalink":"/tags/bash/","section":"Tags","summary":"","title":"Bash","type":"tags"},{"content":"","date":"16 May 2026","externalUrl":null,"permalink":"/tags/encryption/","section":"Tags","summary":"","title":"Encryption","type":"tags"},{"content":" Generating Base64 Random Strings with OpenSSL # The command echo \u0026quot;base64:$(openssl rand -base64 32 2\u0026gt;/dev/null)\u0026quot; is a powerful utility for generating secure, random strings encoded in base64 format. This is particularly useful for creating application keys, API tokens, encryption keys, and other sensitive data that requires cryptographic randomness.\nUnderstanding the Command # Let\u0026rsquo;s break down each component:\necho \u0026#34;base64:$(openssl rand -base64 32 2\u0026gt;/dev/null)\u0026#34; openssl rand -base64 32: Generates 32 random bytes and encodes them in base64 format 2\u0026gt;/dev/null: Suppresses any error messages from OpenSSL echo \u0026quot;base64:$(...): Wraps the output with a \u0026ldquo;base64:\u0026rdquo; prefix for clarity The entire command outputs a prefixed base64 string suitable for use in configuration files Basic Usage # Run the command directly in your terminal:\necho \u0026#34;base64:$(openssl rand -base64 32 2\u0026gt;/dev/null)\u0026#34; Example output:\nbase64:aBcDeF1g2H3ij4KLMnOPqRsTuVwXyZ0a1B2c3D4e5F6gH7i= Generating Different Sizes # The number in the command (32 in this case) specifies the number of random bytes to generate. You can adjust this based on your needs:\n# Generate 16 bytes (128-bit) - shorter string echo \u0026#34;base64:$(openssl rand -base64 16 2\u0026gt;/dev/null)\u0026#34; # Generate 32 bytes (256-bit) - recommended for most applications echo \u0026#34;base64:$(openssl rand -base64 32 2\u0026gt;/dev/null)\u0026#34; # Generate 64 bytes (512-bit) - maximum security echo \u0026#34;base64:$(openssl rand -base64 64 2\u0026gt;/dev/null)\u0026#34; Practical Applications # Laravel Application Key # Laravel applications require an APP_KEY for encryption. Generate one with:\necho \u0026#34;base64:$(openssl rand -base64 32 2\u0026gt;/dev/null)\u0026#34; Then add it to your .env file:\nAPP_KEY=base64:your_generated_key_here Database Encryption Keys # Create secure keys for database encryption:\nDB_ENCRYPTION_KEY=$(echo \u0026#34;base64:$(openssl rand -base64 32 2\u0026gt;/dev/null)\u0026#34; | sed \u0026#39;s/base64://\u0026#39;) API Secrets # Generate API tokens for integrations:\nAPI_SECRET=$(echo \u0026#34;base64:$(openssl rand -base64 32 2\u0026gt;/dev/null)\u0026#34; | sed \u0026#39;s/base64://\u0026#39;) Removing the \u0026ldquo;base64:\u0026rdquo; Prefix # If you only need the raw base64 string without the prefix:\nopenssl rand -base64 32 2\u0026gt;/dev/null Or use sed to strip it:\necho \u0026#34;base64:$(openssl rand -base64 32 2\u0026gt;/dev/null)\u0026#34; | sed \u0026#39;s/base64://\u0026#39; Creating a Bash Function # For frequent use, add this function to your .bashrc or .zshrc:\n# Generate a base64-encoded random string genkey() { local size=${1:-32} echo \u0026#34;base64:$(openssl rand -base64 $size 2\u0026gt;/dev/null)\u0026#34; } # Usage: genkey 32 # Usage: genkey 64 Then source your shell configuration:\nsource ~/.bashrc Now you can simply run:\ngenkey genkey 64 Security Considerations # Use OpenSSL\u0026rsquo;s random source: OpenSSL uses the system\u0026rsquo;s cryptographically secure random number generator Sufficient entropy: 32 bytes (256-bit) is recommended for most applications Never share keys: Treat generated keys as sensitive data Regenerate regularly: For critical keys, implement rotation policies Store securely: Use environment variables or secure vaults, not hardcoded in source files Tips and Tricks # Generate Multiple Keys at Once # for i in {1..5}; do echo \u0026#34;Key $i: $(echo \u0026#34;base64:$(openssl rand -base64 32 2\u0026gt;/dev/null)\u0026#34;)\u0026#34; done Save to a File # echo \u0026#34;base64:$(openssl rand -base64 32 2\u0026gt;/dev/null)\u0026#34; \u0026gt; /path/to/secret.key chmod 600 /path/to/secret.key Conclusion # The echo \u0026quot;base64:$(openssl rand -base64 32 2\u0026gt;/dev/null)\u0026quot; command is an essential tool for generating cryptographically secure random strings. Whether you\u0026rsquo;re setting up Laravel applications, creating API secrets, or generating encryption keys, this one-liner provides a simple, reliable way to produce the random data you need.\n","date":"16 May 2026","externalUrl":null,"permalink":"/posts/generate-base64-random-string/","section":"Posts","summary":"","title":"Generating Base64 Random Strings with OpenSSL","type":"posts"},{"content":"","date":"16 May 2026","externalUrl":null,"permalink":"/tags/openssl/","section":"Tags","summary":"","title":"Openssl","type":"tags"},{"content":"","date":"16 May 2026","externalUrl":null,"permalink":"/posts/","section":"Posts","summary":"","title":"Posts","type":"posts"},{"content":"","date":"16 May 2026","externalUrl":null,"permalink":"/tags/random/","section":"Tags","summary":"","title":"Random","type":"tags"},{"content":"I\u0026rsquo;m a tech enthusiast with a passion for homelabs and self-hosting.\nThis site is a collection of my setup guides, configurations, and notes for anyone building their own homelab.\n","date":"16 May 2026","externalUrl":null,"permalink":"/","section":"Sean's Tech Notes","summary":"","title":"Sean's Tech Notes","type":"page"},{"content":"","date":"16 May 2026","externalUrl":null,"permalink":"/tags/security/","section":"Tags","summary":"","title":"Security","type":"tags"},{"content":"","date":"16 May 2026","externalUrl":null,"permalink":"/tags/","section":"Tags","summary":"","title":"Tags","type":"tags"},{"content":"","date":"16 May 2026","externalUrl":null,"permalink":"/tags/terminal/","section":"Tags","summary":"","title":"Terminal","type":"tags"},{"content":"","date":"25 April 2026","externalUrl":null,"permalink":"/tags/docker/","section":"Tags","summary":"","title":"Docker","type":"tags"},{"content":"","date":"25 April 2026","externalUrl":null,"permalink":"/tags/monitoring/","section":"Tags","summary":"","title":"Monitoring","type":"tags"},{"content":"","date":"25 April 2026","externalUrl":null,"permalink":"/tags/self-hosted/","section":"Tags","summary":"","title":"Self-Hosted","type":"tags"},{"content":"","date":"25 April 2026","externalUrl":null,"permalink":"/tags/status-page/","section":"Tags","summary":"","title":"Status-Page","type":"tags"},{"content":"","date":"25 April 2026","externalUrl":null,"permalink":"/tags/ubuntu/","section":"Tags","summary":"","title":"Ubuntu","type":"tags"},{"content":" My Uptime Kuma Setup # This Uptime Kuma setup runs in a Docker container and is used to monitor websites, services, and network devices. It includes configurations for environment variables, volume mounts, and networking.\nPrerequisites # Docker installed and running (see my Docker installation guide) A user account with sudo privileges or access to Docker Create a Persistent Data Folder # Create a local folder to store Uptime Kuma data:\nmkdir -p ~/uptime-kuma Docker Compose Deployment # Create a file named docker-compose.yml:\nservices: uptime-kuma: image: louislam/uptime-kuma:2 # Uptime Kuma image container_name: uptime-kuma # Container name restart: always # Always restart on failure or reboot ports: - \u0026#34;3001:3001\u0026#34; # This maps the container port \u0026#34;3001\u0026#34; to the host port \u0026#34;3001\u0026#34; volumes: - ~/uptime-kuma/config:/app/data # Configuring persistent storage environment: - TZ=Europe/London # Set the timezone (change to your preferred local timezone so monitoring times are the same) healthcheck: test: [\u0026#34;CMD\u0026#34;, \u0026#34;curl\u0026#34;, \u0026#34;-f\u0026#34;, \u0026#34;http://localhost:3001\u0026#34;] # Check local web health endpoint interval: 30s # Health check interval retries: 3 # Number of retries before unhealthy start_period: 10s # Startup grace period timeout: 5s # Health check timeout logging: driver: \u0026#34;json-file\u0026#34; # Docker default log driver options: max-size: \u0026#34;10m\u0026#34; # Rotate logs after 10MB per file max-file: \u0026#34;3\u0026#34; # Keep up to 3 rotated log files Start it:\ndocker compose up -d Access the Web UI # Open:\nhttp://\u0026lt;your-server-ip\u0026gt;:3001 On first launch, create your admin account and password.\nUpdating Uptime Kuma # If you deployed with Docker Compose:\ndocker compose pull docker compose up -d Your monitor history and settings remain intact because data is stored in ~/uptime-kuma/config.\nUseful Commands # View logs:\ndocker logs -f uptime-kuma Check container status:\ndocker ps --filter name=uptime-kuma Conclusion # Uptime Kuma gives you a simple way to monitor services and publish a status page from your own server. With persistent storage and regular backups, it is easy to run and maintain on Ubuntu.\nFor more details, visit the official documentation:\nUptime Kuma Documentation\n","date":"25 April 2026","externalUrl":null,"permalink":"/posts/uptime-kuma/","section":"Posts","summary":"","title":"Uptime Kuma","type":"posts"},{"content":"","date":"25 April 2026","externalUrl":null,"permalink":"/tags/uptime-kuma/","section":"Tags","summary":"","title":"Uptime-Kuma","type":"tags"},{"content":"","date":"17 April 2026","externalUrl":null,"permalink":"/tags/linux/","section":"Tags","summary":"","title":"Linux","type":"tags"},{"content":"","date":"17 April 2026","externalUrl":null,"permalink":"/tags/netplan/","section":"Tags","summary":"","title":"Netplan","type":"tags"},{"content":"","date":"17 April 2026","externalUrl":null,"permalink":"/tags/networking/","section":"Tags","summary":"","title":"Networking","type":"tags"},{"content":" Introduction # If you want your Ubuntu machine to always keep the same IP address, you can set a static IP. This is useful for servers, homelabs, media boxes, and any system you need to reach reliably on your network.\nThis guide uses Netplan, which is the standard network configuration system on modern Ubuntu releases.\nCheck Your Current Network Details # First, identify your network interface name:\nip a Look for something like ens18, enp0s3, or eth0.\nYou can also check your current gateway with:\nip route Make a note of:\nyour interface name, the IP address you want to use, your subnet size (for example /24), your gateway address, and your DNS servers. Find Your Netplan Configuration File # Most Ubuntu systems store Netplan files in /etc/netplan/.\nList the files with:\nls /etc/netplan/ You will usually see a file such as:\n00-installer-config.yaml or:\n50-cloud-init.yaml Open the file with a text editor:\nsudo nano /etc/netplan/00-installer-config.yaml If your file has a different name, use that instead.\nSet the Static IP # Replace the existing configuration with something like this:\nnetwork: ethernets: ens33: addresses: - 192.168.1.250/24 dhcp6: true match: macaddress: put your device mac address here nameservers: addresses: - 192.168.1.1 search: - put a domain here if u have one routes: - to: default via: 192.168.1.1 set-name: ens33 version: 2 Change the example values to match your network:\nenp0s3 → your actual network interface name, 192.168.1.50/24 → the static IP you want to assign, 192.168.1.1 → your router or gateway, 1.1.1.1 and 8.8.8.8 → your preferred DNS servers. Make sure the static IP you choose is not already in use by another device.\nApply the Changes # Test the configuration first:\nsudo netplan try If everything looks good, apply it permanently:\nsudo netplan apply If you are connected remotely over SSH, be careful when changing network settings because a mistake can disconnect your session.\nVerify the Static IP # Check that the new IP address is active:\nip a Confirm the default route:\nip route You can also test connectivity with:\nping -c 4 1.1.1.1 And test DNS resolution with:\nping -c 4 google.co.uk Conclusion # Your Ubuntu system should now be using a static IP address. This makes it much easier to manage services such as SSH, Docker, Plex, or any self-hosted applications that need a fixed network address.\n","date":"17 April 2026","externalUrl":null,"permalink":"/posts/set-static-ip-ubuntu/","section":"Posts","summary":"","title":"Set a Static IP Address on Ubuntu","type":"posts"},{"content":"","date":"17 April 2026","externalUrl":null,"permalink":"/tags/static-ip/","section":"Tags","summary":"","title":"Static-Ip","type":"tags"},{"content":" Introduction # Tailscale is a secure mesh VPN that makes it easy to connect your Ubuntu machine to your private network from anywhere. In this guide, we will install Tailscale, bring the device online, and verify that everything is working correctly.\nUpdate Your System # Start by updating package lists and upgrading installed packages:\nsudo apt update \u0026amp;\u0026amp; sudo apt upgrade -y Install Tailscale # Run the official install script:\ncurl -fsSL https://tailscale.com/install.sh | sh This adds the Tailscale repository and installs the required package.\nStart and Enable the Service # Enable and start the Tailscale daemon so it also starts on boot:\nsudo systemctl enable --now tailscaled You can check service status with:\nsystemctl status tailscaled Connect the Machine to Your Tailnet # For an interactive login:\nsudo tailscale up Tailscale will print a login URL in the terminal. Open it in your browser and sign in.\nFor unattended setup (optional), use an auth key instead:\nsudo tailscale up --auth-key=\u0026#34;tskey-xxxxxxxxxxxxxxxx\u0026#34; If your tailnet advertises subnet routes and you want this machine to use them:\nsudo tailscale set --accept-routes Verify the Connection # After authentication, check your assigned Tailscale IP and connection details:\ntailscale ip -4 tailscale status You can also check full diagnostic information:\ntailscale netcheck Useful Commands # See your current Tailscale settings:\ntailscale status Disconnect from your tailnet:\nsudo tailscale down Reconnect later:\nsudo tailscale up Conclusion # Your Ubuntu system is now connected to Tailscale and ready for secure remote access. This setup is ideal for homelabs, remote administration, and private access to services without exposing ports publicly.\n","date":"12 April 2026","externalUrl":null,"permalink":"/posts/install-tailscale-ubuntu/","section":"Posts","summary":"","title":"Install Tailscale on Ubuntu","type":"posts"},{"content":"","date":"12 April 2026","externalUrl":null,"permalink":"/tags/tailscale/","section":"Tags","summary":"","title":"Tailscale","type":"tags"},{"content":"","date":"12 April 2026","externalUrl":null,"permalink":"/tags/vpn/","section":"Tags","summary":"","title":"Vpn","type":"tags"},{"content":" Introduction # Creating a separate user account on Ubuntu is a good way to improve security and keep administration tasks organised. In this guide, we’ll create a new user, set a password, and optionally give the account sudo access.\nCreate a New User # Use the adduser command, replacing newusername with the name you want to use:\nsudo adduser newusername Ubuntu will then prompt you to:\ncreate a password for the new account, confirm the password, and optionally enter extra details such as the full name and phone number. If you don’t want to fill in the extra details, you can simply press Enter to skip them.\nConfirm the User Was Created # To verify that the account now exists, run:\nid newusername If the user has been created successfully, Ubuntu will display the user ID (uid) and group information.\nGive the User Sudo Access (Optional) # If the new account needs administrator privileges, add it to the sudo group:\nsudo usermod -aG sudo newusername This allows the user to run administrative commands with sudo.\nOnly grant sudo access to accounts that actually need it.\nSwitch to the New User # To test the new account, switch to it with:\nsu - newusername If everything is working correctly, your shell prompt will change to the new user.\nYou can also confirm whether the user has sudo access by running:\nsudo whoami If configured correctly, the output should be:\nroot Conclusion # You now know how to create a new user on Ubuntu and optionally grant it sudo privileges. This is a basic but essential task for managing servers and desktop systems safely.\n","date":"10 April 2026","externalUrl":null,"permalink":"/posts/create-new-user-ubuntu/","section":"Posts","summary":"","title":"Create a New User on Ubuntu","type":"posts"},{"content":"","date":"10 April 2026","externalUrl":null,"permalink":"/tags/linux-administration/","section":"Tags","summary":"","title":"Linux-Administration","type":"tags"},{"content":"","date":"10 April 2026","externalUrl":null,"permalink":"/tags/sudo/","section":"Tags","summary":"","title":"Sudo","type":"tags"},{"content":"","date":"10 April 2026","externalUrl":null,"permalink":"/tags/system-administration/","section":"Tags","summary":"","title":"System-Administration","type":"tags"},{"content":"","date":"10 April 2026","externalUrl":null,"permalink":"/tags/user-management/","section":"Tags","summary":"","title":"User-Management","type":"tags"},{"content":"","date":"1 April 2026","externalUrl":null,"permalink":"/tags/deployment/","section":"Tags","summary":"","title":"Deployment","type":"tags"},{"content":"","date":"1 April 2026","externalUrl":null,"permalink":"/tags/dism/","section":"Tags","summary":"","title":"Dism","type":"tags"},{"content":"","date":"1 April 2026","externalUrl":null,"permalink":"/tags/execution-policy/","section":"Tags","summary":"","title":"Execution-Policy","type":"tags"},{"content":" Overview # This command exports a single image index from an existing install.wim file into a new WIM file. In this example, index 6 is exported to pro.wim.\nCommand # Dism /Export-Image /SourceImageFile:\u0026#34;D:\\sources\\install.wim\u0026#34; /SourceIndex:6 /DestinationImageFile:\u0026#34;D:\\sources\\pro.wim\u0026#34; What each parameter does # /Export-Image: Exports an image from one WIM file to another. /SourceImageFile: Path to the original WIM file. /SourceIndex:1: The image index to export. /DestinationImageFile: Path and filename for the new exported WIM. Optional check # To verify available image indexes before exporting:\nDism /Get-WimInfo /WimFile:\u0026#34;D:\\sources\\install.wim\u0026#34; ","date":"1 April 2026","externalUrl":null,"permalink":"/posts/dism-export-image/","section":"Posts","summary":"","title":"Export Pro Edition from install.wim using DISM","type":"posts"},{"content":"","date":"1 April 2026","externalUrl":null,"permalink":"/tags/imaging/","section":"Tags","summary":"","title":"Imaging","type":"tags"},{"content":"","date":"1 April 2026","externalUrl":null,"permalink":"/tags/powershell/","section":"Tags","summary":"","title":"Powershell","type":"tags"},{"content":"","date":"1 April 2026","externalUrl":null,"permalink":"/tags/scripting/","section":"Tags","summary":"","title":"Scripting","type":"tags"},{"content":" Overview # This command sets the execution policy to Unrestricted only for the current PowerShell process. It does not permanently change machine or user policy settings.\nCommand # Set-ExecutionPolicy -ExecutionPolicy Unrestricted -Scope Process What this does # -ExecutionPolicy Unrestricted: Allows all scripts to run, including unsigned scripts. -Scope Process: Applies only to the current PowerShell window/process. When the session closes, the policy change is removed automatically. Verify Current Effective Policy # Get-ExecutionPolicy -List Look for the Process row to confirm the temporary setting is active.\nSecurity Note # Use this scope when you need a temporary policy change for a trusted script. For safer day-to-day usage, consider RemoteSigned instead of Unrestricted.\n","date":"1 April 2026","externalUrl":null,"permalink":"/posts/powershell-executionpolicy-process/","section":"Posts","summary":"","title":"Set PowerShell Execution Policy for Current Session","type":"posts"},{"content":"","date":"1 April 2026","externalUrl":null,"permalink":"/tags/wim/","section":"Tags","summary":"","title":"Wim","type":"tags"},{"content":"","date":"1 April 2026","externalUrl":null,"permalink":"/tags/windows/","section":"Tags","summary":"","title":"Windows","type":"tags"},{"content":"","date":"15 February 2026","externalUrl":null,"permalink":"/tags/containerization/","section":"Tags","summary":"","title":"Containerization","type":"tags"},{"content":" My Portainer Setup # This Portainer setup runs in a Docker container and is used to manage Docker environments through a web interface. It includes configurations for environment variables, volume mounts, and networking.\nPrerequisites # Docker installed and running (see my Docker installation guide) User account with sudo privileges or in the docker group Create a Volume for Portainer Data # Portainer stores its data (users, settings, stacks, etc.) in a volume. Create one so your data persists across container restarts:\ndocker volume create portainer_data Deploy Portainer Community Edition # Run the Portainer container with the following command:\ndocker run -d \\ -p 8000:8000 \\ -p 9443:9443 \\ --name portainer \\ --restart=always \\ -v /var/run/docker.sock:/var/run/docker.sock \\ -v portainer_data:/data \\ portainer/portainer-ce:latest Your portainer data will be stored in the portainer_data volume. follow the in-app or docs guidance after first login.\nDeploy Portainer Business edition # Run the Business edition container with the following command:\ndocker run -d \\ -p 8000:8000 \\ -p 9443:9443 \\ --name portainer \\ --restart=always \\ -v /var/run/docker.sock:/var/run/docker.sock \\ -v portainer_data:/data \\ portainer/portainer-ee:lts Your business data will be stored in the portainer_data volume. If your Business license requires activation, follow the in-app or docs guidance after first login.\nBreakdown of the flags:\nFlag Purpose -d Run in detached mode (background) -p 8000:8000 Expose the Edge agent tunnel port -p 9443:9443 Expose the Portainer web UI (HTTPS) --restart=always Automatically restart the container if it stops -v /var/run/docker.sock:/var/run/docker.sock Give Portainer access to the Docker daemon -v portainer_data:/data Persist Portainer data Access the Web UI # Open your browser and navigate to:\nhttps://\u0026lt;your-server-ip\u0026gt;:9443 On first access, you will be prompted to create an admin user and password.\nNote: The certificate is self-signed, so your browser will show a security warning. This is expected — click through to continue.\nConnect Your Environment # After logging in, Portainer will ask you to connect an environment. Select \u0026ldquo;Get Started\u0026rdquo; to connect to the local Docker instance that Portainer is already running on.\nYou should now see your containers, images, volumes, and networks in the Portainer dashboard.\nUpdating Portainer # To update Portainer to the latest version:\ndocker stop portainer docker rm portainer Portainer Community Edition:\ndocker pull portainer/portainer-ce:latest docker run -d \\ -p 8000:8000 \\ -p 9443:9443 \\ --name portainer \\ --restart=always \\ -v /var/run/docker.sock:/var/run/docker.sock \\ -v portainer_data:/data \\ portainer/portainer-ce:latest Portainer Business edition:\ndocker pull portainer/portainer-ee:lts docker run -d \\ -p 8000:8000 \\ -p 9443:9443 \\ --name portainer \\ --restart=always \\ -v /var/run/docker.sock:/var/run/docker.sock \\ -v portainer_data:/data \\ portainer/portainer-ee:lts Your data is safe in the portainer_data volume — only the container image is replaced.\nRemoving Portainer # To remove Portainer and its data:\ndocker stop portainer docker rm portainer docker volume rm portainer_data Conclusion # Portainer gives you a clean web UI to manage your Docker containers, images, networks, and volumes without needing to remember CLI commands. It\u0026rsquo;s one of the first things I deploy on any new Docker host.\nFor more information, visit the official Portainer documentation:\nPortainer Community Installation Guide\nPortainer Business Installation Guide\n","date":"15 February 2026","externalUrl":null,"permalink":"/posts/portainer/","section":"Posts","summary":"","title":"Portainer","type":"posts"},{"content":"","date":"15 February 2026","externalUrl":null,"permalink":"/tags/portainer/","section":"Tags","summary":"","title":"Portainer","type":"tags"},{"content":"","date":"15 February 2026","externalUrl":null,"permalink":"/tags/tutorial/","section":"Tags","summary":"","title":"Tutorial","type":"tags"},{"content":"","date":"16 April 2025","externalUrl":null,"permalink":"/tags/home-media/","section":"Tags","summary":"","title":"Home-Media","type":"tags"},{"content":" Install Plex Media Server via Plex APT Repository # Set up your personal media server with Plex on Ubuntu using the official APT repository. This guide walks you through each step to ensure a smooth installation.\nUpdate Ubuntu Before Plex Installation # Before proceeding, ensure your system is fully up to date:\nsudo apt update Upgrade any outdated packages:\nsudo apt upgrade -y Add the Plex APT Repository # Plex provides an official setup script that automatically adds the APT repository and signing key to your system. Run the following command to configure it:\ncurl -LsSf https://repo.plex.tv/scripts/setupRepo.sh | sudo bash Install Plex Media Server # Update APT with the newly added Plex repository:\nsudo apt update Install Plex Media Server:\nsudo apt install plexmediaserver Verify Plex Media Server Service # Check the status of the Plex service:\nsystemctl status plexmediaserver Confirm that the service status is active (running).\nManage Plex Media Server Service # If the service isn\u0026rsquo;t running, start it manually:\nsudo systemctl start plexmediaserver Enable Plex to start on system boot:\nsudo systemctl enable plexmediaserver Restart the service at any time:\nsudo systemctl restart plexmediaserver ","date":"16 April 2025","externalUrl":null,"permalink":"/posts/plex-media-server/","section":"Posts","summary":"","title":"How to Install Plex Media Server on Ubuntu","type":"posts"},{"content":"","date":"16 April 2025","externalUrl":null,"permalink":"/tags/installation/","section":"Tags","summary":"","title":"Installation","type":"tags"},{"content":"","date":"16 April 2025","externalUrl":null,"permalink":"/tags/media-server/","section":"Tags","summary":"","title":"Media-Server","type":"tags"},{"content":"","date":"16 April 2025","externalUrl":null,"permalink":"/tags/streaming/","section":"Tags","summary":"","title":"Streaming","type":"tags"},{"content":"","date":"15 March 2025","externalUrl":null,"permalink":"/tags/file-systems/","section":"Tags","summary":"","title":"File-Systems","type":"tags"},{"content":"","date":"15 March 2025","externalUrl":null,"permalink":"/tags/mounting/","section":"Tags","summary":"","title":"Mounting","type":"tags"},{"content":" Introduction # CIFS (Common Internet File System) allows you to mount network folders on your Linux system, making it easier to access shared files from Windows machines. In this guide, we\u0026rsquo;ll walk through the steps to install CIFS, mount unprotected and password-protected shares, and discuss the importance of using credentials files for secure mounting.\nInstall CIFS # To install CIFS, run the following command:\nsudo apt install cifs-utils Mount unprotected (guest) network folders # First, let’s create the mount directory. You will need a separate directory for each mount:\nsudo mkdir -p /media/windowsshare Then edit your /etc/fstab file (with root privileges)\nsudo nano /etc/fstab add this line:\n//servername/sharename /media/windowsshare cifs guest,uid=1000 0 0 Where:\nservername is the server hostname or IP address,\nguest indicates you don’t need a password to access the share,\nuid=1000 makes the Linux user (specified by the ID) the owner of the mounted share, allowing them to rename files, and\nIf there is any space in the server path, you need to replace it by \\040, for example: //servername/My\\040Documents\nAfter you add the entry to /etc/fstab, type:\nsudo mount /media/windowsshare Mount password-protected network folders # To auto-mount a password-protected share, you can edit /etc/fstab (with root privileges), and add this line:\nservername/sharename /media/windowsshare cifs username=msusername,password=mspassword 0 0 ** Warning: ** This is not a good idea however: /etc/fstab is readable by everyone – and so is your Windows password within it. The way around this is to use a credentials file.\nCreate a credentials file # Using a text editor, create a file for your remote server’s logon credential:\nsudo nano ~/.smbcredentials Enter your Windows username and password in the file:\nusername=username password=password Save the file and exit the editor.\nChange the permissions of the file to prevent unwanted access to your credentials:\nchmod 600 ~/.smbcredentials Then edit your /etc/fstab file (with root privileges) to add this line (replacing the insecure line in the example above, if you added it):\n//servername/sharename /media/windowsshare cifs credentials=/home/ubuntuusername/.smbcredentials 0 0 Save the file and exit the editor.\nFinally, test mounting the share by running:\nsudo mount /media/windowsshare If there are no errors, you should test how it works after a reboot. Your remote share should mount automatically. However, if the remote server goes offline, the boot process could present errors because it won’t be possible to mount the share.\nConclusion # You now know how to mount network folders on your Linux system using CIFS! With these simple steps, you can access your Windows shares without having to physically connect a cable. Remember to use a credentials file for password-protected shares to keep your passwords safe. Happy mounting!\n","date":"15 March 2025","externalUrl":null,"permalink":"/posts/install-cifs/","section":"Posts","summary":"","title":"Mounting Network Folders with CIFS","type":"posts"},{"content":"","date":"15 March 2025","externalUrl":null,"permalink":"/tags/network-shares/","section":"Tags","summary":"","title":"Network-Shares","type":"tags"},{"content":"","date":"15 March 2025","externalUrl":null,"permalink":"/tags/storage/","section":"Tags","summary":"","title":"Storage","type":"tags"},{"content":"","date":"15 March 2025","externalUrl":null,"permalink":"/tags/administration/","section":"Tags","summary":"","title":"Administration","type":"tags"},{"content":" Introduction # Webmin is a powerful and intuitive web-based interface for managing Unix-like systems, including Ubuntu. This guide will walk you through the steps to install Webmin on your system.\nSetting up the Repository # Setup # The simplest and best way to get Webmin is to use automatic webmin-setup-repo.sh script to configure repositories on your RHEL or Debian derivative systems. It can be done in two easy steps:\ncurl -o webmin-setup-repo.sh https://raw.githubusercontent.com/webmin/webmin/master/webmin-setup-repo.sh After that has downloaded. run the following command:\nsudo sh webmin-setup-repo.sh This script will automatically setup your repository and install our GPG keys on your system.\nInstall # If Webmin repository was setup using our webmin-setup-repo.sh as described above then Webmin can be installed as easy as:\nsudo apt-get install webmin --install-recommends Access # After successful Webmin installation, you can access its interface by entering https://\u0026lt;Your-Server-IP\u0026gt;:10000 in your browser. Check that your firewall configuration allows access through port 10000.\nConclusion # You have successfully installed Webmin on your Ubuntu system. Remember to replace your-ubuntu-server-ip with the actual IP address of your server and access it using a secure connection (HTTPS).\nNote: Make sure you have a valid SSH key or password set up for root user, as Webmin requires authentication.\n","date":"15 March 2025","externalUrl":null,"permalink":"/posts/installing-webmin/","section":"Posts","summary":"","title":"Installing Webmin","type":"posts"},{"content":"","date":"15 March 2025","externalUrl":null,"permalink":"/tags/system-management/","section":"Tags","summary":"","title":"System-Management","type":"tags"},{"content":"","date":"15 March 2025","externalUrl":null,"permalink":"/tags/web-interface/","section":"Tags","summary":"","title":"Web-Interface","type":"tags"},{"content":"","date":"15 March 2025","externalUrl":null,"permalink":"/tags/authentication/","section":"Tags","summary":"","title":"Authentication","type":"tags"},{"content":" Introduction # Public-key SSH authentication is much more secure than password-only login. This guide shows how to generate a key pair, install your public key on a Linux server, and safely disable password authentication.\nGenerate an SSH key pair on Windows # Run the following command in PowerShell:\nssh-keygen -t rsa -b 4096 Follow the prompts to save your keys. You can set an optional passphrase to protect the private key.\nCopy your public key to the Linux server # From PowerShell, copy your key to the target server:\ncat ~/.ssh/id_rsa.pub | ssh username@remote_host \u0026#34;mkdir -p ~/.ssh \u0026amp;\u0026amp; cat \u0026gt;\u0026gt; ~/.ssh/authorized_keys\u0026#34; Replace username@remote_host with your actual SSH username and host.\nConfigure the SSH daemon for key-based authentication # Back up and update the SSH daemon configuration.\nBack up the original config (optional but recommended):\nsudo cp /etc/ssh/sshd_config /etc/ssh/sshd_config.bak Apply key-based auth settings:\nsudo sed -i \u0026#39;s/^#*PasswordAuthentication.*/PasswordAuthentication no/\u0026#39; /etc/ssh/sshd_config sudo sed -i \u0026#39;s/^#*PubkeyAuthentication.*/PubkeyAuthentication yes/\u0026#39; /etc/ssh/sshd_config sudo sed -i \u0026#39;s/^#*PermitRootLogin.*/PermitRootLogin no/\u0026#39; /etc/ssh/sshd_config This sets the PasswordAuthentication, PubkeyAuthentication, and PermitRootLogin values required for key-based authentication.\nAdd any missing directives if sed did not find them (this can usually be skipped):\ngrep -q \u0026#39;^PasswordAuthentication\u0026#39; /etc/ssh/sshd_config || echo \u0026#39;PasswordAuthentication no\u0026#39; \u0026gt;\u0026gt; /etc/ssh/sshd_config grep -q \u0026#39;^PubkeyAuthentication\u0026#39; /etc/ssh/sshd_config || echo \u0026#39;PubkeyAuthentication yes\u0026#39; \u0026gt;\u0026gt; /etc/ssh/sshd_config grep -q \u0026#39;^PermitRootLogin\u0026#39; /etc/ssh/sshd_config || echo \u0026#39;PermitRootLogin no\u0026#39; \u0026gt;\u0026gt; /etc/ssh/sshd_config You can manually inspect the file if needed:\nsudo nano /etc/ssh/sshd_config Restart SSH to apply the changes:\nsudo systemctl restart ssh Ground-truth effective SSH settings # Do not rely only on file contents. Ask ssh which values are actually active:\nsudo sshd -T | grep -E \u0026#34;passwordauthentication|permitrootlogin|kbdinteractiveauthentication\u0026#34; Expected output should include:\npasswordauthentication no permitrootlogin no kbdinteractiveauthentication no Check override files if values are not correct # If the output is not as expected, another file is overriding your settings, usually under /etc/ssh/sshd_config.d/.\nExample file to edit:\nsudo nano /etc/ssh/sshd_config.d/50-cloud-init.conf Inside that file, set:\nPasswordAuthentication no PermitRootLogin no Then restart and verify again:\nsudo systemctl restart ssh sudo sshd -T | grep -E \u0026#34;passwordauthentication|permitrootlogin|kbdinteractiveauthentication\u0026#34; Safety test before disconnecting # From a new local terminal, confirm password login is blocked:\nssh -o PreferredAuthentications=password -o PubkeyAuthentication=no user@remote_host Expected result:\nPermission denied (publickey) If you still get a password prompt, keep your existing session open, fix the override file, and test again.\nConclusion # Your server is now configured for public-key SSH authentication with password logins disabled. This significantly reduces brute-force and credential-guessing risk while keeping remote access reliable.\n","date":"15 March 2025","externalUrl":null,"permalink":"/posts/securing-ssh-login-with-public-keys/","section":"Posts","summary":"","title":"How to Harden SSH on Ubuntu with Public Key Authentication","type":"posts"},{"content":"","date":"15 March 2025","externalUrl":null,"permalink":"/tags/passwordless-login/","section":"Tags","summary":"","title":"Passwordless-Login","type":"tags"},{"content":"","date":"15 March 2025","externalUrl":null,"permalink":"/tags/public-key/","section":"Tags","summary":"","title":"Public-Key","type":"tags"},{"content":"","date":"15 March 2025","externalUrl":null,"permalink":"/tags/security-hardening/","section":"Tags","summary":"","title":"Security-Hardening","type":"tags"},{"content":"","date":"15 March 2025","externalUrl":null,"permalink":"/tags/ssh/","section":"Tags","summary":"","title":"Ssh","type":"tags"},{"content":"","date":"15 March 2025","externalUrl":null,"permalink":"/tags/apache/","section":"Tags","summary":"","title":"Apache","type":"tags"},{"content":"","date":"15 March 2025","externalUrl":null,"permalink":"/tags/brute-force-protection/","section":"Tags","summary":"","title":"Brute-Force-Protection","type":"tags"},{"content":"","date":"15 March 2025","externalUrl":null,"permalink":"/tags/intrusion-prevention/","section":"Tags","summary":"","title":"Intrusion-Prevention","type":"tags"},{"content":" Introduction # Fail2Ban is an excellent tool for protecting your server from brute-force login attempts, DoS (Denial of Service) attacks, and other malicious activities. This guide will walk you through the steps to install and configure Fail2Ban on Ubuntu.\nInstallation # To install Fail2Ban, run the following command:\nsudo apt update \u0026amp;\u0026amp; sudo apt install fail2ban Configuration # 1. Edit the Fail2Ban configuration file # sudo nano /etc/fail2ban/jail.conf 2. Configure the loglevel and maxretry settings: # [DEFAULT] loglevel = INFO maxretry = 3 3. Add filters for common services (e.g., SSH, Apache): # sudo nano /etc/fail2ban/filter.d/ssh.conf # Configure the filter for SSH login attempts [Definition] # Option: failregex # Value: REGEX to match the password failures, ignoring any whitespace # Format: ^\u0026lt;host\u0026gt; - Failed password for \u0026lt;user\u0026gt; from \u0026lt;ip\u0026gt; via PAM failregex = ^\u0026lt;host\u0026gt; - Failed password for \u0026lt;user\u0026gt; from \u0026lt;ip\u0026gt; via PAM # Option: bantime # Value: Time in seconds, or a string with time units (e.g. \u0026#34;1m\u0026#34;, \u0026#34;2h\u0026#34;) bantime = 3600 # Option: findtime # Value: Time in seconds, or a string with time units (e.g. \u0026#34;1m\u0026#34;, \u0026#34;2h\u0026#34;) findtime = 600 # Option: maxretry # Value: Number of authorized login attempts failed before ban maxretry = 3 4. Add jail definitions for common services: # sudo nano /etc/fail2ban/jail.d/ssh.conf [sshd] enabled = true port = ssh filter = sshd logpath = /var/log/auth.log maxretry = 3 Restarting Fail2Ban # sudo systemctl restart fail2ban Checking Status and Banned IP Addresses # sudo fail2ban-client status sudo fail2ban-client get sshd banip Conclusion # You have successfully set up Fail2Ban on Ubuntu. Remember to monitor the logs and adjust your configuration as needed.\n","date":"15 March 2025","externalUrl":null,"permalink":"/posts/setting-up-fail2ban/","section":"Posts","summary":"","title":"Setting Up Fail2Ban for Secure Server Protection","type":"posts"},{"content":"","date":"12 March 2025","externalUrl":null,"permalink":"/tags/configuration/","section":"Tags","summary":"","title":"Configuration","type":"tags"},{"content":"","date":"12 March 2025","externalUrl":null,"permalink":"/tags/ntp/","section":"Tags","summary":"","title":"Ntp","type":"tags"},{"content":" Introduction # Setting the correct timezone ensures logs, schedules, and timestamps are accurate. This guide shows how to set the timezone to Europe/London and configure NTP on Ubuntu.\nCheck Current Time Settings # timedatectl status Set the Timezone # Set the timezone with:\nsudo timedatectl set-timezone Europe/London Verify the Timezone Change # Confirm the change:\ntimedatectl status The output should indicate that the timezone is set to Europe/London.\nNTP Time Configuration # Ubuntu 26.04 (Chrony) # Create a custom source file:\nsudo nano /etc/chrony/sources.d/custom.sources Add pool servers:\npool 0.pool.ntp.org iburst pool 1.pool.ntp.org iburst pool 2.pool.ntp.org iburst pool 3.pool.ntp.org iburst Verify the main Chrony config includes sourcedir /etc/chrony/sources.d:\ngrep \u0026#34;sourcedir\u0026#34; /etc/chrony/chrony.conf If it returns nothing, add this line to the end of /etc/chrony/chrony.conf:\nsourcedir /etc/chrony/sources.d Bring Chrony online and restart it:\nsudo chronyc online sudo systemctl restart chrony Check Chrony sources:\nchronyc sources -v Enable NTP:\nsudo timedatectl set-ntp true This method is useful because custom source files are easier to maintain and are less likely to be overwritten by package updates.\nUbuntu 24.04 (systemd-timesyncd) # Edit the configuration file:\nsudo nano /etc/systemd/timesyncd.conf Under the [Time] section, add:\nNTP=0.pool.ntp.org 1.pool.ntp.org 2.pool.ntp.org 3.pool.ntp.org Then enable NTP:\nsudo timedatectl set-ntp true Example Output # Example timedatectl status output:\nLocal time: Wed 2025-03-12 21:24:32 GMT Universal time: Wed 2025-03-12 21:24:32 UTC RTC time: Wed 2025-03-12 21:24:32 Time zone: Europe/London (GMT, +0000) System clock synchronized: yes NTP service: active RTC in local TZ: no If everything is working correctly, the timezone should be set to Europe/London.\nConclusion # You have now set the system timezone and configured NTP synchronization on Ubuntu. Verify time synchronization after making changes, especially on servers and systems that rely on accurate logs.\n","date":"12 March 2025","externalUrl":null,"permalink":"/posts/setting-up-timezone-and-ntp/","section":"Posts","summary":"","title":"Setting Up Timezone and NTP on Ubuntu","type":"posts"},{"content":"","date":"12 March 2025","externalUrl":null,"permalink":"/tags/time-sync/","section":"Tags","summary":"","title":"Time-Sync","type":"tags"},{"content":"","date":"12 March 2025","externalUrl":null,"permalink":"/tags/timezone/","section":"Tags","summary":"","title":"Timezone","type":"tags"},{"content":"","date":"8 March 2025","externalUrl":null,"permalink":"/tags/automation/","section":"Tags","summary":"","title":"Automation","type":"tags"},{"content":"","date":"8 March 2025","externalUrl":null,"permalink":"/tags/maintenance/","section":"Tags","summary":"","title":"Maintenance","type":"tags"},{"content":" Introduction # This guide will walk you through the steps to update and upgrade your Ubuntu system, configure unattended upgrades for automatic updates, and adjust settings to prevent automatic reboots during upgrades. By following these steps, you can ensure your system remains up-to-date and secure without manual intervention.\nUpdate and Upgrade # First, update the package lists:\nsudo apt-get update Then, upgrade all installed packages:\nsudo apt-get upgrade Reconfigure Unattended Upgrades # To reconfigure unattended upgrades for automatic updates, run:\nsudo dpkg-reconfigure --priority=low unattended-upgrades Verify Configuration # Verify the configuration file for unattended upgrades using your text editor of choice:\n/etc/apt/apt.conf.d/20auto-upgrades Disable Automatic Reboots # To disable automatic reboots during upgrades, edit the following file:\n/etc/apt/apt.conf.d/50unattended-upgrades Uncomment the line by removing the leading slashes:\n//Unattended-Upgrade::Automatic-Reboot \u0026#34;false\u0026#34;; This will prevent automatic reboots after updates.\n","date":"8 March 2025","externalUrl":null,"permalink":"/posts/ubuntu-updates/","section":"Posts","summary":"","title":"Ubuntu Updates","type":"posts"},{"content":"","date":"8 March 2025","externalUrl":null,"permalink":"/tags/unattended-upgrades/","section":"Tags","summary":"","title":"Unattended-Upgrades","type":"tags"},{"content":"","date":"8 March 2025","externalUrl":null,"permalink":"/tags/updates/","section":"Tags","summary":"","title":"Updates","type":"tags"},{"content":"","date":"8 March 2025","externalUrl":null,"permalink":"/tags/access-control/","section":"Tags","summary":"","title":"Access-Control","type":"tags"},{"content":" Introduction # visudo is a command-line utility used to safely edit the sudoers file, which controls user privileges for executing commands as the root user. It ensures that the file is properly formatted before saving changes, preventing syntax errors that could lock users out of administrative privileges.\nUsage # To edit the sudoers file, run:\nsudo visudo Editing Sudo Privileges # To make the necessary changes, edit the following lines.\nBefore Modification # By default, users in the sudo group must enter a password when executing commands with sudo:\n%sudo ALL=(ALL) ALL After Modification # To allow sudo group members to execute commands without a password prompt, change the entry to:\n%sudo ALL=(ALL) NOPASSWD: ALL Note that this will disable the password requirement for users in the sudo group. Be cautious when making changes to sudo privileges.\nConclusion # You have successfully edited the sudo privileges using visudo. Be sure to test the changes by running a command with sudo to ensure that it works as expected.\n","date":"8 March 2025","externalUrl":null,"permalink":"/posts/visudo_setup/","section":"Posts","summary":"","title":"Managing Sudo Privileges with Visudo","type":"posts"},{"content":"","date":"8 March 2025","externalUrl":null,"permalink":"/tags/permissions/","section":"Tags","summary":"","title":"Permissions","type":"tags"},{"content":" Installing Docker on an Ubuntu System # Docker is a powerful platform for developing, shipping, and running applications in containers. This guide will walk you through setting up Docker\u0026rsquo;s apt repository and installing it on an Ubuntu system.\nPrerequisites # Ubuntu 20.04+ (or a later version) User account with sudo privileges Stable internet connection Step 1: Update Package Index # First, update the package list to ensure you have the latest information:\nsudo apt update \u0026amp;\u0026amp; sudo apt upgrade -y Step 2: Install Required Dependencies # Install necessary packages to allow apt to use a repository over HTTPS:\nsudo apt install -y ca-certificates curl Step 3: Add Docker\u0026rsquo;s Official GPG Key # Set up the directory for key storage, download Docker’s official GPG key, and set correct permissions:\nsudo install -m 0755 -d /etc/apt/keyrings sudo curl -fsSL https://download.docker.com/linux/ubuntu/gpg -o /etc/apt/keyrings/docker.asc sudo chmod a+r /etc/apt/keyrings/docker.asc Step 4: Add the Repository to Apt Sources # Add Docker’s stable repository to your system’s package sources:\necho \\ \u0026#34;deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.asc] https://download.docker.com/linux/ubuntu \\ $(. /etc/os-release \u0026amp;\u0026amp; echo \u0026#34;${UBUNTU_CODENAME:-$VERSION_CODENAME}\u0026#34;) stable\u0026#34; | \\ sudo tee /etc/apt/sources.list.d/docker.list \u0026gt; /dev/null Update the package list again:\nsudo apt update Step 5: Install Docker Engine # To install the latest version of Docker, run:\nsudo apt install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin Step 6: Verify Docker Installation # Check if Docker is installed correctly by running:\ndocker --version To test if Docker is working properly, run the hello-world container:\nsudo docker run hello-world Step 7: Manage Docker as a Non-Root User (Optional) # To avoid using sudo every time you run Docker, add your user to the docker group:\nsudo usermod -aG docker $USER Log out and back in, or run:\nnewgrp docker Step 8: Enable Docker to Start on Boot # Ensure Docker starts automatically on system boot:\nsudo systemctl enable docker \u0026amp;\u0026amp; sudo systemctl start docker Uninstalling Docker (If Needed) # If you need to remove Docker, use the following command:\nsudo apt remove -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin \u0026amp;\u0026amp; sudo apt autoremove -y If you also want to delete all Docker data (containers, images, volumes, etc.), run:\nsudo rm -rf /var/lib/docker sudo rm -rf /var/lib/containerd This will completely remove Docker from your system.\nConclusion # You have successfully installed Docker on your Ubuntu system. You can now start using Docker to create, manage, and run containers efficiently.\nFor more information, visit the official Docker documentation:\nDocker Installation Guide\n","date":"1 March 2025","externalUrl":null,"permalink":"/posts/docker_installation/","section":"Posts","summary":"","title":"Docker Installation on Ubuntu","type":"posts"},{"content":"","date":"20 February 2025","externalUrl":null,"permalink":"/tags/docker-compose/","section":"Tags","summary":"","title":"Docker-Compose","type":"tags"},{"content":" My Gluetun Setup # This setup uses qmcgaw/gluetun in Docker to route traffic through a secure VPN tunnel. It also enables an HTTP proxy and Shadowsocks, which gives you flexible options for private networking across your self-hosted services.\nMy Docker Compose Configuration # The first example below is a focused Gluetun-only setup.\nservices: gluetun: container_name: gluetun # Container name image: qmcgaw/gluetun # Gluetun image cap_add: - NET_ADMIN # Required to manage VPN networking ports: - \u0026#34;8888:8888/tcp\u0026#34; # HTTP proxy - \u0026#34;8388:8388/tcp\u0026#34; # Shadowsocks - \u0026#34;8388:8388/udp\u0026#34; # Shadowsocks volumes: - ~/gluetun_vpn/config:/gluetun # Persistent Gluetun configuration environment: - HTTPPROXY=on # Enable built-in HTTP proxy - VPN_SERVICE_PROVIDER=protonvpn # VPN provider name - VPN_TYPE=wireguard # VPN protocol - WIREGUARD_PRIVATE_KEY=your_private_key_here # WireGuard private key - SERVER_COUNTRIES=Germany # VPN endpoint country filter - PORT_FORWARD_ONLY=on # Require servers that support port forwarding - VPN_PORT_FORWARDING=on # Enable VPN port forwarding restart: unless-stopped # Restart unless stopped manually The next example shows a combined stack where Gluetun is used alongside qBittorrent and SABnzbd.\nservices: gluetun: container_name: gluetun image: qmcgaw/gluetun cap_add: - NET_ADMIN ports: - 8888:8888/tcp # HTTP proxy - 8388:8388/tcp # Shadowsocks - 8388:8388/udp # Shadowsocks - 8080:8080 # sabnzbd Webui - 8443:8443 # Qbittorrent Webui volumes: - ~/gluetun_vpn/config:/gluetun environment: - HTTPPROXY=on - VPN_SERVICE_PROVIDER=protonvpn - VPN_TYPE=wireguard - WIREGUARD_PRIVATE_KEY=your_private_key_here - SERVER_COUNTRIES=Germany - PORT_FORWARD_ONLY=on - VPN_PORT_FORWARDING=on - VPN_PORT_FORWARDING_UP_COMMAND=/bin/sh -c \u0026#39;wget -O- --retry-connrefused --post-data \u0026#34;json={\\\u0026#34;listen_port\\\u0026#34;:{{PORTS}}}\u0026#34; http://127.0.0.1:8443/api/v2/app/setPreferences 2\u0026gt;\u0026amp;1\u0026#39; # Push forwarded port to qBittorrent restart: unless-stopped qbittorrent: image: lscr.io/linuxserver/qbittorrent:latest container_name: qbittorrent environment: - PUID=1000 - PGID=1000 - TZ=Europe/London - WEBUI_PORT=8443 volumes: - ~/qbittorrent/config:/config - ~/downloads:/downloads network_mode: \u0026#34;service:gluetun\u0026#34; restart: unless-stopped depends_on: - gluetun sabnzbd: image: lscr.io/linuxserver/sabnzbd:latest container_name: sabnzbd environment: - PUID=1000 - PGID=1000 - TZ=Europe/London volumes: - ~/sabnzbd/config:/config - ~/downloads:/downloads #optional network_mode: \u0026#34;service:gluetun\u0026#34; restart: unless-stopped depends_on: - gluetun Prepare the Downloads Folder # If you are using the combined stack above, create the downloads folder before starting the containers.\nsudo mkdir -p ~/downloads sudo chown -R 1000:1000 ~/downloads Using Docker Secrets for Environment Variables # You can load environment variables from files by prefixing the variable name with FILE__.\nFor example:\nFILE__MYVAR=/run/secrets/mysecretvariable ","date":"20 February 2025","externalUrl":null,"permalink":"/posts/gluetun_vpn/","section":"Posts","summary":"","title":"Gluetun VPN","type":"posts"},{"content":"","date":"20 February 2025","externalUrl":null,"permalink":"/tags/privacy/","section":"Tags","summary":"","title":"Privacy","type":"tags"},{"content":"","date":"19 February 2025","externalUrl":null,"permalink":"/tags/ai/","section":"Tags","summary":"","title":"Ai","type":"tags"},{"content":"","date":"19 February 2025","externalUrl":null,"permalink":"/tags/inference/","section":"Tags","summary":"","title":"Inference","type":"tags"},{"content":"","date":"19 February 2025","externalUrl":null,"permalink":"/tags/llm/","section":"Tags","summary":"","title":"Llm","type":"tags"},{"content":" My LocalAI Setup # This LocalAI setup runs in a Docker container and provides a self-hosted AI model server that can be utilized for running machine learning models locally. The setup includes features such as health checks, volume mounts, and easy-to-configure environment variables for your project.\nMy Docker Compose Configuration # services: api: image: localai/localai:latest-aio-cpu # CPU version # For a specific version: # image: localai/localai:v2.16.0-aio-cpu # For Nvidia GPUs, uncomment one of the following lines (cuda11 or cuda12): # image: localai/localai:v2.16.0-aio-gpu-nvidia-cuda-11 # image: localai/localai:v2.16.0-aio-gpu-nvidia-cuda-12 # image: localai/localai:latest-aio-gpu-nvidia-cuda-11 # image: localai/localai:latest-aio-gpu-nvidia-cuda-12 healthcheck: test: [\u0026#34;CMD\u0026#34;, \u0026#34;curl\u0026#34;, \u0026#34;-f\u0026#34;, \u0026#34;http://localhost:8080/readyz\u0026#34;] # Health check for API readiness interval: 1m # Interval between health checks timeout: 20m # Timeout for the health check retries: 5 # Number of retries before failing ports: - \u0026#34;8300:8080\u0026#34; # Expose port 8080 to 8300 for local access environment: - DEBUG=true # Enables debug mode # Add more environment variables as needed volumes: - ~/local-ai/config/models:/build/models:cached # Mount models directory for persistent storage # Uncomment below if running with Nvidia GPUs # deploy: # resources: # reservations: # devices: # - driver: nvidia # count: 1 # capabilities: [gpu] # GPU configuration ","date":"19 February 2025","externalUrl":null,"permalink":"/posts/local-ai/","section":"Posts","summary":"","title":"Local-AI","type":"posts"},{"content":"","date":"19 February 2025","externalUrl":null,"permalink":"/tags/machine-learning/","section":"Tags","summary":"","title":"Machine-Learning","type":"tags"},{"content":"","date":"19 February 2025","externalUrl":null,"permalink":"/tags/media-automation/","section":"Tags","summary":"","title":"Media-Automation","type":"tags"},{"content":"","date":"19 February 2025","externalUrl":null,"permalink":"/tags/media-library/","section":"Tags","summary":"","title":"Media-Library","type":"tags"},{"content":"","date":"19 February 2025","externalUrl":null,"permalink":"/tags/movies/","section":"Tags","summary":"","title":"Movies","type":"tags"},{"content":" My Radarr Setup # This Radarr setup runs in a Docker container and is used to manage movie downloads. It includes configurations for environment variables, volume mounts, and networking.\nPrepare the Downloads Folder # sudo mkdir -p ~/downloads sudo chown -R 1000:1000 ~/downloads My Docker Compose Configuration # services: radarr: image: lscr.io/linuxserver/radarr:latest container_name: radarr environment: - PUID=1000 - PGID=1000 - TZ=Europe/London volumes: - ~/radarr/config:/config - ~/downloads:/downloads - /mnt/main_nas/movies:/main_nas/movies # optional - /mnt/sean_nas/movies:/sean_nas/movies # optional ports: - \u0026#34;7878:7878\u0026#34; restart: unless-stopped Using Docker Secrets for Environment Variables # You can set any environment variable from a file by using a special prepend FILE__.\nFor example:\nFILE__MYVAR=/run/secrets/mysecretvariable ","date":"19 February 2025","externalUrl":null,"permalink":"/posts/radarr/","section":"Posts","summary":"","title":"Radarr","type":"posts"},{"content":"","date":"19 February 2025","externalUrl":null,"permalink":"/tags/indexer/","section":"Tags","summary":"","title":"Indexer","type":"tags"},{"content":" My Prowlarr Setup # This Prowlarr setup runs in a Docker container and is used to manage indexers for your media downloaders (e.g., Radarr, Sonarr). It includes configurations for environment variables, volume mounts, and networking.\nMy Docker Compose Configuration # services: prowlarr: image: lscr.io/linuxserver/prowlarr:latest # Prowlarr latest image container_name: prowlarr # Container name for identification environment: - PUID=0 # Set user ID (root user) - PGID=0 # Set group ID (root group) - TZ=Europe/London # Set timezone volumes: - ~/prowlarr/config:/config # Mount the configuration directory ports: - \u0026#34;9696:9696\u0026#34; # Expose port 9696 for the Prowlarr web interface restart: unless-stopped # Restart the container unless stopped manually ","date":"19 February 2025","externalUrl":null,"permalink":"/posts/prowlarr/","section":"Posts","summary":"","title":"Prowlarr","type":"posts"},{"content":"","date":"19 February 2025","externalUrl":null,"permalink":"/tags/downloader/","section":"Tags","summary":"","title":"Downloader","type":"tags"},{"content":"","date":"19 February 2025","externalUrl":null,"permalink":"/tags/p2p/","section":"Tags","summary":"","title":"P2p","type":"tags"},{"content":" My qBittorrent Setup # This qBittorrent setup runs in a Docker container and is used to manage downloads via the qBittorrent web UI. It includes configurations for environment variables, volume mounts, and networking.\nPrepare the Downloads Folder # sudo mkdir -p ~/downloads sudo chown -R 1000:1000 ~/downloads My Docker Compose Configuration # services: qbittorrent: image: lscr.io/linuxserver/qbittorrent:latest container_name: qbittorrent environment: - PUID=1000 - PGID=1000 - TZ=Europe/London - WEBUI_PORT=8443 volumes: - ~/qbittorrent/config:/config - ~/downloads:/downloads ports: - \u0026#34;8443:8443\u0026#34; - \u0026#34;6881:6881\u0026#34; - \u0026#34;6881:6881/udp\u0026#34; restart: unless-stopped Using Docker Secrets for Environment Variables # You can set any environment variable from a file by using a special prepend FILE__.\nFor example:\nFILE__MYVAR=/run/secrets/mysecretvariable ","date":"19 February 2025","externalUrl":null,"permalink":"/posts/qbittorent/","section":"Posts","summary":"","title":"Qbittorrent","type":"posts"},{"content":"","date":"19 February 2025","externalUrl":null,"permalink":"/tags/torrent/","section":"Tags","summary":"","title":"Torrent","type":"tags"},{"content":" My Sonarr Setup # This Sonarr setup runs in a Docker container and is used to manage TV series downloads. It includes configurations for environment variables, volume mounts, and networking.\nPrepare the Downloads Folder # sudo mkdir -p ~/downloads sudo chown -R 1000:1000 ~/downloads My Docker Compose Configuration # services: sonarr: image: lscr.io/linuxserver/sonarr:latest container_name: sonarr environment: - PUID=1000 - PGID=1000 - TZ=Europe/London volumes: - ~/sonarr/config:/config - ~/downloads:/downloads - /mnt/main_nas/tv_shows:/main_nas/tv # optional - /mnt/sean_nas/tv_shows:/sean_nas/tv # optional ports: - \u0026#34;8989:8989\u0026#34; restart: unless-stopped Using Docker Secrets for Environment Variables # You can set any environment variable from a file by using a special prepend FILE__.\nFor example:\nFILE__MYVAR=/run/secrets/mysecretvariable ","date":"19 February 2025","externalUrl":null,"permalink":"/posts/sonarr/","section":"Posts","summary":"","title":"Sonarr","type":"posts"},{"content":"","date":"19 February 2025","externalUrl":null,"permalink":"/tags/tv-shows/","section":"Tags","summary":"","title":"Tv-Shows","type":"tags"},{"content":"","date":"19 February 2025","externalUrl":null,"permalink":"/tags/backup/","section":"Tags","summary":"","title":"Backup","type":"tags"},{"content":" My Immich Setup # This Immich setup runs in a Docker container to provide a self-hosted photo and video management solution. It includes essential services such as the Immich server, machine learning module, Redis, and PostgreSQL database.\nMy Docker Compose Configuration # services: immich-server: container_name: immich_server # Immich main API/web service image: ghcr.io/immich-app/immich-server:${IMMICH_VERSION:-release} # Immich server image volumes: - ${UPLOAD_LOCATION}:/usr/src/app/upload # Original uploads - ${THUMB_LOCATION}:/usr/src/app/upload/thumbs # Generated thumbnails - ${ENCODED_VIDEO_LOCATION}:/usr/src/app/upload/encoded-video # Transcoded videos - ${PROFILE_LOCATION}:/usr/src/app/upload/profile # User profile images - ${BACKUP_LOCATION}:/usr/src/app/upload/backups # Application backup artifacts - /etc/localtime:/etc/localtime:ro # Use host timezone env_file: - .env # Load environment variables from .env file ports: - \u0026#34;2283:2283\u0026#34; # Immich web/API port depends_on: - redis # Cache/message broker service - database # PostgreSQL database service restart: always # Always restart on failure or reboot healthcheck: disable: false immich-machine-learning: container_name: immich_machine_learning # ML inference service image: ghcr.io/immich-app/immich-machine-learning:${IMMICH_VERSION:-release} # ML service image volumes: - model-cache:/cache # Cache downloaded ML models env_file: - .env # Load shared environment values restart: always # Always restart on failure or reboot healthcheck: disable: false redis: container_name: immich_redis # Redis cache service image: docker.io/redis:6.2-alpine@sha256:2ba50e1ac3a0ea17b736ce9db2b0a9f6f8b85d4c27d5f5accc6a416d8f42c6d5 # Pinned Redis image healthcheck: test: redis-cli ping || exit 1 # Basic Redis health probe restart: always # Always restart on failure or reboot database: container_name: immich_postgres # PostgreSQL database service image: docker.io/tensorchord/pgvecto-rs:pg14-v0.2.0@sha256:90724186f0a3517cf6914295b5ab410db9ce23190a2d9d0b9dd6463e3fa298f0 # Postgres with vector extension environment: POSTGRES_PASSWORD: ${DB_PASSWORD} # Database password POSTGRES_USER: ${DB_USERNAME} # Database user POSTGRES_DB: ${DB_DATABASE_NAME} # Database name POSTGRES_INITDB_ARGS: \u0026#34;--data-checksums\u0026#34; # Enable data checksums at init volumes: - ${DB_DATA_LOCATION}:/var/lib/postgresql/data # Persistent database data healthcheck: test: pg_isready --dbname=\u0026#39;${DB_DATABASE_NAME}\u0026#39; --username=\u0026#39;${DB_USERNAME}\u0026#39; || exit 1 # Check DB readiness interval: 5m start_interval: 30s start_period: 5m command: [ \u0026#34;postgres\u0026#34;, \u0026#34;-c\u0026#34;, \u0026#34;shared_preload_libraries=vectors.so\u0026#34;, \u0026#34;-c\u0026#34;, \u0026#34;search_path=$$user, public, vectors\u0026#34;, \u0026#34;-c\u0026#34;, \u0026#34;logging_collector=on\u0026#34;, \u0026#34;-c\u0026#34;, \u0026#34;max_wal_size=2GB\u0026#34;, \u0026#34;-c\u0026#34;, \u0026#34;shared_buffers=512MB\u0026#34;, \u0026#34;-c\u0026#34;, \u0026#34;wal_compression=on\u0026#34;, ] restart: always # Always restart on failure or reboot volumes: model-cache: # Named volume for ML model cache Immich Environment Variables Configuration # You can find documentation for all the supported environment variables in the official Immich documentation.\nConfiguration Variables # UPLOAD_LOCATION:\nThe location where your uploaded files are stored.\nDefault: ./library\nDB_DATA_LOCATION:\nThe location where your database files are stored.\nDefault: ./postgres\nTZ:\nThe timezone setting for Immich. Uncomment the next line and change Etc/UTC to a valid timezone identifier from this list.\nExample:\nTZ=Europe/London\nIMMICH_VERSION:\nThe version of Immich to use.\nDefault: release\nYou can pin it to a specific version like \u0026quot;v1.71.0\u0026quot;.\nDB_PASSWORD:\nThe connection secret for PostgreSQL.\nChange this to a random password for security.\nEnsure that only A-Za-z0-9 characters are used, without special characters or spaces.\nExample:\nDB_PASSWORD=yourSecurePassword\nDefault Database Credentials # The following credentials do not need to be changed unless you want to customize the setup:\nDB_USERNAME: postgres DB_DATABASE_NAME: immich Documentation Links # Immich Environment Variables Documentation This configuration ensures your Immich instance has the correct settings for file storage, database credentials, timezone, and version control.\n","date":"19 February 2025","externalUrl":null,"permalink":"/posts/immich-app/","section":"Posts","summary":"","title":"Immich Photo \u0026 Video Management","type":"posts"},{"content":"","date":"19 February 2025","externalUrl":null,"permalink":"/tags/photo-management/","section":"Tags","summary":"","title":"Photo-Management","type":"tags"},{"content":"","date":"19 February 2025","externalUrl":null,"permalink":"/tags/video-management/","section":"Tags","summary":"","title":"Video-Management","type":"tags"},{"content":"","date":"19 February 2025","externalUrl":null,"permalink":"/tags/dashboard/","section":"Tags","summary":"","title":"Dashboard","type":"tags"},{"content":" My Heimdall Setup # This Heimdall setup runs in a Docker container using the official LinuxServer.io Heimdall image. Heimdall serves as a dashboard for organizing and managing self-hosted services.\nMy Docker Compose Configuration # services: heimdall: image: lscr.io/linuxserver/heimdall:latest # Heimdall image container_name: heimdall # Container name environment: - PUID=1000 # User ID for file permissions - PGID=1000 # Group ID for file permissions - TZ=Europe/London # Container timezone volumes: - ~/heimdall/config:/config # Persistent app configuration ports: - \u0026#34;7888:80\u0026#34; # HTTP access - \u0026#34;4433:443\u0026#34; # HTTPS access restart: unless-stopped # Restart unless stopped manually Using Docker Secrets for Environment Variables # You can set any environment variable from a file by using a special prepend FILE__.\nFor example:\nFILE__MYVAR=/run/secrets/mysecretvariable ","date":"19 February 2025","externalUrl":null,"permalink":"/posts/heimdall/","section":"Posts","summary":"","title":"Heimdall Dashboard","type":"posts"},{"content":"","date":"19 February 2025","externalUrl":null,"permalink":"/tags/home-automation/","section":"Tags","summary":"","title":"Home-Automation","type":"tags"},{"content":"","date":"19 February 2025","externalUrl":null,"permalink":"/tags/meal-planning/","section":"Tags","summary":"","title":"Meal-Planning","type":"tags"},{"content":" My Mealie Setup # This Mealie setup runs in a Docker container and provides a self-hosted recipe and meal planning application. It includes configurations for backend environment variables, volume mounts, and resource limits.\nMy Docker Compose Configuration # services: mealie: image: ghcr.io/mealie-recipes/mealie:latest # Mealie latest image container_name: mealie # Container name for identification restart: always # Always restart the container on failure ports: - \u0026#34;9925:9000\u0026#34; # Expose port 9000 for the Mealie web interface deploy: resources: limits: memory: 1000M # Set memory limit to 1000MB volumes: - ~/mealie/config:/app/data/ # Mount the configuration directory environment: # Set Backend ENV Variables Here ALLOW_SIGNUP: true PUID: 1000 PGID: 1000 TZ: Europe/London MAX_WORKERS: 1 WEB_CONCURRENCY: 1 BASE_URL: Your Domain SMTP_HOST: Your SMTP Server host SMTP_PORT: 587 SMTP_FROM_NAME: Mealie SMTP_AUTH_STRATEGY: TLS SMTP_FROM_EMAIL: Your Email SMTP_USER: Your Username SMTP_PASSWORD: Your Password Using Docker Secrets for Environment Variables # You can set any environment variable from a file by using a special prepend FILE__.\nFor example:\nFILE__MYVAR=/run/secrets/mysecretvariable ","date":"19 February 2025","externalUrl":null,"permalink":"/posts/mealie/","section":"Posts","summary":"","title":"Mealie","type":"posts"},{"content":"","date":"19 February 2025","externalUrl":null,"permalink":"/tags/recipe-management/","section":"Tags","summary":"","title":"Recipe-Management","type":"tags"},{"content":"","date":"19 February 2025","externalUrl":null,"permalink":"/tags/web-app/","section":"Tags","summary":"","title":"Web-App","type":"tags"},{"content":"","date":"19 February 2025","externalUrl":null,"permalink":"/tags/data-protection/","section":"Tags","summary":"","title":"Data-Protection","type":"tags"},{"content":" My Duplicati Setup # This Duplicati setup runs in a Docker container using the official LinuxServer.io image. It is configured to operate on port 8200, making the web interface accessible for backup management.\nMy Docker Compose Configuration # services: duplicati: image: lscr.io/linuxserver/duplicati:latest # Duplicati image container_name: duplicati # Container name environment: - PUID=0 # User ID for permissions - PGID=0 # Group ID for permissions - TZ=Europe/London # Container timezone - SETTINGS_ENCRYPTION_KEY= (your secret password) # Encrypt Duplicati settings database volumes: - ~/duplicati/config:/config # Persistent Duplicati configuration - /mnt/main_nas/server_backups:/backups # Backup destination path - ~:/source # Source data to back up - /opt/bitwarden:/opt/bitwarden # Extra source path example ports: - \u0026#34;8200:8200\u0026#34; # Duplicati web interface restart: unless-stopped # Restart unless stopped manually Using Docker Secrets for Environment Variables # You can set any environment variable from a file by using a special prepend FILE__.\nFor example:\nFILE__MYVAR=/run/secrets/mysecretvariable ","date":"19 February 2025","externalUrl":null,"permalink":"/posts/duplicati/","section":"Posts","summary":"","title":"Duplicati Backup","type":"posts"},{"content":"","date":"19 February 2025","externalUrl":null,"permalink":"/tags/nzb/","section":"Tags","summary":"","title":"Nzb","type":"tags"},{"content":" My SABnzbd Setup # This SABnzbd setup runs in a Docker container and is used for managing NZB downloads. It includes configurations for environment variables, volume mounts, and networking.\nPrepare the Downloads Folder # sudo mkdir -p ~/downloads sudo chown -R 1000:1000 ~/downloads My Docker Compose Configuration # services: sabnzbd: image: lscr.io/linuxserver/sabnzbd:latest container_name: sabnzbd environment: - PUID=1000 - PGID=1000 - TZ=Europe/London volumes: - ~/sabnzbd/config:/config - ~/downloads:/downloads # optional ports: - \u0026#34;8080:8080\u0026#34; restart: unless-stopped Using Docker Secrets for Environment Variables # You can set any environment variable from a file by using a special prepend FILE__.\nFor example:\nFILE__MYVAR=/run/secrets/mysecretvariable ","date":"19 February 2025","externalUrl":null,"permalink":"/posts/sabnzbd/","section":"Posts","summary":"","title":"SABnzbd","type":"posts"},{"content":"","date":"19 February 2025","externalUrl":null,"permalink":"/tags/usenet/","section":"Tags","summary":"","title":"Usenet","type":"tags"},{"content":" About Me # I\u0026rsquo;m a tech enthusiast with a deep passion for homelabs and self-hosting. Over the years, I\u0026rsquo;ve built a home lab environment where I experiment with new technologies, automate tasks, and optimise my workflows — from running self-hosted services like media management and file storage, to containerisation with Docker.\nThis site is where I document everything I learn along the way.\nWhat You\u0026rsquo;ll Find Here # Topic Covers Docker Compose Step-by-step setups for self-hosted apps Linux Administration System config, security hardening, SSH, sudo, and more Networking \u0026amp; Storage CIFS mounts, VPNs, and network optimisation Media Stack Plex, Sonarr, Radarr, Prowlarr, SABnzbd, and qBittorrent Tech Stack # Category Tools Infrastructure Ubuntu Server, Docker \u0026amp; Docker Compose, Portainer Networking \u0026amp; Security pfSense, HAProxy, Gluetun VPN, Fail2Ban Home Automation Home Assistant Media Plex, Sonarr, Radarr, Prowlarr, SABnzbd, qBittorrent Self-Hosted Apps Immich, Mealie, Duplicati, Heimdall, Webmin Monitoring \u0026amp; Management Uptime Kuma, Local-AI ","externalUrl":null,"permalink":"/about/","section":"Sean's Tech Notes","summary":"","title":"About","type":"page"}]