#container #supervisor #init

bin+lib horust

A complete supervisor and init system, designed for running in containers

7 releases

0.1.6 Dec 18, 2022
0.1.4 May 6, 2021
0.1.3 Apr 26, 2021
0.1.2 Mar 8, 2021
0.0.1 Mar 14, 2020

#706 in Command line utilities

Download history 6/week @ 2024-02-26 102/week @ 2024-04-01

102 downloads per month

MIT license

115KB
2.5K SLoC

CI MIT licensed Gitter chat

Horust is a supervisor / init system written in rust and designed to be run inside containers.

Table of contents

Goals

  • Supervision: Be a fully-featured supervision system, designed to be run in containers (but not only).
  • Easy to Grasp: Have code that is easy to understand, modify and remove when the situation calls for it.
  • Completeness: Be a drop-in replacement for your own init system.
  • Rock Solid: Be your favorite Egyptian God, to trust across all use cases.

Status

At this point, this should be considered Alpha software. As in, you can (and should) use it, but under your own discretion.

Usage

Assume you'd like to create a website health monitoring system. You can create one using Horust and a small python script.

1. Create a new directory:

That will contain our services:

mkdir -p /etc/horust/services

2. Create your first Horust service:

Pro Tip: You can also bootstrap the creation of a new service, by using horust --sample-service > new_service.toml.

Create a new configuration file for Horust under /etc/horust/services/healthchecker.toml:

command = "/tmp/healthcheck.py"
start-delay = "10s"
[restart]
strategy = "never"

A couple of notes are due here:

  • This library uses TOML for configuration, to go along nicely with Rust's chosen configuration language.
  • There are many supported properties for your service file, but only command is required.

On startup, Horust will read this service file, and run the command. According to the restart strategy "never", as soon as the service has carried out its task it will not restart, and Horust will exit.

As you can see, it will run the /tmp/healthcheck.py Python script, which doesn't exist yet. Let's create it!

3. Create your Python script:

Create a new Python script under /tmp/healthcheck.py:

#!/usr/bin/env python3
import urllib.request
import sys
req = urllib.request.Request("https://www.google.com", method="HEAD")
resp = urllib.request.urlopen(req)
if resp.status == 200:
    sys.exit(0)
else:
    sys.exit(1)

Don't forget to make it executable:

chmod +x /tmp/healthcheck.py

4. Build Horust:

This step is only required because we don't have a release yet, or if you like to live on the edge.

For building Horust, you will need Rust. As soon as it's installed, you can build Horust with Rust's cargo:

cargo build --release

4. Run Horust:

Now you can just:

./horust

By default Horust searches for services inside the /etc/horust/services folder (which we have created in step 1).

Every 10 seconds from now on, Horust will send an HTTP HEAD request to https://google.it. If the response is different than 200, then there is an issue!

In this case, we're just exiting with a different exit code (i.e. a 1 instead of a 0). But in real life, you could trigger other actions - maybe storing this information in a database for long-term analysis, or sending an e-mail to the website's owner.

5. Finish up:

Use Ctrl+C to stop Horust. Horust will send a SIGTERM signal to all the running services, and if it doesn't hear back for a while - it will terminate them by sending an additional SIGKILL signal.


Check out the documentation for a complete reference of the options available on the service config file. A general overview is available below as well:

command = "/bin/bash -c 'echo hello world'"
start-delay = "2s"
start-after = ["database", "backend.toml"]
stdout = "STDOUT"
stderr = "/var/logs/hello_world_svc/stderr.log"
user = "root"
working-directory = "/tmp/"

[restart]
strategy = "never"
backoff = "0s"
attempts = 0

[healthiness]
http-endpoint = "http://localhost:8080/healthcheck"
file-path = "/var/myservice/up"

[failure]
successful-exit-code = [ 0, 1, 255]
strategy = "ignore"

[termination]
signal = "TERM"
wait = "10s"
die-if-failed = ["db.toml"]

[environment]
keep-env = false
re-export = [ "PATH", "DB_PASS"]
additional = { key = "value"} 

Contributing

Thanks for considering contributing to horust! To get started have a look on CONTRIBUTING.md.

License

Horust is provided under the MIT license. Please read the attached license file.

Dependencies

~6–21MB
~278K SLoC