Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions docs/changes.rst
Original file line number Diff line number Diff line change
Expand Up @@ -426,6 +426,8 @@ New features:
and repository chunk statistics, #9579, #9757
- prune: show total vs matching archives in output, #9262
- create --exclude-dataless: macOS: skip cloud files not materialized locally, #9746
- support BORG_HOSTNAME and BORG_USERNAME env vars to override the hostname/username stored
in archives and used by the {hostname}/{user} placeholders, #9651
- Minimal implementation of "related repositories", #9645

This feature allows multiple repositories to share deduplication-relevant secrets
Expand Down
8 changes: 8 additions & 0 deletions docs/usage/general/environment.rst.inc
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,14 @@ General:
So, if you have a all-zero MAC address or other reasons to better externally control the host id, just set this
environment variable to a unique value. If all your FQDNs are unique, you can just use the FQDN. If not,
use fqdn@uniqueid.
BORG_HOSTNAME
When set, use this value as the hostname (instead of the auto-detected one), e.g. to run borg
on one host, but impersonate another host (see #9651). This affects the hostname stored in newly
created archives as well as the ``{hostname}`` placeholder.
BORG_USERNAME
When set, use this value as the username (instead of the auto-detected one), e.g. to run borg
as one user, but impersonate another user. This affects the username stored in newly created
archives as well as the ``{user}`` placeholder.
BORG_LOGGING_CONF
When set, use the given filename as INI_-style logging configuration.
A basic example conf can be found at ``docs/misc/logging.conf``.
Expand Down
4 changes: 2 additions & 2 deletions src/borg/archive.py
Original file line number Diff line number Diff line change
Expand Up @@ -632,8 +632,8 @@ def save(self, name=None, comment=None, timestamp=None, stats=None, additional_m
'comment': comment or '',
'items': self.items_buffer.chunks,
'cmdline': sys.argv,
'hostname': hostname,
'username': getuser(),
'hostname': os.environ.get('BORG_HOSTNAME') or hostname,
'username': os.environ.get('BORG_USERNAME') or getuser(),
'time': start.strftime(ISO_FORMAT),
'time_end': end.strftime(ISO_FORMAT),
'cwd': self.cwd,
Expand Down
4 changes: 2 additions & 2 deletions src/borg/helpers/parseformat.py
Original file line number Diff line number Diff line change
Expand Up @@ -211,11 +211,11 @@ def replace_placeholders(text, overrides={}):
'pid': os.getpid(),
'fqdn': fqdn,
'reverse-fqdn': '.'.join(reversed(fqdn.split('.'))),
'hostname': hostname,
'hostname': os.environ.get('BORG_HOSTNAME') or hostname,
'now': DatetimeWrapper(current_time.astimezone(None)),
'utcnow': DatetimeWrapper(current_time),
'unixtime': int(current_time.timestamp()),
'user': getosusername(),
'user': os.environ.get('BORG_USERNAME') or getosusername(),
'uuid4': str(uuid.uuid4()),
'borgversion': borg_version,
'borgmajor': '%d' % borg_version_tuple[:1],
Expand Down
12 changes: 12 additions & 0 deletions src/borg/testsuite/archiver.py
Original file line number Diff line number Diff line change
Expand Up @@ -2251,6 +2251,18 @@ def test_create_json(self):
assert len(archive['id']) == 64
assert 'stats' in archive

def test_create_hostname_username_override(self):
self.cmd('init', '--encryption=repokey', self.repository_location)
self.create_regular_file('file1', size=1024 * 80)
with environment_variable(BORG_HOSTNAME='foo_host', BORG_USERNAME='bar_user'):
# the override is also used to fill the {hostname}/{user} placeholders in the archive name:
self.cmd('create', self.repository_location + '::{hostname}-{user}', 'input')
info = json.loads(self.cmd('info', '--json', self.repository_location + '::foo_host-bar_user'))
archive = info['archives'][0]
assert archive['name'] == 'foo_host-bar_user'
assert archive['hostname'] == 'foo_host'
assert archive['username'] == 'bar_user'

def test_create_topical(self):
self.create_regular_file('file1', size=1024 * 80)
time.sleep(1) # file2 must have newer timestamps than file1
Expand Down
Loading