[
  {
    "path": ".github/FUNDING.yml",
    "content": "ko_fi: stanislas\ncustom: https://coindrop.to/stanislas\n"
  },
  {
    "path": ".github/dependabot.yml",
    "content": "version: 2\nupdates:\n  - package-ecosystem: \"github-actions\"\n    directory: \"/\"\n    schedule:\n      interval: \"weekly\"\n"
  },
  {
    "path": ".github/issue_template.md",
    "content": "<!---\n❗️ Please read ❗️\n➡️ If you need help with WireGuard itself, please use the community forums (https://www.reddit.com/r/WireGuard/) or Stack Overflow (https://stackoverflow.com/questions/tagged/wireguard)\n➡️ For the script, prefer opening a discussion thread for help: https://github.com/angristan/wireguard-install/discussions\n💡 It helps keep the issue tracker clean and focused on bugs and feature requests.\n\n🙏 Please include as much information as possible, and make sure you're running the latest version of the script.\n✍️ Please state the Linux distribution you're using and its version, as well as the WireGuard version.\n✋ For feature requests, remember that this script is meant to be simple and easy to use. If you want to add a lot of options, it's better to fork the project.\n--->\n"
  },
  {
    "path": ".github/pull_request_template.md",
    "content": "<!---\n❗️ Please read ❗️\n➡️ Please make sure you've followed the guidelines: https://github.com/angristan/wireguard-install#contributing\n✅ Please make sure your changes are tested and working\n🗣️ Please avoid large PRs, and discuss changes in a GitHub issue first\n✋ If the changes are too big and not in line with the project, they will probably be rejected. Remember that this script is meant to be simple and easy to use.\n--->\n"
  },
  {
    "path": ".github/workflows/lint.yml",
    "content": "on: [push, pull_request, pull_request_target]\n\nname: Lint\n\njobs:\n  shellcheck:\n    runs-on: ubuntu-latest\n    steps:\n      - uses: actions/checkout@v4\n      - name: shellcheck\n        uses: ludeeus/action-shellcheck@1.1.0\n        env:\n          SHELLCHECK_OPTS: -e SC1091,SC1117,SC2001,SC2034\n\n  shfmt:\n    runs-on: ubuntu-latest\n    steps:\n      - uses: actions/checkout@v4\n      - uses: mfinelli/setup-shfmt@v3\n      - run: shfmt -d wireguard-install.sh\n"
  },
  {
    "path": "LICENSE",
    "content": "MIT License\n\nCopyright (c) 2019 angristan\n\nPermission is hereby granted, free of charge, to any person obtaining a copy of\nthis software and associated documentation files (the \"Software\"), to deal in\nthe Software without restriction, including without limitation the rights to\nuse, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of\nthe Software, and to permit persons to whom the Software is furnished to do so,\nsubject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS\nFOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR\nCOPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER\nIN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN\nCONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n"
  },
  {
    "path": "README.md",
    "content": "# WireGuard installer\n\n![Lint](https://github.com/angristan/wireguard-install/workflows/Lint/badge.svg)\n[![Say Thanks!](https://img.shields.io/badge/Say%20Thanks-!-1EAEDB.svg)](https://saythanks.io/to/angristan)\n\n**This project is a bash script that aims to setup a [WireGuard](https://www.wireguard.com/) VPN on a Linux server, as easily as possible!**\n\nWireGuard is a point-to-point VPN that can be used in different ways. Here, we mean a VPN as in: the client will forward all its traffic through an encrypted tunnel to the server.\nThe server will apply NAT to the client's traffic so it will appear as if the client is browsing the web with the server's IP.\n\nThe script supports both IPv4 and IPv6. Please check the [issues](https://github.com/angristan/wireguard-install/issues) for ongoing development, bugs and planned features! You might also want to check the [discussions](https://github.com/angristan/wireguard-install/discussions) for help.\n\nWireGuard does not fit your environment? Check out [openvpn-install](https://github.com/angristan/openvpn-install).\n\n## Requirements\n\nSupported distributions:\n\n- AlmaLinux >= 8\n- Alpine Linux\n- Arch Linux\n- CentOS Stream >= 8\n- Debian >= 10\n- Fedora >= 32\n- Oracle Linux\n- Rocky Linux >= 8\n- Ubuntu >= 18.04\n\n## Usage\n\nDownload and execute the script. Answer the questions asked by the script and it will take care of the rest.\n\n```bash\ncurl -O https://raw.githubusercontent.com/angristan/wireguard-install/master/wireguard-install.sh\nchmod +x wireguard-install.sh\n./wireguard-install.sh\n```\n\nIt will install WireGuard (kernel module and tools) on the server, configure it, create a systemd service and a client configuration file.\n\nRun the script again to add or remove clients!\n\n## Providers\n\nI recommend these cheap cloud providers for your VPN server:\n\n- [Vultr](https://www.vultr.com/?ref=8948982-8H): Worldwide locations, IPv6 support, starting at \\$5/month\n- [Hetzner](https://hetzner.cloud/?ref=ywtlvZsjgeDq): Germany, Finland and USA. IPv6, 20 TB of traffic, starting at 4.5€/month\n- [Digital Ocean](https://m.do.co/c/ed0ba143fe53): Worldwide locations, IPv6 support, starting at \\$4/month\n\n## Contributing\n\nContributions are welcome! Here's how you can help:\n\n### Discuss changes\n\nPlease open an issue before submitting a PR if you want to discuss a change, especially if it's a big one.\n\n### Code formatting\n\nWe use [shellcheck](https://github.com/koalaman/shellcheck) and [shfmt](https://github.com/mvdan/sh) to enforce bash styling guidelines and good practices. They are executed for each commit / PR with GitHub Actions, so you can check the configuration [here](https://github.com/angristan/wireguard-install/blob/master/.github/workflows/lint.yml).\n\n## Say thanks\n\nYou can [say thanks](https://saythanks.io/to/angristan) if you want!\n\n## Credits & Licence\n\nThis project is under the [MIT Licence](https://raw.githubusercontent.com/angristan/wireguard-install/master/LICENSE)\n\n## Star History\n\n[![Star History Chart](https://api.star-history.com/svg?repos=angristan/wireguard-install&type=Date)](https://star-history.com/#angristan/wireguard-install&Date)\n"
  },
  {
    "path": "wireguard-install.sh",
    "content": "#!/bin/bash\n\n# Secure WireGuard server installer\n# https://github.com/angristan/wireguard-install\n\nRED='\\033[0;31m'\nORANGE='\\033[0;33m'\nGREEN='\\033[0;32m'\nNC='\\033[0m'\n\nfunction installPackages() {\n\tif ! \"$@\"; then\n\t\techo -e \"${RED}Failed to install packages.${NC}\"\n\t\techo \"Please check your internet connection and package sources.\"\n\t\texit 1\n\tfi\n}\n\nfunction isRoot() {\n\tif [ \"${EUID}\" -ne 0 ]; then\n\t\techo \"You need to run this script as root\"\n\t\texit 1\n\tfi\n}\n\nfunction checkVirt() {\n\tif command -v virt-what &>/dev/null; then\n\t\tVIRT=$(virt-what)\n\telse\n\t\tVIRT=$(systemd-detect-virt)\n\tfi\n\tif [[ ${VIRT} == \"openvz\" ]]; then\n\t\techo \"OpenVZ is not supported\"\n\t\texit 1\n\tfi\n\tif [[ ${VIRT} == \"lxc\" ]]; then\n\t\techo \"LXC is not supported (yet).\"\n\t\techo \"WireGuard can technically run in an LXC container,\"\n\t\techo \"but the kernel module has to be installed on the host,\"\n\t\techo \"the container has to be run with some specific parameters\"\n\t\techo \"and only the tools need to be installed in the container.\"\n\t\texit 1\n\tfi\n}\n\nfunction checkOS() {\n\tsource /etc/os-release\n\tOS=\"${ID}\"\n\tif [[ ${OS} == \"debian\" || ${OS} == \"raspbian\" ]]; then\n\t\tif [[ ${VERSION_ID} -lt 10 ]]; then\n\t\t\techo \"Your version of Debian (${VERSION_ID}) is not supported. Please use Debian 10 Buster or later\"\n\t\t\texit 1\n\t\tfi\n\t\tOS=debian # overwrite if raspbian\n\telif [[ ${OS} == \"ubuntu\" ]]; then\n\t\tRELEASE_YEAR=$(echo \"${VERSION_ID}\" | cut -d'.' -f1)\n\t\tif [[ ${RELEASE_YEAR} -lt 18 ]]; then\n\t\t\techo \"Your version of Ubuntu (${VERSION_ID}) is not supported. Please use Ubuntu 18.04 or later\"\n\t\t\texit 1\n\t\tfi\n\telif [[ ${OS} == \"fedora\" ]]; then\n\t\tif [[ ${VERSION_ID} -lt 32 ]]; then\n\t\t\techo \"Your version of Fedora (${VERSION_ID}) is not supported. Please use Fedora 32 or later\"\n\t\t\texit 1\n\t\tfi\n\telif [[ ${OS} == 'centos' ]] || [[ ${OS} == 'almalinux' ]] || [[ ${OS} == 'rocky' ]]; then\n\t\tif [[ ${VERSION_ID} == 7* ]]; then\n\t\t\techo \"Your version of CentOS (${VERSION_ID}) is not supported. Please use CentOS 8 or later\"\n\t\t\texit 1\n\t\tfi\n\telif [[ -e /etc/oracle-release ]]; then\n\t\tsource /etc/os-release\n\t\tOS=oracle\n\telif [[ -e /etc/arch-release ]]; then\n\t\tOS=arch\n\telif [[ -e /etc/alpine-release ]]; then\n\t\tOS=alpine\n\t\tif ! command -v virt-what &>/dev/null; then\n\t\t\tif ! (apk update && apk add virt-what); then\n\t\t\t\techo -e \"${RED}Failed to install virt-what. Continuing without virtualization check.${NC}\"\n\t\t\tfi\n\t\tfi\n\telse\n\t\techo \"Looks like you aren't running this installer on a Debian, Ubuntu, Fedora, CentOS, AlmaLinux, Oracle or Arch Linux system\"\n\t\texit 1\n\tfi\n}\n\nfunction getHomeDirForClient() {\n\tlocal CLIENT_NAME=$1\n\n\tif [ -z \"${CLIENT_NAME}\" ]; then\n\t\techo \"Error: getHomeDirForClient() requires a client name as argument\"\n\t\texit 1\n\tfi\n\n\t# Home directory of the user, where the client configuration will be written\n\tif [ -e \"/home/${CLIENT_NAME}\" ]; then\n\t\t# if $1 is a user name\n\t\tHOME_DIR=\"/home/${CLIENT_NAME}\"\n\telif [ \"${SUDO_USER}\" ]; then\n\t\t# if not, use SUDO_USER\n\t\tif [ \"${SUDO_USER}\" == \"root\" ]; then\n\t\t\t# If running sudo as root\n\t\t\tHOME_DIR=\"/root\"\n\t\telse\n\t\t\tHOME_DIR=\"/home/${SUDO_USER}\"\n\t\tfi\n\telse\n\t\t# if not SUDO_USER, use /root\n\t\tHOME_DIR=\"/root\"\n\tfi\n\n\techo \"$HOME_DIR\"\n}\n\nfunction initialCheck() {\n\tisRoot\n\tcheckOS\n\tcheckVirt\n}\n\nfunction installQuestions() {\n\techo \"Welcome to the WireGuard installer!\"\n\techo \"The git repository is available at: https://github.com/angristan/wireguard-install\"\n\techo \"\"\n\techo \"I need to ask you a few questions before starting the setup.\"\n\techo \"You can keep the default options and just press enter if you are ok with them.\"\n\techo \"\"\n\n\t# Detect public IPv4 or IPv6 address and pre-fill for the user\n\tSERVER_PUB_IP=$(ip -4 addr | sed -ne 's|^.* inet \\([^/]*\\)/.* scope global.*$|\\1|p' | awk '{print $1}' | head -1)\n\tif [[ -z ${SERVER_PUB_IP} ]]; then\n\t\t# Detect public IPv6 address\n\t\tSERVER_PUB_IP=$(ip -6 addr | sed -ne 's|^.* inet6 \\([^/]*\\)/.* scope global.*$|\\1|p' | head -1)\n\tfi\n\tread -rp \"IPv4 or IPv6 public address: \" -e -i \"${SERVER_PUB_IP}\" SERVER_PUB_IP\n\n\t# Detect public interface and pre-fill for the user\n\tSERVER_NIC=\"$(ip -4 route ls | grep default | awk '/dev/ {for (i=1; i<=NF; i++) if ($i == \"dev\") print $(i+1)}' | head -1)\"\n\tuntil [[ ${SERVER_PUB_NIC} =~ ^[a-zA-Z0-9_]+$ ]]; do\n\t\tread -rp \"Public interface: \" -e -i \"${SERVER_NIC}\" SERVER_PUB_NIC\n\tdone\n\n\tuntil [[ ${SERVER_WG_NIC} =~ ^[a-zA-Z0-9_]+$ && ${#SERVER_WG_NIC} -lt 16 ]]; do\n\t\tread -rp \"WireGuard interface name: \" -e -i wg0 SERVER_WG_NIC\n\tdone\n\n\tuntil [[ ${SERVER_WG_IPV4} =~ ^([0-9]{1,3}\\.){3} ]]; do\n\t\tread -rp \"Server WireGuard IPv4: \" -e -i 10.66.66.1 SERVER_WG_IPV4\n\tdone\n\n\tuntil [[ ${SERVER_WG_IPV6} =~ ^([a-f0-9]{1,4}:){3,4}: ]]; do\n\t\tread -rp \"Server WireGuard IPv6: \" -e -i fd42:42:42::1 SERVER_WG_IPV6\n\tdone\n\n\t# Generate random number within private ports range\n\tRANDOM_PORT=$(shuf -i49152-65535 -n1)\n\tuntil [[ ${SERVER_PORT} =~ ^[0-9]+$ ]] && [ \"${SERVER_PORT}\" -ge 1 ] && [ \"${SERVER_PORT}\" -le 65535 ]; do\n\t\tread -rp \"Server WireGuard port [1-65535]: \" -e -i \"${RANDOM_PORT}\" SERVER_PORT\n\tdone\n\n\t# Cloudflare DNS by default\n\tuntil [[ ${CLIENT_DNS_1} =~ ^((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.){3}(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$ ]]; do\n\t\tread -rp \"First DNS resolver to use for the clients: \" -e -i 1.1.1.1 CLIENT_DNS_1\n\tdone\n\tuntil [[ ${CLIENT_DNS_2} =~ ^((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.){3}(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$ ]]; do\n\t\tread -rp \"Second DNS resolver to use for the clients (optional): \" -e -i 1.0.0.1 CLIENT_DNS_2\n\t\tif [[ ${CLIENT_DNS_2} == \"\" ]]; then\n\t\t\tCLIENT_DNS_2=\"${CLIENT_DNS_1}\"\n\t\tfi\n\tdone\n\n\tuntil [[ ${ALLOWED_IPS} =~ ^.+$ ]]; do\n\t\techo -e \"\\nWireGuard uses a parameter called AllowedIPs to determine what is routed over the VPN.\"\n\t\tread -rp \"Allowed IPs list for generated clients (leave default to route everything): \" -e -i '0.0.0.0/0,::/0' ALLOWED_IPS\n\t\tif [[ ${ALLOWED_IPS} == \"\" ]]; then\n\t\t\tALLOWED_IPS=\"0.0.0.0/0,::/0\"\n\t\tfi\n\tdone\n\n\techo \"\"\n\techo \"Okay, that was all I needed. We are ready to setup your WireGuard server now.\"\n\techo \"You will be able to generate a client at the end of the installation.\"\n\tread -n1 -r -p \"Press any key to continue...\"\n}\n\nfunction installWireGuard() {\n\t# Run setup questions first\n\tinstallQuestions\n\n\t# Install WireGuard tools and module\n\tif [[ ${OS} == 'ubuntu' ]] || [[ ${OS} == 'debian' && ${VERSION_ID} -gt 10 ]]; then\n\t\tapt-get update\n\t\tinstallPackages apt-get install -y wireguard iptables resolvconf qrencode\n\telif [[ ${OS} == 'debian' ]]; then\n\t\tif ! grep -rqs \"^deb .* buster-backports\" /etc/apt/; then\n\t\t\techo \"deb http://deb.debian.org/debian buster-backports main\" >/etc/apt/sources.list.d/backports.list\n\t\t\tapt-get update\n\t\tfi\n\t\tapt-get update\n\t\tinstallPackages apt-get install -y iptables resolvconf qrencode\n\t\tinstallPackages apt-get install -y -t buster-backports wireguard\n\telif [[ ${OS} == 'fedora' ]]; then\n\t\tif [[ ${VERSION_ID} -lt 32 ]]; then\n\t\t\tinstallPackages dnf install -y dnf-plugins-core\n\t\t\tdnf copr enable -y jdoss/wireguard\n\t\t\tinstallPackages dnf install -y wireguard-dkms\n\t\tfi\n\t\tinstallPackages dnf install -y wireguard-tools iptables qrencode\n\telif [[ ${OS} == 'centos' ]] || [[ ${OS} == 'almalinux' ]] || [[ ${OS} == 'rocky' ]]; then\n\t\tif [[ ${VERSION_ID} == 8* ]]; then\n\t\t\tinstallPackages yum install -y epel-release elrepo-release\n\t\t\tinstallPackages yum install -y kmod-wireguard\n\t\t\tyum install -y qrencode || true # not available on release 9\n\t\tfi\n\t\tinstallPackages yum install -y wireguard-tools iptables\n\telif [[ ${OS} == 'oracle' ]]; then\n\t\tinstallPackages dnf install -y oraclelinux-developer-release-el8\n\t\tdnf config-manager --disable -y ol8_developer\n\t\tdnf config-manager --enable -y ol8_developer_UEKR6\n\t\tdnf config-manager --save -y --setopt=ol8_developer_UEKR6.includepkgs='wireguard-tools*'\n\t\tinstallPackages dnf install -y wireguard-tools qrencode iptables\n\telif [[ ${OS} == 'arch' ]]; then\n\t\tinstallPackages pacman -S --needed --noconfirm wireguard-tools qrencode\n\telif [[ ${OS} == 'alpine' ]]; then\n\t\tapk update\n\t\tinstallPackages apk add wireguard-tools iptables libqrencode-tools\n\tfi\n\n\t# Verify WireGuard installation\n\tif ! command -v wg &>/dev/null; then\n\t\techo -e \"${RED}WireGuard installation failed. The 'wg' command was not found.${NC}\"\n\t\techo \"Please check the installation output above for errors.\"\n\t\texit 1\n\tfi\n\n\t# Make sure the directory exists (this does not seem the be the case on fedora)\n\tmkdir /etc/wireguard >/dev/null 2>&1\n\n\tchmod 600 -R /etc/wireguard/\n\n\tSERVER_PRIV_KEY=$(wg genkey)\n\tSERVER_PUB_KEY=$(echo \"${SERVER_PRIV_KEY}\" | wg pubkey)\n\n\t# Save WireGuard settings\n\techo \"SERVER_PUB_IP=${SERVER_PUB_IP}\nSERVER_PUB_NIC=${SERVER_PUB_NIC}\nSERVER_WG_NIC=${SERVER_WG_NIC}\nSERVER_WG_IPV4=${SERVER_WG_IPV4}\nSERVER_WG_IPV6=${SERVER_WG_IPV6}\nSERVER_PORT=${SERVER_PORT}\nSERVER_PRIV_KEY=${SERVER_PRIV_KEY}\nSERVER_PUB_KEY=${SERVER_PUB_KEY}\nCLIENT_DNS_1=${CLIENT_DNS_1}\nCLIENT_DNS_2=${CLIENT_DNS_2}\nALLOWED_IPS=${ALLOWED_IPS}\" >/etc/wireguard/params\n\n\t# Add server interface\n\techo \"[Interface]\nAddress = ${SERVER_WG_IPV4}/24,${SERVER_WG_IPV6}/64\nListenPort = ${SERVER_PORT}\nPrivateKey = ${SERVER_PRIV_KEY}\" >\"/etc/wireguard/${SERVER_WG_NIC}.conf\"\n\n\tif pgrep firewalld; then\n\t\tFIREWALLD_IPV4_ADDRESS=$(echo \"${SERVER_WG_IPV4}\" | cut -d\".\" -f1-3)\".0\"\n\t\tFIREWALLD_IPV6_ADDRESS=$(echo \"${SERVER_WG_IPV6}\" | sed 's/:[^:]*$/:0/')\n\t\techo \"PostUp = firewall-cmd --zone=public --add-interface=${SERVER_WG_NIC} && firewall-cmd --add-port ${SERVER_PORT}/udp && firewall-cmd --add-rich-rule='rule family=ipv4 source address=${FIREWALLD_IPV4_ADDRESS}/24 masquerade' && firewall-cmd --add-rich-rule='rule family=ipv6 source address=${FIREWALLD_IPV6_ADDRESS}/24 masquerade'\nPostDown = firewall-cmd --zone=public --add-interface=${SERVER_WG_NIC} && firewall-cmd --remove-port ${SERVER_PORT}/udp && firewall-cmd --remove-rich-rule='rule family=ipv4 source address=${FIREWALLD_IPV4_ADDRESS}/24 masquerade' && firewall-cmd --remove-rich-rule='rule family=ipv6 source address=${FIREWALLD_IPV6_ADDRESS}/24 masquerade'\" >>\"/etc/wireguard/${SERVER_WG_NIC}.conf\"\n\telse\n\t\techo \"PostUp = iptables -I INPUT -p udp --dport ${SERVER_PORT} -j ACCEPT\nPostUp = iptables -I FORWARD -i ${SERVER_PUB_NIC} -o ${SERVER_WG_NIC} -j ACCEPT\nPostUp = iptables -I FORWARD -i ${SERVER_WG_NIC} -j ACCEPT\nPostUp = iptables -t nat -A POSTROUTING -o ${SERVER_PUB_NIC} -j MASQUERADE\nPostUp = ip6tables -I FORWARD -i ${SERVER_WG_NIC} -j ACCEPT\nPostUp = ip6tables -t nat -A POSTROUTING -o ${SERVER_PUB_NIC} -j MASQUERADE\nPostDown = iptables -D INPUT -p udp --dport ${SERVER_PORT} -j ACCEPT\nPostDown = iptables -D FORWARD -i ${SERVER_PUB_NIC} -o ${SERVER_WG_NIC} -j ACCEPT\nPostDown = iptables -D FORWARD -i ${SERVER_WG_NIC} -j ACCEPT\nPostDown = iptables -t nat -D POSTROUTING -o ${SERVER_PUB_NIC} -j MASQUERADE\nPostDown = ip6tables -D FORWARD -i ${SERVER_WG_NIC} -j ACCEPT\nPostDown = ip6tables -t nat -D POSTROUTING -o ${SERVER_PUB_NIC} -j MASQUERADE\" >>\"/etc/wireguard/${SERVER_WG_NIC}.conf\"\n\tfi\n\n\t# Enable routing on the server\n\techo \"net.ipv4.ip_forward = 1\nnet.ipv6.conf.all.forwarding = 1\" >/etc/sysctl.d/wg.conf\n\n\tif [[ ${OS} == 'fedora' ]]; then\n\t\tchmod -v 700 /etc/wireguard\n\t\tchmod -v 600 /etc/wireguard/*\n\tfi\n\n\tif [[ ${OS} == 'alpine' ]]; then\n\t\tsysctl -p /etc/sysctl.d/wg.conf\n\t\trc-update add sysctl\n\t\tln -s /etc/init.d/wg-quick \"/etc/init.d/wg-quick.${SERVER_WG_NIC}\"\n\t\trc-service \"wg-quick.${SERVER_WG_NIC}\" start\n\t\trc-update add \"wg-quick.${SERVER_WG_NIC}\"\n\telse\n\t\tsysctl --system\n\n\t\tsystemctl start \"wg-quick@${SERVER_WG_NIC}\"\n\t\tsystemctl enable \"wg-quick@${SERVER_WG_NIC}\"\n\tfi\n\n\tnewClient\n\techo -e \"${GREEN}If you want to add more clients, you simply need to run this script another time!${NC}\"\n\n\t# Check if WireGuard is running\n\tif [[ ${OS} == 'alpine' ]]; then\n\t\trc-service --quiet \"wg-quick.${SERVER_WG_NIC}\" status\n\telse\n\t\tsystemctl is-active --quiet \"wg-quick@${SERVER_WG_NIC}\"\n\tfi\n\tWG_RUNNING=$?\n\n\t# WireGuard might not work if we updated the kernel. Tell the user to reboot\n\tif [[ ${WG_RUNNING} -ne 0 ]]; then\n\t\techo -e \"\\n${RED}WARNING: WireGuard does not seem to be running.${NC}\"\n\t\tif [[ ${OS} == 'alpine' ]]; then\n\t\t\techo -e \"${ORANGE}You can check if WireGuard is running with: rc-service wg-quick.${SERVER_WG_NIC} status${NC}\"\n\t\telse\n\t\t\techo -e \"${ORANGE}You can check if WireGuard is running with: systemctl status wg-quick@${SERVER_WG_NIC}${NC}\"\n\t\tfi\n\t\techo -e \"${ORANGE}If you get something like \\\"Cannot find device ${SERVER_WG_NIC}\\\", please reboot!${NC}\"\n\telse # WireGuard is running\n\t\techo -e \"\\n${GREEN}WireGuard is running.${NC}\"\n\t\tif [[ ${OS} == 'alpine' ]]; then\n\t\t\techo -e \"${GREEN}You can check the status of WireGuard with: rc-service wg-quick.${SERVER_WG_NIC} status\\n\\n${NC}\"\n\t\telse\n\t\t\techo -e \"${GREEN}You can check the status of WireGuard with: systemctl status wg-quick@${SERVER_WG_NIC}\\n\\n${NC}\"\n\t\tfi\n\t\techo -e \"${ORANGE}If you don't have internet connectivity from your client, try to reboot the server.${NC}\"\n\tfi\n}\n\nfunction newClient() {\n\t# If SERVER_PUB_IP is IPv6, add brackets if missing\n\tif [[ ${SERVER_PUB_IP} =~ .*:.* ]]; then\n\t\tif [[ ${SERVER_PUB_IP} != *\"[\"* ]] || [[ ${SERVER_PUB_IP} != *\"]\"* ]]; then\n\t\t\tSERVER_PUB_IP=\"[${SERVER_PUB_IP}]\"\n\t\tfi\n\tfi\n\tENDPOINT=\"${SERVER_PUB_IP}:${SERVER_PORT}\"\n\n\techo \"\"\n\techo \"Client configuration\"\n\techo \"\"\n\techo \"The client name must consist of alphanumeric character(s). It may also include underscores or dashes and can't exceed 15 chars.\"\n\n\tuntil [[ ${CLIENT_NAME} =~ ^[a-zA-Z0-9_-]+$ && ${CLIENT_EXISTS} == '0' && ${#CLIENT_NAME} -lt 16 ]]; do\n\t\tread -rp \"Client name: \" -e CLIENT_NAME\n\t\tCLIENT_EXISTS=$(grep -c -E \"^### Client ${CLIENT_NAME}\\$\" \"/etc/wireguard/${SERVER_WG_NIC}.conf\")\n\n\t\tif [[ ${CLIENT_EXISTS} != 0 ]]; then\n\t\t\techo \"\"\n\t\t\techo -e \"${ORANGE}A client with the specified name was already created, please choose another name.${NC}\"\n\t\t\techo \"\"\n\t\tfi\n\tdone\n\n\tfor DOT_IP in {2..254}; do\n\t\tDOT_EXISTS=$(grep -c \"${SERVER_WG_IPV4::-1}${DOT_IP}\" \"/etc/wireguard/${SERVER_WG_NIC}.conf\")\n\t\tif [[ ${DOT_EXISTS} == '0' ]]; then\n\t\t\tbreak\n\t\tfi\n\tdone\n\n\tif [[ ${DOT_EXISTS} == '1' ]]; then\n\t\techo \"\"\n\t\techo \"The subnet configured supports only 253 clients.\"\n\t\texit 1\n\tfi\n\n\tBASE_IP=$(echo \"$SERVER_WG_IPV4\" | awk -F '.' '{ print $1\".\"$2\".\"$3 }')\n\tuntil [[ ${IPV4_EXISTS} == '0' ]]; do\n\t\tread -rp \"Client WireGuard IPv4: ${BASE_IP}.\" -e -i \"${DOT_IP}\" DOT_IP\n\t\tCLIENT_WG_IPV4=\"${BASE_IP}.${DOT_IP}\"\n\t\tIPV4_EXISTS=$(grep -c \"$CLIENT_WG_IPV4/32\" \"/etc/wireguard/${SERVER_WG_NIC}.conf\")\n\n\t\tif [[ ${IPV4_EXISTS} != 0 ]]; then\n\t\t\techo \"\"\n\t\t\techo -e \"${ORANGE}A client with the specified IPv4 was already created, please choose another IPv4.${NC}\"\n\t\t\techo \"\"\n\t\tfi\n\tdone\n\n\tBASE_IP=$(echo \"$SERVER_WG_IPV6\" | awk -F '::' '{ print $1 }')\n\tuntil [[ ${IPV6_EXISTS} == '0' ]]; do\n\t\tread -rp \"Client WireGuard IPv6: ${BASE_IP}::\" -e -i \"${DOT_IP}\" DOT_IP\n\t\tCLIENT_WG_IPV6=\"${BASE_IP}::${DOT_IP}\"\n\t\tIPV6_EXISTS=$(grep -c \"${CLIENT_WG_IPV6}/128\" \"/etc/wireguard/${SERVER_WG_NIC}.conf\")\n\n\t\tif [[ ${IPV6_EXISTS} != 0 ]]; then\n\t\t\techo \"\"\n\t\t\techo -e \"${ORANGE}A client with the specified IPv6 was already created, please choose another IPv6.${NC}\"\n\t\t\techo \"\"\n\t\tfi\n\tdone\n\n\t# Generate key pair for the client\n\tCLIENT_PRIV_KEY=$(wg genkey)\n\tCLIENT_PUB_KEY=$(echo \"${CLIENT_PRIV_KEY}\" | wg pubkey)\n\tCLIENT_PRE_SHARED_KEY=$(wg genpsk)\n\n\tHOME_DIR=$(getHomeDirForClient \"${CLIENT_NAME}\")\n\n\t# Create client file and add the server as a peer\n\techo \"[Interface]\nPrivateKey = ${CLIENT_PRIV_KEY}\nAddress = ${CLIENT_WG_IPV4}/32,${CLIENT_WG_IPV6}/128\nDNS = ${CLIENT_DNS_1},${CLIENT_DNS_2}\n\n# Uncomment the next line to set a custom MTU\n# This might impact performance, so use it only if you know what you are doing\n# See https://github.com/nitred/nr-wg-mtu-finder to find your optimal MTU\n# MTU = 1420\n\n[Peer]\nPublicKey = ${SERVER_PUB_KEY}\nPresharedKey = ${CLIENT_PRE_SHARED_KEY}\nEndpoint = ${ENDPOINT}\nAllowedIPs = ${ALLOWED_IPS}\" >\"${HOME_DIR}/${SERVER_WG_NIC}-client-${CLIENT_NAME}.conf\"\n\n\t# Add the client as a peer to the server\n\techo -e \"\\n### Client ${CLIENT_NAME}\n[Peer]\nPublicKey = ${CLIENT_PUB_KEY}\nPresharedKey = ${CLIENT_PRE_SHARED_KEY}\nAllowedIPs = ${CLIENT_WG_IPV4}/32,${CLIENT_WG_IPV6}/128\" >>\"/etc/wireguard/${SERVER_WG_NIC}.conf\"\n\n\twg syncconf \"${SERVER_WG_NIC}\" <(wg-quick strip \"${SERVER_WG_NIC}\")\n\n\t# Generate QR code if qrencode is installed\n\tif command -v qrencode &>/dev/null; then\n\t\techo -e \"${GREEN}\\nHere is your client config file as a QR Code:\\n${NC}\"\n\t\tqrencode -t ansiutf8 -l L <\"${HOME_DIR}/${SERVER_WG_NIC}-client-${CLIENT_NAME}.conf\"\n\t\techo \"\"\n\tfi\n\n\techo -e \"${GREEN}Your client config file is in ${HOME_DIR}/${SERVER_WG_NIC}-client-${CLIENT_NAME}.conf${NC}\"\n}\n\nfunction listClients() {\n\tNUMBER_OF_CLIENTS=$(grep -c -E \"^### Client\" \"/etc/wireguard/${SERVER_WG_NIC}.conf\")\n\tif [[ ${NUMBER_OF_CLIENTS} -eq 0 ]]; then\n\t\techo \"\"\n\t\techo \"You have no existing clients!\"\n\t\texit 1\n\tfi\n\n\tgrep -E \"^### Client\" \"/etc/wireguard/${SERVER_WG_NIC}.conf\" | cut -d ' ' -f 3 | nl -s ') '\n}\n\nfunction revokeClient() {\n\tNUMBER_OF_CLIENTS=$(grep -c -E \"^### Client\" \"/etc/wireguard/${SERVER_WG_NIC}.conf\")\n\tif [[ ${NUMBER_OF_CLIENTS} == '0' ]]; then\n\t\techo \"\"\n\t\techo \"You have no existing clients!\"\n\t\texit 1\n\tfi\n\n\techo \"\"\n\techo \"Select the existing client you want to revoke\"\n\tgrep -E \"^### Client\" \"/etc/wireguard/${SERVER_WG_NIC}.conf\" | cut -d ' ' -f 3 | nl -s ') '\n\tuntil [[ ${CLIENT_NUMBER} -ge 1 && ${CLIENT_NUMBER} -le ${NUMBER_OF_CLIENTS} ]]; do\n\t\tif [[ ${CLIENT_NUMBER} == '1' ]]; then\n\t\t\tread -rp \"Select one client [1]: \" CLIENT_NUMBER\n\t\telse\n\t\t\tread -rp \"Select one client [1-${NUMBER_OF_CLIENTS}]: \" CLIENT_NUMBER\n\t\tfi\n\tdone\n\n\t# match the selected number to a client name\n\tCLIENT_NAME=$(grep -E \"^### Client\" \"/etc/wireguard/${SERVER_WG_NIC}.conf\" | cut -d ' ' -f 3 | sed -n \"${CLIENT_NUMBER}\"p)\n\n\t# remove [Peer] block matching $CLIENT_NAME\n\tsed -i \"/^### Client ${CLIENT_NAME}\\$/,/^$/d\" \"/etc/wireguard/${SERVER_WG_NIC}.conf\"\n\n\t# remove generated client file\n\tHOME_DIR=$(getHomeDirForClient \"${CLIENT_NAME}\")\n\trm -f \"${HOME_DIR}/${SERVER_WG_NIC}-client-${CLIENT_NAME}.conf\"\n\n\t# restart wireguard to apply changes\n\twg syncconf \"${SERVER_WG_NIC}\" <(wg-quick strip \"${SERVER_WG_NIC}\")\n}\n\nfunction uninstallWg() {\n\techo \"\"\n\techo -e \"\\n${RED}WARNING: This will uninstall WireGuard and remove all the configuration files!${NC}\"\n\techo -e \"${ORANGE}Please backup the /etc/wireguard directory if you want to keep your configuration files.\\n${NC}\"\n\tread -rp \"Do you really want to remove WireGuard? [y/n]: \" -e REMOVE\n\tREMOVE=${REMOVE:-n}\n\tif [[ $REMOVE == 'y' ]]; then\n\t\tcheckOS\n\n\t\tif [[ ${OS} == 'alpine' ]]; then\n\t\t\trc-service \"wg-quick.${SERVER_WG_NIC}\" stop\n\t\t\trc-update del \"wg-quick.${SERVER_WG_NIC}\"\n\t\t\tunlink \"/etc/init.d/wg-quick.${SERVER_WG_NIC}\"\n\t\t\trc-update del sysctl\n\t\telse\n\t\t\tsystemctl stop \"wg-quick@${SERVER_WG_NIC}\"\n\t\t\tsystemctl disable \"wg-quick@${SERVER_WG_NIC}\"\n\t\tfi\n\n\t\tif [[ ${OS} == 'ubuntu' ]] || [[ ${OS} == 'debian' ]]; then\n\t\t\tapt-get remove -y wireguard wireguard-tools qrencode\n\t\telif [[ ${OS} == 'fedora' ]]; then\n\t\t\tdnf remove -y --noautoremove wireguard-tools qrencode\n\t\t\tif [[ ${VERSION_ID} -lt 32 ]]; then\n\t\t\t\tdnf remove -y --noautoremove wireguard-dkms\n\t\t\t\tdnf copr disable -y jdoss/wireguard\n\t\t\tfi\n\t\telif [[ ${OS} == 'centos' ]] || [[ ${OS} == 'almalinux' ]] || [[ ${OS} == 'rocky' ]]; then\n\t\t\tyum remove -y --noautoremove wireguard-tools\n\t\t\tif [[ ${VERSION_ID} == 8* ]]; then\n\t\t\t\tyum remove --noautoremove kmod-wireguard qrencode\n\t\t\tfi\n\t\telif [[ ${OS} == 'oracle' ]]; then\n\t\t\tyum remove --noautoremove wireguard-tools qrencode\n\t\telif [[ ${OS} == 'arch' ]]; then\n\t\t\tpacman -Rs --noconfirm wireguard-tools qrencode\n\t\telif [[ ${OS} == 'alpine' ]]; then\n\t\t\t(cd qrencode-4.1.1 || exit && make uninstall)\n\t\t\trm -rf qrencode-* || exit\n\t\t\tapk del wireguard-tools libqrencode libqrencode-tools\n\t\tfi\n\n\t\trm -rf /etc/wireguard\n\t\trm -f /etc/sysctl.d/wg.conf\n\n\t\tif [[ ${OS} == 'alpine' ]]; then\n\t\t\trc-service --quiet \"wg-quick.${SERVER_WG_NIC}\" status &>/dev/null\n\t\telse\n\t\t\t# Reload sysctl\n\t\t\tsysctl --system\n\n\t\t\t# Check if WireGuard is running\n\t\t\tsystemctl is-active --quiet \"wg-quick@${SERVER_WG_NIC}\"\n\t\tfi\n\t\tWG_RUNNING=$?\n\n\t\tif [[ ${WG_RUNNING} -eq 0 ]]; then\n\t\t\techo \"WireGuard failed to uninstall properly.\"\n\t\t\texit 1\n\t\telse\n\t\t\techo \"WireGuard uninstalled successfully.\"\n\t\t\texit 0\n\t\tfi\n\telse\n\t\techo \"\"\n\t\techo \"Removal aborted!\"\n\tfi\n}\n\nfunction manageMenu() {\n\techo \"Welcome to WireGuard-install!\"\n\techo \"The git repository is available at: https://github.com/angristan/wireguard-install\"\n\techo \"\"\n\techo \"It looks like WireGuard is already installed.\"\n\techo \"\"\n\techo \"What do you want to do?\"\n\techo \"   1) Add a new user\"\n\techo \"   2) List all users\"\n\techo \"   3) Revoke existing user\"\n\techo \"   4) Uninstall WireGuard\"\n\techo \"   5) Exit\"\n\tuntil [[ ${MENU_OPTION} =~ ^[1-5]$ ]]; do\n\t\tread -rp \"Select an option [1-5]: \" MENU_OPTION\n\tdone\n\tcase \"${MENU_OPTION}\" in\n\t1)\n\t\tnewClient\n\t\t;;\n\t2)\n\t\tlistClients\n\t\t;;\n\t3)\n\t\trevokeClient\n\t\t;;\n\t4)\n\t\tuninstallWg\n\t\t;;\n\t5)\n\t\texit 0\n\t\t;;\n\tesac\n}\n\n# Check for root, virt, OS...\ninitialCheck\n\n# Check if WireGuard is already installed and load params\nif [[ -e /etc/wireguard/params ]]; then\n\tsource /etc/wireguard/params\n\tmanageMenu\nelse\n\tinstallWireGuard\nfi\n"
  }
]