Home

java-ngrok is a Java wrapper for ngrok that manages its own binary, making ngrok available via a convenient Java
API.
ngrok is a reverse proxy that opens secure tunnels from public URLs to localhost. It's perfect
for rapid
development (test webhooks, demo local websites, enable SSH access), establishing ingress to external
networks and devices, building production APIs (traffic policies, OAuth, load balancing), and more. And
it's made even more powerful with native Java integration through the java-ngrok client.
Installation
java-ngrok is available
on Maven Central.
If you want ngrok to be available from the command
line, pyngrok
can be installed using pip to manage that for you.
Open a Tunnel
To open a tunnel, use the NgrokClient's connect()
method, which returns a Tunnel,
and this returned object has a reference to the public URL generated by ngrok, which can be retrieved with
getPublicUrl().
final NgrokClient ngrokClient = new NgrokClient.Builder().build();
// Open a HTTP tunnel on the default port 80
// <Tunnel: "https://<public_sub>.ngrok.io" -> "http://localhost:80">
final Tunnel httpTunnel = ngrokClient.connect();
// Open a SSH tunnel
// <Tunnel: "tcp://0.tcp.ngrok.io:12345" -> "localhost:22">
final CreateTunnel sshCreateTunnel = new CreateTunnel.Builder()
.withProto(Proto.TCP)
.withAddr(22)
.build();
final Tunnel sshTunnel = ngrokClient.connect(sshCreateTunnel);
// Open a named tunnel from the config file
final CreateTunnel createNamedTunnel = new CreateTunnel.Builder()
.withName("my-config-file-tunnel")
.build();
final Tunnel namedTunnel = ngrokClient.connect(createNamedTunnel);
// Open an Internal Endpoint that's load balanced
// <Tunnel: "https://some-endpoint.internal" -> "http://localhost:9000">
final CreateTunnel createInternalEndpoint = new CreateTunnel.Builder()
.withAddr("9000")
.withDomain("some-endpoint.internal")
.withPoolingEnabled(true)
.build();
final Tunnel internalEndpoint = ngrokClient.connect(createInternalEndpoint);
The connect()
method can also take
a CreateTunnel
(which can be built through its Builder)
that allows you to pass additional properties that
are supported by ngrok (or withName()
to use a tunnel defined in ngrok's config
file), as documented here.
Note:
ngrokv2's default behavior forhttpwhen no additional properties are set is to open two tunnels, onehttpand onehttps.java-ngroks connect method will return a reference to thehttptunnel in this case. If only a single tunnel is needed, usewithBindTls(true)and a reference to thehttpstunnel will be returned.
Get Active Tunnels
It can be useful to ask the ngrok client what tunnels are currently open. This can be accomplished with the
getTunnels() method, which returns a list of Tunnel objects.
// [<Tunnel: "https://<public_sub>.ngrok.io" -> "http://localhost:80">]
final List<Tunnel> tunnels = ngrokClient.getTunnels();
Close a Tunnel
All open tunnels will automatically be closed when the Java process terminates, but we can also close them manually
with disconnect(String).
// The Tunnel returned from methods like connect(), getTunnels(), etc. contains the public URL
ngrokClient.disconnect(publicUrl);
Expose Other Services
Using ngrok you can expose any number of non-HTTP services, for instances databases, game servers, etc. This can be
accomplished by using java-ngrok to open a TCP tunnel to the desired service.
// Open a tunnel to MySQL with a Reserved TCP Address
// <NgrokTunnel: "tcp://1.tcp.ngrok.io:12345" -> "localhost:3306">
final CreateTunnel mysqlCreateTunnel = new CreateTunnel.Builder()
.withProto(Proto.TCP)
.withAddr(3306)
.withRemoteAddr("1.tcp.ngrok.io:12345")
.build();
final Tunnel mysqlTunnel = ngrokClient.connect(mysqlCreateTunnel);
You can also serve up local directories via ngrok's built-in fileserver.
// Open a tunnel to a local file server
// <NgrokTunnel: "https://<public_sub>.ngrok.io" -> "file:///">
final CreateTunnel fileserverCreateTunnel = new CreateTunnel.Builder()
.withAddr("file:///")
.build();
final Tunnel fileserverTunnel = ngrokClient.connect(fileserverCreateTunnel);
Tunnel Configuration
It is possible to configure the tunnel when it is created, for instance adding authentication, a subdomain, or other
additional tunnel configurations that are supported by ngrok.
This is accomplished by using CreateTunnel.Builder
to set what properties will be used when the tunnel is created. Here is an example that opens a tunnel with subdomain
foo, requires basic authentication for requests, and defines a circuit breaker.
final CreateTunnel createTunnel = new CreateTunnel.Builder()
.withSubdomain("foo")
.withAuth("username:password")
.withCircuitBreaker(50)
.build();
final Tunnel tunnel = ngrokClient.connect(createTunnel);
If you already have a tunnel defined in ngrok's config file, you can start it by its name (note that "-api"
will be appended to its name when started).
final CreateTunnel createTunnel = new CreateTunnel.Builder()
.withName("my-config-file-tunnel")
.build();
final Tunnel tunnel = ngrokClient.connect(createTunnel);
ngrok's API
The api() method allows you to use the local
ngrok agent to make requests against the ngrok API, if you
have set an API key.
For example, here's how you would reserve a ngrok domain, then create a Cloud Endpoint with an associated traffic
policy:
final String domain = "some-domain.ngrok.dev";
final ApiResponse domainResponse = ngrokClient.api(
List.of("reserved-domains", "create",
"--domain", domain));
final ApiResponse endpointResponse = ngrokClient.api(
List.of("endpoints", "create",
"--bindings", "public",
"--url", String.format("https://%s", domain),
"--traffic-policy-file", "policy.yml"));
Event Logs
When ngrok emits logs, java-ngrok can surface them to a callback function. To register this callback, use JavaNgrokConfig.Builder.withLogEventCallback(Function<NgrokLog, Void>), as show here:
final Function<NgrokLog, Void> logEventCallback = ngrokLog -> {
System.out.println(ngrokLog.getLine());
return null;
};
final JavaNgrokConfig javaNgrokConfig = new JavaNgrokConfig.Builder()
.withLogEventCallback(logEventCallback)
.build();
final NgrokClient ngrokClient = new NgrokClient.Builder()
.withJavaNgrokConfig(javaNgrokConfig)
.build();
If these events aren't necessary for your use case, some resources can be freed up by turning them off. JavaNgrokConfig.Builder.withoutMonitoring()
will disable logging, or you can call NgrokProcess.ProcessMonitor.stop()
to stop monitoring on a running process.
Configuration
JavaNgrokConfig
java-ngroks interactions with the ngrok binary can be configured using JavaNgrokConfig,
which can then be passed to NgrokClient.
final JavaNgrokConfig javaNgrokConfig = new JavaNgrokConfig.Builder()
.withRegion(Region.AU)
.withMaxLogs(10);
final NgrokClient ngrokClient = new NgrokClient.Builder()
.withJavaNgrokConfig(javaNgrokConfig)
.build();
Note: If
ngrokis not already installed atJavaNgrokConfig.getNgrokPath, it will be installed the first time most methods inNgrokClientare called.If you need to customize the installation of
ngrok, perhaps specifying a timeout, proxy, use a custom mirror for the download, etc., you can do so by leveraging theNgrokInstaller.
Setting the authtoken or api_key
Running ngrok with an auth token and API key enables access to more features available on your account (for instance,
multiple concurrent tunnels, custom domains, use of Internal Endpoints,
etc). You can obtain your auth token and generate API keys from the ngrok dashboard,
then install it to ngrok’s config file.
final JavaNgrokConfig javaNgrokConfig = new JavaNgrokConfig.Builder()
.withAuthToken("<NGROK_AUTHTOKEN>")
.withApiKey("<NGROK_API_KEY>")
.build();
final NgrokClient ngrokClient = new NgrokClient.Builder()
.withJavaNgrokConfig(javaNgrokConfig)
.build();
You could instead define NGROK_AUTHTOKEN or NGROK_API_KEY as environment variables, if you don’t want to define
them in code.
Config File
By default, ngrok will look for its config file in the default location.
You can override this behavior with JavaNgrokConfig.Builder.withConfigPath(Path).
final JavaNgrokConfig javaNgrokConfig = new JavaNgrokConfig.Builder()
.withConfigPath(Path.of("opt", "ngrok", "config.yml"))
.build();
final NgrokClient ngrokClient = new NgrokClient.Builder()
.withJavaNgrokConfig(javaNgrokConfig)
.build();
Binary Path
The java-ngrok package manages its own ngrok binary. You can use your ngrok binary if you want by setting it with JavaNgrokConfig.Builder.withNgrokPath(Path)
and passing that config to NgrokClient.
final JavaNgrokConfig javaNgrokConfig = new JavaNgrokConfig.Builder()
.withNgrokPath(Path.of("usr", "local", "bin", "ngrok"))
.build();
final NgrokClient ngrokClient = new NgrokClient.Builder()
.withJavaNgrokConfig(javaNgrokConfig)
.build();
ngrok Version Compatibility
java-ngrok is compatible with ngrok v2 and v3, but by default it will install v3. To install v2 instead, set the
version with JavaNgrokConfig.Builder.withNgrokVersion(NgrokVersion)
and CreateTunnel.Builder.withNgrokVersion(NgrokVersion).
final JavaNgrokConfig javaNgrokConfig = new JavaNgrokConfig.Builder()
.withNgrokVersion(NgrokVersion.V2)
.build();
final NgrokClient ngrokClient = new NgrokClient.Builder()
.withJavaNgrokConfig(javaNgrokConfig)
.build();
// Open a V2 tunnel
// <Tunnel: "http://<public_sub>.ngrok.io" -> "http://localhost:80">
final CreateTunnel v2Tunnel = new CreateTunnel.Builder()
.withNgrokVersion(NgrokVersion.V2)
.build();
final Tunnel sshTunnel = ngrokClient.connect(v2Tunnel);
Command Line Usage
Assuming you have also installed pyngrok, all features of
ngrok are available
on the command line.
ngrok http 80
For details on how to fully leverage ngrok from the command line,
see ngrok's official documentation.
Java 8
A Java 8-compatible build was previously maintained in the 1.4.x
branch. While it is no longer supported, it is available through the java8-ngrok artifact instead on Maven Central.
For more details on what differs in the java8-ngrok dependency,
see the "Java 8" section of the docs.