#where to get CONVEX_DEPLOYMENT env variable

37 messages · Page 1 of 1 (latest)

undone moon
#

Im currently trying to set up better auth with nextjs following this guide: https://convex-better-auth.netlify.app/#install-component

there are some environment variables here which im not sure what to put because it seems like they're autogenerated by logging into convex cloud

how do i log in to my self-hosted convex instance?
for example to get stuff like CONVEX_DEPLOYMENT

# Deployment used by `npx convex dev`
CONVEX_DEPLOYMENT=dev:adjective-animal-123 # team: team-name, project: project-name

which shows up on the convex dashboard if you use the cloud version, but doesn't show up for self-hosted versions (i use coolify btw)

undone flameBOT
#

Hi @undone moon. I'm kapa.ai, your friendly support bot. I will try to answer your question by searching through the knowledge base. :wave:

#

For self-hosted Convex deployments, the environment variable CONVEX_DEPLOYMENT is not used or required in the same way as with Convex Cloud. In the cloud, CONVEX_DEPLOYMENT is automatically generated and managed by the Convex CLI and dashboard, but for self-hosted setups, you instead authenticate and connect using the following environment variables:

  • CONVEX_SELF_HOSTED_URL: The URL where your self-hosted Convex backend is accessible.
  • CONVEX_SELF_HOSTED_ADMIN_KEY: The admin key you generate (e.g., with ./generate_admin_key.sh in your Docker or Fly.io setup).

You should set these in your .env.local file for local development, or in your CI/CD environment for deployments. Here’s an example:

CONVEX_SELF_HOSTED_URL='<https://your-backend-url'>
CONVEX_SELF_HOSTED_ADMIN_KEY='<your admin key>'

You do not need to set CONVEX_DEPLOYMENT for self-hosted Convex. The CLI and dashboard for self-hosted Convex use the URL and admin key for authentication and deployment actions instead. Attempting to mix cloud and self-hosted environment variables (like CONVEX_DEPLOYMENT and CONVEX_SELF_HOSTED_URL) will not work and is intentionally prevented to avoid confusion or accidental deployments to the wrong environment.

For your frontend (e.g., Next.js), you should set the deployment URL as required by your framework, such as:

NEXT_PUBLIC_CONVEX_URL='<https://your-backend-url'>

For more details, see the self-hosted Convex documentation and workflow guides:

#

If you need to generate the admin key or set up your self-hosted instance, follow the instructions for your chosen hosting method (Docker Compose, Fly.io, etc.) as described in the linked guides above.

Note: you can ask me a follow up question by @ mentioning me again :speech_balloon:

#

@undone moon Kapa.ai is still learning and improving, please let me know how I did by reacting below.

undone moon
#

NEXT_PUBLIC_CONVEX_URL='<https://your-backend-url'>
by this do you mean the backend convex? or the url of the nextjs app itself? @undone flame

undone flameBOT
#

Let me check the knowledge base for you again. One moment! :books:

#

You should set NEXT_PUBLIC_CONVEX_URL to the URL of your Convex backend, not your Next.js app.

This URL is where your frontend (Next.js) will connect to your self-hosted Convex backend. For example, if you are running Convex on your own server and have set up routing so that <https://api.my-domain.com> forwards to your Convex backend (port 3210), then:

NEXT_PUBLIC_CONVEX_URL='<https://api.my-domain.com'>

This is confirmed in the Convex documentation for both cloud and self-hosted setups. The environment variable should point to the Convex deployment URL, which is the backend, not your frontend app:

When connecting to your backend it's important to correctly configure the deployment URL.
...
Next.js requires them to begin with NEXT_PUBLIC_, so NEXT_PUBLIC_CONVEX_URL is a good name.
...
The URL can be hardcoded, but it's convenient to use an environment variable to determine which deployment the client should connect to.
...
import { ConvexProvider, ConvexReactClient } from "convex/react";
const convex = new ConvexReactClient(process.env.NEXT_PUBLIC_CONVEX_URL);

Client > React: Configuring Deployment URL

For self-hosted Convex, this URL is wherever your Convex backend is accessible from your frontend app, not the URL of your Next.js app itself.

Note: you can ask me a follow up question by @ mentioning me again :speech_balloon:

#

@undone moon Kapa.ai is still learning and improving, please let me know how I did by reacting below.

undone moon
#

NEXT_PUBLIC_CONVEX_URL='<https://your-backend-url'>
by this do you mean the backend convex? or the url of the nextjs app itself? @undone flame

undone flameBOT
#

Let me check the knowledge base for you again. One moment! :books:

#

You should set NEXT_PUBLIC_CONVEX_URL to the URL of your Convex backend, not your Next.js app.

This is the URL where your frontend (Next.js) will connect to your self-hosted Convex backend. For example, if your Convex backend is accessible at <https://api.my-domain.com,> then your .env.local should contain:

NEXT_PUBLIC_CONVEX_URL='<https://api.my-domain.com'>

This is confirmed in the Convex documentation:

The only difference in having your frontend talk to the self-hosted backend is to set the right environment variable so the frontend client points to the cloud-equivalent URL. For instance, for a Vite app with a backend deployed to [https://example-project.fly.dev](https://example-project.fly.dev/):

VITE_CONVEX_URL="<<https://example-project.fly.dev>">

And ensure your Vite code loads that environment variable:

const convex = new ConvexReactClient(import.meta.env.VITE_CONVEX_URL as string);

Stack: Self-hosted development workflow

For Next.js, the variable should be named NEXT_PUBLIC_CONVEX_URL, and it should point to your Convex backend, not your Next.js app itself Configuring Deployment URL.

Note: you can ask me a follow up question by @ mentioning me again :speech_balloon:

#

@undone moon Kapa.ai is still learning and improving, please let me know how I did by reacting below.

undone moon
#

@undone flame

i deloymed my self hosted convex using coolify with
it has two generated urls/services:
https://backend-numbershere.example.com:3210 and https://convex-numbershere.example.com:6791 (frontend dashboard)

what do i use for these environment variables:
NEXT_PUBLIC_CONVEX_URL, NEXT_PUBLIC_CONVEX_SITE_URL, CONVEX_SELF_HOSTED_URL

undone flameBOT
#

Let me check the knowledge base for you again. One moment! :books:

#

Based on your Coolify deployment, here’s how you should set your environment variables:

  • NEXT_PUBLIC_CONVEX_URL:
    Set this to the URL of your Convex backend API (port 3210).

    NEXT_PUBLIC_CONVEX_URL='<https://backend-numbershere.example.com:3210'>
    
  • NEXT_PUBLIC_CONVEX_SITE_URL:
    If your app uses HTTP Actions (e.g., webhooks), set this to the URL serving HTTP actions (typically port 3211).
    However, in your setup, you only mentioned ports 3210 (backend) and 6791 (dashboard). If you have HTTP actions exposed, use that URL (e.g., <https://backend-numbershere.example.com:3211>).
    If not using HTTP actions, you may omit this or leave it unset.
    See Stack: Docker containers on a remote server.

  • CONVEX_SELF_HOSTED_URL:
    This should also be set to your Convex backend API URL (port 3210).

    CONVEX_SELF_HOSTED_URL='<https://backend-numbershere.example.com:3210'>
    

Note:

  • The dashboard URL (<https://convex-numbershere.example.com:6791>) is for admin access and should not be used for these environment variables.
  • You will also need to set CONVEX_SELF_HOSTED_ADMIN_KEY with the admin key you generated for CLI access and deployments.

References:

#

If you expose HTTP actions on a different port (commonly 3211), set NEXT_PUBLIC_CONVEX_SITE_URL to that URL. If not, you can leave it unset.

Note: you can ask me a follow up question by @ mentioning me again :speech_balloon:

#

@undone moon Kapa.ai is still learning and improving, please let me know how I did by reacting below.

undone moon
#

@undone flame
why is it that for my self hosted instance, under the dashboard (frontend convex dashboard) > settings > URL & deploy key, both Deployment URL and HTTP Actions URL are the same and they share the same url as the frontend convex dashboard
whereas for the cloud instance, the deployment and http actions urls are different (ending in .cloud for the deployment while ending in .site for the http actions)

what url should i really use for HTTP actions for the NEXT_PUBLIC_CONVEX_SITE_URL?

and why am i gettings CORS errors for my self-hosted instance but not for the cloud instance?

undone flameBOT
#

Let me check the knowledge base for you again. One moment! :books:

#

Great questions! Here’s what the knowledge sources say:

1. Why are the URLs the same for self-hosted, but different for cloud?

In Convex Cloud, the deployment URL (for queries/mutations) ends in .cloud and the HTTP Actions URL ends in .site. These are two separate endpoints managed by Convex Cloud infrastructure.

In self-hosted Convex, you are responsible for routing and exposing the backend services. By default, the backend (API) runs on port 3210, HTTP Actions on 3211, and the dashboard on 6791. However, if you only expose one port (e.g., just 3210), or if your reverse proxy routes everything through a single domain/port, then the dashboard may show the same URL for both deployment and HTTP Actions. This is a result of your own routing setup, not a Convex requirement. The dashboard simply reports what is configured and accessible.

Set up routing to forward requests from your domain to these ports. For example:

  • <https://api.my-domain.com> forwards to <http://localhost:3210>
  • <https://my-domain.com> forwards to <http://localhost:3211>
  • <https://dashboard.my-domain.com> forwards to <http://localhost:6791>

Self-hosted: Backend hosting on your own infrastructure

If you have not set up a separate route for HTTP Actions (port 3211), both endpoints may appear as the same URL.

2. What URL should you use for NEXT_PUBLIC_CONVEX_SITE_URL?

You should use the URL that points to your HTTP Actions endpoint (typically port 3211). If you have not exposed port 3211 separately, and both your API and HTTP Actions are routed through the same URL, then you must use that shared URL for both NEXT_PUBLIC_CONVEX_URL and NEXT_PUBLIC_CONVEX_SITE_URL.

#

If you want to follow the cloud pattern (separate URLs for API and HTTP Actions), you need to expose both ports and route them to different subdomains or paths.

  • CONVEX_CLOUD_ORIGIN is where you host the backend that typically talks to the 3210 port...
  • CONVEX_SITE_ORIGIN is for the 3211 port that hosts your http action endpoints...

Stack: Docker containers on a remote server

3. Why are you getting CORS errors on self-hosted but not on cloud?

Convex Cloud automatically handles CORS for you. In self-hosted setups, you must configure CORS headers yourself in your HTTP Actions. If you don’t, browsers will block cross-origin requests.

If you see "CORS error" or messages in the browser console like
Access to fetch at '...' from origin '...' has been blocked by CORS policy, you likely need to configure CORS headers and potentially add a handler for the pre-flight OPTIONS request. See this section below.

Functions > HTTP Actions > Debugging

You can add CORS headers in your HTTP Actions like this:

return new Response(null, {
  status: 200,
  headers: {
    "Access-Control-Allow-Origin": "<https://your-frontend-domain.com",>
    "Access-Control-Allow-Methods": "POST, GET, OPTIONS",
    "Access-Control-Allow-Headers": "Content-Type, Authorization",
  },
});

And handle preflight OPTIONS requests as shown in the docs.


#

Summary:

  • The URLs are the same in your dashboard because of your routing setup.
  • Use the HTTP Actions endpoint (ideally on port 3211) for NEXT_PUBLIC_CONVEX_SITE_URL.
  • You must manually configure CORS headers in self-hosted Convex, unlike the cloud version.

If you need to expose HTTP Actions separately, update your reverse proxy or Coolify config to route port 3211 to a different subdomain or path.

Note: you can ask me a follow up question by @ mentioning me again :speech_balloon:

#

@undone moon Kapa.ai is still learning and improving, please let me know how I did by reacting below.

undone moon
#

@undone flame
how do i configure cors on my self hosted convex inside coolify

undone flameBOT
#

Let me check the knowledge base for you again. One moment! :books:

#

To configure CORS on your self-hosted Convex instance (including when running inside Coolify), you need to add the appropriate CORS headers in your HTTP actions. Convex does not automatically handle CORS for self-hosted deployments, so you must do this manually in your convex/http.ts file.

Here’s a standard pattern from the Convex documentation:

import { httpRouter } from "convex/server";
import { httpAction } from "./_generated/server";

const http = httpRouter();

// Example POST endpoint with CORS headers
http.route({
  path: "/your-endpoint",
  method: "POST",
  handler: httpAction(async (ctx, request) => {
    // ...your logic...
    return new Response(null, {
      status: 200,
      headers: new Headers({
        "Access-Control-Allow-Origin": process.env.CLIENT_ORIGIN!, // e.g. <https://your-frontend.com>
        Vary: "origin",
      }),
    });
  }),
});

// Pre-flight OPTIONS handler
http.route({
  path: "/your-endpoint",
  method: "OPTIONS",
  handler: httpAction(async (_, request) => {
    const headers = request.headers;
    if (
      headers.get("Origin") !== null &&
      headers.get("Access-Control-Request-Method") !== null &&
      headers.get("Access-Control-Request-Headers") !== null
    ) {
      return new Response(null, {
        headers: new Headers({
          "Access-Control-Allow-Origin": process.env.CLIENT_ORIGIN!,
          "Access-Control-Allow-Methods": "POST",
          "Access-Control-Allow-Headers": "Content-Type, Digest, Authorization",
          "Access-Control-Max-Age": "86400",
        }),
      });
    } else {
      return new Response();
    }
  }),
});

export default http;
#
  • Set CLIENT_ORIGIN in your environment variables to your frontend’s URL (e.g., <https://your-frontend.com>).
  • Make sure to handle both the actual request and the preflight OPTIONS request with the correct headers.

Why is this needed?
Convex Cloud handles CORS for you, but in self-hosted setups (including Coolify), you must add these headers yourself to allow browsers to make cross-origin requests to your backend Functions > HTTP Actions > Common patterns > CORS.

If you have multiple endpoints, repeat this pattern for each, or use a helper to add CORS headers consistently.

If you want to simplify CORS handling, you can also use the corsRouter helper from convex-helpers as described in the knowledge sources Stack: Using a library.

If you need more advanced CORS configuration (e.g., dynamic origins, credentials), you can adjust the headers accordingly Stack: Implementing CORS on your own.


In summary:
You must manually add CORS headers in your HTTP actions in your Convex project when self-hosting (including on Coolify). There is no automatic CORS configuration for self-hosted Convex Functions > HTTP Actions > Debugging.

Note: you can ask me a follow up question by @ mentioning me again :speech_balloon:

#

@undone moon Kapa.ai is still learning and improving, please let me know how I did by reacting below.

undone moon
#

@undone flame

in general, because bettere-auth handles the auth endpoints, how do i capture such that all of those endpoints have CORS

undone flameBOT
#

Let me check the knowledge base for you again. One moment! :books:

#

When using Better Auth with Convex, you can ensure all auth endpoints have CORS enabled by passing the cors: true option to the registerRoutes method when mounting Better Auth route handlers. This will automatically add CORS handling to all the Better Auth endpoints registered on your Convex deployment.

Here’s how you do it in your convex/http.ts:

import { httpRouter } from 'convex/server'
import { betterAuthComponent } from './auth'
import { createAuth } from '../src/lib/auth'

const http = httpRouter()
// { cors: true } is required for client side frameworks
betterAuthComponent.registerRoutes(http, createAuth, { cors: true })
export default http

This approach is specifically recommended for client-side frameworks or when using the crossDomain plugin. If you are using a full stack framework (like Next.js with server-side auth), you typically do not need to enable CORS here Mount handlers Migrate 0.6 → 0.7.

For React or any app that is only using client side auth (if your app uses the crossDomain plugin, this applies), you will need to pass the cors: true option.

This will ensure all Better Auth endpoints registered via registerRoutes have the necessary CORS headers.

Note: you can ask me a follow up question by @ mentioning me again :speech_balloon:

#

@undone moon Kapa.ai is still learning and improving, please let me know how I did by reacting below.

undone moon
#

@undone flame i already have cors set to true and i still get those cors errors

undone flameBOT
#

Let me check the knowledge base for you again. One moment! :books:

#

If you have already set cors: true in betterAuthComponent.registerRoutes and are still getting CORS errors, here are some possible reasons and troubleshooting steps based on the knowledge sources:

  1. Allowed Origins:
    In Better Auth v0.7+, the allowedOrigins option for registerRoutes has been removed. CORS now defers entirely to Better Auth's trustedOrigins option, which you set when creating your Better Auth instance. Make sure that the trustedOrigins array in your createAuth function includes the exact origin (protocol, domain, and port) of your frontend app. For example:

    const siteUrl = "<http://localhost:5173";>
    export const createAuth = (ctx: GenericCtx) =>
      betterAuth({
        trustedOrigins: [siteUrl],
        // ...other options
      });
    

    Migrate 0.6 → 0.7

  2. CrossDomain Plugin:
    If you are using a client-side framework, ensure you have the crossDomain plugin enabled and configured with the correct siteUrl:

    plugins: [
      convex(),
      crossDomain({ siteUrl }),
    ],
    

    Initialize Better Auth

  3. Frontend Environment Variables:
    Double-check that your frontend is using the correct environment variable for the Convex site URL (e.g., NEXT_PUBLIC_CONVEX_SITE_URL) and that it matches the siteUrl and trustedOrigins you set in your backend.

  4. Browser Cache:
    Sometimes, CORS errors can persist due to cached preflight responses. Try clearing your browser cache or using a private/incognito window.

#
  1. Check Network Tab and Error Details:
    Use your browser's developer tools to inspect the failing network request. Look for the exact CORS error message and compare the Origin header in the request with what you have in trustedOrigins.

  2. Self-hosted Routing:
    If you are self-hosting, ensure your reverse proxy or Coolify setup is not interfering with headers or routing. The backend URL you expose must match what your frontend expects.

If you have confirmed all of the above and still see CORS errors, the knowledge sources do not provide further troubleshooting steps. In that case, you may want to open a GitHub issue or ask for help on Discord, as suggested in the Better Auth documentation.


Summary:

  • Ensure trustedOrigins in your Better Auth config matches your frontend origin exactly.
  • Use the crossDomain plugin with the correct siteUrl.
  • Double-check your environment variables and frontend config.
  • Inspect the network request for more details.

If all settings are correct and the error persists, further debugging may be needed beyond what is covered in the knowledge sources.

Note: you can ask me a follow up question by @ mentioning me again :speech_balloon: