diff --git a/README.md b/README.md
index 55edc74c15b9df0221d2cff862c869eb9321e8ee..cd864127a3eeaec769fe3285ddd32e87c4828afd 100644
--- a/README.md
+++ b/README.md
@@ -26,6 +26,9 @@ vhosts: {}
 # name: *mapsconfig*, see below for definition
 maps: {}
 
+# name: *cacheconfig*, see below for definition
+caches: {}
+
 # force all traffic on ssl, except letsencrypt challenges
 force_ssl: True
 
@@ -117,6 +120,9 @@ alias: None
 
 # Array of custom config strings to add to the vhost config, the ";" is added after every entry
 custom: []
+
+# name of the cache to use, only set if not none
+cache: None
 ```
 
 **authconfig**
@@ -148,7 +154,16 @@ data: {}
 
 **phpconfig**:
 ```
+# If set, fpm forks exactly the number of worker processes specified (pm=static, pm.max_children=COUNT)
+fpm_process_count: 5
 ini:
 	post_max_size: 64M
 	upload_max_filesize: 64M
 ```
+
+**cacheconfig**:
+```
+keys_zone_size: "10m"
+cache_size: "1g"
+inactive_time: "10m"
+```
\ No newline at end of file
diff --git a/defaults/main.yml b/defaults/main.yml
index 62343413d6f7f11e4dff14ba0c46b6eb88a95c48..0b79c71209212b367208acfd0f2fb034f1fa2b85 100644
--- a/defaults/main.yml
+++ b/defaults/main.yml
@@ -12,6 +12,7 @@ nginx:
   vhosts: {}
   streams: {}
   maps: {}
+  caches: {}
   resolver:
     - 8.8.8.8
     - 8.8.4.4
@@ -57,6 +58,11 @@ nginx_streams_defaults:
   proxy_connect_timeout: "2s"
   proxy_next_upstream_tries: 2
 
+nginx_caches_defaults:
+  keys_zone_size: "10m"
+  cache_size: "1g"
+  inactive_time: "60m"
+
 nginx_forcessl_vhost:
   "https-redirect":
     listen:
@@ -78,3 +84,5 @@ phpinidefault:
   upload_max_filesize: 64M
   memory_limit: 128M
   date_timezone: UTC
+  session_gc_maxlifetime: 1440
+  syslog: true
diff --git a/tasks/main.yml b/tasks/main.yml
index 3f3dd30d2b8570303a1011bb06d0da33dcec7f8d..043be4c2ec1dbae1eb03cc203864e696ae6f3df3 100644
--- a/tasks/main.yml
+++ b/tasks/main.yml
@@ -42,6 +42,15 @@
   notify:
   - restart nginx
 
+- name: create cache directories
+  with_dict: "{{ nginx.caches }}"
+  file:
+    path: "/var/cache/nginx/{{ item.key }}"
+    state: directory
+    mode: '0755'
+    owner: www-data
+    recurse: True
+
 - name: execute ssl template
   template:
     src: ssl_files.conf.j2
@@ -58,6 +67,7 @@
     - upstreams.conf
     - proxy.conf
     - maps.conf
+    - caches.conf
   template:
     src: "{{ item }}.j2"
     dest: "/etc/nginx/conf.d/{{ item }}"
diff --git a/tasks/php-fpm.yml b/tasks/php-fpm.yml
index 20afac56f944287235f18436a32d27332c37d2ff..9e066552f9910c0815c35ecc7e3d06e7908a6e02 100644
--- a/tasks/php-fpm.yml
+++ b/tasks/php-fpm.yml
@@ -8,6 +8,7 @@
     - php-ldap
     - php-gd
     - php-imagick
+    - libmagickcore-6.q16-6-extra # SVG support for php-imagick
     - php-xml
     - php-mbstring
     - php-opcache
diff --git a/templates/caches.conf.j2 b/templates/caches.conf.j2
new file mode 100644
index 0000000000000000000000000000000000000000..12dee1741a63b102bc12cfbc9b8a5e9b905bdf7c
--- /dev/null
+++ b/templates/caches.conf.j2
@@ -0,0 +1,6 @@
+{% for cache in nginx.caches %}
+{% set c = {}|combine(nginx_caches_defaults, nginx.caches[cache], recursive=True) %}
+# {{ cache }}
+proxy_cache_path /var/cache/nginx/{{ cache }} levels=1:2 keys_zone={{ cache }}:{{ c.keys_zone_size }} max_size={{ c.cache_size }} inactive={{ c.inactive_time }} use_temp_path=off;
+
+{% endfor %}
\ No newline at end of file
diff --git a/templates/php-fpm/php.ini.j2 b/templates/php-fpm/php.ini.j2
index 9430046dd1e55181c0cc4fafc3a90a51312c5ef2..8e4d93197b89462a670523096029a6548616816f 100644
--- a/templates/php-fpm/php.ini.j2
+++ b/templates/php-fpm/php.ini.j2
@@ -571,7 +571,9 @@ html_errors = On
 ; Example:
 ;error_log = php_errors.log
 ; Log errors to syslog (Event Log on Windows).
-;error_log = syslog
+{% if phpini.syslog %}
+error_log = syslog
+{% endif %}
 
 ;windows.show_crt_warning
 ; Default value: 0
@@ -1422,7 +1424,7 @@ session.gc_divisor = 1000
 ; After this number of seconds, stored data will be seen as 'garbage' and
 ; cleaned up by the garbage collection process.
 ; http://php.net/session.gc-maxlifetime
-session.gc_maxlifetime = 1440
+session.gc_maxlifetime = {{ phpini.session_gc_maxlifetime }}
 
 ; NOTE: If you are using the subdirectory option for storing session files
 ;       (see session.save_path above), then garbage collection does *not*
diff --git a/templates/php-fpm/www.conf.j2 b/templates/php-fpm/www.conf.j2
index b9b341172201839612efb79c2c3671d1676e44eb..e16b2cebea59e18e76539201382f36bd9162eca4 100644
--- a/templates/php-fpm/www.conf.j2
+++ b/templates/php-fpm/www.conf.j2
@@ -99,7 +99,11 @@ listen.group = www-data
 ;             pm.process_idle_timeout   - The number of seconds after which
 ;                                         an idle process will be killed.
 ; Note: This value is mandatory.
+{% if nginx.php.fpm_process_count|d(False) %}
+pm = static
+{% else %}
 pm = dynamic
+{% endif %}
 
 ; The number of child processes to be created when pm is set to 'static' and the
 ; maximum number of child processes when pm is set to 'dynamic' or 'ondemand'.
@@ -110,7 +114,7 @@ pm = dynamic
 ; forget to tweak pm.* to fit your needs.
 ; Note: Used when pm is set to 'static', 'dynamic' or 'ondemand'
 ; Note: This value is mandatory.
-pm.max_children = 50
+pm.max_children = {{ nginx.php.fpm_process_count|d(50) }}
 
 ; The number of child processes created on startup.
 ; Note: Used only when pm is set to 'dynamic'
diff --git a/templates/vhost.conf.j2 b/templates/vhost.conf.j2
index 9b968a805f9f7749163ab99459658f9974981bae..0d5614b350347c34a90dcec5ea295da5b1ee23bf 100644
--- a/templates/vhost.conf.j2
+++ b/templates/vhost.conf.j2
@@ -47,7 +47,19 @@ server {
 		{% if location.backend|d(False) %}
 		proxy_pass {{ location.backend }};
 
+		{% if location.cache|d(False) %}
+		proxy_cache                             {{ location.cache }};
+		proxy_cache_revalidate                  on;
+		proxy_cache_lock                        on;
+		proxy_cache_use_stale                   error timeout http_500 http_502 http_503 http_504;
+		proxy_cache_background_update           on;
+		# use actual host instead of proxy host for cache key
+		proxy_cache_key 						$scheme$host$uri$is_args$args;
+		# for debugging purposes, add the following header
+		#add_header X-Cache-Status $upstream_cache_status;
+		{% else %}
 		proxy_buffering off;
+		{% endif %}
 
 		# add proxy headers
 		proxy_set_header Host			{{ location.host|d(vhost.host) }};