Skip to content

VPS ​

Run Team Hub on a plain Linux VPS when you want a simple, always-on server with persistent storage. Bundled Postgres and Redis work well on a VPS when you mount a Docker volume for /var/lib/postgresql/data.

This guide uses a generic Debian or Ubuntu VPS. OVHcloud is a common choice; their Docker install guide matches the checklist here.

For Compose and env details shared by all hosts, see Docker Compose. For the optional npm wrapper, see npm CLI.

Overview ​

  1. Install Docker on the host.
  2. Pull the prebuilt GHCR image (Compose or team-hub deploy install).
  3. Run with a named volume, restart policy, and a strong database password.
  4. Open the HTTP port in the host firewall.
  5. Create an admin user via docker exec.

This guide covers HTTP. Add a reverse proxy and TLS on the host if you need HTTPS.

Prerequisites ​

  • A VPS with at least 2 GiB RAM (bundled Postgres, Redis, and Node need headroom)
  • SSH access with a user that has sudo privileges
  • Debian 11/12 or Ubuntu 22.04 and later

Install Docker ​

Follow your provider's guide or the OVHcloud Docker tutorial. Summary for Ubuntu 22.04:

bash
sudo apt update && sudo apt upgrade -y
sudo apt install -y ca-certificates curl gnupg

sudo install -m 0755 -d /etc/apt/keyrings
sudo curl -fsSL https://download.docker.com/linux/ubuntu/gpg \
  -o /etc/apt/keyrings/docker.asc
sudo chmod a+r /etc/apt/keyrings/docker.asc

sudo tee /etc/apt/sources.list.d/docker.sources > /dev/null <<EOF
Types: deb
URIs: https://download.docker.com/linux/ubuntu
Suites: $(. /etc/os-release && echo "${UBUNTU_CODENAME:-$VERSION_CODENAME}")
Components: stable
Architectures: $(dpkg --print-architecture)
Signed-By: /etc/apt/keyrings/docker.asc
EOF

sudo apt update
sudo apt install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin

sudo usermod -aG docker $USER
newgrp docker

Avoid running routine Docker commands with sudo — root-owned files in volumes can cause permission errors later.

Verify:

bash
docker --version
docker compose version
docker run hello-world

Deploy ​

bash
mkdir -p ~/team-hub && cd ~/team-hub

curl -fsSLO https://raw.githubusercontent.com/harborclient/harborclient/main/packages/team-hub/deploy/compose.yaml
curl -fsSLO https://raw.githubusercontent.com/harborclient/harborclient/main/packages/team-hub/deploy/.env.example
cp .env.example .env

Edit .env:

  • APP_VERSION — released tag such as 0.8.0 or latest
  • HOST_PORT — host port (for example 80 or 8080)
  • TEAM_HUB_DB_PASSWORD — strong secret

Then:

bash
docker compose pull
docker compose up -d --remove-orphans
docker compose logs -f

See Docker Compose for updates, rollbacks, and authentication.

Optional npm CLI ​

bash
npm install --global @harborclient/team-hub
team-hub deploy install

See npm CLI.

docker run alternative ​

bash
docker pull ghcr.io/harborclient/team-hub:latest

docker run -d \
  --name team-hub \
  --restart unless-stopped \
  -p 80:8080 \
  -v team-hub-pgdata:/var/lib/postgresql/data \
  --env-file .env \
  ghcr.io/harborclient/team-hub:latest

Verify and create users ​

bash
curl -s http://VPS_IP/health
# or, on the VPS itself with HOST_PORT=8080:
curl -s http://127.0.0.1:8080/health

Create the first admin, then a desktop user:

bash
docker exec -it team-hub \
  node /app/dist/cli.js -c /etc/team-hub/server.yaml user create --name ops --role admin

docker exec -it team-hub \
  node /app/dist/cli.js -c /etc/team-hub/server.yaml user create --name alice --role user \
  --collection-access '*' --environment-access '*'

Copy each one-time hbk_… token immediately. Connect HarborClient to http://VPS_IP (and the mapped port if not 80). See Authentication and CLI.

Persistence and backups ​

The team-hub-pgdata volume survives docker stop, docker rm, and image updates as long as you reuse the same volume name.

For disaster recovery:

  • Enable provider snapshots if available (for example OVH VPS snapshots).
  • Periodically back up the volume or use pg_dump from inside the container.

Firewall ​

Allow inbound HTTP to the mapped port. On Ubuntu with UFW (example host port 80):

bash
sudo ufw allow 80/tcp
sudo ufw enable
sudo ufw status

Also open the same port in your provider's network firewall if present.

Updates ​

bash
# Edit APP_VERSION in .env if needed
docker compose pull
docker compose up -d --remove-orphans

Or team-hub deploy update when using the npm CLI. Migrations run automatically on start.

Edit configuration ​

On first boot the entrypoint generates /etc/team-hub/server.yaml from environment variables. Later edits inside the container survive docker restart. To regenerate from env vars, set TEAM_HUB_FORCE_CONFIG_GENERATE=true once.

bash
docker exec -it team-hub nano /etc/team-hub/server.yaml

Apply changes:

  • Reloadable sections (db, redis, llm, plugins) — POST /admin/config/reload or SIGHUP
  • Bind/logging changes — docker exec team-hub /docker/restart-team-hub.sh

To persist config across container recreation, bind-mount a host file to /etc/team-hub/server.yaml. See Docker Compose — Using the CLI in the container and Configuration.

Troubleshooting ​

Connection refused from outside the VPS ​

  • Confirm the container is running: docker compose ps or docker ps
  • Check UFW and the provider firewall allow the mapped host port
  • Verify locally: curl -s http://127.0.0.1:8080/health (adjust port)

Container exits during startup ​

Check docker compose logs. Bundled Postgres + Redis + Node need at least 2 GiB RAM.

Postgres init or permission errors ​

Ensure PGDATA is on a writable volume. If you previously ran Docker with sudo, fix volume ownership or recreate the volume.