diff --git a/.github/scripts/generate-build-context.sh b/.github/scripts/generate-build-context.sh new file mode 100644 index 0000000..2800d90 --- /dev/null +++ b/.github/scripts/generate-build-context.sh @@ -0,0 +1,224 @@ +#!/bin/bash +set -euo pipefail + +echo "Generating Docker build context..." + +# Create necessary directories +mkdir -p humhub nginx backup/scripts + +# --- PHP.ini --- +cat > humhub/php.ini < humhub/Dockerfile < /var/www/html/ping && \\ + chmod -R 755 /var/www/html && \\ + find /var/www/html -type f -exec chmod 644 {} \\; && \\ + find /var/www/html -type d -exec chmod 755 {} \\; && \\ + chmod -R 775 /var/www/html/protected/runtime /var/www/html/protected/modules /var/www/html/uploads /var/www/html/assets && \\ + chown -R www-data:www-data /var/www/html && \\ + rm -rf /var/www/html/protected/vendor/bower-asset/*/test \\ + /var/www/html/protected/vendor/*/tests \\ + /var/www/html/protected/runtime/logs/* + +VOLUME ["/var/www/html/protected/runtime", "/var/www/html/uploads", "/var/www/html/protected/modules", "/var/www/html/protected/config", "/var/www/html/themes"] + +WORKDIR /var/www/html + +ENTRYPOINT ["docker-entrypoint.sh"] +CMD ["php-fpm"] +EOF + +# --- docker-entrypoint.sh --- +cat > humhub/docker-entrypoint.sh <<'EOF' +#!/bin/bash +set -eo pipefail + +# Wait for DB +wait-for-it -t 60 ${HUMHUB_DB_HOST}:3306 + +# Create config files if needed +if [ ! -f "/var/www/html/protected/config/common.php" ]; then + echo "Creating common.php..." + cat > /var/www/html/protected/config/common.php < [ + 'db' => [ + 'dsn' => 'mysql:host=${HUMHUB_DB_HOST};dbname=${HUMHUB_DB_NAME}', + 'username' => '${HUMHUB_DB_USER}', + 'password' => '${HUMHUB_DB_PASSWORD}', + 'charset' => 'utf8mb4', + 'enableSchemaCache' => true, + ], + 'cache' => [ + 'class' => '${HUMHUB_CACHE_CLASS}', + 'hostname' => '${HUMHUB_REDIS_HOSTNAME}', + 'port' => ${HUMHUB_REDIS_PORT}, + 'password' => '${HUMHUB_REDIS_PASSWORD}', + 'database' => 0, + ], + 'mailer' => [ + 'transport' => [ + 'class' => 'Swift_SmtpTransport', + 'host' => '${HUMHUB_MAILER_HOST}', + 'username' => '${HUMHUB_MAILER_USERNAME}', + 'password' => '${HUMHUB_MAILER_PASSWORD}', + 'port' => ${HUMHUB_MAILER_PORT}, + 'encryption' => '${HUMHUB_MAILER_ENCRYPTION}', + ], + ], + 'urlManager' => [ + 'showScriptName' => false, + 'enablePrettyUrl' => true, + ], + 'formatter' => [ + 'defaultTimeZone' => 'UTC', + ], + 'queue' => [ + 'class' => 'humhub\\modules\\queue\\driver\\Redis', + 'hostname' => '${HUMHUB_REDIS_HOSTNAME}', + 'port' => ${HUMHUB_REDIS_PORT}, + 'password' => '${HUMHUB_REDIS_PASSWORD}', + 'database' => 1, + ], + ], + 'params' => [ + 'installed' => false, + 'installationId' => '', + 'dynamic' => [], + ], +]; +EOL +fi + +if [ ! -f "/var/www/html/protected/config/dynamic.php" ]; then + echo " /var/www/html/protected/config/dynamic.php + chown www-data:www-data /var/www/html/protected/config/dynamic.php + chmod 644 /var/www/html/protected/config/dynamic.php +fi + +chmod -R 775 /var/www/html/{protected/runtime,protected/modules,uploads,assets} +chown -R www-data:www-data /var/www/html/{protected/runtime,protected/modules,uploads,assets,protected/config} + +# Auto install if ENV present +if [ -n "${HUMHUB_ADMIN_EMAIL}" ] && [ -n "${HUMHUB_ADMIN_LOGIN}" ] && [ -n "${HUMHUB_ADMIN_PASSWORD}" ] && [ -n "${HUMHUB_SITE_NAME}" ] && [ -n "${HUMHUB_SITE_EMAIL}" ]; then + if grep -q '"installed":false' /var/www/html/protected/config/dynamic.php 2>/dev/null || ! grep -q '"installed":true' /var/www/html/protected/config/dynamic.php 2>/dev/null; then + echo "Auto-installing HumHub..." + php /var/www/html/protected/yii installer/auto-install \ + --db-host="${HUMHUB_DB_HOST}" \ + --db-name="${HUMHUB_DB_NAME}" \ + --db-username="${HUMHUB_DB_USER}" \ + --db-password="${HUMHUB_DB_PASSWORD}" \ + --admin-email="${HUMHUB_ADMIN_EMAIL}" \ + --admin-username="${HUMHUB_ADMIN_LOGIN}" \ + --admin-password="${HUMHUB_ADMIN_PASSWORD}" \ + --name="${HUMHUB_SITE_NAME}" \ + --email="${HUMHUB_SITE_EMAIL}" + fi +fi + +php /var/www/html/protected/yii migrate/up --includeModuleMigrations=1 --interactive=0 + +exec "$@" +EOF +chmod +x humhub/docker-entrypoint.sh + +# --- wait-for-it.sh --- +curl -fsSL https://raw.githubusercontent.com/vishnubob/wait-for-it/master/wait-for-it.sh -o humhub/wait-for-it.sh +chmod +x humhub/wait-for-it.sh + +# --- nginx --- +cat > nginx/Dockerfile < nginx/docker-entrypoint.sh < backup/scripts/backup.sh < /backup/source/db_backup.sql +borg create --stats --compression lz4 /backup/repo::\$(date +%Y-%m-%d_%H-%M-%S) /backup/source +echo "Backup completed successfully!" +EOF +chmod +x backup/scripts/backup.sh + +cat > backup/Dockerfile < humhub/php.ini << EOF - [PHP] - ; Security settings - expose_php = Off - max_execution_time = 120 - max_input_time = 120 - memory_limit = 256M - error_reporting = E_ALL & ~E_DEPRECATED & ~E_STRICT - display_errors = Off - display_startup_errors = Off - log_errors = On - error_log = /proc/self/fd/2 - post_max_size = 32M - file_uploads = On - upload_max_filesize = 32M - max_file_uploads = 20 - allow_url_fopen = On - allow_url_include = Off - default_socket_timeout = 60 - - ; Date - date.timezone = UTC - - ; Session - session.cookie_httponly = 1 - session.use_strict_mode = 1 - session.use_cookies = 1 - session.use_only_cookies = 1 - session.cookie_secure = 1 - session.cookie_samesite = "Lax" - session.gc_maxlifetime = 1440 - - ; OpCache settings - opcache.memory_consumption = 128 - opcache.interned_strings_buffer = 8 - opcache.max_accelerated_files = 4000 - opcache.revalidate_freq = 60 - opcache.fast_shutdown = 1 - opcache.enable_cli = 1 - - ; Other settings - realpath_cache_size = 4096k - realpath_cache_ttl = 600 - disable_functions = exec,passthru,shell_exec,system,proc_open,popen,curl_multi_exec,parse_ini_file,show_source - EOF - - # Create Dockerfile in humhub directory - cat > humhub/Dockerfile << EOF - FROM php:8.2-fpm - - ARG HUMHUB_VERSION=1.17.2 - - # Install dependencies - RUN apt-get update && apt-get install -y \ - libzip-dev \ - libfreetype6-dev \ - libjpeg62-turbo-dev \ - libpng-dev \ - libicu-dev \ - libldap2-dev \ - libxml2-dev \ - curl \ - wget \ - unzip \ - gnupg \ - git \ - libmagickwand-dev \ - --no-install-recommends && \ - rm -rf /var/lib/apt/lists/* && \ - # Install PHP extensions and PECL extensions - docker-php-ext-configure gd --with-freetype --with-jpeg && \ - docker-php-ext-configure ldap --with-libdir=lib/x86_64-linux-gnu/ && \ - docker-php-ext-install -j"$(nproc)" \ - gd \ - intl \ - mysqli \ - pdo_mysql \ - zip \ - exif \ - opcache \ - ldap \ - xml && \ - pecl install imagick redis && \ - docker-php-ext-enable imagick redis - - # Set recommended PHP.ini settings - COPY php.ini /usr/local/etc/php/conf.d/custom.ini - - # Only copy wait-for-it script if not already present - COPY humhub/wait-for-it.sh - - # Copy entrypoint script - COPY humhub/docker-entrypoint.sh - - # Make scripts executable - RUN chmod +x /usr/local/bin/wait-for-it /usr/local/bin/docker-entrypoint.sh - - # Download and verify HumHub - RUN curl -SL https://download.humhub.com/downloads/install/humhub-\${HUMHUB_VERSION}.zip -o humhub.zip && \ - unzip humhub.zip -d /tmp/ && \ - rm humhub.zip && \ - mv /tmp/humhub-* /var/www/html && \ - # Create health check script - echo " /var/www/html/ping && \ - # Set directory permissions - chmod -R 755 /var/www/html && \ - find /var/www/html -type f -exec chmod 644 {} \\; && \ - find /var/www/html -type d -exec chmod 755 {} \\; && \ - chmod -R 775 /var/www/html/protected/runtime /var/www/html/protected/modules /var/www/html/uploads /var/www/html/assets && \ - chown -R www-data:www-data /var/www/html && \ - # Clean up unneeded test dirs - rm -rf /var/www/html/protected/vendor/bower-asset/*/test \ - /var/www/html/protected/vendor/bower-asset/*/tests \ - /var/www/html/protected/vendor/*/test \ - /var/www/html/protected/vendor/*/tests \ - /var/www/html/protected/runtime/logs/* - - # Create volume mount points - VOLUME ["/var/www/html/protected/runtime", "/var/www/html/uploads", "/var/www/html/protected/modules", "/var/www/html/protected/config", "/var/www/html/themes"] - - # Set working directory - WORKDIR /var/www/html - - # Set entrypoint and default command - ENTRYPOINT ["docker-entrypoint.sh"] - CMD ["php-fpm"] - EOF - - # Create nginx directory and add docker-entrypoint.sh - mkdir -p nginx - echo '#!/bin/sh - set -e - - # Run nginx - exec nginx -g "daemon off;"' > nginx/docker-entrypoint.sh - chmod +x nginx/docker-entrypoint.sh - - # Create simple Nginx Dockerfile - cat > nginx/Dockerfile << EOF - FROM nginx:stable-alpine - - COPY docker-entrypoint.sh / - - ENTRYPOINT ["/docker-entrypoint.sh"] - EOF - - # Create backup directory and scripts - mkdir -p backup/scripts - echo '#!/bin/bash - set -e - - echo "Running backup..." - # Add your backup logic here - - # Example backup command - mysqldump -h$MYSQL_HOST -u$MYSQL_USER -p$MYSQL_PASSWORD $MYSQL_DATABASE > /backup/source/db_backup.sql - - # Example creating a borg backup archive - borg create --stats --compression lz4 /backup/repo::$(date +%Y-%m-%d_%H-%M-%S) /backup/source - - echo "Backup completed successfully!" - ' > backup/scripts/backup.sh - chmod +x backup/scripts/backup.sh - - # Create backup Dockerfile - cat > backup/Dockerfile << EOF - FROM alpine:3.17 - - RUN apk add --no-cache borgbackup mariadb-client bash - - VOLUME ["/backup"] - - COPY scripts/backup.sh /usr/local/bin/backup.sh - - ENTRYPOINT ["backup.sh"] - EOF + run: bash .github/scripts/generate-build-context.sh docker-build: name: Build Docker Images runs-on: ubuntu-latest needs: build steps: - - name: Checkout code - uses: actions/checkout@v4 + - uses: actions/checkout@v4 - - name: Set up Docker Buildx - uses: docker/setup-buildx-action@v3 + - uses: docker/setup-buildx-action@v3 - - name: Log in to Docker Hub - uses: docker/login-action@v3 + - uses: docker/login-action@v3 with: registry: ${{ env.REGISTRY }} username: ${{ secrets.DOCKER_USERNAME }} @@ -298,22 +106,19 @@ jobs: echo "nginx_tags=$NGINX_TAGS" >> $GITHUB_OUTPUT echo "backup_tags=$BACKUP_TAGS" >> $GITHUB_OUTPUT - - name: Build and push HumHub Docker image - uses: docker/build-push-action@v4 + - uses: docker/build-push-action@v4 with: context: humhub push: true tags: ${{ steps.tags.outputs.tags }} - - name: Build and push Nginx Docker image - uses: docker/build-push-action@v4 + - uses: docker/build-push-action@v4 with: context: nginx push: true tags: ${{ steps.tags.outputs.nginx_tags }} - - name: Build and push Backup Docker image - uses: docker/build-push-action@v4 + - uses: docker/build-push-action@v4 with: context: backup push: true diff --git a/humhub/Dockerfile b/humhub/Dockerfile index 6d77c8b..e6f6f96 100644 --- a/humhub/Dockerfile +++ b/humhub/Dockerfile @@ -1,5 +1,8 @@ FROM php:8.2-fpm +# Set shell with pipefail option +SHELL ["/bin/bash", "-o", "pipefail", "-c"] + ARG HUMHUB_VERSION=1.17.2 # Install dependencies @@ -17,9 +20,9 @@ RUN apt-get update && apt-get install -y --no-install-recommends --no-install-su unzip \ gnupg \ git \ + file \ libmagickwand-dev && \ rm -rf /var/lib/apt/lists/* && \ - # Install PHP extensions and PECL extensions docker-php-ext-configure gd --with-freetype --with-jpeg && \ docker-php-ext-configure ldap --with-libdir=lib/x86_64-linux-gnu/ && \ docker-php-ext-install -j"$(nproc)" \ @@ -47,28 +50,52 @@ COPY docker-entrypoint.sh /usr/local/bin/docker-entrypoint.sh # Make scripts executable RUN chmod +x /usr/local/bin/wait-for-it /usr/local/bin/docker-entrypoint.sh -# Download and verify HumHub -RUN curl -SL https://download.humhub.com/downloads/install/humhub-${HUMHUB_VERSION}.zip -o humhub.zip && \ - unzip humhub.zip -d /tmp/ && \ +# Download and verify HumHub with better error handling +RUN set -ex && \ + echo "Downloading HumHub version ${HUMHUB_VERSION}..." && \ + wget -q --show-progress --tries=5 --waitretry=5 -O humhub.zip \ + "https://download.humhub.com/downloads/install/humhub-${HUMHUB_VERSION}.zip" && \ + echo "Verifying download..." && \ + file humhub.zip && \ + file humhub.zip | grep -q 'Zip archive data' && \ + echo "Extracting archive..." && \ + unzip -q humhub.zip -d /tmp/ && \ rm humhub.zip && \ - mv /tmp/humhub-* /var/www/html && \ - # Create health check script + echo "Contents of /tmp after extraction:" && \ + ls -la /tmp/ && \ + echo "Moving HumHub files..." && \ + HUMHUB_DIR=$(find /tmp -maxdepth 1 -name "humhub-*" -type d | head -1) && \ + if [ -z "$HUMHUB_DIR" ]; then \ + echo "Error: No humhub directory found in /tmp" && \ + exit 1; \ + fi && \ + echo "Found HumHub directory: $HUMHUB_DIR" && \ + mv "$HUMHUB_DIR"/* /var/www/html/ && \ + find "$HUMHUB_DIR" -name ".*" -not -name "." -not -name ".." -exec mv {} /var/www/html/ \; 2>/dev/null || true && \ + rmdir "$HUMHUB_DIR" && \ + echo "Creating ping file..." && \ echo " /var/www/html/ping && \ - # Set directory permissions + echo "Setting permissions..." && \ chmod -R 755 /var/www/html && \ find /var/www/html -type f -exec chmod 644 {} \; && \ find /var/www/html -type d -exec chmod 755 {} \; && \ + echo "Setting special directory permissions..." && \ + mkdir -p /var/www/html/protected/runtime \ + /var/www/html/protected/modules \ + /var/www/html/uploads \ + /var/www/html/assets && \ chmod -R 775 /var/www/html/protected/runtime \ - /var/www/html/protected/modules \ - /var/www/html/uploads \ - /var/www/html/assets && \ + /var/www/html/protected/modules \ + /var/www/html/uploads \ + /var/www/html/assets && \ chown -R www-data:www-data /var/www/html && \ - # Clean up unneeded test dirs + echo "Cleaning up vendor test directories..." && \ rm -rf /var/www/html/protected/vendor/bower-asset/*/test \ /var/www/html/protected/vendor/bower-asset/*/tests \ /var/www/html/protected/vendor/*/test \ /var/www/html/protected/vendor/*/tests \ - /var/www/html/protected/runtime/logs/* + /var/www/html/protected/runtime/logs/* 2>/dev/null || true && \ + echo "HumHub installation completed successfully" # Create volume mount points VOLUME ["/var/www/html/protected/runtime", "/var/www/html/uploads", "/var/www/html/protected/modules", "/var/www/html/protected/config", "/var/www/html/themes"]