#!/bin/bash # # Copyright (C) 2025 Xibo Signage Ltd # # Xibo - Digital Signage - https://xibosignage.com # # This file is part of Xibo. # # Xibo is free software: you can redistribute it and/or modify # it under the terms of the GNU Affero General Public License as published by # the Free Software Foundation, either version 3 of the License, or # any later version. # # Xibo is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU Affero General Public License for more details. # # You should have received a copy of the GNU Affero General Public License # along with Xibo. If not, see . # if [ "$CMS_DEV_MODE" == "true" ] then # Print MySQL connection details echo "MySQL Connection Details:" echo "Username: $MYSQL_USER" echo "Password: $MYSQL_PASSWORD" echo "DB: $MYSQL_DATABASE" echo "Host: $MYSQL_HOST" echo "" echo "XMR Connection Details:" echo "Host: $XMR_HOST" echo "Player Port: 9505" echo "" echo "Starting Webserver" fi # Sleep for a few seconds to give MySQL time to initialise echo "Waiting for MySQL to start - max 300 seconds" /usr/local/bin/wait-for-command.sh -q -t 300 -c "nc -z $MYSQL_HOST $MYSQL_PORT" if [ ! "$?" == 0 ] then echo "MySQL didn't start in the allocated time" > /var/www/backup/LOG fi # Safety sleep to give MySQL a moment to settle after coming up echo "MySQL started" sleep 1 # Write a /root/.my.cnf file echo "Configuring MySQL cnf file" echo "[client]" > /root/.my.cnf echo "host = $MYSQL_HOST" >> /root/.my.cnf echo "port = $MYSQL_PORT" >> /root/.my.cnf echo "user = $MYSQL_USER" >> /root/.my.cnf echo "password = $MYSQL_PASSWORD" >> /root/.my.cnf if [ ! "$MYSQL_ATTR_SSL_CA" == "none" ] then echo "ssl_ca = $MYSQL_ATTR_SSL_CA" >> /root/.my.cnf if [ "$MYSQL_ATTR_SSL_VERIFY_SERVER_CERT" == "true" ] then echo "ssl_mode = VERIFY_IDENTITY" >> /root/.my.cnf fi fi # Set permissions on the new cnf file. chmod 0600 /root/.my.cnf # Check to see if we have a settings.php file in this container # if we don't, then we will need to create one here (it only contains the $_SERVER environment # variables we've already set if [ ! -f "/var/www/cms/web/settings.php" ] then # Write settings.php echo "Updating settings.php" # We won't have a settings.php in place, so we'll need to copy one in cp /tmp/settings.php-template /var/www/cms/web/settings.php chown www-data.www-data /var/www/cms/web/settings.php SECRET_KEY=$(head /dev/urandom | tr -dc A-Za-z0-9 | head -c 8) /bin/sed -i "s/define('SECRET_KEY','');/define('SECRET_KEY','$SECRET_KEY');/" /var/www/cms/web/settings.php fi # Check to see if we have a public/private key pair and encryption key if [ ! -f "/var/www/cms/library/certs/private.key" ] then # Make the dir mkdir -p /var/www/cms/library/certs # Create the Keys openssl genrsa -out /var/www/cms/library/certs/private.key 2048 openssl rsa -in /var/www/cms/library/certs/private.key -pubout -out /var/www/cms/library/certs/public.key php -r 'echo base64_encode(random_bytes(32)), PHP_EOL;' >> /var/www/cms/library/certs/encryption.key fi # Set the correct permissions on the public/private key chmod 600 /var/www/cms/library/certs/private.key chmod 660 /var/www/cms/library/certs/public.key chown -R www-data.www-data /var/www/cms/library/certs # Check if there's a database file to import if [ -f "/var/www/backup/import.sql" ] && [ "$CMS_DEV_MODE" == "false" ] then echo "Attempting to import database" echo "Importing Database" mysql -D $MYSQL_DATABASE -e "SOURCE /var/www/backup/import.sql" echo "Configuring Database Settings" # Set LIBRARY_LOCATION mysql -D $MYSQL_DATABASE -e "UPDATE \`setting\` SET \`value\`='/var/www/cms/library/', \`userChange\`=0, \`userSee\`=0 WHERE \`setting\`='LIBRARY_LOCATION' LIMIT 1" mysql -D $MYSQL_DATABASE -e "UPDATE \`setting\` SET \`value\`='Apache', \`userChange\`=0, \`userSee\`=0 WHERE \`setting\`='SENDFILE_MODE' LIMIT 1" # Set XMR public/private address mysql -D $MYSQL_DATABASE -e "UPDATE \`setting\` SET \`value\`='http://$XMR_HOST:8081', \`userChange\`=0, \`userSee\`=0 WHERE \`setting\`='XMR_ADDRESS' LIMIT 1" # Configure Maintenance echo "Setting up Maintenance" mysql -D $MYSQL_DATABASE -e "UPDATE \`setting\` SET \`value\`='Protected' WHERE \`setting\`='MAINTENANCE_ENABLED' LIMIT 1" MAINTENANCE_KEY=$(head /dev/urandom | tr -dc A-Za-z0-9 | head -c 16) mysql -D $MYSQL_DATABASE -e "UPDATE \`setting\` SET \`value\`='$MAINTENANCE_KEY' WHERE \`setting\`='MAINTENANCE_KEY' LIMIT 1" # Configure Quick Chart echo "Setting up Quickchart" mysql -D $MYSQL_DATABASE -e "UPDATE \`setting\` SET \`value\`='$CMS_QUICK_CHART_URL', userSee=0 WHERE \`setting\`='QUICK_CHART_URL' LIMIT 1" mv /var/www/backup/import.sql /var/www/backup/import.sql.done fi DB_EXISTS=0 # Check if the database exists already if mysql -D $MYSQL_DATABASE -e "SELECT settingId FROM \`setting\` LIMIT 1" then # Database exists. DB_EXISTS=1 fi # Check if we need to run an upgrade # if DB_EXISTS then see if the version installed matches # only upgrade for production containers if [ "$DB_EXISTS" == "1" ] && [ "$CMS_DEV_MODE" == "false" ] then echo "Existing Database, checking if we need to upgrade it" # Determine if there are any migrations to be run /var/www/cms/vendor/bin/phinx status -c "/var/www/cms/phinx.php" if [ ! "$?" == 0 ] then echo "We will upgrade it, take a backup" # We're going to run an upgrade. Make a database backup mysqldump -h $MYSQL_HOST -P $MYSQL_PORT -u $MYSQL_USER -p$MYSQL_PASSWORD \ --hex-blob --no-tablespaces $MYSQL_DATABASE | gzip > /var/www/backup/db-$(date +"%Y-%m-%d_%H-%M-%S").sql.gz # Drop app cache on upgrade rm -rf /var/www/cms/cache/* # Upgrade echo 'Running database migrations' /var/www/cms/vendor/bin/phinx migrate -c /var/www/cms/phinx.php fi fi if [ "$DB_EXISTS" == "0" ] then # This is a fresh install so bootstrap the whole # system echo "New install" echo "Provisioning Database" # Create the database if it doesn't exist mysql -e "CREATE DATABASE IF NOT EXISTS $MYSQL_DATABASE;" # Populate the database php /var/www/cms/vendor/bin/phinx migrate -c "/var/www/cms/phinx.php" CMS_KEY=$(head /dev/urandom | tr -dc A-Za-z0-9 | head -c 8) echo "Configuring Database Settings" # Set LIBRARY_LOCATION mysql -D $MYSQL_DATABASE -e "UPDATE \`setting\` SET \`value\`='/var/www/cms/library/', \`userChange\`=0, \`userSee\`=0 WHERE \`setting\`='LIBRARY_LOCATION' LIMIT 1" mysql -D $MYSQL_DATABASE -e "UPDATE \`setting\` SET \`value\`='Apache', \`userChange\`=0, \`userSee\`=0 WHERE \`setting\`='SENDFILE_MODE' LIMIT 1" # Set admin username/password mysql -D $MYSQL_DATABASE -e "UPDATE \`user\` SET \`UserName\`='xibo_admin', \`UserPassword\`='5f4dcc3b5aa765d61d8327deb882cf99' WHERE \`UserID\` = 1 LIMIT 1" # Set XMR public address mysql -D $MYSQL_DATABASE -e "UPDATE \`setting\` SET \`value\`='tcp://cms.example.org:9505' WHERE \`setting\`='XMR_PUB_ADDRESS' LIMIT 1" # Set CMS Key mysql -D $MYSQL_DATABASE -e "UPDATE \`setting\` SET \`value\`='$CMS_KEY' WHERE \`setting\`='SERVER_KEY' LIMIT 1" # Configure Maintenance echo "Setting up Maintenance" if [ "$CMS_DEV_MODE" == "false" ] then echo "Protected Maintenance" mysql -D $MYSQL_DATABASE -e "UPDATE \`setting\` SET \`value\`='Protected' WHERE \`setting\`='MAINTENANCE_ENABLED' LIMIT 1" fi MAINTENANCE_KEY=$(head /dev/urandom | tr -dc A-Za-z0-9 | head -c 16) mysql -D $MYSQL_DATABASE -e "UPDATE \`setting\` SET \`value\`='$MAINTENANCE_KEY' WHERE \`setting\`='MAINTENANCE_KEY' LIMIT 1" fi if [ "$CMS_DEV_MODE" == "false" ] then # Import any ca-certificate files that might be needed to use a proxy etc echo "Importing ca-certs" cp -v /var/www/cms/ca-certs/*.pem /usr/local/share/ca-certificates cp -v /var/www/cms/ca-certs/*.crt /usr/local/share/ca-certificates /usr/sbin/update-ca-certificates # Configure XMR private API echo "Setting up XMR private API" mysql -D $MYSQL_DATABASE -e "UPDATE \`setting\` SET \`value\`='http://$XMR_HOST:8081', \`userChange\`=0, \`userSee\`=0 WHERE \`setting\`='XMR_ADDRESS' LIMIT 1" # Configure Quick Chart echo "Setting up Quickchart" mysql -D $MYSQL_DATABASE -e "UPDATE \`setting\` SET \`value\`='$CMS_QUICK_CHART_URL', userSee=0 WHERE \`setting\`='QUICK_CHART_URL' LIMIT 1" # Set the daily maintenance task to run mysql -D $MYSQL_DATABASE -e "UPDATE \`task\` SET \`runNow\`=1 WHERE \`taskId\`='1' LIMIT 1" # Update /etc/periodic/15min/cms-db-backup with current environment (for cron) /bin/sed -i "s/^MYSQL_BACKUP_ENABLED=.*$/MYSQL_BACKUP_ENABLED=$MYSQL_BACKUP_ENABLED/" /etc/periodic/15min/cms-db-backup /bin/sed -i "s/^MYSQL_DATABASE=.*$/MYSQL_DATABASE=$MYSQL_DATABASE/" /etc/periodic/15min/cms-db-backup echo "*/15 * * * * root /etc/periodic/15min/cms-db-backup > /dev/null 2>&1" > /etc/cron.d/cms_backup_cron echo "" >> /etc/cron.d/cms_backup_cron # Update /var/www/maintenance with current environment (for cron) if [ "$XTR_ENABLED" == "true" ] then echo "Configuring Maintenance" echo "#!/bin/bash" > /var/www/maintenance.sh echo "" >> /var/www/maintenance.sh /usr/bin/env | sed 's/^\(.*\)$/export \1/g' | grep -E "^export MYSQL" >> /var/www/maintenance.sh /usr/bin/env | sed 's/^\(.*\)$/export \1/g' | grep -E "^export MEMCACHED" >> /var/www/maintenance.sh echo "export CMS_USE_MEMCACHED=$CMS_USE_MEMCACHED" >> /var/www/maintenance.sh echo "export INSTALL_TYPE=$INSTALL_TYPE" >> /var/www/maintenance.sh echo "cd /var/www/cms && /usr/bin/php bin/xtr.php" >> /var/www/maintenance.sh chmod 755 /var/www/maintenance.sh echo "* * * * * www-data /var/www/maintenance.sh > /dev/null 2>&1 " > /etc/cron.d/cms_maintenance_cron echo "" >> /etc/cron.d/cms_maintenance_cron fi # Configure MSMTP to send emails if required # Config lives in /etc/msmtprc # Split CMS_SMTP_SERVER in to CMS_SMTP_SEVER_HOST : PORT host_port=($(echo $CMS_SMTP_SERVER | tr ":" "\n")) /bin/sed -i "s/host .*$/host ${host_port[0]}/" /etc/msmtprc /bin/sed -i "s/port .*$/port ${host_port[1]}/" /etc/msmtprc if [ -z "$CMS_SMTP_USERNAME" ] || [ "$CMS_SMTP_USERNAME" == "none" ] then # Use no authentication /bin/sed -i "s/^auth .*$/auth off/" /etc/msmtprc else if [ -z "$CMS_SMTP_OAUTH_CLIENT_ID" ] || [ "$CMS_SMTP_OAUTH_CLIENT_ID" == "none" ] then # Use Username/Password /bin/sed -i "s/^auth .*$/auth on/" /etc/msmtprc /bin/sed -i "s/^user .*$/user $CMS_SMTP_USERNAME/" /etc/msmtprc /bin/sed -i "s/^password .*$/password $CMS_SMTP_PASSWORD/" /etc/msmtprc else # Use OAUTH credentials /bin/sed -i "s/^auth .*$/auth oauthbearer/" /etc/msmtprc /bin/sed -i "s/^user .*$/#user/" /etc/msmtprc /bin/sed -i "s/^password .*$/passwordeval \"/usr/bin/oauth2.py --quiet --user=$CMS_SMTP_USERNAME --client_id=$CMS_SMTP_OAUTH_CLIENT_ID --client_secret=$CMS_SMTP_OAUTH_CLIENT_SECRET --refresh_token=$CMS_SMTP_OAUTH_CLIENT_REFRESH\"/" /etc/msmtprc fi fi if [ "$CMS_SMTP_USE_TLS" == "YES" ] then /bin/sed -i "s/tls .*$/tls on/" /etc/msmtprc else /bin/sed -i "s/tls .*$/tls off/" /etc/msmtprc fi if [ "$CMS_SMTP_USE_STARTTLS" == "YES" ] then /bin/sed -i "s/tls_starttls .*$/tls_starttls on/" /etc/msmtprc else /bin/sed -i "s/tls_starttls .*$/tls_starttls off/" /etc/msmtprc fi /bin/sed -i "s/maildomain .*$/maildomain $CMS_SMTP_REWRITE_DOMAIN/" /etc/msmtprc /bin/sed -i "s/domain .*$/domain $CMS_SMTP_HOSTNAME/" /etc/msmtprc if [ "$CMS_SMTP_FROM" == "none" ] then /bin/sed -i "s/from .*$/from cms@$CMS_SMTP_REWRITE_DOMAIN/" /etc/msmtprc else /bin/sed -i "s/from .*$/from $CMS_SMTP_FROM/" /etc/msmtprc fi mkdir -p /var/www/cms/library/temp chown www-data:www-data -R /var/www/cms/library chown www-data:www-data -R /var/www/cms/custom chown www-data:www-data -R /var/www/cms/web/theme/custom chown www-data:www-data -R /var/www/cms/web/userscripts chown www-data:www-data -R /var/www/cms/ca-certs # If we have a CMS ALIAS environment variable, then configure that in our Apache conf. # this must not be done in DEV mode, as it modifies the .htaccess file, which might then be committed by accident if [ ! "$CMS_ALIAS" == "none" ] then echo "Setting up CMS alias" /bin/sed -i "s|.*Alias.*$|Alias $CMS_ALIAS /var/www/cms/web|" /etc/apache2/sites-enabled/000-default.conf echo "Settings up htaccess" /bin/cp /tmp/.htaccess /var/www/cms/web/.htaccess /bin/sed -i "s|REPLACE_ME|$CMS_ALIAS|" /var/www/cms/web/.htaccess fi if [ ! -e /var/www/cms/custom/settings-custom.php ] then /bin/cp /tmp/settings-custom.php /var/www/cms/custom fi # Remove install.php if it exists if [ -e /var/www/cms/web/install/index.php ] then echo "Removing web/install/index.php from production container" rm /var/www/cms/web/install/index.php fi fi # Configure Anonymous usage reporting if [ "$CMS_USAGE_REPORT" == "true" ] then # Turn on mysql -D $MYSQL_DATABASE -e "UPDATE \`setting\` SET \`value\`='1', userChange=0 WHERE \`setting\`='PHONE_HOME' LIMIT 1" fi if [ "$CMS_USAGE_REPORT" == "false" ] then # Turn off mysql -D $MYSQL_DATABASE -e "UPDATE \`setting\` SET \`value\`='0', userChange=0 WHERE \`setting\`='PHONE_HOME' LIMIT 1" fi echo "Configure PHP" # Configure PHP sed -i "s/session.gc_maxlifetime = .*$/session.gc_maxlifetime = $CMS_PHP_SESSION_GC_MAXLIFETIME/" /etc/php/8.4/apache2/php.ini sed -i "s/post_max_size = .*$/post_max_size = $CMS_PHP_POST_MAX_SIZE/" /etc/php/8.4/apache2/php.ini sed -i "s/upload_max_filesize = .*$/upload_max_filesize = $CMS_PHP_UPLOAD_MAX_FILESIZE/" /etc/php/8.4/apache2/php.ini sed -i "s/max_execution_time = .*$/max_execution_time = $CMS_PHP_MAX_EXECUTION_TIME/" /etc/php/8.4/apache2/php.ini sed -i "s/memory_limit = .*$/memory_limit = $CMS_PHP_MEMORY_LIMIT/" /etc/php/8.4/apache2/php.ini sed -i "s/session.cookie_httponly =.*$/session.cookie_httponly = $CMS_PHP_COOKIE_HTTP_ONLY/" /etc/php/8.4/apache2/php.ini sed -i "s/session.cookie_samesite =.*$/session.cookie_samesite = $CMS_PHP_COOKIE_SAMESITE/" /etc/php/8.4/apache2/php.ini sed -i "s/;session.cookie_secure =.*$/session.cookie_secure = $CMS_PHP_COOKIE_SECURE/" /etc/php/8.4/apache2/php.ini sed -i "s/session.gc_maxlifetime = .*$/session.gc_maxlifetime = $CMS_PHP_SESSION_GC_MAXLIFETIME/" /etc/php/8.4/cli/php.ini sed -i "s/post_max_size = .*$/post_max_size = $CMS_PHP_POST_MAX_SIZE/" /etc/php/8.4/cli/php.ini sed -i "s/upload_max_filesize = .*$/upload_max_filesize = $CMS_PHP_UPLOAD_MAX_FILESIZE/" /etc/php/8.4/cli/php.ini sed -i "s/max_execution_time = .*$/max_execution_time = $CMS_PHP_CLI_MAX_EXECUTION_TIME/" /etc/php/8.4/cli/php.ini sed -i "s/memory_limit = .*$/memory_limit = $CMS_PHP_CLI_MEMORY_LIMIT/" /etc/php/8.4/cli/php.ini sed -i "s/session.cookie_httponly =.*$/session.cookie_httponly = $CMS_PHP_COOKIE_HTTP_ONLY/" /etc/php/8.4/cli/php.ini sed -i "s/session.cookie_samesite =.*$/session.cookie_samesite = $CMS_PHP_COOKIE_SAMESITE/" /etc/php/8.4/cli/php.ini sed -i "s/;session.cookie_secure =.*$/session.cookie_secure = $CMS_PHP_COOKIE_SECURE/" /etc/php/8.4/cli/php.ini echo "Configure Apache" # Configure Apache TimeOut sed -i "s/\bTimeout\b .*$/Timeout $CMS_APACHE_TIMEOUT/" /etc/apache2/apache2.conf # Configure Indexes if [ "$CMS_APACHE_OPTIONS_INDEXES" == "true" ] then sed -i "s/\-Indexes/\+Indexes/" /etc/apache2/sites-enabled/000-default.conf fi # Configure Apache ServerTokens if [ "$CMS_APACHE_SERVER_TOKENS" == "Prod" ] then sed -i "s/ServerTokens.*$/ServerTokens Prod/" /etc/apache2/sites-enabled/000-default.conf fi # Configure Apache logging if [ "$CMS_APACHE_LOG_REQUEST_TIME" == "true" ] then sed -i '/combined/s/^/#/' /etc/apache2/sites-enabled/000-default.conf else sed -i '/requesttime/s/^/#/' /etc/apache2/sites-enabled/000-default.conf fi # Run CRON in Production mode if [ "$CMS_DEV_MODE" == "false" ] then echo "Starting cron" /usr/sbin/cron fi echo "Starting webserver" exec /usr/local/bin/httpd-foreground