Write a Safe polkit Rule for a Specific Linux Action
You will finish with a narrowly scoped polkit rule that lets one existing Unix group perform one named action, plus a way to inspect and undo it. The examples use polkit 124, installed here as package polkitd 124-2ubuntu1.24.04.4. They change system authorisation, so read the whole rule before installing it.
The route
Jump straight to the step you need, or tick off Done means at the end.
Allow about 15 minutes. You need shell access, the polkitd package, an existing group, and an action that the target application actually uses. The rule itself needs elevated privileges. Listing actions and checking the service do not.
1. Confirm the service and version
Start with read-only checks. polkitd is the authority behind requests from privileged mechanisms and unprivileged subjects. It normally communicates over the system message bus, while a session's authentication agent handles password prompts.
$ dpkg-query -W -f='${Package} ${Version}
' polkitd
polkitd 124-2ubuntu1.24.04.4
$ pkaction --version
pkaction version 124
$ systemctl is-active polkit.service
active
Your package revision and service state may differ. If the service is not active, fix that separately through your distribution's normal service-management process. Do not start changing rules to compensate for a daemon that is not running.
Checkpoint
You have confirmed the installed major version and know whether the authority is running.
2. Find the exact action identifier
polkit does not authorise a vague operation such as "reboot". Applications define action identifiers, and their policy files provide descriptions and default authorisations. List every registered action with:
$ pkaction --verbose
For a focused query, pass the identifier after --action-id. This machine has the systemd reboot action:
$ pkaction --action-id org.freedesktop.login1.reboot --verbose
org.freedesktop.login1.reboot:
description: Reboot the system
message: Authentication is required to reboot the system.
implicit any: auth_admin_keep
implicit inactive: auth_admin_keep
implicit active: yes
The complete output also includes vendor information and annotations. Do not copy an action name from a blog post without checking it locally. If pkaction says the action does not exist, identify the action from the application's installed policy or documentation instead.
3. Choose the smallest policy change
Use a rule when the existing action is right but its authorisation needs a local exception. This example allows members of linux-reboot to reboot, and changes nothing for other actions or users:
polkit.addRule(function(action, subject) {
if (action.id == "org.freedesktop.login1.reboot" &&
subject.isInGroup("linux-reboot")) {
return polkit.Result.YES;
}
});
The comparison is exact. The rule does not match related actions such as changing the login manager's wall message. The subject check uses the group membership polkit sees for the requesting process.
Security boundary
polkit.Result.YES bypasses authentication for this matching action. Grant it only to a group whose members are trusted to perform the operation. Do not use a broad prefix such as org.freedesktop. unless you have reviewed every action that would match.
Keep rules in JavaScript compatible with ECMAScript 5. In particular, avoid relying on newer syntax merely because the JavaScript engine on this host happens to accept it. The rule function may return YES, NO, an authentication result, or no result. Returning no result allows later rules and the normal policy to be considered.
4. Install the rule with a reviewable filename
Rules intended for local administration belong in /etc/polkit-1/rules.d. Files there and in /usr/share/polkit-1/rules.d are read in lexical filename order. A file in /etc wins a same-name tie with one in /usr.
First create the group if it does not already exist. This is an elevated, persistent account change; skip it when your directory service already provides the group:
$ getent group linux-reboot || sudo groupadd --system linux-reboot
Add a numbered local rule. The temporary file prevents a partially written rule from being observed if the editor or shell is interrupted:
$ sudo install -o root -g root -m 0644 /dev/null /etc/polkit-1/rules.d/49-linux-reboot.rules
$ sudoedit /etc/polkit-1/rules.d/49-linux-reboot.rules
Paste the rule from step 3, save, then inspect what is on disk:
$ sudo sed -n '1,40p' /etc/polkit-1/rules.d/49-linux-reboot.rules
polkit.addRule(function(action, subject) {
if (action.id == "org.freedesktop.login1.reboot" &&
subject.isInGroup("linux-reboot")) {
return polkit.Result.YES;
}
});
polkitd monitors both rules directories. Adding, changing or removing a rule causes it to purge and reload the rules. You normally do not need to restart the service. Avoid a manual restart while another administrator is relying on polkit, because restarting the authority can disrupt active authorisation requests.
Checkpoint
The file is root-owned, mode 0644, has the exact action identifier, and contains no wildcard match.
5. Apply group membership correctly
If you added a user to linux-reboot, that user's existing login session may not know about the new supplementary group. Check the account without changing anything:
$ id --groups --name
alice adm cdrom sudo linux-reboot
Start a new login session if the group is missing. Do not test by assuming that sudo has the same subject identity as the desktop or service that will request the action.
For a real test, use the application's normal operation and a maintenance window. A reboot is service-disrupting and cannot be undone once it starts. First test the rule's match with a harmless action in a lab, or use the application's own dry-run facility if it provides one. A successful authentication or action result proves only that this request was accepted, not that every related operation is permitted.
6. Diagnose a rule that does not match
Start with the action, not with a broader grant:
$ pkaction --action-id org.freedesktop.login1.reboot --verbose
$ stat -c '%U %G %a %n' /etc/polkit-1/rules.d/49-linux-reboot.rules
root root 644 /etc/polkit-1/rules.d/49-linux-reboot.rules
Then check these common traps:
- The application may request a different action identifier, even if its user interface says reboot.
- The requesting process may run as a service account rather than as your interactive user.
- The user may need a new login session after group membership changes.
- A later rule may never run because an earlier rule already returned a result.
- A syntax error or exception prevents the intended rule from behaving as expected.
For temporary debugging, a rule can call polkit.log(), which writes a message with the JavaScript filename and line number to the system logger. Remove debugging output after the test: log messages can expose action and subject details to administrators, and the method is intended mainly for diagnosis.
7. Undo the change
Removing the file restores the policy that would apply without this local rule. This is an elevated and persistent change, so confirm the exact path before running it:
$ sudo rm -- /etc/polkit-1/rules.d/49-linux-reboot.rules
$ test ! -e /etc/polkit-1/rules.d/49-linux-reboot.rules && echo removed
If you created the dedicated group solely for this test, remove users from it through your normal account administration first. Deleting a group can affect file ownership and other policy outside polkit, so do not run groupdel as an automatic cleanup step.
Done means
- You checked the installed polkit version and confirmed the authority is active.
- You obtained the exact action identifier with
pkaction. - Your rule matches one action and one intended group.
- The file is root-owned, mode 0644, and stored under
/etc/polkit-1/rules.d. - You accounted for session group state and the service-disrupting nature of the test.
- You know that deleting the rule restores the previous policy.