<?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>Forem: David M.</title>
    <description>The latest articles on Forem by David M. (@dailytadpole).</description>
    <link>https://forem.com/dailytadpole</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%2F1214022%2Fef8a0766-72de-4a62-b564-c07ad8a0010d.png</url>
      <title>Forem: David M.</title>
      <link>https://forem.com/dailytadpole</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/dailytadpole"/>
    <language>en</language>
    <item>
      <title>How to Host a Blog on a Subdirectory with Cloudflare Workers</title>
      <dc:creator>David M.</dc:creator>
      <pubDate>Tue, 25 Nov 2025 20:11:34 +0000</pubDate>
      <link>https://forem.com/dailytadpole/how-to-host-a-blog-on-a-subdirectory-with-cloudflare-workers-2m31</link>
      <guid>https://forem.com/dailytadpole/how-to-host-a-blog-on-a-subdirectory-with-cloudflare-workers-2m31</guid>
      <description>&lt;p&gt;Original Blog Post: &lt;a href="https://www.davidma.co/blog/2025-11-14-host-your-blog-on-a-subdirectory" rel="noopener noreferrer"&gt;https://www.davidma.co/blog/2025-11-14-host-your-blog-on-a-subdirectory&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  How to Host Your Blog on a Subdirectory with Cloudflare
&lt;/h1&gt;

&lt;p&gt;In this guide, you'll learn how to host your blog on a subdirectory (e.g. example.com/blog) instead of a subdomain (e.g., blog.example.com). Every step here has been tested and verified to work.&lt;/p&gt;

&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;Hosting your blog on a subdirectory can improve SEO and enhance user experience.&lt;/p&gt;

&lt;p&gt;Although there are a lot of articles that espouse the benefits of using subdirectories over subdomains, few resources that provide a step-by-step guide on how to actually set this up.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why Host on a Subdirectory?
&lt;/h2&gt;

&lt;p&gt;The benefits to hosting on a subdirectory is primarily to improve SEO.&lt;/p&gt;

&lt;p&gt;There are a lot of other articles out there on this topic, but they all say something similar to the following:&lt;/p&gt;

&lt;p&gt;Hosting your blog on a subdirectory is better for SEO because it consolidates your website's authority and ranking power.&lt;/p&gt;

&lt;p&gt;Google has stated that they do not treat subdomains as a separate entity.&lt;/p&gt;

&lt;p&gt;Despite what Google has stated, empiric data suggests that subdirectories outperform subdomains in search rankings.&lt;/p&gt;

&lt;p&gt;If you want to maximize your SEO efforts, hosting on a subdirectory is the way to go.&lt;/p&gt;

&lt;p&gt;If you want to learn more, you can read this article by ButterCMS: Blog Subdomain or Subdirectory? Hint: One is 40% Better.&lt;/p&gt;

&lt;p&gt;My personal experience has been similar. When I moved a blog from a subdomain to a subdirectory, I saw a noticeable increase in organic traffic and search engine rankings. The increase happened after a few weeks. During that time, I did not release any new content and nor did I promote the blog.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why Not Host on a Subdirectory?
&lt;/h2&gt;

&lt;p&gt;The setup is more complex. Many blogging platforms and CMSs are designed to work on subdomains, and configuring them to work on a subdirectory can be tricky.&lt;/p&gt;

&lt;p&gt;I've personally found the setup process to be quite time consuming. It's a tricky process and you have to follow the instructions carefully. After having previously changed a blog from a subdomain to a subdirectory, I've found difficult to justify the time to do it for taikohub.com.&lt;/p&gt;

&lt;p&gt;If you still think it's worth your time, then read on.&lt;/p&gt;

&lt;h2&gt;
  
  
  Steps to Host Your Blog on a Subdirectory
&lt;/h2&gt;

&lt;p&gt;Lets suppose you have two sites right now. One is example.com and the other is blog.example.com. You want to host the blog on example.com/blog instead of blog.example.com.&lt;/p&gt;

&lt;p&gt;Lets also suppose your blog (blog.example.com) is a Next.js app hosted on Vercel and your main site (example.com) is a static site hosted on Render.&lt;/p&gt;

&lt;p&gt;Although Vercel and Render are used as examples here, the steps are nearly identical for other hosting providers. You do not need configure anything for your hosting provider. Everything can be done from the Cloudflare Dashboard, and from the comforts of your text editor.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Important:&lt;/strong&gt; Note that Cloudflare often changes their dashboard UI and routes. If you find that the steps here do not match what you see on your Cloudflare Dashboard, just use the search function in the dashboard to find the relevant section.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 1: Set Up DNS Records for the Main Site
&lt;/h3&gt;

&lt;p&gt;First, set up the DNS records for your main site (example.com). Again, if you do not use Render, then follow the equivalent steps for your hosting provider. Generally this should be in their documentation.&lt;/p&gt;

&lt;p&gt;Go to your Cloudflare Dashboard. Click into your domain, then SSL/TLS, then Overview. Then click "Configure".&lt;/p&gt;

&lt;p&gt;Next, select "Custom SSL/TLS" then select "Full".&lt;/p&gt;

&lt;p&gt;Go to DNS records in the sidebar by clicking on "DNS", then "DNS Records". Then click "Add Record".&lt;/p&gt;

&lt;p&gt;Add the following DNS Records. Replace my-site.onrender.com with the service URL for your main site. If you have other applications such as an API, you can add those as well. Note that it's important you set the "Proxy status" to "Proxied". It's also important you do NOT add a wildcard record (eg. *.example.com).&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Type&lt;/th&gt;
&lt;th&gt;Name&lt;/th&gt;
&lt;th&gt;Target&lt;/th&gt;
&lt;th&gt;Proxy status&lt;/th&gt;
&lt;th&gt;TTL&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;CNAME&lt;/td&gt;
&lt;td&gt;@&lt;/td&gt;
&lt;td&gt;my-site.onrender.com&lt;/td&gt;
&lt;td&gt;Proxied&lt;/td&gt;
&lt;td&gt;Auto&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;CNAME&lt;/td&gt;
&lt;td&gt;www&lt;/td&gt;
&lt;td&gt;my-site.onrender.com&lt;/td&gt;
&lt;td&gt;Proxied&lt;/td&gt;
&lt;td&gt;Auto&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;CNAME&lt;/td&gt;
&lt;td&gt;api&lt;/td&gt;
&lt;td&gt;my-api.onrender.com&lt;/td&gt;
&lt;td&gt;Proxied&lt;/td&gt;
&lt;td&gt;Auto&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h3&gt;
  
  
  Step 2: Set Up DNS Records for the Blog
&lt;/h3&gt;

&lt;p&gt;Make sure your blog is already accessible on a subdomain (eg. blog.example.com).&lt;/p&gt;

&lt;p&gt;Add another DNS Record for the blog. Replace cname.vercel-dns.com with the CNAME target provided by the hosting provider for your blog.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Type&lt;/th&gt;
&lt;th&gt;Name&lt;/th&gt;
&lt;th&gt;Target&lt;/th&gt;
&lt;th&gt;Proxy status&lt;/th&gt;
&lt;th&gt;TTL&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;CNAME&lt;/td&gt;
&lt;td&gt;example.com&lt;/td&gt;
&lt;td&gt;my-site.onrender.com&lt;/td&gt;
&lt;td&gt;Proxied&lt;/td&gt;
&lt;td&gt;Auto&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;CNAME&lt;/td&gt;
&lt;td&gt;www&lt;/td&gt;
&lt;td&gt;my-site.onrender.com&lt;/td&gt;
&lt;td&gt;Proxied&lt;/td&gt;
&lt;td&gt;Auto&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;CNAME&lt;/td&gt;
&lt;td&gt;api&lt;/td&gt;
&lt;td&gt;my-api.onrender.com&lt;/td&gt;
&lt;td&gt;Proxied&lt;/td&gt;
&lt;td&gt;Auto&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;CNAME&lt;/td&gt;
&lt;td&gt;blog&lt;/td&gt;
&lt;td&gt;cname.vercel-dns.com&lt;/td&gt;
&lt;td&gt;Proxied&lt;/td&gt;
&lt;td&gt;Auto&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h3&gt;
  
  
  Step 3: Configure Your Next.js Blog
&lt;/h3&gt;

&lt;h4&gt;
  
  
  Ensure Correct Routing for Static Assets
&lt;/h4&gt;

&lt;p&gt;Make sure that your Next.js blog's router points to / and not /blog. You should NOT have any routes that contain /blog. Edit the next.config.js or next.config.mjs file and add basePath: "/blog" to the config.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="cm"&gt;/** @type {import('next').NextConfig} */&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;nextConfig&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;basePath&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/blog&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  &lt;span class="c1"&gt;// Add this line&lt;/span&gt;
  &lt;span class="na"&gt;images&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;remotePatterns&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
      &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;protocol&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;https&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;hostname&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;imagedelivery.net&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;],&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="na"&gt;redirects&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;[];&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nx"&gt;nextConfig&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Step 4: Add a Cloudflare Worker
&lt;/h3&gt;

&lt;p&gt;Go to Cloudflare Dashboard. Click "Workers &amp;amp; Pages". Click "Create" then click "Create Worker".&lt;/p&gt;

&lt;p&gt;For the purpose of this blog post, we'll go with the easiest option by selecting "Start with Hello World!". For production applications, consider using Git. It looks like the following. Lets name it blog-worker. Then click "Deploy".&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// worker.js&lt;/span&gt;
&lt;span class="cm"&gt;/**
* Welcome to Cloudflare Workers! This is your first worker.
*
* - Run "npm run dev" in your terminal to start a development server
* - Open a browser tab at http://localhost:8787/ to see your worker in action
* - Run "npm run deploy" to publish your worker
*
* Learn more at https://developers.cloudflare.com/workers/
*/&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Response&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Hello World!&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now replace the code with the following:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;MethodNotAllowed&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Response&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`Method &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;method&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; not allowed.`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;status&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;405&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="na"&gt;Allow&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;GET&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="p"&gt;},&lt;/span&gt;
      &lt;span class="p"&gt;});&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="c1"&gt;// Only GET requests work with this proxy.&lt;/span&gt;
    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;method&lt;/span&gt; &lt;span class="o"&gt;!==&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;GET&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nc"&gt;MethodNotAllowed&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="c1"&gt;// Get the URL that was just requested.&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;url&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;URL&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="c1"&gt;// Swap out the subdirectory with the subdomain to request the actual URL.&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;originUrl&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;toString&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;replace&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;https://example.com/blog&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;https://blog.example.com/blog&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
    &lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;replace&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;https://www.example.com/blog&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;https://blog.example.com/blog&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
    &lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="c1"&gt;// Fetch the origin.&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;originPage&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;originUrl&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="c1"&gt;// Return the subdomain, as the subdirectory.&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;newResponse&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Response&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;originPage&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;body&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;originPage&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;newResponse&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Change the URLs as needed. To save, click on the version ID hash (eg. b30983e0) then click "Apply".&lt;/p&gt;

&lt;p&gt;To deploy the changes, go to the worker dashboard. Click "Deployments". Look under "Version History". Click "…" then "Deploy" on the latest version.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Version ID&lt;/th&gt;
&lt;th&gt;Created&lt;/th&gt;
&lt;th&gt;Version &amp;amp; Git Message&lt;/th&gt;
&lt;th&gt;Source&lt;/th&gt;
&lt;th&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;vb29485e0&lt;/td&gt;
&lt;td&gt;3min…&lt;/td&gt;
&lt;td&gt;Update to …&lt;/td&gt;
&lt;td&gt;Dashboard&lt;/td&gt;
&lt;td&gt;"…"&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;vf859f2e0&lt;/td&gt;
&lt;td&gt;2h…&lt;/td&gt;
&lt;td&gt;Updated Script&lt;/td&gt;
&lt;td&gt;Dashboard&lt;/td&gt;
&lt;td&gt;"…"&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h3&gt;
  
  
  Step 5: Connect Next.js Site with Cloudflare Worker
&lt;/h3&gt;

&lt;p&gt;Go to "Worker Routes" in the Cloudflare Dashboard sidebar. Click on "Add Route".&lt;/p&gt;

&lt;p&gt;Add the following route for the blog content:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Route:&lt;/strong&gt; example.com/blog*&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Worker:&lt;/strong&gt; blog-worker. This is the worker you just created.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Add another route for the static assets:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Route:&lt;/strong&gt; example.com/blog/_next/static*&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Worker:&lt;/strong&gt; blog-worker&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You should now be able to access your blog at example.com/blog. If this works, congratulations! You've successfully hosted your blog on a subdirectory using Cloudflare Workers.&lt;/p&gt;

&lt;h3&gt;
  
  
  Configure Search Engine Robots.txt in Your Next.js App
&lt;/h3&gt;

&lt;p&gt;Now that you've successfully hosted the blog on the subdirectory, you need to make sure search engines don't index the subdomain. This is because the blog is already indexed on the subdirectory. If search engines index both, then you may run into SEO issues due to duplicate content.&lt;/p&gt;

&lt;p&gt;Update your next.config.js or next.config.mjs file.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="cm"&gt;/** @type {import('next').NextConfig} */&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;nextConfig&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;basePath&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/blog&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;images&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;remotePatterns&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
      &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;protocol&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;https&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;hostname&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;imagedelivery.net&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;],&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="na"&gt;redirects&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;                      &lt;span class="c1"&gt;// Add this block&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;[];&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="nf"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;                             &lt;span class="c1"&gt;// Add this block&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
      &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;source&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/:path*&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
          &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="na"&gt;key&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;X-Robots-Tag&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;noindex, nofollow&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="p"&gt;],&lt;/span&gt;
      &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;];&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nx"&gt;nextConfig&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now update your cloudflare worker.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;MethodNotAllowed&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Response&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`Method &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;method&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; not allowed.`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;status&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;405&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="na"&gt;Allow&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;GET&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="p"&gt;},&lt;/span&gt;
      &lt;span class="p"&gt;});&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="c1"&gt;// Only GET requests work with this proxy.&lt;/span&gt;
    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;method&lt;/span&gt; &lt;span class="o"&gt;!==&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;GET&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nc"&gt;MethodNotAllowed&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="c1"&gt;// Get the URL that was just requested.&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;url&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;URL&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="c1"&gt;// Swap out the subdirectory with the subdomain to request the actual URL.&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;originUrl&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;toString&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;replace&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;https://example.com/blog&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;https://blog.example.com/blog&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
    &lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;replace&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;https://www.example.com/blog&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;https://blog.example.com/blog&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
    &lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="c1"&gt;// Fetch the origin.&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;originPage&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;originUrl&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="c1"&gt;// Return the subdomain, as the subdirectory.&lt;/span&gt;
    &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;newResponse&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Response&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;originPage&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;body&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;originPage&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="c1"&gt;// Remove "noindex" from the origin domain.&lt;/span&gt;
    &lt;span class="nx"&gt;newResponse&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;delete&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;x-robots-tag&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;newResponse&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Step 6: Verify Your Subdomain is Not Indexed
&lt;/h3&gt;

&lt;p&gt;Open your app's deploy URL. This may look something like &lt;a href="https://vercel.com/my-projects-30d8ek3n/my-blog/d934nfid9823sbsNgoMnOOnsiKxn" rel="noopener noreferrer"&gt;https://vercel.com/my-projects-30d8ek3n/my-blog/d934nfid9823sbsNgoMnOOnsiKxn&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Open the browser's Network tab in Developer Tools.&lt;/p&gt;

&lt;p&gt;Check for existence of an "X-Robots-Tag" header. If it's not there, then your Next.js app is correctly configured to not be indexed.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 7: Verify Your Subdirectory is Indexed
&lt;/h3&gt;

&lt;p&gt;Go to Google URL Inspection Tool.&lt;/p&gt;

&lt;p&gt;Enter your subdirectory URL (eg. example.com/blog).&lt;/p&gt;

&lt;p&gt;Confirm that it shows as indexed.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>beginners</category>
      <category>tutorial</category>
      <category>cloud</category>
    </item>
    <item>
      <title>How to Setup a Secure Ubuntu Home Server: A Complete Guide</title>
      <dc:creator>David M.</dc:creator>
      <pubDate>Wed, 30 Jul 2025 20:56:33 +0000</pubDate>
      <link>https://forem.com/dailytadpole/how-to-setup-a-secure-ubuntu-home-server-a-complete-guide-5be7</link>
      <guid>https://forem.com/dailytadpole/how-to-setup-a-secure-ubuntu-home-server-a-complete-guide-5be7</guid>
      <description>&lt;p&gt;Original Blog Post: &lt;a href="https://www.davidma.co/blog/2025-07-24-home-server" rel="noopener noreferrer"&gt;https://www.davidma.co/blog/2025-07-24-home-server&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Setting up a home server can seem daunting, but with this blog post, you too can transform an old PC into a secure home server! This blog post will walk you through every step, from basic SSH setup to advanced security hardening.&lt;/p&gt;

&lt;h2&gt;
  
  
  Prerequisites
&lt;/h2&gt;

&lt;p&gt;Before we begin, ensure you have:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A PC with Ubuntu installed (Either Ubuntu Server or Desktop is fine)&lt;/li&gt;
&lt;li&gt;Basic command line familiarity&lt;/li&gt;
&lt;li&gt;Administrative access to your home router&lt;/li&gt;
&lt;li&gt;Another computer to test SSH connections&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Quick Reference: Essential Commands
&lt;/h2&gt;

&lt;p&gt;Here are some handy vim commands you might use throughout this guide. If you're not familiar with vim, you can use any text editor of your choice.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Open remote files: &lt;code&gt;vim scp://user@server//home/user/file.py&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Open multiple files in tabs: &lt;code&gt;vim -p file1.txt file2.txt&lt;/code&gt; (may need &lt;code&gt;:tab all&lt;/code&gt;)&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Step 1: Setting Up SSH Access
&lt;/h2&gt;

&lt;p&gt;SSH (Secure Shell) is the foundation of remote server management. Let's get it configured first.&lt;/p&gt;

&lt;h3&gt;
  
  
  Install and Enable OpenSSH Server
&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 &lt;span class="nb"&gt;install &lt;/span&gt;openssh-server
&lt;span class="nb"&gt;sudo &lt;/span&gt;systemctl &lt;span class="nb"&gt;enable &lt;/span&gt;ssh
&lt;span class="nb"&gt;sudo &lt;/span&gt;systemctl status ssh
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Find Your Server's IP Address
&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;hostname&lt;/span&gt; &lt;span class="nt"&gt;-I&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This will return something like &lt;code&gt;10.0.0.207&lt;/code&gt; - note this down as we'll use it throughout the guide.&lt;/p&gt;

&lt;h3&gt;
  
  
  Test SSH Connection
&lt;/h3&gt;

&lt;p&gt;From your client computer, try connecting:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;ssh user@10.0.0.207
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You'll need to enter your password at this point.&lt;/p&gt;

&lt;h3&gt;
  
  
  Set Up Key-Based Authentication
&lt;/h3&gt;

&lt;p&gt;For better security and convenience, set up SSH key authentication:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;ssh-copy-id user@10.0.0.207
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After this, you should be able to SSH without entering a password.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 2: Configuring a Static IP Address
&lt;/h2&gt;

&lt;p&gt;Dynamic IP addresses can change, which gets troublesome whenever you need to connect to your server. Let's set up a static IP to avoid this.&lt;/p&gt;

&lt;h3&gt;
  
  
  Understanding Netplan
&lt;/h3&gt;

&lt;p&gt;Ubuntu uses Netplan for network configuration. Navigate to the netplan 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; /etc/netplan/
&lt;span class="nb"&gt;ls&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You should see a file like &lt;code&gt;01-network-manager-all.yaml&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Create a Backup
&lt;/h3&gt;

&lt;p&gt;Always backup before making changes:&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 cp&lt;/span&gt; /etc/netplan/01-network-manager-all.yaml /etc/netplan/01-network-manager-all-BACKUP.yaml
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Create Static IP Configuration
&lt;/h3&gt;

&lt;p&gt;Create a new configuration 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;vim /etc/netplan/static.yaml
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Use this template (we'll customize it next):&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;network&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;version&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;2&lt;/span&gt;
  &lt;span class="na"&gt;renderer&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;networkd&lt;/span&gt;
  &lt;span class="na"&gt;ethernets&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;eth0&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;addresses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;10.10.10.2/24&lt;/span&gt;
      &lt;span class="na"&gt;routes&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;to&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;default&lt;/span&gt;
          &lt;span class="na"&gt;via&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;10.10.10.1&lt;/span&gt;
      &lt;span class="na"&gt;nameservers&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;addresses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;1.1.1.1&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;1.0.0.1&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Get Network Interface Information
&lt;/h3&gt;

&lt;p&gt;Find your network interface name:&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;p&gt;Look for something like &lt;code&gt;enp42s0&lt;/code&gt; (ignore the &lt;code&gt;lo&lt;/code&gt; interface). You'll also note your current IP address.&lt;/p&gt;

&lt;h3&gt;
  
  
  Customize the Configuration
&lt;/h3&gt;

&lt;p&gt;Update your &lt;code&gt;static.yaml&lt;/code&gt; file:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Replace &lt;code&gt;eth0&lt;/code&gt; with your actual interface name (e.g., &lt;code&gt;enp42s0&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;Set your desired static IP (e.g., &lt;code&gt;10.0.0.207/24&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;Set your router's gateway (usually &lt;code&gt;10.0.0.1&lt;/code&gt; for most home routers)&lt;/li&gt;
&lt;li&gt;Use Cloudflare's DNS servers: &lt;code&gt;[1.1.1.1, 1.0.0.1]&lt;/code&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Apply the Configuration
&lt;/h3&gt;

&lt;p&gt;Set proper permissions and apply:&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;600 /etc/netplan/static.yaml
&lt;span class="nb"&gt;sudo &lt;/span&gt;netplan apply
&lt;span class="nb"&gt;sudo &lt;/span&gt;reboot
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Test the connection from your client:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;ssh user@10.0.0.207
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Step 3: Hardening with UFW Firewall
&lt;/h2&gt;

&lt;p&gt;UFW (Uncomplicated Firewall) provides an easy way to manage iptables rules.&lt;/p&gt;

&lt;h3&gt;
  
  
  Install and Enable UFW
&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 &lt;span class="nb"&gt;install &lt;/span&gt;ufw
&lt;span class="nb"&gt;sudo &lt;/span&gt;systemctl status ufw
&lt;span class="nb"&gt;sudo &lt;/span&gt;ufw &lt;span class="nb"&gt;enable&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Set Default Policies
&lt;/h3&gt;

&lt;p&gt;Start with a deny-all approach:&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;ufw default deny incoming
&lt;span class="nb"&gt;sudo &lt;/span&gt;ufw default deny outgoing
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Allow Essential Services
&lt;/h3&gt;

&lt;p&gt;Open only the ports you need:&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;# Web traffic&lt;/span&gt;
&lt;span class="nb"&gt;sudo &lt;/span&gt;ufw allow 80,443/tcp
&lt;span class="nb"&gt;sudo &lt;/span&gt;ufw allow out 80,443/tcp

&lt;span class="c"&gt;# SSH (we'll change this port later)&lt;/span&gt;
&lt;span class="nb"&gt;sudo &lt;/span&gt;ufw allow 22/tcp
&lt;span class="nb"&gt;sudo &lt;/span&gt;ufw allow out 22/tcp

&lt;span class="c"&gt;# NTP for time synchronization&lt;/span&gt;
&lt;span class="nb"&gt;sudo &lt;/span&gt;ufw allow 123/udp
&lt;span class="nb"&gt;sudo &lt;/span&gt;ufw allow out 123/udp

&lt;span class="c"&gt;# DNS resolution&lt;/span&gt;
&lt;span class="nb"&gt;sudo &lt;/span&gt;ufw allow &lt;span class="k"&gt;in &lt;/span&gt;from any to any port 53
&lt;span class="nb"&gt;sudo &lt;/span&gt;ufw allow out from any to any port 53
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Check Firewall Status
&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;ufw status numbered
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You should see a comprehensive list of rules for both IPv4 and IPv6.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 4: Network Time Protocol (NTP) Setup
&lt;/h2&gt;

&lt;p&gt;Accurate time is crucial for security certificates and log correlation.&lt;/p&gt;

&lt;h3&gt;
  
  
  Backup Current Configuration
&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 cp&lt;/span&gt; &lt;span class="nt"&gt;--archive&lt;/span&gt; /etc/systemd/timesyncd.conf /etc/systemd/timesyncd.conf-COPY-&lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;date&lt;/span&gt; +&lt;span class="s2"&gt;"%Y%m%d%H%M%S"&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Configure NTP
&lt;/h3&gt;

&lt;p&gt;Edit the configuration 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;vim /etc/systemd/timesyncd.conf
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Add these lines:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ini"&gt;&lt;code&gt;&lt;span class="nn"&gt;[Time]&lt;/span&gt;
&lt;span class="py"&gt;NTP&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;0.pool.ntp.org 1.pool.ntp.org&lt;/span&gt;
&lt;span class="py"&gt;FallbackNTP&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;ntp.ubuntu.com&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Restart and Verify
&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;systemctl restart systemd-timesyncd
&lt;span class="nb"&gt;sudo &lt;/span&gt;systemctl status systemd-timesyncd
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Set Your Timezone
&lt;/h3&gt;

&lt;p&gt;Check current timezone:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;timedatectl | &lt;span class="nb"&gt;grep &lt;/span&gt;Time
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If needed, set it correctly:&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;timedatectl set-timezone America/Vancouver
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Step 5: Advanced SSH Security
&lt;/h2&gt;

&lt;p&gt;Now let's seriously harden SSH security.&lt;/p&gt;

&lt;h3&gt;
  
  
  Change SSH Port
&lt;/h3&gt;

&lt;p&gt;First, allow the new port through UFW:&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;ufw allow 2222/tcp
&lt;span class="nb"&gt;sudo &lt;/span&gt;ufw allow out 2222/tcp
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Backup SSH Configuration
&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 cp&lt;/span&gt; &lt;span class="nt"&gt;--preserve&lt;/span&gt; /etc/ssh/sshd_config /etc/ssh/sshd_config.&lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;date&lt;/span&gt; +&lt;span class="s2"&gt;"%Y%m%d%H%M%S"&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Apply Hardened SSH Configuration
&lt;/h3&gt;

&lt;p&gt;Edit the SSH config:&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;vim /etc/ssh/sshd_config
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Delete everything (&lt;code&gt;:%d&lt;/code&gt; in vim) and paste this hardened configuration:&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;# Supported HostKey algorithms by order of preference&lt;/span&gt;
HostKey /etc/ssh/ssh_host_ed25519_key
HostKey /etc/ssh/ssh_host_rsa_key
HostKey /etc/ssh/ssh_host_ecdsa_key

&lt;span class="c"&gt;# Cryptographic settings&lt;/span&gt;
KexAlgorithms curve25519-sha256@libssh.org,ecdh-sha2-nistp521,ecdh-sha2-nistp384,ecdh-sha2-nistp256,diffie-hellman-group-exchange-sha256
Ciphers chacha20-poly1305@openssh.com,aes256-gcm@openssh.com,aes128-gcm@openssh.com,aes256-ctr,aes192-ctr,aes128-ctr
MACs hmac-sha2-512-etm@openssh.com,hmac-sha2-256-etm@openssh.com,umac-128-etm@openssh.com,hmac-sha2-512,hmac-sha2-256,umac-128@openssh.com

&lt;span class="c"&gt;# Security settings&lt;/span&gt;
Port                            2222
LogLevel                        VERBOSE
Protocol                        2
PermitUserEnvironment           no
PermitRootLogin                 no
PubkeyAuthentication            &lt;span class="nb"&gt;yes
&lt;/span&gt;PasswordAuthentication          no
PermitEmptyPasswords            no
MaxAuthTries                    3
MaxSessions                     2
X11Forwarding                   no
IgnoreRhosts                    &lt;span class="nb"&gt;yes
&lt;/span&gt;UseDNS                          no
ClientAliveCountMax             0
ClientAliveInterval             300
AllowUsers                      YOUR_USERNAME  &lt;span class="c"&gt;# CHANGE THIS!&lt;/span&gt;

&lt;span class="c"&gt;# Disable port forwarding&lt;/span&gt;
AllowAgentForwarding            no
AllowTcpForwarding              no
AllowStreamLocalForwarding      no
GatewayPorts                    no
PermitTunnel                    no

&lt;span class="c"&gt;# SFTP logging&lt;/span&gt;
Subsystem sftp  /usr/lib/openssh/sftp-server

&lt;span class="c"&gt;# Additional security&lt;/span&gt;
Compression                     no
PrintMotd                       no
TCPKeepAlive                    no
ChallengeResponseAuthentication no
UsePAM                          &lt;span class="nb"&gt;yes
&lt;/span&gt;AcceptEnv LANG LC_&lt;span class="k"&gt;*&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Important&lt;/strong&gt;: Replace &lt;code&gt;YOUR_USERNAME&lt;/code&gt; with your actual username!&lt;/p&gt;

&lt;h3&gt;
  
  
  Restart SSH and Verify
&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;systemctl restart sshd
&lt;span class="nb"&gt;sudo &lt;/span&gt;ss &lt;span class="nt"&gt;-tlpn&lt;/span&gt; | &lt;span class="nb"&gt;grep &lt;/span&gt;ssh
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You should see SSH listening on port 2222.&lt;/p&gt;

&lt;h3&gt;
  
  
  Test New SSH Configuration
&lt;/h3&gt;

&lt;p&gt;From your client computer:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;ssh &lt;span class="nt"&gt;-p&lt;/span&gt; 2222 user@10.0.0.207
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Once you confirm the new port works, delete the old SSH port:&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;ufw delete allow 22/tcp
&lt;span class="nb"&gt;sudo &lt;/span&gt;ufw delete allow out 22/tcp
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Optional: Auto-logout After Inactivity
&lt;/h3&gt;

&lt;p&gt;Add automatic logout after 5 minutes of inactivity:&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;echo&lt;/span&gt; &lt;span class="s1"&gt;'TMOUT=300'&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; ~/.bashrc
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Strengthen SSH Keys
&lt;/h3&gt;

&lt;p&gt;Remove weak moduli:&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;# Backup existing moduli file&lt;/span&gt;
&lt;span class="nb"&gt;sudo cp&lt;/span&gt; &lt;span class="nt"&gt;--archive&lt;/span&gt; /etc/ssh/moduli /etc/ssh/moduli-COPY-&lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;date&lt;/span&gt; +&lt;span class="s2"&gt;"%Y%m%d%H%M%S"&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;

&lt;span class="c"&gt;# Remove keys weaker than 3072 bits&lt;/span&gt;
&lt;span class="nb"&gt;sudo awk&lt;/span&gt; &lt;span class="s1"&gt;'$5 &amp;gt;= 3071'&lt;/span&gt; /etc/ssh/moduli | &lt;span class="nb"&gt;sudo tee&lt;/span&gt; /etc/ssh/moduli.tmp
&lt;span class="nb"&gt;sudo mv&lt;/span&gt; /etc/ssh/moduli.tmp /etc/ssh/moduli
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Add Legal Banner
&lt;/h3&gt;

&lt;p&gt;Create a warning banner:&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;vim /etc/issue.net
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Add this message:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;This system is for the use of authorised users only.

Individuals using this computer system without authority, or in excess of their authority, are subject to having all of their activities on this system monitored and recorded by system personnel.

In the course of monitoring individuals improperly using this system, or in the course of system maintenance, the activities of authorised users may also be monitored.

Anyone using this system expressly consents to such monitoring and is advised that if such monitoring reveals possible evidence of criminal activity, system personnel may provide the evidence of such monitoring to law enforcement officials.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Step 6: Git Configuration for Development
&lt;/h2&gt;

&lt;p&gt;If you plan to use your server for development, configure Git properly.&lt;/p&gt;

&lt;h3&gt;
  
  
  Allow Git Port (Optional)
&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;ufw allow 9418/tcp
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Configure Git for SSH
&lt;/h3&gt;

&lt;p&gt;Instead of the standard GitHub SSH URL, use the HTTPS port for better firewall compatibility:&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;# Standard approach&lt;/span&gt;
git remote add origin git@github.com:username/repository.git

&lt;span class="c"&gt;# Firewall-friendly approach&lt;/span&gt;
git remote add origin ssh://git@ssh.github.com:443/username/repository.git
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Additional Security Considerations
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Network-Level Restrictions
&lt;/h3&gt;

&lt;p&gt;For maximum security, consider restricting SSH access to your local network only. You can modify UFW rules to only allow connections from your local subnet:&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;ufw allow from 10.0.0.0/24 to any port 2222
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Regular Maintenance
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Keep your system updated: &lt;code&gt;sudo apt update &amp;amp;&amp;amp; sudo apt upgrade&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Monitor SSH logs: &lt;code&gt;sudo journalctl -u ssh&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Review firewall logs: &lt;code&gt;sudo ufw status verbose&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Check for failed login attempts: &lt;code&gt;sudo grep "Failed password" /var/log/auth.log&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;You now have a secure Ubuntu home server with:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;✅ SSH access with key-based authentication&lt;/li&gt;
&lt;li&gt;✅ Static IP configuration&lt;/li&gt;
&lt;li&gt;✅ Hardened firewall rules&lt;/li&gt;
&lt;li&gt;✅ Network time synchronization&lt;/li&gt;
&lt;li&gt;✅ Secure SSH configuration on a non-standard port&lt;/li&gt;
&lt;li&gt;✅ Git development capabilities&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This setup provides a solid foundation for hosting services, running development environments, or managing home automation systems. Remember to regularly update your system and monitor logs for any suspicious activity.&lt;/p&gt;

</description>
      <category>programming</category>
      <category>beginners</category>
      <category>tutorial</category>
      <category>linux</category>
    </item>
  </channel>
</rss>
