https://discussion.fedoraproject.org/t/f46-change-proposal-relocate-the-selinux-policy-store-to-etc-selinux-system-wide/204918
# Summary Move the SELinux policy store (installed modules, local customizations and the compiled policy) from `/var/lib/selinux` to `/etc/selinux/<policy>/active` by setting `store-root = /etc/selinux` in the default `semanage.conf`. This brings every Fedora edition, spin and atomic variant to a single layout, matches the location already used on ostree-based systems such as Fedora Silverblue, and follows the migration that openSUSE completed in 2026. Existing systems are migrated automatically on upgrade. ## Detailed Description ### Current location Since the SELinux userspace release adopted in Fedora 23, the policy store lives under `/var/lib/selinux/<policy>/`, while the configuration (`/etc/selinux/config`, `semanage.conf`) and the policy-related content shipped by packages live under `/etc/selinux` and `/usr/share/selinux`. The policy store is the area that `semodule`, `semanage` and `setsebool -P` read and write: it holds the module set, local changes (booleans, users, ports, file contexts) and the linked and compiled policy. ### New location `/etc/selinux/<policy>/active` (for example `/etc/selinux/targeted/active`), reached by changing `store-root` in `/etc/selinux/semanage.conf` from its default `/var/lib/selinux` to `/etc/selinux`. This is the layout that Fedora Silverblue 44 already uses: `booleans.local`, `file_contexts`, `file_contexts.homedirs`, `homedir_template`, `modules/`, `policy.kern`, `policy.linked`, `seusers` and `users_extra` all sit under `/etc/selinux/targeted/active`. ### Why this is needed `/usr` and `/etc` are the trees that atomic and snapshot-based update schemes capture and roll back together; `/var` holds mutable state and is deliberately left alone. A policy store in `/var` therefore breaks that model. After a rollback, the files from packages under `/usr/share/selinux` and `/etc/selinux` return to their earlier state while the store in `/var/lib/selinux` keeps the newer one. If the update added or removed types, attributes or modules, rebuilding the policy or installing an external module afterwards can fail, and the system ends up in a state that is hard to recover automatically. openSUSE documented exactly this failure mode, rated it very rare in practice, and still decided to remove it by moving the store to `/etc`. The same reasoning drove two earlier decisions that this Change builds on: * **Fedora 36, RPM database to /usr** (`Changes/RelocateRPMToUsr`): the RPM database describes mostly `/usr`, so it was moved next to it so that `/usr` can be rolled back as a unit without touching `/var`. The rpm-ostree variants and openSUSE were already doing so, and the move was applied on upgrade by a systemd service that relocated the data. The discussion also raised FHS objections, which are addressed below for this proposal. * **openSUSE, SELinux store to /etc** (2026): the migration landed in Tumbleweed snapshot 20260505 after months of testing, runs automatically on package update, preserves local changes and custom modules, and removes the old `/var/lib/selinux` tree only once no snapshot still needs it. On the atomic side, the problem was already visible in 2016: with an empty `/var` after a factory reset, the store in `/var/lib/selinux` was missing and `semanage` and `semodule` stopped working, which led to a dedicated policy variant that kept the store in `/etc`. Standardizing on `/etc/selinux` removes that special case and the divergence between variants. ### What will change 1. The default `semanage.conf` shipped by Fedora sets `store-root = /etc/selinux` like Atomic spins but for all the Fedora ecosystem. 2. On upgrade, a migration step moves the store from `/var/lib/selinux/<policy>` to `/etc/selinux/<policy>`, keeping local booleans, users, ports, file-context changes, custom modules at any priority and disabled modules, then records completion with a marker file so it runs once. It follows the approach used for the RPM database in Fedora 36: a one-time step during the offline upgrade, with scriptlets as a safety net for online upgrades. 3. The old tree is kept unused as a fallback for one release and then removed. 4. Packages that install SELinux modules or set booleans from scriptlets are audited, for the new location. 5. The policy is checked for the file contexts and rules that apply to the new paths, so `semanage` tools run in their usual domain without new denials. 6. Ostree-based variants drop whatever special-casing they carry today and use the same default as everyone else. ## Benefit to Fedora * Policy and module changes roll back together with the rest of the system on any setup that snapshots `/usr` and `/etc`: openSUSE-style btrfs layouts with `/var` as a separate subvolume, LVM and device-mapper snapshots, and similar schemes. * One layout across Workstation, Server, spins and the atomic variants instead of two. Documentation, tooling and troubleshooting become the same everywhere. * Fixes the empty-`/var` failure on atomic systems at the source, with no variant-specific workaround. Please share your thoughts on this proposal so that it can serve as an incentive for developers and help make this change a reality. -- _______________________________________________ devel mailing list -- [email protected] To unsubscribe send an email to [email protected] Fedora Code of Conduct: https://docs.fedoraproject.org/en-US/project/code-of-conduct/ List Guidelines: https://fedoraproject.org/wiki/Mailing_list_guidelines List Archives: https://lists.fedoraproject.org/archives/list/[email protected] Do not reply to spam, report it: https://forge.fedoraproject.org/infra/tickets/issues/new
