9.0.2-debian-10-r3 release

This commit is contained in:
Bitnami Bot
2020-07-14 19:15:33 +00:00
parent 20499b95f1
commit 3a7daadd44
65 changed files with 5264 additions and 539 deletions

View File

@@ -1,41 +1,46 @@
FROM docker.io/bitnami/minideb:buster
LABEL maintainer "Bitnami <containers@bitnami.com>"
ENV PATH="/opt/bitnami/php/bin:/opt/bitnami/php/sbin:/opt/bitnami/apache/bin:/opt/bitnami/mysql/bin:/opt/bitnami/common/bin:/opt/bitnami/drupal/vendor/bin:/opt/bitnami/nami/bin:$PATH"
ENV HOME="/" \
OS_ARCH="amd64" \
OS_FLAVOUR="debian-10" \
OS_NAME="linux"
COPY prebuildfs /
# Install required system packages and dependencies
RUN install_packages ca-certificates curl dirmngr gnupg gzip libaudit1 libbsd0 libbz2-1.0 libc6 libcap-ng0 libcom-err2 libcurl4 libexpat1 libffi6 libfftw3-double3 libfontconfig1 libfreetype6 libgcc1 libgcrypt20 libglib2.0-0 libgmp10 libgnutls30 libgomp1 libgpg-error0 libgssapi-krb5-2 libhogweed4 libicu63 libidn2-0 libjemalloc2 libjpeg62-turbo libk5crypto3 libkeyutils1 libkrb5-3 libkrb5support0 liblcms2-2 libldap-2.4-2 liblqr-1-0 libltdl7 liblzma5 libmagickcore-6.q16-6 libmagickwand-6.q16-6 libmcrypt4 libmemcached11 libmemcachedutil2 libncurses6 libnettle6 libnghttp2-14 libp11-kit0 libpam0g libpcre3 libpng16-16 libpq5 libpsl5 libreadline7 librtmp1 libsasl2-2 libsqlite3-0 libssh2-1 libssl1.1 libstdc++6 libsybdb5 libtasn1-6 libtidy5deb1 libtinfo6 libunistring2 libuuid1 libx11-6 libxau6 libxcb1 libxdmcp6 libxext6 libxml2 libxslt1.1 libzip4 procps sudo tar zlib1g
RUN /build/bitnami-user.sh
RUN /build/install-nami.sh
RUN bitnami-pkg install php-7.3.20-0 --checksum 23abc614023c7937b0d2a65347e5f9d5cf0003783676fd7173ded7e9e6cc13f3
RUN bitnami-pkg unpack apache-2.4.43-5 --checksum e9faded57e3703fe9fcea650eb302e673d969a399fe9dfafa67e173465637665
RUN bitnami-pkg unpack mysql-client-10.3.23-1 --checksum efab843077267af6a8cde53440a1fef0acf8cb67ab1dcd0b6da2e9cbe050c7e1
RUN bitnami-pkg install libphp-7.3.20-0 --checksum 15fa4a11f2e11377ba0d6476ce22021349f62ef2fdfbe2af4f86dca10baaa997
RUN bitnami-pkg install tini-0.19.0-0 --checksum 9a8ae20be31a518f042fcec359f2cf35bfdb4e2a56f2fa8ff9ef2ecaf45da80c
RUN bitnami-pkg install gosu-1.12.0-1 --checksum 51cfb1b7fd7b05b8abd1df0278c698103a9b1a4964bdacd87ca1d5c01631d59c
RUN bitnami-pkg unpack drupal-9.0.2-0 --checksum 6674f3fa7f1add985efd1d69e5127b49ca21ec71d734e710b78469c10031e707
RUN install_packages acl ca-certificates curl dirmngr gnupg gzip libaudit1 libbsd0 libbz2-1.0 libc6 libcap-ng0 libcom-err2 libcurl4 libexpat1 libffi6 libfftw3-double3 libfontconfig1 libfreetype6 libgcc1 libgcrypt20 libglib2.0-0 libgmp10 libgnutls30 libgomp1 libgpg-error0 libgssapi-krb5-2 libhogweed4 libicu63 libidn2-0 libjemalloc2 libjpeg62-turbo libk5crypto3 libkeyutils1 libkrb5-3 libkrb5support0 liblcms2-2 libldap-2.4-2 liblqr-1-0 libltdl7 liblzma5 libmagickcore-6.q16-6 libmagickwand-6.q16-6 libmcrypt4 libmemcached11 libmemcachedutil2 libncurses6 libnettle6 libnghttp2-14 libp11-kit0 libpam0g libpcre3 libpng16-16 libpq5 libpsl5 libreadline7 librtmp1 libsasl2-2 libsqlite3-0 libssh2-1 libssl1.1 libstdc++6 libsybdb5 libtasn1-6 libtidy5deb1 libtinfo6 libunistring2 libuuid1 libx11-6 libxau6 libxcb1 libxdmcp6 libxext6 libxml2 libxslt1.1 libzip4 procps tar unzip zlib1g
RUN . /opt/bitnami/scripts/libcomponent.sh && component_unpack "php" "7.3.20-0" --checksum 23abc614023c7937b0d2a65347e5f9d5cf0003783676fd7173ded7e9e6cc13f3
RUN . /opt/bitnami/scripts/libcomponent.sh && component_unpack "apache" "2.4.43-5" --checksum e9faded57e3703fe9fcea650eb302e673d969a399fe9dfafa67e173465637665
RUN . /opt/bitnami/scripts/libcomponent.sh && component_unpack "mysql-client" "10.3.23-1" --checksum efab843077267af6a8cde53440a1fef0acf8cb67ab1dcd0b6da2e9cbe050c7e1
RUN . /opt/bitnami/scripts/libcomponent.sh && component_unpack "libphp" "7.3.20-0" --checksum 15fa4a11f2e11377ba0d6476ce22021349f62ef2fdfbe2af4f86dca10baaa997
RUN . /opt/bitnami/scripts/libcomponent.sh && component_unpack "render-template" "1.0.0-1" --checksum a94f94357aa06f3718db1550fa5f5188cd61383d66bf754eef49c58a18bf02cc
RUN . /opt/bitnami/scripts/libcomponent.sh && component_unpack "gosu" "1.12.0-1" --checksum 51cfb1b7fd7b05b8abd1df0278c698103a9b1a4964bdacd87ca1d5c01631d59c
RUN . /opt/bitnami/scripts/libcomponent.sh && component_unpack "drupal" "9.0.2-1" --checksum 7a998c3443183985b5aeb61e79d3da0185c138dbcf6cd2ccf9bdb5c320ceaa44
RUN apt-get update && apt-get upgrade -y && \
rm -r /var/lib/apt/lists /var/cache/apt/archives
RUN ln -sf /dev/stdout /opt/bitnami/apache/logs/access_log && \
ln -sf /dev/stderr /opt/bitnami/apache/logs/error_log
RUN chmod g+rwX /opt/bitnami
COPY rootfs /
RUN /opt/bitnami/scripts/apache/postunpack.sh
RUN /opt/bitnami/scripts/php/postunpack.sh
RUN /opt/bitnami/scripts/apache-modphp/postunpack.sh
RUN /opt/bitnami/scripts/drupal/postunpack.sh
RUN /opt/bitnami/scripts/mysql-client/postunpack.sh
ENV ALLOW_EMPTY_PASSWORD="no" \
APACHE_ENABLE_CUSTOM_PORTS="no" \
APACHE_HTTPS_PORT_NUMBER="443" \
APACHE_HTTP_PORT_NUMBER="80" \
APACHE_HTTPS_PORT_NUMBER="" \
APACHE_HTTP_PORT_NUMBER="" \
BITNAMI_APP_NAME="drupal" \
BITNAMI_IMAGE_VERSION="9.0.2-debian-10-r2" \
DRUPAL_DATABASE_NAME="bitnami_drupal" \
BITNAMI_IMAGE_VERSION="9.0.2-debian-10-r3" \
DRUPAL_DATABASE_NAME="" \
DRUPAL_DATABASE_PASSWORD="" \
DRUPAL_DATABASE_USER="bn_drupal" \
DRUPAL_EMAIL="user@example.com" \
DRUPAL_HTTPS_PORT="443" \
DRUPAL_HTTP_PORT="80" \
DRUPAL_PASSWORD="bitnami" \
DRUPAL_PROFILE="standard" \
DRUPAL_USERNAME="user" \
DRUPAL_DATABASE_USER="" \
DRUPAL_EMAIL="" \
DRUPAL_HTTPS_PORT="" \
DRUPAL_HTTP_PORT="" \
DRUPAL_PASSWORD="" \
DRUPAL_PROFILE="" \
DRUPAL_USERNAME="" \
MARIADB_HOST="mariadb" \
MARIADB_PORT_NUMBER="3306" \
MARIADB_ROOT_PASSWORD="" \
@@ -46,12 +51,11 @@ ENV ALLOW_EMPTY_PASSWORD="no" \
MYSQL_CLIENT_CREATE_DATABASE_USER="" \
MYSQL_CLIENT_ENABLE_SSL="no" \
MYSQL_CLIENT_SSL_CA_FILE="" \
OS_ARCH="amd64" \
OS_FLAVOUR="debian-10" \
OS_NAME="linux" \
PHP_MEMORY_LIMIT="256M"
PATH="/opt/bitnami/php/bin:/opt/bitnami/php/sbin:/opt/bitnami/apache/bin:/opt/bitnami/mysql/bin:/opt/bitnami/common/bin:/opt/bitnami/drupal/vendor/bin:$PATH" \
PHP_MEMORY_LIMIT=""
EXPOSE 80 443
EXPOSE 8080 8443
ENTRYPOINT [ "/app-entrypoint.sh" ]
CMD [ "httpd", "-f", "/opt/bitnami/apache/conf/httpd.conf", "-DFOREGROUND" ]
USER 1001
ENTRYPOINT [ "/opt/bitnami/scripts/drupal/entrypoint.sh" ]
CMD [ "/opt/bitnami/scripts/apache/run.sh" ]

View File

@@ -1,5 +1,4 @@
version: '2'
services:
mariadb:
image: 'docker.io/bitnami/mariadb:10.3-debian-10'
@@ -8,20 +7,20 @@ services:
- MARIADB_USER=bn_drupal
- MARIADB_DATABASE=bitnami_drupal
volumes:
- 'mariadb_data:/bitnami'
- 'mariadb_data:/bitnami/mariadb'
drupal:
image: 'docker.io/bitnami/drupal:9-debian-10'
ports:
- '80:8080'
- '443:8443'
environment:
- MARIADB_HOST=mariadb
- MARIADB_PORT_NUMBER=3306
- DRUPAL_DATABASE_HOST=mariadb
- DRUPAL_DATABASE_PORT_NUMBER=3306
- DRUPAL_DATABASE_USER=bn_drupal
- DRUPAL_DATABASE_NAME=bitnami_drupal
- ALLOW_EMPTY_PASSWORD=yes
ports:
- '80:80'
- '443:443'
volumes:
- 'drupal_data:/bitnami'
- 'drupal_data:/bitnami/drupal'
depends_on:
- mariadb
volumes:

View File

@@ -1,6 +0,0 @@
#!/bin/bash
useradd -ms /bin/bash bitnami
mkdir -p /opt/bitnami
sed -i -e 's/\s*Defaults\s*secure_path\s*=/# Defaults secure_path=/' /etc/sudoers
echo 'bitnami ALL=NOPASSWD: ALL' >> /etc/sudoers

View File

@@ -1,7 +0,0 @@
#!/bin/bash
curl --silent -L https://nami-prod.s3.amazonaws.com/tools/nami/releases/nami-2.0.0-0-linux-x64.tar.gz > /tmp/nami-linux-x64.tar.gz
echo "63e836f3d752cb157b175e1efe2238e5b4e04ab139097c682ca5a0651f0df65c /tmp/nami-linux-x64.tar.gz" | sha256sum --check
mkdir -p /opt/bitnami/nami /opt/bitnami/licenses
tar xzf /tmp/nami-linux-x64.tar.gz --strip 1 -C /opt/bitnami/nami && rm /tmp/nami-linux-x64.tar.gz
curl --silent -L https://raw.githubusercontent.com/bitnami/nami/master/COPYING > /opt/bitnami/licenses/nami-2.0.0-0.txt

View File

@@ -1,120 +0,0 @@
#!/bin/bash
[[ ${BASH_DEBUG:-false} = true ]] && set -x
# Constants
MODULE="$(basename "$0")"
BITNAMI_PREFIX=/opt/bitnami
# Color Palette
RESET='\033[0m'
BOLD='\033[1m'
## Foreground
BLACK='\033[38;5;0m'
RED='\033[38;5;1m'
GREEN='\033[38;5;2m'
YELLOW='\033[38;5;3m'
BLUE='\033[38;5;4m'
MAGENTA='\033[38;5;5m'
CYAN='\033[38;5;6m'
WHITE='\033[38;5;7m'
## Background
ON_BLACK='\033[48;5;0m'
ON_RED='\033[48;5;1m'
ON_GREEN='\033[48;5;2m'
ON_YELLOW='\033[48;5;3m'
ON_BLUE='\033[48;5;4m'
ON_MAGENTA='\033[48;5;5m'
ON_CYAN='\033[48;5;6m'
ON_WHITE='\033[48;5;7m'
# Functions
########################
# Print to STDERR
# Arguments:
# Message to print
# Returns:
# None
#########################
stderr_print() {
printf "%b\\n" "${*}" >&2
}
########################
# Log message
# Arguments:
# Message to log
# Returns:
# None
#########################
log() {
stderr_print "${NAMI_DEBUG:+${CYAN}${MODULE:-} ${MAGENTA}$(date "+%T.%2N ")}${RESET}${*}"
}
########################
# Log an 'info' message
# Arguments:
# Message to log
# Returns:
# None
#########################
info() {
log "${GREEN}INFO ${RESET} ==> ${*}"
}
########################
# Log message
# Arguments:
# Message to log
# Returns:
# None
#########################
warn() {
log "${YELLOW}WARN ${RESET} ==> ${*}"
}
########################
# Log an 'error' message
# Arguments:
# Message to log
# Returns:
# None
#########################
error() {
log "${RED}ERROR${RESET} ==> ${*}"
}
########################
# Print the welcome page
# Globals:
# DISABLE_WELCOME_MESSAGE
# BITNAMI_APP_NAME
# Arguments:
# None
# Returns:
# None
#########################
print_welcome_page() {
if [[ -z "${DISABLE_WELCOME_MESSAGE:-}" ]]; then
if [[ -n "$BITNAMI_APP_NAME" ]]; then
print_image_welcome_page
fi
fi
}
########################
# Print the welcome page for a Bitnami Docker image
# Globals:
# BITNAMI_APP_NAME
# Arguments:
# None
# Returns:
# None
#########################
print_image_welcome_page() {
local github_url="https://github.com/bitnami/bitnami-docker-${BITNAMI_APP_NAME}"
log ""
log "${BOLD}Welcome to the Bitnami ${BITNAMI_APP_NAME} container${RESET}"
log "Subscribe to project updates by watching ${BOLD}${github_url}${RESET}"
log "Submit issues and feature requests at ${BOLD}${github_url}/issues${RESET}"
log ""
}

View File

@@ -1,40 +0,0 @@
#!/bin/bash
. /opt/bitnami/base/functions
########################
# Helper function to initialize a single nami module
# Arguments:
# Module to initialize
# Returns:
# None
# Description:
# Initialize an unpacked nami module with the `nami initialize` command.
# Command arguments can be specified as function argumnts after the module name.
# `--log-level trace` flag is added to the command if `NAMI_DEBUG` env variable exists.
# The log level can be overriden using the `NAMI_LOG_LEVEL` env variable.
#########################
nami_initialize_one() {
local module="${1:?module not specified}"
if nami inspect $module | grep -q '"lifecycle": "unpacked"'; then
local inputs=
if [[ -f "/${module}-inputs.json" ]]; then
inputs="--inputs-file=/${module}-inputs.json"
fi
nami ${NAMI_DEBUG:+--log-level ${NAMI_LOG_LEVEL:-trace}} initialize $module $inputs "${@:2}"
fi
}
########################
# Helper function to initialize one or more nami modules
# Arguments:
# Module to initialize
# Returns:
# None
#########################
nami_initialize() {
local module="${1:?module not specified}"
for module in "${@}"; do
nami_initialize_one $module
done
}

View File

@@ -0,0 +1,51 @@
#!/bin/bash
#
# Bitnami custom library
# shellcheck disable=SC1091
# Load Generic Libraries
. /opt/bitnami/scripts/liblog.sh
# Constants
BOLD='\033[1m'
# Functions
########################
# Print the welcome page
# Globals:
# DISABLE_WELCOME_MESSAGE
# BITNAMI_APP_NAME
# Arguments:
# None
# Returns:
# None
#########################
print_welcome_page() {
if [[ -z "${DISABLE_WELCOME_MESSAGE:-}" ]]; then
if [[ -n "$BITNAMI_APP_NAME" ]]; then
print_image_welcome_page
fi
fi
}
########################
# Print the welcome page for a Bitnami Docker image
# Globals:
# BITNAMI_APP_NAME
# Arguments:
# None
# Returns:
# None
#########################
print_image_welcome_page() {
local github_url="https://github.com/bitnami/bitnami-docker-${BITNAMI_APP_NAME}"
log ""
log "${BOLD}Welcome to the Bitnami ${BITNAMI_APP_NAME} container${RESET}"
log "Subscribe to project updates by watching ${BOLD}${github_url}${RESET}"
log "Submit issues and feature requests at ${BOLD}${github_url}/issues${RESET}"
log ""
}

View File

@@ -0,0 +1,69 @@
#!/bin/bash
#
# Library for managing Bitnami components
# Constants
CACHE_ROOT="/tmp/bitnami/pkg/cache"
DOWNLOAD_URL="https://downloads.bitnami.com/files/stacksmith"
# Functions
########################
# Download and unpack a Bitnami package
# Globals:
# OS_NAME
# OS_ARCH
# OS_FLAVOUR
# Arguments:
# $1 - component's name
# $2 - component's version
# Returns:
# None
#########################
component_unpack() {
local name="${1:?name is required}"
local version="${2:?version is required}"
local base_name="${name}-${version}-${OS_NAME}-${OS_ARCH}-${OS_FLAVOUR}"
local package_sha256=""
local directory="/opt/bitnami"
# Validate arguments
shift 2
while [ "$#" -gt 0 ]; do
case "$1" in
-c|--checksum)
shift
package_sha256="${1:?missing package checksum}"
;;
*)
echo "Invalid command line flag $1" >&2
return 1
;;
esac
shift
done
echo "Downloading $base_name package"
if [ -f "${CACHE_ROOT}/${base_name}.tar.gz" ]; then
echo "${CACHE_ROOT}/${base_name}.tar.gz already exists, skipping download."
cp "${CACHE_ROOT}/${base_name}.tar.gz" .
rm "${CACHE_ROOT}/${base_name}.tar.gz"
if [ -f "${CACHE_ROOT}/${base_name}.tar.gz.sha256" ]; then
echo "Using the local sha256 from ${CACHE_ROOT}/${base_name}.tar.gz.sha256"
package_sha256="$(< "${CACHE_ROOT}/${base_name}.tar.gz.sha256")"
rm "${CACHE_ROOT}/${base_name}.tar.gz.sha256"
fi
else
curl --remote-name --silent "${DOWNLOAD_URL}/${base_name}.tar.gz"
fi
if [ -n "$package_sha256" ]; then
echo "Verifying package integrity"
echo "$package_sha256 ${base_name}.tar.gz" | sha256sum --check -
fi
tar --directory "${directory}" --extract --gunzip --file "${base_name}.tar.gz" --no-same-owner --strip-components=2 "${base_name}/files/"
rm "${base_name}.tar.gz"
# Include metadata about the package
touch "${directory}/.bitnami_packages"
echo "$base_name" >> "${directory}/.bitnami_packages"
}

View File

@@ -0,0 +1,80 @@
#!/bin/bash
#
# Library for managing files
# Functions
########################
# Replace a regex in a file
# Arguments:
# $1 - filename
# $2 - match regex
# $3 - substitute regex
# $4 - use POSIX regex. Default: true
# Returns:
# None
#########################
replace_in_file() {
local filename="${1:?filename is required}"
local match_regex="${2:?match regex is required}"
local substitute_regex="${3:?substitute regex is required}"
local posix_regex=${4:-true}
local result
# We should avoid using 'sed in-place' substitutions
# 1) They are not compatible with files mounted from ConfigMap(s)
# 2) We found incompatibility issues with Debian10 and "in-place" substitutions
del=$'\001' # Use a non-printable character as a 'sed' delimiter to avoid issues
if [[ $posix_regex = true ]]; then
result="$(sed -E "s${del}${match_regex}${del}${substitute_regex}${del}g" "$filename")"
else
result="$(sed "s${del}${match_regex}${del}${substitute_regex}${del}g" "$filename")"
fi
echo "$result" > "$filename"
}
########################
# Remove a line in a file based on a regex
# Arguments:
# $1 - filename
# $2 - match regex
# $3 - use POSIX regex. Default: true
# Returns:
# None
#########################
remove_in_file() {
local filename="${1:?filename is required}"
local match_regex="${2:?match regex is required}"
local posix_regex=${3:-true}
local result
# We should avoid using 'sed in-place' substitutions
# 1) They are not compatible with files mounted from ConfigMap(s)
# 2) We found incompatibility issues with Debian10 and "in-place" substitutions
if [[ $posix_regex = true ]]; then
result="$(sed -E "/$match_regex/d" "$filename")"
else
result="$(sed "/$match_regex/d" "$filename")"
fi
echo "$result" > "$filename"
}
########################
# Appends text after the last line matching a pattern
# Arguments:
# $1 - file
# $2 - match regex
# $3 - contents to add
# Returns:
# None
#########################
append_file_after_last_match() {
local file="${1:?missing file}"
local match_regex="${2:?missing pattern}"
local value="${3:?missing value}"
# We read the file in reverse, replace the first match (0,/pattern/s) and then reverse the results again
result="$(tac "$file" | sed -E "0,/($match_regex)/s||${value}\n\1|" | tac)"
echo "$result" > "$file"
}

View File

@@ -0,0 +1,183 @@
#!/bin/bash
#
# Library for file system actions
# shellcheck disable=SC1091
# Load Generic Libraries
. /opt/bitnami/scripts/liblog.sh
# Functions
########################
# Ensure a file/directory is owned (user and group) but the given user
# Arguments:
# $1 - filepath
# $2 - owner
# Returns:
# None
#########################
owned_by() {
local path="${1:?path is missing}"
local owner="${2:?owner is missing}"
chown "$owner":"$owner" "$path"
}
########################
# Ensure a directory exists and, optionally, is owned by the given user
# Arguments:
# $1 - directory
# $2 - owner
# Returns:
# None
#########################
ensure_dir_exists() {
local dir="${1:?directory is missing}"
local owner="${2:-}"
mkdir -p "${dir}"
if [[ -n $owner ]]; then
owned_by "$dir" "$owner"
fi
}
########################
# Checks whether a directory is empty or not
# arguments:
# $1 - directory
# returns:
# boolean
#########################
is_dir_empty() {
local dir="${1:?missing directory}"
if [[ ! -e "$dir" ]] || [[ -z "$(ls -A "$dir")" ]]; then
true
else
false
fi
}
########################
# Checks whether a mounted directory is empty or not
# arguments:
# $1 - directory
# returns:
# boolean
#########################
is_mounted_dir_empty() {
local dir="${1:?missing directory}"
if is_dir_empty "$dir" || find "$dir" -mindepth 1 -maxdepth 1 -not -name ".snapshot" -not -name "lost+found" -exec false {} +; then
true
else
false
fi
}
########################
# Checks whether a file can be written to or not
# arguments:
# $1 - file
# returns:
# boolean
#########################
is_file_writable() {
local file="${1:?missing file}"
local dir
dir="$(dirname "$file")"
if [[ ( -f "$file" && -w "$file" ) || ( ! -f "$file" && -d "$dir" && -w "$dir" ) ]]; then
true
else
false
fi
}
########################
# Relativize a path
# arguments:
# $1 - path
# $2 - base
# returns:
# None
#########################
relativize() {
local -r path="${1:?missing path}"
local -r base="${2:?missing base}"
pushd "$base" >/dev/null
realpath -q --no-symlinks --relative-base="$base" "$path" | sed -e 's|^/$|.|' -e 's|^/||'
popd >/dev/null
}
########################
# Configure permisions and ownership recursively
# Globals:
# None
# Arguments:
# $1 - paths (as a string).
# Flags:
# -f|--file-mode - mode for directories.
# -d|--dir-mode - mode for files.
# -u|--user - user
# -g|--group - group
# Returns:
# None
#########################
configure_permissions_ownership() {
local -r paths="${1:?paths is missing}"
local dir_mode=""
local file_mode=""
local user=""
local group=""
# Validate arguments
shift 1
while [ "$#" -gt 0 ]; do
case "$1" in
-f|--file-mode)
shift
file_mode="${1:?missing mode for files}"
;;
-d|--dir-mode)
shift
dir_mode="${1:?missing mode for directories}"
;;
-u|--user)
shift
user="${1:?missing user}"
;;
-g|--group)
shift
group="${1:?missing group}"
;;
*)
echo "Invalid command line flag $1" >&2
return 1
;;
esac
shift
done
read -r -a filepaths <<< "$paths"
for p in "${filepaths[@]}"; do
if [[ -e "$p" ]]; then
if [[ -n $dir_mode ]]; then
find -L "$p" -type d -exec chmod "$dir_mode" {} \;
fi
if [[ -n $file_mode ]]; then
find -L "$p" -type f -exec chmod "$file_mode" {} \;
fi
if [[ -n $user ]] && [[ -n $group ]]; then
chown -LR "$user":"$group" "$p"
elif [[ -n $user ]] && [[ -z $group ]]; then
chown -LR "$user" "$p"
elif [[ -z $user ]] && [[ -n $group ]]; then
chgrp -LR "$group" "$p"
fi
else
stderr_print "$p does not exist"
fi
done
}

View File

@@ -0,0 +1,110 @@
#!/bin/bash
#
# Library for logging functions
# Constants
RESET='\033[0m'
RED='\033[38;5;1m'
GREEN='\033[38;5;2m'
YELLOW='\033[38;5;3m'
MAGENTA='\033[38;5;5m'
CYAN='\033[38;5;6m'
# Functions
########################
# Print to STDERR
# Arguments:
# Message to print
# Returns:
# None
#########################
stderr_print() {
# 'is_boolean_yes' is defined in libvalidations.sh, but depends on this file so we cannot source it
local bool="${BITNAMI_QUIET:-false}"
# comparison is performed without regard to the case of alphabetic characters
shopt -s nocasematch
if ! [[ "$bool" = 1 || "$bool" =~ ^(yes|true)$ ]]; then
printf "%b\\n" "${*}" >&2
fi
}
########################
# Log message
# Arguments:
# Message to log
# Returns:
# None
#########################
log() {
stderr_print "${CYAN}${MODULE:-} ${MAGENTA}$(date "+%T.%2N ")${RESET}${*}"
}
########################
# Log an 'info' message
# Arguments:
# Message to log
# Returns:
# None
#########################
info() {
log "${GREEN}INFO ${RESET} ==> ${*}"
}
########################
# Log message
# Arguments:
# Message to log
# Returns:
# None
#########################
warn() {
log "${YELLOW}WARN ${RESET} ==> ${*}"
}
########################
# Log an 'error' message
# Arguments:
# Message to log
# Returns:
# None
#########################
error() {
log "${RED}ERROR${RESET} ==> ${*}"
}
########################
# Log a 'debug' message
# Globals:
# BITNAMI_DEBUG
# Arguments:
# None
# Returns:
# None
#########################
debug() {
# 'is_boolean_yes' is defined in libvalidations.sh, but depends on this file so we cannot source it
local bool="${BITNAMI_DEBUG:-false}"
# comparison is performed without regard to the case of alphabetic characters
shopt -s nocasematch
if [[ "$bool" = 1 || "$bool" =~ ^(yes|true)$ ]]; then
log "${MAGENTA}DEBUG${RESET} ==> ${*}"
fi
}
########################
# Indent a string
# Arguments:
# $1 - string
# $2 - number of indentation characters (default: 4)
# $3 - indentation character (default: " ")
# Returns:
# None
#########################
indent() {
local string="${1:-}"
local num="${2:?missing num}"
local char="${3:-" "}"
# Build the indentation unit string
local indent_unit=""
for ((i = 0; i < num; i++)); do
indent_unit="${indent_unit}${char}"
done
echo "$string" | sed "s/^/${indent_unit}/"
}

View File

@@ -0,0 +1,140 @@
#!/bin/bash
#
# Library for network functions
# shellcheck disable=SC1091
# Load Generic Libraries
. /opt/bitnami/scripts/liblog.sh
# Functions
########################
# Resolve dns
# Arguments:
# $1 - Hostname to resolve
# Returns:
# IP
#########################
dns_lookup() {
local host="${1:?host is missing}"
getent ahosts "$host" | awk '/STREAM/ {print $1 }'
}
#########################
# Wait for a hostname and return the IP
# Arguments:
# $1 - hostname
# $2 - number of retries
# $3 - seconds to wait between retries
# Returns:
# - IP address that corresponds to the hostname
#########################
wait_for_dns_lookup() {
local hostname="${1:?hostname is missing}"
local retries="${2:-5}"
local seconds="${3:-1}"
check_host() {
if [[ $(dns_lookup "$hostname") == "" ]]; then
false
else
true
fi
}
# Wait for the host to be ready
retry_while "check_host ${hostname}" "$retries" "$seconds"
dns_lookup "$hostname"
}
########################
# Get machine's IP
# Arguments:
# None
# Returns:
# Machine IP
#########################
get_machine_ip() {
local -a ip_addresses
local hostname
hostname="$(hostname)"
read -r -a ip_addresses <<< "$(dns_lookup "$hostname" | xargs echo)"
if [[ "${#ip_addresses[@]}" -gt 1 ]]; then
warn "Found more than one IP address associated to hostname ${hostname}: ${ip_addresses[*]}, will use ${ip_addresses[0]}"
elif [[ "${#ip_addresses[@]}" -lt 1 ]]; then
error "Could not find any IP address associated to hostname ${hostname}"
exit 1
fi
echo "${ip_addresses[0]}"
}
########################
# Check if the provided argument is a resolved hostname
# Arguments:
# $1 - Value to check
# Returns:
# Boolean
#########################
is_hostname_resolved() {
local -r host="${1:?missing value}"
if [[ -n "$(dns_lookup "$host")" ]]; then
true
else
false
fi
}
########################
# Parse URL
# Globals:
# None
# Arguments:
# $1 - uri - String
# $2 - component to obtain. Valid options (scheme, authority, userinfo, host, port, path, query or fragment) - String
# Returns:
# String
parse_uri() {
local uri="${1:?uri is missing}"
local component="${2:?component is missing}"
# Solution based on https://tools.ietf.org/html/rfc3986#appendix-B with
# additional sub-expressions to split authority into userinfo, host and port
# Credits to Patryk Obara (see https://stackoverflow.com/a/45977232/6694969)
local -r URI_REGEX='^(([^:/?#]+):)?(//((([^@/?#]+)@)?([^:/?#]+)(:([0-9]+))?))?(/([^?#]*))?(\?([^#]*))?(#(.*))?'
# || | ||| | | | | | | | | |
# |2 scheme | ||6 userinfo 7 host | 9 port | 11 rpath | 13 query | 15 fragment
# 1 scheme: | |5 userinfo@ 8 :... 10 path 12 ?... 14 #...
# | 4 authority
# 3 //...
local index=0
case "$component" in
scheme)
index=2
;;
authority)
index=4
;;
userinfo)
index=6
;;
host)
index=7
;;
port)
index=9
;;
path)
index=10
;;
query)
index=13
;;
fragment)
index=14
;;
*)
stderr_print "unrecognized component $component"
return 1
;;
esac
[[ "$uri" =~ $URI_REGEX ]] && echo "${BASH_REMATCH[${index}]}"
}

View File

@@ -0,0 +1,291 @@
#!/bin/bash
#
# Library for operating system actions
# shellcheck disable=SC1091
# Load Generic Libraries
. /opt/bitnami/scripts/liblog.sh
# Functions
########################
# Check if an user exists in the system
# Arguments:
# $1 - user
# Returns:
# Boolean
#########################
user_exists() {
local user="${1:?user is missing}"
id "$user" >/dev/null 2>&1
}
########################
# Check if a group exists in the system
# Arguments:
# $1 - group
# Returns:
# Boolean
#########################
group_exists() {
local group="${1:?group is missing}"
getent group "$group" >/dev/null 2>&1
}
########################
# Create a group in the system if it does not exist already
# Arguments:
# $1 - group
# Returns:
# None
#########################
ensure_group_exists() {
local group="${1:?group is missing}"
if ! group_exists "$group"; then
groupadd "$group" >/dev/null 2>&1
fi
}
########################
# Create an user in the system if it does not exist already
# Arguments:
# $1 - user
# $2 - group
# Returns:
# None
#########################
ensure_user_exists() {
local user="${1:?user is missing}"
local group="${2:-}"
if ! user_exists "$user"; then
useradd "$user" >/dev/null 2>&1
fi
if [[ -n "$group" ]]; then
ensure_group_exists "$group"
usermod -a -G "$group" "$user" >/dev/null 2>&1
fi
}
########################
# Check if the script is currently running as root
# Arguments:
# $1 - user
# $2 - group
# Returns:
# Boolean
#########################
am_i_root() {
if [[ "$(id -u)" = "0" ]]; then
true
else
false
fi
}
########################
# Get total memory available
# Arguments:
# None
# Returns:
# Memory in bytes
#########################
get_total_memory() {
echo $(($(grep MemTotal /proc/meminfo | awk '{print $2}') / 1024))
}
########################
# Get machine size depending on specified memory
# Globals:
# None
# Arguments:
# None
# Flags:
# --memory - memory size (optional)
# Returns:
# Detected instance size
#########################
get_machine_size() {
local memory=""
# Validate arguments
while [[ "$#" -gt 0 ]]; do
case "$1" in
--memory)
shift
memory="${1:?missing memory}"
;;
*)
echo "Invalid command line flag $1" >&2
return 1
;;
esac
shift
done
if [[ -z "$memory" ]]; then
debug "Memory was not specified, detecting available memory automatically"
memory="$(get_total_memory)"
fi
sanitized_memory=$(convert_to_mb "$memory")
if [[ "$sanitized_memory" -gt 26000 ]]; then
echo 2xlarge
elif [[ "$sanitized_memory" -gt 13000 ]]; then
echo xlarge
elif [[ "$sanitized_memory" -gt 6000 ]]; then
echo large
elif [[ "$sanitized_memory" -gt 3000 ]]; then
echo medium
elif [[ "$sanitized_memory" -gt 1500 ]]; then
echo small
else
echo micro
fi
}
########################
# Get machine size depending on specified memory
# Globals:
# None
# Arguments:
# $1 - memory size (optional)
# Returns:
# Detected instance size
#########################
get_supported_machine_sizes() {
echo micro small medium large xlarge 2xlarge
}
########################
# Convert memory size from string to amount of megabytes (i.e. 2G -> 2048)
# Globals:
# None
# Arguments:
# $1 - memory size
# Returns:
# Result of the conversion
#########################
convert_to_mb() {
local amount="${1:-}"
if [[ $amount =~ ^([0-9]+)(m|M|g|G) ]]; then
size="${BASH_REMATCH[1]}"
unit="${BASH_REMATCH[2]}"
if [[ "$unit" = "g" || "$unit" = "G" ]]; then
amount="$((size * 1024))"
else
amount="$size"
fi
fi
echo "$amount"
}
#########################
# Redirects output to /dev/null if debug mode is disabled
# Globals:
# BITNAMI_DEBUG
# Arguments:
# $@ - Command to execute
# Returns:
# None
#########################
debug_execute() {
if ${BITNAMI_DEBUG:-false}; then
"$@"
else
"$@" >/dev/null 2>&1
fi
}
########################
# Retries a command a given number of times
# Arguments:
# $1 - cmd (as a string)
# $2 - max retries. Default: 12
# $3 - sleep between retries (in seconds). Default: 5
# Returns:
# Boolean
#########################
retry_while() {
local cmd="${1:?cmd is missing}"
local retries="${2:-12}"
local sleep_time="${3:-5}"
local return_value=1
read -r -a command <<< "$cmd"
for ((i = 1 ; i <= retries ; i+=1 )); do
"${command[@]}" && return_value=0 && break
sleep "$sleep_time"
done
return $return_value
}
########################
# Generate a random string
# Arguments:
# -t|--type - String type (ascii, alphanumeric, numeric), defaults to ascii
# -c|--count - Number of characters, defaults to 32
# Arguments:
# None
# Returns:
# None
# Returns:
# String
#########################
generate_random_string() {
local type="ascii"
local count="32"
local filter
local result
# Validate arguments
while [[ "$#" -gt 0 ]]; do
case "$1" in
-t|--type)
shift
type="$1"
;;
-c|--count)
shift
count="$1"
;;
*)
echo "Invalid command line flag $1" >&2
return 1
;;
esac
shift
done
# Validate type
case "$type" in
ascii)
filter="[:print:]"
;;
alphanumeric)
filter="a-zA-Z0-9"
;;
numeric)
filter="0-9"
;;
*)
echo "Invalid type ${type}" >&2
return 1
esac
# Obtain count + 10 lines from /dev/urandom to ensure that the resulting string has the expected size
# Note there is a very small chance of strings starting with EOL character
# Therefore, the higher amount of lines read, this will happen less frequently
result="$(head -n "$((count + 10))" /dev/urandom | tr -dc "$filter" | head -c "$count")"
echo "$result"
}
########################
# Create md5 hash from a string
# Arguments:
# $1 - string
# Returns:
# md5 hash - string
#########################
generate_md5_hash() {
local -r str="${1:?missing input string}"
echo -n "$str" | md5sum | awk '{print $1}'
}

View File

@@ -0,0 +1,122 @@
#!/bin/bash
#
# Bitnami persistence library
# Used for bringing persistence capabilities to applications that don't have clear separation of data and logic
# shellcheck disable=SC1091
# Load Generic Libraries
. /opt/bitnami/scripts/libfs.sh
. /opt/bitnami/scripts/libos.sh
. /opt/bitnami/scripts/liblog.sh
. /opt/bitnami/scripts/libversion.sh
# Functions
########################
# Persist an application directory
# Globals:
# BITNAMI_ROOT_DIR
# BITNAMI_VOLUME_DIR
# Arguments:
# $1 - App folder name
# $2 - List of app files to persist
# Returns:
# true if all steps succeeded, false otherwise
#########################
persist_app() {
local -r app="${1:?missing app}"
local -a files_to_restore
read -r -a files_to_persist <<< "$2"
local -r install_dir="${BITNAMI_ROOT_DIR}/${app}"
local -r persist_dir="${BITNAMI_VOLUME_DIR}/${app}"
# Persist the individual files
if [[ "${#files_to_persist[@]}" -lt 0 ]]; then
warn "No files are configured to be persisted"
return
fi
pushd "$install_dir" >/dev/null
local file_to_persist_relative file_to_persist_destination file_to_persist_destination_folder
local -r tmp_file="/tmp/perms.acl"
for file_to_persist in "${files_to_persist[@]}"; do
if [[ ! -f "$file_to_persist" && ! -d "$file_to_persist" ]]; then
error "Cannot persist '${file_to_persist}' because it does not exist"
return 1
fi
file_to_persist_relative="$(relativize "$file_to_persist" "$install_dir")"
file_to_persist_destination="${persist_dir}/${file_to_persist_relative}"
file_to_persist_destination_folder="$(dirname "$file_to_persist_destination")"
# Get original permissions for existing files, which will be applied later
# Exclude the root directory with 'sed', to avoid issues when copying the entirety of it to a volume
getfacl -R "$file_to_persist_relative" | sed -E '/# file: (\..+|[^.])/,$!d' > "$tmp_file"
# Copy directories to the volume
ensure_dir_exists "$file_to_persist_destination_folder"
cp -Lr --preserve=links "$file_to_persist_relative" "$file_to_persist_destination_folder"
# Restore permissions
pushd "$persist_dir" >/dev/null
if am_i_root; then
setfacl --restore="$tmp_file"
else
# When running as non-root, don't change ownership
setfacl --restore=<(grep -E -v '^# (owner|group):' "$tmp_file")
fi
popd >/dev/null
done
popd >/dev/null
rm -f "$tmp_file"
# Install the persisted files into the installation directory, via symlinks
restore_persisted_app "$@"
}
########################
# Restore a persisted application directory
# Globals:
# BITNAMI_ROOT_DIR
# BITNAMI_VOLUME_DIR
# FORCE_MAJOR_UPGRADE
# Arguments:
# $1 - App folder name
# $2 - List of app files to restore
# Returns:
# true if all steps succeeded, false otherwise
#########################
restore_persisted_app() {
local -r app="${1:?missing app}"
local -a files_to_restore
read -r -a files_to_restore <<< "$2"
local -r install_dir="${BITNAMI_ROOT_DIR}/${app}"
local -r persist_dir="${BITNAMI_VOLUME_DIR}/${app}"
# Restore the individual persisted files
if [[ "${#files_to_restore[@]}" -lt 0 ]]; then
warn "No persisted files are configured to be restored"
return
fi
local file_to_restore_relative file_to_restore_origin file_to_restore_destination
for file_to_restore in "${files_to_restore[@]}"; do
file_to_restore_relative="$(relativize "$file_to_restore" "$install_dir")"
# We use 'realpath --no-symlinks' to ensure that the case of '.' is covered and the directory is removed
file_to_restore_origin="$(realpath --no-symlinks "${install_dir}/${file_to_restore_relative}")"
file_to_restore_destination="$(realpath --no-symlinks "${persist_dir}/${file_to_restore_relative}")"
rm -rf "$file_to_restore_origin"
ln -sfn "$file_to_restore_destination" "$file_to_restore_origin"
done
}
########################
# Check if an application directory was already persisted
# Globals:
# BITNAMI_VOLUME_DIR
# Arguments:
# $1 - App folder name
# Returns:
# true if all steps succeeded, false otherwise
#########################
is_app_initialized() {
local -r app="${1:?missing app}"
local -r persist_dir="${BITNAMI_VOLUME_DIR}/${app}"
if ! is_mounted_dir_empty "$persist_dir"; then
true
else
false
fi
}

View File

@@ -0,0 +1,205 @@
#!/bin/bash
#
# Library for managing services
# shellcheck disable=SC1091
# Load Generic Libraries
. /opt/bitnami/scripts/libvalidations.sh
# Functions
########################
# Read the provided pid file and returns a PID
# Arguments:
# $1 - Pid file
# Returns:
# PID
#########################
get_pid_from_file() {
local pid_file="${1:?pid file is missing}"
if [[ -f "$pid_file" ]]; then
if [[ -n "$(< "$pid_file")" ]] && [[ "$(< "$pid_file")" -gt 0 ]]; then
echo "$(< "$pid_file")"
fi
fi
}
########################
# Check if a provided PID corresponds to a running service
# Arguments:
# $1 - PID
# Returns:
# Boolean
#########################
is_service_running() {
local pid="${1:?pid is missing}"
kill -0 "$pid" 2>/dev/null
}
########################
# Stop a service by sending a termination signal to its pid
# Arguments:
# $1 - Pid file
# $2 - Signal number (optional)
# Returns:
# None
#########################
stop_service_using_pid() {
local pid_file="${1:?pid file is missing}"
local signal="${2:-}"
local pid
pid="$(get_pid_from_file "$pid_file")"
[[ -z "$pid" ]] || ! is_service_running "$pid" && return
if [[ -n "$signal" ]]; then
kill "-${signal}" "$pid"
else
kill "$pid"
fi
local counter=10
while [[ "$counter" -ne 0 ]] && is_service_running "$pid"; do
sleep 1
counter=$((counter - 1))
done
}
########################
# Start cron daemon
# Arguments:
# None
# Returns:
# true if started correctly, false otherwise
#########################
cron_start() {
if [[ -x "/usr/sbin/cron" ]]; then
/usr/sbin/cron
elif [[ -x "/usr/sbin/crond" ]]; then
/usr/sbin/crond
else
false
fi
}
########################
# Generate a cron configuration file for a given service
# Arguments:
# $1 - Service name
# $2 - Command
# Flags:
# --run-as - User to run as (default: root)
# --schedule - Cron schedule configuration (default: * * * * *)
# Returns:
# None
#########################
generate_cron_conf() {
local service_name="${1:?service name is missing}"
local cmd="${2:?command is missing}"
local run_as="root"
local schedule="* * * * *"
# Parse optional CLI flags
shift 2
while [[ "$#" -gt 0 ]]; do
case "$1" in
--run-as)
shift
run_as="$1"
;;
--schedule)
shift
schedule="$1"
;;
*)
echo "Invalid command line flag ${1}" >&2
return 1
;;
esac
shift
done
mkdir -p /etc/cron.d
echo "${schedule} ${run_as} ${cmd}" > /etc/cron.d/"$service_name"
}
########################
# Generate a monit configuration file for a given service
# Arguments:
# $1 - Service name
# $2 - Pid file
# $3 - Start command
# $4 - Stop command
# Flags:
# --disabled - Whether to disable the monit configuration
# Returns:
# None
#########################
generate_monit_conf() {
local service_name="${1:?service name is missing}"
local pid_file="${2:?pid file is missing}"
local start_command="${3:?start command is missing}"
local stop_command="${4:?stop command is missing}"
local monit_conf_dir="/etc/monit/conf.d"
local disabled="no"
# Parse optional CLI flags
shift 4
while [[ "$#" -gt 0 ]]; do
case "$1" in
--disabled)
shift
disabled="$1"
;;
*)
echo "Invalid command line flag ${1}" >&2
return 1
;;
esac
shift
done
is_boolean_yes "$disabled" && conf_suffix=".disabled"
mkdir -p "$monit_conf_dir"
cat >"${monit_conf_dir}/${service_name}.conf${conf_suffix:-}" <<EOF
check process ${service_name}
with pidfile "${pid_file}"
start program = "${start_command}" with timeout 90 seconds
stop program = "${stop_command}" with timeout 90 seconds
EOF
}
########################
# Generate a logrotate configuration file
# Arguments:
# $1 - Log path
# $2 - Period
# $3 - Number of rotations to store
# $4 - Extra options (Optional)
# Returns:
# None
#########################
generate_logrotate_conf() {
local service_name="${1:?service name is missing}"
local log_path="${2:?log path is missing}"
local period="${3:-weekly}"
local rotations="${4:-150}"
local extra_options="${5:-}"
local logrotate_conf_dir="/etc/logrotate.d"
mkdir -p "$logrotate_conf_dir"
cat >"${logrotate_conf_dir}/${service_name}" <<EOF
${log_path} {
${period}
rotate ${rotations}
dateext
compress
copytruncate
missingok
${extra_options}
}
EOF
}

View File

@@ -0,0 +1,248 @@
#!/bin/bash
#
# Validation functions library
# shellcheck disable=SC1091
# Load Generic Libraries
. /opt/bitnami/scripts/liblog.sh
# Functions
########################
# Check if the provided argument is an integer
# Arguments:
# $1 - Value to check
# Returns:
# Boolean
#########################
is_int() {
local -r int="${1:?missing value}"
if [[ "$int" =~ ^-?[0-9]+ ]]; then
true
else
false
fi
}
########################
# Check if the provided argument is a positive integer
# Arguments:
# $1 - Value to check
# Returns:
# Boolean
#########################
is_positive_int() {
local -r int="${1:?missing value}"
if is_int "$int" && (( "${int}" >= 0 )); then
true
else
false
fi
}
########################
# Check if the provided argument is a boolean or is the string 'yes/true'
# Arguments:
# $1 - Value to check
# Returns:
# Boolean
#########################
is_boolean_yes() {
local -r bool="${1:-}"
# comparison is performed without regard to the case of alphabetic characters
shopt -s nocasematch
if [[ "$bool" = 1 || "$bool" =~ ^(yes|true)$ ]]; then
true
else
false
fi
}
########################
# Check if the provided argument is a boolean yes/no value
# Arguments:
# $1 - Value to check
# Returns:
# Boolean
#########################
is_yes_no_value() {
local -r bool="${1:-}"
if [[ "$bool" =~ ^(yes|no)$ ]]; then
true
else
false
fi
}
########################
# Check if the provided argument is a boolean true/false value
# Arguments:
# $1 - Value to check
# Returns:
# Boolean
#########################
is_true_false_value() {
local -r bool="${1:-}"
if [[ "$bool" =~ ^(true|false)$ ]]; then
true
else
false
fi
}
########################
# Check if the provided argument is an empty string or not defined
# Arguments:
# $1 - Value to check
# Returns:
# Boolean
#########################
is_empty_value() {
local -r val="${1:-}"
if [[ -z "$val" ]]; then
true
else
false
fi
}
########################
# Validate if the provided argument is a valid port
# Arguments:
# $1 - Port to validate
# Returns:
# Boolean and error message
#########################
validate_port() {
local value
local unprivileged=0
# Parse flags
while [[ "$#" -gt 0 ]]; do
case "$1" in
-unprivileged)
unprivileged=1
;;
--)
shift
break
;;
-*)
stderr_print "unrecognized flag $1"
return 1
;;
*)
break
;;
esac
shift
done
if [[ "$#" -gt 1 ]]; then
echo "too many arguments provided"
return 2
elif [[ "$#" -eq 0 ]]; then
stderr_print "missing port argument"
return 1
else
value=$1
fi
if [[ -z "$value" ]]; then
echo "the value is empty"
return 1
else
if ! is_int "$value"; then
echo "value is not an integer"
return 2
elif [[ "$value" -lt 0 ]]; then
echo "negative value provided"
return 2
elif [[ "$value" -gt 65535 ]]; then
echo "requested port is greater than 65535"
return 2
elif [[ "$unprivileged" = 1 && "$value" -lt 1024 ]]; then
echo "privileged port requested"
return 3
fi
fi
}
########################
# Validate if the provided argument is a valid IPv4 address
# Arguments:
# $1 - IP to validate
# Returns:
# Boolean
#########################
validate_ipv4() {
local ip="${1:?ip is missing}"
local stat=1
if [[ $ip =~ ^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$ ]]; then
read -r -a ip_array <<< "$(tr '.' ' ' <<< "$ip")"
[[ ${ip_array[0]} -le 255 && ${ip_array[1]} -le 255 \
&& ${ip_array[2]} -le 255 && ${ip_array[3]} -le 255 ]]
stat=$?
fi
return $stat
}
########################
# Validate a string format
# Arguments:
# $1 - String to validate
# Returns:
# Boolean
#########################
validate_string() {
local string
local min_length=-1
local max_length=-1
# Parse flags
while [ "$#" -gt 0 ]; do
case "$1" in
-min-length)
shift
min_length=${1:-}
;;
-max-length)
shift
max_length=${1:-}
;;
--)
shift
break
;;
-*)
stderr_print "unrecognized flag $1"
return 1
;;
*)
break
;;
esac
shift
done
if [ "$#" -gt 1 ]; then
stderr_print "too many arguments provided"
return 2
elif [ "$#" -eq 0 ]; then
stderr_print "missing string"
return 1
else
string=$1
fi
if [[ "$min_length" -ge 0 ]] && [[ "${#string}" -lt "$min_length" ]]; then
echo "string length is less than $min_length"
return 1
fi
if [[ "$max_length" -ge 0 ]] && [[ "${#string}" -gt "$max_length" ]]; then
echo "string length is great than $max_length"
return 1
fi
}

View File

@@ -0,0 +1,49 @@
#!/bin/bash
#
# Library for managing versions strings
# shellcheck disable=SC1091
# Load Generic Libraries
. /opt/bitnami/scripts/liblog.sh
# Functions
########################
# Gets semantic version
# Arguments:
# $1 - version: string to extract major.minor.patch
# $2 - section: 1 to extract major, 2 to extract minor, 3 to extract patch
# Returns:
# array with the major, minor and release
#########################
get_sematic_version () {
local version="${1:?version is required}"
local section="${2:?section is required}"
local -a version_sections
#Regex to parse versions: x.y.z
local -r regex='([0-9]+)(\.([0-9]+)(\.([0-9]+))?)?'
if [[ "$version" =~ $regex ]]; then
local i=1
local j=1
local n=${#BASH_REMATCH[*]}
while [[ $i -lt $n ]]; do
if [[ -n "${BASH_REMATCH[$i]}" ]] && [[ "${BASH_REMATCH[$i]:0:1}" != '.' ]]; then
version_sections[$j]=${BASH_REMATCH[$i]}
((j++))
fi
((i++))
done
local number_regex='^[0-9]+$'
if [[ "$section" =~ $number_regex ]] && (( $section > 0 )) && (( $section <= 3 )); then
echo "${version_sections[$section]}"
return
else
stderr_print "Section allowed values are: 1, 2, and 3"
return 1
fi
fi
}

View File

@@ -0,0 +1,364 @@
#!/bin/bash
#
# Bitnami web server handler library
# shellcheck disable=SC1091
# Load generic libraries
. /opt/bitnami/scripts/liblog.sh
# Load web server libraries
[[ -f "/opt/bitnami/scripts/libapache.sh" ]] && . /opt/bitnami/scripts/libapache.sh
[[ -f "/opt/bitnami/scripts/libnginx.sh" ]] && . /opt/bitnami/scripts/libnginx.sh
# Load environment for all configured web servers
[[ -f "/opt/bitnami/scripts/apache-env.sh" ]] && . /opt/bitnami/scripts/apache-env.sh
[[ -f "/opt/bitnami/scripts/nginx-env.sh" ]] && . /opt/bitnami/scripts/nginx-env.sh
########################
# Prints the currently-enabled web server type
# Globals:
# WEB_SERVER_TYPE
# Arguments:
# None
# Returns:
# None
#########################
web_server_type() {
echo "$WEB_SERVER_TYPE"
}
########################
# Validate that a supported web server is configured
# Globals:
# WEB_SERVER_*
# Arguments:
# None
# Returns:
# None
#########################
web_server_validate() {
local error_code=0
local supported_web_servers=("apache" "nginx")
# Auxiliary functions
print_validation_error() {
error "$1"
error_code=1
}
if [[ -z "$(web_server_type)" || ! " ${supported_web_servers[*]} " == *" $(web_server_type) "* ]]; then
print_validation_error "Could not detect any supported web servers. It must be one of: ${supported_web_servers[*]}"
elif ! type -t "is_$(web_server_type)_running" >/dev/null; then
print_validation_error "Could not load the $(web_server_type) web server library from /opt/bitnami/scripts. Check that it exists and is readable."
fi
return "$error_code"
}
########################
# Check whether the web server is running
# Globals:
# *
# Arguments:
# None
# Returns:
# true if the web server is running, false otherwise
#########################
is_web_server_running() {
"is_$(web_server_type)_running"
}
########################
# Start web server
# Globals:
# *
# Arguments:
# None
# Returns:
# None
#########################
web_server_start() {
"${BITNAMI_ROOT_DIR}/scripts/$(web_server_type)/start.sh"
}
########################
# Stop web server
# Globals:
# *
# Arguments:
# None
# Returns:
# None
#########################
web_server_stop() {
"${BITNAMI_ROOT_DIR}/scripts/$(web_server_type)/stop.sh"
}
########################
# Restart web server
# Globals:
# *
# Arguments:
# None
# Returns:
# None
#########################
web_server_restart() {
"${BITNAMI_ROOT_DIR}/scripts/$(web_server_type)/restart.sh"
}
########################
# Reload web server
# Globals:
# *
# Arguments:
# None
# Returns:
# None
#########################
web_server_reload() {
"${BITNAMI_ROOT_DIR}/scripts/$(web_server_type)/reload.sh"
}
########################
# Ensure a web server application configuration exists (i.e. Apache virtual host format or NGINX server block)
# It serves as a wrapper for the specific web server function
# Globals:
# *
# Arguments:
# $1 - App name
# Flags:
# --hosts - Hosts to enable
# --type - Application type, which has an effect on which configuration template to use
# --allow-remote-connections - Whether to allow remote connections or to require local connections
# --disabled - Whether to render the file with a .disabled prefix
# --enable-https - Enable app configuration on HTTPS port
# --http-port - HTTP port number
# --https-port - HTTPS port number
# --document-root - Path to document root directory
# Apache-specific flags:
# --apache-additional-configuration - Additional vhost configuration (no default)
# --apache-before-vhost-configuration - Configuration to add before the <VirtualHost> directive (no default)
# --apache-allow-override - Whether to allow .htaccess files (only allowed when --move-htaccess is set to 'no')
# --apache-extra-directory-configuration - Extra configuration for the document root directory
# --apache-move-htaccess - Move .htaccess files to a common place so they can be loaded during Apache startup
# NGINX-specific flags:
# --nginx-additional-configuration - Additional server block configuration (no default)
# Returns:
# true if the configuration was enabled, false otherwise
########################
ensure_web_server_app_configuration_exists() {
local app="${1:?missing app}"
local -a args=("$app")
# Validate arguments
shift
while [[ "$#" -gt 0 ]]; do
case "$1" in
# Common flags
--hosts \
| --type \
| --allow-remote-connections \
| --disabled \
| --enable-https \
| --http-port \
| --https-port \
| --document-root \
)
args+=("$1" "${2:?missing value}")
shift
;;
# Specific Apache flags
--apache-additional-configuration \
| --apache-before-vhost-configuration \
| --apache-allow-override \
| --apache-extra-directory-configuration \
| --apache-move-htaccess \
)
[[ "$(web_server_type)" == "apache" ]] && args+=("${1//apache-/}" "${2:?missing value}")
shift
;;
# Specific NGINX flags
--nginx-additional-configuration)
[[ "$(web_server_type)" == "nginx" ]] && args+=("${1//nginx-/}" "${2:?missing value}")
shift
;;
*)
echo "Invalid command line flag $1" >&2
return 1
;;
esac
shift
done
"ensure_$(web_server_type)_app_configuration_exists" "${args[@]}"
}
########################
# Ensure a web server application configuration does not exist anymore (i.e. Apache virtual host format or NGINX server block)
# It serves as a wrapper for the specific web server function
# Globals:
# *
# Arguments:
# $1 - App name
# Returns:
# true if the configuration was disabled, false otherwise
########################
ensure_web_server_app_configuration_not_exists() {
local app="${1:?missing app}"
"ensure_$(web_server_type)_app_configuration_not_exists" "$app"
}
########################
# Ensure the web server loads the configuration for an application in a URL prefix
# It serves as a wrapper for the specific web server function
# Globals:
# *
# Arguments:
# $1 - App name
# Flags:
# --allow-remote-connections - Whether to allow remote connections or to require local connections
# --document-root - Path to document root directory
# --prefix - URL prefix from where it will be accessible (i.e. /myapp)
# --type - Application type, which has an effect on what configuration template will be used
# Apache-specific flags:
# --apache-additional-configuration - Additional vhost configuration (no default)
# --apache-allow-override - Whether to allow .htaccess files (only allowed when --move-htaccess is set to 'no')
# --apache-extra-directory-configuration - Extra configuration for the document root directory
# --apache-move-htaccess - Move .htaccess files to a common place so they can be loaded during Apache startup
# NGINX-specific flags:
# --nginx-additional-configuration - Additional server block configuration (no default)
# Returns:
# true if the configuration was enabled, false otherwise
########################
ensure_web_server_prefix_configuration_exists() {
local app="${1:?missing app}"
local -a args=("$app")
# Validate arguments
shift
while [[ "$#" -gt 0 ]]; do
case "$1" in
# Common flags
--allow-remote-connections \
| --document-root \
| --prefix \
| --type \
)
args+=("$1" "${2:?missing value}")
shift
;;
# Specific Apache flags
--apache-additional-configuration \
| --apache-allow-override \
| --apache-extra-directory-configuration \
| --apache-move-htaccess \
)
[[ "$(web_server_type)" == "apache" ]] && args+=("${1//apache-/}" "$2")
shift
;;
# Specific NGINX flags
--nginx-additional-configuration)
[[ "$(web_server_type)" == "nginx" ]] && args+=("${1//nginx-/}" "$2")
shift
;;
*)
echo "Invalid command line flag $1" >&2
return 1
;;
esac
shift
done
"ensure_$(web_server_type)_prefix_configuration_exists" "${args[@]}"
}
########################
# Ensure a web server application configuration is updated with the runtime configuration (i.e. ports)
# It serves as a wrapper for the specific web server function
# Globals:
# *
# Arguments:
# $1 - App name
# Flags:
# --hosts - Hosts to enable
# --enable-https - Update HTTPS app configuration
# --http-port - HTTP port number
# --https-port - HTTPS port number
# Returns:
# true if the configuration was updated, false otherwise
########################
web_server_update_app_configuration() {
local app="${1:?missing app}"
local -a args=("$app")
# Validate arguments
shift
while [[ "$#" -gt 0 ]]; do
case "$1" in
# Common flags
--hosts \
| --enable-https \
| --http-port \
| --https-port \
)
args+=("$1" "${2:?missing value}")
shift
;;
*)
echo "Invalid command line flag $1" >&2
return 1
;;
esac
shift
done
"$(web_server_type)_update_app_configuration" "${args[@]}"
}
########################
# Enable loading page, which shows users that the initialization process is not yet completed
# Globals:
# *
# Arguments:
# None
# Returns:
# None
#########################
web_server_enable_loading_page() {
ensure_web_server_app_configuration_exists "__loading" --hosts "_default_" \
--apache-additional-configuration "
# Show a HTTP 503 Service Unavailable page by default
RedirectMatch 503 ^/$
# Show index.html if server is answering with 404 Not Found or 503 Service Unavailable status codes
ErrorDocument 404 /index.html
ErrorDocument 503 /index.html" \
--nginx-additional-configuration "
# Show a HTTP 503 Service Unavailable page by default
location / {
return 503;
}
# Show index.html if server is answering with 404 Not Found or 503 Service Unavailable status codes
error_page 404 @installing;
error_page 503 @installing;
location @installing {
rewrite ^(.*)$ /index.html break;
}"
web_server_reload
}
########################
# Enable loading page, which shows users that the initialization process is not yet completed
# Globals:
# *
# Arguments:
# None
# Returns:
# None
#########################
web_server_disable_install_page() {
ensure_web_server_app_configuration_not_exists "__loading"
web_server_reload
}

View File

@@ -1,215 +0,0 @@
#!/bin/bash -e
. /opt/bitnami/base/functions
print_usage() {
log "Usage: bitnami-pkg <COMMAND> <PACKAGE>-<VERSION> [OPTIONS] -- [ARGS]"
log ""
log "Download and install Bitnami packages"
log ""
log "Commands:"
log " install Download and install a package."
log " unpack Download and unpack a package."
log ""
log "Options:"
log " -b, --bucket Package release bucket (default: stacksmith)."
log " -c, --checksum SHA256 verification checksum."
log " -h, --help Show this help message and exit."
log ""
log "If the package is already available in the /tmp/bitnami/pkg/cache/"
log "directory, the download will be skipped. If there is a corresponding"
log "file of the same name post-fixed with .sha256 in the directory,"
log "that sha will be used instead of the --checksum option."
log ""
log "Examples:"
log " - Unpack package"
log " \$ bitnami-pkg unpack nginx-1.9.10-0"
log ""
log " - Verify and Install package"
log " \$ bitnami-pkg install nginx-1.9.10-0 --checksum 15565d06b18c2e3710fc08e579ddb3d0e39aa663264a0f7404f0743cb4cdb58d"
log ""
log " - Install package with arguments"
log " \$ bitnami-pkg install mariadb-10.1.11-0 -- --password bitnami"
log ""
log " - Install package from testing"
log " \$ bitnami-pkg install mariadb-10.1.11-0 --bucket testing"
log ""
}
identify_distro() {
distro="${IMAGE_OS:-unknown}"
if [ "${distro}" == "unknown" -a -f /etc/os-release ]; then
distro="$(grep "^ID=" /etc/os-release | cut -d'=' -f2 | cut -d'"' -f2)-$(grep "^VERSION_ID=" /etc/os-release | cut -d'=' -f2 | cut -d'"' -f2 | cut -d'.' -f1)"
fi
echo "$distro"
}
identify_arch() {
local arch=$(uname -m)
case "${arch}" in
ppc64le)
;; # no-op
x86_64)
case $(identify_distro) in
debian-*)
arch=amd64
;;
ol-*)
arch=x86_64
;;
centos-*)
arch=x86_64
;;
rhel-*)
arch=x86_64
;;
photon-*)
arch=x86_64
;;
esac
;;
*)
arch="unknown"
;;
esac
echo $arch
}
# break up command line for easy parsing and check legal options
ARGS=$(getopt -o b:c:h -l "bucket:,checksum:,help" -n "bitnami-pkg" -- "$@")
if [ $? -ne 0 ];
then
exit 1
fi
eval set -- "$ARGS";
while true; do
case "$1" in
-b|--bucket)
shift
if [ -n "$1" ]; then
RELEASE_BUCKET=$1
shift
fi
;;
-c|--checksum)
shift
if [ -n "$1" ]; then
PACKAGE_SHA256=$1
shift
fi
;;
-h|--help)
print_usage
exit 0
;;
--)
shift
break
;;
esac
done
# weed out unrecognized commands
case "$1" in
install|unpack) ;;
*)
error "Unrecognized command: $1"
print_usage
exit 1
;;
esac
# install/unpack command need to be supplied a package name
if [ $# -lt 2 ]; then
print_usage
exit 1
fi
INSTALL_ROOT=/tmp/bitnami/pkg/install
CACHE_ROOT=/tmp/bitnami/pkg/cache
PACKAGE="$2-linux-$(identify_arch)-$(identify_distro)"
PACKAGE_ARGS=${@:3}
PACKAGE_NAME=$(echo $PACKAGE | sed 's/-[0-9].*//')
RELEASE_BUCKET=${RELEASE_BUCKET:-stacksmith}
mkdir -p $INSTALL_ROOT
cd $INSTALL_ROOT
info "Downloading $PACKAGE package"
if [ -f $CACHE_ROOT/$PACKAGE.tar.gz ]; then
info "$CACHE_ROOT/$PACKAGE.tar.gz already exists, skipping download."
cp $CACHE_ROOT/$PACKAGE.tar.gz .
if [ -f $CACHE_ROOT/$PACKAGE.tar.gz.sha256 ]; then
info "Using the local sha256 from $CACHE_ROOT/$PACKAGE.tar.gz.sha256"
PACKAGE_SHA256=$(cat $CACHE_ROOT/$PACKAGE.tar.gz.sha256)
fi
else
# display cURL progress bar when a tty is attached
if tty -s; then
CURL_ARGS="-#"
else
CURL_ARGS="-sS"
fi
if ! curl $CURL_ARGS -LOf "https://downloads.bitnami.com/files/$RELEASE_BUCKET/$PACKAGE.tar.gz"; then
warn "Package name '$PACKAGE' does not exist, will try '${PACKAGE%-$(identify_distro)}'..."
if curl $CURL_ARGS -LOf "https://downloads.bitnami.com/files/$RELEASE_BUCKET/${PACKAGE%-$(identify_distro)}.tar.gz"; then
PACKAGE="${PACKAGE%-$(identify_distro)}"
else
error "Could not find the requested package..."
exit 1
fi
fi
fi
if ! tar tzf $PACKAGE.tar.gz >/dev/null 2>&1; then
error "Invalid or corrupt '$PACKAGE' package."
exit 1
fi
if [ "$PACKAGE_SHA256" ]; then
info "Verifying package integrity"
echo "$PACKAGE_SHA256 $PACKAGE.tar.gz" | sha256sum -c -
fi
# If the tarball has too many files, it can trigger a bug
# in overlayfs when using tar. Install bsdtar in the container image
# to workaround it. As the overhead is too big (~40 MB), it is not added by
# default. Source: https://github.com/coreos/bugs/issues/1095
if which bsdtar >/dev/null 2>&1; then
bsdtar -xf $PACKAGE.tar.gz
else
tar xzf $PACKAGE.tar.gz
fi
case "$1" in
install) info "Installing $PACKAGE" ;;
unpack) info "Unpacking $PACKAGE" ;;
esac
nami $1 $PACKAGE $PACKAGE_ARGS
rm -rf $INSTALL_ROOT
if [ "$BITNAMI_PKG_EXTRA_DIRS" ]; then
info "Creating extra directories"
for i in ${BITNAMI_PKG_EXTRA_DIRS}; do
mkdir -p $i
done
fi
if [ "$BITNAMI_PKG_CHMOD" ]; then
DIRS="/.nami /bitnami $BITNAMI_PKG_EXTRA_DIRS"
if ! [[ $PACKAGE_NAME =~ .*-client ]]; then
mkdir -p /bitnami/$PACKAGE_NAME
fi
# We need to be in $HOME in order to nami inspect works
cd $HOME
DIRS+=" $(nami inspect $PACKAGE_NAME | grep -e '"installdir"' | cut -f4 -d\")"
info "Fixing permissions: chmod $BITNAMI_PKG_CHMOD $DIRS"
chmod $BITNAMI_PKG_CHMOD $DIRS
fi
# Include metadata about the package
touch "${BITNAMI_PREFIX}/.bitnami_packages"
echo "${PACKAGE}" >> "${BITNAMI_PREFIX}/.bitnami_packages"

View File

@@ -1,24 +0,0 @@
#!/bin/bash
# Check whether Apache ports must be configured
if [[ -n "${APACHE_HTTP_PORT_NUMBER:-}" || -n "${APACHE_HTTPS_PORT_NUMBER:-}" ]]; then
export APACHE_ENABLE_CUSTOM_PORTS="yes"
fi
# Copy vhosts file
if [[ "$(ls -A /vhosts 2>/dev/null)" ]]; then
info "Found vhost definitions in /vhosts. Copying them to /opt/bitnami/apache/conf/vhosts"
cp -r /vhosts/* /opt/bitnami/apache/conf/vhosts
fi
# Mount certificate files
if [[ -d "/opt/bitnami/apache/certs" ]]; then
warn "The directory '/opt/bitnami/apache/certs' was externally mounted. This is a legacy configuration and will be deprecated soon. Please mount certificate files at '/opt/bitnami/apache/conf/bitnami/certs' instead. Find an example at: https://github.com/bitnami/bitnami-docker-apache#using-custom-ssl-certificates"
warn "Restoring certificates at '/opt/bitnami/apache/certs' to '/opt/bitnami/apache/conf/bitnami/certs'..."
rm -rf /opt/bitnami/apache/conf/bitnami/certs
ln -sf /opt/bitnami/apache/certs /opt/bitnami/apache/conf/bitnami/certs
elif [ "$(ls -A /certs 2>/dev/null)" ]; then
info "Mounting certificates files from /certs..."
rm -rf /opt/bitnami/apache/conf/bitnami/certs
ln -sf /certs /opt/bitnami/apache/conf/bitnami/certs
fi

View File

@@ -1,5 +0,0 @@
{
"enableCustomPorts": "{{$global.env.APACHE_ENABLE_CUSTOM_PORTS}}",
"httpPort": "{{$global.env.APACHE_HTTP_PORT_NUMBER}}",
"httpsPort": "{{$global.env.APACHE_HTTPS_PORT_NUMBER}}"
}

View File

@@ -1,16 +0,0 @@
#!/bin/bash -e
. /opt/bitnami/base/functions
. /opt/bitnami/base/helpers
print_welcome_page
if [[ "$1" == "nami" && "$2" == "start" ]] || [[ "$1" == "httpd" ]]; then
. /apache-init.sh
. /drupal-init.sh
nami_initialize apache mysql-client drupal
info "Starting drupal... "
. /post-init.sh
fi
exec tini -- "$@"

View File

@@ -1,31 +0,0 @@
#!/bin/bash
##
## @brief Helper function to show an error when a password is empty and exit
## param $1 Input name
##
empty_password_error() {
error "The $1 environment variable is empty or not set. Set the environment variable ALLOW_EMPTY_PASSWORD=yes to allow the container to be started with blank passwords. This is recommended only for development."
exit 1
}
##
## @brief Helper function to show a warning when the ALLOW_EMPTY_PASSWORD flag is enabled
##
empty_password_enabled_warn() {
warn "You set the environment variable ALLOW_EMPTY_PASSWORD=${ALLOW_EMPTY_PASSWORD}. For safety reasons, do not use this flag in a production environment."
}
# Validate passwords
if [[ "$ALLOW_EMPTY_PASSWORD" =~ ^(yes|Yes|YES)$ ]]; then
empty_password_enabled_warn
else
# Database creation by MySQL client
if [[ -n "$MYSQL_CLIENT_CREATE_DATABASE_USER" && -z "$MYSQL_CLIENT_CREATE_DATABASE_PASSWORD" ]]; then
empty_password_error MYSQL_CLIENT_CREATE_DATABASE_PASSWORD
fi
# Drupal database
if [[ -z "$DRUPAL_DATABASE_PASSWORD" ]]; then
empty_password_error DRUPAL_DATABASE_PASSWORD
fi
fi

View File

@@ -1,14 +0,0 @@
{
"databaseName": "{{$global.env.DRUPAL_DATABASE_NAME}}",
"databasePassword": "{{$global.env.DRUPAL_DATABASE_PASSWORD}}",
"databaseServerHost": "{{$global.env.MARIADB_HOST}}",
"databaseServerPort": "{{$global.env.MARIADB_PORT_NUMBER}}",
"databaseUser": "{{$global.env.DRUPAL_DATABASE_USER}}",
"email": "{{$global.env.DRUPAL_EMAIL}}",
"httpPort": "{{$global.env.DRUPAL_HTTP_PORT}}",
"httpsPort": "{{$global.env.DRUPAL_HTTPS_PORT}}",
"installationProfile": "{{$global.env.DRUPAL_PROFILE}}",
"password": "{{$global.env.DRUPAL_PASSWORD}}",
"phpMemoryLimit": "{{$global.env.PHP_MEMORY_LIMIT}}",
"username": "{{$global.env.DRUPAL_USERNAME}}"
}

View File

@@ -1,13 +0,0 @@
{
"allowEmptyPassword": "{{$global.env.ALLOW_EMPTY_PASSWORD}}",
"createDatabaseName": "{{$global.env.MYSQL_CLIENT_CREATE_DATABASE_NAME}}",
"createDatabasePassword": "{{$global.env.MYSQL_CLIENT_CREATE_DATABASE_PASSWORD}}",
"createDatabasePrivileges": "{{$global.env.MYSQL_CLIENT_CREATE_DATABASE_PRIVILEGES}}",
"createDatabaseUser": "{{$global.env.MYSQL_CLIENT_CREATE_DATABASE_USER}}",
"host": "{{$global.env.MARIADB_HOST}}",
"port": "{{$global.env.MARIADB_PORT_NUMBER}}",
"rootPassword": "{{$global.env.MARIADB_ROOT_PASSWORD}}",
"rootUser": "{{$global.env.MARIADB_ROOT_USER}}",
"sslCAFile": "{{$global.env.MYSQL_CLIENT_SSL_CA_FILE}}",
"sslEnable": "{{$global.env.MYSQL_CLIENT_ENABLE_SSL}}"
}

View File

@@ -0,0 +1,17 @@
-----BEGIN CERTIFICATE-----
MIICqDCCAZACCQCz8T3726LYsjANBgkqhkiG9w0BAQUFADAWMRQwEgYDVQQDDAtl
eGFtcGxlLmNvbTAeFw0xMjExMTQxMTE4MjdaFw0yMjExMTIxMTE4MjdaMBYxFDAS
BgNVBAMMC2V4YW1wbGUuY29tMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKC
AQEA5NHl5TfZtO6zugau2tp5mWIcQYJhuwKTmYeXDLYAGJpoD2SixwPL5c8glneI
Rz1N2EQIZVeaWGbS0FLFlPdOkCkplpW9isYVC4XqKrk5b4HW4+YC+Cup0k+Kd4NM
eZOTUvWr5N6dIpdibkVumBc/pao8VtdwywlCL/PwGRsQtkXrRICzdtRa3MXqTmEF
foyVCGgBRtronlB9x4Plfb8Psk4GrPkjrWYgO8peKrl0O5+F+sYg7Gj95zCH73BQ
ANzCVNrgD9fs9cyx3ru9CUdEoIxAAJwQFkjm7xr6xqhIlSgnQ7B0uOSTNRcXY6rw
s+PxGneec/kRPRgzjC/QHY6n8QIDAQABMA0GCSqGSIb3DQEBBQUAA4IBAQBbyMqF
RDsX8zX1EW5qA8AQ8Jb2XqWrVeSO8blMV3WagJ2airMm3+c/82FCwsd/cZ08UXhA
/Kou0gi/F16tV26PiiUdp590Qao3d8H2qxc1rzzULimZPgxH4iA4vRyMHtyZN6h4
7Fdn7O9xNMPu8siOz8rrzsEdEX5URbOMkDLCZsbTIUWVv2XmqrR0K10d5VuLWeLi
r+4G6c6jpa244WmqT9ClqceJ12G1Wnmezy7ybiW0l5M2iuIKFEiRP5Hj0J15o1I2
pXAbKysAdWRHsJSQOtcgO8Vh9k0wo3tKg4HDp1hbrEzoGzOv92Vjg3lG8X+hzbMJ
MQURotHkD4Gk57wL
-----END CERTIFICATE-----

View File

@@ -0,0 +1,27 @@
-----BEGIN RSA PRIVATE KEY-----
MIIEpAIBAAKCAQEA5NHl5TfZtO6zugau2tp5mWIcQYJhuwKTmYeXDLYAGJpoD2Si
xwPL5c8glneIRz1N2EQIZVeaWGbS0FLFlPdOkCkplpW9isYVC4XqKrk5b4HW4+YC
+Cup0k+Kd4NMeZOTUvWr5N6dIpdibkVumBc/pao8VtdwywlCL/PwGRsQtkXrRICz
dtRa3MXqTmEFfoyVCGgBRtronlB9x4Plfb8Psk4GrPkjrWYgO8peKrl0O5+F+sYg
7Gj95zCH73BQANzCVNrgD9fs9cyx3ru9CUdEoIxAAJwQFkjm7xr6xqhIlSgnQ7B0
uOSTNRcXY6rws+PxGneec/kRPRgzjC/QHY6n8QIDAQABAoIBACo3G131tuGtpFTu
xLW11vdYZXQklNlGuWp63IBI162yVv54B5wF9Ek6tH1uIiNaiREcRBxGVEB4/+3V
R4SbN9Ba98RDbgu7TcipdTFaqOEMqFO1bNjSXWtip14zSBmqA2Ur1AHOnFj0awGD
J8tBhsmOpcEz0Ch1VdO5ApPvLV8jH9wQiMI/Q6yYQMtmzTMCUMYdMqe+LOziIOzL
oqN/WXnKL5E5TiO1bIxSpWPbT+IVn1c3/PShmvmRrLWsFUQlkwXJKMYZPO+rCCfe
b+Q9lMLMnj+vOnM3z16WC3aiiJGCZjVTvQ+x22YrBTRPxZmHO2eZ4H/cUQM7Y/tw
I7RjEM0CgYEA9Kxt1t8bWonzBii3P0rwyx0IECvg63k+pp4BpxpeWQKL7NVdSzk3
AyJVcNjUoZgi2kVPdxzZGLrnZfuZ691xQB3oZF0LwBzQ4GFHkTRCB0s8ZA5lcJaI
9pBu91bhz2VOZSTeQWpdMMURjXVyTXZInU1mwzmjVOIAYmO33shH9gcCgYEA72mX
UoIrFPLkOTSZOb7UbjYH01vf6ThQiYCEWg7mD3CbY7n9oobIcQMzNnt7xN4wOl/V
eKfZ7G56q8enfqm45Dyo9aCBCENVzmwO8wLe5UnvJBNL20KjvtwG8w5A6UZQzC7p
3QS+U2zxVQNEeaE6a8Wrq2d1PlhVAHYw8odgNEcCgYBN38+58xrmrz99d1oTuAt5
6kyVsRGOgPGS4HmQMRFUbT4R7DscZSKASd4945WRtTVqmWLYe4MRnvNlfzYXX0zb
ZmmAAClsRP+qWuwHaEWXwrd+9SIOOqtvJrta1/lZJFpWUOy4j10H18Flb7sosnwc
LPWHL4Iv0xriNfDg5Iga4wKBgQDLJBU59SkJBW+Q+oho7vrg6QeK15IOGbJ8eYfT
woCC6VFwNQh5N1QsUELMH8rNKJpTba18SzAl5ThBOY9tciVnw/C5Og9CK6BLHnUw
zWbDtxAq1BSxXsIB2EAtTBLX3MoB9myJFNVJhE7hi3w2mA8yEu+u6IIa/Ghjk+XE
ZAnFUQKBgQDjMinRZrK5wA09jcetI+dNiLnKHoQG6OaXDDsNCatex0O2F36BvVXE
P78qDz/i5aBMWsLx6VDvWJAkBIpZoNS5UsOn17tFaocGUSkcm48bs8Dn6VvsE8Bd
XMPAHyKuILlKYifBvNq5T22KhqKX7yGmk/AeOOiKr2KeMnh27JYrCA==
-----END RSA PRIVATE KEY-----

View File

@@ -0,0 +1,5 @@
<IfModule mod_deflate.c>
AddOutputFilterByType DEFLATE text/html text/plain text/xml text/css
AddOutputFilterByType DEFLATE application/x-javascript application/javascript application/ecmascript
AddOutputFilterByType DEFLATE application/rss+xml
</IfModule>

View File

@@ -0,0 +1,6 @@
<VirtualHost localhost:80>
ServerName status.localhost
<Location /server-status>
SetHandler server-status
</Location>
</VirtualHost>

View File

@@ -0,0 +1,69 @@
#!/bin/bash
#
# Environment configuration for apache
# The values for all environment variables will be set in the below order of precedence
# 1. Custom environment variables defined below after Bitnami defaults
# 2. Constants defined in this file (environment variables with no default), i.e. BITNAMI_ROOT_DIR
# 3. Environment variables overridden via external files using *_FILE variables (see below)
# 4. Environment variables set externally (i.e. current Bash context/Dockerfile/userdata)
export BITNAMI_ROOT_DIR="/opt/bitnami"
export BITNAMI_VOLUME_DIR="/bitnami"
# Logging configuration
export MODULE="${MODULE:-apache}"
export BITNAMI_DEBUG="${BITNAMI_DEBUG:-false}"
# By setting an environment variable matching *_FILE to a file path, the prefixed environment
# variable will be overridden with the value specified in that file
apache_env_vars=(
APACHE_HTTP_PORT_NUMBER
APACHE_HTTPS_PORT_NUMBER
)
for env_var in "${apache_env_vars[@]}"; do
file_env_var="${env_var}_FILE"
if [[ -n "${!file_env_var:-}" ]]; then
export "${env_var}=$(< "${!file_env_var}")"
unset "${file_env_var}"
fi
done
unset apache_env_vars
export WEB_SERVER_TYPE="apache"
# Paths
export APACHE_BASE_DIR="${BITNAMI_ROOT_DIR}/apache"
export APACHE_BIN_DIR="${APACHE_BASE_DIR}/bin"
export APACHE_CONF_DIR="${APACHE_BASE_DIR}/conf"
export APACHE_HTDOCS_DIR="${APACHE_BASE_DIR}/htdocs"
export APACHE_TMP_DIR="${APACHE_BASE_DIR}/var/run"
export APACHE_LOGS_DIR="${APACHE_BASE_DIR}/logs"
export APACHE_VHOSTS_DIR="${APACHE_CONF_DIR}/vhosts"
export APACHE_HTACCESS_DIR="${APACHE_VHOSTS_DIR}/htaccess"
export APACHE_MOD_PAGESPEED_CACHE_DIR="${APACHE_BASE_DIR}/var/cache"
export APACHE_CONF_FILE="${APACHE_CONF_DIR}/httpd.conf"
export APACHE_PID_FILE="${APACHE_TMP_DIR}/httpd.pid"
export PATH="${APACHE_BIN_DIR}:${BITNAMI_ROOT_DIR}/common/bin:${PATH}"
# System users (when running with a privileged user)
export APACHE_DAEMON_USER="daemon"
export WEB_SERVER_DAEMON_USER="$APACHE_DAEMON_USER"
export APACHE_DAEMON_GROUP="daemon"
export WEB_SERVER_DAEMON_GROUP="$APACHE_DAEMON_GROUP"
export WEB_SERVER_GROUP="$APACHE_DAEMON_GROUP"
# Apache configuration
export APACHE_DEFAULT_HTTP_PORT_NUMBER="8080" # only used at build time
export WEB_SERVER_DEFAULT_HTTP_PORT_NUMBER="$APACHE_DEFAULT_HTTP_PORT_NUMBER"
export APACHE_DEFAULT_HTTPS_PORT_NUMBER="8443" # only used at build time
export WEB_SERVER_DEFAULT_HTTPS_PORT_NUMBER="$APACHE_DEFAULT_HTTPS_PORT_NUMBER"
export APACHE_HTTP_PORT_NUMBER="${APACHE_HTTP_PORT_NUMBER:-}"
export WEB_SERVER_HTTP_PORT_NUMBER="$APACHE_HTTP_PORT_NUMBER"
export APACHE_HTTPS_PORT_NUMBER="${APACHE_HTTPS_PORT_NUMBER:-"${APACHE_HTTPS_PORT:-}"}"
export APACHE_HTTPS_PORT_NUMBER="${APACHE_HTTPS_PORT_NUMBER:-"${WEB_SERVER_HTTPS_PORT:-}"}"
export APACHE_HTTPS_PORT_NUMBER="${APACHE_HTTPS_PORT_NUMBER:-}"
export WEB_SERVER_HTTPS_PORT_NUMBER="$APACHE_HTTPS_PORT_NUMBER"
# Custom environment variables may be defined below

View File

@@ -0,0 +1,30 @@
#!/bin/bash
# shellcheck disable=SC1091
set -o errexit
set -o nounset
set -o pipefail
# set -o xtrace # Uncomment this line for debugging purpose
# Load libraries
. /opt/bitnami/scripts/libapache.sh
# Load Apache environment
. /opt/bitnami/scripts/apache-env.sh
. /opt/bitnami/scripts/php-env.sh
# Enable required Apache modules
apache_enable_module "mpm_prefork_module"
apache_enable_module "php7_module" "modules/libphp7.so"
# Disable incompatible Apache modules
apache_disable_module "mpm_event_module"
# Write Apache configuration
apache_php_conf_file="${APACHE_CONF_DIR}/bitnami/php.conf"
cat > "$apache_php_conf_file" <<EOF
AddType application/x-httpd-php .php
DirectoryIndex index.html index.htm index.php
EOF
ensure_apache_configuration_exists "Include \"${apache_php_conf_file}\""

View File

@@ -0,0 +1,5 @@
{{before_vhost_configuration}}
<VirtualHost {{http_listen_addresses}}>
ServerAlias *
{{additional_configuration}}
</VirtualHost>

View File

@@ -0,0 +1,8 @@
{{before_vhost_configuration}}
<VirtualHost {{https_listen_addresses}}>
ServerAlias *
SSLEngine on
SSLCertificateFile "{{APACHE_CONF_DIR}}/bitnami/certs/server.crt"
SSLCertificateKeyFile "{{APACHE_CONF_DIR}}/bitnami/certs/server.key"
{{additional_configuration}}
</VirtualHost>

View File

@@ -0,0 +1,13 @@
{{before_vhost_configuration}}
<VirtualHost {{http_listen_addresses}}>
ServerAlias *
DocumentRoot {{document_root}}
<Directory "{{document_root}}">
Options -Indexes +FollowSymLinks -MultiViews
AllowOverride {{allow_override}}
{{acl_configuration}}
{{extra_directory_configuration}}
</Directory>
{{additional_configuration}}
{{htaccess_include}}
</VirtualHost>

View File

@@ -0,0 +1,16 @@
{{before_vhost_configuration}}
<VirtualHost {{https_listen_addresses}}>
ServerAlias *
SSLEngine on
SSLCertificateFile "{{APACHE_CONF_DIR}}/bitnami/certs/server.crt"
SSLCertificateKeyFile "{{APACHE_CONF_DIR}}/bitnami/certs/server.key"
DocumentRoot {{document_root}}
<Directory "{{document_root}}">
Options -Indexes +FollowSymLinks -MultiViews
AllowOverride {{allow_override}}
{{acl_configuration}}
{{extra_directory_configuration}}
</Directory>
{{additional_configuration}}
{{htaccess_include}}
</VirtualHost>

View File

@@ -0,0 +1,9 @@
{{prefix_conf}}
<Directory "{{document_root}}">
Options -Indexes +FollowSymLinks -MultiViews
AllowOverride {{allow_override}}
{{acl_configuration}}
{{extra_directory_configuration}}
</Directory>
{{additional_configuration}}
{{htaccess_include}}

View File

@@ -0,0 +1,30 @@
# Default SSL Virtual Host configuration.
<IfModule !ssl_module>
LoadModule ssl_module modules/mod_ssl.so
</IfModule>
Listen 443
SSLProtocol all -SSLv2 -SSLv3
SSLHonorCipherOrder on
SSLCipherSuite "EECDH+ECDSA+AESGCM EECDH+aRSA+AESGCM EECDH+ECDSA+SHA384 EECDH+ECDSA+SHA256 EECDH+aRSA+SHA384 EECDH+aRSA+SHA256 EECDH !aNULL !eNULL !LOW !3DES !MD5 !EXP !PSK !SRP !DSS !EDH !RC4"
SSLPassPhraseDialog builtin
SSLSessionCache "shmcb:{{APACHE_LOGS_DIR}}/ssl_scache(512000)"
SSLSessionCacheTimeout 300
<VirtualHost _default_:443>
DocumentRoot "{{APACHE_BASE_DIR}}/htdocs"
SSLEngine on
SSLCertificateFile "{{APACHE_CONF_DIR}}/bitnami/certs/server.crt"
SSLCertificateKeyFile "{{APACHE_CONF_DIR}}/bitnami/certs/server.key"
<Directory "{{APACHE_BASE_DIR}}/htdocs">
Options Indexes FollowSymLinks
AllowOverride All
Require all granted
</Directory>
# Error Documents
ErrorDocument 503 /503.html
</VirtualHost>

View File

@@ -0,0 +1,19 @@
# Default Virtual Host configuration.
# Let Apache know we're behind a SSL reverse proxy
SetEnvIf X-Forwarded-Proto https HTTPS=on
<VirtualHost _default_:80>
DocumentRoot "{{APACHE_BASE_DIR}}/htdocs"
<Directory "{{APACHE_BASE_DIR}}/htdocs">
Options Indexes FollowSymLinks
AllowOverride All
Require all granted
</Directory>
# Error Documents
ErrorDocument 503 /503.html
</VirtualHost>
Include "{{APACHE_CONF_DIR}}/bitnami/bitnami-ssl.conf"

View File

@@ -0,0 +1,27 @@
#!/bin/bash
# shellcheck disable=SC1091
set -o errexit
set -o nounset
set -o pipefail
#set -o xtrace
# Load libraries
. /opt/bitnami/scripts/libapache.sh
. /opt/bitnami/scripts/libbitnami.sh
. /opt/bitnami/scripts/liblog.sh
# Load Apache environment
. /opt/bitnami/scripts/apache-env.sh
print_welcome_page
if [[ "$*" == *"/opt/bitnami/scripts/apache/run.sh"* ]]; then
info "** Starting Apache setup **"
/opt/bitnami/scripts/apache/setup.sh
info "** Apache setup finished! **"
fi
echo ""
exec "$@"

View File

@@ -0,0 +1,115 @@
#!/bin/bash
# shellcheck disable=SC1091
set -o errexit
set -o nounset
set -o pipefail
# set -o xtrace # Uncomment this line for debugging purpose
# Load libraries
. /opt/bitnami/scripts/libapache.sh
. /opt/bitnami/scripts/libfs.sh
. /opt/bitnami/scripts/liblog.sh
########################
# Sets up the default Bitnami configuration
# Globals:
# APACHE_*
# Arguments:
# None
# Returns:
# None
#########################
apache_setup_bitnami_config() {
local template_dir="${BITNAMI_ROOT_DIR}/scripts/apache/bitnami-templates"
# Enable Apache modules
local -a modules_to_enable=(
"deflate_module"
"negotiation_module"
"proxy[^\s]*_module"
"rewrite_module"
"slotmem_shm_module"
"socache_shmcb_module"
"ssl_module"
"status_module"
"version_module"
)
for module in "${modules_to_enable[@]}"; do
apache_enable_module "$module"
done
# Disable Apache modules
local -a modules_to_disable=(
"http2_module"
"proxy_hcheck_module"
)
for module in "${modules_to_disable[@]}"; do
apache_disable_module "$module"
done
# Bitnami customizations
render-template "${template_dir}/bitnami.conf.tpl" > "${APACHE_CONF_DIR}/bitnami/bitnami.conf"
render-template "${template_dir}/bitnami-ssl.conf.tpl" > "${APACHE_CONF_DIR}/bitnami/bitnami-ssl.conf"
# Add new configuration only once, to avoid a second postunpack run breaking Apache
local apache_conf_add
apache_conf_add="$(cat <<EOF
Include "${APACHE_CONF_DIR}/extra/httpd-default.conf"
PidFile "${APACHE_PID_FILE}"
TraceEnable Off
Include "${APACHE_CONF_DIR}/deflate.conf"
IncludeOptional "${APACHE_VHOSTS_DIR}/*.conf"
Include "${APACHE_CONF_DIR}/bitnami/bitnami.conf"
EOF
)"
ensure_apache_configuration_exists "$apache_conf_add" "${APACHE_CONF_DIR}/bitnami/bitnami.conf"
# Configure the default ports since the container is non root by default
apache_configure_http_port "$APACHE_DEFAULT_HTTP_PORT_NUMBER"
apache_configure_https_port "$APACHE_DEFAULT_HTTPS_PORT_NUMBER"
# Patch the HTTPoxy vulnerability - see: https://docs.bitnami.com/general/security/security-2016-07-18/
apache_patch_httpoxy_vulnerability
# Remove unneeded directories that come with the tarball
rm -rf "/opt/bitnami/certs" "/opt/bitnami/conf"
}
########################
# Patches the HTTPoxy vulnerability - see: https://docs.bitnami.com/general/security/security-2016-07-18/
# Globals:
# APACHE_CONF_FILE
# Arguments:
# None
# Returns:
# None
#########################
apache_patch_httpoxy_vulnerability() {
# Apache HTTPD includes the HTTPoxy fix since 2016, so we only add it if not present
if ! grep -q "RequestHeader unset Proxy" "$APACHE_CONF_FILE"; then
cat >>"$APACHE_CONF_FILE" <<EOF
<IfModule mod_headers.c>
RequestHeader unset Proxy
</IfModule>
EOF
fi
}
# Load Apache environment
. /opt/bitnami/scripts/apache-env.sh
apache_setup_bitnami_config
# Ensure non-root user has write permissions on a set of directories
for dir in "$APACHE_TMP_DIR" "$APACHE_CONF_DIR" "$APACHE_LOGS_DIR" "$APACHE_VHOSTS_DIR" "$APACHE_HTACCESS_DIR" "$APACHE_HTDOCS_DIR" "$APACHE_MOD_PAGESPEED_CACHE_DIR"; do
ensure_dir_exists "$dir"
chmod -R g+rwX "$dir"
done
# Create 'apache2' symlink pointing to the 'apache' directory, for compatibility with Bitnami Docs guides
ln -sf apache "${BITNAMI_ROOT_DIR}/apache2"
ln -sf "/dev/stdout" "${APACHE_LOGS_DIR}/access_log"
ln -sf "/dev/stderr" "${APACHE_LOGS_DIR}/error_log"

View File

@@ -0,0 +1,18 @@
#!/bin/bash
# shellcheck disable=SC1091
set -o errexit
set -o nounset
set -o pipefail
# set -o xtrace # Uncomment this line for debugging purpose
# Load libraries
. /opt/bitnami/scripts/libapache.sh
. /opt/bitnami/scripts/liblog.sh
# Load Apache environment
. /opt/bitnami/scripts/apache-env.sh
info "** Reloading Apache configuration **"
exec "${APACHE_BIN_DIR}/apachectl" -k graceful

View File

@@ -0,0 +1,17 @@
#!/bin/bash
# shellcheck disable=SC1091
set -o errexit
set -o nounset
set -o pipefail
# set -o xtrace # Uncomment this line for debugging purposes
# Load libraries
. /opt/bitnami/scripts/libapache.sh
# Load Apache environment variables
. /opt/bitnami/scripts/apache-env.sh
/opt/bitnami/scripts/apache/stop.sh
/opt/bitnami/scripts/apache/start.sh

View File

@@ -0,0 +1,18 @@
#!/bin/bash
# shellcheck disable=SC1091
set -o errexit
set -o nounset
set -o pipefail
# set -o xtrace # Uncomment this line for debugging purpose
# Load libraries
. /opt/bitnami/scripts/libapache.sh
. /opt/bitnami/scripts/liblog.sh
# Load Apache environment
. /opt/bitnami/scripts/apache-env.sh
info "** Starting Apache **"
exec "${APACHE_BIN_DIR}/httpd" -f "$APACHE_CONF_FILE" -D "FOREGROUND"

View File

@@ -0,0 +1,26 @@
#!/bin/bash
# shellcheck disable=SC1091
set -o errexit
set -o nounset
set -o pipefail
# set -o xtrace # Uncomment this line for debugging purpose
# Load libraries
. /opt/bitnami/scripts/libapache.sh
# Load Apache environment
. /opt/bitnami/scripts/apache-env.sh
# Ensure Apache environment variables are valid
apache_validate
# Ensure Apache daemon user exists when running as 'root'
am_i_root && ensure_user_exists "$APACHE_DAEMON_USER" "$APACHE_DAEMON_GROUP"
# Ensure Apache is initialized
apache_initialize
# Fix logging issue when running as root
! am_i_root || chmod o+w "$(readlink /dev/stdout)" "$(readlink /dev/stderr)"

View File

@@ -0,0 +1,32 @@
#!/bin/bash
# shellcheck disable=SC1091
set -o errexit
set -o nounset
set -o pipefail
# set -o xtrace # Uncomment this line for debugging purposes
# Load libraries
. /opt/bitnami/scripts/libapache.sh
. /opt/bitnami/scripts/libos.sh
. /opt/bitnami/scripts/liblog.sh
# Load Apache environment variables
. /opt/bitnami/scripts/apache-env.sh
error_code=0
if is_apache_not_running; then
"${APACHE_BIN_DIR}/httpd" -f "$APACHE_CONF_FILE"
if ! retry_while "is_apache_running"; then
error "apache did not start"
error_code=1
else
info "apache started"
fi
else
info "apache is already running"
fi
exit "${error_code}"

View File

@@ -0,0 +1,21 @@
#!/bin/bash
# shellcheck disable=SC1091
set -o errexit
set -o nounset
set -o pipefail
# set -o xtrace # Uncomment this line for debugging purposes
# Load libraries
. /opt/bitnami/scripts/libapache.sh
. /opt/bitnami/scripts/liblog.sh
# Load Apache environment variables
. /opt/bitnami/scripts/apache-env.sh
if is_apache_running; then
info "apache is already running"
else
info "apache is not running"
fi

View File

@@ -0,0 +1,32 @@
#!/bin/bash
# shellcheck disable=SC1091
set -o errexit
set -o nounset
set -o pipefail
# set -o xtrace # Uncomment this line for debugging purposes
# Load libraries
. /opt/bitnami/scripts/libapache.sh
. /opt/bitnami/scripts/libos.sh
. /opt/bitnami/scripts/liblog.sh
# Load Apache environment variables
. /opt/bitnami/scripts/apache-env.sh
error_code=0
if is_apache_running; then
apache_stop
if ! retry_while "is_apache_not_running"; then
error "apache could not be stopped"
error_code=1
else
info "apache stopped"
fi
else
info "apache is not running"
fi
exit "${error_code}"

View File

@@ -0,0 +1,85 @@
#!/bin/bash
#
# Environment configuration for drupal
# The values for all environment variables will be set in the below order of precedence
# 1. Custom environment variables defined below after Bitnami defaults
# 2. Constants defined in this file (environment variables with no default), i.e. BITNAMI_ROOT_DIR
# 3. Environment variables overridden via external files using *_FILE variables (see below)
# 4. Environment variables set externally (i.e. current Bash context/Dockerfile/userdata)
export BITNAMI_ROOT_DIR="/opt/bitnami"
export BITNAMI_VOLUME_DIR="/bitnami"
# Logging configuration
export MODULE="${MODULE:-drupal}"
export BITNAMI_DEBUG="${BITNAMI_DEBUG:-false}"
# By setting an environment variable matching *_FILE to a file path, the prefixed environment
# variable will be overridden with the value specified in that file
drupal_env_vars=(
DRUPAL_DATA_TO_PERSIST
DRUPAL_PROFILE
DRUPAL_SITE_NAME
DRUPAL_SKIP_BOOTSTRAP
DRUPAL_ENABLE_MODULES
DRUPAL_USERNAME
DRUPAL_PASSWORD
DRUPAL_EMAIL
DRUPAL_DATABASE_HOST
DRUPAL_DATABASE_PORT_NUMBER
DRUPAL_DATABASE_NAME
DRUPAL_DATABASE_USER
DRUPAL_DATABASE_PASSWORD
DRUPAL_DATABASE_TLS_CA_FILE
DRUPAL_DATABASE_MIN_VERSION
)
for env_var in "${drupal_env_vars[@]}"; do
file_env_var="${env_var}_FILE"
if [[ -n "${!file_env_var:-}" ]]; then
export "${env_var}=$(< "${!file_env_var}")"
unset "${file_env_var}"
fi
done
unset drupal_env_vars
# Paths
export DRUPAL_BASE_DIR="${BITNAMI_ROOT_DIR}/drupal"
export DRUPAL_CONF_FILE="${DRUPAL_BASE_DIR}/sites/default/settings.php"
export DRUPAL_MODULES_DIR="${DRUPAL_BASE_DIR}/modules"
# Drupal persistence configuration
export DRUPAL_VOLUME_DIR="${BITNAMI_VOLUME_DIR}/drupal"
export DRUPAL_MOUNTED_CONF_FILE="${DRUPAL_VOLUME_DIR}/settings.php"
export DRUPAL_DATA_TO_PERSIST="${DRUPAL_DATA_TO_PERSIST:-sites/ themes/ modules/ profiles/}"
# Drupal configuration
export DRUPAL_PROFILE="${DRUPAL_PROFILE:-standard}"
export DRUPAL_SITE_NAME="${DRUPAL_SITE_NAME:-My blog}"
export DRUPAL_SKIP_BOOTSTRAP="${DRUPAL_SKIP_BOOTSTRAP:-}"
export DRUPAL_ENABLE_MODULES="${DRUPAL_ENABLE_MODULES:-}"
# Drupal credentials
export DRUPAL_USERNAME="${DRUPAL_USERNAME:-user}"
export DRUPAL_PASSWORD="${DRUPAL_PASSWORD:-bitnami}"
export DRUPAL_EMAIL="${DRUPAL_EMAIL:-user@example.com}"
# Database configuration
export DRUPAL_DEFAULT_DATABASE_HOST="mariadb" # only used at build time
export DRUPAL_DATABASE_HOST="${DRUPAL_DATABASE_HOST:-"${MARIADB_HOST:-}"}"
export DRUPAL_DATABASE_HOST="${DRUPAL_DATABASE_HOST:-$DRUPAL_DEFAULT_DATABASE_HOST}"
export DRUPAL_DATABASE_PORT_NUMBER="${DRUPAL_DATABASE_PORT_NUMBER:-"${MARIADB_PORT_NUMBER:-}"}"
export DRUPAL_DATABASE_PORT_NUMBER="${DRUPAL_DATABASE_PORT_NUMBER:-3306}"
export DRUPAL_DATABASE_NAME="${DRUPAL_DATABASE_NAME:-bitnami_drupal}"
export DRUPAL_DATABASE_USER="${DRUPAL_DATABASE_USER:-bn_drupal}"
export DRUPAL_DATABASE_PASSWORD="${DRUPAL_DATABASE_PASSWORD:-}"
export DRUPAL_DATABASE_TLS_CA_FILE="${DRUPAL_DATABASE_TLS_CA_FILE:-}"
export DRUPAL_DATABASE_MIN_VERSION="${DRUPAL_DATABASE_MIN_VERSION:-}"
# PHP configuration
export PHP_DEFAULT_MEMORY_LIMIT="256M" # only used at build time
# Custom environment variables may be defined below

View File

@@ -0,0 +1,31 @@
#!/bin/bash
# shellcheck disable=SC1091
set -o errexit
set -o nounset
set -o pipefail
# set -o xtrace # Uncomment this line for debugging purpose
# Load Drupal environment
. /opt/bitnami/scripts/drupal-env.sh
# Load libraries
. /opt/bitnami/scripts/libbitnami.sh
. /opt/bitnami/scripts/liblog.sh
. /opt/bitnami/scripts/libwebserver.sh
print_welcome_page
if [[ "$1" = "/opt/bitnami/scripts/$(web_server_type)/run.sh" || "$1" = "/opt/bitnami/scripts/nginx-php-fpm/run.sh" ]]; then
info "** Starting Drupal setup **"
/opt/bitnami/scripts/"$(web_server_type)"/setup.sh
/opt/bitnami/scripts/php/setup.sh
/opt/bitnami/scripts/mysql-client/setup.sh
/opt/bitnami/scripts/drupal/setup.sh
/post-init.sh
info "** Drupal setup finished! **"
fi
echo ""
exec "$@"

View File

@@ -0,0 +1,121 @@
#!/bin/bash
# shellcheck disable=SC1090
# shellcheck disable=SC1091
set -o errexit
set -o nounset
set -o pipefail
# set -o xtrace # Uncomment this line for debugging purpose
# Load Drupal environment
. /opt/bitnami/scripts/drupal-env.sh
# Load PHP environment for 'php_conf_set' (after 'drupal-env.sh' so that MODULE is not set to a wrong value)
. /opt/bitnami/scripts/php-env.sh
# Load libraries
. /opt/bitnami/scripts/libdrupal.sh
. /opt/bitnami/scripts/libfile.sh
. /opt/bitnami/scripts/libfs.sh
. /opt/bitnami/scripts/liblog.sh
. /opt/bitnami/scripts/libphp.sh
# Load web server environment and functions (after Drupal environment file so MODULE is not set to a wrong value)
. "/opt/bitnami/scripts/$(web_server_type)-env.sh"
. /opt/bitnami/scripts/libwebserver.sh
# Enable Drupal configuration file
[[ ! -f "$DRUPAL_CONF_FILE" ]] && cp "${DRUPAL_BASE_DIR}/sites/default/default.settings.php" "$DRUPAL_CONF_FILE"
[[ "$(web_server_type)" == "apache" ]] && drupal_fix_htaccess_warning_protection
# Ensure the Drupal base directory exists and has proper permissions
info "Configuring file permissions for Drupal"
for dir in "$DRUPAL_BASE_DIR" "${DRUPAL_BASE_DIR}/sites/default/files" "$DRUPAL_VOLUME_DIR" "${HOME}/.drush"; do
ensure_dir_exists "$dir"
configure_permissions_ownership "$dir" -d "775" -f "664"
done
for dir in "${DRUPAL_BASE_DIR}/themes" "${DRUPAL_BASE_DIR}/modules" "${DRUPAL_BASE_DIR}/sites/default/files"; do
ensure_dir_exists "$dir"
configure_permissions_ownership "$dir" -u "$WEB_SERVER_DAEMON_USER" -g "root"
done
chown "$WEB_SERVER_DAEMON_USER" "${DRUPAL_BASE_DIR}/sites/default"
chown "$WEB_SERVER_DAEMON_USER" "$DRUPAL_CONF_FILE"
for script in "${DRUPAL_BASE_DIR}/vendor/drush/drush/drush" "${DRUPAL_BASE_DIR}/vendor/drush/drush/drush.launcher"; do
[[ -f "$script" ]] && chmod +x "$script"
done
# Configure Drupal based on build-time defaults
drupal_conf_set "\$settings['trusted_host_patterns']" "array('^.*$')" yes
# Configure required PHP options for application to work properly, based on build-time defaults
info "Configuring default PHP options for Drupal"
php_conf_set memory_limit "$PHP_DEFAULT_MEMORY_LIMIT"
# Enable default web server configuration for Drupal
info "Creating default web server configuration for Drupal"
web_server_validate
ensure_web_server_app_configuration_exists "drupal" \
--type php \
--nginx-additional-configuration $'
location = /favicon.ico {
log_not_found off;
access_log off;
}
location = /robots.txt {
allow all;
log_not_found off;
access_log off;
}
location ~ ^/sites/.*/private/ {
return 403;
}
# Block access to scripts in site files directory
location ~ ^/sites/[^/]+/files/.*\.php$ {
deny all;
}
# Allow "Well-Known URIs" as per RFC 5785
location ~* ^/.well-known/ {
allow all;
}
location / {
try_files $uri /index.php?$query_string;
}
location @rewrite {
rewrite ^/(.*)$ /index.php?q=$1;
}
# Don\'t allow direct access to PHP files in the vendor directory.
location ~ /vendor/.*\.php$ {
deny all;
return 404;
}
# Fighting with Styles? This little gem is amazing.
location ~ ^/sites/.*/files/styles/ {
try_files $uri @rewrite;
}
# Handle private files through Drupal. Private file\'s path can come
# with a language prefix.
location ~ ^(/[a-z\-]+)?/system/files/ {
try_files $uri /index.php?$query_string;
}
location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg)$ {
try_files $uri @rewrite;
expires max;
log_not_found off;
}'
# Fix warning for Drupal and htaccess by writing the file again
if [[ "$(web_server_type)" == "apache" ]]; then
drupal_fix_htaccess_warning_protection
fi

View File

@@ -0,0 +1,26 @@
#!/bin/bash
# shellcheck disable=SC1091
set -o errexit
set -o nounset
set -o pipefail
# set -o xtrace # Uncomment this line for debugging purpose
# Load Drupal environment
. /opt/bitnami/scripts/drupal-env.sh
# Load environment for web server configuration (after Drupal environment file so MODULE is not set to a wrong value)
. /opt/bitnami/scripts/libwebserver.sh
# Load libraries
. /opt/bitnami/scripts/libdrupal.sh
# Ensure Drupal environment variables are valid
drupal_validate
# Update web server configuration with runtime environment (needs to happen before the initialization)
web_server_update_app_configuration "drupal"
# Ensure Drupal is initialized
drupal_initialize

View File

@@ -0,0 +1,687 @@
#!/bin/bash
#
# Bitnami Apache library
# shellcheck disable=SC1091
# Load Generic Libraries
. /opt/bitnami/scripts/libfs.sh
. /opt/bitnami/scripts/libfile.sh
. /opt/bitnami/scripts/liblog.sh
. /opt/bitnami/scripts/libos.sh
. /opt/bitnami/scripts/libvalidations.sh
. /opt/bitnami/scripts/libservice.sh
########################
# Validate settings in APACHE_* env vars
# Globals:
# APACHE_*
# Arguments:
# None
# Returns:
# None
#########################
apache_validate() {
debug "Validating settings in APACHE_* environment variables"
local error_code=0
# Auxiliary functions
print_validation_error() {
error "$1"
error_code=1
}
check_allowed_port() {
local port_var="${1:?missing port variable}"
local -a validate_port_args=()
! am_i_root && validate_port_args+=("-unprivileged")
validate_port_args+=("${!port_var}")
if ! err=$(validate_port "${validate_port_args[@]}"); then
print_validation_error "An invalid port was specified in the environment variable ${port_var}: ${err}."
fi
}
[[ -w "$APACHE_CONF_FILE" ]] || warn "The Apache configuration file '${APACHE_CONF_FILE}' is not writable. Configurations based on environment variables will not be applied."
if [[ -n "$APACHE_HTTP_PORT_NUMBER" ]] && [[ -n "$APACHE_HTTPS_PORT_NUMBER" ]]; then
if [[ "$APACHE_HTTP_PORT_NUMBER" -eq "$APACHE_HTTPS_PORT_NUMBER" ]]; then
print_validation_error "APACHE_HTTP_PORT_NUMBER and APACHE_HTTPS_PORT_NUMBER are bound to the same port!"
fi
fi
[[ -n "$APACHE_HTTP_PORT_NUMBER" ]] && check_allowed_port APACHE_HTTP_PORT_NUMBER
[[ -n "$APACHE_HTTPS_PORT_NUMBER" ]] && check_allowed_port APACHE_HTTPS_PORT_NUMBER
[[ "$error_code" -eq 0 ]] || exit "$error_code"
}
########################
# Configure Apache's HTTP port
# Globals:
# APACHE_CONF_FILE, APACHE_CONF_DIR
# Arguments:
# None
# Returns:
# None
#########################
apache_configure_http_port() {
local -r port=${1:?missing port}
local -r listen_exp="s|^\s*Listen\s+([^:]*:)?[0-9]+\s*$|Listen ${port}|"
local -r server_name_exp="s|^\s*#?\s*ServerName\s+([^:\s]+)(:[0-9]+)?$|ServerName \1:${port}|"
local -r vhost_exp="s|VirtualHost\s+([^:>]+)(:[0-9]+)|VirtualHost \1:${port}|"
local apache_configuration
if [[ -w "$APACHE_CONF_FILE" ]]; then
debug "Configuring port ${port} on file ${APACHE_CONF_FILE}"
apache_configuration="$(sed -E -e "$listen_exp" -e "$server_name_exp" "$APACHE_CONF_FILE")"
echo "$apache_configuration" > "$APACHE_CONF_FILE"
fi
if [[ -w "${APACHE_CONF_DIR}/bitnami/bitnami.conf" ]]; then
debug "Configuring port ${port} on file ${APACHE_CONF_DIR}/bitnami/bitnami.conf"
apache_configuration="$(sed -E "$vhost_exp" "${APACHE_CONF_DIR}/bitnami/bitnami.conf")"
echo "$apache_configuration" > "${APACHE_CONF_DIR}/bitnami/bitnami.conf"
fi
if [[ -w "${APACHE_VHOSTS_DIR}/00_status-vhost.conf" ]]; then
debug "Configuring port ${port} on file ${APACHE_VHOSTS_DIR}/00_status-vhost.conf"
apache_configuration="$(sed -E "$vhost_exp" "${APACHE_VHOSTS_DIR}/00_status-vhost.conf")"
echo "$apache_configuration" > "${APACHE_VHOSTS_DIR}/00_status-vhost.conf"
fi
}
########################
# Configure Apache's HTTPS port
# Globals:
# APACHE_CONF_DIR
# Arguments:
# None
# Returns:
# None
#########################
apache_configure_https_port() {
local -r port=${1:?missing port}
local -r listen_exp="s|^\s*Listen\s+([^:]*:)?[0-9]+\s*$|Listen ${port}|"
local -r vhost_exp="s|VirtualHost\s+([^:>]+)(:[0-9]+)|VirtualHost \1:${port}|"
local apache_configuration
if [[ -w "${APACHE_CONF_DIR}/bitnami/bitnami-ssl.conf" ]]; then
debug "Configuring port ${port} on file ${APACHE_CONF_DIR}/bitnami/bitnami-ssl.conf"
apache_configuration="$(sed -E -e "$listen_exp" -e "$vhost_exp" "${APACHE_CONF_DIR}/bitnami/bitnami-ssl.conf")"
echo "$apache_configuration" > "${APACHE_CONF_DIR}/bitnami/bitnami-ssl.conf"
fi
}
########################
# Ensure Apache is initialized
# Globals:
# APACHE_*
# Arguments:
# None
# Returns:
# None
#########################
apache_initialize() {
# Copy vhosts files
if ! is_dir_empty "/vhosts"; then
info "Found mounted virtual hosts in '/vhosts'. Copying them to '${APACHE_BASE_DIR}/conf/vhosts'"
cp -Lr "/vhosts/." "${APACHE_VHOSTS_DIR}"
fi
# Mount certificate files
if ! is_dir_empty "${APACHE_BASE_DIR}/certs"; then
warn "The directory '${APACHE_BASE_DIR}/certs' was externally mounted. This is a legacy configuration and will be deprecated soon. Please mount certificate files at '/certs' instead. Find an example at: https://github.com/bitnami/bitnami-docker-apache#using-custom-ssl-certificates"
warn "Restoring certificates at '${APACHE_BASE_DIR}/certs' to '${APACHE_CONF_DIR}/bitnami/certs'"
rm -rf "${APACHE_CONF_DIR}/bitnami/certs"
ln -sf "${APACHE_BASE_DIR}/certs" "${APACHE_CONF_DIR}/bitnami/certs"
elif ! is_dir_empty "/certs"; then
info "Mounting certificates files from '/certs'"
rm -rf "${APACHE_CONF_DIR}/bitnami/certs"
ln -sf "/certs" "${APACHE_CONF_DIR}/bitnami/certs"
fi
# Mount application files
if ! is_dir_empty "/app"; then
info "Mounting application files from '/app'"
rm -rf "$APACHE_HTDOCS_DIR"
ln -sf "/app" "$APACHE_HTDOCS_DIR"
fi
# Port configuration
[[ -n "$APACHE_HTTP_PORT_NUMBER" ]] && info "Configuring the HTTP port" && apache_configure_http_port "$APACHE_HTTP_PORT_NUMBER"
[[ -n "$APACHE_HTTPS_PORT_NUMBER" ]] && info "Configuring the HTTPS port" && apache_configure_https_port "$APACHE_HTTPS_PORT_NUMBER"
# Restore persisted configuration files (deprecated)
if ! is_dir_empty "/bitnami/apache/conf"; then
warn "The directory '/bitnami/apache/conf' was externally mounted. This is a legacy configuration and will be deprecated soon. Please mount certificate files at '${APACHE_CONF_DIR}' instead. Find an example at: https://github.com/bitnami/bitnami-docker-apache#full-configuration"
warn "Restoring configuration at '/bitnami/apache/conf' to '${APACHE_CONF_DIR}'"
rm -rf "$APACHE_CONF_DIR"
ln -sf "/bitnami/apache/conf" "$APACHE_CONF_DIR"
fi
}
########################
# Enable a module in the Apache configuration file
# Globals:
# APACHE_CONF_FILE
# Arguments:
# $1 - Module to enable
# $2 - Path to module .so file (optional if already defined in httpd.conf)
# Returns:
# None
#########################
apache_enable_module() {
local -r name="${1:?missing name}"
local -r file="${2:-}"
local -r regex="[#\s]*(LoadModule\s+${name}\s+.*)$"
local apache_configuration
if [[ -w "$APACHE_CONF_FILE" ]]; then
debug "Enabling module '${name}'"
if grep -q -E "$regex" "$APACHE_CONF_FILE"; then
# Uncomment line if the module was already defined
replace_in_file "$APACHE_CONF_FILE" "$regex" "\1"
elif [[ -n "$file" ]]; then
# Add right after the last LoadModule, so all Apache modules are organized in the same section of the file
append_file_after_last_match "$APACHE_CONF_FILE" "^[#\s]*LoadModule" "LoadModule ${name} ${file}"
else
error "Module ${name} was not defined in ${APACHE_CONF_FILE}. Please specify the 'file' parameter for 'apache_enable_module'."
fi
fi
}
########################
# Disable a module in the Apache configuration file
# Globals:
# APACHE_CONF_FILE
# Arguments:
# $1 - Module to disable
# Returns:
# None
#########################
apache_disable_module() {
local -r name="${1:?missing name}"
local -r file="${2:-}"
local -r regex="[#\s]*(LoadModule\s+${name}\s+.*)$"
local apache_configuration
if [[ -w "$APACHE_CONF_FILE" ]]; then
debug "Disabling module '${name}'"
replace_in_file "$APACHE_CONF_FILE" "$regex" "#\1"
fi
}
########################
# Stop Apache
# Globals:
# APACHE_*
# Arguments:
# None
# Returns:
# None
#########################
apache_stop() {
is_apache_not_running && return
stop_service_using_pid "$APACHE_PID_FILE"
}
########################
# Check if Apache is running
# Globals:
# APACHE_PID_FILE
# Arguments:
# None
# Returns:
# Whether Apache is running
########################
is_apache_running() {
local pid
pid="$(get_pid_from_file "$APACHE_PID_FILE")"
if [[ -n "$pid" ]]; then
is_service_running "$pid"
else
false
fi
}
########################
# Check if Apache is running
# Globals:
# APACHE_PID_FILE
# Arguments:
# None
# Returns:
# Whether Apache is not running
########################
is_apache_not_running() {
! is_apache_running
}
########################
# Ensure configuration gets added to the main Apache configuration file
# Globals:
# APACHE_*
# Arguments:
# $1 - configuration string
# $2 - pattern to use for checking if the configuration already exists (default: $1)
# Returns:
# None
########################
ensure_apache_configuration_exists() {
local -r conf="${1:?conf missing}"
local -r pattern="${2:-"$conf"}"
# Enable configuration by appending to httpd.conf
if ! grep -E -q "$pattern" "$APACHE_CONF_FILE"; then
if is_file_writable "$APACHE_CONF_FILE"; then
cat >> "$APACHE_CONF_FILE" <<< "$conf"
else
error "Could not add the following configuration to '${APACHE_CONF_FILE}:"
error ""
error "$(indent "$conf" 4)"
error ""
error "Include the configuration manually and try again."
return 1
fi
fi
}
########################
# Collect all the .htaccess files from /opt/bitnami/$name and write the result in the 'htaccess' directory
# Globals:
# APACHE_*
# Arguments:
# $1 - App name
# $2 - Overwrite the original .htaccess with the explanation text (defaults to 'yes')
# Flags:
# --document-root - Path to document root directory
# Returns:
# None
########################
apache_replace_htaccess_files() {
local -r app="${1:?missing app}"
local -r result_file="${APACHE_HTACCESS_DIR}/${app}-htaccess.conf"
# Default options
local document_root="${BITNAMI_ROOT_DIR}/${app}"
local overwrite="yes"
local -a htaccess_files
local htaccess_dir
local htaccess_contents
# Validate arguments
shift
while [[ "$#" -gt 0 ]]; do
case "$1" in
--document-root)
shift
document_root="$1"
;;
--overwrite)
shift
overwrite="$1"
;;
*)
echo "Invalid command line flag ${1}" >&2
return 1
;;
esac
shift
done
# Locate all .htaccess files inside the document root
read -r -a htaccess_files <<< "$(find "$document_root" -name .htaccess -print0 | xargs -0)"
[[ "${#htaccess_files[@]}" = 0 ]] && return
for htaccess_file in "${htaccess_files[@]}"; do
htaccess_dir="$(dirname "$htaccess_file")"
htaccess_contents="$(indent "$(< "$htaccess_file")" 2)"
# Skip if it was already included to the resulting htaccess file
if grep -q "^<Directory \"$htaccess_dir\">" <<< "$htaccess_contents"; then
continue
fi
# Add to the htaccess file
cat >> "$result_file" <<EOF
<Directory "${htaccess_dir}">
${htaccess_contents}
</Directory>
EOF
# Overwrite the original .htaccess with the explanation text
if is_boolean_yes "$overwrite"; then
echo "# This configuration has been moved to the ${result_file} config file for performance and security reasons" > "$htaccess_file"
fi
done
}
########################
# Ensure an Apache application configuration exists (in virtual host format)
# Globals:
# APACHE_*
# Arguments:
# $1 - App name
# Flags:
# --hosts - Hosts to enable
# --type - Application type, which has an effect on what configuration template will be used, allowed values: php, (empty)
# --allow-remote-connections - Whether to allow remote connections or to require local connections
# --disabled - Whether to render the file with a .disabled prefix
# --enable-https - Enable app configuration on HTTPS port
# --http-port - HTTP port number
# --https-port - HTTPS port number
# --move-htaccess - Move .htaccess files to a common place so they can be loaded during Apache startup
# --additional-configuration - Additional vhost configuration (no default)
# --before-vhost-configuration - Configuration to add before the <VirtualHost> directive (no default)
# --allow-override - Whether to allow .htaccess files (only allowed when --move-htaccess is set to 'no')
# --document-root - Path to document root directory
# --extra-directory-configuration - Extra configuration for the document root directory
# Returns:
# true if the configuration was enabled, false otherwise
########################
ensure_apache_app_configuration_exists() {
local -r app="${1:?missing app}"
# Default options
local -a hosts=("127.0.0.1" "_default_")
local type=""
local allow_remote_connections="yes"
local disabled="no"
local enable_https="yes"
local http_port="${APACHE_HTTP_PORT_NUMBER:-"$APACHE_DEFAULT_HTTP_PORT_NUMBER"}"
local https_port="${APACHE_HTTPS_PORT_NUMBER:-"$APACHE_DEFAULT_HTTPS_PORT_NUMBER"}"
local move_htaccess="yes"
local var_name
# Template variables defaults
export additional_configuration=""
export before_vhost_configuration=""
export allow_override="All"
export document_root="${BITNAMI_ROOT_DIR}/${app}"
export extra_directory_configuration=""
# Validate arguments
shift
while [[ "$#" -gt 0 ]]; do
case "$1" in
--hosts)
shift
read -r -a hosts <<< "$1"
;;
--type \
| --allow-remote-connections \
| --disabled \
| --enable-https \
| --http-port \
| --https-port \
| --move-htaccess \
| --additional-configuration \
| --before-vhost-configuration \
| --allow-override \
| --document-root \
| --extra-directory-configuration \
)
var_name="$(echo "$1" | sed -e "s/^--//" -e "s/-/_/g")"
shift
export "${var_name}"="$1"
;;
*)
echo "Invalid command line flag $1" >&2
return 1
;;
esac
shift
done
# Construct host string in the format of "host1:port1[ host2:port2[ ...]]"
export http_listen_addresses=""
export https_listen_addresses=""
for host in "${hosts[@]}"; do
http_listen="${host}:${http_port}"
https_listen="${host}:${https_port}"
[[ -z "${http_listen_addresses:-}" ]] && http_listen_addresses="$http_listen" || http_listen_addresses="${http_listen_addresses} ${http_listen}"
[[ -z "${https_listen_addresses:-}" ]] && https_listen_addresses="$https_listen" || https_listen_addresses="${https_listen_addresses} ${https_listen}"
done
# App .htaccess support
export htaccess_include
is_boolean_yes "$move_htaccess" && apache_replace_htaccess_files "$app" --document-root "$document_root"
if [[ -f "${APACHE_HTACCESS_DIR}/${app}-htaccess.conf" ]]; then
allow_override="None"
htaccess_include="Include \"${APACHE_HTACCESS_DIR}/${app}-htaccess.conf\""
else
allow_override="$allow_override"
htaccess_include=""
fi
# ACL configuration
export acl_configuration
if is_boolean_yes "$allow_remote_connections"; then
acl_configuration="Require all granted"
else
acl_configuration="$(cat <<EOF
Require local
ErrorDocument 403 "For security reasons, this URL is only accessible using localhost (127.0.0.1) as the hostname."
# AuthType Basic
# AuthName ${app}
# AuthUserFile "${APACHE_BASE_DIR}/users"
# Require valid-user
EOF
)"
fi
# Indent configurations
additional_configuration="$(indent $'\n'"$additional_configuration" 2)"
htaccess_include="$(indent $'\n'"$htaccess_include" 2)"
extra_directory_configuration="$(indent $'\n'"$extra_directory_configuration" 4)"
# Render templates
# We remove lines that are empty or contain only newspaces with 'sed', so the resulting file looks better
local template_name="app"
[[ -n "$type" && "$type" != "php" ]] && template_name="app-${type}"
local -r template_dir="${BITNAMI_ROOT_DIR}/scripts/apache/bitnami-templates"
local vhost_suffix=""
is_boolean_yes "$disabled" && vhost_suffix=".disabled"
local -r http_vhost="${APACHE_VHOSTS_DIR}/${app}-vhost.conf${vhost_suffix}"
local -r https_vhost="${APACHE_VHOSTS_DIR}/${app}-https-vhost.conf${vhost_suffix}"
if is_file_writable "$http_vhost"; then
# Create file with root group write privileges, so it can be modified in non-root containers
[[ ! -f "$http_vhost" ]] && touch "$http_vhost" && chmod g+rw "$http_vhost"
render-template "${template_dir}/${template_name}-http-vhost.conf.tpl" | sed '/^\s*$/d' > "$http_vhost"
elif [[ ! -f "$http_vhost" ]]; then
error "Could not create virtual host for ${app} at '${http_vhost}'. Check permissions and ownership for parent directories."
return 1
else
warn "The ${app} virtual host file '${http_vhost}' is not writable. Configurations based on environment variables will not be applied for this file."
fi
if is_boolean_yes "$enable_https"; then
if is_file_writable "$https_vhost"; then
# Create file with root group write privileges, so it can be modified in non-root containers
[[ ! -f "$https_vhost" ]] && touch "$https_vhost" && chmod g+rw "$https_vhost"
render-template "${template_dir}/${template_name}-https-vhost.conf.tpl" | sed '/^\s*$/d' > "$https_vhost"
elif [[ ! -f "$https_vhost" ]]; then
error "Could not create virtual host for ${app} at '${https_vhost}'. Check permissions and ownership for parent directories."
return 1
else
warn "The ${app} virtual host file '${https_vhost}' is not writable. Configurations based on environment variables will not be applied for this file."
fi
fi
}
########################
# Ensure an Apache application configuration does not exist anymore (in virtual hosts format)
# Globals:
# *
# Arguments:
# $1 - App name
# Returns:
# true if the configuration was disabled, false otherwise
########################
ensure_apache_app_configuration_not_exists() {
local -r app="${1:?missing app}"
local -r http_vhost="${APACHE_VHOSTS_DIR}/${app}-vhost.conf"
local -r https_vhost="${APACHE_VHOSTS_DIR}/${app}-https-vhost.conf"
# Note that 'rm -f' will not fail if the files don't exist
# However if we lack permissions to remove the file, it will result in a non-zero exit code, as expected by this function
rm -f "$http_vhost" "$https_vhost"
}
########################
# Ensure Apache loads the configuration for an application in a URL prefix
# Globals:
# APACHE_*
# Arguments:
# $1 - App name
# Flags:
# --type - Application type, which has an effect on what configuration template will be used, allowed values: php, (empty)
# --allow-remote-connections - Whether to allow remote connections or to require local connections
# --move-htaccess - Move .htaccess files to a common place so they can be loaded during Apache startup
# --prefix - URL prefix from where it will be accessible (i.e. /myapp)
# --additional-configuration - Additional vhost configuration (no default)
# --allow-override - Whether to allow .htaccess files (only allowed when --move-htaccess is set to 'no')
# --document-root - Path to document root directory
# --extra-directory-configuration - Extra configuration for the document root directory
# Returns:
# true if the configuration was enabled, false otherwise
########################
ensure_apache_prefix_configuration_exists() {
local -r app="${1:?missing app}"
# Default options
local type=""
local allow_remote_connections="yes"
local move_htaccess="yes"
local prefix="/${app}"
local var_name
# Template variables defaults
export additional_configuration=""
export allow_override="All"
export document_root="${BITNAMI_ROOT_DIR}/${app}"
export extra_directory_configuration=""
# Validate arguments
shift
while [[ "$#" -gt 0 ]]; do
case "$1" in
--type \
| --allow-remote-connections \
| --move-htaccess \
| --prefix \
| --additional-configuration \
| --allow-override \
| --document-root \
| --extra-directory-configuration \
)
var_name="$(echo "$1" | sed -e "s/^--//" -e "s/-/_/g")"
shift
declare "${var_name}"="$1"
;;
*)
echo "Invalid command line flag $1" >&2
return 1
;;
esac
shift
done
# App .htaccess support
export htaccess_include
is_boolean_yes "$move_htaccess" && apache_replace_htaccess_files "$app" --document-root "$document_root"
if [[ -f "${APACHE_HTACCESS_DIR}/${app}-htaccess.conf" ]]; then
allow_override="None"
htaccess_include="Include \"${APACHE_HTACCESS_DIR}/${app}-htaccess.conf\""
else
allow_override="$allow_override"
htaccess_include=""
fi
# ACL configuration
export acl_configuration
if is_boolean_yes "$allow_remote_connections"; then
acl_configuration="Require all granted"
else
acl_configuration="$(cat <<EOF
Require local
ErrorDocument 403 "For security reasons, this URL is only accessible using localhost (127.0.0.1) as the hostname."
# AuthType Basic
# AuthName ${app}
# AuthUserFile "${APACHE_CONF_DIR}/users"
# Require valid-user
EOF
)"
fi
# Prefix configuration
export prefix_conf="Alias ${prefix} \"${document_root}\""
# Indent configurations
acl_configuration="$(indent $'\n'"$acl_configuration" 2)"
extra_directory_configuration="$(indent $'\n'"$extra_directory_configuration" 2)"
# Render templates
# We remove lines that are empty or contain only newspaces with 'sed', so the resulting file looks better
local template_name="app"
[[ -n "$type" && "$type" != "php" ]] && template_name="app-${type}"
local -r template_dir="${BITNAMI_ROOT_DIR}/scripts/apache/bitnami-templates"
local -r prefix_file="${APACHE_CONF_DIR}/bitnami/${app}.conf"
if is_file_writable "$prefix_file"; then
# Create file with root group write privileges, so it can be modified in non-root containers
[[ ! -f "$prefix_file" ]] && touch "$prefix_file" && chmod g+rw "$prefix_file"
render-template "${template_dir}/${template_name}-prefix.conf.tpl" | sed '/^\s*$/d' > "$prefix_file"
ensure_apache_configuration_exists "Include \"$prefix_file\""
elif [[ ! -f "$prefix_file" ]]; then
error "Could not create web server configuration file for ${app} at '${prefix_file}'. Check permissions and ownership for parent directories."
return 1
else
warn "The ${app} web server configuration file '${prefix_file}' is not writable. Configurations based on environment variables will not be applied for this file."
fi
}
########################
# Ensure Apache application configuration is updated with the runtime configuration (i.e. ports)
# Globals:
# *
# Arguments:
# $1 - App name
# Flags:
# --hosts - Hosts to enable
# --enable-https - Update HTTPS app configuration
# --http-port - HTTP port number
# --https-port - HTTPS port number
# Returns:
# true if the configuration was updated, false otherwise
########################
apache_update_app_configuration() {
local -r app="${1:?missing app}"
# Default options
local -a hosts=("127.0.0.1" "_default_")
local enable_https="yes"
local http_port="${APACHE_HTTP_PORT_NUMBER:-"$APACHE_DEFAULT_HTTP_PORT_NUMBER"}"
local https_port="${APACHE_HTTPS_PORT_NUMBER:-"$APACHE_DEFAULT_HTTPS_PORT_NUMBER"}"
# Validate arguments
shift
while [[ "$#" -gt 0 ]]; do
case "$1" in
--hosts)
shift
read -r -a hosts <<< "$1"
;;
# Common flags
--enable-https \
| --http-port \
| --https-port \
)
args+=("$1" "$2")
shift
;;
*)
echo "Invalid command line flag $1" >&2
return 1
;;
esac
shift
done
# Construct host string in the format of "host1:port1[ host2:port2[ ...]]"
export http_listen_addresses=""
export https_listen_addresses=""
for host in "${hosts[@]}"; do
http_listen="${host}:${http_port}"
https_listen="${host}:${https_port}"
[[ -z "${http_listen_addresses:-}" ]] && http_listen_addresses="$http_listen" || http_listen_addresses="${http_listen_addresses} ${http_listen}"
[[ -z "${https_listen_addresses:-}" ]] && https_listen_addresses="$https_listen" || https_listen_addresses="${https_listen_addresses} ${https_listen}"
done
# Update configuration
local -r http_vhost="${APACHE_VHOSTS_DIR}/${app}-vhost.conf"
local -r https_vhost="${APACHE_VHOSTS_DIR}/${app}-https-vhost.conf"
if is_file_writable "$http_vhost"; then
replace_in_file "$http_vhost" "^<VirtualHost\s.*>$" "<VirtualHost ${http_listen_addresses}>"
else
warn "The ${app} virtual host file '${http_vhost}' is not writable. Configurations based on environment variables will not be applied for this file."
fi
if is_boolean_yes "$enable_https"; then
if is_file_writable "$https_vhost"; then
replace_in_file "$https_vhost" "^<VirtualHost\s.*>$" "<VirtualHost ${https_listen_addresses}>"
else
warn "The ${app} virtual host file '${https_vhost}' is not writable. Configurations based on environment variables will not be applied for this file."
fi
fi
}

View File

@@ -0,0 +1,425 @@
#!/bin/bash
#
# Bitnami Drupal library
# shellcheck disable=SC1091
# Load Drupal environment
. /opt/bitnami/scripts/drupal-env.sh
# Load MySQL Client environment for 'mysql_execute' (after 'drupal-env.sh' so that MODULE is not set to a wrong value)
. /opt/bitnami/scripts/mysql-client-env.sh
# Load Generic Libraries
. /opt/bitnami/scripts/libphp.sh
. /opt/bitnami/scripts/libfs.sh
. /opt/bitnami/scripts/libos.sh
. /opt/bitnami/scripts/libnet.sh
. /opt/bitnami/scripts/libvalidations.sh
. /opt/bitnami/scripts/libversion.sh
. /opt/bitnami/scripts/libwebserver.sh
. /opt/bitnami/scripts/libmysqlclient.sh
. /opt/bitnami/scripts/libpersistence.sh
########################
# Validate settings in DRUPAL_* env vars
# Globals:
# DRUPAL_*
# Arguments:
# None
# Returns:
# 0 if the validation succeeded, 1 otherwise
#########################
drupal_validate() {
debug "Validating settings in DRUPAL_* environment variables..."
local error_code=0
# Auxiliary functions
print_validation_error() {
error "$1"
error_code=1
}
check_yes_no_value() {
if ! is_yes_no_value "${!1}" && ! is_true_false_value "${!1}"; then
print_validation_error "The allowed values for ${1} are: yes no"
fi
}
check_resolved_hostname() {
if ! is_hostname_resolved "$1"; then
warn "Hostname $1 could not be resolved. This could lead to connection issues"
fi
}
check_mounted_file() {
if [[ -n "${!1:-}" ]] && ! [[ -f "${!1:-}" ]]; then
print_validation_error "The variable ${1} is defined but the file ${!1} is not accessible or does not exist"
fi
}
# Warn users in case the configuration file is not writable
is_file_writable "$DRUPAL_CONF_FILE" || warn "The Drupal configuration file '${DRUPAL_CONF_FILE}' is not writable. Configurations based on environment variables will not be applied for this file."
# Validate user inputs
! is_empty_value "$DRUPAL_SKIP_BOOTSTRAP" && check_yes_no_value "DRUPAL_SKIP_BOOTSTRAP"
! is_empty_value "$DRUPAL_DATABASE_PORT_NUMBER" && validate_port "$DRUPAL_DATABASE_PORT_NUMBER"
! is_empty_value "$DRUPAL_DATABASE_HOST" && check_resolved_hostname "$DRUPAL_DATABASE_HOST"
check_mounted_file "DRUPAL_DATABASE_TLS_CA_FILE"
# Validate database credentials
if is_boolean_yes "$ALLOW_EMPTY_PASSWORD"; then
warn "You set the environment variable ALLOW_EMPTY_PASSWORD=${ALLOW_EMPTY_PASSWORD}. For safety reasons, do not use this flag in a production environment."
else
for empty_env_var in "DRUPAL_DATABASE_PASSWORD" "DRUPAL_PASSWORD"; do
is_empty_value "${!empty_env_var}" && print_validation_error "The ${empty_env_var} environment variable is empty or not set. Set the environment variable ALLOW_EMPTY_PASSWORD=yes to allow a blank password. This is only recommended for development environments."
done
fi
# Check that the web server is properly set up
web_server_validate || print_validation_error "Web server validation failed"
return "$error_code"
}
########################
# Ensure Drupal is initialized
# Globals:
# DRUPAL_*
# Arguments:
# None
# Returns:
# None
#########################
drupal_initialize() {
# Update Drupal configuration via mounted configuration files and environment variables
if is_file_writable "$DRUPAL_CONF_FILE"; then
# Enable mounted configuration files
if [[ -f "$DRUPAL_MOUNTED_CONF_FILE" ]]; then
info "Found mounted Drupal configuration file '${DRUPAL_MOUNTED_CONF_FILE}', copying to '${DRUPAL_CONF_FILE}'"
cp "$DRUPAL_MOUNTED_CONF_FILE" "$DRUPAL_CONF_FILE"
return
fi
fi
# Force a change in the database minimum version requirement
is_empty_value "$DRUPAL_DATABASE_MIN_VERSION" || drupal_force_database_min_version
# Check if Drupal has already been initialized and persisted in a previous run
local -r app_name="drupal"
if ! is_app_initialized "$app_name"; then
info "Trying to connect to the database server"
drupal_wait_for_db_connection "$DRUPAL_DATABASE_HOST" "$DRUPAL_DATABASE_PORT_NUMBER" "$DRUPAL_DATABASE_NAME" "$DRUPAL_DATABASE_USER" "$DRUPAL_DATABASE_PASSWORD"
# Ensure the Drupal base directory exists and has proper permissions
info "Configuring file permissions for Drupal"
ensure_dir_exists "$DRUPAL_VOLUME_DIR"
# Use daemon:root ownership for compatibility when running as a non-root user
am_i_root && configure_permissions_ownership "$DRUPAL_VOLUME_DIR" -d "775" -f "664" -u "$WEB_SERVER_DAEMON_USER" -g "root"
if ! is_boolean_yes "$DRUPAL_SKIP_BOOTSTRAP"; then
# Perform initial bootstrapping for Drupal
info "Installing Drupal site"
drupal_site_install
if ! is_empty_value "$DRUPAL_ENABLE_MODULES"; then
info "Enabling Drupal modules"
drupal_enable_modules
fi
info "Flushing Drupal cache"
drupal_flush_cache
else
info "An already initialized Drupal database was provided, configuration will be skipped"
drupal_update_database
fi
info "Persisting Drupal installation"
persist_app "$app_name" "$DRUPAL_DATA_TO_PERSIST"
else
info "Restoring persisted Drupal installation"
restore_persisted_app "$app_name" "$DRUPAL_DATA_TO_PERSIST"
info "Trying to connect to the database server"
db_host="$(drupal_database_conf_get 'host')"
db_port="$(drupal_database_conf_get 'port')"
db_name="$(drupal_database_conf_get 'database')"
db_user="$(drupal_database_conf_get 'username')"
db_pass="$(drupal_database_conf_get 'password')"
drupal_wait_for_db_connection "$db_host" "$db_port" "$db_name" "$db_user" "$db_pass"
drupal_update_database
fi
# Avoid exit code of previous commands to affect the result of this function
true
}
########################
# Get a database entry from the Drupal configuration file (settings.php)
# Globals:
# DRUPAL_*
# Arguments:
# $1 - Key
# Returns:
# None
#########################
drupal_database_conf_get() {
local -r key="${1:?key missing}"
debug "Getting ${key} from Drupal database configuration"
grep -E "^\s*'${key}' =>" "$DRUPAL_CONF_FILE" | grep -E -o "=> '.*'" | cut -f2 -d\'
}
########################
# Add or modify an entry in the Drupal configuration file (settings.php)
# Globals:
# DRUPAL_*
# Arguments:
# $1 - PHP variable name
# $2 - Value to assign to the PHP variable
# $3 - Whether the value is a literal, or if instead it should be quoted (default: no)
# Returns:
# None
#########################
drupal_conf_set() {
local -r key="${1:?key missing}"
local -r value="${2:?value missing}"
local -r is_literal="${3:-no}"
debug "Setting ${key} to '${value}' in Drupal configuration (literal: ${is_literal})"
# Sanitize key (sed does not support fixed string substitutions)
local sanitized_pattern
sanitized_pattern="^(#\s*)?$(sed 's/[]\[^$.*/]/\\&/g' <<< "$key")\s*=.*"
local entry
is_boolean_yes "$is_literal" && entry="${key} = $value;" || entry="${key} = '$value';"
# Check if the configuration exists in the file
if grep -q -E "$sanitized_pattern" "$DRUPAL_CONF_FILE"; then
# It exists, so replace the line
replace_in_file "$DRUPAL_CONF_FILE" "$sanitized_pattern" "$entry"
else
echo "$entry" >> "$DRUPAL_CONF_FILE"
fi
}
########################
# Wait until the database is accessible with the currently-known credentials
# Globals:
# *
# Arguments:
# $1 - database host
# $2 - database port
# $3 - database name
# $4 - database username
# $5 - database user password (optional)
# Returns:
# true if the database connection succeeded, false otherwise
#########################
drupal_wait_for_db_connection() {
local -r db_host="${1:?missing database host}"
local -r db_port="${2:?missing database port}"
local -r db_name="${3:?missing database name}"
local -r db_user="${4:?missing database user}"
local -r db_pass="${5:-}"
check_mysql_connection() {
echo "SELECT 1" | mysql_remote_execute "$db_host" "$db_port" "$db_name" "$db_user" "$db_pass"
}
if ! retry_while "check_mysql_connection"; then
error "Could not connect to the database"
return 1
fi
}
########################
# Drupal Site Install
# Globals:
# *
# Arguments:
# None
# Returns:
# None
#########################
drupal_site_install() {
is_empty_value "$DRUPAL_DATABASE_TLS_CA_FILE" || drupal_set_database_ssl_settings
drush_execute "-y" "site:install" "$DRUPAL_PROFILE" \
"--db-url=mysql://${DRUPAL_DATABASE_USER}:${DRUPAL_DATABASE_PASSWORD}@${DRUPAL_DATABASE_HOST}:${DRUPAL_DATABASE_PORT_NUMBER}/${DRUPAL_DATABASE_NAME}" \
"--account-name=${DRUPAL_USERNAME}" \
"--account-mail=${DRUPAL_EMAIL}" \
"--account-pass=${DRUPAL_PASSWORD}" \
"--site-name=${DRUPAL_SITE_NAME}" \
"--site-mail=${DRUPAL_EMAIL}"
# When Drupal settings are patched to allow SSL database connections, the database settings block is duplicated
# after the installation with Drush
is_empty_value "$DRUPAL_DATABASE_TLS_CA_FILE" || drupal_remove_duplicated_database_settings
# Restrict permissions of the configuration file to keep the site secure
if am_i_root; then
configure_permissions_ownership "$DRUPAL_CONF_FILE" -u "root" -g "$WEB_SERVER_DAEMON_USER" -f "644"
fi
}
########################
# Execute Drush Tool
# Globals:
# *
# Arguments:
# None
# Returns:
# None
#########################
drush_execute() {
if am_i_root; then
debug_execute gosu "$WEB_SERVER_DAEMON_USER" drush "--root=${DRUPAL_BASE_DIR}" "$@"
else
debug_execute drush "--root=${DRUPAL_BASE_DIR}" "$@"
fi
}
########################
# Get Drupal version
# Globals:
# *
# Arguments:
# None
# Returns:
# Version string
#########################
drupal_get_version() {
BITNAMI_DEBUG=true drush_execute "status" "drupal-version" "--pipe" | grep -E -o '[0-9.]+'
}
########################
# Drupal enable modules
# Globals:
# *
# Arguments:
# None
# Returns:
# None
#########################
drupal_enable_modules() {
local -a modules
read -r -a modules <<< "${DRUPAL_ENABLE_MODULES/,/ }"
[[ "${#modules[@]}" -gt 0 ]] || return 0
drush_execute "pm:enable" "--yes" "${modules[@]}"
}
########################
# Drupal flush cache
# Globals:
# *
# Arguments:
# None
# Returns:
# None
#########################
drupal_flush_cache() {
local -r major_version="$(get_sematic_version "$(drupal_get_version)" 1)"
if [[ "$major_version" -gt 7 ]]; then
drush_execute "cache:rebuild"
else
drush_execute "cache:clear" "all"
fi
}
########################
# Drupal update database
# Globals:
# *
# Arguments:
# None
# Returns:
# None
#########################
drupal_update_database() {
debug 'Upgrading Drupal database with drush...'
drush_execute "updatedb"
}
########################
# Drupal set database SSL settings
# Globals:
# *
# Arguments:
# None
# Returns:
# None
#########################
drupal_set_database_ssl_settings() {
cat >>"$DRUPAL_CONF_FILE" <<EOF
\$databases['default']['default'] = array ( // Database block with SSL support
'database' => '${DRUPAL_DATABASE_NAME}',
'username' => '${DRUPAL_DATABASE_USER}',
'password' => '${DRUPAL_DATABASE_PASSWORD}',
'prefix' => '',
'host' => '${DRUPAL_DATABASE_HOST}',
'port' => '${DRUPAL_DATABASE_PORT_NUMBER}',
'namespace' => 'Drupal\\Core\\Database\\Driver\\mysql',
'driver' => 'mysql',
'pdo' => array (
PDO::MYSQL_ATTR_SSL_CA => '${DRUPAL_DATABASE_TLS_CA_FILE}',
PDO::MYSQL_ATTR_SSL_VERIFY_SERVER_CERT => 0
)
);
EOF
}
########################
# Drupal remove duplicated database block from settings file
# Globals:
# *
# Arguments:
# None
# Returns:
# None
#########################
drupal_remove_duplicated_database_settings() {
local -r first_line_block=$'\$databases\[\'default\'\]\[\'default\'\] = array \($'
local -r last_line_block='\);'
remove_in_file "$DRUPAL_CONF_FILE" "${first_line_block}/,/${last_line_block}"
}
########################
# Drupal force database minimum version requirement.
# Required for some third-party databases that report wrong versions
# Globals:
# *
# Arguments:
# None
# Returns:
# None
#########################
drupal_force_database_min_version() {
local -r install_task_file="${DRUPAL_BASE_DIR}/core/lib/Drupal/Core/Database/Driver/mysql/Install/Tasks.php"
replace_in_file "$install_task_file" 'const MYSQL_MINIMUM_VERSION.*' "const MYSQL_MINIMUM_VERSION = '${DRUPAL_DATABASE_MIN_VERSION}';"
}
########################
# Drupal fix htaccess warning protection.
# Drupal checks for the htaccess file to prevent malicious attacks
# Globals:
# *
# Arguments:
# None
# Returns:
# None
#########################
drupal_fix_htaccess_warning_protection() {
local -r files_dir="${DRUPAL_BASE_DIR}/sites/default/files/"
local -r htaccess_file="${files_dir}/.htaccess"
ensure_dir_exists "$files_dir"
cat <<EOF >"$htaccess_file"
# Recommended protections: https://www.drupal.org/forum/newsletters/security-advisories-for-drupal-core/2013-11-20/sa-core-2013-003-drupal-core
# Turn off all options we don\'t need.
Options -Indexes -ExecCGI -Includes -MultiViews
# Set the catch-all handler to prevent scripts from being executed.
SetHandler Drupal_Security_Do_Not_Remove_See_SA_2006_006
<Files *>
# Override the handler again if we\'re run later in the evaluation list.
SetHandler Drupal_Security_Do_Not_Remove_See_SA_2013_003
</Files>
# If we know how to do it safely, disable the PHP engine entirely.
<IfModule mod_php7.c>
php_flag engine off
</IfModule>
EOF
}

View File

@@ -0,0 +1,957 @@
#!/bin/bash
#
# Bitnami MySQL Client library
# shellcheck disable=SC1091
# Load Generic Libraries
. /opt/bitnami/scripts/liblog.sh
. /opt/bitnami/scripts/libos.sh
. /opt/bitnami/scripts/libvalidations.sh
########################
# Validate settings in MYSQL_CLIENT_* environment variables
# Globals:
# DB_*
# Arguments:
# None
# Returns:
# None
#########################
mysql_client_validate() {
info "Validating settings in MYSQL_CLIENT_* env vars"
local error_code=0
# Auxiliary functions
print_validation_error() {
error "$1"
error_code=1
}
empty_password_enabled_warn() {
warn "You set the environment variable ALLOW_EMPTY_PASSWORD=${ALLOW_EMPTY_PASSWORD}. For safety reasons, do not use this flag in a production environment."
}
empty_password_error() {
print_validation_error "The $1 environment variable is empty or not set. Set the environment variable ALLOW_EMPTY_PASSWORD=yes to allow the container to be started with blank passwords. This is recommended only for development."
}
backslash_password_error() {
print_validation_error "The password cannot contain backslashes ('\'). Set the environment variable $1 with no backslashes (more info at https://dev.mysql.com/doc/refman/8.0/en/string-comparison-functions.html)"
}
check_yes_no_value() {
if ! is_yes_no_value "${!1}" && ! is_true_false_value "${!1}"; then
print_validation_error "The allowed values for ${1} are: yes no"
fi
}
# Only validate environment variables if any action needs to be performed
check_yes_no_value "DB_TLS_ENABLED"
if [[ -n "$DB_CREATE_DATABASE_USER" || -n "$DB_CREATE_DATABASE_NAME" ]]; then
if is_boolean_yes "$ALLOW_EMPTY_PASSWORD"; then
empty_password_enabled_warn
else
if [[ -z "$DB_ROOT_PASSWORD" ]]; then
empty_password_error "$(get_env_var ROOT_PASSWORD)"
fi
if [[ -n "$DB_CREATE_DATABASE_USER" ]] && [[ -z "$DB_CREATE_DATABASE_PASSWORD" ]]; then
empty_password_error "$(get_env_var CREATE_DATABASE_PASSWORD)"
fi
fi
if [[ "${DB_ROOT_PASSWORD:-}" = *\\* ]]; then
backslash_password_error "$(get_env_var ROOT_PASSWORD)"
fi
if [[ "${DB_CREATE_DATABASE_PASSWORD:-}" = *\\* ]]; then
backslash_password_error "$(get_env_var CREATE_DATABASE_PASSWORD)"
fi
fi
return "$error_code"
}
########################
# Perform actions to a database
# Globals:
# DB_*
# Arguments:
# None
# Returns:
# None
#########################
mysql_client_initialize() {
# Wrap binary to force the usage of TLS
if is_boolean_yes "$DB_TLS_ENABLED"; then
mysql_client_wrap_binary_for_tls
fi
# Wait for the database to be accessible if any action needs to be performed
if [[ -n "$DB_CREATE_DATABASE_USER" || -n "$DB_CREATE_DATABASE_NAME" ]]; then
info "Trying to connect to the database server"
check_mysql_connection() {
echo "SELECT 1" | mysql_execute "mysql" "$DB_ROOT_USER" "$DB_ROOT_PASSWORD" "-h" "$DB_DATABASE_HOST" "-P" "$DB_DATABASE_PORT_NUMBER"
}
if ! retry_while "check_mysql_connection"; then
error "Could not connect to the database server"
return 1
fi
fi
# Ensure a database user exists in the server
if [[ -n "$DB_CREATE_DATABASE_USER" ]]; then
info "Creating database user ${DB_CREATE_DATABASE_USER}"
local -a args=("$DB_CREATE_DATABASE_USER" "--host" "$DB_DATABASE_HOST" "--port" "$DB_DATABASE_PORT_NUMBER")
[[ -n "$DB_CREATE_DATABASE_PASSWORD" ]] && args+=("-p" "$DB_CREATE_DATABASE_PASSWORD")
[[ -n "$DB_DATABASE_AUTHENTICATION_PLUGIN" ]] && args+=("--auth-plugin" "$DB_DATABASE_AUTHENTICATION_PLUGIN")
mysql_ensure_optional_user_exists "${args[@]}"
fi
# Ensure a database exists in the server (and that the user has write privileges, if specified)
if [[ -n "$DB_CREATE_DATABASE_NAME" ]]; then
info "Creating database ${DB_CREATE_DATABASE_NAME}"
local -a createdb_args=("$DB_CREATE_DATABASE_NAME" "--host" "$DB_DATABASE_HOST" "--port" "$DB_DATABASE_PORT_NUMBER")
[[ -n "$DB_CREATE_DATABASE_USER" ]] && createdb_args+=("-u" "$DB_CREATE_DATABASE_USER")
[[ -n "$DB_CREATE_DATABASE_CHARACTER_SET" ]] && createdb_args+=("--character-set" "$DB_CREATE_DATABASE_CHARACTER_SET")
[[ -n "$DB_CREATE_DATABASE_COLLATE" ]] && createdb_args+=("--collate" "$DB_CREATE_DATABASE_COLLATE")
mysql_ensure_optional_database_exists "${createdb_args[@]}"
fi
}
########################
# Wrap binary to force the usage of TLS
# Globals:
# DB_*
# Arguments:
# None
# Returns:
# None
#########################
mysql_client_wrap_binary_for_tls() {
local -r wrapper_file="${DB_BIN_DIR}/mysql"
local -r wrapped_binary_file="${DB_BASE_DIR}/.bin/mysql"
mv "$wrapper_file" "$wrapped_binary_file"
cat >"$wrapper_file" <<EOF
#!/bin/sh
exec "${wrapped_binary_file}" "\$@" --ssl=1
EOF
chmod +x "$wrapper_file"
}
########################
# Extract mysql version from version string
# Globals:
# DB_*
# Arguments:
# None
# Returns:
# Version string
#########################
mysql_get_version() {
local ver_string
local -a ver_split
ver_string=$("${DB_BIN_DIR}/mysql" "--version")
ver_split=(${ver_string// / })
if [[ "$ver_string" == *" Distrib "* ]]; then
echo "${ver_split[4]::-1}"
else
echo "${ver_split[2]}"
fi
}
########################
# Gets an environment variable name based on the suffix
# Globals:
# DB_FLAVOR
# Arguments:
# $1 - environment variable suffix
# Returns:
# environment variable name
#########################
get_env_var() {
local -r id="${1:?id is required}"
echo "${DB_FLAVOR^^}_${id}"
}
########################
# Gets an environment variable value for the master node and based on the suffix
# Arguments:
# $1 - environment variable suffix
# Returns:
# environment variable value
#########################
get_master_env_var_value() {
local envVar
PREFIX=""
[[ "${DB_REPLICATION_MODE:-}" = "slave" ]] && PREFIX="MASTER_"
envVar="$(get_env_var "${PREFIX}${1}_FILE")"
if [[ -f "${!envVar:-}" ]]; then
echo "$(< "${!envVar}")"
else
envVar="$(get_env_var "${PREFIX}${1}")"
echo "${!envVar:-}"
fi
}
########################
# Execute an arbitrary query/queries against the running MySQL/MariaDB service and print to stdout
# Stdin:
# Query/queries to execute
# Globals:
# BITNAMI_DEBUG
# DB_*
# Arguments:
# $1 - Database where to run the queries
# $2 - User to run queries
# $3 - Password
# $4 - Extra MySQL CLI options
# Returns:
# None
mysql_execute_print_output() {
local -r db="${1:-}"
local -r user="${2:-root}"
local -r pass="${3:-}"
local mysql_cmd opts
read -r -a opts <<<"${@:4}"
# Process mysql CLI arguments
local -a args=()
if [[ -f "$DB_CONF_FILE" ]]; then
args+=("--defaults-file=${DB_CONF_FILE}")
fi
args+=("-N" "-u" "$user" "$db")
[[ -n "$pass" ]] && args+=("-p$pass")
[[ -n "${opts[*]:-}" ]] && args+=("${opts[@]:-}")
# Obtain the command specified via stdin
mysql_cmd="$(</dev/stdin)"
debug "Executing SQL command:\n$mysql_cmd"
"$DB_BIN_DIR/mysql" "${args[@]}" <<<"$mysql_cmd"
}
########################
# Execute an arbitrary query/queries against the running MySQL/MariaDB service
# Stdin:
# Query/queries to execute
# Globals:
# BITNAMI_DEBUG
# DB_*
# Arguments:
# $1 - Database where to run the queries
# $2 - User to run queries
# $3 - Password
# $4 - Extra MySQL CLI options
# Returns:
# None
mysql_execute() {
debug_execute "mysql_execute_print_output" "$@"
}
########################
# Execute an arbitrary query/queries against a remote MySQL/MariaDB service
# Stdin:
# Query/queries to execute
# Globals:
# BITNAMI_DEBUG
# DB_*
# Arguments:
# $1 - Remote MySQL/MariaDB service hostname
# $2 - Remote MySQL/MariaDB service port
# $3 - Database where to run the queries
# $4 - User to run queries
# $5 - Password
# $6 - Extra MySQL CLI options
# Returns:
# None
mysql_remote_execute() {
local -r hostname="${1:?hostname is required}"
local -r port="${2:?port is required}"
local -a args=("-h" "$hostname" "-P" "$port" "--connect-timeout=5")
shift 2
debug_execute "mysql_execute_print_output" "$@" "${args[@]}"
}
########################
# Checks if MySQL/MariaDB is running
# Globals:
# DB_TMP_DIR
# Arguments:
# None
# Returns:
# Boolean
#########################
is_mysql_running() {
local pid
pid="$(get_pid_from_file "$DB_PID_FILE")"
if [[ -z "$pid" ]]; then
false
else
is_service_running "$pid"
fi
}
########################
# Checks if MySQL/MariaDB is not running
# Globals:
# DB_TMP_DIR
# Arguments:
# None
# Returns:
# Boolean
#########################
is_mysql_not_running() {
! is_mysql_running
}
########################
# Starts MySQL/MariaDB in the background and waits until it's ready
# Globals:
# DB_*
# Arguments:
# None
# Returns:
# None
#########################
mysql_start_bg() {
local -a flags=("--defaults-file=${DB_CONF_FILE}" "--basedir=${DB_BASE_DIR}" "--datadir=${DB_DATA_DIR}" "--socket=${DB_SOCKET_FILE}")
# Only allow local connections until MySQL is fully initialized, to avoid apps trying to connect to MySQL before it is fully initialized
flags+=("--bind-address=127.0.0.1")
# Add flags specified via the 'DB_EXTRA_FLAGS' environment variable
read -r -a db_extra_flags <<< "$(mysql_extra_flags)"
[[ "${#db_extra_flags[@]}" -gt 0 ]] && flags+=("${db_extra_flags[@]}")
# Do not start as root, to avoid permission issues
am_i_root && flags+=("--user=${DB_DAEMON_USER}")
# The slave should only start in 'run.sh', elseways user credentials would be needed for any connection
flags+=("--skip-slave-start")
flags+=("$@")
is_mysql_running && return
info "Starting $DB_FLAVOR in background"
debug_execute "${DB_SBIN_DIR}/mysqld" "${flags[@]}" &
# we cannot use wait_for_mysql_access here as mysql_upgrade for MySQL >=8 depends on this command
# users are not configured on slave nodes during initialization due to --skip-slave-start
wait_for_mysql
# Special configuration flag for system with slow disks that could take more time
# in initializing
if [[ -n "${DB_INIT_SLEEP_TIME}" ]]; then
debug "Sleeping ${DB_INIT_SLEEP_TIME} seconds before continuing with initialization"
sleep "${DB_INIT_SLEEP_TIME}"
fi
}
########################
# Wait for MySQL/MariaDB to be running
# Globals:
# DB_TMP_DIR
# Arguments:
# None
# Returns:
# Boolean
#########################
wait_for_mysql() {
local pid
while ! is_mysql_running; do
sleep 1
done
}
########################
# Wait for MySQL/MariaDB to be ready for accepting connections
# Globals:
# DB_*
# Arguments:
# None
# Returns:
# None
#########################
wait_for_mysql_access() {
# wait until the server is up and answering queries.
local -a args=("mysql" "root")
is_boolean_yes "${ROOT_AUTH_ENABLED:-false}" && args+=("$(get_master_env_var_value ROOT_PASSWORD)")
while ! echo "select 1" | mysql_execute "${args[@]}"; do
sleep 1
done
}
########################
# Stop MySQL/Mariadb
# Globals:
# DB_*
# Arguments:
# None
# Returns:
# None
#########################
mysql_stop() {
! is_mysql_running && return
info "Stopping $DB_FLAVOR"
stop_service_using_pid "$DB_PID_FILE"
}
########################
# Initialize database data
# Globals:
# BITNAMI_DEBUG
# DB_*
# Arguments:
# None
# Returns:
# None
#########################
mysql_install_db() {
local command="${DB_BIN_DIR}/mysql_install_db"
local -a args=("--defaults-file=${DB_CONF_FILE}" "--basedir=${DB_BASE_DIR}" "--datadir=${DB_DATA_DIR}")
am_i_root && args=("${args[@]}" "--user=$DB_DAEMON_USER")
if [[ "$DB_FLAVOR" = "mysql" ]]; then
command="${DB_BIN_DIR}/mysqld"
args+=("--initialize-insecure")
else
args+=("--auth-root-authentication-method=normal")
fi
debug_execute "$command" "${args[@]}"
}
########################
# Upgrade Database Schema
# Globals:
# BITNAMI_DEBUG
# DB_*
# Arguments:
# None
# Returns:
# None
#########################
mysql_upgrade() {
local -a args=("--defaults-file=${DB_CONF_FILE}" "-u" "$DB_ROOT_USER" "--force")
local major_version minor_version patch_version
major_version="$(get_sematic_version "$(mysql_get_version)" 1)"
minor_version="$(get_sematic_version "$(mysql_get_version)" 2)"
patch_version="$(get_sematic_version "$(mysql_get_version)" 3)"
info "Running mysql_upgrade"
if [[ "$DB_FLAVOR" = "mysql" ]] && [[
"$major_version" -gt "8"
|| ( "$major_version" -eq "8" && "$minor_version" -gt "0" )
|| ( "$major_version" -eq "8" && "$minor_version" -eq "0" && "$patch_version" -ge "16" )
]]; then
mysql_stop
mysql_start_bg "--upgrade=FORCE"
else
mysql_start_bg
is_boolean_yes "${ROOT_AUTH_ENABLED:-false}" && args+=("-p$(get_master_env_var_value ROOT_PASSWORD)")
debug_execute "${DB_BIN_DIR}/mysql_upgrade" "${args[@]}"
fi
}
########################
# Migrate old custom configuration files
# Globals:
# DB_*
# Arguments:
# None
# Returns:
# None
#########################
migrate_old_configuration() {
local -r old_custom_conf_file="$DB_VOLUME_DIR/conf/my_custom.cnf"
local -r custom_conf_file="$DB_CONF_DIR/bitnami/my_custom.cnf"
debug "Persisted configuration detected. Migrating any existing 'my_custom.cnf' file to new location"
warn "Custom configuration files are not persisted any longer"
if [[ -f "$old_custom_conf_file" ]]; then
info "Adding old custom configuration to user configuration"
echo "" >> "$custom_conf_file"
cat "$old_custom_conf_file" >> "$custom_conf_file"
fi
if am_i_root; then
[[ -e "$DB_VOLUME_DIR/.initialized" ]] && rm "$DB_VOLUME_DIR/.initialized"
rm -rf "$DB_VOLUME_DIR/conf"
else
warn "Old custom configuration migrated, please manually remove the 'conf' directory from the volume use to persist data"
fi
}
########################
# Ensure a db user exists with the given password for the '%' host
# Globals:
# DB_*
# Flags:
# -p|--password - database password
# -u|--user - database user
# --auth-plugin - authentication plugin
# --use-ldap - authenticate user via LDAP
# --host - database host
# --port - database host
# Arguments:
# $1 - database user
# Returns:
# None
#########################
mysql_ensure_user_exists() {
local -r user="${1:?user is required}"
local password=""
local auth_plugin=""
local use_ldap="no"
local hosts
local auth_string=""
local ssl_ca=""
# For accessing an external database
local db_host=""
local db_port=""
# Validate arguments
shift 1
while [ "$#" -gt 0 ]; do
case "$1" in
-p|--password)
shift
password="${1:?missing database password}"
;;
--auth-plugin)
shift
auth_plugin="${1:?missing authentication plugin}"
;;
--use-ldap)
use_ldap="yes"
;;
--ssl-ca)
shift
ssl_ca="${1:?missing path to ssl CA}"
;;
--host)
shift
db_host="${1:?missing database host}"
;;
--port)
shift
db_port="${1:?missing database port}"
;;
*)
echo "Invalid command line flag $1" >&2
return 1
;;
esac
shift
done
if is_boolean_yes "$use_ldap"; then
auth_string="identified via pam using '$DB_FLAVOR'"
elif [[ -n "$password" ]]; then
if [[ -n "$auth_plugin" ]]; then
auth_string="identified with $auth_plugin by '$password'"
else
auth_string="identified by '$password'"
fi
fi
debug "creating database user \'$user\'"
local -a opts=()
[[ -n "$db_host" ]] && opts+=("-h" "${db_host}")
[[ -n "$db_port" ]] && opts+=("-P" "${db_port}")
[[ -n "$ssl_ca" ]] && opts+=("--ssl-ca" "$ssl_ca")
local mysql_create_user_cmd
[[ "$DB_FLAVOR" = "mariadb" ]] && mysql_create_user_cmd="create or replace user" || mysql_create_user_cmd="create user if not exists"
mysql_execute "mysql" "$DB_ROOT_USER" "$DB_ROOT_PASSWORD" "${opts[@]:-}" <<EOF
${mysql_create_user_cmd} '${user}'@'%' ${auth_string};
EOF
debug "Removing all other hosts for the user"
hosts=$(mysql_execute_print_output "mysql" "$DB_ROOT_USER" "$DB_ROOT_PASSWORD" "${opts[@]:-}" <<EOF
select Host from user where User='${user}' and Host!='%';
EOF
)
for host in $hosts; do
mysql_execute "mysql" "$DB_ROOT_USER" "$DB_ROOT_PASSWORD" "${opts[@]:-}" <<EOF
drop user '$user'@'$host';
EOF
done
}
########################
# Ensure a db user does not exist
# Globals:
# DB_*
# Arguments:
# $1 - db user
# Returns:
# None
#########################
mysql_ensure_user_not_exists() {
local -r user="${1}"
local hosts
if [[ -z "$user" ]]; then
debug "removing the unknown user"
else
debug "removing user $user"
fi
hosts=$(mysql_execute_print_output "mysql" "$DB_ROOT_USER" "$DB_ROOT_PASSWORD" <<EOF
select Host from user where User='$user';
EOF
)
for host in $hosts; do
mysql_execute "mysql" "$DB_ROOT_USER" "$DB_ROOT_PASSWORD" <<EOF
drop user '$user'@'$host';
EOF
done
}
########################
# Ensure the root user exists for host '%' and has full access
# Globals:
# DB_*
# Arguments:
# $1 - root user
# $2 - root password
# $3 - authentication plugin
# Returns:
# None
#########################
mysql_ensure_root_user_exists() {
local -r user="${1:?user is required}"
local -r password="${2:-}"
local -r auth_plugin="${3:-}"
local auth_plugin_str=""
local alter_view_str=""
if [[ -n "$auth_plugin" ]]; then
auth_plugin_str="with $auth_plugin"
fi
debug "Configuring root user credentials"
if [ "$DB_FLAVOR" == "mariadb" ]; then
mysql_execute "mysql" "root" <<EOF
-- create root@localhost user for local admin access
-- create user 'root'@'localhost' $([ "$password" != "" ] && echo "identified by '$password'");
-- grant all on *.* to 'root'@'localhost' with grant option;
-- create admin user for remote access
create user '$user'@'%' $([ "$password" != "" ] && echo "identified $auth_plugin_str by '$password'");
grant all on *.* to '$user'@'%' with grant option;
flush privileges;
EOF
# Since MariaDB >=10.4, the mysql.user table was replaced with a view: https://mariadb.com/kb/en/mysqluser-table/
# Views have a definer user, in this case set to 'root', which needs to exist for the view to work
# In MySQL, to avoid issues when renaming the root user, they use the 'mysql.sys' user as a definer: https://dev.mysql.com/doc/refman/5.7/en/sys-schema.html
# However, for MariaDB that is not the case, so when the 'root' user is renamed the 'mysql.user' table stops working and the view needs to be fixed
if [[ "$user" != "root" && ! "$(mysql_get_version)" =~ ^10.[0123]. ]]; then
alter_view_str="$(mysql_execute_print_output "mysql" "$user" "$password" "-s" <<EOF
-- create per-view string for altering its definer
select concat("alter definer='$user'@'%' VIEW ", table_name, " AS ", view_definition, ";") FROM information_schema.views WHERE table_schema='mysql';
EOF
)"
mysql_execute "mysql" "$user" "$password" <<<"$alter_view_str; flush privileges;"
fi
else
mysql_execute "mysql" "root" <<EOF
-- create admin user
create user '$user'@'%' $([ "$password" != "" ] && echo "identified by '$password'");
grant all on *.* to '$user'@'%' with grant option;
flush privileges;
EOF
fi
}
########################
# Ensure the application database exists
# Globals:
# DB_*
# Arguments:
# $1 - database name
# Flags:
# --character-set - character set
# --collation - collation
# --host - database host
# --port - database port
# Returns:
# None
#########################
mysql_ensure_database_exists() {
local -r database="${1:?database is required}"
local character_set=""
local collate=""
# For accessing an external database
local db_host=""
local db_port=""
# Validate arguments
shift 1
while [ "$#" -gt 0 ]; do
case "$1" in
--character-set)
shift
character_set="${1:?missing character set}"
;;
--collate)
shift
collate="${1:?missing collate}"
;;
--host)
shift
db_host="${1:?missing database host}"
;;
--port)
shift
db_port="${1:?missing database port}"
;;
*)
echo "Invalid command line flag $1" >&2
return 1
;;
esac
shift
done
local -a extra_args=()
[[ -n "$character_set" ]] && extra_args=("character set = '${character_set}'")
[[ -n "$collate" ]] && extra_args=("collate = '${collate}'")
local -a mysql_execute_cmd=("mysql_execute")
[[ -n "$db_host" && -n "$db_port" ]] && mysql_execute_cmd=("mysql_remote_execute" "$db_host" "$db_port")
debug "Creating database $database"
"${mysql_execute_cmd[@]}" "mysql" "$DB_ROOT_USER" "$DB_ROOT_PASSWORD" <<EOF
create database if not exists \`$database\` ${extra_args[@]:-};
EOF
}
########################
# Ensure a user has all privileges to access a database
# Globals:
# DB_*
# Arguments:
# $1 - database name
# $2 - database user
# $3 - database host (optional)
# $4 - database port (optional)
# Returns:
# None
#########################
mysql_ensure_user_has_database_privileges() {
local -r user="${1:?user is required}"
local -r database="${2:?db is required}"
local -r db_host="${3:-}"
local -r db_port="${4:-}"
local -a mysql_execute_cmd=("mysql_execute")
[[ -n "$db_host" && -n "$db_port" ]] && mysql_execute_cmd=("mysql_remote_execute" "$db_host" "$db_port")
debug "Providing privileges to username $user on database $database"
"${mysql_execute_cmd[@]}" "mysql" "$DB_ROOT_USER" "$DB_ROOT_PASSWORD" <<EOF
grant all on \`$database\`.* to '$user'@'%';
EOF
}
########################
# Optionally create the given database user
# Flags:
# -p|--password - database password
# --auth-plugin - authentication plugin
# --use-ldap - authenticate user via LDAP
# --host - database host
# --port - database port
# Arguments:
# $1 - user
# Returns:
# None
#########################
mysql_ensure_optional_user_exists() {
local -r user="${1:?user is missing}"
local password=""
local auth_plugin=""
local use_ldap="no"
# For accessing an external database
local db_host=""
local db_port=""
# Validate arguments
shift 1
while [ "$#" -gt 0 ]; do
case "$1" in
-p|--password)
shift
password="${1:?missing password}"
;;
--auth-plugin)
shift
auth_plugin="${1:?missing authentication plugin}"
;;
--use-ldap)
use_ldap="yes"
;;
--host)
shift
db_host="${1:?missing database host}"
;;
--port)
shift
db_port="${1:?missing database port}"
;;
*)
echo "Invalid command line flag $1" >&2
return 1
;;
esac
shift
done
local -a flags=("$user")
[[ -n "$db_host" ]] && flags+=("--host" "${db_host}")
[[ -n "$db_port" ]] && flags+=("--port" "${db_port}")
if is_boolean_yes "$use_ldap"; then
flags+=("--use-ldap")
elif [[ -n "$password" ]]; then
flags+=("-p" "$password")
[[ -n "$auth_plugin" ]] && flags=("${flags[@]}" "--auth-plugin" "$auth_plugin")
fi
mysql_ensure_user_exists "${flags[@]}"
}
########################
# Optionally create the given database, and then optionally give a user
# full privileges on the database.
# Flags:
# -u|--user - database user
# --character-set - character set
# --collation - collation
# --host - database host
# --port - database port
# Arguments:
# $1 - database name
# Returns:
# None
#########################
mysql_ensure_optional_database_exists() {
local -r database="${1:?database is missing}"
local character_set=""
local collate=""
local user=""
# For accessing an external database
local db_host=""
local db_port=""
# Validate arguments
shift 1
while [ "$#" -gt 0 ]; do
case "$1" in
--character-set)
shift
character_set="${1:?missing character set}"
;;
--collate)
shift
collate="${1:?missing collate}"
;;
-u|--user)
shift
user="${1:?missing database user}"
;;
--host)
shift
db_host="${1:?missing database host}"
;;
--port)
shift
db_port="${1:?missing database port}"
;;
*)
echo "Invalid command line flag $1" >&2
return 1
;;
esac
shift
done
local -a flags=("$database")
[[ -n "$character_set" ]] && flags+=("--character-set" "$character_set")
[[ -n "$collate" ]] && flags+=("--collate" "$collate")
[[ -n "$db_host" ]] && flags+=("--host" "$db_host")
[[ -n "$db_port" ]] && flags+=("--port" "$db_port")
mysql_ensure_database_exists "${flags[@]}"
if [[ -n "$user" ]]; then
local -a grant_flags=("$user" "$database")
[[ -n "$db_host" ]] && grant_flags+=("$db_host")
[[ -n "$db_port" ]] && grant_flags+=("$db_port")
mysql_ensure_user_has_database_privileges "${grant_flags[@]}"
fi
}
########################
# Add or modify an entry in the MySQL configuration file ("$DB_CONF_FILE")
# Globals:
# DB_*
# Arguments:
# $1 - MySQL variable name
# $2 - Value to assign to the MySQL variable
# $3 - Section in the MySQL configuration file the key is located (default: mysqld)
# $4 - Configuration file (default: "$BD_CONF_FILE")
# Returns:
# None
#########################
mysql_conf_set() {
local -r key="${1:?key missing}"
local -r value="${2:?value missing}"
read -r -a sections <<<"${3:-mysqld}"
local -r file="${4:-"$DB_CONF_FILE"}"
info "Setting ${key} option"
debug "Setting ${key} to '${value}' in ${DB_FLAVOR} configuration file ${file}"
# Check if the configuration exists in the file
for section in "${sections[@]}"; do
ini-file set --section "$section" --key "$key" --value "$value" "$file"
done
}
########################
# Update MySQL/MariaDB configuration file with user custom inputs
# Globals:
# DB_*
# Arguments:
# None
# Returns:
# None
#########################
mysql_update_custom_config() {
# Persisted configuration files from old versions
! is_dir_empty "$DB_VOLUME_DIR" && [[ -d "$DB_VOLUME_DIR/conf" ]] && migrate_old_configuration
# User injected custom configuration
if [[ -f "$DB_CONF_DIR/my_custom.cnf" ]]; then
debug "Injecting custom configuration from my_custom.conf"
cat "$DB_CONF_DIR/my_custom.cnf" > "$DB_CONF_DIR/bitnami/my_custom.cnf"
fi
! is_empty_value "$DB_USER" && mysql_conf_set "user" "$DB_USER" "mysqladmin"
! is_empty_value "$DB_PORT_NUMBER" && mysql_conf_set "port" "$DB_PORT_NUMBER" "mysqld client manager"
! is_empty_value "$DB_CHARACTER_SET" && mysql_conf_set "character_set_server" "$DB_CHARACTER_SET"
! is_empty_value "$DB_COLLATE" && mysql_conf_set "collation_server" "$DB_COLLATE"
! is_empty_value "$DB_BIND_ADDRESS" && mysql_conf_set "bind_address" "$DB_BIND_ADDRESS"
! is_empty_value "$DB_AUTHENTICATION_PLUGIN" && mysql_conf_set "default_authentication_plugin" "$DB_AUTHENTICATION_PLUGIN"
! is_empty_value "$DB_SQL_MODE" && mysql_conf_set "sql_mode" "$DB_SQL_MODE"
# Avoid exit code of previous commands to affect the result of this function
true
}
########################
# Find the path to the libjemalloc library file
# Globals:
# None
# Arguments:
# None
# Returns:
# Path to a libjemalloc shared object file
#########################
find_jemalloc_lib() {
local -a locations=( "/usr/lib" "/usr/lib64" )
local -r pattern='libjemalloc.so.[0-9]'
local path
for dir in "${locations[@]}"; do
# Find the first element matching the pattern and quit
[[ ! -d "$dir" ]] && continue
path="$(find "$dir" -name "$pattern" -print -quit)"
[[ -n "$path" ]] && break
done
echo "${path:-}"
}

View File

@@ -0,0 +1,129 @@
#!/bin/bash
#
# Bitnami PHP library
# shellcheck disable=SC1091
# Load Generic Libraries
. /opt/bitnami/scripts/libfs.sh
. /opt/bitnami/scripts/libfile.sh
. /opt/bitnami/scripts/libservice.sh
. /opt/bitnami/scripts/libvalidations.sh
########################
# Add or modify an entry in the main PHP configuration file (php.ini)
# Globals:
# PHP_CONF_FILE
# Arguments:
# $1 - Key
# $2 - Value
# $3 - File to modify (default: $PHP_CONF_FILE)
# Returns:
# None
#########################
php_conf_set() {
local -r key="${1:?key missing}"
local -r value="${2:?value missing}"
local -r file="${3:-"$PHP_CONF_FILE"}"
local pattern="^[;\s]*${key}\s*=.*$"
if [[ "$key" = "extension" || "$key" = "zend_extension" ]]; then
# The "extension" property works a bit different for PHP, as there is one per module to be included, meaning it is additive unlike other configurations
# Because of that, we first check if the extension was defined in the file to replace the proper entry
pattern="^[;\s]*${key}\s*=\s*[\"]?${value}(\.so)?[\"]?\s*$"
fi
local -r entry="${key} = ${value}"
if is_file_writable "$file"; then
# Not using the ini-file tool since it does not play well with php.ini
if grep -q -E "$pattern" "$file"; then
replace_in_file "$file" "$pattern" "$entry"
else
cat >> "$file" <<< "$entry"
fi
else
warn "The PHP configuration file '${file}' is not writable. The '${key}' option will not be configured."
fi
}
########################
# Ensure PHP is initialized
# Globals:
# PHP_*
# Arguments:
# None
# Returns:
# None
#########################
php_initialize() {
# Configure PHP options based on the runtime environment
info "Configuring PHP options"
! is_empty_value "$PHP_UPLOAD_MAX_FILESIZE" && info "Setting PHP upload_max_filesize option" && php_conf_set upload_max_filesize "$PHP_UPLOAD_MAX_FILESIZE"
! is_empty_value "$PHP_POST_MAX_SIZE" && info "Setting PHP post_max_size option" && php_conf_set post_max_size "$PHP_POST_MAX_SIZE"
! is_empty_value "$PHP_MEMORY_LIMIT" && info "Setting PHP memory_limit option" && php_conf_set memory_limit "$PHP_MEMORY_LIMIT"
# PHP-FPM configuration
! is_empty_value "$PHP_FPM_LISTEN_ADDRESS" && info "Setting PHP-FPM listen option" && php_conf_set "listen" "$PHP_FPM_LISTEN_ADDRESS" "${PHP_CONF_DIR}/php-fpm.d/www.conf"
# Avoid exit code of previous commands to affect the result of this function
true
}
########################
# Convert a yes/no value to a PHP boolean
# Globals:
# None
# Arguments:
# $1 - yes/no value
# Returns:
# None
#########################
php_convert_to_boolean() {
local -r value="${1:?missing value}"
is_boolean_yes "$value" && echo "true" || echo "false"
}
########################
# Stop PHP-FPM
# Globals:
# PHP_FPM_PID_FILE
# Arguments:
# $1 - Signal (default: SIGTERM)
# Returns:
# None
#########################
php_fpm_stop() {
local -r signal="${1:-}"
is_php_fpm_not_running && return
stop_service_using_pid "$PHP_FPM_PID_FILE" "$signal"
}
########################
# Check if PHP-FPM is running
# Globals:
# PHP_FPM_PID_FILE
# Arguments:
# None
# Returns:
# true if PHP-FPM is running, false otherwise
########################
is_php_fpm_running() {
local pid
pid="$(get_pid_from_file "$PHP_FPM_PID_FILE")"
if [[ -n "$pid" ]]; then
is_service_running "$pid"
else
false
fi
}
########################
# Check if PHP-FPM is running
# Globals:
# PHP_FPM_PID_FILE
# Arguments:
# None
# Returns:
# true PHP-FPM is not running, false otherwise
########################
is_php_fpm_not_running() {
! is_php_fpm_running
}

View File

@@ -0,0 +1,86 @@
#!/bin/bash
#
# Environment configuration for mysql
# The values for all environment variables will be set in the below order of precedence
# 1. Custom environment variables defined below after Bitnami defaults
# 2. Constants defined in this file (environment variables with no default), i.e. BITNAMI_ROOT_DIR
# 3. Environment variables overridden via external files using *_FILE variables (see below)
# 4. Environment variables set externally (i.e. current Bash context/Dockerfile/userdata)
export BITNAMI_ROOT_DIR="/opt/bitnami"
export BITNAMI_VOLUME_DIR="/bitnami"
# Logging configuration
export MODULE="${MODULE:-mysql}"
export BITNAMI_DEBUG="${BITNAMI_DEBUG:-false}"
# By setting an environment variable matching *_FILE to a file path, the prefixed environment
# variable will be overridden with the value specified in that file
mysql_env_vars=(
ALLOW_EMPTY_PASSWORD
MYSQL_CLIENT_DATABASE_AUTHENTICATION_PLUGIN
MYSQL_CLIENT_DATABASE_HOST
MYSQL_CLIENT_DATABASE_PORT_NUMBER
MYSQL_CLIENT_DATABASE_ROOT_USER
MYSQL_CLIENT_DATABASE_ROOT_PASSWORD
MYSQL_CLIENT_CREATE_DATABASE_NAME
MYSQL_CLIENT_CREATE_DATABASE_USER
MYSQL_CLIENT_CREATE_DATABASE_PASSWORD
MYSQL_CLIENT_CREATE_DATABASE_CHARACTER_SET
MYSQL_CLIENT_CREATE_DATABASE_COLLATE
MYSQL_CLIENT_TLS_ENABLED
)
for env_var in "${mysql_env_vars[@]}"; do
file_env_var="${env_var}_FILE"
if [[ -n "${!file_env_var:-}" ]]; then
export "${env_var}=$(< "${!file_env_var}")"
unset "${file_env_var}"
fi
done
unset mysql_env_vars
export DB_FLAVOR="mariadb"
# Paths
export DB_BASE_DIR="${BITNAMI_ROOT_DIR}/mysql"
export DB_VOLUME_DIR="${BITNAMI_VOLUME_DIR}/mysql"
export DB_DATA_DIR="${DB_VOLUME_DIR}/data"
export DB_BIN_DIR="${DB_BASE_DIR}/bin"
export DB_SBIN_DIR="${DB_BASE_DIR}/bin"
export DB_CONF_DIR="${DB_BASE_DIR}/conf"
export DB_LOGS_DIR="${DB_BASE_DIR}/logs"
export DB_TMP_DIR="${DB_BASE_DIR}/tmp"
export DB_CONF_FILE="${DB_CONF_DIR}/my.cnf"
export DB_PID_FILE="${DB_TMP_DIR}/mysqld.pid"
export DB_SOCKET_FILE="${DB_TMP_DIR}/mysql.sock"
export PATH="${DB_SBIN_DIR}:${DB_BIN_DIR}:/opt/bitnami/common/bin:${PATH}"
# System users (when running with a privileged user)
export DB_DAEMON_USER="mysql"
export DB_DAEMON_GROUP="mysql"
export ALLOW_EMPTY_PASSWORD="${ALLOW_EMPTY_PASSWORD:-no}"
export MYSQL_CLIENT_DATABASE_AUTHENTICATION_PLUGIN="${MYSQL_CLIENT_DATABASE_AUTHENTICATION_PLUGIN:-}"
export DB_DATABASE_AUTHENTICATION_PLUGIN="$MYSQL_CLIENT_DATABASE_AUTHENTICATION_PLUGIN"
export MYSQL_CLIENT_DATABASE_HOST="${MYSQL_CLIENT_DATABASE_HOST:-mariadb}"
export DB_DATABASE_HOST="$MYSQL_CLIENT_DATABASE_HOST"
export MYSQL_CLIENT_DATABASE_PORT_NUMBER="${MYSQL_CLIENT_DATABASE_PORT_NUMBER:-3306}"
export DB_DATABASE_PORT_NUMBER="$MYSQL_CLIENT_DATABASE_PORT_NUMBER"
export MYSQL_CLIENT_DATABASE_ROOT_USER="${MYSQL_CLIENT_DATABASE_ROOT_USER:-root}" # only used during the first initialization
export DB_ROOT_USER="$MYSQL_CLIENT_DATABASE_ROOT_USER"
export MYSQL_CLIENT_DATABASE_ROOT_PASSWORD="${MYSQL_CLIENT_DATABASE_ROOT_PASSWORD:-}" # only used during the first initialization
export DB_ROOT_PASSWORD="$MYSQL_CLIENT_DATABASE_ROOT_PASSWORD"
export MYSQL_CLIENT_CREATE_DATABASE_NAME="${MYSQL_CLIENT_CREATE_DATABASE_NAME:-}" # only used during the first initialization
export DB_CREATE_DATABASE_NAME="$MYSQL_CLIENT_CREATE_DATABASE_NAME"
export MYSQL_CLIENT_CREATE_DATABASE_USER="${MYSQL_CLIENT_CREATE_DATABASE_USER:-}"
export DB_CREATE_DATABASE_USER="$MYSQL_CLIENT_CREATE_DATABASE_USER"
export MYSQL_CLIENT_CREATE_DATABASE_PASSWORD="${MYSQL_CLIENT_CREATE_DATABASE_PASSWORD:-}"
export DB_CREATE_DATABASE_PASSWORD="$MYSQL_CLIENT_CREATE_DATABASE_PASSWORD"
export MYSQL_CLIENT_CREATE_DATABASE_CHARACTER_SET="${MYSQL_CLIENT_CREATE_DATABASE_CHARACTER_SET:-}"
export DB_CREATE_DATABASE_CHARACTER_SET="$MYSQL_CLIENT_CREATE_DATABASE_CHARACTER_SET"
export MYSQL_CLIENT_CREATE_DATABASE_COLLATE="${MYSQL_CLIENT_CREATE_DATABASE_COLLATE:-}"
export DB_CREATE_DATABASE_COLLATE="$MYSQL_CLIENT_CREATE_DATABASE_COLLATE"
export MYSQL_CLIENT_TLS_ENABLED="${MYSQL_CLIENT_TLS_ENABLED:-no}"
export DB_TLS_ENABLED="$MYSQL_CLIENT_TLS_ENABLED"
# Custom environment variables may be defined below

View File

@@ -0,0 +1,19 @@
#!/bin/bash
# shellcheck disable=SC1091
set -o errexit
set -o nounset
set -o pipefail
# set -o xtrace # Uncomment this line for debugging purposes
# Load libraries
. /opt/bitnami/scripts/libfs.sh
# Load MySQL Client environment variables
. /opt/bitnami/scripts/mysql-client-env.sh
for dir in "$DB_BIN_DIR" "${DB_BASE_DIR}/.bin"; do
ensure_dir_exists "$dir"
chmod g+rwX "$dir"
done

View File

@@ -0,0 +1,19 @@
#!/bin/bash
# shellcheck disable=SC1091
set -o errexit
set -o nounset
set -o pipefail
# set -o xtrace # Uncomment this line for debugging purposes
# Load libraries
. /opt/bitnami/scripts/libmysqlclient.sh
# Load MySQL Client environment variables
. /opt/bitnami/scripts/mysql-client-env.sh
# Ensure MySQL Client environment variables settings are valid
mysql_client_validate
# Ensure MySQL Client is initialized
mysql_client_initialize

View File

@@ -0,0 +1,67 @@
#!/bin/bash
#
# Environment configuration for php
# The values for all environment variables will be set in the below order of precedence
# 1. Custom environment variables defined below after Bitnami defaults
# 2. Constants defined in this file (environment variables with no default), i.e. BITNAMI_ROOT_DIR
# 3. Environment variables overridden via external files using *_FILE variables (see below)
# 4. Environment variables set externally (i.e. current Bash context/Dockerfile/userdata)
export BITNAMI_ROOT_DIR="/opt/bitnami"
export BITNAMI_VOLUME_DIR="/bitnami"
# Logging configuration
export MODULE="${MODULE:-php}"
export BITNAMI_DEBUG="${BITNAMI_DEBUG:-false}"
# By setting an environment variable matching *_FILE to a file path, the prefixed environment
# variable will be overridden with the value specified in that file
php_env_vars=(
PHP_FPM_LISTEN_ADDRESS
PHP_UPLOAD_MAX_FILESIZE
PHP_POST_MAX_SIZE
PHP_MEMORY_LIMIT
)
for env_var in "${php_env_vars[@]}"; do
file_env_var="${env_var}_FILE"
if [[ -n "${!file_env_var:-}" ]]; then
export "${env_var}=$(< "${!file_env_var}")"
unset "${file_env_var}"
fi
done
unset php_env_vars
# Paths
export PHP_BASE_DIR="${BITNAMI_ROOT_DIR}/php"
export PHP_BIN_DIR="${PHP_BASE_DIR}/bin"
export PHP_CONF_DIR="${PHP_BASE_DIR}/etc"
export PHP_TMP_DIR="${PHP_BASE_DIR}/var/run"
export PHP_CONF_FILE="${PHP_CONF_DIR}/php.ini"
# PHP default build-time configuration
export PHP_DEFAULT_OPCACHE_INTERNED_STRINGS_BUFFER="16" # only used at build time
export PHP_DEFAULT_OPCACHE_MEMORY_CONSUMPTION="192" # only used at build time
export PHP_DEFAULT_OPCACHE_FILE_CACHE="${PHP_TMP_DIR}/opcache_file" # only used at build time
# PHP-FPM configuration
export PHP_FPM_SBIN_DIR="${PHP_BASE_DIR}/sbin"
export PHP_FPM_LOGS_DIR="${PHP_BASE_DIR}/logs"
export PHP_FPM_LOG_FILE="${PHP_FPM_LOGS_DIR}/php-fpm.log"
export PHP_FPM_CONF_FILE="${PHP_CONF_DIR}/php-fpm.conf"
export PHP_FPM_PID_FILE="${PHP_TMP_DIR}/php-fpm.pid"
export PHP_FPM_DEFAULT_LISTEN_ADDRESS="${PHP_TMP_DIR}/www.sock" # only used at build time
export PHP_FPM_LISTEN_ADDRESS="${PHP_FPM_LISTEN_ADDRESS:-}"
export PATH="${PHP_FPM_SBIN_DIR}:${PHP_BIN_DIR}:${BITNAMI_ROOT_DIR}/common/bin:${PATH}"
# System users (when running with a privileged user)
export PHP_FPM_DAEMON_USER="daemon"
export PHP_FPM_DAEMON_GROUP="daemon"
# PHP configuration
export PHP_UPLOAD_MAX_FILESIZE="${PHP_UPLOAD_MAX_FILESIZE:-}"
export PHP_POST_MAX_SIZE="${PHP_POST_MAX_SIZE:-}"
export PHP_MEMORY_LIMIT="${PHP_MEMORY_LIMIT:-}"
# Custom environment variables may be defined below

View File

@@ -0,0 +1,38 @@
#!/bin/bash
# shellcheck disable=SC1091
set -o errexit
set -o nounset
set -o pipefail
# set -o xtrace # Uncomment this line for debugging purposes
# Load libraries
. /opt/bitnami/scripts/libphp.sh
. /opt/bitnami/scripts/libfs.sh
# Load PHP-FPM environment variables
. /opt/bitnami/scripts/php-env.sh
# PHP OPcache optimizations
php_conf_set "opcache.interned_strings_buffer" "$PHP_DEFAULT_OPCACHE_INTERNED_STRINGS_BUFFER"
php_conf_set "opcache.memory_consumption" "$PHP_DEFAULT_OPCACHE_MEMORY_CONSUMPTION"
php_conf_set "opcache.file_cache" "$PHP_DEFAULT_OPCACHE_FILE_CACHE"
# PHP-FPM configuration
php_conf_set "listen" "$PHP_FPM_DEFAULT_LISTEN_ADDRESS" "${PHP_CONF_DIR}/php-fpm.d/www.conf"
# TMP dir configuration
php_conf_set upload_tmp_dir "$PHP_TMP_DIR"
# Ensure directories used by PHP-FPM exist and have proper ownership and permissions
for dir in "$PHP_CONF_DIR" "$PHP_TMP_DIR" "$PHP_FPM_LOGS_DIR"; do
ensure_dir_exists "$dir"
chmod -R g+rwX "$dir"
done
info "Disabling PHP-FPM daemon user/group configuration"
mv "${PHP_CONF_DIR}/common.conf" "${PHP_CONF_DIR}/common.conf.disabled"
touch "${PHP_CONF_DIR}/common.conf"
ln -sf "/dev/stdout" "${PHP_FPM_LOG_FILE}"

View File

@@ -0,0 +1,19 @@
#!/bin/bash
# shellcheck disable=SC1091
set -o errexit
set -o nounset
set -o pipefail
# set -o xtrace # Uncomment this line for debugging purposes
# Load libraries
. /opt/bitnami/scripts/libphp.sh
. /opt/bitnami/scripts/liblog.sh
# Load PHP-FPM environment variables
. /opt/bitnami/scripts/php-env.sh
info "** Starting PHP-FPM **"
declare -a args=("--pid" "$PHP_FPM_PID_FILE" "--fpm-config" "$PHP_FPM_CONF_FILE" "-c" "$PHP_CONF_DIR" "-F")
exec "${PHP_FPM_SBIN_DIR}/php-fpm" "${args[@]}"

View File

@@ -0,0 +1,32 @@
#!/bin/bash
# shellcheck disable=SC1091
set -o errexit
set -o nounset
set -o pipefail
# set -o xtrace # Uncomment this line for debugging purposes
# Load libraries
. /opt/bitnami/scripts/libphp.sh
. /opt/bitnami/scripts/libfs.sh
. /opt/bitnami/scripts/libos.sh
# Load PHP-FPM environment variables
. /opt/bitnami/scripts/php-env.sh
# Ensure PHP-FPM daemon user exists and required folder belongs to this user when running as 'root'
if am_i_root; then
ensure_user_exists "$PHP_FPM_DAEMON_USER" "$PHP_FPM_DAEMON_GROUP"
ensure_dir_exists "$PHP_TMP_DIR"
chown -R "${PHP_FPM_DAEMON_USER}:${PHP_FPM_DAEMON_GROUP}" "$PHP_TMP_DIR"
# Enable daemon configuration
if [[ ! -f "${PHP_CONF_DIR}/common.conf" ]]; then
cp "${PHP_CONF_DIR}/common.conf.disabled" "${PHP_CONF_DIR}/common.conf"
fi
fi
php_initialize
# Fix logging issue when running as root
! am_i_root || chmod o+w "$(readlink /dev/stdout)" "$(readlink /dev/stderr)"

View File

@@ -39,7 +39,7 @@ Bitnami containers can be used with [Kubeapps](https://kubeapps.com/) for deploy
Learn more about the Bitnami tagging policy and the difference between rolling tags and immutable tags [in our documentation page](https://docs.bitnami.com/tutorials/understand-rolling-tags-containers/).
* [`9-debian-10`, `9.0.2-debian-10-r2`, `9`, `9.0.2`, `latest` (9/debian-10/Dockerfile)](https://github.com/bitnami/bitnami-docker-drupal/blob/9.0.2-debian-10-r2/9/debian-10/Dockerfile)
* [`9-debian-10`, `9.0.2-debian-10-r3`, `9`, `9.0.2`, `latest` (9/debian-10/Dockerfile)](https://github.com/bitnami/bitnami-docker-drupal/blob/9.0.2-debian-10-r3/9/debian-10/Dockerfile)
* [`8-debian-10`, `8.9.2-debian-10-r3`, `8`, `8.9.2` (8/debian-10/Dockerfile)](https://github.com/bitnami/bitnami-docker-drupal/blob/8.9.2-debian-10-r3/8/debian-10/Dockerfile)
Subscribe to project updates by watching the [bitnami/drupal GitHub repo](https://github.com/bitnami/bitnami-docker-drupal).

View File

@@ -1,5 +1,4 @@
version: '2'
services:
mariadb:
image: 'docker.io/bitnami/mariadb:10.3-debian-10'
@@ -8,20 +7,20 @@ services:
- MARIADB_USER=bn_drupal
- MARIADB_DATABASE=bitnami_drupal
volumes:
- 'mariadb_data:/bitnami'
- 'mariadb_data:/bitnami/mariadb'
drupal:
image: 'docker.io/bitnami/drupal:9-debian-10'
ports:
- '80:8080'
- '443:8443'
environment:
- MARIADB_HOST=mariadb
- MARIADB_PORT_NUMBER=3306
- DRUPAL_DATABASE_HOST=mariadb
- DRUPAL_DATABASE_PORT_NUMBER=3306
- DRUPAL_DATABASE_USER=bn_drupal
- DRUPAL_DATABASE_NAME=bitnami_drupal
- ALLOW_EMPTY_PASSWORD=yes
ports:
- '80:80'
- '443:443'
volumes:
- 'drupal_data:/bitnami'
- 'drupal_data:/bitnami/drupal'
depends_on:
- mariadb
volumes: