Web-based container manager for disposable browsers, messengers, Kali, and Ubuntu workspaces.
1.0K
GhostDeck launches disposable browser, messenger, Kali and Ubuntu workspaces from a web interface. It manages project containers through the Docker socket and serves the dashboard and every workspace through a managed Caddy container with HTTPS.
Screenshots, Debian packages and full documentation: github.com/solivagvs-dev/ghostdeck
latest, <version> — multi-arch manifests for linux/amd64 and linux/arm64<version>-amd64, <version>-arm64 — single-architecture imagesservices:
ghostdeck:
image: solivagvs/ghostdeck:latest
container_name: ghostdeck
restart: unless-stopped
volumes:
- /var/run/docker.sock:/var/run/docker.sock
# Must be the same absolute path inside and outside the container.
# Named volumes will not work here.
- /var/lib/ghostdeck:/var/lib/ghostdeck
environment:
TZ: Europe/Berlin
sudo mkdir -p /var/lib/ghostdeck
docker compose up -d
sudo cat /var/lib/ghostdeck/.initial-admin-password
Then open https://<host>/ and sign in at /admin/. Plain HTTP redirects to HTTPS, and the default certificate is issued by Caddy's internal CA, so browsers warn until you trust it.
No configuration is required to start. On first run the container writes /var/lib/ghostdeck/.env with a generated APP_SECRET, a generated admin password and every default listed below. That file is never rewritten afterwards; variables set on the container override it.
| Variable | Default | Purpose |
|---|---|---|
APP_SECRET | generated | HMAC key for session and CSRF cookies. Changing it signs everyone out. |
ADMIN_PASSWORD | generated | Admin login. Ignored when ADMIN_PASSWORD_HASH is set. |
ADMIN_PASSWORD_HASH | empty | bcrypt hash instead of a plaintext password. Compose expands $, so double it. |
REGISTRATION_TOKEN | empty | Invite code for /register. Empty leaves signup open to anyone who can reach the dashboard. |
PROJECT_NETWORK_ISOLATION | true | One Docker network per project. false puts every workspace on the shared network. |
DOCKER_NETWORK | ghostdeck-net | Base network name. Per-project networks are <name>-p<id>. |
PROJECT_UNCONFINED | false | Runs workspaces with seccomp=unconfined. Only needed if an image will not start otherwise. |
CADDY_HTTP_BIND | 80 | Host port for HTTP. off disables it. 127.0.0.1:8080 binds one address. |
CADDY_HTTPS_BIND | 443 | Host port for HTTPS, same syntax. |
TRUSTED_PROXIES | none | CIDRs whose X-Forwarded-For is trusted, so login rate limits see the real client address. |
PUID / PGID | 1000 | uid and gid owning workspace files. |
TZ | Europe/Berlin | Workspace timezone. |
IMAGE_<NAME>_ENABLED | true | Catalog toggles: FIREFOX, BRAVE, CHROME, CHROMIUM, TELEGRAM, SIGNAL, UBUNTU, KALI. |
Each project container runs on its own Docker bridge network, <DOCKER_NETWORK>-p<project-id>. Only the managed Caddy container is attached to every project network, so one workspace cannot reach another workspace's container directly; reaching one through Caddy requires a session that owns it.
Isolation applies between workspaces only. Every workspace keeps normal outbound access to the internet, the host's LAN and ports published on the host. Kali workspaces run with NET_ADMIN and NET_RAW, and Ubuntu Webtop runs with apparmor=unconfined.
80 and 443 on the host daemon./var/lib/ghostdeck, created 0700.docker logs ghostdeck 2>&1 | grep 'audit event='.Content type
Image
Digest
sha256:712007d73…
Size
74.9 MB
Last updated
about 2 months ago
docker pull solivagvs/ghostdeck