add DocuSeal to GKE — manifests, Terraform, Argo CD app; update ci-base Dockerfile

This commit is contained in:
Will Anderson
2026-05-05 10:38:45 -05:00
parent 73b9095d83
commit 086a7b0bf0
8 changed files with 291 additions and 1 deletions
+68
View File
@@ -0,0 +1,68 @@
# ── DocuSeal GKE service account and Workload Identity ───────────────────────
# DocuSeal runs in the `docuseal` namespace on GKE. It accesses GCP Secret
# Manager via Workload Identity — no JSON key files.
#
# Secret flow: Vault → GCP Secret Manager → ExternalSecret → k8s Secret → pod
resource "google_service_account" "docuseal_gke" {
account_id = "docuseal-gke"
display_name = "DocuSeal GKE"
description = "Identity for DocuSeal pod on GKE. Accesses Secret Manager via Workload Identity."
project = var.project_id
}
# ── Secret Manager access ─────────────────────────────────────────────────────
resource "google_secret_manager_secret_iam_member" "docuseal_secret_key_base" {
project = var.project_id
secret_id = "docuseal-secret-key-base"
role = "roles/secretmanager.secretAccessor"
member = "serviceAccount:${google_service_account.docuseal_gke.email}"
}
resource "google_secret_manager_secret_iam_member" "docuseal_smtp_host" {
project = var.project_id
secret_id = "docuseal-smtp-host"
role = "roles/secretmanager.secretAccessor"
member = "serviceAccount:${google_service_account.docuseal_gke.email}"
}
resource "google_secret_manager_secret_iam_member" "docuseal_smtp_port" {
project = var.project_id
secret_id = "docuseal-smtp-port"
role = "roles/secretmanager.secretAccessor"
member = "serviceAccount:${google_service_account.docuseal_gke.email}"
}
resource "google_secret_manager_secret_iam_member" "docuseal_smtp_username" {
project = var.project_id
secret_id = "docuseal-smtp-username"
role = "roles/secretmanager.secretAccessor"
member = "serviceAccount:${google_service_account.docuseal_gke.email}"
}
resource "google_secret_manager_secret_iam_member" "docuseal_smtp_password" {
project = var.project_id
secret_id = "docuseal-smtp-password"
role = "roles/secretmanager.secretAccessor"
member = "serviceAccount:${google_service_account.docuseal_gke.email}"
}
resource "google_secret_manager_secret_iam_member" "docuseal_smtp_from" {
project = var.project_id
secret_id = "docuseal-smtp-from"
role = "roles/secretmanager.secretAccessor"
member = "serviceAccount:${google_service_account.docuseal_gke.email}"
}
# ── Workload Identity binding ─────────────────────────────────────────────────
# The k8s SA `docuseal` in the `docuseal` namespace can impersonate this GCP SA.
# ESO uses this to authenticate to Secret Manager without a key file.
resource "google_service_account_iam_member" "docuseal_workload_identity" {
service_account_id = google_service_account.docuseal_gke.name
role = "roles/iam.workloadIdentityUser"
member = "serviceAccount:${var.project_id}.svc.id.goog[docuseal/docuseal]"
depends_on = [google_container_cluster.neuron_platform]
}
@@ -0,0 +1,26 @@
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: docuseal-gke
namespace: argocd
spec:
project: default
source:
repoURL: https://git.neuralplatform.ai/will/infrastructure.git
targetRevision: main
path: servers/gcp/k8s/docuseal
destination:
server: https://34.63.89.52
namespace: docuseal
ignoreDifferences:
- group: apps
kind: Deployment
jsonPointers:
- /status
syncPolicy:
automated:
prune: true
selfHeal: true
syncOptions:
- CreateNamespace=true
- ServerSideApply=true
+101
View File
@@ -0,0 +1,101 @@
apiVersion: apps/v1
kind: Deployment
metadata:
name: docuseal
namespace: docuseal
labels:
app: docuseal
spec:
replicas: 1
# Recreate — only one pod can hold the RWO PVC at a time.
strategy:
type: Recreate
selector:
matchLabels:
app: docuseal
template:
metadata:
labels:
app: docuseal
spec:
serviceAccountName: docuseal
containers:
- name: docuseal
image: ee.docuseal.com/lip5viwf/ds-ee:latest
ports:
- containerPort: 3000
env:
- name: SECRET_KEY_BASE
valueFrom:
secretKeyRef:
name: docuseal-secrets
key: secret_key_base
- name: FORCE_SSL
value: "false"
- name: HOST
value: "sign.neurontechnologies.ai"
- name: SMTP_ADDRESS
valueFrom:
secretKeyRef:
name: docuseal-secrets
key: smtp_host
- name: SMTP_PORT
valueFrom:
secretKeyRef:
name: docuseal-secrets
key: smtp_port
- name: SMTP_USERNAME
valueFrom:
secretKeyRef:
name: docuseal-secrets
key: smtp_username
- name: SMTP_PASSWORD
valueFrom:
secretKeyRef:
name: docuseal-secrets
key: smtp_password
- name: SMTP_FROM
valueFrom:
secretKeyRef:
name: docuseal-secrets
key: smtp_from
volumeMounts:
- name: data
mountPath: /data
readinessProbe:
httpGet:
path: /
port: 3000
initialDelaySeconds: 15
periodSeconds: 10
resources:
requests:
cpu: 100m
memory: 256Mi
limits:
cpu: 500m
memory: 512Mi
volumes:
- name: data
persistentVolumeClaim:
claimName: docuseal-data
---
apiVersion: v1
kind: Service
metadata:
name: docuseal
namespace: docuseal
annotations:
# External GCP Network LB — Cloudflare proxies in front, provides TLS.
# After provisioning, get the external IP:
# kubectl -n docuseal get svc docuseal
# Update Cloudflare DNS A record for sign.neurontechnologies.ai to this IP.
cloud.google.com/load-balancer-type: "External"
spec:
selector:
app: docuseal
ports:
- name: http
port: 80
targetPort: 3000
type: LoadBalancer
@@ -0,0 +1,56 @@
---
# SecretStore for GKE — uses GCP Secret Manager directly via Workload Identity.
# The DocuSeal GCP SA has secretmanager.secretAccessor on its own secrets
# (see servers/gcp/docuseal.tf).
apiVersion: external-secrets.io/v1
kind: SecretStore
metadata:
name: gcp-secretmanager
namespace: docuseal
spec:
provider:
gcpsm:
projectID: neuron-785695
# Workload Identity — ESO impersonates the docuseal-gke GCP SA to access
# Secret Manager. No JSON key file required.
auth:
workloadIdentity:
clusterLocation: us-central1
clusterName: neuron-platform
serviceAccountRef:
name: docuseal
namespace: docuseal
---
# Pull all DocuSeal secrets from GCP Secret Manager into a single k8s Secret.
apiVersion: external-secrets.io/v1
kind: ExternalSecret
metadata:
name: docuseal-secrets
namespace: docuseal
spec:
refreshInterval: 1h
secretStoreRef:
name: gcp-secretmanager
kind: SecretStore
target:
name: docuseal-secrets
creationPolicy: Owner
data:
- secretKey: secret_key_base
remoteRef:
key: docuseal-secret-key-base
- secretKey: smtp_host
remoteRef:
key: docuseal-smtp-host
- secretKey: smtp_port
remoteRef:
key: docuseal-smtp-port
- secretKey: smtp_username
remoteRef:
key: docuseal-smtp-username
- secretKey: smtp_password
remoteRef:
key: docuseal-smtp-password
- secretKey: smtp_from
remoteRef:
key: docuseal-smtp-from
+6
View File
@@ -0,0 +1,6 @@
apiVersion: v1
kind: Namespace
metadata:
name: docuseal
labels:
app.kubernetes.io/name: docuseal
+12
View File
@@ -0,0 +1,12 @@
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: docuseal-data
namespace: docuseal
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 5Gi
storageClassName: standard-rwo
@@ -0,0 +1,10 @@
apiVersion: v1
kind: ServiceAccount
metadata:
name: docuseal
namespace: docuseal
annotations:
# Workload Identity — allows ESO to authenticate to GCP Secret Manager
# as the docuseal-gke GCP SA without a JSON key file.
# The GCP SA binding is in servers/gcp/docuseal.tf (docuseal_workload_identity).
iam.gke.io/gcp-service-account: docuseal-gke@neuron-785695.iam.gserviceaccount.com
+12 -1
View File
@@ -6,7 +6,7 @@ ENV DEBIAN_FRONTEND=noninteractive
COPY --from=runner-bin /bin/forgejo-runner /usr/local/bin/act_runner
# Core system tools
# Core system tools + C build deps needed by El compiler and other CI jobs
RUN apt-get update && apt-get install -y --no-install-recommends \
ca-certificates \
curl \
@@ -27,8 +27,19 @@ RUN apt-get update && apt-get install -y --no-install-recommends \
pkg-config \
software-properties-common \
zstd \
sudo \
libcurl4-openssl-dev \
libssl-dev \
libsqlite3-dev \
libpq-dev \
libffi-dev \
zlib1g-dev \
dpkg-dev \
&& rm -rf /var/lib/apt/lists/*
# Allow any user to run sudo without a password (CI containers need apt-get etc.)
RUN echo "ALL ALL=(ALL) NOPASSWD:ALL" >> /etc/sudoers
# Node.js 20 LTS via binary tarball (nodesource apt repo is unreliable on Ubuntu 24.04)
RUN NODE_VERSION=20.19.1 \
&& curl -fsSL "https://nodejs.org/dist/v${NODE_VERSION}/node-v${NODE_VERSION}-linux-x64.tar.xz" \