Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: enable running nginx containers with read-only root fs #210

Merged
merged 3 commits into from
Feb 23, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions apache/Dockerfile
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
ARG HTTPD_VERSION="n/a"

FROM httpd:${HTTPD_VERSION} AS build
FROM image AS build

ARG MODSEC2_VERSION="n/a"
ARG LUA_VERSION="n/a"
Expand Down Expand Up @@ -36,7 +36,7 @@ RUN set -eux; \
make install; \
make clean

FROM httpd:${HTTPD_VERSION} AS crs_release
FROM image AS crs_release

ARG CRS_RELEASE

Expand All @@ -56,7 +56,7 @@ RUN set -eux; \
rm -f v${CRS_RELEASE}-minimal.tar.gz coreruleset-${CRS_RELEASE}-minimal.tar.gz.asc; \
mv -v /opt/owasp-crs/crs-setup.conf.example /opt/owasp-crs/crs-setup.conf

FROM httpd:${HTTPD_VERSION}
FROM image

ARG MODSEC2_VERSION
ARG LUA_VERSION
Expand Down
6 changes: 3 additions & 3 deletions apache/Dockerfile-alpine
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
ARG HTTPD_VERSION="n/a"

FROM httpd:${HTTPD_VERSION}-alpine AS build
FROM image AS build

ARG MODSEC2_VERSION="n/a"
ARG LUA_VERSION="n/a"
Expand Down Expand Up @@ -46,7 +46,7 @@ RUN set -eux; \
make install; \
make clean

FROM httpd:${HTTPD_VERSION}-alpine AS crs_release
FROM image AS crs_release

ARG CRS_RELEASE

Expand All @@ -66,7 +66,7 @@ RUN set -eux; \
rm -f v${CRS_RELEASE}-minimal.tar.gz coreruleset-${CRS_RELEASE}-minimal.tar.gz.asc; \
mv -v /opt/owasp-crs/crs-setup.conf.example /opt/owasp-crs/crs-setup.conf

FROM httpd:${HTTPD_VERSION}-alpine
FROM image

ARG MODSEC2_VERSION
ARG LUA_VERSION
Expand Down
102 changes: 64 additions & 38 deletions docker-bake.hcl
Original file line number Diff line number Diff line change
Expand Up @@ -96,16 +96,11 @@ function "vtag" {
group "default" {
targets = [
"apache",
"apache-alpine",
"nginx",
"nginx-alpine",
"nginx"
]
}

target "docker-metadata-action" {}

target "platforms-base" {
inherits = ["docker-metadata-action"]
context="."
platforms = ["linux/amd64", "linux/arm64/v8", "linux/arm/v7", "linux/i386"]
labels = {
Expand All @@ -121,51 +116,82 @@ target "platforms-base" {
}

target "apache" {
inherits = ["platforms-base"]
dockerfile="apache/Dockerfile"
args = {
HTTPD_VERSION = "${httpd-version}"
LUA_MODULES = join(" ", lua-modules-debian)
matrix = {
base = [
{
name = "debian"
dockerfile="apache/Dockerfile"
image = "docker-image://httpd:${httpd-version}"
lua_modules = join(" ", lua-modules-debian)
tag_base = "apache"
},
{
name = "alpine"
dockerfile = "apache/Dockerfile-alpine"
image = "docker-image://httpd:${httpd-version}-alpine"
lua_modules = join(" ", lua-modules-alpine)
tag_base = "apache-alpine"
}
]
}
tags = concat(tag("apache"),
vtag("${crs-version}", "apache")
)
}

target "apache-alpine" {
inherits = ["platforms-base"]
dockerfile="apache/Dockerfile-alpine"
name = "apache-${base.name}"
contexts = {
image = base.image
}
dockerfile = base.dockerfile
args = {
HTTPD_VERSION = "${httpd-version}"
LUA_MODULES = join(" ", lua-modules-alpine)
LUA_MODULES = base.lua_modules
}
tags = concat(tag("apache-alpine"),
vtag("${crs-version}", "apache-alpine")
tags = concat(tag(base.tag_base),
vtag("${crs-version}", base.tag_base)
)
}

target "nginx" {
inherits = ["platforms-base"]
dockerfile="nginx/Dockerfile"
args = {
LUA_MODULES = join(" ", lua-modules-debian)
NGINX_VERSION = "${nginx-version}"
NGINX_DYNAMIC_MODULES = join(" ", [for mod in nginx-dynamic-modules : join(" ", [mod.owner, mod.name, mod.version])])
matrix = {
base = [
{
name = "debian"
dockerfile = "nginx/Dockerfile"
image = "docker-image://nginxinc/nginx-unprivileged:${nginx-version}"
lua_modules = join(" ", lua-modules-debian)
tag_base = "nginx"
},
{
name = "alpine"
dockerfile = "nginx/Dockerfile-alpine"
image = "docker-image://nginxinc/nginx-unprivileged:${nginx-version}-alpine"
lua_modules = join(" ", lua-modules-alpine)
tag_base = "nginx-alpine"
}
],
read-only-fs = [
{
name = "writable"
read-only = "false"
},
{
name = "read-only"
read-only = "true"
}
]
}
tags = concat(tag("nginx"),
vtag("${crs-version}", "nginx")
)
}

target "nginx-alpine" {
inherits = ["platforms-base"]
dockerfile="nginx/Dockerfile-alpine"
name = "nginx-${base.name}-${read-only-fs.name}"
contexts = {
image = base.image
}
dockerfile = base.dockerfile
args = {
LUA_MODULES = join(" ", lua-modules-alpine)
NGINX_VERSION = "${nginx-version}"
NGINX_VERSION = nginx-version
LUA_MODULES = base.lua_modules
NGINX_DYNAMIC_MODULES = join(" ", [for mod in nginx-dynamic-modules : join(" ", [mod.owner, mod.name, mod.version])])
NGINX_HOME = "/etc/nginx"
READ_ONLY_FS = read-only-fs.read-only
}
tags = concat(tag("nginx-alpine"),
vtag("${crs-version}", "nginx-alpine")
tags = concat(tag(base.tag_base),
vtag("${crs-version}", base.tag_base)
)
}
36 changes: 29 additions & 7 deletions nginx/Dockerfile
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
ARG NGINX_VERSION="n/a"

FROM nginxinc/nginx-unprivileged:${NGINX_VERSION} AS build
FROM image AS build

ARG NGINX_VERSION="n/a"
ARG MODSEC3_VERSION="n/a"
ARG LMDB_VERSION="n/a"
ARG LUA_VERSION="n/a"
ARG NGINX_DYNAMIC_MODULES="n/a"
ARG NGINX_HOME="n/a"
ARG READ_ONLY_FS="false"

USER root

Expand Down Expand Up @@ -86,7 +87,7 @@ RUN set -eux; \
curl -sSL https://ssl-config.mozilla.org/ffdhe2048.txt -o /usr/share/TLS/dhparam-2048.pem; \
curl -sSL https://ssl-config.mozilla.org/ffdhe4096.txt -o /usr/share/TLS/dhparam-4096.pem

FROM nginxinc/nginx-unprivileged:${NGINX_VERSION} AS crs_release
FROM image AS crs_release

ARG CRS_RELEASE

Expand Down Expand Up @@ -114,15 +115,19 @@ RUN curl -sSL https://github.com/coreruleset/coreruleset/releases/download/v${CR
rm -f v${CRS_RELEASE}-minimal.tar.gz coreruleset-${CRS_RELEASE}-minimal.tar.gz.asc; \
mv -v /opt/owasp-crs/crs-setup.conf.example /opt/owasp-crs/crs-setup.conf

FROM nginxinc/nginx-unprivileged:${NGINX_VERSION}
FROM image

ARG MODSEC3_VERSION
ARG LMDB_VERSION
ARG LUA_VERSION
ARG LUA_MODULES
ARG NGINX_HOME
ARG READ_ONLY_FS

LABEL maintainer="Felipe Zipitria <felipe.zipitria@owasp.org>"

ENV NGINX_HOME="${NGINX_HOME}"

ENV \
ACCESSLOG=/var/log/nginx/access.log \
BACKEND=http://localhost:80 \
Expand Down Expand Up @@ -250,8 +255,25 @@ RUN set -eux; \
ln -s /usr/local/modsecurity/lib/libmodsecurity.so.${MODSEC3_VERSION} /usr/local/modsecurity/lib/libmodsecurity.so.3.0; \
ln -s /usr/local/modsecurity/lib/libmodsecurity.so.${MODSEC3_VERSION} /usr/local/modsecurity/lib/libmodsecurity.so.3; \
ln -s /usr/local/modsecurity/lib/libmodsecurity.so.${MODSEC3_VERSION} /usr/local/modsecurity/lib/libmodsecurity.so; \
ln -sv /opt/owasp-crs /etc/modsecurity.d/; \
chown nginx:nginx /opt/owasp-crs /etc/modsecurity.d
ln -sv /opt/owasp-crs /etc/modsecurity.d/

RUN set -eux; \
if [ "${READ_ONLY_FS}" = "true" ]; then \
# move files that need to be writable so we can use tmpfs for them later
mkdir -p /usr/local/bootstrap/nginx /usr/local/bootstrap/modsecurity.d /usr/local/bootstrap/owasp-crs; \
mv "${NGINX_HOME}/"* /usr/local/bootstrap/nginx/; \
mv /etc/modsecurity.d/* /usr/local/bootstrap/modsecurity.d/; \
mv /opt/owasp-crs/* /usr/local/bootstrap/owasp-crs/; \
chown nginx:nginx \
"${NGINX_HOME}" \
/usr/local/bootstrap/*; \
else \
# only run this script in read-only configuration
rm /docker-entrypoint.d/0-move-writables.sh; \
fi; \
chown nginx:nginx \
/opt/owasp-crs \
/etc/modsecurity.d

USER nginx

Expand Down
38 changes: 30 additions & 8 deletions nginx/Dockerfile-alpine
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
ARG NGINX_VERSION="n/a"

FROM nginxinc/nginx-unprivileged:${NGINX_VERSION}-alpine AS build
FROM image AS build

ARG NGINX_VERSION="n/a"
ARG MODSEC3_VERSION="n/a"
ARG LUA_VERSION="n/a"
ARG NGINX_DYNAMIC_MODULES="n/a"
ARG NGINX_HOME="n/a"
ARG READ_ONLY_FS="false"

USER root

Expand Down Expand Up @@ -65,7 +66,7 @@ RUN set -eux; \
git clone -b "${version}" --depth 1 "https://github.com/${owner}/${name}.git"; \
modules="${modules} --add-dynamic-module=../${name}"; \
done; \
curl -sSL https://nginx.org/download/nginx-${NGINX_VERSION}.tar.gz -o nginx-${NGINX_VERSION}.tar.gz; \
curl -sSL "https://nginx.org/download/nginx-${NGINX_VERSION}.tar.gz" -o nginx-${NGINX_VERSION}.tar.gz; \
tar -xzf nginx-${NGINX_VERSION}.tar.gz; \
cd ./nginx-${NGINX_VERSION}; \
./configure --with-compat ${modules}; \
Expand All @@ -82,7 +83,7 @@ RUN set -eux; \
curl -sSL https://ssl-config.mozilla.org/ffdhe2048.txt -o /usr/share/TLS/dhparam-2048.pem; \
curl -sSL https://ssl-config.mozilla.org/ffdhe4096.txt -o /usr/share/TLS/dhparam-4096.pem

FROM nginxinc/nginx-unprivileged:${NGINX_VERSION}-alpine AS crs_release
FROM image AS crs_release

ARG CRS_RELEASE

Expand All @@ -109,14 +110,18 @@ RUN curl -sSL https://github.com/coreruleset/coreruleset/releases/download/v${CR
rm -f v${CRS_RELEASE}-minimal.tar.gz coreruleset-${CRS_RELEASE}-minimal.tar.gz.asc; \
mv -v /opt/owasp-crs/crs-setup.conf.example /opt/owasp-crs/crs-setup.conf

FROM nginxinc/nginx-unprivileged:${NGINX_VERSION}-alpine
FROM image

ARG MODSEC3_VERSION
ARG LUA_VERSION
ARG LUA_MODULES
ARG NGINX_HOME
ARG READ_ONLY_FS

LABEL maintainer="Felipe Zipitria <felipe.zipitria@owasp.org>"

ENV NGINX_HOME="${NGINX_HOME}"

ENV \
ACCESSLOG=/var/log/nginx/access.log \
BACKEND=http://localhost:80 \
Expand Down Expand Up @@ -247,8 +252,25 @@ RUN set -eux; \
ln -s /usr/local/modsecurity/lib/libmodsecurity.so.${MODSEC3_VERSION} /usr/local/modsecurity/lib/libmodsecurity.so.3.0; \
ln -s /usr/local/modsecurity/lib/libmodsecurity.so.${MODSEC3_VERSION} /usr/local/modsecurity/lib/libmodsecurity.so.3; \
ln -s /usr/local/modsecurity/lib/libmodsecurity.so.${MODSEC3_VERSION} /usr/local/modsecurity/lib/libmodsecurity.so; \
ln -sv /opt/owasp-crs /etc/modsecurity.d/; \
chown nginx:nginx /opt/owasp-crs /etc/modsecurity.d
ln -sv /opt/owasp-crs /etc/modsecurity.d/

RUN set -eux; \
if [ "${READ_ONLY_FS}" = "true" ]; then \
# move files that need to be writable so we can use tmpfs for them later
mkdir -p /usr/local/bootstrap/nginx /usr/local/bootstrap/modsecurity.d /usr/local/bootstrap/owasp-crs; \
mv "${NGINX_HOME}/"* /usr/local/bootstrap/nginx/; \
mv /etc/modsecurity.d/* /usr/local/bootstrap/modsecurity.d/; \
mv /opt/owasp-crs/* /usr/local/bootstrap/owasp-crs/; \
chown nginx:nginx \
"${NGINX_HOME}" \
/usr/local/bootstrap/*; \
else \
# only run this script in read-only configuration
rm /docker-entrypoint.d/0-move-writables.sh; \
fi; \
chown nginx:nginx \
/opt/owasp-crs \
/etc/modsecurity.d

USER nginx

Expand Down
13 changes: 13 additions & 0 deletions nginx/docker-entrypoint.d/0-move-writables.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
#!/bin/sh
# vim:sw=2:ts=2:sts=2:et

set -eu

LC_ALL=C
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin

cp -r /usr/local/bootstrap/nginx/* "${NGINX_HOME}/"
cp -r /usr/local/bootstrap/modsecurity.d/* /etc/modsecurity.d/
cp -r /usr/local/bootstrap/owasp-crs/* /opt/owasp-crs/

exit 0
Loading