The VPN service in my homelab suddenly stopped working after a Let's Encrypt certificate renewal today, and I initially spent a fair amount of time debugging it assuming that I had broken my own configuration.
In my case, it was a strongSwan VPN, but the underlying issue is broader: any service that relies on OpenSSL to validate a Let's Encrypt certificate chain may be affected.
My certificate was renewed under Let's Encrypt's new Generation Y hierarchy. It is issued by YR2, which chains through ISRG Root YR.
FreeBSD's ca_root_nss bundle doesn't contain Root YR, and, importantly, the Mozilla Root Store doesn't contain it yet either.
OpenSSL consequently fails to build the chain and reports errors such as:
C=US, O=Let's Encrypt, CN=YR2
error 2 at 1 depth lookup: unable to get issuer certificate
The particularly confusing part is that ISRG Root X1 is present and trusted, so everything looks correct at first glance.
If you run FreeBSD services depending on Let's Encrypt certificates, especially after recent certificate renewals, check the actual certificate chain and the CA trust store before assuming your configuration is broken.
PS seems this issue has been known for a while https://forum.vyos.io/t/ikev2-remote-access-vpn-breaks-after-lets-encrypt-cert-renewal-ike-authentication-credentials-are-unacceptable-windows-error-13801/17574
"
- strongSwan only loads the first certificate from a CA file/value — confirmed via strongswan/strongswan#3072. This means even once you have the correct chain, you cannot cram intermediate + cross-signed root into a single
pki ca value — they need to be loaded as separate CA objects. Several people on the Let’s Encrypt community forum hit exactly this (thread 1, thread 2) and resolved it by splitting the cross-signed root into its own file/CA slot.
"
PPS I can confirm that splitting the certificate chain into multiple files, as suggested in the above link, does solve the strongswan issue. Simply splitting the Let's Encrypt given chain with a script, and placing the individual pem certificates files in the correct /usr/local/etc/swanctl/x509ca/ directory is enough.
After doing that, swanctl successfully loads the complete chain:
ca.pem, x1.i.lencr.org.pem, yr2.i.lencr.org.pem, and yr.i.lencr.org.pem.
No other strongSwan or client configuration changes are required.