mirror of
https://github.com/netbirdio/docs.git
synced 2026-04-15 23:16:36 +00:00
Migration guide from external idp to embedded idp (#658)
* added migration guide from external to embedded idp * updated guide * clarify issuer domain used * improved docs structure and added clarifying notes * updated guide to match latest binary * link fixes and added extra psql instructions * update versions properly
This commit is contained in:
@@ -644,6 +644,10 @@ export const docsNavigation = [
|
|||||||
title: 'Enable Reverse Proxy',
|
title: 'Enable Reverse Proxy',
|
||||||
href: '/selfhosted/migration/enable-reverse-proxy',
|
href: '/selfhosted/migration/enable-reverse-proxy',
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
title: 'External IdP to Embedded IdP',
|
||||||
|
href: '/selfhosted/migration/external-to-embedded-idp',
|
||||||
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ This guide walks you through migrating a pre-v0.65.0 NetBird self-hosted deploym
|
|||||||
</Note>
|
</Note>
|
||||||
|
|
||||||
<Warning>
|
<Warning>
|
||||||
The migration script **exits with an error** if it detects an external identity provider (Auth0, Keycloak, Okta, Zitadel, Google Workspace, Microsoft Entra ID, etc.). If you are using an external IdP, do not run this script. Instead, follow the [self-hosting quickstart](/selfhosted/selfhosted-quickstart) for a fresh installation.
|
The migration script **exits with an error** if it detects an external identity provider (Auth0, Keycloak, Okta, Zitadel, Google Workspace, Microsoft Entra ID, etc.). If you are using an external IdP, first follow the [External IdP to Embedded IdP migration guide](/selfhosted/migration/external-to-embedded-idp) to switch to the embedded Dex IdP, then return here to complete the combined container migration.
|
||||||
</Warning>
|
</Warning>
|
||||||
|
|
||||||
## Overview of changes
|
## Overview of changes
|
||||||
|
|||||||
425
src/pages/selfhosted/migration/external-to-embedded-idp.mdx
Normal file
425
src/pages/selfhosted/migration/external-to-embedded-idp.mdx
Normal file
@@ -0,0 +1,425 @@
|
|||||||
|
import {Note, Warning, Success} from "@/components/mdx"
|
||||||
|
|
||||||
|
export const description = 'Migrate a self-hosted NetBird deployment from an external identity provider to the embedded IdP introduced in v0.62.0.'
|
||||||
|
|
||||||
|
# Migration Guide: External IdP to Embedded IdP
|
||||||
|
|
||||||
|
This guide walks through migrating a self-hosted NetBird deployment from an external identity provider to the embedded IdP introduced in v0.62.0.
|
||||||
|
|
||||||
|
<Note>
|
||||||
|
**Who is this guide for?** This migration guide is for users who:
|
||||||
|
- Have an existing self-hosted deployment using an **external IdP**
|
||||||
|
- Want to move to the **embedded Dex-based IdP** for a simpler, self-contained authentication setup
|
||||||
|
</Note>
|
||||||
|
|
||||||
|
## Overview
|
||||||
|
|
||||||
|
|
||||||
|
<Note>
|
||||||
|
Migrating to the embedded IdP also unlocks the [Combined Container Setup migration](/selfhosted/migration/combined-container), which consolidates management, signal, relay, and STUN into a single container. If you plan to simplify your deployment, complete this IdP migration first, then follow the combined container guide.
|
||||||
|
</Note>
|
||||||
|
|
||||||
|
|
||||||
|
The migration tool does two things:
|
||||||
|
1. **Re-encodes user IDs** in the database to include the external connector ID, so Dex can route returning users to the correct external provider.
|
||||||
|
2. **Generates a new `management.json`** that replaces `IdpManagerConfig` with `EmbeddedIdP` and updates OAuth2 endpoints to the embedded Dex issuer.
|
||||||
|
|
||||||
|
After migration, existing users keep logging in through the same external provider — Dex acts as a broker in front of it. No passwords or credentials change.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Before You Begin
|
||||||
|
|
||||||
|
<Note>
|
||||||
|
This guide assumes you're using Docker and everything is run in the same bash session, if you're using a different setup, adjust the commands accordingly.
|
||||||
|
</Note>
|
||||||
|
|
||||||
|
### Prerequisites
|
||||||
|
|
||||||
|
| Requirement | Details |
|
||||||
|
|-------------|---------|
|
||||||
|
| NetBird version | v0.67.2 or later |
|
||||||
|
| Config access | You can read and write `management.json` |
|
||||||
|
| Server downtime | The management server **must be stopped** during migration |
|
||||||
|
| Backups | Back up your database and config before starting |
|
||||||
|
|
||||||
|
|
||||||
|
### Flags and Environment variables
|
||||||
|
|
||||||
|
| Flag | Environment variable | Description | Expected format |
|
||||||
|
|------|----------------------|-------------| --------------- |
|
||||||
|
| `--domain` | `NETBIRD_DOMAIN` | Domain for both dashboard and API | example.com |
|
||||||
|
| `--dashboard-url` | `NETBIRD_DASHBOARD_URL` | Dashboard domain (will override --domain) | example.com or example.com:33073 or https://example.com |
|
||||||
|
| `--api-url` | `NETBIRD_API_URL` | API domain (will override --domain) | example.com or example.com:33073 or https://example.com |
|
||||||
|
| `--config` | `NETBIRD_CONFIG_PATH` | Path to management.json (required) | /path/to/management.json |
|
||||||
|
| `--datadir` | `NETBIRD_DATA_DIR` | Override data directory from config (store.db path will be derived from this) | /path/to/datadir |
|
||||||
|
| `--idp-seed-info` | `NETBIRD_IDP_SEED_INFO` | Base64-encoded connector JSON | base64-encoded JSON string |
|
||||||
|
| `--dry-run` | `NETBIRD_DRY_RUN` | Preview changes without writing | true or false |
|
||||||
|
| `--force` | `NETBIRD_FORCE` | Skip confirmation prompt | true or false |
|
||||||
|
| `--skip-config` | `NETBIRD_SKIP_CONFIG` | Skip config generation (DB migration only) | true or false |
|
||||||
|
| `--skip-populate-user-info` | `NETBIRD_SKIP_POPULATE_USER_INFO` | Skip populating user info (user id migration only) | true or false |
|
||||||
|
| `--log-level` | `NETBIRD_LOG_LEVEL` | Log level: debug, info, warn, error (default "info") | debug, info, warn, error |
|
||||||
|
|
||||||
|
|
||||||
|
<Note>
|
||||||
|
When to use --domain vs --dashboard-domain vs --api-domain:
|
||||||
|
- If you have a single domain for both dashboard and API, use --domain
|
||||||
|
- If you don't have a reverse proxy in front of dashboard and API, make sure you use the domain + port combination for each.
|
||||||
|
For example, `--dashboard-domain demo.netbird.io` and `--api-domain demo.netbird.io:33073`
|
||||||
|
</Note>
|
||||||
|
---
|
||||||
|
|
||||||
|
## Step 1: Prepare your Management Server
|
||||||
|
|
||||||
|
Make sure your management server is on the latest version, otherwise management will not be able to properly parse the new `management.json` file generated by this migration tool.
|
||||||
|
|
||||||
|
```bash
|
||||||
|
docker compose pull
|
||||||
|
docker compose up -d management
|
||||||
|
```
|
||||||
|
|
||||||
|
<Warning>
|
||||||
|
Before starting the migration, it's also a good idea to log out of the dashboard, as you might get a "stale" token from the old IdP which can cause 401 errors.
|
||||||
|
</Warning>
|
||||||
|
---
|
||||||
|
|
||||||
|
## Step 2: Get the Migration Tool
|
||||||
|
|
||||||
|
**Option A — Download a pre-built binary:**
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Replace VERSION with the release tag, and adjust the architecture as needed
|
||||||
|
curl -L -o netbird-idp-migrate.tar.gz \
|
||||||
|
https://github.com/netbirdio/netbird/releases/download/v0.67.2/netbird-idp-migrate_0.67.2_linux_amd64.tar.gz
|
||||||
|
tar xzf netbird-idp-migrate.tar.gz
|
||||||
|
chmod +x netbird-idp-migrate
|
||||||
|
```
|
||||||
|
|
||||||
|
Available architectures: `linux_amd64`, `linux_arm64`, `linux_arm`.
|
||||||
|
|
||||||
|
**Option B — Build from source** (requires Go 1.25+ and a C compiler for CGO/SQLite):
|
||||||
|
|
||||||
|
```bash
|
||||||
|
go build -o netbird-idp-migrate ./tools/idp-migrate/
|
||||||
|
```
|
||||||
|
|
||||||
|
Copy the binary to the management server host if you built it elsewhere.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Step 3: Prepare Your Provider
|
||||||
|
|
||||||
|
The new embedded IdP made the generation of the OIDC connector config easier, that's why we recommend generating a new application for your provider.
|
||||||
|
|
||||||
|
When following the guides to generate the application, make sure you store the client ID and client Secret somewhere safe. You'll need them later.
|
||||||
|
|
||||||
|
To spare details in this guide, you can use the following guides to create the OIDC connector configuration for your provider:
|
||||||
|
- <a href="/selfhosted/identity-providers/managed/auth0" target="_blank">Auth0</a>
|
||||||
|
- <a href="/selfhosted/identity-providers/managed/microsoft-entra-id" target="_blank">Azure AD</a>
|
||||||
|
- <a href="/selfhosted/identity-providers/keycloak" target="_blank">Keycloak</a>
|
||||||
|
- <a href="/selfhosted/identity-providers/managed/okta" target="_blank">Okta</a>
|
||||||
|
- <a href="/selfhosted/identity-providers/authentik" target="_blank">Authentik</a>
|
||||||
|
- <a href="/selfhosted/identity-providers/pocketid" target="_blank">PocketID</a>
|
||||||
|
- <a href="/selfhosted/identity-providers/managed/google-workspace" target="_blank">Google Workspace</a>
|
||||||
|
- <a href="/selfhosted/identity-providers/managed/jumpcloud" target="_blank">JumpCloud</a>
|
||||||
|
- <a href="/selfhosted/identity-providers/zitadel" target="_blank">Zitadel</a>
|
||||||
|
|
||||||
|
|
||||||
|
### Creating the IdP Seed info
|
||||||
|
|
||||||
|
With the client id and client secret from the previous step, you can create the `idp-seed-info` for the tool, which will be used to generate the OIDC connector config.
|
||||||
|
|
||||||
|
1. We'll create a new file "connector.json" with the following contents, make sure you remember where you save it:
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"type": "oidc",
|
||||||
|
"name": "My Provider",
|
||||||
|
"id": "my-provider",
|
||||||
|
"config": {
|
||||||
|
"issuer": "https://idp.example.com",
|
||||||
|
"clientID": "my-client-id",
|
||||||
|
"clientSecret": "my-client-secret"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
<Note>
|
||||||
|
Using Zitadel as an example, the JSON should have the following values:
|
||||||
|
- "issuer": is the root domain of your zitadel instance, make sure you don't have any trailing slashes (e.g. https://zitadel.example.com)
|
||||||
|
- "clientID" and "clientSecret": are the values you copy when creating the OAuth app
|
||||||
|
</Note>
|
||||||
|
|
||||||
|
|
||||||
|
2. Encode and store it in the `NETBIRD_IDP_SEED_INFO` environment variable:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
export NETBIRD_IDP_SEED_INFO=$(base64 < connector.json | tr -d '\n')
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Step 4: Stop the Management Server
|
||||||
|
|
||||||
|
```bash
|
||||||
|
docker compose stop management
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Step 5: Back Up Your Data
|
||||||
|
|
||||||
|
The tool creates `management.json.bak` automatically, but always make your own backups.
|
||||||
|
|
||||||
|
<Warning>
|
||||||
|
Do not skip this step. The migration modifies user IDs in the database. A manual backup is your only recovery path if something goes wrong.
|
||||||
|
</Warning>
|
||||||
|
|
||||||
|
**Docker Compose (SQLite in a named volume):**
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Identify the volume name
|
||||||
|
VOLUME_NAME=$(docker volume ls --format '{{ .Name }}' | grep -Ei 'management|mgmt')
|
||||||
|
echo "Volume: $VOLUME_NAME"
|
||||||
|
|
||||||
|
# Get the host path
|
||||||
|
export NETBIRD_DATA_DIR=$(docker volume inspect "$VOLUME_NAME" --format '{{ .Mountpoint }}')
|
||||||
|
echo "Path: $NETBIRD_DATA_DIR"
|
||||||
|
|
||||||
|
# (SQLite only) Verify store.db exists, then back up
|
||||||
|
sudo ls "$NETBIRD_DATA_DIR/store.db"
|
||||||
|
sudo cp "$NETBIRD_DATA_DIR/store.db" "$NETBIRD_DATA_DIR/store.db.bak"
|
||||||
|
|
||||||
|
# Verify management.json exists, the path will vary based on your setup, then back up
|
||||||
|
export NETBIRD_CONFIG_PATH="<path-to-config>/management.json"
|
||||||
|
cat "$NETBIRD_CONFIG_PATH"
|
||||||
|
|
||||||
|
cp "$NETBIRD_CONFIG_PATH" "$NETBIRD_CONFIG_PATH.bak"
|
||||||
|
```
|
||||||
|
---
|
||||||
|
|
||||||
|
## Step 6: Run the Migration
|
||||||
|
|
||||||
|
### Validate required env vars / flags
|
||||||
|
|
||||||
|
```bash
|
||||||
|
echo $NETBIRD_CONFIG_PATH
|
||||||
|
echo $NETBIRD_DATA_DIR
|
||||||
|
echo $NETBIRD_IDP_SEED_INFO | base64 -d
|
||||||
|
```
|
||||||
|
|
||||||
|
You should expect to see an output similar to this:
|
||||||
|
```
|
||||||
|
/etc/netbird/management.json
|
||||||
|
/var/lib/docker/volumes/management_data/_data
|
||||||
|
{
|
||||||
|
"type": "oidc",
|
||||||
|
"name": "my-provider",
|
||||||
|
"id": "my-provider",
|
||||||
|
"config": {
|
||||||
|
"issuer": "https://idp.example.com",
|
||||||
|
"clientID": "my-client-id",
|
||||||
|
"clientSecret": "my-client-secret",
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### (PostgreSQL only) Verify that the database env var is set
|
||||||
|
|
||||||
|
The postgres store engine requires the postgres container to expose the port over the host
|
||||||
|
so that the migration tool can connect to it. You can set the env var in your shell:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# This should match the same env var content that is passed to the management server
|
||||||
|
export NB_STORE_ENGINE_POSTGRES_DSN="host=localhost port=5432 user=postgres password=postgres dbname=netbird sslmode=disable"
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
If you don't see the expected output, please make sure you followed the steps in this guide, or that you use
|
||||||
|
the correct flags while running the tool.
|
||||||
|
|
||||||
|
### Dry run (always do this first)
|
||||||
|
|
||||||
|
Assuming that you've followed the steps in this guide, you should be able to run the tool with the following command:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
./netbird-idp-migrate --domain mgmt.example.com --dry-run
|
||||||
|
```
|
||||||
|
|
||||||
|
<Note>
|
||||||
|
If the env vars are not set, you can use the flags listed at the [Flags and Environment variables](#flags-and-environment-variables) section.
|
||||||
|
</Note>
|
||||||
|
|
||||||
|
|
||||||
|
After running the dry run command you should see output like:
|
||||||
|
|
||||||
|
```
|
||||||
|
INFO resolved connector: type=oidc, id=auth0, name=auth0
|
||||||
|
INFO found 12 total users: 12 pending migration, 0 already migrated
|
||||||
|
INFO [DRY RUN] would migrate user abc123 -> CgZhYmMxMjMSB3ppdGFkZWw (account: acct-1)
|
||||||
|
...
|
||||||
|
INFO [DRY RUN] migration summary: 12 users would be migrated, 0 already migrated
|
||||||
|
INFO derived domain for embedded IdP: mgmt.example.com
|
||||||
|
INFO [DRY RUN] new management.json would be:
|
||||||
|
{ ... }
|
||||||
|
```
|
||||||
|
|
||||||
|
Verify before proceeding:
|
||||||
|
|
||||||
|
- Connector type and ID match your provider.
|
||||||
|
- User count matches what you expect.
|
||||||
|
- Generated config has the correct domain and endpoints.
|
||||||
|
|
||||||
|
### Execute the migration
|
||||||
|
|
||||||
|
Run the same command without `--dry-run`:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
./netbird-idp-migrate --domain mgmt.example.com
|
||||||
|
```
|
||||||
|
|
||||||
|
The tool will show a summary and prompt for confirmation:
|
||||||
|
|
||||||
|
```
|
||||||
|
About to migrate 12 users. This cannot be easily undone. Continue? [y/N]
|
||||||
|
```
|
||||||
|
|
||||||
|
Type `y` and press Enter.
|
||||||
|
|
||||||
|
### Review the new config
|
||||||
|
|
||||||
|
Your `management.json` should be significantly smaller now, and the OIDC connector config should be present in `StaticConnectors`.
|
||||||
|
Make sure you verify the following:
|
||||||
|
- `IdpManagerConfig` is **removed**.
|
||||||
|
- `EmbeddedIdP` is present with `"Enabled": true` and your connector in `StaticConnectors`.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Step 7: Post-Migration Configuration
|
||||||
|
|
||||||
|
### Update your reverse proxy
|
||||||
|
|
||||||
|
The embedded Dex IdP is served under `/oauth2/`. Your reverse proxy must route this path to the management server.
|
||||||
|
|
||||||
|
**Caddy** — add to your `Caddyfile` inside the site block for your management domain:
|
||||||
|
|
||||||
|
```
|
||||||
|
reverse_proxy /oauth2/* management:80
|
||||||
|
```
|
||||||
|
|
||||||
|
Place it alongside existing `/api/*` and `/management.ManagementService/*` routes, then reload:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
docker compose restart caddy
|
||||||
|
```
|
||||||
|
|
||||||
|
**Nginx:**
|
||||||
|
|
||||||
|
```nginx
|
||||||
|
location /oauth2/ {
|
||||||
|
proxy_pass http://management:80;
|
||||||
|
proxy_set_header Host $host;
|
||||||
|
proxy_set_header X-Real-IP $remote_addr;
|
||||||
|
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||||
|
proxy_set_header X-Forwarded-Proto $scheme;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Reload nginx after adding the route.
|
||||||
|
|
||||||
|
**Traefik:** Add a route matching the `/oauth2/` path prefix, forwarding to the management service.
|
||||||
|
|
||||||
|
**Verify the route works:**
|
||||||
|
|
||||||
|
```bash
|
||||||
|
curl -s https://<your-domain>/oauth2/.well-known/openid-configuration | head -5
|
||||||
|
```
|
||||||
|
|
||||||
|
Expected: a JSON response with `"issuer": "https://<your-domain>/oauth2"`.
|
||||||
|
|
||||||
|
### Update dashboard environment
|
||||||
|
|
||||||
|
Your dashboard should also be updated to use the embedded IdP configuration, for this, make sure you update the
|
||||||
|
`dashboard.env` or environment variables (check docker compose file for reference).
|
||||||
|
|
||||||
|
Your env vars should have the following values:
|
||||||
|
```bash
|
||||||
|
AUTH_AUDIENCE=netbird-dashboard
|
||||||
|
AUTH_CLIENT_ID=netbird-dashboard
|
||||||
|
AUTH_AUTHORITY=https://<your-domain>/oauth2
|
||||||
|
AUTH_SUPPORTED_SCOPES=openid profile email groups
|
||||||
|
AUTH_REDIRECT_URI=/nb-auth
|
||||||
|
AUTH_SILENT_REDIRECT_URI=/nb-silent-auth
|
||||||
|
```
|
||||||
|
|
||||||
|
If you're using docker, make sure to recreate the dashboard container to apply the new environment variables with `docker compose up -d dashboard`
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Step 8: Start and Verify
|
||||||
|
|
||||||
|
### Start the management server
|
||||||
|
|
||||||
|
```bash
|
||||||
|
docker compose up -d management
|
||||||
|
```
|
||||||
|
|
||||||
|
### Verify everything works
|
||||||
|
|
||||||
|
1. **OIDC discovery:** Open `https://<your-domain>/oauth2/.well-known/openid-configuration` — it should return valid JSON.
|
||||||
|
2. **Dashboard login:** Log in to the dashboard — you should be redirected through your external IdP as before.
|
||||||
|
3. **Data integrity:** Check that peers are visible and policies are intact.
|
||||||
|
|
||||||
|
<Note>
|
||||||
|
Use an incognito/private browser window or clear cookies for your first login. Stale tokens from the old IdP will fail validation.
|
||||||
|
</Note>
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Troubleshooting
|
||||||
|
|
||||||
|
### "store does not support migration operations"
|
||||||
|
|
||||||
|
The store implementation is missing the required `ListUsers`/`UpdateUserID` methods. Upgrade to v0.67.2+ binaries.
|
||||||
|
|
||||||
|
### "could not open activity store"
|
||||||
|
|
||||||
|
This is a **warning**, not an error. If `events.db` doesn't exist (e.g., fresh install), activity event migration is skipped. User ID migration in the main database still proceeds normally.
|
||||||
|
|
||||||
|
### "no connector configuration found"
|
||||||
|
|
||||||
|
No IdP configuration was detected. Provide it explicitly with `--idp-seed-info`, or set the `IDP_SEED_INFO` env var.
|
||||||
|
|
||||||
|
### "Errors.App.NotFound" from Zitadel after migration
|
||||||
|
|
||||||
|
The dashboard is still redirecting to Zitadel's `/oauth/v2/` endpoint instead of the management server's `/oauth2` endpoint. Set `AUTH_AUTHORITY=https://<your-domain>/oauth2` in your dashboard environment — see [Update dashboard environment](#update-dashboard-environment).
|
||||||
|
|
||||||
|
### OIDC discovery returns 404
|
||||||
|
|
||||||
|
The `/oauth2/` path is not being routed to the management server. Add a reverse proxy route — see [Update your reverse proxy](#update-your-reverse-proxy).
|
||||||
|
|
||||||
|
### "jumpcloud does not have a supported Dex connector type"
|
||||||
|
|
||||||
|
JumpCloud has no native Dex connector. Configure a generic OIDC connector manually with `--idp-seed-info` — see [Other Providers](#other-providers-auth0-azure-ad-keycloak-okta-authentik-pocketid-google-jumpcloud-etc) in Step 3.
|
||||||
|
|
||||||
|
### "failed to create embedded IDP service: cannot disable local authentication..."
|
||||||
|
|
||||||
|
The embedded IdP didn't support `StaticConnectors` in this config version. Upgrade to v0.67.2+ which includes this fix.
|
||||||
|
|
||||||
|
### Partial failure / re-running
|
||||||
|
|
||||||
|
The migration is **idempotent**. Already-migrated users are detected and skipped. If the tool fails partway through, fix the underlying issue and re-run — it picks up where it left off.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Rolling Back
|
||||||
|
|
||||||
|
If something goes wrong after migration:
|
||||||
|
|
||||||
|
1. **Stop** the management server: `docker compose stop management`
|
||||||
|
2. **Restore the database:**
|
||||||
|
- SQLite (Docker volume): `sudo cp $NETBIRD_DATA_DIR/store.db.bak $NETBIRD_DATA_DIR/store.db`
|
||||||
|
- PostgreSQL: restore from your `pg_dump` backup
|
||||||
|
3. **Restore the config:** `cp $NETBIRD_CONFIG_PATH.bak $NETBIRD_CONFIG_PATH`
|
||||||
|
4. **Revert** any reverse proxy or dashboard env changes.
|
||||||
|
5. **Start** the management server: `docker compose up -d management`
|
||||||
Reference in New Issue
Block a user