- gitea-web/gitea-sshd ClusterIP services: the chart's gitea-http/ssh are HEADLESS (pod IP 100.64.x) which COLLIDES with the Tailscale CGNAT range 100.64.0.0/10, so the tailscale-sidecar proxy swallowed the traffic. ClusterIP (10.32.x) fixes it. - tailscale-proxy: nginx git.fxhnt.ai -> gitea-web:3000; socat :22 -> gitea-sshd:22 (drop :2222, GitLab); GitLab webservice/registry blocks left for Task 4/2C. - dns git_ip -> 100.95.225.27 (live proxy node); stale 100.90.76.85 duplicate A records removed across api/chat/dashboard/git/grafana/mail/minio (were causing platform-wide flakiness). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
353 lines
11 KiB
YAML
353 lines
11 KiB
YAML
---
|
|
apiVersion: v1
|
|
kind: ServiceAccount
|
|
metadata:
|
|
name: tailscale-gitlab
|
|
namespace: foxhunt
|
|
---
|
|
apiVersion: rbac.authorization.k8s.io/v1
|
|
kind: Role
|
|
metadata:
|
|
name: tailscale-gitlab
|
|
namespace: foxhunt
|
|
rules:
|
|
- apiGroups: [""]
|
|
resources: ["secrets"]
|
|
verbs: ["create", "get", "update", "patch"]
|
|
---
|
|
apiVersion: rbac.authorization.k8s.io/v1
|
|
kind: RoleBinding
|
|
metadata:
|
|
name: tailscale-gitlab
|
|
namespace: foxhunt
|
|
subjects:
|
|
- kind: ServiceAccount
|
|
name: tailscale-gitlab
|
|
namespace: foxhunt
|
|
roleRef:
|
|
kind: Role
|
|
name: tailscale-gitlab
|
|
apiGroup: rbac.authorization.k8s.io
|
|
---
|
|
apiVersion: apps/v1
|
|
kind: Deployment
|
|
metadata:
|
|
name: tailscale-gitlab-proxy
|
|
namespace: foxhunt
|
|
labels:
|
|
app.kubernetes.io/name: tailscale-gitlab-proxy
|
|
app.kubernetes.io/part-of: foxhunt
|
|
spec:
|
|
replicas: 1
|
|
strategy:
|
|
type: Recreate
|
|
selector:
|
|
matchLabels:
|
|
app.kubernetes.io/name: tailscale-gitlab-proxy
|
|
template:
|
|
metadata:
|
|
labels:
|
|
app.kubernetes.io/name: tailscale-gitlab-proxy
|
|
spec:
|
|
serviceAccountName: tailscale-gitlab
|
|
nodeSelector:
|
|
k8s.scaleway.com/pool-name: platform
|
|
containers:
|
|
- name: nginx
|
|
image: nginx:alpine
|
|
ports:
|
|
- containerPort: 80
|
|
- containerPort: 443
|
|
- containerPort: 5050
|
|
volumeMounts:
|
|
- name: nginx-conf
|
|
mountPath: /etc/nginx/conf.d
|
|
- name: tls-certs
|
|
mountPath: /etc/nginx/certs
|
|
readOnly: true
|
|
resources:
|
|
requests:
|
|
cpu: 25m
|
|
memory: 32Mi
|
|
limits:
|
|
cpu: 100m
|
|
memory: 64Mi
|
|
- name: ssh-proxy
|
|
image: alpine/socat:latest
|
|
args:
|
|
- "TCP-LISTEN:22,fork,reuseaddr,sndbuf=1048576,rcvbuf=1048576"
|
|
- "TCP:gitea-sshd.foxhunt.svc.cluster.local:22,sndbuf=1048576,rcvbuf=1048576"
|
|
ports:
|
|
- containerPort: 22
|
|
resources:
|
|
requests:
|
|
cpu: 25m
|
|
memory: 64Mi
|
|
limits:
|
|
cpu: 200m
|
|
memory: 128Mi
|
|
- name: imap-proxy
|
|
image: alpine/socat:latest
|
|
args:
|
|
- "TCP-LISTEN:993,fork,reuseaddr"
|
|
- "TCP:stalwart.foxhunt.svc.cluster.local:993"
|
|
ports:
|
|
- containerPort: 993
|
|
resources:
|
|
requests:
|
|
cpu: 10m
|
|
memory: 16Mi
|
|
limits:
|
|
cpu: 50m
|
|
memory: 32Mi
|
|
- name: tailscale
|
|
image: ghcr.io/tailscale/tailscale:latest
|
|
env:
|
|
- name: TS_AUTHKEY
|
|
valueFrom:
|
|
secretKeyRef:
|
|
name: tailscale-auth
|
|
key: TS_AUTHKEY
|
|
- name: TS_KUBE_SECRET
|
|
value: tailscale-gitlab-state
|
|
- name: TS_USERSPACE
|
|
value: "false"
|
|
- name: TS_HOSTNAME
|
|
value: "foxhunt-gitlab"
|
|
- name: TS_ACCEPT_DNS
|
|
value: "false"
|
|
- name: TS_EXTRA_ARGS
|
|
value: ""
|
|
resources:
|
|
requests:
|
|
cpu: 25m
|
|
memory: 32Mi
|
|
limits:
|
|
cpu: 100m
|
|
memory: 64Mi
|
|
securityContext:
|
|
capabilities:
|
|
add:
|
|
- NET_ADMIN
|
|
- NET_RAW
|
|
volumes:
|
|
- name: nginx-conf
|
|
configMap:
|
|
name: tailscale-gitlab-nginx
|
|
- name: tls-certs
|
|
secret:
|
|
secretName: gitlab-tls-cert
|
|
---
|
|
apiVersion: v1
|
|
kind: ConfigMap
|
|
metadata:
|
|
name: tailscale-gitlab-nginx
|
|
namespace: foxhunt
|
|
data:
|
|
default.conf: |
|
|
# HTTP → HTTPS redirect for all subdomains
|
|
server {
|
|
listen 80;
|
|
server_name *.fxhnt.ai;
|
|
return 301 https://$host$request_uri;
|
|
}
|
|
|
|
# Gitea — git.fxhnt.ai (replaced GitLab, Phase 2B cutover)
|
|
server {
|
|
listen 443 ssl;
|
|
server_name git.fxhnt.ai;
|
|
|
|
ssl_certificate /etc/nginx/certs/tls.crt;
|
|
ssl_certificate_key /etc/nginx/certs/tls.key;
|
|
ssl_protocols TLSv1.2 TLSv1.3;
|
|
|
|
client_max_body_size 0;
|
|
|
|
location / {
|
|
proxy_pass http://gitea-web.foxhunt.svc.cluster.local:3000;
|
|
proxy_set_header Host $http_host;
|
|
proxy_set_header X-Real-IP $remote_addr;
|
|
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
|
proxy_set_header X-Forwarded-Proto https;
|
|
|
|
proxy_buffering off;
|
|
proxy_request_buffering off;
|
|
proxy_http_version 1.1;
|
|
proxy_read_timeout 3600s;
|
|
proxy_send_timeout 3600s;
|
|
proxy_connect_timeout 300s;
|
|
}
|
|
}
|
|
|
|
# Container Registry — git.fxhnt.ai:5050
|
|
server {
|
|
listen 5050 ssl;
|
|
server_name git.fxhnt.ai;
|
|
|
|
ssl_certificate /etc/nginx/certs/tls.crt;
|
|
ssl_certificate_key /etc/nginx/certs/tls.key;
|
|
ssl_protocols TLSv1.2 TLSv1.3;
|
|
|
|
client_max_body_size 0;
|
|
|
|
location / {
|
|
proxy_pass http://gitlab-registry.foxhunt.svc.cluster.local:5000;
|
|
proxy_set_header Host $http_host;
|
|
proxy_set_header X-Real-IP $remote_addr;
|
|
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
|
proxy_set_header X-Forwarded-Proto https;
|
|
|
|
proxy_buffering off;
|
|
proxy_request_buffering off;
|
|
proxy_http_version 1.1;
|
|
proxy_read_timeout 3600s;
|
|
proxy_send_timeout 3600s;
|
|
}
|
|
}
|
|
|
|
# Grafana — grafana.fxhnt.ai
|
|
server {
|
|
listen 443 ssl;
|
|
server_name grafana.fxhnt.ai;
|
|
|
|
ssl_certificate /etc/nginx/certs/tls.crt;
|
|
ssl_certificate_key /etc/nginx/certs/tls.key;
|
|
ssl_protocols TLSv1.2 TLSv1.3;
|
|
|
|
location / {
|
|
proxy_pass http://grafana.foxhunt.svc.cluster.local:80;
|
|
proxy_set_header Host $http_host;
|
|
proxy_set_header X-Real-IP $remote_addr;
|
|
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
|
proxy_set_header X-Forwarded-Proto https;
|
|
proxy_http_version 1.1;
|
|
proxy_set_header Upgrade $http_upgrade;
|
|
proxy_set_header Connection "upgrade";
|
|
}
|
|
}
|
|
|
|
# fxhnt cockpit — dashboard.fxhnt.ai
|
|
# Proxies to the cockpit's Tailscale node (peer-to-peer over the tailnet) rather than the cluster Service:
|
|
# the pod CIDR 100.64.0.0/15 overlaps Tailscale CGNAT, so this kernel-mode proxy can't reach platform-pool
|
|
# pods via ClusterIP, but it CAN reach another tailnet node. IP is stable while the cockpit's TS state
|
|
# secret (fxhnt-dashboard-ts-state) persists. (Was web-dashboard.foxhunt.svc — replaced by the fxhnt cockpit.)
|
|
server {
|
|
listen 443 ssl;
|
|
server_name dashboard.fxhnt.ai;
|
|
|
|
ssl_certificate /etc/nginx/certs/tls.crt;
|
|
ssl_certificate_key /etc/nginx/certs/tls.key;
|
|
ssl_protocols TLSv1.2 TLSv1.3;
|
|
|
|
location / {
|
|
proxy_pass http://100.81.150.18:80; # fxhnt-dashboard tailnet node (TCP:80 -> cockpit :8080)
|
|
proxy_set_header Host $http_host;
|
|
proxy_set_header X-Real-IP $remote_addr;
|
|
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
|
proxy_set_header X-Forwarded-Proto https;
|
|
proxy_http_version 1.1;
|
|
proxy_set_header Upgrade $http_upgrade;
|
|
proxy_set_header Connection "upgrade";
|
|
}
|
|
}
|
|
|
|
# API Gateway (gRPC-Web + gRPC) — api.fxhnt.ai
|
|
# Browser dashboard uses gRPC-web (HTTP/1.1 POST), so proxy_pass not grpc_pass
|
|
server {
|
|
listen 443 ssl;
|
|
http2 on;
|
|
server_name api.fxhnt.ai;
|
|
|
|
ssl_certificate /etc/nginx/certs/tls.crt;
|
|
ssl_certificate_key /etc/nginx/certs/tls.key;
|
|
ssl_protocols TLSv1.2 TLSv1.3;
|
|
|
|
location / {
|
|
proxy_pass http://api.foxhunt.svc.cluster.local:50051;
|
|
proxy_set_header Host $http_host;
|
|
proxy_set_header X-Real-IP $remote_addr;
|
|
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
|
proxy_set_header X-Forwarded-Proto https;
|
|
proxy_http_version 1.1;
|
|
proxy_read_timeout 3600s;
|
|
proxy_send_timeout 3600s;
|
|
proxy_connect_timeout 30s;
|
|
}
|
|
}
|
|
|
|
# Stalwart Admin — mail.fxhnt.ai
|
|
server {
|
|
listen 443 ssl;
|
|
server_name mail.fxhnt.ai;
|
|
|
|
ssl_certificate /etc/nginx/certs/tls.crt;
|
|
ssl_certificate_key /etc/nginx/certs/tls.key;
|
|
ssl_protocols TLSv1.2 TLSv1.3;
|
|
|
|
location / {
|
|
proxy_pass https://stalwart.foxhunt.svc.cluster.local:443;
|
|
proxy_set_header Host $http_host;
|
|
proxy_set_header X-Real-IP $remote_addr;
|
|
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
|
proxy_set_header X-Forwarded-Proto https;
|
|
proxy_http_version 1.1;
|
|
proxy_ssl_verify off;
|
|
}
|
|
}
|
|
|
|
# Mattermost — chat.fxhnt.ai
|
|
server {
|
|
listen 443 ssl;
|
|
server_name chat.fxhnt.ai;
|
|
|
|
ssl_certificate /etc/nginx/certs/tls.crt;
|
|
ssl_certificate_key /etc/nginx/certs/tls.key;
|
|
ssl_protocols TLSv1.2 TLSv1.3;
|
|
|
|
client_max_body_size 50m;
|
|
|
|
location / {
|
|
proxy_pass http://mattermost.foxhunt.svc.cluster.local:8065;
|
|
proxy_set_header Host $http_host;
|
|
proxy_set_header X-Real-IP $remote_addr;
|
|
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
|
proxy_set_header X-Forwarded-Proto https;
|
|
proxy_http_version 1.1;
|
|
proxy_set_header Upgrade $http_upgrade;
|
|
proxy_set_header Connection "upgrade";
|
|
proxy_read_timeout 3600s;
|
|
proxy_send_timeout 3600s;
|
|
}
|
|
}
|
|
|
|
# MinIO S3 API — minio.fxhnt.ai
|
|
server {
|
|
listen 443 ssl;
|
|
server_name minio.fxhnt.ai;
|
|
|
|
ssl_certificate /etc/nginx/certs/tls.crt;
|
|
ssl_certificate_key /etc/nginx/certs/tls.key;
|
|
ssl_protocols TLSv1.2 TLSv1.3;
|
|
|
|
client_max_body_size 0;
|
|
|
|
location / {
|
|
proxy_pass http://minio.foxhunt.svc.cluster.local:9000;
|
|
proxy_set_header Host $http_host;
|
|
proxy_set_header X-Real-IP $remote_addr;
|
|
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
|
proxy_set_header X-Forwarded-Proto https;
|
|
|
|
proxy_buffering off;
|
|
proxy_request_buffering off;
|
|
proxy_http_version 1.1;
|
|
proxy_read_timeout 3600s;
|
|
proxy_send_timeout 3600s;
|
|
proxy_connect_timeout 300s;
|
|
|
|
# MinIO uses self-signed TLS internally
|
|
proxy_ssl_verify off;
|
|
}
|
|
}
|
|
|