Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 0 additions & 4 deletions .github/dependabot.yml
Original file line number Diff line number Diff line change
@@ -1,10 +1,6 @@
# https://docs.github.com/en/code-security/dependabot/dependabot-version-updates/configuration-options-for-the-dependabot.yml-file
version: 2
updates:
- package-ecosystem: "gitsubmodule"
directory: "/"
schedule:
interval: "weekly"
- package-ecosystem: "gomod"
directory: "/"
schedule:
Expand Down
33 changes: 33 additions & 0 deletions .github/workflows/docs-gen.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
name: Docs reference drift

on:
# Narrowed to master: an unfiltered `push` also fires on every topic branch
# and every tag, duplicating the run each pull request already performs.
push:
branches: [ master ]
pull_request:

jobs:
docs-gen:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v7
- name: Set up Go
uses: actions/setup-go@v6
with:
go-version: 1.26
- name: Regenerate the reference
run: make docs-gen
- name: Fail if the generated reference is stale
# The output is staged before diffing because `git diff --exit-code`
# ignores untracked paths: a brand-new command makes the generator emit
# a new cli/<name>.md, and an unstaged diff would pass while that page
# went uncommitted. Diffing the index catches additions alongside
# modifications and deletions.
run: |
git add -A docs/content/en/docs/reference/
if ! git diff --cached --exit-code docs/content/en/docs/reference/; then
echo "::error::The generated CLI reference is out of date. Run 'make docs-gen' and commit the result."
exit 1
fi
5 changes: 5 additions & 0 deletions .github/workflows/pages.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,11 @@ name: Github Pages
on:
push:
branches: [ master ]
# Pull requests build the docs so breakage is caught before merge. They must
# never deploy: the Deploy step below is guarded on a push to master.
pull_request:
paths:
- 'docs/**'

jobs:
build:
Expand Down
3 changes: 0 additions & 3 deletions .gitmodules

This file was deleted.

76 changes: 76 additions & 0 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
# Contributing to EdgeVPN

Thanks for wanting to help. This page is the short version; the full
documentation lives at <https://mudler.github.io/edgevpn/docs/>.

## Build

EdgeVPN ships as a single binary, but the web interface is a React application
compiled into it, so you need Go 1.26 (the version in `go.mod`) **and** Node.js
20.19 or newer:

```bash
make build # compiles the web interface, then the Go binary
make react-ui-force # force a clean rebuild of the interface
```

`go build` on its own works only when `api/react-ui/dist` already exists — the
interface is embedded with `//go:embed`, so a missing directory is a compile
error. Working on the Go side only? Stub it:

```bash
mkdir -p api/react-ui/dist && touch api/react-ui/dist/index.html
```

Building the **documentation site** additionally needs Hugo and Node/npm —
`docs/scripts/build.sh` downloads the pinned Hugo (see `docs/Makefile`) and
installs `postcss-cli` and `autoprefixer` for you:

```bash
cd docs && make build # one-off build into docs/public
cd docs && make serve # live preview on http://localhost:1313
```

## Test

```bash
make test # go test ./...
```

The end-to-end suites that CI runs (VPN connectivity, services, file transfer)
are the scripts under `.github/`; see `.github/workflows/test.yml` for how they
are invoked.

## Adding or changing a CLI flag

The CLI and environment-variable reference under
`docs/content/en/docs/reference/` is **generated** from the real `cli.App` — do
not hand-edit those pages. After touching any flag or command, run:

```bash
make docs-gen
```

and commit the result. The `Docs reference drift` workflow regenerates the
reference on every push and pull request and fails if the committed output
differs, so a forgotten `make docs-gen` will turn CI red.

## Issues and pull requests

- Open issues and feature requests at
<https://github.com/mudler/edgevpn/issues>.
- Questions and general discussion belong in
[GitHub Discussions](https://github.com/mudler/edgevpn/discussions) or the
[Matrix room](https://matrix.to/#/#edgevpn:matrix.org).
- Pull requests go against `master`. Please make sure `make test` and
`make docs-gen` are clean before asking for review, and mark work in progress
with a draft PR or a `WIP` prefix.

Docs-only changes have their own walkthrough (including the *Edit this page*
shortcut) at
<https://mudler.github.io/edgevpn/docs/contribution-guidelines/>.

## License

EdgeVPN is Apache 2.0 licensed. By contributing you agree that your
contributions are licensed under the same terms.
8 changes: 7 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
.PHONY: all build react-ui react-ui-force test clean
.PHONY: all build react-ui react-ui-force test clean docs-gen

all: build

Expand All @@ -25,5 +25,11 @@ build: api/react-ui/dist
test: api/react-ui/dist
go test ./...

# docs-gen regenerates the CLI and environment-variable reference from the real
# cli.App. The output is committed; CI re-runs this and fails on a diff, so the
# docs cannot drift from the binary.
docs-gen:
go run ./internal/docsgen

clean:
rm -rf api/react-ui/dist edgevpn
108 changes: 15 additions & 93 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ It can:
- **Create a VPN** : Secure VPN between p2p peers
- Automatically assign IPs to nodes
- Embedded tiny DNS server to resolve internal/external IPs
- Create trusted zones to prevent network access if token is leaked
- Create trusted zones to restrict which peers may join (experimental: it does not currently stop a token holder from entering the zone — see the [security model](https://mudler.github.io/edgevpn/docs/explanation/security-model/))
- For example, the [Kairos](https://github.com/kairos-io/kairos) CNCF project uses it as a layer for creating decentralized clusters with Kubernetes

- **Act as a reverse Proxy** : Share a tcp service like you would do with `ngrok`. EdgeVPN let expose TCP services to the p2p network nodes without establishing a VPN connection: creates reverse proxy and tunnels traffic into the p2p network.
Expand Down Expand Up @@ -75,6 +75,14 @@ Check out [Kairos](https://github.com/kairos-io/kairos) for seeing EdgeVPN in ac

Download the precompiled static release in the [releases page](https://github.com/mudler/edgevpn/releases). You can either install it in your system or just run it.

Or install the latest release with the one-liner:

```bash
curl -sfL https://raw.githubusercontent.com/mudler/edgevpn/master/install.sh | sh
```

Every installation route — install script, release archives, Homebrew, the container image and building from source — is covered in [Install EdgeVPN](https://mudler.github.io/edgevpn/docs/tutorials/install/).

# :hammer: Building from source

The web UI is a React application compiled into the binary, so a Node
Expand Down Expand Up @@ -149,90 +157,20 @@ $ EDGEVPNTOKEN=.. edgevpn --address 10.1.0.13/24

# :question: Is it for me?

EdgeVPN makes VPN decentralization a first strong requirement.

Its main use is for edge and low-end devices and especially for development.

The decentralized approach has few cons:

- The underlying network is chatty. It uses a Gossip protocol for synchronizing the routing table and p2p. Every blockchain message is broadcasted to all peers, while the traffic is to the host only.
- Might be not suited for low latency workload.

Keep that in mind before using it for your prod networks!

But it has a strong pro: it just works everywhere libp2p works!
The decentralized approach is chatty and might not suit low-latency workloads, and this software has not been security audited. Read [when not to use EdgeVPN](https://mudler.github.io/edgevpn/docs/explanation/when-not-to-use-edgevpn/) before you rely on it.

# :question: Why?

First of all it's my first experiment with libp2p. Second, I always wanted a more "open" `ngrok` alternative, but I always prefer to have "less infra" as possible to maintain. That's why building something like this on top of `libp2p` makes sense.

# :warning: Warning!

I'm not a security expert, and this software didn't went through a full security audit, so don't use and rely on it for sensible traffic and not even for production environment! I did this mostly for fun while I was experimenting with libp2p.

## Example use case: network-decentralized [k3s](https://github.com/k3s-io/k3s) test cluster

Let's see a practical example, you are developing something for kubernetes and you want to try a multi-node setup, but you have machines available that are only behind NAT (pity!) and you would really like to leverage HW.

If you are not really interested in network performance (again, that's for development purposes only!) then you could use `edgevpn` + [k3s](https://github.com/k3s-io/k3s) in this way:

1) Generate edgevpn config: `edgevpn -g > vpn.yaml`
2) Start the vpn:

on node A: `sudo IFACE=edgevpn0 ADDRESS=10.1.0.3/24 EDGEVPNCONFIG=vpn.yml edgevpn`

on node B: `sudo IFACE=edgevpn0 ADDRESS=10.1.0.4/24 EDGEVPNCONFIG=vpm.yml edgevpn`
3) Start k3s:

on node A: `k3s server --flannel-iface=edgevpn0`

on node B: `K3S_URL=https://10.1.0.3:6443 K3S_TOKEN=xx k3s agent --flannel-iface=edgevpn0 --node-ip 10.1.0.4`

We have used flannel here, but other CNI should work as well.


# :notebook: As a library

EdgeVPN can be used as a library. It is very portable and offers a functional interface.

To join a node in a network from a token, without starting the vpn:

```golang
This software has not been through a full security audit — don't rely on it for sensitive traffic or production environments. The full caveats are in [when not to use EdgeVPN](https://mudler.github.io/edgevpn/docs/explanation/when-not-to-use-edgevpn/).

import (
node "github.com/mudler/edgevpn/pkg/node"
)
# :books: Examples

e := node.New(
node.Logger(l),
node.LogLevel(log.LevelInfo),
node.MaxMessageSize(2 << 20),
node.FromBase64( mDNSEnabled, DHTEnabled, token ),
// ....
)

e.Start(ctx)

```

or to start a VPN:

```golang

import (
vpn "github.com/mudler/edgevpn/pkg/vpn"
node "github.com/mudler/edgevpn/pkg/node"
)

opts, err := vpn.Register(vpnOpts...)
if err != nil {
return err
}

e := edgevpn.New(append(o, opts...)...)

e.Start(ctx)
```
- [A network-decentralized k3s test cluster](https://mudler.github.io/edgevpn/docs/tutorials/decentralized-k3s-cluster/) — a multi-node Kubernetes development cluster across machines behind NAT.
- [Use EdgeVPN as a library](https://mudler.github.io/edgevpn/docs/how-to/use-as-a-library/) — embed a node in your own Go program.

# 🧑‍💻 Projects using EdgeVPN

Expand All @@ -259,23 +197,7 @@ and any other way if not mentioned here.

# :notebook: Troubleshooting

If during bootstrap you see messages like:

```
edgevpn[3679]: * [/ip4/104.131.131.82/tcp/4001] failed to negotiate stream multiplexer: context deadline exceeded
```

or

```
edgevpn[9971]: 2021/12/16 20:56:34 failed to sufficiently increase receive buffer size (was: 208 kiB, wanted: 2048 kiB, got: 416 kiB). See https://github.com/lucas-clemente/quic-go/wiki/UDP-Receive-Buffer-Size for details.
```

or generally experiencing poor network performance, it is recommended to increase the maximum buffer size by running:

```
sysctl -w net.core.rmem_max=2500000
```
Bootstrap failures, receive-buffer warnings and poor network performance are covered in [Troubleshooting](https://mudler.github.io/edgevpn/docs/troubleshooting/).

# :notebook: TODO

Expand Down
22 changes: 14 additions & 8 deletions docs/config.toml
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
baseURL = "https://mudler.github.io/edgevpn/docs/"
# Must match the -b value passed by scripts/build.sh, which is what production
# is actually built with. The site root is https://mudler.github.io/edgevpn/;
# /docs/ is a content section inside it, not the base.
baseURL = "https://mudler.github.io/edgevpn/"
title = "EdgeVPN"

enableRobotsTXT = true
Expand Down Expand Up @@ -42,10 +45,9 @@ resampleFilter = "CatmullRom"
quality = 75
anchor = "smart"

[services]
[services.googleAnalytics]
# Comment out the next line to disable GA tracking. Also disables the feature described in [params.ui.feedback].
id = "UA-00000000-0"
# No analytics property is configured. The Docsy template ships a placeholder
# "UA-00000000-0" here; leaving it in place sent page views and the
# [params.ui.feedback] events to a property that does not exist.

# Language configuration

Expand Down Expand Up @@ -118,8 +120,9 @@ offlineSearch = true
[params.ui]
# Enable to show the side bar menu in its compact state.
sidebar_menu_compact = false
# Set to true to disable breadcrumb navigation.
breadcrumb_disable = true
# Set to true to disable breadcrumb navigation. The docs tree is three levels
# deep (docs / section / page), so breadcrumbs earn their keep.
breadcrumb_disable = false
# Set to true to hide the sidebar search box (the top nav search box will still be displayed if search is enabled)
sidebar_search_disable = false
# Set to false if you don't want to display a logo (/assets/icons/logo.svg) in the top nav bar
Expand All @@ -131,8 +134,11 @@ footer_about_disable = false
# This feature depends on [services.googleAnalytics] and will be disabled if "services.googleAnalytics.id" is not set.
# If you want this feature, but occasionally need to remove the "Feedback" section from a single page,
# add "hide_feedback: true" to the page's front matter.
# Disabled along with the analytics property above: the responses are delivered
# as Google Analytics events, so with no property configured the widget would
# only collect clicks and drop them. Re-enable once a GA4 property exists.
[params.ui.feedback]
enable = true
enable = false
# The responses that the user sees after clicking "yes" (the page was helpful) or "no" (the page was not helpful).
yes = 'Glad to hear it! Please <a href="https://github.com/mudler/edgevpn/issues/new">tell us how we can improve</a>.'
no = 'Sorry to hear that. Please <a href="https://github.com/mudler/edgevpn/issues/new">tell us how we can improve</a>.'
Expand Down
4 changes: 2 additions & 2 deletions docs/content/en/_index.html
Original file line number Diff line number Diff line change
Expand Up @@ -71,10 +71,10 @@ <h1 class="text-center">
</h1>

<center>
<a class="btn btn-md btn-primary mr-3 mb-4" href="{{< relref "/docs">}}/getting-started/api/">
<a class="btn btn-md btn-primary mr-3 mb-4" href="{{< relref "/docs/reference/api" >}}">
WebUI
<i class="fa fa-globe ml-2"></i></a>
<a class="btn btn-md btn-primary mr-3 mb-4" href="{{< relref "/docs">}}/getting-started/gui/">GUI
<a class="btn btn-md btn-primary mr-3 mb-4" href="{{< relref "/docs/tools/desktop-gui" >}}">GUI
<i class="fa fa-desktop ml-2"></i></a><br>
Keep an eye on your network with the Web UI. <br>
Connect easily from your workstation with the frontend GUI app.
Expand Down
8 changes: 0 additions & 8 deletions docs/content/en/community/_index.md

This file was deleted.

Loading
Loading