# Newt: the user space WireGuard client that Pangolin is retiring

> Newt is a Go client that joins a private network to a Pangolin control plane over a websocket and carries traffic through a user space WireGuard stack, but the project itself now points users at the Pangolin CLI instead. It is a working connector with a short runway.

**fosrl/newt** — Tunneled network connector for Pangolin

- Repository: https://github.com/fosrl/newt
- Website: https://docs.pangolin.net
- Stars: 919 · Forks: 89
- Language: Go
- License: AGPL-3.0
- Published: 2026-10-20 · Updated: 2026-10-20 · Language: en
- Canonical page: https://hysenlabs.com/projects/fosrl-newt

## Newt never touches the kernel WireGuard module

Newt is described in its own documentation as a fully user space WireGuard tunnel client and TCP/UDP proxy, and that phrase is the whole design. The project does not load a kernel interface, does not write routing tables, and does not need a tunnel device to be present on the host. Everything happens inside the process through the Go netstack implementation, which the README points at through the wireguard-go netstack example.

That choice is what makes the client interesting to operators. A traditional WireGuard client needs a kernel module, elevated privileges for the interface, and routing changes that fight with whatever else the machine is doing. Newt sidesteps all of that, so it can run as an ordinary container or an unprivileged service account on a box that the organisation does not want to reconfigure.

The tradeoff is visible in the dependency list rather than the prose. The module pulls in golang.zx2c4.com/wireguard for the protocol work, but the traffic path itself is carried by gvisor.dev/gvisor, the userspace network stack. Running a full TCP/IP implementation in userspace costs CPU and memory that a kernel path would not, and it introduces a second stack alongside whatever the host is already running. The repository also carries a separate netstack2 directory, which suggests the stack is being worked on in parallel with the older one rather than being a single frozen path.

For a reader deciding whether to adopt this, the important question is whether you want a tunnel with no host level footprint. If yes, Newt answers it directly. If you want maximum throughput and would rather hand the packet path to the kernel, this is the wrong tool.

## Registration trades a Newt ID and secret for a websocket token

The connection sequence has three distinct parts, and only the first is obvious from the name. A site is identified by a Newt ID and a secret, both of which live in the environment when the client starts. The client makes HTTP requests to the Pangolin endpoint with those credentials to receive a session token, then opens a websocket and holds it. Control messages travel over that websocket for the life of the connection.

The token exchange is the reason the client needs the endpoint to be reachable before it can do anything useful. A container that starts before the network is up, or a site whose endpoint has moved, has no path to a working tunnel until that first HTTP exchange succeeds. The startup order in the container image reflects this, since the entrypoint script runs the binary and the environment is supplied by the compose file rather than by the image itself.

Once the websocket is up, the connection is not idle. It is the channel through which the server tells the client to raise a tunnel and through which proxy instructions arrive. A dropped websocket therefore means a dropped tunnel, and the client has to re-register and re-authenticate rather than resume a session in place. The documentation at docs.pangolin.net under managing sites is the place to look for how that recovery is expected to behave, because the README itself does not describe reconnection timing or backoff.

## The compose file shows the entire required configuration

There is no sprawling configuration file to learn here. The repository ships a compose file whose service definition is short enough to read in one pass, and the environment block contains every setting a fresh client needs:

```yaml
    environment:
      - PANGOLIN_ENDPOINT=https://app.pangolin.net
      - NEWT_ID=2ix2t8xk22ubpfy
      - NEWT_SECRET=nnisrfsdfc7prqsp9ewo1dvtvci50j5uiqotez00dgap0ii2
      - LOG_LEVEL=DEBUG
```

The endpoint points at the hosted Pangolin service, the ID and secret identify the site that the client belongs to, and the log level is the one knob you would realistically change. A matching example file in the repository reduces to the three required values, with placeholders rather than real ones:

```bash
PANGOLIN_ENDPOINT=https://app.pangolin.net
NEWT_ID=changeme-id
NEWT_SECRET=changeme-secret
```

For a self hosted deployment the endpoint is the address of your own Pangolin instance. The secret is the sensitive value, and the compose file as committed contains what look like working values, so a real deployment should always start from a local copy with the placeholders filled in rather than reusing the checked in ones.

## Building the binary, or running it as a container

The build section is short. A Go toolchain is the only prerequisite, and the documentation asks for Go 1.25, while the module file declares a newer language version, so check the go.mod line against your installed toolchain before a build fails on a version mismatch. The Makefile route is the plain one:

```bash
make
```

A Nix flake is provided for people who want a reproducible build, and it produces the binary under the standard result directory:

```bash
nix build
```

The documentation states that the resulting binary will be at ./result/bin/newt, and that a development shell is available with nix develop for working on the source rather than packaging it.

The container route is the one most deployments will take, and the Dockerfile is a two stage build that ends on a minimal Alpine image. The builder stage is pinned to a specific Go toolchain image, the binary is compiled with the version stamped into it, and the runtime stage adds only certificates, timezone data and a network utility package. Two details matter to whoever runs this in production. The image sets NEWT_SYSTEM_SUBSTRATE to CONTAINER, which tells the client it is running in a container, and it exposes port 2112 for the admin and metrics endpoint that Prometheus is expected to scrape.

```dockerfile
ENV NEWT_SYSTEM_SUBSTRATE="CONTAINER"
```

```dockerfile
EXPOSE 2112
```

The compose file also sets restart to unless-stopped, so a crashed client comes back on its own, and the repository contains a separate metrics collector compose file, which suggests that observability is a supported use case rather than an afterthought.

## Two kinds of traffic share one virtual interface

Newt handles two separate kinds of work that both end up on the same tunnel. The first is a peer tunnel. When the client receives WireGuard control messages carrying an endpoint and a public key, it brings up a tunnel to that peer using the userspace stack, then pings across the tunnel so that the peer on the Gerbil side is confirmed to be up. The ping is a practical detail worth noting, because it means the client verifies the far end before declaring success.

The second is local proxying. Using the same control information, the client creates low level TCP and UDP proxies bound to the virtual tunnel, and those proxies relay traffic to whatever targets have been programmed. The repository layout makes the division visible: a proxy directory, a bind directory, an exitnode directory, a holepunch directory and a browsergateway directory sit alongside the networking code, and a websocket directory holds the control channel.

So a Newt site is not a generic VPN peer in the traditional sense. It is a client that receives instructions and turns them into listeners and relays on the local machine. That model is what makes it useful for exposing a private resource that has no inbound connectivity of its own, and it is also why the client cannot be evaluated as a standalone WireGuard implementation.

## The README tells you to stop using Newt

The first thing the project documentation says, in a note at the top, is that Newt is being phased out in favour of the Pangolin CLI, with the instruction to run pangolin site up. Everything else in the repository is still there, the releases are still landing, and the client still works, but the maintainers are steering new deployments elsewhere.

That single note changes how the whole project should be evaluated. The three most recent releases are 1.17.0 on 2026-09-15, 1.18.0 on 2026-09-29 and 1.18.1 on 2026-10-02, and the last push to the repository was on 2026-10-14, so the code is not abandoned. What is being retired is the client role, not the code.

```bash
pangolin site up
```

The new CLI is expected to cover the same site lifecycle, including bringing a site online, and the fact that it lives in a separate repository means the tunnel client, the control plane and the site tool are being decoupled. Anyone adopting Newt today is adopting a path the project itself labels as temporary, and the documentation does not say when it will be removed or what the migration steps are beyond the one line above. A sensible reading is that a Newt based deployment still needs a plan to move to the CLI, and that plan has to be written before the client becomes a dead end rather than after.

## Licence, dependency weight, and the case against Newt

Newt is dual licensed under the AGPLv3 and the Fossorial Commercial licence, with commercial enquiries routed to the vendor. For an organisation that modifies the client and serves it over a network, the AGPL obligations are the part that needs a look, and that is a question for your own counsel rather than for this page. The practical point is that the licence is not a plain permissive one, and a commercial route exists for teams that want different terms.

The dependency list is long for a small client. Besides the wireguard and gvisor entries, the module includes an OpenTelemetry stack with OTLP gRPC exporters, a Prometheus client, a gRPC client, a Docker API client, gopkg.in/yaml.v3, golang.org/x/crypto, and a PKCS#12 package for certificate handling. Observability support is genuinely first class here, and there is an otel-collector example and a prometheus example in the examples directory. The cost is a large build surface and a release train that inherits upstream changes across many projects.

The clearest cases against Newt are these. It does nothing without a Pangolin server and Gerbil on the other side, so there is no standalone mode. It does not replace a general purpose VPN for connecting laptops to a corporate network. It adds a userspace TCP/IP stack alongside the host stack, which costs resources. And the project is phasing it out, which means every new install is on borrowed time. Against that, the uptime record is current and the mechanism it implements is a clean fit for exposing a private resource that cannot accept inbound connections.

## Conclusion

Newt is the right tool only if you already run a Pangolin deployment with Gerbil and need a client that needs no kernel WireGuard module and no root level network setup, since it brings the whole tunnel up in user space. Anyone starting a fresh site deployment should follow the Pangolin CLI route the project recommends instead, and anyone already running Newt should first confirm the version their Pangolin server expects, because the README does not state a minimum server version, a rollback procedure, or a deprecation timeline for the client.

## FAQ

### What is Newt used for in a Pangolin deployment?

Newt is the client side of a Pangolin site. It registers with the Pangolin endpoint using a Newt ID and secret, keeps a websocket open for control messages, and then brings up a user space WireGuard tunnel and local TCP and UDP proxies for the targets it is told to reach.

### Does Newt need root access or a kernel WireGuard module?

No. Newt runs the tunnel entirely in user space through the Go netstack, so it does not load a kernel module or create a tunnel device. It can therefore run as an ordinary container or an unprivileged service account.

### How do I install and configure Newt?

You can build it with make or nix build, which the documentation says places the binary at./result/bin/newt, or run the published container image with the PANGOLIN_ENDPOINT, NEWT_ID and NEWT_SECRET environment variables set. The repository ships a compose file with these three settings plus LOG_LEVEL, and a.env example showing the same three required values.

### Is Newt still being developed?

The code is current, with releases 1.17.0, 1.18.0 and 1.18.1 in September and October 2026 and the last push on 2026-10-14. However, the project states that Newt is being phased out in favour of the Pangolin CLI, so new deployments are expected to use pangolin site up instead.

### What licence applies to Newt?

The README states that Newt is dual licensed under the AGPLv3 and the Fossorial Commercial licence, and that commercial licensing inquiries should go to the vendor. The project is not offered under a permissive open source licence.

## Sources

- [fosrl/newt on GitHub](https://github.com/fosrl/newt)
- [License: AGPL-3.0](https://github.com/fosrl/newt/blob/main/LICENSE)
- [Project website](https://docs.pangolin.net)
- [README](https://github.com/fosrl/newt/blob/main/README.md)
- [Releases](https://github.com/fosrl/newt/releases)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/fosrl-newt
