<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0">
<channel>
<title>Coder Legion - Recent posts tagged convex</title>
<link>https://coderlegion.com/tag/convex</link>
<description>Powered by Question2Answer</description>
<item>
<title>Mastering Self-Hosted Convex on Dokploy: A Complete Deployment Guide</title>
<link>https://coderlegion.com/24030/mastering-self-hosted-convex-on-dokploy-a-complete-deployment-guide</link>
<description>&lt;p&gt;So, you've decided to take control of your data and self-host &lt;strong&gt;Convex&lt;/strong&gt;. It's a great choice but if you've tried pushing your functions to a local or private server, you might have run into cryptic errors about &quot;Relative import paths&quot; or &quot;Missing modules.&quot;&lt;/p&gt;
&lt;p&gt;The secret? You don't need custom deployment scripts. In fact, you &lt;em&gt;shouldn't&lt;/em&gt; use them. The official Convex CLI is actually powerful enough to handle self-hosted deployments perfectly—if you know which buttons to press.&lt;/p&gt;
&lt;p&gt;In this guide, I’ll show you exactly how to configure your project and deploy your functions like a pro.&lt;/p&gt;
&lt;hr&gt;
&lt;h3 id=&quot;1-before-you-start&quot;&gt;1. Before You Start&lt;/h3&gt;
&lt;p&gt;Before we dive into the code, make sure you have the following ready:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Your Convex Instance&lt;/strong&gt;: Whether you're using Dokploy, Docker, or a raw VPS, your backend should be up and running.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;The Admin Key&lt;/strong&gt;: You'll need the master key for your server. &lt;ul&gt;
&lt;li&gt;&lt;em&gt;Tip&lt;/em&gt;: If you're using Dokploy, you can usually generate this by running &lt;code&gt;./generate_admin_key.sh&lt;/code&gt; inside your backend container's terminal.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;The CLI&lt;/strong&gt;: Make sure you have the latest version of Convex installed locally:&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;npm install convex
&lt;/code&gt;&lt;/pre&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h3 id=&quot;2-preparing-your-project&quot;&gt;2. Preparing Your Project&lt;/h3&gt;
&lt;p&gt;For a smooth deployment, your &lt;code&gt;convex/&lt;/code&gt; folder needs to be a bit more &quot;independent.&quot;&lt;/p&gt;
&lt;h4 id=&quot;step-1-give-convex-its-own-identity&quot;&gt;Step 1: Give Convex its own Identity&lt;/h4&gt;
&lt;p&gt;Create a &lt;code&gt;package.json&lt;/code&gt; inside your &lt;code&gt;convex/&lt;/code&gt; directory. This ensures the CLI knows exactly which dependencies to bundle when it prepares your code for the server.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-json&quot;&gt;{
  &quot;name&quot;: &quot;my-convex-backend&quot;,
  &quot;private&quot;: true,
  &quot;type&quot;: &quot;module&quot;,
  &quot;dependencies&quot;: {
    &quot;convex&quot;: &quot;^1.16.0&quot;,
    &quot;typescript&quot;: &quot;^5.0.0&quot;
  }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;h4 id=&quot;step-2-fix-your-config&quot;&gt;Step 2: Fix your Config&lt;/h4&gt;
&lt;p&gt;Ensure your &lt;code&gt;convex/convex.config.ts&lt;/code&gt; is using the modern &lt;code&gt;defineApp&lt;/code&gt; export. The server expects this structure to understand your app's layout.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-typescript&quot;&gt;import { defineApp } from &quot;convex/server&quot;;

export default defineApp();
&lt;/code&gt;&lt;/pre&gt;
&lt;hr&gt;
&lt;h3 id=&quot;3-the-magic-environment-variables&quot;&gt;3. The Magic Environment Variables&lt;/h3&gt;
&lt;p&gt;The Convex CLI is &quot;Cloud-first&quot; by default, but we can tell it to target our own server by setting two specific environment variables.&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;&lt;th align=&quot;left&quot;&gt;Variable &lt;/th&gt;&lt;th align=&quot;left&quot;&gt;What it does&lt;/th&gt;&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;&lt;code&gt;CONVEX_SELF_HOSTED_URL&lt;/code&gt; &lt;/td&gt;&lt;td align=&quot;left&quot;&gt;Points the CLI to your backend URL (e.g., &lt;code&gt;https://api.myapp.com&lt;/code&gt;).&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;&lt;code&gt;CONVEX_SELF_HOSTED_ADMIN_KEY&lt;/code&gt; &lt;/td&gt;&lt;td align=&quot;left&quot;&gt;Your secret key. &lt;strong&gt;Crucial&lt;/strong&gt;: It must include the &lt;code&gt;convex-self-hosted|&lt;/code&gt; prefix!&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;hr&gt;
&lt;h3 id=&quot;4-the-big-moment-deploying&quot;&gt;4. The Big Moment: Deploying&lt;/h3&gt;
&lt;p&gt;Now, let's push your code. We're going to use the official &lt;code&gt;deploy&lt;/code&gt; command. &lt;/p&gt;
&lt;p&gt;Run this from your &lt;strong&gt;root&lt;/strong&gt; or &lt;strong&gt;convex&lt;/strong&gt; directory:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;CONVEX_SELF_HOSTED_URL=&quot;https://your-api-url.com&quot; \
CONVEX_SELF_HOSTED_ADMIN_KEY=&quot;convex-self-hosted|your-key-here&quot; \
npx convex deploy --typecheck disable
&lt;/code&gt;&lt;/pre&gt;
&lt;h4 id=&quot;why-this-works-where-other-scripts-fail-&quot;&gt;Why this works where other scripts fail:&lt;/h4&gt;
&lt;p&gt;When you use a custom &lt;code&gt;fetch&lt;/code&gt; script to send files, you're just sending raw text. The server has no idea where &lt;code&gt;convex/server&lt;/code&gt; is. &lt;/p&gt;
&lt;p&gt;&lt;strong&gt;The CLI is smarter.&lt;/strong&gt; It uses &lt;code&gt;esbuild&lt;/code&gt; to &quot;bundle&quot; 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.&lt;/p&gt;
&lt;hr&gt;
&lt;h3 id=&quot;5-pro-tip-automate-everything&quot;&gt;5. Pro Tip: Automate Everything&lt;/h3&gt;
&lt;p&gt;Don't type those long variables every time. Add a script to your &lt;code&gt;convex/package.json&lt;/code&gt;:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-json&quot;&gt;&quot;scripts&quot;: {
  &quot;deploy&quot;: &quot;CONVEX_SELF_HOSTED_URL=... CONVEX_SELF_HOSTED_ADMIN_KEY=... npx convex deploy --typecheck disable&quot;
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Now, all it takes is a simple:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;npm run deploy
&lt;/code&gt;&lt;/pre&gt;
&lt;hr&gt;
&lt;h3 id=&quot;troubleshooting-common-gotchas-&quot;&gt;Troubleshooting common &quot;Gotchas&quot;&lt;/h3&gt;
&lt;h4 id=&quot;-relative-import-path-convex-server-not-found-&quot;&gt;&quot;Relative import path 'convex/server' not found&quot;&lt;/h4&gt;
&lt;p&gt;If you see this, you likely bypassed the CLI. Always use &lt;code&gt;npx convex deploy&lt;/code&gt; so the bundler can do its job!&lt;/p&gt;
&lt;h4 id=&quot;-badadminkey-&quot;&gt;&quot;BadAdminKey&quot;&lt;/h4&gt;
&lt;p&gt;Double-check your key. Most people forget the &lt;code&gt;convex-self-hosted|&lt;/code&gt; prefix. Without it, the server will reject your request every time.&lt;/p&gt;
&lt;h4 id=&quot;missing-generated-files-in-your-frontend&quot;&gt;Missing &lt;code&gt;_generated&lt;/code&gt; files in your frontend&lt;/h4&gt;
&lt;p&gt;Run &lt;code&gt;npx convex codegen&lt;/code&gt; while your &lt;code&gt;CONVEX_SELF_HOSTED_URL&lt;/code&gt; is set to update your local TypeScript types to match what you just deployed.&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;Happy hosting! Your Convex backend is now truly yours.&lt;/p&gt;
</description>
<category>Articles</category>
<guid isPermaLink="true">https://coderlegion.com/24030/mastering-self-hosted-convex-on-dokploy-a-complete-deployment-guide</guid>
<pubDate>Mon, 03 Aug 2026 07:41:58 +0000</pubDate>
</item>
</channel>
</rss>