backup: do not make systemd service wait for backup to complete
fixes #421
This commit is contained in:
parent
4855404f5d
commit
96a8753548
8 changed files with 97 additions and 11 deletions
|
|
@ -347,6 +347,12 @@
|
||||||
"blocks-borgbackup-maintenance": [
|
"blocks-borgbackup-maintenance": [
|
||||||
"blocks-borgbackup.html#blocks-borgbackup-maintenance"
|
"blocks-borgbackup.html#blocks-borgbackup-maintenance"
|
||||||
],
|
],
|
||||||
|
"blocks-borgbackup-maintenance-manuql": [
|
||||||
|
"blocks-borgbackup.html#blocks-borgbackup-maintenance-manuql"
|
||||||
|
],
|
||||||
|
"blocks-borgbackup-maintenance-restore": [
|
||||||
|
"blocks-borgbackup.html#blocks-borgbackup-maintenance-restore"
|
||||||
|
],
|
||||||
"blocks-borgbackup-maintenance-troubleshooting": [
|
"blocks-borgbackup-maintenance-troubleshooting": [
|
||||||
"blocks-borgbackup.html#blocks-borgbackup-maintenance-troubleshooting"
|
"blocks-borgbackup.html#blocks-borgbackup-maintenance-troubleshooting"
|
||||||
],
|
],
|
||||||
|
|
@ -1373,6 +1379,12 @@
|
||||||
"blocks-restic-maintenance": [
|
"blocks-restic-maintenance": [
|
||||||
"blocks-restic.html#blocks-restic-maintenance"
|
"blocks-restic.html#blocks-restic-maintenance"
|
||||||
],
|
],
|
||||||
|
"blocks-restic-maintenance-manuql": [
|
||||||
|
"blocks-restic.html#blocks-restic-maintenance-manuql"
|
||||||
|
],
|
||||||
|
"blocks-restic-maintenance-restore": [
|
||||||
|
"blocks-restic.html#blocks-restic-maintenance-restore"
|
||||||
|
],
|
||||||
"blocks-restic-maintenance-troubleshooting": [
|
"blocks-restic-maintenance-troubleshooting": [
|
||||||
"blocks-restic.html#blocks-restic-maintenance-troubleshooting"
|
"blocks-restic.html#blocks-restic-maintenance-troubleshooting"
|
||||||
],
|
],
|
||||||
|
|
|
||||||
|
|
@ -386,8 +386,13 @@ in
|
||||||
${serviceName} = mkMerge [
|
${serviceName} = mkMerge [
|
||||||
{
|
{
|
||||||
serviceConfig = {
|
serviceConfig = {
|
||||||
# Makes the systemd service wait for the backup to be done before changing state to inactive.
|
# Purposely not a oneshot systemd service otherwise
|
||||||
Type = "oneshot";
|
# the service waits on the completion the backup before deactivating.
|
||||||
|
# This seems like a nice property at first but there is one annoying
|
||||||
|
# edge case when deploying. If a backup job somehow is started when
|
||||||
|
# the deploy happens, the deploy will wait on the service to finish
|
||||||
|
# before considering the deploy done. And worse, it will consider the
|
||||||
|
# deploy as failed if the backup fails, which is not what you want.
|
||||||
Nice = lib.mkForce cfg.performance.niceness;
|
Nice = lib.mkForce cfg.performance.niceness;
|
||||||
IOSchedulingClass = lib.mkForce cfg.performance.ioSchedulingClass;
|
IOSchedulingClass = lib.mkForce cfg.performance.ioSchedulingClass;
|
||||||
IOSchedulingPriority = lib.mkForce cfg.performance.ioPriority;
|
IOSchedulingPriority = lib.mkForce cfg.performance.ioPriority;
|
||||||
|
|
@ -414,6 +419,7 @@ in
|
||||||
in
|
in
|
||||||
{
|
{
|
||||||
script = script.preStart;
|
script = script.preStart;
|
||||||
|
# Makes the systemd service wait for the backup to be done before changing state to inactive.
|
||||||
serviceConfig.Type = "oneshot";
|
serviceConfig.Type = "oneshot";
|
||||||
serviceConfig.LoadCredential = script.loadCredentials;
|
serviceConfig.LoadCredential = script.loadCredentials;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,7 @@
|
||||||
Defined in [`/modules/blocks/borgbackup.nix`](@REPO@/modules/blocks/borgbackup.nix).
|
Defined in [`/modules/blocks/borgbackup.nix`](@REPO@/modules/blocks/borgbackup.nix).
|
||||||
|
|
||||||
This block sets up a backup job using [BorgBackup][].
|
This block sets up a backup job using [BorgBackup][].
|
||||||
|
It is heavily based on the nixpkgs BorgBackup module.
|
||||||
|
|
||||||
[borgbackup]: https://www.borgbackup.org/
|
[borgbackup]: https://www.borgbackup.org/
|
||||||
|
|
||||||
|
|
@ -229,6 +230,36 @@ See [Backups Dashboard and Alert](blocks-monitoring.html#blocks-monitoring-backu
|
||||||
|
|
||||||
## Maintenance {#blocks-borgbackup-maintenance}
|
## Maintenance {#blocks-borgbackup-maintenance}
|
||||||
|
|
||||||
|
### Manual Backup {#blocks-borgbackup-maintenance-manuql}
|
||||||
|
|
||||||
|
To launch a backup manually, just run:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
systemctl start <systemd-service-name>
|
||||||
|
```
|
||||||
|
|
||||||
|
You can easily discover the systemd service name you need by either listing the units:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
systemctl list-units 'borgbackup*'
|
||||||
|
```
|
||||||
|
|
||||||
|
Or by autocompleting the unit name with `<TAB>`:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
systemctl start borgbackup<TAB><TAB>
|
||||||
|
```
|
||||||
|
|
||||||
|
Note that the systemd services are of `Type=simple` which means the systemd service
|
||||||
|
will not wait for the backup completion to terminate.
|
||||||
|
If you want instead to wait for the backup to complete, use the `--wait` flag:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
systemctl start --wait <systemd-service-name>
|
||||||
|
```
|
||||||
|
|
||||||
|
### Restore {#blocks-borgbackup-maintenance-restore}
|
||||||
|
|
||||||
One command-line helper is provided per backup instance and repository pair to automatically supply the needed secrets.
|
One command-line helper is provided per backup instance and repository pair to automatically supply the needed secrets.
|
||||||
|
|
||||||
The restore script has all the secrets needed to access the repo,
|
The restore script has all the secrets needed to access the repo,
|
||||||
|
|
|
||||||
|
|
@ -413,7 +413,13 @@ in
|
||||||
nameValuePair "${fullName name instance.settings.repository}_restore_gen" {
|
nameValuePair "${fullName name instance.settings.repository}_restore_gen" {
|
||||||
enable = true;
|
enable = true;
|
||||||
wantedBy = [ "multi-user.target" ];
|
wantedBy = [ "multi-user.target" ];
|
||||||
serviceConfig.Type = "oneshot";
|
# Purposely not a oneshot systemd service otherwise
|
||||||
|
# the service waits on the completion the backup before deactivating.
|
||||||
|
# This seems like a nice property at first but there is one annoying
|
||||||
|
# edge case when deploying. If a backup job somehow is started when
|
||||||
|
# the deploy happens, the deploy will wait on the service to finish
|
||||||
|
# before considering the deploy done. And worse, it will consider the
|
||||||
|
# deploy as failed if the backup fails, which is not what you want.
|
||||||
script = (
|
script = (
|
||||||
shb.replaceSecrets {
|
shb.replaceSecrets {
|
||||||
userConfig = instance.settings.repository.secrets // {
|
userConfig = instance.settings.repository.secrets // {
|
||||||
|
|
|
||||||
|
|
@ -3,12 +3,12 @@
|
||||||
Defined in [`/modules/blocks/restic.nix`](@REPO@/modules/blocks/restic.nix).
|
Defined in [`/modules/blocks/restic.nix`](@REPO@/modules/blocks/restic.nix).
|
||||||
|
|
||||||
This block sets up a backup job using [Restic][].
|
This block sets up a backup job using [Restic][].
|
||||||
|
It is heavily based on the nixpkgs Restic module.
|
||||||
|
|
||||||
[restic]: https://restic.net/
|
[restic]: https://restic.net/
|
||||||
|
|
||||||
## Provider Contracts {#blocks-restic-contract-provider}
|
## Provider Contracts {#blocks-restic-contract-provider}
|
||||||
|
|
||||||
|
|
||||||
This block provides the following contracts:
|
This block provides the following contracts:
|
||||||
|
|
||||||
- [backup contract](contracts-backup.html) under the [`shb.restic.instances`][instances] option.
|
- [backup contract](contracts-backup.html) under the [`shb.restic.instances`][instances] option.
|
||||||
|
|
@ -26,7 +26,6 @@ a backup Systemd service and a [restore script](#blocks-restic-maintenance) are
|
||||||
|
|
||||||
## Usage {#blocks-restic-usage}
|
## Usage {#blocks-restic-usage}
|
||||||
|
|
||||||
|
|
||||||
The following examples assume usage of the [sops block][] to provide secrets
|
The following examples assume usage of the [sops block][] to provide secrets
|
||||||
although any blocks providing the [secrets contract][] works too.
|
although any blocks providing the [secrets contract][] works too.
|
||||||
|
|
||||||
|
|
@ -35,7 +34,6 @@ although any blocks providing the [secrets contract][] works too.
|
||||||
|
|
||||||
### One folder backed up manually {#blocks-restic-usage-provider-manual}
|
### One folder backed up manually {#blocks-restic-usage-provider-manual}
|
||||||
|
|
||||||
|
|
||||||
The following snippet shows how to configure
|
The following snippet shows how to configure
|
||||||
the backup of 1 folder to 1 repository.
|
the backup of 1 folder to 1 repository.
|
||||||
We assume that the folder `/var/lib/myfolder` of the service `myservice` must be backed up.
|
We assume that the folder `/var/lib/myfolder` of the service `myservice` must be backed up.
|
||||||
|
|
@ -232,11 +230,44 @@ See [Backups Dashboard and Alert](blocks-monitoring.html#blocks-monitoring-backu
|
||||||
|
|
||||||
## Maintenance {#blocks-restic-maintenance}
|
## Maintenance {#blocks-restic-maintenance}
|
||||||
|
|
||||||
One command-line helper is provided per backup instance and repository pair to automatically supply the needed secrets.
|
### Manual Backup {#blocks-restic-maintenance-manuql}
|
||||||
|
|
||||||
|
To launch a backup manually, just run:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
systemctl start <systemd-service-name>
|
||||||
|
```
|
||||||
|
|
||||||
|
You can easily discover the systemd service name you need by either listing the units:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
systemctl list-units 'restic*'
|
||||||
|
```
|
||||||
|
|
||||||
|
Or by autocompleting the unit name with `<TAB>`:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
systemctl start restic<TAB><TAB>
|
||||||
|
```
|
||||||
|
|
||||||
|
Note that the systemd services are of `Type=simple` which means the systemd service
|
||||||
|
will not wait for the backup completion to terminate.
|
||||||
|
If you want instead to wait for the backup to complete, use the `--wait` flag:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
systemctl start --wait <systemd-service-name>
|
||||||
|
```
|
||||||
|
|
||||||
|
### Restore {#blocks-restic-maintenance-restore}
|
||||||
|
|
||||||
|
One command-line helper is provided per backup instance and repository pair which allows to:
|
||||||
|
|
||||||
|
- list snapshots: `<script> snapshots`
|
||||||
|
- to restore a snapshot: `<script> restore <snapshot>`
|
||||||
|
|
||||||
The restore script has all the secrets needed to access the repo,
|
The restore script has all the secrets needed to access the repo,
|
||||||
it will run `sudo` automatically
|
it will run `sudo` automatically
|
||||||
and the user running it needs to have correct permissions for privilege escalation
|
and the user running it needs to have correct permissions for privilege escalation.
|
||||||
|
|
||||||
In the [multiple directories example](#blocks-restic-usage-multiple) above, the following 6 helpers are provided in the `$PATH`:
|
In the [multiple directories example](#blocks-restic-usage-multiple) above, the following 6 helpers are provided in the `$PATH`:
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -105,7 +105,7 @@ shb.test.runNixOSTest {
|
||||||
|
|
||||||
with subtest("First backup in repo"):
|
with subtest("First backup in repo"):
|
||||||
print(machine.succeed("systemctl cat ${provider.backupService}"))
|
print(machine.succeed("systemctl cat ${provider.backupService}"))
|
||||||
machine.succeed("systemctl start ${provider.backupService}")
|
machine.succeed("systemctl start --wait ${provider.backupService}")
|
||||||
|
|
||||||
with subtest("New content"):
|
with subtest("New content"):
|
||||||
for path in sourceDirectories:
|
for path in sourceDirectories:
|
||||||
|
|
|
||||||
|
|
@ -85,7 +85,7 @@ shb.test.runNixOSTest {
|
||||||
with subtest("backup"):
|
with subtest("backup"):
|
||||||
print(machine.succeed("systemctl cat ${provider.result.backupService}"))
|
print(machine.succeed("systemctl cat ${provider.result.backupService}"))
|
||||||
print(machine.succeed("ls -l /run/hardcodedsecrets/hardcodedsecret_passphrase"))
|
print(machine.succeed("ls -l /run/hardcodedsecrets/hardcodedsecret_passphrase"))
|
||||||
machine.succeed("systemctl start ${provider.result.backupService}")
|
machine.succeed("systemctl start --wait ${provider.result.backupService}")
|
||||||
|
|
||||||
with subtest("drop database"):
|
with subtest("drop database"):
|
||||||
machine.succeed(peer_cmd("DROP DATABASE ${database}", db="postgres"))
|
machine.succeed(peer_cmd("DROP DATABASE ${database}", db="postgres"))
|
||||||
|
|
|
||||||
|
|
@ -143,7 +143,7 @@ let
|
||||||
})
|
})
|
||||||
|
|
||||||
with subtest("First backup in repo A"):
|
with subtest("First backup in repo A"):
|
||||||
machine.succeed("systemctl start ${backupService}")
|
machine.succeed("systemctl start --wait ${backupService}")
|
||||||
|
|
||||||
with subtest("New content"):
|
with subtest("New content"):
|
||||||
machine.succeed("""
|
machine.succeed("""
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue