Skip to content

Instantly share code, notes, and snippets.

@freespace
Last active April 6, 2025 14:05
Show Gist options
  • Save freespace/7967697f5e26c7732040a39e87ce0fea to your computer and use it in GitHub Desktop.
Save freespace/7967697f5e26c7732040a39e87ce0fea to your computer and use it in GitHub Desktop.
Simple script to add a wireguard client and show the client config as a QR code for ease of client configuration.
#!/bin/bash
# Script to add a wireguard client. You need qrencode installed. By default clients are allowed to try to
# access the internet, though you will need to configure iptable rules and enable IP forwarding.
CONF_DIR="/etc/wireguard/clients"
SERVER_PUBLIC_KEY="/etc/wireguard/wg0.publickey"
SERVER_CONF="/etc/wireguard/wg0.conf"
SUBNET="192.168.90"
FIRST_CLIENT_IP="100"
# https://www.dns0.eu/
DNS_SERVERS="193.110.81.0, 185.253.5.0"
SERVER_ENDPOINT="<server-hostname-or-ip>:<port>"
DEVICE_NAME="$1"
function show_help {
printf "Usage: $0 <device name>\n"
printf "<device name> must only contain alpha-numeric characters and dash (-)\n"
exit 1
}
function check_ok_or_exit {
if [ $? -ne 0 ]; then
printf "$1\n"
exit 2;
fi
}
if [ -z "${DEVICE_NAME}" ]; then
show_help
fi
# device name must be alphanum and dash (-) only
# https://unix.stackexchange.com/a/340485/191141
if [[ ! "${DEVICE_NAME}" =~ ^([[:alnum:]]|-)+$ ]] || [[ "${DEVICE_NAME}" =~ ^[[:digit:]]+$ ]]; then
show_help
fi
NUM_CLIENTS="$(ls "${CONF_DIR}"/*.conf 2>/dev/null| wc -l)"
printf "Found ${NUM_CLIENTS} existing clients\n"
# note that b/c we start _from_ 100 we don't need to increment
NEW_IP="${SUBNET}.$(( ${FIRST_CLIENT_IP} + ${NUM_CLIENTS} ))"
# go into the client config dir and make sure we are creating files with
# appropriate permissions
pushd "${CONF_DIR}"
umask 077
DEVICE_CONF="${DEVICE_NAME}.conf"
DEVICE_PRIVATE_KEY="${DEVICE_NAME}.privatekey"
DEVICE_PUBLIC_KEY="${DEVICE_NAME}.publickey"
if [ -e "${DEVICE_CONF}" ]; then
printf "Refusing to run: ${DEVICE_CONF} already exists\n"
exit 2
fi
# generate keys
wg genkey > "${DEVICE_PRIVATE_KEY}"
check_ok_or_exit "Failed to generate private key"
wg pubkey < "${DEVICE_PRIVATE_KEY}" > "${DEVICE_PUBLIC_KEY}"
check_ok_or_exit "Failed to generate public key"
# generate config
cat << EOF > "${DEVICE_CONF}"
[Interface]
PrivateKey = $(cat "${DEVICE_PRIVATE_KEY}")
Address = ${NEW_IP}/24
DNS = ${DNS_SERVERS}
[Peer]
PublicKey = $(cat "${SERVER_PUBLIC_KEY}")
AllowedIPs = ${SUBNET}.0/24, 0.0.0.0/0
Endpoint = ${SERVER_ENDPOINT}
PersistentKeepalive = 25
EOF
# render config as QR code
qrencode -t ansiutf8 < "${DEVICE_CONF}"
# add the client to peers we know about
SERVER_CONF_BACKUP="${SERVER_CONF}.$(date +%s)"
cp "${SERVER_CONF}" "${SERVER_CONF_BACKUP}"
printf "${SERVER_CONF} backed up to ${SERVER_CONF_BACKUP}\n"
cat << EOF >> "${SERVER_CONF}"
[Peer]
# ${DEVICE_NAME}
AllowedIPs = ${NEW_IP}/32
PublicKey = $(cat "${DEVICE_PUBLIC_KEY}")
EOF
# restart the server
wg-quick down wg0
check_ok_or_exit "Failed to shutdown wireguard server"
wg-quick up wg0
check_ok_or_exit "Failed to start wireguard server"
# good bye
popd
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment