Configuration
Octopus is configured from a single declarative file (or a set of merged files). The format is
detected from the file extension: YAML (.yaml/.yml), TOML (.toml), or JSON
(.json). All three deserialize into the same schema, so YAML field names, TOML keys, and JSON
keys are identical.
The only required section is gateway, which must specify a listen address. Every other section
has defaults and may be omitted.
Implementation status. Octopus parses the entire schema documented here, but some fields are
accepted for forward-compatibility and not yet enforced at runtime. The notable ones (each
flagged on its page): the grpc block is parsed but not consumed, and
in the plugins array only script plugins are loaded
(static/dynamic plugin loading is not yet wired). The middleware wired into the request chain
today are compression, CORS (global + per-route), per-route rate limiting, script plugins, and
authentication.
gateway:
listen: "0.0.0.0:8080"
upstreams:
- name: api
instances:
- id: api-1
host: 127.0.0.1
port: 9000
routes:
- path: /api
upstream: apiFile formats01
The same configuration in each supported format:
gateway:
listen: "0.0.0.0:8080"
upstreams:
- name: api
instances:
- id: api-1
host: 127.0.0.1
port: 9000
routes:
- path: /api
upstream: api[gateway]
listen = "0.0.0.0:8080"
[[upstreams]]
name = "api"
[[upstreams.instances]]
id = "api-1"
host = "127.0.0.1"
port = 9000
[[routes]]
path = "/api"
upstream = "api"{
"gateway": { "listen": "0.0.0.0:8080" },
"upstreams": [
{
"name": "api",
"instances": [{ "id": "api-1", "host": "127.0.0.1", "port": 9000 }]
}
],
"routes": [{ "path": "/api", "upstream": "api" }]
}Durations are written in humantime form: 30s, 5m, 1h,
500ms. Sizes such as max_body_size are plain byte counts (integers), not 10MB-style
strings.
Environment variable substitution02
Before parsing, Octopus expands ${VAR} references in the raw file text (in any format). Two
forms are supported:
| Syntax | Behavior |
${VAR} | Replaced with the value of VAR. Loading fails if VAR is unset. |
${VAR:-default} | Replaced with VAR if set, otherwise the literal default. |
gateway:
listen: "${LISTEN_ADDR:-0.0.0.0:8080}"
auth_providers:
primary:
type: jwt
secret: "${JWT_SECRET}" # required — startup fails if unsetExpansion is purely textual and happens everywhere in the file, so it works for any value (addresses, secrets, full URLs).
Loading and merging03
The gateway is started with octopus serve. The -c / --config flag accepts one or more
files or directories (default: config.yaml).
# Single file
octopus serve -c config.yaml
# Multiple files, merged left to right (later wins)
octopus serve -c base.yaml -c production.yaml
# A directory — all *.yaml, *.yml, *.json, *.toml files are merged
octopus serve -c ./config.dMerge order:
Multiple
-cvalues are merged in the order given on the command line.For a directory, files are collected per extension and sorted alphabetically within each extension group (the scan order is
yaml,yml,json,toml), then merged.
Merge semantics (later file overrides earlier):
upstreams,routes, andpluginsare merged by key — bynamefor upstreams and plugins, bypathfor routes. A later entry with the same key replaces the earlier one; new keys are added.gatewayis overlaid field by field (the later file's values win;workers: 0is treated as "unset" and keeps the base value, andtls/internal_route_prefixfall back to the base when the overlay omits them).observabilityfrom the last file replaces the earlier value wholesale.
The farp, auth, auth_providers, cors, admin, grpc, and kubernetes sections are
not deep-merged. They retain the value from the first file in the merge set; later files
do not override them. Keep each of these sections defined in a single file.
Validation04
Validate a configuration without starting the gateway:
octopus validate -c config.yamlThis loads and merges exactly as serve does, then runs the validator. It checks, among other
things:
gateway.request_timeoutis greater than zero (and warns if over 5 minutes).gateway.max_body_sizeis greater than zero.When
gateway.tlsis present:cert_fileandkey_fileare non-empty,min_tls_versionis1.2or1.3, andreload_interval_secsis non-zero when cert reload is enabled.Each upstream has a non-empty
name; each instance has a non-emptyid, non-emptyhost, and a non-zeroport.Each route
pathstarts with/, has a non-emptyupstream, and references an upstream that exists.
A valid configuration prints a summary (listen address, upstream/route/plugin counts) and exits 0; an invalid one prints the error and exits 1.
Top-level schema05
These are the fields of the root Config object. Each links to its detailed reference.
| Key | Type | Default | Description |
gateway | object | — | Listener, timeouts, body limits, compression, probes, TLS. Required. |
upstreams | array | [] | Backend services and their instances. |
routes | array | [] | Path-based routing rules to upstreams. |
plugins | array | [] | Plugin instances (static or dynamic). |
farp | object | discovery off | Service discovery and auto-routing. |
observability | object | defaults | Logging, metrics, tracing. |
auth_providers | map | {} | Named authentication providers. |
auth | object | enforce off | Global auth/authz behavior. |
cors | object | none | Global CORS policy. |
admin | object | no auth | Admin dashboard access control. |
grpc | object | enabled | gRPC / gRPC-Web proxying. |
kubernetes | object | disabled | In-process Gateway API controller. |