diff --git a/modules/ingest-geoip/src/internalClusterTest/java/org/elasticsearch/ingest/geoip/GeoIpDownloaderCliIT.java b/modules/ingest-geoip/src/internalClusterTest/java/org/elasticsearch/ingest/geoip/GeoIpDownloaderCliIT.java
new file mode 100644
index 0000000000000..28db1ef5cb699
--- /dev/null
+++ b/modules/ingest-geoip/src/internalClusterTest/java/org/elasticsearch/ingest/geoip/GeoIpDownloaderCliIT.java
@@ -0,0 +1,27 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License
+ * 2.0 and the Server Side Public License, v 1; you may not use this file except
+ * in compliance with, at your election, the Elastic License 2.0 or the Server
+ * Side Public License, v 1.
+ */
+
+package org.elasticsearch.ingest.geoip;
+
+import org.elasticsearch.common.settings.Settings;
+
+public class GeoIpDownloaderCliIT extends GeoIpDownloaderIT {
+
+    @Override
+    protected Settings nodeSettings(int nodeOrdinal, Settings otherSettings) {
+        Settings.Builder settings = Settings.builder().put(super.nodeSettings(nodeOrdinal, otherSettings));
+        if (ENDPOINT != null) {
+            settings.put(GeoIpDownloader.ENDPOINT_SETTING.getKey(), ENDPOINT + "cli/overview.json");
+        }
+        return settings.build();
+    }
+
+    public void testUseGeoIpProcessorWithDownloadedDBs() {
+        assumeTrue("this test can't work with CLI (some expected files are missing)", false);
+    }
+}
diff --git a/modules/ingest-geoip/src/internalClusterTest/java/org/elasticsearch/ingest/geoip/GeoIpDownloaderIT.java b/modules/ingest-geoip/src/internalClusterTest/java/org/elasticsearch/ingest/geoip/GeoIpDownloaderIT.java
index 9849395bbd09f..789234fb8e695 100644
--- a/modules/ingest-geoip/src/internalClusterTest/java/org/elasticsearch/ingest/geoip/GeoIpDownloaderIT.java
+++ b/modules/ingest-geoip/src/internalClusterTest/java/org/elasticsearch/ingest/geoip/GeoIpDownloaderIT.java
@@ -58,7 +58,7 @@
 
 public class GeoIpDownloaderIT extends AbstractGeoIpIT {
 
-    private static final String ENDPOINT = System.getProperty("geoip_endpoint");
+    protected static final String ENDPOINT = System.getProperty("geoip_endpoint");
 
     @Override
     protected Settings nodeSettings(int nodeOrdinal, Settings otherSettings) {
@@ -240,8 +240,8 @@ public void testUseGeoIpProcessorWithDownloadedDBs() throws Exception {
                 try (Stream<Path> list = Files.list(geoipTmpDir)) {
                     List<String> files = list.map(Path::getFileName).map(Path::toString).collect(Collectors.toList());
                     assertThat(files, containsInAnyOrder("GeoLite2-City.mmdb", "GeoLite2-Country.mmdb", "GeoLite2-ASN.mmdb",
-                        "GeoLite2-City.mmdb_COPYRIGHT.txt","GeoLite2-Country.mmdb_COPYRIGHT.txt","GeoLite2-ASN.mmdb_COPYRIGHT.txt",
-                        "GeoLite2-City.mmdb_LICENSE.txt","GeoLite2-Country.mmdb_LICENSE.txt","GeoLite2-ASN.mmdb_LICENSE.txt",
+                        "GeoLite2-City.mmdb_COPYRIGHT.txt", "GeoLite2-Country.mmdb_COPYRIGHT.txt", "GeoLite2-ASN.mmdb_COPYRIGHT.txt",
+                        "GeoLite2-City.mmdb_LICENSE.txt", "GeoLite2-Country.mmdb_LICENSE.txt", "GeoLite2-ASN.mmdb_LICENSE.txt",
                         "GeoLite2-ASN.mmdb_README.txt"));
                 }
             }
diff --git a/test/fixtures/geoip-fixture/build.gradle b/test/fixtures/geoip-fixture/build.gradle
index d8f85759cf7f8..d6935624046d4 100644
--- a/test/fixtures/geoip-fixture/build.gradle
+++ b/test/fixtures/geoip-fixture/build.gradle
@@ -13,6 +13,9 @@ tasks.named("test").configure { enabled = false }
 
 dependencies {
   api project(':server')
+  api project(':distribution:tools:geoip-cli')
+  api project(":libs:elasticsearch-cli")
+  api project(":libs:elasticsearch-x-content")
 }
 
 tasks.named("preProcessFixture").configure {
diff --git a/test/fixtures/geoip-fixture/src/main/java/fixture/geoip/GeoIpHttpFixture.java b/test/fixtures/geoip-fixture/src/main/java/fixture/geoip/GeoIpHttpFixture.java
index f2d0e89be9e06..0b6e5eca30d8b 100644
--- a/test/fixtures/geoip-fixture/src/main/java/fixture/geoip/GeoIpHttpFixture.java
+++ b/test/fixtures/geoip-fixture/src/main/java/fixture/geoip/GeoIpHttpFixture.java
@@ -9,21 +9,27 @@
 package fixture.geoip;
 
 import com.sun.net.httpserver.HttpServer;
+import org.elasticsearch.cli.Terminal;
+import org.elasticsearch.geoip.GeoIpCli;
 
 import java.io.BufferedWriter;
 import java.io.ByteArrayOutputStream;
+import java.io.File;
 import java.io.InputStream;
 import java.io.OutputStream;
 import java.io.OutputStreamWriter;
 import java.net.InetAddress;
 import java.net.InetSocketAddress;
 import java.nio.charset.StandardCharsets;
+import java.nio.file.Files;
+import java.nio.file.Path;
 
 public class GeoIpHttpFixture {
 
     private final HttpServer server;
 
     GeoIpHttpFixture(final String[] args) throws Exception {
+        copyFiles();
         byte[] bytes = new byte[4096];
         int read;
         ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
@@ -57,6 +63,41 @@ public class GeoIpHttpFixture {
                 }
             }
         });
+        this.server.createContext("/cli", exchange -> {
+            String fileName = exchange.getRequestURI().getPath().replaceAll(".*/cli/", "");
+            Path target = new File("target").toPath().resolve(fileName);
+            if (Files.isRegularFile(target)) {
+                try (OutputStream outputStream = exchange.getResponseBody();
+                     InputStream db = Files.newInputStream(target)) {
+                    exchange.sendResponseHeaders(200, 0);
+                    int read3;
+                    while((read3 = db.read(bytes)) != -1) {
+                        outputStream.write(bytes, 0, read3);
+                    }
+                } catch (Exception e) {
+                    exchange.sendResponseHeaders(500, 0);
+                    exchange.getResponseBody().close();
+                }
+            } else {
+                exchange.sendResponseHeaders(404, 0);
+                exchange.getResponseBody().close();
+            }
+        });
+    }
+
+    private void copyFiles() throws Exception {
+        Path source = new File("source").toPath();
+        Files.createDirectory(source);
+
+        Path target = new File("target").toPath();
+        Files.createDirectory(target);
+
+        Files.copy(GeoIpHttpFixture.class.getResourceAsStream("/GeoLite2-ASN.tgz"), source.resolve("GeoLite2-ASN.tgz"));
+        Files.copy(GeoIpHttpFixture.class.getResourceAsStream("/GeoLite2-City.mmdb"), source.resolve("GeoLite2-City.mmdb"));
+        Files.copy(GeoIpHttpFixture.class.getResourceAsStream("/GeoLite2-Country.mmdb"), source.resolve("GeoLite2-Country.mmdb"));
+
+        new GeoIpCli().main(new String[]{"-s", source.toAbsolutePath().toString(), "-t", target.toAbsolutePath().toString()},
+            Terminal.DEFAULT);
     }
 
     final void start() throws Exception {
diff --git a/test/fixtures/geoip-fixture/src/main/resources/GeoLite2-City.mmdb b/test/fixtures/geoip-fixture/src/main/resources/GeoLite2-City.mmdb
new file mode 100644
index 0000000000000..0809201619b59
Binary files /dev/null and b/test/fixtures/geoip-fixture/src/main/resources/GeoLite2-City.mmdb differ
diff --git a/test/fixtures/geoip-fixture/src/main/resources/GeoLite2-Country.mmdb b/test/fixtures/geoip-fixture/src/main/resources/GeoLite2-Country.mmdb
new file mode 100644
index 0000000000000..aa81cbe8a2f0e
Binary files /dev/null and b/test/fixtures/geoip-fixture/src/main/resources/GeoLite2-Country.mmdb differ