Nightscout on NixOS
These instructions will help you build, configure, and run Nightscout (plus MongoDB and Nginx) on any infrastructure (bare metal, VM, VPS, etc.) that can run NixOS.
Table of contents
Install and configure MongoDB
MongoDB is installed and configured via the options under
services.mongodb.
Authentication and the root user can be set up automatically via the
enableAuth and initialRootPasswordFile options, or manually via the
mongosh shell command:
$ nix-shell -p mongosh
$ mongosh
test> use admin
admin> db.createUser(
{
user: "root",
pwd: "SUPER_SECRET_PASSWORD",
roles: [
{ role: "userAdminAnyDatabase", db: "admin" },
{ role: "dbAdminAnyDatabase", db: "admin" },
{ role: "readWriteAnyDatabase", db: "admin" }
]
}
)
A database and user for Nightscout to use can be created automatically
via the initialScript option, or manually via the mongosh shell
command:
$ nix-shell -p mongosh
$ mongosh --username root --authenticationDatabase admin
test> use nightscout
nightscout> db.createUser(
{
user: 'nightscout',
pwd: 'CHANGEME',
roles: [
{ role: 'readWrite', db: 'nightscout' }
]
}
)
Run Nightscout 15.0.8
The recommended documented way to run Nightscout 15.0.8 on NixOS is the official multi-architecture container image. Enable Docker in your NixOS configuration:
virtualisation.docker.enable = true;
Apply the NixOS configuration, then follow the Docker deployment guidance, beginning with the Nightscout configuration steps after Docker is installed. Pin nightscout/cgm-remote-monitor:15.0.8 if you want to remain on this release. The image is published for both amd64 and arm64 Linux.
Use the documented Docker secret configuration to mount the API-secret file read-only and set API_SECRET_FILE inside the container. Keep the source file outside the repository and Nix store. Do not define secret text directly in a Nix expression because evaluated values can be copied into the world-readable Nix store.
Legacy native build example
The historical native setup used buildNpmPackage and passed the Node.js package as an argument.
Warning
The native Nix expression below is a historical example pinned to Nightscout 15.0.3; it is not the current Nightscout release and is not validated against current Nixpkgs. Nightscout 15.0.8’s published npm lockfile omits registry metadata required by Nix’s offline fetchNpmDeps build, so changing only the version and hashes does not produce a working native build. Use the 15.0.8 container method above for a current installation.
nightscout.nix:
{ pkgs, nodejs }:
pkgs.buildNpmPackage (finalAttrs: {
pname = "cgm-remote-monitor";
version = "15.0.3";
src = pkgs.fetchFromGitHub {
owner = "nightscout";
repo = finalAttrs.pname;
rev = "${finalAttrs.version}";
hash = "sha256-bI7RvEz9+7k0ZsZWuW9SrLs2qlUHhmDjOwPlLp83Jzs=";
};
npmDepsHash = "sha256-p3Dqj78vzRmTPMgaodGXQgvHFE0jGsmBL0p9n403Y2M=";
nodejs = nodejs;
npmFlags = [ "--ignore-scripts" ];
npmBuildScript = "bundle";
meta = {
description = "nightscout web monitor";
homepage = "https://github.com/nightscout/cgm-remote-monitor";
license = pkgs.lib.licenses.agpl3Only;
maintainers = with pkgs.lib.maintainers; [ earldouglas ];
};
})
Run Nightscout with Systemd
See systemd.services.nightscout block in the complete NixOS
configuration below.
Read more about Systemd services on the NixOS wiki.
Configure Nginx as an entry point
See services.nginx block in the complete NixOS
configuration below.
Read more about Nginx on the NixOS wiki.
Complete legacy NixOS configuration
The configuration below expects the following environment variables to be set:
NIGHTSCOUT_API_SECRETNIGHTSCOUT_MONGO_PASSWORDNIGHTSCOUT_PORTNIGHTSCOUT_DNS_NAMEDEXCOM_PASSWORDDEXCOM_USERNAME
This configuration assumes that we want to source our data from Dexcom
Share. For alternatives, see the connect section of the docs.
This configuration also assumes that we want to run an Nginx reverse proxy in front of our Nightscout instance. This can be useful for observability, rate limiting, HTTPS support, etc.
configuration.nix:
{ pkgs, lib, ... }:
let
dexcomPassword = builtins.getEnv "DEXCOM_PASSWORD";
dexcomUsername = builtins.getEnv "DEXCOM_USERNAME";
nightscoutApiSecret = builtins.getEnv "NIGHTSCOUT_API_SECRET";
nightscoutMongoPassword = builtins.getEnv "NIGHTSCOUT_MONGO_PASSWORD";
nightscoutPort = builtins.parseInt(builtins.getEnv "NIGHTSCOUT_PORT");
dnsName = builtins.getEnv "NIGHTSCOUT_DNS_NAME";
# Use a supported version of Node.js
nodejs = pkgs.nodejs_20;
mongodb =
(import <nixpkgs> {
config.permittedInsecurePackages = [];
config.allowUnfreePredicate =
pkg: builtins.elem (pkgs.lib.getName pkg) [ "mongodb-ce" ];
}).mongodb-ce;
nightscout =
import ./nightscout.nix {
inherit pkgs;
inherit nodejs;
};
in {
## MongoDB ###########################################################
services.mongodb = {
enable = true;
package = mongodb;
extraConfig = ''
security.authorization: enabled
'';
};
## Nightscout service account ########################################
users.groups.nightscout = {};
users.users.nightscout = {
group = "nightscout";
isSystemUser = true;
};
## Nightscout service ################################################
systemd.services.nightscout = {
description = "nightscout";
after = [ "network.target" ];
wantedBy = [ "multi-user.target" ];
serviceConfig = {
WorkingDirectory = "${nightscout}/lib/node_modules/nightscout";
ExecStart = "${nodejs}/bin/node lib/server/server.js";
User = "nightscout";
Restart = "always";
};
environment = {
## Required ######################################################
# See https://github.com/nightscout/cgm-remote-monitor?tab=readme-ov-file#required
MONGODB_URI = "mongodb://nightscout:${nightscoutMongoPassword}@localhost:27017/nightscout";
API_SECRET = nightscoutApiSecret;
MONGODB_COLLECTION = "entries";
DISPLAY_UNITS = "mg/dl";
## Features ######################################################
# See https://github.com/nightscout/cgm-remote-monitor?tab=readme-ov-file#features
ENABLE =
lib.strings.concatStrings (
lib.intersperse " " [
"connect"
"ar2"
"basal"
"boluscalc"
"careportal"
"delta"
"devicestatus"
"direction"
"errorcodes"
"food"
"profile"
"simplealarms"
"speech"
"timeago"
]
);
AUTH_DEFAULT_ROLES = "denied";
BASE_URL = "https://nightscout.earldouglas.com";
## Core ##########################################################
# See https://github.com/nightscout/cgm-remote-monitor?tab=readme-ov-file#core
PORT = toString nightscoutPort;
# See https://github.com/nightscout/cgm-remote-monitor?tab=readme-ov-file#predefined-values-for-your-server-settings-optional
TIME_FORMAT = "24";
INSECURE_USE_HTTP = "true";
THEME = "colors";
## Dexcom Share ##################################################
# See https://github.com/nightscout/cgm-remote-monitor?tab=readme-ov-file#connect-nightscout-connect
CONNECT_SOURCE = "dexcomshare";
CONNECT_SHARE_ACCOUNT_NAME = dexcomUsername;
CONNECT_SHARE_PASSWORD = dexcomPassword;
## Plugins #######################################################
# See https://github.com/nightscout/cgm-remote-monitor?tab=readme-ov-file#plugins
AR2_CONE_FACTOR = "0";
};
};
## Nginx entry point and reverse proxy ###############################
services.nginx = {
enable = true;
virtualHosts."${dnsName}" = {
locations."/".extraConfig = ''
proxy_pass http://localhost:${toString nightscoutPort};
'';
};
};
}