SSL certificate maximum validity is being reduced to 200 days from March 2026. Read more →

F5 BIG-IP: SSL certificate via ACME and iControl REST

F5 BIG-IP has no built-in ACME client, but the well-established iControl REST API makes automation straightforward. We issue the certificate on a proxy host via Lego and FairSSL AutoDNS, and upload it to F5 with a deploy hook that updates the Client SSL profile.

How the setup is wired

  • A proxy host (Linux, e.g. an existing management server) runs Lego v5.0.4+.
  • Lego issues the certificate via FairSSL AutoDNS. No DNS API access required.
  • A deploy hook uploads cert + key via iControl REST and updates the Client SSL profile.
  • If F5 runs as an HA pair the script calls ConfigSync to standby.
  • cron runs Lego daily. ARI drives renewal.

Setup

Step 1: Create an iControl REST user on F5

In the BIG-IP web UI: go to System → Users → User List and create a local user (e.g. acme-deploy) with the Certificate Manager role for partition Common (or whichever partition your SSL profiles live in). Use a strong password.

Step 2: Install Lego

arch=$(dpkg --print-architecture)
case "$arch" in amd64|arm64) ;; *) echo "Adjust arch"; exit 1 ;; esac
version=$(curl -fsSL https://api.github.com/repos/go-acme/lego/releases/latest \
  | sed -n 's/.*"tag_name": "\(v[^"]*\)".*/\1/p' | head -1)
curl -fL "https://github.com/go-acme/lego/releases/download/${version}/lego_${version}_linux_${arch}.tar.gz" \
  | sudo tar -xz -C /usr/local/bin lego
sudo install -d -m 0700 /etc/ssl/f5

Step 3: Create the deploy script

The script uploads cert and key with POST /mgmt/shared/file-transfer/uploads, creates or updates ssl-cert and ssl-key objects via cmd=install, and updates the Client SSL profile. Optionally add a ConfigSync block if you run HA.

sudo tee /usr/local/bin/f5-deploy.sh > /dev/null << 'SCRIPT'
#!/bin/bash
set -euo pipefail
F5_HOST="bigip.example.com"
F5_USER="acme-deploy"
F5_PASS="YOUR_API_PASSWORD"
CERT_NAME="fairssl-acme-cert"
KEY_NAME="fairssl-acme-key"
PROFILE="fairssl-clientssl"   # Client SSL profile name in partition Common

CERT="$LEGO_HOOK_CERT_PATH"
KEY="$LEGO_HOOK_CERT_KEY_PATH"

# 1. Upload cert + key to /var/config/rest/downloads
curl -sS -k --user "$F5_USER:$F5_PASS" \
  -H "Content-Type: application/octet-stream" \
  -H "Content-Range: 0-$(($(stat -c%s "$CERT")-1))/$(stat -c%s "$CERT")" \
  --data-binary "@$CERT" \
  "https://$F5_HOST/mgmt/shared/file-transfer/uploads/$CERT_NAME.crt"

curl -sS -k --user "$F5_USER:$F5_PASS" \
  -H "Content-Type: application/octet-stream" \
  -H "Content-Range: 0-$(($(stat -c%s "$KEY")-1))/$(stat -c%s "$KEY")" \
  --data-binary "@$KEY" \
  "https://$F5_HOST/mgmt/shared/file-transfer/uploads/$KEY_NAME.key"

# 2. Install cert + key as objects (overwrites if they exist)
curl -sS -k --user "$F5_USER:$F5_PASS" \
  -H "Content-Type: application/json" \
  -d "{ \"command\": \"install\", \"name\": \"$CERT_NAME\", \"from-local-file\": \"/var/config/rest/downloads/$CERT_NAME.crt\" }" \
  "https://$F5_HOST/mgmt/tm/sys/crypto/cert"

curl -sS -k --user "$F5_USER:$F5_PASS" \
  -H "Content-Type: application/json" \
  -d "{ \"command\": \"install\", \"name\": \"$KEY_NAME\", \"from-local-file\": \"/var/config/rest/downloads/$KEY_NAME.key\" }" \
  "https://$F5_HOST/mgmt/tm/sys/crypto/key"

# 3. Update the Client SSL profile
curl -sS -k --user "$F5_USER:$F5_PASS" \
  -X PATCH -H "Content-Type: application/json" \
  -d "{ \"cert\": \"$CERT_NAME\", \"key\": \"$KEY_NAME\" }" \
  "https://$F5_HOST/mgmt/tm/ltm/profile/client-ssl/~Common~$PROFILE"

# 4. (Optional) ConfigSync to standby in an HA pair
# curl -sS -k --user "$F5_USER:$F5_PASS" \
#   -H "Content-Type: application/json" \
#   -d '{"command": "run", "utilCmdArgs": "config-sync to-group /Common/device-trust-group"}' \
#   "https://$F5_HOST/mgmt/tm/cm"
SCRIPT
sudo chmod 700 /usr/local/bin/f5-deploy.sh

Step 4: Issue the certificate

sudo /usr/local/bin/lego run \
  --domains "vip.example.com" \
  --server https://fairssl.dk/acme \
  --eab --eab.kid YOUR_EAB_KID --eab.hmac YOUR_EAB_HMAC \
  --accept-tos --email acme-client@fairssl.dk \
  --http --http.webroot "/var/www/html" \
  --path "/etc/ssl/f5" \
  --deploy-hook "/usr/local/bin/f5-deploy.sh"

Step 5: Schedule daily

# /etc/cron.d/lego-f5
17 04 * * * root /usr/local/bin/lego run \
  --domains "vip.example.com" \
  --server https://fairssl.dk/acme \
  --accept-tos --email acme-client@fairssl.dk \
  --http --http.webroot "/var/www/html" \
  --path "/etc/ssl/f5" \
  --renew-days 7 \
  --deploy-hook "/usr/local/bin/f5-deploy.sh"

Step 6: Verify

  • In the BIG-IP web UI under System → Certificate Management → Traffic Certificate Management → SSL Certificate List: confirm fairssl-acme-cert exists with the new expiry date.
  • Under Local Traffic → Profiles → SSL → Client: confirm the fairssl-clientssl profile uses the new cert + key.
  • Test publicly with FairSSL\'s SSL scanner.
  • HA deployments: verify from the standby BIG-IP that the configuration is synchronised.

Frequently asked questions

Find answers to the most common questions about SSL certificates and FairSSL.

iControl REST is F5's REST API for BIG-IP. It covers the full configuration surface, including SSL certificate management via /mgmt/tm/sys/file/ssl-cert and /mgmt/tm/sys/file/ssl-key. The API is enabled by default on modern BIG-IP versions and is used by F5's official Ansible modules, Terraform provider and a wide range of automation tooling.
iControl REST is more flexible and can be called from any host with curl. tmsh is better if you are already on the BIG-IP box or have a bastion. Our example uses iControl REST because the proxy host sits outside F5.
Create a dedicated iControl REST user with the Certificate Manager role (or Administrator if you do not use granular roles). The user must be able to upload files, create and update ssl-cert and ssl-key, and update the Client SSL profile. Use a strong password and store it with restrictive read access (chmod 600) on the proxy host.
After the certificate and key are uploaded, the script updates the Client SSL profile via PATCH /mgmt/tm/ltm/profile/client-ssl/<profile> with the new cert and key fields. Existing Virtual Servers using the profile pick up the new certificate as soon as F5 reloads the profile.
Upload to the active unit, then call POST /mgmt/tm/cm/config-sync to sync the configuration to standby. Our example covers the single-unit case; add the sync call if you have HA. ConfigSync transfers both the certificate files and the profile update.
Lego runs daily. When ARI or the 7-day fallback triggers a renewal, a new certificate is fetched and the deploy hook uploads the files, updates the Client SSL profile and syncs (if HA). Virtual Servers start serving the new certificate on the next connection without being restarted.

Ready to automate F5 certificates?

Create a free account and issue your first certificate in under 10 minutes.