I wanted to upgrade the apache http server reverse proxy in my OpenWRT router to support https (http over Secured Socket Layer (SSL) -- basically a way to encrypt web traffic to a server). This is so I can secure access to my home-based resources using https, something which is becoming the norm these days. This should be simple enough to do in apache http server, but it turns out the build of apache on my router breaks http when https is enabled.

I looked at haproxy, which is small and light, and while it supports reverse proxying by domain name and also support HTTPS, it is not able to do reverse proxying that requires URL mapping -- something I can forsee needing in the future.

Finally I checked out nginx, which is also small and light, and seems like it would do what I need. However, I discovered that nginx on the version of openwrt in my router is built without SSL.

So I decided to explore how to recompile nginx to include SSL support.


This was done on my desktop PC running Ubuntu 16.04.03 LTS.

I plan to build stuff under ~/src/openwrt.

I don't plan to build the entire firmware to flash into the router, rather I just want to get far enough to build an ipk package for nginx with SSL enabled, that I can install into my router.

Setup Operating System

I started with the instructions here.

  • Execute the following:
    • sudo apt-get update
    • sudo apt-get install git-core build-essential libssl-dev libncurses5-dev unzip gawk zlib1g-dev
    • sudo apt-get install subversion mercurial

Clone OpenWRT

It would be great if we could build on the latest bleeding edge trunk, but OpenWRT changed the system library from uClibC to musl libc shortly after the Chaos Calmer release. This means that stuff built from the latest trunk would expect musl libc libraries to be in place, which would not be the case on a router with Chaos Calmer firmware. So you need to roll back to the Chaos Calmer release (v15.05.1) to build packages for an existing firmware.

  • git checkout v15.05.1

This brings up the next problem with build scripts that download its source code from the internet. As time goes by, the links that it downloads from tend to break. I had to pre-populate the download directory with the following files whose original links are broken:

Setup the Build System

  • cd ~/src/openwrt
  • make menuconfig
    • Target System : Atheros AR7xxx/AR9xxx
    • Subtarget: Generic
    • Target Profile : TP-Link TL-WR1043N/ND
    • Build the OpenWRT SDK : true
    • Exit & Save
  • make V=s

sit back and wait ... on my machine it took 46 minutes.

Add nginx to the build

Now that we've got the basic build working and the kinks sorted out, it's time to add nginx. Nginx is not included in the openwrt base, but you can add it to the build from a "feed".

  • Execute:
    • scripts/feeds update
    • scripts/feeds search nginx
    • scripts/feeds install nginx
    • make menuconfig
      • Network
        • Web Servers/Proxies
          • nginx : M
          • nginx: ENTER
            • Configuration
              • Enable SSL module : Y
        • Exit ( x5) & Save
    • time make -j5

Sit back and wait again ... on my machine this one took 2 minutes 30 seconds. The ipk file is now located at:

shahada@pc-shahada:~/src/openwrt$ find . -type f -name nginx\*ipk

Install the new nginx package

Copy the .ipk over to the router:
shahada@pc-shahada:~/src/openwrt$ scp ./bin/ar71xx/packages/packages/nginx_1.4.7-2_ar71xx.ipk root@router:/tmp
root@router's password:
nginx_1.4.7-2_ar71xx.ipk 100% 205KB 204.8KB/s 00:00

Then ssh into the router and execute the following:
  • opkg install /tmp/nginx_1.4.7-2_ar71xx.ipk
  • rm /tmp/nginx_1.4.7-2_ar71xx.ipk

You can now make use of the "ssl on" directive in your /etc/nginx/nginx.conf.

My Configuration

This is what my /etc/nginx/nginx.conf looks like:

user nobody nogroup;
worker_processes 1;

#error_log logs/error.log;
#error_log logs/error.log notice;
#error_log logs/error.log info;

#pid logs/;

events {
worker_connections 1024;

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

log_format main '$server_name $host $remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';

#access_log logs/access.log main;

sendfile on;
#tcp_nopush on;

#keepalive_timeout 0;
keepalive_timeout 65;

#gzip on;


server {
listen 80 default_server;
listen [::]:80 default_server;

server_name _;

location / {
root /etc/nginx/html;
index index.html index.htm;

#error_page 404 /404.html;

# redirect server error pages to the static page /50x.html
#error_page 500 502 503 504 /50x.html;
#location = /50x.html {
# root html;



server {
listen 80;
listen [::]:80;

location / {
proxy_set_header Host;


server {
listen 443;
listen [::]:443;

ssl on;
ssl_certificate /etc/dehydrated/certs/;
ssl_certificate_key /etc/dehydrated/certs/;

ssl_session_timeout 5m;

ssl_protocols SSLv2 SSLv3 TLSv1;
ssl_ciphers HIGH:!aNULL:!MD5;
ssl_prefer_server_ciphers on;

location / {
proxy_set_header Host;



  • The nginx with ssl support that we build has the same version number as the nginx that doesn't have ssl support that is in the openwrt repositories for chaos calmer v15.05.1. So it will survive a "opkg upgrade". If for some reason openwrt has a newer version of nginx, then you may have to repeat these instructions after checking out the latest branch.
  • I relocated luci to a different port on my router, so I can use port 80 and 443 freely.
  • I used free SSL certificates from, via the dehydrated tool to extract, sign and keep them up to date.
  • Not everything that worked on http works on https, so my internal sites may need some work.
  • I'm not actually using url path mapping (i.e. proxying to different back-end servers depending on parts of the url path) yet, but this will come later.
  • You might need to allow connections port 80 and 443 of your router's wan interface. In luci, network -> Firewall -> Traffic Rules, set this: