Baby Mirror

Baby Mirror

The Baby Mirror is a MagicMirror² smart mirror: a Raspberry Pi driving a monitor mounted behind one-way glass. It was donated to DMA by /dev/hack, thanks to the folks over there! We use it to display info to the space, including a feed of community quotes.

Where it is

Currently sitting on top of the tool chest. Planned to be wall-mounted above the chest.

Hardware and software

  • Board: Raspberry Pi 3B+ (1 GB RAM)
  • Display: monitor + display driver board behind one-way glass
  • OS: Debian 13 (Trixie), 64-bit
  • MagicMirror: v2.37.0, running under Electron 42.5.2 on Node 24
  • Networking: managed by NetworkManager

Note that the Pi has been updated since it was donated. It is no longer running the original /dev/hack image, so do not assume the stock /dev/hack layout or tooling. Paths and service setup are documented below and were confirmed on the device on 2026-08-25.

Finding the mirror on the network

The mirror is on the DMA user VLAN (the dma.space/hello network), so you must be on that network to reach it. Its address comes from DHCP and changes.

The hostname does not resolve. smartmirror.user.dma.computer will not resolve even when you are on the user VLAN, because every VLAN's DHCP hands out public DNS (1.1.1.1 and 1.0.0.1) and the router does not run an internal resolver. Do not rely on the hostname. mDNS (smartmirror.local) did not answer either when this was last checked.

To find its current address, use one of:

  1. The router's DHCP lease table.
  2. A sweep of the user VLAN, then look for a host answering SSH with a Debian banner. It was at 10.20.110.92 on 2026-08-25.
  3. A keyboard on the Pi itself and hostname -I.

Access

  • SSH user: localadmin
  • Password: stored in the infra Vaultwarden (vault.dma.space) under the smartmirror item. That item lived in a personal vault until 2026-08-24 and is now shared to the org, so if you cannot find it, check that you are looking at the org vault. (Do not paste credentials on this page, the wiki is public.)
ssh localadmin@<ip>

SSH host key fingerprints (verify on first connect):

256  SHA256:3KxeMLQ0FjtB0n0XmRc0ugtDom14vmPNLxVWl/idsEA (ED25519)
256  SHA256:QubQF144eoTKvpVRUvECWkBkMP5zG7dTFgEVft/hJaU (ECDSA)
3072 SHA256:TfAb3KQ5LukzQ/dXTOH2esfB9q4QgeBNKeidXbsNLJs (RSA)

All three were confirmed correct on 2026-08-25.

Console access

If the mirror is off the network, you can get a local console with a USB keyboard:

  • Ctrl+Alt+F2 switches to a text console.
  • Ctrl+Alt+F7 switches back to the MagicMirror display.

Two things to know before you rely on this. The console keymap is not US and has dead keys, so quotes and symbols are hard to type correctly, and loadkeys cannot help because /usr/share/keymaps is not installed. Anything involving quotes or a password is much easier over SSH. Also remember to log out of the console when you are done, since the space is shared.

If the mirror is on but shows no data

A module reporting “no internet connection” usually means the Pi is up but has dropped off wifi. This happened on 2026-08-25 and the device had been offline long enough that nobody noticed.

Wifi is managed by NetworkManager, not by a wpa_supplicant.conf file. There is no /etc/wpa_supplicant/wpa_supplicant.conf on this box, and editing wpa_cli network blocks will not work, because NetworkManager owns the supplicant.

From a console on the Pi, the fix that worked was simply restarting the service:

sudo systemctl restart NetworkManager

It reconnected and picked up a DHCP lease immediately. If that is not enough:

nmcli device status
sudo nmcli device wifi rescan
nmcli device wifi list
sudo nmcli --ask device wifi connect dma.space/hello

nmcli device wifi connect can report that the network cannot be found when the scan cache is stale, so always rescan first. Using --ask prompts for the password instead of taking it on the command line, which avoids both shell quoting and the console keymap problem.

How MagicMirror is managed

MagicMirror runs as a systemd user service under the localadmin account. The unit lives at ~/.config/systemd/user/magicmirror.service, is enabled at boot, and starts /home/localadmin/scripts/start_mm.sh. The systemd unit and the /dev/hack start script are not alternatives to each other; the unit runs the script.

systemctl --user status magicmirror.service
systemctl --user restart magicmirror.service

Logs. journalctl --user does not work on this device and reports “No journal files were found”, because the per-user journal is not persisted. Use either of these instead:

systemctl --user status magicmirror.service --no-pager
sudo journalctl _UID=1000 -n 40 --no-pager

Configuration

MagicMirror config lives at:

/home/localadmin/MagicMirror/config/config.js

Modules are configured in the modules: [ ... ] array in that file. Installed modules live under /home/localadmin/MagicMirror/modules/.

Always back up and validate before restarting. A malformed config.js stops MagicMirror from starting and leaves the mirror blank.

cd /home/localadmin/MagicMirror/config
cp config.js config.js.bak-$(date +%F)
# edit, then check that it parses before restarting:
node -e 'require("/home/localadmin/MagicMirror/config/config.js"); console.log("OK")'
systemctl --user restart magicmirror.service

To roll back:

cp config.js.bak-<date> config.js
systemctl --user restart magicmirror.service

Displaying the community quotes feed

Quotes come from #.offtopic > quotes in Zulip, published as an Atom feed:

https://portal.dma.space/api/feeds/quotes.atom

The feed is public and needs no token. Confirm the mirror can reach it before relying on it, and test with GET, not HEAD. The endpoint is GET-only and curl -I returns 405 even when the feed is perfectly healthy:

curl -sS -o /dev/null -w '%{http_code}\n' https://portal.dma.space/api/feeds/quotes.atom

The display uses MagicMirror's built-in ''%%newsfeed%%'' module. This is the block currently in config.js:

{
    module: "newsfeed",
    position: "bottom_bar",
    config: {
        feeds: [
            {
                title: "DMA Quotes",
                url: "https://portal.dma.space/api/feeds/quotes.atom"
            }
        ],
        showSourceTitle: false,
        showPublishDate: false,
        showDescription: false
    }
},

showDescription is deliberately false. Each entry carries the whole quote in its <title> and has no <summary> or <content>, so there is no description to show. For the same reason, do not add ignoreOldItems: quotes are posted infrequently and the newest entry is often weeks old, so filtering by age would empty the bar.

The large centred text on the mirror is the separate compliments module, not the quotes feed.

Editing safely

This is a production device on the space's network. Coordinate before making changes, back up config.js first, validate that it parses, and restart the service to apply. If the mirror comes up blank after a change, restore the backup and restart.

Known issues

  • The wifi dropout described above has not been tested across a reboot. The NetworkManager profile should persist, but a silent recurrence is possible. If the mirror goes dark again, check wifi first.