Full migration
What the export contains
The export is an archive with your organization’s data. Every document keeps its original ID, so all references survive the move.
Passwords. By default, the export contains no password hashes or OAuth tokens. Users set a new password with Forgot password on your instance, which needs email configured, or sign in with Google or GitHub if you enable them. If you want users to keep their passwords, ask for an export with credentials when you request it. Treat that archive like a password database.
Changes made on app.nt3.io after the export are not included. Agree on a cut-off time with your team, and stop working on the hosted instance at that point.
Steps
1
Deploy your instance
Deploy Entri with Docker Compose or Kubernetes. Use the same version as the hosted service or newer. Set
ENCRYPTION_KEY and configure email.Make sure migrations have run. With Docker Compose, the migrate service runs them on docker compose up -d. With Helm, the migration hook runs them on install. You can also run them by hand:2
Request your export
Contact the Entri team at bram@xlab.be. Tell them:
- your organization’s name or slug on app.nt3.io
- whether users should keep their passwords (an export with credentials)
- a public key or other secure channel for receiving the archive
acme-2026-01-31.tar.gz.age, with the password or key sent separately. Decrypt it (age -d -i key.txt acme-2026-01-31.tar.gz.age > acme.tar.gz, or as instructed) and keep it private: it contains all your data.3
Get the import tool
The tool is in the Entri repository, in
tools/org-migration. It is plain Node.js, needs Node.js 20.19 or later, tar, and the mongodb driver, and it writes directly to your instance’s MongoDB.4
Import
Use the same connection string as your instance’s The import refuses to write anything when:
MONGO_URI, including the database name. Run a dry run first: it checks everything and writes nothing.- Docker Compose
- Kubernetes (bundled MongoDB)
- Managed MongoDB
MongoDB is only reachable inside the Compose network (
entri_default), so run the tool in a throwaway Node container. Put the archive in the current directory and replace PASS with MONGO_ROOT_PASSWORD from your .env:- your instance is behind the export on database migrations. Upgrade Entri and run
migratefirst. If your instance is ahead, add--allow-newer-target. - the organization already exists on the instance. Add
--forceto update it: it upserts by ID and never deletes anything. - another organization on the instance uses the same slug
- a user on the instance has the same email as an imported user but a different ID. The tool lists every conflict.
5
Restart Entri and sign in
Post-import checklist
1
Configure SMTP or Resend before you tell users to sign in, so password resets and invitations arrive. See Email.
2
Close sign-up
Your users now exist, so set
DISABLE_SIGNUP=true to allow new accounts by invitation only.3
AI provider keys
An owner or admin enters the OpenAI and Anthropic keys again in Organization settings. They are encrypted with your instance’s
ENCRYPTION_KEY.4
Webhooks
Imported webhooks are deactivated, and their signing secrets were replaced with unknown values. A secret is shown only when a webhook is created, so delete each webhook, create it again, and put the new secret in your receiver.
5
GitHub sync
The imported connection points at the hosted GitHub App, which does not work with your instance. Register your own GitHub App, install it, and reconnect under Settings → Integrations. The repository, branch and mode settings on your projects are kept.
6
Social login
To offer “Sign in with Google” or “Sign in with GitHub”, create your own OAuth apps with callback URLs on your domain and set
GOOGLE_CLIENT_ID/GOOGLE_CLIENT_SECRET and GITHUB_CLIENT_ID/GITHUB_CLIENT_SECRET. See Social login. The hosted OAuth apps only work for app.nt3.io.7
Search index
Skip this if you use the default MongoDB search. With Typesense or Algolia, rebuild each project’s index as a signed-in user or with an API token of the organization:
8
CLI
Existing API tokens keep working, but the CLI must point at your instance. Each developer logs in again:To point everyone on a project at your instance, add this to The CLI only sends a stored token to the URL it was saved for, so a developer who logged in to app.nt3.io gets a clear error until they log in again.
.nt3.yml:9
CI pipelines
Set
NT3_API_URL next to NT3_API_TOKEN. The existing token values keep working:NT3_API_TOKEN is only sent to NT3_API_URL. Without it, the CLI keeps calling app.nt3.io.10
Delete the archive
Once everything works, delete the archive and any decrypted copies.
Lightweight migration
If you only need your keys and translations, you can move them yourself with the CLI, project by project, without an export from the Entri team.1
Set up the new instance
Deploy your instance, sign up, and create your organization. For each project, create a project with the same source language. Create an API token on the new instance.
2
Pull from app.nt3.io
In the repository that holds your This writes the source language and every target language to the paths in
.nt3.yml, with a token from app.nt3.io:.nt3.yml.3
Point the project at your instance
In
.nt3.yml, replace project_id with the new project’s ID and add api_url:4
Push to your instance
push uploads the source file first, then every target-language file it finds, and enables those languages in the project.5
Move glossaries
On app.nt3.io, open Glossary, select a glossary and choose Export as CSV. On your instance, create a glossary with the same name and choose Import terms (CSV or TBX).
6
Redo the rest
Invite your team, re-create webhooks, add AI keys, and update CLI and CI configuration as in the post-import checklist.