Nightscout
Overview
Nightscout (cgm-remote-monitor) is an open-source, self-hosted continuous glucose monitoring (CGM) remote monitor. It stores CGM data in a private database and presents it on a live web dashboard. A REST API lets uploaders (xDrip+, AndroidAPS, Loop and others) write data and lets caregivers read it.
This image runs Nightscout (cgm-remote-monitor) 15.0.7 on Ubuntu 24.04 LTS, managed by systemd as the unprivileged nightscout user. It is secured from first boot: two secrets are generated fresh on every VM, and no default login ever ships.
What you get:
- Nightscout 15.0.7 run from
/opt/nightscouton the Node.js 22 LTS runtime, by the unprivilegednightscoutsystem account under a systemd service that starts on boot and restarts on failure - A local MongoDB 7.0 Community database that stores every glucose entry, treatment and profile. It is bound to loopback with authentication enabled, and its data directory is on a dedicated Azure data disk at
/var/lib/nightscout. - Nightscout listening on the loopback address
127.0.0.1:1337by design. It is never exposed directly. - The Nightscout dashboard and REST API on
:80, through an nginx reverse proxy to127.0.0.1:1337. Visitors reach the dashboard on the standard HTTP port. - A per-VM API secret (Nightscout's write/admin passphrase) and MongoDB password, generated fresh on the first boot of every VM, never baked into the image, and recorded in a root-only file
- Access set to
deniedby default, so the dashboard and API return nothing until the API secret is supplied mongod.service,nightscout.serviceandnginx.serviceas systemd units, enabled and active- An unauthenticated
/healthzendpoint for Azure Load Balancer health probes - 24/7 SecureAnyCloud support
Prerequisites
- An active Azure subscription, an SSH key pair, and a VNet plus subnet in the target region
- Standard_B2s (2 vCPU / 4 GiB RAM) is a sensible starting point. Size up for many concurrent followers.
- NSG inbound: allow
22/tcpfrom your management network and80/tcpfor the dashboard and API. - Nightscout serves plain HTTP on port 80. For production, terminate TLS in front of it with your own domain, because glucose data is sensitive and uploaders should connect over HTTPS.
Step 1 - Deploy from the Azure Marketplace
Sign in to the Azure Portal. Choose Create a resource, search the Marketplace for Nightscout by SecureAnyCloud, and select Create.
On Basics, pick your subscription, resource group, region and size. Under Administrator account, choose SSH public key and paste your key. Under Inbound port rules, allow SSH (22) and HTTP (80).
Review the dedicated data disk on the Disks tab. Then select Review + create, followed by Create.
Step 2 - Deploy from the Azure CLI
Deploy the image from the Azure CLI. Replace the values in angle brackets with your own:
# Accept the Marketplace terms once per subscription (required before the first CLI deploy)
az vm image terms accept --urn sac1647283583153:nightscout-ubuntu-24-04:default:latest
az vm create \
--resource-group <your-rg> \
--name nightscout \
--image sac1647283583153:nightscout-ubuntu-24-04:default:latest \
--size Standard_B2s \
--admin-username azureuser \
--ssh-key-values ~/.ssh/id_ed25519.pub \
--vnet-name <your-vnet> --subnet <your-subnet> \
--public-ip-sku Standard
az vm open-port --resource-group <your-rg> --name nightscout --port 80 --priority 1010Step 3 - Connect to your VM
Connect to the VM over SSH:
ssh azureuser@<vm-public-ip>Step 4 - Confirm the services are running
nginx serves Nightscout on port 80 and reverse-proxies to the Node.js app on 127.0.0.1:1337. The app in turn talks to MongoDB on 127.0.0.1:27017. Confirm that all three services are active and the ports are bound:
systemctl is-active mongod nightscout nginx nightscout-firstboot
sudo ss -tlnp | grep -E ':80 |:1337 |:27017 'Expected output:
active active active active LISTEN 0 511 0.0.0.0:80 0.0.0.0:* users:(("nginx",pid=...)) LISTEN 0 511 127.0.0.1:1337 0.0.0.0:* users:(("node",pid=...)) LISTEN 0 4096 127.0.0.1:27017 0.0.0.0:* users:(("mongod",pid=...)) LISTEN 0 511 [::]:80 [::]:* users:(("nginx",pid=...))Step 5 - Retrieve your API secret
On the first boot of every VM, nightscout-firstboot.service generates a unique API secret and MongoDB password. It writes them, together with the dashboard URL, into a root-only file. Read the file with:
sudo cat /root/nightscout-credentials.txtThe API secret unlocks the dashboard and authorizes writes to the REST API. Uploaders authenticate by sending the SHA1 hash of this secret as the api-secret HTTP header.
Keep this file safe. Anyone with the API secret can read and write your glucose data.
Step 6 - Confirm the stack and health endpoint
nginx serves an unauthenticated /healthz endpoint for load balancer probes. Confirm the Node.js and MongoDB versions, and confirm that the dashboard responds:
node -v mongod --version | head -1 curl -sI http://127.0.0.1/healthz | head -1 curl -s http://127.0.0.1/ | grep -o '<title>[^<]*</title>'Expected output:
v22.23.1 db version v7.0.37 HTTP/1.1 200 OK <title>Nightscout</title>Step 7 - Open the dashboard and authenticate
Browse to http://<vm-public-ip>/. Access is denied by default, so the dashboard first loads locked. No data is shown until you authenticate.
Click the padlock icon (or open the menu and choose Authentication Status). Paste the API secret from Step 5 and confirm.
Your browser stores the hashed secret locally, and the dashboard unlocks. It shows the glucose chart and the current reading.
Step 8 - Upload and read a glucose entry over the REST API
Uploaders and integrations use the Nightscout REST API v1. Authentication is the SHA1 hash of your API secret, sent as the api-secret header.
The example below computes the hash, posts a sample SGV (sensor glucose value) entry, and reads it back. Run it on the VM, or from any host after you replace 127.0.0.1 with the VM's address:
SECRET=$(sudo grep '^NIGHTSCOUT_API_SECRET=' /root/nightscout-credentials.txt | cut -d= -f2-)
HASH=$(printf '%s' "$SECRET" | sha1sum | cut -d' ' -f1)
TS=$(date +%s%3N)
# An unauthenticated write is rejected (secure by default):
curl -s -o /dev/null -w 'unauthenticated POST -> HTTP %{http_code}\n' \
-X POST http://127.0.0.1/api/v1/entries.json -H 'Content-Type: application/json' \
--data "[{\"type\":\"sgv\",\"sgv\":120,\"date\":${TS},\"direction\":\"Flat\"}]"
# An authenticated write succeeds and echoes the stored entry:
curl -s -X POST http://127.0.0.1/api/v1/entries.json \
-H "api-secret: ${HASH}" -H 'Content-Type: application/json' \
--data "[{\"type\":\"sgv\",\"sgv\":120,\"date\":${TS},\"direction\":\"FortyFiveUp\",\"device\":\"guide-demo\"}]"
# Read it back:
curl -s -H "api-secret: ${HASH}" 'http://127.0.0.1/api/v1/entries.json?count=1'Expected output:
unauthenticated POST -> HTTP 401 [{"type":"sgv","sgv":120,"date":1784599618173,"direction":"FortyFiveUp","device":"guide-demo","utcOffset":0,"sysTime":"2026-07-21T02:06:58.173Z","_id":"6a5ed4429f073ee2f61195b9"}] [{"_id":"6a5ed4429f073ee2f61195b9","sysTime":"2026-07-21T02:06:58.173Z","type":"sgv","date":1784599618173,"device":"guide-demo","direction":"FortyFiveUp","sgv":120,"utcOffset":0,"mills":1784599618173}]Point your CGM uploader app at http://<vm-public-ip> with the same API secret. Your live readings then begin to flow onto the dashboard.
Step 9 - Review glucose history with Reports
The Reports page renders longer-term views of your data across a date range you choose. The views include daily glucose profiles, distribution and day-to-day charts.
Open the page from the menu, or browse to http://<vm-public-ip>/report/.
Step 10 - Configure your treatment profile
Use the Profile Editor to set the parameters that Nightscout uses to interpret your data. These are insulin duration (DIA), insulin-to-carb ratios, insulin sensitivity factor, basal rates and your target glucose range.
Open the editor from the menu, or browse to http://<vm-public-ip>/profile/. Adjust the values for your care plan and save.
Step 11 - Confirm data lives on the dedicated disk
All MongoDB data lives under /var/lib/nightscout. This covers every glucose entry, treatment and profile. The path is a dedicated Azure data disk, captured into the image and re-provisioned on every VM:
df -h /var/lib/nightscout | tail -1 findmnt -no SOURCE,TARGET,FSTYPE /var/lib/nightscout
sudo ls /var/lib/nightscout/mongodb | head -5Expected output:
/dev/sdc 20G 301M 19G 2% /var/lib/nightscout /dev/sdc /var/lib/nightscout ext4 WiredTiger WiredTiger.lock WiredTiger.turtle WiredTiger.wt WiredTigerHS.wtMaintenance
- Back up your data: everything Nightscout stores lives in MongoDB's data files under
/var/lib/nightscout. Snapshot the data disk, or usemongodump/mongorestorefor logical backups. - Rotate the API secret: the API secret lives in the Nightscout process environment at
/etc/nightscout/nightscout.env(readable by root only). EditAPI_SECRET, then runsudo systemctl restart nightscout. Re-enter the new secret in each browser and uploader. - Add followers and roles: Nightscout supports named access tokens with fine-grained roles from the Admin Tools page, so followers do not need the full API secret. See the upstream documentation.
- Security updates: unattended security upgrades are enabled, so the OS keeps itself patched. Reboot when a new kernel is installed.
- TLS: for production, front Nightscout with your own domain and a TLS-terminating reverse proxy or Azure Application Gateway. Glucose data is sensitive and should travel over HTTPS.
Support
SecureAnyCloud provides 24/7/365 expert technical support for this image. Contact sales@secureanycloud.com.
Nightscout (cgm-remote-monitor) is licensed under the GNU Affero General Public License v3.0 (AGPL-3.0). SecureAnyCloud provides this image. Additional charges apply for build, maintenance and 24/7 support.
Deploy on Azure
Launch Nightscout CGM Remote Monitor on Ubuntu 24.04 LTS on Azure with 24/7 support from SecureAnyCloud.
View this image
Need Help?
Our support team is available 24/7.
sales@secureanycloud.com
Overview
Nightscout (the cgm-remote-monitor project) is a widely used open-source, self-hosted continuous glucose monitoring (CGM) remote monitor. It lets people with diabetes, their families and their care teams store and visualize glucose data in real time through a live web dashboard and a documented REST API. Readings from a sensor can be followed from any browser or shared with remote caregivers.
The SecureAnyCloud image installs Nightscout natively (no Docker), pinned to release 15.0.7. It is secured by default, and no login ships in the image.
What you get:
- Nightscout cgm-remote-monitor 15.0.7 installed natively on Ubuntu 24.04 LTS
- The Node.js application, pre-built (its client bundle is produced by the project's own webpack build) and managed by
nightscout.serviceon127.0.0.1:1337 - MongoDB 7.0 Community bound to
127.0.0.1with authorization enabled, with its data directory on a dedicated EBS data volume mounted at/var/lib/nightscout - nginx serving the dashboard on port 80 and reverse-proxying it to the application, with an unauthenticated
/healthzendpoint for load balancer probes - A
nightscout-firstboot.serviceoneshot that generates a unique API secret (Nightscout's shared passphrase that gates all write and administrative access) and a unique MongoDB database credential. It writes them to/root/nightscout-credentials.txt(readable only by root), starts the stack, then disables itself. - Access denied by default (
AUTH_DEFAULT_ROLES=denied): the dashboard and API are not readable or writable until the API secret is presented. MongoDB is never exposed to the network. - A fully patched OS with unattended security upgrades enabled
- 24/7 SecureAnyCloud support
Not a medical device. Nightscout is a project of the Nightscout Foundation and is provided for informational purposes only. It is not a medical device, is not intended to diagnose, treat, cure or prevent any disease, and does not replace professional medical advice or a prescribed monitoring device. Always confirm treatment decisions with a fingerstick and your care team.
Connecting to your instance
Connect over SSH as the default login user for your operating system variant:
OS variant SSH login user
Ubuntu 24.04 ubuntu
ssh ubuntu@<public-ip>Launch the instance
- Subscribe to the Nightscout listing in AWS Marketplace and choose Launch.
- Pick an instance type with at least 2 vCPUs and 8 GB RAM. The recommended type is
m5.large. - Under the security group, allow inbound 80 (dashboard) and 22 (SSH) from the addresses you will manage the instance from. Add 443 if you enable HTTPS.
- Launch, then wait for the instance to reach a running state. First boot provisions the database, generates the per-instance API secret and database credential, and brings the dashboard up.
You can also launch from the CLI:
aws ec2 run-instances \
--image-id <nightscout-ami-id> \
--instance-type m5.large \
--key-name <your-key> \
--security-group-ids <sg-with-22-and-80> \
--tag-specifications 'ResourceType=instance,Tags=[{Key=Name,Value=nightscout}]'Verify the services are running
Connect over SSH and confirm that the four managed units are active:
systemctl is-active mongod nightscout nightscout-firstboot nginxmongod active nightscout active nightscout-firstboot active nginx activeOnly the dashboard is exposed to the network. MongoDB and the Node application listen on loopback only:
sudo ss -tlnp | grep -E ':(80|1337|27017)\b'LISTEN 127.0.0.1:1337 node LISTEN 127.0.0.1:27017 mongod LISTEN 0.0.0.0:80 nginxThe MongoDB data directory is on the dedicated data volume:
df -h /var/lib/nightscout/dev/nvme1n1 20G 302M 19G 2% /var/lib/nightscoutSecure by default, no credential ships
The upstream project runs unauthenticated unless you set an API secret. This image is locked down and generates its own on first boot. Retrieve the per-instance secret (root only):
sudo cat /root/nightscout-credentials.txtNIGHTSCOUT_URL=http://<your-public-ip>/ NIGHTSCOUT_API_SECRET=<unique-24-char-secret> MONGO_APP_PASSWORD=<unique-mongodb-password>No shared password, database user or pre-seeded record exists in the image. MongoDB is bound to loopback with authorization enabled:
grep -E 'bindIp|authorization|dbPath' /etc/mongod.confdbPath: /var/lib/nightscout/mongodb bindIp: 127.0.0.1 authorization: enabledOpen the dashboard and authenticate
Browse to http://<your-public-ip>/. Access is denied by default, so Nightscout presents a device authentication dialog. Enter the NIGHTSCOUT_API_SECRET from Step 3 to unlock the dashboard.
Once you are authenticated, the dashboard shows the current glucose value, a trend arrow and a live chart of readings over time. You can select a time window of 2, 3, 4, 6, 12 or 24 hours.
Review reports
The built-in reporting suite turns the stored readings into clinical views. These include day to day, daily stats, distribution, percentile charts, weekly distribution, calibrations, treatments and more.
Open the suite from Reports (/report/).
Configure a treatment profile
The Profile Editor holds the clinical settings that Nightscout uses for its calculations and plugins. These are target range, insulin activity duration (DIA), insulin-to-carb ratio, sensitivity, timezone and units.
A default profile is created automatically. Edit it to match the care team's settings.
Connect a CGM uploader
CGM uploaders and follower apps push readings to Nightscout's REST API. They authenticate by sending the SHA1 of the API secret as the api-secret HTTP header. They never send the secret in plain text. Compute the hash your uploader needs:
printf '%s' 'YOUR_API_SECRET' | sha1sumCommon clients and where to enter the details:
- xDrip+ (Android): Settings, Cloud Upload, Nightscout Sync (REST-API), then enter
https://YOUR_API_SECRET@<your-host>/api/v1/. - AndroidAPS / Loop: configure the Nightscout URL and API secret in the app's Nightscout settings.
- Spike (iOS) and other uploaders: enter the site URL and the API secret.
You can verify the API end to end from the shell. An unauthenticated write is rejected. An authenticated write is stored, and it reads back:
SECRET=$(sudo grep '^NIGHTSCOUT_API_SECRET=' /root/nightscout-credentials.txt | cut -d= -f2-)
H=$(printf '%s' "$SECRET" | sha1sum | cut -d' ' -f1)
TS=$(date +%s%3N)
# Authenticated write of a sample sensor glucose value curl -s -H "api-secret: $H" -H 'Content-Type: application/json' \
-X POST http://127.0.0.1/api/v1/entries.json \
--data "[{\"type\":\"sgv\",\"sgv\":137,\"date\":$TS,\"direction\":\"Flat\",\"device\":\"guide\"}]"
# Read it back curl -s -H "api-secret: $H" 'http://127.0.0.1/api/v1/entries.json?count=1'The runtime stack
The appliance manages four systemd units. Knowing them helps with day-to-day operation:
mongod.service: MongoDB 7.0 Community, bound to127.0.0.1, authorization enabled, with its data directory on the dedicated volume at/var/lib/nightscout/mongodb.nightscout-firstboot.service: a oneshot that runs once on the first customer boot. It creates the per-instance MongoDB user, generates the API secret and writes/etc/nightscout/nightscout.envand the root-only credentials file. It then hands off to the app and disables itself via a sentinel.nightscout.service: the Node application (node lib/server/server.js) running as the unprivilegednightscoutsystem user on127.0.0.1:1337. It is gated so that it never starts before the per-instance secret exists.nginx.service: the reverse proxy on port 80 with the unauthenticated/healthzendpoint.
Installed versions on this image:
Nightscout 15.0.7 Node.js v22.23.1 npm 10.9.8 MongoDB v7.0.39 nginx 1.24.0Add a custom domain and HTTPS
Nightscout derives its base URL from the request host. It works by public IP or your own domain with no rebuild. To serve it over HTTPS:
- Point a DNS A record at the instance's public IP.
- Open port 443 in the security group.
- Install a certificate with Certbot:
sudo apt-get update && sudo apt-get install -y certbot python3-certbot-nginx
sudo certbot --nginx -d your-domain.exampleCertbot edits the nginx server block and reloads it. Renewals run automatically through the packaged systemd timer.
Managing the services
Use these commands to check, restart and reload the services:
# Status and logs systemctl status nightscout journalctl -u nightscout -e
# Restart the app or the database
sudo systemctl restart nightscout
sudo systemctl restart mongod
# Reload nginx after editing the site config
sudo nginx -t && sudo systemctl reload nginxSource code and licence
Nightscout / cgm-remote-monitor is free software licensed under the GNU Affero General Public License, version 3 (AGPL-3.0). This image ships the unmodified upstream 15.0.7 release. The corresponding source code is available from the upstream project at github.com/nightscout/cgm-remote-monitor.
The AGPL covers network use. If you modify Nightscout and let others interact with your modified version over the network, you must offer them the modified source under the same license.
Support
Every SecureAnyCloud image includes 24/7 support. If you have questions about deploying or operating this image, contact the SecureAnyCloud team through the details on your AWS Marketplace listing.
Nightscout is a trademark of its respective owner. Use of it here is nominative and does not imply affiliation or endorsement.
Deploy on AWS
Launch Nightscout CGM Remote Monitor with 24/7 support from SecureAnyCloud.
View on Marketplace
Need Help?
Our support team is available 24/7.
sales@secureanycloud.com