#!/usr/bin/env python3 import os import socket import subprocess import uuid from flask import Flask, request, render_template_string, flash app = Flask(__name__) app.secret_key = os.environ.get("MICROCONTAINERS_SECRET_KEY", "dev-only-not-secret") # --- Config ----------------------------------------------------------------- IMAGES = { "debian": { "docker_image": "micro-debian-dev:latest", "label": "Debian Dev Box (micro-debian-dev)" }, "fedora": { "docker_image": "micro-fedora43-dev:latest", "label": "Fedora 43 Dev Box (micro-fedora43-dev)" }, } DEFAULT_IMAGE_KEY = "debian" DATA_ROOT = "/srv/microcontainers" # per-tenant metadata + disk.img MOUNT_ROOT = "/mnt/microcontainers" # where disk.img files are mounted HOSTNAME = "arthur.lan" # or "mentalnet.xyz" if you prefer PORT_RANGE_START = 20000 PORT_RANGE_END = 21000 os.makedirs(DATA_ROOT, exist_ok=True) os.makedirs(MOUNT_ROOT, exist_ok=True) # --- Helpers ---------------------------------------------------------------- def find_free_port(start=PORT_RANGE_START, end=PORT_RANGE_END): """Find a free TCP port on the host in the given range.""" for port in range(start, end): with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s: s.settimeout(0.2) try: s.bind(("", port)) return port except OSError: continue raise RuntimeError("No free ports available in range") def validate_ssh_key(key: str) -> bool: """Very basic SSH public key validation.""" key = key.strip() if not key: return False allowed_prefixes = ( "ssh-ed25519", "ssh-rsa", "ecdsa-sha2-", "sk-ssh-", ) return any(key.startswith(p) for p in allowed_prefixes) def is_mounted(mount_point: str) -> bool: """Check if a given mount point is already mounted.""" try: with open("/proc/mounts", "r") as f: for line in f: parts = line.split() if len(parts) >= 2 and parts[1] == mount_point: return True except FileNotFoundError: pass return False def ensure_tenant_disk(container_name: str, ssh_key: str, size_gb: int = 3) -> str: """ Ensure a per-tenant disk.img exists, is formatted, mounted, and has .ssh/authorized_keys populated. Returns the host mount point path, which will be bind-mounted to /home/micro. """ tenant_root = os.path.join(DATA_ROOT, container_name) os.makedirs(tenant_root, exist_ok=True) disk_img = os.path.join(tenant_root, "disk.img") mount_point = os.path.join(MOUNT_ROOT, container_name) os.makedirs(mount_point, exist_ok=True) # 1) Create sparse disk.img if it doesn't exist if not os.path.exists(disk_img): subprocess.run(["fallocate", "-l", f"{size_gb}G", disk_img], check=True) subprocess.run(["mkfs.ext4", "-F", disk_img], check=True) # 2) Mount it if not already mounted if not is_mounted(mount_point): subprocess.run(["mount", "-o", "loop", disk_img, mount_point], check=True) # 3) Prepare /home/micro layout inside the filesystem # (we're mounting this whole thing as /home/micro in the container) ssh_dir = os.path.join(mount_point, ".ssh") os.makedirs(ssh_dir, exist_ok=True) auth_keys_path = os.path.join(ssh_dir, "authorized_keys") with open(auth_keys_path, "w") as f: f.write(ssh_key.strip() + "\n") # Proper perms for SSH os.chmod(ssh_dir, 0o700) os.chmod(auth_keys_path, 0o600) # Make everything in /home/micro look like micro:micro (uid/gid 1000) subprocess.run(["chown", "-R", "1000:1000", mount_point], check=True) return mount_point def run_docker_container(container_name: str, host_port: int, docker_image: str, home_mount: str): """ Start the tenant container: - Binds host_port -> container:22 - Mounts per-tenant 3GB disk as /home/micro """ cmd = [ "docker", "run", "-d", "--name", container_name, "--memory=512m", "--memory-swap=512m", "-p", f"{host_port}:22", "-v", f"{home_mount}:/home/micro", docker_image, ] subprocess.run(cmd, check=True) # --- Template --------------------------------------------------------------- INDEX_TEMPLATE = """
This prototype spins up a small Docker-based "micro VM" and wires in your SSH public key.
{{ key }}: {{ info.label }}micro3 GB (loopback ext4)port 22{{ port_start }}-{{ port_end }}Image: {{ result.image_key }} — {{ images[result.image_key].label }}
Container name: {{ result.name }}
Host port: {{ result.port }}
SSH command:
ssh micro@{{ hostname }} -p {{ result.port }}
You can change the password for micro after logging in with:
passwd