From 5e2712273523104c2a2b45ba934bd287054125d3 Mon Sep 17 00:00:00 2001 From: Thomas Waldmann Date: Thu, 25 Jun 2026 21:06:14 +0200 Subject: [PATCH] replace create --hostname/--username with BORG_HOSTNAME/BORG_USERNAME env vars, fixes #9651 The --hostname/--username options on borg create (added in 2.0.0b21, #9402) are removed in favor of the BORG_HOSTNAME / BORG_USERNAME environment variables. When set, these override the hostname/username stored in newly created archives and used by the {hostname}/{user} placeholders (so they also apply to archive names, prune --glob-archives, check, etc.). Useful to run borg on host A but impersonate host B. The env vars are read at the point of use; fqdn/hostid (see BORG_HOST_ID) and the auto-detection are intentionally left untouched. Co-Authored-By: Claude Opus 4.8 --- docs/changes.rst | 3 +++ docs/usage/create.rst.inc | 6 ------ docs/usage/general/environment.rst.inc | 8 ++++++++ src/borg/archive.py | 8 ++------ src/borg/archiver/create_cmd.py | 20 ------------------- src/borg/helpers/parseformat.py | 4 ++-- .../testsuite/archiver/create_cmd_test.py | 10 +++++++--- 7 files changed, 22 insertions(+), 37 deletions(-) diff --git a/docs/changes.rst b/docs/changes.rst index 566c3d4610..682a083048 100644 --- a/docs/changes.rst +++ b/docs/changes.rst @@ -201,6 +201,9 @@ New features: - prune: show total vs matching archives in output, #9262 - prune: add --json option, #9222 - archive: preserve cwd archive metadata, #9495 +- create: replace the --hostname/--username options (added in 2.0.0b21) with the + BORG_HOSTNAME and BORG_USERNAME env vars. When set, they override the hostname/username + stored in newly created archives and used by the {hostname}/{user} placeholders, #9651 Fixes: diff --git a/docs/usage/create.rst.inc b/docs/usage/create.rst.inc index 27bdb7c86d..7437733313 100644 --- a/docs/usage/create.rst.inc +++ b/docs/usage/create.rst.inc @@ -107,10 +107,6 @@ borg create +-------------------------------------------------------+---------------------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ | | ``-C COMPRESSION``, ``--compression COMPRESSION`` | select compression algorithm, see the output of the "borg help compression" command for details. | +-------------------------------------------------------+---------------------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ - | | ``--hostname HOSTNAME`` | explicitly set hostname for the archive | - +-------------------------------------------------------+---------------------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ - | | ``--username USERNAME`` | explicitly set username for the archive | - +-------------------------------------------------------+---------------------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ | | ``--tags TAG`` | add tags to archive (comma-separated or multiple arguments) | +-------------------------------------------------------+---------------------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ @@ -181,8 +177,6 @@ borg create --timestamp TIMESTAMP manually specify the archive creation date/time (yyyy-mm-ddThh:mm:ss[(+|-)HH:MM] format, (+|-)HH:MM is the UTC offset, default: local time zone). Alternatively, give a reference file/directory. --chunker-params PARAMS specify the chunker parameters (ALGO, CHUNK_MIN_EXP, CHUNK_MAX_EXP, HASH_MASK_BITS, HASH_WINDOW_SIZE). default: buzhash,19,23,21,4095 -C COMPRESSION, --compression COMPRESSION select compression algorithm, see the output of the "borg help compression" command for details. - --hostname HOSTNAME explicitly set hostname for the archive - --username USERNAME explicitly set username for the archive --tags TAG add tags to archive (comma-separated or multiple arguments) diff --git a/docs/usage/general/environment.rst.inc b/docs/usage/general/environment.rst.inc index 120025979c..fb3eaca53c 100644 --- a/docs/usage/general/environment.rst.inc +++ b/docs/usage/general/environment.rst.inc @@ -49,6 +49,14 @@ General: So, if you have an all-zero MAC address or other reasons to better control the host id externally, 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. 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_LOCK_WAIT You can set the default value for the ``--lock-wait`` option with this, so you do not need to give it as a command line option. diff --git a/src/borg/archive.py b/src/borg/archive.py index 07a1932941..17a7d4dc14 100644 --- a/src/borg/archive.py +++ b/src/borg/archive.py @@ -475,8 +475,6 @@ def __init__( log_json=False, iec=False, deleted=False, - hostname=None, - username=None, ): name_is_id = isinstance(name, bytes) if not name_is_id: @@ -495,8 +493,6 @@ def __init__( self.name_in_manifest = name # can differ from .name later (if borg check fixed duplicate archive names) self.comment = None self.tags = None - self.hostname = hostname if hostname is not None else platform.hostname - self.username = username if username is not None else getuser() self.numeric_ids = numeric_ids self.noatime = noatime self.noctime = noctime @@ -658,8 +654,8 @@ def save(self, name=None, comment=None, timestamp=None, stats=None, additional_m "item_ptrs": item_ptrs, # see #1473 "command_line": join_cmd(sys.argv), "cwd": self.cwd, - "hostname": self.hostname, - "username": self.username, + "hostname": os.environ.get("BORG_HOSTNAME") or platform.hostname, + "username": os.environ.get("BORG_USERNAME") or getuser(), "time": nominal.isoformat(timespec="microseconds"), "start": start.isoformat(timespec="microseconds"), "end": end.isoformat(timespec="microseconds"), diff --git a/src/borg/archiver/create_cmd.py b/src/borg/archiver/create_cmd.py index 44cb4fbc23..ec98aab253 100644 --- a/src/borg/archiver/create_cmd.py +++ b/src/borg/archiver/create_cmd.py @@ -252,8 +252,6 @@ def create_inner(archive, cache, fso): start=t0, log_json=args.log_json, iec=args.iec, - hostname=args.hostname, - username=args.username, ) metadata_collector = MetadataCollector( noatime=not args.atime, @@ -1013,24 +1011,6 @@ def build_parser_create(self, subparsers, common_parser, mid_common_parser): action=Highlander, help="select compression algorithm, see the output of the " '"borg help compression" command for details.', ) - archive_group.add_argument( - "--hostname", - metavar="HOSTNAME", - dest="hostname", - type=str, - default=None, - action=Highlander, - help="explicitly set hostname for the archive", - ) - archive_group.add_argument( - "--username", - metavar="USERNAME", - dest="username", - type=str, - default=None, - action=Highlander, - help="explicitly set username for the archive", - ) archive_group.add_argument( "--tags", metavar="TAG", diff --git a/src/borg/helpers/parseformat.py b/src/borg/helpers/parseformat.py index b8d9f89a9a..0238d2fa7b 100644 --- a/src/borg/helpers/parseformat.py +++ b/src/borg/helpers/parseformat.py @@ -403,11 +403,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()), "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], diff --git a/src/borg/testsuite/archiver/create_cmd_test.py b/src/borg/testsuite/archiver/create_cmd_test.py index a65d9f9998..56e5d7fce6 100644 --- a/src/borg/testsuite/archiver/create_cmd_test.py +++ b/src/borg/testsuite/archiver/create_cmd_test.py @@ -887,13 +887,17 @@ def test_create_json(archivers, request): assert "stats" in archive -def test_explicit_hostname_and_username(archivers, request): +def test_hostname_and_username_override(archivers, request, monkeypatch): archiver = request.getfixturevalue(archivers) create_regular_file(archiver.input_path, "file1", size=1024 * 80) cmd(archiver, "repo-create", RK_ENCRYPTION) - cmd(archiver, "create", "--hostname", "foo_host", "--username", "bar_user", "test", "input") - info = json.loads(cmd(archiver, "info", "--json", "test")) + monkeypatch.setenv("BORG_HOSTNAME", "foo_host") + monkeypatch.setenv("BORG_USERNAME", "bar_user") + # the override is also used to fill the {hostname}/{user} placeholders in the archive name: + cmd(archiver, "create", "{hostname}-{user}", "input") + info = json.loads(cmd(archiver, "info", "--json", "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"