Skip to content

2026-02-14-kasm-mount-orchestration-decisions

2026-02-14 — Kasm + Mount Orchestration Decisions

Section titled “2026-02-14 — Kasm + Mount Orchestration Decisions”

Investigating how components 3.4 (Filesystem Composition) and 3.5 (Mount Orchestrator) from ARCHITECTURE_COMPONENTS concretely integrate with Kasm Workspaces. This is the hardest part of the architecture to visualize working in practice.

Key Discovery: Kasm Has Native Mount Primitives

Section titled “Key Discovery: Kasm Has Native Mount Primitives”

Kasm Workspaces provides three mechanisms that cover most of what a Mount Orchestrator would do:

  • First-class feature for attaching Docker volumes to session containers
  • Can be placed on User, Group, or Workspace objects
  • Kasm merges all mappings from user + groups + workspace at session launch
  • Variable substitution: {username}, {user_id}, {image_id}
  • Read-only enforcement available at group level
  • Volumes created at session start, destroyed at termination
  • JSON blob on Workspace definition, passed to Docker Container.run() API
  • Mirrors Docker SDK for Python kwargs — can inject arbitrary bind mounts
  • Supports {username} and {user_id} substitution
  • Limitation: per-Workspace only, not per-User or per-Group
  • Useful for static mounts all users of a workspace share (e.g., wiki)
  • Runs commands inside container at lifecycle points: first_launch, go, assign
  • Cannot add bind mounts (those are Docker-level, set at creation)
  • CAN: generate .obsidian/ config, write sync daemon config, symlink/reorganize

Pattern A: Kasm-Native (No Custom Orchestrator)

Section titled “Pattern A: Kasm-Native (No Custom Orchestrator)”
Admin Setup (one-time):
1. Create Storage Provider → "Host Path" type
2. Per group: create Storage Mappings
- Group "engineering" → /shared/engineering → /vault/engineering (rw)
- Group "all-employees" → /shared/wiki → /vault/wiki (ro)
3. Per user template: /users/{username}/personal → /vault/personal
4. Docker Exec Config: startup script auto-discovers mounts, configures Obsidian + sync
Runtime:
User SSO → Kasm resolves groups → merges Storage Mappings → container launches → first_launch configures

Pros: No custom service. RBAC in Kasm admin UI. Group membership = vault permissions. Cons: Manual admin work per new folder. No compound rules. Startup script must introspect mounts.

Pattern B: Custom Mount Orchestrator + Kasm API

Section titled “Pattern B: Custom Mount Orchestrator + Kasm API”
Runtime:
User SSO → Kasm creates session → webhook/API to Orchestrator
→ Orchestrator reads JWT + vault-permissions.yaml
→ Generates Docker run config with exact bind mounts
→ Calls Kasm API to set session-specific config
→ Container launches → Exec Config finalizes config

Pros: Full programmatic control. Single source of truth (vault-permissions.yaml). Complex rules. Cons: Custom service to build. Kasm API may not support per-session config injection.

  • POC: Docker Run Config Override for static mounts + {username} for personal
  • Team Pilot: Group-based Storage Mappings for department folders
  • Enterprise: Add Orchestrator if group-based hits limits

DECISION-PENDING-003: Mount Integration Strategy

Build the custom orchestrator but ALSO test Kasm-native Storage Mappings to understand their limits empirically. Rationale:

  1. We’ll need the orchestrator eventually for compound rules (see below)
  2. Testing Kasm-native first gives us a fallback and baseline
  3. The orchestrator’s permission logic is useful even if Kasm handles the mount injection
  4. Understanding Kasm’s native limits lets us scope the orchestrator correctly

Compound Rules: Why Kasm Groups Aren’t Enough

Section titled “Compound Rules: Why Kasm Groups Aren’t Enough”

Kasm’s native model: user is in group → gets these mounts (purely additive/union).

Enterprise access patterns require intersection (compound rules), not just union. Real examples:

Where Compound Rules Exist in Enterprise AD/NTFS

Section titled “Where Compound Rules Exist in Enterprise AD/NTFS”
ScenarioRuleWhy Union Fails
M&A deal roomslegal AND executiveEither group alone shouldn’t have access
Departmental HRHR AND specific-departmentHR sees eng HR files, not marketing HR files
Compliance/auditauditors AND regional-scopeAuditor can audit EMEA, not APAC
Project escalationproject-team AND financeBudget/contracts need both memberships
Cross-functionalproject-group AND departmentOnly dept members assigned to that project
Client vaultsexternal-consultant AND engagement-scopeScoped to their engagement only
  • NTFS ACLs support compound expressions — an ACE can require membership in multiple groups
  • AD nested groups express hierarchy — project-alpha-admins contains engineering-leads
  • AD dynamic groups (Azure AD) use attribute-based rules — department == "legal" AND title contains "VP"
  • Conditional Access Policies (Azure AD) layer additional conditions (location, device, time)

Docker bind mounts are binary: mounted or not. No ACL granularity. The orchestrator must evaluate compound rules BEFORE mount time and translate the result to a flat list of mounts. This is the core job of component 3.5.

When Kasm-Native Breaks Down (Tipping Points)

Section titled “When Kasm-Native Breaks Down (Tipping Points)”
  1. > 5 shared folders with mixed read/write permissions — need separate groups per access level per folder
  2. Same folder, different access levels — wiki-editors (rw) vs wiki-readers (ro) requires two groups that must not overlap
  3. Non-admin users need to manage access — Kasm requires admin UI changes
  4. AD groups don’t map 1:1 to vault folders — almost every real org; need translation layer
  5. Temporal access — contractor access windows, project lifecycles
  6. Derived permissions — access to project-alpha implies access to project-alpha-resources

Proposed vault-permissions.yaml Extension for Compound Rules

Section titled “Proposed vault-permissions.yaml Extension for Compound Rules”
folders:
- name: engineering
path: /shared/engineering
access:
- groups: [engineering]
mode: rw
- groups: [all-employees]
mode: ro
- name: deal-room-acme
path: /shared/deals/acme
access:
- groups: [legal, executive] # AND — must be in BOTH
mode: rw
compound: all # "all" = AND, "any" = OR (default)
- name: hr-engineering
path: /shared/hr/engineering
access:
- groups: [hr, engineering]
compound: all
mode: rw
- groups: [hr]
mode: ro # HR can read all dept HR, but edit only their dept
- name: wiki
path: /shared/wiki
access:
- groups: [wiki-editors]
mode: rw
- groups: [all-employees]
mode: ro

The EXDEV cross-mount problem (Linux rename() fails across filesystem boundaries) exists regardless of how mounts get created. Whether Kasm Storage Mappings or a custom orchestrator injects bind mounts, /vault/engineering and /vault/marketing are separate mount points.

The shim lives in the sync daemon or Obsidian plugin, inside the container. It’s completely independent of Kasm. The container startup script (first_launch) ensures it’s active.

NeedKasm ProvidesCustom Code Needed
Per-user personal folder{username} variable in Storage MappingNone
Group-based shared foldersGroup-level Storage MappingsAdmin setup only
Read-only enforcementGroup setting read_only_user_storage_mappingsNone
Composite vault assemblyMerges User + Group + Workspace mappingsNone
.obsidian/ config generationExec Config (first_launch hook)Startup shell script
Sync daemon room configExec Config (first_launch hook)Startup shell script
EXDEV cross-mount shimNothingPlugin/daemon logic
Compound permission rulesNothing beyond group membershipMount Orchestrator
Dynamic per-session overridesPossibly via Developer APIMount Orchestrator
Temporal/expiring accessNothingMount Orchestrator
  • Does Kasm’s Developer API support per-session config injection, or only per-workspace?
  • Can Storage Mappings use host-path bind mounts directly, or only Docker volumes with drivers?
  • What’s the performance overhead of rclone-based Storage Providers vs raw bind mounts?
  • How does Kasm handle conflicting mappings (same target path from user + group)?
  • Can Exec Config scripts access the user’s JWT claims for runtime decisions?
  1. POC Test A: Set up Kasm with group-based Storage Mappings, measure admin overhead
  2. POC Test B: Build minimal orchestrator that generates Docker run configs
  3. Compare: Which approach requires less ongoing admin work for N folders × M groups?
  4. Document: Results feed into ARCHITECTURE_COMPONENTS update