I wanted to download the latest Ubuntu Desktop ISO image for a new system. I always use Transmission with Bittorrent links for that - they’re usually the fastest, but not this time. When I started Transmission and tried to load a torrent link file, it greeted me with an “Access Denied” message for my downloads directory. Trying to change the directory resulted in the same error. Attempting to fetch from a URL loaded the torrent but failed to start downloading. My storage was fine, and I could access all the files… What was going on?
I’ve run Transmission from the terminal to get more details:
(transmission-gtk:6417): GVFS-WARNING **: 15:15:45.378: Error: GDBus.Error:org.freedesktop.DBus.Error.AccessDenied: An AppArmor policy prevents this sender from sending this message to this recipient; type="method_call", sender=":1.122" (uid=1000 pid=6417 comm="transmission-gtk" label="transmission-gtk (enforce)") interface="org.gtk.vfs.Metadata" member="GetTreeFromDevice" error name="(unset)" requested_reply="0" destination=":1.94" (uid=1000 pid=5002 comm="/usr/libexec/gvfsd-metadata" label="unconfined")
(transmission-gtk:6417): GVFS-WARNING **: 15:15:45.378: can't init metadata tree /home/xxx/.local/share/gvfs-metadata/root: open: Access denied
AppArmor? Every time I hear about it, it reminds me of how many instructions on the web used to advise disabling SELinux on CentOS 😁
Let me check /var/log/syslog for more information:
2025-12-21T15:31:04.770350+01:00 ygg transmission-gtk[11851]: Unable to acquire the address of the accessibility bus: GDBus.Error:org.freedesktop.DBus.Error.AccessDenied: An AppArmor policy prevents this sender from sending this message to this recipient; type="method_call", sender=":1.191" (uid=1000 pid=11851 comm="/usr/bin/transmission-gtk" label="transmission-gtk (enforce)") interface="org.a11y.Bus" member="GetAddress" error name="(unset)" requested_reply="0" destination="org.a11y.Bus" (uid=1000 pid=4257 comm="/usr/libexec/at-spi-bus-launcher" label="unconfined"). If you are attempting to run GTK without a11y support, GTK_A11Y should be set to 'none'.
2025-12-21T15:31:04.791324+01:00 ygg kernel: audit: type=1400 audit(1766327464.790:481): apparmor="DENIED" operation="open" class="file" profile="transmission-gtk" name="/var/lib/snapd/desktop/icons/" pid=11851 comm="transmission-gt" requested_mask="r" denied_mask="r" fsuid=1000 ouid=0
2025-12-21T15:31:04.792318+01:00 ygg kernel: audit: type=1400 audit(1766327464.791:482): apparmor="DENIED" operation="open" class="file" profile="transmission-gtk" name="/etc/vulkan/implicit_layer.d/" pid=11851 comm="transmission-gt" requested_mask="r" denied_mask="r" fsuid=1000 ouid=0
2025-12-21T15:31:04.792322+01:00 ygg kernel: audit: type=1400 audit(1766327464.791:483): apparmor="DENIED" operation="open" class="file" profile="transmission-gtk" name="/home/xxx/.local/share/vulkan/implicit_layer.d/" pid=11851 comm="transmission-gt" requested_mask="r" denied_mask="r" fsuid=1000 ouid=1000
2025-12-21T15:31:04.792323+01:00 ygg kernel: audit: type=1400 audit(1766327464.791:484): apparmor="DENIED" operation="open" class="file" profile="transmission-gtk" name="/usr/share/vulkan/implicit_layer.d/" pid=11851 comm="transmission-gt" requested_mask="r" denied_mask="r" fsuid=1000 ouid=0
2025-12-21T15:31:04.792329+01:00 ygg kernel: audit: type=1400 audit(1766327464.791:485): apparmor="DENIED" operation="open" class="file" profile="transmission-gtk" name="/etc/vulkan/icd.d/" pid=11851 comm="transmission-gt" requested_mask="r" denied_mask="r" fsuid=1000 ouid=0
2025-12-21T15:31:04.792330+01:00 ygg kernel: audit: type=1400 audit(1766327464.791:486): apparmor="DENIED" operation="open" class="file" profile="transmission-gtk" name="/usr/share/vulkan/icd.d/" pid=11851 comm="transmission-gt" requested_mask="r" denied_mask="r" fsuid=1000 ouid=0
2025-12-21T15:31:04.792330+01:00 ygg kernel: audit: type=1400 audit(1766327464.791:487): apparmor="DENIED" operation="open" class="file" profile="transmission-gtk" name="/etc/vulkan/icd.d/" pid=11851 comm="transmission-gt" requested_mask="r" denied_mask="r" fsuid=1000 ouid=0
2025-12-21T15:31:04.792330+01:00 ygg kernel: audit: type=1400 audit(1766327464.791:488): apparmor="DENIED" operation="open" class="file" profile="transmission-gtk" name="/usr/share/vulkan/icd.d/" pid=11851 comm="transmission-gt" requested_mask="r" denied_mask="r" fsuid=1000 ouid=0
2025-12-21T15:31:04.792331+01:00 ygg kernel: audit: type=1400 audit(1766327464.791:489): apparmor="DENIED" operation="open" class="file" profile="transmission-gtk" name="/etc/vulkan/implicit_layer.d/" pid=11851 comm="transmission-gt" requested_mask="r" denied_mask="r" fsuid=1000 ouid=0
2025-12-21T15:31:04.798542+01:00 ygg dbus-daemon[3966]: apparmor="DENIED" operation="dbus_method_call" bus="session" path="/com/transmissionbt/transmission_64513_17317649" interface="org.gtk.Actions" member="DescribeAll" name=":1.24" mask="receive" pid=11851 label="transmission-gtk" peer_pid=4195 peer_label="unconfined"
2025-12-21T15:31:04.798579+01:00 ygg dbus-daemon[3966]: apparmor="DENIED" operation="dbus_method_call" bus="session" path="/com/transmissionbt/transmission_64513_17317649" interface="org.freedesktop.DBus.Properties" member="GetAll" name=":1.24" mask="receive" pid=11851 label="transmission-gtk" peer_pid=4195 peer_label="unconfined"
2025-12-21T15:31:04.973826+01:00 ygg dbus-daemon[3966]: apparmor="DENIED" operation="dbus_method_call" bus="session" path="/com/transmissionbt/transmission_64513_17317649/window/1" interface="org.gtk.Actions" member="DescribeAll" name=":1.24" mask="receive" pid=11851 label="transmission-gtk" peer_pid=4195 peer_label="unconfined"
And there it is - a lot of denials.
I googled a bit and found the official bug . It’s been broken since at least October (the release time) and no permanent fix has been provided. Eh… One workaround proposed is to run:
sudo apparmor_parser -Cr /etc/apparmor.d/transmission
Which would:
It will remain in complain mode until the next reboot or reload of policy (hopefully when the apparmor team officially updates the file).
But I would have to remember to fix it every time I want to run Transmission? No way - there has to be a better solution.
I want it to work, so I quickly reviewed the XDG documentation about files like /etc/xdg/user-dirs.defaults, /etc/xdg/user-dirs.conf, then ~/.config/user-dirs.dirs, and eventually /etc/apparmor.d/tunables/xdg-user-dirs and /etc/apparmor.d/tunables/xdg-user-dirs.d/site.local, which states:
# ------------------------------------------------------------------
#
# Copyright (C) 2014 Canonical Ltd.
# This program is free software; you can redistribute it and/or
# modify it under the terms of version 2 of the GNU General Public
# License published by the Free Software Foundation.
#
# ------------------------------------------------------------------
# The following may be used to add additional entries such as for
# translations. See tunables/xdg-user-dirs for details. Eg:
#@{XDG_MUSIC_DIR}+="Musique"
@{XDG_DESKTOP_DIR}+=""
@{XDG_DOWNLOAD_DIR}+=""
@{XDG_TEMPLATES_DIR}+=""
@{XDG_PUBLICSHARE_DIR}+=""
@{XDG_DOCUMENTS_DIR}+=""
@{XDG_MUSIC_DIR}+=""
@{XDG_PICTURES_DIR}+=""
@{XDG_VIDEOS_DIR}+=""
So here it is. Even though I have ~/.config/user-dirs.dirs properly configured with my localized directories, AppArmor redefines everything and expects me to use the English variants of directory names. But I want them localized, and that’s the problem.
I updated /etc/apparmor.d/tunables/xdg-user-dirs.d/site.local with my localized variants:
@{XDG_DESKTOP_DIR}+="Pulpit"
@{XDG_DOWNLOAD_DIR}+="Pobrane"
@{XDG_TEMPLATES_DIR}+="Szablony"
@{XDG_PUBLICSHARE_DIR}+="Publiczny"
@{XDG_DOCUMENTS_DIR}+="Dokumenty"
@{XDG_MUSIC_DIR}+="Muzyka"
@{XDG_PICTURES_DIR}+="Obrazy"
@{XDG_VIDEOS_DIR}+="Wideo"
Then restarted AppArmor:
sudo systemctl restart apparmor.service
Started Transmission and it works as it should.
The interesting outcome is that AppArmor is here to stay and will redefine how I work with desktop apps. Previously, you could download everything everywhere. Now, applications are more like containers and can only access files and directories within the “standard usage” scope. This feels more like container configuration. On one hand, it’s safer; on the other, it’s more restrictive and less flexible.
