# Runner as a Windows Service

On Windows, the runner can install itself as a native [Windows service](https://learn.microsoft.com/en-us/windows/win32/services/about-services) managed by the Service Control Manager (SCM). Running as a service means the runner starts automatically at boot, runs in the background without a logged-in user, and is automatically restarted by Windows if it crashes.

This page covers installing, configuring, and managing the runner as a Windows service using the built-in `service` commands.

{% hint style="info" %}
The `service` commands are only available on Windows builds of the runner. On Linux and macOS, manage the runner with systemd or launchd instead.
{% endhint %}

## Prerequisites

Before installing the service, make sure you have:

* The `act_runner` binary on the Windows machine where jobs will run.
* **An elevated (Administrator) terminal.** Creating, starting, stopping, and removing services all require administrator rights.
* **A registered runner.** Run `act_runner register` *before* installing the service so a `.runner` registration file exists in the working directory. See [Getting Started](broken://pages/ba8255ffc58be81036c8fa7411f5cd9ef26a27d1) for how to obtain a registration token and register a runner.

The installer checks for the `.runner` file at install time and refuses to proceed if it is missing. You can skip these checks with `--no-config-check`, but the service will fail to start without a valid registration.

## The `service` Commands

All service management is done through the `service` subcommand:

| Command                        | Description                                          |
| ------------------------------ | ---------------------------------------------------- |
| `act_runner service install`   | Create the service in SCM. Requires admin.           |
| `act_runner service start`     | Start the installed service.                         |
| `act_runner service stop`      | Stop the service, draining any in-flight jobs first. |
| `act_runner service status`    | Print the current SCM status of the service.         |
| `act_runner service uninstall` | Stop and remove the service.                         |

## Installing the Service

{% stepper %}
{% step %}

### Register the runner

From the directory where you want the runner to live, register it with your Copia instance. This creates the `.runner` file the service needs.

```powershell
.\act_runner.exe register `
  --no-interactive `
  --instance https://app.copia.io `
  --token <your_registration_token> `
  --name <runner_name>
  --labels '<your_labels_here>'
```

{% endstep %}

{% step %}

### Install the service

In an **elevated** terminal, run:

```powershell
.\act_runner.exe service install
```

This creates the service in SCM, registers a Windows event-log source, and grants the service account read/write access to the working directory. By default the service is named `CopiaActRunner`, shows as **Copia Act Runner** in `services.msc`, starts automatically at boot, and runs under an auto-managed virtual service account.

See [Install Options](#install-options) below to customize the name, account, start type, and more.
{% endstep %}

{% step %}

### Start the service

```powershell
.\act_runner.exe service start
```

The command blocks until the service reports **Running** (or times out). The runner will now pick up jobs and survive reboots.
{% endstep %}

{% step %}

### Verify

```powershell
.\act_runner.exe service status
```

A healthy, running service prints something like:

```
name=CopiaActRunner state=Running pid=12345 checkpoint=0 waitHint=0ms exitCode=0 serviceExit=0
```

The runner should also appear as online in your organization or repository **Runners** settings on Copia.
{% endstep %}
{% endstepper %}

## Install Options

The `service install` command accepts the following flags:

| Flag                   | Default                         | Description                                                                                                                       |
| ---------------------- | ------------------------------- | --------------------------------------------------------------------------------------------------------------------------------- |
| `--name`               | `CopiaActRunner`                | Service name (the SCM key, virtual-account name, and event-log source). Letters, digits, `-`, and `_` only.                       |
| `--display-name`       | `Copia Act Runner`              | Friendly name shown in `services.msc`.                                                                                            |
| `--description`        | `Runs Copia Actions workflows.` | Service description.                                                                                                              |
| `--config`             | *(none)*                        | Absolute path to a `config.yaml`. If omitted, the runner uses built-in defaults plus the `.runner` file in the working directory. |
| `--working-directory`  | directory of the binary         | Absolute path the service runs from. The `.runner` file and logs live here.                                                       |
| `--user`               | `virtual`                       | The Windows account the service runs as. See [Service Accounts](#service-accounts).                                               |
| `--password`           | *(none)*                        | Password for a real local/domain account. Prefer the `ACT_RUNNER_SVC_PASSWORD` environment variable.                              |
| `--start-type`         | `automatic`                     | One of `automatic`, `automatic-delayed`, `manual`, `disabled`.                                                                    |
| `--restart-on-failure` | `true`                          | Configure SCM recovery actions to auto-restart the runner if it crashes.                                                          |
| `--overwrite`          | `false`                         | Stop and replace an existing service of the same name.                                                                            |
| `--no-config-check`    | `false`                         | Skip the install-time existence checks for the config and `.runner` files.                                                        |

{% hint style="warning" %}
The working directory and the binary must be on a **local** drive. Installation is rejected for UNC/network paths (`\\server\share\…`) because service accounts cannot reliably authenticate to network shares.
{% endhint %}

### Running multiple runners on one machine

Each Windows service needs a unique name. To run more than one runner on the same host, give each its own `--name` and `--working-directory`:

```powershell
.\act_runner.exe service install --name CopiaActRunner-1 --working-directory C:\copia\runner1
.\act_runner.exe service install --name CopiaActRunner-2 --working-directory C:\copia\runner2
```

Pass the matching `--name` to `start`, `stop`, `status`, and `uninstall` for each.

## Service Accounts

The `--user` flag selects which Windows identity the service runs as:

| `--user` value                         | Account type                         | Notes                                                                                                                                                                           |
| -------------------------------------- | ------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| *(omitted)* or `virtual`               | **Virtual account** (default)        | SCM auto-creates an `NT SERVICE\<name>` account with no password and a per-service SID. The installer automatically grants it read/write on the working directory. Recommended. |
| `LocalSystem`                          | Built-in LocalSystem                 | The most privileged local account. No password.                                                                                                                                 |
| `NetworkService`                       | Built-in NetworkService              | Presents the machine account on the network. No password.                                                                                                                       |
| `.\name`, `DOMAIN\name`, `name@domain` | Real local or domain user            | **Requires a password.**                                                                                                                                                        |
| `DOMAIN\name$`, `name$@domain`         | Group Managed Service Account (gMSA) | The trailing `$` marks a gMSA. Must be domain-qualified. No password.                                                                                                           |

For real local/domain accounts, supply the password via the `ACT_RUNNER_SVC_PASSWORD` environment variable rather than the `--password` flag, which would otherwise be visible in shell history and process listings:

```powershell
$env:ACT_RUNNER_SVC_PASSWORD = "<password>"
.\act_runner.exe service install --user "DOMAIN\copia-runner"
```

## Managing the Service

```powershell
# Start / stop
.\act_runner.exe service start
.\act_runner.exe service stop

# Check status
.\act_runner.exe service status
```

You can also manage the service from the standard Windows tooling — `services.msc`, `sc.exe`, or `Start-Service` / `Stop-Service` in PowerShell — using the service name (default `CopiaActRunner`).

### Graceful stop and job draining

`service stop` triggers a graceful shutdown: the runner stops accepting new jobs and waits for any in-flight job to finish before the service reports **Stopped**. Windows is kept informed throughout so it does not kill the process prematurely. The drain is bounded by the runner's configured `ShutdownTimeout`. The same draining happens automatically on a system shutdown.

### Automatic restart

When installed with `--restart-on-failure` (the default), SCM is configured to automatically restart the runner if it exits unexpectedly, with escalating delays of 5 seconds, 15 seconds, and 60 seconds between successive failures.

## Logs and Troubleshooting

The service writes logs to two places:

* **`act_runner.log`** in the working directory. Because SCM discards the runner's standard output, this file is the primary log. All normal runner output goes here.
* **The Windows Application event log**, under the service name as the source. Errors and key lifecycle events (started, stopping, stopped, fatal) are mirrored here. View them in **Event Viewer → Windows Logs → Application**.

If the service fails so early that the log file cannot be opened, the runner writes a one-line breadcrumb to `act_runner.startup-error.log` next to the binary.

Common issues:

* **"service already exists"** — A service with that name is already installed. Pass `--overwrite` to replace it, or choose a different `--name`.
* **"runner registration file ... not found"** — Run `act_runner register` in the working directory first, or pass `--no-config-check` if you are registering separately.
* **Access denied / "admin required"** — Run the command from an elevated (Administrator) terminal.
* **Service starts then stops immediately** — Check `act_runner.log` and the Application event log. A missing or invalid `.runner` registration is the most common cause.

## Uninstalling

In an elevated terminal:

```powershell
.\act_runner.exe service uninstall
```

This stops the service (if running), removes it from SCM, and deregisters its event-log source. Add `--name <name>` if you installed under a non-default name. The working directory and its logs are left in place.

{% hint style="info" %}
Note for Self-Hosted customers: replace `https://app.copia.io` with your instance URL in all commands above.
{% 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/runner-as-a-windows-service.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.
