Skip to content

add PostgreSQL backend and portable backup system.#3999

Open
JustRin wants to merge 2 commits intoMHSanaei:mainfrom
JustRin:main
Open

add PostgreSQL backend and portable backup system.#3999
JustRin wants to merge 2 commits intoMHSanaei:mainfrom
JustRin:main

Conversation

@JustRin
Copy link
Copy Markdown

@JustRin JustRin commented Apr 7, 2026

What is the pull request?

Adds PostgreSQL as a second database backend alongside SQLite. Both backends are interchangeable at runtime via the panel UI or environment variables, with automatic data migration and zero data loss. Introduces a portable, driver-agnostic backup format (.xui-backup) that works with both engines. Also fixes several bugs uncovered during PostgreSQL testing.

Which part of the application is affected by the change?

  • Frontend
  • Backend

Type of Changes

  • Bug fix
  • New feature
  • Refactoring
  • Other

Changes

  • Add SQLite/PostgreSQL switching via panel UI and env variables
  • Introduce portable .xui-backup format for cross-backend backups
  • Add connection pooling and PrepareStmt cache for PostgreSQL
  • Fix raw SQL double-quote bug breaking queries on PostgreSQL
  • Fix GORM record-not-found log spam on every Xray config poll
  • Add database section to Settings with full EN/RU i18n

Details

New database layer (database/backup.go, database/manager.go, config/database.go):

  • SwitchDatabase() — saves portable backup → tests target → migrates all data → writes new config
  • Portable snapshot: logical JSON+ZIP export/import, driver-agnostic, supports legacy .db import
  • Runtime config stored in database.json outside the panel database (or via XUI_DB_* env vars)

PostgreSQL connection (database/db.go):

  • Connection pool: MaxIdleConns=5, MaxOpenConns=25, ConnMaxLifetime=30m
  • PrepareStmt=true — client-side statement cache eliminates repeated parse overhead

Settings UI (web/html/settings/panel/general.html):

  • Backend selector (radio buttons: SQLite / PostgreSQL)
  • PostgreSQL mode: Local (panel-managed) / External — hides Host/Port in Local mode
  • Test Connection / Switch Database actions
  • Backup & Restore: Export Portable, Export Native SQLite, Import Backup
  • Config Source row hidden in normal state; shown only for env (read-only warning)

Bug fixes:

inbound.go — raw SQL "listen = """ → parameterized "listen = ?" (PostgreSQL treats "" as identifier, not string literal)
setting.go — First() → Limit(1).Find() to suppress GORM error-level log on every Xray config poll
setting.go (controller) — testDatabaseSetting now returns correct success/failure message separately
i18n: [pages.settings.database] section — 40 keys in en_US and ru_RU

Environment variable override (Docker / IaC)

XUI_DB_DRIVER=postgres
XUI_DB_HOST=127.0.0.1
XUI_DB_PORT=5432
XUI_DB_NAME=x-ui
XUI_DB_USER=x-ui
XUI_DB_PASSWORD=secret
XUI_DB_SSLMODE=disable   # or: require, verify-ca, verify-full

When any XUI_DB_* variable is set, the Database section in the UI becomes read-only.

Screenshots

Снимок экрана — 2026-04-07 в 19 33 06 Снимок экрана — 2026-04-07 в 19 33 29 Снимок экрана — 2026-04-07 в 19 33 51

JustRin added 2 commits April 7, 2026 19:18
- Add SQLite/PostgreSQL switching via panel UI and env variables
- Introduce portable .xui-backup format for cross-backend backups
- Add connection pooling and PrepareStmt cache for PostgreSQL
- Fix raw SQL double-quote bug breaking queries on PostgreSQL
- Fix GORM record-not-found log spam on every Xray config poll
- Add database section to Settings with full EN/RU i18n
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant