Setup
All four install paths — from zero-cloud quickstart to Key Vault + Firecracker production.
Detailed walkthroughs for all four install paths. For the short version, see the README Quickstart.
All paths start the same way:
sudo mkdir -p /iris && sudo chown $USER:$USER /iris
git clone https://github.com/irisworks/iris-core.git /iris/repo
cd /iris/repo| No Firecracker | With Firecracker (isolated microVMs) | |
|---|---|---|
| No Azure | Option 1 — quickstart, zero cloud deps | Option 3 |
| Azure Key Vault | Option 2 | Option 4 — full production |
Every option prompts for Slack and/or Telegram tokens during setup — answer Y to
whichever you want (or both; they run in the same process). See
Telegram Setup.
Option 1 — No Azure, No Firecracker
Iris runs on your machine and executes commands directly on the host. No Azure account, no KVM needed.
Requirements: Ubuntu 22.04 (laptop, VPS, or any VM) · LLM provider API key · Slack workspace (admin) or Telegram account · GitHub account (optional)
bash bootstrap.sh --setup --no-keyvaultThe script will:
- Install system dependencies (Docker, Node 22, jq, GitHub CLI). nginx and certbot are installed only if you configure a public domain; the Azure CLI and Terraform are installed only on the Key Vault paths (Options 2 and 4).
- Ask for your LLM provider (anthropic / openai / azure-foundry / amazon-bedrock / deepseek / mistral / custom) and API key.
customcovers any other OpenAI-compatible endpoint — Kimi/Moonshot direct, a self-hosted gateway, etc. — and prompts for a base URL and provider name in addition to the key. - Walk you through creating a Slack app (exact token scopes shown in-terminal) and/or a Telegram bot.
- Optionally set up email sending (Resend), a public domain, and a GitHub
token — if you add one, you'll also name the repo Iris pushes her own
skill/sub-agent commits to (your own private overlay repo, or a private
mirror of
iris-core— see Extending Iris; never the upstream you cloned from, and never a public fork). - Write
/iris/.env(chmod 600), build the runtime, install and start theirissystemd service.
Verify:
sudo systemctl status irisThen in Slack: @iris what model are you? — or message your Telegram bot after
claiming it.
Slack app creation (reference)
When the bootstrap pauses for Slack tokens:
- https://api.slack.com/apps → Create New App → From scratch → name it
Iris→ pick your workspace. - Socket Mode → Enable → generate an App-Level Token with scope
connections:write→ copy thexapp-...token. - OAuth & Permissions → Bot Token Scopes → add:
app_mentions:readchannels:historychannels:readchat:writegroups:historygroups:readim:historyim:readim:writempim:historyreactions:writeusers:read→ Install to Workspace → copy thexoxb-...token. - Event Subscriptions → Enable → subscribe to bot events:
app_mentionmessage.channelsmessage.groupsmessage.immessage.mpim. - App Home → enable the Messages Tab.
- (Optional) Slash Commands → Create New Command for each of
/stop,/compact,/clear,/reset,/verbose— leave the Request URL blank (Socket Mode delivers them). Without this step Slack rejects a typed/stopbefore it reaches Iris; the bare wordsstop/compact/clearwork either way. See Channel Modes.
Option 2 — Azure Key Vault, No Firecracker
Same as Option 1, but secrets live in Azure Key Vault instead of /iris/.env.
Requirements: all of Option 1 + an Azure account
bash bootstrap.sh --setup --keyvaultAdditional steps over Option 1: the Azure CLI and Terraform are installed,
followed by Azure login (az login, skipped if the VM has a managed identity),
then prompts for a Key Vault name (default iris-kv-<hostname>)
and resource group. The script creates the vault and seeds all secrets into it.
Option 3 — No Azure, With Firecracker
Every bash command Iris runs executes inside an isolated Firecracker microVM. No Azure account needed.
Requirements: all of Option 1, plus a machine with /dev/kvm. On Azure use the
Ddsv5 series (e.g. Standard_D4ds_v5) — B-series and D-series have no KVM.
bash bootstrap.sh --setup --no-keyvault --firecrackerAdditional steps over Option 1:
- KVM check (re-execs via
sg kvmif group membership isn't active yet — no logout needed). - Downloads Firecracker + jailer v1.7.0 and a Linux kernel; creates the
irisjailersystem user (uid/gid 10000). - Builds
rootfs.ext4from the iris-runtime Docker image (~1 minute). - Provisions the
iris-fc-public-sandboxsystemd service, waits for the VM health check athttp://172.20.1.2:8080/health, then switches Iris to--sandbox=firecracker:172.20.1.2via a systemd drop-in.
Verify: @iris run: uname -a — the kernel should differ from the host's.
Option 4 — Azure Key Vault + Firecracker (full production)
Option 2 + Option 3 combined, with Terraform managing the sandbox VM lifecycle.
bash bootstrap.sh --setup --keyvault --firecrackerAdditional prompt: a Terraform state storage account name (lowercase + numbers,
max 24 chars). The script creates the storage account, runs terraform init with
the Azure backend, and terraform apply provisions the sandbox VM service.
Telegram Setup
Iris supports Telegram natively. The bot is private by design — it ignores all messages until you claim it with a one-time token.
1. Create a bot: message @BotFather, send /newbot, pick a display name and a
username ending in bot, and copy the token (7123456789:AAF...). Do this at
web.telegram.org or the desktop app on the same machine you're running bootstrap
from — Telegram syncs the BotFather chat to every logged-in device, so you can
copy-paste the token locally instead of moving it off your phone.
2. Add the token: enter it when bootstrap asks (Set up Telegram integration? [Y/n]).
It echoes back a masked confirmation (123456789…xyz9 (46 chars)) so you can confirm
the paste landed, then verifies the token live against Telegram's getMe API before
continuing — useful if you're pasting from a phone, where a masked terminal prompt
gives no feedback on a mangled copy — and re-prompts if it's rejected. Once verified,
it's written to /iris/.env automatically.
3. Claim the bot: on first startup Iris prints a one-time claim token to the
terminal, alongside a scannable QR code (journalctl -u iris -f if you missed
it). The QR code is a t.me/<bot>?start=<token> deep link — scanning it opens
a chat with the bot with the token pre-filled, so a tap on Send claims it with
no typing at all. You can also just send the plaintext token by hand. Either
way the bot replies ✅ Bot claimed. Claim state persists across restarts.
Tokens expire after 10 minutes — restart Iris to generate a new one. Until
claimed, any other message to the bot gets a reminder to check the terminal
for the claim token.
Reclaiming (transfer to a different Telegram account):
echo "IRIS_TELEGRAM_FORCE_RECLAIM=true" >> /iris/.env && sudo systemctl restart irisSend the freshly printed token from the new account, then remove
IRIS_TELEGRAM_FORCE_RECLAIM from /iris/.env.
Swapping bots: the claim is scoped to the bot's identity. If you replace
TELEGRAM_BOT_TOKEN with a token for a different bot, the old claim is cleared
automatically on startup and a fresh claim token is printed — no
IRIS_TELEGRAM_FORCE_RECLAIM needed. (Force-reclaim is only for transferring the
same bot to a new owner.)
Bot commands: /reset or /clear (clear history) · /compact (summarise context) ·
/stop (abort a running response)
Running Slack and Telegram simultaneously: set all three tokens in /iris/.env
— both transports start in the same process:
IRIS_SLACK_APP_TOKEN=xapp-...
IRIS_SLACK_BOT_TOKEN=xoxb-...
TELEGRAM_BOT_TOKEN=...Secrets
Two backends, chosen at bootstrap:
/iris/.env (default, no cloud dependencies) — bootstrap prompts for all values
and writes the file with chmod 600. Never commit it.
Azure Key Vault (opt-in, recommended for Azure production):
KV=$(grep ^IRIS_KEY_VAULT /iris/.env | cut -d= -f2)
az keyvault secret set --vault-name "$KV" --name "SLACK-APP-TOKEN" --value "xapp-..."
az keyvault secret set --vault-name "$KV" --name "SLACK-BOT-TOKEN" --value "xoxb-..."
az keyvault secret set --vault-name "$KV" --name "GITHUB-TOKEN" --value "ghp_..."Iris itself always accesses secrets through the get-secret skill, which handles
both backends.
Release Tag Verification
install.sh resolves the latest v* release tag and, once checked out, runs
git verify-tag against it. This doesn't change the delivery mechanism's root
of trust — curl -fsSL … | bash from raw.githubusercontent.com is still
TLS-plus-GitHub either way — but it does catch a tampered or force-moved tag
inside the repo you just cloned, and gives installs that mirror or vendor
iris-core something to check against.
The signing key is fetched at install time from https://github.com/<user>.gpg
— the maintainer's public GPG key(s) as published on their GitHub profile
(Settings → SSH and GPG keys), no key file stored in this repo. The
GitHub user checked is katrohit by default; override with
IRIS_CORE_SIGNING_GH_USER if a different maintainer's key should be trusted.
Verification is best-effort by design:
IRIS_CORE_REFis a branch (e.g.main, or any non-tag override) — skipped, with a notice. Branches aren't signed.- No key published, or
gpgunavailable — skipped, with a notice, so a first install on a minimal box isn't blocked by tooling it doesn't have. - A release tag is unsigned or its signature doesn't match the published
key — the install aborts with an actionable message. Release tags are
always signed as part of
docs/RELEASING.md, so a bad signature here means something is wrong.
Pin the exact key you trust instead of whatever github.com/<user>.gpg serves
today. The env var must be set on bash, the process that actually reads
it — not on curl, which never sees it:
curl -fsSL .../install.sh | IRIS_CORE_SIGNING_FINGERPRINT="<published fingerprint>" bashPin the fingerprint of the primary key (the one under "Fingerprint" in
docs/RELEASING.md), not a subkey — the install
only ever compares against and trusts primary keys.
The current maintainer signing key fingerprint is published in
docs/RELEASING.md. To bypass verification
entirely (not recommended): IRIS_SKIP_TAG_VERIFY=1.
Resetting a Firecracker VM Between Sessions
sudo systemctl stop iris-fc-public-sandbox
sudo cp --sparse=always \
/var/lib/iris/firecracker/rootfs.ext4 \
/var/lib/iris/firecracker/agents/public-sandbox/rootfs.ext4
sudo systemctl start iris-fc-public-sandboxDynamic-pool VMs are reset automatically by VmManager on session reset or idle
timeout.