# Webseiten migrieren: Umzug und Backup ohne Datenbank

> So sicherst du eine CMF-Website und ziehst sie um: Ordner kopieren, Rechte setzen, baseUrl anpassen – dazu Admin-ZIP, API-Export und was ins Backup gehört.

Kanonische URL: https://cmf.brosemedien.de/news/webseiten-migrieren

---

# Webseiten migrieren: Umzug und Backup ohne Datenbank

Kein SQL-Export, kein Suchen und Ersetzen in der Datenbank. Eine CMF-Migration ist im Kern ein Kopiervorgang – plus ein paar Handgriffe am Server.

Was bei datenbankbasierten Systemen ein mehrstufiger Prozess ist, schrumpft beim CMF auf wenige Schritte. Inhalte, Einstellungen und Medien sind Dateien – wer den Ordner vollständig überträgt, hat die Website übertragen. Worauf du dabei achten musst, steht hier.

## Migration in 4 Schritten

1
**Kopieren**Den kompletten Projektordner per FTP, SCP oder rsync auf den neuen Server übertragen – Code, Inhalte, Konfiguration und Medien.

2
**Server einrichten**DocumentRoot auf `public/` setzen. Schreibrechte für `config/`, `content/` und `public/`, fürs System-Update zusätzlich `app/` und `version.json`.

3
**URL anpassen**In `config/site.json` die `baseUrl` auf die neue Domain ändern – per FTP oder per API mit `site_update`. Im Admin gibt es dafür kein Feld.

4
**Neu erzeugen**Eine Seite im Admin speichern oder per API `?a=sitemap_generate` aufrufen: Sitemap, Feed, llms.txt und Suchindex entstehen mit der neuen Adresse.

Danach sieht die Website auf dem neuen Server so aus wie auf dem alten. Keine Datenbank-Migration, keine Plugin-Kompatibilität prüfen.

## Vier Wege zum Backup

### Backend-Export

Im Admin unter **Einstellungen → Export**. Per Häkchen wählst du: Header, Footer, Seiten, Medien, Blog sowie Theme und Custom CSS.

Ergebnis: `cmf-backup-YYYY-MM-DD.zip`. Zurück geht es unter Einstellungen → Import. Nicht enthalten sind Benutzer, `site.json` und Formular-Einsendungen.

### API-Export

`GET ?a=site_export` liefert Site-Konfiguration, Styles, Header, Footer, Custom CSS und alle Seiten als ein JSON-Objekt – praktisch für automatisierte Sicherungen.

**Achtung:** Blog-Beiträge und Medien sind nicht enthalten. Als alleiniges Backup reicht der API-Export deshalb nicht.

### Ordner kopieren

Den gesamten Projektordner per FTP, SCP oder rsync sichern. Das ist das vollständigste Backup: Code, Inhalte, Medien, Konfiguration, Benutzer und Formular-Einsendungen.

Einsendungen sind personenbezogene Daten – bewahre die Kopie entsprechend sicher auf.

### Git

Weil die Inhalte JSON-Dateien sind, kannst du den Ordner selbst mit Git versionieren – das CMF bringt dafür keine eigene Anbindung mit. Diffs zeigen dann, welcher Block sich geändert hat.

Nicht ins Repository gehören Formular-Einsendungen (`content/form-submissions/`), `config/secret.json` und bei öffentlichen Repositories auch `config/users.json`.

## Was gesichert werden muss – und was nicht

### Kritisch (Inhalte)

- content/pages.json – Seitenindex
- content/pages/ – alle Seiteninhalte
- content/blog.json – Blogindex
- content/blog/ – alle Blogbeiträge
- content/globals/ – Header + Footer
- content/form-submissions/ – Formular-Einsendungen
- public/media/ – alle Uploads
- public/files/ – eigene Downloads

### Wichtig (Konfiguration)

- config/site.json – Name, Sprache, URL
- config/styles.json – Design-Tokens
- config/users.json – Benutzer + Token-Hashes
- public/assets/css/custom.css – eigene Klassen

### Regenerierbar

- theme.css – aus styles.json, beim Speichern des Themes
- sitemap.xml und robots.txt – aus Seiten und Blog
- feed.xml – aus den Blog-Beiträgen
- llms.txt – aus Seiten und Beiträgen
- search-index.json – Index der Live-Suche
- login_attempts.json – temporäre Daten

**Tipp:** Sitemap, robots.txt, Feed, llms.txt und Suchindex entstehen bei jeder Änderung an Seiten oder Blog neu – im Admin wie per API – oder gezielt mit `sitemap_generate`.

## Migrations-Szenarien

### Hoster wechseln

Ordner zum neuen Hoster kopieren, DocumentRoot auf `public/` setzen, Schreibrechte vergeben, `baseUrl` ändern, DNS umstellen, Sitemap und Co. neu erzeugen.

Kein Setup-Assistent, keine Datenbank. Prüfe beim neuen Hoster einmal: PHP ab 8.1, Apache mit mod_rewrite und die PHP-Erweiterungen, die das CMF nutzt (zip, dom, curl, mbstring, fileinfo).

### Staging-Umgebung

Eine Kopie auf einer Subdomain mit eigener `baseUrl` ergibt eine identische Testumgebung.

Änderungen überträgst du danach per Admin-ZIP (Export auf Staging, Import auf Production) oder kopierst die geänderten JSON-Dateien. `site_import` überträgt nur Seiten, Header, Footer, Theme und Site-Konfiguration – keine Beiträge, keine Medien.

### Vorlagen verteilen

Eine fertige Website als Admin-Backup-ZIP weitergeben: Der Empfänger installiert ein frisches CMF, spielt das ZIP unter Einstellungen → Import ein und hat Seiten, Blog, Medien und Theme – die Pfade bleiben gleich.

Praktisch für Agenturen, die mehrere Kunden mit demselben Grundlayout bedienen.

## Der Vergleich

**WordPress**

- Datenbank exportieren (phpMyAdmin)
- Dateien per FTP herunterladen
- Auf neuem Server Datenbank anlegen
- Datenbank importieren
- wp-config.php anpassen
- URLs in serialisierten Daten ersetzen (Search-Replace-Tool)
- Permalinks neu speichern
- Plugins prüfen und ggf. neu aktivieren
- Theme-Einstellungen prüfen
- Cache leeren

**CMF**

- Ordner kopieren
- DocumentRoot und Schreibrechte setzen
- baseUrl in site.json ändern
- Sitemap und Co. neu erzeugen

Gleiche Website, neuer Server.

## Automatisierte Migration per API

### Export (Quelle)

```
GET /api.php?a=site_export
Authorization: Bearer TOKEN_QUELLE
```

Liefert ein JSON-Objekt mit: `site`, `styles`, `header`, `footer`, `custom_css` und `pages` (Array mit Index + Inhalt jeder Seite).

**Achtung:** Dieses JSON enthält weder Blog-Beiträge noch Medien. Beiträge holst du über `blog_posts` und `blog_post`, Medien über `media` und überträgst sie mit `media_upload`. Für einen vollständigen Umzug ist das Admin-ZIP der einfachere Weg.

### Import (Ziel)

```
POST /api.php?a=site_import
Authorization: Bearer TOKEN_ZIEL
Content-Type: application/json

{ komplettes Export-JSON }
```

Mitgesendete Teile werden ersetzt, fehlende bleiben unverändert, gelöscht wird nichts. Seiten mit gleicher ID werden aktualisiert, neue angelegt.

Ungültige Teile lehnt der Import ab und nennt sie in `data.rejected` – die Antwort also prüfen. Und: `site` ersetzt die `site.json` des Ziels samt `baseUrl`. Beim Übertragen von Staging auf Production `site` weglassen oder vorher anpassen.

- [CMF herunterladen](/download)
- [API-Referenz](/api-anleitung)
- [Maschinengesteuerte Seitenerstellung](/maschinen-anleitung)
