<?xml version="1.0" encoding="UTF-8"?><rss version="2.0" xmlns:content="http://purl.org/rss/1.0/modules/content/"><channel><title>ExCloudVault.com | Engineering Blog</title><description>Showcase and Knowledge Base for building an enterprise-grade self-hosted private cloud with ExCloudVault.com.</description><link>https://excloudvault.mbabros.com/</link><language>en</language><item><title>Automating Caddy Reverse Proxy Deployments with GitHub Actions</title><link>https://excloudvault.mbabros.com/blog/caddy-gitops-automation/</link><guid isPermaLink="true">https://excloudvault.mbabros.com/blog/caddy-gitops-automation/</guid><description>How we achieve zero-downtime Caddy configuration updates using automated syntax validation, unit testing, and SSH GitOps deployment pipelines.

</description><pubDate>Sun, 08 Nov 2026 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;One of the most dangerous anti-patterns in self-hosting is editing live reverse proxy configurations directly on production hosts via SSH. A single misplaced bracket or invalid directive can take down all subdomains simultaneously.&lt;/p&gt;
&lt;p&gt;To prevent outages, the &lt;strong&gt;ExCloudVault.com&lt;/strong&gt; private cloud enforces a strict GitOps deployment model for Caddy using &lt;strong&gt;GitHub Actions&lt;/strong&gt;.&lt;/p&gt;
&lt;hr&gt;
&lt;div&gt;&lt;h2 id=&quot;the-gitops-workflow-lifecycle&quot;&gt;The GitOps Workflow Lifecycle&lt;/h2&gt;&lt;/div&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;sequenceDiagram&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;autonumber&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;actor Dev as Engineer&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;participant GH as GitHub Repository (mbabros/homelab)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;participant Runner as GitHub Actions CI&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;participant OCI as OCI Caddy Gateway&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;Dev-&gt;&gt;GH: git push (Changes to Caddyfile)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;GH-&gt;&gt;Runner: Trigger CI/CD Pipeline&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;Note over Runner: Step 1: Caddy Syntax Validation (caddy validate)&amp;#x3C;br/&gt;Step 2: Security Linting &amp;#x26; Policy Check&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;alt Validation Fails&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span&gt;Runner--&gt;&gt;Dev: Pipeline Failed ❌ (Deployment aborted)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;else Validation Passes&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span&gt;Runner-&gt;&gt;OCI: SSH Deploy (rsync Caddyfile &amp;#x26; trigger reload)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span&gt;OCI-&gt;&gt;OCI: caddy reload --config /etc/caddy/Caddyfile&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span&gt;OCI--&gt;&gt;Runner: Reload Successful (HTTP 200 OK)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span&gt;Runner--&gt;&gt;Dev: Deployment Successful ✅ (Zero downtime)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;end&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div aria-live=&quot;polite&quot;&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;hr&gt;
&lt;div&gt;&lt;h2 id=&quot;1-automated-syntax-validation-in-ci&quot;&gt;1. Automated Syntax Validation in CI&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;Before any Caddyfile change reaches production, GitHub Actions validates the syntax using the official Caddy Docker image:&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;name&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;Validate Caddyfile&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;on&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;pull_request&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;paths&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;      &lt;/span&gt;&lt;/span&gt;&lt;span&gt;- &lt;/span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;span&gt;Caddyfile&lt;/span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;push&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;branches&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;      &lt;/span&gt;&lt;/span&gt;&lt;span&gt;- &lt;/span&gt;&lt;span&gt;main&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;paths&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;      &lt;/span&gt;&lt;/span&gt;&lt;span&gt;- &lt;/span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;span&gt;Caddyfile&lt;/span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;jobs&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;validate&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;name&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;Lint &amp;#x26; Validate Syntax&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;runs-on&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;ubuntu-latest&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;steps&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;      &lt;/span&gt;&lt;/span&gt;&lt;span&gt;- &lt;/span&gt;&lt;span&gt;name&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;Checkout Code&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;uses&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;actions/checkout@v4&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;      &lt;/span&gt;&lt;/span&gt;&lt;span&gt;- &lt;/span&gt;&lt;span&gt;name&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;Validate Caddyfile Syntax&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;run&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;|&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;          &lt;/span&gt;&lt;/span&gt;&lt;span&gt;docker run --rm -v $(pwd)/Caddyfile:/etc/caddy/Caddyfile:ro \&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;            &lt;/span&gt;&lt;/span&gt;&lt;span&gt;caddy:2-alpine caddy validate --config /etc/caddy/Caddyfile&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div aria-live=&quot;polite&quot;&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;If a typo or syntax error exists, the pipeline halts immediately, preventing broken configurations from ever being deployed.&lt;/p&gt;
&lt;hr&gt;
&lt;div&gt;&lt;h2 id=&quot;2-zero-downtime-hot-reloading&quot;&gt;2. Zero-Downtime Hot Reloading&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;Unlike Nginx, which often requires process restarts or complex signal handling, Caddy features a native API and CLI command for dynamic, zero-downtime configuration reloads:&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span&gt;&lt;/span&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;docker&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;exec&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;caddy&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;caddy&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;reload&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;--config&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;/etc/caddy/Caddyfile&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div aria-live=&quot;polite&quot;&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;Caddy parses the new configuration in memory. If valid, it hot-swaps active listener sockets without dropping in-flight TCP connections or terminating active WebSocket sessions. If the new config contains an operational error, Caddy rolls back immediately to the previous running configuration in memory.&lt;/p&gt;
&lt;hr&gt;
&lt;div&gt;&lt;h2 id=&quot;3-production-deployment-step&quot;&gt;3. Production Deployment Step&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;Once the syntax is verified, the deployment job connects to the OCI gateway via SSH (using GitHub Secrets for private keys):&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;deploy&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;name&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;Deploy to Edge Gateway&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;needs&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;validate&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;if&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;github.ref == &apos;refs/heads/main&apos;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;runs-on&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;self-hosted&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;# Or ubuntu-latest with Tailscale action&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;steps&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;      &lt;/span&gt;&lt;/span&gt;&lt;span&gt;- &lt;/span&gt;&lt;span&gt;name&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;Checkout Code&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;uses&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;actions/checkout@v4&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;      &lt;/span&gt;&lt;/span&gt;&lt;span&gt;- &lt;/span&gt;&lt;span&gt;name&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;Sync Caddyfile &amp;#x26; Reload&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;env&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;          &lt;/span&gt;&lt;span&gt;SSH_KEY&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;${{ secrets.OCI_SSH_KEY }}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;          &lt;/span&gt;&lt;span&gt;HOST&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;${{ secrets.OCI_HOST }}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;run&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;|&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;          &lt;/span&gt;&lt;/span&gt;&lt;span&gt;echo &quot;$SSH_KEY&quot; &gt; key.pem &amp;#x26;&amp;#x26; chmod 600 key.pem&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;          &lt;/span&gt;&lt;/span&gt;&lt;span&gt;scp -i key.pem Caddyfile ubuntu@$HOST:/opt/caddy/Caddyfile&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;          &lt;/span&gt;&lt;/span&gt;&lt;span&gt;ssh -i key.pem ubuntu@$HOST &quot;docker exec caddy caddy reload --config /etc/caddy/Caddyfile&quot;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;          &lt;/span&gt;&lt;/span&gt;&lt;span&gt;rm -f key.pem&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div aria-live=&quot;polite&quot;&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;hr&gt;
&lt;div&gt;&lt;h2 id=&quot;summary&quot;&gt;Summary&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;With automated syntax checking, zero-downtime hot reloading, and GitOps versioning, our team can add new services or modify routing rules with complete confidence. Every change is peer-reviewed in pull requests, and production remains reliable and resilient.&lt;/p&gt;</content:encoded><category>gitops</category><category>caddy</category><category>github-actions</category><category>ci-cd</category><category>devops</category></item><item><title>Building an Enterprise-Grade Zero-Trust Private Cloud</title><link>https://excloudvault.mbabros.com/blog/building-a-hardened-hybrid-cloud/</link><guid isPermaLink="true">https://excloudvault.mbabros.com/blog/building-a-hardened-hybrid-cloud/</guid><description>How we built a whisper-quiet, zero-port self-hosted cloud combining Oracle Cloud Infrastructure, Caddy, Tailscale, Apple Silicon, and Coolify.

</description><pubDate>Sat, 07 Nov 2026 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;For years, self-hosting at home came with unavoidable compromises: noisy enterprise server racks, surging electric bills, fragile dynamic DNS scripts, and the inherent security risks of opening ports on your home router.&lt;/p&gt;
&lt;p&gt;Today, modern networking and virtualization primitives have completely reshaped the self-hosting landscape. In this post, we explain how we designed and deployed &lt;strong&gt;ExCloudVault.com&lt;/strong&gt;—a zero-trust, high-density private cloud infrastructure running on an Apple Silicon Mac mini and an Oracle Cloud Always-Free edge gateway.&lt;/p&gt;
&lt;hr&gt;
&lt;div&gt;&lt;h2 id=&quot;the-core-design-requirements&quot;&gt;The Core Design Requirements&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;When we set out to re-architect our private cloud, we established non-negotiable architectural requirements:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Zero Open Ports at Home:&lt;/strong&gt; No port forwarding on the residential NAT router. Immunity to port scanning, brute-force bots, and ISP CGNAT limitations.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Instant Wildcard SSL:&lt;/strong&gt; Automated Let’s Encrypt certificates for &lt;code dir=&quot;auto&quot;&gt;*.mbabros.com&lt;/code&gt; without relying on HTTP port 80 domain validation.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;HTTP/3 (QUIC) Acceleration:&lt;/strong&gt; Accelerated page loading and WebSocket reliability over UDP.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Low Power Consumption:&lt;/strong&gt; Sub-20W average power draw to maintain whisper-quiet operation and negligible electricity cost.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;100% Codified GitOps:&lt;/strong&gt; Zero manual configuration drifts. All Caddy routing rules, firewall tables, and Docker stacks version-controlled in Git.&lt;/li&gt;
&lt;/ol&gt;
&lt;hr&gt;
&lt;div&gt;&lt;h2 id=&quot;the-architecture-at-a-glance&quot;&gt;The Architecture at a Glance&lt;/h2&gt;&lt;/div&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;flowchart LR&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;Client[&quot;Client Browser&quot;] --&gt;|&quot;HTTPS / QUIC&quot;| OCI[&quot;Oracle Cloud Gateway&amp;#x3C;br/&gt;(Caddy + Cloudflare DNS-01)&quot;]&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;OCI --&gt;|&quot;Tailscale WireGuard Mesh&amp;#x3C;br/&gt;(Encrypted 100.x.y.z Tunnel)&quot;| MacMini[&quot;Mac mini Node&amp;#x3C;br/&gt;(OrbStack + Coolify PaaS)&quot;]&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;MacMini --&gt; Apps[&quot;Nextcloud · Shlink · Immich · Paperless&quot;]&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div aria-live=&quot;polite&quot;&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;div&gt;&lt;h3 id=&quot;1-the-cloud-ingress-edge-oracle-cloud--caddy&quot;&gt;1. The Cloud Ingress Edge: Oracle Cloud + Caddy&lt;/h3&gt;&lt;/div&gt;
&lt;p&gt;Rather than exposing our home IP, we provisioned an &lt;strong&gt;OCI Always Free ARM Ampere A1&lt;/strong&gt; instance. With 4 OCPUs and 24GB of RAM permanently free of charge, it acts as an unyielding cloud bastion.&lt;/p&gt;
&lt;p&gt;On this VM, we run &lt;strong&gt;Caddy&lt;/strong&gt; compiled with the Cloudflare DNS module (&lt;code dir=&quot;auto&quot;&gt;caddy-dns/cloudflare&lt;/code&gt;). Caddy interacts directly with Cloudflare’s API to solve DNS-01 ACME challenges, issuing Let’s Encrypt wildcard certificates (&lt;code dir=&quot;auto&quot;&gt;*.mbabros.com&lt;/code&gt;) seamlessly in the background.&lt;/p&gt;
&lt;div&gt;&lt;h3 id=&quot;2-the-private-mesh-tailscale-wireguard&quot;&gt;2. The Private Mesh: Tailscale WireGuard&lt;/h3&gt;&lt;/div&gt;
&lt;p&gt;To bridge the OCI gateway to the Mac mini in our home office, we use &lt;strong&gt;Tailscale&lt;/strong&gt;. Tailscale creates an encrypted point-to-point WireGuard mesh. Traffic never touches an unauthenticated public interface. The Mac mini establishes an outbound UDP connection; no inbound ports are opened on the router.&lt;/p&gt;
&lt;div&gt;&lt;h3 id=&quot;3-the-powerhouse-mac-mini-m2--coolify-paas&quot;&gt;3. The Powerhouse: Mac mini M2 &amp;#x26; Coolify PaaS&lt;/h3&gt;&lt;/div&gt;
&lt;p&gt;At the center of our home network sits an Apple Silicon Mac mini running &lt;strong&gt;OrbStack&lt;/strong&gt;. With ultra-low memory overhead and instant container boot times, it hosts &lt;strong&gt;Coolify&lt;/strong&gt;, our self-hosted PaaS controller.&lt;/p&gt;
&lt;p&gt;Coolify orchestrates our application inventory—Nextcloud, Microbin, Immich, Karakeep, and Paperless-ngx—while handling database provisioning, environment variables, and daily encrypted S3 backups.&lt;/p&gt;
&lt;hr&gt;
&lt;div&gt;&lt;h2 id=&quot;lessons-learned--key-takeaways&quot;&gt;Lessons Learned &amp;#x26; Key Takeaways&lt;/h2&gt;&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Wildcard DNS-01 is a Game Changer:&lt;/strong&gt; Managing per-container SSL certificates inside your local network is complex and error-prone. By terminating wildcard TLS once at the cloud edge, internal apps can operate over secure HTTP within the WireGuard mesh.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Apple Silicon is the Future of Homelabs:&lt;/strong&gt; Replacing bulky x86 server hardware with an M-series Mac mini reduced our idle power consumption from 180 Watts to under 7 Watts, with zero fan noise.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;In our next article, we will dive deep into how we automate Caddy testing and deployments using GitHub Actions!&lt;/p&gt;</content:encoded><category>homelab</category><category>architecture</category><category>caddy</category><category>tailscale</category><category>security</category></item></channel></rss>