Skip to content

Instantly share code, notes, and snippets.

@dko1905
Last active May 17, 2021 14:20
Show Gist options
  • Save dko1905/c46fce1b0767bfb87c1a5f54466df3c2 to your computer and use it in GitHub Desktop.
Save dko1905/c46fce1b0767bfb87c1a5f54466df3c2 to your computer and use it in GitHub Desktop.
Fast Pi

Fast Pi Setup

A fast raspberry pi setup. This guide is currently being written.

Steps

  1. Install Alpine Linux on Raspberry Pi guide.
  2. Configure sshd with mozilla config.
  3. Configure regular stuff.
  4. Install #needed-software.
  5. Configure #ramfs.
  6. Configure #www.

Needed software

List of software that you should install (possibly not complete):

  • nginx nginx-doc
  • git git-doc
  • musl-dev libc-dev g++
  • gcc gcc-doc make make-doc bmake bmake meson meson-doc samurai samurai-doc
$ apk add nginx ...

Ramfs

  1. Create the directories /var/tank/ram and /var/ram.
  2. Add ramfs to /etc/fstab:
tmpfs		/var/ram	tmpfs	rw,nodev,defaults,size=600M	0 0
  1. Create the file /etc/init.d/ramsyncd, and open it in vim. The contents of /etc/init.d/ramsyncd should be this:
#!/sbin/openrc-run

supervisor="supervise-daemon"
command=/usr/local/bin/ramsyncd
pidfile=/var/run/ramsyncd
name=$RC_SVCNAME

description="/var/ram sync daemon"

depend() {
	need localmount
	after bootmisc
	before nginx
}

start_pre() {
	rsync -rauL --delete /var/tank/ram/ /var/ram > /dev/null
}

stop_post() {
	rsync -rauL --delete /var/ram/ /var/tank/ram > /dev/null
}

Now enable and start ramsyncd:

$ rc-update add ramsyncd boot # Add service to start at boot
$ rc-service ramsyncd start # Start the service

The daemon ramsyncd will sync /var/tank/ram and /var/ram. The daemon syncs from /var/ram -> /var/tank/ram every minute and at shutdown. The daemon syncs from /var/tank/ram -> /var/ram on boot. :)

WWW

Start by creating /var/ram/www, then create a src folder and a folder with your domain (example.com). Your directoy tree should look something like this:

.
├── example.com
└── src

You can now clone the source of your website into the src folder.

/var/ram/www/src $ git clone ...

You can now compile the website source code and cp/symlink it to /var/ram/www/example.com.

Nginx

  • Delete /etc/nginx/conf.d & /etc/nginx/http.d.
  • Create /etc/nginx/snippets/ and write contents to them.

/etc/nginx/snippets/acmeroot.conf

location /.well-known/acme-challenge/ {
        root "/var/ram/www/acme";
}

/etc/nginx/snippets/secure-http.conf

add_header X-Frame-Options  "SAMEORIGIN" always;
add_header X-XSS-Protection "1; mode=block" always;
add_header Referrer-Policy  "no-referrer-when-downgrade" always;
add_header X-Content-Type-Options    "nosniff" always;
# Setup CSP
add_header Content-Security-Policy   "default-src 'self' data: 190405.xyz; frame-src 'self'" always;
add_header X-Content-Security=Policy "default-src 'self' data: 190405.xyz; frame-src 'self'" always;
add_header X-WebKit-CSP              "default-src 'self' data: 190405.xyz; frame-src 'self'" always;

/etc/nginx/snippets/secure-https.conf

add_header X-Frame-Options  "SAMEORIGIN" always;
add_header X-XSS-Protection "1; mode=block" always;
add_header Referrer-Policy  "no-referrer-when-downgrade" always;
add_header X-Content-Type-Options    "nosniff" always;
add_header Strict-Transport-Security "max-age=172800" always;
# Setup CSP
add_header Content-Security-Policy   "default-src 'self' data: 190405.xyz; frame-src 'self'" always;
add_header X-Content-Security=Policy "default-src 'self' data: 190405.xyz; frame-src 'self'" always;
add_header X-WebKit-CSP              "default-src 'self' data: 190405.xyz; frame-src 'self'" always;

/etc/nginx/snippets/default-cache.conf

etag    on;
expires 24h;

/etc/nginx/snippets/no-cache.conf

etag       off;
expires    off;
add_header Cache-Control 'no-store, no-cache, must-revalidate, proxy-revalidate, max-age=0';

/etc/nginx/nginx.conf

# /etc/nginx/nginx.conf
worker_processes auto;
user nginx;
pcre_jit on;
error_log /var/log/nginx/error.log warn;

events {
	worker_connections 1024;
}

http {
	include /etc/nginx/mime.types;
	default_type application/octet-stream;

	# ETC
	resolver 1.1.1.1 1.0.0.1;
	server_tokens off;
	client_max_body_size 1m;
	sendfile on;
	tcp_nopush on;
	gzip_vary on;

	# SSL
	ssl_protocols TLSv1.2 TLSv1.3;
	# to generate: openssl dhparam -out /etc/ssl/nginx/dh2048.pem 2048
	ssl_dhparam /etc/ssl/nginx/dh2048.pem;
	ssl_prefer_server_ciphers on;
	ssl_session_cache shared:SSL:2m;
	ssl_session_timeout 1h;
	ssl_session_tickets off;

	map $http_upgrade $connection_upgrade {
		default upgrade;
		'' close;
	}

	# Specifies the main log format.
	log_format main '[$time_local] $remote_addr - $host "$request" '
	                '$status $remote_user "$http_referer" "$http_user_agent"';
	access_log /var/log/nginx/access.log main;

	# 190405.xyz
	server {
		listen      80;
		server_name 190405.xyz;

		root        /var/ram/www/190405.xyz;
		autoindex   off;
		index       index.xhtml;
		include     /etc/nginx/snippets/secure-http.conf;
		include     /etc/nginx/snippets/acmeroot.conf;

		location / {
			try_files $uri $uri/ =404;
		}
	}

	# Default server
	server {
		listen      80 default_server;
		server_name _;

		root        /var/ram/www/default;
		autoindex   off;
		index       index.html;
		include     /etc/nginx/snippets/secure-http.conf;

		location / {
			try_files $uri $uri/ =404;
		}
	}
	# Git http server
	server {
		listen      80;
		server_name git.190405.xyz;

		root        /var/ram/www/default;
		autoindex   on;
		include     /etc/nginx/snippets/secure-http.conf;

		# default location
		location / {
			# redirect git to @git
			# redirect web to @web
			error_page 460 = @web;
			error_page 461 = @git;
			recursive_error_pages on;
			if ($http_user_agent ~* git\/.*) {
				return 461;
			}
			location / {
				return 460;
			}
		}
		# serve raw git files
		location @git {
			root /var/ram/www/git;
			include /etc/nginx/snippets/no-cache.conf;

			client_max_body_size 0;
			autoindex on;

			try_files $uri $uri/ =404;
		}
		# serve nicer view (if available)
		location @web {
			root /var/ram/www/git;
			include /etc/nginx/snippets/default-cache.conf;

			autoindex on;

			try_files $uri $uri/ =404;
		}
	}
}

Configuring git with ssh and http

Our goal is to have two git folders: one public and one private.
The public folder will be available using http, but the private will only be available using ssh.

Global things

Create the directories /var/ram/git, /var/ram/git/public and /var/ram/git/private.
We will use a script for our repository creation and some others for other things.
/var/ram/git/doas.sh

#!/bin/sh
set -e

doas -u git "$@"

/var/ram/git/add-repo.sh

#!/bin/sh
set -e

GREEN='\033[0;32m'
ORG='\033[0;34m'
NC='\033[0m'

type="$1" # Public or private ("public" or "private")
name="$2"
fullname="${name}.git"

# ask if this is what they want
printf "type: %s\nname: %s\nfullname: %s\n" "$type" "$name" "$fullname"
while true; do
	read -p "Do you wish to continue? " yn
	case "$yn" in
		[Yy]* ) break;;
		[Nn]* ) exit;;
        	* ) echo "Please anwer yes or no.";;
	esac
done

echo ""
cd "$type"
mkdir "${fullname}"
echo "Created ${fullname}"
cd "${fullname}"
git init --bare > /dev/null
echo "Created git repo"
mv hooks/post-update.sample hooks/post-update
echo "Configured hook"
git gc > /dev/null
git update-server-info > /dev/null
echo -e "Configured git repo\n"
echo -e "${GREEN}Done!${NC}"
echo -e "${ORG}Remember to run ./doas.sh ./update-ref.sh${NC}"

/var/ram/git/update-ref.sh

#!/bin/sh

[ "$1" = "clean" ] && find . -maxdepth 1 -iname "*.git" -exec unlink {} \; && exit 0;

for dir in `find ./public -maxdepth 1 -iname "*.git"`; do
        ln -svf "$dir" "$(basename "$dir")"
done

for dir in `find ./private -maxdepth 1 -iname "*.git"`; do
        ln -svf "$dir" "$(basename "$dir")"
done

The "real " repo will live inside the private or public folders, we will link them all to the root git folder, because we want to be able to clone them all from the home folder. Create the git user and chown the git folder.

# The password isn't imporatant, it will never be used.
$ adduser -h /var/ram/git git
$ chown -R git:git /var/ram/git

To make doas.sh work, you need to add this like to /etc/doas.conf:

permit nopass root

You can test if it works by running:

$ ./doas.sh whoami

It should return git.

Setup sshd

Copy your private keys from /root/.ssh/... to /var/ram/git/.ssh/ and set the correct permissions.

Setup acme.sh

Create a new user acme with the home /var/db/acme. wget acme.sh and install it:

# Inside /var/db/acme running as the acme user.
$ mkdir .acme.sh/
$ mkdir certs/
$ wget https://raw.githubusercontent.com/acmesh-official/acme.sh/master/acme.sh
$ ./acme.sh --install \
--config-home /var/db/acme/.acme.sh/ \
--cert-home /var/db/acme/certs/ \
--accountemail "[email protected]"
# The previus command might say "crontab: can't open 'acme': No such file or directory"
# but that's ok.
# You can now safely remove the acme.sh file.
$ rm -v acme.sh

Because I use nginx, I must allow it to reload to server. We can give it the permission to reload by adding this line to /etc/doas.conf:

permit nopass acme cmd /sbin/rc-service args nginx reload

The script writes to /var/ram/www/acme and therefore you need to chown that directory.

$ chown -R acme:acme /var/ram/www/acme/

To issue a certificate, run the command below:

$ ./.acme.sh/acme.sh --issue -d example.com --webroot /var/ram/www/acme --reloadcmd "doas /sbin/rc-service nginx reload"
@dko1905
Copy link
Author

dko1905 commented May 14, 2021

v0.1 published

@dko1905
Copy link
Author

dko1905 commented May 14, 2021

v0.2

@dko1905
Copy link
Author

dko1905 commented May 14, 2021

v0.3

@dko1905
Copy link
Author

dko1905 commented May 14, 2021

v0.4

@dko1905
Copy link
Author

dko1905 commented May 14, 2021

v0.5

@dko1905
Copy link
Author

dko1905 commented May 15, 2021

0.6

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment