Deploy a darkbot or a simple generic service with SaltStack (part 2)

This is the part 2 of our service deployment walkthrough.
See also: Part 1 — Service accounts, sudo capabilities

In the first part, we’ve seen how to create an user account for the service, a group to put users with access to the service into, and sudo capabilities to allow full control on the service account, some control as root to interact with systemd or another service manager.

Deploy an application through package

If your application is packaged or you package it, something we recommend hearthily, you can simply the pkg.installed state.

For example if you wish to deploy with this state configuration:

If you only have one application you installed, you can omit pkgs, it will then take the state name:

If you want to force the last version to be reinstalled when you run again the state, you can instead use pkg.latest:

Salt can then take care of your upgrade process.

Deploy an application fetching and building it

In this sample, we’ll fetch the source code from the last version of the production branch of a Git repository cloned at /usr/local/src/darkbot, and we’ll install the software to /opt/odderon. To use /opt will allow us to perform an installation process running as a non privileged user.

Fetch the source code

Sometimes, you want a workflow to fetch, build, install, to have a better control on the compilation. Docker image creators tend to like to automate build processes.

For that, you need two things:

  1. A directory where to clone the software
  2. To actually clone the repository

A same Salt state can call several functions, here one from file to create a directory ( and one from git to clone (git.latest):

We’ve reused the user and group created in previous part.

To clone the repository, we recommend to do the clone from a source you can trust (e.g. PHP provides GPG signed packages) or better, a source you control.

Note it’s currently not possible to call two functions from the same module, e.g. two git or two file wouldn’t work.

If you automate the upgrade process (something best to do only if your CI/CD infrastructure tests the Salt deployment), provide your deployers a quick way to stop the update process.

For example, you can provide a lock file in the application directory (here /opt/odderon):

If the file exists, state will be skipped, so it’s as simple as touch /opt/odderon/LOCKED to pause deployment, rm /opt/odderon/LOCKED to resume it. SaltStack has a good documentation about requisites, requisites not always intuitive.


Let’s start with a simple case where you only have one command to write to configure, compile, install, for example here: ./ --with-sleep=0 --with-add=0 --with-del=0 --with-random=0 --destdir=/opt/odderon.

For that, you only need

The cwd parameter allows to change the working directory (cd /usr… ; ./…) and runas to run the command as another user than root.

If you don’t have such script available, just create it.

Salt allows to deploy a custom script before to run it in one step with the cmd.script command:

The roles/shellserver/odderon/files/ file will be copied on the server, and run, and yes you can also send arguments to the script like with

This process isn’t useful if Git failed, so we can require another state succeeded:

The same process can be used to provide the service configuration. For example, to copy a hierarchy of files from your Salt root directory to the server:

The 770 directory mode will allow the service and the deployers to access it, files by default read only for deployers to encourage to use Salt to edit them.

By the way, you probably also want a warning like this:

It’s then clear when you’re on the production server a file opened is managed.

Upgrade the code

So, what can you do with that?

First, it can provision your service to a new server, but you can also use it for updat. For example, if you’ve your states in roles/shellserver/odderon/init.sls, you can upgrade with:

salt eglide state.apply roles/shellserver/odderon

It will then upgrade your package or fetch the latest Git commit and recompile your code.

If you compile manually, note the build script doesn’t especially need a clean step. For example, if you use a Makefile, make will detect your file has been modified (looking the timestamp) and so should be upgraded.

Create a service

Thanks to Sandlayth to have prepared the Salt configuration for this part.

If your application doesn’t provide a service, it’s valuable to create one.

Two steps are needed: deploy the service file, ensure the service runs. For systemd, a third step is needed to force reload configuration.

The first part is service manager dependant, the second part is service manager agnostic.

We told you there is an extra step for systemd. This one is tricky: as this is a command to refresh an application knowledge, that’s not something we can declare and check, so it’s not available as a state. SaltStack also allows to run commands, and provide modules for that. For example, you can do salt eglide service.force_reload odderon (see systemd module doc, right menu offers the same for other systems).

Parameters for the module you run are directly put after the name. But here service.force_reload has also a name parameter. To disambiguate, you prepend m_ and get m_name.

There is currently in Salt a work of progress to abstract more the services.

Finally, whatever the service manager, you want to ensure the service runs:

The enable parameter is useful if you use a systemd-like service, as the service must be explicitly enabled to be automatically launched at server start time.

One Reply to “Deploy a darkbot or a simple generic service with SaltStack (part 2)”

Leave a Reply

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