server edition, first version complete
This commit is contained in:
parent
38a66427ce
commit
7c8ba859fb
6 changed files with 848 additions and 551 deletions
403
README.md
403
README.md
|
|
@ -1,142 +1,265 @@
|
|||
# 🚀 MNMIVM-SE (Server Edition)
|
||||
|
||||
# 🚀 MNMIVM
|
||||
|
||||
### *Fire-and-Forget Virtual Machines*
|
||||
### *A LAN-Native VM Cloud with a Minimal Control Plane*
|
||||
|
||||

|
||||
|
||||
**MNMIVM** is a minimal, single-binary VM launcher built on **QEMU + KVM + cloud-init**.
|
||||
It is designed for *fast iteration*, *ephemeral usage*, and *zero ceremony*.
|
||||
**MNMIVM-SE** is the **server-focused edition** of MNMIVM — a minimal, single-binary VM launcher built on **QEMU + KVM + cloud-init** that turns your **LAN into a local VM cloud**.
|
||||
|
||||
If Docker feels too constrained, and OpenStack / Proxmox feel like overkill — MNMIVM sits comfortably in the middle.
|
||||
Unlike traditional platforms, MNMIVM-SE exposes the raw infrastructure primitives directly:
|
||||
bridges, TAP devices, MAC addresses, static IPs, and Linux processes.
|
||||
|
||||
> Spin it up.
|
||||
> Get a random port.
|
||||
> SSH in.
|
||||
> Done.
|
||||
> Your LAN is the fabric.
|
||||
> The kernel is the scheduler.
|
||||
> The CLI is the control plane.
|
||||
|
||||
---
|
||||
|
||||
## ✨ What MNMIVM Is
|
||||
## ☁️ What MNMIVM-SE Is
|
||||
|
||||
* A **fire-and-forget VM launcher**
|
||||
* A **CLI-first** virtualization tool
|
||||
* A **thin orchestration layer**, not a platform
|
||||
* A way to spin up *real Linux VMs* without running a control plane
|
||||
* A **local VM cloud** built directly on your LAN
|
||||
* A **process-native control plane**
|
||||
* A **CLI-first infrastructure tool**
|
||||
* A Proxmox-style networking model **without Proxmox**
|
||||
|
||||
MNMIVM intentionally avoids:
|
||||
Each VM:
|
||||
- Has a persistent MAC address
|
||||
- Has a static IP on your LAN
|
||||
- Appears as a first-class network device
|
||||
- Can host real infrastructure services (DNS, CI, storage, routing, etc.)
|
||||
|
||||
* Long-lived port bindings
|
||||
* Static network assumptions
|
||||
* Cluster state
|
||||
* Databases
|
||||
* APIs
|
||||
* Daemons
|
||||
|
||||
It launches a VM, hands you SSH + VNC, and gets out of the way.
|
||||
Routers, firewalls, and switches see MNMIVM-SE VMs as **real machines**, not NAT artifacts.
|
||||
|
||||
---
|
||||
|
||||
## 🧠 Design Philosophy
|
||||
## 🧠 Control Plane Model
|
||||
|
||||
MNMIVM is built around a few hard rules:
|
||||
MNMIVM-SE **does have a control plane** — it’s just intentionally **minimal, local, and explicit**.
|
||||
|
||||
* **No background services**
|
||||
* **No required config files**
|
||||
* **No global state beyond `/var/lib/microvm`**
|
||||
* **Every VM is self-contained**
|
||||
* **Cloud-init is the source of truth**
|
||||
* **Root-only, explicit control**
|
||||
The control plane is implemented as:
|
||||
- A single CLI binary
|
||||
- A file-backed state store
|
||||
- Linux process lifecycle tracking
|
||||
|
||||
This makes MNMIVM ideal for:
|
||||
There is:
|
||||
- No always-on daemon
|
||||
- No API server
|
||||
- No database
|
||||
- No reconciliation loop
|
||||
- No scheduler service
|
||||
|
||||
* Homelabs
|
||||
* CI runners
|
||||
* Testing OS images
|
||||
* Disposable dev environments
|
||||
* Learning QEMU/KVM internals
|
||||
* “I just need a VM *right now*”
|
||||
Instead:
|
||||
|
||||
- VM lifecycle = Linux process lifecycle
|
||||
- State = files under `/var/lib/microvm`
|
||||
- Configuration changes = cloud-init regeneration
|
||||
- Access = SSH + VNC
|
||||
|
||||
> The filesystem is the state store.
|
||||
> `/proc` is the source of truth.
|
||||
> Each CLI command is a deliberate control action.
|
||||
|
||||
This makes MNMIVM-SE closer to **early private IaaS** and **bare-metal virtualization** than modern hyperscaler platforms.
|
||||
|
||||
---
|
||||
|
||||
## 🆚 How It Compares (At a Glance)
|
||||
## 🧱 Supported Host Operating Systems
|
||||
|
||||
| Feature | MNMIVM | Docker | LXC/LXD | Proxmox | OpenStack |
|
||||
| ---------------------- | ----------- | ------- | ------- | ------- | --------- |
|
||||
| Real VMs | ✅ | ❌ | ⚠️ | ✅ | ✅ |
|
||||
| Cloud-init | ✅ | ❌ | ⚠️ | ✅ | ✅ |
|
||||
| Requires Daemons | ❌ | ✅ | ✅ | ✅ | ✅ |
|
||||
| Random Ports | ✅ | ❌ | ❌ | ❌ | ❌ |
|
||||
| Cluster-aware | ❌ | ❌ | ⚠️ | ✅ | ✅ |
|
||||
| Stateful Control Plane | ❌ | ❌ | ⚠️ | ✅ | ✅ |
|
||||
| Setup Time | **Seconds** | Minutes | Minutes | Hours | Days |
|
||||
MNMIVM-SE is conservative about host support and only documents what is tested.
|
||||
|
||||
> MNMIVM behaves more like **`docker run` for VMs**, not like a cloud.
|
||||
### ✅ Supported
|
||||
|
||||
| Host OS | Version |
|
||||
|------|---------|
|
||||
| **Debian** | 12+ |
|
||||
| **Alpine Linux** | 3.22+ |
|
||||
|
||||
### 🕒 Coming Soon
|
||||
|
||||
| Host OS | Notes |
|
||||
|------|------|
|
||||
| Ubuntu | Netplan-based host networking support planned |
|
||||
|
||||
> Ubuntu is not currently documented due to netplan-specific bridge handling.
|
||||
> Support will be added, but is not a top priority.
|
||||
|
||||
### ❌ Not Supported
|
||||
|
||||
- Wi-Fi–only hosts
|
||||
- WSL / nested hypervisors
|
||||
- Desktop laptop setups expecting NAT
|
||||
|
||||
---
|
||||
|
||||
## 🧱 Architecture Overview
|
||||
|
||||
* **QEMU + KVM** for virtualization
|
||||
* **User-mode networking** (no bridges required)
|
||||
* **Cloud-init seed ISO** (`cidata`) for provisioning
|
||||
* **QCOW2 backing images**
|
||||
* **Ephemeral SSH + VNC ports**
|
||||
* **State stored on disk only**
|
||||
* **QEMU + KVM**
|
||||
* **Linux bridge (`br0`)**
|
||||
* **TAP devices**
|
||||
* **Cloud-init seed ISO**
|
||||
* **Static IP networking**
|
||||
* **VNC console for recovery**
|
||||
|
||||
```
|
||||
|
||||
/var/lib/microvm/
|
||||
├── images/ # Base cloud images
|
||||
├── images/
|
||||
└── vms/
|
||||
└── vm1/
|
||||
├── disk.qcow2
|
||||
├── seed.iso
|
||||
├── pubkey.pub
|
||||
├── os.name
|
||||
├── ssh.port
|
||||
├── vnc.port
|
||||
└── vm.pid
|
||||
```
|
||||
└── vm1/
|
||||
├── disk.qcow2
|
||||
├── seed.iso
|
||||
├── pubkey.pub
|
||||
├── os.name
|
||||
├── vm.ip
|
||||
├── vm.mac
|
||||
├── vnc.port
|
||||
└── vm.pid
|
||||
|
||||
No database.
|
||||
No API.
|
||||
````
|
||||
|
||||
No libvirt.
|
||||
No XML.
|
||||
No daemon.
|
||||
|
||||
---
|
||||
|
||||
## 📦 Supported Operating Systems
|
||||
## 🌐 Host Networking Requirements (CRITICAL)
|
||||
|
||||
| OS | Version | Boot Mode |
|
||||
| ------ | ----------- | --------- |
|
||||
| Ubuntu | 24.04 LTS | BIOS |
|
||||
| Debian | 13 (Trixie) | BIOS |
|
||||
| Fedora | 43 Cloud | BIOS |
|
||||
| Alpine | 3.22 | BIOS |
|
||||
MNMIVM-SE requires a **proper Linux bridge**.
|
||||
|
||||
> UEFI images are intentionally avoided for simplicity and reliability.
|
||||
### Example: `/etc/network/interfaces` (Debian)
|
||||
|
||||
```ini
|
||||
auto lo
|
||||
iface lo inet loopback
|
||||
|
||||
auto ens18
|
||||
iface ens18 inet manual
|
||||
|
||||
auto br0
|
||||
iface br0 inet static
|
||||
address 192.168.86.10
|
||||
netmask 255.255.255.0
|
||||
gateway 192.168.86.1
|
||||
dns-nameservers 1.1.1.1 8.8.8.8
|
||||
bridge_ports ens18
|
||||
bridge_stp off
|
||||
bridge_fd 0
|
||||
````
|
||||
|
||||
**Rules that must be followed:**
|
||||
|
||||
* The host IP must live on `br0`
|
||||
* The physical NIC must have no IP
|
||||
* Wi-Fi cannot be bridged
|
||||
* VMs attach via TAP devices
|
||||
|
||||
---
|
||||
|
||||
## 🔑 SSH & Identity Management
|
||||
## 🔥 Kernel Bridge Filtering (THIS WILL BREAK VMs)
|
||||
|
||||
* SSH keys are injected via **cloud-init**
|
||||
* Keys are **fully replaced**, not appended
|
||||
* Old keys are **revoked**
|
||||
* `update-cloud` regenerates the seed ISO
|
||||
* Changes apply on **next boot**
|
||||
Linux defaults can silently block bridged traffic.
|
||||
|
||||
This gives you **real identity revocation**, not just key sprawl.
|
||||
This **must** be disabled:
|
||||
|
||||
```bash
|
||||
cat /proc/sys/net/bridge/bridge-nf-call-iptables
|
||||
# must be 0
|
||||
```
|
||||
|
||||
If set to `1`, VMs will:
|
||||
|
||||
* Boot successfully
|
||||
* Have valid IPs
|
||||
* Be completely unreachable
|
||||
|
||||
### Fix (runtime)
|
||||
|
||||
```bash
|
||||
sudo sysctl -w net.bridge.bridge-nf-call-iptables=0
|
||||
sudo sysctl -w net.bridge.bridge-nf-call-ip6tables=0
|
||||
sudo sysctl -w net.bridge.bridge-nf-call-arptables=0
|
||||
```
|
||||
|
||||
### Persistent fix
|
||||
|
||||
`/etc/sysctl.d/99-bridge.conf`:
|
||||
|
||||
```ini
|
||||
net.bridge.bridge-nf-call-iptables = 0
|
||||
net.bridge.bridge-nf-call-ip6tables = 0
|
||||
net.bridge.bridge-nf-call-arptables = 0
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 📀 Disk Behavior
|
||||
## 🔐 QEMU Bridge Permissions
|
||||
|
||||
* Base disk size is **12GB** (configurable constant)
|
||||
* Uses **QCOW2 backing images**
|
||||
* Root filesystem auto-expands on first boot
|
||||
* Predictable, uniform VM sizing
|
||||
QEMU must be allowed to attach TAP devices.
|
||||
|
||||
This keeps resource usage balanced and intentional.
|
||||
### `/etc/qemu/bridge.conf`
|
||||
|
||||
```ini
|
||||
allow br0
|
||||
```
|
||||
|
||||
Verify helper:
|
||||
|
||||
```bash
|
||||
ls -l /usr/lib/qemu/qemu-bridge-helper
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🐧 Alpine Linux Host Notes (3.22+)
|
||||
|
||||
Alpine does not ship a hypervisor stack by default.
|
||||
|
||||
Install required packages:
|
||||
|
||||
```bash
|
||||
apk add \
|
||||
qemu-system-x86_64 \
|
||||
qemu-img \
|
||||
qemu-hw-display-virtio-vga \
|
||||
bridge-utils \
|
||||
cdrkit \
|
||||
go
|
||||
```
|
||||
|
||||
Notes:
|
||||
|
||||
* `cdrkit` provides `genisoimage`
|
||||
* `bridge-utils` provides `brctl`
|
||||
* `qemu-hw-display-virtio-vga` is required for VNC
|
||||
* No libvirt or services are used
|
||||
* OpenRC is sufficient
|
||||
|
||||
Alpine works well as a **minimal KVM host** once assembled.
|
||||
|
||||
---
|
||||
|
||||
## ⚙️ Server Edition Configuration (Code-Level)
|
||||
|
||||
Networking and sizing are configured **in code**, not via runtime flags.
|
||||
|
||||
Edit these constants in `main.go` (around lines 25–30):
|
||||
|
||||
```go
|
||||
// Networking
|
||||
bridgeName = "br0"
|
||||
lanCIDR = "192.168.86.0/24"
|
||||
lanGW = "192.168.86.1"
|
||||
lanDNS1 = "192.168.86.1"
|
||||
lanDNS2 = "8.8.8.8"
|
||||
|
||||
// VM sizing
|
||||
baseDiskSize = "12G"
|
||||
memMB = "1024"
|
||||
cpus = "1"
|
||||
```
|
||||
|
||||
This keeps runtime behavior explicit and predictable.
|
||||
|
||||
---
|
||||
|
||||
|
|
@ -145,95 +268,91 @@ This keeps resource usage balanced and intentional.
|
|||
### Create a VM
|
||||
|
||||
```bash
|
||||
sudo mnmivm create vm1 --os debian --pubkey-path ~/.ssh/id_ed25519.pub
|
||||
sudo mnmivm-se create vm1 \
|
||||
--os debian \
|
||||
--pubkey-path ~/.ssh/id_ed25519.pub \
|
||||
--ip 192.168.86.53
|
||||
```
|
||||
|
||||
### Start a VM
|
||||
|
||||
```bash
|
||||
sudo mnmivm start vm1
|
||||
sudo mnmivm-se start vm1
|
||||
```
|
||||
|
||||
### SSH in
|
||||
|
||||
```bash
|
||||
ssh debian@192.168.86.53
|
||||
```
|
||||
|
||||
### Stop a VM
|
||||
|
||||
```bash
|
||||
sudo mnmivm stop vm1
|
||||
sudo mnmivm-se stop vm1
|
||||
```
|
||||
|
||||
### Update SSH key (cloud-init)
|
||||
### Update cloud-init (SSH key / IP)
|
||||
|
||||
```bash
|
||||
sudo mnmivm update-cloud vm1 --pubkey-path newkey.pub
|
||||
```
|
||||
|
||||
### List VMs
|
||||
|
||||
```bash
|
||||
sudo mnmivm list
|
||||
```
|
||||
|
||||
### Delete a VM
|
||||
|
||||
```bash
|
||||
sudo mnmivm delete vm1
|
||||
# Requires typing YES in all caps
|
||||
sudo mnmivm-se update-cloud vm1 \
|
||||
--pubkey-path newkey.pub \
|
||||
--ip 192.168.86.54
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 📊 VM List Output
|
||||
## 🔑 Security Model
|
||||
|
||||
MNMIVM renders a clean Unicode table showing:
|
||||
* SSH key–only access
|
||||
* No password authentication
|
||||
* No root login
|
||||
* Static IPs (no DHCP ambiguity)
|
||||
* MAC addresses pinned via cloud-init
|
||||
* VNC console for recovery only
|
||||
|
||||
* Name
|
||||
* Running state
|
||||
* OS
|
||||
* SSH endpoint
|
||||
* VNC endpoint
|
||||
* SSH public key path
|
||||
|
||||
This makes it usable *without* scripting.
|
||||
This follows **server-grade discipline**, not container ergonomics.
|
||||
|
||||
---
|
||||
|
||||
## ⚠️ What MNMIVM Is Not
|
||||
## ⚠️ What MNMIVM-SE Is Not
|
||||
|
||||
* ❌ A cloud platform
|
||||
* ❌ A hypervisor manager
|
||||
* ❌ A replacement for Proxmox
|
||||
* ❌ A Kubernetes node orchestrator
|
||||
* ❌ A long-lived VM manager
|
||||
* ❌ A managed cloud service
|
||||
* ❌ A multi-tenant platform
|
||||
* ❌ A scheduler or orchestrator
|
||||
* ❌ A UI-driven system
|
||||
* ❌ A laptop-friendly NAT tool
|
||||
|
||||
If you want **policy, HA, scheduling, quotas, tenants** — use Proxmox or OpenStack.
|
||||
If you want **policy, HA, quotas, tenants**, use Proxmox or OpenStack.
|
||||
|
||||
If you want **a VM right now**, MNMIVM wins.
|
||||
If you want **direct control over real infrastructure**, MNMIVM-SE is the tool.
|
||||
|
||||
---
|
||||
|
||||
## 🧪 Project Status
|
||||
## 🐧 Why MNMIVM-SE Exists
|
||||
|
||||
* ✅ Actively working
|
||||
* ✅ Under ~600 lines of Go
|
||||
* ✅ No external Go dependencies
|
||||
* ⚠️ API not stabilized yet
|
||||
* ⚠️ CLI flags may evolve
|
||||
Because sometimes you don’t want:
|
||||
|
||||
This project is intentionally **hackable** and **readable**.
|
||||
* libvirt
|
||||
* XML
|
||||
* dashboards
|
||||
* APIs
|
||||
* orchestration layers
|
||||
|
||||
You want:
|
||||
|
||||
> “Put a VM on my LAN, give it an IP, and let me build infrastructure.”
|
||||
|
||||
MNMIVM-SE does exactly that — and nothing more.
|
||||
|
||||
---
|
||||
|
||||
## 🐧 Why MNMIVM Exists
|
||||
### ⚠️ Final Note
|
||||
|
||||
Sometimes you don’t want:
|
||||
If you break networking with MNMIVM-SE, it isn’t a bug.
|
||||
|
||||
* A cluster
|
||||
* A UI
|
||||
* A dashboard
|
||||
* A service mesh
|
||||
It’s Linux doing exactly what you told it to do.
|
||||
|
||||
You just want to:
|
||||
And that’s the point.
|
||||
|
||||
> “Launch a VM and throw it into orbit.”
|
||||
|
||||
That’s MNMIVM.
|
||||
|
||||
|
|
|
|||
Binary file not shown.
|
Before Width: | Height: | Size: 288 KiB After Width: | Height: | Size: 427 KiB |
2
build.sh
2
build.sh
|
|
@ -1,2 +1,2 @@
|
|||
#!/bin/sh
|
||||
go build -o ./mnmivm
|
||||
go build -o ./mnmivm-se
|
||||
|
|
|
|||
4
go.mod
4
go.mod
|
|
@ -1,3 +1,3 @@
|
|||
module tux-microvm
|
||||
module mnmivm
|
||||
|
||||
go 1.24.4
|
||||
go 1.19
|
||||
|
|
|
|||
BIN
mnmivm-se
Executable file
BIN
mnmivm-se
Executable file
Binary file not shown.
Loading…
Add table
Add a link
Reference in a new issue