Modern container runtimes like Docker, Podman, and containerd rely directly on Linux kernel namespaces to isolate system resources—including process tables, network interfaces, filesystem mount points, and user IDs. While these container managers abstract lower-level mechanics, Linux includes a native utility called unshare that allows administrators, developers, and security auditors to detach process execution contexts from their parent system directly from the terminal without deploying full container engines.
Understanding Linux Kernel Namespaces
Namespaces partition global system resources so that a group of processes perceives a dedicated, isolated instances of the system. The Linux kernel supports several distinct namespace domains:
- Mount (mnt): Isolates filesystem mount tables and volume points.
- Process ID (pid): Isolates the process ID space, allowing a child process to act as PID 1 inside its domain.
- Network (net): Isolates network interfaces, routing tables, and firewall rules.
- Interprocess Communication (ipc): Isolates POSIX message queues and System V IPC mechanisms.
- UTS: Isolates system hostnames and NIS domain names.
- User (user): Maps internal root privileges (UID 0) to an unprivileged user on the host system, enabling rootless isolation.
Using unshare with User Namespaces for Rootless Isolation
Traditionally, isolating filesystem mounts or system hostnames required elevated sudo permissions. Combining unshare with the --user and --map-root-user flags permits standard, unprivileged users to simulate root actions inside an isolated boundary without compromising host security:
unshare --user --map-root-user /bin/bash
Inside the resulting sub-shell, execute:
whoami
id
Notice that id returns uid=0(root) gid=0(root). However, exiting this sub-shell (type exit) returns you to your regular user context. The simulated root user cannot alter protected system files on the host drive.
Creating an Isolated Network Namespace
Testing application behaviour on clean network stacks—without default route interference or existing listening ports—is achieved by combining network and user namespaces:
unshare --user --map-root-user --net /bin/bash
Inside this isolated environment, query your available network interfaces:
ip link show
Notice that external interfaces (such as eth0 or wlan0) do not appear; only an unconfigured loopback interface is present. Bring up the loopback interface:
ip link set dev lo up
ip addr show
You can now bind network daemons to local ports for sandboxed integration testing without exposing ports to your LAN or conflicting with host services.
Isolating Mount Points and Creating a Private /tmp Directory
To run untrusted scripts or build jobs that must write temporary files without polluting or reading the host system’s /tmp partition, detach the mount namespace and mount a clean memory-backed temporary filesystem:
unshare --user --map-root-user --mount /bin/bash
Inside the new shell, remount a dedicated tmpfs over /tmp:
mount -t tmpfs none /tmp
echo "Confidential session data" > /tmp/test_isolated.txt
ls -l /tmp
Open a secondary terminal on your host machine and verify ls -l /tmp/test_isolated.txt. The file is completely invisible and inaccessible to any process outside that specific mount namespace.
Isolating Process Trees with a New PID 1
To run an application in an environment where it cannot inspect or signal any processes running on the host system, spawn an isolated PID namespace using the --pid and --fork options:
unshare --user --map-root-user --pid --mount --fork /bin/bash
Mount a dedicated pseudo-filesystem (proc) inside the namespace so utilities like ps only inspect the sandboxed container:
mount -t proc none /proc
ps aux
You will observe that your initial sub-shell operates as PID 1, with no exposure to background systemd services or user daemons active on the physical host machine.
Automating Ephemeral Sandboxes with One-Liner Commands
Rather than launching interactive sub-shells, you can wrap automated scripts or command invocations directly within unshare:
unshare -Urnm /bin/sh -c "mount -t tmpfs none /tmp && python3 /path/to/script.py"
The short-form flags represent:
-U:--user(unprivileged user isolation)-r:--map-root-user(map current user to root in the namespace)-n:--net(isolated network stack)-m:--mount(private filesystem mount table)
When the target command finishes execution, all namespace boundaries collapse immediately, releasing allocated memory and temporary mounts cleanly.