> ## Documentation Index
> Fetch the complete documentation index at: https://certplane.kippel.org/llms.txt
> Use this file to discover all available pages before exploring further.

# Reload services automatically after certificate renewal

> Use reload_command in the agent config to restart or reload services automatically whenever Certplane renews and writes a certificate to disk.

Certplane's agent can run a shell command immediately after writing a renewed certificate to disk. Use this to reload your web server, proxy, or any service that reads certificates at startup or on SIGHUP — no cron jobs or external watchers required.

## How it works

Each entry in the `certificates` list in `agent.yml` accepts two reload-related fields:

* **`reload_command`** — a shell command string executed after the certificate files are written. The agent passes this directly to `/bin/sh -c`, so you can use pipes, conditionals, or any other shell syntax.
* **`reload_timeout`** — how long the agent waits for the command to exit before killing it and logging a timeout error. Accepts Go duration strings such as `30s` or `2m`.

<Note>
  The `reload_command` runs as the same operating system user as the agent process. Make sure that user has permission to run the command — for example, by adding a `sudoers` entry or by granting the agent user membership in the appropriate systemd unit's `ExecReload` policy.
</Note>

<Note>
  If `reload_command` exits with a non-zero status, the agent logs an error but the certificate is still written to disk. A failed reload does not roll back the certificate or block future renewals.
</Note>

<Warning>
  If `reload_timeout` is exceeded, the agent kills the reload command and logs an error. Set the timeout long enough for your service's reload to complete — a value that is too short will leave your service running with the old certificate.
</Warning>

## Complete example

The following `certificates` entry shows all relevant fields together:

```yaml theme={null}
certificates:
  - name: web-wildcard
    profile: public_wildcard
    dns_names:
      - "*.example.com"
    key: /etc/ssl/private/service.key
    cert: /etc/ssl/certs/service.crt
    chain: /etc/ssl/certs/service.chain.crt
    fullchain: /etc/ssl/certs/service.fullchain.crt
    reload_command: systemctl reload nginx
    reload_timeout: 30s
    renew_before: 720h
```

## Examples by service

<CodeGroup>
  ```yaml nginx theme={null}
  certificates:
    - name: web-wildcard
      profile: public_wildcard
      key: /etc/ssl/private/service.key
      cert: /etc/ssl/certs/service.crt
      fullchain: /etc/ssl/certs/service.fullchain.crt
      reload_command: systemctl reload nginx
      reload_timeout: 30s
  ```

  ```yaml Traefik theme={null}
  certificates:
    - name: edge-wildcard
      profile: public_wildcard
      key: /etc/ssl/private/service.key
      cert: /etc/ssl/certs/service.crt
      fullchain: /etc/ssl/certs/service.fullchain.crt
      reload_command: systemctl reload traefik
      reload_timeout: 30s
  ```

  ```yaml Vault theme={null}
  certificates:
    - name: vault-cert
      profile: internal_vault
      key: /opt/vault/tls/vault.key
      cert: /opt/vault/tls/vault.crt
      fullchain: /opt/vault/tls/vault-fullchain.crt
      reload_command: systemctl reload vault
      reload_timeout: 30s
  ```

  ```yaml HAProxy theme={null}
  certificates:
    - name: lb-wildcard
      profile: public_wildcard
      key: /etc/haproxy/certs/service.key
      cert: /etc/haproxy/certs/service.crt
      fullchain: /etc/haproxy/certs/service.fullchain.crt
      reload_command: systemctl reload haproxy
      reload_timeout: 30s
  ```

  ```yaml "Custom script" theme={null}
  certificates:
    - name: web-wildcard
      profile: public_wildcard
      key: /etc/ssl/private/service.key
      cert: /etc/ssl/certs/service.crt
      fullchain: /etc/ssl/certs/service.fullchain.crt
      reload_command: /usr/local/bin/deploy-cert.sh
      reload_timeout: 60s
  ```
</CodeGroup>

## Using a wrapper script for complex logic

<Tip>
  If your reload logic involves multiple steps — for example, concatenating the key and certificate into a PEM bundle, setting ownership, and then reloading HAProxy — put that logic in a wrapper script and point `reload_command` at it. This keeps `agent.yml` readable and makes the reload logic independently testable.

  ```bash theme={null}
  #!/usr/bin/env bash
  set -euo pipefail

  cat /etc/ssl/private/service.key /etc/ssl/certs/service.fullchain.crt \
    > /etc/haproxy/certs/bundle.pem
  chown haproxy:haproxy /etc/haproxy/certs/bundle.pem
  chmod 640 /etc/haproxy/certs/bundle.pem
  systemctl reload haproxy
  ```

  Make the script executable (`chmod +x /usr/local/bin/deploy-cert.sh`) and ensure it is owned by root or the agent user.
</Tip>
