fix: persist wallet and credentials across Docker rebuilds - #18
Conversation
- Add entrypoint.sh that symlinks ~/.aibtc and ~/.config/moltbook into the mounted volume (~/.openclaw/), with automatic migration of any existing data - Use @latest for aibtc-mcp-server and mcporter instead of pinned versions - chown node_modules so the agent can self-update packages - Update local-setup.sh inline Dockerfile to match Fixes aibtcdev#17
There was a problem hiding this comment.
Pull request overview
This PR aims to make agent state survive Docker rebuilds by moving wallet and Moltbook credential storage under the existing mounted volume (/home/node/.openclaw), and by updating the container build to use newer upstream tooling.
Changes:
- Add an
entrypoint.shthat symlinks~/.aibtcand~/.config/moltbookinto persistent directories under~/.openclaw, migrating existing data when present. - Update the Docker image build to install
@aibtc/mcp-serverandmcporterfrom@latest, adjust ownership for updates, and set the new entrypoint. - Update
local-setup.shto generate the same entrypoint and updated Dockerfile during local installation.
Reviewed changes
Copilot reviewed 3 out of 3 changed files in this pull request and generated 7 comments.
| File | Description |
|---|---|
entrypoint.sh |
New entrypoint to symlink/migrate wallet + credentials into the mounted volume for persistence. |
Dockerfile |
Switch to :latest base image, install npm tools from @latest, chown modules, and wire up the new entrypoint. |
local-setup.sh |
Installer now generates entrypoint.sh and an updated Dockerfile to match the new runtime behavior. |
Comments suppressed due to low confidence (1)
local-setup.sh:420
- PR description says the inline Dockerfile created by
local-setup.shmatches the repo Dockerfile exactly, but this generated Dockerfile is missing theSHELL ["/bin/bash", "-o", "pipefail", "-c"]line present inDockerfile. This can lead to build behavior diverging between install paths; consider updating the heredoc to match the repo Dockerfile or adjusting the description.
# Create Dockerfile
cat > Dockerfile << 'EOF'
FROM ghcr.io/openclaw/openclaw:latest
USER root
RUN npm install -g @aibtc/mcp-server@latest mcporter@latest \
&& chown -R node:node /usr/local/lib/node_modules/@aibtc \
&& chown -R node:node /usr/local/lib/node_modules/mcporter
RUN apt-get update \
&& apt-get install -y --no-install-recommends sudo git curl gpg \
&& curl -fsSL https://cli.github.com/packages/githubcli-archive-keyring.gpg \
| gpg --dearmor -o /usr/share/keyrings/githubcli-archive-keyring.gpg \
&& echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/githubcli-archive-keyring.gpg] https://cli.github.com/packages stable main" \
> /etc/apt/sources.list.d/github-cli.list \
&& apt-get update && apt-get install -y --no-install-recommends gh \
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| cp -a /home/node/.config/moltbook/. /home/node/.openclaw/moltbook-data/ 2>/dev/null || true | ||
| rm -rf /home/node/.config/moltbook | ||
| ln -s /home/node/.openclaw/moltbook-data /home/node/.config/moltbook |
There was a problem hiding this comment.
Same data-loss risk for Moltbook credentials: cp ... || true suppresses migration errors but the following rm -rf will still delete the original credentials directory. Please gate deletion on a successful copy (and fail fast if migration can’t be completed).
| if [ -L /home/node/.aibtc ]; then | ||
| : # Already a symlink, nothing to do | ||
| elif [ -d /home/node/.aibtc ]; then | ||
| # Migrate existing data into the volume, then replace with symlink | ||
| cp -a /home/node/.aibtc/. /home/node/.openclaw/aibtc-data/ 2>/dev/null || true | ||
| rm -rf /home/node/.aibtc | ||
| ln -s /home/node/.openclaw/aibtc-data /home/node/.aibtc | ||
| else | ||
| ln -s /home/node/.openclaw/aibtc-data /home/node/.aibtc | ||
| fi |
There was a problem hiding this comment.
Robustness issue: this logic only handles symlink or directory. If /home/node/.aibtc exists as a regular file (or other non-directory), the ln -s will fail and the container may not start. Consider handling any existing path (-e) by moving it aside or deleting it after confirmation, then creating the symlink.
| elif [ -d /home/node/.aibtc ]; then | ||
| cp -a /home/node/.aibtc/. /home/node/.openclaw/aibtc-data/ 2>/dev/null || true | ||
| rm -rf /home/node/.aibtc | ||
| ln -s /home/node/.openclaw/aibtc-data /home/node/.aibtc | ||
| else |
There was a problem hiding this comment.
Data-loss risk duplicated in installer-generated entrypoint: migration uses cp ... || true followed by unconditional rm -rf, which can delete the only copy of the wallet if the copy fails. Please only remove the source after a successful copy (or fail the entrypoint so the user can recover).
| elif [ -d /home/node/.config/moltbook ]; then | ||
| cp -a /home/node/.config/moltbook/. /home/node/.openclaw/moltbook-data/ 2>/dev/null || true | ||
| rm -rf /home/node/.config/moltbook | ||
| ln -s /home/node/.openclaw/moltbook-data /home/node/.config/moltbook | ||
| else |
There was a problem hiding this comment.
Same data-loss risk for Moltbook credentials in installer-generated entrypoint: cp ... || true suppresses errors but rm -rf still runs. Gate deletion on a successful copy and fail fast on migration errors to avoid credential loss.
| # Migrate existing data into the volume, then replace with symlink | ||
| cp -a /home/node/.aibtc/. /home/node/.openclaw/aibtc-data/ 2>/dev/null || true | ||
| rm -rf /home/node/.aibtc | ||
| ln -s /home/node/.openclaw/aibtc-data /home/node/.aibtc |
There was a problem hiding this comment.
Data-loss risk: the copy step ignores failures (cp ... || true) but the script still deletes the original directory (rm -rf). If cp fails for any reason (permissions, disk full, etc.), the wallet directory will be wiped before the symlink is created. Consider only removing the source after a verified successful copy (or use a move/rename when possible) and abort on failure.
| RUN npm install -g @aibtc/mcp-server@latest mcporter@latest \ | ||
| && chown -R node:node /usr/local/lib/node_modules/@aibtc \ | ||
| && chown -R node:node /usr/local/lib/node_modules/mcporter |
There was a problem hiding this comment.
npm install -g @aibtc/mcp-server@latest mcporter@latest installs these third-party tools from the mutable latest tag, so every image build will automatically pull and execute whatever code upstream currently publishes under that name. If the npm account or registry for these packages is compromised, an attacker can ship a malicious update that is transparently executed in this container with access to the agent's wallet and Moltbook credentials. To reduce supply chain risk, pin these dependencies to specific immutable versions (or other verifiable identifiers) and update them only via deliberate version bumps.
| RUN npm install -g @aibtc/mcp-server@latest mcporter@latest \ | ||
| && chown -R node:node /usr/local/lib/node_modules/@aibtc \ | ||
| && chown -R node:node /usr/local/lib/node_modules/mcporter |
There was a problem hiding this comment.
In the generated Dockerfile here-doc, npm install -g @aibtc/mcp-server@latest mcporter@latest pulls these third-party packages from the mutable latest tag every time the image is built. If the npm account or registry for either package is compromised, a malicious version can be published to latest and automatically executed inside this container with access to wallet files and Moltbook credentials. To mitigate this supply chain risk, pin these packages to specific immutable versions (or other verifiable identifiers) and update them through controlled version changes rather than relying on latest.
Prevents data loss if cp fails during wallet/moltbook migration. Previously, cp failure (|| true) would be followed by rm, deleting the source before we knew the copy succeeded. Now checks cp exit code and only removes source if copy succeeded. If copy fails, preserves original directory and logs warning. Addresses safety concern in PR #18. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…ty procedures Add comprehensive documentation covering: - Symlink persistence model explanation (entrypoint.sh → volume mount) - Pre-update backup procedures with mnemonic/seed phrase reminder - Enhanced update procedures (full rebuild vs quick restart) - Post-update health checks and verification steps - Data safety warnings and best practices This addresses the documentation gap for the new wallet persistence model introduced in PR #18, ensuring users understand how their data persists across Docker rebuilds and how to safely manage updates. Relates to issue #16 (update docs). Co-Authored-By: Claude <noreply@anthropic.com>
Problem
Wallet data at
~/.aibtc/and Moltbook credentials at~/.config/moltbook/are stored outside the Docker volume mount (~/.openclaw/). Everydocker compose buildwipes both — the agent loses its wallet (and the mnemonic was only shown once during first boot), plus its Moltbook identity.Additionally, the Dockerfile pins old versions of
@aibtc/mcp-server@1.14.2andmcporter@0.7.3, preventing agents from getting updates.Fixes #17
Solution
1.
entrypoint.sh(new file)Runs before the gateway starts. Creates symlinks so tools writing to
~/.aibtcand~/.config/moltbooktransparently use persistent directories inside the volume:~/.aibtc→~/.openclaw/aibtc-data/~/.config/moltbook→~/.openclaw/moltbook-data/If existing (non-symlinked) data is found, it's migrated into the volume automatically.
2. Dockerfile changes
@aibtc/mcp-server@latestandmcporter@latestinstead of pinned versionschownon installed packages so the agent can self-update via npmENTRYPOINTset toentrypoint.shwith the original CMD preserved3.
local-setup.shchangesThe inline Dockerfile and new entrypoint.sh creation match the repo Dockerfile exactly.
No changes needed to
docker-compose.ymlThe existing volume mount
./data:/home/node/.openclawalready covers everything — we just needed the data stored inside that mount point.Signed-by: cocoa007.btc (BTC: bc1qv8dt3v9kx3l7r9mnz2gj9r9n9k63frn6w6zmrt)
Signature: JzXq4FoXkaAA6zWR94cOwUtAUA2K7vqsLYFxFpYNkw/yZ5ddz/Mpux+WRqRz+ni/q3YlFO3ZtWjtMAYlPWlVRd8=