# Installation

> The binary or the image, signature check, the privileges integrations need and the environment they run in.

The agent is a single self-contained executable. Install it on any machine in your
network that has access to your git server (and to the tracker, if you install
an integration) and outbound internet access.

## What the machine needs

| | Why | Without it |
|---|---|---|
| **git** | the agent calls it to work with repositories | the git bridge does not work; the Docker image already has git |
| **root** | an integration runs under a separate OS user; root itself is checked — a separate capability is not enough | the git bridge works, integrations do not start |
| **Python 3.11+**, available to other users | integrations are written in Python | the git bridge works, integrations do not start |
| outbound HTTPS | the link to the platform and the catalogue | the agent will not pair |

You do not need to open any ports to the outside: the agent only calls out. The event receiver is
[a separate and optional](/en/docs/connector/trackers#events-polling-and-webhooks)
setting. The exceptions are GitLab commit comments and Figma without a list of files and projects:
they arrive only by webhook. For Figma the receiver must be reachable from the internet, because
the `FILE_COMMENT` webhook comes from Figma’s cloud ([more](/en/docs/connector/knowledge#events)).

## Binary

Download the file for your OS and architecture from the **[downloads page](/en/downloads)**:

- Linux — `connector-linux-amd64` / `connector-linux-arm64`
- macOS — `connector-darwin-arm64` / `connector-darwin-amd64`
- Windows — `connector-windows-amd64.exe` / `connector-windows-arm64.exe`

Next to them are `SHA256SUMS` and the public key `cosign.pub`. Check the checksum and
the signature **before** running:

```bash
sha256sum -c SHA256SUMS --ignore-missing
cosign verify-blob --key cosign.pub \
  --signature connector-linux-amd64.sig connector-linux-amd64
chmod +x connector-linux-amd64 && sudo mv connector-linux-amd64 /usr/local/bin/connector
connector version
```

The signature is uploaded to a public transparency log, so the command above can be verified
without trusting our site: the file, the key and the log entry either match or they do not.

## Docker

The image is multi-arch (amd64/arm64) and already contains `git`:

```bash
docker run -d --name buff-connector \
  -v /srv/connector:/etc/connector \
  -v buff-connector-state:/var/lib/connector \
  registry.buff.systems/buff/connector:latest
```

The state volume (`/var/lib/connector`) keeps the agent’s key, tokens and installed
integrations — mount it so they survive a container restart. For one-off
commands, override the arguments:

```bash
docker run --rm -v /srv/connector:/etc/connector \
  registry.buff.systems/buff/connector:latest \
  pair --config /etc/connector/connector.yaml --code bufc_…
```

<Callout type="warn">
A container started with `--user` **cannot isolate integrations**: switching
users requires privileges such a process does not have. This makes no difference for the git bridge,
but it does for integrations.
</Callout>

## Privileges: why integrations require root

Each connection runs **as its own process under its own OS user** — this is exactly
what separates an integration from the connector’s key and from your tokens
([in detail](/en/docs/connector/isolation)). Only something that can switch users can start such
a process, and the agent checks for root specifically: it refuses a process that has only
a user-switching capability.

If there are no privileges, the agent **does not start integrations at all** and says so on
its local page. This is not a “works, but without isolation” degradation: without
isolation it would be a different security promise, and we do not make it.

The git bridge works fully meanwhile. A connector that carries repositories and
nothing more can run under an ordinary account.

## The integration runtime

Integrations are written in Python. The connector takes the interpreter in this order:

1. **Its own, deployed next to the state** — `<state_dir>/runtime/python/bin/python3`.
   It is preferable: the version is pinned and there are no stray libraries in it.
2. **The system one** — the first `python3` in `PATH` of version **3.11 or newer** that
   the connection’s user can reach.

The local page shows which interpreter is used, and if there is no suitable one,
it says so plainly instead of bringing the connection down with “permission
denied”.

<Callout type="warn">
The interpreter must be available to **another user**, not only to root:
an integration runs under its own OS user. A Python installed in
root’s home directory (`/root/…`, permissions `700`) will not do, however new it
is — the connector skips it and says why.
</Callout>

To deploy your own runtime if the system Python is old or missing:

```bash
STATE=/var/lib/connector                  # your state_dir
mkdir -p "$STATE/runtime"
# a self-contained CPython 3.12 build (python-build-standalone), install_only archive:
curl -L -o /tmp/py.tar.gz "<link from the project's releases page>"
tar xzf /tmp/py.tar.gz -C "$STATE/runtime"      # gives $STATE/runtime/python
chmod -R a+rX "$STATE/runtime"                  # the connection runs as another user
"$STATE/runtime/python/bin/python3" --version
```

The file name in the releases changes from version to version, so take the link from the releases
page. It is important to choose the right build: **gnu** — for an ordinary host, **musl** — for
the Docker image (it is based on alpine). A mixed-up build fails with “no such file or
directory”, and that is about the ELF loader, not a missing file.

## Updating the agent

Download the new version, [check the signature](#binary) and replace the executable
(or pull the fresh image and restart the container). The state directory and the config
are kept: installed integrations, connections and their secrets stay in place.
The agent’s version is shown in the app, in the “Connectors” section.

## Next — setup

- [Local page](/en/docs/connector/web-setup) — forms in the browser.
- [Terminal](/en/docs/connector/cli-setup) — the same with commands.
- [YAML by hand](/en/docs/connector/yaml) — for Ansible and CI.
