Mastering Self-Hosted Convex: A Complete Deployment Guide
Stop struggling with custom scripts and learn the professional way to deploy Convex functions to your own server using the official CLI.

Originally published on DEV Community by Jookllo. Read on the original site
title: "Mastering Self-Hosted Convex: A Complete Deployment Guide" published: true description: "Stop struggling with custom scripts and learn the professional way to deploy Convex functions to your own server using the official CLI." tags: "convex, selfhosted, tutorial"
cover_image: https://www.convex.dev/_next/image?url=%2F_next%2Fstatic%2Fmedia%2FlogoColor.167xlrvlsjp8k.svg&w=384&q=75
Use a ratio of 100:42 for best results.
published_at: 2026-06-11 02:45 +0000
Mastering Self-Hosted Convex: A Complete Deployment Guide
So, you've decided to take control of your data and self-host Convex. Great choice! But if you've tried pushing your functions to a local or private server, you might have run into cryptic errors about "Relative import paths" or "Missing modules."
The secret? You don't need custom deployment scripts. In fact, you shouldn't use them. The official Convex CLI is actually powerful enough to handle self-hosted deployments perfectly—if you know which buttons to press.
In this guide, I’ll show you exactly how to configure your project and deploy your functions like a pro.
1. Before You Start
Before we dive into the code, make sure you have the following ready:
- Your Convex Instance: Whether you're using Dokploy, Docker, or a raw VPS, your backend should be up and running.
- The Admin Key: You'll need the master key for your server.
- Tip: If you're using Dokploy, you can usually generate this by running
./generate_admin_key.shinside your backend container's terminal.
- Tip: If you're using Dokploy, you can usually generate this by running
- The CLI: Make sure you have the latest version of Convex installed locally:
npm install convex
2. Preparing Your Project
For a smooth deployment, your convex/ folder needs to be a bit more "independent."
Step 1: Give Convex its own Identity
Create a package.json inside your convex/ directory. This ensures the CLI knows exactly which dependencies to bundle when it prepares your code for the server.
{
"name": "my-convex-backend",
"private": true,
"type": "module",
"dependencies": {
"convex": "^1.16.0",
"typescript": "^5.0.0"
}
}
Step 2: Fix your Config
Ensure your convex/convex.config.ts is using the modern defineApp export. The server expects this structure to understand your app's layout.
import { defineApp } from "convex/server";
export default defineApp();
3. The Magic Environment Variables
The Convex CLI is "Cloud-first" by default, but we can tell it to target our own server by setting two specific environment variables.
| Variable | What it does |
|---|---|
CONVEX_SELF_HOSTED_URL | Points the CLI to your backend URL (e.g., https://api.myapp.com). |
CONVEX_SELF_HOSTED_ADMIN_KEY | Your secret key. Crucial: It must include the `convex-self-hosted |
4. The Big Moment: Deploying
Now, let's push your code. We're going to use the official deploy command.
Run this from your root or convex directory:
CONVEX_SELF_HOSTED_URL="https://your-api-url.com" \
CONVEX_SELF_HOSTED_ADMIN_KEY="convex-self-hosted|your-key-here" \
npx convex deploy --typecheck disable
Why this works where other scripts fail:
When you use a custom fetch script to send files, you're just sending raw text. The server has no idea where convex/server is.
The CLI is smarter. It uses esbuild to "bundle" your code into a single, self-contained JavaScript package. It finds all your imports and bakes them right into the file so the server can run them instantly.
5. Pro Tip: Automate Everything
Don't type those long variables every time. Add a script to your convex/package.json:
"scripts": {
"deploy": "CONVEX_SELF_HOSTED_URL=... CONVEX_SELF_HOSTED_ADMIN_KEY=... npx convex deploy --typecheck disable"
}
Now, all it takes is a simple:
npm run deploy
Troubleshooting common "Gotchas"
"Relative import path 'convex/server' not found"
If you see this, you likely bypassed the CLI. Always use npx convex deploy so the bundler can do its job!
"BadAdminKey"
Double-check your key. Most people forget the convex-self-hosted| prefix. Without it, the server will reject your request every time.
Missing _generated files in your frontend
Run npx convex codegen while your CONVEX_SELF_HOSTED_URL is set to update your local TypeScript types to match what you just deployed.
Happy hosting! Your Convex backend is now truly yours.
Originally published on DEV Community by Jookllo. Read on the original site
You might also like

Production RAG with LangChain & Vector Databases
Master the transition from simple prototypes to production-grade RAG systems by addressing the critical scaling, debugging, and security challenges that standard tutorials often ignore. We just posted

How to Build a Calculator with Tkinter in Python
In this tutorial, you'll learn how to create a simple arithmetic calculator in Python with Tkinter. The project will be one of your first steps towards building an actual GUI in Python. This is a hand

How to Build a Scoped Note-Taking API with Django Rest Framework and SimpleJWT
If you've built a Django API and you're wondering how to add authentication so that each user can only access their own data, you're in the right place. Most Django tutorials teach you session-based a