Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 29 additions & 0 deletions library/ntfy/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
FROM golang:1.21-alpine AS build

ARG NTFY_VERSION=v2.11.0

WORKDIR /ntfy

RUN apk add --no-cache git ca-certificates gcc musl-dev && \
git clone --depth=1 --branch ${NTFY_VERSION} https://github.com/binwiederhier/ntfy.git /ntfy

RUN mkdir -p server/docs server/site && \
echo "Unikraft Ntfy Docs" > server/docs/index.html && \
echo "Unikraft Ntfy Web" > server/site/index.html

RUN CGO_ENABLED=1 go build \
-buildmode=pie \
-tags sqlite_omit_load_extension,osusergo,netgo \
-trimpath \
-ldflags="-linkmode=external -extldflags=-static-pie -s -w" \
-o /usr/bin/ntfy \
./main.go

RUN echo "127.0.0.1 localhost" > /tmp/hosts

FROM scratch

COPY --from=build /usr/bin/ntfy /usr/bin/ntfy
COPY --from=build /tmp/hosts /etc/hosts
COPY --from=build /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/
COPY ./server.yml /etc/ntfy/server.yml
109 changes: 109 additions & 0 deletions library/ntfy/Kraftfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
spec: v0.6

name: ntfy

rootfs: ./Dockerfile

cmd: ["/usr/bin/ntfy", "serve", "-c", "/etc/ntfy/server.yml"]

template:
source: https://github.com/unikraft/app-elfloader.git
version: staging

unikraft:
source: https://github.com/unikraft/unikraft.git
version: staging
kconfig:
CONFIG_LIBUKBOOT_MAINTHREAD: 'y'
CONFIG_HAVE_PAGING_DIRECTMAP: 'y'
CONFIG_HAVE_PAGING: 'y'
CONFIG_PAGING: 'y'

CONFIG_LIBUKVMEM: 'y'
CONFIG_LIBUKVMEM_DEFAULT_BASE: '0x0000001000000000'
CONFIG_LIBUKVMEM_DEMAND_PAGE_IN_SIZE: 12
CONFIG_LIBUKVMEM_PAGEFAULT_HANDLER_PRIO: 4

CONFIG_LIBPOSIX_PROCESS: 'y'
CONFIG_LIBPOSIX_PROCESS_ARCH_PRCTL: 'y'
CONFIG_LIBPOSIX_PROCESS_MULTITHREADING: 'y'
CONFIG_LIBPOSIX_USER: 'y'
CONFIG_LIBPOSIX_USER_UID: 0
CONFIG_LIBPOSIX_USER_GID: 0
CONFIG_LIBPOSIX_ENVIRON: 'y'

CONFIG_LIBPOSIX_FDIO: 'y'
CONFIG_LIBPOSIX_FDTAB: 'y'
CONFIG_LIBPOSIX_MMAP: 'y'
CONFIG_LIBPOSIX_PIPE: 'y'
CONFIG_LIBPOSIX_POLL: 'y'
CONFIG_LIBPOSIX_EVENTFD: 'y'
CONFIG_LIBPOSIX_TIME: 'y'
CONFIG_LIBPOSIX_TIMERFD: 'y'
CONFIG_LIBPOSIX_FUTEX: 'y'
CONFIG_LIBPOSIX_SYSINFO: 'y'
CONFIG_LIBPOSIX_SOCKET: 'y'

CONFIG_LIBVFSCORE: 'y'
CONFIG_LIBVFSCORE_AUTOMOUNT: 'y'
CONFIG_LIBVFSCORE_AUTOMOUNT_CI: 'y'
CONFIG_LIBVFSCORE_AUTOMOUNT_CI_EINITRD: 'y'
CONFIG_LIBVFSCORE_AUTOMOUNT_UP: 'y'
CONFIG_LIBRAMFS: 'y'
CONFIG_LIBUK9P: 'y'

CONFIG_APPELFLOADER_CUSTOMAPPNAME: 'y'
CONFIG_APPELFLOADER_BRK: 'y'
CONFIG_APPELFLOADER_VFSEXEC: 'y'
CONFIG_APPELFLOADER_VFSEXEC_EXECBIT: 'n'
CONFIG_APPELFLOADER_HFS: 'y'
CONFIG_APPELFLOADER_HFS_ETCRESOLVCONF: 'y'
CONFIG_APPELFLOADER_HFS_ETCHOSTS: 'y'
CONFIG_APPELFLOADER_HFS_ETCHOSTNAME: 'y'
CONFIG_APPELFLOADER_HFS_REPLACEEXIST: 'y'

CONFIG_LIBUKRANDOM: 'y'
CONFIG_LIBUKRANDOM_GETRANDOM: 'y'
CONFIG_LIBUKRANDOM_DEVFS: 'y'

CONFIG_UKPLAT_MEMREGION_MAX_COUNT: 128
CONFIG_OPTIMIZE_DEADELIM: 'y'
CONFIG_OPTIMIZE_LTO: 'y'
CONFIG_LIBUKDEBUG: 'y'
CONFIG_LIBUKDEBUG_CRASH_SCREEN: 'y'
CONFIG_LIBUKDEBUG_ENABLE_ASSERT: 'y'
CONFIG_LIBUKDEBUG_PRINT_TIME: 'y'
CONFIG_LIBUKDEBUG_PRINTK: 'y'
CONFIG_LIBUKDEBUG_PRINTK_ERR: 'y'

libraries:
lwip:
source: https://github.com/unikraft/lib-lwip.git
version: staging
kconfig:
CONFIG_LWIP_LOOPIF: 'y'
CONFIG_LWIP_UKNETDEV: 'y'
CONFIG_LWIP_LOOPBACK: 'y'
CONFIG_LWIP_THREADS: 'y'
CONFIG_LWIP_HEAP: 'y'
CONFIG_LWIP_IPV4: 'y'
CONFIG_LWIP_TCP: 'y'
CONFIG_LWIP_UDP: 'y'
CONFIG_LWIP_RAW: 'y'
CONFIG_LWIP_WND_SCALE: 'y'
CONFIG_LWIP_TCP_KEEPALIVE: 'y'
CONFIG_LWIP_SOCKET: 'y'
CONFIG_LWIP_AUTOIFACE: 'y'
CONFIG_LWIP_DHCP: 'y'
CONFIG_LWIP_DNS: 'y'
CONFIG_LWIP_ICMP: 'y'
CONFIG_LWIP_NUM_TCPCON: 64
CONFIG_LWIP_NUM_TCPLISTENERS: 64

libelf:
source: https://github.com/unikraft/lib-libelf.git
version: staging

targets:
- qemu/x86_64
- fc/x86_64
83 changes: 83 additions & 0 deletions library/ntfy/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
# Ntfy

This directory contains the [ntfy](https://ntfy.sh/) runtime on Unikraft, in binary compatibility mode.
It implements a simple, HTTP-based pub-sub notification service that allows you to send push notifications to your phone or desktop via PUT/POST requests, running entirely on Unikraft.

## Run and Use

Use `kraft` to run the image and start a Unikraft instance:

```bash
kraft run --rm -p 8080:80 -v /tmp:/tmp --plat qemu --arch x86_64 -M 256M unikraft.org/ntfy:latest
```

If the `--plat` argument is left out, it defaults to `qemu`.
If the `--arch` argument is left out, it defaults to your system's CPU architecture.

Once executed, the Unikraft instance will listen internally on port `80` (mapped to `8080` on your host) and wait for connections.

**Note:** To keep the Unikernel extremely lightweight and avoid massive Node.js/React dependencies, the graphical web UI is bypassed. You interact directly with the core Ntfy API via the terminal.

To verify that the server is running and successfully processing messages, open a new terminal window and send a push notification to a topic (e.g., `test`) using `curl`:

```bash
curl -d "Hello from Unikraft!" localhost:8080/test
```

You should immediately receive a JSON response from the Unikernel confirming that the payload was processed and saved, looking similar to this:

```json
{"id":"EHmxKOCNDYre","time":1774517227,"expires":1774560427,"event":"message","topic":"test","message":"Hello from Unikraft!"}
```

## Inspect and Close

To list information about the Unikraft instance, use:

```bash
kraft ps -a
```

```text
NAME KERNEL ARGS CREATED STATUS MEM PORTS PLAT
kind_ozzie project://ntfy:qemu/x86_64 /usr/bin/ntfy serve -c /etc/ntfy/serv... 15 seconds ago running 256M 0.0.0.0:8080->80/tcp qemu/x86_64
```

The instance name is `kind_ozzie`.
To close the Unikraft instance, close the `kraft` process (e.g., via `Ctrl+c`) or run:

```bash
kraft rm kind_ozzie
```

## Build and Run Locally

The commands so far used the pre-built Ntfy image available in the Unikraft registry.

In order to build a local Ntfy image, clone this repository and `cd` into this directory.
Then use `kraft` to build an image locally:

```bash
kraft build --no-cache --no-update --plat qemu --arch x86_64
```

Similar to the `kraft run` command, if the `--plat` argument is left out, it defaults to `qemu`.
If the `--arch` argument is left out, it defaults to your system's CPU architecture.

In order to run the locally built image, use `.` (*dot*, the current directory) as the final argument to the `kraft run` command:

```bash
kraft run --rm -p 8080:80 -v /tmp:/tmp --plat qemu --arch x86_64 -M 256M .
```

Same as above, it will open port `8080` and wait for connections.

## `kraft` and `sudo`

Mixing invocations of `kraft` and `sudo` can lead to unexpected behavior.
Read more about how to start `kraft` without `sudo` at [https://unikraft.org/sudoless](https://unikraft.org/sudoless).

## Learn More

- [How to run unikernels locally](https://unikraft.org/docs/cli/running)
- [How to build `Dockerfile` root filesystems with BuildKit](https://unikraft.org/guides/building-dockerfile-images-with-buildkit)
4 changes: 4 additions & 0 deletions library/ntfy/server.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
base-url: "http://localhost"
listen-http: ":80"
cache-file: "/tmp/ntfy.db"
attachment-cache-dir: "/tmp/attachments"