blob: c74480f6f62c44f26c4f17ad3e5e4e780c231066 [file] [log] [blame]
Giorgi Lekveishvilib59b7c22024-04-03 22:17:50 +04001import (
2 "encoding/base64"
3)
4
Giorgi Lekveishvilie009a5d2024-01-05 14:10:11 +04005input: {
6 privateNetwork: {
7 hostname: string
8 username: string
9 ipSubnet: string // TODO(gio): use cidr type
10 }
gio9bd87ca2025-04-20 08:05:34 +040011 sshPrivateKey: string
giof55ab362025-04-11 17:48:17 +040012 controllerReplicaCount: int | *3
Giorgi Lekveishvilie009a5d2024-01-05 14:10:11 +040013}
14
gio9bd87ca2025-04-20 08:05:34 +040015name: "private-network"
Giorgi Lekveishvili08af67a2024-01-18 08:53:05 +040016namespace: "ingress-private"
17
gio7fbd4ad2024-08-27 10:06:39 +040018out: {
19 images: {
20 "ingress-nginx": {
gio9bd87ca2025-04-20 08:05:34 +040021 registry: "registry.k8s.io"
gio7fbd4ad2024-08-27 10:06:39 +040022 repository: "ingress-nginx"
gio9bd87ca2025-04-20 08:05:34 +040023 name: "controller"
24 tag: "v1.8.0"
gio7fbd4ad2024-08-27 10:06:39 +040025 pullPolicy: "IfNotPresent"
26 }
gio3cabc3e2024-10-06 18:37:27 +040027 nginx: {
28 repository: "library"
gio9bd87ca2025-04-20 08:05:34 +040029 name: "nginx"
30 tag: "1.27.1-alpine3.20-slim"
gio3cabc3e2024-10-06 18:37:27 +040031 pullPolicy: "IfNotPresent"
32 }
33 tailscale: {
gio7fbd4ad2024-08-27 10:06:39 +040034 repository: "tailscale"
gio9bd87ca2025-04-20 08:05:34 +040035 name: "tailscale"
36 tag: "v1.82.0"
gio7fbd4ad2024-08-27 10:06:39 +040037 pullPolicy: "IfNotPresent"
38 }
39 portAllocator: {
40 repository: "giolekva"
gio9bd87ca2025-04-20 08:05:34 +040041 name: "port-allocator"
42 tag: "latest"
gio7fbd4ad2024-08-27 10:06:39 +040043 pullPolicy: "Always"
44 }
Giorgi Lekveishvilie009a5d2024-01-05 14:10:11 +040045 }
Giorgi Lekveishvilie009a5d2024-01-05 14:10:11 +040046
gio7fbd4ad2024-08-27 10:06:39 +040047 charts: {
gio4557dc02024-10-04 19:29:25 +040048 "access-secrets": {
gio9bd87ca2025-04-20 08:05:34 +040049 kind: "GitRepository"
gio4557dc02024-10-04 19:29:25 +040050 address: "https://code.v1.dodo.cloud/helm-charts"
gio9bd87ca2025-04-20 08:05:34 +040051 branch: "main"
52 path: "charts/access-secrets"
gio4557dc02024-10-04 19:29:25 +040053 }
gio3cabc3e2024-10-06 18:37:27 +040054 service: {
gio9bd87ca2025-04-20 08:05:34 +040055 kind: "GitRepository"
gio3cabc3e2024-10-06 18:37:27 +040056 address: "https://code.v1.dodo.cloud/helm-charts"
gio9bd87ca2025-04-20 08:05:34 +040057 branch: "main"
58 path: "charts/service"
gio3cabc3e2024-10-06 18:37:27 +040059 }
gio7fbd4ad2024-08-27 10:06:39 +040060 "ingress-nginx": {
gio9bd87ca2025-04-20 08:05:34 +040061 kind: "GitRepository"
gio7fbd4ad2024-08-27 10:06:39 +040062 address: "https://code.v1.dodo.cloud/helm-charts"
gio9bd87ca2025-04-20 08:05:34 +040063 branch: "main"
64 path: "charts/ingress-nginx"
gio7fbd4ad2024-08-27 10:06:39 +040065 }
66 "tailscale-proxy": {
gio9bd87ca2025-04-20 08:05:34 +040067 kind: "GitRepository"
gio7fbd4ad2024-08-27 10:06:39 +040068 address: "https://code.v1.dodo.cloud/helm-charts"
gio9bd87ca2025-04-20 08:05:34 +040069 branch: "main"
70 path: "charts/tailscale-proxy"
gio7fbd4ad2024-08-27 10:06:39 +040071 }
72 portAllocator: {
gio9bd87ca2025-04-20 08:05:34 +040073 kind: "GitRepository"
gio7fbd4ad2024-08-27 10:06:39 +040074 address: "https://code.v1.dodo.cloud/helm-charts"
gio9bd87ca2025-04-20 08:05:34 +040075 branch: "main"
76 path: "charts/port-allocator"
gio7fbd4ad2024-08-27 10:06:39 +040077 }
gio3cabc3e2024-10-06 18:37:27 +040078 headscaleUser: {
gio9bd87ca2025-04-20 08:05:34 +040079 kind: "GitRepository"
gio3cabc3e2024-10-06 18:37:27 +040080 address: "https://code.v1.dodo.cloud/helm-charts"
gio9bd87ca2025-04-20 08:05:34 +040081 branch: "main"
82 path: "charts/headscale-user"
gio3cabc3e2024-10-06 18:37:27 +040083 }
Giorgi Lekveishvilie009a5d2024-01-05 14:10:11 +040084 }
Giorgi Lekveishvilie009a5d2024-01-05 14:10:11 +040085
gio7fbd4ad2024-08-27 10:06:39 +040086 _ingressPrivate: "\(global.id)-ingress-private"
gio7841f4f2024-07-26 19:53:49 +040087
gio7fbd4ad2024-08-27 10:06:39 +040088 helm: {
gio4557dc02024-10-04 19:29:25 +040089 "access-secrets": {
90 chart: charts["access-secrets"]
91 values: {
92 serviceAccountName: "default"
93 }
94 }
95 "access-secrets-nginx": {
96 chart: charts["access-secrets"]
97 values: {
98 serviceAccountName: "\(global.id)-nginx-private"
99 }
100 }
gio7fbd4ad2024-08-27 10:06:39 +0400101 "ingress-nginx": {
102 chart: charts["ingress-nginx"]
103 values: {
104 fullnameOverride: "\(global.id)-nginx-private"
105 controller: {
giof55ab362025-04-11 17:48:17 +0400106 replicaCount: input.controllerReplicaCount
107 updateStrategy: {
108 type: "RollingUpdate"
109 rollingUpdate: {
110 maxUnavailable: "30%"
111 }
112 }
gio7fbd4ad2024-08-27 10:06:39 +0400113 service: {
114 enabled: true
gio9bd87ca2025-04-20 08:05:34 +0400115 type: "LoadBalancer"
gio7fbd4ad2024-08-27 10:06:39 +0400116 annotations: {
117 "metallb.universe.tf/address-pool": _ingressPrivate
118 }
giof55ab362025-04-11 17:48:17 +0400119 extraPorts: {
120 tcp: {}
121 udp: {}
122 }
gio7fbd4ad2024-08-27 10:06:39 +0400123 }
124 ingressClassByName: true
125 ingressClassResource: {
gio9bd87ca2025-04-20 08:05:34 +0400126 name: _ingressPrivate
127 enabled: true
128 default: false
gio7fbd4ad2024-08-27 10:06:39 +0400129 controllerValue: "k8s.io/\(_ingressPrivate)"
130 }
131 config: {
gio9bd87ca2025-04-20 08:05:34 +0400132 "proxy-body-size": "200M" // TODO(giolekva): configurable
gio7fbd4ad2024-08-27 10:06:39 +0400133 "force-ssl-redirect": "true"
134 "server-snippet": """
135 more_clear_headers "X-Frame-Options";
136 """
137 }
138 extraArgs: {
139 "default-ssl-certificate": "\(_ingressPrivate)/cert-wildcard.\(global.privateDomain)"
140 }
gio3cabc3e2024-10-06 18:37:27 +0400141 extraVolumes: [{
142 name: _proxyBackendConfigName
143 configMap: {
144 name: _proxyBackendConfigName
145 }
giof55ab362025-04-11 17:48:17 +0400146 }, {
147 name: "proxy-backend-pid"
148 emptyDir: {
149 size: "2Mi"
150 }
151 }, {
152 name: "ts-proxy-state"
153 emptyDir: {
154 size: "2Mi"
155 }
gio3cabc3e2024-10-06 18:37:27 +0400156 }]
giof55ab362025-04-11 17:48:17 +0400157 shareProcessNamespace: true
gio3cabc3e2024-10-06 18:37:27 +0400158 extraContainers: [{
gio9bd87ca2025-04-20 08:05:34 +0400159 name: "proxy"
gio3cabc3e2024-10-06 18:37:27 +0400160 image: images.tailscale.fullNameWithTag
161 securityContext: {
162 capabilities: {
163 add: ["NET_ADMIN"]
164 }
165 privileged: true
166 }
167 env: [{
gio9bd87ca2025-04-20 08:05:34 +0400168 name: "TS_STATE_DIR"
giof55ab362025-04-11 17:48:17 +0400169 value: "/ts-state"
gio3cabc3e2024-10-06 18:37:27 +0400170 }, {
171 name: "TS_HOSTNAME"
giof55ab362025-04-11 17:48:17 +0400172 valueFrom: {
173 fieldRef: {
174 fieldPath: "metadata.name"
175 }
176 }
gio3cabc3e2024-10-06 18:37:27 +0400177 }, {
gio9bd87ca2025-04-20 08:05:34 +0400178 name: "TS_EXTRA_ARGS"
gio3cabc3e2024-10-06 18:37:27 +0400179 value: "--login-server=https://headscale.\(global.domain)"
180 }, {
gio9bd87ca2025-04-20 08:05:34 +0400181 name: "TS_USERSPACE"
gio3cabc3e2024-10-06 18:37:27 +0400182 value: "false"
183 }]
giof55ab362025-04-11 17:48:17 +0400184 command: ["/bin/sh"]
185 args: [
186 "-c",
gio9bd87ca2025-04-20 08:05:34 +0400187 "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",
188 ]
giof55ab362025-04-11 17:48:17 +0400189 volumeMounts: [{
190 mountPath: "/ts-state"
gio9bd87ca2025-04-20 08:05:34 +0400191 name: "ts-proxy-state"
192 readOnly: false
giof55ab362025-04-11 17:48:17 +0400193 }]
gio3cabc3e2024-10-06 18:37:27 +0400194 }, {
gio9bd87ca2025-04-20 08:05:34 +0400195 name: "proxy-backend"
196 image: images.nginx.fullNameWithTag
gio3cabc3e2024-10-06 18:37:27 +0400197 imagePullPolicy: images.nginx.pullPolicy
198 ports: [{
gio9bd87ca2025-04-20 08:05:34 +0400199 name: "proxy"
gio3cabc3e2024-10-06 18:37:27 +0400200 containerPort: 9090
gio9bd87ca2025-04-20 08:05:34 +0400201 protocol: "TCP"
gio3cabc3e2024-10-06 18:37:27 +0400202 }]
203 volumeMounts: [{
gio9bd87ca2025-04-20 08:05:34 +0400204 name: _proxyBackendConfigName
gio3cabc3e2024-10-06 18:37:27 +0400205 mountPath: "/etc/nginx"
gio9bd87ca2025-04-20 08:05:34 +0400206 readOnly: true
giof55ab362025-04-11 17:48:17 +0400207 }, {
gio9bd87ca2025-04-20 08:05:34 +0400208 name: "proxy-backend-pid"
giof55ab362025-04-11 17:48:17 +0400209 mountPath: "/var/run/nginx"
gio9bd87ca2025-04-20 08:05:34 +0400210 readOnly: false
gio3cabc3e2024-10-06 18:37:27 +0400211 }]
giof55ab362025-04-11 17:48:17 +0400212 }, {
gio9bd87ca2025-04-20 08:05:34 +0400213 name: "reload-config"
214 image: "giolekva/reload:latest"
giof55ab362025-04-11 17:48:17 +0400215 imagePullPolicy: "Always"
216 command: [
217 "/usr/bin/reload",
218 "--watch=/etc/nginx/nginx.conf",
219 "--reload=/var/run/nginx/nginx.pid",
gio9bd87ca2025-04-20 08:05:34 +0400220 ]
giof55ab362025-04-11 17:48:17 +0400221 volumeMounts: [{
gio9bd87ca2025-04-20 08:05:34 +0400222 name: "proxy-backend-config"
giof55ab362025-04-11 17:48:17 +0400223 mountPath: "/etc/nginx"
gio9bd87ca2025-04-20 08:05:34 +0400224 readOnly: true
giof55ab362025-04-11 17:48:17 +0400225 }, {
gio9bd87ca2025-04-20 08:05:34 +0400226 name: "proxy-backend-pid"
giof55ab362025-04-11 17:48:17 +0400227 mountPath: "/var/run/nginx"
gio9bd87ca2025-04-20 08:05:34 +0400228 readOnly: true
giof55ab362025-04-11 17:48:17 +0400229 }]
230 securityContext: {
231 capabilities: {
232 add: ["SYS_PTRACE"]
233 }
234 }
gio3cabc3e2024-10-06 18:37:27 +0400235 }]
gio7fbd4ad2024-08-27 10:06:39 +0400236 admissionWebhooks: {
237 enabled: false
238 }
239 image: {
gio9bd87ca2025-04-20 08:05:34 +0400240 registry: images["ingress-nginx"].registry
241 image: images["ingress-nginx"].imageName
242 tag: images["ingress-nginx"].tag
gio7fbd4ad2024-08-27 10:06:39 +0400243 pullPolicy: images["ingress-nginx"].pullPolicy
Giorgi Lekveishvilie009a5d2024-01-05 14:10:11 +0400244 }
245 }
gio7fbd4ad2024-08-27 10:06:39 +0400246 }
247 }
248 "tailscale-proxy": {
249 chart: charts["tailscale-proxy"]
250 values: {
gio9bd87ca2025-04-20 08:05:34 +0400251 hostname: input.privateNetwork.hostname
252 apiServer: "http://headscale-api.\(global.namespacePrefix)app-headscale.svc.cluster.local"
253 loginServer: "https://headscale.\(networks.public.domain)" // TODO(gio): take headscale subdomain from configuration
254 ipSubnet: input.privateNetwork.ipSubnet
255 username: input.privateNetwork.username // TODO(gio): maybe install headscale-user chart separately?
gio7fbd4ad2024-08-27 10:06:39 +0400256 preAuthKeySecret: "headscale-preauth-key"
Giorgi Lekveishvilie009a5d2024-01-05 14:10:11 +0400257 image: {
gio3cabc3e2024-10-06 18:37:27 +0400258 repository: images.tailscale.fullName
gio9bd87ca2025-04-20 08:05:34 +0400259 tag: images.tailscale.tag
gio3cabc3e2024-10-06 18:37:27 +0400260 pullPolicy: images.tailscale.pullPolicy
Giorgi Lekveishvilie009a5d2024-01-05 14:10:11 +0400261 }
262 }
263 }
gio7fbd4ad2024-08-27 10:06:39 +0400264 "port-allocator": {
265 chart: charts.portAllocator
266 values: {
gio9bd87ca2025-04-20 08:05:34 +0400267 repoAddr: release.repoAddr
268 sshPrivateKey: base64.Encode(null, input.sshPrivateKey)
gio7fbd4ad2024-08-27 10:06:39 +0400269 ingressNginxPath: "\(release.appDir)/resources/ingress-nginx.yaml"
270 image: {
271 repository: images.portAllocator.fullName
gio9bd87ca2025-04-20 08:05:34 +0400272 tag: images.portAllocator.tag
gio7fbd4ad2024-08-27 10:06:39 +0400273 pullPolicy: images.portAllocator.pullPolicy
274 }
Giorgi Lekveishvilib59b7c22024-04-03 22:17:50 +0400275 }
276 }
gio3cabc3e2024-10-06 18:37:27 +0400277 // TODO(gio): Generate proxy-backend-config as well
278 "proxy-backend-service": {
279 chart: charts.service
280 values: {
281 name: "proxy-backend-service"
282 type: "ClusterIP"
283 selector: {
284 "app.kubernetes.io/component": "controller"
gio9bd87ca2025-04-20 08:05:34 +0400285 "app.kubernetes.io/instance": "ingress-nginx"
286 "app.kubernetes.io/name": "ingress-nginx"
gio3cabc3e2024-10-06 18:37:27 +0400287 }
gio9bd87ca2025-04-20 08:05:34 +0400288 ports: [{
289 name: "http"
290 port: 80
gio3cabc3e2024-10-06 18:37:27 +0400291 targetPort: 9090
gio9bd87ca2025-04-20 08:05:34 +0400292 protocol: "TCP"
gio3cabc3e2024-10-06 18:37:27 +0400293 }]
294 }
295 }
Giorgi Lekveishvilib59b7c22024-04-03 22:17:50 +0400296 }
Giorgi Lekveishvilie009a5d2024-01-05 14:10:11 +0400297}
gio3cabc3e2024-10-06 18:37:27 +0400298resources: {
299 "proxy-backend-config": {
300 apiVersion: "v1"
gio9bd87ca2025-04-20 08:05:34 +0400301 kind: "ConfigMap"
gio3cabc3e2024-10-06 18:37:27 +0400302 metadata: {
gio9bd87ca2025-04-20 08:05:34 +0400303 name: "proxy-backend-config"
gio3cabc3e2024-10-06 18:37:27 +0400304 namespace: release.namespace
305 }
306 data: {
307 "nginx.conf": """
gio9bd87ca2025-04-20 08:05:34 +0400308 worker_processes 1;
309 worker_rlimit_nofile 8192;
310 pid /var/run/nginx/nginx.pid;
311 events {
312 worker_connections 1024;
313 }
314 http {
315 map $http_host $backend {
316 }
317 server {
318 listen 9090;
319 location / {
320 resolver 135.181.48.180;
321 proxy_pass http://$backend;
322 }
323 }
324 }
325 """
gio3cabc3e2024-10-06 18:37:27 +0400326 }
327 }
328}
329
gio3cabc3e2024-10-06 18:37:27 +0400330_proxyBackendConfigName: "proxy-backend-config"