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
11 changes: 11 additions & 0 deletions services/gotify/.env
Original file line number Diff line number Diff line change
Expand Up @@ -23,4 +23,15 @@ TZ=Europe/Amsterdam # See: https://en.wikipedia.org/wiki/List_of_tz_database_tim
# Required: password of the user admin that Gotify creates at the first start.
GOTIFY_DEFAULTUSER_PASS=

# Optional: set to igotify to also start the iGotify container for the iOS app, see the README.
COMPOSE_PROFILES=

# iGotify Configuration (only used with the igotify profile)
IGOTIFY_IMAGE_URL=ghcr.io/androidseb25/igotify-notification-assist:latest
# Address at which iGotify reaches Gotify. Keep it: iGotify shares the network of the Tailscale sidecar and reaches Gotify on the loopback address.
GOTIFY_URLS=http://127.0.0.1:80
# Set the next two values after you set up the iGotify app, see the README.
GOTIFY_CLIENT_TOKENS=
SECNTFY_TOKENS=

#EXAMPLE_VAR="Environment variable"
26 changes: 25 additions & 1 deletion services/gotify/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,14 +12,17 @@ This stack runs Gotify with a Tailscale sidecar, as described in [the standard s
| Service port | `80` |
| Image | `gotify/server` |
| Data | `./gotify-data/app/data` |
| iGotify image | `ghcr.io/androidseb25/igotify-notification-assist` (optional) |
| iGotify data | `./gotify-data/igotify` (optional) |

## Before you start

Set `GOTIFY_DEFAULTUSER_PASS` in `.env`. It is the password of the user `admin` that Gotify creates at the first start. Compose stops with an error if it is empty.

## Deviations from the standard setup

None.
- **Optional iGotify container.** The Compose service `igotify` (container `app-gotify-igotify`) only runs when the `igotify` profile is active. It shares the network of the Tailscale sidecar, like the application, and stores its data in `./gotify-data/igotify`. See [iGotify for iPhone and iPad](#igotify-for-iphone-and-ipad).
- **iGotify port.** iGotify listens on port `8080` for its API and device pages. Tailscale Serve does not publish it, but it is reachable at the Tailscale IP address of the device when your Tailnet policy allows it.

## First run

Expand All @@ -31,7 +34,28 @@ In the Gotify app, use `https://gotify.<tailnet>.ts.net` as the server address.

Earlier versions of this stack set `GOTIFY_DEFAULTUSER_PASS=admin` in `compose.yaml`. The value is now empty in `.env`, and Compose stops with an error until you set it. Gotify reads it only at the first start, so a new value does not change the password of an existing installation. If you still log in as `admin` with the password `admin`, change the password in the web interface.

## Configuration

### iGotify for iPhone and iPad

Gotify has no iOS app. [iGotify](https://github.com/androidseb25/iGotify-Notification-Assistent) fills that gap: the optional `igotify` container listens to Gotify and forwards each message to the iGotify app on your iPhone or iPad.

Notifications leave your Tailnet on this route. iGotify encrypts each message and sends it over HTTPS to the SecNtfy relay of its author, which hands it to Apple's push service. Skip this section when you do not want that.

The stack uses the "local instance" mode of iGotify, so Gotify stays reachable only through your Tailnet. In this mode the app talks to Gotify directly, and the images of apps and contacts do not show in the iGotify app.

1. Start the stack as usual and install the [iGotify app](https://apps.apple.com/app/igotify/id6473452512) on a device that is connected to your Tailnet.
2. In the app, enter `https://gotify.<tailnet>.ts.net`, turn on the Local Instance toggle, and log in with your Gotify account. The app then shows three values: the Gotify URL, the Gotify client token, and the SecNtfy token.
3. In `.env`, set `COMPOSE_PROFILES=igotify`, and fill in `GOTIFY_CLIENT_TOKENS` and `SECNTFY_TOKENS` with the values from the app. Keep `GOTIFY_URLS=http://127.0.0.1:80` instead of the URL that the app shows: the iGotify container shares the network of the Tailscale sidecar and cannot resolve the MagicDNS name, but it reaches Gotify on the loopback address. The three values go together: if one is missing, the connection fails.
4. Apply the change with `docker compose up -d`.

The two tokens are secrets, so keep them out of anything you publish. Keep `COMPOSE_PROFILES=igotify` in `.env` as long as you use iGotify: without it, `docker compose down` and `docker compose pull` skip the `igotify` container.

To stop using iGotify, run `docker compose --profile igotify down`, empty `COMPOSE_PROFILES` in `.env`, and run `docker compose up -d`. A plain `docker compose down` leaves the `igotify` container behind once the profile is no longer active.

## Links

- [Gotify documentation](https://gotify.net/docs/)
- [Gotify source code](https://github.com/gotify/server)
- [iGotify documentation](https://github.com/androidseb25/iGotify-Notification-Assistent/wiki)
- [iGotify source code](https://github.com/androidseb25/iGotify-Notification-Assistent)
25 changes: 25 additions & 0 deletions services/gotify/compose.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -62,3 +62,28 @@ services:
condition: service_healthy
# Healthcheck: defined by the image (curl against /health), so this file does not override it.
restart: always

# Optional iGotify container: forwards Gotify messages to the iGotify iOS app. Start it with the igotify profile.
igotify:
profiles:
- igotify
image: ${IGOTIFY_IMAGE_URL} # Image to be used
network_mode: service:tailscale # Sidecar configuration to route the service through Tailscale
container_name: app-${SERVICE}-igotify # Name for local container management
environment:
- GOTIFY_URLS=${GOTIFY_URLS:-http://127.0.0.1:80} # Gotify on the loopback address of the shared network
- GOTIFY_CLIENT_TOKENS=${GOTIFY_CLIENT_TOKENS:-}
- SECNTFY_TOKENS=${SECNTFY_TOKENS:-}
- TZ=${TZ}
volumes:
- ./${SERVICE}-data/igotify:/app/data
depends_on:
application:
condition: service_healthy
healthcheck:
test: ["CMD", "curl", "-fs", "http://127.0.0.1:8080/Version"] # The image has no HEALTHCHECK, so call the version endpoint of iGotify
interval: 1m # How often to perform the check
timeout: 10s # Time to wait for the check to succeed
retries: 3 # Number of retries before marking as unhealthy
start_period: 10s # Time to wait before starting health checks
restart: always
Loading