A lightweight, self-hosted web UI for running Ansible playbooks.
No complex setup. Just clone, run, and manage your infrastructure.
| AnsiblePower | AWX / Tower | Semaphore | |
|---|---|---|---|
| Setup | 1 minute | 30+ minutes | 10 minutes |
| Database | SQLite (auto) | PostgreSQL | MySQL / BoltDB |
| Dependencies | Python + Flask | Docker + PostgreSQL + Redis | Go + DB |
| Footprint | ~20 MB | ~2 GB | ~100 MB |
| Cost | Free & open source | Free / Paid | Free |
If you need a simple, fast way to run playbooks from a browser — without setting up a full platform — AnsiblePower is for you.
- 📋 Playbook Management — List, view, and execute
.yml/.yamlplaybooks from a configurable directory ▶️ One-Click Execution — Run playbooks with a single click; a confirm dialog prevents accidental runs- 🎨 Color-coded Output —
ok:lines are green,changed:amber,fatal:/failed:red,PLAY RECAPbold — output is scannable at a glance - 📊 Color-coded History — Green rows for successful runs, red for failures, yellow for unreachable hosts
- 🔍 Search & Filter — Live search on the History page filters by playbook name or output text
- 📊 Execution History — Full log of every run with timestamps; export to JSON/CSV, import from backup
- 🖥️ System Monitoring — CPU and memory usage with colored progress bars
- 📁 Hosts Editor — View and edit your Ansible inventory file directly from the browser
- 🌙 Dark Mode — Toggle between light and dark themes (stored in
localStorage, no server round-trip) - 🔒 Security — CSRF protection, path traversal prevention, input validation, and hardened HTTP headers (
X-Frame-Options,X-Content-Type-Options,Referrer-Policy) - 🚦 Rate Limiting — 60 req/min default;
/run_playbookcapped at 5 req/min to prevent abuse - ⚙️ Configurable — Set playbooks directory and hosts file path from the UI or environment variables
- ⏱️ Timeout protection — Playbooks that hang are killed after 5 minutes with a friendly message
- 🔔 Toast notifications — Non-blocking success/error toasts replace browser
alert()calls - ⏳ Loading spinner — Visual feedback while a playbook runs; button disabled to prevent double-clicks
- 🛡️ Confirm dialogs — Destructive actions (run playbook, clear history) ask for confirmation first
- 📱 Mobile navigation — Responsive sidebar collapses on small screens
- 🧩 Utils module — Shared helpers (
utils.py) keep route logic clean and testable
git clone https://github.com/pooyanazad/AnsiblePower.git
cd AnsiblePower
cp .env.example .env # edit .env to set your FLASK_SECRET_KEY
docker compose up -dOpen http://localhost:5000 — done.
Volume mounts
| Host path | Container path | Purpose |
|---|---|---|
./playbooks/ |
/app/playbooks |
Your Ansible playbooks |
./data/ |
/app/data |
Config, history (SQLite), hosts file |
./logs/ |
/app/logs |
Application logs |
~/.ssh/ |
/home/appuser/.ssh (read-only) |
SSH keys for remote hosts |
Data persists across docker compose down && up.
git clone https://github.com/pooyanazad/AnsiblePower.git
cd AnsiblePower
pip install -r requirements.txt
python ansiblePower.pyOpen http://localhost:5000 and you're ready to go.
Requirements: Python 3.9+, Ansible installed and accessible via
ansible-playbook
make run # Start the Flask dev server (auto-reload)
make test # Run the full pytest test suite
make lint # Run flake8 on application source
make docker-build # Build the Docker image
make docker-up # Build + start via docker compose (detached)
make docker-down # Stop and remove containers
make clean # Remove __pycache__, .pyc, .coverage artefactsRun make (no target) for a full help summary.
| Light Mode | Dark Mode |
|---|---|
![]() |
![]() |
AnsiblePower/
├── ansiblePower.py # Main Flask application (routes, blueprints)
├── utils.py # Shared helpers: config, history, logging
├── Makefile # Developer convenience targets
├── Dockerfile # Multi-stage Docker build
├── docker-compose.yml # One-command deployment
├── .env.example # Environment variable template
├── requirements.txt # Python runtime dependencies
├── requirements-dev.txt # Dev/test extras (pytest, flake8, …)
├── templates/ # Jinja2 HTML templates
│ ├── base.html # Layout with sidebar, navbar, dark-mode toggle
│ ├── index.html # Playbook listing and execution
│ ├── history.html # Color-coded execution history table + search
│ ├── settings.html # Hosts editor, system status, config
│ ├── errors/ # Custom 400 / 404 / 500 error pages
│ └── partials/ # Header and sidebar components
├── static/
│ ├── css/styles.css # Custom styling + dark mode + output colors
│ └── js/main.js # Frontend logic (run, colorize, search, dark mode)
├── data/ # Runtime data (config.json, history.db, hosts)
├── playbooks/ # Your Ansible playbooks go here
├── logs/ # Application logs (rotating, 1 MB × 3)
└── tests/ # Unit and integration tests
Playbook output is automatically highlighted after each run:
| Pattern | Color | Meaning |
|---|---|---|
ok: / ok=N |
🟢 Green | Task succeeded, no change |
changed: / changed=N |
🟡 Amber | Task ran and changed state |
fatal: / failed: / failed=N>0 |
🔴 Red | Task failed |
PLAY RECAP |
Bold | Summary section |
PLAY [name] |
Bold | Play header |
TASK [name] |
Italic | Task header |
History table rows are also color-coded:
- 🟢 Green tint — all tasks succeeded (
ok=N, no failures) - 🔴 Red tint — one or more tasks failed
- 🟡 Yellow tint — hosts were unreachable
To prevent abuse and accidental DoS on the control node:
| Endpoint | Limit |
|---|---|
| All routes (default) | 60 requests / minute |
POST /run_playbook |
5 requests / minute |
When a limit is exceeded the server responds with HTTP 429 and a JSON error: {"error": "Too many requests. Please try again later."}.
AnsiblePower works out of the box. You can customize it through the Settings page or environment variables:
| Environment Variable | Default | Description |
|---|---|---|
FLASK_SECRET_KEY |
Auto-generated | Session encryption key |
FLASK_DEBUG |
false |
Enable Flask debug mode |
ANSIBLE_PLAYBOOK_BIN |
Auto-detected | Path to ansible-playbook binary |
Playbooks directory and hosts file path can be changed from Settings in the web UI.
# All tests
pytest tests/ -v
# With coverage report
pytest tests/ --cov=ansiblePower --cov=utils --cov-report=term-missing
# Or via make
make testContributions are welcome! Check out CONTRIBUTING.md and the open issues.
MIT © 2024 Pooyan Azad


