Self-hosted service
sky22333/ansible-ui avatar
sky22333/ansible-ui

ansible-ui puts a browser panel in front of Ansible for small server fleets

轻量级,简单易用的Ansible Web管理面板,提供批量主机管理、运行剧本任务、命令执行、文件传输和Web终端等功能。

543 stars72 forksTypeScriptGPL-3.0

At a glance

What is it?
ansible-ui is a lightweight web management panel for Ansible that handles bulk host management, command execution, file upload, custom playbook runs, a browser terminal and access logs. It ships as a single container with a Flask and Paramiko backend and a TypeScript frontend, and its own README makes the encryption model unusually explicit.
Who is it for?
Adopt ansible-ui if you run a handful of Linux hosts and want a browser panel for running commands and playbooks without typing SSH each time. Skip it if you need multi-user RBAC, audit-grade logging or a credential store your operators cannot read, since the README says host passwords are encrypted with a key derived from the admin credentials.
Can I use it commercially?
Yes, with conditions. GPL-3.0 is a copyleft licence: if you distribute software that includes it, you must release that software's source code under the same licence. Running it internally without distributing it does not trigger that obligation.
Is it still maintained?
Yes. The repository last received commits 68 days ago.
What is it written in?
Mainly TypeScript, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on October 22, 2026, and from our analysis. They are not legal advice.

Editorial analysis

The feature set and who it is aimed at

The project describes itself in one line as a lightweight, simple Ansible web management panel providing bulk host management, command execution, file transfer and a web terminal, and it says explicitly that it suits beginners. The feature list expands that. Host management covers adding hosts in bulk, with password authentication supported and unified key authentication available as an alternative, and host passwords stored encrypted. Command execution sends a command to the selected hosts and shows the results. File upload sends a file to the selected hosts. Custom playbook execution lets you write and run Ansible Playbook tasks. The web terminal connects straight to a remote host from the browser. And there is an access log for recording and reviewing system access. The primary language is recorded as TypeScript, and the reason is visible in the build: the Dockerfile has a Node stage that installs pnpm and builds the frontend, while the server side is Python. The repository layout confirms the split, with a web directory for the frontend and app.py, database.py, ansible_manager.py and crypto_utils.py at the top level. The licence is GPL-3.0 and the last push was on 2026-08-16.

The container, its ports and its environment variables

Deployment is a single Docker run, with the panel on port 5000 and two directories mounted.

bash
docker run -d \
  --name ansible-ui \
  -p 5000:5000 \
  -e ANSIBLE_HOST_KEY_CHECKING=False \
  -e ADMIN_USERNAME=admin123 \
  -e ADMIN_PASSWORD=admin123 \
  -v ./ansible:/app/db \
  -v /root/.ssh:/root/.ssh:ro \
  ghcr.io/sky22333/ansible-ui

The same variables appear in the compose file that ships in the repository.

yaml
services:
  app:
    build: .
    ports:
      - "5000:5000"
    environment:
      - ANSIBLE_HOST_KEY_CHECKING=False
      - ADMIN_USERNAME=admin123
      - ADMIN_PASSWORD=admin123

Two things in that command deserve a second look. ANSIBLE_HOST_KEY_CHECKING=False disables SSH host key verification, which is convenient for a lab and dangerous anywhere else, since it means the panel will connect to any host that answers without verifying its identity. And the example credentials are admin123 for both, which the README asks you to change. The README also recommends putting a reverse proxy in front with HTTPS enabled, and says plainly that a strong password must be set. The mounted /root/.ssh directory is read-only and exists so the container can use the host's key for key-based authentication, while the ./ansible mount is the database directory that holds the panel's own state.

The encryption model, which is the part to read carefully

The README has a notice section that is more detailed than most, and it should be read before anything else. It states that the system depends entirely on administrator credentials to derive the encryption key, with no local key file at all. Changing the administrator password means previously encrypted data can no longer be decrypted, so important data must be backed up before a password change. The encryption key is only valid for the login session, so if the service restarts you have to log in again before you can reach the encrypted data. Those three facts together describe a design where there is no key escrow and no key rotation path: the admin credential is the root of trust for every stored host password. For a panel holding the credentials of every server it manages, that is the central operational fact, and it is the one to weigh against the convenience of the browser interface.

Key-based host authentication and the keypair setup

Key authentication is the recommended path for connecting hosts, and the README explains how it works. When key authentication is enabled, the hosts use one unified key, and you do not need to add a password when adding a host. By default the container reads /root/.ssh/id_ed25519 inside it, and you can either generate the keypair on the host and mount it in, or generate it inside the container. Generating it looks like this.

bash
ssh-keygen -t ed25519

The public key then has to reach the target host.

bash
ssh-copy-id -i /root/.ssh/id_ed25519.pub [email protected]

If the target host does not listen on the default port 22 you need to add the port parameter, and the README gives -o Port=2222 as the form. The command appends the contents of id_ed25519.pub to the authorized_keys file on the target host, and the README notes that a script with a for loop can do this to several hosts at once. That last point is the recommended workflow rather than a footnote: enrolling a fleet by hand is exactly the chore this panel exists to remove.

How the backend is put together

The Python dependency list is short and tells you the mechanism. Flask 3.0.3 serves the panel and its API, ansible 6.7.0 is the automation engine doing the actual playbook and command work, flask-sock 0.7.0 provides the WebSocket transport that a browser terminal needs, paramiko 3.5.0 handles the SSH connections to the managed hosts, PyJWT 2.4.0 or later under 3.0 issues the session tokens, and cryptography 41.0.3 does the encryption of stored host passwords. The Dockerfile is a two-stage build. The first stage is node:22-alpine, where pnpm is installed globally, the web directory is copied in and built with pnpm install and pnpm run build. The second stage is python:3.12-alpine, which copies the whole project, copies the built frontend from the first stage into /app/public, installs the Python requirements, removes the /app/web source directory and clears the apk cache, and adds the openssh-client and sshpass packages. The container exposes port 5000 and starts with CMD ["python", "app.py"]. Note the mismatch between the recorded primary language and the runtime: the TypeScript frontend is compiled away and discarded, and what actually runs is Flask.

Where ansible-ui is the wrong choice

Several limits are structural. The first is the credential model. Storing the SSH password of every managed host in a SQLite-style database in a mounted directory, encrypted with a key derived from the admin password, means a single leaked credential exposes the whole fleet's access, and a service restart forces a fresh login before the data is readable at all. There is no per-operator account model, no role separation and no team workflow described in the README, so this is a single-admin tool rather than a shared platform. The second is the deployment advice. The README's own security notice says no system can guarantee the absence of bugs and that a public-facing deployment must use nginx or caddy with an IP allowlist, which is an admission that the panel itself does not handle hostile network exposure. The third is the scope of Ansible itself. The panel does commands, playbooks, uploads and a terminal, and nothing about inventory management, roles, vault or secrets. If what you need is to run a scheduled job on forty hosts with proper reporting, a CI pipeline with an Ansible playbook is the better tool, and the panel is a convenience wrapper around a smaller job.

How it compares with the usual Ansible front ends

The standard alternatives are AWX and Ansible Tower, and the difference is one of size and intent. AWX is a full platform with a project model, inventory sources, scheduled jobs, a workflow designer, RBAC and a job history database, and it runs as a Kubernetes deployment or a container stack. ansible-ui is a single Flask process with a SQLite database and a static frontend, aimed at someone who wants a browser panel rather than a platform to deploy. The other alternative is not a product at all: ssh into the host and run ansible-playbook from a laptop, which is what most small fleets do and which costs nothing. What ansible-ui adds over that is reach. You can add a host from a browser, run a command against a selection of hosts and see the output without an SSH client, and the same unified key authenticates across the fleet. The key-authentication flow described in the README is the practical argument for it, because enrolling keys by script and then operating from a browser removes the per-host command line. What you give up is everything AWX provides around the Ansible execution itself.

Editorial conclusion

Adopt ansible-ui if you run a handful of Linux hosts and want a browser panel for running commands and playbooks without typing SSH each time. Skip it if you need multi-user RBAC, audit-grade logging or a credential store your operators cannot read, since the README says host passwords are encrypted with a key derived from the admin credentials. Before you deploy it, change ADMIN_USERNAME and ADMIN_PASSWORD, put it behind a reverse proxy with HTTPS and an IP allowlist, and back up the database before any password change.

Frequently asked questions

What does the ansible-ui web panel provide?

Bulk host management with password or unified key authentication, command execution against selected hosts, file upload, custom Ansible playbook execution, a browser web terminal, and an access log. The README describes it as a lightweight panel suited to beginners.

How do I deploy ansible-ui with Docker?

Run the published image with a port mapping to 5000, set ADMIN_USERNAME and ADMIN_PASSWORD, mount a directory for the database at /app/db and the host SSH directory read-only at /root/.ssh, and set ANSIBLE_HOST_KEY_CHECKING=False. A compose file with the same settings is included in the repository.

How are host passwords stored in ansible-ui?

The README states that the system depends entirely on the administrator credentials to derive the encryption key, with no local key file, that changing the admin password makes previously encrypted data undecryptable so data must be backed up first, and that the key is only valid for the login session so a service restart requires logging in again.

How do I connect hosts to ansible-ui with SSH keys?

Enable key authentication so hosts use one unified key and no password is needed when adding a host. The container reads /root/.ssh/id_ed25519 by default; generate the keypair with `ssh-keygen -t ed25519` and copy the public key to each target with `ssh-copy-id -i /root/.ssh/id_ed25519.pub [email protected]`, adding `-o Port=2222` if the host uses a non-default SSH port.

Official sources

  1. Issues
  2. License: GPL-3.0
  3. README
  4. sky22333/ansible-ui on GitHub
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/sky22333-ansible-ui.svg)](https://hysenlabs.com/projects/sky22333-ansible-ui)

Was this useful?