owned this note
owned this note
Published
Linked with GitHub
# Running Pantavisor container by switching container user to non-root
One of the simpler ways to install a Pantavisor application is by using one of the available docker image. This is done by using the following command
```
pvr app install --from <docker_image> <app_name>
```
For example to install **nginx** as a Pantavisor platform we simply need to do
```
pvr app install --from nginx mynginx
```
Some docker images however don't run as root user and would often need to create or access files as non-root user. Since Pantavisor doesn't manage volumes same way as Docker, this can cause issues when trying to run such a container as being not able to access files or directories.
To overcome this we could use a read-write tmpfs mount within container with **0777** permissions. Thus adding following **tmpfs** entry could help
```
lxc.mount.entry = tmpfs tmp tmpfs rw,nodev,relatime,create=dir,mode=777 0 0
```
If the container needs to create device files replace **nodev** with **dev**.
The above solution doesn't work for persistent storage since for **bind** mount the mode wouldn't change for the backing directory.
## Use case, running mysql/mariadb
Mysql can be installed using the **pvr** tool as follows,
```
pvr app install --from mysql mysql
```
The default configuration created however doesn't work out of the box, the following is the changed configuration,
```text=
lxc.tty.max = 8
lxc.pty.max = 1024
lxc.cgroup.devices.allow = a
lxc.rootfs.path = overlayfs:/volumes/mysql/root.squashfs:/volumes/mysql/lxc-overlay/upper
lxc.init.cmd = docker-entrypoint.sh "mysqld" "--socket=/tmp/mysqld.sock" "--pid-file=/tmp/mysqld.pid"
lxc.environment = PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
lxc.environment = GOSU_VERSION=1.12
lxc.environment = MYSQL_MAJOR=8.0
lxc.environment = MYSQL_VERSION=8.0.20-1debian10
lxc.environment = MYSQL_ROOT_PASSWORD=changeit
lxc.environment = MYSQL_USER=admin
lxc.environment = MYSQL_PASSWORD=admin
lxc.namespace.keep = user net ipc
lxc.mount.auto = proc sys:rw cgroup
lxc.mount.entry = /etc/resolv.conf etc/resolv.conf none bind,rw,create=file 0 0
lxc.mount.entry = tmpfs run tmpfs rw,nodev,relatime,create=dir,mode=755 0 0
lxc.mount.entry = tmpfs tmp tmpfs rw,dev,relatime,create=dir,mode=777 0 0
lxc.mount.entry = /volumes/mysql/docker--var-lib-mysql var/lib/mysql none bind,rw,create=dir 0 0
```
Apart from some of the Mysql environment variables, the following are the important line changes,
```text=
lxc.init.cmd = docker-entrypoint.sh "mysqld" "--socket=/tmp/mysqld.sock" "--pid-file=/tmp/mysqld.pid"
lxc.mount.entry = tmpfs tmp tmpfs rw,dev,relatime,create=dir,mode=777 0 0
```
We create a new tmpfs mount for the container and make it writable by all. The socket and pid-file are both create in this container's tmpfs mount which would otherwise be created in the **/run** mount point of the container but it doesn't work due to
```text=
lxc.mount.entry = tmpfs run tmpfs rw,nodev,relatime,create=dir,mode=755 0 0
```
The **mode=755** and **nodev** prohibits any non-root user access and also doesn't allow for any device files.
## Changes required in run.json
Pantavisor currently creates volume directories which are hard-coded with **0755** permission value. Even if the volume is bind-mounted the volume directory permissions would remain the same.
The container could create a user in the following ways
1. With specific uid, gid.
2. Without any specific uid, gid.
We should be able to provide volume(s) permissions for both cases above. The following additions are proposed for a persistent volume in **run.json** for an application container
```json=
{
"mode" : mode_t (Defaults to 0755 if not present),
"owner" : {
"uid" : <int>, [Defaults to 0 if not present]
"gid" : <int> [Defaults to 0 if not present]
}
}
```
With the above options we could've run.json defined as follows, taking example of mysql again here,
```json=
{
"#spec": "service-manifest-run@1",
"config": "lxc.container.conf",
"name":"mysql",
"storage":{
"docker--var-lib-mysql": {
"persistence": "permanent",
"mode": "0755",
"owner" : {
"gid" : 999,
"uid" : 999
},
},
"docker--var-run-mysqld": {
"persistence": "permanent",
"mode": "0777"
},
"lxc-overlay" : {
"persistence": "boot"
}
},
"type":"lxc",
"root-volume": "root.squashfs",
"volumes":[]
}
```
In **line 10**, in the above **run.json**, we've one of the permanent persistence volume as owned by a specific **uid and gid**. The **uid 999 and gid 999** would be mapped to the container user which requires this volume.
The mount options can be provided in **lxc.container.conf** so those aren't required to be present here.
This would be useful when say a separate storage media is required to store large amount of data for which a sdcard won't suffice.