Set Up Backups & Monitoring
This tutorial configures automated backups and uptime monitoring for your Temps instance. By the end, your data will be backed up to S3 on a schedule, you will receive alerts when something goes down, and you will know how to restore from a backup.
What you will build
By the end of this tutorial, you will have:
- An S3-compatible storage bucket connected to Temps for off-site backups
- A manual backup of your Temps database and all managed services
- An automated backup schedule that runs nightly
- A notification channel (email, Slack, or webhook) for alerts
- An uptime monitor that checks your application every 60 seconds
- Experience restoring from a backup
Time required: approximately 20 minutes.
What this tutorial covers and does not cover:
| Covered | Not covered |
|---|---|
| Connecting S3 storage for backups | Setting up managed databases (tutorial) |
| Manual and scheduled backups | CI/CD pipeline configuration (how-to guide) |
| Email (SES/Scaleway/SMTP), Slack, and webhook notifications | Custom status pages |
| Uptime monitors, incidents, and disk-space alerts | Email domain DNS setup for SMTP providers (you own it) |
| Restoring from a backup | Point-in-time recovery with WAL-G |
Prerequisites
You need:
- A running Temps instance with at least one deployed project (complete Your First Deployment first)
- S3-compatible storage — any of the following:
- AWS S3 bucket
- MinIO instance (self-hosted)
- DigitalOcean Spaces
- Cloudflare R2
- Any S3-compatible object storage
- Credentials for your S3 storage: access key ID, secret access key, bucket name, region, and endpoint URL (for non-AWS providers)
If you do not have S3 storage yet: The cheapest option for getting started is Cloudflare R2 (free tier includes 10 GB) or a self-hosted MinIO instance on the same server. For production, use a provider in a different region from your Temps server so backups survive even if the server is lost.
Connect S3 storage
Temps stores backups in S3-compatible object storage. You need to connect a storage source before you can create backups.
- In the Temps dashboard sidebar, click Settings (at the bottom)
- Find the Backups section
- Click Add S3 Source
- Fill in your storage details:
- Name
Name- Description
A label for this storage source, e.g.
production-backups. This is for your reference only.
- Name
Bucket Name- Description
The name of your S3 bucket. It must already exist, or Temps will attempt to create it automatically.
- Name
Bucket Path- Description
The prefix (folder) within the bucket where backups are stored. Defaults to
/(the root of the bucket). Use a different path if you share the bucket with other tools.
- Name
Access Key ID- Description
Your S3 access key. Stored encrypted at rest (AES-256-GCM).
- Name
Secret Access Key- Description
Your S3 secret key. Stored encrypted at rest.
- Name
Region- Description
The bucket region, e.g.
us-east-1,eu-west-1. For MinIO or other self-hosted providers, use whatever region your instance is configured with (oftenus-east-1).
- Name
Endpoint- Description
The S3-compatible endpoint URL. Leave blank for AWS S3. For other providers:
- MinIO:
http://your-minio-server:9000 - DigitalOcean Spaces:
https://nyc3.digitaloceanspaces.com - Cloudflare R2:
https://<account-id>.r2.cloudflarestorage.com
- MinIO:
- Name
Force Path Style- Description
Enable this for MinIO and most non-AWS providers. AWS S3 uses virtual-hosted-style by default. When in doubt, enable it.
Click Save. When you create a source, Temps tests the connection and auto-creates the bucket before saving the source. If validation fails, verify your credentials and ensure the endpoint is reachable.
Security: Both your access key ID and secret access key are encrypted before being stored in the database using AES-256-GCM. They are decrypted only when building an S3 client. They are never exposed in API responses — the dashboard shows *** in place of secret values, and the secret key is marked write-only in the API schema.
Default source and connection testing
Temps tracks a single default S3 source so schedules and on-demand backups have a destination without you re-selecting it each time:
- The first source you create is automatically the default, regardless of what you pass.
- Marking another source as default (the Set Default action) atomically swaps the default inside a database transaction. A partial-unique index guarantees at most one source is ever the default.
You can test a source two ways:
- Test a saved source — uses the stored credentials and reports whether the bucket is reachable. Does not create anything.
- Preview-test before saving — checks a prospective configuration from the form by attempting a list. It does not create the bucket or store any credentials, so you can validate keys before committing them.
The S3 sources are managed through a CRUD API under /api. All routes require a bearer token and the listed permission:
| Route | Method | Permission | Notes |
|---|---|---|---|
/api/backups/s3-sources | GET | BackupsRead | List sources |
/api/backups/s3-sources | POST | BackupsCreate | Create (tests + auto-creates bucket); returns 201 |
/api/backups/s3-sources/{id} | GET | BackupsRead | Get one |
/api/backups/s3-sources/{id} | PATCH | BackupsWrite | Update |
/api/backups/s3-sources/{id} | DELETE | BackupsDelete | Delete; returns 204 |
/api/backups/s3-sources/{id}/set-default | POST | BackupsWrite | Mark as default |
/api/backups/s3-sources/{id}/test | POST | BackupsRead | Test stored credentials |
/api/backups/s3-sources/test | POST | BackupsCreate | Preview-test an unsaved config |
/api/backups/s3-sources/{id}/run | POST | BackupsCreate | Enqueue an on-demand backup; returns 202, runs async |
/api/backups/s3-sources/{id}/backups | GET | BackupsRead | List backups stored in the source |
Run your first backup
With storage connected, run a manual backup to verify everything works.
- On the Backups settings page, find your S3 source
- Click the Run Backup button (or use the actions menu)
- Select Full as the backup type
Temps starts the backup immediately. The process:
- Temps database — The internal PostgreSQL database (with TimescaleDB extension) is backed up first.
- Managed services — Every managed service you have provisioned (PostgreSQL databases, Redis instances, S3 storage) is backed up individually.
- Metadata — A
metadata.jsonfile is generated with checksums, sizes, timestamps, and service inventory. - Upload — Everything is uploaded to your S3 bucket and the backup index is updated.
You can watch the progress on the page. When the status changes to Completed, your first backup is done.
How PostgreSQL dumps run: Temps runs each PostgreSQL dump inside a disposable Docker sidecar container rather than streaming it through the Temps process, so Temps' memory stays flat regardless of database size. The dump command writes a cluster-wide, plain-SQL dump to a temp file and then gzips it (pg_dumpall --clean --if-exists --no-password ... > dump.sql && gzip dump.sql), uploaded as a .sql.gz — compression happens on disk after the dump completes, not streamed through a pipe. The container is created with auto_remove (plus an explicit force-remove backstop) so it is reaped after the dump exits. For the control-plane (Temps' own) database the sidecar uses a version-matched generic postgres:{major} image.
Verify the backup
Check that files were written to your S3 bucket. The backup is stored at:
{bucket_path}/backups/{YYYY}/{MM}/{DD}/{backup-uuid}/
├── backup.sql.gz # Temps database dump (gzip compressed)
├── metadata.json # Checksums, sizes, timestamps
└── ... # External service backups (if any)
There is also an index file at {bucket_path}/backups/index.json that lists all backups.
Verify from the CLI
If you have the Temps CLI installed, you can list backups using your configured backup source. First create a backup source (if you have not done so already), then list backups for it.
Create a backup source (AWS S3):
bunx @temps-sdk/cli backup source create \
--name my-s3-source \
--bucket your-backup-bucket \
--region us-east-1 \
--access-key YOUR_ACCESS_KEY \
--secret-key YOUR_SECRET_KEY
Create a backup source (non-AWS, e.g. MinIO):
bunx @temps-sdk/cli backup source create \
--name my-minio-source \
--bucket your-backup-bucket \
--endpoint https://your-minio-server:9000 \
--access-key YOUR_ACCESS_KEY \
--secret-key YOUR_SECRET_KEY
List backups for a source or schedule:
# List by schedule
bunx @temps-sdk/cli backup list --schedule-id YOUR_SCHEDULE_ID
# List all backups for a source
bunx @temps-sdk/cli backup source backups --id YOUR_SOURCE_ID
Create a backup schedule
Manual backups are useful for one-off situations (before a migration, before an upgrade). For day-to-day protection, set up an automated schedule.
- On the Backups settings page, click Add Schedule
- Configure the schedule:
- Name
Name- Description
A descriptive name, e.g.
nightly-full-backup.
- Name
Backup Type- Description
The type of backup. Use
fullfor complete database dumps.
- Name
S3 Source- Description
Select the S3 source you created earlier.
- Name
Schedule Expression- Description
A cron expression (with seconds) defining when the backup runs. Examples:
0 0 2 * * *— Every day at 2:00 AM0 0 3 * * 0— Every Sunday at 3:00 AM0 0 */6 * * *— Every 6 hours
The minimum interval between backups is 1 hour.
- Name
Retention Period- Description
Number of days to keep backups before automatic deletion. For example,
30keeps one month of backups.
- Name
Description- Description
Optional notes about this schedule.
- Name
Tags- Description
Optional tags for organizing backups, e.g.
production,nightly.
Click Create. The schedule starts immediately — the next backup will run at the time specified by your cron expression.
Choose what a schedule backs up
By default a schedule backs up every database plus the Temps control plane, but you can scope it. The create, edit, and schedule-detail pages expose two controls:
- All databases (recommended) / Specific databases — a radio. All databases fans every run out to every external service on the host, including databases you add in the future. Specific databases restricts the run to the databases you explicitly attach via the checkbox list.
- Also back up the Temps control plane — a switch. When on, every run also produces a
control_planebackup of Temps' own Postgres; when off, that step is skipped.
Both options map to boolean columns on the schedule (target_all_services and include_control_plane), both default to true. Temps rejects a schedule that would back up nothing: if the control plane is off and "All databases" is off and no databases are attached, create/update fail with a validation error. Flipping back to "All databases" clears any explicit per-database membership ("all means all"). On upgrade, existing schedules backfill to the prior behavior — back up every database plus the control plane.
The explicit per-database membership is also exposed through the API (all routes under /api, bearer token required):
| Route | Method | Permission | Notes |
|---|---|---|---|
/api/backups/schedules/{id}/services | GET | BackupsRead | List attached databases |
/api/backups/schedules/{id}/services | POST | BackupsCreate | Attach databases (idempotent); returns inserted + total attached |
/api/backups/schedules/{id}/services/{service_id} | DELETE | BackupsDelete | Detach; returns 204 whether or not the row existed |
/api/backups/external-services/{service_id}/schedules | GET | BackupsRead | List schedules that target a database |
Attach and detach write audit logs.
Recommended schedules
| Use case | Cron expression | Retention | Rationale |
|---|---|---|---|
| Production (daily) | 0 0 2 * * * | 30 days | Daily at 2 AM, keep one month |
| Production (hourly) | 0 0 * * * * | 7 days | Every hour, keep one week. For high-write databases. |
| Staging (weekly) | 0 0 3 * * 0 | 14 days | Sunday at 3 AM, keep two weeks |
When do schedules run? Temps checks for due schedules at the top of every hour. A schedule is considered due when the current time exceeds its next_run timestamp. After running, the next execution time is calculated from the cron expression.
Disable or enable a schedule
You can pause a schedule without deleting it. On the Backups page, use the toggle or actions menu to Disable or Enable a schedule. Disabled schedules retain their configuration and history but do not run.
How retention is enforced
Retention is enforced two ways, and the app-side path is the source of truth:
- App-side (primary).
BackupService::enforce_retentionsweeps enabled schedules and deletes backups older than each schedule's retention period. This is what keeps your storage clean and is the source of truth on providers that don't support tagging. - Bucket lifecycle rules (best-effort). So expired backups are still removed even while Temps is offline, Temps also reconciles per-bucket lifecycle rules from your current schedules. Each backup object is tagged on upload (via a separate
PutObjectTaggingcall, not an upload header) withtemps-managed=true,temps-retention-days(the schedule's retention in days, or the literalneverfor ad-hoc backups or non-positive retentions), and traceability tags. Temps then emits one tag-filtered lifecycle rule per distinct retention value (e.g.temps-retention-7d,temps-retention-30d) that expires objects after that many days. Tag filters were chosen over key prefixes so existing backup keys are untouched and restore keeps working; objects written before this feature lack the tags and are simply ignored by the rules.
Reconcile runs fire-and-forget on schedule create and delete (and on update only when retention or enabled changed), plus an hourly drift sweep that re-pushes the desired state.
Provider support for lifecycle rules: Tag-filtered lifecycle rules are supported on AWS S3, MinIO, OVH Object Storage (High Performance), and RustFS. Cloudflare R2 and Backblaze B2 do not support object tagging (R2 returns 501 NotImplemented on both the tagging upload header and PutObjectTagging), so Temps falls back silently to app-side retention there — the backup itself never fails, and enforce_retention cleans up expired backups normally. Only the bucket-side lifecycle rules are skipped.
Set up a notification channel
Before setting up monitoring, configure where Temps should send alerts. Temps supports three notification channels: email, Slack, and webhooks.
Option A: Email notifications
Temps supports three email provider types: AWS SES, Scaleway, and a generic SMTP provider. Use generic SMTP when you only have plain SMTP credentials — AWS SES SMTP endpoints, Sendgrid, Mailgun, Postmark, a self-hosted Postfix, or a local Mailpit/Mailhog instance for testing.
- In the sidebar, click Settings
- Find the Notifications (or Email Providers) section
- Click Add Provider and choose the provider type. For generic SMTP (the Server icon), configure your relay:
- Name
Host- Description
Your SMTP host, e.g.
email-smtp.eu-west-1.amazonaws.com,smtp.sendgrid.net.
- Name
Port- Description
The relay port. The form autosuggests
587for STARTTLS,465for implicit TLS, and25for no encryption.
- Name
Username- Description
Your SMTP username. Optional — omit it for unauthenticated relays.
- Name
Password- Description
Your SMTP password or API token. Optional; required when a username is set.
- Name
Encryption- Description
The TLS mode (
encryptionfield). One of:starttls(default) — start plain, then upgrade. Used by AWS SES SMTP, Sendgrid, Mailgun (typically port 587).tls— implicit TLS / SMTPS, encrypted from byte 0 (typically port 465).none— no encryption. Local testing only.
- Name
Accept Invalid Certs- Description
Accept self-signed certificates. Only safe for local testing. For loopback hosts (
localhost,127.0.0.1,::1) Temps automatically loosens TLS certificate and hostname verification so local relays work without this flag.
Generic SMTP providers send via the lettre library. Creating one sends a SmtpCredentialsRequest to POST /api/email-providers.
SMTP domains are "imported." Because plain SMTP has no domain-management API, any domain you add under an SMTP provider is treated as already-configured: Temps returns no SPF/DKIM/MX records to set up, reports the domain verified immediately, and treats deletion as a no-op. You own DNS at the upstream mail server. The provider form shows a warning to this effect. (SES and Scaleway providers still manage and verify domain records for you.)
Edit an email provider
Email providers are editable in place — the Edit dropdown item is now active for SES, Scaleway, and SMTP providers. Editing sends a partial update to PATCH /api/email-providers/{id} (requires the email_providers:write permission).
name,region,is_active, and credentials are individually updatable.provider_typeis immutable — the Edit dialog shows it read-only, and sending a credential block for a different type is rejected (Cannot change provider type from … to …).- Omitting a credential block preserves the stored secret, so you can rename a provider or change its region without re-typing passwords. Secret fields render blank with "Leave blank to keep current" helper text.
- Updates emit an
EMAIL_PROVIDER_UPDATEDaudit event that records only the names of the changed fields (e.g.["name","region","credentials"]), never their values.
Option B: Slack notifications
- Create a Slack Incoming Webhook for the channel you want alerts in
- In Temps, click Add Provider and choose Slack
- Paste the webhook URL (must start with
https://hooks.slack.com/) - Optionally set a channel name for display purposes
Slack notifications include color-coded attachments: red for errors, orange for warnings, blue for informational.
Option C: Webhook notifications
For integrations with Discord, PagerDuty, or any HTTP endpoint:
- Click Add Provider and choose Webhook
- Enter the URL of your webhook endpoint
- Optionally configure:
- HTTP Method — POST (default), PUT, or PATCH
- Headers — Custom headers for authentication (e.g.
Authorization: Bearer your-token) - Timeout — Maximum wait time in seconds (default: 30)
Webhook payloads are JSON:
{
"id": "notif_abc123",
"title": "Backup Failed",
"message": "Nightly backup schedule 'production-daily' failed",
"type": "error",
"priority": "high",
"severity": "error",
"timestamp": "2026-02-28T02:00:15Z",
"metadata": {
"schedule_id": 1,
"schedule_name": "production-daily",
"backup_type": "full"
}
}
Test your notification channel
After creating a provider, click the Test button. Temps sends a test notification to verify the connection works. You should receive a test message within a few seconds.
Both test emails are sent with the standard Temps template (dark header, status badge, details table, footer):
- Email-provider test (the "Send Test Email" action on an email provider) arrives with subject
[Temps] Email provider test — <name>and renders the provider type as a human-readable label (AWS SES / Scaleway / SMTP). The provider name, region, and type are HTML-escaped before rendering, so a provider name like<script>…</script>can't inject markup into the inbox. - Notification-provider health-check arrives as a
multipart/alternativemessage (plaintext + HTML) with subject[Temps] Notification provider health check. The body shows an "Notification provider is reachable" title and a details table with the instance hostname, the SMTP relay ashost:port, the From address, and a timestamp. The instance label is resolved fromTEMPS_HOSTNAME, thenTEMPS_PUBLIC_HOSTNAME, then the literaltemps instance. The health check no longer fails on an empty recipient list or a single malformed recipient address (the SMTP connection succeeding is still a valid signal), and it logs which stage failed (connection vs send) so you can act on a misconfiguration.
Configure notification preferences
Temps lets you fine-tune what triggers notifications. In Settings > Notifications > Preferences, you can control:
- Backup notifications — failures (enabled by default), successes, S3 connection issues, retention violations
- Domain notifications — SSL certificate expiration (30 days before), domain expiration, DNS changes
- Runtime notifications — deployment failures, build errors, runtime error spikes
- Weekly digest — a summary email sent every Monday at 9 AM with deployment stats, error trends, and performance metrics (see below)
Smart throttling: Temps batches similar notifications to avoid alert fatigue. Critical alerts have a 15-minute cooldown, high-priority alerts 1 hour, and normal alerts 1 day. Identical notifications within the cooldown window are grouped with an occurrence count.
Weekly digest
The weekly digest is a scheduled summary email that gives admin users a high-level view of how their Temps instance performed over the past week. It replaces the need to manually check each project for activity.
What it contains:
- Deployment stats — total successful and failed deployments across all projects for the week, giving a quick sense of release cadence and reliability
- Error trends — error event counts broken down by project, so you can spot which projects had a spike before digging into logs
- Performance metrics — aggregated request-level performance data for the week
When it is sent: every Monday at 9 AM (server local time).
Who receives it: all admin users on the instance.
Subject line format: [Temps] Weekly digest — week of <date>
Requirements:
- An email provider must be configured (AWS SES, Scaleway, or SMTP — the same provider used for transactional auth email)
- The Weekly digest toggle must be enabled in Settings > Notifications > Preferences
If no email provider is configured, the digest is silently skipped — no error is logged and no fallback notification is sent. To start receiving it, add an email provider and make sure the preference is on.
Create an uptime monitor
Uptime monitors check your application's health at regular intervals and alert you when something goes down.
- Open your project in the dashboard
- Click Monitors in the project sidebar
- Click Add Monitor
- Configure the monitor:
- Name
Name- Description
A label for this monitor, e.g.
Production Health Check.
- Name
Monitor Type- Description
The type of check to perform:
- web — Checks any URL for a successful HTTP response
- health — Checks the
/healthendpoint of the environment's subdomain - api — Checks an API endpoint for a successful response
- Name
Environment- Description
Which environment to monitor (e.g. production). The check URL is constructed from the environment's subdomain.
- Name
Check Interval- Description
How often to check, in seconds. Default:
60(every minute).
Click Create. Temps runs the first check immediately and then continues at the interval you specified.
How health checks work
Each check:
- Sends an HTTP GET request to the monitor URL
- Waits up to 10 seconds for a response (within a 30-second client timeout)
- Retries up to 3 times with exponential backoff (100ms, 200ms, 400ms) before marking as failed
- Maps the response to a status:
| HTTP Response | Monitor Status |
|---|---|
| 2xx (Success) | Operational |
| 4xx (Client Error) | Degraded |
| 5xx (Server Error) | Major Outage |
| Timeout / No Response | Major Outage |
Failure threshold and incidents
A single failed check does not trigger an alert. By default, Temps requires 2 consecutive failures before creating an incident. This avoids false alarms from network blips.
When an outage is confirmed:
- The monitor status changes to Down
- An incident is created with severity based on the failure type (Minor for degraded, Major for down)
- A notification is sent to all configured channels
- The incident appears on the project's status overview
When the monitor recovers:
- The monitor status returns to Operational
- The incident is automatically resolved
- A recovery notification is sent
View uptime history
On the Monitors page, each monitor shows:
- Current status — Operational, Degraded, or Down
- Response time — Average, P50, P75, P95, P99 percentiles
- Uptime history — Time-bucketed data showing operational/degraded/down periods
- Incident history — All past incidents with severity, duration, and resolution time
Simulate a failure
To verify your monitoring and notification setup is working end-to-end, you can temporarily break your application and watch the system respond.
Option 1: Stop the container (recommended)
If you have SSH access to your server:
# Find your application's container
docker ps | grep your-project-name
# Pause it temporarily (does not destroy it)
docker pause <container-id>
Wait for 2-3 minutes (two check intervals). You should:
- See the monitor status change to Down in the dashboard
- Receive an outage notification on your configured channel
- See an incident created in the project's Monitors section
Now resume the container:
docker unpause <container-id>
Within one check interval (60 seconds), you should:
- See the monitor status return to Operational
- Receive a recovery notification
- See the incident automatically resolved
Option 2: Deploy a broken version
Push a commit that returns a 500 error from your health endpoint, deploy it, wait for the alert, then fix and redeploy. This tests the full loop including deployments, but takes longer.
Alert cooldown: After an outage alert, Temps waits 5 minutes before sending another alert for the same monitor. This is configurable. If you are testing, be patient — the recovery notification will arrive after the cooldown period.
Restore from a backup
The point of backups is restoring from them. Test this now while everything is working, so you are prepared if you ever need it for real.
Warning: Restoring replaces your current data. In production, always restore to a staging environment first. For this tutorial, since you are learning, a direct restore is fine — but be aware it will overwrite the Temps database.
Restore via the CLI
The CLI is the primary way to restore backups. It handles downloading from S3, decompressing, and restoring both the Temps database and all managed services.
Step 1: List available backups
# List backups by schedule ID
bunx @temps-sdk/cli backup list --schedule-id YOUR_SCHEDULE_ID
# Or list all backups for a backup source
bunx @temps-sdk/cli backup source backups --id YOUR_SOURCE_ID
Note the backup-id (UUID) of the backup you want to restore.
Step 2: Restore the full backup
bunx @temps-sdk/cli services restore \
--id YOUR_SERVICE_ID \
--backup-id YOUR_BACKUP_UUID
To restore into a new service instead of overwriting the existing one, add --new-service:
bunx @temps-sdk/cli services restore \
--id YOUR_SERVICE_ID \
--backup-id YOUR_BACKUP_UUID \
--new-service
Step 3: Restart Temps
After a restore, restart the Temps service to pick up the restored data:
sudo systemctl restart temps
Restore a single managed service
If you only need to restore one specific service (e.g. a PostgreSQL database that was corrupted), use services restore targeting that service's ID:
bunx @temps-sdk/cli services restore \
--id YOUR_SERVICE_ID \
--backup-id YOUR_BACKUP_UUID
For point-in-time recovery (Postgres only), add --pitr with an ISO 8601 timestamp:
bunx @temps-sdk/cli services restore \
--id YOUR_SERVICE_ID \
--backup-id YOUR_BACKUP_UUID \
--pitr "2026-05-01T03:00:00Z"
What you have accomplished
Your Temps instance now has a complete protection layer:
| Feature | What it does | Status |
|---|---|---|
| S3 backup storage | Off-site storage for all backups | Connected |
| Manual backups | On-demand database and service snapshots | Tested |
| Scheduled backups | Automatic nightly (or custom schedule) backups | Running |
| Notifications | Alerts via email, Slack, or webhook | Configured |
| Uptime monitoring | 60-second health checks with incident tracking | Active |
| Restore process | CLI-based full or per-service restoration | Verified |
Additional protections that Temps runs automatically in the background:
- Disk space monitoring — Watches free space on the data volume and alerts before it fills up (see below).
- Backup failure alerts — High-priority notifications if a scheduled backup fails.
- SSL expiration warnings — Notifications 30 days before certificates expire.
- Weekly digest — A summary of deployment stats, error trends, and performance metrics sent every Monday at 9 AM to admin users (requires an email provider and the preference enabled).
Disk space monitoring
Temps runs a background monitor that watches free space on the data volume and notifies you before it fills up. It is enabled by default and uses these settings (configurable under Settings → System Monitoring):
| Setting | Default | Notes |
|---|---|---|
enabled | true | Enabled by default |
threshold_percent | 80 | Alert fires when usage is at or above this percent (0–100) |
check_interval_seconds | 300 | How often the volume is checked (minimum 60; 300 = every 5 minutes) |
monitor_path | data directory | Falls back to the configured data directory when unset |
When an alert fires, the severity is derived from usage: ≥ 95% is Critical, ≥ 90% is High, otherwise Normal. The notification title is Disk Space Alert: {mount_point} at {usage}% and the body tells you to free up disk space or raise the threshold in Settings → System Monitoring.
The monitor only runs when a notification provider is configured — alerts are skipped entirely if none is set up. While monitoring is disabled, the loop re-checks settings every 60 seconds.
You can also read current disk usage on demand without sending any notifications:
GET /api/settings/disk-status
This read-only endpoint (requires the SettingsRead permission) returns a DiskSpaceCheckResult with checked_at, enabled, threshold_percent, the per-mount disks usage, and any alerts (mounts meeting or exceeding the threshold). The dashboard uses it to surface a low-disk-space warning.