<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Platform on mi-homes.org</title><link>https://mi-homes.org/docs/platform/</link><description>Recent content in Platform on mi-homes.org</description><generator>Hugo -- gohugo.io</generator><language>en-us</language><copyright>© 2026 Minh Phuong Nguyen</copyright><atom:link href="https://mi-homes.org/docs/platform/index.xml" rel="self" type="application/rss+xml"/><item><title>K3s</title><link>https://mi-homes.org/docs/k3s/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://mi-homes.org/docs/k3s/</guid><description>&lt;p&gt;This guide documents how to create Proxmox VMs using Terraform for use as Kubernetes nodes in a k3s cluster. The Terraform configuration clones a cloud-init template, assigns fixed IPs and SSH keys, and tags VMs for k3s roles so they can be targeted by &lt;code&gt;k3s-ansible&lt;/code&gt; or similar automation.&lt;/p&gt;

&lt;h2 class="relative group"&gt;Overview
 &lt;div id="overview" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#overview" aria-label="Anchor"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h2&gt;
&lt;p&gt;The setup provisions two groups of VMs:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;k3s masters&lt;/strong&gt; (3 VMs): control-plane nodes for the Kubernetes cluster&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;k3s workers&lt;/strong&gt; (2 VMs): worker nodes for running workloads&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;All VMs are created by &lt;strong&gt;full clone&lt;/strong&gt; from a cloud-init template (VM ID &lt;code&gt;9999&lt;/code&gt; in the examples). They receive static IPs, a common SSH user and public key, and Proxmox tags (&lt;code&gt;k3s&lt;/code&gt;, &lt;code&gt;master&lt;/code&gt; or &lt;code&gt;worker&lt;/code&gt;) for identification. After Terraform applies, you deploy k3s onto these VMs using Ansible or another method. This guide uses placeholders like &lt;code&gt;&amp;lt;subnet&amp;gt;&lt;/code&gt; and &lt;code&gt;&amp;lt;first-master-ip&amp;gt;&lt;/code&gt;; replace them with values that match your network.&lt;/p&gt;</description></item><item><title>Rancher</title><link>https://mi-homes.org/docs/rancher/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://mi-homes.org/docs/rancher/</guid><description>&lt;p&gt;This guide installs and operates &lt;a href="https://ranchermanager.docs.rancher.com/" target="_blank" rel="noreferrer"&gt;Rancher&lt;/a&gt; on an existing Kubernetes cluster using Helm and cert-manager.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Official docs:&lt;/strong&gt; &lt;a href="https://ranchermanager.docs.rancher.com/getting-started/installation-and-upgrade/install-upgrade-on-a-kubernetes-cluster" target="_blank" rel="noreferrer"&gt;Install/Upgrade Rancher on a Kubernetes Cluster&lt;/a&gt;&lt;/p&gt;

&lt;h2 class="relative group"&gt;Prerequisites
 &lt;div id="prerequisites" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#prerequisites" aria-label="Anchor"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Kubernetes cluster (K3s, RKE2, EKS, or any supported distribution)&lt;/li&gt;
&lt;li&gt;&lt;code&gt;kubectl&lt;/code&gt; and &lt;code&gt;Helm&lt;/code&gt; installed&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 class="relative group"&gt;Installation
 &lt;div id="installation" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#installation" aria-label="Anchor"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h2&gt;

&lt;h3 class="relative group"&gt;1. Add Helm repos
 &lt;div id="1-add-helm-repos" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#1-add-helm-repos" aria-label="Anchor"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h3&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;helm repo add rancher-stable https://releases.rancher.com/server-charts/stable
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;helm repo update&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 class="relative group"&gt;2. Create namespace
 &lt;div id="2-create-namespace" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#2-create-namespace" aria-label="Anchor"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h3&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;kubectl create namespace cattle-system&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 class="relative group"&gt;3. Install cert-manager
 &lt;div id="3-install-cert-manager" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#3-install-cert-manager" aria-label="Anchor"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h3&gt;
&lt;p&gt;Required for Rancher-generated TLS certificates (default). Skip if you use your own certificates (&lt;code&gt;ingress.tls.source=secret&lt;/code&gt;) or TLS termination on an external load balancer.&lt;/p&gt;</description></item><item><title>Helm</title><link>https://mi-homes.org/docs/helm/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://mi-homes.org/docs/helm/</guid><description>&lt;p&gt;Use commands below to install &lt;a href="https://helm.sh/" target="_blank" rel="noreferrer"&gt;Helm&lt;/a&gt;, the package manager for Kubernetes.&lt;/p&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;curl -fsSL -o get_helm.sh https://raw.githubusercontent.com/helm/helm/main/scripts/get-helm-3
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;chmod &lt;span style="color:#ae81ff"&gt;700&lt;/span&gt; get_helm.sh
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;./get_helm.sh
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;helm version&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;</description></item><item><title>HashiCorp Vault</title><link>https://mi-homes.org/docs/hashicorp-vault/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://mi-homes.org/docs/hashicorp-vault/</guid><description>&lt;p&gt;&lt;strong&gt;HashiCorp Vault&lt;/strong&gt; can hold API keys, database passwords, tokens, and other sensitive values so they never appear in Git or Helm values. A typical Kubernetes pattern is: &lt;strong&gt;Vault (KV v2)&lt;/strong&gt; → &lt;strong&gt;&lt;a href="https://mi-homes.org/docs/external-secrets-operator/" &gt;External Secrets Operator&lt;/a&gt;&lt;/strong&gt; → &lt;strong&gt;Kubernetes &lt;code&gt;Secret&lt;/code&gt;&lt;/strong&gt; → &lt;strong&gt;Pods&lt;/strong&gt; (env or volumes). Any workload that reads from a &lt;code&gt;Secret&lt;/code&gt; can use this flow; you only align Vault paths and &lt;code&gt;ExternalSecret&lt;/code&gt; fields with your app’s expectations.&lt;/p&gt;

&lt;h2 class="relative group"&gt;Role in the stack
 &lt;div id="role-in-the-stack" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#role-in-the-stack" aria-label="Anchor"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h2&gt;
&lt;pre class="not-prose mermaid"&gt;
flowchart LR
 subgraph git["Git"]
 VY[Helm values / manifests]
 NS[Namespace and wiring]
 end
 subgraph cluster["Cluster"]
 V[Vault KV v2]
 ESO[External Secrets Operator]
 KS[Kubernetes Secret]
 end
 VY --&gt; V
 NS --&gt; V
 ESO --&gt;|Vault API + token| V
 ESO --&gt; KS
&lt;/pre&gt;

&lt;p&gt;Vault must be &lt;strong&gt;running and unsealed&lt;/strong&gt; before &lt;code&gt;ClusterSecretStore&lt;/code&gt; and &lt;code&gt;ExternalSecret&lt;/code&gt; resources can sync. In GitOps setups, install &lt;strong&gt;Vault first&lt;/strong&gt;, then &lt;strong&gt;External Secrets Operator&lt;/strong&gt;, then applications that declare &lt;code&gt;ExternalSecret&lt;/code&gt; objects (or use equivalent sync waves / dependencies).&lt;/p&gt;</description></item><item><title>External Secrets Operator</title><link>https://mi-homes.org/docs/external-secrets-operator/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://mi-homes.org/docs/external-secrets-operator/</guid><description>&lt;p&gt;&lt;strong&gt;External Secrets Operator (ESO)&lt;/strong&gt; watches &lt;strong&gt;&lt;code&gt;ExternalSecret&lt;/code&gt;&lt;/strong&gt; resources and materializes ordinary Kubernetes &lt;strong&gt;&lt;code&gt;Secret&lt;/code&gt;&lt;/strong&gt; objects from an upstream backend. With &lt;a href="https://mi-homes.org/docs/hashicorp-vault/" &gt;HashiCorp Vault&lt;/a&gt; as the backend, the same pattern works for &lt;strong&gt;any application&lt;/strong&gt;: you store values in Vault, declare mappings in Git, and mount or env-inject the resulting &lt;code&gt;Secret&lt;/code&gt; as usual.&lt;/p&gt;

&lt;h2 class="relative group"&gt;Role in the stack
 &lt;div id="role-in-the-stack" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#role-in-the-stack" aria-label="Anchor"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h2&gt;
&lt;pre class="not-prose mermaid"&gt;
flowchart LR
 subgraph git["Git"]
 CSS[ClusterSecretStore]
 X[ExternalSecret per app]
 end
 subgraph cluster["Cluster"]
 ESO[External Secrets Operator]
 V[Vault KV v2]
 KS[Kubernetes Secret]
 P[Pods]
 end
 CSS --&gt; ESO
 X --&gt; ESO
 ESO --&gt;|token auth| V
 ESO --&gt;|reconcile| KS
 KS --&gt; P
&lt;/pre&gt;

&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;ClusterSecretStore&lt;/strong&gt; (cluster-scoped): one connection from the cluster to Vault (URL, mount, auth). Every namespace can reference it.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;ExternalSecret&lt;/strong&gt; (namespace-scoped): one per app (or per secret bundle), mapping Vault paths and properties to keys on a target &lt;code&gt;Secret&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;ESO &lt;strong&gt;reconciles&lt;/strong&gt; on an interval and when specs change.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Install ESO &lt;strong&gt;after&lt;/strong&gt; Vault is available and unsealable; install &lt;strong&gt;before&lt;/strong&gt; workloads that depend on synced secrets, or ensure those workloads tolerate a short delay until the &lt;code&gt;Secret&lt;/code&gt; exists.&lt;/p&gt;</description></item></channel></rss>