<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Homelab on Zwindler's Reflection</title><link>https://blog.zwindler.fr/en/tags/homelab/</link><description>Recent content in Homelab on Zwindler's Reflection</description><generator>Hugo -- gohugo.io</generator><language>en</language><copyright>Licensed under CC BY-SA 4.0</copyright><lastBuildDate>Mon, 24 Nov 2025 18:00:00 +0200</lastBuildDate><atom:link href="https://blog.zwindler.fr/en/tags/homelab/index.xml" rel="self" type="application/rss+xml"/><item><title>OCI Artifacts as LXC Machine Base on Proxmox 9.1, Finally?</title><link>https://blog.zwindler.fr/en/2025/11/24/oci-artifacts-as-lxc-machine-base-on-proxmox-9.1-finally/</link><pubDate>Mon, 24 Nov 2025 18:00:00 +0200</pubDate><guid>https://blog.zwindler.fr/en/2025/11/24/oci-artifacts-as-lxc-machine-base-on-proxmox-9.1-finally/</guid><description>&lt;img src="https://blog.zwindler.fr/2025/11/pve-oci2.webp" alt="Featured image of post OCI Artifacts as LXC Machine Base on Proxmox 9.1, Finally?" /&gt;&lt;h2 id="context"&gt;Context
&lt;/h2&gt;&lt;p&gt;A few days ago, &lt;a class="link" href="https://proxmox.com/en/about/company-details/press-releases/proxmox-virtual-environment-9-1" target="_blank" rel="noopener"
&gt;the Proxmox VE dev team announced a new version (9.1)&lt;/a&gt; whose major new feature is the addition of OCI artifacts support as a base for creating LXC containers.&lt;/p&gt;
&lt;p&gt;A long-awaited feature, since in theory it finally opens the door to launching &amp;ldquo;Docker&amp;rdquo;-type containers in Proxmox, something the Proxmox devs had always refused.&lt;/p&gt;
&lt;p&gt;That&amp;rsquo;s also why one of my blog articles gets the most traffic on Google (sniff, soon the end of glory):&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://blog.zwindler.fr/2022/11/07/containers-docker-dans-proxmox-avec-lxc/" target="_blank" rel="noopener"
&gt;This article where I explain how to launch Docker containers (via LXC) in Proxmox VE (normally not possible)&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote&gt;
&lt;p&gt;Create LXC containers from OCI images&lt;/p&gt;
&lt;p&gt;Proxmox VE 9.1 integrates support for Open Container Initiative (OCI) images, a standard format for container distribution. Users can now download widely-adopted OCI images directly from registries or upload them manually to use as templates for LXC containers. Depending on the image, these containers are provisioned as full system containers or lean application containers.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id="lets-test-first-the-prerequisites"&gt;Let&amp;rsquo;s Test? First the Prerequisites
&lt;/h2&gt;&lt;p&gt;So, I&amp;rsquo;m curious, how does it work?&lt;/p&gt;
&lt;p&gt;First, you need to pre-download the image you&amp;rsquo;re interested in to your storage (one that can host &amp;ldquo;CT Templates&amp;rdquo;).&lt;/p&gt;
&lt;p&gt;&lt;img src="https://blog.zwindler.fr/2025/11/pve-oci1.avif"
loading="lazy"
&gt;&lt;/p&gt;
&lt;p&gt;Fun thing, there&amp;rsquo;s a button called &amp;ldquo;Query tags&amp;rdquo;, which I imagine retrieves a list of tags. Well, it&amp;rsquo;s not starting well, it doesn&amp;rsquo;t work (at least not on docker.io&amp;hellip;).&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;command &amp;#39;skopeo list-tags docker://docker.io/zwindler/prime-calculator&amp;#39; failed: exit code 1 (500)
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;EDIT: since then, it works again, on all my nodes. Perhaps a temporary issue.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://blog.zwindler.fr/2025/12/qwen.avif"
loading="lazy"
&gt;&lt;/p&gt;
&lt;p&gt;Note: &lt;code&gt;skopeo&lt;/code&gt; is precisely one of the dependencies used in my &amp;ldquo;proxmox+docker hack&amp;rdquo; article that allows manipulating (mainly downloading) containers from remote registries.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://blog.zwindler.fr/2025/11/pve-oci2.avif"
loading="lazy"
&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src="https://blog.zwindler.fr/2025/11/pve-oci3.avif"
loading="lazy"
&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src="https://blog.zwindler.fr/2025/11/pve-oci4.avif"
loading="lazy"
&gt;&lt;/p&gt;
&lt;h2 id="creating-the-lxc-container"&gt;Creating the LXC Container
&lt;/h2&gt;&lt;p&gt;Now that the template (the OCI image) is available on our storage, we can create an LXC container as usual. Click on &amp;ldquo;Create CT&amp;rdquo;, give a CT ID, a password:&lt;/p&gt;
&lt;p&gt;&lt;img src="https://blog.zwindler.fr/2025/11/pve-oci5.avif"
loading="lazy"
&gt;&lt;/p&gt;
&lt;p&gt;For the template, we choose our OCI artifact:&lt;/p&gt;
&lt;p&gt;&lt;img src="https://blog.zwindler.fr/2025/11/pve-oci6.avif"
loading="lazy"
&gt;&lt;/p&gt;
&lt;p&gt;And validate. Proxmox should create our container:&lt;/p&gt;
&lt;p&gt;&lt;img src="https://blog.zwindler.fr/2025/11/pve-oci7.avif"
loading="lazy"
&gt;&lt;/p&gt;
&lt;p&gt;Even though the terminal tells us that application containers may not work well in the JS console, for all the containers I managed to start (see below), I always had a functional console.&lt;/p&gt;
&lt;p&gt;So the bet seems rather successful.&lt;/p&gt;
&lt;p&gt;Example with &lt;code&gt;docker.io/python:3.11.14-trixie&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src="https://blog.zwindler.fr/2025/12/python.avif"
loading="lazy"
&gt;&lt;/p&gt;
&lt;h2 id="when-it-wasnt-working-yet"&gt;When It Wasn&amp;rsquo;t Working (Yet)
&lt;/h2&gt;&lt;p&gt;I had 2 issues on a Proxmox VE 9.1 (that had been upgraded and tinkered with a bit, in short, a machine that had seen some use) starting an LXC container on OCI base with Proxmox VE 9.1 because I ran into 2 bugs.&lt;/p&gt;
&lt;p&gt;I didn&amp;rsquo;t reproduce these bugs on a &amp;ldquo;fresh&amp;rdquo; install.&lt;/p&gt;
&lt;h3 id="first-bug-from-scratch-image"&gt;First Bug: &amp;ldquo;from scratch&amp;rdquo; Image
&lt;/h3&gt;&lt;p&gt;First, my &lt;code&gt;prime-calculator&lt;/code&gt; image wasn&amp;rsquo;t even created.&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;TASK ERROR: unable to create CT 106 - Error while extracting OCI image: Unknown layer digest sha256:2bc4d17e1eb16f6b52acbafeb6d86c8f3eaf9588a5e2a7a245b6bb1d85e93396 found in rootfs.diff_ids: Unknown layer digest sha256:2bc4d17e1eb16f6b52acbafeb6d86c8f3eaf9588a5e2a7a245b6bb1d85e93396 found in rootfs.diff_ids
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;OK, fair enough. My image is a binary &amp;ldquo;from scratch&amp;rdquo;, with nothing but the binary, and maybe I made a mistake somewhere&amp;hellip;&lt;/p&gt;
&lt;p&gt;Still doesn&amp;rsquo;t work.&lt;/p&gt;
&lt;h3 id="second-bug-unable-to-start"&gt;Second Bug: Unable to Start
&lt;/h3&gt;&lt;p&gt;However, even with known images, the container is properly created:&lt;/p&gt;
&lt;p&gt;&lt;img src="https://blog.zwindler.fr/2025/11/pve-oci8.avif"
loading="lazy"
&gt;&lt;/p&gt;
&lt;p&gt;But impossible to start it:&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;problem with monitor socket, but continuing anyway: got timeout
TASK ERROR: unable to get PID for CT 105 (not running?)
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Same error with command line:&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;pct start 105 --debug
problem with monitor socket, but continuing anyway: got timeout
lxc_start_main: 257 Container is already running
- Read uid map: type u nsid 0 hostid 100000 range 65536
INFO confile - ../src/lxc/confile.c:set_config_idmaps:2295 - Read uid map: type g nsid 0 hostid 100000 range 65536
ERROR lxc_start - ../src/lxc/tools/lxc_start.c:lxc_start_main:257 - Container is already running
unable to get PID for CT 105 (not running?)
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;&lt;img src="https://blog.zwindler.fr/2025/11/pve-oci9.avif"
loading="lazy"
&gt;&lt;/p&gt;
&lt;p&gt;After (laborious) investigation, it turns out it&amp;rsquo;s an AppArmor problem. I don&amp;rsquo;t know if I caused it with my tinkering or if it&amp;rsquo;s a more generalized bug for now (probably option 1, but 2 isn&amp;rsquo;t impossible either&amp;hellip;)&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;Nov 23 10:37:26 node01 systemd[1]: Started pve-container-debug@105.service - PVE LXC Container: 151.
Nov 23 10:37:27 node01 kernel: audit: type=1400 audit(1764067047.008:175): apparmor=&amp;#34;DENIED&amp;#34; operation=&amp;#34;create&amp;#34; class=&amp;#34;net&amp;#34;
Nov 23 10:37:27 node01 kernel: audit: type=1400 audit(1764067047.008:176): apparmor=&amp;#34;DENIED&amp;#34; operation=&amp;#34;create&amp;#34; class=&amp;#34;net&amp;#34;
Nov 23 10:37:27 node01 systemd[1]: pve-container-debug@105.service: Deactivated successfully.
Nov 23 10:37:37 node01 pct[21369]: unable to get PID for CT 105 (not running?)
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;The temporary (and dirty) workaround is to disable the AppArmor profile for &lt;code&gt;lxc-start&lt;/code&gt;, and remove any zombie files/processes.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;apparmor_parser -R /etc/apparmor.d/usr.bin.lxc-start
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;ps aux &lt;span class="p"&gt;|&lt;/span&gt; grep &lt;span class="s2"&gt;&amp;#34;lxc-start&amp;#34;&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt; grep &lt;span class="s2"&gt;&amp;#34;105&amp;#34;&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt; awk &lt;span class="s1"&gt;&amp;#39;{print $2}&amp;#39;&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt; xargs -r &lt;span class="nb"&gt;kill&lt;/span&gt; -9
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;rm -f /var/lib/lxc/105/config.lock
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;rm -f /run/lxc/lock/var/lib/lxc/105
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Note: You can also disable it permanently, but that&amp;rsquo;s obviously something you shouldn&amp;rsquo;t do.&lt;/p&gt;
&lt;p&gt;From there, the container is accessible, sometimes in console (depends on the container)&lt;/p&gt;
&lt;p&gt;&lt;img src="https://blog.zwindler.fr/2025/11/pve-oci10.avif"
loading="lazy"
&gt;&lt;/p&gt;
&lt;h2 id="conclusion"&gt;Conclusion
&lt;/h2&gt;&lt;p&gt;Apparently, the problems I encountered don&amp;rsquo;t reproduce on a &amp;ldquo;fresh install&amp;rdquo;. So it&amp;rsquo;s probably an issue related to my &amp;ldquo;old&amp;rdquo; machines.&lt;/p&gt;
&lt;p&gt;As a bonus, another article in English that made me persevere when I understood it worked for some:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://raymii.org/s/tutorials/Finally_run_Docker_containers_natively_in_Proxmox_9.1.html" target="_blank" rel="noopener"
&gt;Raymii.org blog - Finally, run Docker containers natively in Proxmox 9.1 (OCI images)&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Note: this article helped me rediscover the &lt;code&gt;pct enter CTID&lt;/code&gt; command that allows you to log into the container.&lt;/p&gt;
&lt;p&gt;In the meantime, you still have my hack ;-)&lt;/p&gt;</description></item><item><title>MicroStack evolves: HP EliteDesk and Lenovo ThinkCentre compatibility for your homelab</title><link>https://blog.zwindler.fr/en/2025/09/17/microstack-evolves-hp-elitedesk-and-lenovo-thinkcentre-compatibility-for-your-homelab/</link><pubDate>Wed, 17 Sep 2025 12:00:00 +0200</pubDate><guid>https://blog.zwindler.fr/en/2025/09/17/microstack-evolves-hp-elitedesk-and-lenovo-thinkcentre-compatibility-for-your-homelab/</guid><description>&lt;img src="https://blog.zwindler.fr/2025/09/lenovo.webp" alt="Featured image of post MicroStack evolves: HP EliteDesk and Lenovo ThinkCentre compatibility for your homelab" /&gt;&lt;h1 id="a-microstack-update-"&gt;A MicroStack update? 😍
&lt;/h1&gt;&lt;p&gt;Yes! A few months ago, I introduced you to &lt;a class="link" href="https://blog.zwindler.fr/en/2025/03/22/microstack-an-open-source-project-to-3d-print-a-modular-rack-for-my-dell-micro-homelab/" &gt;MicroStack, my 3D printed modular rack project for Dell Micro&lt;/a&gt;. The project had unexpected success on MakerWorld / Bluesky (and even a bit on Reddit) and I received several requests to extend compatibility&amp;hellip;&lt;/p&gt;
&lt;p&gt;And since I&amp;rsquo;m nice (and I like my 3D printing side projects), I decided to respond to community requests!&lt;/p&gt;
&lt;h2 id="promise-kept-hp-elitedesk-and-lenovo-thinkcentre"&gt;Promise kept: HP EliteDesk and Lenovo ThinkCentre!
&lt;/h2&gt;&lt;p&gt;In the original article, I mentioned that &lt;strong&gt;&amp;ldquo;a version compatible with Lenovo ThinkCentre Tiny was planned&amp;rdquo;&lt;/strong&gt;. Well&amp;hellip; it&amp;rsquo;s done! And I even made a bonus with &lt;strong&gt;HP EliteDesk/ProDesk&lt;/strong&gt; because&amp;hellip; why not?&lt;/p&gt;
&lt;p&gt;Now, the &lt;strong&gt;MicroStack&lt;/strong&gt; project officially supports &lt;strong&gt;three ranges&lt;/strong&gt; of mini-PCs:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Dell OptiPlex Micro&lt;/strong&gt; (all generations) - &lt;em&gt;the pioneer&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Lenovo ThinkCentre Tiny&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;HP EliteDesk/ProDesk&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="a-growing-ecosystem"&gt;A growing ecosystem
&lt;/h2&gt;&lt;p&gt;The concept remains the same: &lt;strong&gt;stackable&lt;/strong&gt; and &lt;strong&gt;modular&lt;/strong&gt; modules to neatly organize your homelab. But now, you can &lt;strong&gt;mix brands&lt;/strong&gt; in the same rack if you have a heterogeneous fleet (and we all know how it happens in homelabs&amp;hellip; &amp;ldquo;oh look, this used machine is at a good price!&amp;rdquo;).&lt;/p&gt;
&lt;p&gt;The &lt;a class="link" href="https://makerworld.com/en/collections/5818204-microstack-rack" target="_blank" rel="noopener"
&gt;complete MicroStack collection&lt;/a&gt; now includes:&lt;/p&gt;
&lt;h3 id="pc-modules"&gt;PC Modules:
&lt;/h3&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://makerworld.com/en/models/1236448-microstack-rack-modular-rack-for-dell-micro-pcs#profileId-1256174" target="_blank" rel="noopener"
&gt;&lt;strong&gt;Dell Micro Module&lt;/strong&gt;&lt;/a&gt; - &lt;em&gt;the original&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://makerworld.com/en/models/1317460-microstack-rack-a-modular-rack-system-for-lenovo-m#profileId-1352912" target="_blank" rel="noopener"
&gt;&lt;strong&gt;Lenovo ThinkCentre Module&lt;/strong&gt;&lt;/a&gt; - &lt;em&gt;the requested one&lt;/em&gt; (thanks to a loan from someone on LinkedIn! Thanks!)&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://makerworld.com/en/models/1446203-microstack-rack-modular-rack-for-hp-elitedesk#profileId-1505986" target="_blank" rel="noopener"
&gt;&lt;strong&gt;HP EliteDesk/ProDesk Module&lt;/strong&gt;&lt;/a&gt; - &lt;em&gt;the bonus&lt;/em&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="common-modules"&gt;Common Modules:
&lt;/h3&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://makerworld.com/en/models/1236457-microstack-rack-modular-rack-storage-module#profileId-1256190" target="_blank" rel="noopener"
&gt;&lt;strong&gt;Storage Module&lt;/strong&gt;&lt;/a&gt; - for switch, accessories, etc.&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://makerworld.com/en/models/1236461-microstack-rack-modular-rack-top-hat#profileId-1256198" target="_blank" rel="noopener"
&gt;&lt;strong&gt;Hat&lt;/strong&gt;&lt;/a&gt; - clean rack finish&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;All these modules are &lt;strong&gt;inter-compatible&lt;/strong&gt; and use the same stacking system.&lt;/p&gt;
&lt;h2 id="still-the-same-best-practices"&gt;Still the same best practices
&lt;/h2&gt;&lt;p&gt;As with the original, I still recommend printing in &lt;strong&gt;PETG&lt;/strong&gt; (or even ASA or ABS?) rather than PLA for better heat resistance, even though these mini-PCs remain quite cool. The &lt;strong&gt;honeycomb&lt;/strong&gt; floor design ensures good ventilation while saving filament.&lt;/p&gt;
&lt;h2 id="the-feedback-multi-range-modeling"&gt;The feedback: multi-range modeling
&lt;/h2&gt;&lt;p&gt;Adapting the original design to new ranges was &lt;strong&gt;simpler&lt;/strong&gt; than expected, thanks to the solid foundation of the initial project. Once the concept was established with the Dell module, you &amp;ldquo;just&amp;rdquo; need to:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Take (precise!) measurements of the new models (still need to find them&amp;hellip;)&lt;/li&gt;
&lt;li&gt;Adapt the chassis dimensions&lt;/li&gt;
&lt;li&gt;Do one (or more) test prints and validate stacking (the stress, every time, of having burned 120g of plastic for nothing if you messed up)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Each new module took me about an hour of modeling, much less than the initial 3x2h of the &lt;a class="link" href="https://blog.zwindler.fr/2025/03/22/microstack-un-projet-open-source-pour-imprimer-un-rack-dell-micro/" &gt;original project&lt;/a&gt;. Prototyping (testing incomplete versions to save plastic) took quite a bit of time, which I had forgotten to count in the previous article. Easily a few more hours.&lt;/p&gt;
&lt;h2 id="community-feedback"&gt;Community feedback
&lt;/h2&gt;&lt;p&gt;What makes me happiest is seeing that the project found its audience. The feedback on MakerWorld is generally enthusiastic and the evolution requests show that the concept really meets a need.&lt;/p&gt;
&lt;p&gt;Some users have already sent me photos of their mixed installations with different brands in the same rack. This is exactly the &lt;strong&gt;modular&lt;/strong&gt; spirit I wanted to bring to the project!&lt;/p&gt;
&lt;p&gt;I also had &lt;strong&gt;one&lt;/strong&gt; negative feedback, for which I can&amp;rsquo;t do much as it stands but which was interesting and allowed me to add a warning. The fact that the back is dedicated to the charger (PSU) blocks some ports, particularly for the Lenovo. The solutions:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Live with only Ethernet (for a lab, personally I think that&amp;rsquo;s fine)&lt;/li&gt;
&lt;li&gt;Move the power supplies to the &amp;ldquo;storage&amp;rdquo; module&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;img src="https://blog.zwindler.fr/2025/09/limitations.avif"
loading="lazy"
&gt;&lt;/p&gt;
&lt;h2 id="and-now"&gt;And now?
&lt;/h2&gt;&lt;p&gt;With these three ranges covered, my MicroStack project becomes really &lt;strong&gt;versatile&lt;/strong&gt;. If you have suggestions for other mini-PCs to support, don&amp;rsquo;t hesitate! MinisForum, perhaps?&lt;/p&gt;
&lt;p&gt;If this project interests you, feel free to comment, share, provide feedback, &lt;strong&gt;or even &lt;em&gt;boost&lt;/em&gt; the three models&lt;/strong&gt; for those who have a MakerWorld account (it&amp;rsquo;s free, but it&amp;rsquo;s appreciated :-P).&lt;/p&gt;</description></item><item><title>MicroStack - an open source project to 3D print a modular rack for my Dell Micro homelab</title><link>https://blog.zwindler.fr/en/2025/03/22/microstack-an-open-source-project-to-3d-print-a-modular-rack-for-my-dell-micro-homelab/</link><pubDate>Sat, 22 Mar 2025 12:00:00 +0200</pubDate><guid>https://blog.zwindler.fr/en/2025/03/22/microstack-an-open-source-project-to-3d-print-a-modular-rack-for-my-dell-micro-homelab/</guid><description>&lt;img src="https://blog.zwindler.fr/2025/03/microstack.webp" alt="Featured image of post MicroStack - an open source project to 3D print a modular rack for my Dell Micro homelab" /&gt;&lt;h1 id="again-another-evolution-of-your-lab"&gt;AGAIN? Another evolution of your lab???
&lt;/h1&gt;&lt;p&gt;If you&amp;rsquo;ve been following the lore of my blog a bit, you know I have as many versions of my homelab as years of experience XD.&lt;/p&gt;
&lt;p&gt;2025 will be no exception. In early 2024, I embarked on the &lt;a class="link" href="https://blog.zwindler.fr/2024/02/15/microrack-v1-pour-dell-micro/" &gt;construction of a rack based on aluminum profiles and 3D printing (in french)&lt;/a&gt;, based on a project sent by a friend on Whatsapp!&lt;/p&gt;
&lt;p&gt;&lt;img src="https://blog.zwindler.fr/2024/02/microrack.avif"
loading="lazy"
&gt;&lt;/p&gt;
&lt;p&gt;But in use, I found it massive, not very practical, not very pretty&amp;hellip; in short, not adapted to my needs.&lt;/p&gt;
&lt;p&gt;Except that (I&amp;rsquo;ve already mentioned it) I&amp;rsquo;ve since gotten into 3D printing and a bit (by force of circumstance) into 3D modeling (they often go hand in hand). I said to myself: why not create my own project that fits my needs?&lt;/p&gt;
&lt;p&gt;So I wanted to explore a homemade solution for my homelab, 3D printed, that would be both modular and stackable. The idea was to offer an adaptable system according to needs, with a simple and effective design.&lt;/p&gt;
&lt;h2 id="a-design-designed-for-organization"&gt;A design designed for organization
&lt;/h2&gt;&lt;p&gt;The &lt;strong&gt;MicroStack Rack&lt;/strong&gt; is designed to neatly store several &lt;strong&gt;Dell OptiPlex Micro&lt;/strong&gt; while maximizing space. It consists of &lt;strong&gt;three different modules&lt;/strong&gt; for now:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://makerworld.com/fr/models/1236448-microstack-rack-modular-rack-for-dell-micro-pcs#profileId-1256174" target="_blank" rel="noopener"
&gt;&lt;strong&gt;The PC module&lt;/strong&gt;&lt;/a&gt;, which accommodates a &lt;strong&gt;Dell Micro&lt;/strong&gt; (all generations) and its &lt;strong&gt;external power supply&lt;/strong&gt; at the back for more practicality.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;img src="https://blog.zwindler.fr/2025/03/dellmodule.avif"
loading="lazy"
&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://makerworld.com/fr/models/1236457-microstack-rack-modular-rack-storage-module#profileId-1256190" target="_blank" rel="noopener"
&gt;&lt;strong&gt;The storage module&lt;/strong&gt;&lt;/a&gt;, an empty compartment for &lt;strong&gt;accessories, network switch or other equipment&lt;/strong&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;img src="https://blog.zwindler.fr/2025/03/storagemodule.avif"
loading="lazy"
&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://makerworld.com/fr/models/1236461-microstack-rack-modular-rack-top-hat#profileId-1256198" target="_blank" rel="noopener"
&gt;&lt;strong&gt;The hat&lt;/strong&gt;&lt;/a&gt;, an optional element that covers the rack for a cleaner rendering.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;img src="https://blog.zwindler.fr/2025/03/hatmodule.avif"
loading="lazy"
&gt;&lt;/p&gt;
&lt;p&gt;All modules are &lt;strong&gt;stackable&lt;/strong&gt;, allowing you to adapt the configuration according to your number of machines.&lt;/p&gt;
&lt;p&gt;Even though I printed the prototype in PLA, I recommend using &lt;strong&gt;PETG&lt;/strong&gt; instead, which resists heat better than PLA. However, these machines remain rather cool at idle and the &lt;strong&gt;honeycomb floor&lt;/strong&gt; improves ventilation (and reduces material consumption). Maybe it works too.&lt;/p&gt;
&lt;h2 id="how-long-does-it-take-to-do-this-kind-of-project"&gt;How long does it take to do this kind of project?
&lt;/h2&gt;&lt;p&gt;A quick note on time spent.&lt;/p&gt;
&lt;p&gt;I haven&amp;rsquo;t done much 3D design in the past (I made a few maps on Unreal Tournament 2004&amp;hellip; oh my&amp;hellip;, that was 20 years ago!!!). So, I thought it might be interesting to share how long it took me.&lt;/p&gt;
&lt;p&gt;The modeling was done in &lt;strong&gt;three sessions of 2 hours&lt;/strong&gt;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;2h&lt;/strong&gt; to take measurements, make an initial prototype and get familiar with Blender.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;2h&lt;/strong&gt; to create the module dedicated to the &lt;strong&gt;Dell Micro&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;2h&lt;/strong&gt; to add the &lt;strong&gt;storage module&lt;/strong&gt; and the &lt;strong&gt;hat&lt;/strong&gt; (it goes faster, I&amp;rsquo;ve already done part of the work and I&amp;rsquo;m more efficient in my use of Blender).&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;We can add an hour or two for handling the 3D printer (launching the print, checking it doesn&amp;rsquo;t fail a few minutes in, cleaning the plate after printing, etc.) and 3-4 hours for the &amp;ldquo;social&amp;rdquo; part (photos, upload to makerworld, writing descriptions and blog post, sharing on social networks).&lt;/p&gt;
&lt;p&gt;A nice little side project of about ten hours then.&lt;/p&gt;
&lt;h2 id="files-and-evolutions"&gt;Files and evolutions
&lt;/h2&gt;&lt;p&gt;As promised on Bluesky where I teased the project, the files were created under &lt;strong&gt;Creative Commons 4.0 BY-SA&lt;/strong&gt; license (STL formats and Blender sources), but this is incompatible with &lt;strong&gt;MakerWorld&lt;/strong&gt; exclusive policy (obviously) so the 3MF files are in Standard Digital File Licence:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://makerworld.com/en/models/1236448-microstack-rack-modular-rack-for-dell-micro-pcs#profileId-1256174" target="_blank" rel="noopener"
&gt;MicroStack Rack – Dell Micro Module&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://makerworld.com/en/models/1236457-microstack-rack-modular-rack-storage-module#profileId-1256190" target="_blank" rel="noopener"
&gt;MicroStack Rack – Storage Module&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://makerworld.com/en/models/1236461-microstack-rack-modular-rack-top-hat#profileId-1256198" target="_blank" rel="noopener"
&gt;MicroStack Rack – Hat&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;A &lt;strong&gt;version compatible with Lenovo ThinkCentre Tiny&lt;/strong&gt; is planned for the future (I was asked on Bluesky).&lt;/p&gt;
&lt;p&gt;If this project interests you, feel free to comment, share, provide feedback, or even &lt;em&gt;boost&lt;/em&gt; the three models for those who have a MakerWorld account (it&amp;rsquo;s free, but it&amp;rsquo;s appreciated :-P).&lt;/p&gt;</description></item><item><title>Sidero Omni - Talos Linux on Oracle Cloud (free tier)</title><link>https://blog.zwindler.fr/en/2025/01/04/sidero-omni-talos-linux-on-oracle-cloud-free-tier/</link><pubDate>Sat, 04 Jan 2025 18:00:00 +0200</pubDate><guid>https://blog.zwindler.fr/en/2025/01/04/sidero-omni-talos-linux-on-oracle-cloud-free-tier/</guid><description>&lt;img src="https://blog.zwindler.fr/2025/01/omni-oracle.webp" alt="Featured image of post Sidero Omni - Talos Linux on Oracle Cloud (free tier)" /&gt;&lt;p&gt;Fun fact, on January 4th, 2024 (exactly one year ago), my first article of the year was about &lt;a class="link" href="https://blog.zwindler.fr/2024/01/04/un-peu-plus-loin-avec-maas-canonical" &gt;Maas&lt;/a&gt;. Starting 2025, on the same day, with another article about a solution that aims to automate infrastructure, especially bare metal, is funny :)&lt;/p&gt;
&lt;h2 id="context"&gt;Context
&lt;/h2&gt;&lt;p&gt;I won!!!&lt;/p&gt;
&lt;p&gt;&lt;img src="https://blog.zwindler.fr/2025/01/sidero-win.avif"
loading="lazy"
&gt;&lt;/p&gt;
&lt;p&gt;I occasionally play games on social media (less often now) and I also sometimes enter contests at conferences.&lt;/p&gt;
&lt;p&gt;And there, I won a one-year subscription to Sidero Labs&amp;rsquo; SaaS (the creators of Talos Linux), &lt;strong&gt;Omni&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;For those wondering, Omni is a Kubernetes cluster deployment solution that allows you to orchestrate servers running Talos, a minimalist and secure Linux operating system dedicated to Kubernetes. As for Talos, we&amp;rsquo;ll certainly talk about it in future articles.&lt;/p&gt;
&lt;h2 id="what-does-this-have-to-do-with-oracle-cloud"&gt;What Does This Have to Do with Oracle Cloud?
&lt;/h2&gt;&lt;p&gt;Winning is great, it&amp;rsquo;s always nice. But what do I do with this SaaS now?&lt;/p&gt;
&lt;p&gt;The first idea that comes to mind is to order a dedicated server somewhere and install Talos on it (with an ISO generated by Omni), or do the same thing but install a hypervisor, then create Talos Linux VMs (again, thanks to Omni).&lt;/p&gt;
&lt;p&gt;But I&amp;rsquo;m &lt;del&gt;cheap&lt;/del&gt; eternally frugal and I saw that Oracle Cloud Infrastructure (OCI) is supported by Talos Linux and Omni, so I wanted to try it.&lt;/p&gt;
&lt;p&gt;For those who don&amp;rsquo;t know OCI, I wrote a series of articles in 2023 explaining how to create a free cluster with &lt;code&gt;kubeadm&lt;/code&gt; on the (quite generous) free tier:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://blog.zwindler.fr/2023/04/24/cluster-kubernetes-gratuit-part1/" &gt;A free Kubernetes cluster for your personal labs! - part 1&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://blog.zwindler.fr/2023/05/23/cluster-kubernetes-gratuit-part2/" &gt;A free Kubernetes cluster for your personal labs! - part 2&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;We&amp;rsquo;re going to reuse the free tier here, but to deploy and manage clusters with Omni.&lt;/p&gt;
&lt;p&gt;Note: you can reread them, but I&amp;rsquo;ve done better since then because I managed to integrate free tier machines INTO a managed Kubernetes cluster, which is much nicer to use. Stay tuned for the upcoming article ;).&lt;/p&gt;
&lt;h2 id="prerequisites"&gt;Prerequisites
&lt;/h2&gt;&lt;p&gt;For Talos Linux on Oracle Cloud Infrastructure (OCI) and more specifically integrating machines with Omni, there are a few necessary configuration steps.&lt;/p&gt;
&lt;p&gt;Note: this tutorial is partially based on &lt;a class="link" href="https://www.talos.dev/v1.9/talos-guides/install/cloud-platforms/oracle/" target="_blank" rel="noopener"
&gt;the official Talos Linux documentation&lt;/a&gt;, adapted for Omni and with additional details on Oracle Cloud Infrastructure.&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;m assuming you already have an account on Oracle Cloud Infrastructure, as well as the &lt;code&gt;talosctl&lt;/code&gt; binaries and the &lt;code&gt;oci&lt;/code&gt; CLI. Otherwise, a quick:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;brew update &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; brew install oci-cli talosctl
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Authenticate with the CLI tool:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;oci session authenticate
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;When authentication is requested, choose the region corresponding to your location (for example, eu-paris-1). Once done, you&amp;rsquo;ll see a confirmation message in the browser and you&amp;rsquo;ll need to give a cute name to the profile for &lt;code&gt;oci&lt;/code&gt; in the terminal and validate.&lt;/p&gt;
&lt;h2 id="retrieving-the-compartment-id"&gt;Retrieving the Compartment ID
&lt;/h2&gt;&lt;p&gt;One of the interesting concepts of Oracle Cloud Infrastructure (found in other cloud providers in one form or another) is the notion of &amp;ldquo;compartment&amp;rdquo;. Basically, resources are stored in &amp;ldquo;compartments&amp;rdquo; to organize resources.&lt;/p&gt;
&lt;p&gt;You can work in the &amp;ldquo;root&amp;rdquo; compartment, but it&amp;rsquo;s cleaner to create a specific one for the occasion.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://blog.zwindler.fr/2025/01/compartments.avif"
loading="lazy"
&gt;&lt;/p&gt;
&lt;p&gt;Example OCID:&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;ocid1.compartment.oc1..aaaaaaaayrmiilkb5m2b7never345435gonna345give87978you12upu6ifoh6csihm4awsjq
&lt;/code&gt;&lt;/pre&gt;&lt;h2 id="preparing-the-oracle-cloud-environment"&gt;Preparing the Oracle Cloud Environment
&lt;/h2&gt;&lt;p&gt;Once we have that, we&amp;rsquo;ll use the CLI to create all the things we&amp;rsquo;ll need for our virtual machines to register on Omni&amp;rsquo;s SaaS.&lt;/p&gt;
&lt;p&gt;Creating a VCN (Virtual Cloud Network) and network configuration:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;export&lt;/span&gt; &lt;span class="nv"&gt;cidr_block&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;10.0.0.0/16
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;export&lt;/span&gt; &lt;span class="nv"&gt;subnet_block&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;10.0.0.0/24
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;export&lt;/span&gt; &lt;span class="nv"&gt;compartment_id&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&amp;lt;your_ocid_compartment&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Create the VCN and subnet:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;export&lt;/span&gt; &lt;span class="nv"&gt;vcn_id&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="k"&gt;$(&lt;/span&gt;oci network vcn create --cidr-block &lt;span class="nv"&gt;$cidr_block&lt;/span&gt; --display-name talos-example --compartment-id &lt;span class="nv"&gt;$compartment_id&lt;/span&gt; --query data.id --raw-output&lt;span class="k"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;export&lt;/span&gt; &lt;span class="nv"&gt;rt_id&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="k"&gt;$(&lt;/span&gt;oci network subnet create --cidr-block &lt;span class="nv"&gt;$subnet_block&lt;/span&gt; --display-name kubernetes --compartment-id &lt;span class="nv"&gt;$compartment_id&lt;/span&gt; --vcn-id &lt;span class="nv"&gt;$vcn_id&lt;/span&gt; --query data.route-table-id --raw-output&lt;span class="k"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;After the 2nd command, we retrieve not the OCID of the subnet (we don&amp;rsquo;t need it), but that of the &amp;ldquo;Route Table&amp;rdquo;, a subcomponent of the subnet, which allows defining the routing table of the subnet we just created.&lt;/p&gt;
&lt;p&gt;Configure a gateway (Internet Gateway):&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;export&lt;/span&gt; &lt;span class="nv"&gt;ig_id&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="k"&gt;$(&lt;/span&gt;oci network internet-gateway create --compartment-id &lt;span class="nv"&gt;$compartment_id&lt;/span&gt; --is-enabled &lt;span class="nb"&gt;true&lt;/span&gt; --vcn-id &lt;span class="nv"&gt;$vcn_id&lt;/span&gt; --query data.id --raw-output&lt;span class="k"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Add a routing rule (to our route table) to allow Internet access:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;oci network route-table update --rt-id &lt;span class="nv"&gt;$rt_id&lt;/span&gt; --route-rules &lt;span class="s2"&gt;&amp;#34;[{\&amp;#34;cidrBlock\&amp;#34;:\&amp;#34;0.0.0.0/0\&amp;#34;,\&amp;#34;networkEntityId\&amp;#34;:\&amp;#34;&lt;/span&gt;&lt;span class="nv"&gt;$ig_id&lt;/span&gt;&lt;span class="s2"&gt;\&amp;#34;}]&amp;#34;&lt;/span&gt; --force
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Disable default firewall rules (YOLO):&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;export&lt;/span&gt; &lt;span class="nv"&gt;sl_id&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="k"&gt;$(&lt;/span&gt;oci network vcn list --compartment-id &lt;span class="nv"&gt;$compartment_id&lt;/span&gt; --query &lt;span class="s1"&gt;&amp;#39;data[0].&amp;#34;default-security-list-id&amp;#34;&amp;#39;&lt;/span&gt; --raw-output&lt;span class="k"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;From there, we have the functional network part, ready to host our machines!&lt;/p&gt;
&lt;h2 id="but-its-not-over-yet--"&gt;But It&amp;rsquo;s Not Over Yet :-/
&lt;/h2&gt;&lt;p&gt;With Oracle Cloud Infrastructure, it&amp;rsquo;s possible to boot a list of predefined OSes, but in our case, Talos Linux is not on the list.&lt;/p&gt;
&lt;p&gt;Fortunately, Omni will generate a preconfigured virtual disk with our credentials, which will allow us to enroll Talos Linux servers to our Omni SaaS from the first boot. Classy 😎.&lt;/p&gt;
&lt;p&gt;So we connect to our Omni interface and download the appropriate Talos Linux image:&lt;/p&gt;
&lt;p&gt;&lt;img src="https://blog.zwindler.fr/2025/01/omni_iso_generation.avif"
loading="lazy"
&gt;&lt;/p&gt;
&lt;p&gt;Here, I chose version 1.9.1 (the very latest because we like danger), for amd64 architecture. I retrieve the image &lt;code&gt;oracle-amd64-omni-zwindler-v1.9.1.qcow2.xz&lt;/code&gt; which I decompress:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;xz --decompress ./oracle-amd64-omni-zwindler-v1.9.1.qcow2.xz
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Reminder: OCI&amp;rsquo;s free tier consists of:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;2 &lt;strong&gt;amd64&lt;/strong&gt; machines with 1 oCPU (= vCPU) and 1 GB of RAM each&lt;/li&gt;
&lt;li&gt;a &lt;em&gt;flexible&lt;/em&gt; combination of &lt;strong&gt;arm64&lt;/strong&gt; instances having 1 x &lt;strong&gt;n&lt;/strong&gt; oCPU and 6 x &lt;strong&gt;n&lt;/strong&gt; GB, as long as the total doesn&amp;rsquo;t exceed 4 oCPU (and therefore 6x4 = 24 GB of RAM).&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;On OCI, there are several formats for importing disks. The simplest is to use OCI&amp;rsquo;s &amp;ldquo;homemade&amp;rdquo; format (the .oci, super original name), which consists of a metadata file and the QCOW2.&lt;/p&gt;
&lt;p&gt;Create the metadata file for import, with the &lt;strong&gt;VM.Standard.E2.1.Micro&lt;/strong&gt; shape since we have an amd64 image (otherwise it&amp;rsquo;s VM.Standard.A1.Flex):&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;cat &amp;gt; image_metadata.json &lt;span class="s"&gt;&amp;lt;&amp;lt; EOF
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt; &amp;#34;version&amp;#34;: 2,
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt; &amp;#34;externalLaunchOptions&amp;#34;: {
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt; &amp;#34;firmware&amp;#34;: &amp;#34;UEFI_64&amp;#34;,
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt; &amp;#34;networkType&amp;#34;: &amp;#34;PARAVIRTUALIZED&amp;#34;,
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt; &amp;#34;bootVolumeType&amp;#34;: &amp;#34;PARAVIRTUALIZED&amp;#34;,
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt; &amp;#34;remoteDataVolumeType&amp;#34;: &amp;#34;PARAVIRTUALIZED&amp;#34;,
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt; &amp;#34;localDataVolumeType&amp;#34;: &amp;#34;PARAVIRTUALIZED&amp;#34;,
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt; &amp;#34;launchOptionsSource&amp;#34;: &amp;#34;PARAVIRTUALIZED&amp;#34;,
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt; &amp;#34;pvAttachmentVersion&amp;#34;: 2,
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt; &amp;#34;pvEncryptionInTransitEnabled&amp;#34;: true,
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt; &amp;#34;consistentVolumeNamingEnabled&amp;#34;: true
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt; },
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt; &amp;#34;imageCapabilityData&amp;#34;: null,
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt; &amp;#34;imageCapsFormatVersion&amp;#34;: null,
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt; &amp;#34;operatingSystem&amp;#34;: &amp;#34;Talos&amp;#34;,
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt; &amp;#34;operatingSystemVersion&amp;#34;: &amp;#34;1.9.1&amp;#34;,
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt; &amp;#34;additionalMetadata&amp;#34;: {
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt; &amp;#34;shapeCompatibilities&amp;#34;: [
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt; &amp;#34;internalShapeName&amp;#34;: &amp;#34;VM.Standard.E2.1.Micro&amp;#34;,
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt; &amp;#34;ocpuConstraints&amp;#34;: null,
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt; &amp;#34;memoryConstraints&amp;#34;: null
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt; ]
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt;EOF&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;And then create the image for import:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;qemu-img convert -f raw -O qcow2 oracle-amd64-omni-zwindler-v1.9.1.raw oracle-amd64-omni-zwindler-v1.9.1.qcow2
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;tar zcf oracle-amd64-omni-zwindler-v1.9.1.oci oracle-amd64-omni-zwindler-v1.9.1.qcow2 image_metadata.json
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="importing-the-image-to-oracle-cloud"&gt;Importing the Image to Oracle Cloud
&lt;/h2&gt;&lt;p&gt;We have the file ready to be uploaded&amp;hellip; but where do we upload it??&lt;/p&gt;
&lt;p&gt;Unfortunately, this step is done in 2 parts. First, you need to upload the .oci file to a bucket. It&amp;rsquo;s quite simple to do in the UI (we could also do it via CLI):&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Create a bucket in the Storage section to upload the compressed image.&lt;/li&gt;
&lt;li&gt;Upload the image (oracle-amd64-omni-zwindler-v1.9.1.oci) to this bucket.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;img src="https://blog.zwindler.fr/2025/01/bucket.avif"
loading="lazy"
&gt;&lt;/p&gt;
&lt;p&gt;Second step, we transform the file into &amp;ldquo;Custom images&amp;rdquo; (in the &lt;strong&gt;Compute&lt;/strong&gt; section):&lt;/p&gt;
&lt;p&gt;&lt;img src="https://blog.zwindler.fr/2025/01/custom-images.avif"
loading="lazy"
&gt;&lt;/p&gt;
&lt;p&gt;This step is oddly quite long, the image which is only 100 MB took 10 minutes each time I tried so far.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://blog.zwindler.fr/2025/01/custom-images-2.avif"
loading="lazy"
&gt;&lt;/p&gt;
&lt;h2 id="creating-the-vm"&gt;Creating the VM
&lt;/h2&gt;&lt;p&gt;Once the image is imported, we can now use our Omni-customized image to boot our free tier machines.&lt;/p&gt;
&lt;p&gt;I also did this through the OCI interface, but again, we could do it via CLI.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://blog.zwindler.fr/2025/01/vm1.avif"
loading="lazy"
&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src="https://blog.zwindler.fr/2025/01/vm2.avif"
loading="lazy"
&gt;&lt;/p&gt;
&lt;p&gt;A few seconds after boot, it appears in Omni&amp;rsquo;s UI and can be added to a cluster.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://blog.zwindler.fr/2025/01/omni-oracle.avif"
loading="lazy"
&gt;&lt;/p&gt;
&lt;p&gt;Have fun!!&lt;/p&gt;
&lt;h2 id="addendum-is-it-really-free"&gt;Addendum: Is It Really Free?
&lt;/h2&gt;&lt;p&gt;Yes&amp;hellip;-ish.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;In theory&lt;/strong&gt;, the machines are free (forever free as they say). But beware, lots of little things can be paid.&lt;/p&gt;
&lt;p&gt;For example, the bucket where we uploaded the QCOW2/.oci is most likely paid. Same for the custom image, which is billed as 1 GB of storage (according to the UI, I don&amp;rsquo;t have the bill yet LOL).&lt;/p&gt;
&lt;p&gt;If you put the VMs behind a load balancer (there&amp;rsquo;s no reason you&amp;rsquo;d do that here), be careful, only the &amp;ldquo;non-flexible&amp;rdquo; LB capped at 10 Mbps is free (and only one).&lt;/p&gt;
&lt;p&gt;And if like me, you already have 4 x 50 GB disks, the OS storage is paid (€1.85 / month).&lt;/p&gt;
&lt;p&gt;In short, as you&amp;rsquo;ve understood, it&amp;rsquo;s like often in the cloud, nothing is really free and you have to read all the fine print.&lt;/p&gt;</description></item></channel></rss>