Harbor

Guide · Remote access · harborvps.com

Protect Harbor when it runs on a VPS

Harbor has no built-in login. If the UI/API are reachable, anyone who can hit them can run SSH actions on your configured hosts. Use one of these operator recipes — Harbor does not implement these for you.

Defaults: API 127.0.0.1:8787, UI 127.0.0.1:5173 (dev). Binding outside loopback only warns at startup; you must still gate access.

Pick a pattern

RecipeBest whenNotes
SSH tunnel You already SSH to the box Recommended default — no public Harbor ports
IP allowlist Stable home/office IP IP changes lock you out
Tailscale / WG Private access from devices No public Harbor surface
CF Zero Trust Browser login + MFA Tunnel + Access; origin stays localhost
Proxy basic auth Simple password on HTTPS Weaker than Access / VPN

1. SSH tunnel (recommended default)

Keep Harbor on loopback on the VPS. Reach it from your laptop through SSH.

ssh -N -L 5173:127.0.0.1:5173 -L 8787:127.0.0.1:8787 your-vps

Open http://127.0.0.1:5173 locally. Authorization = “can you SSH as the operator.”

2. Firewall / cloud IP allowlist

Allow Harbor ports only from your public IP. Drop everyone else.

Ubuntu ufw

sudo ufw default deny incoming
sudo ufw allow OpenSSH
sudo ufw allow from YOUR.PUBLIC.IP.HERE to any port 8787 proto tcp
sudo ufw allow from YOUR.PUBLIC.IP.HERE to any port 5173 proto tcp
sudo ufw enable
sudo ufw status

Same idea in a cloud security group: source /32, never 0.0.0.0/0 on Harbor ports. Home IPs change; shared NAT is a poor allowlist source. This is network-only — no MFA.

3. Tailscale / WireGuard

  1. Install Tailscale (or WireGuard) on the VPS and your devices.
  2. Bind Harbor to the mesh IP, or keep 127.0.0.1 and use Serve / an SSH tunnel over the mesh.
  3. Keep the public firewall closed on Harbor ports.

Access ≈ membership of your tailnet / WG peers (optionally Tailscale ACLs / SSO).

4. Cloudflare Zero Trust (Access + Tunnel)

Expose Harbor without opening inbound ports: Tunnel connects out; Access enforces login (email OTP, Google/GitHub, IdP, device posture).

  1. Create a Zero Trust team; install cloudflared on the VPS.
  2. Create a Tunnel; keep Harbor on 127.0.0.1.
  3. Route harbor.example.comhttp://127.0.0.1:5173 (and protect the API the same way if separate).
  4. Access application + policy: allow only your email / IdP group (MFA if available).
  5. Firewall: deny public 8787 / 5173.
# cloudflared ingress — illustrative; follow current Cloudflare docs
ingress:
  - hostname: harbor.example.com
    service: http://127.0.0.1:5173
  - service: http_status:404

Point the UI at an Access-protected API origin. Cloudflare’s UI changes — treat this as the pattern.

5. Reverse proxy + HTTP basic auth

TLS terminator on :443; Harbor stays on localhost. Caddy sketch:

harbor.example.com {
  basicauth {
    # caddy hash-password
    operator JDJhJDEwJ...hashed...
  }
  reverse_proxy 127.0.0.1:5173
}

Prefer Access / Tailscale / SSH for anything serious. Protect UI and API if both are reachable.

What not to do

Checklist