Baby Buddy on Ubuntu 24.04 on Azure User Guide
Overview
Baby Buddy is a popular open source, self hosted web application that helps caregivers track a baby's daily activities and growth. It records feedings, sleep, diaper changes, tummy time, pumping, temperature and measurements, and presents them as an at a glance dashboard of cards, a chronological timeline and a set of reporting charts. The cloudimg image installs Baby Buddy as a Django 5.2 application in a dedicated Python virtual environment, served by gunicorn and reverse proxied behind nginx, then locks it down for a marketplace appliance. gunicorn is bound to loopback 127.0.0.1:8000 and never exposed directly; nginx on port 80 is the only way in, plus an unauthenticated /healthz endpoint for load balancer probes. Baby Buddy has its own built in authentication, so this image is secure by default in a Django specific way: the well known default admin/admin account is removed at build time, and on the first boot of every VM a fresh Django secret key is generated and the administrator account is created with a unique, randomly generated password written to a root only file. A populated demo child with several weeks of sample entries ships so the dashboard, timeline and charts are non empty out of the box; you delete it and add your own child whenever you are ready. Backed by 24/7 cloudimg support.
What is included:
- Baby Buddy 2.9.2 installed in a dedicated Python virtual environment and running as the
babybuddygunicorn systemd service - The full Baby Buddy web application on
:80, fronted by nginx with gunicorn bound to loopback only - Built in Django authentication with the default
admin/adminaccount removed and a unique administrator password generated on first boot - A per VM Django secret key generated on first boot, never baked into the image
- Host settings configured so sign in works on the public IP address or a custom domain, with no baked in hostname
- A populated demo child with roughly a month of feedings, sleep, diaper changes, tummy time and pumping so the dashboard and charts are non empty
- An unauthenticated
/healthzendpoint for Azure Load Balancer health probes babybuddy.service(gunicorn) +nginx.serviceas systemd units, enabled and active- 24/7 cloudimg 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 comfortable starting point; Baby Buddy is light on resources. NSG inbound: allow 22/tcp from your management network, 80/tcp for the web application, and 443/tcp if you add TLS. Baby Buddy serves plain HTTP on port 80; for production use, terminate TLS in front of it with your own domain and restrict access to trusted IP ranges (see Maintenance).
Step 1 - Deploy from the Azure Marketplace
Sign in to the Azure Portal, choose Create a resource, search the Marketplace for Baby Buddy by cloudimg, 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). Then Review + create -> Create.
Step 2 - Deploy from the Azure CLI
az vm create \
--resource-group <your-rg> \
--name baby-buddy \
--image <marketplace-image-urn> \
--size Standard_B2s \
--admin-username azureuser \
--generate-ssh-keys \
--public-ip-sku Standard
Open port 80 to your network so you can reach the web application:
az vm open-port --resource-group <your-rg> --name baby-buddy --port 80
Step 3 - Connect to your VM
ssh azureuser@<vm-public-ip>
Step 4 - Confirm the services are running
systemctl is-active babybuddy.service nginx.service
Both report active. Baby Buddy runs under gunicorn on the loopback address 127.0.0.1:8000; nginx fronts it on port 80. The application is never bound to a public interface, so nginx is the only way in.

Step 5 - Retrieve your admin password
Baby Buddy uses its own Django login. The username is admin and a unique password is generated on the first boot of your VM and written to a root only file:
sudo cat /root/babybuddy-credentials.txt
This file contains BABYBUDDY_USERNAME, BABYBUDDY_PASSWORD and the BABYBUDDY_URL to open in a browser. The file is mode 0600 root:root, and the default admin/admin account that Baby Buddy normally ships is removed at build time, so no shared or default credential exists in the image. Store the password somewhere safe and change it after first sign in (see Maintenance).

Step 6 - Confirm the health endpoint
nginx serves an unauthenticated health endpoint for load balancers and probes:
curl -s http://localhost/healthz
It returns ok. This endpoint never requires authentication, so it is safe for an Azure Load Balancer health probe.
Step 7 - Confirm authentication is required
Because Baby Buddy manages its own login, the dashboard cannot be reached without signing in. An unauthenticated request to the dashboard returns HTTP 302 and redirects to the sign in page, while the health endpoint stays open:
echo "health : $(curl -s -o /dev/null -w '%{http_code}' http://127.0.0.1/healthz)"
echo "dashboard: $(curl -s -o /dev/null -w '%{http_code}' http://127.0.0.1/dashboard/)"
It prints health : 200 and dashboard : 302. The dashboard, timeline and every tracking view require the per VM admin password; only the health endpoint is open. gunicorn is bound to loopback and nginx is the only way in.

Step 8 - Confirm the installed version and components
Baby Buddy runs on Django in a dedicated virtual environment. Confirm the framework version and that the core components are in place:
/opt/babybuddy/venv/bin/python -c "import django; print('Django', django.get_version())"
sudo ls /opt/babybuddy/venv/bin/gunicorn /opt/babybuddy/app/data/db.sqlite3 /etc/systemd/system/babybuddy.service
It reports Django 5.2 and lists the gunicorn binary, the SQLite database on the OS disk and the systemd unit. The image ships Baby Buddy 2.9.2 with a populated demo child so the dashboard is non empty on first boot.

Step 9 - Sign in
Browse to http://<vm-public-ip>/. Baby Buddy shows its sign in page. Enter admin and the password from Step 5.

After signing in you land on the dashboard for the demo child. It is a grid of at a glance cards - last feeding, last sleep, last diaper change, last pumping, recent activity counts and rolling statistics - all populated from the sample entries that ship with the image.

Step 10 - Explore the timeline
Open a child from the Children menu, or Timeline from the top navigation, to see the chronological record of everything that has been tracked - feedings, sleep, diaper changes, tummy time and notes - with timestamps and quick edit links. This is where you review and correct individual entries.

Step 11 - View the reporting charts
Open a child and choose Reports to reach the charting views. Baby Buddy renders interactive charts for feeding amounts and types, sleep patterns, diaper change frequency, tummy time and growth (weight, height and head circumference). The Feeding Amounts report, for example, breaks daily intake down by type across the tracked period.

Step 12 - Add your own child and remove the demo data
The image ships a populated demo child so the dashboard is not empty. When you are ready, add your own child from the Children menu (Children -> Add Child), then start tracking from the Activities and Measurements menus or with the quick add buttons on the dashboard. To remove the demo child once you have your own, open it from the Children list and choose Delete - this removes the demo child and all of its sample entries.
Maintenance
- Password: the administrator password is generated on first boot and stored in
/root/babybuddy-credentials.txt(mode0600 root:root). Change it from the web interface under the admin user menu -> Settings, or by resetting it from the command line:cd /opt/babybuddy/app && sudo runuser -u babybuddy -- env DJANGO_SETTINGS_MODULE=babybuddy.settings.production SECRET_KEY=$(grep '^SECRET_KEY=' /opt/babybuddy/babybuddy.env | cut -d= -f2-) /opt/babybuddy/venv/bin/python manage.py changepassword admin. - Add users: invite additional caregivers from Users in the top navigation, or create one on the command line with Baby Buddy's
createusermanagement command. - Restrict access: Baby Buddy serves plain HTTP on port 80. For production, restrict access to trusted IP ranges in your Network Security Group, and front it with TLS (for example certbot with your own domain) terminating on
:443. Add your domain toCSRF_TRUSTED_ORIGINSandALLOWED_HOSTSin/opt/babybuddy/babybuddy.envandsudo systemctl restart babybuddyif you use a custom hostname. - Loopback binding: gunicorn is bound to
127.0.0.1:8000in/etc/systemd/system/babybuddy.service, so nginx is the only path in. Keep it that way - do not change the bind address to a public interface. - Database: the SQLite database lives at
/opt/babybuddy/app/data/db.sqlite3(ownedbabybuddy:babybuddy). Back it up by copying the file while the service is stopped, or use Baby Buddy's built in Import / Export under the Database menu. - Upgrades: Baby Buddy is installed from a pinned release into its virtual environment. To upgrade, replace the source under
/opt/babybuddy/app, reinstall requirements with/opt/babybuddy/venv/bin/pip, runmanage.py migrateandmanage.py collectstatic, thensudo systemctl restart babybuddy. - Security patches: unattended-upgrades remains enabled so the OS continues to receive security updates automatically.
Support
cloudimg provides 24/7 expert support for this image. Contact support@cloudimg.co.uk.