docker-bastion/examples/docker-mailserver-vps/README.md

64 lines
2.8 KiB
Markdown
Raw Permalink Normal View History

# docker-mailserver "fake VPS" (one directory, nothing else)
A copy-paste setup that gives an operator (or an agent) an **interactive SSH
shell that feels like a VPS** — but the only real host data on it is your
`docker-mailserver` directory. The rest of the server's filesystem isn't
mounted, so there's nothing else to see.
Contrast with the sibling [`../docker-mailserver/`](../docker-mailserver/)
example: that one is **broker mode** — a fixed *menu* of `setup email …`
commands, no shell. This one is the opposite — a **full shell**, scoped to one
directory, for when you want to edit configs and drive `docker compose`
yourself.
## What you get
```
ssh -p 2222 agent@your-host
└─ bastion-vps key auth; forces every session into the jail
└─ docker exec -it dms-jail bash
└─ dms-jail disposable alpine + docker/compose/editors/git
ONLY real mount: your docker-mailserver directory
you land in it, read-write
```
Inside the shell you can `vim mailserver.env`, `docker compose up -d`,
`docker exec mailserver setup email add …`, `git pull`, etc.
## Setup
1. Paths are preset to `/srv/docker-mailserver` (host and in-jail, identical).
If your directory is elsewhere, edit the **two** paths in
[`docker-compose.yml`](docker-compose.yml) and keep both sides of the `:`
identical — a different in-jail path still lets you read/edit files, but
`docker compose` from the jail would resolve the stack's bind mounts to a
host path that doesn't exist and bring the mailserver up with empty data.
2. Add your key:
```bash
mkdir -p docker-data/bastion/users.d
cp ~/.ssh/id_ed25519.pub docker-data/bastion/users.d/me.pub
```
3. Launch:
```bash
docker compose up -d --build
ssh -p 2222 agent@your-host
```
## Security note — the docker-socket tradeoff
To let you run `docker compose` / restart the mailserver from the shell, the
jail is given the host docker socket. **A docker socket is host-root
equivalent** — from inside the shell, `docker run -v /:/host alpine sh` would
expose the whole host. So this is a *practical* one-directory VPS for **trusted
operators**, not a hard sandbox an adversary can't escape.
Want a real "only this directory exists" boundary instead? Remove the
`/var/run/docker.sock` mount from **both** services in the compose file. You
lose in-shell `docker compose`/restart (manage the stack from a separate
broker-mode bastion — see [`../docker-mailserver/`](../docker-mailserver/)),
but the shell then genuinely cannot reach anything but the mounted directory.
The auth boundary is your SSH key (`users.d/*.pub`) plus the bastion's
`ForceCommand`, which clients cannot bypass — a session can only ever become
the jail shell, never anything else.