From 06193d27c0cd86f2e2531cf9d3507866068b8649 Mon Sep 17 00:00:00 2001 From: Daan Date: Tue, 4 Jun 2024 17:05:17 +0200 Subject: [PATCH 01/14] Added dockerfile and entrypoint for basic compilation, moving to finalizing --- docker/Dockerfile | 43 +++++++++++++++++++++++++++++++++++++++++++ docker/entrypoint.sh | 19 +++++++++++++++++++ 2 files changed, 62 insertions(+) create mode 100644 docker/Dockerfile create mode 100644 docker/entrypoint.sh diff --git a/docker/Dockerfile b/docker/Dockerfile new file mode 100644 index 0000000..d6d4fc3 --- /dev/null +++ b/docker/Dockerfile @@ -0,0 +1,43 @@ +# Pull from small Debian stable image. +FROM debian:stable-slim +LABEL maintainer="dselen@nerthus.nl" + +# Copy the basic entrypoint.sh script. +COPY entrypoint.sh /entrypoint.sh + +# Declaring environment variables +ENV tz=Europe/Amsterdam +ENV WGPEERNET=10.0.0.1 + +# Doing basic system maintenance. Change the timezone to the desired timezone. +RUN ln -sf /usr/share/zoneinfo/${tz} /etc/localtime \ + && apt-get update \ + && apt-get upgrade -y \ + && apt-get purge linux-image* -y \ + && apt-get autoremove -y +# Removing the linux-image package to preserve space on the container. + +# Installing needed packages for installation. +RUN apt-get install -y --no-install-recommends git wireguard wireguard-tools python3 python3-pip python3-venv iproute2 openresolv procps + +ENV WGDASH=/opt/wireguardashboard +RUN python3 -m venv ${WGDASH}/venv + +# Doing WireGuard Dashboard installation measures. +RUN . ${WGDASH}/venv/bin/activate \ + && git clone -b v3.0.6.2 https://github.com/donaldzou/WGDashboard.git ${WGDASH}/app \ + && pip3 install -r ${WGDASH}/app/src/requirements.txt \ + && chmod +x ${WGDASH}/app/src/wgd.sh \ + && .${WGDASH}/app/src/wgd.sh install + +# Set the volume to be used for persistency. +VOLUME /etc/wireguard + +# Generate basic WireGuard interface. Change Peernet to CIDR you would like. +RUN wg genkey | tee /etc/wireguard/wg0_privatekey \ + && echo "[Interface]\nSaveConfig = true\nAddress = ${WGPEERNET}/24\nPrivateKey = $(cat /etc/wireguard/wg0_privatekey)\nListenPort = 51820\nDNS = 8.8.8.8" > /etc/wireguard/wg0.conf \ + && rm /etc/wireguard/wg0_privatekey + +# Exposing the default WireGuard Dashboard port for web access. +EXPOSE 10086 +ENTRYPOINT ["/bin/bash", "/entrypoint.sh"] \ No newline at end of file diff --git a/docker/entrypoint.sh b/docker/entrypoint.sh new file mode 100644 index 0000000..ed61833 --- /dev/null +++ b/docker/entrypoint.sh @@ -0,0 +1,19 @@ +echo "Starting the WireGuard Dashboard." + +outgoing=$(ip -o -4 route show to default | awk '{print $NF}') +echo $outgoing + +. ${WGDASH}/venv/bin/activate +cd /opt/wireguardashboard/app/src +bash ./wgd.sh start + +if [ "$tz" != "Europe/Amsterdam" ]; then + echo "Changing timezone..." + ln -sf /usr/share/zoneinfo/$tz /etc/localtime +fi + +sleep 3s +tail -f /opt/wireguardashboard/app/src/log/*.log + +# Blocking command in case of erroring. +sleep infinity \ No newline at end of file From 0938f5ab7113854c391d62c7e2fe646a5c7d028b Mon Sep 17 00:00:00 2001 From: Daan Date: Tue, 4 Jun 2024 22:49:17 +0200 Subject: [PATCH 02/14] Container deployed with working VPN server built-in. Missing is persistency among recreations, looking into that... --- docker/Dockerfile | 19 ++++++++++++++----- docker/compose.yaml | 18 ++++++++++++++++++ docker/entrypoint.sh | 18 ++++++++++++++---- 3 files changed, 46 insertions(+), 9 deletions(-) create mode 100644 docker/compose.yaml diff --git a/docker/Dockerfile b/docker/Dockerfile index d6d4fc3..3c6a800 100644 --- a/docker/Dockerfile +++ b/docker/Dockerfile @@ -5,9 +5,11 @@ LABEL maintainer="dselen@nerthus.nl" # Copy the basic entrypoint.sh script. COPY entrypoint.sh /entrypoint.sh -# Declaring environment variables +# Declaring environment variables, change Peernet to an address you like, standard is a 24 bit subnet. ENV tz=Europe/Amsterdam -ENV WGPEERNET=10.0.0.1 +ENV public_ip=0.0.0.0 +ENV wg_net=10.0.0.1 +ENV global_dns=1.1.1.1 # Doing basic system maintenance. Change the timezone to the desired timezone. RUN ln -sf /usr/share/zoneinfo/${tz} /etc/localtime \ @@ -18,7 +20,7 @@ RUN ln -sf /usr/share/zoneinfo/${tz} /etc/localtime \ # Removing the linux-image package to preserve space on the container. # Installing needed packages for installation. -RUN apt-get install -y --no-install-recommends git wireguard wireguard-tools python3 python3-pip python3-venv iproute2 openresolv procps +RUN apt-get install -y --no-install-recommends git wireguard wireguard-tools python3 python3-pip python3-venv iproute2 openresolv procps iptables curl ENV WGDASH=/opt/wireguardashboard RUN python3 -m venv ${WGDASH}/venv @@ -33,9 +35,16 @@ RUN . ${WGDASH}/venv/bin/activate \ # Set the volume to be used for persistency. VOLUME /etc/wireguard -# Generate basic WireGuard interface. Change Peernet to CIDR you would like. +# Generate basic WireGuard interface. Echoing the WireGuard interface config for readability, adjust if you want it for efficiency. RUN wg genkey | tee /etc/wireguard/wg0_privatekey \ - && echo "[Interface]\nSaveConfig = true\nAddress = ${WGPEERNET}/24\nPrivateKey = $(cat /etc/wireguard/wg0_privatekey)\nListenPort = 51820\nDNS = 8.8.8.8" > /etc/wireguard/wg0.conf \ + && echo "[Interface]" > /etc/wireguard/wg0.conf \ + && echo "SaveConfig = true" >> /etc/wireguard/wg0.conf \ + && echo "Address = ${wg_net}/24" >> /etc/wireguard/wg0.conf \ + && echo "PrivateKey = $(cat /etc/wireguard/wg0_privatekey)" >> /etc/wireguard/wg0.conf \ + && echo "PostUp = iptables -t nat -I POSTROUTING 1 -s ${wg_net}/24 -o $(ip -o -4 route show to default | awk '{print $NF}') -j MASQUERADE" >> /etc/wireguard/wg0.conf \ + && echo "PreDown = iptables -t nat -D POSTROUTING -s ${wg_net}/24 -o $(ip -o -4 route show to default | awk '{print $NF}') -j MASQUERADE" >> /etc/wireguard/wg0.conf \ + && echo "ListenPort = 51820" >> /etc/wireguard/wg0.conf \ + && echo "DNS = ${global_dns}" >> /etc/wireguard/wg0.conf \ && rm /etc/wireguard/wg0_privatekey # Exposing the default WireGuard Dashboard port for web access. diff --git a/docker/compose.yaml b/docker/compose.yaml new file mode 100644 index 0000000..3b6ca95 --- /dev/null +++ b/docker/compose.yaml @@ -0,0 +1,18 @@ +services: + wireguard-dashboard: + image: repo.nerthus.nl/app/wireguard-dashboard:latest + restart: unless-stopped + container_name: wire-dash + environment: + #- tz=Europe/Amsterdam # <--- is default + - public_ip=212.124.66.17 + ports: + - 10086:10086/tcp + - 51820:51820/udp + volumes: + - wireguard_confs:/etc/wireguard + cap_add: + - NET_ADMIN + +volumes: + wireguard_confs: diff --git a/docker/entrypoint.sh b/docker/entrypoint.sh index ed61833..1009e56 100644 --- a/docker/entrypoint.sh +++ b/docker/entrypoint.sh @@ -1,10 +1,8 @@ echo "Starting the WireGuard Dashboard." -outgoing=$(ip -o -4 route show to default | awk '{print $NF}') -echo $outgoing - +# Starting the WireGuard Dashboard Web-UI. . ${WGDASH}/venv/bin/activate -cd /opt/wireguardashboard/app/src +cd ${WGDASH}/app/src bash ./wgd.sh start if [ "$tz" != "Europe/Amsterdam" ]; then @@ -12,6 +10,18 @@ if [ "$tz" != "Europe/Amsterdam" ]; then ln -sf /usr/share/zoneinfo/$tz /etc/localtime fi +if [ "$global_dns" != "1.1.1.1" ]; then # Changing the DNS used for clients. Had to change it in 2 locations. + echo "Changing default dns..." + sed -i 's/^DNS = .*/DNS = ${global_dns}/' /etc/wireguard/wg0.conf + sed -i "s/^peer_global_dns = .*/peer_global_dns = $global_dns/" /opt/wireguardashboard/app/src/wg-dashboard.ini +fi + +if [ "$public_ip" != "0.0.0.0" ]; then # Setting the public IP of the WireGuard Dashboard container host. If not defined, it will be tried using ifconfig.me. + sed -i "s/^remote_endpoint = .*/remote_endpoint = $public_ip/" /opt/wireguardashboard/app/src/wg-dashboard.ini +else + sed -i "s/^remote_endpoint = .*/remote_endpoint = $(curl ifconfig.me)/" /opt/wireguardashboard/app/src/wg-dashboard.ini +fi + sleep 3s tail -f /opt/wireguardashboard/app/src/log/*.log From 560096878fb13daf31707e34517301b76b38d4ff Mon Sep 17 00:00:00 2001 From: Daan Date: Tue, 4 Jun 2024 23:26:03 +0200 Subject: [PATCH 03/14] Persistency seems to work with this model, it has succeeded my tests. --- docker/Dockerfile | 2 +- docker/compose.yaml | 3 +++ docker/entrypoint.sh | 7 +++++-- 3 files changed, 9 insertions(+), 3 deletions(-) diff --git a/docker/Dockerfile b/docker/Dockerfile index 3c6a800..9441739 100644 --- a/docker/Dockerfile +++ b/docker/Dockerfile @@ -20,7 +20,7 @@ RUN ln -sf /usr/share/zoneinfo/${tz} /etc/localtime \ # Removing the linux-image package to preserve space on the container. # Installing needed packages for installation. -RUN apt-get install -y --no-install-recommends git wireguard wireguard-tools python3 python3-pip python3-venv iproute2 openresolv procps iptables curl +RUN apt-get install -y --no-install-recommends git wireguard wireguard-tools python3 python3-pip python3-venv iproute2 openresolv procps iptables curl iputils-ping traceroute ENV WGDASH=/opt/wireguardashboard RUN python3 -m venv ${WGDASH}/venv diff --git a/docker/compose.yaml b/docker/compose.yaml index 3b6ca95..e900be2 100644 --- a/docker/compose.yaml +++ b/docker/compose.yaml @@ -4,6 +4,7 @@ services: restart: unless-stopped container_name: wire-dash environment: + #- global_dns=8.8.8.8 #- tz=Europe/Amsterdam # <--- is default - public_ip=212.124.66.17 ports: @@ -11,8 +12,10 @@ services: - 51820:51820/udp volumes: - wireguard_confs:/etc/wireguard + - wireguard_app:/opt/wireguardashboard/app cap_add: - NET_ADMIN volumes: wireguard_confs: + wireguard_app: \ No newline at end of file diff --git a/docker/entrypoint.sh b/docker/entrypoint.sh index 1009e56..3d0ce59 100644 --- a/docker/entrypoint.sh +++ b/docker/entrypoint.sh @@ -1,4 +1,7 @@ -echo "Starting the WireGuard Dashboard." +echo "\nStarting the WireGuard Dashboard." + +# Cleaning out previous data such as the .pid file. +rm /opt/wireguardashboard/app/src/gunicorn.pid # Starting the WireGuard Dashboard Web-UI. . ${WGDASH}/venv/bin/activate @@ -23,7 +26,7 @@ else fi sleep 3s -tail -f /opt/wireguardashboard/app/src/log/*.log +tail -f $(ls -t /opt/wireguardashboard/app/src/log/error_*.log | head -n 1) # Blocking command in case of erroring. sleep infinity \ No newline at end of file From f400844a3dd291575a7969cb95eecaa83de36188 Mon Sep 17 00:00:00 2001 From: Daan Date: Wed, 5 Jun 2024 09:16:29 +0200 Subject: [PATCH 04/14] Modified scripts --- docker/compose.yaml | 4 +-- docker/entrypoint.sh | 79 ++++++++++++++++++++++++++++++-------------- 2 files changed, 56 insertions(+), 27 deletions(-) diff --git a/docker/compose.yaml b/docker/compose.yaml index e900be2..6fb6d68 100644 --- a/docker/compose.yaml +++ b/docker/compose.yaml @@ -4,8 +4,8 @@ services: restart: unless-stopped container_name: wire-dash environment: - #- global_dns=8.8.8.8 - #- tz=Europe/Amsterdam # <--- is default + #- global_dns=8.8.8.8 # <--- 1.1.1.1 is default + #- tz=Europe/Amsterdam # <--- Europe/Amsterdam is default - public_ip=212.124.66.17 ports: - 10086:10086/tcp diff --git a/docker/entrypoint.sh b/docker/entrypoint.sh index 3d0ce59..f1ef204 100644 --- a/docker/entrypoint.sh +++ b/docker/entrypoint.sh @@ -1,32 +1,61 @@ -echo "\nStarting the WireGuard Dashboard." +#!/bin/bash +echo "\nStarting the WireGuard Dashboard Docker container." -# Cleaning out previous data such as the .pid file. -rm /opt/wireguardashboard/app/src/gunicorn.pid +# Execute functions for the WireGuard Dashboard services, then set the environment variables +start_core +set_envvars +ensure_blocking -# Starting the WireGuard Dashboard Web-UI. -. ${WGDASH}/venv/bin/activate -cd ${WGDASH}/app/src -bash ./wgd.sh start +start_core() { + # Cleaning out previous data such as the .pid file and starting the WireGuard Dashboard. Making sure to use the python venv. + echo "Activating Python venv and executing the WireGuard Dashboard service..." -if [ "$tz" != "Europe/Amsterdam" ]; then - echo "Changing timezone..." - ln -sf /usr/share/zoneinfo/$tz /etc/localtime -fi + rm /opt/wireguardashboard/app/src/gunicorn.pid + . ${WGDASH}/venv/bin/activate + bash ${WGDASH}/app/src/wgd.sh start +} -if [ "$global_dns" != "1.1.1.1" ]; then # Changing the DNS used for clients. Had to change it in 2 locations. - echo "Changing default dns..." - sed -i 's/^DNS = .*/DNS = ${global_dns}/' /etc/wireguard/wg0.conf - sed -i "s/^peer_global_dns = .*/peer_global_dns = $global_dns/" /opt/wireguardashboard/app/src/wg-dashboard.ini -fi +set_envvars() { + echo "Setting relevant variables for operation..." -if [ "$public_ip" != "0.0.0.0" ]; then # Setting the public IP of the WireGuard Dashboard container host. If not defined, it will be tried using ifconfig.me. - sed -i "s/^remote_endpoint = .*/remote_endpoint = $public_ip/" /opt/wireguardashboard/app/src/wg-dashboard.ini -else - sed -i "s/^remote_endpoint = .*/remote_endpoint = $(curl ifconfig.me)/" /opt/wireguardashboard/app/src/wg-dashboard.ini -fi + # If the timezone is different, for example in North-America or Asia. + if [ "$tz" != "Europe/Amsterdam" ]; then + echo "Changing timezone..." + + ln -sf /usr/share/zoneinfo/$tz /etc/localtime + fi -sleep 3s -tail -f $(ls -t /opt/wireguardashboard/app/src/log/error_*.log | head -n 1) + # Changing the DNS used for clients and the dashboard itself. + if [ "$global_dns" != "1.1.1.1" ]; then + echo "Changing default dns..." -# Blocking command in case of erroring. -sleep infinity \ No newline at end of file + sed -i 's/^DNS = .*/DNS = ${global_dns}/' /etc/wireguard/wg0.conf + sed -i "s/^peer_global_dns = .*/peer_global_dns = $global_dns/" /opt/wireguardashboard/app/src/wg-dashboard.ini + fi + + # Setting the public IP of the WireGuard Dashboard container host. If not defined, it will trying fetching it using a curl to ifconfig.me. + if [ "$public_ip" != "0.0.0.0" ]; then + echo "Setting the Public-IP using given variable: $public_ip" + + sed -i "s/^remote_endpoint = .*/remote_endpoint = $public_ip/" /opt/wireguardashboard/app/src/wg-dashboard.ini + else + default_ip=$(curl ifconfig.me) + echo "Trying to fetch the Public-IP using ifconfig.me: $default_ip" + + sed -i "s/^remote_endpoint = .*/remote_endpoint = $default_ip/" /opt/wireguardashboard/app/src/wg-dashboard.ini + fi +} + +ensure_blocking() { + echo "Ensuring container continuation..." + + # This function checks if the latest error log is created and tails it for docker logs uses. + if find "/opt/wireguardashboard/app/src/log" -mindepth 1 -maxdepth 1 -type f | read -r; then + latestlog=$(ls -t /opt/wireguardashboard/app/src/log/error_*.log | head -n 1) + sleep 3s + tail -f $latestlog + fi + + # Blocking command in case of erroring. So the container does not quit. + sleep infinity +} \ No newline at end of file From 8ad601fcc00dbd3f72d5e81fe0130fd9d17093ff Mon Sep 17 00:00:00 2001 From: Daan Date: Wed, 5 Jun 2024 20:27:24 +0200 Subject: [PATCH 05/14] Added features, plus explanations in about them in the compose.yaml file. Looking great! --- docker/Dockerfile | 23 +++++++------- docker/compose.yaml | 11 +++---- docker/entrypoint.sh | 71 ++++++++++++++++++++++++++++---------------- 3 files changed, 64 insertions(+), 41 deletions(-) diff --git a/docker/Dockerfile b/docker/Dockerfile index 9441739..4b98e20 100644 --- a/docker/Dockerfile +++ b/docker/Dockerfile @@ -6,28 +6,31 @@ LABEL maintainer="dselen@nerthus.nl" COPY entrypoint.sh /entrypoint.sh # Declaring environment variables, change Peernet to an address you like, standard is a 24 bit subnet. -ENV tz=Europe/Amsterdam -ENV public_ip=0.0.0.0 -ENV wg_net=10.0.0.1 -ENV global_dns=1.1.1.1 +ARG dash_ver="v3.0.6.2" + +ENV tz="Europe/Amsterdam" +ENV public_ip="0.0.0.0" +ENV wg_net="10.0.0.1" +ENV global_dns="1.1.1.1" +ENV enable_wg0="false" # Doing basic system maintenance. Change the timezone to the desired timezone. RUN ln -sf /usr/share/zoneinfo/${tz} /etc/localtime \ && apt-get update \ - && apt-get upgrade -y \ - && apt-get purge linux-image* -y \ - && apt-get autoremove -y + && apt-get upgrade -y # Removing the linux-image package to preserve space on the container. # Installing needed packages for installation. -RUN apt-get install -y --no-install-recommends git wireguard wireguard-tools python3 python3-pip python3-venv iproute2 openresolv procps iptables curl iputils-ping traceroute +RUN apt-get install -y --no-install-recommends git wireguard wireguard-tools python3 python3-pip python3-venv iproute2 openresolv procps iptables curl iputils-ping traceroute \ + && apt remove linux-image-* --autoremove -y \ + && apt-get clean ENV WGDASH=/opt/wireguardashboard RUN python3 -m venv ${WGDASH}/venv # Doing WireGuard Dashboard installation measures. RUN . ${WGDASH}/venv/bin/activate \ - && git clone -b v3.0.6.2 https://github.com/donaldzou/WGDashboard.git ${WGDASH}/app \ + && git clone -b ${dash_ver} https://github.com/donaldzou/WGDashboard.git ${WGDASH}/app \ && pip3 install -r ${WGDASH}/app/src/requirements.txt \ && chmod +x ${WGDASH}/app/src/wgd.sh \ && .${WGDASH}/app/src/wgd.sh install @@ -44,7 +47,7 @@ RUN wg genkey | tee /etc/wireguard/wg0_privatekey \ && echo "PostUp = iptables -t nat -I POSTROUTING 1 -s ${wg_net}/24 -o $(ip -o -4 route show to default | awk '{print $NF}') -j MASQUERADE" >> /etc/wireguard/wg0.conf \ && echo "PreDown = iptables -t nat -D POSTROUTING -s ${wg_net}/24 -o $(ip -o -4 route show to default | awk '{print $NF}') -j MASQUERADE" >> /etc/wireguard/wg0.conf \ && echo "ListenPort = 51820" >> /etc/wireguard/wg0.conf \ - && echo "DNS = ${global_dns}" >> /etc/wireguard/wg0.conf \ + #&& echo "DNS = ${global_dns}" >> /etc/wireguard/wg0.conf \ && rm /etc/wireguard/wg0_privatekey # Exposing the default WireGuard Dashboard port for web access. diff --git a/docker/compose.yaml b/docker/compose.yaml index 6fb6d68..733d755 100644 --- a/docker/compose.yaml +++ b/docker/compose.yaml @@ -1,12 +1,13 @@ services: wireguard-dashboard: - image: repo.nerthus.nl/app/wireguard-dashboard:latest + image: repo.nerthus.nl/app/wireguard-dashboard:05-06-2024 restart: unless-stopped container_name: wire-dash environment: - #- global_dns=8.8.8.8 # <--- 1.1.1.1 is default - #- tz=Europe/Amsterdam # <--- Europe/Amsterdam is default - - public_ip=212.124.66.17 + #- tz= # <--- Set container timezone, default: Europe/Amsterdam. + #- global_dns= # <--- Set global DNS address, default: 1.1.1.1. + #- public_ip= # <--- Set public IP to ensure the correct one is chosen, defaulting to the IP give by ifconfig.me. + - enable_wg0=true # <--- If set to true, it will try to enable the wg0 (main) interface on startup, to immediatly accept connections. When true, there will be no need to manually start the interface. ports: - 10086:10086/tcp - 51820:51820/udp @@ -18,4 +19,4 @@ services: volumes: wireguard_confs: - wireguard_app: \ No newline at end of file + wireguard_app: diff --git a/docker/entrypoint.sh b/docker/entrypoint.sh index f1ef204..c2a9614 100644 --- a/docker/entrypoint.sh +++ b/docker/entrypoint.sh @@ -1,61 +1,80 @@ #!/bin/bash -echo "\nStarting the WireGuard Dashboard Docker container." +echo "Starting the WireGuard Dashboard Docker container." -# Execute functions for the WireGuard Dashboard services, then set the environment variables -start_core -set_envvars -ensure_blocking +clean_up() { + echo "Looking for remains of previous instances..." + if [ -f "/opt/wireguardashboard/app/src/gunicorn.pid" ]; then + echo "Found old .pid file, removing." + rm /opt/wireguardashboard/app/src/gunicorn.pid + else + echo "No remains found, continuing." + fi +} start_core() { # Cleaning out previous data such as the .pid file and starting the WireGuard Dashboard. Making sure to use the python venv. - echo "Activating Python venv and executing the WireGuard Dashboard service..." + echo "Activating Python venv and executing the WireGuard Dashboard service." - rm /opt/wireguardashboard/app/src/gunicorn.pid . ${WGDASH}/venv/bin/activate - bash ${WGDASH}/app/src/wgd.sh start + cd ${WGDASH}/app/src + bash wgd.sh start + + if [ "${enable_wg0,,}" == "true" ]; then + echo "Preference for wg0 to be turned on found." + wg-quick up wg0 + else + echo "Preference for wg0 to be turned off found." + fi } set_envvars() { - echo "Setting relevant variables for operation..." + echo "Setting relevant variables for operation." # If the timezone is different, for example in North-America or Asia. - if [ "$tz" != "Europe/Amsterdam" ]; then - echo "Changing timezone..." + if [ "${tz}" != "$(cat /etc/timezone)" ]; then + echo "Changing timezone." - ln -sf /usr/share/zoneinfo/$tz /etc/localtime + ln -sf /usr/share/zoneinfo/${tz} /etc/localtime + echo ${tz} > /etc/timezone fi # Changing the DNS used for clients and the dashboard itself. - if [ "$global_dns" != "1.1.1.1" ]; then - echo "Changing default dns..." + if [ "${global_dns}" != "$(grep "peer_global_dns = " /opt/wireguardashboard/app/src/wg-dashboard.ini | awk '{print $NF}')" ]; then + echo "Changing default dns." sed -i 's/^DNS = .*/DNS = ${global_dns}/' /etc/wireguard/wg0.conf - sed -i "s/^peer_global_dns = .*/peer_global_dns = $global_dns/" /opt/wireguardashboard/app/src/wg-dashboard.ini + sed -i "s/^peer_global_dns = .*/peer_global_dns = ${global_dns}/" /opt/wireguardashboard/app/src/wg-dashboard.ini fi # Setting the public IP of the WireGuard Dashboard container host. If not defined, it will trying fetching it using a curl to ifconfig.me. - if [ "$public_ip" != "0.0.0.0" ]; then - echo "Setting the Public-IP using given variable: $public_ip" + if [ "${public_ip}" == "0.0.0.0" ]; then + default_ip=$(curl -s ifconfig.me) + echo "Trying to fetch the Public-IP using ifconfig.me: ${default_ip}" - sed -i "s/^remote_endpoint = .*/remote_endpoint = $public_ip/" /opt/wireguardashboard/app/src/wg-dashboard.ini - else - default_ip=$(curl ifconfig.me) - echo "Trying to fetch the Public-IP using ifconfig.me: $default_ip" + sed -i "s/^remote_endpoint = .*/remote_endpoint = ${default_ip}/" /opt/wireguardashboard/app/src/wg-dashboard.ini + elif [ "${public_ip}" != $(grep "remote_endpoint = " /opt/wireguardashboard/app/src/wg-dashboard.ini | awk '{print $NF}') ]; then + echo "Setting the Public-IP using given variable: ${public_ip}" - sed -i "s/^remote_endpoint = .*/remote_endpoint = $default_ip/" /opt/wireguardashboard/app/src/wg-dashboard.ini + sed -i "s/^remote_endpoint = .*/remote_endpoint = ${public_ip}/" /opt/wireguardashboard/app/src/wg-dashboard.ini fi } ensure_blocking() { - echo "Ensuring container continuation..." - + echo "Ensuring container continuation." + # This function checks if the latest error log is created and tails it for docker logs uses. if find "/opt/wireguardashboard/app/src/log" -mindepth 1 -maxdepth 1 -type f | read -r; then latestlog=$(ls -t /opt/wireguardashboard/app/src/log/error_*.log | head -n 1) sleep 3s - tail -f $latestlog + tail -f ${latestlog} fi # Blocking command in case of erroring. So the container does not quit. sleep infinity -} \ No newline at end of file +} + +# Execute functions for the WireGuard Dashboard services, then set the environment variables +clean_up +start_core +set_envvars +ensure_blocking \ No newline at end of file From 6dc28f11e0581602491b7414c7e89ad119f1a775 Mon Sep 17 00:00:00 2001 From: Daan Date: Thu, 6 Jun 2024 00:12:11 +0200 Subject: [PATCH 06/14] Working on isolated peers feature. --- docker/Dockerfile | 8 ++++++-- docker/compose.yaml | 13 +++++++------ docker/entrypoint.sh | 12 ++++++++++++ 3 files changed, 25 insertions(+), 8 deletions(-) diff --git a/docker/Dockerfile b/docker/Dockerfile index 4b98e20..1c5c681 100644 --- a/docker/Dockerfile +++ b/docker/Dockerfile @@ -7,12 +7,14 @@ COPY entrypoint.sh /entrypoint.sh # Declaring environment variables, change Peernet to an address you like, standard is a 24 bit subnet. ARG dash_ver="v3.0.6.2" +ENV wg_net="10.0.0.1" +# wg_net is used functionally as an ARG for its environment variable nature, do not change unless you know what you are doing. ENV tz="Europe/Amsterdam" -ENV public_ip="0.0.0.0" -ENV wg_net="10.0.0.1" ENV global_dns="1.1.1.1" ENV enable_wg0="false" +ENV isolated_peers="true" +ENV public_ip="0.0.0.0" # Doing basic system maintenance. Change the timezone to the desired timezone. RUN ln -sf /usr/share/zoneinfo/${tz} /etc/localtime \ @@ -45,7 +47,9 @@ RUN wg genkey | tee /etc/wireguard/wg0_privatekey \ && echo "Address = ${wg_net}/24" >> /etc/wireguard/wg0.conf \ && echo "PrivateKey = $(cat /etc/wireguard/wg0_privatekey)" >> /etc/wireguard/wg0.conf \ && echo "PostUp = iptables -t nat -I POSTROUTING 1 -s ${wg_net}/24 -o $(ip -o -4 route show to default | awk '{print $NF}') -j MASQUERADE" >> /etc/wireguard/wg0.conf \ + && echo "PostUp = iptables -I FORWARD -i wg0 -o wg0 -j DROP" >> /etc/wireguard/wg0.conf \ && echo "PreDown = iptables -t nat -D POSTROUTING -s ${wg_net}/24 -o $(ip -o -4 route show to default | awk '{print $NF}') -j MASQUERADE" >> /etc/wireguard/wg0.conf \ + && echo "PreDown = iptables -D FORWARD -i wg0 -o wg0 -j DROP" >> /etc/wireguard/wg0.conf \ && echo "ListenPort = 51820" >> /etc/wireguard/wg0.conf \ #&& echo "DNS = ${global_dns}" >> /etc/wireguard/wg0.conf \ && rm /etc/wireguard/wg0_privatekey diff --git a/docker/compose.yaml b/docker/compose.yaml index 733d755..7ac31af 100644 --- a/docker/compose.yaml +++ b/docker/compose.yaml @@ -1,22 +1,23 @@ services: wireguard-dashboard: - image: repo.nerthus.nl/app/wireguard-dashboard:05-06-2024 + image: repo.nerthus.nl/app/wireguard-dashboard:dev restart: unless-stopped container_name: wire-dash environment: #- tz= # <--- Set container timezone, default: Europe/Amsterdam. #- global_dns= # <--- Set global DNS address, default: 1.1.1.1. + - enable_wg0=true # <--- If true, wg0 will be started on container startup. defaul: + - isolated_peers=false # <--- When set to true, it disallows peers to talk to eachother, setting to false, allows it, default: true. #- public_ip= # <--- Set public IP to ensure the correct one is chosen, defaulting to the IP give by ifconfig.me. - - enable_wg0=true # <--- If set to true, it will try to enable the wg0 (main) interface on startup, to immediatly accept connections. When true, there will be no need to manually start the interface. ports: - 10086:10086/tcp - 51820:51820/udp volumes: - - wireguard_confs:/etc/wireguard - - wireguard_app:/opt/wireguardashboard/app + - conf:/etc/wireguard + - app:/opt/wireguardashboard/app cap_add: - NET_ADMIN volumes: - wireguard_confs: - wireguard_app: + conf: + app: diff --git a/docker/entrypoint.sh b/docker/entrypoint.sh index c2a9614..2825e61 100644 --- a/docker/entrypoint.sh +++ b/docker/entrypoint.sh @@ -19,8 +19,20 @@ start_core() { cd ${WGDASH}/app/src bash wgd.sh start + echo "${isolated_peers}" + if [ "${isolated_peers,,}" == "false" ]; then + echo "Isolated peers disabled, adjusting." + + sed -i '/^.*FORWARD -i wg0 -o wg0 -j DROP.*$/s/^/#/' /etc/wireguard/wg0.conf + elif [ "${isolated_peers,,}" == "true" ]; then + echo "Isolated peers enabled, adjusting." + + sed -i 's/^#//' /etc/wireguard/wg0.conf + fi + if [ "${enable_wg0,,}" == "true" ]; then echo "Preference for wg0 to be turned on found." + wg-quick up wg0 else echo "Preference for wg0 to be turned off found." From 1bcddadb7a19747bb0df970381051585b65992e1 Mon Sep 17 00:00:00 2001 From: Daan Date: Thu, 6 Jun 2024 16:11:49 +0200 Subject: [PATCH 07/14] Features tested working, feeling good about a release. --- docker/Dockerfile | 33 ++++++++++++++++++++++++--------- docker/compose.yaml | 2 +- docker/entrypoint.sh | 29 +++++++++++++++++------------ 3 files changed, 42 insertions(+), 22 deletions(-) diff --git a/docker/Dockerfile b/docker/Dockerfile index 1c5c681..aa75ae0 100644 --- a/docker/Dockerfile +++ b/docker/Dockerfile @@ -10,6 +10,7 @@ ARG dash_ver="v3.0.6.2" ENV wg_net="10.0.0.1" # wg_net is used functionally as an ARG for its environment variable nature, do not change unless you know what you are doing. +# Following ENV variables are changable on container runtime because /entrypoint.sh handles that. See compose.yaml for more info. ENV tz="Europe/Amsterdam" ENV global_dns="1.1.1.1" ENV enable_wg0="false" @@ -17,15 +18,27 @@ ENV isolated_peers="true" ENV public_ip="0.0.0.0" # Doing basic system maintenance. Change the timezone to the desired timezone. -RUN ln -sf /usr/share/zoneinfo/${tz} /etc/localtime \ - && apt-get update \ - && apt-get upgrade -y -# Removing the linux-image package to preserve space on the container. +RUN ln -sf /usr/share/zoneinfo/${tz} /etc/localtime -# Installing needed packages for installation. -RUN apt-get install -y --no-install-recommends git wireguard wireguard-tools python3 python3-pip python3-venv iproute2 openresolv procps iptables curl iputils-ping traceroute \ - && apt remove linux-image-* --autoremove -y \ - && apt-get clean +# Doing package management operations, such as upgrading +RUN apt-get update && apt-get upgrade -y \ + && apt-get install -y --no-install-recommends curl \ + git \ + iproute2 \ + iptables \ + iputils-ping \ + openresolv \ + procps \ + python3 \ + python3-pip \ + python3-venv \ + traceroute \ + wireguard \ + wireguard-tools \ + && apt-get remove linux-image-* --autoremove -y \ + && apt-get clean \ + && rm -rf /var/lib/apt/lists/* +# Removing the Linux Image package to preserve space on the image, for this reason also deleting apt lists, to be able to install packages: run apt update. ENV WGDASH=/opt/wireguardashboard RUN python3 -m venv ${WGDASH}/venv @@ -41,6 +54,8 @@ RUN . ${WGDASH}/venv/bin/activate \ VOLUME /etc/wireguard # Generate basic WireGuard interface. Echoing the WireGuard interface config for readability, adjust if you want it for efficiency. +# Also setting the pipefail option, verbose: https://github.com/hadolint/hadolint/wiki/DL4006. +SHELL ["/bin/bash", "-o", "pipefail", "-c"] RUN wg genkey | tee /etc/wireguard/wg0_privatekey \ && echo "[Interface]" > /etc/wireguard/wg0.conf \ && echo "SaveConfig = true" >> /etc/wireguard/wg0.conf \ @@ -48,7 +63,7 @@ RUN wg genkey | tee /etc/wireguard/wg0_privatekey \ && echo "PrivateKey = $(cat /etc/wireguard/wg0_privatekey)" >> /etc/wireguard/wg0.conf \ && echo "PostUp = iptables -t nat -I POSTROUTING 1 -s ${wg_net}/24 -o $(ip -o -4 route show to default | awk '{print $NF}') -j MASQUERADE" >> /etc/wireguard/wg0.conf \ && echo "PostUp = iptables -I FORWARD -i wg0 -o wg0 -j DROP" >> /etc/wireguard/wg0.conf \ - && echo "PreDown = iptables -t nat -D POSTROUTING -s ${wg_net}/24 -o $(ip -o -4 route show to default | awk '{print $NF}') -j MASQUERADE" >> /etc/wireguard/wg0.conf \ + && echo "PreDown = iptables -t nat -D POSTROUTING 1 -s ${wg_net}/24 -o $(ip -o -4 route show to default | awk '{print $NF}') -j MASQUERADE" >> /etc/wireguard/wg0.conf \ && echo "PreDown = iptables -D FORWARD -i wg0 -o wg0 -j DROP" >> /etc/wireguard/wg0.conf \ && echo "ListenPort = 51820" >> /etc/wireguard/wg0.conf \ #&& echo "DNS = ${global_dns}" >> /etc/wireguard/wg0.conf \ diff --git a/docker/compose.yaml b/docker/compose.yaml index 7ac31af..5c2a1d9 100644 --- a/docker/compose.yaml +++ b/docker/compose.yaml @@ -6,7 +6,7 @@ services: environment: #- tz= # <--- Set container timezone, default: Europe/Amsterdam. #- global_dns= # <--- Set global DNS address, default: 1.1.1.1. - - enable_wg0=true # <--- If true, wg0 will be started on container startup. defaul: + - enable_wg0=true # <--- If true, wg0 will be started on container startup. default: false. - isolated_peers=false # <--- When set to true, it disallows peers to talk to eachother, setting to false, allows it, default: true. #- public_ip= # <--- Set public IP to ensure the correct one is chosen, defaulting to the IP give by ifconfig.me. ports: diff --git a/docker/entrypoint.sh b/docker/entrypoint.sh index 2825e61..4024b30 100644 --- a/docker/entrypoint.sh +++ b/docker/entrypoint.sh @@ -15,21 +15,26 @@ start_core() { # Cleaning out previous data such as the .pid file and starting the WireGuard Dashboard. Making sure to use the python venv. echo "Activating Python venv and executing the WireGuard Dashboard service." - . ${WGDASH}/venv/bin/activate - cd ${WGDASH}/app/src + . "${WGDASH}"/venv/bin/activate + cd "${WGDASH}"/app/src || return # If changing the directory fails (permission or presence error), then bash will exist this function, causing the WireGuard Dashboard to not be succesfully launched. bash wgd.sh start - echo "${isolated_peers}" + # The following section takes care of the firewall rules regarding the 'isolated_peers' feature, which allows or drops packets destined from the wg0 to the wg0 interface. if [ "${isolated_peers,,}" == "false" ]; then echo "Isolated peers disabled, adjusting." - sed -i '/^.*FORWARD -i wg0 -o wg0 -j DROP.*$/s/^/#/' /etc/wireguard/wg0.conf - elif [ "${isolated_peers,,}" == "true" ]; then + sed -i '/PostUp = iptables -I FORWARD -i wg0 -o wg0 -j DROP/d' /etc/wireguard/wg0.conf + sed -i '/PreDown = iptables -D FORWARD -i wg0 -o wg0 -j DROP/d' /etc/wireguard/wg0.conf + elif [ "${isolated_peers,,}" == "true" ] && \ + [ "$(grep -c "PostUp = iptables -I FORWARD -i wg0 -o wg0 -j DROP" /etc/wireguard/wg0.conf)" -lt 1 ] && \ + [ "$(grep -c "PreDown = iptables -D FORWARD -i wg0 -o wg0 -j DROP" /etc/wireguard/wg0.conf)" -lt 1 ]; then echo "Isolated peers enabled, adjusting." - sed -i 's/^#//' /etc/wireguard/wg0.conf + sed -i '/PostUp = iptables -t nat -I POSTROUTING 1 -s/a PostUp = iptables -I FORWARD -i wg0 -o wg0 -j DROP' /etc/wireguard/wg0.conf + sed -i '/PreDown = iptables -t nat -D POSTROUTING 1 -s/a PreDown = iptables -D FORWARD -i wg0 -o wg0 -j DROP' /etc/wireguard/wg0.conf fi + # The following section takes care of if [ "${enable_wg0,,}" == "true" ]; then echo "Preference for wg0 to be turned on found." @@ -46,15 +51,15 @@ set_envvars() { if [ "${tz}" != "$(cat /etc/timezone)" ]; then echo "Changing timezone." - ln -sf /usr/share/zoneinfo/${tz} /etc/localtime - echo ${tz} > /etc/timezone + ln -sf /usr/share/zoneinfo/"${tz}" /etc/localtime + echo "${tz}" > /etc/timezone fi # Changing the DNS used for clients and the dashboard itself. if [ "${global_dns}" != "$(grep "peer_global_dns = " /opt/wireguardashboard/app/src/wg-dashboard.ini | awk '{print $NF}')" ]; then echo "Changing default dns." - sed -i 's/^DNS = .*/DNS = ${global_dns}/' /etc/wireguard/wg0.conf + #sed -i "s/^DNS = .*/DNS = ${global_dns}/" /etc/wireguard/wg0.conf # Uncomment if you want to have DNS on server-level. sed -i "s/^peer_global_dns = .*/peer_global_dns = ${global_dns}/" /opt/wireguardashboard/app/src/wg-dashboard.ini fi @@ -64,7 +69,7 @@ set_envvars() { echo "Trying to fetch the Public-IP using ifconfig.me: ${default_ip}" sed -i "s/^remote_endpoint = .*/remote_endpoint = ${default_ip}/" /opt/wireguardashboard/app/src/wg-dashboard.ini - elif [ "${public_ip}" != $(grep "remote_endpoint = " /opt/wireguardashboard/app/src/wg-dashboard.ini | awk '{print $NF}') ]; then + elif [ "${public_ip}" != "$(grep "remote_endpoint = " /opt/wireguardashboard/app/src/wg-dashboard.ini | awk '{print $NF}')" ]; then echo "Setting the Public-IP using given variable: ${public_ip}" sed -i "s/^remote_endpoint = .*/remote_endpoint = ${public_ip}/" /opt/wireguardashboard/app/src/wg-dashboard.ini @@ -76,9 +81,9 @@ ensure_blocking() { # This function checks if the latest error log is created and tails it for docker logs uses. if find "/opt/wireguardashboard/app/src/log" -mindepth 1 -maxdepth 1 -type f | read -r; then - latestlog=$(ls -t /opt/wireguardashboard/app/src/log/error_*.log | head -n 1) + latestlog=$(find /opt/wireguardashboard/app/src/log -name "error_*.log" | head -n 1) sleep 3s - tail -f ${latestlog} + tail -f "${latestlog}" fi # Blocking command in case of erroring. So the container does not quit. From cf455fc19b1dd97cdb559c5f24eb1dd555c1d788 Mon Sep 17 00:00:00 2001 From: Daan Date: Fri, 7 Jun 2024 13:25:46 +0200 Subject: [PATCH 08/14] Modified code so that the docker logging makes sense. Also fixed a bug which can happen with iptables (-s illegal option). Pushing to repo. --- docker/Dockerfile | 7 ++++++- docker/compose.yaml | 2 +- docker/entrypoint.sh | 7 ++++--- 3 files changed, 11 insertions(+), 5 deletions(-) diff --git a/docker/Dockerfile b/docker/Dockerfile index aa75ae0..70be161 100644 --- a/docker/Dockerfile +++ b/docker/Dockerfile @@ -40,12 +40,14 @@ RUN apt-get update && apt-get upgrade -y \ && rm -rf /var/lib/apt/lists/* # Removing the Linux Image package to preserve space on the image, for this reason also deleting apt lists, to be able to install packages: run apt update. +# Using WGDASH -- like wg_net functionally as a ARG command. But it is needed in entrypoint.sh so it needs to be exported as environment variable. ENV WGDASH=/opt/wireguardashboard RUN python3 -m venv ${WGDASH}/venv # Doing WireGuard Dashboard installation measures. RUN . ${WGDASH}/venv/bin/activate \ && git clone -b ${dash_ver} https://github.com/donaldzou/WGDashboard.git ${WGDASH}/app \ + && sed -i '/Restart=always/a\StandardOutput=file:{{APP_ROOT}}/log/log1.log\nStandardError=file:{{APP_ROOT}}/log/log2.log' ${WGDASH}/app/src/wg-dashboard.service \ && pip3 install -r ${WGDASH}/app/src/requirements.txt \ && chmod +x ${WGDASH}/app/src/wgd.sh \ && .${WGDASH}/app/src/wgd.sh install @@ -63,12 +65,15 @@ RUN wg genkey | tee /etc/wireguard/wg0_privatekey \ && echo "PrivateKey = $(cat /etc/wireguard/wg0_privatekey)" >> /etc/wireguard/wg0.conf \ && echo "PostUp = iptables -t nat -I POSTROUTING 1 -s ${wg_net}/24 -o $(ip -o -4 route show to default | awk '{print $NF}') -j MASQUERADE" >> /etc/wireguard/wg0.conf \ && echo "PostUp = iptables -I FORWARD -i wg0 -o wg0 -j DROP" >> /etc/wireguard/wg0.conf \ - && echo "PreDown = iptables -t nat -D POSTROUTING 1 -s ${wg_net}/24 -o $(ip -o -4 route show to default | awk '{print $NF}') -j MASQUERADE" >> /etc/wireguard/wg0.conf \ + && echo "PreDown = iptables -t nat -D POSTROUTING 1" >> /etc/wireguard/wg0.conf \ && echo "PreDown = iptables -D FORWARD -i wg0 -o wg0 -j DROP" >> /etc/wireguard/wg0.conf \ && echo "ListenPort = 51820" >> /etc/wireguard/wg0.conf \ #&& echo "DNS = ${global_dns}" >> /etc/wireguard/wg0.conf \ && rm /etc/wireguard/wg0_privatekey +# Defining a way for Docker to check the health of the container. +HEALTHCHECK --interval=30s --timeout=10s --start-period=5s --retries=3 CMD curl -f http://localhost:10086/signin || exit 1 + # Exposing the default WireGuard Dashboard port for web access. EXPOSE 10086 ENTRYPOINT ["/bin/bash", "/entrypoint.sh"] \ No newline at end of file diff --git a/docker/compose.yaml b/docker/compose.yaml index 5c2a1d9..abc9ffc 100644 --- a/docker/compose.yaml +++ b/docker/compose.yaml @@ -1,6 +1,6 @@ services: wireguard-dashboard: - image: repo.nerthus.nl/app/wireguard-dashboard:dev + image: repo.nerthus.nl/app/wireguard-dashboard:latest restart: unless-stopped container_name: wire-dash environment: diff --git a/docker/entrypoint.sh b/docker/entrypoint.sh index 4024b30..c0d51c3 100644 --- a/docker/entrypoint.sh +++ b/docker/entrypoint.sh @@ -77,13 +77,14 @@ set_envvars() { } ensure_blocking() { + sleep 1s echo "Ensuring container continuation." # This function checks if the latest error log is created and tails it for docker logs uses. if find "/opt/wireguardashboard/app/src/log" -mindepth 1 -maxdepth 1 -type f | read -r; then - latestlog=$(find /opt/wireguardashboard/app/src/log -name "error_*.log" | head -n 1) - sleep 3s - tail -f "${latestlog}" + latestErrLog=$(find /opt/wireguardashboard/app/src/log -name "error_*.log" | head -n 1) + latestAccLog=$(find /opt/wireguardashboard/app/src/log -name "access_*.log" | head -n 1) + tail -f "${latestErrLog}" "${latestAccLog}" fi # Blocking command in case of erroring. So the container does not quit. From bdeb4a4efeb56e7501ea5970d5e745b22b8b9dde Mon Sep 17 00:00:00 2001 From: Daan Date: Fri, 7 Jun 2024 14:55:16 +0200 Subject: [PATCH 09/14] Cleaned up lingering code line. --- docker/Dockerfile | 1 - 1 file changed, 1 deletion(-) diff --git a/docker/Dockerfile b/docker/Dockerfile index 70be161..702cc61 100644 --- a/docker/Dockerfile +++ b/docker/Dockerfile @@ -47,7 +47,6 @@ RUN python3 -m venv ${WGDASH}/venv # Doing WireGuard Dashboard installation measures. RUN . ${WGDASH}/venv/bin/activate \ && git clone -b ${dash_ver} https://github.com/donaldzou/WGDashboard.git ${WGDASH}/app \ - && sed -i '/Restart=always/a\StandardOutput=file:{{APP_ROOT}}/log/log1.log\nStandardError=file:{{APP_ROOT}}/log/log2.log' ${WGDASH}/app/src/wg-dashboard.service \ && pip3 install -r ${WGDASH}/app/src/requirements.txt \ && chmod +x ${WGDASH}/app/src/wgd.sh \ && .${WGDASH}/app/src/wgd.sh install From 8824786fb4511282629e8112f1e8caa06c861e2f Mon Sep 17 00:00:00 2001 From: Daan Date: Sat, 8 Jun 2024 13:30:24 +0200 Subject: [PATCH 10/14] For some reason, cloning the GitHub (which has been simplified) works from the Dockerfile directly. But the wg0.conf file needs a re-copy on run-time. Working now. Made code modifications and optimizations. Please report bugs to me. --- docker/Dockerfile | 33 ++++++++++++++--------------- docker/compose.yaml | 2 +- docker/entrypoint.sh | 50 ++++++++++++++++++++++++++------------------ 3 files changed, 47 insertions(+), 38 deletions(-) diff --git a/docker/Dockerfile b/docker/Dockerfile index 702cc61..19251f1 100644 --- a/docker/Dockerfile +++ b/docker/Dockerfile @@ -2,11 +2,7 @@ FROM debian:stable-slim LABEL maintainer="dselen@nerthus.nl" -# Copy the basic entrypoint.sh script. -COPY entrypoint.sh /entrypoint.sh - # Declaring environment variables, change Peernet to an address you like, standard is a 24 bit subnet. -ARG dash_ver="v3.0.6.2" ENV wg_net="10.0.0.1" # wg_net is used functionally as an ARG for its environment variable nature, do not change unless you know what you are doing. @@ -41,12 +37,12 @@ RUN apt-get update && apt-get upgrade -y \ # Removing the Linux Image package to preserve space on the image, for this reason also deleting apt lists, to be able to install packages: run apt update. # Using WGDASH -- like wg_net functionally as a ARG command. But it is needed in entrypoint.sh so it needs to be exported as environment variable. -ENV WGDASH=/opt/wireguardashboard +ENV WGDASH=/opt/wireguarddashboard RUN python3 -m venv ${WGDASH}/venv -# Doing WireGuard Dashboard installation measures. +# Doing WireGuard Dashboard installation measures. Modify the git clone command to get the preferred version, with a specific branch for example. RUN . ${WGDASH}/venv/bin/activate \ - && git clone -b ${dash_ver} https://github.com/donaldzou/WGDashboard.git ${WGDASH}/app \ + && git clone https://github.com/donaldzou/WGDashboard.git ${WGDASH}/app \ && pip3 install -r ${WGDASH}/app/src/requirements.txt \ && chmod +x ${WGDASH}/app/src/wgd.sh \ && .${WGDASH}/app/src/wgd.sh install @@ -58,21 +54,24 @@ VOLUME /etc/wireguard # Also setting the pipefail option, verbose: https://github.com/hadolint/hadolint/wiki/DL4006. SHELL ["/bin/bash", "-o", "pipefail", "-c"] RUN wg genkey | tee /etc/wireguard/wg0_privatekey \ - && echo "[Interface]" > /etc/wireguard/wg0.conf \ - && echo "SaveConfig = true" >> /etc/wireguard/wg0.conf \ - && echo "Address = ${wg_net}/24" >> /etc/wireguard/wg0.conf \ - && echo "PrivateKey = $(cat /etc/wireguard/wg0_privatekey)" >> /etc/wireguard/wg0.conf \ - && echo "PostUp = iptables -t nat -I POSTROUTING 1 -s ${wg_net}/24 -o $(ip -o -4 route show to default | awk '{print $NF}') -j MASQUERADE" >> /etc/wireguard/wg0.conf \ - && echo "PostUp = iptables -I FORWARD -i wg0 -o wg0 -j DROP" >> /etc/wireguard/wg0.conf \ - && echo "PreDown = iptables -t nat -D POSTROUTING 1" >> /etc/wireguard/wg0.conf \ - && echo "PreDown = iptables -D FORWARD -i wg0 -o wg0 -j DROP" >> /etc/wireguard/wg0.conf \ - && echo "ListenPort = 51820" >> /etc/wireguard/wg0.conf \ - #&& echo "DNS = ${global_dns}" >> /etc/wireguard/wg0.conf \ + && echo "[Interface]" > /wg0.conf \ + && echo "SaveConfig = true" >> /wg0.conf \ + && echo "Address = ${wg_net}/24" >> /wg0.conf \ + && echo "PrivateKey = $(cat /etc/wireguard/wg0_privatekey)" >> /wg0.conf \ + && echo "PostUp = iptables -t nat -I POSTROUTING 1 -s ${wg_net}/24 -o $(ip -o -4 route show to default | awk '{print $NF}') -j MASQUERADE" >> /wg0.conf \ + && echo "PostUp = iptables -I FORWARD -i wg0 -o wg0 -j DROP" >> /wg0.conf \ + && echo "PreDown = iptables -t nat -D POSTROUTING 1" >> /wg0.conf \ + && echo "PreDown = iptables -D FORWARD -i wg0 -o wg0 -j DROP" >> /wg0.conf \ + && echo "ListenPort = 51820" >> /wg0.conf \ + #&& echo "DNS = ${global_dns}" >> /wg0.conf \ && rm /etc/wireguard/wg0_privatekey # Defining a way for Docker to check the health of the container. HEALTHCHECK --interval=30s --timeout=10s --start-period=5s --retries=3 CMD curl -f http://localhost:10086/signin || exit 1 +# Copy the basic entrypoint.sh script. +COPY entrypoint.sh /entrypoint.sh + # Exposing the default WireGuard Dashboard port for web access. EXPOSE 10086 ENTRYPOINT ["/bin/bash", "/entrypoint.sh"] \ No newline at end of file diff --git a/docker/compose.yaml b/docker/compose.yaml index abc9ffc..9d7509f 100644 --- a/docker/compose.yaml +++ b/docker/compose.yaml @@ -14,7 +14,7 @@ services: - 51820:51820/udp volumes: - conf:/etc/wireguard - - app:/opt/wireguardashboard/app + - app:/opt/wireguarddashboard/app cap_add: - NET_ADMIN diff --git a/docker/entrypoint.sh b/docker/entrypoint.sh index c0d51c3..40cb3cb 100644 --- a/docker/entrypoint.sh +++ b/docker/entrypoint.sh @@ -2,17 +2,24 @@ echo "Starting the WireGuard Dashboard Docker container." clean_up() { + # Cleaning out previous data such as the .pid file and starting the WireGuard Dashboard. Making sure to use the python venv. echo "Looking for remains of previous instances..." - if [ -f "/opt/wireguardashboard/app/src/gunicorn.pid" ]; then + if [ -f "/opt/wireguarddashboard/app/src/gunicorn.pid" ]; then echo "Found old .pid file, removing." - rm /opt/wireguardashboard/app/src/gunicorn.pid + rm /opt/wireguarddashboard/app/src/gunicorn.pid else echo "No remains found, continuing." fi } start_core() { - # Cleaning out previous data such as the .pid file and starting the WireGuard Dashboard. Making sure to use the python venv. + if [ ! -f "/etc/wireguard/wg0.conf" ]; then + cp "/wg0.conf" "/etc/wireguard/wg0.conf" + echo "WireGuard interface file copied over." + else + echo "WireGuard interface file looks to already be existing." + fi + echo "Activating Python venv and executing the WireGuard Dashboard service." . "${WGDASH}"/venv/bin/activate @@ -20,22 +27,25 @@ start_core() { bash wgd.sh start # The following section takes care of the firewall rules regarding the 'isolated_peers' feature, which allows or drops packets destined from the wg0 to the wg0 interface. - if [ "${isolated_peers,,}" == "false" ]; then + if [ "${isolated_peers,,}" = "false" ]; then echo "Isolated peers disabled, adjusting." sed -i '/PostUp = iptables -I FORWARD -i wg0 -o wg0 -j DROP/d' /etc/wireguard/wg0.conf sed -i '/PreDown = iptables -D FORWARD -i wg0 -o wg0 -j DROP/d' /etc/wireguard/wg0.conf - elif [ "${isolated_peers,,}" == "true" ] && \ - [ "$(grep -c "PostUp = iptables -I FORWARD -i wg0 -o wg0 -j DROP" /etc/wireguard/wg0.conf)" -lt 1 ] && \ - [ "$(grep -c "PreDown = iptables -D FORWARD -i wg0 -o wg0 -j DROP" /etc/wireguard/wg0.conf)" -lt 1 ]; then - echo "Isolated peers enabled, adjusting." + elif [ "${isolated_peers,,}" = "true" ]; then + upblocking=$(grep -c "PostUp = iptables -I FORWARD -i wg0 -o wg0 -j DROP" /etc/wireguard/wg0.conf) + downblocking=$(grep -c "PreDown = iptables -D FORWARD -i wg0 -o wg0 -j DROP" /etc/wireguard/wg0.conf) + if [ "$upblocking" -lt 1 ] && [ "$downblocking" -lt 1 ]; then + echo "Isolated peers enabled, adjusting." + + sed -i '/PostUp = iptables -t nat -I POSTROUTING 1 -s/a PostUp = iptables -I FORWARD -i wg0 -o wg0 -j DROP' /etc/wireguard/wg0.conf + sed -i '/PreDown = iptables -t nat -D POSTROUTING 1 -s/a PreDown = iptables -D FORWARD -i wg0 -o wg0 -j DROP' /etc/wireguard/wg0.conf + fi - sed -i '/PostUp = iptables -t nat -I POSTROUTING 1 -s/a PostUp = iptables -I FORWARD -i wg0 -o wg0 -j DROP' /etc/wireguard/wg0.conf - sed -i '/PreDown = iptables -t nat -D POSTROUTING 1 -s/a PreDown = iptables -D FORWARD -i wg0 -o wg0 -j DROP' /etc/wireguard/wg0.conf fi # The following section takes care of - if [ "${enable_wg0,,}" == "true" ]; then + if [ "${enable_wg0,,}" = "true" ]; then echo "Preference for wg0 to be turned on found." wg-quick up wg0 @@ -56,23 +66,23 @@ set_envvars() { fi # Changing the DNS used for clients and the dashboard itself. - if [ "${global_dns}" != "$(grep "peer_global_dns = " /opt/wireguardashboard/app/src/wg-dashboard.ini | awk '{print $NF}')" ]; then + if [ "${global_dns}" != "$(grep "peer_global_dns = " /opt/wireguarddashboard/app/src/wg-dashboard.ini | awk '{print $NF}')" ]; then echo "Changing default dns." #sed -i "s/^DNS = .*/DNS = ${global_dns}/" /etc/wireguard/wg0.conf # Uncomment if you want to have DNS on server-level. - sed -i "s/^peer_global_dns = .*/peer_global_dns = ${global_dns}/" /opt/wireguardashboard/app/src/wg-dashboard.ini + sed -i "s/^peer_global_dns = .*/peer_global_dns = ${global_dns}/" /opt/wireguarddashboard/app/src/wg-dashboard.ini fi # Setting the public IP of the WireGuard Dashboard container host. If not defined, it will trying fetching it using a curl to ifconfig.me. - if [ "${public_ip}" == "0.0.0.0" ]; then + if [ "${public_ip}" = "0.0.0.0" ]; then default_ip=$(curl -s ifconfig.me) echo "Trying to fetch the Public-IP using ifconfig.me: ${default_ip}" - sed -i "s/^remote_endpoint = .*/remote_endpoint = ${default_ip}/" /opt/wireguardashboard/app/src/wg-dashboard.ini - elif [ "${public_ip}" != "$(grep "remote_endpoint = " /opt/wireguardashboard/app/src/wg-dashboard.ini | awk '{print $NF}')" ]; then + sed -i "s/^remote_endpoint = .*/remote_endpoint = ${default_ip}/" /opt/wireguarddashboard/app/src/wg-dashboard.ini + elif [ "${public_ip}" != "$(grep "remote_endpoint = " /opt/wireguarddashboard/app/src/wg-dashboard.ini | awk '{print $NF}')" ]; then echo "Setting the Public-IP using given variable: ${public_ip}" - sed -i "s/^remote_endpoint = .*/remote_endpoint = ${public_ip}/" /opt/wireguardashboard/app/src/wg-dashboard.ini + sed -i "s/^remote_endpoint = .*/remote_endpoint = ${public_ip}/" /opt/wireguarddashboard/app/src/wg-dashboard.ini fi } @@ -81,9 +91,9 @@ ensure_blocking() { echo "Ensuring container continuation." # This function checks if the latest error log is created and tails it for docker logs uses. - if find "/opt/wireguardashboard/app/src/log" -mindepth 1 -maxdepth 1 -type f | read -r; then - latestErrLog=$(find /opt/wireguardashboard/app/src/log -name "error_*.log" | head -n 1) - latestAccLog=$(find /opt/wireguardashboard/app/src/log -name "access_*.log" | head -n 1) + if find "/opt/wireguarddashboard/app/src/log" -mindepth 1 -maxdepth 1 -type f | read -r; then + latestErrLog=$(find /opt/wireguarddashboard/app/src/log -name "error_*.log" | head -n 1) + latestAccLog=$(find /opt/wireguarddashboard/app/src/log -name "access_*.log" | head -n 1) tail -f "${latestErrLog}" "${latestAccLog}" fi From 20530c000ee184e381e31f6bd59a93fb8842a72a Mon Sep 17 00:00:00 2001 From: Daan Date: Sun, 9 Jun 2024 23:11:22 +0200 Subject: [PATCH 11/14] Added container documentation, and added a few new comments. --- docker/Docker-explain.md | 82 ++++++++++++++++++++++++++++++++++++++++ docker/Dockerfile | 2 +- docker/entrypoint.sh | 1 + 3 files changed, 84 insertions(+), 1 deletion(-) create mode 100644 docker/Docker-explain.md diff --git a/docker/Docker-explain.md b/docker/Docker-explain.md new file mode 100644 index 0000000..5ff02d1 --- /dev/null +++ b/docker/Docker-explain.md @@ -0,0 +1,82 @@ +# WG-Dashboard Docker Explanation: + +Author: DaanSelen
+ +This document delves into how the WG-Dashboard Docker container has been built.
+Of course there are two stages, one before run-time and one at/after run-time.
+The `Dockerfile` describes how the container image is made, and the `entrypoint.sh` is executed after running the container.
+In this example, WireGuard is integrated into the container itself, so it should be a run-and-go.
+For more details on the source-code specific to this Docker image, refer to the source files, they have lots of comments. + +I have tried to embed some new features such as `isolated_peers` and interface startup on container-start (through `enable_wg0`). + +WG-Dashboard Logo + +## Getting the container running: + +To get the container running you either pull the image from the repository, at the moment: `repo.nerthus.nl/app/wireguard-dashboard:latest`.
+From there either use the environment variables describe below as parameters or use the Docker Compose file: `compose.yaml`. + +An example of a simple command to get the container running is show below:
+ +```shell +docker run -d \ + --name wireguard-dashboard \ + --restart unless-stopped \ + -e enable_wg0=true \ + -e isolated_peers=true \ + -p 10086:10086/tcp \ + -p 51820:51820/udp \ + --cap-add NET_ADMIN \ + repo.nerthus.nl/app/wireguard-dashboard:latest +``` +
+If you want to use Compose instead of a raw Docker command, refer to the example in the `compose.yaml` or the one pasted below: +

+ +```yaml +services: + wireguard-dashboard: + image: repo.nerthus.nl/app/wireguard-dashboard:latest + restart: unless-stopped + container_name: wire-dash + environment: + #- tz= + #- global_dns= + - enable_wg0=true + - isolated_peers=false + #- public_ip= + ports: + - 10086:10086/tcp + - 51820:51820/udp + volumes: + - conf:/etc/wireguard + - app:/opt/wireguarddashboard/app + cap_add: + - NET_ADMIN + +volumes: + conf: + app: + +``` + +If you want to customize the yaml, make sure the core stays the same, but for example volume PATHs can be freely changed.
+This setup is just generic and will use the Docker volumes. + +## Working with the container and environment variables: + +Once the container is running, the installation process is essentially the same as running it on bare-metal.
+So go to the assign TCP port in this case HTTP, like the default 10086 one in the example and log into the WEB-GUI.
+ +| Environment variable | Accepted arguments | Default value | Verbose | +| -------------- | ------- | ------- | ------- | +| tz | Europe/Amsterdam or any confirming timezone notation. | Europe/Amsterdam | Sets the timezone of the Docker container. This is to timesync the container to any other processes which would need it. | +| global_dns | Any IPv4 address, such as my personal recommendation: 9.9.9.9 (QUAD9) | 1.1.1.1 | Set the default DNS given to clients once they connect to the WireGuard tunnel (VPN). +| enable_wg0 | `true` or `false` | `false` | Enables or disables the starting of the WireGuard interface on container 'boot-up'. +| isolated_peers | `true` or `false` | `true` | For security the default is true, and it disables peers to ping or reach eachother, the WireGuard interface IS able to reach the peers (Done through `iptables`). +| public_ip | Any IPv4 (public recommended) address, such as the one returned by default | Default uses the return of `curl ifconfig.me` | To reach your VPN from outside your own network, you need WG-Dashboard to know what your public IP-address is, otherwise it will generate faulty config files for clients. + +## Closing remarks: + +For feedback please submit an issue to the repository. Or message dselen@nerthus.nl. \ No newline at end of file diff --git a/docker/Dockerfile b/docker/Dockerfile index 19251f1..fb373d2 100644 --- a/docker/Dockerfile +++ b/docker/Dockerfile @@ -66,7 +66,7 @@ RUN wg genkey | tee /etc/wireguard/wg0_privatekey \ #&& echo "DNS = ${global_dns}" >> /wg0.conf \ && rm /etc/wireguard/wg0_privatekey -# Defining a way for Docker to check the health of the container. +# Defining a way for Docker to check the health of the container. In this case: checking the login URL. HEALTHCHECK --interval=30s --timeout=10s --start-period=5s --retries=3 CMD curl -f http://localhost:10086/signin || exit 1 # Copy the basic entrypoint.sh script. diff --git a/docker/entrypoint.sh b/docker/entrypoint.sh index 40cb3cb..118e9ef 100644 --- a/docker/entrypoint.sh +++ b/docker/entrypoint.sh @@ -13,6 +13,7 @@ clean_up() { } start_core() { + # This first step is to ensure the wg0.conf file exists, and if not, then its copied over from the ephemeral container storage. if [ ! -f "/etc/wireguard/wg0.conf" ]; then cp "/wg0.conf" "/etc/wireguard/wg0.conf" echo "WireGuard interface file copied over." From 632cd66b57da08ebca80d7e7086de14ee5e28abb Mon Sep 17 00:00:00 2001 From: dselen <80752476+DaanSelen@users.noreply.github.com> Date: Sun, 9 Jun 2024 23:13:19 +0200 Subject: [PATCH 12/14] Update Docker-explain.md --- docker/Docker-explain.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docker/Docker-explain.md b/docker/Docker-explain.md index 5ff02d1..500a10d 100644 --- a/docker/Docker-explain.md +++ b/docker/Docker-explain.md @@ -10,7 +10,7 @@ For more details on the source-code specific to this Docker image, refer to the I have tried to embed some new features such as `isolated_peers` and interface startup on container-start (through `enable_wg0`). -WG-Dashboard Logo +WG-Dashboard Logo ## Getting the container running: @@ -79,4 +79,4 @@ So go to the assign TCP port in this case HTTP, like the default 10086 one in th ## Closing remarks: -For feedback please submit an issue to the repository. Or message dselen@nerthus.nl. \ No newline at end of file +For feedback please submit an issue to the repository. Or message dselen@nerthus.nl. From 72fe687d822052b434b79d4b2e7a4c67967a450c Mon Sep 17 00:00:00 2001 From: dselen <80752476+DaanSelen@users.noreply.github.com> Date: Sun, 9 Jun 2024 23:13:31 +0200 Subject: [PATCH 13/14] Update Docker-explain.md --- docker/Docker-explain.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docker/Docker-explain.md b/docker/Docker-explain.md index 500a10d..dd7bfe8 100644 --- a/docker/Docker-explain.md +++ b/docker/Docker-explain.md @@ -10,7 +10,7 @@ For more details on the source-code specific to this Docker image, refer to the I have tried to embed some new features such as `isolated_peers` and interface startup on container-start (through `enable_wg0`). -WG-Dashboard Logo +WG-Dashboard Logo ## Getting the container running: From 701b45c286eac1f33072af63e03c58266dbfa6d8 Mon Sep 17 00:00:00 2001 From: Daan Date: Mon, 10 Jun 2024 20:34:30 +0200 Subject: [PATCH 14/14] Improved (imo) the use of English. --- src/dashboard.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/dashboard.py b/src/dashboard.py index 4310104..30e012f 100644 --- a/src/dashboard.py +++ b/src/dashboard.py @@ -873,7 +873,7 @@ def update_pwd(): config.set("Account", "password", hashlib.sha256(request.form['repnewpass'].encode()).hexdigest()) try: set_dashboard_conf(config) - session['message'] = "Password update successfully!" + session['message'] = "Password updated successfully!" session['message_status'] = "success" config.clear() return redirect(url_for("settings")) @@ -888,7 +888,7 @@ def update_pwd(): config.clear() return redirect(url_for("settings")) else: - session['message'] = "Your Password does not match." + session['message'] = "Your Passwords do not match." session['message_status'] = "danger" config.clear() return redirect(url_for("settings"))