Manage workspace toolchains with Mise
Instead of building and maintaining separate container images for every team, you can use Mise-en-Place (Mise) to define project-specific toolchains on top of a single base image. Mise is a polyglot developer tool version manager that lets each team declare their required languages, runtimes, and CLI tools in a mise.toml configuration file that lives in the repository alongside the code.
Why use Mise?
Mise simplifies how your organization manages development toolchains in Citrix Secure Developer Spaces (SDS). It offers several benefits over maintaining multiple container images:
- Fewer images to maintain. Use one base image across your organization and let teams define their tooling needs per project.
- Faster onboarding. Developers clone a repository and the tools install automatically — no manual setup, no outdated documentation.
- Version-controlled environments. Toolchain definitions live in Git, so changes go through pull requests and code review just like any other code change.
-
Faster workspace restarts. Because workspaces persist the
/home/developerdirectory, installed tools survive between sessions. After the first start, subsequent starts activate in under a second. - Self-service for developers. Teams update their own toolchain without requesting a new container image from the platform team.
- Consistency across the team. Every developer on a project gets the same tool versions, reducing “works on my machine” issues.
How it works in Citrix Secure Developer Spaces
The overall approach follows this pattern:
- Your platform team creates a single base container image with Mise pre-installed.
- Each team commits a
mise.tomlconfiguration file to their repository. - When a developer starts a workspace, Mise reads the configuration and installs the declared tools.
- Because
/home/developerpersists across workspace restarts, installed tools remain available on subsequent starts without re-downloading.
What happens on first start versus subsequent starts
| First workspace start | Subsequent starts |
|---|---|
| Downloads and installs declared tools (typically 10–60 seconds depending on the number of tools) | Detects tools already present; activates instantly (under 1 second) |
Sample scenario
The examples in this guide use a web application project that requires the following toolchain:
- Node.js 22 (application runtime)
- Python 3.13 (build scripts and tooling)
- Terraform 1.x (infrastructure management)
- jq (JSON processing)
Configure a base container image
Start with the generic image from the Citrix Secure Developer Spaces image repository. This image is based on Ubuntu 24.04 and includes common development utilities like Git, Docker, kubectl, and cloud CLIs. Extend this image by installing Mise at build time. This ensures Mise is available immediately when a workspace starts, without requiring developers to install it themselves. Create a Dockerfile that extends the generic image:
FROM strongnetwork/generic:latest
USER root
# Install Mise for all users
RUN curl https://mise.run | MISE_INSTALL_PATH=/usr/local/bin/mise sh
# Add a first-start script that configures Mise for the developer user.
# Scripts in /usr/bin/strong_network_startup/ run automatically on first
# workspace start, after /home/developer has been created.
COPY setup-mise.sh /usr/bin/strong_network_startup/setup-mise.sh
RUN chmod +x /usr/bin/strong_network_startup/setup-mise.sh
USER 1000
WORKDIR /home/developer
<!--NeedCopy-->
Create setup-mise.sh alongside your Dockerfile:
#!/bin/bash
# setup-mise.sh — runs once on first workspace start
# At this point /home/developer exists and is writable.
if ! grep -q 'mise activate' /home/developer/.bashrc 2>/dev/null; then
echo 'eval "$(mise activate bash)"' >> /home/developer/.bashrc
fi
<!--NeedCopy-->
Why not write to .bashrc in the Dockerfile? The /home/developer directory doesn’t exist during the initial startup phases of a new workspace. It’s created later in the startup flow. Scripts placed in /usr/bin/strong_network_startup/ run after /home/developer is available, so they can safely write to it.
Mise installs tools into ~/.local/share/mise/installs/ by default. Because this path is inside /home/developer, all installed tools persist across workspace restarts.
Enable Mise on existing workspaces
The container image approach above works for new workspaces created from the updated image. For existing workspaces that are already running, use a workspace startup script instead. Configure a startup script in the SDS console (under workspace properties or as part of the workspace template). The script checks whether Mise is already set up and only runs the installation if needed:
#!/bin/bash
# Workspace startup script — configure in the SDS console or workspace template
# Install Mise if not already present
if ! command -v mise &> /dev/null; then
curl https://mise.run | MISE_INSTALL_PATH=/home/developer/.local/bin/mise sh
fi
# Activate Mise in the shell if not already configured
if ! grep -q 'mise activate' /home/developer/.bashrc 2>/dev/null; then
echo 'eval "$(mise activate bash)"' >> /home/developer/.bashrc
fi
# Source Mise for the current script session
eval "$(mise activate bash)"
# Install project tools if a mise.toml exists
if [ -f /home/developer/project/mise.toml ]; then
cd /home/developer/project
mise install
fi
<!--NeedCopy-->
Because this script checks for existing installations before acting, it’s safe to run on every workspace start. On an already-configured workspace, it completes in under a second.
Define your project toolchain
Once your base image includes Mise, each team defines their toolchain in a mise.toml file at the root of their repository:
[tools]
node = "22"
python = "3.13"
terraform = "1"
jq = "latest"
<!--NeedCopy-->
When a developer opens a workspace and navigates to the project directory, Mise automatically installs the specified tool versions and adds them to the shell’s PATH.
Install tools on workspace start
If you want tools pre-installed before the developer opens a terminal, add mise install to your workspace startup script (see Enable Mise on existing workspaces for the full script pattern). The essential command is:
cd /home/developer/project
mise install
<!--NeedCopy-->
On first start, this downloads and installs all declared tools. On subsequent starts, Mise detects the tools are already present and completes in under a second.
Use environment variables and tasks
Mise also manages environment variables and project tasks. Add them to the same mise.toml:
[tools]
node = "22"
python = "3.13"
terraform = "1"
jq = "latest"
[env]
NODE_ENV = "development"
AWS_REGION = "eu-west-1"
[tasks]
dev = "npm run dev"
test = "npm test"
lint = "npm run lint && terraform validate"
<!--NeedCopy-->
Developers can then run mise run dev or mise run test and the correct tools and environment variables load automatically.
For full details on Mise configuration, see the Mise documentation.
Understand workspace persistence
Citrix Secure Developer Spaces persists the /home/developer directory across workspace restarts using Kubernetes Persistent Volume Claims. This is what makes Mise practical in workspaces — tools only need to download once.
What persists
-
/home/developer/.local/share/mise/installs/— all Mise-installed tool binaries -
/home/developer/.local/share/mise/— tool metadata and shims -
/home/developer/.cache/mise/— download cache -
/home/developer/.bashrc— shell activation configuration - Any files the developer creates under their home directory
What doesn’t persist
- System directories outside
/home/developer(for example,/usr/local/bin/miseis part of the container layer and is always available from the image) - Packages installed with
apt-getat runtime (these live in/usr/, which is part of the container layer) - Temporary files in
/tmp
Optimize first-start performance
The first workspace start always requires downloading tools because /home/developer is created as an empty persistent volume — any files written there during the Docker image build are hidden by the volume mount. Subsequent starts benefit from persistence and complete in under a second.
To reduce the time developers wait on their first start, consider these strategies:
- Use an internal mirror or cache. If your organization restricts egress traffic or wants faster downloads, host a binary mirror internally for the tool downloads. Internal mirrors on the same network significantly reduce download times.
-
Pin specific versions. Avoid
latestin production configurations. Pinned versions resolve faster because Mise doesn’t need to query for the newest release.
Network and security considerations
Mise downloads binaries from external registries at runtime. If your Citrix Secure Developer Spaces deployment enforces egress controls, allow access to the following domains:
-
mise.run— installer -
github.comandapi.github.com— tool downloads and version resolution -
nodejs.org,python.org, and similar upstream registries depending on the tools used
Alternatively, configure internal mirrors for these registries and point Mise to your internal URLs. See the Mise settings documentation for details on configuring custom registries.
Where to go next
- Mise documentation — full reference for tool management, tasks, and environment variables
- SDS workspace images repository — base and generic container images for Citrix Secure Developer Spaces
- Workspace templates — configure startup scripts and resource settings in your workspace templates