NestHealth

Server documentation

Everything you need to run NestHealth at home: installing, adding your family, connecting phones, and keeping it backed up.

Overview

The NestHealth server is a single small program. It stores your family's records in a SQLite database and serves:

It has no dependencies beyond Node.js, and it never contacts the developer. It only talks to the push services and webhooks you set up.

The server and web app are free software under the GNU Affero General Public License v3.0. You can use, study, change and share them. If you modify them and let other people use your version over a network, you must offer those people your modified source code. The licence doesn't cover the NestHealth name or icon, so please give forks their own.

Requirements

Install with Docker

The server is published on Docker Hub as hansford909/nesthealth-server, for ordinary PCs and NAS boxes (amd64) and Raspberry Pi (arm64).

  1. Make a folder for it and download the Docker Compose file:
    mkdir nesthealth && cd nesthealth
    curl -O https://nesthealth.soam.uk/download/docker-compose.yml
  2. Start it. Docker downloads the image and restarts the server automatically after a reboot:
    docker compose up -d
  3. Open http://<server-address>:8080 in a browser, for example http://192.168.1.20:8080, and create the first account.

Records and photos are kept in a Docker volume called nesthealth-data, so they survive updates.

Without a compose file

docker run -d --name nesthealth --restart unless-stopped -p 8080:8080 \
  -e TZ=Europe/London -v nesthealth-data:/data hansford909/nesthealth-server

This also works in NAS apps such as Synology Container Manager, Unraid or Portainer: use the image hansford909/nesthealth-server, port 8080, and a volume or folder mounted at /data.

Building from source

Prefer to build it yourself? Download the source or clone it from GitHub, then run docker compose up -d --build in that folder after changing image: to build: . in docker-compose.yml.

Different port? If 8080 is already taken, change the ports line in docker-compose.yml to, for example, "8090:8080", and use port 8090 instead.

Install without Docker

With Node.js 22.13 or newer installed:

git clone https://github.com/mahansford/nesthealth-server.git
cd nesthealth-server
node server.js

Records are stored in a data folder next to server.js. Set DATA_DIR to keep them somewhere else, and PORT to use a different port. To keep it running in the background, use your system's service manager (for example a systemd service or a launchd agent).

Accounts

Headless setup: set ADMIN_EMAIL and ADMIN_PASSWORD (and optionally ADMIN_NAME) to create the admin account when the server first starts. Remove them afterwards.

The iPhone app

  1. Open NestHealth and choose Share with the family. If you've been using Just this iPhone, go to Settings → Data → Connect to a Home Server instead. Your records can be copied across.
  2. Enter the server's address including the port, for example http://192.168.1.20:8080, or its HTTPS address.
  3. Sign in with your account.

Reminders for when a dose can be given again are scheduled on each iPhone, so they work on any server. Widgets and the Lock Screen countdown work too.

Two limits on your own server: instant alerts when another parent logs a dose or a fever, and passkeys in the app, rely on Apple keys that belong to the app. In the iPhone app you'll sign in with your password. For alerts, turn on web push or a webhook such as ntfy.

The web app

Open the server's address in any browser to use NestHealth on a computer, an Android phone or a tablet.

HTTPS and remote access

On your home network, plain http:// works for logging and syncing. HTTPS is needed for web push notifications and passkeys, and a VPN or tunnel lets you use NestHealth away from home. Any of these work:

Behind a proxy, set PUBLIC_URL to the HTTPS address people use (for example https://health.example.com) so passkeys work.

Notifications

Set these up in the web app under Settings → Notifications. Notify About chooses the events; the settings apply to every device and webhook.

EventSent when
dose_dueA medicine can be given again
dose_givenAnother parent logs a dose (you're not notified about your own)
feverA reading is at or above your fever threshold
check_tempIt's time to recheck a temperature
testYou tap Send Test

Web push

Works on iPhone (iOS 16.4 or later, from the Home Screen app), Android and desktop browsers. It needs HTTPS. In the web app, go to Settings → Notifications and turn on push notifications for this device.

Webhooks

Choose Add Webhook and pick a format: ntfy, Discord, Slack or JSON (for Home Assistant, Node-RED or n8n). The JSON format posts:

{
  "event": "dose_given",
  "title": "Ella had Children's paracetamol",
  "message": "5 ml given at 14:05 by Mum.",
  "person": "Ella",
  "time": "2026-09-25T13:05:00.000Z",
  "data": {}
}

Backups

Back up everything (records, photos and settings) from the folder where you want the backup saved:

docker run --rm -v nesthealth-data:/data -v "$PWD":/backup alpine \
  tar czf /backup/nesthealth-backup.tgz -C /data .

To restore, stop the server, restore into the volume, and start it again:

docker compose down
docker run --rm -v nesthealth-data:/data -v "$PWD":/backup alpine \
  sh -c "cd /data && tar xzf /backup/nesthealth-backup.tgz"
docker compose up -d

Without Docker, copy the data folder while the server is stopped. You can also export every record as a spreadsheet from Settings → Data → Export all records (CSV).

Updating

From the folder with your docker-compose.yml:

docker compose pull
docker compose up -d

Your records live in the nesthealth-data volume, so they're kept. To stay on one version, use a tag such as hansford909/nesthealth-server:1.0 instead of latest.

If you build from source or run it without Docker, update the code with git pull, then run docker compose up -d --build or restart node server.js.

Configuration

Set these as environment variables, in the environment section of docker-compose.yml.

VariableDefaultWhat it does
PORT8080The port the server listens on
DATA_DIR./data (/data in Docker)Where the database and photos are stored
TZEurope/LondonTime zone for times shown in notifications
PUBLIC_URLFrom the requestThe HTTPS address people use. Set it if passkeys fail behind a proxy
VAPID_SUBJECTA placeholder addressA contact address (mailto:[email protected]) sent to web push services
ADMIN_EMAIL, ADMIN_PASSWORD, ADMIN_NAMENot setCreate the first admin account on start-up

Security

Troubleshooting

The app says it can't reach the server

Check that the address includes the port (http://192.168.1.20:8080), that your phone is on the same network or VPN, and that the server is running: docker compose ps. Opening http://<server-address>:8080/healthz in a browser should show ok.

The iPhone app isn't getting notifications

In the app, open Settings → Notifications and tap Turn On Notifications if it's there (NestHealth only appears in the iPhone's own notification settings once it has asked). Send Test Notification goes only to the devices of the person who pressed it, never the rest of the family.

Web push notifications don't arrive on iPhone

Web push on iPhone needs iOS 16.4 or later, the web app opened from the Home Screen (not in Safari), and an HTTPS address. Use Send Test in Settings → Notifications to check.

There's no option to add a passkey

Passkeys need HTTPS with a domain name, not an IP address. Browsers don't allow them for plain http:// or IP addresses. In the iPhone app, sign in with your password.

“Too many attempts”

Sign-in is paused for 15 minutes after repeated wrong passwords. Wait, then try again, or ask the admin to reset your password.

Seeing the server's log

docker compose logs -f

Still stuck? Get in touch.