144 lines
7.9 KiB
Markdown
144 lines
7.9 KiB
Markdown
# Moving CodeCraft to another host (Unraid)
|
||
|
||
This guide moves a running installation – Docker volume `codecraft-data` on the current host –
|
||
to another Docker host that keeps its data in **bind mounts**, for example Unraid. The script
|
||
`scripts/move-server.sh` does the work; this page explains what goes where, what to prepare and
|
||
how to check and roll back.
|
||
|
||
## What lives where
|
||
|
||
| Part | Contents | Today (Docker volume) | On the new host |
|
||
|---|---|---|---|
|
||
| **Data** | database `codecraft.db`, `config.toml` (incl. API keys), daily backups | `codecraft-data:/data` | `<dir>/data` → `/data` |
|
||
| **Agent installs** | the agent's home `/data/home`: toolchains (Rust, …), pip/pipx/npm/cargo packages, downloaded programs (`~/opt`), caches | inside the volume | `<tools-dir>/home` → `/data/home` |
|
||
| **Users' homes** | homes of sandboxed users `/data/users/<name>/home` (their installs, git settings) | inside the volume | `<tools-dir>/users` → `/data/users` |
|
||
| **Temporary files** | `/tmp` of agents, builds, downloads | container layer | `<tools-dir>/tmp` → `/tmp` |
|
||
| **Workspace** | your projects | `WORKSPACE` from `.env` | `--workspace` path → `/workspace` |
|
||
| **Image** | the program | registry image | registry image |
|
||
|
||
The image never changes: the container runs without root (no `apt`, no `sudo`), so agents can
|
||
only install into their home directory. With `--tools-dir` everything agents install or
|
||
download lands on a separate disk (e.g. an SSD); the data folder keeps only the database,
|
||
configuration and backups. If the tools disk is lost, agents simply install what they need
|
||
again – nothing important is on it. (Backups contain the database and configuration, not the
|
||
agent home.)
|
||
|
||
Sizes on 2026-11-09 for orientation: agent home 2.2 GB (of which downloaded programs 1.3 GB,
|
||
Rust toolchain 0.8 GB), database/config/backups about 1.2 GB.
|
||
|
||
## Before you start
|
||
|
||
On the **new host** (Unraid):
|
||
|
||
- **SSH with a key** from the current host, without a password prompt. Check from the current
|
||
host: `ssh root@unraid true` (no output, no question = fine).
|
||
- **docker**, **rsync** and **tar** available (all three are on Unraid by default).
|
||
- **Docker Compose** is optional: without it the script starts the container with the generated
|
||
`start.sh` (Unraid: the "Docker Compose Manager" plugin adds Compose).
|
||
- The **tools disk** is mounted, e.g. an SSD via Unassigned Devices under `/mnt/disks/ssd`.
|
||
- **Registry access**: the image comes from `git.familie-zink.org/zink/codecraft`. If the pull is
|
||
refused, run `docker login git.familie-zink.org` on Unraid once.
|
||
|
||
Decide:
|
||
|
||
| Question | Option | Example |
|
||
|---|---|---|
|
||
| Folder for data, compose file and scripts | target `root@host:/dir` | `/mnt/user/appdata/codecraft` |
|
||
| Folder for agent installs and `/tmp` | `--tools-dir` | `/mnt/disks/ssd/codecraft` |
|
||
| 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` |
|
||
| 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 |
|
||
|
||
## Moving
|
||
|
||
On the **current host**, in the repository folder (where `.env` is):
|
||
|
||
```sh
|
||
# 1. Look at the steps first (changes nothing)
|
||
scripts/move-server.sh root@unraid:/mnt/user/appdata/codecraft \
|
||
--workspace /mnt/user/projects --tools-dir /mnt/disks/ssd/codecraft \
|
||
--uid 99 --gid 100 --bind 0.0.0.0 --docker-sock --dry-run
|
||
|
||
# 2. Move (same command without --dry-run)
|
||
scripts/move-server.sh root@unraid:/mnt/user/appdata/codecraft \
|
||
--workspace /mnt/user/projects --tools-dir /mnt/disks/ssd/codecraft \
|
||
--uid 99 --gid 100 --bind 0.0.0.0 --docker-sock
|
||
```
|
||
|
||
What happens:
|
||
|
||
1. **Checks**: docker/tar/rsync on the target; the target data folder (and `home/`, `users/` in
|
||
the tools folder) must be empty – the script never overwrites.
|
||
2. **Workspace, first pass** with rsync while CodeCraft keeps running (the long part).
|
||
3. **Stops CodeCraft here.** Running agents and terminals end. The container is only stopped,
|
||
not removed.
|
||
4. **Data volume** is streamed with tar over SSH into `<dir>/data`; with `--tools-dir` the agent
|
||
home and the users' homes are then moved to the tools folder.
|
||
5. **Workspace, second pass**: only what changed since step 2.
|
||
6. **Owner** of data, tools and workspace set to `--uid:--gid` (needs root on the target).
|
||
7. **Writes** `<dir>/docker-compose.yml`, `<dir>/.env` (your `.env` with the new paths, port and
|
||
owner), `<dir>/start.sh` (the same as `docker run`, for hosts without Compose) and
|
||
`<dir>/docker/seccomp-sandbox.json`.
|
||
8. **Starts** the image `CODECRAFT_VERSION` from `.env` (Compose, else `start.sh`).
|
||
9. **Smoke test** on the target (`scripts/smoke-test.sh`): health, version, web UI, terminal
|
||
client download.
|
||
|
||
Afterwards:
|
||
|
||
- **Reverse proxy**: point the proxy host for `code.familie-zink.org` (Nginx Proxy Manager) to the
|
||
new host and port; keep WebSocket support on.
|
||
- **Check in the web UI**: sign in, open a chat, check the status LEDs (providers, MCP servers),
|
||
let an agent run `git status` in a project (credentials, identity), open a terminal tab.
|
||
Models or MCP servers on the old host's LAN address or `localhost` need new addresses.
|
||
- **Clean up** on the old host when everything works: `docker rm codecraft`, later
|
||
`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 contains the Docker CLI (static client); the daemon is the host's.
|
||
|
||
The current host has the same setup in its local `docker-compose.override.yml` (group 997).
|
||
|
||
## Rollback
|
||
|
||
Nothing is deleted on the old host. On Unraid stop the new container (`docker stop codecraft`),
|
||
on the old host start the old one (`docker start codecraft`) and point the reverse proxy back.
|
||
Changes made on the new host in the meantime (chats, settings) are not in the old installation.
|
||
|
||
## Running it on the new host
|
||
|
||
In `<dir>` on Unraid:
|
||
|
||
| Task | With Compose | Without Compose |
|
||
|---|---|---|
|
||
| Update | set `CODECRAFT_VERSION` in `.env`, then `docker compose pull && docker compose up -d` | set `CODECRAFT_VERSION` in `.env`, `docker pull …:<version>`, then `./start.sh` |
|
||
| Restart | `docker compose restart` | `docker restart codecraft` |
|
||
| Logs | `docker compose logs -f` | `docker logs -f codecraft` |
|
||
| Check | `bash smoke-test.sh http://127.0.0.1:8787 <version>` | same |
|
||
|
||
Releases are published from the development machine with `scripts/release.sh`; the new host
|
||
only pulls them.
|
||
|
||
## Troubleshooting
|
||
|
||
- **`data on the target is not empty`**: an earlier attempt left files. Move `<dir>/data` (and
|
||
`home/`, `users/` in the tools folder) away and run the script again.
|
||
- **Image pull refused**: `docker login git.familie-zink.org` on the target, then
|
||
`cd <dir> && docker compose up -d` (or `./start.sh`).
|
||
- **Smoke test fails**: `docker logs codecraft` on the target. The old installation is stopped but
|
||
intact – `docker start codecraft` on the old host brings it back.
|
||
- **`could not chown`**: the SSH user is not root; set the owner by hand
|
||
(`chown -R 99:100 <dir>/data <tools-dir> <workspace>`).
|
||
- **Permission denied inside the container**: data, tools and workspace must belong to the
|
||
`UID`/`GID` in `<dir>/.env`.
|
||
- **Port already in use**: change `PORT` in `<dir>/.env` and start again.
|