Prepare, configure, and manage Firecracker microVMs in seconds!
virtualization linux microvm firecracker
8
fork

Configure Feed

Select the types of activity you want to include in your feed.

add support for alpine microVM

+122 -2
+1 -1
README.md
··· 8 8 9 9 ## Features 10 10 11 - - **Quick Setup**: Prepares linux kernel, Ubuntu rootfs, and SSH keys in one command. 11 + - **Quick Setup**: Prepares linux kernel, Ubuntu/Debian/Alpine rootfs, and SSH keys in one command. 12 12 - **Seamless VM Management**: Start, stop, and monitor Firecracker microVMs with intuitive subcommands. 13 13 - **Network Configuration**: Automatically sets up TAP devices, IP forwarding, and NAT for connectivity. 14 14 - **SSH Access**: Easily connect to the microVM via SSH.
+10
crates/firecracker-prepare/src/downloader.rs
··· 160 160 run_command_with_stdout_inherit("wget", &["-O", output, url], false)?; 161 161 Ok(()) 162 162 } 163 + 164 + pub fn download_alpine_rootfs(minirootfs: &str, arch: &str) -> Result<()> { 165 + let app_dir = crate::config::get_config_dir()?; 166 + let output = format!("{}/alpine-{}.tar.gz", app_dir, arch); 167 + const ALPINE_VERSION: &str = "3.22"; 168 + download_file(&format!("https://mirrors.aliyun.com/alpine/v{}/releases/x86_64/alpine-minirootfs-{}.0-{}.tar.gz", ALPINE_VERSION, ALPINE_VERSION, arch), &output)?; 169 + run_command("mkdir", &["-p", minirootfs], true)?; 170 + run_command("tar", &["-xzf", &output, "-C", minirootfs], true)?; 171 + Ok(()) 172 + }
+111 -1
crates/firecracker-prepare/src/lib.rs
··· 11 11 pub mod rootfs; 12 12 pub mod ssh; 13 13 14 + pub const GUEST_IP: &str = "172.16.0.2"; 15 + 14 16 #[derive(Default, Clone)] 15 17 pub struct PrepareOptions { 16 18 pub debian: Option<bool>, ··· 136 138 137 139 pub fn prepare_alpine(arch: &str) -> Result<(String, String, String)> { 138 140 let kernel_file = downloader::download_kernel(arch)?; 139 - unimplemented!("Alpine preparation is not implemented yet."); 141 + let app_dir = config::get_config_dir()?; 142 + let minirootfs = format!("{}/minirootfs", app_dir); 143 + downloader::download_alpine_rootfs(&minirootfs, arch)?; 144 + 145 + run_command( 146 + "sh", 147 + &[ 148 + "-c", 149 + &format!("echo 'nameserver 8.8.8.8' > {}/etc/resolv.conf", minirootfs), 150 + ], 151 + true, 152 + )?; 153 + if !run_command("chroot", &[&minirootfs, "which", "sshd"], true) 154 + .map(|output| output.status.success()) 155 + .unwrap_or(false) 156 + { 157 + run_command_with_stdout_inherit("chroot", &[&minirootfs, "apk", "update"], true)?; 158 + run_command_with_stdout_inherit( 159 + "chroot", 160 + &[ 161 + &minirootfs, 162 + "apk", 163 + "add", 164 + "alpine-base", 165 + "util-linux", 166 + "linux-virt", 167 + "haveged", 168 + "openssh", 169 + ], 170 + true, 171 + )?; 172 + } 173 + 174 + run_command_with_stdout_inherit( 175 + "chroot", 176 + &[&minirootfs, "rc-update", "add", "haveged"], 177 + true, 178 + )?; 179 + run_command( 180 + "chroot", 181 + &[ 182 + &minirootfs, 183 + "sh", 184 + "-c", 185 + "for svc in devfs procfs sysfs; do ln -fs /etc/init.d/$svc /etc/runlevels/boot; done", 186 + ], 187 + true, 188 + )?; 189 + if !run_command( 190 + "chroot", 191 + &[ 192 + &minirootfs, 193 + "ln", 194 + "-s", 195 + "agetty", 196 + "/etc/init.d/agetty.ttyS0", 197 + ], 198 + true, 199 + ) 200 + .map(|output| output.status.success()) 201 + .unwrap_or(false) 202 + { 203 + println!("[!] Failed to create symlink for agetty.ttyS0, please check manually."); 204 + } 205 + run_command_with_stdout_inherit( 206 + "chroot", 207 + &[&minirootfs, "sh", "-c", "echo ttyS0 > /etc/securetty"], 208 + true, 209 + )?; 210 + run_command( 211 + "chroot", 212 + &[&minirootfs, "rc-update", "add", "agetty.ttyS0", "default"], 213 + true, 214 + )?; 215 + 216 + run_command("chroot", &[&minirootfs, "rc-update", "add", "sshd"], true)?; 217 + run_command( 218 + "chroot", 219 + &[&minirootfs, "rc-update", "add", "networking", "boot"], 220 + true, 221 + )?; 222 + run_command( 223 + "chroot", 224 + &[&minirootfs, "mkdir", "-p", "/root/.ssh", "/etc/network"], 225 + true, 226 + )?; 227 + 228 + run_command( 229 + "chroot", 230 + &[ 231 + &minirootfs, 232 + "sh", 233 + "-c", 234 + &format!("echo 'auto eth0\niface eth0 inet static\n address {}\n netmask 255.255.255.0\n gateway 172.16.0.1\n' > /etc/network/interfaces", GUEST_IP), 235 + ], 236 + true, 237 + )?; 238 + 239 + let ssh_key_name = "id_rsa"; 240 + ssh::generate_and_copy_ssh_key(&ssh_key_name, &minirootfs)?; 241 + 242 + let ext4_file = format!("{}/alpine-{}.ext4", app_dir, arch); 243 + if !std::path::Path::new(&ext4_file).exists() { 244 + rootfs::create_ext4_filesystem(&minirootfs, &ext4_file, 500)?; 245 + } 246 + 247 + let ssh_key_file = format!("{}/{}", app_dir, ssh_key_name); 248 + 249 + Ok((kernel_file, ext4_file, ssh_key_file)) 140 250 }