Skip to content
Back to blog
LaravelHomelabSeguridad

Repository-level Dependabot runners for private networks

GitHub now lets each repository choose its Dependabot runner, which is useful when packages live on private networks.

Ismael Catala4 min read

The network is usually the real problem

In a Laravel project with private packages, Dependabot may need to reach a Composer registry that is not exposed to the public Internet. The same applies to an internal npm registry, a Git server, or any service that only exists inside a homelab or company network. A GitHub-hosted runner is not guaranteed to resolve that private DNS name or connect to that infrastructure.

Runner selection for Dependabot used to be an organization-wide concern. That is fine when every repository has the same network requirements, but it becomes awkward when only a few projects need access to a VLAN, a specific proxy, or a private registry. A global setting quickly becomes too broad for a very specific requirement.

GitHub now lets private repositories choose a runner for Dependabot directly. You can select a labeled runner, optionally choose a runner group, and run Dependabot version and security updates there. When no custom label is provided, Dependabot uses the dependabot label. (github.blog)

A practical Laravel setup

Take a Laravel application that depends on Composer packages published to a registry only reachable from a homelab. A self-hosted runner on that network can resolve internal hostnames, access the registry, and authenticate with the credentials configured for Dependabot. There is no need to expose the package service publicly just so GitHub can check for dependency updates.

The runner setting does not live in .github/dependabot.yml. It is configured in the repository UI under Settings, then Advanced Security, then Dependency scanning, in the Dependabot version updates section, through the Runner type selector. Select Labeled runner, optionally provide a runner group and custom label, then save the selection. (docs.github.com)

The registry configuration can still stay in dependabot.yml. This example defines a private Composer repository and makes it available to the update job:

version: 2
 
registries:
  composer-internal:
    type: composer-repository
    url: https://packages.intra.example
    username: dependabot
    password: ${{secrets.COMPOSER_REPOSITORY_PASSWORD}}
 
updates:
  - package-ecosystem: "composer"
    directory: "/"
    registries: "*"
    schedule:
      interval: "weekly"

The password should not be committed to the repository. GitHub supports Dependabot secrets at repository and organization level, and those secrets can be referenced from the configuration file. For a Composer registry, the documented registry type is composer-repository, with username and password authentication fields. (docs.github.com)

Keep private access where it belongs

The useful part is not merely having a self-hosted runner. It is being able to reserve it for repositories that actually need it. A project using only Packagist can keep the standard GitHub-hosted environment, while a Laravel application with internal dependencies can target a label such as dependabot-homelab.

This also makes network boundaries easier to maintain. You can place runners with internal access in a dedicated runner group instead of giving every organization runner the same reach into private services. Labels route the work, while runner groups limit which repositories can use those runners, provided the repository has access to the selected group. (docs.github.com)

I would treat this as part of network segmentation, not as a convenience toggle. A Dependabot runner needs access to the registry and little else; it does not need unrestricted access to the entire homelab. If it has more permissions than necessary, a routine dependency update gains an unnecessarily large blast radius.

The fine print

This does not turn Dependabot into a fully custom workflow engine. Selecting a runner decides where update jobs run, but it does not replace registry settings, secrets, or update rules in dependabot.yml. Missing credentials, an invalid internal certificate, or broken DNS will still cause failures even when the job runs inside the private network.

Before choosing a labeled runner, that runner must already exist and have the intended label. If you specify a runner group, the group must exist and the repository must be allowed to use it. Also, changing the runner selection does not trigger a new Dependabot run by itself. (docs.github.com)

It is not available everywhere either. GitHub states that these controls are shown for private and internal repositories on github.com, not for public repositories or GitHub Enterprise Server. Security configurations do not currently enforce Dependabot runner settings, so repositories that rely on this setup need to be reviewed individually. (github.blog)

Finally, self-hosted runners need operational care. Keep them updated, monitor their connectivity, limit who can use them, and avoid sharing them casually across jobs with different trust levels. Private network access solves the registry problem, but it also makes isolation more important.


Source: GitHub Changelog Official documentation: Configuring Dependabot on self-hosted runners