ipset-load-balancing — independently scanned and version-tracked by SaferSkills.
SaferSkills independently audited ipset-load-balancing (Agent Skill) and scored it 100/100 (green). The audit ran 55 deterministic rules across Security, Supply Chain, Maintenance, Transparency, and Community; it found 0 high-severity and 0 lower-severity findings. The full rule-by-rule trace and per-finding evidence are below. Free, methodology-open.
Findings & checks · 0 flagged
Every scanned point with the score it earned and what moved between them.
First recorded scan — no prior version to compare against.
The primary manifest — the file an agent reads to learn what this artifact does.
Tool availability: some MCP tools named here live in thefulltoolset profile — if one is not advertised on this connection, tell the user to reconnect the MCP server with?toolsets=full(or use thecplnCLI fallback). Reads and deletes work on every profile via the genericlist_resources/get_resource/delete_resourcetools.
An IP set reserves one static public IPv4 address per location and attaches it to a direct (per-workload) or dedicated (per-GVC) load balancer. The linking is bidirectional, and the recurring failure is configuring only one side: the IP set's spec.link must point at the workload/GVC AND that target's load balancer must reference the IP set back — otherwise addresses sit unbound and the IP set carries status.warning: Cross-link misconfiguration. The workload skill is primary for the LB-type picker and routing basics; this skill carries the full configuration.
| Type | Scope | What it adds | Cost |
|---|---|---|---|
| Default (shared) | every workload | HTTP/HTTPS on 80/443, nothing to configure | included |
| Direct | one workload | raw TCP/UDP on external ports 22-32768, static IPs, TLS passthrough | charged while enabled |
| Dedicated | whole GVC | domain custom ports and TCP routing, wildcard and accept-all hosts, redirects, trusted proxies, static IPs | per location (multiZone adds cross-zone charges) |
Toggling the direct block (workload) or dedicated flag (GVC) requires the `configureLoadBalancer` permission on that resource — edit does not imply it (403 "Not allowed to change loadBalancer configuration"); manage covers it.
kind: ipset
name: partner-ips
spec:
link: //gvc/GVC/workload/WORKLOAD # or //gvc/GVC for a dedicated LB
locations:
- name: //location/aws-us-west-2
retentionPolicy: keep # keep | freeHow allocation actually works:
spec.link, no allocation — spec.locations alone does nothing.spec.locations pins a per-location retentionPolicy; unlisted locations behave as keep while in the GVC. Workload links require the GVC segment — //workload/WORKLOAD without it is rejected.keep (default) allocates eagerly and holds the IP through unlinking, GVC location removal, and target deletion (state drops to unbound, billing continues until the IP set is deleted). free allocates only while bound and releases once the location leaves the GVC or the link/target goes away.update_ipset with removeLink: true) so free locations release, then delete the IP set to release the rest.state: bound means both sides point at each other; unbound means allocated but unused. Delete is blocked with 400 while any address is bound — remove the back-link first. Re-adding a location later does NOT return the same IP.status.error "provider not configured to use IpSets"; cloud IP-quota errors also land in status.error.One cloud L4 load balancer per location running the workload, with externalTrafficPolicy: Local so the client IP reaches the workload. No TLS termination — the workload owns its certificates. No domain registration needed: each location's address is published on the workload's canonical endpoint DNS with latency-based geo routing, and status.canonicalEndpoint switches to the first port's scheme://HOST:externalPort. Custom hostnames can CNAME to that endpoint. Inbound firewall CIDRs still apply — they become cloud-level source ranges on the LB.
spec:
loadBalancer:
direct:
enabled: true
ipSet: //ipset/partner-ips # optional static IPs; that IP set must link back to this workload
ports:
- externalPort: 5432 # 22-32768
protocol: TCP # TCP or UDP
containerPort: 5432 # plain number 80-65535; reserved: 8012, 8022, 9090, 9091, 15000, 15001, 15006, 15020, 15021, 15090, 41000
- externalPort: 443
protocol: TCP
scheme: https # display-only (http|tcp|https|ws|wss): sets the URL scheme shown in UI/statusSet with mcp__cpln__configure_workload_load_balancer — it replaces the whole spec.loadBalancer block (remove: true clears it) and rolls a new deployment (about a minute).
spec.loadBalancer.geoLocation)Injects MaxMind GeoLite2 client-location headers on inbound HTTP requests — works with any LB type, no effect on non-HTTP ports. Set enabled: true plus headers naming at least one of asn/city/country/region (names unique, max 128 chars each). Matching client-sent headers are replaced, so apps can trust the values; the country header carries the two-letter ISO code. Filtering on these headers (geo blocking) lives in the firewall-networking skill.
spec.loadBalancer.replicaDirect: true)Stateful workloads only (rejected for other types, including vm), capped by a separate quota of 6 replicas per workload. Each replica becomes addressable as replica-INDEX. on the workload's endpoints; internal names appear in status.replicaInternalNames. Per-replica custom-domain routing is in the domain skill; replica identities and database patterns in stateful-storage.
A GVC setting — set with mcp__cpln__update_gvc (the loadBalancer object is replaced wholesale):
spec:
loadBalancer:
dedicated: true
ipSet: //ipset/gvc-ips # optional; that IP set must link back to //gvc/GVC
trustedProxies: 0 # 0 (default) source client IP | 1 last X-Forwarded-For address | 2 second-to-last; sets the logged IP and X-Envoy-External-Address
multiZone: { enabled: false } # cross-zone load balancing, extra charges
redirect:
class:
status5xx: https://errors.example.com # any 500-level response (must be a valid URI)
status401: https://auth.example.com/login?return_to=%REQ(:path)% # supports Envoy format stringsRequired before domains can use custom ports or the TCP protocol (without it those deploy as warnings and never route) and for wildcard / accept-all hosts — details in the domain skill. Enabling or disabling it can cause a brief connectivity blip while DNS propagates. Its access logs are queryable as {gvc="GVC", workload="_loadbalancer"}.
mcp__cpln__get_resource (kind="ipset") — every status.ipAddresses[].state is bound, and no status.warning (cross-link) or status.error (provider/quota). Share the ip values only once bound.mcp__cpln__list_deployments — all locations ready after an LB change; the workload's status.canonicalEndpoint reflects the direct-LB scheme and port.CPLN_TOKEN + cpln ipset get NAME --org ORG -o yaml.| Symptom | Cause and fix |
|---|---|
IPs stay unbound, warning Cross-link misconfiguration: /org/... | Only one side is linked — the object named in the warning points here without a matching spec.link (or vice versa); configure both sides |
| No IPs allocated at all | spec.link missing (locations alone allocate nothing), or the linked GVC has no locations |
| Delete fails 400 "one or more ip addresses are bound" | Remove the workload/GVC back-link or pass removeLink: true to update_ipset, wait for unbound, delete again |
Still billed after setting free | The location is still active in the GVC — free releases only when it leaves the GVC or the IP set is unlinked |
status.error "provider not configured to use IpSets" | That location's cloud has no IP-set support (AWS, GCP, Azure only — including BYOK on them) |
status.error AddressLimitExceeded / QUOTA_EXCEEDED / PublicIPCountLimitReached | Cloud-account IP quota exhausted in that region — request an increase from the provider |
| 403 "not granted [configureLoadBalancer]" | Toggling direct/dedicated needs that permission — edit alone is not enough |
API rejects containerPort | It is a plain number (80-65535 minus reserved ports); the docs' containerPort: {port: N} object form is wrong |
| Deploy warning "TCP access can only be restricted to specific ip addresses when using a custom domain and the GVC has dedicated loadBalancer enabled" | Inbound CIDR rules on a TCP port need the dedicated LB (custom domain) or a direct LB — the shared LB cannot enforce them |
| Tool | Purpose |
|---|---|
mcp__cpln__create_ipset | Create with optional link and locations[] (retentionPolicy defaults to keep); friendly location names resolve server-side |
mcp__cpln__update_ipset | Description, tags, replace link, or removeLink: true to detach |
mcp__cpln__add_ipset_location | Add locations or overwrite an existing location's retentionPolicy |
mcp__cpln__remove_ipset_location | Drop location entries (releases only IPs whose location is no longer active in the GVC) |
mcp__cpln__list_resources / mcp__cpln__get_resource / mcp__cpln__delete_resource (kind="ipset") | Read, and delete (releases every IP; blocked while bound) |
mcp__cpln__configure_workload_load_balancer | Workload side: direct, geoLocation, replicaDirect (remove: true clears) |
mcp__cpln__update_gvc | GVC side: loadBalancer (dedicated, ipSet, trustedProxies, multiZone, redirect) |
CLI fallback: cpln ipset create --name NAME --link LINK --location LOC,POLICY, plus add-location / update-location / remove-location REF --location ... and get / delete. cpln gvc update --set cannot reach spec.loadBalancer — use cpln gvc edit or cpln apply.
configure_workload_* tools.~30 seconds. Free. No account. Every finding cites a rule and a line of evidence.