diff --git a/defaults/main.yml b/defaults/main.yml
index a5f9df11fb802348f2b0aa81a643dd73a529385e..33f214163ec7ab82231eae8b5d324e23d7fb18a6 100644
--- a/defaults/main.yml
+++ b/defaults/main.yml
@@ -1,5 +1,6 @@
 nginx:
   add_headers: []
+  real_ip_header: "X-Forwarded-For"
   real_ip_from:
     "127.0.0.1": {}
     "::1": {}
@@ -9,6 +10,7 @@ nginx:
   snakeoil_default: false
   upstreams: {}
   vhosts: {}
+  streams: {}
   maps: {}
   resolver:
     - 8.8.8.8
@@ -44,6 +46,13 @@ nginx_vhosts_defaults:
   hide_proxy_headers: {}
   backend: ~
 
+nginx_streams_defaults:
+  listen:
+    custom: []
+  includes: []
+  proxy_pass: ~
+  proxy_protocol: "off"
+
 nginx_forcessl_vhost:
   "https-redirect":
     listen:
diff --git a/files/config/nginx.conf b/files/config/nginx.conf
index 889052d50a20df390df00ac9db20d1922b14673c..59f8e3f33a20063ebbebe05812c5666257ac8a90 100644
--- a/files/config/nginx.conf
+++ b/files/config/nginx.conf
@@ -3,6 +3,7 @@ worker_processes auto;
 pid /run/nginx.pid;
 
 load_module /usr/lib/nginx/modules/ngx_http_headers_more_filter_module.so;
+load_module /usr/lib/nginx/modules/ngx_stream_module.so;
 
 events {
 	use epoll;
@@ -22,6 +23,7 @@ http {
 	types_hash_max_size 2048;
 	server_tokens off;
 	reset_timedout_connection on;
+	large_client_header_buffers 4 32k;
 
 	server_names_hash_bucket_size 64;
 	map_hash_bucket_size 64;
@@ -36,3 +38,8 @@ http {
 	##
 	include /etc/nginx/sites-enabled/*;
 }
+
+stream {
+	include /etc/nginx/conf.d/upstreams.conf;
+	include /etc/nginx/streams/*;
+}
diff --git a/tasks/main.yml b/tasks/main.yml
index 2191a57b10df2578cb192b4d1860f25ebacc0bb4..5a05673adf0501068eb74825554d8dcf1011d555 100644
--- a/tasks/main.yml
+++ b/tasks/main.yml
@@ -22,6 +22,7 @@
     pkg:
       - nginx
       - libnginx-mod-http-headers-more-filter
+      - libnginx-mod-stream
       - goaccess
   notify:
   - delete nginx index.nginx-debian.html
@@ -83,6 +84,17 @@
   notify:
   - restart nginx
 
+- name: create and enable nginx streams
+  template:
+    src: stream.conf.j2
+    dest: "/etc/nginx/streams/{{ item.key }}"
+    owner: root
+    group: root
+    mode: 0644
+  with_dict: "{{ {}|combine(nginx.streams, recursive=True) }}"
+  notify:
+  - restart nginx
+
 - name: delete nginx default config
   file: path=/etc/nginx/sites-enabled/default state=absent
 
diff --git a/templates/proxy.conf.j2 b/templates/proxy.conf.j2
index 0103e1ab11d94ebac1b4baa5b60ddb8451c0a8bb..4d3095e2b0addc6d6bcbf9110c76e824887f498c 100644
--- a/templates/proxy.conf.j2
+++ b/templates/proxy.conf.j2
@@ -1,5 +1,5 @@
 {% for ip in nginx.real_ip_from %}
 set_real_ip_from	{{ ip }};
 {% endfor %}
-real_ip_header		X-Forwarded-For;
+real_ip_header		{{ nginx.real_ip_header }};
 real_ip_recursive	on;
diff --git a/templates/stream.conf.j2 b/templates/stream.conf.j2
new file mode 100644
index 0000000000000000000000000000000000000000..f5cb28c136472dd477836eb6a77b8b32dd866212
--- /dev/null
+++ b/templates/stream.conf.j2
@@ -0,0 +1,22 @@
+#jinja2:lstrip_blocks: True
+{% set stream = {}|combine(nginx_streams_defaults, item.value, recursive=True) %}
+{% set stream_name = item.key %}
+
+server {
+
+	{% for i in stream.listen.custom %}
+	listen {{ i }};
+	{% endfor %}
+
+	proxy_pass {{ stream.proxy_pass }};
+	proxy_protocol {{ stream.proxy_protocol }};
+
+	{% for c in stream.custom|default([]) %}
+	{{ c }};
+	{% endfor %}
+
+	{% for include in stream.includes %}
+	include {{ include }};
+	{% endfor %}
+
+}
diff --git a/templates/vhost.conf.j2 b/templates/vhost.conf.j2
index 7cb386aaa11488d87e0f077d5b889908443c4ac6..3d8fbb498874989548b0a4f6b9146aad5088b136 100644
--- a/templates/vhost.conf.j2
+++ b/templates/vhost.conf.j2
@@ -47,6 +47,8 @@ server {
 		{% if location.backend|d(False) %}
 		proxy_pass {{ location.backend }};
 
+		proxy_buffering off;
+
 		# add proxy headers
 		proxy_set_header Host			{{ vhost.host }};
 		proxy_set_header X-Real-IP		$remote_addr;