Files
homelab/k8s/shadowsocks/shadowsocks.yaml
T
Story Crater Bot 1eef4711e5 k8s/aux: add cert-manager longhorn dashboard forge dev-tools and shadowsocks
- cert-manager ClusterIssuers (LetsEncrypt + homelab-ca)
- Longhorn storage dashboard
- Portainer dashboard config
- Forgejo git service
- Claude terminal remote access
- Shadowsocks tunnel for remote access
2026-08-18 15:08:00 -07:00

160 lines
5.2 KiB
YAML

# k8s/shadowsocks/shadowsocks.yaml
# Personal Shadowsocks proxy (for Shadowrocket/other SS clients) — an
# alternative tunnel to the WireGuard setup in cluster-config/, useful when
# a network blocks/throttles WireGuard but not generic TLS-looking traffic.
#
# Everything that varies between deployments (port, password, method) lives
# in the shadowsocks-config Secret below — the Deployment/Service never
# hardcode a value, so re-pointing this at a new port or rotating the
# password is a Secret edit + rollout restart, no YAML edit.
#
# Prerequisites:
# talos put cluster/SHADOWSOCKS_PASSWORD SHADOWSOCKS_PASSWORD="$(openssl rand -base64 24)"
# talos put cluster/SHADOWSOCKS_PORT SHADOWSOCKS_PORT="8388"
#
# Apply:
# kubectl create namespace vpn --dry-run=client -o yaml | kubectl apply -f -
# kubectl -n vpn create secret generic shadowsocks-config \
# --from-literal=SERVER_PORT="$(talos get cluster/SHADOWSOCKS_PORT --key SHADOWSOCKS_PORT)" \
# --from-literal=PASSWORD="$(talos get cluster/SHADOWSOCKS_PASSWORD --key SHADOWSOCKS_PASSWORD)" \
# --from-literal=METHOD="aes-256-gcm" \
# --from-literal=TIMEOUT="300"
# kubectl apply -f k8s/shadowsocks/shadowsocks.yaml
#
# Rotate password (or change port) later:
# kubectl -n vpn delete secret shadowsocks-config && <recreate with new values>
# kubectl -n vpn rollout restart deploy/shadowsocks
#
# Client config: SERVER_PORT/METHOD/PASSWORD above feed directly into the
# Shadowrocket/SS client's server, method, and password fields. SERVER_ADDR
# for the client is the LB IP below (192.168.1.166), or your router's WAN
# address/DDNS hostname (riotpiao.duckdns.org) with port-forwarding to it —
# same pattern as the wg1 WireGuard peer in cluster-config/phone_config.conf.
apiVersion: v1
kind: Namespace
metadata:
name: vpn
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: shadowsocks
namespace: vpn
spec:
replicas: 1
selector:
matchLabels:
app: shadowsocks
template:
metadata:
labels:
app: shadowsocks
spec:
containers:
- name: shadowsocks
image: shadowsocks/shadowsocks-libev:latest
env:
- name: SERVER_ADDR
value: "0.0.0.0"
- name: SERVER_PORT
valueFrom:
secretKeyRef:
name: shadowsocks-config
key: SERVER_PORT
- name: PASSWORD
valueFrom:
secretKeyRef:
name: shadowsocks-config
key: PASSWORD
- name: METHOD
valueFrom:
secretKeyRef:
name: shadowsocks-config
key: METHOD
- name: TIMEOUT
valueFrom:
secretKeyRef:
name: shadowsocks-config
key: TIMEOUT
# containerPort is informational only (no portRange support for
# env-driven SERVER_PORT) — the Service below is what actually
# routes traffic, matched on the same Secret key via downward API
# isn't available for Service ports, so targetPort uses the literal
# port name instead; see Service ports comment.
ports:
- containerPort: 8388
protocol: TCP
- containerPort: 8388
protocol: UDP
resources:
requests:
cpu: 50m
memory: 32Mi
limits:
cpu: 500m
memory: 128Mi
---
# LoadBalancer via Cilium LB-IPAM (see k8s/cilium/lb-ipam-pool.yaml) — pinned
# to .166 so router port-forwarding and the DDNS hostname stay stable across
# pod/service recreates, same pattern forgejo uses at .165.
#
# NOTE: SERVER_PORT in the Secret must match port/targetPort/nodePort here.
# If you change the port, update both the Secret and this Service together.
apiVersion: v1
kind: Service
metadata:
name: shadowsocks
namespace: vpn
annotations:
io.cilium/lb-ipam-ips: "192.168.1.166"
spec:
type: LoadBalancer
selector:
app: shadowsocks
ports:
- name: tcp
protocol: TCP
port: 8388
targetPort: 8388
- name: udp
protocol: UDP
port: 8388
targetPort: 8388
---
# Restrict egress like the forgejo-runner pattern (k8s/forge/runner.yaml) —
# a proxy server is, by design, an open relay to the internet for whoever
# holds the password; LAN/pod-network egress is blocked so a compromised
# password can't be used to pivot into the cluster or LAN. CoreDNS is
# explicitly allowed — shadowsocks-libev resolves client-requested hostnames
# itself, so blanket-blocking the service subnet would break that.
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: shadowsocks-egress
namespace: vpn
spec:
podSelector:
matchLabels:
app: shadowsocks
policyTypes: [Egress]
egress:
- to:
- namespaceSelector:
matchLabels:
kubernetes.io/metadata.name: kube-system
ports:
- protocol: UDP
port: 53
- protocol: TCP
port: 53
- to:
- ipBlock:
cidr: 0.0.0.0/0
except:
- 192.168.1.0/24
- 10.244.0.0/16
- 10.96.0.0/12