move-server.sh: --docker-sock to give the container the target's Docker

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Richard ZinkandClaude Opus 5.5 committed 2026-11-09 15:30:29 +01:00
1 parent b59c5b8890
commit 36de035dd8
2 files changed
+35 -6

No files matched your search

+18 -2
View File
@@ -47,6 +47,7 @@ Decide:
| Folder for agent installs and `/tmp` | `--tools-dir` | `/mnt/disks/ssd/codecraft` | | Folder for agent installs and `/tmp` | `--tools-dir` | `/mnt/disks/ssd/codecraft` |
| Your projects | `--workspace` | `/mnt/user/projects` | | Your projects | `--workspace` | `/mnt/user/projects` |
| Owner of files (the container runs as this user) | `--uid`, `--gid` | Unraid default `99`/`100` (nobody:users); today `1000`/`1000` | | Owner of files (the container runs as this user) | `--uid`, `--gid` | Unraid default `99`/`100` (nobody:users); today `1000`/`1000` |
| Docker of the new host for agents and terminals | `--docker-sock` | bind mount of `/var/run/docker.sock` plus its group (see below) |
| Port and address | `--port`, `--bind` | `8787`; `0.0.0.0` if the reverse proxy runs on another machine or in another Docker network, `127.0.0.1` if it runs on the same host with host networking | | Port and address | `--port`, `--bind` | `8787`; `0.0.0.0` if the reverse proxy runs on another machine or in another Docker network, `127.0.0.1` if it runs on the same host with host networking |
## Moving ## Moving
@@ -57,12 +58,12 @@ On the **current host**, in the repository folder (where `.env` is):
# 1. Look at the steps first (changes nothing) # 1. Look at the steps first (changes nothing)
scripts/move-server.sh root@unraid:/mnt/user/appdata/codecraft \ scripts/move-server.sh root@unraid:/mnt/user/appdata/codecraft \
--workspace /mnt/user/projects --tools-dir /mnt/disks/ssd/codecraft \ --workspace /mnt/user/projects --tools-dir /mnt/disks/ssd/codecraft \
--uid 99 --gid 100 --bind 0.0.0.0 --dry-run --uid 99 --gid 100 --bind 0.0.0.0 --docker-sock --dry-run
# 2. Move (same command without --dry-run) # 2. Move (same command without --dry-run)
scripts/move-server.sh root@unraid:/mnt/user/appdata/codecraft \ scripts/move-server.sh root@unraid:/mnt/user/appdata/codecraft \
--workspace /mnt/user/projects --tools-dir /mnt/disks/ssd/codecraft \ --workspace /mnt/user/projects --tools-dir /mnt/disks/ssd/codecraft \
--uid 99 --gid 100 --bind 0.0.0.0 --uid 99 --gid 100 --bind 0.0.0.0 --docker-sock
``` ```
What happens: What happens:
@@ -93,6 +94,21 @@ Afterwards:
- **Clean up** on the old host when everything works: `docker rm codecraft`, later - **Clean up** on the old host when everything works: `docker rm codecraft`, later
`docker volume rm codecraft-data`. `docker volume rm codecraft-data`.
## Docker socket (`--docker-sock`)
With `--docker-sock` the container gets the new host's Docker: `/var/run/docker.sock` is bind
mounted and the container joins the socket's group (the script reads its group id on the
target). This is **root-equivalent access to the host**: whoever can start containers can mount
any host folder.
- Admins' agents and terminals (they run without sandbox) can use it.
- Sandboxed users do not see the socket (the sandbox does not mount `/var/run`).
- `docker` and `docker-compose` commands always need an approval, except in *bypass* mode.
- The image has no Docker CLI; agents install the static CLI into their home when they need it
(on the tools disk with `--tools-dir`).
The current host has the same setup in its local `docker-compose.override.yml` (group 997).
## Rollback ## Rollback
Nothing is deleted on the old host. On Unraid stop the new container (`docker stop codecraft`), Nothing is deleted on the old host. On Unraid stop the new container (`docker stop codecraft`),
+17 -4
View File
@@ -27,6 +27,10 @@
# (/data/home), the users' homes (/data/users) and /tmp are bind # (/data/home), the users' homes (/data/users) and /tmp are bind
# mounts from DIR/home, DIR/users and DIR/tmp (default: inside <dir>/data) # mounts from DIR/home, DIR/users and DIR/tmp (default: inside <dir>/data)
# --uid N --gid N owner of data and workspace on the target (default: UID/GID of .env) # --uid N --gid N owner of data and workspace on the target (default: UID/GID of .env)
# --docker-sock give the container the target's Docker (bind mount of
# /var/run/docker.sock plus its group). Root-equivalent access to the
# target host for admins' agents and terminals; sandboxed users do not
# see it, and docker commands still need approval
# --port N host port on the target (default: PORT of .env) # --port N host port on the target (default: PORT of .env)
# --bind ADDR bind address on the target (default: BIND_ADDR of .env or 127.0.0.1) # --bind ADDR bind address on the target (default: BIND_ADDR of .env or 127.0.0.1)
# --name NAME container name on the target (default codecraft) # --name NAME container name on the target (default codecraft)
@@ -37,12 +41,13 @@
# --dry-run show the steps only # --dry-run show the steps only
set -euo pipefail set -euo pipefail
target="" ws_target="" tools_dir="" uid="" gid="" port="" bind="" name="codecraft" target="" ws_target="" tools_dir="" docker_sock=0 uid="" gid="" port="" bind="" name="codecraft"
src_container="codecraft" src_volume="codecraft-data" ws_source="" stop=1 dry=0 src_container="codecraft" src_volume="codecraft-data" ws_source="" stop=1 dry=0
while (($#)); do while (($#)); do
case "$1" in case "$1" in
--workspace) ws_target="$2"; shift ;; --workspace) ws_target="$2"; shift ;;
--tools-dir) tools_dir="$2"; shift ;; --tools-dir) tools_dir="$2"; shift ;;
--docker-sock) docker_sock=1 ;;
--uid) uid="$2"; shift ;; --uid) uid="$2"; shift ;;
--gid) gid="$2"; shift ;; --gid) gid="$2"; shift ;;
--port) port="$2"; shift ;; --port) port="$2"; shift ;;
@@ -137,8 +142,15 @@ fi
step "Copying the workspace (changes since the first pass)" step "Copying the workspace (changes since the first pass)"
sync_workspace sync_workspace
remote "chown -R $uid:$gid $(q "$dir/data") $(q "$ws_target") ${tools_dir:+$(q "$tools_dir/home") $(q "$tools_dir/users")} 2>/dev/null || echo 'note: could not chown (not root) – check file owners'" remote "chown -R $uid:$gid $(q "$dir/data") $(q "$ws_target") ${tools_dir:+$(q "$tools_dir/home") $(q "$tools_dir/users")} 2>/dev/null || echo 'note: could not chown (not root) – check file owners'"
# Bind mounts for the tools disk (compose lines and docker run flags). # Bind mounts for the tools disk and the Docker socket (compose lines and docker run flags).
tool_mounts="" tool_flags="" tool_mounts="" tool_flags="" sock_compose="" sock_flags=""
if (( docker_sock )); then
if (( dry )); then sock_gid=0; else
sock_gid=$(remote "stat -c %g /var/run/docker.sock") || fail "no /var/run/docker.sock on the target"
fi
sock_compose=$(printf ' - /var/run/docker.sock:/var/run/docker.sock\n group_add:\n - "%s"\n' "$sock_gid")
sock_flags="-v /var/run/docker.sock:/var/run/docker.sock --group-add $sock_gid "
fi
if [[ -n "$tools_dir" ]]; then if [[ -n "$tools_dir" ]]; then
tool_mounts=$(printf ' - %s/home:/data/home\n - %s/users:/data/users\n - %s/tmp:/tmp\n' "$tools_dir" "$tools_dir" "$tools_dir") tool_mounts=$(printf ' - %s/home:/data/home\n - %s/users:/data/users\n - %s/tmp:/tmp\n' "$tools_dir" "$tools_dir" "$tools_dir")
tool_flags="-v $tools_dir/home:/data/home -v $tools_dir/users:/data/users -v $tools_dir/tmp:/tmp " tool_flags="-v $tools_dir/home:/data/home -v $tools_dir/users:/data/users -v $tools_dir/tmp:/tmp "
@@ -168,6 +180,7 @@ services:
- $dir/data:/data - $dir/data:/data
- \${WORKSPACE}:/workspace - \${WORKSPACE}:/workspace
$tool_mounts $tool_mounts
$sock_compose
extra_hosts: extra_hosts:
- "host.docker.internal:host-gateway" - "host.docker.internal:host-gateway"
shm_size: "1gb" shm_size: "1gb"
@@ -186,7 +199,7 @@ val() { sed -n "s/^\$1=//p" .env | tail -1; }
docker rm -f $name >/dev/null 2>&1 || true docker rm -f $name >/dev/null 2>&1 || true
exec docker run -d --name $name --restart unless-stopped --user "\$(val UID):\$(val GID)" \\ exec docker run -d --name $name --restart unless-stopped --user "\$(val UID):\$(val GID)" \\
-p "\$(val BIND_ADDR):\$(val PORT):8787" --env-file .env \\ -p "\$(val BIND_ADDR):\$(val PORT):8787" --env-file .env \\
-v $dir/data:/data -v "\$(val WORKSPACE):/workspace" $tool_flags\\ -v $dir/data:/data -v "\$(val WORKSPACE):/workspace" $tool_flags$sock_flags\\
--add-host host.docker.internal:host-gateway --shm-size 1g \\ --add-host host.docker.internal:host-gateway --shm-size 1g \\
--security-opt seccomp=$dir/docker/seccomp-sandbox.json \\ --security-opt seccomp=$dir/docker/seccomp-sandbox.json \\
--security-opt apparmor=unconfined --security-opt systempaths=unconfined \\ --security-opt apparmor=unconfined --security-opt systempaths=unconfined \\