Lufi is a self-hosted temporary file sharing platform with a key property: files are encrypted client-side before being sent to the server, so even the server operator can't read uploaded content. Built on Perl and Mojolicious, it uses Hypnotoad as its production server and Minion for background job processing. The encryption makes it uniquely trustworthy, but self-hosting means you own the uptime — and Vigilmon gives you the external visibility to know when the platform breaks before your users hit a broken upload page.
What You'll Set Up
- HTTP uptime monitor for the Hypnotoad/Mojolicious application
- File upload and download endpoint health checks
- Minion job queue worker heartbeat
- File expiry worker heartbeat
- SQLite or PostgreSQL database connectivity check
- Disk usage threshold alerting
- SSL/TLS certificate expiry alerts
- Admin API endpoint availability check
Prerequisites
- Lufi deployed on a VPS (Perl/Mojolicious, Hypnotoad, port 8080 typically proxied via nginx)
- SQLite or PostgreSQL database
- Minion for background jobs
- A free Vigilmon account
Step 1: Monitor the Hypnotoad Web Server
Lufi runs under Mojolicious's Hypnotoad production server, typically on port 8080 behind an nginx reverse proxy that handles SSL. Monitor the public-facing URL:
- Log in to vigilmon.online and click Add Monitor.
- Set Type to
HTTP / HTTPS. - Enter your instance URL:
https://lufi.yourdomain.com - Set Check interval to
1 minute. - Set Expected HTTP status to
200. - Enable Monitor SSL certificate with a
21 dayexpiry alert. - Click Save.
Add a keyword check to confirm the Lufi upload interface loads:
- Under Keyword check, enter
lufiorupload— both appear in the default Lufi page title and UI.
This distinguishes between nginx returning 200 from a static error page (Hypnotoad crashed) vs. the real Lufi application responding.
Step 2: Add a Custom Health Check Endpoint
Lufi's Mojolicious application can be extended with a lightweight health route. Add it to your Lufi configuration by creating a custom plugin or modifying the app startup.
For Mojolicious Lite-style extensions, add to your lufi.conf startup or create a small plugin at lib/Lufi/Plugin/HealthCheck.pm:
package Lufi::Plugin::HealthCheck;
use Mojo::Base 'Mojolicious::Plugin';
sub register {
my ($self, $app) = @_;
$app->routes->get('/health' => sub {
my $c = shift;
my %checks;
my $status = 200;
# Database connectivity check
eval {
$c->app->db->db->query('SELECT 1');
$checks{database} = 'ok';
};
if ($@) {
$checks{database} = 'error';
$status = 503;
}
# Upload directory writable
my $upload_dir = $c->app->config('upload_dir') // 'files';
$checks{upload_dir} = (-d $upload_dir && -w $upload_dir) ? 'ok' : 'error';
$status = 503 if $checks{upload_dir} eq 'error';
# Disk space check (alert below 10% free)
my @df = `df -k "$upload_dir"`;
if (@df > 1) {
my @fields = split(/\s+/, $df[1]);
my $use_pct = $fields[4];
$use_pct =~ s/%//;
$checks{disk_space} = ($use_pct < 90) ? 'ok' : 'warn';
}
$c->render(json => {
status => $status == 200 ? 'ok' : 'degraded',
checks => \%checks,
}, status => $status);
});
}
1;
Load the plugin in your Lufi application startup. Then add a Vigilmon HTTP monitor for https://lufi.yourdomain.com/health.
Step 3: Monitor File Upload and Download Endpoints
The upload and download handlers are Lufi's core functionality. Test them independently from the web UI.
Upload endpoint check:
Create a probe script at /usr/local/bin/lufi-upload-probe.sh:
#!/bin/bash
set -e
LUFI_URL="https://lufi.yourdomain.com"
HEARTBEAT_URL="https://vigilmon.online/heartbeat/YOUR_UPLOAD_TOKEN"
# Create a tiny test file
TMPFILE=$(mktemp)
echo "vigilmon probe $(date)" > "$TMPFILE"
# Attempt upload using Lufi's API
RESPONSE=$(curl -fsS -X POST "$LUFI_URL/upload" \
-F "file=@$TMPFILE" \
-F "delay=1" \
-w "%{http_code}" \
-o /tmp/lufi-probe-response.json)
rm -f "$TMPFILE"
if echo "$RESPONSE" | grep -qE "^(200|201|302)$"; then
curl -fsS "$HEARTBEAT_URL" > /dev/null
else
echo "Lufi upload probe failed with HTTP $RESPONSE" >&2
cat /tmp/lufi-probe-response.json >&2
exit 1
fi
chmod +x /usr/local/bin/lufi-upload-probe.sh
# Run every 5 minutes
*/5 * * * * /usr/local/bin/lufi-upload-probe.sh
Create a Vigilmon Cron Heartbeat monitor with a 10 minute expected interval.
Download endpoint check:
After a successful probe upload, capture the generated download URL and add a static Vigilmon HTTP monitor for a known-good file link. This stays valid until the file's expiry TTL.
Step 4: Heartbeat for the Minion Job Queue Worker
Lufi uses Minion to process background jobs including file expiry, cleanup, and potentially virus scanning. If the Minion worker stops, files won't be cleaned up and jobs will accumulate silently.
Add a Minion task that pings Vigilmon after each successful job execution cycle. In your Lufi app or a custom plugin:
# Add a recurring Minion task that acts as a heartbeat
$app->minion->add_task(vigilmon_heartbeat => sub {
my $job = shift;
my $url = $app->config('vigilmon_minion_heartbeat_url');
return unless $url;
eval {
Mojo::UserAgent->new->get($url);
};
$job->finish('heartbeat sent');
});
# Schedule it every 5 minutes
$app->minion->enqueue('vigilmon_heartbeat')
unless $app->minion->jobs({tasks => ['vigilmon_heartbeat'], states => ['active', 'inactive']})->total;
For a simpler approach, add a cron-based check that confirms the Minion worker process is alive:
#!/bin/bash
# /usr/local/bin/lufi-minion-heartbeat.sh
HEARTBEAT_URL="https://vigilmon.online/heartbeat/YOUR_MINION_TOKEN"
# Check if the Minion worker is running
if pgrep -f "minion worker" > /dev/null; then
curl -fsS "$HEARTBEAT_URL" > /dev/null
else
echo "Lufi Minion worker not running" >&2
exit 1
fi
chmod +x /usr/local/bin/lufi-minion-heartbeat.sh
# Run every 5 minutes
*/5 * * * * /usr/local/bin/lufi-minion-heartbeat.sh
Create a Vigilmon Cron Heartbeat with a 10 minute expected interval.
Step 5: Heartbeat for the File Expiry Worker
Lufi automatically deletes files after their expiry period. This is typically handled by a Minion job or a standalone cron task. Wrap it in a heartbeat so you know if cleanup stops working.
If Lufi uses a dedicated cleanup script:
#!/bin/bash
# /etc/cron.hourly/lufi-cleanup
set -e
cd /var/www/lufi
# Run the Lufi cleanup command (adjust for your installation)
carton exec perl lufi.pl minion job -e clean_expired >> /var/log/lufi/cleanup.log 2>&1
# Ping Vigilmon on success
curl -fsS --retry 3 "https://vigilmon.online/heartbeat/YOUR_CLEANUP_TOKEN" > /dev/null
chmod +x /etc/cron.hourly/lufi-cleanup
Create a Vigilmon Cron Heartbeat with a 2 hour expected interval. A missed hourly cleanup fires an alert within two hours — before the disk fills.
Step 6: Database Connectivity and Disk Usage
Database health:
The health endpoint created in Step 2 already covers database connectivity. For an additional low-level check targeting SQLite specifically, add this wrapper:
#!/bin/bash
# SQLite integrity check (run daily)
DB_PATH="/var/www/lufi/lufi.db"
HEARTBEAT_URL="https://vigilmon.online/heartbeat/YOUR_DB_TOKEN"
RESULT=$(sqlite3 "$DB_PATH" "PRAGMA integrity_check;" 2>&1)
if echo "$RESULT" | grep -q "^ok$"; then
curl -fsS "$HEARTBEAT_URL" > /dev/null
else
echo "SQLite integrity check failed: $RESULT" >&2
exit 1
fi
For PostgreSQL, use pg_isready:
if pg_isready -h 127.0.0.1 -d lufi -U lufi > /dev/null 2>&1; then
curl -fsS "$HEARTBEAT_URL" > /dev/null
fi
Disk usage:
#!/bin/bash
# /usr/local/bin/lufi-disk-check.sh
UPLOAD_DIR="/var/www/lufi/files"
HEARTBEAT_URL="https://vigilmon.online/heartbeat/YOUR_DISK_TOKEN"
THRESHOLD=85
USED=$(df "$UPLOAD_DIR" | awk 'NR==2 {gsub(/%/,"",$5); print $5}')
if [ "$USED" -lt "$THRESHOLD" ]; then
curl -fsS "$HEARTBEAT_URL" > /dev/null
else
echo "Disk at ${USED}% — above ${THRESHOLD}% threshold" >&2
exit 1
fi
# Run every 15 minutes
*/15 * * * * /usr/local/bin/lufi-disk-check.sh
Step 7: Monitor the Admin API Endpoint
Lufi exposes an admin interface for managing stored files. Monitor it to confirm it's accessible (authenticated 403 is fine — it proves the route is live):
- In Vigilmon, add an HTTP monitor for
https://lufi.yourdomain.com/admin. - Set Expected HTTP status to
200or302(redirect to login). - Set Check interval to
5 minutes.
A 503 from the admin endpoint when the main UI is responding normally can indicate a Minion worker crash affecting the admin statistics page.
Step 8: Configure Alert Channels
- Go to Alert Channels in Vigilmon and add your email or Slack webhook.
- On the main web monitor and upload heartbeat, set Consecutive failures before alert to
2. - On the disk usage heartbeat, set Consecutive failures before alert to
1. - On the Minion worker heartbeat, set Consecutive failures before alert to
1.
Suppress alerts during Hypnotoad restarts (typically under 5 seconds) by using Vigilmon's maintenance window API in your deployment scripts:
# Before restarting Hypnotoad
curl -X POST https://vigilmon.online/api/maintenance \
-H "Authorization: Bearer YOUR_API_KEY" \
-d '{"monitor_id": "MONITOR_ID", "duration_minutes": 2}'
hypnotoad /var/www/lufi/lufi.pl
Summary
| Monitor | Target | What It Catches |
|---|---|---|
| Web availability | https://lufi.yourdomain.com | Hypnotoad crash, nginx misconfiguration |
| Health endpoint | /health | DB down, upload dir unwritable |
| Upload probe heartbeat | Vigilmon heartbeat URL | Upload handler broken |
| Minion worker heartbeat | Vigilmon heartbeat URL | Background job worker stopped |
| Expiry job heartbeat | Vigilmon heartbeat URL | File cleanup stopped |
| Disk threshold heartbeat | Vigilmon heartbeat URL | Disk above 85% |
| Database check heartbeat | Vigilmon heartbeat URL | SQLite/PostgreSQL integrity failure |
| Admin endpoint | /admin | Admin API down |
| SSL certificate | Main domain | TLS certificate expired |
Lufi's client-side encryption means you can promise users their files are private — but that promise only holds if the service stays up. With Vigilmon monitoring Hypnotoad, the Minion job queue, file expiry jobs, disk space, and every critical endpoint, you can keep that promise running 24/7.
Get started free at vigilmon.online.