1

I am deploying an Nodejs Express app. It is going to run as on the same box as an Nginx server, which will proxy requests to it via a unix socket. The question is not specific to Nodejs, however.

The express app runs as user nodejs, and nginx runs as nginx.

My plan is to create a /sockets directory owned by nodejs for Express to put sockets in, and to grant nginx access to those sockets via a default ACL on the directory. Feel free to tell me if this is a silly idea, but keep in mind that's not my core question.

I create ACLs on the directory by running, as root,

setfacl -Rd --mask -m nginx:rw  /sockets
setfacl -R  --mask -m nginx:rwX /sockets

The directory then has the following ACLs: (tabulation by me for legibility in the question)

# file: /sockets
# owner: nodejs
# group: root
user:      : rwx
user: nginx: rwx
group:     : r-x
mask:      : rwx
other:     : r-x
default: user:     :rwx
default: user:nginx:rw-
default:group:     :r-x
default: mask:     :rwx
default:other:     :r-x

If, running as nodejs, I write to a file, it is created appropriately:

sudo -su nodejs
touch /sockets/testFile
getfacl /sockets/testFile

# file: /sockets/testFile
# owner: nodejs
# group: nodejs
user:     :rw-
user:nginx:rw-
group:    :r-x                      #effective:r--
mask:     :rw-
other:    :r--

Great!

However, if Node creates a socket by calling listen() on a path in this directory , it is created with an ACL mask that prevents nginx from accessing it.

const e = require('express')()
e.listen('/sockets/testSocket', (e) => console.error(e))

getfacl /sockets/testSocket 
# file: /sockets/testSocket
# owner: nodejs
# group: nodejs
user:     :rwx
user:nginx:rw-                  #effective:r--
group:    :r-x
mask:     :r-x
other:    :r-x

If I create an ordinary file with Nodejs in /sockets (e.g. by fs.writeFile) it is created with the same permissions as when I ran touch /sockets/testFile above, so I don't think it's a problem of Node's umask.

Likewise, if I run equivalent code to bind to a socket in python, the results are the same, so I don't think it's a problem with Node itself.

Obviously, this is stopping Nginx from talking to my Express app. Can anyone work out why? :/ The server is running CentOS 7.

  • I'm currently experiencing the same issue. Were you ever able to resolve it? – Dominic P Aug 10 '17 at 22:02
  • @DominicP I ended up running umask 022 before node, from memory. – Jarrad Aug 18 '17 at 2:57
  • Gotcha, thanks for reply. I'm hacking it by manually running fs.chmod on the socket from my app when it starts like this. – Dominic P Aug 18 '17 at 21:59
0

The answer is that socket() is a libc function that doesn't implement the ACL policies that are documented at 100%.

Through experimentation I found that you have to set the umask for the calling process, which according to ACL rules should not matter when creating files, and to successfully create sockets the way you want to, you have to:

umask 0002
setfacl -d -m user:nginx:rwx /sockets
setfacl -d -m group::rwx /sockets
setfacl -d -m mask::rwx /sockets

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.