From 5091cafac2111b2e80062c90e0ca0a6f0ec8a716 Mon Sep 17 00:00:00 2001 From: Nick Smith Date: Fri, 25 Aug 2023 00:04:36 -0400 Subject: [PATCH 1/8] Initialize gluetun --- gluetun/CHANGELOG.md | 4 + gluetun/Dockerfile | 139 ++++++++++++++ gluetun/README.md | 53 ++++++ gluetun/apparmor.txt | 66 +++++++ gluetun/build.json | 12 ++ gluetun/config.json | 187 +++++++++++++++++++ gluetun/icon.png | Bin 0 -> 24216 bytes gluetun/logo.png | Bin 0 -> 24216 bytes gluetun/rootfs/etc/cont-init.d/20-folders.sh | 19 ++ gluetun/updater.json | 8 + 10 files changed, 488 insertions(+) create mode 100644 gluetun/CHANGELOG.md create mode 100644 gluetun/Dockerfile create mode 100644 gluetun/README.md create mode 100644 gluetun/apparmor.txt create mode 100644 gluetun/build.json create mode 100644 gluetun/config.json create mode 100644 gluetun/icon.png create mode 100644 gluetun/logo.png create mode 100644 gluetun/rootfs/etc/cont-init.d/20-folders.sh create mode 100644 gluetun/updater.json diff --git a/gluetun/CHANGELOG.md b/gluetun/CHANGELOG.md new file mode 100644 index 00000000000..6adad934fa4 --- /dev/null +++ b/gluetun/CHANGELOG.md @@ -0,0 +1,4 @@ + +## 3.35.0 (24-08-2023) +- Update to latest version from qmcgaw/gluetun + diff --git a/gluetun/Dockerfile b/gluetun/Dockerfile new file mode 100644 index 00000000000..83638275a58 --- /dev/null +++ b/gluetun/Dockerfile @@ -0,0 +1,139 @@ +#============================# +# ALEXBELGIUM'S DOCKERFILE # +#============================# +# _.------. +# _.-` ('>.-`"""-. +# '.--'` _'` _ .--.) +# -' '-.-';` ` +# ' - _.' ``'--. +# '---` .-'""` +# /` +#=== Home Assistant Addon ===# + +################# +# 1 Build Image # +################# + +ARG BUILD_FROM +ARG BUILD_VERSION +FROM ${BUILD_FROM} + +################## +# 2 Modify Image # +################## + +# Set S6 wait time +ENV S6_CMD_WAIT_FOR_SERVICES=1 \ + S6_CMD_WAIT_FOR_SERVICES_MAXTIME=0 \ + S6_SERVICES_GRACETIME=0 + +# Global LSIO modifications +ARG CONFIGLOCATION="/config/addons_config/glueten" +# hadolint ignore=SC2015, SC2013, SC2086 +RUN \ + # Avoid custom-init.d duplications + for file in $(grep -sril 'Potential tampering with custom' /etc/cont-init.d /etc/services.d /etc/s6-overlay/s6-rc.d); do rm -f $file; done \ + \ + # Create new config folder if needed + && for file in $(grep -srl "PUID" /etc/cont-init.d /etc/s6-overlay/s6-rc.d); do sed -i "1a mkdir -p $CONFIGLOCATION" $file; done \ + \ + # Allow UID and GID setting + && for file in $(grep -srl "PUID" /etc/cont-init.d /etc/s6-overlay/s6-rc.d); do sed -i 's/bash/bashio/g' $file && sed -i '1a PUID="$(if bashio::config.has_value "PUID"; then bashio::config "PUID"; else echo "0"; fi)"' $file && sed -i '1a PGID="$(if bashio::config.has_value "PGID"; then bashio::config "PGID"; else echo "0"; fi)"' $file; done \ + \ + # Correct config location + && for file in $(grep -Esril "/config[ '\"/]|/config\$" /etc /defaults); do sed -Ei "s=(/config)+(/| |$|\"|\')=$CONFIGLOCATION\2=g" $file; done \ + \ + # Avoid chmod /config + && for file in /etc/services.d/*/* /etc/cont-init.d/* /etc/s6-overlay/s6-rc.d/*/*;do if [ -f $file ] && [[ ! -z $(awk '/chown.*abc:abc.*\\/,/.*\/config( |$)/{print FILENAME}' $file) ]] ; then sed -i "s|/config$|/data|g" $file; fi ;done \ + \ + # Docker mods addition + #&& if [ -f /docker-mods ]; then sed -i 's|bash|bashio|g' /docker-mods && sed -i "1a if bashio::config.has_value \"DOCKER_MODS\"; then DOCKER_MODS=\$(bashio::config \"DOCKER_MODS\"); fi" /docker-mods; fi \ + \ + # Replace lsiown if not found + && if [ ! -f /usr/bin/lsiown ]; then for file in $(grep -sril "lsiown" /etc); do sed -i "s|lsiown|chown|g" $file; done; fi + +# Changes config directory +ENV XDG_CONFIG_HOME="/config/addons_config" + +################## +# 3 Install apps # +################## + +# Add rootfs +COPY rootfs/ / + +# Corrects permissions for s6 v3 +RUN if [ -d /etc/cont-init.d ]; then chmod -R 755 /etc/cont-init.d; fi + +# Modules +ARG MODULES="00-banner.sh 01-custom_script.sh 00-local_mounts.sh 00-smb_mounts.sh" + +# Automatic modules download +RUN if ! command -v bash >/dev/null 2>/dev/null; then (apt-get update && apt-get install -yqq --no-install-recommends bash || apk add --no-cache bash) >/dev/null; fi \ + && if ! command -v curl >/dev/null 2>/dev/null; then (apt-get update && apt-get install -yqq --no-install-recommends curl || apk add --no-cache curl) >/dev/null; fi \ + && apt-get update && apt-get install -yqq --no-install-recommends ca-certificates || apk add --no-cache ca-certificates >/dev/null || true \ + && mkdir -p /etc/cont-init.d \ + && for scripts in $MODULES; do echo "$scripts" && curl -f -L -s -S "https://raw.githubusercontent.com/alexbelgium/hassio-addons/master/.templates/$scripts" -o /etc/cont-init.d/"$scripts" && [ "$(sed -n '/\/bin/p;q' /etc/cont-init.d/"$scripts")" != "" ] || (echo "script failed to install $scripts" && exit 1); done \ + && chmod -R 755 /etc/cont-init.d + +# Manual apps +ENV PACKAGES="curl" + +# Automatic apps & bashio +RUN if ! command -v bash >/dev/null 2>/dev/null; then (apt-get update && apt-get install -yqq --no-install-recommends bash || apk add --no-cache bash) >/dev/null; fi \ + && if ! command -v curl >/dev/null 2>/dev/null; then (apt-get update && apt-get install -yqq --no-install-recommends curl || apk add --no-cache curl) >/dev/null; fi \ + && curl -f -L -s -S "https://raw.githubusercontent.com/alexbelgium/hassio-addons/master/.templates/automatic_packages.sh" --output /automatic_packages.sh \ + && chmod 777 /automatic_packages.sh \ + && eval /./automatic_packages.sh "${PACKAGES:-}" \ + && rm /automatic_packages.sh + +################ +# 4 Entrypoint # +################ + +#RUN chmod 777 /entrypoint.sh +#WORKDIR / +#ENTRYPOINT [ "/usr/bin/env" ] +#CMD [ "/entrypoint.sh" ] + +############ +# 5 Labels # +############ + +ARG BUILD_ARCH +ARG BUILD_DATE +ARG BUILD_DESCRIPTION +ARG BUILD_NAME +ARG BUILD_REF +ARG BUILD_REPOSITORY +ARG BUILD_VERSION +LABEL \ + io.hass.name="${BUILD_NAME}" \ + io.hass.description="${BUILD_DESCRIPTION}" \ + io.hass.arch="${BUILD_ARCH}" \ + io.hass.type="addon" \ + io.hass.version=${BUILD_VERSION} \ + maintainer="alexbelgium (https://github.com/alexbelgium)" \ + org.opencontainers.image.title="${BUILD_NAME}" \ + org.opencontainers.image.description="${BUILD_DESCRIPTION}" \ + org.opencontainers.image.vendor="Home Assistant Add-ons" \ + org.opencontainers.image.authors="alexbelgium (https://github.com/alexbelgium)" \ + org.opencontainers.image.licenses="MIT" \ + org.opencontainers.image.url="https://github.com/alexbelgium" \ + org.opencontainers.image.source="https://github.com/${BUILD_REPOSITORY}" \ + org.opencontainers.image.documentation="https://github.com/${BUILD_REPOSITORY}/blob/main/README.md" \ + org.opencontainers.image.created=${BUILD_DATE} \ + org.opencontainers.image.revision=${BUILD_REF} \ + org.opencontainers.image.version=${BUILD_VERSION} + +################# +# 6 Healthcheck # +################# + +ENV HEALTH_SERVER_ADDRESS="127.0.0.1:9999" +HEALTHCHECK \ + --interval=5s \ + --retries=5 \ + --start-period=30s \ + --timeout=25s \ + CMD curl --fail "http://${HEALTH_SERVER_ADDRESS}" &>/dev/null || exit 1 diff --git a/gluetun/README.md b/gluetun/README.md new file mode 100644 index 00000000000..091a69db27e --- /dev/null +++ b/gluetun/README.md @@ -0,0 +1,53 @@ +# Home assistant add-on: glueten + +[![Donate][donation-badge]](https://www.buymeacoffee.com/alexbelgium) + +![Version](https://img.shields.io/badge/dynamic/json?label=Version&query=%24.version&url=https%3A%2F%2Fraw.githubusercontent.com%2Falexbelgium%2Fhassio-addons%2Fmaster%2Fglueten%2Fconfig.json) +![Ingress](https://img.shields.io/badge/dynamic/json?label=Ingress&query=%24.ingress&url=https%3A%2F%2Fraw.githubusercontent.com%2Falexbelgium%2Fhassio-addons%2Fmaster%2Fglueten%2Fconfig.json) +![Arch](https://img.shields.io/badge/dynamic/json?color=success&label=Arch&query=%24.arch&url=https%3A%2F%2Fraw.githubusercontent.com%2Falexbelgium%2Fhassio-addons%2Fmaster%2Fglueten%2Fconfig.json) + +[![Codacy Badge](https://app.codacy.com/project/badge/Grade/9c6cf10bdbba45ecb202d7f579b5be0e)](https://www.codacy.com/gh/alexbelgium/hassio-addons/dashboard?utm_source=github.com&utm_medium=referral&utm_content=alexbelgium/hassio-addons&utm_campaign=Badge_Grade) +[![GitHub Super-Linter](https://github.com/alexbelgium/hassio-addons/workflows/Lint%20Code%20Base/badge.svg)](https://github.com/marketplace/actions/super-linter) +[![Builder](https://github.com/alexbelgium/hassio-addons/workflows/Builder/badge.svg)](https://github.com/alexbelgium/hassio-addons/actions/workflows/builder.yaml) + +[donation-badge]: https://img.shields.io/badge/Buy%20me%20a%20coffee-%23d32f2f?logo=buy-me-a-coffee&style=flat&logoColor=white + +_Thanks to everyone having starred my repo! To star it click on the image below, then it will be on top right. Thanks!_ + +[![Stargazers repo roster for @alexbelgium/hassio-addons](https://raw.githubusercontent.com/alexbelgium/hassio-addons/master/.github/stars2.svg)](https://github.com/alexbelgium/hassio-addons/stargazers) + +![downloads evolution](https://raw.githubusercontent.com/alexbelgium/hassio-addons/master/glueten/stats.png) + +## About + +[glueten](https://github.com/qdm12/gluetun) - VPN client in a thin Docker container for multiple VPN providers, written in Go, and using OpenVPN or Wireguard, DNS over TLS, with a few proxy servers built-in. + +This addon is based on the [docker image](https://github.com/qdm12/gluetun) from qdm12. + +## Configuration + +Configurations can be done through the app webUI, except for the following options : + +```yaml +PGID: user +GPID: user +TZ: timezone +localdisks: sda1 #put the hardware name of your drive to mount separated by commas, or its label. ex. sda1, sdb1, MYNAS... +networkdisks: "//SERVER/SHARE" # optional, list of smb servers to mount, separated by commas +cifsusername: "username" # optional, smb username, same for all smb shares +cifspassword: "password" # optional, smb password +``` + +## Installation + +The installation of this add-on is pretty straightforward and not different in +comparison to installing any other Hass.io add-on. + +1. [Add my Hass.io add-ons repository][repository] to your Hass.io instance. +1. Install this add-on. +1. Click the `Save` button to store your configuration. +1. Start the add-on. +1. Check the logs of the add-on to see if everything went well. +1. Carefully configure the add-on to your preferences, see the official documentation for for that. + +[repository]: https://github.com/alexbelgium/hassio-addons diff --git a/gluetun/apparmor.txt b/gluetun/apparmor.txt new file mode 100644 index 00000000000..6937ad211a9 --- /dev/null +++ b/gluetun/apparmor.txt @@ -0,0 +1,66 @@ +#include + +profile gluetun_addon flags=(attach_disconnected,mediate_deleted) { + #include + + capability, + file, + signal, + mount, + umount, + remount, + network udp, + network tcp, + network dgram, + network stream, + network inet, + network inet6, + network netlink raw, + network unix dgram, + + capability setgid, + capability setuid, + capability sys_admin, + capability dac_read_search, + # capability dac_override, + # capability sys_rawio, + +# S6-Overlay + /init ix, + /run/{s6,s6-rc*,service}/** ix, + /package/** ix, + /command/** ix, + /run/{,**} rwk, + /dev/tty rw, + /bin/** ix, + /usr/bin/** ix, + /usr/lib/bashio/** ix, + /etc/s6/** rix, + /run/s6/** rix, + /etc/services.d/** rwix, + /etc/cont-init.d/** rwix, + /etc/cont-finish.d/** rwix, + /init rix, + /var/run/** mrwkl, + /var/run/ mrwkl, + /dev/i2c-1 mrwkl, + # Files required + /dev/fuse mrwkl, + /dev/sda1 mrwkl, + /dev/sdb1 mrwkl, + /dev/nvme0 mrwkl, + /dev/nvme1 mrwkl, + /dev/mmcblk0p1 mrwkl, + /dev/* mrwkl, + /tmp/** mrkwl, + + # Data access + /data/** rw, + + # suppress ptrace denials when using 'docker ps' or using 'ps' inside a container + ptrace (trace,read) peer=docker-default, + + # docker daemon confinement requires explict allow rule for signal + signal (receive) set=(kill,term) peer=/usr/bin/docker, + +} diff --git a/gluetun/build.json b/gluetun/build.json new file mode 100644 index 00000000000..9b6171ca7c6 --- /dev/null +++ b/gluetun/build.json @@ -0,0 +1,12 @@ +{ + "build_from": { + "386": "qmcgaw/gluetun:v3.35", + "amd64": "qmcgaw/gluetun:v3.35", + "armv6": "qmcgaw/gluetun:v3.35", + "armv7": "qmcgaw/gluetun:v3.35", + "arm64": "qmcgaw/gluetun:v3.35" + }, + "codenotary": { + "signer": "alexandrep.github@gmail.com" + } +} diff --git a/gluetun/config.json b/gluetun/config.json new file mode 100644 index 00000000000..1af219a131d --- /dev/null +++ b/gluetun/config.json @@ -0,0 +1,187 @@ +{ + "arch": [ + "386", + "amd64", + "armv6", + "armv7", + "arm64" + ], + "codenotary": "alexandrep.github@gmail.com", + "description": "Lightweight Swiss-knife VPN client to connect to several VPN providers ", + "devices": [ + "/dev/dri", + "/dev/dri/card0", + "/dev/dri/card1", + "/dev/dri/renderD128", + "/dev/vchiq", + "/dev/video10", + "/dev/video11", + "/dev/video12", + "/dev/video13", + "/dev/video14", + "/dev/video15", + "/dev/video16", + "/dev/ttyUSB0", + "/dev/sda", + "/dev/sdb", + "/dev/sdc", + "/dev/sdd", + "/dev/sde", + "/dev/sdf", + "/dev/sdg", + "/dev/nvme", + "/dev/nvme0n1p1", + "/dev/nvme0n1p2", + "/dev/mmcblk", + "/dev/fuse", + "/dev/sda1", + "/dev/sdb1", + "/dev/sdc1", + "/dev/sdd1", + "/dev/sde1", + "/dev/sdf1", + "/dev/sdg1", + "/dev/sda2", + "/dev/sdb2", + "/dev/sdc2", + "/dev/sdd2", + "/dev/sde2", + "/dev/sdf2", + "/dev/sdg2", + "/dev/sda3", + "/dev/sdb3", + "/dev/sda4", + "/dev/sdb4", + "/dev/nvme0", + "/dev/nvme1", + "/dev/nvme2" + ], + "options": { + "VPN_SERVICE_PROVIDER": "private internet access", + "VPN_TYPE": "openvpn", + "OPENVPN_USER": "", + "OPENVPN_PASSWORD": "" + }, + "image": "ghcr.io/alexbelgium/gluetun-{arch}", + "init": false, + "map": [ + "config:rw", + "share:rw", + "media:rw", + "ssl" + ], + "name": "Gluetun VPN client", + "ports": {, + "6789/tcp": 6789, + "7878": 7878, + "8081": 8081, + "8112": 8112 + "8888/tcp": 8888, + "8388/tcp": 8388, + "8388/udp": 8388, + "9091/tcp": 9091, + "9117/tcp": 9117, + "51413/udp": 51413, + "51413/tcp": 51413 + }, + "ports_description": {, + "6789/tcp": "nzbget", + "7878": "radarr", + "8081": "sickchill", + "8112": "Deluge web UI", + "8888/tcp": "HTTP proxy", + "8388/tcp": "Shadowsocks", + "8388/udp": "Shadowsocks", + "9091/tcp": "Transmission", + "9117/tcp": "Jackett", + "51413/tcp": "", + "51413/udp": "" + }, + "privileged": [ + "SYS_ADMIN", + "DAC_READ_SEARCH" + ], + "schema": { + "PGID": "int?", + "PUID": "int?", + "TZ": "str?", + "VPN_SERVICE_PROVIDER": "str", + "VPN_TYPE": "list(openvpn,wireguard)", + "OPENVPN_USER": "str", + "OPENVPN_PASSWORD": "str", + "SERVER_REGIONS": "str?", + "WIREGUARD_PRIVATE_KEY": "str?", + "WIREGUARD_PUBLIC_KEY": "str?", + "WIREGUARD_ADDRESSES": "str?", + "WIREGUARD_IMPLEMENTATION": "list(auto,kernelspace,userspace)?", + "WIREGUARD_MTU": "int(0,65535)?", + "UPDATER_PERIOD": "int?", + "HTTP_CONTROL_SERVER_ADDRESS": "str?", + "HTTP_CONTROL_SERVER_LOG": "list(on,off)?", + "DOT": "list(on,off)?", + "DOT_PROVIDERS": "str?", + "DOT_CACHING": "list(on,off)?", + "DOT_IPV6": "list(on,off)?", + "DOT_PRIVATE_ADDRESS": "str?", + "DOT_VERBOSITY": "int(0,5)?", + "DOT_VERBOSITY_DETAILS": "int(0,4)?", + "DOT_VALIDATION_LOGLEVEL": "int(0,2)?", + "DNS_UPDATE_PERIOD": "str?", + "BLOCK_MALICIOUS": "list(on,off)?", + "BLOCK_SURVEILLANCE": "list(on,off)?", + "BLOCK_ADS": "list(on,off)?", + "UNBLOCK": "str?", + "DNS_ADDRESS": "str?", + "DNS_KEEP_NAMESERVER": "list(on,off)?", + "FIREWALL_VPN_INPUT_PORTS": "port?", + "FIREWALL_INPUT_PORTS": "port?", + "FIREWALL_DEBUG": "list(on,off)?", + "FIREWALL_OUTBOUND_SUBNETS": "str?", + "HEALTH_TARGET_ADDRESS": "str?", + "HEALTH_VPN_DURATION_INITIAL": "str?", + "HEALTH_VPN_DURATION_ADDITION": "str?", + "HEALTH_SUCCESS_WAIT_DURATION": "str?", + "HEALTH_SERVER_ADDRESS": "str?", + "HTTPPROXY": "list(on,off)?", + "HTTPPROXY_LOG": "list(on,off)?", + "HTTPPROXY_LISTENING_ADDRESS": "str?", + "HTTPPROXY_USER": "str?", + "HTTPPROXY_PASSWORD": "str?", + "HTTPPROXY_STEALTH": "list(on,off)?", + "OPENVPN_PROTOCOL": "str?", + "OPENVPN_VERSION": "str?", + "OPENVPN_VERBOSITY": "int(0,6)?", + "OPENVPN_FLAGS": "str?", + "OPENVPN_ROOT": "list(on,off)?", + "OPENVPN_CIPHERS": "str?", + "OPENVPN_AUTH": "str?", + "OPENVPN_MSSFIX": "int(0,9999)?", + "OPENVPN_CERT": "str?", + "OPENVPN_KEY": "str?", + "OPENVPN_ENCRYPTED_KEY": "str?", + "OPENVPN_KEY_PASSPHRASE": "str?", + "OPENVPN_PROCESS_USER": "str?", + "OPENVPN_CUSTOM_CONFIG": "str?", + "PUBLICIP_PERIOD": "str?", + "PUBLICIP_FILE": "str?", + "VERSION_INFORMATION": "list(on,off)?", + "VPN_PORT_FORWARDING": "list(on,off)?", + "VPN_PORT_FORWARDING_PROVIDER": "str?", + "VPN_PORT_FORWARDING_STATUS_FILE": "str?", + "SHADOWSOCKS": "list(on,off)?", + "SHADOWSOCKS_LOG": "list(on,off)?", + "SHADOWSOCKS_LISTENING_ADDRESS": "str?", + "SHADOWSOCKS_PASSWORD": "str?", + "SHADOWSOCKS_CIPHER": "str?", + "UPDATER_MIN_RATIO": "float(0,1)?", + "UPDATER_VPN_SERVICE_PROVIDERS": "str?", + "VPN_ENDPOINT_IP": "str?", + "VPN_ENDPOINT_PORT": "port?", + "VPN_INTERFACE": "str?", + "OPENVPN_CERT": "str?", + "OPENVPN_CERT": "str?" + }, + "slug": "gluetun", + "url": "https://github.com/alexbelgium/hassio-addons/tree/master/gluetun", + "version": "3.35.0" +} diff --git a/gluetun/icon.png b/gluetun/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..f7c822d6ab2a14f220de1cdf81e0efcdcebadbbe GIT binary patch literal 24216 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 z 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 za&

2rjAupmWtXpl;jTTR+Cq;O>d^*Xbn zx2ZGNJ-ys*{}6?X#k50+dU?U-tCZukfv1XxI-pSfyR}L410uH2EOKX?n1|=rU-k&8 zUaYPuf9D#YtwoiU6u&Ix+jLYjZK!^!XKp6P?)Xj>fG!`#te#pyNpouCqrQ;~GBTzG za&b5Fw>-!wFor-jE%R&z;pPLSRHN|jnund##I(F*6oA?W^<>J(BA;&pMsDaGtC#zN zhH@7qRvahA-Jdah`r_0EAo2U>(rJ=f-Q4Io*q*S*+i3xlsDe_1V60LB7$atFxfMk* z?MUjo_gvQ;9wH4+-Wr-Cis#?}Dv>UCP|a5p*O>D0XAR}Rc>1umANjf*jGwq41w611 zP*rLz?ckdEXq)IVK&?|aW=y;~k@@;~5yadurjmK98XYVxsQaS&bBxamuTr56f&q1X zSmx+AO$DY~itcpL^Bs|+g+tu!JC9(u74?jAB8#Qm-0H8hr zFQFlkhE$d@t_dksQ5$brFO$D)Zpi!l;77Fbq`}uOQFMQpI_i;8R+_#%B&!rW9adcm z>?7Tk^mg_siHy?JbA;t4d!f=98fBK4pZDf~$H30R49D;Ffc_J;pK-U&{Jn0$M_H}B zTaio6osnQ&uR(#kKSU-aH9{E(72R_H)VA7Hxtt!h+DWgqF2DHszJ=1B*ilKP_|-4~ zch{W*hO0-<0x5b|R7PuDKDue1Dxuy)(TBxta$ zl3Cya@UemFg`PI{omu9Dz86xxBwx&1tB@$$>RV$EPr2+l;edbJapsQ2m-Uw5(7T9d zP$Cw?7a&Bn-`rLz)1c|3LfBG_7R|&hE=_&;6}-GUY+;BM=mHcY^s&$J^*11_viNgZq?;djt{M^r`?iA z>*b=3I>`6+Aeu+W$=dk=)pVQuPf+gF;z1O2Zep7v1(Ze^IX+sIV} seC5>tca8d|^M82!f1lodE$8x1+;DT!v2Ce49yJe8R@6`^l`{+aFCE6ol>h($ literal 0 HcmV?d00001 diff --git a/gluetun/logo.png b/gluetun/logo.png new file mode 100644 index 0000000000000000000000000000000000000000..f7c822d6ab2a14f220de1cdf81e0efcdcebadbbe GIT binary patch literal 24216 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 z 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 za&

2rjAupmWtXpl;jTTR+Cq;O>d^*Xbn zx2ZGNJ-ys*{}6?X#k50+dU?U-tCZukfv1XxI-pSfyR}L410uH2EOKX?n1|=rU-k&8 zUaYPuf9D#YtwoiU6u&Ix+jLYjZK!^!XKp6P?)Xj>fG!`#te#pyNpouCqrQ;~GBTzG za&b5Fw>-!wFor-jE%R&z;pPLSRHN|jnund##I(F*6oA?W^<>J(BA;&pMsDaGtC#zN zhH@7qRvahA-Jdah`r_0EAo2U>(rJ=f-Q4Io*q*S*+i3xlsDe_1V60LB7$atFxfMk* z?MUjo_gvQ;9wH4+-Wr-Cis#?}Dv>UCP|a5p*O>D0XAR}Rc>1umANjf*jGwq41w611 zP*rLz?ckdEXq)IVK&?|aW=y;~k@@;~5yadurjmK98XYVxsQaS&bBxamuTr56f&q1X zSmx+AO$DY~itcpL^Bs|+g+tu!JC9(u74?jAB8#Qm-0H8hr zFQFlkhE$d@t_dksQ5$brFO$D)Zpi!l;77Fbq`}uOQFMQpI_i;8R+_#%B&!rW9adcm z>?7Tk^mg_siHy?JbA;t4d!f=98fBK4pZDf~$H30R49D;Ffc_J;pK-U&{Jn0$M_H}B zTaio6osnQ&uR(#kKSU-aH9{E(72R_H)VA7Hxtt!h+DWgqF2DHszJ=1B*ilKP_|-4~ zch{W*hO0-<0x5b|R7PuDKDue1Dxuy)(TBxta$ zl3Cya@UemFg`PI{omu9Dz86xxBwx&1tB@$$>RV$EPr2+l;edbJapsQ2m-Uw5(7T9d zP$Cw?7a&Bn-`rLz)1c|3LfBG_7R|&hE=_&;6}-GUY+;BM=mHcY^s&$J^*11_viNgZq?;djt{M^r`?iA z>*b=3I>`6+Aeu+W$=dk=)pVQuPf+gF;z1O2Zep7v1(Ze^IX+sIV} seC5>tca8d|^M82!f1lodE$8x1+;DT!v2Ce49yJe8R@6`^l`{+aFCE6ol>h($ literal 0 HcmV?d00001 diff --git a/gluetun/rootfs/etc/cont-init.d/20-folders.sh b/gluetun/rootfs/etc/cont-init.d/20-folders.sh new file mode 100644 index 00000000000..7dc22eff1e2 --- /dev/null +++ b/gluetun/rootfs/etc/cont-init.d/20-folders.sh @@ -0,0 +1,19 @@ +#!/usr/bin/with-contenv bashio +# shellcheck shell=bash + +slug=gluetun + +if [ ! -d /config/addons_config/$slug ]; then + + if [ -d /config/$slug ]; then + echo "Moving to new location /config/addons_config/$slug" + mkdir -p /config/addons_config/$slug + chmod 777 /config/addons_config/$slug + mv /config/$slug/* /config/addons_config/$slug/ + rm -r /config/$slug + fi + + echo "Creating /config/addons_config/$slug" + mkdir -p /config/addons_config/$slug + chmod 777 /config/addons_config/$slug +fi diff --git a/gluetun/updater.json b/gluetun/updater.json new file mode 100644 index 00000000000..292cf716885 --- /dev/null +++ b/gluetun/updater.json @@ -0,0 +1,8 @@ +{ + "last_update": "24-08-2023", + "repository": "alexbelgium/hassio-addons", + "slug": "gluetun", + "source": "github", + "upstream_repo": "qdm12/gluetun", + "upstream_version": "3.35.0" +} From e7c04b47238240033895534514cdca975b58bd4e Mon Sep 17 00:00:00 2001 From: Nick Smith Date: Fri, 25 Aug 2023 00:13:49 -0400 Subject: [PATCH 2/8] Fixed spacing --- gluetun/config.json | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/gluetun/config.json b/gluetun/config.json index 1af219a131d..099d06b3e15 100644 --- a/gluetun/config.json +++ b/gluetun/config.json @@ -72,17 +72,17 @@ ], "name": "Gluetun VPN client", "ports": {, - "6789/tcp": 6789, - "7878": 7878, - "8081": 8081, - "8112": 8112 + "6789/tcp": 6789, + "7878": 7878, + "8081": 8081, + "8112": 8112 "8888/tcp": 8888, - "8388/tcp": 8388, - "8388/udp": 8388, - "9091/tcp": 9091, - "9117/tcp": 9117, - "51413/udp": 51413, - "51413/tcp": 51413 + "8388/tcp": 8388, + "8388/udp": 8388, + "9091/tcp": 9091, + "9117/tcp": 9117, + "51413/udp": 51413, + "51413/tcp": 51413 }, "ports_description": {, "6789/tcp": "nzbget", @@ -109,12 +109,12 @@ "VPN_TYPE": "list(openvpn,wireguard)", "OPENVPN_USER": "str", "OPENVPN_PASSWORD": "str", - "SERVER_REGIONS": "str?", + "SERVER_REGIONS": "str?", "WIREGUARD_PRIVATE_KEY": "str?", - "WIREGUARD_PUBLIC_KEY": "str?", + "WIREGUARD_PUBLIC_KEY": "str?", "WIREGUARD_ADDRESSES": "str?", - "WIREGUARD_IMPLEMENTATION": "list(auto,kernelspace,userspace)?", - "WIREGUARD_MTU": "int(0,65535)?", + "WIREGUARD_IMPLEMENTATION": "list(auto,kernelspace,userspace)?", + "WIREGUARD_MTU": "int(0,65535)?", "UPDATER_PERIOD": "int?", "HTTP_CONTROL_SERVER_ADDRESS": "str?", "HTTP_CONTROL_SERVER_LOG": "list(on,off)?", From 33494c940ebc6f122ca864931bc59e4695681eee Mon Sep 17 00:00:00 2001 From: Nick Smith Date: Fri, 25 Aug 2023 01:01:33 -0400 Subject: [PATCH 3/8] Fixed incorrect json formatting --- gluetun/build.json | 6 ++---- gluetun/config.json | 12 +++++------- 2 files changed, 7 insertions(+), 11 deletions(-) diff --git a/gluetun/build.json b/gluetun/build.json index 9b6171ca7c6..6103423444d 100644 --- a/gluetun/build.json +++ b/gluetun/build.json @@ -1,10 +1,8 @@ { "build_from": { - "386": "qmcgaw/gluetun:v3.35", + "i386": "qmcgaw/gluetun:v3.35", "amd64": "qmcgaw/gluetun:v3.35", - "armv6": "qmcgaw/gluetun:v3.35", - "armv7": "qmcgaw/gluetun:v3.35", - "arm64": "qmcgaw/gluetun:v3.35" + "armv7": "qmcgaw/gluetun:v3.35" }, "codenotary": { "signer": "alexandrep.github@gmail.com" diff --git a/gluetun/config.json b/gluetun/config.json index 099d06b3e15..3e1591228f0 100644 --- a/gluetun/config.json +++ b/gluetun/config.json @@ -1,10 +1,8 @@ { "arch": [ - "386", + "i386", "amd64", - "armv6", - "armv7", - "arm64" + "armv7" ], "codenotary": "alexandrep.github@gmail.com", "description": "Lightweight Swiss-knife VPN client to connect to several VPN providers ", @@ -71,11 +69,11 @@ "ssl" ], "name": "Gluetun VPN client", - "ports": {, + "ports": { "6789/tcp": 6789, "7878": 7878, "8081": 8081, - "8112": 8112 + "8112": 8112, "8888/tcp": 8888, "8388/tcp": 8388, "8388/udp": 8388, @@ -84,7 +82,7 @@ "51413/udp": 51413, "51413/tcp": 51413 }, - "ports_description": {, + "ports_description": { "6789/tcp": "nzbget", "7878": "radarr", "8081": "sickchill", From c391c715c63422238eb7ef763c91db34362d9ac3 Mon Sep 17 00:00:00 2001 From: Nick Smith Date: Fri, 25 Aug 2023 01:13:10 -0400 Subject: [PATCH 4/8] Improved readme --- gluetun/README.md | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/gluetun/README.md b/gluetun/README.md index 091a69db27e..94354f9dc4c 100644 --- a/gluetun/README.md +++ b/gluetun/README.md @@ -1,4 +1,4 @@ -# Home assistant add-on: glueten +# Home assistant add-on: gluetun [![Donate][donation-badge]](https://www.buymeacoffee.com/alexbelgium) @@ -16,28 +16,26 @@ _Thanks to everyone having starred my repo! To star it click on the image below, [![Stargazers repo roster for @alexbelgium/hassio-addons](https://raw.githubusercontent.com/alexbelgium/hassio-addons/master/.github/stars2.svg)](https://github.com/alexbelgium/hassio-addons/stargazers) -![downloads evolution](https://raw.githubusercontent.com/alexbelgium/hassio-addons/master/glueten/stats.png) +![downloads evolution](https://raw.githubusercontent.com/alexbelgium/hassio-addons/master/gluetun/stats.png) ## About -[glueten](https://github.com/qdm12/gluetun) - VPN client in a thin Docker container for multiple VPN providers, written in Go, and using OpenVPN or Wireguard, DNS over TLS, with a few proxy servers built-in. +[gluetun](https://github.com/qdm12/gluetun) - VPN client in a thin Docker container for multiple VPN providers, written in Go, and using OpenVPN or Wireguard, DNS over TLS, with a few proxy servers built-in. This addon is based on the [docker image](https://github.com/qdm12/gluetun) from qdm12. ## Configuration -Configurations can be done through the app webUI, except for the following options : +Configurations can be done through the app webUI, except for the following options: ```yaml PGID: user GPID: user TZ: timezone -localdisks: sda1 #put the hardware name of your drive to mount separated by commas, or its label. ex. sda1, sdb1, MYNAS... -networkdisks: "//SERVER/SHARE" # optional, list of smb servers to mount, separated by commas -cifsusername: "username" # optional, smb username, same for all smb shares -cifspassword: "password" # optional, smb password ``` +[Additional options gluetun specific](https://github.com/qdm12/gluetun-wiki/tree/main#table-of-contents) + ## Installation The installation of this add-on is pretty straightforward and not different in From d334d0e1ab05c5387cb70cc644377aebb41c8be7 Mon Sep 17 00:00:00 2001 From: Nick Smith Date: Fri, 25 Aug 2023 01:25:29 -0400 Subject: [PATCH 5/8] Removed duplicate OPENVPN_CERT --- gluetun/config.json | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/gluetun/config.json b/gluetun/config.json index 3e1591228f0..dd55c48fd1e 100644 --- a/gluetun/config.json +++ b/gluetun/config.json @@ -175,9 +175,7 @@ "UPDATER_VPN_SERVICE_PROVIDERS": "str?", "VPN_ENDPOINT_IP": "str?", "VPN_ENDPOINT_PORT": "port?", - "VPN_INTERFACE": "str?", - "OPENVPN_CERT": "str?", - "OPENVPN_CERT": "str?" + "VPN_INTERFACE": "str?" }, "slug": "gluetun", "url": "https://github.com/alexbelgium/hassio-addons/tree/master/gluetun", From 329befaa537b0ceb2de8afa8f9461445fcef97a0 Mon Sep 17 00:00:00 2001 From: Nick Smith Date: Fri, 25 Aug 2023 13:15:31 -0400 Subject: [PATCH 6/8] Fixed list using incorrect syntax. Added aarch64 architecture. --- gluetun/build.json | 1 + gluetun/config.json | 47 +++++++++++++++++++++++---------------------- 2 files changed, 25 insertions(+), 23 deletions(-) diff --git a/gluetun/build.json b/gluetun/build.json index 6103423444d..db3c631a337 100644 --- a/gluetun/build.json +++ b/gluetun/build.json @@ -1,6 +1,7 @@ { "build_from": { "i386": "qmcgaw/gluetun:v3.35", + "aarch64": "qmcgaw/gluetun:v3.35", "amd64": "qmcgaw/gluetun:v3.35", "armv7": "qmcgaw/gluetun:v3.35" }, diff --git a/gluetun/config.json b/gluetun/config.json index dd55c48fd1e..f4b2f9d5dc1 100644 --- a/gluetun/config.json +++ b/gluetun/config.json @@ -1,6 +1,7 @@ { "arch": [ "i386", + "aarch64", "amd64", "armv7" ], @@ -83,9 +84,9 @@ "51413/tcp": 51413 }, "ports_description": { - "6789/tcp": "nzbget", - "7878": "radarr", - "8081": "sickchill", + "6789/tcp": "NZBget", + "7878": "Radarr", + "8081": "SickChill", "8112": "Deluge web UI", "8888/tcp": "HTTP proxy", "8388/tcp": "Shadowsocks", @@ -104,53 +105,53 @@ "PUID": "int?", "TZ": "str?", "VPN_SERVICE_PROVIDER": "str", - "VPN_TYPE": "list(openvpn,wireguard)", + "VPN_TYPE": "list(openvpn|wireguard)", "OPENVPN_USER": "str", - "OPENVPN_PASSWORD": "str", + "OPENVPN_PASSWORD": "password", "SERVER_REGIONS": "str?", "WIREGUARD_PRIVATE_KEY": "str?", "WIREGUARD_PUBLIC_KEY": "str?", "WIREGUARD_ADDRESSES": "str?", - "WIREGUARD_IMPLEMENTATION": "list(auto,kernelspace,userspace)?", + "WIREGUARD_IMPLEMENTATION": "list(auto|kernelspace|userspace)?", "WIREGUARD_MTU": "int(0,65535)?", "UPDATER_PERIOD": "int?", "HTTP_CONTROL_SERVER_ADDRESS": "str?", - "HTTP_CONTROL_SERVER_LOG": "list(on,off)?", - "DOT": "list(on,off)?", + "HTTP_CONTROL_SERVER_LOG": "list(on|off)?", + "DOT": "list(on|off)?", "DOT_PROVIDERS": "str?", - "DOT_CACHING": "list(on,off)?", - "DOT_IPV6": "list(on,off)?", + "DOT_CACHING": "list(on|off)?", + "DOT_IPV6": "list(on|off)?", "DOT_PRIVATE_ADDRESS": "str?", "DOT_VERBOSITY": "int(0,5)?", "DOT_VERBOSITY_DETAILS": "int(0,4)?", "DOT_VALIDATION_LOGLEVEL": "int(0,2)?", "DNS_UPDATE_PERIOD": "str?", - "BLOCK_MALICIOUS": "list(on,off)?", - "BLOCK_SURVEILLANCE": "list(on,off)?", - "BLOCK_ADS": "list(on,off)?", + "BLOCK_MALICIOUS": "list(on|off)?", + "BLOCK_SURVEILLANCE": "list(on|off)?", + "BLOCK_ADS": "list(on|off)?", "UNBLOCK": "str?", "DNS_ADDRESS": "str?", - "DNS_KEEP_NAMESERVER": "list(on,off)?", + "DNS_KEEP_NAMESERVER": "list(on|off)?", "FIREWALL_VPN_INPUT_PORTS": "port?", "FIREWALL_INPUT_PORTS": "port?", - "FIREWALL_DEBUG": "list(on,off)?", + "FIREWALL_DEBUG": "list(on|off)?", "FIREWALL_OUTBOUND_SUBNETS": "str?", "HEALTH_TARGET_ADDRESS": "str?", "HEALTH_VPN_DURATION_INITIAL": "str?", "HEALTH_VPN_DURATION_ADDITION": "str?", "HEALTH_SUCCESS_WAIT_DURATION": "str?", "HEALTH_SERVER_ADDRESS": "str?", - "HTTPPROXY": "list(on,off)?", - "HTTPPROXY_LOG": "list(on,off)?", + "HTTPPROXY": "list(on|off)?", + "HTTPPROXY_LOG": "list(on|off)?", "HTTPPROXY_LISTENING_ADDRESS": "str?", "HTTPPROXY_USER": "str?", "HTTPPROXY_PASSWORD": "str?", - "HTTPPROXY_STEALTH": "list(on,off)?", + "HTTPPROXY_STEALTH": "list(on|off)?", "OPENVPN_PROTOCOL": "str?", "OPENVPN_VERSION": "str?", "OPENVPN_VERBOSITY": "int(0,6)?", "OPENVPN_FLAGS": "str?", - "OPENVPN_ROOT": "list(on,off)?", + "OPENVPN_ROOT": "list(on|off)?", "OPENVPN_CIPHERS": "str?", "OPENVPN_AUTH": "str?", "OPENVPN_MSSFIX": "int(0,9999)?", @@ -162,12 +163,12 @@ "OPENVPN_CUSTOM_CONFIG": "str?", "PUBLICIP_PERIOD": "str?", "PUBLICIP_FILE": "str?", - "VERSION_INFORMATION": "list(on,off)?", - "VPN_PORT_FORWARDING": "list(on,off)?", + "VERSION_INFORMATION": "list(on|off)?", + "VPN_PORT_FORWARDING": "list(on|off)?", "VPN_PORT_FORWARDING_PROVIDER": "str?", "VPN_PORT_FORWARDING_STATUS_FILE": "str?", - "SHADOWSOCKS": "list(on,off)?", - "SHADOWSOCKS_LOG": "list(on,off)?", + "SHADOWSOCKS": "list(on|off)?", + "SHADOWSOCKS_LOG": "list(on|off)?", "SHADOWSOCKS_LISTENING_ADDRESS": "str?", "SHADOWSOCKS_PASSWORD": "str?", "SHADOWSOCKS_CIPHER": "str?", From cd9b5d7f237491ec20151feb3066370a85e07e74 Mon Sep 17 00:00:00 2001 From: Nick Smith Date: Sat, 26 Aug 2023 12:45:39 -0400 Subject: [PATCH 7/8] Added translations Added net admin privileged Changed to experimental project Cleaned up dockerfile --- gluetun/Dockerfile | 6 +- gluetun/config.json | 22 +-- gluetun/translations/en.json | 325 +++++++++++++++++++++++++++++++++++ 3 files changed, 334 insertions(+), 19 deletions(-) create mode 100644 gluetun/translations/en.json diff --git a/gluetun/Dockerfile b/gluetun/Dockerfile index 83638275a58..bd766aa76eb 100644 --- a/gluetun/Dockerfile +++ b/gluetun/Dockerfile @@ -63,10 +63,12 @@ ENV XDG_CONFIG_HOME="/config/addons_config" COPY rootfs/ / # Corrects permissions for s6 v3 -RUN if [ -d /etc/cont-init.d ]; then chmod -R 755 /etc/cont-init.d; fi +RUN if [ -d /etc/cont-init.d ]; then chmod -R 755 /etc/cont-init.d; fi && \ + if [ -d /etc/services.d ]; then chmod -R 755 /etc/services.d; fi && \ + if [ -f /entrypoint.sh ]; then chmod 755 /entrypoint.sh; fi # Modules -ARG MODULES="00-banner.sh 01-custom_script.sh 00-local_mounts.sh 00-smb_mounts.sh" +ARG MODULES="00-banner.sh" # Automatic modules download RUN if ! command -v bash >/dev/null 2>/dev/null; then (apt-get update && apt-get install -yqq --no-install-recommends bash || apk add --no-cache bash) >/dev/null; fi \ diff --git a/gluetun/config.json b/gluetun/config.json index f4b2f9d5dc1..1d21c5f887f 100644 --- a/gluetun/config.json +++ b/gluetun/config.json @@ -65,8 +65,6 @@ "init": false, "map": [ "config:rw", - "share:rw", - "media:rw", "ssl" ], "name": "Gluetun VPN client", @@ -83,22 +81,9 @@ "51413/udp": 51413, "51413/tcp": 51413 }, - "ports_description": { - "6789/tcp": "NZBget", - "7878": "Radarr", - "8081": "SickChill", - "8112": "Deluge web UI", - "8888/tcp": "HTTP proxy", - "8388/tcp": "Shadowsocks", - "8388/udp": "Shadowsocks", - "9091/tcp": "Transmission", - "9117/tcp": "Jackett", - "51413/tcp": "", - "51413/udp": "" - }, "privileged": [ "SYS_ADMIN", - "DAC_READ_SEARCH" + "NET_ADMIN" ], "schema": { "PGID": "int?", @@ -111,10 +96,11 @@ "SERVER_REGIONS": "str?", "WIREGUARD_PRIVATE_KEY": "str?", "WIREGUARD_PUBLIC_KEY": "str?", + "WIREGUARD_PRESHARED_KEY": "str?", + "WIREGUARD_ALLOWED_IPS": "str?", "WIREGUARD_ADDRESSES": "str?", "WIREGUARD_IMPLEMENTATION": "list(auto|kernelspace|userspace)?", "WIREGUARD_MTU": "int(0,65535)?", - "UPDATER_PERIOD": "int?", "HTTP_CONTROL_SERVER_ADDRESS": "str?", "HTTP_CONTROL_SERVER_LOG": "list(on|off)?", "DOT": "list(on|off)?", @@ -172,12 +158,14 @@ "SHADOWSOCKS_LISTENING_ADDRESS": "str?", "SHADOWSOCKS_PASSWORD": "str?", "SHADOWSOCKS_CIPHER": "str?", + "UPDATER_PERIOD": "int?", "UPDATER_MIN_RATIO": "float(0,1)?", "UPDATER_VPN_SERVICE_PROVIDERS": "str?", "VPN_ENDPOINT_IP": "str?", "VPN_ENDPOINT_PORT": "port?", "VPN_INTERFACE": "str?" }, + "stage": "experimental", "slug": "gluetun", "url": "https://github.com/alexbelgium/hassio-addons/tree/master/gluetun", "version": "3.35.0" diff --git a/gluetun/translations/en.json b/gluetun/translations/en.json new file mode 100644 index 00000000000..969eadeff8f --- /dev/null +++ b/gluetun/translations/en.json @@ -0,0 +1,325 @@ +{ + "configuration": { + "HTTP_CONTROL_SERVER_ADDRESS": { + "name": "HTTP control server address", + "description": "Listening address for the HTTP control server." + }, + "HTTP_CONTROL_SERVER_LOG": { + "name": "HTTP control server log", + "description": "Enable logging of HTTP requests" + }, + "DOT": { + "name": "DOT", + "description": "Activate DNS over TLS with Unbound" + }, + "DOT_PROVIDERS": { + "name": "DOT providers", + "description": "Comma delimited list of DNS over TLS providers" + }, + "DOT_CACHING": { + "name": "DOT caching", + "description": "Unbound caching" + }, + "DOT_IPV6": { + "name": "DOT IPV6", + "description": "DNS IPv6 resolution" + }, + "DOT_PRIVATE_ADDRESS": { + "name": "DOT private address", + "description": "Comma separated list of CIDRs or single IP addresses Unbound won't resolve to. Note that the default setting prevents DNS rebinding" + }, + "DOT_VERBOSITY": { + "name": "DOT verbosity", + "description": "Unbound verbosity level" + }, + "DOT_VERBOSITY_DETAILS": { + "name": "DOT verbosity details", + "description": "Unbound details verbosity level" + }, + "DOT_VALIDATION_LOGLEVEL": { + "name": "DOT validation log level", + "description": "Unbound validation log level" + }, + "DNS_UPDATE_PERIOD": { + "name": "DNS update period", + "description": "Period to update block lists and cryptographic files and restart Unbound. Set to 0 to deactivate updates" + }, + "BLOCK_MALICIOUS": { + "name": "Block malicious", + "description": "Block malicious hostnames and IPs with Unbound" + }, + "BLOCK_SURVEILLANCE": { + "name": "Block surveillance", + "description": "Block surveillance hostnames and IPs with Unbound" + }, + "BLOCK_ADS": { + "name": "Block ads", + "description": "Block ads hostnames and IPs with Unbound" + }, + "UNBLOCK": { + "name": "Unblock", + "description": "Comma separated list of domain names to leave unblocked with Unbound" + }, + "DNS_ADDRESS": { + "name": "DNS address", + "description": "IP address to use as DNS resolver. It defaults to localhost to use the DNS over TLS Unbound server." + }, + "DNS_KEEP_NAMESERVER": { + "name": "DNS keep nameserver", + "description": "Keep /etc/resolv.conf untouched. ⚠ this will likely leak DNS traffic outside the VPN through your default container DNS. This imples DOT=off and ignores DNS_ADDRESS" + }, + "FIREWALL_VPN_INPUT_PORTS": { + "name": "Firewall VPN input ports", + "description": "Comma separated list of ports to allow from the VPN server side" + }, + "FIREWALL_INPUT_PORTS": { + "name": "Firewall input ports", + "description": "Comma separated list of ports to allow through the default interface. This seems needed for Kubernetes sidecars." + }, + "FIREWALL_DEBUG": { + "name": "Firewall debug", + "description": "Prints every firewall related command. You should use it for debugging purposes only." + }, + "FIREWALL_OUTBOUND_SUBNETS": { + "name": "Firewall outbound subnets", + "description": "Comma separated subnets that Gluetun and the containers sharing its network stack are allowed to access. This involves firewall and routing modifications." + }, + "HEALTH_TARGET_ADDRESS": { + "name": "Health target address", + "description": "Address to ping on every internal health check" + }, + "HEALTH_VPN_DURATION_INITIAL": { + "name": "Health VPN duration initial", + "description": "Initial duration to wait for the VPN to be ready before restarting it" + }, + "HEALTH_VPN_DURATION_ADDITION": { + "name": "Health VPN duration addition", + "description": "Additional duration to add to the wait time for each consecutive failure of the VPN" + }, + "HEALTH_SUCCESS_WAIT_DURATION": { + "name": "Health success wait duration", + "description": "Duration to wait after a success check to perform another check" + }, + "HEALTH_SERVER_ADDRESS": { + "name": "Health server address", + "description": "Internal health check server listening address" + }, + "HTTPPROXY": { + "name": "HTTP proxy", + "description": "Enable the internal HTTP proxy" + }, + "HTTPPROXY_LOG": { + "name": "HTTP proxy log", + "description": "Logs every tunnel requests" + }, + "HTTPPROXY_LISTENING_ADDRESS": { + "name": "HTTP proxy listening address", + "description": "Internal listening address for the HTTP proxy" + }, + "HTTPPROXY_USER": { + "name": "HTTP proxy user", + "description": "Username to use to connect to the HTTP proxy" + }, + "HTTPPROXY_PASSWORD": { + "name": "HTTP proxy password", + "description": "Password to use to connect to the HTTP proxy" + }, + "HTTPPROXY_STEALTH": { + "name": "HTTP proxy stealth", + "description": "Stealth mode means HTTP proxy headers are not added to your requests" + }, + "OPENVPN_USER": { + "name": "OpenVPN username", + "description": "OpenVPN username" + }, + "OPENVPN_PASSWORD": { + "name": "OpenVPN password", + "description": "OpenVPN password" + }, + "OPENVPN_PROTOCOL": { + "name": "OpenVPN protocol", + "description": "Network protocol to use, only valid for OpenVPN" + }, + "OPENVPN_VERSION": { + "name": "OpenVPN version", + "description": "Set the OpenVPN version to run" + }, + "OPENVPN_VERBOSITY": { + "name": "OpenVPN verbosity", + "description": "Openvpn verbosity level" + }, + "OPENVPN_FLAGS": { + "name": "OpenVPN flags", + "description": "Space delimited openvpn flags to pass to openvpn" + }, + "OPENVPN_ROOT": { + "name": "OpenVPN root", + "description": "Run OpenVPN as root" + }, + "OPENVPN_CIPHERS": { + "name": "OpenVPN ciphers", + "description": "Specify a custom cipher to use. It will also set ncp-disable if using AES GCM for PIA" + }, + "OPENVPN_AUTH": { + "name": "OpenVPN authentication", + "description": "Specify a custom auth algorithm to use" + }, + "OPENVPN_MSSFIX": { + "name": "OpenVPN MSS fix", + "description": "Set the MSS fix parameter. Set to 0 to use the defaults." + }, + "OPENVPN_CERT": { + "name": "OpenVPN certificate", + "description": "OpenVPN certificate content (base64 part only)" + }, + "OPENVPN_KEY": { + "name": "OpenVPN key", + "description": "OpenVPN key (base64 part only)" + }, + "OPENVPN_ENCRYPTED_KEY": { + "name": "OpenVPN encrypted key", + "description": "OpenVPN encrypted key (base64 part only)" + }, + "OPENVPN_KEY_PASSPHRASE": { + "name": "OpenVPN key passphrase", + "description": "Specify a key passphrase to decrypt an encrypted key" + }, + "OPENVPN_PROCESS_USER": { + "name": "OpenVPN process user", + "description": "Specify a user to run the OpenVPN subprocess" + }, + "OPENVPN_CUSTOM_CONFIG": { + "name": "OpenVPN custom config", + "description": "Specify a custom OpenVPN configuration file to use for the custom VPN provider." + }, + "TZ": { + "name": "Time Zone", + "description": "Specify a timezone to use to have correct log times" + }, + "PUID": { + "name": "PUID", + "description": "User ID to run as non root and for ownership of files written" + }, + "PGID": { + "name": "PGID", + "description": "Group ID to run as non root and for ownership of files written" + }, + "PUBLICIP_PERIOD": { + "name": "Public IP period", + "description": "Period to check for public IP address. Set to 0 to disable." + }, + "PUBLICIP_FILE": { + "name": "Public IP file", + "description": "Filepath to store the public IP address assigned. This will be removed in the v4 program, instead you might want to use the control server" + }, + "VERSION_INFORMATION": { + "name": "Version information", + "description": "Logs a message indicating if a newer version is available once the VPN is connected" + }, + "VPN_PORT_FORWARDING": { + "name": "VPN port forwarding", + "description": "Enable custom port forwarding code for supported providers" + }, + "VPN_PORT_FORWARDING_PROVIDER": { + "name": "VPN port forwarding provider", + "description": "Choose the custom port forwarding code to use. This is useful when using the custom provider with Wireguard." + }, + "VPN_PORT_FORWARDING_STATUS_FILE": { + "name": "VPN port forwarding status file", + "description": "File path to use for writing the forwarded port obtained." + }, + "SHADOWSOCKS": { + "name": "Shadow socks", + "description": "Enable the internal Shadowsocks proxy" + }, + "SHADOWSOCKS_LOG": { + "name": "Shadow socks log", + "description": "Enable logging" + }, + "SHADOWSOCKS_LISTENING_ADDRESS": { + "name": "Shadow socks listening address", + "description": "Internal listening address for Shadowsocks" + }, + "SHADOWSOCKS_PASSWORD": { + "name": "Shadow socks password", + "description": "Password to use to connect to Shadowsocks" + }, + "SHADOWSOCKS_CIPHER": { + "name": "Shadow socks cipher", + "description": "AEAD Cipher to use for Shadowsocks" + }, + "UPDATER_PERIOD": { + "name": "Updater period", + "description": "Period to update the VPN servers data in memory and to /gluetun/servers.json. Set to 0 to disable. This does a burst of DNS over TLS requests, which may be blocked if you set BLOCK_MALICIOUS=on for example." + }, + "UPDATER_MIN_RATIO": { + "name": "Updater min ratio", + "description": "Ratio of servers to be found for the update to succeed, compared to the servers already built in the program" + }, + "UPDATER_VPN_SERVICE_PROVIDERS": { + "name": "Updater VPN service providers", + "description": "List of providers to update servers data for, when the updater triggers periodically. If left empty, it defaults to the current VPN provider used at start." + }, + "VPN_SERVICE_PROVIDER": { + "name": "VPN service provider", + "description": "Specify a supported VPN provider to use" + }, + "VPN_TYPE": { + "name": "VPN type", + "description": "VPN protocol to use. Not all providers support Wireguard." + }, + "VPN_ENDPOINT_IP": { + "name": "VPN endpoint ip", + "description": "Specify a target VPN server IP address to use" + }, + "VPN_ENDPOINT_PORT": { + "name": "VPN endpoint port", + "description": "Specify a target VPN server port number to use" + }, + "VPN_INTERFACE": { + "name": "VPN interface", + "description": "Specify a custom network interface name to use" + }, + "WIREGUARD_PRIVATE_KEY": { + "name": "Wireguard private key", + "description": "Wireguard client private key to use. This is usually always needed." + }, + "WIREGUARD_ADDRESSES": { + "name": "Wireguard addresses", + "description": "This is usually needed." + }, + "WIREGUARD_PUBLIC_KEY": { + "name": "Wireguard public key", + "description": "Wireguard server public key to use. This may or may not be needed." + }, + "WIREGUARD_PRESHARED_KEY": { + "name": "Wireguard preshared key", + "description": "Wireguard pre-shared key" + }, + "WIREGUARD_ALLOWED_IPS": { + "name": "Wireguard allowed IPs", + "description": "Wireguard peer allowed ips" + }, + "WIREGUARD_IMPLEMENTATION": { + "name": "Wireguard implementation", + "description": "Wireguard implementation to use" + }, + "WIREGUARD_MTU": { + "name": "Wireguard MTU", + "description": "Wireguard MTU" + } + }, + "network": { + "7878": "The port to redirect Radarr VPN traffic through.", + "6789/tcp": "NZBget", + "8081": "SickChill", + "8112": "Deluge web UI", + "8888/tcp": "HTTP proxy", + "8388/tcp": "Shadowsocks", + "8388/udp": "Shadowsocks", + "9091/tcp": "Transmission", + "9117/tcp": "Jackett", + "51413/tcp": "Peer port (DO NOT setup router port forwarding to this port)", + "51413/udp": "Peer port (DO NOT setup router port forwarding to this port)" + } +} \ No newline at end of file From 363f579d477d2a9d3f8d7c194abeb321a6d1c437 Mon Sep 17 00:00:00 2001 From: Nick Smith Date: Fri, 1 Sep 2023 23:34:47 -0400 Subject: [PATCH 8/8] Added entrypoint and functionality for other parameters --- gluetun/Dockerfile | 10 +++++----- gluetun/config.json | 17 ++++++++++++++--- gluetun/rootfs/entrypoint.sh | 16 ++++++++++++++++ gluetun/rootfs/etc/cont-init.d/90-run.sh | 3 +++ 4 files changed, 38 insertions(+), 8 deletions(-) create mode 100644 gluetun/rootfs/entrypoint.sh create mode 100644 gluetun/rootfs/etc/cont-init.d/90-run.sh diff --git a/gluetun/Dockerfile b/gluetun/Dockerfile index bd766aa76eb..ae20755ff74 100644 --- a/gluetun/Dockerfile +++ b/gluetun/Dockerfile @@ -68,7 +68,7 @@ RUN if [ -d /etc/cont-init.d ]; then chmod -R 755 /etc/cont-init.d; fi && \ if [ -f /entrypoint.sh ]; then chmod 755 /entrypoint.sh; fi # Modules -ARG MODULES="00-banner.sh" +ARG MODULES="00-banner.sh 01-custom_script.sh 00-global_var.sh" # Automatic modules download RUN if ! command -v bash >/dev/null 2>/dev/null; then (apt-get update && apt-get install -yqq --no-install-recommends bash || apk add --no-cache bash) >/dev/null; fi \ @@ -93,10 +93,10 @@ RUN if ! command -v bash >/dev/null 2>/dev/null; then (apt-get update && apt-get # 4 Entrypoint # ################ -#RUN chmod 777 /entrypoint.sh -#WORKDIR / -#ENTRYPOINT [ "/usr/bin/env" ] -#CMD [ "/entrypoint.sh" ] +RUN chmod 777 /entrypoint.sh +WORKDIR / +ENTRYPOINT [ "/usr/bin/env" ] +CMD [ "/entrypoint.sh" ] ############ # 5 Labels # diff --git a/gluetun/config.json b/gluetun/config.json index 1d21c5f887f..f68882cb51e 100644 --- a/gluetun/config.json +++ b/gluetun/config.json @@ -55,7 +55,9 @@ "/dev/nvme1", "/dev/nvme2" ], - "options": { + "environment": { + "PGID": "0", + "PUID": "0", "VPN_SERVICE_PROVIDER": "private internet access", "VPN_TYPE": "openvpn", "OPENVPN_USER": "", @@ -65,9 +67,17 @@ "init": false, "map": [ "config:rw", - "ssl" + "ssl:ro" ], "name": "Gluetun VPN client", + "options": { + "VPN_SERVICE_PROVIDER": "private internet access", + "VPN_TYPE": "openvpn", + "OPENVPN_USER": "", + "OPENVPN_PASSWORD": "", + "PGID": 0, + "PUID": 0 + }, "ports": { "6789/tcp": 6789, "7878": 7878, @@ -83,7 +93,8 @@ }, "privileged": [ "SYS_ADMIN", - "NET_ADMIN" + "NET_ADMIN", + "NET_RAW" ], "schema": { "PGID": "int?", diff --git a/gluetun/rootfs/entrypoint.sh b/gluetun/rootfs/entrypoint.sh new file mode 100644 index 00000000000..433f4d73df5 --- /dev/null +++ b/gluetun/rootfs/entrypoint.sh @@ -0,0 +1,16 @@ +#!/bin/bash +echo "Starting..." + +#################### +# Starting scripts # +#################### + +for SCRIPTS in /etc/cont-init.d/*; do + [ -e "$SCRIPTS" ] || continue + echo "$SCRIPTS: executing" + chown "$(id -u)":"$(id -g)" "$SCRIPTS" + chmod a+x "$SCRIPTS" + # Change shebang if no s6 supervision + sed -i 's|/usr/bin/with-contenv bashio|/usr/bin/env bashio|g' "$SCRIPTS" + /."$SCRIPTS" || echo "$SCRIPTS: exiting $?" +done \ No newline at end of file diff --git a/gluetun/rootfs/etc/cont-init.d/90-run.sh b/gluetun/rootfs/etc/cont-init.d/90-run.sh new file mode 100644 index 00000000000..b96f389e755 --- /dev/null +++ b/gluetun/rootfs/etc/cont-init.d/90-run.sh @@ -0,0 +1,3 @@ +#!/bin/bash + +/./gluetun-entrypoint \ No newline at end of file