> This page is for Developers.

> For clean Markdown of any page, append .md to the page URL.
> For a complete documentation index, see https://docs.emnify.com/llms.txt.
> For AI client integration (Claude Code, Cursor, etc.), connect to the MCP server at https://docs.emnify.com/_mcp/server.

# Integrate OpenVPN on Linux

> Step-by-step guide for integrating OpenVPN on Linux to use on devices with emnify eSIMs.

Using emnify, you can create a [virtual private network (VPN)](https://www.emnify.com/iot-glossary#vpn) for your mobile IoT/M2M devices fitted with emnify SIMs.
Data traffic is exchanged between the devices and the application server through an OpenVPN tunnel, enabling direct communication with the IPs of the mobile devices—no network address translation (NAT) applied.

The tunnel is established between the emnify Core Network and the customer's VPN gateway or server.

> **Tip**
>
> The [Secure your devices with OpenVPN](https://youtu.be/yt44fJpfkQ4) video provides a step-by-step walk-through.

## Required preparation in the emnify Portal

Any traffic exchanged with mobile devices is encrypted before being transmitted over the public internet, which adds an additional layer of security and privacy.
No VPN software needs to be installed on the device, or there aren't any required configuration changes necessary.
The default emnify APN also supports VPN flows.

### Download the VPN configuration file

[Log in to your emnify account](https://portal.emnify.com/sign).

Navigate to **Integrations** and find the [**Secure Connection**](https://portal.emnify.com/integrations#secure-connection) section.

Under **OpenVPN**, select **Show instructions**.

![](/_fern-img/dc9a5cf67757307da107bd7841461d21f2cac2d80bf6bf9fc87497588822b36f.webp)

Make sure you're on the **Linux** tab, then click **Download client.conf**.

![](/_fern-img/26be2decfccfffe28121ec33a90fc2f0c3333a4cf95d89a21d930d90cad59f7c.webp)

Select the region that matches the breakout region configured in the device's service policy or **Download all regions**.

> **Warning**
>
> End-to-end connectivity only works between devices and OpenVPN clients configured in the same region.

Once downloaded, store that file on your server in the folder `/etc/openvpn`.

### Change the internet breakout region

Navigate to [**Device Policies**](https://portal.emnify.com/device-policies) in the emnify Portal.

In **Service Policies**, select the policy assigned to the devices you want to secure and expand the policy details.

In **Data**, find **Internet breakout region**.
By default, the badge next to the section title reads **Automatic Breakout Region**.
Click **Edit** to access the **Breakout region** dropdown menu.

Select a VPN breakout region (for example, `eu-west-1 (VPN)`).

> **Check**
>
> Changes save automatically.

## Set up the OpenVPN client on Linux/Ubuntu

### Install the OpenVPN software

First, install the OpenVPN package:

```bash
sudo apt-get install openvpn
```

### Create credentials for authentication

Once you install the software and [download the configuration file](#download-the-vpn-configuration-file), setting up authentication is next.
Create a file called `credentials.txt` in the folder `/etc/openvpn`.
You can use your user credentials to authenticate or use an application token (recommended).

#### Authentication with user credentials

The content of the `credentials.txt` must be two lines.
The first line is your username, and the second is your password.

```txt
username@domain.com
YourPassword
```

> **Info**
>
> If you don't want to store your credentials, you can also choose to enter them each time the VPN tunnel is established.
> If you prefer that option, comment out the line `auth-user-pass /etc/openvpn/credentials.txt` in the `client.conf` file.

#### Authentication with an application token

When you run the OpenVPN client on a VPN gateway or application server, using a dedicated application token is recommended.
In this case, the first line in the `credentials.txt` file needs to contain your emnify organization identifier. Instead of the password on the second line, store the application token.

You can create application tokens in the emnify Portal.
For instructions, see [Application tokens](/portal/application-tokens).

Once created, copy the token into the credentials file.
The content of the credentials file would then look like this:

```txt
orgId
ApplicationToken
```

When you log in to the emnify Portal, it shows this data under the VPN settings.

### Protect the credentials file

You should keep the `credentials.txt` file only readable by root and not by other server users.
You can ensure this with the following commands:

```bash
sudo chown root:root /etc/openvpn/credentials.txt
sudo chmod 600 /etc/openvpn/credentials.txt
```

### Start and monitor the OpenVPN connection

Now you can start the VPN client by running:

```bash
sudo service openvpn start
```

The OpenVPN daemon logs into `/var/log/syslog`.
If everything works, it looks like this:

```txt
Jul 12 17:53:55 openvpn-client ovpn-client[3027]: Data Channel Encrypt: Cipher 'BF-CBC' initialized with 128 bit key
Jul 12 17:53:55 openvpn-client ovpn-client[3027]: Data Channel Encrypt: Using 160 bit message hash 'SHA1' for HMAC authentication
Jul 12 17:53:55 openvpn-client ovpn-client[3027]: Control Channel: TLSv1, cipher TLSv1/SSLv3 DHE-RSA-AES256-SHA, 2048 bit RSA
Jul 12 17:53:55 openvpn-client ovpn-client[3027]: [openvpn.emnify.net] Peer Connection Initiated with [AF_INET]52.209.x.y:1194
Jul 12 17:53:57 openvpn-client ovpn-client[3027]: SENT CONTROL [openvpn.emnify.net]: 'PUSH_REQUEST' (status=1)
Jul 12 17:53:57 openvpn-client ovpn-client[3027]: PUSH: Received control message: 'PUSH_REPLY,route 10.64.0.1,topology net30,ping 1,ping-restart 5,route 10.x.y.z 255.255.128.0,ifconfig 10.64.0.224 10.64.0.225'
Jul 12 17:53:57 openvpn-client ovpn-client[3027]: TUN/TAP device tun0 opened
Jul 12 17:53:57 openvpn-client ovpn-client[3027]: /sbin/route add -net 10.64.0.1 netmask 255.255.255.255 gw 10.64.0.225
Jul 12 17:53:57 openvpn-client ovpn-client[3027]: /sbin/route add -net 10.x.y.z netmask 255.255.128.0 gw 10.64.0.225
```

### Find the static private IP of your VPN client

The emnify OpenVPN server allocates a static IP address to the tun interface of your VPN client.
This IP also stays the same when your VPN client is reconnecting or if you move the tunnel to a different machine.
So you can use it on your mobile devices to address your application.
Nevertheless, you should never configure the IP directly on your devices but use a DNS to resolve it.

Once the tunnel is established, you can see that IP address on your tun interface.
In this example, the IP address is `10.64.0.224`:

```bash
ubuntu@openvpn-client:~$ ip a s tun0
14: tun0: <POINTOPOINT,MULTICAST,NOARP,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UNKNOWN qlen 100
    link/none 
    inet 10.64.0.224 peer 10.64.0.225/32 scope global tun0
```

### Test successful data connectivity

If the VPN tunnel is established successfully, you can connect directly to your mobile devices' private IP addresses.

For testing, you can choose any of your devices that are currently in an active data session.

[Log in to your emnify account](https://portal.emnify.com/sign).

Navigate to **Connected Devices** and find the device you want to test.
Click anywhere on the table row to open the device details.

Under **General**, go to **Status** > **Connectivity Status** to see if it's currently online.
Then check **Device** > **IP address** for the assigned IP address.

Now you can ping that private IP address:

```bash
root@openvpn-client:~# ping 10.x.y.z
PING 10.x.y.z (10.x.y.z) 56(84) bytes of data.
64 bytes from 10.x.y.z: icmp_req=1 ttl=62 time=72 ms
64 bytes from 10.x.y.z: icmp_req=2 ttl=62 time=80 ms
64 bytes from 10.x.y.z: icmp_req=3 ttl=62 time=75 ms
```

For this to work, your device must run an IP stack responding to ICMP echo requests.
This might differ for embedded devices that implement only part of the IP stack.

You can use any network protocol.
For example, if your device runs an `sshd` daemon you can log into it via SSH.

### Enable access for servers behind the VPN client

If you have multiple servers behind your VPN gateway that need to communicate with your mobile device, you can apply masquerading using `iptables` to hide them behind the single IP address of your VPN client.

First, you need to enable IP forwarding on your VPN gateway (if it isn't already active):

Open your `/etc/sysctl.conf`

Set `net.ipv4.ip_forward=1`

Load the configuration with `sudo sysctl -p /etc/sysctl.conf`\`

After, you need to enable masquerading for the tun interface by running:

```bash
sudo iptables -t nat -A POSTROUTING -o tun0 -j MASQUERADE
```

You can also forward connections coming to specific ports to an application server behind your VPN gateway by using DNAT.
For example, to forward to an internal HTTP server at IP `192.168.100.21` use:

```bash
sudo iptables -t nat -A PREROUTING -i tun0 -p tcp --dport 80 -j DNAT --to-destination 192.168.100.21
```

To make these settings persistent, you can use the `iptables-persistent` package.