This is a work in progres - Check settings and security afterwards!
Raspberry Pi inital setup
Setup OS - Raspbian
1. Download latest Raspbian: www.raspberrypi.org/downloads/
2. Get Win32Diskimager to load an .img to your sd card: Win32DiskImager
a. edit /boot/cmdline.txt add rootdelay=5 (allows for usb drives to be found)
3. Boot up pi, run sudo raspi-config
a. expand_rootfs
b. change pi password
c. change locale - en_US.UTF-8
d. change timezone
e. enable ssh
f. set hostname (e.g. mypiserver)
g. (opt) memory_split - 64 (pi2 has enough cpu/ram)
h. (opt) overclock - mild
4. run ifconfig to get mac address; set router to use a static ip for mac address
5. sudo reboot, go headless
6. ssh in using putty, login as pi
7. add user: sudo useradd -m -G adm,dialout,cdrom,sudo,audio,video,plugdev,games,users,netdev,input USERNAME
8. reboot and login with new user, then delete pi user
a. sudo deluser --remove-all-files pi
9. update os: sudo apt-get update ; sudo apt-get upgrade
USB Storage
1. Plug in usb drive, check fdisk -l
a. use sudo parted to format:
i. select /dev/sda ; mklabel gpt ; mkpart primary 0GB 100%
ii. (opt) startx, then install/use gparted to do this
b. mkfs.ext4 /dev/sda1, check fdkisk -l again
c. Make a dir to mount usb to: sudo mkdir /data ; sudo mount /dev/sda1 /data
i. permissions: sudo chgrp -R users /data ; sudo chmod -R g+w /data
d. Auto-mount the USB drive
i. run sudo blkid /dev/sda1 and get the UUID
ii. edit fstab; sudo nano /etc/fstab
iii. add: UUID=xxxx-xxxx-xxxx-xxxx-xxxx [tab] /data [tab] ext4 [tab] defaults,noatime,x-systemd.automount [tab] 0 [tab] 2
2. If upgrading to a new drive, plug in new drive and start Pi, find device with sudo fdisk -l
a. Use sudo parted to format and then set file system, similar to steps 1.a-b, you can test similar to step 1.c also.
b. Install dd_rescue and clone drive: sudo dd_rescue -p /dev/sdb1 /dev/sda1
c. After clone finishes, reset UUID: sudo tune2fs /dev/sda1 -U random
d. Use sudo blkid to get the new UUID
e. Edit /etc/fstab and replace UUID with new one, check that it mounts with sudo mount -a
f. If df -h doesn't report correct values after a reboot, fix the filesystem:
i. run sudo e2fsck -f /dev/sda1
ii. then run sudo resize2fs /dev/sda1 292500M
iii. reboot and check df -h
3. reboot, check df -h for usb drive mounted to /data
Initial Security - making ssh keys
1. use PuTTYgen to generate public/private keys
2. use WinSCP to copy the public key to the Pi home directory
3. in /home/USERNAME sudo mkdir .ssh ; sudo mv pubkey.pub .ssh/authorized_keys
a. permissions: sudo chown -R USERNAME:USERNAME .ssh
b. sudo chmod 700 .ssh
c. sudo chmod 600 .ssh/authorized_keys
4. try PuTTY w/ ssh and authorization using the private key
5. if above works, turn off ssh password authentication and root login ability
a. sudo nano /etc/ssh/sshd_config
i. PasswordAuthentication no
ii. PermitRootLogin no
b. sudo service ssh restart
Create a Firewall
1. sudo nano /etc/iptables.firewall.rules
2. paste in rules LIST RULES
3. activate ; sudo iptables-restore < /etc/iptables.firewall.rules
4. check sudo iptables -L
5. set to startup
a. sudo nano /etc/network/if-pre-up.d/firewall
#!/bin/sh
/sbin/iptables-restore < /etc/iptables.firewall.rules
b. sudo chmod +x /etc/network/if-pre-up.d/firewall
6. install Fail2Ban, sudo apt-get install fail2ban
7. More additions will be added below
Software Installation
Nginx
-These steps assumes you have a dd-wrt router, a non-static ip, and don't have a domain:
-Dynamic DNS, before continuing, think about website name:
1. Install software packages
a. sudo apt-get install nginx php8.3-fpm php8.3-curl php8.3-gd php8.3-cli php8.3-mysql php8.3-apcu php8.3-gmp php8.3-bcmath php8.3-imagick php8.3-zip php8.3-xml php8.3-mbstring php8.3-intl php8.3-bz2 mysql-server
b. assign mysql root password
2. edit config, sudo nano /etc/nginx/nginx.conf
a. Set user, worker_processes, uncomment server_tokens off, add gzip settings, set timeouts
3. edit default parameters, sudo nano /etc/nginx/fastcgi_params
4. PHP - check listen.owner and listen.group are enabled, sudo nano /etc/php/8.3/fpm/pool.d/www.conf
a. make sure env[PATH] and env[HOSTNAME] are uncommented
5. Secure MySQL, sudo mysql_secure_installation (later we'll add a database & user for Nextcloud)
6. (opt) edit your pc's hosts file to map pi's ip to a 'name' eg. piwebsite.com.local
7. make 2 directories, sudo mkdir -p /data/mysite.com/www ; sudo mkdir -p /data/mysite.com/logs
8. make a sample index file, sudo nano /data/mysite.com/www/index.html ; save it
9. permissions, sudo chown -R www-data:www-data /data/mysite.com ; sudo chmod g+w /data/mysite.com/logs
10. make a copy of default, cd /etc/nginx/sites-available ; sudo cp default mysite.com
11. make a symlink from the sites-available to sites-enabled:
sudo ln -s /etc/nginx/sites-available/mysite.com /etc/nginx/sites-enabled/mysite.com
12. remove default from enabled, sudo rm /etc/nginx/sites-enabled/default
13. edit your site, sudo nano /etc/nginx/sites-available/mysite.com
a. root /data/mysite.com/www;
index index.html index.htm index.php;
server_name mysite.com.local mysite.com;
b. add logging: error_log /data/mysite.com/logs/error.log error;
access_log /data/mysite.com/logs/access.log;
14. restart nginx, sudo /etc/init.d/nginx reload
15. set logs to rotate by adding /data/mysite.com/logs/*.log to /etc/logrotate.d/nginx
16. check that http://mysite.com.local loads up the test,
if not change nginx user from www-data to USERNAME in /etc/nginx/nginx.conf
check errors, tail /data/mysite.com/logs/error.log ; tail /var/log/nginx/error.log
17. Add PHP settings; sudo nano /etc/nginx/sites-available/mysite.com
location ~ [^/].php(/|$) {
fastcgi_split_path_info ^(.+?.php)(/.*)$;
fastcgi_pass unix:/var/run/php8.3-fpm.sock;
fastcgi_index index.php;
include fastcgi.conf;
include fastcgi_params;}
18. make a test index.php file, sudo nano /data/mysite/www/index.php, add <?php phpinfo(); ?>
19. Add APCu settings: sudo nano /etc/php/8.3/mods-available/apcu.ini
apc.enabled=1
apc.shm_size=32M
apc.ttl=7200
apc.enable_cli=1
20. restart both php & nginx:
sudo /etc/init.d/php8.3-fpm restart ; sudo /etc/init.d/nginx restart
21. check http://mysite.com.local/index.php for php info, if good remove index.php
SSL Certs and HTTPS
1. For this part use a self-signed cert or get one from the various cert vendors
a. make a ssl directory, sudo mkdir /etc/nginx/ssl ; cd /etc/nginx/ssl
b. Self signed - sudo openssl req $@ -new -newkey rsa:2048 -sha256 -x509 -days 730 -nodes -out /etc/nginx/ssl/cert.pem -keyout /etc/nginx/ssl/cert.key
1. Have mysite.com as O and CN (add cert to trusted ca locally for self-signed)
2. permissions: sudo chmod 600 /etc/nginx/ssl/cert.pem ; sudo chmod 600 /etc/nginx/ssl/cert.key
c. Purchased SSL - sudo openssl req -new -newkey rsa:2048 -nodes -keyout mysite.com.key -out mysite.com.csr
1. fill in all fields as required.
2. Go get/renew SSL cert, provide CSR data
3. Validate yourself to the SSL authority, usually via email
4. Get zip file with SSL documents: cat mysite.crt mysite.ca-bundle >> cert_chain.crt
5. upload cert_chain.crt to /etc/nginx/ssl
2. add https to mysite.com file (read both pesmeester or techjawab), sudo nano /etc/nginx/sites-available/mysite.com
server {
listen 443 ssl;
server_name mysite.com;
#depending on self-signed or purchased cert:
#ssl_certificate /etc/nginx/ssl/cert.pem;
#ssl_certificate_key /etc/nginx/ssl/cert.key;
ssl_certificate /etc/nginx/ssl/cert_chain.crt;
ssl_certificate_key /etc/nginx/mysite.net.key;
3. restart both php & nginx, sudo /etc/init.d/php8.3-fpm restart ; sudo /etc/init.d/nginx restart
4. check https://www.mysite.com.local/index.html to see if https working
MySQL
1. login with passwd used during mysql install, think of a user & dbname
a. mysql -u root -p
b. CREATE DATABASE IF NOT EXISTS nextclouddb;
c. CREATE USER 'username'@'localhost' IDENTIFIED BY 'password';
d. GRANT ALL PRIVILEGES ON nextclouddb.* TO 'username'@'localhost' IDENTIFIED BY 'password';
e. quit
2. "old notes"-check if any changes needed in /etc/php/8.3/fpm/conf.d/mysql.ini
3. if needed, reference: Nextcloud Documentation
phpMyAdmin
1. sudo apt-get install phpmyadmin, Yes to db-config, enter MySQL credentials
2. edit mysite.com, sudo nano /etc/nginx/sites-available/mysite.com
a. Add phpMyAdmin block
b. Add - allow (ip address you want to admin from);
c. Add - deny all;
3. restart php, sudo service php8.3-fpm restart
4. check that it is working, https://www.mysite.com/phpmyadmin
Nextcloud
1. sudo nano /etc/php/8.3/fpm/php.ini
1. sizes, upload_max_filesize = 1000M ; post_max_size = 1000M ; memory_limit 1024M
2. Edit sudo nano /etc/dphys-swapfile for CONF_SWAPSIZE=512
3. Edit /etc/php/8.3/cli/php.ini to add intl.default_locale = en_US.UTF-8
4. Restart both php & nginx
sudo /etc/init.d/php8.3-fpm restart ; sudo /etc/init.d/nginx restart
5. double check your site settings ; sudo nano /etc/nginx/sites-available/mysite.com
6. Install Nextcloud
a. sudo mkdir -p /data/mysite.com/www/nextcloud
b. cd /data/mysite.com/www
c. check the latest version at Nextcloud download page
d. sudo tar xvf nextcloud-25.0.2.tar.bz2
e. sudo chown -R www-data:www-data /data/mysite.com/www
f. rm -rf nextcloud-25.0.2.tar.bz2
7. Try out site: https://www.mysite.com/nextcloud
a. pick admin name/password
8. Edit config.php, sudo nano /data/mysite.com/www/nextcloud/config/config.php
may have to change nextcloud to use mysql (or go through web gui)
$CONFIG = array (
'instanceid' => 'xxxxxxxxxxxx',
'passwordsalt' => 'xxxxxxxxxxxxxxxxxxxxxxxxx',
'secret' => 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx',
'serverid' => 'yourserverid',
'trusted_domains' =>
array (
0 => 'localhost', *local address here*,
1 => 'mysite.com', *remote address here*,
2 => 'mysite.com.local',
...
'memcache.local' => '\OC\Memcache\APCu',
9. Edit mysite.com; sudo nano /etc/nginx/sites-available/mysite.com
a. Refer to Nextloud Nginx Config settings
b. Add redirects for nextcloud carddav / caldav
rewrite ^/.well-known/carddav /nextcloud/remote.php/carddav/ redirect;
rewrite ^/.well-known/caldav /nextcloud/remote.php/caldav/ redirect;
10. If the Web Updater is not working, refer to Nextcloud Manual Upgrade
11. If the instance is missing indexes
sudo -u www-data php8.3 /data/mysite.com/www/nextcloud/occ db:add-missing-indices
12. setup cron job: sudo crontab -e -u www-data
sample: */10 * * * * php8.3 -f /data/mysite.com/www/nextcloud/cron.php --define apc.enable_cli=1
OpenVPN
1. install openvpn ; sudo apt-get install openvpn openssl easy-rsa
2. change to root & make a copy of easy-rsa, and edit it
a. sudo -s
b. cp -r /usr/share/easy-rsa /etc/openvpn/easy-rsa
c. in /etc/openvpn/easy-rsa nano vars
i. change: export EASY_RSA=/etc/openvpn/easy-rsa & export KEY_SIZE=2048
ii. set the export KEY values at the end
3. build server & client certs & keys
a. cd /etc/openvpn/easy-rsa
b. source ./vars
c. ./clean-all
d. ./build-ca (builds the Cert Authority, answer most fields, use . for blank)
e. ./build-key-server ServerName (builds keys for server, commonName must match Server_Name)
f. ./build-key-pass UserName (builds keys for clients, can do by-user or by-clientdevice, enter PEM password)
g. in /etc/openvpn/easy-rsa/keys run:
openssl rsa -in commonName.key -des3 -out commonName.3des.key (enter pass 3x)
h. finish encryption, cd .., ./build-dh (may take awhile)
4. generate HMAC code for DoS protection, openvpn --genkey --secret keys/ta.key
5. configure OpenVPN server (change port if you want to), nano /etc/openvpn/server.conf From Here
6. set your pi to forward traffic, sudo nano /etc/sysctl.conf
a. uncomment command to enable packet forwarding for IPV4: net.ipv4.ip_forward=1
b. reload, sysctl -p
7. sudo reboot
8. make client keys in /etc/openvpn/easy-rsa/keys
a. Make a script for this MakeOVPN.sh
b. Make a Default.txt
9. copy .ovpn file to client
10. remove .ovpn from the pi server, securely store: USER.key, USER.3des.key
11. port forward the port used in /etc/openvpn/server.conf to port 1194 to the raspberry pi
12. After firewall set up, test remote access from a client
put .ovpn file in \OpenVPN\config folder, or import on mobile client
Firewall
Checking Security
Qualys SSL Labs
Hardening
1. cd /etc/nginx
2. sudo nano /etc/nginx/nginx.conf
#disable ssl v3
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
3. cd ssl do 4096 only if you have a day to spare, else 2048
sudo openssl dhparam -out dh4096.pem 4096
4. In /etc/nginx run; sudo nano perfect-forward-secrecy.conf
ssl_protocols TLSv1.2 TLSv1.3;
ssl_prefer_server_ciphers on;
ssl_ciphers generate from Mozilla
ssl_dhparam dh4096.pem; or dh2048.pem
add_header Strict-Transport-Security "max-age=31536000; includeSubdomains;";
5. sudo nano /etc/nginx/nginx.conf
include /etc/nginx/perfect-forward-secrecy.conf;
Extras
| TABLE One |
| Data 1 |
Data 2 |
| Data 3 |
Data 4 |
| Data 5 |
Data 6 |