Zenaton white logo

Going to production

Before we start, let's define some vocabulary that will be used in the next step.

Web App
Web App represents servers that will receive HTTP traffic from your users. They are able to run your application code.
Worker
Workers are servers dedicated to the execution of workflows and tasks. They have access to the same code as the Web App servers. Technically, they are not so different from Web App servers. They have the necessary software needed to run your application. The only difference is that they should not handle HTTP traffic from your users. It's more a conceptual difference, to be able to separate the load generated from HTTP traffic and the load generated by workflows and tasks, to make sure one will not have any performance impact on the other.
Agent
The Zenaton Agent means the software we distribute which is running on your servers (Web App and Workers). It's a binary, run as a daemon.

Dedicated workers setup

On both your Web App and your workers, you will need to:

  • have Ruby installed;
  • have workflows and tasks' source code available;
  • have a Zenaton Agent installed, configured and always running.

Network traffic

Traffic is always initiated by the Agent to Zenaton. You must open the following ports for the Agent to work:

  • Outbound
    • 443/tcp: port used by the Agent to send requests to Zenaton API
    • 5672/tcp: port used by the Agent to send and receive instructions

Client Mode

Since we don't want any task execution to happen in your Web App, we will start the Agent there in "client mode". Client mode means that the Agent is able to dispatch workflows and tasks, send events, pause, kill and resume workflows, but will not handle any of the executions.

To start the Agent in client mode, just add the --client option during configuration:

zenaton listen --client --php
zenaton listen --client --node
zenaton listen --client --ruby
zenaton listen --client --python
zenaton listen --client --go

On your Workers, configure the Agent as usual:

zenaton listen --boot=boot.php
zenaton listen --boot=boot.js
zenaton listen --boot=boot.rb
zenaton listen --boot=boot.py
zenaton listen --boot=boot/boot.go

If you want to use your Web App as a Worker also, and thus avoid having more servers to manage, just configure your Agent in your Web App as if it was a Worker.

Environment

When deploying to production, make sure to use the production environment.

ZENATON_APP_ENV=production

Keep the Agent Running

To make sure your application is able to dispatch tasks and workflows at any time, you need to make sure the Agent is always running and listening using your application credentials.

To enforce this, you will need to use a software capable of monitoring the execution of a process and make sure it's always running. You can use systemd, supervisord, or any similar software to achieve this. Let's see how we can do that using systemd. You will need to run the following commands as user root.

First, create a systemd unit file:

touch /etc/systemd/system/zenaton-agent.service

Make sure the file permissions are correct:

chmod 664 /etc/systemd/system/zenaton-agent.service

Open the file we just created with your favorite text editor and add the following content:

[Unit]
Description=Zenaton Agent Daemon service
After=network-online.target

[Service]
Type=forking

# User and group that will be used to run your Zenaton Agent. User must have a Zenaton Agent installation
# in its home directory and have correct permissions to execute your sources.
User=...
Group=...

# Path to sources of your workflows & tasks.
WorkingDirectory=...

# Add your exact listen command
ExecStartPost=/usr/local/bin/zenaton listen --boot=...

ExecStart=/usr/local/bin/zenaton start
ExecStop=/usr/local/bin/zenaton stop
Restart=always

[Install]
WantedBy=multi-user.target

Make sure to replace ... with correct values.

Deploying to Heroku

To be able to use Zenaton in your Heroku hosted app, you will need to use our Heroku buildpack. The buildpack will install a Zenaton Agent inside your dynos, allowing your application to dispatch tasks and workflows, send events, etc. You will also be able to use your dynos as Zenaton workers.

Installation

To add the buildpack to your project, as well as the required environment variables, use the following commands:

cd <HEROKU_PROJECT_ROOT_FOLDER>

# If this is a new Heroku project
heroku create

# Add the appropriate language-specific buildpack
heroku buildpacks:add heroku/php

# Add Zenaton buildpack and set your Zenaton credentials
heroku buildpacks:add --index 1 zenaton/heroku-buildpack-zenaton
heroku config:set ZENATON_APP_ID=<ZENATON_APP_ID>
heroku config:set ZENATON_API_TOKEN=<ZENATON_API_TOKEN>
heroku config:set ZENATON_APP_ENV=production
# ZENATON_LISTEN_ARGS environment variable is used to give the parameters you want to use for the listen command of the Agent
heroku config:set ZENATON_LISTEN_ARGS="--boot=boot.php --php"

# Deploy to Heroku
git push heroku master
cd <HEROKU_PROJECT_ROOT_FOLDER>

# If this is a new Heroku project
heroku create

# Add the appropriate language-specific buildpack
heroku buildpacks:add heroku/nodejs

# Add Zenaton buildpack and set your Zenaton credentials
heroku buildpacks:add --index 1 zenaton/heroku-buildpack-zenaton
heroku config:set ZENATON_APP_ID=<ZENATON_APP_ID>
heroku config:set ZENATON_API_TOKEN=<ZENATON_API_TOKEN>
heroku config:set ZENATON_APP_ENV=production
# ZENATON_LISTEN_ARGS environment variable is used to give the parameters you want to use for the listen command of the Agent
heroku config:set ZENATON_LISTEN_ARGS="--boot=boot.js --node"

# Deploy to Heroku
git push heroku master

cd <HEROKU_PROJECT_ROOT_FOLDER>

# If this is a new Heroku project
heroku create

# Add the appropriate language-specific buildpack
heroku buildpacks:add heroku/ruby

# Add Zenaton buildpack and set your Zenaton credentials
heroku buildpacks:add --index 1 zenaton/heroku-buildpack-zenaton
heroku config:set ZENATON_APP_ID=<ZENATON_APP_ID>
heroku config:set ZENATON_API_TOKEN=<ZENATON_API_TOKEN>
heroku config:set ZENATON_APP_ENV=production
# ZENATON_LISTEN_ARGS environment variable is used to give the parameters you want to use for the listen command of the Agent
heroku config:set ZENATON_LISTEN_ARGS="--boot=boot.rb --ruby"

# Deploy to Heroku
git push heroku master
cd <HEROKU_PROJECT_ROOT_FOLDER>

# If this is a new Heroku project
heroku create

# Add the appropriate language-specific buildpack
heroku buildpacks:add heroku/python

# Add Zenaton buildpack and set your Zenaton credentials
heroku buildpacks:add --index 1 zenaton/heroku-buildpack-zenaton
heroku config:set ZENATON_APP_ID=<ZENATON_APP_ID>
heroku config:set ZENATON_API_TOKEN=<ZENATON_API_TOKEN>
heroku config:set ZENATON_APP_ENV=production
# ZENATON_LISTEN_ARGS environment variable is used to give the parameters you want to use for the listen command of the Agent
heroku config:set ZENATON_LISTEN_ARGS="--boot=boot.py --python"

# Deploy to Heroku
git push heroku master

Replace <ZENATON_APP_ID> and <ZENATON_API_TOKEN> with your Zenaton credentials.

When the deploy is finished, the Zenaton Agent will be automatically started when each dyno starts.
The Agent is started in client mode in order to avoid adding load to your web dyno.

Worker dynos

If you want to use some dynos to perform the execution of workflows and tasks, you have to make some dynos using type zenatonworker. These dynos will start the Zenaton Agent in regular mode, executing workflows and tasks. In order to make these worker dynos, add them in your Procfile:

# Procfile
web: vendor/bin/heroku-php-apache2 web/
zenatonworker: tail -f /dev/null
# Procfile
web: node index.js
zenatonworker: tail -f /dev/null
# Procfile
web: bundle exec puma -C config/puma.rb
zenatonworker: tail -f /dev/null
# Procfile
web: gunicorn gettingstarted.wsgi --log-file -
zenatonworker: tail -f /dev/null

Because the buildpack automatically starts the Zenaton Agent, you do not need to provide any specific command for the dyno, that's why we use tail -f /dev/null.