{"id":619,"date":"2026-03-21T22:52:57","date_gmt":"2026-03-21T14:52:57","guid":{"rendered":"https:\/\/pa.yingzhi8.cn\/index.php\/2026\/03\/21\/install-podman\/"},"modified":"2026-03-21T23:23:48","modified_gmt":"2026-03-21T15:23:48","slug":"install-podman","status":"publish","type":"post","link":"https:\/\/pa.yingzhi8.cn\/index.php\/2026\/03\/21\/install-podman\/","title":{"rendered":"Podman"},"content":{"rendered":"<h1>Podman<\/h1>\n<p>Run the OpenClaw Gateway in a <strong>rootless<\/strong> Podman container. Uses the same image as Docker (built from the repo <a href=\"https:\/\/github.com\/openclaw\/openclaw\/blob\/main\/Dockerfile\">Dockerfile<\/a>).<\/p>\n<h2>Prerequisites<\/h2>\n<ul>\n<li><strong>Podman<\/strong> (rootless mode)<\/li>\n<li><strong>sudo<\/strong> access for one-time setup (creating the dedicated user and building the image)<\/li>\n<\/ul>\n<h2>&#24555;&#36895;&#24320;&#22987;<\/h2>\n<p>    From the repo root, run the setup script. It creates a dedicated <code>openclaw<\/code> user, builds the container image, and installs the launch script:<\/p>\n<pre><code>```bash  theme={\"theme\":{\"light\":\"min-light\",\"dark\":\"min-dark\"}}\n.\/scripts\/podman\/setup.sh\n```\n\nThis also creates a minimal config at `~openclaw\/.openclaw\/openclaw.json` (sets `gateway.mode` to `\"local\"`) so the Gateway can start without running the wizard.\n\nBy default the container is **not** installed as a systemd service -- you start it manually in the next step. For a production-style setup with auto-start and restarts, pass `--quadlet` instead:\n\n```bash  theme={\"theme\":{\"light\":\"min-light\",\"dark\":\"min-dark\"}}\n.\/scripts\/podman\/setup.sh --quadlet\n```\n\n(Or set `OPENCLAW_PODMAN_QUADLET=1`. Use `--container` to install only the container and launch script.)\n\n**Optional build-time env vars** (set before running `scripts\/podman\/setup.sh`):\n\n* `OPENCLAW_DOCKER_APT_PACKAGES` -- install extra apt packages during image build.\n* `OPENCLAW_EXTENSIONS` -- pre-install extension dependencies (space-separated names, e.g. `diagnostics-otel matrix`).\n<\/code><\/pre>\n<\/p>\n<p>\n    For a quick manual launch:<\/p>\n<pre><code>```bash  theme={\"theme\":{\"light\":\"min-light\",\"dark\":\"min-dark\"}}\n.\/scripts\/run-openclaw-podman.sh launch\n```\n<\/code><\/pre>\n<\/p>\n<p>\n    To add channels or providers interactively:<\/p>\n<pre><code>```bash  theme={\"theme\":{\"light\":\"min-light\",\"dark\":\"min-dark\"}}\n.\/scripts\/run-openclaw-podman.sh launch setup\n```\n\nThen open `http:\/\/127.0.0.1:18789\/` and use the token from `~openclaw\/.openclaw\/.env` (or the value printed by setup).\n<\/code><\/pre>\n<\/p>\n<h2>Systemd (Quadlet, optional)<\/h2>\n<p>If you ran <code>.\/scripts\/podman\/setup.sh --quadlet<\/code> (or <code>OPENCLAW_PODMAN_QUADLET=1<\/code>), a <a href=\"https:\/\/docs.podman.io\/en\/latest\/markdown\/podman-systemd.unit.5.html\">Podman Quadlet<\/a> unit is installed so the gateway runs as a systemd user service for the openclaw user. The service is enabled and started at the end of setup.<\/p>\n<ul>\n<li><strong>Start:<\/strong> <code>sudo systemctl --machine openclaw@ --user start openclaw.service<\/code><\/li>\n<li><strong>Stop:<\/strong> <code>sudo systemctl --machine openclaw@ --user stop openclaw.service<\/code><\/li>\n<li><strong>Status:<\/strong> <code>sudo systemctl --machine openclaw@ --user status openclaw.service<\/code><\/li>\n<li><strong>Logs:<\/strong> <code>sudo journalctl --machine openclaw@ --user -u openclaw.service -f<\/code><\/li>\n<\/ul>\n<p>The quadlet file lives at <code>~openclaw\/.config\/containers\/systemd\/openclaw.container<\/code>. To change ports or env, edit that file (or the <code>.env<\/code> it sources), then <code>sudo systemctl --machine openclaw@ --user daemon-reload<\/code> and restart the service. On boot, the service starts automatically if lingering is enabled for openclaw (setup does this when loginctl is available).<\/p>\n<p>To add quadlet <strong>after<\/strong> an initial setup that did not use it, re-run: <code>.\/scripts\/podman\/setup.sh --quadlet<\/code>.<\/p>\n<h2>The openclaw user (non-login)<\/h2>\n<p><code>scripts\/podman\/setup.sh<\/code> creates a dedicated system user <code>openclaw<\/code>:<\/p>\n<ul>\n<li>\n<p><strong>Shell:<\/strong> <code>nologin<\/code> &mdash; no interactive login; reduces attack surface.<\/p>\n<\/li>\n<li>\n<p><strong>Home:<\/strong> e.g. <code>\/home\/openclaw<\/code> &mdash; holds <code>~\/.openclaw<\/code> (config, workspace) and the launch script <code>run-openclaw-podman.sh<\/code>.<\/p>\n<\/li>\n<li>\n<p><strong>Rootless Podman:<\/strong> The user must have a <strong>subuid<\/strong> and <strong>subgid<\/strong> range. Many distros assign these automatically when the user is created. If setup prints a warning, add lines to <code>\/etc\/subuid<\/code> and <code>\/etc\/subgid<\/code>:<\/p>\n<\/li>\n<\/ul>\n<p><code>text  theme={\"theme\":{\"light\":\"min-light\",\"dark\":\"min-dark\"}}<br \/>\n  openclaw:100000:65536<\/code><\/p>\n<p>Then start the gateway as that user (e.g. from cron or systemd):<\/p>\n<p><code>bash  theme={\"theme\":{\"light\":\"min-light\",\"dark\":\"min-dark\"}}<br \/>\n  sudo -u openclaw \/home\/openclaw\/run-openclaw-podman.sh<br \/>\n  sudo -u openclaw \/home\/openclaw\/run-openclaw-podman.sh setup<\/code><\/p>\n<ul>\n<li><strong>Config:<\/strong> Only <code>openclaw<\/code> and root can access <code>\/home\/openclaw\/.openclaw<\/code>. To edit config: use the Control UI once the gateway is running, or <code>sudo -u openclaw $EDITOR \/home\/openclaw\/.openclaw\/openclaw.json<\/code>.<\/li>\n<\/ul>\n<h2>Environment and config<\/h2>\n<ul>\n<li><strong>Token:<\/strong> Stored in <code>~openclaw\/.openclaw\/.env<\/code> as <code>OPENCLAW_GATEWAY_TOKEN<\/code>. <code>scripts\/podman\/setup.sh<\/code> and <code>run-openclaw-podman.sh<\/code> generate it if missing (uses <code>openssl<\/code>, <code>python3<\/code>, or <code>od<\/code>).<\/li>\n<li><strong>&#21487;&#36873;&#39033;:<\/strong> In that <code>.env<\/code> you can set provider keys (e.g. <code>GROQ_API_KEY<\/code>, <code>OLLAMA_API_KEY<\/code>) and other OpenClaw env vars.<\/li>\n<li><strong>Host ports:<\/strong> By default the script maps <code>18789<\/code> (gateway) and <code>18790<\/code> (bridge). Override the <strong>host<\/strong> port mapping with <code>OPENCLAW_PODMAN_GATEWAY_HOST_PORT<\/code> and <code>OPENCLAW_PODMAN_BRIDGE_HOST_PORT<\/code> when launching.<\/li>\n<li><strong>Gateway bind:<\/strong> By default, <code>run-openclaw-podman.sh<\/code> starts the gateway with <code>--bind loopback<\/code> for safe local access. To expose on LAN, set <code>OPENCLAW_GATEWAY_BIND=lan<\/code> and configure <code>gateway.controlUi.allowedOrigins<\/code> (or explicitly enable host-header fallback) in <code>openclaw.json<\/code>.<\/li>\n<li><strong>Paths:<\/strong> Host config and workspace default to <code>~openclaw\/.openclaw<\/code> and <code>~openclaw\/.openclaw\/workspace<\/code>. Override the host paths used by the launch script with <code>OPENCLAW_CONFIG_DIR<\/code> and <code>OPENCLAW_WORKSPACE_DIR<\/code>.<\/li>\n<\/ul>\n<h2>Storage model<\/h2>\n<ul>\n<li><strong>Persistent host data:<\/strong> <code>OPENCLAW_CONFIG_DIR<\/code> and <code>OPENCLAW_WORKSPACE_DIR<\/code> are bind-mounted into the container and retain state on the host.<\/li>\n<li><strong>Ephemeral sandbox tmpfs:<\/strong> if you enable <code>agents.defaults.sandbox<\/code>, the tool sandbox containers mount <code>tmpfs<\/code> at <code>\/tmp<\/code>, <code>\/var\/tmp<\/code>, and <code>\/run<\/code>. Those paths are memory-backed and disappear with the sandbox container; the top-level Podman container setup does not add its own tmpfs mounts.<\/li>\n<li><strong>Disk growth hotspots:<\/strong> the main paths to watch are <code>media\/<\/code>, <code>agents\/&lt;agentId&gt;\/sessions\/sessions.json<\/code>, transcript JSONL files, <code>cron\/runs\/*.jsonl<\/code>, and rolling file logs under <code>\/tmp\/openclaw\/<\/code> (or your configured <code>logging.file<\/code>).<\/li>\n<\/ul>\n<p><code>scripts\/podman\/setup.sh<\/code> now stages the image tar in a private temp directory and prints the chosen base dir during setup. For non-root runs it accepts <code>TMPDIR<\/code> only when that base is safe to use; otherwise it falls back to <code>\/var\/tmp<\/code>, then <code>\/tmp<\/code>. The saved tar stays owner-only and is streamed into the target user&rsquo;s <code>podman load<\/code>, so private caller temp dirs do not block setup.<\/p>\n<h2>Useful commands<\/h2>\n<ul>\n<li><strong>Logs:<\/strong> With quadlet: <code>sudo journalctl --machine openclaw@ --user -u openclaw.service -f<\/code>. With script: <code>sudo -u openclaw podman logs -f openclaw<\/code><\/li>\n<li><strong>Stop:<\/strong> With quadlet: <code>sudo systemctl --machine openclaw@ --user stop openclaw.service<\/code>. With script: <code>sudo -u openclaw podman stop openclaw<\/code><\/li>\n<li><strong>Start again:<\/strong> With quadlet: <code>sudo systemctl --machine openclaw@ --user start openclaw.service<\/code>. With script: re-run the launch script or <code>podman start openclaw<\/code><\/li>\n<li><strong>Remove container:<\/strong> <code>sudo -u openclaw podman rm -f openclaw<\/code> &mdash; config and workspace on the host are kept<\/li>\n<\/ul>\n<h2>&#25925;&#38556;&#25490;&#26597;<\/h2>\n<ul>\n<li><strong>Permission denied (EACCES) on config or auth-profiles:<\/strong> The container defaults to <code>--userns=keep-id<\/code> and runs as the same uid\/gid as the host user running the script. Ensure your host <code>OPENCLAW_CONFIG_DIR<\/code> and <code>OPENCLAW_WORKSPACE_DIR<\/code> are owned by that user.<\/li>\n<li><strong>Gateway start blocked (missing <code>gateway.mode=local<\/code>):<\/strong> Ensure <code>~openclaw\/.openclaw\/openclaw.json<\/code> exists and sets <code>gateway.mode=\"local\"<\/code>. <code>scripts\/podman\/setup.sh<\/code> creates this file if missing.<\/li>\n<li><strong>Rootless Podman fails for user openclaw:<\/strong> Check <code>\/etc\/subuid<\/code> and <code>\/etc\/subgid<\/code> contain a line for <code>openclaw<\/code> (e.g. <code>openclaw:100000:65536<\/code>). Add it if missing and restart.<\/li>\n<li><strong>Container name in use:<\/strong> The launch script uses <code>podman run --replace<\/code>, so the existing container is replaced when you start again. To clean up manually: <code>podman rm -f openclaw<\/code>.<\/li>\n<li><strong>Script not found when running as openclaw:<\/strong> Ensure <code>scripts\/podman\/setup.sh<\/code> was run so that <code>run-openclaw-podman.sh<\/code> is copied to openclaw&rsquo;s home (e.g. <code>\/home\/openclaw\/run-openclaw-podman.sh<\/code>).<\/li>\n<li><strong>Quadlet service not found or fails to start:<\/strong> Run <code>sudo systemctl --machine openclaw@ --user daemon-reload<\/code> after editing the <code>.container<\/code> file. Quadlet requires cgroups v2: <code>podman info --format '{{.Host.CgroupsVersion}}'<\/code> should show <code>2<\/code>.<\/li>\n<\/ul>\n<h2>&#21487;&#36873;&#39033;: run as your own user<\/h2>\n<p>To run the gateway as your normal user (no dedicated openclaw user): build the image, create <code>~\/.openclaw\/.env<\/code> with <code>OPENCLAW_GATEWAY_TOKEN<\/code>, and run the container with <code>--userns=keep-id<\/code> and mounts to your <code>~\/.openclaw<\/code>. The launch script is designed for the openclaw-user flow; for a single-user setup you can instead run the <code>podman run<\/code> command from the script manually, pointing config and workspace to your home. &#25512;&#33616; for most users: use <code>scripts\/podman\/setup.sh<\/code> and run as the openclaw user so config and process are isolated.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Podman Run the OpenClaw Gateway in a rootless Podman co [&hellip;]<\/p>\n","protected":false},"author":0,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[2],"tags":[],"class_list":["post-619","post","type-post","status-publish","format-standard","hentry","category-docs"],"_links":{"self":[{"href":"https:\/\/pa.yingzhi8.cn\/index.php\/wp-json\/wp\/v2\/posts\/619","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/pa.yingzhi8.cn\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/pa.yingzhi8.cn\/index.php\/wp-json\/wp\/v2\/types\/post"}],"replies":[{"embeddable":true,"href":"https:\/\/pa.yingzhi8.cn\/index.php\/wp-json\/wp\/v2\/comments?post=619"}],"version-history":[{"count":3,"href":"https:\/\/pa.yingzhi8.cn\/index.php\/wp-json\/wp\/v2\/posts\/619\/revisions"}],"predecessor-version":[{"id":773,"href":"https:\/\/pa.yingzhi8.cn\/index.php\/wp-json\/wp\/v2\/posts\/619\/revisions\/773"}],"wp:attachment":[{"href":"https:\/\/pa.yingzhi8.cn\/index.php\/wp-json\/wp\/v2\/media?parent=619"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/pa.yingzhi8.cn\/index.php\/wp-json\/wp\/v2\/categories?post=619"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/pa.yingzhi8.cn\/index.php\/wp-json\/wp\/v2\/tags?post=619"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}