MCPcopy Index your code
hub / github.com/FedericoPonzi/Horust

github.com/FedericoPonzi/Horust @v0.1.13

Chat with this repo
repository ↗ · DeepWiki ↗ · release v0.1.13 ↗ · + Follow
303 symbols 644 edges 35 files 66 documented · 22%
What it actually does AI analysis from the code graph — generated when you open this
loading…
README

CI MIT licensed

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

Table of contents

Goals

  • Supervision: A fully-featured supervisor system, easy to use and designed to be run in containers (but not exclusively).
  • Simplicity: Simple to use and simple to modify.
  • Completeness: A seamless drop-in for any init or supervisor system.
  • Reliability: Written using safe and correct wrappers.

Status

This should be considered Beta software. You can (and should) use it, but under your own discretion. Please report any issue you encounter, or also sharing your use cases would be very helpful. Horust can be used on macOS in development situations. Due to limitations in the macOS API, subprocesses of supervised processes may not correctly be reaped when their parent process exits.

Usage

Being a supervision and init system, it can be used to start and manage a bunch of processes. You can use it to supervise a program and, for example, restart it in case it exists with an error. Or startup dependencies like start a webserver after starting a database.

Keep scrolling for a quick tutorial or check out the documentation for a complete reference of the options available on the service config file.

This is a quick overview:

command = "/bin/bash -c 'echo hello world'"
start-delay = "2s"
start-after = ["database", "backend.toml"]
stdout = "STDOUT"
stdout-rotate-size = "100MB"
stdout-should-append-timestamp-to-filename = false
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"
command = "curl -s localhost:8080/healthcheck"

[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" }

[resource-limit]
cpu = 0.5
memory = "100 MiB"
pids-max = 100

How to get started with Horust:

You can grab the latest release from the releases page. If you like to live on the edge, scroll down to the building section.

There are docker releases:

  • Github: https://github.com/FedericoPonzi/Horust/pkgs/container/horust
  • Dockerhub: https://hub.docker.com/r/federicoponzi/horust

You can also pull horust as a library from crates.io, or use cargo to install it:

cargo install horust

Horustctl:

Horustctl is a program that allows you to interact with horust. They communicate using Unix Domain Socket (UDS), and by default, horust stores the sockets in /var/run/horust. You can override the path by using the argument --uds-folder-path. Then you can use it like this:

horustctl --uds-folder-path /tmp status myapp.toml

To check the status of your service. Currently, horustctl only supports querying for the service status.

Quick tutorial

Problem:

Assume you have a container in which you want to run a database and a monitoring system. The database should be started first, and the monitoring system should be started only after the database is up.

A container can spin up a single process, so you create a simple bash file to handle the dependency. Then, if the monitoring system fails or the database fails, you want to restart it. While you figure the different requirements, your simple bash script keeps growing.

Let's see how we can use horust to spin up the two services and monitor them.

1. Create your first Horust service:

[!TIP] You can also bootstrap the creation of a new service, by using horust --sample-service > new_service.toml.

Each program we need to spin up has its own service config file. They are defined in TOML and the default path where horust will look for service is in /etc/horust/services/.

[!NOTE] It's possible to run a one-shot instance just by doing horust myprogram without defining a service config file.

Let's create a new service under /etc/horust/services/database.toml:

command = "python3 /opt/db/my-cool-database.py --bind 0.0.0.0 --port 5323"
start-delay = "2s"
[restart]
strategy = "always"

and another service for the monitoring: /etc/horust/services/monitoring.toml:

command = "python3 /opt/db/monitoring.py --port 5323"
start-after = ["database.toml"]
working-directory = "/tmp/"

There are many supported properties for your service file, but only command is required.

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

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

2. Define your container:

FROM federicoponzi/horust:v0.2.0
# Install dependencies for my cool db
RUN apt-get update && \
    apt-get install -y python3 python3-pip && \
    pip3 install requests

COPY db /opt/db/

# Copy Horust service definition into the container
COPY database.toml /etc/horust/services/
COPY monitoring.toml /etc/horust/services/

# Set entrypoint to Horust
ENTRYPOINT ["/sbin/horust"]

and we're ready to start our container: docker build -t my-cool-db . and docker run -it --rm --name my-cool-db my-cool-db.

3. Terminate the container

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. Wait time and signals are configurable.

Building

For building Horust, you will need Rust and protoc compiler. Protoc is used for interacting with horust through horustctl. As soon as both are installed, you can build Horust with:

cargo build --release

Contributing

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

License

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

Extension points exported contracts — how you extend this code

Check (Interface)
(no doc) [3 implementers]
horust/src/horust/healthcheck/checks.rs
CommandsHandlerTrait (Interface)
(no doc) [2 implementers]
commands/src/server.rs

Core symbols most depended-on inside this repo

iter
called by 23
horust/src/horust/bus.rs
send_event
called by 13
horust/src/horust/bus.rs
spawn
called by 13
horust/src/horust/supervisor/mod.rs
service
called by 9
horust/src/horust/supervisor/service_handler.rs
kill
called by 9
horust/src/horust/supervisor/mod.rs
eprint_ssafe
called by 8
horust/src/horust/signal_safe.rs
join_bus
called by 7
horust/src/horust/bus.rs
get_mut_sh
called by 7
horust/src/horust/supervisor/repo.rs

Shape

Function 129
Method 117
Class 38
Enum 17
Interface 2

Languages

Rust100%

Modules by API surface

horust/src/horust/formats/service.rs51 symbols
horust/src/horust/supervisor/service_handler.rs29 symbols
horust/src/horust/bus.rs21 symbols
horust/src/horust/mod.rs16 symbols
horust/src/horust/supervisor/repo.rs15 symbols
commands/src/proto/messages.rs14 symbols
horust/src/horust/healthcheck/mod.rs13 symbols
horust/tests/section_general.rs10 symbols
horust/src/horust/healthcheck/checks.rs10 symbols
horust/src/horust/formats/mod.rs10 symbols
horust/src/horust/supervisor/process_spawner.rs9 symbols
horust/tests/utils/mod.rs8 symbols

For agents

$ claude mcp add Horust \
  -- python -m otcore.mcp_server <graph>

⬇ download graph artifact