mirror of
https://github.com/borgmatic-collective/borgmatic.git
synced 2026-07-24 19:03:02 +02:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
22776b123d | ||
|
|
56304fdcad | ||
|
|
3f75e9931f | ||
|
|
227f475e17 | ||
|
|
467ddd0e93 | ||
|
|
be08e889f0 | ||
|
|
94c8a56373 |
@@ -1,3 +1,9 @@
|
||||
1.9.1
|
||||
* #928: Fix the user runtime directory location on macOS (and possibly Cygwin).
|
||||
* #930: Fix an error with the sample systemd service when no credentials are configured.
|
||||
* #931: Fix an error when implicitly upgrading the check state directory from ~/.borgmatic to
|
||||
~/.local/state/borgmatic across filesystems.
|
||||
|
||||
1.9.0
|
||||
* #609: Fix the glob expansion of "source_directories" values to respect the "working_directory"
|
||||
option.
|
||||
@@ -20,6 +26,7 @@
|
||||
cases.
|
||||
* #902: Add loading of encrypted systemd credentials. See the documentation for more information:
|
||||
https://torsion.org/borgmatic/docs/how-to/provide-your-passwords/#using-systemd-service-credentials
|
||||
* #911: Add a "key change-passphrase" action to change the passphrase protecting a repository key.
|
||||
* #914: Fix a confusing apparent hang when when the repository location changes, and instead
|
||||
show a helpful error message.
|
||||
* #915: BREAKING: Rename repository actions like "rcreate" to more explicit names like
|
||||
@@ -31,7 +38,6 @@
|
||||
* #919: Clarify the command-line help for the "--config" flag.
|
||||
* #919: Document a policy for versioning and breaking changes:
|
||||
https://torsion.org/borgmatic/docs/how-to/upgrade/#versioning-and-breaking-changes
|
||||
* #911: Add a "key change-passphrase" action to change the passphrase protecting a repository key.
|
||||
* #921: BREAKING: Change soft failure command hooks to skip only the current repository rather than
|
||||
all repositories in the configuration file.
|
||||
* #922: Replace setup.py (Python packaging metadata) with the more modern pyproject.toml.
|
||||
|
||||
@@ -6,6 +6,7 @@ import logging
|
||||
import os
|
||||
import pathlib
|
||||
import random
|
||||
import shutil
|
||||
|
||||
import borgmatic.borg.check
|
||||
import borgmatic.borg.create
|
||||
@@ -322,7 +323,7 @@ def upgrade_check_times(config, borg_repository_id):
|
||||
f'Upgrading archives check times directory from {borgmatic_source_checks_path} to {borgmatic_state_checks_path}'
|
||||
)
|
||||
os.makedirs(borgmatic_state_path, mode=0o700, exist_ok=True)
|
||||
os.rename(borgmatic_source_checks_path, borgmatic_state_checks_path)
|
||||
shutil.move(borgmatic_source_checks_path, borgmatic_state_checks_path)
|
||||
|
||||
for check_type in ('archives', 'data'):
|
||||
new_path = make_check_time_path(config, borg_repository_id, check_type, 'all')
|
||||
@@ -335,12 +336,12 @@ def upgrade_check_times(config, borg_repository_id):
|
||||
logger.debug(f'Upgrading archives check time file from {old_path} to {new_path}')
|
||||
|
||||
try:
|
||||
os.rename(old_path, temporary_path)
|
||||
shutil.move(old_path, temporary_path)
|
||||
except FileNotFoundError:
|
||||
pass
|
||||
|
||||
os.mkdir(old_path)
|
||||
os.rename(temporary_path, new_path)
|
||||
shutil.move(temporary_path, new_path)
|
||||
|
||||
|
||||
def collect_spot_check_source_paths(
|
||||
|
||||
@@ -91,7 +91,9 @@ def strip_path_prefix_from_extracted_dump_destination(
|
||||
if not databases_directory.endswith('_databases'):
|
||||
continue
|
||||
|
||||
os.rename(subdirectory_path, os.path.join(borgmatic_runtime_directory, databases_directory))
|
||||
shutil.move(
|
||||
subdirectory_path, os.path.join(borgmatic_runtime_directory, databases_directory)
|
||||
)
|
||||
break
|
||||
|
||||
|
||||
|
||||
@@ -876,7 +876,7 @@ def make_parsers():
|
||||
)
|
||||
config_bootstrap_group.add_argument(
|
||||
'--user-runtime-directory',
|
||||
help='Path used for temporary runtime data like bootstrap metadata. Defaults to $XDG_RUNTIME_DIR or /var/run/$UID',
|
||||
help='Path used for temporary runtime data like bootstrap metadata. Defaults to $XDG_RUNTIME_DIR or $TMPDIR or $TEMP or /var/run/$UID',
|
||||
)
|
||||
config_bootstrap_group.add_argument(
|
||||
'--borgmatic-source-directory',
|
||||
|
||||
@@ -30,7 +30,8 @@ def get_borgmatic_runtime_directory(config):
|
||||
'''
|
||||
Given a configuration dict, get the borgmatic runtime directory used for storing temporary
|
||||
runtime data like streaming database dumps and bootstrap metadata. Defaults to
|
||||
$XDG_RUNTIME_DIR/./borgmatic or /run/user/$UID/./borgmatic.
|
||||
$XDG_RUNTIME_DIR/./borgmatic or $TMPDIR/./borgmatic or $TEMP/./borgmatic or
|
||||
/run/user/$UID/./borgmatic.
|
||||
|
||||
The "/./" is taking advantage of a Borg feature such that the part of the path before the "/./"
|
||||
does not get stored in the file path within an archive. That way, the path of the runtime
|
||||
@@ -39,10 +40,10 @@ def get_borgmatic_runtime_directory(config):
|
||||
return expand_user_in_path(
|
||||
os.path.join(
|
||||
config.get('user_runtime_directory')
|
||||
or os.environ.get(
|
||||
'XDG_RUNTIME_DIR',
|
||||
f'/run/user/{os.getuid()}',
|
||||
),
|
||||
or os.environ.get('XDG_RUNTIME_DIR')
|
||||
or os.environ.get('TMPDIR')
|
||||
or os.environ.get('TEMP')
|
||||
or f'/run/user/{os.getuid()}',
|
||||
'.',
|
||||
'borgmatic',
|
||||
)
|
||||
|
||||
@@ -218,7 +218,7 @@ properties:
|
||||
Path for storing temporary runtime data like streaming database
|
||||
dumps and bootstrap metadata. borgmatic automatically creates and
|
||||
uses a "borgmatic" subdirectory here. Defaults to $XDG_RUNTIME_DIR
|
||||
or /run/user/$UID.
|
||||
or or $TMPDIR or $TEMP or /run/user/$UID.
|
||||
example: /run/user/1001/borgmatic
|
||||
user_state_directory:
|
||||
type: string
|
||||
|
||||
@@ -76,6 +76,11 @@ borgmatic created temporary streaming database dumps within the `~/.borgmatic`
|
||||
directory by default. At that time, the path was configurable by the
|
||||
`borgmatic_source_directory` configuration option (now deprecated).
|
||||
|
||||
<span class="minilink minilink-addedin">New in version 1.9.1</span>In addition
|
||||
to `XDG_RUNTIME_DIR`, borgmatic also uses the `TMPDIR` or `TEMP` environment
|
||||
variable if set. `TMPDIR` is available on macOS, while `TEMP` is often
|
||||
available on other platforms.
|
||||
|
||||
Also note that using a database hook implicitly enables the
|
||||
`read_special` configuration option (even if it's disabled in your
|
||||
configuration) to support this dump and restore streaming. See Limitations
|
||||
|
||||
@@ -39,9 +39,15 @@ Save your password as an encrypted credential to `/etc/credstore.encrypted/borgm
|
||||
# systemd-ask-password -n | systemd-creds encrypt - /etc/credstore.encrypted/borgmatic.pw
|
||||
```
|
||||
|
||||
Then uncomment or use the following in your configuration file:
|
||||
|
||||
```yaml
|
||||
encryption_passcommand: "cat ${CREDENTIALS_DIRECTORY}/borgmatic.pw"
|
||||
```
|
||||
|
||||
Note that the name `borgmatic.pw` is hardcoded in the systemd service file.
|
||||
|
||||
If you use multiple different passwords, save them as encrypted credentials to `/etc/credstore.encrypted/borgmatic/`, e.g.,
|
||||
To use multiple different passwords, save them as encrypted credentials to `/etc/credstore.encrypted/borgmatic/`, e.g.,
|
||||
|
||||
```
|
||||
# mkdir /etc/credstore.encrypted/borgmatic
|
||||
@@ -49,17 +55,29 @@ If you use multiple different passwords, save them as encrypted credentials to `
|
||||
# systemd-ask-password -n | systemd-creds encrypt --name=borgmatic_pw2 - /etc/credstore.encrypted/borgmatic/pw2
|
||||
...
|
||||
```
|
||||
|
||||
Ensure that the file names, (e.g. `backupserver1`) match the corresponding part of
|
||||
the `--name` option *after* the underscore (_). The `borgmatic` folder is hardcoded in the systemd service file.
|
||||
the `--name` option *after* the underscore (_), and that the part *before*
|
||||
the underscore matches the directory name (e.g. `borgmatic`).
|
||||
|
||||
Then uncomment or use one of the following in your configuration file. Adjust `borgmatic_backupserver1`
|
||||
according to the name given to the credential.
|
||||
Then, uncomment the appropriate line in the systemd service file:
|
||||
|
||||
```yaml
|
||||
encryption_passcommand: "cat ${CREDENTIALS_DIRECTORY}/borgmatic.pw"
|
||||
```
|
||||
# systemctl edit borgmatic.service
|
||||
...
|
||||
# Load multiple encrypted credentials.
|
||||
LoadCredentialEncrypted=borgmatic:/etc/credstore.encrypted/borgmatic/
|
||||
```
|
||||
|
||||
Finally, use the following in your configuration file:
|
||||
|
||||
```
|
||||
encryption_passcommand: "cat ${CREDENTIALS_DIRECTORY}/borgmatic_backupserver1"
|
||||
```
|
||||
|
||||
Adjust `borgmatic_backupserver1` according to the name given to the credential
|
||||
and the directory set in the service file.
|
||||
|
||||
### Environment variable interpolation
|
||||
|
||||
<span class="minilink minilink-addedin">New in version 1.6.4</span> borgmatic
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
[project]
|
||||
name = "borgmatic"
|
||||
version = "1.9.0"
|
||||
version = "1.9.1"
|
||||
authors = [
|
||||
{ name="Dan Helfman", email="witten@torsion.org" },
|
||||
]
|
||||
|
||||
@@ -10,10 +10,12 @@ Documentation=https://torsion.org/borgmatic/
|
||||
[Service]
|
||||
Type=oneshot
|
||||
|
||||
# Load encrypted credentials.
|
||||
LoadCredentialEncrypted=borgmatic:/etc/credstore.encrypted/borgmatic/
|
||||
# Load single encrypted credential.
|
||||
LoadCredentialEncrypted=borgmatic.pw
|
||||
|
||||
# Load multiple encrypted credentials.
|
||||
# LoadCredentialEncrypted=borgmatic:/etc/credstore.encrypted/borgmatic/
|
||||
|
||||
# Security settings for systemd running as root, optional but recommended to improve security. You
|
||||
# can disable individual settings if they cause problems for your use case. For more details, see
|
||||
# the systemd manual: https://www.freedesktop.org/software/systemd/man/systemd.exec.html
|
||||
|
||||
@@ -381,7 +381,7 @@ def test_upgrade_check_times_moves_checks_from_borgmatic_source_directory_to_sta
|
||||
'/home/user/.local/state/borgmatic/checks'
|
||||
).and_return(False)
|
||||
flexmock(module.os).should_receive('makedirs')
|
||||
flexmock(module.os).should_receive('rename').with_args(
|
||||
flexmock(module.shutil).should_receive('move').with_args(
|
||||
'/home/user/.borgmatic/checks', '/home/user/.local/state/borgmatic/checks'
|
||||
).once()
|
||||
|
||||
@@ -408,13 +408,13 @@ def test_upgrade_check_times_with_checks_already_in_borgmatic_state_directory_do
|
||||
'/home/user/.local/state/borgmatic/checks'
|
||||
).and_return(True)
|
||||
flexmock(module.os).should_receive('makedirs').never()
|
||||
flexmock(module.os).should_receive('rename').never()
|
||||
flexmock(module.shutil).should_receive('move').never()
|
||||
|
||||
flexmock(module).should_receive('make_check_time_path').and_return(
|
||||
'/home/user/.local/state/borgmatic/checks/1234/archives/all'
|
||||
)
|
||||
flexmock(module.os.path).should_receive('isfile').and_return(False)
|
||||
flexmock(module.os).should_receive('rename').never()
|
||||
flexmock(module.shutil).should_receive('move').never()
|
||||
flexmock(module.os).should_receive('mkdir').never()
|
||||
|
||||
module.upgrade_check_times(flexmock(), flexmock())
|
||||
@@ -448,11 +448,11 @@ def test_upgrade_check_times_renames_old_check_paths_to_all():
|
||||
flexmock(module.os.path).should_receive('isfile').with_args(
|
||||
f'{base_path}/data.temp'
|
||||
).and_return(False)
|
||||
flexmock(module.os).should_receive('rename').with_args(
|
||||
flexmock(module.shutil).should_receive('move').with_args(
|
||||
f'{base_path}/archives', f'{base_path}/archives.temp'
|
||||
).once()
|
||||
flexmock(module.os).should_receive('mkdir').with_args(f'{base_path}/archives').once()
|
||||
flexmock(module.os).should_receive('rename').with_args(
|
||||
flexmock(module.shutil).should_receive('move').with_args(
|
||||
f'{base_path}/archives.temp', f'{base_path}/archives/all'
|
||||
).once()
|
||||
|
||||
@@ -484,11 +484,11 @@ def test_upgrade_check_times_renames_data_check_paths_when_archives_paths_are_al
|
||||
flexmock(module.os.path).should_receive('isfile').with_args(f'{base_path}/data').and_return(
|
||||
True
|
||||
)
|
||||
flexmock(module.os).should_receive('rename').with_args(
|
||||
flexmock(module.shutil).should_receive('move').with_args(
|
||||
f'{base_path}/data', f'{base_path}/data.temp'
|
||||
).once()
|
||||
flexmock(module.os).should_receive('mkdir').with_args(f'{base_path}/data').once()
|
||||
flexmock(module.os).should_receive('rename').with_args(
|
||||
flexmock(module.shutil).should_receive('move').with_args(
|
||||
f'{base_path}/data.temp', f'{base_path}/data/all'
|
||||
).once()
|
||||
|
||||
@@ -508,7 +508,7 @@ def test_upgrade_check_times_skips_already_upgraded_check_paths():
|
||||
'/home/user/.local/state/borgmatic/checks/1234/archives/all'
|
||||
)
|
||||
flexmock(module.os.path).should_receive('isfile').and_return(False)
|
||||
flexmock(module.os).should_receive('rename').never()
|
||||
flexmock(module.shutil).should_receive('move').never()
|
||||
flexmock(module.os).should_receive('mkdir').never()
|
||||
|
||||
module.upgrade_check_times(flexmock(), flexmock())
|
||||
@@ -542,11 +542,11 @@ def test_upgrade_check_times_renames_stale_temporary_check_path():
|
||||
flexmock(module.os.path).should_receive('isfile').with_args(
|
||||
f'{base_path}/data.temp'
|
||||
).and_return(False)
|
||||
flexmock(module.os).should_receive('rename').with_args(
|
||||
flexmock(module.shutil).should_receive('move').with_args(
|
||||
f'{base_path}/archives', f'{base_path}/archives.temp'
|
||||
).and_raise(FileNotFoundError)
|
||||
flexmock(module.os).should_receive('mkdir').with_args(f'{base_path}/archives').once()
|
||||
flexmock(module.os).should_receive('rename').with_args(
|
||||
flexmock(module.shutil).should_receive('move').with_args(
|
||||
f'{base_path}/archives.temp', f'{base_path}/archives/all'
|
||||
).once()
|
||||
|
||||
|
||||
@@ -75,10 +75,10 @@ def test_strip_path_prefix_from_extracted_dump_destination_renames_first_matchin
|
||||
]
|
||||
)
|
||||
|
||||
flexmock(module.os).should_receive('rename').with_args(
|
||||
flexmock(module.shutil).should_receive('move').with_args(
|
||||
'/foo/bar/postgresql_databases', '/run/user/0/borgmatic/postgresql_databases'
|
||||
).once()
|
||||
flexmock(module.os).should_receive('rename').with_args(
|
||||
flexmock(module.shutil).should_receive('move').with_args(
|
||||
'/foo/bar/mariadb_databases', '/run/user/0/borgmatic/mariadb_databases'
|
||||
).never()
|
||||
|
||||
|
||||
@@ -44,11 +44,28 @@ def test_get_borgmatic_runtime_directory_uses_config_option():
|
||||
)
|
||||
|
||||
|
||||
def test_get_borgmatic_runtime_directory_falls_back_to_environment_variable():
|
||||
def test_get_borgmatic_runtime_directory_falls_back_to_linux_environment_variable():
|
||||
flexmock(module).should_receive('expand_user_in_path').replace_with(lambda path: path)
|
||||
flexmock(module.os.environ).should_receive('get').with_args(
|
||||
'XDG_RUNTIME_DIR', object
|
||||
).and_return('/tmp')
|
||||
flexmock(module.os.environ).should_receive('get').with_args('XDG_RUNTIME_DIR').and_return(
|
||||
'/tmp'
|
||||
)
|
||||
|
||||
assert module.get_borgmatic_runtime_directory({}) == '/tmp/./borgmatic'
|
||||
|
||||
|
||||
def test_get_borgmatic_runtime_directory_falls_back_to_macos_environment_variable():
|
||||
flexmock(module).should_receive('expand_user_in_path').replace_with(lambda path: path)
|
||||
flexmock(module.os.environ).should_receive('get').with_args('XDG_RUNTIME_DIR').and_return(None)
|
||||
flexmock(module.os.environ).should_receive('get').with_args('TMPDIR').and_return('/tmp')
|
||||
|
||||
assert module.get_borgmatic_runtime_directory({}) == '/tmp/./borgmatic'
|
||||
|
||||
|
||||
def test_get_borgmatic_runtime_directory_falls_back_to_other_environment_variable():
|
||||
flexmock(module).should_receive('expand_user_in_path').replace_with(lambda path: path)
|
||||
flexmock(module.os.environ).should_receive('get').with_args('XDG_RUNTIME_DIR').and_return(None)
|
||||
flexmock(module.os.environ).should_receive('get').with_args('TMPDIR').and_return(None)
|
||||
flexmock(module.os.environ).should_receive('get').with_args('TEMP').and_return('/tmp')
|
||||
|
||||
assert module.get_borgmatic_runtime_directory({}) == '/tmp/./borgmatic'
|
||||
|
||||
|
||||
Reference in New Issue
Block a user