-
Notifications
You must be signed in to change notification settings - Fork 625
Comparison of firejail and systemd hardening options
Kelvin M. Klann edited this page Oct 13, 2025
·
1 revision
TL;DR: These tables list equivalent options rather than equal options. Read their docs!
NOTE: Keep in mind that systemd is made to run and sandbox system-services
while firejail has its focus on desktop programs. Therefore some options differ
in their behavior, for example does firejail's private-tmp always bind-mount
/tmp/.X11-unix, while systemd's PrivateTmp=yes does not. Always read the
documentation of the option you use!
man 5 systemd.execman 5 systemd.resource-controlman 5 systemd.serviceman 5 systemd.unitman 1 firejailman 5 firejail-profile
| firejail | systemd |
|---|---|
| always | PrivateMounts=yes |
blacklist /homeblacklist /rootblacklist /run/user
|
ProtectHome=yes |
read-only /homeread-only /rootread-only /run/user
|
ProtectHome=read-only |
Possible via tmpfs or whitelist
|
ProtectHome=tmpfs |
blacklist /boot |
InaccessiblePaths=/boot |
chroot /foobaz |
RootDirectory=/foobaz |
disable-mnt |
InaccessiblePaths=/mntInaccessiblePaths=/mediaInaccessiblePaths=/run/mount(breaks systemd)InaccessiblePaths=/run/media
|
mkdir |
Not Implemented You can use RuntimeDirectory=, StateDirectory=, CacheDirectory=, LogsDirectory=, ConfigurationDirectory=.You could write a [email protected] and use After=mkdir\x2fetc\x2fdnsmasq.service/[email protected]. |
mkfile |
Not Implemented |
noexec /tmp |
NoExecPaths=/tmp |
| Not Implemented | ExecPaths=/tmp/bin |
private-bin bash,getenforce,python3 |
TemporaryFileSystem=/binTemporaryFileSystem=/usr/binTemporaryFileSystem=/sbinTemporaryFileSystem=/usr/sbinBindReadOnlyPaths=/bin/bashBindReadOnlyPaths=/usr/bin/python3BindReadOnlyPaths=/usr/sbin/getenforce
|
private-cwd |
WorkingDirectory=~ |
private-cwd /root |
WorkingDirectory=/root |
private-etc ca-certificates,crypto-policies,nsswitch.conf,pki,resolv.conf,ssl |
TemporaryFileSystem=/etcBindReadOnlyPaths=-/etc/ca-certificatesBindReadOnlyPaths=-/etc/crypto-policiesBindReadOnlyPaths=-/etc/nsswitch.confBindReadOnlyPaths=-/etc/pkiBindReadOnlyPaths=-/etc/resolv.confBindReadOnlyPaths=-/etc/ssl
|
private-lib |
Not Implemented |
private-opt vivaldi |
TemporaryFileSystem=/optBindReadOnlyPaths=/opt/vivaldi
|
private-srv www |
TemporaryFileSystem=/srvBindReadOnlyPaths=-/srv/www
|
private-tmp |
PrivateTmp=yes / PrivateTmp=disconnected
|
read-only /usr |
ProtectSystem=yes |
read-only /usrread-only /etc
|
ProtectSystem=full |
read-only / |
ProtectSystem=strict |
read-only /homeread-only /rootread-only /run/user
|
ProtectHome=read-only |
read-only /sys/fs/cgroup |
ProtectControlGroups=yes |
| fixme | ProtectControlGroups=private |
| fixme | ProtectControlGroups=strict |
read-only /proc/acpiread-only /proc/fsread-only /proc/irqread-only /proc/latency_statsread-only /proc/sysread-only /proc/sysrq-triggerread-only /proc/timer_statsread-only /sys
|
ProtectKernelTunables=yes |
read-only /foo |
ReadOnlyPaths=/foo |
read-write /foo/bar |
ReadWritePaths=/foo/bar |
tmpfs /hometmpfs /roottmpfs /run/user
|
ProtectHome=tmpfs |
tmpfs /xyzzy |
TemporaryFileSystem=/xyzzy |
tracelog |
Not Implemented |
whitelist /mnt/backup |
TemporaryFileSystem=/mntBindPaths=/mnt/backup
|
| fixme |
BindPaths= BindReadOnlyPaths=
|
| always | PrivatePIDs=yes |
| always (via pid-namespace) | ProtectProc=invisible |
| Not Implemented | ProtectProc=noaccess |
| #6491 | ProcSubset=pid |
| Not Implemented | RestrictSUIDSGID=yes |
| firejail | systemd |
|---|---|
private-dev |
PrivateDevices=yes |
no3d |
InaccessiblePaths=/dev/dri |
nodvd |
InaccessiblePaths=/dev/sr* |
noinput |
InaccessiblePaths=/dev/input |
noprinters |
fixme |
nosound |
InaccessiblePaths=/dev/snd |
notv |
InaccessiblePaths=/dev/dvb |
nou2f |
InaccessiblePaths=/dev/hidraw* |
novideo |
InaccessiblePaths=/dev/video* |
| firejail | systemd |
|---|---|
caps.drop all |
CapabilityBoundingSet= |
caps.drop sys_admin,net_admin |
CapabilityBoundingSet=~CAP_SYS_ADMIN CAP_NET_ADMIN |
caps.keep net_bind_service |
CapabilityBoundingSet=CAP_NET_BIND_SERVICE |
memory-deny-write-execute |
MemoryDenyWriteExecute=yesSystemCallFilter=~memfd_create
|
nonewprivs |
NoNewPrivileges=yes |
seccomp |
SystemCallFilter=<omitted because it is to long, look at syscalls.txt> |
seccomp.block-secondary |
SystemCallArchitectures=native |
seccomp.drop @debug |
SystemCallFilter=~@debug |
seccomp.keep @file-system,mount |
SystemCallFilter=@file-system mount |
| #3106 | SystemCallFilter=@system-service |
seccomp-error-action EPERM (default) |
SystemCallErrorNumber=EPERM |
seccomp-error-action kill |
SystemCallErrorNumber= (default) |
| fixme | SystemCallLog= |
caps.drop sys_time,wake_alarmseccomp.drop @clockread-only /dev/rtc*
|
ProtectClock=yes |
caps.drop syslogseccomp.drop syslogblacklist /dev/kmsgblacklist /proc/kmsg
|
ProtectKernelLogs=yes |
caps.drop sys_moduleblacklist /usr/lib/modulesseccomp.drop @module
|
ProtectKernelModules=yes |
| fixme | LockPersonality=yes |
systemd does not support Landlock (yet).
| firejail | systemd |
|---|---|
dns 9.9.9.9 |
Not Implemented |
hosts-file |
Not Implemented |
hostname myhost |
ProtectHostname=private:myhost |
net none |
PrivateNetwork=yes |
net eth0 |
Not Implemented |
netfilter /etc/firejail/myfilter.net |
Not Implemented |
| Not Implemented |
IPIngressFilterPath= IPEgressFilterPath=
|
net eth0netfilter ipdenyallow.netnftables based |
IPAddressDeny= IPAddressAllow=eBPF based |
| fixme |
SocketBindAllow= SocketBindDeny=
|
| fixme | RestrictNetworkInterfaces= |
netns NAME |
NetworkNamespacePath=/var/run/netns/NAME |
protocol unix,inet,inet6 |
RestrictAddressFamilies=AF_UNIX AF_INET AF_INET6 |
| fixme | ProtectHostname=yes |
D-Bus filtering is not implemented for systemd and blocking the system-bus socket breaks systemd.
| firejail | systemd |
|---|---|
cpu 0,1 |
CPUAffinity=0,1 |
nice 2 |
Nice=2 |
rlimit* |
Limit* |
timeout |
TimeoutSec= |
| fixme | RestrictRealtime=yes |
| Not Implemented | CoredumpFilter= |
| Not Implemented | KeyringMode= |
oom |
OOMScoreAdjust= |
| Not Implemented | UMask=0077 |
| firejail | systemd |
|---|---|
nogroups |
Not Implemented |
noroot |
PrivateUsers=yes |
| Not Implemented | PrivateUsers=identity |
| Not Implemented |
User=userGroup=groupSupplementaryGroups=supp_group1 supp_group2
|
| Not Implemented | DynamicUser=yes |
| Not Implemented | RemoveIPC=yes |
| firejail | systemd |
|---|---|
env FOO=bar |
Environment=FOO=bar |
rmenv |
UnsetEnvironment=EDITOR |
| firejail | systemd |
|---|---|
include some-common.inc |
Not Implemented You can use symlinks / hardlinks in /etc/systemd/system/UNIT.d. |
ipc-namespace |
PrivateIPC=yes |
join |
JoinsNamespaceOf= |
machine-id |
Not Implemented Maybe you can use ExecStartPre=!/bin/sh -c "dbus-uuidgen > /etc/machine-id", however until now nobody had tested this. |
restrict-namespaces |
RestrictNamespaces= |
| Not Implemented | RestrictFileSystems= |