nginx is a popular web server that is also often used as a reverse proxy. With reverse proxy nginx can expose local services to the public. Exposing local services makes them available to anyone and potentially involves security issues. Authelia comes to the rescue in such scenarios. It adds an authentication capabilities to services that do not have them built-in, for example Homer dashboard.
nginx needs to have additional modules installed to work with authelia. The required modules are:
- http_auth_request
- http_realip
- http_set_misc
The first two are usually included with the default nginx installation, whereas the last one needs to be added. Before nginx version 1.9.11 we had to rebuild nginx from sources in order to add new modules. Starting with version 1.9.11, we can build modules from sources and add them dynamically.
There is a very clean way of doing it for docker installations of nginx that was originally shared by user hermanbanken at https://gist.github.com/hermanbanken/96f0ff298c162a522ddbba44cad31081.js
The idea is to use another docker image to build the modules and have required dependencies installed. After the modules are built we copy them to target docker image. After modules are copied we need to use nginx directive load_module
to start using them.
Modern versions of nginx do require some updates to the originally posted Dockerfile: built modules need to be copied to /etc/nginx/modules
instead of /usr/local/nginx/modules
. Also instead of copying some pre-existing nginx.conf
to target container, I updated Dockerfile to add load_module
on top of provided nginx.conf
. This way we can keep original file if there are some updates to it in the upstream.
After running the following Dockerfile, a new nginx image will be created that loads two dynamic modules required to work with Authelia.
FROM nginx:alpine AS builder
# nginx:alpine contains NGINX_VERSION environment variable, like so:
# ENV NGINX_VERSION 1.23.3
# Modules versions
ENV NGX_DEVEL_KIT_VERSION=0.3.2
ENV NGX_DEVEL_KIT_FILE=ngx-devel-kit.tag.gz
ENV SET_MISC_VERSION=0.33
ENV SET_MISC_FILE=set-misc.tag.gz
# Download sources
RUN wget "http://nginx.org/download/nginx-${NGINX_VERSION}.tar.gz" -O nginx.tar.gz && \
wget "https://github.com/vision5/ngx_devel_kit/archive/refs/tags/v${NGX_DEVEL_KIT_VERSION}.tar.gz" -O $NGX_DEVEL_KIT_FILE && \
wget "https://github.com/openresty/set-misc-nginx-module/archive/refs/tags/v${SET_MISC_VERSION}.tar.gz" -O $SET_MISC_FILE
# For latest build deps, see https://github.com/nginxinc/docker-nginx/blob/master/mainline/alpine/Dockerfile
RUN apk add --no-cache --virtual .build-deps \
gcc \
libc-dev \
make \
openssl-dev \
pcre-dev \
zlib-dev \
linux-headers \
curl \
gnupg \
libxslt-dev \
gd-dev \
geoip-dev
# Reuse same cli arguments as the nginx:alpine image used to build
RUN CONFARGS=$(nginx -V 2>&1 | sed -n -e 's/^.*arguments: //p') \
mkdir -p /usr/src/nginx && \
tar -zxC /usr/src/nginx -f nginx.tar.gz && \
tar -xzvf "${NGX_DEVEL_KIT_FILE}" && \
NGX_DEVEL_KIT_DIR="$(pwd)/ngx_devel_kit-${NGX_DEVEL_KIT_VERSION}" && \
tar -xzvf $SET_MISC_FILE && \
SET_MISC_DIR="$(pwd)/set-misc-nginx-module-${SET_MISC_VERSION}" && \
cd /usr/src/nginx/nginx-$NGINX_VERSION && \
./configure --with-compat $CONFARGS --add-dynamic-module=$NGX_DEVEL_KIT_DIR --add-dynamic-module=$SET_MISC_DIR && \
make modules
FROM nginx:alpine
# Extract the dynamic modules from the builder image
COPY --from=builder /usr/src/nginx/nginx-${NGINX_VERSION}/objs/*_module.so /etc/nginx/modules/
RUN rm /etc/nginx/conf.d/default.conf
RUN sed -i '1s/^/# Load dynamic modules\n/' /etc/nginx/nginx.conf
RUN sed -i '2s/^/load_module \/etc\/nginx\/modules\/ndk_http_module.so;\n/' /etc/nginx/nginx.conf
RUN sed -i '3s/^/load_module \/etc\/nginx\/modules\/ngx_http_set_misc_module.so;\n/' /etc/nginx/nginx.conf
EXPOSE 80
STOPSIGNAL SIGTERM
CMD ["nginx", "-g", "daemon off;"]