# Connector specification sources

The [machine requirements page](/docs/connector-requirements/) gives starting
container allocations. This document records their scope and how to reproduce them.

## Releases and platforms

- Container: qurl v2.5.3, including Connector v0.13.2.
- Runtime source: `1ea78386bfc63118e91269f7d501d64b35b7e0e2`.
- Container source: `645a478ed58805e9c9c17c2d44dd6cd23b95de28`.
- Image: `ghcr.io/layervai/qurl@sha256:81c4528f95c490a28eba2b16f39bb60338010eb69fcc5cd0f3d9b001e62d596b`.
- [Image manifest, sizes, runtime user, and original startup checks](image-verification.json).
- [ARM64 results on Docker Desktop’s LinuxKit VM on macOS](container-profiles.json).
- [AMD64 results on a Linux GitHub Actions VM](container-profiles-amd64.json).

Both runs used the host CPU architecture without instruction-set emulation. ARM64
ran inside Docker Desktop’s LinuxKit VM on macOS; AMD64 ran on a Linux GitHub
Actions VM. The host and VM details remain in each raw report.

### Image storage measurements

The page uses Docker Desktop’s containerd image-store readings: 41,306,687 bytes
for ARM64 and 45,882,722 bytes for AMD64. The AMD64 runner reports 33,733,953 bytes
for the same image. These are different storage accounting results, not different
image contents. A fresh export of the pinned AMD64 image confirms its two layers
contain 179,359 and 33,554,594 bytes of file content: exactly 33,733,953 bytes.
The compressed layer blobs add 104,783 and 12,004,409 bytes. Docker documents that
[the containerd image store keeps compressed and uncompressed data](https://docs.docker.com/engine/storage/containerd/#disk-space-usage),
while legacy storage drivers retain only uncompressed layers. The containerd
reading also includes archive and metadata overhead. The 128 MiB allowance covers
two copies of the larger measured reading; host storage overhead is separate.

## CPU and RAM sizing basis

| Allocation | RAM | Workload routes |
| --- | --- | --- |
| 0.25 vCPU | 128 MiB | 50 |
| 1 vCPU | 256 MiB | 50 |
| 2 vCPU | 512 MiB | 1,000 |

These are starting allocations, not universal minimums, maximum route counts, or
throughput guarantees. The recommended allocation provides headroom above the
smallest workload. Reserve resources for the host and application separately.

Each profile runs three times with Docker CPU and RAM limits, no swap, a read-only
root filesystem, no GPU, no added capabilities, 512 tasks, and 4,096 open files.
The workload runs actual Connector forwarding and session-renewal code with a real
FRP client/server and eight HTTP backends in one constrained process. Requests use
small responses and loopback networking. Admission is scripted. The pinned runtime
test executable replaces the image entrypoint: these measurements do not cover the
full packaged daemon, live enrollment, or Internet performance.

The fixture enables tunnel TLS and changes readiness polling to the production
100 ms interval. Both fixture changes and all enforced limits are in the reports.
The reports also identify the host processor, Docker engine, and Go version.
Different CPUs, payloads, concurrency, and traffic rates can change capacity.

Resource completion and request continuity are recorded separately. The ARM64
report retains one failed request out of 416,537 requests during renewal, with no
out-of-memory kills. The AMD64 report retains one failed request out of 410,848
renewal-period requests, also with no out-of-memory kills. Both strict continuity
results remain false. The specification
page does not claim zero-error operation. Every collected trial, including failures,
is retained in its architecture's report.

## Reproduce

Use Python 3.12 or later, Go 1.27.1, Docker, and an AMD64 or ARM64 Linux Docker
engine on the matching CPU architecture. A Linux VM is supported. Build tools are
needed only for these checks, not for customer deployment.
Download [measure.py](measure.py), then run:

```sh
git clone https://github.com/layervai/qurl-connector.git
git -C qurl-connector checkout 1ea78386bfc63118e91269f7d501d64b35b7e0e2
python3 measure.py --source ./qurl-connector --output connector-results.json
```

The script rejects a dirty source checkout and preserves all completed results
before returning a nonzero exit status for a strict check failure. AMD64 host and
Docker details are included in its downloadable report above. The original CI run
is linked in the website PR for repository reviewers.
The first CI attempt could not collect the non-root report due to host file
permissions; the corrected script uses Docker to copy the report to the host.
