setName('backup:restore:full') ->setDescription('Disaster recovery: restore the database, data directory and config on a fresh installation') ->addArgument('target', InputArgument::REQUIRED, 'Location name or id') ->addArgument('snapshot', InputArgument::REQUIRED, 'Snapshot id (see backup:list)') ->setHelp(<<<'HELP' For a FRESH Nextcloud installation only, same major version as the backup, right after occ maintenance:install, occ backup:key:import and occ backup:target:add -- before anyone else uses this instance. Every app that was enabled when the snapshot was taken must already be installed here (its database tables must exist before the restore can write into them); the command lists what is missing and refuses to continue rather than guess. Steps: the database is replaced (consistent, in one transaction); the data directory is restored directly in place; config.php is merged in -- everything from the backup except the database connection and data directory settings, which stay as occ maintenance:install configured them here. Other files under config/ (if any) are not restored. Afterwards: check trusted_domains and overwritehost/overwriteprotocol match this server, and occ maintenance:repair. Example: occ backup:restore:full offsite 537bf7e9c1a4... HELP); } protected function execute(InputInterface $input, OutputInterface $output): int { try { $target = $this->targets->get($input->getArgument('target')); $snapshot = (string)$input->getArgument('snapshot'); $result = $this->restoreFull->restoreFull($target, $snapshot); } catch (\Throwable $e) { $output->writeln('' . $e->getMessage() . ''); return 1; } $output->writeln(sprintf( 'Database restored (%d tables, %d unchanged), config merged (%d keys), %d data files restored.', count($result['dbReport']['restored']), count($result['dbReport']['skipped']), $result['configKeys'], $result['dataFiles'], )); $output->writeln('Next: check trusted_domains and overwritehost/overwriteprotocol match this server, then occ maintenance:repair.'); return 0; } }