# Operations Everything done from outside the server is a command, run in the instance repository: `nix run .#sov -- ` (or `sov ` in its dev shell). `sov help` lists them. Each one is idempotent where it can be, never shows a secret, and makes its repository changes as signed commits that the server deploys by itself. ## Day to day | | | |---|---| | Change anything | edit the spec or a site, signed commit, `git push` | | Is everything fine? | `sov status` (the live checks; they also run hourly and alarm on failure) | | Does recovery work? | `sov drill` (also runs monthly and alarms on failure) | ## Secrets `sov secrets` lists every secret: what it is, where it lives, how a new one is made. They are declared next to the code that uses them (`sov.secrets` in the modules). `sov rotate ...` replaces secrets; `sov rotate --all` replaces every secret kept in git: the response to "a key leaked". Generated secrets need nothing from you. For secrets of outside services (healthchecks.io, Hetzner, Bluesky) it opens the right page, tells you what to click, and takes the new value in a hidden prompt. The order is always: the new value works before the old one stops. | Secret kind | What rotation does | |---|---| | restic password | the bucket accepts the new password, the server switches, the old one is removed | | DNS secondaries secret | the server switches, then the secondaries (Hetzner API) | | host key | both keys may decrypt and open the bucket, the server switches, the old key is removed | | mirror deploy key | the server makes a new key; you register it on the mirror | | pasted tokens | new token stored and deployed; you delete the old one on the service | ## The owner's key `sov key rotate` makes a new owner key (in the file git signs with), registers it everywhere (server login, deploy signatures, secrets, source bucket, Tangled), switches, and removes the old key everywhere. The one step left to you is printed: the key on GitHub. If the owner's key is lost: use the paper key (below) to decrypt, reinstall from the source bucket (`sov install`, through the provider's rescue system), then `sov key rotate` and `sov paper print`. ## The paper recovery key `sov paper print` makes a new recovery key (age): every secret is encrypted to it, and it opens the source bucket. The previous paper key stops working. It writes a printable sheet: the key in short lines with check codes and a QR code, plus the recovery steps for this instance. Print it, store it offline, delete the file. `sov paper check` (yearly; the alarm reminds you): type the key in from the paper, line by line. It verifies the key decrypts the secrets and opens the bucket, and resets the reminder. ## Once per new thing | | | |---|---| | A repository on the knot | `sov add repo ""`, then add the printed entry to the spec | | A DNS zone | add it to the spec's `dns.records`, deploy, `sov add zone `, then point the domain's nameservers to `spec.dns.nameservers` | | A domain moved to INWX | `sov add domain --prices `, `--check`, then without flags (asks for the INWX login and auth codes) | | A GitHub mirror | `repos..mirror = { owner; name; }`, deploy, create the repository, register the key: `ssh admin@ sudo ssh-keygen -y -f /var/lib/sov/secrets/mirror_key_` as deploy key with write access | ## Recovery `sov install @` wipes the machine and installs the instance; on first boot it restores the state from the source bucket and starts with the same identity. The monthly drill does exactly this on a temporary VM. The paper sheet lists the steps for the case where everything else is lost. The source bucket's door (in the box's `.ssh/authorized_keys`, kept by `sov rotate host_key`): ``` command="rclone serve restic --stdio /home/",restrict ssh-ed25519 ```