# Migrate from SQLite to PostgreSQL import {Note, Warning} from "@/components/mdx"; This guide is part of the [Splitting Your Self-Hosted Deployment](/selfhosted/maintenance/scaling/scaling-your-self-hosted-deployment) guide. It covers migrating your Management server database from SQLite to PostgreSQL. The default NetBird deployment uses SQLite, which stores all data in a single file. This works well for smaller setups, but you may want to migrate to PostgreSQL if: - You want the database on a separate, dedicated machine - You need better concurrency handling for larger deployments - You prefer the operational tooling and backup options that PostgreSQL provides For smaller teams, SQLite is perfectly capable and migration is not required. ## Set Up PostgreSQL If you don't already have a PostgreSQL instance, you can run one in Docker: ```bash docker run -d \ --name postgres-server \ -e POSTGRES_USER=postgres \ -e POSTGRES_PASSWORD=password \ -p 5432:5432 \ -v postgres_data:/var/lib/postgresql/data \ postgres:16 ``` Replace the default `password` with a strong, unique password for production deployments. ## Back Up the SQLite Store Before migrating, create a backup of your SQLite database: ```bash mkdir backup docker compose cp -a netbird-server:/var/lib/netbird/. backup/ ``` ## Install pgloader The migration uses [pgloader](https://github.com/dimitri/pgloader) to transfer data from SQLite to PostgreSQL: ```bash # Debian/Ubuntu sudo apt-get install pgloader # macOS brew install pgloader ``` ## Create the Migration File Create a file called `sqlite.load` with the following content: ``` LOAD DATABASE FROM sqlite:///root/combined/backup/store.db INTO postgresql://postgres:password@localhost:5432/postgres WITH include drop, create tables, create indexes, reset sequences CAST column accounts.is_domain_primary_account to boolean, column accounts.settings_peer_login_expiration_enabled to boolean, column accounts.settings_peer_inactivity_expiration_enabled to boolean, column accounts.settings_regular_users_view_blocked to boolean, column accounts.settings_groups_propagation_enabled to boolean, column accounts.settings_jwt_groups_enabled to boolean, column accounts.settings_routing_peer_dns_resolution_enabled to boolean, column accounts.settings_extra_peer_approval_enabled to boolean, column accounts.settings_extra_user_approval_required to boolean, column accounts.settings_lazy_connection_enabled to boolean ; ``` Update the SQLite path and PostgreSQL connection string to match your environment. ## Run the Migration ```bash pgloader sqlite.load ``` ## Update config.yaml On your main server, update the `store` section in `config.yaml` to use PostgreSQL: ```yaml server: # ... existing settings ... store: engine: "postgres" dsn: "host=postgres-server user=postgres password=password dbname=postgres port=5432" ``` Alternatively, you can pass the connection string as an environment variable instead of putting it in the config file: ```yaml netbird-server: environment: - NETBIRD_STORE_ENGINE_POSTGRES_DSN=host=postgres-server user=postgres password=password dbname=postgres port=5432 ``` ## Restart and Verify ```bash docker compose up -d ``` Check the logs to confirm PostgreSQL is being used: ```bash docker compose logs netbird-server | grep store ``` You should see: ``` using Postgres store engine ```