Skip to content

Configuration

David edited this page Feb 23, 2026 · 1 revision

Edge is configured via a single YAML file passed as the first argument. Keys use snake_case. Unknown keys are rejected at startup.

edge <path-to-config.yml>

Authentication

If api_keys is configured, every request must include the key as a header:

x-api-key: <your-api-key>

A missing, empty, or unrecognised key returns 401 Unauthorized. When omitted or empty, all endpoints are publicly accessible.

api_keys:
  - "key-alpha"
  - "key-beta"

server (optional)

Property Type Default Description
host string "127.0.0.1" Bind address. Use "0.0.0.0" to listen on all interfaces.
port integer 8080 TCP port.

source (required)

Redis instance Edge subscribes to for incoming proxy events.

Property Type Default Description
endpoint string host:port of the Redis server.
password string? Redis AUTH password.
ssl boolean false Enable TLS.
channel string "proxy_feed" Pub/sub channel to subscribe to.

sink (required)

Redis instance Edge stores bucketed event data in.

Property Type Default Description
endpoint string host:port of the Redis server.
password string? Redis AUTH password.
ssl boolean false Enable TLS.
database integer 0 Redis logical database index.

mmdb (required)

Path to a MaxMind-format IP database. Used to populate location and network fields in API responses, and to evaluate mmdb.* filter conditions. The file must exist at startup.

Property Type Description
path string Absolute path to the .mmdb file.
mmdb:
  path: "/data/geoip.mmdb"

filters (optional)

Named, reusable predicates referenced by buckets. A filter matches when all of its conditions are satisfied simultaneously. Filters with no conditions always match.

Two condition types are supported:

provider: matches the event's provider field. Accepts a single string or a list; any match passes. Case-insensitive.

mmdb.<path>: matches a field in the MMDB record for the event's IP using dot-notation. Accepts a single value or a list; any match passes. Comparisons are case-insensitive; numeric fields (e.g. ASN) are matched by their string representation.

filters:
  skynet:
    provider: "skynet"

  known_providers:
    provider: [skynet, netprobe]

  us:
    mmdb.country.iso_code: "US"

  europe:
    mmdb.country.iso_code: [DE, FR, NL, SE, PL]

  hosting:
    mmdb.traits.user_type: "hosting"

  residential:
    mmdb.traits.user_type: "residential"

  # Multiple conditions, all must match
  us_hosting:
    mmdb.country.iso_code: "US"
    mmdb.traits.user_type: "hosting"

Filter names must be unique and are referenced by name in bucket definitions.


buckets (required)

Named retention windows. An incoming event is written to every bucket whose conditions it satisfies. At least one bucket must be defined.

Property Type Required Description
ttl string Yes Retention period as a TimeSpan, e.g. "00:05:00" (5 min), "01:00:00" (1 h), "1.00:00:00" (1 day).
all string[] No Event must match every listed filter.
any string[] No Event must match at least one listed filter.
not string[] No Event must not match any listed filter.

All three clauses may be combined; all must pass. A bucket with no clauses accepts every event. All referenced filter names must be defined in filters.

buckets:
  # No filters, accepts everything
  global:
    ttl: "00:05:00"

  # US residential IPs, short window
  us_residential:
    ttl: "00:30:00"
    all: [us, residential]

  # Hosting infra in US or Europe, from any known provider
  known_hosting_west:
    ttl: "01:00:00"
    all: [hosting]
    any: [us, europe]
    not: [skynet]

  # skynet only, regardless of geo
  skynet_global:
    ttl: "00:15:00"
    all: [skynet]

Event Feed Format

Each message published to the configured source.channel must be a JSON object:

{
  "ip": "1.3.3.7",
  "provider": "skynet",
  "timestamp": "1708356600"
}
Field Type Description
ip string IPv4 or IPv6 address.
provider string Data source identifier. Used for filter matching and recorded in per-bucket activity.
timestamp string Unix epoch seconds as a string. Events older than now - bucket.ttl are discarded.

Examples

Minimal

source:
  endpoint: "127.0.0.1:6379"

sink:
  endpoint: "127.0.0.1:6379"
  database: 1

mmdb:
  path: "/data/dbip.mmdb"

buckets:
  all_traffic:
    ttl: "01:00:00"

Production

server:
  host: "0.0.0.0"
  port: 8080

api_keys:
  - "prod-key-abc123"

source:
  endpoint: "redis-feed.internal:6379"
  password: "feed-secret"
  ssl: true
  channel: "proxy_feed"

sink:
  endpoint: "redis-store.internal:6379"
  password: "store-secret"
  ssl: true
  database: 2

mmdb:
  path: "/data/geoip.mmdb"

filters:
  skynet:
    provider: "skynet"

  us:
    mmdb.country.iso_code: "US"

  europe:
    mmdb.country.iso_code: [DE, FR, NL, SE, PL]

  hosting:
    mmdb.traits.user_type: "hosting"

  residential:
    mmdb.traits.user_type: "residential"

buckets:
  # No filters, accepts everything
  global:
    ttl: "00:05:00"

  # Short-lived window for US residential IPs
  us_residential:
    ttl: "00:30:00"
    all: [us, residential]

  # Hosting infra in US or Europe from trusted providers, excluding skynet
  known_hosting_west:
    ttl: "01:00:00"
    all: [hosting]
    any: [us, europe]
    not: [skynet]

  # skynet activity only, medium retention
  skynet_global:
    ttl: "00:15:00"
    all: [skynet]

Clone this wiki locally