Investigation: UIS Distribution Architecture
Purpose: Design a new distribution model for UIS that allows users to install and update without forking the repo or editing core files.
Status: Completed
Goal: Design a container-based distribution model for UIS.
Created: 2026-01-22 Completed: 2026-02-18
Priority: High (foundational for product scalability)
Decision: Container-as-Deliverable - The UIS product is delivered as a container image, not a zip file. Users only need to provide their topsecret/ folder (secrets + config).
Completed: PLAN-003 implemented minimal container delivery:
- Container image published to
ghcr.io/terchris/uis-provision-host:latest - Size reduced from 2.7GB to 1.86GB
./uiswrapper script with auto-pull from registry- CI/CD pipeline for multi-arch builds (amd64/arm64)
- Branded welcome page for nginx catch-all
Next Action: Implement full orchestration system (Phase 1-6 below).
Related Plans:
- PLAN-003-minimal-container-delivery.md - ✅ Complete
- PLAN-004-uis-orchestration-system.md - ✅ Complete
- PLAN-002-json-generator.md - Complete
Problem Statement
Current Model (Fork & Edit)
- Users fork the entire repository
- Users edit files directly (move from
not-in-use/, modify configs) - Updates require git pull and merge conflicts
- Works for creator/power users, not scalable for product
Desired Model (Install & Configure)
- CI/CD creates distributable package
- Users install via simple command
- Users customize via config files (never edit core files)
- Updates via
uis-updatecommand - Parallel to existing system during development
Investigation Questions
1. Distribution Package
- What files should be included in the distribution? → Container image with baked-in files
- What files should be excluded (website, docs, dev tools)? → website/, docs/, .devcontainer/, .git/
- What is the package format (zip, tar.gz)? → Container image (not zip)
- Where is the package hosted (GitHub releases)? → Container registry: ghcr.io/sovereignsky/uis-provision-host
2. User Customization
- Where does the user customization folder live? →
topsecret/config/for config,topsecret/secrets-config/for secrets - What is the structure of
enabled-services.conf? → One SCRIPT_ID per line (like DCT) - How do users override service configurations (Helm values, manifests)? →
topsecret/config/service-overrides/ - How do users add their own custom services? →
topsecret/config/custom-manifests/
3. Service Enable/Disable
- How does config-driven enable/disable work? → Read enabled-services.conf, match against SCRIPT_ID
- What happens to
not-in-use/folders? → Keep for old system; new system ignores file location - Should all services be in the package (enabled via config)? → Yes, all in container, enabled via config
- Or should there be "core" vs "optional" services? → No distinction - all config-driven
4. Update Mechanism
- How does
uis-updatework? →docker pullnew image; user config in mounts preserved - How are user customizations preserved during update? → Mounts stay on host, image gets replaced
- How is version tracked? → Container image tags +
.versionfile inside container - What about breaking changes between versions? → TBD during implementation
5. Provision-Host Integration
- How does the new system integrate with provision-host container? → UIS IS the container
- What paths are mounted into the container? →
topsecret/→/mnt/urbalurbadisk/topsecret/ - How does
uis-setup.sh(wrapper on host) call into provision-host? →docker exectouis-cli.sh
6. Migration Path
- How do existing users migrate to new system? → TBD (Phase 6)
- Can both systems coexist during transition? → Yes, container includes both orchestration systems
- What documentation is needed? → TBD (Phase 6)
Reference: DCT Architecture
Distribution
CI/CD creates: dev_containers.zip
├── .devcontainer/ # Product (never edited by user)
│ ├── additions/
│ ├── manage/
│ ├── devcontainer.json
│ └── .version
User Customization
.devcontainer.extend/ # User customization (persisted)
├── enabled-tools.conf # Which tools to install
├── enabled-services.conf # Which services to start
└── project-installs.sh # Custom project setup
Update Flow
dev-update
# 1. Downloads latest zip from GitHub releases
# 2. Extracts to temp folder
# 3. Replaces .devcontainer/ (preserves .devcontainer.extend/)
# 4. Records version in .devcontainer/.version
# 5. Prompts rebuild if devcontainer.json changed
Key DCT Files to Study
.devcontainer/manage/dev-update.sh- Update mechanism.devcontainer/manage/dev-setup.sh- Interactive menu.devcontainer.extend/enabled-tools.conf- Config-driven installation.devcontainer/additions/lib/component-scanner.sh- Metadata discovery
Proposed UIS Architecture: Container-as-Deliverable
Key Decision: The UIS product is delivered as a container image, not a zip file. The repository structure stays as-is. CI/CD builds a container with everything inside. Users only need their
topsecret/folder locally (config + secrets).
Container Image Contents
ghcr.io/sovereignsky/uis-provision-host:1.0.0
│
├── /mnt/urbalurbadisk/ # UIS product (baked into image) - SAME PATH AS TODAY
│ ├── ansible/ # Playbooks
│ ├── manifests/ # K8s manifests
│ ├── hosts/ # Cluster setup scripts
│ ├── cloud-init/ # VM templates
│ ├── networking/ # Network scripts
│ ├── provision-host/
│ │ ├── kubernetes/ # Existing orchestration (unchanged)
│ │ └── uis/ # NEW orchestration (to be built)
│ │ ├── lib/
│ │ ├── manage/
│ │ └── services/
│ ├── topsecret/ # Mount point - user's folder overlays this
│ │ └── secrets-templates/ # Base templates (baked in)
│ ├── scripts/
│ └── .version
│
└── (tools: ansible, kubectl, helm, az, tailscale, etc.)
User's Local Folder
my-project/
├── topsecret/ # User's folder (mounted into container)
│ ├── secrets-templates/ # Can override templates (optional)
│ ├── secrets-config/ # User-edited secret values (required)
│ │ └── 00-common-values.env
│ ├── secrets-generated/ # Temp processing
│ ├── kubernetes/ # Generated K8s secrets
│ └── config/ # NEW - user config files
│ ├── enabled-services.conf # Which services to deploy
│ ├── cluster-config.sh # Cluster type, project name, domain
│ └── service-overrides/ # Per-service customization (optional)
│
└── (user's own project files...)
What's In Container vs Local
Note: Current system uses
docker cpto copy files. New model uses mounts instead.
| Location | Contents | New Model |
|---|---|---|
Container /mnt/urbalurbadisk/ | UIS product (ansible, manifests, scripts) | Baked in |
Local topsecret/ → /mnt/urbalurbadisk/topsecret/ | User config + secrets | Mounted |
Local ~/.kube/ → /home/ansible/.kube/ | Kubernetes config | Mounted (ro) |