InfraRunBook
    Back to articles

    F5 SSL Profile Client and Server Setup

    F5
    Published: Apr 16, 2026
    Updated: Apr 16, 2026

    A practical, senior-engineer walkthrough of configuring F5 BIG-IP Client SSL and Server SSL profiles — from certificate import through verification and common production mistakes.

    F5 SSL Profile Client and Server Setup

    Prerequisites

    Before you start creating SSL profiles on the BIG-IP, a few things need to be in place. First, you need a valid SSL certificate and its corresponding private key. These should be signed by a trusted CA — either a public CA or your internal PKI. If you're using a certificate chain (which you almost always will be in production), you'll also need the intermediate and root CA certificates in a bundle file.

    On the BIG-IP side, you need at minimum:

    • BIG-IP LTM licensed and provisioned
    • Administrative access — either via the GUI at
      https://192.168.10.1
      or over SSH as
      infrarunbook-admin
    • A virtual server already configured, or at least a pool and nodes ready to attach the SSL profiles to
    • The certificate, key, and CA bundle files staged and ready to import into the BIG-IP certificate store

    I'd also strongly recommend having an OpenSSL-capable Linux host on hand so you can verify the SSL handshake from outside the F5 once the profiles are live. Troubleshooting blind is no fun.

    Understanding Client vs. Server SSL Profiles

    This trips people up constantly, so let's be explicit. A Client SSL profile handles the SSL connection between the client — browser, application, API consumer, whatever is hitting your VIP — and the BIG-IP itself. The BIG-IP terminates that SSL session. The Server SSL profile handles the connection between the BIG-IP and the back-end pool members. If you're re-encrypting traffic on its way to the servers, you need a Server SSL profile.

    You can run Client SSL only — SSL offload, where decrypted traffic hits the servers over plain HTTP. You can run both Client and Server SSL — SSL bridging or re-encryption, where the F5 decrypts, potentially inspects, then re-encrypts to the servers. What you almost never want is Server SSL without Client SSL, unless you're doing something unusual like gateway mode. Keep that mental model clear before you touch anything.

    Importing Certificates and Keys

    Before you can build the profiles, the certificates need to live in the BIG-IP's certificate store. You can do this via the GUI under System > Certificate Management > Traffic Certificate Management, or via tmsh. I prefer tmsh for repeatability — GUI clicks don't go in a runbook very well, and they don't survive config audits either.

    Copy your certificate, key, and CA bundle files to the BIG-IP:

    scp solvethenetwork.com.crt infrarunbook-admin@192.168.10.1:/var/tmp/
    scp solvethenetwork.com.key infrarunbook-admin@192.168.10.1:/var/tmp/
    scp solvethenetwork-ca-bundle.crt infrarunbook-admin@192.168.10.1:/var/tmp/

    Then SSH into the BIG-IP and import them:

    tmsh install sys crypto cert solvethenetwork-2025 from-local-file /var/tmp/solvethenetwork.com.crt
    tmsh install sys crypto key solvethenetwork-2025 from-local-file /var/tmp/solvethenetwork.com.key
    tmsh install sys crypto cert solvethenetwork-ca-bundle from-local-file /var/tmp/solvethenetwork-ca-bundle.crt

    Verify they landed correctly:

    tmsh list sys crypto cert solvethenetwork-2025
    tmsh list sys crypto key solvethenetwork-2025

    If the list commands return output with the expected subject and expiry, you're good. If either returns an error, the import failed — usually because the file path is wrong or the file is malformed. Check it with

    openssl x509 -in /var/tmp/solvethenetwork.com.crt -noout -text
    before retrying.

    Step 1 — Creating the Client SSL Profile

    The Client SSL profile is where most of the heavy lifting happens. This is what clients negotiate with, so your cipher suite selection, certificate presentation, and SNI configuration all live here.

    Via tmsh, create the Client SSL profile like this:

    tmsh create ltm profile client-ssl solvethenetwork-clientssl {
        cert-key-chain {
            solvethenetwork-2025 {
                cert solvethenetwork-2025.crt
                key solvethenetwork-2025.key
                chain solvethenetwork-ca-bundle.crt
            }
        }
        ciphers "ECDHE+AESGCM:ECDHE+AES256:!RC4:!aNULL:!eNULL:!LOW:!3DES:!MD5:!EXP"
        options { dont-insert-empty-fragments no-tlsv1 no-sslv3 no-tlsv1-1 }
        sni-default true
        defaults-from clientssl
    }

    Let me walk through the key parameters. The

    cert-key-chain
    block references the objects you just imported — cert, key, and chain all in one named entry. The
    chain
    field is your CA bundle. Don't skip it. Clients that don't have your intermediate CA cached will fail validation, and that includes most mobile apps and API clients that don't do AIA fetching.

    The

    ciphers
    string uses OpenSSL-style cipher notation. The example above disables RC4, null ciphers, export-grade ciphers, and 3DES while preferring ECDHE-based suites with AES-GCM. This is a solid baseline for most environments in 2025.

    The

    options
    block controls protocol versions.
    no-tlsv1
    and
    no-tlsv1-1
    disable TLS 1.0 and 1.1, enforcing TLS 1.2 as the minimum.
    no-sslv3
    disables SSL 3.0 entirely. If you still have legacy clients that require TLS 1.0 or 1.1, you'll need to remove those options — but document why and get sign-off, because you're making a deliberate security concession.
    dont-insert-empty-fragments
    is a legacy workaround for certain older TLS implementations and is generally fine to leave in.

    The

    defaults-from clientssl
    line means this custom profile inherits all unset parameters from the built-in
    clientssl
    parent profile. Always use the built-in parent unless you have a very specific reason not to. Inheriting from another custom profile stacks up configuration layers that become impossible to reason about when something breaks at 2am.

    Setting

    sni-default true
    designates this profile as the fallback when a client doesn't send a Server Name Indication in the ClientHello. If you plan to have multiple certificate/key pairs under the same VIP for different hostnames, this is the one that answers when no SNI match is found. For a single-domain VIP, you still want this set to true.

    Step 2 — Creating the Server SSL Profile

    The Server SSL profile controls how the BIG-IP establishes its outbound connection to your back-end pool members. If you're doing SSL offload — plain HTTP to the servers — you skip this entirely. But if your servers require HTTPS, which is increasingly the norm for compliance reasons, you need this profile.

    tmsh create ltm profile server-ssl solvethenetwork-serverssl {
        ciphers "ECDHE+AESGCM:ECDHE+AES256:!RC4:!aNULL:!eNULL:!LOW:!3DES"
        options { dont-insert-empty-fragments no-tlsv1 no-sslv3 }
        peer-cert-mode ignore
        server-name www.solvethenetwork.com
        defaults-from serverssl
    }

    The

    peer-cert-mode
    setting controls whether the BIG-IP validates the server's certificate. Setting it to
    ignore
    means no validation happens — which sounds insecure, but is actually common in internal environments where servers use self-signed certificates or an internal PKI that the BIG-IP doesn't have a trust anchor for. In my experience, most internal deployments start here and tighten up later.

    If you want the BIG-IP to actually authenticate the server certificate, set

    peer-cert-mode require
    and configure the CA bundle the server cert was signed by:

    tmsh modify ltm profile server-ssl solvethenetwork-serverssl {
        peer-cert-mode require
        ca-file solvethenetwork-ca-bundle.crt
    }

    The

    server-name
    field sends an SNI hostname in the BIG-IP's outbound ClientHello to the server. If your back-end servers host multiple certificates on the same IP and port, this tells them which certificate to present. Match this to the FQDN the server expects — typically the same hostname your clients use to reach the VIP, unless you're doing host header rewriting.

    Step 3 — Attaching Profiles to the Virtual Server

    With both profiles created, attach them to your virtual server. The virtual server must be a Standard type — Performance Layer 4 and FastL4 virtual servers bypass the full proxy stack and can't do SSL termination. If you're not sure what type your VS is, check with

    tmsh list ltm virtual vs_solvethenetwork_443 | grep type
    .

    tmsh modify ltm virtual vs_solvethenetwork_443 {
        profiles add {
            solvethenetwork-clientssl { context clientside }
            solvethenetwork-serverssl { context serverside }
            http { }
            tcp { }
        }
    }

    The

    context clientside
    and
    context serverside
    assignments are mandatory for SSL profiles. Without them, the BIG-IP doesn't know which side of the proxy to apply the profile to and will reject the configuration. The
    http
    profile is there because once you're terminating SSL, you almost always want L7 HTTP awareness — access to headers, URI, host for persistence and iRule logic, plus proper HTTP logging.

    Full Configuration Example

    Here's the complete tmsh configuration in a single block, suitable for a runbook or a configuration script. This assumes the virtual server already exists at 192.168.10.100:443 with an associated pool.

    # Import certificates and keys
    install sys crypto cert solvethenetwork-2025 from-local-file /var/tmp/solvethenetwork.com.crt
    install sys crypto key solvethenetwork-2025 from-local-file /var/tmp/solvethenetwork.com.key
    install sys crypto cert solvethenetwork-ca-bundle from-local-file /var/tmp/solvethenetwork-ca-bundle.crt
    
    # Create Client SSL Profile
    create ltm profile client-ssl solvethenetwork-clientssl {
        cert-key-chain {
            solvethenetwork-2025 {
                cert solvethenetwork-2025.crt
                key solvethenetwork-2025.key
                chain solvethenetwork-ca-bundle.crt
            }
        }
        ciphers "ECDHE+AESGCM:ECDHE+AES256:!RC4:!aNULL:!eNULL:!LOW:!3DES:!MD5:!EXP"
        options { dont-insert-empty-fragments no-tlsv1 no-sslv3 no-tlsv1-1 }
        sni-default true
        defaults-from clientssl
    }
    
    # Create Server SSL Profile
    create ltm profile server-ssl solvethenetwork-serverssl {
        ciphers "ECDHE+AESGCM:ECDHE+AES256:!RC4:!aNULL:!eNULL:!LOW:!3DES"
        options { dont-insert-empty-fragments no-tlsv1 no-sslv3 }
        peer-cert-mode ignore
        server-name www.solvethenetwork.com
        defaults-from serverssl
    }
    
    # Attach profiles to the Virtual Server
    modify ltm virtual vs_solvethenetwork_443 {
        destination 192.168.10.100:443
        ip-protocol tcp
        profiles add {
            solvethenetwork-clientssl { context clientside }
            solvethenetwork-serverssl { context serverside }
            http { }
            tcp { }
        }
        pool pool_solvethenetwork_web
        source-address-translation {
            type automap
        }
    }
    
    # Save configuration to disk
    save sys config

    That last line matters more than people think. The BIG-IP does not auto-save on configuration changes. I've seen engineers make a dozen changes during an incident, test successfully, then watch everything revert after a chassis failover because the config was never committed to disk.

    save sys config
    is not optional.

    Verification Steps

    Once the profiles are attached and the config is saved, verify it works. Don't assume the absence of errors means everything is correct — test the actual SSL handshake.

    Verify the Handshake with OpenSSL

    From a Linux host that can reach the VIP, run:

    openssl s_client -connect 192.168.10.100:443 -servername www.solvethenetwork.com

    Read the output carefully. You want to see the full certificate chain returned — server cert first, followed by the intermediates. The session should end with

    Verify return code: 0 (ok)
    . If you get code 20 (unable to get local issuer certificate) or code 21 (unable to verify the first certificate), your
    chain
    parameter in the Client SSL profile is either wrong or missing entirely.

    To check specifically which TLS version and cipher were negotiated:

    openssl s_client -connect 192.168.10.100:443 -servername www.solvethenetwork.com 2>&1 | grep -E "Protocol|Cipher"

    Expected output looks something like this:

        Protocol  : TLSv1.2
        Cipher    : ECDHE-RSA-AES256-GCM-SHA384

    If you see TLSv1 or TLSv1.1, your options block didn't apply — double-check the profile is actually attached to the virtual server and that you saved the config.

    Check BIG-IP SSL Statistics

    After a few test connections, pull profile-level statistics from the BIG-IP:

    tmsh show ltm profile client-ssl solvethenetwork-clientssl

    This shows handshake counts, cipher negotiation breakdown, and — critically — handshake failure counts. If failures are non-zero and climbing after your initial tests, that's your first signal to look at cipher compatibility or certificate validity.

    You can also pull virtual server-level SSL stats:

    tmsh show ltm virtual vs_solvethenetwork_443 detail | grep -i ssl

    Test the Server-Side Connection

    To verify the BIG-IP can establish its outbound SSL connection to the pool members, test from the BIG-IP CLI directly:

    curl -vk https://192.168.10.50/ --resolve www.solvethenetwork.com:443:192.168.10.50

    This simulates what the Server SSL profile will do when the BIG-IP connects to a pool member at 192.168.10.50. The

    -k
    flag skips certificate validation here, which is intentional — you're testing TCP and SSL connectivity, not certificate trust. If this curl fails but the pool member is up and listening on 443, look at your Server SSL cipher string or check whether the server requires a minimum TLS version your profile doesn't support.

    Common Mistakes

    Not including the certificate chain. This is the single most common mistake I see. The

    chain
    field inside
    cert-key-chain
    is where your intermediate CA certificate or bundle goes. Without it, clients that haven't previously cached your intermediate CA will get an untrusted certificate error — even if the cert itself is perfectly valid. Modern browsers often recover via AIA fetching, but mobile apps, IoT devices, and API clients generally don't. Always include the full chain.

    Mixing old-style and new-style certificate configuration. Older BIG-IP configs used top-level

    cert
    ,
    key
    , and
    chain
    parameters directly in the profile. Current versions use the
    cert-key-chain
    block. If you're adapting configs from older runbooks or copying from the F5 docs without checking the version, you can end up with a profile that looks correct but doesn't behave correctly. After creating any SSL profile, always run
    tmsh list ltm profile client-ssl solvethenetwork-clientssl
    and read back what was actually stored.

    Wrong parent profile. Always inherit Client SSL profiles from the built-in

    clientssl
    and Server SSL profiles from the built-in
    serverssl
    . Using
    clientssl-secure
    as the parent is reasonable for high-security environments — it enforces stricter defaults — but you need to know exactly what defaults you're inheriting. I've seen engineers accidentally chain custom profiles from other custom profiles, creating layers of conflicting settings that took hours to unwind during a maintenance window.

    Forgetting to specify context on the virtual server. When you attach an SSL profile to a virtual server, the

    context clientside
    or
    context serverside
    assignment is not optional. If you omit it, the BIG-IP will throw an error, or in older firmware versions, silently ignore the profile. Always be explicit.

    Cipher mismatch with back-end servers. In my experience, Server SSL profile issues are almost always cipher-related. Legacy Java applications, older Node.js services, and some embedded devices support a limited cipher set. If your Server SSL profile is too restrictive, the BIG-IP will fail to establish the server-side connection and your pool members will appear down in the monitor stats even though the servers themselves are healthy. Start with a more permissive cipher string on the server side, confirm connectivity, then tighten from there.

    No certificate expiry monitoring. The BIG-IP doesn't alert you by default when a certificate is approaching expiry. This has caused outages in every organization I've worked in at least once. Wire up expiry alerting — either via your monitoring platform querying the BIG-IP's certificate objects, or a scheduled OpenSSL check against the VIP itself. An expired certificate on a production load balancer is an entirely preventable incident.


    A Note on BIG-IP 15.x and Cipher Groups

    If you're running BIG-IP 15.1 or later, F5 introduced named cipher groups as a replacement for raw OpenSSL cipher strings. Instead of an inline string in the profile, you define a

    ltm cipher group
    object and reference it from the profile. The approach is the same conceptually — you're still building a Client SSL profile with specific protocol and cipher restrictions — but the configuration syntax is cleaner and cipher policies become reusable across profiles. Worth knowing about if you're managing multiple virtual servers with consistent cipher requirements or working toward PCI-DSS or FedRAMP compliance where cipher policy needs to be documented and auditable.

    Frequently Asked Questions

    What is the difference between a Client SSL profile and a Server SSL profile on F5 BIG-IP?

    A Client SSL profile handles the TLS session between external clients and the BIG-IP VIP — the F5 terminates that connection. A Server SSL profile handles the outbound TLS connection from the BIG-IP to the back-end pool members. You use Client SSL for SSL offload, and both Client and Server SSL when you need to re-encrypt traffic before it reaches your servers.

    Why do clients get certificate errors even though my certificate is valid?

    The most common cause is a missing certificate chain. The Client SSL profile's cert-key-chain block requires a 'chain' field pointing to your intermediate CA bundle. Without it, clients that haven't cached your intermediate CA will fail chain validation. Always include the full certificate chain in your profile, not just the leaf certificate.

    How do I verify that my F5 SSL profile is using TLS 1.2 and not TLS 1.0?

    From a Linux host that can reach the VIP, run: openssl s_client -connect 192.168.10.100:443 -servername www.solvethenetwork.com 2>&1 | grep Protocol. This will show the negotiated TLS version. If TLS 1.0 is showing up, verify that 'no-tlsv1' and 'no-tlsv1-1' are set in the options block of your Client SSL profile, and confirm the profile is actually attached to the virtual server.

    Do I need to save the configuration after creating SSL profiles on BIG-IP?

    Yes, always. The BIG-IP does not auto-save configuration changes. Run 'tmsh save sys config' after making changes. If you don't, an HA failover, chassis reboot, or config reload will revert all unsaved changes — including your new SSL profiles.

    What should I set for peer-cert-mode in the Server SSL profile?

    Set it to 'ignore' when your back-end servers use self-signed certificates or an internal CA that the BIG-IP doesn't have a trust anchor for — this is common in internal environments. Set it to 'require' when you want the BIG-IP to fully validate the server certificate, and pair it with the 'ca-file' parameter pointing to the CA bundle that signed the server certificates.

    Related Articles