Compare commits
30 Commits
c0fbc3f647
...
aa8eed4e51
Author | SHA1 | Date |
---|---|---|
|
aa8eed4e51 | |
|
40801993b0 | |
|
34ba0c6bbe | |
|
1391267437 | |
|
824fb1a1de | |
|
3fbd3c1dad | |
|
efe5cccb02 | |
|
31c59c1b26 | |
|
6e891ad9fb | |
|
e2fe3b8b32 | |
|
3aeb551516 | |
|
d272d4ea60 | |
|
4db8dd87cb | |
|
7b1e606bc2 | |
|
c607a96743 | |
|
e9f57afbeb | |
|
2d8236795f | |
|
3c15fa697e | |
|
76d5ac2d0b | |
|
4b9af5e8b3 | |
|
ae239ef92e | |
|
87e6ce3f74 | |
|
2afe8d177b | |
|
621b54e204 | |
|
06cbfc4292 | |
|
47e8e1406b | |
|
924b548320 | |
|
a8ac1cd014 | |
|
d3f2fa5a43 | |
|
eb3c7b1760 |
|
@ -0,0 +1,11 @@
|
|||
WG_HOST=🚨YOUR_SERVER_IP
|
||||
# (Supports: en, ru, tr, no, pl, fr, de, ca, es)
|
||||
LANGUAGE=en
|
||||
PORT=51821
|
||||
WG_DEVICE=eth0
|
||||
WG_PORT=51820
|
||||
WG_DEFAULT_ADDRESS=10.8.0.x
|
||||
WG_DEFAULT_DNS=1.1.1.1
|
||||
WG_ALLOWED_IPS=0.0.0.0/0, ::/0
|
||||
DICEBEAR_TYPE=bottts
|
||||
USE_GRAVATAR=true
|
|
@ -1,6 +0,0 @@
|
|||
# Copyright (c) Emile Nijssen (WeeJeWel)
|
||||
# Founder and Codeowner of WireGuard Easy (wg-easy)
|
||||
# Maintained by Philip Heiduck (pheiduck) and Bernd Storath (kaaax0815)
|
||||
* @WeeJeWel
|
||||
* @pheiduck
|
||||
* @kaaax0815
|
|
@ -1,3 +0,0 @@
|
|||
# These are supported funding model platforms
|
||||
|
||||
github: weejewel
|
|
@ -1,38 +0,0 @@
|
|||
---
|
||||
name: 🐛 Bug Report
|
||||
description: Create a report to help us improve
|
||||
title: "[Bug]: "
|
||||
labels:
|
||||
- "type: bug"
|
||||
|
||||
body:
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: |
|
||||
**Thanks :heart: for taking the time to fill out this bug report!**
|
||||
We kindly ask that you search to see if an issue [already exists](https://github.com/wg-easy/wg-easy/issues?q=is%3Aissue+sort%3Acreated-desc+) for the bug you encountered.
|
||||
|
||||
- type: textarea
|
||||
id: what-happened
|
||||
attributes:
|
||||
label: Describe the bug
|
||||
placeholder: Tell us what you see!
|
||||
value: "A bug happened!"
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: textarea
|
||||
id: what-should-happen
|
||||
attributes:
|
||||
label: Expected behavior
|
||||
placeholder: Tell us what you expected!
|
||||
value: "Work just fine!"
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: textarea
|
||||
id: logs
|
||||
attributes:
|
||||
label: Relevant log output
|
||||
description: Please copy and paste any relevant log output. This will be automatically formatted into code, so no need for backticks.
|
||||
render: shell
|
|
@ -1,48 +0,0 @@
|
|||
---
|
||||
name: 🛠️ Feature Request
|
||||
description: Suggest an idea to help us improve
|
||||
title: "[Feat]: "
|
||||
labels:
|
||||
- "type: feature request"
|
||||
|
||||
body:
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: |
|
||||
**Thanks :heart: for taking the time to fill out this feature request report!**
|
||||
We kindly ask that you search to see if an issue [already exists](https://github.com/wg-easy/wg-easy/issues?q=is%3Aissue+sort%3Acreated-desc+) for your feature.
|
||||
|
||||
We are also happy to accept contributions from our users. For more details see [here](https://github.com/wg-easy/wg-easy/blob/master/contributing.md).
|
||||
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: Description
|
||||
description: |
|
||||
A clear and concise description of the feature you're interested in.
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: Suggested Solution
|
||||
description: |
|
||||
Describe the solution you'd like. A clear and concise description of what you want to happen.
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: Alternatives
|
||||
description: |
|
||||
Describe alternatives you've considered.
|
||||
A clear and concise description of any alternative solutions or features you've considered.
|
||||
validations:
|
||||
required: false
|
||||
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: Additional Context
|
||||
description: |
|
||||
Add any other context about the problem here.
|
||||
validations:
|
||||
required: false
|
|
@ -1,5 +0,0 @@
|
|||
contact_links:
|
||||
- name: Get Help
|
||||
url: https://github.com/wg-easy/wg-easy/discussions/new?category=q-a
|
||||
about: If you can't get something to work the way you expect, open a question in the discussions.
|
||||
blank_issues_enabled: false
|
|
@ -1,28 +0,0 @@
|
|||
<!--- Provide a general summary of your changes in the Title above -->
|
||||
|
||||
## Description
|
||||
<!--- Describe your changes in detail -->
|
||||
|
||||
## Motivation and Context
|
||||
<!--- Why is this change required? What problem does it solve? -->
|
||||
<!--- If it fixes an open issue, please link to the issue here. -->
|
||||
|
||||
## How has this been tested?
|
||||
<!--- Please describe in detail how you tested your changes. -->
|
||||
<!--- Include details of your testing environment, tests ran to see how -->
|
||||
<!--- your change affects other areas of the code, etc. -->
|
||||
|
||||
## Screenshots (if appropriate):
|
||||
|
||||
## Types of changes
|
||||
<!--- What types of changes does your code introduce? Put an `x` in all the boxes that apply: -->
|
||||
- [ ] Bug fix (non-breaking change which fixes an issue)
|
||||
- [ ] New feature (non-breaking change which adds functionality)
|
||||
- [ ] Breaking change (fix or feature that would cause existing functionality to not work as expected)
|
||||
|
||||
## Checklist:
|
||||
<!--- Go over all the following points, and put an `x` in all the boxes that apply. -->
|
||||
<!--- If you're unsure about any of these, don't hesitate to ask. We're here to help! -->
|
||||
- [ ] My code follows the code style of this project.
|
||||
- [ ] My change requires a change to the documentation.
|
||||
- [ ] I have updated the documentation accordingly.
|
|
@ -1,17 +0,0 @@
|
|||
version: 2
|
||||
updates:
|
||||
- package-ecosystem: "github-actions"
|
||||
directory: "/"
|
||||
schedule:
|
||||
interval: "weekly"
|
||||
rebase-strategy: "auto"
|
||||
- package-ecosystem: "npm"
|
||||
directory: "/"
|
||||
schedule:
|
||||
interval: "weekly"
|
||||
rebase-strategy: "auto"
|
||||
- package-ecosystem: "npm"
|
||||
directory: "/src/"
|
||||
schedule:
|
||||
interval: "weekly"
|
||||
rebase-strategy: "auto"
|
|
@ -1,41 +0,0 @@
|
|||
name: "CodeQL"
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [ "master" ]
|
||||
pull_request:
|
||||
branches: [ "master" ]
|
||||
schedule:
|
||||
- cron: "15 0 * * *"
|
||||
|
||||
jobs:
|
||||
analyze:
|
||||
name: Analyze
|
||||
runs-on: ubuntu-latest
|
||||
if: github.repository_owner == 'wg-easy'
|
||||
permissions:
|
||||
actions: read
|
||||
contents: read
|
||||
security-events: write
|
||||
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
language: [ 'javascript-typescript' ]
|
||||
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Initialize CodeQL
|
||||
uses: github/codeql-action/init@v3
|
||||
with:
|
||||
languages: ${{ matrix.language }}
|
||||
|
||||
- name: Autobuild
|
||||
uses: github/codeql-action/autobuild@v3
|
||||
|
||||
- name: Perform CodeQL Analysis
|
||||
uses: github/codeql-action/analyze@v3
|
||||
with:
|
||||
category: "/language:${{matrix.language}}"
|
|
@ -1,37 +0,0 @@
|
|||
name: Build & Publish Development
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
deploy:
|
||||
name: Build & Deploy
|
||||
runs-on: ubuntu-latest
|
||||
if: github.repository_owner == 'wg-easy'
|
||||
permissions:
|
||||
packages: write
|
||||
contents: read
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
ref: master
|
||||
|
||||
- name: Set up QEMU
|
||||
uses: docker/setup-qemu-action@v3
|
||||
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v3
|
||||
|
||||
- name: Login to GitHub Container Registry
|
||||
uses: docker/login-action@v3
|
||||
with:
|
||||
registry: ghcr.io
|
||||
username: ${{ github.actor }}
|
||||
password: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Build & Publish Docker Image
|
||||
uses: docker/build-push-action@v6
|
||||
with:
|
||||
push: true
|
||||
platforms: linux/amd64,linux/arm/v6,linux/arm/v7,linux/arm64/v8
|
||||
tags: ghcr.io/wg-easy/wg-easy:development
|
|
@ -1,39 +0,0 @@
|
|||
name: Build & Publish Nightly
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
schedule:
|
||||
- cron: "0 0 * * *"
|
||||
|
||||
jobs:
|
||||
deploy:
|
||||
name: Build & Deploy
|
||||
runs-on: ubuntu-latest
|
||||
if: github.repository_owner == 'wg-easy'
|
||||
permissions:
|
||||
packages: write
|
||||
contents: read
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
ref: master
|
||||
|
||||
- name: Set up QEMU
|
||||
uses: docker/setup-qemu-action@v3
|
||||
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v3
|
||||
|
||||
- name: Login to GitHub Container Registry
|
||||
uses: docker/login-action@v3
|
||||
with:
|
||||
registry: ghcr.io
|
||||
username: ${{ github.actor }}
|
||||
password: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Build & Publish Docker Image
|
||||
uses: docker/build-push-action@v6
|
||||
with:
|
||||
push: true
|
||||
platforms: linux/amd64,linux/arm/v6,linux/arm/v7,linux/arm64/v8
|
||||
tags: ghcr.io/wg-easy/wg-easy:nightly
|
|
@ -1,38 +0,0 @@
|
|||
name: Build Pull Request
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
pull_request:
|
||||
|
||||
jobs:
|
||||
deploy:
|
||||
name: Build & Deploy
|
||||
runs-on: ubuntu-latest
|
||||
if: github.repository_owner == 'wg-easy'
|
||||
permissions:
|
||||
packages: write
|
||||
contents: read
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
ref: master
|
||||
|
||||
- name: Set up QEMU
|
||||
uses: docker/setup-qemu-action@v3
|
||||
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v3
|
||||
|
||||
- name: Login to GitHub Container Registry
|
||||
uses: docker/login-action@v3
|
||||
with:
|
||||
registry: ghcr.io
|
||||
username: ${{ github.actor }}
|
||||
password: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Build Docker Image
|
||||
uses: docker/build-push-action@v6
|
||||
with:
|
||||
push: false
|
||||
platforms: linux/amd64,linux/arm/v6,linux/arm/v7,linux/arm64/v8
|
||||
tags: ghcr.io/wg-easy/wg-easy:pr
|
|
@ -4,20 +4,20 @@ on:
|
|||
workflow_dispatch:
|
||||
push:
|
||||
branches:
|
||||
- production
|
||||
- master
|
||||
|
||||
jobs:
|
||||
deploy:
|
||||
name: Build & Deploy
|
||||
runs-on: ubuntu-latest
|
||||
if: github.repository_owner == 'wg-easy'
|
||||
if: github.repository_owner == 'w0rng'
|
||||
permissions:
|
||||
packages: write
|
||||
contents: read
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
ref: production
|
||||
ref: master
|
||||
|
||||
- name: Set up QEMU
|
||||
uses: docker/setup-qemu-action@v3
|
||||
|
@ -33,11 +33,11 @@ jobs:
|
|||
password: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Set environment variables
|
||||
run: RELEASE=echo $(cat ./src/package.json | jq -r .release | jq -r .version) >> $GITHUB_ENV
|
||||
run: echo RELEASE=$(cat ./src/package.json | jq -r .release | jq -r .version) >> $GITHUB_ENV
|
||||
|
||||
- name: Build & Publish Docker Image
|
||||
uses: docker/build-push-action@v6
|
||||
with:
|
||||
push: true
|
||||
platforms: linux/amd64,linux/arm/v6,linux/arm/v7,linux/arm64/v8
|
||||
tags: ghcr.io/wg-easy/wg-easy:latest, ghcr.io/wg-easy/wg-easy:${{ env.RELEASE }}
|
||||
tags: ghcr.io/w0rng/amnezia-wg-easy:latest, ghcr.io/w0rng/amnezia-wg-easy:${{ env.RELEASE }}
|
||||
|
|
|
@ -1,29 +0,0 @@
|
|||
name: Lint
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
- production
|
||||
pull_request:
|
||||
|
||||
jobs:
|
||||
lint:
|
||||
name: Lint
|
||||
runs-on: ubuntu-latest
|
||||
if: github.repository_owner == 'wg-easy'
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v4
|
||||
- name: Setup Node
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: 'lts/*'
|
||||
check-latest: true
|
||||
cache: 'npm'
|
||||
|
||||
- name: npm run lint
|
||||
run: |
|
||||
cd src
|
||||
npm ci
|
||||
npm run lint
|
|
@ -1,35 +0,0 @@
|
|||
# This workflow warns and then closes issues and PRs that have had no activity for a specified amount of time.
|
||||
#
|
||||
# You can adjust the behavior by modifying this file.
|
||||
# For more information, see:
|
||||
# https://github.com/actions/stale
|
||||
name: Mark stale issues and pull requests
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
schedule:
|
||||
- cron: '*/5 * * * *'
|
||||
|
||||
jobs:
|
||||
stale:
|
||||
|
||||
runs-on: ubuntu-latest
|
||||
if: github.repository_owner == 'wg-easy'
|
||||
permissions:
|
||||
issues: write
|
||||
pull-requests: write
|
||||
|
||||
steps:
|
||||
- uses: actions/stale@v9
|
||||
with:
|
||||
days-before-issue-stale: 30
|
||||
days-before-issue-close: 14
|
||||
stale-issue-label: "stale"
|
||||
stale-issue-message: "This issue is stale because it has been open for 30 days with no activity."
|
||||
close-issue-message: "This issue was closed because it has been inactive for 14 days since being marked as stale."
|
||||
days-before-pr-stale: 30
|
||||
days-before-pr-close: 14
|
||||
stale-pr-message: "This PR is stale because it has been open for 30 days with no activity."
|
||||
close-pr-message: "This PR was closed because it has been inactive for 14 days since being marked as stale."
|
||||
repo-token: ${{ secrets.GITHUB_TOKEN }}
|
||||
operations-per-run: 100
|
|
@ -4,3 +4,5 @@
|
|||
/src/node_modules
|
||||
.DS_Store
|
||||
*.swp
|
||||
.idea
|
||||
package-lock.json
|
||||
|
|
45
Dockerfile
45
Dockerfile
|
@ -1,6 +1,6 @@
|
|||
# As a workaround we have to build on nodejs 18
|
||||
# nodejs 20 hangs on build with armv6/armv7
|
||||
FROM docker.io/library/node:18-alpine AS build_node_modules
|
||||
FROM docker.io/library/node:20-alpine AS build_node_modules
|
||||
|
||||
# Update npm to latest
|
||||
RUN npm install -g npm@latest
|
||||
|
@ -13,7 +13,7 @@ RUN npm ci --omit=dev &&\
|
|||
|
||||
# Copy build result to a new image.
|
||||
# This saves a lot of disk space.
|
||||
FROM docker.io/library/node:lts-alpine
|
||||
FROM amneziavpn/amneziawg-go:latest
|
||||
HEALTHCHECK CMD /usr/bin/timeout 5s /bin/sh -c "/usr/bin/wg show | /bin/grep -q interface || exit 1" --interval=1m --timeout=5s --retries=3
|
||||
COPY --from=build_node_modules /app /app
|
||||
|
||||
|
@ -35,11 +35,44 @@ RUN apk add --no-cache \
|
|||
dpkg \
|
||||
dumb-init \
|
||||
iptables \
|
||||
iptables-legacy \
|
||||
wireguard-tools
|
||||
nodejs \
|
||||
npm
|
||||
|
||||
#Use iptables-legacy
|
||||
# RUN update-alternatives --install /sbin/iptables iptables /sbin/iptables-legacy 10 --slave /sbin/iptables-restore iptables-restore /sbin/iptables-legacy-restore --slave /sbin/iptables-save iptables-save /sbin/iptables-legacy-save
|
||||
|
||||
# Tune network
|
||||
RUN echo -e " \n\
|
||||
fs.file-max = 51200 \n\
|
||||
\n\
|
||||
net.core.rmem_max = 67108864 \n\
|
||||
net.core.wmem_max = 67108864 \n\
|
||||
net.core.netdev_max_backlog = 250000 \n\
|
||||
net.core.somaxconn = 4096 \n\
|
||||
\n\
|
||||
net.ipv4.tcp_syncookies = 1 \n\
|
||||
net.ipv4.tcp_tw_reuse = 1 \n\
|
||||
net.ipv4.tcp_tw_recycle = 0 \n\
|
||||
net.ipv4.tcp_fin_timeout = 30 \n\
|
||||
net.ipv4.tcp_keepalive_time = 1200 \n\
|
||||
net.ipv4.ip_local_port_range = 10000 65000 \n\
|
||||
net.ipv4.tcp_max_syn_backlog = 8192 \n\
|
||||
net.ipv4.tcp_max_tw_buckets = 5000 \n\
|
||||
net.ipv4.tcp_fastopen = 3 \n\
|
||||
net.ipv4.tcp_mem = 25600 51200 102400 \n\
|
||||
net.ipv4.tcp_rmem = 4096 87380 67108864 \n\
|
||||
net.ipv4.tcp_wmem = 4096 65536 67108864 \n\
|
||||
net.ipv4.tcp_mtu_probing = 1 \n\
|
||||
net.ipv4.tcp_congestion_control = hybla \n\
|
||||
# for low-latency network, use cubic instead \n\
|
||||
# net.ipv4.tcp_congestion_control = cubic \n\
|
||||
" | sed -e 's/^\s\+//g' | tee -a /etc/sysctl.conf && \
|
||||
mkdir -p /etc/security && \
|
||||
echo -e " \n\
|
||||
* soft nofile 51200 \n\
|
||||
* hard nofile 51200 \n\
|
||||
" | sed -e 's/^\s\+//g' | tee -a /etc/security/limits.conf
|
||||
|
||||
# Use iptables-legacy
|
||||
RUN update-alternatives --install /sbin/iptables iptables /sbin/iptables-legacy 10 --slave /sbin/iptables-restore iptables-restore /sbin/iptables-legacy-restore --slave /sbin/iptables-save iptables-save /sbin/iptables-legacy-save
|
||||
|
||||
# Set Environment
|
||||
ENV DEBUG=Server,WireGuard
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
To generate a bcrypt password hash using docker, run the following command :
|
||||
|
||||
```sh
|
||||
docker run -it ghcr.io/wg-easy/wg-easy wgpw YOUR_PASSWORD
|
||||
docker run -it ghcr.io/w0rng/amnezia-wg-easy wgpw YOUR_PASSWORD
|
||||
PASSWORD_HASH='$2b$12$coPqCsPtcFO.Ab99xylBNOW4.Iu7OOA2/ZIboHN6/oyxca3MWo7fW' // literally YOUR_PASSWORD
|
||||
```
|
||||
If a password is not provided, the tool will prompt you for one :
|
||||
|
|
136
README.md
136
README.md
|
@ -1,10 +1,4 @@
|
|||
# WireGuard Easy
|
||||
|
||||
[](https://github.com/wg-easy/wg-easy/actions/workflows/deploy.yml)
|
||||
[](https://github.com/wg-easy/wg-easy/actions/workflows/lint.yml)
|
||||

|
||||
[](https://github.com/sponsors/WeeJeWel)
|
||||

|
||||
# AmnewziaWG Easy
|
||||
|
||||
You have found the easiest way to install & manage WireGuard on any Linux host!
|
||||
|
||||
|
@ -14,14 +8,14 @@ You have found the easiest way to install & manage WireGuard on any Linux host!
|
|||
|
||||
## Features
|
||||
|
||||
* All-in-one: WireGuard + Web UI.
|
||||
* All-in-one: AmneziaWG + Web UI.
|
||||
* Easy installation, simple to use.
|
||||
* List, create, edit, delete, enable & disable clients.
|
||||
* Show a client's QR code.
|
||||
* Download a client's configuration file.
|
||||
* Statistics for which clients are connected.
|
||||
* Tx/Rx charts for each connected client.
|
||||
* Gravatar support.
|
||||
* Gravatar support or random avatars.
|
||||
* Automatic Light / Dark Mode
|
||||
* Multilanguage Support
|
||||
* Traffic Stats (default off)
|
||||
|
@ -31,21 +25,8 @@ You have found the easiest way to install & manage WireGuard on any Linux host!
|
|||
|
||||
## Requirements
|
||||
|
||||
* A host with a kernel that supports WireGuard (all modern kernels).
|
||||
* A host with Docker installed.
|
||||
|
||||
## Versions
|
||||
|
||||
We provide more then 1 docker image to get, this will help you decide which one is best for you. <br>
|
||||
For **stable** versions instead of nightly or development please read **README** from the **production** branch!
|
||||
|
||||
| tag | Branch | Example | Description |
|
||||
| - | - | - | - |
|
||||
| `latest` | production | `ghcr.io/wg-easy/wg-easy:latest` or `ghcr.io/wg-easy/wg-easy` | stable as possbile get bug fixes quickly when needed, deployed against `production`. |
|
||||
| `13` | production | `ghcr.io/wg-easy/wg-easy:13` | same as latest, stick to a version tag. |
|
||||
| `nightly` | master | `ghcr.io/wg-easy/wg-easy:nightly` | mostly unstable gets frequent package and code updates, deployed against `master`. |
|
||||
| `development` | pull requests | `ghcr.io/wg-easy/wg-easy:development` | used for development, testing code from PRs before landing into `master`. |
|
||||
|
||||
## Installation
|
||||
|
||||
### 1. Install Docker
|
||||
|
@ -60,78 +41,83 @@ exit
|
|||
|
||||
And log in again.
|
||||
|
||||
### 2. Run WireGuard Easy
|
||||
### 2. Run AmneziaWG Easy
|
||||
|
||||
To automatically install & run wg-easy, simply run:
|
||||
|
||||
```
|
||||
docker run -d \
|
||||
--name=wg-easy \
|
||||
-e LANG=de \
|
||||
--name=amnezia-wg-easy \
|
||||
-e LANG=en \
|
||||
-e WG_HOST=<🚨YOUR_SERVER_IP> \
|
||||
-e PASSWORD_HASH=<🚨YOUR_ADMIN_PASSWORD_HASH> \
|
||||
-e PORT=51821 \
|
||||
-e WG_PORT=51820 \
|
||||
-v ~/.wg-easy:/etc/wireguard \
|
||||
-v ~/.amnezia-wg-easy:/etc/wireguard \
|
||||
-p 51820:51820/udp \
|
||||
-p 51821:51821/tcp \
|
||||
--cap-add=NET_ADMIN \
|
||||
--cap-add=SYS_MODULE \
|
||||
--sysctl="net.ipv4.conf.all.src_valid_mark=1" \
|
||||
--sysctl="net.ipv4.ip_forward=1" \
|
||||
--device=/dev/net/tun:/dev/net/tun \
|
||||
--restart unless-stopped \
|
||||
ghcr.io/wg-easy/wg-easy
|
||||
ghcr.io/w0rng/amnezia-wg-easy
|
||||
```
|
||||
|
||||
> 💡 Replace `YOUR_SERVER_IP` with your WAN IP, or a Dynamic DNS hostname.
|
||||
>
|
||||
> 💡 Replace `YOUR_ADMIN_PASSWORD_HASH` with a bcrypt password hash to log in on the Web UI. See [How_to_generate_an_bcrypt_hash.md](./How_to_generate_an_bcrypt_hash.md) for know how generate the hash.
|
||||
> 💡 Replace `YOUR_ADMIN_PASSWORD_HASH` with a bcrypt password hash to log in on the Web UI.
|
||||
> See [How_to_generate_an_bcrypt_hash.md](./How_to_generate_an_bcrypt_hash.md) for know how generate the hash.
|
||||
|
||||
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/metrics`. Grafana dashboard [21733](https://grafana.com/grafana/dashboards/21733-wireguard/)
|
||||
|
||||
> 💡 Your configuration files will be saved in `~/.wg-easy`
|
||||
|
||||
WireGuard Easy can be launched with Docker Compose as well - just download
|
||||
[`docker-compose.yml`](docker-compose.yml), make necessary adjustments and
|
||||
execute `docker compose up --detach`.
|
||||
|
||||
### 3. Sponsor
|
||||
|
||||
Are you enjoying this project? [Buy Emile a beer!](https://github.com/sponsors/WeeJeWel) 🍻
|
||||
> 💡 Your configuration files will be saved in `~/.amnezia-wg-easy`
|
||||
|
||||
## Options
|
||||
|
||||
These options can be configured by setting environment variables using `-e KEY="VALUE"` in the `docker run` command.
|
||||
|
||||
| Env | Default | Example | Description |
|
||||
| - | - | - |------------------------------------------------------------------------------------------------------------------------------------------------------|
|
||||
| `PORT` | `51821` | `6789` | TCP port for Web UI. |
|
||||
| `WEBUI_HOST` | `0.0.0.0` | `localhost` | IP address web UI binds to. |
|
||||
| `PASSWORD_HASH` | - | `$2y$05$Ci...` | When set, requires a password when logging in to the Web UI. See [How to generate an bcrypt hash.md]("https://github.com/wg-easy/wg-easy/blob/master/How_to_generate_an_bcrypt_hash.md") for know how generate the hash. |
|
||||
| `WG_HOST` | - | `vpn.myserver.com` | The public hostname of your VPN server. |
|
||||
| `WG_DEVICE` | `eth0` | `ens6f0` | Ethernet device the wireguard traffic should be forwarded through. |
|
||||
| `WG_PORT` | `51820` | `12345` | The public UDP port of your VPN server. WireGuard will listen on that (othwise default) inside the Docker container. |
|
||||
| `WG_CONFIG_PORT`| `51820` | `12345` | The UDP port used on [Home Assistant Plugin](https://github.com/adriy-be/homeassistant-addons-jdeath/tree/main/wgeasy)
|
||||
| `WG_MTU` | `null` | `1420` | The MTU the clients will use. Server uses default WG MTU. |
|
||||
| `WG_PERSISTENT_KEEPALIVE` | `0` | `25` | Value in seconds to keep the "connection" open. If this value is 0, then connections won't be kept alive. |
|
||||
| `WG_DEFAULT_ADDRESS` | `10.8.0.x` | `10.6.0.x` | Clients IP address range. |
|
||||
| `WG_DEFAULT_DNS` | `1.1.1.1` | `8.8.8.8, 8.8.4.4` | DNS server clients will use. If set to blank value, clients will not use any DNS. |
|
||||
| `WG_ALLOWED_IPS` | `0.0.0.0/0, ::/0` | `192.168.15.0/24, 10.0.1.0/24` | Allowed IPs clients will use. |
|
||||
| `WG_PRE_UP` | `...` | - | See [config.js](https://github.com/wg-easy/wg-easy/blob/master/src/config.js#L19) for the default value. |
|
||||
| `WG_POST_UP` | `...` | `iptables ...` | See [config.js](https://github.com/wg-easy/wg-easy/blob/master/src/config.js#L20) for the default value. |
|
||||
| `WG_PRE_DOWN` | `...` | - | See [config.js](https://github.com/wg-easy/wg-easy/blob/master/src/config.js#L27) for the default value. |
|
||||
| `WG_POST_DOWN` | `...` | `iptables ...` | See [config.js](https://github.com/wg-easy/wg-easy/blob/master/src/config.js#L28) for the default value. |
|
||||
| `WG_ENABLE_EXPIRES_TIME` | `false` | `true` | Enable expire time for clients |
|
||||
| `LANG` | `en` | `de` | Web UI language (Supports: en, ua, ru, tr, no, pl, fr, de, ca, es, ko, vi, nl, is, pt, chs, cht, it, th, hi). |
|
||||
| `UI_TRAFFIC_STATS` | `false` | `true` | Enable detailed RX / TX client stats in Web UI |
|
||||
| `UI_CHART_TYPE` | `0` | `1` | UI_CHART_TYPE=0 # Charts disabled, UI_CHART_TYPE=1 # Line chart, UI_CHART_TYPE=2 # Area chart, UI_CHART_TYPE=3 # Bar chart |
|
||||
| `WG_ENABLE_ONE_TIME_LINKS` | `false` | `true` | Enable display and generation of short one time download links (expire after 5 minutes) |
|
||||
| `MAX_AGE` | `0` | `1440` | The maximum age of Web UI sessions in minutes. `0` means that the session will exist until the browser is closed. |
|
||||
| `UI_ENABLE_SORT_CLIENTS` | `false` | `true` | Enable UI sort clients by name |
|
||||
| `ENABLE_PROMETHEUS_METRICS` | `false` | `true` | Enable Prometheus metrics `http://0.0.0.0:51821/metrics` and `http://0.0.0.0:51821/metrics/json`|
|
||||
| `PROMETHEUS_METRICS_PASSWORD` | - | `$2y$05$Ci...` | If set, Basic Auth is required when requesting metrics. See [How to generate an bcrypt hash.md]("https://github.com/wg-easy/wg-easy/blob/master/How_to_generate_an_bcrypt_hash.md") for know how generate the hash. |
|
||||
| Env | Default | Example | Description |
|
||||
|-------------------------------|-------------------|--------------------------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
|
||||
| `PORT` | `51821` | `6789` | TCP port for Web UI. |
|
||||
| `WEBUI_HOST` | `0.0.0.0` | `localhost` | IP address web UI binds to. |
|
||||
| `PASSWORD_HASH` | - | `$2y$05$Ci...` | When set, requires a password when logging in to the Web UI. See [How to generate an bcrypt hash.md]("https://github.com/wg-easy/wg-easy/blob/master/How_to_generate_an_bcrypt_hash.md") for know how generate the hash. |
|
||||
| `WG_HOST` | - | `vpn.myserver.com` | The public hostname of your VPN server. |
|
||||
| `WG_DEVICE` | `eth0` | `ens6f0` | Ethernet device the wireguard traffic should be forwarded through. |
|
||||
| `WG_PORT` | `51820` | `12345` | The public UDP port of your VPN server. WireGuard will listen on that (othwise default) inside the Docker container. |
|
||||
| `WG_CONFIG_PORT` | `51820` | `12345` | The UDP port used on [Home Assistant Plugin](https://github.com/adriy-be/homeassistant-addons-jdeath/tree/main/wgeasy) |
|
||||
| `WG_MTU` | `null` | `1420` | The MTU the clients will use. Server uses default WG MTU. |
|
||||
| `WG_PERSISTENT_KEEPALIVE` | `0` | `25` | Value in seconds to keep the "connection" open. If this value is 0, then connections won't be kept alive. |
|
||||
| `WG_DEFAULT_ADDRESS` | `10.8.0.x` | `10.6.0.x` | Clients IP address range. |
|
||||
| `WG_DEFAULT_DNS` | `1.1.1.1` | `8.8.8.8, 8.8.4.4` | DNS server clients will use. If set to blank value, clients will not use any DNS. |
|
||||
| `WG_ALLOWED_IPS` | `0.0.0.0/0, ::/0` | `192.168.15.0/24, 10.0.1.0/24` | Allowed IPs clients will use. |
|
||||
| `WG_PRE_UP` | `...` | - | See [config.js](https://github.com/wg-easy/wg-easy/blob/master/src/config.js#L19) for the default value. |
|
||||
| `WG_POST_UP` | `...` | `iptables ...` | See [config.js](https://github.com/wg-easy/wg-easy/blob/master/src/config.js#L20) for the default value. |
|
||||
| `WG_PRE_DOWN` | `...` | - | See [config.js](https://github.com/wg-easy/wg-easy/blob/master/src/config.js#L27) for the default value. |
|
||||
| `WG_POST_DOWN` | `...` | `iptables ...` | See [config.js](https://github.com/wg-easy/wg-easy/blob/master/src/config.js#L28) for the default value. |
|
||||
| `WG_ENABLE_EXPIRES_TIME` | `false` | `true` | Enable expire time for clients |
|
||||
| `LANG` | `en` | `de` | Web UI language (Supports: en, ua, ru, tr, no, pl, fr, de, ca, es, ko, vi, nl, is, pt, chs, cht, it, th, hi). |
|
||||
| `UI_TRAFFIC_STATS` | `false` | `true` | Enable detailed RX / TX client stats in Web UI |
|
||||
| `UI_CHART_TYPE` | `0` | `1` | UI_CHART_TYPE=0 # Charts disabled, UI_CHART_TYPE=1 # Line chart, UI_CHART_TYPE=2 # Area chart, UI_CHART_TYPE=3 # Bar chart |
|
||||
| `DICEBEAR_TYPE` | `false` | `bottts` | see [dicebear types](https://www.dicebear.com/styles/) |
|
||||
| `USE_GRAVATAR` | `false` | `true` | Use or not GRAVATAR service |
|
||||
| `WG_ENABLE_ONE_TIME_LINKS` | `false` | `true` | Enable display and generation of short one time download links (expire after 5 minutes) |
|
||||
| `MAX_AGE` | `0` | `1440` | The maximum age of Web UI sessions in minutes. `0` means that the session will exist until the browser is closed. |
|
||||
| `UI_ENABLE_SORT_CLIENTS` | `false` | `true` | Enable UI sort clients by name |
|
||||
| `ENABLE_PROMETHEUS_METRICS` | `false` | `true` | Enable Prometheus metrics `http://0.0.0.0:51821/metrics` and `http://0.0.0.0:51821/metrics/json` |
|
||||
| `PROMETHEUS_METRICS_PASSWORD` | - | `$2y$05$Ci...` | If set, Basic Auth is required when requesting metrics. See [How to generate an bcrypt hash.md]("https://github.com/wg-easy/wg-easy/blob/master/How_to_generate_an_bcrypt_hash.md") for know how generate the hash. |
|
||||
| `JC` | `random` | `5` | Junk packet count — number of packets with random data that are sent before the start of the session. |
|
||||
| `JMIN` | `50` | `25` | Junk packet minimum size — minimum packet size for Junk packet. That is, all randomly generated packets will have a size no smaller than Jmin. |
|
||||
| `JMAX` | `1000` | `250` | Junk packet maximum size — maximum size for Junk packets. |
|
||||
| `S1` | `random` | `75` | Init packet junk size — the size of random data that will be added to the init packet, the size of which is initially fixed. |
|
||||
| `S2` | `random` | `75` | Response packet junk size — the size of random data that will be added to the response packet, the size of which is initially fixed. |
|
||||
| `H1` | `random` | `1234567891` | Init packet magic header — the header of the first byte of the handshake. Must be < uint_max. |
|
||||
| `H2` | `random` | `1234567892` | Response packet magic header — header of the first byte of the handshake response. Must be < uint_max. |
|
||||
| `H3` | `random` | `1234567893` | Underload packet magic header — UnderLoad packet header. Must be < uint_max. |
|
||||
| `H4` | `random` | `1234567894` | Transport packet magic header — header of the packet of the data packet. Must be < uint_max. |
|
||||
|
||||
> If you change `WG_PORT`, make sure to also change the exposed port.
|
||||
|
||||
|
@ -140,24 +126,14 @@ These options can be configured by setting environment variables using `-e KEY="
|
|||
To update to the latest version, simply run:
|
||||
|
||||
```bash
|
||||
docker stop wg-easy
|
||||
docker rm wg-easy
|
||||
docker pull ghcr.io/wg-easy/wg-easy
|
||||
docker stop amnezia-wg-easy
|
||||
docker rm amnezia-wg-easy
|
||||
docker pull ghcr.io/w0rng/amnezia-wg-easy
|
||||
```
|
||||
|
||||
And then run the `docker run -d \ ...` command above again.
|
||||
|
||||
With Docker Compose WireGuard Easy can be updated with a single command:
|
||||
`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 WireGuared Easy container will be automatically recreated if a newer image
|
||||
was pulled.
|
||||
## Thanks
|
||||
|
||||
## Common Use Cases
|
||||
|
||||
* [Using WireGuard-Easy with Pi-Hole](https://github.com/wg-easy/wg-easy/wiki/Using-WireGuard-Easy-with-Pi-Hole)
|
||||
* [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).
|
||||
Based on [wg-easy](https://github.com/wg-easy/wg-easy) by Emile Nijssen.
|
||||
Use integrations with AmneziaWg from [amnezia-wg-easy](https://github.com/spcfox/amnezia-wg-easy) by Viktor Yudov.
|
||||
|
|
Binary file not shown.
Before ![]() (image error) Size: 104 KiB After ![]() (image error) Size: 75 KiB ![]() ![]() |
Binary file not shown.
101
contributing.md
101
contributing.md
|
@ -1,101 +0,0 @@
|
|||
# Contributing to wg-easy
|
||||
|
||||
First and foremost, thank you! We appreciate that you want to contribute to wg-easy, your time is valuable, and your contributions mean a lot to us.
|
||||
|
||||
|
||||
## Important!
|
||||
|
||||
By contributing to this project, you:
|
||||
|
||||
* Agree that you have authored 100% of the content
|
||||
* Agree that you have the necessary rights to the content
|
||||
* Agree that you have received the necessary permissions from your employer to make the contributions (if applicable)
|
||||
* Agree that the content you contribute may be provided under the Project license(s)
|
||||
* Agree that, if you did not author 100% of the content, the appropriate licenses and copyrights have been added along with any other necessary attribution.
|
||||
|
||||
|
||||
## Getting started
|
||||
|
||||
**What does "contributing" mean?**
|
||||
|
||||
Creating an issue is the simplest form of contributing to a project. But there are many ways to contribute, including the following:
|
||||
|
||||
- Updating or correcting documentation
|
||||
- Feature requests
|
||||
- Bug reports
|
||||
|
||||
|
||||
## Showing support for wg-easy
|
||||
|
||||
Please keep in mind that open source software is built by people like you, who spend their free time creating things the rest the community can use.
|
||||
|
||||
Don't have time to contribute? No worries, here are some other ways to show your support for wg-easy:
|
||||
|
||||
- star the [project](https://github.com/wg-easy/wg-easy)
|
||||
- tweet your support for wg-easy
|
||||
|
||||
|
||||
## Issues
|
||||
|
||||
Please only create issues for bug reports or feature requests. Issues discussing any other topics may be closed by the project's maintainers without further explanation.
|
||||
|
||||
Do not create issues about bumping dependencies unless a bug has been identified and you can demonstrate that it effects this library.
|
||||
|
||||
**Help us to help you**
|
||||
|
||||
Remember that we’re here to help, but not to make guesses about what you need help with:
|
||||
|
||||
- Whatever bug or issue you're experiencing, assume that it will not be as obvious to the maintainers as it is to you.
|
||||
- Spell it out completely. Keep in mind that maintainers need to think about _all potential use cases_ of a library. It's important that you explain how you're using a library so that maintainers can make that connection and solve the issue.
|
||||
|
||||
_It can't be understated how frustrating and draining it can be to maintainers to have to ask clarifying questions on the most basic things, before it's even possible to start debugging. Please try to make the best use of everyone's time involved, including yourself, by providing this information up front._
|
||||
|
||||
### Before creating an issue
|
||||
|
||||
Please try to determine if the issue is caused by an underlying library, and if so, create the issue there. Sometimes this is difficult to know. We only ask that you attempt to give a reasonable attempt to find out. Oftentimes the readme will have advice about where to go to create issues.
|
||||
|
||||
Try to follow these guidelines:
|
||||
|
||||
- **Avoid creating issues for implementation help** - It's much better for discoverability, SEO, and semantics - to keep the issue tracker focused on bugs and feature requests - to ask implementation-related questions on [stackoverflow.com][so]
|
||||
- **Investigate the issue** - Search for exising issues (open or closed) that address the issue, and might have even resolved it already.
|
||||
- **Check the readme** - oftentimes you will find notes about creating issues, and where to go depending on the type of issue.
|
||||
- Create the issue in the appropriate repository.
|
||||
|
||||
### Creating an issue
|
||||
|
||||
Please be as descriptive as possible when creating an issue. Give us the information we need to successfully answer your question or address your issue by answering the following in your issue:
|
||||
|
||||
- **description**: (required) What is the bug you're experiencing? How are you using this library/app?
|
||||
- **OS**: (required) what operating system are you on?
|
||||
- **version**: (required) please note the version of wg-easy are you using
|
||||
- **error messages**: (required) please paste any error messages into the issue, or a [gist](https://gist.github.com/)
|
||||
- **extensions, plugins, helpers, etc** (if applicable): please list any extensions you're using
|
||||
|
||||
|
||||
### Closing issues
|
||||
|
||||
The original poster or the maintainers of wg-easy may close an issue at any time. Typically, but not exclusively, issues are closed when:
|
||||
|
||||
- The issue is resolved
|
||||
- The project's maintainers have determined the issue is out of scope
|
||||
- An issue is clearly a duplicate of another issue, in which case the duplicate issue will be linked.
|
||||
- A discussion has clearly run its course
|
||||
|
||||
|
||||
## Next steps
|
||||
|
||||
**Tips for creating idiomatic issues**
|
||||
|
||||
Spending just a little extra time to review best practices and brush up on your contributing skills will, at minimum, make your issue easier to read, easier to resolve, and more likely to be found by others who have the same or similar issue in the future. At best, it will open up doors and potential career opportunities by helping you be at your best.
|
||||
|
||||
The following resources were hand-picked to help you be the most effective contributor you can be:
|
||||
|
||||
- The [Guide to Idiomatic Contributing](https://github.com/jonschlinkert/idiomatic-contributing) is a great place for newcomers to start, but there is also information for experienced contributors there.
|
||||
- Take some time to learn basic markdown. We can't stress this enough. Don't start pasting code into GitHub issues before you've taken a moment to review this [markdown cheatsheet](https://gist.github.com/jonschlinkert/5854601)
|
||||
- The GitHub guide to [basic markdown](https://help.github.com/articles/markdown-basics/) is another great markdown resource.
|
||||
- Learn about [GitHub Flavored Markdown](https://help.github.com/articles/github-flavored-markdown/). And if you want to really go above and beyond, read [mastering markdown](https://guides.github.com/features/mastering-markdown/).
|
||||
|
||||
At the very least, please try to:
|
||||
|
||||
- Use backticks to wrap code. This ensures that it retains its formatting and isn't modified when it's rendered by GitHub, and makes the code more readable to others
|
||||
- When applicable, use syntax highlighting by adding the correct language name after the first "code fence"
|
|
@ -1,17 +0,0 @@
|
|||
services:
|
||||
wg-easy:
|
||||
build:
|
||||
dockerfile: ./Dockerfile
|
||||
command: npm run serve
|
||||
volumes:
|
||||
- ./src/:/app/
|
||||
# - ./data/:/etc/wireguard
|
||||
ports:
|
||||
- "51820:51820/udp"
|
||||
- "51821:51821/tcp"
|
||||
cap_add:
|
||||
- NET_ADMIN
|
||||
- SYS_MODULE
|
||||
environment:
|
||||
# - PASSWORD_HASH=p
|
||||
- WG_HOST=192.168.1.233
|
|
@ -2,44 +2,18 @@ volumes:
|
|||
etc_wireguard:
|
||||
|
||||
services:
|
||||
wg-easy:
|
||||
environment:
|
||||
# Change Language:
|
||||
# (Supports: en, ua, ru, tr, no, pl, fr, de, ca, es, ko, vi, nl, is, pt, chs, cht, it, th, hi)
|
||||
- LANG=en
|
||||
# ⚠️ Required:
|
||||
# Change this to your host's public address
|
||||
- WG_HOST=raspberrypi.local
|
||||
|
||||
# Optional:
|
||||
# - PASSWORD_HASH=$$2y$$10$$hBCoykrB95WSzuV4fafBzOHWKu9sbyVa34GJr8VV5R/pIelfEMYyG (needs double $$, hash of 'foobar123'; see "How_to_generate_an_bcrypt_hash.md" for generate the hash)
|
||||
# - PORT=51821
|
||||
# - WG_PORT=51820
|
||||
# - WG_CONFIG_PORT=92820
|
||||
# - WG_DEFAULT_ADDRESS=10.8.0.x
|
||||
# - WG_DEFAULT_DNS=1.1.1.1
|
||||
# - WG_MTU=1420
|
||||
# - WG_ALLOWED_IPS=192.168.15.0/24, 10.0.1.0/24
|
||||
# - WG_PERSISTENT_KEEPALIVE=25
|
||||
# - WG_PRE_UP=echo "Pre Up" > /etc/wireguard/pre-up.txt
|
||||
# - WG_POST_UP=echo "Post Up" > /etc/wireguard/post-up.txt
|
||||
# - WG_PRE_DOWN=echo "Pre Down" > /etc/wireguard/pre-down.txt
|
||||
# - WG_POST_DOWN=echo "Post Down" > /etc/wireguard/post-down.txt
|
||||
# - UI_TRAFFIC_STATS=true
|
||||
# - UI_CHART_TYPE=0 # (0 Charts disabled, 1 # Line chart, 2 # Area chart, 3 # Bar chart)
|
||||
# - WG_ENABLE_ONE_TIME_LINKS=true
|
||||
# - UI_ENABLE_SORT_CLIENTS=true
|
||||
# - WG_ENABLE_EXPIRES_TIME=true
|
||||
# - ENABLE_PROMETHEUS_METRICS=false
|
||||
# - PROMETHEUS_METRICS_PASSWORD=$$2a$$12$$vkvKpeEAHD78gasyawIod.1leBMKg8sBwKW.pQyNsq78bXV3INf2G # (needs double $$, hash of 'prometheus_password'; see "How_to_generate_an_bcrypt_hash.md" for generate the hash)
|
||||
|
||||
image: ghcr.io/wg-easy/wg-easy
|
||||
container_name: wg-easy
|
||||
amnezia-wg-easy:
|
||||
env_file:
|
||||
- .env
|
||||
image: amnezia-wg-easy
|
||||
build:
|
||||
context: .
|
||||
container_name: amnezia-wg-easy
|
||||
volumes:
|
||||
- etc_wireguard:/etc/wireguard
|
||||
ports:
|
||||
- "51820:51820/udp"
|
||||
- "51821:51821/tcp"
|
||||
- "${WG_PORT}:${WG_PORT}/udp"
|
||||
- "${PORT}:${PORT}/tcp"
|
||||
restart: unless-stopped
|
||||
cap_add:
|
||||
- NET_ADMIN
|
||||
|
@ -48,3 +22,5 @@ services:
|
|||
sysctls:
|
||||
- net.ipv4.ip_forward=1
|
||||
- net.ipv4.conf.all.src_valid_mark=1
|
||||
devices:
|
||||
- /dev/net/tun:/dev/net/tun
|
||||
|
|
|
@ -5,8 +5,6 @@ const { release: { version } } = require('./package.json');
|
|||
module.exports.RELEASE = version;
|
||||
module.exports.PORT = process.env.PORT || '51821';
|
||||
module.exports.WEBUI_HOST = process.env.WEBUI_HOST || '0.0.0.0';
|
||||
/** This is only kept for migration purpose. DO NOT USE! */
|
||||
module.exports.PASSWORD = process.env.PASSWORD;
|
||||
module.exports.PASSWORD_HASH = process.env.PASSWORD_HASH;
|
||||
module.exports.MAX_AGE = parseInt(process.env.MAX_AGE, 10) * 1000 * 60 || 0;
|
||||
module.exports.WG_PATH = process.env.WG_PATH || '/etc/wireguard/';
|
||||
|
@ -45,3 +43,20 @@ module.exports.UI_ENABLE_SORT_CLIENTS = process.env.UI_ENABLE_SORT_CLIENTS || 'f
|
|||
module.exports.WG_ENABLE_EXPIRES_TIME = process.env.WG_ENABLE_EXPIRES_TIME || 'false';
|
||||
module.exports.ENABLE_PROMETHEUS_METRICS = process.env.ENABLE_PROMETHEUS_METRICS || 'false';
|
||||
module.exports.PROMETHEUS_METRICS_PASSWORD = process.env.PROMETHEUS_METRICS_PASSWORD;
|
||||
|
||||
module.exports.DICEBEAR_TYPE = process.env.DICEBEAR_TYPE || false;
|
||||
module.exports.USE_GRAVATAR = process.env.USE_GRAVATAR || false;
|
||||
|
||||
const getRandomInt = (min, max) => min + Math.floor(Math.random() * (max - min));
|
||||
const getRandomJunkSize = () => getRandomInt(15, 150);
|
||||
const getRandomHeader = () => getRandomInt(1, 2_147_483_647);
|
||||
|
||||
module.exports.JC = process.env.JC || getRandomInt(3, 10);
|
||||
module.exports.JMIN = process.env.JMIN || 50;
|
||||
module.exports.JMAX = process.env.JMAX || 1000;
|
||||
module.exports.S1 = process.env.S1 || getRandomJunkSize();
|
||||
module.exports.S2 = process.env.S2 || getRandomJunkSize();
|
||||
module.exports.H1 = process.env.H1 || getRandomHeader();
|
||||
module.exports.H2 = process.env.H2 || getRandomHeader();
|
||||
module.exports.H3 = process.env.H3 || getRandomHeader();
|
||||
module.exports.H4 = process.env.H4 || getRandomHeader();
|
||||
|
|
|
@ -29,7 +29,6 @@ const {
|
|||
PORT,
|
||||
WEBUI_HOST,
|
||||
RELEASE,
|
||||
PASSWORD,
|
||||
PASSWORD_HASH,
|
||||
MAX_AGE,
|
||||
LANG,
|
||||
|
@ -40,6 +39,8 @@ const {
|
|||
WG_ENABLE_EXPIRES_TIME,
|
||||
ENABLE_PROMETHEUS_METRICS,
|
||||
PROMETHEUS_METRICS_PASSWORD,
|
||||
DICEBEAR_TYPE,
|
||||
USE_GRAVATAR,
|
||||
} = require('../config');
|
||||
|
||||
const requiresPassword = !!PASSWORD_HASH;
|
||||
|
@ -125,6 +126,14 @@ module.exports = class Server {
|
|||
return `${WG_ENABLE_EXPIRES_TIME}`;
|
||||
}))
|
||||
|
||||
.get('/api/ui-avatar-settings', defineEventHandler((event) => {
|
||||
setHeader(event, 'Content-Type', 'application/json');
|
||||
return {
|
||||
dicebear: DICEBEAR_TYPE,
|
||||
gravatar: USE_GRAVATAR,
|
||||
}
|
||||
}))
|
||||
|
||||
// Authentication
|
||||
.get('/api/session', defineEventHandler((event) => {
|
||||
const authenticated = requiresPassword
|
||||
|
@ -336,10 +345,6 @@ module.exports = class Server {
|
|||
});
|
||||
};
|
||||
|
||||
// Prometheus Metrics API
|
||||
const routerPrometheusMetrics = createRouter();
|
||||
app.use(routerPrometheusMetrics);
|
||||
|
||||
// Check Prometheus credentials
|
||||
app.use(
|
||||
fromNodeMiddleware((req, res, next) => {
|
||||
|
@ -347,11 +352,10 @@ module.exports = class Server {
|
|||
return next();
|
||||
}
|
||||
const user = basicAuth(req);
|
||||
if (requiresPrometheusPassword && !user) {
|
||||
if (!user) {
|
||||
res.statusCode = 401;
|
||||
return { error: 'Not Logged In' };
|
||||
}
|
||||
|
||||
if (user.pass) {
|
||||
if (isPasswordValid(user.pass, PROMETHEUS_METRICS_PASSWORD)) {
|
||||
return next();
|
||||
|
@ -364,6 +368,10 @@ module.exports = class Server {
|
|||
}),
|
||||
);
|
||||
|
||||
// Prometheus Metrics API
|
||||
const routerPrometheusMetrics = createRouter();
|
||||
app.use(routerPrometheusMetrics);
|
||||
|
||||
// Prometheus Routes
|
||||
routerPrometheusMetrics
|
||||
.get('/metrics', defineEventHandler(async (event) => {
|
||||
|
@ -419,6 +427,7 @@ module.exports = class Server {
|
|||
if (id.endsWith('.json')) setHeader(event, 'Content-Type', 'application/json');
|
||||
if (id.endsWith('.css')) setHeader(event, 'Content-Type', 'text/css');
|
||||
if (id.endsWith('.png')) setHeader(event, 'Content-Type', 'image/png');
|
||||
if (id.endsWith('.svg')) setHeader(event, 'Content-Type', 'image/svg+xml');
|
||||
|
||||
return {
|
||||
size: stats.size,
|
||||
|
@ -429,10 +438,6 @@ module.exports = class Server {
|
|||
}),
|
||||
);
|
||||
|
||||
if (PASSWORD) {
|
||||
throw new Error('DO NOT USE PASSWORD ENVIRONMENT VARIABLE. USE PASSWORD_HASH INSTEAD.\nSee https://github.com/wg-easy/wg-easy/blob/master/How_to_generate_an_bcrypt_hash.md');
|
||||
}
|
||||
|
||||
createServer(toNodeListener(app)).listen(PORT, WEBUI_HOST);
|
||||
debug(`Listening on http://${WEBUI_HOST}:${PORT}`);
|
||||
|
||||
|
|
|
@ -26,6 +26,15 @@ const {
|
|||
WG_POST_DOWN,
|
||||
WG_ENABLE_EXPIRES_TIME,
|
||||
WG_ENABLE_ONE_TIME_LINKS,
|
||||
JC,
|
||||
JMIN,
|
||||
JMAX,
|
||||
S1,
|
||||
S2,
|
||||
H1,
|
||||
H2,
|
||||
H3,
|
||||
H4,
|
||||
} = require('../config');
|
||||
|
||||
module.exports = class WireGuard {
|
||||
|
@ -54,6 +63,15 @@ module.exports = class WireGuard {
|
|||
privateKey,
|
||||
publicKey,
|
||||
address,
|
||||
jc: JC,
|
||||
jmin: JMIN,
|
||||
jmax: JMAX,
|
||||
s1: S1,
|
||||
s2: S2,
|
||||
h1: H1,
|
||||
h2: H2,
|
||||
h3: H3,
|
||||
h4: H4,
|
||||
},
|
||||
clients: {},
|
||||
};
|
||||
|
@ -71,8 +89,8 @@ module.exports = class WireGuard {
|
|||
const config = await this.__buildConfig();
|
||||
|
||||
await this.__saveConfig(config);
|
||||
await Util.exec('wg-quick down wg0').catch(() => {});
|
||||
await Util.exec('wg-quick up wg0').catch((err) => {
|
||||
await Util.exec('awg-quick down /etc/wireguard/wg0.conf').catch(() => {});
|
||||
await Util.exec('awg-quick up /etc/wireguard/wg0.conf').catch((err) => {
|
||||
if (err && err.message && err.message.includes('Cannot find device "wg0"')) {
|
||||
throw new Error('WireGuard exited with the error: Cannot find device "wg0"\nThis usually means that your host\'s kernel does not support WireGuard!');
|
||||
}
|
||||
|
@ -109,6 +127,15 @@ PreUp = ${WG_PRE_UP}
|
|||
PostUp = ${WG_POST_UP}
|
||||
PreDown = ${WG_PRE_DOWN}
|
||||
PostDown = ${WG_POST_DOWN}
|
||||
Jc = ${config.server.jc}
|
||||
Jmin = ${config.server.jmin}
|
||||
Jmax = ${config.server.jmax}
|
||||
S1 = ${config.server.s1}
|
||||
S2 = ${config.server.s2}
|
||||
H1 = ${config.server.h1}
|
||||
H2 = ${config.server.h2}
|
||||
H3 = ${config.server.h3}
|
||||
H4 = ${config.server.h4}
|
||||
`;
|
||||
|
||||
for (const [clientId, client] of Object.entries(config.clients)) {
|
||||
|
@ -135,7 +162,7 @@ ${client.preSharedKey ? `PresharedKey = ${client.preSharedKey}\n` : ''
|
|||
|
||||
async __syncConfig() {
|
||||
debug('Config syncing...');
|
||||
await Util.exec('wg syncconf wg0 <(wg-quick strip wg0)');
|
||||
await Util.exec('wg syncconf wg0 <(wg-quick strip /etc/wireguard/wg0.conf)');
|
||||
debug('Config synced.');
|
||||
}
|
||||
|
||||
|
@ -218,6 +245,15 @@ PrivateKey = ${client.privateKey ? `${client.privateKey}` : 'REPLACE_ME'}
|
|||
Address = ${client.address}/24
|
||||
${WG_DEFAULT_DNS ? `DNS = ${WG_DEFAULT_DNS}\n` : ''}\
|
||||
${WG_MTU ? `MTU = ${WG_MTU}\n` : ''}\
|
||||
Jc = ${config.server.jc}
|
||||
Jmin = ${config.server.jmin}
|
||||
Jmax = ${config.server.jmax}
|
||||
S1 = ${config.server.s1}
|
||||
S2 = ${config.server.s2}
|
||||
H1 = ${config.server.h1}
|
||||
H2 = ${config.server.h2}
|
||||
H3 = ${config.server.h3}
|
||||
H4 = ${config.server.h4}
|
||||
|
||||
[Peer]
|
||||
PublicKey = ${config.server.publicKey}
|
||||
|
|
Binary file not shown.
Before ![]() (image error) Size: 69 KiB After ![]() (image error) Size: 14 KiB ![]() ![]() |
Binary file not shown.
After Width: 64px | Height: 64px | Size: 32 KiB |
Binary file not shown.
Before ![]() (image error) Size: 2.9 KiB |
File diff suppressed because one or more lines are too long
After (image error) Size: 28 KiB |
|
@ -2,11 +2,11 @@
|
|||
<html>
|
||||
|
||||
<head>
|
||||
<title>WireGuard</title>
|
||||
<title>AmneziaWG</title>
|
||||
<meta charset="utf-8"/>
|
||||
<link href="./css/app.css" rel="stylesheet">
|
||||
<link rel="manifest" href="./manifest.json">
|
||||
<link rel="icon" type="image/png" href="./img/favicon.png">
|
||||
<link rel="icon" href="./img/favicon.ico" sizes="any">
|
||||
<link rel="apple-touch-icon" href="./img/apple-touch-icon.png">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover">
|
||||
<meta name="apple-mobile-web-app-capable" content="yes">
|
||||
|
@ -27,7 +27,7 @@
|
|||
<div v-if="authenticated === true">
|
||||
<div class="flex flex-col-reverse xxs:flex-row flex-auto items-center items-end gap-3">
|
||||
<h1 class="text-4xl dark:text-neutral-200 font-medium flex-grow self-start mb-4">
|
||||
<img src="./img/logo.png" width="32" class="inline align-middle dark:bg mr-2" /><span class="align-middle">WireGuard</span>
|
||||
<img src="./img/logo.svg" width="60" class="inline align-middle dark:bg mr-2" /><span class="align-middle">AmneziaWG</span>
|
||||
</h1>
|
||||
<div class="flex items-center grow-0 gap-3 items-end self-end xxs:self-center">
|
||||
<!-- Dark / light theme -->
|
||||
|
@ -615,8 +615,8 @@
|
|||
|
||||
<div v-if="authenticated === false">
|
||||
<h1 class="text-4xl font-medium my-16 text-gray-700 dark:text-neutral-200 text-center">
|
||||
<img src="./img/logo.png" width="32" class="inline align-middle dark:bg" />
|
||||
<span class="align-middle">WireGuard</span>
|
||||
<img src="./img/logo.svg" width="60" class="inline align-middle dark:bg" />
|
||||
<span class="align-middle">AmneziaWG</span>
|
||||
</h1>
|
||||
|
||||
<form @submit="login"
|
||||
|
@ -683,12 +683,6 @@
|
|||
|
||||
</div>
|
||||
|
||||
<p v-cloak class="text-center m-10 text-gray-300 dark:text-neutral-600 text-xs"> <a class="hover:underline" target="_blank"
|
||||
href="https://github.com/wg-easy/wg-easy">WireGuard Easy</a> © 2021-2024 by <a class="hover:underline" target="_blank"
|
||||
href="https://emilenijssen.nl/?ref=wg-easy">Emile Nijssen</a> is licensed under <a class="hover:underline" target="_blank"
|
||||
href="http://creativecommons.org/licenses/by-nc-sa/4.0/">CC BY-NC-SA 4.0</a> · <a class="hover:underline"
|
||||
href="https://github.com/sponsors/WeeJeWel" target="_blank">{{$t("donate")}}</a></p>
|
||||
|
||||
</div>
|
||||
|
||||
<script src="./js/vendor/vue.min.js"></script>
|
||||
|
|
|
@ -78,6 +78,13 @@ class API {
|
|||
});
|
||||
}
|
||||
|
||||
async getAvatarSettings() {
|
||||
return this.call({
|
||||
method: 'get',
|
||||
path: '/ui-avatar-settings',
|
||||
});
|
||||
}
|
||||
|
||||
async getSession() {
|
||||
return this.call({
|
||||
method: 'get',
|
||||
|
|
|
@ -92,6 +92,10 @@ new Vue({
|
|||
uiTrafficStats: false,
|
||||
|
||||
uiChartType: 0,
|
||||
avatarSettings: {
|
||||
'dicebear': null,
|
||||
'gravatar': false,
|
||||
},
|
||||
enableOneTimeLinks: false,
|
||||
enableSortClient: false,
|
||||
sortClient: true, // Sort clients by name, true = asc, false = desc
|
||||
|
@ -200,8 +204,10 @@ new Vue({
|
|||
|
||||
const clients = await this.api.getClients();
|
||||
this.clients = clients.map((client) => {
|
||||
if (client.name.includes('@') && client.name.includes('.')) {
|
||||
if (client.name.includes('@') && client.name.includes('.') && this.avatarSettings.gravatar) {
|
||||
client.avatar = `https://gravatar.com/avatar/${sha256(client.name.toLowerCase().trim())}.jpg`;
|
||||
} else if (this.avatarSettings.dicebear) {
|
||||
client.avatar = `https://api.dicebear.com/9.x/${this.avatarSettings.dicebear}/svg?seed=${sha256(client.name.toLowerCase().trim())}`
|
||||
}
|
||||
|
||||
if (!this.clientsPersist[client.id]) {
|
||||
|
@ -465,6 +471,17 @@ new Vue({
|
|||
this.enableExpireTime = false;
|
||||
});
|
||||
|
||||
this.api.getAvatarSettings()
|
||||
.then((res) => {
|
||||
this.avatarSettings = res;
|
||||
})
|
||||
.catch(() => {
|
||||
this.avatarSettings = {
|
||||
'dicebear': null,
|
||||
'gravatar': false,
|
||||
};
|
||||
});
|
||||
|
||||
Promise.resolve().then(async () => {
|
||||
const lang = await this.api.getLang();
|
||||
if (lang !== localStorage.getItem('lang') && i18n.availableLocales.includes(lang)) {
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
{
|
||||
"name": "WireGuard",
|
||||
"name": "AmneziaWG",
|
||||
"display": "standalone",
|
||||
"background_color": "#fff",
|
||||
"icons": [
|
||||
{
|
||||
"src": "img/favicon.png",
|
||||
"type": "image/png"
|
||||
"src": "img/favicon.ico",
|
||||
"type": "image/x-icon"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
|
@ -1,22 +0,0 @@
|
|||
[Unit]
|
||||
Description=Wireguard VPN + Web-based Admin UI
|
||||
After=network-online.target nss-lookup.target
|
||||
|
||||
[Service]
|
||||
Environment="WG_HOST=raspberrypi.local" # Change this to your host's public address or static public ip.
|
||||
Environment="PASSWORD=REPLACEME" # When set, requires a password when logging in to the Web UI, to disable add a hashtag
|
||||
#Environment="WG_DEFAULT_ADDRESS=10.0.8.x" #Clients IP address range.
|
||||
#Environment="WG_DEFAULT_DNS=10.0.8.1, 1.1.1.1" #DNS server clients will use. If set to blank value, clients will not use any DNS.
|
||||
#Environment="WG_ALLOWED_IPS=0.0.0.0/0,::/0" #Allowed IPs clients will use.
|
||||
#Environment="WG_DEVICE=ens1" #Ethernet device the wireguard traffic should be forwarded through.
|
||||
#Environment="PORT=80" #TCP port for Web UI. Default : 51821
|
||||
#Environment="WG_MTU=1420" #The MTU the clients will use. Server uses default WG MTU
|
||||
#Environment="WG_PERSISTENT_KEEPALIVE=25" #Value in seconds to keep the "connection" open. If this value is 0, then connections won't be kept alive.
|
||||
Type=simple
|
||||
RemainAfterExit=no
|
||||
ExecStart=/usr/bin/env node /app/server.js
|
||||
Restart=on-failure
|
||||
RestartSec=1
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
Loading…
Reference in New Issue