diff --git a/library/ix-dev/community/tailscale/Chart.lock b/library/ix-dev/community/tailscale/Chart.lock new file mode 100644 index 0000000000..5d130ffb66 --- /dev/null +++ b/library/ix-dev/community/tailscale/Chart.lock @@ -0,0 +1,6 @@ +dependencies: +- name: common + repository: file://../../../common + version: 1.0.5 +digest: sha256:cf1db8c2ae650987a3e3d8d98767caab62c341bd0fb15309213b00dce87111cc +generated: "2023-04-17T12:58:28.51235027+03:00" diff --git a/library/ix-dev/community/tailscale/Chart.yaml b/library/ix-dev/community/tailscale/Chart.yaml new file mode 100644 index 0000000000..882880a95e --- /dev/null +++ b/library/ix-dev/community/tailscale/Chart.yaml @@ -0,0 +1,25 @@ +name: tailscale +description: Secure remote access to shared resources +annotations: + title: Tailscale +type: application +version: 1.0.0 +apiVersion: v2 +appVersion: 'v1.38.4' +kubeVersion: '>=1.16.0-0' +maintainers: + - name: truenas + url: https://www.truenas.com/ +dependencies: + - name: common + repository: file://../../../common + version: 1.0.5 +home: https://tailscale.com/ +icon: https://avatars.githubusercontent.com/u/48932923 +sources: + - https://tailscale.com/ + - https://github.com/truenas/charts/tree/master/community/tailscale + - https://hub.docker.com/r/tailscale/tailscale +keywords: + - vpn + - tailscale diff --git a/library/ix-dev/community/tailscale/README.md b/library/ix-dev/community/tailscale/README.md new file mode 100644 index 0000000000..0421cf0b16 --- /dev/null +++ b/library/ix-dev/community/tailscale/README.md @@ -0,0 +1,6 @@ +# Tailscale + +[Tailscale](https://tailscale.com) Secure remote access to shared resources + +- When `Userspace` is **disabled**, `Tailscale` will run as root, with `/dev/net/tun` device mounted from the host. +- When `Userspace` is **enabled**, `Tailscale` will run as a non-root user. diff --git a/library/ix-dev/community/tailscale/app-readme.md b/library/ix-dev/community/tailscale/app-readme.md new file mode 100644 index 0000000000..0421cf0b16 --- /dev/null +++ b/library/ix-dev/community/tailscale/app-readme.md @@ -0,0 +1,6 @@ +# Tailscale + +[Tailscale](https://tailscale.com) Secure remote access to shared resources + +- When `Userspace` is **disabled**, `Tailscale` will run as root, with `/dev/net/tun` device mounted from the host. +- When `Userspace` is **enabled**, `Tailscale` will run as a non-root user. diff --git a/library/ix-dev/community/tailscale/charts/common-1.0.5.tgz b/library/ix-dev/community/tailscale/charts/common-1.0.5.tgz new file mode 100644 index 0000000000..7e5b3b8a5a Binary files /dev/null and b/library/ix-dev/community/tailscale/charts/common-1.0.5.tgz differ diff --git a/library/ix-dev/community/tailscale/ci/basic-values.yaml b/library/ix-dev/community/tailscale/ci/basic-values.yaml new file mode 100644 index 0000000000..f6f337ee92 --- /dev/null +++ b/library/ix-dev/community/tailscale/ci/basic-values.yaml @@ -0,0 +1,20 @@ +# FIXME: Find a way to have a test key for CI testing +tailscaleConfig: + authkey: 'tskey-auth-abcd123CNTRL-abcde12345abcde12345abcde12345ab' + hostname: 'test-host' + advertiseExitNode: true + userspace: true + acceptDns: true + +workload: + tailscale: + podSpec: + containers: + tailscale: + probes: + liveness: + enabled: false + readiness: + enabled: false + startup: + enabled: false diff --git a/library/ix-dev/community/tailscale/item.yaml b/library/ix-dev/community/tailscale/item.yaml new file mode 100644 index 0000000000..960030f450 --- /dev/null +++ b/library/ix-dev/community/tailscale/item.yaml @@ -0,0 +1,4 @@ +icon_url: https://avatars.githubusercontent.com/u/48932923 +categories: + - vpn + - tailscale diff --git a/library/ix-dev/community/tailscale/questions.yaml b/library/ix-dev/community/tailscale/questions.yaml new file mode 100644 index 0000000000..46f0f3fb23 --- /dev/null +++ b/library/ix-dev/community/tailscale/questions.yaml @@ -0,0 +1,158 @@ +groups: + - name: Tailscale Configuration + description: Configure Tailscale + - name: Network Configuration + description: Configure Network for Tailscale + - name: Resources Configuration + description: Configure Resources for Tailscale + +questions: + - variable: tailscaleConfig + label: "" + group: Tailscale Configuration + schema: + type: dict + attrs: + - variable: authkey + label: Auth Key + description: | + The auth key for Tailscale.
+ Same as `--authkey` flag. + schema: + type: string + default: "" + required: true + private: true + - variable: hostname + label: Hostname + description: | + The hostname for Tailscale Node.
+ Only lowercase letters, numbers, and hyphens are allowed.
+ Same as `--hostname` flag. + schema: + type: string + default: "truenas-scale" + required: true + - variable: advertiseRoutes + label: Advertise Routes + description: | + The routes to advertise.
+ Same as `--advertise-routes` flag. + schema: + type: list + default: [] + items: + - variable: routeEntry + label: Route + schema: + type: string + required: true + - variable: advertiseExitNode + label: Advertise Exit Node + description: | + Advertise as Exit Node.
+ Same as `--advertise-exit-node` flag. + schema: + type: boolean + default: false + - variable: userspace + label: Userspace + description: Userspace for Tailscale. + schema: + type: boolean + default: true + - variable: acceptDns + label: Accept DNS + description: | + Accept DNS.
+ Same as `--accept-dns` flag. + schema: + type: boolean + default: false + - variable: extraArgs + label: Extra Arguments + description: Extra arguments for Tailscale. + schema: + type: list + default: [] + items: + - variable: argEntry + label: Argument + schema: + type: string + required: true + - variable: extraDaemonArgs + label: Extra Daemon Arguments + description: Extra arguments for Tailscale daemon. + schema: + type: list + default: [] + items: + - variable: DaemonArgEntry + label: Daemon Argument + schema: + type: string + required: true + + - variable: additionalEnvs + label: Additional Environment Variables + description: Configure additional environment variables for Tailscale. + 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: tailscaleNetwork + label: "" + group: Network Configuration + schema: + type: dict + attrs: + - variable: hostNetwork + label: Host Network + description: | + Bind to the host network. It's recommended to keep this disabled.
+ schema: + type: boolean + default: false + + - variable: resources + group: Resources Configuration + label: "" + schema: + type: dict + attrs: + - variable: limits + label: Limits + schema: + type: dict + attrs: + - variable: cpu + label: CPU + description: CPU limit for Tailscale. + schema: + type: string + default: "4000m" + required: true + - variable: memory + label: Memory + description: Memory limit for Tailscale. + schema: + type: string + default: "8Gi" + required: true diff --git a/library/ix-dev/community/tailscale/templates/NOTES.txt b/library/ix-dev/community/tailscale/templates/NOTES.txt new file mode 100644 index 0000000000..ba4e01146c --- /dev/null +++ b/library/ix-dev/community/tailscale/templates/NOTES.txt @@ -0,0 +1 @@ +{{ include "ix.v1.common.lib.chart.notes" $ }} diff --git a/library/ix-dev/community/tailscale/templates/_helper.tpl b/library/ix-dev/community/tailscale/templates/_helper.tpl new file mode 100644 index 0000000000..a9855045e9 --- /dev/null +++ b/library/ix-dev/community/tailscale/templates/_helper.tpl @@ -0,0 +1,32 @@ +{{- define "tailscale.args" -}} + {{- $args := list -}} + + {{- with .Values.tailscaleConfig.hostname -}} + {{- $args = mustAppend $args (printf "--hostname %v" .) -}} + {{- end -}} + + {{- with .Values.tailscaleConfig.advertiseExitNode -}} + {{- $args = mustAppend $args "--advertise-exit-node" -}} + {{- end -}} + + {{- with .Values.tailscaleConfig.extraArgs -}} + {{- $args = mustAppend $args . -}} + {{- end -}} + + {{- if $args -}} + {{- $args | join " " -}} + {{- end -}} +{{- end -}} + +{{- define "tailscale.validation" -}} + {{- if not .Values.tailscaleConfig.authkey -}} + {{- fail "Tailscale - Expected non-empty [Auth Key]" -}} + {{- end -}} + + {{- with .Values.tailscaleConfig.hostname -}} + {{- if not (mustRegexMatch "^[a-z0-9-]+$" .) -}} + {{- fail "Tailscale - Expected [Hostname] to match the following - [All lowercase, numbers, dashes, No spaces, No underscores]" -}} + {{- end -}} + {{- end -}} + +{{- end -}} diff --git a/library/ix-dev/community/tailscale/templates/_tailscale.tpl b/library/ix-dev/community/tailscale/templates/_tailscale.tpl new file mode 100644 index 0000000000..2157ed1352 --- /dev/null +++ b/library/ix-dev/community/tailscale/templates/_tailscale.tpl @@ -0,0 +1,138 @@ +{{- define "tailscale.workload" -}} +{{ include "tailscale.validation" $ }} +workload: + tailscale: + enabled: true + primary: true + type: Deployment + podSpec: + automountServiceAccountToken: true + hostNetwork: {{ .Values.tailscaleNetwork.hostNetwork }} + sysctls: + - name: net.ipv4.ip_forward + value: "1" + - name: net.ipv6.conf.all.forwarding + value: "1" + containers: + tailscale: + enabled: true + primary: true + imageSelector: image + command: /usr/local/bin/containerboot + securityContext: + {{ if .Values.tailscaleConfig.userspace }} + runAsUser: 568 + runAsGroup: 568 + {{ else }} + runAsUser: 0 + runAsGroup: 0 + runAsNonRoot: false + {{ end }} + readOnlyRootFilesystem: false + capabilities: + add: + - NET_ADMIN + - NET_RAW + env: + TS_KUBE_SECRET: {{ printf "%s-tailscale-secret" (include "ix.v1.common.lib.chart.names.fullname" .) }} + TS_SOCKET: /var/run/tailscale/tailscaled.sock + TS_USERSPACE: {{ .Values.tailscaleConfig.userspace | quote }} + TS_ACCEPT_DNS: {{ .Values.tailscaleConfig.acceptDns | quote }} + {{ with .Values.tailscaleConfig.advertiseRoutes }} + TS_ROUTES: {{ join "," . }} + {{ end }} + {{ with (include "tailscale.args" $) }} + TS_EXTRA_ARGS: {{ . }} + {{ end }} + {{ with .Values.tailscaleConfig.extraDaemonArgs }} + TS_TAILSCALED_ARGS: {{ join " " . }} + {{ end }} + {{ with .Values.tailscaleConfig.additionalEnvs }} + envList: + {{ range $env := . }} + - name: {{ $env.name }} + value: {{ $env.value }} + {{ end }} + {{ end }} + probes: + liveness: + enabled: true + type: exec + command: + - tailscale + - status + readiness: + enabled: true + type: exec + command: + - tailscale + - status + startup: + enabled: true + type: exec + command: + - tailscale + - status + +{{/* RBAC */}} +serviceAccount: + tailscale: + enabled: true + primary: true + +rbac: + tailscale: + enabled: true + primary: true + rules: + - apiGroups: + - "" + resources: + - secrets + verbs: + - create + - apiGroups: + - "" + resources: + - secrets + resourceNames: + - {{ printf "%s-tailscale-secret" (include "ix.v1.common.lib.chart.names.fullname" .) }} + verbs: + - get + - update + - patch + +{{/* Persistence */}} +persistence: + tun-dev: + enabled: {{ not .Values.tailscaleConfig.userspace }} + type: device + hostPath: /dev/net/tun + targetSelector: + tailscale: + tailscale: + mountPath: /dev/net/tun + var-run: + enabled: true + type: emptyDir + targetSelector: + tailscale: + tailscale: + mountPath: /var/run + cache: + enabled: true + type: emptyDir + targetSelector: + tailscale: + tailscale: + mountPath: /.cache + +{{/* Secret */}} +secret: + tailscale-secret: + enabled: true + data: + {{/* Name "authkey" must not be changed, it's what tailscale looks for */}} + authkey: {{ .Values.tailscaleConfig.authkey }} + +{{- end -}} diff --git a/library/ix-dev/community/tailscale/templates/common.yaml b/library/ix-dev/community/tailscale/templates/common.yaml new file mode 100644 index 0000000000..7f46c93af7 --- /dev/null +++ b/library/ix-dev/community/tailscale/templates/common.yaml @@ -0,0 +1,6 @@ +{{- include "ix.v1.common.loader.init" . -}} + +{{/* Merge the templates with Values */}} +{{- $_ := mustMergeOverwrite .Values (include "tailscale.workload" $ | fromYaml) -}} + +{{- include "ix.v1.common.loader.apply" . -}} diff --git a/library/ix-dev/community/tailscale/upgrade_info.json b/library/ix-dev/community/tailscale/upgrade_info.json new file mode 100644 index 0000000000..767388094a --- /dev/null +++ b/library/ix-dev/community/tailscale/upgrade_info.json @@ -0,0 +1 @@ +{"filename": "values.yaml", "keys": ["image"]} diff --git a/library/ix-dev/community/tailscale/upgrade_strategy b/library/ix-dev/community/tailscale/upgrade_strategy new file mode 100644 index 0000000000..3455360789 --- /dev/null +++ b/library/ix-dev/community/tailscale/upgrade_strategy @@ -0,0 +1,31 @@ +#!/usr/bin/python3 +import json +import re +import sys + +from catalog_update.upgrade_strategy import semantic_versioning + +# Minor part of version is considered "stable" when it is an even number +RE_STABLE_VERSION = re.compile(r'[0-9]+\.[0-9]+[02468]+\.[0-9]+') + + +def newer_mapping(image_tags): + key = list(image_tags.keys())[0] + tags = {t: t for t in image_tags[key] if RE_STABLE_VERSION.fullmatch(t)} + version = semantic_versioning(list(tags)) + if not version: + return {} + + return { + 'tags': {key: tags[version]}, + 'app_version': 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))) diff --git a/library/ix-dev/community/tailscale/values.yaml b/library/ix-dev/community/tailscale/values.yaml new file mode 100644 index 0000000000..7f5640fb54 --- /dev/null +++ b/library/ix-dev/community/tailscale/values.yaml @@ -0,0 +1,23 @@ +image: + repository: tailscale/tailscale + pullPolicy: IfNotPresent + tag: 'v1.38.4' + +resources: + limits: + cpu: 4000m + memory: 8Gi + +tailscaleConfig: + authkey: '' + hostname: '' + advertiseRoutes: [] + advertiseExitNode: false + userspace: true + acceptDns: false + extraArgs: [] + extraDaemonArgs: [] + additionalEnvs: [] + +tailscaleNetwork: + hostNetwork: false