Using policy-rc.d to Stop Services in Debian Chroot

This article provides an overview of the policy-rc.d mechanism in Debian-based operating systems and demonstrates how to use it to block services from starting automatically within chroot environments, image builds, and container setups.

What Is policy-rc.d?

In Debian and its derivatives, package maintainer scripts do not invoke init scripts or systemd units directly during installation or upgrade. Instead, they call a wrapper script named invoke-rc.d.

Before invoke-rc.d executes any action—such as start, stop, or restart—it checks for the existence of /usr/sbin/policy-rc.d. If this file is present and executable, invoke-rc.d executes it with the target service name and requested action as arguments to query whether the operation is permitted.

Why Block Services in a Chroot?

When you install packages via apt or dpkg inside a chroot (or during a debootstrap process, Docker build, or VM image creation), Debian defaults to starting newly installed daemons immediately.

In a chroot, this default behavior causes several problems:

  • Port Conflicts: Daemons may attempt to bind to network interfaces already used by the host system.
  • Hanging Builds: Long-running daemon processes can cause automated build scripts to hang.
  • Missing Subsystems: Daemons that depend on a fully booted kernel, mounted virtual filesystems (like /proc or /sys), or a running D-Bus/systemd daemon will fail, causing package installation scripts to return non-zero exit codes.

How policy-rc.d Works

The interface specification dictates that /usr/sbin/policy-rc.d returns specific exit codes to signal whether an action is allowed:

  • 0: Action is permitted.
  • 101: Action is forbidden.
  • 104: Action is forbidden, but the script fallback should occur if applicable.

When /usr/sbin/policy-rc.d exits with status 101, invoke-rc.d suppresses the execution of the init script and exits cleanly with a status code of 0. This allows package configuration to complete successfully without the service ever running.

Implementing policy-rc.d

To block all services from starting within a chroot, create an executable script at /usr/sbin/policy-rc.d that always exits with 101.

Execute the following command inside the chroot environment:

printf '#!/bin/sh\nexit 101\n' > /usr/sbin/policy-rc.d
chmod +x /usr/sbin/policy-rc.d

Verification

Once the file is created, installing any daemon package will bypass service execution. The package manager output will typically display a message indicating that the action was denied by policy:

invoke-rc.d: policy-rc.d denied execution of start.

Cleaning Up

If the chroot environment will later be booted as a full operating system (such as when preparing a root filesystem for a physical machine or virtual machine), remove the script before final packaging:

rm -f /usr/sbin/policy-rc.d

If the chroot is used strictly as an isolated build environment or container where daemons should never be managed via invoke-rc.d, the file can remain in place permanently.