6.5.28 OpenVPN

Run the agent on the OpenVPN host, update client trust once, and point it at the right config

CertKit has three OpenVPN templates. Each one runs on the OpenVPN host itself, so install the CertKit Agent there.

Template Agent What it replaces
OpenVPN Community Edition Server Linux The server certificate and key in the OpenVPN server config. Restarts the systemd unit.
OpenVPN Community Edition Server Windows The server certificate and key in the .ovpn server profile. Restarts the OpenVPN Windows service.
OpenVPN Access Server: Web Services Certificate Linux The web certificate for the Admin Web UI, the Client Web UI, and profile downloads. The VPN tunnel isn’t changed.

All three accept either PEM format: the certificate with its chain plus a key file, or a separate chain file.

OpenVPN Community Edition

Requirements

  • OpenVPN Community Edition running as a server on the agent host.
  • On Linux, the agent runs as root. On Windows, it needs administrator rights. The template edits the server config and restarts the service.
  • The config must use separate cert and key directives or inline <cert> and <key> blocks. A config that uses pkcs12 is refused.
  • On Linux, openssl should be installed. Without it, the template can’t check that the key matches the certificate.
  • On Linux, systemd is expected. Without it, the template restarts with service openvpn restart and can’t confirm that OpenVPN started.

Update client trust before the first deployment

The template replaces only the server certificate and key. The server’s ca (which checks client certificates), tls-auth or tls-crypt key, and every other directive stay as they are, so client certificates keep working.

The clients are what change. An OpenVPN client trusts only the CA in its profile’s ca file or <ca> block, usually the Easy-RSA CA that signed the original server certificate. It ignores the operating system’s trust store. If the new certificate comes from a different CA, clients fail verification and can’t connect.

Before the first deployment:

  1. Add the root of the new certificate to every client profile’s ca. You can keep the old CA in the same file during the switch, since ca accepts several certificates.
  2. If client profiles use verify-x509-name with the old name (for example server), change it to the name on the new certificate.
  3. If you add a public root, also add verify-x509-name with your server’s name. OpenVPN doesn’t check the hostname, and remote-cert-tls server accepts any server certificate that root has signed. A CertKit private CA that signs only your VPN servers avoids this.

Renewals after the switch come from the same root, so the clients need no further changes.

Variables

Both variables default to auto and are hidden in easy mode. Set them in the Advanced view when you run more than one server instance or use a custom layout.

Agent Variable What to enter
Linux OpenVPN server config file Full path to the server config, for example /etc/openvpn/server/server.conf, or a bare instance name such as server.
Linux systemd unit to restart The unit that runs that config, for example openvpn-server@server.
Windows OpenVPN server profile (.ovpn) Full path to the server profile, for example C:\Program Files\OpenVPN\config-auto\server.ovpn, or a bare profile name.
Windows OpenVPN Windows service OpenVPNService for profiles in config-auto, or OpenVPNServiceLegacy for profiles in config.

With auto on Linux, the template looks at the active openvpn systemd units. openvpn-server@<name> maps to /etc/openvpn/server/<name>.conf and openvpn@<name> maps to /etc/openvpn/<name>.conf. Other units are read from the --config argument in their ExecStart. Client units (openvpn-client@) are skipped. If no unit is running, it looks for .conf files in /etc/openvpn/server and /etc/openvpn.

With auto on Windows, the template reads the install locations from HKLM\SOFTWARE\OpenVPN and uses the single profile in the automatic-start folder, normally C:\Program Files\OpenVPN\config-auto.

If auto finds more than one server config, the deployment stops and lists them. Set the config variable to the right one.

What happens on each deployment

  1. Find the config and service. The template resolves the config path and the systemd unit or Windows service, and checks that the unit or service exists.
  2. Check the new certificate. It confirms the files hold a PEM certificate and an unencrypted PEM key. On Linux it also checks that the key matches the certificate. It warns when the certificate isn’t marked for TLS server use, because clients with remote-cert-tls server reject it.
  3. Write the files. The server certificate and every distinct intermediate go into one file, certkit-<config name>.crt, next to the config. The key goes into certkit-<config name>.key. OpenVPN sends every certificate after the first as the chain, so extra-certs isn’t needed. On Linux, the certificate file is mode 644, the key is mode 600, and both keep the owner of the files the config used before.
  4. Update the config. The cert and key directives are pointed at the new files. Inline <cert> and <key> blocks are replaced with directives, <extra-certs> blocks are removed, and extra-certs and cryptoapicert lines are commented out with a # certkit: prefix. The original config is saved as <config>.certkit-bak. Nothing is written when the config already points at the CertKit files.
  5. Restart and confirm. If nothing changed, the restart is skipped. Otherwise the template restarts OpenVPN and watches for startup.
    • On Linux, it watches the unit and its journal for up to 20 seconds. “Initialization Sequence Completed” is success. “Exiting due to fatal error” or a stopped unit is failure. A unit that is still running after 20 seconds is accepted.
    • On Windows, it restarts the service (or starts it if it was stopped), then reads the profile’s log in the OpenVPN log folder for up to 60 seconds. “Initialization Sequence Completed” is success. Errors such as “Cannot load certificate file” or “Private key does not match” are failure.

The Easy-RSA certificate and key the config used before stay on disk, unreferenced.

Rollback

When OpenVPN fails to start on the new certificate, the template restores the config from the backup, puts back the previous certkit- files (or deletes them on a first deployment), and restarts OpenVPN again. The job then fails with “Deployment rolled back; OpenVPN is running the previous certificate.”

On Windows, if the log shows neither success nor a known error within 60 seconds, the template doesn’t roll back. The new files stay in place and the job fails with the path to the backup. Check the log, and copy <profile>.certkit-bak back over the profile if you need to undo the change.

Restarts and disconnects

Restarting OpenVPN disconnects every connected client. Clients reconnect on their own. On Windows, restarting OpenVPNService restarts every profile in config-auto, not only the one this template changed. Use a deploy window to keep restarts outside working hours.

OpenVPN Access Server

Requirements

  • OpenVPN Access Server on Linux, with sacli at /usr/local/openvpn_as/scripts/sacli.
  • The agent runs as root on the Access Server host.
  • python3 must be available to read the current configuration. Access Server 3 runs on the system python3. Without it, a rollback can only return to Access Server’s self-signed certificate.
  • openssl must be installed to confirm the web port serves the new certificate. Without it, the template applies the certificate but can’t verify it.
  • If you turned on Access Server’s built-in ACME client, turn it off by setting acme.enable to false. Otherwise it replaces the CertKit certificate at its next renewal.

The template has been tested on a standalone Access Server. It changes only the node it runs on. Access Server clusters haven’t been tested.

What it replaces

The template sets the web services certificate, stored in the cs.cert, cs.priv_key, and cs.ca_bundle keys of the Access Server configuration. That certificate serves the Admin Web UI, the Client Web UI, and profile downloads on the web port (cs.https.port, 943 by default).

The VPN tunnel uses Access Server’s internal CA, and every connection profile it issues trusts that CA. The template doesn’t touch it, so existing client profiles keep working.

What happens on each deployment

  1. Find Access Server. The template locates sacli and reads the version and web port.
  2. Check the new certificate. It splits the certificate into the server certificate and an intermediate bundle, then runs Access Server’s own sacli TestWebCerts check. The template prints the findings but never the raw output, which echoes the private key.
  3. Compare with what’s installed. It reads the current cs.cert, cs.priv_key, and cs.ca_bundle and keeps them for rollback. If they already match, it stops without changing anything.
  4. Store the new certificate. sacli ConfigPut writes the key, the certificate, and the bundle. With no intermediates, cs.ca_bundle is removed.
  5. Apply and verify. sacli start restarts the web service. The VPN daemons keep running, so connected VPN sessions stay up. The template then connects to 127.0.0.1 on the web port for up to 30 seconds and checks that it serves the new certificate’s SHA-1 fingerprint.

Rollback

If sacli start fails or the web port doesn’t serve the new certificate within 30 seconds, the template restores the previous values (or removes them, which returns Access Server to its self-signed certificate) and runs sacli start again.

Common problems

Community Edition

  • “No OpenVPN server config found”: no active OpenVPN unit and no .conf file in the standard folders. Set OpenVPN server config file to the config path.
  • “Found more than one OpenVPN server config” or “Found more than one profile”: set OpenVPN server config file or OpenVPN server profile (.ovpn) to the one this certificate is for.
  • “Could not derive the systemd unit” or “systemd unit ‘…’ is not loaded”: set systemd unit to restart to the unit that runs the config.
  • “Windows service ‘…’ was not found”: set OpenVPN Windows service to OpenVPNService or OpenVPNServiceLegacy, whichever runs the profile.
  • “… uses a pkcs12 bundle for its CA, certificate and key”: split the PKCS#12 file into separate ca, cert, and key directives, then deploy again.
  • “The private key in … does not match the certificate”: the deployed files don’t belong together. Reissue the certificate in CertKit.
  • “Could not read the private key in … (is it encrypted?)” or “is password-protected; OpenVPN needs an unencrypted key file”: the template only installs unencrypted keys. CertKit writes the key without a password, so check that the deployment uses the CertKit key file.
  • “WARNING: the certificate is not marked for TLS server use”: the certificate lacks the TLS server usage, and clients with remote-cert-tls server will reject it. Issue a server certificate.
  • “Deployment rolled back; OpenVPN is running the previous certificate”: OpenVPN wouldn’t start on the new certificate. The log lines printed above the error show why.
  • “Could not confirm ‘Initialization Sequence Completed’ … within 60 seconds” (Windows): the template couldn’t find the success line in the profile’s log. Check that log, and check the log_dir value under HKLM\SOFTWARE\OpenVPN.
  • Clients fail with VERIFY ERROR after a successful deployment: their profiles don’t trust the new certificate’s root, or verify-x509-name still names the old certificate. See Update client trust before the first deployment.

Access Server

  • “OpenVPN Access Server not found”: sacli is missing. Use the Community Edition template for a plain openvpn install.
  • “Access Server rejected the certificate (TestWebCerts failed)”: the findings printed above the error say why, for example a key that doesn’t match or a chain that doesn’t link up. Nothing was changed.
  • “sacli ConfigPut … failed”: Access Server couldn’t store the value. Run sacli ConfigQuery as root to confirm the configuration database is reachable.
  • “Deployment rolled back; the web service did not pick up the new certificate”: the web port kept serving a different certificate for 30 seconds. Check cs.https.port, and check that nothing else on the host answers on that port.
  • The certificate changes back on its own later: Access Server’s ACME client is turned on. Set acme.enable to false.

For a product overview, see certificate automation for OpenVPN.