Skip to content

Add a server health check that reports to Discord - #23

Merged
OpenSource-For-Freedom merged 1 commit into
mainfrom
feat/health-workflow
Aug 15, 2026
Merged

Add a server health check that reports to Discord#23
OpenSource-For-Freedom merged 1 commit into
mainfrom
feat/health-workflow

Conversation

@OpenSource-For-Freedom

Copy link
Copy Markdown
Owner

Runs every 30 minutes and on demand. Probes the live server from outside and posts to Discord when something is wrong.

It reports three states, not two

A boolean would be wrong here. The server currently answers roughly one ping in four from some networks while being completely healthy, so a one-shot check would cry outage constantly and the channel would get muted.

It retries and reports the ratio, distinguishing down from reachable but lossy. Its first live run produced exactly that:

host=159.65.25.218:25565 state=UP pings=1/4 latency=276ms
  -> "EduCraft is up but lossy"   (amber)

Security, since this is the first workflow holding a credential

No SSH, and none of the MC_SSH_* secrets are referenced. Port 22 is open only to DigitalOcean console ranges, so a GitHub runner cannot reach it anyway. The options were opening 22 to GitHub published ranges (thousands of third-party addresses) or putting a long-lived SSH credential in CI where every workflow and every fork PR becomes a path to the box. Both trade a real boundary for a nicer report.

Everything reported comes from the same public interface a player uses, so green answers the question that actually matters: can people get in.

Control Implementation
Secret scope DISCORD_WEBHOOK exposed to one step, never job-wide
Secret leakage Never echoed, no set -x, never written to disk
Fork PRs No pull_request trigger
Permissions contents: read
Supply chain Actions pinned to full commit SHAs, not tags
Checkout persist-credentials: false
Runaway 5-minute timeout
Dependencies Standard library only, no pip install

Verified with a fake webhook: 0 occurrences in output.

Concurrency is serialised deliberately

This server drops TCP under concurrent connections, so overlapping probes would manufacture the very failure they exist to detect.

Quiet when healthy

On the schedule it posts only on trouble. A green message every 30 minutes is how a channel gets muted, and a muted channel means the red one is missed too. Manual runs default to posting so you can confirm the wiring.

Player names are opt-in and off by default. If the webhook leaks, everything posted through it leaks with it, and these players are children.

Tested

live server      caught "up but lossy 1/4"    correct amber embed
server down      correct red embed, exit 1
webhook leak     0 occurrences with a fake secret
compile + YAML   both valid

After merge, run it manually from the Actions tab to confirm the Discord webhook works end to end.

Runs every 30 minutes and on demand, probes the live server from the
outside, and posts to Discord when something is wrong.

It reports three states, not two. A boolean would be wrong here: this
server currently answers roughly one ping in four from some networks
while being completely healthy, so a one-shot check would cry outage
constantly and everyone would learn to ignore the channel. Instead it
retries and reports the ratio, which distinguishes "down" from
"reachable but lossy". Its first live run correctly produced
"up but lossy, 1/4 pings succeeded", which is exactly the condition
being chased right now.

SECURITY, since this is the first workflow holding a credential:

No SSH, and none of the MC_SSH_* secrets are referenced. Port 22 on the
droplet is open only to DigitalOcean console ranges, so a GitHub-hosted
runner cannot reach it regardless. The options were to open 22 to
GitHub's published ranges, which is thousands of third-party addresses,
or to put a long-lived SSH credential into CI where every workflow and
every fork PR becomes a path to the box. Both trade a real security
boundary for a richer report, so neither was taken. Everything reported
comes from the same public interface a player uses, which means a green
result answers the question an owner actually has: can people get in.

Only DISCORD_WEBHOOK is exposed, and only to the single step that needs
it. That URL is a bearer credential, so it is never echoed, never put in
a job-wide env block, and never written to disk; `set -x` is deliberately
absent for the same reason. Verified by running with a fake webhook and
grepping the output: zero occurrences.

No pull_request trigger, so a fork PR cannot run modified code with
access to the secret. Permissions are contents:read. Actions are pinned
to full commit SHAs rather than tags, which can be repointed. checkout
uses persist-credentials:false. Five-minute timeout. Standard library
only, so an unattended monthly run has no dependency that can be swapped
underneath it.

Concurrency is serialised on purpose: this server drops TCP under
concurrent connections, so overlapping probes would manufacture the very
failure they exist to detect.

On the schedule it stays silent while healthy and posts only on trouble.
A green message every 30 minutes is how a channel gets muted, and a muted
channel means the one red message is missed too. Manual runs default to
posting so the wiring can be confirmed.

Player names are opt-in and off by default. If the webhook ever leaks,
everything posted through it leaks with it, and these players are
children.
@OpenSource-For-Freedom
OpenSource-For-Freedom merged commit db70582 into main Aug 15, 2026
7 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant