profile picture

UpCloud & Unifi: IPSec VPN Tunnel

September 26, 2026 - networking

As always, I'm in the middle of a home infrastructure migration project.

In this instance, I've been building out a personal "cloud" with UpCloud.

To simplify and secure communication between services running in my basement with the servers in the cloud, I decided to set up an IPSec tunnel, which is a type of VPN link to bridge two networks.

Once configured, servers within UpCloud can directly reach internal machines in a specific subnet within a local network and vice-versa!

While I'm pretty experienced with networks and VPNs, this was my first time dealing with IPSec, and though the actual configuration isn't too onerous, I ran into a few problems that were very subtle and hard to debug.

My home network is Unifi-based with a Unifi Dream Machine Pro as the core gateway/router, and its IPSec defaults are incompatible with UpCloud, so various options need to get tweaked in its web interface. Additionally, I ran into multiple subnet conflicts: first between my home network and UpCloud's managed Kubernetes and then between the new subnet I picked also already being used locally for another purpose!

Setup: Create Network/VLAN in Unifi

Within your Unifi admin console, navigate to Settings > Networks (note: this is accurate as of 10.x) and create a new subnet named "UpCloud Bridge" within the 172.16.0.0/12 block, e.g. 172.20.0.0/24.

💡 If you've got other VPN networks or are running containers/VMs, be sure that you don't pick a conflicting range! For example, 172.17.0.0/16 is the default Docker bridge.

In my case, I also chose to shrink the DHCP pool range to .125 -> .225 because I largely intend to statically assign IPs within this subnet.

You can use an existing subnet as long as it's in neither the 192.168.0.0/16 range (used by Cilium CNI in UpCloud) nor the 10.0.0.0/8 range (used by UpCloud SDN, i.e. private and utility networks).

Setup: Create UpCloud VPN Gateway

First, within the UpCloud web console, create a new VPN Gateway attached to the SDN router you want to bridge with (they must live in the same UpCloud region).

Once created, it will take a few minutes to provision: when the public IP is visible, it's ready to be configured.

Add a VPN connection to it:

  1. "Local" IP will be automatically set (this is your VPN gateway's public IP)
  2. "Remote" IP should be your public/home IP for the Unifi gateway
  3. Copy the PSK: you will need it for the Unifi set up next!
  4. Add a "local" route to the desired UpCloud subnet range (e.g. 10.80.0.0/24)
  5. Add a "remote" route to the desired Unifi/VLAN subnet range (e.g. 172.20.0.0/24)

You will need to restart any running UpCloud servers so they get the updated route table. Tip: this can be done in bulk (including for Kubernetes nodes) from the web console with multi-select actions.

Setup: Create Unifi Site-to-Site VPN Connection

Within your Unifi web console, navigate to Settings > VPN (note: this is accurate as of 10.x) and create a new Site-to-Site VPN.

Under Advanced, toggle from "Auto" to "Manual" and then configure:

The other values can remain at their defaults, but it's worth opening the "Advanced Settings" dialog for the VPN Connection within the gateway in UpCloud to make sure things line up.

Note that the IKE + ESP "lifetime" values on the Unifi side are independent of the key/timeout/delay values in UpCloud!

For key exchange, UpCloud only supports IKEv2.

For encryption, I opted to stick with AES128 over AES256 for reduced resource usage, as it's still a strong encryption algorithm (as of late 2026). While UpCloud also supports the GCM variants, these are not available in the Unifi console.

For integrity/hashing, UpCloud does NOT support SHA1 (the Unifi default); I opted to go with SHA256 over SHA384/SHA512 again for reduced resource usage and no known weaknesses (as of late 2026).

Once saved, the tunnel should show as "Established" in the Unifi console.

Setup: Add Local Device to Unifi Network

With the tunnel actually set up, we need local device(s) on the new "UpCloud Bridge" Unifi network/subnet.

In the interest of avoiding internal/private DNS records across UpCloud and Unifi networks, I'd recommend using static IPs or DHCP reservations.

⚠️ Take care when modifying VLAN and IP address assignments!

It's easy to misconfigure and block network access to/from the target machine.

Option A: Move Local Machine to "UpCloud Bridge" Network (Single IP)

The lowest-effort option is to change the native network (VLAN) for the port in the Unifi Console to be the "UpCloud Bridge" subnet (172.x.x.x) you created instead of "Default" (192.168.x.x).

If you're using DHCP (with or without reservation), reconnecting/restarting the device should be all that's needed.

If you're using a static IP with a headless device, you will need to change it on the target machine before updating the port assignment on the Unifi side, but note that you'll lose connectivity while they're out of sync.

Option B: Configure Local Machine VLAN Trunking (Multiple IPs)

In my situation, I didn't want to re-assign the machine to the new network/subnet, as the local server I'm trying to bridge with UpCloud already runs various core LAN services like DNS, and its 192.168.x.x address is hardcoded a bunch of places that would need updating.

Instead, I left the port's default network (VLAN) as my "Default" but enabled "Custom" for "Tagged VLAN Management", adding "UpCloud Bridge" network to the allowed tagged VLANs.

This permits the device to live on both VLANs simultaneously via a "trunked" network adapter.

Configuration for this varies greatly across OSes. I use systemd-networkd, so the process is roughly:

  1. Create a .netdev for the "UpCloud Bridge" VLAN ID
  2. Create a .network for the trunked adapter
    • Create a static route to the UpCloud 10.x.x.x range via the 172.x.x.1 gateway
    • (Optional) Assign a static 172.x.x.x IP
  3. Add a VLAN= reference to the trunked adapter in the parent/real adapter .network file

Here's the actual configuration from my network:

/etc/systemd/network/40-wired.network

[Match]
Name=eth0

[Network]
Address=192.168.1.99/24
DHCP=no
DNS=127.0.0.1
Gateway=192.168.1.1
VLAN=upcloud

/etc/systemd/network/50-upcloud.netdev

[Network]

[NetDev]
Kind=vlan
Name=upcloud

[VLAN]
Id=7

/etc/systemd/50-upcloud.network

[Match]
Name=upcloud

[Network]
Address=172.20.0.10/24

[Route]
Destination=10.80.0.0/24
Gateway=172.20.0.1

Summary: Caveats / Gotchas

UpCloud's managed Kubernetes clusters use 192.168.0.0/16 for Cilium CNI networking and 10.0.0.0/8 for SDN (custom private networks and default utility network).

Solution: network/VLAN in Unifi must be within the 172.16.0.0/12 private IP block.

Unifi IPSec defaults ("Auto") are incompatible with UpCloud.

Solution: switch Unifi IPSec Advanced config to "Manual" with IKEv2, something besides SHA1, and correct MTU/MSS (see above for specifics).

Public IP changes require manual updates in both UpCloud + Unifi after renewal.

Solution: in UpCloud, on the VPN gateway connection, update the "remote IP" to your new public IP. In Unifi, on the site-to-site VPN connection, update the "local IP" to your new public IP.

NOTE: Unifi suggests using a hostname (maintained with dynamic DNS aka DDNS) instead of an IP directly for this reason, but I did not test to see if UpCloud supports that.

Summary: Final Thoughts

I've only had this configured for a couple days now, most of which was spent debugging the connectivity problems! However, since getting that sorted out, it's been working great.

Performance-wise, I'm using the free "Essentials" tier, which suits my needs.

In the end, while admittedly a bit more of a niche use case, being able to seamlessly bridge servers over a private network is a nice security & convenience option.

I'm already using it for Kanidm replication and plan to use it for local ARM64 CI runners next!