Let a host with no internet supply the migration script itself
`run` and `rehearse` always fetched migrate_v016.py from GitHub, so a mail server with no route out could not be migrated at all - an air-gapped host, or a clone deliberately cut off so it cannot renew certificates or deliver queued mail for the domains it was copied from. --migration-script takes a local copy instead, still checked against --migration-script-sha256 when one is pinned. Found while staging a production clone for a dress rehearsal: the clone has no route out on purpose, and that is exactly the property that stops a copy of a live mail server doing something in the real world.
This commit is contained in:
@@ -55,6 +55,7 @@ func runRehearse(args []string) (err error) {
|
||||
stalwartCLI := fs.String("stalwart-cli", "stalwart-cli",
|
||||
"path to stalwart-cli (v1.0.2 or later; a separate download from the server) - rehearsal doesn't invoke it, but checks it so `run` doesn't fail after stopping the service")
|
||||
migrationScriptSHA256 := fs.String("migration-script-sha256", "", "pinned sha256 of migrate_v016.py (recommended; the first run prints the hash to pin)")
|
||||
migrationScriptPath := fs.String("migration-script", "", "use a local copy of migrate_v016.py instead of fetching it (for a host with no route to the internet)")
|
||||
minFree := fs.Float64("min-free-multiple", 2.0, "free-space multiple preflight checks for; rehearsal itself copies nothing")
|
||||
keepArtifacts := fs.Bool("keep-artifacts", false, "don't delete work-dir/<run-id> afterward")
|
||||
if err := fs.Parse(args); err != nil {
|
||||
@@ -146,7 +147,7 @@ func runRehearse(args []string) (err error) {
|
||||
if err := os.MkdirAll(runWorkDir, 0o750); err != nil {
|
||||
return checkpoint.StepOutcome{}, err
|
||||
}
|
||||
sum, err := backup.DownloadFile(ctx, httpClient, backup.DefaultMigrationScriptURL, scriptDest, *migrationScriptSHA256)
|
||||
sum, err := backup.ProvideFile(ctx, httpClient, *migrationScriptPath, backup.DefaultMigrationScriptURL, scriptDest, *migrationScriptSHA256)
|
||||
if err != nil {
|
||||
return checkpoint.StepOutcome{}, err
|
||||
}
|
||||
|
||||
@@ -66,6 +66,7 @@ func runRun(args []string) (err error) {
|
||||
pythonPath := fs.String("python", "python3", "path to python3")
|
||||
stalwartCLI := fs.String("stalwart-cli", "stalwart-cli", "path to stalwart-cli (v1.0.2 or later; a separate download from the server)")
|
||||
scriptSHA := fs.String("migration-script-sha256", "", "pinned sha256 of migrate_v016.py")
|
||||
scriptPath := fs.String("migration-script", "", "use a local copy of migrate_v016.py instead of fetching it (for a host with no route to the internet)")
|
||||
binarySHA := fs.String("target-binary-sha256", "", "pinned sha256 of the target release archive")
|
||||
minFree := fs.Float64("min-free-multiple", 2.0, "required free disk space as a multiple of the data directory size")
|
||||
recalcQuotas := fs.Bool("recalculate-quotas", true, "schedule the post-migration quota rebuild")
|
||||
@@ -196,7 +197,7 @@ func runRun(args []string) (err error) {
|
||||
if p.CrossesMajorBoundary {
|
||||
fmt.Println("\n--- dump (service still up) ---")
|
||||
if _, err := store.RunStep(rs, checkpoint.PhaseBackup, "settings-dump", func() (checkpoint.StepOutcome, error) {
|
||||
if _, err := backup.DownloadFile(ctx, httpClient, backup.DefaultMigrationScriptURL, script, *scriptSHA); err != nil {
|
||||
if _, err := backup.ProvideFile(ctx, httpClient, *scriptPath, backup.DefaultMigrationScriptURL, script, *scriptSHA); err != nil {
|
||||
return checkpoint.StepOutcome{}, err
|
||||
}
|
||||
if err := backup.RunSettingsDump(ctx, backup.SettingsDumpOptions{
|
||||
|
||||
Reference in New Issue
Block a user