From 5d6cdac153d7b2181fee67a61838c832eb6468fe Mon Sep 17 00:00:00 2001
From: Bernd Storath <999999bst@gmail.com>
Date: Wed, 2 Apr 2025 12:01:53 +0200
Subject: [PATCH] improve docs
---
README.md | 32 +---
docs/content/advanced/api.md | 35 +++-
.../advanced/config/optional-config.md | 2 +-
.../advanced/config/unattended-setup.md | 2 +-
docs/content/advanced/metrics/prometheus.md | 39 +++-
docs/content/examples/tutorials/adguard.md | 4 +-
.../examples/tutorials/auto-updates.md | 44 ++++-
.../examples/tutorials/basic-installation.md | 23 +--
docs/content/examples/tutorials/caddy.md | 4 +-
docs/content/examples/tutorials/docker-run.md | 4 +-
docs/content/examples/tutorials/dockerless.md | 4 +-
docs/content/examples/tutorials/nginx.md | 5 -
.../tutorials/{podman.md => podman-nft.md} | 14 +-
docs/content/examples/tutorials/traefik.md | 181 +++++++++++++++++-
docs/content/faq.md | 97 ++++++++++
docs/content/getting-started.md | 14 +-
16 files changed, 433 insertions(+), 71 deletions(-)
delete mode 100644 docs/content/examples/tutorials/nginx.md
rename docs/content/examples/tutorials/{podman.md => podman-nft.md} (82%)
create mode 100644 docs/content/faq.md
diff --git a/README.md b/README.md
index 3f389b8b..cb729232 100644
--- a/README.md
+++ b/README.md
@@ -5,7 +5,7 @@
[](https://github.com/wg-easy/wg-easy/stargazers)
[](LICENSE)
[](https://github.com/wg-easy/wg-easy/releases/latest)
-[](https://github.com/wg-easy/wg-easy/pkgs/container/wg-easy)
+[](https://github.com/wg-easy/wg-easy/pkgs/container/wg-easy)
@@ -51,35 +51,18 @@ You have found the easiest way to install & manage WireGuard on any Linux host!
- [Getting Started](https://wg-easy.github.io/wg-easy/latest/getting-started/)
- [Basic Installation](https://wg-easy.github.io/wg-easy/latest/examples/tutorials/basic-installation/)
- [Caddy](https://wg-easy.github.io/wg-easy/latest/examples/tutorials/caddy/)
-- [Nginx](https://wg-easy.github.io/wg-easy/latest/examples/tutorials/nginx/)
- [Traefik](https://wg-easy.github.io/wg-easy/latest/examples/tutorials/traefik/)
-- [Podman](https://wg-easy.github.io/wg-easy/latest/examples/tutorials/podman/)
+- [Podman](https://wg-easy.github.io/wg-easy/latest/examples/tutorials/podman-nft/)
- [AdGuard Home](https://wg-easy.github.io/wg-easy/latest/examples/tutorials/adguard/)
> [!NOTE]
> If you want to migrate from the old version to the new version, you can find the migration guide here: [Migration Guide](https://wg-easy.github.io/wg-easy/latest/advanced/migrate/)
-## Requirements
-
-- A host with a kernel that supports WireGuard (all modern kernels).
-- A host with Docker installed.
-
-## Versions
-
-> 💡 We follow semantic versioning (semver)
-
-We offer multiple Docker image tags to suit your needs. The table below is in a particular order, with the first tag being the most recommended:
+## Installation
-| tag | Branch | Example | Description |
-| ------------- | ---------------------------------------------------------- | ------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------ |
-| `15` | latest minor for that major tag | `ghcr.io/wg-easy/wg-easy:15` | latest features for specific major versions, no breaking changes |
-| `latest` | latest tag | `ghcr.io/wg-easy/wg-easy:latest` or `ghcr.io/wg-easy/wg-easy` | stable as possible get bug fixes quickly when needed, see Releases for more information. |
-| `15.0` | latest patch for that minor tag | `ghcr.io/wg-easy/wg-easy:15.0` | latest patches for specific minor version |
-| `15.0.0` | specific tag | `ghcr.io/wg-easy/wg-easy:15.0.0` | specific release, don't use this as this will not get updated |
-| `nightly` | [`master`](https://github.com/wg-easy/wg-easy/tree/master) | `ghcr.io/wg-easy/wg-easy:nightly` | mostly unstable gets frequent package and code updates, deployed against [`master`](https://github.com/wg-easy/wg-easy/tree/master). |
-| `development` | pull requests | `ghcr.io/wg-easy/wg-easy:development` | used for development, testing code from PRs before landing into [`master`](https://github.com/wg-easy/wg-easy/tree/master). |
+This is a quick start guide to get you up and running with WireGuard Easy.
-## Installation
+For a more detailed installation guide, please refer to the [Getting Started](https://wg-easy.github.io/wg-easy/latest/getting-started/) page.
### 1. Install Docker
@@ -96,14 +79,13 @@ And log in again.
The easiest way to run WireGuard Easy is with Docker Compose.
-Just download [`docker-compose.yml`](docker-compose.yml), make necessary adjustments and
-execute `sudo docker compose up -d`.
+Just download [`docker-compose.yml`](docker-compose.yml) and execute `sudo docker compose up -d`.
Now setup a reverse proxy to be able to access the Web UI from the internet.
If you want to access the Web UI over HTTP, change the env var `INSECURE` to `true`. This is not recommended. Only use this for testing
-### Donate
+## Donate
Are you enjoying this project? Consider donating.
diff --git a/docs/content/advanced/api.md b/docs/content/advanced/api.md
index 3fa4f793..a41ea66c 100644
--- a/docs/content/advanced/api.md
+++ b/docs/content/advanced/api.md
@@ -2,4 +2,37 @@
title: API
---
-TODO
+You can use the API to interact with the application programmatically. The API is available at `/api` and supports both GET and POST requests. The API is designed to be simple and easy to use, with a focus on providing a consistent interface for all endpoints.
+
+There is no documentation for the API yet, but this will be added as the underlying library supports it.
+
+## Authentication
+
+To use the API, you need to authenticate using Basic Authentication. The username and password are the same as the ones you use to log in to the web application.
+If you use 2FA, the API will not work. You need to disable 2FA in the web application to use the API.
+
+### Authentication Example
+
+```python
+import requests
+from requests.auth import HTTPBasicAuth
+
+url = "https://example.com:51821/api/client"
+response = requests.get(url, auth=HTTPBasicAuth('username', 'password'))
+if response.status_code == 200:
+ data = response.json()
+ print(data)
+else:
+ print(f"Error: {response.status_code}")
+```
+
+## Endpoints
+
+The Endpoints are not yet documented. But as file-based routing is used, you can find the endpoints in the `src/server/api` folder. The method is defined in the file name.
+
+### Endpoints Example
+
+| File Name | Endpoint | Method |
+| -------------------------------- | -------------- | ------ |
+| `src/server/api/client.get.ts` | `/api/client` | GET |
+| `src/server/api/setup/2.post.ts` | `/api/setup/2` | POST |
diff --git a/docs/content/advanced/config/optional-config.md b/docs/content/advanced/config/optional-config.md
index 871088b8..34d94db7 100644
--- a/docs/content/advanced/config/optional-config.md
+++ b/docs/content/advanced/config/optional-config.md
@@ -2,7 +2,7 @@
title: Optional Configuration
---
-TODO
+You can set these environment variables to configure the container. They are not required, but can be useful in some cases.
| Env | Default | Example | Description |
| ---------- | --------- | ----------- | ------------------------------ |
diff --git a/docs/content/advanced/config/unattended-setup.md b/docs/content/advanced/config/unattended-setup.md
index ee864efe..95f513e1 100644
--- a/docs/content/advanced/config/unattended-setup.md
+++ b/docs/content/advanced/config/unattended-setup.md
@@ -26,7 +26,7 @@ If you want to skip the setup process, you have to configure group `1`
/// note | Security
-The initial username and password is not checked for complexity. Make sure to set a long enough username and a secure password. Otherwise, the user won't be able to log in.
+The initial username and password is not checked for complexity. Make sure to set a long enough username and password. Otherwise, the user won't be able to log in.
Its recommended to remove the variables after the setup is done to prevent the password from being exposed.
///
diff --git a/docs/content/advanced/metrics/prometheus.md b/docs/content/advanced/metrics/prometheus.md
index b690890d..f5d7c5dc 100644
--- a/docs/content/advanced/metrics/prometheus.md
+++ b/docs/content/advanced/metrics/prometheus.md
@@ -2,6 +2,41 @@
title: Prometheus
---
-TODO
+To monitor the WireGuard server, you can use [Prometheus](https://prometheus.io/) and [Grafana](https://grafana.com/). The container exposes a `/metrics/prometheus` endpoint that can be scraped by Prometheus.
-
+## Enable Prometheus
+
+The enable Prometheus metrics go to Admin Panel > General and enable Prometheus.
+
+You can optionally set a Bearer Password for the metrics endpoints. This is useful if you want to expose the metrics endpoint to the internet.
+
+## Configure Prometheus
+
+You need to add a scrape config to your Prometheus configuration file. Here is an example:
+
+```yaml
+scrape_configs:
+ - job_name: "wg-easy"
+ scrape_interval: 30s
+ metrics_path: /metrics/prometheus
+ static_configs:
+ - targets:
+ - "localhost:51821"
+ authorization:
+ type: Bearer
+ credentials: "SuperSecurePassword"
+```
+
+## Grafana Dashboard
+
+You can use the following Grafana dashboard to visualize the metrics:
+
+[](https://grafana.com/grafana/dashboards/21733-wireguard/)
+
+[21733](https://grafana.com/grafana/dashboards/21733-wireguard/)
+
+/// note | Unofficial
+
+The Grafana dashboard is not official and is not maintained by the wg-easy team. If you have any issues with the dashboard, please contact the author of the dashboard.
+See [#1299](https://github.com/wg-easy/wg-easy/pull/1299) for more information.
+///
diff --git a/docs/content/examples/tutorials/adguard.md b/docs/content/examples/tutorials/adguard.md
index ba0f6da5..ddbed8de 100644
--- a/docs/content/examples/tutorials/adguard.md
+++ b/docs/content/examples/tutorials/adguard.md
@@ -2,4 +2,6 @@
title: AdGuard Home
---
-TODO
+It seems like the Docs on how to setup AdGuard Home are not available yet.
+
+Feel free to create a PR and add them here.
diff --git a/docs/content/examples/tutorials/auto-updates.md b/docs/content/examples/tutorials/auto-updates.md
index eaabe3b1..fd655735 100644
--- a/docs/content/examples/tutorials/auto-updates.md
+++ b/docs/content/examples/tutorials/auto-updates.md
@@ -6,13 +6,51 @@ title: Auto Updates
With Docker Compose `wg-easy` can be updated with a single command:
-Replace `$DIR` with the directory where your `docker-compose.yml` is located.
-
```shell
-cd $DIR
+cd /etc/docker/containers/wg-easy
sudo docker compose up -d --pull always
```
+### Watchtower
+
+If you want the updates to be fully automatic you can install Watchtower. This will check for updates every day at 4:00 AM and update the container if a new version is available.
+
+File: `/etc/docker/containers/watchtower/docker-compose.yml`
+
+```yaml
+services:
+ watchtower:
+ image: containrrr/watchtower:latest
+ volumes:
+ - /var/run/docker.sock:/var/run/docker.sock
+ env_file:
+ - watchtower.env
+ restart: unless-stopped
+```
+
+File: `/etc/docker/containers/watchtower/watchtower.env`
+
+```env
+WATCHTOWER_CLEANUP=true
+WATCHTOWER_SCHEDULE=0 0 4 * * *
+TZ=Europe/Berlin
+
+# Email
+# WATCHTOWER_NOTIFICATIONS_LEVEL=info
+# WATCHTOWER_NOTIFICATIONS=email
+# WATCHTOWER_NOTIFICATION_EMAIL_FROM=mail@example.com
+# WATCHTOWER_NOTIFICATION_EMAIL_TO=mail@example.com
+# WATCHTOWER_NOTIFICATION_EMAIL_SERVER=smtp.example.com
+# WATCHTOWER_NOTIFICATION_EMAIL_SERVER_USER=mail@example.com
+# WATCHTOWER_NOTIFICATION_EMAIL_SERVER_PASSWORD="SuperSecurePassword"
+# WATCHTOWER_NOTIFICATION_EMAIL_SERVER_PORT=587
+```
+
+```shell
+cd /etc/docker/containers/watchtower
+sudo docker compose up -d
+```
+
## Docker Run
```shell
diff --git a/docs/content/examples/tutorials/basic-installation.md b/docs/content/examples/tutorials/basic-installation.md
index 31ee4dcf..f4e5c1be 100644
--- a/docs/content/examples/tutorials/basic-installation.md
+++ b/docs/content/examples/tutorials/basic-installation.md
@@ -20,20 +20,20 @@ Follow the Docs here: and install Dock
1. Create a directory for the configuration files (you can choose any directory you like):
```shell
- DIR=/docker/wg-easy
- sudo mkdir -p $DIR
+ sudo mkdir -p /etc/docker/containers/wg-easy
```
2. Download docker compose file
```shell
- sudo curl -o $DIR/docker-compose.yml https://raw.githubusercontent.com/wg-easy/wg-easy/master/docker-compose.yml
+ sudo curl -o /etc/docker/containers/wg-easy/docker-compose.yml https://raw.githubusercontent.com/wg-easy/wg-easy/master/docker-compose.yml
```
3. Start `wg-easy`
```shell
- sudo docker-compose -f $DIR/docker-compose.yml up -d
+ cd /etc/docker/containers/wg-easy
+ sudo docker-compose up -d
```
## Setup Firewall
@@ -41,27 +41,22 @@ Follow the Docs here: and install Dock
If you are using a firewall, you need to open the following ports:
- UDP 51820 (WireGuard)
-- TCP 51821 (Web UI)
These ports can be changed, so if you change them you have to update your firewall rules accordingly.
## Setup Reverse Proxy
-TODO
-
-## Access the Web UI
-
-Open your browser and navigate to `https://:51821` or `https://:51821`.
-
-Follow the instructions to set up your WireGuard VPN.
+- To setup traefik follow the instructions here: [Traefik](./traefik.md)
+- To setup caddy follow the instructions here: [Caddy](./caddy.md)
## Update `wg-easy`
To update `wg-easy` to the latest version, run:
```shell
-sudo docker-compose -f $DIR/docker-compose.yml pull
-sudo docker-compose -f $DIR/docker-compose.yml up -d
+cd /etc/docker/containers/wg-easy
+sudo docker-compose pull
+sudo docker-compose up -d
```
## Auto Update
diff --git a/docs/content/examples/tutorials/caddy.md b/docs/content/examples/tutorials/caddy.md
index 2f02f2f9..47799035 100644
--- a/docs/content/examples/tutorials/caddy.md
+++ b/docs/content/examples/tutorials/caddy.md
@@ -2,4 +2,6 @@
title: Caddy
---
-TODO
+It seems like the Docs on how to setup Caddy are not available yet.
+
+Feel free to create a PR and add them here.
diff --git a/docs/content/examples/tutorials/docker-run.md b/docs/content/examples/tutorials/docker-run.md
index d6d5be37..010661bf 100644
--- a/docs/content/examples/tutorials/docker-run.md
+++ b/docs/content/examples/tutorials/docker-run.md
@@ -14,7 +14,7 @@ To setup the IPv6 Network, simply run once:
-To automatically install & run ``wg-easy, simply run:
+To automatically install & run wg-easy, simply run:
```shell
docker run -d \
@@ -39,5 +39,3 @@ To automatically install & run ``wg-easy, simply run:
```
The Web UI will now be available on `http://0.0.0.0:51821`.
-
-> 💡 Your configuration files will be saved in `~/.wg-easy`
diff --git a/docs/content/examples/tutorials/dockerless.md b/docs/content/examples/tutorials/dockerless.md
index c8377eb9..4d7ad400 100644
--- a/docs/content/examples/tutorials/dockerless.md
+++ b/docs/content/examples/tutorials/dockerless.md
@@ -2,4 +2,6 @@
title: Without Docker
---
-TODO
+This is currently not yet supported.
+
+
diff --git a/docs/content/examples/tutorials/nginx.md b/docs/content/examples/tutorials/nginx.md
deleted file mode 100644
index c2ae2eac..00000000
--- a/docs/content/examples/tutorials/nginx.md
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: NGINX
----
-
-TODO
diff --git a/docs/content/examples/tutorials/podman.md b/docs/content/examples/tutorials/podman-nft.md
similarity index 82%
rename from docs/content/examples/tutorials/podman.md
rename to docs/content/examples/tutorials/podman-nft.md
index 3cc49d98..9707b0e5 100644
--- a/docs/content/examples/tutorials/podman.md
+++ b/docs/content/examples/tutorials/podman-nft.md
@@ -1,7 +1,12 @@
---
-title: Podman
+title: Podman + nftables
---
+/// warning |Â Not working yet
+
+There are some problems with nftables currently. You can use the Quadlet files anyway
+///
+
This guide will show you how to run `wg-easy` with rootful Podman and nftables.
## Requirements
@@ -88,7 +93,7 @@ In the Admin Panel of your WireGuard server, go to the `Hooks` tab and add the f
1. PostUp
```shell
- apk add nftables; nft add table inet wg_table; nft add chain inet wg_table postrouting { type nat hook postrouting priority 100 \; }; nft add rule inet wg_table postrouting ip saddr {{ipv4Cidr}} oifname {{device}} masquerade; nft add rule inet wg_table postrouting ip6 saddr {{ipv6Cidr}} oifname {{device}} masquerade; nft add chain inet wg_table input { type filter hook input priority 0 \; policy drop \; }; nft add rule inet wg_table input udp dport {{port}} accept; nft add rule inet wg_table input tcp dport {{uiPort}} accept; nft add chain inet wg_table forward { type filter hook forward priority 0 \; policy drop \; }; nft add rule inet wg_table forward iifname "wg0" accept; nft add rule inet wg_table forward oifname "wg0" accept;
+ apk add nftables; nft add table inet wg_table; nft add chain inet wg_table postrouting { type nat hook postrouting priority 100 \; }; nft add rule inet wg_table postrouting ip saddr {{ipv4Cidr}} oifname {{device}} masquerade; nft add rule inet wg_table postrouting ip6 saddr {{ipv6Cidr}} oifname {{device}} masquerade; nft add chain inet wg_table input { type filter hook input priority 0 \; policy accept \; }; nft add rule inet wg_table input udp dport {{port}} accept; nft add rule inet wg_table input tcp dport {{uiPort}} accept; nft add chain inet wg_table forward { type filter hook forward priority 0 \; policy accept \; }; nft add rule inet wg_table forward iifname "wg0" accept; nft add rule inet wg_table forward oifname "wg0" accept;
```
2. PostDown
@@ -106,8 +111,3 @@ Restart the container to apply the new hooks:
```shell
sudo systemctl restart wg-easy
```
-
-
diff --git a/docs/content/examples/tutorials/traefik.md b/docs/content/examples/tutorials/traefik.md
index a0c79b45..551f920b 100644
--- a/docs/content/examples/tutorials/traefik.md
+++ b/docs/content/examples/tutorials/traefik.md
@@ -2,4 +2,183 @@
title: Traefik
---
-TODO
+/// note | Opiniated
+
+This guide is opinionated. If you use other conventions or folder layouts, feel free to change the commands and paths.
+///
+
+## Create docker compose project
+
+```shell
+sudo mkdir -p /etc/docker/containers/traefik
+cd /etc/docker/containers/traefik
+```
+
+## Create docker compose file
+
+File: `/etc/docker/containers/traefik/docker-compose.yml`
+
+```yaml
+services:
+ traefik:
+ image: traefik:3.3
+ container_name: traefik
+ restart: unless-stopped
+ ports:
+ - "80:80"
+ - "443:443/tcp"
+ - "443:443/udp"
+ volumes:
+ - /var/run/docker.sock:/var/run/docker.sock
+ - /etc/docker/volumes/traefik/traefik.yml:/traefik.yml:ro
+ - /etc/docker/volumes/traefik/traefik_dynamic.yml:/traefik_dynamic.yml:ro
+ - /etc/docker/volumes/traefik/acme.json:/acme.json
+ networks:
+ - traefik
+
+networks:
+ traefik:
+ external: true
+```
+
+## Create traefik.yml
+
+File: `/etc/docker/volumes/traefik/traefik.yml`
+
+```yaml
+log:
+ level: INFO
+
+entryPoints:
+ web:
+ address: ":80/tcp"
+ http:
+ redirections:
+ entryPoint:
+ to: websecure
+ scheme: https
+ websecure:
+ address: ":443/tcp"
+ http:
+ middlewares:
+ - compress@file
+ - hsts@file
+ tls:
+ certResolver: letsencrypt
+ http3: {}
+
+api:
+ dashboard: true
+
+certificatesResolvers:
+ letsencrypt:
+ acme:
+ email: $mail@example.com$
+ storage: acme.json
+ httpChallenge:
+ entryPoint: web
+
+providers:
+ docker:
+ watch: true
+ network: traefik
+ exposedByDefault: false
+ file:
+ filename: traefik_dynamic.yml
+
+serversTransport:
+ insecureSkipVerify: true
+```
+
+## Create traefik_dynamic.yml
+
+File: `/etc/docker/volumes/traefik/traefik_dynamic.yml`
+
+```yaml
+http:
+ middlewares:
+ services:
+ basicAuth:
+ users:
+ - "$username$:$password$"
+ compress:
+ compress: {}
+ hsts:
+ headers:
+ stsSeconds: 2592000
+ routers:
+ api:
+ rule: Host(`traefik.$example.com$`)
+ entrypoints:
+ - websecure
+ middlewares:
+ - services
+ service: api@internal
+
+tls:
+ options:
+ default:
+ cipherSuites:
+ - TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
+ - TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384
+ - TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256
+ sniStrict: true
+```
+
+## Create acme.json
+
+```shell
+sudo touch /etc/docker/volumes/traefik/acme.json
+sudo chmod 600 /etc/docker/volumes/traefik/acme.json
+```
+
+## Create network
+
+```shell
+sudo docker network create traefik
+```
+
+## Start traefik
+
+```shell
+sudo docker-compose up -d
+```
+
+You can no access the Traefik dashboard at `https://traefik.$example.com$` with the credentials you set in `traefik_dynamic.yml`.
+
+## Add Labels to wg-easy
+
+To add labels to your `wg-easy` service, you can add the following to your `docker-compose.yml` file:
+
+File: `/etc/docker/containers/wg-easy/docker-compose.yml`
+
+```yaml
+services:
+ wg-easy:
+ ...
+ container_name: wg-easy
+ networks:
+ ...
+ traefik: {}
+ labels:
+ - "traefik.enable=true"
+ - "traefik.http.routers.wg-easy.rule=Host(`wg-easy.$example.com$`)"
+ - "traefik.http.routers.wg-easy.entrypoints=websecure"
+ - "traefik.http.routers.wg-easy.service=wg-easy"
+ - "traefik.http.services.wg-easy.loadbalancer.server.port=51821"
+ ...
+
+networks:
+ ...
+ traefik:
+ external: true
+```
+
+## Restart wg-easy
+
+```shell
+cd /etc/docker/containers/wg-easy
+sudo docker-compose up -d
+```
+
+You can now access `wg-easy` at `https://wg-easy.$example.com$` and start the setup.
diff --git a/docs/content/faq.md b/docs/content/faq.md
new file mode 100644
index 00000000..ec321e0f
--- /dev/null
+++ b/docs/content/faq.md
@@ -0,0 +1,97 @@
+---
+title: FAQ
+hide:
+ - navigation
+---
+
+Here are some frequently asked questions or errors about `wg-easy`. If you have a question that is not answered here, please feel free to open a discussion on GitHub.
+
+## Error: WireGuard exited with the error: Cannot find device "wg0"
+
+This error indicates that the WireGuard interface `wg0` does not exist. This can happen if the WireGuard kernel module is not loaded or if the interface was not created properly.
+
+To resolve this issue, you can try the following steps:
+
+1. **Load the WireGuard kernel module**: If the WireGuard kernel module is not loaded, you can load it manually by running:
+
+ ```bash
+ sudo modprobe wireguard
+ ```
+
+2. **Load the WireGuard kernel module on boot**: If you want to ensure that the WireGuard kernel module is loaded automatically on boot, you can add it to the `/etc/modules` file:
+
+ ```bash
+ echo "wireguard" | sudo tee -a /etc/modules
+ ```
+
+## can't initialize iptables table `nat': Table does not exist (do you need to insmod?)
+
+This error indicates that the `nat` table in `iptables` does not exist. This can happen if the `iptables` kernel module is not loaded or if the `nat` table is not supported by your kernel.
+
+To resolve this issue, you can try the following steps:
+
+1. **Load the `nat` kernel module**: If the `nat` kernel module is not loaded, you can load it manually by running:
+
+ ```bash
+ sudo modprobe iptable_nat
+ ```
+
+2. **Load the `nat` kernel module on boot**: If you want to ensure that the `nat` kernel module is loaded automatically on boot, you can add it to the `/etc/modules` file:
+
+ ```bash
+ echo "iptable_nat" | sudo tee -a /etc/modules
+ ```
+
+## can't initialize ip6tables table `nat': Table does not exist (do you need to insmod?)
+
+This error indicates that the `nat` table in `ip6tables` does not exist. This can happen if the `ip6tables` kernel module is not loaded or if the `nat` table is not supported by your kernel.
+
+To resolve this issue, you can try the following steps:
+
+1. **Load the `nat` kernel module**: If the `nat` kernel module is not loaded, you can load it manually by running:
+
+ ```bash
+ sudo modprobe ip6table_nat
+ ```
+
+2. **Load the `nat` kernel module on boot**: If you want to ensure that the `nat` kernel module is loaded automatically on boot, you can add it to the `/etc/modules` file:
+
+ ```bash
+ echo "ip6table_nat" | sudo tee -a /etc/modules
+ ```
+
+## can't initialize iptables table `filter': Permission denied
+
+This error indicates that the `filter` table in `iptables` cannot be initialized due to permission issues. This can happen if you are not running the command with sufficient privileges.
+
+To resolve this issue, you can try the following steps:
+
+1. **Load the `filter` kernel module**: If the `filter` kernel module is not loaded, you can load it manually by running:
+
+ ```bash
+ sudo modprobe iptable_filter
+ ```
+
+2. **Load the `filter` kernel module on boot**: If you want to ensure that the `filter` kernel module is loaded automatically on boot, you can add it to the `/etc/modules` file:
+
+ ```bash
+ echo "iptable_filter" | sudo tee -a /etc/modules
+ ```
+
+## can't initialize ip6tables table `filter': Permission denied
+
+This error indicates that the `filter` table in `ip6tables` cannot be initialized due to permission issues. This can happen if you are not running the command with sufficient privileges.
+
+To resolve this issue, you can try the following steps:
+
+1. **Load the `filter` kernel module**: If the `filter` kernel module is not loaded, you can load it manually by running:
+
+ ```bash
+ sudo modprobe ip6table_filter
+ ```
+
+2. **Load the `filter` kernel module on boot**: If you want to ensure that the `filter` kernel module is loaded automatically on boot, you can add it to the `/etc/modules` file:
+
+ ```bash
+ echo "ip6table_filter" | sudo tee -a /etc/modules
+ ```
diff --git a/docs/content/getting-started.md b/docs/content/getting-started.md
index 47638d07..7ddf6ecf 100644
--- a/docs/content/getting-started.md
+++ b/docs/content/getting-started.md
@@ -29,7 +29,7 @@ If you're using podman, make sure to read the related [documentation][docs-podma
[docker-compose]: https://docs.docker.com/compose/
[docker-compose-installation]: https://docs.docker.com/compose/install/
[docker-compose-specification]: https://docs.docker.com/compose/compose-file/
-[docs-podman]: ./examples/tutorials/podman.md
+[docs-podman]: ./examples/tutorials/podman-nft.md
## Deploying the Actual Image
@@ -41,10 +41,14 @@ To understand which tags you should use, read this section carefully. [Our CI][g
All workflows are using the tagging convention listed below. It is subsequently applied to all images.
-| Event | Image Tags |
-| ----------------------- | ----------------------------- |
-| `cron` on `master` | `nightly` |
-| `push` a tag (`v1.2.3`) | `1.2.3`, `1.2`, `1`, `latest` |
+| tag | Type | Example | Description |
+| ------------- | ---------------------------------------------------------- | ------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------ |
+| `15` | latest minor for that major tag | `ghcr.io/wg-easy/wg-easy:15` | latest features for specific major versions, no breaking changes |
+| `latest` | latest tag | `ghcr.io/wg-easy/wg-easy:latest` or `ghcr.io/wg-easy/wg-easy` | stable as possible get bug fixes quickly when needed, see Releases for more information. |
+| `15.0` | latest patch for that minor tag | `ghcr.io/wg-easy/wg-easy:15.0` | latest patches for specific minor version |
+| `15.0.0` | specific tag | `ghcr.io/wg-easy/wg-easy:15.0.0` | specific release, don't use this as this will not get updated |
+| `nightly` | [`master`](https://github.com/wg-easy/wg-easy/tree/master) | `ghcr.io/wg-easy/wg-easy:nightly` | mostly unstable gets frequent package and code updates, deployed against [`master`](https://github.com/wg-easy/wg-easy/tree/master). |
+| `development` | pull requests | `ghcr.io/wg-easy/wg-easy:development` | used for development, testing code from PRs before landing into [`master`](https://github.com/wg-easy/wg-easy/tree/master). |
When publishing a tag we follow the [Semantic Versioning][semver] specification. The `latest` tag is always pointing to the latest stable release. If you want to avoid breaking changes, use the major version tag (e.g. `15`).