#selfhost convex on pi
21 messages · Page 1 of 1 (latest)
Short answer: the prebuilt self‑hosted Convex Docker images and binaries are built for x86_64, not ARM. A Raspberry Pi (64‑bit OS on ARM64) will pull the image fine but the container will exit immediately with an “exec format”/illegal instruction type failure (exit code 132) because the architecture doesn’t match. The docs and guides provided don’t list ARM builds, and suggest either using Docker images as-is or building from source when a precompiled binary for your platform isn’t available. [Developing OSS; Running the binary]
Ways to proceed:
-
Build the backend from source directly on the Pi, then run the binary:
- Clone the repo and install build deps (Rust, Node, rush, just), then run the local backend:
- git clone https://github.com/get-convex/convex-backend
- Install deps per README, then just run-local-backend
- When it’s listening on 0.0.0.0:3210, point your app/CLI at it with --url and the default admin key (or generate your own). [Building backend; Developing OSS]
- Clone the repo and install build deps (Rust, Node, rush, just), then run the local backend:
-
Alternatively, compile your own ARM64 Docker image from the open‑source repo’s Docker files instead of using the prebuilt images, which are intended for common cloud x86_64 targets. The self-hosting materials note you can “build your own containers” from the provided Docker build files. [Option 3]
Once you have the backend running (binary or custom ARM image), generate an admin key and wire up your dev workflow:
- Generate admin key (script in container or via keybroker if running from source), then set:
- CONVEX_SELF_HOSTED_URL to your Pi’s backend URL (e.g., <http://<pi-ip>:3210>)
- CONVEX_SELF_HOSTED_ADMIN_KEY to the generated key
- Use npx convex dev/deploy as usual. [Docker self‑host; Dev workflow]
If you’d like, I can sketch the exact “build from source on Pi” commands from the guide for Debian Bookworm ARM64.
Note: you can ask me a follow up question by @ mentioning me again :speech_balloon:
@minor schooner Kapa.ai is still learning and improving, please let me know how I did by reacting below.
@autumn gale I have built an arm64 image of convex-backend called convex-backend-arm64. where can i go from here?
Let me check the knowledge base for you again. One moment! :books:
Great — with an arm64 image built, you can proceed just like the standard self-hosted flow, substituting your image where the docs reference the prebuilt one. Here are the concrete next steps.
- Run your container and generate an admin key
- Start your backend container (mapping the standard ports):
- 3210: Convex API
- 3211: HTTP actions
- Exec into the container and run the provided script to generate an admin key:
- docker exec -it <container_name> ./generate_admin_key.sh
Use this key for CLI deploys and the dashboard. [Self-hosting Convex]
- docker exec -it <container_name> ./generate_admin_key.sh
- Set environment variables for a smooth dev workflow
In your Convex app, add to .env.local:
- CONVEX_SELF_HOSTED_URL='<http://<pi-ip> or domain>:3210'
- CONVEX_SELF_HOSTED_ADMIN_KEY='<admin key from step 1>'
Then you can run: - npx convex dev
- npx convex deploy
These commands will target your self-hosted backend (mixing cloud and self-hosted env vars is not allowed, by design). [Development workflow]
- (Optional) Run the dashboard
You can:
- Run the dashboard container (arm64 build if needed) and point it at your backend via NEXT_PUBLIC_DEPLOYMENT_URL, or
- Run it locally with Docker:
- docker run -e 'NEXT_PUBLIC_DEPLOYMENT_URL=<<http://<pi-ip>:3210>'> -p '6791:6791' ghcr.io/get-convex/convex-dashboard:latest
Then visit http://localhost:6791 and paste the admin key. [Dev workflow]
- docker run -e 'NEXT_PUBLIC_DEPLOYMENT_URL=<<http://<pi-ip>:3210>'> -p '6791:6791' ghcr.io/get-convex/convex-dashboard:latest
- If you’re fronting with your own domain
If you put your Pi behind a reverse proxy, set:
- CONVEX_CLOUD_ORIGIN='https://api.your-domain.com'
- CONVEX_SITE_ORIGIN='https://your-domain.com'
- NEXT_PUBLIC_DEPLOYMENT_URL='https://api.your-domain.com'
And route: - https://api.your-domain.com -> pi:3210
- https://your-domain.com -> pi:3211
- https://dashboard.your-domain.com -> pi:6791
Then use the same admin key and .env.local variables from step 2. [Own infrastructure]
- Optional: use Postgres/MySQL instead of SQLite
If you don’t want SQLite on the Pi’s disk, point the backend to a SQL database. Provide the URL without a db name, and ensure a database named convex_self_hosted exists. Example with Postgres (Neon shown in docs):
- Create DB convex_self_hosted
- Set POSTGRES_URL to the connection string without db name/query
Keep backend and DB in the same region to minimize latency. [Postgres/MySQL]
Minimal checklist to confirm it works
- Container logs show Listening on 0.0.0.0:3210 and Connected to <DB> (if using external DB). [Developing OSS]
- You can run npx convex dev from your app with CONVEX_SELF_HOSTED_* set. [Self-hosting Convex]
- Dashboard loads and accepts the admin key. [Dev workflow]
If you want, share how you tagged your arm64 image, and I can suggest a docker-compose.yml snippet that swaps in your image and sets the right env vars. [Option 3]
Note: you can ask me a follow up question by @ mentioning me again :speech_balloon:
@minor schooner Kapa.ai is still learning and improving, please let me know how I did by reacting below.
@autumn gale okay, I get this now even though I changed the image in the docker compose file to my image:
[+] Running 1/1
✔ Container convex-backend-1 Recreated 0.3s
Attaching to backend-1, dashboard-1
dependency failed to start: container convex-backend-1 exited (0)
Let me check the knowledge base for you again. One moment! :books:
A container exiting immediately with code 0 usually means the process in the container finished right away (nothing is keeping it running), not necessarily a crash. With Convex’s self‑hosted images, the backend should start a long‑running server that listens on 3210/3211. A few things to check based on the self‑hosting guides:
-
Ensure the container is actually starting the backend entrypoint. If you built your own ARM64 image, confirm it uses the same CMD/entrypoint as the official backend image so it launches the Convex server and doesn’t just exit after a script finishes. The official Docker setup expects a long‑running backend process and maps:
- 3210: Convex API
- 3211: HTTP actions [Self-hosting Convex].
-
Verify required environment variables. The stock docker-compose sets CONVEX_CLOUD_ORIGIN and CONVEX_SITE_ORIGIN (and others). If your compose references the dashboard too, it also needs NEXT_PUBLIC_DEPLOYMENT_URL pointing at your backend URL. Missing or mismatched env vars can cause components not to connect even if the backend runs. [Own infrastructure; Option 3].
-
Check logs directly:
- docker logs <backend-container-name>
If there’s no output, the process likely never started. If you see “Listening on http://0.0.0.0:3210” then it did start and something else is marking “dependency failed to start.” The compose file often has healthchecks that must pass; the backend must respond on /version to be considered healthy. [Developing OSS].
- docker logs <backend-container-name>
-
Healthcheck in compose. The provided compose uses:
- test: curl -f http://localhost:3210/version
If your image doesn’t expose the same /version endpoint or isn’t binding to 0.0.0.0:3210, the healthcheck will fail and dependent services (dashboard) will report “dependency failed to start.” Make sure your build runs the same backend binary and binds to 0.0.0.0:3210. [Self-hosting Convex].
- test: curl -f http://localhost:3210/version
-
Confirm ports and mapping match. The dashboard expects the backend to be reachable at the URL you set via NEXT_PUBLIC_DEPLOYMENT_URL (often http://127.0.0.1:3210 in local compose). If you changed ports, update those env vars accordingly, otherwise the dashboard will wait on a backend that appears down. [Self-hosting setup].
-
Try running the backend container interactively to see if it exits:
- docker run --rm -it -p 3210:3210 -p 3211:3211 your/convex-backend-arm64
If it exits immediately with no logs, the CMD may be wrong. If it runs, you should see logs like “Listening on http://0.0.0.0:3210”. [Building backend].
- docker run --rm -it -p 3210:3210 -p 3211:3211 your/convex-backend-arm64
If you share your docker-compose service block (image, command/entrypoint, env, healthcheck), I can help spot the mismatch. In the meantime, aim to replicate the official compose and env, just swapping the image:
- backend service:
- image: your/convex-backend-arm64
- ports: "3210:3210", "3211:3211"
- environment: CONVEX_CLOUD_ORIGIN, CONVEX_SITE_ORIGIN, etc.
- healthcheck: curl -f http://localhost:3210/version
- dashboard service:
- NEXT_PUBLIC_DEPLOYMENT_URL set to the backend URL [Self-hosting Convex].
Note: you can ask me a follow up question by @ mentioning me again :speech_balloon:
@minor schooner Kapa.ai is still learning and improving, please let me know how I did by reacting below.
@autumn gale say there's something wrong with my image, how should i recreate a correct image that will run on the raspberry pi os?
Let me check the knowledge base for you again. One moment! :books:
If your custom image might be wrong, the safest path is to rebuild it directly from the open-source backend’s Docker build files, targeting ARM64. The docs explicitly say you can “build your own containers” from the provided Docker files; the prebuilt images are oriented to common cloud targets, so rebuilding for Pi (arm64) is the right move. [Option 3]
Two reliable approaches:
- Build an arm64 Docker image from the repo’s Docker files
- Start from the self-hosted/docker-build context in the open-source repo (that’s what the official images are built from).
- Build on the Pi (native arm64) to avoid cross-compilation issues.
- Keep the same entrypoint/CMD and required env vars as the official docker-compose so the backend starts and listens on 3210/3211, and the healthcheck /version works. [Self-hosting Convex]
- Then swap this image into the provided docker-compose.yml.
Example outline:
- Clone the repo.
- Use the docker-build files to produce your image (same structure as the official compose expects).
- Verify by docker run … and check for “Listening on …:3210” in logs. [Building OSS; Self-hosting Convex]
- Build the backend binary on the Pi, then create a minimal image around it
- Compile the backend on the Pi (Debian bookworm arm64) following the “build from source” guide:
- Install Rust, Node, just, rush, then run the local backend build. [Building backend]
- Once the binary works locally (you see “Listening on http://0.0.0.0:3210”), package it into an image whose CMD matches the official one, so docker-compose healthchecks pass and dependent services (dashboard) can start. [Developing OSS; Self-hosting Convex]
Key correctness checks for your rebuilt image
- Entrypoint/CMD starts the long-running Convex backend (not a build step that exits). Container should keep running and expose:
- 3210: Convex API
- 3211: HTTP actions
And respond to GET /version for the healthcheck. [Self-hosting Convex]
- Required env vars honored when using docker-compose:
- CONVEX_CLOUD_ORIGIN and CONVEX_SITE_ORIGIN when fronting with your own domain, or the local defaults in the stock compose.
- The dashboard uses NEXT_PUBLIC_DEPLOYMENT_URL to point at the backend. [Own infrastructure]
- You can exec and generate an admin key via ./generate_admin_key_sh (or the keybroker path, if running binaries directly), then npx convex dev works with CONVEX_SELF_HOSTED_URL and CONVEX_SELF_HOSTED_ADMIN_KEY. [Self-hosting Convex; Development workflow]