GNOME applications (and others) are commonly using the GSettings API for storing their application settings.
GSettings has many nice aspects:
- flexible data types, with GVariant
- schemas, so others can understand your settings (e.,g. dconf-editor)
- overrides, so distros can tweak defaults they don’t like
And it has different backends, so it can be adapted to work transparently in many situations. One example for where this comes in handy is when we use a memory backend to avoid persisting any settings while running tests.
The GSettings backend that is typically used for normal operation is the DConf one.
DConf
DConf features include profiles, a stack of databases, a facility for locking down keys so they are not writable, and a single-writer design with a central service.
The DConf design is flexible and enterprisey – we have taken advantage of this when we created fleet commander to centrally manage application and desktop settings for large deployments.
But it is not a great fit for sandboxing, where we want to isolate applications from each other and from the host system. In DConf, all settings are stored in a single database, and apps are free to read and write any keys, not just their own – plenty of potential for mischief and accidents.
Most of the apps that are available as flatpaks today are poking a ‘DConf hole’ into their sandbox to allow the GSettings code to keep talking to the dconf daemon on the session bus, and mmap the dconf database.
Here is how the DConf hole looks in the flatpak metadata file:
[Context] filesystems=xdg-run/dconf;~/.config/dconf:ro; [Session Bus Policy] ca.desrt.dconf=talk
Sandboxes
Ideally, we want sandboxed apps to only have access to their own settings, and maybe readonly access to a limited set of shared settings (for things like the current font, or accessibility settings). It would also be nice if uninstalling a sandboxed app did not leave traces behind, like leftover settings in some central database.
It might be possible to retrofit some of this into DConf. But when we looked, it did not seem easy, and would require reconsidering some of the central aspects of the DConf design. Instead of going down that road, we decided to take advantage of another GSettings backend that already exists, and stores settings in a keyfile.
Unsurprisingly, it is called the keyfile backend.
Keyfiles
The keyfile backend was originally created to facilitate the migration from GConf to GSettings, and has been a bit neglected, but we’ve given it some love and attention, and it can now function as the default GSettings backend inside sandboxes.
It provides many of the isolation aspects we want: Apps can only read and write their own settings, and the settings are in a single file, in the same place as all the application data:
~/.var/app/$APP/config/glib-2.0/settings/keyfile
One of the things we added to the keyfile backend is support for locks and overrides, so that fleet commander can keep working for apps that are in flatpaks.
For shared desktop-wide settings, there is a companion Settings portal, which provides readonly access to some global settings. It is used transparently by GTK and Qt for toolkit-level settings.
What does all this mean for flatpak apps?
If your application is not yet available as a flatpak, and you want to provide one, you don’t have to do anything in particular. Things will just work. Don’t poke a hole in your sandbox for DConf, and GSettings will use the keyfile backend without any extra work on your part.
If your flatpak is currently shipping with a DConf hole, you can keep doing that for now. When you are ready for it, you should
- Remove the DConf hole from your flatpak metadata
- Instruct flatpak to migrate existing DConf settings, by adding a migrate-path setting to the X-DConf section in your flatpak metadata. The value fo the migrate-path key is the DConf path prefix where your application’s settings are stored.
Note that this is a one-time migration; it will only happen if the keyfile does not exist. The existing settings will be left in the DConf database, so if you need to do the migration again for whatever reason, you can simply remove the the keyfile.
This is how the migrate-path key looks in the metadata file:
[X-DConf] migrate-path=/org/gnome/builder/
Closing the DConf hole is what makes GSettings use the keyfile backend, and the migrate-path key tells flatpak to migrate settings from DConf – you need both parts for a seamless transition.
There were some recent fixes to the keyfile backend code, so you want to make sure that the runtime has GLib 2.60.6, for best results.
Happy flatpaking!
Update: One of the most recent fixes in the keyfile backend was to correct under what circumstances GSettings will choose it as the default backend. If you have problems where the wrong backend is chosen, as a short-term workaround, you can override the choice with the GSETTINGS_BACKEND environment variable.
Update 2: To add the migrate-path setting with flatpak-builder, use the following option:
--metadata=X-DConf=migrate-path=/your/path/