Skip to content
Esc
navigateopen⌘Jpreview
Dashboard
On this page

Self-host SuperTokens

Deploy SuperTokens Core privately with Docker or on a VM and connect PostgreSQL for persistent storage.

See how you can run SuperTokens in your own infrastructure.


Overview

One of the main features of SuperTokens is that you can run it using your own resources. This way you have full control over the authentication data and you can scale based on your needs.

Before you start

To deploy the Core Service you must configure two things: the actual API and the database.

  • The core service can be deployed using a Docker image or directly inside your VM.
  • The supported database is PostgreSQL. Confirm the supported version range for the exact Core/database-plugin release you select.

The exact PostgreSQL support range and current Core/database artifact mapping are not established by this guide. Verify both for the immutable release selected for production.

Steps

1. Install SuperTokens core

With Docker

Do not use an untagged image or latest. Select and verify an exact supported Core image, pin it by digest, and set it as SUPERTOKENS_IMAGE. For a local-only in-memory test, bind Core to 127.0.0.1:

: "${SUPERTOKENS_IMAGE:?Set an immutable image reference such as repository:version@sha256:digest}"
docker run -p 127.0.0.1:3567:3567 -d "$SUPERTOKENS_IMAGE"

Omitting PostgreSQL configuration starts the container with an in-memory database. Use this only for testing.

Without Docker

1. Download SuperTokens

Visit the open source download page

Click on the Binary tab

Choose your database

Download the SuperTokens zip file for your OS

After downloading, verify the release checksum or signature and extract the archive. You should see a folder named supertokens.

2. Install SuperTokens
# sudo is required so that the supertokens
# command can be added to your PATH variable.

cd supertokens
sudo ./install

cd supertokens
./install

Rem run as an Administrator. This is required so that the supertokens
Rem command can be added to your PATH.

cd supertokens
install.bat
3. Start the core service

Running the following command starts the service.

supertokens start [--host=...] [--port=...]
  • The above command starts the Core service using the configured database.
  • To see all available options please run supertokens start --help

2. Test that the service is running

Open a browser and visit http://localhost:3567/hello. If you see a page that says Hello back, then the container started successfully!

If you are having issues with starting the docker image, please feel free to reach out over email or via Discord.

3. Connect the backend SDK with SuperTokens

  • The default port for SuperTokens is 3567. Keep it private. For local testing, bind it only to 127.0.0.1, for example -p 127.0.0.1:8080:3567.
  • The connection info goes in the supertokens object in the init function on your backend:
import supertokens from "supertokens-node";

const apiKey = process.env.SUPERTOKENS_API_KEY;
if (apiKey === undefined || apiKey.length === 0) {
  throw new Error("SUPERTOKENS_API_KEY is required");
}

supertokens.init({
  supertokens: {
    connectionURI: "http://localhost:3567",
    apiKey,
  },
  appInfo: {
    apiDomain: "...",
    appName: "...",
    websiteDomain: "...",
  },
  recipeList: [],
});
import (
	"os"

	"github.com/supertokens/supertokens-golang/supertokens"
)

func main() {
	apiKey := os.Getenv("SUPERTOKENS_API_KEY")
	if apiKey == "" {
		panic("SUPERTOKENS_API_KEY is required")
	}
	supertokens.Init(supertokens.TypeInput{
		Supertokens: &supertokens.ConnectionInfo{
			ConnectionURI: "http://localhost:3567",
			APIKey:        apiKey,
		},
	})
}
import os

from supertokens_python import init, InputAppInfo, SupertokensConfig

api_key = os.environ["SUPERTOKENS_API_KEY"]
if not api_key:
    raise RuntimeError("SUPERTOKENS_API_KEY is required")

init(
    app_info=InputAppInfo(api_domain="...", app_name="...", website_domain="..."),
    supertokens_config=SupertokensConfig(
        connection_uri='http://localhost:3567',
        api_key=api_key
    ),
    framework='...',
    recipe_list=[
      #...
   ]
)

4. Set up the database

4.1 Create a database (optional)

CREATE DATABASE supertokens;

You can skip this step if you want SuperTokens to write to your own database. In this case, you need to provide your database’s name as shown in the step below.

4.2 Connect SuperTokens to your database

With Docker

: "${SUPERTOKENS_IMAGE:?Set an immutable Core image reference}"
: "${SUPERTOKENS_API_KEY:?Set a generated Core API key}"
docker run \
    --network app-network \
    -e POSTGRESQL_CONNECTION_URI="postgresql://username:pass@host/dbName" \
    -e API_KEYS="$SUPERTOKENS_API_KEY" \
    -d "$SUPERTOKENS_IMAGE"

# OR

docker run \
    --network app-network \
    -e POSTGRESQL_USER="username" \
    -e POSTGRESQL_PASSWORD="password" \
	-e POSTGRESQL_HOST="host" \
	-e POSTGRESQL_PORT="5432" \
    -e POSTGRESQL_DATABASE_NAME="supertokens" \
    -e API_KEYS="$SUPERTOKENS_API_KEY" \
    -d "$SUPERTOKENS_IMAGE"
Without Docker
# You need to add the following to the config.yaml file.
# The file path can be found by running the "supertokens --help" command

postgresql_connection_uri: "postgresql://username:pass@host/dbName"

# OR

postgresql_user: "username"

postgresql_password: "password"

postgresql_host: "host"

postgresql_port: "5432"

postgresql_database_name: "supertokens"

You can also provide the table schema by setting the postgresql_table_schema option.

4.3 Test the connection

Start the exact Core release against a staging copy of the database and require startup/migration success. Then exercise an authenticated SDK operation. A query against one table does not prove that every required migration was applied.

4.4 Rename database tables (optional)

You can add a prefix to all table names that SuperTokens manages. This way, all will be renamed in a way that has no clashes with your tables.

For example, two tables created by SuperTokens have the names emailpassword_users and thirdparty_users. If you add a prefix to them (something like "my_prefix"), then the tables become my_prefix_emailpassword_users and my_prefix_thirdparty_users.

docker run \
    --network app-network \
    -e POSTGRESQL_TABLE_NAMES_PREFIX="my_prefix" \
    -e API_KEYS="$SUPERTOKENS_API_KEY" \
    -d "$SUPERTOKENS_IMAGE"
# You need to add the following to the config.yaml file.
# The file path can be found by running the "supertokens --help" command

postgresql_table_names_prefix: "my_prefix"

5. Add license keys

To access some features in your self-hosted service you must use license keys. You can sign up on SuperTokens to receive one.

Once you have the license key you need to manually add it to your SuperTokens Core Instance. To do this you have to call the Core API with the following request:

curl --location --request PUT "${CORE_API_ENDPOINT:?Set the private Core endpoint}/ee/license" \
     --header 'Content-Type: application/json' \
     --header "api-key: ${SUPERTOKENS_API_KEY:?Set the Core API key}" \
     --data-raw "{ \"licenseKey\": \"${SUPERTOKENS_LICENSE_KEY:?Set the license key}\" }"

Secure the core

The SuperTokens Core exposes administrative operations over its API — creating and updating users, issuing password-reset and passwordless codes, managing tenants, and more. By design these are available to the connecting backend, because the Core has no direct channel to your frontend and relies on your backend to mediate every request and to deliver codes and tokens to end users.

This trust model means the Core must be treated like your database: reachable only by your own backend, never by untrusted clients.

  • Isolate the network. Run the Core on a private network or subnet that only your backend can reach. This is the primary protection and applies regardless of any other setting.
  • Set an API key. No API key exists by default, so any caller that can reach an unprotected Core can perform administrative operations. Configure a generated API key as defense in depth. Core supports multiple keys for rotation, but these are not per-tenant authorization credentials and do not replace network isolation.
  • Restrict by IP and use TLS. Limit access with firewall/security-group rules and, optionally, Core’s IP allow/deny configuration. Terminate TLS/SSL at a trusted proxy or load balancer.
  • Enforce tenant scoping in your backend. For session-authenticated requests restricted to a specific tenant, verify the session and check that its tenant matches the required tenant. Authorize access to tenant-specific resources in your backend; do not rely on the URL alone.

API reference

API schema and response details