Running act in Privileged Docker Mode: A Complete Guide to the `--privileged` Flag

The --privileged flag in act grants workflow containers full Linux capabilities (device access, kernel module loading, and unrestricted syscalls) by passing the setting through Cobra CLI parsing → runner configuration → Docker SDK HostConfig.

Running act in privileged Docker mode is essential when your GitHub Actions workflows require low-level system operations that standard container security policies block. This open-source CLI tool (available at nektos/act) executes workflows locally by spinning up Docker containers, and the --privileged flag ensures those containers receive the same extended privileges as Docker's native --privileged runtime option. Understanding the internal data flow—from command-line parsing in cmd/root.go to the final Docker SDK invocation—helps you debug permission failures and secure your local CI/CD pipeline.

Architecture: How --privileged Flows Through the Codebase

The flag travels through six distinct layers before reaching the Docker Engine, each handled by specific source files in the repository.

CLI Flag Definition and Parsing

In cmd/root.go at line 90, the Cobra framework registers the flag:

rootCmd.Flags().BoolVar(&input.privileged, "privileged", false, "use privileged mode")

This binds the command-line argument to the Input struct field, making the value available during runner initialization.

Configuration Propagation

The parsed value moves into pkg/runner/runner.go at line 44, where the Config struct defines:

Privileged bool // use privileged mode

When act initializes a new run, this Config object embeds into RunContext (defined in pkg/runner/run_context.go), ensuring every workflow step can access the privileged setting via rc.Config.Privileged.

Container Creation for docker:// Steps

When executing a step that uses uses: docker://, the newStepContainer function in pkg/runner/step_docker.go (line 30) constructs the container input:

Privileged: rc.Config.Privileged

This bridges the runner configuration with the container abstraction layer.

Docker SDK Integration

The flag passes through two critical files in the container package:

  1. CLI Options (pkg/container/docker_cli.go, line 10): Exposes the flag to internal Docker option parsing with flags.BoolVar(&copts.privileged, "privileged", false, "Give extended privileges to this container")

  2. Runtime Execution (pkg/container/docker_run.go, line 465): Translates the boolean into Docker's HostConfig:

Privileged: input.Privileged,

This final assignment tells the Docker Engine to launch the container with unrestricted capabilities.

Practical Usage Examples

Running Full Workflows with Privileged Containers

Execute your entire workflow with elevated privileges when you need operations like modprobe or device mounting:

act --privileged -P ubuntu-latest=nektos/act-environments-ubuntu:20.04

The -P flag specifies a custom runner image, while --privileged ensures any step requiring kernel-level access succeeds without Operation not permitted errors.

Privileged Mode for Specific docker:// Steps

Target privileged mode for individual container steps in your workflow YAML:

jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - name: Mount tmpfs filesystem
        uses: docker://alpine
        with:
          args: sh -c "mount -t tmpfs none /mnt && echo 'Success'"

Then invoke act with:

act --privileged

The implementation in pkg/runner/step_docker.go automatically forwards the privileged flag to these transient containers.

Programmatic Configuration (Library Usage)

When embedding act as a Go library, enable privileged mode explicitly in the configuration struct:

cfg := &runner.Config{
    Privileged: true, // Maps to pkg/runner/runner.go line 44
    Workdir:    "./my-project",
}

r, err := runner.New(cfg)
if err != nil {
    log.Fatal(err)
}

This directly sets the Privileged field analyzed in pkg/runner/runner.go, bypassing CLI parsing while maintaining identical runtime behavior.

Key Implementation Files

  • cmd/root.go: Root command flag registration using Cobra; defines the --privileged switch and binds it to the Input struct
  • pkg/runner/runner.go: Defines the canonical Config struct with the Privileged bool field (line 44) that serves as the single source of truth
  • pkg/runner/step_docker.go: Constructs container.NewContainerInput and maps rc.Config.Privileged to the container definition (line 30)
  • pkg/container/docker_cli.go: Parses Docker-specific CLI options, including the privileged flag for container runtime settings (line 10)
  • pkg/container/docker_run.go: Final translation layer that assigns Privileged: input.Privileged to the Docker SDK HostConfig (line 465)

Summary

  • The --privileged flag propagates from cmd/root.go through runner.Config to the Docker SDK's HostConfig.Privileged field
  • Use it when workflows require kernel module loading, device access, or mounting filesystems that standard containers cannot perform
  • Implementation spans six source files across the CLI, runner, and container packages, ensuring type-safe boolean propagation
  • Security warning: Privileged mode grants the container the same power as the host root user—only enable it for trusted workflows
  • Library users can set runner.Config.Privileged = true directly without using command-line arguments

Frequently Asked Questions

What does the --privileged flag do in act?

The flag grants workflow containers full Linux capabilities by setting Privileged: true in the Docker SDK HostConfig, equivalent to Docker's native --privileged runtime option. According to the source in pkg/container/docker_run.go, this allows the container to access all host devices, load kernel modules, and bypass standard syscall restrictions.

Is it safe to run act with --privileged?

Running act in privileged Docker mode exposes your host system to the same risks as running any privileged container—workflow steps gain root-equivalent access to your kernel and hardware. Only enable this flag when executing trusted workflows that specifically require capabilities like modprobe or device mounting, as implemented in pkg/runner/step_docker.go.

Why would I need privileged mode for GitHub Actions?

You need this mode when workflows perform low-level system operations that Docker's default seccomp profile blocks, such as mounting filesystems, accessing /dev devices, or loading kernel modules. The act tool forwards this requirement through runner.Config.Privileged to ensure local execution matches GitHub-hosted runner capabilities.

How do I verify that privileged mode is active?

Check the container runtime configuration by inspecting the HostConfig passed to the Docker client in pkg/container/docker_run.go. When Privileged is true, the Docker Engine logs will show "Privileged": true in the container creation JSON, and operations like mount -t tmpfs will succeed without permission errors inside the workflow step.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →