How to automatically create a runtime folder with a systemd service or tmpfiles.d?

25,115

Solution 1

I added in PermissionsStartOnly=True and set a runtime folder per service, as suggested. I also added 0 to the start of the folder mode.

[Unit]
Description=gunicorn_django daemon
After=network.target

[Service]
PermissionsStartOnly=True
User=gunicorn
Group=www-data
RuntimeDirectory=gunicorn_django
RuntimeDirectoryMode=0775
PIDFile=/run/gunicorn_django/django_test_pid
WorkingDirectory=/vagrant/webapps/django_venv/django_test
ExecStart=/vagrant/webapps/django_venv/bin/gunicorn --pid /run/gunicorn_django/django_test_pid --workers 3 --bind unix:/run/gunicorn_django/django_test_socket django_test.wsgi --error-logfile /var/log/gunicorn/django_test_error.log
ExecReload=/bin/kill -s HUP $MAINPID
ExecStop=/bin/kill -s TERM $MAINPID

[Install]
WantedBy=multi-user.target

It's now creating a folder with the correct permissions.

drwxrwxrw-  2 gunicorn www-data   40 Mar 30 07:11 gunicorn_django/

Thanks @quixotic and @mark-stosberg

Solution 2

My problem was that I had two services using same RuntimeDirectory (isc-dhcp-server and isc-dhcp-server6), but I configured only one to work. So when the second one died, its runtime directory got removed, making it a problem for the first service.

Share:
25,115

Related videos on Youtube

geonaut
Author by

geonaut

Python, Go & DevOps

Updated on September 18, 2022

Comments

  • geonaut
    geonaut over 1 year

    I'm trying to create a runtime folder at /run/gunicorn for some Gunicorn socket / PID files, which are for a Django application. I can get everything working if I manually create directories. However, I'm trying to make this a robust setup, and eventually use Ansible to automate everything.

    I think I have 2 options, based on this question.

    Option 1 - RuntimeDirectory

    I think the first option is to use RuntimeDirectory= within my systemd service file, but I can't get it to create the folder. The service files contains:

    #/etc/systemd/system/gunicorn_django_test.service
    [Unit]
    Description=gunicorn_django daemon
    After=network.target
    
    [Service]
    User=gunicorn
    Group=www-data
    RuntimeDirectory=gunicorn #This line is supposed to create a directory
    RuntimeDirectoryMode=755
    PIDFile=/run/gunicorn/django_test_pid
    WorkingDirectory=/vagrant/webapps/django_venv/django_test
    ExecStart=/vagrant/webapps/django_venv/bin/gunicorn --pid /run/gunicorn/django_test_pid --workers 3 --bind unix:/run/gunicorn/django_test_socket django_test.wsgi --error-logfile /var/log/gunicorn/django_test_error.log
    ExecReload=/bin/kill -s HUP $MAINPID
    ExecStop=/bin/kill -s TERM $MAINPID
    PrivateTmp=true
    
    [Install]
    WantedBy=multi-user.target
    

    When I run systemctl start gunicorn_django_test.service, the service fails to start. When I snip out the exec line, and run it manually, I get Error: /run/gunicorn doesn't exist. Can't create pidfile. If I create the /run/gunicorn folder manually, I can get things to work.

    Option 2 - tmpfiles.d

    The second option is to use tmpfiles.d to have a folder created on boot, ready for the pid / socket files. I've tried this file:

    #/etc/tmpfiles.d/gunicorn.conf
    d /run/gunicorn 0755 gunicorn www-data -
    

    This creates a directory, but it is quickly deleted somehow, and by the time I start the service, the folder isn't available.

    I can manually add some PreExec mkdir commands into the service file, but I'd like to get to the bottom of why RuntimeDirectory / tmpfiles.d aren't working. Thanks.

    Versions / Info: Ubuntu 16.04 Server / systemd 229 / Gunicorn 19.7.1 / runtime dir = /run

    • geonaut
      geonaut about 7 years
      It's something to do with group permissions in the /run/ folder. I can create a 0755 folder with the group as www-data, but I need the folder to be group writeable, so both the Nginx user and the Gunicorn user can access the socket file. In order to do that, I need sudo-level permissions. For some reason, sudo systemctl... etc isn't passing the sudo permissions to the service.
    • quixotic
      quixotic about 7 years
      i'll bet it's trying to create the directory with the uid from User= and failing. try adding PermissionsStartOnly=true. see unix.stackexchange.com/a/207493/222377
    • quixotic
      quixotic about 7 years
      hmm. actually i'll bet it's failing because the runtime directory is made but isn't /run/gunicorn. it's probably $XDG_RUNTIME_DIR/gunicorn which might resolve to /run/user/$UID/gunicorn for the gunicorn user UID. (same question, next answer.)
    • Mark Stosberg
      Mark Stosberg about 7 years
      Are you trying to use the same directory for multiple Gunicorn instances? You could be running into this related issue>
    • Alexis Wilke
      Alexis Wilke over 5 years
      Your Option 2 would have worked. However, the tmpfiles.d and RuntimeDirectory=... definitions are not compatible. You should not have both turned on at the same time.