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-certexists with the new expiry date. - Under Local Traffic → Profiles → SSL → Client: confirm the
fairssl-clientsslprofile 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.
/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.chmod 600) on the proxy host.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.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.Ready to automate F5 certificates?
Create a free account and issue your first certificate in under 10 minutes.