NixOS’s declarative container management provides a way to declaratively configure an entire (NixOS) Linux system to be run inside the host. Below you will find the Nix config that configures a new container named “vpn” in the following way:

  • Add the specified system packages
  • Add the specified user

Of course, you can do more - such as adding systemd services, configuring firewall, etc. But for this post, we are interested only in creating an isolated system that will connect to a VPN network whilst leaving the rest of your computer remain connected without VPN 1 .

  containers.vpn = { 
    config =  { config, pkgs, ... }: {
      environment.systemPackages = with pkgs; [
        protonvpn-cli  # Our VPN client
      users.extraUsers.user = {
        isNormalUser = true;
        uid = 1000;

Add the above to your host’s configuration.nix, and then nixos-rebuild switch. Now you can start the container as:

sudo nixos-container start vpn

And access its root shell as:

sudo nixos-container root-login vpn

From within the root shell, you will want to login to your ProtonVPN account:

protonvpn init

Connect to VPN,

protonvpn c --fastest

And then login as a non-root user (important!) with tmux:

su - user -c "tmux new -A"

From here, you can use your favourite network clients to access the outside world through VPN.

In particular, the protonvpn Linux client is not always reliable over long-time; it is not uncommon to find my home-server host unreachable from the outside due to a frozen VPN connection.