> For the complete documentation index, see [llms.txt](https://cortex-docs.paloaltonetworks.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://cortex-docs.paloaltonetworks.com/cortex-cloud-api/broker-vm-on-appliance/network-configuration.md).

# Network configuration

Configure the on-appliance network stack: physical interfaces, Docker internal subnet, outbound proxy, NTP servers, SSL serving certificate, trusted CA bundle. All six endpoints carry a 1/sec/IP rate limit and several are ⚠️ Operationally Dangerous (see per-operation descriptions).

## Configure (or disable) a physical network interface

> Configure a physical NIC on the broker:\
> \- \`interface\_type=''\` — disable the interface.\
> \- \`interface\_type='dhcp'\` — enable DHCP.\
> \- \`interface\_type='static'\` — enable static configuration\
> &#x20; (additionally requires \`address\` and \`netmask\`; \`gateway\`\
> &#x20; optional).\
> \
> ⚠️ Operationally Dangerous. A bad configuration can render the\
> VM unreachable. Console-recovery is required to undo a\
> misconfiguration.<br>

```json
{"openapi":"3.0.3","info":{"title":"Cortex Broker Direct Public API (on-appliance)","version":"1.0.0"},"tags":[{"name":"network","description":"Configure the on-appliance network stack: physical interfaces,\nDocker internal subnet, outbound proxy, NTP servers, SSL serving\ncertificate, trusted CA bundle. All six endpoints carry a\n1/sec/IP rate limit and several are ⚠️ Operationally Dangerous\n(see per-operation descriptions).\n"}],"servers":[{"url":"https://{broker_host}","description":"The broker appliance's on-board HTTPS listener.","variables":{"broker_host":{"default":"broker.example.local","description":"Operator-chosen hostname or IP of the Broker VM appliance.\nReplace with your broker's actual address.\n"}}}],"security":[{"PublicApiToken":[]}],"components":{"securitySchemes":{"PublicApiToken":{"type":"http","scheme":"bearer","bearerFormat":"opaque","description":"Short-lived (10-minute TTL) opaque API token issued by\n[`generateToken`](#operation/generateToken). Sent as\n`Authorization: Bearer <token>`. A token that expires mid-request\ndoes NOT abort the response (DRF authenticates once at request\nstart).\n"}},"schemas":{"SetNetworkInterfaceRequest":{"type":"object","required":["interface_type","name"],"description":"When `interface_type='static'`, both `address` and `netmask`\nmust additionally be non-empty (enforced by Pydantic's\n`_static_requires_address` model validator).\n","properties":{"interface_type":{"type":"string","enum":["","dhcp","static"],"description":"`''` disables the interface. `'dhcp'` enables DHCP. `'static'`\nrequires `address` and `netmask`.\n"},"name":{"type":"string","minLength":1,"maxLength":64,"description":"Interface name (e.g., `eth0`, `eth1`)."},"address":{"type":"string","default":"","description":"IPv4 address. Required when `interface_type='static'`."},"netmask":{"type":"string","default":"","description":"IPv4 netmask. Required when `interface_type='static'`."},"gateway":{"type":"string","default":"","description":"Default gateway. Optional; at most one gateway is allowed across all interfaces."},"dns":{"type":"array","maxItems":8,"default":[],"items":{"type":"string"},"description":"DNS servers (up to 8 entries)."},"is_admin":{"type":"boolean","default":false,"description":"Whether this interface serves the broker's admin UI."}}},"PublicApiSuccessResponse":{"type":"object","description":"Canonical envelope for every successful (`2xx`) JSON response.\nWraps the per-endpoint payload (or `null` when the operation\ncarries no body content).\n","properties":{"reply":{"nullable":true,"description":"Endpoint-specific payload. Schema varies; see each\noperation's `200.content.schema`.\n"}}},"PublicApiErrorResponse":{"type":"object","description":"Canonical envelope for every error (`4xx`/`5xx`) JSON response.\n","required":["error"],"properties":{"error":{"type":"string","description":"Human-readable error message. Pydantic validation failures\nare rendered as `\"<field>: <message>; <field>: <message>; ...\"`\n(semicolon-separated) by `format_pydantic_errors`.\n"},"reply":{"nullable":true,"description":"Always `null` on error responses. Present in the envelope to\nkeep the JSON shape consistent with success responses.\n"}}}},"responses":{"EmptyOk":{"description":"Operation succeeded; response carries the empty envelope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublicApiSuccessResponse"}}}},"BadRequest":{"description":"Request body failed Pydantic validation, or a semantic\nvalidation check (CIDR shape, PEM well-formedness, ...) failed\nin the handler.\n","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublicApiErrorResponse"}}}},"Unauthorized":{"description":"Missing, malformed, or expired Bearer token.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublicApiErrorResponse"}}}},"InitialPasswordRequired":{"description":"`InitialPasswordGateMiddleware` blocked the request because the\nfactory-default admin password has not yet been replaced via\n[`resetInitialPassword`](#operation/resetInitialPassword).\n","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublicApiErrorResponse"}}}},"NetworkConflict":{"description":"Operation conflicts with the appliance's current state: subnet\noverlap with an existing physical interface, interface already\nconfigured the requested way, gateway already set on another\ninterface, etc.\n","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublicApiErrorResponse"}}}},"RateLimited":{"description":"Caller exceeded the per-IP rate limit on this endpoint (5/min\non the two bootstrap endpoints, 1/sec on the six network\nendpoints).\n","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublicApiErrorResponse"}}}},"InternalServerError":{"description":"Unexpected server-side failure; details captured in broker logs.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublicApiErrorResponse"}}}}}},"paths":{"/public_api/v1/network/interface":{"post":{"tags":["network"],"operationId":"setNetworkInterface","summary":"Configure (or disable) a physical network interface","description":"Configure a physical NIC on the broker:\n- `interface_type=''` — disable the interface.\n- `interface_type='dhcp'` — enable DHCP.\n- `interface_type='static'` — enable static configuration\n  (additionally requires `address` and `netmask`; `gateway`\n  optional).\n\n⚠️ Operationally Dangerous. A bad configuration can render the\nVM unreachable. Console-recovery is required to undo a\nmisconfiguration.\n","requestBody":{"required":true,"description":"Carries the network-interface configuration (`interface_type`, `name`, `address`, `netmask`, `gateway`, `dns`, `is_admin`).\n","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SetNetworkInterfaceRequest"}}}},"responses":{"200":{"$ref":"#/components/responses/EmptyOk"},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/InitialPasswordRequired"},"409":{"$ref":"#/components/responses/NetworkConflict"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalServerError"}}}}}}
```

## Set the Docker internal subnet

> Replace the \*\*parent address pool\*\* used by Docker's per-network\
> allocator on the broker. Docker's allocator carves slices of\
> width \`parent\_prefix + DOCKER\_SUBNET\_ADDITIONAL\_BITS\` (currently\
> +2) from this pool — a \`/18\` parent therefore yields \`/20\`\
> per-network bridges. To leave room for more than one per-network\
> bridge, supply a parent prefix of \`/22\` or wider.\
> \
> ⚠️ Operationally Dangerous. The Docker daemon is restarted,\
> which restarts every container on the bridge network. Expect\
> \*\*30-60 seconds of broker-wide unavailability\*\* — including\
> this PAPI itself, which will return 502/connection-refused\
> during the window. Treat as fire-and-poll.\
> \
> A subnet that overlaps an existing physical interface is\
> rejected with \`409\`.<br>

```json
{"openapi":"3.0.3","info":{"title":"Cortex Broker Direct Public API (on-appliance)","version":"1.0.0"},"tags":[{"name":"network","description":"Configure the on-appliance network stack: physical interfaces,\nDocker internal subnet, outbound proxy, NTP servers, SSL serving\ncertificate, trusted CA bundle. All six endpoints carry a\n1/sec/IP rate limit and several are ⚠️ Operationally Dangerous\n(see per-operation descriptions).\n"}],"servers":[{"url":"https://{broker_host}","description":"The broker appliance's on-board HTTPS listener.","variables":{"broker_host":{"default":"broker.example.local","description":"Operator-chosen hostname or IP of the Broker VM appliance.\nReplace with your broker's actual address.\n"}}}],"security":[{"PublicApiToken":[]}],"components":{"securitySchemes":{"PublicApiToken":{"type":"http","scheme":"bearer","bearerFormat":"opaque","description":"Short-lived (10-minute TTL) opaque API token issued by\n[`generateToken`](#operation/generateToken). Sent as\n`Authorization: Bearer <token>`. A token that expires mid-request\ndoes NOT abort the response (DRF authenticates once at request\nstart).\n"}},"schemas":{"SetInternalSubnetRequest":{"description":"Body for `setInternalSubnet`. The `docker_subnet` is the parent address pool, not a single bridge subnet — see the endpoint description for pool semantics.\n","type":"object","required":["docker_subnet"],"properties":{"docker_subnet":{"type":"string","minLength":1,"maxLength":64,"description":"Parent address pool CIDR. Per-network bridges are carved\nfrom this pool at `parent_prefix + 2` width (e.g., a `/18`\nyields `/20` bridges).\n"}}},"PublicApiSuccessResponse":{"type":"object","description":"Canonical envelope for every successful (`2xx`) JSON response.\nWraps the per-endpoint payload (or `null` when the operation\ncarries no body content).\n","properties":{"reply":{"nullable":true,"description":"Endpoint-specific payload. Schema varies; see each\noperation's `200.content.schema`.\n"}}},"PublicApiErrorResponse":{"type":"object","description":"Canonical envelope for every error (`4xx`/`5xx`) JSON response.\n","required":["error"],"properties":{"error":{"type":"string","description":"Human-readable error message. Pydantic validation failures\nare rendered as `\"<field>: <message>; <field>: <message>; ...\"`\n(semicolon-separated) by `format_pydantic_errors`.\n"},"reply":{"nullable":true,"description":"Always `null` on error responses. Present in the envelope to\nkeep the JSON shape consistent with success responses.\n"}}}},"responses":{"EmptyOk":{"description":"Operation succeeded; response carries the empty envelope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublicApiSuccessResponse"}}}},"BadRequest":{"description":"Request body failed Pydantic validation, or a semantic\nvalidation check (CIDR shape, PEM well-formedness, ...) failed\nin the handler.\n","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublicApiErrorResponse"}}}},"Unauthorized":{"description":"Missing, malformed, or expired Bearer token.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublicApiErrorResponse"}}}},"InitialPasswordRequired":{"description":"`InitialPasswordGateMiddleware` blocked the request because the\nfactory-default admin password has not yet been replaced via\n[`resetInitialPassword`](#operation/resetInitialPassword).\n","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublicApiErrorResponse"}}}},"NetworkConflict":{"description":"Operation conflicts with the appliance's current state: subnet\noverlap with an existing physical interface, interface already\nconfigured the requested way, gateway already set on another\ninterface, etc.\n","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublicApiErrorResponse"}}}},"RateLimited":{"description":"Caller exceeded the per-IP rate limit on this endpoint (5/min\non the two bootstrap endpoints, 1/sec on the six network\nendpoints).\n","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublicApiErrorResponse"}}}},"InternalServerError":{"description":"Unexpected server-side failure; details captured in broker logs.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublicApiErrorResponse"}}}}}},"paths":{"/public_api/v1/network/internal_subnet":{"post":{"tags":["network"],"operationId":"setInternalSubnet","summary":"Set the Docker internal subnet","description":"Replace the **parent address pool** used by Docker's per-network\nallocator on the broker. Docker's allocator carves slices of\nwidth `parent_prefix + DOCKER_SUBNET_ADDITIONAL_BITS` (currently\n+2) from this pool — a `/18` parent therefore yields `/20`\nper-network bridges. To leave room for more than one per-network\nbridge, supply a parent prefix of `/22` or wider.\n\n⚠️ Operationally Dangerous. The Docker daemon is restarted,\nwhich restarts every container on the bridge network. Expect\n**30-60 seconds of broker-wide unavailability** — including\nthis PAPI itself, which will return 502/connection-refused\nduring the window. Treat as fire-and-poll.\n\nA subnet that overlaps an existing physical interface is\nrejected with `409`.\n","requestBody":{"required":true,"description":"Carries the parent CIDR (`docker_subnet`) used as Docker's per-network address pool.\n","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SetInternalSubnetRequest"}}}},"responses":{"200":{"$ref":"#/components/responses/EmptyOk"},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/InitialPasswordRequired"},"409":{"$ref":"#/components/responses/NetworkConflict"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalServerError"}}}}}}
```

## Configure the outbound HTTP/SOCKS proxy

> Configure the outbound proxy used by all broker services for\
> upstream connectivity.\
> \
> \- \`proxy\_type=''\` disables the proxy.\
> \- When \`proxy\_type\` is set, \`host\` and \`port\` are required.\
> \- \`pwd\` follows tristate semantics:\
> &#x20; \- \*\*omitted / \`null\`\*\* — keep the existing stored password.\
> &#x20; \- \*\*\`""\`\*\* — clear the password.\
> &#x20; \- \*\*\`"value"\`\*\* — set the password to \`value\`.\
> \
> Side effect: triggers \`restart\_services\_and\_applets()\` — services\
> handling the in-flight API request are deliberately excluded so\
> the response can return cleanly.<br>

```json
{"openapi":"3.0.3","info":{"title":"Cortex Broker Direct Public API (on-appliance)","version":"1.0.0"},"tags":[{"name":"network","description":"Configure the on-appliance network stack: physical interfaces,\nDocker internal subnet, outbound proxy, NTP servers, SSL serving\ncertificate, trusted CA bundle. All six endpoints carry a\n1/sec/IP rate limit and several are ⚠️ Operationally Dangerous\n(see per-operation descriptions).\n"}],"servers":[{"url":"https://{broker_host}","description":"The broker appliance's on-board HTTPS listener.","variables":{"broker_host":{"default":"broker.example.local","description":"Operator-chosen hostname or IP of the Broker VM appliance.\nReplace with your broker's actual address.\n"}}}],"security":[{"PublicApiToken":[]}],"components":{"securitySchemes":{"PublicApiToken":{"type":"http","scheme":"bearer","bearerFormat":"opaque","description":"Short-lived (10-minute TTL) opaque API token issued by\n[`generateToken`](#operation/generateToken). Sent as\n`Authorization: Bearer <token>`. A token that expires mid-request\ndoes NOT abort the response (DRF authenticates once at request\nstart).\n"}},"schemas":{"SetProxyRequest":{"type":"object","required":["proxy_type"],"description":"`pwd` follows tristate semantics — omit (`null`) to preserve\nthe stored password, set to `\"\"` to clear it, set to a value\nto replace it. When `proxy_type` is non-empty, both `host` and\n`port` are required (cross-field rule, enforced server-side).\n","properties":{"proxy_type":{"type":"string","enum":["","http","socks4","socks5"]},"host":{"type":"string","default":""},"port":{"type":"integer","nullable":true,"minimum":1,"maximum":65535},"user":{"type":"string","default":""},"pwd":{"type":"string","format":"password","nullable":true,"description":"Tristate: `null`/absent = keep existing, `\"\"` = clear,\n`\"value\"` = set.\n"}}},"PublicApiSuccessResponse":{"type":"object","description":"Canonical envelope for every successful (`2xx`) JSON response.\nWraps the per-endpoint payload (or `null` when the operation\ncarries no body content).\n","properties":{"reply":{"nullable":true,"description":"Endpoint-specific payload. Schema varies; see each\noperation's `200.content.schema`.\n"}}},"PublicApiErrorResponse":{"type":"object","description":"Canonical envelope for every error (`4xx`/`5xx`) JSON response.\n","required":["error"],"properties":{"error":{"type":"string","description":"Human-readable error message. Pydantic validation failures\nare rendered as `\"<field>: <message>; <field>: <message>; ...\"`\n(semicolon-separated) by `format_pydantic_errors`.\n"},"reply":{"nullable":true,"description":"Always `null` on error responses. Present in the envelope to\nkeep the JSON shape consistent with success responses.\n"}}}},"responses":{"EmptyOk":{"description":"Operation succeeded; response carries the empty envelope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublicApiSuccessResponse"}}}},"BadRequest":{"description":"Request body failed Pydantic validation, or a semantic\nvalidation check (CIDR shape, PEM well-formedness, ...) failed\nin the handler.\n","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublicApiErrorResponse"}}}},"Unauthorized":{"description":"Missing, malformed, or expired Bearer token.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublicApiErrorResponse"}}}},"InitialPasswordRequired":{"description":"`InitialPasswordGateMiddleware` blocked the request because the\nfactory-default admin password has not yet been replaced via\n[`resetInitialPassword`](#operation/resetInitialPassword).\n","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublicApiErrorResponse"}}}},"RateLimited":{"description":"Caller exceeded the per-IP rate limit on this endpoint (5/min\non the two bootstrap endpoints, 1/sec on the six network\nendpoints).\n","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublicApiErrorResponse"}}}},"InternalServerError":{"description":"Unexpected server-side failure; details captured in broker logs.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublicApiErrorResponse"}}}}}},"paths":{"/public_api/v1/network/proxy":{"post":{"tags":["network"],"operationId":"setProxy","summary":"Configure the outbound HTTP/SOCKS proxy","description":"Configure the outbound proxy used by all broker services for\nupstream connectivity.\n\n- `proxy_type=''` disables the proxy.\n- When `proxy_type` is set, `host` and `port` are required.\n- `pwd` follows tristate semantics:\n  - **omitted / `null`** — keep the existing stored password.\n  - **`\"\"`** — clear the password.\n  - **`\"value\"`** — set the password to `value`.\n\nSide effect: triggers `restart_services_and_applets()` — services\nhandling the in-flight API request are deliberately excluded so\nthe response can return cleanly.\n","requestBody":{"required":true,"description":"Carries the outbound proxy configuration (`proxy_type`, `host`, `port`, `user`, `pwd`). See `pwd` tristate semantics in the operation description.\n","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SetProxyRequest"}}}},"responses":{"200":{"$ref":"#/components/responses/EmptyOk"},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/InitialPasswordRequired"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalServerError"}}}}}}
```

## Replace the configured NTP servers

> Replace the broker's NTP server list. At least one entry is\
> required, at most \`MAX\_NTP\_SERVERS\` (10).\
> \
> \*\*Reachability is NOT pre-validated.\*\* Servers that are\
> unreachable from the broker are silently accepted (parity with\
> the WebUI). The broker reports NTP-sync failures through normal\
> monitoring channels.<br>

```json
{"openapi":"3.0.3","info":{"title":"Cortex Broker Direct Public API (on-appliance)","version":"1.0.0"},"tags":[{"name":"network","description":"Configure the on-appliance network stack: physical interfaces,\nDocker internal subnet, outbound proxy, NTP servers, SSL serving\ncertificate, trusted CA bundle. All six endpoints carry a\n1/sec/IP rate limit and several are ⚠️ Operationally Dangerous\n(see per-operation descriptions).\n"}],"servers":[{"url":"https://{broker_host}","description":"The broker appliance's on-board HTTPS listener.","variables":{"broker_host":{"default":"broker.example.local","description":"Operator-chosen hostname or IP of the Broker VM appliance.\nReplace with your broker's actual address.\n"}}}],"security":[{"PublicApiToken":[]}],"components":{"securitySchemes":{"PublicApiToken":{"type":"http","scheme":"bearer","bearerFormat":"opaque","description":"Short-lived (10-minute TTL) opaque API token issued by\n[`generateToken`](#operation/generateToken). Sent as\n`Authorization: Bearer <token>`. A token that expires mid-request\ndoes NOT abort the response (DRF authenticates once at request\nstart).\n"}},"schemas":{"SetNtpRequest":{"description":"Body for `setNtp`. Replaces the broker's NTP server list (between 1 and 10 entries).\n","type":"object","required":["ntp"],"properties":{"ntp":{"type":"array","minItems":1,"maxItems":10,"items":{"type":"string","description":"Hostname or IP of an NTP server."}}}},"PublicApiSuccessResponse":{"type":"object","description":"Canonical envelope for every successful (`2xx`) JSON response.\nWraps the per-endpoint payload (or `null` when the operation\ncarries no body content).\n","properties":{"reply":{"nullable":true,"description":"Endpoint-specific payload. Schema varies; see each\noperation's `200.content.schema`.\n"}}},"PublicApiErrorResponse":{"type":"object","description":"Canonical envelope for every error (`4xx`/`5xx`) JSON response.\n","required":["error"],"properties":{"error":{"type":"string","description":"Human-readable error message. Pydantic validation failures\nare rendered as `\"<field>: <message>; <field>: <message>; ...\"`\n(semicolon-separated) by `format_pydantic_errors`.\n"},"reply":{"nullable":true,"description":"Always `null` on error responses. Present in the envelope to\nkeep the JSON shape consistent with success responses.\n"}}}},"responses":{"EmptyOk":{"description":"Operation succeeded; response carries the empty envelope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublicApiSuccessResponse"}}}},"BadRequest":{"description":"Request body failed Pydantic validation, or a semantic\nvalidation check (CIDR shape, PEM well-formedness, ...) failed\nin the handler.\n","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublicApiErrorResponse"}}}},"Unauthorized":{"description":"Missing, malformed, or expired Bearer token.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublicApiErrorResponse"}}}},"InitialPasswordRequired":{"description":"`InitialPasswordGateMiddleware` blocked the request because the\nfactory-default admin password has not yet been replaced via\n[`resetInitialPassword`](#operation/resetInitialPassword).\n","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublicApiErrorResponse"}}}},"RateLimited":{"description":"Caller exceeded the per-IP rate limit on this endpoint (5/min\non the two bootstrap endpoints, 1/sec on the six network\nendpoints).\n","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublicApiErrorResponse"}}}},"InternalServerError":{"description":"Unexpected server-side failure; details captured in broker logs.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublicApiErrorResponse"}}}}}},"paths":{"/public_api/v1/network/ntp":{"post":{"tags":["network"],"operationId":"setNtp","summary":"Replace the configured NTP servers","description":"Replace the broker's NTP server list. At least one entry is\nrequired, at most `MAX_NTP_SERVERS` (10).\n\n**Reachability is NOT pre-validated.** Servers that are\nunreachable from the broker are silently accepted (parity with\nthe WebUI). The broker reports NTP-sync failures through normal\nmonitoring channels.\n","requestBody":{"required":true,"description":"Carries the replacement list of `ntp` servers (1..10 entries).\n","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SetNtpRequest"}}}},"responses":{"200":{"$ref":"#/components/responses/EmptyOk"},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/InitialPasswordRequired"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalServerError"}}}}}}
```

## Install a custom SSL serving certificate

> Install a custom private key + certificate-chain pair as the\
> broker's HTTPS serving identity (replacing the self-signed\
> default that ships with a fresh broker).\
> \
> Both \`ssl\_key\` and \`ssl\_cert\` are \*\*base64-encoded\*\* PEM\
> payloads. Each is capped at \`MAX\_BASE64\_CERT\_BYTES\` (\~1.4 MiB\
> encoded) to bound the body size.\
> \
> ⚠️ Operationally Dangerous. The nginx serving cert is\
> replaced; a malformed PEM may break HTTPS access (in-flight\
> sessions remain valid; the next handshake uses the new cert).<br>

```json
{"openapi":"3.0.3","info":{"title":"Cortex Broker Direct Public API (on-appliance)","version":"1.0.0"},"tags":[{"name":"network","description":"Configure the on-appliance network stack: physical interfaces,\nDocker internal subnet, outbound proxy, NTP servers, SSL serving\ncertificate, trusted CA bundle. All six endpoints carry a\n1/sec/IP rate limit and several are ⚠️ Operationally Dangerous\n(see per-operation descriptions).\n"}],"servers":[{"url":"https://{broker_host}","description":"The broker appliance's on-board HTTPS listener.","variables":{"broker_host":{"default":"broker.example.local","description":"Operator-chosen hostname or IP of the Broker VM appliance.\nReplace with your broker's actual address.\n"}}}],"security":[{"PublicApiToken":[]}],"components":{"securitySchemes":{"PublicApiToken":{"type":"http","scheme":"bearer","bearerFormat":"opaque","description":"Short-lived (10-minute TTL) opaque API token issued by\n[`generateToken`](#operation/generateToken). Sent as\n`Authorization: Bearer <token>`. A token that expires mid-request\ndoes NOT abort the response (DRF authenticates once at request\nstart).\n"}},"schemas":{"SetSslCertificateRequest":{"description":"Body for `setSslCertificate`. The `ssl_key` and `ssl_cert` are base64-encoded PEM payloads, each capped at ~1.4 MiB encoded.\n","type":"object","required":["ssl_key","ssl_cert"],"properties":{"ssl_key":{"type":"string","format":"password","minLength":1,"maxLength":1500000,"description":"Base64-encoded PEM private key (capped at ~1.4 MiB encoded)."},"ssl_cert":{"type":"string","minLength":1,"maxLength":1500000,"description":"Base64-encoded PEM certificate chain (capped at ~1.4 MiB encoded)."},"ssl_key_name":{"type":"string","default":"","maxLength":128,"description":"Optional display name for the certificate (max 128 chars)."}}},"PublicApiSuccessResponse":{"type":"object","description":"Canonical envelope for every successful (`2xx`) JSON response.\nWraps the per-endpoint payload (or `null` when the operation\ncarries no body content).\n","properties":{"reply":{"nullable":true,"description":"Endpoint-specific payload. Schema varies; see each\noperation's `200.content.schema`.\n"}}},"PublicApiErrorResponse":{"type":"object","description":"Canonical envelope for every error (`4xx`/`5xx`) JSON response.\n","required":["error"],"properties":{"error":{"type":"string","description":"Human-readable error message. Pydantic validation failures\nare rendered as `\"<field>: <message>; <field>: <message>; ...\"`\n(semicolon-separated) by `format_pydantic_errors`.\n"},"reply":{"nullable":true,"description":"Always `null` on error responses. Present in the envelope to\nkeep the JSON shape consistent with success responses.\n"}}}},"responses":{"EmptyOk":{"description":"Operation succeeded; response carries the empty envelope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublicApiSuccessResponse"}}}},"BadRequest":{"description":"Request body failed Pydantic validation, or a semantic\nvalidation check (CIDR shape, PEM well-formedness, ...) failed\nin the handler.\n","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublicApiErrorResponse"}}}},"Unauthorized":{"description":"Missing, malformed, or expired Bearer token.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublicApiErrorResponse"}}}},"InitialPasswordRequired":{"description":"`InitialPasswordGateMiddleware` blocked the request because the\nfactory-default admin password has not yet been replaced via\n[`resetInitialPassword`](#operation/resetInitialPassword).\n","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublicApiErrorResponse"}}}},"RateLimited":{"description":"Caller exceeded the per-IP rate limit on this endpoint (5/min\non the two bootstrap endpoints, 1/sec on the six network\nendpoints).\n","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublicApiErrorResponse"}}}},"InternalServerError":{"description":"Unexpected server-side failure; details captured in broker logs.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublicApiErrorResponse"}}}}}},"paths":{"/public_api/v1/network/ssl_certificate":{"post":{"tags":["network"],"operationId":"setSslCertificate","summary":"Install a custom SSL serving certificate","description":"Install a custom private key + certificate-chain pair as the\nbroker's HTTPS serving identity (replacing the self-signed\ndefault that ships with a fresh broker).\n\nBoth `ssl_key` and `ssl_cert` are **base64-encoded** PEM\npayloads. Each is capped at `MAX_BASE64_CERT_BYTES` (~1.4 MiB\nencoded) to bound the body size.\n\n⚠️ Operationally Dangerous. The nginx serving cert is\nreplaced; a malformed PEM may break HTTPS access (in-flight\nsessions remain valid; the next handshake uses the new cert).\n","requestBody":{"required":true,"description":"Carries base64-encoded PEM `ssl_key` + `ssl_cert` to install as the broker's HTTPS serving identity.\n","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SetSslCertificateRequest"}}}},"responses":{"200":{"$ref":"#/components/responses/EmptyOk"},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/InitialPasswordRequired"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalServerError"}}}}}}
```

## Install a custom trusted CA bundle

> Install a custom trusted-CA bundle on the broker so it trusts\
> certificates issued by an internal / private CA when reaching\
> out to upstream HTTPS services (proxies, SAML IdPs, syslog\
> secure\_TCP targets, etc.).\
> \
> \`file\` is a \*\*base64-encoded\*\* PEM CA bundle, capped at\
> \`MAX\_BASE64\_CA\_BYTES\` (\~1.4 MiB encoded).\
> \
> Returns \`500\` (not \`200\`) when \`update-ca-certificates\` fails on\
> the appliance.<br>

```json
{"openapi":"3.0.3","info":{"title":"Cortex Broker Direct Public API (on-appliance)","version":"1.0.0"},"tags":[{"name":"network","description":"Configure the on-appliance network stack: physical interfaces,\nDocker internal subnet, outbound proxy, NTP servers, SSL serving\ncertificate, trusted CA bundle. All six endpoints carry a\n1/sec/IP rate limit and several are ⚠️ Operationally Dangerous\n(see per-operation descriptions).\n"}],"servers":[{"url":"https://{broker_host}","description":"The broker appliance's on-board HTTPS listener.","variables":{"broker_host":{"default":"broker.example.local","description":"Operator-chosen hostname or IP of the Broker VM appliance.\nReplace with your broker's actual address.\n"}}}],"security":[{"PublicApiToken":[]}],"components":{"securitySchemes":{"PublicApiToken":{"type":"http","scheme":"bearer","bearerFormat":"opaque","description":"Short-lived (10-minute TTL) opaque API token issued by\n[`generateToken`](#operation/generateToken). Sent as\n`Authorization: Bearer <token>`. A token that expires mid-request\ndoes NOT abort the response (DRF authenticates once at request\nstart).\n"}},"schemas":{"SetTrustedCaRequest":{"description":"Body for `setTrustedCa`. The `file` is a base64-encoded PEM CA bundle, capped at ~1.4 MiB encoded.\n","type":"object","required":["file"],"properties":{"file":{"type":"string","minLength":1,"maxLength":1500000,"description":"Base64-encoded PEM CA bundle (capped at ~1.4 MiB encoded)."}}},"PublicApiSuccessResponse":{"type":"object","description":"Canonical envelope for every successful (`2xx`) JSON response.\nWraps the per-endpoint payload (or `null` when the operation\ncarries no body content).\n","properties":{"reply":{"nullable":true,"description":"Endpoint-specific payload. Schema varies; see each\noperation's `200.content.schema`.\n"}}},"PublicApiErrorResponse":{"type":"object","description":"Canonical envelope for every error (`4xx`/`5xx`) JSON response.\n","required":["error"],"properties":{"error":{"type":"string","description":"Human-readable error message. Pydantic validation failures\nare rendered as `\"<field>: <message>; <field>: <message>; ...\"`\n(semicolon-separated) by `format_pydantic_errors`.\n"},"reply":{"nullable":true,"description":"Always `null` on error responses. Present in the envelope to\nkeep the JSON shape consistent with success responses.\n"}}}},"responses":{"EmptyOk":{"description":"Operation succeeded; response carries the empty envelope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublicApiSuccessResponse"}}}},"BadRequest":{"description":"Request body failed Pydantic validation, or a semantic\nvalidation check (CIDR shape, PEM well-formedness, ...) failed\nin the handler.\n","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublicApiErrorResponse"}}}},"Unauthorized":{"description":"Missing, malformed, or expired Bearer token.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublicApiErrorResponse"}}}},"InitialPasswordRequired":{"description":"`InitialPasswordGateMiddleware` blocked the request because the\nfactory-default admin password has not yet been replaced via\n[`resetInitialPassword`](#operation/resetInitialPassword).\n","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublicApiErrorResponse"}}}},"RateLimited":{"description":"Caller exceeded the per-IP rate limit on this endpoint (5/min\non the two bootstrap endpoints, 1/sec on the six network\nendpoints).\n","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublicApiErrorResponse"}}}},"InternalServerError":{"description":"Unexpected server-side failure; details captured in broker logs.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublicApiErrorResponse"}}}}}},"paths":{"/public_api/v1/network/trusted_ca":{"post":{"tags":["network"],"operationId":"setTrustedCa","summary":"Install a custom trusted CA bundle","description":"Install a custom trusted-CA bundle on the broker so it trusts\ncertificates issued by an internal / private CA when reaching\nout to upstream HTTPS services (proxies, SAML IdPs, syslog\nsecure_TCP targets, etc.).\n\n`file` is a **base64-encoded** PEM CA bundle, capped at\n`MAX_BASE64_CA_BYTES` (~1.4 MiB encoded).\n\nReturns `500` (not `200`) when `update-ca-certificates` fails on\nthe appliance.\n","requestBody":{"required":true,"description":"Carries a base64-encoded PEM CA bundle (`file`) to install as a custom trusted CA.\n","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SetTrustedCaRequest"}}}},"responses":{"200":{"$ref":"#/components/responses/EmptyOk"},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/InitialPasswordRequired"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalServerError"}}}}}}
```


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://cortex-docs.paloaltonetworks.com/cortex-cloud-api/broker-vm-on-appliance/network-configuration.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
