How to Run a Production Node.js Server 24/7 on a $100 Raspberry Pi
Development

How to Run a Production Node.js Server 24/7 on a $100 Raspberry Pi

Ricardo Gil
January 25, 2026
9 min read
#Raspberry Pi #Node.js #Self-Hosting #Tailscale #PM2 #DevOps
πŸ›’

Products in This Post

Affiliate links

As an Amazon Associate I earn from qualifying purchases at no extra cost to you.

Introduction

Tired of paying $10-50/month for hosting simple APIs? I was running a Node.js/Express server for my wife's photography business Stripe payments on my Windows machineβ€”which meant it only worked when my PC was on. Cloud hosting felt like overkill for a simple payment endpoint processing 10-20 transactions monthly.

Enter the Raspberry Pi 3 B+ β€” $100 of hardware (complete kit) that runs 24/7 for about $2/year in electricity. In this guide, I'll show you exactly how I migrated my production server to a Pi using Tailscale for secure remote access.

Why a Raspberry Pi for Production?

Cost Breakdown:

  • Cloud hosting (AWS Lightsail, DigitalOcean): $10-25/month = $120-300/year
  • Raspberry Pi 3 B+: $100 one-time + ~$2/year electricity
  • Break-even: First year. Pure savings after that.

My Use Case:

  • Node.js/Express API
  • Stripe webhook handler
  • Low traffic (~100 requests/day)
  • Needs 24/7 uptime
  • Must be secure and remotely accessible

Perfect fit for a Pi.

What You'll Need

Hardware: CanaKit Raspberry Pi 3 B+ Starter Kit ($99.99)

I used the CanaKit Raspberry Pi 3 B+ Starter Kit which includes everything:

What's in the box:

  • Raspberry Pi 3 B+ board (1.4GHz quad-core, 1GB RAM, dual-band WiFi)
  • 32GB Samsung EVO+ microSD card (pre-loaded with OS)
  • 2.5A power supply with noise filter (UL Listed)
  • Premium black case
  • 2x aluminum heat sinks
  • 6-foot HDMI cable
  • USB microSD card reader
  • PiSwitch (on/off power switch with LED - game changer!)
  • GPIO quick reference card
  • Full-color quick-start guide

Why this kit?

  • Everything you need in one package
  • No guesswork on compatibility
  • Quality components (Samsung EVO+ SD card, proper power supply)
  • That power switch alone is worth it (no more unplugging)

Software (All Free)

  • Node.js
  • PM2 (process manager)
  • Tailscale (secure remote access)
  • Your existing Node.js application

Step 1: Initial Raspberry Pi Setup (10 Minutes)

Unbox and Assemble

  1. Install heat sinks on the CPU and RAM chips
  2. Insert microSD card (comes pre-loaded with Raspberry Pi OS)
  3. Snap Pi into the case
  4. Connect HDMI, keyboard, mouse
  5. Plug in power via the PiSwitch

First Boot Configuration

The Pi will boot into the setup wizard:

  1. Set your country/timezone
  2. Change default password (important!)
  3. Connect to WiFi (or use ethernet)
  4. Update software (takes ~10 minutes)
  5. Reboot

Enable SSH for Headless Access

bash
# Open Raspberry Pi Configuration
sudo raspi-config

# Navigate to: Interface Options β†’ SSH β†’ Enable

# Reboot
sudo reboot

Find your Pi's IP address:

bash
hostname -I

Now you can SSH from your laptop:

bash
ssh pi@192.168.1.XXX

Step 2: Install Node.js and PM2

Install Node.js (v18 LTS)

bash
# Update system packages
sudo apt update && sudo apt upgrade -y

# Install Node.js from NodeSource
curl -fsSL https://deb.nodesource.com/setup_18.x | sudo -E bash -
sudo apt install -y nodejs

# Verify installation
node -v  # Should show v18.x.x
npm -v   # Should show 9.x.x

Install PM2 Process Manager

PM2 keeps your Node.js app running 24/7, auto-restarts on crashes, and survives reboots.

bash
# Install PM2 globally
sudo npm install -g pm2

# Verify
pm2 -v

Step 3: Transfer Your Server Files

I transferred my files from Windows using SCP. You have several options:

Option A: SCP from Windows/Mac/Linux

bash
# From your development machine
scp -r /path/to/your/server pi@192.168.1.XXX:/home/pi/

Option B: WinSCP (Windows GUI)

  1. Download WinSCP
  2. Connect to pi@YOUR_PI_IP
  3. Drag and drop your server folder

Option C: Git Clone

If your project is in GitHub:

bash
# On the Pi
cd /home/pi
git clone https://github.com/yourusername/your-server.git
cd your-server

My server structure:

code
/home/pi/stripe-server/
β”œβ”€β”€ index.js
β”œβ”€β”€ package.json
β”œβ”€β”€ package-lock.json
β”œβ”€β”€ .env
└── node_modules/ (will install on Pi)

Step 4: Install Dependencies and Start Server

bash
# Navigate to your server directory
cd /home/pi/stripe-server

# Install dependencies
npm install

# Test run (should work locally)
node index.js

# If it works, stop it (Ctrl+C) and start with PM2
pm2 start index.js --name "stripe-server"

# Check status
pm2 status

# View logs
pm2 logs stripe-server

# Make it survive reboots
pm2 startup
pm2 save

PM2 Startup Output: PM2 will give you a command to run. Execute it:

bash
sudo env PATH=$PATH:/usr/bin pm2 startup systemd -u pi --hp /home/pi

Now your server starts automatically when the Pi boots!

Step 5: Secure Remote Access with Tailscale

This is where the magic happens. Instead of opening ports and dealing with dynamic DNS, Tailscale creates a secure mesh network.

Install Tailscale on the Pi

bash
# Install Tailscale
curl -fsSL https://tailscale.com/install.sh | sh

# Authenticate and connect
sudo tailscale up

This will give you a URL to authorize the device. Open it in your browser and log in with Google/GitHub/etc.

Get Your Tailscale IP

bash
tailscale ip -4

You'll get something like xxx.78.xxx.13. This is your Pi's permanent Tailscale IP.

Test Local Access

From another device on your Tailscale network:

bash
curl http://xxx.78.xxx.13:3000

Enable Tailscale Funnel (Public Access)

Funnel makes your server publicly accessible via HTTPS without exposing your home IP:

bash
# Enable funnel on port 3000
tailscale funnel 3000

Your server is now available at:

code
https://raspberry.tailXXXX.ts.net

Security Note: Only enable funnel if you need public access. For internal tools, just use the Tailscale IP.

Step 6: Update Your Frontend

Update your Angular/React/whatever frontend to point to the new URL:

Before:

typescript
const API_URL = 'http://localhost:3000';

After:

typescript
const API_URL = 'https://raspberry.taila561.ts.net';

Or use the Tailscale IP if accessing from within your network:

typescript
const API_URL = 'http://xxx.78.xxx.13:3000';

Real-World Performance

After running this setup for several weeks:

Response Times

  • Local network: 5-15ms
  • Over Tailscale: 40-80ms
  • Public funnel: 60-120ms
  • Cold starts: None (always running)

Resource Usage

bash
# Check resource usage
htop

My Stripe server:

  • CPU: 0.5-2% (idle to moderate load)
  • RAM: 45MB out of 1GB
  • Disk: 120MB total

Power Consumption

  • Idle: ~3.5W
  • Under load: ~5.5W
  • Monthly cost: ~$0.16 @ $0.12/kWh
  • Yearly cost: ~$2

Compare to AWS Lightsail $10/month instance: $120/year saved.

Monitoring & Maintenance

PM2 Commands

bash
# Check server status
pm2 status

# View real-time logs
pm2 logs stripe-server

# Restart server
pm2 restart stripe-server

# Stop server
pm2 stop stripe-server

# View resource usage
pm2 monit

System Monitoring

bash
# Check CPU temperature
vcgencmd measure_temp

# Check system resources
htop

# Check disk space
df -h

# View system logs
sudo journalctl -xe

Auto-Updates

Set up unattended-upgrades for security:

bash
sudo apt install unattended-upgrades
sudo dpkg-reconfigure --priority=low unattended-upgrades

Production Considerations

What Works Great on a Pi

βœ… Low-traffic APIs (< 1,000 requests/day)
βœ… Webhook handlers (Stripe, GitHub, etc.)
βœ… Scheduled jobs/cron tasks
βœ… Internal tools and dashboards
βœ… Development/staging environments
βœ… IoT/home automation backends

What Doesn't Work Well

❌ High CPU workloads (video encoding, ML training)
❌ Heavy database operations (large PostgreSQL queries)
❌ Memory-intensive apps (limited to 1GB RAM)
❌ Mission-critical services (no redundancy)
❌ High-traffic production (1000+ concurrent users)

My Recommendation

Use the Pi for:

  • Side projects
  • Hobby apps
  • Low-traffic production services
  • Learning and experimentation

For high-traffic or mission-critical stuff, stick with proper cloud hosting.

Backup Strategy

My backup approach:

  1. Code: Always in Git (GitHub private repo)
  2. Database: Daily dump to Tailscale-connected NAS
  3. SD card image: Monthly full backup
bash
# Backup script (save as backup.sh)
#!/bin/bash
DATE=$(date +%Y-%m-%d)
tar -czf ~/backups/server-$DATE.tar.gz ~/stripe-server

Run it with cron:

bash
crontab -e
# Add this line:
0 2 * * * ~/backup.sh

Cost Analysis: 1-Year Total Cost of Ownership

Raspberry Pi Setup

  • CanaKit Starter Kit: $99.99 (one-time)
  • Electricity: ~$2/year
  • Total Year 1: $102
  • Total Year 2+: $2/year

Cloud Hosting Alternative

  • AWS Lightsail (512MB): $3.50/month = $42/year
  • DigitalOcean (1GB): $6/month = $72/year
  • AWS EC2 t3.micro: ~$10/month = $120/year

Break-even with cheapest cloud option: 2-3 months
5-year savings vs DigitalOcean: $350

Troubleshooting

Server won't start after reboot

bash
# Check PM2 status
pm2 status

# Reinstall PM2 startup
pm2 unstartup
pm2 startup
pm2 save

Can't access via Tailscale

bash
# Check Tailscale status
tailscale status

# Restart Tailscale
sudo systemctl restart tailscaled

High CPU temperature (> 80Β°C)

bash
# Check temperature
vcgencmd measure_temp

# The heat sinks should keep it under 70Β°C
# If higher, ensure case ventilation is good

Out of disk space

bash
# Check space
df -h

# Clean up logs
sudo journalctl --vacuum-time=7d

# Clean npm cache
npm cache clean --force

Next Steps

Once you're comfortable with this setup, consider:

  1. Add SSL certificate (if not using Tailscale funnel)
  2. Set up monitoring (Prometheus + Grafana)
  3. Add a second Pi for redundancy
  4. Run multiple services (add Nginx reverse proxy)
  5. Dockerize your apps for easier management

Conclusion

Running a production Node.js server on a Raspberry Pi 3 B+ is:

  • Cheap: $100 upfront, $2/year after
  • Easy: PM2 handles the heavy lifting
  • Secure: Tailscale provides zero-trust networking
  • Reliable: PM2 auto-restarts, survives reboots
  • Perfect for: Low-traffic APIs, webhooks, side projects

The CanaKit Raspberry Pi 3 B+ Starter Kit at $99.99 gives you everything you need in one package. No hunting for compatible parts, no surprises.

My Stripe payment server has been running flawlessly for weeks, costing me pennies while saving $10-25/month in cloud hosting fees.

If you're running simple services that don't need enterprise-grade infrastructure, give the Pi a shot. Worst case, you're out $100 and learned a lot about Linux system administration. Best case, you save hundreds per year and gain complete control over your infrastructure.


Questions or running into issues? Drop a comment below or reach out on LinkedIn.

Affiliate Disclosure: The Amazon link above is an affiliate link. If you purchase through it, I earn a small commission at no extra cost to you. It helps support this blog!

Related Posts

Building with Angular + Firebase? Check out my Photography E-Commerce Platform that combines Firebase auth with Stripe payments and AWS S3 storage.

Self-hosting your projects? Learn how I host production apps on a Raspberry Pi with PM2, Nginx, and Tailscale.

About the Author: Ricardo Gil is a full-stack software engineer specializing in .NET/C#, Angular, and cloud platforms. Read more or subscribe for updates.

Want this kind of setup for your business?

I deploy private, self-hosted infrastructure on Proxmox: AI, automation and internal tools on hardware you own, documented and handed off. See the Private AI Stack β†’

Not sure what you need? Book a free discovery call.

πŸ“¬Weekly Newsletter

Get the best home lab & AI content

No spam. One email per week. Unsubscribe anytime.

Share this article