# How to create a VPN server with AWS

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

As the internet has become an indispensable part of our daily lives, addressing its inherent challenges is more important than ever — be it maintaining privacy, securing connections, or accessing global content without restrictions. A personal VPN server can be an effective solution to these concerns, allowing you to navigate the digital world with greater control and peace of mind.

This article focuses on how to create a VPN server using a cloud-based approach in combination with Meshnet. With Meshnet's connectivity and [traffic routing capabilities](https://meshnet.nordvpn.com/~/changes/1En9yEoSh1cmyjIBsnEk/features/routing-traffic-in-meshnet), you can access your VPN server securely from any location and device, without the need for advanced configuration.

When it comes to choosing a cloud provider for setting up a virtual machine, [Amazon Web Services](https://en.wikipedia.org/wiki/Amazon_Web_Services) (AWS) stands out as a popular and reliable option. AWS provides an attractive free tier, enabling you to explore their services without any financial commitment.

{% 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, sign up for an [AWS account](https://aws.amazon.com/ec2/?p=ft\&c=cp\&z=3) and log in. During registration, you can choose from various support plans, including a free option.

## Create a VM instance on AWS <a href="#create-a-virtual-machine-instance-on-aws" id="create-a-virtual-machine-instance-on-aws"></a>

Complete the following steps to prepare for launching a virtual machine (VM), referred to as an *EC2 instance* in the AWS environment.

1. From the navigation bar, select the Regions dropdown menu and choose the region where you want your server to be located.\
   \
   ![Choosing a region for the VPN server.](https://3559400189-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F0cTezbT2vN0lurEio8Z5%2Fuploads%2F9Nwm8WYBrwion94t3FmX%2Faws_select_region.png?alt=media\&token=80fa841d-0ddc-4421-b8ed-456915ca8a27)<br>
2. Do any of the following:
   * On the **Console home** page, under **Build a solution**, choose **Launch a virtual machine**.<br>

     <div align="left"><figure><img src="https://3559400189-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F0cTezbT2vN0lurEio8Z5%2Fuploads%2FDGGm6KS4G9TG0aIs4jCk%2Faws_launch_vm.png?alt=media&#x26;token=39483c8e-f4df-4ce0-90b1-5ec63e997c23" alt="Selecting Launch a virtual machine in the AWS console."><figcaption></figcaption></figure></div>

   * Open the [EC2 console dashboard](https://console.aws.amazon.com/ec2/) and, under **Launch instance**, select the **Launch instance** button, and then choose the **Launch instance** option.

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

This guide primarily covers the setup of an Ubuntu-based VM, but AWS also supports Windows, macOS, and other operating system VMs for custom virtual servers.
{% endhint %}

To configure and launch a VM instance:

1. Under **Name and tags**, in the **Name** field, enter a name for your instance.

2. Under **Application and OS Images (Amazon Machine Image)**, choose an operating system for your instance, like Ubuntu, and its preferred version. Consider choosing a version marked as **Free tier eligible** to avoid additional costs.<br>

   <div align="left"><figure><img src="https://3559400189-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F0cTezbT2vN0lurEio8Z5%2Fuploads%2F5N9S4ApYEZvM1gY8nkRw%2Faws_os_vm.png?alt=media&#x26;token=9ce06ac5-bbe5-456f-a8f7-fa10705fa136" alt="Selecting the operating system of the virtual machine."><figcaption></figcaption></figure></div>

3. Under **Instance type**, you can select the hardware configuration for your instance. The instance type eligible for the free tier is already selected by default, so you can proceed without modifying it unless you need additional resources.

4. Under **Key pair (login)**, choose the option to create a new key pair. Make sure to save the automatically downloaded private key file in a secure location. For additional details, refer to [Amazon's documentation on creating a key pair](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/get-set-up-for-amazon-ec2.html#create-a-key-pair).

5. Configure network settings for better security if needed. Default settings usually suffice for a typical setup, but customizing security groups adds extra protection. For more information, see the [Create a security group](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/get-set-up-for-amazon-ec2.html#create-a-base-security-group) procedure in Amazon's documentation.

6. You can leave the default options selected for the remaining configuration settings of your instance.

7. Under **Summary**, select **Launch instance**. It will take a few minutes for AWS to set up the instance.

Before connecting to your instance, ensure that it has passed all status checks displayed in the **Status check** column of the **Instances** pane, as shown:

<figure><img src="https://3559400189-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F0cTezbT2vN0lurEio8Z5%2Fuploads%2FJTBKHEodujrtIn7NC3KW%2Faws_vm_active.png?alt=media&#x26;token=ac33cc99-da0c-43a6-a328-047b9ee55883" alt="Checking if the VM has passed the status checks."><figcaption></figcaption></figure>

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

Once your instance is running, you can access it from your local computer using [SSH](https://nordvpn.com/cybersecurity/glossary/secure-shell/).

### Setting permissions for the private key <a href="#setting-permissions-for-the-private-key" id="setting-permissions-for-the-private-key"></a>

To protect your private key, make sure that only you have read access to it by setting the appropriate permissions.

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

1. Right-click the downloaded 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%2FtvYqak6fNWY7DCx0lcxe%2Faws_win_key.png?alt=media&#x26;token=afcaf12c-f176-4d2d-8da7-29656faa9fce" alt="Clicking Remove."><figcaption></figcaption></figure></div>

5. Click **Apply**, and then click **OK** to save changes.
   {% endtab %}

{% tab title="From macOS or Linux" %}

1. Open **Terminal**.
2. Enter the following command, replacing `</path/key-pair-name.pem>` with the path to the downloaded private key:<br>

   ```bash
   chmod 400 </path/key-pair-name.pem>
   ```

   \
   **Example**

   <figure><img src="https://3559400189-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F0cTezbT2vN0lurEio8Z5%2Fuploads%2FuxtXHEsLB9vkjgqHfizE%2Faws_mac_key.png?alt=media&#x26;token=6b83c00b-26f9-46d7-a46d-cb61fe24a1e3" alt="Running the &#x27;chmod 400&#x27; command."><figcaption></figcaption></figure>

{% endtab %}
{% endtabs %}

### Accessing your instance using an SSH client <a href="#connect-to-your-instance-using-an-ssh-client" id="connect-to-your-instance-using-an-ssh-client"></a>

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

By default, password authentication and root login are disabled.
{% endhint %}

To establish an SSH connection to your VM instance:

1. Locate the public DNS address of your instance in the **Public IPv4 DNS** column of the **Instances** pane.<br>

   <figure><img src="https://3559400189-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F0cTezbT2vN0lurEio8Z5%2Fuploads%2FXyYAGb35kPcIqGbqlfTw%2Fimage.png?alt=media&#x26;token=b815240f-fe45-49c8-ac5a-f4d311c5e708" alt="Finding the public IPv4 DNS of the VM"><figcaption></figcaption></figure>

2. Open **Command prompt** (on Windows) or **Terminal** (on Linux and macOS).

3. Enter the following command, replacing the placeholders with the appropriate values for your VM instance, where:<br>

   * `</path/key-pair-name.pem>` is the path to your private SSH key file.
   * `<instance-username>` is the username associated with your VM. \
     The default username is determined by the AMI selected when configuring the instance. For example, an Ubuntu AMI uses `ubuntu` as the username. For more information, consult the [Manage users on your Linux instance](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/managing-users.html#ami-default-user-names) article in Amazon’s documentation.
   * `<instance-public-dns-name>` is the public DNS address of your VM instance.

   <pre class="language-bash" data-overflow="wrap"><code class="lang-bash">ssh -i &#x3C;/path/key-pair-name.pem> &#x3C;instance-username>@&#x3C;instance-public-dns-name>
   </code></pre>

   \
   **Example**

   <figure><img src="https://3559400189-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F0cTezbT2vN0lurEio8Z5%2Fuploads%2F1z4NTNiDzNFzyj4IpFug%2Faws_ssh_connect.png?alt=media&#x26;token=87d92b10-47c6-4e85-8563-42bc22b259bb" alt="Connecting to the VM over SSH."><figcaption></figcaption></figure>

4. You will receive a response similar to the one below. Type `yes` and press **Enter** to confirm the connection.<br>

   <figure><img src="https://3559400189-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F0cTezbT2vN0lurEio8Z5%2Fuploads%2FEiYHHjX4anff7lNaZjaP%2Faws_ssh_auth.png?alt=media&#x26;token=8b38aecc-24b3-4530-ad69-ab3df4776bc5" alt="SSH connection confirmation message."><figcaption></figcaption></figure>

You should now be successfully connected to your instance.

## 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>

   <pre class="language-bash" data-overflow="wrap"><code class="lang-bash">sh &#x3C;(wget -qO - https://downloads.nordcdn.com/apps/linux/install.sh)
   </code></pre>

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 and, 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>

2. Scroll down until you see **Manual setup**, and select **Set up NordVPN manually**.<br>

   <div align="left"><figure><img src="https://3559400189-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F0cTezbT2vN0lurEio8Z5%2Fuploads%2FxwVDJGsloM478lIwWmfG%2Fucp_setup_manualy.png?alt=media&#x26;token=601786ee-711d-46a1-8466-d946e7acd57b" alt="Clicking the &#x27;Set up NordVPN manually&#x27; button." width="563"><figcaption></figcaption></figure></div>

3. Enter the verification code sent to your email address.

4. Under **Access token**, select **Generate new 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%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>

   ```bash
   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 into your instance.
{% endhint %}

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

On your instance, [enable Meshnet](https://meshnet.nordvpn.com/~/changes/1En9yEoSh1cmyjIBsnEk/getting-started/how-to-start-using-meshnet/using-meshnet-on-linux#enable-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 [permissions](https://meshnet.nordvpn.com/~/changes/1En9yEoSh1cmyjIBsnEk/features/explaining-permissions) granted to each device, they will have access to this server via Meshnet.

## Route traffic through your instance

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. For specific instructions, see [Routing traffic in Meshnet](https://meshnet.nordvpn.com/~/changes/1En9yEoSh1cmyjIBsnEk/features/routing-traffic-in-meshnet#see-also).&#x20;

<figure><img src="https://3559400189-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F0cTezbT2vN0lurEio8Z5%2Fuploads%2FdjBc6cjca3PEzUvFme2z%2Faws_start_routing.png?alt=media&#x26;token=061a896b-6e73-4b55-b1c1-96d5fde3deb7" alt="Clicking Route all traffic."><figcaption></figcaption></figure>

[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.

<figure><img src="https://3559400189-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F0cTezbT2vN0lurEio8Z5%2Fuploads%2F6oB5529UJaufG4KbWGg3%2Faws_new_ip.png?alt=media&#x26;token=67bbd496-53d2-4f45-af61-2d7fff51f0d4" alt="Checking the new IP address after connecting to the VPN server."><figcaption></figcaption></figure>
