How do I automatically set the target context for a .sock file to be **httpd_var_run_t** so that nginx can connect to and write to the socket?

The original file context for /run/unicorn.sock is tcontext=system_u:object_r:var_run_t:s0

How do I have the file context automatically be system_u:object_r:httpd_var_run_t:s0 when I start the socket unit so that the nginx server can connect to and write to the socket file without being denied by SELinux.

Here is the socket daemon I created in /usr/lib/systemd/system/unicorn.socket

[Unit]
Description=unicorn socket

[Socket]
ListenStream=/run/unicorn.sock

[Install]
WantedBy=sockets.target

and the corresponding /usr/lib/systemd/system/unicorn.service

[Unit]
Description=unicorn daemon
Requires=unicorn.socket
After=network.target

[Service]
User=ec2-user
Group=ec2-user
WorkingDirectory=/home/ec2-user/product-catalog
ExecStart=/home/ec2-user/product-catalog/venv/bin/gunicorn 
          --access-logfile - 
          -k uvicorn.workers.UvicornWorker 
          --workers 3 
          --bind unix:/run/unicorn.sock 
          app:app


[Install]
WantedBy=multi-user.target

I noticed php-fpm’s socket file in /run/php-fpm

Asked By: siralbert

||

When systemd creates files and directories it uses your selinux policy to assign labels. That means the first step is to update your selinux policy database with information about the socket:

semanage fcontext -a -t httpd_var_run_t /var/run/unicorn.sock

Given a socket unit like this:

[Unit]
Description=unicorn socket

[Socket]
ListenStream=/run/unicorn.sock
SocketUser=nginx
SocketGroup=nginx
SocketMode=0660

[Install]
WantedBy=sockets.target

And a service unit like this:

[Service]
Type=exec
User=nginx
Group=nginx
WorkingDirectory=/srv/app
ExecStart=gunicorn --bind unix:/run/unicorn/unicorn.sock app:app

That gets us:

[root@localhost system]# ls -lZ /run/unicorn.sock
srw-rw----. 1 nginx nginx system_u:object_r:httpd_var_run_t:s0 0 Mar 20 21:49 /run/unicorn.sock

I also had to install the following selinux policy module:

module nginx_unix_socket 1.0;

require {
        type httpd_t;
        type unconfined_service_t;
        class unix_stream_socket connectto;
}

#============= httpd_t ==============
allow httpd_t unconfined_service_t:unix_stream_socket connectto;

To install the module (assuming it it stored in nginx_unix_socket.te):

checkmodule -M -m -o nginx_unix_socket.mod nginx_unix_socket.te
semodule_package -o  nginx_unix_socket.pp -m nginx_unix_socket.mod
semodule -i nginx_unix_socket.pp

That should be all you need. I have in my nginx configuration:

location / {
        proxy_pass http://unix:/run/unicorn.sock;
}

With that in place, curl localhost successfully connects to the gunicorn service bound to /run/unicorn.sock.

Answered By: larsks
Categories: Answers Tags: , ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.