Commit-confirmed for OPNsense.
Automatic configuration rollback with safe mode, connectivity watchdog, and crash recovery.
Quick Start · How It Works · Features · Configuration · CLI Reference · FAQ
You SSH into your remote firewall. You change a firewall rule. The connection drops. The firewall is 500 miles away.
One bad rule, one typo in an interface config, one misguided NAT change, and you're driving to the data center at 2 AM.
Auto Rollback adds a dead man's switch to OPNsense. Before you make changes, enter Safe Mode. A countdown timer starts. If you don't confirm your changes before the timer expires, the system reverts to the last known-good configuration.
Juniper's commit confirmed and MikroTik's Safe Mode work the same way; this brings the pattern to OPNsense.
The plugin is submitted upstream (opnsense/plugins#5236) and not yet in the OPNsense package repository. Until it lands, install from source.
Option 1: copy the full plugin from this repository
SSH into the firewall as root:
fetch -o /tmp/autorollback.tar.gz https://github.com/mplind/os-autorollback/archive/refs/tags/v1.1.0.tar.gz
tar -xzf /tmp/autorollback.tar.gz -C /tmp
cp -R /tmp/os-autorollback-1.1.0/sysutils/autorollback/src/ /usr/local/
service configd restart
This installs everything this README describes: safe mode, the connectivity watchdog, and early boot recovery. Developed and tested against OPNsense 25.1.
Option 2: apply the upstream pull request
opnsense-patch -a mplind -c plugins c585c45b50
service configd restart
opnsense-patch fetches the commit from GitHub and applies it to the live system; running the same command again removes it. The pull request is scoped to the safe mode core for review, so this option installs the timer, rollback and safety net without the watchdog and boot recovery.
Once the plugin reaches the official repository:
pkg install os-autorollback
Navigate to System > Auto Rollback and check Enable plugin. Click Save.
- Click Enter Safe Mode
- Make your configuration changes (firewall rules, interfaces, NAT, etc.)
- Verify everything works
- Click Confirm Changes to keep them, or let the timer expire to revert
That's it. If anything goes wrong, the system rolls back automatically.
You click You make Timer Changes
"Enter Safe Mode" changes expires revert
| | | |
v v v v
+---------+ +------------------+ +-------------------+ +---------+
| Snapshot | -> | Countdown Timer | -> | Automatic Revert | -> | Reboot |
| Config | | (120s default) | | to snapshot | | or |
+---------+ +------------------+ +-------------------+ | Reload |
| +---------+
v
Click "Confirm"
to keep changes
Three independent layers protect the configuration:
If the timer daemon crashes, the watchdog catches it. If the whole system reboots, the boot recovery hook restores your config before any services read it.
- Snapshot your configuration with one click (or one command)
- Configurable timeout: 30 seconds to 60 minutes (default: 2 minutes)
- Extend the timer in 60-second increments if you need more time
- Full reboot or fast service reload on rollback
- Git backup integration (if
os-git-backupis installed)
The plugin page (System > Auto Rollback) shows a live control panel during safe mode:
- Countdown timer with progress bar
- Color-coded urgency (green > amber > red)
- Confirm, Revert, and +60s buttons
- CLI hints for SSH users
The dashboard widget mirrors the countdown and quick actions.
A page-wide banner (autorollback_banner.js) ships with the plugin but is not wired in: OPNsense has no plugin hook for injecting JavaScript into every page. It runs only if you reference it from a custom theme or a local template override.
An always-on health monitor that automatically rolls back if your changes break connectivity. No safe mode required.
- Runs independently of safe mode as a cron job (every 60 seconds)
- Configurable grace period after config changes (default: 60 seconds)
- Four predefined check types: ping the default gateway, ping a host, resolve a DNS name, fetch an HTTP(S) URL
- Optional secondary check; a round fails when either check fails
- Configurable failure threshold before rollback (default: 3 consecutive failures)
- No shell involved: checks run as argument lists or native Python calls with validated targets
Example: You change a VLAN config that breaks your management interface. The watchdog finds the gateway unreachable, counts 3 failures, and reverts. The management interface comes back on the old config.
A compact status indicator on your OPNsense dashboard showing:
- Current state (Disabled / Armed / Safe Mode / Restoring)
- Live countdown during safe mode
- Quick-action buttons
- Watchdog failure count
Every operation is available via configctl for SSH users and automation:
configctl autorollback safemode start # Enter safe mode
configctl autorollback safemode confirm # Confirm changes
configctl autorollback safemode cancel # Revert immediately
configctl autorollback safemode extend # Add 60 seconds
configctl autorollback status # Show current status
configctl autorollback watchdog check # Run watchdog checkNavigate to System > Auto Rollback to configure the plugin.
| Setting | Default | Description |
|---|---|---|
| Enable plugin | Off | Master switch for the entire plugin |
| Safe mode timeout | 120 seconds | Time before automatic rollback (30 - 3600) |
| Rollback method | Full reboot | How to apply the restored config. reboot is safest. reload is faster but may not fully apply all changes. |
| Setting | Default | Description |
|---|---|---|
| Enable watchdog | Off | Enable always-on connectivity monitoring |
| Grace period | 60 seconds | Wait time after a config change before running checks (15 - 600) |
| Failure threshold | 3 | Consecutive check failures before rollback (1 - 10) |
| Primary check | Ping the default gateway | One of: ping the default gateway, ping a host, resolve a DNS name, fetch an HTTP(S) URL |
| Primary check target | (empty) | Host/IP, DNS name, or URL, depending on the check type. Unused for the gateway ping. |
| Secondary check | Disabled | Optional second check; a round fails when either check fails |
| Secondary check target | (empty) | Target for the secondary check |
| Setting | Default | Description |
|---|---|---|
| Log rollbacks | On | Log all rollback events to syslog (autorollback facility) |
All commands return JSON and can be piped to jq for scripting.
configctl autorollback safemode start{
"status": "ok",
"message": "Safe mode activated. You have 120 seconds to confirm changes.",
"timeout": 120,
"remaining_seconds": 120,
"expiry_time": 1700000120.0,
"backup_file": "/conf/backup/config-1700000000.xml",
"backup_revision": "1700000000",
"token": "a1b2c3d4...",
"rollback_method": "reboot"
}Optional: override timeout (clamped to 30-3600):
configctl autorollback safemode start 300configctl autorollback safemode confirmconfigctl autorollback safemode cancelconfigctl autorollback safemode extend # +60 seconds (default)
configctl autorollback safemode extend 120 # +120 secondsconfigctl autorollback status{
"status": "ok",
"timestamp": 1700000033.0,
"system_state": "safe_mode",
"safe_mode": {
"active": true,
"remaining_seconds": 87,
"backup_file": "/conf/backup/config-1700000000.xml",
"backup_revision": "1700000000",
"start_time": 1700000000.0,
"expiry_time": 1700000120.0,
"timeout": 120,
"rollback_method": "reboot",
"timer_pid": 12345
},
"watchdog": {
"enabled": true,
"fail_count": 0,
"last_config_change": 0,
"last_config_backup": ""
},
"settings": {
"enabled": true,
"timeout": 120,
"rollback_method": "reboot",
"watchdog_enabled": true,
"grace_period": 60,
"fail_threshold": 3,
"check_type": "ping_gateway",
"check_target": "",
"check_type_2": "none",
"check_target_2": "",
"log_rollbacks": true
},
"token": "a1b2c3d4..."
}| State | Meaning |
|---|---|
disabled |
Plugin is turned off |
armed |
Plugin enabled, waiting for safe mode |
safe_mode |
Countdown active, waiting for confirmation |
restoring |
Rollback in progress |
All endpoints require OPNsense API authentication.
| Endpoint | Method | Description |
|---|---|---|
/api/autorollback/service/start |
POST | Enter safe mode |
/api/autorollback/service/confirm |
POST | Confirm changes |
/api/autorollback/service/cancel |
POST | Revert immediately |
/api/autorollback/service/extend |
POST | Extend timer |
/api/autorollback/service/status |
GET | Get current status |
/api/autorollback/settings/get |
GET | Get plugin settings |
/api/autorollback/settings/set |
POST | Update plugin settings |
For firewalls in remote locations where physical access is difficult:
Timeout: 300 seconds (5 minutes)
Rollback method: Full reboot
Watchdog: Enabled
Grace period: 60 seconds
Fail threshold: 2
Primary check: Ping the default gateway
Secondary check: Resolve a DNS name (target: opnsense.org)
For local development or lab environments where you want faster turnaround:
Timeout: 60 seconds
Rollback method: Service reload
Watchdog: Disabled
For high-availability deployments, use a longer timeout to allow both nodes to sync:
Timeout: 300 seconds
Rollback method: Full reboot
Watchdog: Enabled
Grace period: 120 seconds
Fail threshold: 3
When a rollback triggers (timer expiry, watchdog threshold, or manual revert), the system:
- Validates the backup file (XML parsing, schema checks, path validation)
- Acquires an exclusive restore lock (prevents concurrent rollbacks)
- Creates a safety backup of the current config (
config-pre-rollback.xml) - Writes the backup atomically (temp file + rename, never a partial write)
- Preserves file ownership and permissions
- Clears the config cache
- Applies the restored config via the configured method (reboot or reload)
- Cleans up state files and timer processes
- Logs the event to syslog
The operation is crash-safe: if power fails mid-rollback, the boot recovery hook picks up where it left off.
Yes. The rollback state is local to each node. If you're making changes to an HA pair, enter safe mode on each node independently. The timeout gives you enough time to sync changes between nodes before confirming.
The boot recovery hook detects the expired timer and restores the backup before any services start. Your firewall boots into the known-good configuration.
Yes. All operations are available via the standard OPNsense REST API. Use /api/autorollback/service/start to enter safe mode, apply your changes via other API endpoints, verify connectivity, then call /api/autorollback/service/confirm. If your automation script dies, the timer rolls back the change.
The watchdog and safe mode operate independently. The watchdog monitors connectivity after any config change, whether or not safe mode is active. During safe mode, the timer daemon handles rollback. The watchdog adds a second, always-on layer.
The entire /conf/config.xml file is restored from the backup. This includes firewall rules, interface configurations, NAT, VPN settings, and all other OPNsense configuration. Plugin-specific data stored outside of config.xml is not affected.
Yes. The timeout is clamped to the range of 30 to 3600 seconds (1 hour). This caps how long an unconfirmed safe mode can last.
- Reboot restarts the entire system. Every service picks up the restored configuration. It takes longer (30-60 seconds) but is the safest option.
- Reload restarts services in-place without a full reboot. It is faster (5-10 seconds), but some changes may not apply without a reboot.
For remote firewalls, choose reboot.
Pick from four predefined check types and set a target:
| Check type | Target | Passes when |
|---|---|---|
| Ping the default gateway | none needed | one ping reply arrives |
| Ping a host | IP or hostname | one ping reply arrives |
| Resolve a DNS name | hostname | the system resolver returns a record |
| Fetch an HTTP(S) URL | http:// or https:// URL |
any HTTP response arrives (a 404 still proves connectivity) |
Earlier versions accepted a free-form shell command. That design ran operator-supplied strings as root and could not be reviewed safely, so it is gone: targets are validated (hostname, IP, or URL shape only) and no check ever touches a shell.
Yes. When os-git-backup is installed, Auto Rollback triggers a git backup snapshot at the start of safe mode. This gives you a git-versioned record of the configuration at the point safe mode was entered.
OPNsense Web UI
|
PHP Controllers
(MVC Pattern)
|
configd Backend
(actions.conf)
|
+---------------+---------------+
| | |
safemode.py watchdog.py status.py
(Safe Mode (Cron (Status
Manager) Watchdog) Reporter)
| |
timer_daemon.py rollback.py
(Background (Rollback
Countdown) Executor)
| |
+-------+-------+
|
lib/common.py
(Shared Utilities)
|
+-------+-------+
| |
config.xml persistent state
(OPNsense (/conf/autorollback_
Config) pending.json)
Config saved ──> 50-autorollback (config hook)
Records config change timestamp
Enables watchdog tracking
System boots ──> 10-autorollback-recovery (early hook)
Checks for expired timers
Restores config before services start
cd os-autorollback
python -m pytest tests/ -v --tb=shortThe suite runs 238 tests.
os-autorollback/
sysutils/autorollback/
Makefile # OPNsense build config
pkg-descr # Package description
src/
etc/
inc/plugins.inc.d/
autorollback.inc # Cron and service registration
rc.syshook.d/
config/
50-autorollback # Config change hook
early/
10-autorollback-recovery # Boot recovery hook
opnsense/
mvc/app/
controllers/ # PHP MVC controllers
models/ # XML data model and ACL
views/ # Volt templates (UI)
scripts/autorollback/ # Python backend
lib/common.py # Shared utilities
safemode.py # Safe mode manager
timer_daemon.py # Background countdown
watchdog.py # Health monitor
rollback.py # Rollback executor
status.py # Status reporter
service/conf/actions.d/
actions_autorollback.conf # configd action definitions
www/js/
autorollback_banner.js # Global countdown banner
widgets/
AutoRollback.js # Dashboard widget
Metadata/
AutoRollback.xml # Widget metadata (endpoints, translations)
tests/ # 238 unit tests
conftest.py # Shared fixtures
test_common.py
test_safemode.py
test_timer_daemon.py
test_watchdog.py
test_rollback.py
test_status.py
test_syshooks.py
- Juniper JUNOS
commit confirmed— Rollback on confirmation timeout - MikroTik Safe Mode — Automatic revert on session loss
BSD-2-Clause. See LICENSE.
Built for the OPNsense community.