<?xml version="1.0" encoding="UTF-8"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
    <title>Alek&#x27;s Blog - go</title>
    <subtitle>Production notes on Kubernetes, OpenShift, and OVHcloud: observability, log archiving, service mesh, LLM inference, and digital sovereignty.</subtitle>
    <link rel="self" type="application/atom+xml" href="https://blog.none.at/tags/go/atom.xml"/>
    <link rel="alternate" type="text/html" href="https://blog.none.at"/>
    <generator uri="https://www.getzola.org/">Zola</generator>
    <updated>2026-06-27T00:00:00+00:00</updated>
    <id>https://blog.none.at/tags/go/atom.xml</id>
    <entry xml:lang="en">
        <title>ClickHouse Use Case: Vector, Istio, nginx, Java on OVH MKS</title>
        <published>2026-05-14T00:00:00+00:00</published>
        <updated>2026-06-27T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              aleks
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://blog.none.at/blog/2026/2026-05-14-es-os-loki-quickwit-clickhouse-usecases/"/>
        <id>https://blog.none.at/blog/2026/2026-05-14-es-os-loki-quickwit-clickhouse-usecases/</id>
        
        <summary type="html">&lt;p&gt;The first four parts of this series compared Elasticsearch, OpenSearch, Loki, Quickwit, and
ClickHouse across storage models, operations, security, and UX. This part shows what a
concrete production setup looks like when the decision has been made: &lt;strong&gt;ClickHouse&lt;&#x2F;strong&gt; as the
log store, &lt;strong&gt;Vector&lt;&#x2F;strong&gt; as the ingestion agent, running on &lt;strong&gt;OVH Managed Kubernetes Service
(MKS)&lt;&#x2F;strong&gt; with &lt;strong&gt;OVH Object Storage&lt;&#x2F;strong&gt; as the cold tier.&lt;&#x2F;p&gt;
&lt;p&gt;This is Part 5 of a five-part series:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Full guide:&lt;&#x2F;strong&gt; &lt;a href=&quot;https:&#x2F;&#x2F;blog.none.at&#x2F;blog&#x2F;2026&#x2F;2026-05-14-es-os-loki-quickwit-clickhouse-guide&#x2F;&quot;&gt;Elasticsearch vs. OpenSearch vs. Loki vs. Quickwit vs. ClickHouse: The Complete Guide&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;blog.none.at&#x2F;blog&#x2F;2026&#x2F;2026-05-14-es-os-loki-quickwit-clickhouse&#x2F;&quot;&gt;Part 1&lt;&#x2F;a&gt; — storage models, compression, resource consumption, and SaaS options&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;blog.none.at&#x2F;blog&#x2F;2026&#x2F;2026-05-14-es-os-loki-quickwit-clickhouse-operations&#x2F;&quot;&gt;Part 2&lt;&#x2F;a&gt; — cluster setup, Kubernetes operations, backup and disaster recovery&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;blog.none.at&#x2F;blog&#x2F;2026&#x2F;2026-05-14-es-os-loki-quickwit-clickhouse-security&#x2F;&quot;&gt;Part 3&lt;&#x2F;a&gt; — encryption, RBAC, and WORM compliance&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;blog.none.at&#x2F;blog&#x2F;2026&#x2F;2026-05-14-es-os-loki-quickwit-clickhouse-ux&#x2F;&quot;&gt;Part 4&lt;&#x2F;a&gt; — UI layers, dashboards, alerting, and cold-tier query behaviour&lt;&#x2F;li&gt;
&lt;li&gt;Part 5 — this post&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;</summary>
        
    </entry>
    <entry xml:lang="en">
        <title>cert-manager-webhook-libdns: One Webhook, Many DNS Providers</title>
        <published>2026-03-03T00:00:00+00:00</published>
        <updated>2026-03-03T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              aleks
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://blog.none.at/blog/2026/2026-03-03-cert-manager-webhook-libdns/"/>
        <id>https://blog.none.at/blog/2026/2026-03-03-cert-manager-webhook-libdns/</id>
        
        <content type="html" xml:base="https://blog.none.at/blog/2026/2026-03-03-cert-manager-webhook-libdns/">&lt;h1 id=&quot;cert-manager-webhook-libdns-one-webhook-many-dns-providers&quot;&gt;cert-manager-webhook-libdns: One Webhook, Many DNS Providers&lt;a class=&quot;zola-anchor&quot; href=&quot;#cert-manager-webhook-libdns-one-webhook-many-dns-providers&quot; aria-label=&quot;Anchor link for: cert-manager-webhook-libdns-one-webhook-many-dns-providers&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h1&gt;
&lt;p&gt;Managing DNS-01 challenges with cert-manager often means choosing one provider-specific integration and staying tightly coupled to it.
&lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;git001&#x2F;cert-manager-webhook-libdns&quot;&gt;cert-manager-webhook-libdns&lt;&#x2F;a&gt; takes a different approach: it uses the &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;libdns&#x2F;libdns&quot;&gt;libdns&lt;&#x2F;a&gt; ecosystem so one webhook can support many DNS providers through a shared interface.&lt;&#x2F;p&gt;
&lt;p&gt;If you run mixed infrastructure, migrate between DNS vendors, or just want a cleaner operational model, this project is built for that.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;why-this-project-exists&quot;&gt;Why this project exists&lt;a class=&quot;zola-anchor&quot; href=&quot;#why-this-project-exists&quot; aria-label=&quot;Anchor link for: why-this-project-exists&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;In many Kubernetes setups, certificate automation becomes harder than it should be because DNS integrations are fragmented:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Every provider has different APIs, credentials, and operational quirks.&lt;&#x2F;li&gt;
&lt;li&gt;Switching providers often means switching tooling.&lt;&#x2F;li&gt;
&lt;li&gt;Testing and maintenance can become provider-specific and brittle.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;&lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;git001&#x2F;cert-manager-webhook-libdns&quot;&gt;cert-manager-webhook-libdns&lt;&#x2F;a&gt; solves this by exposing a single cert-manager webhook that delegates DNS record operations to pluggable libdns providers.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;what-it-does&quot;&gt;What it does&lt;a class=&quot;zola-anchor&quot; href=&quot;#what-it-does&quot; aria-label=&quot;Anchor link for: what-it-does&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;At a high level, the webhook:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Receives DNS-01 challenge requests from cert-manager.&lt;&#x2F;li&gt;
&lt;li&gt;Loads provider credentials from Kubernetes Secrets.&lt;&#x2F;li&gt;
&lt;li&gt;Resolves and writes challenge TXT records through the selected libdns provider.&lt;&#x2F;li&gt;
&lt;li&gt;Cleans up records after validation.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;It supports important real-world behaviors, including:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Handling multiple TXT values for wildcard + apex certificate requests.&lt;&#x2F;li&gt;
&lt;li&gt;Safer fallback logic when record listing fails.&lt;&#x2F;li&gt;
&lt;li&gt;Provider-specific TTL handling (for example, deSEC minimum TTL enforcement).&lt;&#x2F;li&gt;
&lt;li&gt;Deterministic provider listing in CLI output.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h2 id=&quot;operational-improvements-in-recent-iterations&quot;&gt;Operational improvements in recent iterations&lt;a class=&quot;zola-anchor&quot; href=&quot;#operational-improvements-in-recent-iterations&quot; aria-label=&quot;Anchor link for: operational-improvements-in-recent-iterations&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;Several practical improvements were added to make this project easier to run and maintain:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Semantic version output via &lt;code&gt;--version&lt;&#x2F;code&gt; (currently &lt;code&gt;v0.5.0&lt;&#x2F;code&gt;).&lt;&#x2F;li&gt;
&lt;li&gt;No etcd&#x2F;envtest dependency in the default &lt;code&gt;make test&lt;&#x2F;code&gt; path.&lt;&#x2F;li&gt;
&lt;li&gt;Cleaner container workflow with &lt;code&gt;Containerfile&lt;&#x2F;code&gt; support.&lt;&#x2F;li&gt;
&lt;li&gt;Release workflow hardening:&lt;&#x2F;li&gt;
&lt;li&gt;tests run before image release&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;latest&lt;&#x2F;code&gt; is only published for stable tags&lt;&#x2F;li&gt;
&lt;li&gt;release creation happens after successful image push&lt;&#x2F;li&gt;
&lt;li&gt;concurrency guard to prevent overlapping tag releases&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;These are the kinds of changes that reduce surprises in CI&#x2F;CD and day-to-day operations.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;provider-compatibility-is-now-automated&quot;&gt;Provider compatibility is now automated&lt;a class=&quot;zola-anchor&quot; href=&quot;#provider-compatibility-is-now-automated&quot; aria-label=&quot;Anchor link for: provider-compatibility-is-now-automated&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;A major maintenance challenge with libdns-based projects is knowing which upstream provider modules are actually compatible with your pinned &lt;code&gt;libdns&lt;&#x2F;code&gt; version.&lt;&#x2F;p&gt;
&lt;p&gt;This repository now includes an automated compatibility process:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Script: &lt;code&gt;scripts&#x2F;check_libdns_provider_compat.sh&lt;&#x2F;code&gt;&lt;&#x2F;li&gt;
&lt;li&gt;Workflow: &lt;code&gt;.github&#x2F;workflows&#x2F;libdns-provider-compat.yml&lt;&#x2F;code&gt;&lt;&#x2F;li&gt;
&lt;li&gt;Report snapshot: &lt;code&gt;docs&#x2F;01_provider-compat-latest.md&lt;&#x2F;code&gt;&lt;&#x2F;li&gt;
&lt;li&gt;Historical snapshots: &lt;code&gt;docs&#x2F;YYYY-MM-DD_provider-compat.md&lt;&#x2F;code&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;The check uses &lt;code&gt;gh api&lt;&#x2F;code&gt; to scan provider repositories, inspect their &lt;code&gt;go.mod&lt;&#x2F;code&gt;, and classify compatibility against the libdns version used in this project.&lt;&#x2F;p&gt;
&lt;p&gt;That gives maintainers a repeatable compatibility signal instead of manual guesswork.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;quick-start&quot;&gt;Quick start&lt;a class=&quot;zola-anchor&quot; href=&quot;#quick-start&quot; aria-label=&quot;Anchor link for: quick-start&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;h3 id=&quot;1-build-and-publish-the-image&quot;&gt;1. Build and publish the image&lt;a class=&quot;zola-anchor&quot; href=&quot;#1-build-and-publish-the-image&quot; aria-label=&quot;Anchor link for: 1-build-and-publish-the-image&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;Use your preferred container runtime (Podman is preferred, Docker fallback is supported):&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;make&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; container-build&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;make&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; container-push&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; IMAGE_TAG=v0.5.0&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; REGISTRY=ghcr.io&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;your-or&lt;&#x2F;span&gt;&lt;span&gt;g&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h3 id=&quot;2-deploy-the-helm-chart&quot;&gt;2. Deploy the Helm chart&lt;a class=&quot;zola-anchor&quot; href=&quot;#2-deploy-the-helm-chart&quot; aria-label=&quot;Anchor link for: 2-deploy-the-helm-chart&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;helm&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; install&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; libdns-webhook&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; .&#x2F;deploy&#x2F;libdns-webhook&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-character&quot;&gt; \&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-constant z-constant z-other&quot;&gt;  -&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-constant z-other&quot;&gt;-namespace&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; cert-manager&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-character&quot;&gt; \&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-constant z-constant z-other&quot;&gt;  -&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-constant z-other&quot;&gt;-set&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; image.repository=ghcr.io&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;your-or&lt;&#x2F;span&gt;&lt;span&gt;g&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&#x2F;cert-manager-webhook-libdns&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-character&quot;&gt; \&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-constant z-constant z-other&quot;&gt;  -&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-constant z-other&quot;&gt;-set&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; image.tag=v0.5.0&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-character&quot;&gt; \&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-constant z-constant z-other&quot;&gt;  -&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-constant z-other&quot;&gt;-set&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; groupName=acme.yourdomain.com&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h3 id=&quot;3-create-provider-credentials-secret&quot;&gt;3. Create provider credentials secret&lt;a class=&quot;zola-anchor&quot; href=&quot;#3-create-provider-credentials-secret&quot; aria-label=&quot;Anchor link for: 3-create-provider-credentials-secret&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;Example for token-based providers:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;yaml&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;a&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;piVersion&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; v&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;1&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;k&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;ind&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; S&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;ecret&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;m&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;etadata&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator&quot;&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;  n&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;ame&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; d&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;ns-provider-credentials&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;  n&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;amespace&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; c&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;ert-manager&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;t&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;ype&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; O&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;paque&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;s&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;tringData&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator&quot;&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;  a&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;pi_token&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;lt;YOUR_API_TOKEN&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h3 id=&quot;4-configure-clusterissuer&quot;&gt;4. Configure ClusterIssuer&lt;a class=&quot;zola-anchor&quot; href=&quot;#4-configure-clusterissuer&quot; aria-label=&quot;Anchor link for: 4-configure-clusterissuer&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;yaml&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;a&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;piVersion&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; c&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;ert-manager.io&#x2F;v1&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;k&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;ind&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; C&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;lusterIssuer&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;m&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;etadata&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator&quot;&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;  n&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;ame&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; l&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;etsencrypt-prod&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;s&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;pec&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator&quot;&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;  a&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;cme&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator&quot;&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;    s&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;erver&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; h&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;ttps:&#x2F;&#x2F;acme-v02.api.letsencrypt.org&#x2F;directory&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;    e&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;mail&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; y&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;our-email@example.com&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;    p&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;rivateKeySecretRef&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator&quot;&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;      n&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;ame&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; l&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;etsencrypt-prod-account&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;    s&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;olvers&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator&quot;&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      -&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt; d&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;ns01&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator&quot;&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;          w&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;ebhook&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator&quot;&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;            g&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;roupName&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; a&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;cme.yourdomain.com&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;            s&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;olverName&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; l&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;ibdns&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;            c&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;onfig&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator&quot;&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;              p&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;rovider&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; c&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;loudflare&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;              s&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;ecretRef&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator&quot;&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;                n&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;ame&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; d&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;ns-provider-credentials&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;                n&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;amespace&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; c&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;ert-manager&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h2 id=&quot;useful-cli-checks&quot;&gt;Useful CLI checks&lt;a class=&quot;zola-anchor&quot; href=&quot;#useful-cli-checks&quot; aria-label=&quot;Anchor link for: useful-cli-checks&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;Before deployment, you can quickly inspect the binary:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;.&#x2F;webhook&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-constant z-other&quot;&gt; -&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-constant z-other&quot;&gt;-version&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;.&#x2F;webhook&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-constant z-other&quot;&gt; -&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-constant z-other&quot;&gt;-list-providers&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This is helpful for validating exactly what was compiled into your image.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;who-should-use-this&quot;&gt;Who should use this&lt;a class=&quot;zola-anchor&quot; href=&quot;#who-should-use-this&quot; aria-label=&quot;Anchor link for: who-should-use-this&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;This project is a strong fit if you:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Run cert-manager and use DNS-01 challenges.&lt;&#x2F;li&gt;
&lt;li&gt;Need flexibility across multiple DNS providers.&lt;&#x2F;li&gt;
&lt;li&gt;Want one consistent webhook integration instead of many provider-specific implementations.&lt;&#x2F;li&gt;
&lt;li&gt;Care about release discipline and compatibility visibility.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h2 id=&quot;final-thoughts&quot;&gt;Final thoughts&lt;a class=&quot;zola-anchor&quot; href=&quot;#final-thoughts&quot; aria-label=&quot;Anchor link for: final-thoughts&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;&lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;git001&#x2F;cert-manager-webhook-libdns&quot;&gt;cert-manager-webhook-libdns&lt;&#x2F;a&gt; is not just a DNS integration layer. It is an operational strategy: keep cert-manager integration stable while letting providers vary underneath.&lt;&#x2F;p&gt;
&lt;p&gt;If your platform team wants fewer moving parts and more predictable certificate automation, this is a practical approach worth adopting.&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Building a native file upload handler for Caddy v2</title>
        <published>2022-03-01T00:00:00+00:00</published>
        <updated>2026-03-04T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              aleks
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://blog.none.at/blog/2022/2022-03-01-caddy-upload/"/>
        <id>https://blog.none.at/blog/2022/2022-03-01-caddy-upload/</id>
        
        <content type="html" xml:base="https://blog.none.at/blog/2022/2022-03-01-caddy-upload/">&lt;p&gt;When &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;caddyserver&#x2F;caddy&#x2F;releases&#x2F;tag&#x2F;v2.0.0&quot;&gt;Caddy v2&lt;&#x2F;a&gt; was released in 2020, it introduced a new concept of handlers that use Go’s native module features.&lt;&#x2F;p&gt;
&lt;p&gt;In 2022 one of our customers needed to upload files, and at that time none of the available web servers could handle this natively without an extra program. So I decided to create a new handler for Caddy v2 — &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;git001&#x2F;caddyv2-upload&quot;&gt;caddyv2-upload&lt;&#x2F;a&gt; was born.&lt;&#x2F;p&gt;
&lt;p&gt;I was not aware of any other tool which can handle file uploads natively in just one binary which can be used in Kubernetes or OpenShift, or I have not searched hard enough 😁. I also wanted to learn go, so I decided to create a new handler for the go based webserver &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;caddyserver.com&#x2F;&quot;&gt;caddyserver&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;In May 2022 &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;sigoden&#x2F;dufs&quot;&gt;dufs&lt;&#x2F;a&gt;, a Rust-based server, was created — so that might be another option worth considering. 🤷&lt;&#x2F;p&gt;
&lt;p&gt;Any how I wanted to learn go in the pre AI Area and at that time I looked into the docs of go modules, into the source of caddy servers own handlers and created step by step a new handler.&lt;&#x2F;p&gt;
&lt;p&gt;Luckily there was already podman and buildah, so I was able to create container images to run and test locally.&lt;&#x2F;p&gt;
&lt;p&gt;Building something real turned out to be the most effective way to learn Go. Diving into Caddy’s own handler source code, understanding the module system, and iterating with containers made the concepts stick far better than any tutorial would have.&lt;&#x2F;p&gt;
&lt;p&gt;A minimal Caddyfile configuration looks like this:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;{&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    order upload before file_server&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;:2015 {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    root .&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    file_server browse&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    @mypost method POST&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    upload @mypost {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        dest_dir &#x2F;var&#x2F;uploads&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        max_filesize 4MB&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Build with &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;caddyserver&#x2F;xcaddy&quot;&gt;xcaddy&lt;&#x2F;a&gt;:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;xcaddy&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; build&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-constant z-other&quot;&gt; -&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-constant z-other&quot;&gt;-with&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; github.com&#x2F;git001&#x2F;caddyv2-upload&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Today &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;git001&#x2F;caddyv2-upload&quot;&gt;caddyv2-upload&lt;&#x2F;a&gt; (v0.20.0) supports file uploads via HTTP multipart form, configurable destination directories, UUID-based subdirectory creation per upload, fixed filenames, pass-through mode to continue to the next Caddy handler after upload, configurable file size limits, an HTTP notification callback after successful uploads, and a &lt;code&gt;&#x2F;health&lt;&#x2F;code&gt; endpoint. It integrates with Caddy’s variable system and works in Kubernetes and OpenShift environments. Authentication is handled by Caddy’s own security layer rather than the module itself.&lt;&#x2F;p&gt;
</content>
        
    </entry>
</feed>
