Skip to content

Conversation

@nupplaphil
Copy link
Contributor

@nupplaphil nupplaphil commented Aug 10, 2019

We, the Friendica upstream team (@MrPetovan @annando and I) want to add the Friendica image to the official image repository - see friendica/docker#74 .

Checklist for Review

NOTE: This checklist is intended for the use of the Official Images maintainers both to track the status of your PR and to help inform you and others of where we're at. As such, please leave the "checking" of items to the repository maintainers. If there is a point below for which you would like to provide additional information or note completion, please do so by commenting on the PR. Thanks! (and thanks for staying patient with us ❤️)

@nupplaphil
Copy link
Contributor Author

nupplaphil commented Aug 13, 2019

btw. I took nextcloud as a blueprint for our image :-)

Copy link
Member

@tianon tianon left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Howdy! Took an initial look and have a few comments (both on the proposed tags and on the Dockerization itself):

  1. LABEL keys should follow https://github.com/opencontainers/image-spec/blob/v1.0.1/annotations.md (in other words, LABEL maintainer=... should either be updated to something like org.opencontainers.image.authors or similar reverse-DNS name or simply dropped; we've got a separate Maintainers: field here so it's not necessary unless you care for having it)

  2. git is an interesting dependency -- does Friendica itself use that, or is that for the -dev variant?

  3. the debMultiarch variable doesn't appear to be used anywhere

  4. the # set recommended PHP.ini settings block appears to be using ; as a delimiter but is missing set -e (I believe this might actually be an issue with nextcloud too that we've missed previously 😅)

  5. VOLUME /var/www/html is OK, but I'd like to understand a little more about how Friendica is typically deployed/updated and how it uses the filesystem

    • for example, the WordPress image (where this pattern originated) treats the WordPress source/install itself as mutable data, performing self-updates via PHP, etc, so it makes sense to store the full installation inside a volume, but for some other applications the volumes can be more specific because the mutable state is less spread out
    • in the WordPress example, if it weren't for wp-config.php and self-updating, we'd probably instead have the image put the WordPress source code directly in /var/www/html and simply put VOLUME /var/www/html/wp-content instead (since that's where the real "mutable" state lives)
    • keeping this slim has the benefit of the container image actually providing the important files, and allows for neat things like being able to run a container with --read-only in order to ensure the core PHP files cannot be modified at runtime (which is an interesting security benefit that's not really possible with the entire source in a single VOLUME)
    • this would also have the benefit of making the entrypoint.sh script significantly simpler
  6. RUN a2enmod rewrite remoteip -- this block also appears to be using ; without set -e; see also docker-library/wordpress#383 (comment) (particularly that the default LogFormat does not use this remoteip functionality as-is)

  7. RUN chmod +x /*.sh -- running chmod in a separate layer often has issues, and we'd recommend instead making sure the .sh files have the +x bit tracked in Git directly (so it gets set by the COPY directly)

Maintainers: Friendica <[email protected]> (@friendica), Philipp Holzer <[email protected]> (@nupplaphil)
GitRepo: https://github.com/friendica/docker.git

Tags: 2019.06-apache, apache, stable-apache, production-apache, 2019.06, latest, stable, production
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are "production" and "stable" aliases that hold meaning for Friendica releases (as in, are those words used upstream), or are those aliases simply copied from nextcloud?

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Only stable is used for quarterly releases like 2019.06 and 2019.09.

Copy link
Contributor Author

@nupplaphil nupplaphil Aug 25, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'll recreate a new manifest and add just the stable tag after friendica/docker#76 is merged

GitCommit: ae608b6380adb65075843c8294d52af769087ce8
Directory: 2019.06/fpm-alpine

Tags: 2019.09-dev-apache, dev-apache, 2019.09-dev, dev
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is "2019.09-dev" a specific upstream release, or is this intended to be a master build/development snapshot?

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is the version string we use to designate Friendica installs running the develop branch before the 2019.09 release.

GitCommit: ae608b6380adb65075843c8294d52af769087ce8
Directory: 2019.09-dev/fpm-alpine

Tags: 2019.09-rc-apache, rc-apache, 2019.09-rc, rc
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Likewise, is "2019.09-rc" a specific release? (not seeing anything at https://github.com/friendica/friendica/tags?)

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's a development branch where we only merge fixes towards the 2019.09 release that will have a tag.

@nupplaphil
Copy link
Contributor Author

nupplaphil commented Aug 25, 2019

Hi @tianon and thanks for your review! I solved almost any finding of you and the new image will get available soon (after friendica/docker#76 is merged).

1. `LABEL` keys should follow https://github.com/opencontainers/image-spec/blob/v1.0.1/annotations.md (in other words, `LABEL maintainer=...` should either be updated to something like `org.opencontainers.image.authors` or similar reverse-DNS name or simply dropped; we've got a separate `Maintainers:` field here so it's not necessary unless you care for having it)

I don't need it, so I removed it with friendica/docker#76

2. `git` is an interesting dependency -- does Friendica itself use that, or is that for the `-dev` variant?

It's mainly for the -rc or -dev branch, but with the current images, it's possible to clone forks too (I introduced this option to easily test federation-wide changes, which aren't possible to test localy)

3. the `debMultiarch` variable doesn't appear to be used anywhere

Yes, you're right -> removed it with friendica/docker#76

4. the `# set recommended PHP.ini settings` block appears to be using `;` as a delimiter but is missing `set -e` (I believe this might actually be an issue with `nextcloud` too that we've missed previously sweat_smile)

Done (Copy&Paste error ;-) ) with friendica/docker#76

5. `VOLUME /var/www/html` is OK, but I'd like to understand a little more about how Friendica is typically deployed/updated and how it uses the filesystem
   
   * for example, the WordPress image (where this pattern originated) treats the WordPress source/install itself as mutable data, performing self-updates via PHP, etc, so it makes sense to store the full installation inside a volume, but for some other applications the volumes can be more specific because the mutable state is less spread out
   * in the WordPress example, if it weren't for `wp-config.php` and self-updating, we'd probably instead have the image put the WordPress source code directly in `/var/www/html` and simply put `VOLUME /var/www/html/wp-content` instead (since that's where the real "mutable" state lives)
   * keeping this slim has the benefit of the container image actually providing the important files, and allows for neat things like being able to run a container with `--read-only` in order to ensure the core PHP files _cannot_ be modified at runtime (which is an interesting security benefit that's not really possible with the entire source in a single `VOLUME`)
   * this would also have the benefit of making the `entrypoint.sh` script significantly simpler

The -dev and -rc branches are pulling the current files of Friendica after each restart. Therefore the whole /var/www/html directory is mutable. And currently, there are mutable directorys introduced by Friendica itself too:

  • config/
  • storage/ (optional directory for image-storage)
  • proxy/
  • view/smarty3/compiled
  • logs/

I can add each of these sub-directories as a VOLUME for the stable image and let the whole /var/www/html for the -dev/-rc branch if you like.

6. `RUN a2enmod rewrite remoteip` -- this block also appears to be using `;` without `set -e`; see also [docker-library/wordpress#383 (comment)](https://github.com/docker-library/wordpress/issues/383#issuecomment-507886512) (particularly that the default `LogFormat` does not use this `remoteip` functionality as-is)

Fixed with friendica/docker#76 , and thanks for the hint with the LogFormat!

7. `RUN chmod +x /*.sh` -- running `chmod` in a separate layer often has issues, and we'd recommend instead making sure the `.sh` files have the `+x` bit tracked in Git directly (so it gets set by the `COPY` directly)

Done with friendica/docker#76

@nupplaphil
Copy link
Contributor Author

rebased because of friendica/docker#78

@nupplaphil
Copy link
Contributor Author

@tianon with great respect due the fact that you obviously have a lot to do, would it nevertheless be possible to check the 2-3 things which I didn't changed but gave you an answer if these answers fits for you? Because I'd like to start refactoring the images in case it doesn't ;)

Thanks :)

@tianon
Copy link
Member

tianon commented Oct 2, 2019

Your patience is definitely appreciated 😅 ❤️ 😇

Regarding git, that makes sense, and in light of the VOLUME point, I think it's likely fine (and your notes about the VOLUME make sense -- I don't think it really makes a ton of sense to split that up further).

I think the Dockerfile is looking pretty solid now, although I hadn't looked at the .sh files too deeply yet (hoping that perhaps we could make a lot of what's there semi-moot by discussing VOLUME more, but alas).

What's the intended use of cron.sh? Is that supposed to run as a long-running sidecar to the main Apache / FPM container? (at the minimum, php /var/www/html/bin/daemon.php -f start should include exec so it becomes PID 1 and the shell goes away, but I'd like to understand more about what it does)

"TODO let the database and the autoinstall time to complete - not winning a beauty contest" is definitely something we'll want resolved somehow more cleanly than just sleeping for 15 seconds 😄

Looking at entrypoint.sh, there's a lot of complexity here, and I think some of it could be simpler.

For example, version_greater could probably be implemented more reliably via PHP's version_compare (given that this is a PHP container, we can safely assume PHP is available):

root@65bdab888b82:/# php -r 'exit(version_compare($argv[1], $argv[2]) > 0 ? 0 : 1);' -- 1.2.3 4.5.6
root@65bdab888b82:/# echo $?
1

Also, it seems like everywhere run_as gets used includes cd /var/www/html but it also embeds that same cd, but even then only in the running-as-root case? Maybe something like this would be easier to keep consistent:

# run an command with the www-data user
run_as() {
	set -- -eu -c "cd /var/www/html; $*"
	if [ "$(id -u)" -eq 0 ]; then
		su - www-data -s /bin/sh "$@"
	else
		sh  "$@"
	fi
}

(and then drop the cd bits in each run_as line)

There are also a few lines doing things like sh -c "..." that seem like they're really looking for eval "..."?

@nupplaphil
Copy link
Contributor Author

nupplaphil commented Nov 30, 2019

Your patience is definitely appreciated sweat_smile heart innocent

👍

What's the intended use of cron.sh? Is that supposed to run as a long-running sidecar to the main Apache / FPM container? (at the minimum, php /var/www/html/bin/daemon.php -f start should include exec so it becomes PID 1 and the shell goes away, but I'd like to understand more about what it does)

Yes, it's a background task, which is running about every 10 minutes and is the "heart" of a node. It pulls latest news, cleans up DB-stuff, ... It's now called per exec

"TODO let the database and the autoinstall time to complete - not winning a beauty contest" is definitely something we'll want resolved somehow more cleanly than just sleeping for 15 seconds smile

Fixed with friendica/docker#88

Looking at entrypoint.sh, there's a lot of complexity here, and I think some of it could be simpler.

Therefore I completely separated the "stable" entrypoint from the "dev" entrypoint (friendica/docker#87)

For example, version_greater could probably be implemented more reliably via PHP's version_compare (given that this is a PHP container, we can safely assume PHP is available):

root@65bdab888b82:/# php -r 'exit(version_compare($argv[1], $argv[2]) > 0 ? 0 : 1);' -- 1.2.3 4.5.6
root@65bdab888b82:/# echo $?
1

The version_compare() should be aware that 2019.09-dev is lower than 2019.09. That was the reason why I added a own sub.

Also, it seems like everywhere run_as gets used includes cd /var/www/html but it also embeds that same cd, but even then only in the running-as-root case? Maybe something like this would be easier to keep consistent:

# run an command with the www-data user
run_as() {
	set -- -eu -c "cd /var/www/html; $*"
	if [ "$(id -u)" -eq 0 ]; then
		su - www-data -s /bin/sh "$@"
	else
		sh  "$@"
	fi
}

(and then drop the cd bits in each run_as line)

Fixed with friendica/docker#85

There are also a few lines doing things like sh -c "..." that seem like they're really looking for eval "..."?

Fixed with friendica/docker#85

I pushed the latest version to this PR now :-)

@tianon
Copy link
Member

tianon commented Dec 31, 2019

Thanks again for being patient here. I think this generally is looking really good.

I had a couple minor suggestions that I do not think this needs to wait on / be updated with which I submitted as a PR at friendica/docker#92

However, there are some comments I made on the docs PR that I think need to be addressed before we can merge: docker-library/docs#1551 (review)

@yosifkit
Copy link
Member

yosifkit commented Jan 3, 2020

A few minor bits of feedback.

  • Fix $MYSQL_PORT default fallback & Removes the packed binary friendica/docker#96 👍

  • entrypoint-dev.sh should end with exec /entrypoint.sh "$@" (just missing an exec)

  • entrypoint.sh has sed -i "s/:Linux\ User:/:${FRIENDICA_SITENAME}:/g" /etc/passwd, but as far as I can tell, won't work correctly:

    $ # doesn't match on Alpine, since there are commas
    $ docker run -it --rm php:7.3-fpm-alpine sh
    /var/www/html # cat /etc/passwd | grep 'Linux User'
    www-data:x:82:82:Linux User,,,:/home/www-data:/sbin/nologin
    
    $ # there is no "Linux User" in the gecos field on Debian
    $ docker run -it --rm php:7.3-fpm-stretch bash
    root@578bd5fddd63:/var/www/html# cat /etc/passwd | grep 'Linux User'
    root@578bd5fddd63:/var/www/html# cat /etc/passwd | grep 'www-data'
    www-data:x:33:33:www-data:/var/www:/usr/sbin/nologin

    It may be better to key off the line starting with www-data (and root in the earlier sed) and filling in/replacing the gecos field (since "Linux User,,," looks like a bug to me and so I filed a fix to the gecos field for php-alpine images: Set gecos field on Alpine to match Debian php#935).
    Something like this sed should work:
    sed -Ei "s/(^www-data:([^:]*:){3})[^:]*/\1${variable}/" /etc/passwd

  • shouldn't need to install $PHPIZE_DEPS on the Debian-based images since they are kept in the image, but it should be harmless


Minor side note, you may want to consider stripping colons (and newlines/carriage returns) from FRIENDICA_SITENAME (since they will mess up /etc/passwd formatting).

@tianon
Copy link
Member

tianon commented Jan 3, 2020

sed -Ei "s/(^www-data:([^:]*:){3})[^:]*/\1${variable}/" /etc/passwd

Instead of doing sed on /etc/passwd, it would probably be better to install the shadow package in Alpine and use usermod --comment (in both Alpine and Debian).

@yosifkit

This comment has been minimized.

@yosifkit

This comment has been minimized.

@nupplaphil
Copy link
Contributor Author

nupplaphil commented Jan 4, 2020

I'm sorry, I found two issues left, introduced with friendica/docker#97 .. It'll fixed after the merge of friendica/docker#98

Done

@yosifkit
Copy link
Member

yosifkit commented Jan 6, 2020

Diff:
diff --git a/_bashbrew-arches b/_bashbrew-arches
index e69de29..a85482a 100644
--- a/_bashbrew-arches
+++ b/_bashbrew-arches
@@ -0,0 +1,36 @@
+friendica:dev @ amd64
+friendica:dev @ arm32v5
+friendica:dev @ arm32v7
+friendica:dev @ arm64v8
+friendica:dev @ i386
+friendica:dev @ ppc64le
+friendica:dev-fpm @ amd64
+friendica:dev-fpm @ arm32v5
+friendica:dev-fpm @ arm32v7
+friendica:dev-fpm @ arm64v8
+friendica:dev-fpm @ i386
+friendica:dev-fpm @ ppc64le
+friendica:dev-fpm-alpine @ amd64
+friendica:dev-fpm-alpine @ arm32v6
+friendica:dev-fpm-alpine @ arm32v7
+friendica:dev-fpm-alpine @ arm64v8
+friendica:dev-fpm-alpine @ i386
+friendica:dev-fpm-alpine @ ppc64le
+friendica:stable @ amd64
+friendica:stable @ arm32v5
+friendica:stable @ arm32v7
+friendica:stable @ arm64v8
+friendica:stable @ i386
+friendica:stable @ ppc64le
+friendica:stable-fpm @ amd64
+friendica:stable-fpm @ arm32v5
+friendica:stable-fpm @ arm32v7
+friendica:stable-fpm @ arm64v8
+friendica:stable-fpm @ i386
+friendica:stable-fpm @ ppc64le
+friendica:stable-fpm-alpine @ amd64
+friendica:stable-fpm-alpine @ arm32v6
+friendica:stable-fpm-alpine @ arm32v7
+friendica:stable-fpm-alpine @ arm64v8
+friendica:stable-fpm-alpine @ i386
+friendica:stable-fpm-alpine @ ppc64le
diff --git a/_bashbrew-list b/_bashbrew-list
index e69de29..7fe1eb1 100644
--- a/_bashbrew-list
+++ b/_bashbrew-list
@@ -0,0 +1,20 @@
+friendica:2019.12
+friendica:2019.12-apache
+friendica:2019.12-fpm
+friendica:2019.12-fpm-alpine
+friendica:2020.03-dev
+friendica:2020.03-dev-apache
+friendica:2020.03-dev-fpm
+friendica:2020.03-dev-fpm-alpine
+friendica:apache
+friendica:dev
+friendica:dev-apache
+friendica:dev-fpm
+friendica:dev-fpm-alpine
+friendica:fpm
+friendica:fpm-alpine
+friendica:latest
+friendica:stable
+friendica:stable-apache
+friendica:stable-fpm
+friendica:stable-fpm-alpine
diff --git a/friendica_dev-fpm-alpine/Dockerfile b/friendica_dev-fpm-alpine/Dockerfile
new file mode 100644
index 0000000..524cb07
--- /dev/null
+++ b/friendica_dev-fpm-alpine/Dockerfile
@@ -0,0 +1,108 @@
+# DO NOT EDIT: created by update.sh from Dockerfile-alpine.template
+FROM php:7.3-fpm-alpine
+
+# entrypoint.sh and cron.sh dependencies
+RUN set -ex; \
+    apk add --no-cache \
+        rsync \
+        git \
+# For mail() support
+        ssmtp \
+        shadow;
+
+# install the PHP extensions we need
+# see https://friendi.ca/resources/requirements/
+RUN set -ex; \
+    \
+    apk add --no-cache --virtual .build-deps \
+        mysql-client \
+        bash \
+        $PHPIZE_DEPS \
+        libpng-dev \
+        libjpeg-turbo-dev \
+        imagemagick-dev \
+        libtool \
+        libmemcached-dev \
+        cyrus-sasl-dev \
+        libjpeg-turbo-dev \
+        freetype-dev \
+        librsvg \
+        pcre-dev \
+        libzip-dev \
+        icu-dev \
+        openldap-dev \
+    ; \
+    \
+    docker-php-ext-configure gd \
+        --with-gd \
+        --with-freetype-dir=/usr/include/ \
+        --with-png-dir=/usr/include/ \
+        --with-jpeg-dir=/usr/include/ \
+    ; \
+    \
+    docker-php-ext-install -j "$(nproc)" \
+       pdo_mysql \
+       gd \
+       zip \
+       opcache \
+       pcntl \
+       ldap \
+    ; \
+    \
+# pecl will claim success even if one install fails, so we need to perform each install separately
+    pecl install APCu-5.1.18; \
+    pecl install memcached-3.1.5; \
+    pecl install redis-5.1.1; \
+    pecl install imagick-3.4.4; \
+    \
+    docker-php-ext-enable \
+    	apcu \
+        memcached \
+        redis \
+        imagick \
+    ; \
+    \
+    runDeps="$( \
+      scanelf --needed --nobanner --format '%n#p' --recursive /usr/local/lib/php/extensions \
+          | tr ',' '\n' \
+          | sort -u \
+          | awk 'system("[ -e /usr/local/lib" $1 " ]") == 0 { next } { print "so:" $1 }' \
+    )"; \
+    apk add --no-network --virtual .friendica-phpext-rundeps $runDeps; \
+    apk del --no-network .build-deps;
+
+# set recommended PHP.ini settings
+RUN set -ex; \
+    { \
+        echo 'opcache.enable=1' ; \
+        echo 'opcache.interned_strings_buffer=8'; \
+        echo 'opcache.max_accelerated_files=10000'; \
+        echo 'opcache.memory_consumption=128'; \
+        echo 'opcache.save_comments=1'; \
+        echo 'opcache.revalidte_freq=1'; \
+    } > /usr/local/etc/php/conf.d/opcache-recommended.ini; \
+    \
+    { \
+        echo sendmail_path = "/usr/sbin/sendmail -t -i"; \
+    } > /usr/local/etc/php/conf.d/sendmail.ini; \
+    \
+    echo 'apc.enable_cli=1' >> /usr/local/etc/php/conf.d/docker-php-ext-apcu.ini; \
+    \
+    echo 'memory_limit=512M' > /usr/local/etc/php/conf.d/memory-limit.ini; \
+    \
+    mkdir /var/www/data; \
+    chown -R www-data:root /var/www; \
+    chmod -R g=u /var/www
+
+VOLUME /var/www/html
+
+
+ENV FRIENDICA_VERSION 2020.03-dev
+ENV FRIENDICA_ADDONS 2020.03-dev
+
+
+COPY *.sh upgrade.exclude /
+COPY config/* /usr/src/friendica/config/
+
+ENTRYPOINT ["/entrypoint-dev.sh"]
+CMD ["php-fpm"]
diff --git a/friendica_dev-fpm-alpine/config/00apcu.config.php b/friendica_dev-fpm-alpine/config/00apcu.config.php
new file mode 100644
index 0000000..d6dac4f
--- /dev/null
+++ b/friendica_dev-fpm-alpine/config/00apcu.config.php
@@ -0,0 +1,12 @@
+<?php
+
+/**
+ * If nothing else set, use APCu as a caching driver (best performance for local caching)
+ */
+
+return [
+	'system' => [
+		'cache_driver' => 'apcu',
+		'session_handler' => 'cache',
+	],
+];
diff --git a/friendica_dev-fpm-alpine/config/01redis.config.php b/friendica_dev-fpm-alpine/config/01redis.config.php
new file mode 100644
index 0000000..1a43c95
--- /dev/null
+++ b/friendica_dev-fpm-alpine/config/01redis.config.php
@@ -0,0 +1,15 @@
+<?php
+
+if (getenv('REDIS_HOST')) {
+	return [
+		'system' => [
+			'lock_driver' => 'redis',
+			'redis_host' => getenv('REDIS_HOST'),
+			'redis_port' => (getenv('REDIS_PORT') ? getenv('REDIS_PORT') : ''),
+			'redis_password' => (getenv('REDIS_PW') ? getenv('REDIS_PW') : ''),
+			'redis_db' => (getenv('REDIS_DB') ? getenv('REDIS_DB') : 0),
+		],
+	];
+} else {
+	return [];
+}
diff --git a/friendica_dev-fpm-alpine/config/zz-docker.config.php b/friendica_dev-fpm-alpine/config/zz-docker.config.php
new file mode 100644
index 0000000..c9e5ed8
--- /dev/null
+++ b/friendica_dev-fpm-alpine/config/zz-docker.config.php
@@ -0,0 +1,66 @@
+<?php
+
+/**
+ * Fallback config to make it possible overwriting config values
+ * because of docker environment variables
+ *
+ * This doesn't affect DB configurations, but will replace other config values
+ */
+
+$config = [
+	'system' => [
+		// Necessary because otherwise the daemon isn't working
+		'pidfile' => '/var/run/friendica.pid',
+
+		'logfile' => '/var/www/html/friendica.log',
+		'loglevel' => 'notice',
+	],
+	'storage' => [
+		'filesystem_path' => '/var/www/html/storage',
+	],
+];
+
+if (getenv('FRIENDICA_TZ')) {
+	$config['config']['timezone'] = getenv('FRIENDICA_TZ');
+}
+
+if (getenv('FRIENDICA_LANG')) {
+	$config['config']['language'] = getenv('FRIENDICA_LANG');
+}
+
+if (getenv('FRIENDICA_ADMIN_MAIL')) {
+	$config['config']['admin_mail'] = getenv('FRIENDICA_ADMIN_MAIL');
+}
+
+if (getenv('FRIENDICA_SITENAME')) {
+	$config['config']['sitename'] = getenv('FRIENDICA_SITENAME');
+}
+
+if (!empty(getenv('FRIENDICA_NO_VALIDATION'))) {
+	$config['system']['disable_url_validation'] = true;
+	$config['system']['disable_email_validation'] = true;
+}
+
+if (!empty(getenv('FRIENDICA_DATA'))) {
+	$config['storage']['class'] = \Friendica\Model\Storage\Filesystem::class;
+
+	if (!empty(getenv('FRIENDICA_DATA_DIR'))) {
+		$config['storage']['filesystem_path'] = getenv('FRIENDICA_DATA');
+	}
+}
+
+if (!empty(getenv('FRIENDICA_DEBUGGING'))) {
+	$config['system']['debugging'] = true;
+	if (!empty(getenv('FRIENDICA_LOGFILE'))) {
+		$config['system']['logfile'] = getenv('FRIENDICA_LOGFILE');
+	}
+	if (!empty(getenv('FRIENDICA_LOGLEVEL'))) {
+		$config['system']['loglevel'] = getenv('FRIENDICA_LOGLEVEL');
+	}
+}
+
+if (!empty(getenv('HOSTNAME'))) {
+	$config['config']['hostname'] = getenv('HOSTNAME');
+}
+
+return $config;
diff --git a/friendica_dev-fpm-alpine/cron.sh b/friendica_dev-fpm-alpine/cron.sh
new file mode 100755
index 0000000..3f03a41
--- /dev/null
+++ b/friendica_dev-fpm-alpine/cron.sh
@@ -0,0 +1,13 @@
+#!/bin/sh
+trap "break;exit" HUP INT TERM
+
+while [ ! -f /var/www/html/bin/daemon.php ]; do
+    sleep 1
+done
+
+echo "Waiting for MySQL $MYSQL_HOST initialization..."
+if php /var/www/html/bin/wait-for-connection "$MYSQL_HOST" "${MYSQL_PORT:-3306}" 300; then
+  exec php /var/www/html/bin/daemon.php -f start
+else
+  echo "[ERROR] Waited 300 seconds, no response" >&2
+fi
diff --git a/friendica_dev-fpm-alpine/entrypoint-dev.sh b/friendica_dev-fpm-alpine/entrypoint-dev.sh
new file mode 100755
index 0000000..55afb80
--- /dev/null
+++ b/friendica_dev-fpm-alpine/entrypoint-dev.sh
@@ -0,0 +1,69 @@
+#!/bin/sh
+set -eu
+
+# checks if the branch and repository exists
+check_branch() {
+	repo=${1:-}
+	branch=${2:-}
+	git ls-remote --heads --tags "https://github.com/$repo" | grep -E "refs/(heads|tags)/${branch}$" >/dev/null
+	[ "$?" -eq "0" ]
+}
+
+# clones the whole develop branch (Friendica and Addons)
+clone_develop() {
+	friendica_git="${FRIENDICA_VERSION}"
+	addons_git="${FRIENDICA_ADDONS}"
+	friendica_repo="${FRIENDICA_REPOSITORY:-friendica/friendica}"
+	friendica_addons_repo="${FRIENDICA_ADDONS_REPO:-friendica/friendica-addons}"
+
+	if echo "{$friendica_git,,}" | grep -Eq '^.*\-dev'; then
+		friendica_git="develop"
+	fi
+
+	if echo "{$addons_git,,}" | grep -Eq '^.*\-dev'; then
+		addons_git="develop"
+	fi
+
+	# Check if the branches exist before wiping the
+	if check_branch "$friendica_repo" "$friendica_git" && check_branch "$friendica_addons_repo" "$addons_git" ; then
+		echo "Cloning '${friendica_git}' from GitHub repository '${friendica_repo}' ..."
+
+		# Removing the whole directory first
+		rm -fr /usr/src/friendica
+		git clone -q -b ${friendica_git} "https://github.com/${friendica_repo}" /usr/src/friendica
+
+		mkdir /usr/src/friendica/addon
+		git clone -q -b ${addons_git} "https://github.com/${friendica_addons_repo}" /usr/src/friendica/addon
+
+		echo "Download finished"
+
+		if [ ! -f /usr/src/friendica/VERSION ]; then
+			echo "Couldn't clone repository"
+			exit 1
+		fi
+
+		/usr/src/friendica/bin/composer.phar install --no-dev -d /usr/src/friendica
+		return 0
+
+	else
+		if check_branch "$friendica_repo" "$friendica_git"; then
+			echo "$friendica_repo/$friendica_git is not valid."
+		else
+			echo "$friendica_addons_repo/$addons_git is not valid."
+		fi
+		echo "Using old version."
+		return 1
+
+	fi
+}
+
+# just check if we execute apache or php-fpm
+if expr "$1" : "apache" 1>/dev/null || [ "$1" = "php-fpm" ]; then
+	# cloning from git is just possible for develop or Release Candidats
+	if echo "${FRIENDICA_VERSION}" | grep -Eq '^.*(\-dev|-rc|-RC)' || [ "${FRIENDICA_UPGRADE:-false}" = "true" ] || [ ! -f /usr/src/friendica/VERSION ]; then
+		# just clone & check if it's a new install or upgrade
+		clone_develop
+	fi
+fi
+
+exec /entrypoint.sh "$@"
diff --git a/friendica_dev-fpm-alpine/entrypoint.sh b/friendica_dev-fpm-alpine/entrypoint.sh
new file mode 100755
index 0000000..99b5f4a
--- /dev/null
+++ b/friendica_dev-fpm-alpine/entrypoint.sh
@@ -0,0 +1,149 @@
+#!/bin/sh
+set -eu
+
+# run an command with the www-data user
+run_as() {
+	set -- -c "cd /var/www/html; $*"
+	if [ "$(id -u)" -eq 0 ]; then
+		su - www-data -s /bin/sh "$@"
+	else
+		sh  "$@"
+	fi
+}
+
+# checks if the the first parameter is greater than the second parameter
+version_greater() {
+	[ "$(printf '%s\n' "$@" | sort -r -t '-' -k2,2  | sort -t '.' -n -k1,1 -k2,2 -s | head -n 1)" != "$1" ]
+}
+
+setup_ssmtp() {
+	if [ -n "${HOSTNAME+x}" ] && [ -n "${SMTP+x}" ] && [ "${SMTP}" != "localhost" ]; then
+		SITENAME="${FRIENDICA_SITENAME:-Friendica Social Network}"
+		echo "Setup SSMTP for '$SITENAME' with '$SMTP' ..."
+
+		smtp_from=${SMTP_FROM:-no-reply}
+
+		# Setup SSMTP
+		usermod --comment "$(echo "$SITENAME" | tr -dc '[:print:]')" root
+		usermod --comment "$(echo "$SITENAME" | tr -dc '[:print:]')" www-data
+
+		# add possible mail-senders
+		{
+		 echo "www-data:$smtp_from@$HOSTNAME:$SMTP"
+		 echo "root::$smtp_from@$HOSTNAME:$SMTP"
+		} > /etc/ssmtp/revaliases
+
+		# replace ssmtp.conf settings
+		{
+		 echo "root=:$smtp_from@$HOSTNAME"
+		 echo "hostname=$HOSTNAME"
+		 echo "mailhub=$SMTP"
+		 echo "FromLineOverride=YES"
+		 if [ -n "${SMTP_TLS+x}" ]; then echo "UseTLS=$SMTP_TLS"; fi
+		 if [ -n "${SMTP_STARTTLS+x}" ]; then echo "UseSTARTTLS=$SMTP_STARTTLS"; fi
+		 if [ -n "${SMTP_AUTH_USER+x}" ]; then echo "AuthUser=$SMTP_AUTH_USER"; fi
+		 if [ -n "${SMTP_AUTH_PASS+x}" ]; then echo "AuthPass=$SMTP_AUTH_PASS";fi
+		 if [ -n "${SMTP_AUTH_METHOD+x}" ]; then echo "AuthMethod=$SMTP_AUTH_METHOD"; fi
+		} > /etc/ssmtp/ssmtp.conf
+
+		echo "Setup finished"
+	fi
+}
+
+# just check if we execute apache or php-fpm
+if expr "$1" : "apache" 1>/dev/null || [ "$1" = "php-fpm" ]; then
+	installed_version="0.0.0.0"
+	if [ -f /var/www/html/VERSION ]; then
+		installed_version="$(cat /var/www/html/VERSION)"
+	fi
+
+	image_version="$(cat /usr/src/friendica/VERSION)"
+
+	# no downgrading possible
+	if version_greater "$installed_version" "$image_version"; then
+		echo "Can't copy Friendica sources because the version of the data ($installed_version) is higher than the docker image ($image_version)"
+		exit 1
+	fi
+
+	setup_ssmtp
+
+	# check it just in case the version is greater or if we force the upgrade
+	if version_greater "$image_version" "$installed_version" || [ "${FRIENDICA_UPGRADE:-false}" = "true" ]; then
+		echo "Initializing Friendica $image_version ..."
+
+		if [ "$installed_version" != "0.0.0.0" ]; then
+			echo "Upgrading Friendica from $installed_version ..."
+		fi
+
+		if [ "$(id -u)" -eq 0 ]; then
+			rsync_options="-rlDog --chown=www-data:www-data"
+		else
+			rsync_options="-rlD"
+		fi
+
+		rsync $rsync_options --delete --exclude-from=/upgrade.exclude /usr/src/friendica/ /var/www/html/
+
+		# Update docker-based config files, but never delete other config files
+		rsync $rsync_options --update /usr/src/friendica/config/ /var/www/html/config/
+
+		# In case there is no .htaccess, copy it from the default dist file
+		if [ ! -f "/var/www/html/.htaccess" ]; then
+			cp "/var/www/html/.htaccess-dist" "/var/www/html/.htaccess"
+		fi
+
+		if [ -d /var/www/html/view/smarty3 ]; then
+			chmod -R 777 /var/www/html/view/smarty3
+		fi
+		echo "Initializing finished"
+
+		# install
+		if [ "$installed_version" = "0.0.0.0" ]; then
+			echo "New Friendica instance"
+
+			install=false
+			if [ -n "${MYSQL_DATABASE+x}" ] && [ -n "${MYSQL_PASSWORD+x}" ] && [ -n "${MYSQL_HOST+x}" ] && [ -n "${MYSQL_USER+x}" ] && [ -n "${FRIENDICA_ADMIN_MAIL+x}" ] && [ -n "${FRIENDICA_URL+x}" ]; then
+				echo "Installation with environment variables"
+
+				FRIENDICA_TZ=${FRIENDICA_TZ:-America/LosAngeles}
+				FRIENDICA_LANG=${FRIENDICA_LANG:-en}
+				MYSQL_PORT=${MYSQL_PORT:-3306}
+
+				# shellcheck disable=SC2016
+				install_options='-s --dbhost "'$MYSQL_HOST'" --dbport "'$MYSQL_PORT'" --dbdata "'$MYSQL_DATABASE'" --dbuser "'$MYSQL_USER'" --dbpass "'$MYSQL_PASSWORD'"'
+
+				# shellcheck disable=SC2016
+				install_options=$install_options' --admin "'$FRIENDICA_ADMIN_MAIL'" --tz "'$FRIENDICA_TZ'" --lang "'$FRIENDICA_LANG'" --url "'$FRIENDICA_URL'"'
+				install=true
+			fi
+
+			if [ "$install" = true ]; then
+				echo "Waiting for MySQL $MYSQL_HOST initialization..."
+				if run_as "php /var/www/html/bin/wait-for-connection $MYSQL_HOST ${MYSQL_PORT:-3306} 300"; then
+
+					echo "Starting Friendica installation ..."
+					run_as "php /var/www/html/bin/console.php autoinstall $install_options"
+
+					rm -fr /var/www/html/view/smarty3/compiled
+
+					# load other config files (*.config.php) to the config folder
+					if [ -d "/usr/src/config" ]; then
+					  rsync $rsync_options --ignore-existing /usr/src/config/ /var/www/html/config/
+					fi
+
+					echo "Installation finished"
+				else
+					echo "[ERROR] Waited 300 seconds, no response" >&2
+				fi
+			else
+				echo "Running web-based installer on first connect!"
+			fi
+		# upgrade
+		else
+			echo "Upgrading Friendica ..."
+			run_as 'php /var/www/html/bin/console.php dbstructure update'
+			echo "Upgrading finished"
+		fi
+	fi
+fi
+
+exec "$@"
diff --git a/friendica_dev-fpm-alpine/upgrade.exclude b/friendica_dev-fpm-alpine/upgrade.exclude
new file mode 100644
index 0000000..2fb6533
--- /dev/null
+++ b/friendica_dev-fpm-alpine/upgrade.exclude
@@ -0,0 +1,10 @@
+/.git/
+/photo/
+/proxy/
+/.htconfig.php
+/.htaccess
+/home.*
+/config/
+/storage/
+/log/
+*.log
\ No newline at end of file
diff --git a/friendica_dev-fpm/Dockerfile b/friendica_dev-fpm/Dockerfile
new file mode 100644
index 0000000..1f0dfb1
--- /dev/null
+++ b/friendica_dev-fpm/Dockerfile
@@ -0,0 +1,121 @@
+# DO NOT EDIT: created by update.sh from Dockerfile-debian.template
+FROM php:7.3-fpm-stretch
+
+# entrypoint.sh and cron.sh dependencies
+RUN set -ex; \
+    \
+    apt-get update; \
+    apt-get install -y --no-install-recommends \
+        rsync \
+        bzip2 \
+        git \
+# For mail() support
+        ssmtp \
+    ; \
+    rm -rf /var/lib/apt/lists/*;
+
+# install the PHP extensions we need
+# see https://friendi.ca/resources/requirements/
+RUN set -ex; \
+    \
+    savedAptMark="$(apt-mark showmanual)"; \
+    \
+    apt-get update; \
+    apt-get install -y --no-install-recommends \
+        mysql-client \
+        bash \
+        libpng-dev \
+        libjpeg62-turbo-dev \
+        libtool \
+        libmagick++-dev \
+        libmemcached-dev \
+        libgraphicsmagick1-dev \
+        libfreetype6-dev \
+        librsvg2-2 \
+        libzip-dev \
+        libldap2-dev \
+    ; \
+    \
+        debMultiarch="$(dpkg-architecture --query DEB_BUILD_MULTIARCH)"; \
+    \
+    docker-php-ext-configure gd \
+        --with-gd \
+        --with-freetype-dir=/usr/include/ \
+        --with-png-dir=/usr/include/ \
+        --with-jpeg-dir=/usr/include/ \
+    ; \
+    docker-php-ext-configure ldap \
+        	--with-libdir=lib/$debMultiarch/ \
+	; \
+    docker-php-ext-install -j "$(nproc)" \
+        pdo_mysql \
+        gd \
+        zip \
+        opcache \
+        ctype \
+        pcntl \
+        ldap \
+    ; \
+    \
+# pecl will claim success even if one install fails, so we need to perform each install separately
+    pecl install apcu-5.1.18; \
+    pecl install memcached-3.1.5; \
+    pecl install redis-5.1.1; \
+    pecl install imagick-3.4.4; \
+    \
+    docker-php-ext-enable \
+        apcu \
+        memcached \
+        redis \
+        imagick \
+    ; \
+    \
+# reset apt-mark's "manual" list so that "purge --auto-remove" will remove all build dependencies
+    apt-mark auto '.*' > /dev/null; \
+    apt-mark manual $savedAptMark; \
+    ldd "$(php -r 'echo ini_get("extension_dir");')"/*.so \
+      | awk '/=>/ { print $3 }' \
+      | sort -u \
+      | xargs -r dpkg-query -S \
+      | cut -d: -f1 \
+      | sort -u \
+      | xargs -rt apt-mark manual; \
+    \
+    apt-get purge -y --auto-remove -o APT::AutoRemove::RecommendsImportant=false; \
+    rm -rf /var/lib/apt/lists/*
+
+# set recommended PHP.ini settings
+RUN set -ex; \
+    { \
+        echo 'opcache.enable=1' ; \
+        echo 'opcache.interned_strings_buffer=8'; \
+        echo 'opcache.max_accelerated_files=10000'; \
+        echo 'opcache.memory_consumption=128'; \
+        echo 'opcache.save_comments=1'; \
+        echo 'opcache.revalidte_freq=1'; \
+    } > /usr/local/etc/php/conf.d/opcache-recommended.ini; \
+    \
+    { \
+        echo sendmail_path = "/usr/sbin/sendmail -t -i"; \
+    } > /usr/local/etc/php/conf.d/sendmail.ini; \
+    \
+    echo 'apc.enable_cli=1' >> /usr/local/etc/php/conf.d/docker-php-ext-apcu.ini; \
+    \
+    echo 'memory_limit=512M' > /usr/local/etc/php/conf.d/memory-limit.ini; \
+    \
+    mkdir /var/www/data; \
+    chown -R www-data:root /var/www; \
+    chmod -R g=u /var/www
+
+VOLUME /var/www/html
+
+
+ENV FRIENDICA_VERSION 2020.03-dev
+ENV FRIENDICA_ADDONS 2020.03-dev
+
+
+COPY *.sh upgrade.exclude /
+COPY config/* /usr/src/friendica/config/
+
+ENTRYPOINT ["/entrypoint-dev.sh"]
+CMD ["php-fpm"]
diff --git a/friendica_dev-fpm/config/00apcu.config.php b/friendica_dev-fpm/config/00apcu.config.php
new file mode 100644
index 0000000..d6dac4f
--- /dev/null
+++ b/friendica_dev-fpm/config/00apcu.config.php
@@ -0,0 +1,12 @@
+<?php
+
+/**
+ * If nothing else set, use APCu as a caching driver (best performance for local caching)
+ */
+
+return [
+	'system' => [
+		'cache_driver' => 'apcu',
+		'session_handler' => 'cache',
+	],
+];
diff --git a/friendica_dev-fpm/config/01redis.config.php b/friendica_dev-fpm/config/01redis.config.php
new file mode 100644
index 0000000..1a43c95
--- /dev/null
+++ b/friendica_dev-fpm/config/01redis.config.php
@@ -0,0 +1,15 @@
+<?php
+
+if (getenv('REDIS_HOST')) {
+	return [
+		'system' => [
+			'lock_driver' => 'redis',
+			'redis_host' => getenv('REDIS_HOST'),
+			'redis_port' => (getenv('REDIS_PORT') ? getenv('REDIS_PORT') : ''),
+			'redis_password' => (getenv('REDIS_PW') ? getenv('REDIS_PW') : ''),
+			'redis_db' => (getenv('REDIS_DB') ? getenv('REDIS_DB') : 0),
+		],
+	];
+} else {
+	return [];
+}
diff --git a/friendica_dev-fpm/config/zz-docker.config.php b/friendica_dev-fpm/config/zz-docker.config.php
new file mode 100644
index 0000000..c9e5ed8
--- /dev/null
+++ b/friendica_dev-fpm/config/zz-docker.config.php
@@ -0,0 +1,66 @@
+<?php
+
+/**
+ * Fallback config to make it possible overwriting config values
+ * because of docker environment variables
+ *
+ * This doesn't affect DB configurations, but will replace other config values
+ */
+
+$config = [
+	'system' => [
+		// Necessary because otherwise the daemon isn't working
+		'pidfile' => '/var/run/friendica.pid',
+
+		'logfile' => '/var/www/html/friendica.log',
+		'loglevel' => 'notice',
+	],
+	'storage' => [
+		'filesystem_path' => '/var/www/html/storage',
+	],
+];
+
+if (getenv('FRIENDICA_TZ')) {
+	$config['config']['timezone'] = getenv('FRIENDICA_TZ');
+}
+
+if (getenv('FRIENDICA_LANG')) {
+	$config['config']['language'] = getenv('FRIENDICA_LANG');
+}
+
+if (getenv('FRIENDICA_ADMIN_MAIL')) {
+	$config['config']['admin_mail'] = getenv('FRIENDICA_ADMIN_MAIL');
+}
+
+if (getenv('FRIENDICA_SITENAME')) {
+	$config['config']['sitename'] = getenv('FRIENDICA_SITENAME');
+}
+
+if (!empty(getenv('FRIENDICA_NO_VALIDATION'))) {
+	$config['system']['disable_url_validation'] = true;
+	$config['system']['disable_email_validation'] = true;
+}
+
+if (!empty(getenv('FRIENDICA_DATA'))) {
+	$config['storage']['class'] = \Friendica\Model\Storage\Filesystem::class;
+
+	if (!empty(getenv('FRIENDICA_DATA_DIR'))) {
+		$config['storage']['filesystem_path'] = getenv('FRIENDICA_DATA');
+	}
+}
+
+if (!empty(getenv('FRIENDICA_DEBUGGING'))) {
+	$config['system']['debugging'] = true;
+	if (!empty(getenv('FRIENDICA_LOGFILE'))) {
+		$config['system']['logfile'] = getenv('FRIENDICA_LOGFILE');
+	}
+	if (!empty(getenv('FRIENDICA_LOGLEVEL'))) {
+		$config['system']['loglevel'] = getenv('FRIENDICA_LOGLEVEL');
+	}
+}
+
+if (!empty(getenv('HOSTNAME'))) {
+	$config['config']['hostname'] = getenv('HOSTNAME');
+}
+
+return $config;
diff --git a/friendica_dev-fpm/cron.sh b/friendica_dev-fpm/cron.sh
new file mode 100755
index 0000000..3f03a41
--- /dev/null
+++ b/friendica_dev-fpm/cron.sh
@@ -0,0 +1,13 @@
+#!/bin/sh
+trap "break;exit" HUP INT TERM
+
+while [ ! -f /var/www/html/bin/daemon.php ]; do
+    sleep 1
+done
+
+echo "Waiting for MySQL $MYSQL_HOST initialization..."
+if php /var/www/html/bin/wait-for-connection "$MYSQL_HOST" "${MYSQL_PORT:-3306}" 300; then
+  exec php /var/www/html/bin/daemon.php -f start
+else
+  echo "[ERROR] Waited 300 seconds, no response" >&2
+fi
diff --git a/friendica_dev-fpm/entrypoint-dev.sh b/friendica_dev-fpm/entrypoint-dev.sh
new file mode 100755
index 0000000..55afb80
--- /dev/null
+++ b/friendica_dev-fpm/entrypoint-dev.sh
@@ -0,0 +1,69 @@
+#!/bin/sh
+set -eu
+
+# checks if the branch and repository exists
+check_branch() {
+	repo=${1:-}
+	branch=${2:-}
+	git ls-remote --heads --tags "https://github.com/$repo" | grep -E "refs/(heads|tags)/${branch}$" >/dev/null
+	[ "$?" -eq "0" ]
+}
+
+# clones the whole develop branch (Friendica and Addons)
+clone_develop() {
+	friendica_git="${FRIENDICA_VERSION}"
+	addons_git="${FRIENDICA_ADDONS}"
+	friendica_repo="${FRIENDICA_REPOSITORY:-friendica/friendica}"
+	friendica_addons_repo="${FRIENDICA_ADDONS_REPO:-friendica/friendica-addons}"
+
+	if echo "{$friendica_git,,}" | grep -Eq '^.*\-dev'; then
+		friendica_git="develop"
+	fi
+
+	if echo "{$addons_git,,}" | grep -Eq '^.*\-dev'; then
+		addons_git="develop"
+	fi
+
+	# Check if the branches exist before wiping the
+	if check_branch "$friendica_repo" "$friendica_git" && check_branch "$friendica_addons_repo" "$addons_git" ; then
+		echo "Cloning '${friendica_git}' from GitHub repository '${friendica_repo}' ..."
+
+		# Removing the whole directory first
+		rm -fr /usr/src/friendica
+		git clone -q -b ${friendica_git} "https://github.com/${friendica_repo}" /usr/src/friendica
+
+		mkdir /usr/src/friendica/addon
+		git clone -q -b ${addons_git} "https://github.com/${friendica_addons_repo}" /usr/src/friendica/addon
+
+		echo "Download finished"
+
+		if [ ! -f /usr/src/friendica/VERSION ]; then
+			echo "Couldn't clone repository"
+			exit 1
+		fi
+
+		/usr/src/friendica/bin/composer.phar install --no-dev -d /usr/src/friendica
+		return 0
+
+	else
+		if check_branch "$friendica_repo" "$friendica_git"; then
+			echo "$friendica_repo/$friendica_git is not valid."
+		else
+			echo "$friendica_addons_repo/$addons_git is not valid."
+		fi
+		echo "Using old version."
+		return 1
+
+	fi
+}
+
+# just check if we execute apache or php-fpm
+if expr "$1" : "apache" 1>/dev/null || [ "$1" = "php-fpm" ]; then
+	# cloning from git is just possible for develop or Release Candidats
+	if echo "${FRIENDICA_VERSION}" | grep -Eq '^.*(\-dev|-rc|-RC)' || [ "${FRIENDICA_UPGRADE:-false}" = "true" ] || [ ! -f /usr/src/friendica/VERSION ]; then
+		# just clone & check if it's a new install or upgrade
+		clone_develop
+	fi
+fi
+
+exec /entrypoint.sh "$@"
diff --git a/friendica_dev-fpm/entrypoint.sh b/friendica_dev-fpm/entrypoint.sh
new file mode 100755
index 0000000..99b5f4a
--- /dev/null
+++ b/friendica_dev-fpm/entrypoint.sh
@@ -0,0 +1,149 @@
+#!/bin/sh
+set -eu
+
+# run an command with the www-data user
+run_as() {
+	set -- -c "cd /var/www/html; $*"
+	if [ "$(id -u)" -eq 0 ]; then
+		su - www-data -s /bin/sh "$@"
+	else
+		sh  "$@"
+	fi
+}
+
+# checks if the the first parameter is greater than the second parameter
+version_greater() {
+	[ "$(printf '%s\n' "$@" | sort -r -t '-' -k2,2  | sort -t '.' -n -k1,1 -k2,2 -s | head -n 1)" != "$1" ]
+}
+
+setup_ssmtp() {
+	if [ -n "${HOSTNAME+x}" ] && [ -n "${SMTP+x}" ] && [ "${SMTP}" != "localhost" ]; then
+		SITENAME="${FRIENDICA_SITENAME:-Friendica Social Network}"
+		echo "Setup SSMTP for '$SITENAME' with '$SMTP' ..."
+
+		smtp_from=${SMTP_FROM:-no-reply}
+
+		# Setup SSMTP
+		usermod --comment "$(echo "$SITENAME" | tr -dc '[:print:]')" root
+		usermod --comment "$(echo "$SITENAME" | tr -dc '[:print:]')" www-data
+
+		# add possible mail-senders
+		{
+		 echo "www-data:$smtp_from@$HOSTNAME:$SMTP"
+		 echo "root::$smtp_from@$HOSTNAME:$SMTP"
+		} > /etc/ssmtp/revaliases
+
+		# replace ssmtp.conf settings
+		{
+		 echo "root=:$smtp_from@$HOSTNAME"
+		 echo "hostname=$HOSTNAME"
+		 echo "mailhub=$SMTP"
+		 echo "FromLineOverride=YES"
+		 if [ -n "${SMTP_TLS+x}" ]; then echo "UseTLS=$SMTP_TLS"; fi
+		 if [ -n "${SMTP_STARTTLS+x}" ]; then echo "UseSTARTTLS=$SMTP_STARTTLS"; fi
+		 if [ -n "${SMTP_AUTH_USER+x}" ]; then echo "AuthUser=$SMTP_AUTH_USER"; fi
+		 if [ -n "${SMTP_AUTH_PASS+x}" ]; then echo "AuthPass=$SMTP_AUTH_PASS";fi
+		 if [ -n "${SMTP_AUTH_METHOD+x}" ]; then echo "AuthMethod=$SMTP_AUTH_METHOD"; fi
+		} > /etc/ssmtp/ssmtp.conf
+
+		echo "Setup finished"
+	fi
+}
+
+# just check if we execute apache or php-fpm
+if expr "$1" : "apache" 1>/dev/null || [ "$1" = "php-fpm" ]; then
+	installed_version="0.0.0.0"
+	if [ -f /var/www/html/VERSION ]; then
+		installed_version="$(cat /var/www/html/VERSION)"
+	fi
+
+	image_version="$(cat /usr/src/friendica/VERSION)"
+
+	# no downgrading possible
+	if version_greater "$installed_version" "$image_version"; then
+		echo "Can't copy Friendica sources because the version of the data ($installed_version) is higher than the docker image ($image_version)"
+		exit 1
+	fi
+
+	setup_ssmtp
+
+	# check it just in case the version is greater or if we force the upgrade
+	if version_greater "$image_version" "$installed_version" || [ "${FRIENDICA_UPGRADE:-false}" = "true" ]; then
+		echo "Initializing Friendica $image_version ..."
+
+		if [ "$installed_version" != "0.0.0.0" ]; then
+			echo "Upgrading Friendica from $installed_version ..."
+		fi
+
+		if [ "$(id -u)" -eq 0 ]; then
+			rsync_options="-rlDog --chown=www-data:www-data"
+		else
+			rsync_options="-rlD"
+		fi
+
+		rsync $rsync_options --delete --exclude-from=/upgrade.exclude /usr/src/friendica/ /var/www/html/
+
+		# Update docker-based config files, but never delete other config files
+		rsync $rsync_options --update /usr/src/friendica/config/ /var/www/html/config/
+
+		# In case there is no .htaccess, copy it from the default dist file
+		if [ ! -f "/var/www/html/.htaccess" ]; then
+			cp "/var/www/html/.htaccess-dist" "/var/www/html/.htaccess"
+		fi
+
+		if [ -d /var/www/html/view/smarty3 ]; then
+			chmod -R 777 /var/www/html/view/smarty3
+		fi
+		echo "Initializing finished"
+
+		# install
+		if [ "$installed_version" = "0.0.0.0" ]; then
+			echo "New Friendica instance"
+
+			install=false
+			if [ -n "${MYSQL_DATABASE+x}" ] && [ -n "${MYSQL_PASSWORD+x}" ] && [ -n "${MYSQL_HOST+x}" ] && [ -n "${MYSQL_USER+x}" ] && [ -n "${FRIENDICA_ADMIN_MAIL+x}" ] && [ -n "${FRIENDICA_URL+x}" ]; then
+				echo "Installation with environment variables"
+
+				FRIENDICA_TZ=${FRIENDICA_TZ:-America/LosAngeles}
+				FRIENDICA_LANG=${FRIENDICA_LANG:-en}
+				MYSQL_PORT=${MYSQL_PORT:-3306}
+
+				# shellcheck disable=SC2016
+				install_options='-s --dbhost "'$MYSQL_HOST'" --dbport "'$MYSQL_PORT'" --dbdata "'$MYSQL_DATABASE'" --dbuser "'$MYSQL_USER'" --dbpass "'$MYSQL_PASSWORD'"'
+
+				# shellcheck disable=SC2016
+				install_options=$install_options' --admin "'$FRIENDICA_ADMIN_MAIL'" --tz "'$FRIENDICA_TZ'" --lang "'$FRIENDICA_LANG'" --url "'$FRIENDICA_URL'"'
+				install=true
+			fi
+
+			if [ "$install" = true ]; then
+				echo "Waiting for MySQL $MYSQL_HOST initialization..."
+				if run_as "php /var/www/html/bin/wait-for-connection $MYSQL_HOST ${MYSQL_PORT:-3306} 300"; then
+
+					echo "Starting Friendica installation ..."
+					run_as "php /var/www/html/bin/console.php autoinstall $install_options"
+
+					rm -fr /var/www/html/view/smarty3/compiled
+
+					# load other config files (*.config.php) to the config folder
+					if [ -d "/usr/src/config" ]; then
+					  rsync $rsync_options --ignore-existing /usr/src/config/ /var/www/html/config/
+					fi
+
+					echo "Installation finished"
+				else
+					echo "[ERROR] Waited 300 seconds, no response" >&2
+				fi
+			else
+				echo "Running web-based installer on first connect!"
+			fi
+		# upgrade
+		else
+			echo "Upgrading Friendica ..."
+			run_as 'php /var/www/html/bin/console.php dbstructure update'
+			echo "Upgrading finished"
+		fi
+	fi
+fi
+
+exec "$@"
diff --git a/friendica_dev-fpm/upgrade.exclude b/friendica_dev-fpm/upgrade.exclude
new file mode 100644
index 0000000..2fb6533
--- /dev/null
+++ b/friendica_dev-fpm/upgrade.exclude
@@ -0,0 +1,10 @@
+/.git/
+/photo/
+/proxy/
+/.htconfig.php
+/.htaccess
+/home.*
+/config/
+/storage/
+/log/
+*.log
\ No newline at end of file
diff --git a/friendica_dev/Dockerfile b/friendica_dev/Dockerfile
new file mode 100644
index 0000000..0ee76a3
--- /dev/null
+++ b/friendica_dev/Dockerfile
@@ -0,0 +1,130 @@
+# DO NOT EDIT: created by update.sh from Dockerfile-debian.template
+FROM php:7.3-apache-stretch
+
+# entrypoint.sh and cron.sh dependencies
+RUN set -ex; \
+    \
+    apt-get update; \
+    apt-get install -y --no-install-recommends \
+        rsync \
+        bzip2 \
+        git \
+# For mail() support
+        ssmtp \
+    ; \
+    rm -rf /var/lib/apt/lists/*;
+
+# install the PHP extensions we need
+# see https://friendi.ca/resources/requirements/
+RUN set -ex; \
+    \
+    savedAptMark="$(apt-mark showmanual)"; \
+    \
+    apt-get update; \
+    apt-get install -y --no-install-recommends \
+        mysql-client \
+        bash \
+        libpng-dev \
+        libjpeg62-turbo-dev \
+        libtool \
+        libmagick++-dev \
+        libmemcached-dev \
+        libgraphicsmagick1-dev \
+        libfreetype6-dev \
+        librsvg2-2 \
+        libzip-dev \
+        libldap2-dev \
+    ; \
+    \
+        debMultiarch="$(dpkg-architecture --query DEB_BUILD_MULTIARCH)"; \
+    \
+    docker-php-ext-configure gd \
+        --with-gd \
+        --with-freetype-dir=/usr/include/ \
+        --with-png-dir=/usr/include/ \
+        --with-jpeg-dir=/usr/include/ \
+    ; \
+    docker-php-ext-configure ldap \
+        	--with-libdir=lib/$debMultiarch/ \
+	; \
+    docker-php-ext-install -j "$(nproc)" \
+        pdo_mysql \
+        gd \
+        zip \
+        opcache \
+        ctype \
+        pcntl \
+        ldap \
+    ; \
+    \
+# pecl will claim success even if one install fails, so we need to perform each install separately
+    pecl install apcu-5.1.18; \
+    pecl install memcached-3.1.5; \
+    pecl install redis-5.1.1; \
+    pecl install imagick-3.4.4; \
+    \
+    docker-php-ext-enable \
+        apcu \
+        memcached \
+        redis \
+        imagick \
+    ; \
+    \
+# reset apt-mark's "manual" list so that "purge --auto-remove" will remove all build dependencies
+    apt-mark auto '.*' > /dev/null; \
+    apt-mark manual $savedAptMark; \
+    ldd "$(php -r 'echo ini_get("extension_dir");')"/*.so \
+      | awk '/=>/ { print $3 }' \
+      | sort -u \
+      | xargs -r dpkg-query -S \
+      | cut -d: -f1 \
+      | sort -u \
+      | xargs -rt apt-mark manual; \
+    \
+    apt-get purge -y --auto-remove -o APT::AutoRemove::RecommendsImportant=false; \
+    rm -rf /var/lib/apt/lists/*
+
+# set recommended PHP.ini settings
+RUN set -ex; \
+    { \
+        echo 'opcache.enable=1' ; \
+        echo 'opcache.interned_strings_buffer=8'; \
+        echo 'opcache.max_accelerated_files=10000'; \
+        echo 'opcache.memory_consumption=128'; \
+        echo 'opcache.save_comments=1'; \
+        echo 'opcache.revalidte_freq=1'; \
+    } > /usr/local/etc/php/conf.d/opcache-recommended.ini; \
+    \
+    { \
+        echo sendmail_path = "/usr/sbin/sendmail -t -i"; \
+    } > /usr/local/etc/php/conf.d/sendmail.ini; \
+    \
+    echo 'apc.enable_cli=1' >> /usr/local/etc/php/conf.d/docker-php-ext-apcu.ini; \
+    \
+    echo 'memory_limit=512M' > /usr/local/etc/php/conf.d/memory-limit.ini; \
+    \
+    mkdir /var/www/data; \
+    chown -R www-data:root /var/www; \
+    chmod -R g=u /var/www
+
+VOLUME /var/www/html
+
+RUN set -ex;\
+    a2enmod rewrite remoteip ;\
+    {\
+     echo RemoteIPHeader X-Real-IP ;\
+     echo RemoteIPTrustedProxy 10.0.0.0/8 ;\
+     echo RemoteIPTrustedProxy 172.16.0.0/12 ;\
+     echo RemoteIPTrustedProxy 192.168.0.0/16 ;\
+    } > /etc/apache2/conf-available/remoteip.conf;\
+    a2enconf remoteip
+
+ENV FRIENDICA_VERSION 2020.03-dev
+ENV FRIENDICA_ADDONS 2020.03-dev
+
+
+COPY *.sh upgrade.exclude /
+COPY config/* /usr/src/friendica/config/
+
+ENTRYPOINT ["/entrypoint-dev.sh"]
+CMD ["apache2-foreground"]
diff --git a/friendica_dev/config/00apcu.config.php b/friendica_dev/config/00apcu.config.php
new file mode 100644
index 0000000..d6dac4f
--- /dev/null
+++ b/friendica_dev/config/00apcu.config.php
@@ -0,0 +1,12 @@
+<?php
+
+/**
+ * If nothing else set, use APCu as a caching driver (best performance for local caching)
+ */
+
+return [
+	'system' => [
+		'cache_driver' => 'apcu',
+		'session_handler' => 'cache',
+	],
+];
diff --git a/friendica_dev/config/01redis.config.php b/friendica_dev/config/01redis.config.php
new file mode 100644
index 0000000..1a43c95
--- /dev/null
+++ b/friendica_dev/config/01redis.config.php
@@ -0,0 +1,15 @@
+<?php
+
+if (getenv('REDIS_HOST')) {
+	return [
+		'system' => [
+			'lock_driver' => 'redis',
+			'redis_host' => getenv('REDIS_HOST'),
+			'redis_port' => (getenv('REDIS_PORT') ? getenv('REDIS_PORT') : ''),
+			'redis_password' => (getenv('REDIS_PW') ? getenv('REDIS_PW') : ''),
+			'redis_db' => (getenv('REDIS_DB') ? getenv('REDIS_DB') : 0),
+		],
+	];
+} else {
+	return [];
+}
diff --git a/friendica_dev/config/zz-docker.config.php b/friendica_dev/config/zz-docker.config.php
new file mode 100644
index 0000000..c9e5ed8
--- /dev/null
+++ b/friendica_dev/config/zz-docker.config.php
@@ -0,0 +1,66 @@
+<?php
+
+/**
+ * Fallback config to make it possible overwriting config values
+ * because of docker environment variables
+ *
+ * This doesn't affect DB configurations, but will replace other config values
+ */
+
+$config = [
+	'system' => [
+		// Necessary because otherwise the daemon isn't working
+		'pidfile' => '/var/run/friendica.pid',
+
+		'logfile' => '/var/www/html/friendica.log',
+		'loglevel' => 'notice',
+	],
+	'storage' => [
+		'filesystem_path' => '/var/www/html/storage',
+	],
+];
+
+if (getenv('FRIENDICA_TZ')) {
+	$config['config']['timezone'] = getenv('FRIENDICA_TZ');
+}
+
+if (getenv('FRIENDICA_LANG')) {
+	$config['config']['language'] = getenv('FRIENDICA_LANG');
+}
+
+if (getenv('FRIENDICA_ADMIN_MAIL')) {
+	$config['config']['admin_mail'] = getenv('FRIENDICA_ADMIN_MAIL');
+}
+
+if (getenv('FRIENDICA_SITENAME')) {
+	$config['config']['sitename'] = getenv('FRIENDICA_SITENAME');
+}
+
+if (!empty(getenv('FRIENDICA_NO_VALIDATION'))) {
+	$config['system']['disable_url_validation'] = true;
+	$config['system']['disable_email_validation'] = true;
+}
+
+if (!empty(getenv('FRIENDICA_DATA'))) {
+	$config['storage']['class'] = \Friendica\Model\Storage\Filesystem::class;
+
+	if (!empty(getenv('FRIENDICA_DATA_DIR'))) {
+		$config['storage']['filesystem_path'] = getenv('FRIENDICA_DATA');
+	}
+}
+
+if (!empty(getenv('FRIENDICA_DEBUGGING'))) {
+	$config['system']['debugging'] = true;
+	if (!empty(getenv('FRIENDICA_LOGFILE'))) {
+		$config['system']['logfile'] = getenv('FRIENDICA_LOGFILE');
+	}
+	if (!empty(getenv('FRIENDICA_LOGLEVEL'))) {
+		$config['system']['loglevel'] = getenv('FRIENDICA_LOGLEVEL');
+	}
+}
+
+if (!empty(getenv('HOSTNAME'))) {
+	$config['config']['hostname'] = getenv('HOSTNAME');
+}
+
+return $config;
diff --git a/friendica_dev/cron.sh b/friendica_dev/cron.sh
new file mode 100755
index 0000000..3f03a41
--- /dev/null
+++ b/friendica_dev/cron.sh
@@ -0,0 +1,13 @@
+#!/bin/sh
+trap "break;exit" HUP INT TERM
+
+while [ ! -f /var/www/html/bin/daemon.php ]; do
+    sleep 1
+done
+
+echo "Waiting for MySQL $MYSQL_HOST initialization..."
+if php /var/www/html/bin/wait-for-connection "$MYSQL_HOST" "${MYSQL_PORT:-3306}" 300; then
+  exec php /var/www/html/bin/daemon.php -f start
+else
+  echo "[ERROR] Waited 300 seconds, no response" >&2
+fi
diff --git a/friendica_dev/entrypoint-dev.sh b/friendica_dev/entrypoint-dev.sh
new file mode 100755
index 0000000..55afb80
--- /dev/null
+++ b/friendica_dev/entrypoint-dev.sh
@@ -0,0 +1,69 @@
+#!/bin/sh
+set -eu
+
+# checks if the branch and repository exists
+check_branch() {
+	repo=${1:-}
+	branch=${2:-}
+	git ls-remote --heads --tags "https://github.com/$repo" | grep -E "refs/(heads|tags)/${branch}$" >/dev/null
+	[ "$?" -eq "0" ]
+}
+
+# clones the whole develop branch (Friendica and Addons)
+clone_develop() {
+	friendica_git="${FRIENDICA_VERSION}"
+	addons_git="${FRIENDICA_ADDONS}"
+	friendica_repo="${FRIENDICA_REPOSITORY:-friendica/friendica}"
+	friendica_addons_repo="${FRIENDICA_ADDONS_REPO:-friendica/friendica-addons}"
+
+	if echo "{$friendica_git,,}" | grep -Eq '^.*\-dev'; then
+		friendica_git="develop"
+	fi
+
+	if echo "{$addons_git,,}" | grep -Eq '^.*\-dev'; then
+		addons_git="develop"
+	fi
+
+	# Check if the branches exist before wiping the
+	if check_branch "$friendica_repo" "$friendica_git" && check_branch "$friendica_addons_repo" "$addons_git" ; then
+		echo "Cloning '${friendica_git}' from GitHub repository '${friendica_repo}' ..."
+
+		# Removing the whole directory first
+		rm -fr /usr/src/friendica
+		git clone -q -b ${friendica_git} "https://github.com/${friendica_repo}" /usr/src/friendica
+
+		mkdir /usr/src/friendica/addon
+		git clone -q -b ${addons_git} "https://github.com/${friendica_addons_repo}" /usr/src/friendica/addon
+
+		echo "Download finished"
+
+		if [ ! -f /usr/src/friendica/VERSION ]; then
+			echo "Couldn't clone repository"
+			exit 1
+		fi
+
+		/usr/src/friendica/bin/composer.phar install --no-dev -d /usr/src/friendica
+		return 0
+
+	else
+		if check_branch "$friendica_repo" "$friendica_git"; then
+			echo "$friendica_repo/$friendica_git is not valid."
+		else
+			echo "$friendica_addons_repo/$addons_git is not valid."
+		fi
+		echo "Using old version."
+		return 1
+
+	fi
+}
+
+# just check if we execute apache or php-fpm
+if expr "$1" : "apache" 1>/dev/null || [ "$1" = "php-fpm" ]; then
+	# cloning from git is just possible for develop or Release Candidats
+	if echo "${FRIENDICA_VERSION}" | grep -Eq '^.*(\-dev|-rc|-RC)' || [ "${FRIENDICA_UPGRADE:-false}" = "true" ] || [ ! -f /usr/src/friendica/VERSION ]; then
+		# just clone & check if it's a new install or upgrade
+		clone_develop
+	fi
+fi
+
+exec /entrypoint.sh "$@"
diff --git a/friendica_dev/entrypoint.sh b/friendica_dev/entrypoint.sh
new file mode 100755
index 0000000..99b5f4a
--- /dev/null
+++ b/friendica_dev/entrypoint.sh
@@ -0,0 +1,149 @@
+#!/bin/sh
+set -eu
+
+# run an command with the www-data user
+run_as() {
+	set -- -c "cd /var/www/html; $*"
+	if [ "$(id -u)" -eq 0 ]; then
+		su - www-data -s /bin/sh "$@"
+	else
+		sh  "$@"
+	fi
+}
+
+# checks if the the first parameter is greater than the second parameter
+version_greater() {
+	[ "$(printf '%s\n' "$@" | sort -r -t '-' -k2,2  | sort -t '.' -n -k1,1 -k2,2 -s | head -n 1)" != "$1" ]
+}
+
+setup_ssmtp() {
+	if [ -n "${HOSTNAME+x}" ] && [ -n "${SMTP+x}" ] && [ "${SMTP}" != "localhost" ]; then
+		SITENAME="${FRIENDICA_SITENAME:-Friendica Social Network}"
+		echo "Setup SSMTP for '$SITENAME' with '$SMTP' ..."
+
+		smtp_from=${SMTP_FROM:-no-reply}
+
+		# Setup SSMTP
+		usermod --comment "$(echo "$SITENAME" | tr -dc '[:print:]')" root
+		usermod --comment "$(echo "$SITENAME" | tr -dc '[:print:]')" www-data
+
+		# add possible mail-senders
+		{
+		 echo "www-data:$smtp_from@$HOSTNAME:$SMTP"
+		 echo "root::$smtp_from@$HOSTNAME:$SMTP"
+		} > /etc/ssmtp/revaliases
+
+		# replace ssmtp.conf settings
+		{
+		 echo "root=:$smtp_from@$HOSTNAME"
+		 echo "hostname=$HOSTNAME"
+		 echo "mailhub=$SMTP"
+		 echo "FromLineOverride=YES"
+		 if [ -n "${SMTP_TLS+x}" ]; then echo "UseTLS=$SMTP_TLS"; fi
+		 if [ -n "${SMTP_STARTTLS+x}" ]; then echo "UseSTARTTLS=$SMTP_STARTTLS"; fi
+		 if [ -n "${SMTP_AUTH_USER+x}" ]; then echo "AuthUser=$SMTP_AUTH_USER"; fi
+		 if [ -n "${SMTP_AUTH_PASS+x}" ]; then echo "AuthPass=$SMTP_AUTH_PASS";fi
+		 if [ -n "${SMTP_AUTH_METHOD+x}" ]; then echo "AuthMethod=$SMTP_AUTH_METHOD"; fi
+		} > /etc/ssmtp/ssmtp.conf
+
+		echo "Setup finished"
+	fi
+}
+
+# just check if we execute apache or php-fpm
+if expr "$1" : "apache" 1>/dev/null || [ "$1" = "php-fpm" ]; then
+	installed_version="0.0.0.0"
+	if [ -f /var/www/html/VERSION ]; then
+		installed_version="$(cat /var/www/html/VERSION)"
+	fi
+
+	image_version="$(cat /usr/src/friendica/VERSION)"
+
+	# no downgrading possible
+	if version_greater "$installed_version" "$image_version"; then
+		echo "Can't copy Friendica sources because the version of the data ($installed_version) is higher than the docker image ($image_version)"
+		exit 1
+	fi
+
+	setup_ssmtp
+
+	# check it just in case the version is greater or if we force the upgrade
+	if version_greater "$image_version" "$installed_version" || [ "${FRIENDICA_UPGRADE:-false}" = "true" ]; then
+		echo "Initializing Friendica $image_version ..."
+
+		if [ "$installed_version" != "0.0.0.0" ]; then
+			echo "Upgrading Friendica from $installed_version ..."
+		fi
+
+		if [ "$(id -u)" -eq 0 ]; then
+			rsync_options="-rlDog --chown=www-data:www-data"
+		else
+			rsync_options="-rlD"
+		fi
+
+		rsync $rsync_options --delete --exclude-from=/upgrade.exclude /usr/src/friendica/ /var/www/html/
+
+		# Update docker-based config files, but never delete other config files
+		rsync $rsync_options --update /usr/src/friendica/config/ /var/www/html/config/
+
+		# In case there is no .htaccess, copy it from the default dist file
+		if [ ! -f "/var/www/html/.htaccess" ]; then
+			cp "/var/www/html/.htaccess-dist" "/var/www/html/.htaccess"
+		fi
+
+		if [ -d /var/www/html/view/smarty3 ]; then
+			chmod -R 777 /var/www/html/view/smarty3
+		fi
+		echo "Initializing finished"
+
+		# install
+		if [ "$installed_version" = "0.0.0.0" ]; then
+			echo "New Friendica instance"
+
+			install=false
+			if [ -n "${MYSQL_DATABASE+x}" ] && [ -n "${MYSQL_PASSWORD+x}" ] && [ -n "${MYSQL_HOST+x}" ] && [ -n "${MYSQL_USER+x}" ] && [ -n "${FRIENDICA_ADMIN_MAIL+x}" ] && [ -n "${FRIENDICA_URL+x}" ]; then
+				echo "Installation with environment variables"
+
+				FRIENDICA_TZ=${FRIENDICA_TZ:-America/LosAngeles}
+				FRIENDICA_LANG=${FRIENDICA_LANG:-en}
+				MYSQL_PORT=${MYSQL_PORT:-3306}
+
+				# shellcheck disable=SC2016
+				install_options='-s --dbhost "'$MYSQL_HOST'" --dbport "'$MYSQL_PORT'" --dbdata "'$MYSQL_DATABASE'" --dbuser "'$MYSQL_USER'" --dbpass "'$MYSQL_PASSWORD'"'
+
+				# shellcheck disable=SC2016
+				install_options=$install_options' --admin "'$FRIENDICA_ADMIN_MAIL'" --tz "'$FRIENDICA_TZ'" --lang "'$FRIENDICA_LANG'" --url "'$FRIENDICA_URL'"'
+				install=true
+			fi
+
+			if [ "$install" = true ]; then
+				echo "Waiting for MySQL $MYSQL_HOST initialization..."
+				if run_as "php /var/www/html/bin/wait-for-connection $MYSQL_HOST ${MYSQL_PORT:-3306} 300"; then
+
+					echo "Starting Friendica installation ..."
+					run_as "php /var/www/html/bin/console.php autoinstall $install_options"
+
+					rm -fr /var/www/html/view/smarty3/compiled
+
+					# load other config files (*.config.php) to the config folder
+					if [ -d "/usr/src/config" ]; then
+					  rsync $rsync_options --ignore-existing /usr/src/config/ /var/www/html/config/
+					fi
+
+					echo "Installation finished"
+				else
+					echo "[ERROR] Waited 300 seconds, no response" >&2
+				fi
+			else
+				echo "Running web-based installer on first connect!"
+			fi
+		# upgrade
+		else
+			echo "Upgrading Friendica ..."
+			run_as 'php /var/www/html/bin/console.php dbstructure update'
+			echo "Upgrading finished"
+		fi
+	fi
+fi
+
+exec "$@"
diff --git a/friendica_dev/upgrade.exclude b/friendica_dev/upgrade.exclude
new file mode 100644
index 0000000..2fb6533
--- /dev/null
+++ b/friendica_dev/upgrade.exclude
@@ -0,0 +1,10 @@
+/.git/
+/photo/
+/proxy/
+/.htconfig.php
+/.htaccess
+/home.*
+/config/
+/storage/
+/log/
+*.log
\ No newline at end of file
diff --git a/friendica_stable-fpm-alpine/Dockerfile b/friendica_stable-fpm-alpine/Dockerfile
new file mode 100644
index 0000000..6b26dbf
--- /dev/null
+++ b/friendica_stable-fpm-alpine/Dockerfile
@@ -0,0 +1,122 @@
+# DO NOT EDIT: created by update.sh from Dockerfile-alpine.template
+FROM php:7.3-fpm-alpine
+
+# entrypoint.sh and cron.sh dependencies
+RUN set -ex; \
+    apk add --no-cache \
+        rsync \
+        git \
+# For mail() support
+        ssmtp \
+        shadow;
+
+# install the PHP extensions we need
+# see https://friendi.ca/resources/requirements/
+RUN set -ex; \
+    \
+    apk add --no-cache --virtual .build-deps \
+        mysql-client \
+        bash \
+        $PHPIZE_DEPS \
+        libpng-dev \
+        libjpeg-turbo-dev \
+        imagemagick-dev \
+        libtool \
+        libmemcached-dev \
+        cyrus-sasl-dev \
+        libjpeg-turbo-dev \
+        freetype-dev \
+        librsvg \
+        pcre-dev \
+        libzip-dev \
+        icu-dev \
+        openldap-dev \
+    ; \
+    \
+    docker-php-ext-configure gd \
+        --with-gd \
+        --with-freetype-dir=/usr/include/ \
+        --with-png-dir=/usr/include/ \
+        --with-jpeg-dir=/usr/include/ \
+    ; \
+    \
+    docker-php-ext-install -j "$(nproc)" \
+       pdo_mysql \
+       gd \
+       zip \
+       opcache \
+       pcntl \
+       ldap \
+    ; \
+    \
+# pecl will claim success even if one install fails, so we need to perform each install separately
+    pecl install APCu-5.1.18; \
+    pecl install memcached-3.1.5; \
+    pecl install redis-5.1.1; \
+    pecl install imagick-3.4.4; \
+    \
+    docker-php-ext-enable \
+    	apcu \
+        memcached \
+        redis \
+        imagick \
+    ; \
+    \
+    runDeps="$( \
+      scanelf --needed --nobanner --format '%n#p' --recursive /usr/local/lib/php/extensions \
+          | tr ',' '\n' \
+          | sort -u \
+          | awk 'system("[ -e /usr/local/lib" $1 " ]") == 0 { next } { print "so:" $1 }' \
+    )"; \
+    apk add --no-network --virtual .friendica-phpext-rundeps $runDeps; \
+    apk del --no-network .build-deps;
+
+# set recommended PHP.ini settings
+RUN set -ex; \
+    { \
+        echo 'opcache.enable=1' ; \
+        echo 'opcache.interned_strings_buffer=8'; \
+        echo 'opcache.max_accelerated_files=10000'; \
+        echo 'opcache.memory_consumption=128'; \
+        echo 'opcache.save_comments=1'; \
+        echo 'opcache.revalidte_freq=1'; \
+    } > /usr/local/etc/php/conf.d/opcache-recommended.ini; \
+    \
+    { \
+        echo sendmail_path = "/usr/sbin/sendmail -t -i"; \
+    } > /usr/local/etc/php/conf.d/sendmail.ini; \
+    \
+    echo 'apc.enable_cli=1' >> /usr/local/etc/php/conf.d/docker-php-ext-apcu.ini; \
+    \
+    echo 'memory_limit=512M' > /usr/local/etc/php/conf.d/memory-limit.ini; \
+    \
+    mkdir /var/www/data; \
+    chown -R www-data:root /var/www; \
+    chmod -R g=u /var/www
+
+VOLUME /var/www/html
+
+
+ENV FRIENDICA_VERSION 2019.12
+ENV FRIENDICA_ADDONS 2019.12
+
+RUN set -ex; \
+    curl -fsSL -o friendica.tar.gz \
+        "https://github.com/friendica/friendica/archive/${FRIENDICA_VERSION}.tar.gz"; \
+    tar -xzf friendica.tar.gz -C /usr/src/; \
+    rm friendica.tar.gz; \
+    mv -f /usr/src/friendica-${FRIENDICA_VERSION}/ /usr/src/friendica; \
+    chmod 777 /usr/src/friendica/view/smarty3; \
+    curl -fsSL -o friendica_addons.tar.gz \
+        "https://github.com/friendica/friendica-addons/archive/${FRIENDICA_ADDONS}.tar.gz"; \
+    mkdir -p /usr/src/friendica/proxy; \
+    mkdir -p /usr/src/friendica/addon; \
+    tar -xzf friendica_addons.tar.gz -C /usr/src/friendica/addon --strip-components=1; \
+    rm friendica_addons.tar.gz; \
+    /usr/src/friendica/bin/composer.phar install --no-dev -d /usr/src/friendica;
+
+COPY *.sh upgrade.exclude /
+COPY config/* /usr/src/friendica/config/
+
+ENTRYPOINT ["/entrypoint.sh"]
+CMD ["php-fpm"]
diff --git a/friendica_stable-fpm-alpine/config/00apcu.config.php b/friendica_stable-fpm-alpine/config/00apcu.config.php
new file mode 100644
index 0000000..d6dac4f
--- /dev/null
+++ b/friendica_stable-fpm-alpine/config/00apcu.config.php
@@ -0,0 +1,12 @@
+<?php
+
+/**
+ * If nothing else set, use APCu as a caching driver (best performance for local caching)
+ */
+
+return [
+	'system' => [
+		'cache_driver' => 'apcu',
+		'session_handler' => 'cache',
+	],
+];
diff --git a/friendica_stable-fpm-alpine/config/01redis.config.php b/friendica_stable-fpm-alpine/config/01redis.config.php
new file mode 100644
index 0000000..1a43c95
--- /dev/null
+++ b/friendica_stable-fpm-alpine/config/01redis.config.php
@@ -0,0 +1,15 @@
+<?php
+
+if (getenv('REDIS_HOST')) {
+	return [
+		'system' => [
+			'lock_driver' => 'redis',
+			'redis_host' => getenv('REDIS_HOST'),
+			'redis_port' => (getenv('REDIS_PORT') ? getenv('REDIS_PORT') : ''),
+			'redis_password' => (getenv('REDIS_PW') ? getenv('REDIS_PW') : ''),
+			'redis_db' => (getenv('REDIS_DB') ? getenv('REDIS_DB') : 0),
+		],
+	];
+} else {
+	return [];
+}
diff --git a/friendica_stable-fpm-alpine/config/zz-docker.config.php b/friendica_stable-fpm-alpine/config/zz-docker.config.php
new file mode 100644
index 0000000..c9e5ed8
--- /dev/null
+++ b/friendica_stable-fpm-alpine/config/zz-docker.config.php
@@ -0,0 +1,66 @@
+<?php
+
+/**
+ * Fallback config to make it possible overwriting config values
+ * because of docker environment variables
+ *
+ * This doesn't affect DB configurations, but will replace other config values
+ */
+
+$config = [
+	'system' => [
+		// Necessary because otherwise the daemon isn't working
+		'pidfile' => '/var/run/friendica.pid',
+
+		'logfile' => '/var/www/html/friendica.log',
+		'loglevel' => 'notice',
+	],
+	'storage' => [
+		'filesystem_path' => '/var/www/html/storage',
+	],
+];
+
+if (getenv('FRIENDICA_TZ')) {
+	$config['config']['timezone'] = getenv('FRIENDICA_TZ');
+}
+
+if (getenv('FRIENDICA_LANG')) {
+	$config['config']['language'] = getenv('FRIENDICA_LANG');
+}
+
+if (getenv('FRIENDICA_ADMIN_MAIL')) {
+	$config['config']['admin_mail'] = getenv('FRIENDICA_ADMIN_MAIL');
+}
+
+if (getenv('FRIENDICA_SITENAME')) {
+	$config['config']['sitename'] = getenv('FRIENDICA_SITENAME');
+}
+
+if (!empty(getenv('FRIENDICA_NO_VALIDATION'))) {
+	$config['system']['disable_url_validation'] = true;
+	$config['system']['disable_email_validation'] = true;
+}
+
+if (!empty(getenv('FRIENDICA_DATA'))) {
+	$config['storage']['class'] = \Friendica\Model\Storage\Filesystem::class;
+
+	if (!empty(getenv('FRIENDICA_DATA_DIR'))) {
+		$config['storage']['filesystem_path'] = getenv('FRIENDICA_DATA');
+	}
+}
+
+if (!empty(getenv('FRIENDICA_DEBUGGING'))) {
+	$config['system']['debugging'] = true;
+	if (!empty(getenv('FRIENDICA_LOGFILE'))) {
+		$config['system']['logfile'] = getenv('FRIENDICA_LOGFILE');
+	}
+	if (!empty(getenv('FRIENDICA_LOGLEVEL'))) {
+		$config['system']['loglevel'] = getenv('FRIENDICA_LOGLEVEL');
+	}
+}
+
+if (!empty(getenv('HOSTNAME'))) {
+	$config['config']['hostname'] = getenv('HOSTNAME');
+}
+
+return $config;
diff --git a/friendica_stable-fpm-alpine/cron.sh b/friendica_stable-fpm-alpine/cron.sh
new file mode 100755
index 0000000..3f03a41
--- /dev/null
+++ b/friendica_stable-fpm-alpine/cron.sh
@@ -0,0 +1,13 @@
+#!/bin/sh
+trap "break;exit" HUP INT TERM
+
+while [ ! -f /var/www/html/bin/daemon.php ]; do
+    sleep 1
+done
+
+echo "Waiting for MySQL $MYSQL_HOST initialization..."
+if php /var/www/html/bin/wait-for-connection "$MYSQL_HOST" "${MYSQL_PORT:-3306}" 300; then
+  exec php /var/www/html/bin/daemon.php -f start
+else
+  echo "[ERROR] Waited 300 seconds, no response" >&2
+fi
diff --git a/friendica_stable-fpm-alpine/entrypoint.sh b/friendica_stable-fpm-alpine/entrypoint.sh
new file mode 100755
index 0000000..99b5f4a
--- /dev/null
+++ b/friendica_stable-fpm-alpine/entrypoint.sh
@@ -0,0 +1,149 @@
+#!/bin/sh
+set -eu
+
+# run an command with the www-data user
+run_as() {
+	set -- -c "cd /var/www/html; $*"
+	if [ "$(id -u)" -eq 0 ]; then
+		su - www-data -s /bin/sh "$@"
+	else
+		sh  "$@"
+	fi
+}
+
+# checks if the the first parameter is greater than the second parameter
+version_greater() {
+	[ "$(printf '%s\n' "$@" | sort -r -t '-' -k2,2  | sort -t '.' -n -k1,1 -k2,2 -s | head -n 1)" != "$1" ]
+}
+
+setup_ssmtp() {
+	if [ -n "${HOSTNAME+x}" ] && [ -n "${SMTP+x}" ] && [ "${SMTP}" != "localhost" ]; then
+		SITENAME="${FRIENDICA_SITENAME:-Friendica Social Network}"
+		echo "Setup SSMTP for '$SITENAME' with '$SMTP' ..."
+
+		smtp_from=${SMTP_FROM:-no-reply}
+
+		# Setup SSMTP
+		usermod --comment "$(echo "$SITENAME" | tr -dc '[:print:]')" root
+		usermod --comment "$(echo "$SITENAME" | tr -dc '[:print:]')" www-data
+
+		# add possible mail-senders
+		{
+		 echo "www-data:$smtp_from@$HOSTNAME:$SMTP"
+		 echo "root::$smtp_from@$HOSTNAME:$SMTP"
+		} > /etc/ssmtp/revaliases
+
+		# replace ssmtp.conf settings
+		{
+		 echo "root=:$smtp_from@$HOSTNAME"
+		 echo "hostname=$HOSTNAME"
+		 echo "mailhub=$SMTP"
+		 echo "FromLineOverride=YES"
+		 if [ -n "${SMTP_TLS+x}" ]; then echo "UseTLS=$SMTP_TLS"; fi
+		 if [ -n "${SMTP_STARTTLS+x}" ]; then echo "UseSTARTTLS=$SMTP_STARTTLS"; fi
+		 if [ -n "${SMTP_AUTH_USER+x}" ]; then echo "AuthUser=$SMTP_AUTH_USER"; fi
+		 if [ -n "${SMTP_AUTH_PASS+x}" ]; then echo "AuthPass=$SMTP_AUTH_PASS";fi
+		 if [ -n "${SMTP_AUTH_METHOD+x}" ]; then echo "AuthMethod=$SMTP_AUTH_METHOD"; fi
+		} > /etc/ssmtp/ssmtp.conf
+
+		echo "Setup finished"
+	fi
+}
+
+# just check if we execute apache or php-fpm
+if expr "$1" : "apache" 1>/dev/null || [ "$1" = "php-fpm" ]; then
+	installed_version="0.0.0.0"
+	if [ -f /var/www/html/VERSION ]; then
+		installed_version="$(cat /var/www/html/VERSION)"
+	fi
+
+	image_version="$(cat /usr/src/friendica/VERSION)"
+
+	# no downgrading possible
+	if version_greater "$installed_version" "$image_version"; then
+		echo "Can't copy Friendica sources because the version of the data ($installed_version) is higher than the docker image ($image_version)"
+		exit 1
+	fi
+
+	setup_ssmtp
+
+	# check it just in case the version is greater or if we force the upgrade
+	if version_greater "$image_version" "$installed_version" || [ "${FRIENDICA_UPGRADE:-false}" = "true" ]; then
+		echo "Initializing Friendica $image_version ..."
+
+		if [ "$installed_version" != "0.0.0.0" ]; then
+			echo "Upgrading Friendica from $installed_version ..."
+		fi
+
+		if [ "$(id -u)" -eq 0 ]; then
+			rsync_options="-rlDog --chown=www-data:www-data"
+		else
+			rsync_options="-rlD"
+		fi
+
+		rsync $rsync_options --delete --exclude-from=/upgrade.exclude /usr/src/friendica/ /var/www/html/
+
+		# Update docker-based config files, but never delete other config files
+		rsync $rsync_options --update /usr/src/friendica/config/ /var/www/html/config/
+
+		# In case there is no .htaccess, copy it from the default dist file
+		if [ ! -f "/var/www/html/.htaccess" ]; then
+			cp "/var/www/html/.htaccess-dist" "/var/www/html/.htaccess"
+		fi
+
+		if [ -d /var/www/html/view/smarty3 ]; then
+			chmod -R 777 /var/www/html/view/smarty3
+		fi
+		echo "Initializing finished"
+
+		# install
+		if [ "$installed_version" = "0.0.0.0" ]; then
+			echo "New Friendica instance"
+
+			install=false
+			if [ -n "${MYSQL_DATABASE+x}" ] && [ -n "${MYSQL_PASSWORD+x}" ] && [ -n "${MYSQL_HOST+x}" ] && [ -n "${MYSQL_USER+x}" ] && [ -n "${FRIENDICA_ADMIN_MAIL+x}" ] && [ -n "${FRIENDICA_URL+x}" ]; then
+				echo "Installation with environment variables"
+
+				FRIENDICA_TZ=${FRIENDICA_TZ:-America/LosAngeles}
+				FRIENDICA_LANG=${FRIENDICA_LANG:-en}
+				MYSQL_PORT=${MYSQL_PORT:-3306}
+
+				# shellcheck disable=SC2016
+				install_options='-s --dbhost "'$MYSQL_HOST'" --dbport "'$MYSQL_PORT'" --dbdata "'$MYSQL_DATABASE'" --dbuser "'$MYSQL_USER'" --dbpass "'$MYSQL_PASSWORD'"'
+
+				# shellcheck disable=SC2016
+				install_options=$install_options' --admin "'$FRIENDICA_ADMIN_MAIL'" --tz "'$FRIENDICA_TZ'" --lang "'$FRIENDICA_LANG'" --url "'$FRIENDICA_URL'"'
+				install=true
+			fi
+
+			if [ "$install" = true ]; then
+				echo "Waiting for MySQL $MYSQL_HOST initialization..."
+				if run_as "php /var/www/html/bin/wait-for-connection $MYSQL_HOST ${MYSQL_PORT:-3306} 300"; then
+
+					echo "Starting Friendica installation ..."
+					run_as "php /var/www/html/bin/console.php autoinstall $install_options"
+
+					rm -fr /var/www/html/view/smarty3/compiled
+
+					# load other config files (*.config.php) to the config folder
+					if [ -d "/usr/src/config" ]; then
+					  rsync $rsync_options --ignore-existing /usr/src/config/ /var/www/html/config/
+					fi
+
+					echo "Installation finished"
+				else
+					echo "[ERROR] Waited 300 seconds, no response" >&2
+				fi
+			else
+				echo "Running web-based installer on first connect!"
+			fi
+		# upgrade
+		else
+			echo "Upgrading Friendica ..."
+			run_as 'php /var/www/html/bin/console.php dbstructure update'
+			echo "Upgrading finished"
+		fi
+	fi
+fi
+
+exec "$@"
diff --git a/friendica_stable-fpm-alpine/upgrade.exclude b/friendica_stable-fpm-alpine/upgrade.exclude
new file mode 100644
index 0000000..2fb6533
--- /dev/null
+++ b/friendica_stable-fpm-alpine/upgrade.exclude
@@ -0,0 +1,10 @@
+/.git/
+/photo/
+/proxy/
+/.htconfig.php
+/.htaccess
+/home.*
+/config/
+/storage/
+/log/
+*.log
\ No newline at end of file
diff --git a/friendica_stable-fpm/Dockerfile b/friendica_stable-fpm/Dockerfile
new file mode 100644
index 0000000..c86e09a
--- /dev/null
+++ b/friendica_stable-fpm/Dockerfile
@@ -0,0 +1,135 @@
+# DO NOT EDIT: created by update.sh from Dockerfile-debian.template
+FROM php:7.3-fpm-stretch
+
+# entrypoint.sh and cron.sh dependencies
+RUN set -ex; \
+    \
+    apt-get update; \
+    apt-get install -y --no-install-recommends \
+        rsync \
+        bzip2 \
+        git \
+# For mail() support
+        ssmtp \
+    ; \
+    rm -rf /var/lib/apt/lists/*;
+
+# install the PHP extensions we need
+# see https://friendi.ca/resources/requirements/
+RUN set -ex; \
+    \
+    savedAptMark="$(apt-mark showmanual)"; \
+    \
+    apt-get update; \
+    apt-get install -y --no-install-recommends \
+        mysql-client \
+        bash \
+        libpng-dev \
+        libjpeg62-turbo-dev \
+        libtool \
+        libmagick++-dev \
+        libmemcached-dev \
+        libgraphicsmagick1-dev \
+        libfreetype6-dev \
+        librsvg2-2 \
+        libzip-dev \
+        libldap2-dev \
+    ; \
+    \
+        debMultiarch="$(dpkg-architecture --query DEB_BUILD_MULTIARCH)"; \
+    \
+    docker-php-ext-configure gd \
+        --with-gd \
+        --with-freetype-dir=/usr/include/ \
+        --with-png-dir=/usr/include/ \
+        --with-jpeg-dir=/usr/include/ \
+    ; \
+    docker-php-ext-configure ldap \
+        	--with-libdir=lib/$debMultiarch/ \
+	; \
+    docker-php-ext-install -j "$(nproc)" \
+        pdo_mysql \
+        gd \
+        zip \
+        opcache \
+        ctype \
+        pcntl \
+        ldap \
+    ; \
+    \
+# pecl will claim success even if one install fails, so we need to perform each install separately
+    pecl install apcu-5.1.18; \
+    pecl install memcached-3.1.5; \
+    pecl install redis-5.1.1; \
+    pecl install imagick-3.4.4; \
+    \
+    docker-php-ext-enable \
+        apcu \
+        memcached \
+        redis \
+        imagick \
+    ; \
+    \
+# reset apt-mark's "manual" list so that "purge --auto-remove" will remove all build dependencies
+    apt-mark auto '.*' > /dev/null; \
+    apt-mark manual $savedAptMark; \
+    ldd "$(php -r 'echo ini_get("extension_dir");')"/*.so \
+      | awk '/=>/ { print $3 }' \
+      | sort -u \
+      | xargs -r dpkg-query -S \
+      | cut -d: -f1 \
+      | sort -u \
+      | xargs -rt apt-mark manual; \
+    \
+    apt-get purge -y --auto-remove -o APT::AutoRemove::RecommendsImportant=false; \
+    rm -rf /var/lib/apt/lists/*
+
+# set recommended PHP.ini settings
+RUN set -ex; \
+    { \
+        echo 'opcache.enable=1' ; \
+        echo 'opcache.interned_strings_buffer=8'; \
+        echo 'opcache.max_accelerated_files=10000'; \
+        echo 'opcache.memory_consumption=128'; \
+        echo 'opcache.save_comments=1'; \
+        echo 'opcache.revalidte_freq=1'; \
+    } > /usr/local/etc/php/conf.d/opcache-recommended.ini; \
+    \
+    { \
+        echo sendmail_path = "/usr/sbin/sendmail -t -i"; \
+    } > /usr/local/etc/php/conf.d/sendmail.ini; \
+    \
+    echo 'apc.enable_cli=1' >> /usr/local/etc/php/conf.d/docker-php-ext-apcu.ini; \
+    \
+    echo 'memory_limit=512M' > /usr/local/etc/php/conf.d/memory-limit.ini; \
+    \
+    mkdir /var/www/data; \
+    chown -R www-data:root /var/www; \
+    chmod -R g=u /var/www
+
+VOLUME /var/www/html
+
+
+ENV FRIENDICA_VERSION 2019.12
+ENV FRIENDICA_ADDONS 2019.12
+
+RUN set -ex; \
+    curl -fsSL -o friendica.tar.gz \
+        "https://github.com/friendica/friendica/archive/${FRIENDICA_VERSION}.tar.gz"; \
+    tar -xzf friendica.tar.gz -C /usr/src/; \
+    rm friendica.tar.gz; \
+    mv -f /usr/src/friendica-${FRIENDICA_VERSION}/ /usr/src/friendica; \
+    chmod 777 /usr/src/friendica/view/smarty3; \
+    curl -fsSL -o friendica_addons.tar.gz \
+        "https://github.com/friendica/friendica-addons/archive/${FRIENDICA_ADDONS}.tar.gz"; \
+    mkdir -p /usr/src/friendica/proxy; \
+    mkdir -p /usr/src/friendica/addon; \
+    tar -xzf friendica_addons.tar.gz -C /usr/src/friendica/addon --strip-components=1; \
+    rm friendica_addons.tar.gz; \
+    /usr/src/friendica/bin/composer.phar install --no-dev -d /usr/src/friendica;
+
+COPY *.sh upgrade.exclude /
+COPY config/* /usr/src/friendica/config/
+
+ENTRYPOINT ["/entrypoint.sh"]
+CMD ["php-fpm"]
diff --git a/friendica_stable-fpm/config/00apcu.config.php b/friendica_stable-fpm/config/00apcu.config.php
new file mode 100644
index 0000000..d6dac4f
--- /dev/null
+++ b/friendica_stable-fpm/config/00apcu.config.php
@@ -0,0 +1,12 @@
+<?php
+
+/**
+ * If nothing else set, use APCu as a caching driver (best performance for local caching)
+ */
+
+return [
+	'system' => [
+		'cache_driver' => 'apcu',
+		'session_handler' => 'cache',
+	],
+];
diff --git a/friendica_stable-fpm/config/01redis.config.php b/friendica_stable-fpm/config/01redis.config.php
new file mode 100644
index 0000000..1a43c95
--- /dev/null
+++ b/friendica_stable-fpm/config/01redis.config.php
@@ -0,0 +1,15 @@
+<?php
+
+if (getenv('REDIS_HOST')) {
+	return [
+		'system' => [
+			'lock_driver' => 'redis',
+			'redis_host' => getenv('REDIS_HOST'),
+			'redis_port' => (getenv('REDIS_PORT') ? getenv('REDIS_PORT') : ''),
+			'redis_password' => (getenv('REDIS_PW') ? getenv('REDIS_PW') : ''),
+			'redis_db' => (getenv('REDIS_DB') ? getenv('REDIS_DB') : 0),
+		],
+	];
+} else {
+	return [];
+}
diff --git a/friendica_stable-fpm/config/zz-docker.config.php b/friendica_stable-fpm/config/zz-docker.config.php
new file mode 100644
index 0000000..c9e5ed8
--- /dev/null
+++ b/friendica_stable-fpm/config/zz-docker.config.php
@@ -0,0 +1,66 @@
+<?php
+
+/**
+ * Fallback config to make it possible overwriting config values
+ * because of docker environment variables
+ *
+ * This doesn't affect DB configurations, but will replace other config values
+ */
+
+$config = [
+	'system' => [
+		// Necessary because otherwise the daemon isn't working
+		'pidfile' => '/var/run/friendica.pid',
+
+		'logfile' => '/var/www/html/friendica.log',
+		'loglevel' => 'notice',
+	],
+	'storage' => [
+		'filesystem_path' => '/var/www/html/storage',
+	],
+];
+
+if (getenv('FRIENDICA_TZ')) {
+	$config['config']['timezone'] = getenv('FRIENDICA_TZ');
+}
+
+if (getenv('FRIENDICA_LANG')) {
+	$config['config']['language'] = getenv('FRIENDICA_LANG');
+}
+
+if (getenv('FRIENDICA_ADMIN_MAIL')) {
+	$config['config']['admin_mail'] = getenv('FRIENDICA_ADMIN_MAIL');
+}
+
+if (getenv('FRIENDICA_SITENAME')) {
+	$config['config']['sitename'] = getenv('FRIENDICA_SITENAME');
+}
+
+if (!empty(getenv('FRIENDICA_NO_VALIDATION'))) {
+	$config['system']['disable_url_validation'] = true;
+	$config['system']['disable_email_validation'] = true;
+}
+
+if (!empty(getenv('FRIENDICA_DATA'))) {
+	$config['storage']['class'] = \Friendica\Model\Storage\Filesystem::class;
+
+	if (!empty(getenv('FRIENDICA_DATA_DIR'))) {
+		$config['storage']['filesystem_path'] = getenv('FRIENDICA_DATA');
+	}
+}
+
+if (!empty(getenv('FRIENDICA_DEBUGGING'))) {
+	$config['system']['debugging'] = true;
+	if (!empty(getenv('FRIENDICA_LOGFILE'))) {
+		$config['system']['logfile'] = getenv('FRIENDICA_LOGFILE');
+	}
+	if (!empty(getenv('FRIENDICA_LOGLEVEL'))) {
+		$config['system']['loglevel'] = getenv('FRIENDICA_LOGLEVEL');
+	}
+}
+
+if (!empty(getenv('HOSTNAME'))) {
+	$config['config']['hostname'] = getenv('HOSTNAME');
+}
+
+return $config;
diff --git a/friendica_stable-fpm/cron.sh b/friendica_stable-fpm/cron.sh
new file mode 100755
index 0000000..3f03a41
--- /dev/null
+++ b/friendica_stable-fpm/cron.sh
@@ -0,0 +1,13 @@
+#!/bin/sh
+trap "break;exit" HUP INT TERM
+
+while [ ! -f /var/www/html/bin/daemon.php ]; do
+    sleep 1
+done
+
+echo "Waiting for MySQL $MYSQL_HOST initialization..."
+if php /var/www/html/bin/wait-for-connection "$MYSQL_HOST" "${MYSQL_PORT:-3306}" 300; then
+  exec php /var/www/html/bin/daemon.php -f start
+else
+  echo "[ERROR] Waited 300 seconds, no response" >&2
+fi
diff --git a/friendica_stable-fpm/entrypoint.sh b/friendica_stable-fpm/entrypoint.sh
new file mode 100755
index 0000000..99b5f4a
--- /dev/null
+++ b/friendica_stable-fpm/entrypoint.sh
@@ -0,0 +1,149 @@
+#!/bin/sh
+set -eu
+
+# run an command with the www-data user
+run_as() {
+	set -- -c "cd /var/www/html; $*"
+	if [ "$(id -u)" -eq 0 ]; then
+		su - www-data -s /bin/sh "$@"
+	else
+		sh  "$@"
+	fi
+}
+
+# checks if the the first parameter is greater than the second parameter
+version_greater() {
+	[ "$(printf '%s\n' "$@" | sort -r -t '-' -k2,2  | sort -t '.' -n -k1,1 -k2,2 -s | head -n 1)" != "$1" ]
+}
+
+setup_ssmtp() {
+	if [ -n "${HOSTNAME+x}" ] && [ -n "${SMTP+x}" ] && [ "${SMTP}" != "localhost" ]; then
+		SITENAME="${FRIENDICA_SITENAME:-Friendica Social Network}"
+		echo "Setup SSMTP for '$SITENAME' with '$SMTP' ..."
+
+		smtp_from=${SMTP_FROM:-no-reply}
+
+		# Setup SSMTP
+		usermod --comment "$(echo "$SITENAME" | tr -dc '[:print:]')" root
+		usermod --comment "$(echo "$SITENAME" | tr -dc '[:print:]')" www-data
+
+		# add possible mail-senders
+		{
+		 echo "www-data:$smtp_from@$HOSTNAME:$SMTP"
+		 echo "root::$smtp_from@$HOSTNAME:$SMTP"
+		} > /etc/ssmtp/revaliases
+
+		# replace ssmtp.conf settings
+		{
+		 echo "root=:$smtp_from@$HOSTNAME"
+		 echo "hostname=$HOSTNAME"
+		 echo "mailhub=$SMTP"
+		 echo "FromLineOverride=YES"
+		 if [ -n "${SMTP_TLS+x}" ]; then echo "UseTLS=$SMTP_TLS"; fi
+		 if [ -n "${SMTP_STARTTLS+x}" ]; then echo "UseSTARTTLS=$SMTP_STARTTLS"; fi
+		 if [ -n "${SMTP_AUTH_USER+x}" ]; then echo "AuthUser=$SMTP_AUTH_USER"; fi
+		 if [ -n "${SMTP_AUTH_PASS+x}" ]; then echo "AuthPass=$SMTP_AUTH_PASS";fi
+		 if [ -n "${SMTP_AUTH_METHOD+x}" ]; then echo "AuthMethod=$SMTP_AUTH_METHOD"; fi
+		} > /etc/ssmtp/ssmtp.conf
+
+		echo "Setup finished"
+	fi
+}
+
+# just check if we execute apache or php-fpm
+if expr "$1" : "apache" 1>/dev/null || [ "$1" = "php-fpm" ]; then
+	installed_version="0.0.0.0"
+	if [ -f /var/www/html/VERSION ]; then
+		installed_version="$(cat /var/www/html/VERSION)"
+	fi
+
+	image_version="$(cat /usr/src/friendica/VERSION)"
+
+	# no downgrading possible
+	if version_greater "$installed_version" "$image_version"; then
+		echo "Can't copy Friendica sources because the version of the data ($installed_version) is higher than the docker image ($image_version)"
+		exit 1
+	fi
+
+	setup_ssmtp
+
+	# check it just in case the version is greater or if we force the upgrade
+	if version_greater "$image_version" "$installed_version" || [ "${FRIENDICA_UPGRADE:-false}" = "true" ]; then
+		echo "Initializing Friendica $image_version ..."
+
+		if [ "$installed_version" != "0.0.0.0" ]; then
+			echo "Upgrading Friendica from $installed_version ..."
+		fi
+
+		if [ "$(id -u)" -eq 0 ]; then
+			rsync_options="-rlDog --chown=www-data:www-data"
+		else
+			rsync_options="-rlD"
+		fi
+
+		rsync $rsync_options --delete --exclude-from=/upgrade.exclude /usr/src/friendica/ /var/www/html/
+
+		# Update docker-based config files, but never delete other config files
+		rsync $rsync_options --update /usr/src/friendica/config/ /var/www/html/config/
+
+		# In case there is no .htaccess, copy it from the default dist file
+		if [ ! -f "/var/www/html/.htaccess" ]; then
+			cp "/var/www/html/.htaccess-dist" "/var/www/html/.htaccess"
+		fi
+
+		if [ -d /var/www/html/view/smarty3 ]; then
+			chmod -R 777 /var/www/html/view/smarty3
+		fi
+		echo "Initializing finished"
+
+		# install
+		if [ "$installed_version" = "0.0.0.0" ]; then
+			echo "New Friendica instance"
+
+			install=false
+			if [ -n "${MYSQL_DATABASE+x}" ] && [ -n "${MYSQL_PASSWORD+x}" ] && [ -n "${MYSQL_HOST+x}" ] && [ -n "${MYSQL_USER+x}" ] && [ -n "${FRIENDICA_ADMIN_MAIL+x}" ] && [ -n "${FRIENDICA_URL+x}" ]; then
+				echo "Installation with environment variables"
+
+				FRIENDICA_TZ=${FRIENDICA_TZ:-America/LosAngeles}
+				FRIENDICA_LANG=${FRIENDICA_LANG:-en}
+				MYSQL_PORT=${MYSQL_PORT:-3306}
+
+				# shellcheck disable=SC2016
+				install_options='-s --dbhost "'$MYSQL_HOST'" --dbport "'$MYSQL_PORT'" --dbdata "'$MYSQL_DATABASE'" --dbuser "'$MYSQL_USER'" --dbpass "'$MYSQL_PASSWORD'"'
+
+				# shellcheck disable=SC2016
+				install_options=$install_options' --admin "'$FRIENDICA_ADMIN_MAIL'" --tz "'$FRIENDICA_TZ'" --lang "'$FRIENDICA_LANG'" --url "'$FRIENDICA_URL'"'
+				install=true
+			fi
+
+			if [ "$install" = true ]; then
+				echo "Waiting for MySQL $MYSQL_HOST initialization..."
+				if run_as "php /var/www/html/bin/wait-for-connection $MYSQL_HOST ${MYSQL_PORT:-3306} 300"; then
+
+					echo "Starting Friendica installation ..."
+					run_as "php /var/www/html/bin/console.php autoinstall $install_options"
+
+					rm -fr /var/www/html/view/smarty3/compiled
+
+					# load other config files (*.config.php) to the config folder
+					if [ -d "/usr/src/config" ]; then
+					  rsync $rsync_options --ignore-existing /usr/src/config/ /var/www/html/config/
+					fi
+
+					echo "Installation finished"
+				else
+					echo "[ERROR] Waited 300 seconds, no response" >&2
+				fi
+			else
+				echo "Running web-based installer on first connect!"
+			fi
+		# upgrade
+		else
+			echo "Upgrading Friendica ..."
+			run_as 'php /var/www/html/bin/console.php dbstructure update'
+			echo "Upgrading finished"
+		fi
+	fi
+fi
+
+exec "$@"
diff --git a/friendica_stable-fpm/upgrade.exclude b/friendica_stable-fpm/upgrade.exclude
new file mode 100644
index 0000000..2fb6533
--- /dev/null
+++ b/friendica_stable-fpm/upgrade.exclude
@@ -0,0 +1,10 @@
+/.git/
+/photo/
+/proxy/
+/.htconfig.php
+/.htaccess
+/home.*
+/config/
+/storage/
+/log/
+*.log
\ No newline at end of file
diff --git a/friendica_stable/Dockerfile b/friendica_stable/Dockerfile
new file mode 100644
index 0000000..ac047bd
--- /dev/null
+++ b/friendica_stable/Dockerfile
@@ -0,0 +1,144 @@
+# DO NOT EDIT: created by update.sh from Dockerfile-debian.template
+FROM php:7.3-apache-stretch
+
+# entrypoint.sh and cron.sh dependencies
+RUN set -ex; \
+    \
+    apt-get update; \
+    apt-get install -y --no-install-recommends \
+        rsync \
+        bzip2 \
+        git \
+# For mail() support
+        ssmtp \
+    ; \
+    rm -rf /var/lib/apt/lists/*;
+
+# install the PHP extensions we need
+# see https://friendi.ca/resources/requirements/
+RUN set -ex; \
+    \
+    savedAptMark="$(apt-mark showmanual)"; \
+    \
+    apt-get update; \
+    apt-get install -y --no-install-recommends \
+        mysql-client \
+        bash \
+        libpng-dev \
+        libjpeg62-turbo-dev \
+        libtool \
+        libmagick++-dev \
+        libmemcached-dev \
+        libgraphicsmagick1-dev \
+        libfreetype6-dev \
+        librsvg2-2 \
+        libzip-dev \
+        libldap2-dev \
+    ; \
+    \
+        debMultiarch="$(dpkg-architecture --query DEB_BUILD_MULTIARCH)"; \
+    \
+    docker-php-ext-configure gd \
+        --with-gd \
+        --with-freetype-dir=/usr/include/ \
+        --with-png-dir=/usr/include/ \
+        --with-jpeg-dir=/usr/include/ \
+    ; \
+    docker-php-ext-configure ldap \
+        	--with-libdir=lib/$debMultiarch/ \
+	; \
+    docker-php-ext-install -j "$(nproc)" \
+        pdo_mysql \
+        gd \
+        zip \
+        opcache \
+        ctype \
+        pcntl \
+        ldap \
+    ; \
+    \
+# pecl will claim success even if one install fails, so we need to perform each install separately
+    pecl install apcu-5.1.18; \
+    pecl install memcached-3.1.5; \
+    pecl install redis-5.1.1; \
+    pecl install imagick-3.4.4; \
+    \
+    docker-php-ext-enable \
+        apcu \
+        memcached \
+        redis \
+        imagick \
+    ; \
+    \
+# reset apt-mark's "manual" list so that "purge --auto-remove" will remove all build dependencies
+    apt-mark auto '.*' > /dev/null; \
+    apt-mark manual $savedAptMark; \
+    ldd "$(php -r 'echo ini_get("extension_dir");')"/*.so \
+      | awk '/=>/ { print $3 }' \
+      | sort -u \
+      | xargs -r dpkg-query -S \
+      | cut -d: -f1 \
+      | sort -u \
+      | xargs -rt apt-mark manual; \
+    \
+    apt-get purge -y --auto-remove -o APT::AutoRemove::RecommendsImportant=false; \
+    rm -rf /var/lib/apt/lists/*
+
+# set recommended PHP.ini settings
+RUN set -ex; \
+    { \
+        echo 'opcache.enable=1' ; \
+        echo 'opcache.interned_strings_buffer=8'; \
+        echo 'opcache.max_accelerated_files=10000'; \
+        echo 'opcache.memory_consumption=128'; \
+        echo 'opcache.save_comments=1'; \
+        echo 'opcache.revalidte_freq=1'; \
+    } > /usr/local/etc/php/conf.d/opcache-recommended.ini; \
+    \
+    { \
+        echo sendmail_path = "/usr/sbin/sendmail -t -i"; \
+    } > /usr/local/etc/php/conf.d/sendmail.ini; \
+    \
+    echo 'apc.enable_cli=1' >> /usr/local/etc/php/conf.d/docker-php-ext-apcu.ini; \
+    \
+    echo 'memory_limit=512M' > /usr/local/etc/php/conf.d/memory-limit.ini; \
+    \
+    mkdir /var/www/data; \
+    chown -R www-data:root /var/www; \
+    chmod -R g=u /var/www
+
+VOLUME /var/www/html
+
+RUN set -ex;\
+    a2enmod rewrite remoteip ;\
+    {\
+     echo RemoteIPHeader X-Real-IP ;\
+     echo RemoteIPTrustedProxy 10.0.0.0/8 ;\
+     echo RemoteIPTrustedProxy 172.16.0.0/12 ;\
+     echo RemoteIPTrustedProxy 192.168.0.0/16 ;\
+    } > /etc/apache2/conf-available/remoteip.conf;\
+    a2enconf remoteip
+
+ENV FRIENDICA_VERSION 2019.12
+ENV FRIENDICA_ADDONS 2019.12
+
+RUN set -ex; \
+    curl -fsSL -o friendica.tar.gz \
+        "https://github.com/friendica/friendica/archive/${FRIENDICA_VERSION}.tar.gz"; \
+    tar -xzf friendica.tar.gz -C /usr/src/; \
+    rm friendica.tar.gz; \
+    mv -f /usr/src/friendica-${FRIENDICA_VERSION}/ /usr/src/friendica; \
+    chmod 777 /usr/src/friendica/view/smarty3; \
+    curl -fsSL -o friendica_addons.tar.gz \
+        "https://github.com/friendica/friendica-addons/archive/${FRIENDICA_ADDONS}.tar.gz"; \
+    mkdir -p /usr/src/friendica/proxy; \
+    mkdir -p /usr/src/friendica/addon; \
+    tar -xzf friendica_addons.tar.gz -C /usr/src/friendica/addon --strip-components=1; \
+    rm friendica_addons.tar.gz; \
+    /usr/src/friendica/bin/composer.phar install --no-dev -d /usr/src/friendica;
+
+COPY *.sh upgrade.exclude /
+COPY config/* /usr/src/friendica/config/
+
+ENTRYPOINT ["/entrypoint.sh"]
+CMD ["apache2-foreground"]
diff --git a/friendica_stable/config/00apcu.config.php b/friendica_stable/config/00apcu.config.php
new file mode 100644
index 0000000..d6dac4f
--- /dev/null
+++ b/friendica_stable/config/00apcu.config.php
@@ -0,0 +1,12 @@
+<?php
+
+/**
+ * If nothing else set, use APCu as a caching driver (best performance for local caching)
+ */
+
+return [
+	'system' => [
+		'cache_driver' => 'apcu',
+		'session_handler' => 'cache',
+	],
+];
diff --git a/friendica_stable/config/01redis.config.php b/friendica_stable/config/01redis.config.php
new file mode 100644
index 0000000..1a43c95
--- /dev/null
+++ b/friendica_stable/config/01redis.config.php
@@ -0,0 +1,15 @@
+<?php
+
+if (getenv('REDIS_HOST')) {
+	return [
+		'system' => [
+			'lock_driver' => 'redis',
+			'redis_host' => getenv('REDIS_HOST'),
+			'redis_port' => (getenv('REDIS_PORT') ? getenv('REDIS_PORT') : ''),
+			'redis_password' => (getenv('REDIS_PW') ? getenv('REDIS_PW') : ''),
+			'redis_db' => (getenv('REDIS_DB') ? getenv('REDIS_DB') : 0),
+		],
+	];
+} else {
+	return [];
+}
diff --git a/friendica_stable/config/zz-docker.config.php b/friendica_stable/config/zz-docker.config.php
new file mode 100644
index 0000000..c9e5ed8
--- /dev/null
+++ b/friendica_stable/config/zz-docker.config.php
@@ -0,0 +1,66 @@
+<?php
+
+/**
+ * Fallback config to make it possible overwriting config values
+ * because of docker environment variables
+ *
+ * This doesn't affect DB configurations, but will replace other config values
+ */
+
+$config = [
+	'system' => [
+		// Necessary because otherwise the daemon isn't working
+		'pidfile' => '/var/run/friendica.pid',
+
+		'logfile' => '/var/www/html/friendica.log',
+		'loglevel' => 'notice',
+	],
+	'storage' => [
+		'filesystem_path' => '/var/www/html/storage',
+	],
+];
+
+if (getenv('FRIENDICA_TZ')) {
+	$config['config']['timezone'] = getenv('FRIENDICA_TZ');
+}
+
+if (getenv('FRIENDICA_LANG')) {
+	$config['config']['language'] = getenv('FRIENDICA_LANG');
+}
+
+if (getenv('FRIENDICA_ADMIN_MAIL')) {
+	$config['config']['admin_mail'] = getenv('FRIENDICA_ADMIN_MAIL');
+}
+
+if (getenv('FRIENDICA_SITENAME')) {
+	$config['config']['sitename'] = getenv('FRIENDICA_SITENAME');
+}
+
+if (!empty(getenv('FRIENDICA_NO_VALIDATION'))) {
+	$config['system']['disable_url_validation'] = true;
+	$config['system']['disable_email_validation'] = true;
+}
+
+if (!empty(getenv('FRIENDICA_DATA'))) {
+	$config['storage']['class'] = \Friendica\Model\Storage\Filesystem::class;
+
+	if (!empty(getenv('FRIENDICA_DATA_DIR'))) {
+		$config['storage']['filesystem_path'] = getenv('FRIENDICA_DATA');
+	}
+}
+
+if (!empty(getenv('FRIENDICA_DEBUGGING'))) {
+	$config['system']['debugging'] = true;
+	if (!empty(getenv('FRIENDICA_LOGFILE'))) {
+		$config['system']['logfile'] = getenv('FRIENDICA_LOGFILE');
+	}
+	if (!empty(getenv('FRIENDICA_LOGLEVEL'))) {
+		$config['system']['loglevel'] = getenv('FRIENDICA_LOGLEVEL');
+	}
+}
+
+if (!empty(getenv('HOSTNAME'))) {
+	$config['config']['hostname'] = getenv('HOSTNAME');
+}
+
+return $config;
diff --git a/friendica_stable/cron.sh b/friendica_stable/cron.sh
new file mode 100755
index 0000000..3f03a41
--- /dev/null
+++ b/friendica_stable/cron.sh
@@ -0,0 +1,13 @@
+#!/bin/sh
+trap "break;exit" HUP INT TERM
+
+while [ ! -f /var/www/html/bin/daemon.php ]; do
+    sleep 1
+done
+
+echo "Waiting for MySQL $MYSQL_HOST initialization..."
+if php /var/www/html/bin/wait-for-connection "$MYSQL_HOST" "${MYSQL_PORT:-3306}" 300; then
+  exec php /var/www/html/bin/daemon.php -f start
+else
+  echo "[ERROR] Waited 300 seconds, no response" >&2
+fi
diff --git a/friendica_stable/entrypoint.sh b/friendica_stable/entrypoint.sh
new file mode 100755
index 0000000..99b5f4a
--- /dev/null
+++ b/friendica_stable/entrypoint.sh
@@ -0,0 +1,149 @@
+#!/bin/sh
+set -eu
+
+# run an command with the www-data user
+run_as() {
+	set -- -c "cd /var/www/html; $*"
+	if [ "$(id -u)" -eq 0 ]; then
+		su - www-data -s /bin/sh "$@"
+	else
+		sh  "$@"
+	fi
+}
+
+# checks if the the first parameter is greater than the second parameter
+version_greater() {
+	[ "$(printf '%s\n' "$@" | sort -r -t '-' -k2,2  | sort -t '.' -n -k1,1 -k2,2 -s | head -n 1)" != "$1" ]
+}
+
+setup_ssmtp() {
+	if [ -n "${HOSTNAME+x}" ] && [ -n "${SMTP+x}" ] && [ "${SMTP}" != "localhost" ]; then
+		SITENAME="${FRIENDICA_SITENAME:-Friendica Social Network}"
+		echo "Setup SSMTP for '$SITENAME' with '$SMTP' ..."
+
+		smtp_from=${SMTP_FROM:-no-reply}
+
+		# Setup SSMTP
+		usermod --comment "$(echo "$SITENAME" | tr -dc '[:print:]')" root
+		usermod --comment "$(echo "$SITENAME" | tr -dc '[:print:]')" www-data
+
+		# add possible mail-senders
+		{
+		 echo "www-data:$smtp_from@$HOSTNAME:$SMTP"
+		 echo "root::$smtp_from@$HOSTNAME:$SMTP"
+		} > /etc/ssmtp/revaliases
+
+		# replace ssmtp.conf settings
+		{
+		 echo "root=:$smtp_from@$HOSTNAME"
+		 echo "hostname=$HOSTNAME"
+		 echo "mailhub=$SMTP"
+		 echo "FromLineOverride=YES"
+		 if [ -n "${SMTP_TLS+x}" ]; then echo "UseTLS=$SMTP_TLS"; fi
+		 if [ -n "${SMTP_STARTTLS+x}" ]; then echo "UseSTARTTLS=$SMTP_STARTTLS"; fi
+		 if [ -n "${SMTP_AUTH_USER+x}" ]; then echo "AuthUser=$SMTP_AUTH_USER"; fi
+		 if [ -n "${SMTP_AUTH_PASS+x}" ]; then echo "AuthPass=$SMTP_AUTH_PASS";fi
+		 if [ -n "${SMTP_AUTH_METHOD+x}" ]; then echo "AuthMethod=$SMTP_AUTH_METHOD"; fi
+		} > /etc/ssmtp/ssmtp.conf
+
+		echo "Setup finished"
+	fi
+}
+
+# just check if we execute apache or php-fpm
+if expr "$1" : "apache" 1>/dev/null || [ "$1" = "php-fpm" ]; then
+	installed_version="0.0.0.0"
+	if [ -f /var/www/html/VERSION ]; then
+		installed_version="$(cat /var/www/html/VERSION)"
+	fi
+
+	image_version="$(cat /usr/src/friendica/VERSION)"
+
+	# no downgrading possible
+	if version_greater "$installed_version" "$image_version"; then
+		echo "Can't copy Friendica sources because the version of the data ($installed_version) is higher than the docker image ($image_version)"
+		exit 1
+	fi
+
+	setup_ssmtp
+
+	# check it just in case the version is greater or if we force the upgrade
+	if version_greater "$image_version" "$installed_version" || [ "${FRIENDICA_UPGRADE:-false}" = "true" ]; then
+		echo "Initializing Friendica $image_version ..."
+
+		if [ "$installed_version" != "0.0.0.0" ]; then
+			echo "Upgrading Friendica from $installed_version ..."
+		fi
+
+		if [ "$(id -u)" -eq 0 ]; then
+			rsync_options="-rlDog --chown=www-data:www-data"
+		else
+			rsync_options="-rlD"
+		fi
+
+		rsync $rsync_options --delete --exclude-from=/upgrade.exclude /usr/src/friendica/ /var/www/html/
+
+		# Update docker-based config files, but never delete other config files
+		rsync $rsync_options --update /usr/src/friendica/config/ /var/www/html/config/
+
+		# In case there is no .htaccess, copy it from the default dist file
+		if [ ! -f "/var/www/html/.htaccess" ]; then
+			cp "/var/www/html/.htaccess-dist" "/var/www/html/.htaccess"
+		fi
+
+		if [ -d /var/www/html/view/smarty3 ]; then
+			chmod -R 777 /var/www/html/view/smarty3
+		fi
+		echo "Initializing finished"
+
+		# install
+		if [ "$installed_version" = "0.0.0.0" ]; then
+			echo "New Friendica instance"
+
+			install=false
+			if [ -n "${MYSQL_DATABASE+x}" ] && [ -n "${MYSQL_PASSWORD+x}" ] && [ -n "${MYSQL_HOST+x}" ] && [ -n "${MYSQL_USER+x}" ] && [ -n "${FRIENDICA_ADMIN_MAIL+x}" ] && [ -n "${FRIENDICA_URL+x}" ]; then
+				echo "Installation with environment variables"
+
+				FRIENDICA_TZ=${FRIENDICA_TZ:-America/LosAngeles}
+				FRIENDICA_LANG=${FRIENDICA_LANG:-en}
+				MYSQL_PORT=${MYSQL_PORT:-3306}
+
+				# shellcheck disable=SC2016
+				install_options='-s --dbhost "'$MYSQL_HOST'" --dbport "'$MYSQL_PORT'" --dbdata "'$MYSQL_DATABASE'" --dbuser "'$MYSQL_USER'" --dbpass "'$MYSQL_PASSWORD'"'
+
+				# shellcheck disable=SC2016
+				install_options=$install_options' --admin "'$FRIENDICA_ADMIN_MAIL'" --tz "'$FRIENDICA_TZ'" --lang "'$FRIENDICA_LANG'" --url "'$FRIENDICA_URL'"'
+				install=true
+			fi
+
+			if [ "$install" = true ]; then
+				echo "Waiting for MySQL $MYSQL_HOST initialization..."
+				if run_as "php /var/www/html/bin/wait-for-connection $MYSQL_HOST ${MYSQL_PORT:-3306} 300"; then
+
+					echo "Starting Friendica installation ..."
+					run_as "php /var/www/html/bin/console.php autoinstall $install_options"
+
+					rm -fr /var/www/html/view/smarty3/compiled
+
+					# load other config files (*.config.php) to the config folder
+					if [ -d "/usr/src/config" ]; then
+					  rsync $rsync_options --ignore-existing /usr/src/config/ /var/www/html/config/
+					fi
+
+					echo "Installation finished"
+				else
+					echo "[ERROR] Waited 300 seconds, no response" >&2
+				fi
+			else
+				echo "Running web-based installer on first connect!"
+			fi
+		# upgrade
+		else
+			echo "Upgrading Friendica ..."
+			run_as 'php /var/www/html/bin/console.php dbstructure update'
+			echo "Upgrading finished"
+		fi
+	fi
+fi
+
+exec "$@"
diff --git a/friendica_stable/upgrade.exclude b/friendica_stable/upgrade.exclude
new file mode 100644
index 0000000..2fb6533
--- /dev/null
+++ b/friendica_stable/upgrade.exclude
@@ -0,0 +1,10 @@
+/.git/
+/photo/
+/proxy/
+/.htconfig.php
+/.htaccess
+/home.*
+/config/
+/storage/
+/log/
+*.log
\ No newline at end of file

@yosifkit
Copy link
Member

yosifkit commented Jan 6, 2020

Build test of #6446; dca5efe; amd64 (friendica):

$ bashbrew build friendica:2019.12-apache
Building bashbrew/cache:38cc6d6543a274049e20a435349abc69c33b639ce143dcdc01139f74591ab247 (friendica:2019.12-apache)
Tagging friendica:2019.12-apache
Tagging friendica:apache
Tagging friendica:stable-apache
Tagging friendica:2019.12
Tagging friendica:latest
Tagging friendica:stable

$ test/run.sh friendica:2019.12-apache
testing friendica:2019.12-apache
	'utc' [1/4]...passed
	'cve-2014--shellshock' [2/4]...passed
	'no-hard-coded-passwords' [3/4]...passed
	'override-cmd' [4/4]...passed


$ bashbrew build friendica:2019.12-fpm
Building bashbrew/cache:9da6bb15e37905a44016d75c399b688a64cc429679024bf12fbfc49339711c2a (friendica:2019.12-fpm)
Tagging friendica:2019.12-fpm
Tagging friendica:fpm
Tagging friendica:stable-fpm

$ test/run.sh friendica:2019.12-fpm
testing friendica:2019.12-fpm
	'utc' [1/4]...passed
	'cve-2014--shellshock' [2/4]...passed
	'no-hard-coded-passwords' [3/4]...passed
	'override-cmd' [4/4]...passed


$ bashbrew build friendica:2019.12-fpm-alpine
Building bashbrew/cache:029bba05c3ca682acb416a60b167cbab86834222a1fab7bca8179c4208ce63a9 (friendica:2019.12-fpm-alpine)
Tagging friendica:2019.12-fpm-alpine
Tagging friendica:fpm-alpine
Tagging friendica:stable-fpm-alpine

$ test/run.sh friendica:2019.12-fpm-alpine
testing friendica:2019.12-fpm-alpine
	'utc' [1/4]...passed
	'cve-2014--shellshock' [2/4]...passed
	'no-hard-coded-passwords' [3/4]...passed
	'override-cmd' [4/4]...passed


$ bashbrew build friendica:2020.03-dev-apache
Building bashbrew/cache:3ad5a243757c41c678e20aecf0590be8d4653c18918a51c45555888ed36dc85e (friendica:2020.03-dev-apache)
Tagging friendica:2020.03-dev-apache
Tagging friendica:dev-apache
Tagging friendica:2020.03-dev
Tagging friendica:dev

$ test/run.sh friendica:2020.03-dev-apache
testing friendica:2020.03-dev-apache
	'utc' [1/4]...passed
	'cve-2014--shellshock' [2/4]...passed
	'no-hard-coded-passwords' [3/4]...passed
	'override-cmd' [4/4]...passed


$ bashbrew build friendica:2020.03-dev-fpm
Building bashbrew/cache:bf29515ea3b96afb1a72ddcc41825302c4433233594afd1bc29df7cbc57e5f83 (friendica:2020.03-dev-fpm)
Tagging friendica:2020.03-dev-fpm
Tagging friendica:dev-fpm

$ test/run.sh friendica:2020.03-dev-fpm
testing friendica:2020.03-dev-fpm
	'utc' [1/4]...passed
	'cve-2014--shellshock' [2/4]...passed
	'no-hard-coded-passwords' [3/4]...passed
	'override-cmd' [4/4]...passed


$ bashbrew build friendica:2020.03-dev-fpm-alpine
Building bashbrew/cache:b12aaffb7dc6017cfae55698dcbdf08e2c1e18a8ff3c2e6ddbb7e11118d964f2 (friendica:2020.03-dev-fpm-alpine)
Tagging friendica:2020.03-dev-fpm-alpine
Tagging friendica:dev-fpm-alpine

$ test/run.sh friendica:2020.03-dev-fpm-alpine
testing friendica:2020.03-dev-fpm-alpine
	'utc' [1/4]...passed
	'cve-2014--shellshock' [2/4]...passed
	'no-hard-coded-passwords' [3/4]...passed
	'override-cmd' [4/4]...passed

@tianon
Copy link
Member

tianon commented Jan 8, 2020

LGTM 👍

@tianon tianon merged commit 5b18883 into docker-library:master Jan 8, 2020
@nupplaphil nupplaphil deleted the friendica branch January 8, 2020 22:24
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants