Restarting nginx&gunicorn without sudo

Python Fan asked:

Can I run systemctl restart gunicorn && systemctl restart nginx without sudo? Currently I get:

out: Authentication is required to reload ‘gunicorn.service’.

out: Authenticating as: myuser

out: Password:

# coding: utf-8
from fabric.api import *
from fabric.colors import green, red


def production():
    env.host_string = '159.xxx.xxx.xx'
    env.user = 'myuser'
    path = "/home/myuser/myproject/myproject"
    print(red("Beginning Deploy:"))
    with cd(path):
        with prefix('. /home/myuser/myproject/myenv/bin/activate'):
            run("pwd")
            print(green("Pulling master from git..."))
            run("git pull")
            print(green("Migrate the database..."))
            run("python3 manage.py migrate")
            print(green("Restart the uwsgi process"))
            run("systemctl restart gunicorn && systemctl restart nginx")
        print(red("DONE!"))

My answer:


You can try adding a PolicyKit rule to allow for restarting units without authentication.

For example this will allow any user to restart the named services (may need a bit of tweaking):

polkit.addRule(function(action, subject) {
    if (action.id == "org.freedesktop.systemd1.manage-units") {
        polkit.log("action=" + action)
        polkit.log("subject=" + subject)
        polkit.log("unit="+action.lookup("unit"))
        polkit.log("verb="+action.lookup("verb"))
        if (action.lookup("unit") == "gunicorn.service" ||
            action.lookup("unit") == "nginx.service") {
            var verb = action.lookup("verb");
            if (verb == "start" || verb == "restart") {
                polkit.log("returning YES")
                return polkit.Result.YES;
            }
        }
    }
    polkit.log("returning NO")
});

Place your rules in a file in the /etc/polkit-1/rules.d directory, with a filename ending in .rules.

This requires systemd 226 or higher, which in Ubuntu means 16.04 LTS or later.

(And if you think that looks like JavaScript, that’s because it is JavaScript.)

You can also limit it to specific users by checking subject.user, e.g.:

if (subject.user == "deploy" || subject.user == "me") {

View the full question and answer on Server Fault.

Creative Commons License
This work is licensed under a Creative Commons Attribution-ShareAlike 3.0 Unported License.