# Installation Requires Node.js 22+ (24.7+ for post-quantum SSH key exchange) and `git` on the `PATH`. ```bash bun install # also downloads the PocketBase server into bin/ bun dev ``` Open http://localhost:3000, sign up, and create a repository. The data lives in [PocketBase](https://pocketbase.io). Vectrum starts `bin/pocketbase` itself on `127.0.0.1:8090`, with its data in `data/pb_data` and the schema from `pb_migrations/`; its superuser login is generated into `data/pocketbase-superuser.json` (also good for the PocketBase dashboard at http://127.0.0.1:8090/_/). Run `bun run pocketbase:install` if the binary is missing. To use a PocketBase server of your own instead, set `PB_URL` and the superuser credentials; it needs the migrations in `pb_migrations/` (`pocketbase serve --migrationsDir pb_migrations`). ## Running with Docker ```bash docker compose up -d --build ``` The image runs the web UI on port 3000 and the SSH server on port 2222, with all data in the `vectrum-data` volume (mounted at `/data`). Settings go under `environment:` in `docker-compose.yml` (see [Configuration](#configuration)). To close registration, set `SIGNUPS_DISABLED: "1"` before you deploy, and create accounts from the command line instead: ```bash docker compose exec -it vectrum node scripts/create-user.mjs [name] ``` It asks for the password (or reads `VECTRUM_PASSWORD`). Outside Docker, run `node scripts/create-user.mjs` the same way while Vectrum runs. Clone URLs show `SSH_PORT`, so publish SSH on the same port on the host, and set `SSH_HOST` to your domain. Put a TLS reverse proxy in front of port 3000 if the server is reachable from the internet, and set `PUBLIC_URL` to its address. ## Configuration | Variable | Default | Purpose | | ----------------- | ----------- | --------------------------------------------------------- | | `PUBLIC_URL` | request host | Canonical address, e.g. `https://vectrum.cc`. Used for clone URLs; `https` also makes session cookies `Secure`. Set it in production | | `SECURE_COOKIES` | — | Set to `1` to mark session cookies `Secure` without `PUBLIC_URL` | | `DATA_ROOT` | `./data` | Where repositories, the database and the SSH host key live | | `PB_PORT` | `8090` | Port of the PocketBase server Vectrum runs | | `PB_URL` | — | Use this PocketBase server instead of running one | | `PB_SUPERUSER_EMAIL`, `PB_SUPERUSER_PASSWORD` | generated | Superuser login; required with `PB_URL` | | `PB_BINARY` | `bin/pocketbase` | PocketBase executable to run | | `SSH_PORT` | `2222` | Port of the built-in SSH server | | `SSH_LISTEN_HOST` | `0.0.0.0` | Interface the SSH server binds to | | `SSH_HOST` | request host | Host name shown in SSH clone URLs, e.g. `vectrum.cc` | | `SSH_DISABLED` | — | Set to `1` to not start the SSH server | | `SIGNUPS_DISABLED` | — | Set to `1` to close registration (add users with `scripts/create-user.mjs`) | | `WEBHOOKS_ALLOW_PRIVATE` | — | Set to `1` to let webhooks reach private and local addresses (a trusted, single-team server) | Data layout: ``` data/ pb_data/ PocketBase: users, keys, tokens, repos, issues, releases, workflow runs and logs pocketbase-superuser.json the generated PocketBase superuser login ssh_host_ed25519_key generated on first start hooks/ server-side git hooks for every push, rewritten on start, and the socket they ask the server on repos//.git bare git repositories wikis/.git each repository's wiki, named by its record id registry.db container image manifests, tags and blob records (SQLite) registry/blobs/sha256/… container image layers, shared by all repositories registry/uploads/ image uploads in progress releases///… release files, named by their record id ``` The registry keeps its records in SQLite rather than PocketBase so that storing a blob and pruning unused ones never interleave. A blob is deleted once no manifest of any repository references it (blobs pushed in the last 24 hours are kept so pushes in progress don't lose their layers).