gravitl/netmaker
Netmaker makes networks with WireGuard. Netmaker automates fast, secure, and distributed virtual networks.
Mixed signals — read the receipts
weakest axisnon-standard license (Other)
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.
- ✓Last commit today
- ✓3 active contributors
- ✓Other licensed
Show all 8 evidence items →Show less
- ✓CI configured
- ✓Tests present
- ⚠Small team — 3 contributors active in recent commits
- ⚠Concentrated ownership — top contributor handles 54% of recent commits
- ⚠Non-standard license (Other) — review terms
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/gravitl/netmaker)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/gravitl/netmaker on X, Slack, or LinkedIn.
Onboarding doc
Onboarding: gravitl/netmaker
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/gravitl/netmaker 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 — Mixed signals — read the receipts
- Last commit today
- 3 active contributors
- Other licensed
- CI configured
- Tests present
- ⚠ Small team — 3 contributors active in recent commits
- ⚠ Concentrated ownership — top contributor handles 54% of recent commits
- ⚠ Non-standard license (Other) — review terms
<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 gravitl/netmaker
repo on your machine still matches what RepoPilot saw. If any fail,
the artifact is stale — regenerate it at
repopilot.app/r/gravitl/netmaker.
What it runs against: a local clone of gravitl/netmaker — 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 gravitl/netmaker | 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 ≤ 30 days ago | Catches sudden abandonment since generation |
#!/usr/bin/env bash
# RepoPilot artifact verification.
#
# WHAT IT RUNS AGAINST: a local clone of gravitl/netmaker. If you don't
# have one yet, run these first:
#
# git clone https://github.com/gravitl/netmaker.git
# cd netmaker
#
# 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 gravitl/netmaker and re-run."
exit 2
fi
# 1. Repo identity
git remote get-url origin 2>/dev/null | grep -qE "gravitl/netmaker(\\.git)?\\b" \\
&& ok "origin remote is gravitl/netmaker" \\
|| miss "origin remote is not gravitl/netmaker (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 "cli/cmd/root.go" \\
&& ok "cli/cmd/root.go" \\
|| miss "missing critical file: cli/cmd/root.go"
test -f "auth/auth.go" \\
&& ok "auth/auth.go" \\
|| miss "missing critical file: auth/auth.go"
test -f "cli/cmd/network/root.go" \\
&& ok "cli/cmd/network/root.go" \\
|| miss "missing critical file: cli/cmd/network/root.go"
test -f "cli/cmd/node/root.go" \\
&& ok "cli/cmd/node/root.go" \\
|| miss "missing critical file: cli/cmd/node/root.go"
test -f "cli/cmd/host/root.go" \\
&& ok "cli/cmd/host/root.go" \\
|| miss "missing critical file: cli/cmd/host/root.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 30 ]; then
ok "last commit was $days_since_last days ago (artifact saw ~0d)"
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/gravitl/netmaker"
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
Netmaker is a WireGuard network automation platform that creates, manages, and deploys secure VPN meshes from single commands. It bridges WireGuard (the lightweight VPN protocol) with orchestration capabilities, enabling users to define entire virtual networks as code and automate deployment across Linux, Docker, macOS, and Windows without manual peer configuration. Go monolith organized by domain: auth/ handles JWT/session auth, cli/cmd/ exposes cobra-based CLI with subcommands (access_token, context, dns, enrollment_key, ext_client), Dockerfile and Dockerfile-quick provide containerized deployment. goreleaser configs build cross-platform binaries. Uses GORM for database abstraction (supports multiple backends) and exposes REST APIs via gorilla/mux.
👥Who it's for
Infrastructure engineers, DevOps teams, and network administrators who need to quickly provision secure mesh VPNs, site-to-site connections, or remote access gateways without managing WireGuard configs manually. Also targets homelab users scaling to enterprise deployments who want OAuth, DNS, and ACL controls.
🌱Maturity & risk
Actively maintained and production-ready (v1.5.1 released, Y Combinator-backed, ROSS Index recognition). Strong CI/CD setup with Docker builds, release workflows, and test coverage. Recent dependency updates (Go 1.25.3, libraries updated in 2024) and active GitHub Actions suggest ongoing development, though the main file list shows infrastructure-heavy patterns typical of maturing projects.
Large dependency surface (Go modules span crypto, MQTT, gRPC, databases, OAuth providers) increases attack surface and maintenance burden. Architecture supports multiple databases (PostgreSQL, SQLite, rqlite, ClickHouse) and authentication backends (OIDC, Okta, OAuth2), which increases complexity. Single Go monolith (1.7M LOC) means changes ripple widely; no visible service isolation or canary deployment patterns in the file list.
Active areas of work
Active GitHub Actions workflows for branch testing, Docker publishing, and releases suggest frequent deployments. Dependabot configuration indicates automated dependency management. File structure shows recent focus on CLI expansion (access_token, enrollment_key, context subcommands) and multi-provider auth (Okta SDK, OIDC, OAuth2 integrations visible in go.mod).
🚀Get running
Clone: git clone https://github.com/gravitl/netmaker.git && cd netmaker. Install: go mod download (Go 1.25.3+ required). Build: go build -o netmaker . or docker build -f Dockerfile -t netmaker .. Run: Check Dockerfile for entrypoint—likely ./netmaker with environment config (DATABASE_URL, AUTH_PROVIDER, etc.).
Daily commands:
From repo root: go run . [command] for CLI execution. For server: likely go run . server or environment-dependent startup (check main.go). Docker: docker-compose up if a compose file exists (not listed but typical), else docker build -f Dockerfile -t netmaker . && docker run -e DATABASE_URL=<...> netmaker. See Dockerfile for expected env vars.
🗺️Map of the codebase
cli/cmd/root.go— Entry point for the entire Netmaker CLI application; all CLI commands are registered and initialized here.auth/auth.go— Core authentication logic handling JWT tokens and user session validation across all API endpoints.cli/cmd/network/root.go— Network command handler; foundational for understanding how Netmaker's primary abstraction (networks) is managed via CLI.cli/cmd/node/root.go— Node command handler; essential for understanding WireGuard node management and VPN peer configuration.cli/cmd/host/root.go— Host command handler; defines how physical/virtual hosts are registered and managed in the system..github/workflows/docker-builder.yml— Docker build and push workflow; critical for understanding build pipeline and artifact distribution.Dockerfile— Production container definition; shows deployment model and runtime dependencies for Netmaker server.
🛠️How to make changes
Add a New CLI Command
- Create a new command directory under cli/cmd/<feature>/ (
cli/cmd/node/root.go (as reference structure)) - Implement root.go with cobra.Command definition and subcommands (create, delete, list, update patterns) (
cli/cmd/<feature>/root.go) - Add individual action files (create.go, delete.go, etc.) following the existing naming convention (
cli/cmd/<feature>/create.go) - Register the new command in the parent root.go or directly in cli/cmd/root.go if top-level (
cli/cmd/root.go)
Add a New Network Feature (e.g., DNS, Failover, Relay)
- Create feature module directory under cli/cmd/<feature_name>/ (
cli/cmd/dns/ (as reference)) - Define root command with list, create, delete subcommands mirroring existing patterns (
cli/cmd/<feature_name>/root.go) - Implement flags if needed to customize behavior (e.g., create.go with flags) (
cli/cmd/network/flags.go (as reference for flag patterns)) - Register feature in cli/cmd/root.go or parent command and ensure auth.go validates permissions (
cli/cmd/root.go)
Extend Authentication/Authorization
- Modify core auth logic to add new token claim or session attribute (
auth/auth.go) - For host-specific session handling, update host session validation (
auth/host_session.go) - Add role/permission checks in API handlers or CLI command setup using updated auth logic (
cli/cmd/user/flags.go (as reference for permission-related flags))
Add Metrics or Monitoring Feature
- Create new metric collector command under cli/cmd/metrics/ (
cli/cmd/metrics/all.go (as reference)) - Define what data to collect (node metrics, network metrics, etc.) (
cli/cmd/metrics/node.go) - Implement query logic and output formatting (JSON, table, etc.) (
cli/cmd/metrics/root.go) - Register in metrics root command and ensure auth gates access if needed (
cli/cmd/metrics/root.go)
🔧Why these technologies
- Go — Fast compilation, static binaries, built-in concurrency primitives (goroutines) ideal for managing distributed WireGuard peers and network state.
- WireGuard — Modern, lightweight VPN protocol with excellent performance and security; Netmaker automates WireGuard peer management and configuration.
- PostgreSQL / SQLite — Persistent storage for network topology, user accounts, enrollment keys, and node configuration; PostgreSQL for production multi-node deployments.
- MQTT (Paho) — Lightweight pub/sub messaging for edge node communication and real-time state synchronization across distributed hosts.
- JWT (golang-jwt) — Stateless authentication for CLI and API clients; enables distributed authentication without central session store.
- Docker — Containerization for server deployment; isolates Netmaker from host system and simplifies multi-host orchestration.
⚖️Trade-offs already made
-
CLI-first interface (Cobra) rather than primary web UI
- Why: Enables scriptable, version-controllable infrastructure-as-code approach; lighter weight than full web dashboard.
- Consequence: Users must learn CLI commands; less intuitive for non-technical users; requires documentation and help text.
-
Dual database support (PostgreSQL + SQLite)
- Why: SQLite for single-node dev/test; PostgreSQL for production multi-server deployments.
- Consequence: Additional code paths for different databases; potential consistency issues if schemas diverge; testing burden.
-
Token-based (JWT) vs. session-based authentication
- Why: Stateless design allows horizontal scaling without shared session store; JWT portable across distributed servers.
- Consequence: Token revocation requires external blacklist; no immediate logout; token lifetime must be carefully tuned.
-
MQTT for node-to-server communication
- Why: Lightweight, pub/sub model fits edge node push of state changes and metrics; reduces polling overhead.
- Consequence: Requires MQTT broker deployment; adds operational complexity; debugging network issues harder than REST.
🚫Non-goals (don't propose these)
- Does not provide a primary web UI—focuses on CLI and API; web dashboard is secondary/optional.
- Not a general-purpose VPN service—optimized for programmatic virtual network creation and management.
- Does not handle end-user authentication (OAuth, LDAP, SAML)—relies on pre-created service accounts and JWT tokens.
- Not a real-time streaming analytics platform—metrics collection is periodic, not continuous stream ingestion.
- Does not manage or provision underlying infrastructure (cloud VMs, containers)—assumes hosts/nodes already exist and are reachable.
🪤Traps & gotchas
No main.go in file list: entry point not visible—check root directory or cmd/ directory. Multiple database drivers bundled: code must handle database abstraction carefully; DATABASE_URL and driver selection likely via environment. MQTT integration: broker connectivity required for some operations (eclipse/paho.mqtt); broker address/creds must be configured. WireGuard kernel module dependency: Linux nodes require wireguard kernel module or userspace implementation (wireguard-go); deployment scripts likely handle this. OAuth/OIDC state: auth provider credentials (Okta, Google) must be set via environment; missing creds causes auth failure silently. CLI context persistence: cli/cmd/context/ suggests config stored on disk; may interfere with testing or concurrent test runs.
🏗️Architecture
💡Concepts to learn
- WireGuard Protocol — Core transport layer; understanding its peer-to-peer, cryptographic key exchange, and minimal surface area is essential to comprehend what Netmaker automates
- Mesh Networking — Netmaker's primary value is automating mesh topologies; understanding fully-connected vs. partial-mesh vs. hub-spoke is critical for designing and debugging networks
- JWT (JSON Web Tokens) — Used for authentication throughout Netmaker (
golang-jwt/jwtdependency); core to understanding session management inauth/auth.goand CLI context persistence - MQTT (Message Queuing Telemetry Transport) — Lightweight messaging protocol used for node-to-server communication (
eclipse/paho.mqtt.golangdependency); essential for understanding distributed state propagation in the system - OAuth2 / OIDC (OpenID Connect) — Multi-provider auth pattern used throughout (Okta, Google, generic OIDC); critical for understanding authentication flows and adding new auth backends in
auth/auth.go - Database Abstraction (GORM) — GORM provides abstraction across PostgreSQL, SQLite, rqlite, ClickHouse; understanding driver selection and model definition is key to modifying data persistence
- gRPC (gRPC Remote Procedure Call) — High-performance RPC framework for inter-service communication; understanding protocol buffers and service definitions helps debug distributed operations across nodes
🔗Related repos
WireGuard/wireguard-go— User-space WireGuard implementation that Netmaker can fall back to on systems without kernel WireGuard moduletailscale/tailscale— Direct competitor offering encrypted mesh networks; similar goal (seamless VPN) but proprietary control plane vs. Netmaker's open-source approachgravitl/netmaker-ui— Companion frontend repository (inferred—not listed) providing the Admin UI mentioned in README for network management and monitoringgravitl/netmaker-docs— Official documentation repository (referenced in README) containing deployment guides, API docs, and CLI reference for users and contributorsslackhq/nebula— Alternative overlay network tool with similar goals; evaluating Netmaker vs. Nebula common for teams choosing mesh VPN solutions
🪄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 comprehensive unit tests for auth package (auth/auth.go and auth/host_session.go)
The auth package handles critical security functionality (JWT tokens, host sessions) but has no visible test files in the repo structure. Given that Netmaker is a security-focused networking tool, authentication tests are high-value. This would improve code coverage for a sensitive area and catch regressions early.
- [ ] Create auth/auth_test.go with tests for token validation, expiration, and claims parsing
- [ ] Create auth/host_session_test.go with tests for session creation, validation, and cleanup
- [ ] Test edge cases: expired tokens, invalid signatures, missing claims, concurrent session access
- [ ] Verify integration with golang-jwt/jwt/v4 library
- [ ] Add test coverage report to CI pipeline
Add integration tests for CLI commands (cli/cmd/) with test fixtures and helpers
The CLI has many subcommands (access_token, context, dns, enrollment_key, ext_client, failover, gateway, host, etc.) but no visible test structure. A test helper package and integration tests would ensure CLI reliability and prevent regressions when refactoring commands.
- [ ] Create cli/cmd/commons/test_helpers.go with utilities for mocking API responses and CLI context
- [ ] Add cli/cmd/*/cmd_test.go files for each command group (e.g., access_token_test.go, context_test.go)
- [ ] Test flag parsing, error handling, and output formatting for critical commands
- [ ] Use testify/assert for assertions and consider table-driven tests for multiple scenarios
- [ ] Document CLI testing patterns in CONTRIBUTING.md
Create GitHub Actions workflow for Go linting and code quality checks (golangci-lint)
While branchtest.yml and test.yml exist, there's no visible linting workflow. Adding golangci-lint CI would catch code style issues, potential bugs, and security problems early. This is especially important for a security-focused project with many contributors.
- [ ] Create .github/workflows/lint.yml with golangci-lint action
- [ ] Create .golangci.yml configuration file with rules for: unused code, shadow variables, SQL injection patterns, error handling
- [ ] Run linting on PRs to main and develop branches
- [ ] Add linting results as required status check in branch protection rules
- [ ] Document linting standards in CONTRIBUTING.md (e.g., max cyclomatic complexity, naming conventions)
🌿Good first issues
- Add unit tests for auth/host_session.go: File exists but test coverage visibility missing. Write tests for session validation, expiry, and edge cases (malformed JWT, expired tokens). Location: create
auth/host_session_test.gofollowing Go conventions. - Improve CLI help output for enrollment_key subcommands: The enrollment_key feature (
cli/cmd/enrollment_key/) spans create, delete, list but no visible docs. Add--helpdescriptions and examples to each subcommand inenrollment_key/root.goand child files. - Add integration test for DNS push workflow:
cli/cmd/dns/push.goexists but test presence unknown. Createdns/push_test.gomocking a DNS server and verifying the push operation; reveals API contracts and helps prevent regressions.
⭐Top contributors
Click to expand
Top contributors
- @abhishek9686 — 54 commits
- @VishalDalwadi — 45 commits
- @Mejdii — 1 commits
📝Recent commits
Click to expand
Recent commits
575d44f— Merge pull request #3993 from gravitl/release-v1.5.1 (abhishek9686)0feeded— Merge pull request #3992 from gravitl/NM-323 (abhishek9686)3144088— fix: merge deduplicated egress routes for shared relay peer keys (abhishek9686)8eedb58— Merge pull request #3989 from gravitl/release-v1.5.1 (abhishek9686)48f2147— Merge pull request #3988 from gravitl/NM-321-v1 (abhishek9686)928ab8d— fix(go): revert mq publish on validate license; (VishalDalwadi)20c8b50— feat(go): rename pro license file; (VishalDalwadi)b17abe4— feat(go): check for err during user get; (VishalDalwadi)a46b064— feat(go): remove ee tag from pro/license pkg; (VishalDalwadi)acf2e21— feat(go): add api to trigger license validation; move license functions and types into separate package; (VishalDalwadi)
🔒Security observations
- High · Outdated Go Version —
go.mod. The project uses Go 1.25.3, which is significantly ahead of the current stable release cycle. This appears to be a pre-release or unreleased version, which may contain unpatched vulnerabilities and lacks community testing. Fix: Use a stable, officially released Go version. As of late 2024, use Go 1.23.x or the latest stable release from golang.org. - High · Outdated Cryptographic Dependencies —
go.mod - golang.org/x/crypto dependency. golang.org/x/crypto v0.49.0 is outdated. Current stable versions are much newer (v0.25.0+). Outdated crypto libraries may contain known vulnerabilities in cipher implementations. Fix: Update to the latest stable version of golang.org/x/crypto (ideally v0.27.0 or newer) to ensure security patches are applied. - High · Outdated JWT Library —
go.mod - github.com/golang-jwt/jwt/v4 dependency. github.com/golang-jwt/jwt/v4 v4.5.2 is used, but v5.x is available with improved security features and bug fixes. JWT libraries are critical for authentication. Fix: Evaluate migration to golang-jwt/jwt v5.x or ensure v4.5.2 has no known CVEs. Consider applying security patches if available. - Medium · Multiple Outdated Dependencies —
go.mod - multiple dependencies. Several dependencies have outdated versions including github.com/lib/pq v1.11.2 (PostgreSQL driver from 2020), github.com/mattn/go-sqlite3 v1.14.37 (2021), and github.com/skip2/go-qrcode v0.0.0-20200617195104-da1b6568686e (2020). These may contain known vulnerabilities. Fix: Run 'go list -u -m all' to identify updates. Update all dependencies to their latest stable versions, especially database drivers and cryptographic libraries. - Medium · Missing SBOM and Dependency Scanning —
.github/workflows/ - test.yml, branchtest.yml. No evidence of dependency vulnerability scanning (OWASP Dependency-Check, Snyk, or similar) in CI/CD pipeline. Multiple outdated dependencies with potential CVEs may go undetected. Fix: Integrate automated dependency scanning in CI/CD. Add 'go list -json -m all | nancy sleuth' or use GitHub's native Dependabot with vulnerability alerts enabled. - Medium · Exposed Ports in Docker Image —
Dockerfile - EXPOSE 6060. Dockerfile exposes ports 8081 and 6060. Port 6060 is commonly used for pprof (Go profiling), which should not be exposed in production as it leaks runtime information. Fix: Remove or conditionally expose port 6060. Use build arguments or environment variables to control port exposure. Ensure 6060 is only accessible in development/debug mode. - Medium · No Security Headers Configuration Visible —
auth/auth.go, routing configuration. File structure shows HTTP handlers (gorilla/mux) but no visible security middleware configuration (HSTS, CSP, X-Frame-Options, etc.) in the codebase snapshot provided. Fix: Implement security headers middleware using gorilla/handlers or similar. Add HSTS, Content-Security-Policy, X-Content-Type-Options, and X-Frame-Options headers. - Medium · OIDC/OAuth Integration without Visible Validation —
auth/ directory - oauth2 implementation. coreos/go-oidc/v3 and oauth2 dependencies present, but no evidence of proper token validation, state parameter verification, or PKCE enforcement in file structure. Fix: Ensure PKCE is enforced for OAuth2 flows, state parameter is validated, and OIDC tokens are properly verified before trust. Review auth/auth.go for proper implementation. - Low · No Visible Input Validation Framework Configuration —
undefined. While go-playground Fix: undefined
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.