diff --git a/apps/docs/docs/management/backup.mdx b/apps/docs/docs/management/backup.mdx index 1c47291d3..da4260998 100644 --- a/apps/docs/docs/management/backup.mdx +++ b/apps/docs/docs/management/backup.mdx @@ -30,8 +30,9 @@ needed to restore encrypted integration credentials. Select a Homarr backup ZIP. The browser previews entity counts, board names, and required database migrations before the archive is uploaded. -Restoring replaces the current SQLite database and cannot be undone. After a successful restore, the Next.js process -restarts and the page reloads when Homarr is ready. +Restoring replaces the current SQLite database and cannot be undone. It also invalidates the current database session. +After a successful management restore, Homarr waits for the restarted server and sends the administrator to sign in +again. The first-run onboarding restore keeps its existing board destination. A backup can be restored on another Homarr instance. When its `SECRET_ENCRYPTION_KEY` differs, Homarr re-encrypts stored integration secrets for the target instance. Version metadata is used to apply compatible migrations. diff --git a/apps/nextjs/src/components/backup/database-restore-flow.tsx b/apps/nextjs/src/components/backup/database-restore-flow.tsx index 7b43d7e3a..79e094c38 100644 --- a/apps/nextjs/src/components/backup/database-restore-flow.tsx +++ b/apps/nextjs/src/components/backup/database-restore-flow.tsx @@ -204,8 +204,12 @@ export const DatabaseRestoreFlow = ({ variant = "card", onRestoreComplete }: Dat } onRestoreComplete?.(); - const destination = - variant === "standalone" && homeBoardName ? `/boards/${encodeURIComponent(homeBoardName)}` : null; + let destination: string | null = null; + if (variant === "standalone" && homeBoardName) { + destination = `/boards/${encodeURIComponent(homeBoardName)}`; + } else if (variant === "card") { + destination = "/auth/login"; + } startReadinessCheck(restartAfterMs, destination); }, [file, onRestoreComplete, startReadinessCheck, t, variant]); @@ -317,6 +321,7 @@ export const DatabaseRestoreFlow = ({ variant = "card", onRestoreComplete }: Dat startReadinessCheck(0)} onReload={() => window.location.reload()} /> diff --git a/apps/nextjs/src/components/backup/restore-progress-panel.tsx b/apps/nextjs/src/components/backup/restore-progress-panel.tsx index 0157294f6..160788d8e 100644 --- a/apps/nextjs/src/components/backup/restore-progress-panel.tsx +++ b/apps/nextjs/src/components/backup/restore-progress-panel.tsx @@ -11,11 +11,18 @@ export type RestoreProgressStatus = "restoring" | "restarting" | "timedOut"; interface RestoreProgressPanelProps { active: boolean; status: RestoreProgressStatus; + reloginRequired?: boolean; onRetry: () => void; onReload: () => void; } -export const RestoreProgressPanel = ({ active, status, onRetry, onReload }: RestoreProgressPanelProps) => { +export const RestoreProgressPanel = ({ + active, + status, + reloginRequired = false, + onRetry, + onReload, +}: RestoreProgressPanelProps) => { const t = useI18n("management.page.tool.backup.restore"); const tCommon = useI18n("common"); const reduceMotion = useReducedMotion(); @@ -63,6 +70,12 @@ export const RestoreProgressPanel = ({ active, status, onRetry, onReload }: Rest + {reloginRequired && !isRestoring ? ( + + {t("progress.relogin")} + + ) : null} + {isTimedOut ? (