# Self-hosting

Running a gateway of your own, from a clone. This is the development setup;
for a real host, the operator's runbook in `deploy/RUNBOOK.md` covers
provisioning, backups, replication and delivery.

## What you need

- Go 1.27 or later
- Docker with Compose
- `git` 2.29 or later, `ssh`, and `ssh-keygen`

## Start PostgreSQL and the object store

```sh
cp .env.example .env
make up
```

`make up` waits until both containers are healthy. The binaries read `.env`
from the directory you run them in, so run them from the checkout root — or
point `OTISK_ENV_FILE` at the file. Anything already set in the environment
takes precedence, which is how the compose stack configures them.

PostgreSQL holds metadata only — accounts, keys, repository records, the ref
mirror — and never git object data.

## Build

```sh
make build
```

This produces `bin/git-gateway` and `bin/otisk`.

## Create the first account

```sh
./bin/git-gateway bootstrap -handle yuritomanek -key ~/.ssh/id_ed25519.pub
```

This is the only command that needs access to the host, and it has to be:
authenticating over SSH requires a key that is already registered. Everything
after this happens over SSH.

## Run the gateway

From the checkout root, so it finds `.env`:

```sh
./bin/git-gateway serve
```

It applies any pending migrations on start and listens on `:2222` by default.

## Use it

```sh
otisk host set git@localhost:2222
otisk whoami
```

From here, [getting started](getting-started.md) applies as written, with
`git@localhost:2222` wherever it says a host.

## Development

```sh
make lint     # gofmt and go vet, no tools to install
make test     # the full suite, with the race detector
make verify   # the same, refusing a run that skipped more than expected
make build    # binaries into ./bin
make up       # start PostgreSQL and the object store
make down     # stop them, keeping volumes
```

Tests need the stack running: they create an isolated database and bucket per
test and drop them afterwards. Without it they skip rather than fail — which
is why `make verify` exists, and why it refuses a run where more tests skipped
than expected.

Stock git is kept available as a correctness oracle — `internal/oracle`
compares otisk's view of a repository against `git cat-file`, object by
object. That matters most for work not yet done: serving objects by parsing
packfiles directly is exactly the kind of change that can silently return
wrong bytes.

Planning artifacts live in `openspec/`.
