Repository navigation
Come Home Firebase
Start a fresh nSelf project before importing. Postgres and Hasura must be healthy, and the
project must have no tables in the firebase schema and no users in auth.users.
You need three things from Firebase:
- The project id (
--project). - A service-account key file for a service account that can read Firestore and Cloud Storage
(
--credentials-file). The key stays on disk where you keep it. The importer reads it, signs a short-lived token with the standard library and holds both only in memory. Neither appears in output, reports or errors. With the Firebase emulator, setFIRESTORE_EMULATOR_HOST(andSTORAGE_EMULATOR_HOSTfor a bucket) and no key file is needed. Giving both a key file and an emulator host is refused, so a stale host variable cannot read the wrong data. - A user export:
firebase auth:export auth-users.json --format=json(--auth-export).
nself db import firebase --project my-project --credentials-file ./key.json --auth-export ./auth-users.json --bucket my-project.appspot.com --plan --json
nself db import firebase --project my-project --credentials-file ./key.json --auth-export ./auth-users.json --bucket my-project.appspot.com --jsonIn v1.4 mode nself migrate firebase --export-dir <dir> keeps writing migration artifacts from a
Firestore export. In v1.5 mode the same command, and nself db import firebase, run this import.
--bucket is optional; without it no storage is copied. --plan checks the inputs, the source
and the target and writes nothing; the old --dry-run flag means --plan in v1.5 mode.
Documents. Firestore is read through its REST API (documents, listCollectionIds, and the
runAggregationQuery COUNT used as the independent source count). Every top-level collection
becomes a table in the schema firebase:
| Part | Rule |
|---|---|
| Table name | the collection id, lower-cased, other characters replaced by _ (a leading digit gets a _) |
| Name clash | the first collection (sorted) keeps the name, the next gets _2, _3; each rename is listed in the report's exemptions with kind metadata
|
| Columns |
id text (primary key), data jsonb (the whole document) |
| Typed columns | a top-level field becomes a column when every document that has it agrees on one scalar type: string text, integer bigint, double double precision, boolean boolean, timestamp timestamptz
|
| Disagreement | a field whose documents disagree on type, or whose column name clashes after sanitising (Title and title, or id), gets no column; the value stays in data, and the report lists the field in exemptions (kind metadata) |
| Column limit | at most 200 typed columns per table, the most common fields first; the rest stay in data and are listed |
| Unsafe text | a text value with a line that is only a backslash and a dot would end the psql \copy early, so that field gets no column (the value stays in data) |
| Sub-collections | table <parent>__<sub> with parent_path (for example users/u1) and parent_id; the key is (parent_path, id) because document ids repeat across parents |
| Nested maps, arrays, geo points, references, bytes | stay in data only (bytes as base64, references as the resource name) |
In data, bytes, references and timestamps are plain strings, a NaN or infinite double is the
string "NaN" or "Infinity", and a whole-number double reads the same as an integer; the typed
columns keep the exact type.
No type is ever guessed. There is no data exemption: every document and every field is in a table. A document that holds a NUL character in a string cannot be stored by Postgres and stops the import.
Users. Firebase hashes passwords with a modified scrypt that hasura-auth cannot verify, so
users arrive without a password and users.reset_required in the report lists each one with
its id and email. The hash is never copied into the bundle. Send each user through hasura-auth's
/user/password/reset. A user id is a UUIDv5 of the Firebase uid, so a re-run gives the same ids;
the uid stays in auth.users.metadata.firebase.uid, with providers and custom attributes.
Users that only sign in through a provider (Google, Apple) have no hash and are not in the reset
list; they keep metadata.firebase.providers and sign in again after re-linking the provider.
Anonymous users (no email, phone or provider) are imported as ordinary accounts without any
credential, flagged metadata.firebase.anonymous, and counted in one report note. A user
whose email or phone number repeats (hasura-auth keeps them unique) is left out and listed as an
exemption of kind user that names the Firebase uid.
Storage. With --bucket, every object is read through the Cloud Storage JSON API and loaded
into the project's object store. Without an enabled store the import stops with E529 unless you
pass --skip-storage, which lists each object as an exemption.
The report passes only when, for every table, the row count and a content hash match, and the independent source counts match: documents per collection from the Firestore COUNT aggregation (a different API than the document listing, so a missing page shows up), users from the export file's element count, and objects from a second bucket listing. A mismatch is E523 and the exit code is 1.
- Firestore Security Rules and indexes are not translated. Add Hasura permissions after the import.
- A document that was deleted but still has sub-collections is not a row; its sub-collections are still imported (the listing asks Firestore for such parents).
- Each document costs one
listCollectionIdsread to find sub-collections. - Objects are copied as stored (a gzip-encoded object stays gzip) and each one is checked against the size and MD5 the bucket listing reports. Failed requests are retried with a growing wait.
- Object versions other than the live one are not copied.
report.json under .nself/import/<run-id>/ records wrote and last_step, exactly as for the
other sources. If wrote is false, nothing changed: fix the cause and rerun. If it is true, reset
the fresh target and rerun:
nself db reset --yes
nself stop
nself start
nself db import firebase --project my-project --credentials-file ./key.json --auth-export ./auth-users.json --jsondb reset drops and recreates the project database, so run it only on the fresh target you were
importing into. See Come-Home-Postgres for the full recovery notes.
Getting Started
Commands
- Commands, Overview
- Lifecycle: cmd-init · cmd-build · cmd-start · cmd-stop · cmd-restart · cmd-dev
- Monitoring: cmd-status · cmd-logs · cmd-health · cmd-urls · cmd-doctor · cmd-monitor · cmd-alerts · cmd-sentry · cmd-watchdog
- Data: cmd-db · cmd-backup · cmd-dr · cmd-queue · cmd-webhooks
- Config: cmd-config · cmd-service · cmd-env · cmd-promote
- Networking: cmd-ssl · cmd-trust · cmd-dns-setup
- Security: cmd-access · cmd-security · cmd-secrets
- Tenancy: cmd-tenant · cmd-billing
- Plugins: cmd-plugin · cmd-license · cmd-dogfood (extracted, CLI-R11) · cmd-k8s (extracted, CLI-R11) · cmd-encryption (extracted, CLI-R11) · cmd-waf (extracted, CLI-R11) · cmd-federation (extracted, CLI-R11) · cmd-mail (extracted, CLI-R11) · cmd-dlq (extracted, CLI-R11)
- AI: cmd-ai · cmd-claw · cmd-model
- Templates: cmd-template
- Utilities: cmd-exec · cmd-clean · cmd-reset · cmd-update · cmd-upgrade · cmd-version · cmd-admin · cmd-migrate · cmd-migrate-firebase · cmd-migrate-supabase · cmd-completion
Features
- Features, Overview
- Feature-Auth
- Feature-Storage
- Feature-Search
- Feature-Functions
- Feature-Email
- Feature-Monitoring
- Feature-Plugins
- Feature-nClaw, AI Assistant
- Feature-nChat, Messaging
- Feature-nFamily, Family Social
- Feature-nCloud, Managed Hosting
- Feature-Memory-Rooms, Knowledge Organization
- Feature-Agent-Dashboard, Agent Metrics
- Feature-Image-Generation, AI Image Generation
Configuration
- Configuration, Overview
- Config-Env-Vars
- Config-Postgres
- Config-Hasura
- Config-Auth
- Config-Nginx
- Shared-Proxy
- Config-Optional-Services
- Config-Custom-Services
- Config-System
Plugins (87 + 10 monitoring)
- Plugin-Overview
- Plugin-Catalog
- Plugin-Install
- Plugin-Licensing
- Plugin-Architecture
- Plugin-Dev-Guide
- Plugin-Migrations-Contract
Free (25)
- plugin-backup
- plugin-content-acquisition
- plugin-content-progress
- plugin-cron
- plugin-donorbox
- plugin-feature-flags
- plugin-github
- plugin-github-runner
- plugin-invitations
- plugin-jobs
- plugin-link-preview
- plugin-mdns
- plugin-mlflow
- plugin-monitoring
- plugin-notifications
- plugin-notify
- plugin-paypal
- plugin-search
- plugin-shopify
- plugin-stripe
- plugin-subtitle-manager
- plugin-tokens
- plugin-torrent-manager
- plugin-vpn
- plugin-webhooks
Pro (62)
- plugin-access-controls
- plugin-activity-feed
- plugin-admin-api
- plugin-analytics
- plugin-auth
- plugin-bots
- plugin-browser
- plugin-calendar
- plugin-cdn
- plugin-chat
- plugin-claw
- plugin-claw-budget
- plugin-claw-news
- plugin-claw-web
- plugin-cloudflare
- plugin-cms
- plugin-compliance
- plugin-ddns
- plugin-devices
- plugin-documents
- plugin-entitlements
- plugin-file-processing
- plugin-game-metadata
- plugin-geocoding
- plugin-geolocation
- plugin-google
- plugin-home
- plugin-idme
- plugin-knowledge-base
- plugin-linkedin
- plugin-livekit
- plugin-media-processing
- plugin-meetings
- plugin-moderation
- plugin-mux
- plugin-object-storage
- plugin-observability
- plugin-photos
- plugin-podcast
- plugin-post
- plugin-realtime
- plugin-retro-gaming
- plugin-rom-discovery
- plugin-social
- plugin-sports
- plugin-support
- plugin-tmdb
- plugin-voice
- plugin-web3
- plugin-workflows
Planned (26)
plugin-auditplugin-blogplugin-checkoutplugin-commerceplugin-drmplugin-exportplugin-flowplugin-importplugin-ldapplugin-mailgunplugin-mediaplugin-oauth-providersplugin-pagesplugin-postmarkplugin-rate-limitplugin-reportsplugin-samlplugin-schedulerplugin-sendgridplugin-ssoplugin-subscriptionplugin-thumbplugin-transcoderplugin-twilioplugin-wafplugin-watermark
Guides
- Guide-Production-Deployment
- Guide-SSL-Setup
- Guide-Multi-Tenancy
- Guide-Security-Hardening
- Guide-Monitoring-Setup
- Guide-Backup-Restore
- Guide-Custom-Services
- Guide-Migration-from-v1
Architecture
- Architecture
- Architecture-Guardrails
- Service-Graph
- Compose-Generation
- Nginx-Generation
- Plugin-Architecture
Reference
Machine interface
-
JSON-Output,
--jsonenvelope -
Command-Registry,
nself help --json - Exit-Codes
- error-codes, Error Codes
-
Compat-V15,
NSELF_V15gate
Licensing
Security
Brand
Operations
- operations/release-cascade, Release Cascade
- operations/self-healing, Self-Healing Schema
- operations/redis-tuning, Redis Pool Tuning
- operations/meilisearch-warmup, MeiliSearch Warm-Up
- operations/jwt-rotation, JWT Key Rotation
- operations/windows-wsl2-setup, Windows / WSL2 Setup
- operations/gemini-oauth-reauth, Gemini OAuth Reauth
Contributing
Admin
- USER-ACTION-QUEUE, Pending Admin Actions
All commands (21)
- A: cmd-add · cmd-admin
- B: cmd-backup · cmd-build
- C: cmd-clean · cmd-config
- D: cmd-db · cmd-deploy · cmd-doctor
- E: cmd-exec
- I: cmd-init
- L: cmd-license · cmd-logs
- M: cmd-mcp
- R: cmd-remove · cmd-reset · cmd-restart
- S: cmd-start · cmd-status · cmd-stop
- U: cmd-update