= Riffol

Riffol is a supervising process that can run as a traditional daemon
on Unix-like systems or as an `init` system for containers (such as
https://github.com/krallin/tini[tini]).

Riffol can be configured by creating application groups that consist
of applications and health checks.

[source]
----
   +--------+
   | Riffol |
   +----+---+
        |
        |
        |
 +------v------+
 | Application |
 |    Group    +-------+-------------+
 +------+------+       |             |
        |              |             |
        |              |             |
        |              |             |
 +------v------+   +---v----+   +----v-----+
 | Application |   | Health |   | Resource |
 +-------------+   | Check  |   |  Limits  |
                   +--------+   +----------+
----

Riffol uses the unified configuration model from
https://github.com/riboseinc/event-configuration-models for its
configuration syntax definition, startup configuration and also
runtime configuration.

Riffol is implemented in Rust.

=== Building From Source

Make sure there is a Rust environment installed. Otherwise follow the
https://www.rust-lang.org/en-US/install.html[Rust installation guide].

[source,shell]
----
cargo install --git https:/github.com/riboseinc/riffol
----

This command will build a `riffol` binary and store it in the `bin`
directory under `$CARGO_HOME` - usually `~/.cargo/bin/riffol`.

== Usage

 riffol [-f config-file]

Riffol requires a configuration file. The default location of this
file is `/etc/riffol.conf`.

This location can be specified either via the `RIFFOL_CONFIG`
environment variable or by using the `-f` command line flag.

== Configuration

=== Init

The main configuration to create application groups:

[source]
----
init name {
  application_groups [
    applicationgroup.name
  ]
}
----

E.g.:

[source]
----
init web {
    application_groups ["applicationgroup.webstack"]
}
----

=== Application Group

[source]
----
application_group name {
  applications [
    "application.name"
  ]
}
----

E.g.:

[source]
----
application_group webstack {
  applications [
    "application.db"
    "application.www"
  ]
}
----

=== Application

[source]
----
application "name" {
  mode application_mode
  requires [other applications]
  start [executable start args]
  stop [executable stop args]
  pidfile file
  dir working_directory
  env {
    new var1 value
    new var2 value
    pass oldname newname
  }
  env_file env_filename
  stdout stream_destination
  stderr stream_destination
  uid int
  gid int
  healthchecks [
    "healthcheck.name"
  ]
}
----

`application_mode` can be one of `oneshot`, `simple` or `forking`

Applications are started with a clean environment. Environment
variables can be added with `env` and `env_file` fields.

`env` values can take two forms. `env new <name> <value>` creates a
new variable with the supplied value. `env pass <oldname> <newname>`
creates a new variable named `newname` with the value taken from
Riffol's environment variable `oldname`.

[source]
----
env {
    new {
        VAR1 value1
        VAR2 value2
    }
    pass {
        ENV1 VAR3
        ENV2 VAR4
    }
}
----

This creates two new environment variables, `VAR1` and `VAR2` with
values `value1` and `value2` respectively. It also passes the
variables `ENV1` and `ENV2` into new variables `VAR3` nad `VAR4`
respectively.

`env_file <filename>` reads a file of environment variables, one per
line in the following format:

[source]
----
VAR1=value1
VAR2=value2
VAR3
VAR4=
----

`VAR1` and `VAR2` are set to `value1` and `value2`
respectively. `VAR3` and `VAR4` are set to the empty value "".

The `env_file` field is processed before the `env` field so variables
set up using `env` will override those read from `env_file`.

`stream_destination` can be one of:
[source]
----
file [
    filename
]
----
[source]
----
syslog {
    socket unix_sock_address
    facility syslog_facility
    severity syslog_severity
}
----
[source]
----
rsyslog {
    address remote_inet_address
    local local_inet_address
    facility syslog_facility
    severity syslog_severity
}
----

`syslog_facility` is one of `kern`, `user`, `mail`, `daemon`, `auth`,
`syslog`, `lpr`, `news`, `uucp`, `cron`, `authpriv`, `ftp`, `local0`,
`local1`, `local2`, `local3`, `local4`, `local5`, `local6` or
`local7`.  (default `daemon`)

`syslog_severity` is one of `emerg`, `alert`, `crit`, `err`,
`warning`, `notice`, `info` or `debug` (default `debug`)

`healthcheckfail` can be one of `start`, `restart` or `stop`.
E.g.:

[source]
----
application www {
  exec "/etc/init.d/http"
  dir "/var/www"
  env {
    new var1key var1value
    new var2key var2value
    pass oldname newname
  }
  env_file "/etc/httpd/morevars"
  start start
  stop stop
  restart restart
  stdout file "/var/log/riffol_www.log"
  stderr syslog {
  }
  uid 0
  gid 0
  healthchecks [
    "healthcheck.www"
  ]
  healthcheckfail restart
}
----

=== Health Check

[source]
----
healthcheck name {
  checks [
    "class://value"
  ]
  interval int
  timeout int
}
----

There are several `checks` classes:

. `df`, disk free space
. `proc`, process name
. `tcp`, TCP connection
. `udp`, UDP connection
. `http`, establish a http connection
. `https`, establish a https connection

Parameters:

. `interval`, the interval of the check defined in seconds
. `timeout`, the timeout of network connections defined in seconds

E.g.:

[source]
----
healthcheck db {
  checks [
    "df:///var/lib/mysql:512"
    "proc://mysqld",
    "tcp://127.0.0.1:3306"
  ]
  interval 60
  timeout 10
}
----

=== Resource Limits

[source]
----
limits name {
  max_procs int
  max_mem int
}
----

e.g.:

[source]
----
limits db {
  max_procs 4
  max_mem 1024
}
----

== ... Riffol?

https://en.wikipedia.org/wiki/Salmon_run#The_spawning

> The eggs of a female salmon are called her roe. To lay her roe, the
  female salmon builds a **spawn**ing nest, called a redd, in a riffle
  with gravel as its streambed. A **riffle** is a relatively shallow
  length of stream where the water is turbulent and flows faster.

By spelling "riffol" with an O, we are putting the chemical symbol for
oxygen in the word: we are
https://en.wikipedia.org/wiki/Redox[oxidising] Riffol. Which makes
sense, since Riffol is in Rust.
