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

> Easily migrate your GeoIP data to supported formats using the loyalsoldier/geoip tool. Create a config file and run the geoip convert command to transform your data efficiently.

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

---

**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`](https://github.com/loyalsoldier/geoip/blob/main/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`](https://github.com/loyalsoldier/geoip/blob/main/lib/config.go), which registers available converters and validates the JSON schema. Finally, [`lib/converter.go`](https://github.com/loyalsoldier/geoip/blob/main/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`](https://github.com/loyalsoldier/geoip/blob/main/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`](https://github.com/loyalsoldier/geoip/blob/main/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:

```json
{
  "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`](https://github.com/loyalsoldier/geoip/blob/main/convert.go). The command initializes the Instance, loads your configuration, and processes the pipeline:

```bash
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:

```bash
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`](https://github.com/loyalsoldier/geoip/blob/main/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`](https://github.com/loyalsoldier/geoip/blob/main/plugin/v2ray/dat_out.go), the `v2rayGeoIPDat` converter writes binary format using internal `WriteGeoIPDat` logic, while [`plugin/maxmind/maxmind_country_mmdb_out.go`](https://github.com/loyalsoldier/geoip/blob/main/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:**

- `maxmindGeoLite2CountryCSV`: Reads MaxMind GeoLite2 country CSV files (implementation in [`plugin/maxmind/maxmind_country_csv_in.go`](https://github.com/loyalsoldier/geoip/blob/main/plugin/maxmind/maxmind_country_csv_in.go))
- `maxmindGeoLite2ASNCSV`: Processes MaxMind ASN databases
- `v2rayGeoIPDat`: Ingests existing V2Ray binary databases ([`plugin/v2ray/dat_in.go`](https://github.com/loyalsoldier/geoip/blob/main/plugin/v2ray/dat_in.go))
- `text`: Parses plain-text IP/CIDR lists from files or stdin ([`plugin/plaintext/text_in.go`](https://github.com/loyalsoldier/geoip/blob/main/plugin/plaintext/text_in.go))
- `clashRuleSet` / `clashRuleSetClassical`: Reads Clash proxy rule sets

**Output Formats:**

- `v2rayGeoIPDat`: Writes V2Ray binary format ([`plugin/v2ray/dat_out.go`](https://github.com/loyalsoldier/geoip/blob/main/plugin/v2ray/dat_out.go))
- `maxmindMMDB`: Generates MaxMind MMDB databases ([`plugin/maxmind/maxmind_country_mmdb_out.go`](https://github.com/loyalsoldier/geoip/blob/main/plugin/maxmind/maxmind_country_mmdb_out.go))
- `text`: Exports plain-text CIDR lists ([`plugin/plaintext/text_out.go`](https://github.com/loyalsoldier/geoip/blob/main/plugin/plaintext/text_out.go))

Inspect all available converters by running `go run ./ list` (defined in [`list.go`](https://github.com/loyalsoldier/geoip/blob/main/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`](https://github.com/loyalsoldier/geoip/blob/main/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`](https://github.com/loyalsoldier/geoip/blob/main/maxmind_country_csv_in.go) and [`dat_in.go`](https://github.com/loyalsoldier/geoip/blob/main/dat_in.go)) read source data into a shared `Container` of `Entry` objects.
- Output converters (such as [`dat_out.go`](https://github.com/loyalsoldier/geoip/blob/main/dat_out.go) and [`maxmind_country_mmdb_out.go`](https://github.com/loyalsoldier/geoip/blob/main/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`](https://github.com/loyalsoldier/geoip/blob/main/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.