# How to Add Linux Capabilities to a Container Using Apple Container

> Easily add Linux capabilities to your containers with Apple Container using the cap add flag. Learn to control container permissions effectively.

- Repository: [Apple/container](https://github.com/apple/container)
- Tags: how-to-guide
- Published: 2026-07-05

---

**You can add Linux capabilities to a container using the `--cap-add` flag (e.g., `container run --cap-add NET_ADMIN alpine`) or remove them with `--cap-drop`, with processing occurring in that specific order.**

Apple Container provides granular control over the Linux kernel capabilities available to your containers, moving beyond the traditional "all-or-nothing" permission model. By default, containers run with a minimal, hardened capability set defined in the runtime configuration. This guide explains how to leverage the `--cap-add` and `--cap-drop` flags to customize security permissions for specific use cases.

## Understanding Linux Capabilities in Apple Container

Linux capabilities are kernel-level permissions that grant specific privileges to processes without requiring full root access. Traditional Linux processes either have all capabilities (running as root) or none, but Apple Container adopts a **minimal default approach** for enhanced security.

The container runtime initializes with a curated subset of capabilities optimized for general workloads. When you need additional privileges—such as `CAP_NET_ADMIN` for network administration or `CAP_SYS_ADMIN` for system-level operations—you can surgically add only what is necessary rather than running a fully privileged container.

## CLI Flags for Capability Management

The Apple Container CLI exposes two primary flags for capability manipulation, implemented in [`Sources/Services/ContainerAPIService/Client/Flags.swift`](https://github.com/apple/container/blob/main/Sources/Services/ContainerAPIService/Client/Flags.swift) through the `capAdd` and `capDrop` string array properties.

### Adding Capabilities with --cap-add

Use `--cap-add` to grant additional capabilities to the container's effective set. The flag accepts capability names with or without the `CAP_` prefix and is case-insensitive.

```bash

# Add a specific capability

container run --cap-add NET_ADMIN alpine ip link set lo down

# Add multiple capabilities

container run --cap-add NET_RAW --cap-add SYS_ADMIN alpine sh

# Grant all capabilities (privileged mode)

container run --cap-add ALL alpine sh -c "ip link set lo down && echo ok"

```

### Removing Capabilities with --cap-drop

Use `--cap-drop` to remove capabilities from the default set or from any previously added ones. This is useful for creating even more restrictive environments than the default.

```bash

# Drop a specific capability from the default set

container run --cap-drop CHOWN alpine chown 100 /tmp

# Remove all capabilities for maximum restriction

container run --cap-drop ALL alpine id

```

### Understanding Processing Order

**Capabilities are dropped before they are added.** This processing order means that `--cap-drop ALL --cap-add ALL` results in a container with **all capabilities enabled**, because the drop operation occurs first, then the add operation restores full access. This behavior is documented in the *Control Linux capabilities* section of the project documentation.

## Implementation Architecture

The capability configuration flows from the CLI through to the Linux kernel via the container runtime service. In [`Sources/Services/ContainerAPIService/Client/Flags.swift`](https://github.com/apple/container/blob/main/Sources/Services/ContainerAPIService/Client/Flags.swift), the flags are defined as Swift `@Option` properties:

```swift
@Option(
    name: .customLong("cap-add"),
    help: .init("Add a Linux capability (e.g. CAP_NET_RAW, or ALL)", valueName: "cap")
)
public var capAdd: [String] = []

@Option(
    name: .customLong("cap-drop"),
    help: .init("Drop a Linux capability (e.g. CAP_NET_RAW, or ALL)", valueName: "cap")
)
public var capDrop: [String] = []

```

These values are passed to the runtime when executing `container run` or `container create` commands. The [`Sources/Services/RuntimeLinux/Server/RuntimeService.swift`](https://github.com/apple/container/blob/main/Sources/Services/RuntimeLinux/Server/RuntimeService.swift) file configures the underlying Linux kernel's **capability Linux Security Module (LSM)** through kernel command-line arguments (`lsm=lockdown,capability,…`), ensuring the kernel enforces the specified capability boundaries.

## Practical Examples

Combine drops and adds to create a least-privilege container that has only the specific permissions it needs:

```bash

# Drop all capabilities, then add only the specific ones required

container run --cap-drop ALL --cap-add SETUID --cap-add SETGID alpine id

# Network administration container with default set minus CHOWN

container run --cap-add NET_ADMIN --cap-drop CHOWN alpine sh

```

These flags work identically with both `container run` (immediate execution) and `container create` (pre-creation setup), as verified by the integration tests in [`Tests/IntegrationTests/Run/TestCLIRunCapabilities.swift`](https://github.com/apple/container/blob/main/Tests/IntegrationTests/Run/TestCLIRunCapabilities.swift).

## Summary

- **Default security**: Apple Container starts containers with a minimal, hardened capability set rather than granting all root privileges.
- **Granular control**: Use `--cap-add` to grant specific kernel capabilities and `--cap-drop` to remove them.
- **Processing order**: Drops are processed before adds, allowing patterns like `--cap-drop ALL --cap-add NET_ADMIN` for least-privilege networking.
- **Flexibility**: Capability names are case-insensitive and work with or without the `CAP_` prefix.
- **Integration**: Flags are parsed in [`Flags.swift`](https://github.com/apple/container/blob/main/Flags.swift) and enforced by the LSM configuration in [`RuntimeService.swift`](https://github.com/apple/container/blob/main/RuntimeService.swift).

## Frequently Asked Questions

### What is the default capability set for containers?

According to the Apple Container source code, containers start with a curated list of capabilities chosen specifically for security hardening. This minimal set excludes most administrative capabilities like `CAP_SYS_ADMIN` or `CAP_NET_ADMIN`, requiring explicit opt-in through `--cap-add` when these permissions are necessary.

### Can I use --cap-add with container create?

Yes, the `--cap-add` and `--cap-drop` flags work with both `container run` and `container create` commands. The capability configuration is stored when creating the container and applied when the container subsequently starts.

### Is the capability name case-sensitive?

No, capability names are case-insensitive in Apple Container. You can specify `NET_ADMIN`, `net_admin`, `Cap_Net_Admin`, or use the full kernel name `CAP_NET_ADMIN`—all resolve to the same capability.

### How does --cap-drop ALL --cap-add ALL behave?

This combination results in a container with **all capabilities enabled**. Because drops are processed before adds, the sequence first removes all capabilities, then immediately adds them all back. This is functionally equivalent to running a privileged container and is supported by the processing order logic implemented in the runtime.