Browse Source

2019-12-19 update

itix-theme
Nicolas Massé 6 years ago
parent
commit
df16b83918
  1. 6
      content/blog/install-openwrt-raspberry-pi.md
  2. 313
      content/blog/nginx-with-tls-on-openwrt.md
  3. BIN
      static/blog/nginx-with-tls-on-openwrt/make-menuconfig.png

6
content/blog/install-openwrt-raspberry-pi.md

@ -5,7 +5,7 @@ opensource:
- OpenWRT
---
OpenWRT is a Linux distribution for embedded systems.
[OpenWRT](https://openwrt.org/) is a Linux distribution for embedded systems.
It made design choices that take it apart from the usual Linux distributions: musl libc instead of the usual glibc, busybox instead of coreutils, ash instead of bash, etc.
As a result, the system is very light and blazing fast!
@ -331,10 +331,10 @@ uci commit
OpenWRT was originally a Linux distribution for routers, so it comes bundled with network software that might be useless for you. You can remove those unneeded software if you wish.
```sh
opkg remove --force-removal-of-dependent-packages ppp ppp-mod-pppoe odhcpd-ipv6only dnsmasq hostapd-common luci-base lua luci-app-firewall luci-lib-ip luci-lib-jsonc luci-lib-nixio luci-proto-ipv6 luci-proto-ppp luci-theme-bootstrap
opkg remove --force-removal-of-dependent-packages ppp ppp-mod-pppoe odhcpd-ipv6only dnsmasq hostapd-common luci luci-ssl-openssl luci-base lua luci-app-firewall luci-lib-ip luci-lib-jsonc luci-lib-nixio luci-proto-ipv6 luci-proto-ppp luci-theme-bootstrap uhttpd uhttpd-mod-ubus
```
## Conclusion
OpenWRT is now installed on your Raspberry PI.
You can start installing software on it, such as the nginx reverse proxy or miniflux, an RSS reader.
You can start installing software on it, such as the [nginx reverse proxy](../nginx-with-tls-on-openwrt/) or miniflux, an RSS reader.

313
content/blog/nginx-with-tls-on-openwrt.md

@ -0,0 +1,313 @@
---
title: "Nginx with TLS on OpenWRT"
date: 2019-12-19T00:00:00+02:00
opensource:
- OpenWRT
- nginx
---
In the article "[Install OpenWRT on your Raspberry PI](../install-openwrt-raspberry-pi/)", I explained how to install OpenWRT on a Raspberry PI and the first steps as an OpenWRT user.
As I plan to use my Raspberry PI to host plenty of web applications, I wanted to setup a versatile reverse proxy to protect them all, along with TLS support to meet nowadays security requirements.
OpenWRT has an [nginx package](https://openwrt.org/packages/pkgdata/nginx), ready to be installed using *opkg* but unfortunately it does not have TLS enabled. So we need to recompile nginx with TLS enabled!
## Install the OpenWRT build system
Install a Linux distribution [supported by the OpenWRT build system](https://openwrt.org/docs/guide-developer/build-system/install-buildsystem) in a Virtual Machine. For instance, [Ubuntu Server LTS 18.04.3](http://cdimage.ubuntu.com/releases/18.04.3/release/).
Install the build system pre-requisites.
```sh
sudo apt-get install -y build-essential libncurses5-dev gawk git libssl-dev gettext unzip zlib1g-dev file python-dev libmodule-build-perl libmodule-install-perl libthread-queue-any-perl
```
Clone the OpenWRT GIT repository. Change the branch name to your version number, if you are not on 18.06.
```sh
git clone https://git.openwrt.org/openwrt/openwrt.git -b openwrt-18.06
cd openwrt
```
Run *make menuconfig* to configure the build system.
```sh
make menuconfig
```
Select the following options:
- Target System: **Broadcom BCM27xx**
- Subtarget: **BCM2710 64 bit based boards**
- Target Profile: **Raspberry Pi 3B/3B+**
- Enable **Build the OpenWRT SDK**
![make menuconfig](make-menuconfig.png)
Launch a complete build. According to [the documentation](https://oldwiki.archive.openwrt.org/doc/techref/buildroot), the parameter *V=s* in the following command is used to display verbose output.
```sh
make V=s
```
## Recompile the nginx package
Fetch the existing nginx package sources.
```sh
scripts/feeds update
scripts/feeds install nginx
```
Run *make menuconfig* again.
```sh
make menuconfig
```
Drill down to **Network** > **Web Servers/Proxies** and:
- Press space to select **nginx**
- Press enter to enter configuration
- Choose **Configuration**
- Press space to select "**Enable SSL Module**"
- Exit five times and save
Build the nginx package.
```sh
make V=s
```
Once the build finished, the nginx package will be in *bin/packages*.
```raw
$ find . -type f -name 'nginx*.ipk'
./bin/packages/aarch64_cortex-a53/packages/nginx_1.12.2-1_aarch64_cortex-a53.ipk
```
## Install nginx
Install the freshly compiled nginx package on your OpenWRT system.
```sh
scp ./bin/packages/aarch64_cortex-a53/packages/nginx_1.12.2-1_aarch64_cortex-a53.ipk root@raspberry-pi.example.test:/tmp
ssh root@raspberry-pi.example.test opkg install /tmp/nginx_1.12.2-1_aarch64_cortex-a53.ipk
```
## Install Lego
[Lego](https://go-acme.github.io/lego/) is a client for the Let's Encrypt CA. It will help us get valid TLS certificates for our nginx instance.
Install lego from the [binaries](https://github.com/go-acme/lego/releases).
```sh
mkdir -p /opt/lego/bin
wget -O /tmp/lego.tgz https://github.com/go-acme/lego/releases/download/v3.2.0/lego_v3.2.0_linux_arm64.tar.gz
tar -C /opt/lego/bin -zxvf /tmp/lego.tgz lego
chown root:root /opt/lego/bin/lego
chmod 755 /opt/lego/bin/lego
```
## Get a public TLS certificate
Request a public certificate for your Raspberry PI hostname. In the following example, I'm using the DNS challenge method and the Gandi DNS provider. Of course, you would have also to replace *raspberry-pi.example.test* with your Raspberry PI's hostname.
```sh
mkdir /etc/nginx/tls
GANDIV5_API_KEY=[REDACTED] /opt/lego/bin/lego -m replace.with@your.email -d raspberry-pi.example.test -a --dns gandiv5 --path /etc/nginx/tls run --no-bundle
```
If everything went fine, you will find the freshly issued certificates in */etc/nginx/tls/certificates/$hostname.{key,crt}*.
```raw
root@OpenWrt:~# find /etc/nginx/tls/
/etc/nginx/tls/
/etc/nginx/tls/certificates
/etc/nginx/tls/certificates/raspberry-pi.example.test.crt
/etc/nginx/tls/certificates/raspberry-pi.example.test.issuer.crt
/etc/nginx/tls/certificates/raspberry-pi.example.test.key
/etc/nginx/tls/certificates/raspberry-pi.example.test.json
```
## Configure nginx
Create a user for the nginx workers.
```sh
opkg update
opkg install shadow-useradd
useradd -d /var/run/nginx -s /bin/false -m -r nginx
```
Create the nginx configuration file in **/etc/nginx/nginx.conf**.
```raw
user nginx nginx;
worker_processes 1;
error_log syslog:server=unix:/dev/log,nohostname warn;
events {
worker_connections 1024;
}
http {
server_names_hash_bucket_size 64;
include mime.types;
log_format main '$remote_addr "$request" => $status';
access_log syslog:server=unix:/dev/log,nohostname main;
sendfile on;
keepalive_timeout 65;
gzip off;
server {
listen 443 ssl default_server;
ssl_certificate /etc/nginx/tls/certificates/raspberry-pi.example.test.crt;
ssl_certificate_key /etc/nginx/tls/certificates/raspberry-pi.example.test.key;
ssl_session_cache shared:SSL:1m;
ssl_session_timeout 5m;
ssl_ciphers HIGH:!aNULL:!MD5;
ssl_prefer_server_ciphers on;
# Error pages
error_page 404 /404.html;
error_page 500 502 503 504 /50x.html;
location ~ /[45][0-9x][0-9x].html {
root /srv/nginx/default;
}
# Main content
index index.html index.htm;
location / {
root /srv/nginx/default;
}
}
}
```
Create the default page and the error pages.
```sh
mkdir -p /srv/nginx/default
echo "None of your business." > /srv/nginx/default/index.html
echo "Nope. Not here." > /srv/nginx/default/404.html
echo "OOPS..." > /srv/nginx/default/50x.html
```
## Start nginx
Start the nginx instance.
```sh
service nginx enable
service nginx start
```
If your configuration is valid, the port 443 should be bound to nginx.
```raw
root@OpenWrt:~# netstat -tlnp |grep :443
tcp 0 0 0.0.0.0:443 0.0.0.0:* LISTEN 11305/nginx.conf -g
```
If nginx does not start, you can get some details using the *logread* command.
```raw
logread |tail -n 10
```
If you cannot get any details using *logread*, try to start nginx manually.
```sh
nginx -g "daemon off;" -c /etc/nginx/nginx.conf
```
From your workstation, try to query your nginx instance by its IP address.
```raw
$ curl -k https://192.168.2.2/
None of your business.
```
## Further configuration
So far, our nginx instance is only serving a few static files with unpleasant messages.
This is the default virtual host of our nginx instance that is used when bots try to scan your web server by its IP address without knowing its actual hostname.
To add another virtual host, just add a new *server* block after the default one.
```raw
server {
listen 443 ssl;
server_name raspberry-pi.example.test
ssl_certificate /etc/nginx/tls/certificates/raspberry-pi.example.test.crt;
ssl_certificate_key /etc/nginx/tls/certificates/raspberry-pi.example.test.key;
ssl_session_cache shared:SSL:1m;
ssl_session_timeout 5m;
ssl_ciphers HIGH:!aNULL:!MD5;
ssl_prefer_server_ciphers on;
# Error pages
error_page 404 /404.html;
error_page 500 502 503 504 /50x.html;
location ~ /[45][0-9x][0-9x].html {
root /srv/nginx/default;
}
# Main content
index index.html index.htm;
location / {
root /srv/nginx/main;
}
}
```
Serve some nice content.
```sh
mkdir -p /srv/nginx/main
echo 'Welcome!' > /srv/nginx/main/index.html
```
From your workstation, try to query your nginx instance by its hostname.
```raw
$ curl https://raspberry-pi.itix.fr/
Welcome!
```
## Certificate renewal
The TLS certificate we fetched from Let's Encrypt is valid for ninety days.
If you do not want to manually renew the certificate every ninety days, you will have to setup automatic renewal in a cron job.
Install pkill. We will use it to tell nginx to reload its configuration and the renewed certificates.
```sh
opkg update
opkg install procps-ng-pkill
```
Edit the crontab of the root user.
```sh
crontab -e -u root
```
And an entry to renew the certificate using lego.
```crontab
# At 3:59 the first day of the month, renew the Let's Encrypt certificates
3 59 1 * * GANDIV5_API_KEY=[REDACTED] /opt/lego/bin/lego -m replace.with@your.email -d raspberry-pi.example.test -a --dns gandiv5 --path /etc/nginx/tls run --no-bundle && pkill -SIGHUP 'nginx: master'
```
## Conclusion
Nginx is now installed on your Raspberry PI, with TLS support enabled and a valid public certificate from Let's Encrypt that will be renewed automatically.
The configuration serves a default virtual host to every bot that queries the nginx instance by its IP address and can serve any number of virtual host, provided you add the matching *server* block.
Discover in the next article how to deploy a real world application: miniflux, an RSS reader.

BIN
static/blog/nginx-with-tls-on-openwrt/make-menuconfig.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 488 KiB

Loading…
Cancel
Save