diff --git a/src/components/NavigationDocs.jsx b/src/components/NavigationDocs.jsx index aabb2bdbc..317c9287b 100644 --- a/src/components/NavigationDocs.jsx +++ b/src/components/NavigationDocs.jsx @@ -879,6 +879,10 @@ export const docsNavigation = [ title: 'External IdP to Embedded IdP', href: '/selfhosted/migration/external-to-embedded-idp', }, + { + title: 'MySQL to PostgreSQL', + href: '/selfhosted/migration/mysql-to-postgresql', + }, ], }, ], diff --git a/src/pages/selfhosted/environment-variables.mdx b/src/pages/selfhosted/environment-variables.mdx index 9bf985b1a..246e7d304 100644 --- a/src/pages/selfhosted/environment-variables.mdx +++ b/src/pages/selfhosted/environment-variables.mdx @@ -54,9 +54,9 @@ The default quickstart deployment uses the relay service's embedded STUN server. | Variable | Default | Description | |----------|---------|-------------| -| `NETBIRD_STORE_CONFIG_ENGINE` | `sqlite` | Store engine: `sqlite`, `postgres`, or `mysql` | +| `NETBIRD_STORE_CONFIG_ENGINE` | `sqlite` | Store engine: `sqlite`, `postgres`, or `mysql` (deprecated) | | `NETBIRD_STORE_ENGINE_POSTGRES_DSN` | - | PostgreSQL connection string | -| `NETBIRD_STORE_ENGINE_MYSQL_DSN` | - | MySQL connection string | +| `NETBIRD_STORE_ENGINE_MYSQL_DSN` | - | MySQL connection string. Deprecated, see [Migrate from MySQL to PostgreSQL](/selfhosted/migration/mysql-to-postgresql) | | `NETBIRD_DATASTORE_ENC_KEY` | Auto-generated | Encryption key for sensitive data | diff --git a/src/pages/selfhosted/maintenance/configuration-files.mdx b/src/pages/selfhosted/maintenance/configuration-files.mdx index e3c66a7b6..f3cc4e428 100644 --- a/src/pages/selfhosted/maintenance/configuration-files.mdx +++ b/src/pages/selfhosted/maintenance/configuration-files.mdx @@ -333,7 +333,7 @@ Configures the database backend for storing all NetBird management data includin - Database engine. Options: `sqlite`, `postgres`, `mysql`. Default: `sqlite`. + Database engine. Options: `sqlite`, `postgres`, `mysql`. Default: `sqlite`. `mysql` is deprecated, see [Migrate from MySQL to PostgreSQL](/selfhosted/migration/mysql-to-postgresql). Connection string for postgres or mysql engines. For postgres: `host=localhost user=netbird password=secret dbname=netbird port=5432`. Alternatively, use the `NETBIRD_STORE_ENGINE_POSTGRES_DSN` or `NETBIRD_STORE_ENGINE_MYSQL_DSN` environment variables. @@ -358,7 +358,7 @@ Configures the database backend for storing all NetBird management data includin |--------|---------|-------| | SQLite (default) | `/var/lib/netbird/` volume | File-based database stored in the `netbird_data` Docker volume. Zero configuration required, but does not support concurrent writes or running multiple management instances. Best for testing or small deployments. | | PostgreSQL | External database server | Recommended for production deployments. Supports concurrent access, enabling multiple management instances for high availability. | -| MySQL | External database server | Alternative to PostgreSQL for organizations that have standardized on MySQL/MariaDB. Provides similar benefits including concurrent access. | +| MySQL | External database server | Deprecated and will be removed in an upcoming release. See [Migrate from MySQL to PostgreSQL](/selfhosted/migration/mysql-to-postgresql). | For PostgreSQL or MySQL, set the connection string via the `server.store.dsn` field in `config.yaml` or environment variables on the `netbird-server` container. See [Using an External Database](#using-an-external-database) below. diff --git a/src/pages/selfhosted/migration/mysql-to-postgresql.mdx b/src/pages/selfhosted/migration/mysql-to-postgresql.mdx new file mode 100644 index 000000000..2e5b22d9d --- /dev/null +++ b/src/pages/selfhosted/migration/mysql-to-postgresql.mdx @@ -0,0 +1,131 @@ +import {Note} from "@/components/mdx" + +export const description = 'Move a self-hosted NetBird deployment from MySQL to PostgreSQL before MySQL support is removed.' + +# Migrate from MySQL to PostgreSQL + +MySQL support for the Management store is deprecated and will be removed in an upcoming release. This guide moves an existing MySQL deployment to PostgreSQL with the `netbird-mysql-migrate` tool. + +The tool copies the following into PostgreSQL: +- the Management store, from MySQL +- the activity events (`events.db`) and embedded IdP (`idp.db`) stores, from their SQLite files + +The tool only reads your MySQL database and doesn't change it. + +## Before You Begin + +- Upgrade NetBird to `vX.Y.Z` and start it once on MySQL, so the database schema is current. Use the tool from the same release. +- Prepare an empty PostgreSQL database. To run one in Docker, see [Set Up PostgreSQL](/selfhosted/maintenance/scaling/migrate-sqlite-to-postgresql#set-up-postgre-sql). +- Run the tool on a machine that can reach both MySQL and PostgreSQL. + +## Step 1: Get the Migration Tool + +```bash +VERSION=X.Y.Z # your NetBird version +curl -L -o netbird-mysql-migrate.tar.gz \ + https://github.com/netbirdio/netbird/releases/download/v${VERSION}/netbird-mysql-migrate_${VERSION}_linux_amd64.tar.gz +tar xzf netbird-mysql-migrate.tar.gz +chmod +x netbird-mysql-migrate +``` + +Available architectures: `linux_amd64`, `linux_arm64`, `linux_arm`. + +## Step 2: Stop NetBird and Back Up + +Stop the server and copy its data directory, which holds `events.db` and `idp.db`: + +```bash +docker compose stop netbird-server +mkdir backup +docker compose cp -a netbird-server:/var/lib/netbird/. backup/ +``` + +On the older multi-container setup, use the `management` service instead of `netbird-server`. + +Back up MySQL as well: + +```bash +mysqldump -h -u -p > backup/netbird-mysql.sql +``` + +## Step 3: Run the Migration + +```bash +./netbird-mysql-migrate \ + --mysql-dsn ':@tcp(:3306)/' \ + --postgres-dsn 'host= port=5432 user= password= dbname= sslmode=disable' \ + --events-db backup/events.db \ + --auth-db backup/idp.db +``` + +When it finishes, you see: + +``` +management: 1520 rows from 39 tables +activity: 8230 rows from 2 tables +auth: 41 rows from 12 tables +Done. Point the store, activity and auth store settings at Postgres before starting the server. +``` + + +- All stores go into the database given by `--postgres-dsn`. To keep the activity or auth store in a separate database, add `--events-postgres-dsn` or `--auth-postgres-dsn`. +- A missing `events.db` or `idp.db` is skipped. For example, deployments on an external IdP have no `idp.db`. +- MySQL timestamps are read as UTC. If your NetBird server runs in another time zone, for example with `TZ` set on the container, add `--mysql-timezone`, such as `--mysql-timezone Europe/Berlin`. +- The tool stops if the PostgreSQL database already holds NetBird data. + + +## Step 4: Point NetBird at PostgreSQL + +### Combined setup (config.yaml) + +Set all three stores to PostgreSQL in `config.yaml`, using the DSNs you migrated into: + +```yaml +server: + store: + engine: "postgres" + dsn: "host= port=5432 user= password= dbname= sslmode=disable" + activityStore: + engine: "postgres" + dsn: "host= port=5432 user= password= dbname= sslmode=disable" + authStore: + engine: "postgres" + dsn: "host= port=5432 user= password= dbname= sslmode=disable" +``` + +Remove any `NETBIRD_STORE_ENGINE_MYSQL_DSN` or `NB_STORE_ENGINE_MYSQL_DSN` variable from `docker-compose.yml`. + +### Older multi-container setup (management.json) + +In `management.json`, set the store engine and, if the file has an `EmbeddedIdP` section, its storage: + +```json +"StoreConfig": { + "Engine": "postgres" +}, +"EmbeddedIdP": { + "Storage": { + "Type": "postgres", + "Config": { + "DSN": "host= port=5432 user= password= dbname= sslmode=disable" + } + } +} +``` + +Then, on the `management` service in `docker-compose.yml`, replace `NETBIRD_STORE_ENGINE_MYSQL_DSN` with: + +```yaml +environment: + - NETBIRD_STORE_ENGINE_POSTGRES_DSN=host= port=5432 user= password= dbname= sslmode=disable + - NB_ACTIVITY_EVENT_STORE_ENGINE=postgres + - NB_ACTIVITY_EVENT_POSTGRES_DSN=host= port=5432 user= password= dbname= sslmode=disable +``` + +## Step 5: Start and Verify + +```bash +docker compose up -d +``` + +Log in to the dashboard and confirm that your peers, users, and activity events are there.