The API server of Nighttune.
The Nighttune API backend can be run/installed manually, and by building and running a docker container. The easiest and fastest way to get up and running is by using docker.
To run the Nighttune backend in a docker container, you should be comfortable using the unix shell and the docker cli.
TLDR;
git clone https://github.com/houthacker/nighttune-backend.git
# Enter the repository root
cd nighttune-backend
# Either: prepare the required configuration directory structure in a directory of your choosing
# and build the image using default values.
./scripts/docker-image.sh --prepare ~/nighttune-docker
# Or, just prepare the directory and have the image pulled by docker compose.
# Ensure that the pull_policy parameter is removed from the compose file in this case.
./scripts/docker-image.sh --prepare-only ~/nighttune-docker
cd ~/nighttune-docker
# Edit compose.yml and .env to your needs
# ...
# Run the container
docker compose up -dTo build the docker container, either Docker Desktop or both Docker Engine and Docker Compose are required, so make sure you have either option installed first.
Running Nighttune on Windows has not been tested so please report any issues you might encounter.
Even if you're on Windows, you need access to bash. If you haven't yet, first install a tool
like Git for Windows which includes git and bash, or install
WSL which also includes git and bash, using PowerShell in administrator mode: wsl --install.
Checkout the repository:
git clone https://github.com/houthacker/nighttune-backend.git
# Enter the repository root
cd nighttune-backendThen build the container, or pull it from the registry.
# If you want to, let the build script explain itself:
./scripts/docker-image.sh --help
# Either: prepare the required configuration directory structure in a directory of your choosing
# and build the image using default values.
./scripts/docker-image.sh --prepare ~/nighttune-docker
# Or, just prepare the directory and pull the image.
# Ensure that the pull_policy parameter is removed from the compose file in this case.
./scripts/docker-image.sh --prepare-only ~/nighttune-docker
# Change into that directory and edit the configuration files to your needs.
cd ~/nighttune-docker# Change to the configuration directory
cd ~/nighttune-docker
# Run the container
docker compose up -d
# The container should now be reachable at http://localhost:3333Please ensure the following prerequisites have been installed. For some tools there are well-known alternatives, but if you want to use those you're on your own.
| Prerequisite | Notes |
|---|---|
| Docker | Required only if using the captcha service. |
| ufw | Firewall. Required only if Nighttune will be accessed remotely. |
| npm | Node Version Manager |
| nginx | HTTP web server. Required only if Nighttune will be accessed remotely. |
| certbot | A commandline tool to automate certificate administration. Required only when using nginx. |
Follow these steps if the captcha service is required.
Follow step 1 to install docker on your machine.
The frontend uses Cap for bot protection and the backend handles the verification. How to install and configure Cap is described at Cap.
Copy the template cap-compose.example.yaml to a suitable
directory in your vm and set the ADMIN_KEY environment variable to the admin key of your Cap
installation. Ensure any directories mentioned in the compose file have been created.
Details
Follow these steps if your Nighttune instance will be accessed remotely.
Important: In your compose file, ensure that the web service only listens on localhost (i.e. 127.0.0.1 or ::1), otherwise the web server can still be bypassed because nighttune will be listening on all interfaces.
Deny all incoming traffic by default, but leave ssh, http and https open.
$ sudo systemctl enable ufw
$ sudo ufw enable
# Allow ssh from your ip
$ sudo ufw allow from $your_ip to any port 22
# Or from any ip
$ sudo ufw allow 22/tcp
# Allow http, https
$ sudo ufw allow http
$ sudo ufw allow https
# Deny all other incoming traffic by default
$ sudo ufw default deny incominggit clone https://github.com/houthacker/nighttune-backend.git
# Enter the repository root
cd nighttune-backendCopy your (production) .env file to a suitable directory in your vm. See .env.example for its format.
# Copy env file to nightscout
$ scp .env.production nightscout.local:~# Create a directory to hold the database. Make sure it doesn't overlap with the repository directory.
$ mkdir -p ~/nighttune-backend/data
# Create or migrate the database
$ docker run --rm --mount type=bind,src=/home/user/nighttune-backend/data,dst=/data ghcr.io/houthacker/nighttune-backend:latest bash -c 'npx initdb /data/nighttune-backend-prod.db'Follow these steps if your Nighttune instance will be accessed remotely.
nighttune-backend uses nginx as a reverse proxy that also provides the ssl certificates using certbot.
sudo apt install nginx -yCheck if nginx is running. The output should look like the following:
$ sudo systemctl status nginx
● nginx.service - A high performance web server and a reverse proxy server
Loaded: loaded (/usr/lib/systemd/system/nginx.service; enabled; preset: enabled)
Active: active (running) since Sat 2025-10-18 15:45:36 CEST; 41s ago
Docs: man:nginx(8)
Process: 23433 ExecStartPre=/usr/sbin/nginx -t -q -g daemon on; master_process on; (code=exited, status=0/SUCCESS)
Process: 23434 ExecStart=/usr/sbin/nginx -g daemon on; master_process on; (code=exited, status=0/SUCCESS)
Main PID: 23465 (nginx)
Tasks: 3 (limit: 4595)
Memory: 2.4M (peak: 5.3M)
CPU: 55ms
CGroup: /system.slice/nginx.service
├─23465 "nginx: master process /usr/sbin/nginx -g daemon on; master_process on;"
├─23467 "nginx: worker process"
└─23468 "nginx: worker process"Answer the questions asked by certbot and have your certificates deployed.
sudo apt install certbot python3-certbot-nginx
sudo certbot --nginxAdd captcha config if you require the captcha service.
server {
# Update to your needs
server_name captcha.nighttune.local;
location / {
proxy_pass http://127.0.0.1:3334;
proxy_buffering off;
# Let Cap know the IP address of solvers.
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
include proxy_params;
}
location /ws/ {
proxy_pass http://127.0.0.1:3334;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
include proxy_params;
}
listen 443 ssl; # managed by Certbot
ssl_certificate /etc/letsencrypt/live/nighttune.local/fullchain.pem; # managed by Certbot
ssl_certificate_key /etc/letsencrypt/live/nighttune.local/privkey.pem; # managed by Certbot
include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot
ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot
}
server {
if ($host = captcha.nighttune.local) {
return 301 https://$host$request_uri;
} # managed by Certbot
listen 80;
# Keep in sync with server_name at the top of this file.
server_name captcha.nighttune.local;
return 404; # managed by Certbot
}
Edit the site config to allow reverse proxying to the backend (or docker container).
An example of this is shown below, assuming $backend_ip and $backend_port have been set correctly.
Usually, backend_ip will be 127.0.0.1 and backend_port will be 3333.
server {
# Update to your needs
server_name api.nighttune.local;
location / {
proxy_pass http://127.0.0.1:3333;
proxy_buffering off;
include proxy_params;
}
location /ws/ {
proxy_pass http://127.0.0.1:3333;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
include proxy_params;
}
listen 443 ssl; # managed by Certbot
ssl_certificate /etc/letsencrypt/live/nighttune.local/fullchain.pem; # managed by Certbot
ssl_certificate_key /etc/letsencrypt/live/nighttune.local/privkey.pem; # managed by Certbot
include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot
ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot
}
server {
if ($host = api.nighttune.local) {
return 301 https://$host$request_uri;
} # managed by Certbot
listen 80;
# Keep in sync with the server_name at the top of this file.
server_name api.nighttune.local;
return 404; # managed by Certbot
}
If checking the site configuration is successful, reload nginx.
$ sudo nginx -t
[sudo] password for houthacker:
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful
# Then reload nginx
$ sudo systemctl reload nginxAfther this, the backend should be reachable at the location you configured; congrats!