102 Commits

Author SHA1 Message Date
a18044bc0e chore: update Nextcloud to 30.0.12 2025-06-12 10:40:49 +02:00
316f0382c9 chore: update Nextcloud to 30.0.11 2025-05-16 09:16:05 +02:00
60ba7aee48 chore: update Nextcloud to 30.0.10 2025-04-25 10:55:41 +02:00
d460ad50a3 chore: update Nextcloud to 30.0.9 2025-04-14 10:23:42 +02:00
ee1adeef8f chore: update Nextcloud to 30.0.8 2025-03-19 22:16:15 +01:00
6f8f4290a0 chore: update Nextcloud to 30.0.7 2025-03-14 09:27:41 +01:00
921eec5693 chore: update Nextcloud to 30.0.6 2025-02-13 15:45:41 +01:00
1b0c1fb747 chore: update Nextcloud to 30.0.5 2025-01-21 22:15:49 +01:00
a7ade2cbc4 fix: pin Imagick version to fix build error (#102)
Related: #102, #103
2024-12-18 13:32:50 +01:00
3451a6219a fix: wrong path because of usr-merge 2024-12-13 15:10:06 +01:00
16acf58089 chore: update Nextcloud to 30.0.4 2024-12-13 11:18:34 +01:00
ae0277a368 chore: raise Alpine Linux version to 3.21
Release notes: https://wiki.alpinelinux.org/wiki/Release_Notes_for_Alpine_3.21.0
2024-12-13 11:18:06 +01:00
aeea888ef9 Raise PHP version to 8.3
(Closes: #94)
2024-12-08 13:37:56 +01:00
ae5b0cfd0c chore: update Nextcloud to version 30.0.3 2024-12-06 03:31:04 +01:00
ee9d26963c chore: update Nextcloud to version 30.0.2 2024-11-07 19:40:18 +01:00
a5538adb2f fix: add otf loading in nginx config 2024-10-18 12:03:06 +02:00
ee98f35852 chore: update Nextcloud to 30.0.1 2024-10-18 12:02:34 +02:00
2ceb05c146 chore: update Nextcloud to 30.0.0 2024-09-14 19:52:28 +02:00
ee2760237f chore: update Nextcloud to 29.0.7 2024-09-13 05:38:50 +02:00
6aa67c63b5 chore: update Nextcloud to 29.0.5 2024-08-21 10:03:37 +02:00
a0442ed1de chore: adding trailing slash
see https://docs.nextcloud.com/server/29/admin_manual/installation/nginx.html
2024-08-21 10:02:39 +02:00
74e06ec86d chore: update Nextcloud to 29.0.4 2024-07-20 11:06:42 +02:00
ce390fc654 chore: update Nextcloud to 29.0.3 2024-06-25 15:03:57 +02:00
6facdfba4f chore: update Nextcloud to 29.0.2 2024-06-07 00:26:54 +02:00
60954e1ad7 chore: update Nextcloud to 29.0.1 2024-05-23 23:07:46 +02:00
539f41e25e chore: update Alpine to 3.20 2024-05-23 23:07:46 +02:00
fa3fe52dd2 chore: update Nextcloud to 29.0.0 2024-04-24 17:39:44 +02:00
1528fc9a00 feat: enhance branch workflow 2024-04-24 17:05:32 +02:00
cb21fa369e chore: update Nginx to 1.26 (stable) 2024-04-24 09:12:30 +02:00
35f8a4f1ae chore: mark version 26 as EOL 2024-04-09 15:06:45 +02:00
34f40fe438 fix: add missing librsvg
This was caused by the update to Alpine 3.19.
2024-04-09 14:47:04 +02:00
aec283db22 chore: update cosign 2024-03-29 15:44:15 +01:00
6b6e52fbdc chore: update Alpine to 3.19 2024-03-29 14:59:30 +01:00
e0cb8643f0 chore: update Nextcloud to 28.0.4 2024-03-29 14:58:29 +01:00
314cc8016d chore: update Nextcloud to 28.0.3 2024-03-02 05:01:32 +01:00
4f112a4cdb Fully qualify the base images 2024-03-02 05:00:45 +01:00
18e11abda1 chore: update Nextcloud to 28.0.2 2024-02-01 14:48:00 +01:00
bf3c76a5f8 chore: update nginx configuration
- update static file extensions
 - add mjs to mimetype
   https://github.com/hoellen/docker-nextcloud/issues/60
 - remove legacy header
   https://github.com/hoellen/docker-nextcloud/pull/61
2024-01-02 11:10:11 +01:00
dec3a7f789 fix: set default port for PostgreSQL in db check 2023-12-27 11:24:10 +01:00
cedf7fc4c6 chore: update Nextcloud to 28.0.1 2023-12-21 20:58:05 +01:00
80704341e6 feat: check if db is available, not just in setup 2023-12-21 20:57:11 +01:00
1ee6c08552 chore: update Nextcloud to 28.0.0 2023-12-15 21:09:46 +01:00
112339b5c8 chore: update Nextcloud to 27.1.4 2023-11-24 09:21:16 +01:00
2334b3e231 chore: update Nextcloud to 27.1.3 2023-10-30 10:18:22 +01:00
6adf9e6bf8 Fix resolving osc-provider (Closes: #47)
Accordingly to dc0b8d9c39
2023-10-21 09:40:13 +02:00
0bb63de5b4 chore: update Nextcloud to 27.1.2 2023-10-06 00:44:08 +02:00
0ee4012ae6 Update Snuffleupagus to 0.10.0 2023-09-21 16:17:49 +02:00
18da631215 Drop call of libxml_set_external_entity_loader
ref:
  - https://github.com/jvoisin/snuffleupagus/issues/463
  - https://github.com/hoellen/docker-nextcloud/issues/42
2023-09-21 16:12:33 +02:00
e627d1fd4c chore: update Nextcloud to 27.1.1 2023-09-21 15:52:33 +02:00
86012886af chore: update Nextcloud to 27.1.0 2023-09-15 22:22:15 +02:00
de096e78a4 chore: update Nextcloud to 27.0.2 2023-08-10 12:34:01 +02:00
2d3fd8f5c3 fix: disable snuffleupagus xxe protection
Nextcloud now prevents loading external entities by using libxml_set_external_entity_loader.

ref:
https://github.com/nextcloud/server/pull/39490
https://github.com/hoellen/docker-nextcloud/issues/42
2023-07-25 06:34:32 +02:00
9070495ad0 chore: update Nextcloud to 27.0.1 2023-07-21 00:15:21 +03:00
4ba3589149 chore: update Nextcloud to 27, PHP to 8.2 and Alpine to 3.18 2023-06-13 16:06:23 +02:00
a7ba180598 Update Nextcloud to 26.0.2 2023-05-25 21:08:59 +02:00
4ea95f826a chore: update Nextcloud to 26.0.1 2023-04-20 09:36:26 +02:00
8451b3d94d chore: update nginx to new stable (1.24.0) 2023-04-12 10:42:30 +02:00
9c24fd91b2 chore: update Alpine Linux to 3.17 2023-04-01 12:30:42 +02:00
0bb5b1fa73 chore: update Nextcloud to 26.0.0 2023-03-21 21:30:47 +01:00
b2fcf47b96 Update Nextcloud 25.0.4 2023-02-23 21:17:44 +01:00
be2aa5a6d8 Update Nextcloud to 25.0.3 2023-01-17 10:38:14 +01:00
fb1d5d60ff Update supported versions 2023-01-11 09:45:55 +01:00
fe53018962 Update Nextcloud to 25.0.2 2022-12-08 15:39:54 +01:00
43a5b6bb6f Update to 25.0.1 2022-11-03 18:34:21 +01:00
93866f1171 update cosign 2022-10-31 15:49:22 +01:00
06d89226c5 Whitelist PHP functions for Nextcloud 25 2022-10-19 13:06:53 +02:00
d009280681 Update Nextcloud to 25.0.0 2022-10-19 13:05:57 +02:00
66f1ca8176 Update Nextcloud to 24.0.6 2022-10-06 14:52:36 +02:00
1a6ce671a6 Update Nextcloud to 24.0.5 2022-09-09 09:47:56 +02:00
49eca961a8 Update Shufflepagus to 0.8.3 2022-09-09 09:46:17 +02:00
05f056644a fix: use correct tar.bz2 checksum 2022-08-12 08:44:28 +02:00
41b50052f4 chore: update Nextcloud to 24.0.4 2022-08-12 08:14:48 +02:00
57409ee693 Update to 24.0.3 2022-07-19 19:01:02 +02:00
e850f6a1df Update Nextcloud to 24.0.2 2022-06-21 00:00:51 +02:00
251903fd3d Update cosign 2022-06-08 00:41:49 +02:00
5ef63c0bb3 Update Alpine and dependencies 2022-06-08 00:01:17 +02:00
6eb2fac3a4 Snuffleupagus 0.8.1 2022-05-20 13:33:12 +02:00
4f1e5c1b7f Update to PHP 8.1 2022-05-20 13:32:35 +02:00
9c8feeb088 Update to 24.0.1 2022-05-20 13:17:32 +02:00
f194e4b319 Use GITHUB_TOKEN for authentication again
was overriden by upstream sync
2022-05-06 09:46:11 +02:00
3c945d7ee7 snuffleupagus: Add exception rule for Nextcloud 2022-05-06 09:26:00 +02:00
7a377af96a Merge branch 'version-24-testing' 2022-05-05 21:58:51 +02:00
7905e3a7c4 Update to Nextcloud 24.0.0 2022-05-05 21:57:09 +02:00
425b04ad03 Update README.md and SECURITY.md 2022-05-05 21:56:17 +02:00
79d99eb02f iconv workaround no longer needed
Official PHP image now includes it by default for Alpine
2022-05-05 08:34:33 +02:00
0b3b86dfff snuffleupagus: fix basic settings on new installs 2022-05-05 08:34:20 +02:00
a906f113b5 Update SECURITY.md 2022-05-05 08:31:30 +02:00
1ffd446214 ensure JIT is disabled
It was disabled by default (jit_buffer_size=0 by default), but this setting makes sure JIT is unavailable at runtime. While JIT may bring minor performance improvements, this is not worth the risk of being exposed to tons of bugs due to JIT code complexity.
2022-05-05 08:31:10 +02:00
8c11184ba1 follow OCI spec for labels 2022-05-05 08:30:45 +02:00
2c662e7862 snuffleupagus: fix broken "Basic settings" access 2022-05-05 08:29:46 +02:00
f7aded2aeb chown not necessary here 2022-05-05 08:28:41 +02:00
9a30d0ff02 snuffleupagus: enable sloppy_comparison 2022-05-05 08:28:32 +02:00
33dc46def2 snuffleupagus: enable global_strict 2022-05-05 08:28:21 +02:00
7974e54491 support and enable snuffleupagus 2022-05-05 08:25:52 +02:00
6e8e9619ed add note about signed images 2022-05-05 08:24:32 +02:00
eceef9c4ac fix setup: do not wait for db if using sqlite3 2022-05-05 08:24:05 +02:00
bce0750e6e refactor build workflow, support signing 2022-05-05 08:23:13 +02:00
d451bcf1ef mention gpg key user id 2022-05-05 07:50:40 +02:00
2ac3ec67f2 proper integrity check 2022-05-05 07:50:09 +02:00
df476c0dc4 remove unused build-time variables
we always use the latest anyway
2022-05-05 07:49:41 +02:00
7611471834 disable legacy X-XSS-Protection
Obsolete, unsafe, and superseded by CSP
2022-05-05 07:48:42 +02:00
125ea0a2f6 Update to 23.0.4 (Closes: #13) 2022-04-21 23:26:14 +02:00
11 changed files with 365 additions and 100 deletions

View File

@ -3,48 +3,76 @@ name: build
on:
workflow_dispatch:
push:
branches: [ version-23 ]
branches:
- master
- version-*
schedule:
# Build the image regularly (each Friday)
- cron: '23 04 * * 5'
env:
REGISTRY: ghcr.io
IMAGE_NAME: ${{ github.repository_owner }}/nextcloud
jobs:
build:
name: Build, scan & push
runs-on: "ubuntu-20.04"
name: Build, push & sign
runs-on: "ubuntu-latest"
permissions:
contents: read
packages: write
id-token: write
steps:
- name: Checkout code
uses: actions/checkout@v2
- name: Build an image from Dockerfile
- name: Extract version for tags
run: |
docker build \
-t ghcr.io/${{ github.actor }}/nextcloud:$(grep -oP '(?<=NEXTCLOUD_VERSION=).*' Dockerfile | head -c6) \
-t ghcr.io/${{ github.actor }}/nextcloud:$(grep -oP '(?<=NEXTCLOUD_VERSION=).*' Dockerfile | head -c2) \
.
BRANCH="${GITHUB_REF#refs/heads/}"
VERSION=$(grep -oP '(?<=NEXTCLOUD_VERSION=).*' Dockerfile)
[ "$BRANCH" = "master" ] && echo "BRANCH_VERSION=latest" >> $GITHUB_ENV
echo "FULL_VERSION=${VERSION:0:7}" >> $GITHUB_ENV
echo "MAJOR_VERSION=${VERSION:0:2}" >> $GITHUB_ENV
- name: Run Trivy vulnerability scanner
uses: aquasecurity/trivy-action@master
- name: Install cosign
if: github.event_name != 'pull_request'
uses: sigstore/cosign-installer@main
with:
image-ref: 'ghcr.io/${{ github.actor }}/nextcloud'
format: 'template'
template: '@/contrib/sarif.tpl'
output: 'trivy-results.sarif'
severity: 'CRITICAL,HIGH'
vuln-type: "os"
cosign-release: 'v2.2.2'
- name: Upload Trivy scan results to GitHub Security tab
uses: github/codeql-action/upload-sarif@v1
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v1
- name: Login to registry
if: github.event_name != 'pull_request'
uses: docker/login-action@v1
with:
sarif_file: 'trivy-results.sarif'
registry: ${{ env.REGISTRY }}
username: ${{ github.repository_owner }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Login to the registry
run: >-
echo "${{ secrets.GITHUB_TOKEN }}"
| docker login -u "${{ github.actor }}" --password-stdin ghcr.io
- name: Set Docker metadata
id: meta
uses: docker/metadata-action@v3
with:
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
tags: |
${{ env.BRANCH_VERSION }}
${{ env.FULL_VERSION }}
${{ env.MAJOR_VERSION }}
- name: Push image to GitHub
run: |
docker push ghcr.io/${{ github.actor }}/nextcloud:$(grep -oP '(?<=NEXTCLOUD_VERSION=).*' Dockerfile | head -c6)
docker push ghcr.io/${{ github.actor }}/nextcloud:$(grep -oP '(?<=NEXTCLOUD_VERSION=).*' Dockerfile | head -c2)
- name: Build and push Docker image
id: build-and-push
uses: docker/build-push-action@v2
with:
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 }}

View File

@ -1,25 +1,34 @@
# -------------- Build-time variables --------------
ARG NEXTCLOUD_VERSION=23.0.12
ARG PHP_VERSION=8.0
ARG NGINX_VERSION=1.20
ARG NEXTCLOUD_VERSION=30.0.12
ARG PHP_VERSION=8.3
ARG NGINX_VERSION=1.26
ARG ALPINE_VERSION=3.15
ARG ALPINE_VERSION=3.21
ARG HARDENED_MALLOC_VERSION=11
ARG SNUFFLEUPAGUS_VERSION=0.10.0
ARG UID=1000
ARG GID=1000
# nextcloud-30.0.12.tar.bz2
ARG SHA256_SUM="9e19b25f42273d4361218426b4762a766bee408cfa6aa8219f8c27f72095a7a8"
# Nextcloud Security <security@nextcloud.com> (D75899B9A724937A)
ARG GPG_FINGERPRINT="2880 6A87 8AE4 23A2 8372 792E D758 99B9 A724 937A"
# ---------------------------------------------------
### 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 REDIS_VERSION
ARG SNUFFLEUPAGUS_VERSION
ENV IMAGICK_SHA 28f27044e435a2b203e32675e942eb8de620ee58
RUN apk -U upgrade \
&& apk add -t build-deps \
$PHPIZE_DEPS \
freetype-dev \
git \
gmp-dev \
icu-dev \
libjpeg-turbo-dev \
@ -36,13 +45,14 @@ RUN apk -U upgrade \
gmp \
icu \
libjpeg-turbo \
librsvg \
libpq \
libpq \
libwebp \
libzip \
libsmbclient \
openldap \
libgomp \
libgomp \
imagemagick \
zlib \
&& docker-php-ext-configure gd --with-freetype --with-jpeg --with-webp \
@ -51,29 +61,34 @@ RUN apk -U upgrade \
bcmath \
exif \
gd \
bz2 \
intl \
ldap \
opcache \
pcntl \
pdo_mysql \
pdo_pgsql \
sysvsem \
zip \
gmp \
&& pecl install smbclient \
&& pecl install APCu \
&& pecl install redis \
&& pecl install imagick \
&& curl -L -o /tmp/imagick.tar.gz https://github.com/Imagick/imagick/archive/${IMAGICK_SHA}.tar.gz && tar --strip-components=1 -xf /tmp/imagick.tar.gz && phpize && ./configure && make && make install \
&& apk add --no-cache --virtual .imagick-runtime-deps imagemagick \
&& docker-php-ext-enable \
smbclient \
redis \
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 \
&& rm -rf /var/cache/apk/*
&& rm -rf /var/cache/apk/* /tmp/*
### Build Hardened Malloc
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 CONFIG_NATIVE=false
@ -87,7 +102,7 @@ RUN apk --no-cache add build-base git gnupg && cd /tmp \
### Fetch nginx
FROM nginx:${NGINX_VERSION}-alpine as nginx
FROM docker.io/library/nginx:${NGINX_VERSION}-alpine as nginx
### Build Nextcloud (production environemnt)
@ -98,7 +113,8 @@ COPY --from=nginx /etc/nginx /etc/nginx
COPY --from=build-malloc /tmp/hardened_malloc/out-light/libhardened_malloc-light.so /usr/local/lib/
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 GID
@ -111,31 +127,30 @@ ENV UPLOAD_MAX_SIZE=10G \
CRON_MEMORY_LIMIT=1g \
DB_TYPE=sqlite3 \
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 \
gnupg \
gnu-libiconv \
pcre \
pcre2 \
s6 \
&& 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}.sha512 \
&& wget -q https://download.nextcloud.com/server/releases/${NEXTCLOUD_TARBALL}.asc \
&& wget -q https://nextcloud.com/nextcloud.asc \
&& 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 \
&& gpg --import nextcloud.asc \
&& FINGERPRINT="$(LANG=C gpg --verify ${NEXTCLOUD_TARBALL}.asc ${NEXTCLOUD_TARBALL} 2>&1 \
| sed -n "s#Primary key fingerprint: \(.*\)#\1#p")" \
&& 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}..." \
&& mkdir /nextcloud && tar xjf ${NEXTCLOUD_TARBALL} --strip 1 -C /nextcloud \
&& apk del gnupg && rm -rf /tmp/* /root/.gnupg \
&& 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 /
@ -149,8 +164,9 @@ VOLUME /data /nextcloud/config /nextcloud/apps2 /nextcloud/themes
EXPOSE 8888
LABEL description="A server software for creating file hosting services" \
nextcloud="Nextcloud v${NEXTCLOUD_VERSION}" \
maintainer="Hoellen <dev@hoellen.eu>"
LABEL org.opencontainers.image.description="All-in-one Nextcloud image, based on Alpine Linux" \
org.opencontainers.image.version="${NEXTCLOUD_VERSION}" \
org.opencontainers.image.authors="Hoellen <dev@hoellen.eu>" \
org.opencontainers.image.source="https://github.com/hoellen/docker-nextcloud"
CMD ["run.sh"]

108
README.md
View File

@ -3,71 +3,115 @@
Nextcloud [official website](https://nextcloud.com/) and [source code](https://github.com/nextcloud).
## Why this image?
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).
## About
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
Don't run random images from random dudes on the Internet. Ideally, you want to maintain and build it yourself.
Check out Nextcloud [official website](https://nextcloud.com/) and [source code](https://github.com/nextcloud).
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
- Based on [Alpine Linux](https://alpinelinux.org/).
- Fetching PHP/nginx from their official images.
- **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.
- Much easier to maintain thanks to multi-stages build.
- 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.
## 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
- `latest` : latest Nextcloud version
- `x` : latest Nextcloud x.x (e.g. `21`)
- `x.x.x` : Nextcloud x.x.x (e.g. `21.0.2`)
- `x` : latest Nextcloud x.x (e.g. `30`)
- `x.x.x` : Nextcloud x.x.x (e.g. `30.0.0`)
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.
*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
| 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 |
| ------------------------- | --------------------------- | ------------------ |
| **UPLOAD_MAX_SIZE** | file upload maximum size | 10G |
| **APC_SHM_SIZE** | apc shared memory size | 128M |
| **OPCACHE_MEM_SIZE** | opcache available memory | 128M |
| **MEMORY_LIMIT** | max php command mem usage | 512M |
| **CRON_PERIOD** | cron time interval (min.) | 5m |
| **CRON_MEMORY_LIMIT** | cron max memory usage | 1G |
| **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.
## Environment variables (used by setup.sh)
### Startup
| Variable | Description |
| ------------------------- | --------------------------- |
| **ADMIN_USER** | admin username |
| **ADMIN_PASSWORD** | admin password |
| **DB_TYPE** | sqlit3, mysql, pgsql |
| **DB_TYPE** | sqlite3, mysql, pgsql |
| **DB_NAME** | name of the database |
| **DB_USER** | name of the database 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.
## Volumes
| Variable | Description |
| ------------------------- | -------------------------- |
| **/data** | data files |
| **/nextcloud/config** | config files |
| **/nextcloud/apps2** | 3rd-party apps |
| **/nextcloud/themes** | custom themes |
| **/php/session** | PHP session files |
*Note: mounting `/php/session` isn't required but could be desirable in some circumstances.*
## Ports
| Port | Use |
| ------------------------- | -------------------------- |
| **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:
- Redirecting all HTTP traffic to HTTPS
- 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.
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.
## Get started
## Usage
*To do.*

View File

@ -1,14 +1,30 @@
# 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 |
| ------- | ------------------ |
| 21. x | :white_check_mark: |
| 30. x | :white_check_mark: |
| 29. x | :white_check_mark: |
| 28. x | :white_check_mark: |
| 27. x | :negative_squared_cross_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.
@ -17,4 +33,4 @@ Regarding vulnerabilities specific to this project:
- Unsafe defaults
- 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`.

View File

@ -18,11 +18,10 @@ server {
add_header Referrer-Policy "no-referrer" 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-Permitted-Cross-Domain-Policies "none" always;
add_header X-Robots-Tag "none" always;
add_header X-XSS-Protection "1; mode=block" always;
add_header X-Robots-Tag "noindex, nofollow" always;
add_header X-XSS-Protection "0" always;
location = /robots.txt {
allow all;
@ -31,8 +30,8 @@ server {
}
location ^~ /.well-known {
location = /.well-known/carddav { return 301 $nc_proto://$host/remote.php/dav; }
location = /.well-known/caldav { return 301 $nc_proto://$host/remote.php/dav; }
location = /.well-known/carddav { return 301 $nc_proto://$host/remote.php/dav/; }
location = /.well-known/caldav { return 301 $nc_proto://$host/remote.php/dav/; }
location ^~ /.well-known { return 301 $nc_proto://$host/index.php$uri; }
try_files $uri $uri/ =404;
}
@ -49,7 +48,7 @@ server {
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;
fastcgi_split_path_info ^(.+\.php)(/.*)$;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
@ -62,18 +61,18 @@ server {
fastcgi_read_timeout 1200;
}
location ~ ^\/(?:updater|oc[ms]-provider)(?:$|\/) {
location ~ ^\/(?:updater|ocs-provider)(?:$|\/) {
try_files $uri/ =404;
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;
expires 6M;
access_log off;
}
location ~ \.woff2?$ {
location ~ \.(otf|woff2)?$ {
try_files $uri /index.php$uri$is_args$args;
expires 7d;
access_log off;

View File

@ -9,6 +9,11 @@ events {
http {
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;
access_log /nginx/logs/access.log combined;

View File

@ -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/<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 [ ! -f /nextcloud/config/config.php ]; then
touch /nextcloud/config/CAN_INSTALL
@ -18,4 +34,4 @@ else
fi
# Run processes
exec /bin/s6-svscan /etc/s6.d
exec /usr/bin/s6-svscan /etc/s6.d

View File

@ -55,12 +55,6 @@ cat >> /nextcloud/config/autoconfig.php <<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..."
# Execute setup
(cd /nextcloud; php index.php &>/dev/null)

View File

@ -6,3 +6,5 @@ opcache.memory_consumption=<OPCACHE_MEM_SIZE>
opcache.interned_strings_buffer=16
opcache.max_accelerated_files=10000
opcache.revalidate_freq=60
opcache.jit=disable
opcache.jit_buffer_size=0

View 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()

View File

@ -0,0 +1,2 @@
extension=snuffleupagus.so
sp.configuration_file=/usr/local/etc/php/conf.d/nextcloud-php8.rules