docs: spell out .spbk and .spde extensions

SelfPost backup / SelfPost domain export — in the guide, security notes,
architecture, and Backup/Export panel copy.

Co-Authored-By: Composer <noreply@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
mixeme
2026-08-09 00:49:43 +03:00
parent 1dd0aa9fea
commit 18880a8286
7 changed files with 27 additions and 17 deletions
+3
View File
@@ -51,6 +51,9 @@ Format follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/); version
### Changed
- Document what `.spbk` and `.spde` stand for (SelfPost backup / SelfPost domain
export) in the operator guide, security notes, architecture, and the Backup /
Export panel copy.
- Docs aligned with the code: setup URL is `/setup/<token>` (README and
guide; local trial rewrites the printed `https://<hostname>/…` link to
`http://127.0.0.1:8080/…`); domain import uses the file extension / magic
+4 -4
View File
@@ -290,10 +290,10 @@ restore. Stopped-container `tar` of `./data` is safe (see guide).
([internal/secretfile](../internal/secretfile/secretfile.go)): password →
scrypt → AES-256-GCM over 64 KiB chunks, each authenticated with the header,
its counter and an end-of-stream flag (so truncation and reordering fail to
open). Full backup `.tar.gz``.spbk`, domain export `.json``.spde`; the
plain forms remain the default. Domain import detects the envelope by magic
bytes; an encrypted full backup is converted back with `selfpost-backup
-decrypt` before restore.
open). Full backup `.tar.gz``.spbk` (SelfPost backup), domain export
`.json``.spde` (SelfPost domain export); the plain forms remain the
default. Domain import detects the envelope by magic bytes; an encrypted full
backup is converted back with `selfpost-backup -decrypt` before restore.
---
+5 -2
View File
@@ -332,8 +332,11 @@ file that comes down is an encrypted envelope instead of the plain archive:
| Artefact | Plain | Encrypted |
|----------|-------|-----------|
| Full backup | `.tar.gz` | `.spbk` |
| Domain export | `.json` | `.spde` |
| Full backup | `.tar.gz` | `.spbk` (**S**elf**P**ost **b**ac**k**up) |
| Domain export | `.json` | `.spde` (**S**elf**P**ost **d**omain **e**xport) |
The suffixes are for the operator only — the server detects an encrypted file
by its magic bytes (`SELFPOST1`), not by the extension.
The key is derived from the password with scrypt and the contents are sealed
with AES-256-GCM, in chunks, so a truncated or altered file fails to open rather
+4 -3
View File
@@ -80,9 +80,10 @@ Hardening сверх обязательного (security-заголовки, п
аутентифицирован заголовком, номером и флагом конца потока — обрезанный или
подменённый файл не открывается вместо тихого восстановления «хвоста».
Формат и обёртка: [internal/secretfile](../internal/secretfile/secretfile.go).
- Расширения: `.spbk` (полный бэкап), `.spde` (экспорт домена); незашифрованные
остаются `.tar.gz` / `.json`. Импорт домена определяет шифрование по magic
файла, а не по расширению.
- Расширения: `.spbk` (**S**elf**P**ost **b**ac**k**up — полный бэкап),
`.spde` (**S**elf**P**ost **d**omain **e**xport — экспорт домена);
незашифрованные остаются `.tar.gz` / `.json`. Импорт домена определяет
шифрование по magic файла, а не по расширению.
- Пароль нигде не сохраняется: восстановить файл без него нельзя. Пароль в CLI —
только через `SELFPOST_BACKUP_PASSWORD` или `-password-file`, никогда
аргументом (список процессов читается любым процессом контейнера).
+6 -4
View File
@@ -11,7 +11,8 @@
<p class="muted"><strong>The backup file is a secret</strong> (it contains
private keys and credentials). Store and transfer it securely and delete it
once the restore succeeds. Encrypting it below is the simplest way to do that:
the download is then a <code>.spbk</code> file that only the password opens.</p>
the download is then a <code>.spbk</code> file (SelfPost backup) that only
the password opens.</p>
{{if .BackupErr}}<p class="error">{{.BackupErr}}</p>{{end}}
<form method="post" action="/backup">
{{template "encryptfields" .}}
@@ -22,9 +23,10 @@
<div class="card">
<h2>Import a domain</h2>
<p class="muted">Move a single domain here from another SelfPost instance using
a domain export file (from that domain's page). Its DKIM key and application
passwords come across, so the published DNS record needs no change. The export
file is a secret, like a full backup.</p>
a domain export file (from that domain's page) — plain <code>.json</code> or
encrypted <code>.spde</code> (SelfPost domain export). Its DKIM key and
application passwords come across, so the published DNS record needs no
change. The export file is a secret, like a full backup.</p>
{{if .ImportErr}}<p class="error">{{.ImportErr}}</p>{{end}}
<form method="post" action="/domains/import" enctype="multipart/form-data">
<label for="importfile">Domain export file</label>
+1 -1
View File
@@ -299,7 +299,7 @@
<p class="muted"><strong>The export file is a secret</strong> — it contains the
private DKIM key and application passwords. Transfer it securely and delete it
after the import, or encrypt it below and move a <code>.spde</code> file
instead; the import form asks for the password.</p>
(SelfPost domain export) instead; the import form asks for the password.</p>
{{if .ExportErr}}<p class="error">{{.ExportErr}}</p>{{end}}
<form method="post" action="/domains/{{.Domain.ID}}/export">
{{template "encryptfields" .}}
+4 -3
View File
@@ -1,9 +1,10 @@
{{/* Password fields shared by the full-backup and domain-export forms. The
checkbox is the switch: unticked, the download keeps its historic plain
form (.tar.gz / .json); ticked, the file is sealed in a password-encrypted
envelope (.spbk / .spde). The fields start hidden and are revealed by
panel.js — with JavaScript blocked they are simply always visible, and the
server still decides from the checkbox alone. */}}
envelope (.spbk = SelfPost backup, .spde = SelfPost domain export). The
fields start hidden and are revealed by panel.js — with JavaScript blocked
they are simply always visible, and the server still decides from the
checkbox alone. */}}
{{define "encryptfields"}}
<div class="encrypt">
<label class="check">