Skip to content

Commit ba0d784

Browse files
gdamjanbenoitc
authored andcommitted
documentation: update systemd deploy unit examples (#1950)
There's no need for PIDFile=, especially not for Type=notify services. systemd knows the correct pid of the process it manages. No need for the `--bind` option either, since gunicorn supports the LISTEN_FDS environment variable and will use all of the sockets that systemd provides. This way, it's also more flexible, since we can specify several sockets in a .socket unit. The .socket unit should specify User=www-data so that nginx can connect to the socket. The service (gunicorn process) will inherit the file descriptor so it doesn't even need permissions for the socket (it's nginx which needs permissions). tmpfiles.d is not needed. replace ExecStop=/bin/kill with KillMode=mixed
1 parent 9184ae8 commit ba0d784

File tree

1 file changed

+44
-23
lines changed

1 file changed

+44
-23
lines changed

docs/source/deploy.rst

+44-23
Original file line numberDiff line numberDiff line change
@@ -212,12 +212,15 @@ Using Gunicorn with upstart is simple. In this example we will run the app
212212
Systemd
213213
-------
214214

215-
A tool that is starting to be common on linux systems is Systemd_. Below are
216-
configurations files and instructions for using systemd to create a unix socket
217-
for incoming Gunicorn requests. Systemd will listen on this socket and start
218-
gunicorn automatically in response to traffic. Later in this section are
219-
instructions for configuring Nginx to forward web traffic to the newly created
220-
unix socket:
215+
A tool that is starting to be common on linux systems is Systemd_. It is a
216+
system services manager that allows for strict process management, resources
217+
and permissions control.
218+
219+
Below are configurations files and instructions for using systemd to create
220+
a unix socket for incoming Gunicorn requests. Systemd will listen on this
221+
socket and start gunicorn automatically in response to traffic. Later in
222+
this section are instructions for configuring Nginx to forward web traffic
223+
to the newly created unix socket:
221224

222225
**/etc/systemd/system/gunicorn.service**::
223226

@@ -228,14 +231,18 @@ unix socket:
228231

229232
[Service]
230233
Type=notify
234+
# the specific user that our service will run as
231235
User=someuser
232236
Group=someuser
237+
# another option for an even more restricted service is
238+
# DynamicUser=yes
239+
# see http://0pointer.net/blog/dynamic-users-with-systemd.html
233240
RuntimeDirectory=gunicorn
234241
WorkingDirectory=/home/someuser/applicationroot
235-
ExecStart=/usr/bin/gunicorn --pid /run/gunicorn/pid \
236-
--bind unix:/run/gunicorn.sock applicationname.wsgi
242+
ExecStart=/usr/bin/gunicorn applicationname.wsgi
237243
ExecReload=/bin/kill -s HUP $MAINPID
238-
ExecStop=/bin/kill -s TERM $MAINPID
244+
KillMode=mixed
245+
TimeoutStopSec=5
239246
PrivateTmp=true
240247

241248
[Install]
@@ -248,33 +255,47 @@ unix socket:
248255

249256
[Socket]
250257
ListenStream=/run/gunicorn.sock
251-
User=someuser
252-
Group=someuser
253-
258+
# Our service won't need permissions for the socket, since it
259+
# inherits the file descriptor by socket activation
260+
# only the nginx daemon will need access to the socket
261+
User=www-data
262+
# Optionally restrict the socket permissions even more.
263+
# Mode=600
264+
254265
[Install]
255266
WantedBy=sockets.target
256267

257-
**/etc/tmpfiles.d/gunicorn.conf**::
258268

259-
d /run/gunicorn 0755 someuser somegroup -
269+
Next enable and start the socket (it will autostart at boot too)::
270+
271+
systemctl enable --now gunicorn.socket
260272

261-
Next enable the socket so it autostarts at boot::
262273

263-
systemctl enable gunicorn.socket
274+
Now let's see if the nginx daemon will be able to connect to the socket.
275+
Running ``sudo -u www-data curl --unix-socket /run/gunicorn.sock http``,
276+
our Gunicorn service will be automatically started and you should see some
277+
HTML from your server in the terminal.
264278

265-
Either reboot, or start the services manually::
279+
.. note::
266280

267-
systemctl start gunicorn.socket
281+
systemd employs cgroups to track the processes of a service, so it doesn't
282+
need pid files. In the rare case that you need to find out the service main
283+
pid, you can use ``systemctl show --value -p MainPID gunicorn.service``, but
284+
if you only want to send a signal an even better option is
285+
``systemctl kill -s HUP gunicorn.service``.
268286

287+
.. note::
269288

270-
After running ``curl --unix-socket /run/gunicorn.sock http``, Gunicorn
271-
should start and you should see some HTML from your server in the terminal.
289+
``www-data`` is the default nginx user in debian, other distriburions use
290+
different users (for example: ``http`` or ``nginx``). Check you distro to
291+
know what to put for the socket user, and for the sudo command.
272292

273293
You must now configure your web proxy to send traffic to the new Gunicorn
274294
socket. Edit your ``nginx.conf`` to include the following:
275295

276296
**/etc/nginx/nginx.conf**::
277297

298+
user www-data;
278299
...
279300
http {
280301
server {
@@ -292,15 +313,15 @@ socket. Edit your ``nginx.conf`` to include the following:
292313
The listen and server_name used here are configured for a local machine.
293314
In a production server you will most likely listen on port 80,
294315
and use your URL as the server_name.
295-
316+
296317
Now make sure you enable the nginx service so it automatically starts at boot::
297318

298319
systemctl enable nginx.service
299-
320+
300321
Either reboot, or start Nginx with the following command::
301322

302323
systemctl start nginx
303-
324+
304325
Now you should be able to test Nginx with Gunicorn by visiting
305326
http://127.0.0.1:8000/ in any web browser. Systemd is now set up.
306327

0 commit comments

Comments
 (0)