Restore Firefox’s stability and performance on Ubuntu by switching from the Snap package to Mozilla’s official .deb to overcome configuration caveats and recent Firefox Snap issues.
While using Firefox, numerous
apparmor="DENIED" profile="snap.firefox.firefox" name="/proc/pressure/memory" comm="MemoryPoller"
messages flooded the syslog, making log analysis impossible.
See also
- Apparmor denying firefox polling memory pressure
- Mozilla Bug 2005923: Snap firefox spams apparmor denied message about /proc/pressure/memory
Further investigation revealed these stemmed from missing AppArmor permissions – Firefox's MemoryPoller needed to read system memory pressure, but Snap's rigid confinement blocked it.
Without the ability to poll memory pressure Firefox loses a key signal about system memory state and cannot react properly to low‑memory situations, which can lead to degraded performance or crashes under load.
Unfortunately, corrective settings could not be applied to the SNAP installation because of
- Profiles in
/var/lib/snapd/apparmor/→ overwritten everysnap refresh /etc/apparmor.d/local/snap.firefox.firefox→ ignored by snapdsystemctl restart snapd.apparmor→ oneshot service, no reload- Snap too rigid – no proper override merging
Tip
Solution: Switch to Debian packages from Mozilla Team PPA.
- Better RAM usage, native GPU/scrolling
- Direct file handling, perfect GTK themes, full extensions
- Customizable AppArmor – local overrides persist across updates
- Standard
aptworkflow, no Snap daemon overhead - Clean logs – no more DENIED spam in
/var/log/syslog´after simplefixes - Summary: Firefox shows a much lower CPU footprint and runs noticeably smoother overall.
This guide summarizes the complete process to migrate Firefox from Snap to the Mozilla Team .deb package on Ubuntu, including APT configuration to prevent Snap reinstallation, and AppArmor profile adjustments to eliminate DENIED log spam while maintaining reasonable security. It preserves all profiles (bookmarks, passwords, extensions) while eliminating Snap's technical limitations.
Caution
Please note that by following the instructions below you are stepping outside the standard Ubuntu approach. As a result, support from the Ubuntu forums will no longer be available, and any assistance may be limited or redirected to other communities. You are doing this at your own risk and should be fully aware of what you are doing - in case of doubt, these changes may put your Ubuntu system at risk.
Hint: If you later decide to return to the official Ubuntu-supported setup, you will find instructions at the end of this gist on how to revert these changes and switch back to Snap.
Note
This guide was successfully tested with FF 146.0 (SNAP) -> firefox/noble,now 146.0+build1-0ubuntu0.24.04.1~mt1 (MOZ/DEBIAN) on Ubuntu 24.04.3 LTS.
Caution
SNAP stores the Firefox profiles in a different location. If you don’t back them up, they will be lost during the later procedures. Without a backup, all saved passwords, session information, and browsing history will be permanently deleted.
cp -r ~/snap/firefox/common/.mozilla/firefox ~/.mozilla-firefox-backupsudo snap remove --purge firefox
sudo apt purge firefox firefox-locale-* # Removes APT Snap wrappersudo add-apt-repository ppa:mozillateam/ppa -yAlternatively you could also use the mozilla debian repo instead of the mozillateam-ppa (see https://support.mozilla.org/en-US/kb/install-firefox-linux#w_install-firefox-deb-package-for-debian-based-distributions-recommended ) for details. Be aware that the below mentioned AppArmor rules might be different then.
echo '
Package: snapd
Pin: release a=*
Pin-Priority: -10' | sudo tee /etc/apt/preferences.d/nosnap.prefPurpose: Prevents apt install firefox from pulling the Snap meta-package. Ubuntu's default firefox APT package is just a Snap wrapper.
Security: None – purely prevents Snap confinement issues.
sudo apt updatesudo apt install firefoxcp -r ~/.mozilla-firefox-backup/* ~/.mozilla/firefox/
firefox --ProfileManager # Select & set default profileResult: Full profile migration (bookmarks, passwords, extensions preserved).
Note
The Mozilla/Debian .deb installation of Firefox also/still produces AppArmor DENIED errors due to its restrictive default profile blocking legitimate resource access like memory pressure and GPU caching.
You can verify this by running journalctl -f | grep -iE "(apparmor.*firefox|DENIED.*firefox) in a terminal while starting/using Firefox.
These problems will now be finally resolved through targeted local overrides in /etc/apparmor.d/local/usr.bin.firefox. These overrides grant Firefox specific permissions to monitor its processes and subprocesses more effectively, optimize resource usage, and enable hardware acceleration. The adjustments persist across updates, preserve core sandbox security, and provide improved system performance with reduced system load.
Please create/edit:
sudo mkdir -p /etc/apparmor.d/local
sudo nano /etc/apparmor.d/local/usr.bin.firefoxFile Content (copy exactly - prevent spaces at EOL):
# memory pressure information (used by sandboxing and performance checks)
/proc/pressure/memory r,
# process cgroup membership (detects container/session environment)
/proc/[0-9]*/cgroup r,
# adjust OOM score for content sandbox processes
/proc/[0-9]*/oom_score_adj w,
# Thread name introspection: Firefox reads /proc/[pid]/task/[tid]/comm for process monitoring
/proc/[0-9]*/task/[0-9]*/comm r,
# GPU shader cache database (read/write/lock); improves graphics performance
owner @{HOME}/.cache/mesa_shader_cache**/mesa_cache.db rwlk,
# Additional Mesa shader cache location used by some drivers
owner @{HOME}/.cache/mesa_shader_cache_db/** rwk,
# read cgroup filesystem to gather system resource info
/sys/fs/cgroup/** r,
# allow loading of DRM/Widevine decryption module used by streaming services
owner @{HOME}/.{firefox,mozilla}/**/libwidevinecdm.so m,
# allow launching helper applications outside Firefox sandbox
/usr/lib/x86_64-linux-gnu/glib-2.0/gio-launch-desktop ix -> unconfined,
# system hardware identification (model/serial; read‑only)
/sys/devices/virtual/dmi/id/** r,
# allow snap based apps to be started for file associations
/usr/bin/snap ix,
# GTK VFS Metadata (file thumbnails/properties)
dbus (send)
bus=session
interface=org.gtk.vfs.Metadata
path=/org/gtk/vfs/metadata,
# UPower (complete power management - devices + service)
dbus (receive, send)
bus=system
path=/org/freedesktop/UPower**,
# Firefox cache & profiles (full access with locks)
owner @{HOME}/.{firefox,mozilla}/** rwlkix,
# systemd‑logind (complete power/session integration)
dbus (receive, send)
bus=system
path=/org/freedesktop/login1**
interface=org.freedesktop.**,
# Accessibility Bus (screen readers, high contrast)
dbus (send)
bus=session
path=/org/a11y/bus
interface=org.freedesktop.DBus.Properties
member=GetAll,
# systemd-timedated (timezone, date)
dbus (send)
bus=system
path=/org/freedesktop/timedate1
interface=org.freedesktop.DBus.Properties
member=GetAll,
# D-Bus: Standard session bus (broad but safe)
#dbus (send)
#bus=session,
# xdg-desktop-portal (complete desktop integration)
dbus (send)
bus=session
path=/org/freedesktop/portal/**,
# DConf Writer (configuration change + notifications)
dbus (send, receive)
bus=session
path=/ca/desrt/dconf/Writer/**
interface=ca.desrt.dconf.Writer,
# MPRIS MediaPlayer (full bidirectional support)
dbus (receive, send)
bus=session
path=/org/mpris/MediaPlayer2
interface=org.freedesktop.DBus.Properties
member=PropertiesChanged,
dbus (receive, send)
bus=session
path=/org/mpris/MediaPlayer2
interface=org.mpris.MediaPlayer2.Player
member=Seeked,
# MPRIS MediaPlayer (name binding - Firefox as media player)
dbus (bind)
bus=session
name=org.mpris.MediaPlayer2.firefox.*,
# Allow Firefox to receive MPRIS property queries
dbus (receive)
bus=session
path=/org/mpris/MediaPlayer2
interface=org.freedesktop.DBus.Properties
member=GetAll,
# Allow Firefox to release its MPRIS bus name
dbus (send)
bus=session
path=/org/freedesktop/DBus
interface=org.freedesktop.DBus
member=ReleaseName,
# GTK VFS Daemon (file chooser backend, mount tracking)
dbus (send)
bus=session
path=/org/gtk/vfs/**
interface=org.gtk.**,
# Hostname service (system identity queries)
dbus (send)
bus=system
path=/org/freedesktop/hostname1
interface=org.freedesktop.DBus.Properties,
Reload:
sudo apparmor_parser -r /etc/apparmor.d/usr.bin.firefoxclick to open
| Rule | Example Log Message | Purpose | Security Impact |
|---|---|---|---|
/proc/pressure/memory r, |
apparmor="DENIED" ... name="/proc/pressure/memory" ... comm="MemoryPoller" |
MemoryPoller reads system memory pressure | Minimal: Read-only system metric, no user data |
/proc/[0-9]*/cgroup r, |
apparmor="DENIED" ... name="/proc/39014/cgroup" ... comm="57656220436F6E74656E74" |
Content processes read own cgroup membership | Low: Process metadata only, read-only |
/proc/[0-9]*/oom_score_adj w, |
apparmor="DENIED" ... name="/proc/37749/oom_score_adj" ... requested_mask="w" |
Firefox adjusts OOM priority of own child processes | Low: Only affects own processes, no privilege escalation |
/proc/[0-9]*/task/[0-9]*/comm r, |
apparmor="DENIED" ... name="/proc/132553/task/132553/comm" ... comm="53747265616D547E73202335323938" |
Read thread names of own processes | Minimal: Own thread names only |
owner @{HOME}/.cache/mesa_shader_cache**/mesa_cache.db rwlk, |
apparmor="DENIED" ... name="/home/dirk/.cache/mesa_shader_cache_db/part0/mesa_cache.db" ... operation="file_lock" |
GPU Renderer locks Mesa shader cache files | Minimal: User-owned cache, GPU performance only |
owner @{HOME}/.cache/mesa_shader_cache_db/** rwk, |
apparmor="DENIED" ... name="/home/dirk/.cache/mesa_shader_cache_db/part4/mesa_cache.db" ... comm="firefox:disk$0" |
Disk cache process accesses new Mesa DB format | Minimal: User-owned cache, GPU performance only |
owner @{HOME}/.{firefox,mozilla}/**/libwidevinecdm.so m, |
apparmor="DENIED" ... name="/home/dirk/.mozilla/firefox/4zc8eowf.default/gmp-widevinecdm/4.10.2934.0/libwidevinecdm.so" ... comm="MainThread" ... requested_mask="m" |
Firefox tries to map the library into memory for execution. https://support.mozilla.org/en-US/kb/enable-drm | Minimal/Low (narrow scope, standard practice, no privilege escalation): allows memory‑mapping a single library file, but you have to trust Widevine |
/sys/fs/cgroup/** r, |
apparmor="DENIED" ... name="/sys/fs/cgroup/user.slice/user-1000.slice/session-c2.scope/cpu.max" |
Read cgroup-v2 resource limits (CPU/Memory) | Low: Read-only own user.slice limits |
dbus (receive, send) bus=system path=/org/freedesktop/UPower**, |
path="/org/freedesktop/UPower" member="GetAll" |
Full power service (battery + AC status) | None: Hardware power data |
/usr/bin/snap ix, |
name="/usr/bin/snap" comm="firefox" or desktop apps |
Launch Snap packages (Firefox downloads) | Low: Snap confinement handles sandboxing |
/usr/lib/x86_64-linux-gnu/glib-2.0/gio-launch-desktop -> unconfined, |
operation="exec" name="/usr/bin/systemctl" comm="freecad" |
Desktop apps run unconfined (breaks chain) | Acceptable: Normal user apps |
dbus (send) bus=session interface=org.gtk.vfs.Metadata ... |
operation="dbus_method_call" path="/org/gtk/vfs/metadata" interface="org.gtk.vfs.Metadata" member="Set" |
File thumbnails/properties metadata | Minimal: User-owned GTK metadata storage |
dbus (receive, send) bus=system path=/org/freedesktop/login1** interface=org.freedesktop.**, |
path="/org/freedesktop/login1" interface="org.freedesktop.login1.Manager" member="PrepareForSleep"path="/org/freedesktop/login1" interface="org.freedesktop.DBus.Properties" member="PropertiesChanged" |
Enables Firefox to both query and listen for all power and session management signals (e.g. suspend/resume, user logins, lid events). Ensures browser reacts properly to sleep/wake and session transitions. | Minimal risk – rule is limited to the login1 namespace; allows only signal and query operations, no privileged writes or control actions. |
dbus (send) bus=session interface=org.freedesktop.DBus path=/org/freedesktop/DBus member=ReleaseName, |
path="/org/freedesktop/DBus" interface="org.freedesktop.DBus" member="ReleaseName" |
D-Bus name cleanup | None: Standard bus protocol |
/sys/devices/virtual/dmi/id/** r, |
name="/sys/devices/virtual/dmi/id/product_name" |
Hardware detection (telemetry, crash reports) | Minimal: Read-only hardware facts (model, serial); standard for browsers |
owner /home/**/mozilla/firefox/** mrklix, |
name="...quicksuggest-other.sql" requested_mask="k" |
Cache + SQLite locking (QuickSuggest) | None: Temporary user cache |
owner /home/**/.mozilla/** rwlkix, |
Profile database operations | Firefox settings/profiles | Low: User-owned config |
dbus (send) bus=session path=/org/freedesktop/portal/desktop interface=org.freedesktop.portal.Registry member=Register, |
path="/org/freedesktop/portal/desktop" interface="org.freedesktop.portal.Registry" member="Register" |
File picker, screen sharing | Low: Portal-mediated user actions only |
dbus (send) bus=system path=/org/freedesktop/login1 interface=org.freedesktop.DBus.Properties member=GetAll, |
path="/org/freedesktop/login1" interface="org.freedesktop.DBus.Properties" member="GetAll" |
Full session status (idle, lid) | Minimal: Standard session broadcasts |
dbus (send) bus=session path=/org/a11y/bus interface=org.freedesktop.DBus.Properties member=GetAll, |
path="/org/a11y/bus" interface="org.freedesktop.DBus.Properties" member="GetAll" |
Screen reader/high contrast detection | None: Accessibility status only |
dbus (send) bus=system path=/org/freedesktop/timedate1 interface=org.freedesktop.DBus.Properties member=GetAll, |
path="/org/freedesktop/timedate1" interface="org.freedesktop.DBus.Properties" member="GetAll" |
Timezone/calendar display | None: Public system clock data |
dbus (send) bus=session path=/org/freedesktop/portal/**, |
path="/org/freedesktop/portal/desktop" member="Register" |
ALL portals (file picker, screen share, print) | Low: User consent required |
dbus (receive, send) bus=session path=/org/mpris/MediaPlayer2 interface=org.mpris.MediaPlayer2.Player member=Seeked, |
path="/org/mpris/MediaPlayer2" interface="org.mpris.MediaPlayer2.Player" member="Seeked" |
Media seek/scrub events | None: Media position updates |
dbus (bind) bus=session name=org.mpris.MediaPlayer2.firefox.*, |
operation="dbus_bind" name="org.mpris.MediaPlayer2.firefox.instance_1_221" |
Firefox registers as media player | None: Own service name only |
dbus (send) bus=session path=/org/gtk/vfs/** interface=org.gtk.**, |
path="/org/gtk/vfs/mounttracker" interface="org.gtk.vfs.MountTracker" member="LookupMount" |
Query GVFS for mounts and volume information (file dialogs). | Low: Read‑only mount state. |
dbus (receive) bus=session path=/org/mpris/MediaPlayer2 interface=org.freedesktop.DBus.Properties member=GetAll, |
apparmor="DENIED" operation="dbus_method_call" path="/org/mpris/MediaPlayer2" interface="org.freedesktop.DBus.Properties" member="GetAll" |
Receive MPRIS property queries for media controls | Low: Session bus media properties only |
dbus (send) bus=session path=/org/freedesktop/DBus interface=org.freedesktop.DBus member=ReleaseName, |
apparmor="DENIED" operation="dbus_method_call" path="/org/freedesktop/DBus" interface="org.freedesktop.DBus" member="ReleaseName" |
Release MPRIS bus name when done | Minimal: Standard D-Bus name management |
dbus (send, receive) bus=session path=/ca/desrt/dconf/Writer/** interface=ca.desrt.dconf.Writer, |
interface="ca.desrt.dconf.Writer" member="Change" |
Read/write personal dconf settings, e.g., theme updates or preference saves. | Low: User‑scope configuration only. |
dbus (send) bus=system path=/org/freedesktop/hostname1 interface=org.freedesktop.DBus.Properties, |
path="/org/freedesktop/hostname1" member="GetAll" |
Allow host name and OS information queries. | Minimal: Public system info. |
- All rules are scoped to Firefox’s own processes, caches, and system‑exposed resource data
- No access to other users’ data, privileged system files, or expanded network abilities
- Read/write limited to performance‑related cache files in the user’s home (Firefox/Mozilla profiles, Mesa shader cache)
- AppArmor main sandbox remains intact (no /etc/, /root/, or cross‑user access)
- Thread and cgroup introspection allowed only for Firefox‑owned processes (comm, cgroup, OOM score)
- GTK VFS: Metadata lookups only, no arbitrary file access
- UPower: Full device/service access (send+receive) but still read‑only and non‑privileged
- systemd‑logind: Full session/power integration (send+receive) via org.freedesktop.*, still no control operations
- systemd‑timedated: Read‑only timezone/date properties, no modification ability
- Accessibility Bus: Read‑only property access for assistive technologies
- xdg-desktop-portal: Desktop integration only, no privileged operations
- DConf Writer: Full send+receive for notifications and change events, but no ability to read or modify settings directly
- MPRIS: Full bidirectional media control (PropertiesChanged, Seeked, GetAll) plus ReleaseName for clean media‑player registration; no privilege escalation
- MPRIS name binding: Firefox registers as a media player, no additional permissions
- GTK VFS Daemon: File chooser + mount tracking integration, no privileged operations
- Hostname service: Read‑only system identity queries, no modification ability
- gio-launch-desktop: Runs unconfined for file‑opening integration, without weakening Firefox’s confinement
- snap launcher: Allows starting snap apps for file associations, no additional privileges
- DMI system info: Read‑only hardware identifiers, no sensitive data exposure
- Widevine CDM: Module load only, no extra filesystem access beyond Firefox’s own profile
Net Security Impact: Minimal degradation.
Firefox gains fine‑grained control over its own resource management (OOM tuning, cgroup awareness, GPU caching, hardware info, desktop integration, full media controls) while remaining fully confined. Tradeoff: Clean logs + full performance vs. the stricter but noisy default profile.
# Check AppArmor status
sudo aa-status | grep firefox
# Monitor for new DENIED messages
journalctl -f | grep -E "(apparmor.*firefox|DENIED.*firefox|dbus.*firefox)"
# Test Firefox functionality
firefox --ProfileManager # All profiles intactIf the Xfce starter menu no longer works for Firefox, you need to reset the default applications.
To configure default apps in XFCE, open the Settings Manager and go to Default Applications. There you can set programs for common tasks such as web browsing, mail, file management, and the terminal. For specific file types (MIME types), right‑click a file and choose Open With > Other Application to assign a new default.
In case you want to switch back to the official Ubuntu SNAP variant of Firefox:
here's a quick undo guide
cp -r ~/.mozilla/firefox ~/mozilla-deb-backupsudo apt purge firefox
sudo ppa-purge ppa:mozillateam/ppasudo rm /etc/apt/preferences.d/nosnap.pref
sudo apt updatesudo snap install firefoxmkdir -p ~/snap/firefox/common/.mozilla/firefox/- Copy the profile either from your existing Debian installation. (compare step1)
cp -r ~/mozilla-deb-backup/* ~/snap/firefox/common/.mozilla/firefox/
- Or (if no changes were made to the profile in the meantime) use the profile copy created during the snap-to-deb switch (see above).
cp -r ~/.mozilla-firefox-backup/* ~/snap/firefox/common/.mozilla/firefox/ # From original Snap backup
firefox --ProfileManager # Select & set default profile in Snapsudo rm /etc/apparmor.d/local/usr.bin.firefox
sudo apparmor_parser -r /etc/apparmor.d/usr.bin.firefox
Thanks.. It didnt work out-of-the-box, though a lot of directions were indeed very useful! Thanks for that!
Even after setting /etc/apt/preferences.d/nosnap.pref , the normal ubuntu firefox.deb still takes precedence over the mozilla .deb Therefore, it reinstalls the snap.
I created an apt firefox pin to disable the snap (/etc/apt/preferences.d/firefox.pref), and removed the 'nosnap.pref'
/etc/apt/preferences.d/firefox.pref:
After that I again removed the snap
snap remove --purge firefox, reinstalled the debapt install --reinstall firefox,doing the profile restore again...
You can check the right package selection with 'apt policy'
Also the apparmor directions didn't work right out of the box. On my noble installation, there was a symlink /etc/apparmor.d/disable/usr.bin.firefox , that took precedence over the 'local' file. Removing that symlink was necessary.
sudo rm /etc/apparmor.d/disable/usr.bin.firefox