Compare commits

..

24 Commits

Author SHA1 Message Date
Bernd Storath 7964dc7993 Bump version to 15.2.0 2026-01-12 08:28:23 +01:00
RaffaelHold 0ac5d7d461 feat(docs): Extend docs for routed setup with nftables (#2380)
* Extend docs for routed setup with nftables

When using nftables in a routed setup different up and down hooks need to be used. 
To limit interaction with docker managed chains a custom WG_EASY chain is added as a jump target.
Since nft only supports deletion via handles awk is needed to get the handle of the jump rule for deletion

* Remove link to podman-nft

* Fix formatting according to prettier rules

* Add additional whitespace
2026-01-12 08:21:18 +01:00
Bernd Storath 826914a4f3 update packages 2026-01-12 08:19:01 +01:00
Bernd Storath 261da431e7 Fix: reset onetimelink expiration instead of failing (#2370)
* update expiresAt instead of failing

* add changelog
2025-12-29 19:12:53 +01:00
Bernd Storath 94b33abf5e Remove armv7 support (#2369)
remove armv7 support
2025-12-29 18:54:47 +01:00
Bernd Storath 8325056ccc update lockfile 2025-12-29 18:47:48 +01:00
Bernd Storath 81a1b2c907 update packages 2025-12-29 18:36:51 +01:00
dependabot[bot] fc8f89fb83 build(deps): bump actions/download-artifact from 6 to 7 (#2343)
Bumps [actions/download-artifact](https://github.com/actions/download-artifact) from 6 to 7.
- [Release notes](https://github.com/actions/download-artifact/releases)
- [Commits](https://github.com/actions/download-artifact/compare/v6...v7)

---
updated-dependencies:
- dependency-name: actions/download-artifact
  dependency-version: '7'
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-12-18 07:58:23 +01:00
dependabot[bot] d846c7745f build(deps): bump actions/upload-artifact from 5 to 6 (#2344)
Bumps [actions/upload-artifact](https://github.com/actions/upload-artifact) from 5 to 6.
- [Release notes](https://github.com/actions/upload-artifact/releases)
- [Commits](https://github.com/actions/upload-artifact/compare/v5...v6)

---
updated-dependencies:
- dependency-name: actions/upload-artifact
  dependency-version: '6'
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-12-18 07:58:12 +01:00
Bernd Storath 61c6fd6c02 update packages 2025-12-15 08:03:25 +01:00
David DIVERRES abe5708058 Update fr.json (#2326)
Update fr.json - Add missing translations and improve existing ones

- Add missing keys: client.delete, client.search, client.config, client.viewConfig
- Add complete copy section (4 keys)
- Add complete awg section (27 keys for AmneziaWG parameters)
- Fix terminology: "double facteur" → "deux facteurs" (standard French)
- Fix zod.generic.validBoolean translation
- Fix zod.generic.stringMin capitalization and wording
- Translate zod.client.id to French
- Improve admin.general route descriptions
2025-12-08 08:51:38 +01:00
Bernd Storath 626339bddb update packages 2025-12-08 08:30:53 +01:00
Danya 381ae23c07 Update ru (#2324)
* Update ru.json

Full revision of the Russian localization for the AWG configuration block, including terminology corrections, improved consistency, and clarified parameter descriptions.

* Update ru.json

* fix formatting

---------

Co-authored-by: Bernd Storath <999999bst@gmail.com>
2025-12-05 15:59:12 +01:00
Nikolas 52382d1d7a Update uk.json (#2323) 2025-12-05 07:35:15 +01:00
Mike 68e5216d4b Update ru.json (#2319)
* Update ru.json

* format

---------

Co-authored-by: Bernd Storath <999999bst@gmail.com>
2025-12-02 12:26:04 +01:00
Bernd Storath ceff95b336 Bump version to 15.2.0-beta.3 2025-12-01 10:12:01 +01:00
Alexander Chepurnoy 782d1c215f feat(docs): edit amnezia page (#2292)
* feat(docs): edit amnezia page

* Fix AmneziaWG documentation link

* Update AmneziaWG client compatibility information
2025-12-01 08:23:01 +01:00
Bernd Storath e8e26cfe10 update packages 2025-12-01 07:54:59 +01:00
Bernd Storath 400d4d992e Fix light mode admin menu active text color (#2307)
* fix color

* remove duplicates
2025-11-25 08:26:18 +01:00
Bernd Storath b08df55321 fix build 2025-11-24 08:03:37 +01:00
Bernd Storath b26a8110e0 update packages 2025-11-24 08:01:11 +01:00
杨黄林 692f550596 Improve zh-CN translate (#2298)
Fix zh-CN translate

Co-authored-by: yanghuanglin <yanghuanglin@qq.com>
2025-11-24 07:57:17 +01:00
Chiahong badae8b8e4 fix(i18n): Add missing translation for delete action (#2295) 2025-11-21 17:55:11 +01:00
Nikolas 7f89bde99e Update uk.json (#2293) 2025-11-21 08:02:47 +01:00
25 changed files with 2221 additions and 1900 deletions
+1 -1
View File
@@ -27,7 +27,7 @@ jobs:
steps: steps:
- name: Checkout repository - name: Checkout repository
uses: actions/checkout@v5 uses: actions/checkout@v6
- name: Initialize CodeQL - name: Initialize CodeQL
uses: github/codeql-action/init@v4 uses: github/codeql-action/init@v4
+6 -6
View File
@@ -18,10 +18,10 @@ jobs:
os: ubuntu-latest os: ubuntu-latest
- platform: linux/arm64 - platform: linux/arm64
os: ubuntu-24.04-arm os: ubuntu-24.04-arm
- platform: linux/arm/v7 # - platform: linux/arm/v7
os: ubuntu-24.04-arm # os: ubuntu-24.04-arm
steps: steps:
- uses: actions/checkout@v5 - uses: actions/checkout@v6
- name: Prepare - name: Prepare
run: | run: |
@@ -69,7 +69,7 @@ jobs:
touch "${{ runner.temp }}/digests/${digest#sha256:}" touch "${{ runner.temp }}/digests/${digest#sha256:}"
- name: Upload digest - name: Upload digest
uses: actions/upload-artifact@v5 uses: actions/upload-artifact@v6
with: with:
name: digests-${{ env.PLATFORM_PAIR }} name: digests-${{ env.PLATFORM_PAIR }}
path: ${{ runner.temp }}/digests/* path: ${{ runner.temp }}/digests/*
@@ -85,7 +85,7 @@ jobs:
needs: docker-build needs: docker-build
steps: steps:
- name: Download digests - name: Download digests
uses: actions/download-artifact@v6 uses: actions/download-artifact@v7
with: with:
path: ${{ runner.temp }}/digests path: ${{ runner.temp }}/digests
pattern: digests-* pattern: digests-*
@@ -138,7 +138,7 @@ jobs:
contents: write contents: write
needs: docker-merge needs: docker-merge
steps: steps:
- uses: actions/checkout@v5 - uses: actions/checkout@v6
- name: Setup Python - name: Setup Python
uses: actions/setup-python@v6 uses: actions/setup-python@v6
+6 -6
View File
@@ -25,10 +25,10 @@ jobs:
os: ubuntu-latest os: ubuntu-latest
- platform: linux/arm64 - platform: linux/arm64
os: ubuntu-24.04-arm os: ubuntu-24.04-arm
- platform: linux/arm/v7 # - platform: linux/arm/v7
os: ubuntu-24.04-arm # os: ubuntu-24.04-arm
steps: steps:
- uses: actions/checkout@v5 - uses: actions/checkout@v6
with: with:
ref: master ref: master
@@ -78,7 +78,7 @@ jobs:
touch "${{ runner.temp }}/digests/${digest#sha256:}" touch "${{ runner.temp }}/digests/${digest#sha256:}"
- name: Upload digest - name: Upload digest
uses: actions/upload-artifact@v5 uses: actions/upload-artifact@v6
with: with:
name: digests-${{ env.PLATFORM_PAIR }} name: digests-${{ env.PLATFORM_PAIR }}
path: ${{ runner.temp }}/digests/* path: ${{ runner.temp }}/digests/*
@@ -94,7 +94,7 @@ jobs:
needs: docker-build needs: docker-build
steps: steps:
- name: Download digests - name: Download digests
uses: actions/download-artifact@v6 uses: actions/download-artifact@v7
with: with:
path: ${{ runner.temp }}/digests path: ${{ runner.temp }}/digests
pattern: digests-* pattern: digests-*
@@ -147,7 +147,7 @@ jobs:
contents: write contents: write
needs: docker-merge needs: docker-merge
steps: steps:
- uses: actions/checkout@v5 - uses: actions/checkout@v6
with: with:
ref: master ref: master
+3 -3
View File
@@ -21,10 +21,10 @@ jobs:
os: ubuntu-latest os: ubuntu-latest
- platform: linux/arm64 - platform: linux/arm64
os: ubuntu-24.04-arm os: ubuntu-24.04-arm
- platform: linux/arm/v7 # - platform: linux/arm/v7
os: ubuntu-24.04-arm # os: ubuntu-24.04-arm
steps: steps:
- uses: actions/checkout@v5 - uses: actions/checkout@v6
- name: Prepare - name: Prepare
run: | run: |
+6 -6
View File
@@ -26,10 +26,10 @@ jobs:
os: ubuntu-latest os: ubuntu-latest
- platform: linux/arm64 - platform: linux/arm64
os: ubuntu-24.04-arm os: ubuntu-24.04-arm
- platform: linux/arm/v7 # - platform: linux/arm/v7
os: ubuntu-24.04-arm # os: ubuntu-24.04-arm
steps: steps:
- uses: actions/checkout@v5 - uses: actions/checkout@v6
- name: Prepare - name: Prepare
run: | run: |
@@ -77,7 +77,7 @@ jobs:
touch "${{ runner.temp }}/digests/${digest#sha256:}" touch "${{ runner.temp }}/digests/${digest#sha256:}"
- name: Upload digest - name: Upload digest
uses: actions/upload-artifact@v5 uses: actions/upload-artifact@v6
with: with:
name: digests-${{ env.PLATFORM_PAIR }} name: digests-${{ env.PLATFORM_PAIR }}
path: ${{ runner.temp }}/digests/* path: ${{ runner.temp }}/digests/*
@@ -95,7 +95,7 @@ jobs:
needs: docker-build needs: docker-build
steps: steps:
- name: Download digests - name: Download digests
uses: actions/download-artifact@v6 uses: actions/download-artifact@v7
with: with:
path: ${{ runner.temp }}/digests path: ${{ runner.temp }}/digests
pattern: digests-* pattern: digests-*
@@ -152,7 +152,7 @@ jobs:
contents: write contents: write
needs: docker-merge needs: docker-merge
steps: steps:
- uses: actions/checkout@v5 - uses: actions/checkout@v6
- name: Setup Python - name: Setup Python
uses: actions/setup-python@v6 uses: actions/setup-python@v6
+2 -2
View File
@@ -14,7 +14,7 @@ jobs:
steps: steps:
- name: Checkout repository - name: Checkout repository
uses: actions/checkout@v5 uses: actions/checkout@v6
- uses: pnpm/action-setup@v4 - uses: pnpm/action-setup@v4
name: Install pnpm name: Install pnpm
@@ -47,7 +47,7 @@ jobs:
steps: steps:
- name: Checkout repository - name: Checkout repository
uses: actions/checkout@v5 uses: actions/checkout@v6
- uses: pnpm/action-setup@v4 - uses: pnpm/action-setup@v4
name: Install pnpm name: Install pnpm
+11 -5
View File
@@ -7,7 +7,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
## [Unreleased] ## [Unreleased]
## Added ## [15.2.0] - 2026-01-12
### Added
- AmneziaWG integration (https://github.com/wg-easy/wg-easy/pull/2102, https://github.com/wg-easy/wg-easy/pull/2226) - AmneziaWG integration (https://github.com/wg-easy/wg-easy/pull/2102, https://github.com/wg-easy/wg-easy/pull/2226)
- Search / filter box (https://github.com/wg-easy/wg-easy/pull/2170) - Search / filter box (https://github.com/wg-easy/wg-easy/pull/2170)
@@ -15,12 +17,13 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Show client endpoint (https://github.com/wg-easy/wg-easy/pull/2058) - Show client endpoint (https://github.com/wg-easy/wg-easy/pull/2058)
- Add option to view and copy config (https://github.com/wg-easy/wg-easy/pull/2289) - Add option to view and copy config (https://github.com/wg-easy/wg-easy/pull/2289)
## Fixed ### Fixed
- Fix download as conf.txt (https://github.com/wg-easy/wg-easy/pull/2269) - Fix download as conf.txt (https://github.com/wg-easy/wg-easy/pull/2269)
- Clean filename for OTL download (https://github.com/wg-easy/wg-easy/pull/2253) - Clean filename for OTL download (https://github.com/wg-easy/wg-easy/pull/2253)
- Text color in admin menu in light mode (https://github.com/wg-easy/wg-easy/pull/2307)
## Changed ### Changed
- Allow lower MTU (https://github.com/wg-easy/wg-easy/pull/2228) - Allow lower MTU (https://github.com/wg-easy/wg-easy/pull/2228)
- Use /32 and /128 for client Cidr (https://github.com/wg-easy/wg-easy/pull/2217) - Use /32 and /128 for client Cidr (https://github.com/wg-easy/wg-easy/pull/2217)
@@ -29,11 +32,14 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Allow empty DNS (https://github.com/wg-easy/wg-easy/pull/2052, https://github.com/wg-easy/wg-easy/pull/2057) - Allow empty DNS (https://github.com/wg-easy/wg-easy/pull/2052, https://github.com/wg-easy/wg-easy/pull/2057)
- Don't include keys in API responses (https://github.com/wg-easy/wg-easy/pull/2015) - Don't include keys in API responses (https://github.com/wg-easy/wg-easy/pull/2015)
- Try all QR ecc levels (https://github.com/wg-easy/wg-easy/pull/2288) - Try all QR ecc levels (https://github.com/wg-easy/wg-easy/pull/2288)
- Update OneTimeLink expiry on reuse (https://github.com/wg-easy/wg-easy/pull/2370)
- Removed ARMv7 support (https://github.com/wg-easy/wg-easy/pull/2369)
## Docs ### Docs
- Add AdGuard Home (https://github.com/wg-easy/wg-easy/pull/2175) - Add AdGuard Home (https://github.com/wg-easy/wg-easy/pull/2175)
- Add Routed (No NAT) docs (https://github.com/wg-easy/wg-easy/pull/2181) - Add Routed (No NAT) docs (https://github.com/wg-easy/wg-easy/pull/2181, https://github.com/wg-easy/wg-easy/pull/2380)
- Add AmneziaWG docs (https://github.com/wg-easy/wg-easy/pull/2108, https://github.com/wg-easy/wg-easy/pull/2292)
## [15.1.0] - 2025-07-01 ## [15.1.0] - 2025-07-01
+47 -5
View File
@@ -2,7 +2,9 @@
title: AmneziaWG title: AmneziaWG
--- ---
Experimental support for AmneziaWG can be enabled by setting the `EXPERIMENTAL_AWG` environment variable to `true`. This feature is still under development and may change in future releases. ## Introduction
**AmneziaWG** is a modified version of the WireGuard protocol with enhanced traffic obfuscation capabilities. AmneziaWG's primary goal is to counter deep packet inspection (DPI) systems and bypass VPN blocking.
AmneziaWG adds multi-level transport-layer obfuscation by: AmneziaWG adds multi-level transport-layer obfuscation by:
@@ -12,6 +14,12 @@ AmneziaWG adds multi-level transport-layer obfuscation by:
These measures make it harder for third parties to analyze or identify your traffic, enhancing both privacy and security. These measures make it harder for third parties to analyze or identify your traffic, enhancing both privacy and security.
## Activating AmneziaWG
You must install the [AmneziaWG kernel module](https://github.com/amnezia-vpn/amneziawg-linux-kernel-module) on the host system.
Experimental support for AmneziaWG can be enabled by setting the `EXPERIMENTAL_AWG` environment variable to `true`. Starting from wg-easy version 16, this setting will be enabled by default. This feature is still under development and may change in future releases.
When enabled, wg-easy will automatically detect whether the AmneziaWG kernel module is available. If it is not, the system will fall back to the standard WireGuard module. When enabled, wg-easy will automatically detect whether the AmneziaWG kernel module is available. If it is not, the system will fall back to the standard WireGuard module.
To override this automatic detection, set the `OVERRIDE_AUTO_AWG` environment variable. By default, this variable is unset. To override this automatic detection, set the `OVERRIDE_AUTO_AWG` environment variable. By default, this variable is unset.
@@ -21,17 +29,51 @@ Possible values:
- `awg` — Force use of AmneziaWG - `awg` — Force use of AmneziaWG
- `wg` — Force use of standard WireGuard - `wg` — Force use of standard WireGuard
To be able to connect to wg-easy if AmneziaWG is enabled, you must have a AmneziaWG-compatible client. ## AmneziaWG Parameters
Parameter descriptions can be found in the [AmneziaWG documentation](https://docs.amnezia.org/documentation/amnezia-wg) and on the [kernel module page](https://github.com/amnezia-vpn/amneziawg-linux-kernel-module).
All parameters except I1-I5 will be set at first startup. For information on how to set I1-I5 parameters, refer to the [AmneziaWG documentation](https://docs.amnezia.org/documentation/instructions/new-amneziawg-selfhosted/#how-to-extract-a-protocol-signature-for-amneziawg-15-manually).
If a parameter is not set, it will not be added to the configuration. If all AmneziaWG-specific parameters are absent, AmneziaWG will be fully compatible with standard WireGuard.
### Parameter Compatibility Table
| Parameter | Can differ between server and client | Configurable on server | Configurable on client |
| --------- | ------------------------------------ | ---------------------- | ----------------------- |
| Jc | ✅ Yes | ✅ | ✅ |
| Jmin | ✅ Yes | ✅ | ✅ |
| Jmax | ✅ Yes | ✅ | ✅ |
| S1-S4 | ❌ No, must match | ✅ | ❌ (copied from server) |
| H1-H4 | ❌ No, must match | ✅ | ❌ (copied from server) |
| I1-I5 | ✅ Yes | ✅ | ✅ |
## Client Applications
To be able to connect to wg-easy if AmneziaWG is enabled, you must have an AmneziaWG-compatible client. Currently, only WG Tunnel and Amnezia VPN supports AmneziaWG 1.5/2.0! AmneziaWG clients require building from source code.
Android: Android:
- [AmneziaWG](https://play.google.com/store/apps/details?id=org.amnezia.awg) - Official Client - [Amnezia VPN](https://play.google.com/store/apps/details?id=org.amnezia.vpn) - Amnezia VPN Official Client
- [AmneziaWG](https://play.google.com/store/apps/details?id=org.amnezia.awg) - AmneziaWG Official Client
- [WG Tunnel](https://play.google.com/store/apps/details?id=com.zaneschepke.wireguardautotunnel) - Third Party Client - [WG Tunnel](https://play.google.com/store/apps/details?id=com.zaneschepke.wireguardautotunnel) - Third Party Client
iOS and macOS: iOS and macOS:
- [AmneziaWG](https://apps.apple.com/us/app/amneziawg/id6478942365) - Official Client - [Amnezia VPN](https://apps.apple.com/us/app/amneziavpn/id1600529900) - Amnezia VPN Official Client
- [AmneziaWG](https://apps.apple.com/us/app/amneziawg/id6478942365) - AmneziaWG Official Client
Windows: Windows:
- [AmneziaWG](https://github.com/amnezia-vpn/amneziawg-windows-client/releases) - Official Client - [Amnezia VPN](https://amnezia.org/downloads) - Amnezia VPN Official Client
- [AmneziaWG](https://github.com/amnezia-vpn/amneziawg-windows-client/releases) - AmneziaWG Official Client
Linux:
- [Amnezia VPN](https://amnezia.org/downloads) - Amnezia VPN Official Client
- [amneziawg-tools](https://github.com/amnezia-vpn/amneziawg-tools) - AmneziaWG Tools
OpenWRT:
- [AmneziaWG OpenWRT](https://github.com/Slava-Shchipunov/awg-openwrt) - AmneziaWG OpenWRT Packages
- [AmneziaWG OpenWRT](https://github.com/lolo6oT/awg-openwrt) - AmneziaWG OpenWRT Packages
@@ -7,7 +7,7 @@ This guide will help you migrate from `v14` to version `v15` of `wg-easy`.
## Changes ## Changes
- This is a complete rewrite of the `wg-easy` project, therefore the configuration files and the way you interact with the project have changed. - This is a complete rewrite of the `wg-easy` project, therefore the configuration files and the way you interact with the project have changed.
- If you use armv6, you unfortunately won't be able to migrate to `v15`. - If you use armv6 or armv7, you unfortunately won't be able to migrate to `v15`.
- If you are connecting to the Web UI via HTTP, you need to set the `INSECURE` environment variable to `true` in the new container. - If you are connecting to the Web UI via HTTP, you need to set the `INSECURE` environment variable to `true` in the new container.
## Migration ## Migration
@@ -8,7 +8,7 @@ title: Basic Installation
1. You need to have a host that you can manage 1. You need to have a host that you can manage
2. You need to have a domain name or a public IP address 2. You need to have a domain name or a public IP address
3. You need a supported architecture (x86_64, arm64, armv7) 3. You need a supported architecture (x86_64, arm64)
4. You need curl installed on your host 4. You need curl installed on your host
## Install Docker ## Install Docker
+16
View File
@@ -93,3 +93,19 @@ PostDown
```shell ```shell
iptables -D INPUT -p udp -m udp --dport {{port}} -j ACCEPT; iptables -D FORWARD -i wg0 -j ACCEPT; iptables -D FORWARD -o wg0 -j ACCEPT; ip6tables -D INPUT -p udp -m udp --dport {{port}} -j ACCEPT; ip6tables -D FORWARD -i wg0 -j ACCEPT; ip6tables -D FORWARD -o wg0 -j ACCEPT iptables -D INPUT -p udp -m udp --dport {{port}} -j ACCEPT; iptables -D FORWARD -i wg0 -j ACCEPT; iptables -D FORWARD -o wg0 -j ACCEPT; ip6tables -D INPUT -p udp -m udp --dport {{port}} -j ACCEPT; ip6tables -D FORWARD -i wg0 -j ACCEPT; ip6tables -D FORWARD -o wg0 -j ACCEPT
``` ```
/// warning | Important: When using nftables use the following hooks instead.
PostUp
```shell
nft add chain ip filter WG_EASY; nft add rule ip filter DOCKER-USER jump WG_EASY; nft add rule ip filter WG_EASY iifname {{device}} accept; nft add rule ip filter WG_EASY oifname {{device}} accept; nft add chain ip6 filter WG_EASY; nft add rule ip6 filter DOCKER-USER jump WG_EASY; nft add rule ip6 filter WG_EASY iifname {{device}} accept; nft add rule ip6 filter WG_EASY oifname {{device}} accept;
```
PostDown
```shell
nft delete rule ip filter DOCKER-USER handle $(nft -a list chain ip filter DOCKER-USER | awk '/jump WG_EASY/ {print $NF}'); nft flush chain ip filter WG_EASY; nft delete chain ip filter WG_EASY; nft delete rule ip6 filter DOCKER-USER handle $(nft -a list chain ip6 filter DOCKER-USER | awk '/jump WG_EASY/ {print $NF}'); nft flush chain ip6 filter WG_EASY; nft delete chain ip6 filter WG_EASY
```
///
+1 -1
View File
@@ -12,7 +12,7 @@ Before you can get started with deploying your own VPN, there are some requireme
1. You need to have a host that you can manage 1. You need to have a host that you can manage
2. You need to have a domain name or a public IP address 2. You need to have a domain name or a public IP address
3. You need a supported architecture (x86_64, arm64, armv7) 3. You need a supported architecture (x86_64, arm64)
### Host Setup ### Host Setup
+3 -2
View File
@@ -7,10 +7,11 @@
"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", "scripts:version": "bash scripts/version.sh",
"scripts:i18n": "bash scripts/i18n.sh",
"format:check:docs": "prettier --check docs" "format:check:docs": "prettier --check docs"
}, },
"devDependencies": { "devDependencies": {
"prettier": "^3.6.2" "prettier": "^3.7.4"
}, },
"packageManager": "pnpm@10.21.0" "packageManager": "pnpm@10.28.0"
} }
+5 -5
View File
@@ -9,16 +9,16 @@ importers:
.: .:
devDependencies: devDependencies:
prettier: prettier:
specifier: ^3.6.2 specifier: ^3.7.4
version: 3.6.2 version: 3.7.4
packages: packages:
prettier@3.6.2: prettier@3.7.4:
resolution: {integrity: sha512-I7AIg5boAr5R0FFtJ6rCfD+LFsWHp81dolrFD8S79U9tb8Az2nGrJncnMSnys+bpQJfRUzqs9hnA81OAA3hCuQ==} resolution: {integrity: sha512-v6UNi1+3hSlVvv8fSaoUbggEM5VErKmmpGA7Pl3HF8V6uKY7rvClBOJlH6yNwQtfTueNkGVpOv/mtWL9L4bgRA==}
engines: {node: '>=14'} engines: {node: '>=14'}
hasBin: true hasBin: true
snapshots: snapshots:
prettier@3.6.2: {} prettier@3.7.4: {}
+3 -2
View File
@@ -13,11 +13,12 @@
v-for="(item, index) in menuItems" v-for="(item, index) in menuItems"
:key="index" :key="index"
:to="`/admin/${item.id}`" :to="`/admin/${item.id}`"
active-class="bg-red-800 rounded" class="group rounded"
active-class="bg-red-800 active"
> >
<BaseSecondaryButton <BaseSecondaryButton
as="span" as="span"
class="w-full cursor-pointer rounded p-2 font-medium transition-colors duration-200 hover:bg-red-800 dark:text-neutral-200" class="w-full font-medium group-[.active]:text-white"
> >
{{ item.name }} {{ item.name }}
</BaseSecondaryButton> </BaseSecondaryButton>
+1 -1
View File
@@ -179,7 +179,7 @@
@delete="deleteClient" @delete="deleteClient"
> >
<FormSecondaryActionField <FormSecondaryActionField
label="Delete" :label="$t('client.delete')"
class="w-full" class="w-full"
type="button" type="button"
tabindex="-1" tabindex="-1"
+1
View File
@@ -88,6 +88,7 @@
"name": "Name", "name": "Name",
"expireDate": "Expire Date", "expireDate": "Expire Date",
"expireDateDesc": "Date the client will be disabled. Blank for permanent", "expireDateDesc": "Date the client will be disabled. Blank for permanent",
"delete": "Delete",
"deleteClient": "Delete Client", "deleteClient": "Delete Client",
"deleteDialog1": "Are you sure you want to delete", "deleteDialog1": "Are you sure you want to delete",
"deleteDialog2": "This action cannot be undone.", "deleteDialog2": "This action cannot be undone.",
+59 -13
View File
@@ -15,12 +15,12 @@
}, },
"me": { "me": {
"currentPassword": "Mot de passe actuel", "currentPassword": "Mot de passe actuel",
"enable2fa": "Activer l'authentification à double facteur", "enable2fa": "Activer l'authentification à deux facteurs",
"enable2faDesc": "Scannez le code QR avec votre application d'authentification ou saisissez la clé manuellement.", "enable2faDesc": "Scannez le code QR avec votre application d'authentification ou saisissez la clé manuellement.",
"2faKey": "Clé TOTP", "2faKey": "Clé TOTP",
"2faCodeDesc": "Saisissez le code de votre application d'authentification.", "2faCodeDesc": "Saisissez le code de votre application d'authentification.",
"disable2fa": "Désactiver l'authentification à double facteur", "disable2fa": "Désactiver l'authentification à deux facteurs",
"disable2faDesc": "Saisissez votre mot de passe pour désactiver l'authentification à double facteur" "disable2faDesc": "Saisissez votre mot de passe pour désactiver l'authentification à deux facteurs."
}, },
"general": { "general": {
"name": "Nom", "name": "Nom",
@@ -40,7 +40,7 @@
"no": "Non", "no": "Non",
"confirmPassword": "Confirmer le mot de passe", "confirmPassword": "Confirmer le mot de passe",
"loading": "Chargement...", "loading": "Chargement...",
"2fa": "Authentification à double facteur", "2fa": "Authentification à deux facteurs",
"2faCode": "Code TOTP" "2faCode": "Code TOTP"
}, },
"setup": { "setup": {
@@ -75,8 +75,8 @@
"rememberMe": "Se souvenir de moi", "rememberMe": "Se souvenir de moi",
"rememberMeDesc": "Rester connecté après avoir fermé le navigateur", "rememberMeDesc": "Rester connecté après avoir fermé le navigateur",
"insecure": "Vous ne pouvez pas vous connecter avec une connexion non sécurisée. Utilisez HTTPS.", "insecure": "Vous ne pouvez pas vous connecter avec une connexion non sécurisée. Utilisez HTTPS.",
"2faRequired": "Une authentification à double facteur est requise", "2faRequired": "L'authentification à deux facteurs est requise",
"2faWrong": "L'authentification à double facteur est incorrecte" "2faWrong": "Le code d'authentification à deux facteurs est incorrect"
}, },
"client": { "client": {
"empty": "Il n'y a pas encore de clients.", "empty": "Il n'y a pas encore de clients.",
@@ -108,7 +108,7 @@
"downloadConfig": "Télécharger la configuration", "downloadConfig": "Télécharger la configuration",
"allowedIpsDesc": "Quelles IPs seront acheminées par le VPN (remplace la configuration globale)", "allowedIpsDesc": "Quelles IPs seront acheminées par le VPN (remplace la configuration globale)",
"serverAllowedIpsDesc": "Les IPs que le serveur acheminera vers le client", "serverAllowedIpsDesc": "Les IPs que le serveur acheminera vers le client",
"mtuDesc": "Définit le nombre maximum d'unités de transmission (taille des paquets) pour le tunnel VPN.", "mtuDesc": "Définit l'unité de transmission maximale (taille des paquets) pour le tunnel VPN",
"persistentKeepaliveDesc": "Définit l'intervalle (en secondes) pour les paquets keep-alive. 0 le désactive", "persistentKeepaliveDesc": "Définit l'intervalle (en secondes) pour les paquets keep-alive. 0 le désactive",
"hooks": "Hooks", "hooks": "Hooks",
"hooksDescription": "Les hooks ne fonctionnent qu'avec wg-quick", "hooksDescription": "Les hooks ne fonctionnent qu'avec wg-quick",
@@ -116,7 +116,11 @@
"dnsDesc": "Serveur DNS que les clients utiliseront (remplace la configuration globale)", "dnsDesc": "Serveur DNS que les clients utiliseront (remplace la configuration globale)",
"notConnected": "Client non connecté", "notConnected": "Client non connecté",
"endpoint": "Endpoint", "endpoint": "Endpoint",
"endpointDesc": "Adresse IP du client à partir duquel la connexion WireGuard est établie" "endpointDesc": "Adresse IP du client à partir duquel la connexion WireGuard est établie",
"search": "Rechercher des clients...",
"config": "Configuration",
"viewConfig": "Voir la configuration",
"delete": "Supprimer"
}, },
"dialog": { "dialog": {
"change": "Modifier", "change": "Modifier",
@@ -146,9 +150,9 @@
"metricsPassword": "Mot de passe", "metricsPassword": "Mot de passe",
"metricsPasswordDesc": "Mot de passe Bearer pour le endpoint des métriques (mot de passe ou argon2 hash)", "metricsPasswordDesc": "Mot de passe Bearer pour le endpoint des métriques (mot de passe ou argon2 hash)",
"json": "JSON", "json": "JSON",
"jsonDesc": "Acheminement pour les métriques au format JSON", "jsonDesc": "Route pour les métriques au format JSON",
"prometheus": "Prometheus", "prometheus": "Prometheus",
"prometheusDesc": "Acheminement pour les métriques de Prometheus" "prometheusDesc": "Route pour les métriques Prometheus"
}, },
"config": { "config": {
"connection": "Connexion", "connection": "Connexion",
@@ -180,13 +184,13 @@
"required": "{0} est requis", "required": "{0} est requis",
"validNumber": "{0} doit être un nombre valide", "validNumber": "{0} doit être un nombre valide",
"validString": "{0} doit être une chaîne de caractères valide", "validString": "{0} doit être une chaîne de caractères valide",
"validBoolean": "{0} doit être une variable valide", "validBoolean": "{0} doit être un booléen valide",
"validArray": "{0} doit être un tableau valide", "validArray": "{0} doit être un tableau valide",
"stringMin": "{0} doit être d'au moins {1} Caractère", "stringMin": "{0} doit comporter au moins {1} caractère(s)",
"numberMin": "{0} doit être d'au moins {1}" "numberMin": "{0} doit être d'au moins {1}"
}, },
"client": { "client": {
"id": "Client ID", "id": "ID du client",
"name": "Nom", "name": "Nom",
"expiresAt": "Expire le", "expiresAt": "Expire le",
"address4": "Adresse IPv4", "address4": "Adresse IPv4",
@@ -236,5 +240,47 @@
"postUp": "PostUp", "postUp": "PostUp",
"preDown": "PreDown", "preDown": "PreDown",
"postDown": "PostDown" "postDown": "PostDown"
},
"copy": {
"notSupported": "La copie n'est pas prise en charge",
"copied": "Copié !",
"failed": "Échec de la copie",
"copy": "Copier"
},
"awg": {
"jCLabel": "Nombre de paquets parasites (Jc)",
"jCDescription": "Nombre de paquets parasites à envoyer (1-128, recommandé : 4-12)",
"jMinLabel": "Taille min des paquets parasites (Jmin)",
"jMinDescription": "Taille minimale des paquets parasites (0-1279*, recommandé : 8, doit être < Jmax)",
"jMaxLabel": "Taille max des paquets parasites (Jmax)",
"jMaxDescription": "Taille maximale des paquets parasites (1-1280*, recommandé : 80, doit être > Jmin)",
"s1Label": "Taille parasite du paquet init (S1)",
"s1Description": "Taille parasite du paquet d'initialisation (0-1132[1280* - 148 = 1132], recommandé : 15-150, S1+56 ≠ S2)",
"s2Label": "Taille parasite du paquet réponse (S2)",
"s2Description": "Taille parasite du paquet de réponse (0-1188[1280* - 92 = 1188], recommandé : 15-150)",
"s3Label": "Taille parasite du paquet cookie reply (S3)",
"s3Description": "Taille parasite du paquet de réponse cookie",
"s4Label": "Taille parasite du paquet transport (S4)",
"s4Description": "Taille parasite du paquet de transport",
"i1Label": "Paquet parasite spécial 1 (I1)",
"i1Description": "Paquet de simulation de protocole en format hexadécimal : <b 0x...>",
"i2Label": "Paquet parasite spécial 2 (I2)",
"i2Description": "Paquet de simulation de protocole en format hexadécimal : <b 0x...>",
"i3Label": "Paquet parasite spécial 3 (I3)",
"i3Description": "Paquet de simulation de protocole en format hexadécimal : <b 0x...>",
"i4Label": "Paquet parasite spécial 4 (I4)",
"i4Description": "Paquet de simulation de protocole en format hexadécimal : <b 0x...>",
"i5Label": "Paquet parasite spécial 5 (I5)",
"i5Description": "Paquet de simulation de protocole en format hexadécimal : <b 0x...>",
"h1Label": "En-tête magique init (H1)",
"h1Description": "Valeur d'en-tête du paquet init (5-2147483647, doit être unique par rapport à H2-H4)",
"h2Label": "En-tête magique réponse (H2)",
"h2Description": "Valeur d'en-tête du paquet réponse (5-2147483647, doit être unique par rapport à H1, H3, H4)",
"h3Label": "En-tête magique cookie reply (H3)",
"h3Description": "Valeur d'en-tête du paquet cookie reply (5-2147483647, doit être unique par rapport à H1, H2, H4)",
"h4Label": "En-tête magique transport (H4)",
"h4Description": "Valeur d'en-tête du paquet transport (5-2147483647, doit être unique par rapport à H1-H3)",
"mtuNote": "Les valeurs dépendent du MTU",
"obfuscationParameters": "Paramètres d'obfuscation AmneziaWG"
} }
} }
+117 -71
View File
@@ -3,8 +3,8 @@
"me": "Аккаунт", "me": "Аккаунт",
"clients": "Клиенты", "clients": "Клиенты",
"admin": { "admin": {
"panel": "Админ панель", "panel": "Админ-панель",
"general": "Общие", "general": "Общие настройки",
"config": "Конфигурация", "config": "Конфигурация",
"interface": "Интерфейс", "interface": "Интерфейс",
"hooks": "Хуки" "hooks": "Хуки"
@@ -16,11 +16,11 @@
"me": { "me": {
"currentPassword": "Текущий пароль", "currentPassword": "Текущий пароль",
"enable2fa": "Включить двухфакторную аутентификацию", "enable2fa": "Включить двухфакторную аутентификацию",
"enable2faDesc": "Отсканируйте QR-код приложением-аутентификатором или введите ключ вручную.", "enable2faDesc": "Отсканируйте QRкод с помощью приложения‑аутентификатора или введите ключ вручную.",
"2faKey": "TOTP-ключ", "2faKey": "Ключ TOTP",
"2faCodeDesc": "Введите код из приложения-аутентификатора.", "2faCodeDesc": "Введите код из приложенияаутентификатора.",
"disable2fa": "Отключить двухфакторную аутентификацию", "disable2fa": "Отключить двухфакторную аутентификацию",
"disable2faDesc": "Введите пароль, чтобы отключить двухфакторную аутентификацию" "disable2faDesc": "Введите пароль, чтобы отключить двухфакторную аутентификацию."
}, },
"general": { "general": {
"name": "Имя", "name": "Имя",
@@ -29,9 +29,9 @@
"newPassword": "Новый пароль", "newPassword": "Новый пароль",
"updatePassword": "Обновить пароль", "updatePassword": "Обновить пароль",
"mtu": "MTU", "mtu": "MTU",
"allowedIps": "Разрешённые IP", "allowedIps": "Разрешённые IP‑адреса",
"dns": "DNS", "dns": "DNS",
"persistentKeepalive": "Постоянный keepalive", "persistentKeepalive": "Постоянное поддержание соединения",
"logout": "Выйти", "logout": "Выйти",
"continue": "Продолжить", "continue": "Продолжить",
"host": "Хост", "host": "Хост",
@@ -41,21 +41,21 @@
"confirmPassword": "Подтвердите пароль", "confirmPassword": "Подтвердите пароль",
"loading": "Загрузка...", "loading": "Загрузка...",
"2fa": "Двухфакторная аутентификация", "2fa": "Двухфакторная аутентификация",
"2faCode": "TOTP‑код" "2faCode": "Код TOTP"
}, },
"setup": { "setup": {
"welcome": "Добро пожаловать в первичную настройку wg-easy", "welcome": "Добро пожаловать в первичную настройку wg-easy",
"welcomeDesc": "Вы нашли самый простой способ установить и управлять WireGuard на любом Linux-хосте", "welcomeDesc": "Вы нашли самый простой способ установить и управлять WireGuard на любом Linuxхосте",
"existingSetup": "У вас уже есть существующая установка?", "existingSetup": "У вас уже есть существующая настройка?",
"createAdminDesc": "Сначала введите имя администратора и надёжный пароль. Эти данные понадобятся для входа в панель управления", "createAdminDesc": "Сначала введите имя администратора и надёжный пароль. Эти данные будут использоваться для входа в Админ-панель.",
"setupConfigDesc": "Введите информацию о хосте и порте. Она будет использоваться в конфигурации клиента при установке WireGuard на устройствах", "setupConfigDesc": "Введите данные хоста и порта. Они будут использоваться для настройки клиента при установке WireGuard на устройствах.",
"setupMigrationDesc": "Укажите файл резервной копии, если хотите перенести данные из предыдущей версии wg-easy", "setupMigrationDesc": "Укажите файл резервной копии, если хотите перенести данные из предыдущей версии wg-easy.",
"upload": "Загрузить", "upload": "Загрузить",
"migration": "Восстановить из резервной копии:", "migration": "Восстановить из резервной копии:",
"createAccount": "Создать аккаунт", "createAccount": "Создать аккаунт",
"successful": "Настройка успешна", "successful": "Настройка завершена успешно",
"hostDesc": "Публичное имя хоста, к которому будут подключаться клиенты", "hostDesc": "Публичное имя хоста, к которому будут подключаться клиенты",
"portDesc": "Публичный UDP‑порт для подключения клиентов и прослушивания WireGuard" "portDesc": "Публичный UDP‑порт, к которому будут подключаться клиенты и на котором будет слушать WireGuard"
}, },
"update": { "update": {
"updateAvailable": "Доступно обновление!", "updateAvailable": "Доступно обновление!",
@@ -68,7 +68,7 @@
}, },
"layout": { "layout": {
"toggleCharts": "Показать/скрыть графики", "toggleCharts": "Показать/скрыть графики",
"donate": "Пожертвовать" "donate": "Поддержать"
}, },
"login": { "login": {
"signIn": "Войти", "signIn": "Войти",
@@ -87,18 +87,19 @@
"new": "Новый клиент", "new": "Новый клиент",
"name": "Имя", "name": "Имя",
"expireDate": "Дата отключения", "expireDate": "Дата отключения",
"expireDateDesc": "Дата, когда клиент будет отключён. Пусто — бессрочно", "expireDateDesc": "Дата, когда клиент будет отключён. Оставьте пустым для бессрочного доступа",
"delete": "Удалить",
"deleteClient": "Удалить клиента", "deleteClient": "Удалить клиента",
"deleteDialog1": "Вы уверены, что хотите удалить", "deleteDialog1": "Вы уверены, что хотите удалить",
"deleteDialog2": "Это действие необратимо.", "deleteDialog2": "Это действие нельзя отменить.",
"enabled": "Включен", "enabled": "Включён",
"address": "Адрес", "address": "Адрес",
"serverAllowedIps": "Разрешённые IP сервера", "serverAllowedIps": "Разрешённые IP‑адреса сервера",
"otlDesc": "Сгенерировать одноразовую короткую ссылку", "otlDesc": "Сгенерировать короткую одноразовую ссылку",
"permanent": "Постоянный", "permanent": "Бессрочный",
"createdOn": "Создан ", "createdOn": "Создан ",
"lastSeen": "Последнее подключение ", "lastSeen": "Последнее подключение ",
"totalDownload": "Всего загружено: ", "totalDownload": "Всего скачано: ",
"totalUpload": "Всего отправлено: ", "totalUpload": "Всего отправлено: ",
"newClient": "Новый клиент", "newClient": "Новый клиент",
"disableClient": "Отключить клиента", "disableClient": "Отключить клиента",
@@ -106,25 +107,28 @@
"noPrivKey": "У этого клиента нет приватного ключа. Невозможно создать конфигурацию.", "noPrivKey": "У этого клиента нет приватного ключа. Невозможно создать конфигурацию.",
"showQR": "Показать QR‑код", "showQR": "Показать QR‑код",
"downloadConfig": "Скачать конфигурацию", "downloadConfig": "Скачать конфигурацию",
"allowedIpsDesc": "Какие IP будут маршрутизироваться через VPN (перезаписывает общую конфигурацию)", "allowedIpsDesc": "Какие IP‑адреса будут маршрутизироваться через VPN (переопределяет глобальную конфигурацию)",
"serverAllowedIpsDesc": "Какие IP сервер будет отправлять клиенту", "serverAllowedIpsDesc": "Какие IP‑адреса сервер будет отправлять клиенту",
"mtuDesc": "Максимальный размер пакета для VPN‑туннеля", "mtuDesc": "Максимальный размер пакета (MTU) для VPN‑туннеля",
"persistentKeepaliveDesc": "Интервал пакетов для поддержания соединения (в секундах). 0 — отключено.", "persistentKeepaliveDesc": "Устанавливает интервал (в секундах) для пакетов поддержания соединения. 0 — отключить",
"hooks": "Хуки", "hooks": "Хуки",
"hooksDescription": "Хуки работают только с wg-quick", "hooksDescription": "Хуки работают только с wgquick",
"hooksLeaveEmpty": "Только для wg-quick. Иначе оставьте пустым", "hooksLeaveEmpty": "Только для wgquick. В остальных случаях оставьте пустым",
"dnsDesc": "DNS‑сервер, который будут использовать клиенты (перезаписывает общую конфигурацию)", "dnsDesc": "DNS‑сервер, который будут использовать клиенты (переопределяет глобальную конфигурацию)",
"notConnected": "Клиент не подключен", "notConnected": "Клиент не подключен",
"endpoint": "Конечная точка", "endpoint": "Точка подключения",
"endpointDesc": "IP-адрес клиента, с которого установлено соединение WireGuard" "endpointDesc": "IPадрес клиента, с которого установлено соединение WireGuard",
"search": "Поиск клиентов...",
"config": "Конфигурация",
"viewConfig": "Просмотреть конфигурацию"
}, },
"dialog": { "dialog": {
"change": "Изменить", "change": "Изменить",
"cancel": "Отмена", "cancel": "Отменить",
"create": "Создать" "create": "Создать"
}, },
"toast": { "toast": {
"success": "Успех", "success": "Успешно",
"saved": "Сохранено", "saved": "Сохранено",
"error": "Ошибка" "error": "Ошибка"
}, },
@@ -133,18 +137,18 @@
"save": "Сохранить", "save": "Сохранить",
"revert": "Отменить", "revert": "Отменить",
"sectionGeneral": "Общие", "sectionGeneral": "Общие",
"sectionAdvanced": "Дополнительно", "sectionAdvanced": "Расширенные",
"noItems": "Нет элементов", "noItems": "Нет элементов",
"nullNoItems": "Нет элементов. Используется глобальная конфигурация", "nullNoItems": "Нет элементов. Используется глобальная конфигурация",
"add": "Добавить" "add": "Добавить"
}, },
"admin": { "admin": {
"general": { "general": {
"sessionTimeout": "Тайм-аут сессии", "sessionTimeout": "Время жизни сессии",
"sessionTimeoutDesc": "Длительность сеанса для \"Запомнить меня\" (секунды)", "sessionTimeoutDesc": "Длительность сессии для «Запомнить меня» (в секундах)",
"metrics": "Метрики", "metrics": "Метрики",
"metricsPassword": "Пароль", "metricsPassword": "Пароль",
"metricsPasswordDesc": "Пароль Bearer для эндпоинта метрик (пароль или хеш argon2)", "metricsPasswordDesc": "Пароль Bearer для конечной точки метрик (пароль или хэш argon2)",
"json": "JSON", "json": "JSON",
"jsonDesc": "Путь для метрик в формате JSON", "jsonDesc": "Путь для метрик в формате JSON",
"prometheus": "Prometheus", "prometheus": "Prometheus",
@@ -152,83 +156,83 @@
}, },
"config": { "config": {
"connection": "Соединение", "connection": "Соединение",
"hostDesc": "Публичное имя хоста для подключения клиентов (сбросит конфигурацию)", "hostDesc": "Публичное имя хоста для подключения клиентов(обнуляет конфигурацию)",
"portDesc": "Публичный UDP‑порт для подключения клиентов (также стоит изменить порт интерфейса)", "portDesc": "Публичный UDP‑порт для подключения клиентов (также рекомендуется изменить порт интерфейса)",
"allowedIpsDesc": "Разрешённые IP для клиентов (общая конфигурация)", "allowedIpsDesc": "Разрешённые IP‑адреса для клиентов(глобальная конфигурация)",
"dnsDesc": "DNS‑сервер для клиентов (общая конфигурация)", "dnsDesc": "DNS‑сервер для клиентов (глобальная конфигурация)",
"mtuDesc": "MTU для клиентов (только для новых)", "mtuDesc": "MTU для клиентов (только для новых)",
"persistentKeepaliveDesc": "Интервал отправки keepalive на сервер (секунды). 0 = отключено (только для новых)", "persistentKeepaliveDesc": "Интервал в секундах для отправки пакетов поддержания соединения на сервер. 0 = отключено (только для новых клиентов)",
"suggest": "Определить", "suggest": "Предложить",
"suggestDesc": "Выберите IP‑адрес или имя хоста для поля Host" "suggestDesc": "Выберите IP‑адрес или имя хоста для поля «Хост»"
}, },
"interface": { "interface": {
"cidrSuccess": "CIDR изменён", "cidrSuccess": "CIDR изменён",
"device": "Устройство", "device": "Устройство",
"deviceDesc": "Сетевое устройство, через которое должен проходить трафик WireGuard", "deviceDesc": "Сетевое устройство Ethernet, через которое должен проходить трафик WireGuard",
"mtuDesc": "MTU, который использует WireGuard", "mtuDesc": "MTU, который будет использовать WireGuard",
"portDesc": "UDP‑порт, на котором WireGuard будет слушать (возможно, нужно изменить и порт конфигурации)", "portDesc": "UDP‑порт, на котором будет слушать WireGuard (возможно, нужно также изменить порт конфигурации)",
"changeCidr": "Изменить CIDR", "changeCidr": "Изменить CIDR",
"restart": "Перезапустить интерфейс", "restart": "Перезапустить интерфейс",
"restartDesc": "Перезапустить интерфейс WireGuard", "restartDesc": "Перезапустить интерфейс WireGuard",
"restartWarn": "Вы уверены, что хотите перезапустить интерфейс? Все клиенты будут отключены.", "restartWarn": "Вы уверены, что хотите перезапустить интерфейс? Это приведёт к отключению всех клиентов.",
"restartSuccess": "Интерфейс перезапущен" "restartSuccess": "Интерфейс перезапущен"
}, },
"introText": "Добро пожаловать в панель администратора.\n\nЗдесь вы можете управлять общими настройками, конфигурацией, параметрами интерфейса и хуками.\n\nНачните с выбора раздела в боковой панели." "introText": "Добро пожаловать в панель администратора.\n\nЗдесь вы можете управлять общими настройками, конфигурацией, настройками интерфейса и хуками.\n\nНачните с выбора одного из разделов на боковой панели."
}, },
"zod": { "zod": {
"generic": { "generic": {
"required": "{0} обязательное поле", "required": "{0} обязательно для заполнения",
"validNumber": "{0} должен быть числом", "validNumber": "{0} должно быть числом",
"validString": "{0} должна быть строкой", "validString": "{0} должно быть строкой",
"validBoolean": "{0} должен быть булевым значением", "validBoolean": "{0} должно быть логическим значением",
"validArray": "{0} должен быть массивом", "validArray": "{0} должно быть массивом",
"stringMin": "{0} должен содержать не менее {1} символов", "stringMin": "{0} должно содержать не менее {1} символа",
"numberMin": "{0} должен быть не меньше {1}" "numberMin": "{0} должно быть не менее {1}"
}, },
"client": { "client": {
"id": "ID клиента", "id": "ID клиента",
"name": "Имя", "name": "Имя",
"expiresAt": ействителен до", "expiresAt": ата окончания действия",
"address4": "IPv4 адрес", "address4": "IPv4адрес",
"address6": "IPv6 адрес", "address6": "IPv6адрес",
"serverAllowedIps": "Разрешённые IP сервера" "serverAllowedIps": "Разрешённые IP‑адреса сервера"
}, },
"user": { "user": {
"username": "Имя пользователя", "username": "Имя пользователя",
"password": "Пароль", "password": "Пароль",
"remember": "Запомнить", "remember": "Запомнить",
"name": "Имя", "name": "Имя",
"email": "Email", "email": "Электронная почта",
"emailInvalid": "Email должен быть валидным", "emailInvalid": "Адрес электронной почты должен быть корректным",
"passwordMatch": "Пароли должны совпадать", "passwordMatch": "Пароли должны совпадать",
"totpEnable": "Включить TOTP", "totpEnable": "Включить TOTP",
"totpEnableTrue": "Необходимо включить TOTP", "totpEnableTrue": "TOTP должен быть включён",
"totpCode": "TOTP‑код" "totpCode": "Код TOTP"
}, },
"userConfig": { "userConfig": {
"host": "Хост" "host": "Хост"
}, },
"general": { "general": {
"sessionTimeout": "Тайм-аут сессии", "sessionTimeout": "Время жизни сессии",
"metricsEnabled": "Метрики", "metricsEnabled": "Метрики",
"metricsPassword": "Пароль для метрик" "metricsPassword": "Пароль для метрик"
}, },
"interface": { "interface": {
"cidr": "CIDR", "cidr": "CIDR",
"device": "Устройство", "device": "Устройство",
"cidrValid": "CIDR должен быть валидным" "cidrValid": "CIDR должен быть корректным"
}, },
"otl": "Одноразовая ссылка", "otl": "Одноразовая ссылка",
"stringMalformed": "Строка имеет неверный формат", "stringMalformed": "Строка имеет неверный формат",
"body": "Тело должно быть объектом", "body": "Тело должно быть корректным объектом",
"hook": "Хук", "hook": "Хук",
"enabled": "Включено", "enabled": "Включено",
"mtu": "MTU", "mtu": "MTU",
"port": "Порт", "port": "Порт",
"persistentKeepalive": "Поддерживать соединение", "persistentKeepalive": "Постоянное поддержание соединения",
"address": "IP‑адрес", "address": "IP‑адрес",
"dns": "DNS", "dns": "DNS",
"allowedIps": "Разрешённые IP", "allowedIps": "Разрешённые IP‑адреса",
"file": "Файл" "file": "Файл"
}, },
"hooks": { "hooks": {
@@ -236,5 +240,47 @@
"postUp": "PostUp", "postUp": "PostUp",
"preDown": "PreDown", "preDown": "PreDown",
"postDown": "PostDown" "postDown": "PostDown"
},
"copy": {
"notSupported": "Копирование не поддерживается",
"copied": "Скопировано!",
"failed": "Ошибка копирования",
"copy": "Копировать"
},
"awg": {
"jCLabel": "Количество шумовых пакетов (Jc)",
"jCDescription": "Число шумовых пакетов для отправки (1-128, рекомендуется: 4-12)",
"jMinLabel": "Минимальный размер шумовых пакетов (Jmin)",
"jMinDescription": "Минимальный размер шумовых пакетов (0-1279*, рекомендуется: 8, должен быть < Jmax)",
"jMaxLabel": "Максимальный размер шумовых пакетов (Jmax)",
"jMaxDescription": "Максимальный размер шумовых пакетов (1-1280*, рекомендуется: 80, должен быть > Jmin)",
"s1Label": "Размер шумовых данных в init-пакете (S1)",
"s1Description": "Размер шумовых данных в init-пакете (0-1132[1280* - 148 = 1132], рекомендуется: 15-150, S1+56 ≠ S2)",
"s2Label": "Размер шумовых данных в ответном пакете (S2)",
"s2Description": "Размер шумовых данных в ответном пакете (0-1188[1280* - 92 = 1188], рекомендуется: 15-150)",
"s3Label": "Размер шумовых данных в cookie-reply пакете (S3)",
"s3Description": "Размер шумовых данных в cookie-reply пакете",
"s4Label": "Размер шумовых данных в транспортном пакете (S4)",
"s4Description": "Размер шумовых данных в транспортном пакете",
"i1Label": "Специальный шумовой пакет 1 (I1)",
"i1Description": "Пакет имитации протокола в hex формате: <b 0x...>",
"i2Label": "Специальный шумовой пакет 2 (I2)",
"i2Description": "Пакет имитации протокола в hex формате: <b 0x...>",
"i3Label": "Специальный шумовой пакет 3 (I3)",
"i3Description": "Пакет имитации протокола в hex формате: <b 0x...>",
"i4Label": "Специальный шумовой пакет 4 (I4)",
"i4Description": "Пакет имитации протокола в hex формате: <b 0x...>",
"i5Label": "Специальный шумовой пакет 5 (I5)",
"i5Description": "Пакет имитации протокола в hex формате: <b 0x...>",
"h1Label": "Init magic заголовок (H1)",
"h1Description": "Значение заголовка init-пакета (5-2147483647, должно отличаться от H2-H4)",
"h2Label": "Response magic заголовок (H2)",
"h2Description": "Значение заголовка ответного пакета (5-2147483647, должно отличаться от H1, H3, H4)",
"h3Label": "Cookie reply magic заголовок (H3)",
"h3Description": "Значение заголовка cookie-reply пакета (5-2147483647, должно отличаться от H1, H2, H4)",
"h4Label": "Transport magic заголовок (H4)",
"h4Description": "Значение заголовка транспортного пакета (5-2147483647, должно отличаться от H1-H3)",
"mtuNote": "Значения зависят от MTU",
"obfuscationParameters": "Параметры обфускации AmneziaWG"
} }
} }
+10 -1
View File
@@ -88,6 +88,7 @@
"name": "Ім'я", "name": "Ім'я",
"expireDate": "Термін дії", "expireDate": "Термін дії",
"expireDateDesc": "Дата, коли клієнт буде відключений. Порожнє для постійного користування", "expireDateDesc": "Дата, коли клієнт буде відключений. Порожнє для постійного користування",
"delete": "Видалити",
"deleteClient": "Видалити клієнта", "deleteClient": "Видалити клієнта",
"deleteDialog1": "Ви впевнені, що бажаєте видалити", "deleteDialog1": "Ви впевнені, що бажаєте видалити",
"deleteDialog2": "Цю дію неможливо скасувати.", "deleteDialog2": "Цю дію неможливо скасувати.",
@@ -117,7 +118,9 @@
"notConnected": "Клієнт не підключений", "notConnected": "Клієнт не підключений",
"endpoint": "Кінцева точка", "endpoint": "Кінцева точка",
"endpointDesc": "IP-адреса клієнта, з якої встановлюється з’єднання WireGuard", "endpointDesc": "IP-адреса клієнта, з якої встановлюється з’єднання WireGuard",
"search": "Пошук клієнтів..." "search": "Пошук клієнтів...",
"config": "Конфігурація",
"viewConfig": "Переглянути конфігурацію"
}, },
"dialog": { "dialog": {
"change": "Змінити", "change": "Змінити",
@@ -238,6 +241,12 @@
"preDown": "PreDown", "preDown": "PreDown",
"postDown": "PostDown" "postDown": "PostDown"
}, },
"copy": {
"notSupported": "Копіювання не підтримується",
"copied": "Скопійовано!",
"failed": "Не вдалося скопіювати",
"copy": "Копіювати"
},
"awg": { "awg": {
"jCLabel": "Кількість сміттєвих пакетів (Jc)", "jCLabel": "Кількість сміттєвих пакетів (Jc)",
"jCDescription": "Кількість сміттєвих пакетів для відправки (1–128, рекомендовано: 4–12)", "jCDescription": "Кількість сміттєвих пакетів для відправки (1–128, рекомендовано: 4–12)",
+51 -2
View File
@@ -88,8 +88,9 @@
"name": "客户端名称", "name": "客户端名称",
"expireDate": "过期日期", "expireDate": "过期日期",
"expireDateDesc": "客户端将被自动禁用的日期。留空表示永久有效", "expireDateDesc": "客户端将被自动禁用的日期。留空表示永久有效",
"delete": "删除客户端",
"deleteClient": "删除客户端", "deleteClient": "删除客户端",
"deleteDialog1": "您确定要删除客户端吗?", "deleteDialog1": "您确定要删除客户端",
"deleteDialog2": "此操作无法撤销。", "deleteDialog2": "此操作无法撤销。",
"enabled": "已启用", "enabled": "已启用",
"address": "IP地址", "address": "IP地址",
@@ -113,7 +114,13 @@
"hooks": "钩子脚本", "hooks": "钩子脚本",
"hooksDescription": "钩子脚本仅在使用wg-quick时有效", "hooksDescription": "钩子脚本仅在使用wg-quick时有效",
"hooksLeaveEmpty": "如果不使用wg-quick,请留空此字段", "hooksLeaveEmpty": "如果不使用wg-quick,请留空此字段",
"search": "搜索客户端..." "dnsDesc": "客户端将使用的 DNS 服务器(将覆盖全局配置)",
"notConnected": "客户端未连接",
"endpoint": "端点",
"endpointDesc": "建立 WireGuard 连接时客户端的 IP 地址",
"search": "搜索客户端...",
"config": "配置",
"viewConfig": "查看配置文本"
}, },
"dialog": { "dialog": {
"change": "确认修改", "change": "确认修改",
@@ -233,5 +240,47 @@
"postUp": "启动后脚本", "postUp": "启动后脚本",
"preDown": "停止前脚本", "preDown": "停止前脚本",
"postDown": "停止后脚本" "postDown": "停止后脚本"
},
"copy": {
"notSupported": "不支持复制",
"copied": "已复制!",
"failed": "复制失败",
"copy": "复制"
},
"awg": {
"jCLabel": "垃圾数据包计数(Jc",
"jCDescription": "发送的垃圾数据包数量(范围:1-128,推荐值:4-12",
"jMinLabel": "垃圾数据包最小尺寸(Jmin",
"jMinDescription": "垃圾数据包的最小尺寸(范围:0-1279*,推荐值:8,必须小于 Jmax",
"jMaxLabel": "垃圾数据包最大尺寸(Jmax",
"jMaxDescription": "垃圾数据包的最大尺寸(范围:1-1280*,推荐值:80,必须大于 Jmin",
"s1Label": "初始数据包垃圾数据大小(S1)",
"s1Description": "初始数据包中垃圾数据的大小(范围:0-1132[1280* - 148 = 1132],推荐值:15-150S1+56 ≠ S2",
"s2Label": "响应数据包垃圾数据大小(S2)",
"s2Description": "响应数据包中垃圾数据的大小(范围:0-1188[1280* - 92 = 1188],推荐值:15-150",
"s3Label": "Cookie 回复数据包垃圾数据大小(S3)",
"s3Description": "Cookie 回复数据包中垃圾数据的大小",
"s4Label": "传输数据包垃圾数据大小(S4)",
"s4Description": "传输数据包中垃圾数据的大小",
"i1Label": "特殊垃圾数据包 1I1",
"i1Description": "协议模拟数据包(十六进制格式):<b 0x...>",
"i2Label": "特殊垃圾数据包 2I2",
"i2Description": "协议模拟数据包(十六进制格式):<b 0x...>",
"i3Label": "特殊垃圾数据包 3I3",
"i3Description": "协议模拟数据包(十六进制格式):<b 0x...>",
"i4Label": "特殊垃圾数据包 4I4",
"i4Description": "协议模拟数据包(十六进制格式):<b 0x...>",
"i5Label": "特殊垃圾数据包 5I5",
"i5Description": "协议模拟数据包(十六进制格式):<b 0x...>",
"h1Label": "初始数据包魔术头部(H1",
"h1Description": "初始数据包头部值(范围:5-2147483647,必须与 H2-H4 不同)",
"h2Label": "响应数据包魔术头部(H2",
"h2Description": "响应数据包头部值(范围:5-2147483647,必须与 H1、H3、H4 不同)",
"h3Label": "Cookie 回复数据包魔术头部(H3",
"h3Description": "Cookie 回复数据包头部值(范围:5-2147483647,必须与 H1、H2、H4 不同)",
"h4Label": "传输数据包魔术头部(H4",
"h4Description": "传输数据包头部值(范围:5-2147483647,必须与 H1-H3 不同)",
"mtuNote": "具体数值取决于 MTU(最大传输单元)",
"obfuscationParameters": "AmneziaWG 混淆参数"
} }
} }
+10 -1
View File
@@ -88,6 +88,7 @@
"name": "名稱", "name": "名稱",
"expireDate": "到期日", "expireDate": "到期日",
"expireDateDesc": "用戶端將被停用的日期。留白表示永久有效", "expireDateDesc": "用戶端將被停用的日期。留白表示永久有效",
"delete": "刪除",
"deleteClient": "刪除用戶端", "deleteClient": "刪除用戶端",
"deleteDialog1": "您確定要刪除", "deleteDialog1": "您確定要刪除",
"deleteDialog2": "此動作無法復原。", "deleteDialog2": "此動作無法復原。",
@@ -117,7 +118,9 @@
"notConnected": "用戶端未連線", "notConnected": "用戶端未連線",
"endpoint": "端點", "endpoint": "端點",
"endpointDesc": "用戶端建立 WireGuard 連線的來源 IP", "endpointDesc": "用戶端建立 WireGuard 連線的來源 IP",
"search": "搜尋用戶端..." "search": "搜尋用戶端...",
"config": "組態設定",
"viewConfig": "檢視組態設定"
}, },
"dialog": { "dialog": {
"change": "變更", "change": "變更",
@@ -238,6 +241,12 @@
"preDown": "PreDown", "preDown": "PreDown",
"postDown": "PostDown" "postDown": "PostDown"
}, },
"copy": {
"notSupported": "無法複製",
"copied": "已複製!",
"failed": "複製失敗",
"copy": "複製"
},
"awg": { "awg": {
"jCLabel": "填充封包數量 (Jc)", "jCLabel": "填充封包數量 (Jc)",
"jCDescription": "要傳送的填充封包數量 (1-128,建議: 4-12)", "jCDescription": "要傳送的填充封包數量 (1-128,建議: 4-12)",
+20 -20
View File
@@ -1,6 +1,6 @@
{ {
"name": "wg-easy", "name": "wg-easy",
"version": "15.2.0-beta.2", "version": "15.2.0",
"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",
@@ -22,14 +22,14 @@
"dependencies": { "dependencies": {
"@eschricht/nuxt-color-mode": "^1.2.0", "@eschricht/nuxt-color-mode": "^1.2.0",
"@heroicons/vue": "^2.2.0", "@heroicons/vue": "^2.2.0",
"@libsql/client": "^0.15.15", "@libsql/client": "^0.17.0",
"@nuxtjs/i18n": "^10.2.0", "@nuxtjs/i18n": "^10.2.1",
"@nuxtjs/tailwindcss": "^6.14.0", "@nuxtjs/tailwindcss": "^6.14.0",
"@phc/format": "^1.0.0", "@phc/format": "^1.0.0",
"@pinia/nuxt": "^0.11.3", "@pinia/nuxt": "^0.11.3",
"@tailwindcss/forms": "^0.5.10", "@tailwindcss/forms": "^0.5.11",
"@vueuse/core": "^14.0.0", "@vueuse/core": "^14.1.0",
"@vueuse/nuxt": "^14.0.0", "@vueuse/nuxt": "^14.1.0",
"apexcharts": "^5.3.6", "apexcharts": "^5.3.6",
"argon2": "^0.44.0", "argon2": "^0.44.0",
"cidr-tools": "^11.0.3", "cidr-tools": "^11.0.3",
@@ -37,37 +37,37 @@
"consola": "^3.4.2", "consola": "^3.4.2",
"crc-32": "^1.2.2", "crc-32": "^1.2.2",
"debug": "^4.4.3", "debug": "^4.4.3",
"drizzle-orm": "^0.44.7", "drizzle-orm": "^0.45.1",
"ip-bigint": "^8.2.2", "ip-bigint": "^8.2.2",
"is-cidr": "^6.0.1", "is-cidr": "^6.0.1",
"is-ip": "^5.0.1", "is-ip": "^5.0.1",
"js-sha256": "^0.11.1", "js-sha256": "^0.11.1",
"nuxt": "^3.20.1", "nuxt": "^3.20.2",
"otpauth": "^9.4.1", "otpauth": "^9.4.1",
"pinia": "^3.0.4", "pinia": "^3.0.4",
"qr": "^0.5.2", "qr": "^0.5.4",
"radix-vue": "^1.9.17", "radix-vue": "^1.9.17",
"semver": "^7.7.3", "semver": "^7.7.3",
"tailwindcss": "^3.4.18", "tailwindcss": "^3.4.19",
"timeago.js": "^4.0.2", "timeago.js": "^4.0.2",
"vue": "latest", "vue": "latest",
"vue3-apexcharts": "^1.10.0", "vue3-apexcharts": "^1.10.0",
"zod": "^4.1.12" "zod": "^4.3.5"
}, },
"devDependencies": { "devDependencies": {
"@nuxt/eslint": "^1.10.0", "@nuxt/eslint": "^1.12.1",
"@types/debug": "^4.1.12", "@types/debug": "^4.1.12",
"@types/phc__format": "^1.0.1", "@types/phc__format": "^1.0.1",
"@types/semver": "^7.7.1", "@types/semver": "^7.7.1",
"drizzle-kit": "^0.31.6", "drizzle-kit": "^0.31.8",
"esbuild": "^0.27.0", "esbuild": "^0.27.2",
"eslint": "^9.39.1", "eslint": "^9.39.2",
"eslint-config-prettier": "^10.1.8", "eslint-config-prettier": "^10.1.8",
"prettier": "^3.6.2", "prettier": "^3.7.4",
"prettier-plugin-tailwindcss": "^0.7.1", "prettier-plugin-tailwindcss": "^0.7.2",
"tsx": "^4.20.6", "tsx": "^4.21.0",
"typescript": "^5.9.3", "typescript": "^5.9.3",
"vue-tsc": "^3.1.3" "vue-tsc": "^3.2.2"
}, },
"packageManager": "pnpm@10.21.0" "packageManager": "pnpm@10.28.0"
} }
+1834 -1745
View File
File diff suppressed because it is too large Load Diff
@@ -16,6 +16,12 @@ function createPreparedStatement(db: DBType) {
oneTimeLink: sql.placeholder('oneTimeLink'), oneTimeLink: sql.placeholder('oneTimeLink'),
expiresAt: sql.placeholder('expiresAt'), expiresAt: sql.placeholder('expiresAt'),
}) })
.onConflictDoUpdate({
target: oneTimeLink.id,
set: {
expiresAt: sql.placeholder('expiresAt') as never as string,
},
})
.prepare(), .prepare(),
erase: db erase: db
.update(oneTimeLink) .update(oneTimeLink)