aboutsummaryrefslogtreecommitdiff
path: root/public/running-golang-application-as-pid1.html
diff options
context:
space:
mode:
Diffstat (limited to 'public/running-golang-application-as-pid1.html')
-rwxr-xr-xpublic/running-golang-application-as-pid1.html203
1 files changed, 203 insertions, 0 deletions
diff --git a/public/running-golang-application-as-pid1.html b/public/running-golang-application-as-pid1.html
new file mode 100755
index 0000000..814eecd
--- /dev/null
+++ b/public/running-golang-application-as-pid1.html
@@ -0,0 +1,203 @@
1<!doctype html><html lang=en-us><meta charset=utf-8><meta name=viewport content="width=device-width,initial-scale=1"><link href="data:image/x-icon;base64,AAABAAEAEBAAAAEAIABoBAAAFgAAACgAAAAQAAAAIAAAAAEAIAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAL69vf8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAv76+/8LBwQkAAAAAAAAAAAAAAAC+vb3/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAL+9vf/Bv78JAAAAAAAAAAAAAAAAu7q6/wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC7ubr/vr29CAAAAAAAAAAAy8nJAZ6foP8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAnqGj/6GipAoAAAAAHLjU/xcXHf/BwsL/I8XY/yPK3v8XGiD/IbjL/yPF2f8XGiD/Fxkf/yLF2f8gnK3/Fxog/62ztv8fwNf/FRcd/x271v8mz93/GRsi/xkXHf8p097/GiIp/xobIv8p0t3/KdPe/xocIv8fYmr/KNPe/xoZH/8aHCL/J87c/xy81/8VFxz/IsPZ/8zS0/8XGiD/Ir/R/yPH2/8XGiD/Fxkf/yPH2/8dd4T/GBog/yPJ3f8jyNr/uru9/xcUGv8cudb/EhITDKi5vRKlvMP/RUpOERwcHRAdOj4QHTk8EBwdHRAdNTgQHTo/EBwcHRAcHB0QSGduEKW4vf+koqQfHzg+EBqz0ewSFRv7EyMr/xq51vsTERb7ExUb+xq41fsau9j7ExUb+xiPp/sZudb7ExUb+xMVG/sZuNX/GKvI/BIUGfMdvdn/IrfL/xcaIP8n1eb/J9Dh/xkcIf8ZGR7/J8/f/xxCSv8ZGyH/J9Dg/ybQ4P8ZHCL/FSQs/yPK3/8UExj/GE1b/ybS5P8ZGB7/Ghwj/ynW5P8p2Ob/Ghwi/yWrtv8p1eH/Ghwi/xocIv8p1uT/J8XT/xkcIv8m1un/Hb7d/xUYH/8hzOr/HtHu/xcaIf8XGB//I8vi/xgxOv8XGSD/I8rg/yPK4P8XGiD/GUFL/yPP6f8SERj/Fhkh/x3A4f8AAAAAJ2f9/ydr//8mZPH/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAlYu38J2v//ydo/f8AAAAAAAAAAAd8/fkFqf//Iob8sAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMY39awWr//8FfP3/AAAAAAAAAAAFm/7/SfD//wR+/f8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAOB/f9B7v//BaX+/wAAAAAAAAAAQ878SAyZ/v9n1v4KAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADu9v8DDJb+/z3N/XgAAAAA3/sAAN/7AADf+wAA3/sAAAAAAAAAAAAAAAAAAN/7AAAAAAAAAAAAAAAAAAAAAAAAj/EAAI/5AACP8QAA3/sAAA==" rel=icon type=image/x-icon><title>Running Golang application as PID 1 with Linux kernel</title><meta name=description content="Unikernels, kernels, and alikeI have been reading a lot aboutunikernernels lately and found themvery intriguing."><link rel=alternate type=application/rss+xml title="Mitja Felicijan's posts" href=https://mitjafelicijan.com/index.xml><link rel=alternate type=application/rss+xml title="Mitja Felicijan's notes" href=https://mitjafelicijan.com/notes.xml><style>body{padding:1rem;max-width:760px;background:#fff;font-family:sans-serif;line-height:1.35rem;font-size:16px;margin:0 auto}hr{margin-block-start:1.5rem}h1,h2,h3{line-height:initial}h1{font-size:xx-large}footer{margin-block-start:2rem}cap{text-transform:capitalize}table{max-width:100%;width:100%;border-collapse:separate;border-spacing:2px;border:1px solid #000;border-left:1px solid #999;border-top:1px solid #999}blockquote{font-style:italic}table thead{background:#eee}ul.list li{padding:.2em 0}ul{line-height:1.4em}td,th{border:1px solid #000;padding:4px;border-right:1px solid #999;border-bottom:1px solid #999;text-align:left}pre{text-wrap:nowrap;overflow-x:auto;padding:0 1em;border:1px solid #dcdcdc}code{padding:0 3px;font-size:14px;border:0}pre code{line-height:1.3em}pre,code,pre *,code *{font-family:monospace}figure{margin-inline-start:0;margin-inline-end:0}figcaption{text-align:center}figcaption p{margin:.3em 0 0}img,video,audio{max-width:100%}header{display:flex;flex-direction:row;gap:3rem}nav{display:flex;gap:.75rem}nav.main{flex-grow:1}.pstatus-orange{background:gold}.pstatus-green{background:#9acd32}.pstatus-red{background:#cd5c5c}@media only screen and (max-width:600px){body{padding:15px}header{flex-direction:column;gap:1rem}a{word-wrap:break-word}}</style><header><nav class=main itemscope itemtype=http://schema.org/SiteNavigationElement role=toolbar><a href=/>Home</a>
2<a href=https://git.mitjafelicijan.com/ target=_blank>Git</a>
3<a href=https://files.mitjafelicijan.com/ target=_blank>Files</a>
4<a href=/radio.pls target=_blank>Radio</a>
5<a href=/mitjafelicijan.pgp.pub.txt target=_blank>PGP</a>
6<a href=/curriculum-vitae.html>CV</a>
7<a href=/index.xml target=_blank>RSS</a></nav></header><main role=main><article itemtype=http://schema.org/Article><h1 itemtype=headline>Running Golang application as PID 1 with Linux kernel</h1><p><cap>post</cap>, Dec 25, 2021 on <a href=https://mitjafelicijan.com>Mitja Felicijan's blog</a><div><h2 id=unikernels-kernels-and-alike>Unikernels, kernels, and alike</h2><p>I have been reading a lot about
8<a href=https://en.wikipedia.org/wiki/Unikernel>unikernernels</a> lately and found them
9very intriguing. When you push away all the marketing speak and look at the
10idea, it makes a lot of sense.<blockquote><p>A unikernel is a specialized, single address space machine image constructed
11by using library operating systems. (<a href=https://en.wikipedia.org/wiki/Unikernel>Wikipedia</a>)</blockquote><p>I really like the explanation from the article
12<a href="https://queue.acm.org/detail.cfm?id=2566628">Unikernels: Rise of the Virtual Library Operating System</a>.
13Really worth a read.<p>If we compare a normal operating system to a unikernel side by side, they would
14look something like this.<figure><img src=/posts/pid1/unikernels.png alt="Virtual machines vs Containers vs Unikernels"></figure><p>From this image, we can see how the complexity significantly decreases with
15the use of Unikernels. This comes with a price, of course. Unikernels are hard
16to get running and require a lot of work since you don't have an actual proper
17kernel running in the background providing network access and drivers etc.<p>So as a half step to make the stack simpler, I started looking into using
18Linux kernel as a base and going from there. I came across this
19<a href="https://www.youtube.com/watch?v=Sk9TatW9ino">Youtube video talking about Building the Simplest Possible Linux System</a>
20by <a href=https://landley.net>Rob Landley</a> and apart from statically compiling the
21application to be run as PID1 there was really no other obstacles.<h2 id=what-is-pid-1>What is PID 1?</h2><p>PID 1 is the first process that Linux kernel starts after the boot process.
22It also has a couple of unique properties that are unique to it.<ul><li>When the process with PID 1 dies for any reason, all other processes are
23killed with KILL signal.<li>When any process having children dies for any reason, its children are
24re-parented to process with PID 1.<li>Many signals which have default action of Term do not have one for PID 1.<li>When the process with PID 1 dies for any reason, kernel panics, which
25result in system crash.</ul><p>PID 1 is considered as an Init application which takes care of running other
26and handling services like:<ul><li>sshd,<li>nginx,<li>pulseaudio,<li>etc.</ul><p>If you are on a Linux machine, you can check what your process is with PID 1
27by running the following.<pre tabindex=0 style=background-color:#fff><code><span style=display:flex><span>$ cat /proc/1/status
28</span></span><span style=display:flex><span>Name: systemd
29</span></span><span style=display:flex><span>Umask: 0000
30</span></span><span style=display:flex><span>State: S (sleeping)
31</span></span><span style=display:flex><span>Tgid: 1
32</span></span><span style=display:flex><span>Ngid: 0
33</span></span><span style=display:flex><span>Pid: 1
34</span></span><span style=display:flex><span>PPid: 0
35</span></span><span style=display:flex><span>...
36</span></span></code></pre><p>As we can see on my machine the process with id of 1 is <a href=https://systemd.io/>systemd</a>
37which is a software suite that provides an array of system components for Linux
38operating systems. If you look closely you can also see that the <code>PPid</code>
39(process id of the parent process) is <code>0</code> which additionally confirms that
40this process doesn't have a parent.<h2 id=so-why-even-run-application-as-pid-1-instead-of-just-using-a-container>So why even run application as PID 1 instead of just using a container?</h2><p>Containers are wonderful, but they come with a lot of baggage. And because they
41are in their nature layered, the images require quite a lot of space and also a
42lot of additional software to handle them. They are not as lightweight as they
43seem, and many popular images require 500 MB plus disk space.<p>The idea of running this as PID 1 would result in a significantly smaller footprint,
44as we will see later in the post.<blockquote><p>You could run a simple init system inside Docker container described more
45in this article <a href=https://blog.phusion.nl/2015/01/20/docker-and-the-pid-1-zombie-reaping-problem/>Docker and the PID 1 zombie reaping problem</a>.</blockquote><h2 id=the-master-plan>The master plan</h2><ol><li>Compile Linux kernel with the default definitions.<li>Prepare a Hello World application in Golang that is statically compiled.<li>Run it with <a href=https://www.qemu.org/>QEMU</a> and providing Golang application
46as init application / PID 1.</ol><p>For the sake of simplicity we will not be cross-compiling any of it and just
47use the 64bit version.<h2 id=compiling-linux-kernel>Compiling Linux kernel</h2><pre tabindex=0 style=background-color:#fff><code><span style=display:flex><span>$ wget https://cdn.kernel.org/pub/linux/kernel/v5.x/linux-5.15.7.tar.xz
48</span></span><span style=display:flex><span>$ tar xf linux-5.15.7.tar.xz
49</span></span><span style=display:flex><span>
50</span></span><span style=display:flex><span>$ cd linux-5.15.7
51</span></span><span style=display:flex><span>
52</span></span><span style=display:flex><span>$ make clean
53</span></span><span style=display:flex><span>
54</span></span><span style=display:flex><span><span style=color:green># read more about this https://stackoverflow.com/a/41886394</span>
55</span></span><span style=display:flex><span>$ make defconfig
56</span></span><span style=display:flex><span>
57</span></span><span style=display:flex><span>$ time make -j <span style=color:#a31515>`</span>nproc<span style=color:#a31515>`</span>
58</span></span><span style=display:flex><span>
59</span></span><span style=display:flex><span>$ cd ..
60</span></span></code></pre><p>At this point we have kernel image that is located in <code>arch/x86_64/boot/bzImage</code>.
61We will use this in QEMU later.<p>To make our lives a bit easier lets move the kernel image to another place.
62Lets create a folder <code>bin/</code> in the root of our project with <code>mkdir -p bin</code>.<p>At this point we can copy <code>bzImage</code> to <code>bin/</code> folder with
63<code>cp linux-5.15.7/arch/x86_64/boot/bzImage bin/bzImage</code>.<p>The folder structure of this experiment should look like this.<pre><code>pid1/
64 bin/
65 bzImage
66 linux-5.15.7/
67 linux-5.15.7.tar.xz
68</code></pre><h2 id=preparing-pid-1-application-in-golang>Preparing PID 1 application in Golang</h2><p>This step is relatively easy. The only thing we must have in mind that we will
69need to compile the binary as a static one.<p>Let's create <code>init.go</code> file in the root of the project.<pre tabindex=0 style=background-color:#fff><code><span style=display:flex><span><span style=color:#00f>package</span> main
70</span></span><span style=display:flex><span>
71</span></span><span style=display:flex><span><span style=color:#00f>import</span> (
72</span></span><span style=display:flex><span> <span style=color:#a31515>&#34;fmt&#34;</span>
73</span></span><span style=display:flex><span> <span style=color:#a31515>&#34;time&#34;</span>
74</span></span><span style=display:flex><span>)
75</span></span><span style=display:flex><span>
76</span></span><span style=display:flex><span><span style=color:#00f>func</span> main() {
77</span></span><span style=display:flex><span> <span style=color:#00f>for</span> {
78</span></span><span style=display:flex><span> fmt.Println(<span style=color:#a31515>&#34;Hello from Golang&#34;</span>)
79</span></span><span style=display:flex><span> time.Sleep(1 * time.Second)
80</span></span><span style=display:flex><span> }
81</span></span><span style=display:flex><span>}
82</span></span></code></pre><p>If you notice, we have a forever loop in the main, with a simple sleep of 1
83second to not overwhelm the CPU. This is because PID 1 should never complete
84and/or exit. That would result in a kernel panic. Which is BAD!<p>There are two ways of compiling Golang application. Statically and dynamically.<p>To statically compile the binary, use the following command.<pre tabindex=0 style=background-color:#fff><code><span style=display:flex><span>$ go build -ldflags=<span style=color:#a31515>&#34;-extldflags=-static&#34;</span> init.go
85</span></span></code></pre><p>We can also check if the binary is statically compiled with:<pre tabindex=0 style=background-color:#fff><code><span style=display:flex><span>$ file init
86</span></span><span style=display:flex><span>init: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), statically linked, Go BuildID=Ypu8Zw_4NBxm1Yxg2OYO/H5x721rQ9uTPiDVh-VqP/vZN7kXfGG1zhX_qdHMgH/9vBfmK81tFrygfOXDEOo, not stripped
87</span></span><span style=display:flex><span>
88</span></span><span style=display:flex><span>$ ldd init
89</span></span><span style=display:flex><span>not a dynamic executable
90</span></span></code></pre><p>At this point, we need to create <a href=https://www.linuxfromscratch.org/blfs/view/svn/postlfs/initramfs.html>initramfs</a>
91(abbreviated from "initial RAM file system", is the successor of initrd. It
92is a cpio archive of the initial file system that gets loaded into memory
93during the Linux startup process).<pre tabindex=0 style=background-color:#fff><code><span style=display:flex><span>$ echo init | cpio -o --format=newc &gt; initramfs
94</span></span><span style=display:flex><span>$ mv initramfs bin/initramfs
95</span></span></code></pre><p>The projects at this stage should look like this.<pre><code>pid1/
96 bin/
97 bzImage
98 initramfs
99 linux-5.15.7/
100 linux-5.15.7.tar.xz
101 init.go
102</code></pre><h2 id=running-all-of-it-with-qemu>Running all of it with QEMU</h2><p><a href=https://www.qemu.org/>QEMU</a> is a free and open-source hypervisor. It emulates
103the machine's processor through dynamic binary translation and provides a set
104of different hardware and device models for the machine, enabling it to run a
105variety of guest operating systems.<pre tabindex=0 style=background-color:#fff><code><span style=display:flex><span>$ qemu-system-x86_64 -serial stdio -kernel bin/bzImage -initrd bin/initramfs -append <span style=color:#a31515>&#34;console=ttyS0&#34;</span> -m 128
106</span></span></code></pre><pre tabindex=0 style=background-color:#fff><code><span style=display:flex><span>$ qemu-system-x86_64 -serial stdio -kernel bin/bzImage -initrd bin/initramfs -append <span style=color:#a31515>&#34;console=ttyS0&#34;</span> -m 128
107</span></span><span style=display:flex><span>[ 0.000000] Linux version 5.15.7 (m@khan) (gcc (GCC) 11.2.1 20211203 (Red Hat 11.2.1-7), GNU ld version 2.37-10.fc35) <span style=color:green>#7 SMP Mon Dec 13 10:23:25 CET 2021</span>
108</span></span><span style=display:flex><span>[ 0.000000] Command line: console=ttyS0
109</span></span><span style=display:flex><span>[ 0.000000] x86/fpu: x87 FPU will use FXSAVE
110</span></span><span style=display:flex><span>[ 0.000000] signal: max sigframe size: 1440
111</span></span><span style=display:flex><span>[ 0.000000] BIOS-provided physical RAM map:
112</span></span><span style=display:flex><span>[ 0.000000] BIOS-e820: [mem 0x0000000000000000-0x000000000009fbff] usable
113</span></span><span style=display:flex><span>[ 0.000000] BIOS-e820: [mem 0x000000000009fc00-0x000000000009ffff] reserved
114</span></span><span style=display:flex><span>[ 0.000000] BIOS-e820: [mem 0x00000000000f0000-0x00000000000fffff] reserved
115</span></span><span style=display:flex><span>[ 0.000000] BIOS-e820: [mem 0x0000000000100000-0x0000000007fdffff] usable
116</span></span><span style=display:flex><span>[ 0.000000] BIOS-e820: [mem 0x0000000007fe0000-0x0000000007ffffff] reserved
117</span></span><span style=display:flex><span>[ 0.000000] BIOS-e820: [mem 0x00000000fffc0000-0x00000000ffffffff] reserved
118</span></span><span style=display:flex><span>[ 0.000000] NX (Execute Disable) protection: active
119</span></span><span style=display:flex><span>[ 0.000000] SMBIOS 2.8 present.
120</span></span><span style=display:flex><span>[ 0.000000] DMI: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.14.0-6.fc35 04/01/2014
121</span></span><span style=display:flex><span>[ 0.000000] tsc: Fast TSC calibration failed
122</span></span><span style=display:flex><span>...
123</span></span><span style=display:flex><span>[ 2.016106] ALSA device list:
124</span></span><span style=display:flex><span>[ 2.016329] No soundcards found.
125</span></span><span style=display:flex><span>[ 2.053176] Freeing unused kernel image (initmem) memory: 1368K
126</span></span><span style=display:flex><span>[ 2.056095] Write protecting the kernel read-only data: 20480k
127</span></span><span style=display:flex><span>[ 2.058248] Freeing unused kernel image (text/rodata gap) memory: 2032K
128</span></span><span style=display:flex><span>[ 2.058811] Freeing unused kernel image (rodata/data gap) memory: 500K
129</span></span><span style=display:flex><span>[ 2.059164] Run /init as init process
130</span></span><span style=display:flex><span>Hello from Golang
131</span></span><span style=display:flex><span>[ 2.386879] tsc: Refined TSC clocksource calibration: 3192.032 MHz
132</span></span><span style=display:flex><span>[ 2.387114] clocksource: tsc: mask: 0xffffffffffffffff max_cycles: 0x2e02e31fa14, max_idle_ns: 440795264947 ns
133</span></span><span style=display:flex><span>[ 2.387380] clocksource: Switched to clocksource tsc
134</span></span><span style=display:flex><span>[ 2.587895] input: ImExPS/2 Generic Explorer Mouse as /devices/platform/i8042/serio1/input/input3
135</span></span><span style=display:flex><span>Hello from Golang
136</span></span><span style=display:flex><span>Hello from Golang
137</span></span><span style=display:flex><span>Hello from Golang
138</span></span></code></pre><p>The whole <a href=/posts/pid1/qemu.log>log file here</a>.<h2 id=size-comparison>Size comparison</h2><p>The cool thing about this approach is that the Linux kernel and the application
139together only take around 12 MB, which is impressive as hell. And we need to
140also know that the size of bzImage (Linux kernel) could be greatly decreased
141by going into <code>make menuconfig</code> and removing a ton of features from the kernel,
142making the size even smaller. I managed to get kernel size down to 2 MB and
143still working properly.<pre tabindex=0 style=background-color:#fff><code><span style=display:flex><span>total 12M
144</span></span><span style=display:flex><span>-rw-r--r--. 1 m m 9.3M Dec 13 10:24 bzImage
145</span></span><span style=display:flex><span>-rw-r--r--. 1 m m 1.9M Dec 27 01:19 initramfs
146</span></span></code></pre><h2 id=creating-iso-image-and-running-it-with-gnome-boxes>Creating ISO image and running it with Gnome Boxes</h2><p>First we need to create proper folder structure with <code>mkdir -p iso/boot/grub</code>.<p>Then we need to download the <a href=https://github.com/littleosbook/littleosbook/raw/master/files/stage2_eltorito>grub binary</a>.
147You can read more about this program on <a href=https://github.com/littleosbook/littleosbook>https://github.com/littleosbook/littleosbook</a>.<pre tabindex=0 style=background-color:#fff><code><span style=display:flex><span>$ wget -O iso/boot/grub/stage2_eltorito https://github.com/littleosbook/littleosbook/raw/master/files/stage2_eltorito
148</span></span></code></pre><pre tabindex=0 style=background-color:#fff><code><span style=display:flex><span>$ tree iso/boot/
149</span></span><span style=display:flex><span>iso/boot/
150</span></span><span style=display:flex><span>├── bzImage
151</span></span><span style=display:flex><span>├── grub
152</span></span><span style=display:flex><span>│   ├── menu.lst
153</span></span><span style=display:flex><span>│   └── stage2_eltorito
154</span></span><span style=display:flex><span>└── initramfs
155</span></span></code></pre><p>Let's copy files into proper folders.<pre tabindex=0 style=background-color:#fff><code><span style=display:flex><span>$ cp stage2_eltorito iso/boot/grub/
156</span></span><span style=display:flex><span>$ cp bin/bzImage iso/boot/
157</span></span><span style=display:flex><span>$ cp bin/initramfs iso/boot/
158</span></span></code></pre><p>Lets create a GRUB config file at <code>nano iso/boot/grub/menu.lst</code> with contents.<pre tabindex=0 style=background-color:#fff><code><span style=display:flex><span>default=<span style=color:#a31515>0</span>
159</span></span><span style=display:flex><span>timeout=<span style=color:#a31515>5</span>
160</span></span><span style=display:flex><span>
161</span></span><span style=display:flex><span>title GoAsPID1
162</span></span><span style=display:flex><span>kernel /boot/bzImage
163</span></span><span style=display:flex><span>initrd /boot/initramfs
164</span></span></code></pre><p>Let's create iso file by using genisoimage:<pre tabindex=0 style=background-color:#fff><code><span style=display:flex><span>genisoimage -R <span style=color:#a31515>\
165</span></span></span><span style=display:flex><span><span style=color:#a31515></span> -b boot/grub/stage2_eltorito <span style=color:#a31515>\
166</span></span></span><span style=display:flex><span><span style=color:#a31515></span> -no-emul-boot <span style=color:#a31515>\
167</span></span></span><span style=display:flex><span><span style=color:#a31515></span> -boot-load-size 4 <span style=color:#a31515>\
168</span></span></span><span style=display:flex><span><span style=color:#a31515></span> -A os <span style=color:#a31515>\
169</span></span></span><span style=display:flex><span><span style=color:#a31515></span> -input-charset utf8 <span style=color:#a31515>\
170</span></span></span><span style=display:flex><span><span style=color:#a31515></span> -quiet <span style=color:#a31515>\
171</span></span></span><span style=display:flex><span><span style=color:#a31515></span> -boot-info-table <span style=color:#a31515>\
172</span></span></span><span style=display:flex><span><span style=color:#a31515></span> -o GoAsPID1.iso <span style=color:#a31515>\
173</span></span></span><span style=display:flex><span><span style=color:#a31515></span> iso
174</span></span></code></pre><p>This will produce <code>GoAsPID1.iso</code> which you can use with <a href=https://www.virtualbox.org/>Virtualbox</a>
175or <a href=https://apps.gnome.org/app/org.gnome.Boxes/>Gnome Boxes</a>.<p><video src=/posts/pid1/boxes.mp4 controls></video><h2 id=is-running-applications-as-pid-1-even-worth-it>Is running applications as PID 1 even worth it?</h2><p>Well, the answer to this is not as simple as one would think. Sometimes it is
176and sometimes it's not. For embedded systems and very specialized applications
177it is worth for sure. But in normal uses, I don't think so. It was an interesting
178exercise in compiling kernels and looking at the guts of the Linux kernel,
179but sticking to containers for most of the things is a better option in my
180opinion.<p>An interesting experiment would be creating an image that supports networking
181and could be deployed to AWS as an EC2 instance and observing how it fares.
182But in that case, we would need to write some sort of supervisor that would
183run on a separate EC2 that would check if other EC2 instances are running
184properly. Remember that if your application fails, kernel panics and the
185whole machine is inoperable in this case.</div></article></main><section><hr><h2>Posts from blogs I follow around the net</h2><ul><li><a href=https://chotrin.org/writing/2023-10-20.html target=_blank rel=noopener>OpenBSD upgrade and fall things.</a><div>Been AFK for a bit. It's autumn and I upgraded this server to OpenBSD 7.4! — <a href=https://chotrin.org>chötrin's wiki.</a><li><a href=https://mirzapandzo.com/next-image-url-parameter-is-valid-but-upstream-response-is-invalid target=_blank rel=noopener>Next/Image "url" parameter is valid but upstream response is invalid</a><div>Getting "url" parameter is valid but upstream response is invalid error with Next/Image on WSL2 — <a href=https://mirzapandzo.com/>Mirza Pandzo's Blog</a><li><a href=https://drewdevault.com/2023/10/13/Going-off-script.html target=_blank rel=noopener>Going off-script</a><div>There is a phenomenon in society which I find quite bizarre. Upon our entry to
186this mortal coil, we are endowed with self-awareness, agency, and free will.
187Each of th… — <a href=https://drewdevault.com>Drew DeVault's blog</a><li><a href=https://solar.lowtechmagazine.com/2023/10/workshop-in-rotterdam-how-to-build-a-bike-generator/ target=_blank rel=noopener>Workshop in Rotterdam: How to Build a Bike Generator</a><div>Afbeelding: Low-tech Magazine workshop in Rotterdam, the Netherlands. Poster: Marie Verdeil. Image: Sara Vercauteren
188The workshop takes place on behalf of the “Hou… — <a href=https://solar.lowtechmagazine.com/posts/>LOW←TECH MAGAZINE English</a><li><a href="http://offbeatpursuit.com:80/blog/?id=24" target=_blank rel=noopener>Printf debugging</a><div>tags:
189plan9
190There’s no shame in that. Yes, there is documentation, code to be
191read, and debuggers to be used. But sometimes you just need to “see”
192what is happening.
193So… — <a href=http://offbeatpursuit.com:80/blog/>WLOG - blog</a><li><a href=https://neil.computer/notes/chart-of-accounts-for-startups-and-saas-companies/ target=_blank rel=noopener>Chart of Accounts for Startups and SaaS Companies</a><div>Accounting is fundamental to starting a business. You need to have a basic understanding of accounting principles and essential bookkeeping. I had to learn it. Ther… — <a href=https://neil.computer/>Neil Panchal</a><li><a href=https://journal.valeriansaliou.name/deploy-a-nomad-cluster-on-alpine-linux-with-vultr/ target=_blank rel=noopener>Deploy a Nomad Cluster on Alpine Linux with Vultr</a><div>After spending countless hours trying to understand how to deploy my apps on Kubernetes for the first time to host Mirage, an AI API service that I run, I ended up … — <a href=https://journal.valeriansaliou.name/>Valerian Saliou</a><li><a href=https://jcs.org/2023/10/17/wikipedia target=_blank rel=noopener>Wikipedia Reader 1.0 Released</a><div>Wikipedia Reader
1941.0 has been released:
195wikipedia-1.0.sit
196(StuffIt 3 archive, includes
197source code
198and THINK C 5 project file)
199SHA256: 360e12d064f6579695f1e627ce34cb2f0… — <a href=https://jcs.org/>joshua stein</a></ul><p><a href=https://git.sr.ht/~sircmpwn/openring>Generated with openring.</a></section><footer><hr><p><big><strong>Want to comment or have something to add?</strong></big><p>You can write me an email
200at <a href=mailto:m@mitjafelicijan.com>m@mitjafelicijan.com</a> or
201catch up with me <a href=https://telegram.me/mitjafelicijan target=_blank>on Telegram</a>.<hr><p>This website does not track you. Content is made available under
202the <a href=https://creativecommons.org/licenses/by/4.0/ target=_blank rel=noreferrer>CC BY 4.0 license</a> unless specified
203otherwise. Blog is also available as <a href=/index.xml target=_blank>RSS feed</a>.</footer> \ No newline at end of file