Dead man switch as vibe-coded by Claude
- Python 96%
- Dockerfile 4%
|
|
||
|---|---|---|
| .forgejo/workflows | ||
| config | ||
| static | ||
| .gitignore | ||
| dead_mans_switch.py | ||
| docker-compose.yaml | ||
| Dockerfile | ||
| LICENSE | ||
| README.md | ||
dead-man-switch
Dead man switch as vibe-coded by Claude
A service to detect when notifications sent by it are not acknowledged, for a configurable number of notifications at a configurable interval.
- Read config file at /config/config.yaml
- At startup, send a notification to
- gotify instance
- in the case that gotify is unreachable or otherwise fails, by SMTP (email)
- If the configured number of notifications remain unacknowledged, execute an arbitrary list of
failsafe_commandsfrom theconfig.yamlfile. Types supported are "shell" and "email". Refer toconfig/config.yaml(reproduced below) for examples. A limited number of tools are available to shell scripts, but they includecurlfor tasks such as deleting or creating Nextcloud files.
# Dead Man's Switch Configuration - EXAMPLE
# dms
# instant_failsafe - set to 'true' to instantly execute failsafe commands at service startup. U
# Used to debug the failsafe section of this file
instant_failsafe: false
# check_interval_hours - hours between gotify notifications
check_interval_hours: 24
# notification_expiry_hours - how long the reset link in the notification remains active, in hours.
# Two minutes are subtracted from this by the service.
notification_expiry_hours: 24
# max_missed_notifications - how many times the reset link can be NOT clicked before the failsafe actions execute
max_missed_notifications: 7
# reset_link_base_url - The publicly reachable (if you know what's good for you) base URL of the service, so that
# the reset links are accessible from anywhere with internet access
reset_link_base_url: https://dms.example.com
# gotify_url - URL of your gotify service
gotify_url: https://gotify.example.com
# gotify_app_key - The key to send notifications to the 'DMS' app in Gotify
gotify_app_key: your_key_here
# SMTP Settings
smtp_server: smtp.gmail.com
smtp_port: 587
smtp_use_tls: true
smtp_username: your_email@gmail.com
smtp_password: your_password
smtp_from: your_email@gmail.com
# notification_recipient - The recipient of notifications, used when gotify is unreachable or fails for another reason
notification_recipient: recipient@example.com
# Failsafe Commands
failsafe_commands:
# Delete a file from a nextcloud instance
# note the use of /root/.netrc to provide credentials to the Nextcloud API call
# To do this you must manually create .netrc and bind mount it (in your docker-compose.yaml file)
- type: shell
command: |
curl -v --netrc-file /root/.netrc -X DELETE
https://nextcloud.example.org/remote.php/dav/files/username/Documents/test.md
# Create a passworded public share link to Nextcloud 'alargefile.ext'
- type: shell
command: |
# Generate password
export PASSWORD=$(openssl rand -base64 16)
export FETCHFILE="alargefile.ext";
export FETCHPATH="Documents/Folder/";
# Capture the response and extract the URL and STATUSCODE
RESPONSE=$(curl --netrc-file /root/.netrc -X POST \
'https://nextcloud.example.com/ocs/v2.php/apps/files_sharing/api/v1/shares' \
-H 'OCS-APIRequest: true' \
-d "path=${FETCHPATH}${FETCHFILE}" \
-d 'shareType=3' \
-d "password=$PASSWORD")
SHARE_LINK=$(echo "$RESPONSE" | grep -oP '(?<=<url>)[^<]+')
STATUSCODE=$(echo "$RESPONSE" | grep -oP '(?<=<statuscode>)[^<]+')
echo -n "$(date +'%Y-%m-%d %H:%M:%S') generate sharing link to ${FETCHFILE} returned code: ${STATUSCODE}" >> /logs/curl_cmds.log;
echo "Share link: $SHARE_LINK"
echo "" >> /logs/curl_cmds.log
echo -n "$PASSWORD" > /tmp/share.pwd
echo -n "$SHARE_LINK" > /tmp/share.lnk
- type: email
subject: Dead Man's Switch Activated
to: "someone@example.com, someoneelse@another.org"
file_vars:
share_link_password: /tmp/share.pwd
share_link: /tmp/share.lnk
body_text: |
This is a multi-line email body.
You can write it naturally without escape characters.
You may insert variables defined in file_vars (above in config file) and also
the variable {max_missed_notifications}.
Much easier to read and maintain!
body_html: |
<html>
<body>
<h1>Failsafe Activated</h1>
<p>You may also use variables here. The file <a href="{share_link}">a file</a>
requires password <b>{share_link_password}</b></p>
<p>Easy to format HTML too!</p>
</body>
</html>
attachments:
- /tmp/downloadedfile.ext