Das Problem
NocoDB ist eine quelloffene Tabellenoberfläche über einer Datenbank und wird oft als selbst gehosteter Ersatz für Airtable genutzt. NocoDB kann aus Airtable importieren und eine selbst gehostete Base in die NocoDB Cloud verschieben. Eine Base von einer NocoDB-Installation auf eine andere zu bringen, oder aus der Cloud zurück auf einen eigenen Server, geht nicht. Der CSV-Export arbeitet pro Tabelle und verliert Links, Lookups, Rollups, Formeln und Views.
Issue #9596, "Ability to cross copy bases across installations", ist seit Oktober 2024 offen, hat 81 Reaktionen und keine Antwort der Maintainer. Die Kommentare nennen drei Zwecke: Wiederherstellung nach Ausfällen ("Due to the lack of an option to export the database, there is a feeling of insecurity"), den Umzug aus dem gehosteten Dienst nach einer Testphase und das Weitergeben einer Vorlage an viele andere Nutzer. Ein Kommentar stellt fest, dass der Weg zu und von Airtable einfacher ist als der zwischen zwei NocoDB-Installationen. Der einzige verwandte Code, den ich auf GitHub gefunden habe, zwei Skripte vom Dezember 2025, schreibt im README, dass Link-, Lookup- und Rollup-Spalten nicht enthalten sind.
Wie nocodb-transfer arbeitet
nocodb-transfer ist ein Python-Kommandozeilenwerkzeug ohne Abhängigkeiten. Es nutzt die öffentliche REST-API mit einem API-Token. export schreibt ein Snapshot-Verzeichnis: die Tabellen-Metadaten und Views so, wie NocoDB sie liefert, eine JSON-Zeile pro Datensatz, die Links jeder Relation und die Anhänge unter ihrem SHA-256. import baut daraus eine Base auf, copy macht beides, verify vergleicht zwei Bases.
Der Import muss den Abhängigkeiten in NocoDB folgen. Zuerst entstehen die Tabellen mit ihren einfachen Spalten. Jeder Link steht in den Metadaten zweimal, einmal pro Tabelle. Das Werkzeug ordnet die beiden Seiten einander zu (über die Fremdschlüsselspalte bei has-many und eins-zu-eins, über die Verknüpfungstabelle bei many-to-many), legt die Relation einmal von der Elternseite an und gibt der erzeugten Gegenspalte ihren ursprünglichen Titel zurück. Lookups, Rollups, Formeln, Barcode- und QR-Spalten folgen in Abhängigkeitsreihenfolge, eine Formel über einem Lookup über einem Link funktioniert also. NocoDB speichert Formeln mit internen Spalten-IDs ({{c5xn...}}); sie werden vor dem Anlegen in {Titel} umgeschrieben. Danach werden die Datensätze in Blöcken zu 100 eingefügt. Das Werkzeug merkt sich dabei, welche alte ID zu welcher neuen gehört, weil die IDs abweichen, wenn in der Quelle Zeilen gelöscht wurden. Die Links entstehen über die Links-API mit dieser Zuordnung. Zum Schluss kommen die Views: Filter einschließlich verschachtelter Gruppen, Sortierungen, ausgeblendete Felder, Kanban-Gruppierung, Galerie-Cover und Formulartexte.
Beispiel
So sieht die Kopie der Test-Base zwischen zwei getrennten lokalen Installationen von NocoDB 2026.10.1 aus:
$ nocodb-transfer copy --base Fixture1 --title Fixture1 --verify
exported Authors: 256 records
...
exported 5 tables, 306 records, 66 links, 2 files
importing into base Fixture1 (p5molgg1ngzfsnb)
...
imported 66 links
done: base p5molgg1ngzfsnb, 121 API requests
compared 5 tables, 306 records, 6012 values
no differences
Wie es getestet ist
verify dient auch als wichtigste Prüfung in den Tests. Es vergleicht jedes Feld jedes Datensatzes in ID-Reihenfolge, auch die Werte, die NocoDB auf dem Ziel berechnet: Link-Anzahlen, Lookups, Rollups und Formeln. Hinge eine Relation an den falschen Datensätzen, wichen Rollups und Lookups ab. Ein Test ändert einen Wert im Ziel und prüft, dass verify ihn meldet, zusammen mit dem Rollup und der Formel, die davon abhängen.
Die Test-Base hat fünf Tabellen, 17 einfache Feldtypen, has-many-, many-to-many-, eins-zu-eins- und Selbstbezugs-Links, voneinander abhängige berechnete Spalten, gelöschte Zeilen, Anhänge und neun Views. Die Integrationstests exportieren sie, importieren sie in eine zweite Installation und prüfen zusätzlich View-Details und die Bytes der Anhänge. Das CI führt sie zwischen zwei NocoDB-Containern aus, 2026.10.1 und latest, auch wöchentlich. Der erste CI-Lauf fand einen Unterschied, den ich lokal nicht gesehen hatte: Das Docker-Image von NocoDB 2026.10.1 legt eins-zu-eins-Links über eine Verknüpfungstabelle an, der npm-Build derselben Version, den ich lokal genutzt habe, über einen Fremdschlüssel. Das Werkzeug ordnet jetzt beide Formen zu, und ein Unit-Test enthält die Metadaten aus dem Docker-Image. Weitere Unit-Tests laufen offline auf Metadaten aus einer echten Installation.
Grenzen
Benutzer, Rollen, Freigaben, Webhooks, Automationen, Button-Spalten, Kommentare, Audit-Verlauf sowie Kalender- und Karten-Views werden nicht kopiert. User-Felder bleiben leer, CreatedAt und UpdatedAt bekommen neue Werte. Versionen vor 2026.10 sind nicht getestet; der Aufbau der Test-Base auf 0.263.8 scheiterte, weil die Link-API dieser Version die Anfragen ablehnte. Getestet sind nur Bases auf der Standard-Datenquelle von NocoDB, die NocoDB Cloud gar nicht. Der Client wiederholt Anfragen bei Ratenbegrenzung; in der Cloud würde man im UI eine leere Base anlegen und mit --base-id hinein importieren. Dicht verlinkte Bases brauchen eine Anfrage pro Datensatz mit Links.
Der Code liegt unter github.com/Jwrede/nocodb-transfer.