Octopus
1.x
Docs/Octopus/Quick Start
Open

Reading6 min
Updated31 Jul 2026
Sourcev1/quick-start.mdx

Quick Start

Get Octopus API Gateway up and running in a few minutes.

Prerequisites01

Note

Make sure you have installed Octopus — either the octopus binary or the ghcr.io/xraph/octopus container image.

Basic setup02

1

Create the configuration

Create a file named config.yaml. The only required section is gateway with a listen address; this config also declares one upstream and one route:

gateway:
  listen: "0.0.0.0:8080"
  workers: 0                 # 0 = one worker per CPU core

upstreams:
  - name: example-service
    lb_policy: round_robin
    instances:
      - id: example-1
        host: 127.0.0.1
        port: 8081

routes:
  - path: /api
    methods: [GET, POST]
    upstream: example-service
    strip_prefix: /api

This configuration:

  • Listens on 0.0.0.0:8080 for HTTP traffic.

  • Defines an upstream example-service with one instance on 127.0.0.1:8081.

  • Routes /api/* to that upstream, stripping the /api prefix before proxying.

Validate, then start the gateway

Check the config parses and is valid, then run it:

octopus validate -c config.yaml
octopus serve -c config.yaml

serve and validate take one or more -c/--config paths (each a file or directory). serve also accepts -l/--log-level (trace, debug, info, warn, error):

octopus serve -c config.yaml --log-level debug

Test the gateway

In another terminal, send a request and check the health probes:

# Proxied to example-service (path becomes /123 after strip_prefix)
curl http://localhost:8080/api/123

# Liveness / readiness probes (served on the listen port)
curl http://localhost:8080/livez
curl http://localhost:8080/readyz

# Prometheus metrics
curl http://localhost:9090/metrics

Configuration explained03

Gateway

gateway:
  listen: "0.0.0.0:8080"   # address:port to bind — required
  workers: 0               # worker threads; 0 = one per CPU core
  request_timeout: 30s     # per-request timeout

gateway is the only required top-level section. See Gateway for timeouts, body-size limits, probes, and compression.

Upstreams

upstreams:
  - name: example-service        # unique name, referenced by routes
    lb_policy: round_robin       # load-balancing policy
    instances:
      - id: example-1            # unique instance id
        host: 127.0.0.1          # host or IP
        port: 8081               # port

See Upstreams for instance weights, health checks, and circuit breakers.

Routes

routes:
  - path: /api                   # path pattern to match (must start with /)
    methods: [GET, POST]         # allowed methods; empty means all
    upstream: example-service    # target upstream (must exist)
    strip_prefix: /api           # prefix removed before proxying

See Routes for priority, prefix rewriting, and per-route auth.

Common scenarios04

yaml
gateway:
  listen: "0.0.0.0:8080"

upstreams:
  - name: user-service
    instances:
      - id: user-1
        host: 127.0.0.1
        port: 8081

  - name: order-service
    instances:
      - id: order-1
        host: 127.0.0.1
        port: 8082

routes:
  - path: /api/users
    upstream: user-service
    strip_prefix: /api

  - path: /api/orders
    upstream: order-service
    strip_prefix: /api

Environment variables05

Octopus expands ${VAR} references in the config file before parsing:

gateway:
  listen: "${LISTEN_ADDR:-0.0.0.0:8080}"   # default if LISTEN_ADDR is unset

auth_providers:
  primary:
    type: jwt
    secret: "${JWT_SECRET}"                 # required — startup fails if unset

${VAR} fails to load when VAR is unset; ${VAR:-default} falls back to the literal default. Set them before running:

export JWT_SECRET=your-secret-key
octopus serve -c config.yaml

Run with Docker06

1

Create docker-compose.yml

services:
  octopus:
    image: ghcr.io/xraph/octopus:latest
    ports:
      - "8080:8080"
      - "9090:9090"
    volumes:
      - ./config.yaml:/etc/octopus/config.yaml

Start it

docker compose up -d
docker compose logs -f octopus

See Docker deployment for the full image reference.

Graceful shutdown07

On SIGTERM (or Ctrl+C), Octopus flips readiness to 503, waits gateway.pre_stop_delay so deregistration can propagate, then drains in-flight requests within gateway.shutdown_timeout before exiting. See Graceful shutdown.

Next steps08

Troubleshooting09

Careful

Port already in use — change gateway.listen to a free port:

gateway:
  listen: "0.0.0.0:8081"

Connection refused to upstream — verify the backend is running and the instance host/port are correct:

curl http://127.0.0.1:8081/healthz

Config rejected on startup — run octopus validate -c config.yaml; it reports the exact field that failed (for example a route referencing an upstream that doesn't exist).

For runtime debugging via logs and metrics, see Observability. For task-focused walkthroughs, see the Guides.