Merge pull request #3 from linuxserver/nginx

Switch to nginx
This commit is contained in:
Adam 2024-04-08 19:51:20 +01:00 committed by GitHub
commit a60e777995
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
13 changed files with 397 additions and 165 deletions

View File

@ -20,7 +20,8 @@ jobs:
echo "**** External trigger running off of main branch. To disable this trigger, set a Github secret named \"PAUSE_EXTERNAL_TRIGGER_SOCKET_PROXY_MAIN\". ****"
echo "External trigger running off of main branch. To disable this trigger, set a Github secret named \`PAUSE_EXTERNAL_TRIGGER_SOCKET_PROXY_MAIN\`" >> $GITHUB_STEP_SUMMARY
echo "**** Retrieving external version ****"
EXT_RELEASE=$(docker run --rm quay.io/skopeo/stable:v1 inspect docker://docker.io/haproxy:lts-alpine | jq -r '.Env[] | select(startswith("HAPROXY_VERSION")) | split("=")[1]')
EXT_RELEASE=$(curl -sL "http://dl-cdn.alpinelinux.org/alpine/v3.19/main/x86_64/APKINDEX.tar.gz" | tar -xz -C /tmp \
&& awk '/^P:'"nginx"'$/,/V:/' /tmp/APKINDEX | sed -n 2p | sed 's/^V://')
if [ -z "${EXT_RELEASE}" ] || [ "${EXT_RELEASE}" == "null" ]; then
echo "**** Can't retrieve external version, exiting ****"
FAILURE_REASON="Can't retrieve external version for socket-proxy branch main"
@ -73,6 +74,14 @@ jobs:
echo "**** Version ${EXT_RELEASE} already pushed, exiting ****"
echo "Version ${EXT_RELEASE} already pushed, exiting" >> $GITHUB_STEP_SUMMARY
exit 0
elif [[ $(curl -sL "http://dl-cdn.alpinelinux.org/alpine/v3.19/main/aarch64/APKINDEX.tar.gz" | tar -xz -C /tmp && awk '/^P:'"nginx"'$/,/V:/' /tmp/APKINDEX | sed -n 2p | sed 's/^V://') != "${EXT_RELEASE}" ]]; then
echo "**** New version ${EXT_RELEASE} found; but not all arch repos updated yet; exiting ****"
echo "New version ${EXT_RELEASE} found; but not all arch repos updated yet; exiting" >> $GITHUB_STEP_SUMMARY
FAILURE_REASON="New version ${EXT_RELEASE} for socket-proxy tag latest is detected, however not all arch repos are updated yet. Will try again later."
curl -X POST -H "Content-Type: application/json" --data '{"avatar_url": "https://cdn.discordapp.com/avatars/354986384542662657/df91181b3f1cf0ef1592fbe18e0962d7.png","embeds": [{"color": 9802903,
"description": "**Trigger Failed** \n**Reason:** '"${FAILURE_REASON}"' \n"}],
"username": "Github Actions"}' ${{ secrets.DISCORD_WEBHOOK }}
exit 0
elif [ $(curl -s https://ci.linuxserver.io/job/Docker-Pipeline-Builders/job/docker-socket-proxy/job/main/lastBuild/api/json | jq -r '.building') == "true" ]; then
echo "**** New version ${EXT_RELEASE} found; but there already seems to be an active build on Jenkins; exiting ****"
echo "New version ${EXT_RELEASE} found; but there already seems to be an active build on Jenkins; exiting" >> $GITHUB_STEP_SUMMARY

View File

@ -1,12 +1,11 @@
# syntax=docker/dockerfile:1
ARG HAPROXY_VERSION
FROM haproxy:${HAPROXY_VERSION:-lts}-alpine
FROM docker.io/alpine:3.19
# set version label
ARG BUILD_DATE
ARG VERSION
ARG NGINX_VERSION
LABEL build_version="Linuxserver.io version:- ${VERSION} Build-date:- ${BUILD_DATE}"
LABEL maintainer="thespad"
@ -18,13 +17,11 @@ ENV ALLOW_RESTARTS=0 \
COMMIT=0 \
CONFIGS=0 \
CONTAINERS=0 \
DISABLE_IPV6=0 \
DISTRIBUTION=0 \
EVENTS=1 \
EXEC=0 \
IMAGES=0 \
INFO=0 \
LOG_LEVEL=info \
NETWORKS=0 \
NODES=0 \
PING=1 \
@ -40,8 +37,26 @@ ENV ALLOW_RESTARTS=0 \
VERSION=1 \
VOLUMES=0
USER root
# install packages
RUN \
echo "**** install build packages ****" && \
apk add --no-cache \
alpine-release \
bash \
curl \
envsubst && \
if [ -z ${NGINX_VERSION+x} ]; then \
NGINX_VERSION=$(curl -sL "http://dl-cdn.alpinelinux.org/alpine/v3.19/main/x86_64/APKINDEX.tar.gz" | tar -xz -C /tmp \
&& awk '/^P:nginx$/,/V:/' /tmp/APKINDEX | sed -n 2p | sed 's/^V://'); \
fi && \
apk add --no-cache \
nginx==${NGINX_VERSION} && \
rm -f /etc/nginx/conf.d/stream.conf && \
rm -f /etc/nginx/http.d/default.conf
COPY haproxy.cfg /usr/local/etc/haproxy/haproxy.cfg
# add local files
COPY root/ /
EXPOSE 2375
ENTRYPOINT ["/docker-entrypoint.sh"]

View File

@ -1,12 +1,11 @@
# syntax=docker/dockerfile:1
ARG HAPROXY_VERSION
FROM haproxy:${HAPROXY_VERSION:-lts}-alpine
FROM docker.io/alpine:3.19
# set version label
ARG BUILD_DATE
ARG VERSION
ARG NGINX_VERSION
LABEL build_version="Linuxserver.io version:- ${VERSION} Build-date:- ${BUILD_DATE}"
LABEL maintainer="thespad"
@ -18,13 +17,11 @@ ENV ALLOW_RESTARTS=0 \
COMMIT=0 \
CONFIGS=0 \
CONTAINERS=0 \
DISABLE_IPV6=0 \
DISTRIBUTION=0 \
EVENTS=1 \
EXEC=0 \
IMAGES=0 \
INFO=0 \
LOG_LEVEL=info \
NETWORKS=0 \
NODES=0 \
PING=1 \
@ -40,8 +37,26 @@ ENV ALLOW_RESTARTS=0 \
VERSION=1 \
VOLUMES=0
USER root
# install packages
RUN \
echo "**** install build packages ****" && \
apk add --no-cache \
alpine-release \
bash \
curl \
envsubst && \
if [ -z ${NGINX_VERSION+x} ]; then \
NGINX_VERSION=$(curl -sL "http://dl-cdn.alpinelinux.org/alpine/v3.19/main/x86_64/APKINDEX.tar.gz" | tar -xz -C /tmp \
&& awk '/^P:nginx$/,/V:/' /tmp/APKINDEX | sed -n 2p | sed 's/^V://'); \
fi && \
apk add --no-cache \
nginx==${NGINX_VERSION} && \
rm -f /etc/nginx/conf.d/stream.conf && \
rm -f /etc/nginx/http.d/default.conf
COPY haproxy.cfg /usr/local/etc/haproxy/haproxy.cfg
# add local files
COPY root/ /
EXPOSE 2375
ENTRYPOINT ["/docker-entrypoint.sh"]

18
Jenkinsfile vendored
View File

@ -17,7 +17,7 @@ pipeline {
GITLAB_TOKEN=credentials('b6f0f1dd-6952-4cf6-95d1-9c06380283f0')
GITLAB_NAMESPACE=credentials('gitlab-namespace-id')
DOCKERHUB_TOKEN=credentials('docker-hub-ci-pat')
BUILD_VERSION_ARG = 'HAPROXY_VERSION'
BUILD_VERSION_ARG = 'NGINX_VERSION'
LS_USER = 'linuxserver'
LS_REPO = 'docker-socket-proxy'
CONTAINER_NAME = 'socket-proxy'
@ -25,6 +25,9 @@ pipeline {
DEV_DOCKERHUB_IMAGE = 'lsiodev/socket-proxy'
PR_DOCKERHUB_IMAGE = 'lspipepr/socket-proxy'
DIST_IMAGE = 'alpine'
DIST_TAG = '3.19'
DIST_REPO = 'http://dl-cdn.alpinelinux.org/alpine/v3.19/main/'
DIST_REPO_PACKAGES = 'nginx'
MULTIARCH='true'
CI='false'
CI_WEB='false'
@ -110,14 +113,15 @@ pipeline {
/* ########################
External Release Tagging
######################## */
// If this is a custom command to determine version use that command
stage("Set tag custom bash"){
// If this is an alpine repo change for external version determine an md5 from the version string
stage("Set tag Alpine Repo"){
steps{
script{
env.EXT_RELEASE = sh(
script: ''' docker run --rm quay.io/skopeo/stable:v1 inspect docker://docker.io/haproxy:lts-alpine | jq -r '.Env[] | select(startswith("HAPROXY_VERSION")) | split("=")[1]' ''',
script: '''curl -sL "${DIST_REPO}x86_64/APKINDEX.tar.gz" | tar -xz -C /tmp \
&& awk '/^P:'"${DIST_REPO_PACKAGES}"'$/,/V:/' /tmp/APKINDEX | sed -n 2p | sed 's/^V://' ''',
returnStdout: true).trim()
env.RELEASE_LINK = 'custom_command'
env.RELEASE_LINK = 'alpine_repo'
}
}
}
@ -837,11 +841,11 @@ pipeline {
"tagger": {"name": "LinuxServer Jenkins","email": "jenkins@linuxserver.io","date": "'${GITHUB_DATE}'"}}' '''
echo "Pushing New release for Tag"
sh '''#! /bin/bash
echo "Updating to ${EXT_RELEASE_CLEAN}" > releasebody.json
echo "Updating external repo packages to ${EXT_RELEASE_CLEAN}" > releasebody.json
echo '{"tag_name":"'${META_TAG}'",\
"target_commitish": "main",\
"name": "'${META_TAG}'",\
"body": "**LinuxServer Changes:**\\n\\n'${LS_RELEASE_NOTES}'\\n\\n**Remote Changes:**\\n\\n' > start
"body": "**LinuxServer Changes:**\\n\\n'${LS_RELEASE_NOTES}'\\n\\n**Repo Changes:**\\n\\n' > start
printf '","draft": false,"prerelease": false}' >> releasebody.json
paste -d'\\0' start releasebody.json > releasebody.json.done
curl -H "Authorization: token ${GITHUB_TOKEN}" -X POST https://api.github.com/repos/${LS_USER}/${LS_REPO}/releases -d @releasebody.json.done'''

View File

@ -32,9 +32,9 @@ Find us at:
[![Docker Stars](https://img.shields.io/docker/stars/linuxserver/socket-proxy.svg?color=94398d&labelColor=555555&logoColor=ffffff&style=for-the-badge&label=stars&logo=docker)](https://hub.docker.com/r/linuxserver/socket-proxy)
[![Jenkins Build](https://img.shields.io/jenkins/build?labelColor=555555&logoColor=ffffff&style=for-the-badge&jobUrl=https%3A%2F%2Fci.linuxserver.io%2Fjob%2FDocker-Pipeline-Builders%2Fjob%2Fdocker-socket-proxy%2Fjob%2Fmain%2F&logo=jenkins)](https://ci.linuxserver.io/job/Docker-Pipeline-Builders/job/docker-socket-proxy/job/main/)
[Socket-proxy](https://github.com/Tecnativa/docker-socket-proxy) is a security-enhanced proxy for the Docker Socket.
Socket proxy is a security-enhanced proxy for the Docker Socket.
[![socket-proxy](https://raw.githubusercontent.com/linuxserver/docker-templates/master/linuxserver.io/img/docker-logo.png)](https://github.com/Tecnativa/docker-socket-proxy)
![socket-proxy](https://raw.githubusercontent.com/linuxserver/docker-templates/master/linuxserver.io/img/docker-logo.png)
## Supported Architectures
@ -52,9 +52,9 @@ The architectures supported by this image are:
## Application Setup
This container is a fork of [https://github.com/Tecnativa/docker-socket-proxy](https://github.com/Tecnativa/docker-socket-proxy) and as such does not follow our usual container conventions. It *does not* support mods or custom scripts/services, or running as a user other than root (or the docker user in a rootless environment).
This container is based on [https://github.com/Tecnativa/docker-socket-proxy](https://github.com/Tecnativa/docker-socket-proxy) and as such does not follow our usual container conventions. It *does not* support mods or custom scripts/services, or running as a user other than root (or the docker user in a rootless environment).
The container should be run on the same docker network as the service(s) using it. Most containers that would normally connect to a mounted docker.sock can have their endpoint overridden using the `DOCKER_HOST` environment variable if they do not offer the option in their configuration; it should typically be pointed to tcp://socket-proxy:2375.
The container should be run on the same docker network as the service(s) using it. Most containers that would normally connect to a mounted docker.sock can have their endpoint overridden using the `DOCKER_HOST` environment variable if they do not offer the option in their configuration; it should typically be pointed to `tcp://socket-proxy:2375`.
* Never expose this container's port to a public network. It should be treated the same way you would treat the docker socket or TCP endpoint.
* Revoke access to any API section that you consider your service should not need.
@ -74,34 +74,32 @@ services:
image: lscr.io/linuxserver/socket-proxy:latest
container_name: socket-proxy
environment:
- EVENTS=1 #optional
- PING=1 #optional
- VERSION=1 #optional
- ALLOW_START=0 #optional
- ALLOW_STOP=0 #optional
- ALLOW_RESTARTS=0 #optional
- AUTH=0 #optional
- SECRETS=0 #optional
- POST=0 #optional
- BUILD=0 #optional
- COMMIT=0 #optional
- CONFIGS=0 #optional
- CONTAINERS=0 #optional
- ALLOW_START=0 #optional
- ALLOW_STOP=0 #optional
- ALLOW_RESTARTS=0 #optional
- DISTRIBUTION=0 #optional
- EVENTS=1 #optional
- EXEC=0 #optional
- IMAGES=0 #optional
- INFO=0 #optional
- LOG_LEVEL=info #optional
- NETWORKS=0 #optional
- NODES=0 #optional
- PING=1 #optional
- POST=0 #optional
- PLUGINS=0 #optional
- SECRETS=0 #optional
- SERVICES=0 #optional
- SESSION=0 #optional
- SWARM=0 #optional
- SYSTEM=0 #optional
- TASKS=0 #optional
- VERSION=1 #optional
- VOLUMES=0 #optional
- DISABLE_IPV6=0 #optional
volumes:
- /var/run/docker.sock:/var/run/docker.sock:ro
restart: unless-stopped
@ -115,34 +113,32 @@ services:
```bash
docker run -d \
--name=socket-proxy \
-e EVENTS=1 `#optional` \
-e PING=1 `#optional` \
-e VERSION=1 `#optional` \
-e ALLOW_START=0 `#optional` \
-e ALLOW_STOP=0 `#optional` \
-e ALLOW_RESTARTS=0 `#optional` \
-e AUTH=0 `#optional` \
-e SECRETS=0 `#optional` \
-e POST=0 `#optional` \
-e BUILD=0 `#optional` \
-e COMMIT=0 `#optional` \
-e CONFIGS=0 `#optional` \
-e CONTAINERS=0 `#optional` \
-e ALLOW_START=0 `#optional` \
-e ALLOW_STOP=0 `#optional` \
-e ALLOW_RESTARTS=0 `#optional` \
-e DISTRIBUTION=0 `#optional` \
-e EVENTS=1 `#optional` \
-e EXEC=0 `#optional` \
-e IMAGES=0 `#optional` \
-e INFO=0 `#optional` \
-e LOG_LEVEL=info `#optional` \
-e NETWORKS=0 `#optional` \
-e NODES=0 `#optional` \
-e PING=1 `#optional` \
-e POST=0 `#optional` \
-e PLUGINS=0 `#optional` \
-e SECRETS=0 `#optional` \
-e SERVICES=0 `#optional` \
-e SESSION=0 `#optional` \
-e SWARM=0 `#optional` \
-e SYSTEM=0 `#optional` \
-e TASKS=0 `#optional` \
-e VERSION=1 `#optional` \
-e VOLUMES=0 `#optional` \
-e DISABLE_IPV6=0 `#optional` \
-v /var/run/docker.sock:/var/run/docker.sock:ro \
--restart unless-stopped \
--read-only \
@ -156,34 +152,32 @@ Containers are configured using parameters passed at runtime (such as those abov
| Parameter | Function |
| :----: | --- |
| `-e EVENTS=1` | `/events` |
| `-e PING=1` | `/_ping` |
| `-e VERSION=1` | `/version` |
| `-e ALLOW_START=0` | `/containers/id/start` |
| `-e ALLOW_STOP=0` | `/containers/id/stop` |
| `-e ALLOW_RESTARTS=0` | `/containers/id/stop`, `/containers/id/restart`, and `/containers/id/kill` |
| `-e AUTH=0` | `/auth` |
| `-e SECRETS=0` | `/secrets` |
| `-e POST=0` | When set to `0`, only `GET` and `HEAD` operations are allowed, making API access read-only. |
| `-e BUILD=0` | `/build` |
| `-e COMMIT=0` | `/commit` |
| `-e CONFIGS=0` | `/configs` |
| `-e CONTAINERS=0` | `/containers` |
| `-e ALLOW_START=0` | `/containers/id/start` |
| `-e ALLOW_STOP=0` | `/containers/id/stop` |
| `-e ALLOW_RESTARTS=0` | `/containers/id/stop`, `/containers/id/restart`, and `/containers/id/kill` |
| `-e DISTRIBUTION=0` | `/distribution` |
| `-e EVENTS=1` | `/events` |
| `-e EXEC=0` | `/exec` & `/containers/{id}/exec` |
| `-e IMAGES=0` | `/images` |
| `-e INFO=0` | `/info` |
| `-e LOG_LEVEL=info` | Default value is `info`. Possible values are: `debug`, `info`, `notice`, `warning`, `err`, `crit`, `alert`, and `emerg`. |
| `-e NETWORKS=0` | `/networks` |
| `-e NODES=0` | `/nodes` |
| `-e PING=1` | `/_ping` |
| `-e PLUGINS=0` | `/plugins` |
| `-e POST=0` | When set to `0`, only `GET` and `HEAD` operations are allowed, making API access read-only. |
| `-e SECRETS=0` | `/secrets` |
| `-e SERVICES=0` | `/services` |
| `-e SESSION=0` | `/session` |
| `-e SWARM=0` | `/swarm` |
| `-e SYSTEM=0` | `/system` |
| `-e TASKS=0` | `/tasks` |
| `-e VERSION=1` | `/version` |
| `-e VOLUMES=0` | `/volumes` |
| `-e DISABLE_IPV6=0` | Set to `1` to disable IPv6 bindings in scenarios where the host cannot support it. |
| `-v /var/run/docker.sock:ro` | Mount the host docker socket into the container. |
| `--read-only` | Make the container filesystem read-only. |
| `--tmpfs /run` | Mount /run to tmpfs (RAM) to make it writeable. |
@ -307,4 +301,5 @@ Once registered you can define the dockerfile to use with `-f Dockerfile.aarch64
## Versions
* **08.04.24:** - Use nginx due to haproxy's wonky websockets handling.
* **07.04.24:** - Initial Release.

View File

@ -1,72 +0,0 @@
global
log stdout format raw daemon "${LOG_LEVEL}"
maxconn 4000
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
# 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
backend docker-events
server dockersocket $SOCKET_PATH
frontend dockerfrontend
.if streq("$DISABLE_IPV6",1)
bind :2375
.else
bind [::]:2375 v4v6
.endif
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\.]+)?/containers/[a-zA-Z0-9_.-]+/start } { env(ALLOW_START) -m bool }
http-request allow if { path,url_dec -m reg -i ^(/v[\d\.]+)?/containers/[a-zA-Z0-9_.-]+/stop } { env(ALLOW_STOP) -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\.]+)?/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
use_backend docker-events if { path,url_dec -m reg -i ^(/v[\d\.]+)?/events }

View File

@ -2,14 +2,13 @@
# jenkins variables
project_name: docker-socket-proxy
external_type: na
custom_version_command: "docker run --rm quay.io/skopeo/stable:v1 inspect docker://docker.io/haproxy:lts-alpine | jq -r '.Env[] | select(startswith(\"HAPROXY_VERSION\")) | split(\"=\")[1]'"
external_type: alpine_repo
release_type: stable
release_tag: latest
ls_branch: main
build_armhf: false
repo_vars:
- BUILD_VERSION_ARG = 'HAPROXY_VERSION'
- BUILD_VERSION_ARG = 'NGINX_VERSION'
- LS_USER = 'linuxserver'
- LS_REPO = 'docker-socket-proxy'
- CONTAINER_NAME = 'socket-proxy'
@ -17,6 +16,9 @@ repo_vars:
- DEV_DOCKERHUB_IMAGE = 'lsiodev/socket-proxy'
- PR_DOCKERHUB_IMAGE = 'lspipepr/socket-proxy'
- DIST_IMAGE = 'alpine'
- DIST_TAG = '3.19'
- DIST_REPO = 'http://dl-cdn.alpinelinux.org/alpine/v3.19/main/'
- DIST_REPO_PACKAGES = 'nginx'
- MULTIARCH='true'
- CI='false'
- CI_WEB='false'

View File

@ -36,9 +36,9 @@ full_custom_readme: |
[![Docker Stars](https://img.shields.io/docker/stars/linuxserver/socket-proxy.svg?color=94398d&labelColor=555555&logoColor=ffffff&style=for-the-badge&label=stars&logo=docker)](https://hub.docker.com/r/linuxserver/socket-proxy)
[![Jenkins Build](https://img.shields.io/jenkins/build?labelColor=555555&logoColor=ffffff&style=for-the-badge&jobUrl=https%3A%2F%2Fci.linuxserver.io%2Fjob%2FDocker-Pipeline-Builders%2Fjob%2Fdocker-socket-proxy%2Fjob%2Fmain%2F&logo=jenkins)](https://ci.linuxserver.io/job/Docker-Pipeline-Builders/job/docker-socket-proxy/job/main/)
[Socket-proxy](https://github.com/Tecnativa/docker-socket-proxy) is a security-enhanced proxy for the Docker Socket.
Socket proxy is a security-enhanced proxy for the Docker Socket.
[![socket-proxy](https://raw.githubusercontent.com/linuxserver/docker-templates/master/linuxserver.io/img/docker-logo.png)](https://github.com/Tecnativa/docker-socket-proxy)
![socket-proxy](https://raw.githubusercontent.com/linuxserver/docker-templates/master/linuxserver.io/img/docker-logo.png)
## Supported Architectures
@ -56,9 +56,9 @@ full_custom_readme: |
## Application Setup
This container is a fork of [https://github.com/Tecnativa/docker-socket-proxy](https://github.com/Tecnativa/docker-socket-proxy) and as such does not follow our usual container conventions. It *does not* support mods or custom scripts/services, or running as a user other than root (or the docker user in a rootless environment).
This container is based on [https://github.com/Tecnativa/docker-socket-proxy](https://github.com/Tecnativa/docker-socket-proxy) and as such does not follow our usual container conventions. It *does not* support mods or custom scripts/services, or running as a user other than root (or the docker user in a rootless environment).
The container should be run on the same docker network as the service(s) using it. Most containers that would normally connect to a mounted docker.sock can have their endpoint overridden using the `DOCKER_HOST` environment variable if they do not offer the option in their configuration; it should typically be pointed to tcp://socket-proxy:2375.
The container should be run on the same docker network as the service(s) using it. Most containers that would normally connect to a mounted docker.sock can have their endpoint overridden using the `DOCKER_HOST` environment variable if they do not offer the option in their configuration; it should typically be pointed to `tcp://socket-proxy:2375`.
* Never expose this container's port to a public network. It should be treated the same way you would treat the docker socket or TCP endpoint.
* Revoke access to any API section that you consider your service should not need.
@ -78,34 +78,32 @@ full_custom_readme: |
image: lscr.io/linuxserver/socket-proxy:latest
container_name: socket-proxy
environment:
- EVENTS=1 #optional
- PING=1 #optional
- VERSION=1 #optional
- ALLOW_START=0 #optional
- ALLOW_STOP=0 #optional
- ALLOW_RESTARTS=0 #optional
- AUTH=0 #optional
- SECRETS=0 #optional
- POST=0 #optional
- BUILD=0 #optional
- COMMIT=0 #optional
- CONFIGS=0 #optional
- CONTAINERS=0 #optional
- ALLOW_START=0 #optional
- ALLOW_STOP=0 #optional
- ALLOW_RESTARTS=0 #optional
- DISTRIBUTION=0 #optional
- EVENTS=1 #optional
- EXEC=0 #optional
- IMAGES=0 #optional
- INFO=0 #optional
- LOG_LEVEL=info #optional
- NETWORKS=0 #optional
- NODES=0 #optional
- PING=1 #optional
- POST=0 #optional
- PLUGINS=0 #optional
- SECRETS=0 #optional
- SERVICES=0 #optional
- SESSION=0 #optional
- SWARM=0 #optional
- SYSTEM=0 #optional
- TASKS=0 #optional
- VERSION=1 #optional
- VOLUMES=0 #optional
- DISABLE_IPV6=0 #optional
volumes:
- /var/run/docker.sock:/var/run/docker.sock:ro
restart: unless-stopped
@ -119,34 +117,32 @@ full_custom_readme: |
```bash
docker run -d \
--name=socket-proxy \
-e EVENTS=1 `#optional` \
-e PING=1 `#optional` \
-e VERSION=1 `#optional` \
-e ALLOW_START=0 `#optional` \
-e ALLOW_STOP=0 `#optional` \
-e ALLOW_RESTARTS=0 `#optional` \
-e AUTH=0 `#optional` \
-e SECRETS=0 `#optional` \
-e POST=0 `#optional` \
-e BUILD=0 `#optional` \
-e COMMIT=0 `#optional` \
-e CONFIGS=0 `#optional` \
-e CONTAINERS=0 `#optional` \
-e ALLOW_START=0 `#optional` \
-e ALLOW_STOP=0 `#optional` \
-e ALLOW_RESTARTS=0 `#optional` \
-e DISTRIBUTION=0 `#optional` \
-e EVENTS=1 `#optional` \
-e EXEC=0 `#optional` \
-e IMAGES=0 `#optional` \
-e INFO=0 `#optional` \
-e LOG_LEVEL=info `#optional` \
-e NETWORKS=0 `#optional` \
-e NODES=0 `#optional` \
-e PING=1 `#optional` \
-e POST=0 `#optional` \
-e PLUGINS=0 `#optional` \
-e SECRETS=0 `#optional` \
-e SERVICES=0 `#optional` \
-e SESSION=0 `#optional` \
-e SWARM=0 `#optional` \
-e SYSTEM=0 `#optional` \
-e TASKS=0 `#optional` \
-e VERSION=1 `#optional` \
-e VOLUMES=0 `#optional` \
-e DISABLE_IPV6=0 `#optional` \
-v /var/run/docker.sock:/var/run/docker.sock:ro \
--restart unless-stopped \
--read-only \
@ -160,34 +156,32 @@ full_custom_readme: |
| Parameter | Function |
| :----: | --- |
| `-e EVENTS=1` | `/events` |
| `-e PING=1` | `/_ping` |
| `-e VERSION=1` | `/version` |
| `-e ALLOW_START=0` | `/containers/id/start` |
| `-e ALLOW_STOP=0` | `/containers/id/stop` |
| `-e ALLOW_RESTARTS=0` | `/containers/id/stop`, `/containers/id/restart`, and `/containers/id/kill` |
| `-e AUTH=0` | `/auth` |
| `-e SECRETS=0` | `/secrets` |
| `-e POST=0` | When set to `0`, only `GET` and `HEAD` operations are allowed, making API access read-only. |
| `-e BUILD=0` | `/build` |
| `-e COMMIT=0` | `/commit` |
| `-e CONFIGS=0` | `/configs` |
| `-e CONTAINERS=0` | `/containers` |
| `-e ALLOW_START=0` | `/containers/id/start` |
| `-e ALLOW_STOP=0` | `/containers/id/stop` |
| `-e ALLOW_RESTARTS=0` | `/containers/id/stop`, `/containers/id/restart`, and `/containers/id/kill` |
| `-e DISTRIBUTION=0` | `/distribution` |
| `-e EVENTS=1` | `/events` |
| `-e EXEC=0` | `/exec` & `/containers/{id}/exec` |
| `-e IMAGES=0` | `/images` |
| `-e INFO=0` | `/info` |
| `-e LOG_LEVEL=info` | Default value is `info`. Possible values are: `debug`, `info`, `notice`, `warning`, `err`, `crit`, `alert`, and `emerg`. |
| `-e NETWORKS=0` | `/networks` |
| `-e NODES=0` | `/nodes` |
| `-e PING=1` | `/_ping` |
| `-e PLUGINS=0` | `/plugins` |
| `-e POST=0` | When set to `0`, only `GET` and `HEAD` operations are allowed, making API access read-only. |
| `-e SECRETS=0` | `/secrets` |
| `-e SERVICES=0` | `/services` |
| `-e SESSION=0` | `/session` |
| `-e SWARM=0` | `/swarm` |
| `-e SYSTEM=0` | `/system` |
| `-e TASKS=0` | `/tasks` |
| `-e VERSION=1` | `/version` |
| `-e VOLUMES=0` | `/volumes` |
| `-e DISABLE_IPV6=0` | Set to `1` to disable IPv6 bindings in scenarios where the host cannot support it. |
| `-v /var/run/docker.sock:ro` | Mount the host docker socket into the container. |
| `--read-only` | Make the container filesystem read-only. |
| `--tmpfs /run` | Mount /run to tmpfs (RAM) to make it writeable. |
@ -311,6 +305,7 @@ full_custom_readme: |
## Versions
* **08.04.24:** - Use nginx due to haproxy's wonky websockets handling.
* **07.04.24:** - Initial Release.
{%- endraw %}

31
root/docker-entrypoint.sh Executable file
View File

@ -0,0 +1,31 @@
#!/bin/bash
if [[ $POST == 1 ]]; then
envsubst "$(printf '${%s} ' $(bash -c "compgen -A variable"))" < /templates/default_post.template > /run/default.conf
else
envsubst "$(printf '${%s} ' $(bash -c "compgen -A variable"))" < /templates/default_nopost.template > /run/default.conf
fi
echo '
───────────────────────────────────────
██╗ ███████╗██╗ ██████╗
██║ ██╔════╝██║██╔═══██╗
██║ ███████╗██║██║ ██║
██║ ╚════██║██║██║ ██║
███████╗███████║██║╚██████╔╝
╚══════╝╚══════╝╚═╝ ╚═════╝
Brought to you by linuxserver.io
───────────────────────────────────────
───────────────────────────────────────
To support LSIO projects visit:
https://www.linuxserver.io/donate/
───────────────────────────────────────
'
echo "[ls.io-init] done."
exec /usr/sbin/nginx -e stderr

77
root/etc/nginx/nginx.conf Normal file
View File

@ -0,0 +1,77 @@
## Version 2023/04/13 - Changelog: https://github.com/linuxserver/docker-baseimage-alpine-nginx/commits/master/root/defaults/nginx/nginx.conf.sample
### Based on alpine defaults
# https://git.alpinelinux.org/aports/tree/main/nginx/nginx.conf?h=3.19-stable
user root;
# Enables the use of JIT for regular expressions to speed-up their processing.
pcre_jit on;
# Configures default error logger.
error_log stderr;
# Includes files with directives to load dynamic modules.
include /etc/nginx/modules/*.conf;
# Include files with config snippets into the root context.
include /etc/nginx/conf.d/*.conf;
events {
# The maximum number of simultaneous connections that can be opened by
# a worker process.
worker_connections 1024;
}
http {
# Includes mapping of file name extensions to MIME types of responses
# and defines the default type.
include /etc/nginx/mime.types;
default_type application/octet-stream;
# Don't tell nginx version to the clients. Default is 'on'.
server_tokens off;
# Specifies the maximum accepted body size of a client request, as
# indicated by the request header Content-Length. If the stated content
# length is greater than this size, then the client receives the HTTP
# error code 413. Set to 0 to disable. Default is '1m'.
client_max_body_size 0;
client_body_temp_path /tmp;
proxy_temp_path /tmp;
fastcgi_temp_path /tmp;
uwsgi_temp_path /tmp;
scgi_temp_path /tmp;
# Sendfile copies data between one FD and other from within the kernel,
# which is more efficient than read() + write(). Default is off.
sendfile on;
# Causes nginx to attempt to send its HTTP response head in one packet,
# instead of using partial frames. Default is 'off'.
tcp_nopush on;
# all ssl related config moved to ssl.conf
# included in server blocks where listen 443 is defined
# Enable gzipping of responses.
#gzip on;
# Set the Vary HTTP header as defined in the RFC 2616. Default is 'off'.
gzip_vary on;
# Helper variable for proxying websockets.
map $http_upgrade $connection_upgrade {
default upgrade;
'' close;
}
# Sets the path, format, and configuration for a buffered log write.
access_log /dev/stdout;
# Includes virtual hosts configs.
include /run/default.conf;
}
daemon off;
pid /run/nginx.pid;

37
root/etc/nginx/proxy.conf Normal file
View File

@ -0,0 +1,37 @@
## Version 2023/02/09 - Changelog: https://github.com/linuxserver/docker-swag/commits/master/root/defaults/nginx/proxy.conf.sample
# Timeout if the real server is dead
proxy_next_upstream error timeout invalid_header http_500 http_502 http_503;
# Proxy Connection Settings
proxy_buffers 32 4k;
proxy_connect_timeout 240;
proxy_headers_hash_bucket_size 128;
proxy_headers_hash_max_size 1024;
proxy_http_version 1.1;
proxy_read_timeout 240;
proxy_redirect http:// $scheme://;
proxy_send_timeout 240;
# Proxy Cache and Cookie Settings
proxy_cache_bypass $cookie_session;
#proxy_cookie_path / "/; Secure"; # enable at your own risk, may break certain apps
proxy_no_cache $cookie_session;
# Proxy Header Settings
proxy_set_header Connection $connection_upgrade;
proxy_set_header Early-Data $ssl_early_data;
proxy_set_header Host $host;
proxy_set_header Proxy "";
proxy_set_header Upgrade $http_upgrade;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Host $host;
proxy_set_header X-Forwarded-Method $request_method;
proxy_set_header X-Forwarded-Port $server_port;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Forwarded-Server $host;
proxy_set_header X-Forwarded-Ssl on;
proxy_set_header X-Forwarded-Uri $request_uri;
proxy_set_header X-Original-Method $request_method;
proxy_set_header X-Original-URL $scheme://$http_host$request_uri;
proxy_set_header X-Real-IP $remote_addr;

View File

@ -0,0 +1,62 @@
server {
listen 2375 default_server;
listen [::]:2375 default_server;
server_name _;
set $dockersocket $SOCKET_PATH;
set $path_restarts $ALLOW_RESTARTS;
set $path_stop $ALLOW_STOP;
set $path_start $ALLOW_START;
set $path_auth $AUTH;
set $path_build $BUILD;
set $path_commit $COMMIT;
set $path_configs $CONFIGS;
set $path_containers $CONTAINERS;
set $path_distribution $DISTRIBUTION;
set $path_events $EVENTS;
set $path_exec $EXEC;
set $path_images $IMAGES;
set $path_info $INFO;
set $path_networks $NETWORKS;
set $path_nodes $NODES;
set $path_ping $PING;
set $path_plugins $PLUGINS;
set $path_secrets $SECRETS;
set $path_services $SERVICES;
set $path_session $SESSION;
set $path_swarm $SWARM;
set $path_system $SYSTEM;
set $path_tasks $TASKS;
set $path_version $VERSION;
set $path_volumes $VOLUMES;
include /etc/nginx/proxy.conf;
location ~* ^(/v[\d\.]+)?/containers/[a-zA-Z0-9_.-]+/((stop)|(restart)|(kill)) {limit_except GET HEAD {deny all;}if ($path_restarts = 0){return 403;}proxy_pass http://unix:$dockersocket;}
location ~* ^(/v[\d\.]+)?/containers/[a-zA-Z0-9_.-]+/start {limit_except GET HEAD {deny all;}if ($path_start = 0){return 403;}proxy_pass http://unix:$dockersocket;}
location ~* ^(/v[\d\.]+)?/containers/[a-zA-Z0-9_.-]+/stop {limit_except GET HEAD {deny all;}if ($path_stop = 0){return 403;}proxy_pass http://unix:$dockersocket;}
location ~* ^(/v[\d\.]+)?/auth {limit_except GET HEAD {deny all;}if ($path_auth = 0){return 403;}proxy_pass http://unix:$dockersocket;}
location ~* ^(/v[\d\.]+)?/build {limit_except GET HEAD {deny all;}if ($path_build = 0){return 403;}proxy_pass http://unix:$dockersocket;}
location ~* ^(/v[\d\.]+)?/commit {limit_except GET HEAD {deny all;}if ($path_commit = 0){return 403;}proxy_pass http://unix:$dockersocket;}
location ~* ^(/v[\d\.]+)?/configs {limit_except GET HEAD {deny all;}if ($path_configs = 0){return 403;}proxy_pass http://unix:$dockersocket;}
location ~* ^(/v[\d\.]+)?/containers {limit_except GET HEAD {deny all;}if ($path_containers = 0){return 403;}proxy_pass http://unix:$dockersocket;}
location ~* ^(/v[\d\.]+)?/distribution {limit_except GET HEAD {deny all;}if ($path_distribution = 0){return 403;}proxy_pass http://unix:$dockersocket;}
location ~* ^(/v[\d\.]+)?/events {limit_except GET HEAD {deny all;}if ($path_events = 0){return 403;}proxy_pass http://unix:$dockersocket;}
location ~* ^(/v[\d\.]+)?/exec {limit_except GET HEAD {deny all;}if ($path_exec = 0){return 403;}proxy_pass http://unix:$dockersocket;}
location ~* ^(/v[\d\.]+)?/images {limit_except GET HEAD {deny all;}if ($path_images = 0){return 403;}proxy_pass http://unix:$dockersocket;}
location ~* ^(/v[\d\.]+)?/info {limit_except GET HEAD {deny all;}if ($path_info = 0){return 403;}proxy_pass http://unix:$dockersocket;}
location ~* ^(/v[\d\.]+)?/networks {limit_except GET HEAD {deny all;}if ($path_networks = 0){return 403;}proxy_pass http://unix:$dockersocket;}
location ~* ^(/v[\d\.]+)?/nodes {limit_except GET HEAD {deny all;}if ($path_nodes = 0){return 403;}proxy_pass http://unix:$dockersocket;}
location ~* ^(/v[\d\.]+)?/_ping {limit_except GET HEAD {deny all;}if ($path_ping = 0){return 403;}proxy_pass http://unix:$dockersocket;}
location ~* ^(/v[\d\.]+)?/plugins {limit_except GET HEAD {deny all;}if ($path_plugins = 0){return 403;}proxy_pass http://unix:$dockersocket;}
location ~* ^(/v[\d\.]+)?/secrets {limit_except GET HEAD {deny all;}if ($path_secrets = 0){return 403;}proxy_pass http://unix:$dockersocket;}
location ~* ^(/v[\d\.]+)?/services {limit_except GET HEAD {deny all;}if ($path_services = 0){return 403;}proxy_pass http://unix:$dockersocket;}
location ~* ^(/v[\d\.]+)?/session {limit_except GET HEAD {deny all;}if ($path_session = 0){return 403;}proxy_pass http://unix:$dockersocket;}
location ~* ^(/v[\d\.]+)?/swarm {limit_except GET HEAD {deny all;}if ($path_swarm = 0){return 403;}proxy_pass http://unix:$dockersocket;}
location ~* ^(/v[\d\.]+)?/system {limit_except GET HEAD {deny all;}if ($path_system = 0){return 403;}proxy_pass http://unix:$dockersocket;}
location ~* ^(/v[\d\.]+)?/tasks {limit_except GET HEAD {deny all;}if ($path_tasks = 0){return 403;}proxy_pass http://unix:$dockersocket;}
location ~* ^(/v[\d\.]+)?/version {limit_except GET HEAD {deny all;}if ($path_version = 0){return 403;}proxy_pass http://unix:$dockersocket;}
location ~* ^(/v[\d\.]+)?/volumes {limit_except GET HEAD {deny all;}if ($path_volumes = 0){return 403;}proxy_pass http://unix:$dockersocket;}
}

View File

@ -0,0 +1,62 @@
server {
listen 2375 default_server;
listen [::]:2375 default_server;
server_name _;
set $dockersocket $SOCKET_PATH;
set $path_restarts $ALLOW_RESTARTS;
set $path_stop $ALLOW_STOP;
set $path_start $ALLOW_START;
set $path_auth $AUTH;
set $path_build $BUILD;
set $path_commit $COMMIT;
set $path_configs $CONFIGS;
set $path_containers $CONTAINERS;
set $path_distribution $DISTRIBUTION;
set $path_events $EVENTS;
set $path_exec $EXEC;
set $path_images $IMAGES;
set $path_info $INFO;
set $path_networks $NETWORKS;
set $path_nodes $NODES;
set $path_ping $PING;
set $path_plugins $PLUGINS;
set $path_secrets $SECRETS;
set $path_services $SERVICES;
set $path_session $SESSION;
set $path_swarm $SWARM;
set $path_system $SYSTEM;
set $path_tasks $TASKS;
set $path_version $VERSION;
set $path_volumes $VOLUMES;
include /etc/nginx/proxy.conf;
location ~* ^(/v[\d\.]+)?/containers/[a-zA-Z0-9_.-]+/((stop)|(restart)|(kill)) {if ($path_restarts = 0){return 403;}proxy_pass http://unix:$dockersocket;}
location ~* ^(/v[\d\.]+)?/containers/[a-zA-Z0-9_.-]+/start {if ($path_start = 0){return 403;}proxy_pass http://unix:$dockersocket;}
location ~* ^(/v[\d\.]+)?/containers/[a-zA-Z0-9_.-]+/stop {if ($path_stop = 0){return 403;}proxy_pass http://unix:$dockersocket;}
location ~* ^(/v[\d\.]+)?/auth {if ($path_auth = 0){return 403;}proxy_pass http://unix:$dockersocket;}
location ~* ^(/v[\d\.]+)?/build {if ($path_build = 0){return 403;}proxy_pass http://unix:$dockersocket;}
location ~* ^(/v[\d\.]+)?/commit {if ($path_commit = 0){return 403;}proxy_pass http://unix:$dockersocket;}
location ~* ^(/v[\d\.]+)?/configs {if ($path_configs = 0){return 403;}proxy_pass http://unix:$dockersocket;}
location ~* ^(/v[\d\.]+)?/containers {if ($path_containers = 0){return 403;}proxy_pass http://unix:$dockersocket;}
location ~* ^(/v[\d\.]+)?/distribution {if ($path_distribution = 0){return 403;}proxy_pass http://unix:$dockersocket;}
location ~* ^(/v[\d\.]+)?/events {if ($path_events = 0){return 403;}proxy_pass http://unix:$dockersocket;}
location ~* ^(/v[\d\.]+)?/exec {if ($path_exec = 0){return 403;}proxy_pass http://unix:$dockersocket;}
location ~* ^(/v[\d\.]+)?/images {if ($path_images = 0){return 403;}proxy_pass http://unix:$dockersocket;}
location ~* ^(/v[\d\.]+)?/info {if ($path_info = 0){return 403;}proxy_pass http://unix:$dockersocket;}
location ~* ^(/v[\d\.]+)?/networks {if ($path_networks = 0){return 403;}proxy_pass http://unix:$dockersocket;}
location ~* ^(/v[\d\.]+)?/nodes {if ($path_nodes = 0){return 403;}proxy_pass http://unix:$dockersocket;}
location ~* ^(/v[\d\.]+)?/_ping {if ($path_ping = 0){return 403;}proxy_pass http://unix:$dockersocket;}
location ~* ^(/v[\d\.]+)?/plugins {if ($path_plugins = 0){return 403;}proxy_pass http://unix:$dockersocket;}
location ~* ^(/v[\d\.]+)?/secrets {if ($path_secrets = 0){return 403;}proxy_pass http://unix:$dockersocket;}
location ~* ^(/v[\d\.]+)?/services {if ($path_services = 0){return 403;}proxy_pass http://unix:$dockersocket;}
location ~* ^(/v[\d\.]+)?/session {if ($path_session = 0){return 403;}proxy_pass http://unix:$dockersocket;}
location ~* ^(/v[\d\.]+)?/swarm {if ($path_swarm = 0){return 403;}proxy_pass http://unix:$dockersocket;}
location ~* ^(/v[\d\.]+)?/system {if ($path_system = 0){return 403;}proxy_pass http://unix:$dockersocket;}
location ~* ^(/v[\d\.]+)?/tasks {if ($path_tasks = 0){return 403;}proxy_pass http://unix:$dockersocket;}
location ~* ^(/v[\d\.]+)?/version {if ($path_version = 0){return 403;}proxy_pass http://unix:$dockersocket;}
location ~* ^(/v[\d\.]+)?/volumes {if ($path_volumes = 0){return 403;}proxy_pass http://unix:$dockersocket;}
}