sample.config.yaml
Rama master · réplica de lectura del repositorio original.
# Aastro - example configuration showcasing every available option.
#
# This file is meant as a reference, not a copy-paste production config.
# Most blocks are optional; uncomment and adjust what you actually need.
#
# Required top-level sections: schema, gateway.server, gateway.admin, gateway.routing.
# Everything else has sensible defaults.
schema: v1
debug: false # verbose logging across router, scatter, and upstream components
gateway:
# ── Service identity ─────────────────────────────────────────────────────
# Appears as service.name in OpenTelemetry resource attributes.
service:
name: aastro
# ── Data port ────────────────────────────────────────────────────────────
# Serves API traffic. Optionally protected by TLS or mTLS.
server:
port: 7805
timeout: 20s # read + write timeout per request
header_timeout: 5s # Slowloris defence - caps header read time
http2: auto # auto | on | off - auto negotiates HTTP/2 over TLS, nothing without it.
# "on" requires tls.enabled (no cleartext HTTP/2 / h2c support).
# "off" pins the data port to HTTP/1.1 even over TLS.
# TLS / mTLS on the data port.
# Remove the tls block entirely for plain HTTP.
tls:
enabled: true
cert_file: /etc/aastro/server.crt
key_file: /etc/aastro/server.key
min_version: "1.2" # 1.2 or 1.3 - older versions are not selectable
client_auth: require # none | optional | require
client_ca_file: /etc/aastro/client-ca.crt # required unless client_auth=none
# ── Admin port ───────────────────────────────────────────────────────────
# Health probes, metrics, pprof. Bound to localhost by default.
# Never TLS-terminated - kubelet probes and Prometheus scrape over plain HTTP
# even when the data port enforces mTLS.
admin:
port: 9090
bind_addr: 127.0.0.1 # set to 0.0.0.0 only if Prometheus runs outside the pod
timeout: 5m # generous to accommodate long pprof captures
header_timeout: 5s
enable_pprof: true # exposes /debug/pprof/ on the admin port
# ── Observability ────────────────────────────────────────────────────────
# Push-based instrumentation. Metrics in prometheus mode also exposes
# /metrics on the admin port; OTLP mode is purely push.
observability:
metrics:
enabled: true
exporter: prometheus # prometheus | otlp
# OTLP config is used only when exporter=otlp:
otlp:
endpoint: otel-collector:4318
insecure: true
interval: 10s
tracing:
enabled: true
exporter: otlp
sampling_ratio: 1.0 # 0.0–1.0 (1.0 = sample every trace)
otlp:
endpoint: otel-collector:4318
insecure: true
interval: 10s
# ── Routing ──────────────────────────────────────────────────────────────
routing:
# CIDR ranges whose X-Forwarded-* headers are appended to rather than overwritten.
# Leave empty if Aastro is your outermost edge.
trusted_proxies:
- 127.0.0.1/32
- 10.0.0.0/8
# Per-IP rate limiter. The IP is the one extracted via trusted-proxy resolution.
rate_limiter:
enabled: true
config:
limit: 100
window: 1s
# ── Flow examples ──────────────────────────────────────────────────────
# A flow defines: how a request is matched, which upstreams it scatters to,
# how their responses are aggregated, and which plugins/middlewares run.
flows:
# ── Example 1: merge aggregation across two upstreams ────────────────
# Combines responses from `users` and `orders` services into a single
# JSON object. Returns 206 Partial Content if one fails and best_effort
# is enabled.
- path: /api/v1/customers/{customer_id}
method: GET
aggregation:
strategy: merge # merge | array | namespace
best_effort: true # return partial data on upstream failures
on_conflict:
policy: prefer # overwrite | first | error | prefer
prefer_upstream: users # this upstream wins on key collision
# Cross-cutting middlewares wrap the entire flow handler.
# First in the list = outermost wrapper.
middlewares:
- name: recoverer
source: builtin
- name: logger
source: builtin
- name: auth
source: builtin
config:
alg: HS256
issuer: https://auth.example.com
audience: api
hmac_secret: "base64secret"
# Plugins run at specific lifecycle phases (request / response).
plugins:
- name: snakeify
source: builtin
- name: tenant_resolver
source: file
path: /etc/aastro/plugins/
config:
header: X-Tenant-Id
upstreams:
- name: users
hosts:
- https://users-1.internal
- https://users-2.internal
path: /v1/users/{customer_id}
method: GET
timeout: 3s
forward_headers: [ "Authorization", "X-Tenant-Id", "X-Request-Id" ]
forward_queries: [ "expand", "fields" ]
forward_params: [ "customer_id" ]
transport:
max_idle_conns: 100
max_idle_conns_per_host: 50
idle_conn_timeout: 90s
http2: auto # auto | on | off - same semantics as gateway.server.http2, scoped to
# this upstream. "off" is the escape hatch for a backend with a flaky
# HTTP/2 implementation; "on" requires this upstream's tls.enabled.
# Outbound mTLS to the upstream.
# Omit the tls block entirely for plain HTTPS - Go uses system roots.
tls:
enabled: true
cert_file: /etc/aastro/clients/users.crt
key_file: /etc/aastro/clients/users.key
ca_file: /etc/aastro/internal-ca.crt
server_name: users.internal # SNI / hostname verification
min_version: "1.2"
policy:
require_body: true
max_response_body_size: 1048576 # 1 MiB
header_blacklist:
- X-Internal-Token
retry:
max_retries: 3
retry_on_statuses: [ 500, 502, 503, 504 ]
backoff_delay: 200ms
circuit_breaker:
enabled: true
max_failures: 5
reset_timeout: 10s
load_balancing:
mode: least_conns # round_robin | least_conns
- name: orders
hosts: https://orders.internal # single host - string is fine
path: /v1/customers/{customer_id}/orders
timeout: 2s
forward_params: [ "customer_id" ]
# No upstream tls block → public-ish HTTPS via system root CAs
policy:
retry:
max_retries: 2
retry_on_statuses: [ 503 ]
backoff_delay: 100ms
# ── Example 2: namespace aggregation ─────────────────────────────────
# Each upstream's response lives under a key named after the upstream:
# {"profile": {...}, "preferences": {...}}
- path: /api/v1/me
method: GET
aggregation:
strategy: namespace
best_effort: false # any upstream failure fails the whole request
middlewares:
- name: auth
source: builtin
config:
alg: HS256
hmac_secret: "base64secret"
upstreams:
- name: profile
hosts: https://profile.internal
path: /v1/profile
forward_headers: [ "Authorization" ]
- name: preferences
hosts: https://prefs.internal
path: /v1/prefs
forward_headers: [ "Authorization" ]
# ── Example 3: array aggregation, POST with body ─────────────────────
# Each upstream response becomes an element of a JSON array.
# POST/PUT/PATCH bodies are forwarded; other methods discard the body.
- path: /api/v1/search
method: POST
aggregation:
strategy: array
best_effort: true
upstreams:
- name: catalog
hosts: https://catalog.internal
path: /v1/search
method: POST
timeout: 5s
forward_headers: [ "Content-Type", "Authorization", "X-*" ]
- name: docs
hosts: https://docs.internal
path: /v2/query
method: POST
timeout: 5s
forward_headers: [ "Content-Type", "Authorization" ]
# ── Example 4: streaming (SSE / chunked) ──────────────────────────────
# Bypasses aggregation entirely. Body streams chunk-by-chunk to the
# client. Requires exactly one upstream. Response-phase plugins do not
# run (body is already streaming by the time they'd execute).
- path: /api/v1/events/{user_id}
method: GET
streaming: true
# Request-phase plugins still run before the upstream call.
plugins:
- name: tenant_resolver
source: file
path: /etc/aastro/plugins/
config:
header: X-Tenant-Id
upstreams:
- name: events
hosts: https://events.internal
path: /v1/users/{user_id}/events
timeout: 60s # long-lived; remember server.timeout caps this
forward_headers: [ "Authorization", "Accept", "Last-Event-Id" ]
forward_params: [ "user_id" ]
# ── Example 5: bare minimum ──────────────────────────────────────────
# Single upstream, simplest possible flow.
- path: /api/v1/health-check
method: GET
aggregation:
strategy: array
upstreams:
- name: noop
hosts: https://example.com
path: /