---
title: Self-host SuperTokens
description: Run SuperTokens on your infrastructure, control authentication data, and scale as needed.
sidebar:
  order: 1
  hidden: true
---

## Overview

The following tutorial shows you how to self-host legacy SuperTokens Core 10.x.
Since version `11.0.0`, SuperTokens Core no longer supports MySQL as a database.

## Before you start

To deploy the Core Service you must configure two things: the actual API and the database.
- You can use either **PostgreSQL** or **MySQL** as a data source for the Core service.
- Deploy the core service with **Docker** or directly inside your VM.
- The archived guide recommended MySQL 8.0.11 and PostgreSQL 13.0. Released source does not establish these as exact lower bounds; verify the database version against your selected Core 10.x and database-plugin release.

:::danger
SuperTokens Core is a trusted backend component with privileged user, session, and tenant APIs. Run Core and its database
on private networks reachable only by trusted backend services. Never expose either directly to browsers or other
clients you do not trust. Core v10 has no API key by default. Configure a generated API key, restrict ingress, and terminate TLS
at a trusted reverse proxy as defense in depth. A shared API key does not replace backend tenant authorization.
:::


## Steps

:::warning

This guide is only relevant if you are using a legacy **SuperTokens Core 10.x** release.
**MySQL** is no longer available as a storage option starting with the **11.0.0** version.

:::


### 1. Install SuperTokens core

#### With Docker

<CodeGroup group="database">
<Tab title="Mysql" value="mysql">
```bash
docker run -p 127.0.0.1:3567:3567 -d supertokens/supertokens-mysql:10.1
```
</Tab>
<Tab title="Postgresql" value="postgresql">
```bash
docker run -p 127.0.0.1:3567:3567 -d supertokens/supertokens-postgresql:10.1
```
</Tab>
</CodeGroup>

<DependentContent passive group="database">
<ContentOption title="Mysql" value="mysql">
- The above command starts the container with an in-memory database. This means you **do not need to connect it to MySQL to test out SuperTokens**.
</ContentOption>
<ContentOption title="Postgresql" value="postgresql">
- The above command starts the container with an in-memory database. This means you **do not need to connect it to PostgreSQL to test out SuperTokens**.
</ContentOption>
</DependentContent>

#### Without Docker

##### 1. Download SuperTokens

1. **Visit the open source download page**

    Open the [open source download page](https://SuperTokens.com/use-oss).

2. **Click on the Binary tab**

3. **Choose your database**

4. **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

<CodeGroup group="operating-system">
<Tab title="Linux" value="linux">
```bash
# sudo is required so that the supertokens
# command can be added to your PATH variable.

cd supertokens
sudo ./install
```
</Tab>
<Tab title="Mac" value="mac">
```bash

cd supertokens
./install

```
</Tab>
<Tab title="Windows" value="windows">
```batch

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

cd supertokens
install.bat

```
</Tab>
</CodeGroup>

<DependentContent passive group="operating-system">
<ContentOption title="Mac" value="mac">
:::warning[You may get an error like `java cannot be opened because the developer cannot be verified`. To solve this, visit System Preferences > Security & Privacy > General Tab, and then click on the Allow button at the bottom. Then retry the command above.]
:::
</ContentOption>
</DependentContent>

:::note[After installing, you can delete the downloaded folder as you no longer need it.]

Make any changes to the configuration in the `config.yaml` file in the installation directory, as specified in the output of the `supertokens --help` command.
:::

##### 3. Start the core service

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

:::info[Tip]
To stop the service, run the following command:
```bash
supertokens stop
```
:::


### 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](mailto:support@supertokens.com) or [via Discord](https://supertokens.com/discord).

:::tip
`/hello` performs a storage query in Core v10 and can be used as a basic readiness signal. It deliberately requires no API
key, so a successful response does not prove that protected APIs require authentication or that Core is safely isolated.
Pair it with authenticated application checks and database monitoring; do not expose Core merely to reach this endpoint.
:::


### 3. Connect the backend SDK with SuperTokens

- The default port 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:

<CodeGroup group="backend-language">
<Tab title="Node.js" value="nodejs">
```tsx
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: [],
});
```
</Tab>
<Tab title="Go" value="go">
```go
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,
		},
	})
}

```
</Tab>
<Tab title="Python" value="python">
```python check=false reason="Partial configuration example"
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=[
      #...
   ]
)
```
</Tab>
</CodeGroup>

:::info[Configure the same generated secret in Core and every backend]
Generate a key with `openssl rand -hex 32`, store it in a secret manager, and inject it as Core's `API_KEYS` and the
`SUPERTOKENS_API_KEY` used by the backend. Never bake it into source or an image. Core v10 keys must be at least 20 characters and
contain only alphanumeric characters, `=`, or `-`.
:::

### 4. Set up the database


#### 4.1 Create a database (optional)

<CodeGroup group="database">
<Tab title="Mysql" value="mysql">
```sql
CREATE DATABASE SuperTokens;
```
</Tab>
<Tab title="Postgresql" value="postgresql">
```sql
CREATE DATABASE supertokens;
```
</Tab>
</CodeGroup>

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

<DependentContent passive group="database">
<ContentOption title="Mysql" value="mysql">
:::warning
Inside a container, `localhost` refers to that container. Put Core and MySQL on the same private Docker/VPC network and
restrict the MySQL bind address, grants, firewall, and security groups so that only Core can connect. Do not publish port
3306 or use a public database address.
:::
</ContentOption>
<ContentOption title="Postgresql" value="postgresql">
:::warning
Inside a container, `localhost` refers to that container. Put Core and PostgreSQL on the same private Docker/VPC network
and restrict `listen_addresses`, `pg_hba.conf`, firewall, and security groups so that only Core can connect. Do not publish
port 5432 or use a public database address.
:::
</ContentOption>
</DependentContent>

<CodeGroup group="database">
<Tab title="Mysql" value="mysql">
```bash

: "${SUPERTOKENS_API_KEY:?Set a generated Core API key}"
docker run \
    --network app-network \
    -e MYSQL_CONNECTION_URI="mysql://username:pass@host/dbName" \
    -e API_KEYS="$SUPERTOKENS_API_KEY" \
    -d supertokens/supertokens-mysql:10.1

# OR

docker run \
    --network app-network \
    -e MYSQL_USER="username" \
    -e MYSQL_PASSWORD="password" \
	-e MYSQL_HOST="host" \
	-e MYSQL_PORT="3306" \
    -e MYSQL_DATABASE_NAME="supertokens" \
    -e API_KEYS="$SUPERTOKENS_API_KEY" \
    -d supertokens/supertokens-mysql:10.1
```
</Tab>
<Tab title="Postgresql" value="postgresql">
```bash

: "${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/supertokens-postgresql:10.1

# 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/supertokens-postgresql:10.1
```
</Tab>
</CodeGroup>

<DependentContent passive group="database">
<ContentOption title="Postgresql" value="postgresql">
:::tip[You can also provide the table schema by setting the `POSTGRESQL_TABLE_SCHEMA` option.]
:::
</ContentOption>
</DependentContent>

##### Without Docker


<CodeGroup group="database">
<Tab title="Mysql" value="mysql">
```yaml
# You need to add the following to the config.yaml file.
# The file path can be found by running the "supertokens --help" command

mysql_connection_uri: "mysql://username:pass@host/dbName"

# OR

mysql_user: "username"

mysql_password: "password"

mysql_host: "host"

mysql_port: 3306

mysql_database_name: "supertokens"
```
</Tab>
<Tab title="Postgresql" value="postgresql">
```yaml
# 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"
```
</Tab>
</CodeGroup>

<DependentContent passive group="database">
<ContentOption title="Postgresql" value="postgresql">
You can also provide the table schema by setting the `postgresql_table_schema` option.
</ContentOption>
</DependentContent>

:::info
Core creates and migrates its required tables automatically when the database principal has DDL permission. The previous
manual SQL on this page was incomplete across Core 10.x releases and has been removed. If the runtime principal cannot
perform DDL, use a schema or migration artifact generated and tested for the exact Core 10.x release you deploy; do not
reuse a schema copied from another patch or minor release.
:::


#### 4.3 Test the connection

Start the exact Core 10.x release against a staging copy of the database and require startup/migration success. Then
exercise an authenticated SDK operation. Querying one table does not prove that all release-matched migrations exist.


#### 4.4 Rename database tables (optional)

:::warning[If you already have tables created by SuperTokens, and then you rename them, SuperTokens creates new tables. Please be sure to migrate the data from the existing one to the new one.]
:::

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`.

##### For MySQL

<CodeGroup group="docker">
<Tab title="With Docker" value="with-docker">
```bash
docker run \
    --network app-network \
    -e MYSQL_TABLE_NAMES_PREFIX="my_prefix" \
    -e API_KEYS="$SUPERTOKENS_API_KEY" \
    -d supertokens/supertokens-mysql:10.1
```
</Tab>
<Tab title="Without Docker" value="without-docker">
```yaml
# You need to add the following to the config.yaml file.
# The file path can be found by running the "supertokens --help" command

mysql_table_names_prefix: "my_prefix"
```
</Tab>
</CodeGroup>

##### For PostgreSQL

<CodeGroup group="docker">
<Tab title="With Docker" value="with-docker">
```bash
docker run \
    --network app-network \
    -e POSTGRESQL_TABLE_NAMES_PREFIX="my_prefix" \
    -e API_KEYS="$SUPERTOKENS_API_KEY" \
    -d supertokens/supertokens-postgresql:10.1
```
</Tab>
<Tab title="Without Docker" value="without-docker">
```yaml
# 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"
```
</Tab>
</CodeGroup>


### 5. Add license keys

Some Core v10 enterprise features require a license key. Confirm with SuperTokens that your plan and key apply to the
exact legacy release; this archived page does not establish the current acquisition process.

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:

```bash title="Add License Key"
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}\" }"

```

## Select immutable legacy artifacts

The Core images on this page are pinned to the released v10.1 image line so that Docker does not silently select a newer
Core major. For a production archive, resolve those tags to registry digests and record
`repository:10.1@sha256:<digest>` in deployment configuration. Pin the database image by digest from a version supported
by your verified Core v10/database-plugin tuple, scan all images, and promote unchanged digests between environments.

The archived guide does not establish an immutable MySQL/PostgreSQL image mapping or a maintained Helm-chart release.
Consequently, the old mutable Compose examples and deprecated Helm links have been removed. Confirm the database support
matrix and exact artifacts before treating this legacy guide as a reproducible production deployment.
