How to start a Play Framework application running as a service on Ubuntu 16.04

As a relatively brief note, this seems to be the correct way to start a Play Framework application as a service on an Ubuntu 16.04 system.

A shell script to start your Play application

First, you need to create a little Unix shell script that runs the startup command for your Play Framework application. I created a Play application for a website named kbhr.co, so I cd into the directory for that website:

$ cd /var/www/kbhr.co

With my Play application zip file unzipped under this directory, I now create a shell script in this directory named StartServer.sh, with these contents:

#!/bin/bash

ROOT_DIR=/var/www/kbhr.co

${ROOT_DIR}/kbhr-1.0/bin/kbhr \
    -Dplay.http.secret.key='SUPER-SECRET-KEY-HERE' \
    -Dhttp.port=9000 \
    -J-Xms128M \
    -J-Xmx256m \
    -J-server \
    -Dconfig.file=${ROOT_DIR}/kbhr.conf

Note that my Play application is in the kbhr-1.0 directory that’s inside this directory.

Now make this shell script executable (with chmod +x), and run it to confirm that it works as desired. Very importantly, be sure to stop the application after you confirm that it works.

Setting up the Ubuntu 16.04 service

To set up the Ubuntu 16.04 service for your application, first become the root user:

$ su -

Then cd to the Ubuntu directory for system services:

# cd /etc/systemd/system

Then create a “service” file that defines the characteristics of your Play application. Because my app is for kbhr.co, I name my file kbhr.service:

# vi kbhr.service

Put these contents in that file:

# A Play Framework application systemd service file

[Unit]
Description=My KBHR Play Framework app
# `After` tells systemd when the script should be run.
# (`network.target` or `mysql.service` seems best)
After=mysql.service

[Install]
# `WantedBy` is what boot target the systemd unit should be installed into
# (should probably be `default.target` or `multi-user.target`)
WantedBy=multi-user.target

[Service]
User=alvin
Group=alvin
ExecStart=/var/www/kbhr.co/bin/StartService.sh

I think those are the correct attributes for an application like this (and if they’re not 100% correct, I at least know that they work). Note that I tell the system what Linux user and group the application should be started as, and I specify the path to the shell script I created earlier as the ExecStart parameter.

Now you just need to run a few commands to load this file into the Ubuntu systemd system. First, make sure your file has the right permissions:

# chmod 644 kbhr.service

Then tell the system to find your new service:

# systemctl daemon-reload

Now tell the system to enable your service; this command creates a symbolic link:

# systemctl enable kbhr.service

  Created symlink from /etc/systemd/system/multi-user.target.wants/kbhr.service 
  to /etc/systemd/system/kbhr.service.

Finally, start your service:

# systemctl start kbhr.service

Now you should be able to run a ps command like this and see that your Play Framework application is running:

# ps auxw | grep java | grep kbhr

You should see a very long line of output that begins with a java command, like this:

java -Duser.dir=/var/www/kbhr.co/kbhr-1.0...

This tells you that your application has been started. You can now test it with your browser or a curl command.

If everything is running as expected, this is a great time to reboot it to make sure that your service is started after the reboot.

More information

There are many more configuration variables you can add to your service. For example, here’s the mysql.service file from the /etc/systemd/system/multi-user.target.wants directory on my Ubuntu 16.04 system:

# MySQL systemd service file

[Unit]
Description=MySQL Community Server
After=network.target

[Install]
WantedBy=multi-user.target

[Service]
User=mysql
Group=mysql
PermissionsStartOnly=true
ExecStartPre=/usr/share/mysql/mysql-systemd-start pre
ExecStart=/usr/sbin/mysqld
ExecStartPost=/usr/share/mysql/mysql-systemd-start post
TimeoutSec=600
Restart=on-failure
RuntimeDirectory=mysqld
RuntimeDirectoryMode=755

Here’s the nginx.service file from that same directory:

[Unit]
Description=A high performance web server and a reverse proxy server
After=network.target

[Service]
Type=forking
PIDFile=/run/nginx.pid
ExecStartPre=/usr/sbin/nginx -t -q -g 'daemon on; master_process on;'
ExecStart=/usr/sbin/nginx -g 'daemon on; master_process on;'
ExecReload=/usr/sbin/nginx -g 'daemon on; master_process on;' -s reload
ExecStop=-/sbin/start-stop-daemon --quiet --stop --retry QUIT/5 --pidfile /run/nginx.pid
TimeoutStopSec=5
KillMode=mixed

[Install]
WantedBy=multi-user.target

I didn’t specify ways to stop or reload my application, so the Nginx file is particularly useful as an example of how to do that. For much more information on this process, run this man command on your system:

man systemd.service

This tutorial was also helpful:

Summary

In summary, if you wanted to see how to start a Play Framework application as a service on an Ubuntu 16.04 system, I hope this example is helpful.