mirror of
https://github.com/nextcloud/all-in-one.git
synced 2025-01-26 07:27:58 +08:00
add docker-socket-proxy as option
Signed-off-by: Simon L <szaimen@e.mail.de>
This commit is contained in:
parent
7e5fe5ac8e
commit
6685791427
14 changed files with 236 additions and 7 deletions
9
.github/dependabot.yml
vendored
9
.github/dependabot.yml
vendored
|
@ -165,3 +165,12 @@ updates:
|
|||
labels:
|
||||
- 3. to review
|
||||
- dependencies
|
||||
- package-ecosystem: "docker"
|
||||
directory: "/Containers/docker-socket-proxy"
|
||||
schedule:
|
||||
interval: "daily"
|
||||
time: "12:00"
|
||||
open-pull-requests-limit: 10
|
||||
labels:
|
||||
- 3. to review
|
||||
- dependencies
|
||||
|
|
39
Containers/docker-socket-proxy/Dockerfile
Normal file
39
Containers/docker-socket-proxy/Dockerfile
Normal file
|
@ -0,0 +1,39 @@
|
|||
# Inspiration: https://github.com/Tecnativa/docker-socket-proxy/blob/master/Dockerfile
|
||||
FROM haproxy:2.4.24-alpine3.18
|
||||
|
||||
RUN set -ex; \
|
||||
apk add --no-cache date; \
|
||||
chmod 777 -R /run/; \
|
||||
chmod 777 -R /var/lib/haproxy
|
||||
|
||||
EXPOSE 2375
|
||||
ENV ALLOW_RESTARTS=1 \
|
||||
AUTH=1 \
|
||||
BUILD=0 \
|
||||
COMMIT=0 \
|
||||
CONFIGS=0 \
|
||||
CONTAINERS=1 \
|
||||
DISTRIBUTION=0 \
|
||||
EVENTS=1 \
|
||||
EXEC=0 \
|
||||
GRPC=0 \
|
||||
IMAGES=1 \
|
||||
INFO=1 \
|
||||
LOG_LEVEL=info \
|
||||
NETWORKS=1 \
|
||||
NODES=0 \
|
||||
PING=1 \
|
||||
PLUGINS=0 \
|
||||
POST=0 \
|
||||
SECRETS=0 \
|
||||
SERVICES=1 \
|
||||
SESSION=0 \
|
||||
SOCKET_PATH=/var/run/docker.sock \
|
||||
SWARM=0 \
|
||||
SYSTEM=0 \
|
||||
TASKS=0 \
|
||||
VERSION=1 \
|
||||
VOLUMES=1
|
||||
COPY haproxy.cfg /usr/local/etc/haproxy/haproxy.cfg
|
||||
|
||||
USER haproxy:root
|
72
Containers/docker-socket-proxy/haproxy.cfg
Normal file
72
Containers/docker-socket-proxy/haproxy.cfg
Normal file
|
@ -0,0 +1,72 @@
|
|||
# Inspiration: https://github.com/Tecnativa/docker-socket-proxy/blob/master/haproxy.cfg
|
||||
|
||||
global
|
||||
log stdout format raw daemon "${LOG_LEVEL}"
|
||||
|
||||
pidfile /run/haproxy.pid
|
||||
maxconn 4000
|
||||
|
||||
# Turn on stats unix socket
|
||||
server-state-file /var/lib/haproxy/server-state
|
||||
|
||||
defaults
|
||||
mode http
|
||||
log global
|
||||
option httplog
|
||||
option dontlognull
|
||||
option http-server-close
|
||||
option redispatch
|
||||
retries 3
|
||||
timeout http-request 10s
|
||||
timeout queue 1m
|
||||
timeout connect 10s
|
||||
timeout client 10m
|
||||
timeout server 10m
|
||||
timeout http-keep-alive 10s
|
||||
timeout check 10s
|
||||
maxconn 3000
|
||||
|
||||
# Allow seamless reloads
|
||||
load-server-state-from-file global
|
||||
|
||||
# Use provided example error pages
|
||||
errorfile 400 /usr/local/etc/haproxy/errors/400.http
|
||||
errorfile 403 /usr/local/etc/haproxy/errors/403.http
|
||||
errorfile 408 /usr/local/etc/haproxy/errors/408.http
|
||||
errorfile 500 /usr/local/etc/haproxy/errors/500.http
|
||||
errorfile 502 /usr/local/etc/haproxy/errors/502.http
|
||||
errorfile 503 /usr/local/etc/haproxy/errors/503.http
|
||||
errorfile 504 /usr/local/etc/haproxy/errors/504.http
|
||||
|
||||
backend dockerbackend
|
||||
server dockersocket $SOCKET_PATH
|
||||
|
||||
frontend dockerfrontend
|
||||
bind :2375
|
||||
http-request deny unless METH_GET || { env(POST) -m bool }
|
||||
http-request allow if { path,url_dec -m reg -i ^(/v[\d\.]+)?/containers/[a-zA-Z0-9_.-]+/((stop)|(restart)|(kill)) } { env(ALLOW_RESTARTS) -m bool }
|
||||
http-request allow if { path,url_dec -m reg -i ^(/v[\d\.]+)?/auth } { env(AUTH) -m bool }
|
||||
http-request allow if { path,url_dec -m reg -i ^(/v[\d\.]+)?/build } { env(BUILD) -m bool }
|
||||
http-request allow if { path,url_dec -m reg -i ^(/v[\d\.]+)?/commit } { env(COMMIT) -m bool }
|
||||
http-request allow if { path,url_dec -m reg -i ^(/v[\d\.]+)?/configs } { env(CONFIGS) -m bool }
|
||||
http-request allow if { path,url_dec -m reg -i ^(/v[\d\.]+)?/containers } { env(CONTAINERS) -m bool }
|
||||
http-request allow if { path,url_dec -m reg -i ^(/v[\d\.]+)?/distribution } { env(DISTRIBUTION) -m bool }
|
||||
http-request allow if { path,url_dec -m reg -i ^(/v[\d\.]+)?/events } { env(EVENTS) -m bool }
|
||||
http-request allow if { path,url_dec -m reg -i ^(/v[\d\.]+)?/exec } { env(EXEC) -m bool }
|
||||
http-request allow if { path,url_dec -m reg -i ^(/v[\d\.]+)?/grpc } { env(GRPC) -m bool }
|
||||
http-request allow if { path,url_dec -m reg -i ^(/v[\d\.]+)?/images } { env(IMAGES) -m bool }
|
||||
http-request allow if { path,url_dec -m reg -i ^(/v[\d\.]+)?/info } { env(INFO) -m bool }
|
||||
http-request allow if { path,url_dec -m reg -i ^(/v[\d\.]+)?/networks } { env(NETWORKS) -m bool }
|
||||
http-request allow if { path,url_dec -m reg -i ^(/v[\d\.]+)?/nodes } { env(NODES) -m bool }
|
||||
http-request allow if { path,url_dec -m reg -i ^(/v[\d\.]+)?/_ping } { env(PING) -m bool }
|
||||
http-request allow if { path,url_dec -m reg -i ^(/v[\d\.]+)?/plugins } { env(PLUGINS) -m bool }
|
||||
http-request allow if { path,url_dec -m reg -i ^(/v[\d\.]+)?/secrets } { env(SECRETS) -m bool }
|
||||
http-request allow if { path,url_dec -m reg -i ^(/v[\d\.]+)?/services } { env(SERVICES) -m bool }
|
||||
http-request allow if { path,url_dec -m reg -i ^(/v[\d\.]+)?/session } { env(SESSION) -m bool }
|
||||
http-request allow if { path,url_dec -m reg -i ^(/v[\d\.]+)?/swarm } { env(SWARM) -m bool }
|
||||
http-request allow if { path,url_dec -m reg -i ^(/v[\d\.]+)?/system } { env(SYSTEM) -m bool }
|
||||
http-request allow if { path,url_dec -m reg -i ^(/v[\d\.]+)?/tasks } { env(TASKS) -m bool }
|
||||
http-request allow if { path,url_dec -m reg -i ^(/v[\d\.]+)?/version } { env(VERSION) -m bool }
|
||||
http-request allow if { path,url_dec -m reg -i ^(/v[\d\.]+)?/volumes } { env(VOLUMES) -m bool }
|
||||
http-request deny
|
||||
default_backend dockerbackend
|
|
@ -282,6 +282,8 @@ DATADIR_PERMISSION_CONF
|
|||
touch "$NEXTCLOUD_DATA_DIR/install.failed"
|
||||
exit 1
|
||||
fi
|
||||
# shellcheck disable=SC2016
|
||||
installed_version="$(php -r 'require "/var/www/html/version.php"; echo implode(".", $OC_Version);')"
|
||||
fi
|
||||
php /var/www/html/occ app:disable updatenotification
|
||||
rm -rf /var/www/html/apps/updatenotification
|
||||
|
@ -732,5 +734,22 @@ else
|
|||
fi
|
||||
fi
|
||||
|
||||
# Docker socket proxy
|
||||
if version_greater "$installed_version" "28.0.0.0"; then
|
||||
if [ "$DOCKER_SOCKET_PROXY_ENABLED" = 'yes' ]; then
|
||||
if ! [ -d "/var/www/html/custom_apps/app_ecosystem_v2" ]; then
|
||||
php /var/www/html/occ app:install app_ecosystem_v2
|
||||
elif [ "$(php /var/www/html/occ config:app:get app_ecosystem_v2 enabled)" != "yes" ]; then
|
||||
php /var/www/html/occ app:enable app_ecosystem_v2
|
||||
elif [ "$SKIP_UPDATE" != 1 ]; then
|
||||
php /var/www/html/occ app:update app_ecosystem_v2
|
||||
fi
|
||||
else
|
||||
if [ -d "/var/www/html/custom_apps/app_ecosystem_v2" ]; then
|
||||
php /var/www/html/occ app:remove app_ecosystem_v2
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
# Remove the update skip file always
|
||||
rm -f "$NEXTCLOUD_DATA_DIR"/skip.update
|
||||
|
|
|
@ -20,6 +20,7 @@ OUTPUT="$(echo "$OUTPUT" | jq 'del(.services[].nextcloud_exec_commands)')"
|
|||
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"))')"
|
||||
OUTPUT="$(echo "$OUTPUT" | jq 'del(.services[] | select(.container_name == "nextcloud-aio-docker-socket-proxy"))')"
|
||||
OUTPUT="$(echo "$OUTPUT" | jq '.services[] |= if has("depends_on") then .depends_on |= map({ (.): { "condition": "service_started", "required": false } }) else . end' | jq '.services[] |= if has("depends_on") then .depends_on |= reduce .[] as $item ({}; . + $item) else . end')"
|
||||
|
||||
snap install yq
|
||||
|
@ -66,6 +67,7 @@ do
|
|||
sed -i "s|$variable|\${$sole_variable}|g" containers.yml
|
||||
done
|
||||
|
||||
sed -i '/DOCKER_SOCKET_PROXY_ENABLED/d' sample.conf
|
||||
sed -i 's|_ENABLED=|_ENABLED="no" # Setting this to "yes" (with quotes) enables the option in Nextcloud automatically.|' sample.conf
|
||||
sed -i 's|CLAMAV_ENABLED=no.*|CLAMAV_ENABLED="no" # Setting this to "yes" (with quotes) enables the option in Nextcloud automatically. Note: arm64 has no clamav support|' sample.conf
|
||||
sed -i 's|TALK_ENABLED=no|TALK_ENABLED="yes"|' sample.conf
|
||||
|
|
|
@ -120,7 +120,8 @@
|
|||
"nextcloud-aio-clamav",
|
||||
"nextcloud-aio-fulltextsearch",
|
||||
"nextcloud-aio-talk-recording",
|
||||
"nextcloud-aio-imaginary"
|
||||
"nextcloud-aio-imaginary",
|
||||
"nextcloud-aio-docker-socket-proxy"
|
||||
],
|
||||
"display_name": "Nextcloud",
|
||||
"image": "nextcloud/aio-nextcloud",
|
||||
|
@ -203,7 +204,8 @@
|
|||
"TALK_RECORDING_ENABLED=%TALK_RECORDING_ENABLED%",
|
||||
"RECORDING_SECRET=%RECORDING_SECRET%",
|
||||
"TALK_RECORDING_HOST=nextcloud-aio-talk-recording",
|
||||
"FULLTEXTSEARCH_PASSWORD=%FULLTEXTSEARCH_PASSWORD%"
|
||||
"FULLTEXTSEARCH_PASSWORD=%FULLTEXTSEARCH_PASSWORD%",
|
||||
"DOCKER_SOCKET_PROXY_ENABLED=%DOCKER_SOCKET_PROXY_ENABLED%"
|
||||
],
|
||||
"restart": "unless-stopped",
|
||||
"devices": [
|
||||
|
@ -639,6 +641,29 @@
|
|||
"secrets": [
|
||||
"FULLTEXTSEARCH_PASSWORD"
|
||||
]
|
||||
},
|
||||
{
|
||||
"container_name": "nextcloud-aio-docker-socket-proxy",
|
||||
"display_name": "Docker Socket Proxy",
|
||||
"image": "nextcloud/aio-docker-socket-proxy",
|
||||
"init": true,
|
||||
"internal_port": "2375",
|
||||
"environment": [
|
||||
"TZ=%TIMEZONE%"
|
||||
],
|
||||
"volumes": [
|
||||
{
|
||||
"source": "%WATCHTOWER_DOCKER_SOCKET_PATH%",
|
||||
"destination": "/var/run/docker.sock",
|
||||
"writeable": false
|
||||
}
|
||||
],
|
||||
"restart": "unless-stopped",
|
||||
"read_only": true,
|
||||
"tmpfs": [
|
||||
"/run/",
|
||||
"/var/lib/haproxy"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
4
php/public/disable-docker-socket-proxy.js
Normal file
4
php/public/disable-docker-socket-proxy.js
Normal file
|
@ -0,0 +1,4 @@
|
|||
document.addEventListener("DOMContentLoaded", function(event) {
|
||||
// Docker socket proxy
|
||||
document.getElementById("docker-socket-proxy").disabled = true;
|
||||
});
|
|
@ -121,6 +121,7 @@ $app->get('/containers', function (Request $request, Response $response, array $
|
|||
'nextcloud_memory_limit' => $configurationManager->GetNextcloudMemoryLimit(),
|
||||
'is_dri_device_enabled' => $configurationManager->isDriDeviceEnabled(),
|
||||
'is_talk_recording_enabled' => $configurationManager->isTalkRecordingEnabled(),
|
||||
'is_docker_socket_proxy_enabled' => $configurationManager->isDockerSocketProxyEnabled(),
|
||||
]);
|
||||
})->setName('profile');
|
||||
$app->get('/login', function (Request $request, Response $response, array $args) use ($container) {
|
||||
|
|
|
@ -14,6 +14,13 @@ function handleTalkVisibility() {
|
|||
}
|
||||
}
|
||||
|
||||
function handleDockerSocketProxyWarning() {
|
||||
let dockerSocketProxy = document.getElementById("docker-socket-proxy");
|
||||
if (dockerSocketProxy.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!')
|
||||
}
|
||||
}
|
||||
|
||||
document.addEventListener("DOMContentLoaded", function(event) {
|
||||
// handle submit button for options form
|
||||
let optionsFormSubmit = document.getElementById("options-form-submit");
|
||||
|
@ -52,4 +59,9 @@ document.addEventListener("DOMContentLoaded", function(event) {
|
|||
// Fulltextsearch
|
||||
let fulltextsearch = document.getElementById("fulltextsearch");
|
||||
fulltextsearch.addEventListener('change', makeOptionsFormSubmitVisible);
|
||||
|
||||
// Docker socket proxy
|
||||
let dockerSocketProxy = document.getElementById("docker-socket-proxy");
|
||||
dockerSocketProxy.addEventListener('change', makeOptionsFormSubmitVisible);
|
||||
dockerSocketProxy.addEventListener('change', handleDockerSocketProxyWarning);
|
||||
});
|
||||
|
|
|
@ -93,6 +93,10 @@ class ContainerDefinitionFetcher
|
|||
if (!$this->configurationManager->isFulltextsearchEnabled()) {
|
||||
continue;
|
||||
}
|
||||
} elseif ($entry['container_name'] === 'nextcloud-aio-docker-socket-proxy') {
|
||||
if (!$this->configurationManager->isDockerSocketProxyEnabled()) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
$ports = new ContainerPorts();
|
||||
|
@ -195,6 +199,10 @@ class ContainerDefinitionFetcher
|
|||
if (!$this->configurationManager->isFulltextsearchEnabled()) {
|
||||
continue;
|
||||
}
|
||||
} elseif ($value === 'nextcloud-aio-docker-socket-proxy') {
|
||||
if (!$this->configurationManager->isDockerSocketProxyEnabled()) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
$dependsOn[] = $value;
|
||||
}
|
||||
|
|
|
@ -110,6 +110,11 @@ class ConfigurationController
|
|||
} else {
|
||||
$this->configurationManager->SetFulltextsearchEnabledState(0);
|
||||
}
|
||||
if (isset($request->getParsedBody()['docker-socket-proxy'])) {
|
||||
$this->configurationManager->SetDockerSocketProxyEnabledState(1);
|
||||
} else {
|
||||
$this->configurationManager->SetDockerSocketProxyEnabledState(0);
|
||||
}
|
||||
}
|
||||
|
||||
if (isset($request->getParsedBody()['delete_collabora_dictionaries'])) {
|
||||
|
|
|
@ -149,6 +149,21 @@ class ConfigurationManager
|
|||
}
|
||||
}
|
||||
|
||||
public function isDockerSocketProxyEnabled() : bool {
|
||||
$config = $this->GetConfig();
|
||||
if (isset($config['isDockerSocketProxyEnabled']) && $config['isDockerSocketProxyEnabled'] === 1) {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public function SetDockerSocketProxyEnabledState(int $value) : void {
|
||||
$config = $this->GetConfig();
|
||||
$config['isDockerSocketProxyEnabled'] = $value;
|
||||
$this->WriteConfig($config);
|
||||
}
|
||||
|
||||
public function SetClamavEnabledState(int $value) : void {
|
||||
$config = $this->GetConfig();
|
||||
$config['isClamavEnabled'] = $value;
|
||||
|
|
|
@ -346,6 +346,12 @@ class DockerActionManager
|
|||
} else {
|
||||
$replacements[1] = '';
|
||||
}
|
||||
} elseif ($out[1] === 'DOCKER_SOCKET_PROXY_ENABLED') {
|
||||
if ($this->configurationManager->isDockerSocketProxyEnabled()) {
|
||||
$replacements[1] = 'yes';
|
||||
} else {
|
||||
$replacements[1] = '';
|
||||
}
|
||||
} elseif ($out[1] === 'NEXTCLOUD_UPLOAD_LIMIT') {
|
||||
$replacements[1] = $this->configurationManager->GetNextcloudUploadLimit();
|
||||
} elseif ($out[1] === 'NEXTCLOUD_MEMORY_LIMIT') {
|
||||
|
@ -406,7 +412,11 @@ class DockerActionManager
|
|||
$portWithProtocol = $value->port . '/' . $value->protocol;
|
||||
$exposedPorts[$portWithProtocol] = null;
|
||||
}
|
||||
$requestBody['HostConfig']['NetworkMode'] = 'nextcloud-aio';
|
||||
if ($container->GetIdentifier() !== 'nextcloud-aio-docker-socket-proxy') {
|
||||
$requestBody['HostConfig']['NetworkMode'] = 'nextcloud-aio';
|
||||
} else {
|
||||
$requestBody['HostConfig']['NetworkMode'] = 'nextcloud-aio-docker-socket-proxy-network';
|
||||
}
|
||||
} else {
|
||||
$requestBody['HostConfig']['NetworkMode'] = 'host';
|
||||
}
|
||||
|
@ -763,13 +773,12 @@ class DockerActionManager
|
|||
}
|
||||
}
|
||||
|
||||
private function ConnectContainerIdToNetwork(string $id, string $internalPort) : void
|
||||
private function ConnectContainerIdToNetwork(string $id, string $internalPort, string $network = 'nextcloud-aio') : void
|
||||
{
|
||||
if ($internalPort === 'host') {
|
||||
return;
|
||||
}
|
||||
|
||||
$network = 'nextcloud-aio';
|
||||
$url = $this->BuildApiUrl('networks/create');
|
||||
try {
|
||||
$this->guzzleClient->request(
|
||||
|
@ -777,7 +786,7 @@ class DockerActionManager
|
|||
$url,
|
||||
[
|
||||
'json' => [
|
||||
'Name' => 'nextcloud-aio',
|
||||
'Name' => $network,
|
||||
'CheckDuplicate' => true,
|
||||
'Driver' => 'bridge',
|
||||
'Internal' => false,
|
||||
|
@ -815,13 +824,17 @@ class DockerActionManager
|
|||
public function ConnectMasterContainerToNetwork() : void
|
||||
{
|
||||
$this->ConnectContainerIdToNetwork('nextcloud-aio-mastercontainer', '');
|
||||
$this->ConnectContainerIdToNetwork('nextcloud-aio-mastercontainer', '', 'nextcloud-aio-docker-socket-proxy-network');
|
||||
// Don't disconnect here since it slows down the initial login by a lot. Is getting done during cron.sh instead.
|
||||
// $this->DisconnectContainerFromBridgeNetwork('nextcloud-aio-mastercontainer');
|
||||
}
|
||||
|
||||
public function ConnectContainerToNetwork(Container $container) : void
|
||||
{
|
||||
$this->ConnectContainerIdToNetwork($container->GetIdentifier(), $container->GetInternalPort());
|
||||
$this->ConnectContainerIdToNetwork($container->GetIdentifier(), $container->GetInternalPort());
|
||||
if ($container->GetIdentifier() === 'nextcloud-aio-nextcloud' || $container->GetIdentifier() === 'nextcloud-aio-docker-socket-proxy') {
|
||||
$this->ConnectContainerIdToNetwork($container->GetIdentifier(), $container->GetInternalPort(), 'nextcloud-aio-docker-socket-proxy-network');
|
||||
}
|
||||
}
|
||||
|
||||
public function StopContainer(Container $container) : void {
|
||||
|
|
|
@ -574,6 +574,11 @@
|
|||
{% else %}
|
||||
{#<input type="checkbox" id="onlyoffice" name="onlyoffice"><label for="onlyoffice">OnlyOffice</label><br>#}
|
||||
{% endif %}
|
||||
{% if is_docker_socket_proxy_enabled == true %}
|
||||
<input type="checkbox" id="docker-socket-proxy" name="docker-socket-proxy" checked="checked"><label for="docker-socket-proxy">Docker Socket Proxy (needed for app-ecosystem v2)</label><br><br>
|
||||
{% else %}
|
||||
<input type="checkbox" id="docker-socket-proxy" name="docker-socket-proxy"><label for="docker-socket-proxy">Docker Socket Proxy (needed for app-ecosystem v2)</label><br><br>
|
||||
{% endif %}
|
||||
<input id="options-form-submit" class="button" type="submit" value="Save changes" />
|
||||
<script type="text/javascript" src="options-form-submit.js"></script>
|
||||
</form>
|
||||
|
|
Loading…
Reference in a new issue