``` > /dev/sda: 我如何制作一个能运行 wget | dd 的 Linux 发行版 ```
curl > /dev/sda: How I made a Linux distro that runs wget | dd

原始链接: https://astrid.tech/2026/03/24/0/curl-to-dev-sda/

## 通过 `wget | dd` 安装 Linux 发行版:深入研究 本文详细介绍了作者使用直接写入磁盘管道 `wget | dd` 创建 Linux 发行版安装方法的过程。受到“curl | sh”争论和避免小额云存储成本的启发,作者探索了通过直接将磁盘镜像流式传输到设备(如 `/dev/sda`)来绕过传统的安装方法。 该过程从复制旧的 Raspberry Pi 镜像写入方法(下载,然后 `dd`)发展到完全消除中间文件。这是因为 Unix 将设备视为文件,允许直接写入。作者随后着手解决重新镜像正在运行的 VM 的挑战,发现覆盖已挂载的操作系统磁盘是可行的,但风险很高——导致大约 78% 完成时崩溃。 解决方案?启动到救援镜像(如 Contabo 提供的 Debian)以获取访问权限并在未挂载的系统上运行 `wget | dd` 命令。这引发了进一步的自动化尝试,质疑甚至救援镜像的必要性,并思考完全内存交换以实现完整、自包含安装的可能性。作者利用 NixOS 的自动化镜像创建工具来简化流程。

## Linux 发行版通过 `wget | dd`:一则 Hacker News 摘要 一则 Hacker News 讨论围绕着一篇博客文章展开,文章详细介绍了如何创建一个最小的 Linux 发行版,使其能够仅通过 `wget | dd` 命令运行——本质上是下载并直接写入磁盘镜像。作者成功构建了一个包含 `busybox`、`wget` 和 `dd` 的 6.1MB initramfs 来实现这一点。 对话探讨了写入已挂载文件系统的固有风险,用户建议使用只读重新挂载、`pivot_root`、kexec 以及利用 initramfs 环境等解决方法。 许多评论者分享了类似的“粗糙”但可用的系统替换方法,包括使用网络启动、基于 rsync 的更新,甚至使用软盘时代的技巧。 讨论强调了在受限环境(如某些 VPS 提供商)中配置系统所面临的挑战,以及对更简单、更直接的安装方法的需求。 虽然承认这种方法的“YOLO”精神,用户也指出了潜在的陷阱和更安全的替代方案。 作者确认该系列文章的后续部分将解决一些提出的问题。
相关文章

原文

How I made a Linux distro that runs `wget | dd`

Linux http

To replace your Linux installation with a new OS, you can download a pre-prepared disk image directly to your disk by running a command like this:

curl https://something.example/foo.img > /dev/sda # (or whatever your disk is called)

No need to save it anywhere first, just pipe it directly to the disk. Then you can reboot into that OS, and congratulations, you’ve installed a new OS. This works even for most EFI machines without any further efibootmgr commands because EFI firmware automatically discovers the new EFI system partition!

Why?

This command is possible because /dev/sdX, /dev/nvmeX, and other such disks can be directly accessed from the filesystem, following the ancient Unix concept of “everything is a file.” You can write to the /dev/sdX file, and that directly writes to the disk!

No, like, why would you want to do this instead of installing Linux any other normal way?

Okay, so the reason I initially did this was because I didn’t want to pay Contabo an extra $1.50/mo to have object storage just to be able to spawn VPSes from premade disk images.

I thought it was a neat trick, a funny shitpost that riffs on the eternal curl | sh debate. I could write a blog post about it, I tell you about how you can do it yourself, one thousand words, I learn something, you learn something, I get internet points, win win.

The problem is that it didn’t stop there. I kept asking one more question. I kept peeling one more layer off the onion. I kept turning one more page in the grimoire… and before I knew it, I ended up with a four part blog series that doesn’t end where you expect it to end.

Why don’t we start from the beginning?

How to flash a Raspberry Pi the cool way

Nowadays, the Raspberry Pi Foundation gives you a piece of software that they built that does everything automatically, but back in my day, you had to do it this way.

There’s a Stack Exchange answer that lists the exact series of steps.

  1. First, you go to the website in your web browser.
  2. Then, you click on the button to download the image.
  3. Then, quoting directly from that answer:

Copy the contents of the image file onto the SD card by running

sudo dd bs=1M if=your_image_file_name.img of=/dev/sdx

Yeah, they also said to sha256sum the image, but let’s be honest, nobody fucking does that, not even Caligula users.

lazier?

Now, a logical first improvement to this step is, rather than navigating through the web browser, you can just wget or curl that file from the command line to begin with if you already know the URL. So, you can run:

wget -O disk.img https://www.raspberrypi.com/whatever
sudo dd bs=1M if=disk.img of=/dev/sdx

lazier.

But of course, nothing says you have to download it to a file first. dd will read from stdin if you don’t give it an if= argument. So you can pipe into dd and that achieves the same effect without writing any intermediate files.

curl https://www.raspberrypi.com/whatever | sudo dd bs=1M of=/dev/sdx

lazier!

But of course, nothing says you have to use dd. That just makes your writes to the disk more efficient because of block alignment and caching nonsense. You can just redirect stdout like so:

sudo -i
curl https://www.raspberrypi.com/whatever > /dev/sdx

And congratulations, you have derived the initial shitpost premise from first principles.

it was compressed oops

I glossed over the fact that the Stack Exchange article also tells you that the disk image comes as a zip file that you need to unzip first. But that’s a nice segue, because it turns out there are plenty of other variations on this:

# You may need to unzip your thing
curl https://something.example/foo.img.gz | gunzip | dd bs=1M of=/dev/sda status=progress
# You can use wget
wget -O- https://something.example/foo.iso | dd bs=1M of=/dev/sda status=progress
# You can upload via SSH
gzip -vc disk.img | ssh my-server.example -- sh -c 'gunzip -vc | dd bs=1M of=/dev/sda status=progress'

I mean frankly, there’s an infinite number of ways to write directly from the network to the disk!

sillier?

Okay, so now, let’s say you have a VM running in Contabo, booted off of /dev/sda, that you wanted to reimage with your own OS image. What do we need to do to adapt this method to that?

Making your own bootable OS image

Of course, you do need to figure out how to make such an OS image first. Luckily, you can do this for any OS (even Windows!) by installing it in a VM first, and then using the raw disk image that results from that.

To do that with QEMU, you need to first make a raw disk, preferably of a fairly small size (you should be able to expand it once you’ve copied it).

truncate 10G disk.img

Then, you can run your OS with installer like so:

qemu-system-x86_64
	-hda ./disk.qcow2 \
	-m 2G \
	-enable-kvm \
	-nic user \
	-serial mon:stdio

Go through all the setup steps, and you’re done. You can now send disk.img off to your webserver.

Of course, I use NixOS btw so this entire process was automated! I just did import <nixpkgs/nixos/lib/make-disk-image.nix> and that got me a disk image. If you use Nix as well, you can learn how to use it by reading its documented source code.

Unmounting the disk

Now that we’ve made the disk image, we need to unmount the victim disk. This is a very easy process. You just type in umount /dev/sdwhatever or umount /dev/nvmewhatever, like

root@localhost:~# umount /dev/sda1
umount: /: target is busy.

Oh. Right. The disk we’re trying to replace is the OS’s main disk. The one the OS is running off of.

Well, what can we try instead?

write to the mounted disk anyways. fuck you

The OS may stop you from unmounting /dev/sda1, but it won’t stop you from writing to /dev/sda1 or /dev/sda even if there’s something mounted! How do you think parted, gparted, and fdisk work on live systems?

I ran the following command to upload, and typed in my password:

astrid@chungus infra ❯ gzip -vc result/nixos.img | ssh [email protected] -- bash -c 'gunzip -vc > /dev/sda'
[email protected]'s password:

Now, I tried this out expecting that it probably wouldn’t work. Sure, programs have to get loaded into memory to run, so maybe this might work. But also, given that a whole bunch of other things are happening on the machine at the same time besides the rewrite, doing this may cause those other processes to trigger a kernel panic.

But theory means nothing in the face of practice.

The command had no output, but iftop was indicating that something was happening:

                        191Mb                   381Mb                   572Mb                   763Mb              954Mb
&boxur;&boxh;&boxh;&boxh;&boxh;&boxh;&boxh;&boxh;&boxh;&boxh;&boxh;&boxh;&boxh;&boxh;&boxh;&boxh;&boxh;&boxh;&boxh;&boxh;&boxh;&boxh;&boxh;&boxh;&boxhu;&boxh;&boxh;&boxh;&boxh;&boxh;&boxh;&boxh;&boxh;&boxh;&boxh;&boxh;&boxh;&boxh;&boxh;&boxh;&boxh;&boxh;&boxh;&boxh;&boxh;&boxh;&boxh;&boxh;&boxhu;&boxh;&boxh;&boxh;&boxh;&boxh;&boxh;&boxh;&boxh;&boxh;&boxh;&boxh;&boxh;&boxh;&boxh;&boxh;&boxh;&boxh;&boxh;&boxh;&boxh;&boxh;&boxh;&boxh;&boxhu;&boxh;&boxh;&boxh;&boxh;&boxh;&boxh;&boxh;&boxh;&boxh;&boxh;&boxh;&boxh;&boxh;&boxh;&boxh;&boxh;&boxh;&boxh;&boxh;&boxh;&boxh;&boxh;&boxh;&boxhu;&boxh;&boxh;&boxh;&boxh;&boxh;&boxh;&boxh;&boxh;&boxh;&boxh;&boxh;&boxh;&boxh;&boxh;&boxh;&boxh;&boxh;&boxh;&boxh;&boxh;&boxh;&boxh;&boxh;
chungus.lan                                    => myhost.example.                                32.9Mb  22.3Mb  16.6Mb
                                               <=                                                 424Kb   302Kb   228Kb

After waiting for a little while, the program terminated with the following output:

astrid@chungus infra ❯ gzip -vc result/nixos.img | ssh [email protected] -- bash -c 'gunzip -vc > /dev/sda'
[email protected]'s password:
 77.8% -- replaced with stdout

What happened here?

Well, we tried to overwrite the OS while it was in use, and that caused it to crash 77.8% of the way through! A whole bunch of things could have happened, and the exact crash detail could be interesting, but the sum of it is that we did something stupid and caused something stupid.

Maybe it’s a good idea to unmount the device before writing to it after all.

Still, though, we have to think about the implications here. How do you unmount your OS’s disk while keeping the OS running to be able to overwrite itself?

This may sound like some kind of paradoxical Buddhist meditation riddle, but the solution is actually quite simple: just boot into a new OS where the old one isn’t mounted!

Rescue images to the rescue

Most Linux distros’ installers have all the requisite programs preinstalled, along with networking. Arch and NixOS installers are perfect for this purpose! Fedora installer can even be used for this too. You can piggyback off of them without even running the actual installer included with them! As long as you have networking and terminal access, you can run curl > /dev/sda to your heart’s content.

This was, in fact, the option I went with to overwrite my Contabo VMs. Contabo lets you boot into a Debian-based rescue image instead of whatever’s installed on the disk they give you, so I booted into that, and managed to wget -O- > /dev/sda and get my new OS installed!

I did this once, and I was happy.

Then I did it a second time, and thought, “isn’t there a way to automate this?”

Also, do we really need a second disk?

No really, just think about it. All of the utilities needed to overwrite the disk already exist on the disk before you overwrite it. In theory, you could just copy all of those utilities into RAM, unmount everything else, and overwrite the disk from RAM to achieve an in-place swap.

Disks and boot can’t possibly be that magical… can they?

联系我们 contact @ memedata.com