# How to create a VPN server with Linode

## Introduction <a href="#introduction" id="introduction"></a>

In this guide, you will learn how to create a custom VPN server on Linode using [Meshnet](https://nordvpn.com/meshnet/). One of the benefits of hosting your own VPN is having more control over your IP address, which can be advantageous in managing privacy and enhancing [network security](https://nordvpn.com/cybersecurity/network-security/). This can be particularly useful if you need to access content that may be restricted by geographical location.

Linode, a well-known cloud hosting provider, lets you build a reliable VPN server featuring scalable resources, a variety of global data center locations, and the ability to migrate servers between data centers. With Meshnet, the process of setting up a VPN server on Linode is made accessible for users with different levels of technical expertise. Meshnet's routing capability allows you to bypass the complexity associated with traditional VPN configurations.

The guide will walk you through the steps of deploying a Linode instance, securing SSH access with key-based authentication, [installing the NordVPN app](https://nordvpn.com/download/), and routing traffic through the server using Meshnet.

{% hint style="info" %}
**Note**

While setting up your own VPN server enhances your online privacy, it may not provide the same level of protection as connecting to a standard VPN server offered by NordVPN. NordVPN follows a [strict no-logs policy](https://nordvpn.com/features/strict-no-logs-policy/), which is crucial for ensuring your online activities remain confidential.
{% endhint %}

## Prerequisites <a href="#prerequisites" id="prerequisites"></a>

Before you begin, make sure you have a Linode account with billing activated. As a new customer, you are eligible to receive free credits.

If you do not have a Linode account yet, you can sign up for one by visiting the [Linode signup](https://www.linode.com/signup/) page.

## Deploy a Linode instance <a href="#deploy-a-linode-instance" id="deploy-a-linode-instance"></a>

First, you need to create a new Linode instance, also called a *Linode*, that will serve as the host for your personalized VPN server.

{% hint style="info" %}
**Note**

While this tutorial focuses on configuring an Ubuntu-based instance, the steps below are applicable to other Linux distributions available on Linode, including CentOS, Debian, Fedora, and more.
{% endhint %}

To configure and launch a Linode instance:

1. Log in to the [Linode Cloud Manager](https://cloud.linode.com/), and then select **Create** and choose **Linode** from the dropdown menu.<br>

   <div align="left"><figure><img src="https://3559400189-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F0cTezbT2vN0lurEio8Z5%2Fuploads%2Fp3gFuYrnmDaPsme2NAgH%2Flinode_create_linode.png?alt=media&#x26;token=06931035-63eb-4ac1-ae03-a258b565289e" alt="Creating a new Linode from the Linode Cloud Manager." width="563"><figcaption></figcaption></figure></div>

2. Select a distribution for your instance. It is recommended to use the latest version of Ubuntu, which is currently Ubuntu 22.04 LTS.<br>

   <div align="left"><figure><img src="https://3559400189-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F0cTezbT2vN0lurEio8Z5%2Fuploads%2FNAzOkcVv4nSo911d64f2%2Flinode_create_distro.png?alt=media&#x26;token=1536abe2-0dea-42be-8ac7-ff8f88f68a3b" alt="Ubuntu 22.04 LTS selected as the distribution." width="563"><figcaption></figcaption></figure></div>

3. Under **Region**, choose a data center location for your Linode instance.<br>

   <div align="left"><figure><img src="https://3559400189-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F0cTezbT2vN0lurEio8Z5%2Fuploads%2FZUOt0xk4QIJCpzURmXv4%2Flinode_create_region.png?alt=media&#x26;token=d94e7257-8cce-4223-a8ef-2bc574c7dc25" alt="Selecting the region of the VM." width="563"><figcaption></figcaption></figure></div>

4. Choose a plan that aligns with your requirements for RAM, CPU, and storage. For example, you can select a shared CPU plan, such as Nanode 1GB, which is a popular choice for personal use.<br>

   <div align="left"><figure><img src="https://3559400189-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F0cTezbT2vN0lurEio8Z5%2Fuploads%2FEom70lMjSTVgQ9fQPSMa%2Flinode_create_cpu.png?alt=media&#x26;token=3db9f655-15d5-453f-96ef-15e1ba6cb901" alt="Selecting the Nanode 1GB shared CPU plan." width="563"><figcaption></figcaption></figure></div>

5. Under **Linode label**, provide a label that indicates the purpose of your instance. For example:<br>

   <div align="left"><figure><img src="https://3559400189-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F0cTezbT2vN0lurEio8Z5%2Fuploads%2F554oN7xT26yGS8GknVVC%2Flinode_create_labels.png?alt=media&#x26;token=1dcd036e-0161-471c-8080-ce7ae5ea026a" alt="Adding custom labels and tags to the VM instance." width="563"><figcaption></figcaption></figure></div>

6. Set a root password for your Linode instance. You can also add an SSH key at this stage or later. For instructions on generating and configuring an SSH key pair, refer to the [Secure SSH access with key-based authentication](#secure-ssh-access-with-key-based-authentication) section further in this guide.

7. To initiate the deployment process, click the **Create Linode** button located at the bottom.

Once started, the creation process redirects you to the instance's information page, where you can track the deployment status and find the IP addresses of your instance.

## Connect to your instance <a href="#connect-to-your-instance" id="connect-to-your-instance"></a>

Now that you have your Linode instance ready, you can access it from your local machine using an SSH client.

1. On the instance information page, under the **Access** section, copy the SSH access command along with the public IPv4 address assigned to the instance.<br>

   <div align="left"><figure><img src="https://3559400189-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F0cTezbT2vN0lurEio8Z5%2Fuploads%2FsIBrE1xHu9DAfMhR1PYf%2Flinode_ssh_ip.png?alt=media&#x26;token=fcce2301-e78c-4894-8a56-69f62417905a" alt="Copying the SSH access details from Linode." width="375"><figcaption></figcaption></figure></div>

2. Paste the command into your local computer’s terminal and press **Enter**.

3. When establishing a connection to the server for the first time, the SSH client asks you to review and confirm the host key's fingerprint. To proceed with the connection, type `yes` in response to the prompt, as shown:<br>

   <div align="left"><figure><img src="https://3559400189-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F0cTezbT2vN0lurEio8Z5%2Fuploads%2FAhO8rNXYmbEF4KQ5ND6g%2Flinode_ssh_fingerprint.png?alt=media&#x26;token=87c208e5-5e7f-435e-9c9b-ddc2417ca852" alt="Confirming VM&#x27;s authenticity while establishing an SSH connection." width="563"><figcaption></figcaption></figure></div>

You should now be successfully connected to your Linode instance.

### Secure SSH access with key-based authentication <a href="#secure-ssh-access-with-key-based-authentication" id="secure-ssh-access-with-key-based-authentication"></a>

By default, when you connect to your Linode instance, authentication is done via a password. For enhanced security, you can switch to key-pair authentication instead. Follow the steps below to create a key pair and configure your instance to accept only key-based SSH logins.

#### Generate an SSH key pair <a href="#generate-an-ssh-key-pair" id="generate-an-ssh-key-pair"></a>

1. On your local machine, open the terminal.

2. Run the following command:<br>

   <pre class="language-bash" data-overflow="wrap"><code class="lang-bash">ssh-keygen
   </code></pre>

   &#x20;

3. When prompted for the file name, you can either:
   * Press **Enter** to use the default names — `id_rsa` and `id_rsa.pub` — and save them in the default directory.
   * Type a custom path and file name to save the private and public keys with the specified name and location, as follows:<br>

     <pre class="language-bash" data-overflow="wrap"><code class="lang-bash">&#x3C;/path/key-filename>
     </code></pre>

     \
     **Example**

     <div align="left"><figure><img src="https://3559400189-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F0cTezbT2vN0lurEio8Z5%2Fuploads%2Fl8vKxRkqgfboK8GqvTgK%2Flinode_ssh_keygen.png?alt=media&#x26;token=1e860697-3fc0-4888-a14a-2066f1f0879c" alt="Generating a new SSH key pair in a specified location."><figcaption></figcaption></figure></div>

4. When creating the key pair, you can choose to encrypt the private key with a passphrase to add security. If you prefer not to use a passphrase, leave the field blank and press **Enter**.

{% hint style="info" %}
**Note**

If you are using a Windows machine, specify the custom path using the Windows format, such as `C:\path\key_filename`.
{% endhint %}

#### Set permissions for the private key <a href="#set-permissions-for-the-private-key" id="set-permissions-for-the-private-key"></a>

After creating the SSH key pair, set the appropriate permissions for the private key to ensure that only you can access it.

{% tabs %}
{% tab title="Windows" %}

1. Right-click the private key.
2. Select **Properties**, choose the **Security** tab, and click **Advanced**.
3. Click **Disable inheritance** > **Convert inherited permissions into explicit permission on this object.**
4. Back in the **Advanced security settings** window, remove access for all users except your own account by selecting a permission entry and clicking **Remove**.<br>

   <div align="left"><figure><img src="https://3559400189-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F0cTezbT2vN0lurEio8Z5%2Fuploads%2FOu88eXBLa2TjWjqJfj2Q%2Flinode_ssh_key_win.png?alt=media&#x26;token=88423e37-9505-40c9-bcea-153ff8283f87" alt="Changing permissions for the SSH private key."><figcaption></figcaption></figure></div>

{% endtab %}

{% tab title="macOS and Linux" %}
Enter the `chmod 400` command followed by the path to the generated private key:

{% code overflow="wrap" %}

```bash
chmod 400 </path/private-key-filename>
```

{% endcode %}

**Example**

<div align="left"><figure><img src="https://3559400189-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F0cTezbT2vN0lurEio8Z5%2Fuploads%2FuOAFdxdnqw3BgqwgWAtd%2Flinode_ssh_key_unix.png?alt=media&#x26;token=d6ba6c1c-86d4-4dcb-9062-fd75f16509ff" alt="Running the &#x27;chmod 400&#x27; command in the terminal."><figcaption></figcaption></figure></div>
{% endtab %}
{% endtabs %}

#### Add the public key to the instance <a href="#add-the-public-key-to-the-instance" id="add-the-public-key-to-the-instance"></a>

To add your public SSH key to the Linode instance, follow these steps:

1. On your local computer, open the terminal (**PowerShell** on Windows).
2. Display the contents of the public SSH key file by entering the `cat` command followed by the path to the file.<br>

   <pre class="language-bash" data-overflow="wrap"><code class="lang-bash">cat &#x3C;/path/public-key-filename>
   </code></pre>

   &#x20;

   **Example**

   <pre class="language-bash" data-overflow="wrap"><code class="lang-bash">cat /Users/MeshnetUser/.ssh/linode_key.pub
   </code></pre>

   &#x20;
3. The contents of your SSH key will be displayed in the terminal. Select and copy the output, which starts with `ssh-rsa` and ends with `<your_username>@<hostname>`.
4. Connect to your Linode instance via SSH, as described in the [Connect to your instance](#connect-to-your-instance) section:<br>

   <pre class="language-bash" data-overflow="wrap"><code class="lang-bash">ssh root@&#x3C;linode-ip-address>
   </code></pre>

   &#x20;
5. Create the `~/.ssh` directory and `authorized_keys` file, and set appropriate permissions, as follows:<br>

   <pre class="language-bash" data-overflow="wrap"><code class="lang-bash">mkdir -p ~/.ssh &#x26;&#x26; touch ~/.ssh/authorized_keys 
   chmod 700 ~/.ssh &#x26;&#x26; chmod 600 ~/.ssh/authorized_keys
   </code></pre>

   &#x20;
6. Open the `authorized_keys` file with a text editor, such as nano, by entering this command:<br>

   <pre data-overflow="wrap"><code>nano ~/.ssh/authorized_keys
   </code></pre>

   &#x20;
7. Paste the contents of your public key on a new line and press **Ctrl** + **X**, followed by **Y**, and then press **Enter** to save the changes.

{% hint style="success" %}
**Tip**

You can automate the public SSH key upload process as described in the [How to access remote systems over Meshnet using SSH](https://meshnet.nordvpn.com/~/changes/otYJMg7qFzDy0nWn86iM/how-to/remote-access/access-remote-systems-over-ssh) article. This method is useful for managing multiple instances or frequent key uploads.
{% endhint %}

#### Connect to the instance using the SSH keys <a href="#connect-to-the-instance-using-the-ssh-keys" id="connect-to-the-instance-using-the-ssh-keys"></a>

To further secure your server, you can disable password authentication and rely solely on SSH key-pair authentication. However, before doing so, make sure that you can access your instance through SSH key-pair authentication.

1. Exit the current SSH session on your Linode instance by typing `exit` and pressing **Enter**.
2. To establish an SSH connection using key-based authentication, enter the following command:<br>

   ```bash
   ssh -i </path/private-key-file> root@<linode-ip-address>
   ```

   \
   Replace `</path/private-key-file>` with the path to your private SSH key file and `<linode-ip-address>` with the IP address of your Linode instance.\
   \
   **Example**

   <div align="left"><figure><img src="https://3559400189-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F0cTezbT2vN0lurEio8Z5%2Fuploads%2FWadmBdGZRcwJTIPm2rYV%2Flinode_ssh_connect.png?alt=media&#x26;token=defa710c-d0b0-44ad-8504-0f907587c0c2" alt="Accessing the Linode VM over SSH using the generated SSH keys for authentication."><figcaption></figcaption></figure></div>

If you set a passphrase for your private key, you'll be prompted to enter it when connecting. Once you enter the correct passphrase, you should be logged in to your Linode.

#### Disable password authentication <a href="#disable-password-authentication" id="disable-password-authentication"></a>

Once you've verified that you can access your instance using SSH key-pair authentication, you may want to consider disabling password authentication.

1. Open the SSH configuration file in a text editor, such as nano, by entering:<br>

   ```bash
   sudo nano /etc/ssh/sshd_config
   ```

   &#x20;

2. Locate the line that begins with `PasswordAuthentication` and change the value to `no`, as shown:<br>

   <div align="left"><figure><img src="https://3559400189-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F0cTezbT2vN0lurEio8Z5%2Fuploads%2FmiPKRBcnOg0nCzMW13jx%2Flinode_ssh_pass_auth.png?alt=media&#x26;token=3215ccfc-26d7-4801-bd1d-2373785e41bf" alt="Disabling SSH password authentication on the Linode VM."><figcaption></figcaption></figure></div>

3. To save and close the file, press **Ctrl** + **X**, followed by **Y**, and then press **Enter**.

4. Restart the SSH service to apply the changes by entering:<br>

   ```bash
   sudo systemctl restart sshd
   ```

If you're able to log in to the instance successfully without entering a password, it confirms that your public key has been added and your private key is working as expected.

## Install NordVPN on the instance <a href="#install-nordvpn-on-the-instance" id="install-nordvpn-on-the-instance"></a>

To set up NordVPN on your instance, follow these steps:

1. Download and install the NordVPN Linux client by entering this command in the instance terminal:<br>

   ```bash
   sh <(wget -qO - https://downloads.nordcdn.com/apps/linux/install.sh)
   ```

   &#x20;
2. Log in to your NordVPN account.

### Log in to NordVPN <a href="#log-in-to-nordvpn" id="log-in-to-nordvpn"></a>

You can log in to your NordVPN account without the use of a graphical user interface (GUI) in two ways:

* By running the `nordvpn login` command with the `--token` flag
* By running the `nordvpn login` command with the `--callback` flag

Instructions for both methods are outlined below.

{% tabs %}
{% tab title="Log in using a token" %}

1. On any device, log in to your [Nord Account](https://my.ndaccount.com/) dashboard.&#x20;

2. Under **NordVPN Meshnet free**, select **View details**.<br>

   <div align="left"><figure><img src="https://3559400189-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F0cTezbT2vN0lurEio8Z5%2Fuploads%2Fsn49VgeZ6NMI13J7Ki1N%2Ftoken_generate0.png?alt=media&#x26;token=a773ba2c-27a9-4e88-b7bf-c4fe60cd2d42" alt="Clicking the &#x27;View details&#x27; button under NordVPN Meshnet free." width="563"><figcaption></figcaption></figure></div>

3. Scroll down until you see **Access token**.

4. Select the **Generate new token** button.<br>

   <div align="left"><figure><img src="https://3559400189-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F0cTezbT2vN0lurEio8Z5%2Fuploads%2F4PoIcgMGswTyRI8d8b0i%2Ftoken_generate.png?alt=media&#x26;token=c0502a41-fdea-4212-bb19-5e1eb19638ba" alt="Clicking &#x27;Generate new token&#x27;" width="563"><figcaption></figcaption></figure></div>

5. In the dialog that appears, choose either a token that expires in 30 days or one that never expires, and then select **Generate token**.<br>

   <div align="left"><figure><img src="https://3559400189-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F0cTezbT2vN0lurEio8Z5%2Fuploads%2Fw2MaEvL5cIVshJPYkTbG%2Ftoken_generate2.png?alt=media&#x26;token=82907065-348b-4f0b-bee2-9ea49245a74a" alt="Selecting the token expiration date." width="563"><figcaption></figcaption></figure></div>

6. Select **Copy and close**.

7. On your VM, enter the `nordvpn login --token` command along with the copied token:<br>

   ```bash
   nordvpn login --token <your_token>
   ```

   \
   **Example**

   <pre class="language-bash" data-overflow="wrap"><code class="lang-bash">nordvpn login --token 3fe460cefb8dcf1478c92e45908cec9f9bdbadf7a456a6dfb35dc2c58ee39d5b
   </code></pre>

You should now see a welcome message.

{% hint style="success" %}
**Tip**

To preserve your token when logging out of the NordVPN app, use the `nordvpn logout --persist-token` command. Otherwise, your token will be revoked.&#x20;
{% endhint %}
{% endtab %}

{% tab title="Log in using a URL" %}

1. Run the following command:<br>

   ```
   nordvpn login
   ```

2. Open the provided link on any device in your browser.

3. Complete the login procedure.

4. Right-click the **Continue** button and select **Copy link address**.

5. Run the following command, replacing `<URL>` with the previously copied link address:<br>

   ```bash
   nordvpn login --callback "<URL>"
   ```

   \
   **Example**

   <pre class="language-bash" data-overflow="wrap"><code class="lang-bash">nordvpn login --callback "nordvpn://login?action=login&#x26;exchange_token=MGFlY2E1NmE4YjM2NDM4NjUzN2VjOWIzYWM3ZTU3ZDliNDdiNzRjZTMwMjE5YjkzZTNhNTI3ZWZlOTIwMGJlOQ%3D%3D&#x26;status=done"
   </code></pre>

You should now see a welcome message.
{% endtab %}
{% endtabs %}

{% hint style="info" %}
**Note**

If you encounter the error message “Whoops! Permission denied accessing /run/nordvpn/nordvpnd.sock,” enter `sudo usermod -aG nordvpn $USER`. Then, exit and log back in to your instance.
{% endhint %}

## Enable Meshnet <a href="#enable-meshnet" id="enable-meshnet"></a>

On your instance, [enable Meshnet](https://meshnet.nordvpn.com/~/changes/otYJMg7qFzDy0nWn86iM/getting-started/how-to-start-using-meshnet/using-meshnet-on-linux) by typing this command:

```bash
nordvpn set meshnet on
```

To view the Nord name and Meshnet IP address of your instance, enter the following command.

```bash
nordvpn meshnet peer list
```

Additionally, you will see all the devices connected to your network. Depending on the [Meshnet permissions](https://meshnet.nordvpn.com/~/changes/otYJMg7qFzDy0nWn86iM/features/explaining-permissions/traffic-routing-permissions) granted to each device, they will have access to this server via Meshnet.

## Route traffic through your server <a href="#route-traffic-through-your-server" id="route-traffic-through-your-server"></a>

To begin using your instance as a VPN server, you need to route traffic from a client device through the instance. Follow these steps:

1. On your client device, open **NordVPN** and log in to your account.
2. Start routing traffic through the linked host device you set up.<br>

   <div align="left"><figure><img src="https://3559400189-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F0cTezbT2vN0lurEio8Z5%2Fuploads%2F1UWCvq87AgLqS4JpkybL%2Flinode_route_connect.png?alt=media&#x26;token=124dd286-44e4-4e97-b4b3-61461b84fbeb" alt="Starting routing traffic through the Linode VM."><figcaption></figcaption></figure></div>

   \
   For detailed guidance on enabling traffic routing, refer to [Routing traffic in Meshnet](https://meshnet.nordvpn.com/~/changes/otYJMg7qFzDy0nWn86iM/features/routing-traffic-in-meshnet#see-also).

[Your device's IP address](https://nordvpn.com/what-is-my-ip/) should now match the public IP address of your instance. This way, your real IP address remains secure, and the websites you visit will detect the location of your VPN server instead of your actual device.

![Checking the new IP address after connecting to the VPN server.](https://3559400189-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F0cTezbT2vN0lurEio8Z5%2Fuploads%2F4Pz53TOCpqmT02Cm7tlC%2Flinode_route_connected.png?alt=media\&token=da579ccf-01b6-4086-a78e-f55579140228)
