blob: c74480f6f62c44f26c4f17ad3e5e4e780c231066 [file] [log] [blame]
import (
"encoding/base64"
)
input: {
privateNetwork: {
hostname: string
username: string
ipSubnet: string // TODO(gio): use cidr type
}
sshPrivateKey: string
controllerReplicaCount: int | *3
}
name: "private-network"
namespace: "ingress-private"
out: {
images: {
"ingress-nginx": {
registry: "registry.k8s.io"
repository: "ingress-nginx"
name: "controller"
tag: "v1.8.0"
pullPolicy: "IfNotPresent"
}
nginx: {
repository: "library"
name: "nginx"
tag: "1.27.1-alpine3.20-slim"
pullPolicy: "IfNotPresent"
}
tailscale: {
repository: "tailscale"
name: "tailscale"
tag: "v1.82.0"
pullPolicy: "IfNotPresent"
}
portAllocator: {
repository: "giolekva"
name: "port-allocator"
tag: "latest"
pullPolicy: "Always"
}
}
charts: {
"access-secrets": {
kind: "GitRepository"
address: "https://code.v1.dodo.cloud/helm-charts"
branch: "main"
path: "charts/access-secrets"
}
service: {
kind: "GitRepository"
address: "https://code.v1.dodo.cloud/helm-charts"
branch: "main"
path: "charts/service"
}
"ingress-nginx": {
kind: "GitRepository"
address: "https://code.v1.dodo.cloud/helm-charts"
branch: "main"
path: "charts/ingress-nginx"
}
"tailscale-proxy": {
kind: "GitRepository"
address: "https://code.v1.dodo.cloud/helm-charts"
branch: "main"
path: "charts/tailscale-proxy"
}
portAllocator: {
kind: "GitRepository"
address: "https://code.v1.dodo.cloud/helm-charts"
branch: "main"
path: "charts/port-allocator"
}
headscaleUser: {
kind: "GitRepository"
address: "https://code.v1.dodo.cloud/helm-charts"
branch: "main"
path: "charts/headscale-user"
}
}
_ingressPrivate: "\(global.id)-ingress-private"
helm: {
"access-secrets": {
chart: charts["access-secrets"]
values: {
serviceAccountName: "default"
}
}
"access-secrets-nginx": {
chart: charts["access-secrets"]
values: {
serviceAccountName: "\(global.id)-nginx-private"
}
}
"ingress-nginx": {
chart: charts["ingress-nginx"]
values: {
fullnameOverride: "\(global.id)-nginx-private"
controller: {
replicaCount: input.controllerReplicaCount
updateStrategy: {
type: "RollingUpdate"
rollingUpdate: {
maxUnavailable: "30%"
}
}
service: {
enabled: true
type: "LoadBalancer"
annotations: {
"metallb.universe.tf/address-pool": _ingressPrivate
}
extraPorts: {
tcp: {}
udp: {}
}
}
ingressClassByName: true
ingressClassResource: {
name: _ingressPrivate
enabled: true
default: false
controllerValue: "k8s.io/\(_ingressPrivate)"
}
config: {
"proxy-body-size": "200M" // TODO(giolekva): configurable
"force-ssl-redirect": "true"
"server-snippet": """
more_clear_headers "X-Frame-Options";
"""
}
extraArgs: {
"default-ssl-certificate": "\(_ingressPrivate)/cert-wildcard.\(global.privateDomain)"
}
extraVolumes: [{
name: _proxyBackendConfigName
configMap: {
name: _proxyBackendConfigName
}
}, {
name: "proxy-backend-pid"
emptyDir: {
size: "2Mi"
}
}, {
name: "ts-proxy-state"
emptyDir: {
size: "2Mi"
}
}]
shareProcessNamespace: true
extraContainers: [{
name: "proxy"
image: images.tailscale.fullNameWithTag
securityContext: {
capabilities: {
add: ["NET_ADMIN"]
}
privileged: true
}
env: [{
name: "TS_STATE_DIR"
value: "/ts-state"
}, {
name: "TS_HOSTNAME"
valueFrom: {
fieldRef: {
fieldPath: "metadata.name"
}
}
}, {
name: "TS_EXTRA_ARGS"
value: "--login-server=https://headscale.\(global.domain)"
}, {
name: "TS_USERSPACE"
value: "false"
}]
command: ["/bin/sh"]
args: [
"-c",
"TS_AUTHKEY=$(wget --post-data=\"\" -O /tmp/authkey http://headscale-api.\(global.namespacePrefix)app-headscale.svc.cluster.local/user/private-network-proxy/preauthkey > /dev/null 2>&1 && cat /tmp/authkey) /usr/local/bin/containerboot",
]
volumeMounts: [{
mountPath: "/ts-state"
name: "ts-proxy-state"
readOnly: false
}]
}, {
name: "proxy-backend"
image: images.nginx.fullNameWithTag
imagePullPolicy: images.nginx.pullPolicy
ports: [{
name: "proxy"
containerPort: 9090
protocol: "TCP"
}]
volumeMounts: [{
name: _proxyBackendConfigName
mountPath: "/etc/nginx"
readOnly: true
}, {
name: "proxy-backend-pid"
mountPath: "/var/run/nginx"
readOnly: false
}]
}, {
name: "reload-config"
image: "giolekva/reload:latest"
imagePullPolicy: "Always"
command: [
"/usr/bin/reload",
"--watch=/etc/nginx/nginx.conf",
"--reload=/var/run/nginx/nginx.pid",
]
volumeMounts: [{
name: "proxy-backend-config"
mountPath: "/etc/nginx"
readOnly: true
}, {
name: "proxy-backend-pid"
mountPath: "/var/run/nginx"
readOnly: true
}]
securityContext: {
capabilities: {
add: ["SYS_PTRACE"]
}
}
}]
admissionWebhooks: {
enabled: false
}
image: {
registry: images["ingress-nginx"].registry
image: images["ingress-nginx"].imageName
tag: images["ingress-nginx"].tag
pullPolicy: images["ingress-nginx"].pullPolicy
}
}
}
}
"tailscale-proxy": {
chart: charts["tailscale-proxy"]
values: {
hostname: input.privateNetwork.hostname
apiServer: "http://headscale-api.\(global.namespacePrefix)app-headscale.svc.cluster.local"
loginServer: "https://headscale.\(networks.public.domain)" // TODO(gio): take headscale subdomain from configuration
ipSubnet: input.privateNetwork.ipSubnet
username: input.privateNetwork.username // TODO(gio): maybe install headscale-user chart separately?
preAuthKeySecret: "headscale-preauth-key"
image: {
repository: images.tailscale.fullName
tag: images.tailscale.tag
pullPolicy: images.tailscale.pullPolicy
}
}
}
"port-allocator": {
chart: charts.portAllocator
values: {
repoAddr: release.repoAddr
sshPrivateKey: base64.Encode(null, input.sshPrivateKey)
ingressNginxPath: "\(release.appDir)/resources/ingress-nginx.yaml"
image: {
repository: images.portAllocator.fullName
tag: images.portAllocator.tag
pullPolicy: images.portAllocator.pullPolicy
}
}
}
// TODO(gio): Generate proxy-backend-config as well
"proxy-backend-service": {
chart: charts.service
values: {
name: "proxy-backend-service"
type: "ClusterIP"
selector: {
"app.kubernetes.io/component": "controller"
"app.kubernetes.io/instance": "ingress-nginx"
"app.kubernetes.io/name": "ingress-nginx"
}
ports: [{
name: "http"
port: 80
targetPort: 9090
protocol: "TCP"
}]
}
}
}
}
resources: {
"proxy-backend-config": {
apiVersion: "v1"
kind: "ConfigMap"
metadata: {
name: "proxy-backend-config"
namespace: release.namespace
}
data: {
"nginx.conf": """
worker_processes 1;
worker_rlimit_nofile 8192;
pid /var/run/nginx/nginx.pid;
events {
worker_connections 1024;
}
http {
map $http_host $backend {
}
server {
listen 9090;
location / {
resolver 135.181.48.180;
proxy_pass http://$backend;
}
}
}
"""
}
}
}
_proxyBackendConfigName: "proxy-backend-config"