Versioning
Versioning
Quayel has four independent version layers. Understanding them is key to operating the gateway safely — every access log line records which gateway, which config, and which data it ran with.
| Layer | What it versions | Where it lives | Example |
|---|---|---|---|
| Gateway release | The binary / code | Cargo.toml, Docker tag | 0.1.0, quayel/quayel-gateway:0.1.0 |
| Config version | One config.json revision | config_version field | 2026-01-15-001 |
| Dataset versions | Embedded IP intelligence data | src/data/ at build time | DB-IP 2026-01, registry entries |
| Docs versions | This documentation | URL prefixes + version switcher | v0.1 (latest) |
Gateway releases
The gateway binary follows semantic versioning (MAJOR.MINOR.PATCH) via Cargo.toml:
- MAJOR — breaking config schema changes (fields removed, enums changed, defaults changed)
- MINOR — new plugins, new config fields, new condition paths (backward compatible)
- PATCH — bug fixes, embedded data refreshes, performance work
Release artifacts:
- Binary:
target/release/quayel-gateway(strip debug symbols before shipping) - Docker:
quayel/quayel-gateway:<version>
The config_version system
Every config.json must declare a config_version. It is a free-form string that identifies one revision of the config — the gateway never parses it, it only tracks and logs it.
{
"gateway_id": "gw-prod-01",
"config_version": "2026-01-15-001",
...
}
Rules
- Required. Configs without
config_versionare rejected at startup. - Bump it on every change. This is the whole point: config revisions must be distinguishable.
- Recommended format:
YYYY-MM-DD-NNN— date plus a per-day sequence number (2026-01-15-001,2026-01-15-002, …). Simple counters ("1","2") also work. - Never reuse a version string for different content.
Why it matters
config_version is stamped into every JSONL access log line, so at any moment you can answer "which config produced this traffic?" during an incident or audit:
{
"timestamp": "2026-01-15T10:30:45.123456789+00:00",
"gateway_id": "gw-prod-01",
"config_version": "2026-01-15-001",
"request_id": "a1b2c3d4-..."
}
Hot reload and version transitions
The gateway hot-reloads its config — no restart, no dropped connections. The config watcher periodically hashes the file (SHA-256); when it changes:
- The new config is validated (parse + schema checks) and compiled (conditions, regexes, …)
- If validation or compilation fails, the gateway keeps the current config and retries on the next cycle — a broken config file can never take the gateway down
- On success, the compiled config is atomically swapped in (
ArcSwap) and the transition is logged with both versions:
Config hot-reloaded successfully old_version=2026-01-15-001 new_version=2026-01-15-002
Because every log line carries config_version, you can split traffic analysis across a reload boundary with a one-line jq filter:
jq 'select(.config_version == "2026-01-15-002")' access.jsonl
domains are also updated on hot reload — adding a domain to the config only updates the allowed list; the certificate itself is provisioned on the next TLS handshake for that domain.Dataset versions
IP intelligence data is compiled into the binary, so a dataset version = the vintage of src/data/ at build time. The gateway has no runtime data refresh.
What is versioned
| Dataset | Versioning | Vintage marker |
|---|---|---|
dbip-city-lite.mmdb | DB-IP monthly release | Filename date, e.g. dbip-city-lite-2026-01 |
dbip-asn-lite.mmdb | DB-IP monthly release | Filename date |
dbip-country.mmdb | DB-IP monthly release | Filename date |
vpn.txt | X4BNet, refreshed daily upstream | Date of download |
tor.txt | Tor Project, refreshed hourly upstream | Date of download |
cloudflare.txt | Cloudflare published ranges | Date of download |
hosting-asns.txt | bad-asn-list | Date of download |
provider-asns.txt | Versioned in the gateway repo | Git history — one line per provider |
proxy.txt | FireHOL (empty by default) | Date of download |
The provider ASN registry
provider-asns.txt is the only dataset that is a living registry in the repo. It maps ASN → provider label (47583|Hostinger), driving ip.is_datacenter and ip.provider. Adding a provider is a one-line change followed by a rebuild; each entry is effectively versioned by the git commit that introduced it.
Recording dataset vintages
When cutting a gateway release, record the dataset vintages in the release notes, e.g.:
quayel-gateway 0.1.1 — data refresh
dbip-city-lite 2026-02
dbip-asn-lite 2026-02
dbip-country 2026-02
vpn.txt 2026-02-10
tor.txt 2026-02-10
provider-asns git 8f3a2c1 (38 ASNs)
See Data Sources — Updating embedded data for the refresh procedure and the recommended update schedule.
Documentation versions
This documentation site has a built-in version system.
How it works
- Unversioned URLs are always the LATEST docs.
/quayel-gateway/getting-startedtracks the current gateway release line. - Archived versions are snapshots served under a version prefix:
/quayel-gateway/v0.1/getting-startedis frozen at the moment v0.1 was the latest. - A version switcher appears at the top of the left sidebar on every
/quayel-gatewaypage. It rewrites the current page's path between version prefixes, so you land on the same page in the other version.
Where versions live
| Piece | File |
|---|---|
| Version list & labels | app/app.config.ts → quayel.versions |
| Switcher UI | app/components/DocsVersionSelect.vue |
| Latest docs | content/quayel-gateway/** |
| Archived snapshots | content/quayel-gateway/vX.Y/** |
// app/app.config.ts
quayel: {
versions: [
{ label: 'v0.1 (latest)', base: '/quayel-gateway', latest: true },
{ label: 'v0.1', base: '/quayel-gateway/v0.1', archived: true },
],
},
Cutting a new docs version
When a new gateway release line ships (say v0.2):
Snapshot the current docs
Copy the current pages into a versioned folder (the snapshot is never edited again):
cp -r content/quayel-gateway content/quayel-gateway/v0.1
# remove the section metadata from the snapshot if desired
Update the version list
In app/app.config.ts, add the archived entry and relabel latest:
quayel: {
versions: [
{ label: 'v0.2 (latest)', base: '/quayel-gateway', latest: true },
{ label: 'v0.1', base: '/quayel-gateway/v0.1', archived: true },
],
},
Write the new docs
Edit the unversioned content/quayel-gateway/** pages for v0.2 changes. Archived snapshots stay untouched.
Version policy for docs
- Docs are versioned per gateway release line (
v0.1,v0.2, …), not per patch. - The unversioned docs always describe the latest release; never edit archived snapshots except for critical corrections.
- Cross-version links should use unversioned URLs (they resolve to latest).
Quick reference
| Question | Answer |
|---|---|
| Which binary am I running? | Release version (Cargo.toml / Docker tag) |
| Which config produced this log line? | .config_version in the JSONL line |
| Which IP data does this build embed? | Dataset vintages recorded in the release notes |
| Which docs match my gateway? | Use the version switcher; unversioned = latest |
| Did my config reload take effect? | Stderr: Config hot-reloaded successfully old_version=… new_version=… |