How to update ?

Minor version

Docker

Pull the new image and restart the container.

docker compose pull
docker compose up -d

That’s it.

Debian (manual install)

Backup your config files

Before starting, make sure you have a safe copy of :

  • .env.local
  • config/users.json
  • config/repo.json

Stop the service

systemctl stop borgwarehouse

Fetch the new version

su borgwarehouse
cd borgwarehouse
git pull

Install dependencies

pnpm install --frozen-lockfile

Build the application

pnpm run build

Restart

BorgWarehouse is up-to-date 🥳 !

systemctl start borgwarehouse
Docker migration - v3.1.3 (PUID/PGID)

Migrating to v3.1.3 - Docker

Previous versions required the Docker image to be built with a specific UID and GID baked in at compile time. The official image on Docker Hub was built with 1001:1001, which meant anyone running a different user on their host had to rebuild the image themselves. This was a significant friction point, especially on NAS and other self-hosted platforms where the user and group IDs are fixed by the system.

Starting with this version, the container handles user mapping at runtime (just like other projects like linuxserver.io). You set PUID and PGID in your .env file, and the container remaps its internal user to match on startup. No rebuild needed.

Two other things changed as a result:

  • sshd now runs as root inside the container. This is the standard behavior for OpenSSH — it requires root to handle host keys and privilege separation. Running it as a non-root user was a workaround. This is the same pattern used by projects like Linuxserver.io and atmoz/sftp (1B+ Docker pulls). The security posture is unchanged: PermitRootLogin no, public key only, AllowUsers borgwarehouse.
  • The user: directive has been removed from docker-compose.yml. User mapping is now handled by the entrypoint script, not by Docker.

TL;DR : BorgWarehouse itself never runs as root.


What you need to do

1. Update your .env file

Replace UID and GID with PUID and PGID:

- UID=1001
- GID=1001
+ PUID=1001
+ PGID=1001

Use the same values you had before. If you were already using 1001:1001, just rename the variables.

To find the UID and GID of your host user:

id

2. Update your docker-compose.yml

Remove the user: line and the build args if you had them:

  borgwarehouse:
    container_name: borgwarehouse
-   build:
-     context: .
-     dockerfile: Dockerfile
-     args:
-       - UID=${UID}
-       - GID=${GID}
    image: borgwarehouse/borgwarehouse
-   user: '${UID}:${GID}'

The final file should look like this:

services:
  borgwarehouse:
    container_name: borgwarehouse
    image: borgwarehouse/borgwarehouse
    ports:
      - '${WEB_SERVER_PORT}:3000'
      - '${SSH_SERVER_PORT}:22'
    env_file:
      - .env
    volumes:
      - ${CONFIG_PATH}:/home/borgwarehouse/app/config
      - ${SSH_PATH}:/home/borgwarehouse/.ssh
      - ${SSH_HOST}:/etc/ssh
      - ${BORG_REPOSITORY_PATH}:/home/borgwarehouse/repos

3. Check your volume permissions

Your host directories must be owned by the user matching PUID:PGID. This was already the case before, nothing changes here. If you were running with 1001:1001 and your folders were owned by that user, they still need to be.

If you are unsure:

ls -ln ./config ./ssh ./ssh_host ./repos

The third and fourth columns are the numeric UID and GID. They must match PUID and PGID.

To fix ownership if needed:

chown -R YOUR_PUID:YOUR_PGID ./config ./ssh ./ssh_host ./repos

4. Reset your sshd_config

The sshd_config file in your ssh_host volume was generated by a previous version and contains an outdated PidFile path. Delete it so the new one is copied automatically on startup:

rm ./ssh_host/sshd_config

If you had customized your sshd_config, note down your changes before deleting it and reapply them after the container has started.

5. Pull the new image and restart

docker compose pull
docker compose up -d

If something goes wrong

The container now prints a clear error and exits if a volume is missing or has wrong permissions. Check the logs:

docker logs borgwarehouse

Examples of what you might see:

[ERROR] Volume 'repos' is not mounted. Expected path: /home/borgwarehouse/repos
        Check the volumes section in your docker-compose.yml.
[ERROR] Volume 'config' (/home/borgwarehouse/app/config) is not writable by UID=1000 GID=1000.
        Fix on the host: chown -R 1000:1000 <your-host-path-for-config>

For people who were building their own image

You no longer need to build the image yourself just to set a custom UID/GID. Pull the official image and set PUID/PGID in your .env. That’s it.

If you were maintaining a custom build for other reasons, note that the UID and GID build arguments have been removed from the Dockerfile. They are no longer needed.

From BorgWarehouse v2 to v3

Breaking changes that needs your attention

  • API has been full rewrite to be REST compliant and idempotent
    • Check the new API documentation and update your configurations if you use integrations.
    • repository’s name is now used instead of id to identify repository in all API.
  • You need to update your cron service to trigger the new API for storage and status update :
    • /api/cronjob/checkStatus » /api/v1/cron/status
    • /api/cronjob/getStorageUsed » /api/v1/cron/storage
From BorgWarehouse v1 to v2

What’s new in v2 ?

Core changes :

  • One unix user is now used for all backup. BorgWarehouse now complies with BorgBackup documentation recommendations.
  • sudo permissions is now no longer required at all.
  • Repositories are now all in the same root folder.
  • Inside the repo.json, the repository key is not use anymore. The repositoryName key is new and now match the exact name of the repository where are stored datas for this repository.
  • All SSH public key must be unique (see why here or here). BorgWarehouse will warn you if you try to use an already use one.
  • All environment variables are now runtime variables (buildtime variables have been removed for docker compatibility).

Features :

  • 100% ready for Docker 🚀
  • Add robots.txt to default installation.
  • History of repo.json file is now logged in config/versions folder.

Fixes :

  • Don’t try to stat repositories if there is no repositories created in BorgWarehouse
  • Improvement for SMTP error log
  • Add prettier config file
  • better description in Wizard’step 2

How to migrate from v1 to v2 ?

It’s a big update, and there is no automatic migration process. I will try to explain the steps to follow to migrate from v1 to v2 soon.