- build chain: project, Gitea basic-auth source secret, output ImageStream, BuildConfig (Docker strategy, ubuntu:24.04 base), optional base-image ImageStream and Docker Hub pull secret - runtime: ServiceAccount + least-privilege SCC and its RoleBinding (VShell needs UID 0), PVC for config/certificate, Deployment with ImageStream trigger, ClusterIP Service, passthrough HTTPS Route - all manifests verified with 'oc create --dry-run=client' against the OpenShift 4.22 client scheme (12/12 decode cleanly)
OpenShift manifests for VShell
Everything needed to build vshell:latest inside an OpenShift project and, if you
want, to run it there. Write-tested against the OpenShift 4.22 client scheme and
matching the 4.21 cluster described in /workspace/openshift-win11/FINDINGS.md.
Build (required)
| File | What it does |
|---|---|
00-namespace.yaml |
Project vshell. |
01-gitea-source-secret.yaml |
kubernetes.io/basic-auth secret for the private Gitea repo. |
02-vshell-imagestream.yaml |
Output ImageStream/vshell (latest). |
03-buildconfig.yaml |
BuildConfig/vshell — Docker strategy, git source, ubuntu:24.04 base. |
04-base-imagestream.yaml |
Optional: keep the Ubuntu base inside the cluster instead of pulling Docker Hub on every build. |
05-dockerhub-pull-secret.yaml |
Optional: Docker Hub credentials so base pulls are not rate limited. |
oc apply -f 00-namespace.yaml
# password = the Gitea token from ~/.dsh/AGENTS.md (do not commit it into 01-*.yaml)
oc create secret generic gitea-vshell-source -n vshell \
--type=kubernetes.io/basic-auth \
--from-literal=username=mward4 \
--from-literal=password=<gitea-token>
oc apply -f 02-vshell-imagestream.yaml
oc apply -f 03-buildconfig.yaml
oc start-build vshell -n vshell --follow
oc get is vshell -n vshell
The repository vendors the vendor .deb, so the build pod only needs egress to
gitea.milesward.dev, registry-1.docker.io and archive.ubuntu.com
(apt-get install openssl). Air-gapped clusters: import ubuntu:24.04 with
04-base-imagestream.yaml, point strategy.dockerStrategy.from at
ImageStreamTag ubuntu:24.04, and add an internal apt mirror.
replicas: 1 is not a build concern but a runtime one: the daemons own fixed
ports and a single host key, so never scale the Deployment.
Runtime (optional)
| File | What it does |
|---|---|
runtime/00-serviceaccount.yaml |
ServiceAccount/vshell. |
runtime/01-scc.yaml |
Least-privilege SCC that allows UID 0 + Role/RoleBinding so only this SA may use it. |
runtime/02-pvc.yaml |
PersistentVolumeClaim/vshell-data for config + TLS certificate. |
runtime/03-deployment.yaml |
Deployment, auto-updated by the image.openshift.io/triggers annotation. |
runtime/04-service.yaml |
ClusterIP service for ports 22/21/990/80/443. |
runtime/05-route.yaml |
HTTPS Route, passthrough termination. |
oc apply -f runtime/
oc get route vshell-https -n vshell
restricted-v2 forbids UID 0, so the SCC (or oc adm policy add-scc-to-user anyuid -z vshell -n vshell)
is required — VShell reads /etc/shadow through PAM, writes /var/run/*.pid
and creates root-owned host keys. The custom SCC grants no extra capabilities
and no host access.
The Route is passthrough because vshell-httpsd terminates TLS itself with the
PKCS#12 certificate the entrypoint generated; clients therefore see a
self-signed certificate until you mount a real one at $VSHELL_TLS_P12. SSH
(22), explicit FTPS (21) and implicit FTPS (990) cannot go through a Route —
expose the Service with a NodePort/LoadBalancer or an external load balancer.
The Deployment points VSHELL_CONFIG and VSHELL_TLS_P12 at the PVC-mounted
/data, which keeps the vendor defaults and the HttpsFiles/ web assets
visible. The SSH host key stays at /usr/local/etc/vshelld_hostkey unless you
set HostKeyFilenames /data/vshelld_hostkey in the generated config.
Caveats
- Builds run as root inside the build pod by default, which the Dockerfile's
apt-getanddpkg -ineed. Unprivileged builds (BUILD_PRIVILEGED=false) are an opt-in Developer Preview feature and would break this Dockerfile. - VShell runs under its 60-day evaluation license (expires 2026-12-04) until a
license file is mounted and
LicenseFilePathis set. - The image and repository are private because VShell is commercial software distributed under the VanDyke Software EULA.