* feat(branding): white-label — public /branding, admin write, shell theming app_settings branding.* keys (product name, logo/favicon URLs, accent color, docs/support links). Public GET /branding so login and shell theme pre-auth; admin writes via PUT /settings. useBranding() applies document.title, accent CSS var and favicon; BrandWordmark replaces hardcoded wordmarks; admin Platform settings gain a Branding form. MCP containr_branding_get + settings_update. Generated with [Devin](https://devin.ai) Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com> * feat(invites): team invite links — admin create/revoke, public accept Admins mint single-use invite links (sha256-hashed token at rest, optional email binding, configurable TTL). Public endpoints let the accept page validate the link and register — working even while public signup is disabled. - migration + sqlc queries/model for user_invites - POST /admin/invites (returns one-time token+url), GET list, DELETE revoke - GET /auth/invites/:token public validation, POST /auth/accept-invite - CLI containr invites list|create|revoke; MCP invites tools - /auth/accept-invite page (expired/used/invalid states, bound-email lock) - Admin page Team invites section: create, copy link, revoke - OpenAPI + generated types + CLI guide Generated with [Devin](https://devin.ai) Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com> * feat(admin): impersonate user — 15-min token, audit-logged POST /admin/users/:id/impersonate mints a short-lived bearer token (impersonated_by claim) for support/debugging. Admin accounts cannot be impersonated; every mint is audit-logged with actor + target. - CLI: containr admin impersonate <user-id> (works via CONTAINR_TOKEN) - MCP: containr_admin_impersonate - Admin UI: per-user Impersonate action → token modal with usage hint - OpenAPI + generated types Verified live: token resolves to target, admin target 403, audit row. Generated with [Devin](https://devin.ai) Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com> * feat(git): GitHub App manifest self-provisioning + app-level webhook Admins create the instance GitHub App in-browser instead of hand- setting GITHUB_APP_* env vars: - POST /admin/git/github-app/manifest builds the manifest + URL; the frontend auto-submits it to github.com - /git/github-app/callback page exchanges the code via POST /admin/git/github-app/convert; credentials persist in app_settings (precedence over env) - GET /admin/git/github-app reports configured/source - POST /api/git/github-app/webhook — single app-level push receiver, HMAC-verified, dispatches via extracted dispatchPushToServices - install-url + installation-token paths resolve settings→env - CLI: containr admin github-app status|manifest|convert; MCP tools - Git providers UI shows "Set up GitHub App" for admins when unconfigured Generated with [Devin](https://devin.ai) Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com> * feat: activity feed — enriched audit events, global + per-project timelines audit_logs gains severity/category/label columns derived from resource+action at write time; legacy rows are classified on read and backfilled at boot in batches. - GET /activity: global feed scoped to the caller's visible projects (admins see all); severity/category/resource/project_id/since filters, page+limit - GET /projects/:id/activity: timeline correlated to the project's services, deployments, databases and the project record; access mirrors project read rules - Retention worker prunes rows older than AUDIT_RETENTION_DAYS (default 90, 0 disables), running once at boot then daily - project.create/delete now audited so timelines aren't empty - CLI `containr activity` with filter flags; MCP tools containr_activity_list + containr_project_activity - Frontend: /activity page (severity chips, icon per category) under Operate nav; project workspace gains an Activity view tab - OpenAPI + generated types + CLI docs Generated with [Devin](https://devin.ai) Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com> --------- Co-authored-by: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Containr
Self-hosted platform for deploying and managing containerized services. Railway-style project canvases on your own hardware.
Quick Start • Screenshots • Features • Guides • Contributing
Containr is an open-source control plane for Docker. Create a project, drop services onto a visual canvas, wire them together with environment variables, and deploy — no Kubernetes, no cloud bill. Services appear as nodes with auto-inferred connections; logs, metrics, builds, and rollbacks are one click away.
The platform doubles as a public showcase: visitors browse approved projects and the template catalog without an account, while owners manage everything behind sign-in and a platform admin approves, curates, and moderates from a dedicated console.
Screenshots
| Projects dashboard | Project canvas |
|---|---|
![]() |
![]() |
| Service detail | Managed databases |
|---|---|
![]() |
![]() |
Features
- Project canvas — visual service topology, groups, drag/drop, auto-inferred connections, right-click lifecycle actions
- Public project catalog — approved projects are browsable anonymously; new projects stay private until an admin approves them
- Admin console (
/admin) — platform stats, project approval/edit/delete, user admin management - Private networking — every project gets an isolated Docker network; services reach each other by name (
web:3000) and share variables via${{service.KEY}}references - Deployments & builds — Docker deploys with history, image rollback, live build status
- Runtime — replicas, published ports, domains, health checks, restart policies; start/stop/restart/redeploy from canvas or service page
- Git integration — GitHub, GitLab, Bitbucket, Gitea; webhooks, GitHub App
- Managed databases — create PostgreSQL, MySQL, MariaDB, MongoDB, Redis, Dragonfly, or ClickHouse directly from
/databases, with backup/restore - Template catalog — 30 official templates (NocoDB, Plausible, MinIO, n8n, …) plus user-defined templates with JSON upload and owner-scoped edit/delete
- Metrics — per-service Docker stats plus host CPU/memory/disk telemetry
- HA & scaling — failover policies, node agents, autoscaling rules
- Auth & security — Better Auth sessions (email/password self-hosted), personal access tokens with
read/write/adminscopes for CLI and agents, audit logs, vulnerability scans - CLI —
containrcovers the full API: projects, services, deployments, logs, exec, variables, databases, cron, templates, nodes, scaling, HA, security, gateway, admin — with--json,--yes, named profiles, andcontainr upfor current-directory deploys - Integrated docs — searchable documentation rendered in-app on the landing page and
/docs; syncs from GitHub, falls back to a bundled snapshot offline - Networking — Traefik reverse proxy, optional Cloudflare Tunnel
Access model
| Audience | Can do |
|---|---|
| Anonymous | Browse approved projects, services, templates, databases, HA status, docs |
| Signed-in user | Create/manage own projects, services, databases, templates; view own logs, variables, builds, deployments |
| Admin | Everything above plus project approval/moderation, user admin flags, HA manager controls, agent tokens, platform settings |
Logs, variables, exec consoles, and database connection URLs are never public — they require owner, member, or admin access regardless of a project's public visibility.
Quick Start
Requires Docker with the Compose plugin, openssl, and curl:
curl -fsSL https://raw.githubusercontent.com/Dvorinka/Containr/main/install.sh | bash
Installs into ./containr, generates secrets, pulls the published :latest
images, and starts the stack — UI at http://localhost:3000, API at
http://localhost:8082. Non-interactive; re-runs never overwrite .env.
The platform admin is provisioned at startup from environment variables:
ADMIN_EMAIL=[email protected]
ADMIN_PASSWORD=<generated> # keep in a local untracked file
ADMIN_NAME=Your Name # optional
Both the local account and the Better Auth session account are created, so
either sign-in path works. Without ADMIN_*, the first registered account
becomes owner; registration then closes automatically. The owner can reopen
it and configure a Cloudflare Tunnel token under Settings → Platform —
in-app values override env vars.
Override install defaults with env vars:
curl -fsSL https://raw.githubusercontent.com/Dvorinka/Containr/main/install.sh | \
HTTP_PORT=8080 CONTAINR_DIR=/opt/containr bash
CONTAINR_VERSION pins a release tag, CONTAINR_REF selects the git ref for
downloaded files, CONTAINR_BUILD=1 builds from source. From a git checkout,
./install.sh installs in place; plain docker compose up -d pulls the same
images (--build to compile locally).
Local development and self-hosted deployment (Traefik + Cloudflare Tunnel):
see docs/guides/ and infra/docker-compose.yml.
Architecture
app/frontend/ React 19 + Vite + TypeScript + Tailwind + React Flow
app/backend/ Go API (Gin) · PostgreSQL · Dragonfly · Docker SDK · Better Auth sidecar
infra/ Self-hosted compose: Traefik + Cloudflare Tunnel
docs/ Guides, OpenAPI spec, design documents
All configuration is via environment variables — see .env.example. Never
commit .env or .env.prod; keep generated admin credentials in a local
untracked file (e.g. admin-credentials.local). If a secret was ever
committed, rotate it.
Documentation
- In-app: the landing page and
/docsrender searchable docs — synced from this repository, with a bundled snapshot so they are never blank offline - docs/guides/ — setup, deployment, Cloudflare, autoscaling
- docs/api/openapi.yaml — API contract
- docs/developers/onboarding.md — contributor onboarding
make help— common tasks
Contributing · Security · MIT License © 2026 Tomas Dvorak



