/raspberry-pi-setup

My complete Raspberry Pi setup :octocat:

Primary LanguagePython

          __  __          _____      _                        
         |  \/  |        / ____|    | |                       
  _____  | \  / |_   _  | (___   ___| |_ _   _ _ __    _____  
 |_____| | |\/| | | | |  \___ \ / _ \ __| | | | '_ \  |_____| 
         | |  | | |_| |  ____) |  __/ |_| |_| | |_) |         
  _____  |_|  |_|\__, | |_____/ \___|\__|\__,_| .__/ _____ _  
 |  __ \          __/ || |                    | |   |  __ (_) 
 | |__) |__ _ ___|___/ | |__   ___ _ __ _ __ _|_|_  | |__) |  
 |  _  // _` / __| '_ \| '_ \ / _ \ '__| '__| | | | |  ___/ | 
 | | \ \ (_| \__ \ |_) | |_) |  __/ |  | |  | |_| | | |   | | 
 |_|  \_\__,_|___/ .__/|_.__/ \___|_|  |_|   \__, | |_|   |_| 
                 | |                          __/ |           
                 |_|                         |___/            

My complete Raspberry Pi setup :octocat:

Table of contents 📖

Raspberry Pi 🍓

Raspberry Pi Documentation

Parts:

  • Raspberry Pi (motherboard)
  • Micro-SD
  • Charger
  • Case (optional)

Raspberry Pi OS 💿

Raspberry Pi Imager

Raspberry Pi Imager is the quick and easy way to install Raspberry Pi OS and other operating systems to a microSD card.

Configuration 🔧

Network - Static IP 📌

TCP/IP Documentation

You might want to set your RPi to a Static IP (e.g. 192.168.0.100) if you would like to port forward your RPi online. This could be done by either or both of the following:

  • Assign a static IP adress to RPi with a router, using some router settings
  • Request a static IP adress for the RPi with DHCPCD

Network - External IP 🌍

$ curl https://ipinfo.io/ip

External Storage 📁

External Storage Documentation

# /etc/fstab
UUID=XXXX-XXXX /mnt/exfat exfat defaults,auto,users,rw,nofail,umask=000 0 0

Remote Access (Samba) 📂

File and print services using SMB/CIFS protocol.

Samba Documentation

  • Shared access to mounted storage device
# /etc/samba/smb.conf
[share]
comment = Shared Exfat
path = /mnt/exfat
browseable = yes
writeable = yes
guest ok = yes
create mask = 0777
directory mask = 0777
$ sudo smbpasswd -a pi

Remote Access (SSH) 🔑

SSH or Secure Shell is a cryptographic network protocol, typical used for remote command-line, login, and remote command execution.

SSH Documentation

Fix Raspberry Pi SSH freezing issue

Solution 1: Open /etc/ssh/sshd_config, add ClientAliveInterval=60 and ClientAliveCountMax=3 and run sudo service sshd restart. Solution 2: Open /etc/ssh/sshd_config, add IPQoS cs0 cs0 or IPQoS 0x00 at the bottom and run sudo service sshd restart.

Remote Access (RDP) 💻

Remote Desktop Protocol is a proprietary protocol which provides a user with a graphical interface to connect to another computer over a network connection.

Remote Desktop Setup

Install Xrdp

$ sudo apt-get install xrdp

Connect to raspberry pi

Use a RDP or a VNC software, and enter your raspberry pi's local IP address.

Remote Access (Nginx) 🌍

Nginx is a web server that can also be used as a reverse proxy, load balancer, mail proxy and HTTP cache.

Nginx Documentation

Install Nginx

$ sudo apt install nginx

Nginx Configuration

$ sudo nano /etc/nginx/sites-available/default

# APPLICATION_NAME :: PORT - SUBDOMAIN
#
server {
  listen 443;
  server_name SUBDOMAIN.DOMAIN;

  location / {
    proxy_pass http://localhost:PORT;

    # If you have header issues add the following lines
    # proxy_set_header Host $http_host;
    # proxy_set_header X-Forwarded-Proto $scheme;
  }
}

$ sudo /etc/init.d/nginx reload (start/restart)

DNS setup

Host Type TTL Target
A 86400 {SERVER_IP}
www A 86400 {SERVER_IP}
{PROJECT} A 86400 {SERVER_IP}
...
Alt with wildcard domain name support
Host Type TTL Target
A 86400 {SERVER_IP}
* A 86400 {SERVER_IP}

Crontab 🕓

The editor for the cron jobs (time-based job scheduler).

Scheduling tasks with Cron

Let's Encrypt with Certbot :shipit:

A free, automated, and open certificate authority brought to you by the nonprofit ISRG.

Let's Encrypt

Install Certbot

Automatically enable HTTPS on your website with EFF's Certbot, deploying Let's Encrypt certificates.

Certbot

$ sudo apt install python3-certbot-nginx

Update certs

sudo certbot --authenticator webroot -w /var/www/html --installer nginx --cert-name example.com
$ sudo nano /etc/nginx/sites-available/default
$ sudo /etc/init.d/nginx reload (start/restart)

Delete cert

$ sudo certbot delete --cert-name example.com

Services

Docker 🐳

Docker is an open platform for developing, shipping, and running applications.

Docker

  • Portainer - Portainer simplifies container management in Docker by providing an UI

Postgres 🐘

PostgreSQL is a powerful, open source object-relational database system.

Postgres

  • Install Postgres sudo apt-get -y install postgresql
  • Create user sudo -u postgres createuser USERNAME --interactive --pwprompt
  • Create database sudo -u postgres createdb -O USERNAME DBNAME
  • Drop database sudo -u postgres dropdb DBNAME
  • PostgreSQL interactive terminal sudo -u postgres psql or psql postgres://USERNAME:PASSWORD@localhost/DBNAME
  • Allow remote connection
    • Add following to postgresql.conf:
      • listen_addresses = '*'
    • Add following to pg_hba.conf:
      • host all all 0.0.0.0/0 md5
      • host all all ::/0 md5
    • Restart postgresql sudo /etc/init.d/postgresql restart

Reset Database

db-dumps

pg_dump --format=c -h 192.168.0.100 -U USERNAME DATABASE | pg_restore --clean --no-owner -h localhost -d DATABASE

PG CLI

pgcli is a command line interface for Postgres with auto-completion and syntax highlighting.

Node 💠

Node.js is an open-source, cross-platform, back-end, JavaScript runtime environment that executes JavaScript code outside a web browser.

Applications 💻

Home Assistant 🏠

My Home Assistant Configuration

Open source home automation that puts local control and privacy first. Powered by a worldwide community of tinkerers and DIY enthusiasts. Perfect to run on a Raspberry Pi or a local server.

Home Assistant

  1. Install Home Assistant Docker Image
  2. Install Home Assistant Community Store (HACS)
  3. Configure HTTP Integration
# /home/pi/homeassistant/configuration.yaml

http:
  use_x_forwarded_for: true
  trusted_proxies:
    - 127.0.0.1
    - <your external ip>

Conbee II 🗣️

The universal Zigbee USB gateway unites Zigbee devices of many vendors with a cloud free solution, works with popular Home Automation Systems.

Conbee II Documentation

Home Assistant Integration

Nextcloud ☁️

The self-hosted productivity platform that keeps you in control. Share and collaborate on documents, images and videos. Nextcloud is a suite of client-server software for creating and using file hosting services.

Nextcloud

External Storage

  • Use bind mounts
    • E.g. volumes: - /mnt/exfat:/media/exfat
  • Enable "External storage support" in Apps
  • Add External Storage in Settings/Admin

Git :octocat:

Git Server :octocat:

Convenient for deploying applications to the raspberry pi using git

Git on the Server

/home/git
├── repos
│   └── pm-ui.git
└── www
    └── pm-ui

Setup bare repo

$ ssh git@DOMAIN
$ git init --bare repos/{PROJECT}.git
$ mkdir www/{PROJECT}

Add ssh keys

$ nano /home/git/.ssh/authorized_keys

ssh-rsa ABC123 user@domain.com

Add post-receive hook

Requires: pm2

$ cd repos/{PROJECT}.git && nano hooks/post-receive

#!/bin/bash
set -eu # exit script on errors
. $HOME/.nvm/nvm.sh

PROJECT="INSERT_PROJECT_NAME_HERE"
MAIN="INSERT_NODE_SCRIPT_PATH_HERE"
BRANCH="master"

WORK_TREE="/home/git/www/${PROJECT}"
GIT_DIR="/home/git/repos/${PROJECT}.git"

while read oldrev newrev ref
do
  echo "Ref $ref received."

  if [[ $ref = refs/heads/"$BRANCH" ]];
  then
    echo "Deploying ${BRANCH} branch..."

    echo "> git checkout..."
    git --work-tree="$WORK_TREE" --git-dir="$GIT_DIR" checkout -f
    cd "$WORK_TREE"

    echo "> npm install..."
    npm install

    # # If build wasn't done on github uncomment this
    # echo "> npm run build..."
    # npm run build

    # I use pm2 for process management of my Node applications
    echo "> pm2 start server"
    pm2 restart "${PROJECT}" || pm2 start "${MAIN}" --name "${PROJECT}"

    echo "> pm2 save"
    pm2 save

    echo "Deployment ${BRANCH} branch complete."

  else
    echo "No deployment done."
    echo "Only the ${BRANCH} branch may be deployed."
  fi
done

Don't forget to make hook executable

$ chmod +x hooks/post-receive

You can also run the hook manually

$ echo "oldrev newrev refs/heads/master" | repos/${PROJECT}.git/hooks/post-receive

Git Client :octocat:

Clone

$ git clone git@{DOMAIN}:repos/{PROJECT}.git

Add remote

$ git remote add server git@{DOMAIN}:repos/{PROJECT}.git

Init repo

$ cd {PROJECT}
# Fetch or create a .gitignore
$ curl -o .gitignore https://raw.githubusercontent.com/github/gitignore/master/Node.gitignore
$ npm init
$ npm install express --save
$ code server/index.js
// server/index.js
const express = require('express');
const path = require("path");
const app = express();

const PORT = <<INSERT_PORT_HERE>>;

// Serve static files
app.use(express.static(path.resolve(__dirname, "dist")));

app.get('/api', (req, res) => res.send('API Running!'))

app.listen(PORT, () => console.log(`App running on port ${PORT}!`))

Github Actions :octocat:

Action

name: Build (+Deploy)
on:
  push:
    branches:
      - master
  pull_request:
    branches:
      - master

jobs:
  build:
    name: Test and Build
    runs-on: ubuntu-latest

    strategy:
      matrix:
        node-version: [12.x]

    steps:
      - uses: actions/checkout@v2
      - name: Use Node.js ${{ matrix.node-version }}
        uses: actions/setup-node@v1
        with:
          node-version: ${{ matrix.node-version }}

      - name: Install and cache dependencies
        uses: bahmutov/npm-install@v1

      - name: Build
        run: npm run build

      - name: Test
        run: npm test

      - uses: actions/upload-artifact@v2
        with:
          name: BUILD_FOLDER
          path: BUILD_FOLDER
  deploy:
    needs: build

    name: Deploy to Server
    runs-on: ubuntu-latest
    if: ${{ github.event_name == 'push' }}

    steps:
      - uses: actions/checkout@v2
        with:
          fetch-depth: '0'
          ref: 'master'

      - uses: actions/download-artifact@v2
        with:
          name: BUILD_FOLDER
          path: BUILD_FOLDER

      - name: Install SSH key
        uses: shimataro/ssh-key-action@v2
        with:
          key: ${{ secrets.SSH_PRIVATE_KEY }}
          name: id_rsa # optional
          known_hosts: ${{ secrets.KNOWN_HOSTS }}

      - name: Git Push
        run: |
          git remote add server git@YOUR_DOMAIN:YOUR_GIT_REPO_PATH
          git config --global user.email "actions@github.com"
          git config --global user.name "Github Actions"
          git add build -f
          git commit -m "Build files"
          git push -u server master -f

Secrets

  • SSH_PRIVATE_KEY: -----BEGIN RSA PRIVATE KEY----- ...
  • KNOWN_HOSTS: YOUR_DOMAIN,EXTERNAL_IP sha XXXXXX

Recovery ♻️

TOC Generate

The End 🎉