[{"data":1,"prerenderedAt":183},["ShallowReactive",2],{"doc:self-host\u002Fdocker":3},{"title":4,"description":5,"url":6,"markdownPath":7,"file":8,"section":9,"sectionTitle":10,"html":11,"toc":12,"navigation":42,"previous":181,"next":182},"Run a Server with Docker Compose","Run one L4 Server with Docker Compose behind your own reverse proxy, then update it by changing the image tag.","\u002Fdocs\u002Fself-host\u002Fdocker","\u002Fdocs\u002Fself-host\u002Fdocker.md","docs\u002Fself-host\u002Fdocker.md","self-host","Self-host","\u003Cp>The common Docker Compose stack runs one standalone L4 Server on a single \u003Ca href=\"https:\u002F\u002Fcelld.dev\" rel=\"noopener\">celld\u003C\u002Fa> node, with private \u003Ca href=\"https:\u002F\u002Fgithub.com\u002Frustfs\u002Frustfs\" rel=\"noopener\">RustFS\u003C\u002Fa> storage and a Caddy gateway. Use it when you want to manage Docker yourself, or when the machine already has a reverse proxy. For a managed install with HTTPS, backups and rollback, use the \u003Ca href=\"\u002Fdocs\u002Fself-host\u002Fvps\">VPS installer\u003C\u002Fa>. For Coolify, see \u003Ca href=\"\u002Fdocs\u002Fself-host\u002Fcoolify\">Coolify\u003C\u002Fa>.\u003C\u002Fp>\n\u003Ch2 id=\"what-runs\">\u003Ca class=\"heading-anchor\" href=\"#what-runs\">What runs\u003C\u002Fa>\u003C\u002Fh2>\n\u003Cdiv class=\"table-wrap\">\u003Ctable>\n\u003Cthead>\n\u003Ctr>\n\u003Cth>Service\u003C\u002Fth>\n\u003Cth>Role\u003C\u002Fth>\n\u003C\u002Ftr>\n\u003C\u002Fthead>\n\u003Ctbody>\u003Ctr>\n\u003Ctd>\u003Ccode>llll\u003C\u002Fcode>\u003C\u002Ftd>\n\u003Ctd>The Server on celld. No host port is published.\u003C\u002Ftd>\n\u003C\u002Ftr>\n\u003Ctr>\n\u003Ctd>\u003Ccode>rustfs\u003C\u002Fcode>\u003C\u002Ftd>\n\u003Ctd>Private S3 bucket that holds the database, Durable Object storage, KV, files and the deployment. No host port is published.\u003C\u002Ftd>\n\u003C\u002Ftr>\n\u003Ctr>\n\u003Ctd>\u003Ccode>rustfs-perms\u003C\u002Fcode>, \u003Ccode>bucket-init\u003C\u002Fcode>\u003C\u002Ftd>\n\u003Ctd>One-shot helpers that prepare the volume and create the bucket.\u003C\u002Ftd>\n\u003C\u002Ftr>\n\u003Ctr>\n\u003Ctd>\u003Ccode>gateway\u003C\u002Fcode>\u003C\u002Ftd>\n\u003Ctd>Caddy. Listens on \u003Ccode>127.0.0.1:8080\u003C\u002Fcode> by default.\u003C\u002Ftd>\n\u003C\u002Ftr>\n\u003C\u002Ftbody>\u003C\u002Ftable>\u003C\u002Fdiv>\n\u003Cp>The stack uses four volumes: \u003Ccode>rustfs-data\u003C\u002Fcode>, \u003Ccode>celld-data\u003C\u002Fcode>, \u003Ccode>caddy-data\u003C\u002Fcode> and \u003Ccode>caddy-config\u003C\u002Fcode>.\u003C\u002Fp>\n\u003Cblockquote class=\"callout callout-warning\">\u003Cp class=\"callout-title\">Warning\u003C\u002Fp>\u003Cp>celld has no secrets store. On start the container writes your \u003Ccode>.env\u003C\u002Fcode> into the deployment, which celld stores as plaintext in the RustFS bucket. Keep the RustFS volume private and never publish port 9000.\u003C\u002Fp>\n\u003C\u002Fblockquote>\n\u003Ch2 id=\"get-the-image\">\u003Ca class=\"heading-anchor\" href=\"#get-the-image\">Get the image\u003C\u002Fa>\u003C\u002Fh2>\n\u003Cp>Pick one:\u003C\u002Fp>\n\u003Cul>\n\u003Cli>\u003Cstrong>Published image (stable releases).\u003C\u002Fstrong> \u003Ccode>ghcr.io\u002Finchidev\u002Fllll:&lt;version&gt;\u003C\u002Fcode>, \u003Ccode>:&lt;minor&gt;\u003C\u002Fcode> (for example \u003Ccode>0.3\u003C\u002Fcode>) and \u003Ccode>:latest\u003C\u002Fcode>, for \u003Ccode>linux\u002Famd64\u003C\u002Fcode> and \u003Ccode>linux\u002Farm64\u003C\u002Fcode>. Prereleases are not published as images.\u003C\u002Fli>\n\u003Cli>\u003Cstrong>Release archive.\u003C\u002Fstrong> Each release includes \u003Ccode>llll-runtime-linux-amd64.tar.gz\u003C\u002Fcode> and \u003Ccode>SHA256SUMS\u003C\u002Fcode>. Verify the checksum, then \u003Ccode>docker load --input llll-runtime-linux-amd64.tar.gz\u003C\u002Fcode>. This loads \u003Ccode>llll:&lt;version&gt;\u003C\u002Fcode> locally.\u003C\u002Fli>\n\u003C\u002Ful>\n\u003Cp>The common Compose file uses \u003Ccode>pull_policy: never\u003C\u002Fcode>, so pull the published image yourself before starting:\u003C\u002Fp>\n\u003Cpre>\u003Ccode class=\"language-bash\">docker pull ghcr.io\u002Finchidev\u002Fllll:latest\n\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Ch2 id=\"set-up\">\u003Ca class=\"heading-anchor\" href=\"#set-up\">Set up\u003C\u002Fa>\u003C\u002Fh2>\n\u003Col>\n\u003Cli>\u003Cp>Get the \u003Ccode>self-host\u003C\u002Fcode> folder from the release you run, for example:\u003C\u002Fp>\n\u003Cpre>\u003Ccode class=\"language-bash\">git clone --depth 1 --branch v&lt;version&gt; https:\u002F\u002Fgithub.com\u002Finchidev\u002Fllll.git\ncd llll\u002Fself-host\n\u003C\u002Fcode>\u003C\u002Fpre>\n\u003C\u002Fli>\n\u003Cli>\u003Cp>Create the private configuration:\u003C\u002Fp>\n\u003Cpre>\u003Ccode class=\"language-bash\">cp .env.example .env\nopenssl rand -hex 32   # run twice: one value for AUTH_SECRET, one for SETUP_TOKEN\n\u003C\u002Fcode>\u003C\u002Fpre>\n\u003C\u002Fli>\n\u003Cli>\u003Cp>Edit \u003Ccode>.env\u003C\u002Fcode>:\u003C\u002Fp>\n\u003Cdiv class=\"table-wrap\">\u003Ctable>\n\u003Cthead>\n\u003Ctr>\n\u003Cth>Key\u003C\u002Fth>\n\u003Cth>Value\u003C\u002Fth>\n\u003C\u002Ftr>\n\u003C\u002Fthead>\n\u003Ctbody>\u003Ctr>\n\u003Ctd>\u003Ccode>PUBLIC_ORIGIN\u003C\u002Fcode>\u003C\u002Ftd>\n\u003Ctd>The origin members open, for example \u003Ccode>https:\u002F\u002Fchat.example.com\u003C\u002Fcode>.\u003C\u002Ftd>\n\u003C\u002Ftr>\n\u003Ctr>\n\u003Ctd>\u003Ccode>AUTH_SECRET\u003C\u002Fcode>\u003C\u002Ftd>\n\u003Ctd>Random, at least 32 characters. Signs sessions and encrypts stored credentials.\u003C\u002Ftd>\n\u003C\u002Ftr>\n\u003Ctr>\n\u003Ctd>\u003Ccode>SETUP_TOKEN\u003C\u002Fcode>\u003C\u002Ftd>\n\u003Ctd>Random, at least 32 characters. Used once to claim the Owner.\u003C\u002Ftd>\n\u003C\u002Ftr>\n\u003Ctr>\n\u003Ctd>\u003Ccode>ADMIN_EMAIL\u003C\u002Fcode>\u003C\u002Ftd>\n\u003Ctd>Email of the first Owner.\u003C\u002Ftd>\n\u003C\u002Ftr>\n\u003Ctr>\n\u003Ctd>\u003Ccode>RUSTFS_ACCESS_KEY\u003C\u002Fcode>, \u003Ccode>RUSTFS_SECRET_KEY\u003C\u002Fcode>\u003C\u002Ftd>\n\u003Ctd>Keys for the private bucket.\u003C\u002Ftd>\n\u003C\u002Ftr>\n\u003Ctr>\n\u003Ctd>\u003Ccode>LLLL_IMAGE\u003C\u002Fcode>\u003C\u002Ftd>\n\u003Ctd>\u003Ccode>ghcr.io\u002Finchidev\u002Fllll:&lt;version&gt;\u003C\u002Fcode> or \u003Ccode>llll:&lt;version&gt;\u003C\u002Fcode>.\u003C\u002Ftd>\n\u003C\u002Ftr>\n\u003C\u002Ftbody>\u003C\u002Ftable>\u003C\u002Fdiv>\n\u003C\u002Fli>\n\u003Cli>\u003Cp>Start the stack:\u003C\u002Fp>\n\u003Cpre>\u003Ccode class=\"language-bash\">docker compose up -d --wait\n\u003C\u002Fcode>\u003C\u002Fpre>\n\u003C\u002Fli>\n\u003Cli>\u003Cp>Open \u003Ccode>&lt;PUBLIC_ORIGIN&gt;\u002Fsetup\u003C\u002Fcode>, enter \u003Ccode>SETUP_TOKEN\u003C\u002Fcode> and create the Owner. \u003Ccode>&lt;PUBLIC_ORIGIN&gt;\u002Fsetup#claim=&lt;SETUP_TOKEN&gt;\u003C\u002Fcode> skips the token field. If \u003Ccode>.env\u003C\u002Fcode> sets \u003Ccode>ADMIN_PASSWORD\u003C\u002Fcode> (at least 12 characters), the first start creates the Owner instead: sign in with \u003Ccode>ADMIN_EMAIL\u003C\u002Fcode> and that password, then change it.\u003C\u002Fp>\n\u003C\u002Fli>\n\u003C\u002Fol>\n\u003Cp>The \u003Ccode>llll\u003C\u002Fcode> container stays unhealthy until its database migrations have been applied. Caddy starts after that, and \u003Ccode>\u002Fapi\u002Fsetup\u002Fhealth\u003C\u002Fcode> returns HTTP 200. On first start, the log line \u003Ccode>waiting for the celld node to join\u003C\u002Fcode> is expected.\u003C\u002Fp>\n\u003Cblockquote class=\"callout callout-important\">\u003Cp class=\"callout-title\">Important\u003C\u002Fp>\u003Cp>Never change \u003Ccode>AUTH_SECRET\u003C\u002Fcode> after setup. It signs sessions, and credentials the Server stores (such as backup keys and provider keys) are encrypted with it.\u003C\u002Fp>\n\u003C\u002Fblockquote>\n\u003Ch2 id=\"reverse-proxy-and-tls\">\u003Ca class=\"heading-anchor\" href=\"#reverse-proxy-and-tls\">Reverse proxy and TLS\u003C\u002Fa>\u003C\u002Fh2>\n\u003Cp>The gateway listens on loopback HTTP. For public use, keep it on loopback and terminate TLS in front of it. Set \u003Ccode>PUBLIC_ORIGIN\u003C\u002Fcode> to the public HTTPS origin and run \u003Ccode>docker compose up -d\u003C\u002Fcode> again.\u003C\u002Fp>\n\u003Cp>Caddy on the host:\u003C\u002Fp>\n\u003Cpre>\u003Ccode class=\"language-text\">chat.example.com {\n  reverse_proxy 127.0.0.1:8080\n}\n\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Cp>nginx must forward WebSocket upgrades for chat:\u003C\u002Fp>\n\u003Cpre>\u003Ccode class=\"language-text\">server {\n  server_name chat.example.com;\n  location \u002F {\n    proxy_pass http:\u002F\u002F127.0.0.1:8080;\n    proxy_http_version 1.1;\n    proxy_set_header Host $host;\n    proxy_set_header Upgrade $http_upgrade;\n    proxy_set_header Connection &quot;upgrade&quot;;\n    proxy_set_header X-Forwarded-Proto https;\n  }\n}\n\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Cp>\u003Ccode>LLLL_HTTP_PORT\u003C\u002Fcode> changes the host port. \u003Ccode>LLLL_BIND=0.0.0.0\u003C\u002Fcode> exposes the gateway on every interface; configure TLS before you invite anyone.\u003C\u002Fp>\n\u003Ch3 id=\"more-than-one-address\">\u003Ca class=\"heading-anchor\" href=\"#more-than-one-address\">More than one address\u003C\u002Fa>\u003C\u002Fh3>\n\u003Cp>To serve extra hostnames, set \u003Ccode>LLLL_ORIGINS\u003C\u002Fcode> to a comma-separated list of origins and route all of them to the same container. Only listed origins are trusted. \u003Ccode>PUBLIC_ORIGIN\u003C\u002Fcode> stays the \u003Ca href=\"\u002Fdocs\u002Fconcepts\u002Fserver-and-shell#addresses\">primary address\u003C\u002Fa>.\u003C\u002Fp>\n\u003Ch2 id=\"update\">\u003Ca class=\"heading-anchor\" href=\"#update\">Update\u003C\u002Fa>\u003C\u002Fh2>\n\u003Cp>Updates are an image tag. L4 Settings does not update a Docker Server; \u003Cstrong>Server settings → Deployment → Updates\u003C\u002Fstrong> says that updates are managed outside L4 and shows when a newer stable release exists.\u003C\u002Fp>\n\u003Col>\n\u003Cli>Take and verify a backup (below).\u003C\u002Fli>\n\u003Cli>Pull or load the new image and set \u003Ccode>LLLL_IMAGE\u003C\u002Fcode> to it in \u003Ccode>.env\u003C\u002Fcode>.\u003C\u002Fli>\n\u003Cli>Run \u003Ccode>docker compose up -d --wait\u003C\u002Fcode>.\u003C\u002Fli>\n\u003C\u002Fol>\n\u003Cp>On start, the container applies the new database migrations; ones already applied are skipped. Expect a short outage while the single node restarts.\u003C\u002Fp>\n\u003Cp>Migrations only go forward. The container records the release that last migrated its data and refuses to start an older image:\u003C\u002Fp>\n\u003Cpre>\u003Ccode class=\"language-text\">llll: this data was migrated by L4 0.3.4; image 0.3.3 is older. Use 0.3.4 or newer.\n\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Cp>To go back, restore a backup instead.\u003C\u002Fp>\n\u003Ch2 id=\"back-up-and-restore\">\u003Ca class=\"heading-anchor\" href=\"#back-up-and-restore\">Back up and restore\u003C\u002Fa>\u003C\u002Fh2>\n\u003Cp>Stop the stack, then copy both data volumes and \u003Ccode>.env\u003C\u002Fcode>. The names below assume the Compose project \u003Ccode>llll\u003C\u002Fcode>:\u003C\u002Fp>\n\u003Cpre>\u003Ccode class=\"language-bash\">docker compose stop\ndocker run --rm -v llll_rustfs-data:\u002Ffrom -v &quot;$PWD&quot;:\u002Fto alpine:3.22 \\\n  tar -C \u002Ffrom -czf \u002Fto\u002Frustfs-data.tgz .\ndocker run --rm -v llll_celld-data:\u002Ffrom -v &quot;$PWD&quot;:\u002Fto alpine:3.22 \\\n  tar -C \u002Ffrom -czf \u002Fto\u002Fcelld-data.tgz .\ndocker compose start\n\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Cul>\n\u003Cli>\u003Ccode>rustfs-data\u003C\u002Fcode> holds the database, Durable Object storage, KV, Server files and the deployment, including plaintext Worker variables.\u003C\u002Fli>\n\u003Cli>\u003Ccode>celld-data\u003C\u002Fcode> is the node&#39;s local work directory.\u003C\u002Fli>\n\u003Cli>\u003Ccode>.env\u003C\u002Fcode> holds \u003Ccode>AUTH_SECRET\u003C\u002Fcode> and the RustFS keys.\u003C\u002Fli>\n\u003C\u002Ful>\n\u003Cp>Store all three privately and outside the live volumes. To restore, stop the stack, extract the archives onto empty volumes with the same names, keep the same \u003Ccode>.env\u003C\u002Fcode> and start again.\u003C\u002Fp>\n\u003Cp>\u003Cstrong>Server settings → Deployment → Backups\u003C\u002Fstrong> can also download an archive of the database and files, or send it to an S3 destination. That archive does not include the celld deployment, KV or live Durable Object state. See \u003Ca href=\"\u002Fdocs\u002Fconcepts\u002Ffiles-and-backups\">Files and backups\u003C\u002Fa>.\u003C\u002Fp>\n\u003Ch2 id=\"optional-providers\">\u003Ca class=\"heading-anchor\" href=\"#optional-providers\">Optional providers\u003C\u002Fa>\u003C\u002Fh2>\n\u003Cp>Text chat, Tasks, files and backups work without any provider. Add these keys to \u003Ccode>.env\u003C\u002Fcode> to turn on more. Empty values are ignored.\u003C\u002Fp>\n\u003Cdiv class=\"table-wrap\">\u003Ctable>\n\u003Cthead>\n\u003Ctr>\n\u003Cth>Keys\u003C\u002Fth>\n\u003Cth>Turns on\u003C\u002Fth>\n\u003C\u002Ftr>\n\u003C\u002Fthead>\n\u003Ctbody>\u003Ctr>\n\u003Ctd>\u003Ccode>CLOUDFLARE_ACCOUNT_ID\u003C\u002Fcode>, \u003Ccode>CLOUDFLARE_API_TOKEN\u003C\u002Fcode>\u003C\u002Ftd>\n\u003Ctd>Workers AI, Browser Run (page reading), Email Sending and RealtimeKit calls over Cloudflare&#39;s REST API. The account ID is 32 hex characters.\u003C\u002Ftd>\n\u003C\u002Ftr>\n\u003Ctr>\n\u003Ctd>\u003Ccode>AI_BASE_URL\u003C\u002Fcode>, \u003Ccode>AI_API_KEY\u003C\u002Fcode>, \u003Ccode>AI_MODEL\u003C\u002Fcode>\u003C\u002Ftd>\n\u003Ctd>An OpenAI-compatible model endpoint, used when the Cloudflare token is not set. Set all three.\u003C\u002Ftd>\n\u003C\u002Ftr>\n\u003Ctr>\n\u003Ctd>\u003Ccode>MAIL_GATEWAY_URL\u003C\u002Fcode>, \u003Ccode>MAIL_GATEWAY_TOKEN\u003C\u002Fcode> or \u003Ccode>SMTP_GATEWAY_URL\u003C\u002Fcode>, \u003Ccode>SMTP_GATEWAY_TOKEN\u003C\u002Fcode>\u003C\u002Ftd>\n\u003Ctd>Outbound mail through an HTTP gateway you run. The Server does not open an SMTP port.\u003C\u002Ftd>\n\u003C\u002Ftr>\n\u003Ctr>\n\u003Ctd>\u003Ccode>INBOUND_EMAIL_SECRET\u003C\u002Fcode>, \u003Ccode>POSTMARK_INBOUND_SECRET\u003C\u002Fcode>, \u003Ccode>MAILGUN_WEBHOOK_SIGNING_KEY\u003C\u002Fcode>, \u003Ccode>SES_SNS_TOPIC_ARN\u003C\u002Fcode>\u003C\u002Ftd>\n\u003Ctd>Inbound mail through a signed webhook. Secrets must be at least 32 characters.\u003C\u002Ftd>\n\u003C\u002Ftr>\n\u003Ctr>\n\u003Ctd>\u003Ccode>BROWSER_CDP_URL\u003C\u002Fcode>\u003C\u002Ftd>\n\u003Ctd>A private Chromium DevTools endpoint for page reading. Do not publish its port.\u003C\u002Ftd>\n\u003C\u002Ftr>\n\u003C\u002Ftbody>\u003C\u002Ftable>\u003C\u002Fdiv>\n\u003Cp>\u003Ccode>\u002Fapi\u002Fsetup\u002Fhealth\u003C\u002Fcode> reports which provider the Server chose. The \u003Ca href=\"https:\u002F\u002Fgithub.com\u002Finchidev\u002Fllll\u002Fblob\u002Fmain\u002Fdocs\u002Fself-host\u002Fcelld.md\" rel=\"noopener\">celld reference\u003C\u002Fa> documents each provider, the token permissions and the inbound mail setup in detail.\u003C\u002Fp>\n\u003Cp>Without a Cloudflare token, calls stay unavailable and the call button is disabled; text chat keeps working.\u003C\u002Fp>\n\u003Ch2 id=\"build-from-source\">\u003Ca class=\"heading-anchor\" href=\"#build-from-source\">Build from source\u003C\u002Fa>\u003C\u002Fh2>\n\u003Cp>\u003Ccode>compose.build.yml\u003C\u002Fcode> adds a local source build:\u003C\u002Fp>\n\u003Cpre>\u003Ccode class=\"language-bash\">docker compose -f docker-compose.yml -f compose.build.yml up -d --build --wait\n\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Cp>The build needs about 8 GB of free RAM. Use it to test source changes, not to run a community Server.\u003C\u002Fp>\n",[13,17,20,23,26,30,33,36,39],{"id":14,"text":15,"depth":16},"what-runs","What runs",2,{"id":18,"text":19,"depth":16},"get-the-image","Get the image",{"id":21,"text":22,"depth":16},"set-up","Set up",{"id":24,"text":25,"depth":16},"reverse-proxy-and-tls","Reverse proxy and TLS",{"id":27,"text":28,"depth":29},"more-than-one-address","More than one address",3,{"id":31,"text":32,"depth":16},"update","Update",{"id":34,"text":35,"depth":16},"back-up-and-restore","Back up and restore",{"id":37,"text":38,"depth":16},"optional-providers","Optional providers",{"id":40,"text":41,"depth":16},"build-from-source","Build from source",[43,68,96,108,127,149,171],{"id":44,"title":45,"pages":46},"get-started","Get started",[47,50,53,56,59,62,65],{"title":48,"url":49},"What is L4","\u002Fdocs\u002Fget-started\u002Fwhat-is-l4",{"title":51,"url":52},"Choose how to run your Server","\u002Fdocs\u002Fget-started\u002Fchoose-how-to-run",{"title":54,"url":55},"Create a Server on Cloudflare","\u002Fdocs\u002Fget-started\u002Fcreate-on-cloudflare",{"title":57,"url":58},"Install on a VPS","\u002Fdocs\u002Fget-started\u002Finstall-on-a-vps",{"title":60,"url":61},"Connect to a Server","\u002Fdocs\u002Fget-started\u002Fconnect-a-server",{"title":63,"url":64},"Invite your team","\u002Fdocs\u002Fget-started\u002Finvite-your-team",{"title":66,"url":67},"Create your first Agent","\u002Fdocs\u002Fget-started\u002Ffirst-agent",{"id":69,"title":70,"pages":71},"cloudflare","Cloudflare",[72,75,78,81,84,87,90,93],{"title":73,"url":74},"L4 on Cloudflare","\u002Fdocs\u002Fcloudflare\u002Foverview",{"title":76,"url":77},"Cloudflare access","\u002Fdocs\u002Fcloudflare\u002Faccess",{"title":79,"url":80},"Costs and limits","\u002Fdocs\u002Fcloudflare\u002Fcosts-and-limits",{"title":82,"url":83},"Custom domain","\u002Fdocs\u002Fcloudflare\u002Fcustom-domain",{"title":85,"url":86},"Mail on Cloudflare","\u002Fdocs\u002Fcloudflare\u002Fmail",{"title":88,"url":89},"Update a Cloudflare Server","\u002Fdocs\u002Fcloudflare\u002Fupdates",{"title":91,"url":92},"Backups on Cloudflare","\u002Fdocs\u002Fcloudflare\u002Fbackups",{"title":94,"url":95},"Remove a Cloudflare Server","\u002Fdocs\u002Fcloudflare\u002Fremove-a-server",{"id":9,"title":10,"pages":97},[98,101,102,105],{"title":99,"url":100},"Run a Server on a VPS","\u002Fdocs\u002Fself-host\u002Fvps",{"title":4,"url":6},{"title":103,"url":104},"Run a Server on Coolify","\u002Fdocs\u002Fself-host\u002Fcoolify",{"title":106,"url":107},"Compute Nodes","\u002Fdocs\u002Fself-host\u002Fcompute-nodes",{"id":109,"title":110,"pages":111},"concepts","Concepts",[112,115,118,121,124],{"title":113,"url":114},"Servers and the Shell","\u002Fdocs\u002Fconcepts\u002Fserver-and-shell",{"title":116,"url":117},"Accounts, Members and Roles","\u002Fdocs\u002Fconcepts\u002Faccounts-members-roles",{"title":119,"url":120},"Agents, Tasks and Runs","\u002Fdocs\u002Fconcepts\u002Fagents-tasks-runs",{"title":122,"url":123},"Files and backups","\u002Fdocs\u002Fconcepts\u002Ffiles-and-backups",{"title":125,"url":126},"Releases and updates","\u002Fdocs\u002Fconcepts\u002Freleases-and-updates",{"id":128,"title":129,"pages":130},"agents","Agents and MCP",[131,134,137,140,143,146],{"title":132,"url":133},"Agents overview","\u002Fdocs\u002Fagents\u002Foverview",{"title":135,"url":136},"Models and Providers","\u002Fdocs\u002Fagents\u002Fmodels-and-providers",{"title":138,"url":139},"Connect an MCP client","\u002Fdocs\u002Fagents\u002Fmcp",{"title":141,"url":142},"External agents","\u002Fdocs\u002Fagents\u002Fexternal-agents",{"title":144,"url":145},"Repositories and code work","\u002Fdocs\u002Fagents\u002Frepositories",{"title":147,"url":148},"Schedules","\u002Fdocs\u002Fagents\u002Fschedules",{"id":150,"title":151,"pages":152},"guides","Guides",[153,156,159,162,165,168],{"title":154,"url":155},"Chat","\u002Fdocs\u002Fguides\u002Fchat",{"title":157,"url":158},"Projects and Tasks","\u002Fdocs\u002Fguides\u002Fprojects-and-tasks",{"title":160,"url":161},"Mail","\u002Fdocs\u002Fguides\u002Fmail",{"title":163,"url":164},"Calls and Live","\u002Fdocs\u002Fguides\u002Fcalls",{"title":166,"url":167},"Notifications","\u002Fdocs\u002Fguides\u002Fnotifications",{"title":169,"url":170},"Telegram","\u002Fdocs\u002Fguides\u002Ftelegram",{"id":172,"title":173,"pages":174},"reference","Reference",[175,178],{"title":176,"url":177},"Glossary","\u002Fdocs\u002Freference\u002Fglossary",{"title":179,"url":180},"Troubleshooting","\u002Fdocs\u002Freference\u002Ftroubleshooting",{"title":99,"url":100},{"title":103,"url":104},1793304298307]