How to Migrate Existing GeoIP Data to Supported Formats Using loyalsoldier/geoip

To migrate existing GeoIP data to supported formats, create a JSON configuration file specifying your input sources and desired outputs, then run the geoip convert command to execute the transformation pipeline.

The loyalsoldier/geoip project provides a powerful conversion pipeline that enables you to migrate existing GeoIP data between multiple formats including MaxMind CSV, V2Ray DAT, MMDB, and plain-text lists. This Go-based tool uses a plugin-driven architecture to read data from any supported input format and write it to any supported output format through a simple JSON configuration. Whether you need to convert commercial GeoIP databases into open-source proxy formats or merge multiple sources into a single dataset, this guide walks you through the complete migration process using the project's source code.

Understanding the Migration Architecture

Core Orchestration Components

The migration engine centers around three primary components defined in the lib/ directory. The Instance struct in lib/instance.go orchestrates the entire conversion lifecycle, managing configuration loading and coordinating between input and output phases. Configuration parsing occurs in lib/config.go, which registers available converters and validates the JSON schema. Finally, lib/converter.go maintains the registry that maps type strings (like maxmindGeoLite2CountryCSV) to concrete implementations.

The Container and Entry Model

All GeoIP data flows through an in-memory abstraction defined in lib/lib.go. During migration, InputConverters populate a Container with Entry objects representing CIDR ranges grouped by country codes or categories. This intermediate representation allows the tool to merge multiple sources, apply filters, and perform set operations before OutputConverters serialize the data to the target format.

Step-by-Step Migration Process

1. Prepare the Configuration File

Create a JSON configuration file (e.g., config.json) that defines your migration pipeline. The configuration requires two top-level arrays: input and output. Each array entry is an object containing:

  • type: The converter identifier (e.g., maxmindGeoLite2CountryCSV, v2rayGeoIPDat)
  • action: Either add to include CIDRs or remove to exclude them
  • args: Converter-specific parameters such as file paths, wanted lists, and IP type filters

Example configuration converting MaxMind CSV to V2Ray DAT while filtering for IPv4 only:

{
  "input": [
    {
      "type": "maxmindGeoLite2CountryCSV",
      "action": "add",
      "args": {
        "country": "./geolite2/GeoLite2-Country-Locations-en.csv",
        "ipv4": "./geolite2/GeoLite2-Country-Blocks-IPv4.csv",
        "ipv6": "",
        "wantedList": ["CN"],
        "onlyIPType": "ipv4"
      }
    }
  ],
  "output": [
    {
      "type": "v2rayGeoIPDat",
      "action": "add",
      "args": {
        "outputFile": "./geoip.dat",
        "pretty": false
      }
    }
  ]
}

2. Execute the Conversion Command

Run the migration using the CLI entry point defined in convert.go. The command initializes the Instance, loads your configuration, and processes the pipeline:

go run ./ convert -c ./config.json

This executes Instance.InitConfig which unmarshals the JSON (supporting comments via hujson), creates input configurations through createInputConfig, and prepares output converters.

3. Validate the Generated Data

Verify your migration results using the built-in lookup utility before deploying to production:

go run ./ lookup -f ./geoip.dat 8.8.8.8

Alternatively, load the generated file into your target application (V2Ray, Clash, or other proxy tools) to confirm that categories and IP ranges appear correctly.

How the Conversion Pipeline Works

Input Processing and Plugin Registration

When Instance.InitConfig calls createInputConfig, it queries the inputConfigCreatorCache registry populated by each plugin's init() function. For example, plugin/maxmind/maxmind_country_csv_in.go registers the maxmindGeoLite2CountryCSV type. The concrete InputConverter opens source files, builds mapping tables (such as GeoIP ID to country code), and produces Entry objects stored in the shared Container.

Output Generation

After all inputs are merged into the Container, each OutputConverter receives the dataset. In plugin/v2ray/dat_out.go, the v2rayGeoIPDat converter writes binary format using internal WriteGeoIPDat logic, while plugin/maxmind/maxmind_country_mmdb_out.go handles MMDB generation. You can specify multiple output blocks in your configuration to generate several formats in a single run.

Supported Migration Formats

The project supports extensive format interoperability through its plugin system. Key converters include:

Input Formats:

Output Formats:

Inspect all available converters by running go run ./ list (defined in list.go).

Advanced Migration Techniques

Merging Multiple Sources

Add multiple input blocks to merge several GeoIP databases into a single output. The Container aggregates all entries, allowing you to combine commercial MaxMind data with custom IP lists or private ranges using the private input type.

Applying Set Operations

Use the action: remove directive to prune unwanted CIDRs after merging. This works with cutter plugins to exclude specific IP ranges or countries from the final output, enabling you to create filtered datasets like "all countries except X".

Summary

  • loyalsoldier/geoip migrates data between formats using a JSON-driven configuration pipeline orchestrated by lib/instance.go.
  • The migration process requires creating a configuration file with input and output arrays specifying converter types, actions, and arguments.
  • Input converters in the plugin/ directory (such as maxmind_country_csv_in.go and dat_in.go) read source data into a shared Container of Entry objects.
  • Output converters (such as dat_out.go and maxmind_country_mmdb_out.go) serialize the Container contents to target formats.
  • Execute migrations with geoip convert -c config.json and validate results using geoip lookup.

Frequently Asked Questions

What file formats can I migrate from and to?

The project supports migration between MaxMind CSV/MMDB, V2Ray DAT, plain-text lists, and Clash rule sets. You can convert any supported input format to any supported output format by specifying the appropriate type identifiers in your configuration file, such as maxmindGeoLite2CountryCSV for input and v2rayGeoIPDat for output.

How do I filter specific countries or IP types during migration?

Use the wantedList argument in your input configuration to specify an array of country codes (e.g., ["CN", "US"]), and set onlyIPType to ipv4 or ipv6 to restrict the address family. These filters are applied during the InputConverter phase before data reaches the Container.

Can I convert one input file into multiple output formats simultaneously?

Yes. Add multiple entries to the output array in your configuration file, each with a different type (e.g., v2rayGeoIPDat, maxmindMMDB, and text). The Instance will execute all output converters against the same Container data in a single run.

Does the configuration file support comments?

Yes. The parser in lib/config.go uses hujson to allow C-style and JavaScript-style comments within your JSON configuration files, making it easier to document complex migration pipelines with multiple input sources and transformations.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →