Compare commits

...

10 Commits

Author SHA1 Message Date
Donald Zou
c7c9d62e80 Update WireguardConfiguration.py 2025-12-15 21:02:22 +08:00
Donald Zou
f5ccbdf9d3 Fixed Restricted Peer might still appear after restricted 2025-12-15 17:13:46 +08:00
Donald Zou
a09342ed2a Added fallback when instance is completely disconnected from internet 2025-12-15 16:25:13 +08:00
Donald Zou
d6a930c04b Bumped version number 2025-12-13 17:20:56 +08:00
Donald Zou
6fe257fa4a Update entrypoint.sh 2025-12-13 16:29:48 +08:00
Donald Zou
e5d1a64d7d Update to Python 3.14-alpine and refactor IP parsing
Bump Dockerfile base image from python:3.13.3-alpine to python:3.14-alpine for both build and runtime stages. Refactor IP address parsing in dashboard.py for improved clarity and variable naming.
2025-12-13 16:05:12 +08:00
Donald Zou
da4cec60e5 Update Dockerfile
Some checks failed
CodeQL / Analyze (javascript) (push) Has been cancelled
CodeQL / Analyze (python) (push) Has been cancelled
Docker Build and Push / docker_build (push) Has been cancelled
Docker Build and Push / docker_scan (push) Has been cancelled
Mark stale issues and pull requests / stale (push) Has been cancelled
2025-12-12 23:41:25 +08:00
DaanSelen
a4d471df4f chore: downgrade python due to compatibility 2025-12-12 16:32:48 +01:00
DaanSelen
f00940b73c chore: cleanup
Some checks failed
CodeQL / Analyze (javascript) (push) Has been cancelled
CodeQL / Analyze (python) (push) Has been cancelled
Docker Build and Push / docker_build (push) Has been cancelled
Docker Build and Push / docker_scan (push) Has been cancelled
2025-12-12 15:27:04 +01:00
DaanSelen
cb9cb4a0b6 chore: fix docker (hopefully) 2025-12-12 15:17:25 +01:00
8 changed files with 41 additions and 30 deletions

View File

@@ -96,9 +96,10 @@ LABEL maintainer="dselen@nerthus.nl"
# Install only the runtime dependencies # Install only the runtime dependencies
RUN apk add --no-cache \ RUN apk add --no-cache \
iproute2 iptables openresolv \ iproute2 iptables \
bash curl procps openrc \ bash curl procps openrc \
tzdata wireguard-tools tzdata wireguard-tools envsubst
SHELL ["/bin/bash", "-o", "pipefail", "-c"]
# Copy only the final binaries from the AWG builder stages # Copy only the final binaries from the AWG builder stages
COPY --from=awg-go /usr/bin/amneziawg-go /usr/bin/amneziawg-go COPY --from=awg-go /usr/bin/amneziawg-go /usr/bin/amneziawg-go
@@ -107,6 +108,7 @@ COPY --from=awg-tools /workspace/awg-tools/src/wg-quick/linux.bash /usr/bin/awg-
# Environment variables # Environment variables
ARG wg_net="10.0.0.1" ARG wg_net="10.0.0.1"
ARG wg_subn="24"
ARG wg_port="51820" ARG wg_port="51820"
ENV TZ="Europe/Amsterdam" \ ENV TZ="Europe/Amsterdam" \
global_dns="9.9.9.9" \ global_dns="9.9.9.9" \
@@ -117,32 +119,23 @@ ENV TZ="Europe/Amsterdam" \
# Create directories needed for operation # Create directories needed for operation
RUN mkdir /data /configs -p ${WGDASH}/src /etc/amnezia/amneziawg RUN mkdir /data /configs -p ${WGDASH}/src /etc/amnezia/amneziawg
# Copy the python virtual environment from the pip-builder stage # Copy the venv and source files from local compiled locations or repos
COPY ./src ${WGDASH}/src COPY ./src ${WGDASH}/src
COPY --from=pip-builder /opt/wgdashboard/src/venv /opt/wgdashboard/src/venv COPY --from=pip-builder /opt/wgdashboard/src/venv /opt/wgdashboard/src/venv
COPY ./docker/wg0.conf.template /tmp/wg0.conf.template
# Copy in the runtime script, essential.
COPY ./docker/entrypoint.sh /entrypoint.sh
# First WireGuard interface template # First WireGuard interface template
SHELL ["/bin/bash", "-o", "pipefail", "-c"] RUN export out_adapt=$(ip -o -4 route show to default | awk '{print $NF}') \
RUN out_adapt=$(ip -o -4 route show to default | awk '{print $NF}') \ && envsubst < /tmp/wg0.conf.template > /configs/wg0.conf.template \
&& echo -e "[Interface]\n\ && chmod 600 /configs/wg0.conf.template \
Address = ${wg_net}/24\n\ && cat /configs/wg0.conf.template
PrivateKey =\n\
PostUp = iptables -t nat -I POSTROUTING 1 -s ${wg_net}/24 -o ${out_adapt} -j MASQUERADE\n\
PostUp = iptables -I FORWARD -i wg0 -o wg0 -j DROP\n\
PreDown = iptables -t nat -D POSTROUTING -s ${wg_net}/24 -o ${out_adapt} -j MASQUERADE\n\
PreDown = iptables -D FORWARD -i wg0 -o wg0 -j DROP\n\
ListenPort = ${wg_port}\n\
SaveConfig = true\n\
DNS = ${global_dns}" > /configs/wg0.conf.template \
&& chmod 600 /configs/wg0.conf.template
# Set a healthcheck to determine the container its health # Set a healthcheck to determine the container its health
HEALTHCHECK --interval=30s --timeout=10s --start-period=5s --retries=3 \ HEALTHCHECK --interval=30s --timeout=10s --start-period=5s --retries=3 \
CMD sh -c 'pgrep gunicorn > /dev/null && pgrep tail > /dev/null' || exit 1 CMD sh -c 'pgrep gunicorn > /dev/null && pgrep tail > /dev/null' || exit 1
# Copy in the runtime script, essential.
COPY ./docker/entrypoint.sh /entrypoint.sh
# Expose ports on the container # Expose ports on the container
EXPOSE 10086 EXPOSE 10086
WORKDIR $WGDASH/src WORKDIR $WGDASH/src

View File

@@ -191,7 +191,11 @@ start_and_monitor() {
echo "Starting WGDashboard directly with Gunicorn..." echo "Starting WGDashboard directly with Gunicorn..."
[[ ! -d ${WGDASH}/src/log ]] && mkdir ${WGDASH}/src/log [[ ! -d ${WGDASH}/src/log ]] && mkdir ${WGDASH}/src/log
[[ ! -d ${WGDASH}/src/download ]] && mkdir ${WGDASH}/src/download
${WGDASH}/src/venv/bin/gunicorn --config ${WGDASH}/src/gunicorn.conf.py ${WGDASH}/src/venv/bin/gunicorn --config ${WGDASH}/src/gunicorn.conf.py
resolvconf -u
if [ $? -ne 0 ]; then if [ $? -ne 0 ]; then
echo "Loading WGDashboard failed... Look above for details." echo "Loading WGDashboard failed... Look above for details."
fi fi

8
docker/wg0.conf.template Normal file
View File

@@ -0,0 +1,8 @@
[Interface]
Address = ${wg_net}/24
PrivateKey =
PostUp = iptables -t nat -I POSTROUTING 1 -s ${wg_net}/24 -o ${out_adapt} -j MASQUERADE; iptables -I FORWARD -i wg0 -o wg0 -j DROP
PreDown = iptables -t nat -D POSTROUTING -s ${wg_net}/24 -o ${out_adapt} -j MASQUERADE; iptables -D FORWARD -i wg0 -o wg0 -j DROP
ListenPort = ${wg_port}
SaveConfig = true
DNS = ${global_dns}

View File

@@ -1238,8 +1238,9 @@ def API_ping_getAllPeersIpAddress():
ip = ipaddress.ip_network(x, strict=False) ip = ipaddress.ip_network(x, strict=False)
except ValueError as e: except ValueError as e:
app.logger.error(f"Failed to parse IP address of {p.id} - {c.Name}") app.logger.error(f"Failed to parse IP address of {p.id} - {c.Name}")
if len(list(ip.hosts())) == 1: host = list(ip.hosts())
parsed.append(str(ip.hosts()[0])) if len(host) == 1:
parsed.append(str(host[0]))
endpoint = p.endpoint.replace(" ", "").replace("(none)", "") endpoint = p.endpoint.replace(" ", "").replace("(none)", "")
if len(p.name) > 0: if len(p.name) > 0:
cips[f"{p.name} - {p.id}"] = { cips[f"{p.name} - {p.id}"] = {

View File

@@ -16,7 +16,7 @@ from .DashboardAPIKey import DashboardAPIKey
class DashboardConfig: class DashboardConfig:
DashboardVersion = 'v4.3.0.3' DashboardVersion = 'v4.3.1'
ConfigurationPath = os.getenv('CONFIGURATION_PATH', '.') ConfigurationPath = os.getenv('CONFIGURATION_PATH', '.')
ConfigurationFilePath = os.path.join(ConfigurationPath, 'wg-dashboard.ini') ConfigurationFilePath = os.path.join(ConfigurationPath, 'wg-dashboard.ini')

View File

@@ -18,10 +18,18 @@ def GetRemoteEndpoint() -> str:
@return: @return:
""" """
import socket import socket
try:
with socket.socket(socket.AF_INET, socket.SOCK_DGRAM) as s: with socket.socket(socket.AF_INET, socket.SOCK_DGRAM) as s:
s.connect(("1.1.1.1", 80)) # Connecting to a public IP s.connect(("1.1.1.1", 80)) # Connecting to a public IP
wgd_remote_endpoint = s.getsockname()[0] wgd_remote_endpoint = s.getsockname()[0]
return str(wgd_remote_endpoint) return str(wgd_remote_endpoint)
except (socket.error, OSError):
pass
try:
return socket.gethostbyname(socket.gethostname())
except (socket.error, OSError):
pass
return "127.0.0.1"
def StringToBoolean(value: str): def StringToBoolean(value: str):

View File

@@ -404,6 +404,7 @@ class WireguardConfiguration:
try: try:
if "[Peer]" not in content: if "[Peer]" not in content:
current_app.logger.info(f"{self.Name} config has no [Peer] section") current_app.logger.info(f"{self.Name} config has no [Peer] section")
self.Peers = []
return return
peerStarts = content.index("[Peer]") peerStarts = content.index("[Peer]")
@@ -665,9 +666,8 @@ class WireguardConfiguration:
if not self.__wgSave(): if not self.__wgSave():
return False, "Failed to save configuration through WireGuard" return False, "Failed to save configuration through WireGuard"
self.getRestrictedPeers()
self.getPeers() self.getPeers()
if numOfRestrictedPeers == len(listOfPublicKeys): if numOfRestrictedPeers == len(listOfPublicKeys):
return True, f"Restricted {numOfRestrictedPeers} peer(s)" return True, f"Restricted {numOfRestrictedPeers} peer(s)"
return False, f"Restricted {numOfRestrictedPeers} peer(s) successfully. Failed to restrict {numOfFailedToRestrictPeers} peer(s)" return False, f"Restricted {numOfRestrictedPeers} peer(s) successfully. Failed to restrict {numOfFailedToRestrictPeers} peer(s)"
@@ -783,9 +783,7 @@ class WireguardConfiguration:
) )
).mappings().fetchone() ).mappings().fetchone()
if cur_i is not None: if cur_i is not None:
# print(cur_i is None)
total_sent = cur_i['total_sent'] total_sent = cur_i['total_sent']
# print(cur_i is None)
total_receive = cur_i['total_receive'] total_receive = cur_i['total_receive']
cur_total_sent = float(data_usage[i][2]) / (1024 ** 3) cur_total_sent = float(data_usage[i][2]) / (1024 ** 3)
cur_total_receive = float(data_usage[i][1]) / (1024 ** 3) cur_total_receive = float(data_usage[i][1]) / (1024 ** 3)
@@ -1226,7 +1224,6 @@ class WireguardConfiguration:
def __validateOverridePeerSettings(self, key: str, value: str | int) -> tuple[bool, None] | tuple[bool, str]: def __validateOverridePeerSettings(self, key: str, value: str | int) -> tuple[bool, None] | tuple[bool, str]:
status = True status = True
msg = None msg = None
print(value)
if key == "DNS" and value: if key == "DNS" and value:
status, msg = ValidateDNSAddress(value) status, msg = ValidateDNSAddress(value)
elif key == "EndpointAllowedIPs" and value: elif key == "EndpointAllowedIPs" and value:

View File

@@ -1,6 +1,6 @@
{ {
"name": "app", "name": "app",
"version": "4.3.0.3", "version": "4.3.1",
"private": true, "private": true,
"type": "module", "type": "module",
"module": "es2022", "module": "es2022",