Start — From Zero to SSH
Five steps from clone to shell. Works on Linux, macOS (OrbStack/Docker Desktop), Windows + WSL2. GHCR prebuilts mean no 10-minute first build.
1. Clone
Grab the IaC repo — all definitions are in docker-compose.yml + Dockerfiles + *.sh.
git clone https://github.com/1999AZZAR/ghost-machines.git
cd ghost-machines
2. Host Setup (Linux only — once)
Installs LXCFS so htop/free inside the container reports cgroup limits, not host totals.
Auto-detects your package manager (apt/pacman/dnf/zypper/apk).
Skip on macOS/WSL — start.sh auto-skips LXCFS via --no-lxcfs.
make setup-host # or ./setup-host.sh
# checks Docker, installs LXCFS if on Linux, prepares systemd unit
3. Pick an Engine + Pull (one)
Choose one GHCR package — not four. Ubuntu is the safe default (PPA, richest toolchain). Debian is slim/stabler. Alpine is musl-minimal. Arch is rolling.
docker pull ghcr.io/1999azzar/ghost-machine-ubuntu:latest # ~1.38 GB amd64 / 1.21 GB arm64
docker pull ghcr.io/1999azzar/ghost-machine-debian:latest # ~1.36 / 1.20 GB
All are linux/amd64,arm64 multi-arch — M-series Mac auto-pulls arm64.
4. Launch
start.sh syncs your host UID/GID to the developer user (so mounts/ never has permission hell), wires SSH keys, LXCFS, and GHCR image reuse (GHOST_IMAGE is honored).
Interactive (asks engine + mode):
./start.sh
Non-interactive (CI / headless):
GHOST_IMAGE=ghcr.io/1999azzar/ghost-machine-ubuntu:latest ./start.sh -e ubuntu -m single
./start.sh -e debian -m dual --build # force local build, skip GHCR
Modes:
./start.sh -e ubuntu -m single # 1c / 8G — standard
./start.sh -e debian -m dual # 2 × 1c / 8G — client-server
./start.sh -e arch -m power # 1 × 2c / 16G — heavy builds
./start.sh -e alpine -m half # 50% host CPUs/RAM — scale to host
5. Connect + Work
ssh -p 2223 developer@localhost
# pass: ghost (sudo: ghost)
# or, if ~/.ssh/id_ed25519.pub exists on host — auto-mounted, no password
fastfetch # confirm engine inside
exit # container stays; your work in mounts/ persists
Your home is mounts/ubuntu1 (or mounts/tenants/<id> in WaaS). Delete the container — work stays on host.
Customization
./start.sh -e ubuntu -m single -p 2225 # custom SSH port (useful when 2223 taken)
./start.sh -e debian -m single -t $TUNNEL_TOKEN # Cloudflare Tunnel — no port-forward needed
./start.sh --no-lxcfs # skip LXCFS (macOS/WSL default)
SSH_PASSWORD_AUTH=false ./start.sh # key-only, disable password (via .env)
Verify
docker ps # see ghost-machine-* containers
docker stats --no-stream # CPU/RAM per container
./tenant.sh list # for WaaS — see next page
./clean.sh -s # stop when done (L1)
Troubleshooting
- Port 2223 in use — pass -p 2225 or let tenant auto-allocate from 2225.
- Permission denied on mounts/ — re-run ./start.sh (it re-syncs UID/GID from id -u/g).
- htop shows host RAM — install LXCFS: make setup-host on Linux.
- GHCR pull denied — echo $GH_TOKEN | docker login ghcr.io -u USERNAME --password-stdin.