December 02, 2015

nginx + FastCGI + Plack + systemd

One of my backburner projects has been to migrate this here website onto a fresh server. I never want to feel stuck on an old server again, so I've been investing time to make deploying the full sartak.org experience both quick and painless. That means managing all the configuration with the configuration manager I hate the least. Today that happens to be Ansible.

As part of this betterment, I have decided that the following is no longer an acceptable way to manage web applications:

$ crontab -l
…
@reboot cd /home/sartak/Sartak-Microblog; screen -dmUS microblog plackup -Ilib -E production -s FCGI --listen /tmp/microblog.sock -a app.psgi
@reboot cd /home/sartak/Sartak-Quotes; screen -dmUS quotes plackup -Ilib -E production -s FCGI --listen /tmp/quotes.sock -a app.psgi

I do admit this setup hasn't caused me much grief (probably thanks to how robust FCGI and Plack are), but it definitely feels like amateur hour. And I'm supposed to be a respectable professional here, sheesh.

Since I'm deploying to the latest Debian, I've decided to give systemd a try. It was a little tricky to find the right incantations but I've smuggled them out just for you.

Here's what I'm working with here. I've got a small, light-traffic Perl web app called Sartak-Microblog. Its code, git repository, and SQLite database all live in /usr/local/share/Sartak-Microblog, so that needs to be the current directory from which the app is launched. nginx will serve it up as http://micro.sartak.org, talking to Plack's FastCGI handler over a UNIX socket in /tmp. This doesn't need to be a Google-scale production. I don't need zero-downtime updates or hot spares or multi-datacenter redundancy. I just want the app to at least try to stay running. Also, letting Plack itself serve my static files is plenty fine by me.

First, the nginx config. (For those following along at home, replace both instances of micro.sartak.org with your domain name)

server {
    server_name micro.sartak.org;
    location / {
        fastcgi_pass unix:/tmp/micro.sartak.org.sock;
        include fastcgi_params;
        fastcgi_param SCRIPT_NAME "";
    }
}

Next is to convince systemd to keep the app running. Drop this into /etc/systemd/system/micro.sartak.org.service (Replace micro.sartak.org and /usr/local/share/Sartak-Microblog, and possibly also app.psgi)

[Unit]
Description=micro.sartak.org
After=network.target

[Service]
ExecStart=/usr/bin/plackup -Ilib -E production -s FCGI --listen /tmp/micro.sartak.org.sock -a app.psgi
WorkingDirectory=/usr/local/share/Sartak-Microblog
Restart=on-failure

[Install]
WantedBy=multi-user.target

Tell systemd to use this new config:

$ systemctl enable /etc/systemd/system/micro.sartak.org.service

And finally, have systemd start the web app now:

$ systemctl start micro.sartak.org

Now when you reboot the machine, the app will be launched automatically. And if the app dies (perhaps it was an accident, perhaps you kill -9'd it), it will be restarted right away.

Sure beats screen in a crontab.