> For the complete documentation index, see [llms.txt](https://docs.copia.io/docs/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.copia.io/docs/actions/faqs.md).

# FAQs

Frequently asked questions about Copia Actions Runners, including compatibility with GitHub Actions, security, troubleshooting, and platform support.

## General

<details>

<summary><strong>Do I need to enable Actions on each repository?</strong></summary>

Yes. Actions are enabled per-repository. Go to your repository on Copia, then **Settings > Actions**, and check **Enable Repository Actions**.

</details>

<details>

<summary><strong>Where do workflow files go?</strong></summary>

Workflow files are stored in the `.copia/workflows/` directory of your repository, with a `.yaml` or `.yml` extension. For example: `.copia/workflows/ci.yaml`.

</details>

<details>

<summary><strong>Can I trigger a workflow manually?</strong></summary>

Yes. Add `workflow_dispatch` to your workflow's `on:` triggers, then use the **Run Workflow** button on the Actions tab in the Copia UI.

</details>

<details>

<summary><strong>Can I run workflows on a schedule?</strong></summary>

Scheduling workflows is not available at this time.

</details>

## Compatibility with GitHub Actions

<details>

<summary><strong>How compatible is Copia Actions with GitHub Actions?</strong></summary>

Copia Actions workflow syntax is designed to be largely compatible with GitHub Actions. Most GitHub Actions workflows can be adapted with minimal changes. The main differences are:

* Workflow files go in `.copia/workflows/` instead of `.github/workflows/`.
* Some advanced syntax features are not yet supported (see below).
* Actions are downloaded from GitHub by default, but you can use absolute URLs to reference actions from any Git repository.

</details>

<details>

<summary><strong>Which GitHub Actions syntax features are not supported?</strong></summary>

The following workflow syntax features are currently **not supported** and will be ignored if present:

| Feature                                     | Notes                                                    |
| ------------------------------------------- | -------------------------------------------------------- |
| `concurrency`                               | Running a single job at a time is not enforced           |
| `permissions` / `jobs.<job_id>.permissions` | Job-level permission scoping is not available            |
| `jobs.<job_id>.timeout-minutes`             | Job timeouts are not enforced via this field             |
| `jobs.<job_id>.continue-on-error`           | Jobs will not continue on error                          |
| `jobs.<job_id>.environment`                 | Environment protection rules are not available           |
| Complex `runs-on`                           | Only `runs-on: label` or `runs-on: [label]` is supported |

</details>

<details>

<summary><strong>Are there any other differences from GitHub Actions?</strong></summary>

Yes, a few additional differences to be aware of:

* **Package registry tokens:** The automatic job token cannot currently publish to package registries. Use a Personal Access Token (PAT) stored as a secret instead.
* **Problem matchers:** Scanning action output for regex patterns and surfacing annotations in the UI is not supported.
* **Error annotations:** Not supported.
* **Expression functions:** Only `always()` is supported as a status check function.
* **Pre/Post steps:** These run correctly, but do not have their own section in the job log UI.
* **Service containers:** These run correctly, but do not have their own section in the job log UI.
* **Pull request ref:** For `pull_request` events, the ref is `refs/pull/:prNumber/head` (the PR head), not `refs/pull/:prNumber/merge` (the merge preview) as in GitHub Actions.

</details>

<details>

<summary><strong>Can I use actions from GitHub?</strong></summary>

Yes. By default, actions referenced without a full URL (like `actions/checkout@v4`) are downloaded from GitHub. You can also use absolute URLs to reference actions from any accessible Git repository:

{% code title="example: uses with absolute URL" %}

```yaml
uses: https://github.com/actions/checkout@v4
uses: https://your-internal-server.com/org/my-action@main
```

{% endcode %}

The `https://` or `http://` prefix is required when using absolute URLs.

</details>

<details>

<summary><strong>Should I use `${{ github.xyz }}` or `${{ gitea.xyz }}` in my workflows?</strong></summary>

Both `${{ github.xyz }}` and `${{ gitea.xyz }}` are supported and behave identically. You can use either. We recommend `${{ github.xyz }}` for maximum compatibility if you also use GitHub Actions.

</details>

## Runners

<details>

<summary><strong>What operating systems are supported for runners?</strong></summary>

The runner binary is available for **Linux**, **macOS**, and **Windows**. Other operating systems may work if supported by Go and Docker, but are untested.

When running jobs directly on the host (not in Docker containers), be aware of environment differences. For example, `bash` is typically not available on Windows — you will need to set `powershell` as the default shell:

{% code title="example: set default shell to powershell" %}

```yaml
defaults:
  run:
    shell: powershell
```

{% endcode %}

</details>

<details>

<summary><strong>Can I register runners at the organization level or repository level?</strong></summary>

Runners can be registered at two levels:

* **Organization level** — The runner serves all repositories in your organization.
* **Repository level** — The runner serves only that specific repository.

A repository may use organization-level runners even if it has its own repository-level runners.

</details>

<details>

<summary><strong>What are runner labels and how do they work?</strong></summary>

Labels determine which jobs a runner can accept and how those jobs are executed. When a workflow specifies `runs-on: ubuntu-latest`, the job is routed to a runner with a matching `ubuntu-latest` label.

Labels also encode the execution mode. For example:

* `ubuntu-latest:docker://node:16-bullseye` — Run in Docker using the specified image
* `linux_amd64:host` — Run directly on the host machine

See [Runner Setup — Labels](broken://pages/72f38d5498ddd1a2347ee4882c33159cdf37a790#labels) for details.

</details>

<details>

<summary><strong>What if `runs-on` specifies multiple labels like `[label_a, label_b]`?</strong></summary>

This is valid syntax. It means the job should run on a runner that has **both** labels. The runner must have all specified labels registered.

</details>

<details>

<summary><strong>What is the difference between agent labels and custom labels?</strong></summary>

Agent labels are reported to Copia by the runner during registration. Custom labels can be added manually by an administrator. However, a custom label may not map to an environment the runner knows how to handle. If you need to change a runner's labels, we recommend re-registering the runner or updating the `runners.labels` section in the runner's `config.yaml` and restarting.

</details>

<details>

<summary><strong>Can I use Copia-hosted runners?</strong></summary>

Not at launch. Copia Actions Runners currently supports **self-hosted runners only** — you provide and manage the machines that execute jobs. Copia-hosted runners are planned for a future release.

</details>

<details>

<summary><strong>How do I start my self-hosted runner if it has gone offline?</strong></summary>

In the event that your self-hosted runner is stopped for any reason (noted as "**Offline**" in the UI) you can restart the runner by using your CLI to navigate to the installed folder (usually `./actions-runner`), and running the command `./[runner-binary-name] daemon` .

</details>

## Security

<details>

<summary><strong>What permissions does a runner have?</strong></summary>

Idle runners have **no standing permissions** on your Copia instance. They can only connect and poll for jobs.\
\
Once a job is assigned, the runner receives a temporary, scoped token that grants read-only access to the repository associated with that job. The token expires when the job completes.

Additional permissions can be granted to the runner using personal access tokens (PATs) and [Secrets](/docs/actions/secrets.md).

</details>

<details>

<summary><strong>Can I push to my repository?</strong></summary>

Yes. Your actions runner has read-only permissions to your repository by default, but you can allow write operations (e.g. pushing commits) using personal access tokens (PATs) and [Secrets](/docs/actions/secrets.md). \
\
Start by creating a personal access token. Personal access tokens are tied to a Copia user account and are managed in the user's settings. In your user settings, click "Applications" in the left-hand navigation menu. Give the token a name and click "Generate Token". Ensure the user has write access to the repo you want to push to.\
\
In your repository or organization settings, click "Secrets" in the left-hand navigation menu. Add a new Secret and paste the personal access token you just created in the Secret's "Value" field.\
\
Add the "token" field to the actions/checkout step in your workflow file (replace "YOUR\_SECRET\_NAME\_HERE" with the actual name of the secret you created):

```
- uses: actions/checkout@v5
  with:
    token: ${{ secrets.YOUR_SECRET_NAME_HERE }}
```

</details>

<details>

<summary><strong>How do I protect against malicious workflows?</strong></summary>

There are two main threat vectors: untrusted runners and malicious workflows.

An untrusted runner could steal code or secrets from jobs it executes. Only register runners you control on trusted infrastructure. Only provide runners to organizations and repositories you trust. Run jobs in Docker containers for isolation. Avoid host mode unless necessary. Use ephemeral runners for high-security environments — they execute one job and terminate.\
\
A workflow could run harmful code on your runner. Only register runners you control on trusted infrastructure. Only provide runners to organizations and repositories you trust. Run jobs in Docker containers for isolation. Avoid host mode unless necessary. For pull requests from forks, require approval before workflows run. Use ephemeral runners for high-security environments — they execute one job and terminate.

</details>

<details>

<summary><strong>Why should I use Docker mode?</strong></summary>

Docker mode runs each job in a fresh, isolated container. This prevents jobs from:

* Interfering with each other
* Leaving artifacts on the runner host
* Accessing the runner's filesystem or other processes

It also ensures reproducibility — the same Docker image produces the same environment every time.

</details>

## Troubleshooting

<details>

<summary><strong>My runner shows as "Offline" in the Copia UI</strong></summary>

* Verify the runner process is still running (`./act_runner daemon` or the Docker container).
* Check that the runner can reach your Copia instance over the network.
* If using a self-hosted Copia instance, confirm the instance URL is correct and not a loopback address.

</details>

<details>

<summary><strong>Jobs fail with "checkout" errors</strong></summary>

* Ensure the job container can reach your Copia instance. The `actions/checkout` action clones your repository by connecting to the instance URL.
* Do not use `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.

</details>

<details>

<summary><strong>Windows runner fails because `bash` is not found</strong></summary>

On Windows, `bash` is not available by default. Set `powershell` as the default shell for your workflow:

{% code title="example: set default shell to powershell" %}

```yaml
defaults:
  run:
    shell: powershell
```

{% endcode %}

Or per-step:

{% code title="example: per-step powershell" %}

```yaml
steps:
  - name: Run script
    run: Get-Process
    shell: powershell
```

{% endcode %}

</details>

<details>

<summary><strong>The `.runner` file is corrupted</strong></summary>

If the `.runner` file (created during registration) becomes corrupted or the runner fails to start, delete the file and re-register:

{% code title="example: re-register runner" %}

```bash
rm .runner
./act_runner register --no-interactive --instance https://app.copia.io --token <token> --name <name>
```

{% endcode %}

</details>

<details>

<summary><strong>Git LFS files fail to download in workflows</strong></summary>

See [LFS (Large File Storage)](/docs/actions/lfs-large-file-storage.md)

</details>

> Note for Self-Hosted Copia customers: All troubleshooting steps apply equally. Replace `https://app.copia.io` with your instance URL.


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## 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/faqs.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.
