<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Reginald F. Johnson</title>
    <description>The latest articles on DEV Community by Reginald F. Johnson (@reggiejohnson86).</description>
    <link>https://dev.to/reggiejohnson86</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F865913%2Fc18f8c0a-460d-451f-a6db-b71092c880ba.jpg</url>
      <title>DEV Community: Reginald F. Johnson</title>
      <link>https://dev.to/reggiejohnson86</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/reggiejohnson86"/>
    <language>en</language>
    <item>
      <title>Keep your Ubuntu‑based VPN Server Updated</title>
      <dc:creator>Reginald F. Johnson</dc:creator>
      <pubDate>Tue, 30 Dec 2025 20:10:57 +0000</pubDate>
      <link>https://dev.to/reggiejohnson86/keep-your-ubuntu-based-vpn-server-updated-11al</link>
      <guid>https://dev.to/reggiejohnson86/keep-your-ubuntu-based-vpn-server-updated-11al</guid>
      <description>&lt;h2&gt;
  
  
  🔄 Automate Monthly System Updates on Ubuntu 24.04
&lt;/h2&gt;

&lt;p&gt;&lt;em&gt;A simple, reliable way to keep your Ubuntu‑based VPN server fully updated.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;This guide shows you how to create an update script, schedule it to run monthly, optionally reboot afterward, and verify everything is working.&lt;/p&gt;




&lt;h2&gt;
  
  
  📝 Step 1: Create the Update Script
&lt;/h2&gt;

&lt;p&gt;First, create the script file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;nano /usr/local/bin/auto-update.sh
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Paste the following into the file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;#!/bin/bash&lt;/span&gt;
&lt;span class="c"&gt;# Update package lists and upgrade everything&lt;/span&gt;
apt-get update &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; apt-get dist-upgrade &lt;span class="nt"&gt;-y&lt;/span&gt;

&lt;span class="c"&gt;# Clean up old files&lt;/span&gt;
apt-get autoremove &lt;span class="nt"&gt;-y&lt;/span&gt;
apt-get autoclean

&lt;span class="c"&gt;# Log completion time&lt;/span&gt;
&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"Full system update completed on &lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;date&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; /var/log/sys_update.log
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Make the script executable:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo chmod&lt;/span&gt; +x /usr/local/bin/auto-update.sh
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  ⏱️ Step 2: Schedule Monthly Updates with Cron
&lt;/h2&gt;

&lt;p&gt;Open the root crontab:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;crontab &lt;span class="nt"&gt;-e&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Add this line at the bottom:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;0 3 1 &lt;span class="k"&gt;*&lt;/span&gt; &lt;span class="k"&gt;*&lt;/span&gt; /usr/local/bin/auto-update.sh
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This runs the update script &lt;strong&gt;at 3:00 AM on the 1st day of every month&lt;/strong&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  🔁 Step 3 (Optional): Enable Auto‑Reboot
&lt;/h2&gt;

&lt;p&gt;If you want the server to reboot after updates:&lt;/p&gt;

&lt;p&gt;Open the script again:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;nano /usr/local/bin/auto-update.sh
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Add this line at the very bottom:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;/sbin/reboot
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Save and exit.&lt;/p&gt;




&lt;h2&gt;
  
  
  ✅ Step 4: Verify Everything
&lt;/h2&gt;

&lt;p&gt;Check your scheduled cron jobs:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;crontab &lt;span class="nt"&gt;-l&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Check the update log:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;cat&lt;/span&gt; /var/log/sys_update.log
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you see timestamps, your automated updates are working correctly.&lt;/p&gt;




&lt;h2&gt;
  
  
  🎉 Done!
&lt;/h2&gt;

&lt;p&gt;Your Ubuntu 24.04 VPN server will now stay updated, clean, and low‑maintenance with almost no effort.&lt;/p&gt;

</description>
      <category>ubuntu</category>
      <category>linux</category>
      <category>vpn</category>
      <category>security</category>
    </item>
    <item>
      <title>Step‑by‑Step Ubuntu Linux Installation Guide</title>
      <dc:creator>Reginald F. Johnson</dc:creator>
      <pubDate>Tue, 30 Dec 2025 19:15:28 +0000</pubDate>
      <link>https://dev.to/reggiejohnson86/step-by-step-ubuntu-linux-installation-guide-25di</link>
      <guid>https://dev.to/reggiejohnson86/step-by-step-ubuntu-linux-installation-guide-25di</guid>
      <description>&lt;h2&gt;
  
  
  🧭 Full Environment Shift: Step‑by‑Step Ubuntu Installation Guide
&lt;/h2&gt;

&lt;p&gt;You’re doing a full environment shift here, so this guide is intentionally explicit and linear. Even “obvious” steps are included so nothing gets skipped.&lt;/p&gt;




&lt;h2&gt;
  
  
  1. Decide What Kind of Install You Want
&lt;/h2&gt;

&lt;p&gt;Before touching anything, decide:&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;1. Install Type&lt;/strong&gt;
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Erase Windows and use only Ubuntu&lt;/strong&gt; (simpler)
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Install Ubuntu alongside Windows&lt;/strong&gt; (dual‑boot, more complex)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This guide notes differences where they matter.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;2. Data Backup&lt;/strong&gt;
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;If erasing Windows:&lt;/strong&gt;
Back up &lt;em&gt;all&lt;/em&gt; files (Documents, Desktop, Downloads, browser data, etc.) to an external drive or cloud.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;If dual‑booting:&lt;/strong&gt;
Still back up important data — partition changes always carry risk.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;3. Free Space Requirement&lt;/strong&gt;
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Recommended: &lt;strong&gt;30–50 GB&lt;/strong&gt; free for Ubuntu.&lt;/li&gt;
&lt;li&gt;If dual‑booting, check Windows free space:
&lt;strong&gt;Win + E → This PC → Local Disk (C:)&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  2. Prepare a USB Drive &amp;amp; Downloads (Windows 10/11)
&lt;/h2&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;2.1. Get a USB Drive Ready&lt;/strong&gt;
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;USB size:&lt;/strong&gt;  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Use an &lt;strong&gt;8 GB or larger&lt;/strong&gt; USB flash drive.
&lt;/li&gt;
&lt;li&gt;All data on it will be erased.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Plug in USB:&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Insert the USB drive into your laptop.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Optional: Format USB (clean start):&lt;/strong&gt;  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Win + E → right‑click USB drive → &lt;strong&gt;Format…&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;File system: &lt;strong&gt;FAT32&lt;/strong&gt; or &lt;strong&gt;NTFS&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Click &lt;strong&gt;Start&lt;/strong&gt; → confirm.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;




&lt;h3&gt;
  
  
  &lt;strong&gt;2.2. Download Ubuntu ISO&lt;/strong&gt;
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Open a browser&lt;/strong&gt; (Edge, Chrome, Firefox).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Go to Ubuntu download page:&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
&lt;a href="https://ubuntu.com/download/desktop" rel="noopener noreferrer"&gt;https://ubuntu.com/download/desktop&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Choose version:&lt;/strong&gt;  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Download the latest &lt;strong&gt;LTS&lt;/strong&gt; version (e.g., &lt;em&gt;Ubuntu 24.04 LTS&lt;/em&gt; or &lt;em&gt;22.04 LTS&lt;/em&gt;).
&lt;/li&gt;
&lt;li&gt;Wait for the &lt;code&gt;.iso&lt;/code&gt; file to finish downloading.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Verify download location:&lt;/strong&gt;  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Win + E → &lt;strong&gt;Downloads&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Look for something like:
&lt;code&gt;ubuntu-24.04-desktop-amd64.iso&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;




&lt;h3&gt;
  
  
  &lt;strong&gt;2.3. Download Rufus&lt;/strong&gt;
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;Go to: &lt;a href="https://rufus.ie" rel="noopener noreferrer"&gt;https://rufus.ie&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Scroll to &lt;strong&gt;Download&lt;/strong&gt; section.
&lt;/li&gt;
&lt;li&gt;Download &lt;strong&gt;Rufus x.xx Portable&lt;/strong&gt; or the latest version.
&lt;/li&gt;
&lt;li&gt;Save it (usually in Downloads).&lt;/li&gt;
&lt;/ol&gt;




&lt;h2&gt;
  
  
  3. Create the Ubuntu USB with Rufus
&lt;/h2&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;3.1. Run Rufus&lt;/strong&gt;
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;Win + E → open &lt;strong&gt;Downloads&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Double‑click the Rufus &lt;code&gt;.exe&lt;/code&gt; (e.g., &lt;code&gt;rufus-4.5.exe&lt;/code&gt;)
&lt;/li&gt;
&lt;li&gt;Approve the Windows UAC prompt if it appears.&lt;/li&gt;
&lt;/ol&gt;




&lt;h3&gt;
  
  
  &lt;strong&gt;3.2. Select USB Drive &amp;amp; ISO&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Inside Rufus:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Device:&lt;/strong&gt;  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Select your USB drive from the dropdown.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Boot selection:&lt;/strong&gt;  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Click &lt;strong&gt;SELECT&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Choose the Ubuntu &lt;code&gt;.iso&lt;/code&gt; file.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Partition scheme &amp;amp; target system:&lt;/strong&gt;  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;GPT&lt;/strong&gt; for most modern laptops
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;MBR&lt;/strong&gt; for older BIOS‑only systems
&lt;/li&gt;
&lt;li&gt;Target system adjusts automatically.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Volume label:&lt;/strong&gt;  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Optional: name it &lt;strong&gt;UBUNTU&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;File system:&lt;/strong&gt;  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Leave default (&lt;strong&gt;FAT32&lt;/strong&gt; for UEFI).&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;




&lt;h3&gt;
  
  
  &lt;strong&gt;3.3. Rufus Ubuntu‑Specific Prompts&lt;/strong&gt;
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;ISOHybrid image detected:&lt;/strong&gt;  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Choose &lt;strong&gt;Write in ISO Image mode (Recommended)&lt;/strong&gt; → OK&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Data warning:&lt;/strong&gt;  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Confirm that all USB data will be destroyed.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;




&lt;h3&gt;
  
  
  &lt;strong&gt;3.4. Create the USB&lt;/strong&gt;
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;Click &lt;strong&gt;START&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Wait 5–20 minutes
&lt;/li&gt;
&lt;li&gt;When complete, Rufus will show &lt;strong&gt;READY&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Click &lt;strong&gt;CLOSE&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Leave the USB plugged in&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;




&lt;h2&gt;
  
  
  4. Prepare Your Laptop BIOS/UEFI
&lt;/h2&gt;

&lt;p&gt;You need to ensure the laptop can boot from USB.&lt;/p&gt;




&lt;h3&gt;
  
  
  &lt;strong&gt;4.1. Enter BIOS/UEFI&lt;/strong&gt;
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Restart Windows:&lt;br&gt;&lt;br&gt;
Start → Power → &lt;strong&gt;Restart&lt;/strong&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Press the firmware key repeatedly during boot:&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Manufacturer&lt;/th&gt;
&lt;th&gt;Key(s)&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Dell&lt;/td&gt;
&lt;td&gt;F2 or F12&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;HP&lt;/td&gt;
&lt;td&gt;Esc → F9 or F10&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Lenovo&lt;/td&gt;
&lt;td&gt;F1, F2, or Novo button&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Acer&lt;/td&gt;
&lt;td&gt;F2&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;ASUS&lt;/td&gt;
&lt;td&gt;F2 or Del&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;MSI&lt;/td&gt;
&lt;td&gt;Del&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;If Windows boots normally, restart and try again earlier.&lt;/p&gt;




&lt;h3&gt;
  
  
  &lt;strong&gt;4.2. Adjust Boot Options&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Inside BIOS/UEFI:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Find boot menus:&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Look for &lt;strong&gt;Boot&lt;/strong&gt;, &lt;strong&gt;Boot Options&lt;/strong&gt;, or &lt;strong&gt;Startup&lt;/strong&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Enable USB boot:&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Ensure USB/Removable boot is &lt;strong&gt;Enabled&lt;/strong&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Secure Boot:&lt;/strong&gt;  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Ubuntu can boot with Secure Boot ON, but if issues occur:

&lt;ul&gt;
&lt;li&gt;Set &lt;strong&gt;Secure Boot → Disabled&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Ensure Boot Mode is &lt;strong&gt;UEFI&lt;/strong&gt; (not Legacy).&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Boot order:&lt;/strong&gt;  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Move the USB drive to the &lt;strong&gt;top&lt;/strong&gt; of the boot priority list.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Save &amp;amp; exit:&lt;/strong&gt;  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Usually &lt;strong&gt;F10&lt;/strong&gt; → Yes&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;

</description>
      <category>linux</category>
      <category>ubuntu</category>
      <category>homelab</category>
    </item>
    <item>
      <title>🖥️ Ubuntu Laptop Home Server + Personal VPN (Tailscale Exit Node)</title>
      <dc:creator>Reginald F. Johnson</dc:creator>
      <pubDate>Sat, 27 Dec 2025 18:55:47 +0000</pubDate>
      <link>https://dev.to/reggiejohnson86/-ubuntu-laptop-home-server-personal-vpn-tailscale-exit-node-18b</link>
      <guid>https://dev.to/reggiejohnson86/-ubuntu-laptop-home-server-personal-vpn-tailscale-exit-node-18b</guid>
      <description>&lt;h2&gt;
  
  
  🖥️ Ubuntu Laptop Home Server + Personal VPN (Tailscale Exit Node)
&lt;/h2&gt;

&lt;p&gt;This guide walks you through converting a laptop with Ubuntu Linux installed into a reliable &lt;strong&gt;home server&lt;/strong&gt; and a &lt;strong&gt;personal VPN&lt;/strong&gt; using Tailscale.&lt;br&gt;&lt;br&gt;
You’ll configure the laptop to stay awake with the lid closed, then set it up as a secure VPN exit node accessible from anywhere.&lt;/p&gt;


&lt;h2&gt;
  
  
  🔧 Phase 1: Prepare the Hardware
&lt;/h2&gt;
&lt;h3&gt;
  
  
  Keep the Laptop Awake With the Lid Closed
&lt;/h3&gt;

&lt;p&gt;Ubuntu suspends when the lid is closed — not ideal for a server.&lt;br&gt;&lt;br&gt;
Disable this behavior:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt; Open your terminal.&lt;/li&gt;
&lt;li&gt; Edit the logind configuration file:
&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;nano /etc/systemd/logind.conf
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;ol&gt;
&lt;li&gt; Find this line:
&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;#HandleLidSwitch=suspend
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;ol&gt;
&lt;li&gt; Remove the &lt;code&gt;#&lt;/code&gt; and change it to:
&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;HandleLidSwitch=ignore
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;ol&gt;
&lt;li&gt; Save and exit (&lt;code&gt;Ctrl+O&lt;/code&gt;, Enter, &lt;code&gt;Ctrl+X&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt; Apply the changes:
&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;systemctl restart systemd-logind
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Your laptop will now stay awake with the lid closed.&lt;/p&gt;


&lt;h2&gt;
  
  
  🌐 Turn the Laptop Into a Personal VPN Server
&lt;/h2&gt;

&lt;p&gt;Using &lt;strong&gt;Tailscale&lt;/strong&gt;, you can turn your laptop into a secure VPN server that routes your internet traffic through your home network.&lt;br&gt;&lt;br&gt;
This uses a feature called an &lt;strong&gt;Exit Node&lt;/strong&gt;.&lt;/p&gt;


&lt;h2&gt;
  
  
  🚀 Step 1: Install Tailscale on Ubuntu
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt; Install Tailscale:&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;open TERMINAL:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-fsSL&lt;/span&gt; https://tailscale.com/install.sh | sh
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt; Start and authenticate:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;tailscale up
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Follow the URL provided to log in with Google, Microsoft, or GitHub.&lt;/p&gt;




&lt;h2&gt;
  
  
  🔁 Step 2: Enable Exit Node Mode
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. Enable IP Forwarding
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s1"&gt;'net.ipv4.ip_forward = 1'&lt;/span&gt; | &lt;span class="nb"&gt;sudo tee&lt;/span&gt; &lt;span class="nt"&gt;-a&lt;/span&gt; /etc/sysctl.d/99-tailscale.conf
&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s1"&gt;'net.ipv6.conf.all.forwarding = 1'&lt;/span&gt; | &lt;span class="nb"&gt;sudo tee&lt;/span&gt; &lt;span class="nt"&gt;-a&lt;/span&gt; /etc/sysctl.d/99-tailscale.conf
&lt;span class="nb"&gt;sudo &lt;/span&gt;sysctl &lt;span class="nt"&gt;-p&lt;/span&gt; /etc/sysctl.d/99-tailscale.conf
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  2. Advertise as an Exit Node
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;tailscale up &lt;span class="nt"&gt;--advertise-exit-node&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  🛡️ Step 3: Approve the Exit Node in the Admin Console
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt; Open the Tailscale Admin Console:
&lt;a href="https://login.tailscale.com/admin/machines" rel="noopener noreferrer"&gt;https://login.tailscale.com/admin/machines&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt; Find your Ubuntu laptop.&lt;/li&gt;
&lt;li&gt; Click the &lt;strong&gt;three dots (…)&lt;/strong&gt; → &lt;strong&gt;Edit route settings&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt; Enable &lt;strong&gt;Use as exit node&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt; Save.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Your laptop is now a fully functional VPN server.&lt;/p&gt;




&lt;h2&gt;
  
  
  📱 Step 4: Connect From iOS or Android
&lt;/h2&gt;

&lt;h3&gt;
  
  
  iPhone / iPad (iOS)
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt; Install &lt;strong&gt;Tailscale&lt;/strong&gt; from the App Store.&lt;/li&gt;
&lt;li&gt; Log in with the same account.&lt;/li&gt;
&lt;li&gt; Tap &lt;strong&gt;Exit Node&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt; Select your Ubuntu laptop.&lt;/li&gt;
&lt;li&gt; Toggle the VPN switch to &lt;strong&gt;Active&lt;/strong&gt;.&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Android
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt; Install &lt;strong&gt;Tailscale&lt;/strong&gt; from the Play Store.&lt;/li&gt;
&lt;li&gt; Log in and accept the VPN permission.&lt;/li&gt;
&lt;li&gt; Tap &lt;strong&gt;Exit Node&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt; Select your laptop.&lt;/li&gt;
&lt;li&gt; Toggle the connection on.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Your mobile device now routes all traffic through your home server.&lt;/p&gt;




&lt;h2&gt;
  
  
  🔒 Why This Beats a Commercial VPN
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Privacy:&lt;/strong&gt; You own the server — no third‑party logging.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Local Access:&lt;/strong&gt; Reach home files, printers, or cameras from anywhere.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Zero‑Config:&lt;/strong&gt; Tailscale handles NAT, dynamic IPs, and firewall rules automatically.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  ✔️ Summary
&lt;/h2&gt;

&lt;p&gt;You now have:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A laptop that stays awake with the lid closed&lt;/li&gt;
&lt;li&gt;A secure, self‑hosted VPN server&lt;/li&gt;
&lt;li&gt;Global access to your home network&lt;/li&gt;
&lt;li&gt;A privacy‑focused alternative to commercial VPNs&lt;/li&gt;
&lt;/ul&gt;




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

</description>
      <category>vpn</category>
      <category>ubuntu</category>
      <category>tailscale</category>
      <category>homelab</category>
    </item>
    <item>
      <title>My Simple Docker Project</title>
      <dc:creator>Reginald F. Johnson</dc:creator>
      <pubDate>Sat, 27 Dec 2025 18:48:54 +0000</pubDate>
      <link>https://dev.to/reggiejohnson86/my-simple-docker-project-4l2c</link>
      <guid>https://dev.to/reggiejohnson86/my-simple-docker-project-4l2c</guid>
      <description>&lt;h2&gt;
  
  
  🐳 Building a Simple "Hello World" Docker Project
&lt;/h2&gt;

&lt;p&gt;🚀 In this guide, we'll create a containerized Python web application that displays a "Hello World" message. This tutorial works on Ubuntu/Debian-based Linux distros&lt;/p&gt;




&lt;h2&gt;
  
  
  🔹 System Preparation
&lt;/h2&gt;

&lt;p&gt;Before we start, update and upgrade your system packages:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;apt update
&lt;span class="nb"&gt;sudo &lt;/span&gt;apt upgrade &lt;span class="nt"&gt;-y&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Install Docker and other required dependencies:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;apt &lt;span class="nb"&gt;install &lt;/span&gt;ca-certificates curl gnupg
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Add Docker’s Official GPG Key
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo install&lt;/span&gt; &lt;span class="nt"&gt;-m&lt;/span&gt; 0755 &lt;span class="nt"&gt;-d&lt;/span&gt; /etc/apt/keyrings
curl &lt;span class="nt"&gt;-fsSL&lt;/span&gt; https://download.docker.com/linux/ubuntu/gpg | &lt;span class="nb"&gt;sudo tee&lt;/span&gt; /etc/apt/keyrings/docker.asc &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; /dev/null
&lt;span class="nb"&gt;sudo chmod &lt;/span&gt;a+r /etc/apt/keyrings/docker.asc
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Add Docker Repository
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"deb [signed-by=/etc/apt/keyrings/docker.asc] https://download.docker.com/linux/ubuntu &lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;lsb_release &lt;span class="nt"&gt;-cs&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="s2"&gt; stable"&lt;/span&gt; | &lt;span class="nb"&gt;sudo tee&lt;/span&gt; /etc/apt/sources.list.d/docker.list &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; /dev/null
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Install Docker
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;apt update
&lt;span class="nb"&gt;sudo &lt;/span&gt;apt &lt;span class="nb"&gt;install &lt;/span&gt;docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Verify installation:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker &lt;span class="nt"&gt;--version&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Start and enable Docker:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;systemctl &lt;span class="nb"&gt;enable&lt;/span&gt; &lt;span class="nt"&gt;--now&lt;/span&gt; docker
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Check Docker status:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;systemctl status docker
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  🔹 Install Docker Compose Plugin
&lt;/h2&gt;

&lt;p&gt;Ubuntu now uses the Docker Compose plugin instead of the standalone binary:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;apt &lt;span class="nb"&gt;install &lt;/span&gt;docker-compose-plugin &lt;span class="nt"&gt;-y&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Verify installation:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker compose version
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Install Python Pip for dependencies:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;apt &lt;span class="nb"&gt;install &lt;/span&gt;python3-pip
python3 &lt;span class="nt"&gt;-m&lt;/span&gt; pip &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;--upgrade&lt;/span&gt; pip
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  🔹 Create Project Directory
&lt;/h2&gt;

&lt;p&gt;Set up the directory structure:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;mkdir &lt;/span&gt;docker-projects
&lt;span class="nb"&gt;cd &lt;/span&gt;docker-projects
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  🔹 Create Python Web Application
&lt;/h2&gt;

&lt;p&gt;Create the &lt;code&gt;app.py&lt;/code&gt; file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;touch &lt;/span&gt;app.py
nano app.py
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Copy &amp;amp; paste the following Python Flask app:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;flask&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Flask&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;redis&lt;/span&gt;

&lt;span class="n"&gt;app&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Flask&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;__name__&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;cache&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;redis&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Redis&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;host&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;redis&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;port&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;6379&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;get_hit_count&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="k"&gt;try&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;cache&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;incr&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;hits&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;except&lt;/span&gt; &lt;span class="n"&gt;redis&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;exceptions&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nb"&gt;ConnectionError&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;

&lt;span class="nd"&gt;@app.route&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;/&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;hello&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="n"&gt;count&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;get_hit_count&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Hello World! You have visited &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;count&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt; times.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;

&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;__name__&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;__main__&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;run&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;host&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;0.0.0.0&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;port&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;5000&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Save the file (&lt;code&gt;CTRL + X&lt;/code&gt;, then &lt;code&gt;Y&lt;/code&gt;).&lt;/p&gt;




&lt;h2&gt;
  
  
  🔹 Define Dependencies
&lt;/h2&gt;

&lt;p&gt;Create the &lt;code&gt;requirements.txt&lt;/code&gt; file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;touch &lt;/span&gt;requirements.txt
nano requirements.txt
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Add dependencies inside &lt;code&gt;requirements.txt&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Flask
redis
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Save (&lt;code&gt;CTRL + X&lt;/code&gt;, then &lt;code&gt;Y&lt;/code&gt;).&lt;/p&gt;




&lt;h2&gt;
  
  
  🔹 Create Dockerfile
&lt;/h2&gt;

&lt;p&gt;Create a &lt;code&gt;Dockerfile&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;touch &lt;/span&gt;Dockerfile
nano Dockerfile
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Paste the following Dockerfile configuration:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight docker"&gt;&lt;code&gt;&lt;span class="k"&gt;FROM&lt;/span&gt;&lt;span class="s"&gt; python:3.9&lt;/span&gt;

&lt;span class="k"&gt;WORKDIR&lt;/span&gt;&lt;span class="s"&gt; /app&lt;/span&gt;
&lt;span class="k"&gt;COPY&lt;/span&gt;&lt;span class="s"&gt; . .&lt;/span&gt;
&lt;span class="k"&gt;RUN &lt;/span&gt;pip &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-r&lt;/span&gt; requirements.txt
&lt;span class="k"&gt;CMD&lt;/span&gt;&lt;span class="s"&gt; ["python", "app.py"]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Save (&lt;code&gt;CTRL + X&lt;/code&gt;, then &lt;code&gt;Y&lt;/code&gt;).&lt;/p&gt;




&lt;h2&gt;
  
  
  🔹 Configure Docker Compose
&lt;/h2&gt;

&lt;p&gt;Create the &lt;code&gt;docker-compose.yml&lt;/code&gt; file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;touch &lt;/span&gt;docker-compose.yml
nano docker-compose.yml
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Paste the Docker Compose config:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;version&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;3'&lt;/span&gt;

&lt;span class="na"&gt;services&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;web&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;build&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;.&lt;/span&gt;
    &lt;span class="na"&gt;ports&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;5000:5000"&lt;/span&gt;
    &lt;span class="na"&gt;depends_on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;redis&lt;/span&gt;

  &lt;span class="na"&gt;redis&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;redis:alpine"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Save (&lt;code&gt;CTRL + X&lt;/code&gt;, then &lt;code&gt;Y&lt;/code&gt;). ⚠ YAML files are sensitive to indentation—validate them before running!&lt;/p&gt;




&lt;h2&gt;
  
  
  🔹 Build and Run the Project
&lt;/h2&gt;

&lt;p&gt;Ensure you're in the &lt;code&gt;docker-projects&lt;/code&gt; directory:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;cd &lt;/span&gt;docker-projects
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Start the containers:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;docker-compose up &lt;span class="nt"&gt;--build&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  🔹 Test the Web App
&lt;/h2&gt;

&lt;p&gt;Open a browser and go to &lt;a href="http://localhost:5000" rel="noopener noreferrer"&gt;http://localhost:5000&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;You should see:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Hello World! You have visited 1 times.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Refreshing the page will increase the visitor count.&lt;/p&gt;




&lt;h2&gt;
  
  
  🔹 Stop Containers
&lt;/h2&gt;

&lt;p&gt;Shut down the containers when you're done:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;docker-compose down
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



</description>
      <category>docker</category>
      <category>containers</category>
      <category>kubernetes</category>
    </item>
  </channel>
</rss>
