4.0.4-debian-10-r0 release
This commit is contained in:
parent
faaa9d5e17
commit
d272d76f97
|
|
@ -0,0 +1,53 @@
|
|||
FROM docker.io/bitnami/minideb:buster
|
||||
LABEL maintainer "Bitnami <containers@bitnami.com>"
|
||||
|
||||
ENV HOME="/" \
|
||||
OS_ARCH="amd64" \
|
||||
OS_FLAVOUR="debian-10" \
|
||||
OS_NAME="linux"
|
||||
|
||||
COPY prebuildfs /
|
||||
# Install required system packages and dependencies
|
||||
RUN install_packages acl ca-certificates cron curl gzip libargon2-1 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 rsync tar zlib1g
|
||||
RUN . /opt/bitnami/scripts/libcomponent.sh && component_unpack "php" "7.3.25-1" --checksum f197077c17bfd3aa8ffb20205cfb01118e97266f8d41a58db7ca0f4bf31966d8
|
||||
RUN . /opt/bitnami/scripts/libcomponent.sh && component_unpack "apache" "2.4.46-3" --checksum 07991412bb24fc8493228f4bd67b28a77e011242971dcdd687a5d2113ac89bc9
|
||||
RUN . /opt/bitnami/scripts/libcomponent.sh && component_unpack "mysql-client" "10.3.27-0" --checksum f96905e763a6334b75a7cdb07f8d89658cde02be41cb09d91d0682fc649fdcff
|
||||
RUN . /opt/bitnami/scripts/libcomponent.sh && component_unpack "libphp" "7.3.25-0" --checksum 2a37cccc40fca206beb2a7850815f5bba49ba7b80ebd2e571b75bf825a6ad608
|
||||
RUN . /opt/bitnami/scripts/libcomponent.sh && component_unpack "ini-file" "1.3.0-1" --checksum 6126368b4f1d4c6a9682c12280f2bef3c98962d079b26206e19f406cfa631055
|
||||
RUN . /opt/bitnami/scripts/libcomponent.sh && component_unpack "render-template" "1.0.0-3" --checksum 8179ad1371c9a7d897fe3b1bf53bbe763f94edafef19acad2498dd48b3674efe
|
||||
RUN . /opt/bitnami/scripts/libcomponent.sh && component_unpack "matomo" "4.0.4-0" --checksum d9c2a546da673dfd8d678e860a69cc8990ed5ee9dc3114f56d78b1273b7e2538
|
||||
RUN . /opt/bitnami/scripts/libcomponent.sh && component_unpack "gosu" "1.12.0-2" --checksum 4d858ac600c38af8de454c27b7f65c0074ec3069880cb16d259a6e40a46bbc50
|
||||
RUN apt-get update && apt-get upgrade -y && \
|
||||
rm -r /var/lib/apt/lists /var/cache/apt/archives
|
||||
RUN chmod g+rwX /opt/bitnami
|
||||
RUN sed -i -e '/pam_loginuid.so/ s/^#*/#/' /etc/pam.d/cron
|
||||
|
||||
COPY rootfs /
|
||||
RUN /opt/bitnami/scripts/php/postunpack.sh
|
||||
RUN /opt/bitnami/scripts/apache/postunpack.sh
|
||||
RUN /opt/bitnami/scripts/apache-modphp/postunpack.sh
|
||||
RUN /opt/bitnami/scripts/matomo/postunpack.sh
|
||||
RUN /opt/bitnami/scripts/mysql-client/postunpack.sh
|
||||
ENV ALLOW_EMPTY_PASSWORD="no" \
|
||||
APACHE_ENABLE_CUSTOM_PORTS="no" \
|
||||
APACHE_HTTPS_PORT_NUMBER="" \
|
||||
APACHE_HTTP_PORT_NUMBER="" \
|
||||
BITNAMI_APP_NAME="matomo" \
|
||||
BITNAMI_IMAGE_VERSION="4.0.4-debian-10-r0" \
|
||||
MARIADB_HOST="mariadb" \
|
||||
MARIADB_PORT_NUMBER="3306" \
|
||||
MARIADB_ROOT_PASSWORD="" \
|
||||
MARIADB_ROOT_USER="root" \
|
||||
MYSQL_CLIENT_CREATE_DATABASE_NAME="" \
|
||||
MYSQL_CLIENT_CREATE_DATABASE_PASSWORD="" \
|
||||
MYSQL_CLIENT_CREATE_DATABASE_PRIVILEGES="ALL" \
|
||||
MYSQL_CLIENT_CREATE_DATABASE_USER="" \
|
||||
MYSQL_CLIENT_ENABLE_SSL="no" \
|
||||
MYSQL_CLIENT_SSL_CA_FILE="" \
|
||||
PATH="/opt/bitnami/php/bin:/opt/bitnami/php/sbin:/opt/bitnami/apache/bin:/opt/bitnami/mysql/bin:/opt/bitnami/common/bin:$PATH"
|
||||
|
||||
EXPOSE 8080 8443
|
||||
|
||||
USER 1001
|
||||
ENTRYPOINT [ "/opt/bitnami/scripts/matomo/entrypoint.sh" ]
|
||||
CMD [ "/opt/bitnami/scripts/matomo/run.sh" ]
|
||||
|
|
@ -0,0 +1,33 @@
|
|||
version: "2"
|
||||
services:
|
||||
mariadb:
|
||||
image: "docker.io/bitnami/mariadb:10.3-debian-10"
|
||||
environment:
|
||||
- ALLOW_EMPTY_PASSWORD=yes
|
||||
- MARIADB_USER=bn_matomo
|
||||
- MARIADB_DATABASE=bitnami_matomo
|
||||
# Flag necessary for the database max allowed packet check
|
||||
# https://matomo.org/faq/troubleshooting/faq_183/
|
||||
- MARIADB_EXTRA_FLAGS=--max_allowed_packet=64MB
|
||||
volumes:
|
||||
- "mariadb_data:/bitnami/mariadb"
|
||||
matomo:
|
||||
image: "docker.io/bitnami/matomo:4-debian-10"
|
||||
ports:
|
||||
- "80:8080"
|
||||
- "443:8443"
|
||||
environment:
|
||||
- MATOMO_DATABASE_HOST=mariadb
|
||||
- MATOMO_DATABASE_PORT_NUMBER=3306
|
||||
- MATOMO_DATABASE_USER=bn_matomo
|
||||
- MATOMO_DATABASE_NAME=bitnami_matomo
|
||||
- ALLOW_EMPTY_PASSWORD=yes
|
||||
volumes:
|
||||
- "matomo_data:/bitnami/matomo"
|
||||
depends_on:
|
||||
- mariadb
|
||||
volumes:
|
||||
mariadb_data:
|
||||
driver: local
|
||||
matomo_data:
|
||||
driver: local
|
||||
|
|
@ -0,0 +1,58 @@
|
|||
{
|
||||
"apache": {
|
||||
"arch": "amd64",
|
||||
"digest": "07991412bb24fc8493228f4bd67b28a77e011242971dcdd687a5d2113ac89bc9",
|
||||
"distro": "debian-10",
|
||||
"type": "NAMI",
|
||||
"version": "2.4.46-3"
|
||||
},
|
||||
"gosu": {
|
||||
"arch": "amd64",
|
||||
"digest": "4d858ac600c38af8de454c27b7f65c0074ec3069880cb16d259a6e40a46bbc50",
|
||||
"distro": "debian-10",
|
||||
"type": "NAMI",
|
||||
"version": "1.12.0-2"
|
||||
},
|
||||
"ini-file": {
|
||||
"arch": "amd64",
|
||||
"digest": "6126368b4f1d4c6a9682c12280f2bef3c98962d079b26206e19f406cfa631055",
|
||||
"distro": "debian-10",
|
||||
"type": "NAMI",
|
||||
"version": "1.3.0-1"
|
||||
},
|
||||
"libphp": {
|
||||
"arch": "amd64",
|
||||
"digest": "2a37cccc40fca206beb2a7850815f5bba49ba7b80ebd2e571b75bf825a6ad608",
|
||||
"distro": "debian-10",
|
||||
"type": "NAMI",
|
||||
"version": "7.3.25-0"
|
||||
},
|
||||
"matomo": {
|
||||
"arch": "amd64",
|
||||
"digest": "d9c2a546da673dfd8d678e860a69cc8990ed5ee9dc3114f56d78b1273b7e2538",
|
||||
"distro": "debian-10",
|
||||
"type": "NAMI",
|
||||
"version": "4.0.4-0"
|
||||
},
|
||||
"mysql-client": {
|
||||
"arch": "amd64",
|
||||
"digest": "f96905e763a6334b75a7cdb07f8d89658cde02be41cb09d91d0682fc649fdcff",
|
||||
"distro": "debian-10",
|
||||
"type": "NAMI",
|
||||
"version": "10.3.27-0"
|
||||
},
|
||||
"php": {
|
||||
"arch": "amd64",
|
||||
"digest": "f197077c17bfd3aa8ffb20205cfb01118e97266f8d41a58db7ca0f4bf31966d8",
|
||||
"distro": "debian-10",
|
||||
"type": "NAMI",
|
||||
"version": "7.3.25-1"
|
||||
},
|
||||
"render-template": {
|
||||
"arch": "amd64",
|
||||
"digest": "8179ad1371c9a7d897fe3b1bf53bbe763f94edafef19acad2498dd48b3674efe",
|
||||
"distro": "debian-10",
|
||||
"type": "NAMI",
|
||||
"version": "1.0.0-3"
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
Bitnami containers ship with software bundles. You can find the licenses under:
|
||||
/opt/bitnami/nami/COPYING
|
||||
/opt/bitnami/[name-of-bundle]/licenses/[bundle-version].txt
|
||||
|
|
@ -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 ""
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,65 @@
|
|||
#!/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"
|
||||
}
|
||||
|
|
@ -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"
|
||||
}
|
||||
|
|
@ -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
|
||||
}
|
||||
|
|
@ -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}/"
|
||||
}
|
||||
|
|
@ -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}]}"
|
||||
}
|
||||
|
|
@ -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}'
|
||||
}
|
||||
|
|
@ -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
|
||||
}
|
||||
|
|
@ -0,0 +1,225 @@
|
|||
#!/bin/bash
|
||||
#
|
||||
# Library for managing services
|
||||
|
||||
# shellcheck disable=SC1091
|
||||
|
||||
# Load Generic Libraries
|
||||
. /opt/bitnami/scripts/libvalidations.sh
|
||||
. /opt/bitnami/scripts/liblog.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 - Service name
|
||||
# $2 - Log files pattern
|
||||
# Flags:
|
||||
# --period - Period
|
||||
# --rotations - Number of rotations to store
|
||||
# --extra - 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="weekly"
|
||||
local rotations="150"
|
||||
local extra=""
|
||||
local logrotate_conf_dir="/etc/logrotate.d"
|
||||
local var_name
|
||||
# Parse optional CLI flags
|
||||
shift 2
|
||||
while [[ "$#" -gt 0 ]]; do
|
||||
case "$1" in
|
||||
--period|--rotations|--extra)
|
||||
var_name="$(echo "$1" | sed -e "s/^--//" -e "s/-/_/g")"
|
||||
shift
|
||||
declare "$var_name"="${1:?"$var_name" is missing}"
|
||||
;;
|
||||
*)
|
||||
echo "Invalid command line flag ${1}" >&2
|
||||
return 1
|
||||
;;
|
||||
esac
|
||||
shift
|
||||
done
|
||||
|
||||
mkdir -p "$logrotate_conf_dir"
|
||||
cat <<EOF | sed '/^\s*$/d' >"${logrotate_conf_dir}/${service_name}"
|
||||
${log_path} {
|
||||
${period}
|
||||
rotate ${rotations}
|
||||
dateext
|
||||
compress
|
||||
copytruncate
|
||||
missingok
|
||||
$(indent "$extra" 2)
|
||||
}
|
||||
EOF
|
||||
}
|
||||
|
|
@ -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
|
||||
}
|
||||
|
|
@ -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
|
||||
}
|
||||
|
|
@ -0,0 +1,422 @@
|
|||
#!/bin/bash
|
||||
#
|
||||
# Bitnami web server handler library
|
||||
|
||||
# shellcheck disable=SC1090,SC1091
|
||||
|
||||
# Load generic libraries
|
||||
. /opt/bitnami/scripts/liblog.sh
|
||||
|
||||
########################
|
||||
# Execute a command (or list of commands) with the web server environment and library loaded
|
||||
# Globals:
|
||||
# *
|
||||
# Arguments:
|
||||
# None
|
||||
# Returns:
|
||||
# None
|
||||
#########################
|
||||
web_server_execute() {
|
||||
local -r web_server="${1:?missing web server}"
|
||||
shift
|
||||
# Run program in sub-shell to avoid web server environment getting loaded when not necessary
|
||||
(
|
||||
. "/opt/bitnami/scripts/lib${web_server}.sh"
|
||||
. "/opt/bitnami/scripts/${web_server}-env.sh"
|
||||
"$@"
|
||||
)
|
||||
}
|
||||
|
||||
########################
|
||||
# Prints the list of enabled web servers
|
||||
# Globals:
|
||||
# None
|
||||
# Arguments:
|
||||
# None
|
||||
# Returns:
|
||||
# None
|
||||
#########################
|
||||
web_server_list() {
|
||||
local -r -a supported_web_servers=(apache nginx)
|
||||
local -a existing_web_servers=()
|
||||
for web_server in "${supported_web_servers[@]}"; do
|
||||
[[ -f "/opt/bitnami/scripts/${web_server}-env.sh" ]] && existing_web_servers+=("$web_server")
|
||||
done
|
||||
echo "${existing_web_servers[@]:-}"
|
||||
}
|
||||
|
||||
########################
|
||||
# Prints the currently-enabled web server type (only one, in order of preference)
|
||||
# Globals:
|
||||
# None
|
||||
# Arguments:
|
||||
# None
|
||||
# Returns:
|
||||
# None
|
||||
#########################
|
||||
web_server_type() {
|
||||
local -a web_servers
|
||||
read -r -a web_servers <<< "$(web_server_list)"
|
||||
echo "${web_servers[0]:-}"
|
||||
}
|
||||
|
||||
########################
|
||||
# Validate that a supported web server is configured
|
||||
# Globals:
|
||||
# None
|
||||
# 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 ! web_server_execute "$(web_server_type)" 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() {
|
||||
info "Starting $(web_server_type) in background"
|
||||
"${BITNAMI_ROOT_DIR}/scripts/$(web_server_type)/start.sh"
|
||||
}
|
||||
|
||||
########################
|
||||
# Stop web server
|
||||
# Globals:
|
||||
# *
|
||||
# Arguments:
|
||||
# None
|
||||
# Returns:
|
||||
# None
|
||||
#########################
|
||||
web_server_stop() {
|
||||
info "Stopping $(web_server_type)"
|
||||
"${BITNAMI_ROOT_DIR}/scripts/$(web_server_type)/stop.sh"
|
||||
}
|
||||
|
||||
########################
|
||||
# Restart web server
|
||||
# Globals:
|
||||
# *
|
||||
# Arguments:
|
||||
# None
|
||||
# Returns:
|
||||
# None
|
||||
#########################
|
||||
web_server_restart() {
|
||||
info "Restarting $(web_server_type)"
|
||||
"${BITNAMI_ROOT_DIR}/scripts/$(web_server_type)/restart.sh"
|
||||
}
|
||||
|
||||
########################
|
||||
# Reload web server
|
||||
# Globals:
|
||||
# *
|
||||
# Arguments:
|
||||
# None
|
||||
# Returns:
|
||||
# None
|
||||
#########################
|
||||
web_server_reload() {
|
||||
info "Reloading $(web_server_type) configuration"
|
||||
"${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}"
|
||||
shift
|
||||
local -a apache_args nginx_args web_servers args_var
|
||||
apache_args=("$app")
|
||||
nginx_args=("$app")
|
||||
# Validate arguments
|
||||
while [[ "$#" -gt 0 ]]; do
|
||||
case "$1" in
|
||||
# Common flags
|
||||
--hosts \
|
||||
| --type \
|
||||
| --allow-remote-connections \
|
||||
| --disabled \
|
||||
| --enable-https \
|
||||
| --http-port \
|
||||
| --https-port \
|
||||
| --document-root \
|
||||
)
|
||||
apache_args+=("$1" "${2:?missing value}")
|
||||
nginx_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 \
|
||||
)
|
||||
apache_args+=("${1//apache-/}" "${2:?missing value}")
|
||||
shift
|
||||
;;
|
||||
|
||||
# Specific NGINX flags
|
||||
--nginx-additional-configuration)
|
||||
nginx_args+=("${1//nginx-/}" "${2:?missing value}")
|
||||
shift
|
||||
;;
|
||||
|
||||
*)
|
||||
echo "Invalid command line flag $1" >&2
|
||||
return 1
|
||||
;;
|
||||
esac
|
||||
shift
|
||||
done
|
||||
read -r -a web_servers <<< "$(web_server_list)"
|
||||
for web_server in "${web_servers[@]}"; do
|
||||
args_var="${web_server}_args[@]"
|
||||
web_server_execute "$web_server" "ensure_${web_server}_app_configuration_exists" "${!args_var}"
|
||||
done
|
||||
}
|
||||
|
||||
########################
|
||||
# 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}"
|
||||
local -a web_servers
|
||||
read -r -a web_servers <<< "$(web_server_list)"
|
||||
for web_server in "${web_servers[@]}"; do
|
||||
web_server_execute "$web_server" "ensure_${web_server}_app_configuration_not_exists" "$app"
|
||||
done
|
||||
}
|
||||
|
||||
########################
|
||||
# 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}"
|
||||
shift
|
||||
local -a apache_args nginx_args web_servers args_var
|
||||
apache_args=("$app")
|
||||
nginx_args=("$app")
|
||||
# Validate arguments
|
||||
while [[ "$#" -gt 0 ]]; do
|
||||
case "$1" in
|
||||
# Common flags
|
||||
--allow-remote-connections \
|
||||
| --document-root \
|
||||
| --prefix \
|
||||
| --type \
|
||||
)
|
||||
apache_args+=("$1" "${2:?missing value}")
|
||||
nginx_args+=("$1" "${2:?missing value}")
|
||||
shift
|
||||
;;
|
||||
|
||||
# Specific Apache flags
|
||||
--apache-additional-configuration \
|
||||
| --apache-allow-override \
|
||||
| --apache-extra-directory-configuration \
|
||||
| --apache-move-htaccess \
|
||||
)
|
||||
apache_args+=("${1//apache-/}" "$2")
|
||||
shift
|
||||
;;
|
||||
|
||||
# Specific NGINX flags
|
||||
--nginx-additional-configuration)
|
||||
nginx_args+=("${1//nginx-/}" "$2")
|
||||
shift
|
||||
;;
|
||||
|
||||
*)
|
||||
echo "Invalid command line flag $1" >&2
|
||||
return 1
|
||||
;;
|
||||
esac
|
||||
shift
|
||||
done
|
||||
read -r -a web_servers <<< "$(web_server_list)"
|
||||
for web_server in "${web_servers[@]}"; do
|
||||
args_var="${web_server}_args[@]"
|
||||
web_server_execute "$web_server" "ensure_${web_server}_prefix_configuration_exists" "${!args_var}"
|
||||
done
|
||||
}
|
||||
|
||||
########################
|
||||
# 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}"
|
||||
shift
|
||||
local -a args web_servers
|
||||
args=("$app")
|
||||
# Validate arguments
|
||||
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
|
||||
read -r -a web_servers <<< "$(web_server_list)"
|
||||
for web_server in "${web_servers[@]}"; do
|
||||
web_server_execute "$web_server" "${web_server}_update_app_configuration" "${args[@]}"
|
||||
done
|
||||
}
|
||||
|
||||
########################
|
||||
# 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
|
||||
}
|
||||
|
|
@ -0,0 +1,24 @@
|
|||
#!/bin/sh
|
||||
set -e
|
||||
set -u
|
||||
export DEBIAN_FRONTEND=noninteractive
|
||||
n=0
|
||||
max=2
|
||||
until [ $n -gt $max ]; do
|
||||
set +e
|
||||
(
|
||||
apt-get update -qq &&
|
||||
apt-get install -y --no-install-recommends "$@"
|
||||
)
|
||||
CODE=$?
|
||||
set -e
|
||||
if [ $CODE -eq 0 ]; then
|
||||
break
|
||||
fi
|
||||
if [ $n -eq $max ]; then
|
||||
exit $CODE
|
||||
fi
|
||||
echo "apt failed, retrying"
|
||||
n=$(($n + 1))
|
||||
done
|
||||
rm -r /var/lib/apt/lists /var/cache/apt/archives
|
||||
|
|
@ -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-----
|
||||
|
|
@ -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-----
|
||||
|
|
@ -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>
|
||||
|
|
@ -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
|
||||
APACHE_HTTP_PORT
|
||||
APACHE_HTTPS_PORT
|
||||
)
|
||||
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"
|
||||
export WEB_SERVER_DEFAULT_HTTP_PORT_NUMBER="$APACHE_DEFAULT_HTTP_PORT_NUMBER" # only used at build time
|
||||
export APACHE_DEFAULT_HTTPS_PORT_NUMBER="8443"
|
||||
export WEB_SERVER_DEFAULT_HTTPS_PORT_NUMBER="$APACHE_DEFAULT_HTTPS_PORT_NUMBER" # only used at build time
|
||||
APACHE_HTTP_PORT_NUMBER="${APACHE_HTTP_PORT_NUMBER:-"${APACHE_HTTP_PORT:-}"}"
|
||||
export APACHE_HTTP_PORT_NUMBER="${APACHE_HTTP_PORT_NUMBER:-}"
|
||||
export WEB_SERVER_HTTP_PORT_NUMBER="$APACHE_HTTP_PORT_NUMBER"
|
||||
APACHE_HTTPS_PORT_NUMBER="${APACHE_HTTPS_PORT_NUMBER:-"${APACHE_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
|
||||
|
|
@ -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}\""
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
{{before_vhost_configuration}}
|
||||
<VirtualHost {{http_listen_addresses}}>
|
||||
ServerAlias *
|
||||
{{additional_configuration}}
|
||||
</VirtualHost>
|
||||
|
|
@ -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>
|
||||
|
|
@ -0,0 +1 @@
|
|||
{{additional_configuration}}
|
||||
|
|
@ -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>
|
||||
|
|
@ -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>
|
||||
|
|
@ -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}}
|
||||
|
|
@ -0,0 +1,14 @@
|
|||
{{before_vhost_configuration}}
|
||||
PassengerPreStart http://localhost:{{APACHE_DEFAULT_HTTP_PORT_NUMBER}}/
|
||||
<VirtualHost {{http_listen_addresses}}>
|
||||
ServerAlias *
|
||||
DocumentRoot {{document_root}}
|
||||
<Directory "{{document_root}}">
|
||||
Options -Indexes +FollowSymLinks -MultiViews
|
||||
AllowOverride {{allow_override}}
|
||||
{{acl_configuration}}
|
||||
PassengerEnabled on
|
||||
{{extra_directory_configuration}}
|
||||
</Directory>
|
||||
{{additional_configuration}}
|
||||
</VirtualHost>
|
||||
|
|
@ -0,0 +1,17 @@
|
|||
{{before_vhost_configuration}}
|
||||
PassengerPreStart https://localhost:{{APACHE_DEFAULT_HTTPS_PORT_NUMBER}}/
|
||||
<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}}
|
||||
PassengerEnabled on
|
||||
{{extra_directory_configuration}}
|
||||
</Directory>
|
||||
{{additional_configuration}}
|
||||
</VirtualHost>
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
{{prefix_conf}}
|
||||
<Directory "{{document_root}}">
|
||||
Options -Indexes +FollowSymLinks -MultiViews
|
||||
AllowOverride {{allow_override}}
|
||||
{{acl_configuration}}
|
||||
PassengerEnabled on
|
||||
{{extra_directory_configuration}}
|
||||
</Directory>
|
||||
{{additional_configuration}}
|
||||
|
|
@ -0,0 +1,34 @@
|
|||
# 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
|
||||
|
||||
<Location /server-status>
|
||||
Require local
|
||||
SetHandler server-status
|
||||
</Location>
|
||||
</VirtualHost>
|
||||
|
|
@ -0,0 +1,23 @@
|
|||
# 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
|
||||
|
||||
<Location /server-status>
|
||||
Require local
|
||||
SetHandler server-status
|
||||
</Location>
|
||||
</VirtualHost>
|
||||
|
||||
Include "{{APACHE_CONF_DIR}}/bitnami/bitnami-ssl.conf"
|
||||
|
|
@ -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 "$@"
|
||||
|
|
@ -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 unnecessary directories that come with the tarball
|
||||
rm -rf "${BITNAMI_ROOT_DIR}/certs" "${BITNAMI_ROOT_DIR}/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"
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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"
|
||||
|
|
@ -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)"
|
||||
|
|
@ -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}"
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
BITNAMI_QUIET=1 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}"
|
||||
|
|
@ -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
|
||||
}
|
||||
|
|
@ -0,0 +1,397 @@
|
|||
#!/bin/bash
|
||||
#
|
||||
# Bitnami Matomo library
|
||||
|
||||
# shellcheck disable=SC1091
|
||||
|
||||
# Load generic libraries
|
||||
. /opt/bitnami/scripts/libphp.sh
|
||||
. /opt/bitnami/scripts/libfs.sh
|
||||
. /opt/bitnami/scripts/libos.sh
|
||||
. /opt/bitnami/scripts/libvalidations.sh
|
||||
. /opt/bitnami/scripts/libpersistence.sh
|
||||
. /opt/bitnami/scripts/libwebserver.sh
|
||||
|
||||
# Load database library
|
||||
if [[ -f /opt/bitnami/scripts/libmysqlclient.sh ]]; then
|
||||
. /opt/bitnami/scripts/libmysqlclient.sh
|
||||
elif [[ -f /opt/bitnami/scripts/libmysql.sh ]]; then
|
||||
. /opt/bitnami/scripts/libmysql.sh
|
||||
elif [[ -f /opt/bitnami/scripts/libmariadb.sh ]]; then
|
||||
. /opt/bitnami/scripts/libmariadb.sh
|
||||
fi
|
||||
|
||||
########################
|
||||
# Validate settings in MATOMO_* env vars
|
||||
# Globals:
|
||||
# MATOMO_*
|
||||
# Arguments:
|
||||
# None
|
||||
# Returns:
|
||||
# 0 if the validation succeeded, 1 otherwise
|
||||
#########################
|
||||
matomo_validate() {
|
||||
debug "Validating settings in MATOMO_* 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_multi_value() {
|
||||
if [[ " ${2} " != *" ${!1} "* ]]; then
|
||||
print_validation_error "The allowed values for ${1} are: ${2}"
|
||||
fi
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
# Validate 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 "MATOMO_DATABASE_PASSWORD" "MATOMO_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 yes no values
|
||||
for yes_no_var in "MATOMO_ENABLE_DATABASE_SSL" "MATOMO_ENABLE_PROXY_URI_HEADER" "MATOMO_VERIFY_DATABASE_SSL"; do
|
||||
check_yes_no_value "${yes_no_var}"
|
||||
done
|
||||
|
||||
# Validate SMTP credentials
|
||||
if ! is_empty_value "$MATOMO_SMTP_HOST"; then
|
||||
for empty_env_var in "MATOMO_SMTP_USER" "MATOMO_SMTP_PASSWORD" "MATOMO_SMTP_PORT_NUMBER"; do
|
||||
is_empty_value "${!empty_env_var}" && print_validation_error "The ${empty_env_var} environment variable is empty or not set."
|
||||
done
|
||||
check_allowed_port MATOMO_SMTP_PORT_NUMBER
|
||||
! is_empty_value "$MATOMO_SMTP_PROTOCOL" && check_multi_value "MATOMO_SMTP_PROTOCOL" "ssl tls none"
|
||||
! is_empty_value "$MATOMO_SMTP_AUTH" && check_multi_value "MATOMO_SMTP_PROTOCOL" "Plain Login Crammd5"
|
||||
fi
|
||||
|
||||
# Check that the web server is properly set up
|
||||
web_server_validate || print_validation_error "Web server validation failed"
|
||||
|
||||
return "$error_code"
|
||||
}
|
||||
|
||||
########################
|
||||
# Ensure Matomo is initialized
|
||||
# Globals:
|
||||
# MATOMO_*
|
||||
# Arguments:
|
||||
# None
|
||||
# Returns:
|
||||
# None
|
||||
#########################
|
||||
matomo_initialize() {
|
||||
# Update Matomo configuration via mounted configuration files and environment variables
|
||||
# Check if Matomo has already been initialized and persisted in a previous run
|
||||
local db_host db_port db_name db_user db_pass
|
||||
local -r app_name="matomo"
|
||||
if ! is_app_initialized "$app_name"; then
|
||||
# Ensure Matomo persisted directories exist (i.e. when a volume has been mounted to /bitnami)
|
||||
info "Ensuring Matomo directories exist"
|
||||
ensure_dir_exists "$MATOMO_VOLUME_DIR"
|
||||
# Use daemon:root ownership for compatibility when running as a non-root user
|
||||
am_i_root && configure_permissions_ownership "$MATOMO_VOLUME_DIR" -d "775" -f "664" -u "$WEB_SERVER_DAEMON_USER" -g "root"
|
||||
info "Trying to connect to the database server"
|
||||
db_host="$MATOMO_DATABASE_HOST"
|
||||
db_port="$MATOMO_DATABASE_PORT_NUMBER"
|
||||
db_name="$MATOMO_DATABASE_NAME"
|
||||
db_user="$MATOMO_DATABASE_USER"
|
||||
db_pass="$MATOMO_DATABASE_PASSWORD"
|
||||
matomo_wait_for_db_connection "$db_host" "$db_port" "$db_name" "$db_user" "$db_pass"
|
||||
|
||||
if ! is_boolean_yes "$MATOMO_SKIP_BOOTSTRAP"; then
|
||||
matomo_pass_wizard
|
||||
local -a mysql_execute_args=("$db_host" "$db_port" "$db_name" "$db_user" "$db_pass")
|
||||
if am_i_root; then
|
||||
## If the application is running as root, the cron jobs will be executed, so we need to disable
|
||||
## the browser-triggered archiving so the "Last Successful Archiving Completion" check passes.
|
||||
## In a non-root container we can only use the browser-triggered archiving, meaning that the
|
||||
## system check will show a warning (but not a failure)
|
||||
## https://matomo.org/docs/setup-auto-archiving/
|
||||
mysql_remote_execute "${mysql_execute_args[@]}" <<EOF
|
||||
REPLACE INTO matomo_option VALUES ("enableBrowserTriggerArchiving","0",1);
|
||||
EOF
|
||||
fi
|
||||
else
|
||||
info "An already initialized Matomo database was provided, configuration will be skipped"
|
||||
## Unfortunately, due to how Matomo is designed, it requires passing through the wizard which will not only
|
||||
## re-install the application, but also has some limitations (i.e. supporting only non-SSL db connections)
|
||||
## Therefore, we'll make use of a valid configuration base to modify it to our interest
|
||||
## NOTE: After the first user access, Matomo will re-write the file as if it were created by the wizard
|
||||
cp "$MATOMO_CONF_DIR"/global.ini.php "$MATOMO_CONF_FILE"
|
||||
# We need the configuration file to be writable
|
||||
am_i_root && configure_permissions_ownership "$MATOMO_CONF_FILE" -d "775" -f "664" -u "$WEB_SERVER_DAEMON_USER" -g "root"
|
||||
info "Setting database configuration"
|
||||
ini-file set -s "database" -k "host" -v "$db_host" "$MATOMO_CONF_FILE"
|
||||
ini-file set -s "database" -k "username" -v "$db_user" "$MATOMO_CONF_FILE"
|
||||
ini-file set -s "database" -k "password" -v "$db_pass" "$MATOMO_CONF_FILE"
|
||||
ini-file set -s "database" -k "port" -v "$db_port" "$MATOMO_CONF_FILE"
|
||||
ini-file set -s "database" -k "dbname" -v "$db_name" "$MATOMO_CONF_FILE"
|
||||
ini-file set -s "database" -k "adapter" -v "MYSQLI" "$MATOMO_CONF_FILE"
|
||||
ini-file set -s "database" -k "tables_prefix" -v "matomo_" "$MATOMO_CONF_FILE"
|
||||
fi
|
||||
|
||||
# Configuration options
|
||||
|
||||
if is_boolean_yes "$MATOMO_ENABLE_PROXY_URI_HEADER"; then
|
||||
info "Configuring Matomo to use the HTTP_X_FORWARDED_URI header"
|
||||
ini-file set -s "General" -k "proxy_uri_header" -v "1" "$MATOMO_CONF_FILE"
|
||||
fi
|
||||
|
||||
# Database SSL
|
||||
ini-file set -s "General" -k "force_ssl" -v "0" "$MATOMO_CONF_FILE"
|
||||
if is_boolean_yes "$MATOMO_ENABLE_DATABASE_SSL"; then
|
||||
info "Enabling database SSL"
|
||||
ini-file set -s "database" -k "enable_ssl" -v "1" "$MATOMO_CONF_FILE"
|
||||
! is_empty_value "$MATOMO_DATABASE_SSL_CA_FILE" && ini-file set -s "database" -k "ssl_ca" -v "$MATOMO_DATABASE_SSL_CA_FILE" "$MATOMO_CONF_FILE"
|
||||
! is_empty_value "$MATOMO_DATABASE_SSL_CERT_FILE" && ini-file set -s "database" -k "ssl_cert" -v "$MATOMO_DATABASE_SSL_CERT_FILE" "$MATOMO_CONF_FILE"
|
||||
! is_empty_value "$MATOMO_DATABASE_SSL_KEY_FILE" && ini-file set -s "database" -k "ssl_key" -v "$MATOMO_DATABASE_SSL_KEY_FILE" "$MATOMO_CONF_FILE"
|
||||
! is_boolean_yes "$MATOMO_DATABASE_SSL_KEY_FILE" && ini-file set -s "database" -k "ssl_no_verify" -v "1" "$MATOMO_CONF_FILE"
|
||||
fi
|
||||
|
||||
# Trusted host check
|
||||
if is_boolean_yes "$MATOMO_ENABLE_TRUSTED_HOST_CHECK"; then
|
||||
ini-file set -s "General" -k "enable_trusted_host_check" -v "1" "$MATOMO_CONF_FILE"
|
||||
else
|
||||
ini-file set -s "General" -k "enable_trusted_host_check" -v "0" "$MATOMO_CONF_FILE"
|
||||
fi
|
||||
|
||||
# SMTP
|
||||
if ! is_empty_value "$MATOMO_SMTP_HOST"; then
|
||||
info "Configuring SMTP credentials"
|
||||
ini-file set -s "mail" -k "transport" -v "smtp" "$MATOMO_CONF_FILE"
|
||||
ini-file set -s "mail" -k "port" -v "$MATOMO_SMTP_PORT_NUMBER" "$MATOMO_CONF_FILE"
|
||||
ini-file set -s "mail" -k "host" -v "$MATOMO_SMTP_HOST" "$MATOMO_CONF_FILE"
|
||||
ini-file set -s "mail" -k "username" -v "$MATOMO_SMTP_USER" "$MATOMO_CONF_FILE"
|
||||
ini-file set -s "mail" -k "password" -v "$MATOMO_SMTP_PASSWORD" "$MATOMO_CONF_FILE"
|
||||
ini-file set -s "mail" -k "type" -v "$MATOMO_SMTP_AUTH" "$MATOMO_CONF_FILE"
|
||||
ini-file set -s "mail" -k "encryption" -v "$MATOMO_SMTP_PROTOCOL" "$MATOMO_CONF_FILE"
|
||||
fi
|
||||
|
||||
info "Persisting Matomo installation"
|
||||
persist_app "$app_name" "$MATOMO_DATA_TO_PERSIST"
|
||||
else
|
||||
info "Persisted Matomo installation detected"
|
||||
# Update default plugins
|
||||
info "Updating default plugins in persisted data"
|
||||
rsync -a "$MATOMO_BASE_DIR"/plugins/ "$MATOMO_VOLUME_DIR"/plugins/
|
||||
info "Restoring Matomo installation"
|
||||
restore_persisted_app "$app_name" "$MATOMO_DATA_TO_PERSIST"
|
||||
info "Trying to connect to the database server"
|
||||
db_host="$(ini-file get -s "database" -k "host" "$MATOMO_CONF_FILE")"
|
||||
db_port="$(ini-file get -s "database" -k "port" "$MATOMO_CONF_FILE")"
|
||||
# If port is 3306 it will not appear in the configuration file
|
||||
is_empty_value "$db_port" && db_port="3306"
|
||||
db_name="$(ini-file get -s "database" -k "dbname" "$MATOMO_CONF_FILE")"
|
||||
db_user="$(ini-file get -s "database" -k "username" "$MATOMO_CONF_FILE")"
|
||||
db_pass="$(ini-file get -s "database" -k "password" "$MATOMO_CONF_FILE")"
|
||||
matomo_wait_for_db_connection "$db_host" "$db_port" "$db_name" "$db_user" "$db_pass"
|
||||
info "Launching schema update"
|
||||
php "$MATOMO_BASE_DIR"/console "core:update" "--yes"
|
||||
am_i_root && configure_permissions_ownership "$MATOMO_BASE_DIR"/tmp -d "775" -f "664" -u "$WEB_SERVER_DAEMON_USER" -g "root"
|
||||
fi
|
||||
|
||||
## Ensure Matomo cron jobs are created when running setup with a root user
|
||||
## This is necessary for the "Last Successful Archiving Completion" system check to pass
|
||||
## https://matomo.org/docs/setup-auto-archiving/
|
||||
if am_i_root; then
|
||||
local -r port="${WEB_SERVER_HTTP_PORT_NUMBER:-"$WEB_SERVER_DEFAULT_HTTP_PORT_NUMBER"}"
|
||||
info "Configuring cron jobs"
|
||||
cron_cmd=("${PHP_BIN_DIR}/php" "${MATOMO_BASE_DIR}/console" "core:archive" "--url=http://127.0.0.1:${port}")
|
||||
generate_cron_conf "matomo" "${cron_cmd[*]} > /dev/null 2>> ${MATOMO_BASE_DIR}/tmp/logs/matomo-cron.log" --run-as "$WEB_SERVER_DAEMON_USER" --schedule "*/1 * * * *"
|
||||
else
|
||||
warn "Skipping cron configuration for Matomo because of running as a non-root user"
|
||||
fi
|
||||
|
||||
# Avoid exit code of previous commands to affect the result of this function
|
||||
true
|
||||
}
|
||||
|
||||
########################
|
||||
# Add or modify an entry in the Matomo configuration file (config.inc.php)
|
||||
# Globals:
|
||||
# MATOMO_*
|
||||
# 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
|
||||
#########################
|
||||
matomo_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 Matomo configuration (literal: ${is_literal})"
|
||||
# Sanitize key (sed does not support fixed string substitutions)
|
||||
local sanitized_pattern
|
||||
sanitized_pattern="^\s*(//\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" "$MATOMO_CONF_FILE"; then
|
||||
# It exists, so replace the line
|
||||
replace_in_file "$MATOMO_CONF_FILE" "$sanitized_pattern" "$entry"
|
||||
else
|
||||
# The Matomo configuration file includes all supported keys, but because of its format,
|
||||
# we cannot append contents to the end. We can assume thi
|
||||
warn "Could not set the Matomo '${key}' configuration. Check that the file has not been modified externally."
|
||||
fi
|
||||
}
|
||||
|
||||
########################
|
||||
# Get an entry from the Matomo configuration file (config.inc.php)
|
||||
# Globals:
|
||||
# MATOMO_*
|
||||
# Arguments:
|
||||
# $1 - PHP variable name
|
||||
# Returns:
|
||||
# None
|
||||
#########################
|
||||
matomo_conf_get() {
|
||||
local -r key="${1:?key missing}"
|
||||
debug "Getting ${key} from Matomo configuration"
|
||||
# Sanitize key (sed does not support fixed string substitutions)
|
||||
local sanitized_pattern
|
||||
sanitized_pattern="^\s*(//\s*)?$(sed 's/[]\[^$.*/]/\\&/g' <<<"$key")\s*=([^;]+);"
|
||||
debug "$sanitized_pattern"
|
||||
grep -E "$sanitized_pattern" "$MATOMO_CONF_FILE" | sed -E "s|${sanitized_pattern}|\2|" | tr -d "\"' "
|
||||
}
|
||||
|
||||
########################
|
||||
# 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
|
||||
#########################
|
||||
matomo_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
|
||||
}
|
||||
|
||||
########################
|
||||
# Pass Matomo wizard
|
||||
# Globals:
|
||||
# *
|
||||
# Arguments:
|
||||
# None
|
||||
# Returns:
|
||||
# true if the wizard succeeded, false otherwise
|
||||
#########################
|
||||
matomo_pass_wizard() {
|
||||
local -r port="${WEB_SERVER_HTTP_PORT_NUMBER:-"$WEB_SERVER_DEFAULT_HTTP_PORT_NUMBER"}"
|
||||
local wizard_url cookie_file curl_output
|
||||
local -a curl_opts curl_data_opts
|
||||
wizard_url="http://127.0.0.1:${port}/"
|
||||
cookie_file="/tmp/cookie$(generate_random_string -t alphanumeric -c 8)"
|
||||
curl_opts=("--location" "--silent" "--cookie" "$cookie_file" "--cookie-jar" "$cookie_file")
|
||||
# Ensure the web server is started
|
||||
web_server_start
|
||||
info "Passing Matomo installation wizard"
|
||||
# Step 0: Get cookies
|
||||
debug_execute "curl" "${curl_opts[@]}" "$wizard_url"
|
||||
# Step 1: System check
|
||||
curl_data_opts=(
|
||||
"--data-urlencode" "action=systemCheck"
|
||||
)
|
||||
debug_execute "curl" "${curl_opts[@]}" "${curl_data_opts[@]}" "${wizard_url}"
|
||||
|
||||
# Step 2: Database setup
|
||||
curl_data_opts=(
|
||||
"--data-urlencode" "action=databaseSetup"
|
||||
"--data-urlencode" "host=${MATOMO_DATABASE_HOST}:${MATOMO_DATABASE_PORT_NUMBER}"
|
||||
"--data-urlencode" "username=${MATOMO_DATABASE_USER}"
|
||||
"--data-urlencode" "password=${MATOMO_DATABASE_PASSWORD}"
|
||||
"--data-urlencode" "dbname=${MATOMO_DATABASE_NAME}"
|
||||
"--data-urlencode" "adapter=MYSQLI"
|
||||
)
|
||||
debug_execute "curl" "${curl_opts[@]}" "${curl_data_opts[@]}" "${wizard_url}"
|
||||
|
||||
# Step 3: Create tables
|
||||
curl_data_opts=(
|
||||
"--data-urlencode" "action=tablesCreation"
|
||||
"--data-urlencode" "module=Installation"
|
||||
)
|
||||
debug_execute "curl" "${curl_opts[@]}" "${curl_data_opts[@]}" "${wizard_url}"
|
||||
|
||||
# Step 4: Setup super-user
|
||||
curl_data_opts=(
|
||||
"--data-urlencode" "action=setupSuperUser"
|
||||
"--data-urlencode" "module=Installation"
|
||||
"--data-urlencode" "login=${MATOMO_USERNAME}"
|
||||
"--data-urlencode" "password=${MATOMO_PASSWORD}"
|
||||
"--data-urlencode" "password_bis=${MATOMO_PASSWORD}"
|
||||
"--data-urlencode" "email=${MATOMO_EMAIL}"
|
||||
)
|
||||
debug_execute "curl" "${curl_opts[@]}" "${curl_data_opts[@]}" "${wizard_url}"
|
||||
|
||||
# Step 5: Setup first tracking website
|
||||
curl_data_opts=(
|
||||
"--data-urlencode" "action=firstWebsiteSetup"
|
||||
"--data-urlencode" "module=Installation"
|
||||
"--data-urlencode" "siteName=${MATOMO_WEBSITE_NAME}"
|
||||
"--data-urlencode" "url=${MATOMO_WEBSITE_HOST}"
|
||||
"--data-urlencode" "timezone=UTC-8"
|
||||
)
|
||||
debug_execute "curl" "${curl_opts[@]}" "${curl_data_opts[@]}" "${wizard_url}"
|
||||
|
||||
# Step 6: Tracking code
|
||||
curl_data_opts=(
|
||||
"--data-urlencode" "action=trackingCode"
|
||||
"--data-urlencode" "module=Installation"
|
||||
)
|
||||
|
||||
# Step 7: Finish installation
|
||||
curl_data_opts=(
|
||||
"--data-urlencode" "action=finished"
|
||||
"--data-urlencode" "module=Installation"
|
||||
)
|
||||
|
||||
curl_output="$(curl "${curl_opts[@]}" "${curl_data_opts[@]}" "${wizard_url}" 2>/dev/null)"
|
||||
|
||||
if [[ "$curl_output" != *"Success"* ]]; then
|
||||
error "An error occurred while installing Matomo"
|
||||
debug "$curl_output"
|
||||
return 1
|
||||
else
|
||||
info "Matomo wizard finished successfully"
|
||||
fi
|
||||
# Stop the web server afterwards
|
||||
web_server_stop
|
||||
}
|
||||
|
|
@ -0,0 +1,988 @@
|
|||
#!/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
|
||||
local -r retries=300
|
||||
local -r sleep_time=2
|
||||
if ! retry_while is_mysql_running "$retries" "$sleep_time"; then
|
||||
error "MySQL failed to start"
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
########################
|
||||
# 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 -r user="${1:-root}"
|
||||
local -a args=("mysql" "$user")
|
||||
is_boolean_yes "${ROOT_AUTH_ENABLED:-false}" && args+=("$(get_master_env_var_value ROOT_PASSWORD)")
|
||||
local -r retries=300
|
||||
local -r sleep_time=2
|
||||
is_mysql_accessible() {
|
||||
echo "select 1" | mysql_execute "${args[@]}"
|
||||
}
|
||||
if ! retry_while is_mysql_accessible "$retries" "$sleep_time"; then
|
||||
error "Timed out waiting for MySQL to be accessible"
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
########################
|
||||
# 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:-}"
|
||||
}
|
||||
|
||||
########################
|
||||
# Execute a reliable health check against the current mysql instance
|
||||
# Globals:
|
||||
# DB_ROOT_PASSWORD, DB_MASTER_ROOT_PASSWORD
|
||||
# Arguments:
|
||||
# None
|
||||
# Returns:
|
||||
# mysqladmin output
|
||||
#########################
|
||||
mysql_healthcheck() {
|
||||
local args=("-uroot" "-h0.0.0.0")
|
||||
local root_password
|
||||
|
||||
root_password="$(get_master_env_var_value ROOT_PASSWORD)"
|
||||
if [[ -n "$root_password" ]]; then
|
||||
args+=("-p${root_password}")
|
||||
fi
|
||||
|
||||
mysqladmin "${args[@]}" ping && mysqladmin "${args[@]}" status
|
||||
}
|
||||
|
|
@ -0,0 +1,214 @@
|
|||
#!/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="^[; ]*${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="^[; ]*${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_MAX_EXECUTION_TIME" && info "Setting PHP max_execution_time option" && php_conf_set max_execution_time "$PHP_MAX_EXECUTION_TIME"
|
||||
! is_empty_value "$PHP_MAX_INPUT_TIME" && info "Setting PHP max_input_time option" && php_conf_set max_input_time "$PHP_MAX_INPUT_TIME"
|
||||
! is_empty_value "$PHP_MAX_INPUT_VARS" && info "Setting PHP max_input_vars option" && php_conf_set max_input_vars "$PHP_MAX_INPUT_VARS"
|
||||
! is_empty_value "$PHP_MEMORY_LIMIT" && info "Setting PHP memory_limit option" && php_conf_set memory_limit "$PHP_MEMORY_LIMIT"
|
||||
! 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_UPLOAD_MAX_FILESIZE" && info "Setting PHP upload_max_filesize option" && php_conf_set upload_max_filesize "$PHP_UPLOAD_MAX_FILESIZE"
|
||||
is_yes_no_value "$PHP_EXPOSE_PHP" && info "Setting PHP expose_php option" && php_conf_set expose_php "$(php_convert_to_boolean "$PHP_EXPOSE_PHP")"
|
||||
|
||||
# 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"
|
||||
}
|
||||
|
||||
########################
|
||||
# Execute/run PHP code and print to stdout
|
||||
# Globals:
|
||||
# None
|
||||
# Stdin:
|
||||
# Code to execute
|
||||
# Arguments:
|
||||
# $1..$n - Input arguments to script
|
||||
# Returns:
|
||||
# None
|
||||
#########################
|
||||
php_execute_print_output() {
|
||||
local php_cmd
|
||||
# Obtain the command specified via stdin
|
||||
php_cmd="$(</dev/stdin)"
|
||||
debug "Executing PHP code:\n${php_cmd}"
|
||||
php -- "$@" <<< "<?php ${php_cmd}"
|
||||
}
|
||||
|
||||
########################
|
||||
# Execute/run PHP code
|
||||
# Globals:
|
||||
# None
|
||||
# Stdin:
|
||||
# Code to execute
|
||||
# Arguments:
|
||||
# $1..$n - Input arguments to script
|
||||
# Returns:
|
||||
# None
|
||||
#########################
|
||||
php_execute() {
|
||||
debug_execute php_execute_print_output "$@"
|
||||
}
|
||||
|
||||
########################
|
||||
# Execute/run PHP code and print to stdout
|
||||
# Globals:
|
||||
# None
|
||||
# Stdin:
|
||||
# Code to execute
|
||||
# Arguments:
|
||||
# $1..$n - Input arguments to script
|
||||
# Returns:
|
||||
# None
|
||||
#########################
|
||||
php_execute_print_output() {
|
||||
local php_cmd
|
||||
# Obtain the command specified via stdin
|
||||
php_cmd="$(</dev/stdin)"
|
||||
debug "Executing PHP code:\n${php_cmd}"
|
||||
php -- "$@" <<< "<?php ${php_cmd}"
|
||||
}
|
||||
|
||||
########################
|
||||
# Execute/run PHP code
|
||||
# Globals:
|
||||
# None
|
||||
# Stdin:
|
||||
# Code to execute
|
||||
# Arguments:
|
||||
# $1..$n - Input arguments to script
|
||||
# Returns:
|
||||
# None
|
||||
#########################
|
||||
php_execute() {
|
||||
debug_execute php_execute_print_output "$@"
|
||||
}
|
||||
|
||||
########################
|
||||
# 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"
|
||||
}
|
||||
|
||||
########################
|
||||
# Reload PHP-FPM configuration
|
||||
# Globals:
|
||||
# PHP_FPM_PID_FILE
|
||||
# Arguments:
|
||||
# None
|
||||
# Returns:
|
||||
# None
|
||||
#########################
|
||||
php_fpm_reload() {
|
||||
php_fpm_stop "USR2"
|
||||
}
|
||||
|
||||
########################
|
||||
# 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
|
||||
}
|
||||
|
|
@ -0,0 +1,117 @@
|
|||
#!/bin/bash
|
||||
#
|
||||
# Environment configuration for matomo
|
||||
|
||||
# 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:-matomo}"
|
||||
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
|
||||
matomo_env_vars=(
|
||||
MATOMO_DATA_TO_PERSIST
|
||||
MATOMO_SKIP_BOOTSTRAP
|
||||
MATOMO_USERNAME
|
||||
MATOMO_PASSWORD
|
||||
MATOMO_EMAIL
|
||||
MATOMO_HOST
|
||||
MATOMO_WEBSITE_NAME
|
||||
MATOMO_WEBSITE_HOST
|
||||
MATOMO_ENABLE_PROXY_URI_HEADER
|
||||
MATOMO_ENABLE_TRUSTED_HOST_CHECK
|
||||
MATOMO_ENABLE_DATABASE_SSL
|
||||
MATOMO_DATABASE_SSL_CA_FILE
|
||||
MATOMO_DATABASE_SSL_CERT_FILE
|
||||
MATOMO_DATABASE_SSL_KEY_FILE
|
||||
MATOMO_VERIFY_DATABASE_SSL
|
||||
MATOMO_SMTP_HOST
|
||||
MATOMO_SMTP_PORT_NUMBER
|
||||
MATOMO_SMTP_USER
|
||||
MATOMO_SMTP_PASSWORD
|
||||
MATOMO_SMTP_AUTH
|
||||
MATOMO_SMTP_PROTOCOL
|
||||
MATOMO_DATABASE_HOST
|
||||
MATOMO_DATABASE_PORT_NUMBER
|
||||
MATOMO_DATABASE_NAME
|
||||
MATOMO_DATABASE_USER
|
||||
MATOMO_DATABASE_PASSWORD
|
||||
SMTP_HOST
|
||||
SMTP_PORT
|
||||
MATOMO_SMTP_PORT
|
||||
SMTP_USER
|
||||
SMTP_PASSWORD
|
||||
SMTP_AUTH
|
||||
SMTP_PROTOCOL
|
||||
)
|
||||
for env_var in "${matomo_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 matomo_env_vars
|
||||
|
||||
# Paths
|
||||
export MATOMO_BASE_DIR="${BITNAMI_ROOT_DIR}/matomo"
|
||||
export MATOMO_CONF_DIR="${MATOMO_BASE_DIR}/config"
|
||||
export MATOMO_CONF_FILE="${MATOMO_CONF_DIR}/config.ini.php"
|
||||
|
||||
# Matomo persistence configuration
|
||||
export MATOMO_VOLUME_DIR="${BITNAMI_VOLUME_DIR}/matomo"
|
||||
export MATOMO_DATA_TO_PERSIST="${MATOMO_DATA_TO_PERSIST:-config/config.ini.php misc/user plugins}"
|
||||
|
||||
# Matomo configuration
|
||||
export MATOMO_SKIP_BOOTSTRAP="${MATOMO_SKIP_BOOTSTRAP:-}" # only used during the first initialization
|
||||
|
||||
# Matomo credentials
|
||||
export MATOMO_USERNAME="${MATOMO_USERNAME:-user}" # only used during the first initialization
|
||||
export MATOMO_PASSWORD="${MATOMO_PASSWORD:-bitnami}" # only used during the first initialization
|
||||
export MATOMO_EMAIL="${MATOMO_EMAIL:-user@example.com}" # only used during the first initialization
|
||||
export MATOMO_HOST="${MATOMO_HOST:-127.0.0.1}" # only used during the first initialization
|
||||
export MATOMO_WEBSITE_NAME="${MATOMO_WEBSITE_NAME:-example}" # only used during the first initialization
|
||||
export MATOMO_WEBSITE_HOST="${MATOMO_WEBSITE_HOST:-https://example.org}" # only used during the first initialization
|
||||
export MATOMO_ENABLE_PROXY_URI_HEADER="${MATOMO_ENABLE_PROXY_URI_HEADER:-no}" # only used during the first initialization
|
||||
export MATOMO_ENABLE_TRUSTED_HOST_CHECK="${MATOMO_ENABLE_TRUSTED_HOST_CHECK:-no}" # only used during the first initialization
|
||||
export MATOMO_ENABLE_DATABASE_SSL="${MATOMO_ENABLE_DATABASE_SSL:-no}" # only used during the first initialization
|
||||
export MATOMO_DATABASE_SSL_CA_FILE="${MATOMO_DATABASE_SSL_CA_FILE:-}" # only used during the first initialization
|
||||
export MATOMO_DATABASE_SSL_CERT_FILE="${MATOMO_DATABASE_SSL_CERT_FILE:-}" # only used during the first initialization
|
||||
export MATOMO_DATABASE_SSL_KEY_FILE="${MATOMO_DATABASE_SSL_KEY_FILE:-}" # only used during the first initialization
|
||||
export MATOMO_VERIFY_DATABASE_SSL="${MATOMO_VERIFY_DATABASE_SSL:-yes}" # only used during the first initialization
|
||||
|
||||
# Matomo SMTP credentials
|
||||
MATOMO_SMTP_HOST="${MATOMO_SMTP_HOST:-"${SMTP_HOST:-}"}"
|
||||
export MATOMO_SMTP_HOST="${MATOMO_SMTP_HOST:-}" # only used during the first initialization
|
||||
MATOMO_SMTP_PORT_NUMBER="${MATOMO_SMTP_PORT_NUMBER:-"${SMTP_PORT:-}"}"
|
||||
MATOMO_SMTP_PORT_NUMBER="${MATOMO_SMTP_PORT_NUMBER:-"${MATOMO_SMTP_PORT:-}"}"
|
||||
export MATOMO_SMTP_PORT_NUMBER="${MATOMO_SMTP_PORT_NUMBER:-}" # only used during the first initialization
|
||||
MATOMO_SMTP_USER="${MATOMO_SMTP_USER:-"${SMTP_USER:-}"}"
|
||||
export MATOMO_SMTP_USER="${MATOMO_SMTP_USER:-}" # only used during the first initialization
|
||||
MATOMO_SMTP_PASSWORD="${MATOMO_SMTP_PASSWORD:-"${SMTP_PASSWORD:-}"}"
|
||||
export MATOMO_SMTP_PASSWORD="${MATOMO_SMTP_PASSWORD:-}" # only used during the first initialization
|
||||
MATOMO_SMTP_AUTH="${MATOMO_SMTP_AUTH:-"${SMTP_AUTH:-}"}"
|
||||
export MATOMO_SMTP_AUTH="${MATOMO_SMTP_AUTH:-}" # only used during the first initialization
|
||||
MATOMO_SMTP_PROTOCOL="${MATOMO_SMTP_PROTOCOL:-"${SMTP_PROTOCOL:-}"}"
|
||||
export MATOMO_SMTP_PROTOCOL="${MATOMO_SMTP_PROTOCOL:-}" # only used during the first initialization
|
||||
|
||||
# Database configuration
|
||||
export MATOMO_DEFAULT_DATABASE_HOST="mariadb" # only used at build time
|
||||
export MATOMO_DATABASE_HOST="${MATOMO_DATABASE_HOST:-$MATOMO_DEFAULT_DATABASE_HOST}" # only used during the first initialization
|
||||
export MATOMO_DATABASE_PORT_NUMBER="${MATOMO_DATABASE_PORT_NUMBER:-3306}" # only used during the first initialization
|
||||
export MATOMO_DATABASE_NAME="${MATOMO_DATABASE_NAME:-bitnami_matomo}" # only used during the first initialization
|
||||
export MATOMO_DATABASE_USER="${MATOMO_DATABASE_USER:-bn_matomo}" # only used during the first initialization
|
||||
export MATOMO_DATABASE_PASSWORD="${MATOMO_DATABASE_PASSWORD:-}" # only used during the first initialization
|
||||
|
||||
# PHP configuration
|
||||
export PHP_DEFAULT_MEMORY_LIMIT="256M" # only used at build time
|
||||
|
||||
# Custom environment variables may be defined below
|
||||
|
|
@ -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 Matomo environment
|
||||
. /opt/bitnami/scripts/matomo-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" || "$1" = "/opt/bitnami/scripts/matomo/run.sh" ]]; then
|
||||
info "** Starting Matomo 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/matomo/setup.sh
|
||||
/post-init.sh
|
||||
info "** Matomo setup finished! **"
|
||||
fi
|
||||
|
||||
echo ""
|
||||
exec "$@"
|
||||
|
|
@ -0,0 +1,50 @@
|
|||
#!/bin/bash
|
||||
|
||||
# shellcheck disable=SC1090,SC1091
|
||||
|
||||
set -o errexit
|
||||
set -o nounset
|
||||
set -o pipefail
|
||||
# set -o xtrace # Uncomment this line for debugging purpose
|
||||
|
||||
# Load Matomo environment
|
||||
. /opt/bitnami/scripts/matomo-env.sh
|
||||
|
||||
# Load PHP environment for 'php_conf_set' (after 'matomo-env.sh' so that MODULE is not set to a wrong value)
|
||||
. /opt/bitnami/scripts/php-env.sh
|
||||
|
||||
# Load libraries
|
||||
. /opt/bitnami/scripts/libmatomo.sh
|
||||
. /opt/bitnami/scripts/libfile.sh
|
||||
. /opt/bitnami/scripts/libfs.sh
|
||||
. /opt/bitnami/scripts/liblog.sh
|
||||
. /opt/bitnami/scripts/libphp.sh
|
||||
. /opt/bitnami/scripts/libwebserver.sh
|
||||
|
||||
# Load web server environment and functions (after Matomo environment file so MODULE is not set to a wrong value)
|
||||
. "/opt/bitnami/scripts/$(web_server_type)-env.sh"
|
||||
|
||||
# The Matomo configuration is created by the Wizard so no defaults will be set at postunpack time
|
||||
|
||||
# Ensure the Matomo base directory exists and has proper permissions
|
||||
info "Configuring file permissions for Matomo"
|
||||
ensure_user_exists "$WEB_SERVER_DAEMON_USER" "$WEB_SERVER_DAEMON_GROUP"
|
||||
for dir in "$MATOMO_BASE_DIR" "$MATOMO_VOLUME_DIR" "${MATOMO_BASE_DIR}/tmp" "${MATOMO_BASE_DIR}/misc/" "${MATOMO_BASE_DIR}/misc/user" "${MATOMO_BASE_DIR}/plugins"; do
|
||||
ensure_dir_exists "$dir"
|
||||
# Use daemon:root ownership for compatibility when running as a non-root user
|
||||
configure_permissions_ownership "$dir" -d "775" -f "664" -u "$WEB_SERVER_DAEMON_USER" -g "root"
|
||||
done
|
||||
|
||||
info "Configuring default PHP options for Matomo"
|
||||
# Fix the MySQL local infile system check
|
||||
# https://matomo.org/faq/troubleshooting/faq_194/
|
||||
php_conf_set mysqli.allow_local_infile "1"
|
||||
# Fix the geolocalization system check
|
||||
# https://matomo.org/faq/how-to/faq_164/
|
||||
php_conf_set extension "maxminddb.so"
|
||||
|
||||
# Enable default web server configuration for Matomo
|
||||
info "Creating default web server configuration for Matomo"
|
||||
web_server_validate
|
||||
# We cannot move the .htaccess because one of the system checks will fail
|
||||
ensure_web_server_app_configuration_exists "matomo" --type php --apache-move-htaccess "no"
|
||||
|
|
@ -0,0 +1,44 @@
|
|||
#!/bin/bash
|
||||
|
||||
# shellcheck disable=SC1091
|
||||
|
||||
set -o errexit
|
||||
set -o nounset
|
||||
set -o pipefail
|
||||
# set -o xtrace # Uncomment this line for debugging purpose
|
||||
|
||||
# Load Moodle environment
|
||||
. /opt/bitnami/scripts/matomo-env.sh
|
||||
|
||||
# Load libraries
|
||||
. /opt/bitnami/scripts/libos.sh
|
||||
. /opt/bitnami/scripts/liblog.sh
|
||||
. /opt/bitnami/scripts/libservice.sh
|
||||
. /opt/bitnami/scripts/libwebserver.sh
|
||||
|
||||
# Catch SIGTERM signal and stop all child processes
|
||||
_forwardTerm() {
|
||||
warn "Caught signal SIGTERM, passing it to child processes..."
|
||||
pgrep -P $$ | xargs kill -TERM 2>/dev/null
|
||||
wait
|
||||
exit $?
|
||||
}
|
||||
trap _forwardTerm TERM
|
||||
|
||||
# Start cron
|
||||
if am_i_root; then
|
||||
info "** Starting cron **"
|
||||
if ! cron_start; then
|
||||
error "Failed to start cron. Check that it is installed and its configuration is correct."
|
||||
exit 1
|
||||
fi
|
||||
else
|
||||
warn "Cron will not be started because of running as a non-root user"
|
||||
fi
|
||||
|
||||
# Start Apache
|
||||
if [[ -f "/opt/bitnami/scripts/nginx-php-fpm/run.sh" ]]; then
|
||||
exec "/opt/bitnami/scripts/nginx-php-fpm/run.sh"
|
||||
else
|
||||
exec "/opt/bitnami/scripts/$(web_server_type)/run.sh"
|
||||
fi
|
||||
|
|
@ -0,0 +1,38 @@
|
|||
#!/bin/bash
|
||||
|
||||
# shellcheck disable=SC1090,SC1091
|
||||
|
||||
set -o errexit
|
||||
set -o nounset
|
||||
set -o pipefail
|
||||
# set -o xtrace # Uncomment this line for debugging purpose
|
||||
|
||||
# Load Matomo environment
|
||||
. /opt/bitnami/scripts/matomo-env.sh
|
||||
|
||||
# Load MySQL Client environment for 'mysql_remote_execute' (after 'matomo-env.sh' so that MODULE is not set to a wrong value)
|
||||
if [[ -f /opt/bitnami/scripts/mysql-client-env.sh ]]; then
|
||||
. /opt/bitnami/scripts/mysql-client-env.sh
|
||||
elif [[ -f /opt/bitnami/scripts/mysql-env.sh ]]; then
|
||||
. /opt/bitnami/scripts/mysql-env.sh
|
||||
elif [[ -f /opt/bitnami/scripts/mariadb-env.sh ]]; then
|
||||
. /opt/bitnami/scripts/mariadb-env.sh
|
||||
fi
|
||||
|
||||
# Load libraries
|
||||
. /opt/bitnami/scripts/libmatomo.sh
|
||||
. /opt/bitnami/scripts/libwebserver.sh
|
||||
|
||||
# Load web server environment and functions (after Matomo environment file so MODULE is not set to a wrong value)
|
||||
. "/opt/bitnami/scripts/$(web_server_type)-env.sh"
|
||||
# Load PHP environment for cron configuration (after 'matomo-env.sh' so that MODULE is not set to a wrong value)
|
||||
. /opt/bitnami/scripts/php-env.sh
|
||||
|
||||
# Ensure Matomo environment variables are valid
|
||||
matomo_validate
|
||||
|
||||
# Update web server configuration with runtime environment (needs to happen before the initialization)
|
||||
web_server_update_app_configuration "matomo"
|
||||
|
||||
# Ensure Matomo is initialized
|
||||
matomo_initialize
|
||||
|
|
@ -0,0 +1,85 @@
|
|||
#!/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}"
|
||||
export DB_ROOT_USER="$MYSQL_CLIENT_DATABASE_ROOT_USER" # only used during the first initialization
|
||||
export MYSQL_CLIENT_DATABASE_ROOT_PASSWORD="${MYSQL_CLIENT_DATABASE_ROOT_PASSWORD:-}"
|
||||
export DB_ROOT_PASSWORD="$MYSQL_CLIENT_DATABASE_ROOT_PASSWORD" # only used during the first initialization
|
||||
export MYSQL_CLIENT_CREATE_DATABASE_NAME="${MYSQL_CLIENT_CREATE_DATABASE_NAME:-}"
|
||||
export DB_CREATE_DATABASE_NAME="$MYSQL_CLIENT_CREATE_DATABASE_NAME" # only used during the first initialization
|
||||
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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -0,0 +1,74 @@
|
|||
#!/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_MAX_EXECUTION_TIME
|
||||
PHP_MAX_INPUT_TIME
|
||||
PHP_MAX_INPUT_VARS
|
||||
PHP_MEMORY_LIMIT
|
||||
PHP_POST_MAX_SIZE
|
||||
PHP_UPLOAD_MAX_FILESIZE
|
||||
PHP_EXPOSE_PHP
|
||||
)
|
||||
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_MAX_EXECUTION_TIME="${PHP_MAX_EXECUTION_TIME:-}"
|
||||
export PHP_MAX_INPUT_TIME="${PHP_MAX_INPUT_TIME:-}"
|
||||
export PHP_MAX_INPUT_VARS="${PHP_MAX_INPUT_VARS:-}"
|
||||
export PHP_MEMORY_LIMIT="${PHP_MEMORY_LIMIT:-}"
|
||||
export PHP_POST_MAX_SIZE="${PHP_POST_MAX_SIZE:-}"
|
||||
export PHP_UPLOAD_MAX_FILESIZE="${PHP_UPLOAD_MAX_FILESIZE:-}"
|
||||
export PHP_EXPOSE_PHP="${PHP_EXPOSE_PHP:-yes}"
|
||||
|
||||
# Custom environment variables may be defined below
|
||||
|
|
@ -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}"
|
||||
|
|
@ -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[@]}"
|
||||
|
|
@ -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)"
|
||||
|
|
@ -0,0 +1,31 @@
|
|||
#!/bin/bash
|
||||
#
|
||||
# Executes custom PHP init scripts
|
||||
|
||||
# shellcheck disable=SC1091
|
||||
|
||||
set -o errexit
|
||||
set -o nounset
|
||||
set -o pipefail
|
||||
# set -o xtrace # Uncomment this line for debugging purposes
|
||||
|
||||
# Load libraries with logging functions
|
||||
if [[ -f /opt/bitnami/base/functions ]]; then
|
||||
. /opt/bitnami/base/functions
|
||||
else
|
||||
. /opt/bitnami/scripts/liblog.sh
|
||||
fi
|
||||
|
||||
# Loop through all input files passed via stdin
|
||||
read -r -a custom_init_scripts <<< "$@"
|
||||
failure=0
|
||||
if [[ "${#custom_init_scripts[@]}" -gt 0 ]]; then
|
||||
for custom_init_script in "${custom_init_scripts[@]}"; do
|
||||
[[ "$custom_init_script" != *".php" ]] && continue
|
||||
info "Executing ${custom_init_script} with PHP interpreter"
|
||||
php "$custom_init_script" || failure=1
|
||||
[[ "$failure" -ne 0 ]] && error "Failed to execute ${custom_init_script}"
|
||||
done
|
||||
fi
|
||||
|
||||
exit "$failure"
|
||||
|
|
@ -0,0 +1,37 @@
|
|||
#!/bin/bash
|
||||
#
|
||||
# Executes custom Bash init scripts
|
||||
|
||||
# shellcheck disable=SC1090
|
||||
# shellcheck disable=SC1091
|
||||
|
||||
set -o errexit
|
||||
set -o nounset
|
||||
set -o pipefail
|
||||
# set -o xtrace # Uncomment this line for debugging purposes
|
||||
|
||||
# Load libraries with logging functions
|
||||
if [[ -f /opt/bitnami/base/functions ]]; then
|
||||
. /opt/bitnami/base/functions
|
||||
else
|
||||
. /opt/bitnami/scripts/liblog.sh
|
||||
fi
|
||||
|
||||
# Loop through all input files passed via stdin
|
||||
read -r -a custom_init_scripts <<< "$@"
|
||||
failure=0
|
||||
if [[ "${#custom_init_scripts[@]}" -gt 0 ]]; then
|
||||
for custom_init_script in "${custom_init_scripts[@]}"; do
|
||||
[[ "$custom_init_script" != *".sh" ]] && continue
|
||||
if [[ -x "$custom_init_script" ]]; then
|
||||
info "Executing ${custom_init_script}"
|
||||
"$custom_init_script" || failure="1"
|
||||
else
|
||||
info "Sourcing ${custom_init_script} as it is not executable by the current user, any error may cause initialization to fail"
|
||||
. "$custom_init_script"
|
||||
fi
|
||||
[[ "$failure" -ne 0 ]] && error "Failed to execute ${custom_init_script}"
|
||||
done
|
||||
fi
|
||||
|
||||
exit "$failure"
|
||||
|
|
@ -0,0 +1,46 @@
|
|||
#!/bin/bash
|
||||
#
|
||||
# Executes custom Ruby init scripts
|
||||
|
||||
# shellcheck disable=SC1091
|
||||
|
||||
set -o errexit
|
||||
set -o nounset
|
||||
set -o pipefail
|
||||
# set -o xtrace # Uncomment this line for debugging purposes
|
||||
|
||||
# Load libraries with logging functions
|
||||
if [[ -f /opt/bitnami/base/functions ]]; then
|
||||
. /opt/bitnami/base/functions
|
||||
else
|
||||
. /opt/bitnami/scripts/liblog.sh
|
||||
fi
|
||||
|
||||
mysql_execute() {
|
||||
local -r sql_file="${1:?missing file}"
|
||||
local failure=0
|
||||
mysql_cmd=("mysql" "-h" "$MARIADB_HOST" "-P" "$MARIADB_PORT_NUMBER" "-u" "$MARIADB_ROOT_USER")
|
||||
if [[ "${ALLOW_EMPTY_PASSWORD:-no}" != "yes" ]]; then
|
||||
mysql_cmd+=("-p${MARIADB_ROOT_PASSWORD}")
|
||||
fi
|
||||
if [[ "$sql_file" == *".sql" ]]; then
|
||||
"${mysql_cmd[@]}" < "$sql_file" || failure=$?
|
||||
elif [[ "$sql_file" == *".sql.gz" ]]; then
|
||||
gunzip -c "$sql_file" | "${mysql_cmd[@]}" || failure=$?
|
||||
fi
|
||||
return "$failure"
|
||||
}
|
||||
|
||||
# Loop through all input files passed via stdin
|
||||
read -r -a custom_init_scripts <<< "$@"
|
||||
failure=0
|
||||
if [[ "${#custom_init_scripts[@]}" -gt 0 ]]; then
|
||||
for custom_init_script in "${custom_init_scripts[@]}"; do
|
||||
[[ ! "$custom_init_script" =~ ^.*(\.sql|\.sql\.gz)$ ]] && continue
|
||||
info "Executing ${custom_init_script}"
|
||||
mysql_execute "$custom_init_script" || failure=1
|
||||
[[ "$failure" -ne 0 ]] && error "Failed to execute ${custom_init_script}"
|
||||
done
|
||||
fi
|
||||
|
||||
exit "$failure"
|
||||
|
|
@ -0,0 +1,23 @@
|
|||
#!/bin/bash
|
||||
|
||||
# shellcheck disable=SC1091
|
||||
|
||||
set -o errexit
|
||||
set -o nounset
|
||||
set -o pipefail
|
||||
# set -o xtrace # Uncomment this line for debugging purposes
|
||||
|
||||
# Only execute init scripts once
|
||||
if [[ ! -f "/bitnami/matomo/.user_scripts_initialized" && -d "/docker-entrypoint-init.d" ]]; then
|
||||
read -r -a init_scripts <<< "$(find "/docker-entrypoint-init.d" -type f -print0 | xargs -0)"
|
||||
if [[ "${#init_scripts[@]}" -gt 0 ]] && [[ ! -f "/bitnami/matomo/.user_scripts_initialized" ]]; then
|
||||
mkdir -p "/bitnami/matomo"
|
||||
for init_script in "${init_scripts[@]}"; do
|
||||
for init_script_type_handler in /post-init.d/*.sh; do
|
||||
"$init_script_type_handler" "$init_script"
|
||||
done
|
||||
done
|
||||
fi
|
||||
|
||||
touch "/bitnami/matomo/.user_scripts_initialized"
|
||||
fi
|
||||
|
|
@ -36,7 +36,7 @@ Non-root container images add an extra layer of security and are generally recom
|
|||
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/).
|
||||
|
||||
|
||||
* [`3`, `3-debian-10`, `3.14.1`, `3.14.1-debian-10-r87`, `latest` (3/debian-10/Dockerfile)](https://github.com/bitnami/bitnami-docker-matomo/blob/3.14.1-debian-10-r87/3/debian-10/Dockerfile)
|
||||
* [`4`, `4-debian-10`, `4.0.4`, `4.0.4-debian-10-r0` (4/debian-10/Dockerfile)](https://github.com/bitnami/bitnami-docker-matomo/blob/4.0.4-debian-10-r0/4/debian-10/Dockerfile)
|
||||
|
||||
Subscribe to project updates by watching the [bitnami/matomo GitHub repo](https://github.com/bitnami/bitnami-docker-matomo).
|
||||
|
||||
|
|
@ -56,7 +56,7 @@ $ docker pull bitnami/matomo:[TAG]
|
|||
If you wish, you can also build the image youself.
|
||||
|
||||
```console
|
||||
docker build -t bitnami/matomo:latest 'https://github.com/bitnami/bitnami-docker-matomo.git#master:3/debian-10'
|
||||
|
||||
```
|
||||
|
||||
# How to use this image
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ services:
|
|||
volumes:
|
||||
- "mariadb_data:/bitnami/mariadb"
|
||||
matomo:
|
||||
image: "docker.io/bitnami/matomo:3-debian-10"
|
||||
image: "docker.io/bitnami/matomo:4-debian-10"
|
||||
ports:
|
||||
- "80:8080"
|
||||
- "443:8443"
|
||||
|
|
|
|||
Loading…
Reference in New Issue