Skip to content

Local repo creation fails: hardcoded SSH port 22 + wrong (agent-side) SSH identity used for server-side borg init #356

Description

@Rhonstin

Version: 2.64.1 (Docker image marcpope/borgbackupserver:latest)

Summary

Creating a "local" repository via POST /api/v1/clients/{id}/repositories (and, as far as I can tell, the equivalent web UI flow) fails borg init in two ways, because the init step runs on the server itself but is built as if it were running on the agent.

Bug 1: hardcoded SSH port 22, ignoring the configured ssh_port setting

AdminApiController::createRepository() runs borg init synchronously on the server:

src/Controllers/Api/AdminApiController.php:434
$env = BorgCommandBuilder::buildEnv($repo);

buildEnv() is called with no $sshPort argument, so it falls back to the hardcoded default:

src/Services/BorgCommandBuilder.php:204-205
$port = $sshPort ?? 22;
$env['BORG_RSH'] = "ssh -i /etc/bbs-agent/ssh_key -p {$port} ...";

This ignores the ssh_port value stored in settings (used correctly elsewhere for actual agent backup/restore tasks). If the server's SSH port has been changed from the default 22 (e.g. SSH_PORT=2222 in the Docker Compose env, which is the value the README's Quick Start / docker-compose.yml itself uses), repo creation fails immediately with:

Remote: ssh: connect to host <server-ip> port 22: Connection refused

Fix: read the ssh_port setting and pass it into buildEnv($repo, ..., $sshPort) in createRepository() (and any other server-side call sites that build an init/access command for a "local" repo).

Bug 2: server-side init uses the agent's SSH identity file, which doesn't exist on the server

Even after working around Bug 1 (by also publishing container port 22), borg init still fails, because buildEnv() defaults to $forAgent = true:

src/Services/BorgCommandBuilder.php:180
public static function buildEnv(array $repo, bool $forAgent = true, ?int $sshPort = null, ?array $remoteSshConfig = null): array

For an SSH-style repo path this branch sets BORG_RSH to use /etc/bbs-agent/ssh_key:

src/Services/BorgCommandBuilder.php:205
$env['BORG_RSH'] = "ssh -i /etc/bbs-agent/ssh_key -p {$port} ...";

That path is the agent's installed private key, present on client machines — it does not exist inside the bbs server container, where createRepository() actually executes (proc_open($initCmd, ..., $env) runs in-process on the server via Apache/PHP). The result:

Remote: Warning: Identity file /etc/bbs-agent/ssh_key not accessible: No such file or directory.
Remote: bbs-coolify@<server-ip>: Permission denied (publickey).

Fix: the self-init call in createRepository() should call buildEnv($repo, forAgent: false) (server-side local access, which the code already supports and uses correctly elsewhere — see the else branch a few lines down that sets BORG_BASE_DIR/HOME for www-data), or borg init should operate directly on the local filesystem path (BorgCommandBuilder::getLocalRepoPath(), which the surrounding code already computes for the create-repo-dir helper call a few lines earlier) instead of round-tripping through the repo's ssh:// path.

Workaround (for anyone hitting this)

  1. Publish the container's SSH port on the host as both the configured SSH_PORT and plain 22 (e.g. add "22:22" alongside "${SSH_PORT:-2222}:22" in docker-compose.yml), or revert SSH_PORT to 22.
  2. If borg init still fails on the identity file, run it manually inside the container as www-data with BORG_BASE_DIR/HOME pointed at a writable cache dir, directly against the local repo path (/var/bbs/home/<agent_id>/<repo_name>) instead of the ssh:// path.
  3. After a manual init, chown the repo directory (recursively) to the agent's SSH unix user (ssh_unix_user column in agents, e.g. bbs-agent-<n>) rather than www-data — otherwise the agent-side backup job fails separately with Failed to create/acquire the lock ... Permission denied, since normal backup/restore traffic connects as that unix user, not www-data.

Steps to reproduce

  1. Deploy via the official docker-compose.yml, with SSH_PORT set to anything other than 22 (the compose file's own default is 2222).
  2. Register an agent, then create a local repository for it via the API or UI.
  3. Observe borg init failing as above.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions