Skip to content

Instantly share code, notes, and snippets.

@akutz
Last active August 12, 2018 19:20
Show Gist options
  • Save akutz/d3f5dd4963b926babaa20b4a3bfbe7ae to your computer and use it in GitHub Desktop.
Save akutz/d3f5dd4963b926babaa20b4a3bfbe7ae to your computer and use it in GitHub Desktop.
How to build nginx for Container Linux

Why?

Because some people prefer ./configure over containers.

Omitted Modules

Please note the following modules were omitted on purpose due to Container Linux lacking the required libraries:

The modules below were omitted simply because they were not necessary to satisfy this author's use case (redirect and TLS proxy):

Verify the host is running Container Linux

$ cat /etc/lsb-release 
DISTRIB_ID="Container Linux by CoreOS"
DISTRIB_RELEASE=1800.6.0
DISTRIB_CODENAME="Rhyolite"
DISTRIB_DESCRIPTION="Container Linux by CoreOS 1800.6.0 (Rhyolite)"

Create the Dockerfile used to build nginx

$ cat <<EOF > Dockerfile
FROM gcc:7.3.0
LABEL maintainer="Andrew Kutz <[email protected]>"

ENV SRC_DIR=/usr/local/src

ENV NGINX_VERSION=1.14.0
ENV OPENSSL_VERSION=1.1.0h
ENV PCRE_VERSION=8.42
ENV ZLIB_VERSION=1.2.11

ENV NGINX_URL=http://nginx.org/download/nginx-\${NGINX_VERSION}.tar.gz
ENV NGINX_SRC=\${SRC_DIR}/nginx-\${NGINX_VERSION}

ENV OPENSSL_URL=https://www.openssl.org/source/openssl-\${OPENSSL_VERSION}.tar.gz
ENV OPENSSL_SRC=\${SRC_DIR}/openssl-\${OPENSSL_VERSION}

ENV PCRE_URL=ftp://ftp.csx.cam.ac.uk/pub/software/programming/pcre/pcre-\${PCRE_VERSION}.tar.bz2
ENV PCRE_SRC=\${SRC_DIR}/pcre-\${PCRE_VERSION}

ENV ZLIB_URL=http://zlib.net/zlib-\${ZLIB_VERSION}.tar.gz
ENV ZLIB_SRC=\${SRC_DIR}/zlib-\${ZLIB_VERSION}

RUN apt-get update && apt-get install -y bzip2 libssl-dev libpam-dev

WORKDIR \${SRC_DIR}
RUN curl -L \${NGINX_URL} | tar xz
RUN curl -L \${ZLIB_URL} | tar xz
RUN curl -L \${PCRE_URL} | tar xj
RUN curl -L \${OPENSSL_URL} | tar xz

WORKDIR \${NGINX_SRC}
RUN ./configure \\
    --prefix=/var/lib/nginx \\
    --sbin-path=/opt/sbin/nginx \\
    --conf-path=/etc/nginx/nginx.conf \\
    --http-log-path=/var/log/nginx/access.log \\
    --error-log-path=/var/log/nginx/error.log \\
    --lock-path=/var/lock/nginx.lock \\
    --pid-path=/var/run/nginx.pid \\
    --with-http_v2_module \\
    --conf-path=/etc/nginx/nginx.conf \\
    --with-zlib=\${ZLIB_SRC} \\
    --with-pcre=\${PCRE_SRC} \\
    --with-openssl=\${OPENSSL_SRC} \\
    --with-cc-opt='-g -O2 -fstack-protector --param=ssp-buffer-size=4 -Wformat -Werror=format-security -D_FORTIFY_SOURCE=2' \\
    --with-ld-opt='-Wl,-Bsymbolic-functions -Wl,-z,relro' \\
    --http-client-body-temp-path=/var/lib/nginx/body \\
    --http-fastcgi-temp-path=/var/lib/nginx/fastcgi \\
    --http-proxy-temp-path=/var/lib/nginx/proxy \\
    --http-scgi-temp-path=/var/lib/nginx/scgi \\
    --http-uwsgi-temp-path=/var/lib/nginx/uwsgi \\
    --with-debug \\
    --with-pcre-jit \\
    --with-ipv6 \\
    --with-http_ssl_module \\
    --with-http_stub_status_module \\
    --with-http_gzip_static_module
RUN make
RUN make install
EOF

Build nginx on the Container Linux host using Docker

$ docker build -t build-nginx .

Get the nginx binary from the image

$ docker run --rm -it \
             -v $(pwd):/tmp/local \
             build-nginx \
             /bin/sh -c 'cp /opt/sbin/nginx /tmp/local'

Verify the nginx binary is compatible with the Container Linux host

$ ldd nginx
	linux-vdso.so.1 (0x00007ffd93aaa000)
	libdl.so.2 => /lib64/libdl.so.2 (0x00007fd460d26000)
	libpthread.so.0 => /lib64/libpthread.so.0 (0x00007fd460b05000)
	libcrypt.so.1 => /lib64/libcrypt.so.1 (0x00007fd4608cd000)
	libc.so.6 => /lib64/libc.so.6 (0x00007fd46050a000)
	/lib64/ld-linux-x86-64.so.2 (0x00007fd460f2a000)

Verify the checksum of the nginx binary

Please verify the checksum of the nginx binary before using it.

Verifying the checksum on Container Linux

$ sha1sum -b nginx
98ab36630b535a48b99b7b63118f58a57698c80a *nginx

Verifying the checksum on macOS

$ shasum -ba1 nginx 
98ab36630b535a48b99b7b63118f58a57698c80a *nginx

Add the nginx user

$ sudo useradd -rMd /var/lib/nginx nginx

Create the nginx directories

$ sudo mkdir -p /etc/nginx /var/log/nginx /var/lib/nginx/{body,fastcgi,proxy,scgi,uswgi}

Create the nginx configuration file

The sample configuration file is used to start an nginx server on port 80 with the following characteristics:

  1. A GET /health request is proxied to the secure endpoint, gist.githubusercontent.com:443, and returns HTTP 200 OK.
  2. All other requests redirect to this gist.
sudo cat <<EOF | sudo tee /etc/nginx/nginx.conf >/dev/null 2>&1
user                   nginx;
pid                    /var/run/nginx.pid;
error_log              /var/log/nginx/error.log;
worker_processes       1;

events {
  worker_connections   1024;
}

http {
  default_type         application/octet-stream;
  log_format           main  '\$remote_addr - \$remote_user [\$time_local] "\$request" '
                             '\$status \$body_bytes_sent "\$http_referer" '
                             '"\$http_user_agent" "\$http_x_forwarded_for"';
  access_log           /var/log/nginx/access.log main;
  sendfile             on;
  keepalive_timeout    65;
  gzip                 on;

  server {
    listen             80;
    server_name        nginx;
    
    location = /health {
      proxy_pass       https://gist.githubusercontent.com/akutz/a930d744d884a4208016efdbe54cd2f6/raw/df116902b374a8a64033bd72f05750ab4320ce96/200;
      proxy_set_header Host       gist.githubusercontent.com;
      proxy_set_header X-Real-IP  \$remote_addr;
    }

    location / {
      return           301 https://gist.github.com/akutz/d3f5dd4963b926babaa20b4a3bfbe7ae;
    }
  }
}
EOF

Start nginx

$ sudo ./nginx

Perform a health check against the local nginx server

The following command issues a GET /health to the non-secure port of the local nginx server. However, the response is from this gist, accessed via the secure https protocol:

$ curl -v http://127.0.0.1:80/health && echo
ok

Query any other location on the local nginx server

Any other query against the local nginx server will indicate that the content has moved permanently to this gist:

$ curl -v http://localhost
* Rebuilt URL to: http://localhost/
*   Trying 127.0.0.1...
* TCP_NODELAY set
* Connected to localhost (127.0.0.1) port 80 (#0)
> GET / HTTP/1.1
> Host: localhost
> User-Agent: curl/7.59.0
> Accept: */*
> 
< HTTP/1.1 301 Moved Permanently
< Server: nginx/1.14.0
< Date: Sun, 12 Aug 2018 00:12:11 GMT
< Content-Type: text/html
< Content-Length: 185
< Connection: keep-alive
< Location: https://gist.github.com/akutz/d3f5dd4963b926babaa20b4a3bfbe7ae
< 
<html>
<head><title>301 Moved Permanently</title></head>
<body bgcolor="white">
<center><h1>301 Moved Permanently</h1></center>
<hr><center>nginx/1.14.0</center>
</body>
</html>
* Connection #0 to host localhost left intact

Check the nginx access log

The nginx access log verifies the above queries:

$ cat /var/log/nginx/access.log
127.0.0.1 - - [12/Aug/2018:00:14:09 +0000] "GET / HTTP/1.1" 301 185 "-" "curl/7.59.0" "-"
127.0.0.1 - - [12/Aug/2018:00:14:12 +0000] "GET /health HTTP/1.1" 200 2 "-" "curl/7.59.0" "-"

Stop the nginx server

$ sudo ./nginx -s quit
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment