11 KiB
Building
!!! info These instructions are pretty rough. My apologies for that. Please help improve them my letting me know in a GitHub issue.
ntfy server
The ntfy server source code is available on GitHub. The codebase for the server consists of three components:
- The main server and API is written in Go (so you'll need Go). Its main entrypoint is at
main.go, and the meat you're likely interested in is
in server.go. Notably, the server uses a
SQLite library called go-sqlite3, which requires
Cgo and
CGO_ENABLED=1
to be set. Otherwise things will not work (see below). - The documentation is generated by MkDocs and Material for MkDocs,
which is written in Python. You'll need Python and MkDocs (via
pip
) only if you want to build the docs. - The web app is written in React, using MUI. It uses Create React App
to build the production build. If you want to modify the web app, you need nodejs (for
npm
) to install all the 100,000 dependencies (sigh).
All of these components are built and then baked into one binary.
Navigating the code
Code:
- main.go - Main entrypoint into the CLI, for both server and client
- cmd/ - CLI commands, such as
serve
orpublish
- server/ - The meat of the server logic
- docs/ - The MkDocs documentation, also see
mkdocs.yml
- web/ - The React application, also see
web/package.json
Build related:
- Makefile - Main entrypoint for all things related to building
- .goreleaser.yml - Describes all build outputs (for GoReleaser)
- go.mod - Go modules dependency file
- mkdocs.yml - Config file for the docs (for MkDocs)
- web/package.json - Build and dependency file for web app (for npm)
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).
Build requirements
- Go (required for main server)
- gcc (required main server, for SQLite cgo-based bindings)
- Make (required for convenience)
- libsqlite3/libsqlite3-dev (required for main server, for SQLite cgo-based bindings)
- GoReleaser (required for a proper main server build)
- Python (for
pip
, only to build the docs) - nodejs (for
npm
, only to build the web app)
Install dependencies
These steps assume Ubuntu. Steps may vary on different Linux distributions.
First, install Go (see official instructions):
rm -rf /usr/local/go && tar -C /usr/local -xzf go1.18.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_17.x | sudo -E bash -
sudo apt-get install -y nodejs
npm # 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 \
upx
Check out code
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
Build all the things
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 server-amd64 - Build server/client binary (amd64, no web app or docs)
make install-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 amd64),
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 (1+ minutes on my laptop). 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.
Building ntfy binary
To build only the ntfy
binary without the web app or documentation, use the make server-...
targets:
Build server & client (not release version):
make server - Build server & client (all architectures)
make server-amd64 - Build server & client (amd64 only)
make server-armv7 - Build server & client (armv7 only)
make server-arm64 - Build server & client (arm64 only)
So if you're on an amd64/x86_64-based machine, you may just want to run make server-amd64
during testing. On a modern
system, this shouldn't take longer than 5-10 seconds. I often combine it with install-amd64
so I can run the binary
right away:
$ make server-amd64 install-amd64
$ ntfy serve
During development of the main app, you can also just use go run main.go
(as long as you run make server-deps-static-sites
at least once), otherwise you'll see this:
# Error because docs/web folder is missing
$ go run main.go serve
server/server.go:85:13: pattern docs: no matching files found
# Works!
$ make server-deps-static-sites
$ go run main.go serve
2022/03/18 08:43:55 Listening on :2586[http]
Building the web app
Building the docs
pip3 install -r requirements.txt
mkdocs build
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.
XXXXXXXXXXXXXXXXXXXXx
Quick & dirty (amd64 only)
To quickly build on amd64, you can use make build-simple
:
make build-simple
That'll generate a statically linked binary in dist/ntfy_linux_amd64/ntfy
. This binary will not include the docs
or the web app. To include that
For all other platforms (including Docker), and for production or other snapshot builds, you should use the amazingly awesome GoReleaser make targets:
Build:
make build - Build
make build-snapshot - Build snapshot
make build-simple - Build (using go build, without goreleaser)
make clean - Clean build folder
Releasing (requires goreleaser):
make release - Create a release
make release-snapshot - Create a test release
There are currently no platform-specific make targets, so they will build for all platforms (which may take a while).
Android app
The ntfy Android app source code is available on GitHub. The Android app has two flavors:
- Google Play: The
play
flavor includes Firebase (FCM) and requires a Firebase account - F-Droid: The
fdroid
flavor does not include Firebase or Google dependencies
First check out the repository:
git clone git@github.com:binwiederhier/ntfy-android.git # or: https://github.com/binwiederhier/ntfy-android.git
cd ntfy-android
Then either follow the steps for building with or without Firebase.
Building without Firebase (F-Droid flavor)
Without Firebase, you may want to still change the default app_base_url
in strings.xml
if you're self-hosting the server. Then run:
# To build an unsigned .apk (app/build/outputs/apk/fdroid/*.apk)
./gradlew assembleFdroidRelease
# To build a bundle .aab (app/fdroid/release/*.aab)
./gradlew bundleFdroidRelease
Building with Firebase (FCM, Google Play flavor)
To build your own version with Firebase, you must:
- Create a Firebase/FCM account
- Place your account file at
app/google-services.json
- And change
app_base_url
in strings.xml - Then 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