f5-config-mgmt
F5 BIG-IP Configuration Management
Structured change management workflows for F5 BIG-IP configuration changes via the iControl REST API. Every change follows: Baseline -> Plan -> Apply -> Verify -> Document.
Golden Rule
NEVER apply configuration without first capturing a baseline. If the change goes wrong, you need to know what to restore.
How to Call the Tools
The F5 MCP server provides 6 tools. Call them via mcp-call with the required environment variables:
IP_ADDRESS=$F5_IP_ADDRESS Authorization_string=$F5_AUTH_STRING python3 $MCP_CALL "python3 -u $F5_MCP_SCRIPT" <tool_name> '{"param":"value"}'
Available Tools
| Tool | Purpose | HTTP Method | Key Arguments |
|---|---|---|---|
list_tool |
List F5 objects | GET | object_name, object_type |
show_stats_tool |
Show object statistics | GET | object_name, object_type |
show_logs_tool |
Show system logs | GET | lines_number |
create_tool |
Create objects | POST | url_body, object_type |
update_tool |
Update objects | PATCH | url_body, object_type, object_name |
delete_tool |
Delete objects | DELETE | object_type, object_name |
Object types: virtual, pool, irule, profile
Change Workflow
Phase 1: Pre-Change Baseline
Capture the current state of everything the change might affect. This is the rollback reference.
1A: Capture Virtual Server State
IP_ADDRESS=$F5_IP_ADDRESS Authorization_string=$F5_AUTH_STRING python3 $MCP_CALL "python3 -u $F5_MCP_SCRIPT" list_tool '{"object_name":"","object_type":"virtual"}'
Store the full list of virtual servers, their configurations, pool assignments, and profiles.
1B: Capture Pool State
IP_ADDRESS=$F5_IP_ADDRESS Authorization_string=$F5_AUTH_STRING python3 $MCP_CALL "python3 -u $F5_MCP_SCRIPT" list_tool '{"object_name":"","object_type":"pool"}'
Store pool configurations, member lists, monitor assignments, and load balancing methods.
1C: Capture Statistics Baseline
For each affected object, capture current stats to compare post-change:
IP_ADDRESS=$F5_IP_ADDRESS Authorization_string=$F5_AUTH_STRING python3 $MCP_CALL "python3 -u $F5_MCP_SCRIPT" show_stats_tool '{"object_name":"my_virtual_server","object_type":"virtual"}'
IP_ADDRESS=$F5_IP_ADDRESS Authorization_string=$F5_AUTH_STRING python3 $MCP_CALL "python3 -u $F5_MCP_SCRIPT" show_stats_tool '{"object_name":"my_pool","object_type":"pool"}'
1D: Capture Log Baseline
Record the last 50 lines of logs to establish a timestamp reference:
IP_ADDRESS=$F5_IP_ADDRESS Authorization_string=$F5_AUTH_STRING python3 $MCP_CALL "python3 -u $F5_MCP_SCRIPT" show_logs_tool '{"lines_number":"50"}'
Note the most recent log timestamp -- any errors after this timestamp are change-related.
1E: Capture iRule and Profile State (if affected)
IP_ADDRESS=$F5_IP_ADDRESS Authorization_string=$F5_AUTH_STRING python3 $MCP_CALL "python3 -u $F5_MCP_SCRIPT" list_tool '{"object_name":"","object_type":"irule"}'
IP_ADDRESS=$F5_IP_ADDRESS Authorization_string=$F5_AUTH_STRING python3 $MCP_CALL "python3 -u $F5_MCP_SCRIPT" list_tool '{"object_name":"","object_type":"profile"}'
Phase 2: Plan the Change
Before applying any configuration, explicitly state:
- What objects will be created, updated, or deleted
- Why the change is needed (business justification)
- Expected effect on traffic flow and application delivery
- Risk assessment -- what could go wrong
- Verification criteria -- how to confirm success
- Rollback plan -- exact steps to undo the change
Phase 3: Apply Configuration
Creating Objects
Use create_tool to create new objects via POST. The url_body dict contains the iControl REST API body.
Example: Create a Pool with Members
IP_ADDRESS=$F5_IP_ADDRESS Authorization_string=$F5_AUTH_STRING python3 $MCP_CALL "python3 -u $F5_MCP_SCRIPT" create_tool '{"url_body":{"name":"pool_webapp","monitor":"http","loadBalancingMode":"round-robin","members":["10.1.1.10:80","10.1.1.11:80","10.1.1.12:80"]},"object_type":"pool"}'
Pool creation best practices:
- Always assign a health monitor (
http,https,tcp,icmp, or a custom monitor) - Choose the appropriate load balancing method:
round-robin-- default, equal distributionleast-connections-member-- best for unequal server capacity or variable request durationratio-member-- weighted distribution for heterogeneous backendsfastest-node-- route to fastest responding server
- Specify the
serviceDownActionfor graceful failure handling:none-- connections persist on down member until timeoutreset-- RST sent to clientsreselect-- reselect a new member (recommended for HTTP)drop-- silently drop connections
- Set
minActiveMembersto trigger action when too many members fail - Include
descriptionfor documentation
Example: Create a Pool with Advanced Options
IP_ADDRESS=$F5_IP_ADDRESS Authorization_string=$F5_AUTH_STRING python3 $MCP_CALL "python3 -u $F5_MCP_SCRIPT" create_tool '{"url_body":{"name":"pool_api_backend","monitor":"https_443","loadBalancingMode":"least-connections-member","minActiveMembers":2,"serviceDownAction":"reselect","slowRampTime":300,"description":"API backend pool - managed by NetClaw","members":["10.2.1.20:443","10.2.1.21:443","10.2.1.22:443","10.2.1.23:443"]},"object_type":"pool"}'
Example: Create a Virtual Server
IP_ADDRESS=$F5_IP_ADDRESS Authorization_string=$F5_AUTH_STRING python3 $MCP_CALL "python3 -u $F5_MCP_SCRIPT" create_tool '{"url_body":{"name":"vs_webapp_https","destination":"10.100.1.50:443","ipProtocol":"tcp","pool":"pool_webapp","sourceAddressTranslation":{"type":"automap"},"profiles":[{"name":"clientssl"},{"name":"http"},{"name":"tcp-wan-optimized","context":"clientside"},{"name":"tcp-lan-optimized","context":"serverside"}],"description":"HTTPS virtual server for webapp - managed by NetClaw"},"object_type":"virtual"}'
Virtual server creation best practices:
- Always specify
destinationas VIP_IP:port - Always assign
sourceAddressTranslation(automap or SNAT pool) unless servers have BIG-IP as default gateway - Assign appropriate profiles:
- Client SSL profile for HTTPS termination
- HTTP profile for HTTP inspection, compression, X-Forwarded-For
- TCP profiles:
tcp-wan-optimizedon clientside,tcp-lan-optimizedon serverside - Persistence profile if session affinity is required
- Set
poolto the backend pool name - Include
descriptionfor documentation - Consider
connectionLimitto protect backend servers
Example: Create an HTTP Virtual Server (Non-SSL)
IP_ADDRESS=$F5_IP_ADDRESS Authorization_string=$F5_AUTH_STRING python3 $MCP_CALL "python3 -u $F5_MCP_SCRIPT" create_tool '{"url_body":{"name":"vs_webapp_http","destination":"10.100.1.50:80","ipProtocol":"tcp","pool":"pool_webapp","sourceAddressTranslation":{"type":"automap"},"profiles":[{"name":"http"},{"name":"tcp-wan-optimized","context":"clientside"},{"name":"tcp-lan-optimized","context":"serverside"}],"description":"HTTP virtual server for webapp - managed by NetClaw"},"object_type":"virtual"}'
Example: Create an HTTP-to-HTTPS Redirect Virtual Server
IP_ADDRESS=$F5_IP_ADDRESS Authorization_string=$F5_AUTH_STRING python3 $MCP_CALL "python3 -u $F5_MCP_SCRIPT" create_tool '{"url_body":{"name":"vs_webapp_redirect","destination":"10.100.1.50:80","ipProtocol":"tcp","profiles":[{"name":"http"}],"rules":["/Common/redirect_to_https"],"description":"HTTP-to-HTTPS redirect - managed by NetClaw"},"object_type":"virtual"}'
Example: Create an iRule
IP_ADDRESS=$F5_IP_ADDRESS Authorization_string=$F5_AUTH_STRING python3 $MCP_CALL "python3 -u $F5_MCP_SCRIPT" create_tool '{"url_body":{"name":"redirect_to_https","apiAnonymous":"when HTTP_REQUEST {\n HTTP::redirect https://[HTTP::host][HTTP::uri]\n}"},"object_type":"irule"}'
iRule creation best practices:
- Keep iRules as simple as possible -- complexity degrades performance
- Avoid
logstatements in production iRules on high-traffic virtual servers - Always pair
HTTP::collectwithHTTP::releaseto prevent memory leaks - Use
catchblocks for error handling in complex iRules - Test iRule syntax before deploying (syntax errors can prevent virtual server from starting)
Example: HTTP Header Insertion iRule
IP_ADDRESS=$F5_IP_ADDRESS Authorization_string=$F5_AUTH_STRING python3 $MCP_CALL "python3 -u $F5_MCP_SCRIPT" create_tool '{"url_body":{"name":"insert_headers","apiAnonymous":"when HTTP_REQUEST {\n HTTP::header insert X-Forwarded-Proto https\n HTTP::header insert X-Real-IP [IP::client_addr]\n}\nwhen HTTP_RESPONSE {\n HTTP::header insert Strict-Transport-Security \"max-age=31536000; includeSubDomains\"\n}"},"object_type":"irule"}'
Example: Maintenance Page iRule
IP_ADDRESS=$F5_IP_ADDRESS Authorization_string=$F5_AUTH_STRING python3 $MCP_CALL "python3 -u $F5_MCP_SCRIPT" create_tool '{"url_body":{"name":"maintenance_page","apiAnonymous":"when HTTP_REQUEST {\n HTTP::respond 503 content \"<html><body><h1>Service Temporarily Unavailable</h1><p>We are performing scheduled maintenance. Please try again later.</p></body></html>\" Content-Type \"text/html\"\n}"},"object_type":"irule"}'
Example: URI-Based Pool Selection iRule
IP_ADDRESS=$F5_IP_ADDRESS Authorization_string=$F5_AUTH_STRING python3 $MCP_CALL "python3 -u $F5_MCP_SCRIPT" create_tool '{"url_body":{"name":"uri_routing","apiAnonymous":"when HTTP_REQUEST {\n switch -glob [string tolower [HTTP::uri]] {\n \"/api/*\" { pool pool_api_backend }\n \"/static/*\" { pool pool_static_content }\n default { pool pool_webapp }\n }\n}"},"object_type":"irule"}'
Updating Objects
Use update_tool to modify existing objects via PATCH. Only include the fields you want to change.
Example: Update Pool Members (Add a Member)
IP_ADDRESS=$F5_IP_ADDRESS Authorization_string=$F5_AUTH_STRING python3 $MCP_CALL "python3 -u $F5_MCP_SCRIPT" update_tool '{"url_body":{"members":["10.1.1.10:80","10.1.1.11:80","10.1.1.12:80","10.1.1.13:80"]},"object_type":"pool","object_name":"pool_webapp"}'
WARNING: The members list in an update is a full replacement, not an append. Always include ALL desired members (existing + new) in the list. Omitting existing members will remove them.
Example: Update Pool Load Balancing Method
IP_ADDRESS=$F5_IP_ADDRESS Authorization_string=$F5_AUTH_STRING python3 $MCP_CALL "python3 -u $F5_MCP_SCRIPT" update_tool '{"url_body":{"loadBalancingMode":"least-connections-member"},"object_type":"pool","object_name":"pool_webapp"}'
Example: Update Pool Monitor
IP_ADDRESS=$F5_IP_ADDRESS Authorization_string=$F5_AUTH_STRING python3 $MCP_CALL "python3 -u $F5_MCP_SCRIPT" update_tool '{"url_body":{"monitor":"https_443"},"object_type":"pool","object_name":"pool_api_backend"}'
Example: Update Virtual Server Pool Assignment
IP_ADDRESS=$F5_IP_ADDRESS Authorization_string=$F5_AUTH_STRING python3 $MCP_CALL "python3 -u $F5_MCP_SCRIPT" update_tool '{"url_body":{"pool":"pool_webapp_v2"},"object_type":"virtual","object_name":"vs_webapp_https"}'
Example: Add iRule to Virtual Server
IP_ADDRESS=$F5_IP_ADDRESS Authorization_string=$F5_AUTH_STRING python3 $MCP_CALL "python3 -u $F5_MCP_SCRIPT" update_tool '{"url_body":{"rules":["/Common/redirect_to_https","/Common/insert_headers"]},"object_type":"virtual","object_name":"vs_webapp_https"}'
WARNING: The rules list in an update is a full replacement. Include ALL desired iRules in the list.
Example: Disable a Virtual Server (Maintenance)
IP_ADDRESS=$F5_IP_ADDRESS Authorization_string=$F5_AUTH_STRING python3 $MCP_CALL "python3 -u $F5_MCP_SCRIPT" update_tool '{"url_body":{"enabled":false},"object_type":"virtual","object_name":"vs_webapp_https"}'
Example: Re-enable a Virtual Server
IP_ADDRESS=$F5_IP_ADDRESS Authorization_string=$F5_AUTH_STRING python3 $MCP_CALL "python3 -u $F5_MCP_SCRIPT" update_tool '{"url_body":{"enabled":true},"object_type":"virtual","object_name":"vs_webapp_https"}'
Deleting Objects
Use delete_tool to remove objects. Always verify no dependencies exist before deletion.
Example: Delete a Pool
IP_ADDRESS=$F5_IP_ADDRESS Authorization_string=$F5_AUTH_STRING python3 $MCP_CALL "python3 -u $F5_MCP_SCRIPT" delete_tool '{"object_type":"pool","object_name":"pool_old_webapp"}'
CRITICAL: You cannot delete a pool that is still assigned to a virtual server. Remove the pool reference from the virtual server first, or reassign to a different pool.
Example: Delete a Virtual Server
IP_ADDRESS=$F5_IP_ADDRESS Authorization_string=$F5_AUTH_STRING python3 $MCP_CALL "python3 -u $F5_MCP_SCRIPT" delete_tool '{"object_type":"virtual","object_name":"vs_old_webapp"}'
Example: Delete an iRule
IP_ADDRESS=$F5_IP_ADDRESS Authorization_string=$F5_AUTH_STRING python3 $MCP_CALL "python3 -u $F5_MCP_SCRIPT" delete_tool '{"object_type":"irule","object_name":"old_redirect_rule"}'
CRITICAL: You cannot delete an iRule that is still assigned to a virtual server. Remove the iRule reference from the virtual server first.
Deletion Order (Dependencies)
When decommissioning a full application stack, delete in this order:
- Remove iRule references from virtual servers (update)
- Delete virtual servers
- Delete pools
- Delete orphaned iRules
- Delete orphaned profiles
Reversing this order will cause dependency errors.
Traffic Shifting / Blue-Green Deployment
A common F5 change pattern is shifting traffic between pool versions for deployments.
Step 1: Create the New Pool (Green)
IP_ADDRESS=$F5_IP_ADDRESS Authorization_string=$F5_AUTH_STRING python3 $MCP_CALL "python3 -u $F5_MCP_SCRIPT" create_tool '{"url_body":{"name":"pool_webapp_v2","monitor":"http","loadBalancingMode":"round-robin","members":["10.1.2.10:80","10.1.2.11:80","10.1.2.12:80"],"description":"Webapp v2.0 pool - blue/green deployment"},"object_type":"pool"}'
Step 2: Verify New Pool Health
IP_ADDRESS=$F5_IP_ADDRESS Authorization_string=$F5_AUTH_STRING python3 $MCP_CALL "python3 -u $F5_MCP_SCRIPT" show_stats_tool '{"object_name":"pool_webapp_v2","object_type":"pool"}'
Confirm all members are available and passing health checks before shifting traffic.
Step 3: Shift Virtual Server to New Pool
IP_ADDRESS=$F5_IP_ADDRESS Authorization_string=$F5_AUTH_STRING python3 $MCP_CALL "python3 -u $F5_MCP_SCRIPT" update_tool '{"url_body":{"pool":"pool_webapp_v2"},"object_type":"virtual","object_name":"vs_webapp_https"}'
Step 4: Monitor Post-Shift
IP_ADDRESS=$F5_IP_ADDRESS Authorization_string=$F5_AUTH_STRING python3 $MCP_CALL "python3 -u $F5_MCP_SCRIPT" show_stats_tool '{"object_name":"vs_webapp_https","object_type":"virtual"}'
IP_ADDRESS=$F5_IP_ADDRESS Authorization_string=$F5_AUTH_STRING python3 $MCP_CALL "python3 -u $F5_MCP_SCRIPT" show_stats_tool '{"object_name":"pool_webapp_v2","object_type":"pool"}'
IP_ADDRESS=$F5_IP_ADDRESS Authorization_string=$F5_AUTH_STRING python3 $MCP_CALL "python3 -u $F5_MCP_SCRIPT" show_logs_tool '{"lines_number":"100"}'
Verify traffic is flowing to the new pool, no errors in logs, and response times are acceptable.
Step 5: Rollback (If Needed)
If the new pool is unhealthy, immediately revert to the old pool:
IP_ADDRESS=$F5_IP_ADDRESS Authorization_string=$F5_AUTH_STRING python3 $MCP_CALL "python3 -u $F5_MCP_SCRIPT" update_tool '{"url_body":{"pool":"pool_webapp"},"object_type":"virtual","object_name":"vs_webapp_https"}'
Step 6: Cleanup Old Pool (After Burn-In)
Once the new pool is verified stable (after appropriate burn-in period), remove the old pool:
IP_ADDRESS=$F5_IP_ADDRESS Authorization_string=$F5_AUTH_STRING python3 $MCP_CALL "python3 -u $F5_MCP_SCRIPT" delete_tool '{"object_type":"pool","object_name":"pool_webapp"}'
Phase 4: Post-Change Verification
Immediately after applying configuration, verify the change.
4A: Verify Object Was Created/Updated
IP_ADDRESS=$F5_IP_ADDRESS Authorization_string=$F5_AUTH_STRING python3 $MCP_CALL "python3 -u $F5_MCP_SCRIPT" list_tool '{"object_name":"pool_webapp","object_type":"pool"}'
Compare with the pre-change baseline to confirm only intended changes were made.
4B: Verify Object Health
IP_ADDRESS=$F5_IP_ADDRESS Authorization_string=$F5_AUTH_STRING python3 $MCP_CALL "python3 -u $F5_MCP_SCRIPT" show_stats_tool '{"object_name":"pool_webapp","object_type":"pool"}'
Confirm:
- Pool members are marked available (passing health checks)
- Virtual server is available and accepting connections
- Statistics are incrementing (traffic is flowing)
4C: Check for Errors in Logs
IP_ADDRESS=$F5_IP_ADDRESS Authorization_string=$F5_AUTH_STRING python3 $MCP_CALL "python3 -u $F5_MCP_SCRIPT" show_logs_tool '{"lines_number":"100"}'
Look for new error messages that appeared after the Phase 1D baseline timestamp.
4D: Verify Dependent Objects
If you changed a pool, verify the virtual servers that reference it are still healthy:
IP_ADDRESS=$F5_IP_ADDRESS Authorization_string=$F5_AUTH_STRING python3 $MCP_CALL "python3 -u $F5_MCP_SCRIPT" show_stats_tool '{"object_name":"vs_webapp_https","object_type":"virtual"}'
Phase 5: Rollback (If Verification Fails)
If verification fails, roll back by restoring the baseline state.
For created objects: Delete the newly created object.
IP_ADDRESS=$F5_IP_ADDRESS Authorization_string=$F5_AUTH_STRING python3 $MCP_CALL "python3 -u $F5_MCP_SCRIPT" delete_tool '{"object_type":"pool","object_name":"pool_webapp_v2"}'
For updated objects: Patch the object with the original values from the baseline.
IP_ADDRESS=$F5_IP_ADDRESS Authorization_string=$F5_AUTH_STRING python3 $MCP_CALL "python3 -u $F5_MCP_SCRIPT" update_tool '{"url_body":{"pool":"pool_webapp"},"object_type":"virtual","object_name":"vs_webapp_https"}'
For deleted objects: Recreate the object using the baseline configuration.
After rollback, re-verify that the BIG-IP returned to its baseline state.
Change Documentation
After every change, produce a change report:
F5 Change Report -- YYYY-MM-DD HH:MM UTC
Device: $F5_IP_ADDRESS
Requestor: [who requested the change]
Change Description:
Created pool_webapp with 3 members for new web application
Objects Modified:
[CREATED] pool_webapp (pool) -- 3 members, round-robin, HTTP monitor
[CREATED] vs_webapp_https (virtual) -- 10.100.1.50:443, SSL offload, automap
Pre-Change State:
- Virtual servers: 4 active
- Pools: 3 active
- No errors in logs
Post-Change State:
- Virtual servers: 5 active (+1 vs_webapp_https)
- Pools: 4 active (+1 pool_webapp)
- pool_webapp: 3/3 members available
- vs_webapp_https: available, accepting connections
- New log entries: pool_webapp member 10.1.1.10:80 monitor status up (expected)
Verification: PASSED
Rollback Required: No
ServiceNow Change Request Integration
When ServiceNow is available ($SERVICENOW_MCP_SCRIPT is set), every F5 configuration change MUST be gated by an approved Change Request.
Pre-Change: Create CR
python3 $MCP_CALL "python3 -u $SERVICENOW_MCP_SCRIPT" create_change_request '{"short_description":"Create pool_webapp and vs_webapp_https on F5 BIG-IP","description":"Create new pool with 3 web server members (10.1.1.10-12:80) and HTTPS virtual server (10.100.1.50:443) with SSL offload. Health monitor: HTTP. Load balancing: round-robin. Rollback: delete vs_webapp_https then pool_webapp.","category":"Network","priority":"3","risk":"moderate","impact":"3"}'
Approval Gate
python3 $MCP_CALL "python3 -u $SERVICENOW_MCP_SCRIPT" get_change_request_details '{"change_id":"CHG0012345"}'
STOP if state is not approved. Inform the human and wait.
Post-Change: Close CR
If verification passes:
python3 $MCP_CALL "python3 -u $SERVICENOW_MCP_SCRIPT" update_change_request '{"change_id":"CHG0012345","work_notes":"Change applied and verified. pool_webapp 3/3 members available, vs_webapp_https accepting connections, no errors in logs.","state":"closed"}'
If verification fails:
python3 $MCP_CALL "python3 -u $SERVICENOW_MCP_SCRIPT" update_change_request '{"change_id":"CHG0012345","work_notes":"Post-change verification FAILED. Rollback initiated. Objects removed. Human review required.","state":"review"}'
Integration with Other Skills
| Skill | Integration Point |
|---|---|
| f5-health-check | Pre-change health validation and post-change verification |
| f5-troubleshoot | Investigate failures during verification phase |
| servicenow-change-workflow | CR creation, approval gate, closure |
| drawio-diagram | Generate before/after topology diagrams |
| markmap-viz | Visualize change plan as a mind map |
| gait-session-tracking | Audit trail for every phase |
GAIT Audit Trail
Record every phase of the change in GAIT:
python3 $MCP_CALL "python3 -u $GAIT_MCP_SCRIPT" gait_record_turn '{"prompt":"F5 config change: Create pool_webapp and vs_webapp_https","response":"Phase 1 baseline captured (4 virtuals, 3 pools, no errors). Phase 2 plan approved. Phase 3 applied: created pool_webapp (3 members, HTTP monitor, round-robin) and vs_webapp_https (10.100.1.50:443, SSL offload, automap). Phase 4 verification PASSED: all members available, VIP accepting connections, no log errors. ServiceNow CR CHG0012345 closed successful.","artifacts":["f5-change-report.txt"]}'
The 5-phase workflow with GAIT creates an immutable record:
- Baseline -- GAIT commit with pre-change object state
- Plan -- GAIT commit with change plan and CR number
- Apply -- GAIT commit with exact API calls made
- Verify -- GAIT commit with post-change state and diff
- Document -- GAIT commit with final summary and CR closure