### Example: Get Database File MD5 Hash Source: https://github.com/maxmind/geoipupdate/blob/main/_autodocs/database-api.md Shows how to retrieve the MD5 hash of an existing database file. It checks if the database exists by comparing the returned hash with `database.ZeroMD5`. ```go writer, _ := database.NewLocalFileWriter("/usr/share/GeoIP", false, false) hash, err := writer.GetHash("GeoIP2-City") if err != nil { log.Fatal(err) } if hash == database.ZeroMD5 { log.Println("Database does not exist, will download") } else { log.Printf("Current hash: %s", hash) } ``` -------------------------------- ### Example Configuration File Source: https://github.com/maxmind/geoipupdate/blob/main/_autodocs/config-api.md This snippet shows a typical configuration file for geoipupdate, including account ID, license key, edition IDs, database directory, and other settings. Lines starting with '#' are comments, and empty lines are ignored. ```plaintext # Comments start with # AccountID 123456 LicenseKey myLicenseKeyHere EditionIDs GeoIP2-City GeoIP2-ASN DatabaseDirectory /usr/share/GeoIP Host https://updates.maxmind.com Proxy proxy.example.com:8080 ProxyUserPassword username:password PreserveFileTimes 1 LockFile /var/lock/geoipupdate.lock RetryFor 10m Parallelism 2 ``` -------------------------------- ### Help Message Output Example Source: https://github.com/maxmind/geoipupdate/blob/main/_autodocs/command-line.md This is an example of the help message output, listing all available command-line options and their descriptions. ```text Usage: geoipupdate [OPTIONS] Options: -f, --config-file string Configuration file -d, --database-directory string Store databases in this directory -v, --verbose Use verbose output -o, --output Output download/update results in JSON format --parallelism int Set the number of parallel database downloads -h, --help Display help and exit -V, --version Display the version and exit ``` -------------------------------- ### Download Database Edition Example Source: https://github.com/maxmind/geoipupdate/blob/main/_autodocs/client-api.md Example of how to use the Client.Download method to fetch a database edition. It demonstrates error handling for HTTP errors and checks if an update is available. ```go ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second) def cancel() resp, err := c.Download(ctx, "GeoIP2-City", "") if err != nil { var httpErr client.HTTPError if errors.As(err, &httpErr) { log.Printf("HTTP %d: %s", httpErr.StatusCode, httpErr.Body) } log.Fatal(err) } def resp.Reader.Close() if resp.UpdateAvailable { log.Printf("New version available (MD5: %s)", resp.MD5) // Read database from resp.Reader data, _ := io.ReadAll(resp.Reader) } else { log.Println("Database is up to date") } ``` -------------------------------- ### Configuration File Format Example Source: https://github.com/maxmind/geoipupdate/blob/main/_autodocs/configuration.md Illustrates the key-value syntax and comment handling in the GeoIPUpdate configuration file. Lines starting with '#' are comments, and empty lines are ignored. Each valid line contains a key followed by its value. ```plaintext # This is a comment Key Value # Multiple words must fit on one line after the key EditionIDs Database1 Database2 Database3 ``` -------------------------------- ### Version Information Output Example Source: https://github.com/maxmind/geoipupdate/blob/main/_autodocs/command-line.md This is an example of the output when the --version flag is used, showing the tool's version, git revision, build timestamp, and OS/architecture. ```text geoipupdate 7.1.1 (a1b2c3d4-modified, 2026-07-04T12:00:00Z, linux-amd64) ``` -------------------------------- ### GeoIPUpdate Command-Line Example Source: https://github.com/maxmind/geoipupdate/blob/main/_autodocs/command-line.md Example of running geoipupdate with command-line arguments to specify the configuration file, database directory, and parallelism. ```bash geoipupdate -f /etc/GeoIP.conf -d /tmp/databases --parallelism 8 ``` -------------------------------- ### GeoIPUpdate Configuration File Example Source: https://github.com/maxmind/geoipupdate/blob/main/_autodocs/command-line.md Example of a geoipupdate configuration file. Settings like DatabaseDirectory and Parallelism can be specified here. ```plaintext DatabaseDirectory /usr/share/GeoIP Parallelism 2 ``` -------------------------------- ### GeoIPUpdate Configuration File Example Source: https://github.com/maxmind/geoipupdate/blob/main/_autodocs/README.md An example configuration file for GeoIPUpdate. Set your AccountID, LicenseKey, desired EditionIDs, and database directory. ```properties # /etc/GeoIP.conf AccountID 123456 LicenseKey myLicenseKeyHere EditionIDs GeoIP2-City GeoIP2-ASN DatabaseDirectory /usr/share/GeoIP Parallelism 2 PreserveFileTimes 1 ``` -------------------------------- ### Example Usage of Client.Download() Source: https://github.com/maxmind/geoipupdate/blob/main/_autodocs/types.md Demonstrates how to download a database using Client.Download(), handle potential errors, and read the database content if an update is available. Remember to close the reader. ```go resp, err := client.Download(ctx, "GeoIP2-City", oldHash) if err != nil { log.Fatal(err) } defer resp.Reader.Close() if resp.UpdateAvailable { data, _ := io.ReadAll(resp.Reader) log.Printf("New database: %s", resp.MD5) } ``` -------------------------------- ### Configuration Precedence Example Source: https://github.com/maxmind/geoipupdate/blob/main/_autodocs/architecture.md Illustrates how configuration settings are overridden from lowest to highest priority: file, environment variables, and command-line arguments. ```plaintext config.DatabaseDirectory = "/usr/share/GeoIP" // from file env GEOIPUPDATE_DB_DIR=/var/lib/GeoIP // overrides geoipupdate -d /tmp // final value: /tmp ``` -------------------------------- ### Install GeoIP Update via Proto Source: https://github.com/maxmind/geoipupdate/blob/main/README.md Install GeoIP Update using the Proto toolchain manager. ```shell proto plugin add geoipupdate "https://raw.githubusercontent.com/maxmind/geoipupdate/refs/heads/main/proto.yaml" proto install geoipupdate ``` -------------------------------- ### Example: Initialize LocalFileWriter Source: https://github.com/maxmind/geoipupdate/blob/main/_autodocs/database-api.md Demonstrates how to create a new LocalFileWriter instance. It sets the database directory to /usr/share/GeoIP, enables file time preservation, and turns on verbose logging. Error handling is included. ```go writer, err := database.NewLocalFileWriter("/usr/share/GeoIP", true, true) if err != nil { log.Fatal(err) } ``` -------------------------------- ### Invalid Config File Syntax Examples Source: https://github.com/maxmind/geoipupdate/blob/main/_autodocs/errors.md Shows examples of malformed configuration lines that violate the required key-value format, leading to parsing errors. ```properties AccountID # Missing value 1234567 GeoIP2-City # Reversed order ``` -------------------------------- ### Install GeoIP Update using Go Source: https://github.com/maxmind/geoipupdate/blob/main/README.md Install the GeoIP Update program using the Go compiler. This installs the binary to your Go bin directory. ```bash go install github.com/maxmind/geoipupdate/v7/cmd/geoipupdate@latest ``` -------------------------------- ### Verbose Logging Example Output Source: https://github.com/maxmind/geoipupdate/blob/main/_autodocs/command-line.md This is an example of the detailed output generated when the --verbose flag is enabled, showing the tool's progress and actions. ```text geoipupdate version 7.1.1 Using config file /etc/GeoIP.conf Using database directory /usr/share/GeoIP Initializing file lock at /usr/share/GeoIP/.geoipupdate.lock Acquired lock file at /usr/share/GeoIP/.geoipupdate.lock Updates available for GeoIP2-City Database GeoIP2-City successfully updated: a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6 Database GeoIP2-ASN up to date Lock file /usr/share/GeoIP/.geoipupdate.lock successfully released ``` -------------------------------- ### Check for First Download using ZeroMD5 Source: https://github.com/maxmind/geoipupdate/blob/main/_autodocs/database-api.md This example demonstrates how to use the ZeroMD5 constant to check if a database needs to be downloaded for the first time. It retrieves the hash of a specified database and compares it with ZeroMD5. ```go hash, _ := writer.GetHash("GeoIP2-City") if hash == database.ZeroMD5 { log.Println("First download") } ``` -------------------------------- ### Configuration Precedence Example Source: https://github.com/maxmind/geoipupdate/blob/main/_autodocs/config-api.md Demonstrates how environment variables override configuration file settings for AccountID and EditionIDs. This is useful when dynamic configuration is needed. ```go config, _ := geoipupdate.NewConfig( geoipupdate.WithConfigFile("/etc/GeoIP.conf"), ) // Result: AccountID=200000 (env overrides file), LicenseKey="fileKey", EditionIDs=["GeoIP2-City", "GeoIP2-ASN"] (env overrides) ``` -------------------------------- ### Basic File Lock Usage Example Source: https://github.com/maxmind/geoipupdate/blob/main/_autodocs/file-lock-api.md Demonstrates the basic acquire and release pattern for a file lock. Ensure to release the lock after performing the necessary work. ```go lock, _ := NewFileLock("/var/lock/geoipupdate.lock", false) lock.Acquire() // Perform work lock.Release() ``` -------------------------------- ### Example: Write Database File Source: https://github.com/maxmind/geoipupdate/blob/main/_autodocs/database-api.md Demonstrates how to use the `Write` method to update a database file. It initializes a writer, downloads the latest database, and writes it if an update is available. Ensure the reader is closed after use. ```go writer, _ := database.NewLocalFileWriter("/usr/share/GeoIP", false, false) resp, _ := client.Download(ctx, "GeoIP2-City", "") defer resp.Reader.Close() if resp.UpdateAvailable { err := writer.Write( "GeoIP2-City", resp.Reader, resp.MD5, resp.LastModified, ) if err != nil { log.Printf("Failed to write database: %v", err) } } ``` -------------------------------- ### Example Command-Line Configuration Override Source: https://github.com/maxmind/geoipupdate/blob/main/_autodocs/README.md Demonstrates how command-line arguments override configuration file and environment variables for GeoIPUpdate settings. ```bash # config.DatabaseDirectory from file: /usr/share/GeoIP # env GEOIPUPDATE_DB_DIR overrides to: /var/lib/GeoIP # -d flag overrides to: /tmp git geoipupdate -f /etc/GeoIP.conf -d /tmp ``` -------------------------------- ### Build GeoIPUpdate with Custom Defaults Source: https://github.com/maxmind/geoipupdate/blob/main/_autodocs/command-line.md Install geoipupdate from source using 'go install', specifying custom default paths for the configuration file and database directory via linker flags. ```bash go install -ldflags "-X main.defaultConfigFile=/etc/GeoIP.conf \ -X main.defaultDatabaseDirectory=/usr/share/GeoIP" \ github.com/maxmind/geoipupdate/v7/cmd/geoipupdate@latest ``` -------------------------------- ### GeoIPUpdate Environment Variable Example Source: https://github.com/maxmind/geoipupdate/blob/main/_autodocs/command-line.md Example of setting the GEOIPUPDATE_PARALLELISM environment variable to control the parallelism setting. ```bash export GEOIPUPDATE_PARALLELISM=4 ``` -------------------------------- ### Client Configuration Option (Go) Source: https://github.com/maxmind/geoipupdate/blob/main/_autodocs/architecture.md Example of using the Option Pattern to configure the Client, specifically setting a custom endpoint. This pattern is extensible and backward compatible. ```go type Option func(*Client) func WithEndpoint(url string) Option { return func(c *Client) { c.endpoint = url } } // Usage: client.New(accountID, key, WithEndpoint("...")) ``` -------------------------------- ### Install GeoIP Update on Ubuntu via PPA Source: https://github.com/maxmind/geoipupdate/blob/main/README.md Add the MaxMind PPA to your Ubuntu sources to install GeoIP Update. ```bash sudo add-apt-repository ppa:maxmind/ppa ``` ```bash sudo apt update sudo apt install geoipupdate ``` -------------------------------- ### JSON Output Example Source: https://github.com/maxmind/geoipupdate/blob/main/_autodocs/configuration.md This is an example of the JSON output format when the -o or --output flag is used. It includes details about edition IDs, hashes, and timestamps. ```json [ { "edition_id": "GeoIP2-City", "old_hash": "00000000000000000000000000000000", "new_hash": "a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6", "modified_at": 1719259200, "checked_at": 1719264300 } ] ``` -------------------------------- ### Concurrent Download Configuration Example Source: https://github.com/maxmind/geoipupdate/blob/main/_autodocs/updater-api.md Demonstrates how `config.EditionIDs` and `config.Parallelism` influence the order and concurrency of database edition downloads. The updater uses `errgroup.Group` with a semaphore for managing concurrent operations. ```go config.EditionIDs = []string{"GeoIP2-City", "GeoIP2-ASN", "GeoLite2-Country"} config.Parallelism = 2 // GeoIP2-City and GeoIP2-ASN download concurrently // GeoLite2-Country waits for one to complete, then starts // If GeoIP2-City fails, GeoIP2-ASN is cancelled, GeoLite2-Country never starts ``` -------------------------------- ### High-Performance Configuration (Command-line) Source: https://github.com/maxmind/geoipupdate/blob/main/_autodocs/configuration.md Execute GeoIPUpdate with command-line flags for high-performance tuning. This example uses a configuration file, verbose output, and enables offline mode. ```bash geoipupdate -f /etc/GeoIP.conf -v -o ``` -------------------------------- ### Example Full ReadResult JSON Output Source: https://github.com/maxmind/geoipupdate/blob/main/_autodocs/types.md This example shows a full JSON output containing multiple ReadResult entries, demonstrating how they are returned as a JSON array. ```json [ {"edition_id": "GeoIP2-City", "old_hash": "...", "new_hash": "...", "modified_at": 1719259200, "checked_at": 1719264300}, {"edition_id": "GeoIP2-ASN", "old_hash": "...", "new_hash": "...", "checked_at": 1719264305}, {"edition_id": "GeoLite2-Country", "old_hash": "...", "new_hash": "...", "checked_at": 1719264310} ] ``` -------------------------------- ### Typical GeoIP Database Update Workflow Source: https://github.com/maxmind/geoipupdate/blob/main/_autodocs/database-api.md This pattern shows how to initialize a writer, get the current database hash, download updates if available, and write the new database. Ensure resources like readers are closed. ```go // Create writer once per session writer, err := database.NewLocalFileWriter( "/usr/share/GeoIP", true, // preserve server timestamps false, // quiet mode ) if err != nil { log.Fatal(err) } // Before each download currentHash, err := writer.GetHash("GeoIP2-City") if err != nil { log.Fatal(err) } // Download with current hash (skips download if identical) resp, err := client.Download(ctx, "GeoIP2-City", currentHash) if err != nil { log.Fatal(err) } def resp.Reader.Close() // Write if update available if resp.UpdateAvailable { err := writer.Write( "GeoIP2-City", resp.Reader, resp.MD5, resp.LastModified, ) if err != nil { log.Fatal(err) } log.Println("Update complete") } ``` -------------------------------- ### GeoIPUpdate Exit Codes Examples Source: https://github.com/maxmind/geoipupdate/blob/main/_autodocs/command-line.md Demonstrates successful execution and error conditions using exit codes. Use these examples to understand the tool's behavior on success (0) and various errors (1). ```bash # Success (no updates or all updated) $ geoipupdate -f /etc/GeoIP.conf $ echo $? 0 ``` ```bash # Config error $ geoipupdate -f /nonexistent.conf geoiupdate: Error loading configuration: ... $ echo $? ``` ```bash # API error $ geoipupdate -f /etc/GeoIP.conf geoiupdate: Error retrieving updates: received HTTP status code: 401 $ echo $? ``` -------------------------------- ### EditionIDs Configuration Example Source: https://github.com/maxmind/geoipupdate/blob/main/_autodocs/configuration.md Lists the database edition IDs to be downloaded, separated by spaces. At least one edition ID must be specified. Valid IDs include GeoIP2 and GeoLite2 series. ```plaintext EditionIDs GeoIP2-City GeoIP2-ASN GeoLite2-Country ``` -------------------------------- ### GeoIPUpdate Environment Variables Setup Source: https://github.com/maxmind/geoipupdate/blob/main/_autodocs/README.md Sets environment variables to configure GeoIPUpdate. This is an alternative to using a configuration file. ```bash export GEOIPUPDATE_ACCOUNT_ID=123456 export GEOIPUPDATE_LICENSE_KEY=myLicenseKey export GEOIPUPDATE_EDITION_IDS="GeoIP2-City GeoIP2-ASN" export GEOIPUPDATE_DB_DIR=/var/lib/GeoIP export GEOIPUPDATE_PARALLELISM=4 geoipupdate ``` -------------------------------- ### Handle HTTP Errors in Download Call Source: https://github.com/maxmind/geoipupdate/blob/main/_autodocs/client-api.md Example of how to check for and handle HTTP errors, specifically unauthorized access, after a Download call. ```go resp, err := c.Download(ctx, "GeoIP2-City", "") if err != nil { var httpErr client.HTTPError if errors.As(err, &httpErr) { if httpErr.StatusCode == http.StatusUnauthorized { log.Println("Invalid credentials") } } } ``` -------------------------------- ### Minimal Configuration (Environment Variables) Source: https://github.com/maxmind/geoipupdate/blob/main/_autodocs/configuration.md Configure GeoIPUpdate using environment variables for a minimal setup. This is useful for scripting or containerized environments. ```bash export GEOIPUPDATE_ACCOUNT_ID=123456 export GEOIPUPDATE_LICENSE_KEY=abcDEF123456 export GEOIPUPDATE_EDITION_IDS="GeoIP2-City" ``` -------------------------------- ### File Locking Example (Go) Source: https://github.com/maxmind/geoipupdate/blob/main/_autodocs/architecture.md Demonstrates acquiring and releasing a file lock to ensure process serialization. This is crucial for safe cron job scheduling, preventing multiple overlapping runs. ```go lock.Acquire() // Blocks if held by another process def lock.Release() ``` -------------------------------- ### Write Database File Source: https://github.com/maxmind/geoipupdate/blob/main/_autodocs/database-api.md Writes a new database file to disk, validates its integrity using an MD5 hash, and atomically installs it. Requires the database edition ID, a reader for the decompressed file, the expected MD5 hash, and the server's last modified time. ```go func Write(editionID string, reader io.ReadCloser, md5 string, lastModified time.Time) error ``` -------------------------------- ### Writer.Write Source: https://github.com/maxmind/geoipupdate/blob/main/_autodocs/database-api.md Writes a new database file to disk, validates its integrity, and atomically installs it. It handles temporary file creation, MD5 validation, atomic renaming, and directory syncing. ```APIDOC ## Write ### Description Writes a new database file to disk, validates its integrity, and atomically installs it. ### Method `Write(editionID string, reader io.ReadCloser, md5 string, lastModified time.Time) error` ### Parameters #### Path Parameters None #### Query Parameters None #### Request Body None ### Parameters Table | Parameter | Type | Required | Description | |---|---|---|---| | editionID | `string` | Yes | Database edition ID (e.g., `GeoIP2-City`) used in filename | | reader | `io.ReadCloser` | Yes | Decompressed MMDB file (tar/gzip extracted); must be readable | | md5 | `string` | Yes | Expected MD5 hash of the complete file (lowercase hex, 32 chars) | | lastModified | `time.Time` | Yes | Server's Last-Modified time; may be zero (see PreserveFileTimes) | ### Returns `error` - **nil** — File successfully written, validated, and installed - **Errors:** - MD5 mismatch after write - I/O errors during write or sync - File system errors (permission, space, etc.) ### Request Example ```go writer, _ := database.NewLocalFileWriter("/usr/share/GeoIP", false, false) resp, _ := client.Download(ctx, "GeoIP2-City", "") defer resp.Reader.Close() if resp.UpdateAvailable { err := writer.Write( "GeoIP2-City", resp.Reader, resp.MD5, resp.LastModified, ) if err != nil { log.Printf("Failed to write database: %v", err) } } ``` ``` -------------------------------- ### LicenseKey Configuration Example Source: https://github.com/maxmind/geoipupdate/blob/main/_autodocs/configuration.md Sets the MaxMind license key, which is case-sensitive. This key is used to authorize downloads. It can be provided directly or read from a file for enhanced security. ```plaintext LicenseKey abcDEF123456ghijklMNOPQR ``` -------------------------------- ### Get Database File MD5 Hash Source: https://github.com/maxmind/geoipupdate/blob/main/_autodocs/database-api.md Returns the MD5 hash of the currently installed database file for a given edition ID. Returns `ZeroMD5` if the file does not exist, or an error if the file exists but cannot be read. ```go func GetHash(editionID string) (string, error) ``` -------------------------------- ### AccountID Configuration Example Source: https://github.com/maxmind/geoipupdate/blob/main/_autodocs/configuration.md Specifies the MaxMind account ID required for authentication. This can be set using the 'AccountID' or 'UserId' key in the configuration file. Must be a positive integer. ```plaintext AccountID 123456 ``` -------------------------------- ### Updater Retry Logic Logging Source: https://github.com/maxmind/geoipupdate/blob/main/_autodocs/updater-api.md This example demonstrates the verbose logging output during the retry process for transient errors when downloading GeoIP2 databases. It shows the backoff delays and successful update messages. ```text Couldn't download GeoIP2-City, retrying in 1.5s: received HTTP status code: 503 Couldn't download GeoIP2-City, retrying in 3.1s: received HTTP status code: 503 Updates available for GeoIP2-City Database GeoIP2-City successfully updated: a1b2c3d4... ``` -------------------------------- ### Interface-Based Dependency Injection for Writers Source: https://github.com/maxmind/geoipupdate/blob/main/_autodocs/types.md Accept interfaces rather than concrete types in constructors to enable dependency injection and improve testability. This example shows an Updater accepting a Writer interface. ```go // Define interface type Writer interface { Write(...) error GetHash(...) (string, error) } // Accept interface, not concrete type func NewUpdater(config *Config) (*Updater, error) { // Creates concrete LocalFileWriter internally writer, _ := database.NewLocalFileWriter(...) return &Updater{writer: writer}, nil } ``` -------------------------------- ### Load Configuration and Run Updater (Go) Source: https://github.com/maxmind/geoipupdate/blob/main/_autodocs/architecture.md Shows how to load configuration from a file, create an updater instance, and run the update process. Used by the CLI and larger integrations. ```go import "github.com/maxmind/geoipupdate/v7/internal/geoipupdate" // Load configuration config, _ := geoipupdate.NewConfig( geoipupdate.WithConfigFile("/etc/GeoIP.conf"), ) // Create updater updater, _ := geoipupdate.NewUpdater(config) // Run updates updater.Run(ctx) ``` -------------------------------- ### Create and Use Client (Go) Source: https://github.com/maxmind/geoipupdate/blob/main/_autodocs/architecture.md Demonstrates how to create a new client instance and download GeoIP data using the public API. Requires account ID and license key. ```go import "github.com/maxmind/geoipupdate/v7/client" // Users can directly create and use Client: c, _ := client.New(accountID, licenseKey) resp, _ := c.Download(ctx, "GeoIP2-City", oldMD5) ``` -------------------------------- ### Handle Specific Errors in Code Source: https://github.com/maxmind/geoipupdate/blob/main/_autodocs/errors.md This example demonstrates how to capture and handle specific error conditions within your Go code, such as timeouts, lock contention, or database integrity failures, by inspecting the error string or using errors.Is. ```go ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) deferr cancel() err := updater.Run(ctx) if err != nil { switch { case errors.Is(err, context.DeadlineExceeded): log.Println("Update timed out; increase timeout or check network") case strings.Contains(err.Error(), "lock"): log.Println("Concurrent update in progress") case strings.Contains(err.Error(), "md5"): log.Println("Database integrity check failed") default: log.Printf("Unknown error: %v", err) } } ``` -------------------------------- ### Get Version Info from Build Info Source: https://github.com/maxmind/geoipupdate/blob/main/_autodocs/architecture.md This Go code snippet demonstrates how to read build information, including Git revision, build timestamp, and uncommitted changes, from debug.ReadBuildInfo(). The format includes version, VCS revision, build time, and OS/architecture. ```go // cmd/geoipupdate/version.go init() // Reads from debug.ReadBuildInfo() to extract: // - vcs.revision: Git commit hash // - vcs.time: Build timestamp // - vcs.modified: Uncommitted changes // - GOOS, GOARCH: Operating system and architecture // Format: "7.1.1 (a1b2c3d4-modified, 2026-07-04T12:00:00Z, linux-amd64)" ``` -------------------------------- ### Load Configuration and Create Updater in Go Source: https://github.com/maxmind/geoipupdate/blob/main/_autodocs/updater-api.md This Go snippet demonstrates how to load configuration from a file and enable verbose logging, then create a new updater instance. Ensure proper error handling for configuration and updater creation. ```go // Load configuration config, err := geoipupdate.NewConfig( geoipupdate.WithConfigFile("/etc/GeoIP.conf"), geoipupdate.WithVerbose, ) if err != nil { log.Fatal(err) } // Create updater updater, err := geoipupdate.NewUpdater(config) if err != nil { log.Fatal(err) } // Run with timeout ctx, cancel := context.WithTimeout(context.Background(), 30*time.Minute) def cancel() if err := updater.Run(ctx); err != nil { log.Fatal(err) } log.Println("All editions updated successfully") ``` -------------------------------- ### Install GeoIP Update on macOS via Homebrew Source: https://github.com/maxmind/geoipupdate/blob/main/README.md Install GeoIP Update using the Homebrew package manager on macOS. ```bash brew install geoipupdate ``` -------------------------------- ### Initialize Updater Source: https://github.com/maxmind/geoipupdate/blob/main/_autodocs/INDEX.md Create a new Updater instance with the provided configuration. This orchestrates the download and update process. ```go geoipupdate.NewUpdater(config) → *Updater, error ``` -------------------------------- ### Config Loading Option (Go) Source: https://github.com/maxmind/geoipupdate/blob/main/_autodocs/architecture.md Illustrates using the Option Pattern for configuration loading, such as setting parallelism. This provides a type-safe and extensible way to configure settings. ```go type Option func(*Config) error func WithParallelism(n int) Option { return func(c *Config) error { c.Parallelism = n return nil } } // Usage: config.NewConfig(WithParallelism(4), WithVerbose) ``` -------------------------------- ### Create New Client Source: https://github.com/maxmind/geoipupdate/blob/main/_autodocs/client-api.md Creates a new Client instance. Use this to initialize the GeoIP database downloader with your account credentials. Optional settings can be provided. ```go client, err := client.New(123456, "myLicenseKey") if err != nil { log.Fatal(err) } ``` ```go client, err := client.New( 123456, "myLicenseKey", client.WithEndpoint("https://custom.example.com"), ) ``` -------------------------------- ### Updater File Lock Error Example Source: https://github.com/maxmind/geoipupdate/blob/main/_autodocs/updater-api.md This example shows the typical error message when the geoipupdate updater attempts to acquire a file lock that is already held by another process. This indicates a concurrency issue. ```go log.Fatal(updater.Run(ctx)) // Output: "lock ... already acquired by another process" ``` -------------------------------- ### Create and Run Updater with Library Source: https://github.com/maxmind/geoipupdate/blob/main/_autodocs/INDEX.md Instantiate the updater with your configuration and then run it to perform GeoIP database updates. This is for users who need the full updater logic within their Go application. ```go NewUpdater(config) updater.Run(ctx) ``` -------------------------------- ### Writer.GetHash Source: https://github.com/maxmind/geoipupdate/blob/main/_autodocs/database-api.md Returns the MD5 hash of the currently installed database file. Returns a special zero hash if the file does not exist. ```APIDOC ## GetHash ### Description Returns the MD5 hash of the currently installed database file. ### Method `GetHash(editionID string) (string, error)` ### Parameters #### Path Parameters None #### Query Parameters None #### Request Body None ### Parameters Table | Parameter | Type | Required | Description | |---|---|---|---| | editionID | `string` | Yes | Database edition ID (e.g., `GeoIP2-City`) | ### Returns `string, error` - **String:** Lowercase hex MD5 hash (32 characters) - **Special value:** `ZeroMD5` (`00000000000000000000000000000000`) if file doesn't exist - **Error:** Only if file exists but cannot be read (permission, I/O, etc.) ### Request Example ```go writer, _ := database.NewLocalFileWriter("/usr/share/GeoIP", false, false) hash, err := writer.GetHash("GeoIP2-City") if err != nil { log.Fatal(err) } if hash == database.ZeroMD5 { log.Println("Database does not exist, will download") } else { log.Printf("Current hash: %s", hash) } ``` ``` -------------------------------- ### File Modification Time Example (Bash) Source: https://github.com/maxmind/geoipupdate/blob/main/_autodocs/database-api.md Illustrates the difference in file modification times with and without the `preserveFileTime` option enabled. ```bash # Without preserve -rw-r--r-- admin admin 500K Jul 04 15:30 GeoIP2-City.mmdb # Current time # With preserve -rw-r--r-- admin admin 500K Jun 25 12:00 GeoIP2-City.mmdb # Server's release time ``` -------------------------------- ### GeoIPUpdate Cron Job Setup Source: https://github.com/maxmind/geoipupdate/blob/main/_autodocs/command-line.md Schedule the geoipupdate tool to run automatically at regular intervals using a cron job. ```bash # Every 6 hours 0 */6 * * * /usr/bin/geoipupdate -f /etc/GeoIP.conf -v >> /var/log/geoipupdate.log 2>&1 ``` -------------------------------- ### GeoIPUpdate API Error: Unauthorized Source: https://github.com/maxmind/geoipupdate/blob/main/_autodocs/command-line.md Example of an API error message indicating an 'Unauthorized' status code (401) when retrieving updates. ```text Error retrieving updates: downloading editions: received HTTP status code: 401: Unauthorized ``` -------------------------------- ### Load Config from File and Environment Source: https://github.com/maxmind/geoipupdate/blob/main/_autodocs/config-api.md Loads configuration from a specified file and then applies overrides from environment variables. Handles potential errors during configuration loading. ```go // Load from config file and environment config, err := geoipupdate.NewConfig( geoipupdate.WithConfigFile("/etc/GeoIP.conf"), ) if err != nil { log.Fatal(err) } // Override specific fields from command-line args if cmdDatabaseDir != "" { if err := geoipupdate.WithDatabaseDirectory(cmdDatabaseDir)(config); err != nil { log.Fatal(err) } } log.Printf("Using %d parallel downloads", config.Parallelism) ``` -------------------------------- ### GeoIPUpdate Configuration Error: Missing Required Field Source: https://github.com/maxmind/geoipupdate/blob/main/_autodocs/command-line.md Example of a configuration error message indicating that a required field, such as 'EditionIDs', is missing. ```text Error loading configuration: the 'EditionIDs' option is required ``` -------------------------------- ### Initialize GeoIP Client Library Source: https://github.com/maxmind/geoipupdate/blob/main/_autodocs/INDEX.md Create a new GeoIP client instance using your account credentials. This is the first step when using the client API for custom integrations. ```go client.New(accountID, licenseKey) ``` -------------------------------- ### Get Database Hash Source: https://github.com/maxmind/geoipupdate/blob/main/_autodocs/INDEX.md Retrieve the MD5 hash of a specific database edition that has already been written. Returns the hash string or an error. ```go writer.GetHash(editionID) → string, error ``` -------------------------------- ### Create Configuration Source: https://github.com/maxmind/geoipupdate/blob/main/_autodocs/INDEX.md Initialize a new configuration object for GeoIPUpdate. Use options to specify settings like config file path or parallelism. ```go geoipupdate.NewConfig(options...) → *Config, error ``` -------------------------------- ### GeoIPUpdate Configuration Error: Duplicate Key Source: https://github.com/maxmind/geoipupdate/blob/main/_autodocs/command-line.md Example of a configuration error message indicating that a key, such as 'AccountID', is present multiple times in the configuration. ```text Error loading configuration: 'AccountID' is in the config multiple times ``` -------------------------------- ### GeoIPUpdate Configuration Error: Invalid Value Source: https://github.com/maxmind/geoipupdate/blob/main/_autodocs/command-line.md Example of a configuration error message indicating an invalid value for a setting, such as a negative parallelism value. ```text Error loading configuration: parallelism can't be negative, got '-4' ``` -------------------------------- ### Specify Configuration File Path Source: https://github.com/maxmind/geoipupdate/blob/main/_autodocs/config-api.md Use this option to specify the path to a configuration file. Ignored if the provided file path is empty. ```go geoipupdate.NewConfig(geoipupdate.WithConfigFile("/etc/GeoIP.conf")) ``` -------------------------------- ### Initialize HTTP Client Source: https://github.com/maxmind/geoipupdate/blob/main/_autodocs/INDEX.md Create a new HTTP client instance for the GeoIP API. Pass your AccountID, LicenseKey, and any additional options. ```go client.New(accountID, licenseKey, options...) ``` -------------------------------- ### GeoIPUpdate Configuration Error: Invalid Format Source: https://github.com/maxmind/geoipupdate/blob/main/_autodocs/command-line.md Example of a configuration error message indicating an invalid format on a specific line in the configuration file. ```text Error loading configuration: invalid format on line 15 ``` -------------------------------- ### JSON Output Example Source: https://github.com/maxmind/geoipupdate/blob/main/_autodocs/command-line.md This JSON output represents the results of database updates, including edition IDs, old and new hashes, and timestamps. ```json [ { "edition_id": "GeoIP2-City", "old_hash": "00000000000000000000000000000000", "new_hash": "a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6", "modified_at": 1719259200, "checked_at": 1719264300 }, { "edition_id": "GeoIP2-ASN", "old_hash": "b1c2d3e4f5g6h7i8j9k0l1m2n3o4p5q6", "new_hash": "b1c2d3e4f5g6h7i8j9k0l1m2n3o4p5q6", "checked_at": 1719264305 } ] ``` -------------------------------- ### GeoIPUpdate API Error: Service Unavailable Source: https://github.com/maxmind/geoipupdate/blob/main/_autodocs/command-line.md Example of an API error message indicating a 'Service Unavailable' status code (503), with a note about retrying. ```text Error retrieving updates: downloading editions: Couldn't download GeoIP2-City, retrying in 1.5s: received HTTP status code: 503: Service Unavailable ``` -------------------------------- ### Minimal Configuration (File) Source: https://github.com/maxmind/geoipupdate/blob/main/_autodocs/configuration.md Use this minimal configuration file when only the essential fields are required. Ensure AccountID, LicenseKey, and EditionIDs are provided. ```properties AccountID 123456 LicenseKey abcDEF123456 EditionIDs GeoIP2-City ``` -------------------------------- ### New Client Constructor Source: https://github.com/maxmind/geoipupdate/blob/main/_autodocs/client-api.md Creates a new `Client` instance for downloading GeoIP/GeoLite databases. It requires your MaxMind account ID and license key, and accepts optional configuration functions. ```APIDOC ## New Client Constructor ### Description Creates a new `Client` instance configured with account credentials and optional settings. ### Signature ```go func New( accountID int, licenseKey string, options ...Option, ) (Client, error) ``` ### Parameters #### Path Parameters * **accountID** (int) - Required - MaxMind account ID; must be > 0 * **licenseKey** (string) - Required - MaxMind license key; must be non-empty * **options** (...Option) - Optional - Optional configuration functions ### Returns * **Client** - A configured client instance. * **error** - An error if validation fails (e.g., invalid account ID or empty license key). ### Example ```go client, err := client.New(123456, "myLicenseKey") if err != nil { log.Fatal(err) } // With custom endpoint client, err := client.New( 123456, "myLicenseKey", client.WithEndpoint("https://custom.example.com"), ) ``` ``` -------------------------------- ### Verbose Debugging for GeoIP Update Source: https://github.com/maxmind/geoipupdate/blob/main/_autodocs/file-lock-api.md Run geoipupdate with the verbose flag twice to get detailed output, including information about lock acquisition and release. ```bash geoipupdate -f /etc/GeoIP.conf -v -v # Additional output including lock acquisition/release ``` -------------------------------- ### Version Format at Runtime Source: https://github.com/maxmind/geoipupdate/blob/main/_autodocs/types.md Illustrates the format of the version string when modified at runtime, including build details like commit hash, timestamp, and OS/architecture. ```text 7.1.1 (a1b2c3d4-modified, 2026-07-04T12:00:00Z, linux-amd64) ``` -------------------------------- ### Create Local File Writer Source: https://github.com/maxmind/geoipupdate/blob/main/_autodocs/INDEX.md Instantiate a file writer for local storage. Specify the directory, whether to preserve file times, and verbosity. ```go database.NewLocalFileWriter(dir, preserveTime, verbose) ``` -------------------------------- ### Cron Job for Automatic Updates Source: https://github.com/maxmind/geoipupdate/blob/main/_autodocs/README.md Schedule geoipupdate to run automatically every 6 hours. This example redirects verbose output and errors to a log file. ```cron 0 */6 * * * /usr/bin/geoipupdate -f /etc/GeoIP.conf -v >> /var/log/geoipupdate.log 2>&1 ``` -------------------------------- ### Example JSON Output for ReadResult Source: https://github.com/maxmind/geoipupdate/blob/main/_autodocs/updater-api.md Illustrates the expected JSON format for `ReadResult` when marshaled. Time fields are represented as Unix timestamps, and zero times are omitted. ```json [ { "edition_id": "GeoIP2-City", "old_hash": "00000000000000000000000000000000", "new_hash": "a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6", "modified_at": 1719259200, "checked_at": 1719264300 }, { "edition_id": "GeoIP2-ASN", "old_hash": "x1y2z3a4b5c6d7e8f9g0h1i2j3k4l5m6", "new_hash": "x1y2z3a4b5c6d7e8f9g0h1i2j3k4l5m6" "checked_at": 1719264305 } ] ``` -------------------------------- ### Create Local Database File Writer Source: https://github.com/maxmind/geoipupdate/blob/main/_autodocs/INDEX.md Instantiate a writer for local filesystem databases. Allows specifying the directory, preservation of modification times, and verbosity. ```go NewLocalFileWriter(dir string, preserveTime, verbose bool) (*LocalFileWriter, error) ``` -------------------------------- ### Basic GeoIP Download in Go Source: https://github.com/maxmind/geoipupdate/blob/main/_autodocs/client-api.md Demonstrates the basic usage of the GeoIPUpdate client to download a database. Ensure to handle the error returned by the Download function. ```go client, _ := client.New(accountID, licenseKey) resp, err := client.Download(context.Background(), "GeoIP2-City", "") if err != nil { log.Fatal(err) } defer resp.Reader.Close() ``` -------------------------------- ### GeoIPUpdate API Error: Forbidden Source: https://github.com/maxmind/geoipupdate/blob/main/_autodocs/command-line.md Example of an API error message indicating a 'Forbidden' status code (403), often meaning the account lacks permission. ```text Error retrieving updates: downloading editions: received HTTP status code: 403: Forbidden ``` -------------------------------- ### Configure Proxy Settings in Code Source: https://github.com/maxmind/geoipupdate/blob/main/_autodocs/config-api.md Configure proxy settings by providing a configuration file path. The library automatically parses proxy details from the file, including URL, port, and user authentication. URL credentials take precedence over explicit ProxyUserPassword settings. ```go config, _ := geoipupdate.NewConfig( geoipupdate.WithConfigFile("/etc/GeoIP.conf"), ) // config.Proxy is now &url.URL with scheme "http", host "example.com:8080", User set ``` -------------------------------- ### Go Client: Download GeoIP Database Source: https://github.com/maxmind/geoipupdate/blob/main/_autodocs/README.md Demonstrates how to use the GeoIPUpdate client package in Go to download a specific GeoIP database. Handles potential errors during client creation and download. ```go package main import ( "context" "log" "github.com/maxmind/geoipupdate/v7/client" ) func main() { // Create client c, err := client.New(123456, "myLicenseKey") if err != nil { log.Fatal(err) } // Download database ctx := context.Background() resp, err := c.Download(ctx, "GeoIP2-City", "") if err != nil { log.Fatal(err) } defer resp.Reader.Close() if resp.UpdateAvailable { log.Printf("New database available: %s", resp.MD5) // Read database from resp.Reader } else { log.Println("Database is up to date") } } ``` -------------------------------- ### Load Configuration for Updater Library Source: https://github.com/maxmind/geoipupdate/blob/main/_autodocs/INDEX.md Load configuration settings for the updater, potentially from a configuration file. This is part of setting up the full updater functionality. ```go NewConfig(WithConfigFile(...)) ``` -------------------------------- ### Create Geoipupdate Configuration Source: https://github.com/maxmind/geoipupdate/blob/main/_autodocs/INDEX.md Initialize a new configuration for the geoipupdate CLI. Accepts various option functions for customization. ```go NewConfig(flagOptions...Option) (*Config, error) ``` -------------------------------- ### GeoIPUpdate Fail-Fast Error Example Source: https://github.com/maxmind/geoipupdate/blob/main/_autodocs/errors.md Demonstrates a non-retryable error scenario where a 401 Unauthorized response causes immediate failure without retries, adhering to a fail-fast principle. ```text Download returns 401 Unauthorized → IsRetryableError() returns false → Error returned to Updater → Updater marks edition failed → Processing stops (fail-fast) ``` -------------------------------- ### Display Help Message Source: https://github.com/maxmind/geoipupdate/blob/main/_autodocs/command-line.md The -h or --help option displays a comprehensive help message detailing all available options and their usage. The command then exits. ```bash geoipupdate --help ``` ```bash geoipupdate -h ``` -------------------------------- ### Troubleshoot Configuration and Errors Source: https://github.com/maxmind/geoipupdate/blob/main/_autodocs/README.md Use verbose logging to check the configuration being used and to view detailed error messages. This is helpful for diagnosing issues. ```bash geoipupdate -f /etc/GeoIP.conf -v # Will print config being used ``` ```bash geoipupdate -f /etc/GeoIP.conf -v ``` -------------------------------- ### Invalid Option Values Source: https://github.com/maxmind/geoipupdate/blob/main/_autodocs/configuration.md These errors occur when configuration options are set to values that do not conform to the expected format or constraints. For example, parallelism cannot be negative, and duration values must be valid. ```text Error loading configuration: parallelism can't be negative, got '-4' Error loading configuration: 'not-a-duration' is not a valid duration ``` -------------------------------- ### Go Updater: Run Database Updates Source: https://github.com/maxmind/geoipupdate/blob/main/_autodocs/README.md Shows how to use the GeoIPUpdate internal updater package in Go to load configuration and run database updates. Supports loading configuration from a file and enabling verbose output. ```go package main import ( "context" "log" "github.com/maxmind/geoipupdate/v7/internal/geoipupdate" ) func main() { // Load configuration config, err := geoipupdate.NewConfig( geoipupdate.WithConfigFile("/etc/GeoIP.conf"), geoipupdate.WithVerbose, ) if err != nil { log.Fatal(err) } // Create updater updater, err := geoipupdate.NewUpdater(config) if err != nil { log.Fatal(err) } // Run updates if err := updater.Run(context.Background()); err != nil { log.Fatal(err) } log.Println("Update completed") } ```