# Getting started (/getting-started)



# Getting started

This is the shortest path from a Debian host to a GitHub Actions job executed
by Velnor.

Velnor is research software, not a production-readiness guarantee. Use a
dedicated host and a repository whose jobs you are prepared to run on it.

## 1. Prepare a Debian host

Use a supported Debian system with systemd, outbound HTTPS access to GitHub,
and sufficient disk, CPU, and memory for the selected jobs. Install the host
tools required by the package and backend:

```sh
sudo apt-get update
sudo apt-get install -y ca-certificates curl git util-linux systemd
```

Choose one execution backend before starting Velnor. There is no fallback.

For Docker, install and start the Debian package, then verify the daemon and
socket:

```sh
sudo apt-get install -y docker.io
sudo systemctl enable --now docker
sudo docker info
sudo test -S /var/run/docker.sock
```

For MicroVM, no separate Firecracker download is supported by this tree. The
Velnor `.deb` ships the pinned Firecracker, jailer, kernel, root filesystem,
and guest agent. The host must expose KVM; verify the packaged artifacts after
installation:

```sh
test -c /dev/kvm
sudo test -x /usr/share/velnor/microvm/firecracker
sudo test -x /usr/share/velnor/microvm/jailer
sudo test -s /usr/share/velnor/microvm/vmlinux
sudo test -s /usr/share/velnor/microvm/rootfs.ext4
```

## 2. Install the real release artifact

Velnor currently builds `.deb` files and publishes them as GitHub Release
assets at [github.com/tailrocks/velnor/releases](https://github.com/tailrocks/velnor/releases).
This repository does not contain APT signing-key bootstrap or APT repository
setup metadata. Therefore this is the only acquisition path documented here:
download the exact `velnor-runner-VERSION-ARCH.deb` and matching `.sha256`
asset from that release, then verify it. Do not use an unverified binary.

```sh
sha256sum --check velnor-runner-VERSION-ARCH.deb.sha256
sudo install -d -m 0750 /run/velnor
sudo /usr/bin/flock --exclusive --nonblock --no-fork \
  /run/velnor/package-transaction.lock \
  apt-get install ./velnor-runner-VERSION-ARCH.deb
```

Replace `VERSION` and `ARCH` with the downloaded asset names. Releases also
publish `SHA256SUMS`; use it when present to verify the complete asset set.
Direct `dpkg -i` and unlocked package transactions are rejected. Package
installation does not enable or start services.

## 3. Configure scope, backend, and credentials

Edit the shipped configuration:

```sh
sudoedit /etc/velnor/velnor.env
sudoedit /etc/velnor/execution.toml
```

Minimum settings in `velnor.env`:

```text
VELNOR_URL=https://github.com/OWNER/REPO
VELNOR_NAME=velnor
VELNOR_LABELS=velnor,velnor-target-mvp
VELNOR_SLOTS=1
VELNOR_WORK_DIR=/var/lib/velnor/work
VELNOR_TRUST_SCOPE=trusted
VELNOR_CAPABILITY_VALIDATION=strict
```

Set exactly one backend in `execution.toml`:

```toml
[execution]
backend = "docker"
```

Use `microvm` instead only when the host satisfies the KVM and artifact
requirements.

Keep the operator personal access token (PAT) separate from ordinary
configuration:

```sh
sudo install -m 0600 /dev/null /etc/velnor/secrets.env
sudoedit /etc/velnor/secrets.env
```

Put this in the file:

```text
GITHUB_TOKEN=YOUR_OPERATOR_PAT
```

The token must authorize runner registration for the configured repository,
organization, or enterprise and any selected runner group. Never put it in a
unit argument or workflow file.

## 4. Configure organization or enterprise scope (if applicable)

Repository scope needs only `VELNOR_URL` set to the repository URL. For an
organization or enterprise URL, GitHub requires an explicit runner group;
Velnor refuses the implicit `Default` group. Set the stable group name and,
when known, its numeric GitHub group ID:

```text
VELNOR_POOL_NAME=velnor-trusted
VELNOR_POOL_ID=GROUP_ID
VELNOR_ROUTING_POLICY_FILE=/etc/velnor/ORG-routing-policy.json
```

The policy file must be operator-provided JSON containing non-empty `group`,
`selected_repositories`, `labels`, and `trust_scope`. Its values must exactly
match GitHub’s live group/repository/label/trust evidence. Live membership is
evidence, not the allowlist. The daemon resolves `VELNOR_POOL_NAME` through
GitHub before requesting each per-slot JIT configuration; no pre-registration
command is needed.

## 5. Start and check health

Start the guardian first, then the daemon and periodic doctor:

```sh
sudo systemctl enable --now velnor-guardian.service
sudo systemctl enable --now velnor-daemon.service
sudo systemctl enable --now velnor-doctor.timer
```

Check process state and Velnor health:

```sh
systemctl is-active velnor-guardian.service velnor-daemon.service
velnorctl status --json
velnorctl get runners --output wide
velnorctl get slots --output wide
velnorctl preflight --config-dir /etc/velnor --work-dir /var/lib/velnor/work
```

Healthy is more than an active PID: the daemon must have a writable state
store, valid routing, a ready backend, and available capacity. Confirm the
runner is `online` in GitHub before testing a workflow. If configuration
changes, use `sudo systemctl restart velnor-daemon.service`.

## 6. Target Velnor from a workflow

Add a minimal job to a test workflow in the configured repository:

```yaml
name: Velnor smoke test

on: workflow_dispatch

jobs:
  smoke:
    runs-on: [self-hosted, velnor, velnor-target-mvp]
    steps:
      - run: |
          echo "runner=$RUNNER_NAME"
          echo "workspace=$GITHUB_WORKSPACE"
          uname -a
```

The labels must match the configured runner. GitHub selects eligible runners;
Velnor does not assign jobs from the REST queued-job listing. Trigger the
workflow manually.

## 7. Verify the first job end to end

Watch GitHub until the job leaves `queued`, then inspect Velnor while it runs:

```sh
velnorctl get jobs --output wide
velnorctl get runs --output wide
velnorctl events --limit 100
velnorctl telemetry --limit 100
```

After completion, verify all three sides:

1. GitHub shows the job completed with the expected runner name and labels.
2. Velnor shows the job/run and corresponding events or logs.
3. The workflow output contains the smoke-test lines and the job is not merely
   reported as successful by a local process.

For service-level evidence, use:

```sh
sudo journalctl -u velnor-daemon.service -u velnor-guardian.service -n 200 --no-pager
```

## If the first job does not run

Diagnose in order:

1. GitHub workflow: confirm the job uses the exact Velnor labels and the
   configured repository.
2. Eligibility: confirm the runner is online and the backend/slot is ready.
3. Connectivity: inspect `systemctl status` and `journalctl`; authentication,
   broker, and run-service failures are not idle polls.
4. Delivery: confirm Velnor events show broker polling and job receipt.
5. Admission: unsupported actions, trust scope, capabilities, or routing can
   reject a job before checkout or credentials.
6. Execution: run `velnorctl preflight` and inspect backend-specific errors.
7. Reporting: compare local events/logs with GitHub job state and completion.

```sh
velnorctl logs job-1 --tail 200
```

Replace `job-1` with the exact job UID shown by `velnorctl get jobs --output
wide`. `velnorctl logs` accepts one concrete job or run subject.

For the complete lifecycle and recovery behavior, continue to the
[operator guide](/guides/operator), [observability guide](/operations/observability),
and [architecture](/concepts/architecture).
