Metadata-Version: 2.5
Name: pfsentinel
Version: 0.2.3
Summary: Automated pfSense backup management tool
Project-URL: Homepage, https://github.com/NX1X/pfSentinel
Project-URL: Repository, https://github.com/NX1X/pfSentinel
Project-URL: Bug Tracker, https://github.com/NX1X/pfSentinel/issues
Project-URL: Changelog, https://github.com/NX1X/pfSentinel/blob/main/CHANGELOG.md
Author: nx1x
License: Apache-2.0
License-File: LICENSE
Keywords: backup,cli,firewall,network,pfsense
Classifier: Development Status :: 4 - Beta
Classifier: Environment :: Console
Classifier: Intended Audience :: System Administrators
Classifier: License :: OSI Approved :: Apache Software License
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 3.13
Classifier: Programming Language :: Python :: 3.14
Classifier: Topic :: System :: Systems Administration
Requires-Python: >=3.13
Requires-Dist: cryptography<51,>=50.0.1
Requires-Dist: keyring<26,>=25.0
Requires-Dist: lxml<7,>=6.1.1
Requires-Dist: packaging<27,>=26
Requires-Dist: paramiko<6,>=5
Requires-Dist: pydantic<3,>=2.10.0
Requires-Dist: requests<3,>=2.34.2
Requires-Dist: rich<16,>=15
Requires-Dist: typer<1,>=0.26
Requires-Dist: urllib3<3,>=2.7.0
Provides-Extra: dev
Requires-Dist: bandit[toml]<2,>=1.8; extra == 'dev'
Requires-Dist: build<2,>=1.2; extra == 'dev'
Requires-Dist: editables<1,>=0.5; extra == 'dev'
Requires-Dist: hatchling<2,>=1.25; extra == 'dev'
Requires-Dist: hypothesis<7,>=6.100; extra == 'dev'
Requires-Dist: mypy<3,>=2; extra == 'dev'
Requires-Dist: pip-audit<3,>=2.7.0; extra == 'dev'
Requires-Dist: pip-tools<8,>=7.4.0; extra == 'dev'
Requires-Dist: pyinstaller<7,>=6.10; extra == 'dev'
Requires-Dist: pytest-cov<8,>=7; extra == 'dev'
Requires-Dist: pytest<10,>=9.1.1; extra == 'dev'
Requires-Dist: responses<1,>=0.25.0; extra == 'dev'
Requires-Dist: ruff<0.17,>=0.15; extra == 'dev'
Requires-Dist: twine<8,>=7; extra == 'dev'
Requires-Dist: types-lxml>=2026.2.16; extra == 'dev'
Requires-Dist: types-paramiko<6,>=5; extra == 'dev'
Description-Content-Type: text/markdown

# pfSentinel

[![CI](https://github.com/NX1X/pfSentinel/actions/workflows/ci.yml/badge.svg)](https://github.com/NX1X/pfSentinel/actions/workflows/ci.yml)
[![GitHub Release](https://img.shields.io/github/v/release/NX1X/pfSentinel)](https://github.com/NX1X/pfSentinel/releases)
[![License](https://img.shields.io/badge/License-Apache_2.0-blue.svg)](LICENSE)
[![Python](https://img.shields.io/badge/python-%3E%3D3.13-blue.svg)](https://www.python.org/)
![Views](https://komarev.com/ghpvc/?username=NX1X-pfSentinel&label=views&color=brightgreen)

Automated backup and monitoring tool for pfSense firewalls. Built for homelabs.

pfSentinel connects to your pfSense devices over SSH or HTTPS and backs up configuration files, RRD data, package configs, DHCP leases, certificates, logs, ZFS snapshots, and full filesystem archives. It includes change detection, compression, scheduled backups, and notifications via Telegram, Slack, or Windows toast.

## A Word From the Developer

I was looking for a feature-rich, modern pfSense backup tool and only found projects that were no longer maintained. Since pfSense backups are part of my own [homelab backup infrastructure](https://github.com/NX1X/homelab), I decided to build pfSentinel and share it with the pfSense community.

If you have a request or an idea, I'd love to hear it, please [open a feature request](https://github.com/NX1X/pfSentinel/issues). You can also reach me on [LinkedIn](https://www.linkedin.com/in/edenporat) or through my [website](https://nx1xlab.dev/contact).

## Features

- **Full config backup** via SSH (SFTP) or HTTPS with CSRF-aware login
- **Extended backup targets** -- RRD graphs, package configs, DHCP leases, alias files, certificates, system logs
- **ZFS snapshots** with incremental send (pfSense 2.5+)
- **Filesystem archives** (tar.gz) as a non-ZFS fallback
- **Change detection** -- only saves when config sections actually change
- **SHA-256 verification** for every backup file
- **Scheduled backups** via Windows Task Scheduler, systemd user timers or cron
- **Notifications** -- Telegram, Slack, Windows toast
- **SSH key authentication** -- no password required
- **Strict SSH host key checking** -- confirm the pfSense key once (`pfs device trust-key`); a changed key is refused
- **Credential security** -- passwords in the OS keyring (or an AES-256-GCM encrypted store on headless systems), never in config files
- **Self-update** -- check for and install new releases from GitHub
- **Cross-platform** -- Windows and Linux (macOS best effort)
- **Reproducible CI** -- lint, tests, security audit and build defined with [Dagger](https://dagger.io), so the same pipeline runs on your machine and in GitHub Actions; hash-verified lockfiles and SHA-pinned Actions

## Quick Start

**Download a pre-built binary** (no Python required):

> [**Windows (pfs.exe)**](https://github.com/NX1X/pfSentinel/releases/latest) | [**Linux (pfs)**](https://github.com/NX1X/pfSentinel/releases/latest)

Or install from PyPI (Python 3.13+), same command on Linux and Windows:

```bash
pipx install pfsentinel
```

Plain `pip install pfsentinel` also works in a virtualenv or on Windows; on Ubuntu 23.04+ and Debian 12+ the system Python blocks it, so use pipx there.

Then:

```bash
pfs setup          # guided first-time wizard
pfs device add     # add your pfSense device
pfs backup run     # run your first backup
```

See the [Installation Guide](docs/installation.md) for all installation methods.

## Documentation

| Document | Description |
|----------|-------------|
| [Online manual](https://pfs.nx1xlab.dev/docs) | Every command, recipes, and a copy-paste version for AI assistants (`pfs docs`) |
| [Installation Guide](docs/installation.md) | pip, pre-built binary, and from-source installation |
| [Usage Guide](docs/usage.md) | CLI reference, configuration, scheduling, notifications |
| [Extended Backups](docs/extended-backups.md) | RRD, packages, DHCP, certs, logs, ZFS, archives |
| [Security Policy](SECURITY.md) | Vulnerability reporting, design decisions, credential storage |
| [Contributing](CONTRIBUTING.md) | Development setup, code style, pull requests |
| [CI with Dagger](docs/ci-dagger.md) | Run the CI pipeline locally |
| [Roadmap](ROADMAP.md) | Path to 1.0 and what is planned |
| [Changelog](CHANGELOG.md) | Version history |

## What Gets Backed Up

| Target | Method | Description |
|--------|--------|-------------|
| XML Config | SSH / HTTPS | Full pfSense configuration (`config.xml`) |
| RRD Data | SSH | Traffic and performance graphs |
| Package Configs | SSH | Installed package settings |
| DHCP Leases | SSH | Active DHCP lease table |
| Alias Files | SSH | URL tables and external alias files |
| Certificates | SSH | SSL/TLS certs from the filesystem |
| System Logs | SSH | Filter log, system log, custom log files |
| ZFS Snapshot | SSH | Full or incremental ZFS snapshot stream |
| Filesystem Archive | SSH | Tar archive of critical directories |

## Third-Party Credits

pfSentinel is built on these open-source libraries:

| Library | License | Purpose |
|---------|---------|---------|
| [Typer](https://github.com/fastapi/typer) | MIT | CLI framework |
| [Rich](https://github.com/Textualize/rich) | MIT | Terminal formatting |
| [Pydantic](https://github.com/pydantic/pydantic) | MIT | Data validation |
| [Paramiko](https://github.com/paramiko/paramiko) | LGPL-2.1 | SSH/SFTP connections |
| [cryptography](https://github.com/pyca/cryptography) | Apache-2.0 / BSD-3-Clause | SSH key handling |
| [Requests](https://github.com/psf/requests) | Apache-2.0 | HTTP client |
| [Packaging](https://github.com/pypa/packaging) | Apache-2.0 / BSD-2-Clause | Version parsing |

Paramiko is the only runtime dependency with a copyleft license (LGPL-2.1). When installed via pip, users can freely replace it. For binary releases, pfSentinel uses `--onedir` bundling so Paramiko remains replaceable. See [docs/LICENSE_AUDIT.md](docs/LICENSE_AUDIT.md) for the full dependency license audit.

## Contributing

Contributions are welcome! Please read the [Contributing Guide](CONTRIBUTING.md) before submitting a pull request.

If you find a bug or have a feature request, [open an issue](https://github.com/NX1X/pfSentinel/issues).

## Support

pfSentinel is free and open source. If it saves you time or you'd like to support continued development, you can [sponsor on GitHub](https://github.com/sponsors/NX1X) or [buy me a coffee](https://buymeacoffee.com/nx1x). Thank you!

## License

[Apache 2.0](LICENSE)
