Hinweis: Dieser Artikel wurde mit Unterstützung einer KI (Claude) erstellt und dokumentiert eine reale Migration. Der Artikel wurde manuell geprüft. Es werden keine Garantien für die Korrektheit der Schritte oder der Anleitung insgesamt übernommen. Es liegt in der Verantwortung des Nutzers/der Nutzerin, jede Zeile vor der Anwendung zu prüfen.


Home Assistant Migration: SQLite → PostgreSQL 18 + TimescaleDB + LTSS

Migration von Home Assistant Recorder von SQLite auf PostgreSQL 18.1 mit TimescaleDB 2.23 für optimierte Zeitreihen-Speicherung. Zwei-Datenbank-Setup: homeassistant für kurzfristige Daten (Recorder) und ltss für Langzeit-Speicherung mit TimescaleDB-Optimierungen.

⚠️ WICHTIG: Es findet KEINE Datenkonvertierung statt!

Bei dieser Migration werden neue, leere Datenbanken erstellt. Die bestehende SQLite-Historie wird nicht übertragen. Nach dem Umstieg beginnt die Aufzeichnung von Null. Die alte SQLite-Datenbank bleibt unberührt und kann als Backup aufbewahrt werden.

System: – Proxmox LXC Container – Debian 13.3 “Trixie” (stable) – 2 vCPU, 4 GB RAM, 250 GB Storage – PostgreSQL 18.1 – TimescaleDB 2.23

1. PostgreSQL 18 + TimescaleDB Installation

Migration von Home Assistant Recorder von SQLite auf PostgreSQL 18.1 mit TimescaleDB 2.23 für optimierte Zeitreihen-Speicherung. Zwei-Datenbank-Setup: homeassistant für kurzfristige Daten (Recorder) und ltss für Langzeit-Speicherung mit TimescaleDB-Optimierungen.

⚠️ WICHTIG: Es findet KEINE Datenkonvertierung statt!

Bei dieser Migration werden neue, leere Datenbanken erstellt. Die bestehende SQLite-Historie wird nicht übertragen. Nach dem Umstieg beginnt die Aufzeichnung von Null. Die alte SQLite-Datenbank bleibt unberührt und kann als Backup aufbewahrt werden.

System: – Proxmox LXC Container – Debian 13.3 “Trixie” (stable) – 2 vCPU, 4 GB RAM, 250 GB Storage – PostgreSQL 18.1 – TimescaleDB 2.23

1. PostgreSQL 18 + TimescaleDB Installation

# System aktualisieren
apt update && apt upgrade -y
apt install -y curl ca-certificates gnupg lsb-release wget

# PostgreSQL 18 Repository einrichten
install -d /usr/share/postgresql-common/pgdg
curl -o /usr/share/postgresql-common/pgdg/apt.postgresql.org.asc --fail https://www.postgresql.org/media/keys/ACCC4CF8.asc
sh -c 'echo "deb [signed-by=/usr/share/postgresql-common/pgdg/apt.postgresql.org.asc] https://apt.postgresql.org/pub/repos/apt $(lsb_release -cs)-pgdg main" > /etc/apt/sources.list.d/pgdg.list'

# PostgreSQL installieren
apt update
apt install -y postgresql-18

# TimescaleDB 2.23 Repository einrichten (offiziell via Packagecloud)
curl -fsSL https://packagecloud.io/timescale/timescaledb/gpgkey | gpg --dearmor -o /etc/apt/trusted.gpg.d/timescaledb.gpg
echo "deb https://packagecloud.io/timescale/timescaledb/debian/ $(lsb_release -cs) main" > /etc/apt/sources.list.d/timescaledb.list

# TimescaleDB installieren und konfigurieren
apt update
apt install -y timescaledb-2-postgresql-18
timescaledb-tune --quiet --yes
systemctl restart postgresql

2. Deutsche Locales installieren

# Für UTF-8 Encoding bei Umlauten und Sonderzeichen erforderlich
apt-get install -y locales
echo "de_DE.UTF-8 UTF-8" >> /etc/locale.gen
locale-gen
systemctl restart postgresql

3. PostgreSQL Benutzer erstellen

sudo -u postgres psql
-- Benutzer für Home Assistant erstellen
CREATE USER hass WITH PASSWORD 'DEIN_SICHERES_PASSWORT';
ALTER USER hass CREATEDB;
\q

4. Datenbanken mit UTF-8 Encoding erstellen

WICHTIG: TEMPLATE template0 verwenden und deutsches Locale für korrekte Sortierung!

sudo -u postgres psql
-- Datenbank für Home Assistant Recorder (kurzfristig, 7-60 Tage)
CREATE DATABASE homeassistant 
  OWNER hass 
  ENCODING 'UTF8' 
  LC_COLLATE 'de_DE.UTF-8' 
  LC_CTYPE 'de_DE.UTF-8'
  TEMPLATE template0;

-- Datenbank für LTSS (langfristig, unbegrenzt)
CREATE DATABASE ltss 
  OWNER hass 
  ENCODING 'UTF8' 
  LC_COLLATE 'de_DE.UTF-8' 
  LC_CTYPE 'de_DE.UTF-8'
  TEMPLATE template0;

-- TimescaleDB Extension aktivieren
\c homeassistant
CREATE EXTENSION IF NOT EXISTS timescaledb;
GRANT ALL ON SCHEMA public TO hass;
GRANT CREATE ON SCHEMA public TO hass;

\c ltss
CREATE EXTENSION IF NOT EXISTS timescaledb;
GRANT ALL ON SCHEMA public TO hass;
GRANT CREATE ON SCHEMA public TO hass;

-- Encoding prüfen (muss UTF8 sein!)
SELECT datname, pg_encoding_to_char(encoding) FROM pg_database WHERE datname IN ('ltss', 'homeassistant');

\q

5. Netzwerkzugriff konfigurieren

# PostgreSQL auf allen Interfaces lauschen lassen
echo "listen_addresses = '*'" >> /etc/postgresql/18/main/postgresql.conf

# Zugriff für Home Assistant erlauben (Passwort-Authentifizierung)
echo "host all hass 0.0.0.0/0 scram-sha-256" >> /etc/postgresql/18/main/pg_hba.conf

# PostgreSQL neu starten
systemctl restart postgresql

6. LTSS via HACS installieren

In Home Assistant: 1. HACS öffnen 2. Integrations → Suche “Long Time State Storage (LTSS)” 3. Installieren 4. Home Assistant neu starten

Alternativ manuell:

cd /config/custom_components
git clone https://github.com/freol35241/ltss.git
mv ltss/custom_components/ltss .
rm -rf ltss

7. Home Assistant konfigurieren

configuration.yaml:

# Recorder - Kurzzeit-Speicherung (7-60 Tage)
recorder:
  db_url: !secret psql_connector_string
  auto_purge: true
  purge_keep_days: 60  # oder 7 für minimalen Speicherbedarf
  commit_interval: 5
  exclude:
    entity_globs:
      # iCloud3 erzeugt NULL-Bytes (PostgreSQL-inkompatibel)
      - device_tracker.*_icloud
      - sensor.*_icloud*
      - "*_icloud_*"
      # AlphaESS Helper mit NULL-Bytes in Service-Calls
      - input_boolean.alphaess_helper_*
    event_types:
      - call_service  # Optional: Service-Calls nicht aufzeichnen

# LTSS - Langzeit-Speicherung (unbegrenzt)
ltss:
  db_url: !secret ltss_connector_string
  chunk_time_interval: 2592000000000  # 30 Tage Chunks (in Mikrosekunden)
  
  include:
    domains:
      - sensor
      - binary_sensor
    entities:
      - climate.wohnzimmer
      - switch.heating_main
  
  exclude:
    entity_globs:
      - sensor.*_uptime
      - sensor.*_last_boot

secrets.yaml:

# UTF-8 Encoding explizit angeben für Umlaute (°C, ö, etc.)
psql_connector_string: "postgresql://hass:DEIN_PASSWORT@IP_ADRESSE/homeassistant?client_encoding=utf8"
ltss_connector_string: "postgresql://hass:DEIN_PASSWORT@IP_ADRESSE/ltss?client_encoding=utf8"

Home Assistant neu starten – Tabellen werden automatisch erstellt.

8. Automatisches Backup einrichten

# Backup-Verzeichnis erstellen
mkdir -p /backup

# Cron-Jobs für tägliches Backup um 3 Uhr
cat > /etc/cron.d/postgres-backup << 'EOF'
0 3 * * * postgres pg_dump homeassistant | gzip > /backup/ha_$(date +\%Y\%m\%d).sql.gz
0 3 * * * postgres pg_dump ltss | gzip > /backup/ltss_$(date +\%Y\%m\%d).sql.gz
0 4 * * * root find /backup -name "*.sql.gz" -mtime +14 -delete
EOF

9. Wichtige Hinweise

Zwei-Datenbank-Architektur

homeassistant DB (Recorder): – Standard PostgreSQL-Tabellen (KEINE Hypertables) – Home Assistant Recorder ist nicht mit TimescaleDB Hypertables kompatibel – Kurze Retention (7-60 Tage) – Schnelle Queries für UI und History – Auto-Purge entfernt alte Daten

ltss DB (LTSS): – TimescaleDB Hypertable mit automatischer Kompression – Unbegrenzte Retention (keine purgekeepdays konfiguriert) – Optimiert für Langzeit-Zeitreihenanalysen – Ideal für Grafana und historische Auswertungen – Automatische Kompression nach 30 Tagen spart Speicherplatz

NULL-Byte Problem

PostgreSQL erlaubt keine NULL-Bytes (0x00) in Strings. Folgende Integrationen können Probleme verursachen: – iCloud3: Speichert NULL-Bytes in Attributen – AlphaESS: NULL-Bytes in Service-Call-Daten

Lösung: Betroffene Entities in recorder.exclude.entity_globs ausschließen.

UTF-8 Encoding

Kritisch für deutsche Umlaute und Sonderzeichen: – Datenbanken MÜSSEN mit ENCODING 'UTF8' erstellt werden – TEMPLATE template0 verwenden (template1 hat oft SQL_ASCII) – ?client_encoding=utf8 im Connection String angeben – Deutsche Locale (de_DE.UTF-8) für korrekte Sortierung

TimescaleDB Hypertables

NICHT manuell konvertieren! – Home Assistant Recorder erstellt Standard-Tabellen – LTSS erstellt automatisch Hypertables mit korrektem Schema – Manuelle Konvertierung führt zu StaleDataError im Recorder

10. Monitoring und Wartung

Datenbankgröße prüfen

-- Gesamtgröße
SELECT pg_size_pretty(pg_database_size('homeassistant'));
SELECT pg_size_pretty(pg_database_size('ltss'));

-- Tabellengröße
\c homeassistant
SELECT tablename, pg_size_pretty(pg_total_relation_size(schemaname||'.'||tablename)) AS size
FROM pg_tables WHERE schemaname = 'public' 
ORDER BY pg_total_relation_size(schemaname||'.'||tablename) DESC;

TimescaleDB Status

\c ltss

-- Hypertable-Info
SELECT * FROM timescaledb_information.hypertables;

-- Kompression-Einstellungen
SELECT * FROM timescaledb_information.compression_settings;

-- Chunk-Status
SELECT * FROM timescaledb_information.chunks WHERE hypertable_name = 'ltss';

-- Jobs (Kompression, keine Retention)
SELECT * FROM timescaledb_information.jobs WHERE hypertable_name = 'ltss';

Retention Policy prüfen

\c ltss
-- Sollte leer sein für unbegrenzte Speicherung
SELECT * FROM timescaledb_information.jobs WHERE hypertable_name = 'ltss';

Versionsinformationen (Februar 2026)

Troubleshooting

Problem: invalid LC_COLLATE locale nameLösung: locale-gen ausführen oder C.UTF-8 verwenden

Problem: new encoding (UTF8) is incompatible with template databaseLösung: TEMPLATE template0 beim CREATE DATABASE angeben

Problem: permission denied for schema publicLösung: GRANT ALL ON SCHEMA public TO hass; ausführen

Problem: NULL-Byte Fehler bei States/Events – Lösung: Betroffene Entities in recorder.exclude hinzufügen

Problem: Unicode-Zeichen (°C, ö) werden nicht korrekt gespeichert – Lösung: ?client_encoding=utf8 im Connection String ergänzen

Ergebnis