176 lines
8.0 KiB
Markdown
176 lines
8.0 KiB
Markdown
# FAQ
|
|
|
|
## How to obtain the Gitea registration token
|
|
|
|
There are three levels of registration tokens, depending on which repositories the runner should serve:
|
|
|
|
- **Instance-level** — Site Administration → Actions → Runners → Create Registration Token. The runner will handle jobs from all repositories.
|
|
- **Organization-level** — Organization → Settings → Actions → Runners → Create Registration Token. The runner will only handle jobs from repositories in that organization.
|
|
- **Repository-level** — Repository → Settings → Actions → Runners → Create Registration Token. The runner will only handle jobs from that specific repository.
|
|
|
|
Set the token as `GITEA_REGISTRATION_TOKEN` in your `.env` file or pass it via `--token` on the command line.
|
|
|
|
## What is the CI_GITEA_TOKEN and is it needed?
|
|
|
|
`CI_GITEA_TOKEN` is a Gitea admin API token used for optional post-install verification. When set, GRM queries the Gitea API after installation to confirm the runner appears in the runner list. This is purely informational — the integration test passes/fails based on the `.runner` file and systemd service, not the API check.
|
|
|
|
To generate one: Settings → Applications → Generate New Token, with the `admin` scope (or at minimum `read:user`, `read:repository`, `read:admin`).
|
|
|
|
If you skip it, GRM will still verify the runner correctly — it won't show the extra API confirmation.
|
|
|
|
## How to skip the sudo password prompt for automation
|
|
|
|
Configure passwordless sudo on the remote host and pass `--no-ask-become-pass` to the CLI command. This is recommended for CI/CD pipelines.
|
|
|
|
On the remote host, add a sudoers entry:
|
|
|
|
```bash
|
|
echo "ubuntu ALL=(ALL) NOPASSWD: ALL" | sudo tee /etc/sudoers.d/grm
|
|
```
|
|
|
|
Then use:
|
|
|
|
```bash
|
|
grm install 192.168.1.10 --user ubuntu --key ~/.ssh/id_ed25519 --name prod-runner --no-ask-become-pass
|
|
```
|
|
|
|
## Can multiple runners run on the same host?
|
|
|
|
Yes. Each runner instance is fully isolated with its own system user (`grm-<name>`), rootless Docker daemon, data directory, and systemd user service. Install additional runners with different `--name` values and manage them independently by name.
|
|
|
|
```bash
|
|
grm install 192.168.1.10 --user ubuntu --name workflow-runner
|
|
grm install 192.168.1.10 --user ubuntu --name build-runner
|
|
grm list
|
|
```
|
|
|
|
Runners on the same host never interfere with each other or with the host's Docker installation.
|
|
|
|
## Why does a runner appear offline after installation?
|
|
|
|
Check that `GITEA_URL` and `GITEA_REGISTRATION_TOKEN` are correct, verify the runner service is running with `sudo -u grm-<name> systemctl --user status gitea-runner`, and check the logs for registration errors. You can also confirm the runner appears as **Online** in the Gitea UI under **Actions → Runners**.
|
|
|
|
Common causes:
|
|
- Registration token expired — generate a new one from Gitea
|
|
- Network connectivity issue between the runner host and Gitea
|
|
- Rootless Docker daemon not running — check `sudo -u grm-<name> systemctl --user status docker`
|
|
- Lingering not enabled — check `loginctl show-user grm-<name> | grep Linger`
|
|
|
|
## What does the "Event loop is closed" warning mean?
|
|
|
|
This is a harmless cleanup traceback from Molecule's Docker driver when the test process is interrupted. It does not indicate a test failure.
|
|
|
|
## Where are runner connection details stored?
|
|
|
|
GRM stores each runner's connection details (host, user, SSH key, Gitea URL, labels) in a local JSON registry at `~/.local/share/grm/runners.json`. After installation, lifecycle commands work by runner name only — you can override any stored value by passing the corresponding flag.
|
|
|
|
## How to update the gitea_runner binary
|
|
|
|
Use the `grm update` command:
|
|
|
|
```bash
|
|
grm update 192.168.1.10 --user ubuntu
|
|
```
|
|
|
|
To update to a specific version:
|
|
|
|
```bash
|
|
grm update 192.168.1.10 --user ubuntu --version 1.0.8
|
|
```
|
|
|
|
The update command downloads the new binary and replaces the existing one at `/usr/local/bin/gitea_runner`. The runner service is restarted automatically.
|
|
|
|
## How to remove a runner entirely
|
|
|
|
Use the `grm remove` command:
|
|
|
|
```bash
|
|
grm remove prod-runner --token <registration-token>
|
|
```
|
|
|
|
This deregisters the runner from Gitea, stops and disables the systemd service, removes the system user, deletes data and config directories, removes subuid/subgid entries, disables lingering, and removes the entry from the local registry.
|
|
|
|
If the remote host is already gone or unreachable, use `--force` to skip remote cleanup and only remove the local registry entry:
|
|
|
|
```bash
|
|
grm remove prod-runner --force
|
|
```
|
|
|
|
## What is the difference between disable and remove?
|
|
|
|
- **`grm disable <name>`** — Deregisters the runner from Gitea and stops the service, but leaves the user, directories, and service files in place. The runner can be re-enabled later with `grm enable` and re-registered with a new token.
|
|
- **`grm remove <name>`** — Removes the runner entirely: deregisters from Gitea, stops and disables the service, removes the system user, deletes all directories, and removes the local registry entry. This is irreversible.
|
|
|
|
## What operating systems are supported?
|
|
|
|
GRM supports Arch Linux (rolling), Ubuntu 22.04/24.04, and Debian 12. All supported OSes are tested in CI via Molecule scenarios on every PR that changes Ansible files.
|
|
|
|
On Arch Linux, the rootless Docker setup scripts (`dockerd-rootless-setuptool.sh`, `dockerd-rootless.sh`) and the `rootlesskit` runtime are provisioned automatically — Arch's `docker` package does not ship them. No extra setup is required.
|
|
|
|
## How to change the UI language
|
|
|
|
Set the `GRM_LANG` environment variable to one of the supported languages: `en` (English, default), `bg` (Bulgarian), `de` (German), `ru` (Russian), `zh` (Chinese), `pl` (Polish).
|
|
|
|
```bash
|
|
GRM_LANG=bg grm install 192.168.1.10 --user ubuntu --name prod-runner
|
|
```
|
|
|
|
Or set it in your `.env` file:
|
|
|
|
```bash
|
|
GRM_LANG=bg
|
|
```
|
|
|
|
## How to enable debug logging
|
|
|
|
Set the `GRM_LOG_LEVEL` environment variable to `DEBUG`:
|
|
|
|
```bash
|
|
GRM_LOG_LEVEL=DEBUG grm install 192.168.1.10 --user ubuntu --name prod-runner
|
|
```
|
|
|
|
The log file at `~/.local/state/grm/logs/grm.log` always captures DEBUG level regardless of this setting. Ansible execution logs are stored in timestamped files at `~/.local/state/grm/logs/ansible-<timestamp>.log`.
|
|
|
|
## What runner labels should be used?
|
|
|
|
By default, runners are registered with `docker,ubuntu-latest:docker://runner-images:ubuntu-22.04`. You can override this with `--labels` or the `GITEA_RUNNER_LABELS` environment variable.
|
|
|
|
Use an official Gitea runner image with Node.js, Python, and Docker CLI. Avoid bare OS images like `alpine:latest` because `actions/checkout@v4` needs Node.js.
|
|
|
|
Example:
|
|
|
|
```bash
|
|
grm install 192.168.1.10 --user ubuntu --name prod-runner \
|
|
--labels "docker:docker://gitea/runner-images:ubuntu-latest"
|
|
```
|
|
|
|
## Is GRM secure?
|
|
|
|
Yes. GRM is designed with security as a first-class concern:
|
|
|
|
- **Rootless Docker**: Each runner operates under a dedicated unprivileged system user. Containers never have root access to the host.
|
|
- **Secret handling**: Registration tokens are passed via temporary JSON files with `0600` permissions, never on the command line (CWE-214).
|
|
- **No shell injection**: The CLI never uses `shell=True` with subprocess.
|
|
- **Bandit security scan**: The CI pipeline runs Bandit on every PR.
|
|
|
|
## Can GRM be installed via pip?
|
|
|
|
Yes:
|
|
|
|
```bash
|
|
pip install grm
|
|
```
|
|
|
|
This installs the `grm` CLI and its Python dependencies. The Ansible playbooks and role are bundled with the package. For development or access to Make targets, clone the repository instead.
|
|
|
|
## How does GRM handle idempotence?
|
|
|
|
The Ansible role is idempotent — running `grm install` twice produces zero changes on the second run. Each task checks for existing state before making changes. For example:
|
|
|
|
- User creation uses `ansible.builtin.user` which only creates if the user doesn't exist
|
|
- Package installation uses `state: present` which only installs if not already installed
|
|
- Template creation uses `ansible.builtin.template` which only writes if the content changed
|
|
- Rootless Docker setup uses `creates:` to skip if already configured
|
|
|
|
This makes GRM safe for CI/CD pipelines and configuration management.
|