From 98211d3620fb5e22e9712f2fe24e202304a26c1a Mon Sep 17 00:00:00 2001 From: Christian Winther Date: Thu, 28 Dec 2023 23:46:59 +0000 Subject: [PATCH 001/173] refactor Dockerfile and Docker workflow --- .dockerignore | 3 +- .editorconfig | 4 + .github/workflows/build-docker.yml | 125 ------- .github/workflows/docker.yml | 176 ++++++++++ .hadolint.yaml | 5 + config/filesystems.php | 2 +- contrib/docker/Dockerfile | 320 ++++++++++++++++++ contrib/docker/Dockerfile.apache | 100 ------ contrib/docker/Dockerfile.fpm | 90 ----- contrib/docker/README.md | 214 ++++++++++++ .../apache/conf-available/remoteip.conf | 4 + .../apache/docker-entrypoint.d/.gitkeep | 0 contrib/docker/docker-entrypoint.sh | 45 +++ .../docker/fpm/docker-entrypoint.d/.gitkeep | 0 contrib/docker/nginx/Procfile | 2 + contrib/docker/nginx/default-http.conf | 49 +++ .../docker/nginx/docker-entrypoint.d/.gitkeep | 0 contrib/docker/php.production.ini | 6 +- .../shared/docker-entrypoint.d/00-storage.sh | 13 + .../shared/docker-entrypoint.d/01-cache.sh | 13 + .../shared/docker-entrypoint.d/02-horizon.sh | 6 + contrib/docker/shared/lib.sh | 13 + contrib/docker/start.apache.sh | 15 - contrib/docker/start.fpm.sh | 15 - .../views/admin/diagnostics/home.blade.php | 2 +- 25 files changed, 870 insertions(+), 352 deletions(-) delete mode 100644 .github/workflows/build-docker.yml create mode 100644 .github/workflows/docker.yml create mode 100644 .hadolint.yaml create mode 100644 contrib/docker/Dockerfile delete mode 100644 contrib/docker/Dockerfile.apache delete mode 100644 contrib/docker/Dockerfile.fpm create mode 100644 contrib/docker/README.md create mode 100644 contrib/docker/apache/conf-available/remoteip.conf create mode 100644 contrib/docker/apache/docker-entrypoint.d/.gitkeep create mode 100755 contrib/docker/docker-entrypoint.sh create mode 100644 contrib/docker/fpm/docker-entrypoint.d/.gitkeep create mode 100644 contrib/docker/nginx/Procfile create mode 100644 contrib/docker/nginx/default-http.conf create mode 100644 contrib/docker/nginx/docker-entrypoint.d/.gitkeep create mode 100755 contrib/docker/shared/docker-entrypoint.d/00-storage.sh create mode 100755 contrib/docker/shared/docker-entrypoint.d/01-cache.sh create mode 100755 contrib/docker/shared/docker-entrypoint.d/02-horizon.sh create mode 100644 contrib/docker/shared/lib.sh delete mode 100755 contrib/docker/start.apache.sh delete mode 100755 contrib/docker/start.fpm.sh diff --git a/.dockerignore b/.dockerignore index 70376cdf4..8e25f3cbc 100644 --- a/.dockerignore +++ b/.dockerignore @@ -1,6 +1,5 @@ data -Dockerfile -contrib/docker/Dockerfile.* +contrib/docker/Dockerfile docker-compose*.yml .dockerignore .git diff --git a/.editorconfig b/.editorconfig index 1cd7d1077..0eda619e8 100644 --- a/.editorconfig +++ b/.editorconfig @@ -7,3 +7,7 @@ end_of_line = lf charset = utf-8 trim_trailing_whitespace = true insert_final_newline = true + +[{*.yml,*.yaml}] +indent_style = space +indent_size = 2 diff --git a/.github/workflows/build-docker.yml b/.github/workflows/build-docker.yml deleted file mode 100644 index 34f31cf08..000000000 --- a/.github/workflows/build-docker.yml +++ /dev/null @@ -1,125 +0,0 @@ ---- -name: Build Docker image - -on: - workflow_dispatch: - push: - branches: - - dev - tags: - - '*' - pull_request: - paths: - - .github/workflows/build-docker.yml - - contrib/docker/Dockerfile.apache - - contrib/docker/Dockerfile.fpm -permissions: - contents: read - -jobs: - build-docker-apache: - runs-on: ubuntu-latest - - steps: - - name: Checkout Code - uses: actions/checkout@v3 - - - name: Docker Lint - uses: hadolint/hadolint-action@v3.0.0 - with: - dockerfile: contrib/docker/Dockerfile.apache - failure-threshold: error - - - name: Set up QEMU - uses: docker/setup-qemu-action@v2 - - - name: Set up Docker Buildx - uses: docker/setup-buildx-action@v2 - - - name: Login to DockerHub - uses: docker/login-action@v2 - secrets: inherit - with: - username: ${{ secrets.DOCKER_HUB_USERNAME }} - password: ${{ secrets.DOCKER_HUB_TOKEN }} - if: github.event_name != 'pull_request' - - - name: Fetch tags - uses: docker/metadata-action@v4 - secrets: inherit - id: meta - with: - images: ${{ secrets.DOCKER_HUB_ORGANISATION }}/pixelfed - flavor: | - latest=auto - suffix=-apache - tags: | - type=edge,branch=dev - type=pep440,pattern={{raw}} - type=pep440,pattern=v{{major}}.{{minor}} - type=ref,event=pr - - - name: Build and push Docker image - uses: docker/build-push-action@v3 - with: - context: . - file: contrib/docker/Dockerfile.apache - platforms: linux/amd64,linux/arm64 - builder: ${{ steps.buildx.outputs.name }} - push: ${{ github.event_name != 'pull_request' }} - tags: ${{ steps.meta.outputs.tags }} - cache-from: type=gha - cache-to: type=gha,mode=max - - build-docker-fpm: - runs-on: ubuntu-latest - - steps: - - name: Checkout Code - uses: actions/checkout@v3 - - - name: Docker Lint - uses: hadolint/hadolint-action@v3.0.0 - with: - dockerfile: contrib/docker/Dockerfile.fpm - failure-threshold: error - - - name: Set up QEMU - uses: docker/setup-qemu-action@v2 - - - name: Set up Docker Buildx - uses: docker/setup-buildx-action@v2 - - - name: Login to DockerHub - uses: docker/login-action@v2 - secrets: inherit - with: - username: ${{ secrets.DOCKER_HUB_USERNAME }} - password: ${{ secrets.DOCKER_HUB_TOKEN }} - if: github.event_name != 'pull_request' - - - name: Fetch tags - uses: docker/metadata-action@v4 - secrets: inherit - id: meta - with: - images: ${{ secrets.DOCKER_HUB_ORGANISATION }}/pixelfed - flavor: | - suffix=-fpm - tags: | - type=edge,branch=dev - type=pep440,pattern={{raw}} - type=pep440,pattern=v{{major}}.{{minor}} - type=ref,event=pr - - - name: Build and push Docker image - uses: docker/build-push-action@v3 - with: - context: . - file: contrib/docker/Dockerfile.fpm - platforms: linux/amd64,linux/arm64 - builder: ${{ steps.buildx.outputs.name }} - push: ${{ github.event_name != 'pull_request' }} - tags: ${{ steps.meta.outputs.tags }} - cache-from: type=gha - cache-to: type=gha,mode=max diff --git a/.github/workflows/docker.yml b/.github/workflows/docker.yml new file mode 100644 index 000000000..b71c08c87 --- /dev/null +++ b/.github/workflows/docker.yml @@ -0,0 +1,176 @@ +--- +name: Docker + +on: + # See: https://docs.github.com/en/actions/using-workflows/events-that-trigger-workflows#workflow_dispatch + workflow_dispatch: + + # See: https://docs.github.com/en/actions/using-workflows/events-that-trigger-workflows#push + push: + branches: + - dev + - jippi-fork # TODO(jippi): remove me before merge + tags: + - "*" + + # See: https://docs.github.com/en/actions/using-workflows/events-that-trigger-workflows#pull_request + pull_request: + types: + - labeled + - opened + - ready_for_review + - reopened + - synchronize + +jobs: + lint: + runs-on: ubuntu-latest + + permissions: + contents: read + + steps: + - name: Checkout Code + uses: actions/checkout@v4 + + - name: Docker Lint + uses: hadolint/hadolint-action@v3.1.0 + with: + dockerfile: contrib/docker/Dockerfile + failure-threshold: error + + build: + runs-on: ubuntu-latest + + strategy: + fail-fast: false + + # See: https://docs.github.com/en/actions/using-jobs/using-a-matrix-for-your-jobs + matrix: + php_version: + - 8.1 + - 8.2 + - 8.3 + target_runtime: + - apache + - fpm + - nginx + php_base: + - apache + - fpm + + # See: https://docs.github.com/en/actions/using-jobs/using-a-matrix-for-your-jobs#excluding-matrix-configurations + # See: https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstrategymatrixexclude + exclude: + # Broken for imagick on arm64 due to https://github.com/Imagick/imagick/pull/641 + # Could probably figure out how to do a matrix only ignoring 8.3 + linux/arm64, but this is easier atm + - php_version: 8.3 + + # targeting [apache] runtime with [fpm] base type doesn't make sense + - target_runtime: apache + php_base: fpm + + # targeting [fpm] runtime with [apache] base type doesn't make sense + - target_runtime: fpm + php_base: apache + + # targeting [nginx] runtime with [apache] base type doesn't make sense + - target_runtime: nginx + php_base: apache + + # See: https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#example-using-concurrency-and-the-default-behavior + concurrency: + group: docker-build-${{ github.ref }}-${{ matrix.php_base }}-${{ matrix.php_version }}-${{ matrix.target_runtime }} + cancel-in-progress: true + + permissions: + contents: read + packages: write + + env: + # Set the repo variable [DOCKER_HUB_USERNAME] to override the default at https://github.com///settings/variables/actions + # + # NOTE: no login attempt will happen with Docker Hub until this secret is set + DOCKER_HUB_USERNAME: ${{ vars.DOCKER_HUB_USERNAME || 'pixelfed' }} + + # Set the repo variable [DOCKER_HUB_ORGANISATION] to override the default at https://github.com///settings/variables/actions + # + # NOTE: no login attempt will happen with Docker Hub until this secret is set + DOCKER_HUB_ORGANISATION: ${{ vars.DOCKER_HUB_ORGANISATION || 'pixelfed' }} + + # Set the repo variable [DOCKER_HUB_REPO] to override the default at https://github.com///settings/variables/actions + # + # NOTE: no login attempt will happen with Docker Hub until this secret is set + DOCKER_HUB_REPO: ${{ vars.DOCKER_HUB_REPO || 'pixelfed' }} + + # For Docker Hub pushing to work, you need the secret [DOCKER_HUB_TOKEN] + # set to your Personal Access Token at https://github.com///settings/secrets/actions + # + # NOTE: no login attempt will happen with Docker Hub until this secret is set + HAS_DOCKER_HUB_TOKEN: ${{ secrets.DOCKER_HUB_TOKEN != '' }} + + steps: + - name: Checkout Code + uses: actions/checkout@v4 + + - name: Set up QEMU + uses: docker/setup-qemu-action@v3 + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v3 + id: buildx + with: + version: v0.12.0 # *or* newer, needed for annotations to work + + - name: Log in to the GitHub Container registry + uses: docker/login-action@v3 + with: + registry: ghcr.io + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} + + - name: Login to Docker Hub registry (conditionally) + uses: docker/login-action@v3 + with: + username: ${{ env.DOCKER_HUB_USERNAME }} + password: ${{ secrets.DOCKER_HUB_TOKEN }} + if: ${{ env.HAS_DOCKER_HUB_TOKEN == true }} + + - name: Docker meta + uses: docker/metadata-action@v5 + id: meta + with: + images: | + name=ghcr.io/${{ github.repository }},enable=true + name=${{ env.DOCKER_HUB_ORGANISATION }}/${{ env.DOCKER_HUB_REPO }},enable=${{ env.HAS_DOCKER_HUB_TOKEN }} + flavor: | + latest=auto + suffix=-${{ matrix.target_runtime }}-${{ matrix.php_version }} + tags: | + type=edge,branch=dev + type=pep440,pattern={{raw}} + type=pep440,pattern=v{{major}}.{{minor}} + type=ref,event=branch,prefix=branch- + type=ref,event=pr,prefix=pr- + type=ref,event=tag + env: + DOCKER_METADATA_ANNOTATIONS_LEVELS: manifest,index + + - name: Build and push Docker image + uses: docker/build-push-action@v5 + with: + context: . + file: contrib/docker/Dockerfile + target: ${{ matrix.target_runtime }}-runtime + platforms: linux/amd64,linux/arm64 + builder: ${{ steps.buildx.outputs.name }} + tags: ${{ steps.meta.outputs.tags }} + annotations: ${{ steps.meta.outputs.annotations }} + push: true + sbom: true + provenance: true + build-args: | + PHP_VERSION=${{ matrix.php_version }} + PHP_BASE_TYPE=${{ matrix.php_base }} + cache-from: type=gha,scope=${{ matrix.target_runtime }}-${{ matrix.php_base }}-${{ matrix.php_version }} + cache-to: type=gha,mode=max,scope=${{ matrix.target_runtime }}-${{ matrix.php_base }}-${{ matrix.php_version }} diff --git a/.hadolint.yaml b/.hadolint.yaml new file mode 100644 index 000000000..cbb62ca47 --- /dev/null +++ b/.hadolint.yaml @@ -0,0 +1,5 @@ +ignored: + - DL3002 # warning: Last USER should not be root + - DL3008 # warning: Pin versions in apt get install. Instead of `apt-get install ` use `apt-get install =` + - SC2046 # warning: Quote this to prevent word splitting. + - SC2086 # info: Double quote to prevent globbing and word splitting. diff --git a/config/filesystems.php b/config/filesystems.php index 6817d5e34..d5247c980 100644 --- a/config/filesystems.php +++ b/config/filesystems.php @@ -72,7 +72,7 @@ return [ 'secret' => env('AWS_SECRET_ACCESS_KEY'), 'region' => env('AWS_DEFAULT_REGION'), 'bucket' => env('AWS_BUCKET'), - 'visibility' => 'public', + 'visibility' => env('AWS_VISIBILITY', 'public'), 'url' => env('AWS_URL'), 'endpoint' => env('AWS_ENDPOINT'), 'use_path_style_endpoint' => env('AWS_USE_PATH_STYLE_ENDPOINT', false), diff --git a/contrib/docker/Dockerfile b/contrib/docker/Dockerfile new file mode 100644 index 000000000..0a15bc6b5 --- /dev/null +++ b/contrib/docker/Dockerfile @@ -0,0 +1,320 @@ +# syntax=docker/dockerfile:1 +# See https://hub.docker.com/r/docker/dockerfile + +####################################################### +# Configuration +####################################################### + +ARG COMPOSER_VERSION="2.6" +ARG NGINX_VERSION=1.25.3 +ARG FOREGO_VERSION=0.17.2 +ARG PECL_EXTENSIONS_EXTRA="" +ARG PECL_EXTENSIONS="imagick redis" +ARG PHP_BASE_TYPE="apache" +ARG PHP_DATABASE_EXTENSIONS="pdo_pgsql pdo_mysql" +ARG PHP_DEBIAN_RELEASE="bullseye" +ARG PHP_EXTENSIONS_EXTRA="" +ARG PHP_EXTENSIONS="intl bcmath zip pcntl exif curl gd" +ARG PHP_VERSION="8.1" +ARG APT_PACKAGES_EXTRA="" + +# GPG key for nginx apt repository +ARG NGINX_GPGKEY=573BFD6B3D8FBC641079A6ABABF5BD827BD9BF62 + +# GPP key path for nginx apt repository +ARG NGINX_GPGKEY_PATH=/usr/share/keyrings/nginx-archive-keyring.gpg + +####################################################### +# Docker "copy from" images +####################################################### + +# Composer docker image from Docker Hub +# +# NOTE: Docker will *not* pull this image unless it's referenced (via build target) +FROM composer:${COMPOSER_VERSION} AS composer-image + +# nginx webserver from Docker Hub. +# Used to copy some docker-entrypoint files for [nginx-runtime] +# +# NOTE: Docker will *not* pull this image unless it's referenced (via build target) +FROM nginx:${NGINX_VERSION} AS nginx-image + +# Forego is a Procfile "runner" that makes it trival to run multiple +# processes under a simple init / PID 1 process. +# +# NOTE: Docker will *not* pull this image unless it's referenced (via build target) +# +# See: https://github.com/nginx-proxy/forego +FROM nginxproxy/forego:${FOREGO_VERSION}-debian AS forego-image + +####################################################### +# Base image +####################################################### + +FROM php:${PHP_VERSION}-${PHP_BASE_TYPE}-${PHP_DEBIAN_RELEASE} AS base + +ARG PHP_VERSION +ARG PHP_DEBIAN_RELEASE +ARG APT_PACKAGES_EXTRA + +ARG TARGETPLATFORM +ARG BUILDKIT_SBOM_SCAN_STAGE=true + +ENV DEBIAN_FRONTEND=noninteractive + +# Ensure we run all scripts through 'bash' rather than 'sh' +SHELL ["/bin/bash", "-c"] + +RUN set -ex \ + && mkdir -pv /var/www/ \ + && chown -R 33:33 /var/www + +WORKDIR /var/www/ + +# Install package dependencies +RUN --mount=type=cache,id=pixelfed-apt-${PHP_VERSION}-${PHP_DEBIAN_RELEASE}-${TARGETPLATFORM},sharing=locked,target=/var/lib/apt \ + --mount=type=cache,id=pixelfed-apt-cache-${PHP_VERSION}-${PHP_DEBIAN_RELEASE}-${TARGETPLATFORM},sharing=locked,target=/var/cache/apt \ +<<-SCRIPT + #!/bin/bash + set -ex -o errexit -o nounset -o pipefail + + # ensure we keep apt cache around in a Docker environment + rm -f /etc/apt/apt.conf.d/docker-clean + echo 'Binary::apt::APT::Keep-Downloaded-Packages "true";' > /etc/apt/apt.conf.d/keep-cache + + # Standard packages + standardPackages=( + apt-utils + ca-certificates + gettext-base + git + gnupg1 + gosu + libcurl4-openssl-dev + libzip-dev + locales + locales-all + nano + procps + unzip + zip + ) + + # Image Optimization + imageOptimization=( + gifsicle + jpegoptim + optipng + pngquant + ) + + # Image Processing + imageProcessing=( + libjpeg62-turbo-dev + libmagickwand-dev + libpng-dev + ) + + # Required for GD + gdDependencies=( + libwebp-dev + libwebp6 + libxpm-dev + libxpm4 + ) + + # Video Processing + videoProcessing=( + ffmpeg + ) + + # Database + databaseDependencies=( + libpq-dev + libsqlite3-dev + ) + + apt-get update + + apt-get upgrade -y + + apt-get install -y --no-install-recommends \ + ${standardPackages[*]} \ + ${imageOptimization[*]} \ + ${imageProcessing[*]} \ + ${gdDependencies[*]} \ + ${videoProcessing[*]} \ + ${databaseDependencies[*]} \ + ${APT_PACKAGES_EXTRA} +SCRIPT + +# update locales +RUN set -ex \ + && locale-gen \ + && update-locale + +####################################################### +# PHP: extensions +####################################################### + +FROM base AS php-extensions + +ARG PECL_EXTENSIONS +ARG PECL_EXTENSIONS_EXTRA +ARG PHP_DATABASE_EXTENSIONS +ARG PHP_DEBIAN_RELEASE +ARG PHP_EXTENSIONS +ARG PHP_EXTENSIONS_EXTRA +ARG PHP_VERSION +ARG TARGETPLATFORM + +RUN --mount=type=cache,id=pixelfed-php-${PHP_VERSION}-${PHP_DEBIAN_RELEASE}-${TARGETPLATFORM},sharing=locked,target=/usr/src/php/ \ + set -ex \ + # Grab the PHP source code so we can compile against it + && docker-php-source extract \ + # Install pecl extensions + && pecl install ${PECL_EXTENSIONS} ${PECL_EXTENSIONS_EXTRA} \ + # PHP GD extensions + && docker-php-ext-configure gd \ + --with-freetype \ + --with-jpeg \ + --with-webp \ + --with-xpm \ + # PHP extensions (dependencies) + && docker-php-ext-install -j$(nproc) ${PHP_EXTENSIONS} ${PHP_EXTENSIONS_EXTRA} ${PHP_DATABASE_EXTENSIONS} \ + # Enable all extensions + && docker-php-ext-enable ${PECL_EXTENSIONS} ${PECL_EXTENSIONS_EXTRA} ${PHP_EXTENSIONS} ${PHP_EXTENSIONS_EXTRA} ${PHP_DATABASE_EXTENSIONS} + +####################################################### +# PHP: composer and source code +####################################################### + +FROM base AS composer-and-src + +ARG PHP_VERSION +ARG PHP_DEBIAN_RELEASE +ARG TARGETPLATFORM + +# Make sure composer cache is targeting our cache mount later +ENV COMPOSER_CACHE_DIR=/cache/composer + +# Don't enforce any memory limits for composer +ENV COMPOSER_MEMORY_LIMIT=-1 + +# Disable interactvitity from composer +ENV COMPOSER_NO_INTERACTION=1 + +# Copy composer from https://hub.docker.com/_/composer +COPY --link --from=composer-image /usr/bin/composer /usr/bin/composer + +#! Changing user to 33 +USER 33:33 + +# Copy over only composer related files so docker layer cache isn't invalidated on PHP file changes +COPY --link --chown=33:33 composer.json composer.lock /var/www/ + +# Install composer dependencies +# NOTE: we skip the autoloader generation here since we don't have all files avaliable (yet) +RUN --mount=type=cache,id=pixelfed-composer-${PHP_VERSION}-${PHP_DEBIAN_RELEASE}-${TARGETPLATFORM},sharing=locked,target=/cache/composer \ + set -ex \ + && composer install --prefer-dist --no-autoloader --ignore-platform-reqs + +# Copy all other files over +COPY --link --chown=33:33 . /var/www/ + +# Generate optimized autoloader now that we have all files around +RUN set -ex \ + && composer dump-autoload --optimize + +#! Changing back to root +USER root:root + +####################################################### +# Runtime: base +####################################################### + +FROM base AS shared-runtime + +COPY --link --from=php-extensions /usr/local/lib/php/extensions /usr/local/lib/php/extensions +COPY --link --from=php-extensions /usr/local/etc/php /usr/local/etc/php +COPY --link --from=composer-and-src --chown=33:33 /var/www /var/www +COPY --link --from=forego-image /usr/local/bin/forego /usr/local/bin/forego +COPY --link contrib/docker/php.production.ini "$PHP_INI_DIR/php.ini" + +# for detail why storage is copied this way, pls refer to https://github.com/pixelfed/pixelfed/pull/2137#discussion_r434468862 +RUN set -ex \ + && cp --recursive --link --preserve=all storage storage.skel \ + && rm -rf html && ln -s public html + +COPY --link contrib/docker/docker-entrypoint.sh /docker-entrypoint.sh +COPY --link contrib/docker/shared/lib.sh /lib.sh +COPY --link contrib/docker/shared/docker-entrypoint.d /docker-entrypoint.d/ + +ENTRYPOINT ["/docker-entrypoint.sh"] + +VOLUME /var/www/storage /var/www/bootstrap + +####################################################### +# Runtime: apache +####################################################### + +FROM shared-runtime AS apache-runtime + +COPY --link contrib/docker/apache/conf-available/remoteip.conf /etc/apache2/conf-available/remoteip.conf +COPY --link contrib/docker/apache/docker-entrypoint.d /docker-entrypoint.d/ + +RUN set -ex \ + && a2enmod rewrite remoteip proxy proxy_http \ + && a2enconf remoteip + +CMD ["apache2-foreground"] + +EXPOSE 80 + +####################################################### +# Runtime: fpm +####################################################### + +FROM shared-runtime AS fpm-runtime + +COPY --link contrib/docker/fpm/docker-entrypoint.d /docker-entrypoint.d/ + +CMD ["php-fpm"] + +EXPOSE 9000 + +####################################################### +# Runtime: nginx +####################################################### + +FROM shared-runtime AS nginx-runtime + +ARG NGINX_GPGKEY +ARG NGINX_GPGKEY_PATH +ARG NGINX_VERSION +ARG PHP_DEBIAN_RELEASE +ARG PHP_VERSION +ARG TARGETPLATFORM + +# Install nginx dependencies +RUN --mount=type=cache,id=pixelfed-apt-lists-${PHP_VERSION}-${PHP_DEBIAN_RELEASE}-${TARGETPLATFORM},sharing=locked,target=/var/lib/apt/lists \ + --mount=type=cache,id=pixelfed-apt-cache-${PHP_VERSION}-${PHP_DEBIAN_RELEASE}-${TARGETPLATFORM},sharing=locked,target=/var/cache/apt \ + set -ex \ + && gpg1 --keyserver "hkp://keyserver.ubuntu.com:80" --keyserver-options timeout=10 --recv-keys "${NGINX_GPGKEY}" \ + && gpg1 --export "$NGINX_GPGKEY" > "$NGINX_GPGKEY_PATH" \ + && echo "deb [signed-by=${NGINX_GPGKEY_PATH}] https://nginx.org/packages/mainline/debian/ ${PHP_DEBIAN_RELEASE} nginx" >> /etc/apt/sources.list.d/nginx.list \ + && apt-get update \ + && apt-get install -y --no-install-recommends \ + nginx=${NGINX_VERSION}* + +# copy docker entrypoints from the *real* nginx image directly +COPY --link --from=nginx-image /docker-entrypoint.d /docker-entrypoint.d/ +COPY --link contrib/docker/nginx/docker-entrypoint.d /docker-entrypoint.d/ +COPY --link contrib/docker/nginx/default-http.conf /etc/nginx/templates/default.conf.template +COPY --link contrib/docker/nginx/Procfile . + +EXPOSE 80 + +STOPSIGNAL SIGQUIT + +CMD ["forego", "start", "-r"] diff --git a/contrib/docker/Dockerfile.apache b/contrib/docker/Dockerfile.apache deleted file mode 100644 index 9c33aee17..000000000 --- a/contrib/docker/Dockerfile.apache +++ /dev/null @@ -1,100 +0,0 @@ -FROM php:8.1-apache-bullseye - -ENV COMPOSER_MEMORY_LIMIT=-1 -ARG DEBIAN_FRONTEND=noninteractive -WORKDIR /var/www/ - -# Get Composer binary -COPY --from=composer:2.4.4 /usr/bin/composer /usr/bin/composer - -# Install package dependencies -RUN apt-get update \ - && apt-get upgrade -y \ -# && apt-get install -y --no-install-recommends apt-utils \ - && apt-get install -y --no-install-recommends \ -## Standard - locales \ - locales-all \ - git \ - gosu \ - zip \ - unzip \ - libzip-dev \ - libcurl4-openssl-dev \ -## Image Optimization - optipng \ - pngquant \ - jpegoptim \ - gifsicle \ -## Image Processing - libjpeg62-turbo-dev \ - libpng-dev \ - libmagickwand-dev \ -# Required for GD - libxpm4 \ - libxpm-dev \ - libwebp6 \ - libwebp-dev \ -## Video Processing - ffmpeg \ -## Database -# libpq-dev \ -# libsqlite3-dev \ - mariadb-client \ -# Locales Update - && sed -i '/en_US/s/^#//g' /etc/locale.gen \ - && locale-gen \ - && update-locale \ -# Install PHP extensions - && docker-php-source extract \ -#PHP Imagemagick extensions - && pecl install imagick \ - && docker-php-ext-enable imagick \ -# PHP GD extensions - && docker-php-ext-configure gd \ - --with-freetype \ - --with-jpeg \ - --with-webp \ - --with-xpm \ - && docker-php-ext-install -j$(nproc) gd \ -#PHP Redis extensions - && pecl install redis \ - && docker-php-ext-enable redis \ -#PHP Database extensions - && docker-php-ext-install pdo_mysql \ -#pdo_pgsql pdo_sqlite \ -#PHP extensions (dependencies) - && docker-php-ext-configure intl \ - && docker-php-ext-install -j$(nproc) intl bcmath zip pcntl exif curl \ -#APACHE Bootstrap - && a2enmod rewrite remoteip \ - && {\ - echo RemoteIPHeader X-Real-IP ;\ - echo RemoteIPTrustedProxy 10.0.0.0/8 ;\ - echo RemoteIPTrustedProxy 172.16.0.0/12 ;\ - echo RemoteIPTrustedProxy 192.168.0.0/16 ;\ - echo SetEnvIf X-Forwarded-Proto "https" HTTPS=on ;\ - } > /etc/apache2/conf-available/remoteip.conf \ - && a2enconf remoteip \ -#Cleanup - && docker-php-source delete \ - && apt-get autoremove --purge -y \ - && apt-get clean \ - && rm -rf /var/cache/apt \ - && rm -rf /var/lib/apt/lists/ - -# Use the default production configuration -COPY contrib/docker/php.production.ini "$PHP_INI_DIR/php.ini" - -COPY . /var/www/ -# for detail why storage is copied this way, pls refer to https://github.com/pixelfed/pixelfed/pull/2137#discussion_r434468862 -RUN cp -r storage storage.skel \ - && composer install --prefer-dist --no-interaction --no-ansi --optimize-autoloader \ - && rm -rf html && ln -s public html \ - && chown -R www-data:www-data /var/www - -RUN php artisan horizon:publish - -VOLUME /var/www/storage /var/www/bootstrap - -CMD ["/var/www/contrib/docker/start.apache.sh"] diff --git a/contrib/docker/Dockerfile.fpm b/contrib/docker/Dockerfile.fpm deleted file mode 100644 index 0b8e5c113..000000000 --- a/contrib/docker/Dockerfile.fpm +++ /dev/null @@ -1,90 +0,0 @@ -FROM php:8.1-fpm-bullseye - -ENV COMPOSER_MEMORY_LIMIT=-1 -ARG DEBIAN_FRONTEND=noninteractive -WORKDIR /var/www/ - -# Get Composer binary -COPY --from=composer:2.4.4 /usr/bin/composer /usr/bin/composer - -# Install package dependencies -RUN apt-get update \ - && apt-get upgrade -y \ -# && apt-get install -y --no-install-recommends apt-utils \ - && apt-get install -y --no-install-recommends \ -## Standard - locales \ - locales-all \ - git \ - gosu \ - zip \ - unzip \ - libzip-dev \ - libcurl4-openssl-dev \ -## Image Optimization - optipng \ - pngquant \ - jpegoptim \ - gifsicle \ -## Image Processing - libjpeg62-turbo-dev \ - libpng-dev \ - libmagickwand-dev \ -# Required for GD - libxpm4 \ - libxpm-dev \ - libwebp6 \ - libwebp-dev \ -## Video Processing - ffmpeg \ -## Database -# libpq-dev \ -# libsqlite3-dev \ - mariadb-client \ -# Locales Update - && sed -i '/en_US/s/^#//g' /etc/locale.gen \ - && locale-gen \ - && update-locale \ -# Install PHP extensions - && docker-php-source extract \ -#PHP Imagemagick extensions - && pecl install imagick \ - && docker-php-ext-enable imagick \ -# PHP GD extensions - && docker-php-ext-configure gd \ - --with-freetype \ - --with-jpeg \ - --with-webp \ - --with-xpm \ - && docker-php-ext-install -j$(nproc) gd \ -#PHP Redis extensions - && pecl install redis \ - && docker-php-ext-enable redis \ -#PHP Database extensions - && docker-php-ext-install pdo_mysql \ -#pdo_pgsql pdo_sqlite \ -#PHP extensions (dependencies) - && docker-php-ext-configure intl \ - && docker-php-ext-install -j$(nproc) intl bcmath zip pcntl exif curl \ -#Cleanup - && docker-php-source delete \ - && apt-get autoremove --purge -y \ - && apt-get clean \ - && rm -rf /var/cache/apt \ - && rm -rf /var/lib/apt/lists/ - -# Use the default production configuration -COPY contrib/docker/php.production.ini "$PHP_INI_DIR/php.ini" - -COPY . /var/www/ -# for detail why storage is copied this way, pls refer to https://github.com/pixelfed/pixelfed/pull/2137#discussion_r434468862 -RUN cp -r storage storage.skel \ - && composer install --prefer-dist --no-interaction --no-ansi --optimize-autoloader \ - && rm -rf html && ln -s public html \ - && chown -R www-data:www-data /var/www - -RUN php artisan horizon:publish - -VOLUME /var/www/storage /var/www/bootstrap - -CMD ["/var/www/contrib/docker/start.fpm.sh"] diff --git a/contrib/docker/README.md b/contrib/docker/README.md new file mode 100644 index 000000000..441477fe4 --- /dev/null +++ b/contrib/docker/README.md @@ -0,0 +1,214 @@ +# Pixelfed Docker images + +## Runtimes + +The Pixelfed Dockerfile support multiple target *runtimes* ([Apache](#apache), [Nginx + FPM](#nginx), and [fpm](#fpm)). + +You can consider a *runtime* target as individual Dockerfiles, but instead, all of them are build from the same optimized Dockerfile, sharing +90% of their configuration and packages. + +### Apache + +Building a custom Pixelfed Docker image using Apache + mod_php can be achieved the following way. + +#### docker build (Apache) + +```shell +docker build \ + -f contrib/docker/Dockerfile \ + --target apache-runtime \ + --tag / \ + . +``` + +#### docker compose (Apache) + +```yaml +version: "3" + +services: + app: + build: + context: . + dockerfile: contrib/docker/Dockerfile + target: apache-runtime +``` + +### Nginx + +Building a custom Pixelfed Docker image using nginx + FPM can be achieved the following way. + +#### docker build (nginx) + +```shell +docker build \ + -f contrib/docker/Dockerfile \ + --target nginx-runtime \ + --build-arg 'PHP_BASE_TYPE=fpm' \ + --tag / \ + . +``` + +#### docker compose (nginx) + +```yaml +version: "3" + +services: + app: + build: + context: . + dockerfile: contrib/docker/Dockerfile + target: nginx-runtime + args: + PHP_BASE_TYPE: fpm +``` + +### FPM + +Building a custom Pixelfed Docker image using FPM (only) can be achieved the following way. + +#### docker build (fpm) + +```shell +docker build \ + -f contrib/docker/Dockerfile \ + --target fpm-runtime \ + --build-arg 'PHP_BASE_TYPE=fpm' \ + --tag / \ + . +``` + +#### docker compose (fpm) + +```yaml +version: "3" + +services: + app: + build: + context: . + dockerfile: contrib/docker/Dockerfile + target: fpm-runtime + args: + PHP_BASE_TYPE: fpm +``` + +## Build settings (arguments) + +The Pixelfed Dockerfile utilizes [Docker Multi-stage builds](https://docs.docker.com/build/building/multi-stage/) and [Build arguments](https://docs.docker.com/build/guide/build-args/). + +Using *build arguments* allow us to create a flexible and more maintainable Dockerfile, supporting [multiple runtimes](#runtimes) ([FPM](#fpm), [Nginx](#nginx), [Apache + mod_php](#apache)) and end-user flexibility without having to fork or copy the Dockerfile. + +*Build arguments* can be configured using `--build-arg 'name=value'` for `docker build`, `docker compose build` and `docker buildx build`. For `docker-compose.yml` the `args` key for [`build`](https://docs.docker.com/compose/compose-file/compose-file-v3/#build) can be used. + +### `PHP_VERSION` + +The `PHP` version to use when building the runtime container. + +Any valid Docker Hub PHP version is acceptable here, as long as it's [published to Docker Hub](https://hub.docker.com/_/php/tags) + +**Example values**: + +* `8` will use the latest version of PHP 8 +* `8.1` will use the latest version of PHP 8.1 +* `8.2.14` will use PHP 8.2.14 +* `latest` will use whatever is the latest PHP version + +**Default value**: `8.1` + +### `PECL_EXTENSIONS` + +PECL extensions to install via `pecl install` + +Use [PECL_EXTENSIONS_EXTRA](#pecl_extensions_extra) if you want to add *additional* extenstions. + +Only change this setting if you want to change the baseline extensions. + +See the [`PECL extensions` documentation on Docker Hub](https://hub.docker.com/_/php) for more information. + +**Default value**: `imagick redis` + +### `PECL_EXTENSIONS_EXTRA` + +Extra PECL extensions (separated by space) to install via `pecl install` + +See the [`PECL extensions` documentation on Docker Hub](https://hub.docker.com/_/php) for more information. + +**Default value**: `""` + +### `PHP_EXTENSIONS` + +PHP Extensions to install via `docker-php-ext-install`. + +**NOTE:** use [`PHP_EXTENSIONS_EXTRA`](#php_extensions_extra) if you want to add *additional* extensions, only override this if you want to change the baseline extensions. + +See the [`How to install more PHP extensions` documentation on Docker Hub](https://hub.docker.com/_/php) for more information + +**Default value**: `intl bcmath zip pcntl exif curl gd` + +### `PHP_EXTENSIONS_EXTRA` + +Extra PHP Extensions (separated by space) to install via `docker-php-ext-install`. + +See the [`How to install more PHP extensions` documentation on Docker Hub](https://hub.docker.com/_/php) for more information. + +**Default value**: `""` + +### `PHP_DATABASE_EXTENSIONS` + +PHP database extensions to install. + +By default we install both `pgsql` and `mysql` since it's more convinient (and adds very little build time! but can be overwritten here if required. + +**Default value**: `pdo_pgsql pdo_mysql` + +### `COMPOSER_VERSION` + +The version of Composer to install. + +Please see the [Docker Hub `composer` page](https://hub.docker.com/_/composer) for valid values. + +**Default value**: `2.6` + +### `APT_PACKAGES_EXTRA` + +Extra APT packages (separated by space) that should be installed inside the image by `apt-get install` + +**Default value**: `""` + +### `NGINX_VERSION` + +Version of `nginx` to when targeting [`nginx-runtime`](#nginx). + +Please see the [Docker Hub `nginx` page](https://hub.docker.com/_/nginx) for available versions. + +**Default value**: `1.25.3` + +### `PHP_BASE_TYPE` + +The `PHP` base image layer to use when building the runtime container. + +When targeting + +* [`apache-runtime`](#apache) use `apache` +* [`fpm-runtime`](#fpm) use `fpm` +* [`nginx-runtime`](#nginx) use `fpm` + +**Valid values**: + +* `apache` +* `fpm` +* `cli` + +**Default value**: `apache` + +### `PHP_DEBIAN_RELEASE` + +The `Debian` Operation System version to use. + +**Valid values**: + +* `bullseye` +* `bookworm` + +**Default value**: `bullseye` diff --git a/contrib/docker/apache/conf-available/remoteip.conf b/contrib/docker/apache/conf-available/remoteip.conf new file mode 100644 index 000000000..1632f8e43 --- /dev/null +++ b/contrib/docker/apache/conf-available/remoteip.conf @@ -0,0 +1,4 @@ +RemoteIPHeader X-Real-IP +RemoteIPTrustedProxy 10.0.0.0/8 +RemoteIPTrustedProxy 172.16.0.0/12 +RemoteIPTrustedProxy 192.168.0.0/16 diff --git a/contrib/docker/apache/docker-entrypoint.d/.gitkeep b/contrib/docker/apache/docker-entrypoint.d/.gitkeep new file mode 100644 index 000000000..e69de29bb diff --git a/contrib/docker/docker-entrypoint.sh b/contrib/docker/docker-entrypoint.sh new file mode 100755 index 000000000..706c38317 --- /dev/null +++ b/contrib/docker/docker-entrypoint.sh @@ -0,0 +1,45 @@ +#!/bin/bash +# vim:sw=4:ts=4:et + +set -e + +source /lib.sh + +mkdir -p /docker-entrypoint.d/ + +if /usr/bin/find "/docker-entrypoint.d/" -mindepth 1 -maxdepth 1 -type f -print -quit 2>/dev/null | read v; then + entrypoint_log "/docker-entrypoint.d/ is not empty, will attempt to perform configuration" + + entrypoint_log "looking for shell scripts in /docker-entrypoint.d/" + find "/docker-entrypoint.d/" -follow -type f -print | sort -V | while read -r f; do + case "$f" in + *.envsh) + if [ -x "$f" ]; then + entrypoint_log "Sourcing $f"; + . "$f" + else + # warn on shell scripts without exec bit + entrypoint_log "Ignoring $f, not executable"; + fi + ;; + + *.sh) + if [ -x "$f" ]; then + entrypoint_log "Launching $f"; + "$f" + else + # warn on shell scripts without exec bit + entrypoint_log "Ignoring $f, not executable"; + fi + ;; + + *) entrypoint_log "Ignoring $f";; + esac + done + + entrypoint_log "Configuration complete; ready for start up" +else + entrypoint_log "No files found in /docker-entrypoint.d/, skipping configuration" +fi + +exec "$@" diff --git a/contrib/docker/fpm/docker-entrypoint.d/.gitkeep b/contrib/docker/fpm/docker-entrypoint.d/.gitkeep new file mode 100644 index 000000000..e69de29bb diff --git a/contrib/docker/nginx/Procfile b/contrib/docker/nginx/Procfile new file mode 100644 index 000000000..bd375bf6a --- /dev/null +++ b/contrib/docker/nginx/Procfile @@ -0,0 +1,2 @@ +fpm: php-fpm +nginx: nginx -g "daemon off;" diff --git a/contrib/docker/nginx/default-http.conf b/contrib/docker/nginx/default-http.conf new file mode 100644 index 000000000..8182dba7f --- /dev/null +++ b/contrib/docker/nginx/default-http.conf @@ -0,0 +1,49 @@ +server { + listen 80 default_server; + + server_name ${APP_DOMAIN}; + root /var/www/public; + + add_header X-Frame-Options "SAMEORIGIN"; + add_header X-XSS-Protection "1; mode=block"; + add_header X-Content-Type-Options "nosniff"; + + access_log /dev/stdout; + error_log /dev/stderr warn; + + index index.html index.htm index.php; + + charset utf-8; + client_max_body_size 100M; + + location / { + try_files $uri $uri/ /index.php?$query_string; + } + + location = /favicon.ico { + access_log off; + log_not_found off; + } + + location = /robots.txt { + access_log off; + log_not_found off; + } + + error_page 404 /index.php; + + location ~ \.php$ { + fastcgi_split_path_info ^(.+\.php)(/.+)$; + + fastcgi_pass 127.0.0.1:9000; + fastcgi_index index.php; + + include fastcgi_params; + + fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; + } + + location ~ /\.(?!well-known).* { + deny all; + } +} diff --git a/contrib/docker/nginx/docker-entrypoint.d/.gitkeep b/contrib/docker/nginx/docker-entrypoint.d/.gitkeep new file mode 100644 index 000000000..e69de29bb diff --git a/contrib/docker/php.production.ini b/contrib/docker/php.production.ini index b84839ff5..2a1df3988 100644 --- a/contrib/docker/php.production.ini +++ b/contrib/docker/php.production.ini @@ -363,7 +363,7 @@ zend.enable_gc = On ; Allows to include or exclude arguments from stack traces generated for exceptions ; Default: Off -; In production, it is recommended to turn this setting on to prohibit the output +; In production, it is recommended to turn this setting on to prohibit the output ; of sensitive information in stack traces zend.exception_ignore_args = On @@ -679,7 +679,7 @@ auto_globals_jit = On ; Its value may be 0 to disable the limit. It is ignored if POST data reading ; is disabled through enable_post_data_reading. ; http://php.net/post-max-size -post_max_size = 64M +post_max_size = 95M ; Automatically add files before PHP document. ; http://php.net/auto-prepend-file @@ -831,7 +831,7 @@ file_uploads = On ; Maximum allowed size for uploaded files. ; http://php.net/upload-max-filesize -upload_max_filesize = 64M +upload_max_filesize = 95M ; Maximum number of files that can be uploaded via a single request max_file_uploads = 20 diff --git a/contrib/docker/shared/docker-entrypoint.d/00-storage.sh b/contrib/docker/shared/docker-entrypoint.d/00-storage.sh new file mode 100755 index 000000000..079a7887c --- /dev/null +++ b/contrib/docker/shared/docker-entrypoint.d/00-storage.sh @@ -0,0 +1,13 @@ +#!/bin/bash + +set -e +source /lib.sh + +entrypoint_log "==> Create the storage tree if needed" +as_www_user cp --recursive storage.skel/* storage/ + +entrypoint_log "==> Ensure storage is linked" +as_www_user php artisan storage:link + +entrypoint_log "==> Ensure permissions are correct" +chown --recursive www-data:www-data storage/ bootstrap/ diff --git a/contrib/docker/shared/docker-entrypoint.d/01-cache.sh b/contrib/docker/shared/docker-entrypoint.d/01-cache.sh new file mode 100755 index 000000000..df2466b27 --- /dev/null +++ b/contrib/docker/shared/docker-entrypoint.d/01-cache.sh @@ -0,0 +1,13 @@ +#!/bin/bash + +set -e +source /lib.sh + +entrypoint_log "==> config:cache" +as_www_user php artisan config:cache + +entrypoint_log "==> route:cache" +as_www_user php artisan route:cache + +entrypoint_log "==> view:cache" +as_www_user php artisan view:cache diff --git a/contrib/docker/shared/docker-entrypoint.d/02-horizon.sh b/contrib/docker/shared/docker-entrypoint.d/02-horizon.sh new file mode 100755 index 000000000..4afd1ea4a --- /dev/null +++ b/contrib/docker/shared/docker-entrypoint.d/02-horizon.sh @@ -0,0 +1,6 @@ +#!/bin/bash + +set -e +source /lib.sh + +as_www_user php artisan horizon:publish diff --git a/contrib/docker/shared/lib.sh b/contrib/docker/shared/lib.sh new file mode 100644 index 000000000..3e7ef0f91 --- /dev/null +++ b/contrib/docker/shared/lib.sh @@ -0,0 +1,13 @@ +#!/bin/bash + +set -e + +function entrypoint_log() { + if [ -z "${ENTRYPOINT_QUIET_LOGS:-}" ]; then + echo "/docker-entrypoint.sh: $@" + fi +} + +function as_www_user() { + su --preserve-environment www-data --shell /bin/bash --command "${*}" +} diff --git a/contrib/docker/start.apache.sh b/contrib/docker/start.apache.sh deleted file mode 100755 index 4fb19e476..000000000 --- a/contrib/docker/start.apache.sh +++ /dev/null @@ -1,15 +0,0 @@ -#!/bin/bash - -# Create the storage tree if needed and fix permissions -cp -r storage.skel/* storage/ -chown -R www-data:www-data storage/ bootstrap/ - -# Refresh the environment -php artisan config:cache -php artisan storage:link -php artisan horizon:publish -php artisan route:cache -php artisan view:cache - -# Finally run Apache -apache2-foreground diff --git a/contrib/docker/start.fpm.sh b/contrib/docker/start.fpm.sh deleted file mode 100755 index 199489fc6..000000000 --- a/contrib/docker/start.fpm.sh +++ /dev/null @@ -1,15 +0,0 @@ -#!/bin/bash - -# Create the storage tree if needed and fix permissions -cp -r storage.skel/* storage/ -chown -R www-data:www-data storage/ bootstrap/ - -# Refresh the environment -php artisan config:cache -php artisan storage:link -php artisan horizon:publish -php artisan route:cache -php artisan view:cache - -# Finally run FPM -php-fpm diff --git a/resources/views/admin/diagnostics/home.blade.php b/resources/views/admin/diagnostics/home.blade.php index bf2b5d742..db44a2332 100644 --- a/resources/views/admin/diagnostics/home.blade.php +++ b/resources/views/admin/diagnostics/home.blade.php @@ -654,7 +654,7 @@ MEDIA MEDIA_EXIF_DATABASE - {{config_cache('media.exif.batabase') ? '✅ true' : '❌ false' }} + {{config_cache('media.exif.database') ? '✅ true' : '❌ false' }} From b19d3a20dd4db3c8bf4d221746986e37306dab38 Mon Sep 17 00:00:00 2001 From: Christian Winther Date: Thu, 4 Jan 2024 11:00:45 +0000 Subject: [PATCH 002/173] only run kernel tasks on one server lifted from https://github.com/pixelfed/pixelfed/pull/4634 --- app/Console/Kernel.php | 88 +++++++++---------- .../shared/docker-entrypoint.d/00-storage.sh | 2 +- .../shared/docker-entrypoint.d/01-cache.sh | 2 +- .../shared/docker-entrypoint.d/02-horizon.sh | 2 +- 4 files changed, 47 insertions(+), 47 deletions(-) diff --git a/app/Console/Kernel.php b/app/Console/Kernel.php index 046924eb6..2b6510e35 100644 --- a/app/Console/Kernel.php +++ b/app/Console/Kernel.php @@ -7,53 +7,53 @@ use Illuminate\Foundation\Console\Kernel as ConsoleKernel; class Kernel extends ConsoleKernel { - /** - * The Artisan commands provided by your application. - * - * @var array - */ - protected $commands = [ - // - ]; + /** + * The Artisan commands provided by your application. + * + * @var array + */ + protected $commands = [ + // + ]; - /** - * Define the application's command schedule. - * - * @param \Illuminate\Console\Scheduling\Schedule $schedule - * - * @return void - */ - protected function schedule(Schedule $schedule) - { - $schedule->command('media:optimize')->hourlyAt(40); - $schedule->command('media:gc')->hourlyAt(5); - $schedule->command('horizon:snapshot')->everyFiveMinutes(); - $schedule->command('story:gc')->everyFiveMinutes(); - $schedule->command('gc:failedjobs')->dailyAt(3); - $schedule->command('gc:passwordreset')->dailyAt('09:41'); - $schedule->command('gc:sessions')->twiceDaily(13, 23); + /** + * Define the application's command schedule. + * + * @param \Illuminate\Console\Scheduling\Schedule $schedule + * + * @return void + */ + protected function schedule(Schedule $schedule) + { + $schedule->command('media:optimize')->hourlyAt(40)->onOneServer(); + $schedule->command('media:gc')->hourlyAt(5)->onOneServer(); + $schedule->command('horizon:snapshot')->everyFiveMinutes()->onOneServer(); + $schedule->command('story:gc')->everyFiveMinutes()->onOneServer(); + $schedule->command('gc:failedjobs')->dailyAt(3)->onOneServer(); + $schedule->command('gc:passwordreset')->dailyAt('09:41')->onOneServer(); + $schedule->command('gc:sessions')->twiceDaily(13, 23)->onOneServer(); - if(in_array(config_cache('pixelfed.cloud_storage'), ['1', true, 'true']) && config('media.delete_local_after_cloud')) { - $schedule->command('media:s3gc')->hourlyAt(15); - } + if (in_array(config_cache('pixelfed.cloud_storage'), ['1', true, 'true']) && config('media.delete_local_after_cloud')) { + $schedule->command('media:s3gc')->hourlyAt(15)->onOneServer(); + } - if(config('import.instagram.enabled')) { - $schedule->command('app:transform-imports')->everyFourMinutes(); - $schedule->command('app:import-upload-garbage-collection')->hourlyAt(51); - $schedule->command('app:import-remove-deleted-accounts')->hourlyAt(37); - $schedule->command('app:import-upload-clean-storage')->twiceDailyAt(1, 13, 32); - } - } + if (config('import.instagram.enabled')) { + $schedule->command('app:transform-imports')->everyFourMinutes()->onOneServer(); + $schedule->command('app:import-upload-garbage-collection')->hourlyAt(51)->onOneServer(); + $schedule->command('app:import-remove-deleted-accounts')->hourlyAt(37)->onOneServer(); + $schedule->command('app:import-upload-clean-storage')->twiceDailyAt(1, 13, 32)->onOneServer(); + } + } - /** - * Register the commands for the application. - * - * @return void - */ - protected function commands() - { - $this->load(__DIR__.'/Commands'); + /** + * Register the commands for the application. + * + * @return void + */ + protected function commands() + { + $this->load(__DIR__ . '/Commands'); - require base_path('routes/console.php'); - } + require base_path('routes/console.php'); + } } diff --git a/contrib/docker/shared/docker-entrypoint.d/00-storage.sh b/contrib/docker/shared/docker-entrypoint.d/00-storage.sh index 079a7887c..860ec0425 100755 --- a/contrib/docker/shared/docker-entrypoint.d/00-storage.sh +++ b/contrib/docker/shared/docker-entrypoint.d/00-storage.sh @@ -1,6 +1,6 @@ #!/bin/bash +set -o errexit -o nounset -o pipefail -set -e source /lib.sh entrypoint_log "==> Create the storage tree if needed" diff --git a/contrib/docker/shared/docker-entrypoint.d/01-cache.sh b/contrib/docker/shared/docker-entrypoint.d/01-cache.sh index df2466b27..06e440802 100755 --- a/contrib/docker/shared/docker-entrypoint.d/01-cache.sh +++ b/contrib/docker/shared/docker-entrypoint.d/01-cache.sh @@ -1,6 +1,6 @@ #!/bin/bash +set -o errexit -o nounset -o pipefail -set -e source /lib.sh entrypoint_log "==> config:cache" diff --git a/contrib/docker/shared/docker-entrypoint.d/02-horizon.sh b/contrib/docker/shared/docker-entrypoint.d/02-horizon.sh index 4afd1ea4a..04227cf40 100755 --- a/contrib/docker/shared/docker-entrypoint.d/02-horizon.sh +++ b/contrib/docker/shared/docker-entrypoint.d/02-horizon.sh @@ -1,6 +1,6 @@ #!/bin/bash +set -o errexit -o nounset -o pipefail -set -e source /lib.sh as_www_user php artisan horizon:publish From cf080dda099fcd1b30d00192aeef974f75494e76 Mon Sep 17 00:00:00 2001 From: Christian Winther Date: Thu, 4 Jan 2024 11:01:56 +0000 Subject: [PATCH 003/173] rename init files --- .../shared/docker-entrypoint.d/{00-storage.sh => 10-storage.sh} | 0 .../shared/docker-entrypoint.d/{01-cache.sh => 20-cache.sh} | 0 .../shared/docker-entrypoint.d/{02-horizon.sh => 30-horizon.sh} | 0 3 files changed, 0 insertions(+), 0 deletions(-) rename contrib/docker/shared/docker-entrypoint.d/{00-storage.sh => 10-storage.sh} (100%) rename contrib/docker/shared/docker-entrypoint.d/{01-cache.sh => 20-cache.sh} (100%) rename contrib/docker/shared/docker-entrypoint.d/{02-horizon.sh => 30-horizon.sh} (100%) diff --git a/contrib/docker/shared/docker-entrypoint.d/00-storage.sh b/contrib/docker/shared/docker-entrypoint.d/10-storage.sh similarity index 100% rename from contrib/docker/shared/docker-entrypoint.d/00-storage.sh rename to contrib/docker/shared/docker-entrypoint.d/10-storage.sh diff --git a/contrib/docker/shared/docker-entrypoint.d/01-cache.sh b/contrib/docker/shared/docker-entrypoint.d/20-cache.sh similarity index 100% rename from contrib/docker/shared/docker-entrypoint.d/01-cache.sh rename to contrib/docker/shared/docker-entrypoint.d/20-cache.sh diff --git a/contrib/docker/shared/docker-entrypoint.d/02-horizon.sh b/contrib/docker/shared/docker-entrypoint.d/30-horizon.sh similarity index 100% rename from contrib/docker/shared/docker-entrypoint.d/02-horizon.sh rename to contrib/docker/shared/docker-entrypoint.d/30-horizon.sh From f390c3c3e9a26d17fa3a8eaec2275fb88859049a Mon Sep 17 00:00:00 2001 From: Christian Winther Date: Thu, 4 Jan 2024 11:11:16 +0000 Subject: [PATCH 004/173] install all database extensions by default lifted from https://github.com/pixelfed/pixelfed/pull/4172 --- .editorconfig | 16 +++++++++++++++- contrib/docker/Dockerfile | 2 +- 2 files changed, 16 insertions(+), 2 deletions(-) diff --git a/.editorconfig b/.editorconfig index 0eda619e8..b6ffb5b1c 100644 --- a/.editorconfig +++ b/.editorconfig @@ -1,4 +1,4 @@ -root = true +root = false [*] indent_size = 4 @@ -11,3 +11,17 @@ insert_final_newline = true [{*.yml,*.yaml}] indent_style = space indent_size = 2 + +[*.sh] +indent_style = space +indent_size = 4 + +shell_variant = bash +binary_next_line = true +case-indent = true +switch_case_indent = true +space_redirects = true +keep_padding = true +function_next_line = true +simplify = true +space-redirects = true diff --git a/contrib/docker/Dockerfile b/contrib/docker/Dockerfile index 0a15bc6b5..7715dc7b3 100644 --- a/contrib/docker/Dockerfile +++ b/contrib/docker/Dockerfile @@ -11,7 +11,7 @@ ARG FOREGO_VERSION=0.17.2 ARG PECL_EXTENSIONS_EXTRA="" ARG PECL_EXTENSIONS="imagick redis" ARG PHP_BASE_TYPE="apache" -ARG PHP_DATABASE_EXTENSIONS="pdo_pgsql pdo_mysql" +ARG PHP_DATABASE_EXTENSIONS="pdo_pgsql pdo_mysql pdo_sqlite" ARG PHP_DEBIAN_RELEASE="bullseye" ARG PHP_EXTENSIONS_EXTRA="" ARG PHP_EXTENSIONS="intl bcmath zip pcntl exif curl gd" From 6244511cf8f48e4df78cd721ddefaf29c0372005 Mon Sep 17 00:00:00 2001 From: Christian Winther Date: Thu, 4 Jan 2024 11:20:22 +0000 Subject: [PATCH 005/173] don't hardcode UID/GID for runtime --- contrib/docker/Dockerfile | 18 ++++++++++++------ .../shared/docker-entrypoint.d/10-storage.sh | 6 +++--- .../{30-horizon.sh => 20-horizon.sh} | 2 +- .../{20-cache.sh => 30-cache.sh} | 10 +++++----- contrib/docker/shared/lib.sh | 4 ++-- 5 files changed, 23 insertions(+), 17 deletions(-) rename contrib/docker/shared/docker-entrypoint.d/{30-horizon.sh => 20-horizon.sh} (60%) rename contrib/docker/shared/docker-entrypoint.d/{20-cache.sh => 30-cache.sh} (58%) diff --git a/contrib/docker/Dockerfile b/contrib/docker/Dockerfile index 7715dc7b3..d35276db6 100644 --- a/contrib/docker/Dockerfile +++ b/contrib/docker/Dockerfile @@ -17,6 +17,8 @@ ARG PHP_EXTENSIONS_EXTRA="" ARG PHP_EXTENSIONS="intl bcmath zip pcntl exif curl gd" ARG PHP_VERSION="8.1" ARG APT_PACKAGES_EXTRA="" +ARG RUNTIME_UID=33 +ARG RUNTIME_GID=33 # GPG key for nginx apt repository ARG NGINX_GPGKEY=573BFD6B3D8FBC641079A6ABABF5BD827BD9BF62 @@ -56,6 +58,8 @@ FROM php:${PHP_VERSION}-${PHP_BASE_TYPE}-${PHP_DEBIAN_RELEASE} AS base ARG PHP_VERSION ARG PHP_DEBIAN_RELEASE ARG APT_PACKAGES_EXTRA +ARG RUNTIME_UID +ARG RUNTIME_GID ARG TARGETPLATFORM ARG BUILDKIT_SBOM_SCAN_STAGE=true @@ -67,7 +71,7 @@ SHELL ["/bin/bash", "-c"] RUN set -ex \ && mkdir -pv /var/www/ \ - && chown -R 33:33 /var/www + && chown -R ${RUNTIME_UID}:${RUNTIME_GID} /var/www WORKDIR /var/www/ @@ -193,6 +197,8 @@ FROM base AS composer-and-src ARG PHP_VERSION ARG PHP_DEBIAN_RELEASE +ARG RUNTIME_UID +ARG RUNTIME_GID ARG TARGETPLATFORM # Make sure composer cache is targeting our cache mount later @@ -207,11 +213,11 @@ ENV COMPOSER_NO_INTERACTION=1 # Copy composer from https://hub.docker.com/_/composer COPY --link --from=composer-image /usr/bin/composer /usr/bin/composer -#! Changing user to 33 -USER 33:33 +#! Changing user to runtime user +USER ${RUNTIME_UID}:${RUNTIME_GID} # Copy over only composer related files so docker layer cache isn't invalidated on PHP file changes -COPY --link --chown=33:33 composer.json composer.lock /var/www/ +COPY --link --chown=${RUNTIME_UID}:${RUNTIME_GID} composer.json composer.lock /var/www/ # Install composer dependencies # NOTE: we skip the autoloader generation here since we don't have all files avaliable (yet) @@ -220,7 +226,7 @@ RUN --mount=type=cache,id=pixelfed-composer-${PHP_VERSION}-${PHP_DEBIAN_RELEASE} && composer install --prefer-dist --no-autoloader --ignore-platform-reqs # Copy all other files over -COPY --link --chown=33:33 . /var/www/ +COPY --link --chown=${RUNTIME_UID}:${RUNTIME_GID} . /var/www/ # Generate optimized autoloader now that we have all files around RUN set -ex \ @@ -237,7 +243,7 @@ FROM base AS shared-runtime COPY --link --from=php-extensions /usr/local/lib/php/extensions /usr/local/lib/php/extensions COPY --link --from=php-extensions /usr/local/etc/php /usr/local/etc/php -COPY --link --from=composer-and-src --chown=33:33 /var/www /var/www +COPY --link --from=composer-and-src --chown=${RUNTIME_UID}:${RUNTIME_GID} /var/www /var/www COPY --link --from=forego-image /usr/local/bin/forego /usr/local/bin/forego COPY --link contrib/docker/php.production.ini "$PHP_INI_DIR/php.ini" diff --git a/contrib/docker/shared/docker-entrypoint.d/10-storage.sh b/contrib/docker/shared/docker-entrypoint.d/10-storage.sh index 860ec0425..8357688c1 100755 --- a/contrib/docker/shared/docker-entrypoint.d/10-storage.sh +++ b/contrib/docker/shared/docker-entrypoint.d/10-storage.sh @@ -4,10 +4,10 @@ set -o errexit -o nounset -o pipefail source /lib.sh entrypoint_log "==> Create the storage tree if needed" -as_www_user cp --recursive storage.skel/* storage/ +as_runtime_user cp --recursive storage.skel/* storage/ entrypoint_log "==> Ensure storage is linked" -as_www_user php artisan storage:link +as_runtime_user php artisan storage:link entrypoint_log "==> Ensure permissions are correct" -chown --recursive www-data:www-data storage/ bootstrap/ +chown --recursive ${RUNTIME_UID}:${RUNTIME_GID} storage/ bootstrap/ diff --git a/contrib/docker/shared/docker-entrypoint.d/30-horizon.sh b/contrib/docker/shared/docker-entrypoint.d/20-horizon.sh similarity index 60% rename from contrib/docker/shared/docker-entrypoint.d/30-horizon.sh rename to contrib/docker/shared/docker-entrypoint.d/20-horizon.sh index 04227cf40..9db54ba35 100755 --- a/contrib/docker/shared/docker-entrypoint.d/30-horizon.sh +++ b/contrib/docker/shared/docker-entrypoint.d/20-horizon.sh @@ -3,4 +3,4 @@ set -o errexit -o nounset -o pipefail source /lib.sh -as_www_user php artisan horizon:publish +as_runtime_user php artisan horizon:publish diff --git a/contrib/docker/shared/docker-entrypoint.d/20-cache.sh b/contrib/docker/shared/docker-entrypoint.d/30-cache.sh similarity index 58% rename from contrib/docker/shared/docker-entrypoint.d/20-cache.sh rename to contrib/docker/shared/docker-entrypoint.d/30-cache.sh index 06e440802..3eb87b6bb 100755 --- a/contrib/docker/shared/docker-entrypoint.d/20-cache.sh +++ b/contrib/docker/shared/docker-entrypoint.d/30-cache.sh @@ -3,11 +3,11 @@ set -o errexit -o nounset -o pipefail source /lib.sh -entrypoint_log "==> config:cache" -as_www_user php artisan config:cache - entrypoint_log "==> route:cache" -as_www_user php artisan route:cache +as_runtime_user php artisan route:cache entrypoint_log "==> view:cache" -as_www_user php artisan view:cache +as_runtime_user php artisan view:cache + +entrypoint_log "==> config:cache" +as_runtime_user php artisan config:cache diff --git a/contrib/docker/shared/lib.sh b/contrib/docker/shared/lib.sh index 3e7ef0f91..8253ed085 100644 --- a/contrib/docker/shared/lib.sh +++ b/contrib/docker/shared/lib.sh @@ -8,6 +8,6 @@ function entrypoint_log() { fi } -function as_www_user() { - su --preserve-environment www-data --shell /bin/bash --command "${*}" +function as_runtime_user() { + su --preserve-environment ${RUNTIME_UID} --shell /bin/bash --command "${*}" } From 0aee66810d61d4f35bcbf6ff1fc2d2f18221be9c Mon Sep 17 00:00:00 2001 From: Christian Winther Date: Thu, 4 Jan 2024 11:28:00 +0000 Subject: [PATCH 006/173] fix editorconfig --- .editorconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.editorconfig b/.editorconfig index b6ffb5b1c..0510b0d44 100644 --- a/.editorconfig +++ b/.editorconfig @@ -1,4 +1,4 @@ -root = false +root = true [*] indent_size = 4 From 7dcca09c65cc937563f4573d031768d11b94240a Mon Sep 17 00:00:00 2001 From: Christian Winther Date: Thu, 4 Jan 2024 13:07:01 +0000 Subject: [PATCH 007/173] a bit of refactoring --- .dockerignore | 1 - contrib/docker/Dockerfile | 160 +++++++---------------- contrib/docker/install/base.sh | 81 ++++++++++++ contrib/docker/install/php-extensions.sh | 32 +++++ 4 files changed, 162 insertions(+), 112 deletions(-) create mode 100755 contrib/docker/install/base.sh create mode 100755 contrib/docker/install/php-extensions.sh diff --git a/.dockerignore b/.dockerignore index 8e25f3cbc..bc5af5a21 100644 --- a/.dockerignore +++ b/.dockerignore @@ -1,5 +1,4 @@ data -contrib/docker/Dockerfile docker-compose*.yml .dockerignore .git diff --git a/contrib/docker/Dockerfile b/contrib/docker/Dockerfile index d35276db6..e432216ed 100644 --- a/contrib/docker/Dockerfile +++ b/contrib/docker/Dockerfile @@ -8,17 +8,25 @@ ARG COMPOSER_VERSION="2.6" ARG NGINX_VERSION=1.25.3 ARG FOREGO_VERSION=0.17.2 -ARG PECL_EXTENSIONS_EXTRA="" -ARG PECL_EXTENSIONS="imagick redis" -ARG PHP_BASE_TYPE="apache" -ARG PHP_DATABASE_EXTENSIONS="pdo_pgsql pdo_mysql pdo_sqlite" -ARG PHP_DEBIAN_RELEASE="bullseye" -ARG PHP_EXTENSIONS_EXTRA="" -ARG PHP_EXTENSIONS="intl bcmath zip pcntl exif curl gd" + +# PHP base configuration ARG PHP_VERSION="8.1" -ARG APT_PACKAGES_EXTRA="" -ARG RUNTIME_UID=33 -ARG RUNTIME_GID=33 +ARG PHP_BASE_TYPE="apache" +ARG PHP_DEBIAN_RELEASE="bullseye" +ARG RUNTIME_UID=33 # often called 'www-data' +ARG RUNTIME_GID=33 # often called 'www-data' + +# APT extra packages +ARG APT_PACKAGES_EXTRA= + +# Extensions installed via [pecl install] +ARG PHP_PECL_EXTENSIONS="" +ARG PHP_PECL_EXTENSIONS_EXTRA= + +# Extensions installed via [docker-php-ext-install] +ARG PHP_EXTENSIONS="intl bcmath zip pcntl exif curl gd" +ARG PHP_EXTENSIONS_EXTRA= +ARG PHP_EXTENSIONS_DATABASE="pdo_pgsql pdo_mysql pdo_sqlite" # GPG key for nginx apt repository ARG NGINX_GPGKEY=573BFD6B3D8FBC641079A6ABABF5BD827BD9BF62 @@ -75,87 +83,13 @@ RUN set -ex \ WORKDIR /var/www/ -# Install package dependencies +ENV APT_PACKAGES_EXTRA=${APT_PACKAGES_EXTRA} + +# Install and configure base layer +COPY contrib/docker/install/base.sh /install/base.sh RUN --mount=type=cache,id=pixelfed-apt-${PHP_VERSION}-${PHP_DEBIAN_RELEASE}-${TARGETPLATFORM},sharing=locked,target=/var/lib/apt \ --mount=type=cache,id=pixelfed-apt-cache-${PHP_VERSION}-${PHP_DEBIAN_RELEASE}-${TARGETPLATFORM},sharing=locked,target=/var/cache/apt \ -<<-SCRIPT - #!/bin/bash - set -ex -o errexit -o nounset -o pipefail - - # ensure we keep apt cache around in a Docker environment - rm -f /etc/apt/apt.conf.d/docker-clean - echo 'Binary::apt::APT::Keep-Downloaded-Packages "true";' > /etc/apt/apt.conf.d/keep-cache - - # Standard packages - standardPackages=( - apt-utils - ca-certificates - gettext-base - git - gnupg1 - gosu - libcurl4-openssl-dev - libzip-dev - locales - locales-all - nano - procps - unzip - zip - ) - - # Image Optimization - imageOptimization=( - gifsicle - jpegoptim - optipng - pngquant - ) - - # Image Processing - imageProcessing=( - libjpeg62-turbo-dev - libmagickwand-dev - libpng-dev - ) - - # Required for GD - gdDependencies=( - libwebp-dev - libwebp6 - libxpm-dev - libxpm4 - ) - - # Video Processing - videoProcessing=( - ffmpeg - ) - - # Database - databaseDependencies=( - libpq-dev - libsqlite3-dev - ) - - apt-get update - - apt-get upgrade -y - - apt-get install -y --no-install-recommends \ - ${standardPackages[*]} \ - ${imageOptimization[*]} \ - ${imageProcessing[*]} \ - ${gdDependencies[*]} \ - ${videoProcessing[*]} \ - ${databaseDependencies[*]} \ - ${APT_PACKAGES_EXTRA} -SCRIPT - -# update locales -RUN set -ex \ - && locale-gen \ - && update-locale + /install/base.sh ####################################################### # PHP: extensions @@ -163,37 +97,35 @@ RUN set -ex \ FROM base AS php-extensions -ARG PECL_EXTENSIONS -ARG PECL_EXTENSIONS_EXTRA -ARG PHP_DATABASE_EXTENSIONS +ARG PHP_EXTENSIONS_DATABASE ARG PHP_DEBIAN_RELEASE ARG PHP_EXTENSIONS ARG PHP_EXTENSIONS_EXTRA +ARG PHP_PECL_EXTENSIONS +ARG PHP_PECL_EXTENSIONS_EXTRA ARG PHP_VERSION ARG TARGETPLATFORM +ENV PHP_EXTENSIONS_DATABASE=${PHP_EXTENSIONS_DATABASE} +ENV PHP_DEBIAN_RELEASE=${PHP_DEBIAN_RELEASE} +ENV PHP_EXTENSIONS_EXTRA=${PHP_EXTENSIONS_EXTRA} +ENV PHP_EXTENSIONS=${PHP_EXTENSIONS} +ENV PHP_PECL_EXTENSIONS_EXTRA=${PHP_PECL_EXTENSIONS_EXTRA} +ENV PHP_PECL_EXTENSIONS=${PHP_PECL_EXTENSIONS} +ENV PHP_VERSION=${PHP_VERSION} +ENV TARGETPLATFORM=${TARGETPLATFORM} + +COPY contrib/docker/install/php-extensions.sh /install/php-extensions.sh RUN --mount=type=cache,id=pixelfed-php-${PHP_VERSION}-${PHP_DEBIAN_RELEASE}-${TARGETPLATFORM},sharing=locked,target=/usr/src/php/ \ - set -ex \ - # Grab the PHP source code so we can compile against it - && docker-php-source extract \ - # Install pecl extensions - && pecl install ${PECL_EXTENSIONS} ${PECL_EXTENSIONS_EXTRA} \ - # PHP GD extensions - && docker-php-ext-configure gd \ - --with-freetype \ - --with-jpeg \ - --with-webp \ - --with-xpm \ - # PHP extensions (dependencies) - && docker-php-ext-install -j$(nproc) ${PHP_EXTENSIONS} ${PHP_EXTENSIONS_EXTRA} ${PHP_DATABASE_EXTENSIONS} \ - # Enable all extensions - && docker-php-ext-enable ${PECL_EXTENSIONS} ${PECL_EXTENSIONS_EXTRA} ${PHP_EXTENSIONS} ${PHP_EXTENSIONS_EXTRA} ${PHP_DATABASE_EXTENSIONS} + --mount=type=cache,id=pixelfed-apt-${PHP_VERSION}-${PHP_DEBIAN_RELEASE}-${TARGETPLATFORM},sharing=locked,target=/var/lib/apt \ + --mount=type=cache,id=pixelfed-apt-cache-${PHP_VERSION}-${PHP_DEBIAN_RELEASE}-${TARGETPLATFORM},sharing=locked,target=/var/cache/apt \ + /install/php-extensions.sh ####################################################### # PHP: composer and source code ####################################################### -FROM base AS composer-and-src +FROM php-extensions AS composer-and-src ARG PHP_VERSION ARG PHP_DEBIAN_RELEASE @@ -241,6 +173,12 @@ USER root:root FROM base AS shared-runtime +ARG RUNTIME_UID +ARG RUNTIME_GID + +ENV RUNTIME_UID=${RUNTIME_UID} +ENV RUNTIME_GID=${RUNTIME_GID} + COPY --link --from=php-extensions /usr/local/lib/php/extensions /usr/local/lib/php/extensions COPY --link --from=php-extensions /usr/local/etc/php /usr/local/etc/php COPY --link --from=composer-and-src --chown=${RUNTIME_UID}:${RUNTIME_GID} /var/www /var/www @@ -252,9 +190,9 @@ RUN set -ex \ && cp --recursive --link --preserve=all storage storage.skel \ && rm -rf html && ln -s public html -COPY --link contrib/docker/docker-entrypoint.sh /docker-entrypoint.sh -COPY --link contrib/docker/shared/lib.sh /lib.sh -COPY --link contrib/docker/shared/docker-entrypoint.d /docker-entrypoint.d/ +COPY contrib/docker/docker-entrypoint.sh /docker-entrypoint.sh +COPY contrib/docker/shared/lib.sh /lib.sh +COPY contrib/docker/shared/docker-entrypoint.d /docker-entrypoint.d/ ENTRYPOINT ["/docker-entrypoint.sh"] diff --git a/contrib/docker/install/base.sh b/contrib/docker/install/base.sh new file mode 100755 index 000000000..b0e3d7b6d --- /dev/null +++ b/contrib/docker/install/base.sh @@ -0,0 +1,81 @@ +#!/bin/bash +set -ex -o errexit -o nounset -o pipefail + +# Ensure we keep apt cache around in a Docker environment +rm -f /etc/apt/apt.conf.d/docker-clean +echo 'Binary::apt::APT::Keep-Downloaded-Packages "true";' >/etc/apt/apt.conf.d/keep-cache + +# Don't install recommended packages by default +echo 'APT::Install-Recommends "false";' >>/etc/apt/apt.conf + +# Don't install suggested packages by default +echo 'APT::Install-Suggests "false";' >>/etc/apt/apt.conf + +# Standard packages +declare -ra standardPackages=( + apt-utils + ca-certificates + gettext-base + git + gnupg1 + gosu + libcurl4-openssl-dev + libzip-dev + locales + locales-all + nano + procps + unzip + zip + software-properties-common +) + +# Image Optimization +declare -ra imageOptimization=( + gifsicle + jpegoptim + optipng + pngquant +) + +# Image Processing +declare -ra imageProcessing=( + libjpeg62-turbo-dev + libmagickwand-dev + libpng-dev +) + +# Required for GD +declare -ra gdDependencies=( + libwebp-dev + libwebp6 + libxpm-dev + libxpm4 +) + +# Video Processing +declare -ra videoProcessing=( + ffmpeg +) + +# Database +declare -ra databaseDependencies=( + libpq-dev + libsqlite3-dev +) + +apt-get update + +apt-get upgrade -y + +apt-get install -y \ + ${standardPackages[*]} \ + ${imageOptimization[*]} \ + ${imageProcessing[*]} \ + ${gdDependencies[*]} \ + ${videoProcessing[*]} \ + ${databaseDependencies[*]} \ + ${APT_PACKAGES_EXTRA} + +locale-gen +update-locale diff --git a/contrib/docker/install/php-extensions.sh b/contrib/docker/install/php-extensions.sh new file mode 100755 index 000000000..1cb86fd77 --- /dev/null +++ b/contrib/docker/install/php-extensions.sh @@ -0,0 +1,32 @@ +#!/bin/bash +set -ex -o errexit -o nounset -o pipefail + +# Grab the PHP source code so we can compile against it +docker-php-source extract + +# PHP GD extensions +docker-php-ext-configure gd \ + --with-freetype \ + --with-jpeg \ + --with-webp \ + --with-xpm + +# Optional script folks can copy into their image to do any [docker-php-ext-configure] work before the [docker-php-ext-install] +# this can also overwirte the [gd] configure above by simply running it again +if [[ -f /install/php-extension-configure.sh ]]; then + if [ !-x "$f" ]; then + echo >&2 "ERROR: found /install/php-extension-configure.sh but its not executable - please [chmod +x] the file!" + exit 1 + fi + + /install/php-extension-configure.sh +fi + +# Install pecl extensions +pecl install ${PHP_PECL_EXTENSIONS} ${PHP_PECL_EXTENSIONS_EXTRA} + +# PHP extensions (dependencies) +docker-php-ext-install -j$(nproc) ${PHP_EXTENSIONS} ${PHP_EXTENSIONS_EXTRA} ${PHP_EXTENSIONS_DATABASE} + +# Enable all extensions +docker-php-ext-enable ${PHP_PECL_EXTENSIONS} ${PHP_PECL_EXTENSIONS_EXTRA} ${PHP_EXTENSIONS} ${PHP_EXTENSIONS_EXTRA} ${PHP_EXTENSIONS_DATABASE} From c369ef50a7e479a18f35e66933e300b2132a869f Mon Sep 17 00:00:00 2001 From: Christian Winther Date: Thu, 4 Jan 2024 16:08:01 +0000 Subject: [PATCH 008/173] more refactoring for templating --- contrib/docker/Dockerfile | 27 +++---- .../etc/apache2}/conf-available/remoteip.conf | 4 + contrib/docker/docker-entrypoint.sh | 45 ----------- .../docker/fpm/docker-entrypoint.d/.gitkeep | 0 .../docker-entrypoint.d => fpm/root}/.gitkeep | 0 contrib/docker/nginx/default-http.conf | 49 ------------ .../docker/nginx/docker-entrypoint.d/.gitkeep | 0 .../nginx/root/etc/nginx/conf.d/default.conf | 49 ++++++++++++ .../shared/docker-entrypoint.d/10-storage.sh | 13 ---- .../shared/docker-entrypoint.d/30-cache.sh | 13 ---- contrib/docker/shared/lib.sh | 13 ---- .../docker/entrypoint.d/04-defaults.envsh | 26 +++++++ .../root/docker/entrypoint.d/05-templating.sh | 40 ++++++++++ .../root/docker/entrypoint.d/10-storage.sh | 13 ++++ .../docker/entrypoint.d}/20-horizon.sh | 4 +- .../root/docker/entrypoint.d/30-cache.sh | 13 ++++ .../docker/shared/root/docker/entrypoint.sh | 50 +++++++++++++ contrib/docker/shared/root/docker/helpers.sh | 75 +++++++++++++++++++ .../{ => shared/root/docker}/install/base.sh | 0 .../root/docker}/install/php-extensions.sh | 0 .../templates/usr/local/etc/php/php.ini} | 6 +- 21 files changed, 286 insertions(+), 154 deletions(-) rename contrib/docker/apache/{ => root/etc/apache2}/conf-available/remoteip.conf (56%) delete mode 100755 contrib/docker/docker-entrypoint.sh delete mode 100644 contrib/docker/fpm/docker-entrypoint.d/.gitkeep rename contrib/docker/{apache/docker-entrypoint.d => fpm/root}/.gitkeep (100%) delete mode 100644 contrib/docker/nginx/default-http.conf delete mode 100644 contrib/docker/nginx/docker-entrypoint.d/.gitkeep create mode 100644 contrib/docker/nginx/root/etc/nginx/conf.d/default.conf delete mode 100755 contrib/docker/shared/docker-entrypoint.d/10-storage.sh delete mode 100755 contrib/docker/shared/docker-entrypoint.d/30-cache.sh delete mode 100644 contrib/docker/shared/lib.sh create mode 100755 contrib/docker/shared/root/docker/entrypoint.d/04-defaults.envsh create mode 100755 contrib/docker/shared/root/docker/entrypoint.d/05-templating.sh create mode 100755 contrib/docker/shared/root/docker/entrypoint.d/10-storage.sh rename contrib/docker/shared/{docker-entrypoint.d => root/docker/entrypoint.d}/20-horizon.sh (52%) create mode 100755 contrib/docker/shared/root/docker/entrypoint.d/30-cache.sh create mode 100755 contrib/docker/shared/root/docker/entrypoint.sh create mode 100644 contrib/docker/shared/root/docker/helpers.sh rename contrib/docker/{ => shared/root/docker}/install/base.sh (100%) rename contrib/docker/{ => shared/root/docker}/install/php-extensions.sh (100%) rename contrib/docker/{php.production.ini => shared/root/docker/templates/usr/local/etc/php/php.ini} (99%) diff --git a/contrib/docker/Dockerfile b/contrib/docker/Dockerfile index e432216ed..d3cbca764 100644 --- a/contrib/docker/Dockerfile +++ b/contrib/docker/Dockerfile @@ -86,10 +86,10 @@ WORKDIR /var/www/ ENV APT_PACKAGES_EXTRA=${APT_PACKAGES_EXTRA} # Install and configure base layer -COPY contrib/docker/install/base.sh /install/base.sh +COPY contrib/docker/shared/root/docker/install/base.sh /docker/install/base.sh RUN --mount=type=cache,id=pixelfed-apt-${PHP_VERSION}-${PHP_DEBIAN_RELEASE}-${TARGETPLATFORM},sharing=locked,target=/var/lib/apt \ --mount=type=cache,id=pixelfed-apt-cache-${PHP_VERSION}-${PHP_DEBIAN_RELEASE}-${TARGETPLATFORM},sharing=locked,target=/var/cache/apt \ - /install/base.sh + /docker/install/base.sh ####################################################### # PHP: extensions @@ -115,11 +115,11 @@ ENV PHP_PECL_EXTENSIONS=${PHP_PECL_EXTENSIONS} ENV PHP_VERSION=${PHP_VERSION} ENV TARGETPLATFORM=${TARGETPLATFORM} -COPY contrib/docker/install/php-extensions.sh /install/php-extensions.sh +COPY contrib/docker/shared/root/docker/install/php-extensions.sh /docker/install/php-extensions.sh RUN --mount=type=cache,id=pixelfed-php-${PHP_VERSION}-${PHP_DEBIAN_RELEASE}-${TARGETPLATFORM},sharing=locked,target=/usr/src/php/ \ --mount=type=cache,id=pixelfed-apt-${PHP_VERSION}-${PHP_DEBIAN_RELEASE}-${TARGETPLATFORM},sharing=locked,target=/var/lib/apt \ --mount=type=cache,id=pixelfed-apt-cache-${PHP_VERSION}-${PHP_DEBIAN_RELEASE}-${TARGETPLATFORM},sharing=locked,target=/var/cache/apt \ - /install/php-extensions.sh + /docker/install/php-extensions.sh ####################################################### # PHP: composer and source code @@ -183,18 +183,15 @@ COPY --link --from=php-extensions /usr/local/lib/php/extensions /usr/local/lib/p COPY --link --from=php-extensions /usr/local/etc/php /usr/local/etc/php COPY --link --from=composer-and-src --chown=${RUNTIME_UID}:${RUNTIME_GID} /var/www /var/www COPY --link --from=forego-image /usr/local/bin/forego /usr/local/bin/forego -COPY --link contrib/docker/php.production.ini "$PHP_INI_DIR/php.ini" # for detail why storage is copied this way, pls refer to https://github.com/pixelfed/pixelfed/pull/2137#discussion_r434468862 RUN set -ex \ && cp --recursive --link --preserve=all storage storage.skel \ && rm -rf html && ln -s public html -COPY contrib/docker/docker-entrypoint.sh /docker-entrypoint.sh -COPY contrib/docker/shared/lib.sh /lib.sh -COPY contrib/docker/shared/docker-entrypoint.d /docker-entrypoint.d/ +COPY contrib/docker/shared/root / -ENTRYPOINT ["/docker-entrypoint.sh"] +ENTRYPOINT ["/docker/entrypoint.sh"] VOLUME /var/www/storage /var/www/bootstrap @@ -204,8 +201,7 @@ VOLUME /var/www/storage /var/www/bootstrap FROM shared-runtime AS apache-runtime -COPY --link contrib/docker/apache/conf-available/remoteip.conf /etc/apache2/conf-available/remoteip.conf -COPY --link contrib/docker/apache/docker-entrypoint.d /docker-entrypoint.d/ +COPY contrib/docker/apache/root / RUN set -ex \ && a2enmod rewrite remoteip proxy proxy_http \ @@ -221,7 +217,7 @@ EXPOSE 80 FROM shared-runtime AS fpm-runtime -COPY --link contrib/docker/fpm/docker-entrypoint.d /docker-entrypoint.d/ +COPY contrib/docker/fpm/root / CMD ["php-fpm"] @@ -252,10 +248,9 @@ RUN --mount=type=cache,id=pixelfed-apt-lists-${PHP_VERSION}-${PHP_DEBIAN_RELEASE nginx=${NGINX_VERSION}* # copy docker entrypoints from the *real* nginx image directly -COPY --link --from=nginx-image /docker-entrypoint.d /docker-entrypoint.d/ -COPY --link contrib/docker/nginx/docker-entrypoint.d /docker-entrypoint.d/ -COPY --link contrib/docker/nginx/default-http.conf /etc/nginx/templates/default.conf.template -COPY --link contrib/docker/nginx/Procfile . +COPY --link --from=nginx-image /docker-entrypoint.d /docker/entrypoint.d/ +COPY contrib/docker/nginx/root / +COPY contrib/docker/nginx/Procfile . EXPOSE 80 diff --git a/contrib/docker/apache/conf-available/remoteip.conf b/contrib/docker/apache/root/etc/apache2/conf-available/remoteip.conf similarity index 56% rename from contrib/docker/apache/conf-available/remoteip.conf rename to contrib/docker/apache/root/etc/apache2/conf-available/remoteip.conf index 1632f8e43..516da9f5d 100644 --- a/contrib/docker/apache/conf-available/remoteip.conf +++ b/contrib/docker/apache/root/etc/apache2/conf-available/remoteip.conf @@ -1,4 +1,8 @@ RemoteIPHeader X-Real-IP + +# All private IPs as outlined in rfc1918 +# +# See: https://datatracker.ietf.org/doc/html/rfc1918 RemoteIPTrustedProxy 10.0.0.0/8 RemoteIPTrustedProxy 172.16.0.0/12 RemoteIPTrustedProxy 192.168.0.0/16 diff --git a/contrib/docker/docker-entrypoint.sh b/contrib/docker/docker-entrypoint.sh deleted file mode 100755 index 706c38317..000000000 --- a/contrib/docker/docker-entrypoint.sh +++ /dev/null @@ -1,45 +0,0 @@ -#!/bin/bash -# vim:sw=4:ts=4:et - -set -e - -source /lib.sh - -mkdir -p /docker-entrypoint.d/ - -if /usr/bin/find "/docker-entrypoint.d/" -mindepth 1 -maxdepth 1 -type f -print -quit 2>/dev/null | read v; then - entrypoint_log "/docker-entrypoint.d/ is not empty, will attempt to perform configuration" - - entrypoint_log "looking for shell scripts in /docker-entrypoint.d/" - find "/docker-entrypoint.d/" -follow -type f -print | sort -V | while read -r f; do - case "$f" in - *.envsh) - if [ -x "$f" ]; then - entrypoint_log "Sourcing $f"; - . "$f" - else - # warn on shell scripts without exec bit - entrypoint_log "Ignoring $f, not executable"; - fi - ;; - - *.sh) - if [ -x "$f" ]; then - entrypoint_log "Launching $f"; - "$f" - else - # warn on shell scripts without exec bit - entrypoint_log "Ignoring $f, not executable"; - fi - ;; - - *) entrypoint_log "Ignoring $f";; - esac - done - - entrypoint_log "Configuration complete; ready for start up" -else - entrypoint_log "No files found in /docker-entrypoint.d/, skipping configuration" -fi - -exec "$@" diff --git a/contrib/docker/fpm/docker-entrypoint.d/.gitkeep b/contrib/docker/fpm/docker-entrypoint.d/.gitkeep deleted file mode 100644 index e69de29bb..000000000 diff --git a/contrib/docker/apache/docker-entrypoint.d/.gitkeep b/contrib/docker/fpm/root/.gitkeep similarity index 100% rename from contrib/docker/apache/docker-entrypoint.d/.gitkeep rename to contrib/docker/fpm/root/.gitkeep diff --git a/contrib/docker/nginx/default-http.conf b/contrib/docker/nginx/default-http.conf deleted file mode 100644 index 8182dba7f..000000000 --- a/contrib/docker/nginx/default-http.conf +++ /dev/null @@ -1,49 +0,0 @@ -server { - listen 80 default_server; - - server_name ${APP_DOMAIN}; - root /var/www/public; - - add_header X-Frame-Options "SAMEORIGIN"; - add_header X-XSS-Protection "1; mode=block"; - add_header X-Content-Type-Options "nosniff"; - - access_log /dev/stdout; - error_log /dev/stderr warn; - - index index.html index.htm index.php; - - charset utf-8; - client_max_body_size 100M; - - location / { - try_files $uri $uri/ /index.php?$query_string; - } - - location = /favicon.ico { - access_log off; - log_not_found off; - } - - location = /robots.txt { - access_log off; - log_not_found off; - } - - error_page 404 /index.php; - - location ~ \.php$ { - fastcgi_split_path_info ^(.+\.php)(/.+)$; - - fastcgi_pass 127.0.0.1:9000; - fastcgi_index index.php; - - include fastcgi_params; - - fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; - } - - location ~ /\.(?!well-known).* { - deny all; - } -} diff --git a/contrib/docker/nginx/docker-entrypoint.d/.gitkeep b/contrib/docker/nginx/docker-entrypoint.d/.gitkeep deleted file mode 100644 index e69de29bb..000000000 diff --git a/contrib/docker/nginx/root/etc/nginx/conf.d/default.conf b/contrib/docker/nginx/root/etc/nginx/conf.d/default.conf new file mode 100644 index 000000000..af5a66b77 --- /dev/null +++ b/contrib/docker/nginx/root/etc/nginx/conf.d/default.conf @@ -0,0 +1,49 @@ +server { + listen 80 default_server; + + server_name ${APP_DOMAIN}; + root /var/www/public; + + add_header X-Frame-Options "SAMEORIGIN"; + add_header X-XSS-Protection "1; mode=block"; + add_header X-Content-Type-Options "nosniff"; + + access_log /dev/stdout; + error_log /dev/stderr warn; + + index index.html index.htm index.php; + + charset utf-8; + client_max_body_size ${POST_MAX_SIZE}; + + location / { + try_files $uri $uri/ /index.php?$query_string; + } + + location = /favicon.ico { + access_log off; + log_not_found off; + } + + location = /robots.txt { + access_log off; + log_not_found off; + } + + error_page 404 /index.php; + + location ~ \.php$ { + fastcgi_split_path_info ^(.+\.php)(/.+)$; + + fastcgi_pass 127.0.0.1:9000; + fastcgi_index index.php; + + include fastcgi_params; + + fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; + } + + location ~ /\.(?!well-known).* { + deny all; + } +} diff --git a/contrib/docker/shared/docker-entrypoint.d/10-storage.sh b/contrib/docker/shared/docker-entrypoint.d/10-storage.sh deleted file mode 100755 index 8357688c1..000000000 --- a/contrib/docker/shared/docker-entrypoint.d/10-storage.sh +++ /dev/null @@ -1,13 +0,0 @@ -#!/bin/bash -set -o errexit -o nounset -o pipefail - -source /lib.sh - -entrypoint_log "==> Create the storage tree if needed" -as_runtime_user cp --recursive storage.skel/* storage/ - -entrypoint_log "==> Ensure storage is linked" -as_runtime_user php artisan storage:link - -entrypoint_log "==> Ensure permissions are correct" -chown --recursive ${RUNTIME_UID}:${RUNTIME_GID} storage/ bootstrap/ diff --git a/contrib/docker/shared/docker-entrypoint.d/30-cache.sh b/contrib/docker/shared/docker-entrypoint.d/30-cache.sh deleted file mode 100755 index 3eb87b6bb..000000000 --- a/contrib/docker/shared/docker-entrypoint.d/30-cache.sh +++ /dev/null @@ -1,13 +0,0 @@ -#!/bin/bash -set -o errexit -o nounset -o pipefail - -source /lib.sh - -entrypoint_log "==> route:cache" -as_runtime_user php artisan route:cache - -entrypoint_log "==> view:cache" -as_runtime_user php artisan view:cache - -entrypoint_log "==> config:cache" -as_runtime_user php artisan config:cache diff --git a/contrib/docker/shared/lib.sh b/contrib/docker/shared/lib.sh deleted file mode 100644 index 8253ed085..000000000 --- a/contrib/docker/shared/lib.sh +++ /dev/null @@ -1,13 +0,0 @@ -#!/bin/bash - -set -e - -function entrypoint_log() { - if [ -z "${ENTRYPOINT_QUIET_LOGS:-}" ]; then - echo "/docker-entrypoint.sh: $@" - fi -} - -function as_runtime_user() { - su --preserve-environment ${RUNTIME_UID} --shell /bin/bash --command "${*}" -} diff --git a/contrib/docker/shared/root/docker/entrypoint.d/04-defaults.envsh b/contrib/docker/shared/root/docker/entrypoint.d/04-defaults.envsh new file mode 100755 index 000000000..2244be9b8 --- /dev/null +++ b/contrib/docker/shared/root/docker/entrypoint.d/04-defaults.envsh @@ -0,0 +1,26 @@ +#!/bin/bash + +# NOTE: +# +# this file is *sourced* not run by the entrypoint runner +# so any environment values set here will be accessible to all sub-processes +# and future entrypoint.d scripts +# + +set_identity "${BASH_SOURCE[0]}" + +load-config-files + +: ${POST_MAX_SIZE_BUFFER:=1M} +log "POST_MAX_SIZE_BUFFER is set to [${POST_MAX_SIZE_BUFFER}]" +buffer=$(numfmt --invalid=fail --from=auto --to=none --to-unit=K "${POST_MAX_SIZE_BUFFER}") +log "POST_MAX_SIZE_BUFFER converted to KB is [${buffer}]" + +log "POST_MAX_SIZE will be calculated by [({MAX_PHOTO_SIZE} * {MAX_ALBUM_LENGTH}) + {POST_MAX_SIZE_BUFFER}]" +log " MAX_PHOTO_SIZE=${MAX_PHOTO_SIZE}" +log " MAX_ALBUM_LENGTH=${MAX_ALBUM_LENGTH}" +log " POST_MAX_SIZE_BUFFER=${buffer}" +: ${POST_MAX_SIZE:=$(numfmt --invalid=fail --from=auto --from-unit=K --to=si $(((${MAX_PHOTO_SIZE} * ${MAX_ALBUM_LENGTH}) + ${buffer})))} +log "POST_MAX_SIZE was calculated to [${POST_MAX_SIZE}]" + +export POST_MAX_SIZE diff --git a/contrib/docker/shared/root/docker/entrypoint.d/05-templating.sh b/contrib/docker/shared/root/docker/entrypoint.d/05-templating.sh new file mode 100755 index 000000000..4b9f9014a --- /dev/null +++ b/contrib/docker/shared/root/docker/entrypoint.d/05-templating.sh @@ -0,0 +1,40 @@ +#!/bin/bash +source /docker/helpers.sh + +set_identity "$0" + +auto_envsubst() { + local template_dir="${ENVSUBST_TEMPLATE_DIR:-/docker/templates}" + local output_dir="${ENVSUBST_OUTPUT_DIR:-}" + local filter="${ENVSUBST_FILTER:-}" + local template defined_envs relative_path output_path output_dir subdir + + # load all dot-env files + load-config-files + + # export all dot-env variables so they are available in templating + export ${seen_dot_env_variables[@]} + + defined_envs=$(printf '${%s} ' $(awk "END { for (name in ENVIRON) { print ( name ~ /${filter}/ ) ? name : \"\" } }" "$output_path" + done +} + +auto_envsubst + +exit 0 diff --git a/contrib/docker/shared/root/docker/entrypoint.d/10-storage.sh b/contrib/docker/shared/root/docker/entrypoint.d/10-storage.sh new file mode 100755 index 000000000..c814a3df4 --- /dev/null +++ b/contrib/docker/shared/root/docker/entrypoint.d/10-storage.sh @@ -0,0 +1,13 @@ +#!/bin/bash +source /docker/helpers.sh + +set_identity "$0" + +log "Create the storage tree if needed" +as_runtime_user cp --recursive storage.skel/* storage/ + +log "Ensure storage is linked" +as_runtime_user php artisan storage:link + +log "Ensure permissions are correct" +chown --recursive ${RUNTIME_UID}:${RUNTIME_GID} storage/ bootstrap/ diff --git a/contrib/docker/shared/docker-entrypoint.d/20-horizon.sh b/contrib/docker/shared/root/docker/entrypoint.d/20-horizon.sh similarity index 52% rename from contrib/docker/shared/docker-entrypoint.d/20-horizon.sh rename to contrib/docker/shared/root/docker/entrypoint.d/20-horizon.sh index 9db54ba35..7c1d8fdc6 100755 --- a/contrib/docker/shared/docker-entrypoint.d/20-horizon.sh +++ b/contrib/docker/shared/root/docker/entrypoint.d/20-horizon.sh @@ -1,6 +1,6 @@ #!/bin/bash -set -o errexit -o nounset -o pipefail +source /docker/helpers.sh -source /lib.sh +set_identity "$0" as_runtime_user php artisan horizon:publish diff --git a/contrib/docker/shared/root/docker/entrypoint.d/30-cache.sh b/contrib/docker/shared/root/docker/entrypoint.d/30-cache.sh new file mode 100755 index 000000000..e561daef9 --- /dev/null +++ b/contrib/docker/shared/root/docker/entrypoint.d/30-cache.sh @@ -0,0 +1,13 @@ +#!/bin/bash +source /docker/helpers.sh + +set_identity "$0" + +log "==> route:cache" +as_runtime_user php artisan route:cache + +log "==> view:cache" +as_runtime_user php artisan view:cache + +log "==> config:cache" +as_runtime_user php artisan config:cache diff --git a/contrib/docker/shared/root/docker/entrypoint.sh b/contrib/docker/shared/root/docker/entrypoint.sh new file mode 100755 index 000000000..0964980bc --- /dev/null +++ b/contrib/docker/shared/root/docker/entrypoint.sh @@ -0,0 +1,50 @@ +#!/bin/bash +set -e -o errexit -o nounset -o pipefail + +[[ -n ${ENTRYPOINT_DEBUG:-} ]] && set -x + +declare -g ME="$0" +declare -gr ENTRYPOINT_ROOT=/docker/entrypoint.d/ + +source /docker/helpers.sh + +# ensure the entrypoint folder exists +mkdir -p "${ENTRYPOINT_ROOT}" + +if /usr/bin/find "${ENTRYPOINT_ROOT}" -mindepth 1 -maxdepth 1 -type f -print -quit 2>/dev/null | read v; then + log "looking for shell scripts in /docker/entrypoint.d/" + find "${ENTRYPOINT_ROOT}" -follow -type f -print | sort -V | while read -r f; do + case "$f" in + *.envsh) + if [ -x "$f" ]; then + log "Sourcing $f" + source "$f" + resetore_identity + else + # warn on shell scripts without exec bit + log_warning "Ignoring $f, not executable" + fi + ;; + + *.sh) + if [ -x "$f" ]; then + log "Launching $f" + "$f" + else + # warn on shell scripts without exec bit + log_warning "Ignoring $f, not executable" + fi + ;; + + *) + log_warning "Ignoring $f" + ;; + esac + done + + log "Configuration complete; ready for start up" +else + log_warning "No files found in ${ENTRYPOINT_ROOT}, skipping configuration" +fi + +exec "$@" diff --git a/contrib/docker/shared/root/docker/helpers.sh b/contrib/docker/shared/root/docker/helpers.sh new file mode 100644 index 000000000..fc8691324 --- /dev/null +++ b/contrib/docker/shared/root/docker/helpers.sh @@ -0,0 +1,75 @@ +#!/bin/bash +set -e -o errexit -o nounset -o pipefail + +declare -g error_message_color="\033[1;31m" +declare -g warn_message_color="\033[1;34m" +declare -g color_clear="\033[1;0m" +declare -g log_prefix= +declare -g old_log_prefix= +declare -ra dot_env_files=( + /var/www/.env.docker + /var/www/.env +) +declare -a seen_dot_env_variables=() + +function set_identity() { + old_log_prefix="${log_prefix}" + log_prefix="ENTRYPOINT - [${1}] - " +} + +function resetore_identity() { + log_prefix="${old_log_prefix}" +} + +function as_runtime_user() { + su --preserve-environment $(id -un ${RUNTIME_UID}) --shell /bin/bash --command "${*}" +} + +# @description Display the given error message with its line number on stderr and exit with error. +# @arg $message string A error message. +function log_error() { + echo -e "${error_message_color}${log_prefix}ERROR - ${1}${color_clear}" >/dev/stderr +} + +# @description Display the given error message with its line number on stderr and exit with error. +# @arg $message string A error message. +# @exitcode 1 +function log_error_and_exit() { + log_error "$1" + + exit 1 +} + +# @description Display the given warning message with its line number on stderr. +# @arg $message string A warning message. +function log_warning() { + echo -e "${warn_message_color}${log_prefix}WARNING - ${1}${color_clear}" >/dev/stderr +} + +function log() { + if [ -z "${ENTRYPOINT_QUIET_LOGS:-}" ]; then + echo "${log_prefix}$@" + fi +} + +function load-config-files() { + # Associative array (aka map/disctrionary) holding the unique keys found in dot-env files + local -A _tmp_dot_env_keys + + for f in "${dot_env_files[@]}"; do + if [ ! -e "$f" ]; then + log_warning "Could not source file [${f}]: does not exists" + continue + fi + + log "Sourcing ${f}" + source "${f}" + + # find all keys in the dot-env file and store them in our temp associative array + for k in "$(grep -v '^#' "${f}" | sed -E 's/(.*)=.*/\1/' | xargs)"; do + _tmp_dot_env_keys[$k]=1 + done + done + + seen_dot_env_variables=(${!_tmp_dot_env_keys[@]}) +} diff --git a/contrib/docker/install/base.sh b/contrib/docker/shared/root/docker/install/base.sh similarity index 100% rename from contrib/docker/install/base.sh rename to contrib/docker/shared/root/docker/install/base.sh diff --git a/contrib/docker/install/php-extensions.sh b/contrib/docker/shared/root/docker/install/php-extensions.sh similarity index 100% rename from contrib/docker/install/php-extensions.sh rename to contrib/docker/shared/root/docker/install/php-extensions.sh diff --git a/contrib/docker/php.production.ini b/contrib/docker/shared/root/docker/templates/usr/local/etc/php/php.ini similarity index 99% rename from contrib/docker/php.production.ini rename to contrib/docker/shared/root/docker/templates/usr/local/etc/php/php.ini index 2a1df3988..1a9f6b598 100644 --- a/contrib/docker/php.production.ini +++ b/contrib/docker/shared/root/docker/templates/usr/local/etc/php/php.ini @@ -679,7 +679,7 @@ auto_globals_jit = On ; Its value may be 0 to disable the limit. It is ignored if POST data reading ; is disabled through enable_post_data_reading. ; http://php.net/post-max-size -post_max_size = 95M +post_max_size = ${POST_MAX_SIZE} ; Automatically add files before PHP document. ; http://php.net/auto-prepend-file @@ -831,10 +831,10 @@ file_uploads = On ; Maximum allowed size for uploaded files. ; http://php.net/upload-max-filesize -upload_max_filesize = 95M +upload_max_filesize = ${POST_MAX_SIZE} ; Maximum number of files that can be uploaded via a single request -max_file_uploads = 20 +max_file_uploads = ${MAX_ALBUM_LENGTH} ;;;;;;;;;;;;;;;;;; ; Fopen wrappers ; From e05575283a1fa299b126d83cb189b6291b213354 Mon Sep 17 00:00:00 2001 From: Christian Winther Date: Thu, 4 Jan 2024 16:12:18 +0000 Subject: [PATCH 009/173] update docs --- contrib/docker/README.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/contrib/docker/README.md b/contrib/docker/README.md index 441477fe4..9dd46d06e 100644 --- a/contrib/docker/README.md +++ b/contrib/docker/README.md @@ -116,11 +116,11 @@ Any valid Docker Hub PHP version is acceptable here, as long as it's [published **Default value**: `8.1` -### `PECL_EXTENSIONS` +### `PHP_PECL_EXTENSIONS` PECL extensions to install via `pecl install` -Use [PECL_EXTENSIONS_EXTRA](#pecl_extensions_extra) if you want to add *additional* extenstions. +Use [PHP_PECL_EXTENSIONS_EXTRA](#php_pecl_extensions_extra) if you want to add *additional* extenstions. Only change this setting if you want to change the baseline extensions. @@ -128,7 +128,7 @@ See the [`PECL extensions` documentation on Docker Hub](https://hub.docker.com/_ **Default value**: `imagick redis` -### `PECL_EXTENSIONS_EXTRA` +### `PHP_PECL_EXTENSIONS_EXTRA` Extra PECL extensions (separated by space) to install via `pecl install` @@ -154,13 +154,13 @@ See the [`How to install more PHP extensions` documentation on Docker Hub](https **Default value**: `""` -### `PHP_DATABASE_EXTENSIONS` +### `PHP_EXTENSIONS_DATABASE` PHP database extensions to install. By default we install both `pgsql` and `mysql` since it's more convinient (and adds very little build time! but can be overwritten here if required. -**Default value**: `pdo_pgsql pdo_mysql` +**Default value**: `pdo_pgsql pdo_mysql pdo_sqlite` ### `COMPOSER_VERSION` From a08a5e7cde5682c8afd7eac727c2398447038902 Mon Sep 17 00:00:00 2001 From: Christian Winther Date: Thu, 4 Jan 2024 20:55:04 +0000 Subject: [PATCH 010/173] more docs and rework --- contrib/docker/Dockerfile | 41 +++++++- contrib/docker/README.md | 66 +++++++++++++ .../templates}/conf.d/default.conf | 4 +- .../root/docker/entrypoint.d/05-templating.sh | 53 ++++++----- .../root/docker/entrypoint.d/10-storage.sh | 3 - .../root/docker/entrypoint.d/30-cache.sh | 5 - .../docker/shared/root/docker/entrypoint.sh | 93 ++++++++++++------- contrib/docker/shared/root/docker/helpers.sh | 35 ++++++- .../docker/shared/root/docker/install/base.sh | 7 +- .../templates/usr/local/etc/php/php.ini | 6 +- 10 files changed, 226 insertions(+), 87 deletions(-) rename contrib/docker/nginx/root/{etc/nginx => docker/templates}/conf.d/default.conf (90%) diff --git a/contrib/docker/Dockerfile b/contrib/docker/Dockerfile index d3cbca764..471ac5820 100644 --- a/contrib/docker/Dockerfile +++ b/contrib/docker/Dockerfile @@ -5,14 +5,29 @@ # Configuration ####################################################### +# See: https://github.com/composer/composer/releases ARG COMPOSER_VERSION="2.6" + +# See: https://nginx.org/ ARG NGINX_VERSION=1.25.3 + +# See: https://github.com/ddollar/forego ARG FOREGO_VERSION=0.17.2 +# See: https://github.com/hairyhenderson/gomplate +ARG GOMPLATE_VERSION=v3.11.6 + +### # PHP base configuration +### + +# See: https://hub.docker.com/_/php/tags ARG PHP_VERSION="8.1" + +# See: https://github.com/docker-library/docs/blob/master/php/README.md#image-variants ARG PHP_BASE_TYPE="apache" ARG PHP_DEBIAN_RELEASE="bullseye" + ARG RUNTIME_UID=33 # often called 'www-data' ARG RUNTIME_GID=33 # often called 'www-data' @@ -57,17 +72,31 @@ FROM nginx:${NGINX_VERSION} AS nginx-image # See: https://github.com/nginx-proxy/forego FROM nginxproxy/forego:${FOREGO_VERSION}-debian AS forego-image +# gomplate-image grabs the gomplate binary from GitHub releases +# +# It's in its own layer so it can be fetched in parallel with other build steps +FROM php:${PHP_VERSION}-${PHP_BASE_TYPE}-${PHP_DEBIAN_RELEASE} AS gomplate-image + +ARG BUILDARCH +ARG BUILDOS +ARG GOMPLATE_VERSION + +RUN set -ex \ + && curl --silent --show-error --location --output /usr/local/bin/gomplate https://github.com/hairyhenderson/gomplate/releases/download/${GOMPLATE_VERSION}/gomplate_${BUILDOS}-${BUILDARCH} \ + && chmod +x /usr/local/bin/gomplate \ + && /usr/local/bin/gomplate --version + ####################################################### # Base image ####################################################### FROM php:${PHP_VERSION}-${PHP_BASE_TYPE}-${PHP_DEBIAN_RELEASE} AS base -ARG PHP_VERSION -ARG PHP_DEBIAN_RELEASE ARG APT_PACKAGES_EXTRA -ARG RUNTIME_UID +ARG PHP_DEBIAN_RELEASE +ARG PHP_VERSION ARG RUNTIME_GID +ARG RUNTIME_UID ARG TARGETPLATFORM ARG BUILDKIT_SBOM_SCAN_STAGE=true @@ -173,8 +202,11 @@ USER root:root FROM base AS shared-runtime -ARG RUNTIME_UID +ARG BUILDARCH +ARG BUILDOS +ARG GOMPLATE_VERSION ARG RUNTIME_GID +ARG RUNTIME_UID ENV RUNTIME_UID=${RUNTIME_UID} ENV RUNTIME_GID=${RUNTIME_GID} @@ -183,6 +215,7 @@ COPY --link --from=php-extensions /usr/local/lib/php/extensions /usr/local/lib/p COPY --link --from=php-extensions /usr/local/etc/php /usr/local/etc/php COPY --link --from=composer-and-src --chown=${RUNTIME_UID}:${RUNTIME_GID} /var/www /var/www COPY --link --from=forego-image /usr/local/bin/forego /usr/local/bin/forego +COPY --link --from=gomplate-image /usr/local/bin/gomplate /usr/local/bin/gomplate # for detail why storage is copied this way, pls refer to https://github.com/pixelfed/pixelfed/pull/2137#discussion_r434468862 RUN set -ex \ diff --git a/contrib/docker/README.md b/contrib/docker/README.md index 9dd46d06e..a0b07f5fa 100644 --- a/contrib/docker/README.md +++ b/contrib/docker/README.md @@ -93,6 +93,72 @@ services: PHP_BASE_TYPE: fpm ``` +## Customizing your `Dockerfile` + +### Running commands on container start + +#### Description + +When a Pixelfed container starts up, the [`ENTRYPOINT`](https://docs.docker.com/engine/reference/builder/#entrypoint) script will + +1. Search the `/docker/entrypoint.d/` directory for files and for each file (in lexical order). +1. Check if the file is executable. + 1. If the file is not executable, print an error and exit the container. +1. If the file has the extension `.envsh` the file will be [sourced](https://superuser.com/a/46146). +1. If the file has the extension `.sh` the file will be run like a normal script. +1. Any other file extension will log a warning and will be ignored. + +#### Included scripts + +* `/docker/entrypoint.d/04-defaults.envsh` calculates Docker container environment variables needed for [templating](#templating) configuration files. +* `/docker/entrypoint.d/05-templating.sh` renders [template](#templating) configuration files. +* `/docker/entrypoint.d/10-storage.sh` ensures Pixelfed storage related permissions and commands are run. +* `/docker/entrypoint.d/20-horizon.sh` ensures [Laravel Horizon](https://laravel.com/docs/master/horizon) used by Pixelfed is configured +* `/docker/entrypoint.d/30-cache.sh` ensures all Pixelfed caches (router, view, config) is warmed + +#### Disabling entrypoint or individual scripts + +To disable the entire entrypoint you can set the variable `ENTRYPOINT_SKIP=1`. + +To disable individual entrypoint scripts you can add the filename to the space (`" "`) separated variable `ENTRYPOINT_SKIP_SCRIPTS`. (example: `ENTRYPOINT_SKIP_SCRIPTS="10-storage.sh 30-cache.sh"`) + +### Templating + +The Docker container can do some basic templating (more like variable replacement) as part of the entrypoint scripts via [gomplate](https://docs.gomplate.ca/). + +Any file put in the `/docker/templates/` directory will be templated and written to the right directory. + +#### File path examples + +1. To template `/usr/local/etc/php/php.ini` in the container put the source file in `/docker/templates/usr/local/etc/php/php.ini`. +1. To template `/a/fantastic/example.txt` in the container put the source file in `/docker/templates/a/fantastic/example.txt`. +1. To template `/some/path/anywhere` in the container put the source file in `/docker/templates/a/fantastic/example.txt`. + +#### Available variables + +Variables available for templating are sourced (in order, so *last* source takes precedence) like this: + +1. `env:` in your `docker-compose.yml` or `-e` in your `docker run` / `docker compose run` +1. Any exported variables in `.envsh` files loaded *before* `05-templating.sh` (e.g. any file with `04-`, `03-`, `02-`, `01-` or `00-` prefix) +1. All key/value pairs in `/var/www/.env.docker` +1. All key/value pairs in `/var/www/.env` + +#### Template guide 101 + +Please see the [gomplate documentation](https://docs.gomplate.ca/) for a more comprehensive overview. + +The most frequent use-case you have is likely to print a environment variable (or a default value if it's missing), so this is how to do that: + +* `{{ getenv "VAR_NAME" }}` print an environment variable and **fail** if the variable is not set. ([docs](https://docs.gomplate.ca/functions/env/#envgetenv)) +* `{{ getenv "VAR_NAME" "default" }}` print an environment variable and print `default` if the variable is not set. ([docs](https://docs.gomplate.ca/functions/env/#envgetenv)) + +The script will *fail* if you reference a variable that does not exist (and don't have a default value) in a template. + +Please see the + +* [gomplate syntax documentation](https://docs.gomplate.ca/syntax/) +* [gomplate functions documentation](https://docs.gomplate.ca/functions/) + ## Build settings (arguments) The Pixelfed Dockerfile utilizes [Docker Multi-stage builds](https://docs.docker.com/build/building/multi-stage/) and [Build arguments](https://docs.docker.com/build/guide/build-args/). diff --git a/contrib/docker/nginx/root/etc/nginx/conf.d/default.conf b/contrib/docker/nginx/root/docker/templates/conf.d/default.conf similarity index 90% rename from contrib/docker/nginx/root/etc/nginx/conf.d/default.conf rename to contrib/docker/nginx/root/docker/templates/conf.d/default.conf index af5a66b77..671332e78 100644 --- a/contrib/docker/nginx/root/etc/nginx/conf.d/default.conf +++ b/contrib/docker/nginx/root/docker/templates/conf.d/default.conf @@ -1,7 +1,7 @@ server { listen 80 default_server; - server_name ${APP_DOMAIN}; + server_name {{ getenv "APP_DOMAIN" }}; root /var/www/public; add_header X-Frame-Options "SAMEORIGIN"; @@ -14,7 +14,7 @@ server { index index.html index.htm index.php; charset utf-8; - client_max_body_size ${POST_MAX_SIZE}; + client_max_body_size {{ getenv "POST_MAX_SIZE" }}; location / { try_files $uri $uri/ /index.php?$query_string; diff --git a/contrib/docker/shared/root/docker/entrypoint.d/05-templating.sh b/contrib/docker/shared/root/docker/entrypoint.d/05-templating.sh index 4b9f9014a..468b10617 100755 --- a/contrib/docker/shared/root/docker/entrypoint.d/05-templating.sh +++ b/contrib/docker/shared/root/docker/entrypoint.d/05-templating.sh @@ -3,38 +3,37 @@ source /docker/helpers.sh set_identity "$0" -auto_envsubst() { - local template_dir="${ENVSUBST_TEMPLATE_DIR:-/docker/templates}" - local output_dir="${ENVSUBST_OUTPUT_DIR:-}" - local filter="${ENVSUBST_FILTER:-}" - local template defined_envs relative_path output_path output_dir subdir +declare template_dir="${ENVSUBST_TEMPLATE_DIR:-/docker/templates}" +declare output_dir="${ENVSUBST_OUTPUT_DIR:-}" +declare filter="${ENVSUBST_FILTER:-}" +declare template defined_envs relative_path output_path output_dir subdir - # load all dot-env files - load-config-files +# load all dot-env files +load-config-files - # export all dot-env variables so they are available in templating - export ${seen_dot_env_variables[@]} +: ${ENTRYPOINT_SHOW_TEMPLATE_DIFF:=1} - defined_envs=$(printf '${%s} ' $(awk "END { for (name in ENVIRON) { print ( name ~ /${filter}/ ) ? name : \"\" } }" "$output_path" - done -} + log "Running [gomplate] on [$template] --> [$output_path]" + cat "$template" | gomplate >"$output_path" -auto_envsubst - -exit 0 + # Show the diff from the envsubst command + if [[ ${ENTRYPOINT_SHOW_TEMPLATE_DIFF} = 1 ]]; then + git --no-pager diff "$template" "${output_path}" || : + fi +done diff --git a/contrib/docker/shared/root/docker/entrypoint.d/10-storage.sh b/contrib/docker/shared/root/docker/entrypoint.d/10-storage.sh index c814a3df4..a35eeb5d3 100755 --- a/contrib/docker/shared/root/docker/entrypoint.d/10-storage.sh +++ b/contrib/docker/shared/root/docker/entrypoint.d/10-storage.sh @@ -3,10 +3,7 @@ source /docker/helpers.sh set_identity "$0" -log "Create the storage tree if needed" as_runtime_user cp --recursive storage.skel/* storage/ - -log "Ensure storage is linked" as_runtime_user php artisan storage:link log "Ensure permissions are correct" diff --git a/contrib/docker/shared/root/docker/entrypoint.d/30-cache.sh b/contrib/docker/shared/root/docker/entrypoint.d/30-cache.sh index e561daef9..11965fcea 100755 --- a/contrib/docker/shared/root/docker/entrypoint.d/30-cache.sh +++ b/contrib/docker/shared/root/docker/entrypoint.d/30-cache.sh @@ -3,11 +3,6 @@ source /docker/helpers.sh set_identity "$0" -log "==> route:cache" as_runtime_user php artisan route:cache - -log "==> view:cache" as_runtime_user php artisan view:cache - -log "==> config:cache" as_runtime_user php artisan config:cache diff --git a/contrib/docker/shared/root/docker/entrypoint.sh b/contrib/docker/shared/root/docker/entrypoint.sh index 0964980bc..dbc8aa1b5 100755 --- a/contrib/docker/shared/root/docker/entrypoint.sh +++ b/contrib/docker/shared/root/docker/entrypoint.sh @@ -1,50 +1,71 @@ #!/bin/bash set -e -o errexit -o nounset -o pipefail -[[ -n ${ENTRYPOINT_DEBUG:-} ]] && set -x +: ${ENTRYPOINT_SKIP:=0} +: ${ENTRYPOINT_SKIP_SCRIPTS:=""} +: ${ENTRYPOINT_DEBUG:=0} +: ${ENTRYPOINT_ROOT:="/docker/entrypoint.d/"} -declare -g ME="$0" -declare -gr ENTRYPOINT_ROOT=/docker/entrypoint.d/ +export ENTRYPOINT_ROOT -source /docker/helpers.sh +if [[ ${ENTRYPOINT_SKIP} == 0 ]]; then + [[ ${ENTRYPOINT_DEBUG} == 1 ]] && set -x -# ensure the entrypoint folder exists -mkdir -p "${ENTRYPOINT_ROOT}" + source /docker/helpers.sh -if /usr/bin/find "${ENTRYPOINT_ROOT}" -mindepth 1 -maxdepth 1 -type f -print -quit 2>/dev/null | read v; then - log "looking for shell scripts in /docker/entrypoint.d/" - find "${ENTRYPOINT_ROOT}" -follow -type f -print | sort -V | while read -r f; do - case "$f" in - *.envsh) - if [ -x "$f" ]; then - log "Sourcing $f" - source "$f" - resetore_identity - else - # warn on shell scripts without exec bit - log_warning "Ignoring $f, not executable" + declare -a skip_scripts=() + IFS=' ' read -a skip_scripts <<<"$ENTRYPOINT_SKIP_SCRIPTS" + + declare script_name + + # ensure the entrypoint folder exists + mkdir -p "${ENTRYPOINT_ROOT}" + + if /usr/bin/find "${ENTRYPOINT_ROOT}" -mindepth 1 -maxdepth 1 -type f -print -quit 2>/dev/null | read v; then + log "looking for shell scripts in /docker/entrypoint.d/" + + find "${ENTRYPOINT_ROOT}" -follow -type f -print | sort -V | while read -r f; do + script_name="$(get_script_name $f)" + if array_value_exists skip_scripts "${script_name}"; then + log_warning "Skipping script [${script_name}] since it's in the skip list (\$ENTRYPOINT_SKIP_SCRIPTS)" + + continue fi - ;; - *.sh) - if [ -x "$f" ]; then - log "Launching $f" - "$f" - else - # warn on shell scripts without exec bit - log_warning "Ignoring $f, not executable" - fi - ;; + case "$f" in + *.envsh) + if [ -x "$f" ]; then + log "Sourcing $f" - *) - log_warning "Ignoring $f" - ;; - esac - done + source "$f" - log "Configuration complete; ready for start up" -else - log_warning "No files found in ${ENTRYPOINT_ROOT}, skipping configuration" + resetore_identity + else + # warn on shell scripts without exec bit + log_error_and_exit "File [$f] is not executable (please 'chmod +x' it)" + fi + ;; + + *.sh) + if [ -x "$f" ]; then + log "Launching $f" + "$f" + else + # warn on shell scripts without exec bit + log_error_and_exit "File [$f] is not executable (please 'chmod +x' it)" + fi + ;; + + *) + log_warning "Ignoring $f" + ;; + esac + done + + log "Configuration complete; ready for start up" + else + log_warning "No files found in ${ENTRYPOINT_ROOT}, skipping configuration" + fi fi exec "$@" diff --git a/contrib/docker/shared/root/docker/helpers.sh b/contrib/docker/shared/root/docker/helpers.sh index fc8691324..f1ca33d09 100644 --- a/contrib/docker/shared/root/docker/helpers.sh +++ b/contrib/docker/shared/root/docker/helpers.sh @@ -10,11 +10,11 @@ declare -ra dot_env_files=( /var/www/.env.docker /var/www/.env ) -declare -a seen_dot_env_variables=() +declare -ga seen_dot_env_variables=() function set_identity() { old_log_prefix="${log_prefix}" - log_prefix="ENTRYPOINT - [${1}] - " + log_prefix="ENTRYPOINT - [$(get_script_name $1)] - " } function resetore_identity() { @@ -22,7 +22,23 @@ function resetore_identity() { } function as_runtime_user() { - su --preserve-environment $(id -un ${RUNTIME_UID}) --shell /bin/bash --command "${*}" + local -i exit_code + local target_user + + target_user=$(id -un ${RUNTIME_UID}) + + log "👷 Running [${*}] as [${target_user}]" + + su --preserve-environment "${target_user}" --shell /bin/bash --command "${*}" + exit_code=$? + + if [[ $exit_code != 0 ]]; then + log_error "❌ Error!" + return $exit_code + fi + + log "✅ OK!" + return $exit_code } # @description Display the given error message with its line number on stderr and exit with error. @@ -53,7 +69,7 @@ function log() { } function load-config-files() { - # Associative array (aka map/disctrionary) holding the unique keys found in dot-env files + # Associative array (aka map/dictionary) holding the unique keys found in dot-env files local -A _tmp_dot_env_keys for f in "${dot_env_files[@]}"; do @@ -73,3 +89,14 @@ function load-config-files() { seen_dot_env_variables=(${!_tmp_dot_env_keys[@]}) } + +function array_value_exists() { + local -nr validOptions=$1 + local -r providedValue="\<${2}\>" + + [[ ${validOptions[*]} =~ $providedValue ]] +} + +function get_script_name() { + echo "${1#"$ENTRYPOINT_ROOT"}" +} diff --git a/contrib/docker/shared/root/docker/install/base.sh b/contrib/docker/shared/root/docker/install/base.sh index b0e3d7b6d..b9b37b031 100755 --- a/contrib/docker/shared/root/docker/install/base.sh +++ b/contrib/docker/shared/root/docker/install/base.sh @@ -15,7 +15,7 @@ echo 'APT::Install-Suggests "false";' >>/etc/apt/apt.conf declare -ra standardPackages=( apt-utils ca-certificates - gettext-base + curl git gnupg1 gosu @@ -25,9 +25,10 @@ declare -ra standardPackages=( locales-all nano procps - unzip - zip software-properties-common + unzip + wget + zip ) # Image Optimization diff --git a/contrib/docker/shared/root/docker/templates/usr/local/etc/php/php.ini b/contrib/docker/shared/root/docker/templates/usr/local/etc/php/php.ini index 1a9f6b598..81ba3d207 100644 --- a/contrib/docker/shared/root/docker/templates/usr/local/etc/php/php.ini +++ b/contrib/docker/shared/root/docker/templates/usr/local/etc/php/php.ini @@ -679,7 +679,7 @@ auto_globals_jit = On ; Its value may be 0 to disable the limit. It is ignored if POST data reading ; is disabled through enable_post_data_reading. ; http://php.net/post-max-size -post_max_size = ${POST_MAX_SIZE} +post_max_size = {{ getenv "POST_MAX_SIZE" }} ; Automatically add files before PHP document. ; http://php.net/auto-prepend-file @@ -831,10 +831,10 @@ file_uploads = On ; Maximum allowed size for uploaded files. ; http://php.net/upload-max-filesize -upload_max_filesize = ${POST_MAX_SIZE} +upload_max_filesize = {{ getenv "POST_MAX_SIZE" }} ; Maximum number of files that can be uploaded via a single request -max_file_uploads = ${MAX_ALBUM_LENGTH} +max_file_uploads = {{ getenv "MAX_ALBUM_LENGTH" }} ;;;;;;;;;;;;;;;;;; ; Fopen wrappers ; From ce34e4d04625c02c40eaef6314e225354c103ee5 Mon Sep 17 00:00:00 2001 From: Christian Winther Date: Thu, 4 Jan 2024 21:21:00 +0000 Subject: [PATCH 011/173] more docs and rework --- contrib/docker/Dockerfile | 25 ++++--- .../docker/entrypoint.d/04-defaults.envsh | 16 ++-- .../root/docker/entrypoint.d/05-templating.sh | 6 +- .../root/docker/entrypoint.d/10-storage.sh | 8 +- .../root/docker/entrypoint.d/20-horizon.sh | 4 +- .../root/docker/entrypoint.d/30-cache.sh | 8 +- .../docker/shared/root/docker/entrypoint.sh | 51 +++++++------ contrib/docker/shared/root/docker/helpers.sh | 73 +++++++++++-------- 8 files changed, 106 insertions(+), 85 deletions(-) diff --git a/contrib/docker/Dockerfile b/contrib/docker/Dockerfile index 471ac5820..708d8247b 100644 --- a/contrib/docker/Dockerfile +++ b/contrib/docker/Dockerfile @@ -154,7 +154,7 @@ RUN --mount=type=cache,id=pixelfed-php-${PHP_VERSION}-${PHP_DEBIAN_RELEASE}-${TA # PHP: composer and source code ####################################################### -FROM php-extensions AS composer-and-src +FROM base AS composer-and-src ARG PHP_VERSION ARG PHP_DEBIAN_RELEASE @@ -178,7 +178,7 @@ COPY --link --from=composer-image /usr/bin/composer /usr/bin/composer USER ${RUNTIME_UID}:${RUNTIME_GID} # Copy over only composer related files so docker layer cache isn't invalidated on PHP file changes -COPY --link --chown=${RUNTIME_UID}:${RUNTIME_GID} composer.json composer.lock /var/www/ +COPY --chown=${RUNTIME_UID}:${RUNTIME_GID} composer.json composer.lock /var/www/ # Install composer dependencies # NOTE: we skip the autoloader generation here since we don't have all files avaliable (yet) @@ -187,14 +187,7 @@ RUN --mount=type=cache,id=pixelfed-composer-${PHP_VERSION}-${PHP_DEBIAN_RELEASE} && composer install --prefer-dist --no-autoloader --ignore-platform-reqs # Copy all other files over -COPY --link --chown=${RUNTIME_UID}:${RUNTIME_GID} . /var/www/ - -# Generate optimized autoloader now that we have all files around -RUN set -ex \ - && composer dump-autoload --optimize - -#! Changing back to root -USER root:root +COPY --chown=${RUNTIME_UID}:${RUNTIME_GID} . /var/www/ ####################################################### # Runtime: base @@ -213,9 +206,19 @@ ENV RUNTIME_GID=${RUNTIME_GID} COPY --link --from=php-extensions /usr/local/lib/php/extensions /usr/local/lib/php/extensions COPY --link --from=php-extensions /usr/local/etc/php /usr/local/etc/php -COPY --link --from=composer-and-src --chown=${RUNTIME_UID}:${RUNTIME_GID} /var/www /var/www COPY --link --from=forego-image /usr/local/bin/forego /usr/local/bin/forego COPY --link --from=gomplate-image /usr/local/bin/gomplate /usr/local/bin/gomplate +COPY --link --from=composer-image /usr/bin/composer /usr/bin/composer +COPY --link --from=composer-and-src --chown=${RUNTIME_UID}:${RUNTIME_GID} /var/www /var/www + +#! Changing user to runtime user +USER ${RUNTIME_UID}:${RUNTIME_GID} + +# Generate optimized autoloader now that we have all files around +RUN set -ex \ + && composer dump-autoload --optimize + +USER root # for detail why storage is copied this way, pls refer to https://github.com/pixelfed/pixelfed/pull/2137#discussion_r434468862 RUN set -ex \ diff --git a/contrib/docker/shared/root/docker/entrypoint.d/04-defaults.envsh b/contrib/docker/shared/root/docker/entrypoint.d/04-defaults.envsh index 2244be9b8..00415b22f 100755 --- a/contrib/docker/shared/root/docker/entrypoint.d/04-defaults.envsh +++ b/contrib/docker/shared/root/docker/entrypoint.d/04-defaults.envsh @@ -7,20 +7,20 @@ # and future entrypoint.d scripts # -set_identity "${BASH_SOURCE[0]}" +entrypoint-set-name "${BASH_SOURCE[0]}" load-config-files : ${POST_MAX_SIZE_BUFFER:=1M} -log "POST_MAX_SIZE_BUFFER is set to [${POST_MAX_SIZE_BUFFER}]" +log-info "POST_MAX_SIZE_BUFFER is set to [${POST_MAX_SIZE_BUFFER}]" buffer=$(numfmt --invalid=fail --from=auto --to=none --to-unit=K "${POST_MAX_SIZE_BUFFER}") -log "POST_MAX_SIZE_BUFFER converted to KB is [${buffer}]" +log-info "POST_MAX_SIZE_BUFFER converted to KB is [${buffer}]" -log "POST_MAX_SIZE will be calculated by [({MAX_PHOTO_SIZE} * {MAX_ALBUM_LENGTH}) + {POST_MAX_SIZE_BUFFER}]" -log " MAX_PHOTO_SIZE=${MAX_PHOTO_SIZE}" -log " MAX_ALBUM_LENGTH=${MAX_ALBUM_LENGTH}" -log " POST_MAX_SIZE_BUFFER=${buffer}" +log-info "POST_MAX_SIZE will be calculated by [({MAX_PHOTO_SIZE} * {MAX_ALBUM_LENGTH}) + {POST_MAX_SIZE_BUFFER}]" +log-info " MAX_PHOTO_SIZE=${MAX_PHOTO_SIZE}" +log-info " MAX_ALBUM_LENGTH=${MAX_ALBUM_LENGTH}" +log-info " POST_MAX_SIZE_BUFFER=${buffer}" : ${POST_MAX_SIZE:=$(numfmt --invalid=fail --from=auto --from-unit=K --to=si $(((${MAX_PHOTO_SIZE} * ${MAX_ALBUM_LENGTH}) + ${buffer})))} -log "POST_MAX_SIZE was calculated to [${POST_MAX_SIZE}]" +log-info "POST_MAX_SIZE was calculated to [${POST_MAX_SIZE}]" export POST_MAX_SIZE diff --git a/contrib/docker/shared/root/docker/entrypoint.d/05-templating.sh b/contrib/docker/shared/root/docker/entrypoint.d/05-templating.sh index 468b10617..22975a905 100755 --- a/contrib/docker/shared/root/docker/entrypoint.d/05-templating.sh +++ b/contrib/docker/shared/root/docker/entrypoint.d/05-templating.sh @@ -1,7 +1,7 @@ #!/bin/bash source /docker/helpers.sh -set_identity "$0" +entrypoint-set-name "$0" declare template_dir="${ENVSUBST_TEMPLATE_DIR:-/docker/templates}" declare output_dir="${ENVSUBST_OUTPUT_DIR:-}" @@ -23,13 +23,13 @@ find "$template_dir" -follow -type f -print | while read -r template; do output_dir=$(dirname "$output_path") if [ ! -w "$output_dir" ]; then - log_error_and_exit "ERROR: $template_dir exists, but $output_dir is not writable" + log-error-and-exit "ERROR: $template_dir exists, but $output_dir is not writable" fi # create a subdirectory where the template file exists mkdir -p "$output_dir/$subdir" - log "Running [gomplate] on [$template] --> [$output_path]" + log-info "Running [gomplate] on [$template] --> [$output_path]" cat "$template" | gomplate >"$output_path" # Show the diff from the envsubst command diff --git a/contrib/docker/shared/root/docker/entrypoint.d/10-storage.sh b/contrib/docker/shared/root/docker/entrypoint.d/10-storage.sh index a35eeb5d3..14f66dc27 100755 --- a/contrib/docker/shared/root/docker/entrypoint.d/10-storage.sh +++ b/contrib/docker/shared/root/docker/entrypoint.d/10-storage.sh @@ -1,10 +1,10 @@ #!/bin/bash source /docker/helpers.sh -set_identity "$0" +entrypoint-set-name "$0" -as_runtime_user cp --recursive storage.skel/* storage/ -as_runtime_user php artisan storage:link +run-as-runtime-user cp --recursive storage.skel/* storage/ +run-as-runtime-user php artisan storage:link -log "Ensure permissions are correct" +log-info "Ensure permissions are correct" chown --recursive ${RUNTIME_UID}:${RUNTIME_GID} storage/ bootstrap/ diff --git a/contrib/docker/shared/root/docker/entrypoint.d/20-horizon.sh b/contrib/docker/shared/root/docker/entrypoint.d/20-horizon.sh index 7c1d8fdc6..2d3394746 100755 --- a/contrib/docker/shared/root/docker/entrypoint.d/20-horizon.sh +++ b/contrib/docker/shared/root/docker/entrypoint.d/20-horizon.sh @@ -1,6 +1,6 @@ #!/bin/bash source /docker/helpers.sh -set_identity "$0" +entrypoint-set-name "$0" -as_runtime_user php artisan horizon:publish +run-as-runtime-user php artisan horizon:publish diff --git a/contrib/docker/shared/root/docker/entrypoint.d/30-cache.sh b/contrib/docker/shared/root/docker/entrypoint.d/30-cache.sh index 11965fcea..5c0f20bb8 100755 --- a/contrib/docker/shared/root/docker/entrypoint.d/30-cache.sh +++ b/contrib/docker/shared/root/docker/entrypoint.d/30-cache.sh @@ -1,8 +1,8 @@ #!/bin/bash source /docker/helpers.sh -set_identity "$0" +entrypoint-set-name "$0" -as_runtime_user php artisan route:cache -as_runtime_user php artisan view:cache -as_runtime_user php artisan config:cache +run-as-runtime-user php artisan route:cache +run-as-runtime-user php artisan view:cache +run-as-runtime-user php artisan config:cache diff --git a/contrib/docker/shared/root/docker/entrypoint.sh b/contrib/docker/shared/root/docker/entrypoint.sh index dbc8aa1b5..4f2e2eb90 100755 --- a/contrib/docker/shared/root/docker/entrypoint.sh +++ b/contrib/docker/shared/root/docker/entrypoint.sh @@ -13,7 +13,9 @@ if [[ ${ENTRYPOINT_SKIP} == 0 ]]; then source /docker/helpers.sh - declare -a skip_scripts=() + entrypoint-set-name "entrypoint.sh" + + declare -a skip_scripts IFS=' ' read -a skip_scripts <<<"$ENTRYPOINT_SKIP_SCRIPTS" declare script_name @@ -22,49 +24,52 @@ if [[ ${ENTRYPOINT_SKIP} == 0 ]]; then mkdir -p "${ENTRYPOINT_ROOT}" if /usr/bin/find "${ENTRYPOINT_ROOT}" -mindepth 1 -maxdepth 1 -type f -print -quit 2>/dev/null | read v; then - log "looking for shell scripts in /docker/entrypoint.d/" + log-info "looking for shell scripts in /docker/entrypoint.d/" - find "${ENTRYPOINT_ROOT}" -follow -type f -print | sort -V | while read -r f; do - script_name="$(get_script_name $f)" - if array_value_exists skip_scripts "${script_name}"; then - log_warning "Skipping script [${script_name}] since it's in the skip list (\$ENTRYPOINT_SKIP_SCRIPTS)" + find "${ENTRYPOINT_ROOT}" -follow -type f -print | sort -V | while read -r file; do + script_name="$(get-entrypoint-script-name $file)" + + if in-array "${script_name}" skip_scripts; then + log-warning "Skipping script [${script_name}] since it's in the skip list (\$ENTRYPOINT_SKIP_SCRIPTS)" continue fi - case "$f" in + case "${file}" in *.envsh) - if [ -x "$f" ]; then - log "Sourcing $f" - - source "$f" - - resetore_identity - else + if ! is-executable "${file}"; then # warn on shell scripts without exec bit - log_error_and_exit "File [$f] is not executable (please 'chmod +x' it)" + log-error-and-exit "File [${file}] is not executable (please 'chmod +x' it)" fi + + log-info "Sourcing [${file}]" + + source "${file}" + + # the sourced file will (should) than the log prefix, so this restores our own + # "global" log prefix once the file is done being sourced + entrypoint-restore-name ;; *.sh) - if [ -x "$f" ]; then - log "Launching $f" - "$f" - else + if ! is-executable "${file}"; then # warn on shell scripts without exec bit - log_error_and_exit "File [$f] is not executable (please 'chmod +x' it)" + log-error-and-exit "File [${file}] is not executable (please 'chmod +x' it)" fi + + log-info "Running [${file}]" + "${file}" ;; *) - log_warning "Ignoring $f" + log-warning "Ignoring unrecognized file [${file}]" ;; esac done - log "Configuration complete; ready for start up" + log-info "Configuration complete; ready for start up" else - log_warning "No files found in ${ENTRYPOINT_ROOT}, skipping configuration" + log-warning "No files found in ${ENTRYPOINT_ROOT}, skipping configuration" fi fi diff --git a/contrib/docker/shared/root/docker/helpers.sh b/contrib/docker/shared/root/docker/helpers.sh index f1ca33d09..5fb04d7a9 100644 --- a/contrib/docker/shared/root/docker/helpers.sh +++ b/contrib/docker/shared/root/docker/helpers.sh @@ -1,70 +1,79 @@ #!/bin/bash set -e -o errexit -o nounset -o pipefail +# Some splash of color for important messages declare -g error_message_color="\033[1;31m" declare -g warn_message_color="\033[1;34m" declare -g color_clear="\033[1;0m" + +# Current and previous log prefix declare -g log_prefix= -declare -g old_log_prefix= +declare -g log_prefix_previous= + +# dot-env files to source when reading config declare -ra dot_env_files=( /var/www/.env.docker /var/www/.env ) + +# environment keys seen when source dot files (so we can [export] them) declare -ga seen_dot_env_variables=() -function set_identity() { - old_log_prefix="${log_prefix}" - log_prefix="ENTRYPOINT - [$(get_script_name $1)] - " +function entrypoint-set-name() { + log_prefix_previous="${log_prefix}" + log_prefix="ENTRYPOINT - [$(get-entrypoint-script-name $1)] - " } -function resetore_identity() { - log_prefix="${old_log_prefix}" +function entrypoint-restore-name() { + log_prefix="${log_prefix_previous}" } -function as_runtime_user() { +function run-as-runtime-user() { local -i exit_code local target_user target_user=$(id -un ${RUNTIME_UID}) - log "👷 Running [${*}] as [${target_user}]" + log-info "👷 Running [${*}] as [${target_user}]" su --preserve-environment "${target_user}" --shell /bin/bash --command "${*}" exit_code=$? if [[ $exit_code != 0 ]]; then - log_error "❌ Error!" + log-error "❌ Error!" return $exit_code fi - log "✅ OK!" + log-info "✅ OK!" return $exit_code } -# @description Display the given error message with its line number on stderr and exit with error. +# @description Print the given error message to stderr # @arg $message string A error message. -function log_error() { - echo -e "${error_message_color}${log_prefix}ERROR - ${1}${color_clear}" >/dev/stderr +function log-error() { + echo -e "${error_message_color}${log_prefix}ERROR - ${*}${color_clear}" >/dev/stderr } -# @description Display the given error message with its line number on stderr and exit with error. -# @arg $message string A error message. +# @description Print the given error message to stderr and exit 1 +# @arg $@ string A error message. # @exitcode 1 -function log_error_and_exit() { - log_error "$1" +function log-error-and-exit() { + log-error "$@" exit 1 } -# @description Display the given warning message with its line number on stderr. -# @arg $message string A warning message. -function log_warning() { - echo -e "${warn_message_color}${log_prefix}WARNING - ${1}${color_clear}" >/dev/stderr +# @description Print the given warning message to stderr +# @arg $@ string A warning message. +function log-warning() { + echo -e "${warn_message_color}${log_prefix}WARNING - ${*}${color_clear}" >/dev/stderr } -function log() { +# @description Print the given message to stderr unless [ENTRYPOINT_QUIET_LOGS] is set +# @arg $@ string A warning message. +function log-info() { if [ -z "${ENTRYPOINT_QUIET_LOGS:-}" ]; then - echo "${log_prefix}$@" + echo "${log_prefix}$*" fi } @@ -74,11 +83,11 @@ function load-config-files() { for f in "${dot_env_files[@]}"; do if [ ! -e "$f" ]; then - log_warning "Could not source file [${f}]: does not exists" + log-warning "Could not source file [${f}]: does not exists" continue fi - log "Sourcing ${f}" + log-info "Sourcing ${f}" source "${f}" # find all keys in the dot-env file and store them in our temp associative array @@ -90,13 +99,17 @@ function load-config-files() { seen_dot_env_variables=(${!_tmp_dot_env_keys[@]}) } -function array_value_exists() { - local -nr validOptions=$1 - local -r providedValue="\<${2}\>" +function in-array() { + local -r needle="\<${1}\>" + local -nr haystack=$2 - [[ ${validOptions[*]} =~ $providedValue ]] + [[ ${haystack[*]} =~ $needle ]] } -function get_script_name() { +function is-executable() { + [[ -x "$1" ]] +} + +function get-entrypoint-script-name() { echo "${1#"$ENTRYPOINT_ROOT"}" } From f2c84971363e169f8c0cd2b525c41d88eeffc9aa Mon Sep 17 00:00:00 2001 From: Christian Winther Date: Thu, 4 Jan 2024 21:55:24 +0000 Subject: [PATCH 012/173] more clanup --- contrib/docker/Dockerfile | 5 +- .../docker/entrypoint.d/04-defaults.envsh | 6 +- .../root/docker/entrypoint.d/05-templating.sh | 56 +++++++---- .../docker/shared/root/docker/entrypoint.sh | 96 +++++++++---------- contrib/docker/shared/root/docker/helpers.sh | 12 +++ 5 files changed, 100 insertions(+), 75 deletions(-) diff --git a/contrib/docker/Dockerfile b/contrib/docker/Dockerfile index 708d8247b..cdff0d916 100644 --- a/contrib/docker/Dockerfile +++ b/contrib/docker/Dockerfile @@ -126,9 +126,9 @@ RUN --mount=type=cache,id=pixelfed-apt-${PHP_VERSION}-${PHP_DEBIAN_RELEASE}-${TA FROM base AS php-extensions -ARG PHP_EXTENSIONS_DATABASE ARG PHP_DEBIAN_RELEASE ARG PHP_EXTENSIONS +ARG PHP_EXTENSIONS_DATABASE ARG PHP_EXTENSIONS_EXTRA ARG PHP_PECL_EXTENSIONS ARG PHP_PECL_EXTENSIONS_EXTRA @@ -136,13 +136,10 @@ ARG PHP_VERSION ARG TARGETPLATFORM ENV PHP_EXTENSIONS_DATABASE=${PHP_EXTENSIONS_DATABASE} -ENV PHP_DEBIAN_RELEASE=${PHP_DEBIAN_RELEASE} ENV PHP_EXTENSIONS_EXTRA=${PHP_EXTENSIONS_EXTRA} ENV PHP_EXTENSIONS=${PHP_EXTENSIONS} ENV PHP_PECL_EXTENSIONS_EXTRA=${PHP_PECL_EXTENSIONS_EXTRA} ENV PHP_PECL_EXTENSIONS=${PHP_PECL_EXTENSIONS} -ENV PHP_VERSION=${PHP_VERSION} -ENV TARGETPLATFORM=${TARGETPLATFORM} COPY contrib/docker/shared/root/docker/install/php-extensions.sh /docker/install/php-extensions.sh RUN --mount=type=cache,id=pixelfed-php-${PHP_VERSION}-${PHP_DEBIAN_RELEASE}-${TARGETPLATFORM},sharing=locked,target=/usr/src/php/ \ diff --git a/contrib/docker/shared/root/docker/entrypoint.d/04-defaults.envsh b/contrib/docker/shared/root/docker/entrypoint.d/04-defaults.envsh index 00415b22f..3f1a77843 100755 --- a/contrib/docker/shared/root/docker/entrypoint.d/04-defaults.envsh +++ b/contrib/docker/shared/root/docker/entrypoint.d/04-defaults.envsh @@ -2,20 +2,23 @@ # NOTE: # -# this file is *sourced* not run by the entrypoint runner +# This file is *sourced* not run by the entrypoint runner # so any environment values set here will be accessible to all sub-processes # and future entrypoint.d scripts # +# We also don't need to source `helpers.sh` since it's already available entrypoint-set-name "${BASH_SOURCE[0]}" load-config-files +# We assign a 1MB buffer to the just-in-time calculated max post size to allow for fields and overhead : ${POST_MAX_SIZE_BUFFER:=1M} log-info "POST_MAX_SIZE_BUFFER is set to [${POST_MAX_SIZE_BUFFER}]" buffer=$(numfmt --invalid=fail --from=auto --to=none --to-unit=K "${POST_MAX_SIZE_BUFFER}") log-info "POST_MAX_SIZE_BUFFER converted to KB is [${buffer}]" +# Automatically calculate the [post_max_size] value for [php.ini] and [nginx] log-info "POST_MAX_SIZE will be calculated by [({MAX_PHOTO_SIZE} * {MAX_ALBUM_LENGTH}) + {POST_MAX_SIZE_BUFFER}]" log-info " MAX_PHOTO_SIZE=${MAX_PHOTO_SIZE}" log-info " MAX_ALBUM_LENGTH=${MAX_ALBUM_LENGTH}" @@ -23,4 +26,5 @@ log-info " POST_MAX_SIZE_BUFFER=${buffer}" : ${POST_MAX_SIZE:=$(numfmt --invalid=fail --from=auto --from-unit=K --to=si $(((${MAX_PHOTO_SIZE} * ${MAX_ALBUM_LENGTH}) + ${buffer})))} log-info "POST_MAX_SIZE was calculated to [${POST_MAX_SIZE}]" +# NOTE: must export the value so it's available in other scripts! export POST_MAX_SIZE diff --git a/contrib/docker/shared/root/docker/entrypoint.d/05-templating.sh b/contrib/docker/shared/root/docker/entrypoint.d/05-templating.sh index 22975a905..89b6f0504 100755 --- a/contrib/docker/shared/root/docker/entrypoint.d/05-templating.sh +++ b/contrib/docker/shared/root/docker/entrypoint.d/05-templating.sh @@ -3,37 +3,53 @@ source /docker/helpers.sh entrypoint-set-name "$0" -declare template_dir="${ENVSUBST_TEMPLATE_DIR:-/docker/templates}" -declare output_dir="${ENVSUBST_OUTPUT_DIR:-}" -declare filter="${ENVSUBST_FILTER:-}" -declare template defined_envs relative_path output_path output_dir subdir - -# load all dot-env files -load-config-files - +# Show [git diff] of templates being rendered (will help verify output) : ${ENTRYPOINT_SHOW_TEMPLATE_DIFF:=1} +# Directory where templates can be found +: ${ENTRYPOINT_TEMPLATE_DIR:=/docker/templates/} +# Root path to write template template_files to (default is '', meaning it will be written to /) +: ${ENTRYPOINT_TEMPLATE_OUTPUT_PREFIX:=} + +declare template_file relative_template_file_path output_file_dir + +# load all dot-env config files +load-config-files # export all dot-env variables so they are available in templating export ${seen_dot_env_variables[@]} -find "$template_dir" -follow -type f -print | while read -r template; do - relative_path="${template#"$template_dir/"}" - subdir=$(dirname "$relative_path") - output_path="$output_dir/${relative_path}" - output_dir=$(dirname "$output_path") +find "${ENTRYPOINT_TEMPLATE_DIR}" -follow -type f -print | while read -r template_file; do + # Example: template_file=/docker/templates/usr/local/etc/php/php.ini - if [ ! -w "$output_dir" ]; then - log-error-and-exit "ERROR: $template_dir exists, but $output_dir is not writable" + # The file path without the template dir prefix ($ENTRYPOINT_TEMPLATE_DIR) + # + # Example: /usr/local/etc/php/php.ini + relative_template_file_path="${template_file#"${ENTRYPOINT_TEMPLATE_DIR}"}" + + # Adds optional prefix to the output file path + # + # Example: /usr/local/etc/php/php.ini + output_file_path="${ENTRYPOINT_TEMPLATE_OUTPUT_PREFIX}/${relative_template_file_path}" + + # Remove the file from the path + # + # Example: /usr/local/etc/php + output_file_dir=$(dirname "${output_file_path}") + + # Ensure the output directory is writable + if ! is-writable "${output_file_dir}"; then + log-error-and-exit "${output_file_dir} is not writable" fi - # create a subdirectory where the template file exists - mkdir -p "$output_dir/$subdir" + # Create the output directory if it doesn't exists + ensure-directory "${output_file_dir}" - log-info "Running [gomplate] on [$template] --> [$output_path]" - cat "$template" | gomplate >"$output_path" + # Render the template + log-info "Running [gomplate] on [${template_file}] --> [${output_file_path}]" + cat "${template_file}" | gomplate >"${output_file_path}" # Show the diff from the envsubst command if [[ ${ENTRYPOINT_SHOW_TEMPLATE_DIFF} = 1 ]]; then - git --no-pager diff "$template" "${output_path}" || : + git --no-pager diff "${template_file}" "${output_file_path}" || : fi done diff --git a/contrib/docker/shared/root/docker/entrypoint.sh b/contrib/docker/shared/root/docker/entrypoint.sh index 4f2e2eb90..501fbced7 100755 --- a/contrib/docker/shared/root/docker/entrypoint.sh +++ b/contrib/docker/shared/root/docker/entrypoint.sh @@ -1,76 +1,72 @@ #!/bin/bash -set -e -o errexit -o nounset -o pipefail +if [[ ${ENTRYPOINT_SKIP:=0} != 0 ]]; then + exec "$@" +fi -: ${ENTRYPOINT_SKIP:=0} -: ${ENTRYPOINT_SKIP_SCRIPTS:=""} -: ${ENTRYPOINT_DEBUG:=0} : ${ENTRYPOINT_ROOT:="/docker/entrypoint.d/"} +: ${ENTRYPOINT_SKIP_SCRIPTS:=""} export ENTRYPOINT_ROOT -if [[ ${ENTRYPOINT_SKIP} == 0 ]]; then - [[ ${ENTRYPOINT_DEBUG} == 1 ]] && set -x +source /docker/helpers.sh - source /docker/helpers.sh +entrypoint-set-name "entrypoint.sh" - entrypoint-set-name "entrypoint.sh" +declare -a skip_scripts +IFS=' ' read -a skip_scripts <<<"$ENTRYPOINT_SKIP_SCRIPTS" - declare -a skip_scripts - IFS=' ' read -a skip_scripts <<<"$ENTRYPOINT_SKIP_SCRIPTS" +declare script_name - declare script_name +# ensure the entrypoint folder exists +mkdir -p "${ENTRYPOINT_ROOT}" - # ensure the entrypoint folder exists - mkdir -p "${ENTRYPOINT_ROOT}" +if /usr/bin/find "${ENTRYPOINT_ROOT}" -mindepth 1 -maxdepth 1 -type f -print -quit 2>/dev/null | read v; then + log-info "looking for shell scripts in /docker/entrypoint.d/" - if /usr/bin/find "${ENTRYPOINT_ROOT}" -mindepth 1 -maxdepth 1 -type f -print -quit 2>/dev/null | read v; then - log-info "looking for shell scripts in /docker/entrypoint.d/" + find "${ENTRYPOINT_ROOT}" -follow -type f -print | sort -V | while read -r file; do + script_name="$(get-entrypoint-script-name $file)" - find "${ENTRYPOINT_ROOT}" -follow -type f -print | sort -V | while read -r file; do - script_name="$(get-entrypoint-script-name $file)" + if in-array "${script_name}" skip_scripts; then + log-warning "Skipping script [${script_name}] since it's in the skip list (\$ENTRYPOINT_SKIP_SCRIPTS)" - if in-array "${script_name}" skip_scripts; then - log-warning "Skipping script [${script_name}] since it's in the skip list (\$ENTRYPOINT_SKIP_SCRIPTS)" + continue + fi - continue + case "${file}" in + *.envsh) + if ! is-executable "${file}"; then + # warn on shell scripts without exec bit + log-error-and-exit "File [${file}] is not executable (please 'chmod +x' it)" fi - case "${file}" in - *.envsh) - if ! is-executable "${file}"; then - # warn on shell scripts without exec bit - log-error-and-exit "File [${file}] is not executable (please 'chmod +x' it)" - fi + log-info "Sourcing [${file}]" - log-info "Sourcing [${file}]" + source "${file}" - source "${file}" + # the sourced file will (should) than the log prefix, so this restores our own + # "global" log prefix once the file is done being sourced + entrypoint-restore-name + ;; - # the sourced file will (should) than the log prefix, so this restores our own - # "global" log prefix once the file is done being sourced - entrypoint-restore-name - ;; + *.sh) + if ! is-executable "${file}"; then + # warn on shell scripts without exec bit + log-error-and-exit "File [${file}] is not executable (please 'chmod +x' it)" + fi - *.sh) - if ! is-executable "${file}"; then - # warn on shell scripts without exec bit - log-error-and-exit "File [${file}] is not executable (please 'chmod +x' it)" - fi + log-info "Running [${file}]" + "${file}" + ;; - log-info "Running [${file}]" - "${file}" - ;; + *) + log-warning "Ignoring unrecognized file [${file}]" + ;; + esac + done - *) - log-warning "Ignoring unrecognized file [${file}]" - ;; - esac - done - - log-info "Configuration complete; ready for start up" - else - log-warning "No files found in ${ENTRYPOINT_ROOT}, skipping configuration" - fi + log-info "Configuration complete; ready for start up" +else + log-warning "No files found in ${ENTRYPOINT_ROOT}, skipping configuration" fi exec "$@" diff --git a/contrib/docker/shared/root/docker/helpers.sh b/contrib/docker/shared/root/docker/helpers.sh index 5fb04d7a9..1a4f346b4 100644 --- a/contrib/docker/shared/root/docker/helpers.sh +++ b/contrib/docker/shared/root/docker/helpers.sh @@ -1,6 +1,10 @@ #!/bin/bash set -e -o errexit -o nounset -o pipefail +: ${ENTRYPOINT_DEBUG:=0} + +[[ ${ENTRYPOINT_DEBUG} == 1 ]] && set -x + # Some splash of color for important messages declare -g error_message_color="\033[1;31m" declare -g warn_message_color="\033[1;34m" @@ -110,6 +114,14 @@ function is-executable() { [[ -x "$1" ]] } +function is-writable() { + [[ -w "$1" ]] +} + +function ensure-directory() { + mkdir -pv "$@" +} + function get-entrypoint-script-name() { echo "${1#"$ENTRYPOINT_ROOT"}" } From c64571e46d1b3034bfcd55d2399b28d1e17d485e Mon Sep 17 00:00:00 2001 From: Christian Winther Date: Thu, 4 Jan 2024 22:16:25 +0000 Subject: [PATCH 013/173] more docs --- .../root/docker/entrypoint.d/05-templating.sh | 2 +- .../docker/shared/root/docker/entrypoint.sh | 110 ++++++++++-------- contrib/docker/shared/root/docker/helpers.sh | 47 +++++++- 3 files changed, 104 insertions(+), 55 deletions(-) diff --git a/contrib/docker/shared/root/docker/entrypoint.d/05-templating.sh b/contrib/docker/shared/root/docker/entrypoint.d/05-templating.sh index 89b6f0504..4e6060e43 100755 --- a/contrib/docker/shared/root/docker/entrypoint.d/05-templating.sh +++ b/contrib/docker/shared/root/docker/entrypoint.d/05-templating.sh @@ -42,7 +42,7 @@ find "${ENTRYPOINT_TEMPLATE_DIR}" -follow -type f -print | while read -r templat fi # Create the output directory if it doesn't exists - ensure-directory "${output_file_dir}" + ensure-directory-exists "${output_file_dir}" # Render the template log-info "Running [gomplate] on [${template_file}] --> [${output_file_path}]" diff --git a/contrib/docker/shared/root/docker/entrypoint.sh b/contrib/docker/shared/root/docker/entrypoint.sh index 501fbced7..c1e3064f3 100755 --- a/contrib/docker/shared/root/docker/entrypoint.sh +++ b/contrib/docker/shared/root/docker/entrypoint.sh @@ -1,72 +1,80 @@ #!/bin/bash +# short curcuit the entrypoint if $ENTRYPOINT_SKIP isn't set to 0 if [[ ${ENTRYPOINT_SKIP:=0} != 0 ]]; then exec "$@" fi +# Directory where entrypoint scripts lives : ${ENTRYPOINT_ROOT:="/docker/entrypoint.d/"} -: ${ENTRYPOINT_SKIP_SCRIPTS:=""} - export ENTRYPOINT_ROOT +# Space separated list of scripts the entrypoint runner should skip +: ${ENTRYPOINT_SKIP_SCRIPTS:=""} + +# Load helper scripts source /docker/helpers.sh +# Set the entrypoint name for logging entrypoint-set-name "entrypoint.sh" +# Convert ENTRYPOINT_SKIP_SCRIPTS into a native bash array for easier lookup declare -a skip_scripts IFS=' ' read -a skip_scripts <<<"$ENTRYPOINT_SKIP_SCRIPTS" -declare script_name - -# ensure the entrypoint folder exists +# Ensure the entrypoint root folder exists mkdir -p "${ENTRYPOINT_ROOT}" -if /usr/bin/find "${ENTRYPOINT_ROOT}" -mindepth 1 -maxdepth 1 -type f -print -quit 2>/dev/null | read v; then - log-info "looking for shell scripts in /docker/entrypoint.d/" - - find "${ENTRYPOINT_ROOT}" -follow -type f -print | sort -V | while read -r file; do - script_name="$(get-entrypoint-script-name $file)" - - if in-array "${script_name}" skip_scripts; then - log-warning "Skipping script [${script_name}] since it's in the skip list (\$ENTRYPOINT_SKIP_SCRIPTS)" - - continue - fi - - case "${file}" in - *.envsh) - if ! is-executable "${file}"; then - # warn on shell scripts without exec bit - log-error-and-exit "File [${file}] is not executable (please 'chmod +x' it)" - fi - - log-info "Sourcing [${file}]" - - source "${file}" - - # the sourced file will (should) than the log prefix, so this restores our own - # "global" log prefix once the file is done being sourced - entrypoint-restore-name - ;; - - *.sh) - if ! is-executable "${file}"; then - # warn on shell scripts without exec bit - log-error-and-exit "File [${file}] is not executable (please 'chmod +x' it)" - fi - - log-info "Running [${file}]" - "${file}" - ;; - - *) - log-warning "Ignoring unrecognized file [${file}]" - ;; - esac - done - - log-info "Configuration complete; ready for start up" -else +# If ENTRYPOINT_ROOT directory is empty, warn and run the regular command +if is-directory-empty "${ENTRYPOINT_ROOT}"; then log-warning "No files found in ${ENTRYPOINT_ROOT}, skipping configuration" + + exec "$@" fi +# Start scanning for entrypoint.d files to source or run +log-info "looking for shell scripts in [${ENTRYPOINT_ROOT}]" + +find "${ENTRYPOINT_ROOT}" -follow -type f -print | sort -V | while read -r file; do + # Skip the script if it's in the skip-script list + if in-array $(get-entrypoint-script-name "${file}") skip_scripts; then + log-warning "Skipping script [${script_name}] since it's in the skip list (\$ENTRYPOINT_SKIP_SCRIPTS)" + + continue + fi + + # Inspect the file extension of the file we're processing + case "${file}" in + *.envsh) + if ! is-executable "${file}"; then + # warn on shell scripts without exec bit + log-error-and-exit "File [${file}] is not executable (please 'chmod +x' it)" + fi + + log-info "Sourcing [${file}]" + + source "${file}" + + # the sourced file will (should) than the log prefix, so this restores our own + # "global" log prefix once the file is done being sourced + entrypoint-restore-name + ;; + + *.sh) + if ! is-executable "${file}"; then + # warn on shell scripts without exec bit + log-error-and-exit "File [${file}] is not executable (please 'chmod +x' it)" + fi + + log-info "Running [${file}]" + "${file}" + ;; + + *) + log-warning "Ignoring unrecognized file [${file}]" + ;; + esac +done + +log-info "Configuration complete; ready for start up" + exec "$@" diff --git a/contrib/docker/shared/root/docker/helpers.sh b/contrib/docker/shared/root/docker/helpers.sh index 1a4f346b4..ce9ab2661 100644 --- a/contrib/docker/shared/root/docker/helpers.sh +++ b/contrib/docker/shared/root/docker/helpers.sh @@ -23,15 +23,22 @@ declare -ra dot_env_files=( # environment keys seen when source dot files (so we can [export] them) declare -ga seen_dot_env_variables=() +# @description Restore the log prefix to the previous value that was captured in [entrypoint-set-name] +# @arg $1 string The name (or path) of the entrypoint script being run function entrypoint-set-name() { log_prefix_previous="${log_prefix}" log_prefix="ENTRYPOINT - [$(get-entrypoint-script-name $1)] - " } +# @description Restore the log prefix to the previous value that was captured in [entrypoint-set-name] function entrypoint-restore-name() { log_prefix="${log_prefix_previous}" } +# @description Run a command as the [runtime user] +# @arg $@ string The command to run +# @exitcode 0 if the command succeeeds +# @exitcode 1 if the command fails function run-as-runtime-user() { local -i exit_code local target_user @@ -54,12 +61,14 @@ function run-as-runtime-user() { # @description Print the given error message to stderr # @arg $message string A error message. +# @stderr The error message provided with log prefix function log-error() { echo -e "${error_message_color}${log_prefix}ERROR - ${*}${color_clear}" >/dev/stderr } # @description Print the given error message to stderr and exit 1 # @arg $@ string A error message. +# @stderr The error message provided with log prefix # @exitcode 1 function log-error-and-exit() { log-error "$@" @@ -69,18 +78,22 @@ function log-error-and-exit() { # @description Print the given warning message to stderr # @arg $@ string A warning message. +# @stderr The warning message provided with log prefix function log-warning() { echo -e "${warn_message_color}${log_prefix}WARNING - ${*}${color_clear}" >/dev/stderr } -# @description Print the given message to stderr unless [ENTRYPOINT_QUIET_LOGS] is set -# @arg $@ string A warning message. +# @description Print the given message to stdout unless [ENTRYPOINT_QUIET_LOGS] is set +# @arg $@ string A info message. +# @stdout The info message provided with log prefix unless $ENTRYPOINT_QUIET_LOGS function log-info() { if [ -z "${ENTRYPOINT_QUIET_LOGS:-}" ]; then echo "${log_prefix}$*" fi } +# @description Loads the dot-env files used by Docker and track the keys present in the configuration. +# @sets seen_dot_env_variables array List of config keys discovered during loading function load-config-files() { # Associative array (aka map/dictionary) holding the unique keys found in dot-env files local -A _tmp_dot_env_keys @@ -103,6 +116,11 @@ function load-config-files() { seen_dot_env_variables=(${!_tmp_dot_env_keys[@]}) } +# @description Checks if $needle exists in $haystack +# @arg $1 string The needle (value) to search for +# @arg $2 array The haystack (array) to search in +# @exitcode 0 If $needle was found in $haystack +# @exitcode 1 If $needle was *NOT* found in $haystack function in-array() { local -r needle="\<${1}\>" local -nr haystack=$2 @@ -110,18 +128,41 @@ function in-array() { [[ ${haystack[*]} =~ $needle ]] } +# @description Checks if $1 has executable bit set or not +# @arg $1 string The path to check +# @exitcode 0 If $1 has executable bit +# @exitcode 1 If $1 does *NOT* have executable bit function is-executable() { [[ -x "$1" ]] } +# @description Checks if $1 is writable or not +# @arg $1 string The path to check +# @exitcode 0 If $1 is writable +# @exitcode 1 If $1 is *NOT* writable function is-writable() { [[ -w "$1" ]] } -function ensure-directory() { +# @description Checks if $1 contains any files or not +# @arg $1 string The path to check +# @exitcode 0 If $1 contains files +# @exitcode 1 If $1 does *NOT* contain files +function is-directory-empty() { + ! find "${1}" -mindepth 1 -maxdepth 1 -type f -print -quit 2>/dev/null | read v +} + +# @description Ensures a directory exists (via mkdir) +# @arg $1 string The path to create +# @exitcode 0 If $1 If the path exists *or* was created +# @exitcode 1 If $1 If the path does *NOT* exists and could *NOT* be created +function ensure-directory-exists() { mkdir -pv "$@" } +# @description Find the relative path for a entrypoint script by removing the ENTRYPOINT_ROOT prefix +# @arg $1 string The path to manipulate +# @stdout The relative path to the entrypoint script function get-entrypoint-script-name() { echo "${1#"$ENTRYPOINT_ROOT"}" } From c12ef66c5642d43b1a2efa64c03bf6d6b131c2d3 Mon Sep 17 00:00:00 2001 From: Christian Winther Date: Thu, 4 Jan 2024 22:33:41 +0000 Subject: [PATCH 014/173] opt-in fixing of user/group ownership of files --- contrib/docker/README.md | 11 +++++++++- .../root/docker/entrypoint.d/10-storage.sh | 6 +++--- .../entrypoint.d/15-storage-permissions.sh | 21 +++++++++++++++++++ 3 files changed, 34 insertions(+), 4 deletions(-) create mode 100755 contrib/docker/shared/root/docker/entrypoint.d/15-storage-permissions.sh diff --git a/contrib/docker/README.md b/contrib/docker/README.md index a0b07f5fa..b07a9b1b7 100644 --- a/contrib/docker/README.md +++ b/contrib/docker/README.md @@ -103,7 +103,7 @@ When a Pixelfed container starts up, the [`ENTRYPOINT`](https://docs.docker.com/ 1. Search the `/docker/entrypoint.d/` directory for files and for each file (in lexical order). 1. Check if the file is executable. - 1. If the file is not executable, print an error and exit the container. + 1. If the file is *not* executable, print an error and exit the container. 1. If the file has the extension `.envsh` the file will be [sourced](https://superuser.com/a/46146). 1. If the file has the extension `.sh` the file will be run like a normal script. 1. Any other file extension will log a warning and will be ignored. @@ -159,6 +159,15 @@ Please see the * [gomplate syntax documentation](https://docs.gomplate.ca/syntax/) * [gomplate functions documentation](https://docs.gomplate.ca/functions/) +### Fixing ownership on startup + +You can set the environment variable `ENTRYPOINT_ENSURE_OWNERSHIP_PATHS` to a list of paths that should have their `$USER` and `$GROUP` ownership changed to the configured runtime user and group during container bootstrapping. + +The variable is a space-delimited list shown below and accepts both relative and absolute paths: + +* `ENTRYPOINT_ENSURE_OWNERSHIP_PATHS="./storage ./bootstrap"` +* `ENTRYPOINT_ENSURE_OWNERSHIP_PATHS="/some/other/folder"` + ## Build settings (arguments) The Pixelfed Dockerfile utilizes [Docker Multi-stage builds](https://docs.docker.com/build/building/multi-stage/) and [Build arguments](https://docs.docker.com/build/guide/build-args/). diff --git a/contrib/docker/shared/root/docker/entrypoint.d/10-storage.sh b/contrib/docker/shared/root/docker/entrypoint.d/10-storage.sh index 14f66dc27..83e0abf34 100755 --- a/contrib/docker/shared/root/docker/entrypoint.d/10-storage.sh +++ b/contrib/docker/shared/root/docker/entrypoint.d/10-storage.sh @@ -3,8 +3,8 @@ source /docker/helpers.sh entrypoint-set-name "$0" +# Copy the [storage/] skeleton files over the "real" [storage/] directory so assets are updated between versions run-as-runtime-user cp --recursive storage.skel/* storage/ -run-as-runtime-user php artisan storage:link -log-info "Ensure permissions are correct" -chown --recursive ${RUNTIME_UID}:${RUNTIME_GID} storage/ bootstrap/ +# Ensure storage linkk are correctly configured +run-as-runtime-user php artisan storage:link diff --git a/contrib/docker/shared/root/docker/entrypoint.d/15-storage-permissions.sh b/contrib/docker/shared/root/docker/entrypoint.d/15-storage-permissions.sh new file mode 100755 index 000000000..0a67e3fad --- /dev/null +++ b/contrib/docker/shared/root/docker/entrypoint.d/15-storage-permissions.sh @@ -0,0 +1,21 @@ +#!/bin/bash +source /docker/helpers.sh + +entrypoint-set-name "$0" + +# Optionally fix ownership of configured paths +: ${ENTRYPOINT_ENSURE_OWNERSHIP_PATHS:=""} + +declare -a ensure_ownership_paths=() +IFS=' ' read -a ensure_ownership_paths <<<"$ENTRYPOINT_ENSURE_OWNERSHIP_PATHS" + +if [[ ${#ensure_ownership_paths} == 0 ]]; then + log-info "No paths has been configured for ownership fixes via [\$ENTRYPOINT_ENSURE_OWNERSHIP_PATHS]." + + exit 0 +fi + +for path in "${ensure_ownership_paths[@]}"; do + log-info "Ensure ownership of [${path}] correct" + chown --recursive ${RUNTIME_UID}:${RUNTIME_GID} "${path}" +done From 895b51fd9ff059c3a469ad510ab0127f2e8c7b87 Mon Sep 17 00:00:00 2001 From: Christian Winther Date: Thu, 4 Jan 2024 23:04:25 +0000 Subject: [PATCH 015/173] more tweaks --- contrib/docker/README.md | 12 +++-- .../root/docker/entrypoint.d/10-storage.sh | 2 +- .../entrypoint.d/15-storage-permissions.sh | 8 ++-- .../docker/shared/root/docker/entrypoint.sh | 5 +++ contrib/docker/shared/root/docker/helpers.sh | 44 ++++++++++++++++--- 5 files changed, 56 insertions(+), 15 deletions(-) diff --git a/contrib/docker/README.md b/contrib/docker/README.md index b07a9b1b7..2797b95ff 100644 --- a/contrib/docker/README.md +++ b/contrib/docker/README.md @@ -108,6 +108,12 @@ When a Pixelfed container starts up, the [`ENTRYPOINT`](https://docs.docker.com/ 1. If the file has the extension `.sh` the file will be run like a normal script. 1. Any other file extension will log a warning and will be ignored. +#### Debugging + +You can set environment variable `ENTRYPOINT_DEBUG=1` to show verbose output of what each `entrypoint.d` script is doing. + +You can also `docker exec` or `docker run` into a container and run `/` + #### Included scripts * `/docker/entrypoint.d/04-defaults.envsh` calculates Docker container environment variables needed for [templating](#templating) configuration files. @@ -145,7 +151,7 @@ Variables available for templating are sourced (in order, so *last* source takes #### Template guide 101 -Please see the [gomplate documentation](https://docs.gomplate.ca/) for a more comprehensive overview. +Please see the [`gomplate` documentation](https://docs.gomplate.ca/) for a more comprehensive overview. The most frequent use-case you have is likely to print a environment variable (or a default value if it's missing), so this is how to do that: @@ -156,8 +162,8 @@ The script will *fail* if you reference a variable that does not exist (and don' Please see the -* [gomplate syntax documentation](https://docs.gomplate.ca/syntax/) -* [gomplate functions documentation](https://docs.gomplate.ca/functions/) +* [`gomplate` syntax documentation](https://docs.gomplate.ca/syntax/) +* [`gomplate` functions documentation](https://docs.gomplate.ca/functions/) ### Fixing ownership on startup diff --git a/contrib/docker/shared/root/docker/entrypoint.d/10-storage.sh b/contrib/docker/shared/root/docker/entrypoint.d/10-storage.sh index 83e0abf34..add20b5d6 100755 --- a/contrib/docker/shared/root/docker/entrypoint.d/10-storage.sh +++ b/contrib/docker/shared/root/docker/entrypoint.d/10-storage.sh @@ -4,7 +4,7 @@ source /docker/helpers.sh entrypoint-set-name "$0" # Copy the [storage/] skeleton files over the "real" [storage/] directory so assets are updated between versions -run-as-runtime-user cp --recursive storage.skel/* storage/ +run-as-runtime-user cp --recursive storage.skel/ storage/ # Ensure storage linkk are correctly configured run-as-runtime-user php artisan storage:link diff --git a/contrib/docker/shared/root/docker/entrypoint.d/15-storage-permissions.sh b/contrib/docker/shared/root/docker/entrypoint.d/15-storage-permissions.sh index 0a67e3fad..d5844d661 100755 --- a/contrib/docker/shared/root/docker/entrypoint.d/15-storage-permissions.sh +++ b/contrib/docker/shared/root/docker/entrypoint.d/15-storage-permissions.sh @@ -7,15 +7,15 @@ entrypoint-set-name "$0" : ${ENTRYPOINT_ENSURE_OWNERSHIP_PATHS:=""} declare -a ensure_ownership_paths=() -IFS=' ' read -a ensure_ownership_paths <<<"$ENTRYPOINT_ENSURE_OWNERSHIP_PATHS" +IFS=' ' read -a ensure_ownership_paths <<<"${ENTRYPOINT_ENSURE_OWNERSHIP_PATHS}" -if [[ ${#ensure_ownership_paths} == 0 ]]; then +if [[ ${#ensure_ownership_paths[@]} == 0 ]]; then log-info "No paths has been configured for ownership fixes via [\$ENTRYPOINT_ENSURE_OWNERSHIP_PATHS]." exit 0 fi for path in "${ensure_ownership_paths[@]}"; do - log-info "Ensure ownership of [${path}] correct" - chown --recursive ${RUNTIME_UID}:${RUNTIME_GID} "${path}" + log-info "Ensure ownership of [${path}] is correct" + run-as-current-user chown --recursive ${RUNTIME_UID}:${RUNTIME_GID} "${path}" done diff --git a/contrib/docker/shared/root/docker/entrypoint.sh b/contrib/docker/shared/root/docker/entrypoint.sh index c1e3064f3..e17a1c42b 100755 --- a/contrib/docker/shared/root/docker/entrypoint.sh +++ b/contrib/docker/shared/root/docker/entrypoint.sh @@ -50,7 +50,9 @@ find "${ENTRYPOINT_ROOT}" -follow -type f -print | sort -V | while read -r file; log-error-and-exit "File [${file}] is not executable (please 'chmod +x' it)" fi + log-info log-info "Sourcing [${file}]" + log-info source "${file}" @@ -65,7 +67,10 @@ find "${ENTRYPOINT_ROOT}" -follow -type f -print | sort -V | while read -r file; log-error-and-exit "File [${file}] is not executable (please 'chmod +x' it)" fi + log-info log-info "Running [${file}]" + log-info + "${file}" ;; diff --git a/contrib/docker/shared/root/docker/helpers.sh b/contrib/docker/shared/root/docker/helpers.sh index ce9ab2661..d80dc0d24 100644 --- a/contrib/docker/shared/root/docker/helpers.sh +++ b/contrib/docker/shared/root/docker/helpers.sh @@ -1,9 +1,7 @@ #!/bin/bash set -e -o errexit -o nounset -o pipefail -: ${ENTRYPOINT_DEBUG:=0} - -[[ ${ENTRYPOINT_DEBUG} == 1 ]] && set -x +[[ ${ENTRYPOINT_DEBUG:=0} == 1 ]] && set -x # Some splash of color for important messages declare -g error_message_color="\033[1;31m" @@ -40,14 +38,37 @@ function entrypoint-restore-name() { # @exitcode 0 if the command succeeeds # @exitcode 1 if the command fails function run-as-runtime-user() { + run-command-as "$(id -un ${RUNTIME_UID})" "${@}" +} + +# @description Run a command as the [runtime user] +# @arg $@ string The command to run +# @exitcode 0 if the command succeeeds +# @exitcode 1 if the command fails +function run-as-current-user() { + run-command-as "$(id -un)" "${@}" +} + +# @description Run a command as the a named user +# @arg $1 string The user to run the command as +# @arg $@ string The command to run +# @exitcode 0 If the command succeeeds +# @exitcode 1 If the command fails +function run-command-as() { local -i exit_code local target_user - target_user=$(id -un ${RUNTIME_UID}) + target_user=${1} + shift - log-info "👷 Running [${*}] as [${target_user}]" + log-info-stderr "👷 Running [${*}] as [${target_user}]" + + if [[ ${target_user} != "root" ]]; then + su --preserve-environment "${target_user}" --shell /bin/bash --command "${*}" + else + "${@}" + fi - su --preserve-environment "${target_user}" --shell /bin/bash --command "${*}" exit_code=$? if [[ $exit_code != 0 ]]; then @@ -55,7 +76,7 @@ function run-as-runtime-user() { return $exit_code fi - log-info "✅ OK!" + log-info-stderr "✅ OK!" return $exit_code } @@ -92,6 +113,15 @@ function log-info() { fi } +# @description Print the given message to stderr unless [ENTRYPOINT_QUIET_LOGS] is set +# @arg $@ string A info message. +# @stderr The info message provided with log prefix unless $ENTRYPOINT_QUIET_LOGS +function log-info-stderr() { + if [ -z "${ENTRYPOINT_QUIET_LOGS:-}" ]; then + echo "${log_prefix}$*" + fi +} + # @description Loads the dot-env files used by Docker and track the keys present in the configuration. # @sets seen_dot_env_variables array List of config keys discovered during loading function load-config-files() { From d13895a3e0530011bf6210388dffd2614e4f5675 Mon Sep 17 00:00:00 2001 From: Christian Winther Date: Thu, 4 Jan 2024 23:15:46 +0000 Subject: [PATCH 016/173] add 15-storage-permissions.sh to the docs --- contrib/docker/README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/contrib/docker/README.md b/contrib/docker/README.md index 2797b95ff..443ab6423 100644 --- a/contrib/docker/README.md +++ b/contrib/docker/README.md @@ -119,6 +119,7 @@ You can also `docker exec` or `docker run` into a container and run `/` * `/docker/entrypoint.d/04-defaults.envsh` calculates Docker container environment variables needed for [templating](#templating) configuration files. * `/docker/entrypoint.d/05-templating.sh` renders [template](#templating) configuration files. * `/docker/entrypoint.d/10-storage.sh` ensures Pixelfed storage related permissions and commands are run. +* `//docker/entrypoint.d/15-storage-permissions.sh` (optionally) ensures permissions for files are corrected (see [fixing ownership on startup](#fixing-ownership-on-startup)) * `/docker/entrypoint.d/20-horizon.sh` ensures [Laravel Horizon](https://laravel.com/docs/master/horizon) used by Pixelfed is configured * `/docker/entrypoint.d/30-cache.sh` ensures all Pixelfed caches (router, view, config) is warmed From 99e2a045a6d2d9d0740a19a7b0580775e5c0405f Mon Sep 17 00:00:00 2001 From: Christian Winther Date: Fri, 5 Jan 2024 00:11:20 +0000 Subject: [PATCH 017/173] more renaming for clarity --- .../shared/root/docker/entrypoint.d/04-defaults.envsh | 2 +- .../shared/root/docker/entrypoint.d/05-templating.sh | 2 +- .../docker/shared/root/docker/entrypoint.d/10-storage.sh | 2 +- .../root/docker/entrypoint.d/15-storage-permissions.sh | 2 +- .../docker/shared/root/docker/entrypoint.d/20-horizon.sh | 2 +- .../docker/shared/root/docker/entrypoint.d/30-cache.sh | 2 +- contrib/docker/shared/root/docker/entrypoint.sh | 4 ++-- contrib/docker/shared/root/docker/helpers.sh | 8 ++++---- 8 files changed, 12 insertions(+), 12 deletions(-) diff --git a/contrib/docker/shared/root/docker/entrypoint.d/04-defaults.envsh b/contrib/docker/shared/root/docker/entrypoint.d/04-defaults.envsh index 3f1a77843..3507d94ee 100755 --- a/contrib/docker/shared/root/docker/entrypoint.d/04-defaults.envsh +++ b/contrib/docker/shared/root/docker/entrypoint.d/04-defaults.envsh @@ -8,7 +8,7 @@ # # We also don't need to source `helpers.sh` since it's already available -entrypoint-set-name "${BASH_SOURCE[0]}" +entrypoint-set-script-name "${BASH_SOURCE[0]}" load-config-files diff --git a/contrib/docker/shared/root/docker/entrypoint.d/05-templating.sh b/contrib/docker/shared/root/docker/entrypoint.d/05-templating.sh index 4e6060e43..618a2d406 100755 --- a/contrib/docker/shared/root/docker/entrypoint.d/05-templating.sh +++ b/contrib/docker/shared/root/docker/entrypoint.d/05-templating.sh @@ -1,7 +1,7 @@ #!/bin/bash source /docker/helpers.sh -entrypoint-set-name "$0" +entrypoint-set-script-name "$0" # Show [git diff] of templates being rendered (will help verify output) : ${ENTRYPOINT_SHOW_TEMPLATE_DIFF:=1} diff --git a/contrib/docker/shared/root/docker/entrypoint.d/10-storage.sh b/contrib/docker/shared/root/docker/entrypoint.d/10-storage.sh index add20b5d6..fc952ea3a 100755 --- a/contrib/docker/shared/root/docker/entrypoint.d/10-storage.sh +++ b/contrib/docker/shared/root/docker/entrypoint.d/10-storage.sh @@ -1,7 +1,7 @@ #!/bin/bash source /docker/helpers.sh -entrypoint-set-name "$0" +entrypoint-set-script-name "$0" # Copy the [storage/] skeleton files over the "real" [storage/] directory so assets are updated between versions run-as-runtime-user cp --recursive storage.skel/ storage/ diff --git a/contrib/docker/shared/root/docker/entrypoint.d/15-storage-permissions.sh b/contrib/docker/shared/root/docker/entrypoint.d/15-storage-permissions.sh index d5844d661..30a58c5a9 100755 --- a/contrib/docker/shared/root/docker/entrypoint.d/15-storage-permissions.sh +++ b/contrib/docker/shared/root/docker/entrypoint.d/15-storage-permissions.sh @@ -1,7 +1,7 @@ #!/bin/bash source /docker/helpers.sh -entrypoint-set-name "$0" +entrypoint-set-script-name "$0" # Optionally fix ownership of configured paths : ${ENTRYPOINT_ENSURE_OWNERSHIP_PATHS:=""} diff --git a/contrib/docker/shared/root/docker/entrypoint.d/20-horizon.sh b/contrib/docker/shared/root/docker/entrypoint.d/20-horizon.sh index 2d3394746..6b81e7133 100755 --- a/contrib/docker/shared/root/docker/entrypoint.d/20-horizon.sh +++ b/contrib/docker/shared/root/docker/entrypoint.d/20-horizon.sh @@ -1,6 +1,6 @@ #!/bin/bash source /docker/helpers.sh -entrypoint-set-name "$0" +entrypoint-set-script-name "$0" run-as-runtime-user php artisan horizon:publish diff --git a/contrib/docker/shared/root/docker/entrypoint.d/30-cache.sh b/contrib/docker/shared/root/docker/entrypoint.d/30-cache.sh index 5c0f20bb8..e933a179b 100755 --- a/contrib/docker/shared/root/docker/entrypoint.d/30-cache.sh +++ b/contrib/docker/shared/root/docker/entrypoint.d/30-cache.sh @@ -1,7 +1,7 @@ #!/bin/bash source /docker/helpers.sh -entrypoint-set-name "$0" +entrypoint-set-script-name "$0" run-as-runtime-user php artisan route:cache run-as-runtime-user php artisan view:cache diff --git a/contrib/docker/shared/root/docker/entrypoint.sh b/contrib/docker/shared/root/docker/entrypoint.sh index e17a1c42b..173e4dbe3 100755 --- a/contrib/docker/shared/root/docker/entrypoint.sh +++ b/contrib/docker/shared/root/docker/entrypoint.sh @@ -15,7 +15,7 @@ export ENTRYPOINT_ROOT source /docker/helpers.sh # Set the entrypoint name for logging -entrypoint-set-name "entrypoint.sh" +entrypoint-set-script-name "entrypoint.sh" # Convert ENTRYPOINT_SKIP_SCRIPTS into a native bash array for easier lookup declare -a skip_scripts @@ -58,7 +58,7 @@ find "${ENTRYPOINT_ROOT}" -follow -type f -print | sort -V | while read -r file; # the sourced file will (should) than the log prefix, so this restores our own # "global" log prefix once the file is done being sourced - entrypoint-restore-name + entrypoint-restore-script-name ;; *.sh) diff --git a/contrib/docker/shared/root/docker/helpers.sh b/contrib/docker/shared/root/docker/helpers.sh index d80dc0d24..880027cf4 100644 --- a/contrib/docker/shared/root/docker/helpers.sh +++ b/contrib/docker/shared/root/docker/helpers.sh @@ -21,15 +21,15 @@ declare -ra dot_env_files=( # environment keys seen when source dot files (so we can [export] them) declare -ga seen_dot_env_variables=() -# @description Restore the log prefix to the previous value that was captured in [entrypoint-set-name] +# @description Restore the log prefix to the previous value that was captured in [entrypoint-set-script-name ] # @arg $1 string The name (or path) of the entrypoint script being run -function entrypoint-set-name() { +function entrypoint-set-script-name() { log_prefix_previous="${log_prefix}" log_prefix="ENTRYPOINT - [$(get-entrypoint-script-name $1)] - " } -# @description Restore the log prefix to the previous value that was captured in [entrypoint-set-name] -function entrypoint-restore-name() { +# @description Restore the log prefix to the previous value that was captured in [entrypoint-set-script-name ] +function entrypoint-restore-script-name() { log_prefix="${log_prefix_previous}" } From 5cfd8e15a98f5bfd1a64fb4bc7d337e68224de53 Mon Sep 17 00:00:00 2001 From: Christian Winther Date: Fri, 5 Jan 2024 00:16:36 +0000 Subject: [PATCH 018/173] quotes --- contrib/docker/Dockerfile | 23 +++++++++++------------ 1 file changed, 11 insertions(+), 12 deletions(-) diff --git a/contrib/docker/Dockerfile b/contrib/docker/Dockerfile index cdff0d916..c254b2c4d 100644 --- a/contrib/docker/Dockerfile +++ b/contrib/docker/Dockerfile @@ -9,13 +9,13 @@ ARG COMPOSER_VERSION="2.6" # See: https://nginx.org/ -ARG NGINX_VERSION=1.25.3 +ARG NGINX_VERSION="1.25.3" # See: https://github.com/ddollar/forego -ARG FOREGO_VERSION=0.17.2 +ARG FOREGO_VERSION="0.17.2" # See: https://github.com/hairyhenderson/gomplate -ARG GOMPLATE_VERSION=v3.11.6 +ARG GOMPLATE_VERSION="v3.11.6" ### # PHP base configuration @@ -32,22 +32,22 @@ ARG RUNTIME_UID=33 # often called 'www-data' ARG RUNTIME_GID=33 # often called 'www-data' # APT extra packages -ARG APT_PACKAGES_EXTRA= +ARG APT_PACKAGES_EXTRA="" # Extensions installed via [pecl install] ARG PHP_PECL_EXTENSIONS="" -ARG PHP_PECL_EXTENSIONS_EXTRA= +ARG PHP_PECL_EXTENSIONS_EXTRA="" # Extensions installed via [docker-php-ext-install] ARG PHP_EXTENSIONS="intl bcmath zip pcntl exif curl gd" -ARG PHP_EXTENSIONS_EXTRA= +ARG PHP_EXTENSIONS_EXTRA="" ARG PHP_EXTENSIONS_DATABASE="pdo_pgsql pdo_mysql pdo_sqlite" # GPG key for nginx apt repository -ARG NGINX_GPGKEY=573BFD6B3D8FBC641079A6ABABF5BD827BD9BF62 +ARG NGINX_GPGKEY="573BFD6B3D8FBC641079A6ABABF5BD827BD9BF62" # GPP key path for nginx apt repository -ARG NGINX_GPGKEY_PATH=/usr/share/keyrings/nginx-archive-keyring.gpg +ARG NGINX_GPGKEY_PATH="/usr/share/keyrings/nginx-archive-keyring.gpg" ####################################################### # Docker "copy from" images @@ -93,15 +93,14 @@ RUN set -ex \ FROM php:${PHP_VERSION}-${PHP_BASE_TYPE}-${PHP_DEBIAN_RELEASE} AS base ARG APT_PACKAGES_EXTRA +ARG BUILDKIT_SBOM_SCAN_STAGE="true" ARG PHP_DEBIAN_RELEASE ARG PHP_VERSION ARG RUNTIME_GID ARG RUNTIME_UID - ARG TARGETPLATFORM -ARG BUILDKIT_SBOM_SCAN_STAGE=true -ENV DEBIAN_FRONTEND=noninteractive +ENV DEBIAN_FRONTEND="noninteractive" # Ensure we run all scripts through 'bash' rather than 'sh' SHELL ["/bin/bash", "-c"] @@ -160,7 +159,7 @@ ARG RUNTIME_GID ARG TARGETPLATFORM # Make sure composer cache is targeting our cache mount later -ENV COMPOSER_CACHE_DIR=/cache/composer +ENV COMPOSER_CACHE_DIR="/cache/composer" # Don't enforce any memory limits for composer ENV COMPOSER_MEMORY_LIMIT=-1 From f2eb3df85fc209a184443f9e03cc61faa16a7730 Mon Sep 17 00:00:00 2001 From: Christian Winther Date: Fri, 5 Jan 2024 01:34:46 +0000 Subject: [PATCH 019/173] remove VOLUME and EXPOSE see https://stackoverflow.com/a/52571354/1081818 --- contrib/docker/Dockerfile | 8 -------- 1 file changed, 8 deletions(-) diff --git a/contrib/docker/Dockerfile b/contrib/docker/Dockerfile index c254b2c4d..8ef6a99d4 100644 --- a/contrib/docker/Dockerfile +++ b/contrib/docker/Dockerfile @@ -225,8 +225,6 @@ COPY contrib/docker/shared/root / ENTRYPOINT ["/docker/entrypoint.sh"] -VOLUME /var/www/storage /var/www/bootstrap - ####################################################### # Runtime: apache ####################################################### @@ -241,8 +239,6 @@ RUN set -ex \ CMD ["apache2-foreground"] -EXPOSE 80 - ####################################################### # Runtime: fpm ####################################################### @@ -253,8 +249,6 @@ COPY contrib/docker/fpm/root / CMD ["php-fpm"] -EXPOSE 9000 - ####################################################### # Runtime: nginx ####################################################### @@ -284,8 +278,6 @@ COPY --link --from=nginx-image /docker-entrypoint.d /docker/entrypoint.d/ COPY contrib/docker/nginx/root / COPY contrib/docker/nginx/Procfile . -EXPOSE 80 - STOPSIGNAL SIGQUIT CMD ["forego", "start", "-r"] From 10674ac52337b3df7f9bcae0972fcfc44b7e9754 Mon Sep 17 00:00:00 2001 From: Christian Winther Date: Fri, 5 Jan 2024 16:18:48 +0000 Subject: [PATCH 020/173] iterate on apache example with docker-compose --- .gitignore | 3 + contrib/docker-compose/.env | 916 ++++++++++++++++++ contrib/docker-compose/README.md | 13 + .../docker-compose/docker-compose.apache.yml | 59 ++ .../root/docker/entrypoint.d/10-storage.sh | 2 +- .../templates/usr/local/etc/php/php.ini | 6 +- 6 files changed, 995 insertions(+), 4 deletions(-) create mode 100644 contrib/docker-compose/.env create mode 100644 contrib/docker-compose/README.md create mode 100644 contrib/docker-compose/docker-compose.apache.yml diff --git a/.gitignore b/.gitignore index 0494cee10..4396e4cdd 100644 --- a/.gitignore +++ b/.gitignore @@ -20,3 +20,6 @@ yarn-error.log .git-credentials /.composer/ /nginx.conf +/contrib/docker-compose/data +/contrib/docker-compose/config +!/contrib/docker-compose/.env diff --git a/contrib/docker-compose/.env b/contrib/docker-compose/.env new file mode 100644 index 000000000..4cfde052b --- /dev/null +++ b/contrib/docker-compose/.env @@ -0,0 +1,916 @@ +# -*- mode: bash -*- +# vi: ft=bash + +############################################################### +# Docker-wide configuration +############################################################### + +# Path (relative) to the docker-compose file where containers will store their data +DOCKER_DATA_ROOT="./data" + +# Path (relative) to the docker-compose file where containers will store their config +DOCKER_CONFIG_ROOT="./config" + +# Pixelfed version (image tag) to pull from the registry +DOCKER_TAG="branch-jippi-fork-apache-8.1" + +# Set timezone used by *all* containers - these should be in sync +# +# See: https://www.php.net/manual/en/timezones.php +TZ="UTC" + +############################################################### +# Pixelfed application configuration +############################################################### + +# A random 32-character string to be used as an encryption key. +# +# No default value; use [php artisan key:generate] to generate. +# +# This key is used by the Illuminate encrypter service and should be set to a random, +# 32 character string, otherwise these encrypted strings will not be safe. +# +# Please do this before deploying an application! +# +# See: https://docs.pixelfed.org/technical-documentation/config/#app_key +APP_KEY="" + +# See: https://docs.pixelfed.org/technical-documentation/config/#app_name-1 +APP_NAME="Pixelfed Prod" + +# Application domains used for routing. +# +# See: https://docs.pixelfed.org/technical-documentation/config/#app_domain +APP_DOMAIN="your-domain-here-dot-com" + +# This URL is used by the console to properly generate URLs when using the Artisan command line tool. +# You should set this to the root of your application so that it is used when running Artisan tasks. +# +# See: https://docs.pixelfed.org/technical-documentation/config/#app_url +APP_URL=https://${APP_DOMAIN} + +# Application domains used for routing. +# +# See: https://docs.pixelfed.org/technical-documentation/config/#admin_domain +ADMIN_DOMAIN="${APP_DOMAIN}" + +# This value determines the “environment” your application is currently running in. +# This may determine how you prefer to configure various services your application utilizes. +# +# See: https://docs.pixelfed.org/technical-documentation/config/#app_env +#APP_ENV="production" + +# When your application is in debug mode, detailed error messages with stack traces will +# be shown on every error that occurs within your application. +# +# If disabled, a simple generic error page is shown. +# +# See: https://docs.pixelfed.org/technical-documentation/config/#app_debug +#APP_DEBUG="false" + +# Enable/disable new local account registrations. +# +# See: https://docs.pixelfed.org/technical-documentation/config/#open_registration +#OPEN_REGISTRATION=true + +# Require email verification before a new user can do anything. +# +# Defaults to "true". +# +# See: https://docs.pixelfed.org/technical-documentation/config/#enforce_email_verification +#ENFORCE_EMAIL_VERIFICATION="true" + +# Allow a maximum number of user accounts. +# +# Defaults to "1000". +# +# See: https://docs.pixelfed.org/technical-documentation/config/#pf_max_users +PF_MAX_USERS="false" + +# See: https://docs.pixelfed.org/technical-documentation/config/#oauth_enabled +# OAUTH_ENABLED="true" + +# Defaults to "UTC". +# +# Do not edit your timezone or things will break! +# +# See: https://docs.pixelfed.org/technical-documentation/config/#app_timezone +# See: https://www.php.net/manual/en/timezones.php +APP_TIMEZONE="${TZ}" + +# The application locale determines the default locale that will be used by the translation service provider. +# You are free to set this value to any of the locales which will be supported by the application. +# +# Defaults to "en". +# +# See: https://docs.pixelfed.org/technical-documentation/config/#app_locale +#APP_LOCALE="en" + +# The fallback locale determines the locale to use when the current one is not available. +# +# You may change the value to correspond to any of the language folders that are provided through your application. +# +# Defaults to "en". +# +# See: https://docs.pixelfed.org/technical-documentation/config/#app_fallback_locale +APP_FALLBACK_LOCALE="en" + +# See: https://docs.pixelfed.org/technical-documentation/config/#limit_account_size +#LIMIT_ACCOUNT_SIZE="true" + +# Update the max account size, the per user limit of files in kB. +# +# Defaults to "1000000" (1GB). +# +# See: https://docs.pixelfed.org/technical-documentation/config/#max_account_size-kb +#MAX_ACCOUNT_SIZE="1000000" + +# Update the max photo size, in kB. +# +# Defaults to "15000" (15MB). +# +# See: https://docs.pixelfed.org/technical-documentation/config/#max_photo_size-kb +#MAX_PHOTO_SIZE="15000" + +# Update the max avatar size, in kB. +# +# Defaults to "2000" (2MB). +# +# See: https://docs.pixelfed.org/technical-documentation/config/#max_avatar_size-kb +#MAX_AVATAR_SIZE="2000" + +# Change the caption length limit for new local posts. +# +# Defaults to "500". +# +# See: https://docs.pixelfed.org/technical-documentation/config/#max_caption_length +#MAX_CAPTION_LENGTH="500" + +# Change the bio length limit for user profiles. +# +# Defaults to "125". +# +# See: https://docs.pixelfed.org/technical-documentation/config/#max_bio_length +#MAX_BIO_LENGTH="125" + +# Change the length limit for user names. +# +# Defaults to "30". +# +# See: https://docs.pixelfed.org/technical-documentation/config/#max_name_length +#MAX_NAME_LENGTH="30" + +# The max number of photos allowed per post. +# +# Defaults to "4". +# +# See: https://docs.pixelfed.org/technical-documentation/config/#max_album_length +#MAX_ALBUM_LENGTH="4" + +# Set the image optimization quality, must be a value between 1-100. +# +# Defaults to "80". +# +# See: https://docs.pixelfed.org/technical-documentation/config/#image_quality +#IMAGE_QUALITY="80" + +# Resize and optimize image uploads. +# +# Defaults to "true". +# +# See: https://docs.pixelfed.org/technical-documentation/config/#pf_optimize_images +#PF_OPTIMIZE_IMAGES="true" + +# Resize and optimize video uploads. +# +# Defaults to "true". +# +# See: https://docs.pixelfed.org/technical-documentation/config/#pf_optimize_videos +#PF_OPTIMIZE_VIDEOS="true" + +# Enable account deletion. +# +# Defaults to "true". +# +# See: https://docs.pixelfed.org/technical-documentation/config/#account_deletion +#ACCOUNT_DELETION="true" + +# Set account deletion queue after X days, set to false to delete accounts immediately. +# +# Defaults to "false". +# +# See: https://docs.pixelfed.org/technical-documentation/config/#account_delete_after +#ACCOUNT_DELETE_AFTER="false" + +# Defaults to "Pixelfed - Photo sharing for everyone". +# +# See: https://docs.pixelfed.org/technical-documentation/config/#instance_description +#INSTANCE_DESCRIPTION= + +# Defaults to "false". +# +# See: https://docs.pixelfed.org/technical-documentation/config/#instance_public_hashtags +#INSTANCE_PUBLIC_HASHTAGS="false" + +# Defaults to "". +# +# See: https://docs.pixelfed.org/technical-documentation/config/#instance_contact_email +INSTANCE_CONTACT_EMAIL="admin@${APP_DOMAIN}" + +# Defaults to "false". +# +# See: https://docs.pixelfed.org/technical-documentation/config/#instance_public_local_timeline +#INSTANCE_PUBLIC_LOCAL_TIMELINE="false" + +# Defaults to "". +# +# See: https://docs.pixelfed.org/technical-documentation/config/#banned_usernames +#BANNED_USERNAMES= + +# Defaults to "false". +# +# See: https://docs.pixelfed.org/technical-documentation/config/#stories_enabled +#STORIES_ENABLED="false" + +# Defaults to "false". +# +# Level is hardcoded to 1. +# +# See: https://docs.pixelfed.org/technical-documentation/config/#restricted_instance +#RESTRICTED_INSTANCE="false" + +############################################################### +# Database configuration +############################################################### + +# Here you may specify which of the database connections below you wish to use as your default connection for all database work. +# +# Of course you may use many connections at once using the database library. +# +# Possible values: +# +# - "sqlite" +# - "mysql" (default) +# - "pgsql" +# - "sqlsrv" +# +# See: https://docs.pixelfed.org/technical-documentation/config/#db_connection +DB_CONNECTION="mysql" + +# See: https://docs.pixelfed.org/technical-documentation/config/#db_host +DB_HOST="db" + +# See: https://docs.pixelfed.org/technical-documentation/config/#db_username +DB_USERNAME="pixelfed" + +# See: https://docs.pixelfed.org/technical-documentation/config/#db_password +DB_PASSWORD="__CHANGE_ME__" + +# See: https://docs.pixelfed.org/technical-documentation/config/#db_database +DB_DATABASE="pixelfed_prod" + +# Use "3306" for MySQL/MariaDB and "5432" for PostgreeSQL +# +# See: https://docs.pixelfed.org/technical-documentation/config/#db_port +DB_PORT="3306" + +############################################################### +# Mail configuration +############################################################### + +# Laravel supports both SMTP and PHP’s “mail” function as drivers for the sending of e-mail. +# You may specify which one you’re using throughout your application here. +# +# Possible values: +# +# "smtp" (default) +# "sendmail" +# "mailgun" +# "mandrill" +# "ses" +# "sparkpost" +# "log" +# "array" +# +# See: https://docs.pixelfed.org/technical-documentation/config/#mail_driver +#MAIL_DRIVER="smtp" + +# The host address of the SMTP server used by your applications. +# +# A default option is provided that is compatible with the Mailgun mail service which will provide reliable deliveries. +# +# Defaults to "smtp.mailgun.org". +# +# See: https://docs.pixelfed.org/technical-documentation/config/#mail_host +#MAIL_HOST="smtp.mailgun.org" + +# This is the SMTP port used by your application to deliver e-mails to users of the application. +# +# Like the host we have set this value to stay compatible with the Mailgun e-mail application by default. +# +# Defaults to 587. +# +# See: https://docs.pixelfed.org/technical-documentation/config/#mail_port +#MAIL_PORT="587" + +# You may wish for all e-mails sent by your application to be sent from the same address. +# +# Here, you may specify a name and address that is used globally for all e-mails that are sent by your application. +# +# Defaults to "hello@example.com". +# +# See: https://docs.pixelfed.org/technical-documentation/config/#mail_from_address +MAIL_FROM_ADDRESS="hello@${APP_DOMAIN}" + +# Defaults to "Example". +# +# See: https://docs.pixelfed.org/technical-documentation/config/#mail_from_name +MAIL_FROM_NAME="Pixelfed @ ${APP_DOMAIN}" + +# If your SMTP server requires a username for authentication, you should set it here. +# +# This will get used to authenticate with your server on connection. +# You may also set the “password” value below this one. +# +# Defaults to "". +# +# See: https://docs.pixelfed.org/technical-documentation/config/#mail_username +#MAIL_USERNAME= + +# Defaults to "". +# +# See: https://docs.pixelfed.org/technical-documentation/config/#mail_password +#MAIL_PASSWORD= + +# Here you may specify the encryption protocol that should be used when the application send e-mail messages. +# +# A sensible default using the transport layer security protocol should provide great security. +# +# Defaults to "tls". +# +# See: https://docs.pixelfed.org/technical-documentation/config/#mail_encryption +#MAIL_ENCRYPTION="tls" + +############################################################### +# Redis configuration +############################################################### + +# Defaults to "phpredis". +# +# See: https://docs.pixelfed.org/technical-documentation/config/#db_username +#REDIS_CLIENT="phpredis" + +# Defaults to "tcp". +# +# See: https://docs.pixelfed.org/technical-documentation/config/#redis_scheme +#REDIS_SCHEME="tcp" + +# Defaults to "localhost". +# +# See: https://docs.pixelfed.org/technical-documentation/config/#redis_host +REDIS_HOST="cache" + +# Defaults to null. +# +# See: https://docs.pixelfed.org/technical-documentation/config/#redis_password +#REDIS_PASSWORD= + +# Defaults to 6379. +# +# See: https://docs.pixelfed.org/technical-documentation/config/#redis_port +REDIS_PORT="6379" + +# Defaults to 0. +# +# See: https://docs.pixelfed.org/technical-documentation/config/#redis_database +#REDIS_DATABASE="0" + +############################################################### +# Cache settings +############################################################### + +# This option controls the default cache connection that gets used while using this caching library. +# +# This connection is used when another is not explicitly specified when executing a given caching function. +# +# Possible values: +# - "apc" +# - "array" +# - "database" +# - "file" (default) +# - "memcached" +# - "redis" +# +# See: https://docs.pixelfed.org/technical-documentation/config/#cache_driver +CACHE_DRIVER="redis" + +# Defaults to ${APP_NAME}_cache, or laravel_cache if no APP_NAME is set. +# +# See: https://docs.pixelfed.org/technical-documentation/config/#cache_prefix +# CACHE_PREFIX="{APP_NAME}_cache" + +############################################################### +# Horizon settings +############################################################### + +# This prefix will be used when storing all Horizon data in Redis. +# +# You may modify the prefix when you are running multiple installations +# of Horizon on the same server so that they don’t have problems. +# +# Defaults to "horizon-". +# +# See: https://docs.pixelfed.org/technical-documentation/config/#horizon_prefix +#HORIZON_PREFIX="horizon-" + +# Defaults to "false". +# +# See: https://docs.pixelfed.org/technical-documentation/config/#horizon_darkmode +#HORIZON_DARKMODE="false" + +# This value (in MB) describes the maximum amount of memory (in MB) the Horizon worker +# may consume before it is terminated and restarted. +# +# You should set this value according to the resources available to your server. +# +# Defaults to "64". +#HORIZON_MEMORY_LIMIT="64" + +# See: https://docs.pixelfed.org/technical-documentation/config/#horizon_balance_strategy +#HORIZON_BALANCE_STRATEGY="auto" + +# See: https://docs.pixelfed.org/technical-documentation/config/#horizon_min_processes +#HORIZON_MIN_PROCESSES="1" + +# See: https://docs.pixelfed.org/technical-documentation/config/#horizon_max_processes +#HORIZON_MAX_PROCESSES="20" + +# See: https://docs.pixelfed.org/technical-documentation/config/#horizon_supervisor_memory +#HORIZON_SUPERVISOR_MEMORY="64" + +# See: https://docs.pixelfed.org/technical-documentation/config/#horizon_supervisor_tries +#HORIZON_SUPERVISOR_TRIES="3" + +# See: https://docs.pixelfed.org/technical-documentation/config/#horizon_supervisor_nice +#HORIZON_SUPERVISOR_NICE="0" + +# See: https://docs.pixelfed.org/technical-documentation/config/#horizon_supervisor_timeout +#HORIZON_SUPERVISOR_TIMEOUT="300" + +############################################################### +# Experiments +############################################################### + +# Text only posts (alpha). +# +# Defaults to "false". +# +# See: https://docs.pixelfed.org/technical-documentation/config/#exp_top +#EXP_TOP="false" + +# Poll statuses (alpha). +# +# Defaults to "false". +# +# See: https://docs.pixelfed.org/technical-documentation/config/#exp_polls +#EXP_POLLS="false" + +# Cached public timeline for larger instances (beta). +# +# Defaults to "false". +# +# See: https://docs.pixelfed.org/technical-documentation/config/#exp_cpt +#EXP_CPT="false" + +# Enforce Mastoapi Compatibility (alpha). +# +# Defaults to "true". +# +# See: https://docs.pixelfed.org/technical-documentation/config/#exp_emc +#EXP_EMC="true" + +############################################################### +# ActivityPub confguration +############################################################### + +# Defaults to "false". +# +# See: https://docs.pixelfed.org/technical-documentation/config/#activity_pub +#ACTIVITY_PUB="false" + +# Defaults to "true". +# +# See: https://docs.pixelfed.org/technical-documentation/config/#ap_remote_follow +#AP_REMOTE_FOLLOW="true" + +# Defaults to "true". +# +# See: https://docs.pixelfed.org/technical-documentation/config/#ap_sharedinbox +#AP_SHAREDINBOX="true" + +# Defaults to "true". +# +# See: https://docs.pixelfed.org/technical-documentation/config/#ap_inbox +#AP_INBOX="true" + +# Defaults to "true". +# +# See: https://docs.pixelfed.org/technical-documentation/config/#ap_outbox +#AP_OUTBOX="true" + +############################################################### +# Federation confguration +############################################################### + +# Defaults to "true". +# +# See: https://docs.pixelfed.org/technical-documentation/config/#atom_feeds +#ATOM_FEEDS="true" + +# Defaults to "true". +# +# See: https://docs.pixelfed.org/technical-documentation/config/#nodeinfo +#NODEINFO="true" + +# Defaults to "true". +# +# See: https://docs.pixelfed.org/technical-documentation/config/#webfinger +#WEBFINGER="true" + +############################################################### +# Storage (cloud) +############################################################### + +# Store media on object storage like S3, Digital Ocean Spaces, Rackspace +# +# Defaults to "false". +# +# See: https://docs.pixelfed.org/technical-documentation/config/#pf_enable_cloud +#PF_ENABLE_CLOUD="false" + +# Many applications store files both locally and in the cloud. +# +# For this reason, you may specify a default “cloud” driver here. +# This driver will be bound as the Cloud disk implementation in the container. +# +# Defaults to "s3". +# +# See: https://docs.pixelfed.org/technical-documentation/config/#filesystem_cloud +#FILESYSTEM_CLOUD="s3" + +# Defaults to true. +# +# See: https://docs.pixelfed.org/technical-documentation/config/#media_delete_local_after_cloud +#MEDIA_DELETE_LOCAL_AFTER_CLOUD="true" + +############################################################### +# Storage (cloud) - S3 +############################################################### + +# See: https://docs.pixelfed.org/technical-documentation/config/#aws_access_key_id +#AWS_ACCESS_KEY_ID= + +# See: https://docs.pixelfed.org/technical-documentation/config/#aws_secret_access_key +#AWS_SECRET_ACCESS_KEY= + +# See: https://docs.pixelfed.org/technical-documentation/config/#aws_default_region +#AWS_DEFAULT_REGION= + +# See: https://docs.pixelfed.org/technical-documentation/config/#aws_bucket +#AWS_BUCKET= + +# See: https://docs.pixelfed.org/technical-documentation/config/#aws_url +#AWS_URL= + +# See: https://docs.pixelfed.org/technical-documentation/config/#aws_endpoint +#AWS_ENDPOINT= + +# See: https://docs.pixelfed.org/technical-documentation/config/#aws_use_path_style_endpoint +#AWS_USE_PATH_STYLE_ENDPOINT="false" + +############################################################### +# COSTAR - Confirm Object Sentiment Transform and Reduce +############################################################### + +# Comma-separated list of domains to block. +# +# Defaults to null +# +# See: https://docs.pixelfed.org/technical-documentation/config/#cs_blocked_domains +#CS_BLOCKED_DOMAINS= + +# Comma-separated list of domains to add warnings. +# +# Defaults to null. +# +# See: https://docs.pixelfed.org/technical-documentation/config/#cs_cw_domains +#CS_CW_DOMAINS= + +# Comma-separated list of domains to remove from public timelines. +# +# Defaults to null. +# +# See: https://docs.pixelfed.org/technical-documentation/config/#cs_unlisted_domains +#CS_UNLISTED_DOMAINS= + +# Comma-separated list of keywords to block. +# +# Defaults to null. +# +# See: https://docs.pixelfed.org/technical-documentation/config/#cs_blocked_keywords +#CS_BLOCKED_KEYWORDS= + +# Comma-separated list of keywords to add warnings. +# +# Defaults to null. +# +# See: https://docs.pixelfed.org/technical-documentation/config/#cs_cw_keywords +#CS_CW_KEYWORDS= + +# Comma-separated list of keywords to remove from public timelines. +# +# Defaults to null. +# +# See: https://docs.pixelfed.org/technical-documentation/config/#cs_unlisted_keywords +#CS_UNLISTED_KEYWORDS= + +# Defaults to null. +# +# See: https://docs.pixelfed.org/technical-documentation/config/#cs_blocked_actor +#CS_BLOCKED_ACTOR= + +# Defaults to null. +# +# See: https://docs.pixelfed.org/technical-documentation/config/#cs_cw_actor +#CS_CW_ACTOR= + +# Defaults to null. +# +# See: https://docs.pixelfed.org/technical-documentation/config/#cs_unlisted_actor +#CS_UNLISTED_ACTOR= + +############################################################### +# Media +############################################################### + +# Defaults to false. +# +# See: https://docs.pixelfed.org/technical-documentation/config/#media_exif_database +MEDIA_EXIF_DATABASE="true" + +# Pixelfed supports GD or ImageMagick to process images. +# +# Defaults to "gd". +# +# Possible values: +# - "gd" (default) +# - "imagick" +# +# See: https://docs.pixelfed.org/technical-documentation/config/#image_driver +#IMAGE_DRIVER="gd" + +############################################################### +# Logging +############################################################### + +# Possible values: +# +# - "stack" (default) +# - "single" +# - "daily" +# - "slack" +# - "stderr" +# - "syslog" +# - "errorlog" +# - "null" +# - "emergency" +# - "media" +LOG_CHANNEL="stderr" + +# Used by single, stderr and syslog. +# +# Defaults to "debug" for all of those. +# +# See: https://docs.pixelfed.org/technical-documentation/config/#log_level +#LOG_LEVEL="debug" + +# Used by stderr. +# +# Defaults to "". +# +# See: https://docs.pixelfed.org/technical-documentation/config/#log_stderr_formatter +#LOG_STDERR_FORMATTER= + +# Used by slack. +# +# Defaults to "". +# +# See: https://docs.pixelfed.org/technical-documentation/config/#log_slack_webhook_url +#LOG_SLACK_WEBHOOK_URL= + +############################################################### +# Broadcasting settings +############################################################### + +# This option controls the default broadcaster that will be used by the framework when an event needs to be broadcast. +# +# Possible values: +# - "pusher" +# - "redis" +# - "log" +# - "null" (default) +# +# See: https://docs.pixelfed.org/technical-documentation/config/#broadcast_driver +#BROADCAST_DRIVER= + +############################################################### +# Other settings +############################################################### + +# Defaults to true. +# +# See: https://docs.pixelfed.org/technical-documentation/config/#restrict_html_types +#RESTRICT_HTML_TYPES="true" + +############################################################### +# Queue configuration +############################################################### + +# Possible values: +# - "sync" (default) +# - "database" +# - "beanstalkd" +# - "sqs" +# - "redis" +# - "null" +# +# See: https://docs.pixelfed.org/technical-documentation/config/#queue_driver +QUEUE_DRIVER="redis" + +############################################################### +# Queue (SQS) configuration +############################################################### + +# Defaults to "your-public-key". +# +# See: https://docs.pixelfed.org/technical-documentation/config/#sqs_key +#SQS_KEY="your-public-key" + +# Defaults to "your-secret-key". +# +# See: https://docs.pixelfed.org/technical-documentation/config/#sqs_secret +#SQS_SECRET="your-secret-key" + +# Defaults to "https://sqs.us-east-1.amazonaws.com/your-account-id". +# +# See: https://docs.pixelfed.org/technical-documentation/config/#sqs_prefix +#SQS_PREFIX= + +# Defaults to "your-queue-name". +# +# https://docs.pixelfed.org/technical-documentation/config/#sqs_queue +#SQS_QUEUE="your-queue-name" + +# Defaults to "us-east-1". +# +# See: https://docs.pixelfed.org/technical-documentation/config/#sqs_region +#SQS_REGION="us-east-1" + +############################################################### +# Session configuration +############################################################### + +# This option controls the default session “driver” that will be used on requests. +# +# By default, we will use the lightweight native driver but you may specify any of the other wonderful drivers provided here. +# +# Possible values: +# - "file" +# - "cookie" +# - "database" (default) +# - "apc" +# - "memcached" +# - "redis" +# - "array" +SESSION_DRIVER="redis" + +# Here you may specify the number of minutes that you wish the session to be allowed to remain idle before it expires. +# +# If you want them to immediately expire on the browser closing, set that option. +# +# Defaults to 86400. +# +# See: https://docs.pixelfed.org/technical-documentation/config/#session_lifetime +#SESSION_LIFETIME="86400" + +# Here you may change the domain of the cookie used to identify a session in your application. +# +# This will determine which domains the cookie is available to in your application. +# +# A sensible default has been set. +# +# Defaults to the value of APP_DOMAIN, or null. +# +# See: https://docs.pixelfed.org/technical-documentation/config/#session_domain +#SESSION_DOMAIN="${APP_DOMAIN}" + +############################################################### +# Proxy configuration +############################################################### + +# Set trusted proxy IP addresses. +# +# Both IPv4 and IPv6 addresses are supported, along with CIDR notation. +# +# The “*” character is syntactic sugar within TrustedProxy to trust any +# proxy that connects directly to your server, a requirement when you cannot +# know the address of your proxy (e.g. if using Rackspace balancers). +# +# The “**” character is syntactic sugar within TrustedProxy to trust not just any +# proxy that connects directly to your server, but also proxies that connect to those proxies, +# and all the way back until you reach the original source IP. It will mean that +# $request->getClientIp() always gets the originating client IP, no matter how many proxies +# that client’s request has subsequently passed through. +# +# Defaults to "*". +# +# See: https://docs.pixelfed.org/technical-documentation/config/#trust_proxies +TRUST_PROXIES="*" + +############################################################### +# Passport configuration +############################################################### +# +# Passport uses encryption keys while generating secure access tokens +# for your application. +# +# By default, the keys are stored as local files but can be set via environment +# variables when that is more convenient. + +# See: https://docs.pixelfed.org/technical-documentation/config/#passport_private_key +#PASSPORT_PRIVATE_KEY= + +# See: https://docs.pixelfed.org/technical-documentation/config/#passport_public_key +#PASSPORT_PUBLIC_KEY= + +############################################################### +# PHP configuration +############################################################### + +# See: https://www.php.net/manual/en/ini.core.php#ini.memory-limit +#PHP_MEMORY_LIMIT="128M" + +############################################################### +# MySQL DB container configuration (DO NOT CHANGE) +############################################################### +# +# See "Environment Variables" at https://hub.docker.com/_/mysql + +MYSQL_ROOT_PASSWORD="${DB_PASSWORD}" +MYSQL_USER="${DB_USERNAME}" +MYSQL_PASSWORD="${DB_PASSWORD}" +MYSQL_DATABASE="${DB_DATABASE}" + +############################################################### +# MySQL (MariaDB) DB container configuration (DO NOT CHANGE) +############################################################### +# +# See "Start a mariadb server instance with user, password and database" at https://hub.docker.com/_/mariadb + +MARIADB_ROOT_PASSWORD="${DB_PASSWORD}" +MARIADB_USER="${DB_USERNAME}" +MARIADB_PASSWORD="${DB_PASSWORD}" +MARIADB_DATABASE="${DB_DATABASE}" + +############################################################### +# PostgreSQL DB container configuration (DO NOT CHANGE) +############################################################### +# +# See "Environment Variables" at https://hub.docker.com/_/postgres + +POSTGRES_USER="${DB_USERNAME}" +POSTGRES_PASSWORD="${DB_PASSWORD}" +POSTGRES_DB="${DB_DATABASE}" + +############################################################### +# Docker Specific configuration +############################################################### + +# Image to pull the Pixelfed Docker images from +# +# Possible values: +# - "ghcr.io/pixelfed/pixelfed" to pull from GitHub +# - "pixelfed/pixelfed" to pull from DockerHub +# +DOCKER_IMAGE="ghcr.io/jippi/pixelfed" + +# Port that Redis will listen on *outside* the container (e.g. the host machine) +DOCKER_REDIS_PORT_EXTERNAL="${REDIS_PORT}" + +# Port that the database will listen on *outside* the container (e.g. the host machine) +# +# Use "3306" for MySQL/MariaDB and "5432" for PostgreeSQL +DOCKER_DB_PORT_EXTERNAL="${DB_PORT}" + +# Port that the web will listen on *outside* the container (e.g. the host machine) +DOCKER_WEB_PORT_EXTERNAL="8080" diff --git a/contrib/docker-compose/README.md b/contrib/docker-compose/README.md new file mode 100644 index 000000000..361c2622b --- /dev/null +++ b/contrib/docker-compose/README.md @@ -0,0 +1,13 @@ +# Pixelfed + Docker + Docker Compose + +## Prerequisites + +* One of the `docker-compose.yml` files in this directory +* A copy of the `example.env` file + +In order to set configuration, please use a .env file in your compose project directory (the same directory as your docker-compose.yml), and set database options, application +name, key, and other settings there. + +A list of available settings is available in .env.example + +The services should scale properly across a swarm cluster if the volumes are properly shared between cluster members. diff --git a/contrib/docker-compose/docker-compose.apache.yml b/contrib/docker-compose/docker-compose.apache.yml new file mode 100644 index 000000000..ff7734797 --- /dev/null +++ b/contrib/docker-compose/docker-compose.apache.yml @@ -0,0 +1,59 @@ +--- +version: "3" + +services: + web: + image: "${DOCKER_IMAGE}:${DOCKER_TAG}" + restart: unless-stopped + env_file: + - "./.env" + volumes: + - "./.env:/var/www/.env" + - "${DOCKER_DATA_ROOT}/pixelfed/bootstrap:/var/www/bootstrap" + - "${DOCKER_DATA_ROOT}/pixelfed/storage:/var/www/storage" + ports: + - "${DOCKER_WEB_PORT_EXTERNAL}:80" + depends_on: + - db + - redis + + worker: + image: "${DOCKER_IMAGE}:${DOCKER_TAG}" + command: gosu www-data php artisan horizon + restart: unless-stopped + env_file: + - "./.env" + volumes: + - "./.env:/var/www/.env" + - "${DOCKER_DATA_ROOT}/pixelfed/bootstrap:/var/www/bootstrap" + - "${DOCKER_DATA_ROOT}/pixelfed/storage:/var/www/storage" + depends_on: + - db + - redis + + db: + image: mariadb:11.2 + command: --default-authentication-plugin=mysql_native_password + restart: unless-stopped + env_file: + - "./.env" + volumes: + - "${DOCKER_DATA_ROOT}/db:/var/lib/mysql" + ports: + - "${DOCKER_DB_PORT_EXTERNAL}:3306" + + redis: + image: redis:7 + restart: unless-stopped + env_file: + - "./.env" + volumes: + - "${DOCKER_CONFIG_ROOT}/redis:/etc/redis" + - "${DOCKER_DATA_ROOT}/redis:/data" + ports: + - "${DOCKER_REDIS_PORT_EXTERNAL}:6399" + healthcheck: + interval: 10s + timeout: 5s + retries: 2 + test: ["CMD", "redis-cli", "-p", "6399", "ping"] diff --git a/contrib/docker/shared/root/docker/entrypoint.d/10-storage.sh b/contrib/docker/shared/root/docker/entrypoint.d/10-storage.sh index fc952ea3a..b9809e24c 100755 --- a/contrib/docker/shared/root/docker/entrypoint.d/10-storage.sh +++ b/contrib/docker/shared/root/docker/entrypoint.d/10-storage.sh @@ -4,7 +4,7 @@ source /docker/helpers.sh entrypoint-set-script-name "$0" # Copy the [storage/] skeleton files over the "real" [storage/] directory so assets are updated between versions -run-as-runtime-user cp --recursive storage.skel/ storage/ +run-as-runtime-user cp --recursive storage.skel/. storage/. # Ensure storage linkk are correctly configured run-as-runtime-user php artisan storage:link diff --git a/contrib/docker/shared/root/docker/templates/usr/local/etc/php/php.ini b/contrib/docker/shared/root/docker/templates/usr/local/etc/php/php.ini index 81ba3d207..c34266630 100644 --- a/contrib/docker/shared/root/docker/templates/usr/local/etc/php/php.ini +++ b/contrib/docker/shared/root/docker/templates/usr/local/etc/php/php.ini @@ -376,7 +376,7 @@ zend.exception_ignore_args = On ; threat in any way, but it makes it possible to determine whether you use PHP ; on your server or not. ; http://php.net/expose-php -expose_php = On +expose_php = Off ;;;;;;;;;;;;;;;;;;; ; Resource Limits ; @@ -406,7 +406,7 @@ max_input_time = 60 ; Maximum amount of memory a script may consume (128MB) ; http://php.net/memory-limit -memory_limit = 128M +memory_limit = {{ getenv "PHP_MEMORY_LIMIT" "128M" }} ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; Error handling and logging ; @@ -947,7 +947,7 @@ cli_server.color = On [Date] ; Defines the default timezone used by the date functions ; http://php.net/date.timezone -;date.timezone = +date.timezone = {{ getenv "TZ" "UTC" }} ; http://php.net/date.default-latitude ;date.default_latitude = 31.7667 From 215b49ea3d599d4cfb08bb874a8dd94e057b5f0f Mon Sep 17 00:00:00 2001 From: Christian Winther Date: Fri, 5 Jan 2024 16:27:11 +0000 Subject: [PATCH 021/173] rename2 --- contrib/docker-compose/.env | 4 ++-- contrib/docker-compose/README.md | 17 ++++++++++++----- ...er-compose.apache.yml => docker-compose.yml} | 0 3 files changed, 14 insertions(+), 7 deletions(-) rename contrib/docker-compose/{docker-compose.apache.yml => docker-compose.yml} (100%) diff --git a/contrib/docker-compose/.env b/contrib/docker-compose/.env index 4cfde052b..076edf09b 100644 --- a/contrib/docker-compose/.env +++ b/contrib/docker-compose/.env @@ -113,7 +113,7 @@ APP_TIMEZONE="${TZ}" # Defaults to "en". # # See: https://docs.pixelfed.org/technical-documentation/config/#app_fallback_locale -APP_FALLBACK_LOCALE="en" +#APP_FALLBACK_LOCALE="en" # See: https://docs.pixelfed.org/technical-documentation/config/#limit_account_size #LIMIT_ACCOUNT_SIZE="true" @@ -368,7 +368,7 @@ MAIL_FROM_NAME="Pixelfed @ ${APP_DOMAIN}" # Defaults to "localhost". # # See: https://docs.pixelfed.org/technical-documentation/config/#redis_host -REDIS_HOST="cache" +REDIS_HOST="redis" # Defaults to null. # diff --git a/contrib/docker-compose/README.md b/contrib/docker-compose/README.md index 361c2622b..6c57c43d2 100644 --- a/contrib/docker-compose/README.md +++ b/contrib/docker-compose/README.md @@ -3,11 +3,18 @@ ## Prerequisites * One of the `docker-compose.yml` files in this directory -* A copy of the `example.env` file +* A copy of the `example.env` file named `.env` next to `docker-compose.yml` -In order to set configuration, please use a .env file in your compose project directory (the same directory as your docker-compose.yml), and set database options, application -name, key, and other settings there. +Your folder should look like this -A list of available settings is available in .env.example +```plain +. +├── .env +└── docker-compose.yml +``` -The services should scale properly across a swarm cluster if the volumes are properly shared between cluster members. +## Modifying your settings (`.env` file) + +* `APP_NAME` +* `APP_DOMAIN` +* `DB_PASSWORD` diff --git a/contrib/docker-compose/docker-compose.apache.yml b/contrib/docker-compose/docker-compose.yml similarity index 100% rename from contrib/docker-compose/docker-compose.apache.yml rename to contrib/docker-compose/docker-compose.yml From 052c11882c0da9ea4ddd50b6141242bba99d1e01 Mon Sep 17 00:00:00 2001 From: Christian Winther Date: Fri, 5 Jan 2024 16:33:08 +0000 Subject: [PATCH 022/173] tweak 10-storage.sh --- contrib/docker/shared/root/docker/entrypoint.d/10-storage.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/contrib/docker/shared/root/docker/entrypoint.d/10-storage.sh b/contrib/docker/shared/root/docker/entrypoint.d/10-storage.sh index b9809e24c..6677c313f 100755 --- a/contrib/docker/shared/root/docker/entrypoint.d/10-storage.sh +++ b/contrib/docker/shared/root/docker/entrypoint.d/10-storage.sh @@ -4,7 +4,7 @@ source /docker/helpers.sh entrypoint-set-script-name "$0" # Copy the [storage/] skeleton files over the "real" [storage/] directory so assets are updated between versions -run-as-runtime-user cp --recursive storage.skel/. storage/. +cp --recursive storage.skel/. storage/ # Ensure storage linkk are correctly configured -run-as-runtime-user php artisan storage:link +php artisan storage:link From c1fbccb07c6419dd809c9a273af33868b6c43a73 Mon Sep 17 00:00:00 2001 From: Christian Winther Date: Fri, 5 Jan 2024 16:52:00 +0000 Subject: [PATCH 023/173] bootstrapping worked --- .dockerignore | 9 ++++++--- contrib/docker-compose/.env | 2 +- contrib/docker-compose/docker-compose.yml | 12 ++++++++++-- .../shared/root/docker/entrypoint.d/10-storage.sh | 7 +++++-- 4 files changed, 22 insertions(+), 8 deletions(-) diff --git a/.dockerignore b/.dockerignore index bc5af5a21..a4f4ff035 100644 --- a/.dockerignore +++ b/.dockerignore @@ -1,6 +1,9 @@ -data -docker-compose*.yml .dockerignore +.env .git .gitignore -.env +contrib/docker-compose/.env +contrib/docker-compose/config +contrib/docker-compose/data +data +docker-compose*.yml diff --git a/contrib/docker-compose/.env b/contrib/docker-compose/.env index 076edf09b..9ad25eeff 100644 --- a/contrib/docker-compose/.env +++ b/contrib/docker-compose/.env @@ -41,7 +41,7 @@ APP_NAME="Pixelfed Prod" # Application domains used for routing. # # See: https://docs.pixelfed.org/technical-documentation/config/#app_domain -APP_DOMAIN="your-domain-here-dot-com" +APP_DOMAIN="pixelfed-test.jippi.dev" # This URL is used by the console to properly generate URLs when using the Artisan command line tool. # You should set this to the root of your application so that it is used when running Artisan tasks. diff --git a/contrib/docker-compose/docker-compose.yml b/contrib/docker-compose/docker-compose.yml index ff7734797..8df0777b3 100644 --- a/contrib/docker-compose/docker-compose.yml +++ b/contrib/docker-compose/docker-compose.yml @@ -4,12 +4,16 @@ version: "3" services: web: image: "${DOCKER_IMAGE}:${DOCKER_TAG}" + build: + context: ../.. + dockerfile: contrib/docker/Dockerfile + target: apache-runtime restart: unless-stopped env_file: - "./.env" volumes: - "./.env:/var/www/.env" - - "${DOCKER_DATA_ROOT}/pixelfed/bootstrap:/var/www/bootstrap" + - "${DOCKER_DATA_ROOT}/pixelfed/cache:/var/www/bootstrap/cache" - "${DOCKER_DATA_ROOT}/pixelfed/storage:/var/www/storage" ports: - "${DOCKER_WEB_PORT_EXTERNAL}:80" @@ -19,13 +23,17 @@ services: worker: image: "${DOCKER_IMAGE}:${DOCKER_TAG}" + build: + context: ../.. + dockerfile: contrib/docker/Dockerfile + target: apache-runtime command: gosu www-data php artisan horizon restart: unless-stopped env_file: - "./.env" volumes: - "./.env:/var/www/.env" - - "${DOCKER_DATA_ROOT}/pixelfed/bootstrap:/var/www/bootstrap" + - "${DOCKER_DATA_ROOT}/pixelfed/cache:/var/www/bootstrap/cache" - "${DOCKER_DATA_ROOT}/pixelfed/storage:/var/www/storage" depends_on: - db diff --git a/contrib/docker/shared/root/docker/entrypoint.d/10-storage.sh b/contrib/docker/shared/root/docker/entrypoint.d/10-storage.sh index 6677c313f..f0e467973 100755 --- a/contrib/docker/shared/root/docker/entrypoint.d/10-storage.sh +++ b/contrib/docker/shared/root/docker/entrypoint.d/10-storage.sh @@ -3,8 +3,11 @@ source /docker/helpers.sh entrypoint-set-script-name "$0" +run-as-current-user chown --verbose ${RUNTIME_UID}:${RUNTIME_GID} "./bootstrap/cache" +run-as-current-user chown --verbose ${RUNTIME_UID}:${RUNTIME_GID} "./storage" + # Copy the [storage/] skeleton files over the "real" [storage/] directory so assets are updated between versions -cp --recursive storage.skel/. storage/ +run-as-runtime-user cp --recursive storage.skel/. ./storage/ # Ensure storage linkk are correctly configured -php artisan storage:link +run-as-runtime-user php artisan storage:link From c4404590f233866da4d3bef6b4635bc8d5baac26 Mon Sep 17 00:00:00 2001 From: Christian Winther Date: Fri, 5 Jan 2024 17:29:45 +0000 Subject: [PATCH 024/173] add first time setup logic --- contrib/docker-compose/.env | 4 +- ...orage-permissions.sh => 01-permissions.sh} | 5 +++ .../root/docker/entrypoint.d/10-storage.sh | 3 -- .../entrypoint.d/11-first-time-setup.sh | 45 +++++++++++++++++++ 4 files changed, 52 insertions(+), 5 deletions(-) rename contrib/docker/shared/root/docker/entrypoint.d/{15-storage-permissions.sh => 01-permissions.sh} (68%) create mode 100755 contrib/docker/shared/root/docker/entrypoint.d/11-first-time-setup.sh diff --git a/contrib/docker-compose/.env b/contrib/docker-compose/.env index 9ad25eeff..f371e21ef 100644 --- a/contrib/docker-compose/.env +++ b/contrib/docker-compose/.env @@ -33,7 +33,7 @@ TZ="UTC" # Please do this before deploying an application! # # See: https://docs.pixelfed.org/technical-documentation/config/#app_key -APP_KEY="" +APP_KEY=base64:IvvWCuLmAAcyPBzDI+IH6OxnU9w2kTSYZrcg6F4m7Uk= # See: https://docs.pixelfed.org/technical-documentation/config/#app_name-1 APP_NAME="Pixelfed Prod" @@ -264,7 +264,7 @@ DB_HOST="db" DB_USERNAME="pixelfed" # See: https://docs.pixelfed.org/technical-documentation/config/#db_password -DB_PASSWORD="__CHANGE_ME__" +DB_PASSWORD="helloworld" # See: https://docs.pixelfed.org/technical-documentation/config/#db_database DB_DATABASE="pixelfed_prod" diff --git a/contrib/docker/shared/root/docker/entrypoint.d/15-storage-permissions.sh b/contrib/docker/shared/root/docker/entrypoint.d/01-permissions.sh similarity index 68% rename from contrib/docker/shared/root/docker/entrypoint.d/15-storage-permissions.sh rename to contrib/docker/shared/root/docker/entrypoint.d/01-permissions.sh index 30a58c5a9..81d422ecd 100755 --- a/contrib/docker/shared/root/docker/entrypoint.d/15-storage-permissions.sh +++ b/contrib/docker/shared/root/docker/entrypoint.d/01-permissions.sh @@ -3,6 +3,11 @@ source /docker/helpers.sh entrypoint-set-script-name "$0" +# Ensure the two Docker volumes are owned by the runtime user +run-as-current-user chown --verbose ${RUNTIME_UID}:${RUNTIME_GID} "./.env" +run-as-current-user chown --verbose ${RUNTIME_UID}:${RUNTIME_GID} "./bootstrap/cache" +run-as-current-user chown --verbose ${RUNTIME_UID}:${RUNTIME_GID} "./storage" + # Optionally fix ownership of configured paths : ${ENTRYPOINT_ENSURE_OWNERSHIP_PATHS:=""} diff --git a/contrib/docker/shared/root/docker/entrypoint.d/10-storage.sh b/contrib/docker/shared/root/docker/entrypoint.d/10-storage.sh index f0e467973..bb2f61f0a 100755 --- a/contrib/docker/shared/root/docker/entrypoint.d/10-storage.sh +++ b/contrib/docker/shared/root/docker/entrypoint.d/10-storage.sh @@ -3,9 +3,6 @@ source /docker/helpers.sh entrypoint-set-script-name "$0" -run-as-current-user chown --verbose ${RUNTIME_UID}:${RUNTIME_GID} "./bootstrap/cache" -run-as-current-user chown --verbose ${RUNTIME_UID}:${RUNTIME_GID} "./storage" - # Copy the [storage/] skeleton files over the "real" [storage/] directory so assets are updated between versions run-as-runtime-user cp --recursive storage.skel/. ./storage/ diff --git a/contrib/docker/shared/root/docker/entrypoint.d/11-first-time-setup.sh b/contrib/docker/shared/root/docker/entrypoint.d/11-first-time-setup.sh new file mode 100755 index 000000000..0e30e74ac --- /dev/null +++ b/contrib/docker/shared/root/docker/entrypoint.d/11-first-time-setup.sh @@ -0,0 +1,45 @@ +#!/bin/bash +source /docker/helpers.sh + +entrypoint-set-script-name "$0" + +# if the script is running in another container, wait for it to complete +while [ -e "./storage/docker-first-time-is-running" ]; do + sleep 1 +done + +# We got the lock! +touch "./storage/docker-first-time-is-running" + +# Make sure to clean up on exit +trap "rm -f ./storage/docker-first-time-is-running" EXIT + +if [ ! -e "./storage/docker-storage-link-has-run" ]; then + run-as-runtime-user php artisan storage:link + touch "./storage/docker-storage-link-has-run" +fi + +if [ ! -e "./storage/docker-key-generate-has-run" ]; then + run-as-runtime-user php artisan key:generate + touch "./storage/docker-key-generate-has-run" +fi + +if [ ! -e "./storage/docker-migrate-has-run" ]; then + run-as-runtime-user php artisan migrate --force + touch "./storage/docker-migrate-has-run" +fi + +if [ ! -e "./storage/docker-import-cities-has-run" ]; then + run-as-runtime-user php artisan import:cities + touch "./storage/docker-import-cities-has-run" +fi + +# if [ ! -e "./storage/docker-instance-actor-has-run" ]; then +# run-as-runtime-user php artisan instance:actor +# touch "./storage/docker-instance-actor-has-run" +# fi + +# if [ ! -e "./storage/docker-passport-keys-has-run" ]; then +# run-as-runtime-user php artisan instance:actor +# touch "./storage/docker-passport-keys-has-run" +# fi From d8765339910f00e43a77a06a2ca9e03f4ec55b44 Mon Sep 17 00:00:00 2001 From: Christian Winther Date: Fri, 5 Jan 2024 17:30:30 +0000 Subject: [PATCH 025/173] remove tmp token --- contrib/docker-compose/.env | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contrib/docker-compose/.env b/contrib/docker-compose/.env index f371e21ef..7c70f3cf6 100644 --- a/contrib/docker-compose/.env +++ b/contrib/docker-compose/.env @@ -33,7 +33,7 @@ TZ="UTC" # Please do this before deploying an application! # # See: https://docs.pixelfed.org/technical-documentation/config/#app_key -APP_KEY=base64:IvvWCuLmAAcyPBzDI+IH6OxnU9w2kTSYZrcg6F4m7Uk= +APP_KEY= # See: https://docs.pixelfed.org/technical-documentation/config/#app_name-1 APP_NAME="Pixelfed Prod" From 2e2ffc5519c195fd319df8e76c51adffb7e43dbb Mon Sep 17 00:00:00 2001 From: Christian Winther Date: Fri, 5 Jan 2024 17:31:34 +0000 Subject: [PATCH 026/173] comment build steps out to use remote image --- contrib/docker-compose/docker-compose.yml | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/contrib/docker-compose/docker-compose.yml b/contrib/docker-compose/docker-compose.yml index 8df0777b3..e43e36c78 100644 --- a/contrib/docker-compose/docker-compose.yml +++ b/contrib/docker-compose/docker-compose.yml @@ -4,10 +4,10 @@ version: "3" services: web: image: "${DOCKER_IMAGE}:${DOCKER_TAG}" - build: - context: ../.. - dockerfile: contrib/docker/Dockerfile - target: apache-runtime + # build: + # context: ../.. + # dockerfile: contrib/docker/Dockerfile + # target: apache-runtime restart: unless-stopped env_file: - "./.env" @@ -23,10 +23,10 @@ services: worker: image: "${DOCKER_IMAGE}:${DOCKER_TAG}" - build: - context: ../.. - dockerfile: contrib/docker/Dockerfile - target: apache-runtime + # build: + # context: ../.. + # dockerfile: contrib/docker/Dockerfile + # target: apache-runtime command: gosu www-data php artisan horizon restart: unless-stopped env_file: From 76e1199dc784d40927ff0101e51873a91f20170a Mon Sep 17 00:00:00 2001 From: Christian Winther Date: Fri, 5 Jan 2024 17:35:07 +0000 Subject: [PATCH 027/173] sync --- contrib/docker-compose/README.md | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/contrib/docker-compose/README.md b/contrib/docker-compose/README.md index 6c57c43d2..137773f08 100644 --- a/contrib/docker-compose/README.md +++ b/contrib/docker-compose/README.md @@ -15,6 +15,20 @@ Your folder should look like this ## Modifying your settings (`.env` file) +Minimum required settings to change is: + * `APP_NAME` * `APP_DOMAIN` * `DB_PASSWORD` + +See the [`Configure environment variables`](https://docs.pixelfed.org/running-pixelfed/installation/#app-variables) documentation for details! + +You need to mainly focus on following sections + +* [App variables](https://docs.pixelfed.org/running-pixelfed/installation/#app-variables) +* [Email variables](https://docs.pixelfed.org/running-pixelfed/installation/#email-variables) + +Since the following things are configured for you out of the box: + +* `Redis` +* `Database` (except for `DB_PASSWORD`) From 7db513b366dfaa123637ea28cf1392a35c32450d Mon Sep 17 00:00:00 2001 From: Christian Winther Date: Fri, 5 Jan 2024 18:16:38 +0000 Subject: [PATCH 028/173] sync --- contrib/docker-compose/.env | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/contrib/docker-compose/.env b/contrib/docker-compose/.env index 7c70f3cf6..54f2bb10d 100644 --- a/contrib/docker-compose/.env +++ b/contrib/docker-compose/.env @@ -88,7 +88,7 @@ ADMIN_DOMAIN="${APP_DOMAIN}" PF_MAX_USERS="false" # See: https://docs.pixelfed.org/technical-documentation/config/#oauth_enabled -# OAUTH_ENABLED="true" +OAUTH_ENABLED="true" # Defaults to "UTC". # @@ -167,13 +167,6 @@ APP_TIMEZONE="${TZ}" # See: https://docs.pixelfed.org/technical-documentation/config/#max_album_length #MAX_ALBUM_LENGTH="4" -# Set the image optimization quality, must be a value between 1-100. -# -# Defaults to "80". -# -# See: https://docs.pixelfed.org/technical-documentation/config/#image_quality -#IMAGE_QUALITY="80" - # Resize and optimize image uploads. # # Defaults to "true". @@ -181,6 +174,13 @@ APP_TIMEZONE="${TZ}" # See: https://docs.pixelfed.org/technical-documentation/config/#pf_optimize_images #PF_OPTIMIZE_IMAGES="true" +# Set the image optimization quality, must be a value between 1-100. +# +# Defaults to "80". +# +# See: https://docs.pixelfed.org/technical-documentation/config/#image_quality +#IMAGE_QUALITY="80" + # Resize and optimize video uploads. # # Defaults to "true". @@ -487,7 +487,7 @@ CACHE_DRIVER="redis" # Defaults to "true". # # See: https://docs.pixelfed.org/technical-documentation/config/#exp_emc -#EXP_EMC="true" +EXP_EMC="true" ############################################################### # ActivityPub confguration @@ -496,7 +496,7 @@ CACHE_DRIVER="redis" # Defaults to "false". # # See: https://docs.pixelfed.org/technical-documentation/config/#activity_pub -#ACTIVITY_PUB="false" +ACTIVITY_PUB="true" # Defaults to "true". # @@ -721,7 +721,7 @@ LOG_CHANNEL="stderr" # - "null" (default) # # See: https://docs.pixelfed.org/technical-documentation/config/#broadcast_driver -#BROADCAST_DRIVER= +BROADCAST_DRIVER=redis ############################################################### # Other settings From a25b7910b2691f60ff1e8fd447ea3d7b14d9cb01 Mon Sep 17 00:00:00 2001 From: Christian Winther Date: Fri, 5 Jan 2024 23:16:26 +0000 Subject: [PATCH 029/173] first time setup and more refinements --- contrib/docker-compose/.env | 2 + contrib/docker-compose/docker-compose.yml | 16 +- .../docker/entrypoint.d/01-permissions.sh | 5 +- .../root/docker/entrypoint.d/05-templating.sh | 4 +- .../entrypoint.d/11-first-time-setup.sh | 34 +-- .../root/docker/entrypoint.d/12-migrations.sh | 9 + .../root/docker/entrypoint.d/30-cache.sh | 2 +- .../docker/shared/root/docker/entrypoint.sh | 16 +- contrib/docker/shared/root/docker/helpers.sh | 278 +++++++++++++++++- .../docker/shared/root/docker/install/base.sh | 3 + 10 files changed, 309 insertions(+), 60 deletions(-) create mode 100755 contrib/docker/shared/root/docker/entrypoint.d/12-migrations.sh diff --git a/contrib/docker-compose/.env b/contrib/docker-compose/.env index 54f2bb10d..ee934ef7e 100644 --- a/contrib/docker-compose/.env +++ b/contrib/docker-compose/.env @@ -274,6 +274,8 @@ DB_DATABASE="pixelfed_prod" # See: https://docs.pixelfed.org/technical-documentation/config/#db_port DB_PORT="3306" +ENTRYPOINT_DEBUG=0 + ############################################################### # Mail configuration ############################################################### diff --git a/contrib/docker-compose/docker-compose.yml b/contrib/docker-compose/docker-compose.yml index e43e36c78..8df0777b3 100644 --- a/contrib/docker-compose/docker-compose.yml +++ b/contrib/docker-compose/docker-compose.yml @@ -4,10 +4,10 @@ version: "3" services: web: image: "${DOCKER_IMAGE}:${DOCKER_TAG}" - # build: - # context: ../.. - # dockerfile: contrib/docker/Dockerfile - # target: apache-runtime + build: + context: ../.. + dockerfile: contrib/docker/Dockerfile + target: apache-runtime restart: unless-stopped env_file: - "./.env" @@ -23,10 +23,10 @@ services: worker: image: "${DOCKER_IMAGE}:${DOCKER_TAG}" - # build: - # context: ../.. - # dockerfile: contrib/docker/Dockerfile - # target: apache-runtime + build: + context: ../.. + dockerfile: contrib/docker/Dockerfile + target: apache-runtime command: gosu www-data php artisan horizon restart: unless-stopped env_file: diff --git a/contrib/docker/shared/root/docker/entrypoint.d/01-permissions.sh b/contrib/docker/shared/root/docker/entrypoint.d/01-permissions.sh index 81d422ecd..25a831531 100755 --- a/contrib/docker/shared/root/docker/entrypoint.d/01-permissions.sh +++ b/contrib/docker/shared/root/docker/entrypoint.d/01-permissions.sh @@ -3,7 +3,8 @@ source /docker/helpers.sh entrypoint-set-script-name "$0" -# Ensure the two Docker volumes are owned by the runtime user +# Ensure the two Docker volumes and dot-env files are owned by the runtime user as other scripts +# will be writing to these run-as-current-user chown --verbose ${RUNTIME_UID}:${RUNTIME_GID} "./.env" run-as-current-user chown --verbose ${RUNTIME_UID}:${RUNTIME_GID} "./bootstrap/cache" run-as-current-user chown --verbose ${RUNTIME_UID}:${RUNTIME_GID} "./storage" @@ -22,5 +23,5 @@ fi for path in "${ensure_ownership_paths[@]}"; do log-info "Ensure ownership of [${path}] is correct" - run-as-current-user chown --recursive ${RUNTIME_UID}:${RUNTIME_GID} "${path}" + stream-prefix-command-output run-as-current-user chown --recursive ${RUNTIME_UID}:${RUNTIME_GID} "${path}" done diff --git a/contrib/docker/shared/root/docker/entrypoint.d/05-templating.sh b/contrib/docker/shared/root/docker/entrypoint.d/05-templating.sh index 618a2d406..cafb9d133 100755 --- a/contrib/docker/shared/root/docker/entrypoint.d/05-templating.sh +++ b/contrib/docker/shared/root/docker/entrypoint.d/05-templating.sh @@ -49,7 +49,7 @@ find "${ENTRYPOINT_TEMPLATE_DIR}" -follow -type f -print | while read -r templat cat "${template_file}" | gomplate >"${output_file_path}" # Show the diff from the envsubst command - if [[ ${ENTRYPOINT_SHOW_TEMPLATE_DIFF} = 1 ]]; then - git --no-pager diff "${template_file}" "${output_file_path}" || : + if [[ ${ENTRYPOINT_SHOW_TEMPLATE_DIFF:-1} = 1 ]]; then + git --no-pager diff --color=always "${template_file}" "${output_file_path}" || : fi done diff --git a/contrib/docker/shared/root/docker/entrypoint.d/11-first-time-setup.sh b/contrib/docker/shared/root/docker/entrypoint.d/11-first-time-setup.sh index 0e30e74ac..1a0cbb51c 100755 --- a/contrib/docker/shared/root/docker/entrypoint.d/11-first-time-setup.sh +++ b/contrib/docker/shared/root/docker/entrypoint.d/11-first-time-setup.sh @@ -3,36 +3,12 @@ source /docker/helpers.sh entrypoint-set-script-name "$0" -# if the script is running in another container, wait for it to complete -while [ -e "./storage/docker-first-time-is-running" ]; do - sleep 1 -done +await-database-ready -# We got the lock! -touch "./storage/docker-first-time-is-running" - -# Make sure to clean up on exit -trap "rm -f ./storage/docker-first-time-is-running" EXIT - -if [ ! -e "./storage/docker-storage-link-has-run" ]; then - run-as-runtime-user php artisan storage:link - touch "./storage/docker-storage-link-has-run" -fi - -if [ ! -e "./storage/docker-key-generate-has-run" ]; then - run-as-runtime-user php artisan key:generate - touch "./storage/docker-key-generate-has-run" -fi - -if [ ! -e "./storage/docker-migrate-has-run" ]; then - run-as-runtime-user php artisan migrate --force - touch "./storage/docker-migrate-has-run" -fi - -if [ ! -e "./storage/docker-import-cities-has-run" ]; then - run-as-runtime-user php artisan import:cities - touch "./storage/docker-import-cities-has-run" -fi +only-once "storage:link" run-as-runtime-user php artisan storage:link +only-once "key:generate" run-as-runtime-user php artisan key:generate +only-once "initial:migrate" run-as-runtime-user php artisan migrate --force +only-once "import:cities" run-as-runtime-user php artisan import:cities # if [ ! -e "./storage/docker-instance-actor-has-run" ]; then # run-as-runtime-user php artisan instance:actor diff --git a/contrib/docker/shared/root/docker/entrypoint.d/12-migrations.sh b/contrib/docker/shared/root/docker/entrypoint.d/12-migrations.sh new file mode 100755 index 000000000..2df379ac1 --- /dev/null +++ b/contrib/docker/shared/root/docker/entrypoint.d/12-migrations.sh @@ -0,0 +1,9 @@ +#!/bin/bash +source /docker/helpers.sh + +entrypoint-set-script-name "$0" + +await-database-ready + +declare new_migrations=0 +run-as-runtime-user php artisan migrate:status | grep No && migrations=yes || migrations=no diff --git a/contrib/docker/shared/root/docker/entrypoint.d/30-cache.sh b/contrib/docker/shared/root/docker/entrypoint.d/30-cache.sh index e933a179b..c8791e65b 100755 --- a/contrib/docker/shared/root/docker/entrypoint.d/30-cache.sh +++ b/contrib/docker/shared/root/docker/entrypoint.d/30-cache.sh @@ -3,6 +3,6 @@ source /docker/helpers.sh entrypoint-set-script-name "$0" +run-as-runtime-user php artisan config:cache run-as-runtime-user php artisan route:cache run-as-runtime-user php artisan view:cache -run-as-runtime-user php artisan config:cache diff --git a/contrib/docker/shared/root/docker/entrypoint.sh b/contrib/docker/shared/root/docker/entrypoint.sh index 173e4dbe3..0e8b1089c 100755 --- a/contrib/docker/shared/root/docker/entrypoint.sh +++ b/contrib/docker/shared/root/docker/entrypoint.sh @@ -31,6 +31,8 @@ if is-directory-empty "${ENTRYPOINT_ROOT}"; then exec "$@" fi +acquire-lock + # Start scanning for entrypoint.d files to source or run log-info "looking for shell scripts in [${ENTRYPOINT_ROOT}]" @@ -50,9 +52,9 @@ find "${ENTRYPOINT_ROOT}" -follow -type f -print | sort -V | while read -r file; log-error-and-exit "File [${file}] is not executable (please 'chmod +x' it)" fi - log-info - log-info "Sourcing [${file}]" - log-info + log-info "" + log-info "${notice_message_color}Sourcing [${file}]${color_clear}" + log-info "" source "${file}" @@ -67,9 +69,9 @@ find "${ENTRYPOINT_ROOT}" -follow -type f -print | sort -V | while read -r file; log-error-and-exit "File [${file}] is not executable (please 'chmod +x' it)" fi - log-info - log-info "Running [${file}]" - log-info + log-info "" + log-info "${notice_message_color}Executing [${file}]${color_clear}" + log-info "" "${file}" ;; @@ -80,6 +82,8 @@ find "${ENTRYPOINT_ROOT}" -follow -type f -print | sort -V | while read -r file; esac done +release-lock + log-info "Configuration complete; ready for start up" exec "$@" diff --git a/contrib/docker/shared/root/docker/helpers.sh b/contrib/docker/shared/root/docker/helpers.sh index 880027cf4..453af902d 100644 --- a/contrib/docker/shared/root/docker/helpers.sh +++ b/contrib/docker/shared/root/docker/helpers.sh @@ -6,14 +6,16 @@ set -e -o errexit -o nounset -o pipefail # Some splash of color for important messages declare -g error_message_color="\033[1;31m" declare -g warn_message_color="\033[1;34m" +declare -g notice_message_color="\033[1;34m" declare -g color_clear="\033[1;0m" # Current and previous log prefix +declare -g script_name= +declare -g script_name_previous= declare -g log_prefix= -declare -g log_prefix_previous= # dot-env files to source when reading config -declare -ra dot_env_files=( +declare -a dot_env_files=( /var/www/.env.docker /var/www/.env ) @@ -21,16 +23,24 @@ declare -ra dot_env_files=( # environment keys seen when source dot files (so we can [export] them) declare -ga seen_dot_env_variables=() +declare -g docker_state_path="$(readlink -f ./storage/docker)" +declare -g docker_locks_path="${docker_state_path}/lock" +declare -g docker_once_path="${docker_state_path}/once" + +declare -g runtime_username=$(id -un ${RUNTIME_UID}) + # @description Restore the log prefix to the previous value that was captured in [entrypoint-set-script-name ] # @arg $1 string The name (or path) of the entrypoint script being run function entrypoint-set-script-name() { - log_prefix_previous="${log_prefix}" - log_prefix="ENTRYPOINT - [$(get-entrypoint-script-name $1)] - " + script_name_previous="${script_name}" + script_name="${1}" + + log_prefix="[entrypoint / $(get-entrypoint-script-name $1)] - " } # @description Restore the log prefix to the previous value that was captured in [entrypoint-set-script-name ] function entrypoint-restore-script-name() { - log_prefix="${log_prefix_previous}" + entrypoint-set-script-name "${script_name_previous}" } # @description Run a command as the [runtime user] @@ -38,7 +48,7 @@ function entrypoint-restore-script-name() { # @exitcode 0 if the command succeeeds # @exitcode 1 if the command fails function run-as-runtime-user() { - run-command-as "$(id -un ${RUNTIME_UID})" "${@}" + run-command-as "${runtime_username}" "${@}" } # @description Run a command as the [runtime user] @@ -64,9 +74,9 @@ function run-command-as() { log-info-stderr "👷 Running [${*}] as [${target_user}]" if [[ ${target_user} != "root" ]]; then - su --preserve-environment "${target_user}" --shell /bin/bash --command "${*}" + stream-prefix-command-output su --preserve-environment "${target_user}" --shell /bin/bash --command "${*}" else - "${@}" + stream-prefix-command-output "${@}" fi exit_code=$? @@ -80,11 +90,62 @@ function run-command-as() { return $exit_code } +# @description Streams stdout from the command and echo it +# with log prefixing. +# @see stream-prefix-command-output +function stream-stdout-handler() { + local prefix="${1:-}" + + while read line; do + log-info "(stdout) ${line}" + done +} + +# @description Streams stderr from the command and echo it +# with a bit of color and log prefixing. +# @see stream-prefix-command-output +function stream-stderr-handler() { + while read line; do + log-info-stderr "(${error_message_color}stderr${color_clear}) ${line}" + done +} + +# @description Steam stdout and stderr from a command with log prefix +# and stdout/stderr prefix. If stdout or stderr is being piped/redirected +# it will automatically fall back to non-prefixed output. +# @arg $@ string The command to run +function stream-prefix-command-output() { + local stdout=stream-stdout-handler + local stderr=stream-stderr-handler + + # if stdout is being piped, print it like normal with echo + if [ ! -t 1 ]; then + stdout= echo >&1 -ne + fi + + # if stderr is being piped, print it like normal with echo + if [ ! -t 2 ]; then + stderr= echo >&2 -ne + fi + + "$@" > >($stdout) 2> >($stderr) +} + # @description Print the given error message to stderr # @arg $message string A error message. # @stderr The error message provided with log prefix function log-error() { - echo -e "${error_message_color}${log_prefix}ERROR - ${*}${color_clear}" >/dev/stderr + local msg + + if [[ $# -gt 0 ]]; then + msg="$@" + elif [[ ! -t 0 ]]; then + read msg || log-error-and-exit "[${FUNCNAME}] could not read from stdin" + else + log-error-and-exit "[${FUNCNAME}] did not receive any input arguments and STDIN is empty" + fi + + echo -e "${error_message_color}${log_prefix}ERROR - ${msg}${color_clear}" >/dev/stderr } # @description Print the given error message to stderr and exit 1 @@ -94,6 +155,8 @@ function log-error() { function log-error-and-exit() { log-error "$@" + show-call-stack + exit 1 } @@ -101,15 +164,35 @@ function log-error-and-exit() { # @arg $@ string A warning message. # @stderr The warning message provided with log prefix function log-warning() { - echo -e "${warn_message_color}${log_prefix}WARNING - ${*}${color_clear}" >/dev/stderr + local msg + + if [[ $# -gt 0 ]]; then + msg="$@" + elif [[ ! -t 0 ]]; then + read msg || log-error-and-exit "[${FUNCNAME}] could not read from stdin" + else + log-error-and-exit "[${FUNCNAME}] did not receive any input arguments and STDIN is empty" + fi + + echo -e "${warn_message_color}${log_prefix}WARNING - ${msg}${color_clear}" >/dev/stderr } # @description Print the given message to stdout unless [ENTRYPOINT_QUIET_LOGS] is set # @arg $@ string A info message. # @stdout The info message provided with log prefix unless $ENTRYPOINT_QUIET_LOGS function log-info() { + local msg + + if [[ $# -gt 0 ]]; then + msg="$@" + elif [[ ! -t 0 ]]; then + read msg || log-error-and-exit "[${FUNCNAME}] could not read from stdin" + else + log-error-and-exit "[${FUNCNAME}] did not receive any input arguments and STDIN is empty" + fi + if [ -z "${ENTRYPOINT_QUIET_LOGS:-}" ]; then - echo "${log_prefix}$*" + echo -e "${log_prefix}${msg}" fi } @@ -117,8 +200,18 @@ function log-info() { # @arg $@ string A info message. # @stderr The info message provided with log prefix unless $ENTRYPOINT_QUIET_LOGS function log-info-stderr() { + local msg + + if [[ $# -gt 0 ]]; then + msg="$@" + elif [[ ! -t 0 ]]; then + read msg || log-error-and-exit "[${FUNCNAME}] could not read from stdin" + else + log-error-and-exit "[${FUNCNAME}] did not receive any input arguments and STDIN is empty" + fi + if [ -z "${ENTRYPOINT_QUIET_LOGS:-}" ]; then - echo "${log_prefix}$*" + echo -e "${log_prefix}$msg" >/dev/stderr fi } @@ -196,3 +289,164 @@ function ensure-directory-exists() { function get-entrypoint-script-name() { echo "${1#"$ENTRYPOINT_ROOT"}" } + +# @description Ensure a command is only run once (via a 'lock' file) in the storage directory. +# The 'lock' is only written if the passed in command ($2) successfully ran. +# @arg $1 string The name of the lock file +# @arg $@ string The command to run +function only-once() { + local name="${1:-$script_name}" + local file="${docker_once_path}/${name}" + shift + + if [[ -e "${file}" ]]; then + log-info "Command [${*}] has already run once before (remove file [${file}] to run it again)" + + return 0 + fi + + ensure-directory-exists "$(dirname "${file}")" + + if ! "$@"; then + return 1 + fi + + touch "${file}" + return 0 +} + +# @description Best effort file lock to ensure *something* is not running in multiple containers. +# The script uses "trap" to clean up after itself if the script crashes +# @arg $1 string The lock identifier +function acquire-lock() { + local name="${1:-$script_name}" + local file="${docker_locks_path}/${name}" + + ensure-directory-exists "$(dirname "${file}")" + + log-info "🔑 Trying to acquire lock: ${file}: " + while [[ -e "${file}" ]]; do + log-info "🔒 Waiting on lock ${file}" + + staggered-sleep + done + + touch "${file}" + + log-info "🔐 Lock acquired [${file}]" + + on-trap "release-lock ${name}" EXIT INT QUIT TERM +} + +# @description Release a lock aquired by [acquire-lock] +# @arg $1 string The lock identifier +function release-lock() { + local name="${1:-$script_name}" + local file="${docker_locks_path}/${name}" + + log-info "🔓 Releasing lock [${file}]" + + rm -f "${file}" +} + +# @description Helper function to append multiple actions onto +# the bash [trap] logic +# @arg $1 string The command to run +# @arg $@ string The list of trap signals to register +function on-trap() { + local trap_add_cmd=$1 + shift || log-error-and-exit "${FUNCNAME} usage error" + + for trap_add_name in "$@"; do + trap -- "$( + # helper fn to get existing trap command from output + # of trap -p + extract_trap_cmd() { printf '%s\n' "${3:-}"; } + # print existing trap command with newline + eval "extract_trap_cmd $(trap -p "${trap_add_name}")" + # print the new trap command + printf '%s\n' "${trap_add_cmd}" + )" "${trap_add_name}" || + log-error-and-exit "unable to add to trap ${trap_add_name}" + done +} + +# Set the trace attribute for the above function. +# +# This is required to modify DEBUG or RETURN traps because functions don't +# inherit them unless the trace attribute is set +declare -f -t on-trap + +# @description Waits for the database to be healthy and responsive +function await-database-ready() { + log-info "❓ Waiting for database to be ready" + + case "${DB_CONNECTION:-}" in + mysql) + while ! echo "SELECT 1" | mysql --user="$DB_USERNAME" --password="$DB_PASSWORD" --host="$DB_HOST" "$DB_DATABASE" --silent >/dev/null; do + staggered-sleep + done + ;; + + pgsql) + while ! echo "SELECT 1" | psql --user="$DB_USERNAME" --password="$DB_PASSWORD" --host="$DB_HOST" "$DB_DATABASE" >/dev/null; do + staggered-sleep + done + ;; + + sqlsrv) + log-warning "Don't know how to check if SQLServer is *truely* ready or not - so will just check if we're able to connect to it" + + while ! timeout 1 bash -c "cat < /dev/null > /dev/tcp/${DB_HOST}/${DB_PORT}"; do + staggered-sleep + done + ;; + + sqlite) + log-info "sqlite are always ready" + ;; + + *) + log-error-and-exit "Unknown database type: [${DB_CONNECT}]" + ;; + esac + + log-info "✅ Successfully connected to database" +} + +# @description sleeps between 1 and 3 seconds to ensure a bit of randomness +# in multiple scripts/containers doing work almost at the same time. +function staggered-sleep() { + sleep $(get-random-number-between 1 3) +} + +# @description Helper function to get a random number between $1 and $2 +# @arg $1 int Minimum number in the range (inclusive) +# @arg $2 int Maximum number in the range (inclusive) +function get-random-number-between() { + local -i from=${1:-1} + local -i to="${2:-10}" + + shuf -i "${from}-${to}" -n 1 +} + +# @description Helper function to show the bask call stack when something +# goes wrong. Is super useful when needing to debug an issue +function show-call-stack() { + local stack_size=${#FUNCNAME[@]} + local func + local lineno + local src + + # to avoid noise we start with 1 to skip the get_stack function + for ((i = 1; i < $stack_size; i++)); do + func="${FUNCNAME[$i]}" + [ x$func = x ] && func=MAIN + + lineno="${BASH_LINENO[$((i - 1))]}" + src="${BASH_SOURCE[$i]}" + [ x"$src" = x ] && src=non_file_source + + log-error " at: ${func} ${src}:${lineno}" + done +} diff --git a/contrib/docker/shared/root/docker/install/base.sh b/contrib/docker/shared/root/docker/install/base.sh index b9b37b031..d3da207e5 100755 --- a/contrib/docker/shared/root/docker/install/base.sh +++ b/contrib/docker/shared/root/docker/install/base.sh @@ -23,6 +23,7 @@ declare -ra standardPackages=( libzip-dev locales locales-all + moreutils nano procps software-properties-common @@ -63,6 +64,8 @@ declare -ra videoProcessing=( declare -ra databaseDependencies=( libpq-dev libsqlite3-dev + mariadb-client + postgresql-client ) apt-get update From a8c5585e19f39567a7565aceed466d71b7e0482b Mon Sep 17 00:00:00 2001 From: Christian Winther Date: Fri, 5 Jan 2024 23:41:33 +0000 Subject: [PATCH 030/173] use upstream Docker images over self-built --- contrib/docker-compose/docker-compose.yml | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/contrib/docker-compose/docker-compose.yml b/contrib/docker-compose/docker-compose.yml index 8df0777b3..e43e36c78 100644 --- a/contrib/docker-compose/docker-compose.yml +++ b/contrib/docker-compose/docker-compose.yml @@ -4,10 +4,10 @@ version: "3" services: web: image: "${DOCKER_IMAGE}:${DOCKER_TAG}" - build: - context: ../.. - dockerfile: contrib/docker/Dockerfile - target: apache-runtime + # build: + # context: ../.. + # dockerfile: contrib/docker/Dockerfile + # target: apache-runtime restart: unless-stopped env_file: - "./.env" @@ -23,10 +23,10 @@ services: worker: image: "${DOCKER_IMAGE}:${DOCKER_TAG}" - build: - context: ../.. - dockerfile: contrib/docker/Dockerfile - target: apache-runtime + # build: + # context: ../.. + # dockerfile: contrib/docker/Dockerfile + # target: apache-runtime command: gosu www-data php artisan horizon restart: unless-stopped env_file: From 6edf266a143ea15cf90239c147bba21d47fd06b1 Mon Sep 17 00:00:00 2001 From: Christian Winther Date: Fri, 5 Jan 2024 23:54:17 +0000 Subject: [PATCH 031/173] quick take on applying migrations automatically --- contrib/docker-compose/.env | 3 +++ .../root/docker/entrypoint.d/12-migrations.sh | 26 +++++++++++++++++-- contrib/docker/shared/root/docker/helpers.sh | 3 +++ 3 files changed, 30 insertions(+), 2 deletions(-) diff --git a/contrib/docker-compose/.env b/contrib/docker-compose/.env index ee934ef7e..c9e235533 100644 --- a/contrib/docker-compose/.env +++ b/contrib/docker-compose/.env @@ -19,6 +19,9 @@ DOCKER_TAG="branch-jippi-fork-apache-8.1" # See: https://www.php.net/manual/en/timezones.php TZ="UTC" +# Automatically run [artisan migrate --force] if new migrations are detected +DOCKER_APPLY_NEW_MIGRATIONS_AUTOMATICALLY="0" + ############################################################### # Pixelfed application configuration ############################################################### diff --git a/contrib/docker/shared/root/docker/entrypoint.d/12-migrations.sh b/contrib/docker/shared/root/docker/entrypoint.d/12-migrations.sh index 2df379ac1..68008c596 100755 --- a/contrib/docker/shared/root/docker/entrypoint.d/12-migrations.sh +++ b/contrib/docker/shared/root/docker/entrypoint.d/12-migrations.sh @@ -3,7 +3,29 @@ source /docker/helpers.sh entrypoint-set-script-name "$0" +# Allow automatic applying of outstanding/new migrations on startup +: ${DOCKER_APPLY_NEW_MIGRATIONS_AUTOMATICALLY:=0} + +if [[ $DOCKER_APPLY_NEW_MIGRATIONS_AUTOMATICALLY -eq 0 ]]; then + log-info "Automatic applying of new database migrations is disabled" + log-info "Please set [DOCKER_APPLY_NEW_MIGRATIONS_AUTOMATICALLY=1] in your [.env] file to enable this." + + exit 0 +fi + +# Wait for the database to be ready await-database-ready -declare new_migrations=0 -run-as-runtime-user php artisan migrate:status | grep No && migrations=yes || migrations=no +# Detect if we have new migrations +declare -i new_migrations=0 +run-as-runtime-user php artisan migrate:status | grep No && new_migrations=1 + +if [[ $new_migrations -eq 0 ]]; then + log-info "No outstanding migrations detected" + + exit 0 +fi + +log-warning "New migrations available, will automatically apply them now" + +run-as-runtime-user php artisan migrate --force diff --git a/contrib/docker/shared/root/docker/helpers.sh b/contrib/docker/shared/root/docker/helpers.sh index 453af902d..4217b56a6 100644 --- a/contrib/docker/shared/root/docker/helpers.sh +++ b/contrib/docker/shared/root/docker/helpers.sh @@ -29,6 +29,9 @@ declare -g docker_once_path="${docker_state_path}/once" declare -g runtime_username=$(id -un ${RUNTIME_UID}) +# We should already be in /var/www, but just to be explicit +cd /var/www || log-error-and-exit "could not change to /var/www" + # @description Restore the log prefix to the previous value that was captured in [entrypoint-set-script-name ] # @arg $1 string The name (or path) of the entrypoint script being run function entrypoint-set-script-name() { From 092f7f704cd2881b27bcab6cd0864044f45d37ca Mon Sep 17 00:00:00 2001 From: Christian Winther Date: Sat, 6 Jan 2024 00:01:51 +0000 Subject: [PATCH 032/173] fix nginx? --- contrib/docker-compose/.env | 2 +- .../root/docker/templates/{ => etc/nginx}/conf.d/default.conf | 0 2 files changed, 1 insertion(+), 1 deletion(-) rename contrib/docker/nginx/root/docker/templates/{ => etc/nginx}/conf.d/default.conf (100%) diff --git a/contrib/docker-compose/.env b/contrib/docker-compose/.env index c9e235533..0fce42611 100644 --- a/contrib/docker-compose/.env +++ b/contrib/docker-compose/.env @@ -36,7 +36,7 @@ DOCKER_APPLY_NEW_MIGRATIONS_AUTOMATICALLY="0" # Please do this before deploying an application! # # See: https://docs.pixelfed.org/technical-documentation/config/#app_key -APP_KEY= +APP_KEY=base64:jL9zmd7/HBCssyNf9HpbuyqQB/KN/8Ew7A7GkogF1uc= # See: https://docs.pixelfed.org/technical-documentation/config/#app_name-1 APP_NAME="Pixelfed Prod" diff --git a/contrib/docker/nginx/root/docker/templates/conf.d/default.conf b/contrib/docker/nginx/root/docker/templates/etc/nginx/conf.d/default.conf similarity index 100% rename from contrib/docker/nginx/root/docker/templates/conf.d/default.conf rename to contrib/docker/nginx/root/docker/templates/etc/nginx/conf.d/default.conf From c9b11a4a29359c99b97e1a15db1c1e64009e2f83 Mon Sep 17 00:00:00 2001 From: Christian Winther Date: Sat, 6 Jan 2024 14:13:16 +0000 Subject: [PATCH 033/173] remove testing key --- contrib/docker-compose/.env | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contrib/docker-compose/.env b/contrib/docker-compose/.env index 0fce42611..c9e235533 100644 --- a/contrib/docker-compose/.env +++ b/contrib/docker-compose/.env @@ -36,7 +36,7 @@ DOCKER_APPLY_NEW_MIGRATIONS_AUTOMATICALLY="0" # Please do this before deploying an application! # # See: https://docs.pixelfed.org/technical-documentation/config/#app_key -APP_KEY=base64:jL9zmd7/HBCssyNf9HpbuyqQB/KN/8Ew7A7GkogF1uc= +APP_KEY= # See: https://docs.pixelfed.org/technical-documentation/config/#app_name-1 APP_NAME="Pixelfed Prod" From e228a1622dd6b50480d8b8ca4ed5c6bb980bb3b3 Mon Sep 17 00:00:00 2001 From: Christian Winther Date: Sat, 6 Jan 2024 14:19:36 +0000 Subject: [PATCH 034/173] refactor layout --- .env.docker | 992 ++++++++++++++++-- .github/workflows/docker.yml | 2 +- contrib/docker/Dockerfile => Dockerfile | 14 +- contrib/docker-compose/.env | 921 ---------------- contrib/docker-compose/README.md | 34 - contrib/docker-compose/docker-compose.yml | 67 -- docker-compose.yml | 93 +- {contrib/docker => docker}/README.md | 35 +- .../etc/apache2/conf-available/remoteip.conf | 0 {contrib/docker => docker}/fpm/root/.gitkeep | 0 {contrib/docker => docker}/nginx/Procfile | 0 .../templates/etc/nginx/conf.d/default.conf | 0 .../docker/entrypoint.d/01-permissions.sh | 0 .../docker/entrypoint.d/04-defaults.envsh | 0 .../root/docker/entrypoint.d/05-templating.sh | 0 .../root/docker/entrypoint.d/10-storage.sh | 0 .../entrypoint.d/11-first-time-setup.sh | 0 .../root/docker/entrypoint.d/12-migrations.sh | 0 .../root/docker/entrypoint.d/20-horizon.sh | 0 .../root/docker/entrypoint.d/30-cache.sh | 0 .../shared/root/docker/entrypoint.sh | 0 .../shared/root/docker/helpers.sh | 0 .../shared/root/docker/install/base.sh | 0 .../root/docker/install/php-extensions.sh | 0 .../templates/usr/local/etc/php/php.ini | 0 25 files changed, 959 insertions(+), 1199 deletions(-) rename contrib/docker/Dockerfile => Dockerfile (96%) delete mode 100644 contrib/docker-compose/.env delete mode 100644 contrib/docker-compose/README.md delete mode 100644 contrib/docker-compose/docker-compose.yml rename {contrib/docker => docker}/README.md (91%) rename {contrib/docker => docker}/apache/root/etc/apache2/conf-available/remoteip.conf (100%) rename {contrib/docker => docker}/fpm/root/.gitkeep (100%) rename {contrib/docker => docker}/nginx/Procfile (100%) rename {contrib/docker => docker}/nginx/root/docker/templates/etc/nginx/conf.d/default.conf (100%) rename {contrib/docker => docker}/shared/root/docker/entrypoint.d/01-permissions.sh (100%) rename {contrib/docker => docker}/shared/root/docker/entrypoint.d/04-defaults.envsh (100%) rename {contrib/docker => docker}/shared/root/docker/entrypoint.d/05-templating.sh (100%) rename {contrib/docker => docker}/shared/root/docker/entrypoint.d/10-storage.sh (100%) rename {contrib/docker => docker}/shared/root/docker/entrypoint.d/11-first-time-setup.sh (100%) rename {contrib/docker => docker}/shared/root/docker/entrypoint.d/12-migrations.sh (100%) rename {contrib/docker => docker}/shared/root/docker/entrypoint.d/20-horizon.sh (100%) rename {contrib/docker => docker}/shared/root/docker/entrypoint.d/30-cache.sh (100%) rename {contrib/docker => docker}/shared/root/docker/entrypoint.sh (100%) rename {contrib/docker => docker}/shared/root/docker/helpers.sh (100%) rename {contrib/docker => docker}/shared/root/docker/install/base.sh (100%) rename {contrib/docker => docker}/shared/root/docker/install/php-extensions.sh (100%) rename {contrib/docker => docker}/shared/root/docker/templates/usr/local/etc/php/php.ini (100%) diff --git a/.env.docker b/.env.docker index ce4cfe87c..10e88b8b5 100644 --- a/.env.docker +++ b/.env.docker @@ -1,149 +1,921 @@ -## Crypto +# -*- mode: bash -*- +# vi: ft=bash + +############################################################### +# Docker-wide configuration +############################################################### + +# Path (relative) to the docker-compose file where containers will store their data +DOCKER_DATA_ROOT="./data" + +# Path (relative) to the docker-compose file where containers will store their config +DOCKER_CONFIG_ROOT="./config" + +# Pixelfed version (image tag) to pull from the registry +DOCKER_TAG="branch-jippi-fork-apache-8.1" + +# Set timezone used by *all* containers - these should be in sync +# +# See: https://www.php.net/manual/en/timezones.php +TZ="UTC" + +# Automatically run [artisan migrate --force] if new migrations are detected +DOCKER_APPLY_NEW_MIGRATIONS_AUTOMATICALLY="0" + +############################################################### +# Pixelfed application configuration +############################################################### + +# A random 32-character string to be used as an encryption key. +# +# No default value; use [php artisan key:generate] to generate. +# +# This key is used by the Illuminate encrypter service and should be set to a random, +# 32 character string, otherwise these encrypted strings will not be safe. +# +# Please do this before deploying an application! +# +# See: https://docs.pixelfed.org/technical-documentation/config/#app_key APP_KEY= -## General Settings +# See: https://docs.pixelfed.org/technical-documentation/config/#app_name-1 APP_NAME="Pixelfed Prod" -APP_ENV=production -APP_DEBUG=false -APP_URL=https://real.domain -APP_DOMAIN="real.domain" -ADMIN_DOMAIN="real.domain" -SESSION_DOMAIN="real.domain" -OPEN_REGISTRATION=true -ENFORCE_EMAIL_VERIFICATION=false -PF_MAX_USERS=1000 -OAUTH_ENABLED=true +# Application domains used for routing. +# +# See: https://docs.pixelfed.org/technical-documentation/config/#app_domain +APP_DOMAIN="__CHANGE_ME__" -APP_TIMEZONE=UTC -APP_LOCALE=en +# This URL is used by the console to properly generate URLs when using the Artisan command line tool. +# You should set this to the root of your application so that it is used when running Artisan tasks. +# +# See: https://docs.pixelfed.org/technical-documentation/config/#app_url +APP_URL=https://${APP_DOMAIN} -## Pixelfed Tweaks -LIMIT_ACCOUNT_SIZE=true -MAX_ACCOUNT_SIZE=1000000 -MAX_PHOTO_SIZE=15000 -MAX_AVATAR_SIZE=2000 -MAX_CAPTION_LENGTH=500 -MAX_BIO_LENGTH=125 -MAX_NAME_LENGTH=30 -MAX_ALBUM_LENGTH=4 -IMAGE_QUALITY=80 -PF_OPTIMIZE_IMAGES=true -PF_OPTIMIZE_VIDEOS=true -ADMIN_ENV_EDITOR=false -ACCOUNT_DELETION=true -ACCOUNT_DELETE_AFTER=false -MAX_LINKS_PER_POST=0 +# Application domains used for routing. +# +# See: https://docs.pixelfed.org/technical-documentation/config/#admin_domain +ADMIN_DOMAIN="${APP_DOMAIN}" -## Instance +# This value determines the “environment” your application is currently running in. +# This may determine how you prefer to configure various services your application utilizes. +# +# See: https://docs.pixelfed.org/technical-documentation/config/#app_env +#APP_ENV="production" + +# When your application is in debug mode, detailed error messages with stack traces will +# be shown on every error that occurs within your application. +# +# If disabled, a simple generic error page is shown. +# +# See: https://docs.pixelfed.org/technical-documentation/config/#app_debug +#APP_DEBUG="false" + +# Enable/disable new local account registrations. +# +# See: https://docs.pixelfed.org/technical-documentation/config/#open_registration +#OPEN_REGISTRATION=true + +# Require email verification before a new user can do anything. +# +# Defaults to "true". +# +# See: https://docs.pixelfed.org/technical-documentation/config/#enforce_email_verification +#ENFORCE_EMAIL_VERIFICATION="true" + +# Allow a maximum number of user accounts. +# +# Defaults to "1000". +# +# See: https://docs.pixelfed.org/technical-documentation/config/#pf_max_users +PF_MAX_USERS="false" + +# See: https://docs.pixelfed.org/technical-documentation/config/#oauth_enabled +OAUTH_ENABLED="true" + +# Defaults to "UTC". +# +# Do not edit your timezone or things will break! +# +# See: https://docs.pixelfed.org/technical-documentation/config/#app_timezone +# See: https://www.php.net/manual/en/timezones.php +APP_TIMEZONE="${TZ}" + +# The application locale determines the default locale that will be used by the translation service provider. +# You are free to set this value to any of the locales which will be supported by the application. +# +# Defaults to "en". +# +# See: https://docs.pixelfed.org/technical-documentation/config/#app_locale +#APP_LOCALE="en" + +# The fallback locale determines the locale to use when the current one is not available. +# +# You may change the value to correspond to any of the language folders that are provided through your application. +# +# Defaults to "en". +# +# See: https://docs.pixelfed.org/technical-documentation/config/#app_fallback_locale +#APP_FALLBACK_LOCALE="en" + +# See: https://docs.pixelfed.org/technical-documentation/config/#limit_account_size +#LIMIT_ACCOUNT_SIZE="true" + +# Update the max account size, the per user limit of files in kB. +# +# Defaults to "1000000" (1GB). +# +# See: https://docs.pixelfed.org/technical-documentation/config/#max_account_size-kb +#MAX_ACCOUNT_SIZE="1000000" + +# Update the max photo size, in kB. +# +# Defaults to "15000" (15MB). +# +# See: https://docs.pixelfed.org/technical-documentation/config/#max_photo_size-kb +#MAX_PHOTO_SIZE="15000" + +# Update the max avatar size, in kB. +# +# Defaults to "2000" (2MB). +# +# See: https://docs.pixelfed.org/technical-documentation/config/#max_avatar_size-kb +#MAX_AVATAR_SIZE="2000" + +# Change the caption length limit for new local posts. +# +# Defaults to "500". +# +# See: https://docs.pixelfed.org/technical-documentation/config/#max_caption_length +#MAX_CAPTION_LENGTH="500" + +# Change the bio length limit for user profiles. +# +# Defaults to "125". +# +# See: https://docs.pixelfed.org/technical-documentation/config/#max_bio_length +#MAX_BIO_LENGTH="125" + +# Change the length limit for user names. +# +# Defaults to "30". +# +# See: https://docs.pixelfed.org/technical-documentation/config/#max_name_length +#MAX_NAME_LENGTH="30" + +# The max number of photos allowed per post. +# +# Defaults to "4". +# +# See: https://docs.pixelfed.org/technical-documentation/config/#max_album_length +#MAX_ALBUM_LENGTH="4" + +# Resize and optimize image uploads. +# +# Defaults to "true". +# +# See: https://docs.pixelfed.org/technical-documentation/config/#pf_optimize_images +#PF_OPTIMIZE_IMAGES="true" + +# Set the image optimization quality, must be a value between 1-100. +# +# Defaults to "80". +# +# See: https://docs.pixelfed.org/technical-documentation/config/#image_quality +#IMAGE_QUALITY="80" + +# Resize and optimize video uploads. +# +# Defaults to "true". +# +# See: https://docs.pixelfed.org/technical-documentation/config/#pf_optimize_videos +#PF_OPTIMIZE_VIDEOS="true" + +# Enable account deletion. +# +# Defaults to "true". +# +# See: https://docs.pixelfed.org/technical-documentation/config/#account_deletion +#ACCOUNT_DELETION="true" + +# Set account deletion queue after X days, set to false to delete accounts immediately. +# +# Defaults to "false". +# +# See: https://docs.pixelfed.org/technical-documentation/config/#account_delete_after +#ACCOUNT_DELETE_AFTER="false" + +# Defaults to "Pixelfed - Photo sharing for everyone". +# +# See: https://docs.pixelfed.org/technical-documentation/config/#instance_description #INSTANCE_DESCRIPTION= -INSTANCE_PUBLIC_HASHTAGS=false -#INSTANCE_CONTACT_EMAIL= -INSTANCE_PUBLIC_LOCAL_TIMELINE=false + +# Defaults to "false". +# +# See: https://docs.pixelfed.org/technical-documentation/config/#instance_public_hashtags +#INSTANCE_PUBLIC_HASHTAGS="false" + +# Defaults to "". +# +# See: https://docs.pixelfed.org/technical-documentation/config/#instance_contact_email +INSTANCE_CONTACT_EMAIL="admin@${APP_DOMAIN}" + +# Defaults to "false". +# +# See: https://docs.pixelfed.org/technical-documentation/config/#instance_public_local_timeline +#INSTANCE_PUBLIC_LOCAL_TIMELINE="false" + +# Defaults to "". +# +# See: https://docs.pixelfed.org/technical-documentation/config/#banned_usernames #BANNED_USERNAMES= -STORIES_ENABLED=false -RESTRICTED_INSTANCE=false -## Mail -MAIL_DRIVER=log -MAIL_HOST=smtp.mailtrap.io -MAIL_PORT=2525 -MAIL_FROM_ADDRESS="pixelfed@example.com" -MAIL_FROM_NAME="Pixelfed" -MAIL_USERNAME=null -MAIL_PASSWORD=null -MAIL_ENCRYPTION=null +# Defaults to "false". +# +# See: https://docs.pixelfed.org/technical-documentation/config/#stories_enabled +#STORIES_ENABLED="false" -## Databases (MySQL) -DB_CONNECTION=mysql -DB_DATABASE=pixelfed_prod -DB_HOST=db -DB_PASSWORD=pixelfed_db_pass -DB_PORT=3306 -DB_USERNAME=pixelfed -# pass the same values to the db itself -MYSQL_DATABASE=pixelfed_prod -MYSQL_PASSWORD=pixelfed_db_pass -MYSQL_RANDOM_ROOT_PASSWORD=true -MYSQL_USER=pixelfed +# Defaults to "false". +# +# Level is hardcoded to 1. +# +# See: https://docs.pixelfed.org/technical-documentation/config/#restricted_instance +#RESTRICTED_INSTANCE="false" -## Databases (Postgres) -#DB_CONNECTION=pgsql -#DB_HOST=postgres -#DB_PORT=5432 -#DB_DATABASE=pixelfed -#DB_USERNAME=postgres -#DB_PASSWORD=postgres +############################################################### +# Database configuration +############################################################### -## Cache (Redis) -REDIS_CLIENT=phpredis -REDIS_SCHEME=tcp -REDIS_HOST=redis -REDIS_PASSWORD=redis_password -REDIS_PORT=6379 -REDIS_DATABASE=0 +# Here you may specify which of the database connections below you wish to use as your default connection for all database work. +# +# Of course you may use many connections at once using the database library. +# +# Possible values: +# +# - "sqlite" +# - "mysql" (default) +# - "pgsql" +# - "sqlsrv" +# +# See: https://docs.pixelfed.org/technical-documentation/config/#db_connection +DB_CONNECTION="mysql" -HORIZON_PREFIX="horizon-" +# See: https://docs.pixelfed.org/technical-documentation/config/#db_host +DB_HOST="db" -## EXPERIMENTS -EXP_LC=false -EXP_REC=false -EXP_LOOPS=false +# See: https://docs.pixelfed.org/technical-documentation/config/#db_username +DB_USERNAME="pixelfed" -## ActivityPub Federation -ACTIVITY_PUB=false -AP_REMOTE_FOLLOW=false -AP_SHAREDINBOX=false -AP_INBOX=false -AP_OUTBOX=false -ATOM_FEEDS=true -NODEINFO=true -WEBFINGER=true +# See: https://docs.pixelfed.org/technical-documentation/config/#db_password +DB_PASSWORD="helloworld" -## S3 -FILESYSTEM_CLOUD=s3 -PF_ENABLE_CLOUD=false +# See: https://docs.pixelfed.org/technical-documentation/config/#db_database +DB_DATABASE="pixelfed_prod" + +# Use "3306" for MySQL/MariaDB and "5432" for PostgreeSQL +# +# See: https://docs.pixelfed.org/technical-documentation/config/#db_port +DB_PORT="3306" + +ENTRYPOINT_DEBUG=0 + +############################################################### +# Mail configuration +############################################################### + +# Laravel supports both SMTP and PHP’s “mail” function as drivers for the sending of e-mail. +# You may specify which one you’re using throughout your application here. +# +# Possible values: +# +# "smtp" (default) +# "sendmail" +# "mailgun" +# "mandrill" +# "ses" +# "sparkpost" +# "log" +# "array" +# +# See: https://docs.pixelfed.org/technical-documentation/config/#mail_driver +#MAIL_DRIVER="smtp" + +# The host address of the SMTP server used by your applications. +# +# A default option is provided that is compatible with the Mailgun mail service which will provide reliable deliveries. +# +# Defaults to "smtp.mailgun.org". +# +# See: https://docs.pixelfed.org/technical-documentation/config/#mail_host +#MAIL_HOST="smtp.mailgun.org" + +# This is the SMTP port used by your application to deliver e-mails to users of the application. +# +# Like the host we have set this value to stay compatible with the Mailgun e-mail application by default. +# +# Defaults to 587. +# +# See: https://docs.pixelfed.org/technical-documentation/config/#mail_port +#MAIL_PORT="587" + +# You may wish for all e-mails sent by your application to be sent from the same address. +# +# Here, you may specify a name and address that is used globally for all e-mails that are sent by your application. +# +# Defaults to "hello@example.com". +# +# See: https://docs.pixelfed.org/technical-documentation/config/#mail_from_address +MAIL_FROM_ADDRESS="hello@${APP_DOMAIN}" + +# Defaults to "Example". +# +# See: https://docs.pixelfed.org/technical-documentation/config/#mail_from_name +MAIL_FROM_NAME="Pixelfed @ ${APP_DOMAIN}" + +# If your SMTP server requires a username for authentication, you should set it here. +# +# This will get used to authenticate with your server on connection. +# You may also set the “password” value below this one. +# +# Defaults to "". +# +# See: https://docs.pixelfed.org/technical-documentation/config/#mail_username +#MAIL_USERNAME= + +# Defaults to "". +# +# See: https://docs.pixelfed.org/technical-documentation/config/#mail_password +#MAIL_PASSWORD= + +# Here you may specify the encryption protocol that should be used when the application send e-mail messages. +# +# A sensible default using the transport layer security protocol should provide great security. +# +# Defaults to "tls". +# +# See: https://docs.pixelfed.org/technical-documentation/config/#mail_encryption +#MAIL_ENCRYPTION="tls" + +############################################################### +# Redis configuration +############################################################### + +# Defaults to "phpredis". +# +# See: https://docs.pixelfed.org/technical-documentation/config/#db_username +#REDIS_CLIENT="phpredis" + +# Defaults to "tcp". +# +# See: https://docs.pixelfed.org/technical-documentation/config/#redis_scheme +#REDIS_SCHEME="tcp" + +# Defaults to "localhost". +# +# See: https://docs.pixelfed.org/technical-documentation/config/#redis_host +REDIS_HOST="redis" + +# Defaults to null. +# +# See: https://docs.pixelfed.org/technical-documentation/config/#redis_password +#REDIS_PASSWORD= + +# Defaults to 6379. +# +# See: https://docs.pixelfed.org/technical-documentation/config/#redis_port +REDIS_PORT="6379" + +# Defaults to 0. +# +# See: https://docs.pixelfed.org/technical-documentation/config/#redis_database +#REDIS_DATABASE="0" + +############################################################### +# Cache settings +############################################################### + +# This option controls the default cache connection that gets used while using this caching library. +# +# This connection is used when another is not explicitly specified when executing a given caching function. +# +# Possible values: +# - "apc" +# - "array" +# - "database" +# - "file" (default) +# - "memcached" +# - "redis" +# +# See: https://docs.pixelfed.org/technical-documentation/config/#cache_driver +CACHE_DRIVER="redis" + +# Defaults to ${APP_NAME}_cache, or laravel_cache if no APP_NAME is set. +# +# See: https://docs.pixelfed.org/technical-documentation/config/#cache_prefix +# CACHE_PREFIX="{APP_NAME}_cache" + +############################################################### +# Horizon settings +############################################################### + +# This prefix will be used when storing all Horizon data in Redis. +# +# You may modify the prefix when you are running multiple installations +# of Horizon on the same server so that they don’t have problems. +# +# Defaults to "horizon-". +# +# See: https://docs.pixelfed.org/technical-documentation/config/#horizon_prefix +#HORIZON_PREFIX="horizon-" + +# Defaults to "false". +# +# See: https://docs.pixelfed.org/technical-documentation/config/#horizon_darkmode +#HORIZON_DARKMODE="false" + +# This value (in MB) describes the maximum amount of memory (in MB) the Horizon worker +# may consume before it is terminated and restarted. +# +# You should set this value according to the resources available to your server. +# +# Defaults to "64". +#HORIZON_MEMORY_LIMIT="64" + +# See: https://docs.pixelfed.org/technical-documentation/config/#horizon_balance_strategy +#HORIZON_BALANCE_STRATEGY="auto" + +# See: https://docs.pixelfed.org/technical-documentation/config/#horizon_min_processes +#HORIZON_MIN_PROCESSES="1" + +# See: https://docs.pixelfed.org/technical-documentation/config/#horizon_max_processes +#HORIZON_MAX_PROCESSES="20" + +# See: https://docs.pixelfed.org/technical-documentation/config/#horizon_supervisor_memory +#HORIZON_SUPERVISOR_MEMORY="64" + +# See: https://docs.pixelfed.org/technical-documentation/config/#horizon_supervisor_tries +#HORIZON_SUPERVISOR_TRIES="3" + +# See: https://docs.pixelfed.org/technical-documentation/config/#horizon_supervisor_nice +#HORIZON_SUPERVISOR_NICE="0" + +# See: https://docs.pixelfed.org/technical-documentation/config/#horizon_supervisor_timeout +#HORIZON_SUPERVISOR_TIMEOUT="300" + +############################################################### +# Experiments +############################################################### + +# Text only posts (alpha). +# +# Defaults to "false". +# +# See: https://docs.pixelfed.org/technical-documentation/config/#exp_top +#EXP_TOP="false" + +# Poll statuses (alpha). +# +# Defaults to "false". +# +# See: https://docs.pixelfed.org/technical-documentation/config/#exp_polls +#EXP_POLLS="false" + +# Cached public timeline for larger instances (beta). +# +# Defaults to "false". +# +# See: https://docs.pixelfed.org/technical-documentation/config/#exp_cpt +#EXP_CPT="false" + +# Enforce Mastoapi Compatibility (alpha). +# +# Defaults to "true". +# +# See: https://docs.pixelfed.org/technical-documentation/config/#exp_emc +EXP_EMC="true" + +############################################################### +# ActivityPub confguration +############################################################### + +# Defaults to "false". +# +# See: https://docs.pixelfed.org/technical-documentation/config/#activity_pub +ACTIVITY_PUB="true" + +# Defaults to "true". +# +# See: https://docs.pixelfed.org/technical-documentation/config/#ap_remote_follow +#AP_REMOTE_FOLLOW="true" + +# Defaults to "true". +# +# See: https://docs.pixelfed.org/technical-documentation/config/#ap_sharedinbox +#AP_SHAREDINBOX="true" + +# Defaults to "true". +# +# See: https://docs.pixelfed.org/technical-documentation/config/#ap_inbox +#AP_INBOX="true" + +# Defaults to "true". +# +# See: https://docs.pixelfed.org/technical-documentation/config/#ap_outbox +#AP_OUTBOX="true" + +############################################################### +# Federation confguration +############################################################### + +# Defaults to "true". +# +# See: https://docs.pixelfed.org/technical-documentation/config/#atom_feeds +#ATOM_FEEDS="true" + +# Defaults to "true". +# +# See: https://docs.pixelfed.org/technical-documentation/config/#nodeinfo +#NODEINFO="true" + +# Defaults to "true". +# +# See: https://docs.pixelfed.org/technical-documentation/config/#webfinger +#WEBFINGER="true" + +############################################################### +# Storage (cloud) +############################################################### + +# Store media on object storage like S3, Digital Ocean Spaces, Rackspace +# +# Defaults to "false". +# +# See: https://docs.pixelfed.org/technical-documentation/config/#pf_enable_cloud +#PF_ENABLE_CLOUD="false" + +# Many applications store files both locally and in the cloud. +# +# For this reason, you may specify a default “cloud” driver here. +# This driver will be bound as the Cloud disk implementation in the container. +# +# Defaults to "s3". +# +# See: https://docs.pixelfed.org/technical-documentation/config/#filesystem_cloud +#FILESYSTEM_CLOUD="s3" + +# Defaults to true. +# +# See: https://docs.pixelfed.org/technical-documentation/config/#media_delete_local_after_cloud +#MEDIA_DELETE_LOCAL_AFTER_CLOUD="true" + +############################################################### +# Storage (cloud) - S3 +############################################################### + +# See: https://docs.pixelfed.org/technical-documentation/config/#aws_access_key_id #AWS_ACCESS_KEY_ID= + +# See: https://docs.pixelfed.org/technical-documentation/config/#aws_secret_access_key #AWS_SECRET_ACCESS_KEY= + +# See: https://docs.pixelfed.org/technical-documentation/config/#aws_default_region #AWS_DEFAULT_REGION= + +# See: https://docs.pixelfed.org/technical-documentation/config/#aws_bucket #AWS_BUCKET= + +# See: https://docs.pixelfed.org/technical-documentation/config/#aws_url #AWS_URL= + +# See: https://docs.pixelfed.org/technical-documentation/config/#aws_endpoint #AWS_ENDPOINT= -#AWS_USE_PATH_STYLE_ENDPOINT=false -## Horizon -HORIZON_DARKMODE=false +# See: https://docs.pixelfed.org/technical-documentation/config/#aws_use_path_style_endpoint +#AWS_USE_PATH_STYLE_ENDPOINT="false" -## COSTAR - Confirm Object Sentiment Transform and Reduce -PF_COSTAR_ENABLED=false +############################################################### +# COSTAR - Confirm Object Sentiment Transform and Reduce +############################################################### +# Comma-separated list of domains to block. +# +# Defaults to null +# +# See: https://docs.pixelfed.org/technical-documentation/config/#cs_blocked_domains +#CS_BLOCKED_DOMAINS= + +# Comma-separated list of domains to add warnings. +# +# Defaults to null. +# +# See: https://docs.pixelfed.org/technical-documentation/config/#cs_cw_domains +#CS_CW_DOMAINS= + +# Comma-separated list of domains to remove from public timelines. +# +# Defaults to null. +# +# See: https://docs.pixelfed.org/technical-documentation/config/#cs_unlisted_domains +#CS_UNLISTED_DOMAINS= + +# Comma-separated list of keywords to block. +# +# Defaults to null. +# +# See: https://docs.pixelfed.org/technical-documentation/config/#cs_blocked_keywords +#CS_BLOCKED_KEYWORDS= + +# Comma-separated list of keywords to add warnings. +# +# Defaults to null. +# +# See: https://docs.pixelfed.org/technical-documentation/config/#cs_cw_keywords +#CS_CW_KEYWORDS= + +# Comma-separated list of keywords to remove from public timelines. +# +# Defaults to null. +# +# See: https://docs.pixelfed.org/technical-documentation/config/#cs_unlisted_keywords +#CS_UNLISTED_KEYWORDS= + +# Defaults to null. +# +# See: https://docs.pixelfed.org/technical-documentation/config/#cs_blocked_actor +#CS_BLOCKED_ACTOR= + +# Defaults to null. +# +# See: https://docs.pixelfed.org/technical-documentation/config/#cs_cw_actor +#CS_CW_ACTOR= + +# Defaults to null. +# +# See: https://docs.pixelfed.org/technical-documentation/config/#cs_unlisted_actor +#CS_UNLISTED_ACTOR= + +############################################################### # Media -MEDIA_EXIF_DATABASE=false +############################################################### -## Logging -LOG_CHANNEL=stderr +# Defaults to false. +# +# See: https://docs.pixelfed.org/technical-documentation/config/#media_exif_database +MEDIA_EXIF_DATABASE="true" -## Image -IMAGE_DRIVER=imagick +# Pixelfed supports GD or ImageMagick to process images. +# +# Defaults to "gd". +# +# Possible values: +# - "gd" (default) +# - "imagick" +# +# See: https://docs.pixelfed.org/technical-documentation/config/#image_driver +#IMAGE_DRIVER="gd" -## Broadcasting: log driver for local development -BROADCAST_DRIVER=log +############################################################### +# Logging +############################################################### -## Cache -CACHE_DRIVER=redis +# Possible values: +# +# - "stack" (default) +# - "single" +# - "daily" +# - "slack" +# - "stderr" +# - "syslog" +# - "errorlog" +# - "null" +# - "emergency" +# - "media" +LOG_CHANNEL="stderr" -## Purify -RESTRICT_HTML_TYPES=true +# Used by single, stderr and syslog. +# +# Defaults to "debug" for all of those. +# +# See: https://docs.pixelfed.org/technical-documentation/config/#log_level +#LOG_LEVEL="debug" -## Queue -QUEUE_DRIVER=redis +# Used by stderr. +# +# Defaults to "". +# +# See: https://docs.pixelfed.org/technical-documentation/config/#log_stderr_formatter +#LOG_STDERR_FORMATTER= -## Session -SESSION_DRIVER=redis +# Used by slack. +# +# Defaults to "". +# +# See: https://docs.pixelfed.org/technical-documentation/config/#log_slack_webhook_url +#LOG_SLACK_WEBHOOK_URL= -## Trusted Proxy +############################################################### +# Broadcasting settings +############################################################### + +# This option controls the default broadcaster that will be used by the framework when an event needs to be broadcast. +# +# Possible values: +# - "pusher" +# - "redis" +# - "log" +# - "null" (default) +# +# See: https://docs.pixelfed.org/technical-documentation/config/#broadcast_driver +BROADCAST_DRIVER=redis + +############################################################### +# Other settings +############################################################### + +# Defaults to true. +# +# See: https://docs.pixelfed.org/technical-documentation/config/#restrict_html_types +#RESTRICT_HTML_TYPES="true" + +############################################################### +# Queue configuration +############################################################### + +# Possible values: +# - "sync" (default) +# - "database" +# - "beanstalkd" +# - "sqs" +# - "redis" +# - "null" +# +# See: https://docs.pixelfed.org/technical-documentation/config/#queue_driver +QUEUE_DRIVER="redis" + +############################################################### +# Queue (SQS) configuration +############################################################### + +# Defaults to "your-public-key". +# +# See: https://docs.pixelfed.org/technical-documentation/config/#sqs_key +#SQS_KEY="your-public-key" + +# Defaults to "your-secret-key". +# +# See: https://docs.pixelfed.org/technical-documentation/config/#sqs_secret +#SQS_SECRET="your-secret-key" + +# Defaults to "https://sqs.us-east-1.amazonaws.com/your-account-id". +# +# See: https://docs.pixelfed.org/technical-documentation/config/#sqs_prefix +#SQS_PREFIX= + +# Defaults to "your-queue-name". +# +# https://docs.pixelfed.org/technical-documentation/config/#sqs_queue +#SQS_QUEUE="your-queue-name" + +# Defaults to "us-east-1". +# +# See: https://docs.pixelfed.org/technical-documentation/config/#sqs_region +#SQS_REGION="us-east-1" + +############################################################### +# Session configuration +############################################################### + +# This option controls the default session “driver” that will be used on requests. +# +# By default, we will use the lightweight native driver but you may specify any of the other wonderful drivers provided here. +# +# Possible values: +# - "file" +# - "cookie" +# - "database" (default) +# - "apc" +# - "memcached" +# - "redis" +# - "array" +SESSION_DRIVER="redis" + +# Here you may specify the number of minutes that you wish the session to be allowed to remain idle before it expires. +# +# If you want them to immediately expire on the browser closing, set that option. +# +# Defaults to 86400. +# +# See: https://docs.pixelfed.org/technical-documentation/config/#session_lifetime +#SESSION_LIFETIME="86400" + +# Here you may change the domain of the cookie used to identify a session in your application. +# +# This will determine which domains the cookie is available to in your application. +# +# A sensible default has been set. +# +# Defaults to the value of APP_DOMAIN, or null. +# +# See: https://docs.pixelfed.org/technical-documentation/config/#session_domain +#SESSION_DOMAIN="${APP_DOMAIN}" + +############################################################### +# Proxy configuration +############################################################### + +# Set trusted proxy IP addresses. +# +# Both IPv4 and IPv6 addresses are supported, along with CIDR notation. +# +# The “*” character is syntactic sugar within TrustedProxy to trust any +# proxy that connects directly to your server, a requirement when you cannot +# know the address of your proxy (e.g. if using Rackspace balancers). +# +# The “**” character is syntactic sugar within TrustedProxy to trust not just any +# proxy that connects directly to your server, but also proxies that connect to those proxies, +# and all the way back until you reach the original source IP. It will mean that +# $request->getClientIp() always gets the originating client IP, no matter how many proxies +# that client’s request has subsequently passed through. +# +# Defaults to "*". +# +# See: https://docs.pixelfed.org/technical-documentation/config/#trust_proxies TRUST_PROXIES="*" -## Passport +############################################################### +# Passport configuration +############################################################### +# +# Passport uses encryption keys while generating secure access tokens +# for your application. +# +# By default, the keys are stored as local files but can be set via environment +# variables when that is more convenient. + +# See: https://docs.pixelfed.org/technical-documentation/config/#passport_private_key #PASSPORT_PRIVATE_KEY= + +# See: https://docs.pixelfed.org/technical-documentation/config/#passport_public_key #PASSPORT_PUBLIC_KEY= + +############################################################### +# PHP configuration +############################################################### + +# See: https://www.php.net/manual/en/ini.core.php#ini.memory-limit +#PHP_MEMORY_LIMIT="128M" + +############################################################### +# MySQL DB container configuration (DO NOT CHANGE) +############################################################### +# +# See "Environment Variables" at https://hub.docker.com/_/mysql + +MYSQL_ROOT_PASSWORD="${DB_PASSWORD}" +MYSQL_USER="${DB_USERNAME}" +MYSQL_PASSWORD="${DB_PASSWORD}" +MYSQL_DATABASE="${DB_DATABASE}" + +############################################################### +# MySQL (MariaDB) DB container configuration (DO NOT CHANGE) +############################################################### +# +# See "Start a mariadb server instance with user, password and database" at https://hub.docker.com/_/mariadb + +MARIADB_ROOT_PASSWORD="${DB_PASSWORD}" +MARIADB_USER="${DB_USERNAME}" +MARIADB_PASSWORD="${DB_PASSWORD}" +MARIADB_DATABASE="${DB_DATABASE}" + +############################################################### +# PostgreSQL DB container configuration (DO NOT CHANGE) +############################################################### +# +# See "Environment Variables" at https://hub.docker.com/_/postgres + +POSTGRES_USER="${DB_USERNAME}" +POSTGRES_PASSWORD="${DB_PASSWORD}" +POSTGRES_DB="${DB_DATABASE}" + +############################################################### +# Docker Specific configuration +############################################################### + +# Image to pull the Pixelfed Docker images from +# +# Possible values: +# - "ghcr.io/pixelfed/pixelfed" to pull from GitHub +# - "pixelfed/pixelfed" to pull from DockerHub +# +DOCKER_IMAGE="ghcr.io/jippi/pixelfed" + +# Port that Redis will listen on *outside* the container (e.g. the host machine) +DOCKER_REDIS_PORT_EXTERNAL="${REDIS_PORT}" + +# Port that the database will listen on *outside* the container (e.g. the host machine) +# +# Use "3306" for MySQL/MariaDB and "5432" for PostgreeSQL +DOCKER_DB_PORT_EXTERNAL="${DB_PORT}" + +# Port that the web will listen on *outside* the container (e.g. the host machine) +DOCKER_WEB_PORT_EXTERNAL="8080" diff --git a/.github/workflows/docker.yml b/.github/workflows/docker.yml index b71c08c87..f53559b37 100644 --- a/.github/workflows/docker.yml +++ b/.github/workflows/docker.yml @@ -160,7 +160,7 @@ jobs: uses: docker/build-push-action@v5 with: context: . - file: contrib/docker/Dockerfile + file: Dockerfile target: ${{ matrix.target_runtime }}-runtime platforms: linux/amd64,linux/arm64 builder: ${{ steps.buildx.outputs.name }} diff --git a/contrib/docker/Dockerfile b/Dockerfile similarity index 96% rename from contrib/docker/Dockerfile rename to Dockerfile index 8ef6a99d4..116631f60 100644 --- a/contrib/docker/Dockerfile +++ b/Dockerfile @@ -114,7 +114,7 @@ WORKDIR /var/www/ ENV APT_PACKAGES_EXTRA=${APT_PACKAGES_EXTRA} # Install and configure base layer -COPY contrib/docker/shared/root/docker/install/base.sh /docker/install/base.sh +COPY docker/shared/root/docker/install/base.sh /docker/install/base.sh RUN --mount=type=cache,id=pixelfed-apt-${PHP_VERSION}-${PHP_DEBIAN_RELEASE}-${TARGETPLATFORM},sharing=locked,target=/var/lib/apt \ --mount=type=cache,id=pixelfed-apt-cache-${PHP_VERSION}-${PHP_DEBIAN_RELEASE}-${TARGETPLATFORM},sharing=locked,target=/var/cache/apt \ /docker/install/base.sh @@ -140,7 +140,7 @@ ENV PHP_EXTENSIONS=${PHP_EXTENSIONS} ENV PHP_PECL_EXTENSIONS_EXTRA=${PHP_PECL_EXTENSIONS_EXTRA} ENV PHP_PECL_EXTENSIONS=${PHP_PECL_EXTENSIONS} -COPY contrib/docker/shared/root/docker/install/php-extensions.sh /docker/install/php-extensions.sh +COPY docker/shared/root/docker/install/php-extensions.sh /docker/install/php-extensions.sh RUN --mount=type=cache,id=pixelfed-php-${PHP_VERSION}-${PHP_DEBIAN_RELEASE}-${TARGETPLATFORM},sharing=locked,target=/usr/src/php/ \ --mount=type=cache,id=pixelfed-apt-${PHP_VERSION}-${PHP_DEBIAN_RELEASE}-${TARGETPLATFORM},sharing=locked,target=/var/lib/apt \ --mount=type=cache,id=pixelfed-apt-cache-${PHP_VERSION}-${PHP_DEBIAN_RELEASE}-${TARGETPLATFORM},sharing=locked,target=/var/cache/apt \ @@ -221,7 +221,7 @@ RUN set -ex \ && cp --recursive --link --preserve=all storage storage.skel \ && rm -rf html && ln -s public html -COPY contrib/docker/shared/root / +COPY docker/shared/root / ENTRYPOINT ["/docker/entrypoint.sh"] @@ -231,7 +231,7 @@ ENTRYPOINT ["/docker/entrypoint.sh"] FROM shared-runtime AS apache-runtime -COPY contrib/docker/apache/root / +COPY docker/apache/root / RUN set -ex \ && a2enmod rewrite remoteip proxy proxy_http \ @@ -245,7 +245,7 @@ CMD ["apache2-foreground"] FROM shared-runtime AS fpm-runtime -COPY contrib/docker/fpm/root / +COPY docker/fpm/root / CMD ["php-fpm"] @@ -275,8 +275,8 @@ RUN --mount=type=cache,id=pixelfed-apt-lists-${PHP_VERSION}-${PHP_DEBIAN_RELEASE # copy docker entrypoints from the *real* nginx image directly COPY --link --from=nginx-image /docker-entrypoint.d /docker/entrypoint.d/ -COPY contrib/docker/nginx/root / -COPY contrib/docker/nginx/Procfile . +COPY docker/nginx/root / +COPY docker/nginx/Procfile . STOPSIGNAL SIGQUIT diff --git a/contrib/docker-compose/.env b/contrib/docker-compose/.env deleted file mode 100644 index c9e235533..000000000 --- a/contrib/docker-compose/.env +++ /dev/null @@ -1,921 +0,0 @@ -# -*- mode: bash -*- -# vi: ft=bash - -############################################################### -# Docker-wide configuration -############################################################### - -# Path (relative) to the docker-compose file where containers will store their data -DOCKER_DATA_ROOT="./data" - -# Path (relative) to the docker-compose file where containers will store their config -DOCKER_CONFIG_ROOT="./config" - -# Pixelfed version (image tag) to pull from the registry -DOCKER_TAG="branch-jippi-fork-apache-8.1" - -# Set timezone used by *all* containers - these should be in sync -# -# See: https://www.php.net/manual/en/timezones.php -TZ="UTC" - -# Automatically run [artisan migrate --force] if new migrations are detected -DOCKER_APPLY_NEW_MIGRATIONS_AUTOMATICALLY="0" - -############################################################### -# Pixelfed application configuration -############################################################### - -# A random 32-character string to be used as an encryption key. -# -# No default value; use [php artisan key:generate] to generate. -# -# This key is used by the Illuminate encrypter service and should be set to a random, -# 32 character string, otherwise these encrypted strings will not be safe. -# -# Please do this before deploying an application! -# -# See: https://docs.pixelfed.org/technical-documentation/config/#app_key -APP_KEY= - -# See: https://docs.pixelfed.org/technical-documentation/config/#app_name-1 -APP_NAME="Pixelfed Prod" - -# Application domains used for routing. -# -# See: https://docs.pixelfed.org/technical-documentation/config/#app_domain -APP_DOMAIN="pixelfed-test.jippi.dev" - -# This URL is used by the console to properly generate URLs when using the Artisan command line tool. -# You should set this to the root of your application so that it is used when running Artisan tasks. -# -# See: https://docs.pixelfed.org/technical-documentation/config/#app_url -APP_URL=https://${APP_DOMAIN} - -# Application domains used for routing. -# -# See: https://docs.pixelfed.org/technical-documentation/config/#admin_domain -ADMIN_DOMAIN="${APP_DOMAIN}" - -# This value determines the “environment” your application is currently running in. -# This may determine how you prefer to configure various services your application utilizes. -# -# See: https://docs.pixelfed.org/technical-documentation/config/#app_env -#APP_ENV="production" - -# When your application is in debug mode, detailed error messages with stack traces will -# be shown on every error that occurs within your application. -# -# If disabled, a simple generic error page is shown. -# -# See: https://docs.pixelfed.org/technical-documentation/config/#app_debug -#APP_DEBUG="false" - -# Enable/disable new local account registrations. -# -# See: https://docs.pixelfed.org/technical-documentation/config/#open_registration -#OPEN_REGISTRATION=true - -# Require email verification before a new user can do anything. -# -# Defaults to "true". -# -# See: https://docs.pixelfed.org/technical-documentation/config/#enforce_email_verification -#ENFORCE_EMAIL_VERIFICATION="true" - -# Allow a maximum number of user accounts. -# -# Defaults to "1000". -# -# See: https://docs.pixelfed.org/technical-documentation/config/#pf_max_users -PF_MAX_USERS="false" - -# See: https://docs.pixelfed.org/technical-documentation/config/#oauth_enabled -OAUTH_ENABLED="true" - -# Defaults to "UTC". -# -# Do not edit your timezone or things will break! -# -# See: https://docs.pixelfed.org/technical-documentation/config/#app_timezone -# See: https://www.php.net/manual/en/timezones.php -APP_TIMEZONE="${TZ}" - -# The application locale determines the default locale that will be used by the translation service provider. -# You are free to set this value to any of the locales which will be supported by the application. -# -# Defaults to "en". -# -# See: https://docs.pixelfed.org/technical-documentation/config/#app_locale -#APP_LOCALE="en" - -# The fallback locale determines the locale to use when the current one is not available. -# -# You may change the value to correspond to any of the language folders that are provided through your application. -# -# Defaults to "en". -# -# See: https://docs.pixelfed.org/technical-documentation/config/#app_fallback_locale -#APP_FALLBACK_LOCALE="en" - -# See: https://docs.pixelfed.org/technical-documentation/config/#limit_account_size -#LIMIT_ACCOUNT_SIZE="true" - -# Update the max account size, the per user limit of files in kB. -# -# Defaults to "1000000" (1GB). -# -# See: https://docs.pixelfed.org/technical-documentation/config/#max_account_size-kb -#MAX_ACCOUNT_SIZE="1000000" - -# Update the max photo size, in kB. -# -# Defaults to "15000" (15MB). -# -# See: https://docs.pixelfed.org/technical-documentation/config/#max_photo_size-kb -#MAX_PHOTO_SIZE="15000" - -# Update the max avatar size, in kB. -# -# Defaults to "2000" (2MB). -# -# See: https://docs.pixelfed.org/technical-documentation/config/#max_avatar_size-kb -#MAX_AVATAR_SIZE="2000" - -# Change the caption length limit for new local posts. -# -# Defaults to "500". -# -# See: https://docs.pixelfed.org/technical-documentation/config/#max_caption_length -#MAX_CAPTION_LENGTH="500" - -# Change the bio length limit for user profiles. -# -# Defaults to "125". -# -# See: https://docs.pixelfed.org/technical-documentation/config/#max_bio_length -#MAX_BIO_LENGTH="125" - -# Change the length limit for user names. -# -# Defaults to "30". -# -# See: https://docs.pixelfed.org/technical-documentation/config/#max_name_length -#MAX_NAME_LENGTH="30" - -# The max number of photos allowed per post. -# -# Defaults to "4". -# -# See: https://docs.pixelfed.org/technical-documentation/config/#max_album_length -#MAX_ALBUM_LENGTH="4" - -# Resize and optimize image uploads. -# -# Defaults to "true". -# -# See: https://docs.pixelfed.org/technical-documentation/config/#pf_optimize_images -#PF_OPTIMIZE_IMAGES="true" - -# Set the image optimization quality, must be a value between 1-100. -# -# Defaults to "80". -# -# See: https://docs.pixelfed.org/technical-documentation/config/#image_quality -#IMAGE_QUALITY="80" - -# Resize and optimize video uploads. -# -# Defaults to "true". -# -# See: https://docs.pixelfed.org/technical-documentation/config/#pf_optimize_videos -#PF_OPTIMIZE_VIDEOS="true" - -# Enable account deletion. -# -# Defaults to "true". -# -# See: https://docs.pixelfed.org/technical-documentation/config/#account_deletion -#ACCOUNT_DELETION="true" - -# Set account deletion queue after X days, set to false to delete accounts immediately. -# -# Defaults to "false". -# -# See: https://docs.pixelfed.org/technical-documentation/config/#account_delete_after -#ACCOUNT_DELETE_AFTER="false" - -# Defaults to "Pixelfed - Photo sharing for everyone". -# -# See: https://docs.pixelfed.org/technical-documentation/config/#instance_description -#INSTANCE_DESCRIPTION= - -# Defaults to "false". -# -# See: https://docs.pixelfed.org/technical-documentation/config/#instance_public_hashtags -#INSTANCE_PUBLIC_HASHTAGS="false" - -# Defaults to "". -# -# See: https://docs.pixelfed.org/technical-documentation/config/#instance_contact_email -INSTANCE_CONTACT_EMAIL="admin@${APP_DOMAIN}" - -# Defaults to "false". -# -# See: https://docs.pixelfed.org/technical-documentation/config/#instance_public_local_timeline -#INSTANCE_PUBLIC_LOCAL_TIMELINE="false" - -# Defaults to "". -# -# See: https://docs.pixelfed.org/technical-documentation/config/#banned_usernames -#BANNED_USERNAMES= - -# Defaults to "false". -# -# See: https://docs.pixelfed.org/technical-documentation/config/#stories_enabled -#STORIES_ENABLED="false" - -# Defaults to "false". -# -# Level is hardcoded to 1. -# -# See: https://docs.pixelfed.org/technical-documentation/config/#restricted_instance -#RESTRICTED_INSTANCE="false" - -############################################################### -# Database configuration -############################################################### - -# Here you may specify which of the database connections below you wish to use as your default connection for all database work. -# -# Of course you may use many connections at once using the database library. -# -# Possible values: -# -# - "sqlite" -# - "mysql" (default) -# - "pgsql" -# - "sqlsrv" -# -# See: https://docs.pixelfed.org/technical-documentation/config/#db_connection -DB_CONNECTION="mysql" - -# See: https://docs.pixelfed.org/technical-documentation/config/#db_host -DB_HOST="db" - -# See: https://docs.pixelfed.org/technical-documentation/config/#db_username -DB_USERNAME="pixelfed" - -# See: https://docs.pixelfed.org/technical-documentation/config/#db_password -DB_PASSWORD="helloworld" - -# See: https://docs.pixelfed.org/technical-documentation/config/#db_database -DB_DATABASE="pixelfed_prod" - -# Use "3306" for MySQL/MariaDB and "5432" for PostgreeSQL -# -# See: https://docs.pixelfed.org/technical-documentation/config/#db_port -DB_PORT="3306" - -ENTRYPOINT_DEBUG=0 - -############################################################### -# Mail configuration -############################################################### - -# Laravel supports both SMTP and PHP’s “mail” function as drivers for the sending of e-mail. -# You may specify which one you’re using throughout your application here. -# -# Possible values: -# -# "smtp" (default) -# "sendmail" -# "mailgun" -# "mandrill" -# "ses" -# "sparkpost" -# "log" -# "array" -# -# See: https://docs.pixelfed.org/technical-documentation/config/#mail_driver -#MAIL_DRIVER="smtp" - -# The host address of the SMTP server used by your applications. -# -# A default option is provided that is compatible with the Mailgun mail service which will provide reliable deliveries. -# -# Defaults to "smtp.mailgun.org". -# -# See: https://docs.pixelfed.org/technical-documentation/config/#mail_host -#MAIL_HOST="smtp.mailgun.org" - -# This is the SMTP port used by your application to deliver e-mails to users of the application. -# -# Like the host we have set this value to stay compatible with the Mailgun e-mail application by default. -# -# Defaults to 587. -# -# See: https://docs.pixelfed.org/technical-documentation/config/#mail_port -#MAIL_PORT="587" - -# You may wish for all e-mails sent by your application to be sent from the same address. -# -# Here, you may specify a name and address that is used globally for all e-mails that are sent by your application. -# -# Defaults to "hello@example.com". -# -# See: https://docs.pixelfed.org/technical-documentation/config/#mail_from_address -MAIL_FROM_ADDRESS="hello@${APP_DOMAIN}" - -# Defaults to "Example". -# -# See: https://docs.pixelfed.org/technical-documentation/config/#mail_from_name -MAIL_FROM_NAME="Pixelfed @ ${APP_DOMAIN}" - -# If your SMTP server requires a username for authentication, you should set it here. -# -# This will get used to authenticate with your server on connection. -# You may also set the “password” value below this one. -# -# Defaults to "". -# -# See: https://docs.pixelfed.org/technical-documentation/config/#mail_username -#MAIL_USERNAME= - -# Defaults to "". -# -# See: https://docs.pixelfed.org/technical-documentation/config/#mail_password -#MAIL_PASSWORD= - -# Here you may specify the encryption protocol that should be used when the application send e-mail messages. -# -# A sensible default using the transport layer security protocol should provide great security. -# -# Defaults to "tls". -# -# See: https://docs.pixelfed.org/technical-documentation/config/#mail_encryption -#MAIL_ENCRYPTION="tls" - -############################################################### -# Redis configuration -############################################################### - -# Defaults to "phpredis". -# -# See: https://docs.pixelfed.org/technical-documentation/config/#db_username -#REDIS_CLIENT="phpredis" - -# Defaults to "tcp". -# -# See: https://docs.pixelfed.org/technical-documentation/config/#redis_scheme -#REDIS_SCHEME="tcp" - -# Defaults to "localhost". -# -# See: https://docs.pixelfed.org/technical-documentation/config/#redis_host -REDIS_HOST="redis" - -# Defaults to null. -# -# See: https://docs.pixelfed.org/technical-documentation/config/#redis_password -#REDIS_PASSWORD= - -# Defaults to 6379. -# -# See: https://docs.pixelfed.org/technical-documentation/config/#redis_port -REDIS_PORT="6379" - -# Defaults to 0. -# -# See: https://docs.pixelfed.org/technical-documentation/config/#redis_database -#REDIS_DATABASE="0" - -############################################################### -# Cache settings -############################################################### - -# This option controls the default cache connection that gets used while using this caching library. -# -# This connection is used when another is not explicitly specified when executing a given caching function. -# -# Possible values: -# - "apc" -# - "array" -# - "database" -# - "file" (default) -# - "memcached" -# - "redis" -# -# See: https://docs.pixelfed.org/technical-documentation/config/#cache_driver -CACHE_DRIVER="redis" - -# Defaults to ${APP_NAME}_cache, or laravel_cache if no APP_NAME is set. -# -# See: https://docs.pixelfed.org/technical-documentation/config/#cache_prefix -# CACHE_PREFIX="{APP_NAME}_cache" - -############################################################### -# Horizon settings -############################################################### - -# This prefix will be used when storing all Horizon data in Redis. -# -# You may modify the prefix when you are running multiple installations -# of Horizon on the same server so that they don’t have problems. -# -# Defaults to "horizon-". -# -# See: https://docs.pixelfed.org/technical-documentation/config/#horizon_prefix -#HORIZON_PREFIX="horizon-" - -# Defaults to "false". -# -# See: https://docs.pixelfed.org/technical-documentation/config/#horizon_darkmode -#HORIZON_DARKMODE="false" - -# This value (in MB) describes the maximum amount of memory (in MB) the Horizon worker -# may consume before it is terminated and restarted. -# -# You should set this value according to the resources available to your server. -# -# Defaults to "64". -#HORIZON_MEMORY_LIMIT="64" - -# See: https://docs.pixelfed.org/technical-documentation/config/#horizon_balance_strategy -#HORIZON_BALANCE_STRATEGY="auto" - -# See: https://docs.pixelfed.org/technical-documentation/config/#horizon_min_processes -#HORIZON_MIN_PROCESSES="1" - -# See: https://docs.pixelfed.org/technical-documentation/config/#horizon_max_processes -#HORIZON_MAX_PROCESSES="20" - -# See: https://docs.pixelfed.org/technical-documentation/config/#horizon_supervisor_memory -#HORIZON_SUPERVISOR_MEMORY="64" - -# See: https://docs.pixelfed.org/technical-documentation/config/#horizon_supervisor_tries -#HORIZON_SUPERVISOR_TRIES="3" - -# See: https://docs.pixelfed.org/technical-documentation/config/#horizon_supervisor_nice -#HORIZON_SUPERVISOR_NICE="0" - -# See: https://docs.pixelfed.org/technical-documentation/config/#horizon_supervisor_timeout -#HORIZON_SUPERVISOR_TIMEOUT="300" - -############################################################### -# Experiments -############################################################### - -# Text only posts (alpha). -# -# Defaults to "false". -# -# See: https://docs.pixelfed.org/technical-documentation/config/#exp_top -#EXP_TOP="false" - -# Poll statuses (alpha). -# -# Defaults to "false". -# -# See: https://docs.pixelfed.org/technical-documentation/config/#exp_polls -#EXP_POLLS="false" - -# Cached public timeline for larger instances (beta). -# -# Defaults to "false". -# -# See: https://docs.pixelfed.org/technical-documentation/config/#exp_cpt -#EXP_CPT="false" - -# Enforce Mastoapi Compatibility (alpha). -# -# Defaults to "true". -# -# See: https://docs.pixelfed.org/technical-documentation/config/#exp_emc -EXP_EMC="true" - -############################################################### -# ActivityPub confguration -############################################################### - -# Defaults to "false". -# -# See: https://docs.pixelfed.org/technical-documentation/config/#activity_pub -ACTIVITY_PUB="true" - -# Defaults to "true". -# -# See: https://docs.pixelfed.org/technical-documentation/config/#ap_remote_follow -#AP_REMOTE_FOLLOW="true" - -# Defaults to "true". -# -# See: https://docs.pixelfed.org/technical-documentation/config/#ap_sharedinbox -#AP_SHAREDINBOX="true" - -# Defaults to "true". -# -# See: https://docs.pixelfed.org/technical-documentation/config/#ap_inbox -#AP_INBOX="true" - -# Defaults to "true". -# -# See: https://docs.pixelfed.org/technical-documentation/config/#ap_outbox -#AP_OUTBOX="true" - -############################################################### -# Federation confguration -############################################################### - -# Defaults to "true". -# -# See: https://docs.pixelfed.org/technical-documentation/config/#atom_feeds -#ATOM_FEEDS="true" - -# Defaults to "true". -# -# See: https://docs.pixelfed.org/technical-documentation/config/#nodeinfo -#NODEINFO="true" - -# Defaults to "true". -# -# See: https://docs.pixelfed.org/technical-documentation/config/#webfinger -#WEBFINGER="true" - -############################################################### -# Storage (cloud) -############################################################### - -# Store media on object storage like S3, Digital Ocean Spaces, Rackspace -# -# Defaults to "false". -# -# See: https://docs.pixelfed.org/technical-documentation/config/#pf_enable_cloud -#PF_ENABLE_CLOUD="false" - -# Many applications store files both locally and in the cloud. -# -# For this reason, you may specify a default “cloud” driver here. -# This driver will be bound as the Cloud disk implementation in the container. -# -# Defaults to "s3". -# -# See: https://docs.pixelfed.org/technical-documentation/config/#filesystem_cloud -#FILESYSTEM_CLOUD="s3" - -# Defaults to true. -# -# See: https://docs.pixelfed.org/technical-documentation/config/#media_delete_local_after_cloud -#MEDIA_DELETE_LOCAL_AFTER_CLOUD="true" - -############################################################### -# Storage (cloud) - S3 -############################################################### - -# See: https://docs.pixelfed.org/technical-documentation/config/#aws_access_key_id -#AWS_ACCESS_KEY_ID= - -# See: https://docs.pixelfed.org/technical-documentation/config/#aws_secret_access_key -#AWS_SECRET_ACCESS_KEY= - -# See: https://docs.pixelfed.org/technical-documentation/config/#aws_default_region -#AWS_DEFAULT_REGION= - -# See: https://docs.pixelfed.org/technical-documentation/config/#aws_bucket -#AWS_BUCKET= - -# See: https://docs.pixelfed.org/technical-documentation/config/#aws_url -#AWS_URL= - -# See: https://docs.pixelfed.org/technical-documentation/config/#aws_endpoint -#AWS_ENDPOINT= - -# See: https://docs.pixelfed.org/technical-documentation/config/#aws_use_path_style_endpoint -#AWS_USE_PATH_STYLE_ENDPOINT="false" - -############################################################### -# COSTAR - Confirm Object Sentiment Transform and Reduce -############################################################### - -# Comma-separated list of domains to block. -# -# Defaults to null -# -# See: https://docs.pixelfed.org/technical-documentation/config/#cs_blocked_domains -#CS_BLOCKED_DOMAINS= - -# Comma-separated list of domains to add warnings. -# -# Defaults to null. -# -# See: https://docs.pixelfed.org/technical-documentation/config/#cs_cw_domains -#CS_CW_DOMAINS= - -# Comma-separated list of domains to remove from public timelines. -# -# Defaults to null. -# -# See: https://docs.pixelfed.org/technical-documentation/config/#cs_unlisted_domains -#CS_UNLISTED_DOMAINS= - -# Comma-separated list of keywords to block. -# -# Defaults to null. -# -# See: https://docs.pixelfed.org/technical-documentation/config/#cs_blocked_keywords -#CS_BLOCKED_KEYWORDS= - -# Comma-separated list of keywords to add warnings. -# -# Defaults to null. -# -# See: https://docs.pixelfed.org/technical-documentation/config/#cs_cw_keywords -#CS_CW_KEYWORDS= - -# Comma-separated list of keywords to remove from public timelines. -# -# Defaults to null. -# -# See: https://docs.pixelfed.org/technical-documentation/config/#cs_unlisted_keywords -#CS_UNLISTED_KEYWORDS= - -# Defaults to null. -# -# See: https://docs.pixelfed.org/technical-documentation/config/#cs_blocked_actor -#CS_BLOCKED_ACTOR= - -# Defaults to null. -# -# See: https://docs.pixelfed.org/technical-documentation/config/#cs_cw_actor -#CS_CW_ACTOR= - -# Defaults to null. -# -# See: https://docs.pixelfed.org/technical-documentation/config/#cs_unlisted_actor -#CS_UNLISTED_ACTOR= - -############################################################### -# Media -############################################################### - -# Defaults to false. -# -# See: https://docs.pixelfed.org/technical-documentation/config/#media_exif_database -MEDIA_EXIF_DATABASE="true" - -# Pixelfed supports GD or ImageMagick to process images. -# -# Defaults to "gd". -# -# Possible values: -# - "gd" (default) -# - "imagick" -# -# See: https://docs.pixelfed.org/technical-documentation/config/#image_driver -#IMAGE_DRIVER="gd" - -############################################################### -# Logging -############################################################### - -# Possible values: -# -# - "stack" (default) -# - "single" -# - "daily" -# - "slack" -# - "stderr" -# - "syslog" -# - "errorlog" -# - "null" -# - "emergency" -# - "media" -LOG_CHANNEL="stderr" - -# Used by single, stderr and syslog. -# -# Defaults to "debug" for all of those. -# -# See: https://docs.pixelfed.org/technical-documentation/config/#log_level -#LOG_LEVEL="debug" - -# Used by stderr. -# -# Defaults to "". -# -# See: https://docs.pixelfed.org/technical-documentation/config/#log_stderr_formatter -#LOG_STDERR_FORMATTER= - -# Used by slack. -# -# Defaults to "". -# -# See: https://docs.pixelfed.org/technical-documentation/config/#log_slack_webhook_url -#LOG_SLACK_WEBHOOK_URL= - -############################################################### -# Broadcasting settings -############################################################### - -# This option controls the default broadcaster that will be used by the framework when an event needs to be broadcast. -# -# Possible values: -# - "pusher" -# - "redis" -# - "log" -# - "null" (default) -# -# See: https://docs.pixelfed.org/technical-documentation/config/#broadcast_driver -BROADCAST_DRIVER=redis - -############################################################### -# Other settings -############################################################### - -# Defaults to true. -# -# See: https://docs.pixelfed.org/technical-documentation/config/#restrict_html_types -#RESTRICT_HTML_TYPES="true" - -############################################################### -# Queue configuration -############################################################### - -# Possible values: -# - "sync" (default) -# - "database" -# - "beanstalkd" -# - "sqs" -# - "redis" -# - "null" -# -# See: https://docs.pixelfed.org/technical-documentation/config/#queue_driver -QUEUE_DRIVER="redis" - -############################################################### -# Queue (SQS) configuration -############################################################### - -# Defaults to "your-public-key". -# -# See: https://docs.pixelfed.org/technical-documentation/config/#sqs_key -#SQS_KEY="your-public-key" - -# Defaults to "your-secret-key". -# -# See: https://docs.pixelfed.org/technical-documentation/config/#sqs_secret -#SQS_SECRET="your-secret-key" - -# Defaults to "https://sqs.us-east-1.amazonaws.com/your-account-id". -# -# See: https://docs.pixelfed.org/technical-documentation/config/#sqs_prefix -#SQS_PREFIX= - -# Defaults to "your-queue-name". -# -# https://docs.pixelfed.org/technical-documentation/config/#sqs_queue -#SQS_QUEUE="your-queue-name" - -# Defaults to "us-east-1". -# -# See: https://docs.pixelfed.org/technical-documentation/config/#sqs_region -#SQS_REGION="us-east-1" - -############################################################### -# Session configuration -############################################################### - -# This option controls the default session “driver” that will be used on requests. -# -# By default, we will use the lightweight native driver but you may specify any of the other wonderful drivers provided here. -# -# Possible values: -# - "file" -# - "cookie" -# - "database" (default) -# - "apc" -# - "memcached" -# - "redis" -# - "array" -SESSION_DRIVER="redis" - -# Here you may specify the number of minutes that you wish the session to be allowed to remain idle before it expires. -# -# If you want them to immediately expire on the browser closing, set that option. -# -# Defaults to 86400. -# -# See: https://docs.pixelfed.org/technical-documentation/config/#session_lifetime -#SESSION_LIFETIME="86400" - -# Here you may change the domain of the cookie used to identify a session in your application. -# -# This will determine which domains the cookie is available to in your application. -# -# A sensible default has been set. -# -# Defaults to the value of APP_DOMAIN, or null. -# -# See: https://docs.pixelfed.org/technical-documentation/config/#session_domain -#SESSION_DOMAIN="${APP_DOMAIN}" - -############################################################### -# Proxy configuration -############################################################### - -# Set trusted proxy IP addresses. -# -# Both IPv4 and IPv6 addresses are supported, along with CIDR notation. -# -# The “*” character is syntactic sugar within TrustedProxy to trust any -# proxy that connects directly to your server, a requirement when you cannot -# know the address of your proxy (e.g. if using Rackspace balancers). -# -# The “**” character is syntactic sugar within TrustedProxy to trust not just any -# proxy that connects directly to your server, but also proxies that connect to those proxies, -# and all the way back until you reach the original source IP. It will mean that -# $request->getClientIp() always gets the originating client IP, no matter how many proxies -# that client’s request has subsequently passed through. -# -# Defaults to "*". -# -# See: https://docs.pixelfed.org/technical-documentation/config/#trust_proxies -TRUST_PROXIES="*" - -############################################################### -# Passport configuration -############################################################### -# -# Passport uses encryption keys while generating secure access tokens -# for your application. -# -# By default, the keys are stored as local files but can be set via environment -# variables when that is more convenient. - -# See: https://docs.pixelfed.org/technical-documentation/config/#passport_private_key -#PASSPORT_PRIVATE_KEY= - -# See: https://docs.pixelfed.org/technical-documentation/config/#passport_public_key -#PASSPORT_PUBLIC_KEY= - -############################################################### -# PHP configuration -############################################################### - -# See: https://www.php.net/manual/en/ini.core.php#ini.memory-limit -#PHP_MEMORY_LIMIT="128M" - -############################################################### -# MySQL DB container configuration (DO NOT CHANGE) -############################################################### -# -# See "Environment Variables" at https://hub.docker.com/_/mysql - -MYSQL_ROOT_PASSWORD="${DB_PASSWORD}" -MYSQL_USER="${DB_USERNAME}" -MYSQL_PASSWORD="${DB_PASSWORD}" -MYSQL_DATABASE="${DB_DATABASE}" - -############################################################### -# MySQL (MariaDB) DB container configuration (DO NOT CHANGE) -############################################################### -# -# See "Start a mariadb server instance with user, password and database" at https://hub.docker.com/_/mariadb - -MARIADB_ROOT_PASSWORD="${DB_PASSWORD}" -MARIADB_USER="${DB_USERNAME}" -MARIADB_PASSWORD="${DB_PASSWORD}" -MARIADB_DATABASE="${DB_DATABASE}" - -############################################################### -# PostgreSQL DB container configuration (DO NOT CHANGE) -############################################################### -# -# See "Environment Variables" at https://hub.docker.com/_/postgres - -POSTGRES_USER="${DB_USERNAME}" -POSTGRES_PASSWORD="${DB_PASSWORD}" -POSTGRES_DB="${DB_DATABASE}" - -############################################################### -# Docker Specific configuration -############################################################### - -# Image to pull the Pixelfed Docker images from -# -# Possible values: -# - "ghcr.io/pixelfed/pixelfed" to pull from GitHub -# - "pixelfed/pixelfed" to pull from DockerHub -# -DOCKER_IMAGE="ghcr.io/jippi/pixelfed" - -# Port that Redis will listen on *outside* the container (e.g. the host machine) -DOCKER_REDIS_PORT_EXTERNAL="${REDIS_PORT}" - -# Port that the database will listen on *outside* the container (e.g. the host machine) -# -# Use "3306" for MySQL/MariaDB and "5432" for PostgreeSQL -DOCKER_DB_PORT_EXTERNAL="${DB_PORT}" - -# Port that the web will listen on *outside* the container (e.g. the host machine) -DOCKER_WEB_PORT_EXTERNAL="8080" diff --git a/contrib/docker-compose/README.md b/contrib/docker-compose/README.md deleted file mode 100644 index 137773f08..000000000 --- a/contrib/docker-compose/README.md +++ /dev/null @@ -1,34 +0,0 @@ -# Pixelfed + Docker + Docker Compose - -## Prerequisites - -* One of the `docker-compose.yml` files in this directory -* A copy of the `example.env` file named `.env` next to `docker-compose.yml` - -Your folder should look like this - -```plain -. -├── .env -└── docker-compose.yml -``` - -## Modifying your settings (`.env` file) - -Minimum required settings to change is: - -* `APP_NAME` -* `APP_DOMAIN` -* `DB_PASSWORD` - -See the [`Configure environment variables`](https://docs.pixelfed.org/running-pixelfed/installation/#app-variables) documentation for details! - -You need to mainly focus on following sections - -* [App variables](https://docs.pixelfed.org/running-pixelfed/installation/#app-variables) -* [Email variables](https://docs.pixelfed.org/running-pixelfed/installation/#email-variables) - -Since the following things are configured for you out of the box: - -* `Redis` -* `Database` (except for `DB_PASSWORD`) diff --git a/contrib/docker-compose/docker-compose.yml b/contrib/docker-compose/docker-compose.yml deleted file mode 100644 index e43e36c78..000000000 --- a/contrib/docker-compose/docker-compose.yml +++ /dev/null @@ -1,67 +0,0 @@ ---- -version: "3" - -services: - web: - image: "${DOCKER_IMAGE}:${DOCKER_TAG}" - # build: - # context: ../.. - # dockerfile: contrib/docker/Dockerfile - # target: apache-runtime - restart: unless-stopped - env_file: - - "./.env" - volumes: - - "./.env:/var/www/.env" - - "${DOCKER_DATA_ROOT}/pixelfed/cache:/var/www/bootstrap/cache" - - "${DOCKER_DATA_ROOT}/pixelfed/storage:/var/www/storage" - ports: - - "${DOCKER_WEB_PORT_EXTERNAL}:80" - depends_on: - - db - - redis - - worker: - image: "${DOCKER_IMAGE}:${DOCKER_TAG}" - # build: - # context: ../.. - # dockerfile: contrib/docker/Dockerfile - # target: apache-runtime - command: gosu www-data php artisan horizon - restart: unless-stopped - env_file: - - "./.env" - volumes: - - "./.env:/var/www/.env" - - "${DOCKER_DATA_ROOT}/pixelfed/cache:/var/www/bootstrap/cache" - - "${DOCKER_DATA_ROOT}/pixelfed/storage:/var/www/storage" - depends_on: - - db - - redis - - db: - image: mariadb:11.2 - command: --default-authentication-plugin=mysql_native_password - restart: unless-stopped - env_file: - - "./.env" - volumes: - - "${DOCKER_DATA_ROOT}/db:/var/lib/mysql" - ports: - - "${DOCKER_DB_PORT_EXTERNAL}:3306" - - redis: - image: redis:7 - restart: unless-stopped - env_file: - - "./.env" - volumes: - - "${DOCKER_CONFIG_ROOT}/redis:/etc/redis" - - "${DOCKER_DATA_ROOT}/redis:/data" - ports: - - "${DOCKER_REDIS_PORT_EXTERNAL}:6399" - healthcheck: - interval: 10s - timeout: 5s - retries: 2 - test: ["CMD", "redis-cli", "-p", "6399", "ping"] diff --git a/docker-compose.yml b/docker-compose.yml index 6fca2eeb3..4b93c75e9 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -1,82 +1,59 @@ --- -version: '3' +version: "3" -# In order to set configuration, please use a .env file in -# your compose project directory (the same directory as your -# docker-compose.yml), and set database options, application -# name, key, and other settings there. -# A list of available settings is available in .env.example -# -# The services should scale properly across a swarm cluster -# if the volumes are properly shared between cluster members. +############################################################### +# Please see docker/README.md for usage information +############################################################### services: -## App and Worker - app: - # Comment to use dockerhub image - image: pixelfed/pixelfed:latest + web: + image: "${DOCKER_IMAGE}:${DOCKER_TAG}" + # build: + # target: apache-runtime restart: unless-stopped - env_file: - - .env.docker volumes: - - app-storage:/var/www/storage - - app-bootstrap:/var/www/bootstrap - - "./.env.docker:/var/www/.env" - networks: - - external - - internal + - "./.env:/var/www/.env" + - "${DOCKER_DATA_ROOT}/pixelfed/cache:/var/www/bootstrap/cache" + - "${DOCKER_DATA_ROOT}/pixelfed/storage:/var/www/storage" ports: - - "8080:80" + - "${DOCKER_WEB_PORT_EXTERNAL}:80" depends_on: - db - redis worker: - image: pixelfed/pixelfed:latest - restart: unless-stopped - env_file: - - .env.docker - volumes: - - app-storage:/var/www/storage - - app-bootstrap:/var/www/bootstrap - networks: - - external - - internal + image: "${DOCKER_IMAGE}:${DOCKER_TAG}" + # build: + # target: apache-runtime command: gosu www-data php artisan horizon + restart: unless-stopped + volumes: + - "./.env:/var/www/.env" + - "${DOCKER_DATA_ROOT}/pixelfed/cache:/var/www/bootstrap/cache" + - "${DOCKER_DATA_ROOT}/pixelfed/storage:/var/www/storage" depends_on: - db - redis -## DB and Cache db: - image: mariadb:jammy - restart: unless-stopped - networks: - - internal + image: mariadb:11.2 command: --default-authentication-plugin=mysql_native_password - env_file: - - .env.docker + restart: unless-stopped volumes: - - "db-data:/var/lib/mysql" + - "${DOCKER_DATA_ROOT}/db:/var/lib/mysql" + ports: + - "${DOCKER_DB_PORT_EXTERNAL}:3306" redis: - image: redis:5-alpine + image: redis:7 restart: unless-stopped - env_file: - - .env.docker volumes: - - "redis-data:/data" - networks: - - internal - -volumes: - db-data: - redis-data: - app-storage: - app-bootstrap: - -networks: - internal: - internal: true - external: - driver: bridge + - "${DOCKER_CONFIG_ROOT}/redis:/etc/redis" + - "${DOCKER_DATA_ROOT}/redis:/data" + ports: + - "${DOCKER_REDIS_PORT_EXTERNAL}:6399" + healthcheck: + interval: 10s + timeout: 5s + retries: 2 + test: ["CMD", "redis-cli", "-p", "6399", "ping"] diff --git a/contrib/docker/README.md b/docker/README.md similarity index 91% rename from contrib/docker/README.md rename to docker/README.md index 443ab6423..03bc31246 100644 --- a/contrib/docker/README.md +++ b/docker/README.md @@ -1,4 +1,37 @@ -# Pixelfed Docker images +# Pixelfed + Docker + Docker Compose + +## Prerequisites + +* One of the `docker-compose.yml` files in this directory +* A copy of the `example.env` file named `.env` next to `docker-compose.yml` + +Your folder should look like this + +```plain +. +├── .env +└── docker-compose.yml +``` + +## Modifying your settings (`.env` file) + +Minimum required settings to change is: + +* `APP_NAME` +* `APP_DOMAIN` +* `DB_PASSWORD` + +See the [`Configure environment variables`](https://docs.pixelfed.org/running-pixelfed/installation/#app-variables) documentation for details! + +You need to mainly focus on following sections + +* [App variables](https://docs.pixelfed.org/running-pixelfed/installation/#app-variables) +* [Email variables](https://docs.pixelfed.org/running-pixelfed/installation/#email-variables) + +Since the following things are configured for you out of the box: + +* `Redis` +* `Database` (except for `DB_PASSWORD`) ## Runtimes diff --git a/contrib/docker/apache/root/etc/apache2/conf-available/remoteip.conf b/docker/apache/root/etc/apache2/conf-available/remoteip.conf similarity index 100% rename from contrib/docker/apache/root/etc/apache2/conf-available/remoteip.conf rename to docker/apache/root/etc/apache2/conf-available/remoteip.conf diff --git a/contrib/docker/fpm/root/.gitkeep b/docker/fpm/root/.gitkeep similarity index 100% rename from contrib/docker/fpm/root/.gitkeep rename to docker/fpm/root/.gitkeep diff --git a/contrib/docker/nginx/Procfile b/docker/nginx/Procfile similarity index 100% rename from contrib/docker/nginx/Procfile rename to docker/nginx/Procfile diff --git a/contrib/docker/nginx/root/docker/templates/etc/nginx/conf.d/default.conf b/docker/nginx/root/docker/templates/etc/nginx/conf.d/default.conf similarity index 100% rename from contrib/docker/nginx/root/docker/templates/etc/nginx/conf.d/default.conf rename to docker/nginx/root/docker/templates/etc/nginx/conf.d/default.conf diff --git a/contrib/docker/shared/root/docker/entrypoint.d/01-permissions.sh b/docker/shared/root/docker/entrypoint.d/01-permissions.sh similarity index 100% rename from contrib/docker/shared/root/docker/entrypoint.d/01-permissions.sh rename to docker/shared/root/docker/entrypoint.d/01-permissions.sh diff --git a/contrib/docker/shared/root/docker/entrypoint.d/04-defaults.envsh b/docker/shared/root/docker/entrypoint.d/04-defaults.envsh similarity index 100% rename from contrib/docker/shared/root/docker/entrypoint.d/04-defaults.envsh rename to docker/shared/root/docker/entrypoint.d/04-defaults.envsh diff --git a/contrib/docker/shared/root/docker/entrypoint.d/05-templating.sh b/docker/shared/root/docker/entrypoint.d/05-templating.sh similarity index 100% rename from contrib/docker/shared/root/docker/entrypoint.d/05-templating.sh rename to docker/shared/root/docker/entrypoint.d/05-templating.sh diff --git a/contrib/docker/shared/root/docker/entrypoint.d/10-storage.sh b/docker/shared/root/docker/entrypoint.d/10-storage.sh similarity index 100% rename from contrib/docker/shared/root/docker/entrypoint.d/10-storage.sh rename to docker/shared/root/docker/entrypoint.d/10-storage.sh diff --git a/contrib/docker/shared/root/docker/entrypoint.d/11-first-time-setup.sh b/docker/shared/root/docker/entrypoint.d/11-first-time-setup.sh similarity index 100% rename from contrib/docker/shared/root/docker/entrypoint.d/11-first-time-setup.sh rename to docker/shared/root/docker/entrypoint.d/11-first-time-setup.sh diff --git a/contrib/docker/shared/root/docker/entrypoint.d/12-migrations.sh b/docker/shared/root/docker/entrypoint.d/12-migrations.sh similarity index 100% rename from contrib/docker/shared/root/docker/entrypoint.d/12-migrations.sh rename to docker/shared/root/docker/entrypoint.d/12-migrations.sh diff --git a/contrib/docker/shared/root/docker/entrypoint.d/20-horizon.sh b/docker/shared/root/docker/entrypoint.d/20-horizon.sh similarity index 100% rename from contrib/docker/shared/root/docker/entrypoint.d/20-horizon.sh rename to docker/shared/root/docker/entrypoint.d/20-horizon.sh diff --git a/contrib/docker/shared/root/docker/entrypoint.d/30-cache.sh b/docker/shared/root/docker/entrypoint.d/30-cache.sh similarity index 100% rename from contrib/docker/shared/root/docker/entrypoint.d/30-cache.sh rename to docker/shared/root/docker/entrypoint.d/30-cache.sh diff --git a/contrib/docker/shared/root/docker/entrypoint.sh b/docker/shared/root/docker/entrypoint.sh similarity index 100% rename from contrib/docker/shared/root/docker/entrypoint.sh rename to docker/shared/root/docker/entrypoint.sh diff --git a/contrib/docker/shared/root/docker/helpers.sh b/docker/shared/root/docker/helpers.sh similarity index 100% rename from contrib/docker/shared/root/docker/helpers.sh rename to docker/shared/root/docker/helpers.sh diff --git a/contrib/docker/shared/root/docker/install/base.sh b/docker/shared/root/docker/install/base.sh similarity index 100% rename from contrib/docker/shared/root/docker/install/base.sh rename to docker/shared/root/docker/install/base.sh diff --git a/contrib/docker/shared/root/docker/install/php-extensions.sh b/docker/shared/root/docker/install/php-extensions.sh similarity index 100% rename from contrib/docker/shared/root/docker/install/php-extensions.sh rename to docker/shared/root/docker/install/php-extensions.sh diff --git a/contrib/docker/shared/root/docker/templates/usr/local/etc/php/php.ini b/docker/shared/root/docker/templates/usr/local/etc/php/php.ini similarity index 100% rename from contrib/docker/shared/root/docker/templates/usr/local/etc/php/php.ini rename to docker/shared/root/docker/templates/usr/local/etc/php/php.ini From bd1cd9c4fc44bba07ad7dae02a9d9d33cf1ea11c Mon Sep 17 00:00:00 2001 From: Christian Winther Date: Sat, 6 Jan 2024 15:39:30 +0000 Subject: [PATCH 035/173] more docs --- .env.docker | 22 ++++----- docker/README.md | 117 +++++++++++++++++++++++++++++++++++++++++------ 2 files changed, 115 insertions(+), 24 deletions(-) diff --git a/.env.docker b/.env.docker index 10e88b8b5..0508e939a 100644 --- a/.env.docker +++ b/.env.docker @@ -5,12 +5,20 @@ # Docker-wide configuration ############################################################### -# Path (relative) to the docker-compose file where containers will store their data +# Path (relative to the docker-compose.yml) or absolute (/some/other/path) file where containers will store their data DOCKER_DATA_ROOT="./data" -# Path (relative) to the docker-compose file where containers will store their config +# Path (relative to the docker-compose.yml) or absolute (/some/other/path) file where containers will store their confguration DOCKER_CONFIG_ROOT="./config" +# Image to pull the Pixelfed Docker images from +# +# Possible values: +# - "ghcr.io/pixelfed/pixelfed" to pull from GitHub +# - "pixelfed/pixelfed" to pull from DockerHub +# +DOCKER_IMAGE="ghcr.io/jippi/pixelfed" + # Pixelfed version (image tag) to pull from the registry DOCKER_TAG="branch-jippi-fork-apache-8.1" @@ -569,7 +577,7 @@ ACTIVITY_PUB="true" #MEDIA_DELETE_LOCAL_AFTER_CLOUD="true" ############################################################### -# Storage (cloud) - S3 +# Storage (cloud) - S3 andS S3 *compatible* providers (most of them) ############################################################### # See: https://docs.pixelfed.org/technical-documentation/config/#aws_access_key_id @@ -901,14 +909,6 @@ POSTGRES_DB="${DB_DATABASE}" # Docker Specific configuration ############################################################### -# Image to pull the Pixelfed Docker images from -# -# Possible values: -# - "ghcr.io/pixelfed/pixelfed" to pull from GitHub -# - "pixelfed/pixelfed" to pull from DockerHub -# -DOCKER_IMAGE="ghcr.io/jippi/pixelfed" - # Port that Redis will listen on *outside* the container (e.g. the host machine) DOCKER_REDIS_PORT_EXTERNAL="${REDIS_PORT}" diff --git a/docker/README.md b/docker/README.md index 03bc31246..837c1f646 100644 --- a/docker/README.md +++ b/docker/README.md @@ -1,25 +1,103 @@ # Pixelfed + Docker + Docker Compose +This guide will help you install and run Pixelfed on **your** server using [Docker Compose](https://docs.docker.com/compose/). + ## Prerequisites -* One of the `docker-compose.yml` files in this directory -* A copy of the `example.env` file named `.env` next to `docker-compose.yml` +Recommendations and requirements for hardware and software needed to run Pixelfed using Docker Compose. -Your folder should look like this +It's highly recommended that you have *some* experience with Linux (e.g. Ubuntu or Debian), SSH, and lightweight server administration. -```plain -. -├── .env -└── docker-compose.yml -``` +### Server + +A VPS or dedicated server you can SSH into, for example + +* [linode.com VPS](https://www.linode.com/) +* [DigitalOcean VPS](https://digitalocean.com/) +* [Hetzner](https://www.hetzner.com/) + +### Hardware + +Hardware requirements depends on the amount of users you have (or plan to have), and how active they are. + +A safe starter/small instance hardware for 25 users and blow are: + +* **CPU/vCPU** `2` cores. +* **RAM** `2-4 GB` as your instance grow, memory requirements will increase for the database. +* **Storage** `20-50 GB` HDD is fine, but ideally SSD or NVMe, *especially* for the database. +* **Network** `100 Mbit/s` or faster. + +### Other + +* A **Domain** you need a domain (or subdomain) where your Pixelfed server will be running (for example, `pixelfed.social`) +* (Optional) An **Email/SMTP provider** for sending e-mails to your users, such as e-mail confirmation and notifications. +* (Optional) An **Object Storage** provider for storing all images remotely, rather than locally on your server. + +#### E-mail / SMTP provider + +**NOTE**: If you don't plan to use en e-mail/SMTP provider, then make sure to set `ENFORCE_EMAIL_VERIFICATION="false"` in your `.env` file! + +There are *many* providers out there, with wildly different pricing structures, features, and reliability. + +It's beyond the cope of this document to detail which provider to pick, or how to correctly configure them, but some providers that is known to be working well - with generous free tiers and affordable packages - are included for your convince (*in no particular order*) below: + +* [Simple Email Service (SES)](https://aws.amazon.com/ses/) by Amazon Web Services (AWS) is pay-as-you-go with a cost of $0.10/1000 emails. +* [Brevo](https://www.brevo.com/) (formerly SendInBlue) has a Free Tier with 300 emails/day. +* [Postmark](https://postmarkapp.com/) has a Free Tier with 100 emails/month. +* [Forward Email](https://forwardemail.net/en/private-business-email?pricing=true) has a $3/mo/domain plan with both sending and receiving included. +* [Mailtrap](https://mailtrap.io/email-sending/) has a 1000 emails/month free-tier (their `Email Sending` product, *not* the `Email Testing` one). + +#### Object Storage + +**NOTE**: This is *entirely* optional - by default Pixelfed will store all uploads (videos, images, etc.) directly on your servers storage. + +> Object storage is a technology that stores and manages data in an unstructured format called objects. Modern organizations create and analyze large volumes of unstructured data such as photos, videos, email, web pages, sensor data, and audio files +> +> -- [*What is object storage?*](https://aws.amazon.com/what-is/object-storage/) by Amazon Web Services + +It's beyond the cope of this document to detail which provider to pick, or how to correctly configure them, but some providers that is known to be working well - with generous free tiers and affordable packages - are included for your convince (*in no particular order*) below: + +* [R2](https://www.cloudflare.com/developer-platform/r2/) by CloudFlare has cheap storage, free *egress* (e.g. people downloading images) and included (and free) Content Delivery Network (CDN). +* [B2 cloud storage](https://www.backblaze.com/cloud-storage) by Backblaze. +* [Simple Storage Service (S3)](https://aws.amazon.com/s3/) by Amazon Web Services. + +### Software + +Required software to be installed on your server + +* `git` can be installed with `apt-get install git` on Debian/Ubuntu +* `docker` can be installed by [following the official Docker documentation](https://docs.docker.com/engine/install/) + +## Getting things ready + +Connect via SSH to your server and decide where you want to install Pixelfed. + +In this guide I'm going to assume it will be installed at `/data/pixelfed`. + +1. **Install required software** as mentioned in the [Software Prerequisites section above](#software) +1. **Create the parent directory** by running `mkdir -p /data` +1. **Clone the Pixelfed repository** by running `git clone https://github.com/pixelfed/pixelfed.git /data/pixelfed` +1. **Change to the Pixelfed directory** by running `cd /data/pixelfed` ## Modifying your settings (`.env` file) -Minimum required settings to change is: +### Copy the example configuration file -* `APP_NAME` -* `APP_DOMAIN` -* `DB_PASSWORD` +Pixelfed contains a default configuration file (`.env.docker`) you should use as a starter, however, before editing anything, make a copy of it and put it in the *right* place (`.env`). + +Run the following command to copy the file: `cp .env.docker .env` + +### Modifying the configuration file + +The configuration file is *quite* long, but the good news is that you can ignore *most* of it, all of the *server* specific settings are configured for you out of the box. + +The minimum required settings you **must** change is: + +* (required) `APP_DOMAIN` which is the hostname you plan to run your Pixelfed server on (e.g. `pixelfed.social`) - must **not** include `http://` or a trailing slash (`/`)! +* (required) `DB_PASSWORD` which is the database password, you can use a service like [pwgen.io](https://pwgen.io/en/) to generate a secure one. +* (optional) `ENFORCE_EMAIL_VERIFICATION` should be set to `"false"` if you don't plan to send emails. +* (optional) `MAIL_DRIVER` and related `MAIL_*` settings if you plan to use an [email/SMTP provider](#e-mail--smtp-provider) - See [Email variables documentation](https://docs.pixelfed.org/running-pixelfed/installation/#email-variables). +* (optional) `PF_ENABLE_CLOUD` / `FILESYSTEM_CLOUD` if you plan to use an [Object Storage provider](#object-storage). See the [`Configure environment variables`](https://docs.pixelfed.org/running-pixelfed/installation/#app-variables) documentation for details! @@ -28,10 +106,23 @@ You need to mainly focus on following sections * [App variables](https://docs.pixelfed.org/running-pixelfed/installation/#app-variables) * [Email variables](https://docs.pixelfed.org/running-pixelfed/installation/#email-variables) -Since the following things are configured for you out of the box: +You can skip the following sections, since they are already configured/automated for you: * `Redis` * `Database` (except for `DB_PASSWORD`) +* `One-time setup tasks` + +### Starting the service + +With everything in place and (hopefully) well-configured, we can now go ahead and start our services by running + +```shell +docker compose up -d +``` + +This will download all the required Docker images, start the containers, and being the automatic setup. + +You can follow the logs by running `docker compose logs --tail=100 --follow`. ## Runtimes From 9445980e0433b04579efa89bc4c2e061b7f242ba Mon Sep 17 00:00:00 2001 From: Christian Winther Date: Sat, 6 Jan 2024 15:57:20 +0000 Subject: [PATCH 036/173] expose both http and https ports --- .env.docker | 7 +++++-- docker-compose.yml | 3 ++- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/.env.docker b/.env.docker index 0508e939a..ba4f62556 100644 --- a/.env.docker +++ b/.env.docker @@ -917,5 +917,8 @@ DOCKER_REDIS_PORT_EXTERNAL="${REDIS_PORT}" # Use "3306" for MySQL/MariaDB and "5432" for PostgreeSQL DOCKER_DB_PORT_EXTERNAL="${DB_PORT}" -# Port that the web will listen on *outside* the container (e.g. the host machine) -DOCKER_WEB_PORT_EXTERNAL="8080" +# Port that the web will listen on *outside* the container (e.g. the host machine) for HTTP traffic +DOCKER_WEB_HTTP_PORT_EXTERNAL="8080" + +# Port that the web will listen on *outside* the container (e.g. the host machine) for HTTPS traffic +DOCKER_WEB_HTTPS_PORT_EXTERNAL="444" diff --git a/docker-compose.yml b/docker-compose.yml index 4b93c75e9..4b1b6ac4b 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -16,7 +16,8 @@ services: - "${DOCKER_DATA_ROOT}/pixelfed/cache:/var/www/bootstrap/cache" - "${DOCKER_DATA_ROOT}/pixelfed/storage:/var/www/storage" ports: - - "${DOCKER_WEB_PORT_EXTERNAL}:80" + - "${DOCKER_WEB_HTTP_PORT_EXTERNAL}:80" + - "${DOCKER_WEB_HTTPS_PORT_EXTERNAL}:443" depends_on: - db - redis From 284bb26d92376b3d66d8c0805d977237d92ed0b7 Mon Sep 17 00:00:00 2001 From: Christian Winther Date: Sat, 6 Jan 2024 16:43:48 +0000 Subject: [PATCH 037/173] sync --- .dockerignore | 6 ++-- .env.docker | 16 +++++++-- .gitignore | 3 +- docker-compose.yml | 51 ++++++++++++++++++++++++++-- docker/shared/root/docker/helpers.sh | 2 +- 5 files changed, 66 insertions(+), 12 deletions(-) diff --git a/.dockerignore b/.dockerignore index a4f4ff035..b7a6691d9 100644 --- a/.dockerignore +++ b/.dockerignore @@ -2,8 +2,6 @@ .env .git .gitignore -contrib/docker-compose/.env -contrib/docker-compose/config -contrib/docker-compose/data -data docker-compose*.yml + +/docker-compose/ diff --git a/.env.docker b/.env.docker index ba4f62556..72994a23a 100644 --- a/.env.docker +++ b/.env.docker @@ -6,10 +6,10 @@ ############################################################### # Path (relative to the docker-compose.yml) or absolute (/some/other/path) file where containers will store their data -DOCKER_DATA_ROOT="./data" +DOCKER_DATA_ROOT="./docker-compose/data" # Path (relative to the docker-compose.yml) or absolute (/some/other/path) file where containers will store their confguration -DOCKER_CONFIG_ROOT="./config" +DOCKER_CONFIG_ROOT="./docker-compose/config" # Image to pull the Pixelfed Docker images from # @@ -30,6 +30,12 @@ TZ="UTC" # Automatically run [artisan migrate --force] if new migrations are detected DOCKER_APPLY_NEW_MIGRATIONS_AUTOMATICALLY="0" +# The e-mail to use for Lets Encrypt certificate requests +LETSENCRYPT_EMAIL="__CHANGE_ME__" + +# Lets Encrypt staging/test servers for certificate requests +LETSENCRYPT_TEST="true" + ############################################################### # Pixelfed application configuration ############################################################### @@ -922,3 +928,9 @@ DOCKER_WEB_HTTP_PORT_EXTERNAL="8080" # Port that the web will listen on *outside* the container (e.g. the host machine) for HTTPS traffic DOCKER_WEB_HTTPS_PORT_EXTERNAL="444" + +# Port that the web will listen on *outside* the container (e.g. the host machine) for HTTP traffic +DOCKER_PROXY_PORT_EXTERNAL_HTTP="8080" + +# Port that the web will listen on *outside* the container (e.g. the host machine) for HTTPS traffic +DOCKER_PROXY_PORT_EXTERNAL_HTTPS="443" diff --git a/.gitignore b/.gitignore index 4396e4cdd..abb42ef7c 100644 --- a/.gitignore +++ b/.gitignore @@ -20,6 +20,5 @@ yarn-error.log .git-credentials /.composer/ /nginx.conf -/contrib/docker-compose/data -/contrib/docker-compose/config +/docker-compose/ !/contrib/docker-compose/.env diff --git a/docker-compose.yml b/docker-compose.yml index 4b1b6ac4b..5960f3484 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -6,6 +6,43 @@ version: "3" ############################################################### services: + # HTTP/HTTPS proxy + # + # See: https://github.com/nginx-proxy/nginx-proxy/tree/main/docs + proxy: + image: nginxproxy/nginx-proxy:1.4 + container_name: "${APP_DOMAIN}-proxy" + #restart: unless-stopped + volumes: + - "/var/run/docker.sock:/tmp/docker.sock:ro" + - "${DOCKER_CONFIG_ROOT}/proxy/certs:/etc/nginx/certs" + - "${DOCKER_CONFIG_ROOT}/proxy/conf.d:/etc/nginx/conf.d" + - "${DOCKER_CONFIG_ROOT}/proxy/html:/usr/share/nginx/html" + - "${DOCKER_CONFIG_ROOT}/proxy/vhost.d:/etc/nginx/vhost.d" + ports: + - "${DOCKER_PROXY_PORT_EXTERNAL_HTTP}:80" + - "${DOCKER_PROXY_PORT_EXTERNAL_HTTPS}:443" + + # Proxy companion for managing letsencrypt SSL certificates + # + # See: https://github.com/nginx-proxy/acme-companion/tree/main/docs + proxy-acme: + image: nginxproxy/acme-companion + container_name: "${APP_DOMAIN}-proxy-acme" + #restart: unless-stopped + environment: + DEFAULT_EMAIL: "${LETSENCRYPT_EMAIL}" + LETSENCRYPT_TEST: "${LETSENCRYPT_TEST}" + NGINX_PROXY_CONTAINER: "${APP_DOMAIN}-proxy" + depends_on: + - proxy + volumes: + - /var/run/docker.sock:/var/run/docker.sock:ro + - "${DOCKER_CONFIG_ROOT}/proxy/certs:/etc/nginx/certs" + - "${DOCKER_CONFIG_ROOT}/proxy/conf.d:/etc/nginx/conf.d" + - "${DOCKER_CONFIG_ROOT}/proxy/html:/usr/share/nginx/html" + - "${DOCKER_CONFIG_ROOT}/proxy/vhost.d:/etc/nginx/vhost.d" + web: image: "${DOCKER_IMAGE}:${DOCKER_TAG}" # build: @@ -15,9 +52,17 @@ services: - "./.env:/var/www/.env" - "${DOCKER_DATA_ROOT}/pixelfed/cache:/var/www/bootstrap/cache" - "${DOCKER_DATA_ROOT}/pixelfed/storage:/var/www/storage" - ports: - - "${DOCKER_WEB_HTTP_PORT_EXTERNAL}:80" - - "${DOCKER_WEB_HTTPS_PORT_EXTERNAL}:443" + environment: + LETSENCRYPT_HOST: "${APP_DOMAIN},*.${APP_DOMAIN}" + VIRTUAL_HOST: "${APP_DOMAIN},*.${APP_DOMAIN}" + VIRTUAL_PORT: "80" + labels: + com.github.nginx-proxy.nginx-proxy.keepalive: 30 + com.github.nginx-proxy.nginx-proxy.http2.enable: true + com.github.nginx-proxy.nginx-proxy.http3.enable: true + # ports: + # - "${DOCKER_WEB_HTTP_PORT_EXTERNAL}:80" + # - "${DOCKER_WEB_HTTPS_PORT_EXTERNAL}:443" depends_on: - db - redis diff --git a/docker/shared/root/docker/helpers.sh b/docker/shared/root/docker/helpers.sh index 4217b56a6..c9b5bb531 100644 --- a/docker/shared/root/docker/helpers.sh +++ b/docker/shared/root/docker/helpers.sh @@ -410,7 +410,7 @@ function await-database-ready() { ;; *) - log-error-and-exit "Unknown database type: [${DB_CONNECT}]" + log-error-and-exit "Unknown database type: [${DB_CONNECTION}]" ;; esac From 2e3c7e862c307f23a654bdf3b105051d9d18b00e Mon Sep 17 00:00:00 2001 From: Christian Winther Date: Sat, 6 Jan 2024 18:01:48 +0000 Subject: [PATCH 038/173] iterating on proxy + letsencrypt setup --- .dockerignore | 5 +- .env.docker | 21 ++++++-- .gitignore | 27 +++++----- docker-compose.yml | 49 +++++++++++++------ .../entrypoint.d/11-first-time-setup.sh | 1 + docker/shared/root/docker/helpers.sh | 10 ++-- 6 files changed, 68 insertions(+), 45 deletions(-) diff --git a/.dockerignore b/.dockerignore index b7a6691d9..c8ae49a4e 100644 --- a/.dockerignore +++ b/.dockerignore @@ -1,7 +1,4 @@ -.dockerignore .env .git .gitignore -docker-compose*.yml - -/docker-compose/ +/docker-compose-state/ diff --git a/.env.docker b/.env.docker index 72994a23a..2b4eba197 100644 --- a/.env.docker +++ b/.env.docker @@ -34,7 +34,7 @@ DOCKER_APPLY_NEW_MIGRATIONS_AUTOMATICALLY="0" LETSENCRYPT_EMAIL="__CHANGE_ME__" # Lets Encrypt staging/test servers for certificate requests -LETSENCRYPT_TEST="true" +LETSENCRYPT_TEST= ############################################################### # Pixelfed application configuration @@ -147,7 +147,7 @@ APP_TIMEZONE="${TZ}" # Defaults to "15000" (15MB). # # See: https://docs.pixelfed.org/technical-documentation/config/#max_photo_size-kb -#MAX_PHOTO_SIZE="15000" +MAX_PHOTO_SIZE="15000" # Update the max avatar size, in kB. # @@ -182,7 +182,7 @@ APP_TIMEZONE="${TZ}" # Defaults to "4". # # See: https://docs.pixelfed.org/technical-documentation/config/#max_album_length -#MAX_ALBUM_LENGTH="4" +MAX_ALBUM_LENGTH="4" # Resize and optimize image uploads. # @@ -912,9 +912,14 @@ POSTGRES_PASSWORD="${DB_PASSWORD}" POSTGRES_DB="${DB_DATABASE}" ############################################################### -# Docker Specific configuration +# Lets Encrypt configuration ############################################################### +LETSENCRYPT_HOST="${APP_DOMAIN}" + +############################################################### +# Docker Specific configuration +############################################################### # Port that Redis will listen on *outside* the container (e.g. the host machine) DOCKER_REDIS_PORT_EXTERNAL="${REDIS_PORT}" @@ -933,4 +938,10 @@ DOCKER_WEB_HTTPS_PORT_EXTERNAL="444" DOCKER_PROXY_PORT_EXTERNAL_HTTP="8080" # Port that the web will listen on *outside* the container (e.g. the host machine) for HTTPS traffic -DOCKER_PROXY_PORT_EXTERNAL_HTTPS="443" +DOCKER_PROXY_PORT_EXTERNAL_HTTPS="444" + +# Path to the Docker socket on the *host* +DOCKER_HOST_SOCKET_PATH="/var/run/docker.sock" + +# Prefix for container names (without any dash at the end) +DOCKER_CONTAINER_NAME_PREFIX="${APP_DOMAIN}-" diff --git a/.gitignore b/.gitignore index abb42ef7c..a5cdf3af1 100644 --- a/.gitignore +++ b/.gitignore @@ -1,24 +1,21 @@ +.bash_history +.bash_profile +.bashrc +.DS_Store +.env +.git-credentials +.gitconfig +/.composer/ +/.idea +/.vagrant +/.vscode +/docker-compose-state/ /node_modules /public/hot /public/storage /storage/*.key /vendor -/.idea -/.vscode -/.vagrant -/docker-volumes Homestead.json Homestead.yaml npm-debug.log yarn-error.log -.env -.DS_Store -.bash_profile -.bash_history -.bashrc -.gitconfig -.git-credentials -/.composer/ -/nginx.conf -/docker-compose/ -!/contrib/docker-compose/.env diff --git a/docker-compose.yml b/docker-compose.yml index 5960f3484..3b131635f 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -11,14 +11,14 @@ services: # See: https://github.com/nginx-proxy/nginx-proxy/tree/main/docs proxy: image: nginxproxy/nginx-proxy:1.4 - container_name: "${APP_DOMAIN}-proxy" + container_name: "${DOCKER_CONTAINER_NAME_PREFIX}-proxy" #restart: unless-stopped volumes: - - "/var/run/docker.sock:/tmp/docker.sock:ro" - - "${DOCKER_CONFIG_ROOT}/proxy/certs:/etc/nginx/certs" + - "${DOCKER_HOST_SOCKET_PATH}:/tmp/docker.sock:ro" - "${DOCKER_CONFIG_ROOT}/proxy/conf.d:/etc/nginx/conf.d" - - "${DOCKER_CONFIG_ROOT}/proxy/html:/usr/share/nginx/html" - "${DOCKER_CONFIG_ROOT}/proxy/vhost.d:/etc/nginx/vhost.d" + - "${DOCKER_CONFIG_ROOT}/proxy/certs:/etc/nginx/certs" + - "${DOCKER_DATA_ROOT}/proxy/html:/usr/share/nginx/html" ports: - "${DOCKER_PROXY_PORT_EXTERNAL_HTTP}:80" - "${DOCKER_PROXY_PORT_EXTERNAL_HTTPS}:443" @@ -28,33 +28,40 @@ services: # See: https://github.com/nginx-proxy/acme-companion/tree/main/docs proxy-acme: image: nginxproxy/acme-companion - container_name: "${APP_DOMAIN}-proxy-acme" + container_name: "${DOCKER_CONTAINER_NAME_PREFIX}-proxy-acme" #restart: unless-stopped environment: + DEBUG: 0 DEFAULT_EMAIL: "${LETSENCRYPT_EMAIL}" - LETSENCRYPT_TEST: "${LETSENCRYPT_TEST}" - NGINX_PROXY_CONTAINER: "${APP_DOMAIN}-proxy" + NGINX_PROXY_CONTAINER: "${DOCKER_CONTAINER_NAME_PREFIX}-proxy" depends_on: - proxy volumes: - - /var/run/docker.sock:/var/run/docker.sock:ro - - "${DOCKER_CONFIG_ROOT}/proxy/certs:/etc/nginx/certs" + - "${DOCKER_HOST_SOCKET_PATH}:/var/run/docker.sock:ro" - "${DOCKER_CONFIG_ROOT}/proxy/conf.d:/etc/nginx/conf.d" - - "${DOCKER_CONFIG_ROOT}/proxy/html:/usr/share/nginx/html" - "${DOCKER_CONFIG_ROOT}/proxy/vhost.d:/etc/nginx/vhost.d" + - "${DOCKER_CONFIG_ROOT}/proxy/certs:/etc/nginx/certs" + - "${DOCKER_DATA_ROOT}/proxy/html:/usr/share/nginx/html" + - "${DOCKER_DATA_ROOT}/proxy-acme:/etc/acme.sh" web: image: "${DOCKER_IMAGE}:${DOCKER_TAG}" - # build: - # target: apache-runtime + container_name: "${DOCKER_CONTAINER_NAME_PREFIX}-web" restart: unless-stopped + build: + target: apache-runtime + deploy: + mode: replicated + replicas: 1 volumes: - "./.env:/var/www/.env" - "${DOCKER_DATA_ROOT}/pixelfed/cache:/var/www/bootstrap/cache" - "${DOCKER_DATA_ROOT}/pixelfed/storage:/var/www/storage" environment: - LETSENCRYPT_HOST: "${APP_DOMAIN},*.${APP_DOMAIN}" - VIRTUAL_HOST: "${APP_DOMAIN},*.${APP_DOMAIN}" + LETSENCRYPT_HOST: "${LETSENCRYPT_HOST}" + LETSENCRYPT_EMAIL: "${LETSENCRYPT_EMAIL}" + LETSENCRYPT_TEST: "${LETSENCRYPT_TEST}" + VIRTUAL_HOST: "${APP_DOMAIN}" VIRTUAL_PORT: "80" labels: com.github.nginx-proxy.nginx-proxy.keepalive: 30 @@ -69,10 +76,14 @@ services: worker: image: "${DOCKER_IMAGE}:${DOCKER_TAG}" - # build: - # target: apache-runtime + container_name: "${DOCKER_CONTAINER_NAME_PREFIX}-worker" command: gosu www-data php artisan horizon restart: unless-stopped + deploy: + mode: replicated + replicas: 1 + build: + target: apache-runtime volumes: - "./.env:/var/www/.env" - "${DOCKER_DATA_ROOT}/pixelfed/cache:/var/www/bootstrap/cache" @@ -83,8 +94,11 @@ services: db: image: mariadb:11.2 + container_name: "${DOCKER_CONTAINER_NAME_PREFIX}-db" command: --default-authentication-plugin=mysql_native_password restart: unless-stopped + env_file: + - ".env" volumes: - "${DOCKER_DATA_ROOT}/db:/var/lib/mysql" ports: @@ -92,7 +106,10 @@ services: redis: image: redis:7 + container_name: "${DOCKER_CONTAINER_NAME_PREFIX}-redis" restart: unless-stopped + env_file: + - ".env" volumes: - "${DOCKER_CONFIG_ROOT}/redis:/etc/redis" - "${DOCKER_DATA_ROOT}/redis:/data" diff --git a/docker/shared/root/docker/entrypoint.d/11-first-time-setup.sh b/docker/shared/root/docker/entrypoint.d/11-first-time-setup.sh index 1a0cbb51c..529c1d0cf 100755 --- a/docker/shared/root/docker/entrypoint.d/11-first-time-setup.sh +++ b/docker/shared/root/docker/entrypoint.d/11-first-time-setup.sh @@ -3,6 +3,7 @@ source /docker/helpers.sh entrypoint-set-script-name "$0" +load-config-files await-database-ready only-once "storage:link" run-as-runtime-user php artisan storage:link diff --git a/docker/shared/root/docker/helpers.sh b/docker/shared/root/docker/helpers.sh index c9b5bb531..24bd7f1f8 100644 --- a/docker/shared/root/docker/helpers.sh +++ b/docker/shared/root/docker/helpers.sh @@ -283,7 +283,7 @@ function is-directory-empty() { # @exitcode 0 If $1 If the path exists *or* was created # @exitcode 1 If $1 If the path does *NOT* exists and could *NOT* be created function ensure-directory-exists() { - mkdir -pv "$@" + stream-prefix-command-output mkdir -pv "$@" } # @description Find the relative path for a entrypoint script by removing the ENTRYPOINT_ROOT prefix @@ -314,7 +314,7 @@ function only-once() { return 1 fi - touch "${file}" + stream-prefix-command-output touch "${file}" return 0 } @@ -334,7 +334,7 @@ function acquire-lock() { staggered-sleep done - touch "${file}" + stream-prefix-command-output touch "${file}" log-info "🔐 Lock acquired [${file}]" @@ -349,7 +349,7 @@ function release-lock() { log-info "🔓 Releasing lock [${file}]" - rm -f "${file}" + stream-prefix-command-output rm -fv "${file}" } # @description Helper function to append multiple actions onto @@ -410,7 +410,7 @@ function await-database-ready() { ;; *) - log-error-and-exit "Unknown database type: [${DB_CONNECTION}]" + log-error-and-exit "Unknown database type: [${DB_CONNECTION:-}]" ;; esac From 6f0a6aeb3de31ed8dfd5df86ed2fc131969e45ee Mon Sep 17 00:00:00 2001 From: Christian Winther Date: Sun, 7 Jan 2024 14:54:28 +0000 Subject: [PATCH 039/173] fix hadolint path --- .github/workflows/docker.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/docker.yml b/.github/workflows/docker.yml index f53559b37..d08ab8e73 100644 --- a/.github/workflows/docker.yml +++ b/.github/workflows/docker.yml @@ -36,7 +36,7 @@ jobs: - name: Docker Lint uses: hadolint/hadolint-action@v3.1.0 with: - dockerfile: contrib/docker/Dockerfile + dockerfile: Dockerfile failure-threshold: error build: From 84c9aeb514cc05f3d46ec004f49f90b0ddd17841 Mon Sep 17 00:00:00 2001 From: Christian Winther Date: Mon, 15 Jan 2024 14:16:54 +0000 Subject: [PATCH 040/173] fixing postgresql and some more utility help --- Dockerfile | 7 ++ .../docker/entrypoint.d/00-check-config.sh | 18 ++++ .../root/docker/entrypoint.d/05-templating.sh | 4 +- .../entrypoint.d/11-first-time-setup.sh | 10 --- .../root/docker/entrypoint.d/12-migrations.sh | 16 ++-- docker/shared/root/docker/helpers.sh | 82 +++++++++++++++++-- docker/shared/root/docker/install/base.sh | 3 + 7 files changed, 111 insertions(+), 29 deletions(-) create mode 100755 docker/shared/root/docker/entrypoint.d/00-check-config.sh diff --git a/Dockerfile b/Dockerfile index 116631f60..33d0eeee3 100644 --- a/Dockerfile +++ b/Dockerfile @@ -17,6 +17,11 @@ ARG FOREGO_VERSION="0.17.2" # See: https://github.com/hairyhenderson/gomplate ARG GOMPLATE_VERSION="v3.11.6" +# See: https://github.com/dotenv-linter/dotenv-linter/releases +# +# WARN: v3.3.0 and above requires newer libc version than Ubuntu ships with +ARG DOTENV_LINTER_VERSION="v3.2.0" + ### # PHP base configuration ### @@ -99,8 +104,10 @@ ARG PHP_VERSION ARG RUNTIME_GID ARG RUNTIME_UID ARG TARGETPLATFORM +ARG DOTENV_LINTER_VERSION ENV DEBIAN_FRONTEND="noninteractive" +ENV DOTENV_LINTER_VERSION="${DOTENV_LINTER_VERSION}" # Ensure we run all scripts through 'bash' rather than 'sh' SHELL ["/bin/bash", "-c"] diff --git a/docker/shared/root/docker/entrypoint.d/00-check-config.sh b/docker/shared/root/docker/entrypoint.d/00-check-config.sh new file mode 100755 index 000000000..36244f6ca --- /dev/null +++ b/docker/shared/root/docker/entrypoint.d/00-check-config.sh @@ -0,0 +1,18 @@ +#!/bin/bash +source /docker/helpers.sh + +entrypoint-set-script-name "$0" + +# Validating dot-env files for any issues +for file in "${dot_env_files[@]}"; do + if file-exists "$file"; then + log-warning "Could not source file [${file}]: does not exists" + continue + fi + + log-info "Linting dotenv file ${file}" + dotenv-linter --skip=QuoteCharacter --skip=UnorderedKey "${file}" +done + +# Write the config cache +run-as-runtime-user php artisan config:cache diff --git a/docker/shared/root/docker/entrypoint.d/05-templating.sh b/docker/shared/root/docker/entrypoint.d/05-templating.sh index cafb9d133..1bb62aae6 100755 --- a/docker/shared/root/docker/entrypoint.d/05-templating.sh +++ b/docker/shared/root/docker/entrypoint.d/05-templating.sh @@ -49,7 +49,7 @@ find "${ENTRYPOINT_TEMPLATE_DIR}" -follow -type f -print | while read -r templat cat "${template_file}" | gomplate >"${output_file_path}" # Show the diff from the envsubst command - if [[ ${ENTRYPOINT_SHOW_TEMPLATE_DIFF:-1} = 1 ]]; then - git --no-pager diff --color=always "${template_file}" "${output_file_path}" || : + if is-true "${ENTRYPOINT_SHOW_TEMPLATE_DIFF}"; then + git --no-pager diff --color=always "${template_file}" "${output_file_path}" || : # ignore diff exit code fi done diff --git a/docker/shared/root/docker/entrypoint.d/11-first-time-setup.sh b/docker/shared/root/docker/entrypoint.d/11-first-time-setup.sh index 529c1d0cf..f9fd6a61b 100755 --- a/docker/shared/root/docker/entrypoint.d/11-first-time-setup.sh +++ b/docker/shared/root/docker/entrypoint.d/11-first-time-setup.sh @@ -10,13 +10,3 @@ only-once "storage:link" run-as-runtime-user php artisan storage:link only-once "key:generate" run-as-runtime-user php artisan key:generate only-once "initial:migrate" run-as-runtime-user php artisan migrate --force only-once "import:cities" run-as-runtime-user php artisan import:cities - -# if [ ! -e "./storage/docker-instance-actor-has-run" ]; then -# run-as-runtime-user php artisan instance:actor -# touch "./storage/docker-instance-actor-has-run" -# fi - -# if [ ! -e "./storage/docker-passport-keys-has-run" ]; then -# run-as-runtime-user php artisan instance:actor -# touch "./storage/docker-passport-keys-has-run" -# fi diff --git a/docker/shared/root/docker/entrypoint.d/12-migrations.sh b/docker/shared/root/docker/entrypoint.d/12-migrations.sh index 68008c596..20cbe3a31 100755 --- a/docker/shared/root/docker/entrypoint.d/12-migrations.sh +++ b/docker/shared/root/docker/entrypoint.d/12-migrations.sh @@ -6,13 +6,6 @@ entrypoint-set-script-name "$0" # Allow automatic applying of outstanding/new migrations on startup : ${DOCKER_APPLY_NEW_MIGRATIONS_AUTOMATICALLY:=0} -if [[ $DOCKER_APPLY_NEW_MIGRATIONS_AUTOMATICALLY -eq 0 ]]; then - log-info "Automatic applying of new database migrations is disabled" - log-info "Please set [DOCKER_APPLY_NEW_MIGRATIONS_AUTOMATICALLY=1] in your [.env] file to enable this." - - exit 0 -fi - # Wait for the database to be ready await-database-ready @@ -20,7 +13,7 @@ await-database-ready declare -i new_migrations=0 run-as-runtime-user php artisan migrate:status | grep No && new_migrations=1 -if [[ $new_migrations -eq 0 ]]; then +if is-true "${new_migrations}"; then log-info "No outstanding migrations detected" exit 0 @@ -28,4 +21,11 @@ fi log-warning "New migrations available, will automatically apply them now" +if is-false "${DOCKER_APPLY_NEW_MIGRATIONS_AUTOMATICALLY}"; then + log-info "Automatic applying of new database migrations is disabled" + log-info "Please set [DOCKER_APPLY_NEW_MIGRATIONS_AUTOMATICALLY=1] in your [.env] file to enable this." + + exit 0 +fi + run-as-runtime-user php artisan migrate --force diff --git a/docker/shared/root/docker/helpers.sh b/docker/shared/root/docker/helpers.sh index 24bd7f1f8..e71b4f295 100644 --- a/docker/shared/root/docker/helpers.sh +++ b/docker/shared/root/docker/helpers.sh @@ -224,17 +224,17 @@ function load-config-files() { # Associative array (aka map/dictionary) holding the unique keys found in dot-env files local -A _tmp_dot_env_keys - for f in "${dot_env_files[@]}"; do - if [ ! -e "$f" ]; then - log-warning "Could not source file [${f}]: does not exists" + for file in "${dot_env_files[@]}"; do + if ! file-exists "${file}"; then + log-warning "Could not source file [${file}]: does not exists" continue fi - log-info "Sourcing ${f}" - source "${f}" + log-info "Sourcing ${file}" + source "${file}" # find all keys in the dot-env file and store them in our temp associative array - for k in "$(grep -v '^#' "${f}" | sed -E 's/(.*)=.*/\1/' | xargs)"; do + for k in "$(grep -v '^#' "${file}" | cut -d"=" -f1 | xargs)"; do _tmp_dot_env_keys[$k]=1 done done @@ -270,6 +270,21 @@ function is-writable() { [[ -w "$1" ]] } +# @description Checks if $1 exists (directory or file) +# @arg $1 string The path to check +# @exitcode 0 If $1 exists +# @exitcode 1 If $1 does *NOT* exists +function path-exists() { + [[ -e "$1" ]] +} + +# @description Checks if $1 exists (file only) +# @arg $1 string The path to check +# @exitcode 0 If $1 exists +# @exitcode 1 If $1 does *NOT* exists +function file-exists() { + [[ -f "$1" ]] +} # @description Checks if $1 contains any files or not # @arg $1 string The path to check # @exitcode 0 If $1 contains files @@ -328,7 +343,7 @@ function acquire-lock() { ensure-directory-exists "$(dirname "${file}")" log-info "🔑 Trying to acquire lock: ${file}: " - while [[ -e "${file}" ]]; do + while file-exists "${file}"; do log-info "🔒 Waiting on lock ${file}" staggered-sleep @@ -384,15 +399,17 @@ declare -f -t on-trap function await-database-ready() { log-info "❓ Waiting for database to be ready" + load-config-files + case "${DB_CONNECTION:-}" in mysql) - while ! echo "SELECT 1" | mysql --user="$DB_USERNAME" --password="$DB_PASSWORD" --host="$DB_HOST" "$DB_DATABASE" --silent >/dev/null; do + while ! echo "SELECT 1" | mysql --user="${DB_USERNAME}" --password="${DB_PASSWORD}" --host="${DB_HOST}" "${DB_DATABASE}" --silent >/dev/null; do staggered-sleep done ;; pgsql) - while ! echo "SELECT 1" | psql --user="$DB_USERNAME" --password="$DB_PASSWORD" --host="$DB_HOST" "$DB_DATABASE" >/dev/null; do + while ! echo "SELECT 1" | PGPASSWORD="${DB_PASSWORD}" psql --user="${DB_USERNAME}" --host="${DB_HOST}" "${DB_DATABASE}" >/dev/null; do staggered-sleep done ;; @@ -453,3 +470,50 @@ function show-call-stack() { log-error " at: ${func} ${src}:${lineno}" done } + +# @description Helper function see if $1 could be considered truthy +# @arg $1 string The string to evaluate +# @see as-boolean +function is-true() { + as-boolean "${1:-}" && return 0 +} + +# @description Helper function see if $1 could be considered falsey +# @arg $1 string The string to evaluate +# @see as-boolean +function is-false() { + as-boolean "${1:-}" || return 0 +} + +# @description Helper function see if $1 could be truethy or falsey. +# since this is a bash context, returning 0 is true and 1 is false +# so it works with [if is-false $input; then .... fi] +# +# This is a bit confusing, *especially* in a PHP world where [1] would be truthy and +# [0] would be falsely as return values +# @arg $1 string The string to evaluate +function as-boolean() { + local input="${1:-}" + local var="${input,,}" # convert input to lower-case + + case "$var" in + 1 | true) + log-info "[as-boolean] variable [${var}] was detected as truthy/true, returning [0]" + + return 0 + ;; + + 0 | false) + log-info "[as-boolean] variable [${var}] was detected as falsey/false, returning [1]" + + return 1 + ;; + + *) + log-warning "[as-boolean] variable [${var}] could not be detected as true or false, returning [1] (false) as default" + + return 1 + ;; + + esac +} diff --git a/docker/shared/root/docker/install/base.sh b/docker/shared/root/docker/install/base.sh index d3da207e5..5856836f9 100755 --- a/docker/shared/root/docker/install/base.sh +++ b/docker/shared/root/docker/install/base.sh @@ -83,3 +83,6 @@ apt-get install -y \ locale-gen update-locale + +# Install dotenv linter (https://github.com/dotenv-linter/dotenv-linter) +curl -sSfL https://raw.githubusercontent.com/dotenv-linter/dotenv-linter/master/install.sh | sh -s -- -b /usr/local/bin ${DOTENV_LINTER_VERSION} From c258a15761c1a8c22214119fa74571cb98824385 Mon Sep 17 00:00:00 2001 From: Christian Winther Date: Mon, 15 Jan 2024 14:42:54 +0000 Subject: [PATCH 041/173] cleanup a bit --- .env.docker | 10 ++-------- docker-compose.yml | 7 ++----- 2 files changed, 4 insertions(+), 13 deletions(-) diff --git a/.env.docker b/.env.docker index 2b4eba197..b7094fb49 100644 --- a/.env.docker +++ b/.env.docker @@ -929,16 +929,10 @@ DOCKER_REDIS_PORT_EXTERNAL="${REDIS_PORT}" DOCKER_DB_PORT_EXTERNAL="${DB_PORT}" # Port that the web will listen on *outside* the container (e.g. the host machine) for HTTP traffic -DOCKER_WEB_HTTP_PORT_EXTERNAL="8080" +DOCKER_PROXY_PORT_EXTERNAL_HTTP="80" # Port that the web will listen on *outside* the container (e.g. the host machine) for HTTPS traffic -DOCKER_WEB_HTTPS_PORT_EXTERNAL="444" - -# Port that the web will listen on *outside* the container (e.g. the host machine) for HTTP traffic -DOCKER_PROXY_PORT_EXTERNAL_HTTP="8080" - -# Port that the web will listen on *outside* the container (e.g. the host machine) for HTTPS traffic -DOCKER_PROXY_PORT_EXTERNAL_HTTPS="444" +DOCKER_PROXY_PORT_EXTERNAL_HTTPS="443" # Path to the Docker socket on the *host* DOCKER_HOST_SOCKET_PATH="/var/run/docker.sock" diff --git a/docker-compose.yml b/docker-compose.yml index 3b131635f..888a65847 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -12,7 +12,7 @@ services: proxy: image: nginxproxy/nginx-proxy:1.4 container_name: "${DOCKER_CONTAINER_NAME_PREFIX}-proxy" - #restart: unless-stopped + restart: unless-stopped volumes: - "${DOCKER_HOST_SOCKET_PATH}:/tmp/docker.sock:ro" - "${DOCKER_CONFIG_ROOT}/proxy/conf.d:/etc/nginx/conf.d" @@ -29,7 +29,7 @@ services: proxy-acme: image: nginxproxy/acme-companion container_name: "${DOCKER_CONTAINER_NAME_PREFIX}-proxy-acme" - #restart: unless-stopped + restart: unless-stopped environment: DEBUG: 0 DEFAULT_EMAIL: "${LETSENCRYPT_EMAIL}" @@ -67,9 +67,6 @@ services: com.github.nginx-proxy.nginx-proxy.keepalive: 30 com.github.nginx-proxy.nginx-proxy.http2.enable: true com.github.nginx-proxy.nginx-proxy.http3.enable: true - # ports: - # - "${DOCKER_WEB_HTTP_PORT_EXTERNAL}:80" - # - "${DOCKER_WEB_HTTPS_PORT_EXTERNAL}:443" depends_on: - db - redis From edbc1e4d60be0490dc3c79a449d9eb4d188805df Mon Sep 17 00:00:00 2001 From: Christian Winther Date: Mon, 15 Jan 2024 14:44:47 +0000 Subject: [PATCH 042/173] expand docs --- .env.docker | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/.env.docker b/.env.docker index b7094fb49..00bdb4570 100644 --- a/.env.docker +++ b/.env.docker @@ -102,7 +102,12 @@ ADMIN_DOMAIN="${APP_DOMAIN}" # Defaults to "1000". # # See: https://docs.pixelfed.org/technical-documentation/config/#pf_max_users -PF_MAX_USERS="false" +PF_MAX_USERS="1000" + +# Enforce the maximum number of user accounts +# +# Defaults to "true". +#PF_ENFORCE_MAX_USERS="true" # See: https://docs.pixelfed.org/technical-documentation/config/#oauth_enabled OAUTH_ENABLED="true" From 543dac34f6445829596c30f9d8fb1f942ae353f7 Mon Sep 17 00:00:00 2001 From: Christian Winther Date: Mon, 15 Jan 2024 14:48:12 +0000 Subject: [PATCH 043/173] update path --- .gitignore | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index a5cdf3af1..ebfef1ace 100644 --- a/.gitignore +++ b/.gitignore @@ -9,7 +9,7 @@ /.idea /.vagrant /.vscode -/docker-compose-state/ +/docker-compose/ /node_modules /public/hot /public/storage From 519704cbe84907d3a349eb068f413eb829ef146e Mon Sep 17 00:00:00 2001 From: Christian Winther Date: Mon, 15 Jan 2024 14:57:40 +0000 Subject: [PATCH 044/173] more tuning --- .env.docker | 34 ++++++++++++++++++++-------------- .github/workflows/docker.yml | 3 ++- 2 files changed, 22 insertions(+), 15 deletions(-) diff --git a/.env.docker b/.env.docker index 00bdb4570..559c06553 100644 --- a/.env.docker +++ b/.env.docker @@ -19,22 +19,30 @@ DOCKER_CONFIG_ROOT="./docker-compose/config" # DOCKER_IMAGE="ghcr.io/jippi/pixelfed" -# Pixelfed version (image tag) to pull from the registry +# Pixelfed version (image tag) to pull from the registry. +# +# See: https://github.com/pixelfed/pixelfed/pkgs/container/pixelfed DOCKER_TAG="branch-jippi-fork-apache-8.1" -# Set timezone used by *all* containers - these should be in sync +# Set timezone used by *all* containers - these should be in sync. # # See: https://www.php.net/manual/en/timezones.php TZ="UTC" -# Automatically run [artisan migrate --force] if new migrations are detected +# Automatically run [artisan migrate --force] if new migrations are detected. DOCKER_APPLY_NEW_MIGRATIONS_AUTOMATICALLY="0" -# The e-mail to use for Lets Encrypt certificate requests +# The e-mail to use for Lets Encrypt certificate requests. LETSENCRYPT_EMAIL="__CHANGE_ME__" -# Lets Encrypt staging/test servers for certificate requests -LETSENCRYPT_TEST= +# Lets Encrypt staging/test servers for certificate requests. +# +# Setting this to any value will change to letsencrypt test servers. +#LETSENCRYPT_TEST="1" + +# Enable Docker Entrypoint debug mode (will call [set -x] in bash scripts) +# by setting this to "1". +#ENTRYPOINT_DEBUG="0" ############################################################### # Pixelfed application configuration @@ -42,13 +50,13 @@ LETSENCRYPT_TEST= # A random 32-character string to be used as an encryption key. # -# No default value; use [php artisan key:generate] to generate. +# !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! +# ! NOTE: This will be auto-generated by Docker during bootstrap +# !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! # # This key is used by the Illuminate encrypter service and should be set to a random, # 32 character string, otherwise these encrypted strings will not be safe. # -# Please do this before deploying an application! -# # See: https://docs.pixelfed.org/technical-documentation/config/#app_key APP_KEY= @@ -102,7 +110,7 @@ ADMIN_DOMAIN="${APP_DOMAIN}" # Defaults to "1000". # # See: https://docs.pixelfed.org/technical-documentation/config/#pf_max_users -PF_MAX_USERS="1000" +#PF_MAX_USERS="1000" # Enforce the maximum number of user accounts # @@ -152,7 +160,7 @@ APP_TIMEZONE="${TZ}" # Defaults to "15000" (15MB). # # See: https://docs.pixelfed.org/technical-documentation/config/#max_photo_size-kb -MAX_PHOTO_SIZE="15000" +#MAX_PHOTO_SIZE="15000" # Update the max avatar size, in kB. # @@ -187,7 +195,7 @@ MAX_PHOTO_SIZE="15000" # Defaults to "4". # # See: https://docs.pixelfed.org/technical-documentation/config/#max_album_length -MAX_ALBUM_LENGTH="4" +#MAX_ALBUM_LENGTH="4" # Resize and optimize image uploads. # @@ -296,8 +304,6 @@ DB_DATABASE="pixelfed_prod" # See: https://docs.pixelfed.org/technical-documentation/config/#db_port DB_PORT="3306" -ENTRYPOINT_DEBUG=0 - ############################################################### # Mail configuration ############################################################### diff --git a/.github/workflows/docker.yml b/.github/workflows/docker.yml index d08ab8e73..a2e73a61a 100644 --- a/.github/workflows/docker.yml +++ b/.github/workflows/docker.yml @@ -147,7 +147,8 @@ jobs: latest=auto suffix=-${{ matrix.target_runtime }}-${{ matrix.php_version }} tags: | - type=edge,branch=dev + type=raw,value=dev,enable=${{ github.ref == format('refs/heads/{0}', 'dev') }} + type=raw,value=staging,enable=${{ github.ref == format('refs/heads/{0}', 'staging') }} type=pep440,pattern={{raw}} type=pep440,pattern=v{{major}}.{{minor}} type=ref,event=branch,prefix=branch- From 9814a39fd8c44cfde6feb854233ea75c3e6315fa Mon Sep 17 00:00:00 2001 From: Christian Winther Date: Mon, 15 Jan 2024 15:14:44 +0000 Subject: [PATCH 045/173] more docs --- docker-compose.yml | 3 +++ docker/README.md | 34 ++++++++++++++++++++++++++++------ 2 files changed, 31 insertions(+), 6 deletions(-) diff --git a/docker-compose.yml b/docker-compose.yml index 888a65847..567998411 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -8,6 +8,9 @@ version: "3" services: # HTTP/HTTPS proxy # + # Sits in front of the *real* webserver and manages SSL and (optionally) + # load-balancing between multiple web servers + # # See: https://github.com/nginx-proxy/nginx-proxy/tree/main/docs proxy: image: nginxproxy/nginx-proxy:1.4 diff --git a/docker/README.md b/docker/README.md index 837c1f646..c47b1331a 100644 --- a/docker/README.md +++ b/docker/README.md @@ -27,11 +27,23 @@ A safe starter/small instance hardware for 25 users and blow are: * **Storage** `20-50 GB` HDD is fine, but ideally SSD or NVMe, *especially* for the database. * **Network** `100 Mbit/s` or faster. -### Other +### Domain and DNS -* A **Domain** you need a domain (or subdomain) where your Pixelfed server will be running (for example, `pixelfed.social`) -* (Optional) An **Email/SMTP provider** for sending e-mails to your users, such as e-mail confirmation and notifications. -* (Optional) An **Object Storage** provider for storing all images remotely, rather than locally on your server. +* A **Domain** (or subdomain) is needed for the Pixelfed server (for example, `pixelfed.social` or `pixelfed.mydomain.com`) +* Having the required `A`/`CNAME` DNS records for your domain (above) pointing to your server. + * Typically an `A` record for the root (sometimes shown as `@`) record for `mydomain.com`. + * Possibly an `A` record for `www.` subdomain as well. + +### Network + +* Port `80` (HTTP) and `443` (HTTPS) ports forwarded to the server. + * Example for Ubuntu using [`ufw`](https://help.ubuntu.com/community/UFW) for port `80`: `ufw allow 80` + * Example for Ubuntu using [`ufw`](https://help.ubuntu.com/community/UFW) for port `443`: `ufw allow 443` + +### Optional + +* An **Email/SMTP provider** for sending e-mails to your users, such as e-mail confirmation and notifications. +* An **Object Storage** provider for storing all images remotely, rather than locally on your server. #### E-mail / SMTP provider @@ -89,7 +101,7 @@ Run the following command to copy the file: `cp .env.docker .env` ### Modifying the configuration file -The configuration file is *quite* long, but the good news is that you can ignore *most* of it, all of the *server* specific settings are configured for you out of the box. +The configuration file is *quite* long, but the good news is that you can ignore *most* of it, most of the *server-specific* settings are configured for you out of the box. The minimum required settings you **must** change is: @@ -122,7 +134,15 @@ docker compose up -d This will download all the required Docker images, start the containers, and being the automatic setup. -You can follow the logs by running `docker compose logs --tail=100 --follow`. +You can follow the logs by running `docker compose logs` - you might want to scroll to the top to logs from the start. + +You can use the CLI flag `--tail=100` to only see the most recent (`100` in this example) log lines for each container. + +You can use the CLI flag `--follow` to continue to see log output from the containers. + +You can combine `--tail=100` and `--follow` like this `docker compose logs --tail=100 --follow`. + +If you only care about specific contaieners, you can add them to the end of the command like this `docker compose logs web worker proxy`. ## Runtimes @@ -130,6 +150,8 @@ The Pixelfed Dockerfile support multiple target *runtimes* ([Apache](#apache), [ You can consider a *runtime* target as individual Dockerfiles, but instead, all of them are build from the same optimized Dockerfile, sharing +90% of their configuration and packages. +**If you are unsure of which runtime to choose, please use the [Apache runtime](#apache) it's the most straightforward one and also the default** + ### Apache Building a custom Pixelfed Docker image using Apache + mod_php can be achieved the following way. From 01ecde15925a27f8ea1341b052e1804ecc8801f4 Mon Sep 17 00:00:00 2001 From: Christian Winther Date: Mon, 15 Jan 2024 15:32:29 +0000 Subject: [PATCH 046/173] allow skipping one-time setup tasks --- .../root/docker/entrypoint.d/11-first-time-setup.sh | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/docker/shared/root/docker/entrypoint.d/11-first-time-setup.sh b/docker/shared/root/docker/entrypoint.d/11-first-time-setup.sh index f9fd6a61b..6778bd90e 100755 --- a/docker/shared/root/docker/entrypoint.d/11-first-time-setup.sh +++ b/docker/shared/root/docker/entrypoint.d/11-first-time-setup.sh @@ -3,6 +3,16 @@ source /docker/helpers.sh entrypoint-set-script-name "$0" +# Allow automatic applying of outstanding/new migrations on startup +: ${DOCKER_RUN_ONE_TIME_SETUP_TASKS:=1} + +if is-false "${DOCKER_RUN_ONE_TIME_SETUP_TASKS}"; then + log-warning "Automatic run of the 'One-time setup tasks' is disabled." + log-warning "Please set [DOCKER_RUN_ONE_TIME_SETUP_TASKS=1] in your [.env] file to enable this." + + exit 0 +fi + load-config-files await-database-ready From 20a15c2b659ffe655ab9384198b8483bea7e6544 Mon Sep 17 00:00:00 2001 From: Christian Winther Date: Mon, 15 Jan 2024 16:09:07 +0000 Subject: [PATCH 047/173] split up docs into smaller docs --- docker/README.md | 443 +----------------------------------------- docker/customizing.md | 201 +++++++++++++++++++ docker/new-server.md | 145 ++++++++++++++ docker/runtimes.md | 94 +++++++++ 4 files changed, 443 insertions(+), 440 deletions(-) create mode 100644 docker/customizing.md create mode 100644 docker/new-server.md create mode 100644 docker/runtimes.md diff --git a/docker/README.md b/docker/README.md index c47b1331a..cbadcbf90 100644 --- a/docker/README.md +++ b/docker/README.md @@ -1,442 +1,5 @@ # Pixelfed + Docker + Docker Compose -This guide will help you install and run Pixelfed on **your** server using [Docker Compose](https://docs.docker.com/compose/). - -## Prerequisites - -Recommendations and requirements for hardware and software needed to run Pixelfed using Docker Compose. - -It's highly recommended that you have *some* experience with Linux (e.g. Ubuntu or Debian), SSH, and lightweight server administration. - -### Server - -A VPS or dedicated server you can SSH into, for example - -* [linode.com VPS](https://www.linode.com/) -* [DigitalOcean VPS](https://digitalocean.com/) -* [Hetzner](https://www.hetzner.com/) - -### Hardware - -Hardware requirements depends on the amount of users you have (or plan to have), and how active they are. - -A safe starter/small instance hardware for 25 users and blow are: - -* **CPU/vCPU** `2` cores. -* **RAM** `2-4 GB` as your instance grow, memory requirements will increase for the database. -* **Storage** `20-50 GB` HDD is fine, but ideally SSD or NVMe, *especially* for the database. -* **Network** `100 Mbit/s` or faster. - -### Domain and DNS - -* A **Domain** (or subdomain) is needed for the Pixelfed server (for example, `pixelfed.social` or `pixelfed.mydomain.com`) -* Having the required `A`/`CNAME` DNS records for your domain (above) pointing to your server. - * Typically an `A` record for the root (sometimes shown as `@`) record for `mydomain.com`. - * Possibly an `A` record for `www.` subdomain as well. - -### Network - -* Port `80` (HTTP) and `443` (HTTPS) ports forwarded to the server. - * Example for Ubuntu using [`ufw`](https://help.ubuntu.com/community/UFW) for port `80`: `ufw allow 80` - * Example for Ubuntu using [`ufw`](https://help.ubuntu.com/community/UFW) for port `443`: `ufw allow 443` - -### Optional - -* An **Email/SMTP provider** for sending e-mails to your users, such as e-mail confirmation and notifications. -* An **Object Storage** provider for storing all images remotely, rather than locally on your server. - -#### E-mail / SMTP provider - -**NOTE**: If you don't plan to use en e-mail/SMTP provider, then make sure to set `ENFORCE_EMAIL_VERIFICATION="false"` in your `.env` file! - -There are *many* providers out there, with wildly different pricing structures, features, and reliability. - -It's beyond the cope of this document to detail which provider to pick, or how to correctly configure them, but some providers that is known to be working well - with generous free tiers and affordable packages - are included for your convince (*in no particular order*) below: - -* [Simple Email Service (SES)](https://aws.amazon.com/ses/) by Amazon Web Services (AWS) is pay-as-you-go with a cost of $0.10/1000 emails. -* [Brevo](https://www.brevo.com/) (formerly SendInBlue) has a Free Tier with 300 emails/day. -* [Postmark](https://postmarkapp.com/) has a Free Tier with 100 emails/month. -* [Forward Email](https://forwardemail.net/en/private-business-email?pricing=true) has a $3/mo/domain plan with both sending and receiving included. -* [Mailtrap](https://mailtrap.io/email-sending/) has a 1000 emails/month free-tier (their `Email Sending` product, *not* the `Email Testing` one). - -#### Object Storage - -**NOTE**: This is *entirely* optional - by default Pixelfed will store all uploads (videos, images, etc.) directly on your servers storage. - -> Object storage is a technology that stores and manages data in an unstructured format called objects. Modern organizations create and analyze large volumes of unstructured data such as photos, videos, email, web pages, sensor data, and audio files -> -> -- [*What is object storage?*](https://aws.amazon.com/what-is/object-storage/) by Amazon Web Services - -It's beyond the cope of this document to detail which provider to pick, or how to correctly configure them, but some providers that is known to be working well - with generous free tiers and affordable packages - are included for your convince (*in no particular order*) below: - -* [R2](https://www.cloudflare.com/developer-platform/r2/) by CloudFlare has cheap storage, free *egress* (e.g. people downloading images) and included (and free) Content Delivery Network (CDN). -* [B2 cloud storage](https://www.backblaze.com/cloud-storage) by Backblaze. -* [Simple Storage Service (S3)](https://aws.amazon.com/s3/) by Amazon Web Services. - -### Software - -Required software to be installed on your server - -* `git` can be installed with `apt-get install git` on Debian/Ubuntu -* `docker` can be installed by [following the official Docker documentation](https://docs.docker.com/engine/install/) - -## Getting things ready - -Connect via SSH to your server and decide where you want to install Pixelfed. - -In this guide I'm going to assume it will be installed at `/data/pixelfed`. - -1. **Install required software** as mentioned in the [Software Prerequisites section above](#software) -1. **Create the parent directory** by running `mkdir -p /data` -1. **Clone the Pixelfed repository** by running `git clone https://github.com/pixelfed/pixelfed.git /data/pixelfed` -1. **Change to the Pixelfed directory** by running `cd /data/pixelfed` - -## Modifying your settings (`.env` file) - -### Copy the example configuration file - -Pixelfed contains a default configuration file (`.env.docker`) you should use as a starter, however, before editing anything, make a copy of it and put it in the *right* place (`.env`). - -Run the following command to copy the file: `cp .env.docker .env` - -### Modifying the configuration file - -The configuration file is *quite* long, but the good news is that you can ignore *most* of it, most of the *server-specific* settings are configured for you out of the box. - -The minimum required settings you **must** change is: - -* (required) `APP_DOMAIN` which is the hostname you plan to run your Pixelfed server on (e.g. `pixelfed.social`) - must **not** include `http://` or a trailing slash (`/`)! -* (required) `DB_PASSWORD` which is the database password, you can use a service like [pwgen.io](https://pwgen.io/en/) to generate a secure one. -* (optional) `ENFORCE_EMAIL_VERIFICATION` should be set to `"false"` if you don't plan to send emails. -* (optional) `MAIL_DRIVER` and related `MAIL_*` settings if you plan to use an [email/SMTP provider](#e-mail--smtp-provider) - See [Email variables documentation](https://docs.pixelfed.org/running-pixelfed/installation/#email-variables). -* (optional) `PF_ENABLE_CLOUD` / `FILESYSTEM_CLOUD` if you plan to use an [Object Storage provider](#object-storage). - -See the [`Configure environment variables`](https://docs.pixelfed.org/running-pixelfed/installation/#app-variables) documentation for details! - -You need to mainly focus on following sections - -* [App variables](https://docs.pixelfed.org/running-pixelfed/installation/#app-variables) -* [Email variables](https://docs.pixelfed.org/running-pixelfed/installation/#email-variables) - -You can skip the following sections, since they are already configured/automated for you: - -* `Redis` -* `Database` (except for `DB_PASSWORD`) -* `One-time setup tasks` - -### Starting the service - -With everything in place and (hopefully) well-configured, we can now go ahead and start our services by running - -```shell -docker compose up -d -``` - -This will download all the required Docker images, start the containers, and being the automatic setup. - -You can follow the logs by running `docker compose logs` - you might want to scroll to the top to logs from the start. - -You can use the CLI flag `--tail=100` to only see the most recent (`100` in this example) log lines for each container. - -You can use the CLI flag `--follow` to continue to see log output from the containers. - -You can combine `--tail=100` and `--follow` like this `docker compose logs --tail=100 --follow`. - -If you only care about specific contaieners, you can add them to the end of the command like this `docker compose logs web worker proxy`. - -## Runtimes - -The Pixelfed Dockerfile support multiple target *runtimes* ([Apache](#apache), [Nginx + FPM](#nginx), and [fpm](#fpm)). - -You can consider a *runtime* target as individual Dockerfiles, but instead, all of them are build from the same optimized Dockerfile, sharing +90% of their configuration and packages. - -**If you are unsure of which runtime to choose, please use the [Apache runtime](#apache) it's the most straightforward one and also the default** - -### Apache - -Building a custom Pixelfed Docker image using Apache + mod_php can be achieved the following way. - -#### docker build (Apache) - -```shell -docker build \ - -f contrib/docker/Dockerfile \ - --target apache-runtime \ - --tag / \ - . -``` - -#### docker compose (Apache) - -```yaml -version: "3" - -services: - app: - build: - context: . - dockerfile: contrib/docker/Dockerfile - target: apache-runtime -``` - -### Nginx - -Building a custom Pixelfed Docker image using nginx + FPM can be achieved the following way. - -#### docker build (nginx) - -```shell -docker build \ - -f contrib/docker/Dockerfile \ - --target nginx-runtime \ - --build-arg 'PHP_BASE_TYPE=fpm' \ - --tag / \ - . -``` - -#### docker compose (nginx) - -```yaml -version: "3" - -services: - app: - build: - context: . - dockerfile: contrib/docker/Dockerfile - target: nginx-runtime - args: - PHP_BASE_TYPE: fpm -``` - -### FPM - -Building a custom Pixelfed Docker image using FPM (only) can be achieved the following way. - -#### docker build (fpm) - -```shell -docker build \ - -f contrib/docker/Dockerfile \ - --target fpm-runtime \ - --build-arg 'PHP_BASE_TYPE=fpm' \ - --tag / \ - . -``` - -#### docker compose (fpm) - -```yaml -version: "3" - -services: - app: - build: - context: . - dockerfile: contrib/docker/Dockerfile - target: fpm-runtime - args: - PHP_BASE_TYPE: fpm -``` - -## Customizing your `Dockerfile` - -### Running commands on container start - -#### Description - -When a Pixelfed container starts up, the [`ENTRYPOINT`](https://docs.docker.com/engine/reference/builder/#entrypoint) script will - -1. Search the `/docker/entrypoint.d/` directory for files and for each file (in lexical order). -1. Check if the file is executable. - 1. If the file is *not* executable, print an error and exit the container. -1. If the file has the extension `.envsh` the file will be [sourced](https://superuser.com/a/46146). -1. If the file has the extension `.sh` the file will be run like a normal script. -1. Any other file extension will log a warning and will be ignored. - -#### Debugging - -You can set environment variable `ENTRYPOINT_DEBUG=1` to show verbose output of what each `entrypoint.d` script is doing. - -You can also `docker exec` or `docker run` into a container and run `/` - -#### Included scripts - -* `/docker/entrypoint.d/04-defaults.envsh` calculates Docker container environment variables needed for [templating](#templating) configuration files. -* `/docker/entrypoint.d/05-templating.sh` renders [template](#templating) configuration files. -* `/docker/entrypoint.d/10-storage.sh` ensures Pixelfed storage related permissions and commands are run. -* `//docker/entrypoint.d/15-storage-permissions.sh` (optionally) ensures permissions for files are corrected (see [fixing ownership on startup](#fixing-ownership-on-startup)) -* `/docker/entrypoint.d/20-horizon.sh` ensures [Laravel Horizon](https://laravel.com/docs/master/horizon) used by Pixelfed is configured -* `/docker/entrypoint.d/30-cache.sh` ensures all Pixelfed caches (router, view, config) is warmed - -#### Disabling entrypoint or individual scripts - -To disable the entire entrypoint you can set the variable `ENTRYPOINT_SKIP=1`. - -To disable individual entrypoint scripts you can add the filename to the space (`" "`) separated variable `ENTRYPOINT_SKIP_SCRIPTS`. (example: `ENTRYPOINT_SKIP_SCRIPTS="10-storage.sh 30-cache.sh"`) - -### Templating - -The Docker container can do some basic templating (more like variable replacement) as part of the entrypoint scripts via [gomplate](https://docs.gomplate.ca/). - -Any file put in the `/docker/templates/` directory will be templated and written to the right directory. - -#### File path examples - -1. To template `/usr/local/etc/php/php.ini` in the container put the source file in `/docker/templates/usr/local/etc/php/php.ini`. -1. To template `/a/fantastic/example.txt` in the container put the source file in `/docker/templates/a/fantastic/example.txt`. -1. To template `/some/path/anywhere` in the container put the source file in `/docker/templates/a/fantastic/example.txt`. - -#### Available variables - -Variables available for templating are sourced (in order, so *last* source takes precedence) like this: - -1. `env:` in your `docker-compose.yml` or `-e` in your `docker run` / `docker compose run` -1. Any exported variables in `.envsh` files loaded *before* `05-templating.sh` (e.g. any file with `04-`, `03-`, `02-`, `01-` or `00-` prefix) -1. All key/value pairs in `/var/www/.env.docker` -1. All key/value pairs in `/var/www/.env` - -#### Template guide 101 - -Please see the [`gomplate` documentation](https://docs.gomplate.ca/) for a more comprehensive overview. - -The most frequent use-case you have is likely to print a environment variable (or a default value if it's missing), so this is how to do that: - -* `{{ getenv "VAR_NAME" }}` print an environment variable and **fail** if the variable is not set. ([docs](https://docs.gomplate.ca/functions/env/#envgetenv)) -* `{{ getenv "VAR_NAME" "default" }}` print an environment variable and print `default` if the variable is not set. ([docs](https://docs.gomplate.ca/functions/env/#envgetenv)) - -The script will *fail* if you reference a variable that does not exist (and don't have a default value) in a template. - -Please see the - -* [`gomplate` syntax documentation](https://docs.gomplate.ca/syntax/) -* [`gomplate` functions documentation](https://docs.gomplate.ca/functions/) - -### Fixing ownership on startup - -You can set the environment variable `ENTRYPOINT_ENSURE_OWNERSHIP_PATHS` to a list of paths that should have their `$USER` and `$GROUP` ownership changed to the configured runtime user and group during container bootstrapping. - -The variable is a space-delimited list shown below and accepts both relative and absolute paths: - -* `ENTRYPOINT_ENSURE_OWNERSHIP_PATHS="./storage ./bootstrap"` -* `ENTRYPOINT_ENSURE_OWNERSHIP_PATHS="/some/other/folder"` - -## Build settings (arguments) - -The Pixelfed Dockerfile utilizes [Docker Multi-stage builds](https://docs.docker.com/build/building/multi-stage/) and [Build arguments](https://docs.docker.com/build/guide/build-args/). - -Using *build arguments* allow us to create a flexible and more maintainable Dockerfile, supporting [multiple runtimes](#runtimes) ([FPM](#fpm), [Nginx](#nginx), [Apache + mod_php](#apache)) and end-user flexibility without having to fork or copy the Dockerfile. - -*Build arguments* can be configured using `--build-arg 'name=value'` for `docker build`, `docker compose build` and `docker buildx build`. For `docker-compose.yml` the `args` key for [`build`](https://docs.docker.com/compose/compose-file/compose-file-v3/#build) can be used. - -### `PHP_VERSION` - -The `PHP` version to use when building the runtime container. - -Any valid Docker Hub PHP version is acceptable here, as long as it's [published to Docker Hub](https://hub.docker.com/_/php/tags) - -**Example values**: - -* `8` will use the latest version of PHP 8 -* `8.1` will use the latest version of PHP 8.1 -* `8.2.14` will use PHP 8.2.14 -* `latest` will use whatever is the latest PHP version - -**Default value**: `8.1` - -### `PHP_PECL_EXTENSIONS` - -PECL extensions to install via `pecl install` - -Use [PHP_PECL_EXTENSIONS_EXTRA](#php_pecl_extensions_extra) if you want to add *additional* extenstions. - -Only change this setting if you want to change the baseline extensions. - -See the [`PECL extensions` documentation on Docker Hub](https://hub.docker.com/_/php) for more information. - -**Default value**: `imagick redis` - -### `PHP_PECL_EXTENSIONS_EXTRA` - -Extra PECL extensions (separated by space) to install via `pecl install` - -See the [`PECL extensions` documentation on Docker Hub](https://hub.docker.com/_/php) for more information. - -**Default value**: `""` - -### `PHP_EXTENSIONS` - -PHP Extensions to install via `docker-php-ext-install`. - -**NOTE:** use [`PHP_EXTENSIONS_EXTRA`](#php_extensions_extra) if you want to add *additional* extensions, only override this if you want to change the baseline extensions. - -See the [`How to install more PHP extensions` documentation on Docker Hub](https://hub.docker.com/_/php) for more information - -**Default value**: `intl bcmath zip pcntl exif curl gd` - -### `PHP_EXTENSIONS_EXTRA` - -Extra PHP Extensions (separated by space) to install via `docker-php-ext-install`. - -See the [`How to install more PHP extensions` documentation on Docker Hub](https://hub.docker.com/_/php) for more information. - -**Default value**: `""` - -### `PHP_EXTENSIONS_DATABASE` - -PHP database extensions to install. - -By default we install both `pgsql` and `mysql` since it's more convinient (and adds very little build time! but can be overwritten here if required. - -**Default value**: `pdo_pgsql pdo_mysql pdo_sqlite` - -### `COMPOSER_VERSION` - -The version of Composer to install. - -Please see the [Docker Hub `composer` page](https://hub.docker.com/_/composer) for valid values. - -**Default value**: `2.6` - -### `APT_PACKAGES_EXTRA` - -Extra APT packages (separated by space) that should be installed inside the image by `apt-get install` - -**Default value**: `""` - -### `NGINX_VERSION` - -Version of `nginx` to when targeting [`nginx-runtime`](#nginx). - -Please see the [Docker Hub `nginx` page](https://hub.docker.com/_/nginx) for available versions. - -**Default value**: `1.25.3` - -### `PHP_BASE_TYPE` - -The `PHP` base image layer to use when building the runtime container. - -When targeting - -* [`apache-runtime`](#apache) use `apache` -* [`fpm-runtime`](#fpm) use `fpm` -* [`nginx-runtime`](#nginx) use `fpm` - -**Valid values**: - -* `apache` -* `fpm` -* `cli` - -**Default value**: `apache` - -### `PHP_DEBIAN_RELEASE` - -The `Debian` Operation System version to use. - -**Valid values**: - -* `bullseye` -* `bookworm` - -**Default value**: `bullseye` +* [Setting up a new Pixelfed server with Docker Compose](new-server.md) +* [Understanding Pixelfed Container runtimes (Apache, FPM, Nginx + FPM)](runtimes.md) +* [Customizing Docker image](customizing.md) diff --git a/docker/customizing.md b/docker/customizing.md new file mode 100644 index 000000000..adcc70b28 --- /dev/null +++ b/docker/customizing.md @@ -0,0 +1,201 @@ +# Customizing your `Dockerfile` + +## Running commands on container start + +### Description + +When a Pixelfed container starts up, the [`ENTRYPOINT`](https://docs.docker.com/engine/reference/builder/#entrypoint) script will + +1. Search the `/docker/entrypoint.d/` directory for files and for each file (in lexical order). +1. Check if the file is executable. + 1. If the file is *not* executable, print an error and exit the container. +1. If the file has the extension `.envsh` the file will be [sourced](https://superuser.com/a/46146). +1. If the file has the extension `.sh` the file will be run like a normal script. +1. Any other file extension will log a warning and will be ignored. + +### Debugging + +You can set environment variable `ENTRYPOINT_DEBUG=1` to show verbose output of what each `entrypoint.d` script is doing. + +You can also `docker exec` or `docker run` into a container and run `/` + +### Included scripts + +* `/docker/entrypoint.d/04-defaults.envsh` calculates Docker container environment variables needed for [templating](#templating) configuration files. +* `/docker/entrypoint.d/05-templating.sh` renders [template](#templating) configuration files. +* `/docker/entrypoint.d/10-storage.sh` ensures Pixelfed storage related permissions and commands are run. +* `//docker/entrypoint.d/15-storage-permissions.sh` (optionally) ensures permissions for files are corrected (see [fixing ownership on startup](#fixing-ownership-on-startup)) +* `/docker/entrypoint.d/20-horizon.sh` ensures [Laravel Horizon](https://laravel.com/docs/master/horizon) used by Pixelfed is configured +* `/docker/entrypoint.d/30-cache.sh` ensures all Pixelfed caches (router, view, config) is warmed + +### Disabling entrypoint or individual scripts + +To disable the entire entrypoint you can set the variable `ENTRYPOINT_SKIP=1`. + +To disable individual entrypoint scripts you can add the filename to the space (`" "`) separated variable `ENTRYPOINT_SKIP_SCRIPTS`. (example: `ENTRYPOINT_SKIP_SCRIPTS="10-storage.sh 30-cache.sh"`) + +## Templating + +The Docker container can do some basic templating (more like variable replacement) as part of the entrypoint scripts via [gomplate](https://docs.gomplate.ca/). + +Any file put in the `/docker/templates/` directory will be templated and written to the right directory. + +### File path examples + +1. To template `/usr/local/etc/php/php.ini` in the container put the source file in `/docker/templates/usr/local/etc/php/php.ini`. +1. To template `/a/fantastic/example.txt` in the container put the source file in `/docker/templates/a/fantastic/example.txt`. +1. To template `/some/path/anywhere` in the container put the source file in `/docker/templates/a/fantastic/example.txt`. + +### Available variables + +Variables available for templating are sourced (in order, so *last* source takes precedence) like this: + +1. `env:` in your `docker-compose.yml` or `-e` in your `docker run` / `docker compose run` +1. Any exported variables in `.envsh` files loaded *before* `05-templating.sh` (e.g. any file with `04-`, `03-`, `02-`, `01-` or `00-` prefix) +1. All key/value pairs in `/var/www/.env.docker` +1. All key/value pairs in `/var/www/.env` + +### Template guide 101 + +Please see the [`gomplate` documentation](https://docs.gomplate.ca/) for a more comprehensive overview. + +The most frequent use-case you have is likely to print a environment variable (or a default value if it's missing), so this is how to do that: + +* `{{ getenv "VAR_NAME" }}` print an environment variable and **fail** if the variable is not set. ([docs](https://docs.gomplate.ca/functions/env/#envgetenv)) +* `{{ getenv "VAR_NAME" "default" }}` print an environment variable and print `default` if the variable is not set. ([docs](https://docs.gomplate.ca/functions/env/#envgetenv)) + +The script will *fail* if you reference a variable that does not exist (and don't have a default value) in a template. + +Please see the + +* [`gomplate` syntax documentation](https://docs.gomplate.ca/syntax/) +* [`gomplate` functions documentation](https://docs.gomplate.ca/functions/) + +## Fixing ownership on startup + +You can set the environment variable `ENTRYPOINT_ENSURE_OWNERSHIP_PATHS` to a list of paths that should have their `$USER` and `$GROUP` ownership changed to the configured runtime user and group during container bootstrapping. + +The variable is a space-delimited list shown below and accepts both relative and absolute paths: + +* `ENTRYPOINT_ENSURE_OWNERSHIP_PATHS="./storage ./bootstrap"` +* `ENTRYPOINT_ENSURE_OWNERSHIP_PATHS="/some/other/folder"` + +## Build settings (arguments) + +The Pixelfed Dockerfile utilizes [Docker Multi-stage builds](https://docs.docker.com/build/building/multi-stage/) and [Build arguments](https://docs.docker.com/build/guide/build-args/). + +Using *build arguments* allow us to create a flexible and more maintainable Dockerfile, supporting [multiple runtimes](runtimes.md) ([FPM](runtimes.md#fpm), [Nginx](runtimes.md#nginx), [Apache + mod_php](runtimes.md#apache)) and end-user flexibility without having to fork or copy the Dockerfile. + +*Build arguments* can be configured using `--build-arg 'name=value'` for `docker build`, `docker compose build` and `docker buildx build`. For `docker-compose.yml` the `args` key for [`build`](https://docs.docker.com/compose/compose-file/compose-file-v3/#build) can be used. + +### `PHP_VERSION` + +The `PHP` version to use when building the runtime container. + +Any valid Docker Hub PHP version is acceptable here, as long as it's [published to Docker Hub](https://hub.docker.com/_/php/tags) + +**Example values**: + +* `8` will use the latest version of PHP 8 +* `8.1` will use the latest version of PHP 8.1 +* `8.2.14` will use PHP 8.2.14 +* `latest` will use whatever is the latest PHP version + +**Default value**: `8.1` + +### `PHP_PECL_EXTENSIONS` + +PECL extensions to install via `pecl install` + +Use [PHP_PECL_EXTENSIONS_EXTRA](#php_pecl_extensions_extra) if you want to add *additional* extenstions. + +Only change this setting if you want to change the baseline extensions. + +See the [`PECL extensions` documentation on Docker Hub](https://hub.docker.com/_/php) for more information. + +**Default value**: `imagick redis` + +### `PHP_PECL_EXTENSIONS_EXTRA` + +Extra PECL extensions (separated by space) to install via `pecl install` + +See the [`PECL extensions` documentation on Docker Hub](https://hub.docker.com/_/php) for more information. + +**Default value**: `""` + +### `PHP_EXTENSIONS` + +PHP Extensions to install via `docker-php-ext-install`. + +**NOTE:** use [`PHP_EXTENSIONS_EXTRA`](#php_extensions_extra) if you want to add *additional* extensions, only override this if you want to change the baseline extensions. + +See the [`How to install more PHP extensions` documentation on Docker Hub](https://hub.docker.com/_/php) for more information + +**Default value**: `intl bcmath zip pcntl exif curl gd` + +### `PHP_EXTENSIONS_EXTRA` + +Extra PHP Extensions (separated by space) to install via `docker-php-ext-install`. + +See the [`How to install more PHP extensions` documentation on Docker Hub](https://hub.docker.com/_/php) for more information. + +**Default value**: `""` + +### `PHP_EXTENSIONS_DATABASE` + +PHP database extensions to install. + +By default we install both `pgsql` and `mysql` since it's more convinient (and adds very little build time! but can be overwritten here if required. + +**Default value**: `pdo_pgsql pdo_mysql pdo_sqlite` + +### `COMPOSER_VERSION` + +The version of Composer to install. + +Please see the [Docker Hub `composer` page](https://hub.docker.com/_/composer) for valid values. + +**Default value**: `2.6` + +### `APT_PACKAGES_EXTRA` + +Extra APT packages (separated by space) that should be installed inside the image by `apt-get install` + +**Default value**: `""` + +### `NGINX_VERSION` + +Version of `nginx` to when targeting [`nginx-runtime`](runtimes.md#nginx). + +Please see the [Docker Hub `nginx` page](https://hub.docker.com/_/nginx) for available versions. + +**Default value**: `1.25.3` + +### `PHP_BASE_TYPE` + +The `PHP` base image layer to use when building the runtime container. + +When targeting + +* [`apache-runtime`](runtimes.md#apache) use `apache` +* [`fpm-runtime`](runtimes.md#fpm) use `fpm` +* [`nginx-runtime`](runtimes.md#nginx) use `fpm` + +**Valid values**: + +* `apache` +* `fpm` +* `cli` + +**Default value**: `apache` + +### `PHP_DEBIAN_RELEASE` + +The `Debian` Operation System version to use. + +**Valid values**: + +* `bullseye` +* `bookworm` + +**Default value**: `bullseye` diff --git a/docker/new-server.md b/docker/new-server.md new file mode 100644 index 000000000..dbbf325f4 --- /dev/null +++ b/docker/new-server.md @@ -0,0 +1,145 @@ +# New Pixelfed + Docker + Docker Compose server + +This guide will help you install and run Pixelfed on **your** server using [Docker Compose](https://docs.docker.com/compose/). + +## Prerequisites + +Recommendations and requirements for hardware and software needed to run Pixelfed using Docker Compose. + +It's highly recommended that you have *some* experience with Linux (e.g. Ubuntu or Debian), SSH, and lightweight server administration. + +### Server + +A VPS or dedicated server you can SSH into, for example + +* [linode.com VPS](https://www.linode.com/) +* [DigitalOcean VPS](https://digitalocean.com/) +* [Hetzner](https://www.hetzner.com/) + +### Hardware + +Hardware requirements depends on the amount of users you have (or plan to have), and how active they are. + +A safe starter/small instance hardware for 25 users and blow are: + +* **CPU/vCPU** `2` cores. +* **RAM** `2-4 GB` as your instance grow, memory requirements will increase for the database. +* **Storage** `20-50 GB` HDD is fine, but ideally SSD or NVMe, *especially* for the database. +* **Network** `100 Mbit/s` or faster. + +### Domain and DNS + +* A **Domain** (or subdomain) is needed for the Pixelfed server (for example, `pixelfed.social` or `pixelfed.mydomain.com`) +* Having the required `A`/`CNAME` DNS records for your domain (above) pointing to your server. + * Typically an `A` record for the root (sometimes shown as `@`) record for `mydomain.com`. + * Possibly an `A` record for `www.` subdomain as well. + +### Network + +* Port `80` (HTTP) and `443` (HTTPS) ports forwarded to the server. + * Example for Ubuntu using [`ufw`](https://help.ubuntu.com/community/UFW) for port `80`: `ufw allow 80` + * Example for Ubuntu using [`ufw`](https://help.ubuntu.com/community/UFW) for port `443`: `ufw allow 443` + +### Optional + +* An **Email/SMTP provider** for sending e-mails to your users, such as e-mail confirmation and notifications. +* An **Object Storage** provider for storing all images remotely, rather than locally on your server. + +#### E-mail / SMTP provider + +**NOTE**: If you don't plan to use en e-mail/SMTP provider, then make sure to set `ENFORCE_EMAIL_VERIFICATION="false"` in your `.env` file! + +There are *many* providers out there, with wildly different pricing structures, features, and reliability. + +It's beyond the cope of this document to detail which provider to pick, or how to correctly configure them, but some providers that is known to be working well - with generous free tiers and affordable packages - are included for your convince (*in no particular order*) below: + +* [Simple Email Service (SES)](https://aws.amazon.com/ses/) by Amazon Web Services (AWS) is pay-as-you-go with a cost of $0.10/1000 emails. +* [Brevo](https://www.brevo.com/) (formerly SendInBlue) has a Free Tier with 300 emails/day. +* [Postmark](https://postmarkapp.com/) has a Free Tier with 100 emails/month. +* [Forward Email](https://forwardemail.net/en/private-business-email?pricing=true) has a $3/mo/domain plan with both sending and receiving included. +* [Mailtrap](https://mailtrap.io/email-sending/) has a 1000 emails/month free-tier (their `Email Sending` product, *not* the `Email Testing` one). + +#### Object Storage + +**NOTE**: This is *entirely* optional - by default Pixelfed will store all uploads (videos, images, etc.) directly on your servers storage. + +> Object storage is a technology that stores and manages data in an unstructured format called objects. Modern organizations create and analyze large volumes of unstructured data such as photos, videos, email, web pages, sensor data, and audio files +> +> -- [*What is object storage?*](https://aws.amazon.com/what-is/object-storage/) by Amazon Web Services + +It's beyond the cope of this document to detail which provider to pick, or how to correctly configure them, but some providers that is known to be working well - with generous free tiers and affordable packages - are included for your convince (*in no particular order*) below: + +* [R2](https://www.cloudflare.com/developer-platform/r2/) by CloudFlare has cheap storage, free *egress* (e.g. people downloading images) and included (and free) Content Delivery Network (CDN). +* [B2 cloud storage](https://www.backblaze.com/cloud-storage) by Backblaze. +* [Simple Storage Service (S3)](https://aws.amazon.com/s3/) by Amazon Web Services. + +### Software + +Required software to be installed on your server + +* `git` can be installed with `apt-get install git` on Debian/Ubuntu +* `docker` can be installed by [following the official Docker documentation](https://docs.docker.com/engine/install/) + +## Getting things ready + +Connect via SSH to your server and decide where you want to install Pixelfed. + +In this guide I'm going to assume it will be installed at `/data/pixelfed`. + +1. **Install required software** as mentioned in the [Software Prerequisites section above](#software) +1. **Create the parent directory** by running `mkdir -p /data` +1. **Clone the Pixelfed repository** by running `git clone https://github.com/pixelfed/pixelfed.git /data/pixelfed` +1. **Change to the Pixelfed directory** by running `cd /data/pixelfed` + +## Modifying your settings (`.env` file) + +### Copy the example configuration file + +Pixelfed contains a default configuration file (`.env.docker`) you should use as a starter, however, before editing anything, make a copy of it and put it in the *right* place (`.env`). + +Run the following command to copy the file: `cp .env.docker .env` + +### Modifying the configuration file + +The configuration file is *quite* long, but the good news is that you can ignore *most* of it, most of the *server-specific* settings are configured for you out of the box. + +The minimum required settings you **must** change is: + +* (required) `APP_DOMAIN` which is the hostname you plan to run your Pixelfed server on (e.g. `pixelfed.social`) - must **not** include `http://` or a trailing slash (`/`)! +* (required) `DB_PASSWORD` which is the database password, you can use a service like [pwgen.io](https://pwgen.io/en/) to generate a secure one. +* (optional) `ENFORCE_EMAIL_VERIFICATION` should be set to `"false"` if you don't plan to send emails. +* (optional) `MAIL_DRIVER` and related `MAIL_*` settings if you plan to use an [email/SMTP provider](#e-mail--smtp-provider) - See [Email variables documentation](https://docs.pixelfed.org/running-pixelfed/installation/#email-variables). +* (optional) `PF_ENABLE_CLOUD` / `FILESYSTEM_CLOUD` if you plan to use an [Object Storage provider](#object-storage). + +See the [`Configure environment variables`](https://docs.pixelfed.org/running-pixelfed/installation/#app-variables) documentation for details! + +You need to mainly focus on following sections + +* [App variables](https://docs.pixelfed.org/running-pixelfed/installation/#app-variables) +* [Email variables](https://docs.pixelfed.org/running-pixelfed/installation/#email-variables) + +You can skip the following sections, since they are already configured/automated for you: + +* `Redis` +* `Database` (except for `DB_PASSWORD`) +* `One-time setup tasks` + +### Starting the service + +With everything in place and (hopefully) well-configured, we can now go ahead and start our services by running + +```shell +docker compose up -d +``` + +This will download all the required Docker images, start the containers, and being the automatic setup. + +You can follow the logs by running `docker compose logs` - you might want to scroll to the top to logs from the start. + +You can use the CLI flag `--tail=100` to only see the most recent (`100` in this example) log lines for each container. + +You can use the CLI flag `--follow` to continue to see log output from the containers. + +You can combine `--tail=100` and `--follow` like this `docker compose logs --tail=100 --follow`. + +If you only care about specific contaieners, you can add them to the end of the command like this `docker compose logs web worker proxy`. diff --git a/docker/runtimes.md b/docker/runtimes.md new file mode 100644 index 000000000..68d7ee943 --- /dev/null +++ b/docker/runtimes.md @@ -0,0 +1,94 @@ +# Pixelfed Docker container runtimes + +The Pixelfed Dockerfile support multiple target *runtimes* ([Apache](#apache), [Nginx + FPM](#nginx), and [fpm](#fpm)). + +You can consider a *runtime* target as individual Dockerfiles, but instead, all of them are build from the same optimized Dockerfile, sharing +90% of their configuration and packages. + +**If you are unsure of which runtime to choose, please use the [Apache runtime](#apache) it's the most straightforward one and also the default** + +## Apache + +Building a custom Pixelfed Docker image using Apache + mod_php can be achieved the following way. + +### docker build (Apache) + +```shell +docker build \ + -f contrib/docker/Dockerfile \ + --target apache-runtime \ + --tag / \ + . +``` + +### docker compose (Apache) + +```yaml +version: "3" + +services: + app: + build: + context: . + dockerfile: contrib/docker/Dockerfile + target: apache-runtime +``` + +## Nginx + +Building a custom Pixelfed Docker image using nginx + FPM can be achieved the following way. + +### docker build (nginx) + +```shell +docker build \ + -f contrib/docker/Dockerfile \ + --target nginx-runtime \ + --build-arg 'PHP_BASE_TYPE=fpm' \ + --tag / \ + . +``` + +### docker compose (nginx) + +```yaml +version: "3" + +services: + app: + build: + context: . + dockerfile: contrib/docker/Dockerfile + target: nginx-runtime + args: + PHP_BASE_TYPE: fpm +``` + +## FPM + +Building a custom Pixelfed Docker image using FPM (only) can be achieved the following way. + +### docker build (fpm) + +```shell +docker build \ + -f contrib/docker/Dockerfile \ + --target fpm-runtime \ + --build-arg 'PHP_BASE_TYPE=fpm' \ + --tag / \ + . +``` + +### docker compose (fpm) + +```yaml +version: "3" + +services: + app: + build: + context: . + dockerfile: contrib/docker/Dockerfile + target: fpm-runtime + args: + PHP_BASE_TYPE: fpm +``` From 20ef1c7b940c24f932a05d9b2b4b320761ad2e0a Mon Sep 17 00:00:00 2001 From: Christian Winther Date: Mon, 15 Jan 2024 16:13:59 +0000 Subject: [PATCH 048/173] backfil docs --- docker/customizing.md | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/docker/customizing.md b/docker/customizing.md index adcc70b28..8dfc534dc 100644 --- a/docker/customizing.md +++ b/docker/customizing.md @@ -171,6 +171,24 @@ Please see the [Docker Hub `nginx` page](https://hub.docker.com/_/nginx) for ava **Default value**: `1.25.3` +### `FOREGO_VERSION` + +Version of [`forego`](https://github.com/ddollar/forego) to install. + +**Default value**: `0.17.2` + +### `GOMPLATE_VERSION` + +Version of [`goplate`](https://github.com/hairyhenderson/gomplate) to install. + +**Default value**: `v3.11.6` + +### `DOTENV_LINTER_VERSION` + +Version of [`dotenv-linter`](https://github.com/dotenv-linter/dotenv-linter) to install. + +**Default value**: `v3.2.0` + ### `PHP_BASE_TYPE` The `PHP` base image layer to use when building the runtime container. From 901d11df6007ac25efce6c1ce5173d03900688d6 Mon Sep 17 00:00:00 2001 From: Christian Winther Date: Mon, 15 Jan 2024 16:16:58 +0000 Subject: [PATCH 049/173] more docs help --- docker/README.md | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/docker/README.md b/docker/README.md index cbadcbf90..65fcdf720 100644 --- a/docker/README.md +++ b/docker/README.md @@ -2,4 +2,12 @@ * [Setting up a new Pixelfed server with Docker Compose](new-server.md) * [Understanding Pixelfed Container runtimes (Apache, FPM, Nginx + FPM)](runtimes.md) + * [Apache](runtimes.md#apache) + * [FPM](runtimes.md#fpm) + * [Nginx + FPM](runtimes.md#nginx) * [Customizing Docker image](customizing.md) + * [Running commands on container start](customizing.md#running-commands-on-container-start) + * [Disabling entrypoint or individual scripts](customizing.md#disabling-entrypoint-or-individual-scripts) + * [Templating](customizing.md#templating) + * [Fixing ownership on startup](customizing.md#fixing-ownership-on-startup) + * [Build settings (arguments)](customizing.md#build-settings-arguments) From ed0f9d64c8a29860fbca99e7a9167a59e83d12e3 Mon Sep 17 00:00:00 2001 From: Christian Winther Date: Mon, 15 Jan 2024 17:16:00 +0000 Subject: [PATCH 050/173] implement automatic shellcheck linting --- .github/workflows/docker.yml | 12 +++ docker/.shellcheckrc | 12 +++ .../docker/entrypoint.d/00-check-config.sh | 5 +- .../docker/entrypoint.d/01-permissions.sh | 17 ++-- .../docker/entrypoint.d/04-defaults.envsh | 4 +- .../root/docker/entrypoint.d/05-templating.sh | 15 ++-- .../root/docker/entrypoint.d/10-storage.sh | 5 +- .../entrypoint.d/11-first-time-setup.sh | 7 +- .../root/docker/entrypoint.d/12-migrations.sh | 7 +- .../root/docker/entrypoint.d/20-horizon.sh | 5 +- .../root/docker/entrypoint.d/30-cache.sh | 5 +- docker/shared/root/docker/entrypoint.sh | 37 +++++---- docker/shared/root/docker/helpers.sh | 79 +++++++++++-------- docker/shared/root/docker/install/base.sh | 19 +++-- .../root/docker/install/php-extensions.sh | 23 +++++- 15 files changed, 171 insertions(+), 81 deletions(-) create mode 100644 docker/.shellcheckrc diff --git a/.github/workflows/docker.yml b/.github/workflows/docker.yml index a2e73a61a..2efa04948 100644 --- a/.github/workflows/docker.yml +++ b/.github/workflows/docker.yml @@ -39,6 +39,18 @@ jobs: dockerfile: Dockerfile failure-threshold: error + shellcheck: + name: Shellcheck + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + - name: Run ShellCheck + uses: ludeeus/action-shellcheck@master + env: + SHELLCHECK_OPTS: --shell=bash --external-sources + with: + scandir: docker/ + build: runs-on: ubuntu-latest diff --git a/docker/.shellcheckrc b/docker/.shellcheckrc new file mode 100644 index 000000000..be92f81fc --- /dev/null +++ b/docker/.shellcheckrc @@ -0,0 +1,12 @@ +# See: https://github.com/koalaman/shellcheck/blob/master/shellcheck.1.md#rc-files + +source-path=SCRIPTDIR + +# Allow opening any 'source'd file, even if not specified as input +external-sources=true + +# Turn on warnings for unquoted variables with safe values +enable=quote-safe-variables + +# Turn on warnings for unassigned uppercase variables +enable=check-unassigned-uppercase diff --git a/docker/shared/root/docker/entrypoint.d/00-check-config.sh b/docker/shared/root/docker/entrypoint.d/00-check-config.sh index 36244f6ca..290deb3fc 100755 --- a/docker/shared/root/docker/entrypoint.d/00-check-config.sh +++ b/docker/shared/root/docker/entrypoint.d/00-check-config.sh @@ -1,5 +1,8 @@ #!/bin/bash -source /docker/helpers.sh +: "${ENTRYPOINT_ROOT:="/docker"}" + +# shellcheck source=SCRIPTDIR/../helpers.sh +source "${ENTRYPOINT_ROOT}/helpers.sh" entrypoint-set-script-name "$0" diff --git a/docker/shared/root/docker/entrypoint.d/01-permissions.sh b/docker/shared/root/docker/entrypoint.d/01-permissions.sh index 25a831531..58b2f0bb8 100755 --- a/docker/shared/root/docker/entrypoint.d/01-permissions.sh +++ b/docker/shared/root/docker/entrypoint.d/01-permissions.sh @@ -1,19 +1,22 @@ #!/bin/bash -source /docker/helpers.sh +: "${ENTRYPOINT_ROOT:="/docker"}" + +# shellcheck source=SCRIPTDIR/../helpers.sh +source "${ENTRYPOINT_ROOT}/helpers.sh" entrypoint-set-script-name "$0" # Ensure the two Docker volumes and dot-env files are owned by the runtime user as other scripts # will be writing to these -run-as-current-user chown --verbose ${RUNTIME_UID}:${RUNTIME_GID} "./.env" -run-as-current-user chown --verbose ${RUNTIME_UID}:${RUNTIME_GID} "./bootstrap/cache" -run-as-current-user chown --verbose ${RUNTIME_UID}:${RUNTIME_GID} "./storage" +run-as-current-user chown --verbose "${RUNTIME_UID}:${RUNTIME_GID}" "./.env" +run-as-current-user chown --verbose "${RUNTIME_UID}:${RUNTIME_GID}" "./bootstrap/cache" +run-as-current-user chown --verbose "${RUNTIME_UID}:${RUNTIME_GID}" "./storage" # Optionally fix ownership of configured paths -: ${ENTRYPOINT_ENSURE_OWNERSHIP_PATHS:=""} +: "${ENTRYPOINT_ENSURE_OWNERSHIP_PATHS:=""}" declare -a ensure_ownership_paths=() -IFS=' ' read -a ensure_ownership_paths <<<"${ENTRYPOINT_ENSURE_OWNERSHIP_PATHS}" +IFS=' ' read -ar ensure_ownership_paths <<<"${ENTRYPOINT_ENSURE_OWNERSHIP_PATHS}" if [[ ${#ensure_ownership_paths[@]} == 0 ]]; then log-info "No paths has been configured for ownership fixes via [\$ENTRYPOINT_ENSURE_OWNERSHIP_PATHS]." @@ -23,5 +26,5 @@ fi for path in "${ensure_ownership_paths[@]}"; do log-info "Ensure ownership of [${path}] is correct" - stream-prefix-command-output run-as-current-user chown --recursive ${RUNTIME_UID}:${RUNTIME_GID} "${path}" + stream-prefix-command-output run-as-current-user chown --recursive "${RUNTIME_UID}:${RUNTIME_GID}" "${path}" done diff --git a/docker/shared/root/docker/entrypoint.d/04-defaults.envsh b/docker/shared/root/docker/entrypoint.d/04-defaults.envsh index 3507d94ee..352ea23b7 100755 --- a/docker/shared/root/docker/entrypoint.d/04-defaults.envsh +++ b/docker/shared/root/docker/entrypoint.d/04-defaults.envsh @@ -13,7 +13,7 @@ entrypoint-set-script-name "${BASH_SOURCE[0]}" load-config-files # We assign a 1MB buffer to the just-in-time calculated max post size to allow for fields and overhead -: ${POST_MAX_SIZE_BUFFER:=1M} +: "${POST_MAX_SIZE_BUFFER:=1M}" log-info "POST_MAX_SIZE_BUFFER is set to [${POST_MAX_SIZE_BUFFER}]" buffer=$(numfmt --invalid=fail --from=auto --to=none --to-unit=K "${POST_MAX_SIZE_BUFFER}") log-info "POST_MAX_SIZE_BUFFER converted to KB is [${buffer}]" @@ -23,7 +23,7 @@ log-info "POST_MAX_SIZE will be calculated by [({MAX_PHOTO_SIZE} * {MAX_ALBUM_LE log-info " MAX_PHOTO_SIZE=${MAX_PHOTO_SIZE}" log-info " MAX_ALBUM_LENGTH=${MAX_ALBUM_LENGTH}" log-info " POST_MAX_SIZE_BUFFER=${buffer}" -: ${POST_MAX_SIZE:=$(numfmt --invalid=fail --from=auto --from-unit=K --to=si $(((${MAX_PHOTO_SIZE} * ${MAX_ALBUM_LENGTH}) + ${buffer})))} +: "${POST_MAX_SIZE:=$(numfmt --invalid=fail --from=auto --from-unit=K --to=si $(((MAX_PHOTO_SIZE * MAX_ALBUM_LENGTH) + buffer)))}" log-info "POST_MAX_SIZE was calculated to [${POST_MAX_SIZE}]" # NOTE: must export the value so it's available in other scripts! diff --git a/docker/shared/root/docker/entrypoint.d/05-templating.sh b/docker/shared/root/docker/entrypoint.d/05-templating.sh index 1bb62aae6..4d229b11c 100755 --- a/docker/shared/root/docker/entrypoint.d/05-templating.sh +++ b/docker/shared/root/docker/entrypoint.d/05-templating.sh @@ -1,14 +1,17 @@ #!/bin/bash -source /docker/helpers.sh +: "${ENTRYPOINT_ROOT:="/docker"}" + +# shellcheck source=SCRIPTDIR/../helpers.sh +source "${ENTRYPOINT_ROOT}/helpers.sh" entrypoint-set-script-name "$0" # Show [git diff] of templates being rendered (will help verify output) -: ${ENTRYPOINT_SHOW_TEMPLATE_DIFF:=1} +: "${ENTRYPOINT_SHOW_TEMPLATE_DIFF:=1}" # Directory where templates can be found -: ${ENTRYPOINT_TEMPLATE_DIR:=/docker/templates/} +: "${ENTRYPOINT_TEMPLATE_DIR:=/docker/templates/}" # Root path to write template template_files to (default is '', meaning it will be written to /) -: ${ENTRYPOINT_TEMPLATE_OUTPUT_PREFIX:=} +: "${ENTRYPOINT_TEMPLATE_OUTPUT_PREFIX:=}" declare template_file relative_template_file_path output_file_dir @@ -16,6 +19,8 @@ declare template_file relative_template_file_path output_file_dir load-config-files # export all dot-env variables so they are available in templating +# +# shellcheck disable=SC2068 export ${seen_dot_env_variables[@]} find "${ENTRYPOINT_TEMPLATE_DIR}" -follow -type f -print | while read -r template_file; do @@ -46,7 +51,7 @@ find "${ENTRYPOINT_TEMPLATE_DIR}" -follow -type f -print | while read -r templat # Render the template log-info "Running [gomplate] on [${template_file}] --> [${output_file_path}]" - cat "${template_file}" | gomplate >"${output_file_path}" + gomplate <"${template_file}" >"${output_file_path}" # Show the diff from the envsubst command if is-true "${ENTRYPOINT_SHOW_TEMPLATE_DIFF}"; then diff --git a/docker/shared/root/docker/entrypoint.d/10-storage.sh b/docker/shared/root/docker/entrypoint.d/10-storage.sh index bb2f61f0a..f0c28241d 100755 --- a/docker/shared/root/docker/entrypoint.d/10-storage.sh +++ b/docker/shared/root/docker/entrypoint.d/10-storage.sh @@ -1,5 +1,8 @@ #!/bin/bash -source /docker/helpers.sh +: "${ENTRYPOINT_ROOT:="/docker"}" + +# shellcheck source=SCRIPTDIR/../helpers.sh +source "${ENTRYPOINT_ROOT}/helpers.sh" entrypoint-set-script-name "$0" diff --git a/docker/shared/root/docker/entrypoint.d/11-first-time-setup.sh b/docker/shared/root/docker/entrypoint.d/11-first-time-setup.sh index 6778bd90e..9559eb4de 100755 --- a/docker/shared/root/docker/entrypoint.d/11-first-time-setup.sh +++ b/docker/shared/root/docker/entrypoint.d/11-first-time-setup.sh @@ -1,10 +1,13 @@ #!/bin/bash -source /docker/helpers.sh +: "${ENTRYPOINT_ROOT:="/docker"}" + +# shellcheck source=SCRIPTDIR/../helpers.sh +source "${ENTRYPOINT_ROOT}/helpers.sh" entrypoint-set-script-name "$0" # Allow automatic applying of outstanding/new migrations on startup -: ${DOCKER_RUN_ONE_TIME_SETUP_TASKS:=1} +: "${DOCKER_RUN_ONE_TIME_SETUP_TASKS:=1}" if is-false "${DOCKER_RUN_ONE_TIME_SETUP_TASKS}"; then log-warning "Automatic run of the 'One-time setup tasks' is disabled." diff --git a/docker/shared/root/docker/entrypoint.d/12-migrations.sh b/docker/shared/root/docker/entrypoint.d/12-migrations.sh index 20cbe3a31..b10e34c18 100755 --- a/docker/shared/root/docker/entrypoint.d/12-migrations.sh +++ b/docker/shared/root/docker/entrypoint.d/12-migrations.sh @@ -1,10 +1,13 @@ #!/bin/bash -source /docker/helpers.sh +: "${ENTRYPOINT_ROOT:="/docker"}" + +# shellcheck source=SCRIPTDIR/../helpers.sh +source "${ENTRYPOINT_ROOT}/helpers.sh" entrypoint-set-script-name "$0" # Allow automatic applying of outstanding/new migrations on startup -: ${DOCKER_APPLY_NEW_MIGRATIONS_AUTOMATICALLY:=0} +: "${DOCKER_APPLY_NEW_MIGRATIONS_AUTOMATICALLY:=0}" # Wait for the database to be ready await-database-ready diff --git a/docker/shared/root/docker/entrypoint.d/20-horizon.sh b/docker/shared/root/docker/entrypoint.d/20-horizon.sh index 6b81e7133..55efd768d 100755 --- a/docker/shared/root/docker/entrypoint.d/20-horizon.sh +++ b/docker/shared/root/docker/entrypoint.d/20-horizon.sh @@ -1,5 +1,8 @@ #!/bin/bash -source /docker/helpers.sh +: "${ENTRYPOINT_ROOT:="/docker"}" + +# shellcheck source=SCRIPTDIR/../helpers.sh +source "${ENTRYPOINT_ROOT}/helpers.sh" entrypoint-set-script-name "$0" diff --git a/docker/shared/root/docker/entrypoint.d/30-cache.sh b/docker/shared/root/docker/entrypoint.d/30-cache.sh index c8791e65b..c970db60b 100755 --- a/docker/shared/root/docker/entrypoint.d/30-cache.sh +++ b/docker/shared/root/docker/entrypoint.d/30-cache.sh @@ -1,5 +1,8 @@ #!/bin/bash -source /docker/helpers.sh +: "${ENTRYPOINT_ROOT:="/docker"}" + +# shellcheck source=SCRIPTDIR/../helpers.sh +source "${ENTRYPOINT_ROOT}/helpers.sh" entrypoint-set-script-name "$0" diff --git a/docker/shared/root/docker/entrypoint.sh b/docker/shared/root/docker/entrypoint.sh index 0e8b1089c..49d62afd0 100755 --- a/docker/shared/root/docker/entrypoint.sh +++ b/docker/shared/root/docker/entrypoint.sh @@ -4,42 +4,48 @@ if [[ ${ENTRYPOINT_SKIP:=0} != 0 ]]; then exec "$@" fi -# Directory where entrypoint scripts lives -: ${ENTRYPOINT_ROOT:="/docker/entrypoint.d/"} +: "${ENTRYPOINT_ROOT:="/docker"}" export ENTRYPOINT_ROOT +# Directory where entrypoint scripts lives +: "${ENTRYPOINT_D_ROOT:="${ENTRYPOINT_ROOT}/entrypoint.d/"}" +export ENTRYPOINT_D_ROOT + # Space separated list of scripts the entrypoint runner should skip -: ${ENTRYPOINT_SKIP_SCRIPTS:=""} +: "${ENTRYPOINT_SKIP_SCRIPTS:=""}" # Load helper scripts -source /docker/helpers.sh +# +# shellcheck source=SCRIPTDIR/helpers.sh +source "${ENTRYPOINT_ROOT}/helpers.sh" # Set the entrypoint name for logging entrypoint-set-script-name "entrypoint.sh" # Convert ENTRYPOINT_SKIP_SCRIPTS into a native bash array for easier lookup declare -a skip_scripts -IFS=' ' read -a skip_scripts <<<"$ENTRYPOINT_SKIP_SCRIPTS" +# shellcheck disable=SC2034 +IFS=' ' read -ar skip_scripts <<<"$ENTRYPOINT_SKIP_SCRIPTS" # Ensure the entrypoint root folder exists -mkdir -p "${ENTRYPOINT_ROOT}" +mkdir -p "${ENTRYPOINT_D_ROOT}" -# If ENTRYPOINT_ROOT directory is empty, warn and run the regular command -if is-directory-empty "${ENTRYPOINT_ROOT}"; then - log-warning "No files found in ${ENTRYPOINT_ROOT}, skipping configuration" +# If ENTRYPOINT_D_ROOT directory is empty, warn and run the regular command +if is-directory-empty "${ENTRYPOINT_D_ROOT}"; then + log-warning "No files found in ${ENTRYPOINT_D_ROOT}, skipping configuration" exec "$@" fi -acquire-lock +acquire-lock "entrypoint.sh" # Start scanning for entrypoint.d files to source or run -log-info "looking for shell scripts in [${ENTRYPOINT_ROOT}]" +log-info "looking for shell scripts in [${ENTRYPOINT_D_ROOT}]" -find "${ENTRYPOINT_ROOT}" -follow -type f -print | sort -V | while read -r file; do +find "${ENTRYPOINT_D_ROOT}" -follow -type f -print | sort -V | while read -r file; do # Skip the script if it's in the skip-script list - if in-array $(get-entrypoint-script-name "${file}") skip_scripts; then - log-warning "Skipping script [${script_name}] since it's in the skip list (\$ENTRYPOINT_SKIP_SCRIPTS)" + if in-array "$(get-entrypoint-script-name "${file}")" skip_scripts; then + log-warning "Skipping script [${file}] since it's in the skip list (\$ENTRYPOINT_SKIP_SCRIPTS)" continue fi @@ -56,6 +62,7 @@ find "${ENTRYPOINT_ROOT}" -follow -type f -print | sort -V | while read -r file; log-info "${notice_message_color}Sourcing [${file}]${color_clear}" log-info "" + # shellcheck disable=SC1090 source "${file}" # the sourced file will (should) than the log prefix, so this restores our own @@ -82,7 +89,7 @@ find "${ENTRYPOINT_ROOT}" -follow -type f -print | sort -V | while read -r file; esac done -release-lock +release-lock "entrypoint.sh" log-info "Configuration complete; ready for start up" diff --git a/docker/shared/root/docker/helpers.sh b/docker/shared/root/docker/helpers.sh index e71b4f295..74aa6c468 100644 --- a/docker/shared/root/docker/helpers.sh +++ b/docker/shared/root/docker/helpers.sh @@ -3,6 +3,9 @@ set -e -o errexit -o nounset -o pipefail [[ ${ENTRYPOINT_DEBUG:=0} == 1 ]] && set -x +: "${RUNTIME_UID:="33"}" +: "${RUNTIME_GID:="33"}" + # Some splash of color for important messages declare -g error_message_color="\033[1;31m" declare -g warn_message_color="\033[1;34m" @@ -23,11 +26,14 @@ declare -a dot_env_files=( # environment keys seen when source dot files (so we can [export] them) declare -ga seen_dot_env_variables=() -declare -g docker_state_path="$(readlink -f ./storage/docker)" +declare -g docker_state_path +docker_state_path="$(readlink -f ./storage/docker)" + declare -g docker_locks_path="${docker_state_path}/lock" declare -g docker_once_path="${docker_state_path}/once" -declare -g runtime_username=$(id -un ${RUNTIME_UID}) +declare -g runtime_username +runtime_username=$(id -un "${RUNTIME_UID}") # We should already be in /var/www, but just to be explicit cd /var/www || log-error-and-exit "could not change to /var/www" @@ -38,7 +44,7 @@ function entrypoint-set-script-name() { script_name_previous="${script_name}" script_name="${1}" - log_prefix="[entrypoint / $(get-entrypoint-script-name $1)] - " + log_prefix="[entrypoint / $(get-entrypoint-script-name "$1")] - " } # @description Restore the log prefix to the previous value that was captured in [entrypoint-set-script-name ] @@ -86,20 +92,18 @@ function run-command-as() { if [[ $exit_code != 0 ]]; then log-error "❌ Error!" - return $exit_code + return "$exit_code" fi log-info-stderr "✅ OK!" - return $exit_code + return "$exit_code" } # @description Streams stdout from the command and echo it # with log prefixing. # @see stream-prefix-command-output function stream-stdout-handler() { - local prefix="${1:-}" - - while read line; do + while read -r line; do log-info "(stdout) ${line}" done } @@ -108,7 +112,7 @@ function stream-stdout-handler() { # with a bit of color and log prefixing. # @see stream-prefix-command-output function stream-stderr-handler() { - while read line; do + while read -r line; do log-info-stderr "(${error_message_color}stderr${color_clear}) ${line}" done } @@ -123,11 +127,13 @@ function stream-prefix-command-output() { # if stdout is being piped, print it like normal with echo if [ ! -t 1 ]; then + # shellcheck disable=SC1007 stdout= echo >&1 -ne fi # if stderr is being piped, print it like normal with echo if [ ! -t 2 ]; then + # shellcheck disable=SC1007 stderr= echo >&2 -ne fi @@ -141,11 +147,11 @@ function log-error() { local msg if [[ $# -gt 0 ]]; then - msg="$@" + msg="$*" elif [[ ! -t 0 ]]; then - read msg || log-error-and-exit "[${FUNCNAME}] could not read from stdin" + read -r msg || log-error-and-exit "[${FUNCNAME[0]}] could not read from stdin" else - log-error-and-exit "[${FUNCNAME}] did not receive any input arguments and STDIN is empty" + log-error-and-exit "[${FUNCNAME[0]}] did not receive any input arguments and STDIN is empty" fi echo -e "${error_message_color}${log_prefix}ERROR - ${msg}${color_clear}" >/dev/stderr @@ -170,11 +176,11 @@ function log-warning() { local msg if [[ $# -gt 0 ]]; then - msg="$@" + msg="$*" elif [[ ! -t 0 ]]; then - read msg || log-error-and-exit "[${FUNCNAME}] could not read from stdin" + read -r msg || log-error-and-exit "[${FUNCNAME[0]}] could not read from stdin" else - log-error-and-exit "[${FUNCNAME}] did not receive any input arguments and STDIN is empty" + log-error-and-exit "[${FUNCNAME[0]}] did not receive any input arguments and STDIN is empty" fi echo -e "${warn_message_color}${log_prefix}WARNING - ${msg}${color_clear}" >/dev/stderr @@ -187,15 +193,15 @@ function log-info() { local msg if [[ $# -gt 0 ]]; then - msg="$@" + msg="$*" elif [[ ! -t 0 ]]; then - read msg || log-error-and-exit "[${FUNCNAME}] could not read from stdin" + read -r msg || log-error-and-exit "[${FUNCNAME[0]}] could not read from stdin" else - log-error-and-exit "[${FUNCNAME}] did not receive any input arguments and STDIN is empty" + log-error-and-exit "[${FUNCNAME[0]}] did not receive any input arguments and STDIN is empty" fi if [ -z "${ENTRYPOINT_QUIET_LOGS:-}" ]; then - echo -e "${log_prefix}${msg}" + echo -e "${notice_message_color}${log_prefix}${msg}${color_clear}" fi } @@ -206,11 +212,11 @@ function log-info-stderr() { local msg if [[ $# -gt 0 ]]; then - msg="$@" + msg="$*" elif [[ ! -t 0 ]]; then - read msg || log-error-and-exit "[${FUNCNAME}] could not read from stdin" + read -r msg || log-error-and-exit "[${FUNCNAME[0]}] could not read from stdin" else - log-error-and-exit "[${FUNCNAME}] did not receive any input arguments and STDIN is empty" + log-error-and-exit "[${FUNCNAME[0]}] did not receive any input arguments and STDIN is empty" fi if [ -z "${ENTRYPOINT_QUIET_LOGS:-}" ]; then @@ -231,15 +237,19 @@ function load-config-files() { fi log-info "Sourcing ${file}" + # shellcheck disable=SC1090 source "${file}" # find all keys in the dot-env file and store them in our temp associative array - for k in "$(grep -v '^#' "${file}" | cut -d"=" -f1 | xargs)"; do + for k in $(grep -v '^#' "${file}" | cut -d"=" -f1 | xargs); do _tmp_dot_env_keys[$k]=1 done done - seen_dot_env_variables=(${!_tmp_dot_env_keys[@]}) + # Used in other scripts (like templating) for [export]-ing the values + # + # shellcheck disable=SC2034 + seen_dot_env_variables=("${!_tmp_dot_env_keys[@]}") } # @description Checks if $needle exists in $haystack @@ -290,7 +300,7 @@ function file-exists() { # @exitcode 0 If $1 contains files # @exitcode 1 If $1 does *NOT* contain files function is-directory-empty() { - ! find "${1}" -mindepth 1 -maxdepth 1 -type f -print -quit 2>/dev/null | read v + ! find "${1}" -mindepth 1 -maxdepth 1 -type f -print -quit 2>/dev/null | read -r } # @description Ensures a directory exists (via mkdir) @@ -301,11 +311,11 @@ function ensure-directory-exists() { stream-prefix-command-output mkdir -pv "$@" } -# @description Find the relative path for a entrypoint script by removing the ENTRYPOINT_ROOT prefix +# @description Find the relative path for a entrypoint script by removing the ENTRYPOINT_D_ROOT prefix # @arg $1 string The path to manipulate # @stdout The relative path to the entrypoint script function get-entrypoint-script-name() { - echo "${1#"$ENTRYPOINT_ROOT"}" + echo "${1#"$ENTRYPOINT_D_ROOT"}" } # @description Ensure a command is only run once (via a 'lock' file) in the storage directory. @@ -373,12 +383,14 @@ function release-lock() { # @arg $@ string The list of trap signals to register function on-trap() { local trap_add_cmd=$1 - shift || log-error-and-exit "${FUNCNAME} usage error" + shift || log-error-and-exit "${FUNCNAME[0]} usage error" for trap_add_name in "$@"; do trap -- "$( # helper fn to get existing trap command from output # of trap -p + # + # shellcheck disable=SC2317 extract_trap_cmd() { printf '%s\n' "${3:-}"; } # print existing trap command with newline eval "extract_trap_cmd $(trap -p "${trap_add_name}")" @@ -403,12 +415,14 @@ function await-database-ready() { case "${DB_CONNECTION:-}" in mysql) + # shellcheck disable=SC2154 while ! echo "SELECT 1" | mysql --user="${DB_USERNAME}" --password="${DB_PASSWORD}" --host="${DB_HOST}" "${DB_DATABASE}" --silent >/dev/null; do staggered-sleep done ;; pgsql) + # shellcheck disable=SC2154 while ! echo "SELECT 1" | PGPASSWORD="${DB_PASSWORD}" psql --user="${DB_USERNAME}" --host="${DB_HOST}" "${DB_DATABASE}" >/dev/null; do staggered-sleep done @@ -417,6 +431,7 @@ function await-database-ready() { sqlsrv) log-warning "Don't know how to check if SQLServer is *truely* ready or not - so will just check if we're able to connect to it" + # shellcheck disable=SC2154 while ! timeout 1 bash -c "cat < /dev/null > /dev/tcp/${DB_HOST}/${DB_PORT}"; do staggered-sleep done @@ -437,7 +452,7 @@ function await-database-ready() { # @description sleeps between 1 and 3 seconds to ensure a bit of randomness # in multiple scripts/containers doing work almost at the same time. function staggered-sleep() { - sleep $(get-random-number-between 1 3) + sleep "$(get-random-number-between 1 3)" } # @description Helper function to get a random number between $1 and $2 @@ -459,13 +474,13 @@ function show-call-stack() { local src # to avoid noise we start with 1 to skip the get_stack function - for ((i = 1; i < $stack_size; i++)); do + for ((i = 1; i < stack_size; i++)); do func="${FUNCNAME[$i]}" - [ x$func = x ] && func=MAIN + [ -z "$func" ] && func="MAIN" lineno="${BASH_LINENO[$((i - 1))]}" src="${BASH_SOURCE[$i]}" - [ x"$src" = x ] && src=non_file_source + [ -z "$src" ] && src="non_file_source" log-error " at: ${func} ${src}:${lineno}" done diff --git a/docker/shared/root/docker/install/base.sh b/docker/shared/root/docker/install/base.sh index 5856836f9..5c4f38062 100755 --- a/docker/shared/root/docker/install/base.sh +++ b/docker/shared/root/docker/install/base.sh @@ -1,6 +1,9 @@ #!/bin/bash set -ex -o errexit -o nounset -o pipefail +: "${APT_PACKAGES_EXTRA:=""}" +: "${DOTENV_LINTER_VERSION:=""}" + # Ensure we keep apt cache around in a Docker environment rm -f /etc/apt/apt.conf.d/docker-clean echo 'Binary::apt::APT::Keep-Downloaded-Packages "true";' >/etc/apt/apt.conf.d/keep-cache @@ -73,16 +76,16 @@ apt-get update apt-get upgrade -y apt-get install -y \ - ${standardPackages[*]} \ - ${imageOptimization[*]} \ - ${imageProcessing[*]} \ - ${gdDependencies[*]} \ - ${videoProcessing[*]} \ - ${databaseDependencies[*]} \ - ${APT_PACKAGES_EXTRA} + "${standardPackages[@]}" \ + "${imageOptimization[@]}" \ + "${imageProcessing[@]}" \ + "${gdDependencies[@]}" \ + "${videoProcessing[@]}" \ + "${databaseDependencies[@]}" \ + "${APT_PACKAGES_EXTRA}" locale-gen update-locale # Install dotenv linter (https://github.com/dotenv-linter/dotenv-linter) -curl -sSfL https://raw.githubusercontent.com/dotenv-linter/dotenv-linter/master/install.sh | sh -s -- -b /usr/local/bin ${DOTENV_LINTER_VERSION} +curl -sSfL https://raw.githubusercontent.com/dotenv-linter/dotenv-linter/master/install.sh | sh -s -- -b /usr/local/bin "${DOTENV_LINTER_VERSION}" diff --git a/docker/shared/root/docker/install/php-extensions.sh b/docker/shared/root/docker/install/php-extensions.sh index 1cb86fd77..baf460c80 100755 --- a/docker/shared/root/docker/install/php-extensions.sh +++ b/docker/shared/root/docker/install/php-extensions.sh @@ -1,6 +1,12 @@ #!/bin/bash set -ex -o errexit -o nounset -o pipefail +: "${PHP_PECL_EXTENSIONS:=""}" +: "${PHP_PECL_EXTENSIONS_EXTRA:=""}" +: "${PHP_EXTENSIONS:=""}" +: "${PHP_EXTENSIONS_EXTRA:=""}" +: "${PHP_EXTENSIONS_DATABASE:=""}" + # Grab the PHP source code so we can compile against it docker-php-source extract @@ -14,7 +20,7 @@ docker-php-ext-configure gd \ # Optional script folks can copy into their image to do any [docker-php-ext-configure] work before the [docker-php-ext-install] # this can also overwirte the [gd] configure above by simply running it again if [[ -f /install/php-extension-configure.sh ]]; then - if [ !-x "$f" ]; then + if [ ! -x "/install/php-extension-configure.sh" ]; then echo >&2 "ERROR: found /install/php-extension-configure.sh but its not executable - please [chmod +x] the file!" exit 1 fi @@ -23,10 +29,19 @@ if [[ -f /install/php-extension-configure.sh ]]; then fi # Install pecl extensions -pecl install ${PHP_PECL_EXTENSIONS} ${PHP_PECL_EXTENSIONS_EXTRA} +pecl install "${PHP_PECL_EXTENSIONS}" "${PHP_PECL_EXTENSIONS_EXTRA}" # PHP extensions (dependencies) -docker-php-ext-install -j$(nproc) ${PHP_EXTENSIONS} ${PHP_EXTENSIONS_EXTRA} ${PHP_EXTENSIONS_DATABASE} +docker-php-ext-install \ + -j "$(nproc)" \ + "${PHP_EXTENSIONS}" \ + "${PHP_EXTENSIONS_EXTRA}" \ + "${PHP_EXTENSIONS_DATABASE}" # Enable all extensions -docker-php-ext-enable ${PHP_PECL_EXTENSIONS} ${PHP_PECL_EXTENSIONS_EXTRA} ${PHP_EXTENSIONS} ${PHP_EXTENSIONS_EXTRA} ${PHP_EXTENSIONS_DATABASE} +docker-php-ext-enable \ + "${PHP_PECL_EXTENSIONS}" \ + "${PHP_PECL_EXTENSIONS_EXTRA}" \ + "${PHP_EXTENSIONS}" \ + "${PHP_EXTENSIONS_EXTRA}" \ + "${PHP_EXTENSIONS_DATABASE}" From f2f251750360b350f11e7a481aa14837de693bd3 Mon Sep 17 00:00:00 2001 From: Christian Winther Date: Mon, 15 Jan 2024 17:17:48 +0000 Subject: [PATCH 051/173] implement automatic shellcheck linting --- .github/workflows/docker.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/docker.yml b/.github/workflows/docker.yml index 2efa04948..79dae64e7 100644 --- a/.github/workflows/docker.yml +++ b/.github/workflows/docker.yml @@ -49,7 +49,7 @@ jobs: env: SHELLCHECK_OPTS: --shell=bash --external-sources with: - scandir: docker/ + scandir: ./docker/ build: runs-on: ubuntu-latest From b2d6d3dbe7084a1a1b1c424668600dbf673639fa Mon Sep 17 00:00:00 2001 From: Christian Winther Date: Mon, 15 Jan 2024 17:23:32 +0000 Subject: [PATCH 052/173] implement automatic shellcheck linting --- .github/workflows/docker.yml | 1 + .../root/docker/install/php-extensions.sh | 20 +++++++++++-------- 2 files changed, 13 insertions(+), 8 deletions(-) diff --git a/.github/workflows/docker.yml b/.github/workflows/docker.yml index 79dae64e7..7127cdcbe 100644 --- a/.github/workflows/docker.yml +++ b/.github/workflows/docker.yml @@ -48,6 +48,7 @@ jobs: uses: ludeeus/action-shellcheck@master env: SHELLCHECK_OPTS: --shell=bash --external-sources + INPUT_ADDITIONAL_FILE_ARGS: -o -name '*.envsh' with: scandir: ./docker/ diff --git a/docker/shared/root/docker/install/php-extensions.sh b/docker/shared/root/docker/install/php-extensions.sh index baf460c80..86075ef1d 100755 --- a/docker/shared/root/docker/install/php-extensions.sh +++ b/docker/shared/root/docker/install/php-extensions.sh @@ -32,16 +32,20 @@ fi pecl install "${PHP_PECL_EXTENSIONS}" "${PHP_PECL_EXTENSIONS_EXTRA}" # PHP extensions (dependencies) +# +# shellcheck disable=SC2086 docker-php-ext-install \ -j "$(nproc)" \ - "${PHP_EXTENSIONS}" \ - "${PHP_EXTENSIONS_EXTRA}" \ - "${PHP_EXTENSIONS_DATABASE}" + ${PHP_EXTENSIONS} \ + ${PHP_EXTENSIONS_EXTRA} \ + ${PHP_EXTENSIONS_DATABASE} # Enable all extensions +# +# shellcheck disable=SC2086 docker-php-ext-enable \ - "${PHP_PECL_EXTENSIONS}" \ - "${PHP_PECL_EXTENSIONS_EXTRA}" \ - "${PHP_EXTENSIONS}" \ - "${PHP_EXTENSIONS_EXTRA}" \ - "${PHP_EXTENSIONS_DATABASE}" + ${PHP_PECL_EXTENSIONS} \ + ${PHP_PECL_EXTENSIONS_EXTRA} \ + ${PHP_EXTENSIONS} \ + ${PHP_EXTENSIONS_EXTRA} \ + ${PHP_EXTENSIONS_DATABASE} From fa10fe999e90dd68d7242b300f001a3242b7b2d1 Mon Sep 17 00:00:00 2001 From: Christian Winther Date: Mon, 15 Jan 2024 17:25:42 +0000 Subject: [PATCH 053/173] implement automatic shellcheck linting --- .github/workflows/docker.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/docker.yml b/.github/workflows/docker.yml index 7127cdcbe..bf73cc946 100644 --- a/.github/workflows/docker.yml +++ b/.github/workflows/docker.yml @@ -48,9 +48,10 @@ jobs: uses: ludeeus/action-shellcheck@master env: SHELLCHECK_OPTS: --shell=bash --external-sources - INPUT_ADDITIONAL_FILE_ARGS: -o -name '*.envsh' with: + version: v0.9.0 scandir: ./docker/ + additional_files: "*.envsh" build: runs-on: ubuntu-latest From 7f99bb10242762e553d6c19622156f5106ec66f3 Mon Sep 17 00:00:00 2001 From: Christian Winther Date: Mon, 15 Jan 2024 17:30:14 +0000 Subject: [PATCH 054/173] implement automatic shellcheck linting --- .../root/docker/install/php-extensions.sh | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/docker/shared/root/docker/install/php-extensions.sh b/docker/shared/root/docker/install/php-extensions.sh index 86075ef1d..8abb3dff8 100755 --- a/docker/shared/root/docker/install/php-extensions.sh +++ b/docker/shared/root/docker/install/php-extensions.sh @@ -1,11 +1,20 @@ #!/bin/bash set -ex -o errexit -o nounset -o pipefail -: "${PHP_PECL_EXTENSIONS:=""}" -: "${PHP_PECL_EXTENSIONS_EXTRA:=""}" -: "${PHP_EXTENSIONS:=""}" -: "${PHP_EXTENSIONS_EXTRA:=""}" -: "${PHP_EXTENSIONS_DATABASE:=""}" +# shellcheck disable=SC2223 +: ${PHP_PECL_EXTENSIONS:=""} + +# shellcheck disable=SC2223 +: ${PHP_PECL_EXTENSIONS_EXTRA:=""} + +# shellcheck disable=SC2223 +: ${PHP_EXTENSIONS:=""} + +# shellcheck disable=SC2223 +: ${PHP_EXTENSIONS_EXTRA:=""} + +# shellcheck disable=SC2223 +: ${PHP_EXTENSIONS_DATABASE:=""} # Grab the PHP source code so we can compile against it docker-php-source extract From 685f62a5d0550f4a64e89a2dac60dbae0c5d2586 Mon Sep 17 00:00:00 2001 From: Christian Winther Date: Mon, 15 Jan 2024 18:44:43 +0000 Subject: [PATCH 055/173] allow skipping one-time setup tasks --- Dockerfile | 4 +- .../docker/entrypoint.d/04-defaults.envsh | 3 ++ .../root/docker/install/php-extensions.sh | 48 ++++++------------- 3 files changed, 20 insertions(+), 35 deletions(-) diff --git a/Dockerfile b/Dockerfile index 33d0eeee3..6151d8758 100644 --- a/Dockerfile +++ b/Dockerfile @@ -40,8 +40,8 @@ ARG RUNTIME_GID=33 # often called 'www-data' ARG APT_PACKAGES_EXTRA="" # Extensions installed via [pecl install] -ARG PHP_PECL_EXTENSIONS="" -ARG PHP_PECL_EXTENSIONS_EXTRA="" +ARG PHP_PECL_EXTENSIONS= +ARG PHP_PECL_EXTENSIONS_EXTRA= # Extensions installed via [docker-php-ext-install] ARG PHP_EXTENSIONS="intl bcmath zip pcntl exif curl gd" diff --git a/docker/shared/root/docker/entrypoint.d/04-defaults.envsh b/docker/shared/root/docker/entrypoint.d/04-defaults.envsh index 352ea23b7..d47f55728 100755 --- a/docker/shared/root/docker/entrypoint.d/04-defaults.envsh +++ b/docker/shared/root/docker/entrypoint.d/04-defaults.envsh @@ -10,6 +10,9 @@ entrypoint-set-script-name "${BASH_SOURCE[0]}" +: "${MAX_PHOTO_SIZE:-}" +: "${MAX_ALBUM_LENGTH:-}" + load-config-files # We assign a 1MB buffer to the just-in-time calculated max post size to allow for fields and overhead diff --git a/docker/shared/root/docker/install/php-extensions.sh b/docker/shared/root/docker/install/php-extensions.sh index 8abb3dff8..42c149d76 100755 --- a/docker/shared/root/docker/install/php-extensions.sh +++ b/docker/shared/root/docker/install/php-extensions.sh @@ -1,20 +1,14 @@ #!/bin/bash set -ex -o errexit -o nounset -o pipefail -# shellcheck disable=SC2223 -: ${PHP_PECL_EXTENSIONS:=""} +declare -a pecl_extensions=() +readarray -d ' ' -t pecl_extensions < <(echo -n "${PHP_PECL_EXTENSIONS:-}") +readarray -d ' ' -t -O "${#pecl_extensions[@]}" pecl_extensions < <(echo -n "${PHP_PECL_EXTENSIONS_EXTRA:-}") -# shellcheck disable=SC2223 -: ${PHP_PECL_EXTENSIONS_EXTRA:=""} - -# shellcheck disable=SC2223 -: ${PHP_EXTENSIONS:=""} - -# shellcheck disable=SC2223 -: ${PHP_EXTENSIONS_EXTRA:=""} - -# shellcheck disable=SC2223 -: ${PHP_EXTENSIONS_DATABASE:=""} +declare -a php_extensions=() +readarray -d ' ' -t php_extensions < <(echo -n "${PHP_EXTENSIONS:-}") +readarray -d ' ' -t -O "${#php_extensions[@]}" php_extensions < <(echo -n "${PHP_EXTENSIONS_EXTRA:-}") +readarray -d ' ' -t -O "${#php_extensions[@]}" php_extensions < <(echo -n "${PHP_EXTENSIONS_DATABASE:-}") # Grab the PHP source code so we can compile against it docker-php-source extract @@ -28,33 +22,21 @@ docker-php-ext-configure gd \ # Optional script folks can copy into their image to do any [docker-php-ext-configure] work before the [docker-php-ext-install] # this can also overwirte the [gd] configure above by simply running it again -if [[ -f /install/php-extension-configure.sh ]]; then - if [ ! -x "/install/php-extension-configure.sh" ]; then - echo >&2 "ERROR: found /install/php-extension-configure.sh but its not executable - please [chmod +x] the file!" +declare -r custom_pre_configure_script="" +if [[ -e "${custom_pre_configure_script}" ]]; then + if [ ! -x "${custom_pre_configure_script}" ]; then + echo >&2 "ERROR: found ${custom_pre_configure_script} but its not executable - please [chmod +x] the file!" exit 1 fi - /install/php-extension-configure.sh + "${custom_pre_configure_script}" fi # Install pecl extensions -pecl install "${PHP_PECL_EXTENSIONS}" "${PHP_PECL_EXTENSIONS_EXTRA}" +pecl install "${pecl_extensions[@]}" # PHP extensions (dependencies) -# -# shellcheck disable=SC2086 -docker-php-ext-install \ - -j "$(nproc)" \ - ${PHP_EXTENSIONS} \ - ${PHP_EXTENSIONS_EXTRA} \ - ${PHP_EXTENSIONS_DATABASE} +docker-php-ext-install -j "$(nproc)" "${php_extensions[@]}" # Enable all extensions -# -# shellcheck disable=SC2086 -docker-php-ext-enable \ - ${PHP_PECL_EXTENSIONS} \ - ${PHP_PECL_EXTENSIONS_EXTRA} \ - ${PHP_EXTENSIONS} \ - ${PHP_EXTENSIONS_EXTRA} \ - ${PHP_EXTENSIONS_DATABASE} +docker-php-ext-enable "${pecl_extensions[@]}" "${php_extensions[@]}" From 903aeb7608def2a99b87873d9f22e4fe041154e6 Mon Sep 17 00:00:00 2001 From: Christian Winther Date: Mon, 15 Jan 2024 18:53:54 +0000 Subject: [PATCH 056/173] more cleanup --- .../docker/entrypoint.d/04-defaults.envsh | 6 ++-- docker/shared/root/docker/install/base.sh | 32 +++++++------------ 2 files changed, 15 insertions(+), 23 deletions(-) diff --git a/docker/shared/root/docker/entrypoint.d/04-defaults.envsh b/docker/shared/root/docker/entrypoint.d/04-defaults.envsh index d47f55728..fe906120a 100755 --- a/docker/shared/root/docker/entrypoint.d/04-defaults.envsh +++ b/docker/shared/root/docker/entrypoint.d/04-defaults.envsh @@ -10,11 +10,11 @@ entrypoint-set-script-name "${BASH_SOURCE[0]}" -: "${MAX_PHOTO_SIZE:-}" -: "${MAX_ALBUM_LENGTH:-}" - load-config-files +: "${MAX_PHOTO_SIZE:=}" +: "${MAX_ALBUM_LENGTH:=}" + # We assign a 1MB buffer to the just-in-time calculated max post size to allow for fields and overhead : "${POST_MAX_SIZE_BUFFER:=1M}" log-info "POST_MAX_SIZE_BUFFER is set to [${POST_MAX_SIZE_BUFFER}]" diff --git a/docker/shared/root/docker/install/base.sh b/docker/shared/root/docker/install/base.sh index 5c4f38062..7fa43b0f9 100755 --- a/docker/shared/root/docker/install/base.sh +++ b/docker/shared/root/docker/install/base.sh @@ -1,9 +1,6 @@ #!/bin/bash set -ex -o errexit -o nounset -o pipefail -: "${APT_PACKAGES_EXTRA:=""}" -: "${DOTENV_LINTER_VERSION:=""}" - # Ensure we keep apt cache around in a Docker environment rm -f /etc/apt/apt.conf.d/docker-clean echo 'Binary::apt::APT::Keep-Downloaded-Packages "true";' >/etc/apt/apt.conf.d/keep-cache @@ -14,8 +11,10 @@ echo 'APT::Install-Recommends "false";' >>/etc/apt/apt.conf # Don't install suggested packages by default echo 'APT::Install-Suggests "false";' >>/etc/apt/apt.conf +declare -a packages=() + # Standard packages -declare -ra standardPackages=( +packages+=( apt-utils ca-certificates curl @@ -36,7 +35,7 @@ declare -ra standardPackages=( ) # Image Optimization -declare -ra imageOptimization=( +packages+=( gifsicle jpegoptim optipng @@ -44,14 +43,14 @@ declare -ra imageOptimization=( ) # Image Processing -declare -ra imageProcessing=( +packages+=( libjpeg62-turbo-dev libmagickwand-dev libpng-dev ) # Required for GD -declare -ra gdDependencies=( +packages+=( libwebp-dev libwebp6 libxpm-dev @@ -59,33 +58,26 @@ declare -ra gdDependencies=( ) # Video Processing -declare -ra videoProcessing=( +packages+=( ffmpeg ) # Database -declare -ra databaseDependencies=( +packages+=( libpq-dev libsqlite3-dev mariadb-client postgresql-client ) +readarray -d ' ' -t -O "${#packages[@]}" packages < <(echo -n "${APT_PACKAGES_EXTRA:-}") + apt-get update - apt-get upgrade -y - -apt-get install -y \ - "${standardPackages[@]}" \ - "${imageOptimization[@]}" \ - "${imageProcessing[@]}" \ - "${gdDependencies[@]}" \ - "${videoProcessing[@]}" \ - "${databaseDependencies[@]}" \ - "${APT_PACKAGES_EXTRA}" +apt-get install -y "${packages[@]}" locale-gen update-locale # Install dotenv linter (https://github.com/dotenv-linter/dotenv-linter) -curl -sSfL https://raw.githubusercontent.com/dotenv-linter/dotenv-linter/master/install.sh | sh -s -- -b /usr/local/bin "${DOTENV_LINTER_VERSION}" +curl -sSfL https://raw.githubusercontent.com/dotenv-linter/dotenv-linter/master/install.sh | sh -s -- -b /usr/local/bin "${DOTENV_LINTER_VERSION:-}" From 53eb9c11fc2170d72556c35b4c0cc5e18655e0aa Mon Sep 17 00:00:00 2001 From: Christian Winther Date: Mon, 15 Jan 2024 19:20:22 +0000 Subject: [PATCH 057/173] add faq --- .env.docker | 7 +++++-- docker-compose.yml | 6 ++++++ docker/README.md | 2 ++ docker/faq.md | 19 +++++++++++++++++++ 4 files changed, 32 insertions(+), 2 deletions(-) create mode 100644 docker/faq.md diff --git a/.env.docker b/.env.docker index 559c06553..0f5aa6112 100644 --- a/.env.docker +++ b/.env.docker @@ -939,12 +939,15 @@ DOCKER_REDIS_PORT_EXTERNAL="${REDIS_PORT}" # Use "3306" for MySQL/MariaDB and "5432" for PostgreeSQL DOCKER_DB_PORT_EXTERNAL="${DB_PORT}" -# Port that the web will listen on *outside* the container (e.g. the host machine) for HTTP traffic +# Port that the [proxy] will listen on *outside* the container (e.g. the host machine) for HTTP traffic DOCKER_PROXY_PORT_EXTERNAL_HTTP="80" -# Port that the web will listen on *outside* the container (e.g. the host machine) for HTTPS traffic +# Port that the [proxy] will listen on *outside* the container (e.g. the host machine) for HTTPS traffic DOCKER_PROXY_PORT_EXTERNAL_HTTPS="443" +# Port to expose [web] container will listen on *outside* the container (e.g. the host machine) for *HTTP* traffic only +DOCKER_WEB_PORT_EXTERNAL_HTTP="8080" + # Path to the Docker socket on the *host* DOCKER_HOST_SOCKET_PATH="/var/run/docker.sock" diff --git a/docker-compose.yml b/docker-compose.yml index 567998411..b2977e1e2 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -16,6 +16,8 @@ services: image: nginxproxy/nginx-proxy:1.4 container_name: "${DOCKER_CONTAINER_NAME_PREFIX}-proxy" restart: unless-stopped + profiles: + - ${DOCKER_PROXY_PROFILE} volumes: - "${DOCKER_HOST_SOCKET_PATH}:/tmp/docker.sock:ro" - "${DOCKER_CONFIG_ROOT}/proxy/conf.d:/etc/nginx/conf.d" @@ -33,6 +35,8 @@ services: image: nginxproxy/acme-companion container_name: "${DOCKER_CONTAINER_NAME_PREFIX}-proxy-acme" restart: unless-stopped + profiles: + - ${DOCKER_PROXY_ACME_PROFILE:-$DOCKER_PROXY_PROFILE} environment: DEBUG: 0 DEFAULT_EMAIL: "${LETSENCRYPT_EMAIL}" @@ -70,6 +74,8 @@ services: com.github.nginx-proxy.nginx-proxy.keepalive: 30 com.github.nginx-proxy.nginx-proxy.http2.enable: true com.github.nginx-proxy.nginx-proxy.http3.enable: true + # ports: + # - "${DOCKER_WEB_PORT_EXTERNAL_HTTP}:80" depends_on: - db - redis diff --git a/docker/README.md b/docker/README.md index 65fcdf720..bb3389965 100644 --- a/docker/README.md +++ b/docker/README.md @@ -1,6 +1,8 @@ # Pixelfed + Docker + Docker Compose * [Setting up a new Pixelfed server with Docker Compose](new-server.md) + * [I already have a SSL certificate, how do I use it?](faq.md#i-already-have-a-proxy-how-do-i-disable-the-included-one) + * [I already have an proxy / how do I disable the Nginx proxy](faq.md#i-already-have-a-ssl-certificate-how-do-i-use-it) * [Understanding Pixelfed Container runtimes (Apache, FPM, Nginx + FPM)](runtimes.md) * [Apache](runtimes.md#apache) * [FPM](runtimes.md#fpm) diff --git a/docker/faq.md b/docker/faq.md new file mode 100644 index 000000000..c284940b8 --- /dev/null +++ b/docker/faq.md @@ -0,0 +1,19 @@ +# Pixelfed Docker FAQ + +## I already have a Proxy, how do I disable the included one? + +No problem! All you have to do is + +1. *Comment out* (or delete) the `proxy` and `proxy-acme` services in `docker-compose.yml` +1. *Uncomment* the `ports` block for the `web` servince in `docker-compose.yml` +1. Change the `DOCKER_WEB_PORT_EXTERNAL_HTTP` setting in your `.env` if you want to change the port from the default `8080` +1. Point your proxy upstream to the exposed `web` port. + +## I already have a SSL certificate, how do I use it? + +1. *Comment out* (or delete) the `proxy-acme` service in `docker-compose.yml` +1. Put your certificates in `${DOCKER_CONFIG_ROOT}/proxy/certs/${APP_DOMAIN}/`. The following files are expected to exist in the directory for the proxy to detect and use them automatically (this is the same directory and file names as LetsEncrypt uses) + 1. `cert.pem` + 1. `chain.pem` + 1. `fullchain.pem` + 1. `key.pem` From 98660760c9d4b8cf0ca6293bf8277e78269b7db9 Mon Sep 17 00:00:00 2001 From: Christian Winther Date: Mon, 15 Jan 2024 19:39:59 +0000 Subject: [PATCH 058/173] improve faq --- .env.docker | 8 +++++++- docker-compose.yml | 9 +++------ docker/faq.md | 29 ++++++++++++++++++----------- 3 files changed, 28 insertions(+), 18 deletions(-) diff --git a/.env.docker b/.env.docker index 0f5aa6112..b512ce5d0 100644 --- a/.env.docker +++ b/.env.docker @@ -952,4 +952,10 @@ DOCKER_WEB_PORT_EXTERNAL_HTTP="8080" DOCKER_HOST_SOCKET_PATH="/var/run/docker.sock" # Prefix for container names (without any dash at the end) -DOCKER_CONTAINER_NAME_PREFIX="${APP_DOMAIN}-" +DOCKER_CONTAINER_NAME_PREFIX="${APP_DOMAIN}" + +# Set this to a non-empty value (e.g. "disabled") to disable the [proxy] and [proxy-acme] service +DOCKER_PROXY_PROFILE="" + +# Set this to a non-empty value (e.g. "disabled") to disable the [proxy-acme] service +DOCKER_PROXY_ACME_PROFILE="${DOCKER_PROXY_PROFILE}" diff --git a/docker-compose.yml b/docker-compose.yml index b2977e1e2..d56f61aa6 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -36,7 +36,7 @@ services: container_name: "${DOCKER_CONTAINER_NAME_PREFIX}-proxy-acme" restart: unless-stopped profiles: - - ${DOCKER_PROXY_ACME_PROFILE:-$DOCKER_PROXY_PROFILE} + - ${DOCKER_PROXY_ACME_PROFILE} environment: DEBUG: 0 DEFAULT_EMAIL: "${LETSENCRYPT_EMAIL}" @@ -57,9 +57,6 @@ services: restart: unless-stopped build: target: apache-runtime - deploy: - mode: replicated - replicas: 1 volumes: - "./.env:/var/www/.env" - "${DOCKER_DATA_ROOT}/pixelfed/cache:/var/www/bootstrap/cache" @@ -74,8 +71,8 @@ services: com.github.nginx-proxy.nginx-proxy.keepalive: 30 com.github.nginx-proxy.nginx-proxy.http2.enable: true com.github.nginx-proxy.nginx-proxy.http3.enable: true - # ports: - # - "${DOCKER_WEB_PORT_EXTERNAL_HTTP}:80" + ports: + - "${DOCKER_WEB_PORT_EXTERNAL_HTTP}:80" depends_on: - db - redis diff --git a/docker/faq.md b/docker/faq.md index c284940b8..f1354f1c3 100644 --- a/docker/faq.md +++ b/docker/faq.md @@ -2,18 +2,25 @@ ## I already have a Proxy, how do I disable the included one? -No problem! All you have to do is +No problem! All you have to do is: -1. *Comment out* (or delete) the `proxy` and `proxy-acme` services in `docker-compose.yml` -1. *Uncomment* the `ports` block for the `web` servince in `docker-compose.yml` -1. Change the `DOCKER_WEB_PORT_EXTERNAL_HTTP` setting in your `.env` if you want to change the port from the default `8080` -1. Point your proxy upstream to the exposed `web` port. +1. Change the `DOCKER_PROXY_PROFILE` key/value pair in your `.env` file to `"disabled"`. + * This disables the `proxy` *and* `proxy-acme` services in `docker-compose.yml`. + * The setting is near the bottom of the file. +1. Point your proxy upstream to the exposed `web` port (**Default**: `8080`). + * The port is controlled by the `DOCKER_WEB_PORT_EXTERNAL_HTTP` key in `.env`. + * The setting is near the bottom of the file. ## I already have a SSL certificate, how do I use it? -1. *Comment out* (or delete) the `proxy-acme` service in `docker-compose.yml` -1. Put your certificates in `${DOCKER_CONFIG_ROOT}/proxy/certs/${APP_DOMAIN}/`. The following files are expected to exist in the directory for the proxy to detect and use them automatically (this is the same directory and file names as LetsEncrypt uses) - 1. `cert.pem` - 1. `chain.pem` - 1. `fullchain.pem` - 1. `key.pem` +1. Change the `DOCKER_PROXY_ACME_PROFILE` key/value pair in your `.env` file to `"disabled"`. + * This disabled the `proxy-acme` service in `docker-compose.yml`. + * It does *not* disable the `proxy` service. +1. Put your certificates in `${DOCKER_CONFIG_ROOT}/proxy/certs` (e.g. `./docker-compose/config/proxy/certs`) + * You may need to create this folder manually if it does not exists. + * The following files are expected to exist in the directory for the proxy to detect and use them automatically (this is the same directory and file names as LetsEncrypt uses) + 1. `${APP_DOMAIN}.cert.pem` + 1. `${APP_DOMAIN}.chain.pem` + 1. `${APP_DOMAIN}.fullchain.pem` + 1. `${APP_DOMAIN}.key.pem` + * See the [`nginx-proxy` configuration file for name patterns](https://github.com/nginx-proxy/nginx-proxy/blob/main/nginx.tmpl#L659-L670) From 48e5d45b3f09e1dfbb714ef96c04ee8c12ba04c8 Mon Sep 17 00:00:00 2001 From: Christian Winther Date: Mon, 15 Jan 2024 19:43:52 +0000 Subject: [PATCH 059/173] improve faq --- docker/README.md | 5 +++-- docker/faq.md | 6 ++++-- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/docker/README.md b/docker/README.md index bb3389965..ea1870fd3 100644 --- a/docker/README.md +++ b/docker/README.md @@ -1,8 +1,9 @@ # Pixelfed + Docker + Docker Compose * [Setting up a new Pixelfed server with Docker Compose](new-server.md) - * [I already have a SSL certificate, how do I use it?](faq.md#i-already-have-a-proxy-how-do-i-disable-the-included-one) - * [I already have an proxy / how do I disable the Nginx proxy](faq.md#i-already-have-a-ssl-certificate-how-do-i-use-it) +* [Frequently Asked Question / FAQ](faq.md) + * [How do I use my own Proxy server?](faq.md#how-do-i-use-my-own-proxy-server) + * [How do I use my own SSL certificate?](faq.md#how-do-i-use-my-own-ssl-certificate) * [Understanding Pixelfed Container runtimes (Apache, FPM, Nginx + FPM)](runtimes.md) * [Apache](runtimes.md#apache) * [FPM](runtimes.md#fpm) diff --git a/docker/faq.md b/docker/faq.md index f1354f1c3..39a81f99d 100644 --- a/docker/faq.md +++ b/docker/faq.md @@ -1,6 +1,6 @@ # Pixelfed Docker FAQ -## I already have a Proxy, how do I disable the included one? +## How do I use my own Proxy server? No problem! All you have to do is: @@ -11,7 +11,9 @@ No problem! All you have to do is: * The port is controlled by the `DOCKER_WEB_PORT_EXTERNAL_HTTP` key in `.env`. * The setting is near the bottom of the file. -## I already have a SSL certificate, how do I use it? +## How do I use my own SSL certificate? + +No problem! All you have to do is: 1. Change the `DOCKER_PROXY_ACME_PROFILE` key/value pair in your `.env` file to `"disabled"`. * This disabled the `proxy-acme` service in `docker-compose.yml`. From 9c426b48a122d5e30baff73b62e915a4ce393eb2 Mon Sep 17 00:00:00 2001 From: Christian Winther Date: Mon, 15 Jan 2024 19:56:35 +0000 Subject: [PATCH 060/173] more docs --- docker-compose.yml | 13 +++++++++++-- docker/faq.md | 4 ++++ 2 files changed, 15 insertions(+), 2 deletions(-) diff --git a/docker-compose.yml b/docker-compose.yml index d56f61aa6..574cb1ec8 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -11,13 +11,19 @@ services: # Sits in front of the *real* webserver and manages SSL and (optionally) # load-balancing between multiple web servers # + # You can disable this service by setting [DOCKER_PROXY_PROFILE="disabled"] + # in your [.env] file - the setting is near the bottom of the file. + # + # This also disables the [proxy-acme] service, if this is not desired, change the + # [DOCKER_PROXY_ACME_PROFILE] setting to an empty string [""] + # # See: https://github.com/nginx-proxy/nginx-proxy/tree/main/docs proxy: image: nginxproxy/nginx-proxy:1.4 container_name: "${DOCKER_CONTAINER_NAME_PREFIX}-proxy" restart: unless-stopped profiles: - - ${DOCKER_PROXY_PROFILE} + - ${DOCKER_PROXY_PROFILE:-} volumes: - "${DOCKER_HOST_SOCKET_PATH}:/tmp/docker.sock:ro" - "${DOCKER_CONFIG_ROOT}/proxy/conf.d:/etc/nginx/conf.d" @@ -30,13 +36,16 @@ services: # Proxy companion for managing letsencrypt SSL certificates # + # You can disable this service by setting [DOCKER_PROXY_ACME_PROFILE="disabled"] + # in your [.env] file - the setting is near the bottom of the file. + # # See: https://github.com/nginx-proxy/acme-companion/tree/main/docs proxy-acme: image: nginxproxy/acme-companion container_name: "${DOCKER_CONTAINER_NAME_PREFIX}-proxy-acme" restart: unless-stopped profiles: - - ${DOCKER_PROXY_ACME_PROFILE} + - ${DOCKER_PROXY_ACME_PROFILE:-} environment: DEBUG: 0 DEFAULT_EMAIL: "${LETSENCRYPT_EMAIL}" diff --git a/docker/faq.md b/docker/faq.md index 39a81f99d..3988be578 100644 --- a/docker/faq.md +++ b/docker/faq.md @@ -26,3 +26,7 @@ No problem! All you have to do is: 1. `${APP_DOMAIN}.fullchain.pem` 1. `${APP_DOMAIN}.key.pem` * See the [`nginx-proxy` configuration file for name patterns](https://github.com/nginx-proxy/nginx-proxy/blob/main/nginx.tmpl#L659-L670) + +## How do I change the container name prefix? + +Change the `DOCKER_CONTAINER_NAME_PREFIX` key/value pair in your `.env` file. From 2135199c9787444c3df22fdf2d7afa6524787c25 Mon Sep 17 00:00:00 2001 From: Christian Winther Date: Mon, 15 Jan 2024 20:19:04 +0000 Subject: [PATCH 061/173] tune the github workflow config --- .env.docker | 15 +++++++++++++-- .github/workflows/docker.yml | 23 +++++++---------------- docker-compose.yml | 2 +- 3 files changed, 21 insertions(+), 19 deletions(-) diff --git a/.env.docker b/.env.docker index b512ce5d0..dd7a06887 100644 --- a/.env.docker +++ b/.env.docker @@ -1,6 +1,8 @@ # -*- mode: bash -*- # vi: ft=bash +# shellcheck disable=SC2034 + ############################################################### # Docker-wide configuration ############################################################### @@ -32,6 +34,15 @@ TZ="UTC" # Automatically run [artisan migrate --force] if new migrations are detected. DOCKER_APPLY_NEW_MIGRATIONS_AUTOMATICALLY="0" +# Automatically run "One-time setup tasks" commands. +# +# If you are migrating to this docker-compose setup or have manually run the "One time seutp" +# tasks (https://docs.pixelfed.org/running-pixelfed/installation/#setting-up-services) +# you can set this to "0" to prevent them from running. +# +# Otherwise, leave it at "1" to have them run *once*. +DOCKER_RUN_ONE_TIME_SETUP_TASKS="1" + # The e-mail to use for Lets Encrypt certificate requests. LETSENCRYPT_EMAIL="__CHANGE_ME__" @@ -294,7 +305,7 @@ DB_HOST="db" DB_USERNAME="pixelfed" # See: https://docs.pixelfed.org/technical-documentation/config/#db_password -DB_PASSWORD="helloworld" +DB_PASSWORD="__CHANGE_ME__" # See: https://docs.pixelfed.org/technical-documentation/config/#db_database DB_DATABASE="pixelfed_prod" @@ -751,7 +762,7 @@ LOG_CHANNEL="stderr" # - "null" (default) # # See: https://docs.pixelfed.org/technical-documentation/config/#broadcast_driver -BROADCAST_DRIVER=redis +BROADCAST_DRIVER="redis" ############################################################### # Other settings diff --git a/.github/workflows/docker.yml b/.github/workflows/docker.yml index bf73cc946..bda7004e6 100644 --- a/.github/workflows/docker.yml +++ b/.github/workflows/docker.yml @@ -102,25 +102,14 @@ jobs: packages: write env: - # Set the repo variable [DOCKER_HUB_USERNAME] to override the default at https://github.com///settings/variables/actions - # - # NOTE: no login attempt will happen with Docker Hub until this secret is set + # Set the repo variable [DOCKER_HUB_USERNAME] to override the default + # at https://github.com///settings/variables/actions DOCKER_HUB_USERNAME: ${{ vars.DOCKER_HUB_USERNAME || 'pixelfed' }} - # Set the repo variable [DOCKER_HUB_ORGANISATION] to override the default at https://github.com///settings/variables/actions - # - # NOTE: no login attempt will happen with Docker Hub until this secret is set - DOCKER_HUB_ORGANISATION: ${{ vars.DOCKER_HUB_ORGANISATION || 'pixelfed' }} - - # Set the repo variable [DOCKER_HUB_REPO] to override the default at https://github.com///settings/variables/actions - # - # NOTE: no login attempt will happen with Docker Hub until this secret is set - DOCKER_HUB_REPO: ${{ vars.DOCKER_HUB_REPO || 'pixelfed' }} - # For Docker Hub pushing to work, you need the secret [DOCKER_HUB_TOKEN] # set to your Personal Access Token at https://github.com///settings/secrets/actions # - # NOTE: no login attempt will happen with Docker Hub until this secret is set + # ! NOTE: no [login] or [push] will happen to Docker Hub until this secret is set! HAS_DOCKER_HUB_TOKEN: ${{ secrets.DOCKER_HUB_TOKEN != '' }} steps: @@ -136,6 +125,7 @@ jobs: with: version: v0.12.0 # *or* newer, needed for annotations to work + # See: https://github.com/docker/login-action?tab=readme-ov-file#github-container-registry - name: Log in to the GitHub Container registry uses: docker/login-action@v3 with: @@ -143,12 +133,13 @@ jobs: username: ${{ github.actor }} password: ${{ secrets.GITHUB_TOKEN }} + # See: https://github.com/docker/login-action?tab=readme-ov-file#docker-hub - name: Login to Docker Hub registry (conditionally) + if: ${{ env.HAS_DOCKER_HUB_TOKEN == true }} uses: docker/login-action@v3 with: username: ${{ env.DOCKER_HUB_USERNAME }} password: ${{ secrets.DOCKER_HUB_TOKEN }} - if: ${{ env.HAS_DOCKER_HUB_TOKEN == true }} - name: Docker meta uses: docker/metadata-action@v5 @@ -156,7 +147,7 @@ jobs: with: images: | name=ghcr.io/${{ github.repository }},enable=true - name=${{ env.DOCKER_HUB_ORGANISATION }}/${{ env.DOCKER_HUB_REPO }},enable=${{ env.HAS_DOCKER_HUB_TOKEN }} + name=${{ vars.GITHUB_REPOSITORY }},enable=${{ env.HAS_DOCKER_HUB_TOKEN }} flavor: | latest=auto suffix=-${{ matrix.target_runtime }}-${{ matrix.php_version }} diff --git a/docker-compose.yml b/docker-compose.yml index 574cb1ec8..0e5d2bb19 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -81,7 +81,7 @@ services: com.github.nginx-proxy.nginx-proxy.http2.enable: true com.github.nginx-proxy.nginx-proxy.http3.enable: true ports: - - "${DOCKER_WEB_PORT_EXTERNAL_HTTP}:80" + - "${DOCKER_WEB_PORT_EXTERNAL_HTTP:-8080}:80" depends_on: - db - redis From af1df5edfdfd73e31b9896e2f7895bae0b187470 Mon Sep 17 00:00:00 2001 From: Christian Winther Date: Mon, 15 Jan 2024 20:24:02 +0000 Subject: [PATCH 062/173] ooops --- .github/workflows/docker.yml | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/.github/workflows/docker.yml b/.github/workflows/docker.yml index bda7004e6..591c9d22a 100644 --- a/.github/workflows/docker.yml +++ b/.github/workflows/docker.yml @@ -106,11 +106,19 @@ jobs: # at https://github.com///settings/variables/actions DOCKER_HUB_USERNAME: ${{ vars.DOCKER_HUB_USERNAME || 'pixelfed' }} + # Set the repo variable [DOCKER_HUB_ORGANISATION] to override the default + # at https://github.com///settings/variables/actions + DOCKER_HUB_ORGANISATION: ${{ vars.DOCKER_HUB_ORGANISATION || 'pixelfed' }} + + # Set the repo variable [DOCKER_HUB_REPO] to override the default + # at https://github.com///settings/variables/actions + DOCKER_HUB_REPO: ${{ vars.DOCKER_HUB_REPO || 'pixelfed' }} + # For Docker Hub pushing to work, you need the secret [DOCKER_HUB_TOKEN] # set to your Personal Access Token at https://github.com///settings/secrets/actions # # ! NOTE: no [login] or [push] will happen to Docker Hub until this secret is set! - HAS_DOCKER_HUB_TOKEN: ${{ secrets.DOCKER_HUB_TOKEN != '' }} + HAS_DOCKER_HUB_CONFIGURED: ${{ secrets.DOCKER_HUB_TOKEN != '' }} steps: - name: Checkout Code @@ -135,7 +143,7 @@ jobs: # See: https://github.com/docker/login-action?tab=readme-ov-file#docker-hub - name: Login to Docker Hub registry (conditionally) - if: ${{ env.HAS_DOCKER_HUB_TOKEN == true }} + if: ${{ env.HAS_DOCKER_HUB_CONFIGURED == true }} uses: docker/login-action@v3 with: username: ${{ env.DOCKER_HUB_USERNAME }} @@ -147,7 +155,7 @@ jobs: with: images: | name=ghcr.io/${{ github.repository }},enable=true - name=${{ vars.GITHUB_REPOSITORY }},enable=${{ env.HAS_DOCKER_HUB_TOKEN }} + name=${{ env.DOCKER_HUB_ORGANISATION }}/${{ env.DOCKER_HUB_REPO }},enable=${{ env.HAS_DOCKER_HUB_CONFIGURED }} flavor: | latest=auto suffix=-${{ matrix.target_runtime }}-${{ matrix.php_version }} From 72b454143b0225aea509f2c38bf59e3ef8276c5a Mon Sep 17 00:00:00 2001 From: Christian Winther Date: Mon, 15 Jan 2024 20:42:11 +0000 Subject: [PATCH 063/173] tweaking configs --- .env.docker | 38 ++++++++++++++++--- .github/workflows/docker.yml | 3 +- docker/.shellcheckrc => .shellcheckrc | 0 docker-compose.yml | 12 +++--- .../root/docker/entrypoint.d/12-migrations.sh | 6 +-- 5 files changed, 43 insertions(+), 16 deletions(-) rename docker/.shellcheckrc => .shellcheckrc (100%) diff --git a/.env.docker b/.env.docker index dd7a06887..5dfd766bb 100644 --- a/.env.docker +++ b/.env.docker @@ -1,8 +1,8 @@ +# shellcheck disable=SC2034,SC2148 + # -*- mode: bash -*- # vi: ft=bash -# shellcheck disable=SC2034 - ############################################################### # Docker-wide configuration ############################################################### @@ -31,9 +31,6 @@ DOCKER_TAG="branch-jippi-fork-apache-8.1" # See: https://www.php.net/manual/en/timezones.php TZ="UTC" -# Automatically run [artisan migrate --force] if new migrations are detected. -DOCKER_APPLY_NEW_MIGRATIONS_AUTOMATICALLY="0" - # Automatically run "One-time setup tasks" commands. # # If you are migrating to this docker-compose setup or have manually run the "One time seutp" @@ -315,6 +312,9 @@ DB_DATABASE="pixelfed_prod" # See: https://docs.pixelfed.org/technical-documentation/config/#db_port DB_PORT="3306" +# Automatically run [artisan migrate --force] if new migrations are detected. +DB_APPLY_NEW_MIGRATIONS_AUTOMATICALLY="0" + ############################################################### # Mail configuration ############################################################### @@ -970,3 +970,31 @@ DOCKER_PROXY_PROFILE="" # Set this to a non-empty value (e.g. "disabled") to disable the [proxy-acme] service DOCKER_PROXY_ACME_PROFILE="${DOCKER_PROXY_PROFILE}" + +# Path (relative to the docker-compose.yml) or absolute (/some/other/path) where containers will store their data +DOCKER_DATA_ROOT="./docker-compose-state/data" + +# Path (relative to the docker-compose.yml) or absolute (/some/other/path) where containers will store their confguration +DOCKER_CONFIG_ROOT="./docker-compose-state/config" + +# Path (on host system) where the [db] container will store its data +# +# Path is relative (./some/other/path) to the docker-compose.yml or absolute (/some/other/path) +DB_DATA_PATH="${DOCKER_DATA_ROOT}/db" + +# Path (on host system) where the [redis] container will store its data +# +# Path is relative (./some/other/path) to the docker-compose.yml or absolute (/some/other/path) +REDIS_DATA_PATH="${DOCKER_DATA_ROOT}/redis" + +# Path (on host system) where the [app] + [worker] container will write +# its [storage] data (e.g uploads/images/profile pictures etc.). +# +# Path is relative (./some/other/path) to the docker-compose.yml or absolute (/some/other/path) +APP_STORAGE_PATH="${DOCKER_DATA_ROOT}/pixelfed/storage" + +# Path (on host system) where the [app] + [worker] container will write +# its [cache] data. +# +# Path is relative (./some/other/path) to the docker-compose.yml or absolute (/some/other/path) +APP_CACHE_PATH="${DOCKER_DATA_ROOT}/pixelfed/cache" diff --git a/.github/workflows/docker.yml b/.github/workflows/docker.yml index 591c9d22a..64978070a 100644 --- a/.github/workflows/docker.yml +++ b/.github/workflows/docker.yml @@ -50,8 +50,7 @@ jobs: SHELLCHECK_OPTS: --shell=bash --external-sources with: version: v0.9.0 - scandir: ./docker/ - additional_files: "*.envsh" + additional_files: "*.envsh .env .env.docker .env.example .env.testing" build: runs-on: ubuntu-latest diff --git a/docker/.shellcheckrc b/.shellcheckrc similarity index 100% rename from docker/.shellcheckrc rename to .shellcheckrc diff --git a/docker-compose.yml b/docker-compose.yml index 0e5d2bb19..614d3954a 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -68,8 +68,8 @@ services: target: apache-runtime volumes: - "./.env:/var/www/.env" - - "${DOCKER_DATA_ROOT}/pixelfed/cache:/var/www/bootstrap/cache" - - "${DOCKER_DATA_ROOT}/pixelfed/storage:/var/www/storage" + - "${APP_CACHE_PATH}:/var/www/bootstrap/cache" + - "${APP_STORAGE_PATH}:/var/www/storage" environment: LETSENCRYPT_HOST: "${LETSENCRYPT_HOST}" LETSENCRYPT_EMAIL: "${LETSENCRYPT_EMAIL}" @@ -98,8 +98,8 @@ services: target: apache-runtime volumes: - "./.env:/var/www/.env" - - "${DOCKER_DATA_ROOT}/pixelfed/cache:/var/www/bootstrap/cache" - - "${DOCKER_DATA_ROOT}/pixelfed/storage:/var/www/storage" + - "${APP_CACHE_PATH}:/var/www/bootstrap/cache" + - "${APP_STORAGE_PATH}:/var/www/storage" depends_on: - db - redis @@ -112,7 +112,7 @@ services: env_file: - ".env" volumes: - - "${DOCKER_DATA_ROOT}/db:/var/lib/mysql" + - "${DB_DATA_PATH}:/var/lib/mysql" ports: - "${DOCKER_DB_PORT_EXTERNAL}:3306" @@ -124,7 +124,7 @@ services: - ".env" volumes: - "${DOCKER_CONFIG_ROOT}/redis:/etc/redis" - - "${DOCKER_DATA_ROOT}/redis:/data" + - "${REDIS_DATA_PATH}:/data" ports: - "${DOCKER_REDIS_PORT_EXTERNAL}:6399" healthcheck: diff --git a/docker/shared/root/docker/entrypoint.d/12-migrations.sh b/docker/shared/root/docker/entrypoint.d/12-migrations.sh index b10e34c18..1fb49f393 100755 --- a/docker/shared/root/docker/entrypoint.d/12-migrations.sh +++ b/docker/shared/root/docker/entrypoint.d/12-migrations.sh @@ -7,7 +7,7 @@ source "${ENTRYPOINT_ROOT}/helpers.sh" entrypoint-set-script-name "$0" # Allow automatic applying of outstanding/new migrations on startup -: "${DOCKER_APPLY_NEW_MIGRATIONS_AUTOMATICALLY:=0}" +: "${DB_APPLY_NEW_MIGRATIONS_AUTOMATICALLY:=0}" # Wait for the database to be ready await-database-ready @@ -24,9 +24,9 @@ fi log-warning "New migrations available, will automatically apply them now" -if is-false "${DOCKER_APPLY_NEW_MIGRATIONS_AUTOMATICALLY}"; then +if is-false "${DB_APPLY_NEW_MIGRATIONS_AUTOMATICALLY}"; then log-info "Automatic applying of new database migrations is disabled" - log-info "Please set [DOCKER_APPLY_NEW_MIGRATIONS_AUTOMATICALLY=1] in your [.env] file to enable this." + log-info "Please set [DB_APPLY_NEW_MIGRATIONS_AUTOMATICALLY=1] in your [.env] file to enable this." exit 0 fi From de96c5f06d0c92393e7953547e6b1e678105fbe0 Mon Sep 17 00:00:00 2001 From: Christian Winther Date: Mon, 15 Jan 2024 23:50:16 +0000 Subject: [PATCH 064/173] migration docs --- .env.docker | 360 +++++++++++------- .markdownlint.json | 4 + Dockerfile | 2 +- docker-compose.migrate.yml | 42 ++ docker-compose.yml | 35 +- docker/README.md | 1 + docker/customizing.md | 6 +- docker/faq.md | 2 + docker/migration.md | 326 ++++++++++++++++ .../docker/entrypoint.d/01-permissions.sh | 6 +- 10 files changed, 627 insertions(+), 157 deletions(-) create mode 100644 .markdownlint.json create mode 100644 docker-compose.migrate.yml create mode 100644 docker/migration.md diff --git a/.env.docker b/.env.docker index 5dfd766bb..5f5152968 100644 --- a/.env.docker +++ b/.env.docker @@ -1,60 +1,24 @@ -# shellcheck disable=SC2034,SC2148 - # -*- mode: bash -*- # vi: ft=bash -############################################################### -# Docker-wide configuration -############################################################### +# shellcheck disable=SC2034,SC2148 -# Path (relative to the docker-compose.yml) or absolute (/some/other/path) file where containers will store their data -DOCKER_DATA_ROOT="./docker-compose/data" - -# Path (relative to the docker-compose.yml) or absolute (/some/other/path) file where containers will store their confguration -DOCKER_CONFIG_ROOT="./docker-compose/config" - -# Image to pull the Pixelfed Docker images from -# -# Possible values: -# - "ghcr.io/pixelfed/pixelfed" to pull from GitHub -# - "pixelfed/pixelfed" to pull from DockerHub -# -DOCKER_IMAGE="ghcr.io/jippi/pixelfed" - -# Pixelfed version (image tag) to pull from the registry. -# -# See: https://github.com/pixelfed/pixelfed/pkgs/container/pixelfed -DOCKER_TAG="branch-jippi-fork-apache-8.1" - -# Set timezone used by *all* containers - these should be in sync. -# -# See: https://www.php.net/manual/en/timezones.php -TZ="UTC" - -# Automatically run "One-time setup tasks" commands. -# -# If you are migrating to this docker-compose setup or have manually run the "One time seutp" -# tasks (https://docs.pixelfed.org/running-pixelfed/installation/#setting-up-services) -# you can set this to "0" to prevent them from running. -# -# Otherwise, leave it at "1" to have them run *once*. -DOCKER_RUN_ONE_TIME_SETUP_TASKS="1" - -# The e-mail to use for Lets Encrypt certificate requests. -LETSENCRYPT_EMAIL="__CHANGE_ME__" - -# Lets Encrypt staging/test servers for certificate requests. -# -# Setting this to any value will change to letsencrypt test servers. -#LETSENCRYPT_TEST="1" - -# Enable Docker Entrypoint debug mode (will call [set -x] in bash scripts) -# by setting this to "1". -#ENTRYPOINT_DEBUG="0" - -############################################################### +################################################################################ # Pixelfed application configuration -############################################################### +################################################################################ + +# The docker tag prefix to use for pulling images, can be one of +# +# * latest +# * +# * staging +# * edge +# * branch- +# * pr- +# +# Combined with [DOCKER_RUNTIME] and [PHP_VERSION] configured +# elsewhere in this file, the final Docker tag is computed. +PIXELFED_RELEASE="branch-jippi-fork" # A random 32-character string to be used as an encryption key. # @@ -80,7 +44,7 @@ APP_DOMAIN="__CHANGE_ME__" # You should set this to the root of your application so that it is used when running Artisan tasks. # # See: https://docs.pixelfed.org/technical-documentation/config/#app_url -APP_URL=https://${APP_DOMAIN} +APP_URL="https://${APP_DOMAIN}" # Application domains used for routing. # @@ -104,7 +68,7 @@ ADMIN_DOMAIN="${APP_DOMAIN}" # Enable/disable new local account registrations. # # See: https://docs.pixelfed.org/technical-documentation/config/#open_registration -#OPEN_REGISTRATION=true +#OPEN_REGISTRATION="true" # Require email verification before a new user can do anything. # @@ -130,11 +94,11 @@ OAUTH_ENABLED="true" # Defaults to "UTC". # -# Do not edit your timezone or things will break! +# ! Do not edit your timezone once the service is running - or things will break! # # See: https://docs.pixelfed.org/technical-documentation/config/#app_timezone # See: https://www.php.net/manual/en/timezones.php -APP_TIMEZONE="${TZ}" +APP_TIMEZONE="UTC" # The application locale determines the default locale that will be used by the translation service provider. # You are free to set this value to any of the locales which will be supported by the application. @@ -277,11 +241,27 @@ INSTANCE_CONTACT_EMAIL="admin@${APP_DOMAIN}" # See: https://docs.pixelfed.org/technical-documentation/config/#restricted_instance #RESTRICTED_INSTANCE="false" -############################################################### -# Database configuration -############################################################### +################################################################################ +# Lets Encrypt configuration +################################################################################ -# Here you may specify which of the database connections below you wish to use as your default connection for all database work. +# The host to request LetsEncrypt certificate for +LETSENCRYPT_HOST="${APP_DOMAIN}" + +# The e-mail to use for Lets Encrypt certificate requests. +LETSENCRYPT_EMAIL="__CHANGE_ME__" + +# Lets Encrypt staging/test servers for certificate requests. +# +# Setting this to any value will change to letsencrypt test servers. +#LETSENCRYPT_TEST="1" + +################################################################################ +# Database configuration +################################################################################ + +# Here you may specify which of the database connections below +# you wish to use as your default connection for all database work. # # Of course you may use many connections at once using the database library. # @@ -313,11 +293,11 @@ DB_DATABASE="pixelfed_prod" DB_PORT="3306" # Automatically run [artisan migrate --force] if new migrations are detected. -DB_APPLY_NEW_MIGRATIONS_AUTOMATICALLY="0" +DB_APPLY_NEW_MIGRATIONS_AUTOMATICALLY="false" -############################################################### +################################################################################ # Mail configuration -############################################################### +################################################################################ # Laravel supports both SMTP and PHP’s “mail” function as drivers for the sending of e-mail. # You may specify which one you’re using throughout your application here. @@ -392,9 +372,9 @@ MAIL_FROM_NAME="Pixelfed @ ${APP_DOMAIN}" # See: https://docs.pixelfed.org/technical-documentation/config/#mail_encryption #MAIL_ENCRYPTION="tls" -############################################################### +################################################################################ # Redis configuration -############################################################### +################################################################################ # Defaults to "phpredis". # @@ -419,16 +399,16 @@ REDIS_HOST="redis" # Defaults to 6379. # # See: https://docs.pixelfed.org/technical-documentation/config/#redis_port -REDIS_PORT="6379" +#REDIS_PORT="6379" # Defaults to 0. # # See: https://docs.pixelfed.org/technical-documentation/config/#redis_database #REDIS_DATABASE="0" -############################################################### +################################################################################ # Cache settings -############################################################### +################################################################################ # This option controls the default cache connection that gets used while using this caching library. # @@ -448,11 +428,11 @@ CACHE_DRIVER="redis" # Defaults to ${APP_NAME}_cache, or laravel_cache if no APP_NAME is set. # # See: https://docs.pixelfed.org/technical-documentation/config/#cache_prefix -# CACHE_PREFIX="{APP_NAME}_cache" +#CACHE_PREFIX="{APP_NAME}_cache" -############################################################### +################################################################################ # Horizon settings -############################################################### +################################################################################ # This prefix will be used when storing all Horizon data in Redis. # @@ -498,9 +478,9 @@ CACHE_DRIVER="redis" # See: https://docs.pixelfed.org/technical-documentation/config/#horizon_supervisor_timeout #HORIZON_SUPERVISOR_TIMEOUT="300" -############################################################### +################################################################################ # Experiments -############################################################### +################################################################################ # Text only posts (alpha). # @@ -523,16 +503,16 @@ CACHE_DRIVER="redis" # See: https://docs.pixelfed.org/technical-documentation/config/#exp_cpt #EXP_CPT="false" -# Enforce Mastoapi Compatibility (alpha). +# Enforce Mastodon API Compatibility (alpha). # # Defaults to "true". # # See: https://docs.pixelfed.org/technical-documentation/config/#exp_emc -EXP_EMC="true" +#EXP_EMC="true" -############################################################### +################################################################################ # ActivityPub confguration -############################################################### +################################################################################ # Defaults to "false". # @@ -559,9 +539,9 @@ ACTIVITY_PUB="true" # See: https://docs.pixelfed.org/technical-documentation/config/#ap_outbox #AP_OUTBOX="true" -############################################################### +################################################################################ # Federation confguration -############################################################### +################################################################################ # Defaults to "true". # @@ -578,9 +558,9 @@ ACTIVITY_PUB="true" # See: https://docs.pixelfed.org/technical-documentation/config/#webfinger #WEBFINGER="true" -############################################################### +################################################################################ # Storage (cloud) -############################################################### +################################################################################ # Store media on object storage like S3, Digital Ocean Spaces, Rackspace # @@ -604,9 +584,9 @@ ACTIVITY_PUB="true" # See: https://docs.pixelfed.org/technical-documentation/config/#media_delete_local_after_cloud #MEDIA_DELETE_LOCAL_AFTER_CLOUD="true" -############################################################### +################################################################################ # Storage (cloud) - S3 andS S3 *compatible* providers (most of them) -############################################################### +################################################################################ # See: https://docs.pixelfed.org/technical-documentation/config/#aws_access_key_id #AWS_ACCESS_KEY_ID= @@ -765,10 +745,10 @@ LOG_CHANNEL="stderr" BROADCAST_DRIVER="redis" ############################################################### -# Other settings +# Sanitizing settings ############################################################### -# Defaults to true. +# Defaults to "true". # # See: https://docs.pixelfed.org/technical-documentation/config/#restrict_html_types #RESTRICT_HTML_TYPES="true" @@ -898,52 +878,122 @@ TRUST_PROXIES="*" # PHP configuration ############################################################### +# The PHP version to use for [web] and [worker] container +# +# Any version published on https://hub.docker.com/_/php should work +# +# Example: +# +# * 8.1 +# * 8.2 +# * 8.2.14 +# * latest +# +# Do *NOT* use the full Docker tag (e.g. "8.3.2RC1-fpm-bullseye") +# *only* the version part. The rest of the full tag is derived from +# the [DOCKER_RUNTIME] and [PHP_DEBIAN_RELEASE] settings +PHP_VERSION="8.1" + # See: https://www.php.net/manual/en/ini.core.php#ini.memory-limit #PHP_MEMORY_LIMIT="128M" -############################################################### -# MySQL DB container configuration (DO NOT CHANGE) -############################################################### +# The Debian release variant to use of the [php] Docker image +#PHP_DEBIAN_RELEASE="bullseye" + +# The [php] Docker image base type # -# See "Environment Variables" at https://hub.docker.com/_/mysql +# See: https://github.com/pixelfed/pixelfed/blob/dev/docker/runtimes.md +#PHP_BASE_TYPE="apache" -MYSQL_ROOT_PASSWORD="${DB_PASSWORD}" -MYSQL_USER="${DB_USERNAME}" -MYSQL_PASSWORD="${DB_PASSWORD}" -MYSQL_DATABASE="${DB_DATABASE}" - -############################################################### -# MySQL (MariaDB) DB container configuration (DO NOT CHANGE) -############################################################### +# List of extra APT packages (separated by space) to install when building +# locally using [docker compose build]. # -# See "Start a mariadb server instance with user, password and database" at https://hub.docker.com/_/mariadb +# See: https://github.com/pixelfed/pixelfed/blob/dev/docker/customizing.md +#APT_PACKAGES_EXTRA="" -MARIADB_ROOT_PASSWORD="${DB_PASSWORD}" -MARIADB_USER="${DB_USERNAME}" -MARIADB_PASSWORD="${DB_PASSWORD}" -MARIADB_DATABASE="${DB_DATABASE}" - -############################################################### -# PostgreSQL DB container configuration (DO NOT CHANGE) -############################################################### +# List of *extra* PECL extensions (separated by space) to install when +# building locally using [docker compose build]. # -# See "Environment Variables" at https://hub.docker.com/_/postgres +# See: https://github.com/pixelfed/pixelfed/blob/dev/docker/customizing.md +#PHP_PECL_EXTENSIONS_EXTRA="" -POSTGRES_USER="${DB_USERNAME}" -POSTGRES_PASSWORD="${DB_PASSWORD}" -POSTGRES_DB="${DB_DATABASE}" +# List of *extra* PHP extensions (separated by space) to install when +# building locally using [docker compose build]. +# +# See: https://github.com/pixelfed/pixelfed/blob/dev/docker/customizing.md +#PHP_EXTENSIONS_EXTRA="" -############################################################### -# Lets Encrypt configuration -############################################################### +################################################################################ +# Other configuration +################################################################################ -LETSENCRYPT_HOST="${APP_DOMAIN}" +# ? Add your own configuration here -############################################################### +################################################################################ +# Timezone configuration +################################################################################ + +# Set timezone used by *all* containers - these must be in sync. +# +# ! Do not edit your timezone once the service is running - or things will break! +# +# See: https://www.php.net/manual/en/timezones.php +TZ="${APP_TIMEZONE}" + +################################################################################ # Docker Specific configuration -############################################################### +################################################################################ + +# Image to pull the Pixelfed Docker images from. +# +# Example values: +# +# * "ghcr.io/pixelfed/pixelfed" to pull from GitHub +# * "pixelfed/pixelfed" to pull from DockerHub +# * "your/fork" to pull from a custom fork +# +DOCKER_IMAGE="ghcr.io/jippi/pixelfed" + +# The container runtime to use. +# +# See: https://github.com/jippi/pixelfed/blob/jippi-fork/docker/runtimes.md +DOCKER_RUNTIME="apache" + +# Pixelfed version (image tag) to pull from the registry. +# +# See: https://github.com/pixelfed/pixelfed/pkgs/container/pixelfed +DOCKER_TAG="${PIXELFED_RELEASE}-${DOCKER_RUNTIME}-${PHP_VERSION}" + +# Path (relative to the docker-compose.yml) or absolute (/some/other/path) where containers will store their data +DOCKER_DATA_ROOT="./docker-compose-state/data" + +# Path (relative to the docker-compose.yml) or absolute (/some/other/path) where containers will store their confguration +DOCKER_CONFIG_ROOT="./docker-compose-state/config" + +# Path (on host system) where the [db] container will store its data +# +# Path is relative (./some/other/path) to the docker-compose.yml or absolute (/some/other/path) +DOCKER_DB_DATA_PATH="${DOCKER_DATA_ROOT}/db" + +# Path (on host system) where the [redis] container will store its data +# +# Path is relative (./some/other/path) to the docker-compose.yml or absolute (/some/other/path) +DOCKER_REDIS_DATA_PATH="${DOCKER_DATA_ROOT}/redis" + +# Path (on host system) where the [app] + [worker] container will write +# its [storage] data (e.g uploads/images/profile pictures etc.). +# +# Path is relative (./some/other/path) to the docker-compose.yml or absolute (/some/other/path) +DOCKER_APP_STORAGE_PATH="${DOCKER_DATA_ROOT}/pixelfed/storage" + +# Path (on host system) where the [app] + [worker] container will write +# its [cache] data. +# +# Path is relative (./some/other/path) to the docker-compose.yml or absolute (/some/other/path) +DOCKER_APP_CACHE_PATH="${DOCKER_DATA_ROOT}/pixelfed/cache" + # Port that Redis will listen on *outside* the container (e.g. the host machine) -DOCKER_REDIS_PORT_EXTERNAL="${REDIS_PORT}" +DOCKER_REDIS_PORT_EXTERNAL="${REDIS_PORT:-6379}" # Port that the database will listen on *outside* the container (e.g. the host machine) # @@ -971,30 +1021,64 @@ DOCKER_PROXY_PROFILE="" # Set this to a non-empty value (e.g. "disabled") to disable the [proxy-acme] service DOCKER_PROXY_ACME_PROFILE="${DOCKER_PROXY_PROFILE}" -# Path (relative to the docker-compose.yml) or absolute (/some/other/path) where containers will store their data -DOCKER_DATA_ROOT="./docker-compose-state/data" - -# Path (relative to the docker-compose.yml) or absolute (/some/other/path) where containers will store their confguration -DOCKER_CONFIG_ROOT="./docker-compose-state/config" - -# Path (on host system) where the [db] container will store its data +# Automatically run "One-time setup tasks" commands. # -# Path is relative (./some/other/path) to the docker-compose.yml or absolute (/some/other/path) -DB_DATA_PATH="${DOCKER_DATA_ROOT}/db" - -# Path (on host system) where the [redis] container will store its data +# If you are migrating to this docker-compose setup or have manually run the "One time seutp" +# tasks (https://docs.pixelfed.org/running-pixelfed/installation/#setting-up-services) +# you can set this to "0" to prevent them from running. # -# Path is relative (./some/other/path) to the docker-compose.yml or absolute (/some/other/path) -REDIS_DATA_PATH="${DOCKER_DATA_ROOT}/redis" +# Otherwise, leave it at "1" to have them run *once*. +#DOCKER_RUN_ONE_TIME_SETUP_TASKS="1" -# Path (on host system) where the [app] + [worker] container will write -# its [storage] data (e.g uploads/images/profile pictures etc.). +# A space-seperated list of paths (inside the container) to *recursively* [chown] +# to the container user/group id (UID/GID) in case of permission issues. # -# Path is relative (./some/other/path) to the docker-compose.yml or absolute (/some/other/path) -APP_STORAGE_PATH="${DOCKER_DATA_ROOT}/pixelfed/storage" +# ! You should *not* leave this on permanently, at it can significantly slow down startup +# ! time for the container, and during normal operations there should never be permission +# ! issues. Please report a bug if you see behavior requiring this to be permanently on +# +# Example: "/var/www/storage /var/www/bootstrap/cache" +#DOCKER_ENSURE_OWNERSHIP_PATHS="" -# Path (on host system) where the [app] + [worker] container will write -# its [cache] data. +# Enable Docker Entrypoint debug mode (will call [set -x] in bash scripts) +# by setting this to "1". +#ENTRYPOINT_DEBUG="0" + +################################################################################ +# MySQL DB container configuration +################################################################################ # -# Path is relative (./some/other/path) to the docker-compose.yml or absolute (/some/other/path) -APP_CACHE_PATH="${DOCKER_DATA_ROOT}/pixelfed/cache" +# See "Environment Variables" at https://hub.docker.com/_/mysql +# +# ! DO NOT CHANGE unless you know what you are doing + +MYSQL_ROOT_PASSWORD="${DB_PASSWORD}" +MYSQL_USER="${DB_USERNAME}" +MYSQL_PASSWORD="${DB_PASSWORD}" +MYSQL_DATABASE="${DB_DATABASE}" + +################################################################################ +# MySQL (MariaDB) DB container configuration +################################################################################ +# +# See "Start a mariadb server instance with user, password and database" +# at https://hub.docker.com/_/mariadb +# +# ! DO NOT CHANGE unless you know what you are doing + +MARIADB_ROOT_PASSWORD="${DB_PASSWORD}" +MARIADB_USER="${DB_USERNAME}" +MARIADB_PASSWORD="${DB_PASSWORD}" +MARIADB_DATABASE="${DB_DATABASE}" + +################################################################################ +# PostgreSQL DB container configuration +################################################################################ +# +# See "Environment Variables" at https://hub.docker.com/_/postgres +# +# ! DO NOT CHANGE unless you know what you are doing + +POSTGRES_USER="${DB_USERNAME}" +POSTGRES_PASSWORD="${DB_PASSWORD}" +POSTGRES_DB="${DB_DATABASE}" diff --git a/.markdownlint.json b/.markdownlint.json new file mode 100644 index 000000000..cf98a0902 --- /dev/null +++ b/.markdownlint.json @@ -0,0 +1,4 @@ +{ + "MD013": false, + "MD014": false +} diff --git a/Dockerfile b/Dockerfile index 6151d8758..3d12aba26 100644 --- a/Dockerfile +++ b/Dockerfile @@ -37,7 +37,7 @@ ARG RUNTIME_UID=33 # often called 'www-data' ARG RUNTIME_GID=33 # often called 'www-data' # APT extra packages -ARG APT_PACKAGES_EXTRA="" +ARG APT_PACKAGES_EXTRA= # Extensions installed via [pecl install] ARG PHP_PECL_EXTENSIONS= diff --git a/docker-compose.migrate.yml b/docker-compose.migrate.yml new file mode 100644 index 000000000..b47abeb48 --- /dev/null +++ b/docker-compose.migrate.yml @@ -0,0 +1,42 @@ +--- +version: "3" + +services: + migrate: + image: "secoresearch/rsync" + entrypoint: "" + working_dir: /migrate + command: 'bash -c "exit 1"' + restart: never + volumes: + ################################ + # Storage volume + ################################ + # OLD + - "app-storage:/migrate/app-storage/old" + # NEW + - "${DOCKER_APP_STORAGE_PATH}:/migrate/app-storage/new" + + ################################ + # MySQL/DB volume + ################################ + # OLD + - "db-data:/migrate/db-data/old" + # NEW + - "${DOCKER_DB_DATA_PATH}:/migrate/db-data/new" + + ################################ + # Redis volume + ################################ + # OLD + - "redis-data:/migrate/redis-data/old" + # NEW + - "${DOCKER_REDIS_DATA_PATH}:/migrate/redis-data/new" + +# Volumes from the old [docker-compose.yml] file +# https://github.com/pixelfed/pixelfed/blob/b1ff44ca2f75c088a11576fb03b5bad2fbed4d5c/docker-compose.yml#L72-L76 +volumes: + db-data: + redis-data: + app-storage: + app-bootstrap: diff --git a/docker-compose.yml b/docker-compose.yml index 614d3954a..76aebf609 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -65,15 +65,22 @@ services: container_name: "${DOCKER_CONTAINER_NAME_PREFIX}-web" restart: unless-stopped build: - target: apache-runtime + target: ${DOCKER_RUNTIME}-runtime + args: + PHP_VERSION: "${PHP_VERSION:-8.1}" + PHP_BASE_TYPE: "${PHP_BASE_TYPE:-apache}" + PHP_DEBIAN_RELEASE: "${PHP_DEBIAN_RELEASE:-bullseye}" + APT_PACKAGES_EXTRA: "${APT_PACKAGES_EXTRA:-}" + PHP_PECL_EXTENSIONS_EXTRA: "${PHP_PECL_EXTENSIONS_EXTRA:-}" + PHP_EXTENSIONS_EXTRA: "${PHP_EXTENSIONS_EXTRA:-}" volumes: - "./.env:/var/www/.env" - - "${APP_CACHE_PATH}:/var/www/bootstrap/cache" - - "${APP_STORAGE_PATH}:/var/www/storage" + - "${DOCKER_APP_CACHE_PATH}:/var/www/bootstrap/cache" + - "${DOCKER_APP_STORAGE_PATH}:/var/www/storage" environment: LETSENCRYPT_HOST: "${LETSENCRYPT_HOST}" LETSENCRYPT_EMAIL: "${LETSENCRYPT_EMAIL}" - LETSENCRYPT_TEST: "${LETSENCRYPT_TEST}" + LETSENCRYPT_TEST: "${LETSENCRYPT_TEST:-}" VIRTUAL_HOST: "${APP_DOMAIN}" VIRTUAL_PORT: "80" labels: @@ -91,15 +98,19 @@ services: container_name: "${DOCKER_CONTAINER_NAME_PREFIX}-worker" command: gosu www-data php artisan horizon restart: unless-stopped - deploy: - mode: replicated - replicas: 1 build: - target: apache-runtime + target: ${DOCKER_RUNTIME}-runtime + args: + PHP_VERSION: "${PHP_VERSION:-8.1}" + PHP_BASE_TYPE: "${PHP_BASE_TYPE:-apache}" + PHP_DEBIAN_RELEASE: "${PHP_DEBIAN_RELEASE:-bullseye}" + APT_PACKAGES_EXTRA: "${APT_PACKAGES_EXTRA:-}" + PHP_PECL_EXTENSIONS_EXTRA: "${PHP_PECL_EXTENSIONS_EXTRA:-}" + PHP_EXTENSIONS_EXTRA: "${PHP_EXTENSIONS_EXTRA:-}" volumes: - "./.env:/var/www/.env" - - "${APP_CACHE_PATH}:/var/www/bootstrap/cache" - - "${APP_STORAGE_PATH}:/var/www/storage" + - "${DOCKER_APP_CACHE_PATH}:/var/www/bootstrap/cache" + - "${DOCKER_APP_STORAGE_PATH}:/var/www/storage" depends_on: - db - redis @@ -112,7 +123,7 @@ services: env_file: - ".env" volumes: - - "${DB_DATA_PATH}:/var/lib/mysql" + - "${DOCKER_DB_DATA_PATH}:/var/lib/mysql" ports: - "${DOCKER_DB_PORT_EXTERNAL}:3306" @@ -124,7 +135,7 @@ services: - ".env" volumes: - "${DOCKER_CONFIG_ROOT}/redis:/etc/redis" - - "${REDIS_DATA_PATH}:/data" + - "${DOCKER_REDIS_DATA_PATH}:/data" ports: - "${DOCKER_REDIS_PORT_EXTERNAL}:6399" healthcheck: diff --git a/docker/README.md b/docker/README.md index ea1870fd3..bf73662a8 100644 --- a/docker/README.md +++ b/docker/README.md @@ -1,6 +1,7 @@ # Pixelfed + Docker + Docker Compose * [Setting up a new Pixelfed server with Docker Compose](new-server.md) +* [Migrating to the new `docker-compose.yml` setup](migration.md) * [Frequently Asked Question / FAQ](faq.md) * [How do I use my own Proxy server?](faq.md#how-do-i-use-my-own-proxy-server) * [How do I use my own SSL certificate?](faq.md#how-do-i-use-my-own-ssl-certificate) diff --git a/docker/customizing.md b/docker/customizing.md index 8dfc534dc..dcea45d3d 100644 --- a/docker/customizing.md +++ b/docker/customizing.md @@ -73,12 +73,12 @@ Please see the ## Fixing ownership on startup -You can set the environment variable `ENTRYPOINT_ENSURE_OWNERSHIP_PATHS` to a list of paths that should have their `$USER` and `$GROUP` ownership changed to the configured runtime user and group during container bootstrapping. +You can set the environment variable `DOCKER_ENSURE_OWNERSHIP_PATHS` to a list of paths that should have their `$USER` and `$GROUP` ownership changed to the configured runtime user and group during container bootstrapping. The variable is a space-delimited list shown below and accepts both relative and absolute paths: -* `ENTRYPOINT_ENSURE_OWNERSHIP_PATHS="./storage ./bootstrap"` -* `ENTRYPOINT_ENSURE_OWNERSHIP_PATHS="/some/other/folder"` +* `DOCKER_ENSURE_OWNERSHIP_PATHS="./storage ./bootstrap"` +* `DOCKER_ENSURE_OWNERSHIP_PATHS="/some/other/folder"` ## Build settings (arguments) diff --git a/docker/faq.md b/docker/faq.md index 3988be578..cc2495d15 100644 --- a/docker/faq.md +++ b/docker/faq.md @@ -10,6 +10,7 @@ No problem! All you have to do is: 1. Point your proxy upstream to the exposed `web` port (**Default**: `8080`). * The port is controlled by the `DOCKER_WEB_PORT_EXTERNAL_HTTP` key in `.env`. * The setting is near the bottom of the file. +1. Run `docker compose up -d --remove-orphans` to apply the configuration ## How do I use my own SSL certificate? @@ -26,6 +27,7 @@ No problem! All you have to do is: 1. `${APP_DOMAIN}.fullchain.pem` 1. `${APP_DOMAIN}.key.pem` * See the [`nginx-proxy` configuration file for name patterns](https://github.com/nginx-proxy/nginx-proxy/blob/main/nginx.tmpl#L659-L670) +1. Run `docker compose up -d --remove-orphans` to apply the configuration ## How do I change the container name prefix? diff --git a/docker/migration.md b/docker/migration.md new file mode 100644 index 000000000..76fb0904c --- /dev/null +++ b/docker/migration.md @@ -0,0 +1,326 @@ +# Migrating to the new Pixelfed Docker setup + +There is [*a lot* of changes](https://github.com/pixelfed/pixelfed/pull/4844) in how Pixelfed Docker/Docker Compose images work - it's a complete rewrite - with a bunch of breaking changes. + +## No more anonymous Docker Compose volumes + +The old `docker-compose.yml` configuration file [declared four anonymous volumes](https://github.com/pixelfed/pixelfed/blob/b1ff44ca2f75c088a11576fb03b5bad2fbed4d5c/docker-compose.yml#L72-L76) for storing Pixelfed related data within. + +These are no longer used, instead favoring a [Docker bind volume](https://docs.docker.com/storage/bind-mounts/) approach where content are stored directly on the server disk, outside +of a Docker volume. + +The consequence of this change is that *all* data stored in the - now unsupported - Docker volumes will no longer be accessible by Pixelfed. + +* The `db-data` volume *definitely* contain important data - it's your database after all! +* The `app-storage` volume *definitely* contain important data - it's files uploaded to - or seen by - your server! +* The `redis-data` volume *might* contain important data (depending on your configuration) +* The `app-bootstrap` volume does not contain any important data - all of it will be generated automatically in the new setup on startup. We will *not* be migrating this! + +### Migrating off anonymous Docker Compose volumes + +#### Caveats and warnings + +**NOTE**: This is a best-effort guide to help migrate off the old system, the operation is potentially rather complicated (and risky), so please do be careful! + +***PLEASE MAKE SURE TO BACKUP YOUR SERVER AND DATA BEFORE ATTEMPTING A MIGRATION*** + +We provide a "migration container" for your convenience that can access both the new and old volumes, allowing you to copy the data into the setup. + +**It's important to note that this is a *copy* operation - so disk usage will (temporarily) double while you migrate** + +**YOUR INSTANCE WILL BE *DOWN* WHILE DOING THE MIGRATION, PLEASE PLAN ACCORDINGLY, DEPENDING ON DATA SIZE IT COULD TAKE ANYWHERE FROM 5 *MINUTES* TO 5 *HOURS*** + +#### 0. Backup, rollout, and rollback plan + +1. Make sure to backup your server (ideally *after* step 1 below has completed, but *before* is better than not at all!) +1. Capture the current Git version / Pixelfed release you are on (e.g. `git --no-pager log -1` outputs the commit reference as the 2nd word in first line) +1. Backup your `.env` file (we will do this in step 3 as well) +1. Backup your `docker-compose.yml` file (`cp docker-compose.yml docker-compose.yml.old`) +1. Read through the *entire* document before starting + +#### 1. Migrate your ".env" file + +The new `.env` file for Docker is a bit different from the old one (many new settings!) so the easiest is to grab the new `.env.docker` file and modify it from scratch again. + +```shell +$ cp .env .env.old +$ wget -O .env.new https://raw.githubusercontent.com/pixelfed/pixelfed/dev/.env.docker +``` + +Then open your old `.env.old` configuration file, and for each of the key/value pairs within it, find and update the key in the new `.env.new` configuration file. + +Don't worry though, the file might *look* different (and significantly larger) but it behaves *exactly* the way the old file did, it just has way more options! + +If a key is missing in `.env.new`, don't worry, you can just add those key/value pairs back to the new file - ideally in the `Other configuration` section near the end of the file - but anywhere *should* be fine. + +This is a great time to review your settings and familiarize you with all the new settings. + +In *particular* the following sections and the [Frequently Asked Question / FAQ](faq.md) + +* `PHP configuration` section (near the end of the file) where + * The `PHP_VERSION` settings controls your PHP version + * The `PHP_MEMORY_LIMIT` settings controls your PHP memory limit +* `Docker Specific configuration` section (near the end of the file) where + * The `DOCKER_DATA_ROOT` setting dictate where the new migrated data will live. + * The `DOCKER_RUN_ONE_TIME_SETUP_TASKS` controls if the `One time setup tasks` should run or not. We do *not* want this, since your Pixelfed instance already is set up! + +#### 2. Stop all running containers + +Stop *all* running containers (web, worker, redis, db) + +```shell +$ docker compose down +``` + +#### 3. Pull down the new source code + +Update your project to the latest release of Pixelfed by running + +```shell +$ git pull origin $release +``` + +Where `$release` is either `dev`, `staging` or a [tagged release](https://github.com/pixelfed/pixelfed/releases) such as `v0.12.0`. + +#### 4. Run the migration container + +You can access the Docker container with both old and new volumes by running the following command + +```shell +$ docker compose -f docker-compose.migrate.yml run migrate bash +``` + +This will put you in the `/migrate` directory within the container, containing 8 directories like shown here + +```plain +|-- app-storage +| |-- new +| `-- old +|-- db-data +| |-- new +| `-- old +`-- redis-data + |-- new + `-- old +``` + +#### 5. Check the folders + +##### Old folders + +The following commands should all return *SOME* files and data - if they do not - then there might be an issue with the anonymous volume binding. + +```shell +$ ls app-storage/old +$ ls db-data/old +$ ls redis-data/old +``` + +##### New folders + +The following commands should all return *NO* files and data - if they contain data - you need to either delete it (backup first!) or skip that migration step. + +If you haven't run `docker compose up` since you updated your project in step (2) - they should be empty and good to go. + +```shell +$ ls app-storage/new +$ ls db-data/new +$ ls redis-data/new +``` + +#### 6. Copy the data + +Now we will copy the data from the old volumes, to the new ones. + +The migration container has [`rsync`](https://www.digitalocean.com/community/tutorials/how-to-use-rsync-to-sync-local-and-remote-directories) installed - which is perfect for that kind of work! + +**NOTE** It's important that the "source" (first path in the `rsync` command) has a trailing `/` - otherwise the directory layout will turn out wrong! + +**NOTE** Depending on your server, these commands might take some time to finish, each command should provide a progress bar with rough time estimation. + +**NOTE** `rsync` should preserve ownership, permissions, and symlinks correctly for you as well for all the files copied. + +Lets copy the data by running the following commands: + +```shell +$ rsync -avP app-storage/old/ app-storage/new +$ rsync -avP db-data/old/ db-data/new +$ rsync -avP redis-data/old/ redis-data/new +``` + +#### 7. Sanity checking + +Lets make sure everything copied over successfully! + +Each *new* directory should contain *something* like (but not always exactly) the following - **NO** directory should have a single folder called `old`, if they do, the `rsync` commands above didn't work correctly - and you need to move the content of the `old` folder into the "root" of the `new` folder like shown a bit in the following sections. + +The **redis-data/new** directory might also contain a `server.pid` + +```shell +$ ls redis-data/new +appendonlydir +``` + +The **app-storage/new** directory should look *something* like this + +```shell +$ ls app-storage/new +app debugbar docker framework logs oauth-private.key oauth-public.key purify +``` + +The **db-data/new** directory should look *something* like this. There might be a lot of files, or very few files, but there *must* be a `mysql`, `performance_schema`, and `${DB_DATABASE}` (e.g. `pixelfed_prod` directory) + +```shell +$ ls db-data/new +aria_log_control ddl_recovery-backup.log ib_buffer_pool ib_logfile0 ibdata1 mariadb_upgrade_info multi-master.info mysql performance_schema pixelfed_prod sys undo001 undo002 undo003 +``` + +If everything looks good, type `exit` to leave exit the migration container + +#### 6. Starting up the your Pixelfed server again + +With all an updated Pixelfed (step 2), updated `.env` file (step 3), migrated data (step 4, 5, 6 and 7) we're ready to start things back up again. + +But before we start your Pixelfed server back up again, lets put the new `.env` file we made in step 1 in its right place. + +```shell +$ cp .env.new .env +``` + +##### The Database + +First thing we want to try is to start up the database by running the following command and checking the logs + +```shell +$ docker compose up -d db +$ docker compose logs --tail 250 --follow db +``` + +if there are no errors and the server isn't crashing, great! If you have an easy way of connecting to the Database via a GUI or CLI client, do that as well and verify the database and tables are all there. + +##### Redis + +Next thing we want to try is to start up the Redis server by running the following command and checking the logs + +```shell +$ docker compose up -d redis +$ docker compose logs --tail 250 --follow redis +``` + +if there are no errors and the server isn't crashing, great! + +##### Worker + +Next thing we want to try is to start up the Worker server by running the following command and checking the logs + +```shell +$ docker compose up -d worker +$ docker compose logs --tail 250 --follow worker +``` + +The container should output a *lot* of logs from the [docker-entrypoint system](customizing.md#running-commands-on-container-start), but *eventually* you should see these messages + +* `Configuration complete; ready for start up` +* `Horizon started successfully.` + +If you see one or both of those messages, great, the worker seems to be running. + +If the worker is crash looping, inspect the logs and try to resolve the issues. + +You can consider the following additional steps: + +* Enabling `ENTRYPOINT_DEBUG` which will show even more log output to help understand whats going on +* Enabling `DOCKER_ENSURE_OWNERSHIP_PATHS` against the path(s) that might have permission issues +* Fixing permission issues directly on the host since your data should all be in the `${DOCKER_DATA_ROOT}` folder (`./docker-compose-state/data` by default) + +##### Web + +The final service, `web`, which will bring your site back online! What a journey it has been. + +Lets get to it, run these commands to start the `web` service and inspect the logs. + +```shell +$ docker compose up -d web +$ docker compose logs --tail 250 --follow web +``` + +The output should be pretty much identical to that of the `worker`, so please see that section for debugging tips if the container is crash looping. + +If the `web` service came online without issues, start the rest of the (optional) services, such as the `proxy`, if enabled, by running + +```shell +$ docker compose up -d +$ docker compose logs --tail 250 --follow +``` + +If you changed anything in the `.env` file while debugging, some containers might restart now, thats perfectly fine. + +#### 7. Verify + +With all services online, it's time to go to your browser and check everything is working + +1. Upload and post a picture +1. Comment on a post +1. Like a post +1. Check Horizon (`https://${APP_DOMAIN}/horizon`) for any errors +1. Check the Docker compose logs via `docker compose logs --follow` + +If everything looks fine, yay, you made it to the end! Lets do some cleanup + +#### 8. Final steps + cleanup + +With everything working, please take a new snapshot/backup of your server *before* we do any cleanup. A post-migration snapshot is incredibly useful, since it contains both the old and new configuration + data, making any recovery much easier in a rollback scenario later. + +Now, with all the data in the new folders, you can delete the old Docker Container volumes (if you want, completely optional) + +List all volumes, and give them a look: + +```shell +$ docker volume ls +``` + +The volumes we want to delete *ends* with the volume name (`db-data`, `app-storage`, `redis-data`, and `app-bootstrap`.) but has some prefix in front of them. + +Once you have found the volumes in in the list, delete each of them by running: + +```shell +$ docker volume rm $volume_name_in_column_two_of_the_output +``` + +You can also delete the `docker-compose.yml.old` and `.env.old` file since they are no longer needed + +```shell +$ rm docker-compose.yml.old +$ rm .env.old +``` + +### Rollback + +Oh no, something went wrong? No worries, we you got backups and a quick way back! + +#### Move `docker-compose.yml` back + +```shell +$ cp docker-compose.yml docker-compose.yml.new +$ cp docker-compose.yml.old docker-compose.yml +``` + +#### Move `.env` file back + +```shell +$ cp env.old .env +``` + +#### Go back to old source code version + +```shell +$ git checkout $commit_id_from_step_0 +``` + +#### Start things back up + +```shell +docker compose up -d +``` + +#### Verify it worked diff --git a/docker/shared/root/docker/entrypoint.d/01-permissions.sh b/docker/shared/root/docker/entrypoint.d/01-permissions.sh index 58b2f0bb8..287d708aa 100755 --- a/docker/shared/root/docker/entrypoint.d/01-permissions.sh +++ b/docker/shared/root/docker/entrypoint.d/01-permissions.sh @@ -13,13 +13,13 @@ run-as-current-user chown --verbose "${RUNTIME_UID}:${RUNTIME_GID}" "./bootstrap run-as-current-user chown --verbose "${RUNTIME_UID}:${RUNTIME_GID}" "./storage" # Optionally fix ownership of configured paths -: "${ENTRYPOINT_ENSURE_OWNERSHIP_PATHS:=""}" +: "${DOCKER_ENSURE_OWNERSHIP_PATHS:=""}" declare -a ensure_ownership_paths=() -IFS=' ' read -ar ensure_ownership_paths <<<"${ENTRYPOINT_ENSURE_OWNERSHIP_PATHS}" +IFS=' ' read -ar ensure_ownership_paths <<<"${DOCKER_ENSURE_OWNERSHIP_PATHS}" if [[ ${#ensure_ownership_paths[@]} == 0 ]]; then - log-info "No paths has been configured for ownership fixes via [\$ENTRYPOINT_ENSURE_OWNERSHIP_PATHS]." + log-info "No paths has been configured for ownership fixes via [\$DOCKER_ENSURE_OWNERSHIP_PATHS]." exit 0 fi From daba285ea75724e7fe256048833cde3c4e24aa2a Mon Sep 17 00:00:00 2001 From: Christian Winther Date: Mon, 15 Jan 2024 23:54:41 +0000 Subject: [PATCH 065/173] tune-up --- docker/migration.md | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/docker/migration.md b/docker/migration.md index 76fb0904c..4b0467ddd 100644 --- a/docker/migration.md +++ b/docker/migration.md @@ -55,7 +55,7 @@ If a key is missing in `.env.new`, don't worry, you can just add those key/value This is a great time to review your settings and familiarize you with all the new settings. -In *particular* the following sections and the [Frequently Asked Question / FAQ](faq.md) +In *particular* the following sections * `PHP configuration` section (near the end of the file) where * The `PHP_VERSION` settings controls your PHP version @@ -63,6 +63,9 @@ In *particular* the following sections and the [Frequently Asked Question / FAQ] * `Docker Specific configuration` section (near the end of the file) where * The `DOCKER_DATA_ROOT` setting dictate where the new migrated data will live. * The `DOCKER_RUN_ONE_TIME_SETUP_TASKS` controls if the `One time setup tasks` should run or not. We do *not* want this, since your Pixelfed instance already is set up! +* [Frequently Asked Question / FAQ](faq.md) + * [How do I use my own Proxy server?](faq.md#how-do-i-use-my-own-proxy-server) + * [How do I use my own SSL certificate?](faq.md#how-do-i-use-my-own-ssl-certificate) #### 2. Stop all running containers From 88ad5d6a4f25094562775fad4bdc3f33ea47e2eb Mon Sep 17 00:00:00 2001 From: Christian Winther Date: Tue, 16 Jan 2024 20:51:37 +0000 Subject: [PATCH 066/173] ignore some shellchecks for .env files --- .env.example | 2 ++ .env.testing | 6 ++++-- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/.env.example b/.env.example index d4d7228d1..0a24d1dc1 100644 --- a/.env.example +++ b/.env.example @@ -1,3 +1,5 @@ +# shellcheck disable=SC2034,SC2148 + APP_NAME="Pixelfed" APP_ENV="production" APP_KEY= diff --git a/.env.testing b/.env.testing index 258d8d740..63209d91b 100644 --- a/.env.testing +++ b/.env.testing @@ -1,3 +1,5 @@ +# shellcheck disable=SC2034,SC2148 + APP_NAME="Pixelfed Test" APP_ENV=local APP_KEY=base64:lwX95GbNWX3XsucdMe0XwtOKECta3h/B+p9NbH2jd0E= @@ -62,8 +64,8 @@ CS_BLOCKED_DOMAINS='example.org,example.net,example.com' CS_CW_DOMAINS='example.org,example.net,example.com' CS_UNLISTED_DOMAINS='example.org,example.net,example.com' -## Optional +## Optional #HORIZON_DARKMODE=false # Horizon theme darkmode -#HORIZON_EMBED=false # Single Docker Container mode +#HORIZON_EMBED=false # Single Docker Container mode ENABLE_CONFIG_CACHE=false From a70f108616f289d1c2826e4f784467551c726709 Mon Sep 17 00:00:00 2001 From: Christian Winther Date: Tue, 16 Jan 2024 20:53:54 +0000 Subject: [PATCH 067/173] fix shellcheck error --- .ddev/commands/redis/redis-cli | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.ddev/commands/redis/redis-cli b/.ddev/commands/redis/redis-cli index 27bf575b3..8824c6a6b 100755 --- a/.ddev/commands/redis/redis-cli +++ b/.ddev/commands/redis/redis-cli @@ -4,4 +4,4 @@ ## Usage: redis-cli [flags] [args] ## Example: "redis-cli KEYS *" or "ddev redis-cli INFO" or "ddev redis-cli --version" -redis-cli -p 6379 -h redis $@ +exec redis-cli -p 6379 -h redis "$@" From afa335b7b5670fd8222235c7bc67fdae29d55dd8 Mon Sep 17 00:00:00 2001 From: Christian Winther Date: Wed, 17 Jan 2024 12:50:55 +0000 Subject: [PATCH 068/173] add missing pecl back --- .env.docker | 2 +- Dockerfile | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.env.docker b/.env.docker index 5f5152968..e7f259f2e 100644 --- a/.env.docker +++ b/.env.docker @@ -378,7 +378,7 @@ MAIL_FROM_NAME="Pixelfed @ ${APP_DOMAIN}" # Defaults to "phpredis". # -# See: https://docs.pixelfed.org/technical-documentation/config/#db_username +# See: https://docs.pixelfed.org/technical-documentation/config/#redis_client #REDIS_CLIENT="phpredis" # Defaults to "tcp". diff --git a/Dockerfile b/Dockerfile index 3d12aba26..53037cb05 100644 --- a/Dockerfile +++ b/Dockerfile @@ -40,7 +40,7 @@ ARG RUNTIME_GID=33 # often called 'www-data' ARG APT_PACKAGES_EXTRA= # Extensions installed via [pecl install] -ARG PHP_PECL_EXTENSIONS= +ARG PHP_PECL_EXTENSIONS="redis imagick" ARG PHP_PECL_EXTENSIONS_EXTRA= # Extensions installed via [docker-php-ext-install] From 6563d4d0b90952b7ae32b388d66e16f257332b1d Mon Sep 17 00:00:00 2001 From: Christian Winther Date: Wed, 17 Jan 2024 13:49:56 +0000 Subject: [PATCH 069/173] add goss (https://github.com/goss-org/goss) validation --- .github/workflows/docker.yml | 12 ++++ goss.yaml | 125 +++++++++++++++++++++++++++++++++++ 2 files changed, 137 insertions(+) create mode 100644 goss.yaml diff --git a/.github/workflows/docker.yml b/.github/workflows/docker.yml index 64978070a..ea3533a3e 100644 --- a/.github/workflows/docker.yml +++ b/.github/workflows/docker.yml @@ -187,3 +187,15 @@ jobs: PHP_BASE_TYPE=${{ matrix.php_base }} cache-from: type=gha,scope=${{ matrix.target_runtime }}-${{ matrix.php_base }}-${{ matrix.php_version }} cache-to: type=gha,mode=max,scope=${{ matrix.target_runtime }}-${{ matrix.php_base }}-${{ matrix.php_version }} + + - uses: e1himself/goss-installation-action@v1 + with: + version: "v0.4.4" + + - name: Execute Goss tests + run: | + dgoss run \ + -v "./.env.testing:/var/www/.env" \ + -e EXPECTED_PHP_VERSION=${{ matrix.php_version }} \ + -e PHP_BASE_TYPE=${{ matrix.php_base }} \ + ${{ steps.meta.outputs.tags }} diff --git a/goss.yaml b/goss.yaml new file mode 100644 index 000000000..a43763b7a --- /dev/null +++ b/goss.yaml @@ -0,0 +1,125 @@ +# See: https://github.com/goss-org/goss/blob/master/docs/manual.md#goss-manual + +package: + curl: { installed: true } + ffmpeg: { installed: true } + gifsicle: { installed: true } + gosu: { installed: true } + jpegoptim: { installed: true } + locales-all: { installed: true } + locales: { installed: true } + mariadb-client: { installed: true } + nano: { installed: true } + optipng: { installed: true } + pngquant: { installed: true } + postgresql-client: { installed: true } + unzip: { installed: true } + wget: { installed: true } + zip: { installed: true } + +user: + www-data: + exists: true + uid: 33 + gid: 33 + groups: + - www-data + home: /var/www + shell: /usr/sbin/nologin + +command: + php-version: + exit-status: 0 + exec: 'php -v' + stdout: + - PHP {{ .Env.EXPECTED_PHP_VERSION }} + stderr: [] + + php-extensions: + exit-status: 0 + exec: 'php -m' + stdout: + - bcmath + - Core + - ctype + - curl + - date + - dom + - exif + - fileinfo + - filter + - ftp + - gd + - hash + - iconv + - imagick + - intl + - json + - libxml + - mbstring + - mysqlnd + - openssl + - pcntl + - pcre + - PDO + - pdo_mysql + - pdo_pgsql + - pdo_sqlite + - Phar + - posix + - random + - readline + - redis + - Reflection + - session + - SimpleXML + - sodium + - SPL + - sqlite3 + - standard + - tokenizer + - xml + - xmlreader + - xmlwriter + - zip + - zlib + stderr: [] + + forego-version: + exit-status: 0 + exec: 'forego version' + stdout: + - dev + stderr: [] + + gomplate-version: + exit-status: 0 + exec: 'gomplate -v' + stdout: + - gomplate version + stderr: [] + + gosu-version: + exit-status: 0 + exec: 'gosu -v' + stdout: + - '1.12' + stderr: [] + +{{ if eq .Env.PHP_BASE_TYPE "nginx" }} + nginx-version: + exit-status: 0 + exec: 'nginx -v' + stdout: [] + stderr: + - 'nginx version: nginx' +{{ end }} + +{{ if eq .Env.PHP_BASE_TYPE "apache" }} + nginx-version: + exit-status: 0 + exec: 'apachectl -v' + stdout: + - 'Server version: Apache/' + stderr: [] +{{ end }} From d8b37e6870730e7f39d84fd35c5160d99ddecb94 Mon Sep 17 00:00:00 2001 From: Christian Winther Date: Wed, 17 Jan 2024 14:13:38 +0000 Subject: [PATCH 070/173] debug redis --- .github/workflows/docker.yml | 8 +++++--- docker-compose.yml | 9 ++++++--- goss.yaml | 1 - 3 files changed, 11 insertions(+), 7 deletions(-) diff --git a/.github/workflows/docker.yml b/.github/workflows/docker.yml index ea3533a3e..87b91a20f 100644 --- a/.github/workflows/docker.yml +++ b/.github/workflows/docker.yml @@ -188,14 +188,16 @@ jobs: cache-from: type=gha,scope=${{ matrix.target_runtime }}-${{ matrix.php_base }}-${{ matrix.php_version }} cache-to: type=gha,mode=max,scope=${{ matrix.target_runtime }}-${{ matrix.php_base }}-${{ matrix.php_version }} + # goss validate the image + # + # See: https://github.com/goss-org/goss - uses: e1himself/goss-installation-action@v1 with: version: "v0.4.4" - - name: Execute Goss tests run: | dgoss run \ -v "./.env.testing:/var/www/.env" \ - -e EXPECTED_PHP_VERSION=${{ matrix.php_version }} \ - -e PHP_BASE_TYPE=${{ matrix.php_base }} \ + -e "EXPECTED_PHP_VERSION=${{ matrix.php_version }}" \ + -e "PHP_BASE_TYPE=${{ matrix.php_base }}" \ ${{ steps.meta.outputs.tags }} diff --git a/docker-compose.yml b/docker-compose.yml index 76aebf609..b85118411 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -128,18 +128,21 @@ services: - "${DOCKER_DB_PORT_EXTERNAL}:3306" redis: - image: redis:7 + image: redis:7.2 container_name: "${DOCKER_CONTAINER_NAME_PREFIX}-redis" restart: unless-stopped + command: ["/etc/redis/redis.conf", "--requirepass", "${REDIS_PASSWORD:-}"] + environment: + - REDISCLI_AUTH=${REDIS_PASSWORD:-} env_file: - ".env" volumes: - "${DOCKER_CONFIG_ROOT}/redis:/etc/redis" - "${DOCKER_REDIS_DATA_PATH}:/data" ports: - - "${DOCKER_REDIS_PORT_EXTERNAL}:6399" + - "${DOCKER_REDIS_PORT_EXTERNAL}:6379" healthcheck: interval: 10s timeout: 5s retries: 2 - test: ["CMD", "redis-cli", "-p", "6399", "ping"] + test: ["CMD", "redis-cli", "-p", "6379", "ping"] diff --git a/goss.yaml b/goss.yaml index a43763b7a..aa5ee6058 100644 --- a/goss.yaml +++ b/goss.yaml @@ -67,7 +67,6 @@ command: - pdo_sqlite - Phar - posix - - random - readline - redis - Reflection From be2ba79dc24cbdae1b7fd6413c6bc419cd1ff8ac Mon Sep 17 00:00:00 2001 From: Christian Winther Date: Wed, 17 Jan 2024 14:25:31 +0000 Subject: [PATCH 071/173] bugfixes --- .env.docker | 9 +++++++++ docker-compose.yml | 2 +- .../shared/root/docker/entrypoint.d/00-check-config.sh | 3 --- docker/shared/root/docker/entrypoint.d/12-migrations.sh | 2 +- 4 files changed, 11 insertions(+), 5 deletions(-) diff --git a/.env.docker b/.env.docker index e7f259f2e..d2578d1be 100644 --- a/.env.docker +++ b/.env.docker @@ -995,6 +995,15 @@ DOCKER_APP_CACHE_PATH="${DOCKER_DATA_ROOT}/pixelfed/cache" # Port that Redis will listen on *outside* the container (e.g. the host machine) DOCKER_REDIS_PORT_EXTERNAL="${REDIS_PORT:-6379}" +# The filename that Redis should store its config file within +# +# NOTE: The file *MUST* exists (even empty) before enabling this setting! +# +# Use a command like [touch "${DOCKER_CONFIG_ROOT}/redis/redis.conf"] to create it. +# +# Defaults to "" +#DOCKER_REDIS_CONFIG_FILE="/etc/redis/redis.conf" + # Port that the database will listen on *outside* the container (e.g. the host machine) # # Use "3306" for MySQL/MariaDB and "5432" for PostgreeSQL diff --git a/docker-compose.yml b/docker-compose.yml index b85118411..02024c390 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -131,7 +131,7 @@ services: image: redis:7.2 container_name: "${DOCKER_CONTAINER_NAME_PREFIX}-redis" restart: unless-stopped - command: ["/etc/redis/redis.conf", "--requirepass", "${REDIS_PASSWORD:-}"] + command: "${DOCKER_REDIS_CONFIG_FILE} --requirepass '${REDIS_PASSWORD:-}'" environment: - REDISCLI_AUTH=${REDIS_PASSWORD:-} env_file: diff --git a/docker/shared/root/docker/entrypoint.d/00-check-config.sh b/docker/shared/root/docker/entrypoint.d/00-check-config.sh index 290deb3fc..eecb150b4 100755 --- a/docker/shared/root/docker/entrypoint.d/00-check-config.sh +++ b/docker/shared/root/docker/entrypoint.d/00-check-config.sh @@ -16,6 +16,3 @@ for file in "${dot_env_files[@]}"; do log-info "Linting dotenv file ${file}" dotenv-linter --skip=QuoteCharacter --skip=UnorderedKey "${file}" done - -# Write the config cache -run-as-runtime-user php artisan config:cache diff --git a/docker/shared/root/docker/entrypoint.d/12-migrations.sh b/docker/shared/root/docker/entrypoint.d/12-migrations.sh index 1fb49f393..41c27e986 100755 --- a/docker/shared/root/docker/entrypoint.d/12-migrations.sh +++ b/docker/shared/root/docker/entrypoint.d/12-migrations.sh @@ -14,7 +14,7 @@ await-database-ready # Detect if we have new migrations declare -i new_migrations=0 -run-as-runtime-user php artisan migrate:status | grep No && new_migrations=1 +(run-as-runtime-user php artisan migrate:status || :) | grep No && new_migrations=1 if is-true "${new_migrations}"; then log-info "No outstanding migrations detected" From 44266b950b0b1685df8ce6d57705b6f37cf90cc6 Mon Sep 17 00:00:00 2001 From: Christian Winther Date: Wed, 17 Jan 2024 14:29:24 +0000 Subject: [PATCH 072/173] conditionally initialize passport and instance actor --- .../root/docker/entrypoint.d/11-first-time-setup.sh | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/docker/shared/root/docker/entrypoint.d/11-first-time-setup.sh b/docker/shared/root/docker/entrypoint.d/11-first-time-setup.sh index 9559eb4de..41e28b5ae 100755 --- a/docker/shared/root/docker/entrypoint.d/11-first-time-setup.sh +++ b/docker/shared/root/docker/entrypoint.d/11-first-time-setup.sh @@ -19,7 +19,15 @@ fi load-config-files await-database-ready -only-once "storage:link" run-as-runtime-user php artisan storage:link only-once "key:generate" run-as-runtime-user php artisan key:generate +only-once "storage:link" run-as-runtime-user php artisan storage:link only-once "initial:migrate" run-as-runtime-user php artisan migrate --force only-once "import:cities" run-as-runtime-user php artisan import:cities + +if is-true "${ACTIVITY_PUB:-false}"; then + only-once "instance:actor" run-as-runtime-user php artisan instance:actor +fi + +if is-true "${OAUTH_ENABLED:-false}"; then + only-once "passport:keys" run-as-runtime-user php artisan passport:keys +fi From 45f1df78b05b2021e21df9f5a8b7ce8e0d045e5a Mon Sep 17 00:00:00 2001 From: Christian Winther Date: Wed, 17 Jan 2024 14:41:48 +0000 Subject: [PATCH 073/173] update proxy-acme paths --- Dockerfile | 9 +++++---- docker-compose.yml | 8 ++++---- .../root/docker/entrypoint.d/11-first-time-setup.sh | 4 ++++ 3 files changed, 13 insertions(+), 8 deletions(-) diff --git a/Dockerfile b/Dockerfile index 53037cb05..a5930aec0 100644 --- a/Dockerfile +++ b/Dockerfile @@ -97,17 +97,17 @@ RUN set -ex \ FROM php:${PHP_VERSION}-${PHP_BASE_TYPE}-${PHP_DEBIAN_RELEASE} AS base -ARG APT_PACKAGES_EXTRA ARG BUILDKIT_SBOM_SCAN_STAGE="true" + +ARG APT_PACKAGES_EXTRA +ARG DOTENV_LINTER_VERSION ARG PHP_DEBIAN_RELEASE ARG PHP_VERSION ARG RUNTIME_GID ARG RUNTIME_UID ARG TARGETPLATFORM -ARG DOTENV_LINTER_VERSION ENV DEBIAN_FRONTEND="noninteractive" -ENV DOTENV_LINTER_VERSION="${DOTENV_LINTER_VERSION}" # Ensure we run all scripts through 'bash' rather than 'sh' SHELL ["/bin/bash", "-c"] @@ -119,6 +119,7 @@ RUN set -ex \ WORKDIR /var/www/ ENV APT_PACKAGES_EXTRA=${APT_PACKAGES_EXTRA} +ENV DOTENV_LINTER_VERSION="${DOTENV_LINTER_VERSION}" # Install and configure base layer COPY docker/shared/root/docker/install/base.sh /docker/install/base.sh @@ -148,7 +149,7 @@ ENV PHP_PECL_EXTENSIONS_EXTRA=${PHP_PECL_EXTENSIONS_EXTRA} ENV PHP_PECL_EXTENSIONS=${PHP_PECL_EXTENSIONS} COPY docker/shared/root/docker/install/php-extensions.sh /docker/install/php-extensions.sh -RUN --mount=type=cache,id=pixelfed-php-${PHP_VERSION}-${PHP_DEBIAN_RELEASE}-${TARGETPLATFORM},sharing=locked,target=/usr/src/php/ \ +RUN --mount=type=cache,id=pixelfed-php-${PHP_VERSION}-${PHP_DEBIAN_RELEASE}-${TARGETPLATFORM},sharing=locked,target=/usr/src/php \ --mount=type=cache,id=pixelfed-apt-${PHP_VERSION}-${PHP_DEBIAN_RELEASE}-${TARGETPLATFORM},sharing=locked,target=/var/lib/apt \ --mount=type=cache,id=pixelfed-apt-cache-${PHP_VERSION}-${PHP_DEBIAN_RELEASE}-${TARGETPLATFORM},sharing=locked,target=/var/cache/apt \ /docker/install/php-extensions.sh diff --git a/docker-compose.yml b/docker-compose.yml index 02024c390..ba1a211c9 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -53,12 +53,12 @@ services: depends_on: - proxy volumes: - - "${DOCKER_HOST_SOCKET_PATH}:/var/run/docker.sock:ro" + - "${DOCKER_CONFIG_ROOT}/proxy-acme:/etc/acme.sh" + - "${DOCKER_CONFIG_ROOT}/proxy/certs:/etc/nginx/certs" - "${DOCKER_CONFIG_ROOT}/proxy/conf.d:/etc/nginx/conf.d" - "${DOCKER_CONFIG_ROOT}/proxy/vhost.d:/etc/nginx/vhost.d" - - "${DOCKER_CONFIG_ROOT}/proxy/certs:/etc/nginx/certs" - "${DOCKER_DATA_ROOT}/proxy/html:/usr/share/nginx/html" - - "${DOCKER_DATA_ROOT}/proxy-acme:/etc/acme.sh" + - "${DOCKER_HOST_SOCKET_PATH}:/var/run/docker.sock:ro" web: image: "${DOCKER_IMAGE}:${DOCKER_TAG}" @@ -131,7 +131,7 @@ services: image: redis:7.2 container_name: "${DOCKER_CONTAINER_NAME_PREFIX}-redis" restart: unless-stopped - command: "${DOCKER_REDIS_CONFIG_FILE} --requirepass '${REDIS_PASSWORD:-}'" + command: "${DOCKER_REDIS_CONFIG_FILE:-} --requirepass '${REDIS_PASSWORD:-}'" environment: - REDISCLI_AUTH=${REDIS_PASSWORD:-} env_file: diff --git a/docker/shared/root/docker/entrypoint.d/11-first-time-setup.sh b/docker/shared/root/docker/entrypoint.d/11-first-time-setup.sh index 41e28b5ae..a3582932b 100755 --- a/docker/shared/root/docker/entrypoint.d/11-first-time-setup.sh +++ b/docker/shared/root/docker/entrypoint.d/11-first-time-setup.sh @@ -19,6 +19,10 @@ fi load-config-files await-database-ready +# Following https://docs.pixelfed.org/running-pixelfed/installation/#one-time-setup-tasks +# +# NOTE: Caches happens in [30-cache.sh] + only-once "key:generate" run-as-runtime-user php artisan key:generate only-once "storage:link" run-as-runtime-user php artisan storage:link only-once "initial:migrate" run-as-runtime-user php artisan migrate --force From 3a7fd8eac98263bd96d51cd2b7e162c96cc2cc05 Mon Sep 17 00:00:00 2001 From: Christian Winther Date: Wed, 17 Jan 2024 14:46:07 +0000 Subject: [PATCH 074/173] fix default variables --- .env.docker | 14 +++++++------- .../root/docker/entrypoint.d/04-defaults.envsh | 4 ++-- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/.env.docker b/.env.docker index d2578d1be..fe6c19d4b 100644 --- a/.env.docker +++ b/.env.docker @@ -134,6 +134,13 @@ APP_TIMEZONE="UTC" # See: https://docs.pixelfed.org/technical-documentation/config/#max_photo_size-kb #MAX_PHOTO_SIZE="15000" +# The max number of photos allowed per post. +# +# Defaults to "4". +# +# See: https://docs.pixelfed.org/technical-documentation/config/#max_album_length +#MAX_ALBUM_LENGTH="4" + # Update the max avatar size, in kB. # # Defaults to "2000" (2MB). @@ -162,13 +169,6 @@ APP_TIMEZONE="UTC" # See: https://docs.pixelfed.org/technical-documentation/config/#max_name_length #MAX_NAME_LENGTH="30" -# The max number of photos allowed per post. -# -# Defaults to "4". -# -# See: https://docs.pixelfed.org/technical-documentation/config/#max_album_length -#MAX_ALBUM_LENGTH="4" - # Resize and optimize image uploads. # # Defaults to "true". diff --git a/docker/shared/root/docker/entrypoint.d/04-defaults.envsh b/docker/shared/root/docker/entrypoint.d/04-defaults.envsh index fe906120a..a55a56e6c 100755 --- a/docker/shared/root/docker/entrypoint.d/04-defaults.envsh +++ b/docker/shared/root/docker/entrypoint.d/04-defaults.envsh @@ -12,8 +12,8 @@ entrypoint-set-script-name "${BASH_SOURCE[0]}" load-config-files -: "${MAX_PHOTO_SIZE:=}" -: "${MAX_ALBUM_LENGTH:=}" +: "${MAX_PHOTO_SIZE:=15000}" +: "${MAX_ALBUM_LENGTH:=4}" # We assign a 1MB buffer to the just-in-time calculated max post size to allow for fields and overhead : "${POST_MAX_SIZE_BUFFER:=1M}" From 9ad04a285a2f2c223256af3253b4f96df13f6a20 Mon Sep 17 00:00:00 2001 From: Christian Winther Date: Wed, 17 Jan 2024 14:48:02 +0000 Subject: [PATCH 075/173] fix missing output colors --- docker/shared/root/docker/helpers.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docker/shared/root/docker/helpers.sh b/docker/shared/root/docker/helpers.sh index 74aa6c468..3c21af791 100644 --- a/docker/shared/root/docker/helpers.sh +++ b/docker/shared/root/docker/helpers.sh @@ -220,7 +220,7 @@ function log-info-stderr() { fi if [ -z "${ENTRYPOINT_QUIET_LOGS:-}" ]; then - echo -e "${log_prefix}$msg" >/dev/stderr + echo -e "${notice_message_color}${log_prefix}${msg}${color_clear}" >/dev/stderr fi } From 90c9d8b5a6ca11fbfeac13db38aaaf1cd19e46cb Mon Sep 17 00:00:00 2001 From: Christian Winther Date: Wed, 17 Jan 2024 14:50:29 +0000 Subject: [PATCH 076/173] more toned down colors --- docker/shared/root/docker/helpers.sh | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/docker/shared/root/docker/helpers.sh b/docker/shared/root/docker/helpers.sh index 3c21af791..ea3a726cd 100644 --- a/docker/shared/root/docker/helpers.sh +++ b/docker/shared/root/docker/helpers.sh @@ -154,7 +154,7 @@ function log-error() { log-error-and-exit "[${FUNCNAME[0]}] did not receive any input arguments and STDIN is empty" fi - echo -e "${error_message_color}${log_prefix}ERROR - ${msg}${color_clear}" >/dev/stderr + echo -e "${error_message_color}${log_prefix}ERROR -${color_clear} ${msg}" >/dev/stderr } # @description Print the given error message to stderr and exit 1 @@ -183,7 +183,7 @@ function log-warning() { log-error-and-exit "[${FUNCNAME[0]}] did not receive any input arguments and STDIN is empty" fi - echo -e "${warn_message_color}${log_prefix}WARNING - ${msg}${color_clear}" >/dev/stderr + echo -e "${warn_message_color}${log_prefix}WARNING -${color_clear} ${msg}" >/dev/stderr } # @description Print the given message to stdout unless [ENTRYPOINT_QUIET_LOGS] is set @@ -201,7 +201,7 @@ function log-info() { fi if [ -z "${ENTRYPOINT_QUIET_LOGS:-}" ]; then - echo -e "${notice_message_color}${log_prefix}${msg}${color_clear}" + echo -e "${notice_message_color}${log_prefix}${color_clear}${msg}" fi } @@ -220,7 +220,7 @@ function log-info-stderr() { fi if [ -z "${ENTRYPOINT_QUIET_LOGS:-}" ]; then - echo -e "${notice_message_color}${log_prefix}${msg}${color_clear}" >/dev/stderr + echo -e "${notice_message_color}${log_prefix}${color_clear}${msg}" >/dev/stderr fi } From e70e13e2659c4906bb9716732a0a865f344d8387 Mon Sep 17 00:00:00 2001 From: Christian Winther Date: Wed, 17 Jan 2024 14:52:22 +0000 Subject: [PATCH 077/173] possible fix is-false/true logic --- docker/shared/root/docker/helpers.sh | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/docker/shared/root/docker/helpers.sh b/docker/shared/root/docker/helpers.sh index ea3a726cd..50fd3b1d9 100644 --- a/docker/shared/root/docker/helpers.sh +++ b/docker/shared/root/docker/helpers.sh @@ -491,6 +491,8 @@ function show-call-stack() { # @see as-boolean function is-true() { as-boolean "${1:-}" && return 0 + + return 1 } # @description Helper function see if $1 could be considered falsey @@ -498,6 +500,8 @@ function is-true() { # @see as-boolean function is-false() { as-boolean "${1:-}" || return 0 + + return 1 } # @description Helper function see if $1 could be truethy or falsey. From 2d05eccb87aefd146d1cc3989111e0fbcb97a0ee Mon Sep 17 00:00:00 2001 From: Christian Winther Date: Wed, 17 Jan 2024 15:37:12 +0000 Subject: [PATCH 078/173] add bats testing --- .github/workflows/docker.yml | 10 +++- .gitmodules | 10 ++++ docker/shared/root/docker/helpers.sh | 6 ++- tests/bats/helpers.bats | 74 ++++++++++++++++++++++++++++ 4 files changed, 97 insertions(+), 3 deletions(-) create mode 100644 .gitmodules create mode 100644 tests/bats/helpers.bats diff --git a/.github/workflows/docker.yml b/.github/workflows/docker.yml index 87b91a20f..3296ba9d6 100644 --- a/.github/workflows/docker.yml +++ b/.github/workflows/docker.yml @@ -43,7 +43,7 @@ jobs: name: Shellcheck runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Run ShellCheck uses: ludeeus/action-shellcheck@master env: @@ -52,6 +52,14 @@ jobs: version: v0.9.0 additional_files: "*.envsh .env .env.docker .env.example .env.testing" + bats: + name: Bats Testing + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - name: Run bats + run: docker run -v "$PWD:/var/www" bats/bats:latest /var/www/tests/bats + build: runs-on: ubuntu-latest diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 000000000..6fe990290 --- /dev/null +++ b/.gitmodules @@ -0,0 +1,10 @@ + +[submodule "tests/shell/bats"] + path = tests/shell/bats + url = https://github.com/bats-core/bats-core.git +[submodule "tests/shell/test_helper/bats-support"] + path = tests/shell/test_helper/bats-support + url = https://github.com/bats-core/bats-support.git +[submodule "tests/shell/test_helper/bats-assert"] + path = tests/shell/test_helper/bats-assert + url = https://github.com/bats-core/bats-assert.git diff --git a/docker/shared/root/docker/helpers.sh b/docker/shared/root/docker/helpers.sh index 50fd3b1d9..823abab07 100644 --- a/docker/shared/root/docker/helpers.sh +++ b/docker/shared/root/docker/helpers.sh @@ -487,6 +487,7 @@ function show-call-stack() { } # @description Helper function see if $1 could be considered truthy +# returns [0] if input is truthy, otherwise [1] # @arg $1 string The string to evaluate # @see as-boolean function is-true() { @@ -496,12 +497,13 @@ function is-true() { } # @description Helper function see if $1 could be considered falsey +# returns [0] if input is falsey, otherwise [1] # @arg $1 string The string to evaluate # @see as-boolean function is-false() { - as-boolean "${1:-}" || return 0 + as-boolean "${1:-}" && return 1 - return 1 + return 0 } # @description Helper function see if $1 could be truethy or falsey. diff --git a/tests/bats/helpers.bats b/tests/bats/helpers.bats new file mode 100644 index 000000000..ea4c7b518 --- /dev/null +++ b/tests/bats/helpers.bats @@ -0,0 +1,74 @@ +setup() { + DIR="$(cd "$(dirname "${BATS_TEST_FILENAME:-}")" >/dev/null 2>&1 && pwd)" + ROOT="$(dirname "$(dirname "$DIR")")" + + load "$ROOT/docker/shared/root/docker/helpers.sh" +} + +@test "test [is-true]" { + is-true "1" + is-true "true" + is-true "TrUe" +} + +@test "test [is-false]" { + is-false "0" + is-false "false" + is-false "FaLsE" +} + +@test "test [is-false-expressions-0]" { + if is-false "0"; then + return 0 + fi + + return 1 +} + +@test "test [is-false-expressions-false]" { + if is-false "false"; then + return 0 + fi + + return 1 +} + +@test "test [is-false-expressions-FaLse]" { + if is-false "FaLse"; then + return 0 + fi + + return 1 +} + +@test "test [is-false-expressions-invalid]" { + if is-false "invalid"; then + return 0 + fi + + return 1 +} + +@test "test [is-true-expressions-1]" { + if is-true "1"; then + return 0 + fi + + return 1 +} + +@test "test [is-true-expressions-true]" { + if is-true "true"; then + return 0 + fi + + return 1 +} + +@test "test [is-true-expressions-TrUE]" { + if is-true "TrUE"; then + return 0 + fi + + return 1 +} From a4646df8f23584996d53bcd71f0b082fa266a632 Mon Sep 17 00:00:00 2001 From: Christian Winther Date: Wed, 17 Jan 2024 15:47:39 +0000 Subject: [PATCH 079/173] add some health checks --- docker-compose.yml | 33 ++++++++++++++++++++++++++++++--- 1 file changed, 30 insertions(+), 3 deletions(-) diff --git a/docker-compose.yml b/docker-compose.yml index ba1a211c9..757d7690f 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -33,6 +33,11 @@ services: ports: - "${DOCKER_PROXY_PORT_EXTERNAL_HTTP}:80" - "${DOCKER_PROXY_PORT_EXTERNAL_HTTPS}:443" + healthcheck: + test: 'curl --header "Host: $[APP_DOMAIN}" --fail http://localhost/api/service/health-check' + interval: 10s + retries: 2 + timeout: 5s # Proxy companion for managing letsencrypt SSL certificates # @@ -92,6 +97,11 @@ services: depends_on: - db - redis + healthcheck: + test: 'curl --header "Host: $[APP_DOMAIN}" --fail http://localhost/api/service/health-check' + interval: 10s + retries: 2 + timeout: 5s worker: image: "${DOCKER_IMAGE}:${DOCKER_TAG}" @@ -114,6 +124,11 @@ services: depends_on: - db - redis + healthcheck: + test: gosu www-data php artisan horizon:status | grep running + interval: 10s + timeout: 5s + retries: 2 db: image: mariadb:11.2 @@ -126,6 +141,18 @@ services: - "${DOCKER_DB_DATA_PATH}:/var/lib/mysql" ports: - "${DOCKER_DB_PORT_EXTERNAL}:3306" + healthcheck: + test: + [ + "CMD", + "healthcheck.sh", + "--su-mysql", + "--connect", + "--innodb_initialized", + ] + interval: 10s + retries: 2 + timeout: 5s redis: image: redis:7.2 @@ -142,7 +169,7 @@ services: ports: - "${DOCKER_REDIS_PORT_EXTERNAL}:6379" healthcheck: - interval: 10s - timeout: 5s - retries: 2 test: ["CMD", "redis-cli", "-p", "6379", "ping"] + interval: 10s + retries: 2 + timeout: 5s From 3feb93b0346b16702a01488f3fe9c960e98388de Mon Sep 17 00:00:00 2001 From: Christian Winther Date: Wed, 17 Jan 2024 15:49:49 +0000 Subject: [PATCH 080/173] cleanup color output --- docker/shared/root/docker/entrypoint.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docker/shared/root/docker/entrypoint.sh b/docker/shared/root/docker/entrypoint.sh index 49d62afd0..77b58a019 100755 --- a/docker/shared/root/docker/entrypoint.sh +++ b/docker/shared/root/docker/entrypoint.sh @@ -59,7 +59,7 @@ find "${ENTRYPOINT_D_ROOT}" -follow -type f -print | sort -V | while read -r fil fi log-info "" - log-info "${notice_message_color}Sourcing [${file}]${color_clear}" + log-info "Sourcing [${file}]" log-info "" # shellcheck disable=SC1090 @@ -77,7 +77,7 @@ find "${ENTRYPOINT_D_ROOT}" -follow -type f -print | sort -V | while read -r fil fi log-info "" - log-info "${notice_message_color}Executing [${file}]${color_clear}" + log-info "Executing [${file}]" log-info "" "${file}" From adbd66eb38b387f0bbe4d8d189c116a321ed3ed1 Mon Sep 17 00:00:00 2001 From: Christian Winther Date: Wed, 17 Jan 2024 15:52:09 +0000 Subject: [PATCH 081/173] fix defaults --- docker/shared/root/docker/entrypoint.sh | 4 ++-- docker/shared/root/docker/templates/usr/local/etc/php/php.ini | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/docker/shared/root/docker/entrypoint.sh b/docker/shared/root/docker/entrypoint.sh index 77b58a019..49d62afd0 100755 --- a/docker/shared/root/docker/entrypoint.sh +++ b/docker/shared/root/docker/entrypoint.sh @@ -59,7 +59,7 @@ find "${ENTRYPOINT_D_ROOT}" -follow -type f -print | sort -V | while read -r fil fi log-info "" - log-info "Sourcing [${file}]" + log-info "${notice_message_color}Sourcing [${file}]${color_clear}" log-info "" # shellcheck disable=SC1090 @@ -77,7 +77,7 @@ find "${ENTRYPOINT_D_ROOT}" -follow -type f -print | sort -V | while read -r fil fi log-info "" - log-info "Executing [${file}]" + log-info "${notice_message_color}Executing [${file}]${color_clear}" log-info "" "${file}" diff --git a/docker/shared/root/docker/templates/usr/local/etc/php/php.ini b/docker/shared/root/docker/templates/usr/local/etc/php/php.ini index c34266630..6277ec080 100644 --- a/docker/shared/root/docker/templates/usr/local/etc/php/php.ini +++ b/docker/shared/root/docker/templates/usr/local/etc/php/php.ini @@ -831,10 +831,10 @@ file_uploads = On ; Maximum allowed size for uploaded files. ; http://php.net/upload-max-filesize -upload_max_filesize = {{ getenv "POST_MAX_SIZE" }} +upload_max_filesize = {{ getenv "POST_MAX_SIZE" "61M" }} ; Maximum number of files that can be uploaded via a single request -max_file_uploads = {{ getenv "MAX_ALBUM_LENGTH" }} +max_file_uploads = {{ getenv "MAX_ALBUM_LENGTH" "4" }} ;;;;;;;;;;;;;;;;;; ; Fopen wrappers ; From eee17fe9f24393020f2ea220b5245a421da416b9 Mon Sep 17 00:00:00 2001 From: Christian Winther Date: Wed, 17 Jan 2024 15:53:17 +0000 Subject: [PATCH 082/173] harden proxy health check to be https based --- docker-compose.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docker-compose.yml b/docker-compose.yml index 757d7690f..a029d4ee1 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -34,7 +34,7 @@ services: - "${DOCKER_PROXY_PORT_EXTERNAL_HTTP}:80" - "${DOCKER_PROXY_PORT_EXTERNAL_HTTPS}:443" healthcheck: - test: 'curl --header "Host: $[APP_DOMAIN}" --fail http://localhost/api/service/health-check' + test: 'curl --header "Host: $[APP_DOMAIN}" --fail https://localhost/api/service/health-check' interval: 10s retries: 2 timeout: 5s From 82ab545f1a03920fe2c2d5be14680d615cf6532b Mon Sep 17 00:00:00 2001 From: Christian Winther Date: Wed, 17 Jan 2024 15:55:05 +0000 Subject: [PATCH 083/173] more clear separation between log entry points --- docker/shared/root/docker/entrypoint.sh | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/docker/shared/root/docker/entrypoint.sh b/docker/shared/root/docker/entrypoint.sh index 49d62afd0..1b5f193d6 100755 --- a/docker/shared/root/docker/entrypoint.sh +++ b/docker/shared/root/docker/entrypoint.sh @@ -58,9 +58,9 @@ find "${ENTRYPOINT_D_ROOT}" -follow -type f -print | sort -V | while read -r fil log-error-and-exit "File [${file}] is not executable (please 'chmod +x' it)" fi - log-info "" - log-info "${notice_message_color}Sourcing [${file}]${color_clear}" - log-info "" + log-info "========================================" + log-info "Sourcing [${file}]" + log-info "========================================" # shellcheck disable=SC1090 source "${file}" @@ -76,9 +76,9 @@ find "${ENTRYPOINT_D_ROOT}" -follow -type f -print | sort -V | while read -r fil log-error-and-exit "File [${file}] is not executable (please 'chmod +x' it)" fi - log-info "" - log-info "${notice_message_color}Executing [${file}]${color_clear}" - log-info "" + log-info "========================================" + log-info "Executing [${file}]" + log-info "========================================" "${file}" ;; From 921f34d42eba87c431e25d75f987e8fe1f0e38d3 Mon Sep 17 00:00:00 2001 From: Christian Winther Date: Wed, 17 Jan 2024 15:59:58 +0000 Subject: [PATCH 084/173] color tweaks --- docker/shared/root/docker/helpers.sh | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/docker/shared/root/docker/helpers.sh b/docker/shared/root/docker/helpers.sh index 823abab07..cd4616175 100644 --- a/docker/shared/root/docker/helpers.sh +++ b/docker/shared/root/docker/helpers.sh @@ -10,6 +10,7 @@ set -e -o errexit -o nounset -o pipefail declare -g error_message_color="\033[1;31m" declare -g warn_message_color="\033[1;34m" declare -g notice_message_color="\033[1;34m" +declare -g success_message_color="\033[1;32m" declare -g color_clear="\033[1;0m" # Current and previous log prefix @@ -80,7 +81,7 @@ function run-command-as() { target_user=${1} shift - log-info-stderr "👷 Running [${*}] as [${target_user}]" + log-info-stderr "${notice_message_color}👷 Running [${*}] as [${target_user}]${color_clear}" if [[ ${target_user} != "root" ]]; then stream-prefix-command-output su --preserve-environment "${target_user}" --shell /bin/bash --command "${*}" @@ -91,11 +92,11 @@ function run-command-as() { exit_code=$? if [[ $exit_code != 0 ]]; then - log-error "❌ Error!" + log-error "${error_message_color}❌ Error!${color_clear}" return "$exit_code" fi - log-info-stderr "✅ OK!" + log-info-stderr "${success_message_color}✅ OK!${color_clear}" return "$exit_code" } From cc9f673eeafec0dc18a9f37bf12a33c243f6e5d5 Mon Sep 17 00:00:00 2001 From: Christian Winther Date: Wed, 17 Jan 2024 16:01:52 +0000 Subject: [PATCH 085/173] test proxy via direct url --- docker-compose.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docker-compose.yml b/docker-compose.yml index a029d4ee1..b2a8aa806 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -34,7 +34,7 @@ services: - "${DOCKER_PROXY_PORT_EXTERNAL_HTTP}:80" - "${DOCKER_PROXY_PORT_EXTERNAL_HTTPS}:443" healthcheck: - test: 'curl --header "Host: $[APP_DOMAIN}" --fail https://localhost/api/service/health-check' + test: "curl --fail https://$[APP_DOMAIN}/api/service/health-check" interval: 10s retries: 2 timeout: 5s From ead7c33275d8a85b675a8ecd5cfdf898099faaa4 Mon Sep 17 00:00:00 2001 From: Christian Winther Date: Wed, 17 Jan 2024 16:11:36 +0000 Subject: [PATCH 086/173] more docker config tuning --- .env.docker | 30 ++++++++++++++++++++++++++++++ docker-compose.yml | 14 +++++++------- 2 files changed, 37 insertions(+), 7 deletions(-) diff --git a/.env.docker b/.env.docker index fe6c19d4b..9c440d37e 100644 --- a/.env.docker +++ b/.env.docker @@ -260,6 +260,11 @@ LETSENCRYPT_EMAIL="__CHANGE_ME__" # Database configuration ################################################################################ +# Database version to use (as Docker tag) +# +# See: https://hub.docker.com/_/mariadb +#DB_VERSION="11.2" + # Here you may specify which of the database connections below # you wish to use as your default connection for all database work. # @@ -376,6 +381,11 @@ MAIL_FROM_NAME="Pixelfed @ ${APP_DOMAIN}" # Redis configuration ################################################################################ +# Redis version to use as Docker tag +# +# See: https://hub.docker.com/_/redis +#REDIS_VERSION="7.2" + # Defaults to "phpredis". # # See: https://docs.pixelfed.org/technical-documentation/config/#redis_client @@ -992,6 +1002,11 @@ DOCKER_APP_STORAGE_PATH="${DOCKER_DATA_ROOT}/pixelfed/storage" # Path is relative (./some/other/path) to the docker-compose.yml or absolute (/some/other/path) DOCKER_APP_CACHE_PATH="${DOCKER_DATA_ROOT}/pixelfed/cache" +# How often Docker health check should run for all services +# +# Can be overridden by individual [DOCKER_*_HEALTHCHECK_INTERVAL] settings further down +DOCKER_DEFAULT_HEALTHCHECK_INTERVAL="10s" + # Port that Redis will listen on *outside* the container (e.g. the host machine) DOCKER_REDIS_PORT_EXTERNAL="${REDIS_PORT:-6379}" @@ -1004,11 +1019,17 @@ DOCKER_REDIS_PORT_EXTERNAL="${REDIS_PORT:-6379}" # Defaults to "" #DOCKER_REDIS_CONFIG_FILE="/etc/redis/redis.conf" +# How often Docker health check should run for [redis] service +DOCKER_REDIS_HEALTHCHECK_INTERVAL="${DOCKER_DEFAULT_HEALTHCHECK_INTERVAL}" + # Port that the database will listen on *outside* the container (e.g. the host machine) # # Use "3306" for MySQL/MariaDB and "5432" for PostgreeSQL DOCKER_DB_PORT_EXTERNAL="${DB_PORT}" +# How often Docker health check should run for [db] service +DOCKER_DB_HEALTHCHECK_INTERVAL="${DOCKER_DEFAULT_HEALTHCHECK_INTERVAL}" + # Port that the [proxy] will listen on *outside* the container (e.g. the host machine) for HTTP traffic DOCKER_PROXY_PORT_EXTERNAL_HTTP="80" @@ -1018,6 +1039,12 @@ DOCKER_PROXY_PORT_EXTERNAL_HTTPS="443" # Port to expose [web] container will listen on *outside* the container (e.g. the host machine) for *HTTP* traffic only DOCKER_WEB_PORT_EXTERNAL_HTTP="8080" +# How often Docker health check should run for [web] service +DOCKER_WEB_HEALTHCHECK_INTERVAL="${DOCKER_DEFAULT_HEALTHCHECK_INTERVAL}" + +# How often Docker health check should run for [worker] service +DOCKER_WORKER_HEALTHCHECK_INTERVAL="${DOCKER_DEFAULT_HEALTHCHECK_INTERVAL}" + # Path to the Docker socket on the *host* DOCKER_HOST_SOCKET_PATH="/var/run/docker.sock" @@ -1030,6 +1057,9 @@ DOCKER_PROXY_PROFILE="" # Set this to a non-empty value (e.g. "disabled") to disable the [proxy-acme] service DOCKER_PROXY_ACME_PROFILE="${DOCKER_PROXY_PROFILE}" +# How often Docker health check should run for [proxy] service +DOCKER_PROXY_HEALTHCHECK_INTERVAL="${DOCKER_DEFAULT_HEALTHCHECK_INTERVAL}" + # Automatically run "One-time setup tasks" commands. # # If you are migrating to this docker-compose setup or have manually run the "One time seutp" diff --git a/docker-compose.yml b/docker-compose.yml index b2a8aa806..4d5d6ac64 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -35,7 +35,7 @@ services: - "${DOCKER_PROXY_PORT_EXTERNAL_HTTPS}:443" healthcheck: test: "curl --fail https://$[APP_DOMAIN}/api/service/health-check" - interval: 10s + interval: "${DOCKER_PROXY_HEALTHCHECK_INTERVAL:-10s}" retries: 2 timeout: 5s @@ -99,7 +99,7 @@ services: - redis healthcheck: test: 'curl --header "Host: $[APP_DOMAIN}" --fail http://localhost/api/service/health-check' - interval: 10s + interval: "${DOCKER_WEB_HEALTHCHECK_INTERVAL:-10s}" retries: 2 timeout: 5s @@ -126,12 +126,12 @@ services: - redis healthcheck: test: gosu www-data php artisan horizon:status | grep running - interval: 10s + interval: "${DOCKER_WORKER_HEALTHCHECK_INTERVAL}" timeout: 5s retries: 2 db: - image: mariadb:11.2 + image: mariadb:${DB_VERSION:-11.2} container_name: "${DOCKER_CONTAINER_NAME_PREFIX}-db" command: --default-authentication-plugin=mysql_native_password restart: unless-stopped @@ -150,12 +150,12 @@ services: "--connect", "--innodb_initialized", ] - interval: 10s + interval: "${DOCKER_DB_HEALTHCHECK_INTERVAL:-10s}" retries: 2 timeout: 5s redis: - image: redis:7.2 + image: redis:${REDIS_VERSION:-7.2} container_name: "${DOCKER_CONTAINER_NAME_PREFIX}-redis" restart: unless-stopped command: "${DOCKER_REDIS_CONFIG_FILE:-} --requirepass '${REDIS_PASSWORD:-}'" @@ -170,6 +170,6 @@ services: - "${DOCKER_REDIS_PORT_EXTERNAL}:6379" healthcheck: test: ["CMD", "redis-cli", "-p", "6379", "ping"] - interval: 10s + interval: "${DOCKER_REDIS_HEALTHCHECK_INTERVAL}" retries: 2 timeout: 5s From 62efe8b3d4bde9ddc21be9b17e2c153c0f10fec3 Mon Sep 17 00:00:00 2001 From: Christian Winther Date: Wed, 17 Jan 2024 16:18:29 +0000 Subject: [PATCH 087/173] ensure default health check values --- docker-compose.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docker-compose.yml b/docker-compose.yml index 4d5d6ac64..376bf52d6 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -126,7 +126,7 @@ services: - redis healthcheck: test: gosu www-data php artisan horizon:status | grep running - interval: "${DOCKER_WORKER_HEALTHCHECK_INTERVAL}" + interval: "${DOCKER_WORKER_HEALTHCHECK_INTERVAL:-10s}" timeout: 5s retries: 2 @@ -170,6 +170,6 @@ services: - "${DOCKER_REDIS_PORT_EXTERNAL}:6379" healthcheck: test: ["CMD", "redis-cli", "-p", "6379", "ping"] - interval: "${DOCKER_REDIS_HEALTHCHECK_INTERVAL}" + interval: "${DOCKER_REDIS_HEALTHCHECK_INTERVAL:-10s}" retries: 2 timeout: 5s From ca0a25912aa910164ccb357003c1683ed362355b Mon Sep 17 00:00:00 2001 From: Christian Winther Date: Wed, 17 Jan 2024 16:25:34 +0000 Subject: [PATCH 088/173] more color tuning --- docker/shared/root/docker/entrypoint.sh | 12 ++++++------ docker/shared/root/docker/helpers.sh | 1 + 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/docker/shared/root/docker/entrypoint.sh b/docker/shared/root/docker/entrypoint.sh index 1b5f193d6..44310fa7a 100755 --- a/docker/shared/root/docker/entrypoint.sh +++ b/docker/shared/root/docker/entrypoint.sh @@ -58,9 +58,9 @@ find "${ENTRYPOINT_D_ROOT}" -follow -type f -print | sort -V | while read -r fil log-error-and-exit "File [${file}] is not executable (please 'chmod +x' it)" fi - log-info "========================================" - log-info "Sourcing [${file}]" - log-info "========================================" + log-info "${section_message_color}========================================${color_clear}" + log-info "${section_message_color}Sourcing [${file}]${color_clear}" + log-info "${section_message_color}========================================${color_clear}" # shellcheck disable=SC1090 source "${file}" @@ -76,9 +76,9 @@ find "${ENTRYPOINT_D_ROOT}" -follow -type f -print | sort -V | while read -r fil log-error-and-exit "File [${file}] is not executable (please 'chmod +x' it)" fi - log-info "========================================" - log-info "Executing [${file}]" - log-info "========================================" + log-info "${section_message_color}========================================${color_clear}" + log-info "${section_message_color}Executing [${file}]${color_clear}" + log-info "${section_message_color}========================================${color_clear}" "${file}" ;; diff --git a/docker/shared/root/docker/helpers.sh b/docker/shared/root/docker/helpers.sh index cd4616175..b33528e16 100644 --- a/docker/shared/root/docker/helpers.sh +++ b/docker/shared/root/docker/helpers.sh @@ -11,6 +11,7 @@ declare -g error_message_color="\033[1;31m" declare -g warn_message_color="\033[1;34m" declare -g notice_message_color="\033[1;34m" declare -g success_message_color="\033[1;32m" +declare -g section_message_color="\033[1;35m" declare -g color_clear="\033[1;0m" # Current and previous log prefix From dc95d4d80098d3f9e29e38a6841bbc27653cdceb Mon Sep 17 00:00:00 2001 From: Christian Winther Date: Wed, 17 Jan 2024 16:29:15 +0000 Subject: [PATCH 089/173] colors --- docker/shared/root/docker/helpers.sh | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/docker/shared/root/docker/helpers.sh b/docker/shared/root/docker/helpers.sh index b33528e16..802e21ea5 100644 --- a/docker/shared/root/docker/helpers.sh +++ b/docker/shared/root/docker/helpers.sh @@ -11,6 +11,7 @@ declare -g error_message_color="\033[1;31m" declare -g warn_message_color="\033[1;34m" declare -g notice_message_color="\033[1;34m" declare -g success_message_color="\033[1;32m" +# shellcheck disable=SC2034 declare -g section_message_color="\033[1;35m" declare -g color_clear="\033[1;0m" @@ -440,7 +441,7 @@ function await-database-ready() { ;; sqlite) - log-info "sqlite are always ready" + log-info "${success_message_color}sqlite is always ready${color_clear}" ;; *) @@ -448,7 +449,7 @@ function await-database-ready() { ;; esac - log-info "✅ Successfully connected to database" + log-info "${success_message_color}✅ Successfully connected to database${color_clear}" } # @description sleeps between 1 and 3 seconds to ensure a bit of randomness From a094a0bd66246d35a65a95a2f502a99e33bbb2cc Mon Sep 17 00:00:00 2001 From: Christian Winther Date: Wed, 17 Jan 2024 16:30:40 +0000 Subject: [PATCH 090/173] syntax fix --- docker-compose.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docker-compose.yml b/docker-compose.yml index 376bf52d6..88e2b692d 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -34,7 +34,7 @@ services: - "${DOCKER_PROXY_PORT_EXTERNAL_HTTP}:80" - "${DOCKER_PROXY_PORT_EXTERNAL_HTTPS}:443" healthcheck: - test: "curl --fail https://$[APP_DOMAIN}/api/service/health-check" + test: "curl --fail https://${APP_DOMAIN}/api/service/health-check" interval: "${DOCKER_PROXY_HEALTHCHECK_INTERVAL:-10s}" retries: 2 timeout: 5s @@ -98,7 +98,7 @@ services: - db - redis healthcheck: - test: 'curl --header "Host: $[APP_DOMAIN}" --fail http://localhost/api/service/health-check' + test: 'curl --header "Host: ${APP_DOMAIN}" --fail http://localhost/api/service/health-check' interval: "${DOCKER_WEB_HEALTHCHECK_INTERVAL:-10s}" retries: 2 timeout: 5s From f135a240cdf3b7ad64debeb2dde279d4af54ad7e Mon Sep 17 00:00:00 2001 From: Christian Winther Date: Wed, 17 Jan 2024 16:41:01 +0000 Subject: [PATCH 091/173] fix color --- docker/shared/root/docker/helpers.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docker/shared/root/docker/helpers.sh b/docker/shared/root/docker/helpers.sh index 802e21ea5..3f7148c5a 100644 --- a/docker/shared/root/docker/helpers.sh +++ b/docker/shared/root/docker/helpers.sh @@ -8,7 +8,7 @@ set -e -o errexit -o nounset -o pipefail # Some splash of color for important messages declare -g error_message_color="\033[1;31m" -declare -g warn_message_color="\033[1;34m" +declare -g warn_message_color="\033[1;33m" declare -g notice_message_color="\033[1;34m" declare -g success_message_color="\033[1;32m" # shellcheck disable=SC2034 From 068143639f9b01caa4fb729f360b3c4ac44b8fe6 Mon Sep 17 00:00:00 2001 From: Christian Winther Date: Wed, 17 Jan 2024 16:45:05 +0000 Subject: [PATCH 092/173] fix gitignore --- .gitignore | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index ebfef1ace..a5cdf3af1 100644 --- a/.gitignore +++ b/.gitignore @@ -9,7 +9,7 @@ /.idea /.vagrant /.vscode -/docker-compose/ +/docker-compose-state/ /node_modules /public/hot /public/storage From 98bae1316fa505aa4605b0999dbe4d68553613ba Mon Sep 17 00:00:00 2001 From: Christian Winther Date: Wed, 17 Jan 2024 17:51:37 +0000 Subject: [PATCH 093/173] cleanup .env.docker variable names and placement in the file --- .env.docker | 413 ++++++++++-------- docker-compose.migrate.yml | 6 +- docker-compose.yml | 112 ++--- docker/customizing.md | 8 +- docker/faq.md | 4 +- docker/migration.md | 10 +- .../docker/entrypoint.d/01-permissions.sh | 6 +- .../entrypoint.d/11-first-time-setup.sh | 6 +- docker/shared/root/docker/helpers.sh | 2 +- 9 files changed, 308 insertions(+), 259 deletions(-) diff --git a/.env.docker b/.env.docker index 9c440d37e..25914af89 100644 --- a/.env.docker +++ b/.env.docker @@ -1,3 +1,4 @@ +#!/bin/bash # -*- mode: bash -*- # vi: ft=bash @@ -7,19 +8,6 @@ # Pixelfed application configuration ################################################################################ -# The docker tag prefix to use for pulling images, can be one of -# -# * latest -# * -# * staging -# * edge -# * branch- -# * pr- -# -# Combined with [DOCKER_RUNTIME] and [PHP_VERSION] configured -# elsewhere in this file, the final Docker tag is computed. -PIXELFED_RELEASE="branch-jippi-fork" - # A random 32-character string to be used as an encryption key. # # !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! @@ -207,7 +195,7 @@ APP_TIMEZONE="UTC" # Defaults to "Pixelfed - Photo sharing for everyone". # # See: https://docs.pixelfed.org/technical-documentation/config/#instance_description -#INSTANCE_DESCRIPTION= +#INSTANCE_DESCRIPTION="" # Defaults to "false". # @@ -227,7 +215,7 @@ INSTANCE_CONTACT_EMAIL="admin@${APP_DOMAIN}" # Defaults to "". # # See: https://docs.pixelfed.org/technical-documentation/config/#banned_usernames -#BANNED_USERNAMES= +#BANNED_USERNAMES="" # Defaults to "false". # @@ -263,7 +251,7 @@ LETSENCRYPT_EMAIL="__CHANGE_ME__" # Database version to use (as Docker tag) # # See: https://hub.docker.com/_/mariadb -#DB_VERSION="11.2" +DB_VERSION="11.2" # Here you may specify which of the database connections below # you wish to use as your default connection for all database work. @@ -361,12 +349,12 @@ MAIL_FROM_NAME="Pixelfed @ ${APP_DOMAIN}" # Defaults to "". # # See: https://docs.pixelfed.org/technical-documentation/config/#mail_username -#MAIL_USERNAME= +#MAIL_USERNAME="" # Defaults to "". # # See: https://docs.pixelfed.org/technical-documentation/config/#mail_password -#MAIL_PASSWORD= +#MAIL_PASSWORD="" # Here you may specify the encryption protocol that should be used when the application send e-mail messages. # @@ -381,11 +369,6 @@ MAIL_FROM_NAME="Pixelfed @ ${APP_DOMAIN}" # Redis configuration ################################################################################ -# Redis version to use as Docker tag -# -# See: https://hub.docker.com/_/redis -#REDIS_VERSION="7.2" - # Defaults to "phpredis". # # See: https://docs.pixelfed.org/technical-documentation/config/#redis_client @@ -401,17 +384,17 @@ MAIL_FROM_NAME="Pixelfed @ ${APP_DOMAIN}" # See: https://docs.pixelfed.org/technical-documentation/config/#redis_host REDIS_HOST="redis" -# Defaults to null. +# Defaults to null (not set/commented out). # # See: https://docs.pixelfed.org/technical-documentation/config/#redis_password #REDIS_PASSWORD= -# Defaults to 6379. +# Defaults to "6379". # # See: https://docs.pixelfed.org/technical-documentation/config/#redis_port -#REDIS_PORT="6379" +REDIS_PORT="6379" -# Defaults to 0. +# Defaults to "0". # # See: https://docs.pixelfed.org/technical-documentation/config/#redis_database #REDIS_DATABASE="0" @@ -595,26 +578,26 @@ ACTIVITY_PUB="true" #MEDIA_DELETE_LOCAL_AFTER_CLOUD="true" ################################################################################ -# Storage (cloud) - S3 andS S3 *compatible* providers (most of them) +# Storage (cloud) - S3 andS S3 *compatible* providers ################################################################################ # See: https://docs.pixelfed.org/technical-documentation/config/#aws_access_key_id -#AWS_ACCESS_KEY_ID= +#AWS_ACCESS_KEY_ID="" # See: https://docs.pixelfed.org/technical-documentation/config/#aws_secret_access_key -#AWS_SECRET_ACCESS_KEY= +#AWS_SECRET_ACCESS_KEY="" # See: https://docs.pixelfed.org/technical-documentation/config/#aws_default_region -#AWS_DEFAULT_REGION= +#AWS_DEFAULT_REGION="" # See: https://docs.pixelfed.org/technical-documentation/config/#aws_bucket -#AWS_BUCKET= +#AWS_BUCKET="" # See: https://docs.pixelfed.org/technical-documentation/config/#aws_url -#AWS_URL= +#AWS_URL="" # See: https://docs.pixelfed.org/technical-documentation/config/#aws_endpoint -#AWS_ENDPOINT= +#AWS_ENDPOINT="" # See: https://docs.pixelfed.org/technical-documentation/config/#aws_use_path_style_endpoint #AWS_USE_PATH_STYLE_ENDPOINT="false" @@ -625,60 +608,60 @@ ACTIVITY_PUB="true" # Comma-separated list of domains to block. # -# Defaults to null +# Defaults to null (not set/commented out). # # See: https://docs.pixelfed.org/technical-documentation/config/#cs_blocked_domains -#CS_BLOCKED_DOMAINS= +#CS_BLOCKED_DOMAINS="" # Comma-separated list of domains to add warnings. # -# Defaults to null. +# Defaults to null (not set/commented out). # # See: https://docs.pixelfed.org/technical-documentation/config/#cs_cw_domains -#CS_CW_DOMAINS= +#CS_CW_DOMAINS="" # Comma-separated list of domains to remove from public timelines. # -# Defaults to null. +# Defaults to null (not set/commented out). # # See: https://docs.pixelfed.org/technical-documentation/config/#cs_unlisted_domains -#CS_UNLISTED_DOMAINS= +#CS_UNLISTED_DOMAINS="" # Comma-separated list of keywords to block. # -# Defaults to null. +# Defaults to null (not set/commented out). # # See: https://docs.pixelfed.org/technical-documentation/config/#cs_blocked_keywords -#CS_BLOCKED_KEYWORDS= +#CS_BLOCKED_KEYWORDS="" # Comma-separated list of keywords to add warnings. # -# Defaults to null. +# Defaults to null (not set/commented out). # # See: https://docs.pixelfed.org/technical-documentation/config/#cs_cw_keywords -#CS_CW_KEYWORDS= +#CS_CW_KEYWORDS="" # Comma-separated list of keywords to remove from public timelines. # -# Defaults to null. +# Defaults to null (not set/commented out). # # See: https://docs.pixelfed.org/technical-documentation/config/#cs_unlisted_keywords -#CS_UNLISTED_KEYWORDS= +#CS_UNLISTED_KEYWORDS="" -# Defaults to null. +# Defaults to null (not set/commented out). # # See: https://docs.pixelfed.org/technical-documentation/config/#cs_blocked_actor -#CS_BLOCKED_ACTOR= +#CS_BLOCKED_ACTOR="" -# Defaults to null. +# Defaults to null (not set/commented out). # # See: https://docs.pixelfed.org/technical-documentation/config/#cs_cw_actor -#CS_CW_ACTOR= +#CS_CW_ACTOR="" -# Defaults to null. +# Defaults to null (not set/commented out). # # See: https://docs.pixelfed.org/technical-documentation/config/#cs_unlisted_actor -#CS_UNLISTED_ACTOR= +#CS_UNLISTED_ACTOR="" ############################################################### # Media @@ -730,14 +713,14 @@ LOG_CHANNEL="stderr" # Defaults to "". # # See: https://docs.pixelfed.org/technical-documentation/config/#log_stderr_formatter -#LOG_STDERR_FORMATTER= +#LOG_STDERR_FORMATTER="" # Used by slack. # # Defaults to "". # # See: https://docs.pixelfed.org/technical-documentation/config/#log_slack_webhook_url -#LOG_SLACK_WEBHOOK_URL= +#LOG_SLACK_WEBHOOK_URL="" ############################################################### # Broadcasting settings @@ -795,7 +778,7 @@ QUEUE_DRIVER="redis" # Defaults to "https://sqs.us-east-1.amazonaws.com/your-account-id". # # See: https://docs.pixelfed.org/technical-documentation/config/#sqs_prefix -#SQS_PREFIX= +#SQS_PREFIX="" # Defaults to "your-queue-name". # @@ -879,60 +862,18 @@ TRUST_PROXIES="*" # variables when that is more convenient. # See: https://docs.pixelfed.org/technical-documentation/config/#passport_private_key -#PASSPORT_PRIVATE_KEY= +#PASSPORT_PRIVATE_KEY="" # See: https://docs.pixelfed.org/technical-documentation/config/#passport_public_key -#PASSPORT_PUBLIC_KEY= +#PASSPORT_PUBLIC_KEY="" ############################################################### # PHP configuration ############################################################### -# The PHP version to use for [web] and [worker] container -# -# Any version published on https://hub.docker.com/_/php should work -# -# Example: -# -# * 8.1 -# * 8.2 -# * 8.2.14 -# * latest -# -# Do *NOT* use the full Docker tag (e.g. "8.3.2RC1-fpm-bullseye") -# *only* the version part. The rest of the full tag is derived from -# the [DOCKER_RUNTIME] and [PHP_DEBIAN_RELEASE] settings -PHP_VERSION="8.1" - # See: https://www.php.net/manual/en/ini.core.php#ini.memory-limit #PHP_MEMORY_LIMIT="128M" -# The Debian release variant to use of the [php] Docker image -#PHP_DEBIAN_RELEASE="bullseye" - -# The [php] Docker image base type -# -# See: https://github.com/pixelfed/pixelfed/blob/dev/docker/runtimes.md -#PHP_BASE_TYPE="apache" - -# List of extra APT packages (separated by space) to install when building -# locally using [docker compose build]. -# -# See: https://github.com/pixelfed/pixelfed/blob/dev/docker/customizing.md -#APT_PACKAGES_EXTRA="" - -# List of *extra* PECL extensions (separated by space) to install when -# building locally using [docker compose build]. -# -# See: https://github.com/pixelfed/pixelfed/blob/dev/docker/customizing.md -#PHP_PECL_EXTENSIONS_EXTRA="" - -# List of *extra* PHP extensions (separated by space) to install when -# building locally using [docker compose build]. -# -# See: https://github.com/pixelfed/pixelfed/blob/dev/docker/customizing.md -#PHP_EXTENSIONS_EXTRA="" - ################################################################################ # Other configuration ################################################################################ @@ -951,9 +892,64 @@ PHP_VERSION="8.1" TZ="${APP_TIMEZONE}" ################################################################################ -# Docker Specific configuration +# Docker configuraton for *all* services ################################################################################ +# Prefix for container names (without any dash at the end) +DOCKER_ALL_CONTAINER_NAME_PREFIX="${APP_DOMAIN}" + +# How often Docker health check should run for all services +# +# Can be overridden by individual [DOCKER_*_HEALTHCHECK_INTERVAL] settings further down +DOCKER_ALL_DEFAULT_HEALTHCHECK_INTERVAL="10s" + +# Path (relative to the docker-compose.yml) or absolute (/some/other/path) where containers will store their data +DOCKER_ALL_HOST_DATA_ROOT_PATH="./docker-compose-state/data" + +# Path (relative to the docker-compose.yml) or absolute (/some/other/path) where containers will store their confguration +DOCKER_ALL_HOST_CONFIG_ROOT_PATH="./docker-compose-state/config" + +################################################################################ +# Docker [web] + [worker] (also know as "app") shared service configuration +################################################################################ + +# The docker tag prefix to use for pulling images, can be one of +# +# * latest +# * +# * staging +# * edge +# * branch- +# * pr- +# +# Combined with [DOCKER_APP_RUNTIME] and [PHP_VERSION] configured +# elsewhere in this file, the final Docker tag is computed. +DOCKER_APP_RELEASE="branch-jippi-fork" + +# The PHP version to use for [web] and [worker] container +# +# Any version published on https://hub.docker.com/_/php should work +# +# Example: +# +# * 8.1 +# * 8.2 +# * 8.2.14 +# * latest +# +# Do *NOT* use the full Docker tag (e.g. "8.3.2RC1-fpm-bullseye") +# *only* the version part. The rest of the full tag is derived from +# the [DOCKER_APP_RUNTIME] and [PHP_DEBIAN_RELEASE] settings +DOCKER_APP_PHP_VERSION="8.2" + +# The [php] Docker image base type +# +# See: https://github.com/pixelfed/pixelfed/blob/dev/docker/runtimes.md +DOCKER_APP_BASE_TYPE="apache" + +# The Debian release variant to use of the [php] Docker image +DOCKER_APP_DEBIAN_RELEASE="bullseye" + # Image to pull the Pixelfed Docker images from. # # Example values: @@ -962,103 +958,29 @@ TZ="${APP_TIMEZONE}" # * "pixelfed/pixelfed" to pull from DockerHub # * "your/fork" to pull from a custom fork # -DOCKER_IMAGE="ghcr.io/jippi/pixelfed" +DOCKER_APP_IMAGE="ghcr.io/jippi/pixelfed" # The container runtime to use. # # See: https://github.com/jippi/pixelfed/blob/jippi-fork/docker/runtimes.md -DOCKER_RUNTIME="apache" +DOCKER_APP_RUNTIME="apache" # Pixelfed version (image tag) to pull from the registry. # # See: https://github.com/pixelfed/pixelfed/pkgs/container/pixelfed -DOCKER_TAG="${PIXELFED_RELEASE}-${DOCKER_RUNTIME}-${PHP_VERSION}" - -# Path (relative to the docker-compose.yml) or absolute (/some/other/path) where containers will store their data -DOCKER_DATA_ROOT="./docker-compose-state/data" - -# Path (relative to the docker-compose.yml) or absolute (/some/other/path) where containers will store their confguration -DOCKER_CONFIG_ROOT="./docker-compose-state/config" - -# Path (on host system) where the [db] container will store its data -# -# Path is relative (./some/other/path) to the docker-compose.yml or absolute (/some/other/path) -DOCKER_DB_DATA_PATH="${DOCKER_DATA_ROOT}/db" - -# Path (on host system) where the [redis] container will store its data -# -# Path is relative (./some/other/path) to the docker-compose.yml or absolute (/some/other/path) -DOCKER_REDIS_DATA_PATH="${DOCKER_DATA_ROOT}/redis" +DOCKER_APP_TAG="${DOCKER_APP_RELEASE}-${DOCKER_APP_RUNTIME}-${DOCKER_APP_PHP_VERSION}" # Path (on host system) where the [app] + [worker] container will write # its [storage] data (e.g uploads/images/profile pictures etc.). # # Path is relative (./some/other/path) to the docker-compose.yml or absolute (/some/other/path) -DOCKER_APP_STORAGE_PATH="${DOCKER_DATA_ROOT}/pixelfed/storage" +DOCKER_APP_HOST_STORAGE_PATH="${DOCKER_ALL_HOST_DATA_ROOT_PATH}/pixelfed/storage" # Path (on host system) where the [app] + [worker] container will write # its [cache] data. # # Path is relative (./some/other/path) to the docker-compose.yml or absolute (/some/other/path) -DOCKER_APP_CACHE_PATH="${DOCKER_DATA_ROOT}/pixelfed/cache" - -# How often Docker health check should run for all services -# -# Can be overridden by individual [DOCKER_*_HEALTHCHECK_INTERVAL] settings further down -DOCKER_DEFAULT_HEALTHCHECK_INTERVAL="10s" - -# Port that Redis will listen on *outside* the container (e.g. the host machine) -DOCKER_REDIS_PORT_EXTERNAL="${REDIS_PORT:-6379}" - -# The filename that Redis should store its config file within -# -# NOTE: The file *MUST* exists (even empty) before enabling this setting! -# -# Use a command like [touch "${DOCKER_CONFIG_ROOT}/redis/redis.conf"] to create it. -# -# Defaults to "" -#DOCKER_REDIS_CONFIG_FILE="/etc/redis/redis.conf" - -# How often Docker health check should run for [redis] service -DOCKER_REDIS_HEALTHCHECK_INTERVAL="${DOCKER_DEFAULT_HEALTHCHECK_INTERVAL}" - -# Port that the database will listen on *outside* the container (e.g. the host machine) -# -# Use "3306" for MySQL/MariaDB and "5432" for PostgreeSQL -DOCKER_DB_PORT_EXTERNAL="${DB_PORT}" - -# How often Docker health check should run for [db] service -DOCKER_DB_HEALTHCHECK_INTERVAL="${DOCKER_DEFAULT_HEALTHCHECK_INTERVAL}" - -# Port that the [proxy] will listen on *outside* the container (e.g. the host machine) for HTTP traffic -DOCKER_PROXY_PORT_EXTERNAL_HTTP="80" - -# Port that the [proxy] will listen on *outside* the container (e.g. the host machine) for HTTPS traffic -DOCKER_PROXY_PORT_EXTERNAL_HTTPS="443" - -# Port to expose [web] container will listen on *outside* the container (e.g. the host machine) for *HTTP* traffic only -DOCKER_WEB_PORT_EXTERNAL_HTTP="8080" - -# How often Docker health check should run for [web] service -DOCKER_WEB_HEALTHCHECK_INTERVAL="${DOCKER_DEFAULT_HEALTHCHECK_INTERVAL}" - -# How often Docker health check should run for [worker] service -DOCKER_WORKER_HEALTHCHECK_INTERVAL="${DOCKER_DEFAULT_HEALTHCHECK_INTERVAL}" - -# Path to the Docker socket on the *host* -DOCKER_HOST_SOCKET_PATH="/var/run/docker.sock" - -# Prefix for container names (without any dash at the end) -DOCKER_CONTAINER_NAME_PREFIX="${APP_DOMAIN}" - -# Set this to a non-empty value (e.g. "disabled") to disable the [proxy] and [proxy-acme] service -DOCKER_PROXY_PROFILE="" - -# Set this to a non-empty value (e.g. "disabled") to disable the [proxy-acme] service -DOCKER_PROXY_ACME_PROFILE="${DOCKER_PROXY_PROFILE}" - -# How often Docker health check should run for [proxy] service -DOCKER_PROXY_HEALTHCHECK_INTERVAL="${DOCKER_DEFAULT_HEALTHCHECK_INTERVAL}" +DOCKER_APP_HOST_CACHE_PATH="${DOCKER_ALL_HOST_DATA_ROOT_PATH}/pixelfed/cache" # Automatically run "One-time setup tasks" commands. # @@ -1067,7 +989,7 @@ DOCKER_PROXY_HEALTHCHECK_INTERVAL="${DOCKER_DEFAULT_HEALTHCHECK_INTERVAL}" # you can set this to "0" to prevent them from running. # # Otherwise, leave it at "1" to have them run *once*. -#DOCKER_RUN_ONE_TIME_SETUP_TASKS="1" +#DOCKER_APP_RUN_ONE_TIME_SETUP_TASKS="1" # A space-seperated list of paths (inside the container) to *recursively* [chown] # to the container user/group id (UID/GID) in case of permission issues. @@ -1077,14 +999,135 @@ DOCKER_PROXY_HEALTHCHECK_INTERVAL="${DOCKER_DEFAULT_HEALTHCHECK_INTERVAL}" # ! issues. Please report a bug if you see behavior requiring this to be permanently on # # Example: "/var/www/storage /var/www/bootstrap/cache" -#DOCKER_ENSURE_OWNERSHIP_PATHS="" +#DOCKER_APP_ENSURE_OWNERSHIP_PATHS="" # Enable Docker Entrypoint debug mode (will call [set -x] in bash scripts) # by setting this to "1". -#ENTRYPOINT_DEBUG="0" +#DOCKER_APP_ENTRYPOINT_DEBUG="0" + +# List of extra APT packages (separated by space) to install when building +# locally using [docker compose build]. +# +# See: https://github.com/pixelfed/pixelfed/blob/dev/docker/customizing.md +#DOCKER_APP_APT_PACKAGES_EXTRA="" + +# List of *extra* PECL extensions (separated by space) to install when +# building locally using [docker compose build]. +# +# See: https://github.com/pixelfed/pixelfed/blob/dev/docker/customizing.md +#DOCKER_APP_PHP_PECL_EXTENSIONS_EXTRA="" + +# List of *extra* PHP extensions (separated by space) to install when +# building locally using [docker compose build]. +# +# See: https://github.com/pixelfed/pixelfed/blob/dev/docker/customizing.md +#DOCKER_APP_PHP_EXTENSIONS_EXTRA="" ################################################################################ -# MySQL DB container configuration +# Docker [redis] service configuration +################################################################################ + +# Redis version to use as Docker tag +# +# See: https://hub.docker.com/_/redis +DOCKER_REDIS_VERSION="7.2" + +# Path (on host system) where the [redis] container will store its data +# +# Path is relative (./some/other/path) to the docker-compose.yml or absolute (/some/other/path) +DOCKER_REDIS_HOST_DATA_PATH="${DOCKER_ALL_HOST_DATA_ROOT_PATH}/redis" + +# Port that Redis will listen on *outside* the container (e.g. the host machine) +DOCKER_REDIS_HOST_PORT="${REDIS_PORT}" + +# The filename that Redis should store its config file within +# +# NOTE: The file *MUST* exists (even empty) before enabling this setting! +# +# Use a command like [touch "${DOCKER_ALL_HOST_CONFIG_ROOT_PATH}/redis/redis.conf"] to create it. +# +# Defaults to "" +#DOCKER_REDIS_CONFIG_FILE="/etc/redis/redis.conf" + +# How often Docker health check should run for [redis] service +# +# Defaults to "10s" +DOCKER_REDIS_HEALTHCHECK_INTERVAL="${DOCKER_ALL_DEFAULT_HEALTHCHECK_INTERVAL}" + +################################################################################ +# Docker [db] service configuration +################################################################################ + +# Set this to a non-empty value (e.g. "disabled") to disable the [db] service +#DOCKER_DB_PROFILE="" + +# Path (on host system) where the [db] container will store its data +# +# Path is relative (./some/other/path) to the docker-compose.yml or absolute (/some/other/path) +DOCKER_DB_HOST_DATA_PATH="${DOCKER_ALL_HOST_DATA_ROOT_PATH}/db" + +# Port that the database will listen on *outside* the container (e.g. the host machine) +# +# Use "3306" for MySQL/MariaDB and "5432" for PostgreeSQL +DOCKER_DB_HOST_PORT="${DB_PORT}" + +# How often Docker health check should run for [db] service +DOCKER_DB_HEALTHCHECK_INTERVAL="${DOCKER_ALL_DEFAULT_HEALTHCHECK_INTERVAL}" + +################################################################################ +# Docker [web] service configuration +################################################################################ + +# Set this to a non-empty value (e.g. "disabled") to disable the [web] service +#DOCKER_WEB_PROFILE="" + +# Port to expose [web] container will listen on *outside* the container (e.g. the host machine) for *HTTP* traffic only +DOCKER_WEB_PORT_EXTERNAL_HTTP="8080" + +# How often Docker health check should run for [web] service +DOCKER_WEB_HEALTHCHECK_INTERVAL="${DOCKER_ALL_DEFAULT_HEALTHCHECK_INTERVAL}" + +################################################################################ +# Docker [worker] service configuration +################################################################################ + +# Set this to a non-empty value (e.g. "disabled") to disable the [worker] service +#DOCKER_WORKER_PROFILE="" + +# How often Docker health check should run for [worker] service +DOCKER_WORKER_HEALTHCHECK_INTERVAL="${DOCKER_ALL_DEFAULT_HEALTHCHECK_INTERVAL}" + +################################################################################ +# Docker [proxy] + [proxy-acme] service configuration +################################################################################ + +# Set this to a non-empty value (e.g. "disabled") to disable the [proxy] and [proxy-acme] service +#DOCKER_PROXY_PROFILE="" + +# Set this to a non-empty value (e.g. "disabled") to disable the [proxy-acme] service +#DOCKER_PROXY_ACME_PROFILE="${DOCKER_PROXY_PROFILE:-}" + +# How often Docker health check should run for [proxy] service +DOCKER_PROXY_HEALTHCHECK_INTERVAL="${DOCKER_ALL_DEFAULT_HEALTHCHECK_INTERVAL}" + +# Port that the [proxy] will listen on *outside* the container (e.g. the host machine) for HTTP traffic +DOCKER_PROXY_HOST_PORT_HTTP="80" + +# Port that the [proxy] will listen on *outside* the container (e.g. the host machine) for HTTPS traffic +DOCKER_PROXY_HOST_PORT_HTTPS="443" + +# Path to the Docker socket on the *host* +DOCKER_PROXY_HOST_DOCKER_SOCKET_PATH="/var/run/docker.sock" + +# ! ---------------------------------------------------------------------------- +# ! STOP STOP STOP STOP STOP STOP STOP STOP STOP STOP STOP STOP STOP STOP STOP +# ! ---------------------------------------------------------------------------- +# ! Below this line is default environment variables for various [db] backends +# ! You very likely do *NOT* need to modify any of this, ever. +# ! ---------------------------------------------------------------------------- + +################################################################################ +# Docker [db] service environment variables for MySQL (Oracle) ################################################################################ # # See "Environment Variables" at https://hub.docker.com/_/mysql @@ -1097,7 +1140,7 @@ MYSQL_PASSWORD="${DB_PASSWORD}" MYSQL_DATABASE="${DB_DATABASE}" ################################################################################ -# MySQL (MariaDB) DB container configuration +# Docker [db] service environment variables for MySQL (MariaDB) ################################################################################ # # See "Start a mariadb server instance with user, password and database" @@ -1111,7 +1154,7 @@ MARIADB_PASSWORD="${DB_PASSWORD}" MARIADB_DATABASE="${DB_DATABASE}" ################################################################################ -# PostgreSQL DB container configuration +# Docker [db] service environment variables for PostgreSQL ################################################################################ # # See "Environment Variables" at https://hub.docker.com/_/postgres diff --git a/docker-compose.migrate.yml b/docker-compose.migrate.yml index b47abeb48..b31771f27 100644 --- a/docker-compose.migrate.yml +++ b/docker-compose.migrate.yml @@ -15,7 +15,7 @@ services: # OLD - "app-storage:/migrate/app-storage/old" # NEW - - "${DOCKER_APP_STORAGE_PATH}:/migrate/app-storage/new" + - "${DOCKER_APP_HOST_STORAGE_PATH}:/migrate/app-storage/new" ################################ # MySQL/DB volume @@ -23,7 +23,7 @@ services: # OLD - "db-data:/migrate/db-data/old" # NEW - - "${DOCKER_DB_DATA_PATH}:/migrate/db-data/new" + - "${DOCKER_DB_HOST_DATA_PATH}:/migrate/db-data/new" ################################ # Redis volume @@ -31,7 +31,7 @@ services: # OLD - "redis-data:/migrate/redis-data/old" # NEW - - "${DOCKER_REDIS_DATA_PATH}:/migrate/redis-data/new" + - "${DOCKER_REDIS_HOST_DATA_PATH}:/migrate/redis-data/new" # Volumes from the old [docker-compose.yml] file # https://github.com/pixelfed/pixelfed/blob/b1ff44ca2f75c088a11576fb03b5bad2fbed4d5c/docker-compose.yml#L72-L76 diff --git a/docker-compose.yml b/docker-compose.yml index 88e2b692d..a3516f7ee 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -20,22 +20,22 @@ services: # See: https://github.com/nginx-proxy/nginx-proxy/tree/main/docs proxy: image: nginxproxy/nginx-proxy:1.4 - container_name: "${DOCKER_CONTAINER_NAME_PREFIX}-proxy" + container_name: "${DOCKER_ALL_CONTAINER_NAME_PREFIX}-proxy" restart: unless-stopped profiles: - ${DOCKER_PROXY_PROFILE:-} volumes: - - "${DOCKER_HOST_SOCKET_PATH}:/tmp/docker.sock:ro" - - "${DOCKER_CONFIG_ROOT}/proxy/conf.d:/etc/nginx/conf.d" - - "${DOCKER_CONFIG_ROOT}/proxy/vhost.d:/etc/nginx/vhost.d" - - "${DOCKER_CONFIG_ROOT}/proxy/certs:/etc/nginx/certs" - - "${DOCKER_DATA_ROOT}/proxy/html:/usr/share/nginx/html" + - "${DOCKER_PROXY_HOST_DOCKER_SOCKET_PATH}:/tmp/docker.sock:ro" + - "${DOCKER_ALL_HOST_CONFIG_ROOT_PATH}/proxy/conf.d:/etc/nginx/conf.d" + - "${DOCKER_ALL_HOST_CONFIG_ROOT_PATH}/proxy/vhost.d:/etc/nginx/vhost.d" + - "${DOCKER_ALL_HOST_CONFIG_ROOT_PATH}/proxy/certs:/etc/nginx/certs" + - "${DOCKER_ALL_HOST_DATA_ROOT_PATH}/proxy/html:/usr/share/nginx/html" ports: - - "${DOCKER_PROXY_PORT_EXTERNAL_HTTP}:80" - - "${DOCKER_PROXY_PORT_EXTERNAL_HTTPS}:443" + - "${DOCKER_PROXY_HOST_PORT_HTTP}:80" + - "${DOCKER_PROXY_HOST_PORT_HTTPS}:443" healthcheck: test: "curl --fail https://${APP_DOMAIN}/api/service/health-check" - interval: "${DOCKER_PROXY_HEALTHCHECK_INTERVAL:-10s}" + interval: "${DOCKER_PROXY_HEALTHCHECK_INTERVAL}" retries: 2 timeout: 5s @@ -47,41 +47,43 @@ services: # See: https://github.com/nginx-proxy/acme-companion/tree/main/docs proxy-acme: image: nginxproxy/acme-companion - container_name: "${DOCKER_CONTAINER_NAME_PREFIX}-proxy-acme" + container_name: "${DOCKER_ALL_CONTAINER_NAME_PREFIX}-proxy-acme" restart: unless-stopped profiles: - ${DOCKER_PROXY_ACME_PROFILE:-} environment: DEBUG: 0 DEFAULT_EMAIL: "${LETSENCRYPT_EMAIL}" - NGINX_PROXY_CONTAINER: "${DOCKER_CONTAINER_NAME_PREFIX}-proxy" + NGINX_PROXY_CONTAINER: "${DOCKER_ALL_CONTAINER_NAME_PREFIX}-proxy" depends_on: - proxy volumes: - - "${DOCKER_CONFIG_ROOT}/proxy-acme:/etc/acme.sh" - - "${DOCKER_CONFIG_ROOT}/proxy/certs:/etc/nginx/certs" - - "${DOCKER_CONFIG_ROOT}/proxy/conf.d:/etc/nginx/conf.d" - - "${DOCKER_CONFIG_ROOT}/proxy/vhost.d:/etc/nginx/vhost.d" - - "${DOCKER_DATA_ROOT}/proxy/html:/usr/share/nginx/html" - - "${DOCKER_HOST_SOCKET_PATH}:/var/run/docker.sock:ro" + - "${DOCKER_ALL_HOST_CONFIG_ROOT_PATH}/proxy-acme:/etc/acme.sh" + - "${DOCKER_ALL_HOST_CONFIG_ROOT_PATH}/proxy/certs:/etc/nginx/certs" + - "${DOCKER_ALL_HOST_CONFIG_ROOT_PATH}/proxy/conf.d:/etc/nginx/conf.d" + - "${DOCKER_ALL_HOST_CONFIG_ROOT_PATH}/proxy/vhost.d:/etc/nginx/vhost.d" + - "${DOCKER_ALL_HOST_DATA_ROOT_PATH}/proxy/html:/usr/share/nginx/html" + - "${DOCKER_PROXY_HOST_DOCKER_SOCKET_PATH}:/var/run/docker.sock:ro" web: - image: "${DOCKER_IMAGE}:${DOCKER_TAG}" - container_name: "${DOCKER_CONTAINER_NAME_PREFIX}-web" + image: "${DOCKER_APP_IMAGE}:${DOCKER_APP_TAG}" + container_name: "${DOCKER_ALL_CONTAINER_NAME_PREFIX}-web" restart: unless-stopped + profiles: + - ${DOCKER_WEB_PROFILE:-} build: - target: ${DOCKER_RUNTIME}-runtime + target: ${DOCKER_APP_RUNTIME}-runtime args: - PHP_VERSION: "${PHP_VERSION:-8.1}" - PHP_BASE_TYPE: "${PHP_BASE_TYPE:-apache}" - PHP_DEBIAN_RELEASE: "${PHP_DEBIAN_RELEASE:-bullseye}" - APT_PACKAGES_EXTRA: "${APT_PACKAGES_EXTRA:-}" - PHP_PECL_EXTENSIONS_EXTRA: "${PHP_PECL_EXTENSIONS_EXTRA:-}" - PHP_EXTENSIONS_EXTRA: "${PHP_EXTENSIONS_EXTRA:-}" + PHP_VERSION: "${DOCKER_APP_PHP_VERSION}" + PHP_BASE_TYPE: "${DOCKER_APP_BASE_TYPE}" + PHP_DEBIAN_RELEASE: "${DOCKER_APP_DEBIAN_RELEASE}" + APT_PACKAGES_EXTRA: "${DOCKER_APP_APT_PACKAGES_EXTRA:-}" + PHP_PECL_EXTENSIONS_EXTRA: "${DOCKER_APP_PHP_PECL_EXTENSIONS_EXTRA:-}" + PHP_EXTENSIONS_EXTRA: "${DOCKER_APP_PHP_EXTENSIONS_EXTRA:-}" volumes: - "./.env:/var/www/.env" - - "${DOCKER_APP_CACHE_PATH}:/var/www/bootstrap/cache" - - "${DOCKER_APP_STORAGE_PATH}:/var/www/storage" + - "${DOCKER_APP_HOST_CACHE_PATH}:/var/www/bootstrap/cache" + - "${DOCKER_APP_HOST_STORAGE_PATH}:/var/www/storage" environment: LETSENCRYPT_HOST: "${LETSENCRYPT_HOST}" LETSENCRYPT_EMAIL: "${LETSENCRYPT_EMAIL}" @@ -93,54 +95,58 @@ services: com.github.nginx-proxy.nginx-proxy.http2.enable: true com.github.nginx-proxy.nginx-proxy.http3.enable: true ports: - - "${DOCKER_WEB_PORT_EXTERNAL_HTTP:-8080}:80" + - "${DOCKER_WEB_PORT_EXTERNAL_HTTP}:80" depends_on: - db - redis healthcheck: test: 'curl --header "Host: ${APP_DOMAIN}" --fail http://localhost/api/service/health-check' - interval: "${DOCKER_WEB_HEALTHCHECK_INTERVAL:-10s}" + interval: "${DOCKER_WEB_HEALTHCHECK_INTERVAL}" retries: 2 timeout: 5s worker: - image: "${DOCKER_IMAGE}:${DOCKER_TAG}" - container_name: "${DOCKER_CONTAINER_NAME_PREFIX}-worker" + image: "${DOCKER_APP_IMAGE}:${DOCKER_APP_TAG}" + container_name: "${DOCKER_ALL_CONTAINER_NAME_PREFIX}-worker" command: gosu www-data php artisan horizon restart: unless-stopped + profiles: + - ${DOCKER_WORKER_PROFILE:-} build: - target: ${DOCKER_RUNTIME}-runtime + target: ${DOCKER_APP_RUNTIME}-runtime args: - PHP_VERSION: "${PHP_VERSION:-8.1}" - PHP_BASE_TYPE: "${PHP_BASE_TYPE:-apache}" - PHP_DEBIAN_RELEASE: "${PHP_DEBIAN_RELEASE:-bullseye}" - APT_PACKAGES_EXTRA: "${APT_PACKAGES_EXTRA:-}" - PHP_PECL_EXTENSIONS_EXTRA: "${PHP_PECL_EXTENSIONS_EXTRA:-}" - PHP_EXTENSIONS_EXTRA: "${PHP_EXTENSIONS_EXTRA:-}" + PHP_VERSION: "${DOCKER_APP_PHP_VERSION}" + PHP_BASE_TYPE: "${DOCKER_APP_BASE_TYPE}" + PHP_DEBIAN_RELEASE: "${DOCKER_APP_DEBIAN_RELEASE}" + APT_PACKAGES_EXTRA: "${DOCKER_APP_APT_PACKAGES_EXTRA:-}" + PHP_PECL_EXTENSIONS_EXTRA: "${DOCKER_APP_PHP_PECL_EXTENSIONS_EXTRA:-}" + PHP_EXTENSIONS_EXTRA: "${DOCKER_APP_PHP_EXTENSIONS_EXTRA:-}" volumes: - "./.env:/var/www/.env" - - "${DOCKER_APP_CACHE_PATH}:/var/www/bootstrap/cache" - - "${DOCKER_APP_STORAGE_PATH}:/var/www/storage" + - "${DOCKER_APP_HOST_CACHE_PATH}:/var/www/bootstrap/cache" + - "${DOCKER_APP_HOST_STORAGE_PATH}:/var/www/storage" depends_on: - db - redis healthcheck: test: gosu www-data php artisan horizon:status | grep running - interval: "${DOCKER_WORKER_HEALTHCHECK_INTERVAL:-10s}" + interval: "${DOCKER_WORKER_HEALTHCHECK_INTERVAL}" timeout: 5s retries: 2 db: - image: mariadb:${DB_VERSION:-11.2} - container_name: "${DOCKER_CONTAINER_NAME_PREFIX}-db" + image: mariadb:${DB_VERSION} + container_name: "${DOCKER_ALL_CONTAINER_NAME_PREFIX}-db" command: --default-authentication-plugin=mysql_native_password restart: unless-stopped + profiles: + - ${DOCKER_DB_PROFILE:-} env_file: - ".env" volumes: - - "${DOCKER_DB_DATA_PATH}:/var/lib/mysql" + - "${DOCKER_DB_HOST_DATA_PATH}:/var/lib/mysql" ports: - - "${DOCKER_DB_PORT_EXTERNAL}:3306" + - "${DOCKER_DB_HOST_PORT}:3306" healthcheck: test: [ @@ -150,13 +156,13 @@ services: "--connect", "--innodb_initialized", ] - interval: "${DOCKER_DB_HEALTHCHECK_INTERVAL:-10s}" + interval: "${DOCKER_DB_HEALTHCHECK_INTERVAL}" retries: 2 timeout: 5s redis: - image: redis:${REDIS_VERSION:-7.2} - container_name: "${DOCKER_CONTAINER_NAME_PREFIX}-redis" + image: redis:${DOCKER_REDIS_VERSION} + container_name: "${DOCKER_ALL_CONTAINER_NAME_PREFIX}-redis" restart: unless-stopped command: "${DOCKER_REDIS_CONFIG_FILE:-} --requirepass '${REDIS_PASSWORD:-}'" environment: @@ -164,12 +170,12 @@ services: env_file: - ".env" volumes: - - "${DOCKER_CONFIG_ROOT}/redis:/etc/redis" - - "${DOCKER_REDIS_DATA_PATH}:/data" + - "${DOCKER_ALL_HOST_CONFIG_ROOT_PATH}/redis:/etc/redis" + - "${DOCKER_REDIS_HOST_DATA_PATH}:/data" ports: - - "${DOCKER_REDIS_PORT_EXTERNAL}:6379" + - "${DOCKER_REDIS_HOST_PORT}:6379" healthcheck: test: ["CMD", "redis-cli", "-p", "6379", "ping"] - interval: "${DOCKER_REDIS_HEALTHCHECK_INTERVAL:-10s}" + interval: "${DOCKER_REDIS_HEALTHCHECK_INTERVAL}" retries: 2 timeout: 5s diff --git a/docker/customizing.md b/docker/customizing.md index dcea45d3d..e7c66e842 100644 --- a/docker/customizing.md +++ b/docker/customizing.md @@ -15,7 +15,7 @@ When a Pixelfed container starts up, the [`ENTRYPOINT`](https://docs.docker.com/ ### Debugging -You can set environment variable `ENTRYPOINT_DEBUG=1` to show verbose output of what each `entrypoint.d` script is doing. +You can set environment variable `DOCKER_APP_ENTRYPOINT_DEBUG=1` to show verbose output of what each `entrypoint.d` script is doing. You can also `docker exec` or `docker run` into a container and run `/` @@ -73,12 +73,12 @@ Please see the ## Fixing ownership on startup -You can set the environment variable `DOCKER_ENSURE_OWNERSHIP_PATHS` to a list of paths that should have their `$USER` and `$GROUP` ownership changed to the configured runtime user and group during container bootstrapping. +You can set the environment variable `DOCKER_APP_ENSURE_OWNERSHIP_PATHS` to a list of paths that should have their `$USER` and `$GROUP` ownership changed to the configured runtime user and group during container bootstrapping. The variable is a space-delimited list shown below and accepts both relative and absolute paths: -* `DOCKER_ENSURE_OWNERSHIP_PATHS="./storage ./bootstrap"` -* `DOCKER_ENSURE_OWNERSHIP_PATHS="/some/other/folder"` +* `DOCKER_APP_ENSURE_OWNERSHIP_PATHS="./storage ./bootstrap"` +* `DOCKER_APP_ENSURE_OWNERSHIP_PATHS="/some/other/folder"` ## Build settings (arguments) diff --git a/docker/faq.md b/docker/faq.md index cc2495d15..bbd47fcf5 100644 --- a/docker/faq.md +++ b/docker/faq.md @@ -19,7 +19,7 @@ No problem! All you have to do is: 1. Change the `DOCKER_PROXY_ACME_PROFILE` key/value pair in your `.env` file to `"disabled"`. * This disabled the `proxy-acme` service in `docker-compose.yml`. * It does *not* disable the `proxy` service. -1. Put your certificates in `${DOCKER_CONFIG_ROOT}/proxy/certs` (e.g. `./docker-compose/config/proxy/certs`) +1. Put your certificates in `${DOCKER_ALL_HOST_CONFIG_ROOT_PATH}/proxy/certs` (e.g. `./docker-compose/config/proxy/certs`) * You may need to create this folder manually if it does not exists. * The following files are expected to exist in the directory for the proxy to detect and use them automatically (this is the same directory and file names as LetsEncrypt uses) 1. `${APP_DOMAIN}.cert.pem` @@ -31,4 +31,4 @@ No problem! All you have to do is: ## How do I change the container name prefix? -Change the `DOCKER_CONTAINER_NAME_PREFIX` key/value pair in your `.env` file. +Change the `DOCKER_ALL_CONTAINER_NAME_PREFIX` key/value pair in your `.env` file. diff --git a/docker/migration.md b/docker/migration.md index 4b0467ddd..458be4321 100644 --- a/docker/migration.md +++ b/docker/migration.md @@ -61,8 +61,8 @@ In *particular* the following sections * The `PHP_VERSION` settings controls your PHP version * The `PHP_MEMORY_LIMIT` settings controls your PHP memory limit * `Docker Specific configuration` section (near the end of the file) where - * The `DOCKER_DATA_ROOT` setting dictate where the new migrated data will live. - * The `DOCKER_RUN_ONE_TIME_SETUP_TASKS` controls if the `One time setup tasks` should run or not. We do *not* want this, since your Pixelfed instance already is set up! + * The `DOCKER_ALL_HOST_DATA_ROOT_PATH` setting dictate where the new migrated data will live. + * The `DOCKER_APP_RUN_ONE_TIME_SETUP_TASKS` controls if the `One time setup tasks` should run or not. We do *not* want this, since your Pixelfed instance already is set up! * [Frequently Asked Question / FAQ](faq.md) * [How do I use my own Proxy server?](faq.md#how-do-i-use-my-own-proxy-server) * [How do I use my own SSL certificate?](faq.md#how-do-i-use-my-own-ssl-certificate) @@ -232,9 +232,9 @@ If the worker is crash looping, inspect the logs and try to resolve the issues. You can consider the following additional steps: -* Enabling `ENTRYPOINT_DEBUG` which will show even more log output to help understand whats going on -* Enabling `DOCKER_ENSURE_OWNERSHIP_PATHS` against the path(s) that might have permission issues -* Fixing permission issues directly on the host since your data should all be in the `${DOCKER_DATA_ROOT}` folder (`./docker-compose-state/data` by default) +* Enabling `DOCKER_APP_ENTRYPOINT_DEBUG` which will show even more log output to help understand whats going on +* Enabling `DOCKER_APP_ENSURE_OWNERSHIP_PATHS` against the path(s) that might have permission issues +* Fixing permission issues directly on the host since your data should all be in the `${DOCKER_ALL_HOST_DATA_ROOT_PATH}` folder (`./docker-compose-state/data` by default) ##### Web diff --git a/docker/shared/root/docker/entrypoint.d/01-permissions.sh b/docker/shared/root/docker/entrypoint.d/01-permissions.sh index 287d708aa..11766a742 100755 --- a/docker/shared/root/docker/entrypoint.d/01-permissions.sh +++ b/docker/shared/root/docker/entrypoint.d/01-permissions.sh @@ -13,13 +13,13 @@ run-as-current-user chown --verbose "${RUNTIME_UID}:${RUNTIME_GID}" "./bootstrap run-as-current-user chown --verbose "${RUNTIME_UID}:${RUNTIME_GID}" "./storage" # Optionally fix ownership of configured paths -: "${DOCKER_ENSURE_OWNERSHIP_PATHS:=""}" +: "${DOCKER_APP_ENSURE_OWNERSHIP_PATHS:=""}" declare -a ensure_ownership_paths=() -IFS=' ' read -ar ensure_ownership_paths <<<"${DOCKER_ENSURE_OWNERSHIP_PATHS}" +IFS=' ' read -ar ensure_ownership_paths <<<"${DOCKER_APP_ENSURE_OWNERSHIP_PATHS}" if [[ ${#ensure_ownership_paths[@]} == 0 ]]; then - log-info "No paths has been configured for ownership fixes via [\$DOCKER_ENSURE_OWNERSHIP_PATHS]." + log-info "No paths has been configured for ownership fixes via [\$DOCKER_APP_ENSURE_OWNERSHIP_PATHS]." exit 0 fi diff --git a/docker/shared/root/docker/entrypoint.d/11-first-time-setup.sh b/docker/shared/root/docker/entrypoint.d/11-first-time-setup.sh index a3582932b..d3d83c532 100755 --- a/docker/shared/root/docker/entrypoint.d/11-first-time-setup.sh +++ b/docker/shared/root/docker/entrypoint.d/11-first-time-setup.sh @@ -7,11 +7,11 @@ source "${ENTRYPOINT_ROOT}/helpers.sh" entrypoint-set-script-name "$0" # Allow automatic applying of outstanding/new migrations on startup -: "${DOCKER_RUN_ONE_TIME_SETUP_TASKS:=1}" +: "${DOCKER_APP_RUN_ONE_TIME_SETUP_TASKS:=1}" -if is-false "${DOCKER_RUN_ONE_TIME_SETUP_TASKS}"; then +if is-false "${DOCKER_APP_RUN_ONE_TIME_SETUP_TASKS}"; then log-warning "Automatic run of the 'One-time setup tasks' is disabled." - log-warning "Please set [DOCKER_RUN_ONE_TIME_SETUP_TASKS=1] in your [.env] file to enable this." + log-warning "Please set [DOCKER_APP_RUN_ONE_TIME_SETUP_TASKS=1] in your [.env] file to enable this." exit 0 fi diff --git a/docker/shared/root/docker/helpers.sh b/docker/shared/root/docker/helpers.sh index 3f7148c5a..fb8c11c97 100644 --- a/docker/shared/root/docker/helpers.sh +++ b/docker/shared/root/docker/helpers.sh @@ -1,7 +1,7 @@ #!/bin/bash set -e -o errexit -o nounset -o pipefail -[[ ${ENTRYPOINT_DEBUG:=0} == 1 ]] && set -x +[[ ${DOCKER_APP_ENTRYPOINT_DEBUG:=0} == 1 ]] && set -x : "${RUNTIME_UID:="33"}" : "${RUNTIME_GID:="33"}" From a3fd3737963608de1f03d2ad0cd8b236ae08a4e5 Mon Sep 17 00:00:00 2001 From: Christian Winther Date: Wed, 17 Jan 2024 18:02:38 +0000 Subject: [PATCH 094/173] try github alerts --- docker/migration.md | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/docker/migration.md b/docker/migration.md index 458be4321..ec9102562 100644 --- a/docker/migration.md +++ b/docker/migration.md @@ -20,15 +20,18 @@ The consequence of this change is that *all* data stored in the - now unsupporte #### Caveats and warnings -**NOTE**: This is a best-effort guide to help migrate off the old system, the operation is potentially rather complicated (and risky), so please do be careful! - -***PLEASE MAKE SURE TO BACKUP YOUR SERVER AND DATA BEFORE ATTEMPTING A MIGRATION*** +> [!NOTE] +> This is a best-effort guide to help migrate off the old system, the operation is potentially rather complicated (and risky), so please do be careful! +> +> [!CAUTION] +> ***PLEASE MAKE SURE TO BACKUP YOUR SERVER AND DATA BEFORE ATTEMPTING A MIGRATION*** We provide a "migration container" for your convenience that can access both the new and old volumes, allowing you to copy the data into the setup. -**It's important to note that this is a *copy* operation - so disk usage will (temporarily) double while you migrate** - -**YOUR INSTANCE WILL BE *DOWN* WHILE DOING THE MIGRATION, PLEASE PLAN ACCORDINGLY, DEPENDING ON DATA SIZE IT COULD TAKE ANYWHERE FROM 5 *MINUTES* TO 5 *HOURS*** +> [!CAUTION] +> **It's important to note that this is a *copy* operation - so disk usage will (temporarily) double while you migrate** +> +> **YOUR INSTANCE WILL BE *DOWN* WHILE DOING THE MIGRATION, PLEASE PLAN ACCORDINGLY, DEPENDING ON DATA SIZE IT COULD TAKE ANYWHERE FROM 5 *MINUTES* TO 5 *HOURS*** #### 0. Backup, rollout, and rollback plan From eba2db76f22da3aed5009cd132ec253d2b529d98 Mon Sep 17 00:00:00 2001 From: Christian Winther Date: Wed, 17 Jan 2024 18:03:18 +0000 Subject: [PATCH 095/173] try github alerts --- docker/migration.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docker/migration.md b/docker/migration.md index ec9102562..d705dd346 100644 --- a/docker/migration.md +++ b/docker/migration.md @@ -22,7 +22,7 @@ The consequence of this change is that *all* data stored in the - now unsupporte > [!NOTE] > This is a best-effort guide to help migrate off the old system, the operation is potentially rather complicated (and risky), so please do be careful! -> + > [!CAUTION] > ***PLEASE MAKE SURE TO BACKUP YOUR SERVER AND DATA BEFORE ATTEMPTING A MIGRATION*** From 83d92c4819641bdf30249344722e113064842396 Mon Sep 17 00:00:00 2001 From: Christian Winther Date: Wed, 17 Jan 2024 18:04:08 +0000 Subject: [PATCH 096/173] try github alerts --- docker/migration.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docker/migration.md b/docker/migration.md index d705dd346..1a8433992 100644 --- a/docker/migration.md +++ b/docker/migration.md @@ -25,13 +25,13 @@ The consequence of this change is that *all* data stored in the - now unsupporte > [!CAUTION] > ***PLEASE MAKE SURE TO BACKUP YOUR SERVER AND DATA BEFORE ATTEMPTING A MIGRATION*** +> +> **YOUR INSTANCE WILL BE *DOWN* WHILE DOING THE MIGRATION, PLEASE PLAN ACCORDINGLY, DEPENDING ON DATA SIZE IT COULD TAKE ANYWHERE FROM 5 *MINUTES* TO 5 *HOURS*** We provide a "migration container" for your convenience that can access both the new and old volumes, allowing you to copy the data into the setup. -> [!CAUTION] +> [!WARNING] > **It's important to note that this is a *copy* operation - so disk usage will (temporarily) double while you migrate** -> -> **YOUR INSTANCE WILL BE *DOWN* WHILE DOING THE MIGRATION, PLEASE PLAN ACCORDINGLY, DEPENDING ON DATA SIZE IT COULD TAKE ANYWHERE FROM 5 *MINUTES* TO 5 *HOURS*** #### 0. Backup, rollout, and rollback plan From 4729ffb7d5249863d31c62f3d28a52a027b998c0 Mon Sep 17 00:00:00 2001 From: Christian Winther Date: Wed, 17 Jan 2024 18:05:02 +0000 Subject: [PATCH 097/173] try github alerts --- docker/migration.md | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/docker/migration.md b/docker/migration.md index 1a8433992..0225e5324 100644 --- a/docker/migration.md +++ b/docker/migration.md @@ -20,7 +20,7 @@ The consequence of this change is that *all* data stored in the - now unsupporte #### Caveats and warnings -> [!NOTE] +> [!IMPORTANT] > This is a best-effort guide to help migrate off the old system, the operation is potentially rather complicated (and risky), so please do be careful! > [!CAUTION] @@ -28,10 +28,9 @@ The consequence of this change is that *all* data stored in the - now unsupporte > > **YOUR INSTANCE WILL BE *DOWN* WHILE DOING THE MIGRATION, PLEASE PLAN ACCORDINGLY, DEPENDING ON DATA SIZE IT COULD TAKE ANYWHERE FROM 5 *MINUTES* TO 5 *HOURS*** -We provide a "migration container" for your convenience that can access both the new and old volumes, allowing you to copy the data into the setup. - > [!WARNING] > **It's important to note that this is a *copy* operation - so disk usage will (temporarily) double while you migrate** +> We provide a "migration container" for your convenience that can access both the new and old volumes, allowing you to copy the data into the setup. #### 0. Backup, rollout, and rollback plan From e858a453be052454c18cd54eacfa496d26193509 Mon Sep 17 00:00:00 2001 From: Christian Winther Date: Wed, 17 Jan 2024 18:06:43 +0000 Subject: [PATCH 098/173] try github alerts --- docker/migration.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/docker/migration.md b/docker/migration.md index 0225e5324..a6f5b1243 100644 --- a/docker/migration.md +++ b/docker/migration.md @@ -71,6 +71,9 @@ In *particular* the following sections #### 2. Stop all running containers +> [!CAUTION] +> This will take your Pixelfed instance offline + Stop *all* running containers (web, worker, redis, db) ```shell @@ -135,6 +138,9 @@ $ ls redis-data/new #### 6. Copy the data +> [!WARNING] +> This is where we potentially will double your disk usage (temporarily) + Now we will copy the data from the old volumes, to the new ones. The migration container has [`rsync`](https://www.digitalocean.com/community/tutorials/how-to-use-rsync-to-sync-local-and-remote-directories) installed - which is perfect for that kind of work! From 150079119869faa943c353dacfedd4f2a18d9ff5 Mon Sep 17 00:00:00 2001 From: Christian Winther Date: Wed, 17 Jan 2024 18:07:45 +0000 Subject: [PATCH 099/173] try github alerts --- docker/migration.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/docker/migration.md b/docker/migration.md index a6f5b1243..04163d2e4 100644 --- a/docker/migration.md +++ b/docker/migration.md @@ -53,7 +53,8 @@ Then open your old `.env.old` configuration file, and for each of the key/value Don't worry though, the file might *look* different (and significantly larger) but it behaves *exactly* the way the old file did, it just has way more options! -If a key is missing in `.env.new`, don't worry, you can just add those key/value pairs back to the new file - ideally in the `Other configuration` section near the end of the file - but anywhere *should* be fine. +> [!TIP] +> If a key is missing in `.env.new`, don't worry, you can just add those key/value pairs back to the new file - ideally in the `Other configuration` section near the end of the file - but anywhere *should* be fine. This is a great time to review your settings and familiarize you with all the new settings. From 32ad4266d0b5e9069bf043f6f96f614bd3a93562 Mon Sep 17 00:00:00 2001 From: Christian Winther Date: Wed, 17 Jan 2024 18:10:12 +0000 Subject: [PATCH 100/173] try github alerts --- docker/migration.md | 25 +++++++++++++------------ 1 file changed, 13 insertions(+), 12 deletions(-) diff --git a/docker/migration.md b/docker/migration.md index 04163d2e4..1ce0cff57 100644 --- a/docker/migration.md +++ b/docker/migration.md @@ -54,21 +54,22 @@ Then open your old `.env.old` configuration file, and for each of the key/value Don't worry though, the file might *look* different (and significantly larger) but it behaves *exactly* the way the old file did, it just has way more options! > [!TIP] -> If a key is missing in `.env.new`, don't worry, you can just add those key/value pairs back to the new file - ideally in the `Other configuration` section near the end of the file - but anywhere *should* be fine. +> Don't worry if a key is missing in `.env.new`, you can add those key/value pairs back to the new file - ideally in the `Other configuration` section near the end of the file - but anywhere *should* be fine. This is a great time to review your settings and familiarize you with all the new settings. -In *particular* the following sections - -* `PHP configuration` section (near the end of the file) where - * The `PHP_VERSION` settings controls your PHP version - * The `PHP_MEMORY_LIMIT` settings controls your PHP memory limit -* `Docker Specific configuration` section (near the end of the file) where - * The `DOCKER_ALL_HOST_DATA_ROOT_PATH` setting dictate where the new migrated data will live. - * The `DOCKER_APP_RUN_ONE_TIME_SETUP_TASKS` controls if the `One time setup tasks` should run or not. We do *not* want this, since your Pixelfed instance already is set up! -* [Frequently Asked Question / FAQ](faq.md) - * [How do I use my own Proxy server?](faq.md#how-do-i-use-my-own-proxy-server) - * [How do I use my own SSL certificate?](faq.md#how-do-i-use-my-own-ssl-certificate) +> [!NOTE] +> In *particular* the following sections +> +> * `PHP configuration` section (near the end of the file) where +> * The `DOCKER_APP_PHP_VERSION` settings controls your PHP version +> * The `PHP_MEMORY_LIMIT` settings controls your PHP memory limit +> * `Docker Specific configuration` section (near the end of the file) where +> * The `DOCKER_ALL_HOST_DATA_ROOT_PATH` setting dictate where the new migrated data will live. +> * The `DOCKER_APP_RUN_ONE_TIME_SETUP_TASKS` controls if the `One time setup tasks` should run or not. We do *not* want this, since your Pixelfed instance already is set up! +> * [Frequently Asked Question / FAQ](faq.md) +> * [How do I use my own Proxy server?](faq.md#how-do-i-use-my-own-proxy-server) +> * [How do I use my own SSL certificate?](faq.md#how-do-i-use-my-own-ssl-certificate) #### 2. Stop all running containers From a383233710659e825ac3cf5ef84d9a15c5998733 Mon Sep 17 00:00:00 2001 From: Christian Winther Date: Wed, 17 Jan 2024 18:12:30 +0000 Subject: [PATCH 101/173] try github alerts --- docker/migration.md | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/docker/migration.md b/docker/migration.md index 1ce0cff57..a587fd803 100644 --- a/docker/migration.md +++ b/docker/migration.md @@ -32,7 +32,7 @@ The consequence of this change is that *all* data stored in the - now unsupporte > **It's important to note that this is a *copy* operation - so disk usage will (temporarily) double while you migrate** > We provide a "migration container" for your convenience that can access both the new and old volumes, allowing you to copy the data into the setup. -#### 0. Backup, rollout, and rollback plan +#### Step 0. Backup, rollout, and rollback plan 1. Make sure to backup your server (ideally *after* step 1 below has completed, but *before* is better than not at all!) 1. Capture the current Git version / Pixelfed release you are on (e.g. `git --no-pager log -1` outputs the commit reference as the 2nd word in first line) @@ -40,7 +40,7 @@ The consequence of this change is that *all* data stored in the - now unsupporte 1. Backup your `docker-compose.yml` file (`cp docker-compose.yml docker-compose.yml.old`) 1. Read through the *entire* document before starting -#### 1. Migrate your ".env" file +#### Step 1. Migrate your ".env" file The new `.env` file for Docker is a bit different from the old one (many new settings!) so the easiest is to grab the new `.env.docker` file and modify it from scratch again. @@ -71,7 +71,7 @@ This is a great time to review your settings and familiarize you with all the ne > * [How do I use my own Proxy server?](faq.md#how-do-i-use-my-own-proxy-server) > * [How do I use my own SSL certificate?](faq.md#how-do-i-use-my-own-ssl-certificate) -#### 2. Stop all running containers +#### Step 2. Stop all running containers > [!CAUTION] > This will take your Pixelfed instance offline @@ -82,7 +82,7 @@ Stop *all* running containers (web, worker, redis, db) $ docker compose down ``` -#### 3. Pull down the new source code +#### Step 3. Pull down the new source code Update your project to the latest release of Pixelfed by running @@ -92,7 +92,7 @@ $ git pull origin $release Where `$release` is either `dev`, `staging` or a [tagged release](https://github.com/pixelfed/pixelfed/releases) such as `v0.12.0`. -#### 4. Run the migration container +#### Step 4. Run the migration container You can access the Docker container with both old and new volumes by running the following command @@ -114,7 +114,7 @@ This will put you in the `/migrate` directory within the container, containing 8 `-- old ``` -#### 5. Check the folders +#### Step 5. Check the folders ##### Old folders @@ -138,7 +138,7 @@ $ ls db-data/new $ ls redis-data/new ``` -#### 6. Copy the data +#### Step 6. Copy the data > [!WARNING] > This is where we potentially will double your disk usage (temporarily) @@ -161,7 +161,7 @@ $ rsync -avP db-data/old/ db-data/new $ rsync -avP redis-data/old/ redis-data/new ``` -#### 7. Sanity checking +#### Step 7. Sanity checking Lets make sure everything copied over successfully! @@ -190,7 +190,7 @@ aria_log_control ddl_recovery-backup.log ib_buffer_pool ib_logfile0 ibdata1 If everything looks good, type `exit` to leave exit the migration container -#### 6. Starting up the your Pixelfed server again +#### Step 8. Starting up the your Pixelfed server again With all an updated Pixelfed (step 2), updated `.env` file (step 3), migrated data (step 4, 5, 6 and 7) we're ready to start things back up again. @@ -268,7 +268,7 @@ $ docker compose logs --tail 250 --follow If you changed anything in the `.env` file while debugging, some containers might restart now, thats perfectly fine. -#### 7. Verify +#### Step 9. Verify With all services online, it's time to go to your browser and check everything is working @@ -280,7 +280,7 @@ With all services online, it's time to go to your browser and check everything i If everything looks fine, yay, you made it to the end! Lets do some cleanup -#### 8. Final steps + cleanup +#### Step 10. Final steps + cleanup With everything working, please take a new snapshot/backup of your server *before* we do any cleanup. A post-migration snapshot is incredibly useful, since it contains both the old and new configuration + data, making any recovery much easier in a rollback scenario later. From 033db841f43f8865330d26ebfa3d8e57efb5a446 Mon Sep 17 00:00:00 2001 From: Christian Winther Date: Wed, 17 Jan 2024 18:19:04 +0000 Subject: [PATCH 102/173] try github alerts --- docker/migration.md | 49 +++++++++++++++++++++++---------------------- 1 file changed, 25 insertions(+), 24 deletions(-) diff --git a/docker/migration.md b/docker/migration.md index a587fd803..bc516bc43 100644 --- a/docker/migration.md +++ b/docker/migration.md @@ -44,7 +44,7 @@ The consequence of this change is that *all* data stored in the - now unsupporte The new `.env` file for Docker is a bit different from the old one (many new settings!) so the easiest is to grab the new `.env.docker` file and modify it from scratch again. -```shell +```bash $ cp .env .env.old $ wget -O .env.new https://raw.githubusercontent.com/pixelfed/pixelfed/dev/.env.docker ``` @@ -78,7 +78,7 @@ This is a great time to review your settings and familiarize you with all the ne Stop *all* running containers (web, worker, redis, db) -```shell +```bash $ docker compose down ``` @@ -86,17 +86,18 @@ $ docker compose down Update your project to the latest release of Pixelfed by running -```shell +```bash $ git pull origin $release ``` -Where `$release` is either `dev`, `staging` or a [tagged release](https://github.com/pixelfed/pixelfed/releases) such as `v0.12.0`. +> [!NOTE] +> The `$release` can be any valid git reference like `dev`, `staging` or a [tagged release](https://github.com/pixelfed/pixelfed/releases) such as `v0.12.0`. #### Step 4. Run the migration container You can access the Docker container with both old and new volumes by running the following command -```shell +```bash $ docker compose -f docker-compose.migrate.yml run migrate bash ``` @@ -120,7 +121,7 @@ This will put you in the `/migrate` directory within the container, containing 8 The following commands should all return *SOME* files and data - if they do not - then there might be an issue with the anonymous volume binding. -```shell +```bash $ ls app-storage/old $ ls db-data/old $ ls redis-data/old @@ -132,7 +133,7 @@ The following commands should all return *NO* files and data - if they contain d If you haven't run `docker compose up` since you updated your project in step (2) - they should be empty and good to go. -```shell +```bash $ ls app-storage/new $ ls db-data/new $ ls redis-data/new @@ -155,7 +156,7 @@ The migration container has [`rsync`](https://www.digitalocean.com/community/tut Lets copy the data by running the following commands: -```shell +```bash $ rsync -avP app-storage/old/ app-storage/new $ rsync -avP db-data/old/ db-data/new $ rsync -avP redis-data/old/ redis-data/new @@ -169,21 +170,21 @@ Each *new* directory should contain *something* like (but not always exactly) th The **redis-data/new** directory might also contain a `server.pid` -```shell +```bash $ ls redis-data/new appendonlydir ``` The **app-storage/new** directory should look *something* like this -```shell +```bash $ ls app-storage/new app debugbar docker framework logs oauth-private.key oauth-public.key purify ``` The **db-data/new** directory should look *something* like this. There might be a lot of files, or very few files, but there *must* be a `mysql`, `performance_schema`, and `${DB_DATABASE}` (e.g. `pixelfed_prod` directory) -```shell +```bash $ ls db-data/new aria_log_control ddl_recovery-backup.log ib_buffer_pool ib_logfile0 ibdata1 mariadb_upgrade_info multi-master.info mysql performance_schema pixelfed_prod sys undo001 undo002 undo003 ``` @@ -196,7 +197,7 @@ With all an updated Pixelfed (step 2), updated `.env` file (step 3), migrated da But before we start your Pixelfed server back up again, lets put the new `.env` file we made in step 1 in its right place. -```shell +```bash $ cp .env.new .env ``` @@ -204,7 +205,7 @@ $ cp .env.new .env First thing we want to try is to start up the database by running the following command and checking the logs -```shell +```bash $ docker compose up -d db $ docker compose logs --tail 250 --follow db ``` @@ -215,7 +216,7 @@ if there are no errors and the server isn't crashing, great! If you have an easy Next thing we want to try is to start up the Redis server by running the following command and checking the logs -```shell +```bash $ docker compose up -d redis $ docker compose logs --tail 250 --follow redis ``` @@ -226,7 +227,7 @@ if there are no errors and the server isn't crashing, great! Next thing we want to try is to start up the Worker server by running the following command and checking the logs -```shell +```bash $ docker compose up -d worker $ docker compose logs --tail 250 --follow worker ``` @@ -252,7 +253,7 @@ The final service, `web`, which will bring your site back online! What a journey Lets get to it, run these commands to start the `web` service and inspect the logs. -```shell +```bash $ docker compose up -d web $ docker compose logs --tail 250 --follow web ``` @@ -261,7 +262,7 @@ The output should be pretty much identical to that of the `worker`, so please se If the `web` service came online without issues, start the rest of the (optional) services, such as the `proxy`, if enabled, by running -```shell +```bash $ docker compose up -d $ docker compose logs --tail 250 --follow ``` @@ -288,7 +289,7 @@ Now, with all the data in the new folders, you can delete the old Docker Contain List all volumes, and give them a look: -```shell +```bash $ docker volume ls ``` @@ -296,13 +297,13 @@ The volumes we want to delete *ends* with the volume name (`db-data`, `app-stora Once you have found the volumes in in the list, delete each of them by running: -```shell +```bash $ docker volume rm $volume_name_in_column_two_of_the_output ``` You can also delete the `docker-compose.yml.old` and `.env.old` file since they are no longer needed -```shell +```bash $ rm docker-compose.yml.old $ rm .env.old ``` @@ -313,26 +314,26 @@ Oh no, something went wrong? No worries, we you got backups and a quick way back #### Move `docker-compose.yml` back -```shell +```bash $ cp docker-compose.yml docker-compose.yml.new $ cp docker-compose.yml.old docker-compose.yml ``` #### Move `.env` file back -```shell +```bash $ cp env.old .env ``` #### Go back to old source code version -```shell +```bash $ git checkout $commit_id_from_step_0 ``` #### Start things back up -```shell +```bash docker compose up -d ``` From 29564a58096461b80170672cf4c44a24a4860c12 Mon Sep 17 00:00:00 2001 From: Christian Winther Date: Wed, 17 Jan 2024 18:20:45 +0000 Subject: [PATCH 103/173] docs tuning --- docker/migration.md | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/docker/migration.md b/docker/migration.md index bc516bc43..5e820555d 100644 --- a/docker/migration.md +++ b/docker/migration.md @@ -32,7 +32,7 @@ The consequence of this change is that *all* data stored in the - now unsupporte > **It's important to note that this is a *copy* operation - so disk usage will (temporarily) double while you migrate** > We provide a "migration container" for your convenience that can access both the new and old volumes, allowing you to copy the data into the setup. -#### Step 0. Backup, rollout, and rollback plan +#### Step 0) Backup, rollout, and rollback plan 1. Make sure to backup your server (ideally *after* step 1 below has completed, but *before* is better than not at all!) 1. Capture the current Git version / Pixelfed release you are on (e.g. `git --no-pager log -1` outputs the commit reference as the 2nd word in first line) @@ -40,7 +40,7 @@ The consequence of this change is that *all* data stored in the - now unsupporte 1. Backup your `docker-compose.yml` file (`cp docker-compose.yml docker-compose.yml.old`) 1. Read through the *entire* document before starting -#### Step 1. Migrate your ".env" file +#### Step 1) Migrate your ".env" file The new `.env` file for Docker is a bit different from the old one (many new settings!) so the easiest is to grab the new `.env.docker` file and modify it from scratch again. @@ -71,7 +71,7 @@ This is a great time to review your settings and familiarize you with all the ne > * [How do I use my own Proxy server?](faq.md#how-do-i-use-my-own-proxy-server) > * [How do I use my own SSL certificate?](faq.md#how-do-i-use-my-own-ssl-certificate) -#### Step 2. Stop all running containers +#### Step 2) Stop all running containers > [!CAUTION] > This will take your Pixelfed instance offline @@ -82,7 +82,7 @@ Stop *all* running containers (web, worker, redis, db) $ docker compose down ``` -#### Step 3. Pull down the new source code +#### Step 3) Pull down the new source code Update your project to the latest release of Pixelfed by running @@ -93,7 +93,7 @@ $ git pull origin $release > [!NOTE] > The `$release` can be any valid git reference like `dev`, `staging` or a [tagged release](https://github.com/pixelfed/pixelfed/releases) such as `v0.12.0`. -#### Step 4. Run the migration container +#### Step 4) Run the migration container You can access the Docker container with both old and new volumes by running the following command @@ -115,7 +115,7 @@ This will put you in the `/migrate` directory within the container, containing 8 `-- old ``` -#### Step 5. Check the folders +#### Step 5) Check the folders ##### Old folders @@ -139,7 +139,7 @@ $ ls db-data/new $ ls redis-data/new ``` -#### Step 6. Copy the data +#### Step 6) Copy the data > [!WARNING] > This is where we potentially will double your disk usage (temporarily) @@ -162,7 +162,7 @@ $ rsync -avP db-data/old/ db-data/new $ rsync -avP redis-data/old/ redis-data/new ``` -#### Step 7. Sanity checking +#### Step 7) Sanity checking Lets make sure everything copied over successfully! @@ -191,7 +191,7 @@ aria_log_control ddl_recovery-backup.log ib_buffer_pool ib_logfile0 ibdata1 If everything looks good, type `exit` to leave exit the migration container -#### Step 8. Starting up the your Pixelfed server again +#### Step 8) Starting up the your Pixelfed server again With all an updated Pixelfed (step 2), updated `.env` file (step 3), migrated data (step 4, 5, 6 and 7) we're ready to start things back up again. @@ -269,7 +269,7 @@ $ docker compose logs --tail 250 --follow If you changed anything in the `.env` file while debugging, some containers might restart now, thats perfectly fine. -#### Step 9. Verify +#### Step 9) Verify With all services online, it's time to go to your browser and check everything is working @@ -281,7 +281,7 @@ With all services online, it's time to go to your browser and check everything i If everything looks fine, yay, you made it to the end! Lets do some cleanup -#### Step 10. Final steps + cleanup +#### Step 10) Final steps + cleanup With everything working, please take a new snapshot/backup of your server *before* we do any cleanup. A post-migration snapshot is incredibly useful, since it contains both the old and new configuration + data, making any recovery much easier in a rollback scenario later. From 3598f9f8f47067e47ccc32e10dbcff02ae19b9ae Mon Sep 17 00:00:00 2001 From: Christian Winther Date: Wed, 17 Jan 2024 18:24:35 +0000 Subject: [PATCH 104/173] move check-config to after fix-permissions --- .../entrypoint.d/{00-check-config.sh => 02-check-config.sh} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename docker/shared/root/docker/entrypoint.d/{00-check-config.sh => 02-check-config.sh} (100%) diff --git a/docker/shared/root/docker/entrypoint.d/00-check-config.sh b/docker/shared/root/docker/entrypoint.d/02-check-config.sh similarity index 100% rename from docker/shared/root/docker/entrypoint.d/00-check-config.sh rename to docker/shared/root/docker/entrypoint.d/02-check-config.sh From f2b28ece6ed837faf92f247bea03559cbf08010a Mon Sep 17 00:00:00 2001 From: Christian Winther Date: Wed, 17 Jan 2024 18:26:04 +0000 Subject: [PATCH 105/173] longer entrypoint bars --- docker/shared/root/docker/entrypoint.sh | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/docker/shared/root/docker/entrypoint.sh b/docker/shared/root/docker/entrypoint.sh index 44310fa7a..ed698250b 100755 --- a/docker/shared/root/docker/entrypoint.sh +++ b/docker/shared/root/docker/entrypoint.sh @@ -58,9 +58,9 @@ find "${ENTRYPOINT_D_ROOT}" -follow -type f -print | sort -V | while read -r fil log-error-and-exit "File [${file}] is not executable (please 'chmod +x' it)" fi - log-info "${section_message_color}========================================${color_clear}" + log-info "${section_message_color}============================================================${color_clear}" log-info "${section_message_color}Sourcing [${file}]${color_clear}" - log-info "${section_message_color}========================================${color_clear}" + log-info "${section_message_color}============================================================${color_clear}" # shellcheck disable=SC1090 source "${file}" @@ -76,9 +76,9 @@ find "${ENTRYPOINT_D_ROOT}" -follow -type f -print | sort -V | while read -r fil log-error-and-exit "File [${file}] is not executable (please 'chmod +x' it)" fi - log-info "${section_message_color}========================================${color_clear}" + log-info "${section_message_color}============================================================${color_clear}" log-info "${section_message_color}Executing [${file}]${color_clear}" - log-info "${section_message_color}========================================${color_clear}" + log-info "${section_message_color}============================================================${color_clear}" "${file}" ;; From 2d223d61edf839cb6ac799c4927b0f82f120901b Mon Sep 17 00:00:00 2001 From: Christian Winther Date: Thu, 18 Jan 2024 16:22:26 +0000 Subject: [PATCH 106/173] remove docs they now live in https://github.com/pixelfed/docs-next/pull/1 and https://jippi.github.io/pixelfed-docs-next/pr-preview/pr-1/running-pixelfed/ --- docker/README.md | 16 +- docker/customizing.md | 219 --------------------------- docker/faq.md | 34 ----- docker/migration.md | 340 ------------------------------------------ docker/new-server.md | 145 ------------------ docker/runtimes.md | 94 ------------ 6 files changed, 1 insertion(+), 847 deletions(-) delete mode 100644 docker/customizing.md delete mode 100644 docker/faq.md delete mode 100644 docker/migration.md delete mode 100644 docker/new-server.md delete mode 100644 docker/runtimes.md diff --git a/docker/README.md b/docker/README.md index bf73662a8..23584a4ab 100644 --- a/docker/README.md +++ b/docker/README.md @@ -1,17 +1,3 @@ # Pixelfed + Docker + Docker Compose -* [Setting up a new Pixelfed server with Docker Compose](new-server.md) -* [Migrating to the new `docker-compose.yml` setup](migration.md) -* [Frequently Asked Question / FAQ](faq.md) - * [How do I use my own Proxy server?](faq.md#how-do-i-use-my-own-proxy-server) - * [How do I use my own SSL certificate?](faq.md#how-do-i-use-my-own-ssl-certificate) -* [Understanding Pixelfed Container runtimes (Apache, FPM, Nginx + FPM)](runtimes.md) - * [Apache](runtimes.md#apache) - * [FPM](runtimes.md#fpm) - * [Nginx + FPM](runtimes.md#nginx) -* [Customizing Docker image](customizing.md) - * [Running commands on container start](customizing.md#running-commands-on-container-start) - * [Disabling entrypoint or individual scripts](customizing.md#disabling-entrypoint-or-individual-scripts) - * [Templating](customizing.md#templating) - * [Fixing ownership on startup](customizing.md#fixing-ownership-on-startup) - * [Build settings (arguments)](customizing.md#build-settings-arguments) +Please see the [Pixelfed Docs (Next)](https://jippi.github.io/pixelfed-docs-next/pr-preview/pr-1/running-pixelfed/) for current documentation on Docker usage diff --git a/docker/customizing.md b/docker/customizing.md deleted file mode 100644 index e7c66e842..000000000 --- a/docker/customizing.md +++ /dev/null @@ -1,219 +0,0 @@ -# Customizing your `Dockerfile` - -## Running commands on container start - -### Description - -When a Pixelfed container starts up, the [`ENTRYPOINT`](https://docs.docker.com/engine/reference/builder/#entrypoint) script will - -1. Search the `/docker/entrypoint.d/` directory for files and for each file (in lexical order). -1. Check if the file is executable. - 1. If the file is *not* executable, print an error and exit the container. -1. If the file has the extension `.envsh` the file will be [sourced](https://superuser.com/a/46146). -1. If the file has the extension `.sh` the file will be run like a normal script. -1. Any other file extension will log a warning and will be ignored. - -### Debugging - -You can set environment variable `DOCKER_APP_ENTRYPOINT_DEBUG=1` to show verbose output of what each `entrypoint.d` script is doing. - -You can also `docker exec` or `docker run` into a container and run `/` - -### Included scripts - -* `/docker/entrypoint.d/04-defaults.envsh` calculates Docker container environment variables needed for [templating](#templating) configuration files. -* `/docker/entrypoint.d/05-templating.sh` renders [template](#templating) configuration files. -* `/docker/entrypoint.d/10-storage.sh` ensures Pixelfed storage related permissions and commands are run. -* `//docker/entrypoint.d/15-storage-permissions.sh` (optionally) ensures permissions for files are corrected (see [fixing ownership on startup](#fixing-ownership-on-startup)) -* `/docker/entrypoint.d/20-horizon.sh` ensures [Laravel Horizon](https://laravel.com/docs/master/horizon) used by Pixelfed is configured -* `/docker/entrypoint.d/30-cache.sh` ensures all Pixelfed caches (router, view, config) is warmed - -### Disabling entrypoint or individual scripts - -To disable the entire entrypoint you can set the variable `ENTRYPOINT_SKIP=1`. - -To disable individual entrypoint scripts you can add the filename to the space (`" "`) separated variable `ENTRYPOINT_SKIP_SCRIPTS`. (example: `ENTRYPOINT_SKIP_SCRIPTS="10-storage.sh 30-cache.sh"`) - -## Templating - -The Docker container can do some basic templating (more like variable replacement) as part of the entrypoint scripts via [gomplate](https://docs.gomplate.ca/). - -Any file put in the `/docker/templates/` directory will be templated and written to the right directory. - -### File path examples - -1. To template `/usr/local/etc/php/php.ini` in the container put the source file in `/docker/templates/usr/local/etc/php/php.ini`. -1. To template `/a/fantastic/example.txt` in the container put the source file in `/docker/templates/a/fantastic/example.txt`. -1. To template `/some/path/anywhere` in the container put the source file in `/docker/templates/a/fantastic/example.txt`. - -### Available variables - -Variables available for templating are sourced (in order, so *last* source takes precedence) like this: - -1. `env:` in your `docker-compose.yml` or `-e` in your `docker run` / `docker compose run` -1. Any exported variables in `.envsh` files loaded *before* `05-templating.sh` (e.g. any file with `04-`, `03-`, `02-`, `01-` or `00-` prefix) -1. All key/value pairs in `/var/www/.env.docker` -1. All key/value pairs in `/var/www/.env` - -### Template guide 101 - -Please see the [`gomplate` documentation](https://docs.gomplate.ca/) for a more comprehensive overview. - -The most frequent use-case you have is likely to print a environment variable (or a default value if it's missing), so this is how to do that: - -* `{{ getenv "VAR_NAME" }}` print an environment variable and **fail** if the variable is not set. ([docs](https://docs.gomplate.ca/functions/env/#envgetenv)) -* `{{ getenv "VAR_NAME" "default" }}` print an environment variable and print `default` if the variable is not set. ([docs](https://docs.gomplate.ca/functions/env/#envgetenv)) - -The script will *fail* if you reference a variable that does not exist (and don't have a default value) in a template. - -Please see the - -* [`gomplate` syntax documentation](https://docs.gomplate.ca/syntax/) -* [`gomplate` functions documentation](https://docs.gomplate.ca/functions/) - -## Fixing ownership on startup - -You can set the environment variable `DOCKER_APP_ENSURE_OWNERSHIP_PATHS` to a list of paths that should have their `$USER` and `$GROUP` ownership changed to the configured runtime user and group during container bootstrapping. - -The variable is a space-delimited list shown below and accepts both relative and absolute paths: - -* `DOCKER_APP_ENSURE_OWNERSHIP_PATHS="./storage ./bootstrap"` -* `DOCKER_APP_ENSURE_OWNERSHIP_PATHS="/some/other/folder"` - -## Build settings (arguments) - -The Pixelfed Dockerfile utilizes [Docker Multi-stage builds](https://docs.docker.com/build/building/multi-stage/) and [Build arguments](https://docs.docker.com/build/guide/build-args/). - -Using *build arguments* allow us to create a flexible and more maintainable Dockerfile, supporting [multiple runtimes](runtimes.md) ([FPM](runtimes.md#fpm), [Nginx](runtimes.md#nginx), [Apache + mod_php](runtimes.md#apache)) and end-user flexibility without having to fork or copy the Dockerfile. - -*Build arguments* can be configured using `--build-arg 'name=value'` for `docker build`, `docker compose build` and `docker buildx build`. For `docker-compose.yml` the `args` key for [`build`](https://docs.docker.com/compose/compose-file/compose-file-v3/#build) can be used. - -### `PHP_VERSION` - -The `PHP` version to use when building the runtime container. - -Any valid Docker Hub PHP version is acceptable here, as long as it's [published to Docker Hub](https://hub.docker.com/_/php/tags) - -**Example values**: - -* `8` will use the latest version of PHP 8 -* `8.1` will use the latest version of PHP 8.1 -* `8.2.14` will use PHP 8.2.14 -* `latest` will use whatever is the latest PHP version - -**Default value**: `8.1` - -### `PHP_PECL_EXTENSIONS` - -PECL extensions to install via `pecl install` - -Use [PHP_PECL_EXTENSIONS_EXTRA](#php_pecl_extensions_extra) if you want to add *additional* extenstions. - -Only change this setting if you want to change the baseline extensions. - -See the [`PECL extensions` documentation on Docker Hub](https://hub.docker.com/_/php) for more information. - -**Default value**: `imagick redis` - -### `PHP_PECL_EXTENSIONS_EXTRA` - -Extra PECL extensions (separated by space) to install via `pecl install` - -See the [`PECL extensions` documentation on Docker Hub](https://hub.docker.com/_/php) for more information. - -**Default value**: `""` - -### `PHP_EXTENSIONS` - -PHP Extensions to install via `docker-php-ext-install`. - -**NOTE:** use [`PHP_EXTENSIONS_EXTRA`](#php_extensions_extra) if you want to add *additional* extensions, only override this if you want to change the baseline extensions. - -See the [`How to install more PHP extensions` documentation on Docker Hub](https://hub.docker.com/_/php) for more information - -**Default value**: `intl bcmath zip pcntl exif curl gd` - -### `PHP_EXTENSIONS_EXTRA` - -Extra PHP Extensions (separated by space) to install via `docker-php-ext-install`. - -See the [`How to install more PHP extensions` documentation on Docker Hub](https://hub.docker.com/_/php) for more information. - -**Default value**: `""` - -### `PHP_EXTENSIONS_DATABASE` - -PHP database extensions to install. - -By default we install both `pgsql` and `mysql` since it's more convinient (and adds very little build time! but can be overwritten here if required. - -**Default value**: `pdo_pgsql pdo_mysql pdo_sqlite` - -### `COMPOSER_VERSION` - -The version of Composer to install. - -Please see the [Docker Hub `composer` page](https://hub.docker.com/_/composer) for valid values. - -**Default value**: `2.6` - -### `APT_PACKAGES_EXTRA` - -Extra APT packages (separated by space) that should be installed inside the image by `apt-get install` - -**Default value**: `""` - -### `NGINX_VERSION` - -Version of `nginx` to when targeting [`nginx-runtime`](runtimes.md#nginx). - -Please see the [Docker Hub `nginx` page](https://hub.docker.com/_/nginx) for available versions. - -**Default value**: `1.25.3` - -### `FOREGO_VERSION` - -Version of [`forego`](https://github.com/ddollar/forego) to install. - -**Default value**: `0.17.2` - -### `GOMPLATE_VERSION` - -Version of [`goplate`](https://github.com/hairyhenderson/gomplate) to install. - -**Default value**: `v3.11.6` - -### `DOTENV_LINTER_VERSION` - -Version of [`dotenv-linter`](https://github.com/dotenv-linter/dotenv-linter) to install. - -**Default value**: `v3.2.0` - -### `PHP_BASE_TYPE` - -The `PHP` base image layer to use when building the runtime container. - -When targeting - -* [`apache-runtime`](runtimes.md#apache) use `apache` -* [`fpm-runtime`](runtimes.md#fpm) use `fpm` -* [`nginx-runtime`](runtimes.md#nginx) use `fpm` - -**Valid values**: - -* `apache` -* `fpm` -* `cli` - -**Default value**: `apache` - -### `PHP_DEBIAN_RELEASE` - -The `Debian` Operation System version to use. - -**Valid values**: - -* `bullseye` -* `bookworm` - -**Default value**: `bullseye` diff --git a/docker/faq.md b/docker/faq.md deleted file mode 100644 index bbd47fcf5..000000000 --- a/docker/faq.md +++ /dev/null @@ -1,34 +0,0 @@ -# Pixelfed Docker FAQ - -## How do I use my own Proxy server? - -No problem! All you have to do is: - -1. Change the `DOCKER_PROXY_PROFILE` key/value pair in your `.env` file to `"disabled"`. - * This disables the `proxy` *and* `proxy-acme` services in `docker-compose.yml`. - * The setting is near the bottom of the file. -1. Point your proxy upstream to the exposed `web` port (**Default**: `8080`). - * The port is controlled by the `DOCKER_WEB_PORT_EXTERNAL_HTTP` key in `.env`. - * The setting is near the bottom of the file. -1. Run `docker compose up -d --remove-orphans` to apply the configuration - -## How do I use my own SSL certificate? - -No problem! All you have to do is: - -1. Change the `DOCKER_PROXY_ACME_PROFILE` key/value pair in your `.env` file to `"disabled"`. - * This disabled the `proxy-acme` service in `docker-compose.yml`. - * It does *not* disable the `proxy` service. -1. Put your certificates in `${DOCKER_ALL_HOST_CONFIG_ROOT_PATH}/proxy/certs` (e.g. `./docker-compose/config/proxy/certs`) - * You may need to create this folder manually if it does not exists. - * The following files are expected to exist in the directory for the proxy to detect and use them automatically (this is the same directory and file names as LetsEncrypt uses) - 1. `${APP_DOMAIN}.cert.pem` - 1. `${APP_DOMAIN}.chain.pem` - 1. `${APP_DOMAIN}.fullchain.pem` - 1. `${APP_DOMAIN}.key.pem` - * See the [`nginx-proxy` configuration file for name patterns](https://github.com/nginx-proxy/nginx-proxy/blob/main/nginx.tmpl#L659-L670) -1. Run `docker compose up -d --remove-orphans` to apply the configuration - -## How do I change the container name prefix? - -Change the `DOCKER_ALL_CONTAINER_NAME_PREFIX` key/value pair in your `.env` file. diff --git a/docker/migration.md b/docker/migration.md deleted file mode 100644 index 5e820555d..000000000 --- a/docker/migration.md +++ /dev/null @@ -1,340 +0,0 @@ -# Migrating to the new Pixelfed Docker setup - -There is [*a lot* of changes](https://github.com/pixelfed/pixelfed/pull/4844) in how Pixelfed Docker/Docker Compose images work - it's a complete rewrite - with a bunch of breaking changes. - -## No more anonymous Docker Compose volumes - -The old `docker-compose.yml` configuration file [declared four anonymous volumes](https://github.com/pixelfed/pixelfed/blob/b1ff44ca2f75c088a11576fb03b5bad2fbed4d5c/docker-compose.yml#L72-L76) for storing Pixelfed related data within. - -These are no longer used, instead favoring a [Docker bind volume](https://docs.docker.com/storage/bind-mounts/) approach where content are stored directly on the server disk, outside -of a Docker volume. - -The consequence of this change is that *all* data stored in the - now unsupported - Docker volumes will no longer be accessible by Pixelfed. - -* The `db-data` volume *definitely* contain important data - it's your database after all! -* The `app-storage` volume *definitely* contain important data - it's files uploaded to - or seen by - your server! -* The `redis-data` volume *might* contain important data (depending on your configuration) -* The `app-bootstrap` volume does not contain any important data - all of it will be generated automatically in the new setup on startup. We will *not* be migrating this! - -### Migrating off anonymous Docker Compose volumes - -#### Caveats and warnings - -> [!IMPORTANT] -> This is a best-effort guide to help migrate off the old system, the operation is potentially rather complicated (and risky), so please do be careful! - -> [!CAUTION] -> ***PLEASE MAKE SURE TO BACKUP YOUR SERVER AND DATA BEFORE ATTEMPTING A MIGRATION*** -> -> **YOUR INSTANCE WILL BE *DOWN* WHILE DOING THE MIGRATION, PLEASE PLAN ACCORDINGLY, DEPENDING ON DATA SIZE IT COULD TAKE ANYWHERE FROM 5 *MINUTES* TO 5 *HOURS*** - -> [!WARNING] -> **It's important to note that this is a *copy* operation - so disk usage will (temporarily) double while you migrate** -> We provide a "migration container" for your convenience that can access both the new and old volumes, allowing you to copy the data into the setup. - -#### Step 0) Backup, rollout, and rollback plan - -1. Make sure to backup your server (ideally *after* step 1 below has completed, but *before* is better than not at all!) -1. Capture the current Git version / Pixelfed release you are on (e.g. `git --no-pager log -1` outputs the commit reference as the 2nd word in first line) -1. Backup your `.env` file (we will do this in step 3 as well) -1. Backup your `docker-compose.yml` file (`cp docker-compose.yml docker-compose.yml.old`) -1. Read through the *entire* document before starting - -#### Step 1) Migrate your ".env" file - -The new `.env` file for Docker is a bit different from the old one (many new settings!) so the easiest is to grab the new `.env.docker` file and modify it from scratch again. - -```bash -$ cp .env .env.old -$ wget -O .env.new https://raw.githubusercontent.com/pixelfed/pixelfed/dev/.env.docker -``` - -Then open your old `.env.old` configuration file, and for each of the key/value pairs within it, find and update the key in the new `.env.new` configuration file. - -Don't worry though, the file might *look* different (and significantly larger) but it behaves *exactly* the way the old file did, it just has way more options! - -> [!TIP] -> Don't worry if a key is missing in `.env.new`, you can add those key/value pairs back to the new file - ideally in the `Other configuration` section near the end of the file - but anywhere *should* be fine. - -This is a great time to review your settings and familiarize you with all the new settings. - -> [!NOTE] -> In *particular* the following sections -> -> * `PHP configuration` section (near the end of the file) where -> * The `DOCKER_APP_PHP_VERSION` settings controls your PHP version -> * The `PHP_MEMORY_LIMIT` settings controls your PHP memory limit -> * `Docker Specific configuration` section (near the end of the file) where -> * The `DOCKER_ALL_HOST_DATA_ROOT_PATH` setting dictate where the new migrated data will live. -> * The `DOCKER_APP_RUN_ONE_TIME_SETUP_TASKS` controls if the `One time setup tasks` should run or not. We do *not* want this, since your Pixelfed instance already is set up! -> * [Frequently Asked Question / FAQ](faq.md) -> * [How do I use my own Proxy server?](faq.md#how-do-i-use-my-own-proxy-server) -> * [How do I use my own SSL certificate?](faq.md#how-do-i-use-my-own-ssl-certificate) - -#### Step 2) Stop all running containers - -> [!CAUTION] -> This will take your Pixelfed instance offline - -Stop *all* running containers (web, worker, redis, db) - -```bash -$ docker compose down -``` - -#### Step 3) Pull down the new source code - -Update your project to the latest release of Pixelfed by running - -```bash -$ git pull origin $release -``` - -> [!NOTE] -> The `$release` can be any valid git reference like `dev`, `staging` or a [tagged release](https://github.com/pixelfed/pixelfed/releases) such as `v0.12.0`. - -#### Step 4) Run the migration container - -You can access the Docker container with both old and new volumes by running the following command - -```bash -$ docker compose -f docker-compose.migrate.yml run migrate bash -``` - -This will put you in the `/migrate` directory within the container, containing 8 directories like shown here - -```plain -|-- app-storage -| |-- new -| `-- old -|-- db-data -| |-- new -| `-- old -`-- redis-data - |-- new - `-- old -``` - -#### Step 5) Check the folders - -##### Old folders - -The following commands should all return *SOME* files and data - if they do not - then there might be an issue with the anonymous volume binding. - -```bash -$ ls app-storage/old -$ ls db-data/old -$ ls redis-data/old -``` - -##### New folders - -The following commands should all return *NO* files and data - if they contain data - you need to either delete it (backup first!) or skip that migration step. - -If you haven't run `docker compose up` since you updated your project in step (2) - they should be empty and good to go. - -```bash -$ ls app-storage/new -$ ls db-data/new -$ ls redis-data/new -``` - -#### Step 6) Copy the data - -> [!WARNING] -> This is where we potentially will double your disk usage (temporarily) - -Now we will copy the data from the old volumes, to the new ones. - -The migration container has [`rsync`](https://www.digitalocean.com/community/tutorials/how-to-use-rsync-to-sync-local-and-remote-directories) installed - which is perfect for that kind of work! - -**NOTE** It's important that the "source" (first path in the `rsync` command) has a trailing `/` - otherwise the directory layout will turn out wrong! - -**NOTE** Depending on your server, these commands might take some time to finish, each command should provide a progress bar with rough time estimation. - -**NOTE** `rsync` should preserve ownership, permissions, and symlinks correctly for you as well for all the files copied. - -Lets copy the data by running the following commands: - -```bash -$ rsync -avP app-storage/old/ app-storage/new -$ rsync -avP db-data/old/ db-data/new -$ rsync -avP redis-data/old/ redis-data/new -``` - -#### Step 7) Sanity checking - -Lets make sure everything copied over successfully! - -Each *new* directory should contain *something* like (but not always exactly) the following - **NO** directory should have a single folder called `old`, if they do, the `rsync` commands above didn't work correctly - and you need to move the content of the `old` folder into the "root" of the `new` folder like shown a bit in the following sections. - -The **redis-data/new** directory might also contain a `server.pid` - -```bash -$ ls redis-data/new -appendonlydir -``` - -The **app-storage/new** directory should look *something* like this - -```bash -$ ls app-storage/new -app debugbar docker framework logs oauth-private.key oauth-public.key purify -``` - -The **db-data/new** directory should look *something* like this. There might be a lot of files, or very few files, but there *must* be a `mysql`, `performance_schema`, and `${DB_DATABASE}` (e.g. `pixelfed_prod` directory) - -```bash -$ ls db-data/new -aria_log_control ddl_recovery-backup.log ib_buffer_pool ib_logfile0 ibdata1 mariadb_upgrade_info multi-master.info mysql performance_schema pixelfed_prod sys undo001 undo002 undo003 -``` - -If everything looks good, type `exit` to leave exit the migration container - -#### Step 8) Starting up the your Pixelfed server again - -With all an updated Pixelfed (step 2), updated `.env` file (step 3), migrated data (step 4, 5, 6 and 7) we're ready to start things back up again. - -But before we start your Pixelfed server back up again, lets put the new `.env` file we made in step 1 in its right place. - -```bash -$ cp .env.new .env -``` - -##### The Database - -First thing we want to try is to start up the database by running the following command and checking the logs - -```bash -$ docker compose up -d db -$ docker compose logs --tail 250 --follow db -``` - -if there are no errors and the server isn't crashing, great! If you have an easy way of connecting to the Database via a GUI or CLI client, do that as well and verify the database and tables are all there. - -##### Redis - -Next thing we want to try is to start up the Redis server by running the following command and checking the logs - -```bash -$ docker compose up -d redis -$ docker compose logs --tail 250 --follow redis -``` - -if there are no errors and the server isn't crashing, great! - -##### Worker - -Next thing we want to try is to start up the Worker server by running the following command and checking the logs - -```bash -$ docker compose up -d worker -$ docker compose logs --tail 250 --follow worker -``` - -The container should output a *lot* of logs from the [docker-entrypoint system](customizing.md#running-commands-on-container-start), but *eventually* you should see these messages - -* `Configuration complete; ready for start up` -* `Horizon started successfully.` - -If you see one or both of those messages, great, the worker seems to be running. - -If the worker is crash looping, inspect the logs and try to resolve the issues. - -You can consider the following additional steps: - -* Enabling `DOCKER_APP_ENTRYPOINT_DEBUG` which will show even more log output to help understand whats going on -* Enabling `DOCKER_APP_ENSURE_OWNERSHIP_PATHS` against the path(s) that might have permission issues -* Fixing permission issues directly on the host since your data should all be in the `${DOCKER_ALL_HOST_DATA_ROOT_PATH}` folder (`./docker-compose-state/data` by default) - -##### Web - -The final service, `web`, which will bring your site back online! What a journey it has been. - -Lets get to it, run these commands to start the `web` service and inspect the logs. - -```bash -$ docker compose up -d web -$ docker compose logs --tail 250 --follow web -``` - -The output should be pretty much identical to that of the `worker`, so please see that section for debugging tips if the container is crash looping. - -If the `web` service came online without issues, start the rest of the (optional) services, such as the `proxy`, if enabled, by running - -```bash -$ docker compose up -d -$ docker compose logs --tail 250 --follow -``` - -If you changed anything in the `.env` file while debugging, some containers might restart now, thats perfectly fine. - -#### Step 9) Verify - -With all services online, it's time to go to your browser and check everything is working - -1. Upload and post a picture -1. Comment on a post -1. Like a post -1. Check Horizon (`https://${APP_DOMAIN}/horizon`) for any errors -1. Check the Docker compose logs via `docker compose logs --follow` - -If everything looks fine, yay, you made it to the end! Lets do some cleanup - -#### Step 10) Final steps + cleanup - -With everything working, please take a new snapshot/backup of your server *before* we do any cleanup. A post-migration snapshot is incredibly useful, since it contains both the old and new configuration + data, making any recovery much easier in a rollback scenario later. - -Now, with all the data in the new folders, you can delete the old Docker Container volumes (if you want, completely optional) - -List all volumes, and give them a look: - -```bash -$ docker volume ls -``` - -The volumes we want to delete *ends* with the volume name (`db-data`, `app-storage`, `redis-data`, and `app-bootstrap`.) but has some prefix in front of them. - -Once you have found the volumes in in the list, delete each of them by running: - -```bash -$ docker volume rm $volume_name_in_column_two_of_the_output -``` - -You can also delete the `docker-compose.yml.old` and `.env.old` file since they are no longer needed - -```bash -$ rm docker-compose.yml.old -$ rm .env.old -``` - -### Rollback - -Oh no, something went wrong? No worries, we you got backups and a quick way back! - -#### Move `docker-compose.yml` back - -```bash -$ cp docker-compose.yml docker-compose.yml.new -$ cp docker-compose.yml.old docker-compose.yml -``` - -#### Move `.env` file back - -```bash -$ cp env.old .env -``` - -#### Go back to old source code version - -```bash -$ git checkout $commit_id_from_step_0 -``` - -#### Start things back up - -```bash -docker compose up -d -``` - -#### Verify it worked diff --git a/docker/new-server.md b/docker/new-server.md deleted file mode 100644 index dbbf325f4..000000000 --- a/docker/new-server.md +++ /dev/null @@ -1,145 +0,0 @@ -# New Pixelfed + Docker + Docker Compose server - -This guide will help you install and run Pixelfed on **your** server using [Docker Compose](https://docs.docker.com/compose/). - -## Prerequisites - -Recommendations and requirements for hardware and software needed to run Pixelfed using Docker Compose. - -It's highly recommended that you have *some* experience with Linux (e.g. Ubuntu or Debian), SSH, and lightweight server administration. - -### Server - -A VPS or dedicated server you can SSH into, for example - -* [linode.com VPS](https://www.linode.com/) -* [DigitalOcean VPS](https://digitalocean.com/) -* [Hetzner](https://www.hetzner.com/) - -### Hardware - -Hardware requirements depends on the amount of users you have (or plan to have), and how active they are. - -A safe starter/small instance hardware for 25 users and blow are: - -* **CPU/vCPU** `2` cores. -* **RAM** `2-4 GB` as your instance grow, memory requirements will increase for the database. -* **Storage** `20-50 GB` HDD is fine, but ideally SSD or NVMe, *especially* for the database. -* **Network** `100 Mbit/s` or faster. - -### Domain and DNS - -* A **Domain** (or subdomain) is needed for the Pixelfed server (for example, `pixelfed.social` or `pixelfed.mydomain.com`) -* Having the required `A`/`CNAME` DNS records for your domain (above) pointing to your server. - * Typically an `A` record for the root (sometimes shown as `@`) record for `mydomain.com`. - * Possibly an `A` record for `www.` subdomain as well. - -### Network - -* Port `80` (HTTP) and `443` (HTTPS) ports forwarded to the server. - * Example for Ubuntu using [`ufw`](https://help.ubuntu.com/community/UFW) for port `80`: `ufw allow 80` - * Example for Ubuntu using [`ufw`](https://help.ubuntu.com/community/UFW) for port `443`: `ufw allow 443` - -### Optional - -* An **Email/SMTP provider** for sending e-mails to your users, such as e-mail confirmation and notifications. -* An **Object Storage** provider for storing all images remotely, rather than locally on your server. - -#### E-mail / SMTP provider - -**NOTE**: If you don't plan to use en e-mail/SMTP provider, then make sure to set `ENFORCE_EMAIL_VERIFICATION="false"` in your `.env` file! - -There are *many* providers out there, with wildly different pricing structures, features, and reliability. - -It's beyond the cope of this document to detail which provider to pick, or how to correctly configure them, but some providers that is known to be working well - with generous free tiers and affordable packages - are included for your convince (*in no particular order*) below: - -* [Simple Email Service (SES)](https://aws.amazon.com/ses/) by Amazon Web Services (AWS) is pay-as-you-go with a cost of $0.10/1000 emails. -* [Brevo](https://www.brevo.com/) (formerly SendInBlue) has a Free Tier with 300 emails/day. -* [Postmark](https://postmarkapp.com/) has a Free Tier with 100 emails/month. -* [Forward Email](https://forwardemail.net/en/private-business-email?pricing=true) has a $3/mo/domain plan with both sending and receiving included. -* [Mailtrap](https://mailtrap.io/email-sending/) has a 1000 emails/month free-tier (their `Email Sending` product, *not* the `Email Testing` one). - -#### Object Storage - -**NOTE**: This is *entirely* optional - by default Pixelfed will store all uploads (videos, images, etc.) directly on your servers storage. - -> Object storage is a technology that stores and manages data in an unstructured format called objects. Modern organizations create and analyze large volumes of unstructured data such as photos, videos, email, web pages, sensor data, and audio files -> -> -- [*What is object storage?*](https://aws.amazon.com/what-is/object-storage/) by Amazon Web Services - -It's beyond the cope of this document to detail which provider to pick, or how to correctly configure them, but some providers that is known to be working well - with generous free tiers and affordable packages - are included for your convince (*in no particular order*) below: - -* [R2](https://www.cloudflare.com/developer-platform/r2/) by CloudFlare has cheap storage, free *egress* (e.g. people downloading images) and included (and free) Content Delivery Network (CDN). -* [B2 cloud storage](https://www.backblaze.com/cloud-storage) by Backblaze. -* [Simple Storage Service (S3)](https://aws.amazon.com/s3/) by Amazon Web Services. - -### Software - -Required software to be installed on your server - -* `git` can be installed with `apt-get install git` on Debian/Ubuntu -* `docker` can be installed by [following the official Docker documentation](https://docs.docker.com/engine/install/) - -## Getting things ready - -Connect via SSH to your server and decide where you want to install Pixelfed. - -In this guide I'm going to assume it will be installed at `/data/pixelfed`. - -1. **Install required software** as mentioned in the [Software Prerequisites section above](#software) -1. **Create the parent directory** by running `mkdir -p /data` -1. **Clone the Pixelfed repository** by running `git clone https://github.com/pixelfed/pixelfed.git /data/pixelfed` -1. **Change to the Pixelfed directory** by running `cd /data/pixelfed` - -## Modifying your settings (`.env` file) - -### Copy the example configuration file - -Pixelfed contains a default configuration file (`.env.docker`) you should use as a starter, however, before editing anything, make a copy of it and put it in the *right* place (`.env`). - -Run the following command to copy the file: `cp .env.docker .env` - -### Modifying the configuration file - -The configuration file is *quite* long, but the good news is that you can ignore *most* of it, most of the *server-specific* settings are configured for you out of the box. - -The minimum required settings you **must** change is: - -* (required) `APP_DOMAIN` which is the hostname you plan to run your Pixelfed server on (e.g. `pixelfed.social`) - must **not** include `http://` or a trailing slash (`/`)! -* (required) `DB_PASSWORD` which is the database password, you can use a service like [pwgen.io](https://pwgen.io/en/) to generate a secure one. -* (optional) `ENFORCE_EMAIL_VERIFICATION` should be set to `"false"` if you don't plan to send emails. -* (optional) `MAIL_DRIVER` and related `MAIL_*` settings if you plan to use an [email/SMTP provider](#e-mail--smtp-provider) - See [Email variables documentation](https://docs.pixelfed.org/running-pixelfed/installation/#email-variables). -* (optional) `PF_ENABLE_CLOUD` / `FILESYSTEM_CLOUD` if you plan to use an [Object Storage provider](#object-storage). - -See the [`Configure environment variables`](https://docs.pixelfed.org/running-pixelfed/installation/#app-variables) documentation for details! - -You need to mainly focus on following sections - -* [App variables](https://docs.pixelfed.org/running-pixelfed/installation/#app-variables) -* [Email variables](https://docs.pixelfed.org/running-pixelfed/installation/#email-variables) - -You can skip the following sections, since they are already configured/automated for you: - -* `Redis` -* `Database` (except for `DB_PASSWORD`) -* `One-time setup tasks` - -### Starting the service - -With everything in place and (hopefully) well-configured, we can now go ahead and start our services by running - -```shell -docker compose up -d -``` - -This will download all the required Docker images, start the containers, and being the automatic setup. - -You can follow the logs by running `docker compose logs` - you might want to scroll to the top to logs from the start. - -You can use the CLI flag `--tail=100` to only see the most recent (`100` in this example) log lines for each container. - -You can use the CLI flag `--follow` to continue to see log output from the containers. - -You can combine `--tail=100` and `--follow` like this `docker compose logs --tail=100 --follow`. - -If you only care about specific contaieners, you can add them to the end of the command like this `docker compose logs web worker proxy`. diff --git a/docker/runtimes.md b/docker/runtimes.md deleted file mode 100644 index 68d7ee943..000000000 --- a/docker/runtimes.md +++ /dev/null @@ -1,94 +0,0 @@ -# Pixelfed Docker container runtimes - -The Pixelfed Dockerfile support multiple target *runtimes* ([Apache](#apache), [Nginx + FPM](#nginx), and [fpm](#fpm)). - -You can consider a *runtime* target as individual Dockerfiles, but instead, all of them are build from the same optimized Dockerfile, sharing +90% of their configuration and packages. - -**If you are unsure of which runtime to choose, please use the [Apache runtime](#apache) it's the most straightforward one and also the default** - -## Apache - -Building a custom Pixelfed Docker image using Apache + mod_php can be achieved the following way. - -### docker build (Apache) - -```shell -docker build \ - -f contrib/docker/Dockerfile \ - --target apache-runtime \ - --tag / \ - . -``` - -### docker compose (Apache) - -```yaml -version: "3" - -services: - app: - build: - context: . - dockerfile: contrib/docker/Dockerfile - target: apache-runtime -``` - -## Nginx - -Building a custom Pixelfed Docker image using nginx + FPM can be achieved the following way. - -### docker build (nginx) - -```shell -docker build \ - -f contrib/docker/Dockerfile \ - --target nginx-runtime \ - --build-arg 'PHP_BASE_TYPE=fpm' \ - --tag / \ - . -``` - -### docker compose (nginx) - -```yaml -version: "3" - -services: - app: - build: - context: . - dockerfile: contrib/docker/Dockerfile - target: nginx-runtime - args: - PHP_BASE_TYPE: fpm -``` - -## FPM - -Building a custom Pixelfed Docker image using FPM (only) can be achieved the following way. - -### docker build (fpm) - -```shell -docker build \ - -f contrib/docker/Dockerfile \ - --target fpm-runtime \ - --build-arg 'PHP_BASE_TYPE=fpm' \ - --tag / \ - . -``` - -### docker compose (fpm) - -```yaml -version: "3" - -services: - app: - build: - context: . - dockerfile: contrib/docker/Dockerfile - target: fpm-runtime - args: - PHP_BASE_TYPE: fpm -``` From a940bedf9e257c77888e37c433b523a6091647eb Mon Sep 17 00:00:00 2001 From: Christian Winther Date: Thu, 18 Jan 2024 16:23:05 +0000 Subject: [PATCH 107/173] reference docs PR --- docker/README.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/docker/README.md b/docker/README.md index 23584a4ab..5230f60fd 100644 --- a/docker/README.md +++ b/docker/README.md @@ -1,3 +1,5 @@ # Pixelfed + Docker + Docker Compose -Please see the [Pixelfed Docs (Next)](https://jippi.github.io/pixelfed-docs-next/pr-preview/pr-1/running-pixelfed/) for current documentation on Docker usage +Please see the [Pixelfed Docs (Next)](https://jippi.github.io/pixelfed-docs-next/pr-preview/pr-1/running-pixelfed/) for current documentation on Docker usage. + +The docs can be [reviewed in the pixelfed/docs-next](https://github.com/pixelfed/docs-next/pull/1) repository. From 70f4bc06a824451c671f31e13e157461caae4244 Mon Sep 17 00:00:00 2001 From: Christian Winther Date: Thu, 18 Jan 2024 17:29:15 +0000 Subject: [PATCH 108/173] remove unsuded .gitmodules --- .gitmodules | 10 ---------- 1 file changed, 10 deletions(-) delete mode 100644 .gitmodules diff --git a/.gitmodules b/.gitmodules deleted file mode 100644 index 6fe990290..000000000 --- a/.gitmodules +++ /dev/null @@ -1,10 +0,0 @@ - -[submodule "tests/shell/bats"] - path = tests/shell/bats - url = https://github.com/bats-core/bats-core.git -[submodule "tests/shell/test_helper/bats-support"] - path = tests/shell/test_helper/bats-support - url = https://github.com/bats-core/bats-support.git -[submodule "tests/shell/test_helper/bats-assert"] - path = tests/shell/test_helper/bats-assert - url = https://github.com/bats-core/bats-assert.git From 347ac6f82b78eae660d8880008b11ffc7a9abd5a Mon Sep 17 00:00:00 2001 From: Christian Winther Date: Thu, 18 Jan 2024 17:33:24 +0000 Subject: [PATCH 109/173] fix Dockerfile indent --- Dockerfile | 44 ++++++++++++++++++++++++-------------------- 1 file changed, 24 insertions(+), 20 deletions(-) diff --git a/Dockerfile b/Dockerfile index a5930aec0..5158f2348 100644 --- a/Dockerfile +++ b/Dockerfile @@ -87,7 +87,12 @@ ARG BUILDOS ARG GOMPLATE_VERSION RUN set -ex \ - && curl --silent --show-error --location --output /usr/local/bin/gomplate https://github.com/hairyhenderson/gomplate/releases/download/${GOMPLATE_VERSION}/gomplate_${BUILDOS}-${BUILDARCH} \ + && curl \ + --silent \ + --show-error \ + --location \ + --output /usr/local/bin/gomplate \ + https://github.com/hairyhenderson/gomplate/releases/download/${GOMPLATE_VERSION}/gomplate_${BUILDOS}-${BUILDARCH} \ && chmod +x /usr/local/bin/gomplate \ && /usr/local/bin/gomplate --version @@ -113,8 +118,8 @@ ENV DEBIAN_FRONTEND="noninteractive" SHELL ["/bin/bash", "-c"] RUN set -ex \ - && mkdir -pv /var/www/ \ - && chown -R ${RUNTIME_UID}:${RUNTIME_GID} /var/www + && mkdir -pv /var/www/ \ + && chown -R ${RUNTIME_UID}:${RUNTIME_GID} /var/www WORKDIR /var/www/ @@ -124,7 +129,7 @@ ENV DOTENV_LINTER_VERSION="${DOTENV_LINTER_VERSION}" # Install and configure base layer COPY docker/shared/root/docker/install/base.sh /docker/install/base.sh RUN --mount=type=cache,id=pixelfed-apt-${PHP_VERSION}-${PHP_DEBIAN_RELEASE}-${TARGETPLATFORM},sharing=locked,target=/var/lib/apt \ - --mount=type=cache,id=pixelfed-apt-cache-${PHP_VERSION}-${PHP_DEBIAN_RELEASE}-${TARGETPLATFORM},sharing=locked,target=/var/cache/apt \ + --mount=type=cache,id=pixelfed-apt-cache-${PHP_VERSION}-${PHP_DEBIAN_RELEASE}-${TARGETPLATFORM},sharing=locked,target=/var/cache/apt \ /docker/install/base.sh ####################################################### @@ -151,7 +156,7 @@ ENV PHP_PECL_EXTENSIONS=${PHP_PECL_EXTENSIONS} COPY docker/shared/root/docker/install/php-extensions.sh /docker/install/php-extensions.sh RUN --mount=type=cache,id=pixelfed-php-${PHP_VERSION}-${PHP_DEBIAN_RELEASE}-${TARGETPLATFORM},sharing=locked,target=/usr/src/php \ --mount=type=cache,id=pixelfed-apt-${PHP_VERSION}-${PHP_DEBIAN_RELEASE}-${TARGETPLATFORM},sharing=locked,target=/var/lib/apt \ - --mount=type=cache,id=pixelfed-apt-cache-${PHP_VERSION}-${PHP_DEBIAN_RELEASE}-${TARGETPLATFORM},sharing=locked,target=/var/cache/apt \ + --mount=type=cache,id=pixelfed-apt-cache-${PHP_VERSION}-${PHP_DEBIAN_RELEASE}-${TARGETPLATFORM},sharing=locked,target=/var/cache/apt \ /docker/install/php-extensions.sh ####################################################### @@ -187,8 +192,8 @@ COPY --chown=${RUNTIME_UID}:${RUNTIME_GID} composer.json composer.lock /var/www/ # Install composer dependencies # NOTE: we skip the autoloader generation here since we don't have all files avaliable (yet) RUN --mount=type=cache,id=pixelfed-composer-${PHP_VERSION}-${PHP_DEBIAN_RELEASE}-${TARGETPLATFORM},sharing=locked,target=/cache/composer \ - set -ex \ - && composer install --prefer-dist --no-autoloader --ignore-platform-reqs + set -ex \ + && composer install --prefer-dist --no-autoloader --ignore-platform-reqs # Copy all other files over COPY --chown=${RUNTIME_UID}:${RUNTIME_GID} . /var/www/ @@ -220,14 +225,14 @@ USER ${RUNTIME_UID}:${RUNTIME_GID} # Generate optimized autoloader now that we have all files around RUN set -ex \ - && composer dump-autoload --optimize + && composer dump-autoload --optimize USER root # for detail why storage is copied this way, pls refer to https://github.com/pixelfed/pixelfed/pull/2137#discussion_r434468862 RUN set -ex \ - && cp --recursive --link --preserve=all storage storage.skel \ - && rm -rf html && ln -s public html + && cp --recursive --link --preserve=all storage storage.skel \ + && rm -rf html && ln -s public html COPY docker/shared/root / @@ -242,8 +247,8 @@ FROM shared-runtime AS apache-runtime COPY docker/apache/root / RUN set -ex \ - && a2enmod rewrite remoteip proxy proxy_http \ - && a2enconf remoteip + && a2enmod rewrite remoteip proxy proxy_http \ + && a2enconf remoteip CMD ["apache2-foreground"] @@ -272,14 +277,13 @@ ARG TARGETPLATFORM # Install nginx dependencies RUN --mount=type=cache,id=pixelfed-apt-lists-${PHP_VERSION}-${PHP_DEBIAN_RELEASE}-${TARGETPLATFORM},sharing=locked,target=/var/lib/apt/lists \ - --mount=type=cache,id=pixelfed-apt-cache-${PHP_VERSION}-${PHP_DEBIAN_RELEASE}-${TARGETPLATFORM},sharing=locked,target=/var/cache/apt \ - set -ex \ - && gpg1 --keyserver "hkp://keyserver.ubuntu.com:80" --keyserver-options timeout=10 --recv-keys "${NGINX_GPGKEY}" \ - && gpg1 --export "$NGINX_GPGKEY" > "$NGINX_GPGKEY_PATH" \ - && echo "deb [signed-by=${NGINX_GPGKEY_PATH}] https://nginx.org/packages/mainline/debian/ ${PHP_DEBIAN_RELEASE} nginx" >> /etc/apt/sources.list.d/nginx.list \ - && apt-get update \ - && apt-get install -y --no-install-recommends \ - nginx=${NGINX_VERSION}* + --mount=type=cache,id=pixelfed-apt-cache-${PHP_VERSION}-${PHP_DEBIAN_RELEASE}-${TARGETPLATFORM},sharing=locked,target=/var/cache/apt \ + set -ex \ + && gpg1 --keyserver "hkp://keyserver.ubuntu.com:80" --keyserver-options timeout=10 --recv-keys "${NGINX_GPGKEY}" \ + && gpg1 --export "$NGINX_GPGKEY" > "$NGINX_GPGKEY_PATH" \ + && echo "deb [signed-by=${NGINX_GPGKEY_PATH}] https://nginx.org/packages/mainline/debian/ ${PHP_DEBIAN_RELEASE} nginx" >> /etc/apt/sources.list.d/nginx.list \ + && apt-get update \ + && apt-get install -y --no-install-recommends nginx=${NGINX_VERSION}* # copy docker entrypoints from the *real* nginx image directly COPY --link --from=nginx-image /docker-entrypoint.d /docker/entrypoint.d/ From 86724535960603c33ecd4cf1a847d70a7dcc2a89 Mon Sep 17 00:00:00 2001 From: Christian Winther Date: Mon, 22 Jan 2024 13:48:01 +0000 Subject: [PATCH 110/173] fix configuration loading before referencing config --- docker/shared/root/docker/entrypoint.d/11-first-time-setup.sh | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/docker/shared/root/docker/entrypoint.d/11-first-time-setup.sh b/docker/shared/root/docker/entrypoint.d/11-first-time-setup.sh index d3d83c532..fb5c86a39 100755 --- a/docker/shared/root/docker/entrypoint.d/11-first-time-setup.sh +++ b/docker/shared/root/docker/entrypoint.d/11-first-time-setup.sh @@ -6,6 +6,8 @@ source "${ENTRYPOINT_ROOT}/helpers.sh" entrypoint-set-script-name "$0" +load-config-files + # Allow automatic applying of outstanding/new migrations on startup : "${DOCKER_APP_RUN_ONE_TIME_SETUP_TASKS:=1}" @@ -16,7 +18,6 @@ if is-false "${DOCKER_APP_RUN_ONE_TIME_SETUP_TASKS}"; then exit 0 fi -load-config-files await-database-ready # Following https://docs.pixelfed.org/running-pixelfed/installation/#one-time-setup-tasks From c9a3e3aea7c1444017c59eedf36710493a614494 Mon Sep 17 00:00:00 2001 From: Christian Winther Date: Tue, 23 Jan 2024 19:34:48 +0000 Subject: [PATCH 111/173] automatically + by default turn off proxy acme if proxy is off --- .env.docker | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.env.docker b/.env.docker index 25914af89..c3e0a55ae 100644 --- a/.env.docker +++ b/.env.docker @@ -1105,7 +1105,7 @@ DOCKER_WORKER_HEALTHCHECK_INTERVAL="${DOCKER_ALL_DEFAULT_HEALTHCHECK_INTERVAL}" #DOCKER_PROXY_PROFILE="" # Set this to a non-empty value (e.g. "disabled") to disable the [proxy-acme] service -#DOCKER_PROXY_ACME_PROFILE="${DOCKER_PROXY_PROFILE:-}" +DOCKER_PROXY_ACME_PROFILE="${DOCKER_PROXY_PROFILE:-}" # How often Docker health check should run for [proxy] service DOCKER_PROXY_HEALTHCHECK_INTERVAL="${DOCKER_ALL_DEFAULT_HEALTHCHECK_INTERVAL}" From f263dfc4e10f192cb2646f14e39d9d3b1a06d18e Mon Sep 17 00:00:00 2001 From: Christian Winther Date: Fri, 26 Jan 2024 14:41:44 +0000 Subject: [PATCH 112/173] apply editorconfig + shellcheck + shellfmt to all files --- .editorconfig | 6 +- .gitignore | 1 - .../docker/entrypoint.d/01-permissions.sh | 2 +- .../root/docker/entrypoint.d/05-templating.sh | 2 +- docker/shared/root/docker/entrypoint.sh | 56 +++--- docker/shared/root/docker/helpers.sh | 190 +++++++++++------- docker/shared/root/docker/install/base.sh | 6 +- 7 files changed, 149 insertions(+), 114 deletions(-) diff --git a/.editorconfig b/.editorconfig index 8b31962a6..9551fdc60 100644 --- a/.editorconfig +++ b/.editorconfig @@ -8,20 +8,20 @@ charset = utf-8 trim_trailing_whitespace = true insert_final_newline = true -[{*.yml,*.yaml}] +[*.{yml,yaml}] indent_style = space indent_size = 2 -[*.sh] +[*.{sh,envsh,env,env*}] indent_style = space indent_size = 4 +# ShellCheck config shell_variant = bash binary_next_line = true case-indent = true switch_case_indent = true space_redirects = true -keep_padding = true function_next_line = true simplify = true space-redirects = true diff --git a/.gitignore b/.gitignore index a5cdf3af1..689c2e13a 100644 --- a/.gitignore +++ b/.gitignore @@ -8,7 +8,6 @@ /.composer/ /.idea /.vagrant -/.vscode /docker-compose-state/ /node_modules /public/hot diff --git a/docker/shared/root/docker/entrypoint.d/01-permissions.sh b/docker/shared/root/docker/entrypoint.d/01-permissions.sh index 11766a742..f5624721b 100755 --- a/docker/shared/root/docker/entrypoint.d/01-permissions.sh +++ b/docker/shared/root/docker/entrypoint.d/01-permissions.sh @@ -16,7 +16,7 @@ run-as-current-user chown --verbose "${RUNTIME_UID}:${RUNTIME_GID}" "./storage" : "${DOCKER_APP_ENSURE_OWNERSHIP_PATHS:=""}" declare -a ensure_ownership_paths=() -IFS=' ' read -ar ensure_ownership_paths <<<"${DOCKER_APP_ENSURE_OWNERSHIP_PATHS}" +IFS=' ' read -ar ensure_ownership_paths <<< "${DOCKER_APP_ENSURE_OWNERSHIP_PATHS}" if [[ ${#ensure_ownership_paths[@]} == 0 ]]; then log-info "No paths has been configured for ownership fixes via [\$DOCKER_APP_ENSURE_OWNERSHIP_PATHS]." diff --git a/docker/shared/root/docker/entrypoint.d/05-templating.sh b/docker/shared/root/docker/entrypoint.d/05-templating.sh index 4d229b11c..23d01487a 100755 --- a/docker/shared/root/docker/entrypoint.d/05-templating.sh +++ b/docker/shared/root/docker/entrypoint.d/05-templating.sh @@ -51,7 +51,7 @@ find "${ENTRYPOINT_TEMPLATE_DIR}" -follow -type f -print | while read -r templat # Render the template log-info "Running [gomplate] on [${template_file}] --> [${output_file_path}]" - gomplate <"${template_file}" >"${output_file_path}" + gomplate < "${template_file}" > "${output_file_path}" # Show the diff from the envsubst command if is-true "${ENTRYPOINT_SHOW_TEMPLATE_DIFF}"; then diff --git a/docker/shared/root/docker/entrypoint.sh b/docker/shared/root/docker/entrypoint.sh index ed698250b..57378d23f 100755 --- a/docker/shared/root/docker/entrypoint.sh +++ b/docker/shared/root/docker/entrypoint.sh @@ -25,7 +25,7 @@ entrypoint-set-script-name "entrypoint.sh" # Convert ENTRYPOINT_SKIP_SCRIPTS into a native bash array for easier lookup declare -a skip_scripts # shellcheck disable=SC2034 -IFS=' ' read -ar skip_scripts <<<"$ENTRYPOINT_SKIP_SCRIPTS" +IFS=' ' read -ar skip_scripts <<< "$ENTRYPOINT_SKIP_SCRIPTS" # Ensure the entrypoint root folder exists mkdir -p "${ENTRYPOINT_D_ROOT}" @@ -52,40 +52,40 @@ find "${ENTRYPOINT_D_ROOT}" -follow -type f -print | sort -V | while read -r fil # Inspect the file extension of the file we're processing case "${file}" in - *.envsh) - if ! is-executable "${file}"; then - # warn on shell scripts without exec bit - log-error-and-exit "File [${file}] is not executable (please 'chmod +x' it)" - fi + *.envsh) + if ! is-executable "${file}"; then + # warn on shell scripts without exec bit + log-error-and-exit "File [${file}] is not executable (please 'chmod +x' it)" + fi - log-info "${section_message_color}============================================================${color_clear}" - log-info "${section_message_color}Sourcing [${file}]${color_clear}" - log-info "${section_message_color}============================================================${color_clear}" + log-info "${section_message_color}============================================================${color_clear}" + log-info "${section_message_color}Sourcing [${file}]${color_clear}" + log-info "${section_message_color}============================================================${color_clear}" - # shellcheck disable=SC1090 - source "${file}" + # shellcheck disable=SC1090 + source "${file}" - # the sourced file will (should) than the log prefix, so this restores our own - # "global" log prefix once the file is done being sourced - entrypoint-restore-script-name - ;; + # the sourced file will (should) than the log prefix, so this restores our own + # "global" log prefix once the file is done being sourced + entrypoint-restore-script-name + ;; - *.sh) - if ! is-executable "${file}"; then - # warn on shell scripts without exec bit - log-error-and-exit "File [${file}] is not executable (please 'chmod +x' it)" - fi + *.sh) + if ! is-executable "${file}"; then + # warn on shell scripts without exec bit + log-error-and-exit "File [${file}] is not executable (please 'chmod +x' it)" + fi - log-info "${section_message_color}============================================================${color_clear}" - log-info "${section_message_color}Executing [${file}]${color_clear}" - log-info "${section_message_color}============================================================${color_clear}" + log-info "${section_message_color}============================================================${color_clear}" + log-info "${section_message_color}Executing [${file}]${color_clear}" + log-info "${section_message_color}============================================================${color_clear}" - "${file}" - ;; + "${file}" + ;; - *) - log-warning "Ignoring unrecognized file [${file}]" - ;; + *) + log-warning "Ignoring unrecognized file [${file}]" + ;; esac done diff --git a/docker/shared/root/docker/helpers.sh b/docker/shared/root/docker/helpers.sh index fb8c11c97..5826f3c9a 100644 --- a/docker/shared/root/docker/helpers.sh +++ b/docker/shared/root/docker/helpers.sh @@ -43,7 +43,8 @@ cd /var/www || log-error-and-exit "could not change to /var/www" # @description Restore the log prefix to the previous value that was captured in [entrypoint-set-script-name ] # @arg $1 string The name (or path) of the entrypoint script being run -function entrypoint-set-script-name() { +function entrypoint-set-script-name() +{ script_name_previous="${script_name}" script_name="${1}" @@ -51,7 +52,8 @@ function entrypoint-set-script-name() { } # @description Restore the log prefix to the previous value that was captured in [entrypoint-set-script-name ] -function entrypoint-restore-script-name() { +function entrypoint-restore-script-name() +{ entrypoint-set-script-name "${script_name_previous}" } @@ -59,7 +61,8 @@ function entrypoint-restore-script-name() { # @arg $@ string The command to run # @exitcode 0 if the command succeeeds # @exitcode 1 if the command fails -function run-as-runtime-user() { +function run-as-runtime-user() +{ run-command-as "${runtime_username}" "${@}" } @@ -67,7 +70,8 @@ function run-as-runtime-user() { # @arg $@ string The command to run # @exitcode 0 if the command succeeeds # @exitcode 1 if the command fails -function run-as-current-user() { +function run-as-current-user() +{ run-command-as "$(id -un)" "${@}" } @@ -76,7 +80,8 @@ function run-as-current-user() { # @arg $@ string The command to run # @exitcode 0 If the command succeeeds # @exitcode 1 If the command fails -function run-command-as() { +function run-command-as() +{ local -i exit_code local target_user @@ -105,7 +110,8 @@ function run-command-as() { # @description Streams stdout from the command and echo it # with log prefixing. # @see stream-prefix-command-output -function stream-stdout-handler() { +function stream-stdout-handler() +{ while read -r line; do log-info "(stdout) ${line}" done @@ -114,7 +120,8 @@ function stream-stdout-handler() { # @description Streams stderr from the command and echo it # with a bit of color and log prefixing. # @see stream-prefix-command-output -function stream-stderr-handler() { +function stream-stderr-handler() +{ while read -r line; do log-info-stderr "(${error_message_color}stderr${color_clear}) ${line}" done @@ -124,7 +131,8 @@ function stream-stderr-handler() { # and stdout/stderr prefix. If stdout or stderr is being piped/redirected # it will automatically fall back to non-prefixed output. # @arg $@ string The command to run -function stream-prefix-command-output() { +function stream-prefix-command-output() +{ local stdout=stream-stdout-handler local stderr=stream-stderr-handler @@ -146,7 +154,8 @@ function stream-prefix-command-output() { # @description Print the given error message to stderr # @arg $message string A error message. # @stderr The error message provided with log prefix -function log-error() { +function log-error() +{ local msg if [[ $# -gt 0 ]]; then @@ -157,14 +166,15 @@ function log-error() { log-error-and-exit "[${FUNCNAME[0]}] did not receive any input arguments and STDIN is empty" fi - echo -e "${error_message_color}${log_prefix}ERROR -${color_clear} ${msg}" >/dev/stderr + echo -e "${error_message_color}${log_prefix}ERROR -${color_clear} ${msg}" > /dev/stderr } # @description Print the given error message to stderr and exit 1 # @arg $@ string A error message. # @stderr The error message provided with log prefix # @exitcode 1 -function log-error-and-exit() { +function log-error-and-exit() +{ log-error "$@" show-call-stack @@ -175,7 +185,8 @@ function log-error-and-exit() { # @description Print the given warning message to stderr # @arg $@ string A warning message. # @stderr The warning message provided with log prefix -function log-warning() { +function log-warning() +{ local msg if [[ $# -gt 0 ]]; then @@ -186,13 +197,14 @@ function log-warning() { log-error-and-exit "[${FUNCNAME[0]}] did not receive any input arguments and STDIN is empty" fi - echo -e "${warn_message_color}${log_prefix}WARNING -${color_clear} ${msg}" >/dev/stderr + echo -e "${warn_message_color}${log_prefix}WARNING -${color_clear} ${msg}" > /dev/stderr } # @description Print the given message to stdout unless [ENTRYPOINT_QUIET_LOGS] is set # @arg $@ string A info message. # @stdout The info message provided with log prefix unless $ENTRYPOINT_QUIET_LOGS -function log-info() { +function log-info() +{ local msg if [[ $# -gt 0 ]]; then @@ -211,7 +223,8 @@ function log-info() { # @description Print the given message to stderr unless [ENTRYPOINT_QUIET_LOGS] is set # @arg $@ string A info message. # @stderr The info message provided with log prefix unless $ENTRYPOINT_QUIET_LOGS -function log-info-stderr() { +function log-info-stderr() +{ local msg if [[ $# -gt 0 ]]; then @@ -223,13 +236,14 @@ function log-info-stderr() { fi if [ -z "${ENTRYPOINT_QUIET_LOGS:-}" ]; then - echo -e "${notice_message_color}${log_prefix}${color_clear}${msg}" >/dev/stderr + echo -e "${notice_message_color}${log_prefix}${color_clear}${msg}" > /dev/stderr fi } # @description Loads the dot-env files used by Docker and track the keys present in the configuration. # @sets seen_dot_env_variables array List of config keys discovered during loading -function load-config-files() { +function load-config-files() +{ # Associative array (aka map/dictionary) holding the unique keys found in dot-env files local -A _tmp_dot_env_keys @@ -260,7 +274,8 @@ function load-config-files() { # @arg $2 array The haystack (array) to search in # @exitcode 0 If $needle was found in $haystack # @exitcode 1 If $needle was *NOT* found in $haystack -function in-array() { +function in-array() +{ local -r needle="\<${1}\>" local -nr haystack=$2 @@ -271,7 +286,8 @@ function in-array() { # @arg $1 string The path to check # @exitcode 0 If $1 has executable bit # @exitcode 1 If $1 does *NOT* have executable bit -function is-executable() { +function is-executable() +{ [[ -x "$1" ]] } @@ -279,7 +295,8 @@ function is-executable() { # @arg $1 string The path to check # @exitcode 0 If $1 is writable # @exitcode 1 If $1 is *NOT* writable -function is-writable() { +function is-writable() +{ [[ -w "$1" ]] } @@ -287,7 +304,8 @@ function is-writable() { # @arg $1 string The path to check # @exitcode 0 If $1 exists # @exitcode 1 If $1 does *NOT* exists -function path-exists() { +function path-exists() +{ [[ -e "$1" ]] } @@ -295,29 +313,33 @@ function path-exists() { # @arg $1 string The path to check # @exitcode 0 If $1 exists # @exitcode 1 If $1 does *NOT* exists -function file-exists() { +function file-exists() +{ [[ -f "$1" ]] } # @description Checks if $1 contains any files or not # @arg $1 string The path to check # @exitcode 0 If $1 contains files # @exitcode 1 If $1 does *NOT* contain files -function is-directory-empty() { - ! find "${1}" -mindepth 1 -maxdepth 1 -type f -print -quit 2>/dev/null | read -r +function is-directory-empty() +{ + ! find "${1}" -mindepth 1 -maxdepth 1 -type f -print -quit 2> /dev/null | read -r } # @description Ensures a directory exists (via mkdir) # @arg $1 string The path to create # @exitcode 0 If $1 If the path exists *or* was created # @exitcode 1 If $1 If the path does *NOT* exists and could *NOT* be created -function ensure-directory-exists() { +function ensure-directory-exists() +{ stream-prefix-command-output mkdir -pv "$@" } # @description Find the relative path for a entrypoint script by removing the ENTRYPOINT_D_ROOT prefix # @arg $1 string The path to manipulate # @stdout The relative path to the entrypoint script -function get-entrypoint-script-name() { +function get-entrypoint-script-name() +{ echo "${1#"$ENTRYPOINT_D_ROOT"}" } @@ -325,7 +347,8 @@ function get-entrypoint-script-name() { # The 'lock' is only written if the passed in command ($2) successfully ran. # @arg $1 string The name of the lock file # @arg $@ string The command to run -function only-once() { +function only-once() +{ local name="${1:-$script_name}" local file="${docker_once_path}/${name}" shift @@ -349,7 +372,8 @@ function only-once() { # @description Best effort file lock to ensure *something* is not running in multiple containers. # The script uses "trap" to clean up after itself if the script crashes # @arg $1 string The lock identifier -function acquire-lock() { +function acquire-lock() +{ local name="${1:-$script_name}" local file="${docker_locks_path}/${name}" @@ -371,7 +395,8 @@ function acquire-lock() { # @description Release a lock aquired by [acquire-lock] # @arg $1 string The lock identifier -function release-lock() { +function release-lock() +{ local name="${1:-$script_name}" local file="${docker_locks_path}/${name}" @@ -384,7 +409,8 @@ function release-lock() { # the bash [trap] logic # @arg $1 string The command to run # @arg $@ string The list of trap signals to register -function on-trap() { +function on-trap() +{ local trap_add_cmd=$1 shift || log-error-and-exit "${FUNCNAME[0]} usage error" @@ -394,13 +420,16 @@ function on-trap() { # of trap -p # # shellcheck disable=SC2317 - extract_trap_cmd() { printf '%s\n' "${3:-}"; } + extract_trap_cmd() + { + printf '%s\n' "${3:-}" + } # print existing trap command with newline eval "extract_trap_cmd $(trap -p "${trap_add_name}")" # print the new trap command printf '%s\n' "${trap_add_cmd}" - )" "${trap_add_name}" || - log-error-and-exit "unable to add to trap ${trap_add_name}" + )" "${trap_add_name}" \ + || log-error-and-exit "unable to add to trap ${trap_add_name}" done } @@ -411,42 +440,43 @@ function on-trap() { declare -f -t on-trap # @description Waits for the database to be healthy and responsive -function await-database-ready() { +function await-database-ready() +{ log-info "❓ Waiting for database to be ready" load-config-files case "${DB_CONNECTION:-}" in - mysql) - # shellcheck disable=SC2154 - while ! echo "SELECT 1" | mysql --user="${DB_USERNAME}" --password="${DB_PASSWORD}" --host="${DB_HOST}" "${DB_DATABASE}" --silent >/dev/null; do - staggered-sleep - done - ;; + mysql) + # shellcheck disable=SC2154 + while ! echo "SELECT 1" | mysql --user="${DB_USERNAME}" --password="${DB_PASSWORD}" --host="${DB_HOST}" "${DB_DATABASE}" --silent > /dev/null; do + staggered-sleep + done + ;; - pgsql) - # shellcheck disable=SC2154 - while ! echo "SELECT 1" | PGPASSWORD="${DB_PASSWORD}" psql --user="${DB_USERNAME}" --host="${DB_HOST}" "${DB_DATABASE}" >/dev/null; do - staggered-sleep - done - ;; + pgsql) + # shellcheck disable=SC2154 + while ! echo "SELECT 1" | PGPASSWORD="${DB_PASSWORD}" psql --user="${DB_USERNAME}" --host="${DB_HOST}" "${DB_DATABASE}" > /dev/null; do + staggered-sleep + done + ;; - sqlsrv) - log-warning "Don't know how to check if SQLServer is *truely* ready or not - so will just check if we're able to connect to it" + sqlsrv) + log-warning "Don't know how to check if SQLServer is *truely* ready or not - so will just check if we're able to connect to it" - # shellcheck disable=SC2154 - while ! timeout 1 bash -c "cat < /dev/null > /dev/tcp/${DB_HOST}/${DB_PORT}"; do - staggered-sleep - done - ;; + # shellcheck disable=SC2154 + while ! timeout 1 bash -c "cat < /dev/null > /dev/tcp/${DB_HOST}/${DB_PORT}"; do + staggered-sleep + done + ;; - sqlite) - log-info "${success_message_color}sqlite is always ready${color_clear}" - ;; + sqlite) + log-info "${success_message_color}sqlite is always ready${color_clear}" + ;; - *) - log-error-and-exit "Unknown database type: [${DB_CONNECTION:-}]" - ;; + *) + log-error-and-exit "Unknown database type: [${DB_CONNECTION:-}]" + ;; esac log-info "${success_message_color}✅ Successfully connected to database${color_clear}" @@ -454,14 +484,16 @@ function await-database-ready() { # @description sleeps between 1 and 3 seconds to ensure a bit of randomness # in multiple scripts/containers doing work almost at the same time. -function staggered-sleep() { +function staggered-sleep() +{ sleep "$(get-random-number-between 1 3)" } # @description Helper function to get a random number between $1 and $2 # @arg $1 int Minimum number in the range (inclusive) # @arg $2 int Maximum number in the range (inclusive) -function get-random-number-between() { +function get-random-number-between() +{ local -i from=${1:-1} local -i to="${2:-10}" @@ -470,7 +502,8 @@ function get-random-number-between() { # @description Helper function to show the bask call stack when something # goes wrong. Is super useful when needing to debug an issue -function show-call-stack() { +function show-call-stack() +{ local stack_size=${#FUNCNAME[@]} local func local lineno @@ -493,7 +526,8 @@ function show-call-stack() { # returns [0] if input is truthy, otherwise [1] # @arg $1 string The string to evaluate # @see as-boolean -function is-true() { +function is-true() +{ as-boolean "${1:-}" && return 0 return 1 @@ -503,7 +537,8 @@ function is-true() { # returns [0] if input is falsey, otherwise [1] # @arg $1 string The string to evaluate # @see as-boolean -function is-false() { +function is-false() +{ as-boolean "${1:-}" && return 1 return 0 @@ -516,28 +551,29 @@ function is-false() { # This is a bit confusing, *especially* in a PHP world where [1] would be truthy and # [0] would be falsely as return values # @arg $1 string The string to evaluate -function as-boolean() { +function as-boolean() +{ local input="${1:-}" local var="${input,,}" # convert input to lower-case case "$var" in - 1 | true) - log-info "[as-boolean] variable [${var}] was detected as truthy/true, returning [0]" + 1 | true) + log-info "[as-boolean] variable [${var}] was detected as truthy/true, returning [0]" - return 0 - ;; + return 0 + ;; - 0 | false) - log-info "[as-boolean] variable [${var}] was detected as falsey/false, returning [1]" + 0 | false) + log-info "[as-boolean] variable [${var}] was detected as falsey/false, returning [1]" - return 1 - ;; + return 1 + ;; - *) - log-warning "[as-boolean] variable [${var}] could not be detected as true or false, returning [1] (false) as default" + *) + log-warning "[as-boolean] variable [${var}] could not be detected as true or false, returning [1] (false) as default" - return 1 - ;; + return 1 + ;; esac } diff --git a/docker/shared/root/docker/install/base.sh b/docker/shared/root/docker/install/base.sh index 7fa43b0f9..e20788b56 100755 --- a/docker/shared/root/docker/install/base.sh +++ b/docker/shared/root/docker/install/base.sh @@ -3,13 +3,13 @@ set -ex -o errexit -o nounset -o pipefail # Ensure we keep apt cache around in a Docker environment rm -f /etc/apt/apt.conf.d/docker-clean -echo 'Binary::apt::APT::Keep-Downloaded-Packages "true";' >/etc/apt/apt.conf.d/keep-cache +echo 'Binary::apt::APT::Keep-Downloaded-Packages "true";' > /etc/apt/apt.conf.d/keep-cache # Don't install recommended packages by default -echo 'APT::Install-Recommends "false";' >>/etc/apt/apt.conf +echo 'APT::Install-Recommends "false";' >> /etc/apt/apt.conf # Don't install suggested packages by default -echo 'APT::Install-Suggests "false";' >>/etc/apt/apt.conf +echo 'APT::Install-Suggests "false";' >> /etc/apt/apt.conf declare -a packages=() From 627fffd1ce5b6160772608dca2b95e0b0d4b3c25 Mon Sep 17 00:00:00 2001 From: Christian Winther Date: Fri, 26 Jan 2024 14:42:24 +0000 Subject: [PATCH 113/173] add .vscode with recommended plugins + settings which will give a *great* out of the box experience for folks wanting to contribute and uses VS Code --- .vscode/extensions.json | 13 +++++++++++++ .vscode/settings.json | 7 +++++++ 2 files changed, 20 insertions(+) create mode 100644 .vscode/extensions.json create mode 100644 .vscode/settings.json diff --git a/.vscode/extensions.json b/.vscode/extensions.json new file mode 100644 index 000000000..ea1c99893 --- /dev/null +++ b/.vscode/extensions.json @@ -0,0 +1,13 @@ +{ + "recommendations": [ + "foxundermoon.shell-format", + "timonwong.shellcheck", + "jetmartin.bats", + "aaron-bond.better-comments", + "streetsidesoftware.code-spell-checker", + "editorconfig.editorconfig", + "github.vscode-github-actions", + "bmewburn.vscode-intelephense-client", + "redhat.vscode-yaml" + ] +} diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 000000000..9a1ddb073 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,7 @@ +{ + "shellformat.useEditorConfig": true, + "files.associations": { + ".env": "shellscript", + ".env.*": "shellscript" + } +} From 6fee842b7a0e16fed70a28e3904c44191d22f1da Mon Sep 17 00:00:00 2001 From: Christian Winther Date: Fri, 26 Jan 2024 18:24:15 +0000 Subject: [PATCH 114/173] also build and push staging images --- .github/workflows/docker.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/docker.yml b/.github/workflows/docker.yml index 3296ba9d6..ca6e73630 100644 --- a/.github/workflows/docker.yml +++ b/.github/workflows/docker.yml @@ -9,6 +9,7 @@ on: push: branches: - dev + - staging - jippi-fork # TODO(jippi): remove me before merge tags: - "*" From c859367e1058c0b740d552ab1d4c7a5fd1a52310 Mon Sep 17 00:00:00 2001 From: Christian Winther Date: Fri, 26 Jan 2024 20:14:40 +0000 Subject: [PATCH 115/173] fix 02-check-config.sh logic and bad .env.docker syntax --- .env.docker | 4 ++-- docker/shared/root/docker/entrypoint.d/02-check-config.sh | 5 ++--- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/.env.docker b/.env.docker index c3e0a55ae..7be6e3e05 100644 --- a/.env.docker +++ b/.env.docker @@ -1102,10 +1102,10 @@ DOCKER_WORKER_HEALTHCHECK_INTERVAL="${DOCKER_ALL_DEFAULT_HEALTHCHECK_INTERVAL}" ################################################################################ # Set this to a non-empty value (e.g. "disabled") to disable the [proxy] and [proxy-acme] service -#DOCKER_PROXY_PROFILE="" +DOCKER_PROXY_PROFILE="" # Set this to a non-empty value (e.g. "disabled") to disable the [proxy-acme] service -DOCKER_PROXY_ACME_PROFILE="${DOCKER_PROXY_PROFILE:-}" +DOCKER_PROXY_ACME_PROFILE="${DOCKER_PROXY_PROFILE}" # How often Docker health check should run for [proxy] service DOCKER_PROXY_HEALTHCHECK_INTERVAL="${DOCKER_ALL_DEFAULT_HEALTHCHECK_INTERVAL}" diff --git a/docker/shared/root/docker/entrypoint.d/02-check-config.sh b/docker/shared/root/docker/entrypoint.d/02-check-config.sh index eecb150b4..601cf153e 100755 --- a/docker/shared/root/docker/entrypoint.d/02-check-config.sh +++ b/docker/shared/root/docker/entrypoint.d/02-check-config.sh @@ -8,11 +8,10 @@ entrypoint-set-script-name "$0" # Validating dot-env files for any issues for file in "${dot_env_files[@]}"; do - if file-exists "$file"; then + if ! file-exists "${file}"; then log-warning "Could not source file [${file}]: does not exists" continue fi - log-info "Linting dotenv file ${file}" - dotenv-linter --skip=QuoteCharacter --skip=UnorderedKey "${file}" + run-as-current-user dotenv-linter --skip=QuoteCharacter --skip=UnorderedKey "${file}" done From 8d61b8d2506fb1b5b6c05f4054f1f169ed9574a1 Mon Sep 17 00:00:00 2001 From: Christian Winther Date: Fri, 26 Jan 2024 20:14:59 +0000 Subject: [PATCH 116/173] add Docker as recommended vscode plugin --- .vscode/extensions.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.vscode/extensions.json b/.vscode/extensions.json index ea1c99893..128e0a295 100644 --- a/.vscode/extensions.json +++ b/.vscode/extensions.json @@ -8,6 +8,7 @@ "editorconfig.editorconfig", "github.vscode-github-actions", "bmewburn.vscode-intelephense-client", - "redhat.vscode-yaml" + "redhat.vscode-yaml", + "ms-azuretools.vscode-docker" ] } From d2ed117d3fd9ee168420eeeaea6da661e004a4e2 Mon Sep 17 00:00:00 2001 From: Christian Winther Date: Fri, 26 Jan 2024 20:15:33 +0000 Subject: [PATCH 117/173] improve Dockerfile for composer.json+composer.lock --- Dockerfile | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/Dockerfile b/Dockerfile index 5158f2348..e6d8071fa 100644 --- a/Dockerfile +++ b/Dockerfile @@ -186,12 +186,11 @@ COPY --link --from=composer-image /usr/bin/composer /usr/bin/composer #! Changing user to runtime user USER ${RUNTIME_UID}:${RUNTIME_GID} -# Copy over only composer related files so docker layer cache isn't invalidated on PHP file changes -COPY --chown=${RUNTIME_UID}:${RUNTIME_GID} composer.json composer.lock /var/www/ - # Install composer dependencies # NOTE: we skip the autoloader generation here since we don't have all files avaliable (yet) RUN --mount=type=cache,id=pixelfed-composer-${PHP_VERSION}-${PHP_DEBIAN_RELEASE}-${TARGETPLATFORM},sharing=locked,target=/cache/composer \ + --mount=type=bind,source=composer.json,target=/var/www/composer.json \ + --mount=type=bind,source=composer.lock,target=/var/www/composer.lock \ set -ex \ && composer install --prefer-dist --no-autoloader --ignore-platform-reqs From d372b9dee7cc0deba33c10130c10cec888a13325 Mon Sep 17 00:00:00 2001 From: Christian Winther Date: Fri, 26 Jan 2024 20:15:57 +0000 Subject: [PATCH 118/173] Set stop_signal for worker to stop Horizon more correct --- docker-compose.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/docker-compose.yml b/docker-compose.yml index a3516f7ee..fd62bd86e 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -110,6 +110,7 @@ services: container_name: "${DOCKER_ALL_CONTAINER_NAME_PREFIX}-worker" command: gosu www-data php artisan horizon restart: unless-stopped + stop_signal: SIGTERM profiles: - ${DOCKER_WORKER_PROFILE:-} build: From 8189b01a268ce9468ee9d2e8bbace8d58a31dc1c Mon Sep 17 00:00:00 2001 From: Christian Winther Date: Fri, 26 Jan 2024 20:17:54 +0000 Subject: [PATCH 119/173] improve naming of directory-is-empty --- docker/shared/root/docker/entrypoint.sh | 2 +- docker/shared/root/docker/helpers.sh | 5 +++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/docker/shared/root/docker/entrypoint.sh b/docker/shared/root/docker/entrypoint.sh index 57378d23f..9a170be13 100755 --- a/docker/shared/root/docker/entrypoint.sh +++ b/docker/shared/root/docker/entrypoint.sh @@ -31,7 +31,7 @@ IFS=' ' read -ar skip_scripts <<< "$ENTRYPOINT_SKIP_SCRIPTS" mkdir -p "${ENTRYPOINT_D_ROOT}" # If ENTRYPOINT_D_ROOT directory is empty, warn and run the regular command -if is-directory-empty "${ENTRYPOINT_D_ROOT}"; then +if directory-is-empty "${ENTRYPOINT_D_ROOT}"; then log-warning "No files found in ${ENTRYPOINT_D_ROOT}, skipping configuration" exec "$@" diff --git a/docker/shared/root/docker/helpers.sh b/docker/shared/root/docker/helpers.sh index 5826f3c9a..d2913e7d3 100644 --- a/docker/shared/root/docker/helpers.sh +++ b/docker/shared/root/docker/helpers.sh @@ -317,13 +317,14 @@ function file-exists() { [[ -f "$1" ]] } + # @description Checks if $1 contains any files or not # @arg $1 string The path to check # @exitcode 0 If $1 contains files # @exitcode 1 If $1 does *NOT* contain files -function is-directory-empty() +function directory-is-empty() { - ! find "${1}" -mindepth 1 -maxdepth 1 -type f -print -quit 2> /dev/null | read -r + [ -z "$(ls -A "${1}")" ] } # @description Ensures a directory exists (via mkdir) From aa2669c32791d5ac595b9c22ba3b14432b921294 Mon Sep 17 00:00:00 2001 From: Christian Winther Date: Fri, 26 Jan 2024 20:18:29 +0000 Subject: [PATCH 120/173] remove invalid/confusing statement in migrations about running migrations when it isn't enabled --- docker/shared/root/docker/entrypoint.d/12-migrations.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docker/shared/root/docker/entrypoint.d/12-migrations.sh b/docker/shared/root/docker/entrypoint.d/12-migrations.sh index 41c27e986..e7d52d7f5 100755 --- a/docker/shared/root/docker/entrypoint.d/12-migrations.sh +++ b/docker/shared/root/docker/entrypoint.d/12-migrations.sh @@ -22,7 +22,7 @@ if is-true "${new_migrations}"; then exit 0 fi -log-warning "New migrations available, will automatically apply them now" +log-warning "New migrations available!" if is-false "${DB_APPLY_NEW_MIGRATIONS_AUTOMATICALLY}"; then log-info "Automatic applying of new database migrations is disabled" From 5c208d05198d133510cdf91dd6f95d1fa43b027f Mon Sep 17 00:00:00 2001 From: Christian Winther Date: Fri, 26 Jan 2024 20:19:34 +0000 Subject: [PATCH 121/173] allow easy overrides of any and all files in container via new override mount --- .env.docker | 3 +++ docker-compose.yml | 2 ++ docker/shared/root/docker/entrypoint.sh | 9 +++++++++ 3 files changed, 14 insertions(+) diff --git a/.env.docker b/.env.docker index 7be6e3e05..9cc8dacbd 100644 --- a/.env.docker +++ b/.env.docker @@ -982,6 +982,9 @@ DOCKER_APP_HOST_STORAGE_PATH="${DOCKER_ALL_HOST_DATA_ROOT_PATH}/pixelfed/storage # Path is relative (./some/other/path) to the docker-compose.yml or absolute (/some/other/path) DOCKER_APP_HOST_CACHE_PATH="${DOCKER_ALL_HOST_DATA_ROOT_PATH}/pixelfed/cache" +# Path (relative to the docker-compose.yml) or absolute (/some/other/path) where containers will store overrides +DOCKER_APP_HOST_OVERRIDES_PATH="${DOCKER_ALL_HOST_CONFIG_ROOT_PATH}/overrides" + # Automatically run "One-time setup tasks" commands. # # If you are migrating to this docker-compose setup or have manually run the "One time seutp" diff --git a/docker-compose.yml b/docker-compose.yml index fd62bd86e..986bf351b 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -84,6 +84,7 @@ services: - "./.env:/var/www/.env" - "${DOCKER_APP_HOST_CACHE_PATH}:/var/www/bootstrap/cache" - "${DOCKER_APP_HOST_STORAGE_PATH}:/var/www/storage" + - "${DOCKER_APP_HOST_OVERRIDES_PATH}:/docker/overrides:ro" environment: LETSENCRYPT_HOST: "${LETSENCRYPT_HOST}" LETSENCRYPT_EMAIL: "${LETSENCRYPT_EMAIL}" @@ -126,6 +127,7 @@ services: - "./.env:/var/www/.env" - "${DOCKER_APP_HOST_CACHE_PATH}:/var/www/bootstrap/cache" - "${DOCKER_APP_HOST_STORAGE_PATH}:/var/www/storage" + - "${DOCKER_APP_HOST_OVERRIDES_PATH}:/docker/overrides:ro" depends_on: - db - redis diff --git a/docker/shared/root/docker/entrypoint.sh b/docker/shared/root/docker/entrypoint.sh index 9a170be13..73f6a4f3e 100755 --- a/docker/shared/root/docker/entrypoint.sh +++ b/docker/shared/root/docker/entrypoint.sh @@ -11,6 +11,9 @@ export ENTRYPOINT_ROOT : "${ENTRYPOINT_D_ROOT:="${ENTRYPOINT_ROOT}/entrypoint.d/"}" export ENTRYPOINT_D_ROOT +: "${DOCKER_APP_HOST_OVERRIDES_PATH:="${ENTRYPOINT_ROOT}/overrides"}" +export DOCKER_APP_HOST_OVERRIDES_PATH + # Space separated list of scripts the entrypoint runner should skip : "${ENTRYPOINT_SKIP_SCRIPTS:=""}" @@ -37,6 +40,12 @@ if directory-is-empty "${ENTRYPOINT_D_ROOT}"; then exec "$@" fi +# If the overridess directory exists, then copy all files into the container +if ! directory-is-empty "${DOCKER_APP_HOST_OVERRIDES_PATH}"; then + log-info "Overrides directory is not empty, copying files" + run-as-current-user cp --verbose --recursive "${DOCKER_APP_HOST_OVERRIDES_PATH}/." / +fi + acquire-lock "entrypoint.sh" # Start scanning for entrypoint.d files to source or run From 335e6954d2035a388e746cc878e8313a9baaa282 Mon Sep 17 00:00:00 2001 From: Christian Winther Date: Fri, 26 Jan 2024 20:19:50 +0000 Subject: [PATCH 122/173] remove noisy log statements in as-boolean --- docker/shared/root/docker/helpers.sh | 4 ---- 1 file changed, 4 deletions(-) diff --git a/docker/shared/root/docker/helpers.sh b/docker/shared/root/docker/helpers.sh index d2913e7d3..51be85506 100644 --- a/docker/shared/root/docker/helpers.sh +++ b/docker/shared/root/docker/helpers.sh @@ -559,14 +559,10 @@ function as-boolean() case "$var" in 1 | true) - log-info "[as-boolean] variable [${var}] was detected as truthy/true, returning [0]" - return 0 ;; 0 | false) - log-info "[as-boolean] variable [${var}] was detected as falsey/false, returning [1]" - return 1 ;; From a6651680313f9ec93a3b8d60557daf84def74725 Mon Sep 17 00:00:00 2001 From: Christian Winther Date: Fri, 26 Jan 2024 20:45:08 +0000 Subject: [PATCH 123/173] change where overrides are placed --- .env.docker | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/.env.docker b/.env.docker index 9cc8dacbd..1efd91843 100644 --- a/.env.docker +++ b/.env.docker @@ -903,11 +903,18 @@ DOCKER_ALL_CONTAINER_NAME_PREFIX="${APP_DOMAIN}" # Can be overridden by individual [DOCKER_*_HEALTHCHECK_INTERVAL] settings further down DOCKER_ALL_DEFAULT_HEALTHCHECK_INTERVAL="10s" +# Path (relative to the docker-compose.yml) or absolute (/some/other/path) where containers will *all* data +# will be stored (data, config, overrides) +DOCKER_ALL_HOST_ROOT_PATH="./docker-compose-state" + # Path (relative to the docker-compose.yml) or absolute (/some/other/path) where containers will store their data -DOCKER_ALL_HOST_DATA_ROOT_PATH="./docker-compose-state/data" +DOCKER_ALL_HOST_DATA_ROOT_PATH="${DOCKER_ALL_HOST_ROOT_PATH}/data" # Path (relative to the docker-compose.yml) or absolute (/some/other/path) where containers will store their confguration -DOCKER_ALL_HOST_CONFIG_ROOT_PATH="./docker-compose-state/config" +DOCKER_ALL_HOST_CONFIG_ROOT_PATH="${DOCKER_ALL_HOST_ROOT_PATH}/config" + +# Path (relative to the docker-compose.yml) or absolute (/some/other/path) where containers will store overrides +DOCKER_APP_HOST_OVERRIDES_PATH="${DOCKER_ALL_HOST_ROOT_PATH}/overrides" ################################################################################ # Docker [web] + [worker] (also know as "app") shared service configuration @@ -982,9 +989,6 @@ DOCKER_APP_HOST_STORAGE_PATH="${DOCKER_ALL_HOST_DATA_ROOT_PATH}/pixelfed/storage # Path is relative (./some/other/path) to the docker-compose.yml or absolute (/some/other/path) DOCKER_APP_HOST_CACHE_PATH="${DOCKER_ALL_HOST_DATA_ROOT_PATH}/pixelfed/cache" -# Path (relative to the docker-compose.yml) or absolute (/some/other/path) where containers will store overrides -DOCKER_APP_HOST_OVERRIDES_PATH="${DOCKER_ALL_HOST_CONFIG_ROOT_PATH}/overrides" - # Automatically run "One-time setup tasks" commands. # # If you are migrating to this docker-compose setup or have manually run the "One time seutp" From ca5710b5aeb842dab6f72d5640947b870efe0db5 Mon Sep 17 00:00:00 2001 From: Christian Winther Date: Fri, 26 Jan 2024 20:45:38 +0000 Subject: [PATCH 124/173] fix 12-migrations.sh properly detecting new migrations and printing output --- .../root/docker/entrypoint.d/12-migrations.sh | 20 +++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/docker/shared/root/docker/entrypoint.d/12-migrations.sh b/docker/shared/root/docker/entrypoint.d/12-migrations.sh index e7d52d7f5..3b87daf1f 100755 --- a/docker/shared/root/docker/entrypoint.d/12-migrations.sh +++ b/docker/shared/root/docker/entrypoint.d/12-migrations.sh @@ -12,17 +12,25 @@ entrypoint-set-script-name "$0" # Wait for the database to be ready await-database-ready -# Detect if we have new migrations -declare -i new_migrations=0 -(run-as-runtime-user php artisan migrate:status || :) | grep No && new_migrations=1 +# Run the migrate:status command and capture output +output=$(run-as-runtime-user php artisan migrate:status || :) -if is-true "${new_migrations}"; then - log-info "No outstanding migrations detected" +# By default we have no new migrations +declare -i new_migrations=0 + +# Detect if any new migrations are available by checking for "No" in the output +echo "$output" | grep No && new_migrations=1 + +if is-false "${new_migrations}"; then + log-info "No new migrations detected" exit 0 fi -log-warning "New migrations available!" +log-warning "New migrations available" + +# Print the output +echo "$output" if is-false "${DB_APPLY_NEW_MIGRATIONS_AUTOMATICALLY}"; then log-info "Automatic applying of new database migrations is disabled" From 1616c7cb11d5e90ef7b48967b22afd0765e04361 Mon Sep 17 00:00:00 2001 From: Christian Winther Date: Fri, 26 Jan 2024 20:45:56 +0000 Subject: [PATCH 125/173] make directory-is-empty more robust --- docker/shared/root/docker/helpers.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docker/shared/root/docker/helpers.sh b/docker/shared/root/docker/helpers.sh index 51be85506..1589e0780 100644 --- a/docker/shared/root/docker/helpers.sh +++ b/docker/shared/root/docker/helpers.sh @@ -324,7 +324,7 @@ function file-exists() # @exitcode 1 If $1 does *NOT* contain files function directory-is-empty() { - [ -z "$(ls -A "${1}")" ] + path-exists "${1}" && [[ -z "$(ls -A "${1}")" ]] } # @description Ensures a directory exists (via mkdir) From c4f984b205358a335be21022fc271a7e86a45940 Mon Sep 17 00:00:00 2001 From: Christian Winther Date: Fri, 26 Jan 2024 20:46:09 +0000 Subject: [PATCH 126/173] remove php extension FTP requirement --- goss.yaml | 1 - 1 file changed, 1 deletion(-) diff --git a/goss.yaml b/goss.yaml index aa5ee6058..f558f788a 100644 --- a/goss.yaml +++ b/goss.yaml @@ -48,7 +48,6 @@ command: - exif - fileinfo - filter - - ftp - gd - hash - iconv From 8bdb0ca77bb7c3aabbf1d696c29147f2f08954f0 Mon Sep 17 00:00:00 2001 From: Christian Winther Date: Fri, 26 Jan 2024 21:22:43 +0000 Subject: [PATCH 127/173] fix directory-is-empty and add tests to avoid regressions --- docker/shared/root/docker/helpers.sh | 2 +- tests/bats/helpers.bats | 29 ++++++++++++++++++++++++++++ 2 files changed, 30 insertions(+), 1 deletion(-) diff --git a/docker/shared/root/docker/helpers.sh b/docker/shared/root/docker/helpers.sh index 1589e0780..51e955682 100644 --- a/docker/shared/root/docker/helpers.sh +++ b/docker/shared/root/docker/helpers.sh @@ -324,7 +324,7 @@ function file-exists() # @exitcode 1 If $1 does *NOT* contain files function directory-is-empty() { - path-exists "${1}" && [[ -z "$(ls -A "${1}")" ]] + ! path-exists "${1}" || [[ -z "$(ls -A "${1}")" ]] } # @description Ensures a directory exists (via mkdir) diff --git a/tests/bats/helpers.bats b/tests/bats/helpers.bats index ea4c7b518..6ba65c2c3 100644 --- a/tests/bats/helpers.bats +++ b/tests/bats/helpers.bats @@ -5,6 +5,12 @@ setup() { load "$ROOT/docker/shared/root/docker/helpers.sh" } +teardown() { + if [[ -e test_dir ]]; then + rm -rf test_dir + fi +} + @test "test [is-true]" { is-true "1" is-true "true" @@ -72,3 +78,26 @@ setup() { return 1 } + +@test "test [directory-is-empty] - non existing" { + directory-is-empty test_dir +} + +@test "test [directory-is-empty] - actually empty" { + mkdir -p test_dir + + directory-is-empty test_dir +} + +@test "test [directory-is-empty] - not empty (directory)" { + mkdir -p test_dir/sub-dir + + ! directory-is-empty test_dir +} + +@test "test [directory-is-empty] - not empty (file)" { + mkdir -p test_dir/ + touch test_dir/hello-world.txt + + ! directory-is-empty test_dir +} From 1a6e97c98b92696ed9f96807d5c6ad04edfee13d Mon Sep 17 00:00:00 2001 From: Christian Winther Date: Fri, 26 Jan 2024 22:51:15 +0000 Subject: [PATCH 128/173] try to make 8.3 build working by building imagick from master branch --- .github/workflows/docker.yml | 4 -- Dockerfile | 38 ++++++++++++------- .../root/docker/entrypoint.d/10-storage.sh | 2 +- docker/shared/root/docker/install/base.sh | 19 ---------- .../root/docker/install/php-extensions.sh | 21 ++-------- 5 files changed, 28 insertions(+), 56 deletions(-) diff --git a/.github/workflows/docker.yml b/.github/workflows/docker.yml index ca6e73630..e7b49f419 100644 --- a/.github/workflows/docker.yml +++ b/.github/workflows/docker.yml @@ -84,10 +84,6 @@ jobs: # See: https://docs.github.com/en/actions/using-jobs/using-a-matrix-for-your-jobs#excluding-matrix-configurations # See: https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstrategymatrixexclude exclude: - # Broken for imagick on arm64 due to https://github.com/Imagick/imagick/pull/641 - # Could probably figure out how to do a matrix only ignoring 8.3 + linux/arm64, but this is easier atm - - php_version: 8.3 - # targeting [apache] runtime with [fpm] base type doesn't make sense - target_runtime: apache php_base: fpm diff --git a/Dockerfile b/Dockerfile index e6d8071fa..f5aca8235 100644 --- a/Dockerfile +++ b/Dockerfile @@ -5,7 +5,10 @@ # Configuration ####################################################### -# See: https://github.com/composer/composer/releases +# See: https://github.com/mlocati/docker-php-extension-installer +ARG DOCKER_PHP_EXTENSION_INSTALLER_VERSION="2.1.80" + +# See: https://github.com/composer/composer ARG COMPOSER_VERSION="2.6" # See: https://nginx.org/ @@ -17,7 +20,7 @@ ARG FOREGO_VERSION="0.17.2" # See: https://github.com/hairyhenderson/gomplate ARG GOMPLATE_VERSION="v3.11.6" -# See: https://github.com/dotenv-linter/dotenv-linter/releases +# See: https://github.com/dotenv-linter/dotenv-linter # # WARN: v3.3.0 and above requires newer libc version than Ubuntu ships with ARG DOTENV_LINTER_VERSION="v3.2.0" @@ -40,7 +43,10 @@ ARG RUNTIME_GID=33 # often called 'www-data' ARG APT_PACKAGES_EXTRA= # Extensions installed via [pecl install] -ARG PHP_PECL_EXTENSIONS="redis imagick" +# ! NOTE: imagick is installed from [master] branch on GitHub due to 8.3 bug on ARM that haven't +# ! been released yet (after +10 months)! +# ! See: https://github.com/Imagick/imagick/pull/641 +ARG PHP_PECL_EXTENSIONS="redis https://codeload.github.com/Imagick/imagick/tar.gz/28f27044e435a2b203e32675e942eb8de620ee58" ARG PHP_PECL_EXTENSIONS_EXTRA= # Extensions installed via [docker-php-ext-install] @@ -63,6 +69,11 @@ ARG NGINX_GPGKEY_PATH="/usr/share/keyrings/nginx-archive-keyring.gpg" # NOTE: Docker will *not* pull this image unless it's referenced (via build target) FROM composer:${COMPOSER_VERSION} AS composer-image +# php-extension-installer image from Docker Hub +# +# NOTE: Docker will *not* pull this image unless it's referenced (via build target) +FROM mlocati/php-extension-installer:${DOCKER_PHP_EXTENSION_INSTALLER_VERSION} AS php-extension-installer + # nginx webserver from Docker Hub. # Used to copy some docker-entrypoint files for [nginx-runtime] # @@ -147,23 +158,24 @@ ARG PHP_PECL_EXTENSIONS_EXTRA ARG PHP_VERSION ARG TARGETPLATFORM -ENV PHP_EXTENSIONS_DATABASE=${PHP_EXTENSIONS_DATABASE} -ENV PHP_EXTENSIONS_EXTRA=${PHP_EXTENSIONS_EXTRA} -ENV PHP_EXTENSIONS=${PHP_EXTENSIONS} -ENV PHP_PECL_EXTENSIONS_EXTRA=${PHP_PECL_EXTENSIONS_EXTRA} -ENV PHP_PECL_EXTENSIONS=${PHP_PECL_EXTENSIONS} +COPY --from=php-extension-installer /usr/bin/install-php-extensions /usr/local/bin/ COPY docker/shared/root/docker/install/php-extensions.sh /docker/install/php-extensions.sh -RUN --mount=type=cache,id=pixelfed-php-${PHP_VERSION}-${PHP_DEBIAN_RELEASE}-${TARGETPLATFORM},sharing=locked,target=/usr/src/php \ +RUN --mount=type=cache,id=pixelfed-pear-${PHP_VERSION}-${PHP_DEBIAN_RELEASE}-${TARGETPLATFORM},sharing=locked,target=/tmp/pear \ --mount=type=cache,id=pixelfed-apt-${PHP_VERSION}-${PHP_DEBIAN_RELEASE}-${TARGETPLATFORM},sharing=locked,target=/var/lib/apt \ --mount=type=cache,id=pixelfed-apt-cache-${PHP_VERSION}-${PHP_DEBIAN_RELEASE}-${TARGETPLATFORM},sharing=locked,target=/var/cache/apt \ + PHP_EXTENSIONS=${PHP_EXTENSIONS} \ + PHP_EXTENSIONS_DATABASE=${PHP_EXTENSIONS_DATABASE} \ + PHP_EXTENSIONS_EXTRA=${PHP_EXTENSIONS_EXTRA} \ + PHP_PECL_EXTENSIONS=${PHP_PECL_EXTENSIONS} \ + PHP_PECL_EXTENSIONS_EXTRA=${PHP_PECL_EXTENSIONS_EXTRA} \ /docker/install/php-extensions.sh ####################################################### # PHP: composer and source code ####################################################### -FROM base AS composer-and-src +FROM php-extensions AS composer-and-src ARG PHP_VERSION ARG PHP_DEBIAN_RELEASE @@ -188,7 +200,7 @@ USER ${RUNTIME_UID}:${RUNTIME_GID} # Install composer dependencies # NOTE: we skip the autoloader generation here since we don't have all files avaliable (yet) -RUN --mount=type=cache,id=pixelfed-composer-${PHP_VERSION}-${PHP_DEBIAN_RELEASE}-${TARGETPLATFORM},sharing=locked,target=/cache/composer \ +RUN --mount=type=cache,id=pixelfed-composer-${PHP_VERSION},sharing=locked,target=/cache/composer \ --mount=type=bind,source=composer.json,target=/var/www/composer.json \ --mount=type=bind,source=composer.lock,target=/var/www/composer.lock \ set -ex \ @@ -201,7 +213,7 @@ COPY --chown=${RUNTIME_UID}:${RUNTIME_GID} . /var/www/ # Runtime: base ####################################################### -FROM base AS shared-runtime +FROM php-extensions AS shared-runtime ARG BUILDARCH ARG BUILDOS @@ -212,8 +224,6 @@ ARG RUNTIME_UID ENV RUNTIME_UID=${RUNTIME_UID} ENV RUNTIME_GID=${RUNTIME_GID} -COPY --link --from=php-extensions /usr/local/lib/php/extensions /usr/local/lib/php/extensions -COPY --link --from=php-extensions /usr/local/etc/php /usr/local/etc/php COPY --link --from=forego-image /usr/local/bin/forego /usr/local/bin/forego COPY --link --from=gomplate-image /usr/local/bin/gomplate /usr/local/bin/gomplate COPY --link --from=composer-image /usr/bin/composer /usr/bin/composer diff --git a/docker/shared/root/docker/entrypoint.d/10-storage.sh b/docker/shared/root/docker/entrypoint.d/10-storage.sh index f0c28241d..54145a365 100755 --- a/docker/shared/root/docker/entrypoint.d/10-storage.sh +++ b/docker/shared/root/docker/entrypoint.d/10-storage.sh @@ -7,7 +7,7 @@ source "${ENTRYPOINT_ROOT}/helpers.sh" entrypoint-set-script-name "$0" # Copy the [storage/] skeleton files over the "real" [storage/] directory so assets are updated between versions -run-as-runtime-user cp --recursive storage.skel/. ./storage/ +run-as-runtime-user cp --force --recursive storage.skel/. ./storage/ # Ensure storage linkk are correctly configured run-as-runtime-user php artisan storage:link diff --git a/docker/shared/root/docker/install/base.sh b/docker/shared/root/docker/install/base.sh index e20788b56..4e97e82bb 100755 --- a/docker/shared/root/docker/install/base.sh +++ b/docker/shared/root/docker/install/base.sh @@ -21,8 +21,6 @@ packages+=( git gnupg1 gosu - libcurl4-openssl-dev - libzip-dev locales locales-all moreutils @@ -42,21 +40,6 @@ packages+=( pngquant ) -# Image Processing -packages+=( - libjpeg62-turbo-dev - libmagickwand-dev - libpng-dev -) - -# Required for GD -packages+=( - libwebp-dev - libwebp6 - libxpm-dev - libxpm4 -) - # Video Processing packages+=( ffmpeg @@ -64,8 +47,6 @@ packages+=( # Database packages+=( - libpq-dev - libsqlite3-dev mariadb-client postgresql-client ) diff --git a/docker/shared/root/docker/install/php-extensions.sh b/docker/shared/root/docker/install/php-extensions.sh index 42c149d76..222f2374d 100755 --- a/docker/shared/root/docker/install/php-extensions.sh +++ b/docker/shared/root/docker/install/php-extensions.sh @@ -2,6 +2,7 @@ set -ex -o errexit -o nounset -o pipefail declare -a pecl_extensions=() + readarray -d ' ' -t pecl_extensions < <(echo -n "${PHP_PECL_EXTENSIONS:-}") readarray -d ' ' -t -O "${#pecl_extensions[@]}" pecl_extensions < <(echo -n "${PHP_PECL_EXTENSIONS_EXTRA:-}") @@ -10,16 +11,6 @@ readarray -d ' ' -t php_extensions < <(echo -n "${PHP_EXTENSIONS:-}") readarray -d ' ' -t -O "${#php_extensions[@]}" php_extensions < <(echo -n "${PHP_EXTENSIONS_EXTRA:-}") readarray -d ' ' -t -O "${#php_extensions[@]}" php_extensions < <(echo -n "${PHP_EXTENSIONS_DATABASE:-}") -# Grab the PHP source code so we can compile against it -docker-php-source extract - -# PHP GD extensions -docker-php-ext-configure gd \ - --with-freetype \ - --with-jpeg \ - --with-webp \ - --with-xpm - # Optional script folks can copy into their image to do any [docker-php-ext-configure] work before the [docker-php-ext-install] # this can also overwirte the [gd] configure above by simply running it again declare -r custom_pre_configure_script="" @@ -32,11 +23,5 @@ if [[ -e "${custom_pre_configure_script}" ]]; then "${custom_pre_configure_script}" fi -# Install pecl extensions -pecl install "${pecl_extensions[@]}" - -# PHP extensions (dependencies) -docker-php-ext-install -j "$(nproc)" "${php_extensions[@]}" - -# Enable all extensions -docker-php-ext-enable "${pecl_extensions[@]}" "${php_extensions[@]}" +# PECL + PHP extensions +IPE_KEEP_SYSPKG_CACHE=1 install-php-extensions "${pecl_extensions[@]}" "${php_extensions[@]}" From b73d4522554adc2700793b2e9bc8791b30a6caf5 Mon Sep 17 00:00:00 2001 From: Christian Winther Date: Fri, 26 Jan 2024 23:39:18 +0000 Subject: [PATCH 129/173] sort ARG in Dockerfile --- .env.docker | 18 ++++++++++-------- Dockerfile | 1 + 2 files changed, 11 insertions(+), 8 deletions(-) diff --git a/.env.docker b/.env.docker index 1efd91843..8ca07c21f 100644 --- a/.env.docker +++ b/.env.docker @@ -949,14 +949,21 @@ DOCKER_APP_RELEASE="branch-jippi-fork" # the [DOCKER_APP_RUNTIME] and [PHP_DEBIAN_RELEASE] settings DOCKER_APP_PHP_VERSION="8.2" -# The [php] Docker image base type +# The container runtime to use. # -# See: https://github.com/pixelfed/pixelfed/blob/dev/docker/runtimes.md -DOCKER_APP_BASE_TYPE="apache" +# See: https://docs.pixelfed.org/running-pixelfed/docker/runtimes.html +DOCKER_APP_RUNTIME="apache" # The Debian release variant to use of the [php] Docker image +# +# Examlpe: [bookworm] or [bullseye] DOCKER_APP_DEBIAN_RELEASE="bullseye" +# The [php] Docker image base type +# +# See: https://docs.pixelfed.org/running-pixelfed/docker/runtimes.html +DOCKER_APP_BASE_TYPE="apache" + # Image to pull the Pixelfed Docker images from. # # Example values: @@ -967,11 +974,6 @@ DOCKER_APP_DEBIAN_RELEASE="bullseye" # DOCKER_APP_IMAGE="ghcr.io/jippi/pixelfed" -# The container runtime to use. -# -# See: https://github.com/jippi/pixelfed/blob/jippi-fork/docker/runtimes.md -DOCKER_APP_RUNTIME="apache" - # Pixelfed version (image tag) to pull from the registry. # # See: https://github.com/pixelfed/pixelfed/pkgs/container/pixelfed diff --git a/Dockerfile b/Dockerfile index f5aca8235..1c8a30155 100644 --- a/Dockerfile +++ b/Dockerfile @@ -161,6 +161,7 @@ ARG TARGETPLATFORM COPY --from=php-extension-installer /usr/bin/install-php-extensions /usr/local/bin/ COPY docker/shared/root/docker/install/php-extensions.sh /docker/install/php-extensions.sh + RUN --mount=type=cache,id=pixelfed-pear-${PHP_VERSION}-${PHP_DEBIAN_RELEASE}-${TARGETPLATFORM},sharing=locked,target=/tmp/pear \ --mount=type=cache,id=pixelfed-apt-${PHP_VERSION}-${PHP_DEBIAN_RELEASE}-${TARGETPLATFORM},sharing=locked,target=/var/lib/apt \ --mount=type=cache,id=pixelfed-apt-cache-${PHP_VERSION}-${PHP_DEBIAN_RELEASE}-${TARGETPLATFORM},sharing=locked,target=/var/cache/apt \ From ef37c8f234558582baaa68bc58269bb3ac35a92c Mon Sep 17 00:00:00 2001 From: Christian Winther Date: Fri, 26 Jan 2024 23:48:04 +0000 Subject: [PATCH 130/173] name CI jobs --- .github/workflows/docker.yml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.github/workflows/docker.yml b/.github/workflows/docker.yml index e7b49f419..186919ed7 100644 --- a/.github/workflows/docker.yml +++ b/.github/workflows/docker.yml @@ -25,6 +25,7 @@ on: jobs: lint: + name: hadolint runs-on: ubuntu-latest permissions: @@ -41,7 +42,7 @@ jobs: failure-threshold: error shellcheck: - name: Shellcheck + name: ShellCheck runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 @@ -62,6 +63,7 @@ jobs: run: docker run -v "$PWD:/var/www" bats/bats:latest /var/www/tests/bats build: + name: Build, Test, and Push runs-on: ubuntu-latest strategy: From 3723f36043a6b7a5c25920fe987172ef26967e7d Mon Sep 17 00:00:00 2001 From: Christian Winther Date: Fri, 26 Jan 2024 23:54:24 +0000 Subject: [PATCH 131/173] remove unneeded workflow triggers --- .github/workflows/docker.yml | 2 -- 1 file changed, 2 deletions(-) diff --git a/.github/workflows/docker.yml b/.github/workflows/docker.yml index 186919ed7..ea119bec3 100644 --- a/.github/workflows/docker.yml +++ b/.github/workflows/docker.yml @@ -17,9 +17,7 @@ on: # See: https://docs.github.com/en/actions/using-workflows/events-that-trigger-workflows#pull_request pull_request: types: - - labeled - opened - - ready_for_review - reopened - synchronize From 043f914c8c62010e67e602b765599233009c276d Mon Sep 17 00:00:00 2001 From: Christian Winther Date: Fri, 26 Jan 2024 23:58:38 +0000 Subject: [PATCH 132/173] test: change prefix for docker tags --- .github/workflows/docker.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/docker.yml b/.github/workflows/docker.yml index ea119bec3..511ac911e 100644 --- a/.github/workflows/docker.yml +++ b/.github/workflows/docker.yml @@ -168,8 +168,8 @@ jobs: type=raw,value=staging,enable=${{ github.ref == format('refs/heads/{0}', 'staging') }} type=pep440,pattern={{raw}} type=pep440,pattern=v{{major}}.{{minor}} - type=ref,event=branch,prefix=branch- - type=ref,event=pr,prefix=pr- + type=ref,event=branch,prefix=branch/ + type=ref,event=pr,prefix=pr/ type=ref,event=tag env: DOCKER_METADATA_ANNOTATIONS_LEVELS: manifest,index From 2aeccf885f80a4de9fc0014464fbe538c23613f6 Mon Sep 17 00:00:00 2001 From: Christian Winther Date: Sat, 27 Jan 2024 00:01:06 +0000 Subject: [PATCH 133/173] test: remove slash in tags --- .github/workflows/docker.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/docker.yml b/.github/workflows/docker.yml index 511ac911e..ea119bec3 100644 --- a/.github/workflows/docker.yml +++ b/.github/workflows/docker.yml @@ -168,8 +168,8 @@ jobs: type=raw,value=staging,enable=${{ github.ref == format('refs/heads/{0}', 'staging') }} type=pep440,pattern={{raw}} type=pep440,pattern=v{{major}}.{{minor}} - type=ref,event=branch,prefix=branch/ - type=ref,event=pr,prefix=pr/ + type=ref,event=branch,prefix=branch- + type=ref,event=pr,prefix=pr- type=ref,event=tag env: DOCKER_METADATA_ANNOTATIONS_LEVELS: manifest,index From d9a9507cc857b06cca2729cb381ae02c649c6a6d Mon Sep 17 00:00:00 2001 From: Christian Winther Date: Sat, 10 Feb 2024 00:30:06 +0000 Subject: [PATCH 134/173] sync --- app/Console/Kernel.php | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/app/Console/Kernel.php b/app/Console/Kernel.php index c35af3a20..dcee73ee1 100644 --- a/app/Console/Kernel.php +++ b/app/Console/Kernel.php @@ -33,13 +33,17 @@ class Kernel extends ConsoleKernel $schedule->command('gc:passwordreset')->dailyAt('09:41')->onOneServer(); $schedule->command('gc:sessions')->twiceDaily(13, 23)->onOneServer(); - if(config('import.instagram.enabled')) { + if (in_array(config_cache('pixelfed.cloud_storage'), ['1', true, 'true']) && config('media.delete_local_after_cloud')) { + $schedule->command('media:s3gc')->hourlyAt(15); + } + + if (config('import.instagram.enabled')) { $schedule->command('app:transform-imports')->everyTenMinutes()->onOneServer(); $schedule->command('app:import-upload-garbage-collection')->hourlyAt(51)->onOneServer(); $schedule->command('app:import-remove-deleted-accounts')->hourlyAt(37)->onOneServer(); $schedule->command('app:import-upload-clean-storage')->twiceDailyAt(1, 13, 32)->onOneServer(); - if(config('import.instagram.storage.cloud.enabled') && (bool) config_cache('pixelfed.cloud_storage')) { + if (config('import.instagram.storage.cloud.enabled') && (bool) config_cache('pixelfed.cloud_storage')) { $schedule->command('app:import-upload-media-to-cloud-storage')->hourlyAt(39)->onOneServer(); } } @@ -56,11 +60,7 @@ class Kernel extends ConsoleKernel */ protected function commands() { -<<<<<<< HEAD $this->load(__DIR__ . '/Commands'); -======= - $this->load(__DIR__.'/Commands'); ->>>>>>> d374d73ba74860d6eb90752d596cf2e22f189860 require base_path('routes/console.php'); } From bc66b6da18ae2ab7a038651b90a8f2c77dfc1aa6 Mon Sep 17 00:00:00 2001 From: Christian Winther Date: Sat, 10 Feb 2024 20:03:04 +0000 Subject: [PATCH 135/173] many small fixes and improvements --- .editorconfig | 14 +- .env.docker | 1132 +++++++++-------- .env.example | 80 -- .vscode/settings.json | 14 + Dockerfile | 16 +- docker-compose.yml | 60 +- .../docker/templates/etc/nginx/nginx.conf | 41 + .../docker/entrypoint.d/02-check-config.sh | 6 +- docker/shared/root/docker/helpers.sh | 26 +- docker/shared/root/docker/install/base.sh | 3 - .../templates/usr/local/etc/php/php.ini | 7 +- goss.yaml | 2 +- 12 files changed, 723 insertions(+), 678 deletions(-) delete mode 100644 .env.example create mode 100644 docker/nginx/root/docker/templates/etc/nginx/nginx.conf diff --git a/.editorconfig b/.editorconfig index 9551fdc60..a56c5a37a 100644 --- a/.editorconfig +++ b/.editorconfig @@ -17,11 +17,11 @@ indent_style = space indent_size = 4 # ShellCheck config -shell_variant = bash -binary_next_line = true -case-indent = true -switch_case_indent = true -space_redirects = true -function_next_line = true +shell_variant = bash # like -ln=bash +binary_next_line = true # like -bn +switch_case_indent = true # like -ci +space_redirects = false # like -sr +keep_padding = false # like -kp +function_next_line = true # like -fn +never_split = true # like -ns simplify = true -space-redirects = true diff --git a/.env.docker b/.env.docker index 8ca07c21f..0fa9e1428 100644 --- a/.env.docker +++ b/.env.docker @@ -2,47 +2,45 @@ # -*- mode: bash -*- # vi: ft=bash +# Use Dottie (https://github.com/jippi/dottie) to manage this .env file easier! +# +# @dottie/source .env.docker +# # shellcheck disable=SC2034,SC2148 ################################################################################ -# Pixelfed application configuration +# app ################################################################################ -# A random 32-character string to be used as an encryption key. -# -# !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -# ! NOTE: This will be auto-generated by Docker during bootstrap -# !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -# -# This key is used by the Illuminate encrypter service and should be set to a random, -# 32 character string, otherwise these encrypted strings will not be safe. -# -# See: https://docs.pixelfed.org/technical-documentation/config/#app_key -APP_KEY= - -# See: https://docs.pixelfed.org/technical-documentation/config/#app_name-1 +# @see https://docs.pixelfed.org/technical-documentation/config/#app_name-1 +# @dottie/validate required APP_NAME="Pixelfed Prod" # Application domains used for routing. # -# See: https://docs.pixelfed.org/technical-documentation/config/#app_domain +# @see https://docs.pixelfed.org/technical-documentation/config/#app_domain +# @dottie/validate required,fqdn APP_DOMAIN="__CHANGE_ME__" # This URL is used by the console to properly generate URLs when using the Artisan command line tool. # You should set this to the root of your application so that it is used when running Artisan tasks. # -# See: https://docs.pixelfed.org/technical-documentation/config/#app_url +# @see https://docs.pixelfed.org/technical-documentation/config/#app_url +# @dottie/validate required,http_url APP_URL="https://${APP_DOMAIN}" # Application domains used for routing. # -# See: https://docs.pixelfed.org/technical-documentation/config/#admin_domain +# @see https://docs.pixelfed.org/technical-documentation/config/#admin_domain +# @dottie/validate required,fqdn ADMIN_DOMAIN="${APP_DOMAIN}" # This value determines the “environment” your application is currently running in. # This may determine how you prefer to configure various services your application utilizes. # -# See: https://docs.pixelfed.org/technical-documentation/config/#app_env +# @default "production" +# @see https://docs.pixelfed.org/technical-documentation/config/#app_env +# @dottie/validate required,oneof='production,dev,staging' #APP_ENV="production" # When your application is in debug mode, detailed error messages with stack traces will @@ -50,207 +48,289 @@ ADMIN_DOMAIN="${APP_DOMAIN}" # # If disabled, a simple generic error page is shown. # -# See: https://docs.pixelfed.org/technical-documentation/config/#app_debug +# @default "false" +# @see https://docs.pixelfed.org/technical-documentation/config/#app_debug +# @dottie/validate required,boolean #APP_DEBUG="false" # Enable/disable new local account registrations. # -# See: https://docs.pixelfed.org/technical-documentation/config/#open_registration +# @default "true" +# @see https://docs.pixelfed.org/technical-documentation/config/#open_registration +# @dottie/validate required,boolean #OPEN_REGISTRATION="true" # Require email verification before a new user can do anything. # -# Defaults to "true". -# -# See: https://docs.pixelfed.org/technical-documentation/config/#enforce_email_verification +# @default "true" +# @see https://docs.pixelfed.org/technical-documentation/config/#enforce_email_verification +# @dottie/validate required,boolean #ENFORCE_EMAIL_VERIFICATION="true" # Allow a maximum number of user accounts. # -# Defaults to "1000". -# -# See: https://docs.pixelfed.org/technical-documentation/config/#pf_max_users +# @default "1000" +# @see https://docs.pixelfed.org/technical-documentation/config/#pf_max_users +# @dottie/validate required,number #PF_MAX_USERS="1000" # Enforce the maximum number of user accounts # -# Defaults to "true". +# @default "true" +# @dottie/validate boolean #PF_ENFORCE_MAX_USERS="true" -# See: https://docs.pixelfed.org/technical-documentation/config/#oauth_enabled -OAUTH_ENABLED="true" +# @default "false" +# @see https://docs.pixelfed.org/technical-documentation/config/#oauth_enabled +# @dottie/validate required,boolean +#OAUTH_ENABLED="false" -# Defaults to "UTC". -# # ! Do not edit your timezone once the service is running - or things will break! # -# See: https://docs.pixelfed.org/technical-documentation/config/#app_timezone -# See: https://www.php.net/manual/en/timezones.php +# @default "UTC" +# @see https://docs.pixelfed.org/technical-documentation/config/#app_timezone +# @see https://www.php.net/manual/en/timezones.php +# @dottie/validate required,timezone APP_TIMEZONE="UTC" # The application locale determines the default locale that will be used by the translation service provider. # You are free to set this value to any of the locales which will be supported by the application. # -# Defaults to "en". -# -# See: https://docs.pixelfed.org/technical-documentation/config/#app_locale +# @default "en" +# @see https://docs.pixelfed.org/technical-documentation/config/#app_locale +# @dottie/validate required #APP_LOCALE="en" # The fallback locale determines the locale to use when the current one is not available. # # You may change the value to correspond to any of the language folders that are provided through your application. # -# Defaults to "en". -# -# See: https://docs.pixelfed.org/technical-documentation/config/#app_fallback_locale +# @default "en" +# @see https://docs.pixelfed.org/technical-documentation/config/#app_fallback_locale +# @dottie/validate required #APP_FALLBACK_LOCALE="en" -# See: https://docs.pixelfed.org/technical-documentation/config/#limit_account_size +# @see https://docs.pixelfed.org/technical-documentation/config/#limit_account_size +# @dottie/validate required,boolean #LIMIT_ACCOUNT_SIZE="true" # Update the max account size, the per user limit of files in kB. # -# Defaults to "1000000" (1GB). -# -# See: https://docs.pixelfed.org/technical-documentation/config/#max_account_size-kb +# @default "1000000" (1GB) +# @see https://docs.pixelfed.org/technical-documentation/config/#max_account_size-kb +# @dottie/validate required,number #MAX_ACCOUNT_SIZE="1000000" # Update the max photo size, in kB. # -# Defaults to "15000" (15MB). -# -# See: https://docs.pixelfed.org/technical-documentation/config/#max_photo_size-kb +# @default "15000" (15MB) +# @see https://docs.pixelfed.org/technical-documentation/config/#max_photo_size-kb +# @dottie/validate required,number #MAX_PHOTO_SIZE="15000" # The max number of photos allowed per post. # -# Defaults to "4". -# -# See: https://docs.pixelfed.org/technical-documentation/config/#max_album_length +# @default "4" +# @see https://docs.pixelfed.org/technical-documentation/config/#max_album_length +# @dottie/validate required,number #MAX_ALBUM_LENGTH="4" # Update the max avatar size, in kB. # -# Defaults to "2000" (2MB). -# -# See: https://docs.pixelfed.org/technical-documentation/config/#max_avatar_size-kb +# @default "2000" (2MB). +# @see https://docs.pixelfed.org/technical-documentation/config/#max_avatar_size-kb +# @dottie/validate required,number #MAX_AVATAR_SIZE="2000" # Change the caption length limit for new local posts. # -# Defaults to "500". -# -# See: https://docs.pixelfed.org/technical-documentation/config/#max_caption_length +# @default "500" +# @see https://docs.pixelfed.org/technical-documentation/config/#max_caption_length +# @dottie/validate required,number #MAX_CAPTION_LENGTH="500" # Change the bio length limit for user profiles. # -# Defaults to "125". -# -# See: https://docs.pixelfed.org/technical-documentation/config/#max_bio_length +# @default "125" +# @see https://docs.pixelfed.org/technical-documentation/config/#max_bio_length +# @dottie/validate required,number #MAX_BIO_LENGTH="125" # Change the length limit for user names. # -# Defaults to "30". -# -# See: https://docs.pixelfed.org/technical-documentation/config/#max_name_length +# @default "30" +# @see https://docs.pixelfed.org/technical-documentation/config/#max_name_length +# @dottie/validate required,number #MAX_NAME_LENGTH="30" # Resize and optimize image uploads. # -# Defaults to "true". -# -# See: https://docs.pixelfed.org/technical-documentation/config/#pf_optimize_images +# @default "true" +# @see https://docs.pixelfed.org/technical-documentation/config/#pf_optimize_images +# @dottie/validate required,boolean #PF_OPTIMIZE_IMAGES="true" # Set the image optimization quality, must be a value between 1-100. # -# Defaults to "80". -# -# See: https://docs.pixelfed.org/technical-documentation/config/#image_quality +# @default "80" +# @see https://docs.pixelfed.org/technical-documentation/config/#image_quality +# @dottie/validate required,number #IMAGE_QUALITY="80" # Resize and optimize video uploads. # -# Defaults to "true". -# -# See: https://docs.pixelfed.org/technical-documentation/config/#pf_optimize_videos +# @default "true" +# @see https://docs.pixelfed.org/technical-documentation/config/#pf_optimize_videos +# @dottie/validate required,boolean #PF_OPTIMIZE_VIDEOS="true" # Enable account deletion. # -# Defaults to "true". -# -# See: https://docs.pixelfed.org/technical-documentation/config/#account_deletion +# @default "true" +# @see https://docs.pixelfed.org/technical-documentation/config/#account_deletion +# @dottie/validate required,boolean #ACCOUNT_DELETION="true" # Set account deletion queue after X days, set to false to delete accounts immediately. # -# Defaults to "false". -# -# See: https://docs.pixelfed.org/technical-documentation/config/#account_delete_after +# @default "false" +# @see https://docs.pixelfed.org/technical-documentation/config/#account_delete_after +# @dottie/validate required,boolean #ACCOUNT_DELETE_AFTER="false" -# Defaults to "Pixelfed - Photo sharing for everyone". -# -# See: https://docs.pixelfed.org/technical-documentation/config/#instance_description +# @default "Pixelfed - Photo sharing for everyone" +# @see https://docs.pixelfed.org/technical-documentation/config/#instance_description +# @dottie/validate required #INSTANCE_DESCRIPTION="" -# Defaults to "false". -# -# See: https://docs.pixelfed.org/technical-documentation/config/#instance_public_hashtags +# @default "false" +# @see https://docs.pixelfed.org/technical-documentation/config/#instance_public_hashtags +# @dottie/validate required,boolean #INSTANCE_PUBLIC_HASHTAGS="false" -# Defaults to "". -# -# See: https://docs.pixelfed.org/technical-documentation/config/#instance_contact_email +# @default "" +# @see https://docs.pixelfed.org/technical-documentation/config/#instance_contact_email +# @dottie/validate required,email INSTANCE_CONTACT_EMAIL="admin@${APP_DOMAIN}" -# Defaults to "false". -# -# See: https://docs.pixelfed.org/technical-documentation/config/#instance_public_local_timeline +# @default "false" +# @see https://docs.pixelfed.org/technical-documentation/config/#instance_public_local_timeline +# @dottie/validate required,boolean #INSTANCE_PUBLIC_LOCAL_TIMELINE="false" -# Defaults to "". -# -# See: https://docs.pixelfed.org/technical-documentation/config/#banned_usernames +# @default "" +# @see https://docs.pixelfed.org/technical-documentation/config/#banned_usernames #BANNED_USERNAMES="" -# Defaults to "false". -# -# See: https://docs.pixelfed.org/technical-documentation/config/#stories_enabled +# @default "false" +# @see https://docs.pixelfed.org/technical-documentation/config/#stories_enabled +# @dottie/validate required,boolean #STORIES_ENABLED="false" -# Defaults to "false". -# # Level is hardcoded to 1. # -# See: https://docs.pixelfed.org/technical-documentation/config/#restricted_instance +# @default "false" +# @see https://docs.pixelfed.org/technical-documentation/config/#restricted_instance +# @dottie/validate required,boolean #RESTRICTED_INSTANCE="false" -################################################################################ -# Lets Encrypt configuration -################################################################################ +# @default false +# @see https://docs.pixelfed.org/technical-documentation/config/#media_exif_database +# @dottie/validate required,boolean +MEDIA_EXIF_DATABASE="true" -# The host to request LetsEncrypt certificate for -LETSENCRYPT_HOST="${APP_DOMAIN}" - -# The e-mail to use for Lets Encrypt certificate requests. -LETSENCRYPT_EMAIL="__CHANGE_ME__" - -# Lets Encrypt staging/test servers for certificate requests. +# Pixelfed supports GD or ImageMagick to process images. # -# Setting this to any value will change to letsencrypt test servers. -#LETSENCRYPT_TEST="1" +# Possible values: +# - "gd" (default) +# - "imagick" +# +# @default "gd" +# @see https://docs.pixelfed.org/technical-documentation/config/#image_driver +# @dottie/validate required,oneof=gd imagick +#IMAGE_DRIVER="gd" + +# Set trusted proxy IP addresses. +# +# Both IPv4 and IPv6 addresses are supported, along with CIDR notation. +# +# The “*” character is syntactic sugar within TrustedProxy to trust any +# proxy that connects directly to your server, a requirement when you cannot +# know the address of your proxy (e.g. if using Rackspace balancers). +# +# The “**” character is syntactic sugar within TrustedProxy to trust not just any +# proxy that connects directly to your server, but also proxies that connect to those proxies, +# and all the way back until you reach the original source IP. It will mean that +# $request->getClientIp() always gets the originating client IP, no matter how many proxies +# that client’s request has subsequently passed through. +# +# @default "*" +# @see https://docs.pixelfed.org/technical-documentation/config/#trust_proxies +# @dottie/validate required +#TRUST_PROXIES="*" + +# This option controls the default cache connection that gets used while using this caching library. +# +# This connection is used when another is not explicitly specified when executing a given caching function. +# +# Possible values: +# - "apc" +# - "array" +# - "database" +# - "file" (default) +# - "memcached" +# - "redis" +# +# @default "file" +# @see https://docs.pixelfed.org/technical-documentation/config/#cache_driver +# @dottie/validate required,oneof=apc array database file memcached redis +CACHE_DRIVER="redis" + +# @default ${APP_NAME}_cache, or laravel_cache if no APP_NAME is set. +# @see https://docs.pixelfed.org/technical-documentation/config/#cache_prefix +# @dottie/validate required +#CACHE_PREFIX="{APP_NAME}_cache" + +# This option controls the default broadcaster that will be used by the framework when an event needs to be broadcast. +# +# Possible values: +# - "pusher" +# - "redis" +# - "log" +# - "null" (default) +# +# @default null +# @see https://docs.pixelfed.org/technical-documentation/config/#broadcast_driver +# @dottie/validate required,oneof=pusher redis log null +BROADCAST_DRIVER="redis" + +# @default "true" +# @see https://docs.pixelfed.org/technical-documentation/config/#restrict_html_types +# @dottie/validate required,boolean +#RESTRICT_HTML_TYPES="true" + +# Passport uses encryption keys while generating secure access tokens +# for your application. +# +# By default, the keys are stored as local files but can be set via environment +# variables when that is more convenient. + +# @see https://docs.pixelfed.org/technical-documentation/config/#passport_private_key +# @dottie/validate required +#PASSPORT_PRIVATE_KEY="" + +# @see https://docs.pixelfed.org/technical-documentation/config/#passport_public_key +# @dottie/validate required +#PASSPORT_PUBLIC_KEY="" ################################################################################ -# Database configuration +# database ################################################################################ # Database version to use (as Docker tag) # -# See: https://hub.docker.com/_/mariadb +# @see https://hub.docker.com/_/mariadb +# @dottie/validate required DB_VERSION="11.2" # Here you may specify which of the database connections below @@ -265,31 +345,38 @@ DB_VERSION="11.2" # - "pgsql" # - "sqlsrv" # -# See: https://docs.pixelfed.org/technical-documentation/config/#db_connection +# @see https://docs.pixelfed.org/technical-documentation/config/#db_connection +# @dottie/validate required,oneof=sqlite mysql pgsql sqlsrv DB_CONNECTION="mysql" -# See: https://docs.pixelfed.org/technical-documentation/config/#db_host +# @see https://docs.pixelfed.org/technical-documentation/config/#db_host +# @dottie/validate required,hostname DB_HOST="db" -# See: https://docs.pixelfed.org/technical-documentation/config/#db_username +# @see https://docs.pixelfed.org/technical-documentation/config/#db_username +# @dottie/validate required DB_USERNAME="pixelfed" -# See: https://docs.pixelfed.org/technical-documentation/config/#db_password -DB_PASSWORD="__CHANGE_ME__" +# @see https://docs.pixelfed.org/technical-documentation/config/#db_password +# @dottie/validate required +DB_PASSWORD= -# See: https://docs.pixelfed.org/technical-documentation/config/#db_database +# @see https://docs.pixelfed.org/technical-documentation/config/#db_database +# @dottie/validate required DB_DATABASE="pixelfed_prod" # Use "3306" for MySQL/MariaDB and "5432" for PostgreeSQL # -# See: https://docs.pixelfed.org/technical-documentation/config/#db_port +# @see https://docs.pixelfed.org/technical-documentation/config/#db_port +# @dottie/validate required,number DB_PORT="3306" # Automatically run [artisan migrate --force] if new migrations are detected. +# @dottie/validate required,boolean DB_APPLY_NEW_MIGRATIONS_AUTOMATICALLY="false" ################################################################################ -# Mail configuration +# mail ################################################################################ # Laravel supports both SMTP and PHP’s “mail” function as drivers for the sending of e-mail. @@ -306,39 +393,41 @@ DB_APPLY_NEW_MIGRATIONS_AUTOMATICALLY="false" # "log" # "array" # -# See: https://docs.pixelfed.org/technical-documentation/config/#mail_driver +# @default "smtp" +# @see https://docs.pixelfed.org/technical-documentation/config/#mail_driver +# @dottie/validate required,oneof=smtp sendmail mailgun mandrill ses sparkpost log array #MAIL_DRIVER="smtp" # The host address of the SMTP server used by your applications. # # A default option is provided that is compatible with the Mailgun mail service which will provide reliable deliveries. # -# Defaults to "smtp.mailgun.org". -# -# See: https://docs.pixelfed.org/technical-documentation/config/#mail_host +# @default "smtp.mailgun.org" +# @see https://docs.pixelfed.org/technical-documentation/config/#mail_host +# @dottie/validate required_with=MAIL_DRIVER,fqdn #MAIL_HOST="smtp.mailgun.org" # This is the SMTP port used by your application to deliver e-mails to users of the application. # # Like the host we have set this value to stay compatible with the Mailgun e-mail application by default. # -# Defaults to 587. -# -# See: https://docs.pixelfed.org/technical-documentation/config/#mail_port +# @default 587. +# @see https://docs.pixelfed.org/technical-documentation/config/#mail_port +# @dottie/validate required_with=MAIL_DRIVER,number #MAIL_PORT="587" # You may wish for all e-mails sent by your application to be sent from the same address. # # Here, you may specify a name and address that is used globally for all e-mails that are sent by your application. # -# Defaults to "hello@example.com". -# -# See: https://docs.pixelfed.org/technical-documentation/config/#mail_from_address +# @default "hello@example.com" +# @see https://docs.pixelfed.org/technical-documentation/config/#mail_from_address +# @dottie/validate required_with=MAIL_DRIVER,email MAIL_FROM_ADDRESS="hello@${APP_DOMAIN}" -# Defaults to "Example". -# -# See: https://docs.pixelfed.org/technical-documentation/config/#mail_from_name +# @default "Example" +# @see https://docs.pixelfed.org/technical-documentation/config/#mail_from_name +# @dottie/validate required_with=MAIL_DRIVER MAIL_FROM_NAME="Pixelfed @ ${APP_DOMAIN}" # If your SMTP server requires a username for authentication, you should set it here. @@ -346,220 +435,148 @@ MAIL_FROM_NAME="Pixelfed @ ${APP_DOMAIN}" # This will get used to authenticate with your server on connection. # You may also set the “password” value below this one. # -# Defaults to "". -# -# See: https://docs.pixelfed.org/technical-documentation/config/#mail_username +# @default "" +# @see https://docs.pixelfed.org/technical-documentation/config/#mail_username +# @dottie/validate required_with=MAIL_DRIVER #MAIL_USERNAME="" -# Defaults to "". -# -# See: https://docs.pixelfed.org/technical-documentation/config/#mail_password +# @default "" +# @see https://docs.pixelfed.org/technical-documentation/config/#mail_password +# @dottie/validate required_with=MAIL_DRIVER #MAIL_PASSWORD="" # Here you may specify the encryption protocol that should be used when the application send e-mail messages. # # A sensible default using the transport layer security protocol should provide great security. # -# Defaults to "tls". -# -# See: https://docs.pixelfed.org/technical-documentation/config/#mail_encryption +# @default "tls" +# @see https://docs.pixelfed.org/technical-documentation/config/#mail_encryption +# @dottie/validate required_with=MAIL_DRIVER #MAIL_ENCRYPTION="tls" ################################################################################ -# Redis configuration +# redis ################################################################################ -# Defaults to "phpredis". -# -# See: https://docs.pixelfed.org/technical-documentation/config/#redis_client +# @default "phpredis" +# @see https://docs.pixelfed.org/technical-documentation/config/#redis_client +# @dottie/validate required #REDIS_CLIENT="phpredis" -# Defaults to "tcp". -# -# See: https://docs.pixelfed.org/technical-documentation/config/#redis_scheme +# @default "tcp" +# @see https://docs.pixelfed.org/technical-documentation/config/#redis_scheme +# @dottie/validate required #REDIS_SCHEME="tcp" -# Defaults to "localhost". -# -# See: https://docs.pixelfed.org/technical-documentation/config/#redis_host +# @default "localhost" +# @see https://docs.pixelfed.org/technical-documentation/config/#redis_host +# @dottie/validate required REDIS_HOST="redis" -# Defaults to null (not set/commented out). -# -# See: https://docs.pixelfed.org/technical-documentation/config/#redis_password +# @default "null" (not set/commented out). +# @see https://docs.pixelfed.org/technical-documentation/config/#redis_password +# @dottie/validate omitempty #REDIS_PASSWORD= -# Defaults to "6379". -# -# See: https://docs.pixelfed.org/technical-documentation/config/#redis_port +# @default "6379" +# @see https://docs.pixelfed.org/technical-documentation/config/#redis_port +# @dottie/validate required,number REDIS_PORT="6379" -# Defaults to "0". -# -# See: https://docs.pixelfed.org/technical-documentation/config/#redis_database +# @default "0" +# @see https://docs.pixelfed.org/technical-documentation/config/#redis_database +# @dottie/validate required,number #REDIS_DATABASE="0" ################################################################################ -# Cache settings -################################################################################ - -# This option controls the default cache connection that gets used while using this caching library. -# -# This connection is used when another is not explicitly specified when executing a given caching function. -# -# Possible values: -# - "apc" -# - "array" -# - "database" -# - "file" (default) -# - "memcached" -# - "redis" -# -# See: https://docs.pixelfed.org/technical-documentation/config/#cache_driver -CACHE_DRIVER="redis" - -# Defaults to ${APP_NAME}_cache, or laravel_cache if no APP_NAME is set. -# -# See: https://docs.pixelfed.org/technical-documentation/config/#cache_prefix -#CACHE_PREFIX="{APP_NAME}_cache" - -################################################################################ -# Horizon settings -################################################################################ - -# This prefix will be used when storing all Horizon data in Redis. -# -# You may modify the prefix when you are running multiple installations -# of Horizon on the same server so that they don’t have problems. -# -# Defaults to "horizon-". -# -# See: https://docs.pixelfed.org/technical-documentation/config/#horizon_prefix -#HORIZON_PREFIX="horizon-" - -# Defaults to "false". -# -# See: https://docs.pixelfed.org/technical-documentation/config/#horizon_darkmode -#HORIZON_DARKMODE="false" - -# This value (in MB) describes the maximum amount of memory (in MB) the Horizon worker -# may consume before it is terminated and restarted. -# -# You should set this value according to the resources available to your server. -# -# Defaults to "64". -#HORIZON_MEMORY_LIMIT="64" - -# See: https://docs.pixelfed.org/technical-documentation/config/#horizon_balance_strategy -#HORIZON_BALANCE_STRATEGY="auto" - -# See: https://docs.pixelfed.org/technical-documentation/config/#horizon_min_processes -#HORIZON_MIN_PROCESSES="1" - -# See: https://docs.pixelfed.org/technical-documentation/config/#horizon_max_processes -#HORIZON_MAX_PROCESSES="20" - -# See: https://docs.pixelfed.org/technical-documentation/config/#horizon_supervisor_memory -#HORIZON_SUPERVISOR_MEMORY="64" - -# See: https://docs.pixelfed.org/technical-documentation/config/#horizon_supervisor_tries -#HORIZON_SUPERVISOR_TRIES="3" - -# See: https://docs.pixelfed.org/technical-documentation/config/#horizon_supervisor_nice -#HORIZON_SUPERVISOR_NICE="0" - -# See: https://docs.pixelfed.org/technical-documentation/config/#horizon_supervisor_timeout -#HORIZON_SUPERVISOR_TIMEOUT="300" - -################################################################################ -# Experiments +# experiments ################################################################################ # Text only posts (alpha). # -# Defaults to "false". -# -# See: https://docs.pixelfed.org/technical-documentation/config/#exp_top +# @default "false" +# @see https://docs.pixelfed.org/technical-documentation/config/#exp_top +# @dottie/validate required,boolean #EXP_TOP="false" # Poll statuses (alpha). # -# Defaults to "false". -# -# See: https://docs.pixelfed.org/technical-documentation/config/#exp_polls +# @default "false" +# @see https://docs.pixelfed.org/technical-documentation/config/#exp_polls +# @dottie/validate required,boolean #EXP_POLLS="false" # Cached public timeline for larger instances (beta). # -# Defaults to "false". -# -# See: https://docs.pixelfed.org/technical-documentation/config/#exp_cpt +# @default "false" +# @see https://docs.pixelfed.org/technical-documentation/config/#exp_cpt +# @dottie/validate required,boolean #EXP_CPT="false" # Enforce Mastodon API Compatibility (alpha). # -# Defaults to "true". -# -# See: https://docs.pixelfed.org/technical-documentation/config/#exp_emc +# @default "true" +# @see https://docs.pixelfed.org/technical-documentation/config/#exp_emc +# @dottie/validate required,boolean #EXP_EMC="true" ################################################################################ -# ActivityPub confguration +# ActivityPub ################################################################################ -# Defaults to "false". -# -# See: https://docs.pixelfed.org/technical-documentation/config/#activity_pub -ACTIVITY_PUB="true" +# @default "false" +# @see https://docs.pixelfed.org/technical-documentation/config/#activity_pub +# @dottie/validate required,boolean +#ACTIVITY_PUB="true" -# Defaults to "true". -# -# See: https://docs.pixelfed.org/technical-documentation/config/#ap_remote_follow +# @default "true" +# @see https://docs.pixelfed.org/technical-documentation/config/#ap_remote_follow +# @dottie/validate required,boolean #AP_REMOTE_FOLLOW="true" -# Defaults to "true". -# -# See: https://docs.pixelfed.org/technical-documentation/config/#ap_sharedinbox +# @default "true" +# @see https://docs.pixelfed.org/technical-documentation/config/#ap_sharedinbox +# @dottie/validate required,boolean #AP_SHAREDINBOX="true" -# Defaults to "true". -# -# See: https://docs.pixelfed.org/technical-documentation/config/#ap_inbox +# @default "true" +# @see https://docs.pixelfed.org/technical-documentation/config/#ap_inbox +# @dottie/validate required,boolean #AP_INBOX="true" -# Defaults to "true". -# -# See: https://docs.pixelfed.org/technical-documentation/config/#ap_outbox +# @default "true" +# @see https://docs.pixelfed.org/technical-documentation/config/#ap_outbox +# @dottie/validate required,boolean #AP_OUTBOX="true" ################################################################################ -# Federation confguration +# Federation ################################################################################ -# Defaults to "true". -# -# See: https://docs.pixelfed.org/technical-documentation/config/#atom_feeds +# @default "true" +# @see https://docs.pixelfed.org/technical-documentation/config/#atom_feeds +# @dottie/validate required,boolean #ATOM_FEEDS="true" -# Defaults to "true". -# -# See: https://docs.pixelfed.org/technical-documentation/config/#nodeinfo +# @default "true" +# @see https://docs.pixelfed.org/technical-documentation/config/#nodeinfo +# @dottie/validate required,boolean #NODEINFO="true" -# Defaults to "true". -# -# See: https://docs.pixelfed.org/technical-documentation/config/#webfinger +# @default "true" +# @see https://docs.pixelfed.org/technical-documentation/config/#webfinger +# @dottie/validate required,boolean #WEBFINGER="true" ################################################################################ -# Storage (cloud) +# Storage ################################################################################ # Store media on object storage like S3, Digital Ocean Spaces, Rackspace # -# Defaults to "false". -# -# See: https://docs.pixelfed.org/technical-documentation/config/#pf_enable_cloud +# @default "false" +# @see https://docs.pixelfed.org/technical-documentation/config/#pf_enable_cloud +# @dottie/validate required,boolean #PF_ENABLE_CLOUD="false" # Many applications store files both locally and in the cloud. @@ -567,125 +584,108 @@ ACTIVITY_PUB="true" # For this reason, you may specify a default “cloud” driver here. # This driver will be bound as the Cloud disk implementation in the container. # -# Defaults to "s3". -# -# See: https://docs.pixelfed.org/technical-documentation/config/#filesystem_cloud +# @default "s3" +# @see https://docs.pixelfed.org/technical-documentation/config/#filesystem_cloud +# @dottie/validate required_with=PF_ENABLE_CLOUD #FILESYSTEM_CLOUD="s3" -# Defaults to true. -# -# See: https://docs.pixelfed.org/technical-documentation/config/#media_delete_local_after_cloud +# @default true. +# @see https://docs.pixelfed.org/technical-documentation/config/#media_delete_local_after_cloud +# @dottie/validate required_with=PF_ENABLE_CLOUD,boolean #MEDIA_DELETE_LOCAL_AFTER_CLOUD="true" -################################################################################ -# Storage (cloud) - S3 andS S3 *compatible* providers -################################################################################ - -# See: https://docs.pixelfed.org/technical-documentation/config/#aws_access_key_id +# @see https://docs.pixelfed.org/technical-documentation/config/#aws_access_key_id +# @dottie/validate required_if=FILESYSTEM_CLOUD s3 #AWS_ACCESS_KEY_ID="" -# See: https://docs.pixelfed.org/technical-documentation/config/#aws_secret_access_key +# @see https://docs.pixelfed.org/technical-documentation/config/#aws_secret_access_key +# @dottie/validate required_if=FILESYSTEM_CLOUD s3 #AWS_SECRET_ACCESS_KEY="" -# See: https://docs.pixelfed.org/technical-documentation/config/#aws_default_region +# @see https://docs.pixelfed.org/technical-documentation/config/#aws_default_region +# @dottie/validate required_if=FILESYSTEM_CLOUD s3 #AWS_DEFAULT_REGION="" -# See: https://docs.pixelfed.org/technical-documentation/config/#aws_bucket +# @see https://docs.pixelfed.org/technical-documentation/config/#aws_bucket +# @dottie/validate required_if=FILESYSTEM_CLOUD s3 #AWS_BUCKET="" -# See: https://docs.pixelfed.org/technical-documentation/config/#aws_url +# @see https://docs.pixelfed.org/technical-documentation/config/#aws_url +# @dottie/validate required_if=FILESYSTEM_CLOUD s3 #AWS_URL="" -# See: https://docs.pixelfed.org/technical-documentation/config/#aws_endpoint +# @see https://docs.pixelfed.org/technical-documentation/config/#aws_endpoint +# @dottie/validate required_if=FILESYSTEM_CLOUD s3 #AWS_ENDPOINT="" -# See: https://docs.pixelfed.org/technical-documentation/config/#aws_use_path_style_endpoint +# @see https://docs.pixelfed.org/technical-documentation/config/#aws_use_path_style_endpoint +# @dottie/validate required_if=FILESYSTEM_CLOUD s3 #AWS_USE_PATH_STYLE_ENDPOINT="false" -############################################################### -# COSTAR - Confirm Object Sentiment Transform and Reduce -############################################################### +################################################################################ +# COSTAR +################################################################################ # Comma-separated list of domains to block. # -# Defaults to null (not set/commented out). -# -# See: https://docs.pixelfed.org/technical-documentation/config/#cs_blocked_domains +# @default null (not set/commented out). +# @see https://docs.pixelfed.org/technical-documentation/config/#cs_blocked_domains +# @dottie/validate #CS_BLOCKED_DOMAINS="" # Comma-separated list of domains to add warnings. # -# Defaults to null (not set/commented out). -# -# See: https://docs.pixelfed.org/technical-documentation/config/#cs_cw_domains +# @default null (not set/commented out). +# @see https://docs.pixelfed.org/technical-documentation/config/#cs_cw_domains +# @dottie/validate #CS_CW_DOMAINS="" # Comma-separated list of domains to remove from public timelines. # -# Defaults to null (not set/commented out). -# -# See: https://docs.pixelfed.org/technical-documentation/config/#cs_unlisted_domains +# @default null (not set/commented out). +# @see https://docs.pixelfed.org/technical-documentation/config/#cs_unlisted_domains +# @dottie/validate #CS_UNLISTED_DOMAINS="" # Comma-separated list of keywords to block. # -# Defaults to null (not set/commented out). -# -# See: https://docs.pixelfed.org/technical-documentation/config/#cs_blocked_keywords +# @default null (not set/commented out). +# @see https://docs.pixelfed.org/technical-documentation/config/#cs_blocked_keywords +# @dottie/validate #CS_BLOCKED_KEYWORDS="" # Comma-separated list of keywords to add warnings. # -# Defaults to null (not set/commented out). -# -# See: https://docs.pixelfed.org/technical-documentation/config/#cs_cw_keywords +# @default null (not set/commented out). +# @see https://docs.pixelfed.org/technical-documentation/config/#cs_cw_keywords +# @dottie/validate #CS_CW_KEYWORDS="" # Comma-separated list of keywords to remove from public timelines. # -# Defaults to null (not set/commented out). -# -# See: https://docs.pixelfed.org/technical-documentation/config/#cs_unlisted_keywords +# @default null (not set/commented out). +# @see https://docs.pixelfed.org/technical-documentation/config/#cs_unlisted_keywords +# @dottie/validate #CS_UNLISTED_KEYWORDS="" -# Defaults to null (not set/commented out). -# -# See: https://docs.pixelfed.org/technical-documentation/config/#cs_blocked_actor +# @default null (not set/commented out). +# @see https://docs.pixelfed.org/technical-documentation/config/#cs_blocked_actor +# @dottie/validate #CS_BLOCKED_ACTOR="" -# Defaults to null (not set/commented out). -# -# See: https://docs.pixelfed.org/technical-documentation/config/#cs_cw_actor +# @default null (not set/commented out). +# @see https://docs.pixelfed.org/technical-documentation/config/#cs_cw_actor +# @dottie/validate #CS_CW_ACTOR="" -# Defaults to null (not set/commented out). -# -# See: https://docs.pixelfed.org/technical-documentation/config/#cs_unlisted_actor +# @default null (not set/commented out). +# @see https://docs.pixelfed.org/technical-documentation/config/#cs_unlisted_actor +# @dottie/validate #CS_UNLISTED_ACTOR="" -############################################################### -# Media -############################################################### - -# Defaults to false. -# -# See: https://docs.pixelfed.org/technical-documentation/config/#media_exif_database -MEDIA_EXIF_DATABASE="true" - -# Pixelfed supports GD or ImageMagick to process images. -# -# Defaults to "gd". -# -# Possible values: -# - "gd" (default) -# - "imagick" -# -# See: https://docs.pixelfed.org/technical-documentation/config/#image_driver -#IMAGE_DRIVER="gd" - -############################################################### -# Logging -############################################################### +################################################################################ +# logging +################################################################################ # Possible values: # @@ -699,56 +699,35 @@ MEDIA_EXIF_DATABASE="true" # - "null" # - "emergency" # - "media" +# +# @default "stack" +# @dottie/validate required,oneof=stack single daily slack stderr syslog errorlog null emergency media LOG_CHANNEL="stderr" # Used by single, stderr and syslog. # -# Defaults to "debug" for all of those. -# -# See: https://docs.pixelfed.org/technical-documentation/config/#log_level +# @default "debug" +# @see https://docs.pixelfed.org/technical-documentation/config/#log_level +# @dottie/validate required,boolean #LOG_LEVEL="debug" # Used by stderr. # -# Defaults to "". -# -# See: https://docs.pixelfed.org/technical-documentation/config/#log_stderr_formatter +# @default "" +# @see https://docs.pixelfed.org/technical-documentation/config/#log_stderr_formatter +# @dottie/validate required #LOG_STDERR_FORMATTER="" # Used by slack. # -# Defaults to "". -# -# See: https://docs.pixelfed.org/technical-documentation/config/#log_slack_webhook_url +# @default "" +# @see https://docs.pixelfed.org/technical-documentation/config/#log_slack_webhook_url +# @dottie/validate required,http_url #LOG_SLACK_WEBHOOK_URL="" -############################################################### -# Broadcasting settings -############################################################### - -# This option controls the default broadcaster that will be used by the framework when an event needs to be broadcast. -# -# Possible values: -# - "pusher" -# - "redis" -# - "log" -# - "null" (default) -# -# See: https://docs.pixelfed.org/technical-documentation/config/#broadcast_driver -BROADCAST_DRIVER="redis" - -############################################################### -# Sanitizing settings -############################################################### - -# Defaults to "true". -# -# See: https://docs.pixelfed.org/technical-documentation/config/#restrict_html_types -#RESTRICT_HTML_TYPES="true" - -############################################################### -# Queue configuration -############################################################### +################################################################################ +# queue +################################################################################ # Possible values: # - "sync" (default) @@ -758,41 +737,39 @@ BROADCAST_DRIVER="redis" # - "redis" # - "null" # -# See: https://docs.pixelfed.org/technical-documentation/config/#queue_driver +# @default "sync" +# @see https://docs.pixelfed.org/technical-documentation/config/#queue_driver +# @dottie/validate required,oneof=sync database beanstalkd sqs redis null QUEUE_DRIVER="redis" -############################################################### -# Queue (SQS) configuration -############################################################### - -# Defaults to "your-public-key". -# -# See: https://docs.pixelfed.org/technical-documentation/config/#sqs_key +# @default "your-public-key" +# @see https://docs.pixelfed.org/technical-documentation/config/#sqs_key +# @dottie/validate required_if=QUEUE_DRIVER sqs #SQS_KEY="your-public-key" -# Defaults to "your-secret-key". -# -# See: https://docs.pixelfed.org/technical-documentation/config/#sqs_secret +# @default "your-secret-key" +# @see https://docs.pixelfed.org/technical-documentation/config/#sqs_secret +# @dottie/validate required_if=QUEUE_DRIVER sqs #SQS_SECRET="your-secret-key" -# Defaults to "https://sqs.us-east-1.amazonaws.com/your-account-id". -# -# See: https://docs.pixelfed.org/technical-documentation/config/#sqs_prefix +# @default "https://sqs.us-east-1.amazonaws.com/your-account-id" +# @see https://docs.pixelfed.org/technical-documentation/config/#sqs_prefix +# @dottie/validate required_if=QUEUE_DRIVER sqs #SQS_PREFIX="" -# Defaults to "your-queue-name". -# -# https://docs.pixelfed.org/technical-documentation/config/#sqs_queue +# @default "your-queue-name" +# @see https://docs.pixelfed.org/technical-documentation/config/#sqs_queue +# @dottie/validate required_if=QUEUE_DRIVER sqs #SQS_QUEUE="your-queue-name" -# Defaults to "us-east-1". -# -# See: https://docs.pixelfed.org/technical-documentation/config/#sqs_region +# @default "us-east-1" +# @see https://docs.pixelfed.org/technical-documentation/config/#sqs_region +# @dottie/validate required_if=QUEUE_DRIVER sqs #SQS_REGION="us-east-1" -############################################################### -# Session configuration -############################################################### +################################################################################ +# session +################################################################################ # This option controls the default session “driver” that will be used on requests. # @@ -806,15 +783,18 @@ QUEUE_DRIVER="redis" # - "memcached" # - "redis" # - "array" +# +# @default "database" +# @dottie/validate required,oneof=file cookie database apc memcached redis array SESSION_DRIVER="redis" # Here you may specify the number of minutes that you wish the session to be allowed to remain idle before it expires. # # If you want them to immediately expire on the browser closing, set that option. # -# Defaults to 86400. -# -# See: https://docs.pixelfed.org/technical-documentation/config/#session_lifetime +# @default 86400. +# @see https://docs.pixelfed.org/technical-documentation/config/#session_lifetime +# @dottie/validate required,number #SESSION_LIFETIME="86400" # Here you may change the domain of the cookie used to identify a session in your application. @@ -823,101 +803,130 @@ SESSION_DRIVER="redis" # # A sensible default has been set. # -# Defaults to the value of APP_DOMAIN, or null. -# -# See: https://docs.pixelfed.org/technical-documentation/config/#session_domain +# @default the value of APP_DOMAIN, or null. +# @see https://docs.pixelfed.org/technical-documentation/config/#session_domain +# @dottie/validate required,domain #SESSION_DOMAIN="${APP_DOMAIN}" -############################################################### -# Proxy configuration -############################################################### - -# Set trusted proxy IP addresses. -# -# Both IPv4 and IPv6 addresses are supported, along with CIDR notation. -# -# The “*” character is syntactic sugar within TrustedProxy to trust any -# proxy that connects directly to your server, a requirement when you cannot -# know the address of your proxy (e.g. if using Rackspace balancers). -# -# The “**” character is syntactic sugar within TrustedProxy to trust not just any -# proxy that connects directly to your server, but also proxies that connect to those proxies, -# and all the way back until you reach the original source IP. It will mean that -# $request->getClientIp() always gets the originating client IP, no matter how many proxies -# that client’s request has subsequently passed through. -# -# Defaults to "*". -# -# See: https://docs.pixelfed.org/technical-documentation/config/#trust_proxies -TRUST_PROXIES="*" - -############################################################### -# Passport configuration -############################################################### -# -# Passport uses encryption keys while generating secure access tokens -# for your application. -# -# By default, the keys are stored as local files but can be set via environment -# variables when that is more convenient. - -# See: https://docs.pixelfed.org/technical-documentation/config/#passport_private_key -#PASSPORT_PRIVATE_KEY="" - -# See: https://docs.pixelfed.org/technical-documentation/config/#passport_public_key -#PASSPORT_PUBLIC_KEY="" - -############################################################### -# PHP configuration -############################################################### - -# See: https://www.php.net/manual/en/ini.core.php#ini.memory-limit -#PHP_MEMORY_LIMIT="128M" - ################################################################################ -# Other configuration +# horizon ################################################################################ -# ? Add your own configuration here - -################################################################################ -# Timezone configuration -################################################################################ - -# Set timezone used by *all* containers - these must be in sync. +# This prefix will be used when storing all Horizon data in Redis. # -# ! Do not edit your timezone once the service is running - or things will break! +# You may modify the prefix when you are running multiple installations +# of Horizon on the same server so that they don’t have problems. # -# See: https://www.php.net/manual/en/timezones.php -TZ="${APP_TIMEZONE}" +# @default "horizon-" +# @see https://docs.pixelfed.org/technical-documentation/config/#horizon_prefix +# @dottie/validate required +#HORIZON_PREFIX="horizon-" + +# @default "false" +# @see https://docs.pixelfed.org/technical-documentation/config/#horizon_darkmode +# @dottie/validate required,boolean +#HORIZON_DARKMODE="false" + +# This value (in MB) describes the maximum amount of memory (in MB) the Horizon worker +# may consume before it is terminated and restarted. +# +# You should set this value according to the resources available to your server. +# +# @default "64" +# @dottie/validate required,number +#HORIZON_MEMORY_LIMIT="64" + +# @see https://docs.pixelfed.org/technical-documentation/config/#horizon_balance_strategy +# @dottie/validate required +#HORIZON_BALANCE_STRATEGY="auto" + +# @see https://docs.pixelfed.org/technical-documentation/config/#horizon_min_processes +# @dottie/validate required,number +#HORIZON_MIN_PROCESSES="1" + +# @see https://docs.pixelfed.org/technical-documentation/config/#horizon_max_processes +# @dottie/validate required,number +#HORIZON_MAX_PROCESSES="20" + +# @see https://docs.pixelfed.org/technical-documentation/config/#horizon_supervisor_memory +# @dottie/validate required,number +#HORIZON_SUPERVISOR_MEMORY="64" + +# @see https://docs.pixelfed.org/technical-documentation/config/#horizon_supervisor_tries +# @dottie/validate required,number +#HORIZON_SUPERVISOR_TRIES="3" + +# @see https://docs.pixelfed.org/technical-documentation/config/#horizon_supervisor_nice +# @dottie/validate required,number +#HORIZON_SUPERVISOR_NICE="0" + +# @see https://docs.pixelfed.org/technical-documentation/config/#horizon_supervisor_timeout +# @dottie/validate required,number +#HORIZON_SUPERVISOR_TIMEOUT="300" ################################################################################ -# Docker configuraton for *all* services +# docker shared ################################################################################ +# A random 32-character string to be used as an encryption key. +# +# !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! +# ! NOTE: This will be auto-generated by Docker during bootstrap +# !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! +# +# This key is used by the Illuminate encrypter service and should be set to a random, +# 32 character string, otherwise these encrypted strings will not be safe. +# +# @see https://docs.pixelfed.org/technical-documentation/config/#app_key +APP_KEY= + # Prefix for container names (without any dash at the end) +# @dottie/validate required DOCKER_ALL_CONTAINER_NAME_PREFIX="${APP_DOMAIN}" # How often Docker health check should run for all services # # Can be overridden by individual [DOCKER_*_HEALTHCHECK_INTERVAL] settings further down +# +# @default "10s" +# @dottie/validate required DOCKER_ALL_DEFAULT_HEALTHCHECK_INTERVAL="10s" # Path (relative to the docker-compose.yml) or absolute (/some/other/path) where containers will *all* data # will be stored (data, config, overrides) +# +# @default "./docker-compose-state" +# @dottie/validate required,dir DOCKER_ALL_HOST_ROOT_PATH="./docker-compose-state" # Path (relative to the docker-compose.yml) or absolute (/some/other/path) where containers will store their data -DOCKER_ALL_HOST_DATA_ROOT_PATH="${DOCKER_ALL_HOST_ROOT_PATH}/data" +# +# @default "${DOCKER_ALL_HOST_ROOT_PATH}/data" +# @dottie/validate required,dir +DOCKER_ALL_HOST_DATA_ROOT_PATH="${DOCKER_ALL_HOST_ROOT_PATH:?error}/data" # Path (relative to the docker-compose.yml) or absolute (/some/other/path) where containers will store their confguration -DOCKER_ALL_HOST_CONFIG_ROOT_PATH="${DOCKER_ALL_HOST_ROOT_PATH}/config" +# +# @default "${DOCKER_ALL_HOST_ROOT_PATH}/config" +# @dottie/validate required,dir +DOCKER_ALL_HOST_CONFIG_ROOT_PATH="${DOCKER_ALL_HOST_ROOT_PATH:?error}/config" # Path (relative to the docker-compose.yml) or absolute (/some/other/path) where containers will store overrides -DOCKER_APP_HOST_OVERRIDES_PATH="${DOCKER_ALL_HOST_ROOT_PATH}/overrides" +# +# @default "${DOCKER_ALL_HOST_ROOT_PATH}/overrides" +# @dottie/validate required,dir +DOCKER_APP_HOST_OVERRIDES_PATH="${DOCKER_ALL_HOST_ROOT_PATH:?error}/overrides" + +# Set timezone used by *all* containers - these must be in sync. +# +# ! Do not edit your timezone once the service is running - or things will break! +# +# @see https://www.php.net/manual/en/timezones.php +# @dottie/validate required,timezone +TZ="${APP_TIMEZONE}" ################################################################################ -# Docker [web] + [worker] (also know as "app") shared service configuration +# docker app ################################################################################ # The docker tag prefix to use for pulling images, can be one of @@ -931,6 +940,7 @@ DOCKER_APP_HOST_OVERRIDES_PATH="${DOCKER_ALL_HOST_ROOT_PATH}/overrides" # # Combined with [DOCKER_APP_RUNTIME] and [PHP_VERSION] configured # elsewhere in this file, the final Docker tag is computed. +# @dottie/validate required DOCKER_APP_RELEASE="branch-jippi-fork" # The PHP version to use for [web] and [worker] container @@ -947,21 +957,25 @@ DOCKER_APP_RELEASE="branch-jippi-fork" # Do *NOT* use the full Docker tag (e.g. "8.3.2RC1-fpm-bullseye") # *only* the version part. The rest of the full tag is derived from # the [DOCKER_APP_RUNTIME] and [PHP_DEBIAN_RELEASE] settings +# @dottie/validate required DOCKER_APP_PHP_VERSION="8.2" # The container runtime to use. # -# See: https://docs.pixelfed.org/running-pixelfed/docker/runtimes.html +# @see https://docs.pixelfed.org/running-pixelfed/docker/runtimes.html +# @dottie/validate required,oneof=apache nginx fpm DOCKER_APP_RUNTIME="apache" # The Debian release variant to use of the [php] Docker image # # Examlpe: [bookworm] or [bullseye] +# @dottie/validate required,oneof=bookwork bullseye DOCKER_APP_DEBIAN_RELEASE="bullseye" # The [php] Docker image base type # -# See: https://docs.pixelfed.org/running-pixelfed/docker/runtimes.html +# @see https://docs.pixelfed.org/running-pixelfed/docker/runtimes.html +# @dottie/validate required,oneof=apache fpm cli DOCKER_APP_BASE_TYPE="apache" # Image to pull the Pixelfed Docker images from. @@ -972,24 +986,28 @@ DOCKER_APP_BASE_TYPE="apache" # * "pixelfed/pixelfed" to pull from DockerHub # * "your/fork" to pull from a custom fork # +# @dottie/validate required DOCKER_APP_IMAGE="ghcr.io/jippi/pixelfed" # Pixelfed version (image tag) to pull from the registry. # -# See: https://github.com/pixelfed/pixelfed/pkgs/container/pixelfed -DOCKER_APP_TAG="${DOCKER_APP_RELEASE}-${DOCKER_APP_RUNTIME}-${DOCKER_APP_PHP_VERSION}" +# @see https://github.com/pixelfed/pixelfed/pkgs/container/pixelfed +# @dottie/validate required +DOCKER_APP_TAG="${DOCKER_APP_RELEASE:?error}-${DOCKER_APP_RUNTIME:?error}-${DOCKER_APP_PHP_VERSION:?error}" # Path (on host system) where the [app] + [worker] container will write # its [storage] data (e.g uploads/images/profile pictures etc.). # # Path is relative (./some/other/path) to the docker-compose.yml or absolute (/some/other/path) -DOCKER_APP_HOST_STORAGE_PATH="${DOCKER_ALL_HOST_DATA_ROOT_PATH}/pixelfed/storage" +# @dottie/validate required,dir +DOCKER_APP_HOST_STORAGE_PATH="${DOCKER_ALL_HOST_DATA_ROOT_PATH:?error}/pixelfed/storage" # Path (on host system) where the [app] + [worker] container will write # its [cache] data. # # Path is relative (./some/other/path) to the docker-compose.yml or absolute (/some/other/path) -DOCKER_APP_HOST_CACHE_PATH="${DOCKER_ALL_HOST_DATA_ROOT_PATH}/pixelfed/cache" +# @dottie/validate required,dir +DOCKER_APP_HOST_CACHE_PATH="${DOCKER_ALL_HOST_DATA_ROOT_PATH:?error}/pixelfed/cache" # Automatically run "One-time setup tasks" commands. # @@ -998,6 +1016,7 @@ DOCKER_APP_HOST_CACHE_PATH="${DOCKER_ALL_HOST_DATA_ROOT_PATH}/pixelfed/cache" # you can set this to "0" to prevent them from running. # # Otherwise, leave it at "1" to have them run *once*. +# @dottie/validate required,boolean #DOCKER_APP_RUN_ONE_TIME_SETUP_TASKS="1" # A space-seperated list of paths (inside the container) to *recursively* [chown] @@ -1008,46 +1027,59 @@ DOCKER_APP_HOST_CACHE_PATH="${DOCKER_ALL_HOST_DATA_ROOT_PATH}/pixelfed/cache" # ! issues. Please report a bug if you see behavior requiring this to be permanently on # # Example: "/var/www/storage /var/www/bootstrap/cache" +# @dottie/validate required #DOCKER_APP_ENSURE_OWNERSHIP_PATHS="" # Enable Docker Entrypoint debug mode (will call [set -x] in bash scripts) -# by setting this to "1". +# by setting this to "1" +# @dottie/validate required,boolean #DOCKER_APP_ENTRYPOINT_DEBUG="0" # List of extra APT packages (separated by space) to install when building # locally using [docker compose build]. # -# See: https://github.com/pixelfed/pixelfed/blob/dev/docker/customizing.md +# @see https://github.com/pixelfed/pixelfed/blob/dev/docker/customizing.md +# @dottie/validate required #DOCKER_APP_APT_PACKAGES_EXTRA="" # List of *extra* PECL extensions (separated by space) to install when # building locally using [docker compose build]. # -# See: https://github.com/pixelfed/pixelfed/blob/dev/docker/customizing.md +# @see https://github.com/pixelfed/pixelfed/blob/dev/docker/customizing.md +# @dottie/validate required #DOCKER_APP_PHP_PECL_EXTENSIONS_EXTRA="" # List of *extra* PHP extensions (separated by space) to install when # building locally using [docker compose build]. # -# See: https://github.com/pixelfed/pixelfed/blob/dev/docker/customizing.md +# @see https://github.com/pixelfed/pixelfed/blob/dev/docker/customizing.md +# @dottie/validate required #DOCKER_APP_PHP_EXTENSIONS_EXTRA="" +# @default "128M" +# @see https://www.php.net/manual/en/ini.core.php#ini.memory-limit +# @dottie/validate required +#DOCKER_APP_PHP_MEMORY_LIMIT="128M" + ################################################################################ -# Docker [redis] service configuration +# docker redis ################################################################################ # Redis version to use as Docker tag # -# See: https://hub.docker.com/_/redis +# @see https://hub.docker.com/_/redis +# @dottie/validate required DOCKER_REDIS_VERSION="7.2" # Path (on host system) where the [redis] container will store its data # # Path is relative (./some/other/path) to the docker-compose.yml or absolute (/some/other/path) -DOCKER_REDIS_HOST_DATA_PATH="${DOCKER_ALL_HOST_DATA_ROOT_PATH}/redis" +# @dottie/validate required,dir +DOCKER_REDIS_HOST_DATA_PATH="${DOCKER_ALL_HOST_DATA_ROOT_PATH:?error}/redis" # Port that Redis will listen on *outside* the container (e.g. the host machine) -DOCKER_REDIS_HOST_PORT="${REDIS_PORT}" +# @dottie/validate required,number +DOCKER_REDIS_HOST_PORT="${REDIS_PORT:?error}" # The filename that Redis should store its config file within # @@ -1055,121 +1087,131 @@ DOCKER_REDIS_HOST_PORT="${REDIS_PORT}" # # Use a command like [touch "${DOCKER_ALL_HOST_CONFIG_ROOT_PATH}/redis/redis.conf"] to create it. # -# Defaults to "" +# @default "" +# @dottie/validate required #DOCKER_REDIS_CONFIG_FILE="/etc/redis/redis.conf" # How often Docker health check should run for [redis] service # -# Defaults to "10s" -DOCKER_REDIS_HEALTHCHECK_INTERVAL="${DOCKER_ALL_DEFAULT_HEALTHCHECK_INTERVAL}" +# @default "10s" +# @dottie/validate required +DOCKER_REDIS_HEALTHCHECK_INTERVAL="${DOCKER_ALL_DEFAULT_HEALTHCHECK_INTERVAL:?error}" ################################################################################ -# Docker [db] service configuration +# docker db ################################################################################ +# Docker image for the DB service +# @dottie/validate required +DOCKER_DB_IMAGE="mariadb:${DB_VERSION}" + +# Command to pass to the [db] server container +# @dottie/validate required +DOCKER_DB_COMMAND="--default-authentication-plugin=mysql_native_password" + # Set this to a non-empty value (e.g. "disabled") to disable the [db] service #DOCKER_DB_PROFILE="" # Path (on host system) where the [db] container will store its data # # Path is relative (./some/other/path) to the docker-compose.yml or absolute (/some/other/path) -DOCKER_DB_HOST_DATA_PATH="${DOCKER_ALL_HOST_DATA_ROOT_PATH}/db" +# @dottie/validate required,dir +DOCKER_DB_HOST_DATA_PATH="${DOCKER_ALL_HOST_DATA_ROOT_PATH:?error}/db" -# Port that the database will listen on *outside* the container (e.g. the host machine) +# Path (inside the container) where the [db] will store its data. +# +# Path MUST be absolute. +# +# For MySQL this should be [/var/lib/mysql] +# For PostgreSQL this should be [/var/lib/postgresql/data] +# @dottie/validate required +DOCKER_DB_CONTAINER_DATA_PATH="/var/lib/mysql" + +# Port that the database will listen on *OUTSIDE* the container (e.g. the host machine) # # Use "3306" for MySQL/MariaDB and "5432" for PostgreeSQL -DOCKER_DB_HOST_PORT="${DB_PORT}" +# @dottie/validate required,number +DOCKER_DB_HOST_PORT="${DB_PORT:?error}" + +# Port that the database will listen on *INSIDE* the container +# +# Use "3306" for MySQL/MariaDB and "5432" for PostgreeSQL +# @dottie/validate required,number +DOCKER_DB_CONTAINER_PORT="${DB_PORT:?error}" # How often Docker health check should run for [db] service -DOCKER_DB_HEALTHCHECK_INTERVAL="${DOCKER_ALL_DEFAULT_HEALTHCHECK_INTERVAL}" +# @dottie/validate required +DOCKER_DB_HEALTHCHECK_INTERVAL="${DOCKER_ALL_DEFAULT_HEALTHCHECK_INTERVAL:?error}" ################################################################################ -# Docker [web] service configuration +# docker web ################################################################################ # Set this to a non-empty value (e.g. "disabled") to disable the [web] service +# @dottie/validate required #DOCKER_WEB_PROFILE="" # Port to expose [web] container will listen on *outside* the container (e.g. the host machine) for *HTTP* traffic only +# @dottie/validate required,number DOCKER_WEB_PORT_EXTERNAL_HTTP="8080" # How often Docker health check should run for [web] service -DOCKER_WEB_HEALTHCHECK_INTERVAL="${DOCKER_ALL_DEFAULT_HEALTHCHECK_INTERVAL}" +# @dottie/validate required +DOCKER_WEB_HEALTHCHECK_INTERVAL="${DOCKER_ALL_DEFAULT_HEALTHCHECK_INTERVAL:?error}" ################################################################################ -# Docker [worker] service configuration +# docker worker ################################################################################ # Set this to a non-empty value (e.g. "disabled") to disable the [worker] service +# @dottie/validate required #DOCKER_WORKER_PROFILE="" # How often Docker health check should run for [worker] service -DOCKER_WORKER_HEALTHCHECK_INTERVAL="${DOCKER_ALL_DEFAULT_HEALTHCHECK_INTERVAL}" +# @dottie/validate required +DOCKER_WORKER_HEALTHCHECK_INTERVAL="${DOCKER_ALL_DEFAULT_HEALTHCHECK_INTERVAL:?error}" ################################################################################ -# Docker [proxy] + [proxy-acme] service configuration +# docker proxy ################################################################################ +# The version of nginx-proxy to use +# +# @see https://hub.docker.com/r/nginxproxy/nginx-proxy +# @dottie/validate required +DOCKER_PROXY_VERSION="1.4" + # Set this to a non-empty value (e.g. "disabled") to disable the [proxy] and [proxy-acme] service -DOCKER_PROXY_PROFILE="" +#DOCKER_PROXY_PROFILE= # Set this to a non-empty value (e.g. "disabled") to disable the [proxy-acme] service -DOCKER_PROXY_ACME_PROFILE="${DOCKER_PROXY_PROFILE}" +#DOCKER_PROXY_ACME_PROFILE="${DOCKER_PROXY_PROFILE?error}" # How often Docker health check should run for [proxy] service -DOCKER_PROXY_HEALTHCHECK_INTERVAL="${DOCKER_ALL_DEFAULT_HEALTHCHECK_INTERVAL}" +# @dottie/validate required +DOCKER_PROXY_HEALTHCHECK_INTERVAL="${DOCKER_ALL_DEFAULT_HEALTHCHECK_INTERVAL:?error}" # Port that the [proxy] will listen on *outside* the container (e.g. the host machine) for HTTP traffic +# @dottie/validate required,number DOCKER_PROXY_HOST_PORT_HTTP="80" # Port that the [proxy] will listen on *outside* the container (e.g. the host machine) for HTTPS traffic +# @dottie/validate required,number DOCKER_PROXY_HOST_PORT_HTTPS="443" # Path to the Docker socket on the *host* +# @dottie/validate required,file DOCKER_PROXY_HOST_DOCKER_SOCKET_PATH="/var/run/docker.sock" -# ! ---------------------------------------------------------------------------- -# ! STOP STOP STOP STOP STOP STOP STOP STOP STOP STOP STOP STOP STOP STOP STOP -# ! ---------------------------------------------------------------------------- -# ! Below this line is default environment variables for various [db] backends -# ! You very likely do *NOT* need to modify any of this, ever. -# ! ---------------------------------------------------------------------------- +# The host to request LetsEncrypt certificate for +# @dottie/validate required,fqdn +DOCKER_PROXY_LETSENCRYPT_HOST="${APP_DOMAIN}" -################################################################################ -# Docker [db] service environment variables for MySQL (Oracle) -################################################################################ -# -# See "Environment Variables" at https://hub.docker.com/_/mysql -# -# ! DO NOT CHANGE unless you know what you are doing +# The e-mail to use for Lets Encrypt certificate requests. +# @dottie/validate required,email +DOCKER_PROXY_LETSENCRYPT_EMAIL="${INSTANCE_CONTACT_EMAIL:?error}" -MYSQL_ROOT_PASSWORD="${DB_PASSWORD}" -MYSQL_USER="${DB_USERNAME}" -MYSQL_PASSWORD="${DB_PASSWORD}" -MYSQL_DATABASE="${DB_DATABASE}" - -################################################################################ -# Docker [db] service environment variables for MySQL (MariaDB) -################################################################################ +# Lets Encrypt staging/test servers for certificate requests. # -# See "Start a mariadb server instance with user, password and database" -# at https://hub.docker.com/_/mariadb -# -# ! DO NOT CHANGE unless you know what you are doing - -MARIADB_ROOT_PASSWORD="${DB_PASSWORD}" -MARIADB_USER="${DB_USERNAME}" -MARIADB_PASSWORD="${DB_PASSWORD}" -MARIADB_DATABASE="${DB_DATABASE}" - -################################################################################ -# Docker [db] service environment variables for PostgreSQL -################################################################################ -# -# See "Environment Variables" at https://hub.docker.com/_/postgres -# -# ! DO NOT CHANGE unless you know what you are doing - -POSTGRES_USER="${DB_USERNAME}" -POSTGRES_PASSWORD="${DB_PASSWORD}" -POSTGRES_DB="${DB_DATABASE}" +# Setting this to any value will change to letsencrypt test servers. +DOCKER_PROXY_LETSENCRYPT_TEST="1" diff --git a/.env.example b/.env.example deleted file mode 100644 index 0a24d1dc1..000000000 --- a/.env.example +++ /dev/null @@ -1,80 +0,0 @@ -# shellcheck disable=SC2034,SC2148 - -APP_NAME="Pixelfed" -APP_ENV="production" -APP_KEY= -APP_DEBUG="false" - -# Instance Configuration -OPEN_REGISTRATION="false" -ENFORCE_EMAIL_VERIFICATION="false" -PF_MAX_USERS="1000" -OAUTH_ENABLED="true" - -# Media Configuration -PF_OPTIMIZE_IMAGES="true" -IMAGE_QUALITY="80" -MAX_PHOTO_SIZE="15000" -MAX_CAPTION_LENGTH="500" -MAX_ALBUM_LENGTH="4" - -# Instance URL Configuration -APP_URL="http://localhost" -APP_DOMAIN="localhost" -ADMIN_DOMAIN="localhost" -SESSION_DOMAIN="localhost" -TRUST_PROXIES="*" - -# Database Configuration -DB_CONNECTION="mysql" -DB_HOST="127.0.0.1" -DB_PORT="3306" -DB_DATABASE="pixelfed" -DB_USERNAME="pixelfed" -DB_PASSWORD="pixelfed" - -# Redis Configuration -REDIS_CLIENT="predis" -REDIS_SCHEME="tcp" -REDIS_HOST="127.0.0.1" -REDIS_PASSWORD="null" -REDIS_PORT="6379" - -# Laravel Configuration -SESSION_DRIVER="database" -CACHE_DRIVER="redis" -QUEUE_DRIVER="redis" -BROADCAST_DRIVER="log" -LOG_CHANNEL="stack" -HORIZON_PREFIX="horizon-" - -# ActivityPub Configuration -ACTIVITY_PUB="false" -AP_REMOTE_FOLLOW="false" -AP_INBOX="false" -AP_OUTBOX="false" -AP_SHAREDINBOX="false" - -# Experimental Configuration -EXP_EMC="true" - -## Mail Configuration (Post-Installer) -MAIL_DRIVER=log -MAIL_HOST=smtp.mailtrap.io -MAIL_PORT=2525 -MAIL_USERNAME=null -MAIL_PASSWORD=null -MAIL_ENCRYPTION=null -MAIL_FROM_ADDRESS="pixelfed@example.com" -MAIL_FROM_NAME="Pixelfed" - -## S3 Configuration (Post-Installer) -PF_ENABLE_CLOUD=false -FILESYSTEM_CLOUD=s3 -#AWS_ACCESS_KEY_ID= -#AWS_SECRET_ACCESS_KEY= -#AWS_DEFAULT_REGION= -#AWS_BUCKET= -#AWS_URL= -#AWS_ENDPOINT= -#AWS_USE_PATH_STYLE_ENDPOINT=false diff --git a/.vscode/settings.json b/.vscode/settings.json index 9a1ddb073..6446fb6f5 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,5 +1,19 @@ { "shellformat.useEditorConfig": true, + "[shellscript]": { + "files.eol": "\n", + "editor.defaultFormatter": "foxundermoon.shell-format" + }, + "[yaml]": { + "editor.defaultFormatter": "redhat.vscode-yaml" + }, + "[dockercompose]": { + "editor.defaultFormatter": "redhat.vscode-yaml", + "editor.autoIndent": "advanced", + }, + "yaml.schemas": { + "https://json.schemastore.org/composer": "https://raw.githubusercontent.com/compose-spec/compose-spec/master/schema/compose-spec.json" + }, "files.associations": { ".env": "shellscript", ".env.*": "shellscript" diff --git a/Dockerfile b/Dockerfile index 1c8a30155..0e8e8a32f 100644 --- a/Dockerfile +++ b/Dockerfile @@ -20,10 +20,8 @@ ARG FOREGO_VERSION="0.17.2" # See: https://github.com/hairyhenderson/gomplate ARG GOMPLATE_VERSION="v3.11.6" -# See: https://github.com/dotenv-linter/dotenv-linter -# -# WARN: v3.3.0 and above requires newer libc version than Ubuntu ships with -ARG DOTENV_LINTER_VERSION="v3.2.0" +# See: https://github.com/jippi/dottie +ARG DOTTIE_VERSION="v0.6.5" ### # PHP base configuration @@ -88,6 +86,13 @@ FROM nginx:${NGINX_VERSION} AS nginx-image # See: https://github.com/nginx-proxy/forego FROM nginxproxy/forego:${FOREGO_VERSION}-debian AS forego-image +# Dottie makes working with .env files easier and safer +# +# NOTE: Docker will *not* pull this image unless it's referenced (via build target) +# +# See: https://github.com/jippi/dottie +FROM ghcr.io/jippi/dottie:${DOTTIE_VERSION} AS dottie-image + # gomplate-image grabs the gomplate binary from GitHub releases # # It's in its own layer so it can be fetched in parallel with other build steps @@ -116,7 +121,6 @@ FROM php:${PHP_VERSION}-${PHP_BASE_TYPE}-${PHP_DEBIAN_RELEASE} AS base ARG BUILDKIT_SBOM_SCAN_STAGE="true" ARG APT_PACKAGES_EXTRA -ARG DOTENV_LINTER_VERSION ARG PHP_DEBIAN_RELEASE ARG PHP_VERSION ARG RUNTIME_GID @@ -135,7 +139,6 @@ RUN set -ex \ WORKDIR /var/www/ ENV APT_PACKAGES_EXTRA=${APT_PACKAGES_EXTRA} -ENV DOTENV_LINTER_VERSION="${DOTENV_LINTER_VERSION}" # Install and configure base layer COPY docker/shared/root/docker/install/base.sh /docker/install/base.sh @@ -226,6 +229,7 @@ ENV RUNTIME_UID=${RUNTIME_UID} ENV RUNTIME_GID=${RUNTIME_GID} COPY --link --from=forego-image /usr/local/bin/forego /usr/local/bin/forego +COPY --link --from=dottie-image /dottie /usr/local/bin/dottie COPY --link --from=gomplate-image /usr/local/bin/gomplate /usr/local/bin/gomplate COPY --link --from=composer-image /usr/bin/composer /usr/bin/composer COPY --link --from=composer-and-src --chown=${RUNTIME_UID}:${RUNTIME_GID} /var/www /var/www diff --git a/docker-compose.yml b/docker-compose.yml index 986bf351b..8b537db14 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -1,5 +1,6 @@ --- -version: "3" +# Require 3.8 to ensure people use a recent version of Docker + Compose +version: "3.8" ############################################################### # Please see docker/README.md for usage information @@ -53,7 +54,7 @@ services: - ${DOCKER_PROXY_ACME_PROFILE:-} environment: DEBUG: 0 - DEFAULT_EMAIL: "${LETSENCRYPT_EMAIL}" + DEFAULT_EMAIL: "${DOCKER_PROXY_LETSENCRYPT_EMAIL:?error}" NGINX_PROXY_CONTAINER: "${DOCKER_ALL_CONTAINER_NAME_PREFIX}-proxy" depends_on: - proxy @@ -74,21 +75,21 @@ services: build: target: ${DOCKER_APP_RUNTIME}-runtime args: - PHP_VERSION: "${DOCKER_APP_PHP_VERSION}" + APT_PACKAGES_EXTRA: "${DOCKER_APP_APT_PACKAGES_EXTRA:-}" PHP_BASE_TYPE: "${DOCKER_APP_BASE_TYPE}" PHP_DEBIAN_RELEASE: "${DOCKER_APP_DEBIAN_RELEASE}" - APT_PACKAGES_EXTRA: "${DOCKER_APP_APT_PACKAGES_EXTRA:-}" - PHP_PECL_EXTENSIONS_EXTRA: "${DOCKER_APP_PHP_PECL_EXTENSIONS_EXTRA:-}" PHP_EXTENSIONS_EXTRA: "${DOCKER_APP_PHP_EXTENSIONS_EXTRA:-}" + PHP_PECL_EXTENSIONS_EXTRA: "${DOCKER_APP_PHP_PECL_EXTENSIONS_EXTRA:-}" + PHP_VERSION: "${DOCKER_APP_PHP_VERSION:?error}" volumes: - "./.env:/var/www/.env" - "${DOCKER_APP_HOST_CACHE_PATH}:/var/www/bootstrap/cache" - "${DOCKER_APP_HOST_STORAGE_PATH}:/var/www/storage" - "${DOCKER_APP_HOST_OVERRIDES_PATH}:/docker/overrides:ro" environment: - LETSENCRYPT_HOST: "${LETSENCRYPT_HOST}" - LETSENCRYPT_EMAIL: "${LETSENCRYPT_EMAIL}" - LETSENCRYPT_TEST: "${LETSENCRYPT_TEST:-}" + LETSENCRYPT_HOST: "${DOCKER_PROXY_LETSENCRYPT_HOST:?error}" + LETSENCRYPT_EMAIL: "${DOCKER_PROXY_LETSENCRYPT_EMAIL:?error}" + LETSENCRYPT_TEST: "${DOCKER_PROXY_LETSENCRYPT_TEST:-}" VIRTUAL_HOST: "${APP_DOMAIN}" VIRTUAL_PORT: "80" labels: @@ -117,12 +118,12 @@ services: build: target: ${DOCKER_APP_RUNTIME}-runtime args: - PHP_VERSION: "${DOCKER_APP_PHP_VERSION}" + APT_PACKAGES_EXTRA: "${DOCKER_APP_APT_PACKAGES_EXTRA:-}" PHP_BASE_TYPE: "${DOCKER_APP_BASE_TYPE}" PHP_DEBIAN_RELEASE: "${DOCKER_APP_DEBIAN_RELEASE}" - APT_PACKAGES_EXTRA: "${DOCKER_APP_APT_PACKAGES_EXTRA:-}" - PHP_PECL_EXTENSIONS_EXTRA: "${DOCKER_APP_PHP_PECL_EXTENSIONS_EXTRA:-}" PHP_EXTENSIONS_EXTRA: "${DOCKER_APP_PHP_EXTENSIONS_EXTRA:-}" + PHP_PECL_EXTENSIONS_EXTRA: "${DOCKER_APP_PHP_PECL_EXTENSIONS_EXTRA:-}" + PHP_VERSION: "${DOCKER_APP_PHP_VERSION:?error}" volumes: - "./.env:/var/www/.env" - "${DOCKER_APP_HOST_CACHE_PATH}:/var/www/bootstrap/cache" @@ -133,23 +134,37 @@ services: - redis healthcheck: test: gosu www-data php artisan horizon:status | grep running - interval: "${DOCKER_WORKER_HEALTHCHECK_INTERVAL}" + interval: "${DOCKER_WORKER_HEALTHCHECK_INTERVAL:?error}" timeout: 5s retries: 2 db: - image: mariadb:${DB_VERSION} + image: ${DOCKER_DB_IMAGE:?error} container_name: "${DOCKER_ALL_CONTAINER_NAME_PREFIX}-db" - command: --default-authentication-plugin=mysql_native_password + command: ${DOCKER_DB_COMMAND:-} restart: unless-stopped profiles: - ${DOCKER_DB_PROFILE:-} - env_file: - - ".env" + environment: + TZ: "${TZ:?error}" + # MySQL (Oracle) - "Environment Variables" at https://hub.docker.com/_/mysql + MYSQL_ROOT_PASSWORD: "${DB_PASSWORD:?error}" + MYSQL_USER: "${DB_USERNAME:?error}" + MYSQL_PASSWORD: "${DB_PASSWORD:?error}" + MYSQL_DATABASE: "${DB_DATABASE:?error}" + # MySQL (MariaDB) - "Start a mariadb server instance with user, password and database" at https://hub.docker.com/_/mariadb + MARIADB_ROOT_PASSWORD: "${DB_PASSWORD:?error}" + MARIADB_USER: "${DB_USERNAME:?error}" + MARIADB_PASSWORD: "${DB_PASSWORD:?error}" + MARIADB_DATABASE: "${DB_DATABASE:?error}" + # PostgreSQL - "Environment Variables" at https://hub.docker.com/_/postgres + POSTGRES_USER: "${DB_USERNAME:?error}" + POSTGRES_PASSWORD: "${DB_PASSWORD:?error}" + POSTGRES_DB: "${DB_DATABASE:?error}" volumes: - - "${DOCKER_DB_HOST_DATA_PATH}:/var/lib/mysql" + - "${DOCKER_DB_HOST_DATA_PATH:?error}:${DOCKER_DB_CONTAINER_DATA_PATH:?error}" ports: - - "${DOCKER_DB_HOST_PORT}:3306" + - "${DOCKER_DB_HOST_PORT:?error}:${DOCKER_DB_CONTAINER_PORT:?error}" healthcheck: test: [ @@ -159,7 +174,7 @@ services: "--connect", "--innodb_initialized", ] - interval: "${DOCKER_DB_HEALTHCHECK_INTERVAL}" + interval: "${DOCKER_DB_HEALTHCHECK_INTERVAL:?error}" retries: 2 timeout: 5s @@ -169,9 +184,8 @@ services: restart: unless-stopped command: "${DOCKER_REDIS_CONFIG_FILE:-} --requirepass '${REDIS_PASSWORD:-}'" environment: - - REDISCLI_AUTH=${REDIS_PASSWORD:-} - env_file: - - ".env" + TZ: "${TZ:?error}" + REDISCLI_AUTH: ${REDIS_PASSWORD:-} volumes: - "${DOCKER_ALL_HOST_CONFIG_ROOT_PATH}/redis:/etc/redis" - "${DOCKER_REDIS_HOST_DATA_PATH}:/data" @@ -179,6 +193,6 @@ services: - "${DOCKER_REDIS_HOST_PORT}:6379" healthcheck: test: ["CMD", "redis-cli", "-p", "6379", "ping"] - interval: "${DOCKER_REDIS_HEALTHCHECK_INTERVAL}" + interval: "${DOCKER_REDIS_HEALTHCHECK_INTERVAL:?error}" retries: 2 timeout: 5s diff --git a/docker/nginx/root/docker/templates/etc/nginx/nginx.conf b/docker/nginx/root/docker/templates/etc/nginx/nginx.conf new file mode 100644 index 000000000..4e87a4565 --- /dev/null +++ b/docker/nginx/root/docker/templates/etc/nginx/nginx.conf @@ -0,0 +1,41 @@ +# This is changed from the original "nginx" in upstream to work properly +# with permissions within pixelfed when serving static files. +user www-data; + +worker_processes auto; + +# Ensure the PID is writable +# Lifted from: https://hub.docker.com/r/nginxinc/nginx-unprivileged +pid /tmp/nginx.pid; + +# Write error log to stderr (/proc/self/fd/2 -> /dev/stderr) +error_log /proc/self/fd/2 notice; + +events { + worker_connections 1024; +} + +http { + include /etc/nginx/mime.types; + default_type application/octet-stream; + + log_format main '$remote_addr - $remote_user [$time_local] "$request" $status $body_bytes_sent "$http_referer" "$http_user_agent" "$http_x_forwarded_for"'; + + # Write error log to stdout (/proc/self/fd/1 -> /dev/stdout) + access_log /proc/self/fd/1 main; + + sendfile on; + tcp_nopush on; + keepalive_timeout 65; + gzip on; + + # Ensure all temp paths are in a writable by "www-data" user. + # Lifted from: https://hub.docker.com/r/nginxinc/nginx-unprivileged + client_body_temp_path /tmp/client_temp; + proxy_temp_path /tmp/proxy_temp_path; + fastcgi_temp_path /tmp/fastcgi_temp; + uwsgi_temp_path /tmp/uwsgi_temp; + scgi_temp_path /tmp/scgi_temp; + + include /etc/nginx/conf.d/*.conf; +} diff --git a/docker/shared/root/docker/entrypoint.d/02-check-config.sh b/docker/shared/root/docker/entrypoint.d/02-check-config.sh index 601cf153e..bbf7dd768 100755 --- a/docker/shared/root/docker/entrypoint.d/02-check-config.sh +++ b/docker/shared/root/docker/entrypoint.d/02-check-config.sh @@ -13,5 +13,9 @@ for file in "${dot_env_files[@]}"; do continue fi - run-as-current-user dotenv-linter --skip=QuoteCharacter --skip=UnorderedKey "${file}" + # We ignore 'dir' + 'file' rules since they are validate *host* paths + # which do not (and should not) exists inside the container + # + # We disable fixer since its not interactive anyway + run-as-current-user dottie validate --file "${file}" --ignore-rule dir,file --no-fix done diff --git a/docker/shared/root/docker/helpers.sh b/docker/shared/root/docker/helpers.sh index 51e955682..190c04bc4 100644 --- a/docker/shared/root/docker/helpers.sh +++ b/docker/shared/root/docker/helpers.sh @@ -20,9 +20,10 @@ declare -g script_name= declare -g script_name_previous= declare -g log_prefix= +declare -Ag lock_fds=() + # dot-env files to source when reading config declare -a dot_env_files=( - /var/www/.env.docker /var/www/.env ) @@ -166,7 +167,7 @@ function log-error() log-error-and-exit "[${FUNCNAME[0]}] did not receive any input arguments and STDIN is empty" fi - echo -e "${error_message_color}${log_prefix}ERROR -${color_clear} ${msg}" > /dev/stderr + echo -e "${error_message_color}${log_prefix}ERROR -${color_clear} ${msg}" >/dev/stderr } # @description Print the given error message to stderr and exit 1 @@ -197,7 +198,7 @@ function log-warning() log-error-and-exit "[${FUNCNAME[0]}] did not receive any input arguments and STDIN is empty" fi - echo -e "${warn_message_color}${log_prefix}WARNING -${color_clear} ${msg}" > /dev/stderr + echo -e "${warn_message_color}${log_prefix}WARNING -${color_clear} ${msg}" >/dev/stderr } # @description Print the given message to stdout unless [ENTRYPOINT_QUIET_LOGS] is set @@ -236,7 +237,7 @@ function log-info-stderr() fi if [ -z "${ENTRYPOINT_QUIET_LOGS:-}" ]; then - echo -e "${notice_message_color}${log_prefix}${color_clear}${msg}" > /dev/stderr + echo -e "${notice_message_color}${log_prefix}${color_clear}${msg}" >/dev/stderr fi } @@ -377,17 +378,20 @@ function acquire-lock() { local name="${1:-$script_name}" local file="${docker_locks_path}/${name}" + local lock_fd ensure-directory-exists "$(dirname "${file}")" + exec {lock_fd}>"$file" + log-info "🔑 Trying to acquire lock: ${file}: " - while file-exists "${file}"; do + while ! ([[ -v lock_fds[$name] ]] || flock -n -x "$lock_fd"); do log-info "🔒 Waiting on lock ${file}" staggered-sleep done - stream-prefix-command-output touch "${file}" + [[ -v lock_fds[$name] ]] || lock_fds[$name]=$lock_fd log-info "🔐 Lock acquired [${file}]" @@ -403,7 +407,11 @@ function release-lock() log-info "🔓 Releasing lock [${file}]" - stream-prefix-command-output rm -fv "${file}" + [[ -v lock_fds[$name] ]] || return + + # shellcheck disable=SC1083,SC2086 + flock --unlock ${lock_fds[$name]} + unset 'lock_fds[$name]' } # @description Helper function to append multiple actions onto @@ -450,14 +458,14 @@ function await-database-ready() case "${DB_CONNECTION:-}" in mysql) # shellcheck disable=SC2154 - while ! echo "SELECT 1" | mysql --user="${DB_USERNAME}" --password="${DB_PASSWORD}" --host="${DB_HOST}" "${DB_DATABASE}" --silent > /dev/null; do + while ! echo "SELECT 1" | mysql --user="${DB_USERNAME}" --password="${DB_PASSWORD}" --host="${DB_HOST}" "${DB_DATABASE}" --silent >/dev/null; do staggered-sleep done ;; pgsql) # shellcheck disable=SC2154 - while ! echo "SELECT 1" | PGPASSWORD="${DB_PASSWORD}" psql --user="${DB_USERNAME}" --host="${DB_HOST}" "${DB_DATABASE}" > /dev/null; do + while ! echo "SELECT 1" | PGPASSWORD="${DB_PASSWORD}" psql --user="${DB_USERNAME}" --host="${DB_HOST}" "${DB_DATABASE}" >/dev/null; do staggered-sleep done ;; diff --git a/docker/shared/root/docker/install/base.sh b/docker/shared/root/docker/install/base.sh index 4e97e82bb..a1a32a003 100755 --- a/docker/shared/root/docker/install/base.sh +++ b/docker/shared/root/docker/install/base.sh @@ -59,6 +59,3 @@ apt-get install -y "${packages[@]}" locale-gen update-locale - -# Install dotenv linter (https://github.com/dotenv-linter/dotenv-linter) -curl -sSfL https://raw.githubusercontent.com/dotenv-linter/dotenv-linter/master/install.sh | sh -s -- -b /usr/local/bin "${DOTENV_LINTER_VERSION:-}" diff --git a/docker/shared/root/docker/templates/usr/local/etc/php/php.ini b/docker/shared/root/docker/templates/usr/local/etc/php/php.ini index 6277ec080..0ca96819b 100644 --- a/docker/shared/root/docker/templates/usr/local/etc/php/php.ini +++ b/docker/shared/root/docker/templates/usr/local/etc/php/php.ini @@ -406,7 +406,7 @@ max_input_time = 60 ; Maximum amount of memory a script may consume (128MB) ; http://php.net/memory-limit -memory_limit = {{ getenv "PHP_MEMORY_LIMIT" "128M" }} +memory_limit = {{ getenv "DOCKER_APP_PHP_MEMORY_LIMIT" "128M" }} ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; Error handling and logging ; @@ -570,8 +570,9 @@ report_memleaks = On ; Log errors to specified file. PHP's default behavior is to leave this value ; empty. ; http://php.net/error-log -; Example: -;error_log = php_errors.log +; +; NOTE: Write error log to stderr (/proc/self/fd/2 -> /dev/stderr) +error_log = /proc/self/fd/2 ; Log errors to syslog (Event Log on Windows). ;error_log = syslog diff --git a/goss.yaml b/goss.yaml index f558f788a..73f245c64 100644 --- a/goss.yaml +++ b/goss.yaml @@ -114,7 +114,7 @@ command: {{ end }} {{ if eq .Env.PHP_BASE_TYPE "apache" }} - nginx-version: + apache-version: exit-status: 0 exec: 'apachectl -v' stdout: From 143d5703dd7bb0e847e56a9c52a271bad14ba513 Mon Sep 17 00:00:00 2001 From: Christian Winther Date: Sat, 10 Feb 2024 23:08:22 +0000 Subject: [PATCH 136/173] update .env.docker --- .env.docker | 40 ++++++++++++++++++++++++---------------- Dockerfile | 2 +- 2 files changed, 25 insertions(+), 17 deletions(-) diff --git a/.env.docker b/.env.docker index 0fa9e1428..1158cace4 100644 --- a/.env.docker +++ b/.env.docker @@ -12,15 +12,16 @@ # app ################################################################################ +# The name/title for your site # @see https://docs.pixelfed.org/technical-documentation/config/#app_name-1 -# @dottie/validate required -APP_NAME="Pixelfed Prod" +# @dottie/validate required,ne=My Pixelfed Site +APP_NAME="My Pixelfed Site" -# Application domains used for routing. +# Application domain used for routing. (e.g., pixelfed.org) # # @see https://docs.pixelfed.org/technical-documentation/config/#app_domain -# @dottie/validate required,fqdn -APP_DOMAIN="__CHANGE_ME__" +# @dottie/validate required,ne=example.com,fqdn +APP_DOMAIN="example.com" # This URL is used by the console to properly generate URLs when using the Artisan command line tool. # You should set this to the root of your application so that it is used when running Artisan tasks. @@ -208,10 +209,12 @@ APP_TIMEZONE="UTC" # @dottie/validate required,boolean #INSTANCE_PUBLIC_HASHTAGS="false" +# The public e-mail address people can use to contact you by +# # @default "" # @see https://docs.pixelfed.org/technical-documentation/config/#instance_contact_email -# @dottie/validate required,email -INSTANCE_CONTACT_EMAIL="admin@${APP_DOMAIN}" +# @dottie/validate required,ne=__CHANGE_ME__,email +INSTANCE_CONTACT_EMAIL="__CHANGE_ME__" # @default "false" # @see https://docs.pixelfed.org/technical-documentation/config/#instance_public_local_timeline @@ -237,7 +240,7 @@ INSTANCE_CONTACT_EMAIL="admin@${APP_DOMAIN}" # @default false # @see https://docs.pixelfed.org/technical-documentation/config/#media_exif_database # @dottie/validate required,boolean -MEDIA_EXIF_DATABASE="true" +#MEDIA_EXIF_DATABASE="false" # Pixelfed supports GD or ImageMagick to process images. # @@ -357,9 +360,12 @@ DB_HOST="db" # @dottie/validate required DB_USERNAME="pixelfed" +# The password to your database. Please make it secure. +# Use a site like https://pwgen.io/ to generate it +# # @see https://docs.pixelfed.org/technical-documentation/config/#db_password -# @dottie/validate required -DB_PASSWORD= +# @dottie/validate required,ne=__CHANGE_ME__ +DB_PASSWORD="__CHANGE_ME__" # @see https://docs.pixelfed.org/technical-documentation/config/#db_database # @dottie/validate required @@ -416,19 +422,21 @@ DB_APPLY_NEW_MIGRATIONS_AUTOMATICALLY="false" # @dottie/validate required_with=MAIL_DRIVER,number #MAIL_PORT="587" -# You may wish for all e-mails sent by your application to be sent from the same address. -# # Here, you may specify a name and address that is used globally for all e-mails that are sent by your application. # -# @default "hello@example.com" +# You may wish for all e-mails sent by your application to be sent from the same address. +# +# @default "bot@example.com" # @see https://docs.pixelfed.org/technical-documentation/config/#mail_from_address -# @dottie/validate required_with=MAIL_DRIVER,email -MAIL_FROM_ADDRESS="hello@${APP_DOMAIN}" +# @dottie/validate required_with=MAIL_DRIVER,email,ne=__CHANGE_ME__ +#MAIL_FROM_ADDRESS="__CHANGE_ME__" +# The 'name' you send e-mail from +# # @default "Example" # @see https://docs.pixelfed.org/technical-documentation/config/#mail_from_name # @dottie/validate required_with=MAIL_DRIVER -MAIL_FROM_NAME="Pixelfed @ ${APP_DOMAIN}" +#MAIL_FROM_NAME="${APP_NAME}" # If your SMTP server requires a username for authentication, you should set it here. # diff --git a/Dockerfile b/Dockerfile index 0e8e8a32f..efbe70510 100644 --- a/Dockerfile +++ b/Dockerfile @@ -21,7 +21,7 @@ ARG FOREGO_VERSION="0.17.2" ARG GOMPLATE_VERSION="v3.11.6" # See: https://github.com/jippi/dottie -ARG DOTTIE_VERSION="v0.6.5" +ARG DOTTIE_VERSION="v0.6.9" ### # PHP base configuration From e18d6083a209d5c17d87c6bcb19fb4cc6b9c8434 Mon Sep 17 00:00:00 2001 From: Christian Winther Date: Sun, 11 Feb 2024 01:24:26 +0000 Subject: [PATCH 137/173] bump dottie --- .env.docker | 8 ++++++-- .gitignore | 1 + Dockerfile | 2 +- 3 files changed, 8 insertions(+), 3 deletions(-) diff --git a/.env.docker b/.env.docker index 1158cace4..2b1ab66a6 100644 --- a/.env.docker +++ b/.env.docker @@ -1,12 +1,16 @@ #!/bin/bash # -*- mode: bash -*- # vi: ft=bash +# shellcheck disable=SC2034,SC2148 # Use Dottie (https://github.com/jippi/dottie) to manage this .env file easier! # -# @dottie/source .env.docker +# For example: # -# shellcheck disable=SC2034,SC2148 +# Run [dottie update] to update your [.env] file with upstream (as part of upgrade) +# Run [dottie validate] to validate youe [.env] file +# +# @dottie/source .env.docker ################################################################################ # app diff --git a/.gitignore b/.gitignore index 689c2e13a..f83ec13c4 100644 --- a/.gitignore +++ b/.gitignore @@ -3,6 +3,7 @@ .bashrc .DS_Store .env +.env.dottie-backup .git-credentials .gitconfig /.composer/ diff --git a/Dockerfile b/Dockerfile index efbe70510..5b6f45426 100644 --- a/Dockerfile +++ b/Dockerfile @@ -21,7 +21,7 @@ ARG FOREGO_VERSION="0.17.2" ARG GOMPLATE_VERSION="v3.11.6" # See: https://github.com/jippi/dottie -ARG DOTTIE_VERSION="v0.6.9" +ARG DOTTIE_VERSION="v0.7.0" ### # PHP base configuration From fd62962d201f7bb052b1eeaac0182de313d1d3b6 Mon Sep 17 00:00:00 2001 From: Christian Winther Date: Sun, 11 Feb 2024 01:57:11 +0000 Subject: [PATCH 138/173] delete contrib --- contrib/docker-nginx.conf | 35 -------------------- contrib/nginx.conf | 67 --------------------------------------- 2 files changed, 102 deletions(-) delete mode 100644 contrib/docker-nginx.conf delete mode 100644 contrib/nginx.conf diff --git a/contrib/docker-nginx.conf b/contrib/docker-nginx.conf deleted file mode 100644 index 9d0a199e6..000000000 --- a/contrib/docker-nginx.conf +++ /dev/null @@ -1,35 +0,0 @@ -upstream fe { - server 127.0.0.1:8080; -} - -server { - server_name real.domain; - listen [::]:443 ssl ipv6only=on; - listen 443 ssl; - ssl_certificate /etc/letsencrypt/live/real.domain/fullchain.pem; # managed by Certbot - ssl_certificate_key /etc/letsencrypt/live/real.domain/privkey.pem; # managed by Certbot - include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot - ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot - - location / { - proxy_set_header Host $host; - proxy_set_header X-Real-IP $remote_addr; - proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; - proxy_set_header X-Forwarded-Proto $scheme; - proxy_set_header X-Forwarded-Host $http_x_forwarded_host; - proxy_set_header X-Forwarded-Port $http_x_forwarded_port; - proxy_redirect off; - proxy_pass http://fe/; - } -} - -server { - if ($host = real.domain) { - return 301 https://$host$request_uri; - } - - listen 80; - listen [::]:80; - server_name real.domain; - return 404; -} \ No newline at end of file diff --git a/contrib/nginx.conf b/contrib/nginx.conf deleted file mode 100644 index 0f86ea9e7..000000000 --- a/contrib/nginx.conf +++ /dev/null @@ -1,67 +0,0 @@ -server { - listen 443 ssl http2; - listen [::]:443 ssl http2; - server_name pixelfed.example; # change this to your fqdn - root /home/pixelfed/public; # path to repo/public - - ssl_certificate /etc/nginx/ssl/server.crt; # generate your own - ssl_certificate_key /etc/nginx/ssl/server.key; # or use letsencrypt - - ssl_protocols TLSv1.2; - ssl_ciphers EECDH+AESGCM:EECDH+CHACHA20:EECDH+AES; - ssl_prefer_server_ciphers on; - - #add_header X-Frame-Options "SAMEORIGIN"; - add_header X-XSS-Protection "1; mode=block"; - add_header X-Content-Type-Options "nosniff"; - - index index.php; - - charset utf-8; - client_max_body_size 15M; - - location / { - try_files $uri $uri/ /index.php?$query_string; - } - - location = /favicon.ico { access_log off; log_not_found off; } - location = /robots.txt { access_log off; log_not_found off; } - - error_page 404 /index.php; - - location ~ \.php$ { - fastcgi_split_path_info ^(.+\.php)(/.+)$; - fastcgi_pass unix:/var/run/php/php8.1-fpm.sock; - fastcgi_param SCRIPT_FILENAME $realpath_root$fastcgi_script_name; - fastcgi_param QUERY_STRING $query_string; - fastcgi_param REQUEST_METHOD $request_method; - fastcgi_param CONTENT_TYPE $content_type; - fastcgi_param CONTENT_LENGTH $content_length; - fastcgi_param SCRIPT_NAME $fastcgi_script_name; - fastcgi_param REQUEST_URI $request_uri; - fastcgi_param DOCUMENT_URI $document_uri; - fastcgi_param DOCUMENT_ROOT $document_root; - fastcgi_param SERVER_PROTOCOL $server_protocol; - fastcgi_param GATEWAY_INTERFACE CGI/1.1; - fastcgi_param SERVER_SOFTWARE nginx/$nginx_version; - fastcgi_param REMOTE_ADDR $remote_addr; - fastcgi_param REMOTE_PORT $remote_port; - fastcgi_param SERVER_ADDR $server_addr; - fastcgi_param SERVER_PORT $server_port; - fastcgi_param SERVER_NAME $server_name; - fastcgi_param HTTPS $https if_not_empty; - fastcgi_param REDIRECT_STATUS 200; - fastcgi_param HTTP_PROXY ""; - } - - location ~ /\.(?!well-known).* { - deny all; - } -} - -server { # Redirect http to https - server_name pixelfed.example; # change this to your fqdn - listen 80; - listen [::]:80; - return 301 https://$host$request_uri; -} From 49a778d12889931af77612d6fe0242231cb7a17c Mon Sep 17 00:00:00 2001 From: Christian Winther Date: Sun, 11 Feb 2024 02:00:09 +0000 Subject: [PATCH 139/173] add CODEOWNERS --- .env.docker | 11 +++++++---- CODEOWNERS | 18 ++++++++++++++++++ Dockerfile | 2 +- .../docker/entrypoint.d/02-check-config.sh | 2 +- 4 files changed, 27 insertions(+), 6 deletions(-) create mode 100644 CODEOWNERS diff --git a/.env.docker b/.env.docker index 2b1ab66a6..9a27550d1 100644 --- a/.env.docker +++ b/.env.docker @@ -18,12 +18,14 @@ # The name/title for your site # @see https://docs.pixelfed.org/technical-documentation/config/#app_name-1 +# @dottie/example My Pixelfed Site # @dottie/validate required,ne=My Pixelfed Site -APP_NAME="My Pixelfed Site" +APP_NAME= # Application domain used for routing. (e.g., pixelfed.org) # # @see https://docs.pixelfed.org/technical-documentation/config/#app_domain +# @dottie/example example.com # @dottie/validate required,ne=example.com,fqdn APP_DOMAIN="example.com" @@ -368,8 +370,8 @@ DB_USERNAME="pixelfed" # Use a site like https://pwgen.io/ to generate it # # @see https://docs.pixelfed.org/technical-documentation/config/#db_password -# @dottie/validate required,ne=__CHANGE_ME__ -DB_PASSWORD="__CHANGE_ME__" +# @dottie/validate required +DB_PASSWORD= # @see https://docs.pixelfed.org/technical-documentation/config/#db_database # @dottie/validate required @@ -890,6 +892,7 @@ SESSION_DRIVER="redis" # 32 character string, otherwise these encrypted strings will not be safe. # # @see https://docs.pixelfed.org/technical-documentation/config/#app_key +# @dottie/validate required APP_KEY= # Prefix for container names (without any dash at the end) @@ -1226,4 +1229,4 @@ DOCKER_PROXY_LETSENCRYPT_EMAIL="${INSTANCE_CONTACT_EMAIL:?error}" # Lets Encrypt staging/test servers for certificate requests. # # Setting this to any value will change to letsencrypt test servers. -DOCKER_PROXY_LETSENCRYPT_TEST="1" +#DOCKER_PROXY_LETSENCRYPT_TEST="1" diff --git a/CODEOWNERS b/CODEOWNERS new file mode 100644 index 000000000..69a06cf87 --- /dev/null +++ b/CODEOWNERS @@ -0,0 +1,18 @@ +# See: https://docs.github.com/en/repositories/managing-your-repositorys-settings-and-features/customizing-your-repository/about-code-owners + +# These owners will be the default owners for everything in +# the repo. Unless a later match takes precedence, +* @dansup + +# Docker related files +.editorconfig @jippi @dansup +.env @jippi @dansup +.env.* @jippi @dansup +.hadolint.yaml @jippi @dansup +.shellcheckrc @jippi @dansup +/.github/ @jippi @dansup +/docker/ @jippi @dansup +/tests/ @jippi @dansup +docker-compose.migrate.yml @jippi @dansup +docker-compose.yml @jippi @dansup +goss.yaml @jippi @dansup diff --git a/Dockerfile b/Dockerfile index 5b6f45426..77bb1da62 100644 --- a/Dockerfile +++ b/Dockerfile @@ -21,7 +21,7 @@ ARG FOREGO_VERSION="0.17.2" ARG GOMPLATE_VERSION="v3.11.6" # See: https://github.com/jippi/dottie -ARG DOTTIE_VERSION="v0.7.0" +ARG DOTTIE_VERSION="v0.7.1" ### # PHP base configuration diff --git a/docker/shared/root/docker/entrypoint.d/02-check-config.sh b/docker/shared/root/docker/entrypoint.d/02-check-config.sh index bbf7dd768..627960352 100755 --- a/docker/shared/root/docker/entrypoint.d/02-check-config.sh +++ b/docker/shared/root/docker/entrypoint.d/02-check-config.sh @@ -17,5 +17,5 @@ for file in "${dot_env_files[@]}"; do # which do not (and should not) exists inside the container # # We disable fixer since its not interactive anyway - run-as-current-user dottie validate --file "${file}" --ignore-rule dir,file --no-fix + run-as-current-user dottie validate --file "${file}" --ignore-rule dir,file --exclude-prefix APP_KEY --no-fix done From 6edd71258196ce929acaa11c5741aba2fba93461 Mon Sep 17 00:00:00 2001 From: Christian Winther Date: Sat, 17 Feb 2024 01:19:59 +0000 Subject: [PATCH 140/173] bump dottie --- Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index 77bb1da62..e82de9d45 100644 --- a/Dockerfile +++ b/Dockerfile @@ -21,7 +21,7 @@ ARG FOREGO_VERSION="0.17.2" ARG GOMPLATE_VERSION="v3.11.6" # See: https://github.com/jippi/dottie -ARG DOTTIE_VERSION="v0.7.1" +ARG DOTTIE_VERSION="v0.8.0" ### # PHP base configuration From 9a1c4d42b5f528aef09486ddca906815ef84ba55 Mon Sep 17 00:00:00 2001 From: Christian Winther Date: Sat, 17 Feb 2024 01:23:12 +0000 Subject: [PATCH 141/173] drop php 8.1 support --- .github/workflows/docker.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.github/workflows/docker.yml b/.github/workflows/docker.yml index ea119bec3..9a451937c 100644 --- a/.github/workflows/docker.yml +++ b/.github/workflows/docker.yml @@ -70,7 +70,6 @@ jobs: # See: https://docs.github.com/en/actions/using-jobs/using-a-matrix-for-your-jobs matrix: php_version: - - 8.1 - 8.2 - 8.3 target_runtime: From 4dc15bb37d161695e46d12dc9c6600d6f01940f1 Mon Sep 17 00:00:00 2001 From: Christian Winther Date: Mon, 19 Feb 2024 00:48:36 +0000 Subject: [PATCH 142/173] fix validation --- .env.docker | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.env.docker b/.env.docker index 9a27550d1..fb15956b4 100644 --- a/.env.docker +++ b/.env.docker @@ -819,7 +819,7 @@ SESSION_DRIVER="redis" # # @default the value of APP_DOMAIN, or null. # @see https://docs.pixelfed.org/technical-documentation/config/#session_domain -# @dottie/validate required,domain +# @dottie/validate required,hostname #SESSION_DOMAIN="${APP_DOMAIN}" ################################################################################ From 9117df186c3a1c3bcd6e96941c5a668f559d1195 Mon Sep 17 00:00:00 2001 From: Christian Winther Date: Mon, 19 Feb 2024 00:52:12 +0000 Subject: [PATCH 143/173] more validation fixes --- .env.docker | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.env.docker b/.env.docker index fb15956b4..a38c6b61c 100644 --- a/.env.docker +++ b/.env.docker @@ -47,7 +47,7 @@ ADMIN_DOMAIN="${APP_DOMAIN}" # # @default "production" # @see https://docs.pixelfed.org/technical-documentation/config/#app_env -# @dottie/validate required,oneof='production,dev,staging' +# @dottie/validate required,oneof=production dev staging #APP_ENV="production" # When your application is in debug mode, detailed error messages with stack traces will From abee7d4d620f11e4c70d13a2ec9de0d20782d9a0 Mon Sep 17 00:00:00 2001 From: Christian Winther Date: Wed, 21 Feb 2024 21:52:59 +0000 Subject: [PATCH 144/173] add missing profiles --- .env.docker | 22 ++++++++++++---------- docker-compose.yml | 4 +++- 2 files changed, 15 insertions(+), 11 deletions(-) diff --git a/.env.docker b/.env.docker index a38c6b61c..2368e85d6 100644 --- a/.env.docker +++ b/.env.docker @@ -1080,6 +1080,9 @@ DOCKER_APP_HOST_CACHE_PATH="${DOCKER_ALL_HOST_DATA_ROOT_PATH:?error}/pixelfed/ca # docker redis ################################################################################ +# Set this to a non-empty value (e.g. "disabled") to disable the [redis] service +#DOCKER_REDIS_PROFILE= + # Redis version to use as Docker tag # # @see https://hub.docker.com/_/redis @@ -1105,7 +1108,6 @@ DOCKER_REDIS_HOST_PORT="${REDIS_PORT:?error}" # @default "" # @dottie/validate required #DOCKER_REDIS_CONFIG_FILE="/etc/redis/redis.conf" - # How often Docker health check should run for [redis] service # # @default "10s" @@ -1116,6 +1118,9 @@ DOCKER_REDIS_HEALTHCHECK_INTERVAL="${DOCKER_ALL_DEFAULT_HEALTHCHECK_INTERVAL:?er # docker db ################################################################################ +# Set this to a non-empty value (e.g. "disabled") to disable the [db] service +#DOCKER_DB_PROFILE= + # Docker image for the DB service # @dottie/validate required DOCKER_DB_IMAGE="mariadb:${DB_VERSION}" @@ -1124,9 +1129,6 @@ DOCKER_DB_IMAGE="mariadb:${DB_VERSION}" # @dottie/validate required DOCKER_DB_COMMAND="--default-authentication-plugin=mysql_native_password" -# Set this to a non-empty value (e.g. "disabled") to disable the [db] service -#DOCKER_DB_PROFILE="" - # Path (on host system) where the [db] container will store its data # # Path is relative (./some/other/path) to the docker-compose.yml or absolute (/some/other/path) @@ -1190,18 +1192,18 @@ DOCKER_WORKER_HEALTHCHECK_INTERVAL="${DOCKER_ALL_DEFAULT_HEALTHCHECK_INTERVAL:?e # docker proxy ################################################################################ -# The version of nginx-proxy to use -# -# @see https://hub.docker.com/r/nginxproxy/nginx-proxy -# @dottie/validate required -DOCKER_PROXY_VERSION="1.4" - # Set this to a non-empty value (e.g. "disabled") to disable the [proxy] and [proxy-acme] service #DOCKER_PROXY_PROFILE= # Set this to a non-empty value (e.g. "disabled") to disable the [proxy-acme] service #DOCKER_PROXY_ACME_PROFILE="${DOCKER_PROXY_PROFILE?error}" +# The version of nginx-proxy to use +# +# @see https://hub.docker.com/r/nginxproxy/nginx-proxy +# @dottie/validate required +DOCKER_PROXY_VERSION="1.4" + # How often Docker health check should run for [proxy] service # @dottie/validate required DOCKER_PROXY_HEALTHCHECK_INTERVAL="${DOCKER_ALL_DEFAULT_HEALTHCHECK_INTERVAL:?error}" diff --git a/docker-compose.yml b/docker-compose.yml index 8b537db14..77e184c2c 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -112,9 +112,9 @@ services: container_name: "${DOCKER_ALL_CONTAINER_NAME_PREFIX}-worker" command: gosu www-data php artisan horizon restart: unless-stopped - stop_signal: SIGTERM profiles: - ${DOCKER_WORKER_PROFILE:-} + stop_signal: SIGTERM build: target: ${DOCKER_APP_RUNTIME}-runtime args: @@ -182,6 +182,8 @@ services: image: redis:${DOCKER_REDIS_VERSION} container_name: "${DOCKER_ALL_CONTAINER_NAME_PREFIX}-redis" restart: unless-stopped + profiles: + - ${DOCKER_REDIS_PROFILE:-} command: "${DOCKER_REDIS_CONFIG_FILE:-} --requirepass '${REDIS_PASSWORD:-}'" environment: TZ: "${TZ:?error}" From adf1af3703cc51fe38bbda85ea74baba41f0d2f9 Mon Sep 17 00:00:00 2001 From: Christian Winther Date: Wed, 21 Feb 2024 22:15:41 +0000 Subject: [PATCH 145/173] add small bash/artisan helper commands --- docker/artisan | 6 ++++++ docker/bash | 12 ++++++++++++ 2 files changed, 18 insertions(+) create mode 100755 docker/artisan create mode 100755 docker/bash diff --git a/docker/artisan b/docker/artisan new file mode 100755 index 000000000..d50d65244 --- /dev/null +++ b/docker/artisan @@ -0,0 +1,6 @@ +#!/bin/bash + +declare service="${PF_SERVICE:=worker}" +declare user="${PF_USER:=www-data}" + +exec docker compose exec --user "${user}" "${service}" php artisan "${@}" diff --git a/docker/bash b/docker/bash new file mode 100755 index 000000000..fc889b964 --- /dev/null +++ b/docker/bash @@ -0,0 +1,12 @@ +#!/bin/bash + +declare service="${PF_SERVICE:=worker}" +declare user="${PF_USER:=www-data}" + +declare -a command=("bash") + +if [[ $# -ge 1 ]]; then + command=("$@") +fi + +exec docker compose exec --user "${user}" "${service}" "${command[@]}" From f486bfb73e507e368396abbabf4f27c3d809849a Mon Sep 17 00:00:00 2001 From: Christian Winther Date: Wed, 21 Feb 2024 22:29:07 +0000 Subject: [PATCH 146/173] add small dottie wrapper --- docker/dottie | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) create mode 100755 docker/dottie diff --git a/docker/dottie b/docker/dottie new file mode 100755 index 000000000..bd268a070 --- /dev/null +++ b/docker/dottie @@ -0,0 +1,16 @@ +#!/bin/bash + +declare root="${PWD}" + +if command -v git &>/dev/null; then + root=$(git rev-parse --show-toplevel) +fi + +exec docker run \ + --rm \ + --interactive \ + --tty \ + --volume "${root}:/var/www" \ + --workdir /var/www \ + ghcr.io/jippi/dottie \ + "$@" From 26d6f8f9febd0ee9966acd3cc25eb104fec571e4 Mon Sep 17 00:00:00 2001 From: Christian Winther Date: Thu, 22 Feb 2024 13:21:58 +0000 Subject: [PATCH 147/173] push build cache to registry as well --- .github/workflows/docker.yml | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/.github/workflows/docker.yml b/.github/workflows/docker.yml index 9a451937c..595d4a2e5 100644 --- a/.github/workflows/docker.yml +++ b/.github/workflows/docker.yml @@ -189,8 +189,11 @@ jobs: build-args: | PHP_VERSION=${{ matrix.php_version }} PHP_BASE_TYPE=${{ matrix.php_base }} - cache-from: type=gha,scope=${{ matrix.target_runtime }}-${{ matrix.php_base }}-${{ matrix.php_version }} - cache-to: type=gha,mode=max,scope=${{ matrix.target_runtime }}-${{ matrix.php_base }}-${{ matrix.php_version }} + cache-from: | + type=gha,scope=${{ matrix.target_runtime }}-${{ matrix.php_base }}-${{ matrix.php_version }} + cache-to: | + type=gha,mode=max,scope=${{ matrix.target_runtime }}-${{ matrix.php_base }}-${{ matrix.php_version }} + type=registry,ref=${{ matrix.target_runtime }}-${{ matrix.php_base }}-${{ matrix.php_version }}-cache # goss validate the image # From 14f8478e6ae14cb6d224c87a68748fa85d294059 Mon Sep 17 00:00:00 2001 From: Christian Winther Date: Thu, 22 Feb 2024 13:25:56 +0000 Subject: [PATCH 148/173] push build cache to registry as well --- .github/workflows/docker.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/docker.yml b/.github/workflows/docker.yml index 595d4a2e5..ee49d1351 100644 --- a/.github/workflows/docker.yml +++ b/.github/workflows/docker.yml @@ -193,7 +193,7 @@ jobs: type=gha,scope=${{ matrix.target_runtime }}-${{ matrix.php_base }}-${{ matrix.php_version }} cache-to: | type=gha,mode=max,scope=${{ matrix.target_runtime }}-${{ matrix.php_base }}-${{ matrix.php_version }} - type=registry,ref=${{ matrix.target_runtime }}-${{ matrix.php_base }}-${{ matrix.php_version }}-cache + type=registry,ref=ghcr.io/${{ github.repository }}-cache:${{ matrix.target_runtime }}-${{ matrix.php_base }}-${{ matrix.php_version }} # goss validate the image # From ae358e47cbef2570583f2a56591a7b0ab562f273 Mon Sep 17 00:00:00 2001 From: Christian Winther Date: Thu, 22 Feb 2024 13:38:27 +0000 Subject: [PATCH 149/173] push build cache to registry as well --- .github/workflows/docker.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/docker.yml b/.github/workflows/docker.yml index ee49d1351..e5a3384d5 100644 --- a/.github/workflows/docker.yml +++ b/.github/workflows/docker.yml @@ -193,7 +193,7 @@ jobs: type=gha,scope=${{ matrix.target_runtime }}-${{ matrix.php_base }}-${{ matrix.php_version }} cache-to: | type=gha,mode=max,scope=${{ matrix.target_runtime }}-${{ matrix.php_base }}-${{ matrix.php_version }} - type=registry,ref=ghcr.io/${{ github.repository }}-cache:${{ matrix.target_runtime }}-${{ matrix.php_base }}-${{ matrix.php_version }} + type=registry,ref=ghcr.io/${{ github.repository }}-cache:${{ steps.meta.outputs.tags }} # goss validate the image # From 9c26bf26dd668a0aa12694b8e28801b58b4a865b Mon Sep 17 00:00:00 2001 From: Christian Winther Date: Thu, 22 Feb 2024 13:40:32 +0000 Subject: [PATCH 150/173] push build cache to registry as well --- .github/workflows/docker.yml | 23 ++++++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) diff --git a/.github/workflows/docker.yml b/.github/workflows/docker.yml index e5a3384d5..50c2cbc32 100644 --- a/.github/workflows/docker.yml +++ b/.github/workflows/docker.yml @@ -173,6 +173,27 @@ jobs: env: DOCKER_METADATA_ANNOTATIONS_LEVELS: manifest,index + - name: Docker meta (Cache)) + uses: docker/metadata-action@v5 + id: cache + with: + images: | + name=ghcr.io/${{ github.repository }}-cache,enable=true + name=${{ env.DOCKER_HUB_ORGANISATION }}/${{ env.DOCKER_HUB_REPO }}-cache,enable=${{ env.HAS_DOCKER_HUB_CONFIGURED }} + flavor: | + latest=auto + suffix=-${{ matrix.target_runtime }}-${{ matrix.php_version }} + tags: | + type=raw,value=dev,enable=${{ github.ref == format('refs/heads/{0}', 'dev') }} + type=raw,value=staging,enable=${{ github.ref == format('refs/heads/{0}', 'staging') }} + type=pep440,pattern={{raw}} + type=pep440,pattern=v{{major}}.{{minor}} + type=ref,event=branch,prefix=branch- + type=ref,event=pr,prefix=pr- + type=ref,event=tag + env: + DOCKER_METADATA_ANNOTATIONS_LEVELS: manifest,index + - name: Build and push Docker image uses: docker/build-push-action@v5 with: @@ -193,7 +214,7 @@ jobs: type=gha,scope=${{ matrix.target_runtime }}-${{ matrix.php_base }}-${{ matrix.php_version }} cache-to: | type=gha,mode=max,scope=${{ matrix.target_runtime }}-${{ matrix.php_base }}-${{ matrix.php_version }} - type=registry,ref=ghcr.io/${{ github.repository }}-cache:${{ steps.meta.outputs.tags }} + ${{ steps.cache.outputs.tags }} # goss validate the image # From 0ecebbb8bf0f13f3f8c0b199d18e9bcf33a471f8 Mon Sep 17 00:00:00 2001 From: Christian Winther Date: Thu, 22 Feb 2024 14:07:51 +0000 Subject: [PATCH 151/173] push build cache to registry as well --- .github/workflows/docker.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/docker.yml b/.github/workflows/docker.yml index 50c2cbc32..d14c88dfc 100644 --- a/.github/workflows/docker.yml +++ b/.github/workflows/docker.yml @@ -173,7 +173,7 @@ jobs: env: DOCKER_METADATA_ANNOTATIONS_LEVELS: manifest,index - - name: Docker meta (Cache)) + - name: Docker meta (Cache) uses: docker/metadata-action@v5 id: cache with: From 3bfd043792158dc8c929493ab1bfda68da6801a1 Mon Sep 17 00:00:00 2001 From: Christian Winther Date: Thu, 22 Feb 2024 14:32:50 +0000 Subject: [PATCH 152/173] update ignore files --- .dockerignore | 22 +++++++++++++++++++--- .gitignore | 1 + 2 files changed, 20 insertions(+), 3 deletions(-) diff --git a/.dockerignore b/.dockerignore index c8ae49a4e..7c06534dc 100644 --- a/.dockerignore +++ b/.dockerignore @@ -1,4 +1,20 @@ -.env -.git -.gitignore +.DS_Store +/.composer/ +/.env +/.git +/.gitconfig +/.gitignore +/bootstrap/cache /docker-compose-state/ +/node_modules +/npm-debug.log +/public/storage +/public/vendor/horizon +/storage/*.key +/storage/docker +/vendor +/yarn-error.log + +# exceptions - these *MUST* be last +!/bootstrap/cache/.gitignore +!/public/vendor/horizon/.gitignore diff --git a/.gitignore b/.gitignore index f83ec13c4..b8e9b18de 100644 --- a/.gitignore +++ b/.gitignore @@ -14,6 +14,7 @@ /public/hot /public/storage /storage/*.key +/storage/docker /vendor Homestead.json Homestead.yaml From 28b83b575f13ad8d27aa714085cdbb8cf1c3fd94 Mon Sep 17 00:00:00 2001 From: Christian Winther Date: Thu, 22 Feb 2024 14:48:31 +0000 Subject: [PATCH 153/173] Bump dottie --- Dockerfile | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index e82de9d45..c6b297105 100644 --- a/Dockerfile +++ b/Dockerfile @@ -21,7 +21,7 @@ ARG FOREGO_VERSION="0.17.2" ARG GOMPLATE_VERSION="v3.11.6" # See: https://github.com/jippi/dottie -ARG DOTTIE_VERSION="v0.8.0" +ARG DOTTIE_VERSION="v0.9.3" ### # PHP base configuration @@ -142,6 +142,7 @@ ENV APT_PACKAGES_EXTRA=${APT_PACKAGES_EXTRA} # Install and configure base layer COPY docker/shared/root/docker/install/base.sh /docker/install/base.sh + RUN --mount=type=cache,id=pixelfed-apt-${PHP_VERSION}-${PHP_DEBIAN_RELEASE}-${TARGETPLATFORM},sharing=locked,target=/var/lib/apt \ --mount=type=cache,id=pixelfed-apt-cache-${PHP_VERSION}-${PHP_DEBIAN_RELEASE}-${TARGETPLATFORM},sharing=locked,target=/var/cache/apt \ /docker/install/base.sh From 0addfe5605c06571e897aad33022407642a69551 Mon Sep 17 00:00:00 2001 From: Christian Winther Date: Thu, 22 Feb 2024 14:49:18 +0000 Subject: [PATCH 154/173] allow .env control of a couple of PHP settings --- .env.docker | 51 +++++++++++++++++-- .../templates/usr/local/etc/php/php.ini | 14 ++--- 2 files changed, 55 insertions(+), 10 deletions(-) diff --git a/.env.docker b/.env.docker index 2368e85d6..9a6af8bbd 100644 --- a/.env.docker +++ b/.env.docker @@ -1050,6 +1050,16 @@ DOCKER_APP_HOST_CACHE_PATH="${DOCKER_ALL_HOST_DATA_ROOT_PATH:?error}/pixelfed/ca # @dottie/validate required,boolean #DOCKER_APP_ENTRYPOINT_DEBUG="0" +# Show the "diff" when applying templating to files +# +# @default "1" +# @dottie/validate required,boolean +#DOCKER_APP_ENTRYPOINT_SHOW_TEMPLATE_DIFF="1" + +# Docker entrypoints that should be skipped on startup +# @default "" +#ENTRYPOINT_SKIP_SCRIPTS="" + # List of extra APT packages (separated by space) to install when building # locally using [docker compose build]. # @@ -1076,6 +1086,43 @@ DOCKER_APP_HOST_CACHE_PATH="${DOCKER_ALL_HOST_DATA_ROOT_PATH:?error}/pixelfed/ca # @dottie/validate required #DOCKER_APP_PHP_MEMORY_LIMIT="128M" +# @default "E_ALL & ~E_DEPRECATED & ~E_STRICT" +# @see http://php.net/error-reporting +# @dottie/validate required +#DOCKER_APP_PHP_ERROR_REPORTING="E_ALL & ~E_DEPRECATED & ~E_STRICT" + +# @default "off" +# @see http://php.net/display-errors +# @dottie/validate required,oneof=on off +#DOCKER_APP_PHP_DISPLAY_ERRORS="off" + +# Enables the opcode cache. +# +# When disabled, code is not optimised or cached. +# +# @default "1" +# @see https://www.php.net/manual/en/opcache.configuration.php#ini.opcache.enable +# @dottie/validate required,oneof=0 1 +#DOCKER_APP_PHP_OPCACHE_ENABLE="1" + +# If enabled, OPcache will check for updated scripts every [opcache.revalidate_freq] seconds. +# +# When this directive is disabled, you must reset OPcache manually via opcache_reset(), +# opcache_invalidate() or by restarting the Web server for changes to the filesystem to take effect. +# +# @default "0" +# @see https://www.php.net/manual/en/opcache.configuration.php#ini.opcache.validate-timestamps +# @dottie/validate required,oneof=0 1 +#DOCKER_APP_PHP_OPCACHE_VALIDATE_TIMESTAMPS="0" + +# How often to check script timestamps for updates, in seconds. +# 0 will result in OPcache checking for updates on every request. +# +# @default "2" +# @see https://www.php.net/manual/en/opcache.configuration.php#ini.opcache.revalidate-freq +# @dottie/validate required,oneof=0 1 2 +#DOCKER_APP_PHP_OPCACHE_REVALIDATE_FREQ="2" + ################################################################################ # docker redis ################################################################################ @@ -1165,7 +1212,6 @@ DOCKER_DB_HEALTHCHECK_INTERVAL="${DOCKER_ALL_DEFAULT_HEALTHCHECK_INTERVAL:?error ################################################################################ # Set this to a non-empty value (e.g. "disabled") to disable the [web] service -# @dottie/validate required #DOCKER_WEB_PROFILE="" # Port to expose [web] container will listen on *outside* the container (e.g. the host machine) for *HTTP* traffic only @@ -1181,7 +1227,6 @@ DOCKER_WEB_HEALTHCHECK_INTERVAL="${DOCKER_ALL_DEFAULT_HEALTHCHECK_INTERVAL:?erro ################################################################################ # Set this to a non-empty value (e.g. "disabled") to disable the [worker] service -# @dottie/validate required #DOCKER_WORKER_PROFILE="" # How often Docker health check should run for [worker] service @@ -1196,7 +1241,7 @@ DOCKER_WORKER_HEALTHCHECK_INTERVAL="${DOCKER_ALL_DEFAULT_HEALTHCHECK_INTERVAL:?e #DOCKER_PROXY_PROFILE= # Set this to a non-empty value (e.g. "disabled") to disable the [proxy-acme] service -#DOCKER_PROXY_ACME_PROFILE="${DOCKER_PROXY_PROFILE?error}" +#DOCKER_PROXY_ACME_PROFILE="${DOCKER_PROXY_PROFILE:-}" # The version of nginx-proxy to use # diff --git a/docker/shared/root/docker/templates/usr/local/etc/php/php.ini b/docker/shared/root/docker/templates/usr/local/etc/php/php.ini index 0ca96819b..130166e80 100644 --- a/docker/shared/root/docker/templates/usr/local/etc/php/php.ini +++ b/docker/shared/root/docker/templates/usr/local/etc/php/php.ini @@ -462,7 +462,7 @@ memory_limit = {{ getenv "DOCKER_APP_PHP_MEMORY_LIMIT" "128M" }} ; Development Value: E_ALL ; Production Value: E_ALL & ~E_DEPRECATED & ~E_STRICT ; http://php.net/error-reporting -error_reporting = E_ALL & ~E_DEPRECATED & ~E_STRICT +error_reporting = {{ getenv "DOCKER_APP_PHP_ERROR_REPORTING" "E_ALL & ~E_DEPRECATED & ~E_STRICT" }} ; This directive controls whether or not and where PHP will output errors, ; notices and warnings too. Error output is very useful during development, but @@ -479,7 +479,7 @@ error_reporting = E_ALL & ~E_DEPRECATED & ~E_STRICT ; Development Value: On ; Production Value: Off ; http://php.net/display-errors -display_errors = Off +display_errors = {{ getenv "DOCKER_APP_PHP_DISPLAY_ERRORS" "off" }} ; The display of errors which occur during PHP's startup sequence are handled ; separately from display_errors. We strongly recommend you set this to 'off' @@ -488,7 +488,7 @@ display_errors = Off ; Development Value: On ; Production Value: Off ; http://php.net/display-startup-errors -display_startup_errors = Off +display_startup_errors = {{ getenv "DOCKER_APP_PHP_DISPLAY_ERRORS" "off" }} ; Besides displaying errors, PHP can also log errors to locations such as a ; server-specific log, STDERR, or a location specified by the error_log @@ -680,7 +680,7 @@ auto_globals_jit = On ; Its value may be 0 to disable the limit. It is ignored if POST data reading ; is disabled through enable_post_data_reading. ; http://php.net/post-max-size -post_max_size = {{ getenv "POST_MAX_SIZE" }} +post_max_size = {{ getenv "POST_MAX_SIZE" "61M" }} ; Automatically add files before PHP document. ; http://php.net/auto-prepend-file @@ -1736,7 +1736,7 @@ ldap.max_links = -1 [opcache] ; Determines if Zend OPCache is enabled -;opcache.enable=1 +opcache.enable={{ getenv "DOCKER_APP_PHP_OPCACHE_ENABLE" "1" }} ; Determines if Zend OPCache is enabled for the CLI version of PHP ;opcache.enable_cli=0 @@ -1762,12 +1762,12 @@ ldap.max_links = -1 ; When disabled, you must reset the OPcache manually or restart the ; webserver for changes to the filesystem to take effect. -;opcache.validate_timestamps=1 +opcache.validate_timestamps={{ getenv "DOCKER_APP_PHP_OPCACHE_VALIDATE_TIMESTAMPS" "0" }} ; How often (in seconds) to check file timestamps for changes to the shared ; memory storage allocation. ("1" means validate once per second, but only ; once per request. "0" means always validate) -;opcache.revalidate_freq=2 +opcache.revalidate_freq={{ getenv "DOCKER_APP_PHP_OPCACHE_REVALIDATE_FREQ" "2" }} ; Enables or disables file search in include_path optimization ;opcache.revalidate_path=0 From 8fd27c6f0c978cbeebe2aa9d690b2df8e610f6d5 Mon Sep 17 00:00:00 2001 From: Christian Winther Date: Thu, 22 Feb 2024 14:50:15 +0000 Subject: [PATCH 155/173] use remote build cache for faster local dev --- docker-compose.yml | 4 ++++ .../docker/shared/proxy/conf.d/docker-pixelfed.conf | 7 +++++++ 2 files changed, 11 insertions(+) create mode 100644 docker/shared/root/docker/templates/docker/shared/proxy/conf.d/docker-pixelfed.conf diff --git a/docker-compose.yml b/docker-compose.yml index 77e184c2c..c8eb9458f 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -74,6 +74,8 @@ services: - ${DOCKER_WEB_PROFILE:-} build: target: ${DOCKER_APP_RUNTIME}-runtime + cache_from: + - "type=registry,ref=${DOCKER_APP_IMAGE}-cache:${DOCKER_APP_TAG}" args: APT_PACKAGES_EXTRA: "${DOCKER_APP_APT_PACKAGES_EXTRA:-}" PHP_BASE_TYPE: "${DOCKER_APP_BASE_TYPE}" @@ -117,6 +119,8 @@ services: stop_signal: SIGTERM build: target: ${DOCKER_APP_RUNTIME}-runtime + cache_from: + - "type=registry,ref=${DOCKER_APP_IMAGE}-cache:${DOCKER_APP_TAG}" args: APT_PACKAGES_EXTRA: "${DOCKER_APP_APT_PACKAGES_EXTRA:-}" PHP_BASE_TYPE: "${DOCKER_APP_BASE_TYPE}" diff --git a/docker/shared/root/docker/templates/docker/shared/proxy/conf.d/docker-pixelfed.conf b/docker/shared/root/docker/templates/docker/shared/proxy/conf.d/docker-pixelfed.conf new file mode 100644 index 000000000..1b5a9a80f --- /dev/null +++ b/docker/shared/root/docker/templates/docker/shared/proxy/conf.d/docker-pixelfed.conf @@ -0,0 +1,7 @@ +########################################################### +# DO NOT CHANGE +########################################################### +# This file is generated by the Pixelfed Docker setup, and +# will be rewritten on every container start + +client_max_body_size {{ getenv "POST_MAX_SIZE" "61M" }}; From d9d2a475d8379939516ae682fd4ac739452ef098 Mon Sep 17 00:00:00 2001 From: Christian Winther Date: Thu, 22 Feb 2024 14:53:39 +0000 Subject: [PATCH 156/173] sort keys in compose --- docker-compose.yml | 30 ++++++++++++++++++++++-------- 1 file changed, 22 insertions(+), 8 deletions(-) diff --git a/docker-compose.yml b/docker-compose.yml index c8eb9458f..ca4ece22b 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -25,6 +25,8 @@ services: restart: unless-stopped profiles: - ${DOCKER_PROXY_PROFILE:-} + environment: + DOCKER_SERVICE_NAME: "proxy" volumes: - "${DOCKER_PROXY_HOST_DOCKER_SOCKET_PATH}:/tmp/docker.sock:ro" - "${DOCKER_ALL_HOST_CONFIG_ROOT_PATH}/proxy/conf.d:/etc/nginx/conf.d" @@ -83,17 +85,23 @@ services: PHP_EXTENSIONS_EXTRA: "${DOCKER_APP_PHP_EXTENSIONS_EXTRA:-}" PHP_PECL_EXTENSIONS_EXTRA: "${DOCKER_APP_PHP_PECL_EXTENSIONS_EXTRA:-}" PHP_VERSION: "${DOCKER_APP_PHP_VERSION:?error}" - volumes: - - "./.env:/var/www/.env" - - "${DOCKER_APP_HOST_CACHE_PATH}:/var/www/bootstrap/cache" - - "${DOCKER_APP_HOST_STORAGE_PATH}:/var/www/storage" - - "${DOCKER_APP_HOST_OVERRIDES_PATH}:/docker/overrides:ro" environment: + # Used by Pixelfed Docker init script + DOCKER_SERVICE_NAME: "web" + DOCKER_APP_ENTRYPOINT_DEBUG: ${DOCKER_APP_ENTRYPOINT_DEBUG:-0} + ENTRYPOINT_SKIP_SCRIPTS: ${ENTRYPOINT_SKIP_SCRIPTS:-} + # Used by [proxy] service LETSENCRYPT_HOST: "${DOCKER_PROXY_LETSENCRYPT_HOST:?error}" LETSENCRYPT_EMAIL: "${DOCKER_PROXY_LETSENCRYPT_EMAIL:?error}" LETSENCRYPT_TEST: "${DOCKER_PROXY_LETSENCRYPT_TEST:-}" VIRTUAL_HOST: "${APP_DOMAIN}" VIRTUAL_PORT: "80" + volumes: + - "./.env:/var/www/.env" + - "${DOCKER_ALL_HOST_CONFIG_ROOT_PATH}/proxy/conf.d:/docker/shared/proxy/conf.d" + - "${DOCKER_APP_HOST_CACHE_PATH}:/var/www/bootstrap/cache" + - "${DOCKER_APP_HOST_OVERRIDES_PATH}:/docker/overrides:ro" + - "${DOCKER_APP_HOST_STORAGE_PATH}:/var/www/storage" labels: com.github.nginx-proxy.nginx-proxy.keepalive: 30 com.github.nginx-proxy.nginx-proxy.http2.enable: true @@ -114,9 +122,9 @@ services: container_name: "${DOCKER_ALL_CONTAINER_NAME_PREFIX}-worker" command: gosu www-data php artisan horizon restart: unless-stopped + stop_signal: SIGTERM profiles: - ${DOCKER_WORKER_PROFILE:-} - stop_signal: SIGTERM build: target: ${DOCKER_APP_RUNTIME}-runtime cache_from: @@ -128,11 +136,17 @@ services: PHP_EXTENSIONS_EXTRA: "${DOCKER_APP_PHP_EXTENSIONS_EXTRA:-}" PHP_PECL_EXTENSIONS_EXTRA: "${DOCKER_APP_PHP_PECL_EXTENSIONS_EXTRA:-}" PHP_VERSION: "${DOCKER_APP_PHP_VERSION:?error}" + environment: + # Used by Pixelfed Docker init script + DOCKER_SERVICE_NAME: "worker" + DOCKER_APP_ENTRYPOINT_DEBUG: ${DOCKER_APP_ENTRYPOINT_DEBUG:-0} + ENTRYPOINT_SKIP_SCRIPTS: ${ENTRYPOINT_SKIP_SCRIPTS:-} volumes: - "./.env:/var/www/.env" + - "${DOCKER_ALL_HOST_CONFIG_ROOT_PATH}/proxy/conf.d:/docker/shared/proxy/conf.d" - "${DOCKER_APP_HOST_CACHE_PATH}:/var/www/bootstrap/cache" - - "${DOCKER_APP_HOST_STORAGE_PATH}:/var/www/storage" - "${DOCKER_APP_HOST_OVERRIDES_PATH}:/docker/overrides:ro" + - "${DOCKER_APP_HOST_STORAGE_PATH}:/var/www/storage" depends_on: - db - redis @@ -186,9 +200,9 @@ services: image: redis:${DOCKER_REDIS_VERSION} container_name: "${DOCKER_ALL_CONTAINER_NAME_PREFIX}-redis" restart: unless-stopped + command: "${DOCKER_REDIS_CONFIG_FILE:-} --requirepass '${REDIS_PASSWORD:-}'" profiles: - ${DOCKER_REDIS_PROFILE:-} - command: "${DOCKER_REDIS_CONFIG_FILE:-} --requirepass '${REDIS_PASSWORD:-}'" environment: TZ: "${TZ:?error}" REDISCLI_AUTH: ${REDIS_PASSWORD:-} From f264dd1cbbe70188151a4fcc5e66cdbdb573233a Mon Sep 17 00:00:00 2001 From: Christian Winther Date: Thu, 22 Feb 2024 14:53:59 +0000 Subject: [PATCH 157/173] space redirects in shell scripts --- .editorconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.editorconfig b/.editorconfig index a56c5a37a..b368b11ec 100644 --- a/.editorconfig +++ b/.editorconfig @@ -20,7 +20,7 @@ indent_size = 4 shell_variant = bash # like -ln=bash binary_next_line = true # like -bn switch_case_indent = true # like -ci -space_redirects = false # like -sr +space_redirects = true # like -sr keep_padding = false # like -kp function_next_line = true # like -fn never_split = true # like -ns From 193d536ca1e6f6fca0368f2da6db993484550583 Mon Sep 17 00:00:00 2001 From: Christian Winther Date: Thu, 22 Feb 2024 14:54:20 +0000 Subject: [PATCH 158/173] update dottie --- docker/dottie | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/docker/dottie b/docker/dottie index bd268a070..6e409def2 100755 --- a/docker/dottie +++ b/docker/dottie @@ -1,16 +1,17 @@ #!/bin/bash -declare root="${PWD}" +declare project_root="${PWD}" if command -v git &>/dev/null; then - root=$(git rev-parse --show-toplevel) + project_root=$(git rev-parse --show-toplevel) fi exec docker run \ --rm \ --interactive \ --tty \ - --volume "${root}:/var/www" \ + --volume "${project_root}:/var/www" \ + --volume "/tmp:/tmp" \ --workdir /var/www \ ghcr.io/jippi/dottie \ "$@" From af47d91e7d4ab4b6f560142070e66262cb3790ec Mon Sep 17 00:00:00 2001 From: Christian Winther Date: Thu, 22 Feb 2024 14:56:08 +0000 Subject: [PATCH 159/173] give nginx config default max upload size --- .../nginx/root/docker/templates/etc/nginx/conf.d/default.conf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docker/nginx/root/docker/templates/etc/nginx/conf.d/default.conf b/docker/nginx/root/docker/templates/etc/nginx/conf.d/default.conf index 671332e78..15bf17beb 100644 --- a/docker/nginx/root/docker/templates/etc/nginx/conf.d/default.conf +++ b/docker/nginx/root/docker/templates/etc/nginx/conf.d/default.conf @@ -14,7 +14,7 @@ server { index index.html index.htm index.php; charset utf-8; - client_max_body_size {{ getenv "POST_MAX_SIZE" }}; + client_max_body_size {{ getenv "POST_MAX_SIZE" "61M" }}; location / { try_files $uri $uri/ /index.php?$query_string; From e2821adccaae9dcf55c0fac719029cd4f18d9411 Mon Sep 17 00:00:00 2001 From: Christian Winther Date: Thu, 22 Feb 2024 14:56:33 +0000 Subject: [PATCH 160/173] fix spacing --- .editorconfig | 4 ++-- docker/shared/root/docker/entrypoint.d/01-permissions.sh | 2 +- docker/shared/root/docker/entrypoint.d/05-templating.sh | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.editorconfig b/.editorconfig index b368b11ec..eff249956 100644 --- a/.editorconfig +++ b/.editorconfig @@ -20,8 +20,8 @@ indent_size = 4 shell_variant = bash # like -ln=bash binary_next_line = true # like -bn switch_case_indent = true # like -ci -space_redirects = true # like -sr -keep_padding = false # like -kp +space_redirects = false # like -sr +keep_padding = false # like -kp function_next_line = true # like -fn never_split = true # like -ns simplify = true diff --git a/docker/shared/root/docker/entrypoint.d/01-permissions.sh b/docker/shared/root/docker/entrypoint.d/01-permissions.sh index f5624721b..11766a742 100755 --- a/docker/shared/root/docker/entrypoint.d/01-permissions.sh +++ b/docker/shared/root/docker/entrypoint.d/01-permissions.sh @@ -16,7 +16,7 @@ run-as-current-user chown --verbose "${RUNTIME_UID}:${RUNTIME_GID}" "./storage" : "${DOCKER_APP_ENSURE_OWNERSHIP_PATHS:=""}" declare -a ensure_ownership_paths=() -IFS=' ' read -ar ensure_ownership_paths <<< "${DOCKER_APP_ENSURE_OWNERSHIP_PATHS}" +IFS=' ' read -ar ensure_ownership_paths <<<"${DOCKER_APP_ENSURE_OWNERSHIP_PATHS}" if [[ ${#ensure_ownership_paths[@]} == 0 ]]; then log-info "No paths has been configured for ownership fixes via [\$DOCKER_APP_ENSURE_OWNERSHIP_PATHS]." diff --git a/docker/shared/root/docker/entrypoint.d/05-templating.sh b/docker/shared/root/docker/entrypoint.d/05-templating.sh index 23d01487a..4d229b11c 100755 --- a/docker/shared/root/docker/entrypoint.d/05-templating.sh +++ b/docker/shared/root/docker/entrypoint.d/05-templating.sh @@ -51,7 +51,7 @@ find "${ENTRYPOINT_TEMPLATE_DIR}" -follow -type f -print | while read -r templat # Render the template log-info "Running [gomplate] on [${template_file}] --> [${output_file_path}]" - gomplate < "${template_file}" > "${output_file_path}" + gomplate <"${template_file}" >"${output_file_path}" # Show the diff from the envsubst command if is-true "${ENTRYPOINT_SHOW_TEMPLATE_DIFF}"; then From 027f858d853da63c70687fae5338dcf1c25783ac Mon Sep 17 00:00:00 2001 From: Christian Winther Date: Thu, 22 Feb 2024 14:56:54 +0000 Subject: [PATCH 161/173] ensure correct ownership of ./storage/docker --- docker/shared/root/docker/entrypoint.d/01-permissions.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/docker/shared/root/docker/entrypoint.d/01-permissions.sh b/docker/shared/root/docker/entrypoint.d/01-permissions.sh index 11766a742..930f69bca 100755 --- a/docker/shared/root/docker/entrypoint.d/01-permissions.sh +++ b/docker/shared/root/docker/entrypoint.d/01-permissions.sh @@ -11,6 +11,7 @@ entrypoint-set-script-name "$0" run-as-current-user chown --verbose "${RUNTIME_UID}:${RUNTIME_GID}" "./.env" run-as-current-user chown --verbose "${RUNTIME_UID}:${RUNTIME_GID}" "./bootstrap/cache" run-as-current-user chown --verbose "${RUNTIME_UID}:${RUNTIME_GID}" "./storage" +run-as-current-user chown --verbose --recursive "${RUNTIME_UID}:${RUNTIME_GID}" "./storage/docker" # Optionally fix ownership of configured paths : "${DOCKER_APP_ENSURE_OWNERSHIP_PATHS:=""}" From 5a43d7a65d0ad30583a4e2448ad320a3bea793b7 Mon Sep 17 00:00:00 2001 From: Christian Winther Date: Thu, 22 Feb 2024 14:57:10 +0000 Subject: [PATCH 162/173] improve error handling for [run-command-as] helper --- docker/shared/root/docker/helpers.sh | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/docker/shared/root/docker/helpers.sh b/docker/shared/root/docker/helpers.sh index 190c04bc4..3a21ee89e 100644 --- a/docker/shared/root/docker/helpers.sh +++ b/docker/shared/root/docker/helpers.sh @@ -91,20 +91,29 @@ function run-command-as() log-info-stderr "${notice_message_color}👷 Running [${*}] as [${target_user}]${color_clear}" + # disable error on exit behavior temporarily while we run the command + set +e + if [[ ${target_user} != "root" ]]; then stream-prefix-command-output su --preserve-environment "${target_user}" --shell /bin/bash --command "${*}" else stream-prefix-command-output "${@}" fi + # capture exit code exit_code=$? + # re-enable exit code handling + set -e + if [[ $exit_code != 0 ]]; then log-error "${error_message_color}❌ Error!${color_clear}" + return "$exit_code" fi log-info-stderr "${success_message_color}✅ OK!${color_clear}" + return "$exit_code" } From 7ffbd5d44a44bdb73faa22fdc8224c9263b69047 Mon Sep 17 00:00:00 2001 From: Christian Winther Date: Thu, 22 Feb 2024 14:58:03 +0000 Subject: [PATCH 163/173] rename docker/bash to docker/shell --- docker/{bash => shell} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename docker/{bash => shell} (100%) diff --git a/docker/bash b/docker/shell similarity index 100% rename from docker/bash rename to docker/shell From f0e30c8ab6cc56667bb1cba813bdefd2e1b69999 Mon Sep 17 00:00:00 2001 From: Christian Winther Date: Thu, 22 Feb 2024 15:02:53 +0000 Subject: [PATCH 164/173] expand docs for proxy nginx config --- .../docker/shared/proxy/conf.d/docker-pixelfed.conf | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/docker/shared/root/docker/templates/docker/shared/proxy/conf.d/docker-pixelfed.conf b/docker/shared/root/docker/templates/docker/shared/proxy/conf.d/docker-pixelfed.conf index 1b5a9a80f..8bb8f1c95 100644 --- a/docker/shared/root/docker/templates/docker/shared/proxy/conf.d/docker-pixelfed.conf +++ b/docker/shared/root/docker/templates/docker/shared/proxy/conf.d/docker-pixelfed.conf @@ -3,5 +3,13 @@ ########################################################### # This file is generated by the Pixelfed Docker setup, and # will be rewritten on every container start +# +# You can put any .conf file in this directory and it will be loaded +# by nginx on startup. +# +# Run [docker compose exec proxy bash -c 'nginx -t && nginx -s reload'] +# to test your config and reload the proxy +# +# See: https://github.com/nginx-proxy/nginx-proxy/blob/main/docs/README.md#custom-nginx-configuration client_max_body_size {{ getenv "POST_MAX_SIZE" "61M" }}; From 515198b28c460ab83e6d90678e9f2b881d90babc Mon Sep 17 00:00:00 2001 From: Christian Winther Date: Thu, 22 Feb 2024 15:12:22 +0000 Subject: [PATCH 165/173] sync ignore files --- .dockerignore | 14 ++++++++++++-- .gitignore | 32 ++++++++++++++++++++------------ 2 files changed, 32 insertions(+), 14 deletions(-) diff --git a/.dockerignore b/.dockerignore index 7c06534dc..757a67a51 100644 --- a/.dockerignore +++ b/.dockerignore @@ -1,13 +1,23 @@ .DS_Store -/.composer/ +/.bash_history +/.bash_profile +/.bashrc +/.composer /.env +/.env.dottie-backup /.git +/.git-credentials /.gitconfig /.gitignore +/.idea +/.vagrant /bootstrap/cache /docker-compose-state/ +/Homestead.json +/Homestead.yaml /node_modules /npm-debug.log +/public/hot /public/storage /public/vendor/horizon /storage/*.key @@ -15,6 +25,6 @@ /vendor /yarn-error.log -# exceptions - these *MUST* be last +# Exceptions - these *MUST* be last !/bootstrap/cache/.gitignore !/public/vendor/horizon/.gitignore diff --git a/.gitignore b/.gitignore index b8e9b18de..ba2c7d07f 100644 --- a/.gitignore +++ b/.gitignore @@ -1,22 +1,30 @@ -.bash_history -.bash_profile -.bashrc .DS_Store -.env -.env.dottie-backup -.git-credentials -.gitconfig -/.composer/ +/.bash_history +/.bash_profile +/.bashrc +/.composer +/.env +/.env.dottie-backup +#/.git +/.git-credentials +/.gitconfig +#/.gitignore /.idea /.vagrant +/bootstrap/cache /docker-compose-state/ +/Homestead.json +/Homestead.yaml /node_modules +/npm-debug.log /public/hot /public/storage +/public/vendor/horizon /storage/*.key /storage/docker /vendor -Homestead.json -Homestead.yaml -npm-debug.log -yarn-error.log +/yarn-error.log + +# Exceptions - these *MUST* be last +!/bootstrap/cache/.gitignore +!/public/vendor/horizon/.gitignore From 2d8e81c83f24db100324c972a53a91a7a99aa547 Mon Sep 17 00:00:00 2001 From: Christian Winther Date: Thu, 22 Feb 2024 15:14:32 +0000 Subject: [PATCH 166/173] ensure ownership of shared proxy conf --- docker/shared/root/docker/entrypoint.d/01-permissions.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/docker/shared/root/docker/entrypoint.d/01-permissions.sh b/docker/shared/root/docker/entrypoint.d/01-permissions.sh index 930f69bca..ad0dac724 100755 --- a/docker/shared/root/docker/entrypoint.d/01-permissions.sh +++ b/docker/shared/root/docker/entrypoint.d/01-permissions.sh @@ -11,6 +11,7 @@ entrypoint-set-script-name "$0" run-as-current-user chown --verbose "${RUNTIME_UID}:${RUNTIME_GID}" "./.env" run-as-current-user chown --verbose "${RUNTIME_UID}:${RUNTIME_GID}" "./bootstrap/cache" run-as-current-user chown --verbose "${RUNTIME_UID}:${RUNTIME_GID}" "./storage" +run-as-current-user chown --verbose "${RUNTIME_UID}:${RUNTIME_GID}" "/docker/shared/proxy/conf.d" run-as-current-user chown --verbose --recursive "${RUNTIME_UID}:${RUNTIME_GID}" "./storage/docker" # Optionally fix ownership of configured paths From c8c2e1c2eb03234cc9cbcb058f1b7cf9ce7984a1 Mon Sep 17 00:00:00 2001 From: Christian Winther Date: Thu, 22 Feb 2024 15:24:51 +0000 Subject: [PATCH 167/173] update docs + paths --- docker-compose.yml | 4 ++-- docker/shared/root/docker/entrypoint.d/01-permissions.sh | 1 - .../{docker => }/shared/proxy/conf.d/docker-pixelfed.conf | 5 +++-- docker/shared/root/shared/proxy/conf.d/.gitignore | 0 4 files changed, 5 insertions(+), 5 deletions(-) rename docker/shared/root/docker/templates/{docker => }/shared/proxy/conf.d/docker-pixelfed.conf (78%) create mode 100644 docker/shared/root/shared/proxy/conf.d/.gitignore diff --git a/docker-compose.yml b/docker-compose.yml index ca4ece22b..5df433c83 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -98,7 +98,7 @@ services: VIRTUAL_PORT: "80" volumes: - "./.env:/var/www/.env" - - "${DOCKER_ALL_HOST_CONFIG_ROOT_PATH}/proxy/conf.d:/docker/shared/proxy/conf.d" + - "${DOCKER_ALL_HOST_CONFIG_ROOT_PATH}/proxy/conf.d:/shared/proxy/conf.d" - "${DOCKER_APP_HOST_CACHE_PATH}:/var/www/bootstrap/cache" - "${DOCKER_APP_HOST_OVERRIDES_PATH}:/docker/overrides:ro" - "${DOCKER_APP_HOST_STORAGE_PATH}:/var/www/storage" @@ -143,7 +143,7 @@ services: ENTRYPOINT_SKIP_SCRIPTS: ${ENTRYPOINT_SKIP_SCRIPTS:-} volumes: - "./.env:/var/www/.env" - - "${DOCKER_ALL_HOST_CONFIG_ROOT_PATH}/proxy/conf.d:/docker/shared/proxy/conf.d" + - "${DOCKER_ALL_HOST_CONFIG_ROOT_PATH}/proxy/conf.d:/shared/proxy/conf.d" - "${DOCKER_APP_HOST_CACHE_PATH}:/var/www/bootstrap/cache" - "${DOCKER_APP_HOST_OVERRIDES_PATH}:/docker/overrides:ro" - "${DOCKER_APP_HOST_STORAGE_PATH}:/var/www/storage" diff --git a/docker/shared/root/docker/entrypoint.d/01-permissions.sh b/docker/shared/root/docker/entrypoint.d/01-permissions.sh index ad0dac724..930f69bca 100755 --- a/docker/shared/root/docker/entrypoint.d/01-permissions.sh +++ b/docker/shared/root/docker/entrypoint.d/01-permissions.sh @@ -11,7 +11,6 @@ entrypoint-set-script-name "$0" run-as-current-user chown --verbose "${RUNTIME_UID}:${RUNTIME_GID}" "./.env" run-as-current-user chown --verbose "${RUNTIME_UID}:${RUNTIME_GID}" "./bootstrap/cache" run-as-current-user chown --verbose "${RUNTIME_UID}:${RUNTIME_GID}" "./storage" -run-as-current-user chown --verbose "${RUNTIME_UID}:${RUNTIME_GID}" "/docker/shared/proxy/conf.d" run-as-current-user chown --verbose --recursive "${RUNTIME_UID}:${RUNTIME_GID}" "./storage/docker" # Optionally fix ownership of configured paths diff --git a/docker/shared/root/docker/templates/docker/shared/proxy/conf.d/docker-pixelfed.conf b/docker/shared/root/docker/templates/shared/proxy/conf.d/docker-pixelfed.conf similarity index 78% rename from docker/shared/root/docker/templates/docker/shared/proxy/conf.d/docker-pixelfed.conf rename to docker/shared/root/docker/templates/shared/proxy/conf.d/docker-pixelfed.conf index 8bb8f1c95..0b221e604 100644 --- a/docker/shared/root/docker/templates/docker/shared/proxy/conf.d/docker-pixelfed.conf +++ b/docker/shared/root/docker/templates/shared/proxy/conf.d/docker-pixelfed.conf @@ -4,8 +4,9 @@ # This file is generated by the Pixelfed Docker setup, and # will be rewritten on every container start # -# You can put any .conf file in this directory and it will be loaded -# by nginx on startup. +# You can put any [.conf] file in this directory +# (docker-compose-state/config/proxy/conf.d) and it will +# be loaded by nginx on startup. # # Run [docker compose exec proxy bash -c 'nginx -t && nginx -s reload'] # to test your config and reload the proxy diff --git a/docker/shared/root/shared/proxy/conf.d/.gitignore b/docker/shared/root/shared/proxy/conf.d/.gitignore new file mode 100644 index 000000000..e69de29bb From df1f62e73453654af0d45d9e2ace7950a7651ad7 Mon Sep 17 00:00:00 2001 From: Christian Winther Date: Thu, 22 Feb 2024 15:30:34 +0000 Subject: [PATCH 168/173] update docs --- docker/shared/root/docker/entrypoint.d/01-permissions.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docker/shared/root/docker/entrypoint.d/01-permissions.sh b/docker/shared/root/docker/entrypoint.d/01-permissions.sh index 930f69bca..efff58110 100755 --- a/docker/shared/root/docker/entrypoint.d/01-permissions.sh +++ b/docker/shared/root/docker/entrypoint.d/01-permissions.sh @@ -6,7 +6,7 @@ source "${ENTRYPOINT_ROOT}/helpers.sh" entrypoint-set-script-name "$0" -# Ensure the two Docker volumes and dot-env files are owned by the runtime user as other scripts +# Ensure the Docker volumes and required files are owned by the runtime user as other scripts # will be writing to these run-as-current-user chown --verbose "${RUNTIME_UID}:${RUNTIME_GID}" "./.env" run-as-current-user chown --verbose "${RUNTIME_UID}:${RUNTIME_GID}" "./bootstrap/cache" From 1976af6dd1a30ecf5b1c599ecf798d18e08440e4 Mon Sep 17 00:00:00 2001 From: Christian Winther Date: Sat, 24 Feb 2024 22:50:48 +0000 Subject: [PATCH 169/173] ensure color in dottie output by passing through env --- docker/artisan | 7 ++++++- docker/dottie | 45 ++++++++++++++++++++++++++++++++++++--------- 2 files changed, 42 insertions(+), 10 deletions(-) diff --git a/docker/artisan b/docker/artisan index d50d65244..3bbf58aea 100755 --- a/docker/artisan +++ b/docker/artisan @@ -3,4 +3,9 @@ declare service="${PF_SERVICE:=worker}" declare user="${PF_USER:=www-data}" -exec docker compose exec --user "${user}" "${service}" php artisan "${@}" +exec docker compose exec \ + --user "${user}" \ + --env TERM \ + --env COLORTERM \ + "${service}" \ + php artisan "${@}" diff --git a/docker/dottie b/docker/dottie index 6e409def2..a6ad7bc78 100755 --- a/docker/dottie +++ b/docker/dottie @@ -1,17 +1,44 @@ #!/bin/bash +set -e -o errexit -o nounset -o pipefail + declare project_root="${PWD}" if command -v git &>/dev/null; then project_root=$(git rev-parse --show-toplevel) fi -exec docker run \ - --rm \ - --interactive \ - --tty \ - --volume "${project_root}:/var/www" \ - --volume "/tmp:/tmp" \ - --workdir /var/www \ - ghcr.io/jippi/dottie \ - "$@" +declare -r release="${DOTTIE_VERSION:-latest}" + +declare -r update_check_file="/tmp/.dottie-update-check" # file to check age of since last update +declare -i update_check_max_age=$((8 * 60 * 60)) # 8 hours between checking for dottie version +declare -i update_check_cur_age=$((update_check_max_age + 1)) # by default the "update" event should happen + +# default [docker run] flags +declare -a flags=( + --rm + --interactive + --tty + --env TERM + --env COLORTERM + --volume "/tmp:/tmp" + --volume "${project_root}:/var/www" + --workdir /var/www +) + +# if update file exists, find its age since last modification +if [[ -f "${update_check_file}" ]]; then + now=$(date +%s) + changed=$(date -r "${update_check_file}" +%s) + update_check_cur_age=$((now - changed)) +fi + +# if update file is older than max allowed poll for new version of dottie +if [[ $update_check_cur_age -gt $update_check_max_age ]]; then + flags+=(--pull always) + + touch "${update_check_file}" +fi + +# run dottie +exec docker run "${flags[@]}" "ghcr.io/jippi/dottie:${release}" "$@" From b08bb3669d1904f7d56578adadaaf32c0b491d7a Mon Sep 17 00:00:00 2001 From: Christian Winther Date: Sat, 24 Feb 2024 23:00:38 +0000 Subject: [PATCH 170/173] bump dottie version --- Dockerfile | 2 +- docker/shell | 7 ++++++- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/Dockerfile b/Dockerfile index c6b297105..42238329c 100644 --- a/Dockerfile +++ b/Dockerfile @@ -21,7 +21,7 @@ ARG FOREGO_VERSION="0.17.2" ARG GOMPLATE_VERSION="v3.11.6" # See: https://github.com/jippi/dottie -ARG DOTTIE_VERSION="v0.9.3" +ARG DOTTIE_VERSION="v0.9.5" ### # PHP base configuration diff --git a/docker/shell b/docker/shell index fc889b964..7b725e1b0 100755 --- a/docker/shell +++ b/docker/shell @@ -9,4 +9,9 @@ if [[ $# -ge 1 ]]; then command=("$@") fi -exec docker compose exec --user "${user}" "${service}" "${command[@]}" +exec docker compose exec \ + --user "${user}" \ + --env TERM \ + --env COLORTERM \ + "${service}" \ + "${command[@]}" From c1c361ef9bd866c11e09d28b2f26b6fd43d66dad Mon Sep 17 00:00:00 2001 From: Christian Winther Date: Sat, 24 Feb 2024 23:29:45 +0000 Subject: [PATCH 171/173] tune for new dottie image --- docker/dottie | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/docker/dottie b/docker/dottie index a6ad7bc78..8bd304a03 100755 --- a/docker/dottie +++ b/docker/dottie @@ -3,6 +3,7 @@ set -e -o errexit -o nounset -o pipefail declare project_root="${PWD}" +declare user="${PF_USER:=www-data}" if command -v git &>/dev/null; then project_root=$(git rev-parse --show-toplevel) @@ -19,9 +20,9 @@ declare -a flags=( --rm --interactive --tty + --user "${user}" --env TERM --env COLORTERM - --volume "/tmp:/tmp" --volume "${project_root}:/var/www" --workdir /var/www ) From 02369cce66c3d59b0caff833d23d1698a5628099 Mon Sep 17 00:00:00 2001 From: Christian Winther Date: Sun, 25 Feb 2024 10:53:29 +0000 Subject: [PATCH 172/173] fix validation issues in the .env.docker file --- .env.docker | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/.env.docker b/.env.docker index 9a6af8bbd..0d5836745 100644 --- a/.env.docker +++ b/.env.docker @@ -202,7 +202,7 @@ APP_TIMEZONE="UTC" # # @default "false" # @see https://docs.pixelfed.org/technical-documentation/config/#account_delete_after -# @dottie/validate required,boolean +# @dottie/validate required,boolean|number #ACCOUNT_DELETE_AFTER="false" # @default "Pixelfed - Photo sharing for everyone" @@ -722,14 +722,13 @@ LOG_CHANNEL="stderr" # # @default "debug" # @see https://docs.pixelfed.org/technical-documentation/config/#log_level -# @dottie/validate required,boolean +# @dottie/validate required,oneof=debug info notice warning error critical alert emergency #LOG_LEVEL="debug" # Used by stderr. # # @default "" # @see https://docs.pixelfed.org/technical-documentation/config/#log_stderr_formatter -# @dottie/validate required #LOG_STDERR_FORMATTER="" # Used by slack. @@ -984,7 +983,7 @@ DOCKER_APP_RUNTIME="apache" # The Debian release variant to use of the [php] Docker image # # Examlpe: [bookworm] or [bullseye] -# @dottie/validate required,oneof=bookwork bullseye +# @dottie/validate required,oneof=bookworm bullseye DOCKER_APP_DEBIAN_RELEASE="bullseye" # The [php] Docker image base type From acb699bf133e218671769698abd86eae37f0fb9f Mon Sep 17 00:00:00 2001 From: Christian Winther Date: Sun, 25 Feb 2024 11:00:26 +0000 Subject: [PATCH 173/173] use the correct buildkit env for downloading binaries --- Dockerfile | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/Dockerfile b/Dockerfile index 42238329c..a6ad884b8 100644 --- a/Dockerfile +++ b/Dockerfile @@ -98,8 +98,8 @@ FROM ghcr.io/jippi/dottie:${DOTTIE_VERSION} AS dottie-image # It's in its own layer so it can be fetched in parallel with other build steps FROM php:${PHP_VERSION}-${PHP_BASE_TYPE}-${PHP_DEBIAN_RELEASE} AS gomplate-image -ARG BUILDARCH -ARG BUILDOS +ARG TARGETARCH +ARG TARGETOS ARG GOMPLATE_VERSION RUN set -ex \ @@ -108,7 +108,7 @@ RUN set -ex \ --show-error \ --location \ --output /usr/local/bin/gomplate \ - https://github.com/hairyhenderson/gomplate/releases/download/${GOMPLATE_VERSION}/gomplate_${BUILDOS}-${BUILDARCH} \ + https://github.com/hairyhenderson/gomplate/releases/download/${GOMPLATE_VERSION}/gomplate_${TARGETOS}-${TARGETARCH} \ && chmod +x /usr/local/bin/gomplate \ && /usr/local/bin/gomplate --version @@ -220,9 +220,6 @@ COPY --chown=${RUNTIME_UID}:${RUNTIME_GID} . /var/www/ FROM php-extensions AS shared-runtime -ARG BUILDARCH -ARG BUILDOS -ARG GOMPLATE_VERSION ARG RUNTIME_GID ARG RUNTIME_UID