Hurray 🥳 🎉, you are interested in writing code for ntfy! That's awesome. 😎
I tried my very best to write up detailed instructions, but if at any point in time you run into issues, don't hesitate to contact me on Discord or Matrix.
The ntfy server source code is available on GitHub. The codebase for the server consists of three components:
CGO_ENABLED=1
to be set. Otherwise things will not work (see below).pip
) only if you want to
build the docs.npm
)
and install all the 100,000 dependencies (sigh).All of these components are built and then baked into one binary.
Code:
serve
or publish
mkdocs.yml
web/package.json
Build related:
The web/
and docs/
folder are the sources for web app and documentation. During the build process,
the generated output is copied to server/site
(web app and landing page) and server/docs
(documentation).
To get a quick working development environment you can use Gitpod, an in-browser IDE that makes it easy to develop ntfy without having to set up a desktop IDE. For any real development, I do suggest a proper IDE like IntelliJ IDEA.
pip
, only to build the docs)npm
, only to build the web app)These steps assume Ubuntu. Steps may vary on different Linux distributions.
First, install Go (see official instructions):
wget https://go.dev/dl/go1.19.1.linux-amd64.tar.gz
sudo rm -rf /usr/local/go && sudo tar -C /usr/local -xzf go1.19.1.linux-amd64.tar.gz
export PATH=$PATH:/usr/local/go/bin:$HOME/go/bin
go version # verifies that it worked
Install GoReleaser (see official instructions):
go install github.com/goreleaser/goreleaser@latest
goreleaser -v # verifies that it worked
Install nodejs (see official instructions):
curl -fsSL https://deb.nodesource.com/setup_18.x | sudo -E bash -
sudo apt-get install -y nodejs
npm -v # verifies that it worked
Then install a few other things required:
sudo apt install \
build-essential \
libsqlite3-dev \
gcc-arm-linux-gnueabi \
gcc-aarch64-linux-gnu \
python3-pip \
git
Now check out via git from the GitHub repository:
=== "via HTTPS"
``` shell
git clone https://github.com/binwiederhier/ntfy.git
cd ntfy
```
=== "via SSH"
``` shell
git clone git@github.com:binwiederhier/ntfy.git
cd ntfy
```
Now you can finally build everything. There are tons of make
targets, so maybe just review what's there first
by typing make
:
$ make
Typical commands (more see below):
make build - Build web app, documentation and server/client (sloowwww)
make cli-linux-amd64 - Build server/client binary (amd64, no web app or docs)
make install-linux-amd64 - Install ntfy binary to /usr/bin/ntfy (amd64)
make web - Build the web app
make docs - Build the documentation
make check - Run all tests, vetting/formatting checks and linters
...
If you want to build the ntfy binary including web app and docs for all supported architectures (amd64, armv7, and arm64),
you can simply run make build
:
$ make build
...
# This builds web app, docs, and the ntfy binary (for amd64, armv7 and arm64).
# This will be SLOW (5+ minutes on my laptop on the first run). Maybe look at the other make targets?
You'll see all the outputs in the dist/
folder afterwards:
$ find dist
dist
dist/metadata.json
dist/ntfy_arm64_linux_arm64
dist/ntfy_arm64_linux_arm64/ntfy
dist/ntfy_armv7_linux_arm_7
dist/ntfy_armv7_linux_arm_7/ntfy
dist/ntfy_amd64_linux_amd64
dist/ntfy_amd64_linux_amd64/ntfy
dist/config.yaml
dist/artifacts.json
If you also want to build the Debian/RPM packages and the Docker images for all supported architectures, you can
use the make release-snapshot
target:
$ make release-snapshot
...
# This will be REALLY SLOW (sometimes 5+ minutes on my laptop)
During development, you may want to be more picky and build only certain things. Here are a few examples.
This is useful to test the final build with web app, docs, and server without any dependencies locally
$ make docker-dev
$ docker run --rm -p 80:80 binwiederhier/ntfy:dev serve
To build only the ntfy
binary without the web app or documentation, use the make cli-...
targets:
$ make
Build server & client (using GoReleaser, not release version):
make cli - Build server & client (all architectures)
make cli-linux-amd64 - Build server & client (Linux, amd64 only)
make cli-linux-armv6 - Build server & client (Linux, armv6 only)
make cli-linux-armv7 - Build server & client (Linux, armv7 only)
make cli-linux-arm64 - Build server & client (Linux, arm64 only)
make cli-windows-amd64 - Build client (Windows, amd64 only)
make cli-darwin-all - Build client (macOS, arm64+amd64 universal binary)
So if you're on an amd64/x86_64-based machine, you may just want to run make cli-linux-amd64
during testing. On a modern
system, this shouldn't take longer than 5-10 seconds. I often combine it with install-linux-amd64
so I can run the binary
right away:
$ make cli-linux-amd64 install-linux-amd64
$ ntfy serve
During development of the main app, you can also just use go run main.go
, as long as you run
make cli-deps-static-sites
at least once and CGO_ENABLED=1
:
$ export CGO_ENABLED=1
$ make cli-deps-static-sites
$ go run main.go serve
2022/03/18 08:43:55 Listening on :2586[http]
...
If you don't run cli-deps-static-sites
, you may see an error pattern ...: no matching files found
:
$ go run main.go serve
server/server.go:85:13: pattern docs: no matching files found
This is because we use go:embed
to embed the documentation and web app, so the Go code expects files to be
present at server/docs
and server/site
. If they are not, you'll see the above error. The cli-deps-static-sites
target creates dummy files that ensure that you'll be able to build.
While not officially supported (or released), you can build and run the server on macOS as well. Simply run
make cli-darwin-server
to build a binary, or go run main.go serve
(see above) to run it.
The sources for the web app live in web/
. As long as you have npm
installed (see above), building the web app
is really simple. Just type make web
and you're in business:
$ make web
...
This will build the web app using Create React App and then copy the production build to the server/site
folder, so
that when you make cli
(or make cli-linux-amd64
, ...), you will have the web app included in the ntfy
binary.
If you're developing on the web app, it's best to just cd web
and run npm start
manually. This will open your browser
at http://127.0.0.1:3000
with the web app, and as you edit the source files, they will be recompiled and the browser
will automatically refresh:
$ cd web
$ npm start
Reference: https://stackoverflow.com/questions/34160509/options-for-testing-service-workers-via-http
Get web push keys go run main.go webpush keys
Run the server with web push enabled
go run main.go \
--log-level debug \
serve \
--web-push-public-key KEY \
--web-push-private-key KEY \
--web-push-email-address <email> \
--web-push-file=/tmp/webpush.db
In web/public/config.js
:
Set base_url
to http://localhost
, This is required as web push can only be used with the server matching the base_url
.
Set the web_push_public_key
correctly.
Run npm run start
Run make web-build
Run the server (step 2 above)
Open http://localhost/
The sources for the docs live in docs/
. Similarly to the web app, you can simply run make docs
to build the
documentation. As long as you have mkdocs
installed (see above), this should work fine:
$ make docs
...
If you are changing the documentation, you should be running mkdocs serve
directly. This will build the documentation,
serve the files at http://127.0.0.1:8000/
, and rebuild every time you save the source files:
$ mkdocs serve
INFO - Building documentation...
INFO - Cleaning site directory
INFO - Documentation built in 5.53 seconds
INFO - [16:28:14] Serving on http://127.0.0.1:8000/
Then you can navigate to http://127.0.0.1:8000/ and whenever you change a markdown file in your text editor it'll automatically update.
The ntfy Android app source code is available on GitHub. The Android app has two flavors:
play
flavor includes Firebase (FCM) and requires a Firebase accountfdroid
flavor does not include Firebase or Google dependenciesYou should download Android Studio (or IntelliJ IDEA with the relevant Android plugins). Everything else will just be a pain for you. Do yourself a favor. 😀
First check out the repository:
=== "via HTTPS"
``` shell
git clone https://github.com/binwiederhier/ntfy-android.git
cd ntfy-android
```
=== "via SSH"
``` shell
git clone git@github.com:binwiederhier/ntfy-android.git
cd ntfy-android
```
Then either follow the steps for building with or without Firebase.
!!! info
I do build the ntfy Android app using IntelliJ IDEA (Android Studio), so I don't know if these Gradle commands will
work without issues. Please give me feedback if it does/doesn't work for you.
Without Firebase, you may want to still change the default app_base_url
in values.xml
if you're self-hosting the server. Then run:
# Remove Google dependencies (FCM)
sed -i -e '/google-services/d' build.gradle
sed -i -e '/google-services/d' app/build.gradle
# To build an unsigned .apk (app/build/outputs/apk/fdroid/*.apk)
./gradlew assembleFdroidRelease
# To build a bundle .aab (app/fdroid/release/*.aab)
./gradlew bundleFdroidRelease
!!! info
I do build the ntfy Android app using IntelliJ IDEA (Android Studio), so I don't know if these Gradle commands will
work without issues. Please give me feedback if it does/doesn't work for you.
To build your own version with Firebase, you must:
app/google-services.json
app_base_url
in values.xmlThen run:
# To build an unsigned .apk (app/build/outputs/apk/play/*.apk)
./gradlew assemblePlayRelease
# To build a bundle .aab (app/play/release/*.aab)
./gradlew bundlePlayRelease
Building the iOS app is very involved. Please report any inconsistencies or issues with it. The requirements are strictly based off of my development on this app. There may be other versions of macOS / XCode that work.
!!! info
Along with this step, the [PLIST Deployment](#plist-deployment-and-configuration) step is also required
for these changes to take effect in the iOS app.
AuthKey_ZZZZZZ.p8
, where ZZZZZZ
is the Key ID)!!! warning
If you don't do the above setups for APNS, **notifications will not post instantly or sometimes at all**. This is because of the missing APNS key, which is required for firebase to send notifications to the iOS app. See below for a snip from the firebase docs.
If you don't have an APNs authentication key, you can still send notifications to iOS devices, but they won't be delivered instantly. Instead, they'll be delivered when the device wakes up to check for new notifications or when your application sends a firebase request to check for them. The time to check for new notifications can vary from a few seconds to hours, days or even weeks. Enabling APNs authentication keys ensures that notifications are delivered instantly and is strongly recommended.
Note that the ntfy server is not officially supported on macOS. It should, however, be able to run on macOS using these steps:
/etc/ntfy/
directory and move the service account private key to that folderserver/server.yml
file from the ntfy repository to /etc/ntfy/
/etc/ntfy/server.yml
file firebase-key-file
value to the path of the private keybrew install go
make cli-darwin-server
.firebase-ios-sdk
in XCode, if it's not already present - you can select any packages in addition to Firebase Core / Firebase MessagingTo have instant notifications/better notification delivery when using firebase, you will need to add the
GoogleService-Info.plist
file to your project. Here's how to do that:
GoogleService-Info.plist
file into the Asset/ folder that you get from the firebase console. It can be
found in the "Project settings" > "General" > "Your apps" with a button labled "GoogleService-Info.plist"After that, you should be all set!