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:
ngrok
v2's default behavior forhttp
when no additional properties are set is to open two tunnels, onehttp
and onehttps
.java-ngrok
s connect method will return a reference to thehttp
tunnel in this case. If only a single tunnel is needed, usewithBindTls(true)
and a reference to thehttps
tunnel 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.
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-ngrok
s 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
ngrok
is not already installed atJavaNgrokConfig.getNgrokPath
, it will be installed the first time most methods inNgrokClient
are 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.