A systemd unit file for Play Framework

comments 8
Ops

New for Ubuntu 16.04 (Xenial Xerus) is systemd which replaces Upstart as the default init system.

systemd basics

The basic object that systemd manages is the unit which can be of different types but when it comes to running our Play app we will need to create a service.

The systemctl command is used to manage systemd services, similar to the old service command. E.g. to start Nginx you now type:

sudo systemctl start nginx.service

Custom unit files should go in the /etc/systemd/system directory and you should always run the following command after creating new unit files or modifying existing ones:

sudo systemctl daemon-reload

Run levels have been replaced with systemd units called targets. Target unit files end with the .target file extension and they are used to group other units.

A Play Framework unit file

Here is a basic Play Framework systemd unit file. It makes use of the EnvironmentFile directive which can be used to set environment variables. It is possible to set environment variables in the unit file directly but using a separate file takes some of the clutter out.


ADDRESS=127.0.0.1
PORT=9000
APPLY_EVOLUTIONS=true
APPLICATION_SECRET=my_secret

view raw

env

hosted with ❤ by GitHub


[Unit]
Description=My play app
After=network.target
[Service]
EnvironmentFile=/path/to/app/conf/env
PIDFile=/path/to/app/RUNNING_PID
WorkingDirectory=/path/to/app
ExecStart=/path/to/app/bin/play -Dhttp.address=${ADDRESS} -Dhttp.port=${PORT} -Dplay.evolutions.db.default.autoApply=${APPLY_EVOLUTIONS} -J-server
Restart=on-failure
User=play_user
Group=play_user
# See http://serverfault.com/a/695863
SuccessExitStatus=143
[Install]
WantedBy=multi-user.target

view raw

play.service

hosted with ❤ by GitHub

Deploying the unit file

  • Create the env file in your app’s conf directory and unit file in /etc/systemd/system
  • Set the file permissions
sudo chmod 664 /etc/systemd/system/play.service
  • Reload systemd
sudo systemctl daemon-reload

You can now start and stop your play app using systemctl

sudo systemctl start play.service
sudo systemctl stop play.service

 

8 Comments

  1. Thanks for posting this David. It was very useful.

    Question: When I do a “system enable my-app” I get the following error msg:

    Failed to execute operation: Invalid argument

    Please advise.

  2. Hmm, not a very helpful error message, is it? Does journalctl -xn show anything useful? Are there any problems with environment variables being used?

  3. Both options ExecStop and ExecStopPost are superfluous as this is the default behavior of systemd.

    From the documentation of ExecStop: “If this option is not specified, the process is terminated by sending the signal specified in KillSignal= when service stop is requested.”

    From PIDFile’s documentation: “systemd will not write to the file configured here, although it will remove the file after the service has shut down if it still exists.”

    Furthermore, you should add option SuccessExitStatus=143. Details: http://serverfault.com/a/695863/140809

  4. Daniel says

    Hi

    Do you know, if there is a way to Type=forking the play systemd unit file?
    Without any type Type=simple is assumed; with this I don’t get an error message, if the startup wasn’t successful. I have to do a status after startup to see, if the play app started.
    Do you have an idea, how I could get an error message when the startup fails?
    My systemd unit file looks like that:

    # Systemd unit file for playapp (Netty)
    [Unit]
    Description=Run Server for playapp (Netty)
    Wants=syslog.target network.target
    After=network.target

    [Service]
    Type=simple

    PIDFile=/opt/playapp/play.pid

    ExecStart=/opt/playapp/bin/playapp
    ExecStop=/bin/kill $MAINPID
    Restart=always
    SuccessExitStatus=143

    [Install]
    WantedBy=multi-user.target

    Like this, if e.g. the launcher.jar (started by the bin/playapp script) doesn’t exist, the Type=simple shows no error. But the Type=forking returns an error. But if everything works fine, the systemctl start playapp.service remains in the foreground.

    Do you have a tip to improve my systemd unit file?

    Thanks
    Daniel

  5. Yeah this does look like a problem. Here’s a blog post that seems relevant. I didn’t have much luck redirecting output to the terminal or trying to run with Type=forking and getting the play app to run in the background. What does appear to work is if you set Type=forking and then CTRL+C to get back to a terminal after launch. This doesn’t seem like a great idea though. 🙁

Leave a Reply to Daniel

Your email address will not be published. Required fields are marked *