README.md

Infrapod IP Lists API

This project is the source of truth for Infrapod IP blocklists.

It provides:

  • A FastAPI service that stores and serves internal and external IP sets
  • Scheduled refresh of external lists (for example FireHOL)
  • Cached, deduplicated outputs for reliable client consumption
  • A companion ipcli package (.deb and .rpm) for host-side automation

What this replaces

The API replaces static publication from iplists.infrapod.nl as the authoritative source for internal Infrapod lists.

Internal lists are stored in the application database and managed through the API.

Core concepts

  • Internal sources: infrapod_abuse, infrapod_bots, infrapod_spam
  • External sources: API-configured feeds such as firehol_level1
  • Snapshots: normalized, deduplicated list materializations used by readers
  • Combined views: dynamic union of multiple sources, also deduplicated

Normalization and deduplication are performed using netaddr.IPSet and exposed as canonical CIDR output.

API overview

All API endpoints require authentication.

Source management

  • GET /v1/sources
  • POST /v1/sources
  • PATCH /v1/sources/{name}
  • DELETE /v1/sources/{name}
  • POST /v1/sources/{name}/refresh

Internal list mutations

  • POST /v1/internal/entries
  • DELETE /v1/internal/entries

Read endpoints

  • GET /v1/ipsets/{name}
  • GET /v1/ipsets/{name}/plain
  • GET /v1/ipsets/combined?include=source_a,source_b
  • GET /v1/ipsets/combined/plain?include=source_a,source_b
  • GET /v1/health

Internal entry endpoints

  • POST /v1/internal/entries
  • DELETE /v1/internal/entries

Authentication

Every endpoint is protected by an API key sent as a bearer token.

  • Header format: Authorization: Bearer <api_key>
  • Keys are hashed at rest and shown only once at creation time
  • Keys can be scoped, revoked, and optionally expired

Bootstrap and first key

The first API key is created using a bootstrap secret set in the runtime environment.

  1. Set BOOTSTRAP_API_KEY in the container environment.
  2. Call POST /v1/auth/keys with that value in the bearer token header.
  3. Store the returned key securely; it is not retrievable later.
  4. Rotate or remove BOOTSTRAP_API_KEY after initial provisioning.

Key management endpoints

  • POST /v1/auth/keys
  • GET /v1/auth/keys
  • PATCH /v1/auth/keys/{id}
  • DELETE /v1/auth/keys/{id}

Scheduler behavior

  • External sources are fetched on a configurable interval
  • Conditional requests use ETag and Last-Modified when available
  • Failed refreshes keep the last known good snapshot available
  • Internal source changes trigger immediate recomputation of affected snapshots

Runtime flags:

  • SCHEDULER_ENABLED (1 by default)
  • SCHEDULER_TICK_SECONDS (60 by default)

Storage model

SQLite is used for persistence (mounted in a Docker volume):

  • sources for internal and external source definitions
  • internal_entries as source-of-truth entries for infrapod_*
  • snapshots for read-optimized normalized outputs
  • external_fetch_state for metadata (etag, last_success, last_error)

Docker runtime

The API runs as a container and persists data in /data.

Typical deployment shape:

  • Image based on python:3.14-alpine
  • Entrypoint starts uvicorn and DB initialization runs in lifespan
  • Health check probes GET /v1/health with a bearer key

Build and deploy jobs are tag-only in GitLab CI.

Local run:

pip install -r requirements.txt
export BOOTSTRAP_API_KEY="change-me"
uvicorn iplists_api.main:app --app-dir src --host 0.0.0.0 --port 8080

Container run:

docker build -t iplists-api .
docker run --rm -p 8080:8080 \
  -e BOOTSTRAP_API_KEY="change-me" \
  -e HEALTHCHECK_API_KEY="change-me" \
  -v iplists-data:/data \
  iplists-api

ipcli package

ipcli is distributed as .deb and .rpm for host usage.

It can:

  • Consume API endpoints for source and list operations
  • Export IP data in formats suitable for web proxies:
    • Plain list
    • HAProxy include file format
    • Nginx deny directives format

Example usage:

ipcli --api-url https://iplists-api.example --api-key "$IPLISTS_API_KEY" \
  sources list
ipcli --api-url https://iplists-api.example --api-key "$IPLISTS_API_KEY" \
  ipsets get firehol_level1 --format haproxy
ipcli --api-url https://iplists-api.example --api-key "$IPLISTS_API_KEY" \
  ipsets get combined --include firehol_level1,infrapod_abuse --format nginx

Current status

This repository is currently transitioning from the legacy netset workflow to the API-first architecture described above.