diff --git a/cmd/hepto/config.go b/cmd/hepto/config.go
index 15cef956d1e97c72daf34b99fe9bc40c7749bd27..0724439855110f037dbc4350ddba78a679e010ec 100644
--- a/cmd/hepto/config.go
+++ b/cmd/hepto/config.go
@@ -24,6 +24,43 @@ var defaultDNS = []net.IP{
 	{0x26, 0x06, 0x47, 0, 0x47, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x10, 0x01},
 }
 
+// Required capabilities for kubernetes
+var additionalCapabilities = []string{
+	// Necessary for bind mounts by kubelet
+	"CAP_SYS_ADMIN",
+	// Required for raw sockets, including ICMP
+	"CAP_NET_RAW",
+	// Required for unpacking docker images properly
+	"CAP_CHOWN",
+	"CAP_DAC_OVERRIDE",
+	// Required for adjusting oom score by runc
+	"CAP_SYS_RESOURCE",
+	// Required for setting uid and gid by runc
+	"CAP_SETUID",
+	"CAP_SETGID",
+  // Required to read ns/ipc file in downstream runc
+  "CAP_SYS_PTRACE",
+	// Not used explicitely by runc, but currently default in libcontainer
+  // and not customizable
+	"CAP_FOWNER",
+	"CAP_FSETID",
+	"CAP_KILL",
+	"CAP_SETPCAP",
+	"CAP_NET_BIND_SERVICE",
+	"CAP_SYS_CHROOT",
+	"CAP_MKNOD",
+	"CAP_AUDIT_WRITE",
+	"CAP_SETFCAP",
+	"CAP_FSETID",
+}
+
+// Required devices for kubernetes
+var additionalDevices = []string {
+  "/dev/kmsg",
+  "/dev/full",
+  "/dev/tty",
+}
+
 func (c Config) dataPath(subPath string) string {
 	dir := path.Join(c.DataDir, c.Cluster.Name, c.Node.Name, subPath)
 	os.MkdirAll(dir, 0700)
@@ -34,6 +71,8 @@ func (c *Config) Complete() {
 	c.Container.Root = c.dataPath("root")
 	c.Container.Data = c.dataPath("containers")
 	c.Container.Name = c.Node.Name
+  c.Container.Capabilities = additionalCapabilities
+  c.Container.Devices = additionalDevices
 }
 
 var config Config
diff --git a/pkg/selfcontain/config.go b/pkg/selfcontain/config.go
index 212b0b1ecde9b5291da8666eb5e3ce55f5bdd89b..cf7d4c033fe106b337753cce6d0349f4236149f8 100644
--- a/pkg/selfcontain/config.go
+++ b/pkg/selfcontain/config.go
@@ -19,4 +19,8 @@ type Config struct {
 	GW net.IP
 	// List of DNS servers for the container
 	DNS []net.IP
+  // List of non-standard capabilities (required capabilities are always enabled)
+  Capabilities []string
+  // List of non-standard devices
+  Devices []string
 }
diff --git a/pkg/selfcontain/container.go b/pkg/selfcontain/container.go
index 4f5e49d1acbe99371b5e6d50e374a501bb3e8e78..4b70914854ca0f41acb733399e42a59d10eb6e0d 100644
--- a/pkg/selfcontain/container.go
+++ b/pkg/selfcontain/container.go
@@ -51,8 +51,8 @@ func New(config *Config) (*Container, error) {
 	if err != nil {
 		return nil, err
 	}
-	// Use the default container configuration and create the container and process
-	defaults := makeDefaults(config.Name, config.Root, self)
+	// Customize the default container configuration and create the container and process
+	defaults := makeDefaults(config.Name, config.Root, self, config.Capabilities, config.Devices)
 	container, err := factory.Create(config.Name, defaults)
 	if err != nil {
 		return nil, err
diff --git a/pkg/selfcontain/defaults.go b/pkg/selfcontain/defaults.go
index f3cfbe104585f99505be6982622249c33ec506a3..fbab5d1f9cc97fa481b57147855f67287485bc2a 100644
--- a/pkg/selfcontain/defaults.go
+++ b/pkg/selfcontain/defaults.go
@@ -12,107 +12,14 @@ import (
 // as a libcontainer init, which in turn is handled by init()
 const argInit = "selfcontain-arg-libcontainer"
 
-// Restrict access to the bare minimum for hepto to run properly
+// Restrict access to the bare minimum for container to run properly
 // See https://pkg.go.dev/github.com/opencontainers/runc@v1.0.2/libcontainer/specconv
 // for comments about issues with default restrictions
-var allowedDevices = []*devices.Device{
-	{
-		Path:     "/dev/null",
-		FileMode: 0o666,
-		Uid:      0,
-		Gid:      0,
-		Rule: devices.Rule{
-			Type:        devices.CharDevice,
-			Major:       1,
-			Minor:       3,
-			Permissions: "rw",
-			Allow:       true,
-		},
-	},
-	{
-		Path:     "/dev/zero",
-		FileMode: 0o666,
-		Uid:      0,
-		Gid:      0,
-		Rule: devices.Rule{
-			Type:        devices.CharDevice,
-			Major:       1,
-			Minor:       5,
-			Permissions: "rwm",
-			Allow:       true,
-		},
-	},
-	{
-		Path:     "/dev/urandom",
-		FileMode: 0o666,
-		Uid:      0,
-		Gid:      0,
-		Rule: devices.Rule{
-			Type:        devices.CharDevice,
-			Major:       1,
-			Minor:       9,
-			Permissions: "rwm",
-			Allow:       true,
-		},
-	},
-	// Required by kubelet and other kubernetes related downstream
-	// processes
-	{
-		Path:     "/dev/kmsg",
-		FileMode: 0o666,
-		Uid:      0,
-		Gid:      0,
-		Rule: devices.Rule{
-			Type:        devices.CharDevice,
-			Major:       1,
-			Minor:       11,
-			Permissions: "r",
-			Allow:       true,
-		},
-	},
-	// Required by many downstream processes, including anything
-	// like an http client which does tls
-	{
-		Path:     "/dev/random",
-		FileMode: 0o666,
-		Uid:      0,
-		Gid:      0,
-		Rule: devices.Rule{
-			Type:        devices.CharDevice,
-			Major:       1,
-			Minor:       8,
-			Permissions: "r",
-			Allow:       true,
-		},
-	},
-	// Required by downstream runc for mounting
-	{
-		Path:     "/dev/full",
-		FileMode: 0o666,
-		Uid:      0,
-		Gid:      0,
-		Rule: devices.Rule{
-			Type:        devices.CharDevice,
-			Major:       1,
-			Minor:       7,
-			Permissions: "rw",
-			Allow:       true,
-		},
-	},
-	// Required by downstream containers for mounting a tty
-	{
-		Path:     "/dev/tty",
-		FileMode: 0o666,
-		Uid:      0,
-		Gid:      0,
-		Rule: devices.Rule{
-			Type:        devices.CharDevice,
-			Major:       5,
-			Minor:       0,
-			Permissions: "rw",
-			Allow:       true,
-		},
-	},
+var baseDevices = []string{
+  "/dev/null",
+  "/dev/zero",
+  "/dev/urandom",
+  "/dev/random",
 }
 
 // These path will be mounted as a default base inside the container
@@ -165,34 +72,9 @@ var defaultMounts = []*configs.Mount{
 
 // Restrict capabilities to strictly required capabilities
 // All capabilities are inheritable and ambient, so that init execve works properly
-var capabilities = []string{
-	// TODO: remove this and avoid bind mounts
-	"CAP_SYS_ADMIN",
+var baseCapabilities = []string{
 	// Required for later setting up networking
 	"CAP_NET_ADMIN",
-	// Required for raw sockets, including ICMP
-	"CAP_NET_RAW",
-	// Required for unpacking archives and images
-	"CAP_CHOWN",
-	"CAP_DAC_OVERRIDE",
-	// Required for adjusting oom score by runc
-	"CAP_SYS_RESOURCE",
-	// Required for setting uid and gid by runc
-	"CAP_SETUID",
-	"CAP_SETGID",
-	// Added temporarily to accomodate runc capabilities
-	"CAP_FOWNER",
-	"CAP_FSETID",
-	"CAP_KILL",
-	"CAP_SETPCAP",
-	"CAP_NET_BIND_SERVICE",
-	"CAP_NET_RAW",
-	"CAP_SYS_CHROOT",
-	"CAP_MKNOD",
-	"CAP_AUDIT_WRITE",
-	"CAP_SETFCAP",
-	"CAP_FSETID",
-  "CAP_SYS_PTRACE", // To read ns/ipc files
 }
 
 // These networks will be setup as a default base inside the container
@@ -223,7 +105,16 @@ var readOnlyPath = []string{
 }
 
 // Make a container configuration using defaults
-func makeDefaults(name string, root string, self string) *configs.Config {
+func makeDefaults(name string, root string, self string, capabilities []string, deviceNames []string) *configs.Config {
+  allowedDevices := []*devices.Device{}
+  for _, path := range deviceNames {
+    // TODO: do not ignore the error
+    device, _ := devices.DeviceFromPath(path, "rw")
+    allowedDevices = append(allowedDevices, device)
+  }
+  for _, capability := range baseCapabilities {
+    capabilities = append(capabilities, capability)
+  }
 	deviceRules := []*devices.Rule{}
 	for _, device := range allowedDevices {
 		deviceRules = append(deviceRules, &device.Rule)