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

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

Ricardo Gil
January 25, 2026
15 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.

    πŸ“¬Weekly Newsletter

    Get the best home lab & AI content

    No spam. One email per week. Unsubscribe anytime.

    Share this article