Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 15 additions & 0 deletions .github/workflows/main.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -281,3 +281,18 @@ jobs:
docker exec test docker info
docker exec test ./integration-docker.sh
docker rm -f test

build-tags:
name: "Build with disabled drivers tags"
runs-on: ubuntu-24.04
steps:
- name: "Check out"
uses: actions/checkout@v5
- name: "Set up Go"
uses: actions/setup-go@v5
with:
go-version-file: go.mod
- name: "Build with -tags no_gvisortapvsock"
run: go build -v -tags no_gvisortapvsock ./cmd/rootlesskit
- name: "Build with -tags 'no_slirp4netns no_lxcusernic no_gvisortapvsock'"
run: go build -v -tags "no_slirp4netns no_lxcusernic no_gvisortapvsock" ./cmd/rootlesskit
31 changes: 29 additions & 2 deletions cmd/rootlesskit/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,33 @@ Examples:
Note: RootlessKit requires /etc/subuid and /etc/subgid to be configured by the real root user.
See https://rootlesscontaine.rs/getting-started/common/ .
`
// Build the list of available network drivers for help text
// Only compiled-in drivers will be shown here, so omitted drivers don't appear in --help.
drivers := []string{"host", "none", "pasta(experimental)"}
if slirp4netns.Available {
drivers = append(drivers, "slirp4netns")
}
if vpnkit.Available {
drivers = append(drivers, "vpnkit")
}
if lxcusernic.Available {
drivers = append(drivers, "lxc-user-nic(experimental)")
}
if gvisortapvsock.Available {
drivers = append(drivers, "gvisor-tap-vsock(experimental)")
}
netDriversHelp := strings.Join(drivers, ", ")

// Build the list of available port drivers for help text
portDrivers := []string{"none", "implicit (for pasta)", "builtin"}
if slirp4netns_port.Available {
portDrivers = append(portDrivers, "slirp4netns")
}
if gvisortapvsock_port.Available {
portDrivers = append(portDrivers, "gvisor-tap-vsock(experimental)")
}
portDriversHelp := strings.Join(portDrivers, ", ")

app.Flags = []cli.Flag{
Categorize(&cli.BoolFlag{
Name: "debug",
Expand All @@ -99,7 +126,7 @@ See https://rootlesscontaine.rs/getting-started/common/ .
}, CategoryState),
Categorize(&cli.StringFlag{
Name: "net",
Usage: "network driver [host, none, pasta(experimental), slirp4netns, vpnkit, lxc-user-nic(experimental), gvisor-tap-vsock(experimental)]",
Usage: fmt.Sprintf("network driver [%s]", netDriversHelp),
Value: "host",
}, CategoryNetwork),
Categorize(&cli.StringFlag{
Expand Down Expand Up @@ -169,7 +196,7 @@ See https://rootlesscontaine.rs/getting-started/common/ .
}, CategoryMount),
Categorize(&cli.StringFlag{
Name: "port-driver",
Usage: "port driver for non-host network. [none, implicit (for pasta), builtin, slirp4netns, gvisor-tap-vsock]",
Usage: fmt.Sprintf("port driver for non-host network. [%s]", portDriversHelp),
Value: "none",
}, CategoryPort),
Categorize(&cli.StringSliceFlag{
Expand Down
20 changes: 20 additions & 0 deletions docs/BUILDING.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
# Building RootlessKit

This document describes build-time options, including Go build tags for omitting certain network and port drivers.

## Build tags to omit drivers

To exclude specific drivers at compilation time, use Go build tags:

- Tag `no_vpnkit`: omits the VPNKit network driver implementation.
- Tag `no_gvisortapvsock`: omits the gvisor-tap-vsock network driver implementation and its port driver.
- Tag `no_slirp4netns`: omits the slirp4netns network driver implementation and its port driver.
- Tag `no_lxcusernic`: omits the lxc-user-nic network driver implementation.

Example:

- Build without VPNKit support:
go build -tags no_vpnkit ./cmd/rootlesskit

Notes:
- If a disabled driver is selected at runtime (e.g., `--net=vpnkit` when built with `-tags no_vpnkit`), RootlessKit returns an error indicating that the driver was disabled at build time.
5 changes: 5 additions & 0 deletions docs/network.md
Original file line number Diff line number Diff line change
Expand Up @@ -267,3 +267,8 @@ The `--detach-netns` flag (since v2.0.0) detaches network namespaces into `$ROOT
and executes the child command in the host's network namespace.

The child command can enter `$ROOTLESSKIT_STATE_DIR/netns` by itself to create nested network namespaces.


## Build tags to omit drivers
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should be probably in /BUILDING.md

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixed


Build-time driver selection is documented in [BUILDING.md](BUILDING.md).
4 changes: 4 additions & 0 deletions docs/port.md
Original file line number Diff line number Diff line change
Expand Up @@ -59,3 +59,7 @@ To specify IPv6 explicitly, use `tcp6`, e.g., `[::]:8080:80/tcp6`.

The `tcp4` and `tcp6` forms were introduced in RootlessKit v0.14.0.
The `tcp6` is currently supported only for `builtin` port driver.

## Build tags to omit port drivers

Build-time driver selection is documented in [BUILDING.md](BUILDING.md).
5 changes: 5 additions & 0 deletions pkg/network/gvisortapvsock/gvisortapvsock.go
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
//go:build !no_gvisortapvsock
// +build !no_gvisortapvsock

package gvisortapvsock

import (
Expand Down Expand Up @@ -32,6 +35,8 @@ const (
DriverName = "gvisor-tap-vsock"
// Default buffer size for packet reading/writing
defaultBufferSize = 65536
// Available indicates whether this driver is compiled in (used for generating help text)
Available = true
)

// NewParentDriver instantiates a new parent driver
Expand Down
48 changes: 48 additions & 0 deletions pkg/network/gvisortapvsock/gvisortapvsock_disabled.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
//go:build no_gvisortapvsock
// +build no_gvisortapvsock

package gvisortapvsock

import (
"context"
"errors"
"io"
"net"

"github.com/rootless-containers/rootlesskit/v3/pkg/api"
"github.com/rootless-containers/rootlesskit/v3/pkg/messages"
"github.com/rootless-containers/rootlesskit/v3/pkg/network"
)

// NewParentDriver returns a stub when built with the no_gvisortapvsock tag.
func NewParentDriver(logWriter io.Writer, mtu int, ipnet *net.IPNet, ifname string, disableHostLoopback bool, enableIPv6 bool) (network.ParentDriver, error) {
return &disabledParent{}, errors.New("gvisor-tap-vsock network driver disabled by build tag no_gvisortapvsock")
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Omitted drivers should not appear in --help

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixed

}

type disabledParent struct{}

func (d *disabledParent) Info(ctx context.Context) (*api.NetworkDriverInfo, error) {
return nil, errors.New("gvisor-tap-vsock network driver disabled by build tag no_gvisortapvsock")
}

func (d *disabledParent) MTU() int { return 0 }

func (d *disabledParent) ConfigureNetwork(childPID int, stateDir string, detachedNetNSPath string) (*messages.ParentInitNetworkDriverCompleted, func() error, error) {
return nil, func() error { return nil }, errors.New("gvisor-tap-vsock network driver disabled by build tag no_gvisortapvsock")
}

// NewChildDriver returns a stub when built with the no_gvisortapvsock tag.
func NewChildDriver() network.ChildDriver { return &disabledChild{} }

type disabledChild struct{}

func (d *disabledChild) ChildDriverInfo() (*network.ChildDriverInfo, error) {
return &network.ChildDriverInfo{ConfiguresInterface: false}, nil
}

func (d *disabledChild) ConfigureNetworkChild(netmsg *messages.ParentInitNetworkDriverCompleted, detachedNetNSPath string) (string, error) {
return "", errors.New("gvisor-tap-vsock network driver disabled by build tag no_gvisortapvsock")
}

// Available indicates whether this driver is compiled in (used for generating help text)
const Available = false
6 changes: 6 additions & 0 deletions pkg/network/lxcusernic/lxcusernic.go
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
//go:build !no_lxcusernic
// +build !no_lxcusernic

package lxcusernic

import (
Expand Down Expand Up @@ -214,3 +217,6 @@ func dhcpRenewRoutine(c *client4.Client, dev string, initialIP net.IP, lease tim
lease = p.IPAddressLeaseTime(lease)
}
}

// Available indicates whether this driver is compiled in (used for generating help text)
const Available = true
46 changes: 46 additions & 0 deletions pkg/network/lxcusernic/lxcusernic_disabled.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
//go:build no_lxcusernic
// +build no_lxcusernic

package lxcusernic

import (
"context"
"errors"

"github.com/rootless-containers/rootlesskit/v3/pkg/api"
"github.com/rootless-containers/rootlesskit/v3/pkg/messages"
"github.com/rootless-containers/rootlesskit/v3/pkg/network"
)

// NewParentDriver returns a stub when built with the no_lxcusernic tag.
func NewParentDriver(binary string, mtu int, bridge string, ifname string) (network.ParentDriver, error) {
return &disabledParent{}, errors.New("lxc-user-nic network driver disabled by build tag no_lxcusernic")
}

type disabledParent struct{}

func (d *disabledParent) Info(ctx context.Context) (*api.NetworkDriverInfo, error) {
return nil, errors.New("lxc-user-nic network driver disabled by build tag no_lxcusernic")
}

func (d *disabledParent) MTU() int { return 0 }

func (d *disabledParent) ConfigureNetwork(childPID int, stateDir string, detachedNetNSPath string) (*messages.ParentInitNetworkDriverCompleted, func() error, error) {
return nil, func() error { return nil }, errors.New("lxc-user-nic network driver disabled by build tag no_lxcusernic")
}

// NewChildDriver returns a stub when built with the no_lxcusernic tag.
func NewChildDriver() network.ChildDriver { return &disabledChild{} }

type disabledChild struct{}

func (d *disabledChild) ChildDriverInfo() (*network.ChildDriverInfo, error) {
return &network.ChildDriverInfo{ConfiguresInterface: false}, nil
}

func (d *disabledChild) ConfigureNetworkChild(netmsg *messages.ParentInitNetworkDriverCompleted, detachedNetNSPath string) (string, error) {
return "", errors.New("lxc-user-nic network driver disabled by build tag no_lxcusernic")
}

// Available indicates whether this driver is compiled in (used for generating help text)
const Available = false
6 changes: 6 additions & 0 deletions pkg/network/slirp4netns/slirp4netns.go
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
//go:build !no_slirp4netns
// +build !no_slirp4netns

package slirp4netns

import (
Expand Down Expand Up @@ -353,3 +356,6 @@ func (d *childDriver) ConfigureNetworkChild(netmsg *messages.ParentInitNetworkDr
// and they are up to the child.
return tap, nil
}

// Available indicates whether this driver is compiled in (used for generating help text)
const Available = true
75 changes: 75 additions & 0 deletions pkg/network/slirp4netns/slirp4netns_disabled.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
//go:build no_slirp4netns
// +build no_slirp4netns

package slirp4netns

import (
"context"
"errors"
"io"
"net"

"github.com/rootless-containers/rootlesskit/v3/pkg/api"
"github.com/rootless-containers/rootlesskit/v3/pkg/messages"
"github.com/rootless-containers/rootlesskit/v3/pkg/network"
)

// Features is defined to satisfy references from cmd when the slirp4netns
// network driver is disabled via the no_slirp4netns build tag.
// It mirrors the shape of the real Features struct.
type Features struct {
// SupportsEnableIPv6 --enable-ipv6 (v0.2.0)
SupportsEnableIPv6 bool
// SupportsCIDR --cidr (v0.3.0)
SupportsCIDR bool
// SupportsDisableHostLoopback --disable-host-loopback (v0.3.0)
SupportsDisableHostLoopback bool
// SupportsAPISocket --api-socket (v0.3.0)
SupportsAPISocket bool
// SupportsEnableSandbox --enable-sandbox (v0.4.0)
SupportsEnableSandbox bool
// SupportsEnableSeccomp --enable-seccomp (v0.4.0)
SupportsEnableSeccomp bool
// KernelSupportsEnableSeccomp whether the kernel supports slirp4netns --enable-seccomp
KernelSupportsEnableSeccomp bool
}

// DetectFeatures is a stub used when the slirp4netns network driver is
// disabled via the no_slirp4netns build tag. It always returns an error so
// callers can gracefully handle the lack of support at runtime.
func DetectFeatures(binary string) (*Features, error) {
return nil, errors.New("slirp4netns network driver disabled by build tag no_slirp4netns")
}

// NewParentDriver returns a stub when built with the no_slirp4netns tag.
func NewParentDriver(logWriter io.Writer, binary string, mtu int, ipnet *net.IPNet, ifname string, disableHostLoopback bool, apiSocketPath string, enableSandbox bool, enableSeccomp bool, enableIPv6 bool) (network.ParentDriver, error) {
return &disabledParent{}, errors.New("slirp4netns network driver disabled by build tag no_slirp4netns")
}

type disabledParent struct{}

func (d *disabledParent) Info(ctx context.Context) (*api.NetworkDriverInfo, error) {
return nil, errors.New("slirp4netns network driver disabled by build tag no_slirp4netns")
}

func (d *disabledParent) MTU() int { return 0 }

func (d *disabledParent) ConfigureNetwork(childPID int, stateDir string, detachedNetNSPath string) (*messages.ParentInitNetworkDriverCompleted, func() error, error) {
return nil, func() error { return nil }, errors.New("slirp4netns network driver disabled by build tag no_slirp4netns")
}

// NewChildDriver returns a stub when built with the no_slirp4netns tag.
func NewChildDriver() network.ChildDriver { return &disabledChild{} }

type disabledChild struct{}

func (d *disabledChild) ChildDriverInfo() (*network.ChildDriverInfo, error) {
return &network.ChildDriverInfo{ConfiguresInterface: false}, nil
}

func (d *disabledChild) ConfigureNetworkChild(netmsg *messages.ParentInitNetworkDriverCompleted, detachedNetNSPath string) (string, error) {
return "", errors.New("slirp4netns network driver disabled by build tag no_slirp4netns")
}

// Available indicates whether this driver is compiled in (used for generating help text)
const Available = false
6 changes: 6 additions & 0 deletions pkg/network/vpnkit/vpnkit.go
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
//go:build !no_vpnkit
// +build !no_vpnkit

package vpnkit

import (
Expand Down Expand Up @@ -288,3 +291,6 @@ func vif2tap(w io.Writer, vif *vmnet.Vif) {
}
}
}

// Available indicates whether this driver is compiled in (used for generating help text)
const Available = true
46 changes: 46 additions & 0 deletions pkg/network/vpnkit/vpnkit_disabled.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
//go:build no_vpnkit
// +build no_vpnkit

package vpnkit

import (
"context"
"errors"

"github.com/rootless-containers/rootlesskit/v3/pkg/api"
"github.com/rootless-containers/rootlesskit/v3/pkg/messages"
"github.com/rootless-containers/rootlesskit/v3/pkg/network"
)

// NewParentDriver returns a stub when built with the no_vpnkit tag.
func NewParentDriver(binary string, mtu int, ifname string, disableHostLoopback bool) network.ParentDriver {
return &disabledParent{}
}

type disabledParent struct{}

func (d *disabledParent) Info(ctx context.Context) (*api.NetworkDriverInfo, error) {
return nil, errors.New("vpnkit network driver disabled by build tag no_vpnkit")
}

func (d *disabledParent) MTU() int { return 0 }

func (d *disabledParent) ConfigureNetwork(childPID int, stateDir, detachedNetNSPath string) (*messages.ParentInitNetworkDriverCompleted, func() error, error) {
return nil, func() error { return nil }, errors.New("vpnkit network driver disabled by build tag no_vpnkit")
}

// NewChildDriver returns a stub when built with the no_vpnkit tag.
func NewChildDriver() network.ChildDriver { return &disabledChild{} }

type disabledChild struct{}

func (d *disabledChild) ChildDriverInfo() (*network.ChildDriverInfo, error) {
return &network.ChildDriverInfo{ConfiguresInterface: false}, nil
}

func (d *disabledChild) ConfigureNetworkChild(netmsg *messages.ParentInitNetworkDriverCompleted, detachedNetNSPath string) (string, error) {
return "", errors.New("vpnkit network driver disabled by build tag no_vpnkit")
}

// Available indicates whether this driver is compiled in (used for generating help text)
const Available = false
3 changes: 3 additions & 0 deletions pkg/port/builtin/builtin.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,3 +12,6 @@ var (
NewParentDriver func(logWriter io.Writer, stateDir string) (port.ParentDriver, error) = parent.NewDriver
NewChildDriver func(logWriter io.Writer) port.ChildDriver = child.NewDriver
)

// Available indicates whether this port driver is compiled in (used for generating help text)
const Available = true
Loading