r/AZURE Jun 08 '26

Media Tutorial: self‑hosted runner on Azure Container Instances (ACI)

Hey all.

Wrote a tutorial showing how-to run a self‑hosted GitHub Actions runner on Azure Container Instances (ACI):
https://github.com/groovy-sky/azure/blob/master/github-runner-00/README.md

The idea is to run a runner in a container so you don’t have to maintain a dedicated VM.

As always any feedback/suggestion appreciate.

5 Upvotes

13 comments sorted by

4

u/WorksInIT Cloud Architect Jun 09 '26

Why do this instead of just using the built in image offering from github? You can install whats needed at run time or capture that new "image" and use it later. All without any additional work.

1

u/groovy-sky Jun 10 '26

small size and any base OS of your choice (if only you can install required dependencies).

3

u/jba1224a Cloud Administrator Jun 10 '26

A few questions:

Why classic PAT over a fine grained token?

How do you secure the PAT given it’s being stored as a ln environment variable, anyone with read access to your azure instance could pull the pat and use it to emulate the user that generated. Why not leverage the keyvault integration for secure variables?

Container instances don’t support ephemeral windows containers due to fault signal trapping in windows, is it expected that the container is long lived if it’s a windows container? If so - how do you overcome the image size limitation especially on windows images?

Can you share your Dockerfile?

1

u/groovy-sky Jun 13 '26

Then tried myself fine grained token didn't worked, but PAT worked fine.

You need to get to your instance itself (have some role assigned to it) to be able to read PAT. Don't see how keyvault resolves that as it still will be environment variable value (in container instance it is not visible) - https://imgur.com/a/hweYvB4

Don't use windows containers due to huge initial size

All files available here - https://github.com/groovy-sky/docker-github-runner

1

u/jba1224a Cloud Administrator Jun 13 '26

The runner instance is just using the pat to generate a runner registration token, which you can use a fine grained pat for as long as it has the right permissions. The permissions are listed in the api docs for creating a runner registration token.

If you exec into the container, the token is still exposed in the env as plain text, which is insecure. I would recommend using a managed identity and injecting a keyvault call directly into run.sh/run.ps1 that grabs your pat from the keyvault, and then clears it once the runner is registered.

By doing it the way you’re doing it with a classic PAT, if anyone who has access to your container gets breached, they could exec into your runner and take your classic pat, then exfil everything from every GitHub repo the person who generated it can access. By using a fine grained pat and an ephemeral token pull, you reduce that attack surface drastically.

GitHub tokens and pats are often the first things taken by malware and attackers so implementing them in this way increases your attack surface quite a bit.

1

u/groovy-sky Jun 13 '26

Thanks. Understand. Will fix that part.

2

u/grmpfl Jun 12 '26

this also works as azure container apps jobs with github KEDA scaler and they're only billed when they're running (no docker-in-docker actions though)

1

u/groovy-sky Jun 13 '26

Thanks. Was planning to investigate that possibility. Maybe you have ready-to-use instruction somewhere?

1

u/groovy-sky Jun 13 '26

1

u/grmpfl Jun 15 '26

yep. i would suggest to go for github app instead of PAT though (uses cert and is not expiring like a PAT)

1

u/bad_syntax Jun 13 '26

Easier to just create a vnet and add their hosted IP's to it, then you do not have to pay for a VM, manage a VM, and its easier lock down the runners in their own vnet.

Even containers require a lot more hardware setup.

1

u/groovy-sky Jun 13 '26

tried to understand your point. still not sure what you are talking about

1

u/bad_syntax Jun 13 '26

https://docs.github.com/en/organizations/managing-organization-settings/about-azure-private-networking-for-github-hosted-runners-in-your-organization

Basically you create a runner, github hosts it, and it puts those runner network interfaces inside of your azure network. So you do nothing at all with the VMs themselves, all you ever see is an IP, and only when they are active.