# How It Works

This page explains the architecture behind Copia Actions Runners — how the runner communicates with Copia, how jobs are executed, and what network connectivity is required.

## Architecture Overview

Copia Actions is built on three main components:

{% stepper %}
{% step %}

### Copia (the server)

Your Copia instance manages workflows, schedules jobs, stores logs, and provides the web UI. When a trigger event occurs (such as a push or pull request), Copia parses the workflow files in your repository and creates jobs.
{% endstep %}

{% step %}

### Act Runner (the runner)

A standalone program that runs on your infrastructure. It connects to Copia, polls for available jobs, and executes them. The runner is based on a fork of [nektos/act](https://github.com/nektos/act), a tool originally designed to run GitHub Actions locally.
{% endstep %}
{% endstepper %}

<figure><img src="/files/9GxEpXCTFc0jv3vFjXTT" alt=""><figcaption></figcaption></figure>

## Communication Protocol

The runner communicates with Copia using **gRPC over HTTP**. This means the runner reuses the same HTTP port that serves the Copia web UI — no additional ports need to be opened on the Copia side.

The communication flow works like this:

{% stepper %}
{% step %}

### Registration

The runner sends its registration token and labels to Copia. Copia validates the token and records the runner.
{% endstep %}

{% step %}

### Polling

The runner periodically polls Copia for new jobs that match its labels.
{% endstep %}

{% step %}

### Job assignment

When a matching job is available, Copia assigns it to the runner and provides the job details (workflow steps, secrets, variables).
{% endstep %}

{% step %}

### Execution

The runner executes the job and streams logs back to Copia in real time.
{% endstep %}

{% step %}

### Completion

The runner reports the final job status (success, failure, or cancelled) to Copia.
{% endstep %}
{% endstepper %}

## How Jobs Run

When the runner receives a job, it follows these steps:

{% stepper %}
{% step %}

### Select the execution environment

Based on the label that matched (e.g., `windows-S5K`), the runner prepares the host environment.
{% endstep %}

{% step %}

### Execute steps sequentially

Each step in the job runs in order. Steps can be shell commands (`run:`) or actions (`uses:`).
{% endstep %}

{% step %}

### Download actions

When a step uses an action (e.g., `actions/checkout@v4`), the runner downloads the action's source code from the specified repository. By default, actions without a full URL are downloaded from GitHub.
{% endstep %}

{% step %}

### Stream logs

As each step runs, the output is streamed back to Copia and made available in the Actions tab.
{% endstep %}

{% step %}

### Clean up

After all steps complete (or if the job fails), the container is stopped and removed.
{% endstep %}
{% endstepper %}

## Network Requirements

There are four network connections involved in running a job. Understanding these helps you configure firewalls and network policies.

{% stepper %}
{% step %}

### Runner to Copia Instance (required)

The runner must be able to reach your Copia instance over HTTPS. This is the primary connection used for registration, job polling, log streaming, and status reporting.

* **Protocol:** HTTPS (port 443)
* **Direction:** Runner → Copia
* **Example:** `https://app.copia.io`

{% hint style="danger" %}
Do not use loopback addresses (`127.0.0.1` or `localhost`) as the instance URL. Job containers run in separate network namespaces and cannot reach loopback addresses on the host.
{% endhint %}
{% endstep %}

{% step %}

### Job Containers to Copia Instance (required for most workflows)

Job containers need to connect to Copia to fetch repository code. For example, `actions/checkout@v4` clones the repository by connecting to the Copia instance URL.

* **Protocol:** HTTPS (port 443) or HTTP (port 80)
* **Direction:** Job container → Copia
* **Why:** Code checkout, LFS downloads, API calls within workflows

This is why the instance URL must be a routable address — not `localhost`.
{% endstep %}

{% step %}

### Runner to the Internet (recommended)

When a workflow uses actions like `actions/checkout@v4`, the runner downloads the action's source code. By default, actions are downloaded from GitHub (`github.com`). The runner also pulls Docker images from Docker Hub or other registries when starting job containers.

* **Protocol:** HTTPS (port 443)
* **Direction:** Runner → app.copia.io, github.com, Docker Hub, etc.
* **Required for:** Downloading actions, pulling container images

Hint for air-gapped environments: If your runner cannot access the internet, you can host actions on your Copia instance and reference them using absolute URLs. You can also pre-pull or mirror Docker images to a local registry.
{% endstep %}

{% step %}

### Job Containers to the Internet (optional)

Some actions download additional resources at runtime. For example, `actions/setup-node` downloads Node.js binaries. If your workflows don't need runtime downloads, this connection is not required.

* **Protocol:** HTTPS (port 443)
* **Direction:** Job container → various hosts
* **Required for:** Runtime downloads within actions (e.g., language runtimes, package managers)
  {% endstep %}
  {% endstepper %}

### Network Summary

<table><thead><tr><th align="center" valign="middle">Connection</th><th width="198.7109375" align="center">Required?</th><th align="center">Purpose</th></tr></thead><tbody><tr><td align="center" valign="middle">Runner → Copia</td><td align="center">Yes</td><td align="center">Registration, polling, logs, status</td></tr><tr><td align="center" valign="middle">Job container → Copia</td><td align="center">Yes (for most workflows)</td><td align="center">Code checkout, LFS, API access</td></tr><tr><td align="center" valign="middle">Runner → Internet</td><td align="center">Recommended</td><td align="center">Download actions and Docker images</td></tr><tr><td align="center" valign="middle">Job container → Internet</td><td align="center">Optional</td><td align="center">Runtime downloads within actions</td></tr></tbody></table>

## Runner Labels and Job Routing

When a runner registers with Copia, it reports its **labels**. Labels tell Copia what kinds of jobs the runner can handle and how to run them.

When a workflow specifies `runs-on: windows-S5K`, Copia looks for an online runner that has the `windows-S5K` label and assigns the job to it. If multiple runners match, Copia selects one that is available.

Labels also encode the execution mode:

* `ubuntu-latest:docker://node:16-bullseye` — Run the job in a Docker container using the `node:16-bullseye` image
* `linux_amd64:host` — Run the job directly on the runner's host machine

See [Runner Setup — Labels](broken://pages/72f38d5498ddd1a2347ee4882c33159cdf37a790#labels) for full details on label format and customization.

## Security Model

Runners have **no standing permissions** on your Copia instance beyond the ability to connect and poll for jobs. When a job is assigned, the runner receives a temporary, scoped token that grants access only to the repository associated with that job. This token expires when the job completes.

Additional permissions (such as access to package registries or external services) can be granted through **secrets** that you configure in the Copia UI. See [Variables and Secrets](/docs/actions/secrets.md).

### Recommendations

* **Only register runners you control.** A runner has the ability to execute arbitrary code from workflows, so it should run on trusted infrastructure.
* **Only provide runners to repositories and organizations you trust.** Workflows in those repositories will be able to run code on your runner.

{% hint style="info" %}
Note for Self-Hosted Copia customers: Replace `https://app.copia.io` with your instance URL in all network configurations. All architecture and security considerations apply equally.
{% endhint %}


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.copia.io/docs/actions/how-it-works.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
