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' }
]
}
)
Build Nightscout
Nightscout can be built using the buildNpmPackage
. Here, we pass
as an argument the Node.js package to use.
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 = lib.licenses.agpl3Only;
maintainers = with 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 NixOS configuration
The configuration below expects the following environment variables to be set:
NIGHTSCOUT_API_SECRET
NIGHTSCOUT_MONGO_PASSWORD
NIGHTSCOUT_PORT
NIGHTSCOUT_DNS_NAME
DEXCOM_PASSWORD
DEXCOM_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};
'';
};
};
}