DEV Community

Cover image for Install Windscribe VPN Client in a Distrobox Container on Any Linux Distro!
Archer Allstars
Archer Allstars

Posted on • Edited on

Install Windscribe VPN Client in a Distrobox Container on Any Linux Distro!

Windscribe is a legitimate, privacy-focused VPN service with strong security features. It's regarded as one of the top VPN providers among enthusiasts in privacy-focused communities.

Moreover, you can see miles away from the download page that it takes Linux users seriously. From my personal experience with the client, this is, by far, the best Linux compatible VPN client in the market!

The client also works flawlessly inside a container, eliminating the need of layering the client on an immutable OS like Fedora Silverblue.

Here are reasons why you should consider Windscribe:

  • There are many connection protocols available, WireGuard, Stealth, WStunnel, OpenVPN, IKEv2 (on mobile). The differences between them depend on your use case
    • WireGuard is the fastest.
    • Stealth is a censorship circumvention (China, Russia, Iran), restrictive networks.
    • WStunnel is a last-resort option for the toughest firewalls or corporate networks.
  • If that's not enough, there are more to circumvent censorship, decoy traffic, MAC spoofing, and GPS spoofing.
  • Port forwarding is supported 🀫
  • Split tunneling is supported.
  • CLI client for those on headless servers
  • Many DNS resolver profiles, blocking malware, ads, and trackers by default.
  • Static IP is available, along with static port for port forwarding. This is a killing feature for your remote home projects 🧰
  • Config files for OpenVPN, IKEv2 and WireGuard are available.
  • Arcade sound for the connection! πŸ‘ΎπŸ•ΉοΈ This feature sealed the deal for me πŸ˜†
  • And many more, see all features!

Install Windscribe in a Container

A container

πŸ‘‰οΈ Table of contents:

  1. Install distrobox πŸͺ©, podman πŸ’Š, and screen πŸ“ΊοΈ
  2. Configure distrobox to use podman
  3. Create a Container πŸ“¦οΈ
  4. Install Windscribe client in the Container
  5. Enable the Client's Helper
  6. Create a Launcher Script πŸš€ and a Desktop File πŸ–₯️ on the Host
  7. Make the Container Update Itself Automatically, Zero Maintenance! 😍

🧧 And More:

  • Config Your Firewall πŸ”₯ to Have Port Forwarding πŸ”Œ Working Correctly
    • For ufw System
    • For firewalld System
  • Check the Reach-ability of Your Opened Port πŸ”οΈ
    • GUI way
    • CLI way

😱 Limitations

  • App-based Split Tunneling πŸͺ“
    • Solution βœ…οΈ
  • A Container-safe πŸ‘· Startup Delay
    • Solution βœ…οΈ

1. Install distrobox πŸͺ©, podman πŸ’Š, and screen πŸ“ΊοΈ

The command will be differ based on your specific package manager. Refer to your distro's docs. For example, on Fedora Silverblue:

sudo rpm-ostree install distrobox podman screen
Enter fullscreen mode Exit fullscreen mode

After the installation, reboot your system to activate the new layer. For other mutable distros, there's no need to reboot.


2. Configure distrobox to use podman

echo 'container_manager="podman"' > ~/.config/distrobox/distrobox.conf
Enter fullscreen mode Exit fullscreen mode

3. Create a Container πŸ“¦οΈ

I use the official container image from Ubuntu, as I also use the image for ZeroTier and Cloudflare WARP. Otherwise, you could use openSUSE image instead:

registry.opensuse.org/opensuse/distrobox:latest
Enter fullscreen mode Exit fullscreen mode

Because:

  • It's easier to maintain as it uses a rolling release model, no need to worry about the EOL date of the image/OS.
  • It offers some x86-64-v3 packages, free performance boost!, just by installing the patterns-glibc-hwcaps-x86_64_v3 package.

⚠️ Do NOT create a rootful init container, as it can cause ownership/permission conflicts on shared volumes between the host and other containers.

Creating a Container for Windscribe (Ubuntu Image)

distrobox create -i docker.io/library/ubuntu:latest -n vpn-dbx--root -H ~/distrobox/vpn-dbx--root --additional-packages "pipewire libxcb-shape0 libnl-genl-3-200" --volume /run/dbus/system_bus_socket:/run/dbus/system_bus_socket --additional-flags "--device=/dev/net/tun --cap-add=NET_ADMIN --cap-add=SYS_ADMIN" -r
Enter fullscreen mode Exit fullscreen mode
  • I add the pipewire package to have the audio working for the arcade sound in the client πŸ‘ΎπŸ•ΉοΈ
  • libxcb-shape0 and libnl-genl-3-200 are used by the client.
  • /run/dbus/system_bus_socket, /dev/net/tun, along with --cap-add=NET_ADMIN --cap-add=SYS_ADMIN are universally necessary for any app that wants to modify the state of your network.
  • -r is used to create a rootful container, for obvious reason.

4. Install Windscribe client in the Container

Please refer to Windscribe's official download page.

Update All Packages in the Container

sudo apt update
Enter fullscreen mode Exit fullscreen mode

Install the Official Client You Downloaded

For example:

sudo apt install ./windscribe_2.20.7_amd64.deb
Enter fullscreen mode Exit fullscreen mode

5. Enable the Client's Helper

The client requires its helper running to function. Normally, if you install/layer the client directly on the system, the installer script will create a systemd unit for the helper automatically. But no worry, it can be done easily.

Create a Service Running the Helper

sudo nano /etc/systemd/system/windscribe-helper.service
Enter fullscreen mode Exit fullscreen mode

Inside the file:

[Unit]
Description=Start Windscribe VPN Helper
After=network-online.target
Wants=network-online.target
RequiresMountsFor=%t/containers
StartLimitIntervalSec=30
StartLimitBurst=5

[Service]
Type=exec
ExecStartPre=/bin/podman start vpn-dbx--root
ExecStart=/bin/podman exec vpn-dbx--root bash -c "/opt/windscribe/helper"
Restart=on-failure
RestartSec=5
RemainAfterExit=yes
Enter fullscreen mode Exit fullscreen mode

Create a Timer Triggering the Helper Service

sudo nano /etc/systemd/system/windscribe-helper.timer
Enter fullscreen mode Exit fullscreen mode

Inside the file:

[Unit]
Description=A trigger to start Windscribe's helper on startup

[Timer]
OnBootSec=25
RandomizedDelaySec=10

[Install]
WantedBy=timers.target
Enter fullscreen mode Exit fullscreen mode

Reload and Enable the Timer

sudo systemctl daemon-reload && sudo systemctl enable --now windscribe-helper.timer
Enter fullscreen mode Exit fullscreen mode

The helper is now running in the background πŸ‘Ÿ


6. Create a Launcher Script πŸš€ and a Desktop File πŸ–₯️ on the Host

It wouldn't be practical if you have to manually type a lengthy command in the terminal just to open a VPN client πŸ˜†

There are extra steps we will have to do to circumvent the security of our rootful container. But no worry, I will NOT do it in a way that compromises the security, as it's there for a reason.

I will simply use a wrapper script to launch the client. Then, put the script in a desktop file, so we can launch the app by clicking at a beautiful app icon like any other apps on your system.

The Wrapper Script

nano ~/.local/bin/windscribe-launcher.sh
Enter fullscreen mode Exit fullscreen mode

Inside the file:

#!/bin/bash

# Define container name and flag file
CONTAINER_NAME="vpn-dbx--root"
READY_FLAG="/tmp/${CONTAINER_NAME}-ready.flag"

# Define the app's binary path and its StartupWMClass name
# The StartupWMClass has to be set up correctly. On GNOME, use Alt+F2 then lg to check the correct StartupWMClass of any app
APP_BINARY_PATH="/opt/windscribe/Windscribe"
APP_STARTUP_WM_CLASS_NAME="Windscribe"

: <<'SYSTEM_SERVICE_FILE_SECTION'
If you don't use/enable the system service file,
or you don't want to check whether it's running,
you can safely remove this whole section.
SYSTEM_SERVICE_FILE_SECTION

APP_HELPER_SERVICE_NAME="windscribe-helper.service"

# If invoked with "launch" argument, skip service start and proceed
if [ "$1" = "launch" ]; then
    shift
else
    # Check if the service is active (system service)
    if ! systemctl is-active -q ${APP_HELPER_SERVICE_NAME}; then
        echo "$APP_HELPER_SERVICE_NAME is not active. Attempting to start it..."
        if [ "$(id -u)" -eq 0 ]; then
            # Start directly
            if systemctl start ${APP_HELPER_SERVICE_NAME}; then
                echo "$APP_HELPER_SERVICE_NAME started successfully (as root)."
            else
                echo "Failed to start $APP_HELPER_SERVICE_NAME (as root)."
                exit 1
            fi
            # Drop back to original user and re-run
            exec runuser -u "${SUDO_USER:-$USER}" -- "$0" launch
        else
            # Use pkexec with retries
            MAX_RETRIES=3
            ATTEMPT=1
            while [ $ATTEMPT -le $MAX_RETRIES ]; do
                if pkexec systemctl start ${APP_HELPER_SERVICE_NAME}; then
                    echo "$APP_HELPER_SERVICE_NAME started successfully."
                    break
                else
                    echo "Failed to start $APP_HELPER_SERVICE_NAME (attempt $ATTEMPT/$MAX_RETRIES)."
                    ATTEMPT=$((ATTEMPT + 1))
                fi
            done
            if [ $ATTEMPT -gt $MAX_RETRIES ]; then
                echo "Exceeded maximum retries. Exiting."
                exit 1
            fi
        fi
        # Re-execute to separate pkexec calls
        exec "$0" launch
    fi
fi

### End of SYSTEM_SERVICE_FILE_SECTION

# Check if the systemd scope is active (indicating the app is running)
if systemctl --user is-active -q ${APP_STARTUP_WM_CLASS_NAME}.scope; then
    # Check if there's an existing app's window
    exists=$(gdbus call --session --dest org.gnome.Shell --object-path /org/gnome/Shell --method org.gnome.Shell.Eval "
    global.get_window_actors()
        .map(a => a.meta_window)
        .some(w => w.get_wm_class() === '$APP_STARTUP_WM_CLASS_NAME');" | grep -o 'true')

    if [ "$exists" = "true" ]; then
        # Activate the existing window
        gdbus call --session --dest org.gnome.Shell --object-path /org/gnome/Shell --method org.gnome.Shell.Eval "
        const window = global.get_window_actors()
            .map(a => a.meta_window)
            .find(w => w.get_wm_class() === '$APP_STARTUP_WM_CLASS_NAME');
        if (window) {
            window.activate(global.get_current_time());
        }"
    else
        # No window but scope active: Send resume command to persistent screen session (no prompt)
        screen -S ${APP_STARTUP_WM_CLASS_NAME}-dbx -p 0 -X stuff "${APP_BINARY_PATH}\r"
    fi
    exit 0
fi

# If scope not active, ensure persistent screen session for container entry
if ! screen -ls | grep -q "${APP_STARTUP_WM_CLASS_NAME}-dbx"; then
    # Clean up any old flag (optional, for safety)
    rm -f "$READY_FLAG"

    # Start detached screen session that enters the container and signals readiness (pkexec prompt for graphically auth)
    # The command runs ONLY after the container is ready: touch the flag, then keep the session open with bash
    screen -dmS ${APP_STARTUP_WM_CLASS_NAME}-dbx sh -c "DBX_SUDO_PROGRAM=pkexec distrobox-enter -r $CONTAINER_NAME -- bash -c 'touch $READY_FLAG && bash'"

    # Wait for the flag file to appear (poll with a timeout for safety)
    TIMEOUT=60 # Max seconds to wait
    ELAPSED=0
    while [ ! -f "$READY_FLAG" ]; do
        if [ "$ELAPSED" -ge "$TIMEOUT" ]; then
            echo "Timeout: Container did not become ready in $TIMEOUT seconds."
            # Optional: Kill the screen session if timed out
            screen -S ${APP_STARTUP_WM_CLASS_NAME}-dbx -X quit
            exit 1
        fi
        sleep 1
        ELAPSED=$((ELAPSED + 1))
    done

    # Container is ready! Clean up the flag and proceed
    rm -f "$READY_FLAG"
    echo "Container is ready. Running next command..."
fi

# Send the initial launch command to the screen session
screen -S ${APP_STARTUP_WM_CLASS_NAME}-dbx -p 0 -X stuff "systemd-run --scope --user --unit=${APP_STARTUP_WM_CLASS_NAME}.scope $APP_BINARY_PATH &\r"

exit 0
Enter fullscreen mode Exit fullscreen mode

Explanation πŸ€“

If you need it, this script works with any app in a rootful container. Here are all the variables you can change at the top of the script:

  • CONTAINER_NAME, as the name suggests.
  • READY_FLAG is used to check the readiness of the container.
  • APP_BINARY_PATH is the binary path of the app you want to use. In this case, it's /opt/windscribe/Windscribe.
  • APP_STARTUP_WM_CLASS_NAME is the StartupWMClass of the app. It has to be set up correctly. On GNOME, use Alt+F2 then lg to check the correct StartupWMClass of any app.
  • APP_HELPER_SERVICE_NAME is the file name of the helper service we have created in the previous step. You don't have to wait for the helper to start, if you're in such a hurry, you can launch the app whenever you want, the script will help you launch the helper too if it's not already running!

Thanks to systemd-run and its scope unit, we can check easily whether the app's running, then use different commands to activate the app's window. I would say, not only this is native, but cleaner and more reliable than any other methods.

Then, I use gdbus to manipulate the state of the app's window. This is a native way on GNOME, so it works seamlessly on GNOME, but I don't know about the compatibility with other desktop environments.

But as I don't use other DEs, I wouldn't dare to publish the code that I didn't test or have any idea of. Therefore, if any of you have any idea on how to make it work with other DEs like KDE, COSMIC DE, or even tiling window managers like Hyprland, Niri, etc., please comment down below with a working script.

I also use screen to have a persistent session for distrobox-enter -r to our rootful container, so we don't have to enter our sudo password every single time we click on the app's icon πŸ˜‚

The Desktop File

nano ~/.local/share/applications/windscribe.desktop
Enter fullscreen mode Exit fullscreen mode

Inside the file:

[Desktop Entry]
Type=Application
Icon=/var/home/archerallstars/.local/share/icons/windscribe.png
Name=Windscribe
Comment=Start Windscribe VPN
Keywords=vpn;windscribe
Exec=/bin/bash /var/home/archerallstars/.local/bin/windscribe-launcher.sh
StartupWMClass=Windscribe
Terminal=false
Enter fullscreen mode Exit fullscreen mode

⚠️ Replace /var/home/archerallstars with your host system's $HOME absolute path (the path without ~).

πŸ’‘ You can download the app icon easily from the Play Store πŸ›οΈ Then, replace the icon's path on the above with your icon's absolute path.

Now, you have the client 100% fully working!

The client screenshot

You can check your public IP address and DNS resolver to see if they're matched with the ones showing in your Windscribe client, and also to see if there's any DNS leak by using https://dnscheck.tools/

For what it's worth, you might want to change your systemd-resolved's DNS over TLS setting to opportunistic, so it won't interfere with your VPN's DNS setup.

sudo nano /etc/systemd/resolved.conf
Enter fullscreen mode Exit fullscreen mode

Then, in the file:

[Resolve]
DNSOverTLS=opportunistic
Enter fullscreen mode Exit fullscreen mode

Lastly, restart systemd-resolved:

sudo systemctl restart systemd-resolved
Enter fullscreen mode Exit fullscreen mode

7. Make the Container Update Itself Automatically, Zero Maintenance! 😍

Create a Service File

sudo nano /etc/systemd/system/vpn-dbx-upgrade.service
Enter fullscreen mode Exit fullscreen mode

In the file:

[Unit]
Description=Upgrade vpn-dbx--root
After=network-online.target
Wants=network-online.target
RequiresMountsFor=%t/containers
StartLimitIntervalSec=600
StartLimitBurst=5

[Service]
Type=exec
ExecStartPre=/bin/podman start vpn-dbx--root
ExecStart=/bin/podman exec vpn-dbx--root bash -c "apt update -y && apt full-upgrade -y"
Restart=on-failure
RestartSec=60
RemainAfterExit=yes
Enter fullscreen mode Exit fullscreen mode

Create a Timer File

sudo nano /etc/systemd/system/vpn-dbx-upgrade.timer
Enter fullscreen mode Exit fullscreen mode

In the file:

[Unit]
Description=Upgrade vpn-dbx--root daily.

[Timer]
OnCalendar=daily
Persistent=true
RandomizedDelaySec=5min

[Install]
WantedBy=timers.target
Enter fullscreen mode Exit fullscreen mode

Reload and Enable the Timer

sudo systemctl daemon-reload && sudo systemctl enable vpn-dbx-upgrade.timer
Enter fullscreen mode Exit fullscreen mode

Config Your Firewall πŸ”₯ to Have Port Forwarding πŸ”Œ Working Correctly

A WiFi Device

It depends on your host's firewall. For example, Ubuntu uses ufw, Fedora uses firewalld.


For ufw System

Check your firewall status:

sudo ufw status verbose
Enter fullscreen mode Exit fullscreen mode

If it's enabled, you will need to open the correct port that you've opened in your Windscribe account's port forwarding page:

sudo ufw allow <port>/tcp && sudo ufw allow <port>/udp
Enter fullscreen mode Exit fullscreen mode

⚠️ Change to your desired port number.


For firewalld System

1. Create a New Zone in firewalld

List all the available zones:

firewall-cmd --get-zones
Enter fullscreen mode Exit fullscreen mode

We will create a new zone called vpn, if it's not presented yet, create a new one:

sudo firewall-cmd --permanent --new-zone=vpn
Enter fullscreen mode Exit fullscreen mode

Reload firewalld for it to take effect:

sudo firewall-cmd --reload
Enter fullscreen mode Exit fullscreen mode

Check all the available zones again:

firewall-cmd --get-zones
Enter fullscreen mode Exit fullscreen mode

Now, vpn should be listed as one of the zones.


2. Finding the Interface's Name Using Network Manager

⚠️ It's possible to add a new interface to firewalld's zones using the Network Manager, but it'll be conflicted with how Windscribe's client manages the network. Therefore, you should use firewalld to manage its firewall's rules. Never use the Network Manager to manage your firewall rules!

firewalld, however, only knows and manages the interfaces that are bound to one of its zones. It cannot see any newly created interfaces that have never been introduced to it. Therefore, we use the Network Manager to list all the active interfaces on our system instead.

Finding your active connection name first:

nmcli connection show --active
Enter fullscreen mode Exit fullscreen mode

It will return something like:

NAME                UUID                           TYPE  DEVICE 
YourConnectionName  xxxxxxxxxxxxxxxxxxxxxxxxxxxxx  wifi  xxxxxx
Enter fullscreen mode Exit fullscreen mode

Note down your connection name. Usually, it will be something that has tun it its name. If you have connected to the VPN network, you can use an app like Resources to know the name for sure.


3. Adding the Interface to firewalld Permanently

sudo firewall-cmd --zone=vpn --change-interface='YourConnectionName' --permanent
Enter fullscreen mode Exit fullscreen mode

Reload the firewall (to apply the change):

sudo firewall-cmd --reload
Enter fullscreen mode Exit fullscreen mode

Also, check whether the interface is already in firewalld's zone (it should):

firewall-cmd --zone=vpn --list-interfaces
Enter fullscreen mode Exit fullscreen mode

4. Adding the Required Ports to firewalld's Zone Permanently

List all the rules in vpn zone:

firewall-cmd --zone=vpn --list-all
Enter fullscreen mode Exit fullscreen mode

πŸ’‘ If it doesn't show any port number after the ports: entry, this means firewalld is blocking all incoming ports in this zone (vpn).

You can add your port like this:

sudo firewall-cmd --permanent --zone=vpn --add-port=<yourport>/tcp
sudo firewall-cmd --permanent --zone=vpn --add-port=<yourport>/udp
Enter fullscreen mode Exit fullscreen mode

⚠️ Replace <yourport> with the port you want to allow in the firewall.

Reload the firewall (to apply the change):

sudo firewall-cmd --reload
Enter fullscreen mode Exit fullscreen mode

If you want to remove the port, since most of you would use an ephemeral port anyway:

sudo firewall-cmd --zone=public --remove-port=<yourport>/tcp --permanent
sudo firewall-cmd --zone=public --remove-port=<yourport>/udp --permanent
Enter fullscreen mode Exit fullscreen mode

⚠️ Replace <yourport> with the port you want to allow in the firewall.


πŸ˜… firewalld is very complicate. If you can't connect with your local devices, you need to add mDNS and process forwarded traffic into this new vpn zone. It's the default public zone settings in Fedora that works for me with an app like LocalSend, for example.

sudo firewall-cmd --permanent --zone=vpn --add-service=mdns
Enter fullscreen mode Exit fullscreen mode
sudo firewall-cmd --permanent --zone=vpn --add-forward
Enter fullscreen mode Exit fullscreen mode
sudo firewall-cmd --reload
Enter fullscreen mode Exit fullscreen mode

Check the Reach-ability of Your Opened Port πŸ”οΈ

A Hand

First, please don't use any of the online port checkers like portchecker.co, for example. It never works for me...

The reliable way to test the reach-ability of your opened port is through torrent clients like Fragments, for example:

Fragments Port Test 1

Fragments Port Test 2


For Headless Folks

You can use this command to check the reach-ability of your opened port in the terminal like this:

p=<port_number>; curl -s https://portcheck.transmissionbt.com/$p | grep -q '^1' && echo -e "\033[1;32mβœ… Port $p is OPEN\033[0m" || echo -e "\033[1;31m❌ Port $p is CLOSED\033[0m"
Enter fullscreen mode Exit fullscreen mode

⚠️ Please change the <port_number> to the one you want to check.

This will return:

βœ… Port XXXXX is OPEN
Enter fullscreen mode Exit fullscreen mode

Or:

❌ Port XXXXX is CLOSED
Enter fullscreen mode Exit fullscreen mode

😱 Limitations

A Workplace

App-based Split Tunneling πŸͺ“

πŸ’‘ It should be noted that while we need to work around the app-based split tunneling, IP-based split tunneling is fully working. You can check your current IP routing table with ip route show command. The client's GUI simply routes your desired IPs using the routing table.

The issue with the app-based split tunneling is expected, as we install the client in a container, so there's a layer of separation, even for a rootful container. Therefore, the client doesn't see any of your apps on the host or in other containers.

But no worry! This is a soft limitation, not a hard one or a blocker.


Solution βœ…οΈ

If you really need this functionality, you can install the client in a rootless container with distrobox-create command's --unshare-netns option.

Basically, all routing, interfaces, and VPN tunnels stay confined to the container's network, so the VPN connection stay inside the container and won't be routed on the host, as the container simply lacks the capability/permission to do so.

You can create a container for the apps that you want to connect through the VPN, while leaving your host's connection outside the VPN tunnel. This behavior is exactly the same with Windscribe client's split tunneling in the inclusive mode:

⚠️ Please enable your Windscribe's VPN connection before creating a container. Because pasta, the new podman (v5.3+) container's network interface, even though it's a lot faster than before, it will only capture your host's current DNS addresses into the container.

πŸ’‘ You can also specify multiple DNS addresses using distrobox-create's --additional-flags "--dns 1.1.1.1 --dns 9.9.9.9", for example. If you use this flag, remember to also include at least one public DNS resolver, so you always have the connection.

✍️ Without the --dns flag, pasta will create a DNS forwarding entry, so whatever your host DNS is, it will be used in the container dynamically.

⚠️ The VPN client can only use the DNS as per pasta's snapshot inside the container in /etc/resolv.conf (changing this later on won't have any effects). Therefore, if the VPN's DNS address wasn't there from the start, it would regress back to your current DNS resolver on the host (through pasta's DNS forwarding entry), hence leaking. In that case, please re-create the container again when you have the VPN connection up on the host πŸ˜…

✍️ Otherwise, you can create an init container with its own systemd-resolved and all, but it won't integrate well with the host. Therefore, I don't recommend this route.

Now, finally, we can create a VPN only container:

distrobox-create -i registry.opensuse.org/opensuse/distrobox:latest -n vpn-apps-dbx -H ~/distrobox/vpn-apps-dbx --unshare-netns --volume /run/dbus/system_bus_socket:/run/dbus/system_bus_socket --additional-packages "libnl3-200 libxkbcommon-x11-0 libxcb-icccm4 libxcb-keysyms1 NetworkManager" --additional-flags "-p 127.0.0.1::57383"
Enter fullscreen mode Exit fullscreen mode
  • Now, I use the openSUSE image instead of Ubuntu image, as a rolling release container is much easier to maintain, or rather, to not having to maintain anything πŸ˜‚

  • --unshare-netns so we use the container's network interface instead of the host's network interface (--network=host).

  • -p 127.0.0.1::57383 is basically tell podman that only your host can talk to the container directly. Otherwise, others on the internet can bypass your host's firewall and talk to your container directly, hence a significant security risk. This is something you'll have to be careful when using the container's network interface (pasta) instead of --network=host. You can use any port number with -p 127.0.0.1::<container-port>.

🀩 With a rootless container, you would be able to upgrade all your containers at once by using the distrobox-upgrade --all command. Make it run daily in the background using a --user systemd service, like I wrote here, for example. Moreover, You can use Pods to manage your rootless containers beautifully:

Pods

The rest of the setup is the same as with a rootful container, except now, you don't have to circumvent the security of a rootful container. Meaning, everything works OOTB without the wrapper script.

⚠️ Remember that /opt/windscribe/helper have to be run with sudo, so when you export it with distrobox-export don't forget to add --sudo flag. And now that this is a rootless container, remember to use a systemd's --user service, not the root one (without the --user flag), to launch it on the container's start up.

After you set everything up and running, provided you set up your firewall correctly, you can check your opened port forwarding by using Transmission in the container:

Transmission


A Container-safe πŸ‘· Startup Delay

This is unfortunately, a hard limitation. There's nothing we can do about it. I put some delay in all my containers' initial process. I use 25 seconds delay for the client's helper here.

Otherwise, the system's booting process could crash entirely due to early-boot dependency race with the container runtime, storage, networking, or cgroup/setup layers.

See more here.


Solution βœ…οΈ

We can simply install all of the apps that we want to have the VPN connection at all time inside a rootless container, as shown on the above.

With this solution, there will be no leak, as you have orderly control when launching the apps inside the container using systemd's After= and Requires= directives.

Therefore, it doesn't matter if you can't have the VPN connection right away on startup.


Thanks for reading πŸ€“


Cover Photo by Thomas Richter on Unsplash

A Container Photo by Sophie Cardinale on Unsplash

A WiFi Device Photo by Amal S on Unsplash

A Hand Photo by Frankie Mish on Unsplash

A Workplace Photo by ryu _ on Unsplash

Top comments (0)