system-hook

Crates.io Docs.rs

shook at its core is a web server that listens for webhooks from Github and then will automatically pull new changes to your repository and restart your production servers with the new code. Shook assumes your server is running through systemd and will automatically pull new changes and restart the service.

Installation

note: shook is designed to run on linux systems that use systemd.

cargo-binstall

shook can be installed using cargo-binstall:

shell cargo binstall system-hook

Github Releases

shook can be downloaded from Github Releases

Build from Source

shook can be built from source using cargo:

shell cargo install system-hook

Or, locally:

shell git clone https://github.com/beaconbrigade/system-hook.git cd system-hook cargo build --release

Usage

shook has three main commands: init, serve and daemon. To prepare shook navigate to the repository you want to watch, and run sudo shook init. Sidenote: shook usually needs to run as root because it interacts with systemctl or needs to write files in the /etc/systemd/system/ directory. shook will guide you through creating a config and it will generate the shook.toml in your repository's directory and /etc/systemd/system/shook.service. The shook.toml file tells shook how to run.

After generating a shook.toml, shook can be run using shook serve which starts the server in your terminal, or by running sudo shook daemon start which starts the shook systemd service. For testing out shook it is good to play with shook serve, you can use command line arguments to augment values in the shook.toml file. When running in production it would probably be more helpful to run sudo shook daemon enable so shook is started when your computer starts. note: shook daemon just runs systemctl start, stop and enable under the hood, so you can bypass shook and run those directly if you want.

Sample behind nginx

If your main server is running behind nginx, your webhook proxy might look like this:

```nginx http { server { # example route to serve static files location / { root /www-data; }

# proxy `shook` behind nginx
location /webhook {
  # remove the '/webhook' part of the url so requests to https://yourserver.com/webhook
  # are POSTed to '/' on `shook` (as it expects).
  rewrite /webhook(.*) /$1 break;
  # pass requests onto `shook`
  proxy_pass http://unix://var/run/shook.sock;
}

} } ```

Testing

As a side note, it can be really handy to test if your webhook server is working. You can use the Github CLI to help with this. Refer to here to set up webhook testing. To test shook I created an test repository on Github with a script update.sh that appends data to the README.md file, then commits and pushes. Then, running shook serve --log-level=trace in one terminal, gh webhook ... in another and ./update.sh in a third you can test your deployment.

Details

shook creates its own systemd service to start listening for events. The shook service simply runs shook serve from the right directory and sets a default logging level and log file to /var/log/shook.log. The github-webhook-extract crate provides route extractors for a Github webhook event (note: github-webhook-extract supports very few events at the moment). The text-completions crate provides environment variable and path tab completions for the shook init command.

shook init

The init command will generate both the systemd service file for shook and the shook.toml for your repository. The values for each config value can be optionally passed by command line, and if they aren't present, they will be read from stdin using dialoguer. The init command will store each config value in shook.toml stored in your given repositories directory. The shook.service file generated by shook will invoke shook serve setting the log file to /var/log/shook.log and will also put the working directory to your repositories path.

shook serve

The serve command will read the shook.toml file to configure itself. When the server receives a POST message it will extract a Github payload from it, and then check if the event matches the allowed events in your config. If there's a match, it will then use git to pull the most recent changes then systemctl restart your service. Each config field influences the server, here's an example:

```toml username = "rcullen" repopath = "/home/rcullen/rust/test-webhoks" remote = "origin" branch = "master" systemname = "test-restart" updateevents = ["push"] socketgroup = "www-data" socket_user = "www-data"

[addr] type = "Unix" value = "/var/run/shook.sock" ```

Final note: if shook serves through a unix socket, it will chmod the socket with 0o666.

shook daemon

The daemon command is a simple proxy over systemctl. It can be easily bypassed without causing any harm.