This commit is contained in:
Stavros kois
2023-05-22 14:48:39 +03:00
parent e966492e0d
commit b0ab92e384
46 changed files with 1345 additions and 1 deletions
+36 -1
View File
@@ -966,6 +966,41 @@
],
"icon_url": "https://github.com/mumble-voip/mumble/blob/master/icons/mumble.svg"
},
"gluetun": {
"app_readme": "<h1>gluetun</h1>\n<p><a href=\"https://www.gluetun.info/\">gluetun</a> is an Open Source, Low Latency, High Quality Voice Chat Home Downloads Documentation Blog Contribute About</p>\n<blockquote>\n<p>When application is installed, a container will be launched with <strong>root</strong> privileges.\nThis is required in order to apply the correct permissions to the <code>gluetun</code> directories.\nAfterward, the <code>gluetun</code> container will run as a <strong>non</strong>-root user (<code>1000</code>, Cannot change).</p>\n</blockquote>\n<p>You can change the server configuration by adding additional environment variables.\nPrefix the configuration variable with <code>gluetun_CONFIG_</code> and it will be added to the configuration file.\nView the <a href=\"https://wiki.gluetun.info/wiki/Murmur.ini\">gluetun Configuration File</a> for more information.</p>\n<p>For example you can set <code>autobanAttempts</code> like this:</p>\n<ul>\n<li>Name: <code>gluetun_CONFIG_autobanAttempts</code></li>\n<li>Value: <code>5</code></li>\n</ul>",
"categories": [
"productivity"
],
"description": "gluetun is a free, open source, low latency, high quality voice chat application.",
"healthy": true,
"healthy_error": null,
"home": "https://www.gluetun.info/",
"location": "/__w/charts/charts/community/gluetun",
"latest_version": "1.0.1",
"latest_app_version": "v1.4.230",
"latest_human_version": "v1.4.230_1.0.1",
"last_update": "2023-05-11 16:20:35",
"name": "gluetun",
"recommended": false,
"title": "gluetun",
"maintainers": [
{
"name": "truenas",
"url": "https://www.truenas.com/",
"email": "dev@ixsystems.com"
}
],
"tags": [
"voice"
],
"screenshots": [],
"sources": [
"https://github.com/gluetun-voip/gluetun-docker",
"https://github.com/truenas/charts/tree/master/community/gluetun",
"https://www.gluetun.info/"
],
"icon_url": "https://github.com/gluetun-voip/gluetun/blob/master/icons/gluetun.svg"
},
"zerotier": {
"app_readme": "<h1>Zerotier</h1>\n<p><a href=\"https://www.zerotier.com\">Zerotier</a> Securely connect any device, anywhere.</p>",
"categories": [
@@ -1359,4 +1394,4 @@
"icon_url": "https://raw.githubusercontent.com/Lidarr/Lidarr/develop/Logo/256.png"
}
}
}
}
+6
View File
@@ -0,0 +1,6 @@
dependencies:
- name: common
repository: file://../../../common
version: 1.0.7
digest: sha256:919bcf42446fc1748a1b77001ec0161bb7a72a198381794b716a6ebb459ac31b
generated: "2023-05-16T15:42:24.207377102+03:00"
+24
View File
@@ -0,0 +1,24 @@
name: gluetun
description: Lightweight swiss-knife-like VPN client to multiple VPN service providers
annotations:
title: Gluetun
type: application
version: 1.0.0
apiVersion: v2
appVersion: v3.33.0
kubeVersion: '>=1.16.0-0'
maintainers:
- name: truenas
url: https://www.truenas.com/
email: dev@ixsystems.com
dependencies:
- name: common
repository: file://../../../common
version: 1.0.7
home: https://github.com/qdm12/gluetun
icon: https://raw.githubusercontent.com/qdm12/gluetun/master/title.svg
sources:
- https://github.com/truenas/charts/tree/master/community/gluetun
- https://github.com/qdm12/gluetun
keywords:
- vpn
+9
View File
@@ -0,0 +1,9 @@
# Gluetun
[Gluetun](https://github.com/qdm12/gluetun) - Lightweight swiss-knife-like VPN client to multiple VPN service providers
> App runs as **root** user.
> Validation exists for the most common configuration errors.
> In some providers there might be a need to add additional environment variables.
> Visit the [Gluetun documentation](https://github.com/qdm12/gluetun/wiki) for more information.
> If you don't see the option you need, you can pass it as additional environment variable.
+9
View File
@@ -0,0 +1,9 @@
# Gluetun
[Gluetun](https://github.com/qdm12/gluetun) - Lightweight swiss-knife-like VPN client to multiple VPN service providers
> App runs as **root** user.
> Validation exists for the most common configuration errors.
> In some providers there might be a need to add additional environment variables.
> Visit the [Gluetun documentation](https://github.com/qdm12/gluetun/wiki) for more information.
> If you don't see the option you need, you can pass it as additional environment variable.
Binary file not shown.
+7
View File
@@ -0,0 +1,7 @@
icon_url: https://raw.githubusercontent.com/qdm12/gluetun/master/title.svg
categories:
- networking
tags:
- vpn
- wireguard
- openvpn
+72
View File
@@ -0,0 +1,72 @@
image:
repository: qmcgaw/gluetun
pullPolicy: IfNotPresent
tag: v3.33.0
resources:
limits:
cpu: 4000m
memory: 8Gi
gluetunNetwork:
hostNetwork: false
gluetunID:
user: 568
group: 568
gluetunStorage:
data:
type: ixVolume
hostPath: ''
datasetName: data
gluetunConfig:
# - Required
provider: ''
type: ''
# - Common Wireguard options
# Required based on provider
wireguardPrivateKey: ''
wireguardPresharedKey: ''
wireguardAddresses: []
# - Common OpenVPN options
# Required based on provider
openvpnUser: ''
openvpnPassword: ''
# file | content | none
openvpnCertKeyMethod: none
# openvpnCertKeyMethod: file
openvpnCertHostPath: ''
openvpnKeyHostPath: ''
# openvpnCertKeyMethod: content
openvpnKeyPassphrase: ''
# Single line, no line breaks, without BEGIN/END
openvpnKey: ''
openvpnCert: ''
# - Custom provider
# type: openvpn
openvpnCustomConfigHostPath: ''
# type: wireguard
wireguardPublicKey: ''
vpnEndpointIP: ''
vpnEndpointPort: 0
# - Common options (Optional)
# https://raw.githubusercontent.com/qdm12/gluetun/master/internal/storage/servers.json
serverCountries: []
serverRegions: []
serverCities: []
serverHostnames: []
serverNames: []
additionalEnvs: []
# TODO: openvpn file test
+16
View File
@@ -0,0 +1,16 @@
runAsContext:
- userName: root
groupName: root
gid: 0
uid: 0
description: Gluetun run as root user.
capabilities:
- name: NET_ADMIN
description: Gluetun requires NET_ADMIN to configure the VPN interface, modify routes, etc.
- name: CHOWN
description: Gluetun is able to chown files.
- name: DAC_OVERRIDE
description: Gluetun is able to bypass permission checks for it's sub-processes.
hostMounts:
- hostPath: /dev/tun
description: Required to access the TUN device to create the VPN tunnel.
+464
View File
@@ -0,0 +1,464 @@
groups:
- name: Gluetun Configuration
description: Configure Gluetun
- name: User and Group Configuration
description: Configure User and Group for Gluetun
- name: Network Configuration
description: Configure Network for Gluetun
- name: Storage Configuration
description: Configure Storage for Gluetun
- name: Resources Configuration
description: Configure Resources for Gluetun
questions:
- variable: TZ
group: Gluetun Configuration
label: Timezone
schema:
type: string
default: Etc/UTC
required: true
$ref:
- definitions/timezone
- variable: gluetunConfig
label: ""
group: Gluetun Configuration
schema:
type: dict
attrs:
- variable: provider
label: Provider
description: |
The VPN provider to use.</br>
View available providers at https://github.com/qdm12/gluetun/wiki
schema:
type: string
required: true
enum:
- value: custom
description: Custom
- value: airvpn
description: AirVPN
- value: cyberghost
description: Cyberghost
- value: expressvpn
description: ExpressVPN
- value: fastestvpn
description: FastestVPN
- value: hidemyass
description: HideMyAss (HMA)
- value: ipvanish
description: IPVanish
- value: ivpn
description: IVPN
- value: mullvad
description: Mullvad
- value: nordvpn
description: NordVPN
- value: perfect privacy
description: Perfect Privacy
- value: privado
description: Privado
- value: private internet access
description: Private Internet Access (PIA)
- value: privatevpn
description: PrivateVPN
- value: protonvpn
description: ProtonVPN
- value: purevpn
description: PureVPN
- value: slickvpn
description: SlickVPN
- value: surfshark
description: Surfshark
- value: torguard
description: Tor Guard
- value: vpnsecure
description: VPNSecure
- value: vpn unlimited
description: VPN Unlimited
- value: vyprvpn
description: VyprVPN
- value: wevpn
description: WeVPN
- value: windscribe
description: Windscribe
- variable: type
label: Type
description: |
The VPN type to use.</br>
Not all providers support all types.</br>
An error will be shown if not supported.
schema:
type: string
required: true
enum:
- value: openvpn
description: OpenVPN
- value: wireguard
description: Wireguard
# Custom provider (openvpn)
- variable: openvpnCustomConfigHostPath
label: OpenVPN Custom Configuration Host Path
description: |
The OpenVPN custom configuration host path.</br>
Fill this only if type is openvpn.</br>
schema:
type: hostpath
# Ideally we would have a show_if with type=openvpn too
show_if: [["provider", "=", "custom"]]
# Custom provider (wireguard)
- variable: vpnEndpointIP
label: VPN Endpoint IP
description: |
The VPN endpoint IP.</br>
Fill this only if type is wireguard.</br>
schema:
type: string
# Ideally we would have a show_if with type=wireguard too
show_if: [["provider", "=", "custom"]]
- variable: vpnEndpointPort
label: VPN Endpoint Port
description: |
The VPN endpoint port.</br>
Fill this only if type is wireguard.</br>
schema:
type: int
# Ideally we would have a show_if with type=wireguard too
show_if: [["provider", "=", "custom"]]
- variable: wireguardPublicKey
label: Wireguard Public Key
description: |
The Wireguard public key.</br>
Fill this only if type is wireguard.</br>
schema:
type: string
# Ideally we would have a show_if with type=wireguard too
show_if: [["provider", "=", "custom"]]
private: true
# Common Wireguard options
- variable: wireguardPrivateKey
label: Wireguard Private Key
schema:
type: string
show_if: [["type", "=", "wireguard"]]
- variable: wireguardPresharedKey
label: Wireguard Preshared Key
schema:
type: string
- variable: wireguardAddresses
label: Wireguard Addresses
schema:
type: list
show_if: [["type", "=", "wireguard"]]
default: []
items:
- variable: address
label: Address
schema:
type: string
required: true
# Common OpenVPN options
- variable: openvpnCertKeyMethod
label: OpenVPN Certificate and Key Method
description: |
The method to use for the OpenVPN client certificate and key.</br>
- File: Use a file path on the host.</br>
- Content: Use the content of the variable.</br>
- None: Do not use a certificate and key.</br>
This is only required by a small subset of providers.</br>
An error will be shown if required and not provided.
schema:
type: string
show_if: [["type", "=", "openvpn"]]
default: none
required: true
enum:
- value: file
description: File
- value: content
description: Content
- value: none
description: None
# openvpnCertKeyMethod: content
- variable: openvpnKey
label: OpenVPN Key
description: |
The OpenVPN client key.</br>
Single line, no line breaks, without BEGIN/END.</br>
Check instructions at https://github.com/qdm12/gluetun/wiki/OpenVPN-client-key
schema:
type: string
show_if: [["openvpnCertKeyMethod", "=", "content"]]
private: true
- variable: openvpnCert
label: OpenVPN Certificate
description: |
The OpenVPN client certificate.</br>
Single line, no line breaks, without BEGIN/END.</br>
Check instructions at https://github.com/qdm12/gluetun/wiki/OpenVPN-client-certificate
schema:
type: string
show_if: [["openvpnCertKeyMethod", "=", "content"]]
private: true
# openvpnCertKeyMethod: file
- variable: openvpnCertHostPath
label: OpenVPN Certificate Host Path
description: |
The OpenVPN client certificate host path.</br>
Check instructions at https://github.com/qdm12/gluetun/wiki/OpenVPN-client-certificate
schema:
type: hostpath
show_if: [["openvpnCertKeyMethod", "=", "file"]]
- variable: openvpnKeyHostPath
label: OpenVPN Key Host Path
description: |
The OpenVPN client key host path.</br>
Check instructions at https://github.com/qdm12/gluetun/wiki/OpenVPN-client-certificate
schema:
type: hostpath
show_if: [["openvpnCertKeyMethod", "=", "file"]]
- variable: openvpnUser
label: OpenVPN User
description: |
The OpenVPN username.</br>
Required in some providers.</br>
An error will be shown if required and not provided.
schema:
type: string
show_if: [["type", "=", "openvpn"]]
- variable: openvpnPassword
label: OpenVPN Password
description: |
The OpenVPN password.</br>
Required in some providers.</br>
An error will be shown if required and not provided.
schema:
type: string
show_if: [["type", "=", "openvpn"]]
private: true
- variable: openvpnKeyPassphrase
label: OpenVPN Key Passphrase
description: |
The OpenVPN key passphrase.</br>
Required in some providers.</br>
An error will be shown if required and not provided.
schema:
type: string
show_if: [["type", "=", "openvpn"]]
private: true
# Common options (Optional)
- variable: serverCountries
label: Server Countries (Optional)
description: |
The countries to connect to.</br>
Not all providers support this. An error will be shown if not supported.</br>
View available options at https://raw.githubusercontent.com/qdm12/gluetun/master/internal/storage/servers.json
schema:
type: list
default: []
items:
- variable: country
label: Country
schema:
type: string
required: true
- variable: serverRegions
label: Server Regions (Optional)
description: |
The regions to connect to.</br>
Not all providers support this. An error will be shown if not supported.</br>
View available options at https://raw.githubusercontent.com/qdm12/gluetun/master/internal/storage/servers.json
schema:
type: list
default: []
items:
- variable: region
label: Region
schema:
type: string
required: true
- variable: serverCities
label: Server Cities (Optional)
description: |
The cities to connect to.</br>
Not all providers support this. An error will be shown if not supported.</br>
View available options at https://raw.githubusercontent.com/qdm12/gluetun/master/internal/storage/servers.json
schema:
type: list
default: []
items:
- variable: city
label: City
schema:
type: string
required: true
- variable: serverHostnames
label: Server Hostnames (Optional)
description: |
The hostnames to connect to.</br>
Not all providers support this. An error will be shown if not supported.</br>
View available options at https://raw.githubusercontent.com/qdm12/gluetun/master/internal/storage/servers.json
schema:
type: list
default: []
items:
- variable: hostname
label: Hostname
schema:
type: string
required: true
- variable: serverNames
label: Server Names (Optional)
description: |
The names to connect to.</br>
Not all providers support this. An error will be shown if not supported.</br>
View available options at https://raw.githubusercontent.com/qdm12/gluetun/master/internal/storage/servers.json
schema:
type: list
default: []
items:
- variable: name
label: Name
schema:
type: string
required: true
- variable: additionalEnvs
label: Additional Environment Variables
description: Configure additional environment variables for Gluetun.
schema:
type: list
default: []
items:
- variable: env
label: Environment Variable
schema:
type: dict
attrs:
- variable: name
label: Name
schema:
type: string
required: true
- variable: value
label: Value
schema:
type: string
required: true
- variable: gluetunID
label: ""
group: User and Group Configuration
schema:
type: dict
attrs:
- variable: user
label: User ID
description: The user id that Gluetun files will be owned by.
schema:
type: int
min: 568
default: 568
required: true
- variable: group
label: Group ID
description: The group id that Gluetun files will be owned by.
schema:
type: int
min: 568
default: 568
required: true
- variable: gluetunNetwork
label: ""
group: Network Configuration
schema:
type: dict
attrs:
- variable: hostNetwork
label: Host Network
description: Bind to the host network.
schema:
type: boolean
default: false
- variable: gluetunStorage
label: ""
group: Storage Configuration
schema:
type: dict
attrs:
- variable: data
label: Gluetun Data Storage
description: The path to store Gluetun data.
schema:
type: dict
attrs:
- variable: type
label: Type
description: |
ixVolume: Is dataset created automatically by the system.</br>
Host Path: Is a path that already exists on the system.
schema:
type: string
required: true
default: ixVolume
enum:
- value: hostPath
description: Host Path (Path that already exists on the system)
- value: ixVolume
description: ixVolume (Dataset created automatically by the system)
- variable: datasetName
label: Dataset Name
schema:
type: string
show_if: [["type", "=", "ixVolume"]]
required: true
hidden: true
immutable: true
default: "data"
$ref:
- "normalize/ixVolume"
- variable: hostPath
label: Host Path
schema:
type: hostpath
show_if: [["type", "=", "hostPath"]]
immutable: true
required: true
- variable: resources
label: ""
group: Resources Configuration
schema:
type: dict
attrs:
- variable: limits
label: Limits
schema:
type: dict
attrs:
- variable: cpu
label: CPU
description: CPU limit for Gluetun.
schema:
type: string
default: 4000m
required: true
- variable: memory
label: Memory
description: Memory limit for Gluetun.
schema:
type: string
default: 8Gi
required: true
@@ -0,0 +1 @@
{{ include "ix.v1.common.lib.chart.notes" $ }}
@@ -0,0 +1,63 @@
{{- define "gluetun.configuration" -}}
{{- include "gluetun.validation" $ }}
configmap:
gluetun:
enabled: true
data:
VPN_SERVICE_PROVIDER: {{ .Values.gluetunConfig.provider }}
VPN_TYPE: {{ .Values.gluetunConfig.type }}
PUBLICIP_FILE: /tmp/gluetun/ip
{{/* Make VPN interface unique for each app instance */}}
{{ $vpnInterface := .Release.Name | replace "-" "" | trunc 15 | lower }}
{{ if gt (len $vpnInterface) 15 }}
{{ fail "Gluetun - App name is used also for interface name and cannot exceed 15 characters" }}
{{ end }}
VPN_INTERFACE: {{ $vpnInterface }}
{{/* Include common configuration */}}
{{- include "gluetun.configs.common.env" $ | nindent 6 }}
{{/* Include common configuration based on type */}}
{{- if eq .Values.gluetunConfig.type "openvpn" }}
{{- include "gluetun.configs.openvpn.env" $ | nindent 6 }}
{{- else if eq .Values.gluetunConfig.type "wireguard" }}
{{- include "gluetun.configs.wireguard.env" $ | nindent 6 }}
{{- end }}
{{/* Include provider specific validation */}}
{{- include (printf "gluetun.%v.%v.validation" .Values.gluetunConfig.provider .Values.gluetunConfig.type) $ | nindent 6 }}
{{- end -}}
{{- define "gluetun.openvpn.filemount" -}}
{{ if eq .Values.gluetunConfig.openvpnCertKeyMethod "file" }}
openvpn-certificate:
enabled: true
type: hostPath
hostPath: {{ .Values.gluetunConfig.openvpnCertHostPath }}
hostPathType: File
targetSelector:
gluetun:
gluetun:
mountPath: /gluetun/client.crt
openvpn-key:
enabled: true
type: hostPath
hostPath: {{ .Values.gluetunConfig.openvpnKeyHostPath }}
hostPathType: File
targetSelector:
gluetun:
gluetun:
mountPath: /gluetun/openvpn_encrypted_key
{{ end }}
{{ if eq .Values.gluetunConfig.provider "custom" }}
custom-conf:
enabled: true
type: hostPath
hostPath: {{ .Values.gluetunConfig.openvpnCustomConfigHostPath }}
hostPathType: File
targetSelector:
gluetun:
gluetun:
mountPath: /gluetun/custom.conf
{{ end }}
{{- end -}}
@@ -0,0 +1,87 @@
{{- define "gluetun.workload" -}}
workload:
gluetun:
enabled: true
primary: true
type: Deployment
podSpec:
hostNetwork: {{ .Values.gluetunNetwork.hostNetwork }}
securityContext:
fsGroup: {{ .Values.gluetunID.group }}
containers:
gluetun:
enabled: true
primary: true
imageSelector: image
securityContext:
runAsUser: 0
runAsGroup: 0
runAsNonRoot: false
readOnlyRootFilesystem: false
capabilities:
add:
- CHOWN
- NET_ADMIN
- DAC_OVERRIDE
fixedEnv:
PUID: {{ .Values.gluetunID.user }}
envFrom:
- configMapRef:
name: gluetun
{{ with .Values.gluetunConfig.additionalEnvs }}
envList:
{{ range $env := . }}
- name: {{ $env.name }}
value: {{ $env.value }}
{{ end }}
{{ end }}
probes:
liveness:
enabled: true
type: exec
command:
- /gluetun-entrypoint
- healthcheck
readiness:
enabled: true
type: exec
command:
- /gluetun-entrypoint
- healthcheck
startup:
enabled: true
type: exec
command:
- /gluetun-entrypoint
- healthcheck
{{/* Persistence */}}
persistence:
devtun:
enabled: true
type: device
hostPath: /dev/net/tun
targetSelector:
gluetun:
gluetun:
mountPath: /dev/net/tun
temp:
enabled: true
type: emptyDir
targetSelector:
gluetun:
gluetun:
mountPath: /tmp/gluetun
data:
enabled: true
type: {{ .Values.gluetunStorage.data.type }}
datasetName: {{ .Values.gluetunStorage.data.datasetName | default "" }}
hostPath: {{ .Values.gluetunStorage.data.hostPath | default "" }}
targetSelector:
gluetun:
gluetun:
mountPath: /gluetun
{{ if eq .Values.gluetunConfig.type "openvpn" }}
{{- include "gluetun.openvpn.filemount" $ | nindent 2 }}
{{ end }}
{{- end -}}
@@ -0,0 +1,69 @@
{{- define "gluetun.validation" -}}
{{- $providers := (list "custom" "airvpn" "cyberghost" "expressvpn"
"fastestvpn" "hidemyass" "ipvanish" "ivpn"
"mullvad" "nordvpn" "perfect privacy" "privado"
"private internet access" "privatevpn" "protonvpn"
"purevpn" "slickvpn" "surfshark" "torguard" "vpnsecure"
"vpn unlimited" "vyprvpn" "wevpn" "windscribe") -}}
{{- if not (mustHas .Values.gluetunConfig.provider $providers) -}}
{{- fail (printf "Gluetun - Expected [Provider] to be one of [%v], but got [%v]" (join ", " $providers) .Values.gluetunConfig.provider) -}}
{{- end -}}
{{- $types := (list "openvpn" "wireguard") -}}
{{- if not (mustHas .Values.gluetunConfig.type $types) -}}
{{- fail (printf "Gluetun - Expected [Type] to be one of [%v], but got [%v]" (join ", " $providers) .Values.gluetunConfig.type) -}}
{{- end -}}
{{- $methods := (list "none" "file" "content") -}}
{{- if not (mustHas .Values.gluetunConfig.openvpnCertKeyMethod $methods) -}}
{{- fail (printf "Gluetun - Expected [OpenVPN Cert and Key Method] to be one of [%v], but got [%v]" (join ", " $methods) .Values.gluetunConfig.openvpnCertKeyMethod) -}}
{{- end -}}
{{- end -}}
{{/* Included by providers that require specific options */}}
{{- define "gluetun.options.required" -}}
{{- $options := .options -}}
{{- $rootCtx := .rootCtx -}}
{{- $opts := (list "openvpnCert" "openvpnKey" "openvpnCertHostPath"
"openvpnKeyHostPath" "openvpnUser" "openvpnPassword"
"openvpnKeyPassphrase" "wireguardPrivateKey"
"wireguardPublicKey" "wireguardPresharedKey"
"wireguardAddresses" "vpnEndpointIP" "vpnEndpointPort"
"openvpnCustomConfigHostPath") -}}
{{- range $opt := $options -}}
{{- if not (mustHas $opt $opts) -}} {{/* Dev validation, to avoid typos early */}}
{{- fail (printf "Gluetun - Bad option (%v) passed in provider [%v]." $opt $rootCtx.Values.gluetunConfig.provider) -}}
{{- end -}}
{{- if not (get $rootCtx.Values.gluetunConfig $opt) -}}
{{- fail (printf "Gluetun - Provider [%v] requires non-empty [%v] option on type [%v]." $rootCtx.Values.gluetunConfig.provider $opt $rootCtx.Values.gluetunConfig.type) -}}
{{- end -}}
{{- end -}}
{{- end -}}
{{/* Included by providers that do not support one the the 2 types */}}
{{- define "gluetun.unsupported.type" -}}
{{- fail (printf "Gluetun - Provider [%v] does not support type of [%v]." .Values.gluetunConfig.provider .Values.gluetunConfig.type) -}}
{{- end -}}
{{/* Inluded by providers that do not support all the server options */}}
{{- define "gluetun.unsupported.server.options" -}}
{{- $options := .options -}}
{{- $rootCtx := .rootCtx -}}
{{- $opts := (list "serverRegions" "serverCountries" "serverNames" "serverHostnames" "serverCities") -}}
{{- range $opt := $options -}}
{{- if not (mustHas $opt $opts) -}} {{/* Dev validation, to avoid typos early */}}
{{- fail (printf "Gluetun - Bad option (%v) passed in provider [%v]." $opt $rootCtx.Values.gluetunConfig.provider) -}}
{{- end -}}
{{- if (get $rootCtx.Values.gluetunConfig $opt) -}}
{{- fail (printf "Gluetun - Provider [%v] does not support [%v] option." $rootCtx.Values.gluetunConfig.provider $opt) -}}
{{- end -}}
{{- end -}}
{{- end -}}
{{- define "gluetun.certkey.required.error" -}}
{{- fail (printf "Gluetun - Provider [%v] requires [Key and/or Certificate] either from [File or Content] method on type [openvpn]." .Values.gluetunConfig.provider) -}}
{{- end -}}
@@ -0,0 +1,7 @@
{{- include "ix.v1.common.loader.init" . -}}
{{/* Merge the templates with Values */}}
{{- $_ := mustMergeOverwrite .Values (include "gluetun.configuration" $ | fromYaml) -}}
{{- $_ := mustMergeOverwrite .Values (include "gluetun.workload" $ | fromYaml) -}}
{{- include "ix.v1.common.loader.apply" . -}}
@@ -0,0 +1,18 @@
{{- define "gluetun.configs.common.env" -}}
{{/*
View available options per provider here
https://raw.githubusercontent.com/qdm12/gluetun/master/internal/storage/servers.json
*/}}
{{- with .Values.gluetunConfig.serverCountries }}
SERVER_COUNTRIES: {{ join "," . }}
{{- end }}
{{- with .Values.gluetunConfig.serverRegions }}
SERVER_REGIONS: {{ join "," . }}
{{- end }}
{{- with .Values.gluetunConfig.serverCities }}
SERVER_CITIES: {{ join "," . }}
{{- end }}
{{- with .Values.gluetunConfig.serverHostnames }}
SERVER_HOSTNAMES: {{ join "," . }}
{{- end }}
{{- end -}}
@@ -0,0 +1,20 @@
{{- define "gluetun.configs.openvpn.env" -}}
{{- with .Values.gluetunConfig.openvpnKey }}
OPENVPN_KEY: {{ . }}
{{- end }}
{{- with .Values.gluetunConfig.openvpnCert }}
OPENVPN_CERT: {{ . }}
{{- end }}
{{- with .Values.gluetunConfig.openvpnUser }}
OPENVPN_USER: {{ . }}
{{- end }}
{{- with .Values.gluetunConfig.openvpnPassword }}
OPENVPN_PASSWORD: {{ . }}
{{- end }}
{{- with .Values.gluetunConfig.openvpnKeyPassphrase }}
OPENVPN_KEY_PASSPHRASE: {{ . }}
{{- end }}
{{- if .Values.gluetunConfig.openvpnCustomConfigHostPath }}
OPENVPN_CUSTOM_CONFIG: /gluetun/custom.conf
{{- end }}
{{- end -}}
@@ -0,0 +1,20 @@
{{- define "gluetun.configs.wireguard.env" -}}
{{- with .Values.gluetunConfig.wireguardPrivateKey }}
WIREGUARD_PRIVATE_KEY: {{ . }}
{{- end }}
{{- with .Values.gluetunConfig.wireguardPresharedKey }}
WIREGUARD_PRESHARED_KEY: {{ . }}
{{- end }}
{{- with .Values.gluetunConfig.wireguardPublicKey }}
WIREGUARD_PUBLIC_KEY: {{ . }}
{{- end }}
{{- with .Values.gluetunConfig.wireguardAddresses }}
WIREGUARD_ADDRESSES: {{ join "," . }}
{{- end }}
{{- with .Values.gluetunConfig.vpnEndpointIP }}
VPN_ENDPOINT_IP: {{ . }}
{{- end }}
{{- with .Values.gluetunConfig.vpnEndpointPort }}
VPN_ENDPOINT_PORT: {{ . | quote }}
{{- end }}
{{- end -}}
@@ -0,0 +1,19 @@
{{/* https://github.com/qdm12/gluetun/wiki/AirVPN */}}
{{- define "gluetun.airvpn.openvpn.validation" -}}
{{- $req := list -}}
{{- if eq .Values.gluetunConfig.openvpnCertKeyMethod "file" -}}
{{- $req = (list "openvpnCertHostPath" "openvpnKeyHostPath") -}}
{{- else if eq .Values.gluetunConfig.openvpnCertKeyMethod "content" -}}
{{- $req = (list "openvpnCert" "openvpnKey") -}}
{{- else -}}
{{- include "gluetun.certkey.required.error" $ -}}
{{- end -}}
{{- include "gluetun.options.required" (dict "rootCtx" $ "options" $req) -}}
{{- end -}}
{{- define "gluetun.airvpn.wireguard.validation" -}}
{{- $req := (list "wireguardPrivateKey" "wireguardPresharedKey" "wireguardAddresses") -}}
{{- include "gluetun.options.required" (dict "rootCtx" $ "options" $req) -}}
{{- end -}}
@@ -0,0 +1,12 @@
{{/* https://github.com/qdm12/gluetun/wiki/Custom-provider */}}
{{- define "gluetun.custom.openvpn.validation" -}}
{{- $req := (list "openvpnCustomConfigHostPath") -}}
{{- include "gluetun.options.required" (dict "rootCtx" $ "options" $req) -}}
{{- end -}}
{{- define "gluetun.custom.wireguard.validation" -}}
{{- $req := (list "wireguardPrivateKey" "wireguardPublicKey" "wireguardPrivateKey") -}}
{{- include "gluetun.options.required" (dict "rootCtx" $ "options" $req) -}}
{{- end -}}
@@ -0,0 +1,23 @@
{{/* https://github.com/qdm12/gluetun/wiki/Cyberghost */}}
{{- define "gluetun.cyberghost.openvpn.validation" -}}
{{- $req := list -}}
{{- if eq .Values.gluetunConfig.openvpnCertKeyMethod "file" -}}
{{- $req = (list "openvpnCertHostPath" "openvpnKeyHostPath") -}}
{{- else if eq .Values.gluetunConfig.openvpnCertKeyMethod "content" -}}
{{- $req = (list "openvpnCert" "openvpnKey") -}}
{{- else -}}
{{- include "gluetun.certkey.required.error" $ -}}
{{- end -}}
{{- $req = concat $req (list "openvpnUser" "openvpnPassword") -}}
{{- $unsup := (list "serverRegions" "serverCities" "serverNames") -}}
{{- include "gluetun.options.required" (dict "rootCtx" $ "options" $req) -}}
{{- include "gluetun.unsupported.server.options" (dict "rootCtx" $ "options" $unsup) -}}
{{- end -}}
{{- define "gluetun.cyberghost.wireguard.validation" -}}
{{- include "gluetun.unsupported.type" $ -}}
{{- end -}}
@@ -0,0 +1,13 @@
{{/* https://github.com/qdm12/gluetun/wiki/ExpressVPN */}}
{{- define "gluetun.expressvpn.openvpn.validation" -}}
{{- $req := (list "openvpnUser" "openvpnPassword") -}}
{{- $unsup := (list "serverRegions" "serverNames") -}}
{{- include "gluetun.options.required" (dict "rootCtx" $ "options" $req) -}}
{{- include "gluetun.unsupported.server.options" (dict "rootCtx" $ "options" $unsup) -}}
{{- end -}}
{{- define "gluetun.expressvpn.wireguard.validation" -}}
{{- include "gluetun.unsupported.type" $ -}}
{{- end -}}
@@ -0,0 +1,13 @@
{{/* https://github.com/qdm12/gluetun/wiki/FastestVPN */}}
{{- define "gluetun.fastestvpn.openvpn.validation" -}}
{{- $req := (list "openvpnUser" "openvpnPassword") -}}
{{- $unsup := (list "serverRegions" "serverCities" "serverNames") -}}
{{- include "gluetun.options.required" (dict "rootCtx" $ "options" $req) -}}
{{- include "gluetun.unsupported.server.options" (dict "rootCtx" $ "options" $unsup) -}}
{{- end -}}
{{- define "gluetun.fastestvpn.wireguard.validation" -}}
{{- include "gluetun.unsupported.type" $ -}}
{{- end -}}
@@ -0,0 +1,13 @@
{{/* https://github.com/qdm12/gluetun/wiki/Hidemyass */}}
{{- define "gluetun.hidemyass.openvpn.validation" -}}
{{- $req := (list "openvpnUser" "openvpnPassword") -}}
{{- $unsup := (list "serverNames") -}}
{{- include "gluetun.options.required" (dict "rootCtx" $ "options" $req) -}}
{{- include "gluetun.unsupported.server.options" (dict "rootCtx" $ "options" $unsup) -}}
{{- end -}}
{{- define "gluetun.hidemyass.wireguard.validation" -}}
{{- include "gluetun.unsupported.type" $ -}}
{{- end -}}
@@ -0,0 +1,13 @@
{{/* https://github.com/qdm12/gluetun/wiki/IPVanish */}}
{{- define "gluetun.ipvanish.openvpn.validation" -}}
{{- $req := (list "openvpnUser" "openvpnPassword") -}}
{{- $unsup := (list "serverRegions" "serverNames") -}}
{{- include "gluetun.options.required" (dict "rootCtx" $ "options" $req) -}}
{{- include "gluetun.unsupported.server.options" (dict "rootCtx" $ "options" $unsup) -}}
{{- end -}}
{{- define "gluetun.ipvanish.wireguard.validation" -}}
{{- include "gluetun.unsupported.type" $ -}}
{{- end -}}
@@ -0,0 +1,18 @@
{{/* https://github.com/qdm12/gluetun/wiki/IVPN */}}
{{- define "gluetun.ivpn.openvpn.validation" -}}
{{- $req := (list "openvpnUser") -}}
{{- $unsup := (list "serverRegions" "serverNames") -}}
{{- include "gluetun.options.required" (dict "rootCtx" $ "options" $req) -}}
{{- include "gluetun.unsupported.server.options" (dict "rootCtx" $ "options" $unsup) -}}
{{- end -}}
{{- define "gluetun.ivpn.wireguard.validation" -}}
{{- $req := (list "wireguardPrivateKey" "wireguardAddresses") -}}
{{- $unsup := (list "serverRegions" "serverNames") -}}
{{- include "gluetun.options.required" (dict "rootCtx" $ "options" $req) -}}
{{- include "gluetun.unsupported.server.options" (dict "rootCtx" $ "options" $unsup) -}}
{{- end -}}
@@ -0,0 +1,18 @@
{{/* https://github.com/qdm12/gluetun/wiki/Mullvad */}}
{{- define "gluetun.mullvad.openvpn.validation" -}}
{{- $req := (list "openvpnUser") -}}
{{- $unsup := (list "serverRegions" "serverNames") -}}
{{- include "gluetun.options.required" (dict "rootCtx" $ "options" $req) -}}
{{- include "gluetun.unsupported.server.options" (dict "rootCtx" $ "options" $unsup) -}}
{{- end -}}
{{- define "gluetun.mullvad.wireguard.validation" -}}
{{- $req := (list "wireguardPrivateKey" "wireguardAddresses") -}}
{{- $unsup := (list "serverRegions" "serverNames") -}}
{{- include "gluetun.options.required" (dict "rootCtx" $ "options" $req) -}}
{{- include "gluetun.unsupported.server.options" (dict "rootCtx" $ "options" $unsup) -}}
{{- end -}}
@@ -0,0 +1,13 @@
{{/* https://github.com/qdm12/gluetun/wiki/NordVPN */}}
{{- define "gluetun.nordvpn.openvpn.validation" -}}
{{- $req := (list "openvpnUser" "openvpnPassword") -}}
{{- $unsup := (list "serverCountries" "serverCities" "serverNames") -}}
{{- include "gluetun.options.required" (dict "rootCtx" $ "options" $req) -}}
{{- include "gluetun.unsupported.server.options" (dict "rootCtx" $ "options" $unsup) -}}
{{- end -}}
{{- define "gluetun.nordvpn.wireguard.validation" -}}
{{- include "gluetun.unsupported.type" $ -}}
{{- end -}}
@@ -0,0 +1,13 @@
{{/* https://github.com/qdm12/gluetun/wiki/Perfect-privacy */}}
{{- define "gluetun.perfect privacy.openvpn.validation" -}}
{{- $req := (list "openvpnUser" "openvpnPassword") -}}
{{- $unsup := (list "serverRegions" "serverCountries" "serverHostnames" "serverNames") -}}
{{- include "gluetun.options.required" (dict "rootCtx" $ "options" $req) -}}
{{- include "gluetun.unsupported.server.options" (dict "rootCtx" $ "options" $unsup) -}}
{{- end -}}
{{- define "gluetun.perfect privacy.wireguard.validation" -}}
{{- include "gluetun.unsupported.type" $ -}}
{{- end -}}
@@ -0,0 +1,13 @@
{{/* https://github.com/qdm12/gluetun/wiki/Privado */}}
{{- define "gluetun.privado.openvpn.validation" -}}
{{- $req := (list "openvpnUser" "openvpnPassword") -}}
{{- $unsup := (list "serverNames") -}}
{{- include "gluetun.options.required" (dict "rootCtx" $ "options" $req) -}}
{{- include "gluetun.unsupported.server.options" (dict "rootCtx" $ "options" $unsup) -}}
{{- end -}}
{{- define "gluetun.privado.wireguard.validation" -}}
{{- include "gluetun.unsupported.type" $ -}}
{{- end -}}
@@ -0,0 +1,13 @@
{{/* https://github.com/qdm12/gluetun/wiki/Private-internet-access */}}
{{- define "gluetun.private internet access.openvpn.validation" -}}
{{- $req := (list "openvpnUser" "openvpnPassword") -}}
{{- $unsup := (list "serverCities" "serverCountries") -}}
{{- include "gluetun.options.required" (dict "rootCtx" $ "options" $req) -}}
{{- include "gluetun.unsupported.server.options" (dict "rootCtx" $ "options" $unsup) -}}
{{- end -}}
{{- define "gluetun.private internet access.wireguard.validation" -}}
{{- include "gluetun.unsupported.type" $ -}}
{{- end -}}
@@ -0,0 +1,13 @@
{{/* https://github.com/qdm12/gluetun/wiki/PrivateVPN */}}
{{- define "gluetun.privatevpn.openvpn.validation" -}}
{{- $req := (list "openvpnUser" "openvpnPassword") -}}
{{- $unsup := (list "serverRegions" "serverHostnames" "serverNames") -}}
{{- include "gluetun.options.required" (dict "rootCtx" $ "options" $req) -}}
{{- include "gluetun.unsupported.server.options" (dict "rootCtx" $ "options" $unsup) -}}
{{- end -}}
{{- define "gluetun.privatevpn.wireguard.validation" -}}
{{- include "gluetun.unsupported.type" $ -}}
{{- end -}}
@@ -0,0 +1,13 @@
{{/* https://github.com/qdm12/gluetun/wiki/ProtonVPN */}}
{{- define "gluetun.protonvpn.openvpn.validation" -}}
{{- $req := (list "openvpnUser" "openvpnPassword") -}}
{{- $unsup := (list "serverNames") -}}
{{- include "gluetun.options.required" (dict "rootCtx" $ "options" $req) -}}
{{- include "gluetun.unsupported.server.options" (dict "rootCtx" $ "options" $unsup) -}}
{{- end -}}
{{- define "gluetun.protonvpn.wireguard.validation" -}}
{{- include "gluetun.unsupported.type" $ -}}
{{- end -}}
@@ -0,0 +1,13 @@
{{/* https://github.com/qdm12/gluetun/wiki/PureVPN */}}
{{- define "gluetun.purevpn.openvpn.validation" -}}
{{- $req := (list "openvpnUser" "openvpnPassword") -}}
{{- $unsup := (list "serverNames") -}}
{{- include "gluetun.options.required" (dict "rootCtx" $ "options" $req) -}}
{{- include "gluetun.unsupported.server.options" (dict "rootCtx" $ "options" $unsup) -}}
{{- end -}}
{{- define "gluetun.purevpn.wireguard.validation" -}}
{{- include "gluetun.unsupported.type" $ -}}
{{- end -}}
@@ -0,0 +1,23 @@
{{/* https://github.com/qdm12/gluetun/wiki/SlickVPN */}}
{{- define "gluetun.slickvpn.openvpn.validation" -}}
{{- $req := list -}}
{{- if eq .Values.gluetunConfig.openvpnCertKeyMethod "file" -}}
{{- $req = (list "openvpnCertHostPath" "openvpnKeyHostPath") -}}
{{- else if eq .Values.gluetunConfig.openvpnCertKeyMethod "content" -}}
{{- $req = (list "openvpnCert" "openvpnKey") -}}
{{- else -}}
{{- include "gluetun.certkey.required.error" $ -}}
{{- end -}}
{{- $req = concat $req (list "openvpnUser" "openvpnPassword") -}}
{{- $unsup := (list "serverNames") -}}
{{- include "gluetun.options.required" (dict "rootCtx" $ "options" $req) -}}
{{- include "gluetun.unsupported.server.options" (dict "rootCtx" $ "options" $unsup) -}}
{{- end -}}
{{- define "gluetun.slickvpn.wireguard.validation" -}}
{{- include "gluetun.unsupported.type" $ -}}
{{- end -}}
@@ -0,0 +1,18 @@
{{/* https://github.com/qdm12/gluetun/wiki/Surfshark */}}
{{- define "gluetun.surfshark.openvpn.validation" -}}
{{- $req := (list "openvpnUser" "openvpnPassword") -}}
{{- $unsup := (list "serverNames") -}}
{{- include "gluetun.options.required" (dict "rootCtx" $ "options" $req) -}}
{{- include "gluetun.unsupported.server.options" (dict "rootCtx" $ "options" $unsup) -}}
{{- end -}}
{{- define "gluetun.surfshark.wireguard.validation" -}}
{{- $req := (list "wireguardPrivateKey" "wireguardAddresses") -}}
{{- $unsup := (list "serverNames") -}}
{{- include "gluetun.options.required" (dict "rootCtx" $ "options" $req) -}}
{{- include "gluetun.unsupported.server.options" (dict "rootCtx" $ "options" $unsup) -}}
{{- end -}}
@@ -0,0 +1,13 @@
{{/* https://github.com/qdm12/gluetun/wiki/Torguard */}}
{{- define "gluetun.torguard.openvpn.validation" -}}
{{- $req := (list "openvpnUser" "openvpnPassword") -}}
{{- $unsup := (list "serverRegions" "serverNames") -}}
{{- include "gluetun.options.required" (dict "rootCtx" $ "options" $req) -}}
{{- include "gluetun.unsupported.server.options" (dict "rootCtx" $ "options" $unsup) -}}
{{- end -}}
{{- define "gluetun.torguard.wireguard.validation" -}}
{{- include "gluetun.unsupported.type" $ -}}
{{- end -}}
@@ -0,0 +1,23 @@
{{/* https://github.com/qdm12/gluetun/wiki/VPN-Secure */}}
{{- define "gluetun.vpnsecure.openvpn.validation" -}}
{{- $req := list -}}
{{- if eq .Values.gluetunConfig.openvpnCertKeyMethod "file" -}}
{{- $req = (list "openvpnCertHostPath" "openvpnKeyHostPath") -}}
{{- else if eq .Values.gluetunConfig.openvpnCertKeyMethod "content" -}}
{{- $req = (list "openvpnCert" "openvpnKey") -}}
{{- else -}}
{{- include "gluetun.certkey.required.error" $ -}}
{{- end -}}
{{- $req = concat $req (list "openvpnKeyPassphrase") -}}
{{- $unsup := (list "serverCountries" "serverNames") -}}
{{- include "gluetun.options.required" (dict "rootCtx" $ "options" $req) -}}
{{- include "gluetun.unsupported.server.options" (dict "rootCtx" $ "options" $unsup) -}}
{{- end -}}
{{- define "gluetun.vpnsecure.wireguard.validation" -}}
{{- include "gluetun.unsupported.type" $ -}}
{{- end -}}
@@ -0,0 +1,23 @@
{{/* https://github.com/qdm12/gluetun/wiki/VPN-Unlimited */}}
{{- define "gluetun.vpn unlimited.openvpn.validation" -}}
{{- $req := list -}}
{{- if eq .Values.gluetunConfig.openvpnCertKeyMethod "file" -}}
{{- $req = (list "openvpnCertHostPath" "openvpnKeyHostPath") -}}
{{- else if eq .Values.gluetunConfig.openvpnCertKeyMethod "content" -}}
{{- $req = (list "openvpnCert" "openvpnKey") -}}
{{- else -}}
{{- include "gluetun.certkey.required.error" $ -}}
{{- end -}}
{{- $req = concat $req (list "openvpnUser" "openvpnPassword") -}}
{{- $unsup := (list "serverNames") -}}
{{- include "gluetun.options.required" (dict "rootCtx" $ "options" $req) -}}
{{- include "gluetun.unsupported.server.options" (dict "rootCtx" $ "options" $unsup) -}}
{{- end -}}
{{- define "gluetun.vpn unlimited.wireguard.validation" -}}
{{- include "gluetun.unsupported.type" $ -}}
{{- end -}}
@@ -0,0 +1,13 @@
{{/* https://github.com/qdm12/gluetun/wiki/VyprVPN */}}
{{- define "gluetun.vyprvpn.openvpn.validation" -}}
{{- $req := (list "openvpnUser" "openvpnPassword") -}}
{{- $unsup := (list "serverCountries" "serverCities" "serverNames") -}}
{{- include "gluetun.options.required" (dict "rootCtx" $ "options" $req) -}}
{{- include "gluetun.unsupported.server.options" (dict "rootCtx" $ "options" $unsup) -}}
{{- end -}}
{{- define "gluetun.vyprvpn.wireguard.validation" -}}
{{- include "gluetun.unsupported.type" $ -}}
{{- end -}}
@@ -0,0 +1,23 @@
{{/* https://github.com/qdm12/gluetun/wiki/WeVPN */}}
{{- define "gluetun.wevpn.openvpn.validation" -}}
{{- $req := list -}}
{{- if eq .Values.gluetunConfig.openvpnCertKeyMethod "file" -}}
{{- $req = (list "openvpnKeyHostPath") -}}
{{- else if eq .Values.gluetunConfig.openvpnCertKeyMethod "content" -}}
{{- $req = (list "openvpnKey") -}}
{{- else -}}
{{- include "gluetun.certkey.required.error" $ -}}
{{- end -}}
{{- $req = concat $req (list "openvpnUser" "openvpnPassword") -}}
{{- $unsup := (list "serverRegions" "serverCountries" "serverNames") -}}
{{- include "gluetun.options.required" (dict "rootCtx" $ "options" $req) -}}
{{- include "gluetun.unsupported.server.options" (dict "rootCtx" $ "options" $unsup) -}}
{{- end -}}
{{- define "gluetun.wevpn.wireguard.validation" -}}
{{- include "gluetun.unsupported.type" $ -}}
{{- end -}}
@@ -0,0 +1,18 @@
{{/* https://github.com/qdm12/gluetun/wiki/Windscribe */}}
{{- define "gluetun.windscribe.openvpn.validation" -}}
{{- $req := (list "openvpnUser" "openvpnPassword") -}}
{{- $unsup := (list "serverCountries" "serverNames") -}}
{{- include "gluetun.options.required" (dict "rootCtx" $ "options" $req) -}}
{{- include "gluetun.unsupported.server.options" (dict "rootCtx" $ "options" $unsup) -}}
{{- end -}}
{{- define "gluetun.windscribe.wireguard.validation" -}}
{{- $req := (list "wireguardPrivateKey" "wireguardAddresses") -}}
{{- $unsup := (list "serverCountries" "serverNames") -}}
{{- include "gluetun.options.required" (dict "rootCtx" $ "options" $req) -}}
{{- include "gluetun.unsupported.server.options" (dict "rootCtx" $ "options" $unsup) -}}
{{- end -}}
@@ -0,0 +1 @@
{"filename": "values.yaml", "keys": ["image"]}
+26
View File
@@ -0,0 +1,26 @@
#!/usr/bin/python3
import json
import sys
from catalog_update.upgrade_strategy import semantic_versioning
def newer_mapping(image_tags):
key = list(image_tags.keys())[0]
version = semantic_versioning(image_tags[key])
if not version:
return {}
return {
'tags': {key: f'v{version}'},
'app_version': f'v{version}',
}
if __name__ == '__main__':
try:
versions_json = json.loads(sys.stdin.read())
except ValueError:
raise ValueError('Invalid json specified')
print(json.dumps(newer_mapping(versions_json)))
+3
View File
@@ -0,0 +1,3 @@
icon_url: https://raw.githubusercontent.com/qdm12/gluetun/master/title.svg
categories:
- vpn