bunkerweb 1.4.0

This commit is contained in:
bunkerity
2022-06-03 17:24:14 +02:00
parent 3a078326c5
commit a9f886804a
5245 changed files with 1432051 additions and 27894 deletions

View File

@@ -1,39 +0,0 @@
version: '3'
services:
mybunkerized:
image: bunkerity/bunkerized-nginx
restart: always
ports:
- 80:8080
- 443:8443
volumes:
- ./certs:/etc/letsencrypt
- ./www:/www:ro
- bunkerized-vol:/etc/nginx
environment:
- SERVER_NAME=
- MULTISITE=yes
- AUTO_LETS_ENCRYPT=yes
labels:
- "bunkerized-nginx.AUTOCONF"
networks:
- services-net
myautoconf:
image: bunkerity/bunkerized-nginx-autoconf
restart: always
volumes_from:
- mybunkerized
volumes:
- /var/run/docker.sock:/var/run/docker.sock:ro
depends_on:
- mybunkerized
volumes:
bunkerized-vol:
networks:
services-net:
name: services-net

View File

@@ -1,73 +0,0 @@
#!/bin/bash
# load some functions
. /opt/bunkerized-nginx/entrypoint/utils.sh
function do_and_check_cmd() {
if [ "$CHANGE_DIR" != "" ] ; then
cd "$CHANGE_DIR"
fi
if [ "$AS_ROOT" != "" ] ; then
output=$("$@" 2>&1)
else
output=$(su -s "/bin/bash" -c "$1" nginx 2>&1)
fi
ret="$?"
if [ $ret -ne 0 ] ; then
echo "[!] Error from command : $*"
echo "$output"
exit $ret
fi
echo "$output"
return 0
}
# Check if we are root
if [ $(id -u) -ne 0 ] ; then
echo "[!] Run me as root"
exit 1
fi
# Check if variables.env is present
if [ ! -f "/opt/bunkerized-nginx/variables.env" ] ; then
echo "[!] Missing /opt/bunkerized-nginx/variables.env"
exit 1
fi
# Run generator
echo "[*] Generate configuration files"
do_and_check_cmd "/opt/bunkerized-nginx/gen/main.py --settings /opt/bunkerized-nginx/settings.json --templates /opt/bunkerized-nginx/confs --output /etc/nginx --variables /opt/bunkerized-nginx/variables.env"
# Run temporary nginx if needed
status="$(systemctl status nginx 2>&1)"
if [ $? -ne 0 ] && [ "$(grep "^.*AUTO_LETS_ENCRYPT=yes$" /opt/bunkerized-nginx/variables.env)" != "" ] ; then
echo "[*] Run temp nginx"
do_and_check_cmd "cp /opt/bunkerized-nginx/confs/global/nginx-temp.conf /tmp/nginx-temp.conf"
replace_in_file "/tmp/nginx-temp.conf" "%USE_API%" ""
replace_in_file "/tmp/nginx-temp.conf" "%HTTP_PORT%" "80"
AS_ROOT="yes" do_and_check_cmd nginx -c /tmp/nginx-temp.conf -g 'user nginx;'
fi
# Run pre-jobs
echo "[*] Run jobs"
CHANGE_DIR=/tmp do_and_check_cmd "/opt/bunkerized-nginx/entrypoint/jobs.sh"
# Stop temp nginx
status="$(systemctl status nginx 2>&1)"
if [ $? -ne 0 ] && [ -f "/tmp/nginx-temp.pid" ] ; then
AS_ROOT="yes" do_and_check_cmd nginx -c /tmp/nginx-temp.conf -s quit
fi
# Reload nginx if it's running
status="$(systemctl status nginx 2>&1)"
if [ $? -eq 0 ] ; then
echo "[*] Reload nginx"
AS_ROOT="yes" do_and_check_cmd systemctl reload nginx
# Otherwise start it
else
echo "[*] Start nginx"
AS_ROOT="yes" do_and_check_cmd systemctl start nginx
fi
# Done
echo "[*] bunkerized-nginx successfully executed"

5
helpers/bwcli Normal file
View File

@@ -0,0 +1,5 @@
#!/bin/bash
/opt/bunkerweb/cli/main.py "$@"
exit $?

40
helpers/data.sh Normal file
View File

@@ -0,0 +1,40 @@
#!/bin/bash
. /opt/bunkerweb/helpers/utils.sh
log "$1" "" "Setup and check /data folder ..."
# Create folders if missing and check permissions
rwx_folders=("cache" "letsencrypt")
rx_folders=("configs" "configs/http" "configs/stream" "configs/server-http" "configs/server-stream" "configs/default-server-http" "configs/default-server-stream" "configs/modsec" "configs/modsec-crs" "plugins" "www")
for folder in "${rwx_folders[@]}" ; do
if [ ! -d "/data/${folder}" ] ; then
mkdir -p "/data/${folder}"
if [ $? -ne 0 ] ; then
log "$1" "❌" "Wrong permissions on /data (RWX needed for user nginx with uid 101 and gid 101)"
exit 1
fi
elif [ ! -r "/data/${folder}" ] || [ ! -w "/data/${folder}" ] || [ ! -x "/data/${folder}" ] ; then
log "$1" "❌" "Wrong permissions on /data/${folder} (RWX needed for user nginx with uid 101 and gid 101)"
exit 1
fi
done
for folder in "${rx_folders[@]}" ; do
if [ ! -d "/data/${folder}" ] ; then
mkdir -p "/data/${folder}"
if [ $? -ne 0 ] ; then
log "$1" "❌" "Wrong permissions on /data (RWX needed for user nginx with uid 101 and gid 101)"
exit 1
fi
elif [ ! -r "/data/${folder}" ] || [ ! -x "/data/${folder}" ] ; then
log "$1" "❌" "Wrong permissions on /data/${folder} (RX needed for user nginx with uid 101 and gid 101)"
exit 1
fi
done
# Check permissions on files
for file in $(find /data -type f) ; do
if [ ! -r "${file}" ] ; then
log "$1" "❌" "Wrong permissions on ${file} (at least R needed for user nginx with uid 101 and gid 101)"
exit 1
fi
done

View File

@@ -1,23 +0,0 @@
#!/bin/sh
# prepare folders
folders="www http-confs server-confs modsec-confs modsec-crs-confs cache pre-server-confs acme-challenge plugins"
for folder in $folders ; do
if [ -e "/opt/bunkerized-nginx/${folder}" ] ; then
rm -rf "/opt/bunkerized-nginx/${folder}"
fi
mkdir "/${folder}"
chown root:nginx "/${folder}"
chmod 770 "/${folder}"
ln -s "/$folder" "/opt/bunkerized-nginx/$folder"
done
mkdir -p /acme-challenge/.well-known/acme-challenge
chown -R root:nginx /acme-challenge
chmod -R 770 /acme-challenge
# prepare /var/log
rm -f /var/log/nginx/*
ln -s /proc/1/fd/2 /var/log/nginx/error.log
ln -s /proc/1/fd/2 /var/log/nginx/modsec_audit.log
ln -s /proc/1/fd/1 /var/log/nginx/access.log
ln -s /proc/1/fd/1 /var/log/nginx/jobs.log

104
helpers/entrypoint.sh Normal file
View File

@@ -0,0 +1,104 @@
#!/bin/bash
. /opt/bunkerweb/helpers/utils.sh
log "ENTRYPOINT" "" "Starting BunkerWeb v$(cat /opt/bunkerweb/VERSION) ..."
# setup and check /data folder
/opt/bunkerweb/helpers/data.sh "ENTRYPOINT"
# trap SIGTERM and SIGINT
function trap_exit() {
log "ENTRYPOINT" "" "Catched stop operation"
if [ -f "/opt/bunkerweb/tmp/scheduler.pid" ] ; then
log "ENTRYPOINT" "" "Stopping job scheduler ..."
kill -s TERM "$(cat /opt/bunkerweb/tmp/scheduler.pid)"
fi
log "ENTRYPOINT" "" "Stopping nginx ..."
/usr/sbin/nginx -s stop
}
trap "trap_exit" TERM INT QUIT
# trap SIGHUP
function trap_reload() {
log "ENTRYPOINT" "" "Catched reload operation"
/opt/bunkerweb/helpers/scheduler-restart.sh
if [ $? -ne 0 ] ; then
log "ENTRYPOINT" "" "Error while restarting scheduler"
fi
if [ -f /opt/bunkerweb/tmp/nginx.pid ] ; then
log "ENTRYPOINT" "" "Reloading nginx ..."
nginx -s reload
if [ $? -eq 0 ] ; then
log "ENTRYPOINT" "" "Reload successful"
else
log "ENTRYPOINT" "❌" "Reload failed"
fi
else
log "ENTRYPOINT" "⚠️" "Ignored reload operation because nginx is not running"
fi
}
trap "trap_reload" HUP
if [ "$SWARM_MODE" != "yes" ] && [ "$KUBERNETES_MODE" != "yes" ] && [ "$AUTOCONF_MODE" != "yes" ] ; then
# execute temp nginx with no server
export TEMP_NGINX="yes"
log "ENTRYPOINT" "" "Generating configuration for temp nginx ..."
env | grep -E -v "^(HOSTNAME|PWD|PKG_RELEASE|NJS_VERSION|SHLVL|PATH|_|NGINX_VERSION|HOME)=" > "/tmp/variables.env"
/opt/bunkerweb/gen/main.py --settings /opt/bunkerweb/settings.json --templates /opt/bunkerweb/confs --output /etc/nginx --variables /tmp/variables.env
if [ "$?" -ne 0 ] ; then
log "ENTRYPOINT" "❌" "Generator failed"
exit 1
fi
log "ENTRYPOINT" "" "Generator is successful"
log "ENTRYPOINT" "" "Starting temp nginx ..."
nginx
if [ $? -ne 0 ] ; then
log "ENTRYPOINT" "❌" "Temp nginx failed to start"
exit 1
fi
log "ENTRYPOINT" "" "Temp nginx started"
# execute jobs
log "ENTRYPOINT" "" "Executing jobs ..."
/opt/bunkerweb/job/main.py --variables /etc/nginx/variables.env --run
# stop temporary nginx
nginx -s quit
while [ -f /opt/bunkerweb/tmp/nginx-temp.pid ] ; do
sleep 1
done
fi
# generate final configuration
export TEMP_NGINX="no"
log "ENTRYPOINT" "" "Generating configuration ..."
env | grep -E -v "^(HOSTNAME|PWD|PKG_RELEASE|NJS_VERSION|SHLVL|PATH|_|NGINX_VERSION|HOME)=" > "/tmp/variables.env"
/opt/bunkerweb/gen/main.py --settings /opt/bunkerweb/settings.json --templates /opt/bunkerweb/confs --output /etc/nginx --variables /tmp/variables.env
if [ "$?" -ne 0 ] ; then
log "ENTRYPOINT" "❌" "Generator failed"
exit 1
fi
log "ENTRYPOINT" "" "Generator is successful"
# execute job scheduler
if [ "$SWARM_MODE" != "yes" ] && [ "$KUBERNETES_MODE" != "yes" ] && [ "$AUTOCONF_MODE" != "yes" ] ; then
log "ENTRYPOINT" "" "Executing job scheduler ..."
/opt/bunkerweb/job/main.py --variables /etc/nginx/variables.env &
else
log "ENTRYPOINT" "" "Skipped execution of job scheduler because BunkerWeb is running in cluster mode"
fi
# start nginx
log "ENTRYPOINT" "" "Starting nginx ..."
nginx -g "daemon off;" &
pid="$!"
# wait while nginx is running
wait "$pid"
while [ -f "/opt/bunkerweb/tmp/nginx.pid" ] ; do
wait "$pid"
done
log "ENTRYPOINT" "" "BunkerWeb stopped"
exit 0

16
helpers/healthcheck.sh Normal file
View File

@@ -0,0 +1,16 @@
#!/bin/bash
if [ -f /opt/bunkerweb/tmp/nginx-temp.pid ] ; then
exit 1
fi
if [ ! -f /opt/bunkerweb/tmp/nginx.pid ] ; then
exit 1
fi
check="$(curl -s -H "Host: healthcheck.bunkerweb.io" http://127.0.0.1:6000/healthz 2>&1)"
if [ $? -ne 0 ] || [ "$check" != "ok" ] ; then
exit 1
fi
exit 0

907
helpers/install.sh Executable file → Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -1,121 +0,0 @@
apiVersion: apps/v1
kind: DaemonSet
metadata:
name: bunkerized-nginx
labels:
app: bunkerized-nginx
spec:
selector:
matchLabels:
name: bunkerized-nginx
template:
metadata:
labels:
name: bunkerized-nginx
# this label is mandatory
bunkerized-nginx: "yes"
spec:
containers:
- name: bunkerized-nginx
image: bunkerity/bunkerized-nginx
ports:
- containerPort: 8080
hostPort: 80
- containerPort: 8443
hostPort: 443
env:
- name: KUBERNETES_MODE
value: "yes"
- name: DNS_RESOLVERS
value: "coredns.kube-system.svc.cluster.local"
- name: USE_API
value: "yes"
- name: API_URI
value: "/ChangeMeToSomethingHardToGuess"
- name: SERVER_NAME
value: ""
- name: MULTISITE
value: "yes"
---
apiVersion: v1
kind: Service
metadata:
name: bunkerized-nginx-service
# this label is mandatory
labels:
bunkerized-nginx: "yes"
# this annotation is mandatory
annotations:
bunkerized-nginx.AUTOCONF: "yes"
spec:
clusterIP: None
selector:
name: bunkerized-nginx
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: pvc-nginx
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 5Gi
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: bunkerized-nginx-ingress-controller
labels:
app: bunkerized-nginx-autoconf
spec:
replicas: 1
selector:
matchLabels:
app: bunkerized-nginx-autoconf
template:
metadata:
labels:
app: bunkerized-nginx-autoconf
spec:
serviceAccountName: bunkerized-nginx-ingress-controller
volumes:
- name: vol-nginx
persistentVolumeClaim:
claimName: pvc-nginx
initContainers:
- name: change-data-dir-permissions
command:
- chown
- -R
- 101:101
- /etc/letsencrypt
- /cache
image: busybox
volumeMounts:
- name: vol-nginx
mountPath: /etc/letsencrypt
subPath: letsencrypt
- name: vol-nginx
mountPath: /cache
subPath: cache
securityContext:
runAsNonRoot: false
runAsUser: 0
runAsGroup: 0
containers:
- name: bunkerized-nginx-autoconf
image: bunkerity/bunkerized-nginx-autoconf
env:
- name: KUBERNETES_MODE
value: "yes"
- name: API_URI
value: "/ChangeMeToSomethingHardToGuess"
volumeMounts:
- name: vol-nginx
mountPath: /etc/letsencrypt
subPath: letsencrypt
- name: vol-nginx
mountPath: /cache
subPath: cache

View File

@@ -1,30 +0,0 @@
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: bunkerized-nginx-ingress-controller
rules:
- apiGroups: [""]
resources: ["services", "pods"]
verbs: ["get", "watch", "list"]
- apiGroups: ["extensions"]
resources: ["ingresses"]
verbs: ["get", "watch", "list"]
---
apiVersion: v1
kind: ServiceAccount
metadata:
name: bunkerized-nginx-ingress-controller
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: bunkerized-nginx-ingress-controller
subjects:
- kind: ServiceAccount
name: bunkerized-nginx-ingress-controller
namespace: default
apiGroup: ""
roleRef:
kind: ClusterRole
name: bunkerized-nginx-ingress-controller
apiGroup: rbac.authorization.k8s.io

View File

@@ -0,0 +1,44 @@
#!/bin/bash
. /opt/bunkerweb/helpers/utils.sh
log "SCHEDULER" "" "Doing a restart ..."
# Kill the running scheduler
retry=0
if [ -f "/opt/bunkerweb/tmp/scheduler.pid" ] ; then
kill -s TERM "$(cat /opt/bunkerweb/tmp/scheduler.pid)"
ret=$?
if [ $? -ne 0 ] ; then
log "SCHEDULER" "❌" "Error while sending signal to running scheduler (exit status = $ret)"
exit 1
fi
while [ -f "/opt/bunkerweb/tmp/scheduler.pid" ] && [ $retry -lt 3 ] ; do
echo log "SCHEDULER" "" "Waiting for scheduler to stop ..."
sleep 5
retry=$((retry + 1))
done
if [ $retry -eq 3 ] ; then
log "SCHEDULER" "❌" "Timeout while waiting while waiting for scheduler to stop"
exit 1
fi
fi
# Run jobs once in foreground
log "SCHEDULER" "" "Executing jobs ..."
/opt/bunkerweb/job/main.py --variables /etc/nginx/variables.env --run
ret=$?
if [ $? -ne 0 ] ; then
log "SCHEDULER" "❌" "Error while running jobs (exit status = $ret)"
exit 1
fi
# Run jobs scheduler in background
/opt/bunkerweb/job/main.py --variables /etc/nginx/variables.env &
ret=$?
if [ $? -ne 0 ] ; then
log "SCHEDULER" "❌" "Error while running jobs (exit status = $ret)"
exit 1
fi
exit 0

View File

@@ -1,65 +0,0 @@
version: '3.8'
services:
nginx:
image: bunkerity/bunkerized-nginx
ports:
- published: 80
target: 8080
mode: host
protocol: tcp
- published: 443
target: 8443
mode: host
protocol: tcp
environment:
- SWARM_MODE=yes
- USE_API=yes
- API_URI=/ChangeMeToSomethingHardToGuess # must match API_URI from autoconf
- MULTISITE=yes
- SERVER_NAME=
- AUTO_LETS_ENCRYPT=yes
networks:
- bunkerized-net
- services-net
deploy:
mode: global
placement:
constraints:
- "node.role==worker"
# mandatory label
labels:
- "bunkerized-nginx.AUTOCONF"
autoconf:
image: bunkerity/bunkerized-nginx-autoconf
volumes:
- /var/run/docker.sock:/var/run/docker.sock:ro
- cache-vol:/cache
- certs-vol:/etc/letsencrypt
environment:
- SWARM_MODE=yes
- API_URI=/ChangeMeToSomethingHardToGuess # must match API_URI from nginx
networks:
- bunkerized-net
deploy:
replicas: 1
placement:
constraints:
- "node.role==manager"
# This will create the networks for you
networks:
bunkerized-net:
driver: overlay
attachable: true
name: bunkerized-net
services-net:
driver: overlay
attachable: true
name: services-net
# And the volumes too
volumes:
cache-vol:
certs-vol:

39
helpers/uninstall.sh Executable file → Normal file
View File

@@ -7,7 +7,7 @@ function do_and_check_cmd() {
output=$("$@" 2>&1)
ret="$?"
if [ $ret -ne 0 ] ; then
echo "[!] Error from command : $*"
echo " Error from command : $*"
echo "$output"
exit $ret
fi
@@ -18,7 +18,7 @@ function do_and_check_cmd() {
# Check if we are root
if [ $(id -u) -ne 0 ] ; then
echo "[!] Run me as root"
echo " Run me as root"
exit 1
fi
@@ -32,45 +32,40 @@ elif [ "$(grep CentOS /etc/os-release)" != "" ] ; then
OS="centos"
fi
if [ "$OS" = "" ] ; then
echo "[!] Unsupported Operating System"
echo " Unsupported Operating System"
exit 1
fi
# Stop nginx
systemctl status nginx > /dev/null 2>&1
if [ $? -eq 0 ] ; then
echo "[*] Stop nginx service"
echo " Stop nginx service"
do_and_check_cmd systemctl stop nginx
fi
# Reload old nginx.service file
echo "[*] Restore old nginx service"
echo " Restore old nginx service"
do_and_check_cmd mv /lib/systemd/system/nginx.service.bak /lib/systemd/system/nginx.service
do_and_check_cmd systemctl daemon-reload
# Remove UI service
systemctl status bunkerized-nginx-ui > /dev/null 2>&1
systemctl status bunkerweb-ui > /dev/null 2>&1
if [ $? -eq 0 ] ; then
echo "[*] Stop bunkerized-nginx-ui service"
systemctl status nginx > /dev/null 2>&1
do_and_check_cmd systemctl stop bunkerized-nginx-ui
echo " Stop bunkerweb-ui service"
do_and_check_cmd systemctl stop bunkerweb-ui
fi
echo "[*] Remove bunkerized-nginx-ui service"
do_and_check_cmd systemctl disable bunkerized-nginx-ui
do_and_check_cmd rm -f /lib/systemd/system/bunkerized-nginx-ui.service
echo " Remove bunkerweb-ui service"
do_and_check_cmd systemctl disable bunkerweb-ui
do_and_check_cmd rm -f /lib/systemd/system/bunkerweb-ui.service
do_and_check_cmd systemctl daemon-reload
do_and_check_cmd systemctl reset-failed
sed -i "s@nginx ALL=(root:root) NOPASSWD: /opt/bunkerized-nginx/ui/linux.sh@@" /etc/sudoers
do_and_check_cmd sed -i "s@nginx ALL=(root:root) NOPASSWD: /opt/bunkerweb/ui/linux.sh@@" /etc/sudoers
# Remove cron
echo "[*] Remove cron"
do_and_check_cmd rm -f /etc/crond.d/bunkerized-nginx
# Remove /opt/bunkerized-nginx
if [ -e "/opt/bunkerized-nginx" ] ; then
echo "[*] Remove /opt/bunkerized-nginx"
do_and_check_cmd rm -rf /opt/bunkerized-nginx
# Remove /opt/bunkerweb
if [ -e "/opt/bunkerweb" ] ; then
echo " Remove /opt/bunkerweb"
do_and_check_cmd rm -rf /opt/bunkerweb
fi
# We're done
echo "[*] bunkerized-nginx successfully uninstalled"
echo " BunkerWeb successfully uninstalled"

53
helpers/utils.sh Normal file
View File

@@ -0,0 +1,53 @@
#!/bin/bash
# check rx or rwx permissions on a folder
function check_permissions() {
if [ "$1" = "rx" ] ; then
[ -r "$2" ] && [ -x "$2" ]
return $?
fi
[ -r "$2" ] && [ -x "$2" ] && [ -w "$2" ]
return $?
}
# replace pattern in file
function replace_in_file() {
# escape slashes
pattern=$(echo "$2" | sed "s/\//\\\\\//g")
replace=$(echo "$3" | sed "s/\//\\\\\//g")
sed "s/$pattern/$replace/g" "$1" > /tmp/sed
cat /tmp/sed > "$1"
rm /tmp/sed
}
# convert space separated values to LUA
function spaces_to_lua() {
for element in $1 ; do
if [ "$result" = "" ] ; then
result="\"${element}\""
else
result="${result}, \"${element}\""
fi
done
echo "$result"
}
# check if at least one env var (global or multisite) has a specific value
function has_value() {
envs=$(find /etc/nginx -name "*.env")
for file in $envs ; do
if [ "$(grep "^${1}=${2}$" $file)" != "" ] ; then
echo "$file"
fi
done
}
# log to stdout
function log() {
when="$(date '+[%Y-%m-%d %H:%M:%S]')"
category="$1"
severity="$2"
message="$3"
echo "$when $category - $severity - $message"
}