Run any Linux process in a secure, unprivileged sandbox using Landlock. Think firejail, but lightweight, user-friendly, and baked into the kernel.
Go
2,317
112 commits
updated Jul 23, 2026
A lightweight, secure sandbox for running Linux processes using Landlock. Think firejail, but with kernel-level security and minimal overhead.
Linux Landlock is a kernel-native security module that lets unprivileged processes sandbox themselves.
Landrun is designed to make it practical to sandbox any command with fine-grained filesystem and network access controls. No root. No containers. No SELinux/AppArmor configs.
It's lightweight, auditable, and wraps Landlock up to v9 features (file access, TCP restrictions, IPC scoping, and UNIX-socket controls).
By default landrun targets the highest Landlock ABI (v9). On older kernels, pass
--best-effortso it gracefully degrades to the best ABI the running kernel supports (see Best-Effort Mode).
go install github.com/zouuup/landrun/cmd/landrun@latest
git clone https://github.com/zouuup/landrun.git
cd landrun
go build -o landrun cmd/landrun/main.go
sudo cp landrun /usr/local/bin/
maintained by r1w1s1
sudo sbopkg -i packagename
Available in Ubuntu since questing / resolute (26.04 LTS), available in Debian since forky.
sudo apt install landrun
Basic syntax:
landrun [options] <command> [args...]
--ro <path>: Allow read-only access to specified path (can be specified multiple times or as comma-separated values)--rox <path>: Allow read-only access with execution to specified path (can be specified multiple times or as comma-separated values)--rw <path>: Allow read-write access to specified path (can be specified multiple times or as comma-separated values)--rwx <path>: Allow read-write access with execution to specified path (can be specified multiple times or as comma-separated values)--unix <path>: Allow connect(2)/sendmsg(2) on the specified pathname UNIX domain socket (Landlock ABI v9+; can be specified multiple times or as comma-separated values)--bind-tcp <port>: Allow binding to specified TCP port (can be specified multiple times or as comma-separated values)--connect-tcp <port>: Allow connecting to specified TCP port (can be specified multiple times or as comma-separated values)--env <var>: Environment variable to pass to the sandboxed command (format: KEY=VALUE or just KEY to pass current value)--best-effort: Use best effort mode, falling back to less restrictive sandbox if necessary [default: disabled]--log-level <level>: Set logging level (error, info, debug) [default: "error"]--unrestricted-network: Allows unrestricted network access (disables all network restrictions)--unrestricted-filesystem: Allows unrestricted filesystem access (disables all filesystem restrictions)--unrestricted-scoped: Allows unrestricted IPC scoping, i.e. does not restrict abstract UNIX sockets and signals (Landlock ABI v6+) [default: disabled]--ignore-missing: Gracefully ignore paths that do not exist instead of failing [default: disabled]--log-disable-originating: Disable audit logging of denials from the originating process (Landlock ABI v7+)--log-enable-subprocesses: Enable audit logging of denials after execve(2) in subprocesses (Landlock ABI v7+)--log-disable-subdomains: Disable audit logging of denials from nested Landlock domains (Landlock ABI v7+)--add-exec: Automatically adds the executing binary to --rox--ldd: Automatically adds required libraries to --rox--rox flag/usr/bin, /usr/lib, and other system directories--rwx for directories or files where you need both write access and the ability to execute files--env to explicitly pass environment variables--best-effort flag allows graceful degradation on older kernels that don't support all requested restrictions. Because the default target is Landlock ABI v9, you will usually want --best-effort unless you are on a very recent kernel--ro /usr,/lib,/home)--unrestricted-scoped if this breaks your workload (e.g. some X11 or D-Bus setups)nscd, D-Bus, database sockets) is restricted. Grant access to specific sockets with --unix <path>LANDRUN_LOG_LEVEL: Set logging level (error, info, debug)landrun --rox /usr/bin/ls --rox /usr/lib --ro /home ls /home
landrun --rox /usr/ --ro /path/to/dir ls /path/to/dir
landrun --rox /usr/bin --ro /lib --rw /path/to/dir touch /path/to/dir/newfile
landrun --rox /usr/bin --ro /lib --rw /path/to/dir/newfile touch /path/to/dir/newfile
landrun --rox /usr/ --ro /lib,/lib64 /usr/bin/bash
landrun --log-level debug --rox /usr/ --ro /lib,/lib64,/path/to/dir ls /path/to/dir
landrun --rox /usr/ --ro /lib,/lib64 --bind-tcp 8080 --connect-tcp 80 /usr/bin/my-server
This will allow the program to only bind to TCP port 8080 and connect to TCP port 80.
landrun --log-level debug --ro /etc,/usr --rox /usr/ --connect-tcp 443 nc kernel.org 443
This allows connections to port 443, requires access to /etc/resolv.conf for resolving DNS.
landrun --rox /usr/bin --ro /lib,/lib64,/var/www --rwx /var/log --bind-tcp 80,443 /usr/bin/nginx
landrun ls
landrun --rox /usr strace -f -e trace=all ls
landrun --rox /usr --ro /etc --env HOME --env PATH --env CUSTOM_VAR=my_value -- env
This example passes the current HOME and PATH variables, plus a custom variable named CUSTOM_VAR.
landrun --rox /usr/lib/libc.so.6 --rox /usr/lib64/ld-linux-x86-64.so.2 --rox /usr/bin/true /usr/bin/true
landrun --rox /usr/lib/ --add-exec /usr/bin/true
landrun --ldd --add-exec /usr/bin/true
Note that shared libs always need exec permission due to how they are loaded, PROT_EXEC on mmap() etc.
landrun --best-effort --rox /usr --ro /etc --unix /run/postgresql/.s.PGSQL.5432 -- psql ...
landrun --best-effort --ignore-missing --rox /usr --ro /etc,/opt/optional-config -- myapp
landrun --best-effort --unrestricted-scoped --rox /usr --ro /etc -- some-gui-app
landrun can be integrated with systemd to run services with enhanced security. Here's an example of running nginx with landrun:
/etc/systemd/system/nginx-landrun.service):[Unit]
Description=nginx with landrun sandbox
After=network.target
[Service]
Type=simple
ExecStart=/usr/bin/landrun \
--best-effort \
--rox /usr/bin,/usr/lib \
--ro /etc/nginx,/etc/ssl,/etc/passwd,/etc/group,/etc/nsswitch.conf \
--rwx /var/log/nginx \
--rwx /var/cache/nginx \
--bind-tcp 80,443 \
/usr/bin/nginx -g 'daemon off;'
Restart=always
User=nginx
Group=nginx
[Install]
WantedBy=multi-user.target
sudo systemctl daemon-reload
sudo systemctl enable nginx-landrun
sudo systemctl start nginx-landrun
sudo systemctl status nginx-landrun
This configuration:
You can adjust the permissions based on your specific needs. For example, if you need to serve static files from /var/www, add --ro /var/www to the ExecStart line.
landrun uses Linux's Landlock to create a secure sandbox environment. It provides:
Landlock is an access-control system that enables processes to securely restrict themselves and their future children. As a stackable Linux Security Module (LSM), it creates additional security layers on top of existing system-wide access controls, helping to mitigate security impacts from bugs or malicious behavior in applications.
landrun leverages Landlock's fine-grained access control mechanisms, which include:
File-specific rights:
LANDLOCK_ACCESS_FS_EXECUTE)LANDLOCK_ACCESS_FS_WRITE_FILE)LANDLOCK_ACCESS_FS_READ_FILE)LANDLOCK_ACCESS_FS_TRUNCATE) - Available since Landlock ABI v3LANDLOCK_ACCESS_FS_IOCTL_DEV) - Available since Landlock ABI v5LANDLOCK_ACCESS_FS_RESOLVE_UNIX) - Available since Landlock ABI v9 (granted per-path with --unix)Directory-specific rights:
LANDLOCK_ACCESS_FS_READ_DIR)LANDLOCK_ACCESS_FS_REMOVE_DIR)LANDLOCK_ACCESS_FS_REMOVE_FILE)LANDLOCK_ACCESS_FS_REFER) - Available since Landlock ABI v2Network-specific rights (requires Linux 6.7+ with Landlock ABI v4):
LANDLOCK_ACCESS_NET_BIND_TCP)LANDLOCK_ACCESS_NET_CONNECT_TCP)IPC scoping (requires Linux 6.12+ with Landlock ABI v6):
LANDLOCK_SCOPE_ABSTRACT_UNIX_SOCKET)LANDLOCK_SCOPE_SIGNAL)These are restricted by default and can be relaxed with --unrestricted-scoped.
net.Listen defaults to Multipath TCP and therefore cannot currently be restricted by Landlock (kernel bug landlock-lsm/linux#54)| Feature | Minimum Kernel Version | Landlock ABI Version |
|---|---|---|
| Basic filesystem sandboxing | 5.13 | 1 |
| File referring/reparenting control | 5.19 | 2 |
| File truncation control | 6.2 | 3 |
| Network TCP restrictions | 6.7 | 4 |
| IOCTL on special files | 6.10 | 5 |
| IPC scoping (abstract UNIX sockets, signals) | 6.12 | 6 |
| Audit logging of denials | 6.15 | 7 |
| Thread synchronization (TSYNC) | 7.0 | 8 |
| Pathname UNIX socket connect/sendmsg control | latest | 9 |
If you receive "permission denied" or similar errors:
--ro or --rw--log-level debug to see detailed permission informationgrep -E 'landlock|lsm=' /boot/config-$(uname -r)
# alternatively, if there are no /boot/config-* files
zgrep -iE 'landlock|lsm=' /proc/config.gz
# another alternate method
grep -iE 'landlock|lsm=' /lib/modules/$(uname -r)/config
You should see CONFIG_SECURITY_LANDLOCK=y and lsm=landlock,... in the outputuname -r
This project uses the landlock-lsm/go-landlock package (v0.9.0) for sandboxing, which provides filesystem, network and IPC-scope restrictions. The current implementation targets Landlock ABI v9 and supports:
--unix)--log-*)--ignore-missing)By default, landrun targets the highest Landlock ABI (v9) in strict mode, so on any kernel that does not support v9 it will fail unless --best-effort is used.
When using --best-effort (disabled by default), landrun will gracefully degrade to using the best available Landlock version on the current kernel. This means:
When no rules are specified and neither unrestricted flag is set, landrun will apply maximum restrictions available for the current kernel version.
The project includes a comprehensive test suite that verifies:
Run the tests with:
./test.sh
Use --keep-binary to preserve the test binary after completion:
./test.sh --keep-binary
Use --use-system to test against the system-installed landrun binary:
./test.sh --use-system
Based on the Linux Landlock API capabilities, we plan to add:
This project wouldn't exist without:
Contributions are welcome! Please feel free to submit a Pull Request.
(top 24 of 117)
3,108 followers Β· starred Mar 2025
1,020 followers Β· starred Oct 2025
297 followers Β· starred Oct 2025
1,034 followers Β· starred Nov 2025
Run any Linux process in a secure, unprivileged sandbox using Landlock. Think firejail, but lightweight, user-friendly, and baked into the kernel.
Go
2,317
112 commits
updated Jul 23, 2026
A lightweight, secure sandbox for running Linux processes using Landlock. Think firejail, but with kernel-level security and minimal overhead.
Linux Landlock is a kernel-native security module that lets unprivileged processes sandbox themselves.
Landrun is designed to make it practical to sandbox any command with fine-grained filesystem and network access controls. No root. No containers. No SELinux/AppArmor configs.
It's lightweight, auditable, and wraps Landlock up to v9 features (file access, TCP restrictions, IPC scoping, and UNIX-socket controls).
By default landrun targets the highest Landlock ABI (v9). On older kernels, pass
--best-effortso it gracefully degrades to the best ABI the running kernel supports (see Best-Effort Mode).
go install github.com/zouuup/landrun/cmd/landrun@latest
git clone https://github.com/zouuup/landrun.git
cd landrun
go build -o landrun cmd/landrun/main.go
sudo cp landrun /usr/local/bin/
maintained by r1w1s1
sudo sbopkg -i packagename
Available in Ubuntu since questing / resolute (26.04 LTS), available in Debian since forky.
sudo apt install landrun
Basic syntax:
landrun [options] <command> [args...]
--ro <path>: Allow read-only access to specified path (can be specified multiple times or as comma-separated values)--rox <path>: Allow read-only access with execution to specified path (can be specified multiple times or as comma-separated values)--rw <path>: Allow read-write access to specified path (can be specified multiple times or as comma-separated values)--rwx <path>: Allow read-write access with execution to specified path (can be specified multiple times or as comma-separated values)--unix <path>: Allow connect(2)/sendmsg(2) on the specified pathname UNIX domain socket (Landlock ABI v9+; can be specified multiple times or as comma-separated values)--bind-tcp <port>: Allow binding to specified TCP port (can be specified multiple times or as comma-separated values)--connect-tcp <port>: Allow connecting to specified TCP port (can be specified multiple times or as comma-separated values)--env <var>: Environment variable to pass to the sandboxed command (format: KEY=VALUE or just KEY to pass current value)--best-effort: Use best effort mode, falling back to less restrictive sandbox if necessary [default: disabled]--log-level <level>: Set logging level (error, info, debug) [default: "error"]--unrestricted-network: Allows unrestricted network access (disables all network restrictions)--unrestricted-filesystem: Allows unrestricted filesystem access (disables all filesystem restrictions)--unrestricted-scoped: Allows unrestricted IPC scoping, i.e. does not restrict abstract UNIX sockets and signals (Landlock ABI v6+) [default: disabled]--ignore-missing: Gracefully ignore paths that do not exist instead of failing [default: disabled]--log-disable-originating: Disable audit logging of denials from the originating process (Landlock ABI v7+)--log-enable-subprocesses: Enable audit logging of denials after execve(2) in subprocesses (Landlock ABI v7+)--log-disable-subdomains: Disable audit logging of denials from nested Landlock domains (Landlock ABI v7+)--add-exec: Automatically adds the executing binary to --rox--ldd: Automatically adds required libraries to --rox--rox flag/usr/bin, /usr/lib, and other system directories--rwx for directories or files where you need both write access and the ability to execute files--env to explicitly pass environment variables--best-effort flag allows graceful degradation on older kernels that don't support all requested restrictions. Because the default target is Landlock ABI v9, you will usually want --best-effort unless you are on a very recent kernel--ro /usr,/lib,/home)--unrestricted-scoped if this breaks your workload (e.g. some X11 or D-Bus setups)nscd, D-Bus, database sockets) is restricted. Grant access to specific sockets with --unix <path>LANDRUN_LOG_LEVEL: Set logging level (error, info, debug)landrun --rox /usr/bin/ls --rox /usr/lib --ro /home ls /home
landrun --rox /usr/ --ro /path/to/dir ls /path/to/dir
landrun --rox /usr/bin --ro /lib --rw /path/to/dir touch /path/to/dir/newfile
landrun --rox /usr/bin --ro /lib --rw /path/to/dir/newfile touch /path/to/dir/newfile
landrun --rox /usr/ --ro /lib,/lib64 /usr/bin/bash
landrun --log-level debug --rox /usr/ --ro /lib,/lib64,/path/to/dir ls /path/to/dir
landrun --rox /usr/ --ro /lib,/lib64 --bind-tcp 8080 --connect-tcp 80 /usr/bin/my-server
This will allow the program to only bind to TCP port 8080 and connect to TCP port 80.
landrun --log-level debug --ro /etc,/usr --rox /usr/ --connect-tcp 443 nc kernel.org 443
This allows connections to port 443, requires access to /etc/resolv.conf for resolving DNS.
landrun --rox /usr/bin --ro /lib,/lib64,/var/www --rwx /var/log --bind-tcp 80,443 /usr/bin/nginx
landrun ls
landrun --rox /usr strace -f -e trace=all ls
landrun --rox /usr --ro /etc --env HOME --env PATH --env CUSTOM_VAR=my_value -- env
This example passes the current HOME and PATH variables, plus a custom variable named CUSTOM_VAR.
landrun --rox /usr/lib/libc.so.6 --rox /usr/lib64/ld-linux-x86-64.so.2 --rox /usr/bin/true /usr/bin/true
landrun --rox /usr/lib/ --add-exec /usr/bin/true
landrun --ldd --add-exec /usr/bin/true
Note that shared libs always need exec permission due to how they are loaded, PROT_EXEC on mmap() etc.
landrun --best-effort --rox /usr --ro /etc --unix /run/postgresql/.s.PGSQL.5432 -- psql ...
landrun --best-effort --ignore-missing --rox /usr --ro /etc,/opt/optional-config -- myapp
landrun --best-effort --unrestricted-scoped --rox /usr --ro /etc -- some-gui-app
landrun can be integrated with systemd to run services with enhanced security. Here's an example of running nginx with landrun:
/etc/systemd/system/nginx-landrun.service):[Unit]
Description=nginx with landrun sandbox
After=network.target
[Service]
Type=simple
ExecStart=/usr/bin/landrun \
--best-effort \
--rox /usr/bin,/usr/lib \
--ro /etc/nginx,/etc/ssl,/etc/passwd,/etc/group,/etc/nsswitch.conf \
--rwx /var/log/nginx \
--rwx /var/cache/nginx \
--bind-tcp 80,443 \
/usr/bin/nginx -g 'daemon off;'
Restart=always
User=nginx
Group=nginx
[Install]
WantedBy=multi-user.target
sudo systemctl daemon-reload
sudo systemctl enable nginx-landrun
sudo systemctl start nginx-landrun
sudo systemctl status nginx-landrun
This configuration:
You can adjust the permissions based on your specific needs. For example, if you need to serve static files from /var/www, add --ro /var/www to the ExecStart line.
landrun uses Linux's Landlock to create a secure sandbox environment. It provides:
Landlock is an access-control system that enables processes to securely restrict themselves and their future children. As a stackable Linux Security Module (LSM), it creates additional security layers on top of existing system-wide access controls, helping to mitigate security impacts from bugs or malicious behavior in applications.
landrun leverages Landlock's fine-grained access control mechanisms, which include:
File-specific rights:
LANDLOCK_ACCESS_FS_EXECUTE)LANDLOCK_ACCESS_FS_WRITE_FILE)LANDLOCK_ACCESS_FS_READ_FILE)LANDLOCK_ACCESS_FS_TRUNCATE) - Available since Landlock ABI v3LANDLOCK_ACCESS_FS_IOCTL_DEV) - Available since Landlock ABI v5LANDLOCK_ACCESS_FS_RESOLVE_UNIX) - Available since Landlock ABI v9 (granted per-path with --unix)Directory-specific rights:
LANDLOCK_ACCESS_FS_READ_DIR)LANDLOCK_ACCESS_FS_REMOVE_DIR)LANDLOCK_ACCESS_FS_REMOVE_FILE)LANDLOCK_ACCESS_FS_REFER) - Available since Landlock ABI v2Network-specific rights (requires Linux 6.7+ with Landlock ABI v4):
LANDLOCK_ACCESS_NET_BIND_TCP)LANDLOCK_ACCESS_NET_CONNECT_TCP)IPC scoping (requires Linux 6.12+ with Landlock ABI v6):
LANDLOCK_SCOPE_ABSTRACT_UNIX_SOCKET)LANDLOCK_SCOPE_SIGNAL)These are restricted by default and can be relaxed with --unrestricted-scoped.
net.Listen defaults to Multipath TCP and therefore cannot currently be restricted by Landlock (kernel bug landlock-lsm/linux#54)| Feature | Minimum Kernel Version | Landlock ABI Version |
|---|---|---|
| Basic filesystem sandboxing | 5.13 | 1 |
| File referring/reparenting control | 5.19 | 2 |
| File truncation control | 6.2 | 3 |
| Network TCP restrictions | 6.7 | 4 |
| IOCTL on special files | 6.10 | 5 |
| IPC scoping (abstract UNIX sockets, signals) | 6.12 | 6 |
| Audit logging of denials | 6.15 | 7 |
| Thread synchronization (TSYNC) | 7.0 | 8 |
| Pathname UNIX socket connect/sendmsg control | latest | 9 |
If you receive "permission denied" or similar errors:
--ro or --rw--log-level debug to see detailed permission informationgrep -E 'landlock|lsm=' /boot/config-$(uname -r)
# alternatively, if there are no /boot/config-* files
zgrep -iE 'landlock|lsm=' /proc/config.gz
# another alternate method
grep -iE 'landlock|lsm=' /lib/modules/$(uname -r)/config
You should see CONFIG_SECURITY_LANDLOCK=y and lsm=landlock,... in the outputuname -r
This project uses the landlock-lsm/go-landlock package (v0.9.0) for sandboxing, which provides filesystem, network and IPC-scope restrictions. The current implementation targets Landlock ABI v9 and supports:
--unix)--log-*)--ignore-missing)By default, landrun targets the highest Landlock ABI (v9) in strict mode, so on any kernel that does not support v9 it will fail unless --best-effort is used.
When using --best-effort (disabled by default), landrun will gracefully degrade to using the best available Landlock version on the current kernel. This means:
When no rules are specified and neither unrestricted flag is set, landrun will apply maximum restrictions available for the current kernel version.
The project includes a comprehensive test suite that verifies:
Run the tests with:
./test.sh
Use --keep-binary to preserve the test binary after completion:
./test.sh --keep-binary
Use --use-system to test against the system-installed landrun binary:
./test.sh --use-system
Based on the Linux Landlock API capabilities, we plan to add:
This project wouldn't exist without:
Contributions are welcome! Please feel free to submit a Pull Request.
(top 24 of 117)
3,108 followers Β· starred Mar 2025
1,020 followers Β· starred Oct 2025
297 followers Β· starred Oct 2025
1,034 followers Β· starred Nov 2025