MBTA Dashboard - Setup#
What Was Established#
Office transit dashboard deployed on a self-hosted Debian VM (PLT-MBTADisplay, 192.168.168.42). Nginx serves static files from /var/www/MBTADisplay/public and proxies /api/ requests to a Node/Express caching proxy on port 3000. API keys are stored server-side and never exposed to the browser. Process managed via pm2 with a systemd service.
Architecture#
Browser (Anthias/Desktop)
→ Nginx (:80) → / → static files (/var/www/MBTADisplay/public)
→ /api/ → Node/Express proxy (:3000)
→ MBTA v3 API
→ OpenWeatherMap API
→ RSS feeds
→ Caches responsesNginx Configuration#
server {
listen 80;
server_name transit.intra.plgt.com 192.168.168.42;
root /var/www/MBTADisplay/public;
index index.html;
location / {
try_files $uri $uri/ =404;
}
location /api/ {
proxy_pass http://localhost:3000;
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}
}Node/Express Proxy#
Setup#
mkdir -p /opt/mbta-proxy
cd /opt/mbta-proxy
npm init -y
npm install express node-fetchAPI Key Management#
- API keys stored in
/opt/mbta-proxy/.env - Loaded via
process.env.MBTA_API_KEYin server.js - pm2 started with
--envflag to load .env file - Critical: API key must survive server.js overwrites from GitHub syncs
pm2 Process Manager#
pm2 start server.js --name mbta-proxy
pm2 save
pm2 startup systemdsystemd Service (/etc/systemd/system/pm2-administrator.service)#
[Unit]
Description=PM2 process manager
After=network.target
[Service]
Type=forking
User=administrator
ExecStart=/usr/local/bin/pm2 resurrect
ExecReload=/usr/local/bin/pm2 reload all
ExecStop=/usr/local/bin/pm2 kill
Restart=on-failure
[Install]
WantedBy=multi-user.targetGitHub Deployment#
Repository#
- Repo:
https://github.com/bich-nguyen/MBTADisplay.git - Cloned to
/var/www/MBTADisplay - Static files in
public/subdirectory - Server files in
/opt/mbta-proxy/(separate from web root)
Ownership#
sudo chown -R administrator:administrator /var/www/MBTADisplayNote: www-data ownership breaks git operations from administrator user.