<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
  <title>bmel&#39;s blog</title>
  <subtitle>Helpful tech stories from your friend bmel</subtitle>
  <link href="http://localhost:8080"/>
  <link href="http://localhost:8080/feed.xml" rel="self"/>
  <updated>2025-11-29T12:30:00Z</updated>
  <id>http://localhost:8080</id>
  <author>
    <name>bmel</name>
    <email>bmel@bornstellar.org</email>
  </author>
    
    <entry>
      <title>Building a Secure VPS Over Untrusted Channels</title>
      <link href="http://localhost:8080/2019/05/04/building-a-secure-vps-over-untrusted-channels/"/>
      <updated>2019-05-04T17:44:03Z</updated>
      <id>http://localhost:8080/2019/05/04/building-a-secure-vps-over-untrusted-channels/</id>
      <content type="html">&lt;p&gt;If you have any need for an always on machine, subscribing to a virtual private server service might make more sense than going through the trouble of self-hosting. With offerings as low as $1 a month for 1xCPU and 1GB RAM offerings over seas, it’s more than possible to secure an always available machine for less than the cost of your morning coffee. The only flaw in this is that you have to trust your provider to keep the lights on, and not to snoop on your data. Because they’re hosting it for you, they have full access to the machine, with many providers even configuring SSH and setting the root password for you, meaning they have full root access. Even if you reconfigure SSH, change your root password, and take other measures to protect yourself, they could theoretically take a copy of your VPSs virtual disk and sniff around. For privacy minded folks like me, that’s a very compelling reason to take hosting matters back into my own hand, but as I’ve found through a process of trial and error, it is possible to work with these services to build secure and private servers without having to trust your provider to respect your privacy.&lt;/p&gt;
&lt;h3&gt;What you’ll need:&lt;/h3&gt;
&lt;p&gt;You’ll need to find a VPS provider that offers KVM virtual machines, and that provider will need to support uploading and booting from custom ISOs. OpenVZ or other container based virtual machines won’t work, because we’ll be encrypting our install at the partition level, which is impossible when your virtual machines disk is just a directory on someone else’s file system. I’ve hopped around through my fair share of providers and found that some providers support this and some don’t. I’ve had good luck with SeedVPS, VULTR, and Host4Fun in this respect. Whatever provider you choose will also need to offer VNC console access. Most providers who support uploading your own ISOs also provide this, sometimes through custom built control panels, and other times using a solution like SolusVM. These two features will allow us to boot into known-good live media and configure our server securely. Most providers have a pre-sales chat option where you can speak to a representative before purchasing, so you can ask before you buy. For this tutorial, I’ll be using a KVM VPS provided by SeedVPS&lt;/p&gt;
&lt;h2&gt;1: Log into your VPS control panel, mount your ISO and boot into it.&lt;/h2&gt;
&lt;p&gt;SeedVPS uses SolusVM control panel, so I can access my ISO features, gain VNC access, and reboot all from one page. This provider doesn’t allow me to upload my own ISO directly, but I can choose from a selection of available ISOs that suit my needs. I’ll be using the provided CentOS 7 Live Gnome ISO. CentOS live media has a feature where it can check the integrity of the media before booting, which I’ll use to verify that this ISO hasn’t been tampered with by my provider. Whatever media you use, you’ll need a graphical environment.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;http://localhost:8080/assets/images/2019/09/cpanel.png&quot; alt=&quot;image&quot; /&gt;&lt;/p&gt;
&lt;p&gt;Once the ISO is mounted, you can use the VNC console to connect to the VPS and reboot it. Most providers have a perfectly adequate HTML/Java VNC console, but also provide an IP address and port number that you can point your own VNC client to if you’d prefer. I’ll be using TigerVNC to connect. I’ll restart the machine as normal and then catch the boot prompt and tell it to boot from my ISO. For this specific CentOS media, the ‘check media and boot live’ option is hidden inside the troubleshooting menu.&lt;/p&gt;
&lt;h2&gt;2: Start your own encrypted VNC Server&lt;/h2&gt;
&lt;p&gt;Your hosting provider has provided you with a VNC connection that you can use to interact with your machine at the console level, but that doesn’t mean you should trust that connection. It’s possible for them to snoop on that traffic, and in other cases, providers won’t even bother to encrypt that traffic, meaning your keystrokes are sent over the internet in plain text. No thanks. In this step we’ll be using TigerVNC server to stand up our own VNC service using some randomly generated keys. From within your live media, open a terminal, switch to root, and install tigervnc-server:&lt;/p&gt;
&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;yum &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt;y install tigervnc&lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt;server&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&quot;http://localhost:8080/assets/images/2019/09/install_vnc_server.png&quot; alt=&quot;image&quot; /&gt;&lt;/p&gt;
&lt;p&gt;Now that the tigervnc-server package is installed, we can start our own VNC server from within our live host. For best security and privacy practices, we’ll use a random port, and tell the VNC server to use the TLSVnc security method. Don’t forget to open the port in your firewall too.&lt;/p&gt;
&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;firewall&lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt;cmd –zone&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; –add&lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt;port&lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1908&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt;tcp&lt;br /&gt;vncserver &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt;rfbport &lt;span class=&quot;token number&quot;&gt;1908&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt;SecurityTypes TLSVnc &lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&quot;http://localhost:8080/assets/images/2019/09/start_vnc_server.png&quot; alt=&quot;image&quot; /&gt;&lt;/p&gt;
&lt;h2&gt;3: Connect to your VPS over VNC and start the installer&lt;/h2&gt;
&lt;p&gt;Now that we have a trusted VNC connection to our host, we can enter a disk encryption key remotely without worrying about it being intercepted. Connect to your new VNC server using a VNC client of your choosing. This will drop you into a brand-new desktop session under a new user. If your VNC client supports it, you’ll notice that the connection is encrypted. You can also verify this with a packet capture. Here’s a capture of traffic to my providers unencrypted VNC server:&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;http://localhost:8080/assets/images/2019/09/unencrypted_vncsession.png&quot; alt=&quot;image&quot; /&gt;&lt;/p&gt;
&lt;p&gt;Here’s a connection to my own VNC Server:&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;http://localhost:8080/assets/images/2019/09/encrypted_vncsession.png&quot; alt=&quot;image&quot; /&gt;&lt;/p&gt;
&lt;p&gt;From within your new secure connection, you can start the live installer and install the OS as normal. On CentOS, You can do so by executing /usr/bin/liveinst from a shell. If you aren’t sure how to start the installer on your distro, you can normally find out by searching for an icon on the live user’s desktop.&lt;/p&gt;
&lt;p&gt;Go through the installer like you normally would. On the Installation Destination page, configure partitioning however you like and then check the ‘encrypt my data’ option. This is what will protect your VPS from unauthorized access. Disk encryption is only as strong as the key you use, so enter a strong password, and make sure you remember it because your system will be bricked if you forget it.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;http://localhost:8080/assets/images/2019/09/install_disk_selction.png&quot; alt=&quot;image&quot; /&gt;&lt;br /&gt;
&lt;img src=&quot;http://localhost:8080/assets/images/2019/09/install_disk_passphrase.png&quot; alt=&quot;image&quot; /&gt;&lt;br /&gt;
&lt;img src=&quot;http://localhost:8080/assets/images/2019/09/install_final.png&quot; alt=&quot;image&quot; /&gt;&lt;/p&gt;
&lt;p&gt;When the installer is finished, DO NOT REBOOT! We’ll configure the new install while it’s still mounted to the live OS.&lt;/p&gt;
&lt;h2&gt;4: Chroot into your new install and configure dracut&lt;/h2&gt;
&lt;p&gt;As of right now, we’ve booted into live media, stood up our own VNC server, and used that as a trusted control channel to configure our new operating system with an encrypted disk. Encrypting the disk protects your server from unauthorized access even when it’s offline, but it also requires that your provide the key whenever you start the machine. If we don’t configure a method to provide that key over a trusted channel, then we’ll be forced to send it through our providers un-trusted VNC connection as soon as we reboot, making all of this effort meaningless. To get around that, we’ll chroot into our new system and install Dracut, which will allow us to provide the key directly to our kernel using a special ssh server that we can configure.&lt;/p&gt;
&lt;p&gt;All of this step will take place within a terminal. You may find it easier to ssh into your server rather than try to type everything over VNC. I’m not sure about any other live mediums, but the CentOS live medium turns SSH off by default, and doesn’t require a password to log in as root. If you’re going to enable SSH, you should set a root password first. It will only take minutes for someone to find an unprotected root ssh login if it’s public facing.&lt;/p&gt;
&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;passwd root&lt;br /&gt;systemctl start sshd &lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;When the CentOS installer finished, it leaves the newly created system mounted. If your distro’s installer doesn’t behave this way, you’ll need to mount those partitions manually. You can check whether or not your new system is mounted, and where it’s mounted using the lsblk command:&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;http://localhost:8080/assets/images/2019/09/lsblk.png&quot; alt=&quot;image&quot; /&gt;&lt;/p&gt;
&lt;p&gt;In this example, my new root and boot partitions are neatly mounted at /mnt/sysimage, so I can chroot in there.&lt;/p&gt;
&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;chroot &lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt;mnt&lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt;sysimage &lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Install necessary packages:&lt;/p&gt;
&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;yum &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt;y install epel&lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt;release nano wget &lt;br /&gt;wget &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;O&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt;etc&lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt;yum&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;repos&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;d&lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt;rbu&lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt;dracut&lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt;crypt&lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt;ssh&lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt;epel&lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;7&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;repo https&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt;copr&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;fedorainfrabutt&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;org&lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt;coprs&lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt;rbu&lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt;dracut&lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt;crypt&lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt;ssh&lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt;repo&lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt;epel&lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;7&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt;rbu&lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt;dracut&lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt;crypt&lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt;ssh&lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt;epel&lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;7&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;repo&lt;br /&gt;yum &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt;y install dracut&lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt;crypt&lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt;ssh&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Edit your bootloader configuration to tell the kernel to connect to the network at startup:&lt;/p&gt;
&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;nano &lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt;etc&lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;default&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt;grub&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;insert rd.neednet=1 ip=dhcp before the rd.luks.uuid argument. Here’s my config file:&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;http://localhost:8080/assets/images/2019/09/default_grub.png&quot; alt=&quot;image&quot; /&gt;&lt;/p&gt;
&lt;p&gt;Rebuild your grub config&lt;/p&gt;
&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;grub2&lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt;mkconfig &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt;o &lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt;etc&lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt;grub2&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;cfg&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Backup the original dracut config file&lt;/p&gt;
&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;mv &lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt;etc&lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt;dracut&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;conf&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;d&lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt;crypt&lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt;ssh&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;conf &lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt;etc&lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt;dracut&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;conf&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;d&lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt;crypt&lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt;ssh&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;conf&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;orig &lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Build your new dracut config file&lt;/p&gt;
&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;nano &lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt;etc&lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt;dracut&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;conf&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;d&lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt;crypt&lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt;ssh&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;conf&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Insert these lines:&lt;/p&gt;
&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;token assign-left variable&quot;&gt;dropbear_acl&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;/etc/dropbear/keys/authorized_keys&quot;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token assign-left variable&quot;&gt;dropbear_ecdsa_key&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;/etc/dropbear/keys/ssh_ecdsa_key&quot;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token assign-left variable&quot;&gt;dropbear_rsa_key&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;/etc/dropbear/keys/ssh_rsa_key&quot;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Generate ssh server keys&lt;br /&gt;
image?&lt;/p&gt;
&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;ssh&lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt;keygen &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt;t ecdsa &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt;f &lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt;etc&lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt;dropbear&lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt;keys&lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt;ssh_ecdsa_key&lt;br /&gt;ssh&lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt;keygen &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt;t rsa &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt;f &lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt;etc&lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt;dropbear&lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt;keys&lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt;ssh_rsa_key&lt;br /&gt;chmod &lt;span class=&quot;token number&quot;&gt;400&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt;etc&lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt;dropbear&lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt;keys&lt;span class=&quot;token comment&quot;&gt;/*_key; sudo chmod 444 /etc/dropbear/keys/*.pub&amp;lt;/pre&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Generate private ssh files for authentication&lt;/p&gt;
&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;ssh-keygen &lt;span class=&quot;token parameter variable&quot;&gt;-t&lt;/span&gt; rsa&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&quot;http://localhost:8080/assets/images/2019/09/keypair.png&quot; alt=&quot;image&quot; /&gt;&lt;/p&gt;
&lt;p&gt;Copy your new private key into the authorised keys file&lt;/p&gt;
&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;cat &lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt;root&lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;ssh&lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt;id_rsa&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;pub &lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&quot;http://localhost:8080/assets/images/2019/09/paste_private_pub.png&quot; alt=&quot;image&quot; /&gt;&lt;/p&gt;
&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;nano &lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt;etc&lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt;dropbear&lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt;keys&lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt;authorized_keys &lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&quot;http://localhost:8080/assets/images/2019/09/paste_private_pub_two.png&quot; alt=&quot;image&quot; /&gt;&lt;/p&gt;
&lt;p&gt;Rebuild initramfs with dracut&lt;/p&gt;
&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;dracut &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt;f &lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;5: Reboot your VPS and connect to the dracut ssh server&lt;/h2&gt;
&lt;p&gt;Make sure to dismount your live media and reboot your VPS. When it comes back up you should see the disk passphrase prompt on the machines console. As soon as you see that you should be able to connect to the dracut ssh server. Connect to your VPS ip on port 222 using your new private key. Login as root, and issue the command ‘console_auth’ to enter they key. If it works, the connection will terminate after a few seconds. This means that the disk was unlocked and the system has booted.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;http://localhost:8080/assets/images/2019/09/console_auth.png&quot; alt=&quot;image&quot; /&gt;&lt;/p&gt;
&lt;h2&gt;Sources:&lt;/h2&gt;
&lt;p&gt;&lt;a href=&quot;https://www.vultr.com/docs/install-and-setup-centos-7-to-remotely-unlock-lvm-on-luks-disk-encryption-using-ssh&quot;&gt;VULTR Docs: Install and Setup CentOS 7 to Remotely Unlock LVM on LUKS Disk Encryption Using SSH&lt;/a&gt;&lt;br /&gt;
&lt;a href=&quot;https://github.com/dracutdevs/dracut&quot;&gt;Dracut Github&lt;/a&gt;&lt;/p&gt;
</content>
    </entry>
    
    <entry>
      <title>Managing SMB Version and Signing Requirements in a Windows Environment</title>
      <link href="http://localhost:8080/2019/06/07/managing-smb-version-and-signing-requirements-in-a-windows-environment/"/>
      <updated>2019-06-07T17:44:03Z</updated>
      <id>http://localhost:8080/2019/06/07/managing-smb-version-and-signing-requirements-in-a-windows-environment/</id>
      <content type="html">&lt;h2&gt;SMB Protocol support&lt;/h2&gt;
&lt;p&gt;In 2017 Microsoft released a security bulletin detailing a critical vulnerability in the SMBv1 protocol which in some cases can be used to achieve arbitrary code execution on a remote host. Microsoft has no intention of supporting the outdated protocol anymore, and it is now considered best practice to permanently Disable SMBv1. As of the time of writing (2017) Microsoft does suggest leaving SMBv2 and SMBv3 enabled. To test for this vulnerability, I used the Metasploit smb_ms17_010 scanner. Here’s an example of scanning a vulnerable host:&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;http://localhost:8080/assets/images/2019/06/ms17_scan.png&quot; alt=&quot;image&quot; /&gt;&lt;/p&gt;
&lt;p&gt;SMB versions cannot be controlled through a friendly GP template the way SMB signing can. Instead it must be manipulated through registry settings. SMB version support is defined in the registry key HKLM&#92;SYSTEM&#92;CurrentControlSet&#92;Services&#92;LanmanServer&#92;Parameters, where DWORD values in this key by the name of SMB versions control support for that version. As an example, here’s a key to disable SMBv1:&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;http://localhost:8080/assets/images/2019/06/SMB1_DWORD.png&quot; alt=&quot;image&quot; /&gt;&lt;/p&gt;
&lt;p&gt;Here’s an example of using metasploit to determine that SMBv1 is supported, disabling the protocol via GPO, and then verifying the results using the scanner:&lt;/p&gt;&lt;p&gt;&lt;/p&gt;
&lt;p&gt;Before:&lt;br /&gt;
&lt;img src=&quot;http://localhost:8080/assets/images/2019/06/SMBv1_before.png&quot; alt=&quot;image&quot; /&gt;&lt;/p&gt;
&lt;p&gt;After:&lt;br /&gt;
&lt;img src=&quot;http://localhost:8080/assets/images/2019/06/SMBv1_after.png&quot; alt=&quot;image&quot; /&gt;&lt;/p&gt;
&lt;p&gt;The same can be accomplished with nmap using this &lt;a href=&quot;https://nmap.org/nsedoc/scripts/smb-protocols.html&quot;&gt;auxiliary smb version scanner&lt;/a&gt;. Here’s an example of a nmap output for a host which does not require SMB singing:&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;http://localhost:8080/assets/images/2019/06/nmap_SMBv_scanner.png&quot; alt=&quot;image&quot; /&gt;&lt;/p&gt;
&lt;p&gt;SMB Signing&lt;/p&gt;
&lt;p&gt;By default, SMB singing is supported, but not required. SMB signing requirements can be configured through group policy. The Group Policy path is Computer Configuration &amp;gt; Windows Settings &amp;gt; Security Settings &amp;gt; Local Policies &amp;gt; Security Options. The applicable keys are:&lt;/p&gt;
&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt; Microsoft network server: Digitally sign communications &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;always&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;br /&gt; Microsoft network server: Digitally sign communications &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;if client agrees&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;/li&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;br /&gt; Microsoft network client: Digitally sign communications &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;always&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;br /&gt; Microsoft network client: Digitally sign communications &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;if server agrees&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;For each key you can set the client or server to force SMB signing, or to try SMB signing. If you configure the ‘if server/client agrees’ policy objects then SMB signing will not be enforced, but will be attempted. This would make it possible for malicious actors to force insecure SMB authentication to enable a relay attack. To enforce SMB signing, configure the ‘always’ keys. &lt;/p&gt;&lt;p&gt;&lt;/p&gt;
&lt;p&gt;To test whether a signing is required on a host, you can use this namp script &lt;a href=&quot;https://nmap.org/nsedoc/scripts/smb2-security-mode.html&quot;&gt;smb2-security-mode&lt;/a&gt;. Here’s an example of a nmap output for a host which does not require SMB singing:&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;http://localhost:8080/assets/images/2019/06/signing_scan_not_required.png&quot; alt=&quot;image&quot; /&gt;&lt;/p&gt;
&lt;p&gt;and another example of output from the same host where signing is required.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;http://localhost:8080/assets/images/2019/06/signing_scan_required.png&quot; alt=&quot;image&quot; /&gt;&lt;/p&gt;
&lt;h2&gt;Sources:&lt;/h2&gt;
&lt;p&gt;&lt;a href=&quot;https://docs.microsoft.com/en-us/security-updates/securitybulletins/2017/ms17-010&quot;&gt;Microsoft Security Bulletin MS17-010. docs.microsoft.com&lt;/a&gt;&lt;br /&gt;
&lt;a href=&quot;https://support.microsoft.com/en-gb/help/2696547/how-to-detect-enable-and-disable-smbv1-smbv2-and-smbv3-in-windows-and&quot;&gt;How to detect, enable and disable SMBv1, SMBv2, and SMBv3 in Windows and Windows Server. support.microsoft.com&lt;/a&gt;&lt;br /&gt;
&lt;a href=&quot;https://support.microsoft.com/en-us/help/823659/client-service-and-program-issues-can-occur-if-you-change-security-set&quot;&gt;Client, service, and program issues can occur if you change security settings and user rights assignments. support.microsoft.com&lt;/a&gt;&lt;br /&gt;
&lt;a href=&quot;https://www.rootusers.com/configure-smb-signing-via-group-policy/&quot;&gt;Configure SMB signing via Group Policy. RootUsers.com&lt;/a&gt;&lt;/p&gt;
</content>
    </entry>
    
    <entry>
      <title>Dual Booting Encrypted Arch Linux and Windows 10 Installs With Shared EFI Partition</title>
      <link href="http://localhost:8080/2019/08/25/dual-booting-encrypted-arch-linux-and-windows-10-installs-with-shared-efi-partition/"/>
      <updated>2019-08-25T17:44:03Z</updated>
      <id>http://localhost:8080/2019/08/25/dual-booting-encrypted-arch-linux-and-windows-10-installs-with-shared-efi-partition/</id>
      <content type="html">&lt;p&gt;I’ve been running linux as my primary laptop OS for multiple years now. Like most people, I had my first experience with linux when I installed ubuntu on an older laptop. I happened to be in High School at the time and that laptop happened to be a&lt;br /&gt;
&lt;a href=&quot;http://localhost:8080/2019/08/25/dual-booting-encrypted-arch-linux-and-windows-10-installs-with-shared-efi-partition/%22https://www.cnet.com/reviews/dell-xps-m1710-preview/%22&quot;&gt;Dell XPS M1710&lt;/a&gt; (Yes, with the LEDs!) Since then, I’ve moved around quite a bit. We used CentOS exclusively in my linux classess at Indian Hills, so naturally,&lt;br /&gt;
I evolved into a fulltime Red Hat user. This is a Habit I still haven’t given up as I still use CentOS almost exclusively for any servers I build. For a while I was running Fedora on my laptop, which I also liked quite a bit. Eventually, I got bored of&lt;br /&gt;
Fedora and decided I wanted a challenge, so I decided to give Arch a try. It’s been about two years since my first arch install and I haven’t looked back since.&lt;/p&gt;
&lt;p&gt;Despite all the stigma surrounding the OS, I’ve enjoyed a wonderfully stable and relatively user friendly experience. In my two years of use my arch install has only every ‘broke’ once and, as it so often is, it was entirely my own fault. This could be&lt;br /&gt;
attributed to the fact that I normally use a ‘polished’ desktop environment like gnome or deepin rather than picking and choosing gui components one by one, and it could also be because I genuinely enjoy understanding how my OS works. None the less, I’m&lt;br /&gt;
very happy with it and plan to continue using it for a while. The only caveat to arch is that there are still so many things that tie me to a windows enviornment that I can’t really afford to be caught without a windows install. In school, this was because&lt;br /&gt;
I had to use the infamous lock down browser, which refused to be run in a VM or on linux, and now as a professional in mainly windows/vmware centric infrastructure I need tools that simply don’t have a viable linux alternative. The solution to this (for me)&lt;br /&gt;
has always been to dual boot my install. Dual booting Windows 10 and Arch linux is well documented and relatively easy to set up, but some behavior of windows 10 can make this relatively troublesome to maintain. Namely, with the break neck speed at which&lt;br /&gt;
Microsoft releases feature updates to Windows 10, the consumer branch of windows tends to reinstall itslef every few months, clobbering your boot loader and making it impossible to boot back to your linux distro. Dual booting can also present unique&lt;br /&gt;
challenges in securing your system, namely with full disk encryption.&lt;/p&gt;
&lt;p&gt;After a few installs, I’ve settled into a method of installation that seems to work well for me, so I wanted to share. What I do is install my linux boot loader along side the windows 10 boot loader in a single shared EFI partition. This tends to prevent&lt;br /&gt;
Windows from clobbering the boootloader, meaning it survives feature upgrades. Following this, I encrypt each install at the partition level, meaning each install is secure in it’s own right. Most of this I learned from this guide: &lt;a href=&quot;https://joh.fi/blog/2016-03-05-encrypted-windows-and-arch-linux-dual-boot-installation-using-uefi/&quot;&gt; ‘Joh.Fi/blog’. ‘Encrypted Windows and Arch Linux dual-boot installation using UEFI’&lt;/a&gt;.&lt;br /&gt;
I wanted to supplement this guide with a step by step set of instructions, and a list of the resources I needed to complete the full picture (bottom of page). So, without further adieu, let’s walk through the steps of installing Windows 10&lt;br /&gt;
and Arch Linux for dual booting with a shared EFI partition and using partition level encryption.&lt;/p&gt;
&lt;h2&gt;Step 1: Install Windows&lt;/h2&gt;
&lt;p&gt;Start off by booting into your Windows install media on the target machine. We have to install windows first because it refuses to behave like there are any other OSes in the world. I’ll be using an ISO of Windows 10 LTSB, but any version should work. (Note,&lt;br /&gt;
Bitlocker is not available in the home version). Because we’re going to be sharing efi partition, we’ll need to manually create one that’s larger than what windows creates by default. It can work with a default sized EFI partition, but it makes it difficult to do kernel upgrades in the future.&lt;br /&gt;
In the installer, Next Next Next until you get to this page where you select your disk to install to:&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;http://localhost:8080/assets/images/2019/08/Windows_Installer_Empty_Disk.png&quot; alt=&quot;image&quot; /&gt;&lt;/p&gt;
&lt;p&gt;Double check that your disk shows up as empty, if not, no big deal, we’ll clean it out soon. Press Shift + F10 on your keyboard to open a command prompt, and in this command prompt run the ‘diskpart’ command to launch the disk management tool.&lt;br /&gt;
Inside of diskpart, use the ‘lisk disk’ command to list all available disks, and identify your target disk. Once you know what disk you want to use, select that disk using the unique number that diskpart assigned to it. In my example I only have&lt;br /&gt;
one disk, so I use disk 0.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;http://localhost:8080/assets/images/2019/08/Diskpart_Select_Disk.png&quot; alt=&quot;image&quot; /&gt;&lt;/p&gt;
&lt;p&gt;If your target disk is not empty (i.e. contains other partitions) we can clean it using diskpart. Just issue the ‘clean’ command, which will erase all partitions from the disk. If you have existing partitions on this disk, this will destroy them&lt;br /&gt;
and make their contents unrecoverable.&lt;/p&gt;
&lt;p&gt;Moving on, go ahead and make sure your disk is GPT partitioned by running the ‘convert gpt’ command in disk part. Now we’re going to create our EFI and Windows partitions. Enter these commands, replacing variables for size as necessary:&lt;/p&gt;
&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;create partition efi &lt;span class=&quot;token assign-left variable&quot;&gt;size&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1024&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token function&quot;&gt;format&lt;/span&gt; quick &lt;span class=&quot;token assign-left variable&quot;&gt;fs&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;fat32 &lt;span class=&quot;token assign-left variable&quot;&gt;label&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;System&quot;&lt;/span&gt;&lt;br /&gt;assign &lt;span class=&quot;token assign-left variable&quot;&gt;letter&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;S&quot;&lt;/span&gt;&lt;br /&gt;create partition primary &lt;span class=&quot;token assign-left variable&quot;&gt;size&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;32768&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token function&quot;&gt;format&lt;/span&gt; quick &lt;span class=&quot;token assign-left variable&quot;&gt;fs&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;ntfs &lt;span class=&quot;token assign-left variable&quot;&gt;label&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;Windows&quot;&lt;/span&gt;&lt;br /&gt;assign &lt;span class=&quot;token assign-left variable&quot;&gt;letter&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;W&quot;&lt;/span&gt; &lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&quot;http://localhost:8080/assets/images/2019/08/Diskpart_Create_EFI_Part.png&quot; alt=&quot;image&quot; /&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;http://localhost:8080/assets/images/2019/08/Diskpart_Create_NTFS_Part.png&quot; alt=&quot;image&quot; /&gt;&lt;/p&gt;
&lt;p&gt;The size values are expressed in MB. So if you want to specify size in GB, just mutliply the desired size in GB by 1024. So my 1 GB EFI partition is 1024, and my 32 GB Windows partition is 32768. If you fancy, you can verify these partitions were&lt;br /&gt;
created with a quick ‘list part’ command. Now that our partitions are setup, close the cmd prompt and refresh the disk pane in the installer GUI. You should see your new partitions.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;http://localhost:8080/assets/images/2019/08/Windows_Installer_Select_Target_Partitions.png&quot; alt=&quot;image&quot; /&gt;&lt;/p&gt;
&lt;p&gt;Highlight the “windows” partition and click next to start installing. The installer doesn’t say it anywhere, but because there is already an EFI partition mounted at ‘S’ it will use it instead of creating its’ own. Now just click through the GUI like you normally would.&lt;/p&gt;
&lt;p&gt;After fighting your way through the out of box experience, you’ll end up at a windows desktop. Once here, you should open up disk manager (Run diskmgmt.msc) and verify that the partitions on your disk look correct.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;http://localhost:8080/assets/images/2019/08/Verify_Disk_Setup_Diskmgmt.png&quot; alt=&quot;image&quot; /&gt;&lt;/p&gt;
&lt;p&gt;You should see your efi partition, one windows partition, and maybe another microsoft reserved partition. As long as your EFI partition is sized correctly and you have some unallocated space left to work with, everything is good here. When you’re ready, swap your windows boot media for you arch linux media and reboot into the arch live image to install it.&lt;/p&gt;
&lt;h2&gt;Step 2: Install Arch&lt;/h2&gt;
&lt;p&gt;Boot into your arch linux live media. The first thing we should do when booting into a live linux environment is make sure that we have everything we need to continue the installation process. It would be frustrating to go through the trouble of partitioning your disks just to realize you have no network and need to start over&lt;/p&gt;
&lt;p&gt;First off, verify that you’ve booted using EFI. Check to see if the file ‘/sys/firmware/efi/efivars’ exists. If it doesn’t, you’re not booted in UEFI mode. If you want to use another keyboard layout, now’s the time to do so. You can get instructions on this at the &lt;a href=&quot;https://wiki.archlinux.org/index.php/Installation_guide#Boot_the_live_environment&quot;&gt; Official install guide &lt;/a&gt;.&lt;br /&gt;
You’ll need to be connected to the internet to complete the installtion, so make sure you have a good internet connection. Try the command ‘ping archlinux.org’. If you get a reply, everything is working. Once your internet is confirmed working, you can set your local system time using NTP to ensure you have accurate time. Run the command ‘timedatectl set-ntp true’&lt;/p&gt;
&lt;p&gt;Now let’s identify our disks. We’ll be using the fdisk utility. First we need to identify the disk itself, which will likely be /dev/sdx where x is a unique letter. If you only have one disk it’s probably /dev/sda. Either way, run the command ‘fdisk -l’ and&lt;br /&gt;
review the results to find out which disk contains our windows install&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;http://localhost:8080/assets/images/2019/08/Fdisk_List.png&quot; alt=&quot;image&quot; /&gt;&lt;/p&gt;
&lt;p&gt;Based on this output I know my disk is /dev/sda because it contians my EFI partition (sda1) and my Windows partition (sda2). Now that we know what disk to use, we can start an interactive fdisk session to configure this disk. Enter the command ‘fdisk /dev/sdX’ where X is the unique letter assigned to your drive. Then ‘n’ command to create a new partition, and accept all the defualts by pressing enter, (this will asign the next available partition number, and start and stop at the first/last available sector). Next, use the ‘t’ command to set the partition type to “Linux LVM” which is type 31&lt;br /&gt;
when you’re done, use the ‘wo’ command to write the changes to disk. If you make a mistake, you can exit without writing to restart.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;http://localhost:8080/assets/images/2019/08/Fdisk_LVM_Part.png&quot; alt=&quot;image&quot; /&gt;&lt;/p&gt;
&lt;p&gt;Next, we’re going to encrypt the entire LVM partition we created. We do so using the cryptsetup tool provided in the live ISO. Run the command ‘cryptsetup luksFormat /dev/sdx’ where sdx is your partition. In my case, this was sda4.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;http://localhost:8080/assets/images/2019/08/Encrypt_LVM_Part.png&quot; alt=&quot;image&quot; /&gt;&lt;/p&gt;
&lt;p&gt;Once that completes, the partition is left locked and unmounted, so we have to unlock it and mount it. Run the command ‘cryptsetup open /dev/sda4 cryptlvm’ (replacing sda4 with your own partition number). This will prompt you for your passhprase and then make the partition available at /dev/mapper/cryptlvm.&lt;/p&gt;
&lt;p&gt;Now we need to create our LVM filesystem inside of this encrypted partition, We’ll start by creating a physical volume on the partition, then we create a volume group inside that physical partition, and then we create logical volumes inside of that volume group. Do so by running these commands:&lt;/p&gt;
&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;pvcreate /dev/mapper/cryptlvm&lt;br /&gt;vgcreate VolGroup0 /dev/mapper/cryptlvm&lt;br /&gt;lvcreate &lt;span class=&quot;token parameter variable&quot;&gt;-l&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;100&lt;/span&gt;%FREE VolGroup0 &lt;span class=&quot;token parameter variable&quot;&gt;-n&lt;/span&gt; Vol0&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;If you’d like to create any additional partitions, such as swap or an separate mount point for /var or something, you can do so here. I’ve just chosen not to, so I create one volume consuming all available size.&lt;/p&gt;
&lt;p&gt;Now we just need to initialize the ext4 filesystem inside our logical volume, mount it, and then we can use it as our install destination.&lt;/p&gt;
&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;mkfs.ext4 /dev/VolGroup0/Vol0&lt;br /&gt;&lt;span class=&quot;token function&quot;&gt;mount&lt;/span&gt; /dev/VolGroup0/Vol0 /mnt&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;and now we need to create a mount point inside our new root filesystem for the efi system partition. This should be mouned at /boot so we create the directory /mnt/boot and then mount our efi partition (sda1) to that directory&lt;/p&gt;
&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;token function&quot;&gt;mkdir&lt;/span&gt; /mnt/boot&lt;br /&gt;&lt;span class=&quot;token function&quot;&gt;mount&lt;/span&gt; /dev/sda1 /mnt/boot&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Now we can continue through the rest of the official install guide, knowing that our destination file sytems are mounted where they should be. The next step is to pacstrap our new root filesystem. This is what actually installs the system, it grabs the set of packages that is arch linux and installs them to the filesystem you specify. How versatile! Run the following command:&lt;/p&gt;
&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;pacstrap /mnt base&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Next we generate our FSTAB configuration. FSTAB is the service that tells the kernel what partitions it needs and where they are, along with instructions to mount them. The live ISO comes with a handy tool that will generate this configuration for us&lt;/p&gt;
&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;genfstab &lt;span class=&quot;token parameter variable&quot;&gt;-U&lt;/span&gt; /mnt &lt;span class=&quot;token operator&quot;&gt;&gt;&gt;&lt;/span&gt; /mnt/etc/fstab&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Now we can chroot into our new install, which will be like manually booting into it.&lt;/p&gt;
&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;arch-chroot /mnt&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Now according to the official install guide, the next step is to configure the system time zone and initialize the hardware clock. This is done by simlinking one of the provided time zone files to /etc/localtime. Run these two commands, replacing the time zone information with your own.&lt;/p&gt;
&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;token function&quot;&gt;ln&lt;/span&gt; &lt;span class=&quot;token parameter variable&quot;&gt;-sf&lt;/span&gt; /usr/share/zoneinfo/US/Central /etc/localtime&lt;br /&gt;hwclock –systohc&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Now we’ll build our locale, which is important for language and input puroses:&lt;br /&gt;
Nano (or vi) into /etc/locale.gen and uncomment your locale. If you’re unsure which one to use, and you’re reading this guide in english, just use en_US.UTF-8 like the install guide suggest. (if the locale.gen file doesn’t exist, run locale-gen once and then try again)&lt;/p&gt;
&lt;p&gt;after selecting your locale, run ‘locale-gen’&lt;/p&gt;
&lt;p&gt;Now create the /etc/locale.conf file and put your language preference in there. Again, if you aren’t sure what to use you probably want en_US.UTF-8&lt;/p&gt;
&lt;p&gt;Now create the /etc/hostname file and put your hostname in there&lt;/p&gt;
&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;token builtin class-name&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;arch&#39;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; /etc/hostname &lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Now we need to deviate from the install guide a little bit again. We’re going to configure our initramfs, but because we’re using LVM on an LUKS encrypted paratition, we have to include the relevant hooks in our initramfs so that the kernel has everything it needs to handle the encrypted lvm partition. open the /etc/mkinitcpio.conf file with your favorite editor and find the HOOKS line. insert the hooks, keyboard, encrypt, lvm2. The order of these does matter, so yours should match this exactly&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;http://localhost:8080/assets/images/2019/08/mkinitcpio_hooks.png&quot; alt=&quot;image&quot; /&gt;&lt;/p&gt;
&lt;p&gt;Now we can generate our initramfs image. Run this command:&lt;/p&gt;
&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;mkinitcpio &lt;span class=&quot;token parameter variable&quot;&gt;-p&lt;/span&gt; linux&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Wath the output for erros. Warnings are ok, as long as the process finishes successfully.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;http://localhost:8080/assets/images/2019/08/mkinitcpio_build.png&quot; alt=&quot;image&quot; /&gt;&lt;/p&gt;
&lt;h2&gt;Step 3: Install and Configure GRUB&lt;/h2&gt;
&lt;p&gt;Now you have a configured install. The last thing to do is install and configure the bootloader. Start off by installing the package and it’s dependencies:&lt;/p&gt;
&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;pacman &lt;span class=&quot;token parameter variable&quot;&gt;-S&lt;/span&gt; grub efibootmgr&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Once those packages are installed, use the following command to install grub to our boot partition.&lt;/p&gt;
&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;grub-install &lt;span class=&quot;token parameter variable&quot;&gt;--target&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;x86_64-efi --efi-directory&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;/mnt/boot --bootloader-id&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;GRUB&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&quot;http://localhost:8080/assets/images/2019/08/install_grub_to_boot.png&quot; alt=&quot;image&quot; /&gt;&lt;/p&gt;
&lt;p&gt;This will install the boot loader, but it needs to be configured for our new system. In an encrypted system, grub tells our kernel where to find it’s disks by passing that info to the kernel as arguments. So we have to tell grub what to tell the kernel when it boots. According to the install guide, we need to pass the UUID of our device and it’s mount point to the kernel using this syntax:&lt;/p&gt;
&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;token assign-left variable&quot;&gt;cryptdevice&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;UUID&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;device-UUID:cryptlvm &lt;span class=&quot;token assign-left variable&quot;&gt;root&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;/dev/MyVolGroup/root&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;In my case, cryptlvm is on sda4, so let’s use the blkid command to find the UUID of sda4:&lt;/p&gt;
&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;blkid &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;grep&lt;/span&gt; sda4&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Now we just need to copy and past that into our file. There’s no copy paste functionality that I know of in the live ISO, so I normally just echo it into the end of the /etc/default/grub file and use nano’s copy paste feature to move it around in there:&lt;/p&gt;
&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;blkid &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;grep&lt;/span&gt; sda4 &lt;span class=&quot;token operator&quot;&gt;&gt;&gt;&lt;/span&gt; /etc/default/grub &lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;So nano into /etc/default/grub and find the output of blkid at the bottom. Ctrl+K to cut, and CTRL+U to paste. Paste the line into the blank space underneath the GRUB_CMDLINE_LINUX=”” line, and then erase everything but the UUID. Then, using your UUID, complete the command. For reference, mine is:&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;http://localhost:8080/assets/images/2019/08/etc_default_grub_linux_cmdline.png&quot; alt=&quot;image&quot; /&gt;&lt;/p&gt;
&lt;p&gt;Notice I’m using the names of LVM  components, such as ‘cryplvm’, or VolGroup0? These have to match the components you created in earlier steps. Cryptlvm is the physical volume group I created, volgroup0 is the logical volume group I created, and Vol0 is the logical partition I have mounted at /mnt, and will be the file system that the kernel is looking for.&lt;/p&gt;
&lt;p&gt;Double, even triple check this line for accuracy, and then save and exit. Now build your grub config:&lt;/p&gt;
&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;token function&quot;&gt;grub-mkconfig&lt;/span&gt; &lt;span class=&quot;token parameter variable&quot;&gt;-o&lt;/span&gt; /boot/grub/grub.cfg&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;In the output of this command we can verify that it found our linux install, but it might not have found our windows install. If you don’t see anything about grub finding a windows install in the output of this command, install the packages os-prober and ntfs-3g and try again&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;http://localhost:8080/assets/images/2019/08/grub_Mkconfig_with_windows_Boot.png&quot; alt=&quot;image&quot; /&gt;&lt;/p&gt;
&lt;p&gt;Now for the moment of truth. Let’s try to reboot. exit your chroot session and type reboot. If everything goes well, we should be greeted by the grub splash screen shortly. We can select our Arch option, and hopefully we’ll be greeted by a passphrase prompt. Entering our passphrase should continue the boot process and shortly drop us to the login page of our new arch install.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;http://localhost:8080/assets/images/2019/08/Grub.png&quot; alt=&quot;image&quot; /&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;http://localhost:8080/assets/images/2019/08/arch_boot_prompt.png&quot; alt=&quot;image&quot; /&gt;&lt;/p&gt;
&lt;p&gt;If that worked, reboot once more, selecting the option to boot windows. Both should be working by this point.&lt;/p&gt;
&lt;h2&gt;Step 4: Configure Bitlocker&lt;/h2&gt;
&lt;p&gt;The last step of this process is to configure bitlocker for our Windows install. If we try to do this as is, it will probably fail because it’s mad about not having a TPM. This is where Joh’s guide comes in. Following his instructions we can disable this and use Bitlocker without a TPM.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;http://localhost:8080/assets/images/2019/08/BitLocker_Failed_TPM.png&quot; alt=&quot;image&quot; /&gt;&lt;/p&gt;
&lt;p&gt;From within your Windows install, open up the group policy editor by launching gpedit.msc from a run/cmd prompt and navigate to Computer Configuration -&amp;gt; Administrative Templates -&amp;gt; Windows Components -&amp;gt; BitLocker Drive Encryption -&amp;gt; Operating System Drives. Open the settings entitled ‘Require additional authentication at startup’, click the radio button for ‘enabled’ and make sure the ‘allow use without TPM module’ option is enabled. Save and exit.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;http://localhost:8080/assets/images/2019/08/Bitlocker_GP_Config.png&quot; alt=&quot;image&quot; /&gt;&lt;/p&gt;
&lt;p&gt;Now if we go back to ‘This PC’ in a windows explorer window we can right click on the C: drive and enable bitlocker encryption. Next Next Next, choose to use a password, and then choose a recovery method. I have no idea why Microsoft thinks forcing you to create a plain text copy of your recovery key is a good idea, but it will force you and it won’t let you save it anywhere on the machine. I chose to use save as a file, and then promptly deleted that file.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;http://localhost:8080/assets/images/2019/08/Bitlocker_PassPhrase.png&quot; alt=&quot;image&quot; /&gt;&lt;/p&gt;
&lt;p&gt;Once set up is complete, windows will prompt you to restart to complete the process. Simply restart and select windows from grub.&lt;/p&gt;
&lt;p&gt;Thanks for reading!&lt;/p&gt;
&lt;h2&gt;Sources:&lt;/h2&gt;
&lt;p&gt;&lt;a href=&quot;https://wiki.archlinux.org/index.php/Installation_guide&quot;&gt;Installation guide. wiki.archlinux.org&lt;/a&gt;&lt;br /&gt;
&lt;a href=&quot;https://docs.microsoft.com/en-us/windows-hardware/manufacture/desktop/configure-uefigpt-based-hard-drive-partitions&quot;&gt;UEFI/GPT-based hard drive partitions. docs.microsoft.com&lt;/a&gt;&lt;br /&gt;
&lt;a href=&quot;https://joh.fi/blog/2016-03-05-encrypted-windows-and-arch-linux-dual-boot-installation-using-uefi/&quot;&gt;Encrypted Windows and Arch Linux dual-boot installation using UEFI&lt;/a&gt;&lt;br /&gt;
&lt;a href=&quot;https://wiki.archlinux.org/index.php/Dm-crypt/Encrypting_an_entire_system#LVM_on_LUKS&quot;&gt;LVM on LUKS. wiki.archlinux.org&lt;/a&gt;&lt;br /&gt;
&lt;a href=&quot;https://wiki.archlinux.org/index.php/GRUB&quot;&gt;GRUB. wiki.archlinux.org&lt;/a&gt;&lt;/p&gt;
</content>
    </entry>
    
    <entry>
      <title>TrueK8S Part 01</title>
      <link href="http://localhost:8080/2025/05/15/truek8s-part-01/"/>
      <updated>2025-05-15T12:30:00Z</updated>
      <id>http://localhost:8080/2025/05/15/truek8s-part-01/</id>
      <content type="html">&lt;h1&gt;This is a story about how I ended up running Kubernetes in my homelab&lt;/h1&gt;
&lt;p&gt;Like many homelab stories, this one began with something simple and spiraled out of control. About a year ago, I set out to run Jellyfin on my NAS, a box I named Sesa running TrueNAS scale. Running jellyfin on TrueNAS made sense to me because the box was very underutilised and I wanted to store everything on the NAS anyway. Looking around online, I found a repository of apps for TrueNAS called &lt;a href=&quot;https://truecharts.org/&quot;&gt;TrueCharts&lt;/a&gt;…&lt;/p&gt;
&lt;p&gt;I became a quick fan of the TrueCharts project because they had the app I was looking for and many other apps I didn’t even realise I needed yet. Better yet, all of those apps came in a consistent package with built-in features like automated certificate management, built-in VPN, VolSync and CNPG backups, homepage integration, etc… I read the docs, spun up jellyfin and a couple other apps and went on my way.&lt;/p&gt;
&lt;p&gt;I was happy with my TrueCharts apps right up until I heard the news that TrueNAS was dropping it’s built-in kubernetes backend for applications. At that point I didn’t really know anything about Kubernetes, just that my apps were working but no longer would. Reading around, I heard that all the truecharts guys moved to another kubernetes platform, Talos Linux.&lt;/p&gt;
&lt;p&gt;Part of me thought about abandoning truecharts and just spinning up the apps I wanted the ‘old fashioned’ way by manually installing them on linux VMs and calling it a day. But that would mean accepting that Kubernetes was ‘too hard’ for me and I just can’t stomach that. I decided to follow the TrueCharts project over to Talos Linux, and challenge myself to actually learn and understand the underlying concepts of the apps that I was running.&lt;/p&gt;
&lt;p&gt;This will be a multi-part series of posts documenting what I’ve learned in a How-To format that I wished was available when I was building my own Kubernetes cluster.&lt;/p&gt;
&lt;p&gt;In part one of this series, I’ll describe how I built my Talos Cluster.&lt;/p&gt;
&lt;h2&gt;Disclaimer&lt;/h2&gt;
&lt;p&gt;❗ I am not affiliated with TrueCharts and this is not an official guide on how to deploy TrueCharts apps. This is my own guide of how I built my own kubernetes cluster, which I mostly use to run TrueCharts apps. If you’re looking for a guide on how to deploy truecharts the &lt;em&gt;right&lt;/em&gt; way you should go read their &lt;a href=&quot;https://truecharts.org/general/&quot;&gt;docs&lt;/a&gt;. If you’re looking to learn about Kubernetes from my example, read ahead.&lt;/p&gt;
&lt;h2&gt;Prerequisites&lt;/h2&gt;
&lt;p&gt;To follow along, you’ll need a couple things that (might) cost real life money. Those are:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;A public domain&lt;/li&gt;
&lt;li&gt;A cloudflare account (Free tier is fine)&lt;/li&gt;
&lt;li&gt;An S3 storage account (I’ll be using backblaze)&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Acquire the install media&lt;/h2&gt;
&lt;p&gt;We’re going to build a talos linux cluster with three members. I’ll be using Proxmox to run the talos on VMs, following the guide &lt;a href=&quot;https://www.talos.dev/v1.9/talos-guides/install/virtualized-platforms/proxmox/&quot;&gt;here&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Go ahead and make yourself a folder for this, you’ll have a lot of files to manage. I’ll be using ~/Documents/truek8s-talos.&lt;/p&gt;
&lt;p&gt;The first step is acquiring the install media using Talos image factory. We’ll be using a storage solution that requires the util-linux-tools and iscsi-tools extensions, and I also want to include the qemu guest agent. To build our own install media with those extra bits we can create a schematic and then post it to Talos image factory. (This is described &lt;a href=&quot;https://www.talos.dev/v1.9/talos-guides/install/boot-assets/#image-factory&quot;&gt;here&lt;/a&gt;)&lt;/p&gt;
&lt;p&gt;Create a baremetal.yaml file describing the extensions we want to add. Don’t worry about version yet, because that’s independant of the configuration.&lt;/p&gt;
&lt;pre class=&quot;language-yaml&quot;&gt;&lt;code class=&quot;language-yaml&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;# bare-metal.yaml&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token key atrule&quot;&gt;customization&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token key atrule&quot;&gt;extraKernelArgs&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; net.ifnames=0&lt;br /&gt;  &lt;span class=&quot;token key atrule&quot;&gt;systemExtensions&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token key atrule&quot;&gt;officialExtensions&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;      &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; siderolabs/util&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;linux&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;tools&lt;br /&gt;      &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; siderolabs/iscsi&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;tools&lt;br /&gt;      &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; siderolabs/qemu&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;guest&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;agent&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Now POST that file to the image factory, and it will return a schematic ID. Note that the same config always returns the same ID, so you can skip re-creating the schematic once you have this ID.&lt;/p&gt;
&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;$ &lt;span class=&quot;token function&quot;&gt;curl&lt;/span&gt; &lt;span class=&quot;token parameter variable&quot;&gt;-X&lt;/span&gt; POST --data-binary @bare-metal.yaml https://factory.talos.dev/schematics&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;id&quot;&lt;/span&gt;&lt;span class=&quot;token builtin class-name&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;82866c01b2842b490c27a6f1a4996aae05f096c83db40ecda166b03da9deae46&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Now we can retrieve our boot media from the image factory using that schematic ID. The version is specified separately from the schematic, so you can re-use that config with different versions. I’m running V1.9.2 for this guide, so I’ll call this URL.&lt;/p&gt;
&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;https://factory.talos.dev/image/82866c01b2842b490c27a6f1a4996aae05f096c83db40ecda166b03da9deae46/v1.9.2/metal-amd64.iso&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;Create VMs&lt;/h2&gt;
&lt;p&gt;Now you can go to your ProxMox (or whatever) host and download that ISO.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;http://localhost:8080/assets/images/2025/04/prox-iso-fetch.png&quot; alt=&quot;image&quot; /&gt;&lt;/p&gt;
&lt;p&gt;I’ll be creating three hosts:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;1 controller (2 CPU, 4GBs of RAM, 32GB storage)&lt;/li&gt;
&lt;li&gt;2 workers (4 CPU, 8GB of RAM, 512GB storage)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;CPU and memory is easy enough to change later, but storage will be hard to increase, so make sure you start with plenty.&lt;/p&gt;
&lt;p&gt;The default options for a new VM are good enough, just make sure to enable the QEMU agent (you can enable it later if you forget). I also choose to use writeback cache and use the ‘host’ CPU type.&lt;/p&gt;
&lt;p&gt;My lab environment uses vlan tagging and the vlan id is redacted for privacy.I will also create DHCP reservations for these hosts before turning them on, just to make IPs predictable. These hosts will get a DHCP address and then make that static by default, so manage your networking accordingly.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;http://localhost:8080/assets/images/2025/04/create-vm-1.png&quot; alt=&quot;image&quot; /&gt;&lt;br /&gt;
&lt;img src=&quot;http://localhost:8080/assets/images/2025/04/create-vm-2.png&quot; alt=&quot;image&quot; /&gt;&lt;br /&gt;
&lt;img src=&quot;http://localhost:8080/assets/images/2025/04/create-vm-3.png&quot; alt=&quot;image&quot; /&gt;&lt;br /&gt;
&lt;img src=&quot;http://localhost:8080/assets/images/2025/04/create-vm-4.png&quot; alt=&quot;image&quot; /&gt;&lt;br /&gt;
&lt;img src=&quot;http://localhost:8080/assets/images/2025/04/create-vm-5.png&quot; alt=&quot;image&quot; /&gt;&lt;br /&gt;
&lt;img src=&quot;http://localhost:8080/assets/images/2025/04/create-vm-6.png&quot; alt=&quot;image&quot; /&gt;&lt;br /&gt;
&lt;img src=&quot;http://localhost:8080/assets/images/2025/04/create-vm-7.png&quot; alt=&quot;image&quot; /&gt;&lt;br /&gt;
&lt;img src=&quot;http://localhost:8080/assets/images/2025/04/create-vm-8.png&quot; alt=&quot;image&quot; /&gt;&lt;/p&gt;
&lt;p&gt;Once your machines are configured, go ahead and fire &#39;em up. Make sure that they all come online and grab an IP that you like.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;http://localhost:8080/assets/images/2025/04/vm-boot-1.png&quot; alt=&quot;image&quot; /&gt;&lt;/p&gt;
&lt;p&gt;(Note: if you’re like me and goof up a lot, it may be helpful to snapshot these machines in their ‘untouched’ state before moving on in case you want to try again)&lt;/p&gt;
&lt;h2&gt;Configure the Cluster&lt;/h2&gt;
&lt;p&gt;Once the machines are online, we’re going to configure them using talosctl from another computer on the network. I’ll be using Debian. You /can/ use Windows, but if you were the type of person to do that, you probably would’ve stopped reading by now.&lt;/p&gt;
&lt;p&gt;Install talosctl on your admin workstation&lt;/p&gt;
&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;token function&quot;&gt;curl&lt;/span&gt; &lt;span class=&quot;token parameter variable&quot;&gt;-sL&lt;/span&gt; https://talos.dev/install &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;sh&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Now we’re going to generate machineconfig files, edit them, and apply them to our new talos nodes. Make sure you’re in the directory you created earlier.&lt;/p&gt;
&lt;p&gt;We’re going to use talosctl machineconfig against our new controller to generate our starting config files. We’ll reference the schematic ID we generated earlier to make sure our config is consistent&lt;/p&gt;
&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;# Save your nodes IPs as variables, you&#39;ll need them later&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token builtin class-name&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token assign-left variable&quot;&gt;CONTROL_IP&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;192.168&lt;/span&gt;.XX.101&lt;br /&gt;&lt;span class=&quot;token builtin class-name&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token assign-left variable&quot;&gt;WORKER1_IP&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;192.168&lt;/span&gt;.XX.111&lt;br /&gt;&lt;span class=&quot;token builtin class-name&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token assign-left variable&quot;&gt;WORKER2_IP&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;192.168&lt;/span&gt;.XX.112&lt;br /&gt;&lt;span class=&quot;token builtin class-name&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token assign-left variable&quot;&gt;CLUSTERNAME&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;truek8s&lt;br /&gt;&lt;br /&gt;&lt;span class=&quot;token comment&quot;&gt;#Note we&#39;re re-using the schematic ID from earlier, but not the whole url&lt;/span&gt;&lt;br /&gt;talosctl gen config &lt;span class=&quot;token variable&quot;&gt;$CLUSTERNAME&lt;/span&gt; https://&lt;span class=&quot;token variable&quot;&gt;$CONTROL_IP&lt;/span&gt;:6443 --install-image factory.talos.dev/installer/82866c01b2842b490c27a6f1a4996aae05f096c83db40ecda166b03da9deae46/:v1.9.2&lt;br /&gt;&lt;br /&gt;generating PKI and tokens&lt;br /&gt;Created /home/truek8s/Documents/truek8s/clusterconfig/controlplane.yaml&lt;br /&gt;Created /home/truek8s/Documents/truek8s/clusterconfig/worker.yaml&lt;br /&gt;Created /home/truek8s/Documents/truek8s/clusterconfig/talosconfig&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Now we need to modify those configuration files. You could modify them directly using a text editor like Nano, but the cool way to do it is by using a patch file. I like using patch files because they can be re-used later, and I probably went through this process like 10+ times trying to figure things out.&lt;/p&gt;
&lt;p&gt;We’ll use the patch to reference our schematic once more, set the machine name, tweak cluster networking. We’ll also include some extensions that will be required by our storage provider, Longhorn (more on that later).&lt;/p&gt;
&lt;p&gt;Create three .patch files in your clusterconfig directory:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;truek8s-c1.patch&lt;/li&gt;
&lt;li&gt;truek8s-w1.patch&lt;/li&gt;
&lt;li&gt;truek8s-w2.patch&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The only thing that differs between them is the machine.network.hostname field&lt;/p&gt;
&lt;pre class=&quot;language-yaml&quot;&gt;&lt;code class=&quot;language-yaml&quot;&gt;&lt;span class=&quot;token key atrule&quot;&gt;machine&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token key atrule&quot;&gt;kubelet&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token key atrule&quot;&gt;clusterDNS&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;       &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; 172.XX.0.10&lt;br /&gt;    &lt;span class=&quot;token key atrule&quot;&gt;extraMounts&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token key atrule&quot;&gt;destination&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; /var/lib/longhorn&lt;br /&gt;      &lt;span class=&quot;token key atrule&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; bind&lt;br /&gt;      &lt;span class=&quot;token key atrule&quot;&gt;source&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; /var/lib/longhorn&lt;br /&gt;      &lt;span class=&quot;token key atrule&quot;&gt;options&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; bind&lt;br /&gt;        &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; rshared&lt;br /&gt;        &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; rw&lt;br /&gt;  &lt;span class=&quot;token key atrule&quot;&gt;network&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;br /&gt;    &lt;span class=&quot;token key atrule&quot;&gt;hostname&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; truek8s&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;c1&lt;br /&gt;  &lt;span class=&quot;token key atrule&quot;&gt;install&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token key atrule&quot;&gt;image&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; factory.talos.dev/installer/82866c01b2842b490c27a6f1a4996aae05f096c83db40ecda166b03da9deae46&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;v1.9.2&lt;br /&gt;&lt;span class=&quot;token key atrule&quot;&gt;cluster&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token key atrule&quot;&gt;network&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token key atrule&quot;&gt;dnsDomain&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; cluster.local &lt;span class=&quot;token comment&quot;&gt;# The domain used by Kubernetes DNS.&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token comment&quot;&gt;# The pod subnet CIDR.&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token key atrule&quot;&gt;podSubnets&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;      &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; 172.XX.0.0/16&lt;br /&gt;    &lt;span class=&quot;token comment&quot;&gt;# The service subnet CIDR.&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token key atrule&quot;&gt;serviceSubnets&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;      &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; 172.XX.0.0/16&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;NOTE: you do not have to define the podSubnets, serviceSubnets, and clusterDNS like I did, but I did so to prevent routing errors that I encountered in my own environment.&lt;/p&gt;
&lt;p&gt;And now we’ll use these patches with talosctl to generate our config files. Be careful not to mix up the controller and worker config files when patching. At least twice I made that mistake and built a cluster of 3 controllers then had to restart.&lt;/p&gt;
&lt;p&gt;Run machineconfig patch with your patch, reference the ‘base’ yaml config, and specify your unique output. the output is the config you will apply to the node.&lt;/p&gt;
&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;token variable&quot;&gt;$talosctl&lt;/span&gt; machineconfig patch controlplane.yaml &lt;span class=&quot;token parameter variable&quot;&gt;--patch&lt;/span&gt; @truek8s-c1.patch &lt;span class=&quot;token parameter variable&quot;&gt;--output&lt;/span&gt; truek8s-c1.yaml&lt;br /&gt;&lt;span class=&quot;token variable&quot;&gt;$talosctl&lt;/span&gt; machineconfig patch worker.yaml &lt;span class=&quot;token parameter variable&quot;&gt;--patch&lt;/span&gt; @truek8s-w1.patch &lt;span class=&quot;token parameter variable&quot;&gt;--output&lt;/span&gt; truek8s-w1.yaml&lt;br /&gt;&lt;span class=&quot;token variable&quot;&gt;$talosctl&lt;/span&gt; machineconfig patch worker.yaml &lt;span class=&quot;token parameter variable&quot;&gt;--patch&lt;/span&gt; @truek8s-w2.patch &lt;span class=&quot;token parameter variable&quot;&gt;--output&lt;/span&gt; truek8s-w2.yaml&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;With all of your config files created, you can start configuring the cluster. Starting with the controller, we’ll apply the config with talosctl. Keep your controller console running while you run this command, because as soon as you do you’ll see the machine start working to apply the config.&lt;/p&gt;
&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;token variable&quot;&gt;$talosctl&lt;/span&gt; apply-config &lt;span class=&quot;token parameter variable&quot;&gt;--insecure&lt;/span&gt; &lt;span class=&quot;token parameter variable&quot;&gt;-n&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$CONTROL_IP&lt;/span&gt; &lt;span class=&quot;token parameter variable&quot;&gt;--file&lt;/span&gt; truek8s-c1.yaml&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&quot;http://localhost:8080/assets/images/2025/04/apply-config-controller-1.png&quot; alt=&quot;image&quot; /&gt;&lt;/p&gt;
&lt;p&gt;The controller will reboot, and you should see the Please run talosctl bootstrap message.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;http://localhost:8080/assets/images/2025/04/apply-config-controller-2.png&quot; alt=&quot;image&quot; /&gt;&lt;/p&gt;
&lt;p&gt;Once the controller shows this message, you can apply the config to your workers:&lt;/p&gt;
&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;talosctl apply-config &lt;span class=&quot;token parameter variable&quot;&gt;--insecure&lt;/span&gt; &lt;span class=&quot;token parameter variable&quot;&gt;-n&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$WORKER1_IP&lt;/span&gt; &lt;span class=&quot;token parameter variable&quot;&gt;--file&lt;/span&gt; truek8s-w1.yaml&lt;br /&gt;talosctl apply-config &lt;span class=&quot;token parameter variable&quot;&gt;--insecure&lt;/span&gt; &lt;span class=&quot;token parameter variable&quot;&gt;-n&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$WORKER2_IP&lt;/span&gt; &lt;span class=&quot;token parameter variable&quot;&gt;--file&lt;/span&gt; truek8s-w2.yaml&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Then wait for them to reboot and show healthy:&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;http://localhost:8080/assets/images/2025/04/worker2-ready.png&quot; alt=&quot;image&quot; /&gt;&lt;/p&gt;
&lt;p&gt;When all three are back up and show healthy, you can finalize the install by bootstrapping the cluster:&lt;/p&gt;
&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;talosctl bootstrap &lt;span class=&quot;token parameter variable&quot;&gt;--nodes&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$CONTROL_IP&lt;/span&gt; &lt;span class=&quot;token parameter variable&quot;&gt;--endpoints&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$CONTROL_IP&lt;/span&gt; &lt;span class=&quot;token parameter variable&quot;&gt;--talosconfig&lt;/span&gt; talosconfig&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Create your own talosconfig file so that you can use the talosctl command to interact with the cluster. Just copy it from your clusterconfig directory to ~/.talos/config and specify the controller IP as the endpoint&lt;/p&gt;
&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;token function&quot;&gt;mkdir&lt;/span&gt; ~/.talos&lt;br /&gt;&lt;span class=&quot;token function&quot;&gt;cp&lt;/span&gt; talosconfig ~/.talos/config&lt;br /&gt;&lt;span class=&quot;token function&quot;&gt;nano&lt;/span&gt; ~/.talos/config &lt;br /&gt;&lt;br /&gt;truek8s@debian02:~/Documents/truek8s/clusterconfig$ &lt;span class=&quot;token function&quot;&gt;cat&lt;/span&gt; ~/.talos/config &lt;br /&gt;context: truek8s&lt;br /&gt;contexts:&lt;br /&gt;    truek8s:&lt;br /&gt;        endpoints: &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;192.168&lt;/span&gt;.XX.101&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token comment&quot;&gt;###################&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token comment&quot;&gt;###################&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token comment&quot;&gt;###################&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Test talosctl out by running the dashboard. If all is well, you should see the same dashboard you see on the VM console.&lt;/p&gt;
&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;talosctl dashboard &lt;span class=&quot;token parameter variable&quot;&gt;-n&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$CONTROL_IP&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&quot;http://localhost:8080/assets/images/2025/04/talosctl-dashboard-1.png&quot; alt=&quot;image&quot; /&gt;&lt;/p&gt;
&lt;h2&gt;Configure and Test Kubernetes&lt;/h2&gt;
&lt;p&gt;Now that the cluster is up, you need to grab a kubeconfig from it, and you’ll be ready to go. Use talosctl to generate the config file (this will automatically put it in ~/.kube for you)&lt;/p&gt;
&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;talosctl kubeconfig &lt;span class=&quot;token parameter variable&quot;&gt;-n&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$CONTROL_IP&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;If you don’t already have kubectl installed, install it. The best way to do so is to install through your distro’s package manager because you’ll get autocomplete support and automatic updates. Failing that, install it manually:&lt;/p&gt;
&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;$ &lt;span class=&quot;token function&quot;&gt;curl&lt;/span&gt; &lt;span class=&quot;token parameter variable&quot;&gt;-LO&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;https://dl.k8s.io/release/&lt;span class=&quot;token variable&quot;&gt;&lt;span class=&quot;token variable&quot;&gt;$(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;curl&lt;/span&gt; &lt;span class=&quot;token parameter variable&quot;&gt;-L&lt;/span&gt; &lt;span class=&quot;token parameter variable&quot;&gt;-s&lt;/span&gt; https://dl.k8s.io/release/stable.txt&lt;span class=&quot;token variable&quot;&gt;)&lt;/span&gt;&lt;/span&gt;/bin/linux/amd64/kubectl&quot;&lt;/span&gt;&lt;br /&gt;$ &lt;span class=&quot;token function&quot;&gt;sudo&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;install&lt;/span&gt; &lt;span class=&quot;token parameter variable&quot;&gt;-o&lt;/span&gt; root &lt;span class=&quot;token parameter variable&quot;&gt;-g&lt;/span&gt; root &lt;span class=&quot;token parameter variable&quot;&gt;-m&lt;/span&gt; 0755 kubectl /usr/local/bin/kubectl&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Run kubectl to interface with your new cluster. If these commands come back, everything is good to go.&lt;/p&gt;
&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;truek8s@debian02:~/Documents/truek8s/clusterconfig$ kubectl get nodes&lt;br /&gt;NAME         STATUS   ROLES           AGE     VERSION&lt;br /&gt;truek8s-c1   Ready    control-plane   8m24s   v1.32.2&lt;br /&gt;truek8s-w1   Ready    &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;none&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;          8m36s   v1.32.2&lt;br /&gt;truek8s-w2   Ready    &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;none&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;          8m24s   v1.32.2&lt;br /&gt;truek8s@debian02:~/Documents/truek8s/clusterconfig$ kubectl get pods &lt;span class=&quot;token parameter variable&quot;&gt;-A&lt;/span&gt;&lt;br /&gt;NAMESPACE     NAME                                 READY   STATUS    RESTARTS       AGE&lt;br /&gt;kube-system   coredns-578d4f8ffc-v4g4p             &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;/1     Running   &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;              8m41s&lt;br /&gt;kube-system   coredns-578d4f8ffc-wk2dr             &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;/1     Running   &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;              8m41s&lt;br /&gt;kube-system   kube-apiserver-truek8s-c1            &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;/1     Running   &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;              7m56s&lt;br /&gt;kube-system   kube-controller-manager-truek8s-c1   &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;/1     Running   &lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;9m3s ago&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;   7m56s&lt;br /&gt;kube-system   kube-flannel-khxjs                   &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;/1     Running   &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;              8m39s&lt;br /&gt;kube-system   kube-flannel-lcw24                   &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;/1     Running   &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;              8m27s&lt;br /&gt;kube-system   kube-flannel-lj5t7                   &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;/1     Running   &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;              8m27s&lt;br /&gt;kube-system   kube-proxy-65rm7                     &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;/1     Running   &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;              8m27s&lt;br /&gt;kube-system   kube-proxy-75zbk                     &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;/1     Running   &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;              8m27s&lt;br /&gt;kube-system   kube-proxy-qxn9g                     &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;/1     Running   &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;              8m39s&lt;br /&gt;kube-system   kube-scheduler-truek8s-c1            &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;/1     Running   &lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;9m3s ago&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;   7m56s&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;Up Next&lt;/h2&gt;
&lt;p&gt;In part 2, we’ll configure FluxCD to manage our cluster.&lt;/p&gt;
&lt;h2&gt;Sources&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://www.talos.dev/v1.9/talos-guides/configuration/system-extensions/&quot;&gt;talos.dev: Customizing the Talos Linux immutable root file system.&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.talos.dev/v1.9/talos-guides/install/virtualized-platforms/proxmox/&quot;&gt;talos.dev: Creating Talos Kubernetes cluster using Proxmox&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.talos.dev/v1.9/talos-guides/install/boot-assets/#image-factory&quot;&gt;talos.dev: Creating customized Talos boot assets, disk images, ISO and installer images.&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.talos.dev/v1.8/talos-guides/install/talosctl/&quot;&gt;talos.dev: Install Talos Linux CLI&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://longhorn.io/docs/1.8.1/advanced-resources/os-distro-specific/talos-linux-support/#requirements&quot;&gt;longhorn.io: Talos Linux Support&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://hackmd.io/@QI-AN/Install-Longhorn-on-Talos-Kubernetes#Install-Longhorn-on-Talos-Kubernetes&quot;&gt;hackmd.io: Install Longhorn on Talos Kubernetes&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://calebcoffie.com/part-3-adding-longhorn-for-persistent-storage-on-our-talos-powered-kubernetes-cluster/&quot;&gt;calebcoffie.com: Part 3: Adding Longhorn for Persistent Storage on Our Talos-Powered Kubernetes Cluster&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://kubernetes.io/docs/tasks/tools/&quot;&gt;kubernetes.io: Set up Kubernetes tools on your computer&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
</content>
    </entry>
    
    <entry>
      <title>TrueK8S Part 02</title>
      <link href="http://localhost:8080/2025/05/15/truek8s-part-02/"/>
      <updated>2025-05-15T12:30:00Z</updated>
      <id>http://localhost:8080/2025/05/15/truek8s-part-02/</id>
      <content type="html">&lt;h1&gt;Configuring FluxCD for my TrueCharts Kubernetes cluster&lt;/h1&gt;
&lt;p&gt;So if you followed the last guide, you now have a Kubernetes cluster. Congrats! But what do we do with it?&lt;/p&gt;
&lt;p&gt;You have a couple options for deploying workloads to your cluster, but for the purposes of this series we’ll be deploying Helm Charts (mostly from the TrueCharts project, but not exclusively). Helm charts are essentially distributable ‘packages’ of apps for Kubernetes, and Helm is kind of like a package manager for those charts. Helm provides an easy mechanism to install, uninstall, or update a deployment of associated Kubernetes resources that make up an application.&lt;/p&gt;
&lt;p&gt;Before we go crazy deploying Helm charts, we’re going to take a detour and configure another tool called Flux. Flux is a Continuous Integration&#92;Continuous Deployment tool that manages the work of deploying stuff to your Kubernetes cluster for you. Instead of tossing things at your cluster haphazardly until it works, then inevitably forgetting how you made it work, you’ll instead push your config into a git repo, and flux will keep track of changes and do the work for you. You can (and should) read more about Flux &lt;a href=&quot;https://fluxcd.io/flux/get-started/&quot;&gt;here.&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;For the purpose of this guide, you need to know that Flux is configured through resources called Kustomizations. Kustomizations are written in yaml files and stored in your repository. Each Kustomization will apply resource manifests you define from a specified directory in your repo. The manifests are also written in YAML and can define any Kubernetes object e.g. a helm chart deployment, a namespace, an ingress definition, or even another kustomization.&lt;/p&gt;
&lt;h2&gt;Configuring your Flux Repo&lt;/h2&gt;
&lt;p&gt;Step one in setting up Flux is creating your repo. Flux supports multiple source control options, but I’ll be writing this guide for my preferred flavor of Git, Github.&lt;/p&gt;
&lt;p&gt;Head on over to github and create yourself a new repo. Call it whatever you want and set it to private for now. We’ll discuss how to protect the secrets contained within your repo later.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;http://localhost:8080/assets/images/2025/04/github-newrepo.png&quot; alt=&quot;image&quot; /&gt;&lt;/p&gt;
&lt;p&gt;Now you’ll need to generate a Personal Access Token. The days of basic authentication to github are long gone, and fine grained personal access tokens are all the rage. On Github:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Click on your profile icon in the top right &amp;gt; Settings&lt;/li&gt;
&lt;li&gt;Select Developer Settings from the left hand nav menu&lt;/li&gt;
&lt;li&gt;Expand personal access tokens, then select fine-grained access tokens&lt;/li&gt;
&lt;li&gt;Click on Generate new token&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Give it a descriptive name and description, and give it a reasonable expiration date (not eternity)&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;http://localhost:8080/assets/images/2025/04/github-new-pat-1.png&quot; alt=&quot;image&quot; /&gt;&lt;/p&gt;
&lt;p&gt;Scroll down and select only select repositories under repository access&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;http://localhost:8080/assets/images/2025/04/github-new-pat-2.png&quot; alt=&quot;image&quot; /&gt;&lt;/p&gt;
&lt;p&gt;Expand Repository Permissions and grant:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Administration -&amp;gt; Access: Read-only&lt;/li&gt;
&lt;li&gt;Contents -&amp;gt; Access: Read and write&lt;/li&gt;
&lt;li&gt;Metadata -&amp;gt; Access: Read-only&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;img src=&quot;http://localhost:8080/assets/images/2025/04/github-new-pat-3.png&quot; alt=&quot;image&quot; /&gt;&lt;br /&gt;
&lt;img src=&quot;http://localhost:8080/assets/images/2025/04/github-new-pat-4.png&quot; alt=&quot;image&quot; /&gt;&lt;/p&gt;
&lt;p&gt;And finally, click Generate Token at the bottom of the page. You will only be given one opportunity to retrieve your new PAT. Note, This is a credential that will have read&#92;write access to your cluster, it should be treated as such. Store it securely.&lt;/p&gt;
&lt;h2&gt;Flux Bootstrap&lt;/h2&gt;
&lt;p&gt;With your repo and access token ready to go, we just need to install flux on our admin workstation and run a single command to bootstrap flux into the cluster.&lt;/p&gt;
&lt;p&gt;Install flux cli with this command:&lt;/p&gt;
&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;token function&quot;&gt;curl&lt;/span&gt; &lt;span class=&quot;token parameter variable&quot;&gt;-s&lt;/span&gt; https://fluxcd.io/install.sh &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;sudo&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;bash&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Then set some environmental variables and run flux bootstrap:&lt;/p&gt;
&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;#You don&#39;t need quotes here&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token builtin class-name&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token assign-left variable&quot;&gt;GITHUB_TOKEN&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;your-PAT&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token builtin class-name&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token assign-left variable&quot;&gt;GITHUB_USER&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;your-username&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token builtin class-name&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token assign-left variable&quot;&gt;REPO&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;truek8s&lt;br /&gt;&lt;br /&gt;flux bootstrap github --token-auth &lt;span class=&quot;token parameter variable&quot;&gt;--owner&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$GITHUB_USER&lt;/span&gt;   &lt;span class=&quot;token parameter variable&quot;&gt;--repository&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$REPO&lt;/span&gt; &lt;span class=&quot;token parameter variable&quot;&gt;--branch&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;main   &lt;span class=&quot;token parameter variable&quot;&gt;--path&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;./clusters/&lt;span class=&quot;token variable&quot;&gt;$REPO&lt;/span&gt;   &lt;span class=&quot;token parameter variable&quot;&gt;--personal&lt;/span&gt;&lt;br /&gt;► connecting to github.com&lt;br /&gt;► cloning branch &lt;span class=&quot;token string&quot;&gt;&quot;main&quot;&lt;/span&gt; from Git repository &lt;span class=&quot;token string&quot;&gt;&quot;https://github.com/bmel343/truek8s.git&quot;&lt;/span&gt;&lt;br /&gt;✔ cloned repository&lt;br /&gt;► generating component manifests&lt;br /&gt;✔ generated component manifests&lt;br /&gt;✔ component manifests are up to &lt;span class=&quot;token function&quot;&gt;date&lt;/span&gt;&lt;br /&gt;► installing components &lt;span class=&quot;token keyword&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;flux-system&quot;&lt;/span&gt; namespace&lt;br /&gt;✔ installed components&lt;br /&gt;✔ reconciled components&lt;br /&gt;► determining &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token builtin class-name&quot;&gt;source&lt;/span&gt; secret &lt;span class=&quot;token string&quot;&gt;&quot;flux-system/flux-system&quot;&lt;/span&gt; exists&lt;br /&gt;► generating &lt;span class=&quot;token builtin class-name&quot;&gt;source&lt;/span&gt; secret&lt;br /&gt;► applying &lt;span class=&quot;token builtin class-name&quot;&gt;source&lt;/span&gt; secret &lt;span class=&quot;token string&quot;&gt;&quot;flux-system/flux-system&quot;&lt;/span&gt;&lt;br /&gt;✔ reconciled &lt;span class=&quot;token builtin class-name&quot;&gt;source&lt;/span&gt; secret&lt;br /&gt;► generating &lt;span class=&quot;token function&quot;&gt;sync&lt;/span&gt; manifests&lt;br /&gt;✔ generated &lt;span class=&quot;token function&quot;&gt;sync&lt;/span&gt; manifests&lt;br /&gt;✔ committed &lt;span class=&quot;token function&quot;&gt;sync&lt;/span&gt; manifests to &lt;span class=&quot;token string&quot;&gt;&quot;main&quot;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;678431f55509e67f22c6e57ccc052954f932bed1&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;br /&gt;► pushing &lt;span class=&quot;token function&quot;&gt;sync&lt;/span&gt; manifests to &lt;span class=&quot;token string&quot;&gt;&quot;https://github.com/bmel343/truek8s.git&quot;&lt;/span&gt;&lt;br /&gt;► applying &lt;span class=&quot;token function&quot;&gt;sync&lt;/span&gt; manifests&lt;br /&gt;✔ reconciled &lt;span class=&quot;token function&quot;&gt;sync&lt;/span&gt; configuration&lt;br /&gt;◎ waiting &lt;span class=&quot;token keyword&quot;&gt;for&lt;/span&gt; GitRepository &lt;span class=&quot;token string&quot;&gt;&quot;flux-system/flux-system&quot;&lt;/span&gt; to be reconciled&lt;br /&gt;✔ GitRepository reconciled successfully&lt;br /&gt;◎ waiting &lt;span class=&quot;token keyword&quot;&gt;for&lt;/span&gt; Kustomization &lt;span class=&quot;token string&quot;&gt;&quot;flux-system/flux-system&quot;&lt;/span&gt; to be reconciled&lt;br /&gt;✔ Kustomization reconciled successfully&lt;br /&gt;► confirming components are healthy&lt;br /&gt;✔ helm-controller: deployment ready&lt;br /&gt;✔ kustomize-controller: deployment ready&lt;br /&gt;✔ notification-controller: deployment ready&lt;br /&gt;✔ source-controller: deployment ready&lt;br /&gt;✔ all components are healthy&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Now clone your flux repo to your admin workstation. This will become your working directory where you will stage changes before committing to your cluster. I’ll clone it to ~/Documents.&lt;/p&gt;
&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;token function&quot;&gt;git&lt;/span&gt; clone https://&lt;span class=&quot;token variable&quot;&gt;$GITHUB_TOKEN&lt;/span&gt;@github.com/&lt;span class=&quot;token variable&quot;&gt;$GITHUB_USER&lt;/span&gt;/&lt;span class=&quot;token variable&quot;&gt;$REPO&lt;/span&gt;&lt;br /&gt;Cloning into &lt;span class=&quot;token string&quot;&gt;&#39;truek8s&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;..&lt;/span&gt;.&lt;br /&gt;remote: Enumerating objects: &lt;span class=&quot;token number&quot;&gt;16&lt;/span&gt;, done.&lt;br /&gt;remote: Counting objects: &lt;span class=&quot;token number&quot;&gt;100&lt;/span&gt;% &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;16&lt;/span&gt;/16&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;, done.&lt;br /&gt;remote: Compressing objects: &lt;span class=&quot;token number&quot;&gt;100&lt;/span&gt;% &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;9&lt;/span&gt;/9&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;, done.&lt;br /&gt;remote: Total &lt;span class=&quot;token number&quot;&gt;16&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;delta &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;, reused &lt;span class=&quot;token number&quot;&gt;13&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;delta &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;, pack-reused &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;from &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;br /&gt;Receiving objects: &lt;span class=&quot;token number&quot;&gt;100&lt;/span&gt;% &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;16&lt;/span&gt;/16&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;, &lt;span class=&quot;token number&quot;&gt;59.84&lt;/span&gt; KiB &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1.66&lt;/span&gt; MiB/s, done.&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Now you should have a local copy of your repo, complete with the initial components of flux.&lt;/p&gt;
&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;token variable&quot;&gt;$tree&lt;/span&gt; truek8s&lt;br /&gt;truek8s&lt;br /&gt;├── clusters&lt;br /&gt;│ └── truek8s&lt;br /&gt;│     └── flux-system&lt;br /&gt;│         ├── gotk-components.yaml&lt;br /&gt;│         ├── gotk-sync.yaml&lt;br /&gt;│         └── kustomization.yaml&lt;br /&gt;└── README.md&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Congrats! Flux is now set up and ready to configure your cluster for you.&lt;/p&gt;
&lt;h2&gt;Organizing your flux repo&lt;/h2&gt;
&lt;p&gt;Now comes the important step of deciding how to organize our flux repo. I learned the hard way through trial and error that decisions about how to organize your flux repo have severe consequences. It’s very important to read the docs (linked at the bottom of the page) and make an informed decision on how to organize things before you start deploying. I’ll save you some reading and share a couple lessons I learned the hard way:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Do not mess with the flux-system kustomization. If you do, you may break flux and need to re-bootstrap.&lt;/li&gt;
&lt;li&gt;You must not create kustomizations with overlapping paths. Doing so may seem like an intuitive way to create a heirarchy of resources, but will result in reconcilers fighting over eachother to apply the same resources.&lt;/li&gt;
&lt;li&gt;You should create a unique kustomization for every app deployment. This gives you flexibility for troubleshooting and organization.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;With that said, I’ll be taking guidance on how to structure my repo from the following resources.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/fluxcd/flux2-kustomize-helm-example/tree/main/clusters&quot;&gt;The official flux helm example&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://truecharts.org/guides/staff/&quot;&gt;The Truecharts example clusters&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Learning from those examples, I decided to organize my repo like this:&lt;/p&gt;
&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;$ tree truek8s&lt;br /&gt;truek8s&lt;br /&gt;├── apps&lt;br /&gt;│ ├── general&lt;br /&gt;│ └── production&lt;br /&gt;│     └── kustomization.yaml&lt;br /&gt;├── clusters&lt;br /&gt;│ └── truek8s&lt;br /&gt;│     ├── apps.yaml&lt;br /&gt;│     ├── config.yaml&lt;br /&gt;│     ├── flux-system&lt;br /&gt;│     │ ├── gotk-components.yaml&lt;br /&gt;│     │ ├── gotk-sync.yaml&lt;br /&gt;│     │ └── kustomization.yaml&lt;br /&gt;│     ├── infrastructure.yaml&lt;br /&gt;│     └── repos.yaml&lt;br /&gt;├── config&lt;br /&gt;│ └── kustomization.yaml&lt;br /&gt;── infrastructure&lt;br /&gt;│ ├── core&lt;br /&gt;│ └── production&lt;br /&gt;│     └── kustomization.yaml&lt;br /&gt;└── repos&lt;br /&gt;    └── kustomization.yaml&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;I’ll be separating my flux resources into repositories, infrastructure, config, and apps. For each of those top level directories, a kustomization in clusters/truek8s will tell flux to apply those resources.&lt;/p&gt;
&lt;h2&gt;Dependencies&lt;/h2&gt;
&lt;p&gt;Another important design decision to make at this point is how to configure dependencies. Flux kustomizations can be dependent on other kustomizations, which allows you to control the order in which they are applied. This allows you to instruct flux to install certain charts before others. This will be very important later on in this guide when we talk about using our flux repo to automatically restore our workloads to a new cluster. For now, we’ll configure the dependencies of our three main kustomizations:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Config and Repos will be applied first (no dependencies)&lt;/li&gt;
&lt;li&gt;Infrastructure will apply second, and it must depend on Config.&lt;/li&gt;
&lt;li&gt;Apps will be applied last, and it will depend on Infrastructure.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Dependence is configured in the kustomization manifest in the spec.dependsOn field. There are full examples of that below.&lt;/p&gt;
&lt;h3&gt;Config&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;clusters/truek8s/config.yaml&lt;/strong&gt;&lt;/p&gt;
&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;apiVersion: kustomize.toolkit.fluxcd.io/v1&lt;br /&gt;kind: Kustomization&lt;br /&gt;metadata:&lt;br /&gt;  name: config&lt;br /&gt;  namespace: flux-system&lt;br /&gt;spec:&lt;br /&gt;  interval: 1h&lt;br /&gt;  retryInterval: 1m&lt;br /&gt;  timeout: 5m&lt;br /&gt;  sourceRef:&lt;br /&gt;    kind: GitRepository&lt;br /&gt;    name: flux-system&lt;br /&gt;  path: ./config&lt;br /&gt;  prune: &lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;&lt;br /&gt;  wait: &lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;/config/kustomization.yaml&lt;/strong&gt;&lt;/p&gt;
&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;apiVersion: kustomize.config.k8s.io/v1beta1&lt;br /&gt;kind: Kustomization&lt;br /&gt;resources: &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;div class=&quot;wrapper p-4 p-2 my-4 rounded-lg bg-red-100 text-gray-700 border border-red-300&quot;&gt;
&lt;p&gt;⚠️ Notice how there are two manifests of type ‘kustomization’? That confused me at first. You can read more about that &lt;a href=&quot;https://fluxcd.io/flux/faq/#are-there-two-kustomization-types&quot;&gt;here&lt;/a&gt; but TL;DR:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;kustomize.toolkit.fluxcd.io creates the Kubernetes CRD that is a flux kustomization. This manifests creates the object that you’ll see when you run flux get ks (see below for examples).&lt;/li&gt;
&lt;li&gt;kustomize.config.k8s.io specifics the flux overlay, or I like to think of it as pointing the CRD at the actual manifest.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;So in this case, apps.yaml applies the overlay specified at ./apps/production/kustomization.yaml, which contains references to the actual deployment manifests.&lt;/p&gt;
&lt;/div&gt;
&lt;h3&gt;Repos&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;clusters/truek8s/repos.yaml&lt;/strong&gt;&lt;/p&gt;
&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;apiVersion: kustomize.toolkit.fluxcd.io/v1&lt;br /&gt;kind: Kustomization&lt;br /&gt;metadata:&lt;br /&gt;  name: repos&lt;br /&gt;  namespace: flux-system&lt;br /&gt;spec:&lt;br /&gt;  interval: 1h&lt;br /&gt;  retryInterval: 1m&lt;br /&gt;  timeout: 5m&lt;br /&gt;  sourceRef:&lt;br /&gt;    kind: GitRepository&lt;br /&gt;    name: flux-system&lt;br /&gt;  path: ./repos&lt;br /&gt;  prune: &lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;&lt;br /&gt;  wait: &lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;/repos/kustomization.yaml&lt;/strong&gt;&lt;/p&gt;
&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;apiVersion: kustomize.config.k8s.io/v1beta1&lt;br /&gt;kind: Kustomization&lt;br /&gt;resources: &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;div class=&quot;wrapper p-4 p-2 my-4 rounded-lg bg-red-100 text-gray-700 border border-red-300&quot;&gt;
&lt;p&gt;⚠️ If you’re wondering why repos is not split into two different folders the way that apps and infrastrcture are, it’s because we have no need to create additional kustomizations under /clusters/repos. They can all be applied by clusters/truek8s/config.yaml.&lt;/p&gt;
&lt;/div&gt;
&lt;h3&gt;Infrastructure&lt;/h3&gt;
&lt;p&gt;You may have noticed that the Infrastructure and Apps directories contain additional directores. This design is taken from the &lt;a href=&quot;https://github.com/fluxcd/flux2-kustomize-helm-example/tree/main/clusters&quot;&gt;official flux helm example&lt;/a&gt;, we’ll have separate directories that hold all of our application deployment resources and then we’ll have a different Kustomization within ‘production’ that actually applies those applications to our cluster. This gives us flexibility to re-use our resources in a ‘staging’ or ‘dev’ environment, and also allows us to create separate kustomziaitons for each app without any overlapping paths.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;clusters/truek8s/infrastructure.yaml&lt;/strong&gt;&lt;/p&gt;
&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;apiVersion: kustomize.toolkit.fluxcd.io/v1&lt;br /&gt;kind: Kustomization&lt;br /&gt;metadata:&lt;br /&gt;  name: infrastructure&lt;br /&gt;  namespace: flux-system&lt;br /&gt;spec:&lt;br /&gt;  dependsOn:&lt;br /&gt;    - name: config&lt;br /&gt;  interval: 1h&lt;br /&gt;  retryInterval: 1m&lt;br /&gt;  timeout: 5m&lt;br /&gt;  sourceRef:&lt;br /&gt;    kind: GitRepository&lt;br /&gt;    name: flux-system&lt;br /&gt;  path: ./infrastructure/production&lt;br /&gt;  prune: &lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;&lt;br /&gt;  wait: &lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;/infrastructure/production/kustomization.yaml&lt;/strong&gt;&lt;/p&gt;
&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;apiVersion: kustomize.config.k8s.io/v1beta1&lt;br /&gt;kind: Kustomization&lt;br /&gt;resources: &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;Apps&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;clusters/truek8s/apps.yaml&lt;/strong&gt;&lt;/p&gt;
&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;apiVersion: kustomize.toolkit.fluxcd.io/v1&lt;br /&gt;kind: Kustomization&lt;br /&gt;metadata:&lt;br /&gt;  name: apps&lt;br /&gt;  namespace: flux-system&lt;br /&gt;spec:&lt;br /&gt;  dependsOn:&lt;br /&gt;    - name: infrastructure&lt;br /&gt;  interval: 10m&lt;br /&gt;  retryInterval: 1m&lt;br /&gt;  timeout: 5m&lt;br /&gt;  sourceRef:&lt;br /&gt;    kind: GitRepository&lt;br /&gt;    name: flux-system&lt;br /&gt;  path: ./apps/production&lt;br /&gt;  prune: &lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;&lt;br /&gt;  wait: &lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;/apps/production/kustomization.yaml&lt;/strong&gt;&lt;/p&gt;
&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;apiVersion: kustomize.config.k8s.io/v1beta1&lt;br /&gt;kind: Kustomization&lt;br /&gt;resources: &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;Testing Flux&lt;/h2&gt;
&lt;p&gt;Now that our repository is organized, we can test it out by creating some resources for flux to deploy for us. We’re going to deploy an instance of podinfo, which is used pretty regularly for testing in Kubernetes. This deployment will consist of three manifests:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;The podinfo helm chart repository&lt;/li&gt;
&lt;li&gt;A namespace definition&lt;/li&gt;
&lt;li&gt;The podinfo helm relaase&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;podinfo repo&lt;/h3&gt;
&lt;p&gt;Create the repository at &lt;strong&gt;/repos/podinfo.yaml&lt;/strong&gt;&lt;/p&gt;
&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;apiVersion: source.toolkit.fluxcd.io/v1&lt;br /&gt;kind: HelmRepository&lt;br /&gt;metadata:&lt;br /&gt;  name: podinfo&lt;br /&gt;  namespace: flux-system&lt;br /&gt;spec:&lt;br /&gt;  type: &lt;span class=&quot;token string&quot;&gt;&quot;oci&quot;&lt;/span&gt;&lt;br /&gt;  interval: 2h&lt;br /&gt;  url: oci://ghcr.io/stefanprodan/charts&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;And then add a reference to that manifest in &lt;strong&gt;/repos/kustomization.yaml&lt;/strong&gt;&lt;/p&gt;
&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;apiVersion: kustomize.config.k8s.io/v1beta1&lt;br /&gt;kind: Kustomization&lt;br /&gt;resources:&lt;br /&gt;  - podinfo.yaml&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;Podinfo app&lt;/h3&gt;
&lt;p&gt;To create the other resources, we need to create these files:&lt;/p&gt;
&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;truek8s/apps/&lt;br /&gt;├── general&lt;br /&gt;│└── podinfo&lt;br /&gt;│    ├── kustomization.yaml&lt;br /&gt;│    ├── namespace.yaml&lt;br /&gt;│    └── helm-release.yaml&lt;br /&gt;└── production&lt;br /&gt;    ├── kustomization.yaml&lt;br /&gt;    └── podinfo.yaml&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The manifests at /apps/general/podinfo/ are exactly what they sound like, a helm release, a namespace definition, and a kustomization to reference them. /apps/production/podinfo.yaml creates the actual flux kustomizaiton that will apply the podinfo manifests. One by one:&lt;/p&gt;
&lt;h4&gt;apps/general/podinfo&lt;/h4&gt;
&lt;p&gt;&lt;strong&gt;namespace.yaml&lt;/strong&gt;&lt;/p&gt;
&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;apiVersion: v1&lt;br /&gt;kind: Namespace&lt;br /&gt;metadata:&lt;br /&gt;  name: podinfo&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;helm-release.yaml&lt;/strong&gt;&lt;/p&gt;
&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;apiVersion: helm.toolkit.fluxcd.io/v2&lt;br /&gt;kind: HelmRelease&lt;br /&gt;metadata:&lt;br /&gt;  name: podinfo&lt;br /&gt;  namespace: podinfo&lt;br /&gt;spec:&lt;br /&gt;  interval: 10m&lt;br /&gt;  timeout: 5m&lt;br /&gt;  chart:&lt;br /&gt;    spec:&lt;br /&gt;      chart: podinfo&lt;br /&gt;      sourceRef:&lt;br /&gt;        kind: HelmRepository&lt;br /&gt;        name: podinfo&lt;br /&gt;        namespace: flux-system&lt;br /&gt;      interval: 5m&lt;br /&gt;  releaseName: podinfo&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;kustomization.yaml&lt;/strong&gt;&lt;/p&gt;
&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;apiVersion: kustomize.config.k8s.io/v1beta1&lt;br /&gt;kind: Kustomization&lt;br /&gt;namespace: podinfo&lt;br /&gt;resources:&lt;br /&gt;  - namespace.yaml&lt;br /&gt;  - helm-release.yaml&lt;/code&gt;&lt;/pre&gt;
&lt;h4&gt;apps/production&lt;/h4&gt;
&lt;p&gt;&lt;strong&gt;podinfo.yaml&lt;/strong&gt;&lt;/p&gt;
&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;apiVersion: kustomize.toolkit.fluxcd.io/v1&lt;br /&gt;kind: Kustomization&lt;br /&gt;metadata:&lt;br /&gt;  name: podinfo&lt;br /&gt;  namespace: flux-system&lt;br /&gt;spec:&lt;br /&gt;  interval: 10m&lt;br /&gt;  path: apps/general/podinfo&lt;br /&gt;  prune: &lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;&lt;br /&gt;  sourceRef:&lt;br /&gt;    kind: GitRepository&lt;br /&gt;    name: flux-system&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;kustomization.yaml&lt;/strong&gt;&lt;/p&gt;
&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;apiVersion: kustomize.config.k8s.io/v1beta1&lt;br /&gt;kind: Kustomization&lt;br /&gt;resources:&lt;br /&gt;  - podinfo.yaml&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;Commit&lt;/h3&gt;
&lt;p&gt;With all that created, go ahead and commit to your repo, then watch flux events to see them be reconciled:&lt;/p&gt;
&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;token variable&quot;&gt;$git&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;add&lt;/span&gt; &lt;span class=&quot;token parameter variable&quot;&gt;-A&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;git&lt;/span&gt; commit &lt;span class=&quot;token parameter variable&quot;&gt;-m&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Add podinfo&quot;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token variable&quot;&gt;$git&lt;/span&gt; push&lt;br /&gt;&lt;br /&gt;$ flux events &lt;span class=&quot;token parameter variable&quot;&gt;--watch&lt;/span&gt;&lt;br /&gt;LAST SEEN       TYPE    REASON          OBJECT                  &lt;br /&gt;57s     Normal  Progressing     Kustomization/podinfo   Namespace/podinfo created          &lt;br /&gt;                                                        HelmRelease/podinfo/podinfo created&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;After our commit is reconciled by flux, use the flux get hr command to check on the status of the podinfo deployment.&lt;/p&gt;
&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;$ flux get hr &lt;span class=&quot;token parameter variable&quot;&gt;-n&lt;/span&gt; podinfo&lt;br /&gt;NAME    REVISION        SUSPENDED       READY   MESSAGE                                                                        &lt;br /&gt;podinfo &lt;span class=&quot;token number&quot;&gt;6.8&lt;/span&gt;.0           False           True    Helm &lt;span class=&quot;token function&quot;&gt;install&lt;/span&gt; succeeded &lt;span class=&quot;token keyword&quot;&gt;for&lt;/span&gt; release podinfo/podinfo.v1 with chart podinfo@6.8.0&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;If the helm chart was deployed successfully, we can use kubectl port-forward to access the web service provided by podinfo. Inspect the services in the podinfo namespace, and then port forward from your admin workstation. This will allow you to access the web page in your browser.&lt;/p&gt;
&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;$ kubectl get &lt;span class=&quot;token function&quot;&gt;service&lt;/span&gt; &lt;span class=&quot;token parameter variable&quot;&gt;-n&lt;/span&gt; podinfo&lt;br /&gt;NAME      TYPE        CLUSTER-IP     EXTERNAL-IP   PORT&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;S&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;             AGE&lt;br /&gt;podinfo   ClusterIP   &lt;span class=&quot;token number&quot;&gt;172&lt;/span&gt;.XX.206.4   &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;none&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;        &lt;span class=&quot;token number&quot;&gt;9898&lt;/span&gt;/TCP,9999/TCP   63m&lt;br /&gt;$ kubectl port-forward &lt;span class=&quot;token parameter variable&quot;&gt;-n&lt;/span&gt; podinfo service/podinfo &lt;span class=&quot;token number&quot;&gt;9898&lt;/span&gt;:9898&lt;br /&gt;Forwarding from &lt;span class=&quot;token number&quot;&gt;127.0&lt;/span&gt;.0.1:9898 -&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;9898&lt;/span&gt;&lt;br /&gt;Forwarding from &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;::1&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;:9898 -&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;9898&lt;/span&gt;&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&quot;http://localhost:8080/assets/images/2025/04/podinfo-1.png&quot; alt=&quot;image&quot; /&gt;&lt;/p&gt;
&lt;p&gt;Finally, you can use the flux tree command to inspect the resources and understand how flux applies them:&lt;/p&gt;
&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;$ flux tree ks flux-system&lt;br /&gt;Kustomization/flux-system/flux-system&lt;br /&gt;├── CustomResourceDefinition/alerts.notification.toolkit.fluxcd.io&lt;br /&gt;├── CustomResourceDefinition/buckets.source.toolkit.fluxcd.io&lt;br /&gt;├── CustomResourceDefinition/gitrepositories.source.toolkit.fluxcd.io&lt;br /&gt;├── CustomResourceDefinition/helmcharts.source.toolkit.fluxcd.io&lt;br /&gt;├── CustomResourceDefinition/helmreleases.helm.toolkit.fluxcd.io&lt;br /&gt;├── CustomResourceDefinition/helmrepositories.source.toolkit.fluxcd.io&lt;br /&gt;├── CustomResourceDefinition/kustomizations.kustomize.toolkit.fluxcd.io&lt;br /&gt;├── CustomResourceDefinition/ocirepositories.source.toolkit.fluxcd.io&lt;br /&gt;├── CustomResourceDefinition/providers.notification.toolkit.fluxcd.io&lt;br /&gt;├── CustomResourceDefinition/receivers.notification.toolkit.fluxcd.io&lt;br /&gt;├── Namespace/flux-system&lt;br /&gt;├── ResourceQuota/flux-system/critical-pods-flux-system&lt;br /&gt;├── ServiceAccount/flux-system/helm-controller&lt;br /&gt;├── ServiceAccount/flux-system/kustomize-controller&lt;br /&gt;├── ServiceAccount/flux-system/notification-controller&lt;br /&gt;├── ServiceAccount/flux-system/source-controller&lt;br /&gt;├── ClusterRole/crd-controller-flux-system&lt;br /&gt;├── ClusterRole/flux-edit-flux-system&lt;br /&gt;├── ClusterRole/flux-view-flux-system&lt;br /&gt;├── ClusterRoleBinding/cluster-reconciler-flux-system&lt;br /&gt;├── ClusterRoleBinding/crd-controller-flux-system&lt;br /&gt;├── Service/flux-system/notification-controller&lt;br /&gt;├── Service/flux-system/source-controller&lt;br /&gt;├── Service/flux-system/webhook-receiver&lt;br /&gt;├── Deployment/flux-system/helm-controller&lt;br /&gt;├── Deployment/flux-system/kustomize-controller&lt;br /&gt;├── Deployment/flux-system/notification-controller&lt;br /&gt;├── Deployment/flux-system/source-controller&lt;br /&gt;├── Kustomization/flux-system/apps&lt;br /&gt;│   └── Kustomization/flux-system/podinfo&lt;br /&gt;│       ├── Namespace/podinfo&lt;br /&gt;│       └── HelmRelease/podinfo/podinfo&lt;br /&gt;│           ├── Service/podinfo/podinfo&lt;br /&gt;│           └── Deployment/podinfo/podinfo&lt;br /&gt;├── Kustomization/flux-system/config&lt;br /&gt;├── Kustomization/flux-system/infrastructure&lt;br /&gt;├── Kustomization/flux-system/repos&lt;br /&gt;│   ├── HelmRepository/flux-system/podinfo&lt;br /&gt;├── NetworkPolicy/flux-system/allow-egress&lt;br /&gt;├── NetworkPolicy/flux-system/allow-scraping&lt;br /&gt;├── NetworkPolicy/flux-system/allow-webhooks&lt;br /&gt;└── GitRepository/flux-system/flux-system&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This view helps me understand the way that kustomizations are applied and why the structure of our repository matters. The flux-system kustomization applies builtin flux components, and then also applies the kustomizations the we wrote to the /clusters/truek8s directory. Those kustomizations then apply other cluster resources, such as the repository, helm release, and namespace resources that make up our podinfo deployment.&lt;/p&gt;
&lt;h2&gt;My Cluster&lt;/h2&gt;
&lt;p&gt;I will make my own cluster repository available to supplement this guide. You can view it here: &lt;a href=&quot;https://github.com/bmel343/truek8s&quot;&gt;GitHub - TrueK8s&lt;/a&gt;. You may think that’s a privacy concern, but in the next guide we’ll discuss why I can do this safely.&lt;/p&gt;
&lt;h2&gt;Sources&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://fluxcd.io/flux/cmd/&quot;&gt;fluxcd.io: Flux CLI&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://fluxcd.io/flux/get-started/&quot;&gt;fluxcd.io: Get Started with Flux&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://fluxcd.io/flux/installation/bootstrap/github/#github-organization&quot;&gt;fluxcd.io: Flux bootstrap for GitHub&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://fluxcd.io/flux/faq/#kustomize-questions&quot;&gt;fluxcd.io: Are there two Kustomization types?&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://docs.github.com/en/authentication/keeping-your-account-and-data-secure/managing-your-personal-access-tokens&quot;&gt;docs.github.com: Managing your personal access tokens&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/fluxcd/flux2/discussions/3801&quot;&gt;github.com: How to structure Flux Kustomizations for single repository? #3801&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
</content>
    </entry>
    
    <entry>
      <title>TrueK8S Part 03</title>
      <link href="http://localhost:8080/2025/05/15/truek8s-part-03/"/>
      <updated>2025-05-15T12:30:00Z</updated>
      <id>http://localhost:8080/2025/05/15/truek8s-part-03/</id>
      <content type="html">&lt;h1&gt;Creating an encrypted ConfigMap for secure variable susbtitution with flux.&lt;/h1&gt;
&lt;p&gt;As we write yaml files for kubernetes resources, we’ll be referencing a lot of repetitive and/or sensitive information such as IPs, API Keys, or passwords. Because we’re using flux, all of that sensitive information is going to end up in a git repo. Moreover, we’re going to have to do a lot of silly copy pasting to reference common values. Copy pasting over and over sucks and storing secrets in a github repo (even a private one) is poor practice. Thankfully flux provides mechanisms to deal with this: SOPS for encrypting and decrypting secrets, and post build substitution to implement variables in our deployment resources. Using these two mechanisms we’ll create a kuberentes ConfigMap full of variables that we can reference in our deployment references.&lt;/p&gt;
&lt;p&gt;SOPS (Secret OPerationS) is a tool that can encrypt various file formats, in our case YAML. It knows how to encrypt just the value portions of our files while leaving the rest in-tact. Flux understand SOPS and can use it to decrypt our encrypted cert-manager on the fly. We’ll provide our secret key to Flux securely, and then use the post build susbstituion configuration to perform variable substitution on our deployment resources referencing the secrets from our ConfigMap.&lt;/p&gt;
&lt;h2&gt;Configure SOPS and AGE&lt;/h2&gt;
&lt;p&gt;Let’s start by installing SOPS (the encryption tool) and age (tools for the specific encryption algorithm we will use with SOPS).&lt;/p&gt;
&lt;p&gt;Install SOPS:&lt;/p&gt;
&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;# Download the binary&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token function&quot;&gt;curl&lt;/span&gt; &lt;span class=&quot;token parameter variable&quot;&gt;-LO&lt;/span&gt; https://github.com/getsops/sops/releases/download/v3.10.2/sops-v3.10.2.linux.amd64&lt;br /&gt;&lt;br /&gt;&lt;span class=&quot;token comment&quot;&gt;# Move the binary into your PATH&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token function&quot;&gt;mv&lt;/span&gt; sops-v3.10.2.linux.amd64 /usr/local/bin/sops&lt;br /&gt;&lt;br /&gt;&lt;span class=&quot;token comment&quot;&gt;# Make the binary executable&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token function&quot;&gt;chmod&lt;/span&gt; +x /usr/local/bin/sops&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;and install AGE:&lt;/p&gt;
&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;$ &lt;span class=&quot;token function&quot;&gt;apt&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;install&lt;/span&gt; age&lt;/code&gt;&lt;/pre&gt;
&lt;div class=&quot;wrapper p-4 p-2 my-4 rounded-lg bg-yellow-100 text-gray-700 border border-yellow-300&quot;&gt;
&lt;p&gt;💡 This command installs version 3.10.2. Check SOPS documentation to see if a newer version is available.&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;We’ll use the age tools we just installed to create an age encryption key pair. This will generate a key.txt file including your public and private key, so make sure to save this file securely OUTSIDE of your git repo.&lt;/p&gt;
&lt;p&gt;To create the key pair:&lt;/p&gt;
&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;$ age-keygen &lt;span class=&quot;token parameter variable&quot;&gt;-o&lt;/span&gt; sops-key.txt&lt;br /&gt;Public key: age1uprm5p9crdz7xn3ra9kfwv2axyg6re0jgn6tknf9tmsrn7dm2u3qktlpgx&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Inspect the contents of your key file, it should look like this:&lt;/p&gt;
&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;$ &lt;span class=&quot;token function&quot;&gt;cat&lt;/span&gt; sops-key.txt&lt;br /&gt;created: &lt;span class=&quot;token number&quot;&gt;2025&lt;/span&gt;-04-28T18:30:27-05:00&lt;br /&gt;public key: age1uprm5p9crdz7xn3ra9kfwv2axyg6re0jgn6tknf9tmsrn7dm2u3qktlpgx&lt;br /&gt;AGE-SECRET-KEY-&lt;span class=&quot;token comment&quot;&gt;#############################################################&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Now copy your key file to your ~/.config/sops/age/keys.txt so that SOPS knows where to find it. You’ll probably need to create the directories:&lt;/p&gt;
&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;$ &lt;span class=&quot;token function&quot;&gt;mkdir&lt;/span&gt; ~/.config/sops&lt;br /&gt;$ &lt;span class=&quot;token function&quot;&gt;mkdir&lt;/span&gt; ~/.config/sops/age&lt;br /&gt;$ &lt;span class=&quot;token function&quot;&gt;nano&lt;/span&gt; ~/.config/sops/age/keys.txt&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Now we need to give our encryption keys to flux. We’ll create a generic secret in the flux-system namespace and import content from our sops-key.txt file.&lt;/p&gt;
&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;$ kubectl &lt;span class=&quot;token parameter variable&quot;&gt;-n&lt;/span&gt; flux-system create secret generic sops-age --from-file&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;age.agekey&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;sops-key.txt&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Finally, we need to create a .sops config file within our repo to tell SOPS exactly how we want it to encrypt files within our repository. SOPS looks for a .SOPS.yaml file in any parent directory when it runs, so we’ll create that file in the config directory and populate it with our PUBLIC key (don’t put your age private key here).&lt;/p&gt;
&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;config$ &lt;span class=&quot;token function&quot;&gt;cat&lt;/span&gt; .sops.yaml &lt;br /&gt;creation_rules:&lt;br /&gt;  - encrypted_regex: &lt;span class=&quot;token string&quot;&gt;&#39;^(data|stringData)$&#39;&lt;/span&gt;&lt;br /&gt;    age: age1uprm5p9crdz7xn3ra9kfwv2axyg6re0jgn6tknf9tmsrn7dm2u3qktlpgx&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;Create an encrypted ConfigMap resource in flux&lt;/h2&gt;
&lt;p&gt;Now that we have flux set to use our SOPS key to decrypt files, we’re going to create a ConfigMap and encrypt it with SOPS. If you’ve been following along, you should have a flux repo structure like this:&lt;/p&gt;
&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;truek8s@debian02:~/Documents$ tree truek8s&lt;br /&gt;truek8s&lt;br /&gt;├── apps&lt;br /&gt;│ ├── general&lt;br /&gt;│ └── production&lt;br /&gt;│     └── kustomization.yaml&lt;br /&gt;├── clusters&lt;br /&gt;│ └── truek8s&lt;br /&gt;│     ├── apps.yaml&lt;br /&gt;│     ├── config.yaml&lt;br /&gt;│     ├── flux-system&lt;br /&gt;│     │ ├── gotk-components.yaml&lt;br /&gt;│     │ ├── gotk-sync.yaml&lt;br /&gt;│     │ └── kustomization.yaml&lt;br /&gt;│     ├── infrastructure.yaml&lt;br /&gt;│     └── repos.yaml&lt;br /&gt;├── config&lt;br /&gt;│ ├── .sops.yaml&lt;br /&gt;│ └── kustomization.yaml&lt;br /&gt;── infrastructure&lt;br /&gt;│ ├── core&lt;br /&gt;│ └── production&lt;br /&gt;│     └── kustomization.yaml&lt;br /&gt;└── repos&lt;br /&gt;    └── kustomization.yaml&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;We’re going to create our new ConfigMap in the config directory, where it will be applied by the /clusters/truek8s/config kustomization. We’ll start by making a tweak to the /clusters/truek8s/config kustomization. Go ahead and add the spec.decryption section shown below. This will instruct flux to use the secret we created earlier to decrypt any encypted files it finds. It should look like this:&lt;/p&gt;
&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;apiVersion: kustomize.toolkit.fluxcd.io/v1&lt;br /&gt;kind: Kustomization&lt;br /&gt;metadata:&lt;br /&gt;  name: config&lt;br /&gt;  namespace: flux-system&lt;br /&gt;spec:&lt;br /&gt;  interval: 1h&lt;br /&gt;  retryInterval: 1m&lt;br /&gt;  timeout: 5m&lt;br /&gt;  sourceRef:&lt;br /&gt;    kind: GitRepository&lt;br /&gt;    name: flux-system&lt;br /&gt;  path: ./config&lt;br /&gt;  prune: &lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;&lt;br /&gt;  wait: &lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;&lt;br /&gt;  decryption:&lt;br /&gt;    provider: sops&lt;br /&gt;    secretRef:&lt;br /&gt;      name: sops-age&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Next, create the config map at ./config/cluster-config.yaml, and populate it with a yaml ConfigMap definition like this. You can define any arbitrary values under the data field in the name: value format. In this case, we’ve created a ConfigMap that maps ‘test’ to ‘Value’, and we can reference ‘test’ as a variable later in other flux resources.&lt;/p&gt;
&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;apiVersion: v1&lt;br /&gt;kind: ConfigMap&lt;br /&gt;metadata:&lt;br /&gt;    name: cluster-config&lt;br /&gt;    namespace: flux-system&lt;br /&gt;data:&lt;br /&gt;    test: Value&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;And don’t forget to update the ./config/kustomization.yaml so that it applies the new cluster-config.yaml file:&lt;/p&gt;
&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;apiVersion: kustomize.config.k8s.io/v1beta1&lt;br /&gt;kind: Kustomization&lt;br /&gt;resources: &lt;br /&gt;  - cluster-config.yaml&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Finall, we can encrypt our ConfigMap resource and commit everything to our repo. From the ./config run this command to encrypt the file:&lt;/p&gt;
&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;sops &lt;span class=&quot;token parameter variable&quot;&gt;-e&lt;/span&gt; &lt;span class=&quot;token parameter variable&quot;&gt;-i&lt;/span&gt; cluster-config.yaml&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This will transform your ConfigMap resource from a plaintext file to a SOPS encrypted file, like this:&lt;/p&gt;
&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;apiVersion: v1&lt;br /&gt;kind: ConfigMap&lt;br /&gt;metadata:&lt;br /&gt;    name: cluster-config&lt;br /&gt;    namespace: flux-system&lt;br /&gt;data:&lt;br /&gt;    test: ENC&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;AES256_GCM,data:ajzYI0s&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;,iv:bZ+1ZK4GnaXTkJWgqwWmVj8gPfgeBRHtDFc/kyOtbEA&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;,tag:fctQUsbxfyNyJ/w+/6Ob7Q&lt;span class=&quot;token operator&quot;&gt;==&lt;/span&gt;,type:str&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;br /&gt;sops:&lt;br /&gt;    kms: &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;br /&gt;    gcp_kms: &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;br /&gt;    azure_kv: &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;br /&gt;    hc_vault: &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;br /&gt;    age:&lt;br /&gt;        - recipient: age1uprm5p9crdz7xn3ra9kfwv2axyg6re0jgn6tknf9tmsrn7dm2u3qktlpgx&lt;br /&gt;          enc: &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt;&lt;br /&gt;            -----BEGIN AGE ENCRYPTED FILE-----&lt;br /&gt;            YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBSWDJITGhjQjM4YnRCQUk1&lt;br /&gt;            ----------------------------REDACTED----------------------------&lt;br /&gt;            +XUzewHq1uEa6yvEIu12gu7sLg5yfx93UF44GUDpG8VKWt0vqTuTXA&lt;span class=&quot;token operator&quot;&gt;==&lt;/span&gt;&lt;br /&gt;            -----END AGE ENCRYPTED FILE-----&lt;br /&gt;    lastmodified: &lt;span class=&quot;token string&quot;&gt;&quot;2025-05-01T00:19:39Z&quot;&lt;/span&gt;&lt;br /&gt;    mac: ENC&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;AES256_GCM,data:gFugdPOc/nyLTb8nIo4VjYcYbJSePw2zPXmn1uo5yMGhMQ3y0spwBg9jlCl/lbVzCIVeWJ2aoMI9DAGFglHTTPjNOhyJ9UOBk+Eyh3NpgF+/J9wP8oZXTrIOaNZP+L7BAZnHNgN1CR1obvckBXeta2Eei3ozWptrrs4wy0CXgfQ&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;,iv:9szMfPuxvt44jtT11cY8IM19DxgVMDHuKsq+tM4D+Y8&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;,tag:9RzRy2l3NJCQodprE9spmA&lt;span class=&quot;token operator&quot;&gt;==&lt;/span&gt;,type:str&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;br /&gt;    pgp: &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;br /&gt;    encrypted_regex: ^&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;data&lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt;stringData&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;$&lt;br /&gt;    version: &lt;span class=&quot;token number&quot;&gt;3.9&lt;/span&gt;.4&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Go ahead and commit your changes and watch flux as it works on the commit.&lt;/p&gt;
&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;token function&quot;&gt;git&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;add&lt;/span&gt; &lt;span class=&quot;token parameter variable&quot;&gt;-A&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;git&lt;/span&gt; commit &lt;span class=&quot;token parameter variable&quot;&gt;-m&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Added cluster-config&quot;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token function&quot;&gt;git&lt;/span&gt; push&lt;br /&gt;&lt;br /&gt;flux events &lt;span class=&quot;token parameter variable&quot;&gt;--watch&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;Verify cluster-config&lt;/h2&gt;
&lt;p&gt;If all goes well, you should be able to dump the cluster-config confimap using kubectl and see the decrypted variables in the data field:&lt;/p&gt;
&lt;pre class=&quot;language-json&quot;&gt;&lt;code class=&quot;language-json&quot;&gt;$ kubectl get configmaps -n flux-system cluster-config -o json&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token property&quot;&gt;&quot;apiVersion&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;v1&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token property&quot;&gt;&quot;data&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token property&quot;&gt;&quot;test&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Value&quot;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token property&quot;&gt;&quot;kind&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;ConfigMap&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token property&quot;&gt;&quot;metadata&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token property&quot;&gt;&quot;creationTimestamp&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;2025-04-28T23:53:14Z&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token property&quot;&gt;&quot;labels&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;            &lt;span class=&quot;token property&quot;&gt;&quot;kustomize.toolkit.fluxcd.io/name&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;kubernetes&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;            &lt;span class=&quot;token property&quot;&gt;&quot;kustomize.toolkit.fluxcd.io/namespace&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;flux-system&quot;&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token property&quot;&gt;&quot;managedFields&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;br /&gt;            &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;                &lt;span class=&quot;token property&quot;&gt;&quot;apiVersion&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;v1&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;                &lt;span class=&quot;token property&quot;&gt;&quot;fieldsType&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;FieldsV1&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;                &lt;span class=&quot;token property&quot;&gt;&quot;fieldsV1&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;                    &lt;span class=&quot;token property&quot;&gt;&quot;f:data&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;                        &lt;span class=&quot;token property&quot;&gt;&quot;f:test&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;                    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;                    &lt;span class=&quot;token property&quot;&gt;&quot;f:metadata&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;                        &lt;span class=&quot;token property&quot;&gt;&quot;f:labels&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;                            &lt;span class=&quot;token property&quot;&gt;&quot;f:kustomize.toolkit.fluxcd.io/name&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;                            &lt;span class=&quot;token property&quot;&gt;&quot;f:kustomize.toolkit.fluxcd.io/namespace&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;                        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;                    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;                &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;                &lt;span class=&quot;token property&quot;&gt;&quot;manager&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;kustomize-controller&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;                &lt;span class=&quot;token property&quot;&gt;&quot;operation&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Apply&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;                &lt;span class=&quot;token property&quot;&gt;&quot;time&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;2025-04-28T23:53:14Z&quot;&lt;/span&gt;&lt;br /&gt;            &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token property&quot;&gt;&quot;name&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;cluster-config&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token property&quot;&gt;&quot;namespace&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;flux-system&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token property&quot;&gt;&quot;resourceVersion&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;834225&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token property&quot;&gt;&quot;uid&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;3d7344d0-8960-4c77-acc2-0abc52da29be&quot;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;Configuring Substitution&lt;/h2&gt;
&lt;p&gt;We now have an encrypted ConfigMap that we can use to securely store secrets in our cluster. To utilize these secrets we need to configure the post build substitution on any kustomizations that we want to reference these values in. Making sure to apply substitution to every single kustomization would be tedious, but lucky for us, we have structured our flux repo in such a way that makes our lives easier. We can apply ‘patches’ to higher level kustomizations that will apply changes to other kustomizations applied further down the hierarchy. In our case, we can apply patches to the clusters/truek8s/apps.yaml and clusters/truek8s/infrastructure.yaml kustomizations, and all other resources will automatically inherit our substitution configuration. This is one of the reasons it’s so important to consider how you’ll structure your repository.&lt;/p&gt;
&lt;p&gt;Go ahead and add the following patch definition to the apps and infrastructure kustomizations. I’ll provide apps as an example, but the content is exactly the same for both (or any other kustomizations you wish to apply it to in your own cluster).&lt;/p&gt;
&lt;pre class=&quot;language-yaml&quot;&gt;&lt;code class=&quot;language-yaml&quot;&gt;&lt;span class=&quot;token key atrule&quot;&gt;apiVersion&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; kustomize.toolkit.fluxcd.io/v1&lt;br /&gt;&lt;span class=&quot;token key atrule&quot;&gt;kind&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; Kustomization&lt;br /&gt;&lt;span class=&quot;token key atrule&quot;&gt;metadata&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token key atrule&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; apps&lt;br /&gt;  &lt;span class=&quot;token key atrule&quot;&gt;namespace&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; flux&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;system&lt;br /&gt;&lt;span class=&quot;token key atrule&quot;&gt;spec&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token key atrule&quot;&gt;interval&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; 10m&lt;br /&gt;  &lt;span class=&quot;token key atrule&quot;&gt;retryInterval&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; 1m&lt;br /&gt;  &lt;span class=&quot;token key atrule&quot;&gt;timeout&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; 5m&lt;br /&gt;  &lt;span class=&quot;token key atrule&quot;&gt;sourceRef&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token key atrule&quot;&gt;kind&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; GitRepository&lt;br /&gt;    &lt;span class=&quot;token key atrule&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; flux&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;system&lt;br /&gt;  &lt;span class=&quot;token key atrule&quot;&gt;path&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; ./apps/production&lt;br /&gt;  &lt;span class=&quot;token key atrule&quot;&gt;prune&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean important&quot;&gt;true&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token key atrule&quot;&gt;wait&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean important&quot;&gt;true&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token key atrule&quot;&gt;patches&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;      &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token key atrule&quot;&gt;patch&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;&lt;br /&gt;          &lt;span class=&quot;token key atrule&quot;&gt;apiVersion&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; kustomize.toolkit.fluxcd.io/v1&lt;br /&gt;          &lt;span class=&quot;token key atrule&quot;&gt;kind&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; Kustomization&lt;br /&gt;          &lt;span class=&quot;token key atrule&quot;&gt;metadata&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;            &lt;span class=&quot;token key atrule&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; not&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;used&lt;br /&gt;          &lt;span class=&quot;token key atrule&quot;&gt;spec&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;            &lt;span class=&quot;token key atrule&quot;&gt;decryption&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;              &lt;span class=&quot;token key atrule&quot;&gt;provider&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; sops&lt;br /&gt;              &lt;span class=&quot;token key atrule&quot;&gt;secretRef&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;                &lt;span class=&quot;token key atrule&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; sops&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;age&lt;br /&gt;            &lt;span class=&quot;token key atrule&quot;&gt;postBuild&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;              &lt;span class=&quot;token key atrule&quot;&gt;substituteFrom&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;                &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token key atrule&quot;&gt;kind&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; ConfigMap&lt;br /&gt;                  &lt;span class=&quot;token key atrule&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; cluster&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;config&lt;br /&gt;        &lt;span class=&quot;token key atrule&quot;&gt;target&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;          &lt;span class=&quot;token key atrule&quot;&gt;group&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; kustomize.toolkit.fluxcd.io&lt;br /&gt;          &lt;span class=&quot;token key atrule&quot;&gt;kind&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; Kustomization&lt;br /&gt;          &lt;span class=&quot;token key atrule&quot;&gt;labelSelector&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; substitution.flux.home.arpa/disabled notin (true)&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;It’s that easy! Don’t forget to commit your changes.&lt;/p&gt;
&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;token function&quot;&gt;git&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;add&lt;/span&gt; &lt;span class=&quot;token parameter variable&quot;&gt;-A&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;git&lt;/span&gt; commit &lt;span class=&quot;token parameter variable&quot;&gt;-m&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;patched apps and infrastructure&quot;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token function&quot;&gt;git&lt;/span&gt; push&lt;br /&gt;&lt;br /&gt;flux events &lt;span class=&quot;token parameter variable&quot;&gt;--watch&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;Testing Variable Substitution.&lt;/h2&gt;
&lt;p&gt;We can verify everything is working together by testing out substitution in a helm release. In the last part of the series we deployed podinfo, and that will be the perfect app to test substitution on. Edit the /apps/general/podinfo/podinfo.yaml file, adding a reference to the value we created in our ConfigMap:&lt;/p&gt;
&lt;pre class=&quot;language-yaml&quot;&gt;&lt;code class=&quot;language-yaml&quot;&gt;&lt;span class=&quot;token key atrule&quot;&gt;apiVersion&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; helm.toolkit.fluxcd.io/v2&lt;br /&gt;&lt;span class=&quot;token key atrule&quot;&gt;kind&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; HelmRelease&lt;br /&gt;&lt;span class=&quot;token key atrule&quot;&gt;metadata&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token key atrule&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; podinfo&lt;br /&gt;  &lt;span class=&quot;token key atrule&quot;&gt;namespace&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; podinfo&lt;br /&gt;&lt;span class=&quot;token key atrule&quot;&gt;spec&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token key atrule&quot;&gt;interval&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; 10m&lt;br /&gt;  &lt;span class=&quot;token key atrule&quot;&gt;timeout&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; 5m&lt;br /&gt;  &lt;span class=&quot;token key atrule&quot;&gt;chart&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token key atrule&quot;&gt;spec&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;      &lt;span class=&quot;token key atrule&quot;&gt;chart&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; podinfo&lt;br /&gt;      &lt;span class=&quot;token key atrule&quot;&gt;sourceRef&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token key atrule&quot;&gt;kind&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; HelmRepository&lt;br /&gt;        &lt;span class=&quot;token key atrule&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; podinfo&lt;br /&gt;        &lt;span class=&quot;token key atrule&quot;&gt;namespace&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; flux&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;system&lt;br /&gt;      &lt;span class=&quot;token key atrule&quot;&gt;interval&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; 5m&lt;br /&gt;  &lt;span class=&quot;token key atrule&quot;&gt;releaseName&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; podinfo&lt;br /&gt;  &lt;span class=&quot;token key atrule&quot;&gt;values&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token key atrule&quot;&gt;extraEnvs&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;      &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token key atrule&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; MULTIPLE_VALUES&lt;br /&gt;        &lt;span class=&quot;token key atrule&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; $&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;test&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Commit your changes, and wait for the podinfo helm release to reconcile. Now check the chart values with helm and observe whether or not the test variable was substituted. It should have been replaced with ‘Value’&lt;/p&gt;
&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;$ helm get values &lt;span class=&quot;token parameter variable&quot;&gt;-n&lt;/span&gt; podinfo podinfo&lt;br /&gt;&lt;span class=&quot;token environment constant&quot;&gt;USER&lt;/span&gt;-SUPPLIED VALUES:&lt;br /&gt;extraEnvs:&lt;br /&gt;- name: MULTIPLE_VALUES&lt;br /&gt;  value: Value&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;Sources&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://major.io/p/encrypted-gitops-secrets-with-flux-and-age/&quot;&gt;major.io: Encrypted gitops secrets with flux and age&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://fluxcd.io/flux/guides/mozilla-sops/&quot;&gt;fluxcd.io: Manage Kubernetes secrets with SOPS&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://fluxcd.io/flux/components/kustomize/kustomizations/#post-build-variable-substitution&quot;&gt;fluxcd.io: Post build variable substitution&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://fluxcd.io/flux/faq/#are-there-two-kustomization-types&quot;&gt;fluxcd.io: Kustomize questions&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/getsops/sops/releases&quot;&gt;github.org: sops&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/FiloSottile/age#installation&quot;&gt;github.org: age&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
</content>
    </entry>
    
    <entry>
      <title>TrueK8S Part 04</title>
      <link href="http://localhost:8080/2025/05/15/truek8s-part-04/"/>
      <updated>2025-05-15T12:30:00Z</updated>
      <id>http://localhost:8080/2025/05/15/truek8s-part-04/</id>
      <content type="html">&lt;h1&gt;Certificate management with TrueCharts ClusterIssuer&lt;/h1&gt;
&lt;p&gt;In this addition to the series, we’ll finally deploy a chart from the TrueCharts project. We’re still working on configuring the essential services that our cluster will depend on. One of those essential services is ingress, but before we can set that up we need to talk about certificates.&lt;/p&gt;
&lt;p&gt;Certificates help make HTTPS happen, and help get rid of those annoying ‘your connection is not secure’ errors you see in your browser. If you’re building a kube cluster, you probably knew that. What you may not know is that TrueCharts has a handy tool named ClusterIssuer that will let deployments in your cluster automagically fetch and manage their own certificates.&lt;/p&gt;
&lt;p&gt;All you need to take advantage of this tool is a public domain, and an API key to one of the supported DNS Providers. In this guide we’ll deploy the cert-manager and ClusterIssuer helm charts, and configure them to work with our Cloudflare account.&lt;/p&gt;
&lt;h2&gt;Cloudflare integration&lt;/h2&gt;
&lt;p&gt;Our new certificates will be issued by Let’s Encrypt, which utilizes ACME (Automatic Certificate Management Environment) to prove ownership of a domain. We’ll give cert-manager an API key for our Cloudflare account, which will allow it to publish records in our domain to satisfy the ACME challenge and retrieve certificates automatically.&lt;/p&gt;
&lt;p&gt;Head on over to the &lt;a href=&quot;https://dash.cloudflare.com/profile/api-tokens&quot;&gt;Cloudflare API Tokens&lt;/a&gt; page and get yourself a new API token.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;From the available templates, select &lt;strong&gt;Edit zone DNS&lt;/strong&gt;&lt;br /&gt;
&lt;img src=&quot;http://localhost:8080/assets/images/2025/05/cf-new-token-template.png&quot; alt=&quot;image&quot; /&gt;&lt;/li&gt;
&lt;li&gt;Give your new token a descriptive name, and grant the following permissions:
&lt;ul&gt;
&lt;li&gt;Zone - DNS - Edit&lt;/li&gt;
&lt;li&gt;Zone - Zone - Read&lt;/li&gt;
&lt;li&gt;Zone Resources - All zones (or all zones for which you wish to issue certificates)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;img src=&quot;http://localhost:8080/assets/images/2025/05/cf-new-token-permissions.png&quot; alt=&quot;image&quot; /&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Review the summary and create the token&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;img src=&quot;http://localhost:8080/assets/images/2025/05/cf-new-token-summary.png&quot; alt=&quot;image&quot; /&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Make sure to save your API token securely, you won’t get to see it again.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;img src=&quot;http://localhost:8080/assets/images/2025/05/cf-new-token-token.png&quot; alt=&quot;image&quot; /&gt;&lt;/p&gt;
&lt;p&gt;And now we have a secret that we need to give to our cluster. Sounds like a good use of our cluster-config ConfigMap we created earlier.&lt;/p&gt;
&lt;p&gt;Decrypt your ConfigMap&lt;/p&gt;
&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;token variable&quot;&gt;$sops&lt;/span&gt; &lt;span class=&quot;token parameter variable&quot;&gt;-d&lt;/span&gt; &lt;span class=&quot;token parameter variable&quot;&gt;-i&lt;/span&gt; cluster-config.yaml &lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;and add your token, as well as the email address associated with your Cloudflare account, and the domain name you’d like to use.&lt;/p&gt;
&lt;pre class=&quot;language-yaml&quot;&gt;&lt;code class=&quot;language-yaml&quot;&gt;&lt;span class=&quot;token key atrule&quot;&gt;apiVersion&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; v1&lt;br /&gt;&lt;span class=&quot;token key atrule&quot;&gt;kind&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; ConfigMap&lt;br /&gt;&lt;span class=&quot;token key atrule&quot;&gt;metadata&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token key atrule&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; cluster&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;config&lt;br /&gt;    &lt;span class=&quot;token key atrule&quot;&gt;namespace&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; flux&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;system&lt;br /&gt;&lt;span class=&quot;token key atrule&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token key atrule&quot;&gt;test&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; Value&lt;br /&gt;    &lt;span class=&quot;token key atrule&quot;&gt;DOMAIN_0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; mydomain.tld&lt;br /&gt;    &lt;span class=&quot;token key atrule&quot;&gt;CLOUDFLARE_TOKEN&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; token&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;token&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;token&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;token&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;token&lt;br /&gt;    &lt;span class=&quot;token key atrule&quot;&gt;CLOUDFLARE_EMAIL&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; email&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;email&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;email@domain&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;domain&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;domain.tld&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;And zip your clusterconfig file back up before committing the changes to your repo.&lt;/p&gt;
&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;token variable&quot;&gt;$sops&lt;/span&gt; &lt;span class=&quot;token parameter variable&quot;&gt;-e&lt;/span&gt; &lt;span class=&quot;token parameter variable&quot;&gt;-i&lt;/span&gt; cluster-config.yaml &lt;br /&gt;&lt;span class=&quot;token variable&quot;&gt;$git&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;add&lt;/span&gt; &lt;span class=&quot;token parameter variable&quot;&gt;-A&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;git&lt;/span&gt; commit &lt;span class=&quot;token parameter variable&quot;&gt;-m&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;added ACME info to cluster-config&#39;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token variable&quot;&gt;$git&lt;/span&gt; push&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Now we have everything we need to start getting some certs.&lt;/p&gt;
&lt;h2&gt;Deploying cert-manager and ClusterIssuer&lt;/h2&gt;
&lt;p&gt;cert-manager is the tool that actually does the ACME challenges for us, and cluster-issuer is the tool that takes cert requests from our cluster and hands them to cert-manager to fulfil. We’ll be deploying both.&lt;/p&gt;
&lt;p&gt;Add these resources to your cluster repo:&lt;/p&gt;
&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;truek8s&lt;br /&gt;├── infrastructure&lt;br /&gt;│ ├── core&lt;br /&gt;│ │ ├── cert-manager&lt;br /&gt;│ │ │ ├── helm-release.yaml&lt;br /&gt;│ │ │ ├── kustomization.yaml&lt;br /&gt;│ │ │ └── namespace.yaml&lt;br /&gt;│ │ ├── cluster-issuer&lt;br /&gt;│ │ │ ├── helm-release.yaml&lt;br /&gt;│ │ │ ├── kustomization.yaml&lt;br /&gt;│ │ │ └── namespace.yaml&lt;br /&gt;│ └── production&lt;br /&gt;│     ├── cert-manager.yaml&lt;br /&gt;│     └── cluster-issuer.yaml&lt;br /&gt;└── repos&lt;br /&gt;    ├── jetstack.yaml&lt;br /&gt;    └── truecharts.yaml&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;Repos&lt;/h3&gt;
&lt;h4&gt;jetstack.yaml&lt;/h4&gt;
&lt;pre class=&quot;language-yaml&quot;&gt;&lt;code class=&quot;language-yaml&quot;&gt;&lt;span class=&quot;token key atrule&quot;&gt;apiVersion&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; source.toolkit.fluxcd.io/v1&lt;br /&gt;&lt;span class=&quot;token key atrule&quot;&gt;kind&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; HelmRepository&lt;br /&gt;&lt;span class=&quot;token key atrule&quot;&gt;metadata&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token key atrule&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; jetstack&lt;br /&gt;  &lt;span class=&quot;token key atrule&quot;&gt;namespace&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; flux&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;system&lt;br /&gt;&lt;span class=&quot;token key atrule&quot;&gt;spec&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token key atrule&quot;&gt;interval&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; 2h&lt;br /&gt;  &lt;span class=&quot;token key atrule&quot;&gt;url&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; https&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;//charts.jetstack.io/&lt;/code&gt;&lt;/pre&gt;
&lt;h4&gt;truecharts.yaml&lt;/h4&gt;
&lt;pre class=&quot;language-yaml&quot;&gt;&lt;code class=&quot;language-yaml&quot;&gt;&lt;span class=&quot;token key atrule&quot;&gt;apiVersion&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; source.toolkit.fluxcd.io/v1&lt;br /&gt;&lt;span class=&quot;token key atrule&quot;&gt;kind&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; HelmRepository&lt;br /&gt;&lt;span class=&quot;token key atrule&quot;&gt;metadata&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token key atrule&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; truecharts&lt;br /&gt;    &lt;span class=&quot;token key atrule&quot;&gt;namespace&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; flux&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;system&lt;br /&gt;&lt;span class=&quot;token key atrule&quot;&gt;spec&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token key atrule&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; oci&lt;br /&gt;    &lt;span class=&quot;token key atrule&quot;&gt;interval&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; 2h&lt;br /&gt;    &lt;span class=&quot;token key atrule&quot;&gt;url&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; oci&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;//tccr.io/truecharts&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;infrastructure/core/cert-manager&lt;/h3&gt;
&lt;h4&gt;helm-release.yaml&lt;/h4&gt;
&lt;pre class=&quot;language-yaml&quot;&gt;&lt;code class=&quot;language-yaml&quot;&gt;&lt;span class=&quot;token key atrule&quot;&gt;apiVersion&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; helm.toolkit.fluxcd.io/v2&lt;br /&gt;&lt;span class=&quot;token key atrule&quot;&gt;kind&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; HelmRelease&lt;br /&gt;&lt;span class=&quot;token key atrule&quot;&gt;metadata&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token key atrule&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; cert&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;manager&lt;br /&gt;    &lt;span class=&quot;token key atrule&quot;&gt;namespace&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; cert&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;manager&lt;br /&gt;&lt;span class=&quot;token key atrule&quot;&gt;spec&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token key atrule&quot;&gt;interval&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; 5m&lt;br /&gt;    &lt;span class=&quot;token key atrule&quot;&gt;chart&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token key atrule&quot;&gt;spec&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;            &lt;span class=&quot;token key atrule&quot;&gt;chart&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; cert&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;manager&lt;br /&gt;            &lt;span class=&quot;token key atrule&quot;&gt;sourceRef&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;                &lt;span class=&quot;token key atrule&quot;&gt;kind&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; HelmRepository&lt;br /&gt;                &lt;span class=&quot;token key atrule&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; jetstack&lt;br /&gt;                &lt;span class=&quot;token key atrule&quot;&gt;namespace&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; flux&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;system&lt;br /&gt;            &lt;span class=&quot;token key atrule&quot;&gt;interval&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; 5m&lt;br /&gt;    &lt;span class=&quot;token key atrule&quot;&gt;install&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token key atrule&quot;&gt;createNamespace&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean important&quot;&gt;true&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token key atrule&quot;&gt;crds&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; CreateReplace&lt;br /&gt;        &lt;span class=&quot;token key atrule&quot;&gt;remediation&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;            &lt;span class=&quot;token key atrule&quot;&gt;retries&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;3&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token key atrule&quot;&gt;upgrade&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token key atrule&quot;&gt;crds&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; CreateReplace&lt;br /&gt;        &lt;span class=&quot;token key atrule&quot;&gt;remediation&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;            &lt;span class=&quot;token key atrule&quot;&gt;retries&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;3&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token key atrule&quot;&gt;values&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;      &lt;span class=&quot;token key atrule&quot;&gt;crds&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token key atrule&quot;&gt;enabled&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean important&quot;&gt;true&lt;/span&gt;&lt;br /&gt;      &lt;span class=&quot;token key atrule&quot;&gt;dns01RecursiveNameservers&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;1.1.1.1:53,1.0.0.1:53&quot;&lt;/span&gt;&lt;br /&gt;      &lt;span class=&quot;token key atrule&quot;&gt;dns01RecursiveNameserversOnly&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean important&quot;&gt;false&lt;/span&gt;&lt;br /&gt;      &lt;span class=&quot;token key atrule&quot;&gt;enableCertificateOwnerRef&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean important&quot;&gt;true&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h4&gt;kustomization.yaml&lt;/h4&gt;
&lt;pre class=&quot;language-yaml&quot;&gt;&lt;code class=&quot;language-yaml&quot;&gt;&lt;span class=&quot;token key atrule&quot;&gt;apiVersion&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; kustomize.config.k8s.io/v1beta1&lt;br /&gt;&lt;span class=&quot;token key atrule&quot;&gt;kind&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; Kustomization&lt;br /&gt;&lt;span class=&quot;token key atrule&quot;&gt;resources&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; namespace.yaml&lt;br /&gt;  &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; helm&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;release.yaml&lt;/code&gt;&lt;/pre&gt;
&lt;h4&gt;/namespace.yaml&lt;/h4&gt;
&lt;pre class=&quot;language-yaml&quot;&gt;&lt;code class=&quot;language-yaml&quot;&gt;&lt;span class=&quot;token key atrule&quot;&gt;apiVersion&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; v1&lt;br /&gt;&lt;span class=&quot;token key atrule&quot;&gt;kind&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; Namespace&lt;br /&gt;&lt;span class=&quot;token key atrule&quot;&gt;metadata&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token key atrule&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; cert&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;manager&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;infrastructure/core/cluster-issuer&lt;/h2&gt;
&lt;h4&gt;helm-release.yaml&lt;/h4&gt;
&lt;p&gt;🚧 See how we’re passing the secrets from our ConfigMap here? Also, pay attention to spec.values.clusterCertificates. This will create a default wildcard certificate that we’ll need later!&lt;/p&gt;
&lt;pre class=&quot;language-yaml&quot;&gt;&lt;code class=&quot;language-yaml&quot;&gt;&lt;span class=&quot;token key atrule&quot;&gt;apiVersion&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; helm.toolkit.fluxcd.io/v2&lt;br /&gt;&lt;span class=&quot;token key atrule&quot;&gt;kind&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; HelmRelease&lt;br /&gt;&lt;span class=&quot;token key atrule&quot;&gt;metadata&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token key atrule&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; clusterissuer&lt;br /&gt;  &lt;span class=&quot;token key atrule&quot;&gt;namespace&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; clusterissuer&lt;br /&gt;&lt;span class=&quot;token key atrule&quot;&gt;spec&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token key atrule&quot;&gt;interval&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; 15m&lt;br /&gt;  &lt;span class=&quot;token key atrule&quot;&gt;chart&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token key atrule&quot;&gt;spec&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;      &lt;span class=&quot;token key atrule&quot;&gt;chart&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; clusterissuer&lt;br /&gt;      &lt;span class=&quot;token key atrule&quot;&gt;sourceRef&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token key atrule&quot;&gt;kind&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; HelmRepository&lt;br /&gt;        &lt;span class=&quot;token key atrule&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; truecharts&lt;br /&gt;        &lt;span class=&quot;token key atrule&quot;&gt;namespace&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; flux&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;system&lt;br /&gt;      &lt;span class=&quot;token key atrule&quot;&gt;interval&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; 15m&lt;br /&gt;  &lt;span class=&quot;token key atrule&quot;&gt;timeout&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; 20m&lt;br /&gt;  &lt;span class=&quot;token key atrule&quot;&gt;maxHistory&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;3&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token key atrule&quot;&gt;install&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token key atrule&quot;&gt;createNamespace&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean important&quot;&gt;true&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token key atrule&quot;&gt;remediation&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;      &lt;span class=&quot;token key atrule&quot;&gt;retries&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;3&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token key atrule&quot;&gt;upgrade&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token key atrule&quot;&gt;cleanupOnFail&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean important&quot;&gt;true&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token key atrule&quot;&gt;remediation&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;      &lt;span class=&quot;token key atrule&quot;&gt;retries&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;3&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token key atrule&quot;&gt;uninstall&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token key atrule&quot;&gt;keepHistory&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean important&quot;&gt;false&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token key atrule&quot;&gt;values&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token key atrule&quot;&gt;clusterIssuer&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;      &lt;span class=&quot;token key atrule&quot;&gt;selfSigned&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token key atrule&quot;&gt;enabled&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean important&quot;&gt;true&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token key atrule&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;selfsigned&quot;&lt;/span&gt;&lt;br /&gt;      &lt;span class=&quot;token comment&quot;&gt;## Remove these if you do NOT want to use clusterissuer&lt;/span&gt;&lt;br /&gt;      &lt;span class=&quot;token key atrule&quot;&gt;ACME&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token key atrule&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; letsencrypt&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;domain&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;br /&gt;          &lt;span class=&quot;token comment&quot;&gt;# Used for both logging in to the DNS provider AND ACME registration&lt;/span&gt;&lt;br /&gt;          &lt;span class=&quot;token key atrule&quot;&gt;email&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;${CLOUDFLARE_EMAIL}&quot;&lt;/span&gt;&lt;br /&gt;          &lt;span class=&quot;token key atrule&quot;&gt;server&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;https://acme-v02.api.letsencrypt.org/directory&#39;&lt;/span&gt;&lt;br /&gt;          &lt;span class=&quot;token comment&quot;&gt;# Options: HTTP01, cloudflare, route53, akamai, digitalocean, rfc2136, acmedns&lt;/span&gt;&lt;br /&gt;          &lt;span class=&quot;token key atrule&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;cloudflare&quot;&lt;/span&gt;&lt;br /&gt;          &lt;span class=&quot;token comment&quot;&gt;# for cloudflare&lt;/span&gt;&lt;br /&gt;          &lt;span class=&quot;token key atrule&quot;&gt;cfapitoken&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;${CLOUDFLARE_TOKEN}&quot;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token comment&quot;&gt;## Remove these if you do NOT want to use clusterissuer&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token key atrule&quot;&gt;clusterCertificates&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;      &lt;span class=&quot;token comment&quot;&gt;# Namespaces in which the certificates must be available&lt;/span&gt;&lt;br /&gt;      &lt;span class=&quot;token comment&quot;&gt;# Accepts comma-separated regex expressions&lt;/span&gt;&lt;br /&gt;      &lt;span class=&quot;token key atrule&quot;&gt;replicationNamespaces&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;.*&#39;&lt;/span&gt;&lt;br /&gt;      &lt;span class=&quot;token key atrule&quot;&gt;certificates&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token key atrule&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; star&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;domain&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;br /&gt;          &lt;span class=&quot;token key atrule&quot;&gt;enabled&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean important&quot;&gt;true&lt;/span&gt;&lt;br /&gt;          &lt;span class=&quot;token key atrule&quot;&gt;certificateIssuer&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; letsencrypt&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;domain&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;br /&gt;          &lt;span class=&quot;token key atrule&quot;&gt;hosts&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;            &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; $&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;DOMAIN_0&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;            &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;*.${DOMAIN_0}&#39;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h4&gt;kustomization.yaml&lt;/h4&gt;
&lt;pre class=&quot;language-yaml&quot;&gt;&lt;code class=&quot;language-yaml&quot;&gt;&lt;span class=&quot;token key atrule&quot;&gt;apiVersion&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; kustomize.config.k8s.io/v1beta1&lt;br /&gt;&lt;span class=&quot;token key atrule&quot;&gt;kind&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; Kustomization&lt;br /&gt;&lt;span class=&quot;token key atrule&quot;&gt;resources&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; namespace.yaml&lt;br /&gt;  &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; helm&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;release.yaml&lt;/code&gt;&lt;/pre&gt;
&lt;h4&gt;namespace.yaml&lt;/h4&gt;
&lt;pre class=&quot;language-yaml&quot;&gt;&lt;code class=&quot;language-yaml&quot;&gt;&lt;span class=&quot;token key atrule&quot;&gt;apiVersion&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; v1&lt;br /&gt;&lt;span class=&quot;token key atrule&quot;&gt;kind&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; Namespace&lt;br /&gt;&lt;span class=&quot;token key atrule&quot;&gt;metadata&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token key atrule&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; clusterissuer&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;/infrastructure/production/&lt;/h3&gt;
&lt;h4&gt;cert-manager.yaml&lt;/h4&gt;
&lt;pre class=&quot;language-yaml&quot;&gt;&lt;code class=&quot;language-yaml&quot;&gt;&lt;span class=&quot;token key atrule&quot;&gt;apiVersion&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; kustomize.toolkit.fluxcd.io/v1&lt;br /&gt;&lt;span class=&quot;token key atrule&quot;&gt;kind&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; Kustomization&lt;br /&gt;&lt;span class=&quot;token key atrule&quot;&gt;metadata&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token key atrule&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; cert&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;manager&lt;br /&gt;  &lt;span class=&quot;token key atrule&quot;&gt;namespace&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; flux&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;system&lt;br /&gt;&lt;span class=&quot;token key atrule&quot;&gt;spec&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token key atrule&quot;&gt;interval&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; 10m&lt;br /&gt;  &lt;span class=&quot;token key atrule&quot;&gt;path&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; infrastructure/core/cert&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;manager&lt;br /&gt;  &lt;span class=&quot;token key atrule&quot;&gt;prune&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean important&quot;&gt;true&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token key atrule&quot;&gt;sourceRef&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token key atrule&quot;&gt;kind&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; GitRepository&lt;br /&gt;    &lt;span class=&quot;token key atrule&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; flux&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;system&lt;/code&gt;&lt;/pre&gt;
&lt;h4&gt;cluster-issuer.yaml&lt;/h4&gt;
&lt;p&gt;Note that cluster-issuer depends on cert-manager&lt;/p&gt;
&lt;pre class=&quot;language-yaml&quot;&gt;&lt;code class=&quot;language-yaml&quot;&gt;&lt;span class=&quot;token key atrule&quot;&gt;apiVersion&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; kustomize.toolkit.fluxcd.io/v1&lt;br /&gt;&lt;span class=&quot;token key atrule&quot;&gt;kind&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; Kustomization&lt;br /&gt;&lt;span class=&quot;token key atrule&quot;&gt;metadata&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token key atrule&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; cluster&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;issuer&lt;br /&gt;  &lt;span class=&quot;token key atrule&quot;&gt;namespace&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; flux&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;system&lt;br /&gt;&lt;span class=&quot;token key atrule&quot;&gt;spec&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token key atrule&quot;&gt;dependsOn&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token key atrule&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; cert&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;manager&lt;br /&gt;  &lt;span class=&quot;token key atrule&quot;&gt;interval&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; 10m&lt;br /&gt;  &lt;span class=&quot;token key atrule&quot;&gt;path&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; infrastructure/core/cluster&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;issuer&lt;br /&gt;  &lt;span class=&quot;token key atrule&quot;&gt;prune&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean important&quot;&gt;true&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token key atrule&quot;&gt;sourceRef&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token key atrule&quot;&gt;kind&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; GitRepository&lt;br /&gt;    &lt;span class=&quot;token key atrule&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; flux&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;system&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;And finally, don’t forget to modify existing kustomizations to point to the new kustomizations we’ve created.&lt;/p&gt;
&lt;h3&gt;/repos/kustomization.yaml&lt;/h3&gt;
&lt;pre class=&quot;language-yaml&quot;&gt;&lt;code class=&quot;language-yaml&quot;&gt;&lt;span class=&quot;token key atrule&quot;&gt;apiVersion&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; kustomize.config.k8s.io/v1beta1&lt;br /&gt;&lt;span class=&quot;token key atrule&quot;&gt;kind&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; Kustomization&lt;br /&gt;&lt;span class=&quot;token key atrule&quot;&gt;resources&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; cert&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;manager.yaml&lt;br /&gt;  &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; cluster&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;issuer.yaml&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;/infrastructure/production.yaml&lt;/h3&gt;
&lt;pre class=&quot;language-yaml&quot;&gt;&lt;code class=&quot;language-yaml&quot;&gt;&lt;span class=&quot;token key atrule&quot;&gt;apiVersion&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; kustomize.config.k8s.io/v1beta1&lt;br /&gt;&lt;span class=&quot;token key atrule&quot;&gt;kind&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; Kustomization&lt;br /&gt;&lt;span class=&quot;token key atrule&quot;&gt;resources&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; truecharts.yaml&lt;br /&gt;  &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; podinfo.yaml&lt;br /&gt;  &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; jetstack.yaml&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;That is a lot of junk to write (or copy paste), but that is my experience of flux. The payoff of deploying things this way is that we now have every part of our deployment declaratively defined, and independently documented. Every namespace and helm-chart is well defined, and any changes are tracked very accurately. Notice we’re also using the spec.dependsOn field to tell flux to wait until cert-manager is deployed to try and deploy ClusterIssuer.&lt;/p&gt;
&lt;p&gt;When you’re done complaining about all the files, commit your changes and watch Flux do its work.&lt;/p&gt;
&lt;p&gt;❗ Triple check that cluster-config has been re-encrypted before committing!&lt;/p&gt;
&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;token function&quot;&gt;git&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;add&lt;/span&gt; &lt;span class=&quot;token parameter variable&quot;&gt;-A&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;git&lt;/span&gt; commit &lt;span class=&quot;token parameter variable&quot;&gt;-m&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;added certs stuffs&#39;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token function&quot;&gt;git&lt;/span&gt; push&lt;br /&gt;flux events &lt;span class=&quot;token parameter variable&quot;&gt;--watch&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;Verifying&lt;/h2&gt;
&lt;p&gt;If everything worked correctly, we should have two new helm releases, and a cluster certificate. Let’s verify that with flux and kubectl.&lt;/p&gt;
&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;#Verify that the charts installed successfully.&lt;/span&gt;&lt;br /&gt;$ flux get hr &lt;span class=&quot;token parameter variable&quot;&gt;-A&lt;/span&gt;&lt;br /&gt;NAMESPACE       NAME            REVISION        SUSPENDED       READY   MESSAGE                                                                                             &lt;br /&gt;cert-manager    cert-manager    v1.17.2         False           True    Helm &lt;span class=&quot;token function&quot;&gt;install&lt;/span&gt; succeeded &lt;span class=&quot;token keyword&quot;&gt;for&lt;/span&gt; release cert-manager/cert-manager.v1 with chart cert-manager@v1.17.2    &lt;br /&gt;clusterissuer   clusterissuer   &lt;span class=&quot;token number&quot;&gt;9.6&lt;/span&gt;.4           False           True    Helm &lt;span class=&quot;token function&quot;&gt;install&lt;/span&gt; succeeded &lt;span class=&quot;token keyword&quot;&gt;for&lt;/span&gt; release clusterissuer/clusterissuer.v1 with chart clusterissuer@9.6.4                     &lt;br /&gt;podinfo         podinfo         &lt;span class=&quot;token number&quot;&gt;6.8&lt;/span&gt;.0           False           True    Helm upgrade succeeded &lt;span class=&quot;token keyword&quot;&gt;for&lt;/span&gt; release podinfo/podinfo.v4 with chart podinfo@6.8.0                     &lt;br /&gt;&lt;span class=&quot;token comment&quot;&gt;#Verify that the star-domain-0 certificate was created.&lt;/span&gt;&lt;br /&gt;$ kubectl get certificate &lt;span class=&quot;token parameter variable&quot;&gt;-A&lt;/span&gt;&lt;br /&gt;NAMESPACE       NAME                               READY   SECRET                             AGE&lt;br /&gt;clusterissuer   certificate-issuer-star-domain-0   False   certificate-issuer-star-domain-0   52s&lt;br /&gt;&lt;br /&gt;$ kubectl describe certificate &lt;span class=&quot;token parameter variable&quot;&gt;-n&lt;/span&gt; clusterissuer certificate-issuer-star-domain-0 &lt;br /&gt;Name:         certificate-issuer-star-domain-0&lt;br /&gt;Namespace:    clusterissuer&lt;br /&gt;Labels:       &lt;span class=&quot;token assign-left variable&quot;&gt;app&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;clusterissuer-9.6.4&lt;br /&gt;              app.kubernetes.io/instance&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;clusterissuer&lt;br /&gt;              app.kubernetes.io/managed-by&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;Helm&lt;br /&gt;              app.kubernetes.io/name&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;clusterissuer&lt;br /&gt;              app.kubernetes.io/version&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;latest&lt;br /&gt;              helm-revision&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;br /&gt;              helm.sh/chart&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;clusterissuer-9.6.4&lt;br /&gt;              helm.toolkit.fluxcd.io/name&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;clusterissuer&lt;br /&gt;              helm.toolkit.fluxcd.io/namespace&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;clusterissuer&lt;br /&gt;              &lt;span class=&quot;token assign-left variable&quot;&gt;release&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;clusterissuer&lt;br /&gt;Annotations:  meta.helm.sh/release-name: clusterissuer&lt;br /&gt;              meta.helm.sh/release-namespace: clusterissuer&lt;br /&gt;API Version:  cert-manager.io/v1&lt;br /&gt;Kind:         Certificate&lt;br /&gt;Metadata:&lt;br /&gt;  Creation Timestamp:  &lt;span class=&quot;token number&quot;&gt;2025&lt;/span&gt;-05-15T02:24:56Z&lt;br /&gt;  Generation:          &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;br /&gt;  Managed Fields:&lt;br /&gt;    API Version:  cert-manager.io/v1&lt;br /&gt;    Fields Type:  FieldsV1&lt;br /&gt;    fieldsV1:&lt;br /&gt;      f:status:&lt;br /&gt;        f:nextPrivateKeySecretName:&lt;br /&gt;    Manager:      cert-manager-certificates-key-manager&lt;br /&gt;    Operation:    Update&lt;br /&gt;    Subresource:  status&lt;br /&gt;    Time:         &lt;span class=&quot;token number&quot;&gt;2025&lt;/span&gt;-05-15T02:24:56Z&lt;br /&gt;    API Version:  cert-manager.io/v1&lt;br /&gt;    &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;..&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;..&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;br /&gt;Events:&lt;br /&gt;  Type    Reason     Age   From                                       Message&lt;br /&gt;  ----    ------     ----  ----                                       -------&lt;br /&gt;  Normal  Issuing    71s   cert-manager-certificates-trigger          Issuing certificate as Secret does not exist&lt;br /&gt;  Normal  Generated  71s   cert-manager-certificates-key-manager      Stored new private key &lt;span class=&quot;token keyword&quot;&gt;in&lt;/span&gt; temporary Secret resource &lt;span class=&quot;token string&quot;&gt;&quot;certificate-issuer-star-domain-0-zwn8g&quot;&lt;/span&gt;&lt;br /&gt;  Normal  Requested  71s   cert-manager-certificates-request-manager  Created new CertificateRequest resource &lt;span class=&quot;token string&quot;&gt;&quot;certificate-issuer-star-domain-0-1&quot;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;Next Steps&lt;/h2&gt;
&lt;p&gt;In Part 5, we’ll put that cert to use and configure ingress for our cluster.&lt;/p&gt;
&lt;h2&gt;Sources&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://truecharts.org/charts/premium/clusterissuer/how-to/&quot;&gt;truecharts.org: clusterissuer Setup Guide&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://cert-manager.io/docs/configuration/acme/&quot;&gt;cert-manager.io: ACME&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://cert-manager.io/docs/&quot;&gt;cert-manager.io: docs&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
</content>
    </entry>
    
    <entry>
      <title>TrueK8S Part 05</title>
      <link href="http://localhost:8080/2025/05/15/truek8s-part-05/"/>
      <updated>2025-05-15T12:30:00Z</updated>
      <id>http://localhost:8080/2025/05/15/truek8s-part-05/</id>
      <content type="html">&lt;h2&gt;Configuring Ingress for my Kubernetes Cluster&lt;/h2&gt;
&lt;p&gt;Do you remember in part 2 of this series where we used the kubectl command to manually port-forward to a service in our cluster? That sucked, right? Let’s not do that. Let’s deploy an ingress controller to handle the task of routing traffic for us.&lt;/p&gt;
&lt;p&gt;We’ll be configuring a few things here. First, MetalLB which provides kubernetes with access to REAL IPs on your network. Second, we’ll configure nginx which will be a proxy for application traffic.&lt;/p&gt;
&lt;h2&gt;MetalLB&lt;/h2&gt;
&lt;p&gt;MetalLB is a load balancer for bare (or virtualized?) metal kubernetes clusters. It allows kubernetes services to take a real IP from your clusters physical network. The first step here is to decide what IP or range of IPs we’ll configured MetalLB to use. IPs are not necessarily sensitive information depending who you ask, but we’ll put them in our secure configmap for safe storage anyway.&lt;/p&gt;
&lt;p&gt;We’ll also need to chose one IP from this range to assign to our ingress controller.&lt;/p&gt;
&lt;p&gt;In my case, I’m taking a range of IPs from my cluster’s local network. My nodes are 192.168.XX.101-112. I will assign the range ~.200-.250 for this use case. I will use the first address of that range for nginx.&lt;/p&gt;
&lt;p&gt;Go ahead and decrypt cluster-config.yaml&lt;/p&gt;
&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;$ sops &lt;span class=&quot;token parameter variable&quot;&gt;-d&lt;/span&gt; &lt;span class=&quot;token parameter variable&quot;&gt;-i&lt;/span&gt; cluster-config.yaml &lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;And add your MetalLB range and the IP you want assigned to NGINX like this:&lt;/p&gt;
&lt;pre class=&quot;language-yaml&quot;&gt;&lt;code class=&quot;language-yaml&quot;&gt;&lt;span class=&quot;token key atrule&quot;&gt;apiVersion&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; v1&lt;br /&gt;&lt;span class=&quot;token key atrule&quot;&gt;kind&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; ConfigMap&lt;br /&gt;&lt;span class=&quot;token key atrule&quot;&gt;metadata&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token key atrule&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; cluster&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;config&lt;br /&gt;    &lt;span class=&quot;token key atrule&quot;&gt;namespace&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; flux&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;system&lt;br /&gt;&lt;span class=&quot;token key atrule&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token key atrule&quot;&gt;test&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; Value&lt;br /&gt;    &lt;span class=&quot;token key atrule&quot;&gt;METALLB_RANGE&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; 192.168.XX.200&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;192.168.XX.250&lt;br /&gt;    &lt;span class=&quot;token key atrule&quot;&gt;NGINX_IP&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; 192.168.XX.200&lt;br /&gt;    &lt;span class=&quot;token key atrule&quot;&gt;DOMAIN_0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; mydomain.tld&lt;br /&gt;    &lt;span class=&quot;token key atrule&quot;&gt;CLOUDFLARE_TOKEN&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; token&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;token&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;token&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;token&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;token&lt;br /&gt;    &lt;span class=&quot;token key atrule&quot;&gt;CLOUDFLARE_EMAIL&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; email&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;email&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;email@domain&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;domain&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;domain.tld&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Now re-encrypt the file and commit the changes to your repo. It should also go without saying that you should always be sure to re-encrypt your config files before committing.&lt;/p&gt;
&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;$ sops &lt;span class=&quot;token parameter variable&quot;&gt;-e&lt;/span&gt; &lt;span class=&quot;token parameter variable&quot;&gt;-i&lt;/span&gt; cluster-config.yaml &lt;br /&gt;$ &lt;span class=&quot;token function&quot;&gt;git&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;add&lt;/span&gt; &lt;span class=&quot;token parameter variable&quot;&gt;-A&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;git&lt;/span&gt; commit &lt;span class=&quot;token parameter variable&quot;&gt;-m&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;add metallb range to cluster-config&#39;&lt;/span&gt;&lt;br /&gt;$ &lt;span class=&quot;token function&quot;&gt;git&lt;/span&gt; push&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Now we’re going to create the MetalLB deployment manifests. We’re actually going to create two sets of resources applied by separate kustomizations. The first kustomization will deploy MetalLB itself, and the second will deploy a MetalLB configuration. The configuration can only be applied after MetalLB is deployed, so we’ll use separate kustomizations with the dependsOn configuration to ensure they’re applied in the right order.&lt;/p&gt;
&lt;p&gt;Go ahead and create the following new directories and resources:&lt;/p&gt;
&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;infrastructure/&lt;br /&gt;├── core&lt;br /&gt;│ ├── metallb&lt;br /&gt;│ │   ├── helm-release.yaml&lt;br /&gt;│ │   ├── kustomization.yaml&lt;br /&gt;│ │   └── namespace.yaml&lt;br /&gt;│ └── metallb-config&lt;br /&gt;│     ├── helm-release.yaml&lt;br /&gt;│     ├── kustomization.yaml&lt;br /&gt;│     └── namespace.yaml&lt;br /&gt;└── production&lt;br /&gt;│ ├── kustomization.yaml&lt;br /&gt;│ ├── metallb-config.yaml&lt;br /&gt;│ └── metallb.yaml&lt;br /&gt;└── repos&lt;br /&gt;  └── metallb.yaml&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Where the values of each file are:&lt;/p&gt;
&lt;h3&gt;repos&lt;/h3&gt;
&lt;h4&gt;metallb.yaml&lt;/h4&gt;
&lt;pre class=&quot;language-yaml&quot;&gt;&lt;code class=&quot;language-yaml&quot;&gt;&lt;span class=&quot;token key atrule&quot;&gt;apiVersion&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; source.toolkit.fluxcd.io/v1&lt;br /&gt;&lt;span class=&quot;token key atrule&quot;&gt;kind&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; HelmRepository&lt;br /&gt;&lt;span class=&quot;token key atrule&quot;&gt;metadata&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token key atrule&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; metallb&lt;br /&gt;    &lt;span class=&quot;token key atrule&quot;&gt;namespace&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; flux&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;system&lt;br /&gt;&lt;span class=&quot;token key atrule&quot;&gt;spec&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token key atrule&quot;&gt;interval&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; 10m&lt;br /&gt;    &lt;span class=&quot;token key atrule&quot;&gt;url&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; https&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;//metallb.github.io/metallb&lt;br /&gt;    &lt;span class=&quot;token key atrule&quot;&gt;timeout&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; 3m&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;infrastructure/core/metallb&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;helm-release.yaml&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&quot;language-yaml&quot;&gt;&lt;code class=&quot;language-yaml&quot;&gt;&lt;span class=&quot;token key atrule&quot;&gt;apiVersion&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; helm.toolkit.fluxcd.io/v2&lt;br /&gt;&lt;span class=&quot;token key atrule&quot;&gt;kind&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; HelmRelease&lt;br /&gt;&lt;span class=&quot;token key atrule&quot;&gt;metadata&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token key atrule&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; metallb&lt;br /&gt;    &lt;span class=&quot;token key atrule&quot;&gt;namespace&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; metallb&lt;br /&gt;&lt;span class=&quot;token key atrule&quot;&gt;spec&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token key atrule&quot;&gt;interval&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; 5m&lt;br /&gt;    &lt;span class=&quot;token key atrule&quot;&gt;chart&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token key atrule&quot;&gt;spec&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;            &lt;span class=&quot;token key atrule&quot;&gt;chart&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; metallb&lt;br /&gt;            &lt;span class=&quot;token key atrule&quot;&gt;sourceRef&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;                &lt;span class=&quot;token key atrule&quot;&gt;kind&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; HelmRepository&lt;br /&gt;                &lt;span class=&quot;token key atrule&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; metallb&lt;br /&gt;                &lt;span class=&quot;token key atrule&quot;&gt;namespace&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; flux&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;system&lt;br /&gt;            &lt;span class=&quot;token key atrule&quot;&gt;interval&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; 5m&lt;br /&gt;    &lt;span class=&quot;token key atrule&quot;&gt;install&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token key atrule&quot;&gt;createNamespace&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean important&quot;&gt;true&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token key atrule&quot;&gt;remediation&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;            &lt;span class=&quot;token key atrule&quot;&gt;retries&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;3&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token key atrule&quot;&gt;upgrade&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token key atrule&quot;&gt;remediation&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;            &lt;span class=&quot;token key atrule&quot;&gt;retries&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;3&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token key atrule&quot;&gt;values&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;      &lt;span class=&quot;token key atrule&quot;&gt;speaker&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token key atrule&quot;&gt;ignoreExcludeLB&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean important&quot;&gt;true&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;namespace.yaml&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&quot;language-yaml&quot;&gt;&lt;code class=&quot;language-yaml&quot;&gt;&lt;span class=&quot;token key atrule&quot;&gt;apiVersion&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; v1&lt;br /&gt;&lt;span class=&quot;token key atrule&quot;&gt;kind&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; Namespace&lt;br /&gt;&lt;span class=&quot;token key atrule&quot;&gt;metadata&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token key atrule&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; metallb&lt;br /&gt;    &lt;span class=&quot;token key atrule&quot;&gt;labels&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token key atrule&quot;&gt;pod-security.kubernetes.io/enforce&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; privileged&lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;kustomization.yaml&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&quot;language-yaml&quot;&gt;&lt;code class=&quot;language-yaml&quot;&gt;&lt;span class=&quot;token key atrule&quot;&gt;apiVersion&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; kustomize.config.k8s.io/v1beta1&lt;br /&gt;&lt;span class=&quot;token key atrule&quot;&gt;kind&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; Kustomization&lt;br /&gt;&lt;span class=&quot;token key atrule&quot;&gt;resources&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; namespace.yaml&lt;br /&gt;  &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; helm&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;release.yaml&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;infrastructure/core/metallb-config&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;helm-release.yaml&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&quot;language-yaml&quot;&gt;&lt;code class=&quot;language-yaml&quot;&gt;&lt;span class=&quot;token key atrule&quot;&gt;apiVersion&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; helm.toolkit.fluxcd.io/v2&lt;br /&gt;&lt;span class=&quot;token key atrule&quot;&gt;kind&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; HelmRelease&lt;br /&gt;&lt;span class=&quot;token key atrule&quot;&gt;metadata&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token key atrule&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; metallb&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;config&lt;br /&gt;  &lt;span class=&quot;token key atrule&quot;&gt;namespace&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; metallb&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;config&lt;br /&gt;&lt;span class=&quot;token key atrule&quot;&gt;spec&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token key atrule&quot;&gt;interval&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; 15m&lt;br /&gt;  &lt;span class=&quot;token key atrule&quot;&gt;chart&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token key atrule&quot;&gt;spec&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;      &lt;span class=&quot;token key atrule&quot;&gt;chart&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; metallb&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;config&lt;br /&gt;      &lt;span class=&quot;token key atrule&quot;&gt;sourceRef&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token key atrule&quot;&gt;kind&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; HelmRepository&lt;br /&gt;        &lt;span class=&quot;token key atrule&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; truecharts&lt;br /&gt;        &lt;span class=&quot;token key atrule&quot;&gt;namespace&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; flux&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;system&lt;br /&gt;      &lt;span class=&quot;token key atrule&quot;&gt;interval&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; 15m&lt;br /&gt;  &lt;span class=&quot;token key atrule&quot;&gt;timeout&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; 20m&lt;br /&gt;  &lt;span class=&quot;token key atrule&quot;&gt;maxHistory&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;3&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token key atrule&quot;&gt;driftDetection&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token key atrule&quot;&gt;mode&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; warn&lt;br /&gt;  &lt;span class=&quot;token key atrule&quot;&gt;install&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token key atrule&quot;&gt;createNamespace&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean important&quot;&gt;true&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token key atrule&quot;&gt;remediation&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;      &lt;span class=&quot;token key atrule&quot;&gt;retries&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;3&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token key atrule&quot;&gt;upgrade&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token key atrule&quot;&gt;cleanupOnFail&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean important&quot;&gt;true&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token key atrule&quot;&gt;remediation&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;      &lt;span class=&quot;token key atrule&quot;&gt;retries&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;3&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token key atrule&quot;&gt;uninstall&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token key atrule&quot;&gt;keepHistory&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean important&quot;&gt;false&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token key atrule&quot;&gt;values&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token key atrule&quot;&gt;L2Advertisements&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;      &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token key atrule&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; main&lt;br /&gt;        &lt;span class=&quot;token key atrule&quot;&gt;addressPools&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;          &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; main&lt;br /&gt;    &lt;span class=&quot;token key atrule&quot;&gt;ipAddressPools&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;      &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token key atrule&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; main&lt;br /&gt;        &lt;span class=&quot;token key atrule&quot;&gt;autoAssign&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean important&quot;&gt;false&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token key atrule&quot;&gt;avoidBuggyIPs&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean important&quot;&gt;true&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token key atrule&quot;&gt;addresses&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;          &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; $&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;METALLB_RANGE&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;namespace.yaml&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&quot;language-yaml&quot;&gt;&lt;code class=&quot;language-yaml&quot;&gt;&lt;span class=&quot;token key atrule&quot;&gt;apiVersion&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; v1&lt;br /&gt;&lt;span class=&quot;token key atrule&quot;&gt;kind&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; Namespace&lt;br /&gt;&lt;span class=&quot;token key atrule&quot;&gt;metadata&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token key atrule&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; metallb&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;config&lt;br /&gt;    &lt;span class=&quot;token key atrule&quot;&gt;labels&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token key atrule&quot;&gt;pod-security.kubernetes.io/enforce&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; privileged&lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;kustomization.yaml&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&quot;language-yaml&quot;&gt;&lt;code class=&quot;language-yaml&quot;&gt;&lt;span class=&quot;token key atrule&quot;&gt;apiVersion&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; kustomize.config.k8s.io/v1beta1&lt;br /&gt;&lt;span class=&quot;token key atrule&quot;&gt;kind&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; Kustomization&lt;br /&gt;&lt;span class=&quot;token key atrule&quot;&gt;resources&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; namespace.yaml&lt;br /&gt;  &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; helm&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;release.yaml&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;./infrastructure/production/&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;metallb.yaml&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&quot;language-yaml&quot;&gt;&lt;code class=&quot;language-yaml&quot;&gt;&lt;span class=&quot;token key atrule&quot;&gt;apiVersion&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; kustomize.toolkit.fluxcd.io/v1&lt;br /&gt;&lt;span class=&quot;token key atrule&quot;&gt;kind&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; Kustomization&lt;br /&gt;&lt;span class=&quot;token key atrule&quot;&gt;metadata&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token key atrule&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; metallb&lt;br /&gt;  &lt;span class=&quot;token key atrule&quot;&gt;namespace&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; flux&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;system&lt;br /&gt;&lt;span class=&quot;token key atrule&quot;&gt;spec&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token key atrule&quot;&gt;interval&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; 10m&lt;br /&gt;  &lt;span class=&quot;token key atrule&quot;&gt;path&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; infrastructure/core/metallb&lt;br /&gt;  &lt;span class=&quot;token key atrule&quot;&gt;prune&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean important&quot;&gt;true&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token key atrule&quot;&gt;sourceRef&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token key atrule&quot;&gt;kind&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; GitRepository&lt;br /&gt;    &lt;span class=&quot;token key atrule&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; flux&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;system&lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;metallb-config.yaml&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&quot;language-yaml&quot;&gt;&lt;code class=&quot;language-yaml&quot;&gt;&lt;span class=&quot;token key atrule&quot;&gt;apiVersion&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; kustomize.toolkit.fluxcd.io/v1&lt;br /&gt;&lt;span class=&quot;token key atrule&quot;&gt;kind&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; Kustomization&lt;br /&gt;&lt;span class=&quot;token key atrule&quot;&gt;metadata&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token key atrule&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; metallb&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;config&lt;br /&gt;  &lt;span class=&quot;token key atrule&quot;&gt;namespace&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; flux&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;system&lt;br /&gt;&lt;span class=&quot;token key atrule&quot;&gt;spec&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token key atrule&quot;&gt;dependsOn&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token key atrule&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; metallb&lt;br /&gt;  &lt;span class=&quot;token key atrule&quot;&gt;interval&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; 10m&lt;br /&gt;  &lt;span class=&quot;token key atrule&quot;&gt;path&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; infrastructure/core/metallb&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;config&lt;br /&gt;  &lt;span class=&quot;token key atrule&quot;&gt;prune&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean important&quot;&gt;true&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token key atrule&quot;&gt;sourceRef&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token key atrule&quot;&gt;kind&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; GitRepository&lt;br /&gt;    &lt;span class=&quot;token key atrule&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; flux&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;system&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;And last but not least, edit the infrastructure and repos kustomizations to tie it all together.&lt;/p&gt;
&lt;h2&gt;./infrastructure/production/kustomization.yaml&lt;/h2&gt;
&lt;pre class=&quot;language-yaml&quot;&gt;&lt;code class=&quot;language-yaml&quot;&gt;&lt;span class=&quot;token key atrule&quot;&gt;apiVersion&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; kustomize.config.k8s.io/v1beta1&lt;br /&gt;&lt;span class=&quot;token key atrule&quot;&gt;kind&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; Kustomization&lt;br /&gt;&lt;span class=&quot;token key atrule&quot;&gt;resources&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; metallb.yaml&lt;br /&gt;  &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; metallb&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;config.yaml&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;./repos/kustomization.yaml&lt;/h2&gt;
&lt;pre class=&quot;language-yaml&quot;&gt;&lt;code class=&quot;language-yaml&quot;&gt;&lt;span class=&quot;token key atrule&quot;&gt;apiVersion&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; kustomize.config.k8s.io/v1beta1&lt;br /&gt;&lt;span class=&quot;token key atrule&quot;&gt;kind&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; Kustomization&lt;br /&gt;&lt;span class=&quot;token key atrule&quot;&gt;resources&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; podinfo.yaml&lt;br /&gt;  &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; jetstack.yaml&lt;br /&gt;  &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; truecharts.yaml&lt;br /&gt;  &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; metallb.yaml&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Then commit your changes and watch as flux reconciles the new resources.&lt;/p&gt;
&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;token function&quot;&gt;git&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;add&lt;/span&gt; &lt;span class=&quot;token parameter variable&quot;&gt;-A&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;git&lt;/span&gt; commit &lt;span class=&quot;token parameter variable&quot;&gt;-m&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;added metallb&#39;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token function&quot;&gt;git&lt;/span&gt; push&lt;br /&gt;flux events &lt;span class=&quot;token parameter variable&quot;&gt;--watch&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;Validating Metallb&lt;/h2&gt;
&lt;p&gt;To verify MetalLB was deployed and correctly configured, you can use your tools to inspect the different parts of the deployment. Start with inspecting the resources deployed by our infrastructure kustomization:&lt;/p&gt;
&lt;pre class=&quot;language-yaml&quot;&gt;&lt;code class=&quot;language-yaml&quot;&gt;$ flux tree ks infrastructure&lt;br /&gt;Kustomization/flux&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;system/infrastructure&lt;br /&gt;├── Kustomization/flux&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;system/metallb&lt;br /&gt;│   ├── Namespace/metallb&lt;br /&gt;│   └── HelmRelease/metallb/metallb&lt;br /&gt;│       ├── ServiceAccount/metallb/metallb&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;controller&lt;br /&gt;│       ├── ServiceAccount/metallb/metallb&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;speaker&lt;br /&gt;│       ├── Secret/metallb/metallb&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;webhook&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;cert&lt;br /&gt;│       ├── ConfigMap/metallb/metallb&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;excludel2&lt;br /&gt;│       ├── ConfigMap/metallb/metallb&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;frr&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;startup&lt;br /&gt;│       ├── CustomResourceDefinition/bfdprofiles.metallb.io&lt;br /&gt;│       ├── CustomResourceDefinition/bgpadvertisements.metallb.io&lt;br /&gt;│       ├── CustomResourceDefinition/bgppeers.metallb.io&lt;br /&gt;│       ├── CustomResourceDefinition/communities.metallb.io&lt;br /&gt;│       ├── CustomResourceDefinition/ipaddresspools.metallb.io&lt;br /&gt;│       ├── CustomResourceDefinition/l2advertisements.metallb.io&lt;br /&gt;│       ├── CustomResourceDefinition/servicel2statuses.metallb.io&lt;br /&gt;│       ├── ClusterRole/metallb&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;controller&lt;br /&gt;│       ├── ClusterRole/metallb&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;speaker&lt;br /&gt;│       ├── ClusterRoleBinding/metallb&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;controller&lt;br /&gt;│       ├── ClusterRoleBinding/metallb&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;speaker&lt;br /&gt;│       ├── Role/metallb/metallb&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;pod&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;lister&lt;br /&gt;│       ├── Role/metallb/metallb&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;controller&lt;br /&gt;│       ├── RoleBinding/metallb/metallb&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;pod&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;lister&lt;br /&gt;│       ├── RoleBinding/metallb/metallb&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;controller&lt;br /&gt;│       ├── Service/metallb/metallb&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;webhook&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;service&lt;br /&gt;│       ├── DaemonSet/metallb/metallb&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;speaker&lt;br /&gt;│       ├── Deployment/metallb/metallb&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;controller&lt;br /&gt;│       └── ValidatingWebhookConfiguration/metallb&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;webhook&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;configuration&lt;br /&gt;└── Kustomization/flux&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;system/metallb&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;config&lt;br /&gt;    ├── Namespace/metallb&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;config&lt;br /&gt;    └── HelmRelease/metallb&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;config/metallb&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;config&lt;br /&gt;        ├── IPAddressPool/metallb/main&lt;br /&gt;        └── L2Advertisement/metallb/main&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;We can see that everything has been deployed. The MetalLB kustomization deployed the Helm chart which brought along all the different parts of MetalLB, and the MetalLB-config kustomization created two custom resource definitions that will configure MetalLB within our cluster. Let’s inspect those resources with kubectl:&lt;/p&gt;
&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;$ kubectl get l2advertisements.metallb.io &lt;span class=&quot;token parameter variable&quot;&gt;-A&lt;/span&gt;&lt;br /&gt;NAMESPACE   NAME   IPADDRESSPOOLS   IPADDRESSPOOL SELECTORS   INTERFACES&lt;br /&gt;metallb     main   &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;main&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;                                   &lt;br /&gt;$ kubectl get ipaddresspools.metallb.io &lt;span class=&quot;token parameter variable&quot;&gt;-A&lt;/span&gt;&lt;br /&gt;NAMESPACE   NAME   AUTO ASSIGN   AVOID BUGGY IPS   ADDRESSES&lt;br /&gt;metallb     main   &lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;          &lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;              &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;192.168.XX.200-192.168.XX.250&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;So we have proof that MetalLB has been deployed and is configured. These steps of inspecting resources will be helpful to you whenever you are troubleshooting with flux and kubernetes.&lt;/p&gt;
&lt;h2&gt;Deploy NGINX&lt;/h2&gt;
&lt;p&gt;With MetalLB configured, we can move on to deploying NGINX.&lt;/p&gt;
&lt;p&gt;Create the following directories and manifests:&lt;/p&gt;
&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;truek8s&lt;br /&gt;├── infrastructure&lt;br /&gt;│   ├── core&lt;br /&gt;│   │   └── ingress-nginx&lt;br /&gt;│   │      ├── helm-release.yaml&lt;br /&gt;│   │      ├── kustomization.yaml&lt;br /&gt;│   │      └── namespace.yaml&lt;br /&gt;│   └── production&lt;br /&gt;│       └── ingress-nginx.yaml&lt;br /&gt;└── repos&lt;br /&gt;    └── ingress-nginx.yaml&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;infrastructure/core/ingress-nginx&lt;/h3&gt;
&lt;p&gt;The configuration of NGINX is specified in the spec.values section of this manifest. Pay particular attention to the loadBalancerIPs and ingressClassResource.&lt;/p&gt;
&lt;h4&gt;helm-release.yaml&lt;/h4&gt;
&lt;pre class=&quot;language-yaml&quot;&gt;&lt;code class=&quot;language-yaml&quot;&gt;&lt;span class=&quot;token key atrule&quot;&gt;apiVersion&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; helm.toolkit.fluxcd.io/v2&lt;br /&gt;&lt;span class=&quot;token key atrule&quot;&gt;kind&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; HelmRelease&lt;br /&gt;&lt;span class=&quot;token key atrule&quot;&gt;metadata&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token key atrule&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; ingress&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;nginx&lt;br /&gt;  &lt;span class=&quot;token key atrule&quot;&gt;namespace&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; ingress&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;nginx&lt;br /&gt;&lt;span class=&quot;token key atrule&quot;&gt;spec&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token key atrule&quot;&gt;interval&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; 15m&lt;br /&gt;  &lt;span class=&quot;token key atrule&quot;&gt;chart&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token key atrule&quot;&gt;spec&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;      &lt;span class=&quot;token key atrule&quot;&gt;chart&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;ingress-nginx&#39;&lt;/span&gt;&lt;br /&gt;      &lt;span class=&quot;token key atrule&quot;&gt;version&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; 4.12.2&lt;br /&gt;      &lt;span class=&quot;token key atrule&quot;&gt;sourceRef&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token key atrule&quot;&gt;kind&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; HelmRepository&lt;br /&gt;        &lt;span class=&quot;token key atrule&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;ingress-nginx&#39;&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token key atrule&quot;&gt;namespace&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; flux&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;system&lt;br /&gt;      &lt;span class=&quot;token key atrule&quot;&gt;interval&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; 15m&lt;br /&gt;  &lt;span class=&quot;token key atrule&quot;&gt;timeout&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; 20m&lt;br /&gt;  &lt;span class=&quot;token key atrule&quot;&gt;maxHistory&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;3&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token key atrule&quot;&gt;install&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token key atrule&quot;&gt;createNamespace&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean important&quot;&gt;true&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token key atrule&quot;&gt;remediation&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;      &lt;span class=&quot;token key atrule&quot;&gt;retries&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;3&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token key atrule&quot;&gt;upgrade&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token key atrule&quot;&gt;cleanupOnFail&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean important&quot;&gt;true&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token key atrule&quot;&gt;remediation&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;      &lt;span class=&quot;token key atrule&quot;&gt;retries&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;3&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token key atrule&quot;&gt;uninstall&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token key atrule&quot;&gt;keepHistory&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean important&quot;&gt;false&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token key atrule&quot;&gt;values&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token key atrule&quot;&gt;controller&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;      &lt;span class=&quot;token key atrule&quot;&gt;replicaCount&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt;&lt;br /&gt;      &lt;span class=&quot;token key atrule&quot;&gt;service&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token key atrule&quot;&gt;externalTrafficPolicy&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; Local&lt;br /&gt;        &lt;span class=&quot;token key atrule&quot;&gt;annotations&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;          &lt;span class=&quot;token key atrule&quot;&gt;metallb.io/ip-allocated-from-pool&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; main&lt;br /&gt;          &lt;span class=&quot;token key atrule&quot;&gt;metallb.io/loadBalancerIPs&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; $&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;NGINX_IP&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;          &lt;span class=&quot;token key atrule&quot;&gt;metallb.universe.tf/ip-allocated-from-pool&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; main&lt;br /&gt;      &lt;span class=&quot;token key atrule&quot;&gt;ingressClassByName&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean important&quot;&gt;true&lt;/span&gt;&lt;br /&gt;      &lt;span class=&quot;token key atrule&quot;&gt;ingressClassResource&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token key atrule&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; internal&lt;br /&gt;        &lt;span class=&quot;token key atrule&quot;&gt;default&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean important&quot;&gt;true&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token key atrule&quot;&gt;controllerValue&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; k8s.io/internal&lt;br /&gt;      &lt;span class=&quot;token key atrule&quot;&gt;config&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token key atrule&quot;&gt;allow-snippet-annotations&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean important&quot;&gt;true&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token key atrule&quot;&gt;annotations-risk-level&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; Critical&lt;br /&gt;        &lt;span class=&quot;token key atrule&quot;&gt;client-body-buffer-size&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; 100M&lt;br /&gt;        &lt;span class=&quot;token key atrule&quot;&gt;client-body-timeout&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;120&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token key atrule&quot;&gt;client-header-timeout&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;120&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token key atrule&quot;&gt;enable-brotli&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;true&quot;&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token key atrule&quot;&gt;enable-ocsp&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;true&quot;&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token key atrule&quot;&gt;enable-real-ip&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;true&quot;&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token key atrule&quot;&gt;force-ssl-redirect&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;true&quot;&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token key atrule&quot;&gt;hide-headers&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; Server&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;X&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;Powered&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;By&lt;br /&gt;        &lt;span class=&quot;token key atrule&quot;&gt;hsts-max-age&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;31449600&quot;&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token key atrule&quot;&gt;keep-alive-requests&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;10000&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token key atrule&quot;&gt;keep-alive&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;120&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token key atrule&quot;&gt;proxy-body-size&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token key atrule&quot;&gt;proxy-buffer-size&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; 16k&lt;br /&gt;        &lt;span class=&quot;token key atrule&quot;&gt;ssl-protocols&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; TLSv1.3 TLSv1.2&lt;br /&gt;        &lt;span class=&quot;token key atrule&quot;&gt;use-forwarded-headers&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;true&quot;&lt;/span&gt;&lt;br /&gt;      &lt;span class=&quot;token key atrule&quot;&gt;metrics&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token key atrule&quot;&gt;enabled&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean important&quot;&gt;true&lt;/span&gt;&lt;br /&gt;      &lt;span class=&quot;token key atrule&quot;&gt;extraArgs&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token key atrule&quot;&gt;default-ssl-certificate&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;clusterissuer/certificate-issuer-star-domain-0&quot;&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token key atrule&quot;&gt;publish-status-address&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; $&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;NGINX_IP&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;      &lt;span class=&quot;token key atrule&quot;&gt;terminationGracePeriodSeconds&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;120&lt;/span&gt;&lt;br /&gt;      &lt;span class=&quot;token key atrule&quot;&gt;publishService&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token key atrule&quot;&gt;enabled&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean important&quot;&gt;false&lt;/span&gt;&lt;br /&gt;      &lt;span class=&quot;token key atrule&quot;&gt;resources&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token key atrule&quot;&gt;requests&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;          &lt;span class=&quot;token key atrule&quot;&gt;cpu&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; 100m&lt;br /&gt;        &lt;span class=&quot;token key atrule&quot;&gt;limits&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;          &lt;span class=&quot;token key atrule&quot;&gt;memory&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; 500Mi&lt;br /&gt;    &lt;span class=&quot;token key atrule&quot;&gt;defaultBackend&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;      &lt;span class=&quot;token key atrule&quot;&gt;enabled&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean important&quot;&gt;false&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h4&gt;kustomization.yaml&lt;/h4&gt;
&lt;pre class=&quot;language-yaml&quot;&gt;&lt;code class=&quot;language-yaml&quot;&gt;&lt;span class=&quot;token key atrule&quot;&gt;apiVersion&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; kustomize.config.k8s.io/v1beta1&lt;br /&gt;&lt;span class=&quot;token key atrule&quot;&gt;kind&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; Kustomization&lt;br /&gt;&lt;span class=&quot;token key atrule&quot;&gt;resources&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; namespace.yaml&lt;br /&gt;  &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; helm&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;release.yaml&lt;/code&gt;&lt;/pre&gt;
&lt;h4&gt;namespace.yaml&lt;/h4&gt;
&lt;pre class=&quot;language-yaml&quot;&gt;&lt;code class=&quot;language-yaml&quot;&gt;&lt;span class=&quot;token key atrule&quot;&gt;apiVersion&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; v1&lt;br /&gt;&lt;span class=&quot;token key atrule&quot;&gt;kind&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; Namespace&lt;br /&gt;&lt;span class=&quot;token key atrule&quot;&gt;metadata&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token key atrule&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; ingress&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;nginx&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;infrastructure/production&lt;/h3&gt;
&lt;h4&gt;ingress-nginx.yaml&lt;/h4&gt;
&lt;p&gt;NGINX depends on MetalLB for it’s IP address on the local network, and also needs a certificate, so we’ll configure it to depend on MetalLB-config and cluster-issuer.&lt;/p&gt;
&lt;pre class=&quot;language-yaml&quot;&gt;&lt;code class=&quot;language-yaml&quot;&gt;&lt;span class=&quot;token key atrule&quot;&gt;apiVersion&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; kustomize.toolkit.fluxcd.io/v1&lt;br /&gt;&lt;span class=&quot;token key atrule&quot;&gt;kind&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; Kustomization&lt;br /&gt;&lt;span class=&quot;token key atrule&quot;&gt;metadata&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token key atrule&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; ingress&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;nginx&lt;br /&gt;  &lt;span class=&quot;token key atrule&quot;&gt;namespace&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; flux&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;system&lt;br /&gt;&lt;span class=&quot;token key atrule&quot;&gt;spec&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token key atrule&quot;&gt;dependsOn&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token key atrule&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; metallb&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;config&lt;br /&gt;    &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token key atrule&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; cluster&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;issuer&lt;br /&gt;  &lt;span class=&quot;token key atrule&quot;&gt;interval&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; 10m&lt;br /&gt;  &lt;span class=&quot;token key atrule&quot;&gt;path&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; infrastructure/core/ingress&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;nginx&lt;br /&gt;  &lt;span class=&quot;token key atrule&quot;&gt;prune&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean important&quot;&gt;true&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token key atrule&quot;&gt;sourceRef&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token key atrule&quot;&gt;kind&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; GitRepository&lt;br /&gt;    &lt;span class=&quot;token key atrule&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; flux&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;system&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Once you’ve created all of those, reference the new ingress-nginx kustomization in the infrastructure&#92;production and repos ks:&lt;/p&gt;
&lt;h4&gt;infrastructure/production/kustomization.yaml&lt;/h4&gt;
&lt;pre class=&quot;language-yaml&quot;&gt;&lt;code class=&quot;language-yaml&quot;&gt;&lt;span class=&quot;token key atrule&quot;&gt;apiVersion&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; kustomize.config.k8s.io/v1beta1&lt;br /&gt;&lt;span class=&quot;token key atrule&quot;&gt;kind&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; Kustomization&lt;br /&gt;&lt;span class=&quot;token key atrule&quot;&gt;resources&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; cert&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;manager.yaml&lt;br /&gt;  &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; cluster&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;issuer.yaml&lt;br /&gt;  &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; metallb.yaml&lt;br /&gt;  &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; metallb&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;config.yaml&lt;br /&gt;  &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; ingress&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;nginx.yaml&lt;/code&gt;&lt;/pre&gt;
&lt;h4&gt;repos/kustomization.yaml&lt;/h4&gt;
&lt;pre class=&quot;language-yaml&quot;&gt;&lt;code class=&quot;language-yaml&quot;&gt;&lt;span class=&quot;token key atrule&quot;&gt;apiVersion&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; kustomize.config.k8s.io/v1beta1&lt;br /&gt;&lt;span class=&quot;token key atrule&quot;&gt;kind&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; Kustomization&lt;br /&gt;&lt;span class=&quot;token key atrule&quot;&gt;resources&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; podinfo.yaml&lt;br /&gt;  &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; jetstack.yaml&lt;br /&gt;  &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; truecharts.yaml&lt;br /&gt;  &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; metallb.yaml&lt;br /&gt;  &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; ingress&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;nginx.yaml&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;And push your changes to your repo:&lt;/p&gt;
&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;$ &lt;span class=&quot;token function&quot;&gt;git&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;add&lt;/span&gt; &lt;span class=&quot;token parameter variable&quot;&gt;-A&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;git&lt;/span&gt; commit &lt;span class=&quot;token parameter variable&quot;&gt;-m&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;add ingress nginx&#39;&lt;/span&gt;&lt;br /&gt;$ &lt;span class=&quot;token function&quot;&gt;git&lt;/span&gt; push&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;You can monitor the reconiciliation by waiting for Flux to mark the Helm release as ready.&lt;/p&gt;
&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;flux get hr ingress-nginx &lt;span class=&quot;token parameter variable&quot;&gt;-n&lt;/span&gt; ingress-nginx &lt;span class=&quot;token parameter variable&quot;&gt;--watch&lt;/span&gt;&lt;br /&gt;NAME            REVISION        SUSPENDED       READY   MESSAGE                                                                                           &lt;br /&gt;ingress-nginx   &lt;span class=&quot;token number&quot;&gt;4.12&lt;/span&gt;.2          False           True    Helm &lt;span class=&quot;token function&quot;&gt;install&lt;/span&gt; succeeded &lt;span class=&quot;token keyword&quot;&gt;for&lt;/span&gt; release ingress-nginx/ingress-nginx.v1 with chart ingress-nginx@4.12.2&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;Verify NGINX&lt;/h3&gt;
&lt;p&gt;Is it “EngineX” or “N-Ginx”? anyway… Once it’s installed and configured properly, it should create an ingress class within your cluster. Other apps will use this ingress class to automatically configure ingress with NGINX. You can use kubectl to inspect:&lt;/p&gt;
&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;$ kubectl get ingressclass&lt;br /&gt;NAME         CONTROLLER                                       PARAMETERS   AGE&lt;br /&gt;internal     k8s.io/internal                                  &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;none&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;       2d8h&lt;br /&gt;&lt;br /&gt;$ kubectl describe ingressclass internal &lt;br /&gt;Name:         internal&lt;br /&gt;Labels:       app.kubernetes.io/component&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;controller&lt;br /&gt;              app.kubernetes.io/instance&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;ingress-nginx&lt;br /&gt;              app.kubernetes.io/managed-by&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;Helm&lt;br /&gt;              app.kubernetes.io/name&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;ingress-nginx&lt;br /&gt;              app.kubernetes.io/part-of&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;ingress-nginx&lt;br /&gt;              app.kubernetes.io/version&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1.12&lt;/span&gt;.2&lt;br /&gt;              helm.sh/chart&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;ingress-nginx-4.12.2&lt;br /&gt;              helm.toolkit.fluxcd.io/name&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;ingress-nginx&lt;br /&gt;              helm.toolkit.fluxcd.io/namespace&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;ingress-nginx&lt;br /&gt;Annotations:  ingressclass.kubernetes.io/is-default-class: &lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;&lt;br /&gt;              meta.helm.sh/release-name: ingress-nginx&lt;br /&gt;              meta.helm.sh/release-namespace: ingress-nginx&lt;br /&gt;Controller:   k8s.io/internal&lt;br /&gt;Events:       &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;none&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;Testing ingress&lt;/h2&gt;
&lt;p&gt;Having an ingress controller won’t be very helpful unless you also know how to use that ingress controller for a given application. Let me provide an example by creating an ingress resource for our example deployment of podinfo.&lt;/p&gt;
&lt;h3&gt;apps/general/podinfo&lt;/h3&gt;
&lt;h4&gt;ingress.yaml&lt;/h4&gt;
&lt;p&gt;Create an ingress.yaml file here, and populate it like this:&lt;/p&gt;
&lt;pre class=&quot;language-yaml&quot;&gt;&lt;code class=&quot;language-yaml&quot;&gt;&lt;span class=&quot;token key atrule&quot;&gt;apiVersion&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; networking.k8s.io/v1&lt;br /&gt;&lt;span class=&quot;token key atrule&quot;&gt;kind&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; Ingress&lt;br /&gt;&lt;span class=&quot;token key atrule&quot;&gt;metadata&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token key atrule&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; podinfo&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;nginx&lt;br /&gt;  &lt;span class=&quot;token key atrule&quot;&gt;namespace&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; podinfo&lt;br /&gt;&lt;span class=&quot;token key atrule&quot;&gt;spec&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token key atrule&quot;&gt;ingressClassName&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; internal&lt;br /&gt;  &lt;span class=&quot;token key atrule&quot;&gt;rules&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token key atrule&quot;&gt;host&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; podinfo.$&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;DOMAIN_0&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;      &lt;span class=&quot;token key atrule&quot;&gt;http&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token key atrule&quot;&gt;paths&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;          &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token key atrule&quot;&gt;backend&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;              &lt;span class=&quot;token key atrule&quot;&gt;service&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;                &lt;span class=&quot;token key atrule&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; podinfo&lt;br /&gt;                &lt;span class=&quot;token key atrule&quot;&gt;port&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;                  &lt;span class=&quot;token key atrule&quot;&gt;number&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;9898&lt;/span&gt;&lt;br /&gt;            &lt;span class=&quot;token key atrule&quot;&gt;path&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; /&lt;br /&gt;            &lt;span class=&quot;token key atrule&quot;&gt;pathType&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; Prefix&lt;/code&gt;&lt;/pre&gt;
&lt;h4&gt;kustomization.yaml&lt;/h4&gt;
&lt;p&gt;and add a reference to this new file to the kustomization.&lt;/p&gt;
&lt;pre class=&quot;language-yaml&quot;&gt;&lt;code class=&quot;language-yaml&quot;&gt;&lt;span class=&quot;token key atrule&quot;&gt;apiVersion&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; kustomize.config.k8s.io/v1beta1&lt;br /&gt;&lt;span class=&quot;token key atrule&quot;&gt;kind&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; Kustomization&lt;br /&gt;&lt;span class=&quot;token key atrule&quot;&gt;resources&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; namespace.yaml&lt;br /&gt;  &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; helm&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;release.yaml&lt;br /&gt;  &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; ingress.yaml&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;And commit those changes&lt;/p&gt;
&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;$ &lt;span class=&quot;token function&quot;&gt;git&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;add&lt;/span&gt; &lt;span class=&quot;token parameter variable&quot;&gt;-A&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;git&lt;/span&gt; commit &lt;span class=&quot;token parameter variable&quot;&gt;-m&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;add podinfo ingress&#39;&lt;/span&gt;&lt;br /&gt;$ &lt;span class=&quot;token function&quot;&gt;git&lt;/span&gt; push&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This will create a new ingress resource from the ‘internal’ ingress class we used earlier. inspect the results with flux and kubectl:&lt;/p&gt;
&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;$ flux tree ks podinfo&lt;br /&gt;Kustomization/flux-system/podinfo&lt;br /&gt;├── Namespace/podinfo&lt;br /&gt;├── HelmRelease/podinfo/podinfo&lt;br /&gt;│   ├── Service/podinfo/podinfo&lt;br /&gt;│   └── Deployment/podinfo/podinfo&lt;br /&gt;└── Ingress/podinfo/podinfo-nginx&lt;br /&gt;&lt;br /&gt;$ kubectl get ingress &lt;span class=&quot;token parameter variable&quot;&gt;-n&lt;/span&gt; podinfo podinfo-nginx &lt;br /&gt;NAME            CLASS      HOSTS             ADDRESS                           PORTS   AGE&lt;br /&gt;podinfo-nginx   internal   podinfo.domain.tld   &lt;span class=&quot;token number&quot;&gt;192.168&lt;/span&gt;.XX.111,192.168.XX.112   &lt;span class=&quot;token number&quot;&gt;80&lt;/span&gt;      116s&lt;br /&gt;$ kubectl describe  ingress &lt;span class=&quot;token parameter variable&quot;&gt;-n&lt;/span&gt; podinfo podinfo-nginx &lt;br /&gt;Name:             podinfo-nginx&lt;br /&gt;Namespace:        podinfo&lt;br /&gt;Address:          &lt;span class=&quot;token number&quot;&gt;192.168&lt;/span&gt;.XX.111,192.168.XX.112&lt;br /&gt;Default backend:  default-http-backend:80 &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;error: endpoints &lt;span class=&quot;token string&quot;&gt;&quot;default-http-backend&quot;&lt;/span&gt; not found&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;br /&gt;Rules:&lt;br /&gt;  Host             Path  Backends&lt;br /&gt;  ----             ----  --------&lt;br /&gt;  podinfo.domain.tld  &lt;br /&gt;                   /   podinfo:9898 &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;172&lt;/span&gt;.XX.2.8:9898&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;br /&gt;Annotations:       &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;none&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;br /&gt;Events:&lt;br /&gt;  Type    Reason  Age                   From                      Message&lt;br /&gt;  ----    ------  ----                  ----                      -------&lt;br /&gt;  Normal  Sync    108s &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;x2 over 2m43s&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;  nginx-ingress-controller  Scheduled &lt;span class=&quot;token keyword&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;sync&lt;/span&gt;&lt;br /&gt;  Normal  Sync    108s &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;x2 over 2m43s&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;  nginx-ingress-controller  Scheduled &lt;span class=&quot;token keyword&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;sync&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;You’ll need to configure your local DNS to resolve these names and point at your MetalLB IP. What I do is create a host record pointing at NGINX and then create CNAMES for every service I deploy.&lt;/p&gt;
&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;truek8s@debian02:~/Documents/truek8s/config$ &lt;span class=&quot;token function&quot;&gt;nslookup&lt;/span&gt; nginx.domain.tld&lt;br /&gt;Server:         &lt;span class=&quot;token number&quot;&gt;192.168&lt;/span&gt;.XX.2&lt;br /&gt;Address:        &lt;span class=&quot;token number&quot;&gt;192.168&lt;/span&gt;.XX.2&lt;span class=&quot;token comment&quot;&gt;#53&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Non-authoritative answer:&lt;br /&gt;Name:   nginx.domain.tld&lt;br /&gt;Address: &lt;span class=&quot;token number&quot;&gt;192.168&lt;/span&gt;.XX.200&lt;br /&gt;&lt;br /&gt;truek8s@debian02:~/Documents/truek8s/config$ &lt;span class=&quot;token function&quot;&gt;nslookup&lt;/span&gt; podinfo.domain.tld&lt;br /&gt;Server:         &lt;span class=&quot;token number&quot;&gt;192.168&lt;/span&gt;.XX.2&lt;br /&gt;Address:        &lt;span class=&quot;token number&quot;&gt;192.168&lt;/span&gt;.XX.2&lt;span class=&quot;token comment&quot;&gt;#53&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Non-authoritative answer:&lt;br /&gt;podinfo.domain.tld canonical name &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; nginx.domain.tld.&lt;br /&gt;Name:   nginx.domain.tld&lt;br /&gt;Address: &lt;span class=&quot;token number&quot;&gt;192.168&lt;/span&gt;.XX.200&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;When all that is configured, you should be able to access the podinfo web service at the IP&#92;DNS name you configured. Thanks to the work we did in part 4, nginx was able to automatically retrieve a certificate for the podifo service and serve over HTTPS with a valid cert.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;http://localhost:8080/assets/images/2025/05/podinfo-ingress-with-cert.png&quot; alt=&quot;image&quot; /&gt;&lt;br /&gt;
&lt;img src=&quot;http://localhost:8080/assets/images/2025/05/podinfo-ingress-cert.png&quot; alt=&quot;image&quot; /&gt;&lt;/p&gt;
&lt;h2&gt;sources&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://trueforge.org/truetech/truecharts/charts/stable/metallb-config/setup-guide/&quot;&gt;trueforge.org: MetalLB Basic Setup&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://trueforge.org/truetech/truecharts/guides/ingress/nginx/&quot;&gt;trueforce.org: NGINX&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
</content>
    </entry>
    
    <entry>
      <title>TrueK8S Part 06</title>
      <link href="http://localhost:8080/2025/05/15/truek8s-part-06/"/>
      <updated>2025-05-15T12:30:00Z</updated>
      <id>http://localhost:8080/2025/05/15/truek8s-part-06/</id>
      <content type="html">&lt;h2&gt;Cloudflare Ingress&lt;/h2&gt;
&lt;p&gt;When it comes to hosting services, having them available to you inside your house is nice, but the true value comes from having them externally available. I don’t have the risk appetite to expose services directly from my home network, so I let Cloudflare do it for me. This set up is pretty common among homelabbers, and especially among the TrueCharts community from what I’ve seen. I especially like CloudFlare’s Zero Trust services, which allow me to put an extra layer of security in front of my applications by requiring strong authentication before you can access anything.&lt;/p&gt;
&lt;p&gt;One way that I’ve noticed my cluster differs from some of the examples I’ve seen in the TrueCharts community is how I chose to configure my external ingress. The most current recommendation I see from the TrueCharts project right now is to run two instances of NGINX ingrex, one internal, and one external. Then, point the Cloudflare tunnel daemon at your external ingress, either from a deployment in your cluster, or from elsewhere on your network.&lt;/p&gt;
&lt;p&gt;Personally, I found another project that I find more convenient: &lt;a href=&quot;https://github.com/STRRL/cloudflare-tunnel-ingress-controller&quot;&gt;STRRL cloudflare-tunnel-ingress-controller&lt;/a&gt;. This ingress controller, available as a helm chart, runs a managed Cloudflare tunnel in your environment and provides all the necessary Kubernetes ingress resources.&lt;/p&gt;
&lt;p&gt;If you’re following along and don’t have any interest in configuring Cloudflare ingress, skip ahead to part 7. You won’t miss anything.&lt;/p&gt;
&lt;h2&gt;Deploying cf-tunnel-ingress&lt;/h2&gt;
&lt;p&gt;Start by gathering details and generating a unique API token from your Cloudflare account.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Create custom token&lt;br /&gt;
&lt;img src=&quot;http://localhost:8080/assets/images/2025/05/cf-tunnel-new-api-custom.png&quot; alt=&quot;image&quot; /&gt;&lt;/li&gt;
&lt;li&gt;Add:&lt;/li&gt;
&lt;/ol&gt;
&lt;ul&gt;
&lt;li&gt;Zone:Zone:Read&lt;/li&gt;
&lt;li&gt;Zone:DNS:Edit&lt;/li&gt;
&lt;li&gt;Account:Cloudflare Tunnel:Edit&lt;br /&gt;
&lt;img src=&quot;http://localhost:8080/assets/images/2025/05/cf-tunnel-new-api-perms.png&quot; alt=&quot;image&quot; /&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;ol start=&quot;3&quot;&gt;
&lt;li&gt;Then finally, grab your account ID&lt;br /&gt;
&lt;img src=&quot;http://localhost:8080/assets/images/2025/05/cf-tunnel-account-id.png&quot; alt=&quot;image&quot; /&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Then add that info to your cluster-config:&lt;/p&gt;
&lt;pre class=&quot;language-yaml&quot;&gt;&lt;code class=&quot;language-yaml&quot;&gt;&lt;span class=&quot;token key atrule&quot;&gt;apiVersion&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; v1&lt;br /&gt;&lt;span class=&quot;token key atrule&quot;&gt;kind&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; ConfigMap&lt;br /&gt;&lt;span class=&quot;token key atrule&quot;&gt;metadata&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token key atrule&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; cluster&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;config&lt;br /&gt;    &lt;span class=&quot;token key atrule&quot;&gt;namespace&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; flux&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;system&lt;br /&gt;&lt;span class=&quot;token key atrule&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token key atrule&quot;&gt;CF_INGRESS_ACCOUNT_ID&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &amp;lt;your account ID&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token key atrule&quot;&gt;CF_INGRESS_API_TOKEN&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &amp;lt;your token&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token key atrule&quot;&gt;CF_INGRESS_TUNNEL&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &amp;lt;a descriptive name for your tunnel&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Then deploy the helm chart following the structure of our repo:&lt;/p&gt;
&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;truek8s-v2&lt;br /&gt;├── infrastructure&lt;br /&gt;│   ├── core&lt;br /&gt;│   │   └── cf-tunnel-ingress&lt;br /&gt;│   │      ├── helm-release.yaml&lt;br /&gt;│   │      ├── kustomization.yaml&lt;br /&gt;│   │      └── namespace.yaml&lt;br /&gt;│   └── production&lt;br /&gt;│       └── cf-tunnel-ingress.yaml&lt;br /&gt;└── repos&lt;br /&gt;    └── strrl.yaml&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;infrastructure/core/cf-tunnel-ingress&lt;/h3&gt;
&lt;h4&gt;helm-release.yaml&lt;/h4&gt;
&lt;pre class=&quot;language-yaml&quot;&gt;&lt;code class=&quot;language-yaml&quot;&gt;&lt;span class=&quot;token key atrule&quot;&gt;apiVersion&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; helm.toolkit.fluxcd.io/v2&lt;br /&gt;&lt;span class=&quot;token key atrule&quot;&gt;kind&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; HelmRelease&lt;br /&gt;&lt;span class=&quot;token key atrule&quot;&gt;metadata&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token key atrule&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; cloudflare&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;tunnel&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;ingress&lt;br /&gt;  &lt;span class=&quot;token key atrule&quot;&gt;namespace&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; cloudflare&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;ingress&lt;br /&gt;&lt;span class=&quot;token key atrule&quot;&gt;spec&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token key atrule&quot;&gt;chart&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token key atrule&quot;&gt;spec&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;      &lt;span class=&quot;token key atrule&quot;&gt;chart&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; cloudflare&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;tunnel&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;ingress&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;controller&lt;br /&gt;      &lt;span class=&quot;token key atrule&quot;&gt;reconcileStrategy&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; ChartVersion&lt;br /&gt;      &lt;span class=&quot;token key atrule&quot;&gt;sourceRef&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token key atrule&quot;&gt;kind&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; HelmRepository&lt;br /&gt;        &lt;span class=&quot;token key atrule&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; strrl&lt;br /&gt;        &lt;span class=&quot;token key atrule&quot;&gt;namespace&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; flux&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;system&lt;br /&gt;  &lt;span class=&quot;token key atrule&quot;&gt;values&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token key atrule&quot;&gt;cloudflare&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;      &lt;span class=&quot;token key atrule&quot;&gt;accountId&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; $&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;CF_INGRESS_ACCOUNT_ID&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;      &lt;span class=&quot;token key atrule&quot;&gt;apiToken&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; $&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;CF_INGRESS_API_TOKEN&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;      &lt;span class=&quot;token key atrule&quot;&gt;tunnelName&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; $&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;CF_INGRESS_TUNNEL&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token key atrule&quot;&gt;ingressClass&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;      &lt;span class=&quot;token key atrule&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; cloudflare&lt;br /&gt;      &lt;span class=&quot;token key atrule&quot;&gt;controllerValue&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; strrl.dev/cloudflare&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;tunnel&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;ingress&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;controller&lt;br /&gt;      &lt;span class=&quot;token key atrule&quot;&gt;isDefaultClass&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean important&quot;&gt;false&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token key atrule&quot;&gt;interval&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; 1m0s&lt;/code&gt;&lt;/pre&gt;
&lt;h4&gt;namespace.yaml&lt;/h4&gt;
&lt;pre class=&quot;language-yaml&quot;&gt;&lt;code class=&quot;language-yaml&quot;&gt;&lt;span class=&quot;token key atrule&quot;&gt;apiVersion&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; v1&lt;br /&gt;&lt;span class=&quot;token key atrule&quot;&gt;kind&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; Namespace&lt;br /&gt;&lt;span class=&quot;token key atrule&quot;&gt;metadata&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token key atrule&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; cloudflare&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;ingress&lt;/code&gt;&lt;/pre&gt;
&lt;h4&gt;kustomization.yaml&lt;/h4&gt;
&lt;pre class=&quot;language-yaml&quot;&gt;&lt;code class=&quot;language-yaml&quot;&gt;&lt;span class=&quot;token key atrule&quot;&gt;apiVersion&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; kustomize.config.k8s.io/v1beta1&lt;br /&gt;&lt;span class=&quot;token key atrule&quot;&gt;kind&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; Kustomization&lt;br /&gt;&lt;span class=&quot;token key atrule&quot;&gt;resources&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; namespace.yaml&lt;br /&gt;  &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; helm&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;release.yaml&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;infrastructure/production&lt;/h3&gt;
&lt;h4&gt;cf-tunnel-ingress.yaml&lt;/h4&gt;
&lt;pre class=&quot;language-yaml&quot;&gt;&lt;code class=&quot;language-yaml&quot;&gt;&lt;span class=&quot;token key atrule&quot;&gt;apiVersion&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; kustomize.toolkit.fluxcd.io/v1&lt;br /&gt;&lt;span class=&quot;token key atrule&quot;&gt;kind&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; Kustomization&lt;br /&gt;&lt;span class=&quot;token key atrule&quot;&gt;metadata&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token key atrule&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; cf&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;tunnel&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;ingress&lt;br /&gt;  &lt;span class=&quot;token key atrule&quot;&gt;namespace&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; flux&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;system&lt;br /&gt;&lt;span class=&quot;token key atrule&quot;&gt;spec&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token key atrule&quot;&gt;interval&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; 10m&lt;br /&gt;  &lt;span class=&quot;token key atrule&quot;&gt;path&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; infrastructure/core/cf&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;tunnel&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;ingress&lt;br /&gt;  &lt;span class=&quot;token key atrule&quot;&gt;prune&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean important&quot;&gt;true&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token key atrule&quot;&gt;sourceRef&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token key atrule&quot;&gt;kind&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; GitRepository&lt;br /&gt;    &lt;span class=&quot;token key atrule&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; flux&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;system&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;repos&lt;/h3&gt;
&lt;h4&gt;strrl.yaml&lt;/h4&gt;
&lt;pre class=&quot;language-yaml&quot;&gt;&lt;code class=&quot;language-yaml&quot;&gt;&lt;span class=&quot;token key atrule&quot;&gt;apiVersion&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; source.toolkit.fluxcd.io/v1&lt;br /&gt;&lt;span class=&quot;token key atrule&quot;&gt;kind&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; HelmRepository&lt;br /&gt;&lt;span class=&quot;token key atrule&quot;&gt;metadata&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token key atrule&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; strrl&lt;br /&gt;  &lt;span class=&quot;token key atrule&quot;&gt;namespace&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; flux&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;system&lt;br /&gt;&lt;span class=&quot;token key atrule&quot;&gt;spec&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token key atrule&quot;&gt;interval&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; 1m0s&lt;br /&gt;  &lt;span class=&quot;token key atrule&quot;&gt;url&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; https&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;//helm.strrl.dev&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;And don’t forget to add the new resources to existing kustomizations:&lt;/p&gt;
&lt;h4&gt;/infrastructure/production/kustomization.yaml&lt;/h4&gt;
&lt;pre class=&quot;language-yaml&quot;&gt;&lt;code class=&quot;language-yaml&quot;&gt;&lt;span class=&quot;token key atrule&quot;&gt;apiVersion&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; kustomize.config.k8s.io/v1beta1&lt;br /&gt;&lt;span class=&quot;token key atrule&quot;&gt;kind&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; Kustomization&lt;br /&gt;&lt;span class=&quot;token key atrule&quot;&gt;resources&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; cert&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;manager.yaml&lt;br /&gt;  &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; cluster&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;issuer.yaml&lt;br /&gt;  &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; metallb.yaml&lt;br /&gt;  &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; metallb&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;config.yaml&lt;br /&gt;  &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; ingress&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;nginx.yaml&lt;br /&gt;  &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; cf&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;tunnel&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;ingress.yaml&lt;/code&gt;&lt;/pre&gt;
&lt;h4&gt;/repos/kustomization.yaml&lt;/h4&gt;
&lt;pre class=&quot;language-yaml&quot;&gt;&lt;code class=&quot;language-yaml&quot;&gt;&lt;span class=&quot;token key atrule&quot;&gt;apiVersion&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; kustomize.config.k8s.io/v1beta1&lt;br /&gt;&lt;span class=&quot;token key atrule&quot;&gt;kind&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; Kustomization&lt;br /&gt;&lt;span class=&quot;token key atrule&quot;&gt;resources&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; podinfo.yaml&lt;br /&gt;  &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; jetstack.yaml&lt;br /&gt;  &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; truecharts.yaml&lt;br /&gt;  &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; metallb.yaml&lt;br /&gt;  &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; ingress&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;nginx.yaml&lt;br /&gt;  &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; strrl.yaml&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;Test &amp;amp; Verify&lt;/h2&gt;
&lt;p&gt;Once the CF-Tunnel helm chart is installed, it will create a new ingress class just like NGINX did. Use kubectl to check for it:&lt;br /&gt;
Make sure the ingressclass exists:&lt;/p&gt;
&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;$ kubectl get ingressclasses.networking.k8s.io &lt;br /&gt;NAME         CONTROLLER                                       PARAMETERS   AGE&lt;br /&gt;cloudflare   strrl.dev/cloudflare-tunnel-ingress-controller   &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;none&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;       8m12s&lt;br /&gt;internal     k8s.io/internal                                  &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;none&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;       5d2h&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;To test it out, you can append an additional ingress definition on apps/general/podinfo/ingress.yaml&lt;/p&gt;
&lt;pre class=&quot;language-yaml&quot;&gt;&lt;code class=&quot;language-yaml&quot;&gt;&lt;span class=&quot;token key atrule&quot;&gt;apiVersion&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; networking.k8s.io/v1&lt;br /&gt;&lt;span class=&quot;token key atrule&quot;&gt;kind&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; Ingress&lt;br /&gt;&lt;span class=&quot;token key atrule&quot;&gt;metadata&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token key atrule&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; podinfo&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;nginx&lt;br /&gt;  &lt;span class=&quot;token key atrule&quot;&gt;namespace&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; podinfo&lt;br /&gt;&lt;span class=&quot;token key atrule&quot;&gt;spec&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token key atrule&quot;&gt;ingressClassName&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; internal&lt;br /&gt;  &lt;span class=&quot;token key atrule&quot;&gt;rules&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token key atrule&quot;&gt;host&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; podinfo.$&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;DOMAIN_0&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token key atrule&quot;&gt;http&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;      &lt;span class=&quot;token key atrule&quot;&gt;paths&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;      &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token key atrule&quot;&gt;backend&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;          &lt;span class=&quot;token key atrule&quot;&gt;service&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;            &lt;span class=&quot;token key atrule&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; podinfo&lt;br /&gt;            &lt;span class=&quot;token key atrule&quot;&gt;port&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;              &lt;span class=&quot;token key atrule&quot;&gt;number&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;9898&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token key atrule&quot;&gt;path&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; /&lt;br /&gt;        &lt;span class=&quot;token key atrule&quot;&gt;pathType&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; Prefix&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;---&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token key atrule&quot;&gt;apiVersion&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; networking.k8s.io/v1&lt;br /&gt;&lt;span class=&quot;token key atrule&quot;&gt;kind&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; Ingress&lt;br /&gt;&lt;span class=&quot;token key atrule&quot;&gt;metadata&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token key atrule&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; podinfo&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;cloudflare&lt;br /&gt;  &lt;span class=&quot;token key atrule&quot;&gt;namespace&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; podinfo&lt;br /&gt;&lt;span class=&quot;token key atrule&quot;&gt;spec&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token key atrule&quot;&gt;ingressClassName&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; cloudflare&lt;br /&gt;  &lt;span class=&quot;token key atrule&quot;&gt;rules&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token key atrule&quot;&gt;host&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; podinfo.$&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;DOMAIN_0&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token key atrule&quot;&gt;http&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;      &lt;span class=&quot;token key atrule&quot;&gt;paths&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;      &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token key atrule&quot;&gt;backend&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;          &lt;span class=&quot;token key atrule&quot;&gt;service&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;            &lt;span class=&quot;token key atrule&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; podinfo&lt;br /&gt;            &lt;span class=&quot;token key atrule&quot;&gt;port&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;              &lt;span class=&quot;token key atrule&quot;&gt;number&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;9898&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token key atrule&quot;&gt;path&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; /&lt;br /&gt;        &lt;span class=&quot;token key atrule&quot;&gt;pathType&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; Prefix&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Commit that and inspect the results:&lt;/p&gt;
&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;$ &lt;span class=&quot;token function&quot;&gt;git&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;add&lt;/span&gt; &lt;span class=&quot;token parameter variable&quot;&gt;-A&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;git&lt;/span&gt; commit &lt;span class=&quot;token parameter variable&quot;&gt;-m&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;add podinfo cf ingress&#39;&lt;/span&gt;&lt;br /&gt;$ &lt;span class=&quot;token function&quot;&gt;git&lt;/span&gt; push&lt;br /&gt;$ flux events &lt;span class=&quot;token parameter variable&quot;&gt;--watch&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;inspect any ingress rules create for podinfo:&lt;/p&gt;
&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;$ kubectl get ingress &lt;span class=&quot;token parameter variable&quot;&gt;-n&lt;/span&gt; podinfo &lt;br /&gt;NAME                 CLASS        HOSTS             ADDRESS                                                 PORTS   AGE&lt;br /&gt;podinfo-cloudflare   cloudflare   podinfo.domain.tld   9a6bc2e4-8c73-40a9-b5a3-5ddd0d937f29.cfargotunnel.com   &lt;span class=&quot;token number&quot;&gt;80&lt;/span&gt;      29s&lt;br /&gt;podinfo-nginx        internal     podinfo.domain.tld   &lt;span class=&quot;token number&quot;&gt;192.168&lt;/span&gt;.XX.200                                         &lt;span class=&quot;token number&quot;&gt;80&lt;/span&gt;      5d1h&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;If everything looks good, test it out by accessing it remotely. When you’re all done, this would be a good time to delete your test deployment - you don’t need to put podinfo on the internet with your name attached to it. Just delete the following files, and remove the podinfo reference from /apps/production/kustomization.yaml&lt;/p&gt;
&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;truek8s&lt;br /&gt;├── apps&lt;br /&gt;   ├── general&lt;br /&gt;   │   └── podinfo *&lt;br /&gt;   │       ├── helm-release.yaml *&lt;br /&gt;   │       ├── ingress.yaml *&lt;br /&gt;   │       ├── kustomization.yaml * &lt;br /&gt;   │       └── namespace.yaml *&lt;br /&gt;   └── production&lt;br /&gt;       └── podinfo.yaml *&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;Zero Trust with Cloudflare.&lt;/h2&gt;
&lt;p&gt;Exposing services through Cloudflare is only a little bit better than exposing them through your own firewall. To really make things interesting, you should configure Cloudflare Zero Trust rules. That’s not within the scope of what I want to do with this guide, but I would like to cover it in more depth on this blog later.&lt;/p&gt;
&lt;p&gt;In my case, I’m hosting Authentik, and use it as an OIDC provider for Cloudflare. I have some custom rules set up to pass authorization access to Cloudflare. Whenever I (or anyone) access one of the apps in my cluster, they first have to provide strong authentication through Cloudflare, which significantly reduces the risk of unauthorized access.&lt;/p&gt;
&lt;h2&gt;Sources&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/STRRL/cloudflare-tunnel-ingress-controller&quot;&gt;Github: strrl cloudflare-tunnel-ingress-controller.&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://developers.cloudflare.com/fundamentals/setup/find-account-and-zone-ids/&quot;&gt;Cloudflare: find account and zone ids.&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.cloudflare.com/zero-trust/products/access/&quot;&gt;Cloudflare: Zero Trust&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
</content>
    </entry>
    
    <entry>
      <title>TrueK8S Part 07</title>
      <link href="http://localhost:8080/2025/05/15/truek8s-part-07/"/>
      <updated>2025-05-15T12:30:00Z</updated>
      <id>http://localhost:8080/2025/05/15/truek8s-part-07/</id>
      <content type="html">&lt;h1&gt;Deploying LongHorn to our Kubernetes cluster&lt;/h1&gt;
&lt;p&gt;I learned a hard lesson about making good choices regarding storage for your kubernetes cluster. In early attempts at building my cluster I tried using an ‘nfs-subdir’ provider that provided pod volume storage backed by a local NFS server. This seemed easy and made good sense to me at the time. In practice, the I/O was so bad that many deployments failed due to enormous storage latency. Not only did it perform poorly, that storage provider also didn’t provide the snapshot mechanism that we’ll need for VolSync (up next). So take it from me, you need a good storage provider that provides features, flexibility, and good performance.&lt;/p&gt;
&lt;p&gt;I chose longhorn as the storage provider for my cluster, mainly because there were plenty of examples around longhorn configuration in the TrueCharts community for me to follow. Longhorn allows us to utilize direct attached storage on our worker nodes for high performance, and also provides the volume snapshot features that we’ll need in the next post. You may remember back in part 1 of this guide, I referenced storage for our cluster members and some necessary extensions for TalosOS. If you skipped around, go back to part 1 and make sure that you have the util-linux-tools and iscsi-tools extensions configured.&lt;/p&gt;
&lt;h2&gt;Deploying LongHorn&lt;/h2&gt;
&lt;p&gt;You should know the drill by now. Here are the deployment resources. Once again we’ll create a kustomization to deploy longhorn, and then a separate one to configure it. I chose to do it this way because I want to explicitly wait for the longhorn UI to be online before trying to assign ingress to it, which can cause issues in re-deployment scenarios.&lt;/p&gt;
&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;truek8s&lt;br /&gt;├── infrastructure&lt;br /&gt;│ ├── core&lt;br /&gt;│ │ ├── longhorn&lt;br /&gt;│ │ │ ├── helm-release.yaml&lt;br /&gt;│ │ │ ├── kustomization.yaml&lt;br /&gt;│ │ │ ├── namespace.yaml&lt;br /&gt;│ │ ├── longhorn-config&lt;br /&gt;│ │   ├── ingress.yaml&lt;br /&gt;│ │   └── kustomization.yaml&lt;br /&gt;│ └── production&lt;br /&gt;│     └── longhorn.yaml&lt;br /&gt;└── repos&lt;br /&gt;    ├── longhorn.yaml&lt;br /&gt;    └── longhorn-config.yaml&lt;br /&gt;&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;./repos&lt;/h3&gt;
&lt;h4&gt;longhorn.yaml&lt;/h4&gt;
&lt;pre class=&quot;language-yaml&quot;&gt;&lt;code class=&quot;language-yaml&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;---&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token key atrule&quot;&gt;apiVersion&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; source.toolkit.fluxcd.io/v1&lt;br /&gt;&lt;span class=&quot;token key atrule&quot;&gt;kind&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; HelmRepository&lt;br /&gt;&lt;span class=&quot;token key atrule&quot;&gt;metadata&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token key atrule&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; longhorn&lt;br /&gt;  &lt;span class=&quot;token key atrule&quot;&gt;namespace&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; flux&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;system&lt;br /&gt;&lt;span class=&quot;token key atrule&quot;&gt;spec&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token key atrule&quot;&gt;interval&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; 2h&lt;br /&gt;  &lt;span class=&quot;token key atrule&quot;&gt;url&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; https&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;//charts.longhorn.io&lt;/code&gt;&lt;/pre&gt;
&lt;h4&gt;kustomization.yaml&lt;/h4&gt;
&lt;p&gt;Add this new manifest to the repos kustomization.&lt;/p&gt;
&lt;pre class=&quot;language-yaml&quot;&gt;&lt;code class=&quot;language-yaml&quot;&gt;&lt;span class=&quot;token key atrule&quot;&gt;apiVersion&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; kustomize.config.k8s.io/v1beta1&lt;br /&gt;&lt;span class=&quot;token key atrule&quot;&gt;kind&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; Kustomization&lt;br /&gt;&lt;span class=&quot;token key atrule&quot;&gt;resources&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; longhorn.yaml&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;./infrastructure/core/longhorn&lt;/h3&gt;
&lt;h4&gt;namespace.yaml&lt;/h4&gt;
&lt;pre class=&quot;language-yaml&quot;&gt;&lt;code class=&quot;language-yaml&quot;&gt;&lt;span class=&quot;token key atrule&quot;&gt;apiVersion&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; v1&lt;br /&gt;&lt;span class=&quot;token key atrule&quot;&gt;kind&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; Namespace&lt;br /&gt;&lt;span class=&quot;token key atrule&quot;&gt;metadata&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token key atrule&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; longhorn&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;system&lt;br /&gt;    &lt;span class=&quot;token key atrule&quot;&gt;labels&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token key atrule&quot;&gt;pod-security.kubernetes.io/enforce&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; privileged&lt;/code&gt;&lt;/pre&gt;
&lt;h4&gt;helm-release.yaml&lt;/h4&gt;
&lt;pre class=&quot;language-yaml&quot;&gt;&lt;code class=&quot;language-yaml&quot;&gt;&lt;span class=&quot;token key atrule&quot;&gt;apiVersion&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; helm.toolkit.fluxcd.io/v2&lt;br /&gt;&lt;span class=&quot;token key atrule&quot;&gt;kind&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; HelmRelease&lt;br /&gt;&lt;span class=&quot;token key atrule&quot;&gt;metadata&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token key atrule&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; longhorn&lt;br /&gt;    &lt;span class=&quot;token key atrule&quot;&gt;namespace&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; longhorn&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;system&lt;br /&gt;&lt;span class=&quot;token key atrule&quot;&gt;spec&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token key atrule&quot;&gt;interval&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; 5m&lt;br /&gt;    &lt;span class=&quot;token key atrule&quot;&gt;releaseName&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; longhorn&lt;br /&gt;    &lt;span class=&quot;token key atrule&quot;&gt;chart&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token key atrule&quot;&gt;spec&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;            &lt;span class=&quot;token key atrule&quot;&gt;chart&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; longhorn&lt;br /&gt;            &lt;span class=&quot;token key atrule&quot;&gt;sourceRef&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;                &lt;span class=&quot;token key atrule&quot;&gt;kind&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; HelmRepository&lt;br /&gt;                &lt;span class=&quot;token key atrule&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; longhorn&lt;br /&gt;                &lt;span class=&quot;token key atrule&quot;&gt;namespace&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; flux&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;system&lt;br /&gt;    &lt;span class=&quot;token key atrule&quot;&gt;install&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token key atrule&quot;&gt;createNamespace&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean important&quot;&gt;true&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token key atrule&quot;&gt;crds&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; CreateReplace&lt;br /&gt;        &lt;span class=&quot;token key atrule&quot;&gt;remediation&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;            &lt;span class=&quot;token key atrule&quot;&gt;retries&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;3&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token key atrule&quot;&gt;upgrade&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token key atrule&quot;&gt;crds&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; CreateReplace&lt;br /&gt;        &lt;span class=&quot;token key atrule&quot;&gt;remediation&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;            &lt;span class=&quot;token key atrule&quot;&gt;retries&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;3&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token key atrule&quot;&gt;values&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token key atrule&quot;&gt;defaultSettings&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;            &lt;span class=&quot;token comment&quot;&gt;# Increase to 3 for a multi-node cluster&lt;/span&gt;&lt;br /&gt;            &lt;span class=&quot;token key atrule&quot;&gt;defaultReplicaCount&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;br /&gt;            &lt;span class=&quot;token comment&quot;&gt;# Overprovisioning might be needed when using volsync&lt;/span&gt;&lt;br /&gt;            &lt;span class=&quot;token key atrule&quot;&gt;storageOverProvisioningPercentage&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;100000&lt;/span&gt;&lt;br /&gt;            &lt;span class=&quot;token key atrule&quot;&gt;storageReservedPercentageForDefaultDisk&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;10&lt;/span&gt;&lt;br /&gt;            &lt;span class=&quot;token comment&quot;&gt;# v2DataEngine: true&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token key atrule&quot;&gt;csi&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;            &lt;span class=&quot;token key atrule&quot;&gt;attacherReplicaCount&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;br /&gt;            &lt;span class=&quot;token key atrule&quot;&gt;provisionerReplicaCount&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;br /&gt;            &lt;span class=&quot;token key atrule&quot;&gt;resizerReplicaCount&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;br /&gt;            &lt;span class=&quot;token key atrule&quot;&gt;snapshotterReplicaCount&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token key atrule&quot;&gt;persistence&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;            &lt;span class=&quot;token comment&quot;&gt;# Set to false to pick another CSI as default&lt;/span&gt;&lt;br /&gt;            &lt;span class=&quot;token key atrule&quot;&gt;defaultClass&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean important&quot;&gt;true&lt;/span&gt;&lt;br /&gt;            &lt;span class=&quot;token comment&quot;&gt;# Increase to 3 for a multi-node cluster&lt;/span&gt;&lt;br /&gt;            &lt;span class=&quot;token key atrule&quot;&gt;defaultClassReplicaCount&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token key atrule&quot;&gt;longhornUI&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;            &lt;span class=&quot;token key atrule&quot;&gt;replicas&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;./infrastructure/core/longhorn-config&lt;/h3&gt;
&lt;h4&gt;ingress.yaml&lt;/h4&gt;
&lt;pre class=&quot;language-yaml&quot;&gt;&lt;code class=&quot;language-yaml&quot;&gt;&lt;span class=&quot;token key atrule&quot;&gt;apiVersion&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; networking.k8s.io/v1&lt;br /&gt;&lt;span class=&quot;token key atrule&quot;&gt;kind&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; Ingress&lt;br /&gt;&lt;span class=&quot;token key atrule&quot;&gt;metadata&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token key atrule&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; longhorn&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;nginx&lt;br /&gt;  &lt;span class=&quot;token key atrule&quot;&gt;namespace&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; longhorn&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;system&lt;br /&gt;&lt;span class=&quot;token key atrule&quot;&gt;spec&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token key atrule&quot;&gt;ingressClassName&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; internal&lt;br /&gt;  &lt;span class=&quot;token key atrule&quot;&gt;rules&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token key atrule&quot;&gt;host&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; longhorn.$&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;DOMAIN_0&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token key atrule&quot;&gt;http&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;      &lt;span class=&quot;token key atrule&quot;&gt;paths&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;      &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token key atrule&quot;&gt;backend&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;          &lt;span class=&quot;token key atrule&quot;&gt;service&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;            &lt;span class=&quot;token key atrule&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; longhorn&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;frontend&lt;br /&gt;            &lt;span class=&quot;token key atrule&quot;&gt;port&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;              &lt;span class=&quot;token key atrule&quot;&gt;number&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;80&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token key atrule&quot;&gt;path&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; /&lt;br /&gt;        &lt;span class=&quot;token key atrule&quot;&gt;pathType&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; Prefix&lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;kustomization.yaml&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&quot;language-yaml&quot;&gt;&lt;code class=&quot;language-yaml&quot;&gt;&lt;span class=&quot;token key atrule&quot;&gt;apiVersion&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; kustomize.config.k8s.io/v1beta1&lt;br /&gt;&lt;span class=&quot;token key atrule&quot;&gt;kind&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; Kustomization&lt;br /&gt;&lt;span class=&quot;token key atrule&quot;&gt;resources&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; ingress.yaml&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;./infrastructure/production&lt;/h3&gt;
&lt;p&gt;The order of operations here is to first install longhorn, then use separate kustomization to configure the ingress once longhorn and nginx are both configured.&lt;/p&gt;
&lt;h4&gt;/infrastructure/production/longhorn.yaml&lt;/h4&gt;
&lt;pre class=&quot;language-yaml&quot;&gt;&lt;code class=&quot;language-yaml&quot;&gt;&lt;span class=&quot;token key atrule&quot;&gt;apiVersion&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; kustomize.toolkit.fluxcd.io/v1&lt;br /&gt;&lt;span class=&quot;token key atrule&quot;&gt;kind&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; Kustomization&lt;br /&gt;&lt;span class=&quot;token key atrule&quot;&gt;metadata&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token key atrule&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; longhorn&lt;br /&gt;  &lt;span class=&quot;token key atrule&quot;&gt;namespace&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; flux&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;system&lt;br /&gt;&lt;span class=&quot;token key atrule&quot;&gt;spec&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token key atrule&quot;&gt;interval&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; 10m&lt;br /&gt;  &lt;span class=&quot;token key atrule&quot;&gt;path&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; infrastructure/core/longhorn&lt;br /&gt;  &lt;span class=&quot;token key atrule&quot;&gt;prune&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean important&quot;&gt;true&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token key atrule&quot;&gt;sourceRef&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token key atrule&quot;&gt;kind&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; GitRepository&lt;br /&gt;    &lt;span class=&quot;token key atrule&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; flux&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;system&lt;/code&gt;&lt;/pre&gt;
&lt;h4&gt;/infrastructure/production/longhorn-config.yaml&lt;/h4&gt;
&lt;p&gt;Note the dependsOn configuration of this kustomization.&lt;/p&gt;
&lt;pre class=&quot;language-yaml&quot;&gt;&lt;code class=&quot;language-yaml&quot;&gt;&lt;span class=&quot;token key atrule&quot;&gt;apiVersion&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; kustomize.toolkit.fluxcd.io/v1&lt;br /&gt;&lt;span class=&quot;token key atrule&quot;&gt;kind&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; Kustomization&lt;br /&gt;&lt;span class=&quot;token key atrule&quot;&gt;metadata&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token key atrule&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; longhorn&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;config&lt;br /&gt;  &lt;span class=&quot;token key atrule&quot;&gt;namespace&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; flux&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;system&lt;br /&gt;&lt;span class=&quot;token key atrule&quot;&gt;spec&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token key atrule&quot;&gt;dependsOn&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token key atrule&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; ingress&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;nginx&lt;br /&gt;    &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token key atrule&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; longhorn&lt;br /&gt;  &lt;span class=&quot;token key atrule&quot;&gt;interval&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; 10m&lt;br /&gt;  &lt;span class=&quot;token key atrule&quot;&gt;path&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; infrastructure/core/longhorn&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;config&lt;br /&gt;  &lt;span class=&quot;token key atrule&quot;&gt;prune&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean important&quot;&gt;true&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token key atrule&quot;&gt;sourceRef&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token key atrule&quot;&gt;kind&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; GitRepository&lt;br /&gt;    &lt;span class=&quot;token key atrule&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; flux&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;system&lt;/code&gt;&lt;/pre&gt;
&lt;h4&gt;/infrastructure/production/kustomization.yaml&lt;/h4&gt;
&lt;p&gt;And add these new manifests to the production kustomization&lt;/p&gt;
&lt;pre class=&quot;language-yaml&quot;&gt;&lt;code class=&quot;language-yaml&quot;&gt;&lt;span class=&quot;token key atrule&quot;&gt;apiVersion&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; kustomize.config.k8s.io/v1beta1&lt;br /&gt;&lt;span class=&quot;token key atrule&quot;&gt;kind&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; Kustomization&lt;br /&gt;&lt;span class=&quot;token key atrule&quot;&gt;resources&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; longhorn.yaml&lt;br /&gt;  &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; longhorn&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;config.yaml&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Finally, commit your changes and watch flux as it reconciles the changes.&lt;/p&gt;
&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;token function&quot;&gt;git&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;add&lt;/span&gt; &lt;span class=&quot;token parameter variable&quot;&gt;-A&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;git&lt;/span&gt; commit &lt;span class=&quot;token parameter variable&quot;&gt;-m&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;add longhorn&quot;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token function&quot;&gt;git&lt;/span&gt; push&lt;br /&gt;&lt;br /&gt;flux events &lt;span class=&quot;token parameter variable&quot;&gt;--watch&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;Verify longhorn&lt;/h2&gt;
&lt;p&gt;Check everything over using flux, helm, and kubectl like we did in previous steps. You should see quite a few resources created by the longhorn helm-release. You can inspect those with kubectl to understand what all it’s doing. You should also have new storage classes created by longhorn.&lt;/p&gt;
&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;$ flux get hr longhorn &lt;span class=&quot;token parameter variable&quot;&gt;-n&lt;/span&gt; longhorn-system&lt;br /&gt;NAME            REVISION        SUSPENDED       READY   MESSAGE                                                                                  &lt;br /&gt;longhorn        &lt;span class=&quot;token number&quot;&gt;1.9&lt;/span&gt;.0           False           True    Helm &lt;span class=&quot;token function&quot;&gt;install&lt;/span&gt; succeeded &lt;span class=&quot;token keyword&quot;&gt;for&lt;/span&gt; release longhorn-system/longhorn.v1 with chart longhorn@1.9.0&lt;br /&gt;&lt;br /&gt;$ flux tree ks longhorn&lt;br /&gt;Kustomization/flux-system/longhorn&lt;br /&gt;├── Namespace/longhorn-system&lt;br /&gt;└── HelmRelease/longhorn-system/longhorn&lt;br /&gt;    ├── PriorityClass/longhorn-critical&lt;br /&gt;    ├── ServiceAccount/longhorn-system/longhorn-service-account&lt;br /&gt;    ├── ServiceAccount/longhorn-system/longhorn-ui-service-account&lt;br /&gt;    ├── ServiceAccount/longhorn-system/longhorn-support-bundle&lt;br /&gt;    ├── ConfigMap/longhorn-system/longhorn-default-resource&lt;br /&gt;    ├── ConfigMap/longhorn-system/longhorn-default-setting&lt;br /&gt;    ├── ConfigMap/longhorn-system/longhorn-storageclass&lt;br /&gt;    ├── CustomResourceDefinition/backingimagedatasources.longhorn.io&lt;br /&gt;    ├── CustomResourceDefinition/backingimagemanagers.longhorn.io&lt;br /&gt;    ├── CustomResourceDefinition/backingimages.longhorn.io&lt;br /&gt;    ├── CustomResourceDefinition/backupbackingimages.longhorn.io&lt;br /&gt;    ├── CustomResourceDefinition/backups.longhorn.io&lt;br /&gt;    ├── CustomResourceDefinition/backuptargets.longhorn.io&lt;br /&gt;    ├── CustomResourceDefinition/backupvolumes.longhorn.io&lt;br /&gt;    ├── CustomResourceDefinition/engineimages.longhorn.io&lt;br /&gt;    ├── CustomResourceDefinition/engines.longhorn.io&lt;br /&gt;    ├── CustomResourceDefinition/instancemanagers.longhorn.io&lt;br /&gt;    ├── CustomResourceDefinition/nodes.longhorn.io&lt;br /&gt;    ├── CustomResourceDefinition/orphans.longhorn.io&lt;br /&gt;    ├── CustomResourceDefinition/recurringjobs.longhorn.io&lt;br /&gt;    ├── CustomResourceDefinition/replicas.longhorn.io&lt;br /&gt;    ├── CustomResourceDefinition/settings.longhorn.io&lt;br /&gt;    ├── CustomResourceDefinition/sharemanagers.longhorn.io&lt;br /&gt;    ├── CustomResourceDefinition/snapshots.longhorn.io&lt;br /&gt;    ├── CustomResourceDefinition/supportbundles.longhorn.io&lt;br /&gt;    ├── CustomResourceDefinition/systembackups.longhorn.io&lt;br /&gt;    ├── CustomResourceDefinition/systemrestores.longhorn.io&lt;br /&gt;    ├── CustomResourceDefinition/volumeattachments.longhorn.io&lt;br /&gt;    ├── CustomResourceDefinition/volumes.longhorn.io&lt;br /&gt;    ├── ClusterRole/longhorn-role&lt;br /&gt;    ├── ClusterRoleBinding/longhorn-bind&lt;br /&gt;    ├── ClusterRoleBinding/longhorn-support-bundle&lt;br /&gt;    ├── Service/longhorn-system/longhorn-backend&lt;br /&gt;    ├── Service/longhorn-system/longhorn-frontend&lt;br /&gt;    ├── Service/longhorn-system/longhorn-conversion-webhook&lt;br /&gt;    ├── Service/longhorn-system/longhorn-admission-webhook&lt;br /&gt;    ├── Service/longhorn-system/longhorn-recovery-backend&lt;br /&gt;    ├── DaemonSet/longhorn-system/longhorn-manager&lt;br /&gt;    ├── Deployment/longhorn-system/longhorn-driver-deployer&lt;br /&gt;    └── Deployment/longhorn-system/longhorn-ui&lt;br /&gt;&lt;br /&gt;$ flux tree ks longhorn-config&lt;br /&gt;Kustomization/flux-system/longhorn-config&lt;br /&gt;└── Ingress/longhorn-system/longhorn-nginx&lt;br /&gt;&lt;br /&gt;$ kubectl get storageclasses.storage.k8s.io &lt;br /&gt;NAME                 PROVISIONER          RECLAIMPOLICY   VOLUMEBINDINGMODE   ALLOWVOLUMEEXPANSION   AGE&lt;br /&gt;longhorn &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;default&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;   driver.longhorn.io   Delete          Immediate           &lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;                   2d9h&lt;br /&gt;longhorn-static      driver.longhorn.io   Delete          Immediate           &lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;                   2d9h&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;If everything goes well, you should be able to reach the longhorn webui at longhorn.yourdomain.tld, and it should even be served using it’s own LE certificate.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;http://localhost:8080/assets/images/2025/05/longhorn-webui.png&quot; alt=&quot;image&quot; /&gt;&lt;br /&gt;
&lt;img src=&quot;http://localhost:8080/assets/images/2025/05/longhorn-webui-cert.png&quot; alt=&quot;image&quot; /&gt;&lt;/p&gt;
&lt;h2&gt;Sources&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://longhorn.io/docs/1.8.1/advanced-resources/os-distro-specific/talos-linux-support/#requirements&quot;&gt;longhorn.io: Talos Linux Support&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://hackmd.io/@QI-AN/Install-Longhorn-on-Talos-Kubernetes#Install-Longhorn-on-Talos-Kubernetes&quot;&gt;hackmd.io: Install Longhorn on Talos Kubernetes&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://calebcoffie.com/part-3-adding-longhorn-for-persistent-storage-on-our-talos-powered-kubernetes-cluster/&quot;&gt;calebcoffie.com: Part 3: Adding Longhorn for Persistent Storage on Our Talos-Powered Kubernetes Cluster&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://kubernetes.io/docs/tasks/tools/&quot;&gt;kubernetes.io: Set up Kubernetes tools on your computer&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
</content>
    </entry>
    
    <entry>
      <title>TrueK8S Part 08</title>
      <link href="http://localhost:8080/2025/11/29/truek8s-part-08/"/>
      <updated>2025-11-29T12:30:00Z</updated>
      <id>http://localhost:8080/2025/11/29/truek8s-part-08/</id>
      <content type="html">&lt;h2&gt;Configuring VolSync and CNPG for Cluster Backup&lt;/h2&gt;
&lt;p&gt;One of the things that always made me a little wary of Kubernetes for the homelab was the overall resiliency. In a more traditional scenario running apps on a VM, you can just snapshot/backup the whole virtual machine and restore everything all at once. I would like to have the peace of mind to know that I can restore my apps and data should something ever go wrong. Moreover, I don’t want the management of those backups to constitute a full-time job (like writing this series has).&lt;/p&gt;
&lt;p&gt;TrueCharts has a solution for that. All of the apps in the TrueCharts project ship with integration for VolSync and cloudnative PostgreSQL, which are mature solutions to providing resiliency in a Kubernetes environment. The TrueCharts common library provides a consistent mechanism I can use to backup and restore my deployments, which is one of the reasons I’m such a fan of the project.&lt;/p&gt;
&lt;p&gt;In this installment, we’ll configure and test our backups before we move on to deploying any workloads or data into our cluster.&lt;/p&gt;
&lt;h2&gt;Configure Secrets&lt;/h2&gt;
&lt;h3&gt;S3 secrets&lt;/h3&gt;
&lt;p&gt;Before we can get started, Volsync and CNPG need somewhere to store the backup data. I chose to use an S3 bucket hosted by Backblaze, but any S3 service should work. We’ll start by generating a credential to access our bucket.&lt;/p&gt;
&lt;p&gt;In Backblaze, you can generate an application key by going to:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Backblaze &amp;gt; side panel &amp;gt; Application Keys&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Add a new application key&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;img src=&quot;http://localhost:8080/assets/images/2025/05/backblaze-application-key.png&quot; alt=&quot;image&quot; /&gt;&lt;/p&gt;
&lt;p&gt;This will give you a Key ID and an application key (Secret). In addition to your key, you will create your own encryption key to encrypt data before it ever goes to the S3 bucket. You can put all three of these in your configmap:&lt;/p&gt;
&lt;pre class=&quot;language-yaml&quot;&gt;&lt;code class=&quot;language-yaml&quot;&gt;&lt;span class=&quot;token key atrule&quot;&gt;apiVersion&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; v1&lt;br /&gt;&lt;span class=&quot;token key atrule&quot;&gt;kind&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; ConfigMap&lt;br /&gt;&lt;span class=&quot;token key atrule&quot;&gt;metadata&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token key atrule&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; cluster&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;config&lt;br /&gt;    &lt;span class=&quot;token key atrule&quot;&gt;namespace&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; flux&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;system&lt;br /&gt;&lt;span class=&quot;token key atrule&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token key atrule&quot;&gt;S3_URL&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;#The URL for your S3 service, e.g. https://s3.us-east-005.backblazeb2.com&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token key atrule&quot;&gt;S3_BUCKET&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;# This is the base bucket name that will be used by all new buckets&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token key atrule&quot;&gt;S3_ACCESS_KEY&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;#The Key ID&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token key atrule&quot;&gt;S3_SECRET_KEY&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;# The application key (Secret)&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token key atrule&quot;&gt;S3_ENCRYPTION_KEY&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;#User defined.&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;If I were you, I would make that encryption key 64+ random characters. Consider storing this key safely. If you lose the key you set here, you lose the ability to decrypt the data in your S3 bucket, and will be paying your s3 provider to host waste bits.&lt;/p&gt;
&lt;p&gt;Make sure to re-encrypt your config map, then push the updates:&lt;/p&gt;
&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;$ sops &lt;span class=&quot;token parameter variable&quot;&gt;-e&lt;/span&gt; &lt;span class=&quot;token parameter variable&quot;&gt;-i&lt;/span&gt; cluster-config.yaml&lt;br /&gt;$ &lt;span class=&quot;token function&quot;&gt;git&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;add&lt;/span&gt; &lt;span class=&quot;token parameter variable&quot;&gt;-A&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;git&lt;/span&gt; commit &lt;span class=&quot;token parameter variable&quot;&gt;-m&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Add secrets&quot;&lt;/span&gt;&lt;br /&gt;$ &lt;span class=&quot;token function&quot;&gt;git&lt;/span&gt; push&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;Installing VolSync and CNPG&lt;/h2&gt;
&lt;p&gt;For this part, we need to configure 5 new kustomizations and their associated resources. This is a lot of content to copy, so I’ll provide the contents of each file in the usual fashion, but I’d also encourage you to check out the resources directly in my git repo. &lt;a href=&quot;https://github.com/bmel343/truek8s&quot;&gt;GitHub - TrueK8s&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;The kustomizations we’ll be creating are:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;cloudnative-pg&lt;/li&gt;
&lt;li&gt;kubernetes-reflector&lt;/li&gt;
&lt;li&gt;snapshot-controller&lt;/li&gt;
&lt;li&gt;volsync&lt;/li&gt;
&lt;li&gt;volsync-config&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;And these are the files we’ll need to create in our repo:&lt;/p&gt;
&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;truek8s&lt;br /&gt;├── infrastructure&lt;br /&gt;│   ├── core&lt;br /&gt;│   │   ├── cloudnative-pg&lt;br /&gt;│   │   │   ├── helm-release.yaml&lt;br /&gt;│   │   │   ├── kustomization.yaml&lt;br /&gt;│   │   │   └── namespace.yaml&lt;br /&gt;│   │   ├── kubernetes-reflector&lt;br /&gt;│   │   │   ├── helm-release.yaml&lt;br /&gt;│   │   │   └── kustomization.yaml&lt;br /&gt;│   │   ├── snapshot-controller&lt;br /&gt;│   │   │   ├── helm-release.yaml&lt;br /&gt;│   │   │   ├── kustomization.yaml&lt;br /&gt;│   │   │   └── namespace.yaml&lt;br /&gt;│   │   ├── volsync&lt;br /&gt;│   │   │   ├── helm-release.yaml&lt;br /&gt;│   │   │   ├── kustomization.yaml&lt;br /&gt;│   │   │   └── namespace.yaml&lt;br /&gt;│   │   └── volsync-config&lt;br /&gt;│   │       ├── kustomization.yaml&lt;br /&gt;│   │       └── volumesnapshotclass.yaml&lt;br /&gt;│   └── production&lt;br /&gt;│       ├── cloudnative-pg.yaml&lt;br /&gt;│       ├── kubernetes-reflector.yaml&lt;br /&gt;│       ├── snapshot-controller.yaml&lt;br /&gt;│       ├── volsync-config.yaml&lt;br /&gt;│       └── volsync.yaml&lt;br /&gt;└── repos&lt;br /&gt;    └── cloudnative-pg.yaml&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;/infrastructure/core/cloudnative-pg&lt;/h3&gt;
&lt;h4&gt;helm-release.yaml&lt;/h4&gt;
&lt;pre class=&quot;language-yaml&quot;&gt;&lt;code class=&quot;language-yaml&quot;&gt;&lt;span class=&quot;token key atrule&quot;&gt;apiVersion&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; helm.toolkit.fluxcd.io/v2&lt;br /&gt;&lt;span class=&quot;token key atrule&quot;&gt;kind&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; HelmRelease&lt;br /&gt;&lt;span class=&quot;token key atrule&quot;&gt;metadata&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token key atrule&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; cloudnative&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;pg&lt;br /&gt;    &lt;span class=&quot;token key atrule&quot;&gt;namespace&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; cloudnative&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;pg&lt;br /&gt;&lt;span class=&quot;token key atrule&quot;&gt;spec&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token key atrule&quot;&gt;interval&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; 5m&lt;br /&gt;    &lt;span class=&quot;token key atrule&quot;&gt;chart&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token key atrule&quot;&gt;spec&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;            &lt;span class=&quot;token key atrule&quot;&gt;chart&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; cloudnative&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;pg&lt;br /&gt;            &lt;span class=&quot;token key atrule&quot;&gt;sourceRef&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;                &lt;span class=&quot;token key atrule&quot;&gt;kind&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; HelmRepository&lt;br /&gt;                &lt;span class=&quot;token key atrule&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; cloudnative&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;pg&lt;br /&gt;                &lt;span class=&quot;token key atrule&quot;&gt;namespace&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; flux&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;system&lt;br /&gt;            &lt;span class=&quot;token key atrule&quot;&gt;interval&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; 5m&lt;br /&gt;    &lt;span class=&quot;token key atrule&quot;&gt;install&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token key atrule&quot;&gt;createNamespace&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean important&quot;&gt;true&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token key atrule&quot;&gt;crds&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; CreateReplace&lt;br /&gt;        &lt;span class=&quot;token key atrule&quot;&gt;remediation&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;            &lt;span class=&quot;token key atrule&quot;&gt;retries&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;3&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token key atrule&quot;&gt;upgrade&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token key atrule&quot;&gt;crds&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; CreateReplace&lt;br /&gt;        &lt;span class=&quot;token key atrule&quot;&gt;remediation&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;            &lt;span class=&quot;token key atrule&quot;&gt;retries&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;3&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token key atrule&quot;&gt;values&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;      &lt;span class=&quot;token key atrule&quot;&gt;crds&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token key atrule&quot;&gt;create&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean important&quot;&gt;true&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h4&gt;kustomization.yaml&lt;/h4&gt;
&lt;pre class=&quot;language-yaml&quot;&gt;&lt;code class=&quot;language-yaml&quot;&gt;&lt;span class=&quot;token key atrule&quot;&gt;apiVersion&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; kustomize.config.k8s.io/v1beta1&lt;br /&gt;&lt;span class=&quot;token key atrule&quot;&gt;kind&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; Kustomization&lt;br /&gt;&lt;span class=&quot;token key atrule&quot;&gt;resources&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; helm&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;release.yaml&lt;br /&gt;  &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; namespace.yaml&lt;/code&gt;&lt;/pre&gt;
&lt;h4&gt;namespace.yaml&lt;/h4&gt;
&lt;pre class=&quot;language-yaml&quot;&gt;&lt;code class=&quot;language-yaml&quot;&gt;&lt;span class=&quot;token key atrule&quot;&gt;apiVersion&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; v1&lt;br /&gt;&lt;span class=&quot;token key atrule&quot;&gt;kind&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; Namespace&lt;br /&gt;&lt;span class=&quot;token key atrule&quot;&gt;metadata&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token key atrule&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; cloudnative&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;pg&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;/infrastructure/core/kubernetes-reflector&lt;/h3&gt;
&lt;h4&gt;helm-release.yaml&lt;/h4&gt;
&lt;pre class=&quot;language-yaml&quot;&gt;&lt;code class=&quot;language-yaml&quot;&gt;&lt;span class=&quot;token key atrule&quot;&gt;apiVersion&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; helm.toolkit.fluxcd.io/v2&lt;br /&gt;&lt;span class=&quot;token key atrule&quot;&gt;kind&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; HelmRelease&lt;br /&gt;&lt;span class=&quot;token key atrule&quot;&gt;metadata&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token key atrule&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; kubernetes&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;reflector&lt;br /&gt;    &lt;span class=&quot;token key atrule&quot;&gt;namespace&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; snapshot&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;controller&lt;br /&gt;&lt;span class=&quot;token key atrule&quot;&gt;spec&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token key atrule&quot;&gt;interval&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; 15m&lt;br /&gt;    &lt;span class=&quot;token key atrule&quot;&gt;chart&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token key atrule&quot;&gt;spec&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;            &lt;span class=&quot;token key atrule&quot;&gt;chart&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; kubernetes&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;reflector&lt;br /&gt;            &lt;span class=&quot;token key atrule&quot;&gt;sourceRef&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;                &lt;span class=&quot;token key atrule&quot;&gt;kind&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; HelmRepository&lt;br /&gt;                &lt;span class=&quot;token key atrule&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; truecharts&lt;br /&gt;                &lt;span class=&quot;token key atrule&quot;&gt;namespace&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; flux&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;system&lt;br /&gt;            &lt;span class=&quot;token key atrule&quot;&gt;interval&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; 15m&lt;br /&gt;    &lt;span class=&quot;token key atrule&quot;&gt;timeout&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; 20m&lt;br /&gt;    &lt;span class=&quot;token key atrule&quot;&gt;maxHistory&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;3&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token key atrule&quot;&gt;driftDetection&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;      &lt;span class=&quot;token key atrule&quot;&gt;mode&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; warn&lt;br /&gt;    &lt;span class=&quot;token key atrule&quot;&gt;install&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token key atrule&quot;&gt;createNamespace&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean important&quot;&gt;true&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token key atrule&quot;&gt;remediation&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;            &lt;span class=&quot;token key atrule&quot;&gt;retries&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;3&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token key atrule&quot;&gt;upgrade&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token key atrule&quot;&gt;cleanupOnFail&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean important&quot;&gt;true&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token key atrule&quot;&gt;remediation&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;            &lt;span class=&quot;token key atrule&quot;&gt;retries&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;3&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token key atrule&quot;&gt;uninstall&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token key atrule&quot;&gt;keepHistory&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean important&quot;&gt;false&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token key atrule&quot;&gt;values&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;      &lt;span class=&quot;token key atrule&quot;&gt;podOptions&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token key atrule&quot;&gt;hostUsers&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean important&quot;&gt;true&lt;/span&gt;&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h4&gt;kustomization.yaml&lt;/h4&gt;
&lt;pre class=&quot;language-yaml&quot;&gt;&lt;code class=&quot;language-yaml&quot;&gt;&lt;span class=&quot;token key atrule&quot;&gt;apiVersion&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; kustomize.config.k8s.io/v1beta1&lt;br /&gt;&lt;span class=&quot;token key atrule&quot;&gt;kind&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; Kustomization&lt;br /&gt;&lt;span class=&quot;token key atrule&quot;&gt;resources&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; helm&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;release.yaml&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;/infrastructure/core/snapshot-controller&lt;/h3&gt;
&lt;h4&gt;helm-release.yaml&lt;/h4&gt;
&lt;pre class=&quot;language-yaml&quot;&gt;&lt;code class=&quot;language-yaml&quot;&gt;&lt;span class=&quot;token key atrule&quot;&gt;apiVersion&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; helm.toolkit.fluxcd.io/v2&lt;br /&gt;&lt;span class=&quot;token key atrule&quot;&gt;kind&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; HelmRelease&lt;br /&gt;&lt;span class=&quot;token key atrule&quot;&gt;metadata&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token key atrule&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; snapshot&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;controller&lt;br /&gt;    &lt;span class=&quot;token key atrule&quot;&gt;namespace&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; snapshot&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;controller&lt;br /&gt;&lt;span class=&quot;token key atrule&quot;&gt;spec&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token key atrule&quot;&gt;interval&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; 5m&lt;br /&gt;    &lt;span class=&quot;token key atrule&quot;&gt;chart&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token key atrule&quot;&gt;spec&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;            &lt;span class=&quot;token key atrule&quot;&gt;chart&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; snapshot&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;controller&lt;br /&gt;            &lt;span class=&quot;token key atrule&quot;&gt;sourceRef&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;                &lt;span class=&quot;token key atrule&quot;&gt;kind&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; HelmRepository&lt;br /&gt;                &lt;span class=&quot;token key atrule&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; truecharts&lt;br /&gt;                &lt;span class=&quot;token key atrule&quot;&gt;namespace&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; flux&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;system&lt;br /&gt;            &lt;span class=&quot;token key atrule&quot;&gt;interval&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; 5m&lt;br /&gt;    &lt;span class=&quot;token key atrule&quot;&gt;install&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token key atrule&quot;&gt;createNamespace&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean important&quot;&gt;true&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token key atrule&quot;&gt;remediation&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;            &lt;span class=&quot;token key atrule&quot;&gt;retries&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;3&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token key atrule&quot;&gt;upgrade&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;      &lt;span class=&quot;token key atrule&quot;&gt;cleanupOnFail&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean important&quot;&gt;true&lt;/span&gt;&lt;br /&gt;      &lt;span class=&quot;token key atrule&quot;&gt;crds&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; CreateReplace&lt;br /&gt;      &lt;span class=&quot;token key atrule&quot;&gt;remediation&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token key atrule&quot;&gt;strategy&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; rollback&lt;br /&gt;        &lt;span class=&quot;token key atrule&quot;&gt;retries&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;3&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token key atrule&quot;&gt;values&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;      &lt;span class=&quot;token key atrule&quot;&gt;metrics&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token key atrule&quot;&gt;main&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;          &lt;span class=&quot;token key atrule&quot;&gt;enabled&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean important&quot;&gt;false&lt;/span&gt;&lt;br /&gt;      &lt;span class=&quot;token key atrule&quot;&gt;podOptions&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token key atrule&quot;&gt;hostUsers&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean important&quot;&gt;true&lt;/span&gt;&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h4&gt;kustomization.yaml&lt;/h4&gt;
&lt;pre class=&quot;language-yaml&quot;&gt;&lt;code class=&quot;language-yaml&quot;&gt;&lt;span class=&quot;token key atrule&quot;&gt;apiVersion&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; kustomize.config.k8s.io/v1beta1&lt;br /&gt;&lt;span class=&quot;token key atrule&quot;&gt;kind&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; Kustomization&lt;br /&gt;&lt;span class=&quot;token key atrule&quot;&gt;resources&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; helm&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;release.yaml&lt;br /&gt;  &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; namespace.yaml&lt;/code&gt;&lt;/pre&gt;
&lt;h4&gt;namespace.yaml&lt;/h4&gt;
&lt;pre class=&quot;language-yaml&quot;&gt;&lt;code class=&quot;language-yaml&quot;&gt;&lt;span class=&quot;token key atrule&quot;&gt;apiVersion&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; v1&lt;br /&gt;&lt;span class=&quot;token key atrule&quot;&gt;kind&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; Namespace&lt;br /&gt;&lt;span class=&quot;token key atrule&quot;&gt;metadata&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token key atrule&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; snapshot&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;controller&lt;br /&gt;    &lt;span class=&quot;token key atrule&quot;&gt;labels&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token key atrule&quot;&gt;pod-security.kubernetes.io/enforce&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; privileged&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;/infrastructure/core/volsync&lt;/h3&gt;
&lt;h4&gt;helm-release.yaml&lt;/h4&gt;
&lt;pre class=&quot;language-yaml&quot;&gt;&lt;code class=&quot;language-yaml&quot;&gt;&lt;span class=&quot;token key atrule&quot;&gt;apiVersion&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; helm.toolkit.fluxcd.io/v2&lt;br /&gt;&lt;span class=&quot;token key atrule&quot;&gt;kind&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; HelmRelease&lt;br /&gt;&lt;span class=&quot;token key atrule&quot;&gt;metadata&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token key atrule&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; volsync&lt;br /&gt;    &lt;span class=&quot;token key atrule&quot;&gt;namespace&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; volsync&lt;br /&gt;&lt;span class=&quot;token key atrule&quot;&gt;spec&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token key atrule&quot;&gt;interval&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; 5m&lt;br /&gt;    &lt;span class=&quot;token key atrule&quot;&gt;chart&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token key atrule&quot;&gt;spec&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;            &lt;span class=&quot;token key atrule&quot;&gt;chart&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; volsync&lt;br /&gt;            &lt;span class=&quot;token key atrule&quot;&gt;sourceRef&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;                &lt;span class=&quot;token key atrule&quot;&gt;kind&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; HelmRepository&lt;br /&gt;                &lt;span class=&quot;token key atrule&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; truecharts&lt;br /&gt;                &lt;span class=&quot;token key atrule&quot;&gt;namespace&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; flux&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;system&lt;br /&gt;            &lt;span class=&quot;token key atrule&quot;&gt;interval&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; 5m&lt;br /&gt;    &lt;span class=&quot;token key atrule&quot;&gt;install&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token key atrule&quot;&gt;createNamespace&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean important&quot;&gt;true&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token key atrule&quot;&gt;remediation&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;            &lt;span class=&quot;token key atrule&quot;&gt;retries&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;3&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token key atrule&quot;&gt;upgrade&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token key atrule&quot;&gt;remediation&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;            &lt;span class=&quot;token key atrule&quot;&gt;retries&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;3&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token key atrule&quot;&gt;values&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;      &lt;span class=&quot;token key atrule&quot;&gt;metrics&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token key atrule&quot;&gt;main&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;          &lt;span class=&quot;token key atrule&quot;&gt;enabled&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean important&quot;&gt;false&lt;/span&gt;&lt;br /&gt;      &lt;span class=&quot;token key atrule&quot;&gt;podOptions&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token key atrule&quot;&gt;hostUsers&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean important&quot;&gt;true&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h4&gt;kustomization.yaml&lt;/h4&gt;
&lt;pre class=&quot;language-yaml&quot;&gt;&lt;code class=&quot;language-yaml&quot;&gt;&lt;span class=&quot;token key atrule&quot;&gt;apiVersion&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; kustomize.config.k8s.io/v1beta1&lt;br /&gt;&lt;span class=&quot;token key atrule&quot;&gt;kind&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; Kustomization&lt;br /&gt;&lt;span class=&quot;token key atrule&quot;&gt;resources&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; helm&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;release.yaml&lt;br /&gt;  &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; namespace.yaml&lt;/code&gt;&lt;/pre&gt;
&lt;h4&gt;namespace.yaml&lt;/h4&gt;
&lt;pre class=&quot;language-yaml&quot;&gt;&lt;code class=&quot;language-yaml&quot;&gt;&lt;span class=&quot;token key atrule&quot;&gt;apiVersion&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; v1&lt;br /&gt;&lt;span class=&quot;token key atrule&quot;&gt;kind&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; Namespace&lt;br /&gt;&lt;span class=&quot;token key atrule&quot;&gt;metadata&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token key atrule&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; volsync&lt;br /&gt;    &lt;span class=&quot;token key atrule&quot;&gt;labels&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token key atrule&quot;&gt;pod-security.kubernetes.io/enforce&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; privileged&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;/infrastructure/core/volsync-config&lt;/h3&gt;
&lt;h4&gt;kustomization.yaml&lt;/h4&gt;
&lt;pre class=&quot;language-yaml&quot;&gt;&lt;code class=&quot;language-yaml&quot;&gt;&lt;span class=&quot;token key atrule&quot;&gt;apiVersion&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; kustomize.config.k8s.io/v1beta1&lt;br /&gt;&lt;span class=&quot;token key atrule&quot;&gt;kind&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; Kustomization&lt;br /&gt;&lt;span class=&quot;token key atrule&quot;&gt;resources&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; volumesnapshotclass.yaml&lt;/code&gt;&lt;/pre&gt;
&lt;h4&gt;volumesnapshotclass.yaml&lt;/h4&gt;
&lt;pre class=&quot;language-yaml&quot;&gt;&lt;code class=&quot;language-yaml&quot;&gt;&lt;span class=&quot;token key atrule&quot;&gt;kind&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; VolumeSnapshotClass&lt;br /&gt;&lt;span class=&quot;token key atrule&quot;&gt;apiVersion&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; snapshot.storage.k8s.io/v1&lt;br /&gt;&lt;span class=&quot;token key atrule&quot;&gt;metadata&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token key atrule&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; longhorn&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;snapshot&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;vsc&lt;br /&gt;  &lt;span class=&quot;token key atrule&quot;&gt;annotations&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token key atrule&quot;&gt;snapshot.storage.kubernetes.io/is-default-class&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;true&#39;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token key atrule&quot;&gt;driver&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; driver.longhorn.io&lt;br /&gt;&lt;span class=&quot;token key atrule&quot;&gt;deletionPolicy&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; Delete&lt;br /&gt;&lt;span class=&quot;token key atrule&quot;&gt;parameters&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token key atrule&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; snap&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;/infrastructure/production&lt;/h3&gt;
&lt;h4&gt;cloudnative-pg.yaml&lt;/h4&gt;
&lt;pre class=&quot;language-yaml&quot;&gt;&lt;code class=&quot;language-yaml&quot;&gt;&lt;span class=&quot;token key atrule&quot;&gt;apiVersion&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; kustomize.toolkit.fluxcd.io/v1&lt;br /&gt;&lt;span class=&quot;token key atrule&quot;&gt;kind&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; Kustomization&lt;br /&gt;&lt;span class=&quot;token key atrule&quot;&gt;metadata&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token key atrule&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; cloudnative&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;pg&lt;br /&gt;  &lt;span class=&quot;token key atrule&quot;&gt;namespace&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; flux&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;system&lt;br /&gt;&lt;span class=&quot;token key atrule&quot;&gt;spec&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token key atrule&quot;&gt;dependsOn&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token key atrule&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; longhorn&lt;br /&gt;  &lt;span class=&quot;token key atrule&quot;&gt;interval&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; 10m&lt;br /&gt;  &lt;span class=&quot;token key atrule&quot;&gt;path&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; infrastructure/core/cloudnative&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;pg&lt;br /&gt;  &lt;span class=&quot;token key atrule&quot;&gt;prune&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean important&quot;&gt;true&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token key atrule&quot;&gt;sourceRef&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token key atrule&quot;&gt;kind&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; GitRepository&lt;br /&gt;    &lt;span class=&quot;token key atrule&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; flux&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;system&lt;/code&gt;&lt;/pre&gt;
&lt;h4&gt;kubernetes-reflector.yaml&lt;/h4&gt;
&lt;pre class=&quot;language-yaml&quot;&gt;&lt;code class=&quot;language-yaml&quot;&gt;&lt;span class=&quot;token key atrule&quot;&gt;apiVersion&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; kustomize.toolkit.fluxcd.io/v1&lt;br /&gt;&lt;span class=&quot;token key atrule&quot;&gt;kind&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; Kustomization&lt;br /&gt;&lt;span class=&quot;token key atrule&quot;&gt;metadata&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token key atrule&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; kubernetes&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;reflector&lt;br /&gt;  &lt;span class=&quot;token key atrule&quot;&gt;namespace&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; flux&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;system&lt;br /&gt;&lt;span class=&quot;token key atrule&quot;&gt;spec&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token key atrule&quot;&gt;dependsOn&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token key atrule&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; snapshot&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;controller&lt;br /&gt;  &lt;span class=&quot;token key atrule&quot;&gt;interval&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; 10m&lt;br /&gt;  &lt;span class=&quot;token key atrule&quot;&gt;path&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; infrastructure/core/kubernetes&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;reflector&lt;br /&gt;  &lt;span class=&quot;token key atrule&quot;&gt;prune&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean important&quot;&gt;true&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token key atrule&quot;&gt;sourceRef&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token key atrule&quot;&gt;kind&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; GitRepository&lt;br /&gt;    &lt;span class=&quot;token key atrule&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; flux&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;system&lt;/code&gt;&lt;/pre&gt;
&lt;h4&gt;snapshot-controller.yaml&lt;/h4&gt;
&lt;pre class=&quot;language-yaml&quot;&gt;&lt;code class=&quot;language-yaml&quot;&gt;&lt;span class=&quot;token key atrule&quot;&gt;apiVersion&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; kustomize.toolkit.fluxcd.io/v1&lt;br /&gt;&lt;span class=&quot;token key atrule&quot;&gt;kind&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; Kustomization&lt;br /&gt;&lt;span class=&quot;token key atrule&quot;&gt;metadata&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token key atrule&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; snapshot&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;controller&lt;br /&gt;  &lt;span class=&quot;token key atrule&quot;&gt;namespace&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; flux&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;system&lt;br /&gt;&lt;span class=&quot;token key atrule&quot;&gt;spec&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token key atrule&quot;&gt;dependsOn&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token key atrule&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; longhorn&lt;br /&gt;  &lt;span class=&quot;token key atrule&quot;&gt;interval&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; 10m&lt;br /&gt;  &lt;span class=&quot;token key atrule&quot;&gt;path&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; infrastructure/core/snapshot&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;controller&lt;br /&gt;  &lt;span class=&quot;token key atrule&quot;&gt;prune&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean important&quot;&gt;true&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token key atrule&quot;&gt;sourceRef&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token key atrule&quot;&gt;kind&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; GitRepository&lt;br /&gt;    &lt;span class=&quot;token key atrule&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; flux&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;system&lt;/code&gt;&lt;/pre&gt;
&lt;h4&gt;volsync-config.yaml&lt;/h4&gt;
&lt;pre class=&quot;language-yaml&quot;&gt;&lt;code class=&quot;language-yaml&quot;&gt;&lt;span class=&quot;token key atrule&quot;&gt;apiVersion&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; kustomize.toolkit.fluxcd.io/v1&lt;br /&gt;&lt;span class=&quot;token key atrule&quot;&gt;kind&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; Kustomization&lt;br /&gt;&lt;span class=&quot;token key atrule&quot;&gt;metadata&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token key atrule&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; volsync&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;config&lt;br /&gt;  &lt;span class=&quot;token key atrule&quot;&gt;namespace&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; flux&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;system&lt;br /&gt;&lt;span class=&quot;token key atrule&quot;&gt;spec&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token key atrule&quot;&gt;dependsOn&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token key atrule&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; volsync&lt;br /&gt;  &lt;span class=&quot;token key atrule&quot;&gt;interval&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; 10m&lt;br /&gt;  &lt;span class=&quot;token key atrule&quot;&gt;path&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; infrastructure/core/volsync&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;config&lt;br /&gt;  &lt;span class=&quot;token key atrule&quot;&gt;prune&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean important&quot;&gt;true&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token key atrule&quot;&gt;sourceRef&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token key atrule&quot;&gt;kind&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; GitRepository&lt;br /&gt;    &lt;span class=&quot;token key atrule&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; flux&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;system&lt;/code&gt;&lt;/pre&gt;
&lt;h4&gt;volsync.yaml&lt;/h4&gt;
&lt;pre class=&quot;language-yaml&quot;&gt;&lt;code class=&quot;language-yaml&quot;&gt;&lt;span class=&quot;token key atrule&quot;&gt;apiVersion&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; kustomize.toolkit.fluxcd.io/v1&lt;br /&gt;&lt;span class=&quot;token key atrule&quot;&gt;kind&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; Kustomization&lt;br /&gt;&lt;span class=&quot;token key atrule&quot;&gt;metadata&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token key atrule&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; volsync&lt;br /&gt;  &lt;span class=&quot;token key atrule&quot;&gt;namespace&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; flux&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;system&lt;br /&gt;&lt;span class=&quot;token key atrule&quot;&gt;spec&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token key atrule&quot;&gt;dependsOn&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token key atrule&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; snapshot&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;controller&lt;br /&gt;  &lt;span class=&quot;token key atrule&quot;&gt;interval&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; 10m&lt;br /&gt;  &lt;span class=&quot;token key atrule&quot;&gt;path&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; infrastructure/core/volsync&lt;br /&gt;  &lt;span class=&quot;token key atrule&quot;&gt;prune&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean important&quot;&gt;true&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token key atrule&quot;&gt;sourceRef&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token key atrule&quot;&gt;kind&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; GitRepository&lt;br /&gt;    &lt;span class=&quot;token key atrule&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; flux&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;system&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;/repos&lt;/h3&gt;
&lt;h4&gt;cloudnative-pg.yaml&lt;/h4&gt;
&lt;pre class=&quot;language-yaml&quot;&gt;&lt;code class=&quot;language-yaml&quot;&gt;&lt;span class=&quot;token key atrule&quot;&gt;apiVersion&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; source.toolkit.fluxcd.io/v1&lt;br /&gt;&lt;span class=&quot;token key atrule&quot;&gt;kind&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; HelmRepository&lt;br /&gt;&lt;span class=&quot;token key atrule&quot;&gt;metadata&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token key atrule&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; cloudnative&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;pg&lt;br /&gt;  &lt;span class=&quot;token key atrule&quot;&gt;namespace&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; flux&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;system&lt;br /&gt;&lt;span class=&quot;token key atrule&quot;&gt;spec&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token key atrule&quot;&gt;interval&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; 2h&lt;br /&gt;  &lt;span class=&quot;token key atrule&quot;&gt;url&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; https&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;//cloudnative&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;pg.github.io/charts&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Don’t forget to add a reference to each in the production&#92;kustomization file.&lt;/p&gt;
&lt;h3&gt;&lt;/h3&gt;
&lt;p&gt;/infrastructure/production/kustomization.yaml&lt;/p&gt;
&lt;pre class=&quot;language-yaml&quot;&gt;&lt;code class=&quot;language-yaml&quot;&gt;&lt;span class=&quot;token key atrule&quot;&gt;apiVersion&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; kustomize.config.k8s.io/v1beta1&lt;br /&gt;&lt;span class=&quot;token key atrule&quot;&gt;kind&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; Kustomization&lt;br /&gt;&lt;span class=&quot;token key atrule&quot;&gt;resources&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; cert&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;manager.yaml&lt;br /&gt;  &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; cluster&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;issuer.yaml&lt;br /&gt;  &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; metallb.yaml&lt;br /&gt;  &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; metallb&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;config.yaml&lt;br /&gt;  &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; ingress&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;nginx.yaml&lt;br /&gt;  &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; cf&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;tunnel&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;ingress.yaml&lt;br /&gt;  &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; longhorn.yaml&lt;br /&gt;  &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; longhorn&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;config.yaml&lt;br /&gt;  &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; cloudnative&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;pg.yaml&lt;br /&gt;  &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; kubernetes&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;reflector.yaml&lt;br /&gt;  &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; snapshot&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;controller.yaml&lt;br /&gt;  &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; volsync&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;config.yaml&lt;br /&gt;  &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; volsync.yaml&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;/repos/kustomization.yaml&lt;/p&gt;
&lt;pre class=&quot;language-yaml&quot;&gt;&lt;code class=&quot;language-yaml&quot;&gt;&lt;span class=&quot;token key atrule&quot;&gt;apiVersion&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; kustomize.config.k8s.io/v1beta1&lt;br /&gt;&lt;span class=&quot;token key atrule&quot;&gt;kind&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; Kustomization&lt;br /&gt;&lt;span class=&quot;token key atrule&quot;&gt;resources&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; podinfo.yaml&lt;br /&gt;  &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; jetstack.yaml&lt;br /&gt;  &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; truecharts.yaml&lt;br /&gt;  &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; metallb.yaml&lt;br /&gt;  &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; ingress&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;nginx.yaml&lt;br /&gt;  &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; strrl.yaml&lt;br /&gt;  &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; longhorn.yaml&lt;br /&gt;  &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; cloudnative&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;pg.yaml&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;After you’ve created those manifests, go ahead and push them.&lt;/p&gt;
&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;$ &lt;span class=&quot;token function&quot;&gt;git&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;add&lt;/span&gt; &lt;span class=&quot;token parameter variable&quot;&gt;-A&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;git&lt;/span&gt; commit &lt;span class=&quot;token parameter variable&quot;&gt;-m&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Add VolSync and CNPG&quot;&lt;/span&gt;&lt;br /&gt;$ &lt;span class=&quot;token function&quot;&gt;git&lt;/span&gt; push&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;Verify deployment&lt;/h2&gt;
&lt;p&gt;Deploying VolSync and CNPG along with all their requirement components will create quite a few new resources in your cluster. Here are some commands you can use to verify successful deployment.&lt;/p&gt;
&lt;p&gt;Start by checking to make sure the Kustomizations were applied correctly:&lt;/p&gt;
&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;$ flux get ks &lt;br /&gt;NAME                    REVISION                SUSPENDED       READY   MESSAGE                              &lt;br /&gt;apps                    main@sha1:5a540e51      False           True    Applied revision: main@sha1:5a540e51&lt;br /&gt;cert-manager            main@sha1:5a540e51      False           True    Applied revision: main@sha1:5a540e51&lt;br /&gt;cf-tunnel-ingress       main@sha1:5a540e51      False           True    Applied revision: main@sha1:5a540e51&lt;br /&gt;cloudnative-pg          main@sha1:5a540e51      False           True    Applied revision: main@sha1:5a540e51&lt;br /&gt;cluster-issuer          main@sha1:5a540e51      False           True    Applied revision: main@sha1:5a540e51&lt;br /&gt;config                  main@sha1:5a540e51      False           True    Applied revision: main@sha1:5a540e51&lt;br /&gt;flux-system             main@sha1:5a540e51      False           True    Applied revision: main@sha1:5a540e51&lt;br /&gt;infrastructure          main@sha1:5a540e51      False           True    Applied revision: main@sha1:5a540e51&lt;br /&gt;ingress-nginx           main@sha1:5a540e51      False           True    Applied revision: main@sha1:5a540e51&lt;br /&gt;kubernetes-reflector    main@sha1:5a540e51      False           True    Applied revision: main@sha1:5a540e51&lt;br /&gt;longhorn                main@sha1:5a540e51      False           True    Applied revision: main@sha1:5a540e51&lt;br /&gt;longhorn-config         main@sha1:5a540e51      False           True    Applied revision: main@sha1:5a540e51&lt;br /&gt;metallb                 main@sha1:5a540e51      False           True    Applied revision: main@sha1:5a540e51&lt;br /&gt;metallb-config          main@sha1:5a540e51      False           True    Applied revision: main@sha1:5a540e51&lt;br /&gt;repos                   main@sha1:5a540e51      False           True    Applied revision: main@sha1:5a540e51&lt;br /&gt;snapshot-controller     main@sha1:5a540e51      False           True    Applied revision: main@sha1:5a540e51&lt;br /&gt;volsync                 main@sha1:5a540e51      False           True    Applied revision: main@sha1:5a540e51&lt;br /&gt;volsync-config          main@sha1:5a540e51      False           True    Applied revision: main@sha1:5a540e51&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Next make sure that the custom API resources for CNPG and backube are available in your cluster:&lt;/p&gt;
&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;$ kubectl api-resources  &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;grep&lt;/span&gt; cnpg&lt;br /&gt;backups                                                   postgresql.cnpg.io/v1                    &lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;         Backup&lt;br /&gt;clusterimagecatalogs                                      postgresql.cnpg.io/v1                    &lt;span class=&quot;token boolean&quot;&gt;false&lt;/span&gt;        ClusterImageCatalog&lt;br /&gt;clusters                                                  postgresql.cnpg.io/v1                    &lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;         Cluster&lt;br /&gt;databases                                                 postgresql.cnpg.io/v1                    &lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;         Database&lt;br /&gt;failoverquorums                                           postgresql.cnpg.io/v1                    &lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;         FailoverQuorum&lt;br /&gt;imagecatalogs                                             postgresql.cnpg.io/v1                    &lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;         ImageCatalog&lt;br /&gt;poolers                                                   postgresql.cnpg.io/v1                    &lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;         Pooler&lt;br /&gt;publications                                              postgresql.cnpg.io/v1                    &lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;         Publication&lt;br /&gt;scheduledbackups                                          postgresql.cnpg.io/v1                    &lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;         ScheduledBackup&lt;br /&gt;subscriptions                                             postgresql.cnpg.io/v1                    &lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;         Subscription&lt;br /&gt;$ kubectl api-resources  &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;grep&lt;/span&gt; volsync&lt;br /&gt;replicationdestinations                                   volsync.backube/v1alpha1                 &lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;         ReplicationDestination&lt;br /&gt;replicationsources                                        volsync.backube/v1alpha1                 &lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;         ReplicationSource&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;and also make sure that the custom snapshot class defined in volysnc-config has been created:&lt;/p&gt;
&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;$ kubectl get volumesnapshotclass&lt;br /&gt;NAME                    DRIVER               DELETIONPOLICY   AGE&lt;br /&gt;longhorn-snapshot-vsc   driver.longhorn.io   Delete           11m&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;Deploy Vaultwarden for testing&lt;/h2&gt;
&lt;p&gt;Now that we’ve configured our backup mechanism, we should test it with a real deployment. I’ll walk you through deploying, destroying, and restoring a Vaultwarden instance. Vaultwarden is a password manager well maintained by the TrueCharts community. It’s ideal for our use case, because it will utilize almost every facet of our cluster we’ve configured so far. NGINX&#92;Cloudflare ingress, certificates issued by cluster-issuer, persistent volumes provided by longhorn and backed up with VolSync, and a cloudnative postgresql cluster for backups.&lt;/p&gt;
&lt;h3&gt;VW Secrets&lt;/h3&gt;
&lt;p&gt;To get started, we need to prepare a secret admin token for our Vaultwarden instance. Go ahead and define one in your cluster-config configmap.&lt;/p&gt;
&lt;pre class=&quot;language-yaml&quot;&gt;&lt;code class=&quot;language-yaml&quot;&gt;&lt;span class=&quot;token key atrule&quot;&gt;apiVersion&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; v1&lt;br /&gt;&lt;span class=&quot;token key atrule&quot;&gt;kind&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; ConfigMap&lt;br /&gt;&lt;span class=&quot;token key atrule&quot;&gt;metadata&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token key atrule&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; cluster&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;config&lt;br /&gt;    &lt;span class=&quot;token key atrule&quot;&gt;namespace&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; flux&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;system&lt;br /&gt;&lt;span class=&quot;token key atrule&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token key atrule&quot;&gt;VW_ADMIN_TOKEN&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;###&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;❗ remember to re-encrypt your config map before proceeding&lt;/p&gt;
&lt;h3&gt;Vaultwarden Chart&lt;/h3&gt;
&lt;p&gt;Go ahead and create a vaultwarden directory under apps/general and create the following manifests:&lt;/p&gt;
&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;truek8s&lt;br /&gt;└── apps&lt;br /&gt;   ├── general&lt;br /&gt;   │   └── vaultwarden-test&lt;br /&gt;   │       ├── helm-release.yaml&lt;br /&gt;   │       ├── ks.yaml&lt;br /&gt;   │       ├── kustomization.yaml&lt;br /&gt;   │       └── namespace.yaml&lt;br /&gt;   └── production&lt;br /&gt;       └── vaultwarden-test.yaml&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;./apps/general/vaultwarden&lt;/h3&gt;
&lt;h4&gt;kustomization.yaml&lt;/h4&gt;
&lt;pre class=&quot;language-yaml&quot;&gt;&lt;code class=&quot;language-yaml&quot;&gt;&lt;span class=&quot;token key atrule&quot;&gt;apiVersion&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; kustomize.config.k8s.io/v1beta1&lt;br /&gt;&lt;span class=&quot;token key atrule&quot;&gt;kind&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; Kustomization&lt;br /&gt;&lt;span class=&quot;token key atrule&quot;&gt;resources&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; helm&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;release.yaml&lt;br /&gt;  &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; namespace.yaml&lt;/code&gt;&lt;/pre&gt;
&lt;h4&gt;namespace.yaml&lt;/h4&gt;
&lt;pre class=&quot;language-yaml&quot;&gt;&lt;code class=&quot;language-yaml&quot;&gt;&lt;span class=&quot;token key atrule&quot;&gt;apiVersion&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; v1&lt;br /&gt;&lt;span class=&quot;token key atrule&quot;&gt;kind&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; Namespace&lt;br /&gt;&lt;span class=&quot;token key atrule&quot;&gt;metadata&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token key atrule&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; vaultwarden&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;test&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h4&gt;helm-release.yaml&lt;/h4&gt;
&lt;pre class=&quot;language-yaml&quot;&gt;&lt;code class=&quot;language-yaml&quot;&gt;&lt;span class=&quot;token key atrule&quot;&gt;apiVersion&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; helm.toolkit.fluxcd.io/v2&lt;br /&gt;&lt;span class=&quot;token key atrule&quot;&gt;kind&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; HelmRelease&lt;br /&gt;&lt;span class=&quot;token key atrule&quot;&gt;metadata&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token key atrule&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; vaultwarden&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;test&lt;br /&gt;    &lt;span class=&quot;token key atrule&quot;&gt;namespace&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; vaultwarden&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;test&lt;br /&gt;&lt;span class=&quot;token key atrule&quot;&gt;spec&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token key atrule&quot;&gt;interval&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; 60m&lt;br /&gt;    &lt;span class=&quot;token key atrule&quot;&gt;chart&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token key atrule&quot;&gt;spec&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;            &lt;span class=&quot;token key atrule&quot;&gt;chart&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; vaultwarden&lt;br /&gt;            &lt;span class=&quot;token key atrule&quot;&gt;sourceRef&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;                &lt;span class=&quot;token key atrule&quot;&gt;kind&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; HelmRepository&lt;br /&gt;                &lt;span class=&quot;token key atrule&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; truecharts&lt;br /&gt;                &lt;span class=&quot;token key atrule&quot;&gt;namespace&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; flux&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;system&lt;br /&gt;            &lt;span class=&quot;token key atrule&quot;&gt;interval&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; 60m&lt;br /&gt;    &lt;span class=&quot;token key atrule&quot;&gt;install&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token key atrule&quot;&gt;createNamespace&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean important&quot;&gt;true&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token key atrule&quot;&gt;crds&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; CreateReplace&lt;br /&gt;        &lt;span class=&quot;token key atrule&quot;&gt;timeout&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; 30m&lt;br /&gt;        &lt;span class=&quot;token key atrule&quot;&gt;remediation&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;            &lt;span class=&quot;token key atrule&quot;&gt;retries&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token key atrule&quot;&gt;upgrade&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token key atrule&quot;&gt;crds&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; CreateReplace&lt;br /&gt;        &lt;span class=&quot;token key atrule&quot;&gt;timeout&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; 30m&lt;br /&gt;        &lt;span class=&quot;token key atrule&quot;&gt;remediation&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;            &lt;span class=&quot;token key atrule&quot;&gt;retries&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token key atrule&quot;&gt;values&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token key atrule&quot;&gt;global&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;            &lt;span class=&quot;token key atrule&quot;&gt;stopAll&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean important&quot;&gt;false&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token key atrule&quot;&gt;credentials&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;          &lt;span class=&quot;token key atrule&quot;&gt;backblaze&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;            &lt;span class=&quot;token key atrule&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; s3&lt;br /&gt;            &lt;span class=&quot;token key atrule&quot;&gt;url&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;${S3_URL}&quot;&lt;/span&gt;&lt;br /&gt;            &lt;span class=&quot;token key atrule&quot;&gt;bucket&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;${S3_BUCKET}-vaultwarden-test&quot;&lt;/span&gt;&lt;br /&gt;            &lt;span class=&quot;token key atrule&quot;&gt;accessKey&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;${S3_ACCESS_KEY}&quot;&lt;/span&gt;&lt;br /&gt;            &lt;span class=&quot;token key atrule&quot;&gt;secretKey&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;${S3_SECRET_KEY}&quot;&lt;/span&gt;&lt;br /&gt;            &lt;span class=&quot;token key atrule&quot;&gt;encrKey&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;${S3_ENCRYPTION_KEY}&quot;&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token key atrule&quot;&gt;ingress&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;          &lt;span class=&quot;token key atrule&quot;&gt;main&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;            &lt;span class=&quot;token key atrule&quot;&gt;enabled&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean important&quot;&gt;true&lt;/span&gt;&lt;br /&gt;            &lt;span class=&quot;token key atrule&quot;&gt;ingressClassName&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; internal&lt;br /&gt;            &lt;span class=&quot;token key atrule&quot;&gt;integrations&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;              &lt;span class=&quot;token key atrule&quot;&gt;traefik&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;                &lt;span class=&quot;token key atrule&quot;&gt;enabled&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean important&quot;&gt;false&lt;/span&gt;&lt;br /&gt;              &lt;span class=&quot;token key atrule&quot;&gt;certManager&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;                &lt;span class=&quot;token key atrule&quot;&gt;enabled&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean important&quot;&gt;true&lt;/span&gt;&lt;br /&gt;                &lt;span class=&quot;token key atrule&quot;&gt;certificateIssuer&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; letsencrypt&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;domain&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;br /&gt;            &lt;span class=&quot;token key atrule&quot;&gt;hosts&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;              &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token key atrule&quot;&gt;host&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; vaultwarden&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;test.$&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;DOMAIN_0&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;                &lt;span class=&quot;token key atrule&quot;&gt;paths&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;                  &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token key atrule&quot;&gt;path&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; /&lt;br /&gt;                    &lt;span class=&quot;token key atrule&quot;&gt;pathType&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; Prefix &lt;br /&gt;          &lt;span class=&quot;token key atrule&quot;&gt;cloudflare&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;            &lt;span class=&quot;token key atrule&quot;&gt;enabled&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean important&quot;&gt;true&lt;/span&gt;&lt;br /&gt;            &lt;span class=&quot;token key atrule&quot;&gt;ingressClassName&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; cloudflare&lt;br /&gt;            &lt;span class=&quot;token key atrule&quot;&gt;integrations&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;              &lt;span class=&quot;token key atrule&quot;&gt;traefik&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;                &lt;span class=&quot;token key atrule&quot;&gt;enabled&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean important&quot;&gt;false&lt;/span&gt;&lt;br /&gt;            &lt;span class=&quot;token key atrule&quot;&gt;hosts&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;            &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token key atrule&quot;&gt;host&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; vaultwarden&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;test.$&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;DOMAIN_0&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;              &lt;span class=&quot;token key atrule&quot;&gt;paths&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;              &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token key atrule&quot;&gt;path&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; /&lt;br /&gt;                &lt;span class=&quot;token key atrule&quot;&gt;pathType&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; Prefix&lt;br /&gt;        &lt;span class=&quot;token key atrule&quot;&gt;persistence&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;            &lt;span class=&quot;token key atrule&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;              &lt;span class=&quot;token key atrule&quot;&gt;volsync&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;              &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token key atrule&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; data&lt;br /&gt;                &lt;span class=&quot;token key atrule&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; restic&lt;br /&gt;                &lt;span class=&quot;token key atrule&quot;&gt;cleanupTempPVC&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean important&quot;&gt;false&lt;/span&gt;&lt;br /&gt;                &lt;span class=&quot;token key atrule&quot;&gt;cleanupCachePVC&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean important&quot;&gt;false&lt;/span&gt;&lt;br /&gt;                &lt;span class=&quot;token key atrule&quot;&gt;credentials&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; backblaze&lt;br /&gt;                &lt;span class=&quot;token key atrule&quot;&gt;dest&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;                  &lt;span class=&quot;token key atrule&quot;&gt;enabled&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean important&quot;&gt;true&lt;/span&gt;&lt;br /&gt;                &lt;span class=&quot;token key atrule&quot;&gt;src&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;                  &lt;span class=&quot;token key atrule&quot;&gt;enabled&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean important&quot;&gt;true&lt;/span&gt;&lt;br /&gt;                  &lt;span class=&quot;token key atrule&quot;&gt;trigger&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;                    &lt;span class=&quot;token key atrule&quot;&gt;schedule&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; 40 1 * * *&lt;br /&gt;        &lt;span class=&quot;token key atrule&quot;&gt;cnpg&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;            &lt;span class=&quot;token key atrule&quot;&gt;main&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;              &lt;span class=&quot;token key atrule&quot;&gt;cluster&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;                &lt;span class=&quot;token key atrule&quot;&gt;singleNode&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean important&quot;&gt;true&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token comment&quot;&gt;#              mode: recovery&lt;/span&gt;&lt;br /&gt;              &lt;span class=&quot;token key atrule&quot;&gt;backups&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;                &lt;span class=&quot;token key atrule&quot;&gt;enabled&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean important&quot;&gt;true&lt;/span&gt;&lt;br /&gt;                &lt;span class=&quot;token key atrule&quot;&gt;credentials&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; backblaze&lt;br /&gt;                &lt;span class=&quot;token key atrule&quot;&gt;scheduledBackups&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;                  &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token key atrule&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; daily&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;backup&lt;br /&gt;                    &lt;span class=&quot;token key atrule&quot;&gt;schedule&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;0 5 0 * * *&quot;&lt;/span&gt;&lt;br /&gt;                    &lt;span class=&quot;token key atrule&quot;&gt;backupOwnerReference&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; self&lt;br /&gt;                    &lt;span class=&quot;token key atrule&quot;&gt;immediate&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean important&quot;&gt;true&lt;/span&gt;&lt;br /&gt;                    &lt;span class=&quot;token key atrule&quot;&gt;suspend&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean important&quot;&gt;false&lt;/span&gt;&lt;br /&gt;              &lt;span class=&quot;token key atrule&quot;&gt;recovery&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;                &lt;span class=&quot;token key atrule&quot;&gt;method&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; object_store&lt;br /&gt;                &lt;span class=&quot;token key atrule&quot;&gt;credentials&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; backblaze&lt;br /&gt;        &lt;span class=&quot;token key atrule&quot;&gt;vaultwarden&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;            &lt;span class=&quot;token key atrule&quot;&gt;admin&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;                &lt;span class=&quot;token key atrule&quot;&gt;enabled&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean important&quot;&gt;true&lt;/span&gt;&lt;br /&gt;                &lt;span class=&quot;token key atrule&quot;&gt;token&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; $&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;VW_ADMIN_TOKEN&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The important config items in this manifest are:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;values.credentials
&lt;ul&gt;
&lt;li&gt;This section provides the info and credentials to reach our S3 bucket. In this case, that is all stored in the cluster-config configmap, and will be the same for all charts except for the bucket name, which we’ll append with a static value for each chart.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;values.persistence
&lt;ul&gt;
&lt;li&gt;This section performs two functions. It configures the persistent volumes for our deployment, and also configures VolSync for that volume. Vaultwarden needs one persistent volume named ‘data’ which you see defined here. Other persistent volumes can be defined using the same syntax under the persistence section.&lt;/li&gt;
&lt;li&gt;Take note of the dest and src configuration. This tells VolSync whether this volume should be a source of a backup (src: enabled: true) or the destination of a backup (dest: enabled: true). Setting both to true allows the PVC to both restore from an existing ReplicationDestination if one exists and then act as a backup source afterward&lt;/li&gt;
&lt;li&gt;Take note of the backup schedule, which does what it sounds like it does.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;values.cnpg
&lt;ul&gt;
&lt;li&gt;This section configures CNPG, and can be a bit sticky. Unlike VolSync, CNPG seems to fail if restore is set to true and no backup exists. I run CNPG either in backup mode or in restore mode, but not in both. That’s why the mode: recovery line is commented out, we’ll explore that later in this post.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;./apps/production&lt;/h3&gt;
&lt;h4&gt;vaultwarden-test.yaml&lt;/h4&gt;
&lt;pre class=&quot;language-yaml&quot;&gt;&lt;code class=&quot;language-yaml&quot;&gt;&lt;span class=&quot;token key atrule&quot;&gt;apiVersion&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; kustomize.toolkit.fluxcd.io/v1&lt;br /&gt;&lt;span class=&quot;token key atrule&quot;&gt;kind&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; Kustomization&lt;br /&gt;&lt;span class=&quot;token key atrule&quot;&gt;metadata&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token key atrule&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; vaultwarden&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;test&lt;br /&gt;  &lt;span class=&quot;token key atrule&quot;&gt;namespace&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; flux&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;system&lt;br /&gt;&lt;span class=&quot;token key atrule&quot;&gt;spec&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token key atrule&quot;&gt;dependsOn&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token key atrule&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; ingress&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;nginx&lt;br /&gt;  &lt;span class=&quot;token key atrule&quot;&gt;interval&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; 10m&lt;br /&gt;  &lt;span class=&quot;token key atrule&quot;&gt;path&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; apps/general/vaultwarden&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;test&lt;br /&gt;  &lt;span class=&quot;token key atrule&quot;&gt;prune&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean important&quot;&gt;true&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token key atrule&quot;&gt;sourceRef&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token key atrule&quot;&gt;kind&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; GitRepository&lt;br /&gt;    &lt;span class=&quot;token key atrule&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; flux&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;system&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;And don’t forget to add a reference to apps/production/kustomization.yaml&lt;/p&gt;
&lt;pre class=&quot;language-yaml&quot;&gt;&lt;code class=&quot;language-yaml&quot;&gt;&lt;span class=&quot;token key atrule&quot;&gt;apiVersion&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; kustomize.config.k8s.io/v1beta1&lt;br /&gt;&lt;span class=&quot;token key atrule&quot;&gt;kind&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; Kustomization&lt;br /&gt;&lt;span class=&quot;token key atrule&quot;&gt;resources&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; vaultwarden&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;test.yaml&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;Commit and Test&lt;/h2&gt;
&lt;p&gt;Commit your changes:&lt;/p&gt;
&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;$ &lt;span class=&quot;token function&quot;&gt;git&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;add&lt;/span&gt; &lt;span class=&quot;token parameter variable&quot;&gt;-A&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;git&lt;/span&gt; commit &lt;span class=&quot;token parameter variable&quot;&gt;-m&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;add vaultwarden test&quot;&lt;/span&gt;&lt;br /&gt;$ &lt;span class=&quot;token function&quot;&gt;git&lt;/span&gt; push&lt;br /&gt;&lt;br /&gt;$ flux events &lt;span class=&quot;token parameter variable&quot;&gt;--watch&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;As soon as flux reconciles the HR, your cluster should get to work on the deployment. Switch to watching pods in the vaultwarden namespace. Pay particular attention to the VolSync and CNPG pods that appear, do their tasks, then complete. While it works, you can also watch volumes appear in the longhorn UI.&lt;/p&gt;
&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt; kubectl get pods &lt;span class=&quot;token parameter variable&quot;&gt;-n&lt;/span&gt; vaultwarden-test &lt;span class=&quot;token parameter variable&quot;&gt;--watch&lt;/span&gt;&lt;br /&gt;NAME                                           READY   STATUS              RESTARTS   AGE&lt;br /&gt;vaultwarden-5d5c5bdcdb-djkw2                   &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;/1     Pending             &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;          6s&lt;br /&gt;vaultwarden-cnpg-main-1-initdb-xrbt7           &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;/1     Pending             &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;          4s&lt;br /&gt;volsync-dst-vaultwarden-data-data-dest-wz44l   &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;/1     ContainerCreating   &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;          5s&lt;br /&gt;vaultwarden-cnpg-main-1-initdb-xrbt7           &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;/1     Pending             &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;          4s&lt;br /&gt;vaultwarden-cnpg-main-1-initdb-xrbt7           &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;/1     Init:0/1            &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;          4s&lt;br /&gt;vaultwarden-cnpg-main-1-initdb-xrbt7           &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;/1     Init:0/1            &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;          26s&lt;br /&gt;volsync-dst-vaultwarden-data-data-dest-wz44l   &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;/1     Running             &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;          28s&lt;br /&gt;vaultwarden-cnpg-main-1-initdb-xrbt7           &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;/1     PodInitializing     &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;          28s&lt;br /&gt;vaultwarden-cnpg-main-1-initdb-xrbt7           &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;/1     Running             &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;          30s&lt;br /&gt;volsync-dst-vaultwarden-data-data-dest-wz44l   &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;/1     Completed           &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;          32s&lt;br /&gt;vaultwarden-cnpg-main-1-initdb-xrbt7           &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;/1     Completed           &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;          32s&lt;br /&gt;volsync-dst-vaultwarden-data-data-dest-wz44l   &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;/1     Completed           &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;          33s&lt;br /&gt;vaultwarden-cnpg-main-1-initdb-xrbt7           &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;/1     Completed           &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;          32s&lt;br /&gt;vaultwarden-cnpg-main-1-initdb-xrbt7           &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;/1     Completed           &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;          33s&lt;br /&gt;volsync-dst-vaultwarden-data-data-dest-wz44l   &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;/1     Completed           &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;          34s&lt;br /&gt;vaultwarden-cnpg-main-1                        &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;/1     Pending             &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;          0s&lt;br /&gt;vaultwarden-cnpg-main-1                        &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;/1     Pending             &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;          0s&lt;br /&gt;vaultwarden-cnpg-main-1                        &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;/1     Init:0/1            &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;          0s&lt;br /&gt;volsync-dst-vaultwarden-data-data-dest-wz44l   &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;/1     Completed           &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;          37s&lt;br /&gt;volsync-dst-vaultwarden-data-data-dest-wz44l   &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;/1     Completed           &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;          37s&lt;br /&gt;vaultwarden-cnpg-main-1                        &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;/1     Init:0/1            &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;          15s&lt;br /&gt;vaultwarden-cnpg-main-1                        &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;/1     PodInitializing     &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;          16s&lt;br /&gt;vaultwarden-5d5c5bdcdb-djkw2                   &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;/1     Pending             &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;          54s&lt;br /&gt;vaultwarden-5d5c5bdcdb-djkw2                   &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;/1     Init:0/1            &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;          54s&lt;br /&gt;vaultwarden-cnpg-main-1                        &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;/1     Running             &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;          17s&lt;br /&gt;vaultwarden-cnpg-main-1                        &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;/1     Running             &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;          20s&lt;br /&gt;vaultwarden-cnpg-main-1                        &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;/1     Running             &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;          24s&lt;br /&gt;vaultwarden-cnpg-main-1                        &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;/1     Running             &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;          24s&lt;br /&gt;vaultwarden-cnpg-main-2-join-6j6dw             &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;/1     Pending             &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;          0s&lt;br /&gt;vaultwarden-cnpg-main-2-join-6j6dw             &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;/1     Pending             &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;          0s&lt;br /&gt;vaultwarden-cnpg-main-2-join-6j6dw             &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;/1     Pending             &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;          1s&lt;br /&gt;vaultwarden-cnpg-main-2-join-6j6dw             &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;/1     Pending             &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;          7s&lt;br /&gt;vaultwarden-cnpg-main-2-join-6j6dw             &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;/1     Init:0/1            &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;          7s&lt;br /&gt;vaultwarden-5d5c5bdcdb-djkw2                   &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;/1     Terminating         &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;          71s&lt;br /&gt;vaultwarden-5d5c5bdcdb-4v6t6                   &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;/1     Pending             &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;          0s&lt;br /&gt;vaultwarden-5d5c5bdcdb-4v6t6                   &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;/1     Pending             &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;          0s&lt;br /&gt;vaultwarden-5d5c5bdcdb-4v6t6                   &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;/1     Init:0/1            &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;          0s&lt;br /&gt;vaultwarden-5d5c5bdcdb-djkw2                   &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;/1     Init:ContainerStatusUnknown   &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;          73s&lt;br /&gt;vaultwarden-5d5c5bdcdb-djkw2                   &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;/1     Init:ContainerStatusUnknown   &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;          73s&lt;br /&gt;vaultwarden-5d5c5bdcdb-djkw2                   &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;/1     Init:ContainerStatusUnknown   &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;          73s&lt;br /&gt;volsync-src-vaultwarden-data-data-2sgll        &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;/1     Pending                       &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;          0s&lt;br /&gt;volsync-src-vaultwarden-data-data-2sgll        &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;/1     Pending                       &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;          0s&lt;br /&gt;volsync-src-vaultwarden-data-data-2sgll        &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;/1     Pending                       &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;          7s&lt;br /&gt;volsync-src-vaultwarden-data-data-2sgll        &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;/1     ContainerCreating             &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;          10s&lt;br /&gt;vaultwarden-cnpg-main-2-join-6j6dw             &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;/1     Init:0/1                      &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;          33s&lt;br /&gt;vaultwarden-cnpg-main-2-join-6j6dw             &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;/1     PodInitializing               &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;          35s&lt;br /&gt;vaultwarden-cnpg-main-2-join-6j6dw             &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;/1     Running                       &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;          40s&lt;br /&gt;vaultwarden-cnpg-main-2-join-6j6dw             &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;/1     Completed                     &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;          46s&lt;br /&gt;vaultwarden-cnpg-main-2-join-6j6dw             &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;/1     Completed                     &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;          47s&lt;br /&gt;vaultwarden-cnpg-main-2-join-6j6dw             &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;/1     Completed                     &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;          48s&lt;br /&gt;vaultwarden-cnpg-main-2                        &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;/1     Pending                       &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;          0s&lt;br /&gt;vaultwarden-cnpg-main-2                        &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;/1     Pending                       &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;          0s&lt;br /&gt;vaultwarden-cnpg-main-2                        &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;/1     Init:0/1                      &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;          2s&lt;br /&gt;vaultwarden-cnpg-main-2                        &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;/1     Init:0/1                      &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;          25s&lt;br /&gt;vaultwarden-cnpg-main-2                        &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;/1     PodInitializing               &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;          26s&lt;br /&gt;vaultwarden-cnpg-main-2                        &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;/1     Running                       &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;          30s&lt;br /&gt;vaultwarden-cnpg-main-2                        &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;/1     Running                       &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;          32s&lt;br /&gt;vaultwarden-cnpg-main-2                        &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;/1     Running                       &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;          33s&lt;br /&gt;vaultwarden-cnpg-main-2                        &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;/1     Running                       &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;          34s&lt;br /&gt;vaultwarden-cnpg-main-1-initdb-xrbt7           &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;/1     Completed                     &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;          2m24s&lt;br /&gt;vaultwarden-cnpg-main-2-join-6j6dw             &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;/1     Completed                     &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;          84s&lt;br /&gt;vaultwarden-cnpg-main-1-initdb-xrbt7           &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;/1     Completed                     &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;          2m24s&lt;br /&gt;vaultwarden-cnpg-main-2-join-6j6dw             &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;/1     Completed                     &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;          84s&lt;br /&gt;volsync-src-vaultwarden-data-data-2sgll        &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;/1     Running                       &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;          88s&lt;br /&gt;volsync-src-vaultwarden-data-data-2sgll        &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;/1     Completed                     &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;          90s&lt;br /&gt;volsync-src-vaultwarden-data-data-2sgll        &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;/1     Completed                     &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;          92s&lt;br /&gt;volsync-src-vaultwarden-data-data-2sgll        &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;/1     Completed                     &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;          92s&lt;br /&gt;volsync-src-vaultwarden-data-data-2sgll        &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;/1     Completed                     &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;          93s&lt;br /&gt;volsync-src-vaultwarden-data-data-2sgll        &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;/1     Completed                     &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;          93s&lt;br /&gt;vaultwarden-5d5c5bdcdb-4v6t6                   &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;/1     Init:0/1                      &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;          112s&lt;br /&gt;vaultwarden-5d5c5bdcdb-4v6t6                   &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;/1     PodInitializing               &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;          113s&lt;br /&gt;vaultwarden-5d5c5bdcdb-4v6t6                   &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;/1     Running                       &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;          2m10s&lt;br /&gt;vaultwarden-5d5c5bdcdb-4v6t6                   &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;/1     Running                       &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;          2m21s&lt;br /&gt;vaultwarden-5d5c5bdcdb-4v6t6                   &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;/1     Running                       &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;          2m33s&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;If everything went well, you should be able to reach vaultwarden at the ingress url you set up for it. Go ahead and create yourself a test record, You can verify this record later when we restore.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;http://localhost:8080/assets/images/2025/11/vaultwarden-test-record.png&quot; alt=&quot;image&quot; /&gt;&lt;/p&gt;
&lt;h2&gt;Inspect Your Backups&lt;/h2&gt;
&lt;p&gt;VolSync and CNPG both offer tools that you can use to inspect, verify, and administer your backups.&lt;/p&gt;
&lt;h3&gt;VolSync&lt;/h3&gt;
&lt;p&gt;You can inspect source and destination volume status with Kubectl.&lt;/p&gt;
&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;$ kubectl get replicationdestinations.volsync.backube &lt;span class=&quot;token parameter variable&quot;&gt;-n&lt;/span&gt; vaultwarden-test &lt;br /&gt;NAME                              LAST SYNC              DURATION       NEXT SYNC&lt;br /&gt;vaultwarden-test-data-data-dest   &lt;span class=&quot;token number&quot;&gt;2025&lt;/span&gt;-11-28T01:56:41Z   &lt;span class=&quot;token number&quot;&gt;27&lt;/span&gt;.96262596s   &lt;br /&gt;$ kubectl get replicationsources.volsync.backube &lt;span class=&quot;token parameter variable&quot;&gt;-n&lt;/span&gt; vaultwarden-test &lt;br /&gt;NAME                         SOURCE                  LAST SYNC              DURATION          NEXT SYNC&lt;br /&gt;vaultwarden-test-data-data   vaultwarden-test-data   &lt;span class=&quot;token number&quot;&gt;2025&lt;/span&gt;-11-28T02:02:01Z   5m47.901609977s   &lt;span class=&quot;token number&quot;&gt;2025&lt;/span&gt;-11-29T01:40:00Z&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;If you install the VolSync plugin for kubectl &lt;a href=&quot;https://volsync.readthedocs.io/en/stable/usage/cli/index.html&quot;&gt;VolSync.readthedocs.io&lt;/a&gt;, you can also manually migrate or replicate data. I have not used these commands, but I’m aware they exist, and you should be too.&lt;/p&gt;
&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;$ kubectl volsync migration&lt;br /&gt;$ kubectl volsync replication&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;CNPG&lt;/h3&gt;
&lt;p&gt;Likewise, you can find your CNPG cluster with kubectl and inspect it with the kubectl plugin &lt;a href=&quot;https://cloudnative-pg.io/documentation/current/kubectl-plugin/&quot;&gt;clougnative-pg.io&lt;/a&gt;&lt;/p&gt;
&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;$ kubectl get clusters.postgresql.cnpg.io &lt;span class=&quot;token parameter variable&quot;&gt;-n&lt;/span&gt; vaultwarden-test vaultwarden-test-cnpg-main &lt;br /&gt;NAME                         AGE   INSTANCES   READY   STATUS                     PRIMARY&lt;br /&gt;vaultwarden-test-cnpg-main   10h   &lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt;           &lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt;       Cluster &lt;span class=&quot;token keyword&quot;&gt;in&lt;/span&gt; healthy state   vaultwarden-test-cnpg-main-1&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;And to check health status.&lt;/p&gt;
&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;$ kubectl cnpg status &lt;span class=&quot;token parameter variable&quot;&gt;-n&lt;/span&gt; vaultwarden-test vaultwarden-test-cnpg-main&lt;br /&gt;Cluster Summary&lt;br /&gt;Name                     vaultwarden-test/vaultwarden-test-cnpg-main&lt;br /&gt;System ID:               &lt;span class=&quot;token number&quot;&gt;7577589366663393300&lt;/span&gt;&lt;br /&gt;PostgreSQL Image:        ghcr.io/cloudnative-pg/postgresql:16.11&lt;br /&gt;Primary instance:        vaultwarden-test-cnpg-main-1&lt;br /&gt;Primary promotion time:  &lt;span class=&quot;token number&quot;&gt;2025&lt;/span&gt;-11-28 01:57:07 +0000 UTC &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;10h28m55s&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;br /&gt;Status:                  Cluster &lt;span class=&quot;token keyword&quot;&gt;in&lt;/span&gt; healthy state &lt;br /&gt;Instances:               &lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt;&lt;br /&gt;Ready instances:         &lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt;&lt;br /&gt;Size:                    176M&lt;br /&gt;Current Write LSN:       &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;/9000060 &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;Timeline: &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt; - WAL File: 000000010000000000000009&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Continuous Backup status&lt;br /&gt;First Point of Recoverability:  &lt;span class=&quot;token number&quot;&gt;2025&lt;/span&gt;-11-26T22:16:29Z&lt;br /&gt;Working WAL archiving:          OK&lt;br /&gt;WALs waiting to be archived:    &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;br /&gt;Last Archived WAL:              000000010000000000000008   @   &lt;span class=&quot;token number&quot;&gt;2025&lt;/span&gt;-11-28T02:08:20.28951Z&lt;br /&gt;Last Failed WAL:                -&lt;br /&gt;&lt;br /&gt;Streaming Replication status&lt;br /&gt;Replication Slots Enabled&lt;br /&gt;Name                          Sent LSN   Write LSN  Flush LSN  Replay LSN  Write Lag  Flush Lag  Replay Lag  State      Sync State  Sync Priority  Replication Slot&lt;br /&gt;----                          --------   ---------  ---------  ----------  ---------  ---------  ----------  -----      ----------  -------------  ----------------&lt;br /&gt;vaultwarden-test-cnpg-main-2  &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;/9000060  &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;/9000060  &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;/9000060  &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;/9000060   00:00:00   00:00:00   00:00:00    streaming  async       &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;              active&lt;br /&gt;&lt;br /&gt;Instances status&lt;br /&gt;Name                          Current LSN  Replication role  Status  QoS        Manager Version  Node&lt;br /&gt;----                          -----------  ----------------  ------  ---        ---------------  ----&lt;br /&gt;vaultwarden-test-cnpg-main-1  &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;/9000060    Primary           OK      Burstable  &lt;span class=&quot;token number&quot;&gt;1.27&lt;/span&gt;.1           truek8s-w1&lt;br /&gt;vaultwarden-test-cnpg-main-2  &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;/9000060    Standby &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;async&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;   OK      Burstable  &lt;span class=&quot;token number&quot;&gt;1.27&lt;/span&gt;.1           truek8s-w2&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;Restore Test&lt;/h2&gt;
&lt;p&gt;A backup is only as good as its last verified restore point. Let’s go through the steps of restoring our vaultwarden instance.&lt;/p&gt;
&lt;p&gt;Before you proceed, note that CNPG and VolSync take backups immediately upon deployment and then again on the scheduled defined in the helm-release. If you just deployed your chart and committed a record, you should wait for the next backup or trigger one manually using the commands above.&lt;/p&gt;
&lt;p&gt;First, suspend the vaultwarden ks, then delete the entire vaultwarden namespace. That will delete all kustomizations, deployments, volumes, snapshots, etc.&lt;/p&gt;
&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;$ flux &lt;span class=&quot;token function&quot;&gt;suspend&lt;/span&gt; ks vaultwarden-test&lt;br /&gt;► suspending kustomization vaultwarden-test &lt;span class=&quot;token keyword&quot;&gt;in&lt;/span&gt; flux-system namespace&lt;br /&gt;✔ kustomization suspended&lt;br /&gt;&lt;span class=&quot;token comment&quot;&gt;#It will hang at this step for a while as longhorn works on deleting volumes and snapshots.&lt;/span&gt;&lt;br /&gt;$ kubectl delete namespaces vaultwarden-test &lt;br /&gt;namespace &lt;span class=&quot;token string&quot;&gt;&quot;vaultwarden-test&quot;&lt;/span&gt; deleted&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Now, you just need to edit your helm-release and tell CNPG that it needs to attempt to restore from backup. Just uncomment the cnpg.main.cluster.mode line in your helm-release.yaml.&lt;/p&gt;
&lt;pre class=&quot;language-yaml&quot;&gt;&lt;code class=&quot;language-yaml&quot;&gt;        &lt;span class=&quot;token key atrule&quot;&gt;cnpg&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;            &lt;span class=&quot;token key atrule&quot;&gt;main&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;              &lt;span class=&quot;token key atrule&quot;&gt;cluster&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;                &lt;span class=&quot;token key atrule&quot;&gt;singleNode&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean important&quot;&gt;true&lt;/span&gt;&lt;br /&gt;              &lt;span class=&quot;token key atrule&quot;&gt;mode&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; recovery&lt;br /&gt;              &lt;span class=&quot;token key atrule&quot;&gt;backups&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;                &lt;span class=&quot;token key atrule&quot;&gt;enabled&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean important&quot;&gt;true&lt;/span&gt;&lt;br /&gt;                &lt;span class=&quot;token key atrule&quot;&gt;credentials&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; backblaze&lt;br /&gt;                &lt;span class=&quot;token key atrule&quot;&gt;scheduledBackups&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;                  &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token key atrule&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; daily&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;backup&lt;br /&gt;                    &lt;span class=&quot;token key atrule&quot;&gt;schedule&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;0 5 0 * * *&quot;&lt;/span&gt;&lt;br /&gt;                    &lt;span class=&quot;token key atrule&quot;&gt;backupOwnerReference&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; self&lt;br /&gt;                    &lt;span class=&quot;token key atrule&quot;&gt;immediate&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean important&quot;&gt;true&lt;/span&gt;&lt;br /&gt;                    &lt;span class=&quot;token key atrule&quot;&gt;suspend&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean important&quot;&gt;false&lt;/span&gt;&lt;br /&gt;              &lt;span class=&quot;token key atrule&quot;&gt;recovery&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;                &lt;span class=&quot;token key atrule&quot;&gt;method&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; object_store&lt;br /&gt;                &lt;span class=&quot;token key atrule&quot;&gt;credentials&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; backblaze&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Double check that the vaultwarden ks is suspended, and then commit your changes. Watch for the Vaultwarden Kustomization to be reconcile.&lt;/p&gt;
&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;$ &lt;span class=&quot;token function&quot;&gt;git&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;add&lt;/span&gt; &lt;span class=&quot;token parameter variable&quot;&gt;-A&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;git&lt;/span&gt; commit &lt;span class=&quot;token parameter variable&quot;&gt;-m&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;test vaultwarden restore&#39;&lt;/span&gt;&lt;br /&gt;$ flux get ks vaultwarden&lt;br /&gt;NAME            REVISION                SUSPENDED       READY   MESSAGE                              &lt;br /&gt;vaultwarden     main@sha1:af980727      True            True    Applied revision: main@sha1:af980727&lt;br /&gt;$ flux resume ks vaultwarden&lt;br /&gt;► resuming kustomization vaultwarden &lt;span class=&quot;token keyword&quot;&gt;in&lt;/span&gt; flux-system namespace&lt;br /&gt;✔ kustomization resumed&lt;br /&gt;◎ waiting &lt;span class=&quot;token keyword&quot;&gt;for&lt;/span&gt; Kustomization reconciliation&lt;br /&gt;✔ Kustomization vaultwarden reconciliation completed&lt;br /&gt;✔ applied revision main@sha1:9e77a508dbd94f59dd4d1e3c50bf7c2ede29587f&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Pay attention to the Longhorn UI and watch pods in the vaultwarden namespace. Pay particularly close attention to the VolSync and CNPG pods that show up.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;http://localhost:8080/assets/images/2025/11/vaultwarden-test-restore-longhorn.png&quot; alt=&quot;image&quot; /&gt;&lt;/p&gt;
&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;$ kubectl get pods &lt;span class=&quot;token parameter variable&quot;&gt;-n&lt;/span&gt; vaultwarden-test &lt;span class=&quot;token parameter variable&quot;&gt;--watch&lt;/span&gt;&lt;br /&gt;NAME                                                READY   STATUS              RESTARTS   AGE&lt;br /&gt;vaultwarden-test-7996596577-vtfsl                   &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;/1     Pending             &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;          6s&lt;br /&gt;vaultwarden-test-cnpg-main-1-full-recovery-gpx84    &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;/1     Init:0/1            &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;          5s&lt;br /&gt;volsync-dst-vaultwarden-test-data-data-dest-k5j7t   &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;/1     ContainerCreating   &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;          5s&lt;br /&gt;volsync-dst-vaultwarden-test-data-data-dest-k5j7t   &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;/1     Running             &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;          15s&lt;br /&gt;vaultwarden-test-cnpg-main-1-full-recovery-gpx84    &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;/1     PodInitializing     &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;          15s&lt;br /&gt;vaultwarden-test-cnpg-main-1-full-recovery-gpx84    &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;/1     Running             &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;          16s&lt;br /&gt;volsync-dst-vaultwarden-test-data-data-dest-k5j7t   &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;/1     Completed           &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;          20s&lt;br /&gt;volsync-dst-vaultwarden-test-data-data-dest-k5j7t   &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;/1     Completed           &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;          21s&lt;br /&gt;volsync-dst-vaultwarden-test-data-data-dest-k5j7t   &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;/1     Completed           &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;          22s&lt;br /&gt;volsync-dst-vaultwarden-test-data-data-dest-k5j7t   &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;/1     Completed           &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;          22s&lt;br /&gt;volsync-dst-vaultwarden-test-data-data-dest-k5j7t   &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;/1     Completed           &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;          22s&lt;br /&gt;vaultwarden-test-7996596577-vtfsl                   &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;/1     Pending             &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;          32s&lt;br /&gt;vaultwarden-test-7996596577-vtfsl                   &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;/1     Init:0/1            &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;          32s&lt;br /&gt;vaultwarden-test-cnpg-main-1-full-recovery-gpx84    &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;/1     Completed           &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;          42s&lt;br /&gt;vaultwarden-test-cnpg-main-1-full-recovery-gpx84    &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;/1     Completed           &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;          44s&lt;br /&gt;vaultwarden-test-cnpg-main-1-full-recovery-gpx84    &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;/1     Completed           &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;          44s&lt;br /&gt;vaultwarden-test-cnpg-main-1                        &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;/1     Pending             &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;          0s&lt;br /&gt;vaultwarden-test-cnpg-main-1                        &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;/1     Pending             &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;          0s&lt;br /&gt;vaultwarden-test-cnpg-main-1                        &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;/1     Init:0/1            &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;          0s&lt;br /&gt;vaultwarden-test-cnpg-main-1                        &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;/1     PodInitializing     &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;          15s&lt;br /&gt;vaultwarden-test-cnpg-main-1                        &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;/1     Running             &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;          16s&lt;br /&gt;vaultwarden-test-cnpg-main-1                        &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;/1     Running             &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;          17s&lt;br /&gt;vaultwarden-test-cnpg-main-1                        &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;/1     Running             &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;          24s&lt;br /&gt;vaultwarden-test-cnpg-main-1                        &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;/1     Running             &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;          24s&lt;br /&gt;vaultwarden-test-cnpg-main-2-join-kpnrz             &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;/1     Pending             &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;          0s&lt;br /&gt;vaultwarden-test-cnpg-main-2-join-kpnrz             &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;/1     Pending             &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;          0s&lt;br /&gt;vaultwarden-test-cnpg-main-2-join-kpnrz             &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;/1     Pending             &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;          0s&lt;br /&gt;vaultwarden-test-cnpg-main-2-join-kpnrz             &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;/1     Pending             &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;          2s&lt;br /&gt;volsync-src-vaultwarden-test-data-data-464ws        &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;/1     Pending             &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;          0s&lt;br /&gt;volsync-src-vaultwarden-test-data-data-464ws        &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;/1     Pending             &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;          0s&lt;br /&gt;vaultwarden-test-cnpg-main-2-join-kpnrz             &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;/1     Pending             &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;          3s&lt;br /&gt;vaultwarden-test-cnpg-main-2-join-kpnrz             &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;/1     Init:0/1            &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;          3s&lt;br /&gt;volsync-src-vaultwarden-test-data-data-464ws        &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;/1     Pending             &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;          2s&lt;br /&gt;volsync-src-vaultwarden-test-data-data-464ws        &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;/1     ContainerCreating   &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;          2s&lt;br /&gt;vaultwarden-test-cnpg-main-2-join-kpnrz             &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;/1     PodInitializing     &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;          25s&lt;br /&gt;vaultwarden-test-cnpg-main-2-join-kpnrz             &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;/1     Running             &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;          26s&lt;br /&gt;vaultwarden-test-cnpg-main-2-join-kpnrz             &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;/1     Completed           &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;          33s&lt;br /&gt;vaultwarden-test-7996596577-vtfsl                   &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;/1     PodInitializing     &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;          103s&lt;br /&gt;vaultwarden-test-cnpg-main-2-join-kpnrz             &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;/1     Completed           &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;          34s&lt;br /&gt;vaultwarden-test-7996596577-vtfsl                   &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;/1     Running             &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;          104s&lt;br /&gt;vaultwarden-test-cnpg-main-2-join-kpnrz             &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;/1     Completed           &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;          35s&lt;br /&gt;vaultwarden-test-cnpg-main-2                        &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;/1     Pending             &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;          0s&lt;br /&gt;vaultwarden-test-cnpg-main-2                        &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;/1     Pending             &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;          0s&lt;br /&gt;vaultwarden-test-cnpg-main-2                        &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;/1     Init:0/1            &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;          0s&lt;br /&gt;vaultwarden-test-cnpg-main-2                        &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;/1     Init:0/1            &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;          7s&lt;br /&gt;vaultwarden-test-cnpg-main-2                        &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;/1     PodInitializing     &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;          8s&lt;br /&gt;vaultwarden-test-cnpg-main-2                        &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;/1     Running             &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;          9s&lt;br /&gt;vaultwarden-test-cnpg-main-2                        &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;/1     Running             &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;          10s&lt;br /&gt;vaultwarden-test-7996596577-vtfsl                   &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;/1     Running             &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;          117s&lt;br /&gt;vaultwarden-test-cnpg-main-2                        &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;/1     Running             &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;          15s&lt;br /&gt;vaultwarden-test-cnpg-main-2                        &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;/1     Running             &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;          16s&lt;br /&gt;vaultwarden-test-cnpg-main-1-full-recovery-gpx84    &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;/1     Completed           &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;          2m&lt;br /&gt;vaultwarden-test-cnpg-main-1-full-recovery-gpx84    &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;/1     Completed           &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;          2m&lt;br /&gt;vaultwarden-test-cnpg-main-2-join-kpnrz             &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;/1     Completed           &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;          51s&lt;br /&gt;vaultwarden-test-cnpg-main-2-join-kpnrz             &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;/1     Completed           &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;          51s&lt;br /&gt;vaultwarden-test-7996596577-vtfsl                   &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;/1     Running             &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;          2m9s&lt;br /&gt;volsync-src-vaultwarden-test-data-data-464ws        &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;/1     Running             &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;          72s&lt;br /&gt;volsync-src-vaultwarden-test-data-data-464ws        &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;/1     Completed           &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;          78s&lt;br /&gt;volsync-src-vaultwarden-test-data-data-464ws        &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;/1     Completed           &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;          80s&lt;br /&gt;volsync-src-vaultwarden-test-data-data-464ws        &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;/1     Completed           &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;          80s&lt;br /&gt;volsync-src-vaultwarden-test-data-data-464ws        &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;/1     Completed           &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;          81s&lt;br /&gt;volsync-src-vaultwarden-test-data-data-464ws        &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;/1     Completed           &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;          81s&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;You’ll know it worked when the main vaultwarden pod reaches ready status. Once it does, you should be able to log in and verify your test record.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;http://localhost:8080/assets/images/2025/11/vaultwarden-test-restore-longhorn.png&quot; alt=&quot;image&quot; /&gt;&lt;/p&gt;
&lt;p&gt;If you run into any issues during the restore, use kubectl to inspect pods in the namespace and look for any errors. Most common points of failure are unfulfilled persistent volume claims due to issues with VolSync, or failure of one of the CNPG pods.&lt;/p&gt;
&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;$ kubectl logs &lt;span class=&quot;token parameter variable&quot;&gt;-n&lt;/span&gt; volsync volsync-8547d688c4-hf8ns volsync&lt;br /&gt;$ kubectl logs &lt;span class=&quot;token parameter variable&quot;&gt;-n&lt;/span&gt; cloudnative-pg cloudnative-pg-777f845d49-qssn5 manager&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;Advice and Troubleshooting Tips&lt;/h2&gt;
&lt;p&gt;Of all the features of the TrueCharts&#92;K8S ecosystem, I would say I struggled the most with VolSync and CNPG, mostly because testing and breaking this is costly, and when things went wrong I would have to start all over. Almost the entire point of this whole series was wanting to really work out this backup component and try to share the guide for truecharts backups I wished I had when I set out on this project.&lt;/p&gt;
&lt;h3&gt;1. Replication is not backup&lt;/h3&gt;
&lt;p&gt;The title of this post is a bit of a misnomer… CNPG provides true backups through it’s revision feature, but VolSync is exactly what it says. A synchronization tool, not a backup tool. More than once I accidentally overwrote my ‘backups’ while trying to restore. Consider taking snapshots of your S3 buckets for an extra layer of protection.&lt;/p&gt;
&lt;h3&gt;2. Be safe, waste the space&lt;/h3&gt;
&lt;p&gt;You may notice that in my deployment cleanupTempPVC and cleanupCachePVC are set to false. I started doing this when I had issues restoring from VolSync backups, and found that VolSync was complaining that the target snapshot wasn’t available. This would cause volumes to be created, but VolSync wouldn’t &#39;release them, and the storage claim would never be fulfilled. I’m not sure exactly what the bug is, but one of the guys from TrueCharts told me there was a bug in VolSync and I should disable these features. I haven’t had any issues since.&lt;/p&gt;
&lt;h3&gt;3. Watch for volume not ready errors&lt;/h3&gt;
&lt;p&gt;While performing restore operations, keep an eye on pods as they spin up. If VolSync restore fails, your first hint will be that the pod is stuck in the pending state. If you check in longhorn, the volume will exist but will be in a not ready for workloads state because VolSync didn’t finish it’s job and release it. (see tip #2.) Inspect pods with kubectl describe pod to check for this.&lt;/p&gt;
&lt;h3&gt;4. Optionally manage CNPG Revisions manually&lt;/h3&gt;
&lt;p&gt;In earlier versions of the truecharts common library, CNPG required a revision statement for backup and recovery targets. This is no longer required, but is still supported if you want to manually manage backup revisions. If you do this, make sure you set the correct revision to restore, and also set the backup to an unused revision number, otherwise CNPG will complain about finding existing backups where it’s trying to write new ones.&lt;/p&gt;
&lt;pre class=&quot;language-yaml&quot;&gt;&lt;code class=&quot;language-yaml&quot;&gt;  &lt;span class=&quot;token key atrule&quot;&gt;cnpg&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;      &lt;span class=&quot;token key atrule&quot;&gt;main&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token key atrule&quot;&gt;cluster&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;          &lt;span class=&quot;token key atrule&quot;&gt;singleNode&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean important&quot;&gt;true&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token key atrule&quot;&gt;mode&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; recovery&lt;br /&gt;        &lt;span class=&quot;token key atrule&quot;&gt;backups&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;          &lt;span class=&quot;token key atrule&quot;&gt;enabled&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean important&quot;&gt;true&lt;/span&gt;&lt;br /&gt;          &lt;span class=&quot;token key atrule&quot;&gt;revision&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;2&quot;&lt;/span&gt;&lt;br /&gt;          &lt;span class=&quot;token key atrule&quot;&gt;credentials&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; backblaze&lt;br /&gt;          &lt;span class=&quot;token key atrule&quot;&gt;scheduledBackups&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;            &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token key atrule&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; daily&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;backup&lt;br /&gt;              &lt;span class=&quot;token key atrule&quot;&gt;schedule&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;0 5 0 * * *&quot;&lt;/span&gt;&lt;br /&gt;              &lt;span class=&quot;token key atrule&quot;&gt;backupOwnerReference&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; self&lt;br /&gt;              &lt;span class=&quot;token key atrule&quot;&gt;immediate&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean important&quot;&gt;true&lt;/span&gt;&lt;br /&gt;              &lt;span class=&quot;token key atrule&quot;&gt;suspend&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean important&quot;&gt;false&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token key atrule&quot;&gt;recovery&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;          &lt;span class=&quot;token key atrule&quot;&gt;method&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; object_store&lt;br /&gt;          &lt;span class=&quot;token key atrule&quot;&gt;revision&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;1&quot;&lt;/span&gt;&lt;br /&gt;          &lt;span class=&quot;token key atrule&quot;&gt;credentials&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; backblaze&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;Sources&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://trueforge.org/truetech/truecharts-common/cnpg/cnpg/&quot;&gt;trueforge.org: CNPG&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://trueforge.org/truetech/truecharts/guides/backup--restore/volsync-backup-restore/&quot;&gt;trueforge.org: VolSync&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://trueforge.org/news/chart-backups-and-restores/&quot;&gt;trueforge.org: Enhanced Chart Backup and Restore Solutions&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
</content>
    </entry>
    
    <entry>
      <title>TrueK8S Part 09</title>
      <link href="http://localhost:8080/2025/11/29/truek8s-part-09/"/>
      <updated>2025-11-29T12:30:00Z</updated>
      <id>http://localhost:8080/2025/11/29/truek8s-part-09/</id>
      <content type="html">&lt;h2&gt;Tying It All Together&lt;/h2&gt;
&lt;p&gt;We’ve finally configured all of the infrastructure components of our cluster. We have Flux, secure secret management, certificate management, ingress, and a backup/replication solution. We’re finally ready to deploy a Helm chart that takes advantage of all of these features in our cluster.&lt;/p&gt;
&lt;p&gt;I can’t think of a better example than Nextcloud. Nextcloud was something I had always wanted to host in my homelab to de-consumer-cloud my life, but I never quite got around to it. I never had a solution that felt stable enough to depend on. Through this project, I’ve finally figured out answers to the storage, secure access, and resilience concerns I had about running Nextcloud myself. If you’ve been following along, you should be well equipped to do the same.&lt;/p&gt;
&lt;h2&gt;Mounting NFS share for Nextcloud&lt;/h2&gt;
&lt;p&gt;Before we get started, we need to configure an NFS share for Nextcloud. In Part 7 I was complaining about how NFS was a poor solution for PVC storage. That is true, but there are some cases in which NFS makes sense. Nextcloud will have a particularly large dataset, and it doesn’t make sense to stuff that data into a PVC and try to manage it with VolSync. It makes more sense to keep that data external and to do snapshots/backups on the storage side. I’ll be hosting an NFS share on my TrueNAS server.&lt;/p&gt;
&lt;h3&gt;Configure the Share&lt;/h3&gt;
&lt;p&gt;Details of configuring an NFS share are beyond the scope of this series, but I will summarize by showing you the dataset I’m sharing. Note the permissions are set to ‘apps:apps’ which is the security context for TrueCharts apps (coming from the default apps user in TrueNAS). Also note below how the path you see in TrueNAS relates to the NFS patch you’ll use in your cluster config.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;http://localhost:8080/assets/images/2025/11/nextcloud-demo-dataset.png&quot; alt=&quot;image&quot; /&gt;&lt;/p&gt;
&lt;h3&gt;Save Secrets in cluster-config&lt;/h3&gt;
&lt;p&gt;You’ll need to save some config options for Nextcloud, so get those in your ConfigMap first. You need to create a username and password, specify your NFS server IP and path, and also a unique credential for the collabora service account. Collabora will complain if there are non-alphanumeric characters in its password, so look out for that.&lt;/p&gt;
&lt;pre class=&quot;language-yaml&quot;&gt;&lt;code class=&quot;language-yaml&quot;&gt;&lt;span class=&quot;token key atrule&quot;&gt;apiVersion&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; v1&lt;br /&gt;&lt;span class=&quot;token key atrule&quot;&gt;kind&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; ConfigMap&lt;br /&gt;&lt;span class=&quot;token key atrule&quot;&gt;metadata&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token key atrule&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; cluster&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;config&lt;br /&gt;    &lt;span class=&quot;token key atrule&quot;&gt;namespace&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; flux&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;system&lt;br /&gt;&lt;span class=&quot;token key atrule&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token key atrule&quot;&gt;NEXTCLOUDDEMO_PASSWORD&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; PASSWORD&lt;br /&gt;    &lt;span class=&quot;token key atrule&quot;&gt;NEXTCLOUDDEMO_USER&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; USERNAME&lt;br /&gt;    &lt;span class=&quot;token key atrule&quot;&gt;NEXTCLOUDDEMOCOLLABORA_PASSWORD&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; PASSWORD &lt;span class=&quot;token comment&quot;&gt;#ALPHANUMERIC ONLY&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token key atrule&quot;&gt;NEXTCLOUDDEMO_NFS_PATH&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; /mnt/Pool1/nextcloud&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;demo&lt;br /&gt;    &lt;span class=&quot;token key atrule&quot;&gt;NEXTCLOUDDEMO_NFS_IP&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; 192.168.XX.X&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Then go ahead and save your ConfigMap and push it to the repo&lt;/p&gt;
&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;$ sops &lt;span class=&quot;token parameter variable&quot;&gt;-e&lt;/span&gt; &lt;span class=&quot;token parameter variable&quot;&gt;-i&lt;/span&gt; cluster-config.yaml &lt;br /&gt;$ &lt;span class=&quot;token function&quot;&gt;git&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;add&lt;/span&gt; &lt;span class=&quot;token parameter variable&quot;&gt;-A&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;git&lt;/span&gt; commit &lt;span class=&quot;token parameter variable&quot;&gt;-m&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;added nextcloud secrets to cluster-config&#39;&lt;/span&gt;&lt;br /&gt;$ &lt;span class=&quot;token function&quot;&gt;git&lt;/span&gt; push&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;Deploying Nextcloud&lt;/h2&gt;
&lt;p&gt;Create deployment manifests for Nextcloud. Remember, we’ll define the application itself in the apps directory, and then use a kustomization in production to apply it.&lt;/p&gt;
&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;apps&lt;br /&gt;├── general&lt;br /&gt;│ └── nextcloud-demo&lt;br /&gt;│   ├── helm-release.yaml&lt;br /&gt;│   ├── kustomization.yaml&lt;br /&gt;│   └── namespace.yaml&lt;br /&gt;└── production&lt;br /&gt;    └── nextcloud.yaml&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;./apps/general/nextcloud&lt;/h3&gt;
&lt;h4&gt;helm-release.yaml&lt;/h4&gt;
&lt;p&gt;There are a couple unique items to pay attention to in this manifest.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;I’m using a custom ingress route to route /collabora traffic to a different service&lt;/li&gt;
&lt;li&gt;The NFS share is declared as a persistence item&lt;/li&gt;
&lt;li&gt;The CNPG recovery configuration is staged but commented out&lt;/li&gt;
&lt;li&gt;Cleanup for VolSync is disabled&lt;/li&gt;
&lt;li&gt;spec.value.podOptions.hostUsers is set to true - this prevents an odd ‘no space left on device issue’ and I recommend this for all of your charts.&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&quot;language-yaml&quot;&gt;&lt;code class=&quot;language-yaml&quot;&gt;&lt;span class=&quot;token key atrule&quot;&gt;apiVersion&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; helm.toolkit.fluxcd.io/v2&lt;br /&gt;&lt;span class=&quot;token key atrule&quot;&gt;kind&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; HelmRelease&lt;br /&gt;&lt;span class=&quot;token key atrule&quot;&gt;metadata&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token key atrule&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; nextcloud&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;demo&lt;br /&gt;    &lt;span class=&quot;token key atrule&quot;&gt;namespace&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; nextcloud&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;demo&lt;br /&gt;&lt;span class=&quot;token key atrule&quot;&gt;spec&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token key atrule&quot;&gt;interval&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; 5m&lt;br /&gt;    &lt;span class=&quot;token key atrule&quot;&gt;chart&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token key atrule&quot;&gt;spec&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;            &lt;span class=&quot;token key atrule&quot;&gt;chart&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; nextcloud&lt;br /&gt;            &lt;span class=&quot;token key atrule&quot;&gt;sourceRef&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;                &lt;span class=&quot;token key atrule&quot;&gt;kind&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; HelmRepository&lt;br /&gt;                &lt;span class=&quot;token key atrule&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; truecharts&lt;br /&gt;                &lt;span class=&quot;token key atrule&quot;&gt;namespace&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; flux&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;system&lt;br /&gt;            &lt;span class=&quot;token key atrule&quot;&gt;interval&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; 5m&lt;br /&gt;    &lt;span class=&quot;token key atrule&quot;&gt;install&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token key atrule&quot;&gt;createNamespace&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean important&quot;&gt;true&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token key atrule&quot;&gt;crds&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; CreateReplace&lt;br /&gt;        &lt;span class=&quot;token key atrule&quot;&gt;remediation&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;            &lt;span class=&quot;token key atrule&quot;&gt;retries&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token key atrule&quot;&gt;upgrade&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token key atrule&quot;&gt;crds&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; CreateReplace&lt;br /&gt;        &lt;span class=&quot;token key atrule&quot;&gt;remediation&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;            &lt;span class=&quot;token key atrule&quot;&gt;retries&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token key atrule&quot;&gt;timeout&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; 30m&lt;br /&gt;    &lt;span class=&quot;token key atrule&quot;&gt;values&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;      &lt;span class=&quot;token key atrule&quot;&gt;podOptions&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token key atrule&quot;&gt;hostUsers&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean important&quot;&gt;true&lt;/span&gt;&lt;br /&gt;      &lt;span class=&quot;token key atrule&quot;&gt;global&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token key atrule&quot;&gt;stopAll&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean important&quot;&gt;false&lt;/span&gt;&lt;br /&gt;      &lt;span class=&quot;token key atrule&quot;&gt;credentials&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token key atrule&quot;&gt;backblaze&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;          &lt;span class=&quot;token key atrule&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; s3&lt;br /&gt;          &lt;span class=&quot;token key atrule&quot;&gt;url&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;${S3_URL}&quot;&lt;/span&gt;&lt;br /&gt;          &lt;span class=&quot;token key atrule&quot;&gt;bucket&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;${S3_BUCKET}-nextcloud-demo&quot;&lt;/span&gt;&lt;br /&gt;          &lt;span class=&quot;token key atrule&quot;&gt;accessKey&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;${S3_ACCESS_KEY}&quot;&lt;/span&gt;&lt;br /&gt;          &lt;span class=&quot;token key atrule&quot;&gt;secretKey&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;${S3_SECRET_KEY}&quot;&lt;/span&gt;&lt;br /&gt;          &lt;span class=&quot;token key atrule&quot;&gt;encrKey&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;${S3_ENCRYPTION_KEY}&quot;&lt;/span&gt;&lt;br /&gt;      &lt;span class=&quot;token key atrule&quot;&gt;ingress&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token key atrule&quot;&gt;main&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;          &lt;span class=&quot;token key atrule&quot;&gt;enabled&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean important&quot;&gt;true&lt;/span&gt;&lt;br /&gt;          &lt;span class=&quot;token key atrule&quot;&gt;ingressClassName&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; internal&lt;br /&gt;          &lt;span class=&quot;token key atrule&quot;&gt;integrations&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;            &lt;span class=&quot;token key atrule&quot;&gt;traefik&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;              &lt;span class=&quot;token key atrule&quot;&gt;enabled&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean important&quot;&gt;false&lt;/span&gt;&lt;br /&gt;            &lt;span class=&quot;token key atrule&quot;&gt;certManager&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;              &lt;span class=&quot;token key atrule&quot;&gt;enabled&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean important&quot;&gt;true&lt;/span&gt;&lt;br /&gt;              &lt;span class=&quot;token key atrule&quot;&gt;certificateIssuer&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; letsencrypt&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;domain&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;br /&gt;          &lt;span class=&quot;token key atrule&quot;&gt;hosts&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;            &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token key atrule&quot;&gt;host&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; nextclouddemo.$&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;DOMAIN_0&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;              &lt;span class=&quot;token key atrule&quot;&gt;paths&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;                &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token key atrule&quot;&gt;path&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; /&lt;br /&gt;                  &lt;span class=&quot;token key atrule&quot;&gt;pathType&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; Prefix&lt;br /&gt;        &lt;span class=&quot;token key atrule&quot;&gt;cloudflare&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;          &lt;span class=&quot;token key atrule&quot;&gt;enabled&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean important&quot;&gt;true&lt;/span&gt;&lt;br /&gt;          &lt;span class=&quot;token key atrule&quot;&gt;ingressClassName&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; cloudflare&lt;br /&gt;          &lt;span class=&quot;token key atrule&quot;&gt;integrations&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;            &lt;span class=&quot;token key atrule&quot;&gt;traefik&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;              &lt;span class=&quot;token key atrule&quot;&gt;enabled&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean important&quot;&gt;false&lt;/span&gt;&lt;br /&gt;          &lt;span class=&quot;token key atrule&quot;&gt;hosts&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;          &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token key atrule&quot;&gt;host&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; nextclouddemo.$&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;DOMAIN_0&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;            &lt;span class=&quot;token key atrule&quot;&gt;paths&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;            &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token key atrule&quot;&gt;path&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; /collabora/&lt;br /&gt;              &lt;span class=&quot;token key atrule&quot;&gt;pathType&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; Prefix&lt;br /&gt;              &lt;span class=&quot;token key atrule&quot;&gt;overrideService&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;                &lt;span class=&quot;token key atrule&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; collabora&lt;br /&gt;                &lt;span class=&quot;token key atrule&quot;&gt;port&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;9980&lt;/span&gt;&lt;br /&gt;            &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token key atrule&quot;&gt;path&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; /&lt;br /&gt;              &lt;span class=&quot;token key atrule&quot;&gt;pathType&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; Prefix&lt;br /&gt;      &lt;span class=&quot;token key atrule&quot;&gt;cnpg&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token key atrule&quot;&gt;main&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;          &lt;span class=&quot;token key atrule&quot;&gt;cluster&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;            &lt;span class=&quot;token key atrule&quot;&gt;singleNode&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean important&quot;&gt;true&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token comment&quot;&gt;#          mode: recovery&lt;/span&gt;&lt;br /&gt;          &lt;span class=&quot;token key atrule&quot;&gt;backups&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;            &lt;span class=&quot;token key atrule&quot;&gt;enabled&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean important&quot;&gt;true&lt;/span&gt;&lt;br /&gt;            &lt;span class=&quot;token key atrule&quot;&gt;credentials&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; backblaze&lt;br /&gt;            &lt;span class=&quot;token key atrule&quot;&gt;scheduledBackups&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;              &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token key atrule&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; daily&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;backup&lt;br /&gt;                &lt;span class=&quot;token key atrule&quot;&gt;schedule&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;0 0 0 * * *&quot;&lt;/span&gt;&lt;br /&gt;                &lt;span class=&quot;token key atrule&quot;&gt;backupOwnerReference&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; self&lt;br /&gt;                &lt;span class=&quot;token key atrule&quot;&gt;immediate&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean important&quot;&gt;true&lt;/span&gt;&lt;br /&gt;                &lt;span class=&quot;token key atrule&quot;&gt;suspend&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean important&quot;&gt;false&lt;/span&gt;&lt;br /&gt;          &lt;span class=&quot;token key atrule&quot;&gt;recovery&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;            &lt;span class=&quot;token key atrule&quot;&gt;method&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; object_store&lt;br /&gt;            &lt;span class=&quot;token key atrule&quot;&gt;credentials&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; backblaze&lt;br /&gt;      &lt;span class=&quot;token key atrule&quot;&gt;persistence&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token key atrule&quot;&gt;config&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;          &lt;span class=&quot;token key atrule&quot;&gt;accessModes&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;br /&gt;            &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; ReadWriteMany&lt;br /&gt;          &lt;span class=&quot;token key atrule&quot;&gt;volsync&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;          &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token key atrule&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; config&lt;br /&gt;            &lt;span class=&quot;token key atrule&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; restic&lt;br /&gt;            &lt;span class=&quot;token key atrule&quot;&gt;cleanupTempPVC&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean important&quot;&gt;false&lt;/span&gt;&lt;br /&gt;            &lt;span class=&quot;token key atrule&quot;&gt;cleanupCachePVC&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean important&quot;&gt;false&lt;/span&gt;&lt;br /&gt;            &lt;span class=&quot;token key atrule&quot;&gt;credentials&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; backblaze&lt;br /&gt;            &lt;span class=&quot;token key atrule&quot;&gt;dest&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;              &lt;span class=&quot;token key atrule&quot;&gt;enabled&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean important&quot;&gt;true&lt;/span&gt;&lt;br /&gt;            &lt;span class=&quot;token key atrule&quot;&gt;src&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;              &lt;span class=&quot;token key atrule&quot;&gt;enabled&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean important&quot;&gt;true&lt;/span&gt;&lt;br /&gt;              &lt;span class=&quot;token key atrule&quot;&gt;trigger&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;                &lt;span class=&quot;token key atrule&quot;&gt;schedule&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; 10 1 * * *&lt;br /&gt;        &lt;span class=&quot;token key atrule&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;          &lt;span class=&quot;token key atrule&quot;&gt;enabled&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean important&quot;&gt;true&lt;/span&gt;&lt;br /&gt;          &lt;span class=&quot;token key atrule&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; nfs&lt;br /&gt;          &lt;span class=&quot;token key atrule&quot;&gt;path&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; $&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;NEXTCLOUDDEMO_NFS_PATH&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;          &lt;span class=&quot;token key atrule&quot;&gt;server&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; $&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;NEXTCLOUDDEMO_NFS_IP&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token key atrule&quot;&gt;html&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;          &lt;span class=&quot;token key atrule&quot;&gt;accessModes&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;br /&gt;            &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; ReadWriteMany&lt;br /&gt;          &lt;span class=&quot;token key atrule&quot;&gt;volsync&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;          &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token key atrule&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; html&lt;br /&gt;            &lt;span class=&quot;token key atrule&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; restic&lt;br /&gt;            &lt;span class=&quot;token key atrule&quot;&gt;cleanupTempPVC&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean important&quot;&gt;false&lt;/span&gt;&lt;br /&gt;            &lt;span class=&quot;token key atrule&quot;&gt;cleanupCachePVC&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean important&quot;&gt;false&lt;/span&gt;&lt;br /&gt;            &lt;span class=&quot;token key atrule&quot;&gt;credentials&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; backblaze&lt;br /&gt;            &lt;span class=&quot;token key atrule&quot;&gt;dest&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;              &lt;span class=&quot;token key atrule&quot;&gt;enabled&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean important&quot;&gt;true&lt;/span&gt;&lt;br /&gt;            &lt;span class=&quot;token key atrule&quot;&gt;src&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;              &lt;span class=&quot;token key atrule&quot;&gt;enabled&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean important&quot;&gt;true&lt;/span&gt;&lt;br /&gt;              &lt;span class=&quot;token key atrule&quot;&gt;trigger&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;                &lt;span class=&quot;token key atrule&quot;&gt;schedule&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; 20 1 * * *&lt;br /&gt;      &lt;span class=&quot;token key atrule&quot;&gt;nextcloud&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token key atrule&quot;&gt;clamav&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;          &lt;span class=&quot;token key atrule&quot;&gt;enabled&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean important&quot;&gt;true&lt;/span&gt;&lt;br /&gt;          &lt;span class=&quot;token key atrule&quot;&gt;infected_action&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; delete&lt;br /&gt;        &lt;span class=&quot;token key atrule&quot;&gt;collabora&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;          &lt;span class=&quot;token key atrule&quot;&gt;enabled&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean important&quot;&gt;true&lt;/span&gt;&lt;br /&gt;          &lt;span class=&quot;token key atrule&quot;&gt;password&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;${NEXTCLOUDDEMOCOLLABORA_PASSWORD}&quot;&lt;/span&gt;&lt;br /&gt;          &lt;span class=&quot;token key atrule&quot;&gt;dictionaries&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;            &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; en_US&lt;br /&gt;        &lt;span class=&quot;token key atrule&quot;&gt;credentials&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;          &lt;span class=&quot;token key atrule&quot;&gt;initialAdminPassword&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;${NEXTCLOUDDEMO_PASSWORD}&quot;&lt;/span&gt;&lt;br /&gt;          &lt;span class=&quot;token key atrule&quot;&gt;initialAdminUser&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;${NEXTCLOUDDEMO_USER}&quot;&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token key atrule&quot;&gt;general&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;          &lt;span class=&quot;token key atrule&quot;&gt;accessIP&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; $&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;NGINX_IP&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;          &lt;span class=&quot;token key atrule&quot;&gt;default_phone_region&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; US&lt;/code&gt;&lt;/pre&gt;
&lt;h4&gt;namespace.yaml&lt;/h4&gt;
&lt;pre class=&quot;language-yaml&quot;&gt;&lt;code class=&quot;language-yaml&quot;&gt;&lt;span class=&quot;token key atrule&quot;&gt;apiVersion&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; v1&lt;br /&gt;&lt;span class=&quot;token key atrule&quot;&gt;kind&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; Namespace&lt;br /&gt;&lt;span class=&quot;token key atrule&quot;&gt;metadata&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token key atrule&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; nextcloud&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;demo&lt;/code&gt;&lt;/pre&gt;
&lt;h4&gt;kustomization.yaml&lt;/h4&gt;
&lt;pre class=&quot;language-yaml&quot;&gt;&lt;code class=&quot;language-yaml&quot;&gt;&lt;span class=&quot;token key atrule&quot;&gt;apiVersion&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; kustomize.config.k8s.io/v1beta1&lt;br /&gt;&lt;span class=&quot;token key atrule&quot;&gt;kind&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; Kustomization&lt;br /&gt;&lt;span class=&quot;token key atrule&quot;&gt;resources&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; namespace.yaml&lt;br /&gt;  &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; helm&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;release.yaml&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;./apps/production/&lt;/h3&gt;
&lt;h4&gt;nextcloud.yaml&lt;/h4&gt;
&lt;pre class=&quot;language-yaml&quot;&gt;&lt;code class=&quot;language-yaml&quot;&gt;&lt;span class=&quot;token key atrule&quot;&gt;apiVersion&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; kustomize.toolkit.fluxcd.io/v1&lt;br /&gt;&lt;span class=&quot;token key atrule&quot;&gt;kind&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; Kustomization&lt;br /&gt;&lt;span class=&quot;token key atrule&quot;&gt;metadata&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token key atrule&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; nextcloud&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;demo&lt;br /&gt;  &lt;span class=&quot;token key atrule&quot;&gt;namespace&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; flux&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;system&lt;br /&gt;&lt;span class=&quot;token key atrule&quot;&gt;spec&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token key atrule&quot;&gt;interval&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; 10m&lt;br /&gt;  &lt;span class=&quot;token key atrule&quot;&gt;path&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; apps/general/nextcloud&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;demo&lt;br /&gt;  &lt;span class=&quot;token key atrule&quot;&gt;prune&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean important&quot;&gt;true&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token key atrule&quot;&gt;sourceRef&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token key atrule&quot;&gt;kind&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; GitRepository&lt;br /&gt;    &lt;span class=&quot;token key atrule&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; flux&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;system&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;And don’t forget to add nextcloud-demo.yaml to the production kustomization&lt;/p&gt;
&lt;pre class=&quot;language-yaml&quot;&gt;&lt;code class=&quot;language-yaml&quot;&gt;&lt;span class=&quot;token key atrule&quot;&gt;apiVersion&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; kustomize.config.k8s.io/v1beta1&lt;br /&gt;&lt;span class=&quot;token key atrule&quot;&gt;kind&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; Kustomization&lt;br /&gt;&lt;span class=&quot;token key atrule&quot;&gt;resources&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; nextcloud&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;demo.yaml&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Finally, commit your changes and watch&lt;/p&gt;
&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;token function&quot;&gt;git&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;add&lt;/span&gt; &lt;span class=&quot;token parameter variable&quot;&gt;-A&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;git&lt;/span&gt; commit &lt;span class=&quot;token parameter variable&quot;&gt;-m&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;added nextcloud-demo&quot;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token function&quot;&gt;git&lt;/span&gt; push&lt;br /&gt;&lt;br /&gt;$ flux events &lt;span class=&quot;token parameter variable&quot;&gt;--watch&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;grep&lt;/span&gt; nextcloud-demo&lt;br /&gt;0s      Normal  Progressing     Kustomization/apps      Kustomization/flux-system/nextcloud-demo created&lt;br /&gt;0s      Normal  Progressing     Kustomization/nextcloud-demo    Namespace/nextcloud-demo created                 &lt;br /&gt;                                                                HelmRelease/nextcloud-demo/nextcloud-demo created&lt;br /&gt;0s      Normal  ReconciliationSucceeded Kustomization/nextcloud-demo    Reconciliation finished &lt;span class=&quot;token keyword&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;104&lt;/span&gt;.88413ms, next run &lt;span class=&quot;token keyword&quot;&gt;in&lt;/span&gt; 10m0s&lt;br /&gt;0s      Normal  ChartPullSucceeded      HelmChart/nextcloud-demo-nextcloud-demo pulled &lt;span class=&quot;token string&quot;&gt;&#39;nextcloud&#39;&lt;/span&gt; chart with version &lt;span class=&quot;token string&quot;&gt;&#39;40.4.1&#39;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This will take quite some time to spin up. Be patient and inspect the results as it works. You can check the Longhorn console to view volumes as they’re created.&lt;br /&gt;
&lt;img src=&quot;http://localhost:8080/assets/images/2025/11/nextcloud-demo-deploy-longhorn.png&quot; alt=&quot;image&quot; /&gt;&lt;/p&gt;
&lt;p&gt;And you can watch the status of the containers as they spin up to monitor progress:&lt;/p&gt;
&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;$ kubectl get pods &lt;span class=&quot;token parameter variable&quot;&gt;-n&lt;/span&gt; nextcloud-demo &lt;span class=&quot;token parameter variable&quot;&gt;--watch&lt;/span&gt;&lt;br /&gt;NAME                                                  READY   STATUS              RESTARTS   AGE&lt;br /&gt;nextcloud-demo-7678bd6c84-tnktd                       &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;/1     Pending             &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;          10s&lt;br /&gt;nextcloud-demo-clamav-76d59bb979-jfz2r                &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;/1     Init:0/2            &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;          10s&lt;br /&gt;nextcloud-demo-cnpg-main-1-initdb-lmfxf               &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;/1     Init:0/1            &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;          9s&lt;br /&gt;nextcloud-demo-collabora-845c9c784-qr8rv              &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;/1     Init:0/2            &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;          10s&lt;br /&gt;nextcloud-demo-imaginary-77fd75cdcf-bbt6x             &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;/1     Init:0/2            &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;          10s&lt;br /&gt;nextcloud-demo-nginx-7b5d55df54-wk6fh                 &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;/1     Pending             &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;          10s&lt;br /&gt;nextcloud-demo-notify-654fd67c9c-dwx6b                &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;/1     Pending             &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;          10s&lt;br /&gt;nextcloud-demo-redis-0                                &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;/1     Running             &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;          10s&lt;br /&gt;volsync-dst-nextcloud-demo-config-config-dest-7fw4f   &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;/1     ContainerCreating   &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;          10s&lt;br /&gt;volsync-dst-nextcloud-demo-html-html-dest-827md       &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;/1     ContainerCreating   &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;          10s&lt;br /&gt;nextcloud-demo-cnpg-main-1-initdb-lmfxf               &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;/1     Init:0/1            &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;          17s&lt;br /&gt;nextcloud-demo-cnpg-main-1-initdb-lmfxf               &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;/1     PodInitializing     &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;          18s&lt;br /&gt;nextcloud-demo-cnpg-main-1-initdb-lmfxf               &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;/1     Running             &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;          19s&lt;br /&gt;nextcloud-demo-redis-0                                &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;/1     Running             &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;          20s&lt;br /&gt;nextcloud-demo-cnpg-main-1-initdb-lmfxf               &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;/1     Completed           &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;          20s&lt;br /&gt;nextcloud-demo-cnpg-main-1-initdb-lmfxf               &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;/1     Completed           &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;          21s&lt;br /&gt;nextcloud-demo-cnpg-main-1-initdb-lmfxf               &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;/1     Completed           &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;          22s&lt;br /&gt;volsync-dst-nextcloud-demo-html-html-dest-827md       &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;/1     Running             &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;          23s&lt;br /&gt;nextcloud-demo-cnpg-main-1                            &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;/1     Pending             &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;          0s&lt;br /&gt;nextcloud-demo-cnpg-main-1                            &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;/1     Pending             &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;          0s&lt;br /&gt;nextcloud-demo-cnpg-main-1                            &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;/1     Init:0/1            &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;          0s&lt;br /&gt;volsync-dst-nextcloud-demo-config-config-dest-7fw4f   &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;/1     Running             &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;          24s&lt;br /&gt;volsync-dst-nextcloud-demo-html-html-dest-827md       &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;/1     Completed           &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;          28s&lt;br /&gt;volsync-dst-nextcloud-demo-config-config-dest-7fw4f   &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;/1     Completed           &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;          29s&lt;br /&gt;volsync-dst-nextcloud-demo-html-html-dest-827md       &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;/1     Completed           &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;          29s&lt;br /&gt;volsync-dst-nextcloud-demo-html-html-dest-827md       &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;/1     Completed           &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;          30s&lt;br /&gt;volsync-dst-nextcloud-demo-config-config-dest-7fw4f   &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;/1     Completed           &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;          30s&lt;br /&gt;volsync-dst-nextcloud-demo-html-html-dest-827md       &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;/1     Completed           &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;          30s&lt;br /&gt;volsync-dst-nextcloud-demo-html-html-dest-827md       &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;/1     Completed           &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;          30s&lt;br /&gt;volsync-dst-nextcloud-demo-config-config-dest-7fw4f   &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;/1     Completed           &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;          31s&lt;br /&gt;nextcloud-demo-cnpg-main-1                            &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;/1     PodInitializing     &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;          9s&lt;br /&gt;volsync-dst-nextcloud-demo-config-config-dest-7fw4f   &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;/1     Completed           &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;          32s&lt;br /&gt;volsync-dst-nextcloud-demo-config-config-dest-7fw4f   &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;/1     Completed           &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;          32s&lt;br /&gt;nextcloud-demo-redis-0                                &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;/1     Running             &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;          32s&lt;br /&gt;nextcloud-demo-cnpg-main-1                            &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;/1     Running             &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;          10s&lt;br /&gt;nextcloud-demo-cnpg-main-1                            &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;/1     Running             &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;          11s&lt;br /&gt;nextcloud-demo-cnpg-main-1                            &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;/1     Running             &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;          17s&lt;br /&gt;nextcloud-demo-cnpg-main-1                            &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;/1     Running             &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;          18s&lt;br /&gt;nextcloud-demo-cnpg-main-2-join-lwbqg                 &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;/1     Pending             &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;          0s&lt;br /&gt;nextcloud-demo-cnpg-main-2-join-lwbqg                 &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;/1     Pending             &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;          0s&lt;br /&gt;nextcloud-demo-cnpg-main-2-join-lwbqg                 &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;/1     Pending             &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;          0s&lt;br /&gt;nextcloud-demo-7678bd6c84-tnktd                       &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;/1     Pending             &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;          42s&lt;br /&gt;nextcloud-demo-notify-654fd67c9c-dwx6b                &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;/1     Pending             &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;          42s&lt;br /&gt;nextcloud-demo-nginx-7b5d55df54-wk6fh                 &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;/1     Pending             &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;          42s&lt;br /&gt;nextcloud-demo-7678bd6c84-tnktd                       &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;/1     Init:0/3            &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;          42s&lt;br /&gt;nextcloud-demo-nginx-7b5d55df54-wk6fh                 &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;/1     Init:0/3            &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;          42s&lt;br /&gt;nextcloud-demo-notify-654fd67c9c-dwx6b                &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;/1     Init:0/3            &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;          42s&lt;br /&gt;nextcloud-demo-clamav-76d59bb979-jfz2r                &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;/1     Init:1/2            &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;          43s&lt;br /&gt;nextcloud-demo-collabora-845c9c784-qr8rv              &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;/1     Init:1/2            &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;          43s&lt;br /&gt;nextcloud-demo-imaginary-77fd75cdcf-bbt6x             &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;/1     Init:1/2            &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;          43s&lt;br /&gt;nextcloud-demo-cnpg-main-2-join-lwbqg                 &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;/1     Pending             &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;          3s&lt;br /&gt;nextcloud-demo-cnpg-main-2-join-lwbqg                 &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;/1     Init:0/1            &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;          3s&lt;br /&gt;nextcloud-demo-imaginary-77fd75cdcf-bbt6x             &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;/1     PodInitializing     &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;          44s&lt;br /&gt;nextcloud-demo-clamav-76d59bb979-jfz2r                &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;/1     PodInitializing     &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;          44s&lt;br /&gt;nextcloud-demo-collabora-845c9c784-qr8rv              &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;/1     PodInitializing     &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;          44s&lt;br /&gt;nextcloud-demo-clamav-76d59bb979-jfz2r                &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;/1     Running             &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;          45s&lt;br /&gt;nextcloud-demo-imaginary-77fd75cdcf-bbt6x             &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;/1     Running             &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;          56s&lt;br /&gt;nextcloud-demo-imaginary-77fd75cdcf-bbt6x             &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;/1     Running             &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;          70s&lt;br /&gt;nextcloud-demo-clamav-76d59bb979-jfz2r                &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;/1     Running             &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;          75s&lt;br /&gt;nextcloud-demo-cnpg-main-2-join-lwbqg                 &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;/1     Init:0/1            &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;          54s&lt;br /&gt;nextcloud-demo-imaginary-77fd75cdcf-bbt6x             &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;/1     Running             &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;          98s&lt;br /&gt;nextcloud-demo-clamav-76d59bb979-jfz2r                &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;/1     Running             &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;          98s&lt;br /&gt;nextcloud-demo-cnpg-main-2-join-lwbqg                 &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;/1     PodInitializing     &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;          58s&lt;br /&gt;nextcloud-demo-cnpg-main-2-join-lwbqg                 &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;/1     Running             &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;          60s&lt;br /&gt;nextcloud-demo-collabora-845c9c784-qr8rv              &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;/1     Running             &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;          102s&lt;br /&gt;nextcloud-demo-cnpg-main-2-join-lwbqg                 &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;/1     Completed           &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;          74s&lt;br /&gt;nextcloud-demo-collabora-845c9c784-qr8rv              &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;/1     Running             &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;          115s&lt;br /&gt;nextcloud-demo-cnpg-main-2-join-lwbqg                 &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;/1     Completed           &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;          75s&lt;br /&gt;volsync-src-nextcloud-demo-config-config-4g24x        &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;/1     Pending             &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;          1s&lt;br /&gt;nextcloud-demo-nextcloud-cron-29405805-bz2bs          &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;/1     Pending             &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;          1s&lt;br /&gt;volsync-src-nextcloud-demo-html-html-94mkf            &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;/1     Pending             &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;          1s&lt;br /&gt;volsync-src-nextcloud-demo-config-config-4g24x        &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;/1     Pending             &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;          1s&lt;br /&gt;nextcloud-demo-nextcloud-cron-29405805-bz2bs          &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;/1     Pending             &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;          1s&lt;br /&gt;volsync-src-nextcloud-demo-html-html-94mkf            &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;/1     Pending             &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;          1s&lt;br /&gt;nextcloud-demo-cnpg-main-2-join-lwbqg                 &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;/1     Completed           &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;          79s&lt;br /&gt;nextcloud-demo-nextcloud-cron-29405805-bz2bs          &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;/1     ContainerCreating   &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;          1s&lt;br /&gt;nextcloud-demo-cnpg-main-2                            &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;/1     Pending             &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;          0s&lt;br /&gt;nextcloud-demo-cnpg-main-2                            &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;/1     Pending             &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;          0s&lt;br /&gt;nextcloud-demo-cnpg-main-2                            &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;/1     Init:0/1            &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;          0s&lt;br /&gt;volsync-src-nextcloud-demo-config-config-4g24x        &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;/1     Pending             &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;          4s&lt;br /&gt;volsync-src-nextcloud-demo-html-html-94mkf            &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;/1     Pending             &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;          4s&lt;br /&gt;volsync-src-nextcloud-demo-config-config-4g24x        &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;/1     ContainerCreating   &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;          4s&lt;br /&gt;volsync-src-nextcloud-demo-html-html-94mkf            &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;/1     ContainerCreating   &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;          4s&lt;br /&gt;nextcloud-demo-collabora-845c9c784-qr8rv              &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;/1     Running             &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;          2m7s&lt;br /&gt;nextcloud-demo-cnpg-main-2                            &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;/1     Init:0/1            &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;          9s&lt;br /&gt;nextcloud-demo-cnpg-main-2                            &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;/1     PodInitializing     &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;          9s&lt;br /&gt;nextcloud-demo-cnpg-main-2                            &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;/1     Running             &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;          10s&lt;br /&gt;nextcloud-demo-cnpg-main-2                            &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;/1     Running             &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;          12s&lt;br /&gt;nextcloud-demo-cnpg-main-2                            &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;/1     Running             &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;          17s&lt;br /&gt;nextcloud-demo-cnpg-main-2                            &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;/1     Running             &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;          18s&lt;br /&gt;nextcloud-demo-cnpg-main-1-initdb-lmfxf               &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;/1     Completed           &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;          2m18s&lt;br /&gt;nextcloud-demo-cnpg-main-1-initdb-lmfxf               &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;/1     Completed           &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;          2m18s&lt;br /&gt;nextcloud-demo-cnpg-main-2-join-lwbqg                 &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;/1     Completed           &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;          98s&lt;br /&gt;nextcloud-demo-cnpg-main-2-join-lwbqg                 &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;/1     Completed           &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;          98s&lt;br /&gt;nextcloud-demo-7678bd6c84-tnktd                       &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;/1     Init:1/3            &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;          2m43s&lt;br /&gt;nextcloud-demo-nginx-7b5d55df54-wk6fh                 &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;/1     Init:0/3            &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;          2m44s&lt;br /&gt;nextcloud-demo-nginx-7b5d55df54-wk6fh                 &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;/1     Init:1/3            &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;          2m45s&lt;br /&gt;nextcloud-demo-notify-654fd67c9c-dwx6b                &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;/1     Init:1/3            &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;          2m46s&lt;br /&gt;nextcloud-demo-nextcloud-cron-29405805-bz2bs          &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;/1     Completed           &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;          47s&lt;br /&gt;nextcloud-demo-nextcloud-cron-29405805-bz2bs          &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;/1     Completed           &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;          47s&lt;br /&gt;nextcloud-demo-7678bd6c84-tnktd                       &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;/1     Init:2/3            &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;          2m46s&lt;br /&gt;nextcloud-demo-nginx-7b5d55df54-wk6fh                 &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;/1     Init:1/3            &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;          2m47s&lt;br /&gt;nextcloud-demo-nextcloud-cron-29405805-bz2bs          &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;/1     Completed           &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;          49s&lt;br /&gt;nextcloud-demo-nginx-7b5d55df54-wk6fh                 &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;/1     Init:2/3            &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;          2m48s&lt;br /&gt;nextcloud-demo-notify-654fd67c9c-dwx6b                &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;/1     Init:2/3            &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;          2m48s&lt;br /&gt;nextcloud-demo-7678bd6c84-tnktd                       &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;/1     PodInitializing     &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;          2m49s&lt;br /&gt;nextcloud-demo-nginx-7b5d55df54-wk6fh                 &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;/1     Init:2/3            &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;          2m51s&lt;br /&gt;nextcloud-demo-notify-654fd67c9c-dwx6b                &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;/1     Init:2/3            &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;          2m51s&lt;br /&gt;nextcloud-demo-7678bd6c84-tnktd                       &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;/1     Running             &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;          2m53s&lt;br /&gt;volsync-src-nextcloud-demo-html-html-94mkf            &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;/1     Running             &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;          77s&lt;br /&gt;volsync-src-nextcloud-demo-config-config-4g24x        &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;/1     Running             &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;          77s&lt;br /&gt;volsync-src-nextcloud-demo-html-html-94mkf            &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;/1     Completed           &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;          79s&lt;br /&gt;volsync-src-nextcloud-demo-config-config-4g24x        &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;/1     Completed           &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;          79s&lt;br /&gt;volsync-src-nextcloud-demo-html-html-94mkf            &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;/1     Completed           &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;          80s&lt;br /&gt;volsync-src-nextcloud-demo-html-html-94mkf            &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;/1     Completed           &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;          80s&lt;br /&gt;volsync-src-nextcloud-demo-config-config-4g24x        &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;/1     Completed           &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;          81s&lt;br /&gt;volsync-src-nextcloud-demo-html-html-94mkf            &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;/1     Completed           &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;          82s&lt;br /&gt;volsync-src-nextcloud-demo-html-html-94mkf            &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;/1     Completed           &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;          82s&lt;br /&gt;volsync-src-nextcloud-demo-config-config-4g24x        &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;/1     Completed           &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;          82s&lt;br /&gt;volsync-src-nextcloud-demo-config-config-4g24x        &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;/1     Completed           &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;          84s&lt;br /&gt;volsync-src-nextcloud-demo-config-config-4g24x        &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;/1     Completed           &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;          84s&lt;br /&gt;nextcloud-demo-nextcloud-cron-29405805-bz2bs          &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;/1     Completed           &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;          2m49s&lt;br /&gt;nextcloud-demo-nextcloud-cron-29405805-bz2bs          &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;/1     Completed           &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;          2m49s&lt;br /&gt;nextcloud-demo-7678bd6c84-tnktd                       &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;/1     Error               &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;          6m40s&lt;br /&gt;nextcloud-demo-7678bd6c84-tnktd                       &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;/1     Running             &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;1s ago&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;   6m41s&lt;br /&gt;nextcloud-demo-nextcloud-cron-29405810-nts66          &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;/1     Pending             &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;            0s&lt;br /&gt;nextcloud-demo-nextcloud-cron-29405810-nts66          &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;/1     Pending             &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;            0s&lt;br /&gt;nextcloud-demo-nextcloud-cron-29405810-nts66          &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;/1     ContainerCreating   &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;            0s&lt;br /&gt;nextcloud-demo-nextcloud-cron-29405810-nts66          &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;/1     Running             &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;            1s&lt;br /&gt;nextcloud-demo-nextcloud-cron-29405810-nts66          &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;/1     Completed           &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;            2s&lt;br /&gt;nextcloud-demo-nextcloud-cron-29405810-nts66          &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;/1     Completed           &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;            3s&lt;br /&gt;nextcloud-demo-nextcloud-cron-29405810-nts66          &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;/1     Completed           &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;            4s&lt;br /&gt;nextcloud-demo-nextcloud-cron-29405810-nts66          &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;/1     Completed           &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;            2m4s&lt;br /&gt;nextcloud-demo-nextcloud-cron-29405810-nts66          &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;/1     Completed           &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;            2m4s&lt;br /&gt;nextcloud-demo-7678bd6c84-tnktd                       &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;/1     Running             &lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;1s ago&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;   9m8s&lt;br /&gt;nextcloud-demo-nextcloud-cron-29405815-t6k7m          &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;/1     Pending             &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;            0s&lt;br /&gt;nextcloud-demo-nextcloud-cron-29405815-t6k7m          &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;/1     Pending             &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;            0s&lt;br /&gt;nextcloud-demo-nextcloud-cron-29405815-t6k7m          &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;/1     ContainerCreating   &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;            0s&lt;br /&gt;nextcloud-demo-nextcloud-cron-29405815-t6k7m          &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;/1     Completed           &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;            1s&lt;br /&gt;nextcloud-demo-nextcloud-cron-29405815-t6k7m          &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;/1     Completed           &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;            2s&lt;br /&gt;nextcloud-demo-nextcloud-cron-29405815-t6k7m          &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;/1     Completed           &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;            3s&lt;br /&gt;nextcloud-demo-nextcloud-cron-29405815-t6k7m          &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;/1     Completed           &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;            2m3s&lt;br /&gt;nextcloud-demo-nextcloud-cron-29405815-t6k7m          &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;/1     Completed           &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;            2m3s&lt;br /&gt;nextcloud-demo-7678bd6c84-tnktd                       &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;/1     Running             &lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;5m5s ago&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;   14m&lt;br /&gt;nextcloud-demo-7678bd6c84-tnktd                       &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;/1     Running             &lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;5m17s ago&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;   14m&lt;br /&gt;nextcloud-demo-nginx-7b5d55df54-wk6fh                 &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;/1     PodInitializing     &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;               14m&lt;br /&gt;nextcloud-demo-notify-654fd67c9c-dwx6b                &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;/1     PodInitializing     &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;               14m&lt;br /&gt;nextcloud-demo-nginx-7b5d55df54-wk6fh                 &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;/1     Running             &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;               14m&lt;br /&gt;nextcloud-demo-notify-654fd67c9c-dwx6b                &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;/1     Running             &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;               14m&lt;br /&gt;nextcloud-demo-nginx-7b5d55df54-wk6fh                 &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;/1     Running             &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;               14m&lt;br /&gt;nextcloud-demo-nginx-7b5d55df54-wk6fh                 &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;/1     Running             &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;               14m&lt;br /&gt;nextcloud-demo-notify-654fd67c9c-dwx6b                &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;/1     Running             &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;               14m&lt;br /&gt;nextcloud-demo-notify-654fd67c9c-dwx6b                &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;/1     Running             &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;               15m&lt;br /&gt;nextcloud-demo-nextcloud-cron-29405820-kl57w          &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;/1     Pending             &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;               0s&lt;br /&gt;nextcloud-demo-preview-cron-29405820-bgffl            &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;/1     Pending             &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;               0s&lt;br /&gt;nextcloud-demo-nextcloud-cron-29405820-kl57w          &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;/1     Pending             &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;               0s&lt;br /&gt;nextcloud-demo-preview-cron-29405820-bgffl            &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;/1     Pending             &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;               0s&lt;br /&gt;nextcloud-demo-nextcloud-cron-29405820-kl57w          &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;/1     ContainerCreating   &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;               0s&lt;br /&gt;nextcloud-demo-preview-cron-29405820-bgffl            &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;/1     ContainerCreating   &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;               0s&lt;br /&gt;nextcloud-demo-preview-cron-29405820-bgffl            &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;/1     Running             &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;               0s&lt;br /&gt;nextcloud-demo-nextcloud-cron-29405820-kl57w          &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;/1     Running             &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;               1s&lt;br /&gt;nextcloud-demo-preview-cron-29405820-bgffl            &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;/1     Completed           &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;               2s&lt;br /&gt;nextcloud-demo-preview-cron-29405820-bgffl            &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;/1     Completed           &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;               4s&lt;br /&gt;nextcloud-demo-preview-cron-29405820-bgffl            &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;/1     Completed           &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;               5s&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Once the main Nextcloud container spins up, you can check the logs to see what it’s doing. You’ll know it’s done when it starts logging HTTP requests.&lt;/p&gt;
&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;$ kubectl logs &lt;span class=&quot;token parameter variable&quot;&gt;-n&lt;/span&gt; nextcloud-demo nextcloud-demo-6695869969-2rdt5 &lt;br /&gt;Initializing nextcloud &lt;span class=&quot;token number&quot;&gt;32.0&lt;/span&gt;.1 &lt;span class=&quot;token punctuation&quot;&gt;..&lt;/span&gt;.&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;..&lt;/span&gt;.&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;br /&gt;--------------------------------------------------&lt;br /&gt;Starting Nextcloud PHP-FPM&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;28&lt;/span&gt;-Nov-2025 &lt;span class=&quot;token number&quot;&gt;16&lt;/span&gt;:57:23&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; NOTICE: &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;pool www&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;user&#39;&lt;/span&gt; directive is ignored when FPM is not running as root&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;28&lt;/span&gt;-Nov-2025 &lt;span class=&quot;token number&quot;&gt;16&lt;/span&gt;:57:23&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; NOTICE: &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;pool www&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;group&#39;&lt;/span&gt; directive is ignored when FPM is not running as root&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;28&lt;/span&gt;-Nov-2025 &lt;span class=&quot;token number&quot;&gt;16&lt;/span&gt;:57:23&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; NOTICE: fpm is running, pid &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;28&lt;/span&gt;-Nov-2025 &lt;span class=&quot;token number&quot;&gt;16&lt;/span&gt;:57:23&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; NOTICE: ready to handle connections&lt;br /&gt;&lt;span class=&quot;token number&quot;&gt;127.0&lt;/span&gt;.0.1 -  &lt;span class=&quot;token number&quot;&gt;28&lt;/span&gt;/Nov/2025:16:57:27 +0000 &lt;span class=&quot;token string&quot;&gt;&quot;GET status.php&quot;&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;200&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token number&quot;&gt;127.0&lt;/span&gt;.0.1 -  &lt;span class=&quot;token number&quot;&gt;28&lt;/span&gt;/Nov/2025:16:57:37 +0000 &lt;span class=&quot;token string&quot;&gt;&quot;GET status.php&quot;&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;200&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token number&quot;&gt;127.0&lt;/span&gt;.0.1 -  &lt;span class=&quot;token number&quot;&gt;28&lt;/span&gt;/Nov/2025:16:57:39 +0000 &lt;span class=&quot;token string&quot;&gt;&quot;GET status.php&quot;&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;200&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token number&quot;&gt;172.19&lt;/span&gt;.0.105 -  &lt;span class=&quot;token number&quot;&gt;28&lt;/span&gt;/Nov/2025:16:57:39 +0000 &lt;span class=&quot;token string&quot;&gt;&quot;GET status.php&quot;&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;200&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token number&quot;&gt;172.19&lt;/span&gt;.0.103 -  &lt;span class=&quot;token number&quot;&gt;28&lt;/span&gt;/Nov/2025:16:57:40 +0000 &lt;span class=&quot;token string&quot;&gt;&quot;GET status.php&quot;&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;200&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token number&quot;&gt;172.19&lt;/span&gt;.0.105 -  &lt;span class=&quot;token number&quot;&gt;28&lt;/span&gt;/Nov/2025:16:57:42 +0000 &lt;span class=&quot;token string&quot;&gt;&quot;GET status.php&quot;&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;200&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token number&quot;&gt;172.19&lt;/span&gt;.0.103 -  &lt;span class=&quot;token number&quot;&gt;28&lt;/span&gt;/Nov/2025:16:57:43 +0000 &lt;span class=&quot;token string&quot;&gt;&quot;GET status.php&quot;&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;200&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token number&quot;&gt;127.0&lt;/span&gt;.0.1 -  &lt;span class=&quot;token number&quot;&gt;28&lt;/span&gt;/Nov/2025:16:57:51 +0000 &lt;span class=&quot;token string&quot;&gt;&quot;GET status.php&quot;&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;200&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token number&quot;&gt;127.0&lt;/span&gt;.0.1 -  &lt;span class=&quot;token number&quot;&gt;28&lt;/span&gt;/Nov/2025:16:57:52 +0000 &lt;span class=&quot;token string&quot;&gt;&quot;GET status.php&quot;&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;200&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token number&quot;&gt;127.0&lt;/span&gt;.0.1 -  &lt;span class=&quot;token number&quot;&gt;28&lt;/span&gt;/Nov/2025:16:58:03 +0000 &lt;span class=&quot;token string&quot;&gt;&quot;GET status.php&quot;&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;200&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token number&quot;&gt;127.0&lt;/span&gt;.0.1 -  &lt;span class=&quot;token number&quot;&gt;28&lt;/span&gt;/Nov/2025:16:58:07 +0000 &lt;span class=&quot;token string&quot;&gt;&quot;GET status.php&quot;&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;200&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token number&quot;&gt;172.19&lt;/span&gt;.0.103 -  &lt;span class=&quot;token number&quot;&gt;28&lt;/span&gt;/Nov/2025:16:58:10 +0000 &lt;span class=&quot;token string&quot;&gt;&quot;GET /status.php&quot;&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;200&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token number&quot;&gt;172.19&lt;/span&gt;.0.103 -  &lt;span class=&quot;token number&quot;&gt;28&lt;/span&gt;/Nov/2025:16:58:10 +0000 &lt;span class=&quot;token string&quot;&gt;&quot;GET /index.php&quot;&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;200&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token number&quot;&gt;127.0&lt;/span&gt;.0.1 -  &lt;span class=&quot;token number&quot;&gt;28&lt;/span&gt;/Nov/2025:16:58:15 +0000 &lt;span class=&quot;token string&quot;&gt;&quot;GET status.php&quot;&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;200&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token number&quot;&gt;127.0&lt;/span&gt;.0.1 -  &lt;span class=&quot;token number&quot;&gt;28&lt;/span&gt;/Nov/2025:16:58:22 +0000 &lt;span class=&quot;token string&quot;&gt;&quot;GET status.php&quot;&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;200&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token number&quot;&gt;127.0&lt;/span&gt;.0.1 -  &lt;span class=&quot;token number&quot;&gt;28&lt;/span&gt;/Nov/2025:16:58:27 +0000 &lt;span class=&quot;token string&quot;&gt;&quot;GET status.php&quot;&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;200&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token number&quot;&gt;127.0&lt;/span&gt;.0.1 -  &lt;span class=&quot;token number&quot;&gt;28&lt;/span&gt;/Nov/2025:16:58:37 +0000 &lt;span class=&quot;token string&quot;&gt;&quot;GET status.php&quot;&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;200&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token number&quot;&gt;127.0&lt;/span&gt;.0.1 -  &lt;span class=&quot;token number&quot;&gt;28&lt;/span&gt;/Nov/2025:16:58:39 +0000 &lt;span class=&quot;token string&quot;&gt;&quot;GET status.php&quot;&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;200&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token number&quot;&gt;127.0&lt;/span&gt;.0.1 -  &lt;span class=&quot;token number&quot;&gt;28&lt;/span&gt;/Nov/2025:16:58:51 +0000 &lt;span class=&quot;token string&quot;&gt;&quot;GET status.php&quot;&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;200&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token number&quot;&gt;127.0&lt;/span&gt;.0.1 -  &lt;span class=&quot;token number&quot;&gt;28&lt;/span&gt;/Nov/2025:16:58:52 +0000 &lt;span class=&quot;token string&quot;&gt;&quot;GET status.php&quot;&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;200&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token number&quot;&gt;127.0&lt;/span&gt;.0.1 -  &lt;span class=&quot;token number&quot;&gt;28&lt;/span&gt;/Nov/2025:16:59:03 +0000 &lt;span class=&quot;token string&quot;&gt;&quot;GET status.php&quot;&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;200&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token number&quot;&gt;127.0&lt;/span&gt;.0.1 -  &lt;span class=&quot;token number&quot;&gt;28&lt;/span&gt;/Nov/2025:16:59:07 +0000 &lt;span class=&quot;token string&quot;&gt;&quot;GET status.php&quot;&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;200&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token number&quot;&gt;127.0&lt;/span&gt;.0.1 -  &lt;span class=&quot;token number&quot;&gt;28&lt;/span&gt;/Nov/2025:16:59:15 +0000 &lt;span class=&quot;token string&quot;&gt;&quot;GET status.php&quot;&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;200&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token number&quot;&gt;127.0&lt;/span&gt;.0.1 -  &lt;span class=&quot;token number&quot;&gt;28&lt;/span&gt;/Nov/2025:16:59:22 +0000 &lt;span class=&quot;token string&quot;&gt;&quot;GET status.php&quot;&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;200&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;When all pods show running, you should have a new Nextcloud instance at the ingress URL you configured.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;http://localhost:8080/assets/images/2025/11/nextcloud-demo-instance.png&quot; alt=&quot;image&quot; /&gt;&lt;/p&gt;
&lt;p&gt;You can inspect the final results with the kubectl commands we’ve been using throughout the series.&lt;/p&gt;
&lt;p&gt;Inspect all resources created in your cluster by the nextcloud-demo kustomization.&lt;/p&gt;
&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;$ flux tree ks nextcloud-demo &lt;br /&gt;Kustomization/flux-system/nextcloud-demo&lt;br /&gt;├── Namespace/nextcloud-demo&lt;br /&gt;└── HelmRelease/nextcloud-demo/nextcloud-demo&lt;br /&gt;    ├── Secret/nextcloud-demo/nextcloud-demo-cnpg-main-provider-backup-s3-creds&lt;br /&gt;    ├── Secret/nextcloud-demo/nextcloud-demo-cnpg-main-urls&lt;br /&gt;    ├── Secret/nextcloud-demo/nextcloud-demo-cnpg-main-user&lt;br /&gt;    ├── Secret/nextcloud-demo/nextcloud-demo-rediscreds&lt;br /&gt;    ├── Secret/nextcloud-demo/nextcloud-demo-config-volsync-config&lt;br /&gt;    ├── Secret/nextcloud-demo/nextcloud-demo-html-volsync-html&lt;br /&gt;    ├── ConfigMap/nextcloud-demo/nextcloud-demo-redis-health&lt;br /&gt;    ├── ConfigMap/nextcloud-demo/nextcloud-demo-clamav-config&lt;br /&gt;    ├── ConfigMap/nextcloud-demo/nextcloud-demo-collabora-config&lt;br /&gt;    ├── ConfigMap/nextcloud-demo/nextcloud-demo-hpb-config&lt;br /&gt;    ├── ConfigMap/nextcloud-demo/nextcloud-demo-nextcloud-config&lt;br /&gt;    ├── ConfigMap/nextcloud-demo/nextcloud-demo-nginx-config&lt;br /&gt;    ├── ConfigMap/nextcloud-demo/nextcloud-demo-opcache&lt;br /&gt;    ├── ConfigMap/nextcloud-demo/nextcloud-demo-php-tune&lt;br /&gt;    ├── ConfigMap/nextcloud-demo/nextcloud-demo-redis-session&lt;br /&gt;    ├── PersistentVolumeClaim/nextcloud-demo/nextcloud-demo-config&lt;br /&gt;    ├── PersistentVolumeClaim/nextcloud-demo/nextcloud-demo-html&lt;br /&gt;    ├── Service/nextcloud-demo/nextcloud-demo-redis&lt;br /&gt;    ├── Service/nextcloud-demo/nextcloud-demo-clamav&lt;br /&gt;    ├── Service/nextcloud-demo/nextcloud-demo-collabora&lt;br /&gt;    ├── Service/nextcloud-demo/nextcloud-demo-imaginary&lt;br /&gt;    ├── Service/nextcloud-demo/nextcloud-demo&lt;br /&gt;    ├── Service/nextcloud-demo/nextcloud-demo-nextcloud&lt;br /&gt;    ├── Service/nextcloud-demo/nextcloud-demo-notify&lt;br /&gt;    ├── Deployment/nextcloud-demo/nextcloud-demo-clamav&lt;br /&gt;    ├── Deployment/nextcloud-demo/nextcloud-demo-collabora&lt;br /&gt;    ├── Deployment/nextcloud-demo/nextcloud-demo-imaginary&lt;br /&gt;    ├── Deployment/nextcloud-demo/nextcloud-demo&lt;br /&gt;    ├── Deployment/nextcloud-demo/nextcloud-demo-nginx&lt;br /&gt;    ├── Deployment/nextcloud-demo/nextcloud-demo-notify&lt;br /&gt;    ├── StatefulSet/nextcloud-demo/nextcloud-demo-redis&lt;br /&gt;    ├── CronJob/nextcloud-demo/nextcloud-demo-nextcloud-cron&lt;br /&gt;    ├── CronJob/nextcloud-demo/nextcloud-demo-preview-cron&lt;br /&gt;    ├── Ingress/nextcloud-demo/nextcloud-demo-cloudflare&lt;br /&gt;    ├── Ingress/nextcloud-demo/nextcloud-demo&lt;br /&gt;    ├── Cluster/nextcloud-demo/nextcloud-demo-cnpg-main&lt;br /&gt;    ├── ReplicationDestination/nextcloud-demo/nextcloud-demo-config-config-dest&lt;br /&gt;    ├── ReplicationDestination/nextcloud-demo/nextcloud-demo-html-html-dest&lt;br /&gt;    ├── ReplicationSource/nextcloud-demo/nextcloud-demo-config-config&lt;br /&gt;    ├── ReplicationSource/nextcloud-demo/nextcloud-demo-html-html&lt;br /&gt;    └── ScheduledBackup/nextcloud-demo/nextcloud-demo-cnpg-main-sched-backup-daily-backup&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Verify volsync source and destination configuration:&lt;/p&gt;
&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;$ kubectl get replicationdestinations.volsync.backube &lt;span class=&quot;token parameter variable&quot;&gt;-n&lt;/span&gt; nextcloud-demo &lt;br /&gt;NAME                                LAST SYNC              DURATION        NEXT SYNC&lt;br /&gt;nextcloud-demo-config-config-dest   &lt;span class=&quot;token number&quot;&gt;2025&lt;/span&gt;-11-28T16:43:47Z   &lt;span class=&quot;token number&quot;&gt;32&lt;/span&gt;.604100966s   &lt;br /&gt;nextcloud-demo-html-html-dest       &lt;span class=&quot;token number&quot;&gt;2025&lt;/span&gt;-11-28T16:43:45Z   &lt;span class=&quot;token number&quot;&gt;30&lt;/span&gt;.501917968s   &lt;br /&gt;$ kubectl get replicationsources.volsync.backube &lt;span class=&quot;token parameter variable&quot;&gt;-n&lt;/span&gt; nextcloud-demo &lt;br /&gt;NAME                           SOURCE                  LAST SYNC              DURATION          NEXT SYNC&lt;br /&gt;nextcloud-demo-config-config   nextcloud-demo-config   &lt;span class=&quot;token number&quot;&gt;2025&lt;/span&gt;-11-28T16:46:37Z   3m22.289395955s   &lt;span class=&quot;token number&quot;&gt;2025&lt;/span&gt;-11-29T01:10:00Z&lt;br /&gt;nextcloud-demo-html-html       nextcloud-demo-html     &lt;span class=&quot;token number&quot;&gt;2025&lt;/span&gt;-11-28T16:46:35Z   3m20.125654664s   &lt;span class=&quot;token number&quot;&gt;2025&lt;/span&gt;-11-29T01:20:00Z&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Inspect the CNPG cluster created for Nextcloud:&lt;/p&gt;
&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;$  kubectl get cluster &lt;span class=&quot;token parameter variable&quot;&gt;-n&lt;/span&gt; nextcloud-demo&lt;br /&gt;NAME                       AGE   INSTANCES   READY   STATUS                     PRIMARY&lt;br /&gt;nextcloud-demo-cnpg-main   18m   &lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt;           &lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt;       Cluster &lt;span class=&quot;token keyword&quot;&gt;in&lt;/span&gt; healthy state   nextcloud-demo-cnpg-main-1&lt;br /&gt;&lt;br /&gt;$ kubectl cnpg status &lt;span class=&quot;token parameter variable&quot;&gt;-n&lt;/span&gt; nextcloud-demo nextcloud-demo-cnpg-main&lt;br /&gt;Cluster Summary&lt;br /&gt;Name                     nextcloud-demo/nextcloud-demo-cnpg-main&lt;br /&gt;System ID:               &lt;span class=&quot;token number&quot;&gt;7577817879212458003&lt;/span&gt;&lt;br /&gt;PostgreSQL Image:        ghcr.io/cloudnative-pg/postgresql:16.11&lt;br /&gt;Primary instance:        nextcloud-demo-cnpg-main-1&lt;br /&gt;Primary promotion time:  &lt;span class=&quot;token number&quot;&gt;2025&lt;/span&gt;-11-28 &lt;span class=&quot;token number&quot;&gt;16&lt;/span&gt;:43:48 +0000 UTC &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;18m52s&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;br /&gt;Status:                  Cluster &lt;span class=&quot;token keyword&quot;&gt;in&lt;/span&gt; healthy state &lt;br /&gt;Instances:               &lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt;&lt;br /&gt;Ready instances:         &lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt;&lt;br /&gt;Size:                    183M&lt;br /&gt;Current Write LSN:       &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;/90D3EB8 &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;Timeline: &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt; - WAL File: 000000010000000000000009&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Continuous Backup status&lt;br /&gt;First Point of Recoverability:  &lt;span class=&quot;token number&quot;&gt;2025&lt;/span&gt;-11-28T16:44:59Z&lt;br /&gt;Working WAL archiving:          OK&lt;br /&gt;WALs waiting to be archived:    &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;br /&gt;Last Archived WAL:              000000010000000000000008   @   &lt;span class=&quot;token number&quot;&gt;2025&lt;/span&gt;-11-28T17:00:03.47943Z&lt;br /&gt;Last Failed WAL:                -&lt;br /&gt;&lt;br /&gt;Streaming Replication status&lt;br /&gt;Replication Slots Enabled&lt;br /&gt;Name                        Sent LSN   Write LSN  Flush LSN  Replay LSN  Write Lag  Flush Lag  Replay Lag  State      Sync State  Sync Priority  Replication Slot&lt;br /&gt;----                        --------   ---------  ---------  ----------  ---------  ---------  ----------  -----      ----------  -------------  ----------------&lt;br /&gt;nextcloud-demo-cnpg-main-2  &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;/90D3EB8  &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;/90D3EB8  &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;/90D3EB8  &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;/90D3EB8   00:00:00   00:00:00   00:00:00    streaming  async       &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;              active&lt;br /&gt;&lt;br /&gt;Instances status&lt;br /&gt;Name                        Current LSN  Replication role  Status  QoS        Manager Version  Node&lt;br /&gt;----                        -----------  ----------------  ------  ---        ---------------  ----&lt;br /&gt;nextcloud-demo-cnpg-main-1  &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;/90D3EB8    Primary           OK      Burstable  &lt;span class=&quot;token number&quot;&gt;1.27&lt;/span&gt;.1           truek8s-w2&lt;br /&gt;nextcloud-demo-cnpg-main-2  &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;/90D3EB8    Standby &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;async&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;   OK      Burstable  &lt;span class=&quot;token number&quot;&gt;1.27&lt;/span&gt;.1           truek8s-w1&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;Troubleshooting a failed deployment&lt;/h2&gt;
&lt;p&gt;If you have any issues during deployment (which is common - I did even while writing this guide) here are some steps to help:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Determine the cause of failure: Use flux get hr to see if the chart was deployed successfully or not. It may fail if there’s an error in your helm-release.yaml. Example:&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;$ flux get hr &lt;span class=&quot;token parameter variable&quot;&gt;-n&lt;/span&gt; nextcloud-demo &lt;br /&gt;NAME            REVISION        SUSPENDED       READY   MESSAGE                                                                                                                                                                                                   &lt;br /&gt;nextcloud-demo  &lt;span class=&quot;token number&quot;&gt;40.4&lt;/span&gt;.1          False           False   Helm &lt;span class=&quot;token function&quot;&gt;install&lt;/span&gt; failed &lt;span class=&quot;token keyword&quot;&gt;for&lt;/span&gt; release nextcloud-demo/nextcloud-demo with chart nextcloud@40.4.1: execution error at &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;nextcloud/templates/common.yaml:16:4&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;: Nextcloud - Collabora &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;Password&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; cannot contain &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;$&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Use kubectl describe pods on pods in the nextcloud-demo namespace. Look for unfulfilled persistent volume claims, or any pods in error state.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Restart and try again&lt;br /&gt;
– Suspend the KS with flux suspend ks nextcloud-demo.&lt;br /&gt;
– Delete the entire namespace with kubectl delete namespaces nextcloud-demo&lt;br /&gt;
– Delete any files written to your S3 bucket&lt;br /&gt;
– (unique to Nextcloud) delete any files written to the NFS shared by the failed deployment&lt;br /&gt;
– Make and commit your changes, then try again.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Sources&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://trueforge.org/truetech/truecharts/charts/stable/nextcloud/installation-notes/&quot;&gt;trueforge.org: Nextcloud Installation Notes&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://trueforge.org/truetech/truecharts/guides/backup--restore/volsync-backup-restore/&quot;&gt;trueforge.org: VolySync&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://trueforge.org/truetech/truecharts-common/cnpg/cnpg/&quot;&gt;trueforge.org: CNPG&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://volsync.readthedocs.io/en/stable/&quot;&gt;readthedocs.io: VolSync&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://serverfault.com/questions/1189137/talos-os-and-truecharts-failed-to-create-network-namespace-for-sandbox-error&quot;&gt;serverfault: Talos OS and TrueCharts - Failed to create network namespace for sandbox error&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://trueforge.org/truetech/truecharts-common/podoptions/#hostusers&quot;&gt;trueforge.org: truecharts-common/podoptions&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
</content>
    </entry>
    
    <entry>
      <title>TrueK8S Part 10</title>
      <link href="http://localhost:8080/2025/11/29/truek8s-part-10/"/>
      <updated>2025-11-29T12:30:00Z</updated>
      <id>http://localhost:8080/2025/11/29/truek8s-part-10/</id>
      <content type="html">&lt;h2&gt;Destroying and Rebuilding our Talos Cluster&lt;/h2&gt;
&lt;p&gt;For the final post of this series, we’ll put our cluster through a disaster recovery scenario. Because our cluster’s configuration is defined declaratively and all of our volumes and databases are replicated to cloud storage, we can re-create our cluster with little more than our git repo and our SOPS key. For this exercise, I’ll be simulating a complete disaster recovery. Let’s assume that my current cluster and administration machine have been destroyed and work through the process of rebuilding the Talos cluster, rebuilding our administration workstation, and then bootstrapping our new cluster with our config.&lt;/p&gt;
&lt;p&gt;Before getting started (and especially before destroying any of your work) you’ll need to make sure you have the following things lined up:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Your Talos patch files (optional, but convenient)&lt;/li&gt;
&lt;li&gt;Access to your repo with the same or a new personal access token&lt;/li&gt;
&lt;li&gt;Your SOPS key&lt;/li&gt;
&lt;li&gt;Your Flux bootsrap command (optional, but convenient)&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Destroy the Cluster&lt;/h3&gt;
&lt;p&gt;Go ahead and give your existing cluster a graceful shutdown. If you’re feeling brave you can delete them, otherwise power them off and keep them as a backup.&lt;/p&gt;
&lt;h3&gt;Rebuilding the Cluster&lt;/h3&gt;
&lt;p&gt;I’ll start by creating three new VMs, just like we did in part 1.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;http://localhost:8080/assets/images/2025/07/truek8s-c1-new.png&quot; alt=&quot;image&quot; /&gt;&lt;/p&gt;
&lt;p&gt;Don’t forget to install Talosctl if you haven’t already.&lt;/p&gt;
&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;token function&quot;&gt;curl&lt;/span&gt; &lt;span class=&quot;token parameter variable&quot;&gt;-sL&lt;/span&gt; https://talos.dev/install &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;sh&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Save your IPs and cluster names as variables, then generate your initial talos config file.&lt;/p&gt;
&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;token builtin class-name&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token assign-left variable&quot;&gt;CONTROL_IP&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;192.168&lt;/span&gt;.XX.101&lt;br /&gt;&lt;span class=&quot;token builtin class-name&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token assign-left variable&quot;&gt;WORKER1_IP&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;192.168&lt;/span&gt;.XX.111&lt;br /&gt;&lt;span class=&quot;token builtin class-name&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token assign-left variable&quot;&gt;WORKER2_IP&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;192.168&lt;/span&gt;.XX.112&lt;br /&gt;&lt;span class=&quot;token builtin class-name&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token assign-left variable&quot;&gt;CLUSTERNAME&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;truek8s&lt;br /&gt;&lt;br /&gt;$ talosctl gen config &lt;span class=&quot;token variable&quot;&gt;$CLUSTERNAME&lt;/span&gt; https://&lt;span class=&quot;token variable&quot;&gt;$CONTROL_IP&lt;/span&gt;:6443 --install-image factory.talos.dev/installer/82866c01b2842b490c27a6f1a4996aae05f096c83db40ecda166b03da9deae46/:v1.9.2&lt;br /&gt;generating PKI and tokens&lt;br /&gt;Created /home/bmel/Documents/truek8s-talos/controlplane.yaml&lt;br /&gt;Created /home/bmel/Documents/truek8s-talos/worker.yaml&lt;br /&gt;Created /home/bmel/Documents/truek8s-talos/talosconfig&lt;/code&gt;&lt;/pre&gt;
&lt;div class=&quot;wrapper p-4 p-2 my-4 rounded-lg bg-yellow-100 text-gray-700 border border-yellow-300&quot;&gt;
&lt;p&gt;💡 Remember, you can specify any version using the same schematic ID. This guide was written with v1.9.2 but I’ve tested v1.10.8 and the process is the same.&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;Then go ahead and recreate or copy your patch files to your working directory. Check part 1 for details on recreating them. Remember, the only thing different between these three is the hostname field.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;truek8s-c1.patch&lt;/li&gt;
&lt;li&gt;truek8s-w1.patch&lt;/li&gt;
&lt;li&gt;truek8s-w2.patch&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;And then patch your new machine config files:&lt;/p&gt;
&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;$ talosctl machineconfig patch controlplane.yaml &lt;span class=&quot;token parameter variable&quot;&gt;--patch&lt;/span&gt; @truek8s-c1.patch &lt;span class=&quot;token parameter variable&quot;&gt;--output&lt;/span&gt; truek8s-c1.yaml&lt;br /&gt;$ talosctl machineconfig patch worker.yaml &lt;span class=&quot;token parameter variable&quot;&gt;--patch&lt;/span&gt; @truek8s-w1.patch &lt;span class=&quot;token parameter variable&quot;&gt;--output&lt;/span&gt; truek8s-w1.yaml&lt;br /&gt;$ talosctl machineconfig patch worker.yaml &lt;span class=&quot;token parameter variable&quot;&gt;--patch&lt;/span&gt; @truek8s-w2.patch &lt;span class=&quot;token parameter variable&quot;&gt;--output&lt;/span&gt; truek8s-w2.yaml&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Double-check the machine config files you just generated, and then apply them to your cluster. Start with the control node, wait for it to come up, and then do your workers.&lt;/p&gt;
&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;$ talosctl apply-config &lt;span class=&quot;token parameter variable&quot;&gt;--insecure&lt;/span&gt; &lt;span class=&quot;token parameter variable&quot;&gt;-n&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$CONTROL_IP&lt;/span&gt; &lt;span class=&quot;token parameter variable&quot;&gt;--file&lt;/span&gt; truek8s-c1.yaml&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;$ talosctl apply-config &lt;span class=&quot;token parameter variable&quot;&gt;--insecure&lt;/span&gt; &lt;span class=&quot;token parameter variable&quot;&gt;-n&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$WORKER1_IP&lt;/span&gt; &lt;span class=&quot;token parameter variable&quot;&gt;--file&lt;/span&gt; truek8s-w1.yaml&lt;br /&gt;$ talosctl apply-config &lt;span class=&quot;token parameter variable&quot;&gt;--insecure&lt;/span&gt; &lt;span class=&quot;token parameter variable&quot;&gt;-n&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$WORKER2_IP&lt;/span&gt; &lt;span class=&quot;token parameter variable&quot;&gt;--file&lt;/span&gt; truek8s-w2.yaml&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;When all three are back up and show healthy, finalize the install by bootstrapping the cluster:&lt;/p&gt;
&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;$ talosctl bootstrap &lt;span class=&quot;token parameter variable&quot;&gt;--nodes&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$CONTROL_IP&lt;/span&gt; &lt;span class=&quot;token parameter variable&quot;&gt;--endpoints&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$CONTROL_IP&lt;/span&gt; &lt;span class=&quot;token parameter variable&quot;&gt;--talosconfig&lt;/span&gt; talosconfig&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Finally, generate and save your talos and kube config files.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;copy and edit the talos config file&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;$ &lt;span class=&quot;token function&quot;&gt;cp&lt;/span&gt; talosconfig ~/.talos/config&lt;br /&gt;$ &lt;span class=&quot;token function&quot;&gt;nano&lt;/span&gt; ~/.talos/config &lt;br /&gt;$ &lt;span class=&quot;token function&quot;&gt;cat&lt;/span&gt; ~/.talos/config &lt;br /&gt;context: truek8s&lt;br /&gt;contexts:&lt;br /&gt;    truek8s:&lt;br /&gt;        endpoints: &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;192.168&lt;/span&gt;.XX.101&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token comment&quot;&gt;############################&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token comment&quot;&gt;############################&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token comment&quot;&gt;############################&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;Generate kubeconfig&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;$ talosctl kubeconfig &lt;span class=&quot;token parameter variable&quot;&gt;-n&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$CONTROL_IP&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;If you don’t already have kubectl installed, install it:&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;$ &lt;span class=&quot;token function&quot;&gt;apt&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;install&lt;/span&gt; kubectl&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;And finally, check to make sure talosctl and kubectl are working.&lt;/p&gt;
&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;$ talosctl dashboard &lt;span class=&quot;token parameter variable&quot;&gt;-n&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$CONTROL_IP&lt;/span&gt; &lt;br /&gt;&lt;br /&gt;$ kubectl get nodes&lt;br /&gt;NAME         STATUS   ROLES           AGE   VERSION&lt;br /&gt;truek8s-c1   Ready    control-plane   62s   v1.33.2&lt;br /&gt;truek8s-w1   Ready    &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;none&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;          55s   v1.33.2&lt;br /&gt;truek8s-w2   Ready    &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;none&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;          66s   v1.33.2&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;Clone your repo&lt;/h3&gt;
&lt;p&gt;Once the cluster is up, clone your flux repo to your admin workstation so you can make changes. You will need a private access token, but it doesn’t have to be the same one. Check part 2 for details on how to make a new one if you need it.&lt;/p&gt;
&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;#You don&#39;t need quotes here&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token builtin class-name&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token assign-left variable&quot;&gt;GITHUB_TOKEN&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;your-PAT&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token builtin class-name&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token assign-left variable&quot;&gt;GITHUB_USER&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;your-username&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token builtin class-name&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token assign-left variable&quot;&gt;REPO&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;truek8s&lt;br /&gt;&lt;br /&gt;&lt;span class=&quot;token function&quot;&gt;git&lt;/span&gt; clone https://&lt;span class=&quot;token variable&quot;&gt;$GITHUB_TOKEN&lt;/span&gt;@github.com/&lt;span class=&quot;token variable&quot;&gt;$GITHUB_USER&lt;/span&gt;/&lt;span class=&quot;token variable&quot;&gt;$REPO&lt;/span&gt;&lt;br /&gt;Cloning into &lt;span class=&quot;token string&quot;&gt;&#39;truek8s&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;..&lt;/span&gt;.&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;Configure SOPS&lt;/h3&gt;
&lt;p&gt;Before we can move on to bootstrapping flux, we need to configure SOPS. We’ll need to provide the key to flux as a kube secret later, but also need to have a copy of it on our admin workstation so we can decrypt our config map.&lt;/p&gt;
&lt;p&gt;If you haven’t already, install SOPS and AGE.&lt;/p&gt;
&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;# Download the binary&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token function&quot;&gt;curl&lt;/span&gt; &lt;span class=&quot;token parameter variable&quot;&gt;-LO&lt;/span&gt; https://github.com/getsops/sops/releases/download/v3.10.2/sops-v3.10.2.linux.amd64&lt;br /&gt;&lt;br /&gt;&lt;span class=&quot;token comment&quot;&gt;# Move the binary in to your PATH&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token function&quot;&gt;mv&lt;/span&gt; sops-v3.10.2.linux.amd64 /usr/local/bin/sops&lt;br /&gt;&lt;br /&gt;&lt;span class=&quot;token comment&quot;&gt;# Make the binary executable&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token function&quot;&gt;chmod&lt;/span&gt; +x /usr/local/bin/sops&lt;br /&gt;&lt;br /&gt;&lt;span class=&quot;token comment&quot;&gt;#Install age&lt;/span&gt;&lt;br /&gt;$ &lt;span class=&quot;token function&quot;&gt;apt&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;install&lt;/span&gt; age&lt;/code&gt;&lt;/pre&gt;
&lt;div class=&quot;wrapper p-4 p-2 my-4 rounded-lg bg-yellow-100 text-gray-700 border border-yellow-300&quot;&gt;
&lt;p&gt;💡 This command installs version 3.10.2. Check SOPS documentation to see if a newer version is available.&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;Copy your sops-key.text file to ~/.config/sops/age/keys.txt. You can test that SOPS is configured and that you have the right key by decrypting and re-encrypting your configmap.&lt;/p&gt;
&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;$ sops &lt;span class=&quot;token parameter variable&quot;&gt;-d&lt;/span&gt; &lt;span class=&quot;token parameter variable&quot;&gt;-i&lt;/span&gt; cluster-config.yaml&lt;br /&gt;$ sops &lt;span class=&quot;token parameter variable&quot;&gt;-e&lt;/span&gt; &lt;span class=&quot;token parameter variable&quot;&gt;-i&lt;/span&gt; cluster-config.yaml&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Make sure you keep that key file handy. You’ll need to provide it to flux in a later step.&lt;/p&gt;
&lt;h3&gt;Volsync and CNPG Configuration&lt;/h3&gt;
&lt;p&gt;Before we bootstrap flux and commit our config to the cluster, we need to make sure that any charts using VolSync or CNPG are configured to restore. In the examples we’ve worked on through this guide, that simply means uncommenting the mode: recovery statement in any helm charts.&lt;/p&gt;
&lt;p&gt;Using the configuration we made for nextcloud as an example:&lt;/p&gt;
&lt;pre class=&quot;language-yaml&quot;&gt;&lt;code class=&quot;language-yaml&quot;&gt;      &lt;span class=&quot;token key atrule&quot;&gt;cnpg&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token key atrule&quot;&gt;main&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;          &lt;span class=&quot;token key atrule&quot;&gt;cluster&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;            &lt;span class=&quot;token key atrule&quot;&gt;singleNode&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean important&quot;&gt;true&lt;/span&gt;&lt;br /&gt;          &lt;span class=&quot;token key atrule&quot;&gt;pgVersion&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;15&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token comment&quot;&gt;# Uncomment this line          &lt;/span&gt;&lt;br /&gt;          &lt;span class=&quot;token key atrule&quot;&gt;mode&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; recovery&lt;br /&gt;          &lt;span class=&quot;token key atrule&quot;&gt;backups&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;            &lt;span class=&quot;token key atrule&quot;&gt;enabled&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean important&quot;&gt;true&lt;/span&gt;&lt;br /&gt;            &lt;span class=&quot;token key atrule&quot;&gt;credentials&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; backblaze&lt;br /&gt;            &lt;span class=&quot;token key atrule&quot;&gt;scheduledBackups&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;              &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token key atrule&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; daily&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;backup&lt;br /&gt;                &lt;span class=&quot;token key atrule&quot;&gt;schedule&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;0 0 0 * * *&quot;&lt;/span&gt;&lt;br /&gt;                &lt;span class=&quot;token key atrule&quot;&gt;backupOwnerReference&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; self&lt;br /&gt;                &lt;span class=&quot;token key atrule&quot;&gt;immediate&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean important&quot;&gt;true&lt;/span&gt;&lt;br /&gt;                &lt;span class=&quot;token key atrule&quot;&gt;suspend&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean important&quot;&gt;false&lt;/span&gt;&lt;br /&gt;          &lt;span class=&quot;token key atrule&quot;&gt;recovery&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;            &lt;span class=&quot;token key atrule&quot;&gt;method&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; object_store&lt;br /&gt;            &lt;span class=&quot;token key atrule&quot;&gt;credentials&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; backblaze&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Make sure you do this for any CNPG enabled charts in your repo. When you’re all done, commit any changes to your repo:&lt;/p&gt;
&lt;p&gt;⚠️ make sure you config map is encrypted before committing.&lt;/p&gt;
&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;token function&quot;&gt;git&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;add&lt;/span&gt; &lt;span class=&quot;token parameter variable&quot;&gt;-A&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;git&lt;/span&gt; commit &lt;span class=&quot;token parameter variable&quot;&gt;-m&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;set recovery&#39;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token function&quot;&gt;git&lt;/span&gt; push&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;Flux Bootstrap&lt;/h3&gt;
&lt;p&gt;Now all you need to do is bootstrap flux with your repo, hand it the sops key, and it will take care of everything from there. For the github PAT, you can create a new one or re-use the same one from earlier.&lt;/p&gt;
&lt;p&gt;if you don’t already have it installed, go ahead and install flux:&lt;/p&gt;
&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;token function&quot;&gt;curl&lt;/span&gt; &lt;span class=&quot;token parameter variable&quot;&gt;-s&lt;/span&gt; https://fluxcd.io/install.sh &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;sudo&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;bash&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;And then re-run the flux bootstrap command:&lt;/p&gt;
&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;$ &lt;span class=&quot;token builtin class-name&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token assign-left variable&quot;&gt;GITHUB_TOKEN&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;PAT&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;br /&gt;$ &lt;span class=&quot;token builtin class-name&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token assign-left variable&quot;&gt;GITHUB_USER&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;Github Username&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;br /&gt;$ &lt;span class=&quot;token builtin class-name&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token assign-left variable&quot;&gt;REPO&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;truek8s&lt;br /&gt;$ flux bootstrap github --token-auth &lt;span class=&quot;token parameter variable&quot;&gt;--owner&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$GITHUB_USER&lt;/span&gt;   &lt;span class=&quot;token parameter variable&quot;&gt;--repository&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$REPO&lt;/span&gt; &lt;span class=&quot;token parameter variable&quot;&gt;--branch&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;main   &lt;span class=&quot;token parameter variable&quot;&gt;--path&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;./clusters/&lt;span class=&quot;token variable&quot;&gt;$REPO&lt;/span&gt;   &lt;span class=&quot;token parameter variable&quot;&gt;--personal&lt;/span&gt;&lt;br /&gt;► connecting to github.com&lt;br /&gt;► cloning branch &lt;span class=&quot;token string&quot;&gt;&quot;main&quot;&lt;/span&gt; from Git repository &lt;span class=&quot;token string&quot;&gt;&quot;https://github.com/bmel343/truek8s.git&quot;&lt;/span&gt;&lt;br /&gt;✔ cloned repository&lt;br /&gt;► generating component manifests&lt;br /&gt;✔ generated component manifests&lt;br /&gt;✔ committed &lt;span class=&quot;token function&quot;&gt;sync&lt;/span&gt; manifests to &lt;span class=&quot;token string&quot;&gt;&quot;main&quot;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;6b49c159dff1f604c5df9e542731c41e0d4412f1&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;br /&gt;► pushing component manifests to &lt;span class=&quot;token string&quot;&gt;&quot;https://github.com/bmel343/truek8s.git&quot;&lt;/span&gt;&lt;br /&gt;► installing components &lt;span class=&quot;token keyword&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;flux-system&quot;&lt;/span&gt; namespace&lt;br /&gt;✔ installed components&lt;br /&gt;✔ reconciled components&lt;br /&gt;► determining &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token builtin class-name&quot;&gt;source&lt;/span&gt; secret &lt;span class=&quot;token string&quot;&gt;&quot;flux-system/flux-system&quot;&lt;/span&gt; exists&lt;br /&gt;► generating &lt;span class=&quot;token builtin class-name&quot;&gt;source&lt;/span&gt; secret&lt;br /&gt;► applying &lt;span class=&quot;token builtin class-name&quot;&gt;source&lt;/span&gt; secret &lt;span class=&quot;token string&quot;&gt;&quot;flux-system/flux-system&quot;&lt;/span&gt;&lt;br /&gt;✔ reconciled &lt;span class=&quot;token builtin class-name&quot;&gt;source&lt;/span&gt; secret&lt;br /&gt;► generating &lt;span class=&quot;token function&quot;&gt;sync&lt;/span&gt; manifests&lt;br /&gt;✔ generated &lt;span class=&quot;token function&quot;&gt;sync&lt;/span&gt; manifests&lt;br /&gt;✔ &lt;span class=&quot;token function&quot;&gt;sync&lt;/span&gt; manifests are up to &lt;span class=&quot;token function&quot;&gt;date&lt;/span&gt;&lt;br /&gt;► applying &lt;span class=&quot;token function&quot;&gt;sync&lt;/span&gt; manifests&lt;br /&gt;✔ reconciled &lt;span class=&quot;token function&quot;&gt;sync&lt;/span&gt; configuration&lt;br /&gt;◎ waiting &lt;span class=&quot;token keyword&quot;&gt;for&lt;/span&gt; Kustomization &lt;span class=&quot;token string&quot;&gt;&quot;flux-system/flux-system&quot;&lt;/span&gt; to be reconciled&lt;br /&gt;✔ Kustomization reconciled successfully&lt;br /&gt;► confirming components are healthy&lt;br /&gt;✔ helm-controller: deployment ready&lt;br /&gt;✔ kustomize-controller: deployment ready&lt;br /&gt;✔ notification-controller: deployment ready&lt;br /&gt;✔ source-controller: deployment ready&lt;br /&gt;✔ all components are healthy&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;As soon as flux is done bootstrapping, create the sops-age secret in the flux-system namespace. Don’t worry, thanks to the dependency configuration, Flux will wait for the secret to exist to reconcile the config ks, and all other KS depend on that.&lt;/p&gt;
&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;$ kubectl &lt;span class=&quot;token parameter variable&quot;&gt;-n&lt;/span&gt; flux-system create secret generic sops-age --from-file&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;age.agekey&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;sops-key.txt&lt;br /&gt;&lt;br /&gt;secret/sops-age created&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;Sit Back and Watch&lt;/h3&gt;
&lt;p&gt;Flux will take it from here, working diligently to apply all the resources defined in our repo to the cluster. In my experience, it can take up 20-30 minutes for actual apps to start working again. I like to watch flux events, and check on specific kustomizations while I wait. Flux will be pretty noisy, and you may even see a few errors in there, but flux can often reconcile that by waiting and trying again. In this example it’s complaining about not finding the sops-age secret, but later finds it and continues along.&lt;/p&gt;
&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;$ flux events &lt;span class=&quot;token parameter variable&quot;&gt;--watch&lt;/span&gt;&lt;br /&gt;LAST SEEN       TYPE    REASON                  OBJECT                  MESSAGE                                                   &lt;br /&gt;11s             Normal  DependencyNotReady      Kustomization/apps      Dependencies &lt;span class=&quot;token keyword&quot;&gt;do&lt;/span&gt; not meet ready condition, retrying &lt;span class=&quot;token keyword&quot;&gt;in&lt;/span&gt; 30s&lt;br /&gt;10s     Normal  NewArtifact     HelmRepository/cloudnative-pg   stored fetched index of size &lt;span class=&quot;token number&quot;&gt;77&lt;/span&gt;.48kB from &lt;span class=&quot;token string&quot;&gt;&#39;https://cloudnative-pg.github.io/charts&#39;&lt;/span&gt;&lt;br /&gt;11s     Warning BuildFailed     Kustomization/config    secrets &lt;span class=&quot;token string&quot;&gt;&quot;sops-age&quot;&lt;/span&gt; not found&lt;br /&gt;18s     Normal  NewArtifact     GitRepository/flux-system       stored artifact &lt;span class=&quot;token keyword&quot;&gt;for&lt;/span&gt; commit &lt;span class=&quot;token string&quot;&gt;&#39;set recovery&#39;&lt;/span&gt;&lt;br /&gt;12s     Normal  Progressing     Kustomization/flux-system       CustomResourceDefinition/alerts.notification.toolkit.fluxcd.io configured     &lt;br /&gt;                                                                CustomResourceDefinition/buckets.source.toolkit.fluxcd.io configured          &lt;br /&gt;                                                                CustomResourceDefinition/externalartifacts.source.toolkit.fluxcd.io configured&lt;br /&gt;                                                                CustomResourceDefinition/gitrepositories.source.toolkit.fluxcd.io configured  &lt;br /&gt;                                                                CustomResourceDefinition/helmcharts.source.toolkit.fluxcd.io configured       &lt;br /&gt;                                                                CustomResourceDefinition/helmreleases.helm.toolkit.fluxcd.io configured       &lt;br /&gt;                                                                CustomResourceDefinition/helmrepositories.source.toolkit.fluxcd.io configured &lt;br /&gt;                                                                CustomResourceDefinition/kustomizations.kustomize.toolkit.fluxcd.io configured&lt;br /&gt;                                                                CustomResourceDefinition/ocirepositories.source.toolkit.fluxcd.io configured  &lt;br /&gt;                                                                CustomResourceDefinition/providers.notification.toolkit.fluxcd.io configured  &lt;br /&gt;                                                                CustomResourceDefinition/receivers.notification.toolkit.fluxcd.io configured  &lt;br /&gt;                                                                Namespace/flux-system configured                                              &lt;br /&gt;                                                                ClusterRole/crd-controller-flux-system configured                             &lt;br /&gt;                                                                ClusterRole/flux-edit-flux-system configured                                  &lt;br /&gt;                                                                ClusterRole/flux-view-flux-system configured                                  &lt;br /&gt;                                                                ClusterRoleBinding/cluster-reconciler-flux-system configured                  &lt;br /&gt;                                                                ClusterRoleBinding/crd-controller-flux-system configured                      &lt;br /&gt;                                                                ResourceQuota/flux-system/critical-pods-flux-system configured                &lt;br /&gt;                                                                ServiceAccount/flux-system/helm-controller configured                         &lt;br /&gt;                                                                ServiceAccount/flux-system/kustomize-controller configured                    &lt;br /&gt;                                                                ServiceAccount/flux-system/notification-controller configured                 &lt;br /&gt;                                                                ServiceAccount/flux-system/source-controller configured                       &lt;br /&gt;                                                                Service/flux-system/notification-controller configured                        &lt;br /&gt;                                                                Service/flux-system/source-controller configured                              &lt;br /&gt;                                                                Service/flux-system/webhook-receiver configured                               &lt;br /&gt;                                                                Deployment/flux-system/helm-controller configured                             &lt;br /&gt;                                                                Deployment/flux-system/kustomize-controller configured                        &lt;br /&gt;                                                                Deployment/flux-system/notification-controller configured                     &lt;br /&gt;                                                                Deployment/flux-system/source-controller configured                           &lt;br /&gt;                                                                Kustomization/flux-system/apps created                                        &lt;br /&gt;                                                                Kustomization/flux-system/config created                                      &lt;br /&gt;                                                                Kustomization/flux-system/flux-system configured                              &lt;br /&gt;                                                                Kustomization/flux-system/infrastructure created                              &lt;br /&gt;                                                                Kustomization/flux-system/repos created                                       &lt;br /&gt;                                                                NetworkPolicy/flux-system/allow-egress configured                             &lt;br /&gt;                                                                NetworkPolicy/flux-system/allow-scraping configured                           &lt;br /&gt;                                                                NetworkPolicy/flux-system/allow-webhooks configured                           &lt;br /&gt;                                                                GitRepository/flux-system/flux-system configured                              &lt;br /&gt;12s     Normal  ReconciliationSucceeded Kustomization/flux-system       Reconciliation finished &lt;span class=&quot;token keyword&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;6&lt;/span&gt;.02411383s, next run &lt;span class=&quot;token keyword&quot;&gt;in&lt;/span&gt; 10m0s&lt;br /&gt;11s     Normal  DependencyNotReady      Kustomization/infrastructure    Dependencies &lt;span class=&quot;token keyword&quot;&gt;do&lt;/span&gt; not meet ready condition, retrying &lt;span class=&quot;token keyword&quot;&gt;in&lt;/span&gt; 30s&lt;br /&gt;10s     Normal  NewArtifact     HelmRepository/ingress-nginx    stored fetched index of size &lt;span class=&quot;token number&quot;&gt;224&lt;/span&gt;.7kB from &lt;span class=&quot;token string&quot;&gt;&#39;https://kubernetes.github.io/ingress-nginx&#39;&lt;/span&gt;&lt;br /&gt;10s     Normal  NewArtifact     HelmRepository/jetstack stored fetched index of size &lt;span class=&quot;token number&quot;&gt;492&lt;/span&gt;.1kB from &lt;span class=&quot;token string&quot;&gt;&#39;https://charts.jetstack.io/&#39;&lt;/span&gt;&lt;br /&gt;10s     Normal  NewArtifact     HelmRepository/longhorn stored fetched index of size &lt;span class=&quot;token number&quot;&gt;70&lt;/span&gt;.95kB from &lt;span class=&quot;token string&quot;&gt;&#39;https://charts.longhorn.io&#39;&lt;/span&gt;&lt;br /&gt;9s      Normal  NewArtifact     HelmRepository/metallb  stored fetched index of size &lt;span class=&quot;token number&quot;&gt;29&lt;/span&gt;.23kB from &lt;span class=&quot;token string&quot;&gt;&#39;https://metallb.github.io/metallb&#39;&lt;/span&gt;&lt;br /&gt;11s     Normal  Progressing     Kustomization/repos     HelmRepository/flux-system/cloudnative-pg created&lt;br /&gt;                                                        HelmRepository/flux-system/ingress-nginx created &lt;br /&gt;                                                        HelmRepository/flux-system/jetstack created      &lt;br /&gt;                                                        HelmRepository/flux-system/longhorn created      &lt;br /&gt;                                                        HelmRepository/flux-system/metallb created       &lt;br /&gt;                                                        HelmRepository/flux-system/podinfo created       &lt;br /&gt;                                                        HelmRepository/flux-system/strrl created         &lt;br /&gt;                                                        HelmRepository/flux-system/truecharts created    &lt;br /&gt;6s      Normal  Progressing     Kustomization/repos     Health check passed &lt;span class=&quot;token keyword&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;5&lt;/span&gt;.044890457s&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Pay particular attention to the order in which kustomizations are applied. Think back to part 2 when we considered how best to structure our repository, and how to configure dependencies. For example, the apps kustomization watis for the infrastructure kustomization to be deployed first. An application like Vualtwarden or Nextcloud depends on VolSync, CNPG, clusterissuer, metallb, longhorn, etc. The way we’ve configured things, Flux knows to wait until all of those resources are available to start deploying any apps, which prevents all sorts of potential deployment errors.&lt;/p&gt;
&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;$ flux get ks&lt;br /&gt;NAME                    REVISION                SUSPENDED       READY   MESSAGE                                              &lt;br /&gt;apps                                            False           False   dependency &lt;span class=&quot;token string&quot;&gt;&#39;flux-system/infrastructure&#39;&lt;/span&gt; is not ready&lt;br /&gt;cert-manager            main@sha1:0cf3b4e3      False           True    Applied revision: main@sha1:0cf3b4e3                &lt;br /&gt;cf-tunnel-ingress       main@sha1:0cf3b4e3      False           True    Applied revision: main@sha1:0cf3b4e3                &lt;br /&gt;cloudnative-pg          main@sha1:0cf3b4e3      False           False   dependency &lt;span class=&quot;token string&quot;&gt;&#39;flux-system/longhorn&#39;&lt;/span&gt; is not ready      &lt;br /&gt;cluster-issuer          main@sha1:0cf3b4e3      False           False   dependency &lt;span class=&quot;token string&quot;&gt;&#39;flux-system/cert-manager&#39;&lt;/span&gt; is not ready  &lt;br /&gt;config                  main@sha1:0cf3b4e3      False           True    Applied revision: main@sha1:0cf3b4e3                &lt;br /&gt;flux-system             main@sha1:0cf3b4e3      False           True    Applied revision: main@sha1:0cf3b4e3                &lt;br /&gt;infrastructure                                  False           Unknown Reconciliation &lt;span class=&quot;token keyword&quot;&gt;in&lt;/span&gt; progress                          &lt;br /&gt;ingress-nginx           main@sha1:0cf3b4e3      False           True    Applied revision: main@sha1:0cf3b4e3                &lt;br /&gt;kubernetes-reflector    main@sha1:0cf3b4e3      False           True    Applied revision: main@sha1:0cf3b4e3                &lt;br /&gt;longhorn                main@sha1:0cf3b4e3      False           True    Applied revision: main@sha1:0cf3b4e3                &lt;br /&gt;longhorn-config                                 False           False   dependency &lt;span class=&quot;token string&quot;&gt;&#39;flux-system/longhorn&#39;&lt;/span&gt; is not ready      &lt;br /&gt;metallb                 main@sha1:0cf3b4e3      False           True    Applied revision: main@sha1:0cf3b4e3                &lt;br /&gt;metallb-config          main@sha1:0cf3b4e3      False           True    Applied revision: main@sha1:0cf3b4e3                &lt;br /&gt;repos                   main@sha1:0cf3b4e3      False           True    Applied revision: main@sha1:0cf3b4e3                &lt;br /&gt;snapshot-controller     main@sha1:0cf3b4e3      False           True    Applied revision: main@sha1:0cf3b4e3                &lt;br /&gt;volsync                 main@sha1:0cf3b4e3      False           True    Applied revision: main@sha1:0cf3b4e3                &lt;br /&gt;volsync-config          main@sha1:0cf3b4e3      False           True    Applied revision: main@sha1:0cf3b4e3                &lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Your first sign that things are working is when the infrastructure ks reconciles. Once it does, infrastructure components like longhorn, metallb, nginx should come up. One of my first checks is the longhorn UI, which will show volumes created for any restore tasks or new deployments.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;http://localhost:8080/assets/images/2025/11/cluster-restore-longhorn.png&quot; alt=&quot;image&quot; /&gt;&lt;/p&gt;
&lt;p&gt;Once flux starts deploying your applications, you can keep an eye on any pods created in that applicaiton namespace. It can be anxiety inducing to wait for a large deployment like nextcloud to reach ready status. Just know that if the CNPG and Volsync containers reach complete or running status, you’re probably fine.&lt;/p&gt;
&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;$ kubectl get pods &lt;span class=&quot;token parameter variable&quot;&gt;-n&lt;/span&gt; nextcloud-demo &lt;br /&gt;NAME                                             READY   STATUS              RESTARTS   AGE&lt;br /&gt;nextcloud-demo-5c4777bf8d-f8dhp                  &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;/1     Init:0/3            &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;          8m11s&lt;br /&gt;nextcloud-demo-clamav-76666fbd67-tsrbd           &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;/1     Init:0/2            &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;          8m11s&lt;br /&gt;nextcloud-demo-cnpg-main-1-full-recovery-pws75   &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;/1     Running             &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;          8m10s&lt;br /&gt;nextcloud-demo-collabora-644c55596f-rrglv        &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;/1     Init:0/2            &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;          8m11s&lt;br /&gt;nextcloud-demo-imaginary-5d55d79fcf-2jbzd        &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;/1     Init:0/2            &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;          8m11s&lt;br /&gt;nextcloud-demo-nextcloud-cron-29407260-7c2pq     &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;/1     ContainerCreating   &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;          7m8s&lt;br /&gt;nextcloud-demo-nginx-675b945674-8n5d4            &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;/1     Init:0/3            &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;          8m11s&lt;br /&gt;nextcloud-demo-notify-66bc88d785-zrfkj           &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;/1     Init:0/3            &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;          8m12s&lt;br /&gt;nextcloud-demo-preview-cron-29407260-748xr       &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;/1     ContainerCreating   &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;          7m8s&lt;br /&gt;nextcloud-demo-redis-0                           &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;/1     Running             &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;          8m11s&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;And when it’s all done, your applications should be back online. Here I am checking for my test record in vaultwarden, and logging back into nextcloud.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;http://localhost:8080/assets/images/2025/11/cluster-restore-vaultwarden.png&quot; alt=&quot;image&quot; /&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;http://localhost:8080/assets/images/2025/11/cluster-restore-nextcloud.png&quot; alt=&quot;image&quot; /&gt;&lt;/p&gt;
&lt;h2&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;I could go on writing about this little project of mine for another 10 posts, but I need to draw a line in the sand so I can close this out and return to some of my other projects. All in all, it’s been over a year since I set out to migrate all of my TrueCharts apps into the Talos&#92;Kubernetes ecosystem, and it’s been 6 months since I started writing this series. I think I had everything ‘working’ a few months ago, but challenging myself along the way to write this series of posts forced me to do my best to do things the right way. I’m sure I will have other posts related to this, but let’s call this the ‘core’ guide for my TrueK8S project. Thanks for reading, and I hope you found something useful here.&lt;/p&gt;
</content>
    </entry>
</feed>