# Self-hosting on restricted networks

Use a mirror you control or pre-copy files when GitHub or container registries are unreachable.
These settings change downloads; model and remote-computer providers still need network access.

| Failure | Setting or action |
| --- | --- |
| Cannot fetch the installer | Download it from your mirror or copy it locally |
| Cannot fetch Compose files | `RAKAZO_DOWNLOAD_BASE`, `--local`, or `RAKAZO_DOWNLOAD_SKIP_EXISTING=1` |
| Cannot pull app or computer images | `RAKAZO_IMAGE`, `RAKAZO_IMAGE_TAG`, `RAKAZO_COMPUTER_IMAGE`, `RAKAZO_COMPUTER_IMAGE_TAG` |
| Cannot pull Postgres or busybox | `POSTGRES_IMAGE`, `BUSYBOX_IMAGE`, or Docker daemon `registry-mirrors` |

## Installer script

When raw GitHub is unreachable, download the installer from your mirror:

```bash
export RAKAZO_INSTALLER_URL=https://example.com/mirror/rakazo/infra/compose/install-images.sh
export RAKAZO_DOWNLOAD_BASE=https://example.com/mirror/rakazo/infra/compose
mkdir -p rakazo && cd rakazo &&
curl -fsSL -o install-images.sh "${RAKAZO_INSTALLER_URL}" &&
bash install-images.sh --prepare-only
```

`RAKAZO_INSTALLER_URL` selects the script for this curl command; `RAKAZO_DOWNLOAD_BASE` selects
the Compose files downloaded by that script. Set both when raw GitHub is blocked.

## Compose files

To mirror `docker-compose.images.yml` and `.env.images.example`, point the installer at an HTTPS
mirror of `infra/compose`:

```bash
export RAKAZO_DOWNLOAD_BASE=https://example.com/mirror/rakazo/infra/compose
bash install-images.sh --prepare-only
```

Trailing slashes are trimmed; non-HTTPS bases are rejected. Downloads use bounded retries.

To reuse files already present in the working directory:

```bash
# Place docker-compose.images.yml and .env.images.example in this directory first.
bash install-images.sh --local --prepare-only
# Equivalent environment setting:
RAKAZO_DOWNLOAD_SKIP_EXISTING=1 bash install-images.sh --prepare-only
```

Missing files are still downloaded. `--prepare-only` creates `.env` without starting the stack;
continue with the image settings and startup instructions below.

For an offline installation, copy `docker-compose.images.yml` and `.env.images.example` into the
working directory and preload all required container images on the Docker host. Then run:

```bash
bash install-images.sh --offline
```

`--offline` fails before calling Compose if either required file is missing, even when `.env`
already exists. It never downloads files and does not require curl. It skips image pulls and
passes `--pull never` to startup when Compose supports it. Older Compose versions retain the
startup path and print a warning when that flag is unavailable.

To install restricted computer egress rules offline, also copy `restrict-computer-egress.sh`
into the working directory. If that optional script is missing, the installer records open
egress and warns instead of downloading it. An explicit `SANDBOX_COMPUTER_EGRESS` setting
remains unchanged. See [restricted computer egress](/docs/self-host/#restricted-computer-egress)
for host requirements.

## Container images

After `--prepare-only`, set image overrides in `.env`. For mirrored Postgres or busybox, use
[digest-verified startup](#digest-verified-hub-mirror-startup) below. Otherwise, rerun the installer
(keep `--local` if using pre-copied Compose files):

```env
RAKAZO_IMAGE=registry.example.com/mirror/rakazo/app
RAKAZO_IMAGE_TAG=edge
RAKAZO_COMPUTER_IMAGE=registry.example.com/mirror/rakazo/computer
RAKAZO_COMPUTER_IMAGE_TAG=edge
POSTGRES_IMAGE=registry.example.com/library/postgres@sha256:<trusted-postgres-digest>
BUSYBOX_IMAGE=registry.example.com/library/busybox@sha256:<trusted-busybox-digest>
```

Mirror both app and computer images and pair their tags to the same published version. Arm64
hosts need multi-architecture tags; see [published images and tags](/docs/self-host/#published-images-and-tags).
Image overrides are defined in [docker-compose.images.yml](https://github.com/elie222/rakazo/blob/main/infra/compose/docker-compose.images.yml).

For Docker Hub images, you can instead merge `registry-mirrors` into the Docker daemon's existing
JSON configuration, then restart Docker:

```json
{
  "registry-mirrors": ["https://mirror.example.com"]
}
```

See the [base daemon configuration](https://github.com/elie222/rakazo/blob/main/infra/compose/docker-daemon.json). Docker Hub mirrors do not
replace the GHCR image overrides above.

## Digest-verified Hub mirror startup

Run `bash install-images.sh --prepare-only` in the installation directory first (add `--local`
for pre-copied files). This prepares the Compose file and validates the required secrets without
starting containers.

Treat a mirror as a transport, not as the source of truth. Obtain the expected `postgres:16` and
`busybox:1` digests from a trusted upstream or an out-of-band trusted workstation. Put the digest in
each mirrored image reference, then pull, compare the local repository digests, and start without
pulling again. Replace every example value below before running it:

```bash
(
set -euo pipefail

export POSTGRES_IMAGE='registry.example.com/library/postgres@sha256:<trusted-postgres-digest>'
export BUSYBOX_IMAGE='registry.example.com/library/busybox@sha256:<trusted-busybox-digest>'

docker compose --env-file .env -f docker-compose.images.yml pull

for image_ref in "$POSTGRES_IMAGE" "$BUSYBOX_IMAGE"; do
  expected_digest="${image_ref##*@}"
  docker image inspect --format '{{range .RepoDigests}}{{println .}}{{end}}' "$image_ref" |
    awk -F@ -v expected="$expected_digest" '$2 == expected { found=1 } END { exit !found }' || {
      echo "digest verification failed for $image_ref" >&2
      exit 1
    }
done

docker compose up --help | grep -- '--pull' >/dev/null || {
  echo 'Docker Compose with up --pull is required for verified no-repull startup.' >&2
  exit 1
}
docker compose --env-file .env -f docker-compose.images.yml up -d --pull never
)
```

This sequence fails before startup if pulling or inspection fails, or either image lacks the expected
digest. Save the same `POSTGRES_IMAGE` and `BUSYBOX_IMAGE` references in the installation's `.env`
for later restarts; the exports above apply only to this startup. Do not replace them with mutable
mirror tags. After startup, follow the health checks in [the setup prompt](https://github.com/elie222/rakazo/blob/main/SETUP_PROMPT.md).

Once downloads work, continue with [published-image setup](/docs/self-host/#published-images-no-checkout).
For hosts without external provider access, use local Docker computers and an operator-controlled
model endpoint; see the [self-hosting guide](/docs/self-host/).
