Compose Manager
Compose Manager includes a pip-installable terminal dashboard and an open-source web UI for managing Docker Compose stacks on a remote server over SSH. It discovers compose projects, shows their status and ports, and lets you bring services up, down, or inspect logs from a clean browser interface.
Terminal dashboard (Python package)
Requires Python 3.10+, the ssh executable on your local machine, and Docker
Compose v2 on the remote host. The SSH user must have permission to run Docker.
No Node.js, browser, or local Docker installation is required for the terminal UI.
Install from this checkout (the new Python package has not been published to PyPI):
python3 -m venv .venv
source .venv/bin/activate
pip install .
compose-manager
For development, use pip install -e '.[dev]' instead. You can also install this
checkout with pipx install . if you use pipx for terminal applications.
On first launch, fill in the connection form:
- Profile name and host: IP address, DNS name, or existing SSH alias.
- SSH username: leave blank to use SSH defaults.
- SSH port: leave blank to use SSH configuration (otherwise the SSH default is 22).
- Key path: optional; leave blank to use
ssh-agentor default SSH keys. - Project directories: comma-separated absolute remote paths, searched four levels deep.
- Refresh interval: at least two seconds.
- Use jump host: optional; enabling it reveals jump host, username, port, and a separate optional jump key path. Both hops must be able to authenticate.
A private IP does not automatically enable a jump host. Direct SSH works when the host is reachable through your VPN or local network. Use a jump host when that is the route needed to reach the target.
Profiles are saved to ~/.config/compose-manager/profiles.json (or under
XDG_CONFIG_HOME) with file permissions 0600. Only settings and key paths are
saved, never private key contents. Use Add host and Edit to manage connections.
Existing ~/.ssh/config and SSH agent settings are used by OpenSSH.
Before first use, connect with normal SSH to verify and accept the host key, and
load passphrase-protected keys into your agent (ssh-add /path/to/key). Background
commands use batch mode: they do not prompt for passwords, passphrases, or unknown
host keys. For a jump connection, verify both hosts with your normal SSH workflow.
If your public key is already authorized on the server, the corresponding private
key must still be available on the machine running Compose Manager or its agent.
Select a host, then select a container row with the mouse or keyboard:
| Control | Behavior |
|---|---|
| Up stack | Runs docker compose up -d for the selected Compose file. |
| Stop | Stops the selected service; for an empty stack row, stops the stack. |
| Down stack | Confirms, then removes stack containers and networks; does not pass --volumes. |
| Restart | Restarts the selected service, or the stack for an empty row. |
| Logs | Shows the latest 100 log lines for the service or stack. |
Refresh / r |
Rediscovers Compose files and updates container status. |
| Test SSH | Checks SSH authentication and remote Compose availability. |
Add host / n |
Opens a new connection form. |
q |
Quits. |
The table shows running and stopped containers, health, and published ports.
Stacks without containers appear as down rows and can be brought up. Scheduled
refreshes update status without repeating discovery; Refresh discovers new stacks.
Command output streams into the bottom panel, and failed commands report failure.
Mouse clicks require a terminal with mouse support; keyboard navigation is also
available. Port-conflict analysis remains available in the existing web UI.
Python development and releases
pip install -e '.[dev]'
pytest -q
python -m build
The build produces a wheel and source distribution under dist/. The Python CI
workflow tests supported Python versions and builds both artifacts.
Publish through GitHub Actions and the PyPI web UI
.github/workflows/pypi-publish.yml uses PyPI Trusted Publishing. No API token or
GitHub repository secret is needed.
-
Commit and push the package and workflows to
samirkoirala/compose-manageron GitHub'smainbranch. -
In GitHub repository Settings → Environments, create an environment named
pypi. You may add required reviewers if you want a release approval step. -
Sign in to PyPI and open Publishing. For the first release, add a pending publisher with these exact values:
PyPI field Value PyPI project name compose-managerOwner samirkoiralaRepository name compose-managerWorkflow name pypi-publish.ymlEnvironment name pypiThe workflow field is the filename, not the workflow's display name or full path. If the project already belongs to your PyPI account, add the same publisher under the project's Manage → Publishing page instead.
-
In GitHub Actions → Publish Python package to PyPI → Run workflow, select
main. This publishes the current package version after tests, a build, and strict metadata validation pass. Approve the environment if reviewers were configured. The first successful upload creates the PyPI project. -
After publishing, users can run
pip install compose-managerorpipx install compose-manager, thencompose-manager.
For subsequent releases, update the version in both pyproject.toml and
src/compose_manager/__init__.py, commit and push, then either run the workflow
manually on main or publish a GitHub release with tag python-vX.Y.Z (for example,
python-v0.1.0 for the first version). The release tag must match the package
version. Re-uploading an already published version fails; increment it first.
Docker's integer vN tags do not trigger Python publishing. Tests and builds run
without publishing credentials; only the separate publishing job has OIDC access.
See the official PyPI Trusted Publishing setup guide and publishing guide.
Features
- Discover
docker-compose.yml,docker-compose.yaml,compose.yml, andcompose.yamlfiles on remote servers. - Manage multiple VMs or a single host from one dashboard.
- View running status, service counts, published ports, and port conflicts.
- Start and stop stacks with streaming terminal output.
- Inspect the last 50 log lines for any project.
- Run as a Docker container with a simple
docker compose upworkflow.
Docker Hub Image
The published image name is:
samirkoirala/compose-manager
Versioning is automated by GitHub Actions:
- Each merge to
mainbuilds and pushes a new image. - The workflow auto-increments the latest
vNtag and publishes the next release asvN+1. - The same release is also pushed as
latestand as a commit-specificsha-...tag.
If the repository has no prior release tags, the workflow starts from the next integer version. With the existing v1 Docker Hub tag, the next release will be v2.
Quick Start
- Create a
.envfile in the project root. - Configure your SSH credentials and target server.
- Start the app.
docker compose up -d --build
Open http://localhost:3000 in your browser.
Configuration
All runtime configuration is loaded from .env.
Server Connection
| Variable | Example | Description |
|---|---|---|
VM_SERVERS |
10.x.x.x,10.x.x.x |
Optional comma-separated list of VMs shown in the dropdown. |
SERVER_IP |
10.xx.xx.xx |
Fallback target server if VM_SERVERS is not set. |
SERVER_SSH_PORT |
22 |
Target SSH port. |
SERVER_USERNAME |
ubuntu |
SSH username on the target server. |
PORT |
3000 |
Local web port for the app container. |
Jump Host
| Variable | Example | Description |
|---|---|---|
JUMP_HOST_IP |
2x.xx.xxx.x |
Optional jump host IP or hostname. Leave empty for direct SSH. |
JUMP_HOST_USER |
ubuntu |
SSH username for the jump host. |
JUMP_HOST_KEY_PATH |
/keys/jump.pem |
Optional separate private key for the jump host. |
JUMP_HOST_PORT |
2345 |
SSH port for the jump host. |
Project Discovery
| Variable | Example | Description |
|---|---|---|
PROJECTS_BASE_DIRS |
/home/ubuntu/projects,/srv/projects |
Comma-separated directories searched on the remote host. |
SSH Key Options
Set SSH_KEY_PATH to use a custom key path in the web container. Alternatively,
mount a default key or supply key contents below. If no explicit/default key file
is present, the backend can use SSH_AUTH_SOCK; using a host agent in Docker also
requires mounting its socket into the container.
You can provide the SSH private key in either of these ways:
Option A: Mount a file
volumes:
- ~/.ssh/id_rsa:/root/.ssh/id_rsa:ro
Option B: Use an environment variable
Set SSH_PRIVATE_KEY in .env with either raw key contents or a base64-encoded key.
Local Development
docker compose up --build
The backend serves the frontend from frontend/public, so there is no separate build step for the UI.
Use the published Docker image directly
You can run the published Docker image from Docker Hub without building locally. This is useful for quick deployments or using the image inside orchestration systems.
Run with docker run (example):
docker run --rm -p 3000:3000 \
-e SERVER_IP=10.0.0.10 \
-e SERVER_USERNAME=ubuntu \
-e PROJECTS_BASE_DIRS=/home/ubuntu/projects \
-v ~/.ssh/id_rsa:/root/.ssh/id_rsa:ro \
samirkoirala/compose-manager:latest
Or reference it from your own docker-compose.yml:
services:
compose-manager:
image: samirkoirala/compose-manager:latest # or a specific tag like v2
container_name: compose-manager
env_file: .env
ports:
- "3000:3000"
volumes:
- ~/.ssh/id_rsa:/root/.ssh/id_rsa:ro
restart: unless-stopped
Notes:
- Put your runtime variables (SSH user, server IP(s), jump host, and
PROJECTS_BASE_DIRS) into the.envfile referenced byenv_fileabove. - If you prefer not to mount a private key, set
SSH_PRIVATE_KEYin.envwith the raw key contents (or base64-encoded) — the container writes it to a secure temp file at runtime.
Repository Structure
.
├── backend/
│ ├── package.json
│ └── server.js
├── frontend/
│ └── public/
│ └── index.html
├── Dockerfile
├── docker-compose.yml
├── LICENSE
└── README.md
Release Workflow
The GitHub Actions workflow in .github/workflows/docker-publish.yml is responsible for:
- Building the Docker image.
- Pushing the image to Docker Hub.
- Publishing versioned tags such as
v2,v3, and so on. - Updating
latestto always point at the newest release.
To enable publishing, add these repository secrets in GitHub:
DOCKERHUB_USERNAMEDOCKERHUB_TOKEN
Contributing
Pull requests and issues are welcome. Please keep changes focused and include enough detail for maintainers to review behavior changes quickly.
License
This project is licensed under the MIT License. See LICENSE for details.
Metadata
Release files for compose-manager 0.1.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| compose_manager-0.1.0.tar.gz | 28.3 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| compose_manager-0.1.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 42.2 kB
Release files / compose_manager-0.1.0.tar.gz
| Download URL | compose_manager-0.1.0.tar.gz |
|---|---|
| Size | 28.3 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
b6b97f1b6e3f312f40f57f6630fb2cbc4caf49e2ef75e14b3923da6a9796f689
|
|
BLAKE2b-256 checksum How to use checksums |
8317f4d2acf01db6012f40caacbac166b6b99da8a6ce70553395c9b5c93cab29
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 2, 2026.
Transparency logRelease files / compose_manager-0.1.0-py3-none-any.whl
| Download URL | compose_manager-0.1.0-py3-none-any.whl |
|---|---|
| Size | 14.0 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
772de550e567d972a139da360161ab1fcdee8d7f5c0c405d85abab0ef5d1c432
|
|
BLAKE2b-256 checksum How to use checksums |
f9fc911886dc8e10f6e2f4468ebd0b69e0c7f64c2530ba3098aecce208314c2d
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 2, 2026.
Transparency log