mirror of
https://github.com/hoellen/docker-nextcloud.git
synced 2025-07-01 07:36:08 +00:00
Compare commits
87 Commits
version-23
...
version-28
Author | SHA1 | Date | |
---|---|---|---|
aa9ed8ea18 | |||
2fc97b32a2 | |||
0e84ada3d1 | |||
0ed34272f4 | |||
da2e5d91a8 | |||
0cf21d8b99 | |||
0dccbacce4 | |||
78fde4ae34 | |||
3c7698f73d | |||
9901609c6b | |||
936f60c3d5 | |||
ab3bdd0e43 | |||
1528fc9a00 | |||
cb21fa369e | |||
35f8a4f1ae | |||
34f40fe438 | |||
aec283db22 | |||
6b6e52fbdc | |||
e0cb8643f0 | |||
314cc8016d | |||
4f112a4cdb | |||
18e11abda1 | |||
bf3c76a5f8 | |||
dec3a7f789 | |||
cedf7fc4c6 | |||
80704341e6 | |||
1ee6c08552 | |||
112339b5c8 | |||
2334b3e231 | |||
6adf9e6bf8 | |||
0bb63de5b4 | |||
0ee4012ae6 | |||
18da631215 | |||
e627d1fd4c | |||
86012886af | |||
de096e78a4 | |||
2d3fd8f5c3 | |||
9070495ad0 | |||
4ba3589149 | |||
a7ba180598 | |||
4ea95f826a | |||
8451b3d94d | |||
9c24fd91b2 | |||
0bb5b1fa73 | |||
b2fcf47b96 | |||
be2aa5a6d8 | |||
fb1d5d60ff | |||
fe53018962 | |||
43a5b6bb6f | |||
93866f1171 | |||
06d89226c5 | |||
d009280681 | |||
66f1ca8176 | |||
1a6ce671a6 | |||
49eca961a8 | |||
05f056644a | |||
41b50052f4 | |||
57409ee693 | |||
e850f6a1df | |||
251903fd3d | |||
5ef63c0bb3 | |||
6eb2fac3a4 | |||
4f1e5c1b7f | |||
9c8feeb088 | |||
f194e4b319 | |||
3c945d7ee7 | |||
7a377af96a | |||
7905e3a7c4 | |||
425b04ad03 | |||
79d99eb02f | |||
0b3b86dfff | |||
a906f113b5 | |||
1ffd446214 | |||
8c11184ba1 | |||
2c662e7862 | |||
f7aded2aeb | |||
9a30d0ff02 | |||
33dc46def2 | |||
7974e54491 | |||
6e8e9619ed | |||
eceef9c4ac | |||
bce0750e6e | |||
d451bcf1ef | |||
2ac3ec67f2 | |||
df476c0dc4 | |||
7611471834 | |||
125ea0a2f6 |
85
.github/workflows/build.yml
vendored
85
.github/workflows/build.yml
vendored
@ -3,49 +3,76 @@ name: build
|
|||||||
on:
|
on:
|
||||||
workflow_dispatch:
|
workflow_dispatch:
|
||||||
push:
|
push:
|
||||||
branches: [ master ]
|
branches:
|
||||||
|
- master
|
||||||
|
- version-*
|
||||||
schedule:
|
schedule:
|
||||||
# Build the image regularly (each Friday)
|
# Build the image regularly (each Friday)
|
||||||
- cron: '23 04 * * 5'
|
- cron: '23 04 * * 5'
|
||||||
|
|
||||||
|
env:
|
||||||
|
REGISTRY: ghcr.io
|
||||||
|
IMAGE_NAME: ${{ github.repository_owner }}/nextcloud
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
build:
|
build:
|
||||||
name: Build, scan & push
|
name: Build, push & sign
|
||||||
runs-on: "ubuntu-20.04"
|
runs-on: "ubuntu-latest"
|
||||||
|
permissions:
|
||||||
|
contents: read
|
||||||
|
packages: write
|
||||||
|
id-token: write
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout code
|
- name: Checkout code
|
||||||
uses: actions/checkout@v2
|
uses: actions/checkout@v2
|
||||||
|
|
||||||
- name: Build an image from Dockerfile
|
- name: Extract version for tags
|
||||||
run: |
|
run: |
|
||||||
docker build \
|
BRANCH="${GITHUB_REF#refs/heads/}"
|
||||||
-t ghcr.io/${{ github.actor }}/nextcloud \
|
VERSION=$(grep -oP '(?<=NEXTCLOUD_VERSION=).*' Dockerfile)
|
||||||
-t ghcr.io/${{ github.actor }}/nextcloud:$(grep -oP '(?<=NEXTCLOUD_VERSION=).*' Dockerfile | head -c6) \
|
[ "$BRANCH" = "master" ] && echo "BRANCH_VERSION=latest" >> $GITHUB_ENV
|
||||||
-t ghcr.io/${{ github.actor }}/nextcloud:$(grep -oP '(?<=NEXTCLOUD_VERSION=).*' Dockerfile | head -c2) \
|
echo "FULL_VERSION=${VERSION:0:7}" >> $GITHUB_ENV
|
||||||
.
|
echo "MAJOR_VERSION=${VERSION:0:2}" >> $GITHUB_ENV
|
||||||
|
|
||||||
- name: Run Trivy vulnerability scanner
|
- name: Install cosign
|
||||||
uses: aquasecurity/trivy-action@master
|
if: github.event_name != 'pull_request'
|
||||||
|
uses: sigstore/cosign-installer@main
|
||||||
with:
|
with:
|
||||||
image-ref: 'ghcr.io/${{ github.actor }}/nextcloud'
|
cosign-release: 'v2.2.2'
|
||||||
format: 'template'
|
|
||||||
template: '@/contrib/sarif.tpl'
|
|
||||||
output: 'trivy-results.sarif'
|
|
||||||
severity: 'CRITICAL,HIGH'
|
|
||||||
vuln-type: "os"
|
|
||||||
|
|
||||||
- name: Upload Trivy scan results to GitHub Security tab
|
- name: Set up Docker Buildx
|
||||||
uses: github/codeql-action/upload-sarif@v1
|
uses: docker/setup-buildx-action@v1
|
||||||
|
|
||||||
|
- name: Login to registry
|
||||||
|
if: github.event_name != 'pull_request'
|
||||||
|
uses: docker/login-action@v1
|
||||||
with:
|
with:
|
||||||
sarif_file: 'trivy-results.sarif'
|
registry: ${{ env.REGISTRY }}
|
||||||
|
username: ${{ github.repository_owner }}
|
||||||
|
password: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
|
||||||
- name: Login to the registry
|
- name: Set Docker metadata
|
||||||
run: >-
|
id: meta
|
||||||
echo "${{ secrets.GITHUB_TOKEN }}"
|
uses: docker/metadata-action@v3
|
||||||
| docker login -u "${{ github.actor }}" --password-stdin ghcr.io
|
with:
|
||||||
|
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
|
||||||
|
tags: |
|
||||||
|
${{ env.BRANCH_VERSION }}
|
||||||
|
${{ env.FULL_VERSION }}
|
||||||
|
${{ env.MAJOR_VERSION }}
|
||||||
|
|
||||||
- name: Push image to GitHub
|
- name: Build and push Docker image
|
||||||
run: |
|
id: build-and-push
|
||||||
docker push ghcr.io/${{ github.actor }}/nextcloud
|
uses: docker/build-push-action@v2
|
||||||
docker push ghcr.io/${{ github.actor }}/nextcloud:$(grep -oP '(?<=NEXTCLOUD_VERSION=).*' Dockerfile | head -c6)
|
with:
|
||||||
docker push ghcr.io/${{ github.actor }}/nextcloud:$(grep -oP '(?<=NEXTCLOUD_VERSION=).*' Dockerfile | head -c2)
|
context: .
|
||||||
|
push: ${{ github.event_name != 'pull_request' }}
|
||||||
|
tags: ${{ steps.meta.outputs.tags }}
|
||||||
|
labels: ${{ steps.meta.outputs.labels }}
|
||||||
|
|
||||||
|
- name: Sign the published Docker image
|
||||||
|
if: ${{ github.event_name != 'pull_request' }}
|
||||||
|
env:
|
||||||
|
COSIGN_EXPERIMENTAL: "true"
|
||||||
|
run: cosign sign --yes ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}@${{ steps.build-and-push.outputs.digest }}
|
||||||
|
57
Dockerfile
57
Dockerfile
@ -1,25 +1,32 @@
|
|||||||
# -------------- Build-time variables --------------
|
# -------------- Build-time variables --------------
|
||||||
ARG NEXTCLOUD_VERSION=23.0.3
|
ARG NEXTCLOUD_VERSION=28.0.14
|
||||||
ARG PHP_VERSION=8.0
|
ARG PHP_VERSION=8.2
|
||||||
ARG NGINX_VERSION=1.20
|
ARG NGINX_VERSION=1.26
|
||||||
|
|
||||||
ARG ALPINE_VERSION=3.15
|
ARG ALPINE_VERSION=3.20
|
||||||
ARG HARDENED_MALLOC_VERSION=11
|
ARG HARDENED_MALLOC_VERSION=11
|
||||||
|
ARG SNUFFLEUPAGUS_VERSION=0.10.0
|
||||||
|
|
||||||
ARG UID=1000
|
ARG UID=1000
|
||||||
ARG GID=1000
|
ARG GID=1000
|
||||||
|
|
||||||
|
# nextcloud-28.0.14.tar.bz2
|
||||||
|
ARG SHA256_SUM="4a937f1882486426c9703e59ec4b293f621be8d080b7f85016f629903c3af336"
|
||||||
|
|
||||||
|
# Nextcloud Security <security@nextcloud.com> (D75899B9A724937A)
|
||||||
|
ARG GPG_FINGERPRINT="2880 6A87 8AE4 23A2 8372 792E D758 99B9 A724 937A"
|
||||||
# ---------------------------------------------------
|
# ---------------------------------------------------
|
||||||
|
|
||||||
### Build PHP base
|
### Build PHP base
|
||||||
FROM php:${PHP_VERSION}-fpm-alpine${ALPINE_VERSION} as base
|
FROM docker.io/library/php:${PHP_VERSION}-fpm-alpine${ALPINE_VERSION} as base
|
||||||
|
|
||||||
ARG APCU_VERSION
|
ARG SNUFFLEUPAGUS_VERSION
|
||||||
ARG REDIS_VERSION
|
|
||||||
|
|
||||||
RUN apk -U upgrade \
|
RUN apk -U upgrade \
|
||||||
&& apk add -t build-deps \
|
&& apk add -t build-deps \
|
||||||
$PHPIZE_DEPS \
|
$PHPIZE_DEPS \
|
||||||
freetype-dev \
|
freetype-dev \
|
||||||
|
git \
|
||||||
gmp-dev \
|
gmp-dev \
|
||||||
icu-dev \
|
icu-dev \
|
||||||
libjpeg-turbo-dev \
|
libjpeg-turbo-dev \
|
||||||
@ -36,13 +43,14 @@ RUN apk -U upgrade \
|
|||||||
gmp \
|
gmp \
|
||||||
icu \
|
icu \
|
||||||
libjpeg-turbo \
|
libjpeg-turbo \
|
||||||
|
librsvg \
|
||||||
libpq \
|
libpq \
|
||||||
libpq \
|
libpq \
|
||||||
libwebp \
|
libwebp \
|
||||||
libzip \
|
libzip \
|
||||||
libsmbclient \
|
libsmbclient \
|
||||||
openldap \
|
openldap \
|
||||||
libgomp \
|
libgomp \
|
||||||
imagemagick \
|
imagemagick \
|
||||||
zlib \
|
zlib \
|
||||||
&& docker-php-ext-configure gd --with-freetype --with-jpeg --with-webp \
|
&& docker-php-ext-configure gd --with-freetype --with-jpeg --with-webp \
|
||||||
@ -51,12 +59,14 @@ RUN apk -U upgrade \
|
|||||||
bcmath \
|
bcmath \
|
||||||
exif \
|
exif \
|
||||||
gd \
|
gd \
|
||||||
|
bz2 \
|
||||||
intl \
|
intl \
|
||||||
ldap \
|
ldap \
|
||||||
opcache \
|
opcache \
|
||||||
pcntl \
|
pcntl \
|
||||||
pdo_mysql \
|
pdo_mysql \
|
||||||
pdo_pgsql \
|
pdo_pgsql \
|
||||||
|
sysvsem \
|
||||||
zip \
|
zip \
|
||||||
gmp \
|
gmp \
|
||||||
&& pecl install smbclient \
|
&& pecl install smbclient \
|
||||||
@ -67,13 +77,15 @@ RUN apk -U upgrade \
|
|||||||
smbclient \
|
smbclient \
|
||||||
redis \
|
redis \
|
||||||
imagick \
|
imagick \
|
||||||
|
&& cd /tmp && git clone --depth 1 --branch v${SNUFFLEUPAGUS_VERSION} https://github.com/jvoisin/snuffleupagus \
|
||||||
|
&& cd snuffleupagus/src && phpize && ./configure --enable-snuffleupagus && make && make install \
|
||||||
&& apk del build-deps \
|
&& apk del build-deps \
|
||||||
&& rm -rf /var/cache/apk/*
|
&& rm -rf /var/cache/apk/* /tmp/*
|
||||||
|
|
||||||
|
|
||||||
### Build Hardened Malloc
|
### Build Hardened Malloc
|
||||||
ARG ALPINE_VERSION
|
ARG ALPINE_VERSION
|
||||||
FROM alpine:${ALPINE_VERSION} as build-malloc
|
FROM docker.io/library/alpine:${ALPINE_VERSION} as build-malloc
|
||||||
|
|
||||||
ARG HARDENED_MALLOC_VERSION
|
ARG HARDENED_MALLOC_VERSION
|
||||||
ARG CONFIG_NATIVE=false
|
ARG CONFIG_NATIVE=false
|
||||||
@ -87,7 +99,7 @@ RUN apk --no-cache add build-base git gnupg && cd /tmp \
|
|||||||
|
|
||||||
|
|
||||||
### Fetch nginx
|
### Fetch nginx
|
||||||
FROM nginx:${NGINX_VERSION}-alpine as nginx
|
FROM docker.io/library/nginx:${NGINX_VERSION}-alpine as nginx
|
||||||
|
|
||||||
|
|
||||||
### Build Nextcloud (production environemnt)
|
### Build Nextcloud (production environemnt)
|
||||||
@ -98,7 +110,8 @@ COPY --from=nginx /etc/nginx /etc/nginx
|
|||||||
COPY --from=build-malloc /tmp/hardened_malloc/out-light/libhardened_malloc-light.so /usr/local/lib/
|
COPY --from=build-malloc /tmp/hardened_malloc/out-light/libhardened_malloc-light.so /usr/local/lib/
|
||||||
|
|
||||||
ARG NEXTCLOUD_VERSION
|
ARG NEXTCLOUD_VERSION
|
||||||
ARG GPG_nextcloud="2880 6A87 8AE4 23A2 8372 792E D758 99B9 A724 937A"
|
ARG SHA256_SUM
|
||||||
|
ARG GPG_FINGERPRINT
|
||||||
|
|
||||||
ARG UID
|
ARG UID
|
||||||
ARG GID
|
ARG GID
|
||||||
@ -111,31 +124,30 @@ ENV UPLOAD_MAX_SIZE=10G \
|
|||||||
CRON_MEMORY_LIMIT=1g \
|
CRON_MEMORY_LIMIT=1g \
|
||||||
DB_TYPE=sqlite3 \
|
DB_TYPE=sqlite3 \
|
||||||
DOMAIN=localhost \
|
DOMAIN=localhost \
|
||||||
LD_PRELOAD="/usr/local/lib/libhardened_malloc-light.so /usr/lib/preloadable_libiconv.so"
|
PHP_HARDENING=true \
|
||||||
|
LD_PRELOAD="/usr/local/lib/libhardened_malloc-light.so"
|
||||||
|
|
||||||
RUN apk --no-cache add \
|
RUN apk --no-cache add \
|
||||||
gnupg \
|
gnupg \
|
||||||
gnu-libiconv \
|
pcre2 \
|
||||||
pcre \
|
|
||||||
s6 \
|
s6 \
|
||||||
&& NEXTCLOUD_TARBALL="nextcloud-${NEXTCLOUD_VERSION}.tar.bz2" && cd /tmp \
|
&& NEXTCLOUD_TARBALL="nextcloud-${NEXTCLOUD_VERSION}.tar.bz2" && cd /tmp \
|
||||||
&& wget -q https://download.nextcloud.com/server/releases/${NEXTCLOUD_TARBALL} \
|
&& wget -q https://download.nextcloud.com/server/releases/${NEXTCLOUD_TARBALL} \
|
||||||
&& wget -q https://download.nextcloud.com/server/releases/${NEXTCLOUD_TARBALL}.sha512 \
|
|
||||||
&& wget -q https://download.nextcloud.com/server/releases/${NEXTCLOUD_TARBALL}.asc \
|
&& wget -q https://download.nextcloud.com/server/releases/${NEXTCLOUD_TARBALL}.asc \
|
||||||
&& wget -q https://nextcloud.com/nextcloud.asc \
|
&& wget -q https://nextcloud.com/nextcloud.asc \
|
||||||
&& echo "Verifying both integrity and authenticity of ${NEXTCLOUD_TARBALL}..." \
|
&& echo "Verifying both integrity and authenticity of ${NEXTCLOUD_TARBALL}..." \
|
||||||
&& CHECKSUM_STATE=$(echo -n $(sha512sum -c ${NEXTCLOUD_TARBALL}.sha512) | tail -c 2) \
|
&& CHECKSUM_STATE=$(echo -n $(echo "${SHA256_SUM} ${NEXTCLOUD_TARBALL}" | sha256sum -c) | tail -c 2) \
|
||||||
&& if [ "${CHECKSUM_STATE}" != "OK" ]; then echo "Error: checksum does not match" && exit 1; fi \
|
&& if [ "${CHECKSUM_STATE}" != "OK" ]; then echo "Error: checksum does not match" && exit 1; fi \
|
||||||
&& gpg --import nextcloud.asc \
|
&& gpg --import nextcloud.asc \
|
||||||
&& FINGERPRINT="$(LANG=C gpg --verify ${NEXTCLOUD_TARBALL}.asc ${NEXTCLOUD_TARBALL} 2>&1 \
|
&& FINGERPRINT="$(LANG=C gpg --verify ${NEXTCLOUD_TARBALL}.asc ${NEXTCLOUD_TARBALL} 2>&1 \
|
||||||
| sed -n "s#Primary key fingerprint: \(.*\)#\1#p")" \
|
| sed -n "s#Primary key fingerprint: \(.*\)#\1#p")" \
|
||||||
&& if [ -z "${FINGERPRINT}" ]; then echo "Error: invalid GPG signature!" && exit 1; fi \
|
&& if [ -z "${FINGERPRINT}" ]; then echo "Error: invalid GPG signature!" && exit 1; fi \
|
||||||
&& if [ "${FINGERPRINT}" != "${GPG_nextcloud}" ]; then echo "Error: wrong GPG fingerprint" && exit 1; fi \
|
&& if [ "${FINGERPRINT}" != "${GPG_FINGERPRINT}" ]; then echo "Error: wrong GPG fingerprint" && exit 1; fi \
|
||||||
&& echo "All seems good, now unpacking ${NEXTCLOUD_TARBALL}..." \
|
&& echo "All seems good, now unpacking ${NEXTCLOUD_TARBALL}..." \
|
||||||
&& mkdir /nextcloud && tar xjf ${NEXTCLOUD_TARBALL} --strip 1 -C /nextcloud \
|
&& mkdir /nextcloud && tar xjf ${NEXTCLOUD_TARBALL} --strip 1 -C /nextcloud \
|
||||||
&& apk del gnupg && rm -rf /tmp/* /root/.gnupg \
|
&& apk del gnupg && rm -rf /tmp/* /root/.gnupg \
|
||||||
&& adduser -g ${GID} -u ${UID} --disabled-password --gecos "" nextcloud \
|
&& adduser -g ${GID} -u ${UID} --disabled-password --gecos "" nextcloud \
|
||||||
&& chown -R nextcloud:nextcloud /nextcloud
|
&& chown -R nextcloud:nextcloud /nextcloud/config
|
||||||
|
|
||||||
COPY --chown=nextcloud:nextcloud rootfs /
|
COPY --chown=nextcloud:nextcloud rootfs /
|
||||||
|
|
||||||
@ -149,8 +161,9 @@ VOLUME /data /nextcloud/config /nextcloud/apps2 /nextcloud/themes
|
|||||||
|
|
||||||
EXPOSE 8888
|
EXPOSE 8888
|
||||||
|
|
||||||
LABEL description="A server software for creating file hosting services" \
|
LABEL org.opencontainers.image.description="All-in-one Nextcloud image, based on Alpine Linux" \
|
||||||
nextcloud="Nextcloud v${NEXTCLOUD_VERSION}" \
|
org.opencontainers.image.version="${NEXTCLOUD_VERSION}" \
|
||||||
maintainer="Hoellen <dev@hoellen.eu>"
|
org.opencontainers.image.authors="Hoellen <dev@hoellen.eu>" \
|
||||||
|
org.opencontainers.image.source="https://github.com/hoellen/docker-nextcloud"
|
||||||
|
|
||||||
CMD ["run.sh"]
|
CMD ["run.sh"]
|
||||||
|
108
README.md
108
README.md
@ -3,71 +3,115 @@
|
|||||||
|
|
||||||
Nextcloud [official website](https://nextcloud.com/) and [source code](https://github.com/nextcloud).
|
Nextcloud [official website](https://nextcloud.com/) and [source code](https://github.com/nextcloud).
|
||||||
|
|
||||||
## Why this image?
|
## About
|
||||||
This non-official image is intended as an **all-in-one** (as in monolithic) Nextcloud **production** image. It is based on the [Wondefall/docker-nextcloud](https://github.com/Wonderfall/docker-nextcloud) image. If you're not sure you want this image, you should probably use [the official image](https://hub.docker.com/r/nextcloud).
|
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).
|
||||||
|
|
||||||
## Security
|
Check out Nextcloud [official website](https://nextcloud.com/) and [source code](https://github.com/nextcloud).
|
||||||
Don't run random images from random dudes on the Internet. Ideally, you want to maintain and build it yourself.
|
|
||||||
|
|
||||||
Images are scanned every day by [Trivy](https://github.com/aquasecurity/trivy) for OS vulnerabilities. Latest tag/version is automatically built weekly, so you should often update your images regardless if you're already using the latest Nextcloud version.
|
___
|
||||||
|
|
||||||
If you're building manually, you should always build production images without cache (use `docker build --no-cache` for instance). Latest dependencies will hence be used instead of outdated ones due to a cached layer.
|
* [Features](#features)
|
||||||
|
* [Security](#security)
|
||||||
|
* [Tags](#tags)
|
||||||
|
* [Build-time variables](#build-time-variables)
|
||||||
|
* [Environment variables](#environment-variables)
|
||||||
|
* [Runtime](#runtime)
|
||||||
|
* [Startup](#startup)
|
||||||
|
* [Volumes](#volumes)
|
||||||
|
* [Ports](#ports)
|
||||||
|
* [Migration](#migration)
|
||||||
|
* [Usage](#usage)
|
||||||
|
|
||||||
## Features
|
## Features
|
||||||
|
|
||||||
|
- Based on [Alpine Linux](https://alpinelinux.org/).
|
||||||
- Fetching PHP/nginx from their official images.
|
- Fetching PHP/nginx from their official images.
|
||||||
- **Rootless**: no privilege at any time, even at startup.
|
- **Rootless**: no privilege at any time, even at startup.
|
||||||
- Includes **hardened_malloc**, a hardened memory allocator.
|
- Uses [s6](https://skarnet.org/software/s6/) as a lightweight process supervisor.
|
||||||
|
- Supports MySQL/MariaDB, PostgresQL and SQLite3 database backends.
|
||||||
|
- Includes OPcache and APCu for improved caching & performance, also supports redis.
|
||||||
|
- Tarball integrity & authenticity checked during build process.
|
||||||
|
- Includes **hardened_malloc**, [a hardened memory allocator](https://github.com/GrapheneOS/hardened_malloc).
|
||||||
|
- Includes **Snuffleupagus**, [a PHP security module](https://github.com/jvoisin/snuffleupagus).
|
||||||
- Includes a simple **built-in cron** system.
|
- Includes a simple **built-in cron** system.
|
||||||
- Much easier to maintain thanks to multi-stages build.
|
- Much easier to maintain thanks to multi-stages build.
|
||||||
- Does not include imagick, samba, etc. by default.
|
- Does not include imagick, samba, etc. by default.
|
||||||
|
|
||||||
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.
|
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.
|
||||||
|
|
||||||
|
## Security
|
||||||
|
|
||||||
|
Don't run random images from random dudes on the Internet. Ideally, you want to maintain and build it yourself.
|
||||||
|
|
||||||
|
- **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.
|
||||||
|
- **Latest tag/version is automatically built weekly**, so you should often update your images regardless if you're already using the latest Nextcloud version.
|
||||||
|
- **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.
|
||||||
|
- **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.
|
||||||
|
- **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:
|
||||||
|
|
||||||
|
```
|
||||||
|
COSIGN_EXPERIMENTAL=true cosign verify ghcr.io/hoellen/nextcloud
|
||||||
|
```
|
||||||
|
|
||||||
|
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.
|
||||||
|
|
||||||
## Tags
|
## Tags
|
||||||
|
|
||||||
- `latest` : latest Nextcloud version
|
- `latest` : latest Nextcloud version
|
||||||
- `x` : latest Nextcloud x.x (e.g. `21`)
|
- `x` : latest Nextcloud x.x (e.g. `28`)
|
||||||
- `x.x.x` : Nextcloud x.x.x (e.g. `21.0.2`)
|
- `x.x.x` : Nextcloud x.x.x (e.g. `28.0.0`)
|
||||||
|
|
||||||
You can always have a glance [here](https://github.com/users/hoellen/packages/container/package/nextcloud).
|
You can always have a glance [here](https://github.com/users/hoellen/packages/container/package/nextcloud).
|
||||||
Only the **latest stable version** will be maintained by myself.
|
Only the **latest stable version** will be maintained by myself.
|
||||||
|
|
||||||
|
*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.*
|
||||||
|
|
||||||
## Build-time variables
|
## Build-time variables
|
||||||
| Variable | Description |
|
|
||||||
| --------------------------- | -------------------------- |
|
|
||||||
| **NEXTCLOUD_VERSION** | version of Nextcloud |
|
|
||||||
| **ALPINE_VERSION** | version of Alpine Linux |
|
|
||||||
| **PHP_VERSION** | version of PHP |
|
|
||||||
| **NGINX_VERSION** | version of nginx |
|
|
||||||
| **APCU_VERSION** | version of APCu (php ext) |
|
|
||||||
| **REDIS_VERSION** | version of redis (php ext) |
|
|
||||||
| **HARDENED_MALLOC_VERSION** | version of hardened_malloc |
|
|
||||||
| **CONFIG_NATIVE** | native code for hmalloc |
|
|
||||||
| **UID** | user id (default: 1000) |
|
|
||||||
| **GID** | group id (default: 1000) |
|
|
||||||
|
|
||||||
For convenience they were put at [the very top of the Dockerfile](https://github.com/hoellen/docker-nextcloud/blob/master/Dockerfile#L1-L13) and their usage should be quite explicit if you intend to build this image yourself.
|
| Variable | Description | Default |
|
||||||
|
| --------------------------- | -------------------------------------- | ------------------ |
|
||||||
|
| **NEXTCLOUD_VERSION** | version of Nextcloud | * |
|
||||||
|
| **ALPINE_VERSION** | version of Alpine Linux | * |
|
||||||
|
| **PHP_VERSION** | version of PHP | * |
|
||||||
|
| **NGINX_VERSION** | version of nginx | * |
|
||||||
|
| **HARDENED_MALLOC_VERSION** | version of hardened_malloc | * |
|
||||||
|
| **SNUFFLEUPAGUS_VERSION** | version of Snuffleupagus (php ext) | * |
|
||||||
|
| **SHA256_SUM** | checksum of Nextcloud tarball (sha256) | * |
|
||||||
|
| **GPG_FINGERPRINT** | fingerprint of Nextcloud GPG key | * |
|
||||||
|
| **UID** | user id | 1000 |
|
||||||
|
| **GID** | group id | 1000 |
|
||||||
|
| **CONFIG_NATIVE** | native code for hardened_malloc | false |
|
||||||
|
| **VARIANT** | variant of hardened_malloc (see repo) | light |
|
||||||
|
|
||||||
## Environment variables (Dockerfile)
|
*\* latest known available, likely to change regularly*
|
||||||
|
|
||||||
|
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.
|
||||||
|
|
||||||
|
## Environment variables
|
||||||
|
|
||||||
|
### Runtime
|
||||||
|
|
||||||
| Variable | Description | Default |
|
| Variable | Description | Default |
|
||||||
| ------------------------- | --------------------------- | ------------------ |
|
| ------------------------- | --------------------------- | ------------------ |
|
||||||
| **UPLOAD_MAX_SIZE** | file upload maximum size | 10G |
|
| **UPLOAD_MAX_SIZE** | file upload maximum size | 10G |
|
||||||
| **APC_SHM_SIZE** | apc shared memory size | 128M |
|
| **APC_SHM_SIZE** | apc shared memory size | 128M |
|
||||||
|
| **OPCACHE_MEM_SIZE** | opcache available memory | 128M |
|
||||||
| **MEMORY_LIMIT** | max php command mem usage | 512M |
|
| **MEMORY_LIMIT** | max php command mem usage | 512M |
|
||||||
| **CRON_PERIOD** | cron time interval (min.) | 5m |
|
| **CRON_PERIOD** | cron time interval (min.) | 5m |
|
||||||
| **CRON_MEMORY_LIMIT** | cron max memory usage | 1G |
|
| **CRON_MEMORY_LIMIT** | cron max memory usage | 1G |
|
||||||
| **DB_TYPE** | sqlite3, mysql, pgsql | sqlite3 |
|
| **DB_TYPE** | sqlite3, mysql, pgsql | sqlite3 |
|
||||||
| **DOMAIN** | host domain | localhost |
|
| **DOMAIN** | host domain | localhost |
|
||||||
|
| **PHP_HARDENING** | enables snuffleupagus | true |
|
||||||
|
|
||||||
Leave them at default if you're not sure what you're doing.
|
Leave them at default if you're not sure what you're doing.
|
||||||
|
|
||||||
## Environment variables (used by setup.sh)
|
### Startup
|
||||||
|
|
||||||
| Variable | Description |
|
| Variable | Description |
|
||||||
| ------------------------- | --------------------------- |
|
| ------------------------- | --------------------------- |
|
||||||
| **ADMIN_USER** | admin username |
|
| **ADMIN_USER** | admin username |
|
||||||
| **ADMIN_PASSWORD** | admin password |
|
| **ADMIN_PASSWORD** | admin password |
|
||||||
| **DB_TYPE** | sqlit3, mysql, pgsql |
|
| **DB_TYPE** | sqlite3, mysql, pgsql |
|
||||||
| **DB_NAME** | name of the database |
|
| **DB_NAME** | name of the database |
|
||||||
| **DB_USER** | name of the database user |
|
| **DB_USER** | name of the database user |
|
||||||
| **DB_PASSWORD** | password of the db user |
|
| **DB_PASSWORD** | password of the db user |
|
||||||
@ -78,24 +122,29 @@ Leave them at default if you're not sure what you're doing.
|
|||||||
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.
|
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.
|
||||||
|
|
||||||
## Volumes
|
## Volumes
|
||||||
|
|
||||||
| Variable | Description |
|
| Variable | Description |
|
||||||
| ------------------------- | -------------------------- |
|
| ------------------------- | -------------------------- |
|
||||||
| **/data** | data files |
|
| **/data** | data files |
|
||||||
| **/nextcloud/config** | config files |
|
| **/nextcloud/config** | config files |
|
||||||
| **/nextcloud/apps2** | 3rd-party apps |
|
| **/nextcloud/apps2** | 3rd-party apps |
|
||||||
| **/nextcloud/themes** | custom themes |
|
| **/nextcloud/themes** | custom themes |
|
||||||
|
| **/php/session** | PHP session files |
|
||||||
|
|
||||||
|
*Note: mounting `/php/session` isn't required but could be desirable in some circumstances.*
|
||||||
|
|
||||||
## Ports
|
## Ports
|
||||||
|
|
||||||
| Port | Use |
|
| Port | Use |
|
||||||
| ------------------------- | -------------------------- |
|
| ------------------------- | -------------------------- |
|
||||||
| **8888** (tcp) | Nextcloud web |
|
| **8888** (tcp) | Nextcloud web |
|
||||||
|
|
||||||
|
|
||||||
A reverse proxy like [Traefik](https://doc.traefik.io/traefik/) or [Caddy](https://caddyserver.com/) can be used, and you should consider:
|
A reverse proxy like [Traefik](https://doc.traefik.io/traefik/) or [Caddy](https://caddyserver.com/) can be used, and you should consider:
|
||||||
- Redirecting all HTTP traffic to HTTPS
|
- Redirecting all HTTP traffic to HTTPS
|
||||||
- Setting the [HSTS header](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Strict-Transport-Security) correctly
|
- Setting the [HSTS header](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Strict-Transport-Security) correctly
|
||||||
|
|
||||||
## Migration from the legacy image
|
## Migration
|
||||||
|
|
||||||
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.
|
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.
|
||||||
|
|
||||||
Other changes that should be reflected in your configuration files:
|
Other changes that should be reflected in your configuration files:
|
||||||
@ -105,5 +154,6 @@ Other changes that should be reflected in your configuration files:
|
|||||||
|
|
||||||
You should edit your `docker-compose.yml` and `config.php` accordingly.
|
You should edit your `docker-compose.yml` and `config.php` accordingly.
|
||||||
|
|
||||||
## Get started
|
## Usage
|
||||||
|
|
||||||
*To do.*
|
*To do.*
|
||||||
|
24
SECURITY.md
24
SECURITY.md
@ -1,14 +1,28 @@
|
|||||||
# Security Policy
|
# Security Policy
|
||||||
|
|
||||||
## Supported Versions
|
## Supported versions
|
||||||
|
|
||||||
As of now, only the latest stable version will be supported.
|
All versions of the Nextcloud community version which still receive updates will be supported
|
||||||
|
and will receive the minor version updates and security patches.
|
||||||
|
|
||||||
| Version | Supported |
|
| Version | Supported |
|
||||||
| ------- | ------------------ |
|
| ------- | ------------------ |
|
||||||
| 21. x | :white_check_mark: |
|
| 28. x | :white_check_mark: |
|
||||||
|
| 27. x | :white_check_mark: |
|
||||||
|
| 26. x | :negative_squared_cross_mark: |
|
||||||
|
| 25. x | :negative_squared_cross_mark: |
|
||||||
|
| 24. x | :negative_squared_cross_mark: |
|
||||||
|
| 23. x | :negative_squared_cross_mark: |
|
||||||
|
| 22. x | :negative_squared_cross_mark: |
|
||||||
|
|
||||||
## Reporting a Vulnerability
|
Please update to the latest version available. Major migrations are always tested before being pushed.
|
||||||
|
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).
|
||||||
|
|
||||||
|
## Automated vulnerability scanning
|
||||||
|
|
||||||
|
Uploaded images are regularly scanned for [OS vulnerabilities](https://github.com/Wonderfall/docker-nextcloud/security/code-scanning).
|
||||||
|
|
||||||
|
## Reporting a vulnerability
|
||||||
|
|
||||||
*Upstream* vulnerabilities should be reported to *upstream* projects according to their own security policies.
|
*Upstream* vulnerabilities should be reported to *upstream* projects according to their own security policies.
|
||||||
|
|
||||||
@ -17,4 +31,4 @@ Regarding vulnerabilities specific to this project:
|
|||||||
- Unsafe defaults
|
- Unsafe defaults
|
||||||
- Dependencies security updates
|
- Dependencies security updates
|
||||||
|
|
||||||
Those can be disclosed in private to `wonderfall@pm.me` or `wonderfall:targaryen.house` on Matrix (preferred).
|
Those can be disclosed in private to `dev@hoellen.eu`.
|
||||||
|
@ -18,11 +18,10 @@ server {
|
|||||||
|
|
||||||
add_header Referrer-Policy "no-referrer" always;
|
add_header Referrer-Policy "no-referrer" always;
|
||||||
add_header X-Content-Type-Options "nosniff" always;
|
add_header X-Content-Type-Options "nosniff" always;
|
||||||
add_header X-Download-Options "noopen" always;
|
|
||||||
add_header X-Frame-Options "SAMEORIGIN" always;
|
add_header X-Frame-Options "SAMEORIGIN" always;
|
||||||
add_header X-Permitted-Cross-Domain-Policies "none" always;
|
add_header X-Permitted-Cross-Domain-Policies "none" always;
|
||||||
add_header X-Robots-Tag "none" always;
|
add_header X-Robots-Tag "noindex, nofollow" always;
|
||||||
add_header X-XSS-Protection "1; mode=block" always;
|
add_header X-XSS-Protection "0" always;
|
||||||
|
|
||||||
location = /robots.txt {
|
location = /robots.txt {
|
||||||
allow all;
|
allow all;
|
||||||
@ -49,7 +48,7 @@ server {
|
|||||||
return 404;
|
return 404;
|
||||||
}
|
}
|
||||||
|
|
||||||
location ~ ^\/(?:index|remote|public|cron|core\/ajax\/update|status|ocs\/v[12]|updater\/.+|oc[ms]-provider\/.+)\.php(?:$|\/) {
|
location ~ ^\/(?:index|remote|public|cron|core\/ajax\/update|status|ocs\/v[12]|updater\/.+|ocs-provider\/.+|.+\/richdocumentscode\/proxy)\.php(?:$|\/) {
|
||||||
include /etc/nginx/fastcgi_params;
|
include /etc/nginx/fastcgi_params;
|
||||||
fastcgi_split_path_info ^(.+\.php)(/.*)$;
|
fastcgi_split_path_info ^(.+\.php)(/.*)$;
|
||||||
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
|
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
|
||||||
@ -62,18 +61,18 @@ server {
|
|||||||
fastcgi_read_timeout 1200;
|
fastcgi_read_timeout 1200;
|
||||||
}
|
}
|
||||||
|
|
||||||
location ~ ^\/(?:updater|oc[ms]-provider)(?:$|\/) {
|
location ~ ^\/(?:updater|ocs-provider)(?:$|\/) {
|
||||||
try_files $uri/ =404;
|
try_files $uri/ =404;
|
||||||
index index.php;
|
index index.php;
|
||||||
}
|
}
|
||||||
|
|
||||||
location ~ \.(?:css|js|svg|gif|map)$ {
|
location ~ \.(?:css|js|mjs|svg|gif|png|jpg|ico|wasm|tflite|map|ogg|flac)$ {
|
||||||
try_files $uri /index.php$uri$is_args$args;
|
try_files $uri /index.php$uri$is_args$args;
|
||||||
expires 6M;
|
expires 6M;
|
||||||
access_log off;
|
access_log off;
|
||||||
}
|
}
|
||||||
|
|
||||||
location ~ \.woff2?$ {
|
location ~ \.(otf|woff2)?$ {
|
||||||
try_files $uri /index.php$uri$is_args$args;
|
try_files $uri /index.php$uri$is_args$args;
|
||||||
expires 7d;
|
expires 7d;
|
||||||
access_log off;
|
access_log off;
|
||||||
|
@ -9,6 +9,11 @@ events {
|
|||||||
|
|
||||||
http {
|
http {
|
||||||
include /etc/nginx/mime.types;
|
include /etc/nginx/mime.types;
|
||||||
|
# Add .mjs as a file extension for javascript
|
||||||
|
# https://github.com/nextcloud/server/pull/36057
|
||||||
|
types {
|
||||||
|
application/javascript mjs;
|
||||||
|
}
|
||||||
default_type application/octet-stream;
|
default_type application/octet-stream;
|
||||||
|
|
||||||
access_log /nginx/logs/access.log combined;
|
access_log /nginx/logs/access.log combined;
|
||||||
|
@ -9,6 +9,22 @@ sed -i -e "s/<APC_SHM_SIZE>/$APC_SHM_SIZE/g" /usr/local/etc/php/conf.d/apcu.ini
|
|||||||
-e "s/<UPLOAD_MAX_SIZE>/$UPLOAD_MAX_SIZE/g" /etc/nginx/nginx.conf /usr/local/etc/php-fpm.conf \
|
-e "s/<UPLOAD_MAX_SIZE>/$UPLOAD_MAX_SIZE/g" /etc/nginx/nginx.conf /usr/local/etc/php-fpm.conf \
|
||||||
-e "s/<MEMORY_LIMIT>/$MEMORY_LIMIT/g" /usr/local/etc/php-fpm.conf
|
-e "s/<MEMORY_LIMIT>/$MEMORY_LIMIT/g" /usr/local/etc/php-fpm.conf
|
||||||
|
|
||||||
|
# Enable Snuffleupagus
|
||||||
|
if [ "$PHP_HARDENING" == "true" ] && [ ! -f /usr/local/etc/php/conf.d/snuffleupagus.ini ]; then
|
||||||
|
echo "Enabling Snuffleupagus..."
|
||||||
|
cp /usr/local/etc/php/snuffleupagus/* /usr/local/etc/php/conf.d
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Check if database is available
|
||||||
|
if [ -n "${DB_TYPE}" ] && [ "${DB_TYPE}" != "sqlite3" ]; then
|
||||||
|
DB_PORT=${DB_PORT:-$( [ "${DB_TYPE}" = "pgsql" ] && echo 5432 || echo 3306 )}
|
||||||
|
until nc -z "${DB_HOST:-nextcloud-db}" "${DB_PORT}"
|
||||||
|
do
|
||||||
|
echo "waiting for the database container..."
|
||||||
|
sleep 1
|
||||||
|
done
|
||||||
|
fi
|
||||||
|
|
||||||
# If new install, run setup
|
# If new install, run setup
|
||||||
if [ ! -f /nextcloud/config/config.php ]; then
|
if [ ! -f /nextcloud/config/config.php ]; then
|
||||||
touch /nextcloud/config/CAN_INSTALL
|
touch /nextcloud/config/CAN_INSTALL
|
||||||
|
@ -55,12 +55,6 @@ cat >> /nextcloud/config/autoconfig.php <<EOF;
|
|||||||
?>
|
?>
|
||||||
EOF
|
EOF
|
||||||
|
|
||||||
until nc -z "${DB_HOST:-nextcloud-db}" "${DB_PORT:-3306}"
|
|
||||||
do
|
|
||||||
echo "waiting for the database container..."
|
|
||||||
sleep 1
|
|
||||||
done
|
|
||||||
|
|
||||||
echo "Starting automatic configuration..."
|
echo "Starting automatic configuration..."
|
||||||
# Execute setup
|
# Execute setup
|
||||||
(cd /nextcloud; php index.php &>/dev/null)
|
(cd /nextcloud; php index.php &>/dev/null)
|
||||||
|
@ -6,3 +6,5 @@ opcache.memory_consumption=<OPCACHE_MEM_SIZE>
|
|||||||
opcache.interned_strings_buffer=16
|
opcache.interned_strings_buffer=16
|
||||||
opcache.max_accelerated_files=10000
|
opcache.max_accelerated_files=10000
|
||||||
opcache.revalidate_freq=60
|
opcache.revalidate_freq=60
|
||||||
|
opcache.jit=disable
|
||||||
|
opcache.jit_buffer_size=0
|
||||||
|
137
rootfs/usr/local/etc/php/snuffleupagus/nextcloud-php8.rules
Normal file
137
rootfs/usr/local/etc/php/snuffleupagus/nextcloud-php8.rules
Normal file
@ -0,0 +1,137 @@
|
|||||||
|
# This is the default configuration file for Snuffleupagus (https://snuffleupagus.rtfd.io),
|
||||||
|
# for php8.
|
||||||
|
# It contains "reasonable" defaults that won't break your websites,
|
||||||
|
# and a lot of commented directives that you can enable if you want to
|
||||||
|
# have a better protection.
|
||||||
|
|
||||||
|
# Harden the PRNG
|
||||||
|
sp.harden_random.enable();
|
||||||
|
|
||||||
|
# Disabled XXE
|
||||||
|
#sp.xxe_protection.enable();
|
||||||
|
|
||||||
|
# Global configuration variables
|
||||||
|
# sp.global.secret_key("YOU _DO_ NEED TO CHANGE THIS WITH SOME RANDOM CHARACTERS.");
|
||||||
|
|
||||||
|
# Globally activate strict mode
|
||||||
|
# https://www.php.net/manual/en/language.types.declarations.php#language.types.declarations.strict
|
||||||
|
sp.global_strict.enable();
|
||||||
|
|
||||||
|
# Prevent unserialize-related exploits
|
||||||
|
# sp.unserialize_hmac.enable();
|
||||||
|
|
||||||
|
# Only allow execution of read-only files. This is a low-hanging fruit that you should enable.
|
||||||
|
# sp.readonly_exec.enable();
|
||||||
|
|
||||||
|
# PHP has a lot of wrappers, most of them aren't usually useful, you should
|
||||||
|
# only enable the ones you're using.
|
||||||
|
# sp.wrappers_whitelist.list("file,php,phar");
|
||||||
|
|
||||||
|
# Prevent sloppy comparisons.
|
||||||
|
sp.sloppy_comparison.enable();
|
||||||
|
|
||||||
|
# Use SameSite on session cookie
|
||||||
|
# https://snuffleupagus.readthedocs.io/features.html#protection-against-cross-site-request-forgery
|
||||||
|
sp.cookie.name("PHPSESSID").samesite("lax");
|
||||||
|
|
||||||
|
# Nextcloud whitelist (tested with Nextcloud 27.0.1)
|
||||||
|
sp.disable_function.function("function_exists").param("function").value("proc_open").filename("/nextcloud/3rdparty/symfony/console/Terminal.php").allow();
|
||||||
|
sp.disable_function.function("function_exists").param("function").value("exec").filename("/nextcloud/lib/private/legacy/OC_Helper.php").allow();
|
||||||
|
sp.disable_function.function("function_exists").param("function").value("exec").filename("/nextcloud/lib/public/Util.php").allow();
|
||||||
|
sp.disable_function.function("proc_open").filename("/nextcloud/3rdparty/symfony/console/Terminal.php").allow();
|
||||||
|
sp.disable_function.function("ini_set").param("option").value_r("display_errors").filename("/nextcloud/lib/base.php").allow();
|
||||||
|
sp.disable_function.function("ini_get").param("option").value("open_basedir").filename("/nextcloud/3rdparty/bantu/ini-get-wrapper/src/IniGetWrapper.php").allow();
|
||||||
|
sp.disable_function.function("ini_get").param("option").value_r("suhosin").filename("/nextcloud/3rdparty/bantu/ini-get-wrapper/src/IniGetWrapper.php").allow();
|
||||||
|
sp.disable_function.function("ini_get").param("option").value("open_basedir").filename("/nextcloud/apps2/twofactor_webauthn/vendor/symfony/process/ExecutableFinder.php").allow();
|
||||||
|
sp.disable_function.function("ini_get").param("option").value("open_basedir").filename("/nextcloud/3rdparty/symfony/process/ExecutableFinder.php").allow();
|
||||||
|
sp.disable_function.function("ini_get").param("option").value("allow_url_fopen").filename("/nextcloud/3rdparty/guzzlehttp/guzzle/src/Utils.php").allow();
|
||||||
|
sp.disable_function.function("exec").param("command").value("apachectl -M | grep mpm").filename("/nextcloud/apps2/spreed/lib/Settings/Admin/AdminSettings.php").allow();
|
||||||
|
|
||||||
|
# Nextcloud inherently enables XXE-Protection since 27.0.1, therefore, drop setting a new external entity loader
|
||||||
|
sp.disable_function.function("libxml_set_external_entity_loader").filename("/nextcloud/lib/base.php").allow();
|
||||||
|
sp.disable_function.function("libxml_set_external_entity_loader").drop();
|
||||||
|
|
||||||
|
# Harden the `chmod` function (0777 (oct = 511, 0666 = 438)
|
||||||
|
sp.disable_function.function("chmod").param("permissions").value("438").drop();
|
||||||
|
sp.disable_function.function("chmod").param("permissions").value("511").drop();
|
||||||
|
|
||||||
|
# Prevent various `mail`-related vulnerabilities
|
||||||
|
sp.disable_function.function("mail").param("additional_parameters").value_r("\\-").drop();
|
||||||
|
|
||||||
|
# Since it's now burned, me might as well mitigate it publicly
|
||||||
|
sp.disable_function.function("putenv").param("assignment").value_r("LD_").drop()
|
||||||
|
|
||||||
|
# This one was burned in Nov 2019 - https://gist.github.com/LoadLow/90b60bd5535d6c3927bb24d5f9955b80
|
||||||
|
sp.disable_function.function("putenv").param("assignment").value_r("GCONV_").drop()
|
||||||
|
|
||||||
|
# Since people are stupid enough to use `extract` on things like $_GET or $_POST, we might as well mitigate this vector
|
||||||
|
sp.disable_function.function("extract").param("array").value_r("^_").drop()
|
||||||
|
sp.disable_function.function("extract").param("flags").value("0").drop()
|
||||||
|
|
||||||
|
# This is also burned:
|
||||||
|
# ini_set('open_basedir','..');chdir('..');…;chdir('..');ini_set('open_basedir','/');echo(file_get_contents('/etc/passwd'));
|
||||||
|
# Since we have no way of matching on two parameters at the same time, we're
|
||||||
|
# blocking calls to open_basedir altogether: nobody is using it via ini_set anyway.
|
||||||
|
# Moreover, there are non-public bypasses that are also using this vector ;)
|
||||||
|
sp.disable_function.function("ini_set").param("option").value_r("open_basedir").drop()
|
||||||
|
|
||||||
|
# Prevent various `include`-related vulnerabilities
|
||||||
|
sp.disable_function.function("require_once").value_r("\.(inc|phtml|php)$").allow();
|
||||||
|
sp.disable_function.function("include_once").value_r("\.(inc|phtml|php)$").allow();
|
||||||
|
sp.disable_function.function("require").value_r("\.(inc|phtml|php)$").allow();
|
||||||
|
sp.disable_function.function("include").value_r("\.(inc|phtml|php)$").allow();
|
||||||
|
sp.disable_function.function("require_once").drop()
|
||||||
|
sp.disable_function.function("include_once").drop()
|
||||||
|
sp.disable_function.function("require").drop()
|
||||||
|
sp.disable_function.function("include").drop()
|
||||||
|
|
||||||
|
# Prevent `system`-related injections
|
||||||
|
sp.disable_function.function("system").param("command").value_r("[$|;&`\\n\\(\\)\\\\]").drop();
|
||||||
|
sp.disable_function.function("shell_exec").param("command").value_r("[$|;&`\\n\\(\\)\\\\]").drop();
|
||||||
|
sp.disable_function.function("exec").param("command").value_r("[$|;&`\\n\\(\\)\\\\]").drop();
|
||||||
|
sp.disable_function.function("proc_open").param("command").value_r("[$|;&`\\n\\(\\)\\\\]").drop();
|
||||||
|
|
||||||
|
# Prevent runtime modification of interesting things
|
||||||
|
sp.disable_function.function("ini_set").param("option").value("assert.active").drop();
|
||||||
|
sp.disable_function.function("ini_set").param("option").value("zend.assertions").drop();
|
||||||
|
sp.disable_function.function("ini_set").param("option").value("memory_limit").drop();
|
||||||
|
sp.disable_function.function("ini_set").param("option").value("include_path").drop();
|
||||||
|
sp.disable_function.function("ini_set").param("option").value("open_basedir").drop();
|
||||||
|
|
||||||
|
# Detect some backdoors via environment recon
|
||||||
|
sp.disable_function.function("ini_get").param("option").value("allow_url_fopen").drop();
|
||||||
|
sp.disable_function.function("ini_get").param("option").value("open_basedir").drop();
|
||||||
|
sp.disable_function.function("ini_get").param("option").value_r("suhosin").drop();
|
||||||
|
sp.disable_function.function("function_exists").param("function").value("eval").drop();
|
||||||
|
sp.disable_function.function("function_exists").param("function").value("exec").drop();
|
||||||
|
sp.disable_function.function("function_exists").param("function").value("system").drop();
|
||||||
|
sp.disable_function.function("function_exists").param("function").value("shell_exec").drop();
|
||||||
|
sp.disable_function.function("function_exists").param("function").value("proc_open").drop();
|
||||||
|
sp.disable_function.function("function_exists").param("function").value("passthru").drop();
|
||||||
|
sp.disable_function.function("is_callable").param("value").value("eval").drop();
|
||||||
|
sp.disable_function.function("is_callable").param("value").value("exec").drop();
|
||||||
|
sp.disable_function.function("is_callable").param("value").value("system").drop();
|
||||||
|
sp.disable_function.function("is_callable").param("value").value("shell_exec").drop();
|
||||||
|
sp.disable_function.function("is_callable").param("value").value("proc_open").drop();
|
||||||
|
sp.disable_function.function("is_callable").param("value").value("passthru").drop();
|
||||||
|
|
||||||
|
# Ghetto error-based sqli detection
|
||||||
|
# sp.disable_function.function("mysql_query").ret("FALSE").drop();
|
||||||
|
# sp.disable_function.function("mysqli_query").ret("FALSE").drop();
|
||||||
|
# sp.disable_function.function("PDO::query").ret("FALSE").drop();
|
||||||
|
|
||||||
|
# Ensure that certificates are properly verified
|
||||||
|
sp.disable_function.function("curl_setopt").param("value").value("1").allow();
|
||||||
|
sp.disable_function.function("curl_setopt").param("value").value("2").allow();
|
||||||
|
# `81` is SSL_VERIFYHOST and `64` SSL_VERIFYPEER
|
||||||
|
sp.disable_function.function("curl_setopt").param("option").value("64").drop().alias("Please don't turn CURLOPT_SSL_VERIFYCLIENT off.");
|
||||||
|
sp.disable_function.function("curl_setopt").param("option").value("81").drop().alias("Please don't turn CURLOPT_SSL_VERIFYHOST off.");
|
||||||
|
|
||||||
|
# File upload
|
||||||
|
sp.disable_function.function("move_uploaded_file").param("to").value_r("\\.ph").drop();
|
||||||
|
sp.disable_function.function("move_uploaded_file").param("to").value_r("\\.ht").drop();
|
||||||
|
|
||||||
|
# Logging lockdown
|
||||||
|
sp.disable_function.function("ini_set").param("option").value_r("error_log").drop()
|
||||||
|
sp.disable_function.function("ini_set").param("option").value_r("error_reporting").drop()
|
||||||
|
sp.disable_function.function("ini_set").param("option").value_r("display_errors").drop()
|
2
rootfs/usr/local/etc/php/snuffleupagus/snuffleupagus.ini
Normal file
2
rootfs/usr/local/etc/php/snuffleupagus/snuffleupagus.ini
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
extension=snuffleupagus.so
|
||||||
|
sp.configuration_file=/usr/local/etc/php/conf.d/nextcloud-php8.rules
|
Reference in New Issue
Block a user