This memo is about running a systemd service isolated in a network namespace on linux, inside which a vlan interface has been moved.

Network setup

Create namespace

sudo ip netns add torrentns

Create the vlan interface

/etc/network/interfaces

auto enp5s0.33
iface enp5s0.33 inet manual
    post-up /root/bin/move-to-namespace enp5s0.33

helper script

#!/bin/bash
# Usage: move-to-namespace <iface>
set -e

iface="$1"
ns="torrentns"

# Create namespace if not exists
if ! ip netns list | grep -q "^$ns"; then
    ip netns add "$ns"
fi

# Move interface into namespace
ip link set "$iface" netns "$ns"

# Bring up interfaces inside namespace
ip netns exec "$ns" ip link set lo up
ip netns exec "$ns" ip link set "$iface" up

# Start DHCP client inside namespace
ip netns exec "$ns" dhclient -v "$iface"

# Optional: Set up DNS
mkdir -p /etc/netns/$ns
echo "nameserver 1.1.1.1" > /etc/netns/$ns/resolv.conf

Activation

run : sudo ifup enp5s0.33

check : sudo ip netns exec /bin/bash ip a

Service setup

Systemd will take care of starting the service on boot. Contrary to the default service definition, we’ll start with root to start the service inside the namespace, and rely on sudo to drop permissions.

sudo systemctl edit transmission-daemon

[Service]
# Clear the original ExecStart
ExecStart=
ExecStart=/usr/bin/ip netns exec torrentns /usr/bin/sudo -u debian-transmission /usr/bin/transmission-daemon -f --log-error

# Ensure the service runs as root to enter the namespace
User=root
Group=root

# Drop dangerous capabilities and tighten security
CapabilityBoundingSet=
NoNewPrivileges=true
ProtectSystem=full
ProtectHome=yes
PrivateTmp=yes