Hardening elementary OS with Firejail for safer everyday computing
Australians running elementary OS on a home desktop in Sydney or Melbourne are not immune to the credential-stealing malware that hit Optus and Medibank customers in recent years. Even on Linux, a careless click on a malicious attachment can hand over cookies, saved passwords, or session tokens without much fuss. The kernel will not warn you, and the Pantheon desktop will not show a dramatic prompt. Sandboxing adds a second wall between a vulnerable application and the rest of your system, and Firejail is the lightest-weight way to add that wall on a Linux laptop today.
The tool has been in the Ubuntu and Debian repositories for years, which means elementary OS users get a stable, audited build without hunting for third-party packages. It works by combining Linux namespaces, seccomp-bpf filters, and optional AppArmor policies to wrap a process in a tightly scoped environment. The application sees a fake home directory, a private view of /tmp, and only the network it has been explicitly granted. If something goes wrong inside the sandbox, the damage stays inside.
Before diving in, it is worth being honest about the trade-offs. A sandboxed browser cannot read your existing ~/.mozilla folder, so bookmarks and saved logins will not appear unless you allow them. A sandboxed mail client will not see your local address book unless you mount it in. Firejail ships with hundreds of pre-built profiles that handle these decisions sensibly, and you can override any of them with a single text file in your home directory.
This guide walks through preparing the system, installing the package, running everyday applications from the terminal, crafting custom profiles for tighter restrictions, and finally wiring the whole thing into the Pantheon desktop so you do not have to remember any commands after the first week.
Preparing the system before installing Firejail
elementary OS 8 (Jólnir) ships with the Ubuntu 24.04 LTS package base, so the kernel already has full namespace support and seccomp-bpf enabled by default. You do not need to recompile anything, but a few minutes of preparation will save headaches later. Open the Terminal from the Applications menu, or hit Super+T, and start with a fresh package index.
Run sudo apt update followed by sudo apt upgrade to make sure every installed package is current. Kernel and apparmor packages occasionally need a reboot after an upgrade, so check that you are running the latest installed kernel with uname -r. If a new kernel was pulled in, reboot before installing sandboxing tools; otherwise, some of the security bits Firejail relies on may still belong to the older image.
Confirm that AppArmor is active, since Firejail can layer its profiles on top of the system policy for an extra measure of containment. The command aa-status will list loaded profiles, and you should see at least a handful of enforce entries from the default image. If it returns an empty set, install apparmor-utils and reboot. This step matters more for shared family laptops in Brisbane or Adelaide homes where multiple accounts exist on the same machine.
Finally, decide whether you want a graphical front-end. The optional firetools package ships a small GTK launcher that lets you start sandboxed applications from a list with a click. If you keep the Terminal open for everything, skip it. If you occasionally hand the laptop to a family member who is not comfortable at the command line, firetools gives them a friendlier entry point.
Installing Firejail from default repositories
With the system current, installing Firejail is a single command. Run sudo apt install firejail firejail-profiles and confirm the prompt. The second package is critical: it pulls in the curated profile library maintained upstream and ensures you have up-to-date rules for browsers, chat clients, and media players the moment you need them. Without it, you would be left with a bare sandbox and a long weekend of writing profile files by hand.
Verify the install with firejail --version. The output should report a version in the 0.9.x or 1.0.x range along with the path to the active profile directory. While you are there, run firejail --list once to make sure the helper utilities are wired up correctly. An empty list is fine, but a permission error here means something in the namespace stack is broken and you should investigate before going further.
The next tool to know about is firecfg, which sets a default Firejail wrapper for every application that already has a profile in /etc/firejail. Running sudo firecfg walks the installed desktop files and creates symlinks in /usr/local/bin so launching Firefox or any other known binary goes through Firejail automatically. From the user's perspective, the app starts the same way it always has, but underneath it now runs inside a sandbox. You can reverse this later with sudo firecfg --clean.
After running firecfg, log out and back in once so the updated PATH takes effect across the Pantheon session. This is also a good moment to open the AppArmor panel in System Settings and confirm that the firejail-default profile is loaded in enforce mode, which gives you a second layer of protection on top of the namespace restrictions.
Running sandboxed applications from the terminal
The simplest way to test your new setup is from the Terminal. Try firejail --private firefox to launch Firefox with a throwaway home directory. Bookmarks, history, and saved logins will all be missing, which is exactly the point: anything the browser touches lives only in a tmpfs mount that disappears when the process exits. This mode is perfect for opening a link a colleague emailed from a Melbourne cafe without contaminating your main profile.
For more permanent sandboxing, drop the --private flag and use a real profile. firejail firefox reads /etc/firejail/firefox.profile, which by default gives the browser access to ~/.mozilla, the Downloads folder, and standard system paths. If you want to tighten it further, layer options on the command line: --nodvd blocks access to optical drives, --no3d disables GPU acceleration, and --net=none cuts all networking for fully offline work such as rendering a local PDF.
You will quickly find that some applications need a tweak. WebRTC-heavy conferencing apps sometimes complain when they cannot reach certain ports, and image editors occasionally need access to a scanner or colour profile directory that the default profile blocks. When that happens, copy the relevant profile from /etc/firejail into ~/.config/firejail with the same name, edit the local copy, and Firejail will prefer the user version automatically.
It is worth getting into the habit of checking what is actually running sandboxed. The firejail --list command prints every wrapped process along with its PID and the active profile, which is handy when you suspect something has escaped containment or simply want to confirm that your morning routine is as locked down as you think it is.
Configuring custom profiles for tighter restrictions
Custom profiles live as plain text files in ~/.config/firejail for the current user, and in /etc/firejail for system-wide rules. Each file is a list of directives that look more like an INI file than a shell script. include firefox.profile pulls in another profile as a baseline, private enables a throwaway home, net none blocks networking, and whitelist ~/Documents/secure exposes only one directory while hiding the rest of the home folder.
Say you want to run the Pantheon Mail client in a sandbox with no network access at all, because you only use it to read local mbox archives while travelling on the train between Sydney Central and Parramatta. Create ~/.config/firejail/mail.local with three lines: include mail.profile, net none, and private-bin mail. From now on, firejail --profile=mail.local io.elementary.mail will launch the app fully offline with only its own binary visible to the kernel.
For cloud-aware applications the configuration gets more interesting. If you have connected Mail, Calendar, or the Online Accounts panel to your iCloud, Fastmail, or even a Telstra-branded sync service, the sandbox needs a sensible set of network permissions so authentication and push notifications still work while nothing else gets out. The a guide to elementary OS's online accounts for email and cloud sync walkthrough on the site maps which credentials get cached where on disk, which makes it easier to decide what to whitelist in a custom profile.
Once a profile is in place, test it with firejail --debug to see exactly which syscalls, files, and network operations are being intercepted. The debug output is verbose, but it is the fastest way to discover why a particular feature broke. After a few iterations you will end up with a small set of local profiles that match your real workflow.
Integrating Firejail with the Pantheon desktop and apps
Running everything from the Terminal works for a while, but you will eventually want the same sandboxing to apply when you launch apps from the Slingshot launcher or the dock. The cleanest method is the firecfg symlink approach, but for any application that does not have a stock profile, you can wrap it by hand. Right-click a .desktop file in /usr/share/applications, copy it to ~/.local/share/applications, and change the Exec line from Exec=appname to Exec=firejail appname. The Pantheon launcher will pick up the local override automatically.
Confirm the integration by launching an app from Slingshot and running firejail --list in another terminal window. The process should appear with its profile name in the right-hand column. If it does not, the .desktop file probably points to a wrapper script or a binary that lives outside the default PATH, and the Exec edit needs a full path to the executable instead of just the name.
Some elementary OS apps are sandboxed internally through the portal framework, which means wrapping them again in Firejail can lead to odd behaviour with file pickers, screen sharing, or notifications. When that happens, the simplest fix is to exclude the app from Firecfg with sudo firecfg --exclude appname and let the existing portal sandbox do its job. Layering two sandboxes rarely doubles your safety and frequently halves your stability.
A small but valuable habit is to occasionally audit which apps are actually running inside Firejail and which have slipped through. A short script that diffs firejail --list against the full set of running PIDs will tell you at a glance whether anything escaped. Treat any naked process as a candidate for either re-wrapping or replacing with a sandboxed alternative, and your desktop will quietly become one of the more locked-down Linux setups available.
The most useful first run is to sandbox the one application you use to handle money or sensitive logins. Pick your bank portal in Firefox, your superannuation website in GNOME Web, or whichever client you use to read work email, and launch it tomorrow with firejail --private firefox or the equivalent profile. Spend ten minutes confirming that the sandboxed session behaves normally, log out, and watch the temporary home disappear.