Creating a Raspberry Pi Server for Development

A Raspberry Pi](https://www.raspberrypi.org/) is an affordable computer capable of running various software and supporting diverse projects. This guide explains how to turn it into a home development server for deploying a full-stack JavaScript application accessible outside your network. This setup is excellent for a remote workspace or controlling development hardware.

Requirements for a Raspberry Pi Home Server

While focusing on the Raspberry Pi 3, this tutorial should be compatible with models back to the first generation. Feedback on older models or the Raspberry Pi Zero is welcome in the comments.

Beyond the Raspberry Pi, you’ll need:

  • Micro USB charger
  • Ethernet cable
  • MicroSD card (8GB minimum, up to 32GB recommended)

These are helpful for initial setup:

  • USB keyboard
  • HDMI cable and monitor

Raspberry Pi OS: Raspbian

Installing an OS on a Raspberry Pi is straightforward. Use your computer to install the boot image on a microSD card, insert it into the Pi, and boot.

Raspbian, a Linux distribution based on Debian 7.0 (Wheezy), is the official Raspberry Pi OS, optimized for its architecture. While other OS options exist, Raspbian’s simplicity makes it our choice.

This tutorial is updated for Raspbian version (or later):

1
2
Kernel version : #1 SMP Debian 4.9.110-3+deb9u4 (2018-08-21)
Kernel release : 4.9.0-8-amd64

To install Raspbian, visit the official download page and download the latest version’s zip file.

Insert the microSD card into your computer. Depending on your OS ( Linux, Mac OS, or Windows), follow the instructions on Raspberry Pi’s website.

Eject the SD card and insert it into the Raspberry Pi. Connect the Pi to your router with the Ethernet cable and plug in the Micro USB charger to boot it up.

For initial configuration:

  • Direct Connection:
    • Connect a USB keyboard and HDMI monitor to the Pi.
    • The Pi should recognize them automatically.
    • The first boot runs raspi-config automatically. Subsequent boots require running sudo raspi-config manually.
  • SSH Connection:

raspi-config guides you through the setup. Configure any options, but prioritize: expanding the filesystem for full SD card utilization, and changing the default user’s password for server security.

Raspi-config

Installing Nginx Web Server

Next, install the web server. Nginx is preferred for its low memory footprint and compatibility with Node.js (which we’ll set up later). While alternatives like Apache or lighttpd exist, we’ll use Nginx.

Before installation, update your system:

1
2
sudo apt-get update
sudo apt-get upgrade

Install Nginx using apt-get:

1
sudo apt-get install nginx

After installation, start the server:

1
sudo service nginx start

If you haven’t already, find your Pi’s local IP address using ifconfig. The eth0 section will show your ethernet adapter’s information, with the local IP address labeled inet addr.

Access your Pi’s default Nginx welcome message by entering its IP address in your browser.

Public Access: Port Forwarding

Skip this step if you don’t need external network access. Otherwise, let’s enable it.

Typically, devices within a home network are invisible externally. Only your router, using its external IP, is reachable. It manages incoming traffic, allowing responses to initiated connections but blocking unsolicited ones for security.

To connect to your Pi externally, use port forwarding. Configure your router to forward incoming traffic on specific ports to your Pi. Usually, HTTP uses port 80, SSH uses 22. Open these on your router for application access and secure server management.

Port forwarding.

Port forwarding configuration varies depending on your internet provider and router. Find the relevant options in your router’s admin page, often under “Forwarding,” “Port Forwarding,” or “Network Address Translation.”

Open one port for HTTP and another for SSH. Forward data sent to these external ports to your Pi: web traffic to port 80 (Nginx) and SSH traffic to port 22 (SSH server). Example configuration:

Port forwarding configuration table.
Port forwarding configuration if your Raspberry Pi's internal IP address is 192.168.1.16. All incoming traffic bound for ports 80 or 22 are forwarded to this internal address.

Find your router’s external IP by typing “what’s my ip address” into Google. Test port forwarding from outside your network: SSH with ssh pi@{external IP address}, HTTP by entering the external IP in your browser. Note: This allows anyone knowing your external IP to access your Pi on these ports.

For dynamic IPs, set up dynamic DNS via your router or Pi. While not covered here, resources are available BitPi.co has a good tutorial on the subject if needed.

Full-stack JavaScript Framework

While most web frameworks can run on Nginx, let’s go full-stack with JavaScript. Install Node.js and MongoDB.

Node.js is easily installed:

1
sudo apt-get install nodejs

Verify installation with node -v.

Install MongoDB:

1
sudo apt-get install mongodb

To prevent database corruption, shut down MongoDB before turning off your Pi:

1
sudo service mongodb stop

Deploying Your App

Develop locally and push changes to a BitBucket Git repository. Raspbian includes Git, allowing you to pull and run your code on the Pi.

Project Scaffolding

First, set up and push your application code. Among many methods, generator-angular-fullstack is great for scaffolding server and client code.

Install generator-angular-fullstack on your computer:

1
npm install -g generator-angular-fullstack

Create your application directory:

1
2
mkdir my-app
cd my-app

Scaffold the application:

1
yo angular-fullstack my-app

Repository Creation and Code Push

Create a BitBucket repository as described here and set up your local directory:

1
2
git init
git remote add origin git@bitbucket.org:USER/REPO.git

Commit and push your code:

1
2
3
git add .
git commit -m 'Initial commit'
git push -u origin master

The generator includes the grunt-build-control plugin for committing build code to a specific repository branch. Configure it for BitBucket in Gruntfile.js within your application’s root directory:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
buildcontrol: {
   options: {
      dir: 'dist',
      commit: true,
      push: true,
      connectCommits: false,
      message: 'Built %sourceName% from commit %sourceCommit% on branch %sourceBranch%'
   },
   bitbucket: {
      options: {
         remote: 'git@bitbucket.org:USER/REPO.git',
         branch: 'build'
      }
   }
},
// ...

Run:

1
grunt build

…to create the distribution folder, followed by:

1
grunt buildcontrol:bitbucket

…to commit and push the code to the build branch in your repository.

SSH Key Generation

With your code hosted, generate an SSH key for your Pi and add it to BitBucket for deployment. For detailed instructions, see BitBucket guide.

On your Pi’s terminal, generate the key pair:

1
ssh-keygen

Start the agent:

1
ssh-agent /bin/bash

Add the key:

1
ssh-add /home/pi/.ssh/id_rsa

Output the public key content:

1
cat /home/pi/.ssh/id_rsa.pub

…and copy-paste it into BitBucket.

In BitBucket, go to your profile, Manage account, SECURITY, SSH keys, and click Add key.

Repository Cloning

While there’s no strict convention, create a /var/www directory for your projects:

1
2
cd /var
sudo mkdir www

Avoid using sudo for file placement in the webroot by changing ownership to your Pi user and the group to www-data (used by Nginx):

1
2
sudo chown -R pi:www-data www
cd www

Clone your repository’s build branch and install dependencies:

1
2
3
git clone git@bitbucket.org:USER/REPO.git --branch build --single-branch
cd REPO
npm install --production

Once done, start your app in production mode:

1
export NODE_ENV=production; node server/app.js &

Check if it works by browsing to the Pi’s IP address.

Wish you had a dev server you could call your own? You can, with a #RaspberryPi.

Nginx Reverse Proxy Configuration

One last step: While Nginx listens for HTTP requests on port 80, your Node app uses a different port (e.g., 8080). Configure Nginx as a reverse proxy to forward requests to Node.

Nginx stores application configuration files in sites-available:

1
cd /etc/nginx/sites-available/

Copy and edit the default configuration:

1
2
sudo cp default my-app
sudo nano my-app

The final configuration should resemble this, with Nginx proxying to the Node.js server:

1
2
3
4
5
6
7
8
server {
   listen 80;
   root /var/www/my-app/;                  # identifies the location of the application you are configuring
   server_name my-app.dev;                 # identifies the hostname used by this application's traffic
   location / {
      proxy_pass http://localhost:8080/;   # configures the back-end destination for this traffic
   }
}

Enable this configuration with a symlink in sites-enabled, where Nginx finds active configurations:

1
sudo ln -s /etc/nginx/sites-available/my-app /etc/nginx/sites-enabled/my-app

Reload the service:

1
sudo service nginx reload

Your application can now receive traffic for the my-app.dev domain (configured with server_name my-app.dev). To access it externally, match traffic to this domain. While domain purchase is possible, the hosts file provides a simpler alternative.

On your workstation, edit the hosts file to map your router’s external IP to the my-app.dev hostname. This directs traffic for my-app.dev to your router with the correct hostname.

On Windows, edit c:\windows\system32\drivers\etc\hosts as administrator using Notepad. On Linux/Mac, use sudo nano /etc/hosts or sudo nano /private/etc/hosts respectively.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
##
# Host Database
#
# localhost is used to configure the loopback interface
# when the system is booting. Do not change this entry.
##
127.0.0.1       localhost
255.255.255.255 broadcasthost
::1             localhost

212.124.126.242 my-app.dev    # add your host name to the list

Next Steps

With everything set up, deploy multiple applications to your Pi. Install tools like forever or pm2 to manage your Node.js servers.

Remember, if anything goes wrong, simply wipe the SD card and start over!

Raspberry Pi development server in action.
Licensed under CC BY-NC-SA 4.0