Skip to main content
Version: 2.1.1

Event handlers

An event handler is a script you write that the panel runs when something happens on the server. It is how a hosting company wires HiTechCloud into whatever else it runs — the billing system that has to start charging for a new domain, the CRM that has to know an account was closed, the provisioning spreadsheet somebody still keeps.

Handlers live in one directory per event:

/etc/hitechcloud/hitechcloud/events/<event>.d/

Run this once to create every directory:

hitechcloudcli native-event dirs
hitechcloudcli native-event list

Any executable file in an event's directory runs when that event fires, as root, in filename order. Non-executable files are ignored, which is the way to park a handler without deleting it.

Events and their fields​

Every handler is given these three, whatever the event:

VariableMeaning
HITECHCLOUD_EVENTThe event name
HITECHCLOUD_EVENT_TIMEUTC, RFC 3339
HITECHCLOUD_EVENT_IDUnique per emission — use it to make a handler idempotent

And these per event:

EventFields
domain.createdDOMAIN, USER, DOCROOT, PHP_VERSION
domain.deletedDOMAIN, USER
account.createdUSER, EMAIL, PLAN_ID, OWNER
account.deletedUSER, CONTEXT
account.suspendedUSER
account.unsuspendedUSER
plan.changedUSER, PLAN, PREVIOUS_PLAN, PLAN_ID, CPU, RAM, DISK
backup.finishedKIND, STATUS (ok or incomplete), ARCHIVE, SIZE, WARNINGS, DESTINATION
certificate.renewedDOMAIN, USER, DAYS_VALID
service.restartedSERVICE, UNIT, RESULT (ok, failed or exhausted)
uptime.changedDOMAIN, USER, STATE, PREVIOUS_STATE, REASON
anomaly.detectedUSER, KIND, DETAIL

Each field arrives as HITECHCLOUD_<FIELD> — domain becomes HITECHCLOUD_DOMAIN.

An example​

/etc/hitechcloud/hitechcloud/events/domain.created.d/10-billing:

#!/bin/bash
# Tell the billing system a domain was added. Values arrive in the
# environment; never put one on a command line without quoting it - a domain
# name is text a customer chose.
curl --silent --max-time 20 \
--header "Authorization: Bearer ${BILLING_TOKEN}" \
--data-urlencode "domain=${HITECHCLOUD_DOMAIN}" \
--data-urlencode "account=${HITECHCLOUD_USER}" \
--data-urlencode "event_id=${HITECHCLOUD_EVENT_ID}" \
https://billing.example.com/api/hosting/domain-added
chmod +x /etc/hitechcloud/hitechcloud/events/domain.created.d/10-billing

Test it without waiting for a real domain:

hitechcloudcli native-event test domain.created domain=test.example.com user=bob

test runs the handlers in the foreground and shows their output and exit status. A real event runs them detached, and their output goes to /var/log/hitechcloud/admin/events.log:

hitechcloudcli native-event log

What you can rely on​

A handler cannot fail the operation. Events are emitted detached, and emitting always succeeds. An account creation that half-succeeded because a billing webhook was down is a worse outcome than a billing system that is briefly out of date.

A handler that hangs is killed after 60 seconds. Without that, the first handler that calls an unreachable endpoint would leave a root process behind on every event, forever.

Values never reach a shell. They are passed in the environment, never interpolated into a command line and never passed through eval. A domain name is text a customer chose, and these scripts run as root.

Order is filename order. Prefix with a number if one handler has to run before another.

The event directories are mode 700 and the scripts in them run as root. Anything that can write into them can run anything on this server. Do not relax those permissions, and do not put a handler in a directory a hosting account can write to.

Compared with the CLI hooks​

hitechcloudcli also supports pre_<command> and post_<command> scripts in /etc/hitechcloud/hitechcloud/hooks/. Those are keyed on the name of a CLI command and receive its argv, so a handler for "a domain was created" has to know that domains-add takes the username third and the domain fourth, and breaks the day that order changes. They also cannot fire for anything that did not come through the CLI.

Events are keyed on the thing that happened and carry named fields. Prefer them for anything an outside system depends on.