feat(app-api): add HaRP container (#7493)

Signed-off-by: Oleksander Piskun <oleksandr2088@icloud.com>
Signed-off-by: bigcat88 <bigcat88@icloud.com>
Signed-off-by: Oleksandr Piskun <oleksandr2088@icloud.com>
Signed-off-by: Simon L. <szaimen@e.mail.de>
Co-authored-by: Simon L. <szaimen@e.mail.de>
This commit is contained in:
Oleksandr Piskun
2026-02-18 14:45:44 +02:00
committed by GitHub
parent 92372abfe7
commit 987191ac14
12 changed files with 112 additions and 9 deletions

View File

@@ -10,6 +10,7 @@
"nextcloud-aio-talk",
"nextcloud-aio-notify-push",
"nextcloud-aio-whiteboard",
"nextcloud-aio-harp",
"nextcloud-aio-nextcloud"
],
"display_name": "Apache",
@@ -49,7 +50,8 @@
"APACHE_MAX_SIZE=%APACHE_MAX_SIZE%",
"APACHE_MAX_TIME=%NEXTCLOUD_MAX_TIME%",
"NOTIFY_PUSH_HOST=nextcloud-aio-notify-push",
"WHITEBOARD_HOST=nextcloud-aio-whiteboard"
"WHITEBOARD_HOST=nextcloud-aio-whiteboard",
"HARP_HOST=nextcloud-aio-harp"
],
"volumes": [
{
@@ -172,7 +174,8 @@
"SIGNALING_SECRET",
"FULLTEXTSEARCH_PASSWORD",
"IMAGINARY_SECRET",
"WHITEBOARD_SECRET"
"WHITEBOARD_SECRET",
"HP_SHARED_KEY"
],
"volumes": [
{
@@ -258,7 +261,9 @@
"THIS_IS_AIO=true",
"IMAGINARY_SECRET=%IMAGINARY_SECRET%",
"WHITEBOARD_SECRET=%WHITEBOARD_SECRET%",
"WHITEBOARD_ENABLED=%WHITEBOARD_ENABLED%"
"WHITEBOARD_ENABLED=%WHITEBOARD_ENABLED%",
"HARP_ENABLED=%HARP_ENABLED%",
"HP_SHARED_KEY=%HP_SHARED_KEY%"
],
"stop_grace_period": 600,
"restart": "unless-stopped",
@@ -824,7 +829,7 @@
{
"container_name": "nextcloud-aio-docker-socket-proxy",
"image_tag": "%AIO_CHANNEL%",
"display_name": "Docker Socket Proxy",
"display_name": "Docker Socket Proxy (deprecated)",
"image": "ghcr.io/nextcloud-releases/aio-docker-socket-proxy",
"init": true,
"internal_port": "2375",
@@ -847,6 +852,48 @@
"NET_RAW"
]
},
{
"container_name": "nextcloud-aio-harp",
"image_tag": "release",
"display_name": "HaRP",
"image": "ghcr.io/nextcloud/nextcloud-appapi-harp",
"init": true,
"internal_port": "8780",
"expose": [
"8780"
],
"environment": [
"HP_SHARED_KEY=%HP_SHARED_KEY%",
"NC_INSTANCE_URL=https://%NC_DOMAIN%",
"HP_LOG_LEVEL=warning",
"HP_FRP_DISABLE_TLS=true",
"TZ=%TIMEZONE%"
],
"secrets": [
"HP_SHARED_KEY"
],
"volumes": [
{
"source": "%WATCHTOWER_DOCKER_SOCKET_PATH%",
"destination": "/var/run/docker.sock",
"writeable": false
},
{
"source": "nextcloud_aio_harp",
"destination": "/certs",
"writeable": true
}
],
"restart": "unless-stopped",
"read_only": true,
"tmpfs": [
"/tmp",
"/run/harp"
],
"cap_drop": [
"NET_RAW"
]
},
{
"container_name": "nextcloud-aio-whiteboard",
"image_tag": "%AIO_CHANNEL%",

View File

@@ -121,13 +121,22 @@ document.addEventListener("DOMContentLoaded", function () {
function handleDockerSocketProxyWarning() {
if (document.getElementById("docker-socket-proxy").checked) {
alert('⚠️ Warning! Enabling this container comes with possible Security problems since you are exposing the docker socket and all its privileges to the Nextcloud container. Enable this only if you are sure what you are doing!');
alert('⚠️ The docker socket proxy container is deprecated. Please use the HaRP (High-availability Reverse Proxy for Nextcloud ExApps) instead!');
document.getElementById("docker-socket-proxy").checked = false
}
}
function handleHarpWarning() {
if (document.getElementById("harp").checked) {
alert('⚠️ Warning! Enabling this container comes with possible Security problems since you are exposing the docker socket and all its privileges to the HaRP container. Enable this only if you are sure what you are doing!');
document.getElementById("docker-socket-proxy").checked = false
}
}
// Initialize event listeners for specific behaviors
document.getElementById("talk").addEventListener('change', handleTalkVisibility);
document.getElementById("docker-socket-proxy").addEventListener('change', handleDockerSocketProxyWarning);
document.getElementById("harp").addEventListener('change', handleHarpWarning);
// Initialize talk-recording visibility on page load
handleTalkVisibility(); // Ensure talk-recording is correctly initialized

View File

@@ -0,0 +1,7 @@
document.addEventListener("DOMContentLoaded", function(event) {
// HaRP
let harp = document.getElementById("harp");
if (harp) {
harp.disabled = true;
}
});

View File

@@ -136,6 +136,7 @@ $app->get('/containers', function (Request $request, Response $response, array $
'is_nvidia_gpu_enabled' => $configurationManager->enableNvidiaGpu,
'is_talk_recording_enabled' => $configurationManager->isTalkRecordingEnabled,
'is_docker_socket_proxy_enabled' => $configurationManager->isDockerSocketProxyEnabled,
'is_harp_enabled' => $configurationManager->isHarpEnabled,
'is_whiteboard_enabled' => $configurationManager->isWhiteboardEnabled,
'community_containers' => $configurationManager->listAvailableCommunityContainers(),
'community_containers_enabled' => $configurationManager->aioCommunityContainers,

View File

@@ -91,6 +91,10 @@ readonly class ContainerDefinitionFetcher {
if (!$this->configurationManager->isDockerSocketProxyEnabled) {
continue;
}
} elseif ($entry['container_name'] === 'nextcloud-aio-harp') {
if (!$this->configurationManager->isHarpEnabled) {
continue;
}
} elseif ($entry['container_name'] === 'nextcloud-aio-whiteboard') {
if (!$this->configurationManager->isWhiteboardEnabled) {
continue;
@@ -200,6 +204,10 @@ readonly class ContainerDefinitionFetcher {
if (!$this->configurationManager->isDockerSocketProxyEnabled) {
continue;
}
} elseif ($value === 'nextcloud-aio-harp') {
if (!$this->configurationManager->isHarpEnabled) {
continue;
}
} elseif ($value === 'nextcloud-aio-whiteboard') {
if (!$this->configurationManager->isWhiteboardEnabled) {
continue;

View File

@@ -96,6 +96,7 @@ readonly class ConfigurationController {
$this->configurationManager->isImaginaryEnabled = isset($request->getParsedBody()['imaginary']);
$this->configurationManager->isFulltextsearchEnabled = isset($request->getParsedBody()['fulltextsearch']);
$this->configurationManager->isDockerSocketProxyEnabled = isset($request->getParsedBody()['docker-socket-proxy']);
$this->configurationManager->isHarpEnabled = isset($request->getParsedBody()['harp']);
$this->configurationManager->isWhiteboardEnabled = isset($request->getParsedBody()['whiteboard']);
}

View File

@@ -30,6 +30,11 @@ class ConfigurationManager
set { $this->set('isDockerSocketProxyEnabled', $value); }
}
public bool $isHarpEnabled {
get => $this->get('isHarpEnabled', false);
set { $this->set('isHarpEnabled', $value); }
}
public bool $isWhiteboardEnabled {
// Type-cast because old configs could have 1/0 for this key.
get => (bool) $this->get('isWhiteboardEnabled', true);
@@ -1035,6 +1040,7 @@ class ConfigurationManager
'IMAGINARY_ENABLED' => $this->isImaginaryEnabled ? 'yes' : '',
'FULLTEXTSEARCH_ENABLED' => $this->isFulltextsearchEnabled ? 'yes' : '',
'DOCKER_SOCKET_PROXY_ENABLED' => $this->isDockerSocketProxyEnabled ? 'yes' : '',
'HARP_ENABLED' => $this->isHarpEnabled ? 'yes' : '',
'NEXTCLOUD_UPLOAD_LIMIT' => $this->nextcloudUploadLimit,
'NEXTCLOUD_MEMORY_LIMIT' => $this->nextcloudMemoryLimit,
'NEXTCLOUD_MAX_TIME' => $this->nextcloudMaxTime,

View File

@@ -196,7 +196,21 @@
data-initial-state="false"
{% endif %}
>
<label for="docker-socket-proxy">Docker Socket Proxy (needed for <a target="_blank" href="https://github.com/cloud-py-api/app_api#nextcloud-appapi">Nextcloud App API</a>)</label>
<label for="docker-socket-proxy">Docker Socket Proxy (needed for <a target="_blank" href="https://github.com/cloud-py-api/app_api#nextcloud-appapi">Nextcloud App API</a>) ⚠️ The docker socket proxy container is deprecated. Please use the HaRP (High-availability Reverse Proxy for Nextcloud ExApps) instead!</label>
</p>
<p>
<input
type="checkbox"
id="harp"
name="harp"
{% if is_harp_enabled == true %}
checked="checked"
data-initial-state="true"
{% else %}
data-initial-state="false"
{% endif %}
>
<label for="harp">HaRP (<a target="_blank" href="https://github.com/nextcloud/HaRP">High-availability Reverse Proxy</a> for Nextcloud ExApps)</label>
</p>
<p>
<input
@@ -218,6 +232,7 @@
{% if isAnyRunning == true %}
<script type="text/javascript" src="disable-clamav.js"></script>
<script type="text/javascript" src="disable-docker-socket-proxy.js"></script>
<script type="text/javascript" src="disable-harp.js"></script>
<script type="text/javascript" src="disable-talk.js"></script>
<script type="text/javascript" src="disable-collabora.js?v2"></script>
<script type="text/javascript" src="disable-onlyoffice.js?v2"></script>