From Spare Hardware to Production Server: Why We're Obsessed with Self-Hosting on Raspberry Pi
The Unexpected Server in Your Drawer
There's something deeply satisfying about running a production website from hardware that cost less than a fancy coffee machine. While cloud platforms like Vercel handle the heavy lifting for most projects, there are legitimate reasons to consider self-hosting on a Raspberry Pi—and they're more compelling than pure nostalgia.
The real-world scenario: you've got a Node.js framework like Astro, Svelte Kit, or React, and it includes dependencies that serverless platforms don't play nicely with. Maybe it's an unmaintained i18n library that works flawlessly but can't be bundled statically. Maybe you need fine-grained control over runtime behavior. Whatever the reason, your Pi suddenly becomes a viable alternative to expensive cloud infrastructure.
Step 1: Network Routing—Your Gateway to the Internet
Before your Pi can talk to the world, you need to configure port forwarding on your router. This is the bridge between your public IP address and the little device humming quietly on your shelf.
Next, grab Caddy—a modern reverse proxy that's leagues simpler than older alternatives. Add a configuration that looks something like this:
yoursite.com {
root * /home/username/projects/yoursite
file_server
reverse_proxy localhost:4321
}
The port number depends on your framework: Astro defaults to 4321, Svelte Kit uses 5173, and Node.js apps often run on 3000. Reload your Caddy config, and you're halfway there.
Step 2: Point Your Domain at Your Pi
Domain registrars like NameOcean make this straightforward. Create a simple DNS A record:
A Record: yoursite.com → your.public.ip.address
That's it. Your router's port forwarding handles the rest. Traffic heading to your domain gets redirected to your Pi automatically.
Step 3: Build Once, Run Forever
Build your project with the standard command:
npm run build
This generates a dist folder containing your compiled application and an entry point (typically entry.cjs or entry.mjs).
Here's where PM2 enters the picture—it's a process manager that keeps your Node.js app running indefinitely:
npm install -g pm2
cd dist/
pm2 start entry.mjs
Your site is now live. No console keeping it alive, no dependency on a terminal window.
Step 4: Automate Deployments with GitHub Actions
Self-hosting only works if you can update your code without SSH-ing into your Pi every time. This is where GitHub Actions transforms the experience from tedious to seamless.
Create .github/workflows/deploy.yml in your repository:
name: Deploy to Raspberry Pi
on: [push]
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- name: Deploy via SSH
uses: appleboy/ssh-action@v1
with:
host: ${{ secrets.PI_HOST }}
username: ${{ secrets.PI_USER }}
password: ${{ secrets.PI_PASSWORD }}
script: |
~/bin/deploy.sh
Add your Pi's IP address and credentials to your repository secrets. Then create a deployment script that handles everything:
#!/usr/bin/env bash
set -euo pipefail
BASE_DIR="$HOME/projects"
PORTS=(4321 4322)
PORT_INDEX=0
echo "Pulling latest code..."
for dir in "$BASE_DIR"/*/ ; do
if [[ -d "$dir/.git" ]]; then
(cd "$dir" && git pull)
fi
done
echo "Building projects..."
for dir in "$BASE_DIR"/*/ ; do
if [[ -f "$dir/package.json" ]]; then
CURRENT_PORT=${PORTS[$PORT_INDEX]}
(
cd "$dir"
npm run build -- --port "$CURRENT_PORT"
)
PORT_INDEX=$(( (PORT_INDEX + 1) % PORT_COUNT ))
fi
done
echo "Restarting services..."
pm2 restart all
Now every git push triggers your Pi to pull the latest code, rebuild, and restart—all automatically.
The Honest Calculus
Self-hosting on a Pi isn't for everyone. You lose the redundancy and global CDN benefits of cloud platforms. Bandwidth is limited. Your internet going down takes your site with it. But if you're comfortable trading convenience for control, cost savings, and the satisfaction of owning your entire stack, it's genuinely viable.
Plus, it's an incredible learning experience. You'll understand DNS, reverse proxies, process management, and CI/CD in ways that clicking buttons on a cloud dashboard never teaches you.
Your spare Raspberry Pi isn't just a nostalgic toy. It's a legitimate piece of infrastructure—and proof that you don't always need enterprise solutions for production workloads.