From bfdeed2a445875d2648ca5b280062ceb7129aad8 Mon Sep 17 00:00:00 2001 From: Jannis Mattheis Date: Tue, 7 Jul 2026 20:47:57 +0200 Subject: [PATCH 1/5] fix: add master image guide --- .vitepress/config.ts | 4 ++++ docs/testing-master.md | 18 ++++++++++++++++++ 2 files changed, 22 insertions(+) create mode 100644 docs/testing-master.md diff --git a/.vitepress/config.ts b/.vitepress/config.ts index 2bf35e5..6462124 100644 --- a/.vitepress/config.ts +++ b/.vitepress/config.ts @@ -62,6 +62,10 @@ export default defineConfig({ {text: 'OpenID Connect (OIDC)', link: '/docs/oidc'}, {text: 'Session Elevation', link: '/docs/session-elevation'}, {text: 'Migrate to 3.x', link: '/docs/migrate-to-3'}, + { + text: 'Testing unreleased changes', + link: '/docs/testing-master', + }, {text: 'Apache reverse proxy', link: '/docs/apache'}, {text: 'Caddy 2 reverse proxy', link: '/docs/caddy'}, {text: 'Haproxy reverse proxy', link: '/docs/haproxy'}, diff --git a/docs/testing-master.md b/docs/testing-master.md new file mode 100644 index 0000000..3b9c349 --- /dev/null +++ b/docs/testing-master.md @@ -0,0 +1,18 @@ +# Testing Unreleased Changes + +> [!WARNING] +> The `master` image is built from the current development state. There are no +> guarantees for stability or security. Use it at your own risk. + +The `gotify/server:master` Docker image is built on every push to the +[master branch](https://github.com/gotify/server) and contains the latest +unreleased changes. + +```bash +# Docker Hub +$ docker run -p 8080:80 -v "$PWD/testdata:/app/data" docker.io/gotify/server:master +# GitHub Registry +$ docker run -p 8080:80 -v "$PWD/testdata:/app/data" ghcr.io/gotify/server:master +``` + +Found a bug? Report it on [github.com/gotify/server/issues](https://github.com/gotify/server/issues). From dc6965ae3d9687cf85b0db25f558f87d13eab927 Mon Sep 17 00:00:00 2001 From: Jannis Mattheis Date: Tue, 7 Jul 2026 20:53:52 +0200 Subject: [PATCH 2/5] fix: add priority docs --- .vitepress/config.ts | 1 + docs/priority.md | 30 ++++++++++++++++++++++++++++++ docs/pushmsg.md | 2 ++ 3 files changed, 33 insertions(+) create mode 100644 docs/priority.md diff --git a/.vitepress/config.ts b/.vitepress/config.ts index 6462124..4420a15 100644 --- a/.vitepress/config.ts +++ b/.vitepress/config.ts @@ -69,6 +69,7 @@ export default defineConfig({ {text: 'Apache reverse proxy', link: '/docs/apache'}, {text: 'Caddy 2 reverse proxy', link: '/docs/caddy'}, {text: 'Haproxy reverse proxy', link: '/docs/haproxy'}, + {text: 'Message Priority', link: '/docs/priority'}, {text: '(more) Push message examples', link: '/docs/more-pushmsg'}, {text: 'nginx reverse proxy', link: '/docs/nginx'}, {text: 'Optimize uploaded images', link: '/docs/optimize-images'}, diff --git a/docs/priority.md b/docs/priority.md new file mode 100644 index 0000000..7ceb279 --- /dev/null +++ b/docs/priority.md @@ -0,0 +1,30 @@ +# Message Priority + +Every message has a priority. Higher priorities mean more important messages. Clients can use it to decide how intrusive a message is presented. + +## Setting the priority + +Set the priority when pushing a message: + +```bash +$ curl -H "X-Gotify-Key: " "https://push.example.de/message" -F "message=my message" -F "priority=8" +``` + +When a message is pushed without a priority, the default priority of the application is used. It can be configured in the WebUI by editing the application. + +## How clients handle priorities + +### Android + +The [Android app](https://github.com/gotify/android) maps priorities to notification behavior: + +| Notification | Priority | +| -------------------------------------------- | -------- | +| No notification | 0 | +| Icon in notification bar | 1 - 3 | +| Icon in notification bar + Sound | 4 - 7 | +| Icon in notification bar + Sound + Vibration | 8 - 10 | + +### WebUI + +The WebUI shows a browser notification for every message and additionally plays a notification sound for messages with priority 4 or higher. diff --git a/docs/pushmsg.md b/docs/pushmsg.md index 660acc5..f8538fc 100644 --- a/docs/pushmsg.md +++ b/docs/pushmsg.md @@ -27,6 +27,8 @@ PS> Invoke-WebRequest -Uri "https://push.example.de/message?token=" -M > The message API takes an `extras` property that carries extra information with the message and describes how clients behave to this message. > See [message extras](msgextras.md) for more information. +The `priority` parameter controls how clients present the message, f.ex. whether the Android app plays a notification sound. See [message priority](priority.md) for more information. + As of gotify/server v1.2.0 only the `message` parameter is required. [Here are more examples for pushing messages in different languages.](more-pushmsg.md) From 652e4e83f95cca96824c09770120898639f4a692 Mon Sep 17 00:00:00 2001 From: Jannis Mattheis Date: Tue, 7 Jul 2026 21:21:46 +0200 Subject: [PATCH 3/5] fix: ai improvements --- .vitepress/config.ts | 2 +- docs/apache.md | 12 ++++++------ docs/build.md | 7 ++++--- docs/caddy.md | 14 ++++++------- docs/dev-server-and-tests.md | 29 ++++++++++++--------------- docs/dev-setup.md | 8 ++++---- docs/first-login.md | 6 +++--- docs/haproxy.md | 4 ++-- docs/index.md | 9 ++++----- docs/install.md | 20 +++++++++---------- docs/migrate-to-3.md | 38 +++++++++++++++++++----------------- docs/more-pushmsg.md | 34 ++++++++++++++++---------------- docs/msgextras.md | 6 +++--- docs/nginx.md | 26 ++++++++++++------------ docs/oidc.md | 10 +++++----- docs/pushmsg.md | 24 +++++++++++------------ docs/session-elevation.md | 4 ++-- docs/systemd.md | 12 ++++++------ docs/traefik.md | 7 +++++-- index.md | 10 +++++----- 20 files changed, 140 insertions(+), 142 deletions(-) diff --git a/.vitepress/config.ts b/.vitepress/config.ts index 4420a15..201fe5a 100644 --- a/.vitepress/config.ts +++ b/.vitepress/config.ts @@ -68,7 +68,7 @@ export default defineConfig({ }, {text: 'Apache reverse proxy', link: '/docs/apache'}, {text: 'Caddy 2 reverse proxy', link: '/docs/caddy'}, - {text: 'Haproxy reverse proxy', link: '/docs/haproxy'}, + {text: 'HAProxy reverse proxy', link: '/docs/haproxy'}, {text: 'Message Priority', link: '/docs/priority'}, {text: '(more) Push message examples', link: '/docs/more-pushmsg'}, {text: 'nginx reverse proxy', link: '/docs/nginx'}, diff --git a/docs/apache.md b/docs/apache.md index 8467f93..71df1e7 100644 --- a/docs/apache.md +++ b/docs/apache.md @@ -1,6 +1,6 @@ # Apache reverse proxy -Here are configuration examples for setting up apache as reverse proxy for gotify/server. +Here are configuration examples for setting up Apache as a reverse proxy for Gotify. The following modules are required: @@ -16,11 +16,11 @@ The following modules are required: Keepalive On - # The proxy must preserve the host because gotify verifies the host with the origin + # The proxy must preserve the host because Gotify verifies the host with the origin # for WebSocket connections ProxyPreserveHost On - # Proxy web socket requests to /stream + # Proxy WebSocket requests to /stream ProxyPass "/stream" ws://127.0.0.1:GOTIFY_PORT/stream retry=0 timeout=60 # Proxy all other requests to / @@ -39,11 +39,11 @@ The following modules are required: Redirect 301 "/gotify" "/gotify/" - # The proxy must preserve the host because gotify verifies the host with the origin + # The proxy must preserve the host because Gotify verifies the host with the origin # for WebSocket connections ProxyPreserveHost On - # Proxy web socket requests to /stream + # Proxy WebSocket requests to /stream ProxyPass "/gotify/stream" ws://127.0.0.1:GOTIFY_PORT/stream retry=0 timeout=60 # Proxy all other requests to / @@ -57,7 +57,7 @@ The following modules are required: ## Troubleshooting With some additional Apache configuration, the `ProxyPass` for the `/stream` endpoint may not work correctly. -The request fails with `400 Bad Request` and the following error is logged inside gotify/server. +The request fails with `400 Bad Request` and Gotify logs the following error. ``` Error #01: websocket: the client is not using the websocket protocol: 'upgrade' token not found in 'Connection' header diff --git a/docs/build.md b/docs/build.md index 53259ad..a16fb5e 100644 --- a/docs/build.md +++ b/docs/build.md @@ -10,8 +10,8 @@ 1. Build the Go Binary - It is recommended to build gotify/server via the [gotify/build docker images](https://github.com/gotify/build), - this ensures that [plugins](plugin.md) will be compatible with the built binary (because the same build environment is used). + It is recommended to build gotify/server via the [gotify/build docker images](https://github.com/gotify/build). + This ensures that [plugins](plugin.md) will be compatible with the built binary because the same build environment is used. Set the LD_FLAGS with meta information like the version or the commit: @@ -29,6 +29,7 @@ $ make build-linux-arm-7 $ make build-linux-arm64 $ make build-linux-386 + $ make build-linux-riscv64 $ make build-windows-amd64 $ make build-windows-386 ``` @@ -39,7 +40,7 @@ $ go build -ldflags="$LD_FLAGS" -o gotify-server ``` - _The project has a CGO reference (because of sqlite3), therefore a CGO cross compiler is needed for compiling for + _The project has a CGO reference (because of sqlite3), therefore a CGO cross compiler is needed when compiling for other platforms (the gotify/build docker images already contain the needed cross compilers)._ ```bash diff --git a/docs/caddy.md b/docs/caddy.md index e72133e..2574d5d 100644 --- a/docs/caddy.md +++ b/docs/caddy.md @@ -1,30 +1,30 @@ # Caddy 2 reverse proxy -Setting up [Caddy](https://caddyserver.com) as a reverse proxy is very straightforward. Here are two config examples. +Here are configuration examples for setting up [Caddy](https://caddyserver.com) as a reverse proxy for Gotify. ## As a standalone domain -Here is a sample config file if you run your gotify instance on port 1245 +Here is a sample config file if your Gotify instance runs on port 1245. ``` gotify.example.com { - # Set the port to the one you are using in gotify - # Websocket support, proxy headers, etc. are enabled by default + # Set the port to the one you are using in Gotify + # WebSocket support, proxy headers, etc. are enabled by default reverse_proxy localhost:1245 } ``` -Caddy automatically deploys SSL certificates from Let's Encrypt for your domain. If you want to explicitly disable TLS encryption, prefix your server name with `http://`. +Caddy automatically obtains TLS certificates from Let's Encrypt for your domain. If you want to explicitly disable TLS, prefix your server name with `http://`. ## At a subpath -Here is the equivalent of the sample config above but running under a sub path. +Here is the equivalent of the sample config above but running at a subpath. ``` example.com { route /gotify/* { uri strip_prefix /gotify - # Set the port to the one you are using in gotify + # Set the port to the one you are using in Gotify reverse_proxy localhost:1245 } redir /gotify /gotify/ diff --git a/docs/dev-server-and-tests.md b/docs/dev-server-and-tests.md index 4accd55..8ce977e 100644 --- a/docs/dev-server-and-tests.md +++ b/docs/dev-server-and-tests.md @@ -4,7 +4,7 @@ ### Backend -The backend needs a built ui. Run +The backend embeds the built UI, so build it first. ```bash $ (cd ui && yarn build) @@ -26,17 +26,18 @@ _Commands must be executed inside the ui directory._ $ yarn start ``` -Open `http://localhost:3000` inside your favorite browser. +Open `http://localhost:5173` inside your favorite browser. -The UI requires a Gotify server running on `localhost:80`. This can be adjusted inside -[ui/src/index.tsx](https://github.com/gotify/server/blob/master/ui/src/index.tsx). +The UI development server proxies API requests to a Gotify server running on +`localhost:80`. Create a `gotify-server.env` in the gotify/server repository +containing `GOTIFY_SERVER_PORT=8080` to change the port. ## Update Swagger spec -The [gotify/server REST-API](/api-docs) is documented via Swagger. The Swagger definition is generated via source code comments +The [gotify/server REST-API](/api-docs) is documented via Swagger. The Swagger definition is generated from source code comments ([example comment](https://github.com/gotify/server/blob/09c1516a170dfb47d29644db622655b540b94922/api/application.go#L33)). -After changing such a source code comment, you can run the following command to update the Swagger definition. +After changing such a comment, run the following command to update the Swagger definition. ```bash $ make update-swagger @@ -46,7 +47,7 @@ $ make update-swagger ### Execute Backend Tests -#### Run tests with parallelism +#### Run tests ```bash $ go test ./... @@ -59,22 +60,16 @@ $ make test-coverage $ go tool cover -html=coverage.txt # get a HTML coverage report ``` -#### Run Tests with Race Detector - -```bash -$ make test-race -``` - ### Execute UI (end2end) Tests -Build the ui because the end2end test should be run against the production build. -(This needs to be done on every change in the UI) +Build the UI because the end2end tests run against the production build. +(This needs to be done after every change in the UI) ```bash $ (cd ui && yarn build) ``` -Now execute the tests with yarn +Now execute the tests with yarn. ```bash $ (cd ui && yarn test) @@ -82,7 +77,7 @@ $ (cd ui && yarn test) ### Execute Static Checks -The following command checks the formatting and executes some linters like tslint and govet. +The following command checks the formatting, runs linters like golangci-lint and eslint, and verifies that the Swagger spec is up to date. ```bash $ make check diff --git a/docs/dev-setup.md b/docs/dev-setup.md index aa0d2fc..86304dd 100644 --- a/docs/dev-setup.md +++ b/docs/dev-setup.md @@ -2,13 +2,13 @@ Gotify requires: -- Go 1.18 or newer -- Node 16.x or newer +- Go 1.25 or newer +- Node 24 or newer - Yarn 1.9 or newer ## Clone sources -Clone gotify server source from git: +Clone the gotify/server source from git: ```bash $ git clone https://github.com/gotify/server.git && cd server @@ -16,7 +16,7 @@ $ git clone https://github.com/gotify/server.git && cd server ## Setup Backend -Download dependencies +Install the development tools (needed for generating the Swagger spec): ```bash $ make download-tools diff --git a/docs/first-login.md b/docs/first-login.md index 0169cf3..8ce77ee 100644 --- a/docs/first-login.md +++ b/docs/first-login.md @@ -1,7 +1,7 @@ # First Login -After setting up gotify/server you can login to the WebUI. When first launched an initial account is created so you can log in. If you have not overriden the defaults in the configuration, use username: `admin` password: `admin`. +After setting up gotify/server you can log in to the WebUI. On first launch an initial admin account is created. If you have not overridden the defaults in the configuration, use username `admin` and password `admin`. -Once you have logged in you can create your own user(s) and, if desired, delete the default account (after creating a separate administrator account). You can also remove any username/password overrides in your configuration, as they are only used to initially create this account. +Once logged in you can create your own user(s) and, if desired, delete the default account (after creating another administrator account). You can also remove any username/password overrides from your configuration, they are only used to create this initial account. -If you choose to keep the default account be sure to change the password so it is not `admin`! +If you keep the default account, be sure to change its password so it is not `admin`! diff --git a/docs/haproxy.md b/docs/haproxy.md index 7cbda48..6a4b8bb 100644 --- a/docs/haproxy.md +++ b/docs/haproxy.md @@ -1,6 +1,6 @@ -# Haproxy reverse proxy +# HAProxy reverse proxy -Here are configuration examples for setting up Haproxy as reverse proxy for gotify/server. +Here are configuration examples for setting up HAProxy as a reverse proxy for Gotify. ## Proxy requests diff --git a/docs/index.md b/docs/index.md index b4d4176..ff0882c 100644 --- a/docs/index.md +++ b/docs/index.md @@ -1,13 +1,12 @@ # Intro -This is the documentation of gotify/server. Lets start with some definitions: +This is the documentation of gotify/server. Let's start with some definitions: -A client is a device or application that can manage clients, messages and applications. -However a client is not allowed to send messages. +A client is a device or program that receives messages and can manage clients, applications and messages. A client cannot send messages. -An application is a device or application that only can send messages. +An application is a device or program that can only send messages. -Users are only able to manage (view/edit/delete) clients and applications (includes messages sent by the app) that they've created. +Users can only manage (view/edit/delete) the clients and applications they created, including messages sent by those applications. A message has the following attributes: content, title, creation date, application id and priority. diff --git a/docs/install.md b/docs/install.md index e9a48ba..5c40314 100644 --- a/docs/install.md +++ b/docs/install.md @@ -2,9 +2,7 @@ ## Docker -Setting up gotify/server with docker is pretty easy, you basically just have to start the docker container and you are ready to go: - -Before starting gotify/server you may read the [Configuration](config.md) if you f.ex. use a different database. +Before starting, read the [Configuration](config.md) page if you, for example, want to use a different database. ```bash $ docker run -p 80:80 -v /var/gotify/data:/app/data gotify/server @@ -14,11 +12,10 @@ $ docker run -p 80:80 -v /var/gotify/data:/app/data ghcr.io/gotify/server [gotify/server](https://hub.docker.com/r/gotify/server) and [ghcr.io/gotify/server](https://github.com/gotify/server/pkgs/container/server) -are multi-arch docker images, they will work for the architectures: amd64, -i386, arm64, armv7, and riscv64. +are multi-arch Docker images supporting amd64, i386, arm64, armv7, and riscv64. -`/app/data` contains the database file (if sqlite is used), images for applications and cert-files (if lets encrypt is enabled). -In this example the directory is mounted to `/var/gotify/data` this directory should be included in a backup. +`/app/data` contains the database file (if SQLite is used), application images and certificates (if Let's Encrypt is enabled). +In this example the directory is mounted to `/var/gotify/data`, include this directory in your backups. The time zone inside the container is configurable via the `TZ` environment variable: @@ -53,12 +50,13 @@ Latest version: latest release -### Supported Platforms: +### Supported Platforms - linux-amd64 (64bit) - linux-386 (32bit) -- linux-arm-7 (32bit used for Raspberry Pi) +- linux-arm-7 (32bit, used for Raspberry Pi) - linux-arm64 (ARMv8) +- linux-riscv64 (RISC-V) - windows-386.exe (32bit) - windows-amd64.exe (64bit) @@ -83,9 +81,9 @@ Make the binary executable. $ chmod +x gotify-{PLATFORM} ``` -Execute gotify/server. (By default gotify/server is started on port 80 so it requires sudo) +Execute gotify/server. By default it listens on port 80, which requires sudo. -Before starting gotify/server you may read the [Configuration](config.md) if you f.ex. want to change the port or use a different database. +Before starting, read the [Configuration](config.md) page if you, for example, want to change the port or use a different database. ```bash $ sudo ./gotify-{PLATFORM} diff --git a/docs/migrate-to-3.md b/docs/migrate-to-3.md index 11d7595..5712c95 100644 --- a/docs/migrate-to-3.md +++ b/docs/migrate-to-3.md @@ -18,9 +18,9 @@ ### YAML config file removed -The YAML config file (`config.yml`) is no longer supported. Gotify can now be -only configured by environment variables, which can be loaded from an env file. -The first existing file from this search order is loaded: +The YAML config file (`config.yml`) is no longer supported. Gotify 3 is +configured only through environment variables, which can be loaded from an env +file. The first existing file from this search order is loaded: 1. `gotify-server.env` (in the working directory) 2. `$XDG_CONFIG_HOME/gotify/gotify-server.env` (`$XDG_CONFIG_HOME` falls back to `$HOME/.config` when unset) @@ -44,7 +44,7 @@ $ docker run --rm -v "$(pwd)/config.yml:/app/config.yml" gotify/server:master \ migrate-config config.yml > gotify-server.env ``` -### Environment List and map syntax +### Environment list and map syntax Defining settings via environment variables was already possible, but the syntax for list and map values has changed. If you set any of the variables below, update @@ -82,16 +82,18 @@ GOTIFY_SERVER_RESPONSEHEADERS={"X-Custom-Header":"custom value"} ### Tokens are only shown once -As part of an effort to align with secure API design principles, -tokens will no longer be returned via the API or WebUI except when the token is issued via creation or rotation. -Workflows dependent on introspecting existing clients or applications for their token will stop working. +To align with secure API design principles, tokens are no longer returned by +the API or WebUI, except once when they are created or rotated. Workflows that +read tokens of existing clients or applications will stop working. ::: tip -The post message endpoint now accepts an "appid" parameter, which allows clients -to impersonate applications they control without knowing the corresponding application token. +The create message endpoint now accepts an `appid` parameter. This lets clients +post messages as one of their own applications without knowing the +application token. ::: -Tokens for existing applications can now be rotated via the _application security update_ endpoint. +Tokens of existing applications can be rotated via the application security +update endpoint (`PUT /application/{id}/security`). Existing tokens (starting with `A` and `C`) will continue to work. Plugin tokens (starting with `P`) used to access web resources are not affected by this change. @@ -115,23 +117,23 @@ With a non-elevated client token these return `403`: | `POST /client/{id}/elevate` | Elevate a client token | | `GET /user`, `GET`/`POST`/`DELETE /user/{id}` | Manage users (admin) | -The `Client` and `CurrentUser` models have gotten elevation-related fields. See the -[API documentation](/api-docs) for details. +The `Client` and `CurrentUser` models now include elevation-related fields. See +the [API documentation](/api-docs) for details. ::: tip -To update your workflow that uses the endpoints above with a client token. Perform a separate elevation process before the call. Either: +If a script calls these endpoints with a client token, either: -- Transitition to use HTTP Basic auth as they are elevated by default. -- Elevate the client in the WebUI or the api with basic auth before calling these APIs. +- Switch to HTTP Basic auth, basic auth requests are always elevated. +- Elevate the client token first, in the WebUI. See [Session Elevation](./session-elevation.md). ::: ## CLI Changes -The binary now uses subcommands. You should migrate to using the `serve` -subcommand. For backwards compatibility running gotify without a command will -continue to serve the server. +The binary now uses subcommands. You should migrate to the `serve` subcommand. +For backwards compatibility, running Gotify without a subcommand still starts +the server. ```bash $ ./gotify-linux-amd64 serve diff --git a/docs/more-pushmsg.md b/docs/more-pushmsg.md index 64dfdf4..1033d3d 100644 --- a/docs/more-pushmsg.md +++ b/docs/more-pushmsg.md @@ -1,10 +1,10 @@ # (more) Push message examples -Have a look [here](pushmsg.md) for "How to obtain an application token". +See [Push messages](pushmsg.md) for how to obtain an application token. -NOTE: Assuming Gotify is running on `http://localhost:8008`. +All examples assume Gotify is running on `http://localhost:8008`. Replace `` with your application token. -### Bash (using cURL and markdown) +## Bash (using cURL and markdown) ```bash #!/bin/bash @@ -16,7 +16,7 @@ URL="http://localhost:8008/message?token=" curl -s -S --data '{"message": "'"${MESSAGE}"'", "title": "'"${TITLE}"'", "priority":'"${PRIORITY}"', "extras": {"client::display": {"contentType": "text/markdown"}}}' -H 'Content-Type: application/json' "$URL" ``` -### Python +## Python ```python import requests #pip install requests @@ -27,14 +27,14 @@ resp = requests.post('http://localhost:8008/message?token=', json={ }) ``` -### Golang +## Golang ```go package main import ( - "net/http" - "net/url" + "net/http" + "net/url" ) func main() { @@ -43,7 +43,7 @@ func main() { } ``` -### PHP (using cURL) +## PHP (using cURL) ```php $data = [ @@ -93,7 +93,7 @@ switch ($code) { } ``` -### JavaScript +## JavaScript ```javascript const axios = require('axios'); @@ -114,10 +114,10 @@ axios({ data: bodyFormData, }) .then((response) => console.log(response.data)) - .catch((err) => console.log(err.response ? error.response.data : err)); + .catch((err) => console.log(err.response ? err.response.data : err)); ``` -### Java 11 +## Java 11 With Maven dependency: @@ -143,8 +143,8 @@ import java.net.http.HttpRequest; import java.net.http.HttpResponse; public class GotifyClient { - private static final String BASE_URL = "http://localhost:8080"; - private static final String TOKEN = ""; + private static final String BASE_URL = "http://localhost:8008"; + private static final String TOKEN = ""; public static void main(String[] args) throws IOException, InterruptedException { final var client = new GotifyClient(BASE_URL, TOKEN); @@ -202,7 +202,7 @@ public class GotifyClient { } ``` -### VB/VBA +## VB/VBA ```vb Const GOTIFY_URL As String = "http://localhost:8008/message?token=" @@ -222,13 +222,13 @@ End Function ' Test PushToGotify function Public Sub Test_PushToGotify() - Debug.Print PushToGotify(GOTIFY_URL, "My Title", "Hello there!", 2) + Debug.Print PushToGotify("My Title", "Hello there!", 2) End Sub ``` -### Wget +## Wget -```sh +```bash token="" subject="wget" message="Test push from wget" diff --git a/docs/msgextras.md b/docs/msgextras.md index a4dc280..92e01d7 100644 --- a/docs/msgextras.md +++ b/docs/msgextras.md @@ -32,14 +32,14 @@ Some of the namespaces are used by official clients: > **Note**: Markdown supports rendering images via `![](img url)`, > these images will be automatically downloaded when the message is viewed. -> Similarly, to why remote contents are blocked by default in e-mail clients, +> Similar to why remote content is blocked by default in e-mail clients, > automatically downloading remote images could be used to collect information from the user. > > Also, if part of the message is interpolated from a malicious external source, > the attacker could inject malformed markdown which leads to information disclosure. > > It is recommended to use `text/plain` to reduce possible security issues -> when using text from external sources like f.ex. output from scripts. +> when using text from external sources, for example output from scripts. #### Example @@ -64,7 +64,7 @@ Some of the namespaces are used by official clients: ### `click`.`url` -`click`.`url` (string): Opens an URL on notification click. +`click`.`url` (string): Opens a URL on notification click. #### Example diff --git a/docs/nginx.md b/docs/nginx.md index 22eb7ac..c718344 100644 --- a/docs/nginx.md +++ b/docs/nginx.md @@ -1,14 +1,14 @@ # nginx reverse proxy -You may want to use your nginx server as a reverse proxy to run gotify. +Here are configuration examples for setting up nginx as a reverse proxy for Gotify. ## At the root of the domain -Here is a sample config file if you run your gotify instance on port 1245 +Here is a sample config file if your Gotify instance runs on port 1245. ```nginx upstream gotify { - # Set the port to the one you are using in gotify + # Set the port to the one you are using in Gotify server 127.0.0.1:1245; } @@ -23,7 +23,7 @@ server { proxy_pass http://gotify; proxy_http_version 1.1; - # Ensuring it can use websockets + # Ensuring it can use WebSockets proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "upgrade"; proxy_set_header X-Real-IP $remote_addr; @@ -31,11 +31,11 @@ server { proxy_set_header X-Forwarded-Proto http; proxy_redirect http:// $scheme://; - # The proxy must preserve the host because gotify verifies the host with the origin + # The proxy must preserve the host because Gotify verifies the host with the origin # for WebSocket connections proxy_set_header Host $http_host; - # These sets the timeout so that the websocket can stay alive + # These timeouts keep the WebSocket connection alive proxy_connect_timeout 1m; proxy_send_timeout 1m; proxy_read_timeout 1m; @@ -43,29 +43,29 @@ server { } ``` -If you want to use HTTPS through Nginx, keep the gotify setting GOTIFY_SERVER_SSL_ENABLED=false and rely on nginx to encrypt your traffic like you would with any other website. +If you want to use HTTPS through nginx, keep the Gotify setting `GOTIFY_SERVER_SSL_ENABLED=false` and rely on nginx to encrypt your traffic like you would with any other website. ## At a subpath -Here is the equivalent of the sample config above but running on a subpath +Here is the equivalent of the sample config above but running at a subpath. ```nginx upstream gotify { - # Set the port to the one you are using in gotify - server 192.168.178.34:8080; + # Set the port to the one you are using in Gotify + server 127.0.0.1:1245; } server { listen 80; - server_name localhost; + server_name push.example.com; location /gotify/ { proxy_pass http://gotify; rewrite ^/gotify(/.*) $1 break; proxy_http_version 1.1; - # Ensuring it can use websockets + # Ensuring it can use WebSockets proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "upgrade"; proxy_set_header X-Real-IP $remote_addr; @@ -73,7 +73,7 @@ server { proxy_set_header X-Forwarded-Proto http; proxy_redirect http:// $scheme://; - # The proxy must preserve the host because gotify verifies the host with the origin + # The proxy must preserve the host because Gotify verifies the host with the origin # for WebSocket connections proxy_set_header Host $http_host; diff --git a/docs/oidc.md b/docs/oidc.md index 58e61d0..317766a 100644 --- a/docs/oidc.md +++ b/docs/oidc.md @@ -17,8 +17,8 @@ The identity provider **must** support [PKCE](https://oauth.net/2/pkce/) (Proof | `GOTIFY_OIDC_CLIENTID` | The client ID registered with your identity provider. | | `GOTIFY_OIDC_CLIENTSECRET` | The client secret. | | `GOTIFY_OIDC_REDIRECTURL` | The callback URL the identity provider redirects to after authentication. Must match your provider config. | -| `GOTIFY_OIDC_AUTOREGISTER` | Automatically create a new Gotify user on first OIDC login. | -| `GOTIFY_OIDC_USERNAMECLAIM` | The OIDC claim used to determine the username. Common values: `preferred_username` or `email`. | +| `GOTIFY_OIDC_AUTOREGISTER` | Automatically create a new Gotify user on first OIDC login. Enabled by default. | +| `GOTIFY_OIDC_USERNAMECLAIM` | The OIDC claim used as the username. Common values: `preferred_username` (default) or `email`. | | `GOTIFY_OIDC_LINK_BY_USERNAME` | Link an OIDC identity to an existing local user with the same username. Disabled by default. | | `GOTIFY_OIDC_SCOPES` | Comma-separated scopes to request. Defaults to `openid,profile,email`. | @@ -47,11 +47,11 @@ This URL must match **exactly** between the Gotify config and your identity prov ## Linking by username -Gotify identifies users by username. When the OIDC username claim clashes with an existing local user that is not yet bound to an OIDC identity, this login is rejected by default. Set `GOTIFY_OIDC_LINK_BY_USERNAME=true` to bind OIDC identities to existing local users. +Gotify identifies users by username. By default, an OIDC login is rejected when its username belongs to an existing local user that is not yet linked to an OIDC identity. Set `GOTIFY_OIDC_LINK_BY_USERNAME=true` to link the OIDC identity to the existing local user instead. -Only enable it if you trust that usernames in your identity provider map to the same people as your Gotify usernames. +Only enable this if you trust that usernames in your identity provider map to the same people as your Gotify usernames. -## Sample IdP Config +## Sample IdP configurations ### Authelia diff --git a/docs/pushmsg.md b/docs/pushmsg.md index f8538fc..bfaca42 100644 --- a/docs/pushmsg.md +++ b/docs/pushmsg.md @@ -1,40 +1,40 @@ # Push messages -As already indicated in [Intro](index.md) you need an application to push messages to gotify/server. Only the user who created the application is able to see its messages. +As described in the [Intro](index.md), you need an application to push messages to the Gotify server. Only the user who created the application can see its messages. An application can be added via -- WebUI: click the `apps`-tab in the upper right corner when logged in and add an application -- REST-API: `curl -u admin:admin https://yourdomain.com/application -F "name=test" -F "description=tutorial"` - See [API-Docs](https://gotify.github.io/api-docs/) +- WebUI: click the `apps` tab in the upper right corner when logged in and add an application +- REST API: `curl -u admin:admin https://push.example.de/application -F "name=test" -F "description=tutorial"` + See [API docs](/api-docs) To authenticate as an application you need the application token. -The token is returned in the REST request and is viewable in the WebUI. +The token is returned when creating the application. Starting with Gotify 3, tokens are only shown once, on creation or rotation. -Now you can simply use [curl](https://curl.haxx.se/), [HTTPie](https://httpie.org/) or any other installed http-client to push messages. +Now you can use [curl](https://curl.se/), [HTTPie](https://httpie.io/) or any other HTTP client to push messages. ```bash $ curl "https://push.example.de/message?token=" -F "title=my title" -F "message=my message" -F "priority=5" $ http -f POST "https://push.example.de/message?token=" title="my title" message="my message" priority="5" ``` -On Microsoft PowerShell, you could alternatively use the built-in `Invoke-RestMethod` or `Invoke-WebRequest` cmdlets. +On Microsoft PowerShell, you can use the built-in `Invoke-RestMethod` or `Invoke-WebRequest` cmdlets. ```powershell PS> Invoke-RestMethod -Uri "https://push.example.de/message?token=" -Method POST -Body @{title="my title"; message="my message"; priority=5} # return is automatically parsed into a PowerShell object PS> Invoke-WebRequest -Uri "https://push.example.de/message?token=" -Method POST -Body @{title="my title"; message="my message"; priority=5} # return is as raw response ``` -> The message API takes an `extras` property that carries extra information with the message and describes how clients behave to this message. +> The message API takes an `extras` property that carries extra information with the message and describes how clients should handle it. > See [message extras](msgextras.md) for more information. -The `priority` parameter controls how clients present the message, f.ex. whether the Android app plays a notification sound. See [message priority](priority.md) for more information. +The `priority` parameter controls how clients present the message, for example whether the Android app plays a notification sound. See [message priority](priority.md) for more information. -As of gotify/server v1.2.0 only the `message` parameter is required. +Only the `message` parameter is required. [Here are more examples for pushing messages in different languages.](more-pushmsg.md) -Also you can use [gotify/cli](https://github.com/gotify/cli) to push messages. -The CLI stores url and token in a config file. +You can also use [gotify/cli](https://github.com/gotify/cli) to push messages. +The CLI stores URL and token in a config file. ```bash $ gotify push -t "my title" -p 10 "my message" diff --git a/docs/session-elevation.md b/docs/session-elevation.md index 92a9509..95c9381 100644 --- a/docs/session-elevation.md +++ b/docs/session-elevation.md @@ -7,8 +7,8 @@ hard-to-undo actions, even while already logged in. ## What requires elevation -These actions need an **elevated** session; with a plain client token they -return `403 Forbidden`: +These actions need an **elevated** session. With a non-elevated client token +they return `403 Forbidden`: | Action | Endpoint | | :----------------------------- | :-------------------------------------------- | diff --git a/docs/systemd.md b/docs/systemd.md index 2054ee0..78ecff5 100644 --- a/docs/systemd.md +++ b/docs/systemd.md @@ -4,15 +4,15 @@ To manage starting, logging, etc. of Gotify, systemd can be used. > [!note] > This is only a minimal example and does not provide the most secure or "best" -> way to run gotify. Please adjust the config to your needs. +> way to run Gotify. Please adjust the config to your needs. ## Installation -For this example, Gotify is installed by root in a directory called -`/opt/gotify/` and the executable in there is called `gotify`. The config file -will be `/etc/gotify/config.yml` using relative paths as in the example and the -service will be run as root. A file called `/opt/gotify/gotify.service` should -be created by root containing: +For this example, Gotify is installed by root in `/opt/gotify/` and the +executable in there is called `gotify`. The config file is +`/etc/gotify/config.yml`, using relative paths as in the example config, and +the service runs as root. Create a file `/opt/gotify/gotify.service` as root +containing: ```desktop [Unit] diff --git a/docs/traefik.md b/docs/traefik.md index 9848fa9..7bbfed7 100644 --- a/docs/traefik.md +++ b/docs/traefik.md @@ -1,5 +1,7 @@ # Traefik reverse proxy +Here is a Docker Compose example for setting up Traefik as a reverse proxy for Gotify. + ```yaml services: traefik: @@ -27,5 +29,6 @@ services: 'traefik.http.routers.gotify.tls.certresolver': 'letsencrypt' ``` -This should expose gotify with tls on `gotify.yourdomain.tld` using traefik as -a reverse proxy. See https://doc.traefik.io/traefik/ for more information. +This exposes Gotify with TLS on `gotify.yourdomain.tld` using Traefik as a +reverse proxy. See the [Traefik documentation](https://doc.traefik.io/traefik/) +for more information. diff --git a/index.md b/index.md index cedaa32..b405ced 100644 --- a/index.md +++ b/index.md @@ -3,7 +3,7 @@ layout: home hero: name: Gotify text: '' - tagline: a simple server for sending and receiving messages + tagline: A simple server for sending and receiving messages image: src: /img/logo.png alt: Gotify Logo @@ -43,13 +43,13 @@ The heart of this project. gotify/server features a WebUI and functionality for: ## [gotify/android](https://github.com/gotify/android) -An android client for subscribing to the message stream of gotify/server. -The app creates push notifications on newly received messages. +An Android client for subscribing to the message stream of gotify/server. +The app shows push notifications for newly received messages.
[![Get it on Google Play](/img/playstore.png)](https://play.google.com/store/apps/details?id=com.github.gotify) -[![Get it on F-Droid](/img/fdroid.png)](https://f-droid.org/de/packages/com.github.gotify/) +[![Get it on F-Droid](/img/fdroid.png)](https://f-droid.org/packages/com.github.gotify/) [![Download](/img/download-badge.png)](https://github.com/gotify/android/releases/latest)
@@ -69,7 +69,7 @@ _Google Play and the Google Play logo are trademarks of Google LLC._ ## [gotify/cli](https://github.com/gotify/cli) -A command line client for pushing messages to gotify/server. It is **not** required to push messages. See [Docs](/docs/). +A command line client for pushing messages to gotify/server. It is **not** required for pushing messages, any HTTP client works. See [Push messages](/docs/pushmsg). From 69919aaabaa480327054b62a33cd85713b0af6dc Mon Sep 17 00:00:00 2001 From: Jannis Mattheis Date: Tue, 7 Jul 2026 21:29:57 +0200 Subject: [PATCH 4/5] fix: don't use token in URL --- docs/more-pushmsg.md | 34 +++++++++++++++++++++++----------- docs/pushmsg.md | 8 ++++---- 2 files changed, 27 insertions(+), 15 deletions(-) diff --git a/docs/more-pushmsg.md b/docs/more-pushmsg.md index 1033d3d..a2eca37 100644 --- a/docs/more-pushmsg.md +++ b/docs/more-pushmsg.md @@ -11,16 +11,17 @@ All examples assume Gotify is running on `http://localhost:8008`. Replace `', json={ +resp = requests.post('http://localhost:8008/message', headers={"X-Gotify-Key": ""}, json={ "message": "Well hello there.", "priority": 2, "title": "This is my title" @@ -35,11 +36,15 @@ package main import ( "net/http" "net/url" + "strings" ) func main() { - http.PostForm("http://localhost:8008/message?token=", - url.Values{"message": {"My Message"}, "title": {"My Title"}}) + form := url.Values{"message": {"My Message"}, "title": {"My Title"}} + req, _ := http.NewRequest("POST", "http://localhost:8008/message", strings.NewReader(form.Encode())) + req.Header.Set("Content-Type", "application/x-www-form-urlencoded") + req.Header.Set("X-Gotify-Key", "") + http.DefaultClient.Do(req) } ``` @@ -54,10 +59,11 @@ $data = [ $data_string = json_encode($data); -$url = "http://localhost:8008/message?token="; +$url = "http://localhost:8008/message"; $headers = [ - "Content-Type: application/json; charset=utf-8" + "Content-Type: application/json; charset=utf-8", + "X-Gotify-Key: " ]; $ch = curl_init(); @@ -98,7 +104,7 @@ switch ($code) { ```javascript const axios = require('axios'); -const url = 'http://localhost:8008/message?token='; +const url = 'http://localhost:8008/message'; const bodyFormData = { title: 'Hello from Javascript', message: 'Test Push Service from Node.js', @@ -109,6 +115,7 @@ axios({ method: 'post', headers: { 'Content-Type': 'application/json', + 'X-Gotify-Key': '', }, url: url, data: bodyFormData, @@ -157,11 +164,13 @@ public class GotifyClient { } private final String gotifyUrl; + private final String token; private final HttpClient httpClient; private final ObjectMapper objectMapper; public GotifyClient(String baseUrl, String token) { - this.gotifyUrl = String.format("%s/message?token=%s", baseUrl, token); + this.gotifyUrl = baseUrl + "/message"; + this.token = token; this.httpClient = HttpClient.newHttpClient(); this.objectMapper = new ObjectMapper(); } @@ -172,6 +181,7 @@ public class GotifyClient { final var request = HttpRequest.newBuilder() .uri(URI.create(gotifyUrl)) .header("Content-Type", "application/json") + .header("X-Gotify-Key", token) .POST(HttpRequest.BodyPublishers.ofString(bodyData)) .build(); @@ -205,7 +215,8 @@ public class GotifyClient { ## VB/VBA ```vb -Const GOTIFY_URL As String = "http://localhost:8008/message?token=" +Const GOTIFY_URL As String = "http://localhost:8008/message" +Const GOTIFY_TOKEN As String = "" '--- Based on pushover-vba by Mauricio Arieira (https://github.com/makah/pushover-vba) Public Function PushToGotify(ByVal title As String, ByVal message As String, ByVal priority As Integer) As String @@ -215,6 +226,7 @@ Public Function PushToGotify(ByVal title As String, ByVal message As String, ByV With xhttp .Open "POST", GOTIFY_URL, False .setRequestHeader "Content-type", "application/x-www-form-urlencoded" + .setRequestHeader "X-Gotify-Key", GOTIFY_TOKEN .Send params PushToGotify = .responseText End With @@ -234,5 +246,5 @@ subject="wget" message="Test push from wget" priority=5 -wget "http://localhost:8008/message?token=$token" --post-data "title=$subject&message=$message&priority=$priority" -O /dev/null +wget "http://localhost:8008/message" --header "X-Gotify-Key: $token" --post-data "title=$subject&message=$message&priority=$priority" -O /dev/null ``` diff --git a/docs/pushmsg.md b/docs/pushmsg.md index bfaca42..7d144a1 100644 --- a/docs/pushmsg.md +++ b/docs/pushmsg.md @@ -13,15 +13,15 @@ The token is returned when creating the application. Starting with Gotify 3, tok Now you can use [curl](https://curl.se/), [HTTPie](https://httpie.io/) or any other HTTP client to push messages. ```bash -$ curl "https://push.example.de/message?token=" -F "title=my title" -F "message=my message" -F "priority=5" -$ http -f POST "https://push.example.de/message?token=" title="my title" message="my message" priority="5" +$ curl "https://push.example.de/message" -H "X-Gotify-Key: " -F "title=my title" -F "message=my message" -F "priority=5" +$ http -f POST "https://push.example.de/message" "X-Gotify-Key:" title="my title" message="my message" priority="5" ``` On Microsoft PowerShell, you can use the built-in `Invoke-RestMethod` or `Invoke-WebRequest` cmdlets. ```powershell -PS> Invoke-RestMethod -Uri "https://push.example.de/message?token=" -Method POST -Body @{title="my title"; message="my message"; priority=5} # return is automatically parsed into a PowerShell object -PS> Invoke-WebRequest -Uri "https://push.example.de/message?token=" -Method POST -Body @{title="my title"; message="my message"; priority=5} # return is as raw response +PS> Invoke-RestMethod -Uri "https://push.example.de/message" -Headers @{"X-Gotify-Key"=""} -Method POST -Body @{title="my title"; message="my message"; priority=5} # return is automatically parsed into a PowerShell object +PS> Invoke-WebRequest -Uri "https://push.example.de/message" -Headers @{"X-Gotify-Key"=""} -Method POST -Body @{title="my title"; message="my message"; priority=5} # return is as raw response ``` > The message API takes an `extras` property that carries extra information with the message and describes how clients should handle it. From 469a520a7cd4679b3e20011457a3459508c3eedf Mon Sep 17 00:00:00 2001 From: Jannis Mattheis Date: Tue, 7 Jul 2026 21:34:02 +0200 Subject: [PATCH 5/5] fix: reorder navigation --- .vitepress/config.ts | 30 +++++++++++++++++------------- 1 file changed, 17 insertions(+), 13 deletions(-) diff --git a/.vitepress/config.ts b/.vitepress/config.ts index 201fe5a..897a260 100644 --- a/.vitepress/config.ts +++ b/.vitepress/config.ts @@ -30,6 +30,7 @@ export default defineConfig({ {text: 'Configuration', link: '/docs/config'}, {text: 'First Login', link: '/docs/first-login'}, {text: 'Push messages', link: '/docs/pushmsg'}, + {text: 'Message Priority', link: '/docs/priority'}, {text: 'Message Extras', link: '/docs/msgextras'}, ], }, @@ -54,27 +55,30 @@ export default defineConfig({ {text: 'Setup Environment', link: '/docs/dev-setup'}, {text: 'Servers and Tests', link: '/docs/dev-server-and-tests'}, {text: 'Build Gotify', link: '/docs/build'}, + { + text: 'Testing unreleased changes', + link: '/docs/testing-master', + }, ], }, { text: 'Guides', items: [ - {text: 'OpenID Connect (OIDC)', link: '/docs/oidc'}, - {text: 'Session Elevation', link: '/docs/session-elevation'}, {text: 'Migrate to 3.x', link: '/docs/migrate-to-3'}, - { - text: 'Testing unreleased changes', - link: '/docs/testing-master', - }, - {text: 'Apache reverse proxy', link: '/docs/apache'}, - {text: 'Caddy 2 reverse proxy', link: '/docs/caddy'}, - {text: 'HAProxy reverse proxy', link: '/docs/haproxy'}, - {text: 'Message Priority', link: '/docs/priority'}, {text: '(more) Push message examples', link: '/docs/more-pushmsg'}, - {text: 'nginx reverse proxy', link: '/docs/nginx'}, {text: 'Optimize uploaded images', link: '/docs/optimize-images'}, - {text: 'systemd configuration', link: '/docs/systemd'}, - {text: 'Traefik reverse proxy', link: '/docs/traefik'}, + {text: 'Session Elevation', link: '/docs/session-elevation'}, + {text: 'Systemd configuration', link: '/docs/systemd'}, + { + text: 'Reverse Proxies', + items: [ + {text: 'Apache', link: '/docs/apache'}, + {text: 'Caddy 2', link: '/docs/caddy'}, + {text: 'HAProxy', link: '/docs/haproxy'}, + {text: 'Nginx', link: '/docs/nginx'}, + {text: 'Traefik', link: '/docs/traefik'}, + ], + }, ], }, ],