TLS: what you can tune
📌 TLS examples below use ./certs/ in the working directory. Supply your own certificate, matching private key, or client CA file there; validation reads these files too.
Pingclair obtains certificates for site names automatically. This page covers certificate sources, HTTP/3, and client certificate authentication. Unsupported TLS options are rejected when the configuration loads.
📌 This page describes v0.2.2.
🧾 Before you start
Section titled “🧾 Before you start”- Pingclair installed and running (Install).
- For the certificate-authority parts, a name that resolves to the host, or the internal authority for a lab machine (HTTPS).
🌐 Which protocols are served
Section titled “🌐 Which protocols are served”Configure protocols in the global servers block:
{ servers { protocols h1 h2 h3 }}Measured with sudo ss -lun | grep ':443 ':
| Configuration | UDP 443 listener |
|---|---|
protocols h1 h2 |
0 — no HTTP/3 |
protocols h1 h2 h3 |
1 — HTTP/3 enabled |
⚠️ The list controls HTTP/3 only. Listing h1 alone does not
turn HTTP/2 off: with protocols h1, a client that offered h2 still
negotiated HTTP/2. The only thing the server reads from the list is whether h3
is in it, so no setting disables HTTP/2. Without a protocols line, HTTP/3 is
on.
The per-site http3 off option disables HTTP/3 for that site while the QUIC
listener continues serving other sites:
https://internal.test { tls { internal http3 off } file_server /srv/site}http3 off refuses this site’s QUIC handshake and removes its HTTP/3 advertisement from Alt-Svc. Other sites on the port may continue to use QUIC.
🏛️ Certificate sources
Section titled “🏛️ Certificate sources”Three sources, all shown on the HTTPS page:
| Source | Configuration | What it is for |
|---|---|---|
| Let’s Encrypt | a bare public name | Public names, renewed in the background. |
| Internal authority | tls internal |
Lab names, private origins, tunnels. |
| Your own files | tls { cert … key … } |
Certificates issued elsewhere. |
Renewal runs in the background. The global renewal_window_ratio option sets
how early it starts, as a fraction of each certificate’s lifetime.
🔐 Client certificates
Section titled “🔐 Client certificates”client_auth configures the server to request a client certificate. Create a small
authority and a client certificate with openssl, then point the site at the
authority’s certificate file:
https://internal.test { tls { internal client_auth { mode require_and_verify trusted_ca_cert_file ./certs/client-ca.crt } } file_server /srv/site}Measured: a request without a client certificate fails the handshake, and the
same request with --cert client.crt --key client.key answers 200.
The modes are request, require, verify_if_given, and
require_and_verify. A misspelled mode is refused with the whole list
(expected request, require, verify_if_given or require_and_verify).
⚠️ trusted_ca_cert takes the certificate itself, base64-encoded on one line,
and trusted_ca_cert_file takes a path. Giving a path to the first compiles,
then fails at startup with trusted_ca_cert is not a certificate: not valid base64: Invalid symbol 45
— the - of -----BEGIN. The file also has to be readable by the pingclair
user.
An exact site’s client_auth policy takes precedence over a wildcard on the same port. An exact site with no block requires no client certificate; add its own block if it must require one. Certificates whose usage extensions exclude client authentication are refused.
📦 Moving the certificate store
Section titled “📦 Moving the certificate store”The store contains the issued certificates, the ACME account, and the internal
authority. For a package install it is /var/lib/pingclair/.local/share/pingclair,
the data directory under the service account’s home. A command run as another
user looks in that user’s own data directory, so the examples set
PINGCLAIR_TLS_STORE; without it, root would use /root/.local/share/pingclair.
storage-export and storage-import move the store:
sudo PINGCLAIR_TLS_STORE=/var/lib/pingclair/.local/share/pingclair pingclair storage-export -o /tmp/store.tarsudo systemctl stop pingclairsudo rm -rf /var/lib/pingclair/.local/share/pingclairsudo mkdir -p /var/lib/pingclair/.local/share/pingclair && sudo chown pingclair:pingclair /var/lib/pingclair/.local/share/pingclairsudo PINGCLAIR_TLS_STORE=/var/lib/pingclair/.local/share/pingclair pingclair storage-import -i /tmp/store.tarsudo systemctl start pingclair✅ Store exported to /tmp/store.tar✅ Store imported into /var/lib/pingclair/.local/share/pingclairThe archive is an uncompressed tar, regardless of its filename,
written with mode 600, so reading it back needs root. The import restores the
ownership recorded in the archive. The store also contains autosave.json, the
configuration the Admin API last applied, so an import restores that too.
📌 0.2.0: the internal authority uses Caddy’s directory layout, under
pki/authorities/local/. The old internal/ directory is not migrated: the
server creates a new authority, and every client must trust the new root
again (pingclair trust). A global storage file_system <path> option can also
name the store in the configuration.
If the service refuses to start afterwards with
Internal CA I/O error: Permission denied, the store’s files are not writable by
the service account; sudo chown -R pingclair:pingclair /var/lib/pingclair/.local/share/pingclair
restores the required ownership.
🚫 Unsupported TLS options
Section titled “🚫 Unsupported TLS options”The following Caddy TLS options are recognized but rejected during configuration loading:
Caddy-compatible directive 'tls ciphers' is not supported by Pingclair yet: Pingclair does not implement this TLS option yetCaddy-compatible directive 'tls curves' is not supported by Pingclair yet: Pingclair does not implement this TLS option yetCaddy-compatible directive 'tls alpn' is not supported by Pingclair yet: Pingclair does not implement this TLS option yetCaddy-compatible directive 'tls on_demand' is not supported by Pingclair yet: Pingclair does not implement this TLS option yetCipher suites, curves, the ALPN list, and on-demand issuance are therefore fixed by the build, not by the configuration. OCSP stapling is not performed either. These settings cannot be enabled through configuration.
⚠️ Troubleshooting
Section titled “⚠️ Troubleshooting”client_authrefuses to start withnot valid base64. A path was given totrusted_ca_cert; the file spelling istrusted_ca_cert_file.- A client with a valid certificate is rejected. Check the CA that signed it
is the one in
trusted_ca_cert_file, and that the certificate has not expired. tls ciphers/tls curves/tls alpn/tls on_demandrefuse the file. They are not implemented; see the section above.- HTTP/3 still runs after
protocols h1 h2. It should not, because that list controls it. If UDP 443 is still listening, the file that is running is not the file you edited (what a reload means). - The service will not start after moving a store. Ownership, as above.
