Fast HTTP/JSON API for ALT Linux apt-rpm repository metadata.
  • OCaml 82.4%
  • Standard ML 16.9%
  • Dune 0.4%
  • Dockerfile 0.3%
Find a file
Anton Farygin 6f137f93ec
All checks were successful
Check / check (push) Successful in 2m42s
1.2.0 release
- /repoteka/names case preservation + smartcase prefix
- bounded user prefix/q at 256 bytes (DoS guard)
- per-branch case fidelity, deterministic canonical case
- source_rpm for srclist variants
- Gc.compact + debounced reload
2026-05-27 08:49:15 +00:00
.forgejo/workflows ci: add node to check workflow (required by actions/checkout@v4) 2026-04-04 14:58:33 +03:00
.gear 1.2.0 release 2026-05-27 08:49:15 +00:00
.ralph perf: optimize build_indexes — single pass, kind ID comparison, name cache 2026-04-03 18:52:45 +03:00
bin feat: access log middleware — IP, method, path, status code, response time 2026-04-02 21:45:08 +03:00
lib 1.2.0 release 2026-05-27 08:49:15 +00:00
test fix(names): preserve original case and add smartcase prefix matching 2026-05-27 08:15:02 +00:00
.dockerignore chore: add Containerfile, compose.yaml for podman/docker deployment 2026-04-03 18:56:05 +03:00
.env.example chore: parameterize compose.yaml via .env, add .env.example 2026-04-03 19:46:48 +03:00
.gitignore chore: add bisect_ppx coverage instrumentation 2026-04-03 20:16:55 +03:00
AUTHORS chore: add SPDX license headers and AUTHORS file 2026-04-02 21:18:15 +03:00
CHANGELOG.md 1.1.0 release 2026-04-07 17:46:38 +03:00
CLAUDE.md docs: add CLAUDE.md 2026-04-02 21:14:48 +03:00
compose.yaml docs: add release notes, fix compose to use bind-mount instead of NFS 2026-04-06 11:11:10 +03:00
Containerfile fix: use registry.altlinux.org/alt/alt:sisyphus in Containerfile 2026-04-04 11:20:01 +03:00
COPYING chore: add GPL-2.0 license, author info, generate opam from dune-project 2026-04-02 21:16:53 +03:00
dune-project 1.2.0 release 2026-05-27 08:49:15 +00:00
README.md fix: use Gc.compact after reload + debounce staggered branch updates 2026-04-09 22:25:44 +03:00
README.ru.md fix: use Gc.compact after reload + debounce staggered branch updates 2026-04-09 22:25:44 +03:00
repoteka.opam 1.2.0 release 2026-05-27 08:49:15 +00:00
repoteka.service chore: systemd service with full hardening 2026-04-02 21:29:26 +03:00
repoteka.sysconfig chore: systemd service with full hardening 2026-04-02 21:29:26 +03:00
repoteka.toml.example fix: use Gc.compact after reload + debounce staggered branch updates 2026-04-09 22:25:44 +03:00

repoteka

Fast HTTP/JSON API for ALT Linux apt-rpm repository metadata.

Loads pkglist, srclist, and release files into memory and serves package data with millisecond latency. Designed for TAB completion, package search, and repository introspection.

Features

  • All RPM fields — name, version, deps (provides/requires/conflicts/obsoletes), files, changelog, summary, description, group, packager, buildtime, size, disttag, filename
  • Multiple branches — Sisyphus, p11, p10, c10f2, c9f2, p9, p8, ...
  • Parallel loading — XZ decompression via OCaml 5 Domains + native lzma
  • Zero-copy RPM parsing — headers read directly from decompressed buffer
  • Aggressive dedup — string interning, two-level dep interning, changelog by source_rpm
  • Prefix search — binary search on sorted name arrays, <1.5ms per query
  • Per-branch indexes — scoped search and TAB completion by binary/source kind
  • Automatic reload — mtime-based change detection, atomic snapshot swap

Quick start

dune build
repoteka --config /etc/repoteka.toml

Configuration

listen_addr = "0.0.0.0"
listen_port = 1337
reload_interval_sec = 600
settle_window_sec = 600

[[branches]]
path = "/mnt/ftp/pub/distributions/ALTLinux/Sisyphus"

[[branches]]
path = "/mnt/ftp/pub/distributions/ALTLinux/p11/branch"

[[branches]]
name = "stable-p10"
path = "/mnt/ftp/pub/distributions/ALTLinux/p10/branch"
  • path — required, filesystem path to the branch root
  • name — optional, overrides the label from release metadata
  • reload_interval_sec — how often the background thread polls branch metadata mtimes (default 600).
  • settle_window_sec — debounce window: when 2+ branches are configured, wait this many seconds of "quiet" after the last detected change before triggering a reload. Coalesces staggered branch updates into one reload. Set to 0 to disable. Ignored for single-branch deployments (default 600).
  • Branch layout: <path>/<arch>/base/pkglist.<component>.xz

API

Full OpenAPI 3.0.3 spec at /openapi.json.

Endpoint Description
GET /health Liveness probe
GET /status Counters, per-branch state, GC stats
GET /branches List loaded branches
GET /branches/:branch Branch details
GET /packages?q=&kind=&arch=&branch=&component=&limit=&offset= Global package search
GET /packages/:name?kind=&arch=&branch=&component=&changelog=true Package card (deps, files, changelog)
GET /branches/:branch/packages?q=&kind=&arch=&component=&limit= Branch-scoped search
GET /branches/:branch/packages/:name?kind=&changelog=true Branch-scoped package card
GET /names?prefix=&branch=&kind=&limit= TAB completion
GET /branches/:branch/names?prefix=&kind=&limit= Branch-scoped TAB completion
GET /openapi.json OpenAPI specification

Query parameters

Parameter Default Values
component classic classic, debuginfo, checkinstall, gostcrypto, all
kind all binary, source
limit 100 110000, 0 = unlimited
offset 0 pagination offset
changelog false true to include changelog in package card

Performance (7 branches, 635K packages, 1.1M placements)

Metric Value
Load time ~82s
Live heap ~1.9 GB
TAB completion <1.5ms
Package search <3ms
Package card <8ms
/status <1ms

Container

podman-compose up -d

By default the compose file bind-mounts /mnt/ftp from the host into the container at the same path, so repoteka.toml works identically on bare metal and in a container. Override via .env:

REPO_PATH=/srv/alt-mirror
REPOTEKA_PORT=8080
REPOTEKA_MEM=16g
REPOTEKA_CPUS=8

Place your repoteka.toml in the project directory — it is mounted read-only into /etc/repoteka.toml inside the container.

Requirements

  • OCaml >= 5.0, dune >= 3.0
  • tiny_httpd, yojson, toml, lzma
  • liblzma-devel (system)

License

GPL-2.0-or-later. See COPYING.