diff --git a/Dockerfile b/Dockerfile index cf6970c..02895c7 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,49 +1,31 @@ -FROM php:fpm-alpine +FROM alpine:3.10 MAINTAINER PrivateBin -ENV RELEASE 1.2.1 +ENV RELEASE 1.3.1 +ENV PBURL https://github.com/PrivateBin/PrivateBin/ +ENV S6RELEASE v1.22.1.0 +ENV S6URL https://github.com/just-containers/s6-overlay/releases/download/ +ENV S6_READ_ONLY_ROOT 1 RUN \ # Install dependencies - apk add --no-cache nginx supervisor \ -# Install PHP extension: opcache - && docker-php-ext-install -j$(nproc) opcache \ - && rm -f /usr/local/etc/php/conf.d/docker-php-ext-opcache.ini \ -# Install PHP extension: gd - && apk add --no-cache freetype libpng libjpeg-turbo freetype-dev libpng-dev libjpeg-turbo-dev \ - && docker-php-ext-configure gd \ - --with-freetype-dir=/usr/include/ \ - --with-png-dir=/usr/include/ \ - --with-jpeg-dir=/usr/include/ \ - && docker-php-ext-install -j$(nproc) gd \ - && apk del --no-cache freetype-dev libpng-dev libjpeg-turbo-dev \ + apk add --no-cache tzdata nginx php7-fpm php7-json php7-gd \ + php7-opcache php7-pdo_mysql php7-pdo_pgsql \ # Remove (some of the) default nginx config - && rm -f /etc/nginx.conf \ - && rm -f /etc/nginx/conf.d/default.conf \ + && rm -f /etc/nginx.conf /etc/nginx/conf.d/default.conf /etc/php7/php-fpm.d/www.conf \ && rm -rf /etc/nginx/sites-* \ - && rm -rf /var/log/nginx \ # Ensure nginx logs, even if the config has errors, are written to stderr - && rm /var/lib/nginx/logs \ - && mkdir -p /var/lib/nginx/logs \ - && ln -s /dev/stderr /var/lib/nginx/logs/error.log \ -# Create folder where the user hook into our default configs - && mkdir -p /etc/nginx/server.d/ \ - && mkdir -p /etc/nginx/location.d/ \ -# Bring php-fpm configs into a more controallable state - && rm /usr/local/etc/php-fpm.d/www.conf.default \ - && mv /usr/local/etc/php-fpm.d/docker.conf /usr/local/etc/php-fpm.d/00-docker.conf \ - && mv /usr/local/etc/php-fpm.d/www.conf /usr/local/etc/php-fpm.d/10-www.conf \ - && mv /usr/local/etc/php-fpm.d/zz-docker.conf /usr/local/etc/php-fpm.d/20-docker.conf \ + && ln -s /dev/stderr /var/log/nginx/error.log \ # Install PrivateBin - && apk add --no-cache gnupg \ + && apk add --no-cache gnupg curl libcap \ && export GNUPGHOME="$(mktemp -d)" \ && gpg2 --list-public-keys || /bin/true \ && curl -s https://privatebin.info/key/release.asc | gpg2 --import - \ && rm -rf /var/www/* \ && cd /tmp \ - && curl -Ls https://github.com/PrivateBin/PrivateBin/releases/download/${RELEASE}/PrivateBin-${RELEASE}.tar.gz.asc > PrivateBin-${RELEASE}.tar.gz.asc \ - && curl -Ls https://github.com/PrivateBin/PrivateBin/archive/${RELEASE}.tar.gz > PrivateBin-${RELEASE}.tar.gz \ + && curl -Ls ${PBURL}releases/download/${RELEASE}/PrivateBin-${RELEASE}.tar.gz.asc > PrivateBin-${RELEASE}.tar.gz.asc \ + && curl -Ls ${PBURL}archive/${RELEASE}.tar.gz > PrivateBin-${RELEASE}.tar.gz \ && gpg2 --verify PrivateBin-${RELEASE}.tar.gz.asc \ && cd /var/www \ && tar -xzf /tmp/PrivateBin-${RELEASE}.tar.gz --strip 1 \ @@ -54,18 +36,32 @@ RUN \ && mv vendor /srv \ && mkdir -p /srv/data \ && sed -i "s#define('PATH', '');#define('PATH', '/srv/');#" index.php \ - && chown -R www-data.www-data /var/www /srv/* \ +# Install s6 overlay for service management + && curl -s https://keybase.io/justcontainers/key.asc | gpg2 --import - \ + && cd /tmp \ + && curl -Ls ${S6URL}${S6RELEASE}/s6-overlay-amd64.tar.gz.sig > s6-overlay-amd64.tar.gz.sig \ + && curl -Ls ${S6URL}${S6RELEASE}/s6-overlay-amd64.tar.gz > s6-overlay-amd64.tar.gz \ + && gpg2 --verify s6-overlay-amd64.tar.gz.sig \ + && tar -xzf s6-overlay-amd64.tar.gz -C / \ +# Support running s6 under a non-root user + && mkdir -p /etc/services.d/nginx/supervise /etc/services.d/php-fpm7/supervise \ + && mkfifo /etc/services.d/nginx/supervise/control \ + && mkfifo /etc/services.d/php-fpm7/supervise/control \ + && mkfifo /etc/s6/services/s6-fdholderd/supervise/control \ + && setcap 'cap_net_bind_service=+ep' /usr/sbin/nginx \ + && chown -R nobody.www-data /var/lib/nginx /var/tmp/nginx /var/www /srv/* /etc/services.d /etc/s6 /run \ +# Clean up && rm -rf "${GNUPGHOME}" /tmp/* \ - && apk del --no-cache gnupg + && apk del gnupg curl libcap -WORKDIR /var/www +COPY etc/ /etc/ -ADD etc/ /etc/ -ADD usr/ /usr/ +WORKDIR /var/www +USER nobody:www-data # mark dirs as volumes that need to be writable, allows running the container --read-only -VOLUME /srv/data /tmp /var/tmp /run /var/log +VOLUME /srv/data /tmp /var/tmp/nginx /run /var/log EXPOSE 80 -ENTRYPOINT ["/usr/bin/supervisord","-c","/etc/supervisord.conf"] +ENTRYPOINT ["/init"] diff --git a/README.md b/README.md index 0f4ba14..4de6de0 100644 --- a/README.md +++ b/README.md @@ -4,14 +4,14 @@ **PrivateBin** is a minimalist, open source online [pastebin](https://en.wikipedia.org/wiki/Pastebin) where the server has zero knowledge of pasted data. Data is encrypted and decrypted in the browser using 256bit AES in [Galois Counter mode](https://en.wikipedia.org/wiki/Galois/Counter_Mode). -This repository contains the Dockerfile and resources needed to create a docker image with a pre-installed PrivateBin instance in a secure default configuration. The images are based on the docker hub php:fpm-alpine image, extended with the GD module required to generate discussion avatars and the Nginx webserver to serve static JavaScript libraries, CSS & the logos. All logs of php-fpm and Nginx (access & errors) are forwarded to docker logs. +This repository contains the Dockerfile and resources needed to create a docker image with a pre-installed PrivateBin instance in a secure default configuration. The images are based on the docker hub alpine image, extended with the GD module required to generate discussion avatars and the Nginx webserver to serve static JavaScript libraries, CSS & the logos. All logs of php-fpm and Nginx (access & errors) are forwarded to docker logs. ## Running the image Assuming you have docker successfully installed and internet access, you can fetch and run the image from the docker hub like this: ```bash -docker run -d --restart="always" --read-only -p 8080:80 -v privatebin-data:/srv/data privatebin/nginx-fpm-alpine:1.2.1 +docker run -d --restart="always" --read-only -p 8080:80 -v privatebin-data:/srv/data privatebin/nginx-fpm-alpine ``` The parameters in detail: @@ -22,15 +22,30 @@ The parameters in detail: - `-d` - launches the container in the background. You can use `docker ps` and `docker logs` to check if the container is alive and well. - `--restart="always"` - restart the container if it crashes, mainly useful for production setups +> Note that the volume mounted must be owned by UID 65534 / GID 82. If you run the container in a docker instance with "userns-remap" you need to add your subuid/subgid range to these numbers. + ### Custom configuration In case you want to use a customized [conf.php](https://github.com/PrivateBin/PrivateBin/blob/master/cfg/conf.sample.php) file, for example one that has file uploads enabled or that uses a different template, add the file as a second volume: ```bash -docker run -d --restart="always" --read-only -p 8080:80 -v conf.php:/srv/cfg/conf.php:ro -v privatebin-data:/srv/data privatebin/nginx-fpm-alpine:1.2.1 +docker run -d --restart="always" --read-only -p 8080:80 -v conf.php:/srv/cfg/conf.php:ro -v privatebin-data:/srv/data privatebin/nginx-fpm-alpine ``` -Note: The `Filesystem` data storage is supported out of the box. The image includes PDO modules for MySQL and SQLite, required for the `Database` one, but you still need to keep the /srv/data persisted for the server salt and the traffic limiter. +Note: The `Filesystem` data storage is supported out of the box. The image includes PDO modules for MySQL, PostgreSQL and SQLite, required for the `Database` one, but you still need to keep the /srv/data persisted for the server salt and the traffic limiter. + +### Adjusting nginx or php-fpm settings + +You can attach your own `php.ini` or nginx configuration files to the folders `/etc/php7/conf.d/` and `/etc/nginx/conf.d/` respectively. This would for example let you adjust the maximum size these two services accept for file uploads, if you need more then the default 10 MiB. + +### Timezone settings + +The image supports the use of the following two environment variables to adjust the timezone. This is most useful to ensure the logs show the correct local time. + +- `TZ` +- `PHP_TZ` + +Note: The application internally handles expiration of pastes based on a UNIX timestamp that is calculated based on the timezone set during its creation. Changing the PHP_TZ will affect this and leads to earlier (if the timezone is increased) or later (if it is decreased) expiration then expected. ## Rolling your own image diff --git a/etc/nginx/nginx.conf b/etc/nginx/nginx.conf index b46d5fd..279f76d 100644 --- a/etc/nginx/nginx.conf +++ b/etc/nginx/nginx.conf @@ -1,6 +1,3 @@ -# Run as a unique, less privileged user for security reasons. -user nginx www-data; - # Sets the worker threads to the number of CPU cores available in the system for best performance. # Should be > the number of CPU cores. # Maximum number of connections = worker_processes * worker_connections @@ -66,8 +63,8 @@ http { # since TCP frames are filled up before being sent out. tcp_nopush on; - # Allow up to 3 MiB payload, privatebin defaults to 2 MiB. - client_max_body_size 3M; + # Allow up to 15 MiB payload, privatebin defaults to 10 MiB. + client_max_body_size 15M; # Load even moar configs include /etc/nginx/conf.d/*.conf; diff --git a/etc/php7/conf.d/00-docker.ini b/etc/php7/conf.d/00-docker.ini new file mode 100644 index 0000000..dc0c7c7 --- /dev/null +++ b/etc/php7/conf.d/00-docker.ini @@ -0,0 +1,64 @@ +; session.use_strict_mode specifies whether the module will use strict session id mode. If this +; mode is enabled, the module does not accept uninitialized session ID. If uninitialized session ID +; is sent from browser, new session ID is sent to browser. Applications are protected from session +; fixation via session adoption with strict mode. Defaults to 0 (disabled). +session.use_strict_mode=On + +; Enable assert() evaluation. +assert.active=Off + +; This determines whether errors should be printed to the screen as part of the output or if they +; should be hidden from the user. Value "stderr" sends the errors to stderr instead of stdout. +display_errors=Off + +; Tells whether script error messages should be logged to the server's error log or error_log. +; You're strongly advised to use error logging in place of error displaying on production web sites. +log_errors=On + + + +; increase size limits +upload_max_filesize=15M +post_max_size=15M + + + +; best practices + +; Disable deprecated short open tags ("