{% extends "base.html" %} {% from "_macros.html" import help %} {% block title %}Settings — BackupWatch{% endblock %} {% block main_class %}sv2{% endblock %} {% block subnav %}{% set subnav_on_settings = true %}{% include "_settings_subnav.html" %}{% endblock %} {% block content %}
SETTINGS / CONFIGURATION

Settings

{% if cleared %}{% endif %}
{# JS keeps this on the active tab so Save returns you to it #}

Mailbox

Where BackupWatch reads backup-notification emails from. One source is active at a time.

{# the dropdown is a UI split; storage stays mail_provider graph|imap + imap_auth, normalised in the save/test routes (google -> imap + Gmail server defaults) #} {% set prov_ui = 'graph' if values.mail_provider != 'imap' else ('google' if values.imap_auth == 'google' else 'imap') %} {# ---- Microsoft 365 (Graph) ---- #}

Needs an Azure app registration with the Mail.ReadWrite application permission (admin-consented). Setup: register an app ↗ · Entra admin center ↗. Full step-by-step guide: Documentation/M365-SETUP.md.

{# ---- Google Apps (Gmail / Workspace) ---- #}

Gmail or Google Workspace. Server details are set automatically (imap.gmail.com, SSL).

In Google Cloud, create an OAuth Web application client and add this redirect URI: {{ (values.public_url or '(set Public app URL under Notifications)') }}/settings/google/callback

{% if values.google_email %}

Connected as {{ values.google_email }}.

{% endif %}

{# buttons live inside the main settings form, so they submit sibling forms by id #} {% if values.google_email %} {% endif %}

Save the client ID & secret first, then connect. BackupWatch reads mail over IMAP (XOAUTH2) using the full-mailbox scope; no password is stored.

Use an App Password ↗ (needs 2-step verification, with IMAP enabled). Secrets are encrypted at rest and never shown back.

{# ---- generic IMAP ---- #}
{# ---- credentials: generic IMAP always; Google Apps in app-password mode ---- #}
{# applies to Google Apps + IMAP; for Gmail a label acts as a folder #}
{# ---- shared across providers ---- #} {% if test_result %}{% endif %} {% if poll_result %}{% endif %}
Test checks credentials; Check mailbox imports unread email immediately (uses saved settings).

Notifications

Immediate alerts

Email the moment a problem is detected. Turn both off for a quieter summary-only setup — the daily summary still reports failures and missed backups.


Daily summary

Health watchdog

{% for name in tz_names %}{% endfor %}

{{ tz_status }}

Outbound email (alerts & summaries)

With the connected mailbox, notifications come from the monitored address itself — for Microsoft 365 add the Mail.Send application permission to the same app registration and admin-consent it. Mail the mailbox sends to itself is ignored automatically, so alerts can never loop back into the Review queue.

SMTP server

Port 587 usually needs STARTTLS on; port 465 always uses implicit TLS (the STARTTLS box is ignored). Secrets are encrypted at rest and never shown back.

Send a test email

{% if smtp_test %}{% endif %}
Sends now using the values above — no need to save first.

Automation

When on, an email from a recognised client whose Veeam job name doesn't match any existing job will auto-create that job (active, flagged auto-created) and file the email against it — instead of going to the Review queue. Off = full manual control via Review. Only applies to recognised clients with a detectable Veeam job name; everything else still goes to Review.

AI assistance (optional)

Off by default. BackupWatch works fully without it. When enabled, the Find jobs for a client panel on Onboarding can ask Claude to improve its proposed job groupings. Only subject lines and sender addresses are sent — never message bodies, recipients or attachments. You review the exact payload before each request, and every request is recorded on the AI activity page.

Billed to your own Anthropic account at their published rates. A typical client search costs a few cents.

{# targets for the Google buttons inside the main form above (forms can't nest) #}
{% set licence_badges = {"free": "b-none", "active": "b-success", "grace": "b-warning", "enforced_free": "b-none", "audit_only": "b-warning", "hard_stop": "b-failure"} %} {% set licence_labels = {"free": "Free", "active": "Licensed", "grace": "Grace period", "enforced_free": "Free (grace ended)", "audit_only": "Audit only (alerts paused)", "hard_stop": "Hard stop"} %}

Licence

{{ licence_labels.get(licence_state.mode, licence_state.mode) }}   Active jobs: {{ licence_active_jobs }} / {{ "unlimited" if licence_state.job_limit is none else licence_state.job_limit }} {% if licence_state.type_name %}  Type: {{ licence_state.type_name }}{% endif %} {% if licence_state.expires_at %}  Expires: {{ "Never" if licence_state.expires_at.year >= 2999 else licence_state.expires_at.strftime("%Y-%m-%d") }}{% endif %}

{{ licence_state.reason }}

{% if licence_state.mode == "grace" %}

Every existing job keeps running and keeps being monitored for the whole grace period. New jobs are capped at 5 active until a licence is active.

{% endif %} {% if licence_state.mode == "audit_only" %}

What audit-only mode does: mailbox polling, job matching, missed-backup detection and event recording all keep running exactly as normal, and the dashboard, history and reports stay live. What stops is outbound email: backup alert emails and the daily digest are held back (queued alerts are kept and send once this clears). BackupWatch’s own health watchdog still emails you if polling stalls.

How to fix it: this install hasn’t been able to confirm its licence with the licence server for over a month. Let it reach licence.backupwatch.app again (outbound HTTPS, proxy, DNS) and press Refresh now below — alerting resumes immediately. If the licence itself has lapsed, renew it and activate the key here. New jobs are capped at 5 active until the licence is confirmed.

{% endif %} {% if licence_state.lease_lapsed and licence_state.mode == "grace" %}

This grace period is about reaching the licence server, not about your licence expiring. If it isn’t back in touch by then, BackupWatch switches to audit-only mode: it keeps monitoring and recording, but stops sending alert emails and the daily digest.

{% endif %} {% if values.licence_last_checkin %}

Last check-in: {{ values.licence_last_checkin }}

{% endif %}

Installation ID: {% if values.licence_install_id %}{{ values.licence_install_id }} {% else %}assigned after the first check-in{% endif %} {{ help("Your install's unique ID. Quote it to support so we can identify this installation.") }}

{% if licence_result %}{% endif %}

Free tier: up to 5 active jobs, no key needed. Paid: unlimited active jobs, one yearly subscription. The app checks in with the licence server daily; Refresh now does it immediately.

Every install — free or paid — reports its app version and licence status to licence.backupwatch.app daily, for support and update checks. See our privacy policy.

Email storage

BackupWatch keeps each backup email in its database. "Cleaning up" strips the stored email body from old events to reclaim space — the event itself (status, date, subject, sender) is kept, so history, the dashboard and reports are unaffected. You just can't re-open or export the full email afterwards.

{% set rdays = (values.email_retention_days or '0')|int %} {% set is_custom = rdays not in retention_presets %}
{{ email_stats.total }}
emails recorded
{{ email_stats.kept }}
with content kept {{ help("Events that still hold their full stored email. Cleanup lowers this; the lightweight event records remain for history.") }}
{{ email_stats.bytes|filesizeformat }}
storage used {{ help("Approximate size of all stored email bodies (text + HTML + preview).") }}

Cleanup runs automatically twice a day. It only strips email content — event records are always kept.

Manual cleanup

Backup & restore

Download a snapshot of everything — clients, jobs, history and settings — or restore from one. The backup bundle also carries this install's encryption key and identity, so a restore onto a new server can still decrypt your saved Graph/SMTP passwords and keeps its licence seat. The bundle includes your key — store it like a password.

Restore is a full administrative replacement: it replaces users, settings (including saved mail credentials), clients and history. Only restore a backup you created and trust; a valid database cannot prove who made it.

Full state adds deployment .env, application logs and retained local backups to the database, encryption key and install identity. It carries both credentials and your clients' data — the logs record sender addresses and email subjects, and the retained backups are whole database copies. Encrypt it and store it like a password. Restoring one also replaces the current logs and retained backups, so a newer local backup is lost if you restore an older archive.

Download database only (.db) — no key, no identity; secrets only decrypt with the original instance/secret.key.

Administration

Developer{% if values.dev_mode == "true" %} dev mode{% endif %}

Written to logs/backupwatch.log (rotating, 5 × 1 MB) and the console. View or download logs →

Unlocks the maintenance tools below. Saved with Save settings.

{% if values.dev_mode == "true" %}

Maintenance tools

Wipes all clients, jobs, match rules, emails and alerts for a clean slate while developing. Settings and users are kept. This cannot be undone.

Re-run matching on all stored emails against the current jobs & rules — keeps clients and jobs, only re-files the emails (and re-detects vendor/status). Use it to retest rule changes without re-fetching the mailbox.

Send all stored emails back to the Review queue unprocessed — detached from jobs and un-ignored, like a freshly connected mailbox. Nothing is deleted; clients and jobs are kept. Follow with Reprocess all emails to re-match, or triage the queue by hand.

Load a sample dataset (demo clients, jobs, 30 days of events, review-queue items) to explore the app. Replaces existing clients & emails; settings and users are kept.

Re-run the first-run setup wizard (Microsoft 365, import date, users, notifications). Existing data and your admin login are kept.

{% endif %}
Saves every section, whichever tab is open.
{% endblock %}