🎨 Add docs

This commit is contained in:
Ettore Di Giacinto
2022-01-29 18:23:10 +01:00
parent ab66486bf0
commit ea199579f8
36 changed files with 2965 additions and 196 deletions

23
.github/workflows/pages.yml vendored Normal file
View File

@@ -0,0 +1,23 @@
name: Github Pages
on:
push:
branches: [ master ]
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
with:
submodules: 'recursive'
- name: Build 🔧
run: |
cd docs && make build
mv public ../
- name: Deploy 🚀
if: github.ref == 'refs/heads/master' && github.event_name == 'push'
uses: JamesIves/github-pages-deploy-action@releases/v3
with:
ACCESS_TOKEN: ${{ secrets.ACCESS_TOKEN }}
BRANCH: gh-pages
FOLDER: public

9
.gitignore vendored
View File

@@ -1,4 +1,11 @@
/edgevpn /edgevpn
/edgevpn*.yaml /edgevpn*.yaml
/dist /dist
/vendor /vendor
/docs/bin/
/docs/public/
/docs/resources/
/docs/node_modules/
/docs/.hugo_build.lock
/docs/package-lock.json
/docs/package.json

3
.gitmodules vendored Normal file
View File

@@ -0,0 +1,3 @@
[submodule "docs/themes/docsy"]
path = docs/themes/docsy
url = https://github.com/google/docsy.git

195
README.md
View File

@@ -39,6 +39,7 @@ It can:
- **Be used as a library**: Plug a distributed p2p ledger easily in your golang code! - **Be used as a library**: Plug a distributed p2p ledger easily in your golang code!
See the [documentation](https://mudler.github.io/edgevpn).
# :camera: Screenshots # :camera: Screenshots
@@ -120,200 +121,6 @@ $ EDGEVPNTOKEN=.. edgevpn --address 10.1.0.13/24
*Note*: It might take up time to build the connection between nodes. Wait at least 5 mins, it depends on the network behind the hosts. *Note*: It might take up time to build the connection between nodes. Wait at least 5 mins, it depends on the network behind the hosts.
The VPN takes several options, below you will find a reference for the most important features:
### API
While starting in VPN mode, it is possible _also_ to start in API mode by specifying `--api`.
### DHCP
Note: Experimental feature!
Automatic IP negotiation is available since version `0.8.1`.
DHCP can be enabled with `--dhcp` and `--address` can be omitted. If an IP is specfied with `--address` it will be the default IP.
### :globe_with_meridians: DNS Server
Note: Experimental feature!
A DNS Server is available but disabled by default. It can be enabled by specifying a listening address with `--dns`. For example, to bind to default `53` port locally, use `--dns "127.0.0.1:53"`.
```
--dns value DNS listening address. Empty to disable dns server [$DNSADDRESS]
--dns-forwarder Enables dns forwarding [$DNSFORWARD]
--dns-cache-size value DNS LRU cache size (default: 200) [$DNSCACHESIZE]
--dns-forward-server value List of DNS forward server (default: "8.8.8.8:53", "1.1.1.1:53") [$DNSFORWARDSERVER]
```
The DNS server will resolve DNS queries from the blockchain by default and will forward unknown requests by default. To turn off dns forwarding, specify `--dns-forwarder=false`. Optionally a list of DNS servers can be specified multiple times with `--dns-forward-server`.
Nodes of the VPN can start a local DNS server which will resolve the routes stored in the chain. To add DNS records, use the API:
```bash
$ curl -X POST http://localhost:8080/api/dns --header "Content-Type: application/json" -d '{ "Regex": "foo.bar", "Records": { "A": "2.2.2.2" } }'
```
The `/api/dns` routes accepts `POST` requests as `JSON` of the following form:
```json
{ "Regex": "<regex>",
"Records": {
"A": "2.2.2.2",
"AAAA": "...",
},
}
```
Note, `Regex` accepts regexes which will match the DNS requests received and resolved to the specified entries.
## :loop: Forwarding a local connection
EdgeVPN can also be used to expose local(or remote) services without establishing a VPN and allocating a local tun/tap device, similarly to `ngrok`.
### Exposing a service
If you are used to how Local SSH forwarding works (e.g. `ssh -L 9090:something:remote <my_node>`), EdgeVPN takes a similar approach.
A Service is a generalized TCP service running in a host (also outside the network). For example, let's say that we want to expose a SSH server inside a LAN.
To expose a service to your EdgeVPN network then:
```bash
$ edgevpn service-add "MyCoolService" "127.0.0.1:22"
```
To reach the service, EdgeVPN will setup a local port and bind to it, it will tunnel the traffic to the service over the VPN, for e.g. to bind locally to `9090`:
```bash
$ edgevpn service-connect "MyCoolService" "127.0.0.1:9090"
```
with the example above, 'sshing into `9090` locally would forward to `22`.
## :mailbox: Sending and receiving files
EdgeVPN can be used to send and receive files between hosts via p2p with the `file-send` and `file-receive` subcommand.
Sending and receiving files, as services, don't establish a VPN connection.
### :outbox_tray: Sending
```bash
$ edgevpn file-send 'unique-id' '/src/path'
```
### :inbox_tray: Receiving
```bash
$ edgevpn file-receive 'unique-id' '/dst/path'
```
## :globe_with_meridians: Web interface
To access the web interface, run
```bash
$ edgevpn api
```
with the same `EDGEVPNCONFIG` or `EDGEVPNTOKEN`. It will connect to the network without routing any packet.
By default edgevpn will listen on the `8080` port. See `edgevpn api --help` for the available options
API can also be started together with the vpn.
## :mag: API endpoint
### GET
#### `/api/users`
Returns the users connected to services in the blockchain
#### `/api/services`
Returns the services running in the blockchain
#### `/api/dns`
Returns the domains registered in the blockchain
#### `/api/machines`
Returns the machines connected to the VPN
#### `/api/blockchain`
Returns the latest available blockchain
#### `/api/ledger`
Returns the current data in the ledger
#### `/api/ledger/:bucket`
Returns the current data in the ledger inside the `:bucket`
#### `/api/ledger/:bucket/:key`
Returns the current data in the ledger inside the `:bucket` at given `:key`
### PUT
#### `/api/ledger/:bucket/:key/:value`
Puts `:value` in the ledger inside the `:bucket` at given `:key`
### POST
#### `/api/dns`
The endpoint accept a JSON payload of the following form:
```json
{ "Regex": "<regex>",
"Records": {
"A": "2.2.2.2",
"AAAA": "...",
},
}
```
Takes a regex and a set of records and registers then to the blockchain.
The DNS table in the ledger will be used by the embedded DNS server to handle requests locally.
To create a new entry, for example:
```bash
$ curl -X POST http://localhost:8080/api/dns --header "Content-Type: application/json" -d '{ "Regex": "foo.bar", "Records": { "A": "2.2.2.2" } }'
```
### DELETE
#### `/api/ledger/:bucket/:key`
Deletes the `:key` into `:bucket` inside the ledger
#### `/api/ledger/:bucket`
Deletes the `:bucket` from the ledger
# Architecture
At implementation detail, EdgeVPN uses a blockchain to store *Services UUID*, *Files UUID*, *VPN Data* into the shared ledger: It connect and creates a small blockchain between nodes.
**The blockchain is ephemeral and on-memory**. Each node keeps broadcasting it's state until it is reconciled in the blockchain. If the blockchain would get start from scratch, the hosts would re-announce and try to fill the blockchain with their data.
- Simple (KISS) interface to display network data from the blockchain
- p2p encryption between peers with libp2p
- randezvous points dynamically generated from OTP keys
- extra AES symmetric encryption on top. In case randezvous point is compromised
- blockchain is used as a sealed encrypted store for the routing table
- connections are created host to host
# :question: Is it for me? # :question: Is it for me?

18
docs/Makefile Normal file
View File

@@ -0,0 +1,18 @@
export HUGO_VERSION?=0.91.2
export HUGO_PLATFORM?=Linux-64bit
export ROOT_DIR:=$(shell dirname $(realpath $(lastword $(MAKEFILE_LIST))))
.DEFAULT_GOAL := build
.PHONY: build
build:
scripts/build.sh
.PHONY: serve
serve:
scripts/serve.sh
.PHONY: publish
publish:
scripts/publish.sh

325
docs/assets/icons/logo.svg Normal file
View File

@@ -0,0 +1,325 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
version="1.1"
id="svg2"
width="42"
height="42"
viewBox="0 0 42 42"
sodipodi:docname="logo.svg"
inkscape:version="1.1.1 (3bf5ae0d25, 2021-09-20)"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg">
<defs
id="defs6" />
<sodipodi:namedview
id="namedview4"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageshadow="2"
inkscape:pageopacity="0.0"
inkscape:pagecheckerboard="0"
showgrid="false"
inkscape:zoom="1.4199219"
inkscape:cx="23.240715"
inkscape:cy="199.65887"
inkscape:window-width="1680"
inkscape:window-height="991"
inkscape:window-x="1920"
inkscape:window-y="25"
inkscape:window-maximized="1"
inkscape:current-layer="g8" />
<g
inkscape:groupmode="layer"
inkscape:label="Image"
id="g8">
<image
width="37.374432"
height="37.374432"
preserveAspectRatio="none"
xlink:href="data:image/png;base64,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
IBLPMsO0iTeIpzdtg/M+cZgVZZX4nHjMpAsSP3Jd8fiNc8FlgWeGzXRqnjhMLBbaWGljVjQ14ini
qKrplC9kPFY5b3HWylXWvCd/YSinryxznWYECSxiCRJEKKiihDJsxGjVSbGQov24j3/I9UvkUshV
AiPHAirQILt+8D/43a2Vn5zwkkJxoPPFcT5GgK5doFFznO9jx2mcAMFn4Epv+St1YOaT9FpLix4B
fdvAxXVLU/aAyx1g8MmQTdmVgjSFfB54P6NvygL9t0DPmtdbcx+nD0CaukreAAeHwGiBstd93t3d
3tu/Z5r9/QBaDXKdod5vmwAADRppVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBi
ZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+Cjx4OnhtcG1ldGEgeG1s
bnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IlhNUCBDb3JlIDQuNC4wLUV4aXYyIj4KIDxy
ZGY6UkRGIHhtbG5zOnJkZj0iaHR0cDovL3d3dy53My5vcmcvMTk5OS8wMi8yMi1yZGYtc3ludGF4
LW5zIyI+CiAgPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIKICAgIHhtbG5zOnhtcE1NPSJo
dHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvbW0vIgogICAgeG1sbnM6c3RFdnQ9Imh0dHA6Ly9u
cy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZUV2ZW50IyIKICAgIHhtbG5zOmRjPSJo
dHRwOi8vcHVybC5vcmcvZGMvZWxlbWVudHMvMS4xLyIKICAgIHhtbG5zOkdJTVA9Imh0dHA6Ly93
d3cuZ2ltcC5vcmcveG1wLyIKICAgIHhtbG5zOnRpZmY9Imh0dHA6Ly9ucy5hZG9iZS5jb20vdGlm
Zi8xLjAvIgogICAgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIgogICB4
bXBNTTpEb2N1bWVudElEPSJnaW1wOmRvY2lkOmdpbXA6OWUyODRkYTEtMDVhZS00NGZhLTg5ODYt
ZWJmODA1MWNiZTM4IgogICB4bXBNTTpJbnN0YW5jZUlEPSJ4bXAuaWlkOjU1ZDdhNGNhLThlZDMt
NGUwMi05YjVmLWNhYjk4OTE5NDI0MyIKICAgeG1wTU06T3JpZ2luYWxEb2N1bWVudElEPSJ4bXAu
ZGlkOjk2YTkwMjk2LTgzZTAtNGI5Zi1iZGIxLWJlODZkOGM3Mjg4OCIKICAgZGM6Rm9ybWF0PSJp
bWFnZS9wbmciCiAgIEdJTVA6QVBJPSIyLjAiCiAgIEdJTVA6UGxhdGZvcm09IkxpbnV4IgogICBH
SU1QOlRpbWVTdGFtcD0iMTYzODU2NzI4NTU3MDk4OSIKICAgR0lNUDpWZXJzaW9uPSIyLjEwLjI4
IgogICB0aWZmOk9yaWVudGF0aW9uPSIxIgogICB4bXA6Q3JlYXRvclRvb2w9IkdJTVAgMi4xMCI+
CiAgIDx4bXBNTTpIaXN0b3J5PgogICAgPHJkZjpTZXE+CiAgICAgPHJkZjpsaQogICAgICBzdEV2
dDphY3Rpb249InNhdmVkIgogICAgICBzdEV2dDpjaGFuZ2VkPSIvIgogICAgICBzdEV2dDppbnN0
YW5jZUlEPSJ4bXAuaWlkOjMxZDU4YzU3LTI3ODMtNDBjYi04NzgzLWUzNTU0OWE5YzZjNCIKICAg
ICAgc3RFdnQ6c29mdHdhcmVBZ2VudD0iR2ltcCAyLjEwIChMaW51eCkiCiAgICAgIHN0RXZ0Ondo
ZW49IjIwMjEtMTItMDNUMjI6MzQ6NDUrMDE6MDAiLz4KICAgIDwvcmRmOlNlcT4KICAgPC94bXBN
TTpIaXN0b3J5PgogIDwvcmRmOkRlc2NyaXB0aW9uPgogPC9yZGY6UkRGPgo8L3g6eG1wbWV0YT4K
ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg
ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAg
ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg
ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAg
ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg
ICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg
ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg
ICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg
ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAg
ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg
ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAg
ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg
ICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg
ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg
ICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg
ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAg
ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg
ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAg
ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg
ICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAg
ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg
ICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg
ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg
IAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg
ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAg
ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg
ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAg
ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg
ICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg
ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg
ICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg
ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAg
ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg
ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAg
ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg
ICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgIAo8P3hw
YWNrZXQgZW5kPSJ3Ij8+yFTlLgAAAAZiS0dEAOAA+wD83A1epgAAAAlwSFlzAAAOxAAADsQBlSsO
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
"
id="image10"
x="5.0075426"
y="2.3861113" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 22 KiB

View File

@@ -0,0 +1,68 @@
/*
Add styles or override variables from the theme here.
*/
$google_font_name: "Oxygen";
$google_font_family: "Oxygen:300,300i,400,400i,700,700i";
$primary: #219ebc;
$secondary: #ffb703;
$dark: #023047;
//$white: #8ecae6;
$light: #8ecae6;
$enable-gradients: true;
$enable-rounded: false;
$enable-shadows: true;
/*
.td-box--primary .td-arrow-down::before, .td-box--1 .td-arrow-down::before{
border-color: #457b9d transparent transparent transparent !important;
}
.td-box--primary {
background-color: #457b9d !important;
}
.td-box--1 { background-color: #457b9d !important; }
.td-box--2 { background-color: #457b9d !important; }
.td-box--dark {
background-color: #457b9d !important;
}
.td-box--3 {
color: #f1faee !important;
background-color: #a8dadc !important;
}
.td-navbar {
background: #a8dadc !important;
}
.navbar-bg-onscroll {
background: #a8dadc !important;
}
.td-box--4 {
background-color: #f1faee !important;
}
.btn-primary {
background: #e63946 !important;
border-color: #a8dadc !important;
}
.btn-secondary {
background: #1d3557 !important;
border-color: #a8dadc !important;
}
*/

170
docs/config.toml Normal file
View File

@@ -0,0 +1,170 @@
baseURL = "https://mudler.github.io/edgevpn/docs/"
title = "EdgeVPN"
enableRobotsTXT = true
# Hugo allows theme composition (and inheritance). The precedence is from left to right.
theme = ["docsy"]
# Will give values to .Lastmod etc.
enableGitInfo = true
# Language settings
contentDir = "content/en"
defaultContentLanguage = "en"
defaultContentLanguageInSubdir = false
# Useful when translating.
enableMissingTranslationPlaceholders = true
disableKinds = ["taxonomy", "taxonomyTerm"]
# Highlighting config
pygmentsCodeFences = true
pygmentsUseClasses = false
# Use the new Chroma Go highlighter in Hugo.
pygmentsUseClassic = false
#pygmentsOptions = "linenos=table"
# See https://help.farbox.com/pygments.html
pygmentsStyle = "tango"
# Configure how URLs look like per section.
[permalinks]
blog = "/:section/:year/:month/:day/:slug/"
## Configuration for BlackFriday markdown parser: https://github.com/russross/blackfriday
[blackfriday]
plainIDAnchors = true
hrefTargetBlank = true
angledQuotes = false
latexDashes = true
# Image processing configuration.
[imaging]
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"
# Language configuration
[languages]
[languages.en]
title = "EdgeVPN"
description = "Package manager built from containers"
languageName ="English"
# Weight used for sorting.
weight = 1
#[languages.it]
#title = "EdgeVPN"
#description = "Gestore di pacchetti basato su containers"
#languageName ="Italian"
#contentDir = "content/it"
#time_format_default = "02.01.2006"
#time_format_blog = "02.01.2006"
[[menu.main]]
name = "Contribution guidelines"
weight = 50
url = "https://github.com/mudler/edgevpn/contribute"
pre = "<i class='fab fa-github'></i>"
post = ""
[markup]
[markup.goldmark]
[markup.goldmark.renderer]
unsafe = true
# Everything below this are Site Params
[params]
copyright = "Ettore Di Giacinto"
privacy_policy = "https://policies.google.com/privacy"
# First one is picked as the Twitter card image if not set on page.
# images = ["images/project-illustration.png"]
# Menu title if your navbar has a versions selector to access old versions of your site.
# This menu appears only if you have at least one [params.versions] set.
version_menu = "Releases"
# Repository configuration (URLs for in-page links to opening issues and suggesting changes)
github_repo = "https://github.com/mudler/edgevpn"
# An optional link to a related project repo. For example, the sibling repository where your product code lives.
github_project_repo = "https://github.com/mudler/edgevpn"
# Specify a value here if your content directory is not in your repo's root directory
github_subdir = "docs"
# Google Custom Search Engine ID. Remove or comment out to disable search.
#gcs_engine_id = "011737558837375720776:fsdu1nryfng"
# Enable Algolia DocSearch
algolia_docsearch = false
# Enable Lunr.js offline search
offlineSearch = true
# User interface configuration
[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 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
navbar_logo = true
# Set to true to disable the About link in the site footer
footer_about_disable = false
# Adds a H2 section titled "Feedback" to the bottom of each doc. The responses are sent to Google Analytics as events.
# 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.
[params.ui.feedback]
enable = true
# 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/EdgeVPN-lab/docs/issues/new">tell us how we can improve</a>.'
no = 'Sorry to hear that. Please <a href="https://github.com/EdgeVPN-lab/docs/issues/new">tell us how we can improve</a>.'
[params.links]
# End user relevant links. These will show up on left side of footer and in the community page if you have one.
# [[params.links.user]]
# name = "User mailing list"
# url = "https://example.org/mail"
# icon = "fa fa-envelope"
# desc = "Discussion and help from your fellow users"
# [[params.links.user]]
# name ="Twitter"
# url = "https://example.org/twitter"
# icon = "fab fa-twitter"
# desc = "Follow us on Twitter to get the latest news!"
# [[params.links.user]]
# name = "Stack Overflow"
# url = "https://example.org/stack"
# icon = "fab fa-stack-overflow"
# desc = "Practical questions and curated answers"
# Developer relevant links. These will show up on right side of footer and in the community page if you have one.
[[params.links.developer]]
name = "GitHub"
url = "https://github.com/mudler/edgevpn"
icon = "fab fa-github"
desc = "Development takes place here!"
[[params.links.user]]
name = "GitHub Discussions"
url = "https://github.com/mudler/edgevpn/discussions"
icon = "fab fa-github"
desc = "Discussion and help from your fellow users"
#[[params.links.developer]]
# name = "Slack"
# url = ""
# icon = "fab fa-slack"
# desc = "Join us on Slack!"
# [[params.links.developer]]
# name = "Developer mailing list"
# url = "https://example.org/mail"
# icon = "fa fa-envelope"
# desc = "Discuss development issues around the project"

114
docs/content/en/_index.html Normal file
View File

@@ -0,0 +1,114 @@
+++
title = "EdgeVPN"
linkTitle = "edgevpn"
+++
{{< blocks/cover title="EdgeVPN" image_anchor="top" height="full" color="orange" >}}
<div class="mx-auto">
<a class="btn btn-lg btn-primary mr-3 mb-4" href="{{< relref "/docs" >}}">
Documentation <i class="fas fa-arrow-alt-circle-right ml-2"></i>
</a>
<a class="btn btn-lg btn-secondary mr-3 mb-4" href="https://github.com/mudler/edgevpn/releases">
Download <i class="fab fa-github ml-2 "></i>
</a>
<p class="lead mt-5">Create Decentralized private networks</p>
<hr>
</div>
{{< /blocks/cover >}}
{{% blocks/lead color="primary" %}}
EdgeVPN uses <a href="https://github.com/libp2p/go-libp2p" target="_blank">go-libp2p</a> to create private decentralized networks.
{{% /blocks/lead %}}
{{< blocks/section color="dark" >}}
{{% blocks/feature icon="fa-network-wired" title="VPN" %}}
Join nodes via shared secrets
{{% /blocks/feature %}}
{{% blocks/feature icon="fa-dice-d20" title="Blockchain" %}}
A Lightweight, small blockchain in your pocket.
{{% /blocks/feature %}}
{{% blocks/feature icon="fa-ethernet" title="DHCP and DNS" %}}
Automatically decentralized coordinated IP assignment and Embedded DNS server to resolve domains from a decentralized domain registry
{{% /blocks/feature %}}
{{< /blocks/section >}}
{{< blocks/section color="dark" >}}
{{% blocks/feature icon="fa-file-upload" title="Files" %}}
Send and receive files between hosts also outside the VPN
{{% /blocks/feature %}}
{{% blocks/feature icon="fab fa-project-diagram" title="Services" %}}
Expose and route TCP services over the p2p network also without the VPN
{{% /blocks/feature %}}
{{% blocks/feature icon="fa-cogs" title="API" %}}
Simple REST API with an embedded and simple UI with batteries included to operate the network Blockchain.
{{% /blocks/feature %}}
{{< /blocks/section >}}
{{< blocks/section >}}
<div class="col">
<h1 class="text-center">
Graphical interface
</h1>
<center>
<a class="btn btn-md btn-primary mr-3 mb-4" href="{{< relref "/docs/getting-started/api/" >}}">
WebUI
<i class="fab fa-globe ml-2 "></i></a>
<a class="btn btn-md btn-primary mr-3 mb-4" href="{{< relref "/docs/getting-started/gui/" >}}">GUI
<i class="fab 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
</center>
</div>
<div class="col">
<img width=400 src="https://user-images.githubusercontent.com/2420543/139602704-15bd342f-2db2-4a3b-b1c7-4dc7be27c0f4.png" class="img-fluid">
<img width=300 src="https://user-images.githubusercontent.com/2420543/147854909-a223a7c1-5caa-4e90-b0ac-0ae04dc0949d.png" class="img-fluid">
</div>
{{< /blocks/section >}}
{{< blocks/section color="white">}}
{{% blocks/feature icon="f" %}}
<a class="btn btn-lg btn-secondary mr-3 mb-4" href="https://github.com/mudler/edgevpn/releases">
Download <i class="fab fa-github ml-2 "></i>
</a>
{{% /blocks/feature %}}
{{% blocks/feature icon="fab fa-github" title="Contributions welcome!" url="https://github.com/mudler/edgevpn" %}}
If you like to play with code, check out our issues that are marked as ["good first issue"](https://github.com/mudler/edgevpn/issues?q=is%3Aissue+is%3Aopen+label%3A%22good+first+issue%22) and open a [Pull Request](https://github.com/mudler/edgevpn/pulls) on **GitHub**.
New users are always welcome, and have fun!
{{% /blocks/feature %}}
{{% blocks/feature icon="f" %}}
<a class="btn btn-lg btn-primary mr-3 mb-4" href="{{< relref "/docs" >}}">
Documentation <i class="fas fa-arrow-alt-circle-right ml-2"></i>
</a>
{{% /blocks/feature %}}
{{< /blocks/section >}}

View File

@@ -0,0 +1,8 @@
---
title: Community
menu:
main:
weight: 40
---
<!--add blocks of content here to add more sections to the community page -->

View File

@@ -0,0 +1,44 @@
---
title: "Architecture"
linkTitle: "Architecture"
weight: 2
description: >
EdgeVPN overview
resources:
- src: "**edgevpn_*.png"
---
## Introduction
EdgeVPN uses [libp2p](https://github.com/libp2p/go-libp2p) to establish a decentralized, asymmetrically encrypted gossip network which propagate a (symmetrically encrypted) blockchain states between nodes.
The blockchain is lightweight as:
- There is no PoW mechanism
- It is in memory only, no DAG, CARv2, or GraphSync protocol - the usage is restricted to hold metadata, and not real addressable content
EdgeVPN uses the blockchain to store Services UUID, Files UUID, VPN and other metadata (such as DNS records, IP, etc.) and co-ordinate events between the nodes of the network. Besides, it is used as a mechanism of protection: if nodes are not part of the blockchain, they can't talk to each other.
The blockchain is ephemeral and on-memory, optionally can be stored on disk.
Each node keeps broadcasting it's state until it is reconciled in the blockchain. If the blockchain would get start from scratch, the hosts would re-announce and try to fill the blockchain with their data.
- Simple (KISS) interface to display network data from the blockchain
- asymmetric p2p encryption between peers with libp2p
- randezvous points dynamically generated from OTP keys
- extra AES symmetric encryption on top. In case randezvous point is compromised
- blockchain is used as a sealed encrypted store for the routing table
- connections are created host to host and encrypted asymmetrically
### Connection bootstrap
Network is bootstrapped with libp2p and is composed of 3 phases:
{{< imgproc edevpn_bootstrap.png Fit "1200x550" >}}
{{< /imgproc >}}
In the first phase, nodes do discover each others via DHT and a randevouz secret which is automatically generated via OTP.
Once peers know about each other a gossip network is established, where the nodes exchange a blockchain over an p2p e2e encrypted channel. The blockchain is sealed with a symmetric key which is rotated via OTP that is shared between the nodes.
At that point a blockchain and an API is established between the nodes, and optionally start the VPN binding on the tun/tap device.

Binary file not shown.

After

Width:  |  Height:  |  Size: 63 KiB

View File

@@ -0,0 +1,16 @@
---
title: "Overview"
linkTitle: "Overview"
weight: 1
description: >
EdgeVPN overview
---
EdgeVPN have a simplified model of a blockchain embedded. The model is actually simplified on purpose as the blockchain is used to store merely network and services metadata and not transaction, or content addressable network.
The only data stored in the blockchain is:
- Network Peer IDs, Service IDs, File IDs
- Healthchecks, DNS records and IP allocation
However, the ledger is freely accessible via API, allowing for external coordination to use the blockchain mechanism as a shared memory access (which can be optionally persisted on disk).

View File

@@ -0,0 +1,54 @@
---
title: "DNS"
linkTitle: "DNS"
weight: 20
date: 2017-01-05
description: >
Embedded DNS server documentation
---
## DNS Server
Note: Experimental feature!
A DNS Server is available but disabled by default.
The DNS server will resolve DNS queries using the blockchain as a record and will forward unknown domains by default.
It can be enabled by specifying a listening address with `--dns`. For example, to bind to default `53` port locally, run in the console:
```bash
edgevpn --dns "127.0.0.1:53"
```
To turn off dns forwarding, specify `--dns-forwarder=false`. Optionally a list of DNS servers can be specified multiple times with `--dns-forward-server`.
The dns subcommand has several options:
```
--dns value DNS listening address. Empty to disable dns server [$DNSADDRESS]
--dns-forwarder Enables dns forwarding [$DNSFORWARD]
--dns-cache-size value DNS LRU cache size (default: 200) [$DNSCACHESIZE]
--dns-forward-server value List of DNS forward server (default: "8.8.8.8:53", "1.1.1.1:53") [$DNSFORWARDSERVER]
```
Nodes of the VPN can start a local DNS server which will resolve the routes stored in the chain.
For example, to add DNS records, use the API as such:
```bash
$ curl -X POST http://localhost:8080/api/dns --header "Content-Type: application/json" -d '{ "Regex": "foo.bar", "Records": { "A": "2.2.2.2" } }'
```
The `/api/dns` routes accepts `POST` requests as `JSON` of the following form:
```json
{ "Regex": "<regex>",
"Records": {
"A": "2.2.2.2",
"AAAA": "...",
},
}
```
Note, `Regex` accepts regexes which will match the DNS requests received and resolved to the specified entries.

View File

@@ -0,0 +1,26 @@
---
title: "Sending and receiving files"
linkTitle: "File transfer"
weight: 20
date: 2017-01-05
description: >
Send and receive files between p2p nodes
---
## Sending and receiving files
EdgeVPN can be used to send and receive files between hosts via p2p with the `file-send` and `file-receive` subcommand.
Sending and receiving files, as services, don't establish a VPN connection.
### Sending
```bash
$ edgevpn file-send 'unique-id' '/src/path'
```
### Receiving
```bash
$ edgevpn file-receive 'unique-id' '/dst/path'
```

View File

@@ -0,0 +1,31 @@
---
title: "Tunnel connections"
linkTitle: "Tunnelling"
weight: 1
description: >
EdgeVPN network services for tunnelling TCP services
---
## Forwarding a local connection
EdgeVPN can also be used to expose local(or remote) services without establishing a VPN and allocating a local tun/tap device, similarly to `ngrok`.
### Exposing a service
If you are used to how Local SSH forwarding works (e.g. `ssh -L 9090:something:remote <my_node>`), EdgeVPN takes a similar approach.
A Service is a generalized TCP service running in a host (also outside the network). For example, let's say that we want to expose a SSH server inside a LAN.
To expose a service to your EdgeVPN network then:
```bash
$ edgevpn service-add "MyCoolService" "127.0.0.1:22"
```
To reach the service, EdgeVPN will setup a local port and bind to it, it will tunnel the traffic to the service over the VPN, for e.g. to bind locally to `9090`:
```bash
$ edgevpn service-connect "MyCoolService" "127.0.0.1:9090"
```
with the example above, 'sshing into `9090` locally would forward to `22`.

View File

@@ -0,0 +1,71 @@
---
title: "Token"
linkTitle: "Token"
weight: 3
description: >
The edgevpn network token
---
A network token represent the network which edgevpn attempts to establish a connection among peers.
A token is created by encoding in base64 a network configuration.
## Generating tokens
To generate a network token, run in the console:
```
edgevpn -b -g
```
This will print out in screen a base64 token which is ready to be shared on nodes that you wish to join on the same network.
## Generating configuration files
EdgeVPN can read both tokens and network configuration files.
To generate a configuration file, run in the console:
```
edgevpn -g
```
To turn out a config to a token, you must encode in base64:
```
TOKEN=$(edgevpn -g | base64 -w0)
```
which is equivalent to run `edgevpn -g -b`.
## Anatomy of a configuration file
A typical configuration file looks like the following:
```yaml
otp:
dht:
interval: 9000
key: LHKNKT6YZYQGGY3JANGXMLJTHRH7SW3C
length: 32
crypto:
interval: 9000
key: SGIB6NYJMSRJF2AJDGUI2NDB5LBVCPLS
length: 32
room: ubONSBFkdWbzkSBTglFzOhWvczTBQJOR
rendezvous: exoHOajMYMSPrHhevAEEjnCHLssFfzfT
mdns: VoZfePlTchbSrdmivaqaOyQyEnTMlugi
max_message_size: 20971520
```
The values can be all tweaked to your needs.
EdgeVPN uses an otp mechanism to decrypt blockchain messages between the nodes and to discover nodes from DHT, this is in order to prevent bruteforce attacks and avoid bad actors listening on the protocol.
See [the Architecture section]() for more information.
- The OTP keys (`otp.crypto.key`) rotates the cipher key used to encode/decode the blockchain messages. The interval of rotation can be set for both DHT and the Blockchain messages. The length is the cipher key length (AES-256 by default) used by the sealer to decrypt/encrypt messages.
- The DHT OTP keys (`otp.dht.key`) rotates the discovery key used during DHT node discovery. A key is generated and used with OTP at defined intervals to scramble potential listeners.
- The `room` is a unique ID which all the nodes will subscribe to. It is automatically generated
- Optionally the OTP mechanism can be disabled by commenting the `otp` block. In this case the static DHT rendezvous will be `rendezvous`
- The `mdns` discovery doesn't have any OTP rotation, so a unique identifier must be provided.
- Here can be defined the max message size accepted for the blockchain messages with `max_message_size` (in bytes)

View File

@@ -0,0 +1,5 @@
---
title: "Concepts"
linkTitle: "Concepts"
weight: 20
---

View File

@@ -0,0 +1,48 @@
---
title: "Getting Started"
linkTitle: "Getting Started"
weight: 1
description: >
First steps with EdgeVPN
---
## Get EdgeVPN
Prerequisites: No dependencies. EdgeVPN releases are statically compiled.
### From release
Just grab a release from [the release page on GitHub](https://github.com/mudler/edgevpn/releases). The binaries are statically compiled.
### Building EdgeVPN from source
Requirements:
- [Golang](https://golang.org/) installed in your system.
- make
```bash
$> git clone https://github.com/mudler/edgevpn
$> cd edgevpn
$> go build
```
### First VPN
Let's create our first vpn now and start it:
```bash
$> EDGEVPNTOKEN=$(edgevpn -b -g)
$> edgevpn --dhcp --api
```
That's it!
You can now access the web interface on [http://localhost:8080](http://localhost:8080).
To join new nodes in the network, simply copy the `EDGEVPNTOKEN` and use it to start edgevpn in other nodes:
```bash
$> EDGEVPNTOKEN=<token_generated_before> edgevpn --dhcp
```

View File

@@ -0,0 +1,116 @@
---
title: "webUI and API"
linkTitle: "webUI and API"
weight: 1
description: >
Query the network status and operate the ledger with the built-in API
---
The API has a simple webUI embedded to display network informations.
To access the web interface, run in the console:
```bash
$ edgevpn api
```
with either a `EDGEVPNCONFIG` or `EDGEVPNTOKEN`.
Dashboard | Machine index
:-------------------------:|:-------------------------:
![Screenshot 2021-10-31 at 00-12-16 EdgeVPN - Machines index](https://user-images.githubusercontent.com/2420543/139602703-f04ac4cb-b949-498c-a23a-0ce8deb036f9.png) | ![Screenshot 2021-10-31 at 23-03-26 EdgeVPN - Machines index](https://user-images.githubusercontent.com/2420543/139602704-15bd342f-2db2-4a3b-b1c7-4dc7be27c0f4.png)
Services | File index
:-------------------------:|:-------------------------:
![Screenshot 2021-10-31 at 23-03-44 EdgeVPN - Services index](https://user-images.githubusercontent.com/2420543/139602706-6050dfb7-2ef1-45b2-a768-a00b9de60ba1.png) | ![Screenshot 2021-10-31 at 23-03-59 EdgeVPN - Files index](https://user-images.githubusercontent.com/2420543/139602707-1d29f9b4-972c-490f-8015-067fbf5580f2.png)
Users | Blockchain index
:-------------------------:|:-------------------------:
![Screenshot 2021-10-31 at 23-04-12 EdgeVPN - Users connected](https://user-images.githubusercontent.com/2420543/139602708-d102ae09-12f2-4c4c-bcc2-d8f4366355e0.png) | ![Screenshot 2021-10-31 at 23-04-20 EdgeVPN - Blockchain index](https://user-images.githubusercontent.com/2420543/139602709-244960bb-ea1d-413b-8c3e-8959133427ae.png)
In API mode, EdgeVPN will connect to the network without routing any packet, and without setting up a VPN interface.
By default edgevpn will listen on the `8080` port. See `edgevpn api --help` for the available options
API can also be started together with the vpn with `--api`.
## API endpoints
### GET
#### `/api/users`
Returns the users connected to services in the blockchain
#### `/api/services`
Returns the services running in the blockchain
#### `/api/dns`
Returns the domains registered in the blockchain
#### `/api/machines`
Returns the machines connected to the VPN
#### `/api/blockchain`
Returns the latest available blockchain
#### `/api/ledger`
Returns the current data in the ledger
#### `/api/ledger/:bucket`
Returns the current data in the ledger inside the `:bucket`
#### `/api/ledger/:bucket/:key`
Returns the current data in the ledger inside the `:bucket` at given `:key`
### PUT
#### `/api/ledger/:bucket/:key/:value`
Puts `:value` in the ledger inside the `:bucket` at given `:key`
### POST
#### `/api/dns`
The endpoint accept a JSON payload of the following form:
```json
{ "Regex": "<regex>",
"Records": {
"A": "2.2.2.2",
"AAAA": "...",
},
}
```
Takes a regex and a set of records and registers then to the blockchain.
The DNS table in the ledger will be used by the embedded DNS server to handle requests locally.
To create a new entry, for example:
```bash
$ curl -X POST http://localhost:8080/api/dns --header "Content-Type: application/json" -d '{ "Regex": "foo.bar", "Records": { "A": "2.2.2.2" } }'
```
### DELETE
#### `/api/ledger/:bucket/:key`
Deletes the `:key` into `:bucket` inside the ledger
#### `/api/ledger/:bucket`
Deletes the `:bucket` from the ledger

View File

@@ -0,0 +1,80 @@
---
title: "CLI"
linkTitle: "CLI"
weight: 1
description: >
Command line interface
---
To start the VPN, simply run `edgevpn` without any argument.
An example of running edgevpn on multiple hosts:
```bash
# on Node A
$ EDGEVPNTOKEN=.. edgevpn --address 10.1.0.11/24
# on Node B
$ EDGEVPNTOKEN=.. edgevpn --address 10.1.0.12/24
# on Node C ...
$ EDGEVPNTOKEN=.. edgevpn --address 10.1.0.13/24
...
```
... and that's it! the `--address` is a _virtual_ unique IP for each node, and it is actually the ip where the node will be reachable to from the vpn. You can assign IPs freely to the nodes of the network, while you can override the default `edgevpn0` interface with `IFACE` (or `--interface`)
*Note*: It might take up time to build the connection between nodes. Wait at least 5 mins, it depends on the network behind the hosts.
The VPN takes several options, below you will find a reference for the most important features:
## Generate a network token
EdgeVPN works by generating tokens (or network configuration files) that are shared between different machines.
Every token is unique and identifies the network itself: there is no central server setup, and no IP address is specified in config files.
To generate a new network token, just run `edgevpn -g -b`:
```bash
$ edgevpn -g -b
b3RwOgogIGRodDoKICAgIGludGVydmFsOiA5MDAwCiAgICBrZXk6IDRPNk5aUUMyTzVRNzdKRlJJT1BCWDVWRUkzRUlKSFdECiAgICBsZW5ndGg6IDMyCiAgY3J5cHRvOgogICAgaW50ZXJ2YWw6IDkwMDAKICAgIGtleTogN1hTUUNZN0NaT0haVkxQR0VWTVFRTFZTWE5ORzNOUUgKICAgIGxlbmd0aDogMzIKcm9vbTogWUhmWXlkSUpJRlBieGZDbklLVlNmcGxFa3BhVFFzUk0KcmVuZGV6dm91czoga1hxc2VEcnNqbmFEbFJsclJCU2R0UHZGV0RPZGpXd0cKbWRuczogZ0NzelJqZk5XZEFPdHhubm1mZ3RlSWx6Zk1BRHRiZGEKbWF4X21lc3NhZ2Vfc2l6ZTogMjA5NzE1MjAK
```
A network token needs to be specified for all later interactions with edgevpn, in order to connect and establish a network connection between peers.
For example, to start `edgevpn` in API mode:
```bash
$ edgevpn api --token <token> # or alternatively using $EDGEVPNTOKEN
INFO edgevpn Copyright (C) 2021-2022 Ettore Di Giacinto
This program comes with ABSOLUTELY NO WARRANTY.
This is free software, and you are welcome to redistribute it
under certain conditions.
INFO Version: v0.8.4 commit:
INFO Starting EdgeVPN network
INFO Node ID: 12D3KooWRW4RXSMAh7CTRsTjX7iEjU6DEU8QKJZvFjSosv7zCCeZ
INFO Node Addresses: [/ip6/::1/tcp/38637 /ip4/192.168.1.234/tcp/41607 /ip4/127.0.0.1/tcp/41607]
INFO Bootstrapping DHT
⇨ http server started on [::]:8080
```
Alternatively a network configuration file can be specified with `--config` or `EDGEVPNCONFIG`.
As the token is a network configuration file encoded in base64, using a token or a config is equivalent:
```bash
$ EDGEVPNTOKEN=$(edgevpn -g | tee config.yaml | base64 -w0)
```
## API
While starting in VPN mode, it is possible _also_ to start in API mode by specifying `--api`.
## DHCP
Note: Experimental feature!
Automatic IP negotiation is available since version `0.8.1`.
DHCP can be enabled with `--dhcp` and `--address` can be omitted. If an IP is specfied with `--address` it will be the default IP.

View File

@@ -0,0 +1,16 @@
---
title: "GUI"
linkTitle: "GUI"
weight: 1
description: >
GUI app
---
A Desktop GUI application (alpha) for Linux is available [here](https://github.com/mudler/edgevpn-gui).
Note the GUI doesn't require the CLI to be installed. It will automatically prompt to download the latest available version, and offer a version management option.
Dashboard | Connections index
:-------------------------:|:-------------------------:
![edgevpn-gui-2](https://user-images.githubusercontent.com/2420543/147854909-a223a7c1-5caa-4e90-b0ac-0ae04dc0949d.png) | ![edgevpn-3](https://user-images.githubusercontent.com/2420543/147854904-09d96991-8752-421a-a301-8f0bdd9d5542.png)
![edgevpn-gui](https://user-images.githubusercontent.com/2420543/147854907-1e4a4715-3181-4dc2-8bc0-d052b3bf46d3.png) |

35
docs/content/en/docs/_index.md Executable file
View File

@@ -0,0 +1,35 @@
---
title: "Documentation"
linkTitle: "Documentation"
weight: 20
menu:
main:
weight: 20
---
EdgeVPN uses libp2p to build private decentralized networks that can be accessed via shared secrets.
It can:
- **Create a VPN** :
- Secure VPN between p2p peers
- Automatically assign IPs to nodes
- Embedded tiny DNS server to resolve internal/external IPs
- **Act as a reverse Proxy**
- Share a tcp service like you would do with `ngrok` to the p2p network nodes without establishing a VPN connection
- **Send files via p2p**
- Send files over p2p between nodes without establishing a VPN connection.
- **Be used as a library**
- Plug a distributed p2p ledger easily in your golang code!
Check out the docs below for further example and reference, have a look at our [getting started guide](/getting-started), the [cli interface](/docs/getting-started/cli), [gui desktop app](/docs/getting-started/gui), and the embedde [webUI](/docs/getting-started/webui)/[api](/docs/getting-started/api).
| WebUI | [Desktop](https://github.com/mudler/edgevpn-gui) |
| ------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------ |
| ![img](https://user-images.githubusercontent.com/2420543/139602703-f04ac4cb-b949-498c-a23a-0ce8deb036f9.png) | ![](https://user-images.githubusercontent.com/2420543/147854909-a223a7c1-5caa-4e90-b0ac-0ae04dc0949d.png) |

View File

@@ -0,0 +1,58 @@
---
title: "Contributing"
linkTitle: "Contribution guidelines"
weight: 159
---
## Contributing to EdgeVPN
Contribution guidelines for the EdgeVPN project are on the [Github repository](https://github.com/mudler/edgevpn/blob/master/CONTRIBUTING.md). Here you can find some heads up for contributing to the documentation website.
## Contributing to the Docs website
### We Develop with Github
We use [github to host code](https://github.com/mudler/edgevpn), to track issues and feature requests, as well as accept pull requests.
We use [Hugo](https://gohugo.io/) to format and generate our website, the
[Docsy](https://github.com/google/docsy) theme for styling and site structure,
and Github Actions to manage the deployment of the site.
Hugo is an open-source static site generator that provides us with templates,
content organisation in a standard directory structure, and a website generation
engine. You write the pages in Markdown (or HTML if you want), and Hugo wraps them up into a website.
All submissions, including submissions by project members, require review. We
use GitHub pull requests for this purpose. Consult
[GitHub Help](https://help.github.com/articles/about-pull-requests/) for more
information on using pull requests.
### Any contributions you make will be under the Software License of the repository
In short, when you submit code changes, your submissions are understood to be under the same License that covers the project. Feel free to contact the maintainers if that's a concern.
### Updating a single page
If you've just spotted something you'd like to change while using the docs, Docsy has a shortcut for you:
1. Click **Edit this page** in the top right hand corner of the page you want to modify.
2. If you don't already have an up to date fork of the project repo, you are prompted to get one - click **Fork this repository and propose changes** or **Update your Fork** to get an up to date version of the project to edit. The appropriate page in your fork is displayed in edit mode.
### Quick start with a local checkout
Here's a quick guide to updating the docs with a git local checkout. It assumes you're familiar with the
GitHub workflow and you're happy to use the automated preview of your doc
updates:
1. Fork the [the repo](https://github.com/mudler/edgevpn) on GitHub.
2. Make your changes, if are related to docs
to see the preview cd into `docs` and run `make serve`, then browse to [localhost:1313](http://localhost:1313)
3. If you're not yet ready for a review, add "WIP" to the PR name to indicate
it's a work in progress.
4. Continue updating your doc and pushing your changes until you're happy with
the content.
5. When you're ready for a review, add a comment to the PR, and remove any
"WIP" markers.
6. When you are satisfied send a pull request (PR).
### License
By contributing, you agree that your contributions will be licensed under the project Licenses.

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 MiB

View File

@@ -0,0 +1,4 @@
---
type: "search-index"
url: "index.json"
---

View File

@@ -0,0 +1,6 @@
---
title: Search Results
layout: search
---

10
docs/layouts/404.html Normal file
View File

@@ -0,0 +1,10 @@
{{ define "main"}}
<main id="main">
<div>
<h1 id="title">Not found</h1>
<p>Oops! This page doesn't exist. Try going back to our <a href="{{ "/" | relURL }}">home page</a>.</p>
<p>You can learn how to make a 404 page like this in <a href="https://gohugo.io/templates/404/">Custom 404 Pages</a>.</p>
</div>
</main>
{{ end }}

View File

@@ -0,0 +1,9 @@
{{/* https://github.com/haideralipunjabi/hugo-shortcodes/tree/master/github */}}
{{ $dataJ := getJSON "https://api.github.com/repos/" (.Get "repo") "/contents/" (.Get "file") }}
{{ $con := base64Decode $dataJ.content }}
{{ highlight $con (.Get "lang") (.Get "options") }}
<small> <i class='fab fa-github'></i> <i>Complete source code: <a target=_blank href="{{ print "https://github.com/" ( .Get "repo" ) "/blob/master/" (.Get "file" ) }}">{{ print "https://github.com/" ( .Get "repo" ) "/blob/master/" (.Get "file" ) }}</a></i> </small>
<hr>

1525
docs/package-lock.json generated Normal file

File diff suppressed because it is too large Load Diff

6
docs/package.json Normal file
View File

@@ -0,0 +1,6 @@
{
"devDependencies": {
"autoprefixer": "^10.4.2",
"postcss-cli": "^9.1.0"
}
}

28
docs/scripts/build.sh Executable file
View File

@@ -0,0 +1,28 @@
#!/bin/bash
set -e
BASE_URL="${BASE_URL:-https://mudler.github.io/edgevpn/}"
binpath="${ROOT_DIR}/bin"
publicpath="${ROOT_DIR}/public"
if [ ! -e "${binpath}/hugo" ];
then
[[ ! -d "${binpath}" ]] && mkdir -p "${binpath}"
wget https://github.com/gohugoio/hugo/releases/download/v"${HUGO_VERSION}"/hugo_extended_"${HUGO_VERSION}"_"${HUGO_PLATFORM}".tar.gz -O "$binpath"/hugo.tar.gz
tar -xvf "$binpath"/hugo.tar.gz -C "${binpath}"
rm -rf "$binpath"/hugo.tar.gz
chmod +x "$binpath"/hugo
fi
rm -rf "${publicpath}" || true
[[ ! -d "${publicpath}" ]] && mkdir -p "${publicpath}"
# Note: It needs
# sudo npm install -g postcss-cli
#
npm install -D --save autoprefixer
npm install -D --save postcss-cli
HUGO_ENV="production" "${binpath}/hugo" --gc -b "${BASE_URL}" -s "${ROOT_DIR}" -d "${publicpath}"

14
docs/scripts/publish.sh Executable file
View File

@@ -0,0 +1,14 @@
#!/bin/bash
set -e
"${ROOT_DIR}"/scripts/build.sh
git branch -D gh-pages || true
git checkout --orphan gh-pages
git rm -rf .
cp -rfv public/* ./
rm -rf public/

14
docs/scripts/serve.sh Executable file
View File

@@ -0,0 +1,14 @@
#!/bin/bash
set -e
binpath="${ROOT_DIR}/bin"
if [ ! -e "${binpath}/hugo" ];
then
[[ ! -d "${binpath}" ]] && mkdir -p "${binpath}"
wget https://github.com/gohugoio/hugo/releases/download/v"${HUGO_VERSION}"/hugo_extended_"${HUGO_VERSION}"_"${HUGO_PLATFORM}".tar.gz -O "$binpath"/hugo.tar.gz
tar -xvf "$binpath"/hugo.tar.gz -C "${binpath}"
rm -rf "$binpath"/hugo.tar.gz
chmod +x "$binpath"/hugo
fi
"${binpath}/hugo" --baseURL="$BASE_URL" -s "$ROOT_DIR" serve

1
docs/themes/docsy vendored Submodule

Submodule docs/themes/docsy added at 033225e517

View File

@@ -2,8 +2,17 @@
set -e set -e
set -o noglob set -o noglob
github_version() {
set +e
curl -s https://api.github.com/repos/mudler/edgevpn/releases/latest | \
grep tag_name | \
awk '{ print $2 }' | \
sed -e 's/\"//g' -e 's/,//g' || echo "v0.8.5"
set -e
}
DOWNLOADER=${DOWNLOADER:-curl} DOWNLOADER=${DOWNLOADER:-curl}
VERSION=${VERSION:-v0.8.5} VERSION=${VERSION:-$(github_version)}
info() info()
{ {