{"id":2158,"date":"2020-06-19T10:17:36","date_gmt":"2020-06-19T07:17:36","guid":{"rendered":"https:\/\/upcloud.com\/global\/us\/resources\/tutorials\/get-started-wireguard-vpn\/"},"modified":"2026-04-23T14:11:56","modified_gmt":"2026-04-23T13:11:56","slug":"get-started-wireguard-vpn","status":"publish","type":"tutorial","link":"https:\/\/upcloud.com\/global\/resources\/tutorials\/get-started-wireguard-vpn\/","title":{"rendered":"How to get started with WireGuard VPN"},"content":{"rendered":"\n<p class=\"wp-block-paragraph\">WireGuard is a fast and modern VPN that utilizes state-of-the-art cryptography. It\u2019s much faster than OpenVPN or IPsec and has a smaller codebase that is easier to audit and maintain.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">This tutorial will set up WireGuard on the Ubuntu 24.04 server and configure a firewall. WireGuard was originally launched as a DKMS kernel module but was later incorporated into the 5.6 kernel and newer.<\/p>\n\n\n\n\n\n<h2 class=\"wp-block-heading\">Sign up with UpCloud<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">First things first, if you have not yet registered on UpCloud, <a href=\"https:\/\/signup.upcloud.com\/\" target=\"_blank\" rel=\"noreferrer noopener\">begin by getting signed up.<\/a><\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Deploy a new cloud server<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Deploying a new server on UpCloud is easy and straightforward. Log into your UpCloud Control Panel and select <a href=\"https:\/\/hub.upcloud.com\/deploy\/\" target=\"_blank\" rel=\"noopener\"><b>Deploy a Server<\/b><\/a>&nbsp;under the Servers section.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">The deployment page shows a number of options for customizing a new cloud server.<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li>Choose the server location from the available data centres<\/li>\n\n\n\n<li>Pick a configuration; the \u20ac3\/mo Starter plan works great for testing<\/li>\n\n\n\n<li>Select Ubuntu 24.04 or a similar Debian-based operating system<\/li>\n\n\n\n<li>Add any SSH keys you want to use<\/li>\n\n\n\n<li>Give your server a hostname and description<\/li>\n\n\n\n<li>Deploy!<\/li>\n<\/ol>\n\n\n\n<p class=\"wp-block-paragraph\">You can find more detailed instructions on server deployment at the <a href=\"https:\/\/upcloud.com\/global\/docs\/guides\/deploy-server\/\" target=\"_blank\" rel=\"noreferrer noopener\"><b>UpCloud newcomer\u2019s tutorials<\/b><\/a>.<\/p>\n\n\n\n<div class=\"wp-block-buttons is-layout-flex wp-block-buttons-is-layout-flex\">\n<div class=\"wp-block-button\"><a class=\"wp-block-button__link wp-element-button\" href=\"https:\/\/signup.upcloud.com\/\">Try UpCloud for free!<\/a><\/div>\n<\/div>\n\n\n\n<h2 class=\"wp-block-heading\">Installing WireGuard<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">When your new cloud server is up and running, <a href=\"https:\/\/upcloud.com\/global\/docs\/guides\/connecting-to-your-server\/\" target=\"_blank\" rel=\"noreferrer noopener\">log in using SSH<\/a>.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">WireGuard is available directly from the official repositories on Ubuntu 24.04. However, before installing WireGuard, ensure your system is up to date.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code class=\"\">sudo apt-get update &amp;&amp; sudo apt-get upgrade -y<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Now, we can install WireGuard itself and all of its dependencies.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code class=\"\">sudo apt-get install wireguard<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Repeat the installation steps on each client you wish to connect to the WireGuard server.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">WireGuard has software for most operating systems, so you can easily connect your Windows, Linux, or macOS devices and Android or iOS devices. The available packages are on <a href=\"https:\/\/www.wireguard.com\/install\/\" target=\"_blank\" rel=\"noopener\">their download page<\/a>.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">With WireGuard installed, continue configuring your server further using the steps below.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">IP forwarding<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Next, to connect through your WireGuard server, you\u2019ll need to enable packet forwarding. This is only done on the WireGuard server and is not necessary for any clients.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Open the system variables file for editing.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code class=\"\">sudo nano \/etc\/sysctl.conf<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Then, uncomment the following line by removing the <strong>#<\/strong> at the beginning of the line.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code class=\"\">net.ipv4.ip_forward=1<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Once done, save the file and exit the editor.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Then, apply the new option using the command below.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code class=\"\">sudo sysctl -p<\/code><\/pre>\n\n\n\n<pre class=\"wp-block-code\"><code class=\"\">net.ipv4.ip_forward=1<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">If you see the option repeated like above when reloading the system variables, it was enabled successfully.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Configuring firewall rules<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">You should also configure a firewall to block unwanted connections and keep your server secure. You can do this by installing a software firewall on your cloud server or using the Firewall service at your UpCloud Control Panel.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Using the command below, you can install the ufw, the Uncomplicated Firewall for Ubuntu servers.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code class=\"\">sudo apt install ufw<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Next, add the following rules to allow SSH and WireGuard connections.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code class=\"\">sudo ufw allow ssh\nsudo ufw allow 51820\/udp<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Enable the firewall with the next command.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code class=\"\">sudo ufw enable<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Then, confirm the command when prompted.<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">Command may disrupt existing ssh connections. Proceed with operation (y|n)? y<\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Afterwards, you can check the active firewall rules using the command below.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code class=\"\">sudo ufw status<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">The other option is to use UpCloud\u2019s L3 firewall, which can secure your WireGuard server. To add firewall rules, open your <a href=\"https:\/\/hub.upcloud.com\" target=\"_blank\" rel=\"noopener\">UpCloud Control Panel<\/a> and navigate to the Firewall tab in your server settings.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">The easiest way to configure the firewall is to import a set of premade rules that work for our intended use case. To do so, click <em>Import premade profile<\/em> from the <em>Import rules<\/em> menu.<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img decoding=\"async\" src=\"https:\/\/upcloud.com\/media\/wireguard-firewall-import-premade-profile.png\" alt=\"Wireguard firewall import premade profile\" class=\"wp-image-15494\" \/><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">Then select the <em>Only SSH allowed<\/em> rule set and click the <em>Import rules<\/em> button.<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img decoding=\"async\" src=\"https:\/\/upcloud.com\/media\/wireguard-ssh-only-premade-firewall-rules.png\" alt=\"Wireguard SSH only premade firewall rules\" class=\"wp-image-15493\" \/><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">We also need to allow WireGuard connections, which use the UDP protocol and can be configured to any port. We\u2019ll be using port 51820, so add the following incoming traffic rule.<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img decoding=\"async\" src=\"https:\/\/upcloud.com\/media\/wireguard-add-firewall-rule.png\" alt=\"Wireguard add firewall rule\" class=\"wp-image-15495\" \/><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">Once the rules have been added successfully<span style=\"margin: 0px;padding: 0px\">, check that the default rule is set to&nbsp;<em>drop,<\/em>&nbsp;then click&nbsp;<em>Save Changes<\/em><\/span> and <em>Enable firewall<\/em> to confirm.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Generating private and public keys<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">WireGuard works by encrypting the connection using a pair of cryptographic keys. The key pair is used by sharing the public key with the other party, who then can encrypt their message so that it can only be decrypted with the corresponding private key. To make communication secure both ways, each party must have private and public keys, as each pair only enables one-way messaging.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">For the use in WireGuard, the server and each client must generate their key pair and then exchange public keys.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">To start generating the keys for the server, change into the WireGuard directory.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code class=\"\">cd \/etc\/wireguard<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Next, set the permissions for the directory with the following command. You need to log in with the <em>root<\/em> account to do this.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code class=\"\">umask 077<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Then, with the required permissions set, generate a new key pair using the command below.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code class=\"\">wg genkey | tee privatekey | wg pubkey &gt; publickey<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Repeat these steps on each client you want to connect to the WireGuard server.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Remember that you should never share your private key with anyone.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Generate server config<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">We are then set to start configuring the WireGuard server. The config files are generally stored in the <tt>\/etc\/wireguard<\/tt> folder. Create a new configuration file called <tt>wg0.conf<\/tt> in that folder.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code class=\"\">sudo nano \/etc\/wireguard\/wg0.conf<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">The configuration below will make your WireGuard server accept connections to 51820 and allow a client with the public key corresponding to the private key we made above.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Add the following directives to the configuration file.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code class=\"\">[Interface]\nPrivateKey = <span style=\"color: #ff0000\">&lt;contents-of-server-privatekey&gt;<\/span>\nAddress = 10.0.0.1\/24\nPostUp = iptables -A FORWARD -i wg0 -j ACCEPT; iptables -t nat -A POSTROUTING -o <span style=\"color: #ff0000\">eth0<\/span> -j MASQUERADE\nPostDown = iptables -D FORWARD -i wg0 -j ACCEPT; iptables -t nat -D POSTROUTING -o <span style=\"color: #ff0000\">eth0<\/span> -j MASQUERADE\nListenPort = 51820\n\n[Peer]\nPublicKey = <span style=\"color: #ff0000\">&lt;contents-of-client-publickey&gt;<\/span>\nAllowedIPs = 10.0.0.2\/32<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">If your default network interface name differs, you might need to check it and replace eth0 with it in the config above.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code class=\"\">ip route list default<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Note that the configuration file must include the actual keys, a string of letters, numbers and symbols. You can read the key files with the following commands.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code class=\"\">sudo cat \/etc\/wireguard\/publickey\nsudo cat \/etc\/wireguard\/privatekey<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Then, save the file and exit the editor.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Starting WireGuard and enabling it at boot<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">With the configuration in place, we are ready to start the server. WireGuard has a convenient wrapper called <tt>wg-quick<\/tt> that can be used to start new interfaces without needing to go into the setup details. You can use it to start your configuration using the following command.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code class=\"\">wg-quick up wg0<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Upon successfully starting the interface, you should see an output like the one below.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code class=\"\">[#] ip link add wg0 type wireguard\n[#] wg setconf wg0 \/dev\/fd\/63\n[#] ip -4 address add 10.0.0.1\/24 dev wg0\n[#] ip link set mtu 1420 up dev wg0\n[#] iptables -A FORWARD -i wg0 -j ACCEPT; iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Your WireGuard server is then running. You can check your configuration with the following command.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code class=\"\">wg show<\/code><\/pre>\n\n\n\n<pre class=\"wp-block-code\"><code class=\"\"><span style=\"color: #99cc00\">interface<\/span>: <span style=\"color: #99cc00\">wg0<\/span>\n  public key: pcDxSxSZp5x87cNoRJaHdAOzxrxDfDUn7pGmrY\/AmzI=\n  private key: (hidden)\n  listening port: 51820\n\n<span style=\"color: #ffcc00\">peer<\/span>: <span style=\"color: #ffcc00\">gCQKfJL8Xff2MNmvceVQ0nQAmLsSM0tXClhvVNzSil4=<\/span>\n  allowed ips: 10.0.0.2\/32<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">To enable WireGuard to start automatically at system boot, also enable the systemd service.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code class=\"\">systemctl enable wg-quick@wg0<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">If you get an error starting the server, use the example below.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code class=\"\">RTNETLINK answers: Operation not supported\nUnable to access interface: Protocol not supported<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Make sure your server software is fully up-to-date.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code class=\"\">sudo apt-get update &amp;&amp; sudo apt-get upgrade -y<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Then, check that the WireGuard kernel module is loaded with the command below. If successful, you should not see any output.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code class=\"\">sudo modprobe wireguard<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">If you get an error saying the module is missing, restart your WireGuard server and try again.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code class=\"\">sudo reboot<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">When the kernel module is loaded, you can try starting WireGuard again.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Client configuration<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Once your WireGuard server is up and running, you must configure your client device. They offer software for most operating systems to connect your Windows, Linux, or macOS and Android or iOS devices easily. You can find available packages on <a href=\"https:\/\/www.wireguard.com\/install\/\" target=\"_blank\" rel=\"noopener\">their download page<\/a>.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Create a new configuration file in the \/etc\/wireguard directory on a client computer.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code class=\"\">sudo nano \/etc\/wireguard\/wg0.conf<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Then, add the following to that file. Remember to set the client private key and server public key to their corresponding places and include your WireGuard server\u2019s public IP address.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code class=\"\">[Interface]\nAddress = 10.0.0.2\/32\nPrivateKey = <span style=\"color: #ff0000\">&lt;contents-of-client-privatekey&gt;<\/span>\nDNS = 1.1.1.1\n\n[Peer]\nPublicKey = <span style=\"color: #ff0000\">&lt;contents-of-server-publickey&gt;<\/span>\nEndpoint = <span style=\"color: #ff0000\">&lt;server-public-ip&gt;<\/span>:51820\nAllowedIPs = 0.0.0.0\/0, ::\/0<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Note that setting <tt>AllowedIPs to 0.0.0.0\/0, ::\/0<\/tt> will forward all traffic over the WireGuard VPN connection. If you want only to use WireGuard for specific destinations, set their IP address ranges in the list separated by a comma.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Once you\u2019ve set the keys and the server address, save the file and exit the editor.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Start the connection with the command below.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code class=\"\">sudo wg-quick up wg0<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">You can also use the system command to start WireGuard as a service.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code class=\"\">sudo systemctl start wg-quick@wg0<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Then, when you want to disconnect, use either of the following commands, depending on which method you used to start it.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code class=\"\">sudo wg-quick down wg0\nsudo systemctl stop wg-quick@wg0<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">WireGuard will then disconnect from the server and remove the related network settings.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Adding more clients<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">You can add more clients to your server if you want to use the WireGuard VPN on other devices. Adding clients is simple.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">First, install WireGuard on your new client devices as before and create a new key pair.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Next, stop the server to be able to edit the configuration.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code class=\"\">sudo wg-quick down wg0<br>sudo systemctl stop wg-quick@wg0<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Then, edit the <tt>wg0.conf<\/tt> file on your WireGuard server.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code class=\"\">sudo nano \/etc\/wireguard\/wg0.conf<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Add the following entry at the end of the file to include your second client\u2019s public key and set the IP address.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code class=\"\">[Peer]\nPublicKey = <span style=\"color: #ff0000\">&lt;content-of-client2-publickey&gt;<\/span>\nAllowedIPs = 10.0.0.3\/32<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Afterwards, save the file and exit the editor.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Then, restart the service to update the configuration.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code class=\"\">sudo systemctl start wg-quick@wg0<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">All done! You can then connect with the new client as you did before.<\/p>\n","protected":false},"author":42,"featured_media":15517,"comment_status":"open","ping_status":"closed","template":"","community-category":[223,259,253],"class_list":["post-2158","tutorial","type-tutorial","status-publish","has-post-thumbnail","hentry"],"acf":[],"_links":{"self":[{"href":"https:\/\/upcloud.com\/global\/wp-json\/wp\/v2\/tutorial\/2158","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/upcloud.com\/global\/wp-json\/wp\/v2\/tutorial"}],"about":[{"href":"https:\/\/upcloud.com\/global\/wp-json\/wp\/v2\/types\/tutorial"}],"author":[{"embeddable":true,"href":"https:\/\/upcloud.com\/global\/wp-json\/wp\/v2\/users\/42"}],"replies":[{"embeddable":true,"href":"https:\/\/upcloud.com\/global\/wp-json\/wp\/v2\/comments?post=2158"}],"version-history":[{"count":1,"href":"https:\/\/upcloud.com\/global\/wp-json\/wp\/v2\/tutorial\/2158\/revisions"}],"predecessor-version":[{"id":6439,"href":"https:\/\/upcloud.com\/global\/wp-json\/wp\/v2\/tutorial\/2158\/revisions\/6439"}],"wp:attachment":[{"href":"https:\/\/upcloud.com\/global\/wp-json\/wp\/v2\/media?parent=2158"}],"wp:term":[{"taxonomy":"community-category","embeddable":true,"href":"https:\/\/upcloud.com\/global\/wp-json\/wp\/v2\/community-category?post=2158"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}