mirror of
https://github.com/Ark0N/Codeman.git
synced 2026-11-15 10:59:32 +01:00
Merge #573 feat(docker): guided first run for the Compose deployment
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
commit
a2c530b93c
12 files changed
+1439
-45
No files matched your search
@@ -622,6 +622,10 @@ Adding the header changed the preamble, so `CODEMAN_PREAMBLE` was bumped (1.22.0
|
||||
|
||||
`CODEMAN_DOCKER_DISABLE_SWAP_LIMIT=1` drops `--memory-swap` (and filters only that one kernel warning) for hosts without swap accounting; `--memory` still applies.
|
||||
|
||||
⚠️ **`docker/.env` is generated FROM `.env.example`, at 0600, never from a list of keys.** `Start-Codeman.sh`'s first run (only when nothing exists at that path: a dangling symlink or a directory is refused) rewrites the five `KEY=` lines it asks about and copies every other line, because `diffRequiredEnvKeys` refuses an in-app update while the user's file lacks a key the target release's example sets, so a hand-picked subset would block the very next update. Compose's dotenv is not bash: a backslash escapes a single-quoted value's closing quote (measured on 2.33.0 and 5.5.0), so `accept_password` and `accept_appdata_path` refuse a trailing backslash as well as a single quote. Compose also prefers the shell environment over the file, so setup unsets what it wrote, or a preset would beat a typed answer. `test/docker-start-setup.test.ts` pins all of it, against a stub that reproduces both rules.
|
||||
|
||||
⚠️ **`changeme` is refused by BOTH scripts**, before anything is built or stopped: the container publishes on every interface and holds the Docker socket, so that password is host root. `Update-Codeman.sh` needs its own check, ahead of its `down`, because a refusal found only at the handoff to `Start-Codeman.sh` would leave the stack stopped.
|
||||
|
||||
⚠️ The deployment ALSO self-updates in place (the repo bind mount at `/opt/codeman` + a restart-by-exiting supervisor) — see Self-update and `docs/docker-self-update.md` before touching `server.Dockerfile`, the compose file or `.env.example`, since each is an input to the updater's environment gate. User guides: `docs/docker-compose.md` + `docker/README.md`.
|
||||
|
||||
### DeepSeek web UI
|
||||
|
||||
+15
-10
@@ -12,14 +12,25 @@ It can also include the GitHub CLI (`gh`) and the Azure CLI (`az`) with the `azu
|
||||
|
||||
## Prerequisites
|
||||
|
||||
- Docker Engine or Docker Desktop with Docker Compose v2
|
||||
- A reachable Docker daemon
|
||||
- Docker Engine or Docker Desktop with the Docker Compose v2 plugin, version 2.27.2 or newer
|
||||
- A reachable Docker daemon, usable by your account without sudo (on Linux, membership of the `docker` group)
|
||||
|
||||
The application container mounts the Docker daemon socket so Codeman can create and manage its isolated Docker cases. Treat anyone who can administer this Compose project as having Docker-host-equivalent access.
|
||||
|
||||
## Start
|
||||
|
||||
Copy the environment template, set a strong password, and confirm `CODEMAN_APPDATA_PATH`. The example maps `/mnt/user/appdata/codeman` on the host to `/home/${CODEMAN_RUNTIME_USER}` in the container, preserving Codeman state and CLI credentials outside Docker-managed volumes.
|
||||
On Linux, clone the repository and run the start script:
|
||||
|
||||
```sh
|
||||
git clone https://github.com/Ark0N/Codeman.git && cd Codeman
|
||||
bash docker/Start-Codeman.sh
|
||||
```
|
||||
|
||||
The first run checks Docker, Compose and the daemon, then asks for a data folder (default `~/codeman-docker`), a port (default 3000, or the next free one) and a password (Enter generates one, shows it on your terminal and keeps it in `docker/.env`). It writes `docker/.env` from `docker/.env.example`, builds the image, starts the container and waits until Codeman answers, then prints the URL and how to sign in. `--yes` takes every default without asking, and `--setup-only` writes `docker/.env` and stops so it can be reviewed first. The full description, including the options, is the Start section of the [Docker deployment guide](../docker/README.md#start).
|
||||
|
||||
The data folder is mounted at `/home/${CODEMAN_RUNTIME_USER}` in the container, so Codeman state and CLI credentials stay on the host outside Docker-managed volumes. On every start the script determines `PUID` and `PGID` from the owner of that folder, and `DOCKER_SOCKET_GID` from the configured Docker socket, before invoking Compose. A root-owned data folder is rejected so the runtime account cannot become UID 0.
|
||||
|
||||
To write `docker/.env` by hand instead (Unraid and other root-only hosts, or Compose without the script), copy the template, set a strong password, and confirm `CODEMAN_APPDATA_PATH`. The example value `/mnt/user/appdata/codeman` is an Unraid layout.
|
||||
|
||||
```sh
|
||||
cp docker/.env.example docker/.env
|
||||
@@ -31,12 +42,6 @@ On PowerShell, use the following command instead.
|
||||
Copy-Item docker/.env.example docker/.env
|
||||
```
|
||||
|
||||
On Linux, run the stack with the start script. It determines `PUID` and `PGID` from the owner of `CODEMAN_APPDATA_PATH`, and `DOCKER_SOCKET_GID` from the configured Docker socket, before invoking Compose. A root-owned application-data directory is rejected so the runtime account cannot become UID 0.
|
||||
|
||||
```sh
|
||||
bash docker/Start-Codeman.sh
|
||||
```
|
||||
|
||||
On other platforms, run Compose directly. `PUID` and `PGID` default to `1000:1000`; set them in `docker/.env` when the application-data directory has a different owner. Naming the file with `-f` disables Compose's own discovery of `docker/docker-compose.override.yml`, so add a second `-f` for it when you keep one (see `docker/README.md`, Local customisation).
|
||||
|
||||
```sh
|
||||
@@ -45,7 +50,7 @@ docker compose --env-file docker/.env -f docker/docker-compose.yaml up --build -
|
||||
|
||||
The container starts as root, corrects the ownership of a bind source the daemon had to create, and drops to `PUID:PGID` with `setpriv` before Codeman starts; the capabilities that needs are declared in `docker/docker-compose.yaml` and named by the entrypoint when a compose file written elsewhere lacks them.
|
||||
|
||||
Open `http://localhost:3000` and sign in with the username and password from `docker/.env`.
|
||||
Open the URL the script printed (`http://localhost:3000` by default) and sign in with the username and password from `docker/.env`.
|
||||
|
||||
## Operations
|
||||
|
||||
|
||||
@@ -144,16 +144,24 @@ See [Contributing](Contributing) for the rest of the development loop.
|
||||
## Route D: Docker Compose
|
||||
|
||||
Codeman itself can run in a container and spawn Docker cases as sibling containers through
|
||||
the host's Docker socket. Copy `docker/.env.example` to `docker/.env`, set
|
||||
`CODEMAN_PASSWORD`, then:
|
||||
the host's Docker socket. You need Docker with the Compose v2 plugin (2.27.2 or newer), and
|
||||
an account that can use Docker without sudo (on Linux, the `docker` group). Then, on Linux:
|
||||
|
||||
```bash
|
||||
git clone https://github.com/Ark0N/Codeman.git && cd Codeman
|
||||
bash docker/Start-Codeman.sh
|
||||
```
|
||||
|
||||
The first run asks for a data folder, a port and a password. Enter takes each default,
|
||||
including a generated password, shown on your terminal and kept in `docker/.env`. It then
|
||||
writes that file, builds the image (a few minutes the first time) and ends on the URL once
|
||||
Codeman answers. The image
|
||||
already includes Claude Code, Codex, Gemini CLI and OpenCode: start a session and log the CLI
|
||||
in once, and the login is kept in the data folder.
|
||||
|
||||
Run the script again after updating rather than a plain `docker compose up`, so the rebuilt
|
||||
image, the refreshed volumes and the entrypoint arrive together. The full guide, including
|
||||
storage and networking options, is
|
||||
Unraid, storage and networking options, is
|
||||
[`docker/README.md`](https://github.com/Ark0N/Codeman/blob/master/docker/README.md).
|
||||
|
||||
## Installing an agent CLI
|
||||
@@ -219,7 +227,7 @@ Full detail, including logs and the self-updater, is in
|
||||
| Installer | Re-run the one-liner, or **App Settings → System → Updates** in the UI. |
|
||||
| npm | `npm update -g aicodeman` |
|
||||
| git clone | `git pull && npm install && npm run build`, then restart. |
|
||||
| Docker Compose | Re-run `Start-Codeman.sh`. The in-app updater works too, and refuses a release that changes the container definition until you re-run the script. |
|
||||
| Docker Compose | `git pull`, then re-run `Start-Codeman.sh`. The in-app updater works too, and refuses a release that changes the container definition until you re-run the script. |
|
||||
|
||||
The in-app updater covers git-clone installs supervised by systemd or launchd. It restarts
|
||||
the process that is running it, so the actual work happens in a detached script and the
|
||||
|
||||
@@ -147,7 +147,7 @@ log stream --predicate 'process == "node"' # macOS, noisy
|
||||
| Installer | Re-run the one-liner, or **App Settings → System → Updates**. |
|
||||
| npm | `npm update -g aicodeman` |
|
||||
| git clone | `git pull && npm install && npm run build`, then restart. |
|
||||
| Docker Compose | Re-run `Start-Codeman.sh`, or the in-app updater, which restarts the container in place. |
|
||||
| Docker Compose | The in-app updater, which restarts the container in place, or `git pull`, then re-run `Start-Codeman.sh`. |
|
||||
|
||||
### The in-app updater
|
||||
|
||||
@@ -188,7 +188,13 @@ the bind-mounted directories with the right owner, honours a `docker-compose.ove
|
||||
and refreshes the build volumes when the checkout moved under them. The in-app updater
|
||||
applies code only and restarts by letting the container exit, so it refuses a release that
|
||||
changes the Dockerfile, the compose file, or adds a new `.env` key, until you re-run the
|
||||
script. Guide:
|
||||
script.
|
||||
|
||||
With no `docker/.env` yet, the script first asks for a data folder, a port and a password and
|
||||
writes that file. It then waits up to 180 seconds for Codeman to answer and exits 1 if the
|
||||
container crash-loops or never answers; pass `--no-wait` for scripted use. `Start-Codeman.sh`
|
||||
and `Update-Codeman.sh` both refuse to run while `CODEMAN_PASSWORD` is still the example
|
||||
`changeme`. Guide:
|
||||
[`docker/README.md`](https://github.com/Ark0N/Codeman/blob/master/docker/README.md).
|
||||
|
||||
## The tunnel as a service
|
||||
|
||||
@@ -354,6 +354,21 @@ Start the stack with `bash docker/Start-Codeman.sh` rather than a plain `docker
|
||||
and update: since 1.29.0 the entrypoint corrects a root-owned bind mount before dropping
|
||||
privileges. See [Running As A Service](Running-As-A-Service).
|
||||
|
||||
### Compose: `CODEMAN_PASSWORD is still the example value "changeme"`
|
||||
|
||||
`Start-Codeman.sh` and `Update-Codeman.sh` refuse that password before they build or stop
|
||||
anything, because the container publishes its port on every interface and holds the Docker
|
||||
socket, so whoever signs in controls Docker on the host. Set a real password in `docker/.env`
|
||||
and run the script again.
|
||||
|
||||
### Compose: `Codeman did not come up`, or no answer after 180 seconds
|
||||
|
||||
`Start-Codeman.sh` waits for the server after `up -d`. `did not come up` means the container
|
||||
exited, restarted or went unhealthy, and the script prints its last log lines. `has not
|
||||
answered after 180 seconds` means it is still running but silent, so on a slow host it may
|
||||
just need longer: follow it with `docker compose logs -f codeman` from `docker/`. Either way
|
||||
the script exits 1, and `--no-wait` skips the wait for scripts that check on their own.
|
||||
|
||||
### A remote SSH session dropped and did not come back
|
||||
|
||||
A bounded-backoff watcher reattaches dropped sessions, and it is on by default. Intentional
|
||||
|
||||
Reference in new issue
Block a user