Add K3s dev deployment setup for single-node VPS
Mirrors the prod deploy-k3s/ setup but runs all services in-cluster on a single node: PostgreSQL (replaces Neon), MinIO S3-compatible storage (replaces B2), Redis, API, worker, and admin. Includes fully automated setup scripts (00-init through 04-verify), server hardening (SSH, fail2ban, ufw), Let's Encrypt TLS via Traefik, network policies, RBAC, and security contexts matching prod. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
56
deploy-k3s-dev/manifests/ingress/ingress.yaml
Normal file
56
deploy-k3s-dev/manifests/ingress/ingress.yaml
Normal file
@@ -0,0 +1,56 @@
|
||||
# API Ingress — TLS via Let's Encrypt (default) or Cloudflare origin cert
|
||||
apiVersion: networking.k8s.io/v1
|
||||
kind: Ingress
|
||||
metadata:
|
||||
name: honeydue-api
|
||||
namespace: honeydue
|
||||
labels:
|
||||
app.kubernetes.io/part-of: honeydue
|
||||
annotations:
|
||||
# TLS_ANNOTATIONS_PLACEHOLDER — replaced by 03-deploy.sh based on tls.mode
|
||||
traefik.ingress.kubernetes.io/router.middlewares: honeydue-security-headers@kubernetescrd,honeydue-rate-limit@kubernetescrd
|
||||
spec:
|
||||
tls:
|
||||
- hosts:
|
||||
- API_DOMAIN_PLACEHOLDER
|
||||
secretName: TLS_SECRET_PLACEHOLDER
|
||||
rules:
|
||||
- host: API_DOMAIN_PLACEHOLDER
|
||||
http:
|
||||
paths:
|
||||
- path: /
|
||||
pathType: Prefix
|
||||
backend:
|
||||
service:
|
||||
name: api
|
||||
port:
|
||||
number: 8000
|
||||
|
||||
---
|
||||
# Admin Ingress
|
||||
apiVersion: networking.k8s.io/v1
|
||||
kind: Ingress
|
||||
metadata:
|
||||
name: honeydue-admin
|
||||
namespace: honeydue
|
||||
labels:
|
||||
app.kubernetes.io/part-of: honeydue
|
||||
annotations:
|
||||
# TLS_ANNOTATIONS_PLACEHOLDER — replaced by 03-deploy.sh based on tls.mode
|
||||
traefik.ingress.kubernetes.io/router.middlewares: honeydue-security-headers@kubernetescrd,honeydue-rate-limit@kubernetescrd,honeydue-admin-auth@kubernetescrd
|
||||
spec:
|
||||
tls:
|
||||
- hosts:
|
||||
- ADMIN_DOMAIN_PLACEHOLDER
|
||||
secretName: TLS_SECRET_PLACEHOLDER
|
||||
rules:
|
||||
- host: ADMIN_DOMAIN_PLACEHOLDER
|
||||
http:
|
||||
paths:
|
||||
- path: /
|
||||
pathType: Prefix
|
||||
backend:
|
||||
service:
|
||||
name: admin
|
||||
port:
|
||||
number: 3000
|
||||
45
deploy-k3s-dev/manifests/ingress/middleware.yaml
Normal file
45
deploy-k3s-dev/manifests/ingress/middleware.yaml
Normal file
@@ -0,0 +1,45 @@
|
||||
# Traefik CRD middleware for rate limiting
|
||||
apiVersion: traefik.io/v1alpha1
|
||||
kind: Middleware
|
||||
metadata:
|
||||
name: rate-limit
|
||||
namespace: honeydue
|
||||
spec:
|
||||
rateLimit:
|
||||
average: 100
|
||||
burst: 200
|
||||
period: 1m
|
||||
|
||||
---
|
||||
# Security headers
|
||||
apiVersion: traefik.io/v1alpha1
|
||||
kind: Middleware
|
||||
metadata:
|
||||
name: security-headers
|
||||
namespace: honeydue
|
||||
spec:
|
||||
headers:
|
||||
frameDeny: true
|
||||
contentTypeNosniff: true
|
||||
browserXssFilter: true
|
||||
referrerPolicy: "strict-origin-when-cross-origin"
|
||||
customResponseHeaders:
|
||||
X-Content-Type-Options: "nosniff"
|
||||
X-Frame-Options: "DENY"
|
||||
Strict-Transport-Security: "max-age=31536000; includeSubDomains"
|
||||
Content-Security-Policy: "default-src 'self'; frame-ancestors 'none'"
|
||||
Permissions-Policy: "camera=(), microphone=(), geolocation=()"
|
||||
X-Permitted-Cross-Domain-Policies: "none"
|
||||
|
||||
---
|
||||
# Admin basic auth — additional auth layer for admin panel
|
||||
# Secret created by 02-setup-secrets.sh from config.yaml credentials
|
||||
apiVersion: traefik.io/v1alpha1
|
||||
kind: Middleware
|
||||
metadata:
|
||||
name: admin-auth
|
||||
namespace: honeydue
|
||||
spec:
|
||||
basicAuth:
|
||||
secret: admin-basic-auth
|
||||
realm: "honeyDue Admin"
|
||||
Reference in New Issue
Block a user