<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[LapseZero]]></title><description><![CDATA[LapseZero]]></description><link>https://lapsezero.hashnode.dev</link><generator>RSS for Node</generator><lastBuildDate>Mon, 02 Nov 2026 05:48:02 GMT</lastBuildDate><atom:link href="https://lapsezero.hashnode.dev/rss.xml" rel="self" type="application/rss+xml"/><language><![CDATA[en]]></language><ttl>60</ttl><item><title><![CDATA[Still Renewing Tomcat and Spring Boot Certificates by Hand? How to Automate Renewal and Deployment]]></title><description><![CDATA[Automate Java SSL renewal: generate PKCS12 keystores, handle alias and password errors, and verify HTTPS after a Tomcat or Spring Boot restart.]]></description><link>https://lapsezero.hashnode.dev/still-renewing-tomcat-and-spring-boot-certificates-by-hand-how-to-automate-renewal-and-deployment</link><guid isPermaLink="true">https://lapsezero.hashnode.dev/still-renewing-tomcat-and-spring-boot-certificates-by-hand-how-to-automate-renewal-and-deployment</guid><category><![CDATA[Java]]></category><category><![CDATA[Springboot]]></category><dc:creator><![CDATA[Fizee]]></dc:creator><pubDate>Fri, 30 Oct 2026 13:57:30 GMT</pubDate><enclosure url="https://cdn.hashnode.com/uploads/covers/6abfaa42302f6644ca27b3e9/e166e6f2-2701-4302-89d9-e01f7589b58f.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>With Nginx, a renewed certificate is two PEM files and a reload. Tomcat and Spring Boot usually load a keystore instead (<code>.jks</code> or <code>.p12</code>), so each renewal also means downloading the Tomcat-format certificate from your CA or cloud console, or running <code>openssl pkcs12</code> or <code>keytool</code> to build a keystore yourself, then replacing the old file and restarting the app. That's fine once a year. Public certificates issued today are already capped at 200 days, the cap drops to 100 days on March 15, 2027, and to 47 days on March 15, 2029. At that point you are doing it roughly every month.</p>
<p>This post covers how to automate renewal for Java apps: first check whether the app loads the certificate at all, then the Tomcat and Spring Boot settings that matter, the three errors that most often break a certificate swap, and two ways to automate the whole thing: a Certbot hook you maintain yourself, or <a href="https://lapsezero.com/?utm_source=hashnode&amp;utm_medium=article&amp;utm_campaign=tomcat-spring-boot-ssl">LapseZero</a> as a hosted service.</p>
<h2>Check where HTTPS terminates</h2>
<p>Many Java apps sit behind Nginx, HAProxy or a cloud load balancer that handles TLS, while Tomcat listens on plain HTTP on port 8080. In that setup the certificate has nothing to do with Java. Renew it the way you would for Nginx or the load balancer and skip the keystore work.</p>
<p>To check: in Tomcat, look for a Connector with an <code>SSLHostConfig</code> in <code>conf/server.xml</code>. In Spring Boot, look for <code>server.ssl</code> in <code>application.yml</code>, <code>application.properties</code> or the startup arguments. If neither is there, the Java app usually doesn't load a certificate. The rest of this post assumes it does.</p>
<h2>Tomcat</h2>
<p>Since Tomcat 8.5 (including 9, 10 and 11), TLS settings go in an <code>SSLHostConfig</code> inside the Connector:</p>
<pre><code class="language-xml">&lt;Connector port="8443" protocol="org.apache.coyote.http11.Http11NioProtocol" SSLEnabled="true"&gt;
  &lt;SSLHostConfig&gt;
    &lt;Certificate certificateKeystoreFile="/opt/tomcat/ssl/tomcat.p12"
                 certificateKeystorePassword="changeit"
                 certificateKeystoreType="PKCS12" /&gt;
  &lt;/SSLHostConfig&gt;
&lt;/Connector&gt;
</code></pre>
<p>For automation, four attributes on <code>Certificate</code> matter:</p>
<ul>
<li><code>certificateKeystoreFile</code> is where the renewed keystore has to be written.</li>
<li><code>certificateKeystorePassword</code> has to match the password the new keystore is built with.</li>
<li><code>certificateKeystoreType</code> defaults to <code>JKS</code> when omitted. Use PKCS12 and set it explicitly.</li>
<li><code>certificateKeyAlias</code> is left out above. Without it, Tomcat uses the first key it reads from the keystore, which is the simplest option when the keystore holds a single certificate.</li>
</ul>
<p>You can also skip keystores. Tomcat 8.5 and later read PEM files directly through <code>certificateFile</code>, <code>certificateKeyFile</code> and <code>certificateChainFile</code>. There is no need to switch an existing keystore setup to PEM just to automate it; both work.</p>
<p>Once the file is replaced, Tomcat has to load it. A restart is the simplest way, and HTTPS is down while it runs: on a small test VM, a normal Tomcat 10.1 restart took HTTPS offline for about 7 seconds. To avoid the gap, the Manager app has an <code>sslReload</code> command that re-reads the certificate and key files without re-parsing <code>server.xml</code>:</p>
<pre><code class="language-bash">curl -fsS -u deployer:password "http://localhost:8080/manager/text/sslReload" | grep -q '^OK'
</code></pre>
<p>This needs the Manager app deployed and a user with the <code>manager-script</code> role. When the reload fails, Manager answers with text starting with <code>FAIL</code> and curl still exits 0, so the <code>grep</code> is what turns a failed reload into a non-zero exit code.</p>
<h2>Spring Boot</h2>
<p>Spring Boot runs an embedded Tomcat and reads the certificate from its own configuration:</p>
<pre><code class="language-yaml">server:
  port: 8443
  ssl:
    key-store: file:/opt/app/ssl/app.p12
    key-store-type: PKCS12
    key-store-password: changeit
</code></pre>
<p>This works the same in Spring Boot 2.7 and 3.x. Watch the <code>file:</code> prefix. A lot of tutorials use <code>classpath:keystore.p12</code>, which bundles the keystore into the jar. Then a new certificate means a new build and a new release, and nothing on the server can replace it. Move the keystore out of the jar and point <code>key-store</code> at an absolute <code>file:</code> path before automating anything.</p>
<p>Spring Boot also accepts PEM files: <code>server.ssl.certificate</code> for the chain and <code>server.ssl.certificate-private-key</code> for the key.</p>
<p>From Spring Boot 3.2 you can swap certificates without a restart. Define the certificate as an SSL bundle with <code>reload-on-update</code> enabled and Spring Boot watches the files in the background, reloading them when they change:</p>
<pre><code class="language-yaml">spring:
  ssl:
    bundle:
      jks:
        web:
          reload-on-update: true
          keystore:
            location: file:/opt/app/ssl/app.p12
            password: changeit
            type: PKCS12
server:
  ssl:
    bundle: web
</code></pre>
<p>The bundle type is called <code>jks</code>, but it holds PKCS12 files too; <code>type</code> decides. <code>server.ssl.bundle</code> can't be combined with <code>server.ssl.key-store</code> and the other keystore properties, so remove those when you switch. On versions before 3.2, a restart is the only option. Spring Boot also starts slower than plain Tomcat: on the same test VM, a minimal Spring Boot 3.5 app was unreachable over HTTPS for about 15 seconds during a restart, and real applications usually take longer.</p>
<h2>Three errors that break a certificate swap</h2>
<h3>The alias doesn't match</h3>
<p>Many Tomcat guides create the keystore with <code>keytool -alias tomcat</code> and set <code>certificateKeyAlias="tomcat"</code> (or <code>server.ssl.key-alias: tomcat</code> in Spring Boot). Build the renewed keystore with a different tool and the alias may change. On the next start the app fails with:</p>
<pre><code>java.io.IOException: Alias name [tomcat] does not identify a key entry
</code></pre>
<p>You won't see this while the app is running, because it keeps the old certificate in memory. It shows up on the first restart after renewal, when the app refuses to start. Either build the new keystore with the same alias (<code>openssl pkcs12 -export -name tomcat</code>), or, if the keystore only ever holds one certificate, remove the alias from the config.</p>
<h3>The password doesn't match</h3>
<p>The new keystore's password has to equal <code>certificateKeystorePassword</code> or <code>server.ssl.key-store-password</code>. Otherwise startup fails with:</p>
<pre><code>Failed PKCS12 integrity checking
</code></pre>
<p>A JKS file from a CA or cloud console sometimes has a key password that differs from the keystore password, which shows up as <code>certificateKeyPassword</code> in Tomcat or <code>server.ssl.key-password</code> in Spring Boot. In a generated PKCS12 file both passwords are the same, so remove that setting or set it to the keystore password.</p>
<h3>The restart succeeds and the app is down</h3>
<p>This is the one that slips through. Most systemd units for Java apps use <code>Type=simple</code>, where <code>systemctl restart</code> returns as soon as the process starts, long before Java loads the certificate. With a wrong alias or password, <code>systemctl restart</code> still exits with 0. Tomcat keeps running without its HTTPS connector; Spring Boot exits a few seconds later. Your deploy script sees a successful command and moves on while the service is down.</p>
<p>So the restart step should only succeed once HTTPS actually answers, and fail otherwise:</p>
<pre><code class="language-sh">#!/bin/sh
# Usage: restart-and-wait.sh &lt;service&gt; &lt;https-port&gt;
set -eu
systemctl restart "$1"
for attempt in $(seq 1 30); do
  if curl --insecure --fail --silent --max-time 1 "https://127.0.0.1:$2/" &gt;/dev/null; then
    exit 0
  fi
  sleep 1
done
echo "$1 did not become HTTPS-ready" &gt;&amp;2
exit 1
</code></pre>
<p><code>--insecure</code> is only there because this is a local liveness check. Replace <code>/</code> with a path in your app that returns 200 without a login.</p>
<p>The first time you automate this, also check file permissions. The Java process usually runs as a non-root user, and it has to be able to read the newly written keystore.</p>
<h2>Doing it yourself with a Certbot deploy hook</h2>
<p>If Certbot issues the certificate on the same server, put the conversion, the swap and the restart in a deploy hook. Certbot runs it after each successful renewal and passes the certificate directory in <code>RENEWED_LINEAGE</code>:</p>
<pre><code class="language-sh">#!/bin/sh
set -eu
openssl pkcs12 -export \
  -in "$RENEWED_LINEAGE/fullchain.pem" \
  -inkey "$RENEWED_LINEAGE/privkey.pem" \
  -name tomcat -passout file:/etc/tomcat/keystore.pass \
  -out /opt/tomcat/ssl/tomcat.p12.new
mv /opt/tomcat/ssl/tomcat.p12.new /opt/tomcat/ssl/tomcat.p12
/usr/local/bin/restart-and-wait.sh tomcat 8443
</code></pre>
<p>acme.sh doesn't set <code>RENEWED_LINEAGE</code>. Use <code>--install-cert</code> to choose where the full chain and private key are written, point the script at those paths, and run it through <code>--reloadcmd</code>.</p>
<p>For one app on one server, that's enough. With more servers and apps, a few things are left to you:</p>
<ul>
<li>Recovery: if the restart fails, the old keystore has already been overwritten. Keep a backup and restore it on failure, or the app stays down until someone fixes it.</li>
<li>Distribution: the renewed certificate only exists on the machine where Certbot runs. For several servers you either run Certbot and the hook on each one, or copy the certificate over and run the same steps everywhere.</li>
<li>Alerts: Certbot doesn't notify anyone by default. A failed hook only shows up in its log, so nobody knows unless someone reads it.</li>
</ul>
<h2>Deploying to Java apps with LapseZero</h2>
<p>LapseZero is a hosted service that issues certificates, renews them before they expire and deploys them to servers and cloud services. The certificates are free DV certificates with wildcard support, validated over DNS with either a DNS provider API key or a single CNAME record. Nothing needs to be migrated: the first deployment writes the new certificate to your existing keystore path.</p>
<p>A Java server is set up once. Add a deployment target, choose <strong>Server</strong>, pick <strong>Tomcat</strong> or <strong>Spring Boot</strong>, and fill in three fields:</p>
<ul>
<li><strong>Certificate Path</strong>: the keystore path from your config, without the <code>file:</code> prefix for Spring Boot.</li>
<li><strong>Keystore Password</strong>: the same password as in your config. If your config sets a key alias, enter that alias too.</li>
<li><strong>Post-deploy Command</strong>: the <code>restart-and-wait.sh</code> script above.</li>
</ul>
<p>LapseZero connects over SSH or through a deployment agent that needs no inbound port. Private keys and passwords are stored encrypted.</p>
<p>From then on, every renewal builds a new PKCS12 file, writes it to the same path and runs your command, and the three errors above stop being your problem. The keystore is built with your password and alias, so they match. If the command fails, for example because the app isn't serving HTTPS within 30 seconds, LapseZero puts the old keystore back and runs the command again, so the app keeps the old certificate and the notification tells you it was rolled back. Add the app's HTTPS address under <strong>Live check</strong> and each deployment also confirms the new certificate is actually being served.</p>
<p>For an app on several servers, add one deployment target per server with the same settings. The Nginx, load balancer or cloud services in front of it get the same certificate from the same place, with no hook script to maintain on every machine.</p>
<p>The free plan covers 3 domains and 5 deployment targets with no time limit, enough to try it on one or two servers. One domain on six servers is past the free plan; Starter is $3/month for 10 domains and 20 deployment targets.</p>
]]></content:encoded></item><item><title><![CDATA[Certbot Alternative: When to Keep Certbot and When to Switch]]></title><description><![CDATA[When to keep Certbot, which clients to consider, and how to move to a hosted service once a certificate must reach several servers, CDNs and LBs.]]></description><link>https://lapsezero.hashnode.dev/certbot-alternative-when-to-keep-certbot-and-when-to-switch</link><guid isPermaLink="true">https://lapsezero.hashnode.dev/certbot-alternative-when-to-keep-certbot-and-when-to-switch</guid><category><![CDATA[certbot]]></category><category><![CDATA[SSL]]></category><category><![CDATA[Let's Encrypt]]></category><category><![CDATA[nginx]]></category><category><![CDATA[Devops]]></category><dc:creator><![CDATA[Fizee]]></dc:creator><pubDate>Thu, 29 Oct 2026 00:28:00 GMT</pubDate><enclosure url="https://cdn.hashnode.com/uploads/covers/6abfaa42302f6644ca27b3e9/bef58531-330f-402a-bece-0cffd85423b0.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Certbot is the ACME client most people start with, and for good reason. It is free, maintained by the EFF, and it is what Let's Encrypt recommends to most people with shell access. Install it, run it once, and a timer renews your certificate from then on.</p>
<p>People who look for a Certbot alternative usually have more than one place to put the certificate: a second and third server, a CDN in front of the site, a load balancer that needs the certificate too, and a folder of deploy hooks that only one person understands.</p>
<p>This post compares Certbot, other self-hosted ACME clients and LapseZero on that case: which servers and cloud products each can deploy to, who maintains the deploy scripts, and how you find out a deployment failed. The last part covers moving from Certbot.</p>
<h2>When Certbot is enough</h2>
<p>Certbot is the right tool when:</p>
<ul>
<li>the certificate is used on one server;</li>
<li>the Nginx or Apache plugin installs it and reloads the web server;</li>
<li>nothing else (CDN, load balancer, another machine) needs a copy.</li>
</ul>
<p>In that setup there is nothing to fix. Check that the renewal timer is active (<code>systemctl list-timers</code> on most distributions) and run <code>certbot renew --dry-run</code> once in a while. Moving to anything else adds a moving part without removing one.</p>
<h2>Other self-hosted ACME clients</h2>
<p>If you want to stay self-hosted but prefer a different style, these are the usual alternatives:</p>
<ul>
<li><strong>acme.sh</strong>: a pure shell script, no Python, with a large set of DNS API integrations and deploy hooks.</li>
<li><strong>lego</strong>: a single Go binary, convenient in containers and CI.</li>
<li><strong>Caddy</strong>: a web server that obtains and renews certificates by itself, so there is no separate client at all.</li>
<li><strong>cert-manager</strong>: the standard choice inside Kubernetes.</li>
</ul>
<p>Let's Encrypt keeps a longer list of ACME clients in its docs. For a broader comparison of scripts, self-hosted panels and hosted services, see my earlier post on choosing an SSL certificate automation tool.</p>
<p>acme.sh also ships deploy hooks for remote servers over SSH and for some cloud services. If those cover your targets and you are fine maintaining the setup yourself, it is a reasonable choice. The other clients, like Certbot, leave deployment beyond their own machine or cluster to you.</p>
<h2>Deploying with Certbot hooks</h2>
<p>Certbot can deploy beyond the local web server. <code>--deploy-hook</code> runs a command after each successful renewal, and that command can copy files to other servers or call a cloud API. Plenty of teams do exactly this.</p>
<p>The cost shows up later:</p>
<ul>
<li>every new server or cloud product means another hook to write and test;</li>
<li>a hook that fails quietly leaves a server serving the old certificate while Certbot reports a successful renewal;</li>
<li>if a hook fails halfway, putting the old files back is up to the hook;</li>
<li>seeing which targets already have the new certificate means building that reporting yourself.</li>
</ul>
<p>If that list sounds familiar, a hosted service that deploys as well as renews is a better fit.</p>
<h2>LapseZero</h2>
<p><a href="https://lapsezero.com/?utm_source=hashnode&amp;utm_medium=article&amp;utm_campaign=certbot-alternative">LapseZero</a> is a hosted service that issues SSL certificates, renews them, and deploys them to servers and cloud products. It also monitors HTTPS endpoints, including ones it does not deploy to.</p>
<p>How it covers the gaps above:</p>
<ul>
<li><strong>Validation without a DNS key.</strong> Certificates are issued over DNS-01, wildcards included. You either give LapseZero a DNS API key or add one CNAME record once and keep your DNS credentials to yourself.</li>
<li><strong>Automatic renewal.</strong> A certificate is renewed when less than a third of its validity is left, about 30 days before expiry for a 90-day certificate.</li>
<li><strong>Servers.</strong> Over SSH, or through an open-source agent (<code>lapsezero-agent</code> on GitHub) that connects out over HTTPS, so you open no port and the platform stores no SSH key. 1Panel and Nginx Proxy Manager also work through the agent.</li>
<li><strong>Cloud products.</strong> AWS: CloudFront, ALB, NLB, API Gateway, ACM and Amplify. Google Cloud: Certificate Manager. Azure: Key Vault. Plus CDN, load balancer and storage products from Alibaba Cloud, Tencent Cloud, Huawei Cloud and others.</li>
<li><strong>Safe server updates.</strong> Files are replaced all or nothing. If writing a file or reloading fails, the previous certificate is put back and the notification says so.</li>
<li><strong>Status per target.</strong> Each target has its own record, and failures go out by email, Slack, Telegram or webhook. An optional check connects to the public HTTPS address and compares the certificate fingerprint. On agent targets it can also check on the server itself, which matters when a CDN sits in front: the CDN serving the new certificate says nothing about the origin behind it.</li>
</ul>
<p>If one certificate has to reach several servers, a CDN or a load balancer, LapseZero is the better fit. It takes over issuance and renewal as well, so you cannot keep Certbot issuing and use LapseZero only to distribute.</p>
<h2>Certbot and LapseZero side by side</h2>
<table>
<thead>
<tr>
<th></th>
<th>Certbot</th>
<th>LapseZero</th>
</tr>
</thead>
<tbody><tr>
<td>Runs on</td>
<td>Your server</td>
<td>Hosted</td>
</tr>
<tr>
<td>Cost</td>
<td>Free</td>
<td>Free plan; paid from $3/month</td>
</tr>
<tr>
<td>Wildcards</td>
<td>With a DNS plugin</td>
<td>Yes, DNS-01</td>
</tr>
<tr>
<td>DNS credentials</td>
<td>On your server</td>
<td>API key or one CNAME</td>
</tr>
<tr>
<td>Other servers</td>
<td>Your deploy hooks</td>
<td>SSH or agent</td>
</tr>
<tr>
<td>Cloud products</td>
<td>Your deploy hooks</td>
<td>Built-in targets</td>
</tr>
<tr>
<td>Failed deployment</td>
<td>Depends on your hook</td>
<td>Alert; rollback on servers</td>
</tr>
<tr>
<td>Live check</td>
<td>Not included</td>
<td>Fingerprint check</td>
</tr>
</tbody></table>
<h2>What LapseZero stores, and how to leave</h2>
<p>Moving a production certificate to a hosted service means trusting it with keys and access to your servers.</p>
<p><strong>Private keys.</strong> LapseZero generates the key when it issues the certificate. Keys and certificates, along with DNS, cloud and SSH credentials, are stored encrypted with AES-256-GCM, and saved credentials are never shown again in the console or API. You can download any issued certificate with its key from the console. The security page on the LapseZero site lists what each feature needs.</p>
<p><strong>Cloud permissions.</strong> When you add a cloud account, the console gives you a policy to paste into the provider's IAM console, limited to the certificate and resource actions LapseZero calls. You do not have to hand over an admin key.</p>
<p><strong>The agent.</strong> It runs as root as a systemd service, because it writes certificate files and runs your reload command. The reload command is the one you configure, such as <code>systemctl reload nginx</code>. <code>lapsezero-agent uninstall</code> removes it.</p>
<p><strong>Failures.</strong> A deployment that fails because a server is unreachable is retried automatically for a few minutes. If the server stays offline longer than that, the deployment is marked failed, you get a notification, and you retry it from the console once the server is back.</p>
<p><strong>Leaving.</strong> The certificate files stay at the same paths on your server, so Nginx keeps working whether LapseZero is there or not. To go back to Certbot, move the renewal config you set aside back to <code>/etc/letsencrypt/renewal/</code> and run <code>certbot renew --cert-name example.com --force-renewal</code>.</p>
<h2>Moving from Certbot without breaking anything</h2>
<p>The agent knows what a Certbot setup looks like, so you do not have to rebuild your Nginx config.</p>
<ol>
<li><strong>List your deploy hooks.</strong> Note which certificates have hooks that copy them to other servers or cloud products. Those destinations become deployment targets in LapseZero, and the hooks go away at the end.</li>
<li><strong>Install the agent</strong> on the server with the one-line command from the console.</li>
<li><strong>Scan the server.</strong> The agent runs <code>nginx -T</code>, which only reads the config, and lists each server block with its certificate paths. Paths under <code>/etc/letsencrypt/live/</code> are marked as managed by Certbot. The scan does not read private key contents.</li>
<li><strong>Take over the sites you want.</strong> LapseZero creates a deployment target that writes to the same paths and runs the same reload command. Nothing is deployed at this step.</li>
<li><strong>Issue the certificate</strong> if LapseZero does not have one for the domain yet. It is deployed to the new target, and to any cloud targets you added, through the normal flow.</li>
<li><strong>Check the result.</strong> Each target should show a successful deployment, and the live check should see the new fingerprint, both on the public address and on the server.</li>
<li><strong>Stop Certbot renewing that certificate</strong>, and only that one: move <code>/etc/letsencrypt/renewal/example.com.conf</code> somewhere outside that directory. LapseZero reminds you but does not do this for you, and if both keep running they overwrite each other's files. Do not use <code>certbot delete</code>, which removes the files Nginx points to. Then remove the hooks from step 1.</li>
</ol>
<p>Doing step 7 after step 6 means there is never a moment when nothing renews the certificate.</p>
<p>One case needs a small change first. LapseZero issues one certificate per domain you add: a single name (a root domain can include <code>www</code>), or a wildcard such as <code>*.example.com</code>, which also covers <code>example.com</code>. A server block that serves <code>example.com</code> and <code>example.org</code> together, or <code>a.example.com</code> and <code>b.c.example.com</code>, cannot be covered by one of those certificates, so split it into separate server blocks before taking it over.</p>
<h2>Pricing</h2>
<p>The free plan covers 3 domains, 5 deployment targets and 5 monitors, with no time limit. One domain deployed to two servers, a CDN and a load balancer uses four of the five targets. Paid plans start at $3/month (Starter: 10 domains, 20 targets); Pro is $8/month for 30 domains and 80 targets, and Team is $20/month for 100 domains and 200 targets. Yearly billing costs ten months' worth.</p>
]]></content:encoded></item><item><title><![CDATA[One SSL Certificate for All Your Subdomains: A Practical Guide to Wildcard HTTPS]]></title><description><![CDATA[Learn when to use wildcard SSL certificates, verify domains with DNS, and weigh the trade-offs of sharing a private key across services.]]></description><link>https://lapsezero.hashnode.dev/one-ssl-certificate-for-all-your-subdomains-a-practical-guide-to-wildcard-https</link><guid isPermaLink="true">https://lapsezero.hashnode.dev/one-ssl-certificate-for-all-your-subdomains-a-practical-guide-to-wildcard-https</guid><category><![CDATA[SSL]]></category><category><![CDATA[Devops]]></category><dc:creator><![CDATA[Fizee]]></dc:creator><pubDate>Tue, 20 Oct 2026 01:47:26 GMT</pubDate><enclosure url="https://cdn.hashnode.com/uploads/covers/6abfaa42302f6644ca27b3e9/4512fa8c-dd51-40b9-8633-e323e19d8d45.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>A project with an app, API, admin dashboard, and documentation site can end up with several hostnames:</p>
<pre><code>example.com
├── www.example.com
├── app.example.com
├── api.example.com
├── admin.example.com
└── docs.example.com
</code></pre>
<p>Each service needs HTTPS.</p>
<p>You can manage a separate certificate for every subdomain, but depending on your infrastructure, a wildcard SSL certificate may be a more convenient choice.</p>
<p>This guide covers wildcard matching, DNS validation, and the trade-offs of sharing a certificate across services.</p>
<h2>1. Why Wildcard Certificates Are Useful</h2>
<p>A standard certificate typically covers one or more explicitly listed hostnames.</p>
<p>A wildcard certificate uses an asterisk to match a single subdomain level.</p>
<p>For example:</p>
<pre><code>*.example.com
</code></pre>
<p>matches:</p>
<pre><code>app.example.com
api.example.com
admin.example.com
docs.example.com
</code></pre>
<p>That means you can deploy the same certificate to several services instead of requesting a separate certificate for each hostname.</p>
<p>There are two common misconceptions worth clearing up.</p>
<p><strong>A wildcard doesn't automatically cover the root domain.</strong></p>
<p><code>*.example.com</code> and <code>example.com</code> are different names. If you need both, the certificate must include both.</p>
<p><strong>A wildcard doesn't match every possible depth.</strong></p>
<p><code>*.example.com</code> does not cover <code>api.dev.example.com</code>.</p>
<p>For that hostname, you'd need explicit coverage or a wildcard such as <code>*.dev.example.com</code>.</p>
<h2>2. You Don't Need a Running Web Server to Get a Certificate</h2>
<p>One of the more useful aspects of wildcard certificates is their DNS-based validation process.</p>
<p>Instead of proving domain ownership by serving a file from your web server, you add a DNS record.</p>
<p>The validation system checks whether the expected TXT record exists for your domain.</p>
<p>For example:</p>
<pre><code>_acme-challenge.example.com
</code></pre>
<p>This offers some practical advantages:</p>
<ul>
<li>Your web application doesn't need to be running.</li>
<li>You don't need to expose port 80 for validation.</li>
<li>Validation isn't dependent on your reverse proxy configuration.</li>
<li>You can request certificates before deploying your application.</li>
</ul>
<p>This is useful when you're preparing a staging environment, building infrastructure from scratch, or working with services behind a CDN.</p>
<h2>3. Request a Free Wildcard Certificate from Your Browser</h2>
<p>If you only need a certificate occasionally, setting up a full certificate automation environment may be unnecessary.</p>
<p>There's a browser-based option available at:</p>
<p><a href="https://lapsezero.com/tools/free-ssl-certificate?utm_source=hashnode&amp;utm_medium=community&amp;utm_campaign=free-wildcard-ssl">https://lapsezero.com/tools/free-ssl-certificate?utm_source=hashnode&amp;utm_medium=community&amp;utm_campaign=free-wildcard-ssl</a></p>
<p>The process is straightforward.</p>
<p><strong>First, select the wildcard certificate option.</strong></p>
<p>Enter your domain, such as <code>example.com</code>.</p>
<p>The tool includes both <code>*.example.com</code> and the root domain by default.</p>
<p><strong>Next, complete DNS verification.</strong></p>
<p>The page displays the TXT records needed to prove control of your domain. When both names are included, add both values as separate TXT records with the same name, then continue after they become available.</p>
<p>You can check the record using:</p>
<pre><code>dig TXT _acme-challenge.example.com
</code></pre>
<p><strong>Finally, download the certificate.</strong></p>
<p>Once issuance succeeds, download the certificate and matching private key in the format appropriate for your server.</p>
<p>The tool doesn't require account registration or server-side installation.</p>
<p><img src="https://dev-to-uploads.s3.us-east-2.amazonaws.com/uploads/articles/r4a5c126fkmb3ilupo7v.png" alt="Wildcard certificate request form" /></p>
<p><img src="https://dev-to-uploads.s3.us-east-2.amazonaws.com/uploads/articles/scimnwa8n59a8fpgspog.png" alt="DNS verification records" /></p>
<p>The screenshots use my test domain <code>ssl-guide.hxkit.com</code>; replace it with your own domain.</p>
<h2>4. Where Should the Private Key Be Generated?</h2>
<p>This is worth thinking about whenever you use an online certificate tool.</p>
<p>TLS certificates rely on public-key cryptography.</p>
<p>The server needs a private key that matches the public key associated with its certificate.</p>
<p>If a third-party service generates and stores your private key, you need to trust that service's handling of sensitive cryptographic material.</p>
<p>A safer design for a browser-based certificate tool is to generate the key locally and only transmit the information required for certificate issuance.</p>
<p>That's the approach used by LapseZero's free certificate request tool.</p>
<p>The private key is generated in the browser and isn't uploaded to LapseZero.</p>
<p>This reduces private-key exposure during the request process.</p>
<p>Of course, local key generation isn't a substitute for securing your device, browser, downloaded files, or production infrastructure.</p>
<h2>5. One Certificate Across Multiple Servers: Is That Always a Good Idea?</h2>
<p>Not necessarily.</p>
<p>Suppose your services run on different machines:</p>
<pre><code>Server A → app.example.com
Server B → api.example.com
Server C → docs.example.com
</code></pre>
<p>You could install the same wildcard certificate and private key on all three servers.</p>
<p>Functionally, that works.</p>
<p>But there's a security trade-off.</p>
<p>If one server is compromised and its private key is stolen, the attacker may be able to use that key with the shared certificate for any covered hostname, subject to control of the corresponding traffic or endpoint.</p>
<p>For a small personal project, sharing a wildcard certificate might be a reasonable trade-off.</p>
<p>For environments with stricter isolation requirements, separate certificates and private keys may be preferable.</p>
<h2>6. Certificate Issuance Is Only Half the Problem</h2>
<p>There's a difference between getting HTTPS working today and keeping it working reliably.</p>
<p>The certificate issued for this walkthrough is valid for about 90 days. Check the expiry date on your own certificate.</p>
<p>That means you need a renewal strategy.</p>
<p>For a single site, manually replacing the certificate might be manageable.</p>
<p>For multiple servers, CDNs, and cloud load balancers, renewal involves more than requesting a new certificate.</p>
<p>You also need to:</p>
<ol>
<li>Obtain a replacement certificate before expiry.</li>
<li>Distribute it to the correct deployment targets.</li>
<li>Reload or update the relevant services.</li>
<li>Verify that the new certificate is actually being served.</li>
<li>Monitor for failures.</li>
</ol>
<p>This is where automated certificate management becomes valuable.</p>
<p>If you already have Certbot, acme.sh, or your own deployment scripts working reliably, you may not need another tool.</p>
<p>But for teams managing certificates across multiple environments, combining issuance, deployment, and monitoring into one workflow can reduce operational work.</p>
<h2>7. Choosing the Right Approach</h2>
<p>Here's how I'd think about it.</p>
<table>
<thead>
<tr>
<th>Situation</th>
<th>Practical approach</th>
</tr>
</thead>
<tbody><tr>
<td>One-off HTTPS setup</td>
<td>Browser-based certificate request</td>
</tr>
<tr>
<td>Personal project with several subdomains</td>
<td>Wildcard certificate</td>
</tr>
<tr>
<td>Existing automated server infrastructure</td>
<td>Certbot or acme.sh</td>
</tr>
<tr>
<td>Multiple deployment targets</td>
<td>Automated renewal and deployment</td>
</tr>
<tr>
<td>Strict service isolation requirements</td>
<td>Separate certificates and private keys</td>
</tr>
</tbody></table>
<p>I built the free browser-based certificate request tool as part of <strong>LapseZero</strong>, a project focused on simplifying SSL certificate issuance, renewal, deployment, and monitoring.</p>
<p>The free tool works without an account:</p>
<p><a href="https://lapsezero.com/tools/free-ssl-certificate?utm_source=hashnode&amp;utm_medium=community&amp;utm_campaign=free-wildcard-ssl">https://lapsezero.com/tools/free-ssl-certificate?utm_source=hashnode&amp;utm_medium=community&amp;utm_campaign=free-wildcard-ssl</a></p>
<p>If you're managing multiple subdomains, I'd be curious to know how you're currently handling certificate renewal and deployment.</p>
<p>Do you use wildcard certificates, individual certificates, or a fully automated setup?</p>
]]></content:encoded></item><item><title><![CDATA[Updated an SSL Certificate on Alibaba Cloud, but CLB or ALB Still Serves the Old One?]]></title><description><![CDATA[Find CLB and ALB listener bindings that still use an old certificate, then automate renewal and deployment across them.]]></description><link>https://lapsezero.hashnode.dev/updated-an-ssl-certificate-on-alibaba-cloud-but-clb-or-alb-still-serves-the-old-one</link><guid isPermaLink="true">https://lapsezero.hashnode.dev/updated-an-ssl-certificate-on-alibaba-cloud-but-clb-or-alb-still-serves-the-old-one</guid><dc:creator><![CDATA[Fizee]]></dc:creator><pubDate>Thu, 15 Oct 2026 14:47:41 GMT</pubDate><enclosure url="https://cdn.hashnode.com/uploads/covers/6abfaa42302f6644ca27b3e9/8d1d0907-e20b-49d3-bbcb-1260752e1f07.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>The new certificate is in Certificate Management Service, but browsers still report an expired certificate. Check the load balancer's HTTPS listener: that is where the certificate presented to visitors is bound. Uploading a new certificate, or replacing the certificate on a backend server, may leave that binding unchanged.</p>
<p>When one certificate serves several listeners, it is easy to miss one listener or an additional domain binding. Here is where to update certificates on CLB and ALB, and how to automate those updates after renewal.</p>
<h2>CLB: Check the Default Certificate and Extended Domains</h2>
<p>Open the CLB instance's listener list, find the HTTPS listener, and use <strong>Manage Certificates</strong> to select the new default certificate.</p>
<p>Extended domains have their own certificate bindings. Updating only the default certificate may leave those domains serving the old one.</p>
<p>If several listeners or extended domains reference the same old certificate, <strong>Certificate Management → Replace Certificate</strong> can update its associated resources together. Check the affected resources before proceeding and schedule the replacement during a quiet period.</p>
<p>For example, a domain might be served by load balancers in both Shanghai and Singapore. Updating the Shanghai listener leaves Singapore unchanged. Check the instance, region, and listener port as well as the domain.</p>
<h2>ALB: Update the Binding for the Right Domain</h2>
<p>Prepare the certificate in Certificate Management Service, then open the ALB instance's listener list and choose <strong>Manage Certificates → Server Certificates</strong>. You can replace the default certificate or add an additional certificate there.</p>
<p>Suppose <code>www.example.com</code> uses the default certificate and <code>api.example.net</code> uses an additional certificate. Update the API's binding while preserving the website's certificate. Verify that the new certificate is live before removing the old binding, rather than replacing the listener's entire certificate list.</p>
<p>For listeners managed by Kubernetes ALB Ingress, update certificates through the cluster's configuration.</p>
<h2>Automating Renewal and Deployment for Free Certificates</h2>
<p>Alibaba Cloud offers hosting for paid certificates, with automatic renewal and deployment. If you already use it, keep doing so. Free personal test certificates last about three months and do not support hosting; you need to request and deploy replacements.</p>
<p>To keep using free certificates without replacing each listener's certificate by hand, you can use <a href="https://lapsezero.com/?utm_source=hashnode&amp;utm_medium=article&amp;utm_campaign=aliyun-clb-alb">LapseZero</a>. It issues and renews certificates through Let's Encrypt, then deploys them to connected targets such as CLB, ALB, CDN, and Nginx. This does not use Alibaba Cloud's free certificate quota or require deployment scripts.</p>
<p>Setup involves three tasks:</p>
<ol>
<li>Add your domain and configure the CNAME records shown for DNS delegation. Future renewals reuse those records.</li>
<li>Connect an Alibaba Cloud RAM user and follow the console guide to grant deployment permissions. DNS write access is not required.</li>
<li>Select the HTTPS listeners to update and request the first certificate.</li>
</ol>
<p>Future renewals deploy automatically to those listeners. If the same certificate is used elsewhere, add those targets too. You can also set a deployment window to keep changes outside busy hours.</p>
<h2>Verify the Certificate Visitors Receive</h2>
<p>After deployment, check the certificate using the site's hostname. If that hostname points to a CDN, you will see the CDN's certificate. To check the load balancer, use a hostname that points directly to it and is covered by the certificate.</p>
<p>Set that hostname as the target's live check address in LapseZero to verify it automatically after each deployment. If the check finds the old certificate still in use, a notification helps you identify the missed endpoint.</p>
]]></content:encoded></item><item><title><![CDATA[Choosing an SSL certificate automation tool: acme.sh, Certimate, AWS ACM or a hosted service]]></title><description><![CDATA[Every certificate automation tool issues certificates over ACME, and that part works much the same everywhere. This article compares acme.sh, Certimate and…]]></description><link>https://lapsezero.hashnode.dev/choosing-an-ssl-certificate-automation-tool-acme-sh-certimate-aws-acm-or-a-hosted-service</link><guid isPermaLink="true">https://lapsezero.hashnode.dev/choosing-an-ssl-certificate-automation-tool-acme-sh-certimate-aws-acm-or-a-hosted-service</guid><category><![CDATA[SSL]]></category><dc:creator><![CDATA[Fizee]]></dc:creator><pubDate>Wed, 07 Oct 2026 09:14:43 GMT</pubDate><enclosure url="https://cdn.hashnode.com/uploads/covers/6abfaa42302f6644ca27b3e9/f0d12d2d-fb86-4c01-8ac8-e77c2aa800f5.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Every certificate automation tool issues certificates over ACME, and that part works much the same everywhere. This article compares acme.sh, Certimate and hosted services such as AWS ACM on three points:</p>
<ol>
<li><p>Automatic renewal. Let's Encrypt certificates expire after 90 days, and since March 2026 commercial certificates are capped at 200 days, so renewing by hand will eventually slip. All the tools here renew automatically; the certificate services built into cloud providers have limits, covered further down.</p>
</li>
<li><p>How the renewed certificate is deployed, and where it can go. If the certificate only lives on one or two servers, a reload after renewal is enough and any tool can do it. Once the same certificate also has to reach a CDN, object storage or load balancers, you need a ready-made integration for each of them, or you write scripts against the cloud provider's API yourself. Deploying to cloud services also needs access keys, and some companies have a rule on whether those may leave their own servers.</p>
</li>
<li><p>What happens when a deployment fails. You want an alert that says which location failed, and on servers, a switch back to the old certificate if writing the files or the reload fails. Harder to catch is a location that was never configured: every tool only updates the locations it was given, and a missing one never produces a failure alert.</p>
</li>
</ol>
<p>Deployment is where it went wrong for us. We have one <code>*.example.com</code> wildcard certificate deployed to two Nginx servers, several domains on Alibaba Cloud's DCDN, and custom domains on OSS, their object storage, all of which used to be updated by hand in each product's console. The sites that got missed were usually not the important ones: our sites have tiers, the important ones are monitored and alert on certificate errors, and some low-tier sites have no monitoring at all, so we heard from a user or a colleague, usually after the certificate had already expired.</p>
<h2>acme.sh plus scripts</h2>
<p>acme.sh is a good fit when the certificate only lives on one or two servers. Issuance, renewal and a reload after renewal are mature, and notifications can go to Slack, Telegram and many other channels.</p>
<p>Cloud services are a different story. acme.sh ships deploy hooks for a handful of CDNs and panels, plus a generic <code>ssh</code> hook, but nothing for AWS. Importing into ACM and pointing CloudFront or a listener at the new certificate is your own script.</p>
<p>Even where a hook exists, a wildcard certificate needs every target domain spelled out in a variable. Alibaba Cloud DCDN, for example:</p>
<pre><code class="language-bash">export DEPLOY_ALI_DCDN_DOMAIN="www.example.com static.example.com"
acme.sh --deploy -d example.com --deploy-hook ali_dcdn
</code></pre>
<p>The variable is saved and reused after each renewal. When a new domain is added later and nobody comes back to update it, you are back to the forgotten site, just moved from a console into a config file.</p>
<p>We never put a script on our servers for a different reason: if it replaced something wrongly one day, we would not know, and that is worse than doing it by hand.</p>
<h2>Certimate</h2>
<p><a href="https://github.com/certimate-go/certimate">Certimate</a> is a self-hosted certificate dashboard, MIT-licensed and free. It runs as a single binary or Docker container, and you set up issuance and deployment in a web UI. It covers far more cloud services than acme.sh hooks, including AWS, Kubernetes, CDNs, WAFs and load balancers. Windows and IIS shops tend to use Certify The Web instead.</p>
<p>The cost of self-hosting is that the dashboard becomes one more service to run. Every cloud access key is stored on that machine, so it needs hardening. If the dashboard goes down, renewals and failure alerts stop together, so monitor it from outside as well.</p>
<p>If company policy does not allow cloud credentials to go to a third party, self-host, and use Certimate.</p>
<h2>Hosted services</h2>
<p>A hosted service runs issuance, renewal, deployment and alerts on the provider's side, so there is no server or dashboard of yours to maintain. Cloud providers have something similar for their own products: <a href="https://aws.amazon.com/certificate-manager/pricing/">AWS Certificate Manager</a> renews public certificates for load balancers, CloudFront and API Gateway at no cost, but those certificates cannot be copied onto your Nginx servers, and exportable ones are charged at every renewal.</p>
<p>If the certificate has to reach several servers and several cloud services and you do not want to run a dashboard, a hosted service fits, for example <a href="https://lapsezero.com/?utm_source=hashnode&amp;utm_medium=article&amp;utm_campaign=ssl-automation-tools">LapseZero</a>. It issues certificates from Let's Encrypt (wildcards included), renews them 30 days before expiry by default, and deploys them to every configured location:</p>
<ul>
<li><p>Cloud services: AWS CloudFront, ALB, NLB and API Gateway, plus Alibaba Cloud and Tencent Cloud CDN, load balancers and more.</p>
</li>
<li><p>Servers: over SSH, or through an open-source deployment agent that pulls jobs, so the server does not need SSH exposed.</p>
</li>
</ul>
<p>When you add a cloud location, LapseZero uses your access key to list the CDN distributions, load balancer listeners and similar resources in the account, and you tick the ones to deploy to. Sites nobody checks show up in that list too, so it does not all rely on memory. Domains added later are not picked up automatically; you come back and tick them as well.</p>
<p>Each location has its own result, and failures are sent by email, Slack, Telegram or webhook. On servers, the old files are backed up first, and if writing the files or the reload fails, the server is switched back to the old certificate and the alert says how the rollback went.</p>
<p>The main hesitation with any hosted service is handing over cloud access keys, and with a service you have never used, we would hesitate too. Use an IAM user limited to the services you deploy to, and start with one or two low-stakes sites.</p>
<p>The free plan covers 3 domains and 5 deployment targets; the two Nginx servers plus one CDN domain and one storage domain above make 4. Paid plans start at $3 a month.</p>
<h2>Deployment checks and expiry monitoring</h2>
<p>After replacing a certificate, you want to know that the site is serving the new one. LapseZero can check this automatically after deployment: set an HTTPS check address for a deployment location to see whether it serves the new certificate. When you deploy to Nginx through the agent, it can also check on the server itself that Nginx has loaded the new certificate. If the site sits behind a CDN or load balancer, the public check sees the certificate at that entry point; the agent can check the Nginx origin locally.</p>
<p>Keep expiry monitoring running too. Add every domain that uses the certificate, including sites without automatic deployment and the ones nobody looks at, so you get a reminder before their certificates expire. A monitor only connects to the public HTTPS address and needs no credentials. LapseZero's certificate monitoring includes 5 sites on the free plan, or run your domains through the <a href="https://lapsezero.com/tools/ssl-certificate-expiry-checker?utm_source=hashnode&amp;utm_medium=article&amp;utm_campaign=ssl-automation-tools">SSL certificate expiry checker</a> once to see whether anything has already been missed.</p>
]]></content:encoded></item><item><title><![CDATA[How to Auto-Renew SSL Certificates on Tencent Cloud CDN and EdgeOne]]></title><description><![CDATA[Since April 25, 2024, free certificates from Tencent Cloud's SSL Certificate Service have been valid for 3 months instead of 12, with a quota of 50 per…]]></description><link>https://lapsezero.hashnode.dev/how-to-auto-renew-ssl-certificates-on-tencent-cloud-cdn-and-edgeone</link><guid isPermaLink="true">https://lapsezero.hashnode.dev/how-to-auto-renew-ssl-certificates-on-tencent-cloud-cdn-and-edgeone</guid><category><![CDATA[SSL]]></category><category><![CDATA[Devops]]></category><category><![CDATA[Cloud]]></category><category><![CDATA[Security]]></category><dc:creator><![CDATA[Fizee]]></dc:creator><pubDate>Mon, 05 Oct 2026 08:08:58 GMT</pubDate><enclosure url="https://cdn.hashnode.com/uploads/covers/6abfaa42302f6644ca27b3e9/7ff43a42-9319-407e-b93e-351b5d273496.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h2>The Current Rules for Tencent Cloud Free Certificates</h2>
<p>Since April 25, 2024, free certificates from Tencent Cloud's SSL Certificate Service have been <a href="https://cloud.tencent.com/document/product/400/104538">valid for 3 months instead of 12</a>, with a quota of 50 per account. They are single-domain DV certificates issued by TrustAsia, with no wildcard support. These rules come from the China site (cloud.tencent.com); the international site may differ.</p>
<p>The quota is generous. The number of replacements is what adds up. With a 90-day certificate replaced two or three weeks early, each domain needs a new certificate four or five times a year. For a domain on CDN, that means applying, waiting for validation, and swapping the certificate in the CDN console every time.</p>
<p>CDN and EdgeOne work differently, so they are covered separately below.</p>
<h2>EdgeOne Only: Use Its Built-In Free Certificate</h2>
<p>If your domain is already on EdgeOne, the simplest option is to choose "Apply for free certificate" in the domain's HTTPS settings. According to the <a href="https://cloud.tencent.com/document/product/1552/90437">official documentation</a>, the certificate is issued by TrustAsia or Let's Encrypt, lasts 90 days, renews automatically 15 days before expiry, and deploys itself. There is nothing to maintain.</p>
<p>Its limits:</p>
<ul>
<li>The certificate cannot be downloaded and only works on EdgeOne. If your origin or load balancer needs a certificate for the same domain, you have to get one separately.</li>
<li>Wildcard certificates require DNS delegation validation. After a site switches from NS access to CNAME access, its existing wildcard certificate cannot renew automatically.</li>
<li>With CNAME access and automatic validation, the domain must point its CNAME to EdgeOne within an hour, and split-horizon (per-line) DNS is not allowed.</li>
<li>No SLA. Certificates issued by Let's Encrypt do not support OCSP stapling.</li>
</ul>
<p>If the certificate only ever lives on EdgeOne, none of this gets in your way. Use it and skip the rest of this article.</p>
<h2>Tencent Cloud CDN: Certificate Hosting Only Handles Replacement</h2>
<p>CDN has no one-click free certificate like EdgeOne. The usual flow is to get a certificate from the SSL Certificate Service and then deploy it to the CDN domain.</p>
<p>Tencent Cloud's <a href="https://cloud.tencent.com/document/product/400/55818">certificate hosting</a> covers half the work. Once enabled, when a new certificate is issued, it gets deployed at a time you choose to the cloud resources the old one was attached to, such as CDN and load balancers. Free certificates can be hosted too. The fully automatic setup in the docs is "auto-renewal plus hosting", and auto-renewal applies to paid certificates; the docs do not say that a free certificate will apply for its successor on its own. With free certificates, you still apply for a new one and complete validation every 90 days. Hosting only does the final swap.</p>
<p>Hosting has one more requirement: the old and new certificates must cover the same domains. Pick the wrong one and production is affected directly.</p>
<h2>Writing Your Own Script</h2>
<p>If you would rather not depend on the console, you can issue certificates yourself and deploy them through Tencent Cloud's API. Issuance is a solved problem: the <code>dns_tencent</code> plugin in acme.sh completes DNS validation through the DNSPod API and can get a wildcard certificate from Let's Encrypt.</p>
<p>Deployment is on you. The <code>deploy</code> directory in acme.sh has hooks for Alibaba Cloud CDN (<code>ali_cdn.sh</code>), Qiniu, and Baidu Cloud CDN, but none for Tencent Cloud. Calling the API yourself, you upload the certificate to the SSL Certificate Service to get a certificate ID, then bind it to CDN or EdgeOne:</p>
<pre><code class="language-text"># 1. Upload the certificate. With Repeatable=false, an identical certificate
#    is not uploaded twice; the existing ID is returned instead.
ssl.UploadCertificate
  CertificatePublicKey  = contents of fullchain.pem
  CertificatePrivateKey = contents of privkey.pem
  Repeatable            = false

# 2a. Tencent Cloud CDN: update only the certificate ID path
cdn.ModifyDomainConfig
  Domain = cdn.example.com
  Route  = Https.CertInfo.CertId
  Value  = {"update":"&lt;certificate ID from step 1&gt;"}

# 2b. EdgeOne: swap the certificate on the acceleration domain
teo.ModifyHostsCertificate
  ZoneId         = &lt;zone ID&gt;
  Hosts          = ["www.example.com"]
  Mode           = sslcert
  ServerCertInfo = [{"CertId":"&lt;certificate ID&gt;"}]
</code></pre>
<p>The CDN step is easy to get wrong. If you call <code>UpdateDomainConfig</code> with an <code>Https</code> object that contains only the certificate and private key, you run into this rule from the <a href="https://cloud.tencent.com/document/api/228/41116">API documentation</a>: for complex configuration items, "you must pass all properties of the object; properties not passed will use default values." In other words, HSTS, OCSP stapling, and TLS version restrictions that were enabled on the domain get reset to defaults on every renewal. <a href="https://cloud.tencent.com/document/product/228/94258">ModifyDomainConfig</a> updates a single path and leaves everything else unchanged, which makes it the safer call for swapping certificates.</p>
<p>Updating only <code>Https.CertInfo.CertId</code> assumes HTTPS is already enabled on the domain. If it is not, changing the certificate ID alone has no effect, and setting <code>Https.Switch</code> to on by itself is rejected because there is no certificate yet. In that case, set <code>Route</code> to <code>Https</code> and <code>Value</code> to <code>{"update":{"Switch":"on","CertInfo":{"CertId":"&lt;certificate ID&gt;"}}}</code>. Your script can check <code>Https.Switch</code> with <code>DescribeDomainsConfig</code> first and pick the right call.</p>
<p>Once the script works, you still need scheduling, retries, and alerting. Use a CAM sub-user for credentials, with permissions limited to DNSPod, SSL certificate upload, and CDN / EdgeOne configuration.</p>
<h2>Ways to Stop Replacing Certificates by Hand</h2>
<table>
<thead>
<tr>
<th>Option</th>
<th>Good for</th>
<th>Cost</th>
</tr>
</thead>
<tbody><tr>
<td>EdgeOne free certificate</td>
<td>EdgeOne only</td>
<td>No download, wildcard limits</td>
</tr>
<tr>
<td>SSL Service + hosting</td>
<td>Certificates on Tencent only</td>
<td>Free certs still applied by hand</td>
</tr>
<tr>
<td>acme.sh + your own script</td>
<td>Teams happy to own code</td>
<td>Deploy, retry, alerts all on you</td>
</tr>
<tr>
<td>Self-hosted Certimate</td>
<td>Fully open source setups</td>
<td>You deploy, upgrade, back up</td>
</tr>
<tr>
<td>Hosted automation service</td>
<td>Nothing to maintain</td>
<td>Cloud credentials held by them</td>
</tr>
</tbody></table>
<p><a href="https://github.com/certimate-go/certimate">Certimate</a> is an MIT-licensed open-source project. Once self-hosted, it issues certificates and deploys them to Tencent Cloud CDN, EdgeOne, CLB, COS, and more, along with Alibaba Cloud and other providers. Certificates, private keys, and cloud credentials stay on your own server; the trade-off is that you maintain that server and Certimate itself.</p>
<p>With only one or two CDN domains, replacing certificates by hand looks manageable. But four or five times a year, someone has to remember every time, and eventually nobody will. If you can automate it for free, it is worth setting up even for a few domains.</p>
<h2>Auto-Renewing and Deploying to Tencent Cloud with LapseZero</h2>
<p><a href="https://lapsezero.com/?utm_source=hashnode&amp;utm_medium=article&amp;utm_campaign=tencent-cdn-cert">LapseZero</a> is a hosted certificate automation service. It issues certificates from Let's Encrypt, renews them before expiry, and deploys them to cloud products on Alibaba Cloud, Tencent Cloud, and AWS, or to your own servers. On Tencent Cloud it currently supports CDN, EdgeOne, and HTTPS listeners on CLB load balancers.</p>
<ol>
<li><strong>Add the domain.</strong> If DNS is on DNSPod, provide keys for a CAM sub-user with DNS permissions only, and the platform writes the validation records. If you would rather not hand over DNS access, use DNS delegation, which only needs CNAME records added once, when you add the domain. The differences are covered in <a href="https://lapsezero.com/blog/http-01-vs-dns-01-vs-dns-delegation?utm_source=hashnode&amp;utm_medium=article&amp;utm_campaign=tencent-cdn-cert">HTTP-01 vs DNS-01 vs DNS delegation</a>.</li>
<li><strong>Issue the certificate.</strong> Wildcards are supported, and Tencent Cloud's 50-certificate quota is not touched.</li>
<li><strong>Add deploy targets.</strong> The platform lists the CDN domains and EdgeOne acceleration domains in your account; select the ones that match the certificate. The same certificate can go to CDN, CLB, and your own servers at once.</li>
<li><strong>Renew automatically.</strong> By default it renews 30 days before expiry and deploys to every target after issuance. Each target's result is recorded separately, and failures are sent to you by email, Slack, Telegram, or other channels.</li>
</ol>
<p>Two things to know. A successful deployment means Tencent Cloud's API accepted the new certificate; the platform does not visit the domain afterwards to confirm it is live, and CDN edge nodes take time to pick it up, so check it a little later with the <a href="https://lapsezero.com/tools/ssl-certificate-expiry-checker?utm_source=hashnode&amp;utm_medium=article&amp;utm_campaign=tencent-cdn-cert">SSL certificate expiry checker</a>. Your cloud credentials are stored by the platform, so use a CAM sub-user with minimal permissions. The free plan includes 3 domains and 5 deploy targets.</p>
<p>Certificate lifetimes keep shrinking: from March 15, 2027, every public certificate maxes out at 100 days, and 47 days from 2029, paid certificates included. See <a href="https://lapsezero.com/blog/47-day-ssl-certificates?utm_source=hashnode&amp;utm_medium=article&amp;utm_campaign=tencent-cdn-cert">47-day SSL certificates</a>.</p>
]]></content:encoded></item><item><title><![CDATA[47-Day SSL Certificates: Renewing More Often Without Breaking Production]]></title><description><![CDATA[SSL certificates drop to 100 days in 2027 and 47 in 2029. The SC-081 schedule, why each swap risks a bad reload, and how to roll back failed deploys.]]></description><link>https://lapsezero.hashnode.dev/47-day-ssl-certificates-renewing-more-often-without-breaking-production</link><guid isPermaLink="true">https://lapsezero.hashnode.dev/47-day-ssl-certificates-renewing-more-often-without-breaking-production</guid><category><![CDATA[SSL]]></category><category><![CDATA[Security]]></category><category><![CDATA[Devops]]></category><category><![CDATA[nginx]]></category><dc:creator><![CDATA[Fizee]]></dc:creator><pubDate>Mon, 05 Oct 2026 03:29:25 GMT</pubDate><enclosure url="https://cdn.hashnode.com/uploads/covers/6abfaa42302f6644ca27b3e9/5ede1fc2-4fd6-4325-be5a-2349f636cce4.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>From March 15, 2029, a publicly trusted SSL certificate can be valid for at most 47 days. The step before that, 100 days, starts on March 15, 2027, and the first step is already behind us: certificates issued since March 15, 2026 are capped at 200 days.</p>
<p>A certificate you used to replace once a year will need replacing at least 4 times a year in 2027 and roughly every month in 2029. Every replacement ends with a reload, and a reload is exactly the operation most people running servers would rather not do often.</p>
<h2>The schedule</h2>
<p>The CA/Browser Forum adopted <a href="https://cabforum.org/2025/04/11/ballot-sc081v3-introduce-schedule-of-reducing-validity-and-data-reuse-periods/">Ballot SC-081v3</a> in April 2025. Every publicly trusted CA has to follow it, so paid certificates are affected too:</p>
<table>
<thead>
<tr>
<th>Effective</th>
<th>Max validity</th>
<th>Validation reuse</th>
</tr>
</thead>
<tbody><tr>
<td>2026-03-15</td>
<td>200 days</td>
<td>200 days</td>
</tr>
<tr>
<td>2027-03-15</td>
<td>100 days</td>
<td>100 days</td>
</tr>
<tr>
<td>2029-03-15</td>
<td>47 days</td>
<td>10 days</td>
</tr>
</tbody></table>
<p>The third column gets less attention. Once a CA has validated that you control a domain, it can reuse that result for a while instead of validating again for the next certificate. By 2029 that window is 10 days, so almost every certificate will need fresh domain validation. If you still buy certificates and validate them by email or by uploading a file, you will be doing that every month.</p>
<h2>When it was once a year, the problem was remembering</h2>
<p>A yearly renewal is hard to schedule. Set a phone reminder for a year from now and there is a fair chance you will have a different phone by then. Calendars and ticket queues are not much better, since a year is long enough for the person who owned the task to move on.</p>
<p>If you relied on Let's Encrypt's expiry emails as a safety net, those <a href="https://letsencrypt.org/2025/06/26/expiration-notification-service-has-ended">stopped on June 4, 2025</a>.</p>
<p>So expiry is often discovered by users. A pattern we ran into fairly often: customers on our mobile client reported a "network error" and nothing mentioned certificates. Native apps and embedded webviews often hide TLS failures behind a generic message like that. The server logs had no record of those requests at all, because the client gave up during the TLS handshake and never reached Nginx.</p>
<p>When a client reports network errors and your server logs show nothing, check the certificate first:</p>
<pre><code class="language-bash">echo | openssl s_client -connect example.com:443 -servername example.com 2&gt;/dev/null \
  | openssl x509 -noout -enddate
</code></pre>
<p>Or run the domain through the <a href="https://lapsezero.com/tools/ssl-certificate-expiry-checker?utm_source=hashnode&amp;utm_medium=article&amp;utm_campaign=47-day-cert">SSL certificate expiry checker</a> without logging in to anything.</p>
<h2>At 100 days, the problem is the reload</h2>
<p>We used to run most certificates directly on cloud VMs and later moved many of them to a CDN. Swapping a certificate on a CDN is an upload. No SSH, no service restart.</p>
<p>On a server, the uncomfortable part is the reload, for two reasons:</p>
<ol>
<li>You are not sure whether someone changed the Nginx config since the last reload. A broken config sits there quietly until the next reload, and that reload happens to be the one you ran to swap a certificate.</li>
<li>Some servers have not been touched in months. Reloading or restarting them out of the blue is the kind of thing that surfaces problems nobody knew about.</li>
</ol>
<p>Once a year, you can live with that risk. At 100 days, every server faces it 4 or 5 times a year; at 47 days, every month. The CA/Browser Forum's reasoning is sound: revocation does not work well in practice, so a shorter lifetime limits how long a leaked key stays useful. For the people doing the swaps, it is still more work and more risk.</p>
<h2>Why many admins still swap by hand</h2>
<p>Plenty of people decide not to script it, and their reasons are specific:</p>
<ul>
<li>Servers and configs change over time. A script that was not updated along with them can do more damage than a manual swap.</li>
<li>When you swap by hand, you know when it happened and you test it yourself afterwards. A script can fail at 3 a.m. when nobody is around to deal with it.</li>
</ul>
<p>These concerns are fair. The tooling for issuance and renewal is mature: certbot and acme.sh renew on a schedule and can run a reload hook, Caddy handles certificates on its own, cert-manager renews them inside Kubernetes, and AWS Certificate Manager renews the certificates it issues for services like CloudFront and ALB. If everything you run fits one of these, you may not need anything else.</p>
<p>The gaps show up with a mix of servers and cloud services. certbot has no failure notifications, and acme.sh has notification hooks you have to configure yourself. Pushing a certificate to a CDN or load balancer outside those integrations usually means writing your own script against the provider's API, and that script is exactly the part that breaks when the environment changes.</p>
<p>Doing it by hand is a reasonable choice today. At 100 days the number of manual swaps stops being manageable, so automation has to win the same trust the manual process has.</p>
<h2>The bar for automation: it can fail, but it must not touch production</h2>
<p>The standard we hold automation to is a single rule: it can fail, but it must never take production down. Either the swap succeeds completely, or nothing changes.</p>
<p>A failed issuance or a failed deploy is fine. If certificates renew 30 days before expiry, a failure leaves weeks to fix it, and a failure at 3 a.m. is just a message to read in the morning. What is not fine is a half-finished swap that breaks the live service.</p>
<p>Services only reread certificate files on reload or restart. That means a deploy cannot hurt production as long as you do the following:</p>
<ol>
<li>Before replacing anything, confirm the new certificate and private key match.</li>
<li>Back up the old files, then overwrite in place. Writing with <code>cat &gt;</code> keeps the file's owner, permissions, and symlinks; writing a temp file and <code>mv</code>-ing it over the original replaces all three.</li>
<li>Run <code>nginx -t</code> before reloading. If the check fails, restore the old files and skip the reload.</li>
<li>Make sure a failure reaches a person.</li>
</ol>
<p>If you swap certificates on your own servers, this script is a starting point:</p>
<pre><code class="language-bash">#!/usr/bin/env bash
set -euo pipefail

CERT=/etc/nginx/ssl/example.com.pem
KEY=/etc/nginx/ssl/example.com.key
NEW_CERT=$1
NEW_KEY=$2

# The certificate and the key must share the same public key
if [ "$(openssl x509 -noout -pubkey -in "$NEW_CERT" | openssl sha256)" != \
     "$(openssl pkey -pubout -in "$NEW_KEY" | openssl sha256)" ]; then
  echo "Certificate and key do not match, nothing changed" &gt;&amp;2
  exit 1
fi

cp -a "$CERT" "$CERT.bak"
cp -a "$KEY" "$KEY.bak"

if cat "$NEW_CERT" &gt; "$CERT" &amp;&amp; cat "$NEW_KEY" &gt; "$KEY" \
   &amp;&amp; nginx -t &amp;&amp; systemctl reload nginx; then
  echo "Replaced"
else
  cat "$CERT.bak" &gt; "$CERT"
  cat "$KEY.bak" &gt; "$KEY"
  echo "Replacement failed, old certificate restored" &gt;&amp;2
  exit 1
fi
</code></pre>
<p>The script exits non-zero on failure. Pair it with cron's <code>MAILTO</code>, or post to a Slack or Telegram webhook in the <code>else</code> branch, and someone will hear about it. For services that need a restart, such as Tomcat, restart again after restoring the old files, or the service stays down.</p>
<p>Managed services are simpler. On CloudFront, for example, the new certificate is imported into ACM first, and the distribution switches to it in a single update call. If that call fails, the distribution keeps serving the old certificate, so there is no half-swapped state.</p>
<h2>If you would rather not maintain the script</h2>
<p>You can hand it to <a href="https://lapsezero.com/?utm_source=hashnode&amp;utm_medium=article&amp;utm_campaign=47-day-cert">LapseZero</a>. It issues certificates from free CAs such as Let's Encrypt, renews them before they expire, and deploys them to your servers or to AWS, Alibaba Cloud, and Tencent Cloud services such as CDNs and load balancers.</p>
<p>On servers, it does roughly what the script above does: back up the existing files, write everything before running the post-deploy command, and restore the old files if a write fails. If the post-deploy command fails, it restores the files and runs the command once more to bring the service back on the old certificate, then tells you "rolled back, the old certificate is still live" and waits for you to check the cause before retrying. Including <code>nginx -t</code> in the post-deploy command is recommended here as well.</p>
]]></content:encoded></item></channel></rss>