<?xml version="1.0" encoding="UTF-8"?><rss version="2.0" xmlns:content="http://purl.org/rss/1.0/modules/content/"><channel><title>HRNPH BLOG</title><description>A personal blog of hrnph (hirunkul phimsiri)</description><link>https://blog.hrnph.dev/</link><language>en</language><item><title>How to Run a Fabric Minecraft Server with Docker - Zero to Hero Guide</title><link>https://blog.hrnph.dev/posts/how-to-run-fabric-mc-server-with-docker/</link><guid isPermaLink="true">https://blog.hrnph.dev/posts/how-to-run-fabric-mc-server-with-docker/</guid><description>A beginner-friendly, step-by-step guide to setting up a Fabric Minecraft server using Docker.</description><pubDate>Sat, 06 Dec 2025 00:00:00 GMT</pubDate><content:encoded>&lt;h1&gt;Introduction&lt;/h1&gt;
&lt;p&gt;This is a &quot;Zero-to-Hero&quot; guide designed for someone who has never touched a server, doesn&apos;t know what a terminal is, and just wants to play Minecraft with friends using the Fabric mod loader.&lt;/p&gt;
&lt;p&gt;We are using &lt;strong&gt;Docker&lt;/strong&gt;. Think of Docker as a &quot;robot&quot; that runs software for you in a neat, isolated box so it doesn&apos;t mess up your actual computer.&lt;/p&gt;
&lt;hr /&gt;
&lt;h3&gt;&lt;strong&gt;Phase 1: Get the Tools&lt;/strong&gt;&lt;/h3&gt;
&lt;p&gt;Before we do anything, you need the engine that runs the server.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Download Docker Desktop:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Go to &lt;a href=&quot;https://www.docker.com/products/docker-desktop/&quot;&gt;docker.com/products/docker-desktop&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Download it for your OS (Windows or Mac).&lt;/li&gt;
&lt;li&gt;Install it just like any other program (Next, Next, Finish).&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Crucial Step:&lt;/strong&gt; Once installed, &lt;strong&gt;OPEN Docker Desktop&lt;/strong&gt;. It must be running in the background. If it asks you to log in, you can usually skip it or create a free account.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Open your &quot;Command Center&quot; (Terminal):&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Windows:&lt;/strong&gt; Press the &lt;code&gt;Windows Key&lt;/code&gt;, type &lt;code&gt;PowerShell&lt;/code&gt;, and hit Enter.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Mac:&lt;/strong&gt; Press &lt;code&gt;Command + Space&lt;/code&gt;, type &lt;code&gt;Terminal&lt;/code&gt;, and hit Enter.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;hr /&gt;
&lt;h3&gt;&lt;strong&gt;Phase 2: Create the Server Folder (The &quot;cd&quot; stuff)&lt;/strong&gt;&lt;/h3&gt;
&lt;p&gt;You need a specific place on your computer where your server files will live. We will do this using the terminal to get you comfortable with it.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Type this command&lt;/strong&gt; to create a folder named &lt;code&gt;mc-server&lt;/code&gt; (and press Enter):&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;mkdir mc-server
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;em&gt;(Note: &lt;code&gt;mkdir&lt;/code&gt; stands for &quot;Make Directory&quot;.)&lt;/em&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Type this command&lt;/strong&gt; to &quot;walk inside&quot; that folder:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;cd mc-server
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;em&gt;(Note: &lt;code&gt;cd&lt;/code&gt; stands for &quot;Change Directory&quot;. Your terminal prompt should now look different, showing &lt;code&gt;mc-server&lt;/code&gt; at the end.)&lt;/em&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;hr /&gt;
&lt;h3&gt;&lt;strong&gt;Phase 3: The Blueprint (docker-compose.yml)&lt;/strong&gt;&lt;/h3&gt;
&lt;p&gt;We need to give the Docker robot a set of instructions. This is called a &quot;Compose file&quot;. It tells Docker: &quot;I want Minecraft, I want Fabric, and I want it on this port.&quot;&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Create the file:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Windows:&lt;/strong&gt; Type &lt;code&gt;notepad docker-compose.yml&lt;/code&gt; and press Enter. It will ask if you want to create a new file. Click &lt;strong&gt;Yes&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Mac:&lt;/strong&gt; You can use TextEdit, but ensure it saves as plain text. Or just run &lt;code&gt;touch docker-compose.yml&lt;/code&gt; in the terminal to create it, then open that file with any text editor.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Copy and Paste the specific code:&lt;/strong&gt;
Copy the code block below exactly. Don&apos;t change anything yet.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;services:
  mc:
    image: itzg/minecraft-server
    container_name: my-fabric-server
    tty: true
    stdin_open: true
    ports:
      - &quot;25565:25565&quot;
    environment:
      EULA: &quot;TRUE&quot;
      TYPE: &quot;FABRIC&quot;
      VERSION: &quot;1.20.1&quot;
      MEMORY: &quot;4G&quot;
    volumes:
      - ./data:/data
    restart: unless-stopped
&lt;/code&gt;&lt;/pre&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Understand what you just pasted:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;image: itzg/minecraft-server&lt;/code&gt;: This downloads a pre-made Minecraft server created by a legend named &lt;em&gt;itzg&lt;/em&gt;.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;TYPE: &quot;FABRIC&quot;&lt;/code&gt;: Tells the server to use Fabric, not normal Minecraft.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;VERSION: &quot;1.20.1&quot;&lt;/code&gt;: &lt;strong&gt;Important.&lt;/strong&gt; This dictates the game version. Change this to whatever version you and your friends want to play.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;MEMORY: &quot;4G&quot;&lt;/code&gt;: Gives the server 4 Gigabytes of RAM. If your computer is weak, lower this to &quot;2G&quot;.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;volumes&lt;/code&gt;: This saves your world. It creates a folder called &lt;code&gt;data&lt;/code&gt; in your &lt;code&gt;mc-server&lt;/code&gt; folder so your world doesn&apos;t vanish when you turn the server off.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Save the file&lt;/strong&gt; and close the text editor.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;hr /&gt;
&lt;h3&gt;&lt;strong&gt;Phase 4: Start the Engine&lt;/strong&gt;&lt;/h3&gt;
&lt;p&gt;Now we tell Docker to read that file and build your server.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Go back to your terminal (make sure you are still inside the &lt;code&gt;mc-server&lt;/code&gt; folder).&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Run this command:&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;docker compose up -d
&lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;up&lt;/code&gt;: Start everything.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;-d&lt;/code&gt;: Detached mode. This means &quot;run in the background, don&apos;t lock up my terminal window.&quot;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Wait.&lt;/strong&gt; The first time you run this, it will take a while (5-10 mins) because it is downloading Minecraft, Fabric, and Java.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Check if it&apos;s working:&lt;/strong&gt;
Type this command to watch the logs (the server &quot;thinking&quot;):&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;docker compose logs -f
&lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;You will see a lot of text scrolling.&lt;/li&gt;
&lt;li&gt;Wait until you see a line that says: &lt;strong&gt;&lt;code&gt;Done (X.XXs)! For help, type &quot;help&quot;&lt;/code&gt;&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Press &lt;code&gt;Ctrl + C&lt;/code&gt;&lt;/strong&gt; to stop watching the logs (this &lt;strong&gt;does not&lt;/strong&gt; stop the server, it just stops the scrolling text).&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;strong&gt;Congratulations!&lt;/strong&gt; You now have a vanilla Fabric server running.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;IP Address:&lt;/strong&gt; &lt;code&gt;localhost&lt;/code&gt; (for you).&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;IP Address:&lt;/strong&gt; Your real IP (for friends—you will likely need to Port Forward your router for friends to join, but that is a separate networking topic).&lt;/li&gt;
&lt;/ul&gt;
&lt;hr /&gt;
&lt;h3&gt;&lt;strong&gt;Phase 5: Installing Mods (The &quot;Asshole Beginner&quot; Friendly Way)&lt;/strong&gt;&lt;/h3&gt;
&lt;p&gt;You probably want mods. Here is the safest way to do it.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Step 1: Turn off the server&lt;/strong&gt;
You cannot add mods while the server is running.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;docker compose down
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;Step 2: Locate the mods folder&lt;/strong&gt;&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Open your regular file explorer (Finder on Mac, File Explorer on Windows).&lt;/li&gt;
&lt;li&gt;Find the &lt;code&gt;mc-server&lt;/code&gt; folder we created in Phase 2.&lt;/li&gt;
&lt;li&gt;Inside, you will see a new folder called &lt;code&gt;data&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Inside &lt;code&gt;data&lt;/code&gt;, you will see a folder called &lt;code&gt;mods&lt;/code&gt;.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;strong&gt;Step 3: Download your mods&lt;/strong&gt;&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Go to Modrinth or CurseForge.&lt;/li&gt;
&lt;li&gt;Download the &lt;strong&gt;Fabric&lt;/strong&gt; version of the mod.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;CRITICAL:&lt;/strong&gt; The mod version MUST match your server version (e.g., if server is 1.20.1, mod must be 1.20.1).&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;CRITICAL:&lt;/strong&gt; You must also download the &lt;strong&gt;Fabric API&lt;/strong&gt; mod. Almost all Fabric mods require this. Put it in the folder too.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;strong&gt;Step 4: Drag and Drop&lt;/strong&gt;
Drag the &lt;code&gt;.jar&lt;/code&gt; files you downloaded into that &lt;code&gt;mc-server/data/mods&lt;/code&gt; folder.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Step 5: Turn the server back on&lt;/strong&gt;
Go back to your terminal:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;docker compose up -d
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Watch the logs again (&lt;code&gt;docker compose logs -f&lt;/code&gt;) to make sure the server doesn&apos;t crash. If it crashes, one of your mods is probably the wrong version.&lt;/p&gt;
&lt;hr /&gt;
&lt;h3&gt;&lt;strong&gt;Phase 6: You are the Admin (OP Yourself)&lt;/strong&gt;&lt;/h3&gt;
&lt;p&gt;You want to be able to ban people or switch to creative mode. You need to access the server console.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Run this command&lt;/strong&gt; to execute the admin tool inside the server:&lt;pre&gt;&lt;code&gt;docker exec -i my-fabric-server rcon-cli
&lt;/code&gt;&lt;/pre&gt;
&lt;/li&gt;
&lt;li&gt;Your terminal prompt will change to something like &lt;code&gt;&amp;gt;&lt;/code&gt;. You are now talking directly to the Minecraft server.&lt;/li&gt;
&lt;li&gt;Type:&lt;pre&gt;&lt;code&gt;op YourMinecraftUsername
&lt;/code&gt;&lt;/pre&gt;
(Replace &lt;code&gt;YourMinecraftUsername&lt;/code&gt; with your actual in-game name).&lt;/li&gt;
&lt;li&gt;It should say &quot;Made YourMinecraftUsername a server operator&quot;.&lt;/li&gt;
&lt;li&gt;Type &lt;code&gt;exit&lt;/code&gt; to leave the admin console.&lt;/li&gt;
&lt;/ol&gt;
&lt;hr /&gt;
&lt;h3&gt;&lt;strong&gt;Phase 7: The &quot;Cheat Sheet&quot; for Daily Use&lt;/strong&gt;&lt;/h3&gt;
&lt;p&gt;Save this list. These are the only commands you need to know.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Turn Server ON:&lt;/strong&gt;
&lt;code&gt;docker compose up -d&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Turn Server OFF:&lt;/strong&gt;
&lt;code&gt;docker compose down&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Restart Server (after adding new mods):&lt;/strong&gt;
&lt;code&gt;docker compose restart&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Check Server Status/Logs:&lt;/strong&gt;
&lt;code&gt;docker compose logs -f&lt;/code&gt;
&lt;em&gt;(Press Ctrl+C to exit logs)&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Access Admin Console:&lt;/strong&gt;
&lt;code&gt;docker exec -i my-fabric-server rcon-cli&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;&lt;strong&gt;Summary of Common Mistakes&lt;/strong&gt;&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Client/Server Mismatch:&lt;/strong&gt; You need to install Fabric and the &lt;strong&gt;exact same mods&lt;/strong&gt; on your own computer&apos;s Minecraft Launcher to join the server.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Wrong Java Version:&lt;/strong&gt; If you change the Minecraft version to an old one (like 1.12), the server might fail. The &lt;code&gt;itzg&lt;/code&gt; image usually handles this automatically, but stick to versions 1.18+ for the smoothest experience with this guide.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;EULA:&lt;/strong&gt; If you edited the file and didn&apos;t put &lt;code&gt;EULA: &quot;TRUE&quot;&lt;/code&gt;, the server will immediately shut down.&lt;/li&gt;
&lt;/ol&gt;
</content:encoded></item><item><title>Isolated Kubernetes Cluster on Proxmox with Terraform and Ansible - part 1</title><link>https://blog.hrnph.dev/posts/k8s-ansible-terraform-proxmox-tutorial/</link><guid isPermaLink="true">https://blog.hrnph.dev/posts/k8s-ansible-terraform-proxmox-tutorial/</guid><description>Step-by-step guide to building a fully self-hosted, isolated Kubernetes cluster using Proxmox, Terraform, Ansible, MicroK8s packed with Rancher, and ArgoCD accessible via local domain properly - without wasting your home network IPs.</description><pubDate>Sun, 27 Apr 2025 00:00:00 GMT</pubDate><content:encoded>&lt;h1&gt;Introduction&lt;/h1&gt;
&lt;p&gt;In this blog, I show you how to built a &lt;strong&gt;self-hosted Kubernetes cluster&lt;/strong&gt; on &lt;strong&gt;Proxmox&lt;/strong&gt; using &lt;strong&gt;Terraform&lt;/strong&gt;, &lt;strong&gt;Ansible&lt;/strong&gt;, &lt;strong&gt;MicroK8s&lt;/strong&gt;, &lt;strong&gt;Rancher&lt;/strong&gt;, and &lt;strong&gt;ArgoCD&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;::github{repo=&quot;hrnph/Proxmox-k8s-Terraform&quot;}&lt;/p&gt;
&lt;h2&gt;What you will get&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;A fully functional Kubernetes cluster with Rancher and ArgoCD&lt;/li&gt;
&lt;li&gt;A self-hosted solution with no external dependencies&lt;/li&gt;
&lt;li&gt;An easy to modify and extend templates&lt;/li&gt;
&lt;li&gt;A clear? understanding of how to set up a Kubernetes cluster on Proxmox&lt;/li&gt;
&lt;li&gt;A clear? understanding of how to use Terraform and Ansible for infrastructure automation&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;:::note
I did this project for my r/homelab, so I don&apos;t have a lot of resources like r/homedatacenter.
with a single Proxmox node with 32GB of RAM and 12 CPU cores.
I love HP Prodesk for this job and you should too for a low budget homelab.
:::&lt;/p&gt;
&lt;hr /&gt;
&lt;h1&gt;Overview Diagram&lt;/h1&gt;
&lt;p&gt;&lt;img src=&quot;./0-flow.svg&quot; alt=&quot;Diagram&quot; /&gt;&lt;/p&gt;
&lt;h2&gt;Design Decision &amp;amp; Planning of what we want to achieve&lt;/h2&gt;
&lt;p&gt;Before building the cluster, the following goals were set&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;✅ &lt;strong&gt;Complete network isolation:&lt;/strong&gt; The Kubernetes cluster should not pollute or consume home LAN IP addresses unnecessarily.&lt;/li&gt;
&lt;li&gt;✅ &lt;strong&gt;Controlled external access:&lt;/strong&gt; Only intentional, limited ingress into the cluster (e.g., Rancher/ArgoCD UIs) should be exposed.&lt;/li&gt;
&lt;li&gt;✅ &lt;strong&gt;Infrastructure as Code (IaC):&lt;/strong&gt; Both VM creation (Terraform) and configuration (Ansible) must be fully automated and reproducible.&lt;/li&gt;
&lt;li&gt;✅ &lt;strong&gt;Lightweight Kubernetes:&lt;/strong&gt; Using MicroK8s for a minimal, fast, HA-capable cluster.&lt;/li&gt;
&lt;li&gt;✅ &lt;strong&gt;Modern management UIs:&lt;/strong&gt; Deploy Rancher and ArgoCD for visual cluster and app control.&lt;/li&gt;
&lt;li&gt;✅ &lt;strong&gt;SSH Gateway (Jumpbox):&lt;/strong&gt; Centralized, secured SSH access via a single VM, without needing to expose cluster nodes individually and we can turn this off without affecting the cluster, like if you don&apos;t need local dns access via to master-nodes anymore ex using tailscale or cloudflare tunnels/warps or whatever you want to use.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Key Components and Flow&lt;/h3&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Component&lt;/th&gt;
&lt;th&gt;Purpose&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Proxmox&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Hypervisor that hosts all VMs.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Terraform&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Automates VM provisioning inside Proxmox.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;VMs&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Cluster nodes (Masters, Workers, Jumpbox) created via Terraform.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Jumpbox&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Secure SSH gateway into the cluster private network.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Ansible&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Automates installation and configuration of MicroK8s, Rancher, and ArgoCD.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;MicroK8s&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Kubernetes cluster running across master and worker VMs.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Ingress Controller&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Routes traffic internally from user DNS requests to services.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Rancher &amp;amp; ArgoCD UIs&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Management UIs for the cluster and GitOps applications.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;DNS (Pi-hole or /etc/hosts)&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Local resolution of friendly service names to the exposed master node IP.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Cloudflare Tunnels&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Secure external access to services without exposing IPs, All still defined in Terraform. (for now you can actually just use cloudflare tunnels on jumpbox or master-1)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h3&gt;Security Choices&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Only &lt;code&gt;master-1&lt;/code&gt; exposes a LAN IP (192.168.1.250) for ingress traffic.&lt;/li&gt;
&lt;li&gt;No internal cluster node can initiate outbound connections into the home network.&lt;/li&gt;
&lt;li&gt;Jumpbox can be destroyed after provisioning for improved security hardening.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Why MicroK8s?&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Fast deployment and updates via Snap packages&lt;/li&gt;
&lt;li&gt;Lightweight but HA-capable Kubernetes&lt;/li&gt;
&lt;li&gt;Built-in Helm 3, Ingress, and Cert-Manager&lt;/li&gt;
&lt;li&gt;No etcd dependency (uses Dqlite HA by default)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;:::tip
This design replicates cloud provider Private Subnets inside a homelab environment.
:::&lt;/p&gt;
&lt;hr /&gt;
&lt;h1&gt;Step 0: Prerequisites&lt;/h1&gt;
&lt;p&gt;Clone my template repository&lt;/p&gt;
&lt;p&gt;::github{repo=&quot;hrnph/Proxmox-k8s-Terraform&quot;}&lt;/p&gt;
&lt;h1&gt;Step 1: Proxmox Networking&lt;/h1&gt;
&lt;p&gt;Create &lt;code&gt;vmbr0&lt;/code&gt; (LAN) and &lt;code&gt;vmbr1&lt;/code&gt; (Cluster):&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;# /etc/network/interfaces

auto vmbr0
iface vmbr0 inet static
    address 192.168.1.100/24
    gateway 192.168.1.1
    bridge_ports eno1
    bridge_stp off
    bridge_fd 0

auto vmbr1
iface vmbr1 inet static
    address 192.168.3.1/24
    bridge_ports none
    bridge_stp off
    bridge_fd 0
    post-up echo 1 &amp;gt; /proc/sys/net/ipv4/ip_forward
    post-up iptables -t nat -A POSTROUTING -s 192.168.3.0/24 -o vmbr0 -j MASQUERADE
    post-down iptables -t nat -D POSTROUTING -s 192.168.3.0/24 -o vmbr0 -j MASQUERADE
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;✅ Cluster nodes have isolated internet access.&lt;/p&gt;
&lt;hr /&gt;
&lt;h1&gt;Step 2: Terraform VM Provisioning&lt;/h1&gt;
&lt;p&gt;Prepare your terraform.tfvars file with your Proxmox login and IPs.&lt;/p&gt;
&lt;p&gt;:::tip
2 Master 3 Workers Setup (should go to 3 for Acutal HA, but whatever, this is a good start)
:::&lt;/p&gt;
&lt;p&gt;:::important
You need to also modified the inventory.ini file if you modified the cluster_vms
:::&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;pm_password    = &quot;your-password&quot;
template_id    = &quot;your-cloudinit-template-id&quot;
target_node    = &quot;your-proxmox-node&quot;
ssh_public_key = &quot;your-ssh-public-key&quot;

cluster_vms = [
  { name = &quot;master-1&quot;, ip = &quot;192.168.3.11&quot;, cores = 2, memory = 4096, disk = 32 },
  { name = &quot;master-2&quot;, ip = &quot;192.168.3.12&quot;, cores = 2, memory = 4096, disk = 32 },
  { name = &quot;worker-1&quot;, ip = &quot;192.168.3.21&quot;, cores = 2, memory = 4096, disk = 32 },
  { name = &quot;worker-2&quot;, ip = &quot;192.168.3.22&quot;, cores = 2, memory = 4096, disk = 32 },
  { name = &quot;worker-3&quot;, ip = &quot;192.168.3.23&quot;, cores = 2, memory = 4096, disk = 32 },
]
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;terraform init
terraform plan -out ./plans/1-init
terraform apply ./plans/1-init
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;What is happening&lt;/h2&gt;
&lt;p&gt;Terraform creates VMs in Proxmox using the specified template and cloud-init configuration.
By using the &lt;code&gt;cloud-init&lt;/code&gt; template, it sets up the VMs with the specified IPs and resources.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;2 Masters&lt;/li&gt;
&lt;li&gt;3 Workers&lt;/li&gt;
&lt;li&gt;1 Jumpbox (for SSH)&lt;/li&gt;
&lt;/ul&gt;
&lt;hr /&gt;
&lt;h1&gt;Step 3: Ansible Cluster Configuration&lt;/h1&gt;
&lt;pre&gt;&lt;code&gt;ansible-playbook -i inventory.ini playbook.yml
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;What is happening&lt;/h2&gt;
&lt;p&gt;Ansible configures the VMs by accessing the VMs via SSH through the jumpbox.
Each node and also te jumpy is configured in the inventory.ini file that ansible use.
Ansible then ssh into the jumpbox and then into the master-1 node to install microk8s.
and continues to install microk8s on the other nodes.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Install MicroK8s&lt;/li&gt;
&lt;li&gt;HA cluster setup (Join the cluster to the cluster)&lt;/li&gt;
&lt;li&gt;Rancher + ArgoCD deployment&lt;/li&gt;
&lt;li&gt;Expose via Ingress&lt;/li&gt;
&lt;/ul&gt;
&lt;hr /&gt;
&lt;h1&gt;Step 4: Access Rancher and ArgoCD&lt;/h1&gt;
&lt;p&gt;DNS Mapping:
This can be done in your router or &lt;code&gt;/etc/hosts&lt;/code&gt; file.
by adding the following lines to your &lt;code&gt;/etc/hosts&lt;/code&gt; file for linux and macOS&lt;/p&gt;
&lt;p&gt;:::note
help yourself if you are using Windows, not my forté
:::&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;192.168.1.250 rancher.madoka
192.168.1.250 argocd.madoka
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Then access:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Rancher: &lt;code&gt;https://rancher.madoka&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;ArgoCD: &lt;code&gt;https://argocd.madoka&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;✅ Full UI access secured.&lt;/p&gt;
&lt;hr /&gt;
&lt;h1&gt;📂 Important File Overview&lt;/h1&gt;
&lt;p&gt;This section explains the key files in this repository, what they do, and why they matter.&lt;br /&gt;
&lt;strong&gt;If you&apos;re new to Terraform or Ansible&lt;/strong&gt;, read this carefully before editing!&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;File / Folder&lt;/th&gt;
&lt;th&gt;Purpose&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;main.tf&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Defines the infrastructure Terraform will create: VMs for Kubernetes masters, workers, and the jumpbox.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;terraform.tfvars.example&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;A sample file showing what variables you need to define for Terraform (Proxmox login, cluster IPs, VM specs). Copy to &lt;code&gt;terraform.tfvars&lt;/code&gt; and edit your values.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;terraform.tfvars&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Your actual Terraform variable configuration. Sensitive information like Proxmox API password, SSH public key, cluster VM details are placed here.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;inventory.ini&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Ansible inventory file. Lists all VM IPs and configures SSH access via the jumpbox. Must match the IPs used in &lt;code&gt;terraform.tfvars&lt;/code&gt;.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;playbook.yml&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Main Ansible playbook. Automates the setup of MicroK8s, Rancher, and ArgoCD across the cluster. Fully sequential and clean.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;/plans/&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Terraform plans (output from &lt;code&gt;terraform plan -out&lt;/code&gt;). Used to pre-approve and manage infrastructure changes safely.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;.terraform/&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Terraform working directory (created by &lt;code&gt;terraform init&lt;/code&gt;). Contains plugins, backend data. No need to touch manually.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;terraform.tfstate&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Terraform state file. Tracks everything Terraform created. &lt;strong&gt;Do not edit manually.&lt;/strong&gt; Keep it safe to manage future changes.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;/roles/&lt;/code&gt; (optional)&lt;/td&gt;
&lt;td&gt;Empty or deprecated for now. Originally for modular Ansible roles but merged into &lt;code&gt;playbook.yml&lt;/code&gt; for simplicity.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;README.md&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Full documentation of the project, setup steps, file explanations, and additional tips for modification.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;hr /&gt;
&lt;h1&gt;Final Thoughts&lt;/h1&gt;
&lt;p&gt;✅ Secure Kubernetes cluster&lt;br /&gt;
✅ Rancher and ArgoCD fully operational&lt;br /&gt;
✅ Infrastructure as code&lt;br /&gt;
✅ Minimal home network exposure&lt;/p&gt;
&lt;hr /&gt;
&lt;p&gt;:::tip
Next upgrade will be adding Cloudflare Tunnels for public network access.
This is a great way to expose services without exposing your home network IPs.&lt;/p&gt;
&lt;p&gt;for now you can actually just use cloudflare tunnels on jumpbox or master-1, This is also applied to tailscale or whatever you want to use
:::&lt;/p&gt;
</content:encoded></item><item><title>Markdown Extended Features</title><link>https://blog.hrnph.dev/posts/markdown-extended/</link><guid isPermaLink="true">https://blog.hrnph.dev/posts/markdown-extended/</guid><description>Read more about Markdown features in Fuwari</description><pubDate>Wed, 01 May 2024 00:00:00 GMT</pubDate><content:encoded>&lt;h2&gt;GitHub Repository Cards&lt;/h2&gt;
&lt;p&gt;You can add dynamic cards that link to GitHub repositories, on page load, the repository information is pulled from the GitHub API.&lt;/p&gt;
&lt;p&gt;::github{repo=&quot;Fabrizz/MMM-OnSpotify&quot;}&lt;/p&gt;
&lt;p&gt;Create a GitHub repository card with the code &lt;code&gt;::github{repo=&quot;&amp;lt;owner&amp;gt;/&amp;lt;repo&amp;gt;&quot;}&lt;/code&gt;.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;::github{repo=&quot;saicaca/fuwari&quot;}
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;Admonitions&lt;/h2&gt;
&lt;p&gt;Following types of admonitions are supported: &lt;code&gt;note&lt;/code&gt; &lt;code&gt;tip&lt;/code&gt; &lt;code&gt;important&lt;/code&gt; &lt;code&gt;warning&lt;/code&gt; &lt;code&gt;caution&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;:::note
Highlights information that users should take into account, even when skimming.
:::&lt;/p&gt;
&lt;p&gt;:::tip
Optional information to help a user be more successful.
:::&lt;/p&gt;
&lt;p&gt;:::important
Crucial information necessary for users to succeed.
:::&lt;/p&gt;
&lt;p&gt;:::warning
Critical content demanding immediate user attention due to potential risks.
:::&lt;/p&gt;
&lt;p&gt;:::caution
Negative potential consequences of an action.
:::&lt;/p&gt;
&lt;h3&gt;Basic Syntax&lt;/h3&gt;
&lt;pre&gt;&lt;code&gt;:::note
Highlights information that users should take into account, even when skimming.
:::

:::tip
Optional information to help a user be more successful.
:::
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;Custom Titles&lt;/h3&gt;
&lt;p&gt;The title of the admonition can be customized.&lt;/p&gt;
&lt;p&gt;:::note[MY CUSTOM TITLE]
This is a note with a custom title.
:::&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;:::note[MY CUSTOM TITLE]
This is a note with a custom title.
:::
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;GitHub Syntax&lt;/h3&gt;
&lt;blockquote&gt;
&lt;p&gt;[!TIP]
&lt;a href=&quot;https://github.com/orgs/community/discussions/16925&quot;&gt;The GitHub syntax&lt;/a&gt; is also supported.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;pre&gt;&lt;code&gt;&amp;gt; [!NOTE]
&amp;gt; The GitHub syntax is also supported.

&amp;gt; [!TIP]
&amp;gt; The GitHub syntax is also supported.
&lt;/code&gt;&lt;/pre&gt;
</content:encoded></item><item><title>Simple Guides for Fuwari</title><link>https://blog.hrnph.dev/posts/guide/</link><guid isPermaLink="true">https://blog.hrnph.dev/posts/guide/</guid><description>How to use this blog template.</description><pubDate>Mon, 01 Apr 2024 00:00:00 GMT</pubDate><content:encoded>&lt;blockquote&gt;
&lt;p&gt;Cover image source: &lt;a href=&quot;https://image.civitai.com/xG1nkqKTMzGDvpLrqFT7WA/208fc754-890d-4adb-9753-2c963332675d/width=2048/01651-1456859105-(colour_1.5),girl,_Blue,yellow,green,cyan,purple,red,pink,_best,8k,UHD,masterpiece,male%20focus,%201boy,gloves,%20ponytail,%20long%20hair,.jpeg&quot;&gt;Source&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;This blog template is built with &lt;a href=&quot;https://astro.build/&quot;&gt;Astro&lt;/a&gt;. For the things that are not mentioned in this guide, you may find the answers in the &lt;a href=&quot;https://docs.astro.build/&quot;&gt;Astro Docs&lt;/a&gt;.&lt;/p&gt;
&lt;h2&gt;Front-matter of Posts&lt;/h2&gt;
&lt;pre&gt;&lt;code&gt;---
title: My First Blog Post
published: 2023-09-09
description: This is the first post of my new Astro blog.
image: ./cover.jpg
tags: [Foo, Bar]
category: Front-end
draft: false
---
&lt;/code&gt;&lt;/pre&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Attribute&lt;/th&gt;
&lt;th&gt;Description&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;title&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;The title of the post.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;published&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;The date the post was published.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;description&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;A short description of the post. Displayed on index page.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;image&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;The cover image path of the post.&amp;lt;br/&amp;gt;1. Start with &lt;code&gt;http://&lt;/code&gt; or &lt;code&gt;https://&lt;/code&gt;: Use web image&amp;lt;br/&amp;gt;2. Start with &lt;code&gt;/&lt;/code&gt;: For image in &lt;code&gt;public&lt;/code&gt; dir&amp;lt;br/&amp;gt;3. With none of the prefixes: Relative to the markdown file&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;tags&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;The tags of the post.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;category&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;The category of the post.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;draft&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;If this post is still a draft, which won&apos;t be displayed.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h2&gt;Where to Place the Post Files&lt;/h2&gt;
&lt;p&gt;Your post files should be placed in &lt;code&gt;src/content/posts/&lt;/code&gt; directory. You can also create sub-directories to better organize your posts and assets.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;src/content/posts/
├── post-1.md
└── post-2/
    ├── cover.png
    └── index.md
&lt;/code&gt;&lt;/pre&gt;
</content:encoded></item><item><title>Markdown Example</title><link>https://blog.hrnph.dev/posts/markdown/</link><guid isPermaLink="true">https://blog.hrnph.dev/posts/markdown/</guid><description>A simple example of a Markdown blog post.</description><pubDate>Sun, 01 Oct 2023 00:00:00 GMT</pubDate><content:encoded>&lt;h1&gt;An h1 header&lt;/h1&gt;
&lt;p&gt;Paragraphs are separated by a blank line.&lt;/p&gt;
&lt;p&gt;2nd paragraph. &lt;em&gt;Italic&lt;/em&gt;, &lt;strong&gt;bold&lt;/strong&gt;, and &lt;code&gt;monospace&lt;/code&gt;. Itemized lists
look like:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;this one&lt;/li&gt;
&lt;li&gt;that one&lt;/li&gt;
&lt;li&gt;the other one&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Note that --- not considering the asterisk --- the actual text
content starts at 4-columns in.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Block quotes are
written like so.&lt;/p&gt;
&lt;p&gt;They can span multiple paragraphs,
if you like.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Use 3 dashes for an em-dash. Use 2 dashes for ranges (ex., &quot;it&apos;s all
in chapters 12--14&quot;). Three dots ... will be converted to an ellipsis.
Unicode is supported. ☺&lt;/p&gt;
&lt;h2&gt;An h2 header&lt;/h2&gt;
&lt;p&gt;Here&apos;s a numbered list:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;first item&lt;/li&gt;
&lt;li&gt;second item&lt;/li&gt;
&lt;li&gt;third item&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Note again how the actual text starts at 4 columns in (4 characters
from the left side). Here&apos;s a code sample:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;# Let me re-iterate ...
for i in 1 .. 10 { do-something(i) }
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;As you probably guessed, indented 4 spaces. By the way, instead of
indenting the block, you can use delimited blocks, if you like:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;define foobar() {
    print &quot;Welcome to flavor country!&quot;;
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;(which makes copying &amp;amp; pasting easier). You can optionally mark the
delimited block for Pandoc to syntax highlight it:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;import time
# Quick, count to ten!
for i in range(10):
    # (but not *too* quick)
    time.sleep(0.5)
    print i
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;An h3 header&lt;/h3&gt;
&lt;p&gt;Now a nested list:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;First, get these ingredients:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;carrots&lt;/li&gt;
&lt;li&gt;celery&lt;/li&gt;
&lt;li&gt;lentils&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Boil some water.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Dump everything in the pot and follow
this algorithm:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt; find wooden spoon
 uncover pot
 stir
 cover pot
 balance wooden spoon precariously on pot handle
 wait 10 minutes
 goto first step (or shut off burner when done)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Do not bump wooden spoon or it will fall.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Notice again how text always lines up on 4-space indents (including
that last line which continues item 3 above).&lt;/p&gt;
&lt;p&gt;Here&apos;s a link to &lt;a href=&quot;http://foo.bar&quot;&gt;a website&lt;/a&gt;, to a &lt;a href=&quot;local-doc.html&quot;&gt;local
doc&lt;/a&gt;, and to a &lt;a href=&quot;#an-h2-header&quot;&gt;section heading in the current
doc&lt;/a&gt;. Here&apos;s a footnote [^1].&lt;/p&gt;
&lt;p&gt;[^1]: Footnote text goes here.&lt;/p&gt;
&lt;p&gt;Tables can look like this:&lt;/p&gt;
&lt;p&gt;size material color&lt;/p&gt;
&lt;hr /&gt;
&lt;p&gt;9 leather brown
10 hemp canvas natural
11 glass transparent&lt;/p&gt;
&lt;p&gt;Table: Shoes, their sizes, and what they&apos;re made of&lt;/p&gt;
&lt;p&gt;(The above is the caption for the table.) Pandoc also supports
multi-line tables:&lt;/p&gt;
&lt;hr /&gt;
&lt;p&gt;keyword text&lt;/p&gt;
&lt;hr /&gt;
&lt;p&gt;red Sunsets, apples, and
other red or reddish
things.&lt;/p&gt;
&lt;p&gt;green Leaves, grass, frogs
and other things it&apos;s
not easy being.&lt;/p&gt;
&lt;hr /&gt;
&lt;p&gt;A horizontal rule follows.&lt;/p&gt;
&lt;hr /&gt;
&lt;p&gt;Here&apos;s a definition list:&lt;/p&gt;
&lt;p&gt;apples
: Good for making applesauce.
oranges
: Citrus!
tomatoes
: There&apos;s no &quot;e&quot; in tomatoe.&lt;/p&gt;
&lt;p&gt;Again, text is indented 4 spaces. (Put a blank line between each
term/definition pair to spread things out more.)&lt;/p&gt;
&lt;p&gt;Here&apos;s a &quot;line block&quot;:&lt;/p&gt;
&lt;p&gt;| Line one
| Line too
| Line tree&lt;/p&gt;
&lt;p&gt;and images can be specified like so:&lt;/p&gt;
&lt;p&gt;Inline math equations go in like so: $\omega = d\phi / dt$. Display
math should get its own line and be put in in double-dollarsigns:&lt;/p&gt;
&lt;p&gt;$$I = \int \rho R^{2} dV$$&lt;/p&gt;
&lt;p&gt;And note that you can backslash-escape any punctuation characters
which you wish to be displayed literally, ex.: `foo`, *bar*, etc.&lt;/p&gt;
</content:encoded></item><item><title>Include Video in the Posts</title><link>https://blog.hrnph.dev/posts/video/</link><guid isPermaLink="true">https://blog.hrnph.dev/posts/video/</guid><description>This post demonstrates how to include embedded video in a blog post.</description><pubDate>Tue, 01 Aug 2023 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Just copy the embed code from YouTube or other platforms, and paste it in the markdown file.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;---
title: Include Video in the Post
published: 2023-10-19
// ...
---

&amp;lt;iframe width=&quot;100%&quot; height=&quot;468&quot; src=&quot;https://www.youtube.com/embed/5gIf0_xpFPI?si=N1WTorLKL0uwLsU_&quot; title=&quot;YouTube video player&quot; frameborder=&quot;0&quot; allowfullscreen&amp;gt;&amp;lt;/iframe&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;YouTube&lt;/h2&gt;
&lt;p&gt;&amp;lt;iframe width=&quot;100%&quot; height=&quot;468&quot; src=&quot;https://www.youtube.com/embed/5gIf0_xpFPI?si=N1WTorLKL0uwLsU_&quot; title=&quot;YouTube video player&quot; frameborder=&quot;0&quot; allow=&quot;accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share&quot; allowfullscreen&amp;gt;&amp;lt;/iframe&amp;gt;&lt;/p&gt;
&lt;h2&gt;Bilibili&lt;/h2&gt;
&lt;p&gt;&amp;lt;iframe width=&quot;100%&quot; height=&quot;468&quot; src=&quot;//player.bilibili.com/player.html?bvid=BV1fK4y1s7Qf&amp;amp;p=1&quot; scrolling=&quot;no&quot; border=&quot;0&quot; frameborder=&quot;no&quot; framespacing=&quot;0&quot; allowfullscreen=&quot;true&quot;&amp;gt; &amp;lt;/iframe&amp;gt;&lt;/p&gt;
</content:encoded></item></channel></rss>