Making Fedora 17, Unicorn and Nginx Work Together

- - posted in Code Snippets, Linux, Rails, fedora, nginx

I had a heck of a time getting a Rails + Unicorn + nginx deployment going on Fedora 17. The problem was, I could get it running using TCP sockets but not using unix sockets. I loosely followed these instructions for deploying a Rails 3.2 app but kept having problems with the unix sockets.

The Solution:

Don’t put the socket file in the /tmp directory.

The Why:

Fedora has this in /etc/systemd/system/multi-user.target.wants/nginx.service

1
2
3
4
5
6
7
8
9
10
11
12
13
14
[Unit]
Description=The nginx HTTP and reverse proxy server
After=syslog.target network.target remote-fs.target nss-lookup.target

[Service]
Type=forking
PIDFile=/run/nginx.pid
ExecStartPre=/usr/sbin/nginx -t
ExecStart=/usr/sbin/nginx
ExecReload=/bin/kill -s HUP $MAINPID
ExecStop=/bin/kill -s QUIT $MAINPID
PrivateTmp=true
[Install]
WantedBy=multi-user.target

And if you look over on the Unicorn site, you’ll see this as the documentation for the listen method / configuration setting

Adds an address to the existing listener set. May be specified more than once. address may be an Integer port number for a TCP port, an “IP_ADDRESS:PORT” for TCP listeners or a pathname for UNIX domain sockets.

1
2
3
4
listen 3000 # listen to port 3000 on all TCP interfaces
listen "127.0.0.1:3000"  # listen to port 3000 on the loopback interface
<strong>listen "/tmp/.unicorn.sock" # listen on the given Unix domain socket</strong>
listen "[::1]:3000" # listen to port 3000 on the IPv6 loopback interface

Which encourages folks to put the socket in the /tmp directory. This is going to cause trouble for every Fedora user that tries to use Unicorn.

While debugging this I got the infamous “502 Bad Gateway” page from nginx. I checked out the error_log, and this message was there:

1
2
3
4
5
6
2013/04/05 12:25:58 [crit] 2906#0: *29 connect() to unix:/tmp/my_project_name.socket failed
                    (2: No such file or directory) while connecting to upstream,
                    client: 192.168.10.234, server: my_project_name.railsit.com,
                    request: "GET / HTTP/1.1",
                    upstream: "http://unix:/tmp/my_project_name.socket:/",
                    host: "my_project_name.railsit.com:8081"

So, after a couple of hours of head scratching and WTF’ing, I remembered that systemd did some crazy shenanigans to mysql, preventing me from setting the file limit higher. As soon as I saw the PrivateTmp=true line in the nginx.service file, I knew that systemd was the culprit.

Hope this helps someone.