Compare commits
4 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 0597470f4c | |||
| 159a51cff4 | |||
| 9fc6ebafb3 | |||
| 9a029eeb23 |
@@ -42,8 +42,21 @@ You have found the easiest way to install & manage WireGuard on any Linux host!
|
|||||||
> [!NOTE]
|
> [!NOTE]
|
||||||
> To better manage documentation for this project, it has its own site here: [https://wg-easy.github.io/wg-easy/latest](https://wg-easy.github.io/wg-easy/latest)
|
> To better manage documentation for this project, it has its own site here: [https://wg-easy.github.io/wg-easy/latest](https://wg-easy.github.io/wg-easy/latest)
|
||||||
|
|
||||||
|
<!-- TODO: remove after release -->
|
||||||
|
|
||||||
|
> [!WARNING]
|
||||||
|
> As the Docs are still in Pre-release, you can access them here [https://wg-easy.github.io/wg-easy/Pre-release](https://wg-easy.github.io/wg-easy/Pre-release)
|
||||||
|
|
||||||
- [Getting Started](https://wg-easy.github.io/wg-easy/latest/getting-started/)
|
- [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/)
|
- [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/)
|
||||||
|
- [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
|
## Requirements
|
||||||
|
|
||||||
@@ -89,52 +102,7 @@ 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
|
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
|
||||||
|
|
||||||
<!-- TOOD: add to docs: Grafana dashboard [21733](https://grafana.com/grafana/dashboards/21733-wireguard/) -->
|
### Donate
|
||||||
|
|
||||||
<!-- TOOD: add to docs
|
|
||||||
To setup the IPv6 Network, simply run once:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
docker network create \
|
|
||||||
-d bridge --ipv6 \
|
|
||||||
-d default \
|
|
||||||
--subnet 10.42.42.0/24 \
|
|
||||||
--subnet fdcc:ad94:bacf:61a3::/64 wg \
|
|
||||||
```
|
|
||||||
|
|
||||||
To automatically install & run wg-easy, simply run:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
docker run -d \
|
|
||||||
--net wg \
|
|
||||||
-e PORT=51821 \
|
|
||||||
--name wg-easy \
|
|
||||||
--ip6 fdcc:ad94:bacf:61a3::2a \
|
|
||||||
--ip 10.42.42.42 \
|
|
||||||
-v ~/.wg-easy:/etc/wireguard \
|
|
||||||
-v /lib/modules:/lib/modules:ro \
|
|
||||||
-p 51820:51820/udp \
|
|
||||||
-p 51821:51821/tcp \
|
|
||||||
--cap-add NET_ADMIN \
|
|
||||||
--cap-add SYS_MODULE \
|
|
||||||
--sysctl net.ipv4.ip_forward=1 \
|
|
||||||
--sysctl net.ipv4.conf.all.src_valid_mark=1 \
|
|
||||||
--sysctl net.ipv6.conf.all.disable_ipv6=0 \
|
|
||||||
--sysctl net.ipv6.conf.all.forwarding=1 \
|
|
||||||
--sysctl net.ipv6.conf.default.forwarding=1 \
|
|
||||||
--restart unless-stopped \
|
|
||||||
ghcr.io/wg-easy/wg-easy
|
|
||||||
```
|
|
||||||
|
|
||||||
The Web UI will now be available on `http://0.0.0.0:51821`.
|
|
||||||
|
|
||||||
The Prometheus metrics will now be available on `http://0.0.0.0:51821/api/metrics`. Grafana dashboard [21733](https://grafana.com/grafana/dashboards/21733-wireguard/)
|
|
||||||
|
|
||||||
> 💡 Your configuration files will be saved in `~/.wg-easy`
|
|
||||||
|
|
||||||
-->
|
|
||||||
|
|
||||||
### 3. Sponsor
|
|
||||||
|
|
||||||
Are you enjoying this project? Consider donating.
|
Are you enjoying this project? Consider donating.
|
||||||
|
|
||||||
@@ -142,46 +110,30 @@ Founder: [Buy Emile a beer!](https://github.com/sponsors/WeeJeWel) 🍻
|
|||||||
|
|
||||||
Maintainer: [Buy kaaax0815 a coffee!](https://github.com/sponsors/kaaax0815) ☕
|
Maintainer: [Buy kaaax0815 a coffee!](https://github.com/sponsors/kaaax0815) ☕
|
||||||
|
|
||||||
<!-- TOOD: add to docs
|
## Development
|
||||||
|
|
||||||
## Options
|
### Prerequisites
|
||||||
|
|
||||||
These options can be configured by setting environment variables using `-e KEY="VALUE"` in the `docker run` command.
|
- Docker
|
||||||
|
- Node LTS & corepack enabled
|
||||||
|
- Visual Studio Code
|
||||||
|
|
||||||
| Env | Default | Example | Description |
|
### Dev Server
|
||||||
| ---------- | --------- | ----------- | ------------------------------ |
|
|
||||||
| `PORT`. | `51821` | `6789` | TCP port for Web UI. |
|
|
||||||
| `HOST` | `0.0.0.0` | `localhost` | IP address web UI binds to. |
|
|
||||||
| `INSECURE` | `false` | `true` | If access over http is allowed |
|
|
||||||
|
|
||||||
## Updating
|
This starts the development server with docker
|
||||||
|
|
||||||
To update to the latest version, simply run:
|
|
||||||
|
|
||||||
```shell
|
```shell
|
||||||
docker stop wg-easy
|
pnpm dev
|
||||||
docker rm wg-easy
|
|
||||||
docker pull ghcr.io/wg-easy/wg-easy
|
|
||||||
```
|
```
|
||||||
|
|
||||||
And then run the `docker run -d \ ...` command above again.
|
### Update Auto Imports
|
||||||
|
|
||||||
With Docker Compose WireGuard Easy can be updated with a single command:
|
If you add something that should be auto-importable and VSCode complains, run:
|
||||||
`docker compose up --detach --pull always` (if an image tag is specified in the
|
|
||||||
Compose file and it is not `latest`, make sure that it is changed to the desired
|
|
||||||
one; by default it is omitted and
|
|
||||||
[defaults to `latest`](https://docs.docker.com/engine/reference/run/#image-references)). \
|
|
||||||
The WireGuard Easy container will be automatically recreated if a newer image
|
|
||||||
was pulled.
|
|
||||||
|
|
||||||
## Common Use Cases
|
```shell
|
||||||
|
cd src
|
||||||
- [Using WireGuard-Easy with Pi-Hole](https://github.com/wg-easy/wg-easy/wiki/Using-WireGuard-Easy-with-Pi-Hole)
|
pnpm install
|
||||||
- [Using WireGuard-Easy with nginx/SSL](https://github.com/wg-easy/wg-easy/wiki/Using-WireGuard-Easy-with-nginx-SSL)
|
```
|
||||||
|
|
||||||
For less common or specific edge-case scenarios, please refer to the detailed information provided in the [Wiki](https://github.com/wg-easy/wg-easy/wiki).
|
|
||||||
|
|
||||||
-->
|
|
||||||
|
|
||||||
## License
|
## License
|
||||||
|
|
||||||
|
|||||||
+2
-2
@@ -9,7 +9,7 @@ services:
|
|||||||
# - HOST=0.0.0.0
|
# - HOST=0.0.0.0
|
||||||
# - INSECURE=false
|
# - INSECURE=false
|
||||||
|
|
||||||
image: ghcr.io/wg-easy/wg-easy
|
image: ghcr.io/wg-easy/wg-easy:15
|
||||||
container_name: wg-easy
|
container_name: wg-easy
|
||||||
networks:
|
networks:
|
||||||
wg:
|
wg:
|
||||||
@@ -25,7 +25,7 @@ services:
|
|||||||
cap_add:
|
cap_add:
|
||||||
- NET_ADMIN
|
- NET_ADMIN
|
||||||
- SYS_MODULE
|
- SYS_MODULE
|
||||||
# - NET_RAW # ⚠️ Uncomment if using Podman
|
# - NET_RAW # ⚠️ Uncomment if using Podman Compose
|
||||||
sysctls:
|
sysctls:
|
||||||
- net.ipv4.ip_forward=1
|
- net.ipv4.ip_forward=1
|
||||||
- net.ipv4.conf.all.src_valid_mark=1
|
- net.ipv4.conf.all.src_valid_mark=1
|
||||||
|
|||||||
@@ -3,3 +3,9 @@ title: Optional Configuration
|
|||||||
---
|
---
|
||||||
|
|
||||||
TODO
|
TODO
|
||||||
|
|
||||||
|
| Env | Default | Example | Description |
|
||||||
|
| ---------- | --------- | ----------- | ------------------------------ |
|
||||||
|
| `PORT` | `51821` | `6789` | TCP port for Web UI. |
|
||||||
|
| `HOST` | `0.0.0.0` | `localhost` | IP address web UI binds to. |
|
||||||
|
| `INSECURE` | `false` | `true` | If access over http is allowed |
|
||||||
|
|||||||
@@ -0,0 +1,7 @@
|
|||||||
|
---
|
||||||
|
title: Prometheus
|
||||||
|
---
|
||||||
|
|
||||||
|
TODO
|
||||||
|
|
||||||
|
<!-- TOOD: add to docs: Grafana dashboard [21733](https://grafana.com/grafana/dashboards/21733-wireguard/) -->
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
---
|
||||||
|
title: Migrate
|
||||||
|
---
|
||||||
|
|
||||||
|
If you want to migrate from an older version of `wg-easy` to the new version, you can find the migration guides listed below.
|
||||||
|
|
||||||
|
- [Migrate from v14 to v15](./from-14-to-15.md) : This guide should also work for any version before `v14`.
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
---
|
||||||
|
title: AdGuard Home
|
||||||
|
---
|
||||||
|
|
||||||
|
TODO
|
||||||
@@ -0,0 +1,34 @@
|
|||||||
|
---
|
||||||
|
title: Auto Updates
|
||||||
|
---
|
||||||
|
|
||||||
|
## Docker Compose
|
||||||
|
|
||||||
|
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
|
||||||
|
sudo docker compose up -d --pull always
|
||||||
|
```
|
||||||
|
|
||||||
|
## Docker Run
|
||||||
|
|
||||||
|
```shell
|
||||||
|
sudo docker stop wg-easy
|
||||||
|
sudo docker rm wg-easy
|
||||||
|
sudo docker pull ghcr.io/wg-easy/wg-easy
|
||||||
|
```
|
||||||
|
|
||||||
|
And then run the `docker run -d \ ...` command from [Docker Run][docker-run] again.
|
||||||
|
|
||||||
|
[docker-run]: ./docker-run.md
|
||||||
|
|
||||||
|
## Podman
|
||||||
|
|
||||||
|
To update `wg-easy` (and every container that has auto updates enabled), you can run the following command:
|
||||||
|
|
||||||
|
```shell
|
||||||
|
sudo podman auto-update
|
||||||
|
```
|
||||||
@@ -27,7 +27,7 @@ Follow the Docs here: <https://docs.docker.com/engine/install/> and install Dock
|
|||||||
2. Download docker compose file
|
2. Download docker compose file
|
||||||
|
|
||||||
```shell
|
```shell
|
||||||
sudo curl -o $URL/docker-compose.yml https://raw.githubusercontent.com/wg-easy/wg-easy/master/docker-compose.yml
|
sudo curl -o $DIR/docker-compose.yml https://raw.githubusercontent.com/wg-easy/wg-easy/master/docker-compose.yml
|
||||||
```
|
```
|
||||||
|
|
||||||
3. Start `wg-easy`
|
3. Start `wg-easy`
|
||||||
@@ -54,3 +54,18 @@ TODO
|
|||||||
Open your browser and navigate to `https://<your-domain>:51821` or `https://<your-ip>:51821`.
|
Open your browser and navigate to `https://<your-domain>:51821` or `https://<your-ip>:51821`.
|
||||||
|
|
||||||
Follow the instructions to set up your WireGuard VPN.
|
Follow the instructions to set up your WireGuard VPN.
|
||||||
|
|
||||||
|
## 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
|
||||||
|
```
|
||||||
|
|
||||||
|
## Auto Update
|
||||||
|
|
||||||
|
If you want to enable auto-updates, follow the instructions here: [Auto Updates][auto-updates]
|
||||||
|
|
||||||
|
[auto-updates]: ./auto-updates.md
|
||||||
|
|||||||
@@ -0,0 +1,5 @@
|
|||||||
|
---
|
||||||
|
title: Caddy
|
||||||
|
---
|
||||||
|
|
||||||
|
TODO
|
||||||
@@ -0,0 +1,43 @@
|
|||||||
|
---
|
||||||
|
title: Docker Run
|
||||||
|
---
|
||||||
|
|
||||||
|
To setup the IPv6 Network, simply run once:
|
||||||
|
|
||||||
|
```shell
|
||||||
|
docker network create \
|
||||||
|
-d bridge --ipv6 \
|
||||||
|
-d default \
|
||||||
|
--subnet 10.42.42.0/24 \
|
||||||
|
--subnet fdcc:ad94:bacf:61a3::/64 wg \
|
||||||
|
```
|
||||||
|
|
||||||
|
<!-- ref: major version -->
|
||||||
|
|
||||||
|
To automatically install & run ``wg-easy, simply run:
|
||||||
|
|
||||||
|
```shell
|
||||||
|
docker run -d \
|
||||||
|
--net wg \
|
||||||
|
-e INSECURE=true \
|
||||||
|
--name wg-easy \
|
||||||
|
--ip6 fdcc:ad94:bacf:61a3::2a \
|
||||||
|
--ip 10.42.42.42 \
|
||||||
|
-v ~/.wg-easy:/etc/wireguard \
|
||||||
|
-v /lib/modules:/lib/modules:ro \
|
||||||
|
-p 51820:51820/udp \
|
||||||
|
-p 51821:51821/tcp \
|
||||||
|
--cap-add NET_ADMIN \
|
||||||
|
--cap-add SYS_MODULE \
|
||||||
|
--sysctl net.ipv4.ip_forward=1 \
|
||||||
|
--sysctl net.ipv4.conf.all.src_valid_mark=1 \
|
||||||
|
--sysctl net.ipv6.conf.all.disable_ipv6=0 \
|
||||||
|
--sysctl net.ipv6.conf.all.forwarding=1 \
|
||||||
|
--sysctl net.ipv6.conf.default.forwarding=1 \
|
||||||
|
--restart unless-stopped \
|
||||||
|
ghcr.io/wg-easy/wg-easy:15
|
||||||
|
```
|
||||||
|
|
||||||
|
The Web UI will now be available on `http://0.0.0.0:51821`.
|
||||||
|
|
||||||
|
> 💡 Your configuration files will be saved in `~/.wg-easy`
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
---
|
||||||
|
title: NGINX
|
||||||
|
---
|
||||||
|
|
||||||
|
TODO
|
||||||
@@ -19,16 +19,23 @@ sudo mkdir -p /etc/containers/volumes/wg-easy
|
|||||||
|
|
||||||
Create a file `/etc/containers/systemd/wg-easy/wg-easy.container` with the following content:
|
Create a file `/etc/containers/systemd/wg-easy/wg-easy.container` with the following content:
|
||||||
|
|
||||||
|
<!-- ref: major version -->
|
||||||
|
|
||||||
```ini
|
```ini
|
||||||
[Container]
|
[Container]
|
||||||
ContainerName=wg-easy
|
ContainerName=wg-easy
|
||||||
Image=ghcr.io/wg-easy/wg-easy:latest
|
Image=ghcr.io/wg-easy/wg-easy:15
|
||||||
|
AutoUpdate=registry
|
||||||
|
|
||||||
Volume=/etc/containers/volumes/wg-easy:/etc/wireguard:Z
|
Volume=/etc/containers/volumes/wg-easy:/etc/wireguard:Z
|
||||||
Network=wg-easy.network
|
Network=wg-easy.network
|
||||||
PublishPort=51820:51820/udp
|
PublishPort=51820:51820/udp
|
||||||
PublishPort=51821:51821/tcp
|
PublishPort=51821:51821/tcp
|
||||||
|
|
||||||
|
# this is used to allow access over HTTP
|
||||||
|
# remove this when using a reverse proxy
|
||||||
|
Environment=INSECURE=true
|
||||||
|
|
||||||
AddCapability=NET_ADMIN
|
AddCapability=NET_ADMIN
|
||||||
AddCapability=SYS_MODULE
|
AddCapability=SYS_MODULE
|
||||||
AddCapability=NET_RAW
|
AddCapability=NET_RAW
|
||||||
@@ -90,6 +97,16 @@ In the Admin Panel of your WireGuard server, go to the `Hooks` tab and add the f
|
|||||||
nft delete table inet wg_table
|
nft delete table inet wg_table
|
||||||
```
|
```
|
||||||
|
|
||||||
|
If you don't have iptables loaded on your server, you could see many errors in the logs or in the UI. You can ignore them.
|
||||||
|
|
||||||
|
## Restart the Container
|
||||||
|
|
||||||
|
Restart the container to apply the new hooks:
|
||||||
|
|
||||||
|
```shell
|
||||||
|
sudo systemctl restart wg-easy
|
||||||
|
```
|
||||||
|
|
||||||
<!--
|
<!--
|
||||||
TODO: improve docs after better nftables support
|
TODO: improve docs after better nftables support
|
||||||
TODO: fix accept web ui port
|
TODO: fix accept web ui port
|
||||||
|
|||||||
@@ -0,0 +1,5 @@
|
|||||||
|
---
|
||||||
|
title: Traefik
|
||||||
|
---
|
||||||
|
|
||||||
|
TODO
|
||||||
+2
-1
@@ -4,7 +4,8 @@
|
|||||||
"scripts": {
|
"scripts": {
|
||||||
"dev": "docker compose -f docker-compose.dev.yml up --build",
|
"dev": "docker compose -f docker-compose.dev.yml up --build",
|
||||||
"build": "docker build -t wg-easy .",
|
"build": "docker build -t wg-easy .",
|
||||||
"docs:preview": "docker run --rm -it -p 8080:8080 -v ./docs:/docs squidfunk/mkdocs-material serve -a 0.0.0.0:8080"
|
"docs:preview": "docker run --rm -it -p 8080:8080 -v ./docs:/docs squidfunk/mkdocs-material serve -a 0.0.0.0:8080",
|
||||||
|
"scripts:version": "bash scripts/version.sh"
|
||||||
},
|
},
|
||||||
"packageManager": "pnpm@10.5.2"
|
"packageManager": "pnpm@10.5.2"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,54 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
package_json="src/package.json"
|
||||||
|
|
||||||
|
# Function to update the version in package.json
|
||||||
|
update_version() {
|
||||||
|
local new_version=$1
|
||||||
|
jq --arg new_version "$new_version" '.version = $new_version' $package_json > tmp.json && mv tmp.json $package_json
|
||||||
|
}
|
||||||
|
|
||||||
|
# Get the current version from package.json
|
||||||
|
current_version=$(jq -r '.version' $package_json)
|
||||||
|
echo "Current version: $current_version"
|
||||||
|
|
||||||
|
# Prompt the user for the new version
|
||||||
|
read -p "Enter the new version (following SemVer): " new_version
|
||||||
|
|
||||||
|
# Official SemVer regex for validation
|
||||||
|
semver_regex="^(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(?:-((?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\.(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\+([0-9a-zA-Z-]+(?:\.[0-9a-zA-Z-]+)*))?$"
|
||||||
|
|
||||||
|
# Validate the new version
|
||||||
|
if ! echo "$new_version" | grep -Eq "$semver_regex"; then
|
||||||
|
echo "Invalid version format. Please use SemVer format (e.g., 1.0.0 or 1.0.0-alpha)."
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Update the version in package.json
|
||||||
|
update_version $new_version
|
||||||
|
echo "Updated package.json to version $new_version"
|
||||||
|
|
||||||
|
echo "----"
|
||||||
|
echo "If you changed the major version, remember to update the docker-compose.yml file and docs (search for: ref: major version)"
|
||||||
|
echo "----"
|
||||||
|
|
||||||
|
echo "If you did everything press 'y' to commit the changes and create a new tag"
|
||||||
|
read -p "Do you want to continue? (y/n): " confirm
|
||||||
|
|
||||||
|
if [ "$confirm" != "y" ]; then
|
||||||
|
echo "Aborted."
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Commit the changes
|
||||||
|
git add $package_json
|
||||||
|
git commit -m "Bump version to $new_version"
|
||||||
|
echo "Committed the changes"
|
||||||
|
|
||||||
|
# Create a new Git tag
|
||||||
|
git tag -a "v$new_version" -m "Release version $new_version"
|
||||||
|
echo "Created Git tag v$new_version"
|
||||||
|
|
||||||
|
# Push the commit & tag to the remote repository
|
||||||
|
git push origin master --follow-tags
|
||||||
|
echo "Pushed Git commit and tag v$new_version to remote repository"
|
||||||
@@ -0,0 +1,68 @@
|
|||||||
|
<template>
|
||||||
|
<div class="flex flex-col gap-2">
|
||||||
|
<div v-if="data === null">
|
||||||
|
{{ emptyText || $t('form.nullNoItems') }}
|
||||||
|
</div>
|
||||||
|
<div v-for="(item, i) in data" v-else :key="i">
|
||||||
|
<div class="mt-1 flex flex-row gap-1">
|
||||||
|
<input
|
||||||
|
:value="item"
|
||||||
|
:name="name"
|
||||||
|
type="text"
|
||||||
|
class="rounded-lg border-2 border-gray-100 text-gray-500 focus:border-red-800 focus:outline-0 focus:ring-0 dark:border-neutral-800 dark:bg-neutral-700 dark:text-neutral-200 dark:placeholder:text-neutral-400"
|
||||||
|
@input="update($event, i)"
|
||||||
|
/>
|
||||||
|
<BaseButton
|
||||||
|
as="input"
|
||||||
|
type="button"
|
||||||
|
class="rounded-lg"
|
||||||
|
value="-"
|
||||||
|
@click="del(i)"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="mt-2">
|
||||||
|
<BaseButton
|
||||||
|
as="input"
|
||||||
|
type="button"
|
||||||
|
class="rounded-lg"
|
||||||
|
:value="$t('form.add')"
|
||||||
|
@click="add"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts" setup>
|
||||||
|
const data = defineModel<string[] | null>();
|
||||||
|
defineProps<{ emptyText?: string[]; name: string }>();
|
||||||
|
|
||||||
|
function update(e: Event, i: number) {
|
||||||
|
const v = (e.target as HTMLInputElement).value;
|
||||||
|
if (!data.value) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
data.value[i] = v;
|
||||||
|
}
|
||||||
|
|
||||||
|
function add() {
|
||||||
|
if (data.value === undefined) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (data.value === null) {
|
||||||
|
data.value = [''];
|
||||||
|
} else {
|
||||||
|
data.value.push('');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function del(i: number) {
|
||||||
|
if (!data.value) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
data.value.splice(i, 1);
|
||||||
|
if (data.value.length === 0) {
|
||||||
|
data.value = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
@@ -24,7 +24,7 @@
|
|||||||
·
|
·
|
||||||
<a
|
<a
|
||||||
class="hover:underline"
|
class="hover:underline"
|
||||||
href="https://github.com/sponsors/WeeJeWel"
|
href="https://github.com/wg-easy/wg-easy#donate"
|
||||||
target="_blank"
|
target="_blank"
|
||||||
>{{ $t('layout.donate') }}</a
|
>{{ $t('layout.donate') }}</a
|
||||||
>
|
>
|
||||||
|
|||||||
@@ -27,7 +27,7 @@
|
|||||||
</FormGroup>
|
</FormGroup>
|
||||||
<FormGroup>
|
<FormGroup>
|
||||||
<FormHeading :description="$t('admin.config.dnsDesc')">{{
|
<FormHeading :description="$t('admin.config.dnsDesc')">{{
|
||||||
$t('admin.config.dns')
|
$t('general.dns')
|
||||||
}}</FormHeading>
|
}}</FormHeading>
|
||||||
<FormArrayField v-model="data.defaultDns" name="defaultDns" />
|
<FormArrayField v-model="data.defaultDns" name="defaultDns" />
|
||||||
</FormGroup>
|
</FormGroup>
|
||||||
|
|||||||
@@ -41,21 +41,26 @@
|
|||||||
/>
|
/>
|
||||||
</FormGroup>
|
</FormGroup>
|
||||||
<FormGroup>
|
<FormGroup>
|
||||||
<FormHeading :description="$t('client.allowedIpsDesc')">{{
|
<FormHeading :description="$t('client.allowedIpsDesc')">
|
||||||
$t('general.allowedIps')
|
{{ $t('general.allowedIps') }}
|
||||||
}}</FormHeading>
|
</FormHeading>
|
||||||
<FormArrayField v-model="data.allowedIps" name="allowedIps" />
|
<FormNullArrayField v-model="data.allowedIps" name="allowedIps" />
|
||||||
</FormGroup>
|
</FormGroup>
|
||||||
<FormGroup>
|
<FormGroup>
|
||||||
<FormHeading :description="$t('client.serverAllowedIpsDesc')">{{
|
<FormHeading :description="$t('client.serverAllowedIpsDesc')">
|
||||||
$t('client.serverAllowedIps')
|
{{ $t('client.serverAllowedIps') }}
|
||||||
}}</FormHeading>
|
</FormHeading>
|
||||||
<FormArrayField
|
<FormArrayField
|
||||||
v-model="data.serverAllowedIps"
|
v-model="data.serverAllowedIps"
|
||||||
name="serverAllowedIps"
|
name="serverAllowedIps"
|
||||||
/>
|
/>
|
||||||
</FormGroup>
|
</FormGroup>
|
||||||
<FormGroup></FormGroup>
|
<FormGroup>
|
||||||
|
<FormHeading :description="$t('client.dnsDesc')">
|
||||||
|
{{ $t('general.dns') }}
|
||||||
|
</FormHeading>
|
||||||
|
<FormNullArrayField v-model="data.dns" name="dns" />
|
||||||
|
</FormGroup>
|
||||||
<FormGroup>
|
<FormGroup>
|
||||||
<FormHeading>{{ $t('form.sectionAdvanced') }}</FormHeading>
|
<FormHeading>{{ $t('form.sectionAdvanced') }}</FormHeading>
|
||||||
<FormNumberField
|
<FormNumberField
|
||||||
@@ -142,8 +147,12 @@ const _submit = useSubmit(
|
|||||||
method: 'post',
|
method: 'post',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
revert: async () => {
|
revert: async (success) => {
|
||||||
await navigateTo('/');
|
if (success) {
|
||||||
|
await navigateTo('/');
|
||||||
|
} else {
|
||||||
|
await revert();
|
||||||
|
}
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -25,6 +25,7 @@
|
|||||||
"updatePassword": "Update Password",
|
"updatePassword": "Update Password",
|
||||||
"mtu": "MTU",
|
"mtu": "MTU",
|
||||||
"allowedIps": "Allowed IPs",
|
"allowedIps": "Allowed IPs",
|
||||||
|
"dns": "DNS",
|
||||||
"persistentKeepalive": "Persistent Keepalive",
|
"persistentKeepalive": "Persistent Keepalive",
|
||||||
"logout": "Logout",
|
"logout": "Logout",
|
||||||
"continue": "Continue",
|
"continue": "Continue",
|
||||||
@@ -95,13 +96,14 @@
|
|||||||
"noPrivKey": "This client has no known private key. Cannot create Configuration.",
|
"noPrivKey": "This client has no known private key. Cannot create Configuration.",
|
||||||
"showQR": "Show QR Code",
|
"showQR": "Show QR Code",
|
||||||
"downloadConfig": "Download Configuration",
|
"downloadConfig": "Download Configuration",
|
||||||
"allowedIpsDesc": "Which IPs will be routed through the VPN",
|
"allowedIpsDesc": "Which IPs will be routed through the VPN (overrides global config)",
|
||||||
"serverAllowedIpsDesc": "Which IPs the server will route to the client",
|
"serverAllowedIpsDesc": "Which IPs the server will route to the client",
|
||||||
"mtuDesc": "Sets the maximum transmission unit (packet size) for the VPN tunnel",
|
"mtuDesc": "Sets the maximum transmission unit (packet size) for the VPN tunnel",
|
||||||
"persistentKeepaliveDesc": "Sets the interval (in seconds) for keep-alive packets. 0 disables it",
|
"persistentKeepaliveDesc": "Sets the interval (in seconds) for keep-alive packets. 0 disables it",
|
||||||
"hooks": "Hooks",
|
"hooks": "Hooks",
|
||||||
"hooksDescription": "Hooks only work with wg-quick",
|
"hooksDescription": "Hooks only work with wg-quick",
|
||||||
"hooksLeaveEmpty": "Only for wg-quick. Otherwise, leave it empty"
|
"hooksLeaveEmpty": "Only for wg-quick. Otherwise, leave it empty",
|
||||||
|
"dnsDesc": "DNS server clients will use (overrides global config)"
|
||||||
},
|
},
|
||||||
"dialog": {
|
"dialog": {
|
||||||
"change": "Change",
|
"change": "Change",
|
||||||
@@ -121,6 +123,7 @@
|
|||||||
"sectionGeneral": "General",
|
"sectionGeneral": "General",
|
||||||
"sectionAdvanced": "Advanced",
|
"sectionAdvanced": "Advanced",
|
||||||
"noItems": "No items",
|
"noItems": "No items",
|
||||||
|
"nullNoItems": "No items. Using global config",
|
||||||
"add": "Add"
|
"add": "Add"
|
||||||
},
|
},
|
||||||
"admin": {
|
"admin": {
|
||||||
@@ -139,11 +142,10 @@
|
|||||||
"connection": "Connection",
|
"connection": "Connection",
|
||||||
"hostDesc": "Public hostname clients will connect to (invalidates config)",
|
"hostDesc": "Public hostname clients will connect to (invalidates config)",
|
||||||
"portDesc": "Public UDP port clients will connect to (invalidates config)",
|
"portDesc": "Public UDP port clients will connect to (invalidates config)",
|
||||||
"allowedIpsDesc": "Allowed IPs clients will use (invalidates config)",
|
"allowedIpsDesc": "Allowed IPs clients will use (global config)",
|
||||||
"dns": "DNS",
|
"dnsDesc": "DNS server clients will use (global config)",
|
||||||
"dnsDesc": "DNS server clients will use (invalidates config)",
|
"mtuDesc": "MTU clients will use (only for new clients)",
|
||||||
"mtuDesc": "MTU clients will use (invalidates config)",
|
"persistentKeepaliveDesc": "Interval in seconds to send keepalives to the server. 0 = disabled (only for new clients)"
|
||||||
"persistentKeepaliveDesc": "Interval in seconds to send keepalives to the server. 0 = disabled (invalidates config)"
|
|
||||||
},
|
},
|
||||||
"interface": {
|
"interface": {
|
||||||
"cidrSuccess": "Changed CIDR",
|
"cidrSuccess": "Changed CIDR",
|
||||||
|
|||||||
+1
-1
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "wg-easy",
|
"name": "wg-easy",
|
||||||
"version": "15.0.0-beta.1",
|
"version": "15.0.0-beta.7",
|
||||||
"description": "The easiest way to run WireGuard VPN + Web-based Admin UI.",
|
"description": "The easiest way to run WireGuard VPN + Web-based Admin UI.",
|
||||||
"private": true,
|
"private": true,
|
||||||
"type": "module",
|
"type": "module",
|
||||||
|
|||||||
@@ -12,11 +12,11 @@ CREATE TABLE `clients_table` (
|
|||||||
`public_key` text NOT NULL,
|
`public_key` text NOT NULL,
|
||||||
`pre_shared_key` text NOT NULL,
|
`pre_shared_key` text NOT NULL,
|
||||||
`expires_at` text,
|
`expires_at` text,
|
||||||
`allowed_ips` text NOT NULL,
|
`allowed_ips` text,
|
||||||
`server_allowed_ips` text NOT NULL,
|
`server_allowed_ips` text NOT NULL,
|
||||||
`persistent_keepalive` integer NOT NULL,
|
`persistent_keepalive` integer NOT NULL,
|
||||||
`mtu` integer NOT NULL,
|
`mtu` integer NOT NULL,
|
||||||
`dns` text NOT NULL,
|
`dns` text,
|
||||||
`enabled` integer NOT NULL,
|
`enabled` integer NOT NULL,
|
||||||
`created_at` text DEFAULT (CURRENT_TIMESTAMP) NOT NULL,
|
`created_at` text DEFAULT (CURRENT_TIMESTAMP) NOT NULL,
|
||||||
`updated_at` text DEFAULT (CURRENT_TIMESTAMP) NOT NULL,
|
`updated_at` text DEFAULT (CURRENT_TIMESTAMP) NOT NULL,
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"version": "6",
|
"version": "6",
|
||||||
"dialect": "sqlite",
|
"dialect": "sqlite",
|
||||||
"id": "383501e4-f8de-4413-847f-a9082f6dc398",
|
"id": "8c2af02b-c4bd-4880-a9ad-b38805636208",
|
||||||
"prevId": "00000000-0000-0000-0000-000000000000",
|
"prevId": "00000000-0000-0000-0000-000000000000",
|
||||||
"tables": {
|
"tables": {
|
||||||
"clients_table": {
|
"clients_table": {
|
||||||
@@ -106,7 +106,7 @@
|
|||||||
"name": "allowed_ips",
|
"name": "allowed_ips",
|
||||||
"type": "text",
|
"type": "text",
|
||||||
"primaryKey": false,
|
"primaryKey": false,
|
||||||
"notNull": true,
|
"notNull": false,
|
||||||
"autoincrement": false
|
"autoincrement": false
|
||||||
},
|
},
|
||||||
"server_allowed_ips": {
|
"server_allowed_ips": {
|
||||||
@@ -134,7 +134,7 @@
|
|||||||
"name": "dns",
|
"name": "dns",
|
||||||
"type": "text",
|
"type": "text",
|
||||||
"primaryKey": false,
|
"primaryKey": false,
|
||||||
"notNull": true,
|
"notNull": false,
|
||||||
"autoincrement": false
|
"autoincrement": false
|
||||||
},
|
},
|
||||||
"enabled": {
|
"enabled": {
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"id": "bf316694-e2ce-4e29-bd66-ce6c0a9d3c90",
|
"id": "a61263b1-9af1-4d2e-99e9-80d08127b545",
|
||||||
"prevId": "383501e4-f8de-4413-847f-a9082f6dc398",
|
"prevId": "8c2af02b-c4bd-4880-a9ad-b38805636208",
|
||||||
"version": "6",
|
"version": "6",
|
||||||
"dialect": "sqlite",
|
"dialect": "sqlite",
|
||||||
"tables": {
|
"tables": {
|
||||||
@@ -106,7 +106,7 @@
|
|||||||
"name": "allowed_ips",
|
"name": "allowed_ips",
|
||||||
"type": "text",
|
"type": "text",
|
||||||
"primaryKey": false,
|
"primaryKey": false,
|
||||||
"notNull": true,
|
"notNull": false,
|
||||||
"autoincrement": false
|
"autoincrement": false
|
||||||
},
|
},
|
||||||
"server_allowed_ips": {
|
"server_allowed_ips": {
|
||||||
@@ -134,7 +134,7 @@
|
|||||||
"name": "dns",
|
"name": "dns",
|
||||||
"type": "text",
|
"type": "text",
|
||||||
"primaryKey": false,
|
"primaryKey": false,
|
||||||
"notNull": true,
|
"notNull": false,
|
||||||
"autoincrement": false
|
"autoincrement": false
|
||||||
},
|
},
|
||||||
"enabled": {
|
"enabled": {
|
||||||
|
|||||||
@@ -5,14 +5,14 @@
|
|||||||
{
|
{
|
||||||
"idx": 0,
|
"idx": 0,
|
||||||
"version": "6",
|
"version": "6",
|
||||||
"when": 1741335144499,
|
"when": 1741355094140,
|
||||||
"tag": "0000_short_skin",
|
"tag": "0000_short_skin",
|
||||||
"breakpoints": true
|
"breakpoints": true
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"idx": 1,
|
"idx": 1,
|
||||||
"version": "6",
|
"version": "6",
|
||||||
"when": 1741335153054,
|
"when": 1741355098159,
|
||||||
"tag": "0001_classy_the_stranger",
|
"tag": "0001_classy_the_stranger",
|
||||||
"breakpoints": true
|
"breakpoints": true
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,6 +3,8 @@ import { int, sqliteTable, text } from 'drizzle-orm/sqlite-core';
|
|||||||
|
|
||||||
import { oneTimeLink, user } from '../../schema';
|
import { oneTimeLink, user } from '../../schema';
|
||||||
|
|
||||||
|
/** null means use value from userConfig */
|
||||||
|
|
||||||
export const client = sqliteTable('clients_table', {
|
export const client = sqliteTable('clients_table', {
|
||||||
id: int().primaryKey({ autoIncrement: true }),
|
id: int().primaryKey({ autoIncrement: true }),
|
||||||
userId: int('user_id')
|
userId: int('user_id')
|
||||||
@@ -22,13 +24,13 @@ export const client = sqliteTable('clients_table', {
|
|||||||
publicKey: text('public_key').notNull(),
|
publicKey: text('public_key').notNull(),
|
||||||
preSharedKey: text('pre_shared_key').notNull(),
|
preSharedKey: text('pre_shared_key').notNull(),
|
||||||
expiresAt: text('expires_at'),
|
expiresAt: text('expires_at'),
|
||||||
allowedIps: text('allowed_ips', { mode: 'json' }).$type<string[]>().notNull(),
|
allowedIps: text('allowed_ips', { mode: 'json' }).$type<string[]>(),
|
||||||
serverAllowedIps: text('server_allowed_ips', { mode: 'json' })
|
serverAllowedIps: text('server_allowed_ips', { mode: 'json' })
|
||||||
.$type<string[]>()
|
.$type<string[]>()
|
||||||
.notNull(),
|
.notNull(),
|
||||||
persistentKeepalive: int('persistent_keepalive').notNull(),
|
persistentKeepalive: int('persistent_keepalive').notNull(),
|
||||||
mtu: int().notNull(),
|
mtu: int().notNull(),
|
||||||
dns: text({ mode: 'json' }).$type<string[]>().notNull(),
|
dns: text({ mode: 'json' }).$type<string[]>(),
|
||||||
enabled: int({ mode: 'boolean' }).notNull(),
|
enabled: int({ mode: 'boolean' }).notNull(),
|
||||||
createdAt: text('created_at')
|
createdAt: text('created_at')
|
||||||
.notNull()
|
.notNull()
|
||||||
|
|||||||
@@ -115,8 +115,6 @@ export class ClientService {
|
|||||||
ipv4Address,
|
ipv4Address,
|
||||||
ipv6Address,
|
ipv6Address,
|
||||||
mtu: clientConfig.defaultMtu,
|
mtu: clientConfig.defaultMtu,
|
||||||
allowedIps: clientConfig.defaultAllowedIps,
|
|
||||||
dns: clientConfig.defaultDns,
|
|
||||||
persistentKeepalive: clientConfig.defaultPersistentKeepalive,
|
persistentKeepalive: clientConfig.defaultPersistentKeepalive,
|
||||||
serverAllowedIps: [],
|
serverAllowedIps: [],
|
||||||
enabled: true,
|
enabled: true,
|
||||||
|
|||||||
@@ -61,11 +61,11 @@ export const ClientUpdateSchema = schemaForType<UpdateClientType>()(
|
|||||||
postUp: HookSchema,
|
postUp: HookSchema,
|
||||||
preDown: HookSchema,
|
preDown: HookSchema,
|
||||||
postDown: HookSchema,
|
postDown: HookSchema,
|
||||||
allowedIps: AllowedIpsSchema,
|
allowedIps: AllowedIpsSchema.nullable(),
|
||||||
serverAllowedIps: serverAllowedIps,
|
serverAllowedIps: serverAllowedIps,
|
||||||
mtu: MtuSchema,
|
mtu: MtuSchema,
|
||||||
persistentKeepalive: PersistentKeepaliveSchema,
|
persistentKeepalive: PersistentKeepaliveSchema,
|
||||||
dns: DnsSchema,
|
dns: DnsSchema.nullable(),
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|||||||
@@ -59,13 +59,13 @@ PostDown = ${iptablesTemplate(hooks.postDown, wgInterface)}`;
|
|||||||
return `[Interface]
|
return `[Interface]
|
||||||
PrivateKey = ${client.privateKey}
|
PrivateKey = ${client.privateKey}
|
||||||
Address = ${client.ipv4Address}/${cidr4Block}, ${client.ipv6Address}/${cidr6Block}
|
Address = ${client.ipv4Address}/${cidr4Block}, ${client.ipv6Address}/${cidr6Block}
|
||||||
DNS = ${client.dns.join(', ')}
|
DNS = ${(client.dns ?? userConfig.defaultDns).join(', ')}
|
||||||
MTU = ${client.mtu}
|
MTU = ${client.mtu}
|
||||||
${hookLines.length ? `${hookLines.join('\n')}\n` : ''}
|
${hookLines.length ? `${hookLines.join('\n')}\n` : ''}
|
||||||
[Peer]
|
[Peer]
|
||||||
PublicKey = ${wgInterface.publicKey}
|
PublicKey = ${wgInterface.publicKey}
|
||||||
PresharedKey = ${client.preSharedKey}
|
PresharedKey = ${client.preSharedKey}
|
||||||
AllowedIPs = ${client.allowedIps.join(', ')}
|
AllowedIPs = ${(client.allowedIps ?? userConfig.defaultAllowedIps).join(', ')}
|
||||||
PersistentKeepalive = ${client.persistentKeepalive}
|
PersistentKeepalive = ${client.persistentKeepalive}
|
||||||
Endpoint = ${userConfig.host}:${userConfig.port}`;
|
Endpoint = ${userConfig.host}:${userConfig.port}`;
|
||||||
},
|
},
|
||||||
|
|||||||
Reference in New Issue
Block a user