-
Notifications
You must be signed in to change notification settings - Fork 125
add(blog): Adds IInd post on expanding the Unikraft app ecosystem #572
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
vTusharr
wants to merge
1
commit into
unikraft:main
Choose a base branch
from
vTusharr:blog-gsoc26-xpand2
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from all commits
Commits
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,109 @@ | ||
| --- | ||
| title: "GSoC'26: Expanding the Unikraft Software Support Ecosystem" | ||
| description: | | ||
| This is the second blog post related to my GSoC project on expanding the app ecosystem on Unikraft. | ||
| publishedDate: 2026-07-14 | ||
| image: /images/unikraft-gsoc24.png | ||
| authors: | ||
| - Tushar Verma | ||
| tags: | ||
| - gsoc | ||
| - gsoc26 | ||
| - virtualization | ||
| - apps | ||
| --- | ||
|
|
||
| ## Project Overview | ||
|
|
||
| This is the second blog post related to my GSoC project on expanding the app ecosystem on Unikraft. | ||
| In Part I, I covered dnsmasq, lighttpd(bincompat-port) and the nginx update. | ||
|
|
||
| ## Progress | ||
|
|
||
| ### lighttpd | ||
|
|
||
| [lighttpd](https://www.lighttpd.net/), a lightweight web server, now has a native port! | ||
| The earlier route was binary-compatibility mode — package the binary and its shared libraries into a rootfs and ran under the ELF loader. | ||
|
|
||
| The deeper route is a native source port which is often more performant, `lib-lighttpd`:(lighttpd version `1.4.84`) can now be compiled directly into the unikernel against musl and lwIP. | ||
| A source port produces a smaller, single-purpose image and gives Kconfig-level control over which modules exist at all — but it means taking over the app's build system, and that's where the interesting problems were. | ||
|
|
||
| **Escaping Meson** | ||
| lighttpd builds with meson/cmake/automake , all of which generate files before compiling: a `config.h` of platform feature probes, and a configuration-file parser produced by [lemon](https://sqlite.org/lemon.html) (SQLite's parser generator) from a grammar file. | ||
| Unikraft's build is plain make and fetches a tarball, so none of that generation happens. | ||
| The port ships those artifacts pre-generated in the library repo instead: a hand-written `config.h` describing what musl + lwIP actually provide (epoll via `posix-poll`, IPv6, `getrandom`; no `fork`, no `sendfile`), and `configparser.c` taken straight from midway through meson's build pipeline. | ||
|
|
||
| **TLS as a Kconfig option.** | ||
| `mod_openssl` compiles against Unikraft's `lib-openssl` behind a single `LIBLIGHTTPD_OPENSSL` option, so HTTPS support — and the whole OpenSSL dependency — is one menuconfig toggle. | ||
| `lib-openssl` still ships OpenSSL `1.1.1c`; moving it to a current `3.x` LTS is a heavy port of its own (provider model, ~900 source files), left for future work. | ||
|
|
||
| **Entry-Point Gotcha.** | ||
| One entry-point subtlety worth recording: lighttpd's `server.c` wraps its `main()` in `#ifndef main / #define server_main main`, so the usual `-Dmain=app_main` rename trick silently leaves the symbol as `server_main` — the port's `main()` wrapper calls that directly. | ||
|
|
||
| **Related PRs:** [lib-lighttpd](https://github.com/unikraft/lib-lighttpd/pull/1) | ||
|
|
||
| ### Library housekeeping | ||
|
|
||
| Native ports keep tripping over the same class of outdated libs , so some fixes landed in the libraries themselves: | ||
|
|
||
| **`lib-openssl`: dead download URL.** | ||
| `openssl.org` retired its `/source/old/` archive, so build failed at the fetch step with a tarball that no longer existed. | ||
| The fetch URL now points at the GitHub release tag, which is permanent. | ||
|
|
||
| **`lib-pcre`: dead download URL.** | ||
| The archive for `lib-pcre` moved from `pcre-org` to `sourceforge`. | ||
|
|
||
| **`lib-zlib`: hard-wired to the deprecated filesystem stack.** | ||
| The `Config.uk` for `lib-zlib` hard-selected `vfscore` components, which breaks any image built on the new posix-vfs stack. | ||
| The selects are gone now; the application decides its filesystem stack. | ||
|
|
||
| **Related PRs:** [lib-openssl](https://github.com/unikraft/lib-openssl/pull/11), [lib-pcre](https://github.com/unikraft/lib-pcre/pull/5), [lib-zlib](https://github.com/unikraft/lib-zlib/pull/13) | ||
|
|
||
| ### chronyd | ||
|
|
||
| [chrony](https://chrony-project.org/) is an NTP implementation, and the time-sync daemon from the original project list. | ||
| A unikernel can't adjust its own clock anyway — Unikraft's `settimeofday`/`clock_settime` are stubs — but chronyd's `-x` mode is built for exactly this situation, it tracks the offset to upstream servers in software and serves *corrected* time to clients without ever touching the system clock. | ||
| The result is an NTP server appliance: boot it, it syncs to the pool, and every machine on the network can get accurate time from it. | ||
|
|
||
| It runs in binary-compatibility mode , but getting there surfaced some gaps. | ||
|
|
||
| **An empty `resolv.conf`, injected by the loader.** | ||
| With output visible, the syscall trace showed DNS queries going nowhere: `read(/etc/resolv.conf) = 0`. | ||
| The elfloader's host-filesystem helper (`APPELFLOADER_HFS_ETCRESOLVCONF`) is supposed to inject the host's resolver configuration, but under `kraft run` it creates an *empty* file — and with `HFS_REPLACEEXIST` it even overwrites the one shipped in the rootfs. | ||
| Disabling the helper and baking a static `resolv.conf` (public resolvers; queried in parallel) fixed upstream resolution. | ||
|
|
||
| **No `recvmmsg` in Unikraft.** | ||
| Replies from the pool arrived, `select()` reported the socket readable, and chronyd still never read a packet. | ||
| Alpine's chrony is compiled with `HAVE_RECVMMSG` and has no runtime fallback, while Unikraft's syscall shim returns `-ENOSYS` — so chronyd busy-looped on a socket it could never consume. | ||
| I verified two fixes: an `LD_PRELOAD` shim that rewrites `recvmmsg` into a `recvmsg` loop (keeps the stock distro binary), and building chrony from source with `HAVE_RECVMMSG` removed from `config.h`. | ||
| I finally settled on removing `HAVE_RECVMMSG`, because that was the simpler long-term fix and also enables to remove features that are dead weight in a unikernel (`cmdmon`, refclocks, privilege dropping, seccomp) and strip the binary down to ~250 KB. | ||
|
|
||
| **A dual-stack compile bug in lib-lwip.** | ||
| Enabling IPv6 broke the build in Unikraft's netlink glue: `netif->address.type` — a field that doesn't exist; lwIP calls it `ip_addr`. | ||
| The broken line only compiles when netlink and IPv6 are enabled together. | ||
| One-word fix, headed upstream. (IPv6 stayed off in the shipped images: with `AF_INET6` sockets available chrony preferred the unreachable v6 addresses of every upstream and never synced.) | ||
|
|
||
| **One decision worth explaining: two images.** | ||
| The port ships as `chronyd/4.8` and `chronyd/4.8-nts`. | ||
| NTS (Network Time Security) authenticates the NTP exchange over TLS, which is a real upgrade — but it drags in gnutls and its whole dependency closure plus a CA bundle, inflating the rootfs from **~2 MB to ~10 MB**. | ||
| Deployments syncing within trusted infrastructure shouldn't pay a 5x size cost for certificates they don't check, so the plain image stays minimal and the NTS image is there when authenticated time matters. | ||
| Both were verified end-to-end: the plain image syncs to the pool and answers clients at stratum 2; the NTS image completes NTS-KE against Cloudflare and PTB (all configurable). | ||
|
|
||
| ## Next Steps | ||
|
|
||
| - Upstream the lighttpd's catalog-core app. | ||
| - Upstream an [Odin](https://odin-lang.org/) hello-world program to catalog-core. | ||
| - Upstream the fixes that fell out of the chrony port:`recvmmsg` in `lib/posix-socket`, the lib-lwip netlink dual-stack fix . | ||
| - Investigate [Lwip'sntp application module](https://www.nongnu.org/lwip/2_0_x/group__sntp.html). | ||
| - Continue down the project list: Investigate Gitea and a message broker. | ||
|
|
||
| ## Acknowledgements | ||
|
|
||
| Special thanks to Răzvan Deaconescu and Răzvan Vîrtan, my two amazing mentors, for their support along the way. | ||
| I would also like to thank Alex Andrei Cioc, Cezar Craciunoiu, and the entire Unikraft community for all the work, discussions, and guidance. | ||
|
|
||
| ## About Me | ||
|
|
||
| I'm [Tushar Verma](https://www.linkedin.com/in/tushar-verma-32847b324), a second-year undergraduate student @ IIT Jodhpur. | ||
| I am passionate about operating systems, systems programming and cloud. | ||
| Outside of tech, I enjoy tinkering, making music, swimming and exploring whatever captures my curiosity at the moment. | ||
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.