Complete tutorial on sandboxing in Linux with Firejail and more

Last update: 22/02/2026
Author Isaac
  • Sandboxing in Linux relies on namespaces, seccomp-BPF, MAC, and chroot to isolate processes and limit the impact of vulnerabilities.
  • Firejail offers a lightweight and simple way to jail desktop and server applications with predefined profiles and advanced options.
  • Tools like Bubblewrap, Flatpak, AppArmor, SELinux, and Kata Containers expand isolation possibilities in more complex scenarios.
  • Combining memory safety with sandboxing, as in the Fil-C and OpenSSH approach, provides defense in depth for critical applications.

Sandboxing in Linux

Securing your Linux applications has become almost mandatory if you browse websites full of aggressive advertising, run untrusted binaries, or manage services exposed to the internet. Although Linux is already a fairly robust system, the reality is that your browser, media players, or any network client can be the perfect entry point for malware, cryptojacking, or data theft if you don't properly isolate them.

In this comprehensive tutorial on Linux sandboxing with tools like Firejail, Bubblewrap, AppArmor, and kernel technologies, you'll see how process isolation really works, what security mechanisms the system uses (namespaces, seccomp-BPF, chroot, resource limits, etc.), and how you can practically combine them to minimize the impact of a potential exploit. The goal is for you to leave here with a clear understanding, ready-to-use examples, and a solid foundation for improving the security of your desktop and server applications.

How to use Firejail
Related articles:
How to use Firejail on Linux to isolate and protect applications

What is a sandbox in Linux and why should you use it?

When we talk about sandboxing in Linux, we mean running programs within a restricted environment , separate from the rest of the system, so that if something goes wrong (exploit, malware, malicious script on a website, etc.) the damage is confined within that "sandbox" and cannot easily affect the rest of the operating system, your documents, or other services.

This approach is especially useful for highly exposed applications , such as web browsers, email clients, messaging applications, torrent programs, media players, or network services accessible from the internet. In all these cases, the risk of them processing untrusted content is extremely high, so it makes sense to surround them with multiple layers of protection.

In Linux, modern sandboxing relies primarily on native kernel mechanisms : Linux namespaces , access control policies (MACs) such as AppArmor or SELinux, seccomp-BPF filters, restrictions with setrlimit, chroot, and execution under unprivileged users. Tools like Firejail, Bubblewrap, Flatpak, and even container systems like Docker rely on these fundamental building blocks.

It's also important to understand that memory safety and sandboxing are distinct but complementary concepts . A program can be written in a memory-safe language (or protected by a runtime that prevents typical C/C++ errors), but if it has full access to the file system and all system calls, it remains dangerous if someone manages to manipulate it. Conversely, a program isolated in a sandbox can contain memory vulnerabilities that can be exploited from within. True security comes from combining both approaches.

Firejail: the most popular sandbox for desktop applications

Firejail is probably the best-known sandboxing tool on the Linux desktop . It's written in C and runs as a SUID-bit executable that leverages namespaces, seccomp-BPF, and other kernel features to create an isolated environment around the program you want to run.

Its main advantage is its lightweight and user-friendly design : applications run almost identically to normal execution within the sandbox, it doesn't add resident processes when the system starts, and it has very few dependencies. In practice, it only consumes resources when you launch an application through it, making it suitable even for modestly sized computers.

In addition, Firejail comes with predefined configuration profiles for over 300-1000 common applications (depending on the version): browsers like Firefox and Chromium, VLC, Transmission, PDF readers, text editors, and many more. These profiles specify which parts of the file system each program can access, what permissions it has, whether it can use sound, what kind of network access it has, and so on.

You can also use Firejail for server programs and terminal tools , for example, to jail an Apache web server or a custom service that listens on a specific port. The model is always the same: the process runs within a set of namespaces and restrictions that limit the impact of a security breach.

How Firejail works on a technical level

In order for Firejail to set up its jails, it makes extensive use of Linux namespaces , a feature that began appearing in the kernel in version 2.6.23 and has been expanded to offer various types of isolation: PID, network, user, mount, UTS (hostname), IPC, etc. Each namespace encapsulates a set of resources, so that processes sharing a namespace see a different reality from those outside it.

In other words, a program running with Firejail doesn't see the same file system, process table, network stack, or hostname as the rest of the system, but rather a filtered or partially mounted version depending on the profile in use. This is the basis of many container technologies, such as Docker, and is the main reason why it's so efficient.

Firejail complements namespaces with file system access control (MAC) policies . With these rules, you can, for example, allow the program to access only specific subdirectories of your $HOME directory, such as Downloads or the application's specific configuration folder, while blocking access to the rest. Many default profiles already include well-defined rules to ensure the program functions correctly without allowing it to freely roam your disk.

Another important layer is seccomp-BPF . This mechanism allows a process to be associated with a system call (syscall) filter. The filter is described using BPF (Berkeley Packet Filter) and defines which syscalls are allowed and with what parameters; any other call causes the kernel to terminate the process or return an error. Browsers like Chrome and container systems like Docker also leverage this technique to limit what running code can do.

  CryptoMator Tutorial: A complete guide to encrypting your files and protecting the cloud

Finally, Firejail can coexist with AppArmor and SELinux . These MAC systems work at the kernel level to restrict access to files, sockets, capabilities, etc. Firejail adds another layer of isolation: it not only decides which resources an application can access, but also separates it into namespaces so that even several applications with similar permissions don't necessarily have to see or manipulate each other.

Install Firejail and its graphical interface Firetools

In most GNU/Linux distributions, Firejail is not pre-installed but is available in the official repositories . On Debian, Ubuntu, and derivatives, simply using APT is enough to add it to the system without any extra dependencies or background services.

To install the base Firejail package, you can run:

sudo apt-get install firejail

With that single command, you'll have everything you need to use Firejail from the terminal . There's no need to touch any configuration files to get started; knowing just a couple of basic commands, you can jail your first applications.

If you want a more user-friendly graphical interface for launching and configuring applications, you can also install Firetools, which acts as a launcher with an icon in the system tray and a setup wizard.

sudo apt-get install firetools

After installation you will see two new entries in the applications menu: one for the tray with the launchers and another for the Firejail Configuration Wizard , a step-by-step assistant that allows you to choose the application, decide whether to use the default profile or a custom one, and adjust permissions on directories, sound, network, and other kernel protections.

Using Firejail from the terminal: the basics and more

The most common use of Firejail is to precede the executable you want to isolate with the `firejail` command. If the program has a predefined profile, it will be applied automatically; otherwise, a generic configuration will be used, plus any you add via the command line.

For example, to open Firefox inside a sandbox, the command would be:

firejail firefox

Note that on distributions like Ubuntu 22.04 and later, Firefox is often packaged as a Snap package, so this command may not work directly . In that case, you'll need to use the version packaged with APT or adapt the profile to the correct path of the binary that actually runs.

The story is similar with other desktop applications. Some common examples would be:

firejail gedit
firejail evince
firejail vlc
firejail transmission-gtk

While those applications are open, if you look at the resource monitor you'll see that each process appears as a child of a Firejail process . To see the complete tree of processes running inside sandboxes at any given time, you can use:

firejail --tree

If you want to explore all the supported options (there are many for networking, X11, bandwidth, custom profiles, etc.), you have the usual option available:

firejail --help

Firejail configuration profiles: where they are and how to access them

The true power of Firejail comes from its configuration profiles . Each profile describes how a particular program should be isolated: which directories it mounts as read-only or read-write, whether it has access to the user folder, whether 3D acceleration is allowed, whether it can access the internet, which DNS it uses, whether it listens to the sound server, and so on.

Global system profiles are typically stored in /etc/firejail/ . To see the complete list available on your machine, you can run:

ls /etc/firejail/

Each file with the .profile extension defines the rules for a program. If you want to modify, for example, the default Firefox profile, you can edit it with your favorite text editor by running it with administrator privileges.

sudo nano /etc/firejail/firefox.profile

Inside you'll find Firejail directives that control mounts, access, capabilities, and special options . To understand all the available parameters, it's highly recommended to review the specific man page for profiles.

man 5 firejail-profile

In addition to modifying existing profiles, you can create new profiles for programs that don't have their own . In these cases, Firejail usually uses a slightly more permissive generic configuration. If you want to customize the behavior of a specific application, you can define a profile file with its name and adapt it to your needs, using the official documentation and examples from other users.

User profiles: overwriting and extending standard settings

Often, you don't want to modify the system profiles in /etc/firejail , either to facilitate future updates or because you want to have your own variations for a specific user. Firejail supports profiles in the user's configuration directory, which can include the global profile and allow you to add or modify rules.

The first step is to create the folder where these user profiles will be stored:

mkdir -p ~/.config/firejail/

Imagine you want VLC to never have internet access when you open it with Firejail. You can create a local profile called vlc.profile that includes the global profile and adds the network restriction. To do this, open the file:

nano ~/.config/firejail/vlc.profile

And put something like the following:

include /etc/firejail/vlc.profile
net none

The ` include` directive includes VLC's default configuration, and the following line adds the rule to block network access. From that point on, launching `firejail vlc` will also use this user file, preventing VLC from accessing the internet and limiting it to playing local content.

Remember that the file name in your user folder must match the standard profile name for Firejail to detect and merge it properly.

Firejail advanced options: network, private mode, and resources

In addition to profiles, Firejail offers a good arsenal of command-line parameters to temporarily adjust the sandbox's behavior on each run, without needing to touch configuration files.

  Apple, Siri and the $95 million privacy fine

For example, you can disable network access for a specific application using the `--net=none` option. To start VLC in internet-isolated mode, simply do the following:

firejail --net=none vlc

Another very powerful feature is private mode . In this mode, the program runs in a temporary file system (tmpfs), doesn't see your real settings or personal files, and everything it does disappears when you close the sandbox session. It's ideal for sensitive operations, such as accessing online banking, testing suspicious websites, or running software that you don't want to leave a trace.

A practical example would be opening Google Chrome in private mode with specific DNS (for example, Google's):

firejail --private --dns=8.8.8.8 --dns=8.8.4.4 google-chrome

In this scenario, Chrome starts with its default settings, without extensions or browsing history, isolates itself in a tmpfs environment, and uses the specified DNS servers. This is a fairly reasonable way to minimize risks when visiting sensitive websites.

Firejail also allows applications within the sandbox to use their own virtual network interface , with a separate internal IP address, ARP table, separate firewall, etc., using macvlan. You could, for example, start Firefox on the eth0 interface with:

firejail --net=eth0 firefox

If you want to assign a specific IP address to that sandbox:

firejail --net=eth0 --ip=192.168.1.80 firefox

Keep in mind that this functionality is currently usually limited to wired networks , and may not work on wireless interfaces depending on your system configuration and distribution.

Bandwidth control and sandbox monitoring

A lesser-known feature of Firejail is its ability to limit the bandwidth of applications running within the sandbox. This is incredibly useful for performance testing, simulating slow connections, or simply preventing a torrent client from hogging your entire bandwidth.

The usual pattern is to assign a name to the sandbox and then operate on it from another terminal. For example, starting Firefox in a sandbox called browser connected to eth0:

firejail --name=navegador --net=eth0 firefox

In another terminal, you can set upload and download limits with the –bandwidth option, specifying the sandbox name, interface, and values ​​(in KB/s):

firejail --bandwidth=navegador set eth0 80 20

With those parameters, Firefox would be restricted to 80 KB/s download and 20 KB/s upload . If you later want to remove those restrictions, you can clear the bandwidth rules with:

firejail --bandwidth=navegador clear eth0

To find out at any time which applications you have running inside Firejail , the `--list` command displays a list of PIDs, users, and associated programs:

firejail --list

And if you're interested in seeing the resource consumption (memory, CPU, number of processes) of each active sandbox, you have the following available:

firejail --top

Enter an existing sandbox and use Firejail by default

There are situations where you might want to access a running sandbox "from the inside ," for example, to inspect its network configuration, review mounted routes, or perform administrative tasks. Firejail allows you to join a specific sandbox using the `--join` option, along with the PID of one of the processes.

If, for example, the output of firejail --list shows that Firefox has PID 5394, you could enter its sandbox with:

sudo firejail --join=5394

Firejail itself takes care of switching to the first child process inside the jail and leaves you in a root shell within that isolated environment, from where you can run the checks you need.

Another very practical option is to make Firejail the default way to start any program with an available profile . To do this, you can use the `firecfg` command, which creates symbolic links in `/usr/local/bin` pointing to `/usr/bin/firejail` for each application with a profile.

sudo firecfg

From this point on, every time you launch a program from the list (either from the graphical menu or the terminal), it will automatically start in a sandbox. If you ever want to revert this, simply remove the symbolic links created in /usr/local/bin.

If you prefer to apply this behavior only to a specific application , you can create the symbolic link yourself. For example, to make Firefox always use Firejail:

sudo ln -s /usr/bin/firejail /usr/local/bin/firefox

When you want to stop using Firejail automatically for that program, you just need to delete the corresponding symbolic link in /usr/local/bin.

Alternative graphics servers: Xpra and Xephyr with Firejail

One of the classic criticisms of the X11 model is that it doesn't offer good isolation between graphical applications , leaving the door open to keyloggers, screenshots, and other window-to-window spying techniques. Firejail attempts to mitigate some of this problem by allowing applications to run on alternative graphics servers.

Specifically, you can use Xpra and Xephyr as separate X servers, so the jailed program doesn't share the same X server as the rest of the desktop. First, you need to install the corresponding packages on your system:

sudo apt-get install xpra xserver-xephyr

Then, you can launch an application by specifying the X server to use with the –x11 option. For example, to start VLC without network access and using Xephyr:

firejail --x11=xephyr --net=none vlc

If you prefer the application to run on Xpra, the command would be similar, changing the parameter:

firejail --x11=xpra --net=none vlc

With this setup, you make life much more difficult for keyloggers and screen capturers trying to spy on what you do in that specific application, since it remains "connected" to its own graphical server, independent of the rest of the desktop.

Other sandboxing approaches in Linux: Bubblewrap, Flatpak, AppArmor, and containers

While Firejail is very convenient for desktop users, the Linux ecosystem offers other tools for isolating processes and applications . None are perfect, and all have their pros and cons, but it's worthwhile to explore them to choose the best one for each situation.

Bubblewrap is an alternative that focuses on providing a minimalist sandboxing runtime , cleaner and with a smaller attack surface than a large setuid tool. It's more difficult to configure directly than Firejail, but many modern solutions use it under the hood. Unlike Firejail, Bubblewrap's philosophy is to avoid using SUID whenever possible, reducing the impact of potential internal vulnerabilities.

  How to use Oh My Zsh to get the most out of your terminal

Projects like Bubble Jail are built upon Bubblewrap , aiming to offer a more user-friendly experience by addressing some of Firejail's organizational shortcomings (more consistent profiles, clearer configuration, etc.). The drawback is that it's a relatively unknown tool with a small developer base, so it's not as thoroughly audited or battle-tested as other, more popular options.

On the other hand, there's Flatpak , widely used for distributing isolated desktop applications. Although it relies on sandboxing techniques (namespaces, portals, declarative permissions, etc.), many experts point out that configuring it without leaving any loopholes is not trivial . Furthermore, it only works with applications packaged as Flatpak, so if your program doesn't exist in that format, it won't work for you.

In the realm of MAC policies, AppArmor and SELinux allow for the definition of very fine-grained rules regarding which files, sockets, capabilities, and resources each program can use. Theoretically, they are very powerful and typically offer a higher level of security than user-defined solutions, but they suffer from the same problem: configuring them correctly is complex , and creating robust profiles for each service requires time, experience, and constant maintenance.

In cloud and Kubernetes environments, a very interesting alternative is containers based on lightweight virtual machines , such as Kata Containers, which Red Hat OpenShift integrates as an optional OCI-compliant runtime. In this model, each workload runs on its own isolated kernel within a lightweight VM, providing an extra layer of isolation on top of the usual namespace separation. An operator is responsible for installing, managing, and updating this runtime within the cluster.

Memory safety + sandboxing: the Fil-C approach and the OpenSSH case

Beyond the desktop, many critical server applications (such as OpenSSH or SaaS platform components) benefit from combining memory security and deep sandboxing . This is where projects like Fil-C come in, proposing a secure C/C++ implementation that can coexist well with native Linux mechanisms.

OpenSSH on Linux already uses several isolation techniques: chroot (creating a chroot cage) to limit the view of the file system, running processes as unprivileged users and groups, using setrlimit to restrict resources (opening files, creating processes, etc.) and seccomp-BPF filters that only allow a controlled subset of system calls; everything else causes the process to terminate.

The challenge for runtimes like Fil-C is adapting to these restrictions without breaking the program . For example, if the garbage collector needs background threads, you have to ensure that all those threads are created before activating the sandbox, and that the seccomp filters are installed on all of them, not just the main thread, while also respecting settings like PR_SET_NO_NEW_PRIVS and PR_SET_SECCOMP.

Fil-C offers features like `zlock_runtime_threads()` , which force the initialization of all necessary threads before activating the sandbox and block the creation of new threads afterward, ensuring that restrictions are applied consistently throughout the process. It also requires minor exceptions in the seccomp filters , such as allowing `MAP_NORESERVE` in `mmap` or the `sched_yield` syscall, which are necessary for internal runtime management.

This type of work demonstrates that it's possible to combine memory-safe environments, strict sandboxes, and high-profile applications like OpenSSH without sacrificing compatibility or performance. Chrome and Mozilla developers have been documenting similar practices for their own Linux sandboxes for years, setting the standard for robust defense in depth.

Practical use cases: protecting your browsing and your daily life

All of this translates into very common scenarios for any Linux user. For example, when you visit torrent sites, download sites full of pop-ups, porn sites, or portals with suspicious links , the probability of encountering cryptojacking scripts, malicious ads, or fingerprinting attempts is more than reasonable.

A simple measure is to jail your browser with Firejail every time you get into those messes. Launch the browser with:

firejail chromium &

O well:

firejail firefox &

It gives you an extra layer of peace of mind. The ampersand (&) at the end is useful for keeping the browser open even if you accidentally close the terminal. If you combine this with solutions like Pi-hole on your local network, or script and mining blocking extensions, you significantly reduce the attack surface when browsing suspicious websites.

Firejail's private mode, profiles that block access to sensitive folders, and the use of controlled DNS for the browser you use with your online banks are small decisions that, added together, make the difference between a serious scare and a simple closed tab.

Looking at the big picture, it's clear that sandboxing in Linux isn't a silver bullet, but it is an incredibly powerful tool if you know how to combine it: Firejail and its profiles for everyday use, Bubblewrap and Flatpak for more controlled environments, AppArmor/SELinux and seccomp-BPF for critical services, and technologies like Kata Containers or memory-safe runtimes like Fil-C when building more complex infrastructures. Ultimately, it's about building layers so that even if one fails, the others continue to keep your system reasonably safe.