AWS Lambda MicroVMs : bastions serverless, sandboxes IA et Cloud9 DIY avec VS Code OSS + EFS
- Published on
- Authors

- Name
- Sylvain BRUAS
- @sylvain_bruas
Introduction
Le 22 juin 2026, AWS a lancé Lambda MicroVMs, un nouveau type de ressource serverless qui change la donne. Jusqu'ici, Lambda était synonyme de fonctions stateless limitées à 15 minutes. Désormais, vous pouvez obtenir une machine virtuelle Firecracker dédiée, stateful, avec isolation hardware, démarrage quasi-instantané depuis un snapshot, et une durée de vie allant jusqu'à 8 heures. Le tout sans infrastructure à gérer.
Ce n'est pas une évolution incrémentale de Lambda Functions — c'est un nouveau type de ressource avec sa propre API (run-microvm, suspend-microvm, resume-microvm). AWS expose directement la couche Firecracker qui propulsait déjà secrètement plus de 15 000 milliards d'invocations Lambda par mois.
Dans cet article, nous allons explorer ce que Lambda MicroVMs apporte concrètement, pourquoi c'est un game-changer pour les bastions et les sandboxes, puis nous construirons pas à pas un équivalent de Cloud9 basé sur OpenVSCode Server, Lambda MicroVM et Amazon EFS pour la persistance du code.
Lambda MicroVMs : ce que c'est (et ce que ce n'est pas)
Architecture et spécifications
Lambda MicroVMs repose sur le modèle image-then-launch :
- Vous fournissez un Dockerfile + code source packagé en zip sur S3
- Lambda exécute le Dockerfile, lance votre application via
ENTRYPOINTouCMD, attend le signal/ready(hook optionnel), puis capture un snapshot Firecracker (mémoire + disque) - Chaque lancement ultérieur reprend depuis ce snapshot pré-initialisé — démarrage quasi-instantané
Le sizing suit un modèle baseline-peak : vous configurez une baseline, et la MicroVM peut burst jusqu'à 4x cette baseline automatiquement. Vous payez la baseline tant que la MicroVM tourne, et uniquement le surplus consommé au-delà.
| Baseline | Peak (burst 4x) | Disque max |
|---|---|---|
| 0,5 Go / 0,25 vCPU | 2 Go / 1 vCPU | 8 Go |
| 1 Go / 0,5 vCPU | 4 Go / 2 vCPU | 8 Go |
| 2 Go / 1 vCPU (défaut) | 8 Go / 4 vCPU | 8 Go |
| 4 Go / 2 vCPU | 16 Go / 8 vCPU | 16 Go |
| 8 Go / 4 vCPU | 32 Go / 16 vCPU | 32 Go |
Autres caractéristiques :
| Caractéristique | Valeur |
|---|---|
| Architecture | ARM64 (Graviton) uniquement |
| Durée max | 8 heures (28 800 secondes) |
| Isolation | Firecracker microVM — kernel dédié, pas de partage entre sessions |
| OS | Amazon Linux 2023 (base image managée par Lambda) |
| Protocoles inbound | HTTP/1.1, HTTP/2, WebSockets, gRPC, SSE |
| Authentification | Token JWE obligatoire (X-aws-proxy-auth) |
Ce qui différencie Lambda MicroVMs
Le positionnement est clair : Lambda MicroVMs se situe entre Lambda Functions et EC2 :
- Lambda Functions : stateless, 15 min max, event-driven, scale-to-zero
- Lambda MicroVMs : stateful, 8h max, interactive, suspend/resume avec état intact
- EC2 : stateful, illimité, mais vous gérez tout (AMI, scaling, patching...)
Le modèle économique est intéressant : 0$ de compute pendant la suspension. Vous payez uniquement le stockage du snapshot (~0,08$/Go/mois) et les opérations de suspend/resume. Pour des workloads qui utilisent beaucoup le burst (exactement le profil d'un développeur ou d'un agent IA), c'est redoutable.
Cas d'usage : bastions et sandboxes
Bastions éphémères serverless
Traditionnellement, un bastion SSH est une instance EC2 t3.micro qui tourne 24/7 dans un subnet public ou privé, avec un coût fixe mensuel et une surface d'attaque permanente. Avec Lambda MicroVMs, vous pouvez repenser complètement cette approche :
Le concept : un bastion qui n'existe que quand vous en avez besoin, avec isolation VM complète, et qui disparaît après usage.
# Créer un network connector VPC pour le bastion (une seule fois)
aws lambda-core create-network-connector \
--name bastion-vpc-egress \
--configuration '{
"VpcEgressConfiguration": {
"SubnetIds": ["subnet-private-a"],
"SecurityGroupIds": ["sg-bastion"],
"NetworkProtocol": "IPv4",
"AssociatedComputeResourceTypes": ["MicroVm"]
}
}' \
--operator-role arn:aws:iam::123456789012:role/NetworkConnectorOperatorRole
# Lancer un bastion éphémère
aws lambda-microvms run-microvm \
--image-identifier arn:aws:lambda:eu-west-1:123456789012:microvm-image:bastion-hardened \
--execution-role-arn arn:aws:iam::123456789012:role/BastionMicroVMRole \
--ingress-network-connectors "arn:aws:lambda:eu-west-1:aws:network-connector:aws-network-connector:ALL_INGRESS" \
--egress-network-connectors "arn:aws:lambda:eu-west-1:123456789012:network-connector:bastion-vpc-egress" \
--idle-policy '{"maxIdleDurationSeconds":1800,"suspendedDurationSeconds":600,"autoResumeEnabled":false}'
Avantages par rapport à un bastion EC2 classique :
- Coût quasi-nul : le bastion est suspendu (gratuit en compute) quand personne ne l'utilise. Fini le t3.micro qui tourne 730h/mois pour 10h d'utilisation effective
- Surface d'attaque réduite : pas de machine permanente exposée, kernel dédié sans partage
- Immutabilité : chaque session repart d'un snapshot propre. Pas de drift de configuration, pas de malware persistant
- Audit natif : chaque
run-microvmest un événement CloudTrail. Qui a lancé quoi, quand, combien de temps - Auto-destruction : politique d'idle qui termine automatiquement le bastion après inactivité
Le bastion MicroVM est particulièrement pertinent pour les équipes qui pratiquent le Just-In-Time access : un SRE déclenche un bastion via une Step Function, obtient un accès temporaire à un RDS ou un cluster EKS, et le bastion est terminé 30 minutes plus tard.
Sandboxes pour agents IA et exécution de code non fiable
C'est le cas d'usage principal mis en avant par AWS. Les agents IA (coding assistants, data analysts, vulnerability scanners) ont besoin d'exécuter du code qu'ils génèrent eux-mêmes dans un environnement isolé. Lambda MicroVMs résout le trilemme classique :
- Containers : démarrage rapide mais isolation faible (kernel partagé)
- VMs EC2 : isolation forte mais démarrage lent et gestion lourde
- Lambda MicroVMs : isolation hardware + démarrage rapide + zéro gestion
AWS a d'ailleurs publié une intégration native avec Claude Managed Agents : chaque appel d'outil de l'agent s'exécute dans une MicroVM dédiée, isolée du reste du système.
Pour les plateformes SaaS multi-tenant, c'est le pattern idéal : un étudiant qui exécute du Python sur votre plateforme éducative ne peut jamais accéder aux données d'un autre étudiant, car chaque session tourne dans son propre kernel.
Tutoriel : recréer Cloud9 avec Lambda MicroVM + VS Code OSS + EFS
AWS a retiré Cloud9 des offres pour les nouveaux comptes. Voici comment construire un environnement de développement cloud serverless qui le remplace en combinant Lambda MicroVM, OpenVSCode Server et Amazon EFS pour la persistance.
Architecture cible
┌─────────────────────────────────────────────────────────┐
│ Développeur (navigateur) │
│ https://mvm-xxx.lambda-microvm.eu-west-1.on.aws│
│ Header: X-aws-proxy-auth: <token> │
└──────────────────────────────┬──────────────────────────┘
│ HTTPS (port 8080)
▼
┌─────────────────────────────────────────────────────────┐
│ Lambda MicroVM (ARM64 / Graviton) │
│ Baseline: 4 Go / 2 vCPU │
│ Peak: 16 Go / 8 vCPU (burst auto) │
│ │
│ ┌─────────────────────────────────────────────────┐ │
│ │ OpenVSCode Server (port 8080) │ │
│ │ Extensions, terminal, LSP │ │
│ └─────────────────────────────────────────────────┘ │
│ │
│ ┌─────────────────────────────────────────────────┐ │
│ │ /home/developer/workspace │ │
│ │ (local ou mount EFS optionnel) │ │
│ └─────────────────────────────────────────────────┘ │
│ │
│ Runtime: Node.js 20, Python 3.12, AWS CLI v2 │
└─────────────────────────────────────────────────────────┘
│ (optionnel) NFS via VPC
▼ egress connector
┌─────────────────────────────────────────────────────────┐
│ Amazon EFS (Access Point /dev/workspace) │
│ Persistance du code entre sessions │
│ Throughput mode: elastic │
└─────────────────────────────────────────────────────────┘
Étape 1 : créer le filesystem EFS
# Créer le filesystem
aws efs create-file-system \
--performance-mode generalPurpose \
--throughput-mode elastic \
--encrypted \
--tags Key=Name,Value=dev-workspace-efs \
--region eu-west-1
# Créer un Access Point dédié
aws efs create-access-point \
--file-system-id fs-0abc123def456 \
--posix-user Uid=1000,Gid=1000 \
--root-directory "Path=/dev/workspace,CreationInfo={OwnerUid=1000,OwnerGid=1000,Permissions=755}"
# Créer les mount targets dans les subnets privés
aws efs create-mount-target \
--file-system-id fs-0abc123def456 \
--subnet-id subnet-private-a \
--security-groups sg-efs-access
Étape 2 : construire l'image MicroVM
Voici le Dockerfile qui crée notre environnement de développement. On utilise l'image de base container public.ecr.aws/lambda/microvms:al2023-minimal fournie par AWS, qui est compatible avec le processus de snapshot Firecracker :
FROM public.ecr.aws/lambda/microvms:al2023-minimal
USER root
# Outils système de base
RUN dnf install -y \
nodejs20 npm \
python3.12 python3.12-pip \
git wget unzip tar gzip \
&& dnf clean all
# AWS CLI v2
RUN curl "https://awscli.amazonaws.com/awscli-exe-linux-aarch64.zip" -o "awscliv2.zip" \
&& unzip awscliv2.zip && ./aws/install && rm -rf aws awscliv2.zip
# OpenVSCode Server (build ARM64)
ARG OPENVSCODE_VERSION=1.109.5
RUN mkdir -p /opt/vscode \
&& curl -fsSL "https://github.com/gitpod-io/openvscode-server/releases/download/openvscode-server-v${OPENVSCODE_VERSION}/openvscode-server-v${OPENVSCODE_VERSION}-linux-arm64.tar.gz" \
| tar xz --strip-components=1 -C /opt/vscode
# Créer l'utilisateur développeur avec workspace local
RUN useradd -m -u 1000 -s /bin/bash developer \
&& mkdir -p /home/developer/workspace \
&& mkdir -p /home/developer/.openvscode-server/data/Machine \
&& chown -R developer:developer /home/developer
# Pré-configurer pour désactiver le workspace trust (évite le reload loop)
RUN echo '{"security.workspace.trust.enabled": false}' \
> /home/developer/.openvscode-server/data/Machine/settings.json \
&& chown developer:developer /home/developer/.openvscode-server/data/Machine/settings.json
# Script d'entrypoint
COPY entrypoint.sh /opt/entrypoint.sh
RUN chmod +x /opt/entrypoint.sh
# Extensions VS Code pré-installées
RUN su - developer -c "/opt/vscode/bin/openvscode-server \
--install-extension ms-python.python \
--install-extension dbaeumer.vscode-eslint \
--install-extension esbenp.prettier-vscode \
--install-extension amazonwebservices.aws-toolkit-vscode"
EXPOSE 8080
WORKDIR /home/developer/workspace
CMD ["/opt/entrypoint.sh"]
Quelques points importants sur ce Dockerfile :
USER root: nécessaire pour installer les paquets système et créer l'utilisateur. L'entrypoint switchera versdeveloperpour lancer VS CodeOPENVSCODE_VERSION=1.109.5: version ARM64 stable de OpenVSCode Server- Workspace trust désactivé : sans cette configuration, OpenVSCode Server entre dans un reload loop au premier accès car il demande à l'utilisateur de « faire confiance » au workspace
- Extensions pré-installées : elles sont incluses dans le snapshot, donc disponibles instantanément au démarrage sans téléchargement
Étape 3 : le script d'entrypoint
L'entrypoint lance OpenVSCode Server en tant qu'utilisateur developer. Le montage EFS est géré au niveau de la MicroVM via le VPC egress connector — la MicroVM accède à EFS par le réseau NFS depuis le subnet privé configuré.
#!/bin/bash
# entrypoint.sh — Lance OpenVSCode Server
set -e
# Lancer OpenVSCode Server en tant que developer
exec su - developer -c "/opt/vscode/bin/openvscode-server \
--host 0.0.0.0 \
--port 8080 \
--without-connection-token \
--default-folder /home/developer/workspace"
Note sur EFS : le Dockerfile fourni ne contient pas
nfs-utilset ne monte pas EFS dans l'entrypoint. Pour ajouter la persistance EFS, deux options :
- Montage NFS dans l'entrypoint : ajouter
nfs-utilsau Dockerfile, activer--additional-os-capabilities '["ALL"]'lors ducreate-microvm-image(nécessaire pourmount), et monter EFS avant de lancer VS Code- Workspace local : utiliser
/home/developer/workspacecomme stockage éphémère — le code est perdu à la terminaison mais conservé pendant suspend/resume (le snapshot préserve l'état disque)L'option 1 avec montage EFS dans l'entrypoint ressemblerait à :
#!/bin/bash
# entrypoint.sh — Version avec montage EFS
set -e
EFS_DNS="${EFS_FILE_SYSTEM_ID}.efs.${AWS_REGION}.amazonaws.com"
MOUNT_POINT="/home/developer/workspace"
# Monter EFS (nécessite nfs-utils dans le Dockerfile + additionalOsCapabilities)
if ! mountpoint -q "$MOUNT_POINT"; then
mount -t nfs4 -o nfsvers=4.1,rsize=1048576,wsize=1048576,hard,timeo=600,retrans=2 \
"${EFS_DNS}:/" "$MOUNT_POINT"
chown developer:developer "$MOUNT_POINT"
fi
# Lancer OpenVSCode Server en tant que developer
exec su - developer -c "/opt/vscode/bin/openvscode-server \
--host 0.0.0.0 \
--port 8080 \
--without-connection-token \
--default-folder /home/developer/workspace"
Pour activer les capabilities OS nécessaires au montage NFS, ajoutez --additional-os-capabilities lors de la création de l'image :
aws lambda-microvms create-microvm-image \
--name vscode-dev-environment \
--code-artifact uri=s3://my-microvm-artifacts/vscode-microvm.zip \
--base-image-arn arn:aws:lambda:eu-west-1:aws:microvm-image:al2023-1 \
--build-role-arn arn:aws:iam::123456789012:role/MicroVMBuildRole \
--environment-variables '{"EFS_FILE_SYSTEM_ID":"fs-0abc123def456"}' \
--additional-os-capabilities '["ALL"]'
Étape 4 : packager et créer l'image MicroVM
# Packager le code source
zip -r vscode-microvm.zip Dockerfile entrypoint.sh
# Uploader sur S3
aws s3 cp vscode-microvm.zip s3://my-microvm-artifacts/vscode-microvm.zip
# Créer l'image MicroVM
aws lambda-microvms create-microvm-image \
--name vscode-dev-environment \
--code-artifact uri=s3://my-microvm-artifacts/vscode-microvm.zip \
--base-image-arn arn:aws:lambda:eu-west-1:aws:microvm-image:al2023-1 \
--build-role-arn arn:aws:iam::123456789012:role/MicroVMBuildRole \
--environment-variables '{"EFS_FILE_SYSTEM_ID":"fs-0abc123def456"}'
# Vérifier l'état du build
aws lambda-microvms get-microvm-image \
--image-identifier vscode-dev-environment
Le build est asynchrone. L'image passe de CREATING à CREATED en succès, ou CREATE_FAILED en cas d'erreur. Consultez les logs CloudWatch sous /aws/lambda/microvms/vscode-dev-environment pour le diagnostic.
Étape 5 : lancer l'environnement de développement
# Créer un network connector VPC pour accéder à EFS (une seule fois)
aws lambda-core create-network-connector \
--name dev-vpc-egress \
--configuration '{
"VpcEgressConfiguration": {
"SubnetIds": ["subnet-private-a"],
"SecurityGroupIds": ["sg-dev-microvm"],
"NetworkProtocol": "IPv4",
"AssociatedComputeResourceTypes": ["MicroVm"]
}
}' \
--operator-role arn:aws:iam::123456789012:role/NetworkConnectorOperatorRole
# Lancer la MicroVM avec politique d'idle intelligente
aws lambda-microvms run-microvm \
--image-identifier arn:aws:lambda:eu-west-1:123456789012:microvm-image:vscode-dev-environment \
--execution-role-arn arn:aws:iam::123456789012:role/DevMicroVMRole \
--ingress-network-connectors "arn:aws:lambda:eu-west-1:aws:network-connector:aws-network-connector:ALL_INGRESS" \
--egress-network-connectors "arn:aws:lambda:eu-west-1:123456789012:network-connector:dev-vpc-egress" \
--idle-policy '{"maxIdleDurationSeconds":3600,"suspendedDurationSeconds":1800,"autoResumeEnabled":true}' \
--maximum-duration-in-seconds 28800
La réponse contient l'endpoint HTTPS dédié et le MicroVM ID :
{
"microvmId": "mvm-01234567-abcd-ef01-2345-6789abcdef01",
"state": "PENDING",
"endpoint": "mvm-01234567-abcd-ef01-2345-6789abcdef01.lambda-microvm.eu-west-1.on.aws"
}
Pour vous connecter, générez un token d'authentification :
# Générer un token valide 8h (durée max de la session)
aws lambda-microvms create-microvm-auth-token \
--microvm-identifier mvm-01234567-abcd-ef01-2345-6789abcdef01 \
--expiration-in-minutes 480 \
--allowed-ports '[{"port":8080}]'
# Accéder à l'IDE dans le navigateur :
# https://mvm-01234567-abcd-ef01-2345-6789abcdef01.lambda-microvm.eu-west-1.on.aws
# Header requis : X-aws-proxy-auth: <token>
La politique d'idle est configurée pour suspendre la MicroVM après 1 heure d'inactivité, la garder suspendue 30 minutes, et la reprendre automatiquement au prochain accès HTTP. Pour un développeur qui fait des pauses café ou des réunions, la MicroVM se suspend et se réveille de manière transparente.
Étape 6 : automatiser avec une Step Function
Pour une équipe, vous pouvez automatiser la provision avec une Step Function déclenchée par un portail interne :
{
"Comment": "Provision dev environment on demand",
"StartAt": "RunMicroVM",
"States": {
"RunMicroVM": {
"Type": "Task",
"Resource": "arn:aws:states:::aws-sdk:lambdamicrovms:runMicrovm",
"Parameters": {
"ImageIdentifier": "arn:aws:lambda:eu-west-1:123456789012:microvm-image:vscode-dev-environment",
"ExecutionRoleArn": "arn:aws:iam::123456789012:role/DevMicroVMRole",
"IngressNetworkConnectors": ["arn:aws:lambda:eu-west-1:aws:network-connector:aws-network-connector:ALL_INGRESS"],
"EgressNetworkConnectors": ["arn:aws:lambda:eu-west-1:123456789012:network-connector:dev-vpc-egress"],
"IdlePolicy": {
"MaxIdleDurationSeconds": 3600,
"SuspendedDurationSeconds": 1800,
"AutoResumeEnabled": true
},
"MaximumDurationInSeconds": 28800
},
"ResultPath": "$.microvm",
"Next": "NotifyDeveloper"
},
"NotifyDeveloper": {
"Type": "Task",
"Resource": "arn:aws:states:::sns:publish",
"Parameters": {
"TopicArn": "arn:aws:sns:eu-west-1:123456789012:dev-notifications",
"Message.$": "States.Format('Votre IDE est prêt : {}', $.microvm.Endpoint)"
},
"End": true
}
}
}
Pourquoi le suspend/resume change la donne (et EFS en option)
Le point clé de cette architecture est le modèle suspend/resume natif de Lambda MicroVMs :
- Pendant le suspend : le snapshot Firecracker préserve l'intégralité de la mémoire et du disque. Votre code, vos fichiers ouverts dans VS Code, votre historique terminal — tout est intact au resume
- La MicroVM est éphémère mais stateful : tant qu'elle n'est pas terminée, le workspace persiste entre les sessions suspend/resume
- EFS pour la persistance long-terme : si vous avez besoin que le code survive à la terminaison de la MicroVM (après 8h max ou idle trop long), ajoutez EFS comme décrit à l'étape 3
Sans EFS, le workflow est :
- La MicroVM tourne → vous codez
- Idle 1h → Lambda suspend (0$ compute, snapshot préservé)
- Vous revenez → auto-resume en ~1-2 secondes, tout est là
- Après 8h ou terminaison → workspace perdu
Avec EFS :
- Même workflow, mais le code est sur un montage NFS
- Terminaison → vous relancez une MicroVM, EFS est remonté, code intact
- Partage possible : plusieurs développeurs peuvent monter le même EFS (ou des Access Points différents) pour du pair programming
Étape 7 : proxy local pour l'accès navigateur
Un navigateur ne peut pas injecter le header X-aws-proxy-auth sur chaque requête HTTP et WebSocket. Pour accéder à OpenVSCode Server depuis votre poste, vous avez besoin d'un proxy local qui :
- Écoute sur
http://localhost:8080 - Forward chaque requête vers l'endpoint HTTPS de la MicroVM en ajoutant le token d'authentification
- Gère les upgrades WebSocket (indispensables pour le terminal et le LSP de VS Code) en passant le token via les subprotocols
lambda-microvms - Renouvelle automatiquement le token avant expiration
Voici un proxy minimal en Node.js :
// proxy.mjs — Proxy local d'authentification Lambda MicroVM
import http from "node:http";
import https from "node:https";
import { execSync } from "node:child_process";
const MICROVM_ID = process.env.MICROVM_ID;
const MICROVM_ENDPOINT = process.env.MICROVM_ENDPOINT;
const REGION = process.env.AWS_REGION || "eu-west-1";
const LOCAL_PORT = parseInt(process.env.PORT || "8080", 10);
const TOKEN_EXPIRATION_MINUTES = parseInt(process.env.TOKEN_EXPIRATION || "60", 10);
let authToken = null;
let tokenExpiresAt = 0;
function refreshToken() {
const cmd = `aws lambda-microvms create-microvm-auth-token \
--microvm-identifier ${MICROVM_ID} \
--expiration-in-minutes ${TOKEN_EXPIRATION_MINUTES} \
--allowed-ports '[{"allPorts":{}}]' \
--region ${REGION} --output json`;
const result = JSON.parse(execSync(cmd, { encoding: "utf-8" }));
authToken = result.authToken["X-aws-proxy-auth"];
tokenExpiresAt = Date.now() + (TOKEN_EXPIRATION_MINUTES - 5) * 60_000;
}
function getToken() {
if (!authToken || Date.now() >= tokenExpiresAt) refreshToken();
return authToken;
}
function getEndpoint() {
if (MICROVM_ENDPOINT) return MICROVM_ENDPOINT;
const cmd = `aws lambda-microvms get-microvm --microvm-identifier ${MICROVM_ID} --region ${REGION} --output json`;
return JSON.parse(execSync(cmd, { encoding: "utf-8" })).endpoint;
}
const endpoint = getEndpoint();
// Forward HTTP
async function handleRequest(req, res) {
const chunks = [];
for await (const chunk of req) chunks.push(chunk);
const body = Buffer.concat(chunks);
const headers = { ...req.headers, host: endpoint, "x-aws-proxy-auth": getToken() };
delete headers.connection;
const proxyReq = https.request(
{ hostname: endpoint, port: 443, path: req.url, method: req.method, headers },
(proxyRes) => {
res.writeHead(proxyRes.statusCode, proxyRes.headers);
proxyRes.pipe(res);
}
);
proxyReq.on("error", () => { res.writeHead(502); res.end("Bad Gateway"); });
if (body.length) proxyReq.write(body);
proxyReq.end();
}
// Forward WebSocket upgrades
function handleUpgrade(req, socket, head) {
const token = getToken();
const headers = { ...req.headers, host: endpoint, connection: "Upgrade", upgrade: "websocket" };
// Injecter le token via subprotocols WebSocket
const existing = headers["sec-websocket-protocol"]?.split(",").map((p) => p.trim()) || [];
headers["sec-websocket-protocol"] = [
"lambda-microvms",
`lambda-microvms.authentication.${token}`,
"lambda-microvms.port.8080",
...existing,
].join(", ");
headers["x-aws-proxy-auth"] = token;
const proxyReq = https.request({ hostname: endpoint, port: 443, path: req.url, method: "GET", headers });
proxyReq.on("upgrade", (proxyRes, proxySocket, proxyHead) => {
// Filtrer les subprotocols lambda-microvms de la réponse
let responseHead = "HTTP/1.1 101 Switching Protocols\r\n";
for (const [key, value] of Object.entries(proxyRes.headers)) {
if (key.toLowerCase() === "sec-websocket-protocol") {
const filtered = value.split(",").map((p) => p.trim()).filter((p) => !p.startsWith("lambda-microvms"));
if (filtered.length) responseHead += `${key}: ${filtered.join(", ")}\r\n`;
continue;
}
responseHead += `${key}: ${value}\r\n`;
}
responseHead += "\r\n";
socket.write(responseHead);
if (proxyHead.length) socket.write(proxyHead);
proxySocket.pipe(socket);
socket.pipe(proxySocket);
proxySocket.on("error", () => socket.destroy());
socket.on("error", () => proxySocket.destroy());
});
proxyReq.on("response", (proxyRes) => {
let resp = `HTTP/1.1 ${proxyRes.statusCode} ${proxyRes.statusMessage}\r\n`;
for (const [k, v] of Object.entries(proxyRes.headers)) resp += `${k}: ${v}\r\n`;
resp += "\r\n";
socket.write(resp);
proxyRes.pipe(socket);
});
proxyReq.on("error", () => socket.destroy());
proxyReq.end();
}
const server = http.createServer(handleRequest);
server.on("upgrade", handleUpgrade);
server.listen(LOCAL_PORT, () => {
console.log(`MicroVM proxy → http://localhost:${LOCAL_PORT} → https://${endpoint}`);
});
Utilisation :
# Lancer le proxy
MICROVM_ID=mvm-01234567-abcd-ef01-2345-6789abcdef01 \
MICROVM_ENDPOINT=mvm-01234567-abcd-ef01-2345-6789abcdef01.lambda-microvm.eu-west-1.on.aws \
node proxy.mjs
# Ouvrir VS Code dans le navigateur
open http://localhost:8080
Le proxy renouvelle le token 5 minutes avant expiration, gère le protocole WebSocket avec les subprotocols lambda-microvms (requis par l'endpoint), et filtre ces subprotocols de la réponse pour ne pas perturber VS Code côté client.
Pourquoi un proxy local ? L'endpoint MicroVM est un service managé par Lambda avec authentification JWE obligatoire — il n'est pas possible de placer un ALB ou un CloudFront devant. Il n'y a pas non plus d'option d'accès non authentifié ni de custom domain. Le proxy local (ou un proxy déployé sur une instance/container dans votre VPC) est le pattern d'accès navigateur recommandé pour les cas interactifs comme un IDE.
Comparaison avec les alternatives
| Critère | Cloud9 (ancien) | CodeCatalyst Dev Env | Lambda MicroVM + VS Code |
|---|---|---|---|
| Coût idle | Instance EC2 24/7 | Stoppé = gratuit | Suspendu = ~0$ compute |
| Démarrage | ~60s (boot EC2) | ~30-60s | ~2s (resume snapshot) |
| Isolation | Shared tenancy | Container | Firecracker VM dédiée |
| Personnalisation | Limitée | Devfile | Dockerfile complet |
| Persistance | EBS | EBS | Suspend/resume + EFS optionnel |
| Durée max session | Illimitée | 16h (puis stop auto) | 8h |
| GPU | Non | Non | Non (ARM64 uniquement) |
Considérations de sécurité et bonnes pratiques
- IAM least privilege : le rôle d'exécution ne doit avoir accès qu'aux services nécessaires au développeur. Le rôle de l'opérateur network connector se limite à la création d'ENIs
- VPC egress connector : routez le trafic sortant via un subnet privé avec un NAT Gateway pour l'accès internet, et des security groups pour contrôler l'accès aux ressources internes (EFS, RDS...)
- Authentification : chaque requête vers l'endpoint MicroVM nécessite un token JWE (
X-aws-proxy-auth). Scopez les tokens sur le port 8080 uniquement et avec une expiration courte pour les environnements partagés - Chiffrement : EFS chiffré at-rest (KMS) + in-transit (NFS over TLS). Le trafic entre le client et l'endpoint MicroVM est toujours chiffré en TLS
- Logs : les logs de build et d'exécution sont dans CloudWatch sous
/aws/lambda/microvms/<image-name>. Chaquerun-microvmest tracé dans CloudTrail
Conclusion
Lambda MicroVMs n'est pas juste un nouveau service — c'est un changement de paradigme dans la façon dont on conçoit les environnements de calcul éphémères sur AWS. La combinaison d'une isolation hardware Firecracker, d'un démarrage quasi-instantané depuis snapshot, et d'un modèle de facturation à 0$ pendant la suspension ouvre des possibilités qui étaient auparavant réservées à des startups spécialisées comme E2B ou Daytona.
Que ce soit pour des bastions JIT qui réduisent votre surface d'attaque, des sandboxes d'agents IA qui exécutent du code non fiable en toute sécurité, ou un IDE cloud DIY qui remplace Cloud9 — Lambda MicroVMs mérite une place dans votre boîte à outils architecturale.
Le tutoriel présenté ici avec OpenVSCode Server + EFS est un point de départ. Vous pouvez l'enrichir avec du pair programming (multiple Access Points), des templates par projet (une image MicroVM par stack technique), ou même un système de facturation interne par développeur grâce aux tags CloudWatch.
Sources :

