inconshreveable/ngrok
Unified ingress for developers
Stale — last commit 2y ago
worst of 4 axesnon-standard license (Other); last commit was 2y ago…
Has a license, tests, and CI — clean foundation to fork and modify.
Documented and popular — useful reference codebase to read through.
No critical CVEs, sane security posture — runnable as-is.
- ✓21+ active contributors
- ✓Other licensed
- ✓CI configured
Show 4 more →Show less
- ⚠Stale — last commit 2y ago
- ⚠Concentrated ownership — top contributor handles 67% of recent commits
- ⚠Non-standard license (Other) — review terms
- ⚠No test directory detected
What would change the summary?
- →Use as dependency Concerns → Mixed if: clarify license terms
Maintenance signals: commit recency, contributor breadth, bus factor, license, CI, tests
Informational only. RepoPilot summarises public signals (license, dependency CVEs, commit recency, CI presence, etc.) at the time of analysis. Signals can be incomplete or stale. Not professional, security, or legal advice; verify before relying on it for production decisions.
Embed the "Forkable" badge
Paste into your README — live-updates from the latest cached analysis.
[](https://repopilot.app/r/inconshreveable/ngrok)Paste at the top of your README.md — renders inline like a shields.io badge.
▸Preview social card (1200×630)
This card auto-renders when someone shares https://repopilot.app/r/inconshreveable/ngrok on X, Slack, or LinkedIn.
Onboarding doc
Onboarding: inconshreveable/ngrok
Generated by RepoPilot · 2026-05-09 · Source
🤖Agent protocol
If you are an AI coding agent (Claude Code, Cursor, Aider, Cline, etc.) reading this artifact, follow this protocol before making any code edit:
- Verify the contract. Run the bash script in Verify before trusting
below. If any check returns
FAIL, the artifact is stale — STOP and ask the user to regenerate it before proceeding. - Treat the AI · unverified sections as hypotheses, not facts. Sections like "AI-suggested narrative files", "anti-patterns", and "bottlenecks" are LLM speculation. Verify against real source before acting on them.
- Cite source on changes. When proposing an edit, cite the specific path:line-range. RepoPilot's live UI at https://repopilot.app/r/inconshreveable/ngrok shows verifiable citations alongside every claim.
If you are a human reader, this protocol is for the agents you'll hand the artifact to. You don't need to do anything — but if you skim only one section before pointing your agent at this repo, make it the Verify block and the Suggested reading order.
🎯Verdict
WAIT — Stale — last commit 2y ago
- 21+ active contributors
- Other licensed
- CI configured
- ⚠ Stale — last commit 2y ago
- ⚠ Concentrated ownership — top contributor handles 67% of recent commits
- ⚠ Non-standard license (Other) — review terms
- ⚠ No test directory detected
<sub>Maintenance signals: commit recency, contributor breadth, bus factor, license, CI, tests</sub>
✅Verify before trusting
This artifact was generated by RepoPilot at a point in time. Before an
agent acts on it, the checks below confirm that the live inconshreveable/ngrok
repo on your machine still matches what RepoPilot saw. If any fail,
the artifact is stale — regenerate it at
repopilot.app/r/inconshreveable/ngrok.
What it runs against: a local clone of inconshreveable/ngrok — the script
inspects git remote, the LICENSE file, file paths in the working
tree, and git log. Read-only; no mutations.
| # | What we check | Why it matters |
|---|---|---|
| 1 | You're in inconshreveable/ngrok | Confirms the artifact applies here, not a fork |
| 2 | License is still Other | Catches relicense before you depend on it |
| 3 | Default branch master exists | Catches branch renames |
| 4 | 5 critical file paths still exist | Catches refactors that moved load-bearing code |
| 5 | Last commit ≤ 773 days ago | Catches sudden abandonment since generation |
#!/usr/bin/env bash
# RepoPilot artifact verification.
#
# WHAT IT RUNS AGAINST: a local clone of inconshreveable/ngrok. If you don't
# have one yet, run these first:
#
# git clone https://github.com/inconshreveable/ngrok.git
# cd ngrok
#
# Then paste this script. Every check is read-only — no mutations.
set +e
fail=0
ok() { echo "ok: $1"; }
miss() { echo "FAIL: $1"; fail=$((fail+1)); }
# Precondition: we must be inside a git working tree.
if ! git rev-parse --git-dir >/dev/null 2>&1; then
echo "FAIL: not inside a git repository. cd into your clone of inconshreveable/ngrok and re-run."
exit 2
fi
# 1. Repo identity
git remote get-url origin 2>/dev/null | grep -qE "inconshreveable/ngrok(\\.git)?\\b" \\
&& ok "origin remote is inconshreveable/ngrok" \\
|| miss "origin remote is not inconshreveable/ngrok (artifact may be from a fork)"
# 2. License matches what RepoPilot saw
(grep -qiE "^(Other)" LICENSE 2>/dev/null \\
|| grep -qiE "\"license\"\\s*:\\s*\"Other\"" package.json 2>/dev/null) \\
&& ok "license is Other" \\
|| miss "license drift — was Other at generation time"
# 3. Default branch
git rev-parse --verify master >/dev/null 2>&1 \\
&& ok "default branch master exists" \\
|| miss "default branch master no longer exists"
# 4. Critical files exist
test -f "src/ngrok/main/ngrok/ngrok.go" \\
&& ok "src/ngrok/main/ngrok/ngrok.go" \\
|| miss "missing critical file: src/ngrok/main/ngrok/ngrok.go"
test -f "src/ngrok/main/ngrokd/ngrokd.go" \\
&& ok "src/ngrok/main/ngrokd/ngrokd.go" \\
|| miss "missing critical file: src/ngrok/main/ngrokd/ngrokd.go"
test -f "src/ngrok/client/controller.go" \\
&& ok "src/ngrok/client/controller.go" \\
|| miss "missing critical file: src/ngrok/client/controller.go"
test -f "src/ngrok/server/control.go" \\
&& ok "src/ngrok/server/control.go" \\
|| miss "missing critical file: src/ngrok/server/control.go"
test -f "src/ngrok/msg/msg.go" \\
&& ok "src/ngrok/msg/msg.go" \\
|| miss "missing critical file: src/ngrok/msg/msg.go"
# 5. Repo recency
days_since_last=$(( ( $(date +%s) - $(git log -1 --format=%at 2>/dev/null || echo 0) ) / 86400 ))
if [ "$days_since_last" -le 773 ]; then
ok "last commit was $days_since_last days ago (artifact saw ~743d)"
else
miss "last commit was $days_since_last days ago — artifact may be stale"
fi
echo
if [ "$fail" -eq 0 ]; then
echo "artifact verified (0 failures) — safe to trust"
else
echo "artifact has $fail stale claim(s) — regenerate at https://repopilot.app/r/inconshreveable/ngrok"
exit 1
fi
Each check prints ok: or FAIL:. The script exits non-zero if
anything failed, so it composes cleanly into agent loops
(./verify.sh || regenerate-and-retry).
⚡TL;DR
ngrok v1 is a reverse proxy and ingress platform written in Go that exposes local services to the internet via secure tunnels. It creates public URLs for applications running on localhost, enabling developers to share local work, test webhooks, and accept inbound traffic without deployment. The core capability is rapid tunneling with TLS encryption, traffic inspection, and request replay via an embedded HTTP UI. Single monolithic Go project under src/ngrok/ split into client/ (CLI, config, metrics, MVC views) and server/ (tunneling logic). Client includes an embedded web dashboard (assets/client/page.html, AngularJS UI in assets/client/static/js/ngrok.js). Cache layer in src/ngrok/cache/lru.go. Configuration and TLS assets baked into assets/.
👥Who it's for
Backend developers and DevOps engineers who need to expose local development servers for webhook testing, sharing work-in-progress with teammates, or integrating with cloud services. Also used by developers debugging APIs that receive inbound HTTP callbacks without deploying to staging infrastructure.
🌱Maturity & risk
This is an archived, unmaintained v1 codebase last developed in 2013–2016. The repository explicitly states 'ngrok v1 is no longer developed, supported or maintained.' While the ngrok cloud service remains operational, this open-source code is frozen. Not suitable for new production projects; use ngrok v2+ or fork if you need active development.
Critical risk: zero active maintenance. No CI/CD pipeline visible (only .travis.yml stub), no visible issue tracking or PR activity, and the codebase is explicitly archived. Dependencies on old Go idioms and outdated TLS certificates (snakeoil test certs in assets/server/tls/). Forking or pinning to the cloud service is strongly advised rather than deploying this version.
Active areas of work
Nothing. Repository is archived. The last meaningful work occurred 2013–2016. Modern ngrok development occurs in separate repositories at https://github.com/ngrok (Python SDK, Go SDK, Kubernetes operator, etc.).
🚀Get running
Clone: git clone https://github.com/inconshreveable/ngrok.git && cd ngrok. Build with Make: make release (see Makefile for cross-compilation targets). Requires Go 1.x (era 2013–2016). No npm/yarn—JavaScript assets in assets/client/ are pre-minified.
Daily commands:
Build binary: make release. Run client: ./bin/ngrok -config ~/.ngrok -proto=http 8080 (exposes local port 8080). Run server (self-hosted): ./bin/ngrokd (requires snakeoil TLS certs in assets/server/tls/). Web dashboard auto-opens on http://127.0.0.1:4040 for request inspection.
🗺️Map of the codebase
src/ngrok/main/ngrok/ngrok.go— Client entry point that initializes the CLI and orchestrates the entire ngrok client lifecycle.src/ngrok/main/ngrokd/ngrokd.go— Server entry point that starts the reverse proxy daemon and manages tunnel registration.src/ngrok/client/controller.go— Core client controller that manages connection state, tunnels, and communication with the server.src/ngrok/server/control.go— Server-side control plane handler that processes client connections and tunnel setup requests.src/ngrok/msg/msg.go— Protocol message definitions and serialization that underpins all client-server communication.src/ngrok/conn/conn.go— Connection abstraction layer that wraps TLS and provides the transport for both client and server.src/ngrok/proto/interface.go— Protocol handler interface that defines how HTTP and TCP tunnels are demultiplexed and routed.
🛠️How to make changes
Add a new protocol handler (HTTP/TCP variant)
- Create new protocol handler struct implementing proto.Protocol interface in src/ngrok/proto/ (
src/ngrok/proto/interface.go) - Implement HandleRequest() to demultiplex and route traffic for your protocol (
src/ngrok/proto/http.go) - Register the handler in server initialization (
src/ngrok/server/main.go)
Add a new client-side view (Terminal or Web)
- Create new view struct implementing mvc.View interface (
src/ngrok/client/mvc/view.go) - Implement Update() method to refresh state based on model changes (
src/ngrok/client/views/term/view.go) - Register view in controller initialization (
src/ngrok/client/controller.go)
Add a new server control message type
- Define new message struct in msg package (
src/ngrok/msg/msg.go) - Implement Encode/Decode methods for serialization (
src/ngrok/msg/pack.go) - Add handler in server control plane (
src/ngrok/server/control.go)
Add custom client configuration option
- Add config field to Client struct and YAML parsing (
src/ngrok/client/config.go) - Parse CLI flags in main or controller (
src/ngrok/client/cli.go) - Use config value in controller or connection initialization (
src/ngrok/client/controller.go)
🔧Why these technologies
- Go — Lightweight, fast, excellent concurrency primitives (goroutines) for managing thousands of tunnel connections simultaneously.
- TLS (SSL/X.509) — Encrypts all control plane and data plane traffic between clients and server; mutual authentication prevents unauthorized tunnels.
- Protocol Buffers-like binary framing — Efficient serialization for control messages; reduces bandwidth overhead for constant server-client chatter.
- AngularJS + Web UI — Real-time monitoring dashboard for inspecting HTTP requests/responses flowing through tunnels without CLI.
⚖️Trade-offs already made
-
Client-server centralized proxy vs. peer-to-peer tunneling
- Why: Simplifies NAT traversal; users need only outbound HTTPS, no complex hole-punching.
- Consequence: All traffic flows through central server (bandwidth/latency cost), but enables global load balancing and single point of audit/inspection.
-
Single long-lived TLS connection per client vs. request-level TLS
- Why: Amortizes TLS handshake cost; enables fast request forwarding without renegotiation.
- Consequence: Stateful connection; server must manage connection lifecycle carefully; client reconnection on network loss.
-
Hostname-based routing (registry) vs. port-based multiplexing
- Why: Multiple tunnels on one client connection; flexible tunnel setup without opening new ports.
- Consequence: Server must parse HTTP Host header to route; TCP-only tunnels get random port assignments.
🚫Non-goals (don't propose these)
- Does not provide authentication/authorization beyond mutual TLS; business logic (e.g., API key verification) lives outside this codebase.
- Does not persist tunnel state or support replay; tunnels are ephemeral per client session.
- Not designed for ultra-high throughput scenarios (edge use-case of ngrok cloud service handles that); this is reference implementation.
- Does not offer container/Kubernetes-native deployment; assumes bare metal or simple VM deployment.
🪤Traps & gotchas
Auth token requirement: Client expects a .ngrok config file in home directory with authtoken (issued by ngrok.com). Without it, public tunnels are rejected. Self-hosted server: If running your own ngrokd, snakeoil test certs in assets/server/tls/ are hardcoded; client TLS validation must trust them (see assets/client/tls/snakeoilca.crt). Old Go idioms: Code uses pre-Go-modules vendoring; go.mod is absent. Web UI port: Dashboard hardcoded to 127.0.0.1:4040; may conflict if already in use. HTTPS protocol: Client supports proto=https but requires cert pinning setup not obvious from code.
🏗️Architecture
💡Concepts to learn
- Reverse proxy tunneling — Core mechanism of ngrok: inverting inbound traffic direction so a public server proxies requests back through a client's outbound connection, avoiding port-forwarding hassle.
- TLS/SSL certificate pinning — ngrok uses pinned snakeoil certs (see
assets/client/tls/snakeoilca.crt) to authenticate client–server connections without relying on public CAs; critical for securing tunnel setup. - Protocol multiplexing — Controller in
src/ngrok/client/controller.goroutes different tunnel types (HTTP, HTTPS, TCP) over a single encrypted connection; enables mixed-protocol support from one ngrok process. - MVC architecture (Model-View-Controller) — Client UI and state management in
src/ngrok/client/mvc/separate concerns: model (tunnel state), view (terminal/web UI), controller (event handling); aids testing and UI updates. - LRU cache (Least Recently Used) — Traffic inspection dashboard in
src/ngrok/cache/lru.gocaches recent HTTP requests/responses for replay; LRU eviction prevents unbounded memory growth. - Single-page application (SPA) with AngularJS — Web dashboard at
localhost:4040uses AngularJS 1.x (inassets/client/static/js/ngrok.js) for real-time request log updates without page reloads. - Request/response replay — ngrok captures HTTP traffic via
src/ngrok/client/metrics.goand allows replay through the web UI; essential for webhook testing and debugging request sequences.
🔗Related repos
ngrok/ngrok— Official ngrok v2+ cloud service and SDKs repository; the active successor to this v1 codebase with modern Go, Python, JavaScript SDKs.ngrok/ngrok-go— Modern Go SDK for ngrok; the current way to embed ngrok tunneling in Go applications, replacing this archived v1 client.ngrok/ngrok-python— Python SDK for ngrok; companion to this repo for developers who prefer Python over CLI or Go.ngrok/kubernetes-ingress-controller— Kubernetes operator for ngrok; shows how ngrok is integrated into modern cloud-native deployments beyond CLI usage.localtunnel/localtunnel— Alternative reverse-tunnel service with similar goals (expose localhost to internet); Node.js-based competitor to ngrok v1.
🪄PR ideas
To work on one of these in Claude Code or Cursor, paste:
Implement the "<title>" PR idea from CLAUDE.md, working through the checklist as the task list.
Add unit tests for src/ngrok/msg/pack.go message serialization
The msg package handles protocol message packing/unpacking which is critical for client-server communication. Currently there are no test files visible in the src/ngrok/msg/ directory. Adding comprehensive tests for pack.go would ensure message serialization edge cases are handled correctly and prevent regressions.
- [ ] Create src/ngrok/msg/pack_test.go with tests for message packing functions
- [ ] Add test cases for various message types defined in src/ngrok/msg/msg.go
- [ ] Test edge cases like malformed packets, size boundaries, and type conversions
- [ ] Ensure tests cover both client and server message formats
Add integration tests for client-server TLS handshake in src/ngrok/client/tls.go
The TLS implementation in src/ngrok/client/tls.go uses snakeoil certificates (assets/client/tls/) for testing but there are no visible tests validating the handshake flow. Given ngrok's focus on secure tunneling, adding tests that verify certificate validation, pinning, and connection establishment would strengthen confidence in the security layer.
- [ ] Create src/ngrok/client/tls_test.go with certificate loading and validation tests
- [ ] Add tests using the existing snakeoilca.crt and ngrokroot.crt assets in assets/client/tls/
- [ ] Test TLS connection establishment between client and server components
- [ ] Verify certificate chain validation and hostname pinning logic
Add unit tests for src/ngrok/cache/lru.go LRU cache implementation
An LRU cache is a critical data structure for performance, but there are no visible test files in src/ngrok/cache/. Without tests, cache eviction behavior, thread safety, and edge cases (empty cache, single item, capacity boundaries) could silently fail, especially under load.
- [ ] Create src/ngrok/cache/lru_test.go with comprehensive cache tests
- [ ] Test basic operations: Set, Get, eviction on capacity overflow
- [ ] Add tests for edge cases: accessing evicted items, updating existing keys, concurrent access
- [ ] Verify LRU ordering is maintained correctly on Get and Set operations
🌿Good first issues
- Add unit tests for
src/ngrok/cache/lru.go—currently no test files visible; LRU cache deserves coverage for eviction and hit rates. - Document the config file format with examples in
docs/—onlysrc/ngrok/client/config.goexists without schema or YAML sample; adddocs/CONFIG.md. - Improve error messages in
src/ngrok/client/cli.go—currently minimal feedback on invalid flags or missing auth tokens; add context-aware hints.
⭐Top contributors
Click to expand
Top contributors
- @inconshreveable — 67 commits
- [@Kevin Burke](https://github.com/Kevin Burke) — 6 commits
- [@Harvey Chapman](https://github.com/Harvey Chapman) — 3 commits
- @ojongerius — 3 commits
- @vincentbernat — 3 commits
📝Recent commits
Click to expand
Recent commits
61d4828— Update README.md (inconshreveable)8c57fff— tweak messaging to clarify the service is still running (inconshreveable)e20bf28— update readme with archive messaging (inconshreveable)a8e7fa4— Merge pull request #339 from RealDigitalMedia/default_inspect_addr (inconshreveable)62eba1e— Merge pull request #337 from RealDigitalMedia/fix_import_order (inconshreveable)de0f8ed— no longer build 1.3 (inconshreveable)2b08cee— Merge pull request #338 from RealDigitalMedia/update_ssl_debugging (inconshreveable)e071180— Use InsecureSkipVerify for debug and ServerName for both (Harvey Chapman)8713b4b— Give inspect address a default setting (Harvey Chapman)bf9b8bc— import sort order (Harvey Chapman)
🔒Security observations
- High · Hardcoded TLS Certificates and Keys —
assets/server/tls/snakeoil.key, assets/server/tls/snakeoil.crt, assets/client/tls/ngrokroot.crt, assets/client/tls/snakeoilca.crt. The repository contains hardcoded TLS certificates and private keys in the assets directory (snakeoil.crt, snakeoil.key, ngrokroot.crt, snakeoilca.crt). These appear to be self-signed test certificates, but storing private keys in version control is a critical security risk. If these are used in production or shared across environments, the private keys are compromised. Fix: Remove private keys from version control immediately. Use environment variables or secure key management systems (e.g., HashiCorp Vault, AWS Secrets Manager) to inject certificates and keys at runtime. Mark these files in .gitignore and document the proper key generation process. - High · Archived and Unmaintained Codebase —
Repository root / Overall project. This is ngrok v1 which was last actively developed in 2016 and is now archived. The codebase is no longer maintained, supported, or receiving security updates. Any vulnerabilities discovered will not be patched by the original developers. Fix: Migrate to ngrok v2+ which is actively maintained. If continuing to use v1, conduct thorough security audits, apply patches manually, and consider forking with dedicated security maintenance resources. - High · Potential XSS via Angular Sanitization —
assets/client/static/js/angular-sanitize.min.js, assets/client/static/js/ngrok.js, src/ngrok/client/views/web/. The codebase includes AngularJS with angular-sanitize.min.js and references to dangerouslySetInnerHTML patterns. The web UI (assets/client/static/js/ngrok.js) may be vulnerable to Cross-Site Scripting (XSS) attacks if user input from HTTP requests is not properly sanitized before rendering. Fix: Audit all input handling in ngrok.js and web view components. Ensure AngularJS's built-in sanitization is properly applied to all user-controlled content. Use Content Security Policy (CSP) headers to mitigate XSS risks. Consider upgrading from AngularJS to a modern framework with better security defaults. - Medium · Outdated JavaScript Dependencies —
assets/client/static/js/jquery-1.9.1.min.js, assets/client/static/js/angular.js. The client uses older JavaScript libraries including jQuery 1.9.1 (released 2013) and AngularJS (released 2010), which contain known security vulnerabilities. These are minified versions from years ago with no patch updates. Fix: Update all JavaScript dependencies to their latest versions. Implement a dependency management system (npm/yarn) with regular update cycles. Use tools like npm audit, Snyk, or OWASP Dependency-Check to identify and patch vulnerabilities automatically. - Medium · Missing Security Headers Configuration —
src/ngrok/server/http.go, src/ngrok/client/views/web/view.go. No evidence of security headers (HSTS, CSP, X-Frame-Options, X-Content-Type-Options) in the web view configuration. The ngrok server serves a web dashboard which could be vulnerable to clickjacking, MIME type sniffing, and other header-based attacks. Fix: Implement security headers in HTTP responses: Set Content-Security-Policy, X-Frame-Options: DENY, X-Content-Type-Options: nosniff, Strict-Transport-Security, and X-XSS-Protection headers. Review HTTP response handling code and add middleware for consistent header injection. - Medium · Potential Credential Exposure in Configuration Files —
src/ngrok/client/config.go, src/ngrok/server/cli.go, src/ngrok/client/cli.go. The presence of config.go and CLI argument handling (cli.go) suggests configuration via command-line or config files. No evidence of secure credential handling or encryption of sensitive configuration parameters like auth tokens. Fix: Implement secure credential storage using OS-level credential managers (macOS Keychain, Windows DPAPI, Linux Secret Service). Avoid storing plaintext credentials in config files. Use environment variables for sensitive data with clear documentation on
LLM-derived; treat as a starting point, not a security audit.
👉Where to read next
- Open issues — current backlog
- Recent PRs — what's actively shipping
- Source on GitHub
Generated by RepoPilot. Verdict based on maintenance signals — see the live page for receipts. Re-run on a new commit to refresh.