From 92b271c3e5f3d6a76889b94c85b89445881e30b0 Mon Sep 17 00:00:00 2001 From: Simon L Date: Tue, 3 Jan 2023 02:01:03 +0100 Subject: [PATCH] allow to add the /dev/dri device into the container and refactor devices Signed-off-by: Simon L --- Containers/nextcloud/start.sh | 12 ++++++++++++ docker-compose.yml | 1 + manual-install/update-yaml.sh | 1 + php/containers-schema.json | 6 ++++++ php/containers.json | 8 +++++++- php/src/Container/Container.php | 8 ++++++++ php/src/ContainerDefinitionFetcher.php | 6 ++++++ php/src/Data/ConfigurationManager.php | 15 +++++++++++++++ php/src/Docker/DockerActionManager.php | 13 ++++++++++++- readme.md | 3 +++ tests/QA/060-environmental-variables.md | 1 + 11 files changed, 72 insertions(+), 2 deletions(-) diff --git a/Containers/nextcloud/start.sh b/Containers/nextcloud/start.sh index 2513f52a..88a7ac10 100644 --- a/Containers/nextcloud/start.sh +++ b/Containers/nextcloud/start.sh @@ -30,6 +30,18 @@ if [ -n "$TRUSTED_CACERTS_DIR" ]; then update-ca-certificates fi +# Check if /dev/dri device is present and apply correct permissions +set -x +if ! [ -f "/dev-dri-group-was-added" ] && [ -n "$(find /dev -maxdepth 1 -mindepth 1 -name dri)" ] && [ -n "$(find /dev/dri -maxdepth 1 -mindepth 1 -name renderD128)" ]; then + # From https://github.com/pulsejet/memories/wiki/QSV-Transcoding#docker-installations + GID="$(stat -c "%g" /dev/dri/renderD128)" + groupadd -g "$GID" render2 || true # sometimes this is needed + GROUP="$(getent group "$GID" | cut -d: -f1)" + usermod -aG "$GROUP" www-data + touch "/dev-dri-group-was-added" +fi +set +x + # Check datadir permissions sudo -u www-data touch "$NEXTCLOUD_DATA_DIR/this-is-a-test-file" &>/dev/null if ! [ -f "$NEXTCLOUD_DATA_DIR/this-is-a-test-file" ]; then diff --git a/docker-compose.yml b/docker-compose.yml index e7e1bc02..a3a2c4c5 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -31,6 +31,7 @@ services: # - NEXTCLOUD_STARTUP_APPS=deck tasks calendar contacts # Allows to modify the Nextcloud apps that are installed on starting AIO the first time. See https://github.com/nextcloud/all-in-one#how-to-change-the-nextcloud-apps-that-are-installed-on-the-first-startup # - NEXTCLOUD_ADDITIONAL_APKS=imagemagick # This allows to add additional packages to the Nextcloud container permanently. Default is imagemagick but can be overwritten by modifying this value. See https://github.com/nextcloud/all-in-one#how-to-add-packets-permanently-to-the-nextcloud-container # - NEXTCLOUD_ADDITIONAL_PHP_EXTENSIONS=imagick # This allows to add additional php extensions to the Nextcloud container permanently. Default is imagick but can be overwritten by modifying this value. See https://github.com/nextcloud/all-in-one#how-to-add-php-extensions-permanently-to-the-nextcloud-container + # - NEXTCLOUD_ENABLE_DRI_DEVICE=true # This allows to enable the /dev/dri device in the Nextcloud container which is needed for hardware-transcoding. See https://github.com/nextcloud/all-in-one#how-to-enable-hardware-transcoding-for-nextcloud # - TALK_PORT=3478 # This allows to adjust the port that the talk container is using. # # Optional: Caddy reverse proxy. See https://github.com/nextcloud/all-in-one/blob/main/reverse-proxy.md diff --git a/manual-install/update-yaml.sh b/manual-install/update-yaml.sh index 27a6529b..ef6dcded 100644 --- a/manual-install/update-yaml.sh +++ b/manual-install/update-yaml.sh @@ -12,6 +12,7 @@ cat /tmp/containers.json OUTPUT="$(cat /tmp/containers.json)" OUTPUT="$(echo "$OUTPUT" | jq 'del(.services[].internal_port)')" OUTPUT="$(echo "$OUTPUT" | jq 'del(.services[].secrets)')" +OUTPUT="$(echo "$OUTPUT" | jq 'del(.services[].devices)')" OUTPUT="$(echo "$OUTPUT" | jq 'del(.services[] | select(.container_name == "nextcloud-aio-watchtower"))')" OUTPUT="$(echo "$OUTPUT" | jq 'del(.services[] | select(.container_name == "nextcloud-aio-domaincheck"))')" OUTPUT="$(echo "$OUTPUT" | jq 'del(.services[] | select(.container_name == "nextcloud-aio-borgbackup"))')" diff --git a/php/containers-schema.json b/php/containers-schema.json index c2e962dc..0667942d 100644 --- a/php/containers-schema.json +++ b/php/containers-schema.json @@ -67,6 +67,12 @@ "type": "string" } }, + "devices": { + "type": "array", + "items": { + "type": "string" + } + }, "volumes": { "type": "array", "items": { diff --git a/php/containers.json b/php/containers.json index 9cb179dc..6f326026 100644 --- a/php/containers.json +++ b/php/containers.json @@ -155,7 +155,10 @@ "ADDITIONAL_APKS=%NEXTCLOUD_ADDITIONAL_APKS%", "ADDITIONAL_PHP_EXTENSIONS=%NEXTCLOUD_ADDITIONAL_PHP_EXTENSIONS%" ], - "restart": "unless-stopped" + "restart": "unless-stopped", + "devices": [ + "/dev/dri" + ] }, { "container_name": "nextcloud-aio-redis", @@ -296,6 +299,9 @@ ], "secrets": [ "BORGBACKUP_PASSWORD" + ], + "devices": [ + "/dev/fuse" ] }, { diff --git a/php/src/Container/Container.php b/php/src/Container/Container.php index 9697911b..c7ff5cf7 100644 --- a/php/src/Container/Container.php +++ b/php/src/Container/Container.php @@ -21,6 +21,8 @@ class Container { private array $dependsOn; /** @var string[] */ private array $secrets; + /** @var string[] */ + private array $devices; private DockerActionManager $dockerActionManager; public function __construct( @@ -35,6 +37,7 @@ class Container { ContainerEnvironmentVariables $containerEnvironmentVariables, array $dependsOn, array $secrets, + array $devices, DockerActionManager $dockerActionManager ) { $this->identifier = $identifier; @@ -48,6 +51,7 @@ class Container { $this->containerEnvironmentVariables = $containerEnvironmentVariables; $this->dependsOn = $dependsOn; $this->secrets = $secrets; + $this->devices = $devices; $this->dockerActionManager = $dockerActionManager; } @@ -75,6 +79,10 @@ class Container { return $this->secrets; } + public function GetDevices() : array { + return $this->devices; + } + public function GetPorts() : ContainerPorts { return $this->ports; } diff --git a/php/src/ContainerDefinitionFetcher.php b/php/src/ContainerDefinitionFetcher.php index ce646ccc..4789bbfa 100644 --- a/php/src/ContainerDefinitionFetcher.php +++ b/php/src/ContainerDefinitionFetcher.php @@ -208,6 +208,11 @@ class ContainerDefinitionFetcher $secrets = $entry['secrets']; } + $devices = []; + if (isset($entry['devices'])) { + $devices = $entry['devices']; + } + $containers[] = new Container( $entry['container_name'], $displayName, @@ -220,6 +225,7 @@ class ContainerDefinitionFetcher $variables, $dependsOn, $secrets, + $devices, $this->container->get(DockerActionManager::class) ); } diff --git a/php/src/Data/ConfigurationManager.php b/php/src/Data/ConfigurationManager.php index 0a265fd9..92b5f6be 100644 --- a/php/src/Data/ConfigurationManager.php +++ b/php/src/Data/ConfigurationManager.php @@ -791,4 +791,19 @@ class ConfigurationManager return true; } } + + private function GetEnabledDriDevice() : string { + $envVariableName = 'NEXTCLOUD_ENABLE_DRI_DEVICE'; + $configName = 'nextcloud_enable_dri_device'; + $defaultValue = ''; + return $this->GetEnvironmentalVariableOrConfig($envVariableName, $configName, $defaultValue); + } + + public function isDriDeviceEnabled() : bool { + if ($this->GetEnabledDriDevice() === 'true') { + return true; + } else { + return false; + } + } } diff --git a/php/src/Docker/DockerActionManager.php b/php/src/Docker/DockerActionManager.php index 61d8aa6e..cc4478e0 100644 --- a/php/src/Docker/DockerActionManager.php +++ b/php/src/Docker/DockerActionManager.php @@ -384,10 +384,21 @@ class DockerActionManager } } + $devices = []; + foreach($container->GetDevices() as $device) { + if ($device === '/dev/dri' && ! $this->configurationManager->isDriDeviceEnabled()) { + continue; + } + $devices[] = ["PathOnHost" => $device, "PathInContainer" => $device, "CgroupPermissions" => "rwm"]; + } + + if (count($devices) > 0) { + $requestBody['HostConfig']['Devices'] = $devices; + } + // Special things for the backup container which should not be exposed in the containers.json if ($container->GetIdentifier() === 'nextcloud-aio-borgbackup') { $requestBody['HostConfig']['CapAdd'] = ["SYS_ADMIN"]; - $requestBody['HostConfig']['Devices'] = [["PathOnHost" => "/dev/fuse", "PathInContainer" => "/dev/fuse", "CgroupPermissions" => "rwm"]]; $requestBody['HostConfig']['SecurityOpt'] = ["apparmor:unconfined"]; // Additional backup directories diff --git a/readme.md b/readme.md index bda06f4b..323a415d 100644 --- a/readme.md +++ b/readme.md @@ -499,6 +499,9 @@ You can do so by adding `-e NEXTCLOUD_ADDITIONAL_PHP_EXTENSIONS="imagick extensi ### What about the pdlib PHP extension for the facerecognition app? The [facerecognition app](https://apps.nextcloud.com/apps/facerecognition) requires the pdlib PHP extension to be installed. Unfortunately, it is not available on PECL nor via PHP core, so there is no way to add this into AIO currently. However you can vote up [this issue](https://github.com/goodspb/pdlib/issues/56) to bring it to PECL and there is the [recognize app](https://apps.nextcloud.com/apps/recognize) that also allows to do face-recognition. +### How to enable hardware-transcoding for Nextcloud? +The [memories app](https://apps.nextcloud.com/apps/memories) allows to enable hardware transcoding for videos. In order to use that, you need to add `-e NEXTCLOUD_ENABLE_DRI_DEVICE=true` to the docker run command of the mastercontainer which will mount the `/dev/dri` device into the container (⚠️ Attention: this only works if the device is present on the host!). Additionally, you need to add required packets to the Nextcloud container by using [this feature](https://github.com/nextcloud/all-in-one#how-to-add-packets-permanently-to-the-nextcloud-container) and adding the required Alpine packages that are documented [here](https://github.com/pulsejet/memories/wiki/QSV-Transcoding). + ### Huge docker logs When your containers run for a few days without a restart, the container logs that you can view from the AIO interface can get really huge. You can limit the loge sizes by enabling logrotate for docker container logs. Feel free to enable this by following those instructions: https://sandro-keil.de/blog/logrotate-for-docker-container/ diff --git a/tests/QA/060-environmental-variables.md b/tests/QA/060-environmental-variables.md index b0fca4f8..0b023122 100644 --- a/tests/QA/060-environmental-variables.md +++ b/tests/QA/060-environmental-variables.md @@ -18,5 +18,6 @@ See https://github.com/nextcloud/all-in-one#how-to-trust-user-defiend-certificat - [ ] When starting the mastercontainer with `-e NEXTCLOUD_STARTUP_APPS=deck`, the resulting Nextcloud should have only installed the deck app and not the other apps that get installed by default. Default are `deck tasks calendar contacts`. - [ ] When starting the mastercontainer with `-e NEXTCLOUD_ADDITIONAL_APKS=zip`, the resulting Nextcloud container should have the zip package installed and not imagemagick. - [ ] When starting the mastercontainer with `-e NEXTCLOUD_ADDITIONAL_PHP_EXTENSIONS=inotify`, the resulting Nextcloud container should have the inotify extension installed and not the imagick extension. +- [ ] When starting the mastercontainer with `-e NEXTCLOUD_ENABLE_DRI_DEVICE=true`, the resulting Nextcloud container should have the /dev/dri device mounted into the container. (Only works if a `/dev/dri` device is present on the host) You can now continue with [070-timezone-change.md](./070-timezone-change.md)