# Managing and Updating `config.json` in Production: Best Practices for geoip

> Learn best practices for managing and updating config.json in production. Keep your loyalsoldier/geoip configuration reliable, auditable, and safely updatable with version control and CI pipelines.

- Repository: [Loyalsoldier/geoip](https://github.com/loyalsoldier/geoip)
- Tags: best-practices
- Published: 2026-03-06

---

**Store [`config.json`](https://github.com/loyalsoldier/geoip/blob/main/config.json) under version control, validate it through CI pipelines, and use environment-specific overlays to keep the loyalsoldier/geoip configuration reliable, auditable, and safely updatable.**

The [`config.json`](https://github.com/loyalsoldier/geoip/blob/main/config.json) file serves as the central blueprint that defines all input sources and output targets for the **loyalsoldier/geoip** CLI tool. In production environments, maintaining this configuration requires strict discipline to prevent breaking changes, ensure reproducibility, and protect sensitive credentials. Implementing robust management practices for [`config.json`](https://github.com/loyalsoldier/geoip/blob/main/config.json) ensures that your IP geolocation data pipeline remains stable and maintainable across deployments.

## Version Control and Auditability

Tracking every modification to [`config.json`](https://github.com/loyalsoldier/geoip/blob/main/config.json) is essential for maintaining a reliable production pipeline.

### Tracking Changes with Git

Store the base configuration file in your Git repository to create an immutable history of all modifications. The loyalsoldier/geoip project maintains its default configuration at the repository root, allowing teams to review changes through pull requests before merging. This practice enables rapid rollbacks when a new input source or output filter introduces unexpected behavior.

### Documenting Configuration Intent

Every entry in [`config.json`](https://github.com/loyalsoldier/geoip/blob/main/config.json) should include clear documentation explaining why a specific list was added, its source authority, and any applied filters such as `onlyIPType` or `wantedList`. Maintain a separate [`CHANGELOG.md`](https://github.com/loyalsoldier/geoip/blob/main/CHANGELOG.md) or detailed section in your internal documentation that maps configuration changes to business requirements. The repository's [`configuration.md`](https://github.com/loyalsoldier/geoip/blob/main/configuration.md) file serves as the canonical reference for understanding supported input and output formats.

## Environment Isolation and Security

Production environments require isolation from development settings and protection of sensitive credentials.

### Using Overlay Files for Environment Overrides

Create environment-specific override files such as [`config.prod.json`](https://github.com/loyalsoldier/geoip/blob/main/config.prod.json) or [`config.staging.json`](https://github.com/loyalsoldier/geoip/blob/main/config.staging.json) that extend the base configuration rather than duplicating it. Use `jq` to merge these layers dynamically, keeping environment-specific URIs and file paths separate from the version-controlled base file.

```bash

# Merge base config with production overrides

jq -s '.[0] * .[1]' config.json /secure/config.prod.json > config.merged.json
geoip run -c config.merged.json

```

This approach keeps the base [`config.json`](https://github.com/loyalsoldier/geoip/blob/main/config.json) in the repository while storing sensitive overrides in secure locations accessible only to specific environments.

### Protecting Credentials with Environment Variables

Never embed authentication tokens or passwords directly in [`config.json`](https://github.com/loyalsoldier/geoip/blob/main/config.json). The repository's `.gitignore` already excludes `.env` files to prevent accidental commits. Store required tokens in environment variables and inject them at runtime, as the CLI reads variables via `os.Getenv`.

## Validation and Pre-Deployment Checks

Validating configuration syntax and semantics before deployment prevents service interruptions.

### Schema Validation Using lib/config.go

The [`lib/config.go`](https://github.com/loyalsoldier/geoip/blob/main/lib/config.go) file handles JSON unmarshalling and action validation (lines 55–78). Create a validation step in your deployment pipeline that uses the same logic as the production binary to catch malformed JSON or invalid action types before they reach production.

```go
package main

import (
    "log"
    "github.com/loyalsoldier/geoip/lib"
)

func main() {
    cfg, err := lib.LoadConfig("config.json")
    if err != nil {
        log.Fatalf("invalid config: %v", err)
    }
    log.Printf("config OK – %d inputs, %d outputs", len(cfg.Input), len(cfg.Output))
}

```

### CI Pipeline Integration

Extend the existing GitHub workflow in [`.github/workflows/build.yml`](https://github.com/loyalsoldier/geoip/blob/main/.github/workflows/build.yml) to execute configuration validation on every pull request. Add a step that runs `go vet`, `go test`, and a custom validation command to ensure the configuration loads correctly.

```yaml
- name: Validate config.json
  run: |
    go run ./cmd/validate-config -c config.json

```

## Data Integrity and Immutability

Remote data sources and generated artifacts require version pinning and backup strategies.

### Pinning Remote Resources to Specific Versions

Many [`config.json`](https://github.com/loyalsoldier/geoip/blob/main/config.json) entries reference remote resources via `uri` fields. Pin these to specific commit SHAs or release tags rather than using moving branches like `master`. This prevents breaking changes when upstream sources modify their data formats.

```json
{
  "type": "text",
  "action": "add",
  "args": {
    "name": "cn",
    "uri": "https://raw.githubusercontent.com/17mon/china_ip_list/v2024-01-01/china_ip_list.txt",
    "onlyIPType": "ipv4"
  }
}

```

### Backup Strategies for Generated Artifacts

The geoip tool generates binary and text files such as `output/geoip.dat`. Implement versioned storage using directory structures (`output/v1/`, `output/v2/`) or immutable object storage to preserve previous builds. This enables rapid rollback if a configuration change unintentionally excludes critical IP ranges.

## Deployment Automation

Manual configuration updates introduce human error and inconsistency.

### Incremental Update Strategies

Avoid large monolithic configuration changes that are difficult to review. Add or remove single blocks—such as one new `json` source—and run the CLI locally using `geoip run -c config.json` to verify the effect before committing. This incremental approach reduces the blast radius of configuration errors.

### Automated Regeneration Workflows

Production environments should never rely on manual binary execution. Integrate `geoip run -c config.json` into scheduled jobs, container entrypoints, or orchestration pipelines. Since the binary reads the configuration at startup, updating the file automatically refreshes the generated artifacts without requiring process restarts or complex deployment rituals.

## Summary

- **Version control** [`config.json`](https://github.com/loyalsoldier/geoip/blob/main/config.json) using Git to maintain audit trails and enable rollbacks through pull requests.
- **Separate environment-specific settings** using overlay files merged with `jq`, keeping production URIs and paths out of the base repository.
- **Validate configurations** before deployment using `lib.LoadConfig` from [`lib/config.go`](https://github.com/loyalsoldier/geoip/blob/main/lib/config.go) to catch schema errors early.
- **Pin remote data sources** to specific tags or commit SHAs to prevent upstream changes from breaking your pipeline.
- **Protect secrets** using environment variables rather than embedding credentials in JSON files.
- **Automate** the regeneration process through CI/CD pipelines and scheduled jobs to eliminate manual intervention.

## Frequently Asked Questions

### How do I validate [`config.json`](https://github.com/loyalsoldier/geoip/blob/main/config.json) before deploying to production?

Use the `lib.LoadConfig` function from [`lib/config.go`](https://github.com/loyalsoldier/geoip/blob/main/lib/config.go) to programmatically validate the file. This function unmarshals the JSON and validates all actions (lines 66–78), returning an error if the configuration contains invalid syntax or unsupported action types. Run this validation as part of your CI pipeline to block deployments of malformed configurations.

### What is the best way to handle secrets in geoip configuration files?

Store authentication tokens and sensitive URIs in environment variables rather than in [`config.json`](https://github.com/loyalsoldier/geoip/blob/main/config.json). The loyalsoldier/geoip CLI reads these variables at runtime via `os.Getenv`. Keep environment-specific override files in secure storage outside version control, and merge them with the base configuration at deployment time using tools like `jq`.

### How can I test configuration changes without affecting production data?

Create environment-specific overlay files (e.g., [`config.staging.json`](https://github.com/loyalsoldier/geoip/blob/main/config.staging.json)) that modify input sources or output paths for testing purposes. Merge these with your base configuration and run the CLI locally or in a staging environment. This approach allows you to verify that new sources or filters generate the expected datasets without risking production artifacts.

### Should I pin remote data sources to specific versions?

Yes. Instead of referencing moving branches like `master` in `uri` fields, pin to specific release tags or commit SHAs (e.g., `v2024-01-01`). This practice ensures reproducible builds by preventing upstream repositories from introducing breaking changes or data removals that could corrupt your generated geoip databases.