Linux service targets¶
Agent 1.5.0 and later can deploy a renewed certificate to HAProxy, Caddy, Traefik, LiteSpeed, Postfix, Dovecot, PostgreSQL and MySQL on Linux, in addition to the NGINX, Apache httpd and Tomcat types of the terminal interface.
Not run on a real Linux host yet
The starter hooks were tested with generated scripts, golden files and stand-in commands, not run as root on a real Linux host against these services. Read the generated script before the first renewal and try it on a test host.
How it works¶
The Agent service runs unprivileged: it cannot write into /etc/haproxy or
reload a service itself. For these targets it uses the
root hook runner:
- The Agent saves the certificate as PEM files with an unencrypted key into its own folder (one the service may write; the terminal interface prepares it).
- A
hook.runstep asks the root hook runner to run the starter hook/etc/certintel/hooks.d/certintel-<kind>.sh(owned byroot:root, mode0700). - The hook installs the files where the service reads them, with the service's owner, group and mode, runs the configuration test and reloads the service.
The hook is an ordinary shell script; the paths, owner, group, mode and
commands are written into it and you can edit them. The configuration test
runs before the reload, so a mistake stops the script and the running service
keeps its current certificate. An existing hook is
never replaced: to start again, remove it first. Its output is in
journalctl -t certintel-agent-hooks.
Targets¶
$ID stands for the certificate ID ($CERTINTEL_CERTIFICATE_ID). The paths
are the defaults the terminal interface fills in; change them to what your
service reads.
| Kind | Installed files (default) | Owner:group | Key / certificate mode | Configuration test | Reload |
|---|---|---|---|---|---|
haproxy |
/etc/haproxy/certs/$ID.pem (one combined file: full chain and key) |
root:haproxy |
0640 |
haproxy -c -f /etc/haproxy/haproxy.cfg |
systemctl reload haproxy |
caddy |
/etc/caddy/certs/$ID.crt, $ID.key |
caddy:caddy |
0600 / 0644 |
caddy validate --config /etc/caddy/Caddyfile |
systemctl reload caddy |
traefik |
/etc/traefik/certs/$ID.crt, $ID.key |
root:traefik |
0640 / 0640 |
none | none - Traefik's file provider picks up the new files by itself |
litespeed |
/usr/local/lsws/conf/$ID.crt, $ID.key |
lsadm:lsadm |
0600 / 0600 |
/usr/local/lsws/bin/openlitespeed -t (when present) |
/usr/local/lsws/bin/lswsctrl restart (graceful) |
postfix |
/etc/postfix/certintel-fullchain.pem, certintel-key.pem |
root:root |
0600 / 0644 |
postfix check |
postfix reload |
dovecot |
/etc/dovecot/certintel-fullchain.pem, certintel-key.pem |
root:root |
0600 / 0600 |
doveconf -n |
doveadm reload |
postgresql |
/etc/postgresql/certintel-server.crt, certintel-server.key |
postgres:postgres |
0600 / 0644 |
none | systemctl reload postgresql |
mysql |
/etc/mysql/certintel-cert.pem (certificate only), certintel-key.pem, certintel-ca.pem (chain) |
mysql:mysql |
0600 / 0600 |
none | mysql --protocol=socket -e "ALTER INSTANCE RELOAD TLS" (MySQL 8.0.16 and later), or systemctl restart mysql |
The files must not be writable by other users; the hook builder refuses such a mode.
Point the service at the files¶
The hook only installs the files. Configure the service once to read them, for example:
| Kind | Configuration |
|---|---|
haproxy |
bind :443 ssl crt <file> (or crt <folder>) |
caddy |
tls <certificate> <key> in the site block |
traefik |
tls.certificates certFile/keyFile in a file-provider configuration; the provider watches it |
litespeed |
certFile, keyFile and certChain 1 in the listener or the virtual host's vhssl block |
postfix |
smtpd_tls_chain_files = <key>, <certificate> in main.cf |
dovecot |
ssl_cert = <<certificate> and ssl_key = <<key> in the Dovecot configuration |
postgresql |
ssl_cert_file and ssl_key_file in postgresql.conf |
mysql |
ssl_cert, ssl_key and ssl_ca in the [mysqld] section |
Server detection can read the current paths from an existing HAProxy or LiteSpeed configuration and pre-fill them.
In the terminal interface¶
Run sudo certintel tui, press a on the Workflows screen and choose the
service in Type on the deployment page. The page pre-fills the target
paths, owner, group, mode and the test and reload commands from the table
above; you can change each one. A service type always saves an unencrypted,
owner-only key, because the service cannot read a password-protected one.
When you save, the terminal interface prepares the Agent's folder and writes
the starter hook as root. S (post-renewal scripts) also offers each starter
as Install for
From the command line¶
certintel hooks starter KIND [--write] prints the starter hook
certintel-KIND.sh for one of haproxy, caddy, traefik, litespeed,
postfix, dovecot, postgresql or mysql, or with --write (as root)
writes it to /etc/certintel/hooks.d and prints Wrote … (root:root, mode
0700). Check the paths, owner and commands in it before the first renewal.
Exit codes: 0 success, 1 the script could not be written (for example
script … already exists; edit it, or remove it first to start again), 2
invalid usage or not root.
Dashboard-assigned workflows¶
The catalogue templates haproxy-standard, caddy-standard,
traefik-standard, litespeed-standard, postfix-standard,
dovecot-standard, postgresql-standard and mysql-standard, shown as
/etc/certintel/certs/haproxy), Filename prefix (default
certificate) and, for HAProxy, Caddy, Traefik and LiteSpeed,
Verification hostname and Verification port (443) for an endpoint
check after the reload.
An assignment cannot create a script. Before you assign one of these templates, on the host:
- Install the starter hook:
sudo certintel hooks starter KIND --write, or create the workflow once insudo certintel tui. Until the hook exists the Agent refuses the assignment with starter hook certintel-KIND.sh is not installed; run certintel hooks starter KIND --write as root. - Prepare the Agent folder so the Agent may write it, once, with
sudo certintel tui. The Agent does not check this when the assignment arrives; a folder it cannot write makes the first deployment fail.
The existing nginx-standard and apache-standard catalogue templates are
unchanged; for NGINX and Apache httpd prefer the terminal interface types,
which reload through the hook runner.