From 64a40527dff84bb94b2965ff6531d531902531e2 Mon Sep 17 00:00:00 2001 From: Andrew Tomaka Date: Wed, 28 Feb 2018 20:04:31 -0500 Subject: [PATCH] Migrate to using host network In order to use upnp and other discovery services, home assistant needs to live on our real network and not inside a Docker network. This is trivial, but triggered an issue with our nginx proxy, which does not support proxying to containers on the host network. This is resolved by adding ANOTHER proxy to transition from the docker "proxy" network to the host network (simply by pointing at the machines IP address). HTTP Request | Dynamic Nginx proxy | Static Nginx proxy | Home assistant application --- Makefile | 2 + docker-compose.yml | 28 +++++++----- nginx.template.conf | 109 ++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 128 insertions(+), 11 deletions(-) create mode 100644 nginx.template.conf diff --git a/Makefile b/Makefile index 35662b7..4e8b18d 100644 --- a/Makefile +++ b/Makefile @@ -8,6 +8,8 @@ files: ssh 192.168.1.20 "sudo mv /home/atomaka/nginx.tmpl /mnt/data/docker/nginx/templates/" scp -r ./htpasswd 192.168.1.20:/home/atomaka ssh 192.168.1.20 "sudo cp -f /home/atomaka/htpasswd/* /mnt/data/docker/nginx/htpasswd/ && rm -rf /home/atomaka/htpasswd" + scp ./nginx.template.conf 192.168.1.20:/home/atomaka + ssh 192.168.1.20 "sudo mv /home/atomaka/nginx.template.conf /mnt/data/docker/haproxy/" network: ssh 192.168.1.20 "docker network create nginx-proxy" diff --git a/docker-compose.yml b/docker-compose.yml index 19f24e5..4b8aaa9 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -101,8 +101,6 @@ services: VIRTUAL_HOST: plex-requests.atomaka.com LETSENCRYPT_HOST: plex-requests.atomaka.com LETSENCRYPT_EMAIL: me@atomaka.com - ports: - - "9051:3000" networks: - proxy sabnzdb: @@ -168,25 +166,33 @@ services: - duckdns.env volumes: - "/etc/localtime:/etc/localtime:ro" + haproxy: + image: instal/nginx-proxy-pass-dockerize + container_name: haproxy + restart: always + volumes: + - /mnt/data/docker/haproxy/nginx.template.conf:/app/nginx.template.conf:ro + environment: + NGINX_UPSTREAM_SERVER: 192.168.1.20:8123 + NGINX_UPSTREAM_KEEPALIVE: 0 + NGINX_SERVER_PORT: 80 + VIRTUAL_HOST: ha.atomaka.com + LETSENCRYPT_HOST: ha.atomaka.com + LETSENCRYPT_EMAIL: me@atomaka.com + networks: + - proxy ha: image: homeassistant/home-assistant:latest container_name: ha restart: always + network_mode: host ports: - - "9056:8123" - environment: - VIRTUAL_HOST: ha.atomaka.com - LETSENCRYPT_HOST: ha.atomaka.com - LETSENCRYPT_EMAIL: me@atomaka.com + - "8123:8123" volumes: - "/etc/localtime:/etc/localtime:ro" - "/mnt/data/docker/ha/config:/config" devices: - '/dev/zwave:/dev/zwave:rwm' - links: - - mqtt - networks: - - proxy portainer: image: portainer/portainer container_name: portainer diff --git a/nginx.template.conf b/nginx.template.conf new file mode 100644 index 0000000..06a98f3 --- /dev/null +++ b/nginx.template.conf @@ -0,0 +1,109 @@ +# +# A very simple example configuration showing how to launch Nginx as a non-root +# user without sudo access. +# +# Adjust the paths and other settings for your specific circumstances. They are +# currently configured for transient usage - you'd want to pick more permanent +# locations in the filesystem if intending this to run for a while. +# +# Note that as Nginx is not launched as root, it cannot bind to privileged +# ports lower than 1024. +# +# Usage: nginx -c /path/to/this/nginx.conf +# +daemon off; + +# This error log will be written regardless of server scope error_log +# definitions, so we have to set this here in the main scope. +# +# Even doing this, Nginx will still try to create the default error file, and +# log a non-fatal error when it fails. After that things will work, however. +error_log /dev/stdout {{ NGINX_ERROR_LOGLEVEL }}; + +# The pidfile will be written to /var/run unless this is set. +pid /tmp/nginx.pid; + +# user nobody nogroup; + +worker_processes {{ NGINX_WORKER_PROCESSES }}; + +events { + worker_connections {{ NGINX_WORKER_CONNECTIONS }}; + multi_accept {{ NGINX_MULTI_ACCEPT }}; +} + +http { + log_format timed_combined '[$time_local] "$request" $status $body_bytes_sent "$http_referer" ' + '"$http_user_agent" $request_time $upstream_response_time $remote_addr "$http_x_forwarded_for"'; + + {% if NGINX_ACCESS_LOG_TO_STDOUT == "true" %} + access_log /dev/stdout timed_combined; + {% else %} + access_log off; + {% endif %} + + map $http_upgrade $connection_upgrade { + default upgrade; + '' close; + } + + upstream main_upstream { + server {{ NGINX_UPSTREAM_SERVER }}; + {% if NGINX_UPSTREAM_KEEPALIVE|int > 0 %} + keepalive {{ NGINX_UPSTREAM_KEEPALIVE }}; + {% endif %} + } + + server { + listen {{ NGINX_SERVER_PORT }}; + {% if NGINX_HOSTNAME %} + server_name {{ NGINX_EXTRA_SERVER_NAMES }} {{ NGINX_HOSTNAME }}; + {% endif %} + client_max_body_size {{ NGINX_CLIENT_MAX_BODY_SIZE }}; + client_body_timeout {{ NGINX_CLIENT_BODY_TIMEOUT }}; + fastcgi_read_timeout {{ NGINX_FASTCGI_READ_TIMEOUT }}; + proxy_read_timeout {{ NGINX_PROXY_READ_TIMEOUT }}; + + location = {{ NGINX_HEALTHCHECK_PATH }} { + return 200; + } + + location ~ / { + gzip_types {{ NGINX_GZIP_TYPES }}; + proxy_pass http://main_upstream; + proxy_http_version 1.1; + proxy_redirect off; + proxy_set_header Host $host; + proxy_set_header Connection ""; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header Upgrade $http_upgrade; + proxy_set_header Connection $connection_upgrade; + + # https://blog.percy.io/tuning-nginx-behind-google-cloud-platform-http-s-load-balancer-305982ddb340 + keepalive_timeout {{ NGINX_KEEPALIVE_TIMEOUT }}; + keepalive_requests {{ NGINX_KEEPALIVE_REQUESTS }}; + + {% if NGINX_CORS_DOMAINS %} + if ($request_method ~* "(GET|POST|PUT|DELETE)") { + add_header "Access-Control-Allow-Origin" {{ NGINX_CORS_DOMAINS }}; + } + if ($request_method = OPTIONS ) { + add_header "Access-Control-Allow-Origin" {{ NGINX_CORS_DOMAINS }}; + add_header "Access-Control-Allow-Methods" "GET, POST, OPTIONS, DELETE"; + add_header "Access-Control-Allow-Headers" "Authorization, Origin, X-Requested-With, Content-Type, Accept"; + return 200; + } + {% endif %} + } + } + + {% if NGINX_HOST_REWRITE_ENABLED %} + server { + listen {{ NGINX_SERVER_PORT }}; + server_name {{ NGINX_HOST_REWRITE_SERVER_NAMES }}; + return 301 $scheme://{{ NGINX_HOSTNAME }}$request_uri; + } + {% endif %} +} +