How to compile the ngx_pagespeed (Nginx Pagespeed) module for ARM architecture on the Raspberry Pi 4, or any other aarch64 devices, running Ubuntu Server 20.04

Before you read:

To skip this tutorial and download a precompiled version of Pagespeed for Nginx-1.21.6 Mainline, you can check out the nerd-tech github link here: https://github.com/nerd-tech/Pagespeed-nginx-RaspberryPi/releases/download/pagespeed/v1.21.6.ngx_pagespeed.so.for.Nginx-v1.21.6-Mainline.On.Ubuntu-20.04-aarch64.RaspberryPi3+4.zip For this module to be compatible, you must be running Nginx Mainline v1.21.6 on Ubuntu Server 20.04 for the Raspberry Pi 3 or Raspberry Pi 4. Check the github page for more compatibility info on this precompiled Pagespeed module for the Raspberry Pi.

Preface:

If you are using a Raspberry Pi as a LEMP (Linux, Nginx, MariaDB, PHP) server to host your website, you may want to consider speeding up your site on the server level by using the pagespeed module for Nginx. In this tutorial, we are going to learn how to compile (build) and install google’s ngx_pagespeed module for the Nginx Mainline Version 1.21.6, on a Raspberry Pi 3, Raspberry Pi 4, or any 64 bit ARM (aarch64) Device.

Natively, the ngx_pagespeed module does not support ARM device, nor do they have ARM support in their development roadmap. This poses a problem for users running a web server on aarch64 devices such as the Raspberry Pi 3 and above. This is mostly due to the fact that the PSOL binaries required to compile the pagespeed module are not 64-bit ARM or armv7l compatable. Fortunately, a developer by the name of Mogwai (@gusco) on gitlab, has solved this issue by patching the PSOL Binaries to make them compatible with aarch64/armv7l operating systems and their respective devices. This in turn, makes compiling the Nginx pagespeed module now possible for ARM devices.

As a reference note, This tutorial was created by merging/modifying three different tutorials and sets of instructions into one clean ARM versioned tutorial. You can find the original sources/tutorials/content on Linuxbabe’s page, on the Mogwai Gitlab page and on the official google pagespeed documentation page. Keep in mind, this has only been tested by me on Ubuntu Server (64-bit) 20.04 for the Raspberry Pi 4. However, it should also work on any 64 bit ARM device running Ubuntu 20.04, or any 64-bit version of Rasperry Pi OS. So, without further ado, lets begin:

Before you begin: You should do this on a machine (or seperate SD card) that IS NOT your real production web server or LEMP server! This will prevent code litter scattered throughout your server. Just be sure to use the same OS, Same Architecture, and Same Nginx version.

Step 1) Install the Nginx Mainline repository and corresponding signing keys

sudo nano /etc/apt/apt/sources.list.d/Nginx.list

Then copy and paste the following text into the file.

# Nginx Official Repositories for Ubuntu 20.04 Focal

# Official Nginx Stable Repository for Ubuntu 20.04 Raspi
# Stable Nginx and Nginx source repositories
#deb [arch=arm64] https://nginx.org/packages/ubuntu focal nginx
#deb-src [arch=arm64] https://nginx.org/packages/ubuntu focal nginx

# Official Nginx Mainline Repository for Ubuntu 20.04 Raspi
deb [arch=arm64] https://nginx.org/packages/mainline/ubuntu focal nginx
deb-src [arch=arm64] https://nginx.org/packages/mainline/ubuntu focal nginx

Then update or add the Official Nginx Signing Key to your GPG Keyring.

cd ~/ && curl -O https://nginx.org/keys/nginx_signing.key && sudo apt-key add ./nginx_signing.key

Then type:

apt-key list

and you should see the following text appear.

pub   rsa2048 2011-08-19 [SC] [expires: 2024-06-14]
      573B FD6B 3D8F BC64 1079  A6AB ABF5 BD82 7BD9 BF62
uid           [ unknown] nginx signing key <signing-key@nginx.com>

/etc/apt/trusted.gpg.d/ubuntu-keyring-2012-archive.gpg

Be sure the fingerprints (573B FD6B 3D8F BC64 1079 A6AB ABF5 BD82 7BD9 BF62) match. Then proceed to update, upgrade, and finally install nginx.

sudo apt update && sudo apt upgrade && sudo apt install nginx

Once installed you can check and be sure your version of nginx is 1.21.6 with nginx -v. Then proceed to the next step, which is taken almost directly from linuxbabe.com.

STEP 2) Download nginx source package

Modify this line by changing “yourusername” to your real Ubuntu login user name. Then copy the rest of the line and paste it in your linux terminal.

sudo chown yourusername:yourusername -R /usr/local/src/ && sudod mkdir -p /usr/local/src/nginx && cd /usr/local/src/nginx/ && sudo apt install dpkg-dev && sudo apt source nginx && ls

The final “ls” command should show the following output:

nginx-1.21.6
nginx_1.21.6-1~focal.debian.tar.xz
nginx_1.21.6-1~focal.dsc
nginx_1.21.6.orig.tar.gz

STEP 3) Download the Pagespeed source package

Here is where we do something different for ARM devices. The PSOL (pagespeed optimization Libraries) provided by google are not compatable with ARM devices. Therefore, we are going to use a patched version of the PSOL. Paste this entire one liner to clone the pagespeed module from github, convert it to the stable branch, and then download and extract the aarch64 patched version of the PSOL into the proper directory.

cd /usr/local/src && git clone https://github.com/apache/incubator-pagespeed-ngx.git && cd incubator-pagespeed-ngx/ && git checkout latest-stable && wget https://gitlab.com/gusco/ngx_pagespeed_arm/-/raw/master/psol-1.15.0.0-aarch64.tar.gz && tar xvf psol-1.15.0.0-aarch64.tar.gz && sed -i 's/x86_64/aarch64/' config && sed -i 's/x64/aarch64/' config && sed -i 's/-luuid/-l:libuuid.so.1/' config

STEP 4) Configure the Pagespeed module.

CD into the Nginx directory and install the build dependancies.

cd /usr/local/src/nginx/nginx-1.21.6 && sudo apt build-dep nginx && sudo apt install uuid-dev

Finally, we need to configure the environment with the exact same arguments that are already in your currently installed Nginx. To do that, you have to first check your nginx arguments with the following command:

nginx -V

Should return:

configure arguments: --prefix=/etc/nginx --sbin-path=/usr/sbin/nginx --modules-path=/usr/lib/nginx/modules --conf-path=/etc/nginx/nginx.conf --error-log-path=/var/log/nginx/error.log --http-log-path=/var/log/nginx/access.log --pid-path=/var/run/nginx.pid --lock-path=/var/run/nginx.lock --http-client-body-temp-path=/var/cache/nginx/client_temp --http-proxy-temp-path=/var/cache/nginx/proxy_temp --http-fastcgi-temp-path=/var/cache/nginx/fastcgi_temp --http-uwsgi-temp-path=/var/cache/nginx/uwsgi_temp --http-scgi-temp-path=/var/cache/nginx/scgi_temp --user=nginx --group=nginx --with-compat --with-file-aio --with-threads --with-http_addition_module --with-http_auth_request_module --with-http_dav_module --with-http_flv_module --with-http_gunzip_module --with-http_gzip_static_module --with-http_mp4_module --with-http_random_index_module --with-http_realip_module --with-http_secure_link_module --with-http_slice_module --with-http_ssl_module --with-http_stub_status_module --with-http_sub_module --with-http_v2_module --with-mail --with-mail_ssl_module --with-stream --with-stream_realip_module --with-stream_ssl_module --with-stream_ssl_preread_module --with-cc-opt='-g -O2 -fdebug-prefix-map=/data/builder/debuild/nginx-1.21.6/debian/debuild-base/nginx-1.21.6=. -fstack-protector-strong -Wformat -Werror=format-security -Wp,-D_FORTIFY_SOURCE=2 -fPIC' --with-ld-opt='-Wl,-Bsymbolic-functions -Wl,-z,relro -Wl,-z,now -Wl,--as-needed -pie'

If the “--with-compat” and “--with-cc-opt='-DNGX_HTTP_HEADERS'” arguments are not in there, then you must be sure to them to the next command or your module won’t be compatable with your Nginx. If “--with-compat” is in the above set of arguments, then just continue to copy and paste the above arguments in the next command along with “--with-cc-opt='-DNGX_HTTP_HEADERS'“. Either way, the arguments”--with-compat” and “--with-cc-opt='-DNGX_HTTP_HEADERS'” MUST be in the next command. Lastly, since we are compiling pagespeed as a dynamic argument, we must also include “--add-dynamic-module=/usr/local/src/incubator-pagespeed-ngx” argument. To summarize, the new arguments look like this:

--add-dynamic-module=/usr/local/src/incubator-pagespeed-ngx --with-compat --with-cc-opt='-DNGX_HTTP_HEADERS'

RUNNING MY FINAL ./CONFIGURE COMMAND LOOKS LIKE THIS (adjust according your output of the nginx -V command):

./configure --add-dynamic-module=/usr/local/src/incubator-pagespeed-ngx --with-compat --with-cc-opt='-DNGX_HTTP_HEADERS'

So in my case, since I am compiling for the latest Mainline version of Nginx v1.21.6, my entire configure command, including arguments (with the NEW Additional Arguments first) would be as follows:

./configure --add-dynamic-module=/usr/local/src/incubator-pagespeed-ngx --with-cc-opt='-DNGX_HTTP_HEADERS' --with-compat --prefix=/etc/nginx --sbin-path=/usr/sbin/nginx --modules-path=/usr/lib/nginx/modules --conf-path=/etc/nginx/nginx.conf --error-log-path=/var/log/nginx/error.log --http-log-path=/var/log/nginx/access.log --pid-path=/var/run/nginx.pid --lock-path=/var/run/nginx.lock --http-client-body-temp-path=/var/cache/nginx/client_temp --http-proxy-temp-path=/var/cache/nginx/proxy_temp --http-fastcgi-temp-path=/var/cache/nginx/fastcgi_temp --http-uwsgi-temp-path=/var/cache/nginx/uwsgi_temp --http-scgi-temp-path=/var/cache/nginx/scgi_temp --user=nginx --group=nginx --with-file-aio --with-threads --with-http_addition_module --with-http_auth_request_module --with-http_dav_module --with-http_flv_module --with-http_gunzip_module --with-http_gzip_static_module --with-http_mp4_module --with-http_random_index_module --with-http_realip_module --with-http_secure_link_module --with-http_slice_module --with-http_ssl_module --with-http_stub_status_module --with-http_sub_module --with-http_v2_module --with-mail --with-mail_ssl_module --with-stream --with-stream_realip_module --with-stream_ssl_module --with-stream_ssl_preread_module --with-cc-opt='-g -O2 -fdebug-prefix-map=/data/builder/debuild/nginx-1.21.6/debian/debuild-base/nginx-1.21.6=. -fstack-protector-strong -Wformat -Werror=format-security -Wp,-D_FORTIFY_SOURCE=2 -fPIC' --with-ld-opt='-Wl,-Bsymbolic-functions -Wl,-z,relro -Wl,-z,now -Wl,--as-needed -pie'

So to complete this step, just copy and paste:

./configure --add-dynamic-module=/usr/local/src/incubator-pagespeed-ngx --with-cc-opt='-DNGX_HTTP_HEADERS' --with-compat

before the rest of the output of nginx -V and then hit enter to start configuring! Don’t forget to check for an already existing --with-compat argument before you paste the above line.

STEP 5) Make the Pagecache module!

cd /usr/local/src/nginx/nginx-1.21.6/ && make modules

Then copy your newly created module to the Nginx modules directory.

cd objs && sudo cp ngx_pagespeed.so /etc/nginx/modules/

Step 5b) – (Recommended) – Copy the pagespeed module to your production server

If you built this module on an alternate copy of ubuntu rather than your main production server (which you should have), then you should copy your newly created ngx_pagespeed.so module to a usb stick from your development server, and then from your usb stick to your production server.

First insert your ext4 or dos formatted usb stick into your development server. Then make a mount directory for it.

sudo mkdir /mnt/usb1

Next, Check your device name for your usb stick

lsblk

It should show up as /dev/sda or /dev/sdb. Mount it (depending on what is shows up as in lsblk):

sudo mount /dev/sda /mnt/usb1

then copy your module to your mounted usb stick:

sudo cp /usr/local/src/nginx/nginx-1.21.6/objs/ngx_pagespeed.so /mnt/usb1/

Unmount your usb with sudo umount /dev/sda then insert your usb into your production server, mount it, and copy the ngx_pagespeed.so module to your modules folder in /etc/nginx/modules/.

STEP 6) Load the module

sudo nano /etc/nginx/nginx.conf

Then add the following line to the beginning of the file:

load_module modules/ngx_pagespeed.so;

Underneath the lines…

user www-data;
worker_processes auto;
pid /run/nginx.pid;
load_module modules/ngx_pagespeed.so;

Now it’s your job to set up and configure the Nginx Filter settings. You can find the list of filters here.

Congrats, you can STOP because you are all done! Now you have a working pagespeed module for your 64 bit ARM Raspberry Pi 4!

References:

https://gitlab.com/gusco/ngx_pagespeed_arm

https://www.modpagespeed.com/doc/build_ngx_pagespeed_from_source

https://github.com/apache/incubator-pagespeed-ngx

How to install Letsencrypt Certificates on Open VPN Access Server Web Interface

In this tutorial we are going to show you how to install letsencrypt certificates on your OpenVPN Access Server’s Web Interface. This tutorial assumes you are using an ubuntu or debian based distribution.

STEP 1:

SSH into your openvpn access server in your terminal, and install certbot:

sudo apt update && sudo apt install certbot

STEP 2:

Configure your DNS A records from your registrar to point to your server’s public IP address. If you are using cloudflare, it should look like this:

STEP 3:

Run certbot and enter the answers to its questions.

sudo certbot certonly

How would you like to authenticate with the ACME CA?

1: Spin up a temporary webserver (standalone)
2: Place files in webroot directory (webroot)

Select the appropriate number [1-2] then [enter] (press ‘c’ to cancel): 1

Enter email address (used for urgent renewal and security notices): contact@nerd-tech.net

Please read the Terms of Service at
https://letsencrypt.org/documents/LE-SA-v1.2-November-15-2017.pdf. You must
agree in order to register with the ACME server at
https://acme-v02.api.letsencrypt.org/directory

(A)gree/(C)ancel: A


Would you be willing to share your email address with the Electronic Frontier
Foundation, a founding partner of the Let’s Encrypt project and the non-profit
organization that develops Certbot? We’d like to send you email about our work
encrypting the web, EFF news, campaigns, and ways to support digital freedom.

(Y)es/(N)o: N


Please enter in your domain name(s) (comma and/or space separated) (Enter ‘c’
to cancel): vpn.yourdomain.com (ex: vpn.nerd-tech.net)
Obtaining a new certificate
Performing the following challenges:
http-01 challenge for vpn.nerd-tech.net
Waiting for verification…
Cleaning up challenges

IMPORTANT NOTES:

  • Congratulations! Your certificate and chain have been saved at:
    /etc/letsencrypt/live/vpn.nerd-tech.net/fullchain.pem
    Your key file has been saved at:
    /etc/letsencrypt/live/vpn.nerd-tech.net/privkey.pem
    Your cert will expire on 2021-12-18. To obtain a new or tweaked
    version of this certificate in the future, simply run certbot
    again. To non-interactively renew all of your certificates, run
    “certbot renew”
  • Your account credentials have been saved in your Certbot
    configuration directory at /etc/letsencrypt. You should make a
    secure backup of this folder now. This configuration directory will
    also contain certificates and private keys obtained by Certbot so
    making regular backups of this folder is ideal.
  • If you like Certbot, please consider supporting our work by: Donating to ISRG / Let’s Encrypt: https://letsencrypt.org/donate
    Donating to EFF: https://eff.org/donate-le

Now enter the following lines replacing vpn.mydomain.com with your domain prefaced with a vpn and a dot (ex: vpn.nerd-tech.net).

/usr/local/openvpn_as/scripts/sacli --key "cs.priv_key" --value_file "/etc/letsencrypt/live/vpn.mydomain.com/privkey.pem" ConfigPut
/usr/local/openvpn_as/scripts/sacli --key "cs.cert" --value_file "/etc/letsencrypt/live/vpn.mydomain.com/cert.pem" ConfigPut
sudo /usr/local/openvpn_as/scripts/sacli --key "cs.ca_bundle" --value_file "/etc/letsencrypt/live/vpn.mydomain.com/chain.pem" ConfigPut
sudo /usr/local/openvpn_as/scripts/sacli start

RunStart warm None
{
“active_profile”: “Default”,
“errors”: {},
“last_restarted”: “Sun Sep 19 10:09:45 2021”,
“service_status”: {
“api”: “on”,
“auth”: “on”,
“bridge”: “on”,
“client_query”: “restarted”,
“crl”: “on”,
“daemon_pre”: “on”,
“db_push”: “on”,
“ip6tables_live”: “on”,
“ip6tables_openvpn”: “on”,
“iptables_live”: “on”,
“iptables_openvpn”: “on”,
“iptables_web”: “restarted”,
“log”: “on”,
“openvpn_0”: “on”,
“subscription”: “on”,
“user”: “on”,
“web”: “restarted”
}
}
WILL_RESTART [‘web’, ‘client’]

Now, restart your Openvpn Access Server.

sudo service openvpnas restart

Now you can browse to your new domain on port 943 (unless you changed openvpnas default web interface port).

So open your web browser and go to https://vpn.yourdomain.com:943/admin

You should see a lock icon in the top left corner of your browser, indicating that you are now using your secure letsencrypt certificates.

FINALLY, you need to log into your admin web interface, and change your hostname to the hostname you created for it.

And that is how you install letsencrypt certificates on the Openvpn Access Server Web Interface!

How to install and update Mega command line (megacmd) on your Raspberry Pi running Ubuntu 20.04

This quick guide will teach you how to add the Mega.nz Repositroy so you can easily install and upgrade the “Megacmd” and “Megasync” apps on your Linux Distribution. This tutorial will show you how to do it specifically on Ubuntu 20.04, however, the instructions can be easily modified for any ARM based debian based distribution.

STEP 1:

Go to the Mega.nz repository at https://mega.nz/linux/repo/ in your web browser, and select the folder that pertains to your working distribution. For the Raspberry Pi (because you need the ARM version), that is going to be the Raspbian_10.0 folder located at https://mega.nz/linux/repo//.

Then Go to your terminal and add the Release.key file to your apt repository:

wget https://mega.nz/linux/repo/Raspbian_10.0/Release.key && sudo apt-key add Release.key

STEP 2: Figure out your systems architecture.

Before adding mega.nz to your repository list, you first need to verfiy that you are using the 32-bit Ubuntu or Raspberry Pi OS distribution. If you are not, then you need to add the 32 bit architecture to your OS.

Verify your architecture with the following command:

dpkg --print-architecture

If the above command returns “arm64”, then proceed to the next step (STEP 2b). If the above command returns “armhf”, then you shoudl skip the next step (STEP 2b). If it returns “arm64” then you should continue with the next step (STEP 2b).

STEP 2b:

Add support for a 32-bit arm foreign architecture (armhf) with the following command:

sudo dpkg --add-architecture armhf

Verify you are now using armhf as a foreign architecture, with the following command:

dpkg --print-foreign-architectures

You should see “armhf” from this command. Now you may move on to STEP 3.

STEP 3:

Add the mega.nz repo to your apt repository by openining up your nano editor in terminal…

then pasting the indicated code below:

# Source Repository for Mega-CMD and Mega Desktop (For Raspbian ARM)
# Updated Mega Repo with 4092 bit Release Key
deb [arch=armhf] https://mega.nz/linux/repo/Raspbian_10.0/ ./

Type “Control-X“, then “y“, then “Enter“, to save and quit your nano editor.

Now, update your apt list, then install mega-cmd from your newly added repository with the following command:

sudo apt update && sudo apt install megacmd

Now, whenever you run the command sudo apt update && sudo apt upgrade your “megacmd” installation will automatically update, when updates are available.

To run your newly installed mega command line application run the following command:

mega-cmd

DONE!