From 709c225b2bc946f3ad25c08611a6386456a14372 Mon Sep 17 00:00:00 2001 From: Peter Steinberger Date: Sat, 14 Feb 2026 18:03:06 +0100 Subject: [PATCH] fix(podman): bootstrap config and token --- docs/install/podman.md | 5 ++- scripts/run-openclaw-podman.sh | 34 +++++++++++++++---- setup-podman.sh | 61 ++++++++++++++++++++++++++-------- 3 files changed, 79 insertions(+), 21 deletions(-) diff --git a/docs/install/podman.md b/docs/install/podman.md index 2bf8b61ac23..3b56c9ce25e 100644 --- a/docs/install/podman.md +++ b/docs/install/podman.md @@ -22,6 +22,8 @@ Run the OpenClaw gateway in a **rootless** Podman container. Uses the same image ./setup-podman.sh ``` +This also creates a minimal `~openclaw/.openclaw/openclaw.json` (sets `gateway.mode="local"`) so the gateway can start without running the wizard. + By default the container is **not** installed as a systemd service, you start it manually (see below). For a production-style setup with auto-start and restarts, install it as a systemd Quadlet user service instead: ```bash @@ -80,7 +82,7 @@ To add quadlet **after** an initial setup that did not use it, re-run: `./setup- ## Environment and config -- **Token:** Stored in `~openclaw/.openclaw/.env` as `OPENCLAW_GATEWAY_TOKEN`. Generate with: `openssl rand -hex 32`. +- **Token:** Stored in `~openclaw/.openclaw/.env` as `OPENCLAW_GATEWAY_TOKEN`. `setup-podman.sh` and `run-openclaw-podman.sh` generate it if missing (uses `openssl`, `python3`, or `od`). - **Optional:** In that `.env` you can set provider keys (e.g. `GROQ_API_KEY`, `OLLAMA_API_KEY`) and other OpenClaw env vars. - **Host ports:** By default the script maps `18789` (gateway) and `18790` (bridge). Override the **host** port mapping with `OPENCLAW_PODMAN_GATEWAY_HOST_PORT` and `OPENCLAW_PODMAN_BRIDGE_HOST_PORT` when launching. - **Paths:** Host config and workspace default to `~openclaw/.openclaw` and `~openclaw/.openclaw/workspace`. Override the host paths used by the launch script with `OPENCLAW_CONFIG_DIR` and `OPENCLAW_WORKSPACE_DIR`. @@ -95,6 +97,7 @@ To add quadlet **after** an initial setup that did not use it, re-run: `./setup- ## Troubleshooting - **Permission denied (EACCES) on config or auth-profiles:** The container defaults to `--userns=keep-id` and runs as the same uid/gid as the host user running the script. Ensure your host `OPENCLAW_CONFIG_DIR` and `OPENCLAW_WORKSPACE_DIR` are owned by that user. +- **Gateway start blocked (missing `gateway.mode=local`):** Ensure `~openclaw/.openclaw/openclaw.json` exists and sets `gateway.mode="local"`. `setup-podman.sh` creates this file if missing. - **Rootless Podman fails for user openclaw:** Check `/etc/subuid` and `/etc/subgid` contain a line for `openclaw` (e.g. `openclaw:100000:65536`). Add it if missing and restart. - **Container name in use:** The launch script uses `podman run --replace`, so the existing container is replaced when you start again. To clean up manually: `podman rm -f openclaw`. - **Script not found when running as openclaw:** Ensure `setup-podman.sh` was run so that `run-openclaw-podman.sh` is copied to openclaw’s home (e.g. `/home/openclaw/run-openclaw-podman.sh`). diff --git a/scripts/run-openclaw-podman.sh b/scripts/run-openclaw-podman.sh index fd7bd684fb6..2be9d0a5304 100755 --- a/scripts/run-openclaw-podman.sh +++ b/scripts/run-openclaw-podman.sh @@ -89,6 +89,7 @@ fi mkdir -p "$CONFIG_DIR" "$WORKSPACE_DIR" # Subdirs the app may create at runtime (canvas, cron); create here so ownership is correct mkdir -p "$CONFIG_DIR/canvas" "$CONFIG_DIR/cron" +chmod 700 "$CONFIG_DIR" "$WORKSPACE_DIR" 2>/dev/null || true if [[ -f "$ENV_FILE" ]]; then set -a @@ -117,21 +118,42 @@ upsert_env_var() { chmod 600 "$file" 2>/dev/null || true } -if [[ -z "${OPENCLAW_GATEWAY_TOKEN:-}" ]]; then - if command -v openssl &>/dev/null; then - export OPENCLAW_GATEWAY_TOKEN="$(openssl rand -hex 32)" - else - export OPENCLAW_GATEWAY_TOKEN="$(python3 - <<'PY' +generate_token_hex_32() { + if command -v openssl >/dev/null 2>&1; then + openssl rand -hex 32 + return 0 + fi + if command -v python3 >/dev/null 2>&1; then + python3 - <<'PY' import secrets print(secrets.token_hex(32)) PY -)" + return 0 fi + if command -v od >/dev/null 2>&1; then + od -An -N32 -tx1 /dev/urandom | tr -d " \n" + return 0 + fi + echo "Missing dependency: need openssl or python3 (or od) to generate OPENCLAW_GATEWAY_TOKEN." >&2 + exit 1 +} + +if [[ -z "${OPENCLAW_GATEWAY_TOKEN:-}" ]]; then + export OPENCLAW_GATEWAY_TOKEN="$(generate_token_hex_32)" mkdir -p "$(dirname "$ENV_FILE")" upsert_env_var "$ENV_FILE" "OPENCLAW_GATEWAY_TOKEN" "$OPENCLAW_GATEWAY_TOKEN" echo "Generated OPENCLAW_GATEWAY_TOKEN and wrote it to $ENV_FILE." >&2 fi +# The gateway refuses to start unless gateway.mode=local is set in config. +# Keep this minimal; users can run the wizard later to configure channels/providers. +CONFIG_JSON="$CONFIG_DIR/openclaw.json" +if [[ ! -f "$CONFIG_JSON" ]]; then + echo '{ gateway: { mode: "local" } }' >"$CONFIG_JSON" + chmod 600 "$CONFIG_JSON" 2>/dev/null || true + echo "Created $CONFIG_JSON (minimal gateway.mode=local)." >&2 +fi + PODMAN_USERNS="${OPENCLAW_PODMAN_USERNS:-keep-id}" USERNS_ARGS=() RUN_USER_ARGS=() diff --git a/setup-podman.sh b/setup-podman.sh index fb8c3909a05..06efe2a752a 100755 --- a/setup-podman.sh +++ b/setup-podman.sh @@ -78,6 +78,27 @@ if [[ ! -f "$RUN_SCRIPT_SRC" ]]; then exit 1 fi +generate_token_hex_32() { + if command -v openssl >/dev/null 2>&1; then + openssl rand -hex 32 + return 0 + fi + if command -v python3 >/dev/null 2>&1; then + python3 - <<'PY' +import secrets +print(secrets.token_hex(32)) +PY + return 0 + fi + if command -v od >/dev/null 2>&1; then + # 32 random bytes -> 64 lowercase hex chars + od -An -N32 -tx1 /dev/urandom | tr -d " \n" + return 0 + fi + echo "Missing dependency: need openssl or python3 (or od) to generate OPENCLAW_GATEWAY_TOKEN." >&2 + exit 1 +} + user_exists() { local user="$1" if command -v getent >/dev/null 2>&1; then @@ -138,7 +159,7 @@ LAUNCH_SCRIPT_DST="$OPENCLAW_HOME/run-openclaw-podman.sh" if command -v loginctl &>/dev/null; then run_root loginctl enable-linger "$OPENCLAW_USER" 2>/dev/null || true fi -if [[ -n "${OPENCLAW_UID:-}" && -d /run/user && command -v systemctl &>/dev/null ]]; then +if [[ -n "${OPENCLAW_UID:-}" && -d /run/user ]] && command -v systemctl &>/dev/null; then run_root systemctl start "user@${OPENCLAW_UID}.service" 2>/dev/null || true fi @@ -151,21 +172,33 @@ fi echo "Creating $OPENCLAW_CONFIG and workspace..." run_root mkdir -p "$OPENCLAW_CONFIG/workspace" run_root chown -R "$OPENCLAW_USER:" "$OPENCLAW_CONFIG" +run_root chmod 700 "$OPENCLAW_CONFIG" "$OPENCLAW_CONFIG/workspace" 2>/dev/null || true -if [[ ! -f "$OPENCLAW_CONFIG/.env" ]]; then - if command -v openssl >/dev/null 2>&1; then - TOKEN="$(openssl rand -hex 32)" - else - TOKEN="$(python3 - <<'PY' -import secrets -print(secrets.token_hex(32)) -PY -)" +ENV_FILE="$OPENCLAW_CONFIG/.env" +if [[ -f "$ENV_FILE" ]]; then + if ! grep -q '^OPENCLAW_GATEWAY_TOKEN=' "$ENV_FILE" 2>/dev/null; then + TOKEN="$(generate_token_hex_32)" + echo "OPENCLAW_GATEWAY_TOKEN=$TOKEN" | run_root tee -a "$ENV_FILE" >/dev/null + echo "Added OPENCLAW_GATEWAY_TOKEN to $ENV_FILE." fi - echo "OPENCLAW_GATEWAY_TOKEN=$TOKEN" | run_root tee "$OPENCLAW_CONFIG/.env" >/dev/null - run_root chown "$OPENCLAW_USER:" "$OPENCLAW_CONFIG/.env" - run_root chmod 600 "$OPENCLAW_CONFIG/.env" 2>/dev/null || true - echo "Created $OPENCLAW_CONFIG/.env with new token." + run_root chown "$OPENCLAW_USER:" "$ENV_FILE" + run_root chmod 600 "$ENV_FILE" 2>/dev/null || true +else + TOKEN="$(generate_token_hex_32)" + echo "OPENCLAW_GATEWAY_TOKEN=$TOKEN" | run_root tee "$ENV_FILE" >/dev/null + run_root chown "$OPENCLAW_USER:" "$ENV_FILE" + run_root chmod 600 "$ENV_FILE" 2>/dev/null || true + echo "Created $ENV_FILE with new token." +fi + +# The gateway refuses to start unless gateway.mode=local is set in config. +# Make first-run non-interactive; users can run the wizard later to configure channels/providers. +OPENCLAW_JSON="$OPENCLAW_CONFIG/openclaw.json" +if [[ ! -f "$OPENCLAW_JSON" ]]; then + echo '{ gateway: { mode: "local" } }' | run_root tee "$OPENCLAW_JSON" >/dev/null + run_root chown "$OPENCLAW_USER:" "$OPENCLAW_JSON" + run_root chmod 600 "$OPENCLAW_JSON" 2>/dev/null || true + echo "Created $OPENCLAW_JSON (minimal gateway.mode=local)." fi echo "Building image from $REPO_PATH..."