setName('backup:key:init') ->setDescription('Create the backup key, protected by a passphrase you keep safe') ->addOption('passphrase-file', null, InputOption::VALUE_REQUIRED, 'Read the passphrase from this file instead of asking') ->setHelp(<<<'HELP' Creates the master key that encrypts all backups of this installation. The server keeps the key (encrypted with this instance's secret) so scheduled backups can run. A copy protected by your passphrase goes into every backup location and into the recovery kit (occ backup:key:kit). To restore on a new server you need the recovery kit and the passphrase. Example: occ backup:key:init occ backup:key:kit --output=/root/ng_backup-recovery-kit.json HELP); } protected function execute(InputInterface $input, OutputInterface $output): int { if ($this->keys->isInitialized()) { $output->writeln('A backup key already exists (fingerprint ' . $this->keys->fingerprint() . ').'); return 1; } $file = $input->getOption('passphrase-file'); if ($file !== null) { $pass = rtrim((string)@file_get_contents($file), "\r\n"); } else { $helper = $this->getHelper('question'); $q = (new Question('Passphrase (min. 12 characters): '))->setHidden(true)->setHiddenFallback(false); $pass = (string)$helper->ask($input, $output, $q); $again = (string)$helper->ask($input, $output, (new Question('Repeat passphrase: '))->setHidden(true)->setHiddenFallback(false)); if ($pass !== $again) { $output->writeln('The passphrases do not match.'); return 1; } } try { $this->keys->initialize($pass); } catch (\InvalidArgumentException $e) { $output->writeln('' . $e->getMessage() . ''); return 1; } $output->writeln('Backup key created, fingerprint ' . $this->keys->fingerprint() . '.'); $output->writeln('Next: save the recovery kit with occ backup:key:kit --output=FILE and confirm with occ backup:key:confirm.'); return 0; } }