1
0
mirror of https://github.com/donaldzou/WGDashboard.git synced 2024-11-22 07:10:09 +01:00

Reoganise the documents and added experimental Alpine Linux support in wgd.sh

This commit is contained in:
Dselen 2024-08-23 07:46:41 -05:00
parent e3771a1c53
commit 518e29118c
7 changed files with 372 additions and 28 deletions

62
docker/alpine/Dockerfile Normal file
View File

@ -0,0 +1,62 @@
# Pull from small Debian stable image.
FROM alpine:latest AS build
LABEL maintainer="dselen@nerthus.nl"
# Declaring environment variables, change Peernet to an address you like, standard is a 24 bit subnet.
ARG Git_Url="https://github.com/donaldzou/WGDashboard.git"
ARG wg_net="10.0.0.1"
ARG wg_port="51820"
# 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="none"
ENV isolate="wg0"
ENV public_ip="0.0.0.0"
ENV update="yes"
# Doing package management operations, such as upgrading
RUN apk update \
&& apk add --no-cache bash git curl tzdata \
wireguard-tools sudo \
gcc py3-pip python3-dev musl-dev linux-headers
# 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/wireguarddashboard
# 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.
# Doing WireGuard Dashboard installation measures. Modify the git clone command to get the preferred version, with a specific branch for example.
RUN mkdir -p /setup/conf && mkdir /setup/app && mkdir ${WGDASH}
#&& git clone ${Git_Url} /setup/app
COPY src /setup/app/src
# Set the volume to be used for WireGuard configuration persistency.
VOLUME /etc/wireguard
VOLUME ${WGDASH}
# 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 echo "[Interface]" > /setup/conf/wg0.conf \
&& echo "Address = ${wg_net}/24" >> /setup/conf/wg0.conf \
&& echo "PrivateKey =" >> /setup/conf/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" >> /setup/conf/wg0.conf \
&& echo "PostUp = iptables -I FORWARD -i wg0 -o wg0 -j DROP" >> /setup/conf/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" >> /setup/conf/wg0.conf \
&& echo "PreDown = iptables -D FORWARD -i wg0 -o wg0 -j DROP" >> /setup/conf/wg0.conf \
&& echo "ListenPort = ${wg_port}" >> /setup/conf/wg0.conf \
&& echo "SaveConfig = true" >> /setup/conf/wg0.conf \
&& echo "DNS = ${global_dns}" >> /setup/conf/wg0.conf
# Defining a way for Docker to check the health of the container. In this case: checking the login URL.
HEALTHCHECK --interval=2m --timeout=1m --start-period=20s --retries=3 \
CMD [ "$(curl -s -o /dev/null -w '%{http_code}' http://localhost:10086/)" -eq "200" ] || 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"]

237
docker/alpine/entrypoint.sh Normal file
View File

@ -0,0 +1,237 @@
#!/bin/bash
echo "------------------------- START ----------------------------"
echo "Starting the WireGuard Dashboard Docker container."
ensure_installation() {
# When using a custom directory to store the files, this part moves over and makes sure the installation continues.
echo "Checking if everything is present."
if [ -z "$(ls -A "${WGDASH}")" ]; then
echo "Detected empty directory, moving over..."
mv /setup/app/* "${WGDASH}"
python3 -m venv "${WGDASH}"/src/venv
. "${WGDASH}/src/venv/bin/activate"
chmod +x "${WGDASH}"/src/wgd.sh
cd "${WGDASH}"/src || exit
./wgd.sh install
echo "Looks like the installation succesfully moved over."
else
echo "Looks like everything is present."
fi
# 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
echo "Standard wg0 Configuration file not found, grabbing template."
cp "/setup/conf/wg0.conf" "/etc/wireguard/wg0.conf"
echo "Setting a secure private key."
local privateKey
privateKey=$(wg genkey)
sed -i "s|^PrivateKey =$|PrivateKey = ${privateKey}|g" /etc/wireguard/wg0.conf
sed -i "s|^PrivateKey *=.*$|PrivateKey = ${privateKey}|g" /etc/wireguard/wg0.conf
echo "Done setting template."
else
echo "Existing wg0 configuration file found, using that."
fi
}
# === CLEAN UP ===
clean_up() {
printf "\n------------------------ CLEAN UP --------------------------\n"
# 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..."
local pid_file="${WGDASH}/src/gunicorn.pid"
if [ -f "$pid_file" ]; then
echo "Found old pid file, removing."
rm $pid_file
else
echo "No pid remains found, continuing."
fi
# Also check for Python caches (pycache) inspired by https://github.com/shuricksumy
local pycache="${WGDASH}/src/__pycache__"
if [ -d "$pycache" ]; then
local pycache_filecount=$(find "$pycache" -maxdepth 1 -type f | wc -l)
if [ "$pycache_filecount" -gt 0 ]; then
echo "Found old pycaches, removing."
rm -rf "$pycache"/*
else
echo "No pycaches found, continuing."
fi
else
echo "No pycaches found, continuing."
fi
local logdir="${WGDASH}/src/log"
echo "Cleaning log directory."
find /opt/wireguarddashboard/src/log -name 'access_*.log' -exec rm {} +
find /opt/wireguarddashboard/src/log -name 'error_*.log' -exec rm {} +
echo "Removed unneeded logs!"
}
#update_checker() {
#if [ "$update" = "yes" ]; then
# echo "Activating Python venv and executing the WireGuard Dashboard service."
# . "${WGDASH}/src/venv/bin/activate"
# cd "${WGDASH}"/src || exit
# bash wgd.sh update
#else
# echo "Auto Updater disabled"
#fi
#}
# === SET ENV VARS ===
set_envvars() {
printf "\n------------- SETTING ENVIRONMENT VARIABLES ----------------\n"
# If the timezone is different, for example in North-America or Asia.
if [ "${TZ}" != "$(cat /etc/localtime)" ]; then
echo "Changing timezone."
ln -sf /usr/share/zoneinfo/"${TZ}" /etc/localtime
echo "${TZ}" > /etc/timezone
else
echo "Timezone is set correctly."
fi
# Changing the DNS used for clients and the dashboard itself.
if [ "${global_dns}" != "$(grep "peer_global_dns = " /opt/wireguarddashboard/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/wireguarddashboard/src/wg-dashboard.ini
else
echo "DNS is set correctly."
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
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/wireguarddashboard/src/wg-dashboard.ini
elif [ "${public_ip}" != "$(grep "remote_endpoint = " /opt/wireguarddashboard/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/wireguarddashboard/src/wg-dashboard.ini
fi
}
# === CORE SERVICES ===
start_core() {
printf "\n---------------------- STARTING CORE -----------------------\n"
echo "Activating Python venv and executing the WireGuard Dashboard service."
. "${WGDASH}"/src/venv/bin/activate
cd "${WGDASH}"/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
# Isolated peers feature, first converting the existing configuration files and the given names to arrays.
local configurations=(/etc/wireguard/*)
IFS=',' read -r -a do_isolate <<< "${isolate}"
non_isolate=()
# Checking if there are matches between the two arrays.
for config in "${configurations[@]}"; do
local config=$(echo "$config" | sed -e 's|.*/etc/wireguard/||' -e 's|\.conf$||')
found=false
for interface in "${do_isolate[@]}"; do
if [[ "$config" == "$interface" ]]; then
found=true
break
fi
done
if [ "$found" = false ]; then
non_isolate+=("$config")
fi
done
# Isolating the matches.
for interface in "${do_isolate[@]}"; do
if [ "$interface" = "none" ]; then
echo "Found: $interface, stopping isolation checking."
break
else
if [ -f "/etc/wireguard/${interface}.conf" ]; then
echo "Isolating interface:" $interface
upblocking=$(grep -c "PostUp = iptables -I FORWARD -i ${interface} -o ${interface} -j DROP" /etc/wireguard/${interface}.conf)
downblocking=$(grep -c "PreDown = iptables -D FORWARD -i ${interface} -o ${interface} -j DROP" /etc/wireguard/${interface}.conf)
if [ "$upblocking" -lt 1 ] && [ "$downblocking" -lt 1 ]; then
sed -i "/PostUp =/a PostUp = iptables -I FORWARD -i ${interface} -o ${interface} -j DROP" /etc/wireguard/${interface}.conf
sed -i "/PreDown =/a PreDown = iptables -D FORWARD -i ${interface} -o ${interface} -j DROP" /etc/wireguard/${interface}.conf
fi
else
echo "Configuration for $interface does not seem to exist, continuing."
fi
fi
done
# Removing isolation for the configurations that did not match.
for interface in "${non_isolate[@]}"; do
if [ -f "/etc/wireguard/${interface}.conf" ]; then
echo "Removing Isolation if present for:" $interface
sed -i "/PostUp = iptables -I FORWARD -i ${interface} -o ${interface} -j DROP/d" /etc/wireguard/${interface}.conf
sed -i "/PreDown = iptables -D FORWARD -i ${interface} -o ${interface} -j DROP/d" /etc/wireguard/${interface}.conf
else
echo "Configuration for $interface does not seem to exist, continuing."
fi
done
# The following section takes care of enabling wireguard interfaces on startup. Using arrays and given arguments.
IFS=',' read -r -a enable_array <<< "${enable}"
for interface in "${enable_array[@]}"; do
if [ "$interface" = "none" ]; then
echo "Found: $interface, stopping enabling checking."
break
else
echo "Enabling interface:" $interface
local fileperms=$(stat -c "%a" /etc/wireguard/${interface}.conf)
if [ $fileperms -eq 644 ]; then
echo "Configuration is world accessible, adjusting."
chmod 600 "/etc/wireguard/${interface}.conf"
fi
if [ -f "/etc/wireguard/${interface}.conf" ]; then
wg-quick up $interface
else
echo "No corresponding configuration file found for $interface doing nothing."
fi
fi
done
}
# === CLEAN UP ===
ensure_blocking() {
printf "\n-------------- ENSURING CONTAINER CONTINUATION -------------\n"
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/wireguarddashboard/src/log" -mindepth 1 -maxdepth 1 -type f | read -r; then
latestErrLog=$(find /opt/wireguarddashboard/src/log -name "error_*.log" | head -n 1)
latestAccLog=$(find /opt/wireguarddashboard/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.
sleep infinity
}
# Execute functions for the WireGuard Dashboard services, then set the environment variables
ensure_installation
clean_up
#update_checker
start_core
set_envvars
ensure_blocking

View File

@ -8,7 +8,7 @@ ARG wg_net="10.0.0.1"
ARG wg_port="51820" ARG wg_port="51820"
# Following ENV variables are changable on container runtime because /entrypoint.sh handles that. See compose.yaml for more info. # Following ENV variables are changable on container runtime because /entrypoint.sh handles that. See compose.yaml for more info.
ENV tz="Europe/Amsterdam" ENV TZ="Europe/Amsterdam"
ENV global_dns="1.1.1.1" ENV global_dns="1.1.1.1"
ENV enable="none" ENV enable="none"
ENV isolate="wg0" ENV isolate="wg0"
@ -16,17 +16,15 @@ ENV public_ip="0.0.0.0"
ENV update="yes" ENV update="yes"
# Doing basic system maintenance. Change the timezone to the desired timezone. # Doing basic system maintenance. Change the timezone to the desired timezone.
RUN ln -sf /usr/share/zoneinfo/${tz} /etc/localtime RUN ln -sf /usr/share/zoneinfo/${TZ} /etc/localtime
# 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. # 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/wireguarddashboard ENV WGDASH=/opt/wireguarddashboard
# Doing package management operations, such as upgrading # Doing package management operations, such as upgrading
RUN apt-get update && apt-get install -y --no-install-recommends \ RUN apt-get update && apt-get install -y --no-install-recommends \
curl git iproute2 \ curl git \
iptables iputils-ping \ iptables python3 \
openresolv procps traceroute \
python3 python3-pip python3-venv \
wireguard wireguard-tools \ wireguard wireguard-tools \
sudo && \ sudo && \
apt-get remove -y linux-image-* && \ apt-get remove -y linux-image-* && \

View File

@ -0,0 +1,23 @@
services:
wireguard-dashboard:
image: dselen/wgdashboard:dev
restart: unless-stopped
container_name: wgdashboard
environment:
#- tz= # <--- Set container timezone, default: Europe/Amsterdam.
#- global_dns= # <--- Set global DNS address, default: 1.1.1.1.
- enable=wg0 # <--- Set the interfaces that will be enabled on startup, default: none. The option "off" is also allowed.
- isolate=wg0 # <--- 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:
- 10086:10086/tcp
- 51820:51820/udp
volumes:
- app:/opt/wireguarddashboard
- conf:/etc/wireguard
cap_add:
- NET_ADMIN
volumes:
app:
conf:

View File

@ -7,14 +7,14 @@ ensure_installation() {
# When using a custom directory to store the files, this part moves over and makes sure the installation continues. # When using a custom directory to store the files, this part moves over and makes sure the installation continues.
echo "Checking if everything is present." echo "Checking if everything is present."
if [ -z "$(ls -A ${WGDASH})" ]; then if [ -z "$(ls -A "${WGDASH}")" ]; then
echo "Detected empty directory, moving over..." echo "Detected empty directory, moving over..."
mv /setup/app/* ${WGDASH} mv /setup/app/* "${WGDASH}"
python3 -m venv ${WGDASH}/src/venv python3 -m venv "${WGDASH}"/src/venv
. "${WGDASH}/src/venv/bin/activate" . "${WGDASH}/src/venv/bin/activate"
chmod +x ${WGDASH}/src/wgd.sh chmod +x "${WGDASH}"/src/wgd.sh
cd ${WGDASH}/src cd "${WGDASH}"/src || exit
./wgd.sh install ./wgd.sh install
echo "Looks like the installation succesfully moved over." echo "Looks like the installation succesfully moved over."
@ -28,7 +28,10 @@ ensure_installation() {
cp "/setup/conf/wg0.conf" "/etc/wireguard/wg0.conf" cp "/setup/conf/wg0.conf" "/etc/wireguard/wg0.conf"
echo "Setting a secure private key." echo "Setting a secure private key."
local privateKey=$(wg genkey)
local privateKey
privateKey=$(wg genkey)
sed -i "s|^PrivateKey =$|PrivateKey = ${privateKey}|g" /etc/wireguard/wg0.conf sed -i "s|^PrivateKey =$|PrivateKey = ${privateKey}|g" /etc/wireguard/wg0.conf
sed -i "s|^PrivateKey *=.*$|PrivateKey = ${privateKey}|g" /etc/wireguard/wg0.conf sed -i "s|^PrivateKey *=.*$|PrivateKey = ${privateKey}|g" /etc/wireguard/wg0.conf
echo "Done setting template." echo "Done setting template."
@ -44,7 +47,7 @@ clean_up() {
# Cleaning out previous data such as the .pid file and starting the WireGuard Dashboard. Making sure to use the python venv. # 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..." echo "Looking for remains of previous instances..."
local pid_file="${WGDASH}/src/gunicorn.pid" local pid_file="${WGDASH}/src/gunicorn.pid"
if [ -f $pid_file ]; then if [ -f "$pid_file" ]; then
echo "Found old pid file, removing." echo "Found old pid file, removing."
rm $pid_file rm $pid_file
else else
@ -88,7 +91,7 @@ set_envvars() {
printf "\n------------- SETTING ENVIRONMENT VARIABLES ----------------\n" printf "\n------------- SETTING ENVIRONMENT VARIABLES ----------------\n"
# If the timezone is different, for example in North-America or Asia. # If the timezone is different, for example in North-America or Asia.
if [ "${tz}" != "$(cat /etc/timezone)" ]; then if [ "${tz}" != "$(cat /etc/localtime)" ]; then
echo "Changing timezone." echo "Changing timezone."
ln -sf /usr/share/zoneinfo/"${tz}" /etc/localtime ln -sf /usr/share/zoneinfo/"${tz}" /etc/localtime

View File

@ -65,10 +65,12 @@ _determineOS(){
OS=$ID OS=$ID
elif [ -f /etc/redhat-release ]; then elif [ -f /etc/redhat-release ]; then
OS="redhat" OS="redhat"
elif [ -f /etc/alpine-release ]; then
OS="alpine"
# elif [ -f /etc/arch-release ]; then # elif [ -f /etc/arch-release ]; then
# OS="arch" # OS="arch"
else else
printf "[WGDashboard] %s Sorry, your OS is not supported. Currently the install script only support Debian-based, Red Hat-based OS." "$heavy_crossmark" printf "[WGDashboard] %s Sorry, your OS is not supported. Currently the install script only support Debian-based, Red Hat-based OS. With experimental support for Alpine Linux.\n" "$heavy_crossmark"
printf "%s\n" "$helpMsg" printf "%s\n" "$helpMsg"
kill $TOP_PID kill $TOP_PID
fi fi
@ -87,6 +89,9 @@ _installPython(){
{ sudo yum install -y python3 net-tools ; printf "\n\n"; } >> ./log/install.txt { sudo yum install -y python3 net-tools ; printf "\n\n"; } >> ./log/install.txt
fi fi
;; ;;
alpine)
{ sudo apk update; sudo apk add python3 net-tools; printf "\n\n"; } >> ./log/install.txt
;;
esac esac
if ! python3 --version > /dev/null 2>&1 if ! python3 --version > /dev/null 2>&1
@ -112,8 +117,11 @@ _installPythonVenv(){
{ sudo yum install -y python3-virtualenv; printf "\n\n"; } >> ./log/install.txt { sudo yum install -y python3-virtualenv; printf "\n\n"; } >> ./log/install.txt
fi fi
;; ;;
alpine)
{ sudo apk update; sudo apk add py3-virtualenv ; printf "\n\n"; } >> ./log/install.txt
;;
*) *)
printf "[WGDashboard] %s Sorry, your OS is not supported. Currently the install script only support Debian-based, Red Hat-based OS.\n" "$heavy_crossmark" printf "[WGDashboard] %s Sorry, your OS is not supported. Currently the install script only support Debian-based, Red Hat-based OS. With experimental support for Alpine Linux.\n" "$heavy_crossmark"
printf "%s\n" "$helpMsg" printf "%s\n" "$helpMsg"
kill $TOP_PID kill $TOP_PID
;; ;;
@ -166,8 +174,11 @@ _installPythonPip(){
{ sudo dnf install -y ${pythonExecutable}-pip; printf "\n\n"; } >> ./log/install.txt { sudo dnf install -y ${pythonExecutable}-pip; printf "\n\n"; } >> ./log/install.txt
fi fi
;; ;;
alpine)
{ sudo apk update; sudo apk add py3-pip ; printf "\n\n"; } >> ./log/install.txt
;;
*) *)
printf "[WGDashboard] %s Sorry, your OS is not supported. Currently the install script only support Debian-based, Red Hat-based OS.\n" "$heavy_crossmark" printf "[WGDashboard] %s Sorry, your OS is not supported. Currently the install script only support Debian-based, Red Hat-based OS. With experimental support for Alpine Linux.\n" "$heavy_crossmark"
printf "%s\n" "$helpMsg" printf "%s\n" "$helpMsg"
kill $TOP_PID kill $TOP_PID
;; ;;
@ -185,15 +196,28 @@ _installPythonPip(){
} }
_checkWireguard(){ _checkWireguard(){
if ! wg -h > /dev/null 2>&1 if [ ! wg -h > /dev/null 2>&1 ] || [ ! wg-quick -h > /dev/null 2>&1 ]
then then
printf "[WGDashboard] %s WireGuard is not installed. Please follow instruction on https://www.wireguard.com/install/ to install. \n" "$heavy_crossmark" case "$OS" in
kill $TOP_PID ubuntu|debian)
fi { sudo apt update ; sudo apt-get install -y wireguard; printf "\n\n"; } &>> ./log/install.txt
if ! wg-quick -h > /dev/null 2>&1 ;;
then #centos|fedora|redhat|rhel)
printf "[WGDashboard] %s WireGuard is not installed. Please follow instruction on https://www.wireguard.com/install/ to install. \n" "$heavy_crossmark" # if [ "$pythonExecutable" = "python3" ]; then
kill $TOP_PID # { sudo dnf install -y python3-pip; printf "\n\n"; } >> ./log/install.txt
# else
# { sudo dnf install -y ${pythonExecutable}-pip; printf "\n\n"; } >> ./log/install.txt
# fi
#;;
alpine)
{ sudo apk update; sudo apk add wireguard-tools ; printf "\n\n"; } >> ./log/install.txt
;;
*)
printf "[WGDashboard] %s Sorry, your OS is not supported. Currently the install script only support Debian-based, Red Hat-based OS. With experimental support for Alpine Linux.\n" "$heavy_crossmark"
printf "%s\n" "$helpMsg"
kill $TOP_PID
;;
esac
fi fi
} }
@ -247,9 +271,6 @@ install_wgd(){
_installPythonVenv _installPythonVenv
_installPythonPip _installPythonPip
if [ ! -d "db" ] if [ ! -d "db" ]
then then
printf "[WGDashboard] Creating ./db folder\n" printf "[WGDashboard] Creating ./db folder\n"