Automated LXC Update Hooks¶
This guide explains how automated release updates are architected and configured across homelab LXC web applications using webhook and ChangeDetection.io.
Architecture Overview¶
flowchart LR
A["Upstream Release<br/>(GitHub Atom Feed)"] --> B["ChangeDetection.io<br/>(LXC 116 @ pve04)"]
B -->|HTTP POST JSON<br/>Apprise post://...:9000| C["Webhook Listener<br/>(LXC Container:9000)"]
C -->|Executes<br/>update.sh -s| D["update.sh"]
D -->|Stops Service<br/>Installs Release<br/>Restarts Service| E["Application<br/>(e.g., Tomcat, Node, Binary)"]
D -->|Summary Alert| F["Mailrise / LogWard"]
- Release Detection: ChangeDetection.io monitors the upstream GitHub Atom feed (
https://github.com/<owner>/<repo>/releases.atom). - Webhook Trigger: Upon detecting a new tag, ChangeDetection sends an HTTP POST notification to the target container's webhook listener (
post://<container_ip>:9000/hooks/update-app?method=POST&header=Content-Type:application/json). - Execution: The
webhookbinary executes/root/git/nicholaswilde/homelab/lxc/<app>/update.sh -sinside the container. - Idempotent Update:
update.shcompares the installed version against GitHub API releases. If a new version exists, it stops the service, downloads and installs the release, restarts the service, and fires a summary notification.
Components¶
Each integrated LXC application repository folder (lxc/<app>/) contains three configurations:
1. hooks.json¶
Defines the update-app webhook trigger matching the payload sent by ChangeDetection:
[
{
"id": "update-app",
"execute-command": "/root/git/nicholaswilde/homelab/lxc/<app>/update.sh",
"command-working-directory": "/root/git/nicholaswilde/homelab/lxc/<app>",
"pass-arguments-to-command": [
{
"source": "string",
"name": "-s"
}
],
"response-message": "Updating <app>..."
}
]
2. Systemd Webhook Service (<app>-webhook.service)¶
Runs the webhook server in background on port 9000:
[Unit]
Description=<app> Webhook Listener
After=network.target
[Service]
Type=simple
User=root
Environment=PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/root/.local/bin
WorkingDirectory=/root/git/nicholaswilde/homelab/lxc/<app>
ExecStart=/usr/bin/webhook -hooks hooks.json -verbose -port 9000
Restart=always
RestartSec=5
[Install]
WantedBy=multi-user.target
3. Taskfile Integration (lxc/<app>/Taskfile.yml)¶
Provides standard targets for managing the webhook daemon:
wh:install:
desc: Install and start the systemd webhook service
cmds:
- cp {{ .SERVICE_NAME }}-webhook.service /etc/systemd/system/
- systemctl daemon-reload
- systemctl enable --now {{ .SERVICE_NAME }}-webhook
- echo "🚀 Webhook service installed and started!"
wh:logs:
desc: View the webhook service logs
cmds:
- journalctl -u {{ .SERVICE_NAME }}-webhook -f
wh:status:
desc: Check the status of the systemd webhook service
cmds:
- systemctl status {{ .SERVICE_NAME }}-webhook
wh:test:
desc: Test the webhook listener locally
cmds:
- 'curl -X POST -H "Content-Type: application/json" http://localhost:9000/hooks/update-app'
Automation CLI (scripts/lxc_webhook.py)¶
A helper script automates the entire lifecycle:
# 1. Scaffold files locally
uv run python scripts/lxc_webhook.py scaffold <app>
# 2. Deploy webhook service to container
uv run python scripts/lxc_webhook.py deploy <app> [--node pve04]
# 3. Test listener reachability
uv run python scripts/lxc_webhook.py test <app> [--node pve04]
# 4. Register or update watch in ChangeDetection.io
uv run python scripts/lxc_webhook.py cd-watch <app> --repo <owner/repo>
Antigravity Skill¶
You can invoke the webhook-add agent skill to handle end-to-end integration:
Example: