{"id":50182107,"url":"https://github.com/ipanalytics/mmdb-watchtower","last_synced_at":"2026-05-25T07:05:20.733Z","repository":{"id":359958583,"uuid":"1245815665","full_name":"ipanalytics/MMDB-WatchTower","owner":"ipanalytics","description":"Production-safe updater for MaxMind DB files with verification, smoke tests, atomic swaps, rollback, and Prometheus metrics.","archived":false,"fork":false,"pushed_at":"2026-05-24T09:22:49.000Z","size":32,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-05-24T11:21:23.153Z","etag":null,"topics":["atomic-swap","database-updater","geoip","ip-intelligence","maxmind","mmdb","observability","production-agent","prometheus","rollback","systemd"],"latest_commit_sha":null,"homepage":"","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/ipanalytics.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-05-21T15:27:48.000Z","updated_at":"2026-05-24T09:21:05.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/ipanalytics/MMDB-WatchTower","commit_stats":null,"previous_names":["ipanalytics/mmdb-watchtower"],"tags_count":1,"template":false,"template_full_name":null,"purl":"pkg:github/ipanalytics/MMDB-WatchTower","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ipanalytics%2FMMDB-WatchTower","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ipanalytics%2FMMDB-WatchTower/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ipanalytics%2FMMDB-WatchTower/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ipanalytics%2FMMDB-WatchTower/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/ipanalytics","download_url":"https://codeload.github.com/ipanalytics/MMDB-WatchTower/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ipanalytics%2FMMDB-WatchTower/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":33464014,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-25T06:32:55.349Z","status":"ssl_error","status_checked_at":"2026-05-25T06:32:35.322Z","response_time":57,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["atomic-swap","database-updater","geoip","ip-intelligence","maxmind","mmdb","observability","production-agent","prometheus","rollback","systemd"],"created_at":"2026-05-25T07:04:52.795Z","updated_at":"2026-05-25T07:05:20.715Z","avatar_url":"https://github.com/ipanalytics.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"# MMDB Watchtower\n\nSafe automatic updates for MaxMind DB files.\n\nMMDB Watchtower is a lightweight agent for production systems that depend on\nlocal `.mmdb` databases. It downloads new database releases, verifies integrity,\nruns smoke checks, swaps files atomically, reloads your service, and rolls back\nwhen an update is bad.\n\nLicense: MIT\n\n\n## Why\n\nCron + curl is not a deployment strategy.\n\nCommon failure modes include broken downloads, HTML error pages saved as MMDB\nfiles, unexpected schema changes, empty databases, missing fields, services\nreading files while they are being overwritten, slow rollback, unknown deployed\nversions, and no update metrics.\n\nMMDB Watchtower treats database refreshes like deployments:\n\n```text\ndownload -\u003e verify -\u003e inspect -\u003e smoke test -\u003e atomic swap -\u003e reload hook -\u003e metrics -\u003e rollback if needed\n```\n\n## Features\n\n- scheduled MMDB downloads\n- gzip support\n- sha256 verification\n- Sigstore/cosign signature verification\n- HTTP ETag/If-None-Match\n- mTLS/private registry support\n- multi-channel updates: stable/canary/latest\n- MMDB metadata validation\n- required field checks\n- smoke tests for known IPs\n- atomic file replacement\n- versioned local backups\n- automatic rollback\n- reload hooks\n- Prometheus metrics\n- Kubernetes readiness endpoint\n- JSON status output\n- systemd and Docker examples\n\n## Install\n\nFrom a local checkout:\n\n```bash\ngo build -o ./bin/mmdbwatch ./cmd/mmdbwatch\n./bin/mmdbwatch --help\n```\n\n```bash\ngo install ./cmd/mmdbwatch\n```\n\n## CLI\n\n```bash\nmmdbwatch init\nmmdbwatch update --config /etc/mmdbwatch.yaml\nmmdbwatch update --channel canary --config /etc/mmdbwatch.yaml\nmmdbwatch status --config /etc/mmdbwatch.yaml\nmmdbwatch rollback vpn --config /etc/mmdbwatch.yaml\nmmdbwatch verify /var/lib/mmdb/geo.mmdb\nmmdbwatch run --config /etc/mmdbwatch.yaml\n```\n\n## Configuration\n\n```yaml\ndatabases:\n  - name: geo\n    channel: stable\n    channels:\n      stable:\n        url: https://example.com/mmdb/geo/stable.mmdb.gz\n        sha256_url: https://example.com/mmdb/geo/stable.sha256\n        signature_url: https://example.com/mmdb/geo/stable.mmdb.sig\n        cosign_key: /etc/mmdbwatch/cosign.pub\n      canary:\n        url: https://example.com/mmdb/geo/canary.mmdb.gz\n      latest:\n        url: https://example.com/mmdb/geo/latest.mmdb.gz\n    path: /var/lib/mmdb/geo.mmdb\n    interval: 6h\n    min_size_mb: 20\n    max_size_mb: 500\n    tls:\n      client_cert: /etc/mmdbwatch/client.crt\n      client_key: /etc/mmdbwatch/client.key\n      ca_cert: /etc/mmdbwatch/ca.crt\n    required_fields:\n      - location.country_code\n      - location.city_geoname_id\n      - confidence\n    smoke_tests:\n      - ip: 8.8.8.8\n        expect:\n          location.country_code: US\n\nreload:\n  command: systemctl reload my-ip-api\n  timeout: 10s\n\nretention:\n  keep_versions: 5\n\nmetrics:\n  listen: 127.0.0.1:9417\n\nreadiness:\n  listen: 127.0.0.1:9418\n```\n\n## Docker\n\n```bash\ndocker run -d \\\n  --name mmdbwatch \\\n  -v /etc/mmdbwatch.yaml:/etc/mmdbwatch.yaml:ro \\\n  -v /var/lib/mmdb:/var/lib/mmdb \\\n  mmdb-watchtower:latest \\\n  run --config /etc/mmdbwatch.yaml\n```\n\n## systemd\n\n```ini\n[Unit]\nDescription=MMDB Watchtower\nAfter=network-online.target\n\n[Service]\nExecStart=/usr/local/bin/mmdbwatch run --config /etc/mmdbwatch.yaml\nRestart=always\nUser=mmdbwatch\nGroup=mmdbwatch\n\n[Install]\nWantedBy=multi-user.target\n```\n\n## Kubernetes sidecar\n\n```text\napp container:\n  reads /data/mmdb/vpn.mmdb\n\nmmdbwatch container:\n  updates /data/mmdb/vpn.mmdb atomically\n  exposes /metrics\n  exposes /readyz\n  optionally calls app reload endpoint\n```\n\n## Metrics\n\n```text\nmmdbwatch_update_success_total{name=\"geo\"} 42\nmmdbwatch_update_failure_total{name=\"vpn\",reason=\"smoke_failed\"} 3\nmmdbwatch_database_age_seconds{name=\"geo\"} 1800\nmmdbwatch_database_size_bytes{name=\"geo\"} 104857600\nmmdbwatch_current_build_epoch{name=\"geo\"} 1779364800\nmmdbwatch_rollback_total{name=\"vpn\"} 1\n```\n\n## Status\n\n```bash\nmmdbwatch status --config /etc/mmdbwatch.yaml\n```\n\n```json\n{\n  \"databases\": [\n    {\n      \"name\": \"geo\",\n      \"path\": \"/var/lib/mmdb/geo.mmdb\",\n      \"channel\": \"stable\",\n      \"status\": \"healthy\",\n      \"database_type\": \"ipanalytics-geo\",\n      \"build_epoch\": 1779364800,\n      \"sha256\": \"abc123...\",\n      \"etag\": \"\\\"release-2026.05.21\\\"\",\n      \"last_update_at\": \"2026-05-21T10:00:00Z\",\n      \"last_success_at\": \"2026-05-21T10:00:02Z\",\n      \"previous_versions\": 5\n    }\n  ]\n}\n```\n\n## License\n\nMIT. See [LICENSE](LICENSE).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fipanalytics%2Fmmdb-watchtower","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fipanalytics%2Fmmdb-watchtower","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fipanalytics%2Fmmdb-watchtower/lists"}