Metadata-Version: 2.4
Name: eneru
Version: 4.11
Summary: Intelligent UPS Monitoring & Shutdown Orchestration for NUT
Author-email: Eneru Maintainers <noreply@github.com>
License: MIT
Project-URL: Homepage, https://github.com/m4r1k/Eneru
Project-URL: Documentation, https://eneru.readthedocs.io/latest/
Project-URL: Repository, https://github.com/m4r1k/Eneru.git
Project-URL: Issues, https://github.com/m4r1k/Eneru/issues
Project-URL: Changelog, https://github.com/m4r1k/Eneru/blob/main/CHANGELOG.md
Keywords: ups,nut,monitoring,shutdown,power,infrastructure
Classifier: Development Status :: 5 - Production/Stable
Classifier: Environment :: Console
Classifier: Intended Audience :: System Administrators
Classifier: License :: OSI Approved :: MIT License
Classifier: Operating System :: POSIX :: Linux
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.9
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Programming Language :: Python :: 3.14
Classifier: Topic :: System :: Monitoring
Classifier: Topic :: System :: Power (UPS)
Classifier: Topic :: System :: Systems Administration
Requires-Python: >=3.9
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: PyYAML>=5.4.1
Provides-Extra: notifications
Requires-Dist: apprise>=1.9.7; extra == "notifications"
Provides-Extra: dev
Requires-Dist: pytest>=7.0.0; extra == "dev"
Requires-Dist: pytest-cov>=4.0.0; extra == "dev"
Requires-Dist: pytest-mock>=3.10.0; extra == "dev"
Requires-Dist: pytest-timeout>=2.1.0; extra == "dev"
Requires-Dist: apprise>=1.9.7; extra == "dev"
Provides-Extra: docs
Requires-Dist: mkdocs>=1.6.1; extra == "docs"
Requires-Dist: mkdocs-material>=9.7.1; extra == "docs"
Dynamic: license-file

<div align="center">

# ⚡ Eneru

**UPS monitoring and shutdown orchestration for NUT**

[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
[![Python 3.9+](https://img.shields.io/badge/python-3.9+-blue.svg)](https://www.python.org/downloads/)
[![NUT Compatible](https://img.shields.io/badge/NUT-compatible-green.svg)](https://networkupstools.org/)
[![codecov](https://codecov.io/gh/m4r1k/Eneru/branch/main/graph/badge.svg)](https://codecov.io/gh/m4r1k/Eneru)
[![Documentation](https://img.shields.io/badge/docs-Read%20The%20Docs-blue.svg)](https://eneru.readthedocs.io/)
[![PyPI](https://img.shields.io/pypi/v/eneru.svg)](https://pypi.org/project/eneru/)

<p align="center">
  <img src="https://raw.githubusercontent.com/m4r1k/Eneru/main/docs/images/eneru-diagram.svg" alt="Eneru Architecture" width="600">
</p>

A Python-based UPS monitoring daemon that watches UPS status via [Network UPS Tools (NUT)](https://networkupstools.org/) and executes configurable shutdown sequences during power events.

[Documentation](https://eneru.readthedocs.io/) •
[Getting Started](https://eneru.readthedocs.io/latest/getting-started/) •
[Configuration](https://eneru.readthedocs.io/latest/configuration/) •
[Changelog](CHANGELOG.md)

</div>

---

## Why Eneru?

Most UPS shutdown solutions handle a single system. Eneru handles multiple systems:

| Challenge | Eneru Solution |
|-----------|----------------|
| Multiple servers need coordinated shutdown | ✅ Orchestrated multi-server shutdown via SSH |
| VMs and containers need graceful stop | ✅ Libvirt VM and Docker/Podman container handling |
| Network mounts hang during power loss | ✅ Timeout-protected unmounting |
| No visibility during power events | ✅ Notifications via 100+ services |
| Different systems need different commands | ✅ Per-server custom shutdown commands |
| Hypervisors need VM shutdown before host | ✅ Pre-shutdown actions (Proxmox, ESXi, XCP-ng, libvirt) |
| Battery estimates are unreliable | ✅ Multi-vector shutdown triggers |
| Network down during outage | ✅ Non-blocking notifications with persistent retry |

---

## Use cases

Homelabs, virtualization hosts (Proxmox, ESXi, libvirt), Docker/Podman container hosts, NAS systems (Synology, QNAP, TrueNAS), multi-server environments on a single UPS, and mixed physical/virtual setups.

---

## Quick start

### Installation

**PyPI:**
```bash
pip install eneru[notifications]
```

**Debian/Ubuntu:**
```bash
curl -fsSL https://m4r1k.github.io/Eneru/KEY.gpg | sudo gpg --dearmor -o /usr/share/keyrings/eneru.gpg
echo "deb [arch=all signed-by=/usr/share/keyrings/eneru.gpg] https://m4r1k.github.io/Eneru/deb stable main" | sudo tee /etc/apt/sources.list.d/eneru.list
sudo apt update && sudo apt install eneru
```

**RHEL/Fedora:**
```bash
sudo dnf install -y epel-release
sudo curl -o /etc/yum.repos.d/eneru.repo https://m4r1k.github.io/Eneru/rpm/eneru.repo
sudo dnf install eneru
```

### Configuration

```bash
# Edit configuration
sudo nano /etc/ups-monitor/config.yaml

# Validate and start
sudo python3 /opt/ups-monitor/eneru.py --validate-config
sudo systemctl enable --now eneru.service
```

### Minimal Config

```yaml
ups:
  name: "UPS@192.168.1.100"

triggers:
  low_battery_threshold: 20
  critical_runtime_threshold: 600

local_shutdown:
  enabled: true
```

See the [full documentation](https://eneru.readthedocs.io/) for complete configuration options.

---

## Features

- Multiple shutdown triggers: battery %, runtime, depletion rate, time on battery, FSD flag
- Orchestrated shutdown of VMs, containers, remote servers, filesystems, and the local system
- Notifications to 100+ services (Discord, Slack, Telegram, ntfy, email) via [Apprise](https://github.com/caronc/apprise/wiki), with non-blocking persistent retry
- Power quality monitoring: voltage, AVR, bypass, and overload detection
- Dry-run mode for safe configuration testing
- Unit tests, integration tests across 7 Linux distros, and E2E tests with real NUT/SSH/Docker services on every commit

---

## Why a systemd daemon? (No Docker)

Eneru runs as a systemd daemon, not a container. It shuts down Docker/Podman containers during power events, so running inside a container would mean getting killed during its own shutdown sequence.

See the [documentation](https://eneru.readthedocs.io/#why-a-systemd-daemon-no-docker) for the full explanation.

---

## The name

<img src="https://raw.githubusercontent.com/m4r1k/Eneru/main/docs/images/eneru.jpg" alt="Eneru from One Piece" width="120" align="right">

Named after [Eneru (エネル)](https://onepiece.fandom.com/wiki/Enel) from *One Piece*, the self-proclaimed God of Skypiea who ate the Goro Goro no Mi (Rumble-Rumble Fruit) and can control electricity. When the power from the grid fails, this tool takes over and shuts everything down safely. *Unlimited power... management!*

---

## Documentation

Full documentation at [eneru.readthedocs.io](https://eneru.readthedocs.io/):

- [Getting Started](https://eneru.readthedocs.io/latest/getting-started/) - installation and basic setup
- [Configuration](https://eneru.readthedocs.io/latest/configuration/) - full config reference
- [Shutdown Triggers](https://eneru.readthedocs.io/latest/triggers/) - how shutdown decisions work
- [Notifications](https://eneru.readthedocs.io/latest/notifications/) - Discord, Slack, Telegram, etc.
- [Remote Servers](https://eneru.readthedocs.io/latest/remote-servers/) - SSH setup for NAS and other servers
- [Testing](https://eneru.readthedocs.io/latest/testing/) - testing strategy and coverage
- [Troubleshooting](https://eneru.readthedocs.io/latest/troubleshooting/) - common issues and solutions

---

## License

MIT License - See [LICENSE](LICENSE) file for details.
