Self-hosted service
Gouryella/drip avatar
Gouryella/drip

Drip: a self hosted tunnel that keeps traffic on your own server

Self-hosted tunneling solution to expose localhost securely - unlimited bandwidth, no third-party servers

920 stars61 forksGoBSD-3-Clause

At a glance

What is it?
Drip is a Go tunnel server and client that exposes a local service through a domain you control, with no third party relay in the path. It adds per tunnel bandwidth limiting with a token bucket, bearer token authentication, TLS 1.3 and a websocket transport, and it ships as a single cross platform binary.
Who is it for?
Adopt Drip if you want to expose a local service to the internet through a server and domain you already control, because the traffic path stays between your client and your server and there is no third party relay or paid tier.
Can I use it commercially?
Yes. BSD-3-Clause is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository received new commits within the last day.
What is it written in?
Mainly Go, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on October 23, 2026, and from our analysis. They are not legal advice.

Editorial analysis

The traffic path has no third party in it

Drip is described as a self hosted tunneling solution to expose localhost securely, with the tagline that the tunnel, the domain and the location are all yours. The stated advantages are control of your data with no third party servers so that traffic stays between your client and server, no limits on tunnels, bandwidth or requests, and no paid tiers or feature restrictions.

That last point is the design decision everything else follows from. Most tunnel services work by relaying your traffic through a hosted server that someone else runs. Drip expects you to run the server half yourself, and the documentation has a Server Deployment section under direct mode, so the server is a component you install and configure rather than a service you sign up for.

The result is that bandwidth and request limits are a property of your own server's capacity, and the domain in the URL is one you control. The trade is that you now operate a public-facing server, terminate TLS there, and keep DNS pointing at it.

The project also describes itself with restraint, calling itself a quiet, disciplined tunnel where you light a small lamp on your network and it carries that light outward through your own infrastructure. That framing is unusual in project descriptions and it tells you what kind of tool this is meant to be: a component in an infrastructure you own, not a service you depend on.

Client and server, one binary, a handful of commands

Installation is a shell script fetched over the network, which is the usual convenience trade and worth thinking about before you run it on a build machine.

bash
bash <(curl -sL https://driptunnel.app/install.sh)

The client workflow is short. You configure once, then open a tunnel.

bash
# Configure (first time only)
drip config init

# Expose local HTTP server
drip http 3000

# With custom subdomain
drip http 3000 -n myapp

The custom subdomain flag is the piece you will use most, and the README shows the resulting URL as https://myapp.your-domain.com, which is where the independent configuration of service domain and tunnel domain comes in. That separation was added alongside bandwidth limiting, and it is what lets one server host many services under one domain.

The build produces a single binary. The Makefile builds it with go build into bin/drip, stamping the version, the short git commit and the build time into the binary through linker flags, and a build-all target produces separate binaries for Linux, macOS and Windows on both amd64 and arm64.

bash
	GOOS=linux GOARCH=arm64 go build ${LDFLAGS} -o bin/drip-linux-arm64 ./cmd/drip

The command line is built with cobra, and the documentation lists a Command Reference page alongside the installation, basic tunnels and server deployment guides.

Bandwidth limiting with a token bucket on both ends

The feature that makes Drip more than a tunnel wrapper is per tunnel bandwidth control, described as QoS using a token bucket algorithm. The important detail is the rule for combining the two limits: the server enforces min(client, server) as the effective limit.

That design lets you put a ceiling on the client side, which protects your own network from being saturated by a runaway upload, while the server side sets the global ceiling for all tunnels together. The effective rate is the lower of the two, so a client cannot exceed what the server is willing to give, and a generous server can still be protected per tunnel by a conservative client.

On the client you set it as a flag on the tunnel command.

bash
# Client: limit to 1MB/s
drip http 3000 --bandwidth 1M

On the server it is a global setting in the config file.

yaml
# Server: global limit (config.yaml)
bandwidth: 10M
burst_multiplier: 2.5

The burst multiplier is the token bucket parameter that sets how much surplus traffic can accumulate beyond the steady rate, which is what stops a short burst from being throttled to a crawl. A rate limit without a burst allowance behaves badly for genuinely bursty workloads such as serving a page with many assets.

This is the one area where Drip is doing real work rather than delegating, and it is the area most likely to matter if you expose something that a third party can hammer.

Bearer tokens, TLS 1.3 and the websocket transport

Access control for tunnels arrived as bearer token authentication, added alongside a refactor of the larger modules into smaller focused components. A bearer token is a shared secret that the client presents and the server checks, so it lets you close a tunnel to people who do not have the token, but it does not give you per user identity or per user revocation beyond rotating the secret.

The transport details are visible in the module dependencies. gorilla/websocket appears in the require list, and the topic list names websocket, http, http2, https, tcp and tls. TLS 1.3 is called out in the project badges. The multiplexing layer is hashicorp/yamux, which is what lets many streams share one connection, and that is why websocket and TCP appear as alternatives rather than one being the only path.

The crypto and networking libraries are the standard ones: golang.org/x/crypto, golang.org/x/net, golang.org/x/sys and golang.org/x/time. The CLI presentation uses charmbracelet/lipgloss and the logging uses go.uber.org/zap, which tells you the tool has a deliberately styled terminal output rather than ad hoc prints.

A repository-level SECURITY.md file is present, and the project publishes security-related metadata for it, which is worth reading before you point a public domain at it.

Prometheus metrics, the e2e suite and the Go version mismatch

Operational tooling is part of the deliverable. The prometheus/client_golang dependency means the server exposes metrics, and the Makefile has a target that runs the tests with a coverage profile and generates an HTML report.

There is also a full end to end functional test target that starts a local server, client and backends, driven by a shell script.

bash
e2e: build
	bash scripts/test/e2e-full.sh

The unit test target runs with the race detector and coverage enabled, which is the right choice for a project that multiplexes concurrent streams.

bash
test:
	go test -v -race -cover ./...

One inconsistency is worth flagging. The project badge advertises Go 1.21 or newer, but the go.mod file declares go 1.26.5, which is a much newer directive than the badge suggests. If you build from source, the module file is what the toolchain will enforce. The same file shows the module path is simply drip, not a URL-shaped path, which is unusual for a repository with a homepage and suggests the binary is built and released by goreleaser rather than consumed as a library, with the .goreleaser.yaml file at the repository root.

The repository also has a README_CN.md, so the project is maintained with Chinese documentation alongside the English one, and the documentation site links both.

Where Drip is the wrong tool

Three cases point elsewhere.

If you want a tunnel with no infrastructure of your own, Drip is the opposite of what you need. It assumes you have a public server and a domain, and running that is your job. A hosted quick tunnel service does that part for you, at the cost of the traffic passing through someone else's machine, which is the trade Drip exists to reverse.

If you need real access control with identity, the bearer token model is thin. There is one secret per tunnel or per deployment, and anyone holding it is equivalent to the owner. Product teams with multiple collaborators and per person revocation need something else, and would have to build the authorisation layer on top of Drip rather than in it.

If you need to expose something that is not an HTTP service, check first what the client supports. The documented quick start covers drip http for a local HTTP server, and the topic list includes raw TCP and websocket, but the commands documented in the README are limited, and the full command reference lives on the documentation site rather than in the repository.

There is also the operational reality of running a public server. TLS termination, DNS, firewall rules, patching and log management all become your responsibility, and the project does not provide a managed control plane, a dashboard, or a hosted fallback if your server goes down.

Editorial conclusion

Adopt Drip if you want to expose a local service to the internet through a server and domain you already control, because the traffic path stays between your client and your server and there is no third party relay or paid tier. Do not adopt it if you need a hosted quick tunnel with no infrastructure, since that is exactly the model it avoids, or if you need per user access control, since bearer token authentication is a single shared credential rather than an identity system. Verify first that you have a public server and a DNS zone you can point at it, that the Go toolchain satisfies the go 1.26.5 directive in the module file, and that you read the SECURITY.md file and the deployment guides before exposing anything.

Frequently asked questions

How do I install and start a Drip tunnel?

Run the install script with bash <(curl -sL https://driptunnel.app/install.sh), then run drip config init once, and open a tunnel with drip http 3000. Adding -n myapp gives a custom subdomain such as https://myapp.your-domain.com.

How does Drip limit bandwidth?

Per tunnel bandwidth control uses a token bucket algorithm, with the server enforcing min(client, server) as the effective limit. The client sets it with a flag such as drip http 3000 --bandwidth 1M, and the server sets a global bandwidth and burst_multiplier in config.yaml.

Does Drip need a third party server to relay my traffic?

No. The stated advantage is that there are no third party servers and traffic stays between your client and server. That means you run the server half yourself, with your own domain and public infrastructure.

What Go version is required to build Drip from source?

The project badge advertises Go 1.21 or newer, but the go.mod file declares go 1.26.5, and the module file is what the toolchain enforces when you build. The Makefile builds a single binary into bin/drip and a build-all target for Linux, macOS and Windows on amd64 and arm64.

Official sources

  1. Gouryella/drip on GitHub
  2. License: BSD-3-Clause
  3. Project website
  4. README
  5. Releases
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/gouryella-drip.svg)](https://hysenlabs.com/projects/gouryella-drip)

Was this useful?