port randomization added for VNC + SSH on run

This commit is contained in:
markmental 2025-12-15 14:35:36 -05:00
commit 1e7135b2d2
3 changed files with 20 additions and 12 deletions

1
.gitignore vendored Normal file
View file

@ -0,0 +1 @@
*.pub

31
main.go
View file

@ -4,10 +4,10 @@ import (
"fmt" "fmt"
"io" "io"
"net/http" "net/http"
"net"
"os" "os"
"os/exec" "os/exec"
"path/filepath" "path/filepath"
"strconv"
"strings" "strings"
) )
@ -48,7 +48,7 @@ var osImages = map[string]OSImage{
}, },
"alpine": { "alpine": {
Name: "alpine", Name: "alpine",
URL: "https://dl-cdn.alpinelinux.org/alpine/v3.22/releases/cloud/generic_alpine-3.22.2-x86_64-uefi-cloudinit-r0.qcow2", URL: "https://dl-cdn.alpinelinux.org/alpine/v3.22/releases/cloud/generic_alpine-3.22.2-x86_64-bios-cloudinit-r0.qcow2",
Filename: "alpine-3.22.qcow2", Filename: "alpine-3.22.qcow2",
User: "alpine", User: "alpine",
}, },
@ -121,15 +121,16 @@ Type YES (all caps) to confirm: `, name, dir)
} }
func sshPort(name string) int { func findFreePort() int {
if strings.HasPrefix(name, "vm") { l, err := net.Listen("tcp", "127.0.0.1:0")
if n, err := strconv.Atoi(strings.TrimPrefix(name, "vm")); err == nil { if err != nil {
return 2220 + n panic(err)
} }
} defer l.Close()
return 2222 return l.Addr().(*net.TCPAddr).Port
} }
func parseArg(args []string, key string) string { func parseArg(args []string, key string) string {
for i := 0; i < len(args)-1; i++ { for i := 0; i < len(args)-1; i++ {
if args[i] == key { if args[i] == key {
@ -256,7 +257,13 @@ func startVM(name string) {
os.Remove(pidFile(name)) os.Remove(pidFile(name))
} }
port := sshPort(name) port := findFreePort()
vncPort := findFreePort()
vncDisplay := vncPort - 5900
if vncDisplay < 0 {
panic("invalid VNC port allocation")
}
cmd := exec.Command( cmd := exec.Command(
"qemu-system-x86_64", "qemu-system-x86_64",
@ -267,7 +274,7 @@ func startVM(name string) {
"-smp", cpus, "-smp", cpus,
"-vga", "virtio", "-vga", "virtio",
"-display", "vnc=0.0.0.0:1", "-display", fmt.Sprintf("vnc=0.0.0.0:%d", vncDisplay),
"-drive", fmt.Sprintf("file=%s,if=virtio,format=qcow2", diskPath(name)), "-drive", fmt.Sprintf("file=%s,if=virtio,format=qcow2", diskPath(name)),
"-drive", fmt.Sprintf("file=%s,if=virtio,format=raw", seedISOPath(name)), "-drive", fmt.Sprintf("file=%s,if=virtio,format=raw", seedISOPath(name)),
@ -285,7 +292,7 @@ func startVM(name string) {
} }
fmt.Println("VM started:", name) fmt.Println("VM started:", name)
fmt.Println("VNC: localhost:5901") fmt.Printf("VNC: vnc://127.0.0.1:%d\n", vncPort)
fmt.Printf("SSH: ssh <user>@localhost -p %d\n", port) fmt.Printf("SSH: ssh <user>@localhost -p %d\n", port)
} }

BIN
microvm Executable file

Binary file not shown.