Interactive installer for MiOS, and the user-editable layer of its three-layer profile model. This is the front door to MiOS.
What MiOS is. MiOS is one thing built two ways at once: an immutable,
bootc/OCI-shaped Fedora workstation (the whole OS is a single container
image β boot it, bootc upgrade it like a git pull, bootc rollback
it like a Ctrl-Z) that is also a local, self-replicating, agentic AI
operating system. The same image that ships GNOME/Wayland, NVIDIA+ROCm+iGPU
via CDI, KVM/libvirt with VFIO passthrough, and a k3s+Ceph cluster path
also ships a full local agent stack behind one OpenAI-compatible endpoint.
What this repo does in that whole. The system image, FHS overlay,
Containerfile, Quadlets, and architectural laws live in mios.git. This
repo is the user-facing entry surface: it captures who you are (identity,
keys, image tag) into a layered profile, merges mios.git into the system
root (Phase-1 Total Root Merge), and hands off to the build pipeline that
produces the OCI image the bootc lifecycle then carries forward. End to
end: bootstrap (this repo) β image build (mios.git) β bootc lifecycle
on the host. Nothing here owns runtime system files β it owns the path
in.
Version: v0.3.0 System repo: https://github.com/mios-dev/mios
install.sh-- interactive Phase-0..4 orchestrator. Prompts for Linux username, hostname, password, SSH key, GitHub PAT, and image tag -- everything defaults touseruntil the user overrides.etc/mios/profile.toml-- user-editable profile (TOML) that overlays the vendor defaults shipped bymios.gitat/usr/share/mios/profile.toml.etc/skel/.config/mios/{profile.toml,system-prompt.md}(owned and shipped bymios.git, not this repo) -- per-user templates seeded into every Linux user's home (uid β₯ 1000) byinstall.sh:seed_user_skel_for_all_accountsand byuseradd -mfor future users.system-prompt.md-- host AI prompt redirector. Bootstrap deploys this to/etc/mios/ai/system-prompt.md; the local agent stack loads it for chat completions through the unified AI endpoint (MIOS_AI_ENDPOINTβ Architectural Law 5). Per-user copies live at~/.config/mios/system-prompt.md..env.mios(deprecated, legacy) -- env-style user defaults; sourced byinstall.shafter TOML layers so explicit TOML wins. Migrate toetc/mios/profile.toml.usr/share/mios/knowledge/*-- RAG knowledge graphs. At runtime these are embedded (nomic-embed-text, served by themios-llm-lightlane) and recalled from the PostgreSQL+pgvector agent datastore.
Canonical entry β WinKey+R β paste β Enter β accept UAC:
powershell -ExecutionPolicy Bypass -Command "irm https://raw.githubusercontent.com/mios-dev/mios-bootstrap/main/Get-MiOS.ps1 | iex"
That irm | iex shape is the entry contract. Run it from the Windows
Run dialog, cmd.exe, or any PowerShell session β no pre-existing pwsh,
no ExecutionPolicy override, no manual elevation needed.
Get-MiOS.ps1 handles everything end-to-end:
- Self-cache-busts on entry β Fastly's 5-min TTL on
raw.githubusercontent.comis invisible to you; every paste pulls origin-fresh. - Two-pass self-elevation β Pass 1 (user) installs Windows Terminal
- MiOS scheme, Geist Mono Nerd Font, oh-my-posh, fastfetch, and the
MiOS native-app shortcut on Desktop + Start Menu. Pass 2 (admin)
shrinks
C:\and createsM:\at exactly 256 GB NTFS, installs Podman Desktop, provisions theMiOS-DEVpodman machine, and clonesmios.git+mios-bootstrapontoM:\.
- MiOS scheme, Geist Mono Nerd Font, oh-my-posh, fastfetch, and the
MiOS native-app shortcut on Desktop + Start Menu. Pass 2 (admin)
shrinks
- Auto-chains into
/usr/libexec/mios/mios-build-driverinsideMiOS-DEVfor the OCI build (Phase 6+: identity, OCI build, deploy).
MiOS-DEV is THE builder: every podman build, BIB run, and
bootc switch happens inside it, and it runs every Quadlet container
that ships in production. Windows is provisioning + handoff only.
Equivalent shortcut: mios.bat β WinKey+R β mios.bat (or double-
click the file). The .bat invokes the same irm | iex one-liner above
with cache-bust appended (?cb=<unix-time>); it self-elevates via cmd's
net session probe instead of the script's two-pass dance. Either entry
is valid; the irm | iex shape is the contract.
After installation, the MiOS Start Menu app opens the launcher (Build,
Enter Dev VM, Update, Dashboard, Configurator, Re-run Bootstrap, Open
Install Root). mios-build from any MiOS terminal re-runs the OCI build
inside the dev VM.
Each interactive prompt auto-accepts the resolved-from-mios.toml
default after 90 seconds idle. Override with
$env:MIOS_PROMPT_TIMEOUT (seconds; 0 waits forever, 1 is the
fastest unattended setting).
One script -- all phases in sequence, fully idempotent:
- Checks prerequisites (Git, WSL2, Podman Desktop)
- Creates
%LOCALAPPDATA%\Programs\MiOS\, clones both repos - Configures
%USERPROFILE%\.wslconfig(memory/CPU/mirrored networking) - Collects identity -- username, hostname, password (all default to
mios, just press Enter) - Writes identity into the WSL2 distro (
/etc/mios/install.env) - Registers in Add/Remove Programs and creates the 'MiOS' Start Menu group
- Runs
just buildinsidepodman-machine-default
Re-running is safe -- if the WSL2 distro already has the repo at /, it pulls
the latest and goes straight to build with no prompts.
Prerequisites: Git, Podman Desktop, WSL2 (wsl --install).
On any Fedora bootc-capable host (Fedora Server 41+ or Fedora bootc):
# Canonical one-liner (legacy install.sh URL also works as a redirector):
sudo bash -c "$(curl -fsSL https://raw.githubusercontent.com/mios-dev/mios-bootstrap/main/build-mios.sh)"Each interactive prompt auto-accepts the resolved-from-mios.toml
default after 90 seconds idle. Override with
MIOS_PROMPT_TIMEOUT= (seconds; 0 waits forever, 1 is the fastest
unattended setting).
The installer:
- Phase-0 -- preflight, profile-card load (three-layer overlay), interactive identity capture (defaults from layered profile).
- Phase-1 -- Total Root Merge: clone
mios.gitinto/, copy bootstrap overlays (etc/,usr/,var/) on top. This is the load-bearing premise: the repo root IS the deployed system root, so edits to/on a running host are edits to the source the nextbootc upgradebakes. - Phase-2 -- build:
dnf installfrom the[packages]SSOT inusr/share/mios/mios.toml(FHS path) orbootc switch ghcr.io/mios-dev/mios:latest(bootc path). - Phase-3 -- apply:
systemd-sysusers,systemd-tmpfiles,daemon-reload, services; create the bootstrap user; seed every uid β₯ 1000 home from/etc/skel/.config/mios/. - Phase-4 -- reboot prompt.
To work on this repo from a hosted cloud session: the VM is a fixed Ubuntu image, and MiOS's one dev image (MiOS/.devcontainer/Containerfile, the same one this repo's devcontainer builds) runs inside it, so the session matches the devcontainer. Create the environment once (claude.ai/code, the cloud icon above the message box, Add cloud environment), paste the script below into Setup script, add the variables, and tick it as the default. The platform runs the script, snapshots the disk, and every later session starts from that snapshot.
Setup script. It clones the dev-loop plugin to /opt/dev-loop and hands off to its cloud-fedora-setup.sh. All the logic lives in that clone, so this text never needs editing, and it always exits 0 because a failing setup script fails every session:
#!/bin/bash
# MiOS Fedora dev environment + the dev-loop plugin (/dev-loop:*) in every session.
export FEDORA_DEVCONTAINER_REPO=https://github.com/mios-dev/MiOS
export FEDORA_DEVCONTAINER_FILE=.devcontainer/Containerfile
# dev-loop plugin checkout; loaded by CLAUDE_CODE_PLUGIN_DIRS=/opt/dev-loop
if [ -d /opt/dev-loop/.git ]; then
git -C /opt/dev-loop pull -q --ff-only || true
else
git clone -q --depth 1 https://github.com/mios-dev/-dev-loop /opt/dev-loop || true
fi
[ -f /opt/dev-loop/skills/dev-loop/scripts/env/cloud-fedora-setup.sh ] &&
bash /opt/dev-loop/skills/dev-loop/scripts/env/cloud-fedora-setup.sh
exit 0Environment variables, set in the same dialog:
| Variable | Value | What it does |
|---|---|---|
FEDORA_DEVCONTAINER_REPO |
https://github.com/mios-dev/MiOS |
Projection mode: the session's Fedora userspace is this repo's devcontainer, built unedited, so it is the one MiOS dev image. Unset, the script builds a generic Fedora image instead. |
FEDORA_DEVCONTAINER_FILE |
.devcontainer/Containerfile |
The Containerfile inside that repo. This is the default; setting it keeps the environment a complete record. |
CLAUDE_CODE_PLUGIN_DIRS |
/opt/dev-loop |
Loads the dev-loop plugin in every session, whatever repo it opens: the /dev-loop:* commands, hooks and agents. A cloud session loads plugins no other way. |
Optional, same place:
| Variable | Default | What it does |
|---|---|---|
FEDORA_RUNTIME |
auto |
auto, podman or docker. MiOS is Podman-native: auto takes podman when it is installed and Docker only where it is the sole runtime, which is this cloud VM. An explicit runtime that is missing logs an error and builds nothing. |
FEDORA_SETUP_BUDGET_S |
0 (never) |
Defers the devcontainer lifecycle prebuild (miosd, the root overlay, /opt/mios/bin) once this many seconds of the setup have elapsed, so a slow run stays inside the platform's roughly 5-minute snapshot budget. A deferred prebuild is applied later, inside a session, with bash /opt/dev-loop-fedora/cloud-fedora-setup.sh --lifecycle. A full run measured 452 s; start with 240 if the environment cache stops building. |
FEDORA_DEVCONTAINER_REF |
the repo's default branch | Branch or tag of the repo to clone. |
FEDORA_EXEC_USER |
root |
The user container commands run as. mios-dev matches the devcontainer's remoteUser. |
FEDORA_PROVISION_HOST |
1 |
0 skips provisioning the VM itself (agy, keyring, headless grants, dev-loop skill), which otherwise runs first. |
FEDORA_REBUILD |
0 |
1 forces an image rebuild even when one is cached. |
What every session then has: mios-dev <cmd> and fedora <cmd> run inside the Fedora image at the same path as on the host; agy, claude, gemini and copilot on the host and in the image; the /dev-loop:* commands. Sign in to agy once per container: bash /opt/dev-loop/skills/dev-loop/scripts/env/agy-login.sh prints the URL, then the same command with --code '<code>' finishes. The script and every variable are owned by -dev-loop (skills/dev-loop/references/environment.md); this copy is for the operator creating the environment.
The MiOS bootstrap installer has built-in support for offline/air-gapped and proxied environments:
- System Proxy: If your host is behind a system proxy,
Get-MiOS.ps1(viaInvoke-WebRequest/Invoke-RestMethodusing-UseBasicParsing),gitclones, andwingetpackages will respect the standard Windows system proxy settings. - Offline Fallbacks: When internet access is unavailable or limited, the installer automatically falls back to direct download/offline setups. For instance:
- If
wingetis missing or fails, a direct MSI/executable installation is attempted for prerequisites like Git and Podman CLI. - Pre-seeded local packages and offline configuration are utilized where possible to minimize external network requests during initial provisioning.
- If
Identity and tunables flow from one TOML with three layers, higher
precedence first. This is the same SSOT mechanism (mios.toml) the rest
of the system uses; the profile card is its identity slice.
~/.config/mios/profile.toml-- per-user (seeded from/etc/skel/.config/mios/profile.toml)/etc/mios/profile.toml-- host (this repo's editable copy)/usr/share/mios/profile.toml-- vendor defaults (mios.git)
install.sh:resolve_profile_layers walks all three at install time and
field-level overlays them into the runtime defaults. User-set fields
in higher layers win. Empty strings do NOT override non-empty values
below them (empty user TOML is the vendor-default state, not an error).
The shipped defaults are identical between etc/mios/profile.toml
(this repo) and /usr/share/mios/profile.toml (mios.git). Edit
etc/mios/profile.toml here, or /etc/mios/profile.toml on a deployed
host, to override per-host. Edit ~/.config/mios/profile.toml per user.
Defaults policy (project-wide invariant): every boolean feature
flag -- [quadlets.enable] entries, [ai] enable_*, [network] allow_*, [bootstrap] install_packages / reboot_on_finish -- ships
true. The system never disables a component via static config; when
a component is incompatible with the host, systemd Condition*
directives on the underlying unit short-circuit it at boot/pre-boot.
Operators can still set a flag to false to force-disable. See
INDEX.md Β§5 in the system repo for the active gating table.
| Field | Default |
|---|---|
[identity] username |
mios |
[identity] hostname |
mios |
[identity] fullname |
'MiOS' User |
[identity] shell |
/bin/bash |
[identity] groups |
wheel,libvirt,kvm,video,render,input,dialout,docker |
[auth] ssh_key_type |
ed25519 |
[auth] ssh_key_action |
generate |
[image] ref |
ghcr.io/mios-dev/mios:latest |
[ai] endpoint |
http://localhost:8642/v1 |
[ai] endpoint is the single OpenAI-compatible front door (Law 5,
UNIFIED-AI-REDIRECTS) that every agent, tool, and editor on a deployed
host resolves to via MIOS_AI_ENDPOINT. It fronts the local inference
lanes β the primary mios-llm-light lane (llama.cpp behind the
llama-swap proxy image on
:11450, serving the everyday models and embeddings) plus the gated
heavy GPU lanes β so the URL stays stable while the engine behind it can
change. No vendor-cloud URLs ever appear; the lanes speak the
OpenAI/Ollama-compatible API, which is the only addressable contract.
Pressing Enter at any prompt accepts the resolved layered default.
/etc/mios/install.env-- non-secret installation metadata (mode 0640)/etc/mios/profile.toml-- user-edit overlay (writable; preserved acrossbootc upgrade)/etc/mios/ai/system-prompt.md-- host AI prompt~/.config/mios/profile.toml(per user) -- per-user overlay~/.config/mios/system-prompt.md(per user) -- per-user AI prompt~mios/.ssh/id_ed25519-- generated SSH key (mode 0600)~mios/.git-credentials-- only if a GitHub PAT was provided (mode 0600)
Passwords are piped to chpasswd and never written to disk in plaintext.
Re-running the installer with the same answers updates rather than
duplicates. Existing users are amended (not recreated); existing SSH
keys are not overwritten by the generate path (use a different keypair
name to layer). seed_user_skel_for_all_accounts re-runs every
install -- every uid β₯ 1000 user gets the latest
~/.config/mios/{profile.toml,system-prompt.md} content.
Idempotency is the bootstrap-side mirror of the OS-side promise: the same inputs always reproduce the same deployed state, the same way the single-image bootc lifecycle reproduces the same OS on every host that pulls the ref.
Apache-2.0. See LICENSE.