Declarative patching for MaxMind DB files. MMDBpatch applies reviewed YAML overlays to existing .mmdb databases, producing reproducible patched databases with dry-run diffs suitable for infrastructure, security, fraud/risk, and analytics workflows.
| Resource | Location |
|---|---|
| Repository | github.com/ipanalytics/MMDBpatch |
| Releases | GitHub Releases |
| Example patch | examples/patches.yaml |
| Patch schema | schema/mmdbpatch.schema.json |
| MaxMind DB writer | github.com/maxmind/mmdbwriter |
Operational teams often maintain local corrections and enrichment data for GeoIP, ASN, proxy, risk, or internal network datasets. The usual path is a one-off Go program using mmdbwriter, which makes the result hard to review, repeat, and audit.
MMDBpatch turns those corrections into data:
# yaml-language-server: $schema=https://raw.githubusercontent.com/ipanalytics/MMDBpatch/main/schema/mmdbpatch.schema.json
defaults:
conflict: patch_wins
patches:
- cidr: 203.0.113.0/24
op: merge
set:
custom.source: "manual_override"
custom.risk: "lab"
geo.country.iso_code: "DE"
- cidr: 198.51.100.0/24
op: delete_field
field: traits.is_anonymous_proxyPatch files can live in git, go through code review, run in CI, and be applied during controlled release jobs.
MMDBpatch reads an existing MaxMind DB, loads a YAML patch document, and applies each operation to the matching network using mmdbwriter.InsertFunc.
flowchart LR
A["Input MMDB"] --> C["MMDBpatch"]
B["YAML patch file"] --> C
C --> D["Dry-run diff"]
C --> E["Patched MMDB"]
D --> F["CI / PR review"]
E --> G["Release / deployment"]
By default the CLI performs a dry run and prints before/after records for each affected network. Writing a database requires an explicit -apply flag and output path.
| Capability | Description |
|---|---|
| Declarative patches | YAML operations for CIDR-scoped MMDB changes. |
| Patch validation | Validate YAML patch files without an input database. |
| JSON Schema | Editor and CI validation through schema/mmdbpatch.schema.json. |
| Dry-run first | Default mode prints the proposed changes without writing output. |
| Full affected-network diff | Uses NetworksWithin to report affected records under the patched CIDR. |
| Before/after diff | Human-readable, JSON-lines, or full JSON report output. |
| Merge semantics | Deep-merge overlay values while preserving unrelated record fields. |
| Record replacement | Replace selected networks with controlled records. |
| Field deletion | Remove specific dotted paths from selected records. |
| Record deletion | Remove selected networks from the database tree. |
| Conflict strategies | Define behavior for overlapping patch CIDRs. |
| Reproducible output | Same input database and patch file produce the same patched result. |
mmdbpatch \
-input GeoLite2-City.mmdb \
-patch patches.yamlApply the patch and write a new database:
mmdbpatch \
-input GeoLite2-City.mmdb \
-patch patches.yaml \
-output GeoLite2-City.patched.mmdb \
-applyEmit machine-readable diff records:
mmdbpatch \
-input GeoLite2-City.mmdb \
-patch patches.yaml \
-jsonWrite the full report to a JSON file:
mmdbpatch \
-input GeoLite2-City.mmdb \
-patch patches.yaml \
-report reports/mmdbpatch.jsonValidate a patch file without opening an MMDB:
mmdbpatch validate -patch patches.yamlInstall from source:
go install github.com/ipanalytics/MMDBpatch/cmd/mmdbpatch@latestBuild locally:
git clone https://github.com/ipanalytics/MMDBpatch.git
cd MMDBpatch
go build ./cmd/mmdbpatchReleased binaries are published for Linux, macOS, and Windows on the releases page.
Usage of mmdbpatch:
-apply
write the patched MMDB instead of dry-run only
-input string
input MMDB path
-json
print dry-run diff as JSON lines
-output string
output MMDB path; requires -apply
-patch string
YAML patch file path
-report string
write full JSON report to path
-version
print version information
Patch validation:
Usage of mmdbpatch validate:
-patch string
YAML patch file path
patches:
- cidr: 203.0.113.0/24
op: merge
set:
custom.owner: "security"
custom.environment: "lab"
geo.country.iso_code: "DE"patches:
- cidr: 10.20.30.0/24
op: replace
set:
custom.network: "corp-vpn"
custom.source: "netbox"patches:
- cidr: 198.51.100.0/24
op: delete_field
field: traits.is_anonymous_proxypatches:
- cidr: 192.0.2.0/24
op: delete_recordMMDBpatch produces three operational artifacts:
| Artifact | Description |
|---|---|
| Dry-run diff | Before/after records for each affected network, printed to stdout. |
| JSON report | Complete report written with -report, including summary counters and changed fields. |
| Patched MMDB | New MaxMind DB file written only when -apply and -output are set. |
Example human-readable dry-run output:
merge 203.0.113.0/24
before: {"geo":{"country":{"iso_code":"US"}}}
after: {"custom":{"risk":"lab","source":"manual_override"},"geo":{"country":{"iso_code":"DE"}}}
patches: 1, applied: 1, skipped: 0, affected_networks: 1, changed_networks: 1
Example JSON-lines output:
{"cidr":"203.0.113.0/24","network":"203.0.113.0/24","op":"merge","changed":true,"fields_changed":["custom.risk","custom.source","geo.country.iso_code"],"before":{"geo":{"country":{"iso_code":"US"}}},"after":{"custom":{"risk":"lab","source":"manual_override"},"geo":{"country":{"iso_code":"DE"}}}}Example report summary:
{
"total": 2,
"applied": 2,
"skipped": 0,
"affected_networks": 2,
"changed_networks": 2,
"fields_changed": [
"custom.source",
"geo.country.iso_code",
"traits.is_anonymous_proxy"
]
}Top-level document:
# yaml-language-server: $schema=https://raw.githubusercontent.com/ipanalytics/MMDBpatch/main/schema/mmdbpatch.schema.json
defaults:
conflict: patch_wins
patches:
- cidr: 203.0.113.0/24
op: merge
set:
path.to.field: valueSupported operations:
| Operation | Required fields | Behavior |
|---|---|---|
merge |
cidr, set |
Deep-merges set into the existing MMDB record. |
replace |
cidr, set |
Replaces the record for the CIDR with set. |
delete_field |
cidr, field |
Deletes one dotted field path from the existing record. |
delete_record |
cidr |
Removes the record for the CIDR. |
Conflict strategies:
| Strategy | Behavior |
|---|---|
patch_wins |
Apply patches in file order. Later overlapping patches can refine earlier ranges. |
first_wins |
Apply the first patch for an overlapping range and skip later overlapping patches. |
fail_on_overlap |
Reject the patch file when two patch CIDRs overlap. |
Set a default for the patch file:
defaults:
conflict: fail_on_overlapOverride it for a single patch:
patches:
- cidr: 203.0.113.0/24
op: merge
conflict: patch_wins
set:
custom.source: "manual_override"Field paths are dot-separated:
set:
geo.country.iso_code: "DE"The path above expands to:
{
"geo": {
"country": {
"iso_code": "DE"
}
}
}Nested YAML maps are accepted when they are a better fit for the data.
- Treat patch files as release artifacts. Review them the same way you review firewall, routing, detection, or enrichment changes.
- Keep source MMDB checksums with release metadata when reproducibility matters.
- Run dry-run mode in pull requests and deployment previews.
- Use
mmdbpatch validatein pre-commit hooks and CI jobs. - Write patched databases to a new path and promote them through the same rollout mechanism used for the original database.
- Use JSON-lines diff output when integrating with CI logs, artifact storage, or approval systems.
- Store full
-reportJSON artifacts for audit trails when overrides affect production datasets.
| Team | Example |
|---|---|
| Security engineering | Override risk metadata for lab, VPN, Tor, proxy, and partner ranges. |
| Fraud/risk | Attach internal scoring tags to high-signal prefixes. |
| Infrastructure | Correct geolocation for office, datacenter, and private interconnect ranges. |
| Analytics | Add stable internal dimensions used by pipelines and dashboards. |
| Data engineering | Keep enrichment patches versioned and reproducible across environments. |
MMDBpatch focuses on deterministic patching of existing MaxMind DB files. It is intended to be small, auditable, and easy to run in CI.
In scope:
- reading an existing
.mmdb - applying CIDR-scoped declarative patch operations
- producing reviewable diffs
- writing a patched
.mmdb - supporting automation-friendly output
Out of scope:
- collecting GeoIP, ASN, proxy, VPN, or threat intelligence data
- replacing dataset providers
- operating a hosted enrichment service
- maintaining a central registry of overrides
- Diff reporting follows MaxMind DB network iteration behavior. When a patch CIDR is contained by a larger database network, the containing network is reported as the affected source record.
- Conflict strategies apply to overlapping patch CIDRs. They do not attempt to infer business ownership of fields inside a record.
- Output compatibility depends on the input database structure and reader expectations for that database type.
.
├── cmd/mmdbpatch/ # CLI entrypoint
├── examples/ # Example patch files
├── internal/patch/ # Patch parser, diff logic, and MMDB mutation engine
├── schema/ # JSON Schema for patch files
├── site/ # Repository visual assets
├── .github/workflows/ # CI and release automation
├── .github/actions/ # Reusable local GitHub Actions
├── go.mod
├── LICENSE
└── README.md
MMDBpatch is designed for CI/CD pipelines that already distribute MMDB artifacts.
Typical release job:
mmdbpatch \
-input vendor/GeoLite2-City.mmdb \
-patch overlays/production.yaml \
-output dist/GeoLite2-City.production.mmdb \
-applyRecommended pipeline stages:
| Stage | Action |
|---|---|
| Validate | Parse patch file and run dry-run diff. |
| Review | Store diff output as a CI artifact or PR comment. |
| Build | Apply patch to a pinned input database. |
| Verify | Run downstream lookup checks against known prefixes. |
| Promote | Publish the patched MMDB through existing artifact rollout. |
This repository includes a local validation action:
- uses: ipanalytics/MMDBpatch/.github/actions/validate@v0.1.0
with:
patch: overlays/production.yamlFor repository-local checks, the included CI workflow validates examples/patches.yaml, runs tests, and runs go vet.
Release workflow
This repository includes a GitHub Actions workflow that builds release binaries for Linux, macOS, and Windows when a v* tag is pushed.
git tag v0.1.0
git push origin v0.1.0The workflow creates checksums and attaches archives to the GitHub release.
Apache License 2.0. See LICENSE.
MMDBpatch modifies databases supplied by the operator. Validate patched output against your deployment requirements before promotion.