Skip to content

Repository files navigation

zgrok

Tip my tokens

A self-hosted ngrok alternative built in Rust. Expose your local services to the internet through secure tunnels.

Quick Start

Installation

# Clone and build
git clone https://github.com/copyleftdev/zgrok.git
cd zgrok
cargo build --release

# Binaries are in target/release/
ls target/release/zgrok target/release/zgrok-edge

Expose a Local Service

# Start a tunnel to your local server on port 8080
./target/release/zgrok http 8080

# With a custom subdomain
./target/release/zgrok http 8080 --subdomain myapp

# With authentication
./target/release/zgrok http 8080 --authtoken zg_your_token_here

Run Your Own Edge Server

# Use a publicly trusted wildcard certificate, or create a private CA and
# sign a server certificate for both the base and wildcard domains.
openssl req -x509 -newkey rsa:4096 -nodes -days 3650 \
  -keyout ca-key.pem -out ca.pem -subj "/CN=zgrok private CA" \
  -addext "basicConstraints=critical,CA:TRUE" \
  -addext "keyUsage=critical,keyCertSign,cRLSign"
openssl req -newkey rsa:4096 -nodes -keyout key.pem -out server.csr \
  -subj "/CN=yourdomain.com" \
  -addext "subjectAltName=DNS:yourdomain.com,DNS:*.yourdomain.com"
openssl x509 -req -in server.csr -CA ca.pem -CAkey ca-key.pem \
  -CAcreateserial -days 365 -copy_extensions copy -out cert.pem

# Start the edge server
./target/release/zgrok-edge \
  --cert cert.pem \
  --key key.pem \
  --domain yourdomain.com \
  --https-port 443 \
  --http-port 80 \
  --agent-port 4443 \
  --auth-token zg_replace_with_a_secret

# Point the agent at the self-hosted edge
./target/release/zgrok config set edge_url wss://yourdomain.com:4443
./target/release/zgrok config set public_domain yourdomain.com
./target/release/zgrok config set authtoken zg_replace_with_a_secret
./target/release/zgrok config set ca_cert /path/to/ca.pem # private CA only

Architecture

┌─────────────┐     HTTPS      ┌─────────────┐    Multiplexed    ┌─────────────┐
│   Browser   │ ──────────────▶│    Edge     │◀───────────────── │    Agent    │
│             │  subdomain.    │   Server    │     Tunnel        │    (CLI)    │
└─────────────┘  domain.com    └─────────────┘                   └──────┬──────┘
                                                                        │ HTTP
                                                                        ▼
                                                                 ┌─────────────┐
                                                                 │    Your     │
                                                                 │   Service   │
                                                                 └─────────────┘
Component Crate Description
Agent zgrok-agent CLI client that runs on your machine
Edge zgrok-edge Public server that terminates TLS and routes traffic
Control zgrok-control Authentication, sessions, subdomain allocation
Protocol zgrok-protocol Binary framing, stream multiplexing, keepalive
Common zgrok-common Shared utilities, observability, validation

Agent CLI Reference

zgrok - Expose local services via secure tunnels

USAGE:
    zgrok [OPTIONS] <COMMAND>

COMMANDS:
    http      Start an HTTP tunnel
    config    Manage configuration

OPTIONS:
    -c, --config <PATH>    Path to config file
    -v, --verbose          Increase verbosity (-v, -vv, -vvv)
        --no-color         Disable colored output

HTTP Tunnel Options

zgrok http [OPTIONS] <PORT>

ARGUMENTS:
    <PORT>    Local port to expose

OPTIONS:
        --host <HOST>            Local host to forward to [default: localhost]
    -s, --subdomain <SUBDOMAIN>  Request specific subdomain
        --authtoken <TOKEN>      API key for authentication
        --region <REGION>        Edge region to connect to
        --inspect                Enable request inspection UI

Configuration File

Create ~/.config/zgrok/config.toml:

authtoken = "zg_your_token_here"
region = "us-east"
edge_url = "wss://tunnel.example.com:4443"
public_domain = "tunnel.example.com"
ca_cert = "/path/to/private-ca.pem" # only needed for private/self-signed CAs

[defaults]
inspect = true

[tunnels.webapp]
proto = "http"
addr = "8080"
subdomain = "myapp"

[tunnels.api]
proto = "http"
addr = "3000"
subdomain = "api"

Edge Server Reference

zgrok-edge - Edge/gateway server for zgrok tunneling service

OPTIONS:
        --https-port <PORT>      HTTPS listen port [default: 443]
        --http-port <PORT>       HTTP redirect port, 0 to disable [default: 80]
        --agent-port <PORT>      Agent tunnel port, 0 to disable [default: 4443]
        --auth-token <TOKEN>     Token required from connecting agents [env: ZGROK_AUTH_TOKEN]
        --listen <ADDR>          Listen address [default: 0.0.0.0]
        --cert <PATH>            TLS certificate (PEM)
        --key <PATH>             TLS private key (PEM)
        --domain <DOMAIN>        Base domain for subdomains [default: zgrok.io]
    -v, --verbose                Enable verbose logging

Environment Variables

Variable Description
ZGROK_AUTHTOKEN Default authentication token
ZGROK_AUTH_TOKEN Token accepted by the edge agent listener
ZGROK_CERT_PATH TLS certificate path
ZGROK_KEY_PATH TLS private key path

Deployment

Docker

FROM rust:1.75 as builder
WORKDIR /app
COPY . .
RUN cargo build --release

FROM debian:bookworm-slim
RUN apt-get update && apt-get install -y ca-certificates && rm -rf /var/lib/apt/lists/*
COPY --from=builder /app/target/release/zgrok-edge /usr/local/bin/
EXPOSE 443 80 4443
ENTRYPOINT ["zgrok-edge"]

Systemd Service

# /etc/systemd/system/zgrok-edge.service
[Unit]
Description=zgrok Edge Server
After=network.target

[Service]
Type=simple
User=zgrok
ExecStart=/usr/local/bin/zgrok-edge \
    --cert /etc/zgrok/cert.pem \
    --key /etc/zgrok/key.pem \
    --domain example.com \
    --agent-port 4443
Environment=ZGROK_AUTH_TOKEN=zg_replace_with_a_secret
Restart=always
RestartSec=5

[Install]
WantedBy=multi-user.target

Wildcard DNS

Configure your DNS with a wildcard A record:

*.tunnel.example.com  A  <your-edge-server-ip>

Then run the edge server with --domain tunnel.example.com.

Features

  • HTTP Tunneling: Streaming methods, query strings, headers, and binary bodies
  • WebSocket Relay: Bidirectional upgraded connections over tunnel streams
  • Resilient Tunnels: Concurrent streams, keepalive, and automatic reconnect
  • TLS Termination: HTTPS at the edge and TLS-protected agent connections
  • Subdomain Routing: Each tunnel gets a unique subdomain
  • Authenticated Agents: Required shared-token authentication
  • Self-Hosting: Public CA and private CA certificate support

Development

# Run all tests
cargo test

# Run with verbose output
cargo test -- --nocapture

# Lint
cargo clippy -- -D warnings

# Format
cargo fmt

# Build release
cargo build --release

Project Structure

crates/
├── zgrok-protocol/          # Wire protocol, frame codec, multiplexer
├── zgrok-agent/             # CLI client with TUI
├── zgrok-edge/              # Public-facing gateway server
├── zgrok-control/           # Auth, sessions, subdomain allocation
├── zgrok-common/            # Shared types, observability, validation
└── zgrok-integration-tests/ # Cross-crate integration tests

License

MIT

Contributing

See CONTRIBUTING.md for guidelines.

About

Self-hosted ngrok alternative in Rust. Development in progress - check out the issues for detailed specs.

Topics

Resources

Contributing

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages