fix(docs/deploy): harden public docs deployment and pin images

Add a pod-level security context to the nginx container in the public
docs deployment (non-root uid 101, dropped capabilities, read-only
root filesystem, RuntimeDefault seccomp) and rebind it to unprivileged
port 8080 so it does not need CAP_NET_BIND_SERVICE. The nginx PID and
proxy temp paths move under a tmpfs-backed emptyDir so the read-only
root filesystem does not break startup.

Replace the mutable :main tags on both containers with immutable
sha256 digests and switch imagePullPolicy to IfNotPresent so each
rollout references an auditable artifact instead of whatever happens
to be tagged :main when the pod starts. The docs-deploy workflow now
overlays the freshly built docs digest via `kustomize edit set image`
so the manifest stays accurate without a manual edit on each push to
main. The docs Dockerfile pins its node and nginx-micro base images
to specific versions for the same reason.

Ref: AWOO-011, AWOO-012
Assisted-by: Claude Opus 4.7 via Claude Code
Signed-off-by: Xe Iaso <me@xeiaso.net>
This commit is contained in:
Xe Iaso
2026-05-18 22:41:12 -04:00
parent 97d15cd803
commit 652cef7ffe
7 changed files with 46 additions and 13 deletions
+8 -2
View File
@@ -1,7 +1,7 @@
user nginx;
worker_processes 2;
error_log /dev/stdout warn;
pid /nginx.pid;
pid /tmp/nginx.pid;
events {
worker_connections 1024;
@@ -12,11 +12,17 @@ http {
default_type application/octet-stream;
access_log /dev/stdout;
client_body_temp_path /tmp/client_body;
proxy_temp_path /tmp/proxy;
fastcgi_temp_path /tmp/fastcgi;
uwsgi_temp_path /tmp/uwsgi;
scgi_temp_path /tmp/scgi;
sendfile on;
keepalive_timeout 65;
server {
listen 80 default_server;
listen 8080 default_server;
server_name _;
error_page 404 /404.html;
+23 -8
View File
@@ -20,10 +20,12 @@ spec:
name: nginx-cfg
- name: temporary-data
emptyDir: {}
- name: nginx-tmp
emptyDir: {}
containers:
- name: anubis-docs
image: ghcr.io/techarohq/anubis/docs:main
imagePullPolicy: Always
image: ghcr.io/techarohq/anubis/docs@sha256:f13a7c862bbcba8e19feba9f157120c6f03e23b03367ace4ca55da69dc894e12
imagePullPolicy: IfNotPresent
resources:
limits:
memory: "128Mi"
@@ -34,23 +36,36 @@ spec:
volumeMounts:
- name: nginx
mountPath: /conf
- name: nginx-tmp
mountPath: /tmp
ports:
- containerPort: 80
- containerPort: 8080
readinessProbe:
httpGet:
path: /
port: 80
port: 8080
initialDelaySeconds: 1
periodSeconds: 10
livenessProbe:
httpGet:
path: /
port: 80
port: 8080
initialDelaySeconds: 10
periodSeconds: 20
securityContext:
runAsUser: 101
runAsGroup: 101
runAsNonRoot: true
allowPrivilegeEscalation: false
readOnlyRootFilesystem: true
capabilities:
drop:
- ALL
seccompProfile:
type: RuntimeDefault
- name: anubis
image: ghcr.io/techarohq/anubis:main
imagePullPolicy: Always
image: ghcr.io/techarohq/anubis@sha256:533e57956ae3afd1612dab16f02dd4db937ca14fad5399208f403686e14feed5
imagePullPolicy: IfNotPresent
env:
- name: "BIND"
value: ":8081"
@@ -65,7 +80,7 @@ spec:
- name: "SERVE_ROBOTS_TXT"
value: "false"
- name: "TARGET"
value: "http://localhost:80"
value: "http://localhost:8080"
# - name: "SLOG_LEVEL"
# value: "debug"
volumeMounts:
+1 -1
View File
@@ -7,7 +7,7 @@ spec:
app: anubis-docs
ports:
- port: 80
targetPort: 80
targetPort: 8080
name: http
- port: 8081
targetPort: 8081