├── .github └── workflows │ ├── build.yml │ └── scan.yml ├── Dockerfile ├── README.md ├── SECURITY.md └── rootfs ├── data └── .gitkeep ├── etc ├── nginx │ ├── conf.d │ │ └── default.conf │ └── nginx.conf └── s6.d │ ├── .s6-svscan │ └── finish │ ├── cron │ └── run │ ├── nginx │ └── run │ └── php │ └── run ├── nextcloud ├── apps2 │ └── .gitkeep └── data │ └── .gitkeep ├── nginx ├── logs │ └── .gitkeep └── run │ └── .gitkeep ├── php ├── logs │ └── .gitkeep ├── run │ └── .gitkeep └── session │ └── .gitkeep ├── usr └── local │ ├── bin │ ├── occ │ ├── run.sh │ └── setup.sh │ └── etc │ ├── php-fpm.conf │ └── php │ ├── conf.d │ ├── apcu.ini │ └── docker-php-ext-opcache.ini │ └── snuffleupagus │ ├── nextcloud-php8.rules │ └── snuffleupagus.ini └── var ├── cache └── nginx │ └── .gitkeep └── log └── nginx └── .gitkeep /.github/workflows/build.yml: -------------------------------------------------------------------------------- 1 | name: build 2 | 3 | on: 4 | workflow_dispatch: 5 | push: 6 | branches: 7 | - master 8 | - version-* 9 | schedule: 10 | # Build the image regularly (each Friday) 11 | - cron: '23 04 * * 5' 12 | 13 | env: 14 | REGISTRY: ghcr.io 15 | IMAGE_NAME: ${{ github.repository_owner }}/nextcloud 16 | 17 | jobs: 18 | build: 19 | name: Build, push & sign 20 | runs-on: "ubuntu-latest" 21 | permissions: 22 | contents: read 23 | packages: write 24 | id-token: write 25 | 26 | steps: 27 | - name: Checkout code 28 | uses: actions/checkout@v2 29 | 30 | - name: Extract version for tags 31 | run: | 32 | BRANCH="${GITHUB_REF#refs/heads/}" 33 | VERSION=$(grep -oP '(?<=NEXTCLOUD_VERSION=).*' Dockerfile) 34 | [ "$BRANCH" = "master" ] && echo "BRANCH_VERSION=latest" >> $GITHUB_ENV 35 | echo "FULL_VERSION=${VERSION:0:7}" >> $GITHUB_ENV 36 | echo "MAJOR_VERSION=${VERSION:0:2}" >> $GITHUB_ENV 37 | 38 | - name: Install cosign 39 | if: github.event_name != 'pull_request' 40 | uses: sigstore/cosign-installer@main 41 | with: 42 | cosign-release: 'v2.2.2' 43 | 44 | - name: Set up Docker Buildx 45 | uses: docker/setup-buildx-action@v1 46 | 47 | - name: Login to registry 48 | if: github.event_name != 'pull_request' 49 | uses: docker/login-action@v1 50 | with: 51 | registry: ${{ env.REGISTRY }} 52 | username: ${{ github.repository_owner }} 53 | password: ${{ secrets.GITHUB_TOKEN }} 54 | 55 | - name: Set Docker metadata 56 | id: meta 57 | uses: docker/metadata-action@v3 58 | with: 59 | images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }} 60 | tags: | 61 | ${{ env.BRANCH_VERSION }} 62 | ${{ env.FULL_VERSION }} 63 | ${{ env.MAJOR_VERSION }} 64 | 65 | - name: Build and push Docker image 66 | id: build-and-push 67 | uses: docker/build-push-action@v2 68 | with: 69 | context: . 70 | push: ${{ github.event_name != 'pull_request' }} 71 | tags: ${{ steps.meta.outputs.tags }} 72 | labels: ${{ steps.meta.outputs.labels }} 73 | 74 | - name: Sign the published Docker image 75 | if: ${{ github.event_name != 'pull_request' }} 76 | env: 77 | COSIGN_EXPERIMENTAL: "true" 78 | run: cosign sign --yes ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}@${{ steps.build-and-push.outputs.digest }} 79 | -------------------------------------------------------------------------------- /.github/workflows/scan.yml: -------------------------------------------------------------------------------- 1 | name: scan 2 | 3 | on: 4 | schedule: 5 | # Scan the image regularly (once a day) 6 | - cron: '45 03 * * *' 7 | 8 | jobs: 9 | build: 10 | name: Scan current image & report results 11 | runs-on: "ubuntu-24.04" 12 | steps: 13 | - name: Checkout code 14 | uses: actions/checkout@v2 15 | 16 | - name: Run Trivy vulnerability scanner 17 | uses: aquasecurity/trivy-action@master 18 | with: 19 | image-ref: 'ghcr.io/${{ github.actor }}/nextcloud' 20 | format: 'template' 21 | template: '@/contrib/sarif.tpl' 22 | output: 'trivy-results.sarif' 23 | severity: 'CRITICAL,HIGH' 24 | vuln-type: "os" 25 | 26 | - name: Upload Trivy scan results to GitHub Security tab 27 | uses: github/codeql-action/upload-sarif@v1 28 | with: 29 | sarif_file: 'trivy-results.sarif' 30 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | # -------------- Build-time variables -------------- 2 | ARG NEXTCLOUD_VERSION=31.0.5 3 | ARG PHP_VERSION=8.3 4 | ARG NGINX_VERSION=1.26 5 | 6 | ARG ALPINE_VERSION=3.21 7 | ARG HARDENED_MALLOC_VERSION=11 8 | ARG SNUFFLEUPAGUS_VERSION=0.10.0 9 | 10 | ARG UID=1000 11 | ARG GID=1000 12 | 13 | # nextcloud-31.0.5.tar.bz2 14 | ARG SHA256_SUM="2228b8f524dcd87f08a2a9281d41b04f5cb500b7624bc8c8e07b8e3039061503" 15 | 16 | # Nextcloud Security (D75899B9A724937A) 17 | ARG GPG_FINGERPRINT="2880 6A87 8AE4 23A2 8372 792E D758 99B9 A724 937A" 18 | # --------------------------------------------------- 19 | 20 | ### Build PHP base 21 | FROM docker.io/library/php:${PHP_VERSION}-fpm-alpine${ALPINE_VERSION} AS base 22 | 23 | ARG SNUFFLEUPAGUS_VERSION 24 | 25 | RUN apk -U upgrade \ 26 | && apk add -t build-deps \ 27 | $PHPIZE_DEPS \ 28 | freetype-dev \ 29 | git \ 30 | gmp-dev \ 31 | icu-dev \ 32 | libjpeg-turbo-dev \ 33 | libpng-dev \ 34 | libwebp-dev \ 35 | libzip-dev \ 36 | openldap-dev \ 37 | postgresql-dev \ 38 | samba-dev \ 39 | imagemagick-dev \ 40 | zlib-dev \ 41 | && apk --no-cache add \ 42 | freetype \ 43 | gmp \ 44 | icu \ 45 | libjpeg-turbo \ 46 | librsvg \ 47 | libpq \ 48 | libpq \ 49 | libwebp \ 50 | libzip \ 51 | libsmbclient \ 52 | openldap \ 53 | libgomp \ 54 | imagemagick \ 55 | zlib \ 56 | && docker-php-ext-configure gd --with-freetype --with-jpeg --with-webp \ 57 | && docker-php-ext-configure ldap \ 58 | && docker-php-ext-install -j "$(nproc)" \ 59 | bcmath \ 60 | exif \ 61 | gd \ 62 | bz2 \ 63 | intl \ 64 | ldap \ 65 | opcache \ 66 | pcntl \ 67 | pdo_mysql \ 68 | pdo_pgsql \ 69 | sysvsem \ 70 | zip \ 71 | gmp \ 72 | && pecl install smbclient \ 73 | && pecl install APCu \ 74 | && pecl install redis \ 75 | && pecl install imagick \ 76 | && docker-php-ext-enable \ 77 | smbclient \ 78 | redis \ 79 | imagick \ 80 | && cd /tmp && git clone --depth 1 --branch v${SNUFFLEUPAGUS_VERSION} https://github.com/jvoisin/snuffleupagus \ 81 | && cd snuffleupagus/src && phpize && ./configure --enable-snuffleupagus && make && make install \ 82 | && apk del build-deps \ 83 | && rm -rf /var/cache/apk/* /tmp/* 84 | 85 | 86 | ### Build Hardened Malloc 87 | ARG ALPINE_VERSION 88 | FROM docker.io/library/alpine:${ALPINE_VERSION} AS build-malloc 89 | 90 | ARG HARDENED_MALLOC_VERSION 91 | ARG CONFIG_NATIVE=false 92 | ARG VARIANT=light 93 | 94 | RUN apk --no-cache add build-base git gnupg && cd /tmp \ 95 | && wget -q https://github.com/thestinger.gpg && gpg --import thestinger.gpg \ 96 | && git clone --depth 1 --branch ${HARDENED_MALLOC_VERSION} https://github.com/GrapheneOS/hardened_malloc \ 97 | && cd hardened_malloc && git verify-tag $(git describe --tags) \ 98 | && make CONFIG_NATIVE=${CONFIG_NATIVE} VARIANT=${VARIANT} 99 | 100 | 101 | ### Fetch nginx 102 | FROM docker.io/library/nginx:${NGINX_VERSION}-alpine AS nginx 103 | 104 | 105 | ### Build Nextcloud (production environemnt) 106 | FROM base AS nextcloud 107 | 108 | COPY --from=nginx /usr/sbin/nginx /usr/sbin/nginx 109 | COPY --from=nginx /etc/nginx /etc/nginx 110 | COPY --from=build-malloc /tmp/hardened_malloc/out-light/libhardened_malloc-light.so /usr/local/lib/ 111 | 112 | ARG NEXTCLOUD_VERSION 113 | ARG SHA256_SUM 114 | ARG GPG_FINGERPRINT 115 | 116 | ARG UID 117 | ARG GID 118 | 119 | ENV UPLOAD_MAX_SIZE=10G \ 120 | APC_SHM_SIZE=128M \ 121 | OPCACHE_MEM_SIZE=128 \ 122 | MEMORY_LIMIT=512M \ 123 | CRON_PERIOD=5m \ 124 | CRON_MEMORY_LIMIT=1g \ 125 | DB_TYPE=sqlite3 \ 126 | DOMAIN=localhost \ 127 | PHP_HARDENING=true \ 128 | LD_PRELOAD="/usr/local/lib/libhardened_malloc-light.so" 129 | 130 | RUN apk --no-cache add \ 131 | gnupg \ 132 | pcre2 \ 133 | s6 \ 134 | && NEXTCLOUD_TARBALL="nextcloud-${NEXTCLOUD_VERSION}.tar.bz2" && cd /tmp \ 135 | && wget -q https://download.nextcloud.com/server/releases/${NEXTCLOUD_TARBALL} \ 136 | && wget -q https://download.nextcloud.com/server/releases/${NEXTCLOUD_TARBALL}.asc \ 137 | && wget -q https://nextcloud.com/nextcloud.asc \ 138 | && echo "Verifying both integrity and authenticity of ${NEXTCLOUD_TARBALL}..." \ 139 | && CHECKSUM_STATE=$(echo -n $(echo "${SHA256_SUM} ${NEXTCLOUD_TARBALL}" | sha256sum -c) | tail -c 2) \ 140 | && if [ "${CHECKSUM_STATE}" != "OK" ]; then echo "Error: checksum does not match" && exit 1; fi \ 141 | && gpg --import nextcloud.asc \ 142 | && FINGERPRINT="$(LANG=C gpg --verify ${NEXTCLOUD_TARBALL}.asc ${NEXTCLOUD_TARBALL} 2>&1 \ 143 | | sed -n "s#Primary key fingerprint: \(.*\)#\1#p")" \ 144 | && if [ -z "${FINGERPRINT}" ]; then echo "Error: invalid GPG signature!" && exit 1; fi \ 145 | && if [ "${FINGERPRINT}" != "${GPG_FINGERPRINT}" ]; then echo "Error: wrong GPG fingerprint" && exit 1; fi \ 146 | && echo "All seems good, now unpacking ${NEXTCLOUD_TARBALL}..." \ 147 | && mkdir /nextcloud && tar xjf ${NEXTCLOUD_TARBALL} --strip 1 -C /nextcloud \ 148 | && apk del gnupg && rm -rf /tmp/* /root/.gnupg \ 149 | && adduser -g ${GID} -u ${UID} --disabled-password --gecos "" nextcloud \ 150 | && chown -R nextcloud:nextcloud /nextcloud/config 151 | 152 | COPY --chown=nextcloud:nextcloud rootfs / 153 | 154 | RUN chmod +x /usr/local/bin/* /etc/s6.d/*/* /etc/s6.d/.s6-svscan/* 155 | 156 | USER nextcloud 157 | 158 | WORKDIR /nextcloud 159 | 160 | VOLUME /data /nextcloud/config /nextcloud/apps2 /nextcloud/themes 161 | 162 | EXPOSE 8888 163 | 164 | LABEL org.opencontainers.image.description="All-in-one Nextcloud image, based on Alpine Linux" \ 165 | org.opencontainers.image.version="${NEXTCLOUD_VERSION}" \ 166 | org.opencontainers.image.authors="Hoellen " \ 167 | org.opencontainers.image.source="https://github.com/hoellen/docker-nextcloud" 168 | 169 | CMD ["run.sh"] 170 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # hoellen/nextcloud 2 | *The self-hosted productivity platform that keeps you in control.* 3 | 4 | Nextcloud [official website](https://nextcloud.com/) and [source code](https://github.com/nextcloud). 5 | 6 | ## About 7 | This non-official image is intended as an **all-in-one** (as in monolithic) Nextcloud **production** image. If you're not sure you want this image, you should probably use [the official image](https://hub.docker.com/r/nextcloud). The main goal is to provide an easy-to-use image with decent security standards. This repository is mainly based on [Wondefall/docker-nextcloud](https://github.com/Wonderfall/docker-nextcloud). 8 | 9 | Check out Nextcloud [official website](https://nextcloud.com/) and [source code](https://github.com/nextcloud). 10 | 11 | ___ 12 | 13 | * [Features](#features) 14 | * [Security](#security) 15 | * [Tags](#tags) 16 | * [Build-time variables](#build-time-variables) 17 | * [Environment variables](#environment-variables) 18 | * [Runtime](#runtime) 19 | * [Startup](#startup) 20 | * [Volumes](#volumes) 21 | * [Ports](#ports) 22 | * [Migration](#migration) 23 | * [Usage](#usage) 24 | 25 | ## Features 26 | 27 | - Based on [Alpine Linux](https://alpinelinux.org/). 28 | - Fetching PHP/nginx from their official images. 29 | - **Rootless**: no privilege at any time, even at startup. 30 | - Uses [s6](https://skarnet.org/software/s6/) as a lightweight process supervisor. 31 | - Supports MySQL/MariaDB, PostgresQL and SQLite3 database backends. 32 | - Includes OPcache and APCu for improved caching & performance, also supports redis. 33 | - Tarball integrity & authenticity checked during build process. 34 | - Includes **hardened_malloc**, [a hardened memory allocator](https://github.com/GrapheneOS/hardened_malloc). 35 | - Includes **Snuffleupagus**, [a PHP security module](https://github.com/jvoisin/snuffleupagus). 36 | - Includes a simple **built-in cron** system. 37 | - Much easier to maintain thanks to multi-stages build. 38 | - Does not include imagick, samba, etc. by default. 39 | 40 | You're free to make your own image based on this one if you want a specific feature. Uncommon features won't be included as they can increase attack surface: this image intends to stay **minimal**, but **functional enough** to cover basic needs. 41 | 42 | ## Security 43 | 44 | Don't run random images from random dudes on the Internet. Ideally, you want to maintain and build it yourself. 45 | 46 | - **Images are scanned every day** by [Trivy](https://github.com/aquasecurity/trivy) for OS vulnerabilities. Known vulnerabilities will be automatically uploaded to [GitHub Security Lab](https://github.com/Wonderfall/docker-nextcloud/security/code-scanning) for full transparency. This also warns me if I have to take action to fix a vulnerability. 47 | - **Latest tag/version is automatically built weekly**, so you should often update your images regardless if you're already using the latest Nextcloud version. 48 | - **Build production images without cache** (use `docker build --no-cache` for instance) if you want to build your images manually. Latest dependencies will hence be used instead of outdated ones due to a cached layer. 49 | - **A security module for PHP called [Snuffleupagus](https://github.com/jvoisin/snuffleupagus) is used by default**. This module aims at killing entire bug and security exploit classes (including weak PRNG, file-upload based code execution), thus raising the cost of attacks. For now we're using a configuration file derived from [the default one](https://github.com/jvoisin/snuffleupagus/blob/master/config/default_php8.rules), with some explicit exceptions related to Nextcloud. This configuration file is tested and shouldn't break basic functionality, but it can cause issues in specific and untested use cases: if that happens to you, get logs from either `syslog` or `/nginx/logs/error.log` inside the container, and [open an issue](https://github.com/hoellen/docker-nextcloud/issues). You can also disable the security module altogether by changing the `PHP_HARDENING` environment variable to `false` before recreating the container. 50 | - **Images are signed with the GitHub-provided OIDC token in Actions** using the experimental "keyless" signing feature provided by [cosign](https://github.com/sigstore/cosign). You can verify the image signature using `cosign` as well: 51 | 52 | ``` 53 | COSIGN_EXPERIMENTAL=true cosign verify ghcr.io/hoellen/nextcloud 54 | ``` 55 | 56 | Verifying the signature isn't a requirement, and might not be as seamless as using *Docker Content Trust* (which is not supported by GitHub's OCI registry). However, it's strongly recommended to do so in a sensitive environment to ensure the authenticity of the images and further limit the risk of supply chain attacks. 57 | 58 | ## Tags 59 | 60 | - `latest` : latest Nextcloud version 61 | - `x` : latest Nextcloud x.x (e.g. `31`) 62 | - `x.x.x` : Nextcloud x.x.x (e.g. `31.0.0`) 63 | 64 | You can always have a glance [here](https://github.com/users/hoellen/packages/container/package/nextcloud). 65 | Only the **latest stable version** will be maintained by myself. 66 | 67 | *Note: automated builds only target `linux/amd64` (x86_64). There is no technical reason preventing the image to be built for `arm64` (in fact you can build it yourself), but GitHub Actions runners are limited in memory, and this limit makes it currently impossible to target both platforms.* 68 | 69 | ## Build-time variables 70 | 71 | | Variable | Description | Default | 72 | | --------------------------- | -------------------------------------- | ------------------ | 73 | | **NEXTCLOUD_VERSION** | version of Nextcloud | * | 74 | | **ALPINE_VERSION** | version of Alpine Linux | * | 75 | | **PHP_VERSION** | version of PHP | * | 76 | | **NGINX_VERSION** | version of nginx | * | 77 | | **HARDENED_MALLOC_VERSION** | version of hardened_malloc | * | 78 | | **SNUFFLEUPAGUS_VERSION** | version of Snuffleupagus (php ext) | * | 79 | | **SHA256_SUM** | checksum of Nextcloud tarball (sha256) | * | 80 | | **GPG_FINGERPRINT** | fingerprint of Nextcloud GPG key | * | 81 | | **UID** | user id | 1000 | 82 | | **GID** | group id | 1000 | 83 | | **CONFIG_NATIVE** | native code for hardened_malloc | false | 84 | | **VARIANT** | variant of hardened_malloc (see repo) | light | 85 | 86 | *\* latest known available, likely to change regularly* 87 | 88 | For convenience they were put at [the very top of the Dockerfile](https://github.com/Wonderfall/docker-nextcloud/blob/main/Dockerfile#L1-L13) and their usage should be quite explicit if you intend to build this image yourself. If you intend to change `NEXTCLOUD_VERSION`, change `SHA256_SUM` accordingly. 89 | 90 | ## Environment variables 91 | 92 | ### Runtime 93 | 94 | | Variable | Description | Default | 95 | | ------------------------- | --------------------------- | ------------------ | 96 | | **UPLOAD_MAX_SIZE** | file upload maximum size | 10G | 97 | | **APC_SHM_SIZE** | apc shared memory size | 128M | 98 | | **OPCACHE_MEM_SIZE** | opcache available memory | 128M | 99 | | **MEMORY_LIMIT** | max php command mem usage | 512M | 100 | | **CRON_PERIOD** | cron time interval (min.) | 5m | 101 | | **CRON_MEMORY_LIMIT** | cron max memory usage | 1G | 102 | | **DB_TYPE** | sqlite3, mysql, pgsql | sqlite3 | 103 | | **DOMAIN** | host domain | localhost | 104 | | **PHP_HARDENING** | enables snuffleupagus | true | 105 | 106 | Leave them at default if you're not sure what you're doing. 107 | 108 | ### Startup 109 | 110 | | Variable | Description | 111 | | ------------------------- | --------------------------- | 112 | | **ADMIN_USER** | admin username | 113 | | **ADMIN_PASSWORD** | admin password | 114 | | **DB_TYPE** | sqlite3, mysql, pgsql | 115 | | **DB_NAME** | name of the database | 116 | | **DB_USER** | name of the database user | 117 | | **DB_PASSWORD** | password of the db user | 118 | | **DB_HOST** | database host | 119 | 120 | `ADMIN_USER` and `ADMIN_PASSWORD` are optional and mainly for niche purposes. Obviously, avoid clear text passwords. Once `setup.sh` has run for the first time, these variables can be removed. You should then edit `/nextcloud/config/config.php` directly if you want to change something in your configuration. 121 | 122 | The usage of [Docker secrets](https://docs.docker.com/engine/swarm/secrets/) will be considered in the future, but `config.php` already covers quite a lot. 123 | 124 | ## Volumes 125 | 126 | | Variable | Description | 127 | | ------------------------- | -------------------------- | 128 | | **/data** | data files | 129 | | **/nextcloud/config** | config files | 130 | | **/nextcloud/apps2** | 3rd-party apps | 131 | | **/nextcloud/themes** | custom themes | 132 | | **/php/session** | PHP session files | 133 | 134 | *Note: mounting `/php/session` isn't required but could be desirable in some circumstances.* 135 | 136 | ## Ports 137 | 138 | | Port | Use | 139 | | ------------------------- | -------------------------- | 140 | | **8888** (tcp) | Nextcloud web | 141 | 142 | A reverse proxy like [Traefik](https://doc.traefik.io/traefik/) or [Caddy](https://caddyserver.com/) can be used, and you should consider: 143 | - Redirecting all HTTP traffic to HTTPS 144 | - Setting the [HSTS header](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Strict-Transport-Security) correctly 145 | 146 | ## Migration 147 | 148 | From now on you'll need to make sure all volumes have proper permissions. The default UID/GID is now 1000, so you'll need to build the image yourself if you want to change that, or you can just change the actual permissions of the volumes using `chown -R 1000:1000`. The flexibility provided by the legacy image came at some cost (performance & security), therefore this feature won't be provided anymore. 149 | 150 | Other changes that should be reflected in your configuration files: 151 | - `/config` volume is now `/nextcloud/config` 152 | - `/apps2` volume is now `/nextcloud/apps2` 153 | - `ghcr.io/hoellen/nextcloud` is the new image location 154 | 155 | You should edit your `docker-compose.yml` and `config.php` accordingly. 156 | 157 | ## Usage 158 | 159 | *To do.* 160 | -------------------------------------------------------------------------------- /SECURITY.md: -------------------------------------------------------------------------------- 1 | # Security Policy 2 | 3 | ## Supported versions 4 | 5 | All versions of the Nextcloud community version which still receive updates will be supported 6 | and will receive the minor version updates and security patches. 7 | 8 | | Version | Supported | 9 | | ------- | ------------------ | 10 | | 31. x | :white_check_mark: | 11 | | 30. x | :white_check_mark: | 12 | | 29. x | :negative_squared_cross_mark: | 13 | | 28. x | :negative_squared_cross_mark: | 14 | | 27. x | :negative_squared_cross_mark: | 15 | | 26. x | :negative_squared_cross_mark: | 16 | | 25. x | :negative_squared_cross_mark: | 17 | | 24. x | :negative_squared_cross_mark: | 18 | | 23. x | :negative_squared_cross_mark: | 19 | | 22. x | :negative_squared_cross_mark: | 20 | 21 | Please update to the latest version available. Major migrations are always tested before being pushed. 22 | An up-to-date list of the currently maintained Nextcloud versions can also be found in the [Nextcloud Repository Wiki](https://github.com/nextcloud/server/wiki/Maintenance-and-Release-Schedule). 23 | 24 | ## Automated vulnerability scanning 25 | 26 | Uploaded images are regularly scanned for [OS vulnerabilities](https://github.com/Wonderfall/docker-nextcloud/security/code-scanning). 27 | 28 | ## Reporting a vulnerability 29 | 30 | *Upstream* vulnerabilities should be reported to *upstream* projects according to their own security policies. 31 | 32 | Regarding vulnerabilities specific to this project: 33 | - Faulty configuration files 34 | - Unsafe defaults 35 | - Dependencies security updates 36 | 37 | Those can be disclosed in private to `dev@hoellen.eu`. 38 | -------------------------------------------------------------------------------- /rootfs/data/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hoellen/docker-nextcloud/42b36e3c9b67afe463c3818c41a07c8a74f5b0e4/rootfs/data/.gitkeep -------------------------------------------------------------------------------- /rootfs/etc/nginx/conf.d/default.conf: -------------------------------------------------------------------------------- 1 | map $http_x_forwarded_port $nc_port { 2 | default "$http_x_forwarded_port"; 3 | '' "$server_port"; 4 | } 5 | 6 | map $http_x_forwarded_proto $nc_proto { 7 | default "$http_x_forwarded_proto"; 8 | '' "$scheme"; 9 | } 10 | 11 | server { 12 | listen 8888; 13 | root /nextcloud; 14 | 15 | fastcgi_buffers 64 4K; 16 | fastcgi_hide_header X-Powered-By; 17 | large_client_header_buffers 4 16k; 18 | 19 | add_header Referrer-Policy "no-referrer" always; 20 | add_header X-Content-Type-Options "nosniff" always; 21 | add_header X-Frame-Options "SAMEORIGIN" always; 22 | add_header X-Permitted-Cross-Domain-Policies "none" always; 23 | add_header X-Robots-Tag "noindex, nofollow" always; 24 | add_header X-XSS-Protection "0" always; 25 | 26 | location = /robots.txt { 27 | allow all; 28 | log_not_found off; 29 | access_log off; 30 | } 31 | 32 | location ^~ /.well-known { 33 | location = /.well-known/carddav { return 301 $nc_proto://$host/remote.php/dav/; } 34 | location = /.well-known/caldav { return 301 $nc_proto://$host/remote.php/dav/; } 35 | location ^~ /.well-known { return 301 $nc_proto://$host/index.php$uri; } 36 | try_files $uri $uri/ =404; 37 | } 38 | 39 | location / { 40 | rewrite ^ /index.php$uri; 41 | } 42 | 43 | location ~ ^/(?:build|tests|config|lib|3rdparty|templates|data)(?:$|/) { 44 | return 404; 45 | } 46 | 47 | location ~ ^/(?:\.|autotest|occ|issue|indie|db_|console) { 48 | return 404; 49 | } 50 | 51 | location ~ ^\/(?:index|remote|public|cron|core\/ajax\/update|status|ocs\/v[12]|updater\/.+|ocs-provider\/.+|.+\/richdocumentscode\/proxy)\.php(?:$|\/) { 52 | include /etc/nginx/fastcgi_params; 53 | fastcgi_split_path_info ^(.+\.php)(/.*)$; 54 | fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; 55 | fastcgi_param PATH_INFO $fastcgi_path_info; 56 | fastcgi_param modHeadersAvailable true; 57 | fastcgi_param front_controller_active true; 58 | fastcgi_pass unix:/php/run/php-fpm.sock; 59 | fastcgi_intercept_errors on; 60 | fastcgi_request_buffering off; 61 | fastcgi_read_timeout 1200; 62 | } 63 | 64 | location ~ ^\/(?:updater|ocs-provider)(?:$|\/) { 65 | try_files $uri/ =404; 66 | index index.php; 67 | } 68 | 69 | location ~ \.(?:css|js|mjs|svg|gif|png|jpg|ico|wasm|tflite|map|ogg|flac)$ { 70 | try_files $uri /index.php$uri$is_args$args; 71 | expires 6M; 72 | access_log off; 73 | } 74 | 75 | location ~ \.(otf|woff2)?$ { 76 | try_files $uri /index.php$uri$is_args$args; 77 | expires 7d; 78 | access_log off; 79 | } 80 | 81 | location ~ \.(?:png|html|ttf|ico|jpg|jpeg|bcmap)$ { 82 | try_files $uri /index.php$uri$is_args$args; 83 | access_log off; 84 | } 85 | } 86 | -------------------------------------------------------------------------------- /rootfs/etc/nginx/nginx.conf: -------------------------------------------------------------------------------- 1 | worker_processes auto; 2 | pid /nginx/run/nginx.pid; 3 | daemon off; 4 | 5 | events { 6 | worker_connections 2048; 7 | use epoll; 8 | } 9 | 10 | http { 11 | include /etc/nginx/mime.types; 12 | # Add .mjs as a file extension for javascript 13 | # https://github.com/nextcloud/server/pull/36057 14 | types { 15 | application/javascript mjs; 16 | } 17 | default_type application/octet-stream; 18 | 19 | access_log /nginx/logs/access.log combined; 20 | error_log /nginx/logs/error.log error; 21 | 22 | client_max_body_size ; 23 | 24 | aio threads; 25 | sendfile on; 26 | keepalive_timeout 15; 27 | keepalive_disable msie6; 28 | keepalive_requests 100; 29 | tcp_nopush on; 30 | tcp_nodelay on; 31 | server_tokens off; 32 | 33 | gzip off; 34 | 35 | include /etc/nginx/conf.d/*.conf; 36 | } 37 | -------------------------------------------------------------------------------- /rootfs/etc/s6.d/.s6-svscan/finish: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | exit 0 4 | -------------------------------------------------------------------------------- /rootfs/etc/s6.d/cron/run: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | while true; do 4 | php -d memory_limit= -f /nextcloud/cron.php 5 | sleep 6 | done 7 | -------------------------------------------------------------------------------- /rootfs/etc/s6.d/nginx/run: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | exec nginx 3 | -------------------------------------------------------------------------------- /rootfs/etc/s6.d/php/run: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | exec php-fpm 3 | -------------------------------------------------------------------------------- /rootfs/nextcloud/apps2/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hoellen/docker-nextcloud/42b36e3c9b67afe463c3818c41a07c8a74f5b0e4/rootfs/nextcloud/apps2/.gitkeep -------------------------------------------------------------------------------- /rootfs/nextcloud/data/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hoellen/docker-nextcloud/42b36e3c9b67afe463c3818c41a07c8a74f5b0e4/rootfs/nextcloud/data/.gitkeep -------------------------------------------------------------------------------- /rootfs/nginx/logs/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hoellen/docker-nextcloud/42b36e3c9b67afe463c3818c41a07c8a74f5b0e4/rootfs/nginx/logs/.gitkeep -------------------------------------------------------------------------------- /rootfs/nginx/run/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hoellen/docker-nextcloud/42b36e3c9b67afe463c3818c41a07c8a74f5b0e4/rootfs/nginx/run/.gitkeep -------------------------------------------------------------------------------- /rootfs/php/logs/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hoellen/docker-nextcloud/42b36e3c9b67afe463c3818c41a07c8a74f5b0e4/rootfs/php/logs/.gitkeep -------------------------------------------------------------------------------- /rootfs/php/run/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hoellen/docker-nextcloud/42b36e3c9b67afe463c3818c41a07c8a74f5b0e4/rootfs/php/run/.gitkeep -------------------------------------------------------------------------------- /rootfs/php/session/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hoellen/docker-nextcloud/42b36e3c9b67afe463c3818c41a07c8a74f5b0e4/rootfs/php/session/.gitkeep -------------------------------------------------------------------------------- /rootfs/usr/local/bin/occ: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | php -d memory_limit= -f /nextcloud/occ "$@" 3 | -------------------------------------------------------------------------------- /rootfs/usr/local/bin/run.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # Apply environment variables settings 4 | sed -i -e "s//$APC_SHM_SIZE/g" /usr/local/etc/php/conf.d/apcu.ini \ 5 | -e "s//$OPCACHE_MEM_SIZE/g" /usr/local/etc/php/conf.d/docker-php-ext-opcache.ini \ 6 | -e "s//$CRON_MEMORY_LIMIT/g" /etc/s6.d/cron/run \ 7 | -e "s//$CRON_PERIOD/g" /etc/s6.d/cron/run \ 8 | -e "s//$MEMORY_LIMIT/g" /usr/local/bin/occ \ 9 | -e "s//$UPLOAD_MAX_SIZE/g" /etc/nginx/nginx.conf /usr/local/etc/php-fpm.conf \ 10 | -e "s//$MEMORY_LIMIT/g" /usr/local/etc/php-fpm.conf 11 | 12 | # Enable Snuffleupagus 13 | if [ "$PHP_HARDENING" == "true" ] && [ ! -f /usr/local/etc/php/conf.d/snuffleupagus.ini ]; then 14 | echo "Enabling Snuffleupagus..." 15 | cp /usr/local/etc/php/snuffleupagus/* /usr/local/etc/php/conf.d 16 | fi 17 | 18 | # Check if database is available 19 | if [ -n "${DB_TYPE}" ] && [ "${DB_TYPE}" != "sqlite3" ]; then 20 | DB_PORT=${DB_PORT:-$( [ "${DB_TYPE}" = "pgsql" ] && echo 5432 || echo 3306 )} 21 | until nc -z "${DB_HOST:-nextcloud-db}" "${DB_PORT}" 22 | do 23 | echo "waiting for the database container..." 24 | sleep 1 25 | done 26 | fi 27 | 28 | # If new install, run setup 29 | if [ ! -f /nextcloud/config/config.php ]; then 30 | touch /nextcloud/config/CAN_INSTALL 31 | /usr/local/bin/setup.sh 32 | else 33 | occ upgrade 34 | fi 35 | 36 | # Run processes 37 | exec /usr/bin/s6-svscan /etc/s6.d 38 | -------------------------------------------------------------------------------- /rootfs/usr/local/bin/setup.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | CONFIGFILE=/nextcloud/config/config.php 4 | 5 | # Create an initial configuration file. 6 | instanceid=oc$(openssl rand -hex 6 | head -c 10) 7 | 8 | cat > $CONFIGFILE < '/data', 12 | 13 | "apps_paths" => array ( 14 | 0 => array ( 15 | "path" => "/nextcloud/apps", 16 | "url" => "/apps", 17 | "writable" => false, 18 | ), 19 | 1 => array ( 20 | "path" => "/nextcloud/apps2", 21 | "url" => "/apps2", 22 | "writable" => true, 23 | ), 24 | ), 25 | 26 | 'memcache.local' => '\OC\Memcache\APCu', 27 | 28 | 'instanceid' => '$instanceid', 29 | ); 30 | ?> 31 | EOF 32 | 33 | # Create an auto-configuration file to fill in database settings 34 | adminpassword=$(dd if=/dev/urandom bs=1 count=40 2>/dev/null | sha1sum | fold -w 30 | head -n 1) 35 | cat > /nextcloud/config/autoconfig.php < '/data', 40 | 'dbtype' => '${DB_TYPE:-sqlite3}', 41 | 'dbname' => '${DB_NAME:-nextcloud}', 42 | 'dbuser' => '${DB_USER:-nextcloud}', 43 | 'dbpass' => '${DB_PASSWORD:-password}', 44 | 'dbhost' => '${DB_HOST:-nextcloud-db}', 45 | 'dbtableprefix' => 'oc_', 46 | EOF 47 | if [[ ! -z "$ADMIN_USER" ]]; then 48 | cat >> /nextcloud/config/autoconfig.php < '${ADMIN_USER}', 50 | 'adminpass' => '${ADMIN_PASSWORD}', 51 | EOF 52 | fi 53 | cat >> /nextcloud/config/autoconfig.php < 56 | EOF 57 | 58 | echo "Starting automatic configuration..." 59 | # Execute setup 60 | (cd /nextcloud; php index.php &>/dev/null) 61 | echo "Automatic configuration finished." 62 | 63 | # Update config.php 64 | CONFIG_TEMP=$(/bin/mktemp) 65 | php < $CONFIG_TEMP && mv $CONFIG_TEMP $CONFIGFILE 66 | 79 | EOF 80 | 81 | sed -i "s/localhost/$DOMAIN/g" $CONFIGFILE 82 | 83 | # Setup is finished, no need for first run wizard 84 | if [[ ! -z "$ADMIN_USER" ]]; then 85 | occ app:disable firstrunwizard 86 | fi 87 | -------------------------------------------------------------------------------- /rootfs/usr/local/etc/php-fpm.conf: -------------------------------------------------------------------------------- 1 | [global] 2 | daemonize = no 3 | error_log = /php/logs/error.log 4 | 5 | [www] 6 | listen = /php/run/php-fpm.sock 7 | pm = dynamic 8 | pm.max_children = 25 9 | pm.start_servers = 10 10 | pm.min_spare_servers = 5 11 | pm.max_spare_servers = 20 12 | pm.max_requests = 498 13 | chdir = / 14 | request_terminate_timeout = 0 15 | env[PATH] = /usr/local/bin:/usr/bin:/bin 16 | php_admin_value[post_max_size] = 17 | php_admin_value[upload_max_filesize] = 18 | php_admin_value[max_execution_time] = 10800 19 | php_admin_value[max_input_time] = 3600 20 | php_admin_value[expose_php] = Off 21 | php_admin_value[memory_limit] = 22 | php_admin_value[session.save_path] = "/php/session" 23 | -------------------------------------------------------------------------------- /rootfs/usr/local/etc/php/conf.d/apcu.ini: -------------------------------------------------------------------------------- 1 | extension=apcu.so 2 | apc.enabled=1 3 | apc.shm_size= 4 | apc.ttl=7200 5 | apc.enable_cli=1 6 | -------------------------------------------------------------------------------- /rootfs/usr/local/etc/php/conf.d/docker-php-ext-opcache.ini: -------------------------------------------------------------------------------- 1 | zend_extension=opcache.so 2 | opcache.enable=1 3 | opcache.enable_cli=1 4 | opcache.fast_shutdown=1 5 | opcache.memory_consumption= 6 | opcache.interned_strings_buffer=16 7 | opcache.max_accelerated_files=10000 8 | opcache.revalidate_freq=60 9 | opcache.jit=disable 10 | opcache.jit_buffer_size=0 11 | -------------------------------------------------------------------------------- /rootfs/usr/local/etc/php/snuffleupagus/nextcloud-php8.rules: -------------------------------------------------------------------------------- 1 | # This is the default configuration file for Snuffleupagus (https://snuffleupagus.rtfd.io), 2 | # for php8. 3 | # It contains "reasonable" defaults that won't break your websites, 4 | # and a lot of commented directives that you can enable if you want to 5 | # have a better protection. 6 | 7 | # Harden the PRNG 8 | sp.harden_random.enable(); 9 | 10 | # Disabled XXE 11 | #sp.xxe_protection.enable(); 12 | 13 | # Global configuration variables 14 | # sp.global.secret_key("YOU _DO_ NEED TO CHANGE THIS WITH SOME RANDOM CHARACTERS."); 15 | 16 | # Globally activate strict mode 17 | # https://www.php.net/manual/en/language.types.declarations.php#language.types.declarations.strict 18 | sp.global_strict.enable(); 19 | 20 | # Prevent unserialize-related exploits 21 | # sp.unserialize_hmac.enable(); 22 | 23 | # Only allow execution of read-only files. This is a low-hanging fruit that you should enable. 24 | # sp.readonly_exec.enable(); 25 | 26 | # PHP has a lot of wrappers, most of them aren't usually useful, you should 27 | # only enable the ones you're using. 28 | # sp.wrappers_whitelist.list("file,php,phar"); 29 | 30 | # Prevent sloppy comparisons. 31 | sp.sloppy_comparison.enable(); 32 | 33 | # Use SameSite on session cookie 34 | # https://snuffleupagus.readthedocs.io/features.html#protection-against-cross-site-request-forgery 35 | sp.cookie.name("PHPSESSID").samesite("lax"); 36 | 37 | # Nextcloud whitelist (tested with Nextcloud 27.0.1) 38 | sp.disable_function.function("function_exists").param("function").value("proc_open").filename("/nextcloud/3rdparty/symfony/console/Terminal.php").allow(); 39 | sp.disable_function.function("function_exists").param("function").value("exec").filename("/nextcloud/lib/private/legacy/OC_Helper.php").allow(); 40 | sp.disable_function.function("function_exists").param("function").value("exec").filename("/nextcloud/lib/public/Util.php").allow(); 41 | sp.disable_function.function("proc_open").filename("/nextcloud/3rdparty/symfony/console/Terminal.php").allow(); 42 | sp.disable_function.function("ini_set").param("option").value_r("display_errors").filename("/nextcloud/lib/base.php").allow(); 43 | sp.disable_function.function("ini_get").param("option").value("open_basedir").filename("/nextcloud/3rdparty/bantu/ini-get-wrapper/src/IniGetWrapper.php").allow(); 44 | sp.disable_function.function("ini_get").param("option").value_r("suhosin").filename("/nextcloud/3rdparty/bantu/ini-get-wrapper/src/IniGetWrapper.php").allow(); 45 | sp.disable_function.function("ini_get").param("option").value("open_basedir").filename("/nextcloud/apps2/twofactor_webauthn/vendor/symfony/process/ExecutableFinder.php").allow(); 46 | sp.disable_function.function("ini_get").param("option").value("open_basedir").filename("/nextcloud/3rdparty/symfony/process/ExecutableFinder.php").allow(); 47 | sp.disable_function.function("ini_get").param("option").value("allow_url_fopen").filename("/nextcloud/3rdparty/guzzlehttp/guzzle/src/Utils.php").allow(); 48 | sp.disable_function.function("exec").param("command").value("apachectl -M | grep mpm").filename("/nextcloud/apps2/spreed/lib/Settings/Admin/AdminSettings.php").allow(); 49 | 50 | # Nextcloud inherently enables XXE-Protection since 27.0.1, therefore, drop setting a new external entity loader 51 | sp.disable_function.function("libxml_set_external_entity_loader").filename("/nextcloud/lib/base.php").allow(); 52 | sp.disable_function.function("libxml_set_external_entity_loader").drop(); 53 | 54 | # Harden the `chmod` function (0777 (oct = 511, 0666 = 438) 55 | sp.disable_function.function("chmod").param("permissions").value("438").drop(); 56 | sp.disable_function.function("chmod").param("permissions").value("511").drop(); 57 | 58 | # Prevent various `mail`-related vulnerabilities 59 | sp.disable_function.function("mail").param("additional_parameters").value_r("\\-").drop(); 60 | 61 | # Since it's now burned, me might as well mitigate it publicly 62 | sp.disable_function.function("putenv").param("assignment").value_r("LD_").drop() 63 | 64 | # This one was burned in Nov 2019 - https://gist.github.com/LoadLow/90b60bd5535d6c3927bb24d5f9955b80 65 | sp.disable_function.function("putenv").param("assignment").value_r("GCONV_").drop() 66 | 67 | # Since people are stupid enough to use `extract` on things like $_GET or $_POST, we might as well mitigate this vector 68 | sp.disable_function.function("extract").param("array").value_r("^_").drop() 69 | sp.disable_function.function("extract").param("flags").value("0").drop() 70 | 71 | # This is also burned: 72 | # ini_set('open_basedir','..');chdir('..');…;chdir('..');ini_set('open_basedir','/');echo(file_get_contents('/etc/passwd')); 73 | # Since we have no way of matching on two parameters at the same time, we're 74 | # blocking calls to open_basedir altogether: nobody is using it via ini_set anyway. 75 | # Moreover, there are non-public bypasses that are also using this vector ;) 76 | sp.disable_function.function("ini_set").param("option").value_r("open_basedir").drop() 77 | 78 | # Prevent various `include`-related vulnerabilities 79 | sp.disable_function.function("require_once").value_r("\.(inc|phtml|php)$").allow(); 80 | sp.disable_function.function("include_once").value_r("\.(inc|phtml|php)$").allow(); 81 | sp.disable_function.function("require").value_r("\.(inc|phtml|php)$").allow(); 82 | sp.disable_function.function("include").value_r("\.(inc|phtml|php)$").allow(); 83 | sp.disable_function.function("require_once").drop() 84 | sp.disable_function.function("include_once").drop() 85 | sp.disable_function.function("require").drop() 86 | sp.disable_function.function("include").drop() 87 | 88 | # Prevent `system`-related injections 89 | sp.disable_function.function("system").param("command").value_r("[$|;&`\\n\\(\\)\\\\]").drop(); 90 | sp.disable_function.function("shell_exec").param("command").value_r("[$|;&`\\n\\(\\)\\\\]").drop(); 91 | sp.disable_function.function("exec").param("command").value_r("[$|;&`\\n\\(\\)\\\\]").drop(); 92 | sp.disable_function.function("proc_open").param("command").value_r("[$|;&`\\n\\(\\)\\\\]").drop(); 93 | 94 | # Prevent runtime modification of interesting things 95 | sp.disable_function.function("ini_set").param("option").value("assert.active").drop(); 96 | sp.disable_function.function("ini_set").param("option").value("zend.assertions").drop(); 97 | sp.disable_function.function("ini_set").param("option").value("memory_limit").drop(); 98 | sp.disable_function.function("ini_set").param("option").value("include_path").drop(); 99 | sp.disable_function.function("ini_set").param("option").value("open_basedir").drop(); 100 | 101 | # Detect some backdoors via environment recon 102 | sp.disable_function.function("ini_get").param("option").value("allow_url_fopen").drop(); 103 | sp.disable_function.function("ini_get").param("option").value("open_basedir").drop(); 104 | sp.disable_function.function("ini_get").param("option").value_r("suhosin").drop(); 105 | sp.disable_function.function("function_exists").param("function").value("eval").drop(); 106 | sp.disable_function.function("function_exists").param("function").value("exec").drop(); 107 | sp.disable_function.function("function_exists").param("function").value("system").drop(); 108 | sp.disable_function.function("function_exists").param("function").value("shell_exec").drop(); 109 | sp.disable_function.function("function_exists").param("function").value("proc_open").drop(); 110 | sp.disable_function.function("function_exists").param("function").value("passthru").drop(); 111 | sp.disable_function.function("is_callable").param("value").value("eval").drop(); 112 | sp.disable_function.function("is_callable").param("value").value("exec").drop(); 113 | sp.disable_function.function("is_callable").param("value").value("system").drop(); 114 | sp.disable_function.function("is_callable").param("value").value("shell_exec").drop(); 115 | sp.disable_function.function("is_callable").param("value").value("proc_open").drop(); 116 | sp.disable_function.function("is_callable").param("value").value("passthru").drop(); 117 | 118 | # Ghetto error-based sqli detection 119 | # sp.disable_function.function("mysql_query").ret("FALSE").drop(); 120 | # sp.disable_function.function("mysqli_query").ret("FALSE").drop(); 121 | # sp.disable_function.function("PDO::query").ret("FALSE").drop(); 122 | 123 | # Ensure that certificates are properly verified 124 | sp.disable_function.function("curl_setopt").param("value").value("1").allow(); 125 | sp.disable_function.function("curl_setopt").param("value").value("2").allow(); 126 | # `81` is SSL_VERIFYHOST and `64` SSL_VERIFYPEER 127 | sp.disable_function.function("curl_setopt").param("option").value("64").drop().alias("Please don't turn CURLOPT_SSL_VERIFYCLIENT off."); 128 | sp.disable_function.function("curl_setopt").param("option").value("81").drop().alias("Please don't turn CURLOPT_SSL_VERIFYHOST off."); 129 | 130 | # File upload 131 | sp.disable_function.function("move_uploaded_file").param("to").value_r("\\.ph").drop(); 132 | sp.disable_function.function("move_uploaded_file").param("to").value_r("\\.ht").drop(); 133 | 134 | # Logging lockdown 135 | sp.disable_function.function("ini_set").param("option").value_r("error_log").drop() 136 | sp.disable_function.function("ini_set").param("option").value_r("error_reporting").drop() 137 | sp.disable_function.function("ini_set").param("option").value_r("display_errors").drop() 138 | -------------------------------------------------------------------------------- /rootfs/usr/local/etc/php/snuffleupagus/snuffleupagus.ini: -------------------------------------------------------------------------------- 1 | extension=snuffleupagus.so 2 | sp.configuration_file=/usr/local/etc/php/conf.d/nextcloud-php8.rules -------------------------------------------------------------------------------- /rootfs/var/cache/nginx/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hoellen/docker-nextcloud/42b36e3c9b67afe463c3818c41a07c8a74f5b0e4/rootfs/var/cache/nginx/.gitkeep -------------------------------------------------------------------------------- /rootfs/var/log/nginx/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hoellen/docker-nextcloud/42b36e3c9b67afe463c3818c41a07c8a74f5b0e4/rootfs/var/log/nginx/.gitkeep --------------------------------------------------------------------------------