Nginx reverse proxy is loading different sites when refreshing - docker

I want to host multiple websites in one server with nginx reverse proxy by following this tutorial
https://www.datanovia.com/en/lessons/how-host-multiple-https-websites-on-one-server/
The Nginx proxy and each website are launched separately with Docker.
But every time I reload one of the website, it load the content of other website. For example:
Load websiteone.tk 1st time, loaded website ONE's content.
Refresh websiteone.tk , loaded website TWO's content
Refresh websiteone.tk again, loaded website THREE's content
Load websitetwo.tk 1st time, loaded website TWO content
Refresh websitetwo.tk , loaded website THREE content.
I am a beginner for both nginx and docker. I can't tell if the problem happens in nginx or docker. May anyone please kindly advise? Thank you very much.
The nginx-proxy default.conf is
map $http_x_forwarded_proto $proxy_x_forwarded_proto { default $http_x_forwarded_proto;
'' $scheme;
}
map $http_x_forwarded_port $proxy_x_forwarded_port {
default $http_x_forwarded_port;
'' $server_port;
}
map $http_upgrade $proxy_connection {
default upgrade;
'' close;
}
server_names_hash_bucket_size 128;
map $proxy_x_forwarded_proto $proxy_x_forwarded_ssl {
default off;
https on;
}
gzip_types text/plain text/css application/javascript application/json application/x-javascript text/xml application/xml application/xml+rss t>log_format vhost '$host $remote_addr - $remote_user [$time_local] '
'"$request" $status $body_bytes_sent '
'"$http_referer" "$http_user_agent" '
'"$upstream_addr"';
access_log off;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers 'ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA3> ssl_prefer_server_ciphers off;
error_log /dev/stderr;
# HTTP 1.1 support
proxy_http_version 1.1;
proxy_buffering off;
proxy_set_header Host $http_host;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $proxy_connection;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $proxy_x_forwarded_proto;
proxy_set_header X-Forwarded-Ssl $proxy_x_forwarded_ssl;
proxy_set_header X-Forwarded-Port $proxy_x_forwarded_port;
proxy_set_header X-Original-URI $request_uri;
# Mitigate httpoxy attack (see README for details)
proxy_set_header Proxy "";
server {
server_name _; # This is just an invalid value which will never trigger on a real hostname.
server_tokens off;
listen 80;
access_log /var/log/nginx/access.log vhost;
return 503;
}
server {
server_name _; # This is just an invalid value which will never trigger on a real hostname.
server_tokens off;
listen 443 ssl http2;
access_log /var/log/nginx/access.log vhost;
return 503;
ssl_session_cache shared:SSL:50m;
ssl_session_tickets off;
ssl_certificate /etc/nginx/certs/default.crt;
ssl_certificate_key /etc/nginx/certs/default.key;
}
# websiteone.tk
upstream websiteone.tk {
## Can be connected with "nginx-proxy" network
# websiteonetk_my-app_1
server 192.168.32.8:80;
}
server {
server_name websiteone.tk;
listen 80 ;
access_log /var/log/nginx/access.log vhost;
# Do not HTTPS redirect Let'sEncrypt ACME challenge
location ^~ /.well-known/acme-challenge/ {
auth_basic off;
auth_request off;
allow all;
root /usr/share/nginx/html;
try_files $uri =404;
break;
}
location / {
return 301 https://$host$request_uri;
}
}
server {
server_name websiteone.tk;
listen 443 ssl http2 ;
access_log /var/log/nginx/access.log vhost;
ssl_session_timeout 5m;
ssl_session_cache shared:SSL:50m;
ssl_session_tickets off;
ssl_certificate /etc/nginx/certs/websiteone.tk.crt;
ssl_certificate_key /etc/nginx/certs/websiteone.tk.key;
ssl_dhparam /etc/nginx/certs/websiteone.tk.dhparam.pem;
ssl_stapling on;
ssl_stapling_verify on;
ssl_trusted_certificate /etc/nginx/certs/websiteone.tk.chain.pem;
add_header Strict-Transport-Security "max-age=31536000" always;
include /etc/nginx/vhost.d/default;
location / {
proxy_pass http://websiteone.tk;
}
}
# websitetwo.tk
upstream websitetwo.tk {
## Can be connected with "nginx-proxy" network
# websitetwotk_my-app_1
server 192.168.32.13:80;
}
server {
server_name websitetwo.tk;
listen 80 ;
access_log /var/log/nginx/access.log vhost;
# Do not HTTPS redirect Let'sEncrypt ACME challenge
location ^~ /.well-known/acme-challenge/ {
auth_basic off;
auth_request off;
allow all;
root /usr/share/nginx/html;
try_files $uri =404;
break;
}
location / {
return 301 https://$host$request_uri;
}
}
server {
server_name websitetwo.tk;
listen 443 ssl http2 ;
access_log /var/log/nginx/access.log vhost;
ssl_session_timeout 5m;
ssl_session_cache shared:SSL:50m;
ssl_session_tickets off;
ssl_certificate /etc/nginx/certs/websitetwo.tk.crt;
ssl_certificate_key /etc/nginx/certs/websitetwo.tk.key;
ssl_dhparam /etc/nginx/certs/websitetwo.tk.dhparam.pem;
ssl_stapling on;
ssl_stapling_verify on;
ssl_trusted_certificate /etc/nginx/certs/websitetwo.tk.chain.pem;
add_header Strict-Transport-Security "max-age=31536000" always;
include /etc/nginx/vhost.d/default;
location / {
proxy_pass http://websitetwo.tk;
}
}
# websitethree.tk
upstream websitethree.tk {
## Can be connected with "nginx-proxy" network
# websitethreetk_my-app_1
server 192.168.32.3:80;
}
server {
server_name websitethree.tk;
listen 80 ;
access_log /var/log/nginx/access.log vhost;
# Do not HTTPS redirect Let'sEncrypt ACME challenge
location ^~ /.well-known/acme-challenge/ {
auth_basic off;
auth_request off;
allow all;
root /usr/share/nginx/html;
try_files $uri =404;
break;
}
location / {
return 301 https://$host$request_uri;
}
}
server {
server_name websitethree.tk;
listen 443 ssl http2 ;
access_log /var/log/nginx/access.log vhost;
ssl_session_timeout 5m;
ssl_session_cache shared:SSL:50m;
ssl_session_tickets off;
ssl_certificate /etc/nginx/certs/websitethree.tk.crt;
ssl_certificate_key /etc/nginx/certs/websitethree.tk.key;
ssl_dhparam /etc/nginx/certs/websitethree.tk.dhparam.pem;
ssl_stapling on;
ssl_stapling_verify on;
ssl_trusted_certificate /etc/nginx/certs/websitethree.tk.chain.pem;
add_header Strict-Transport-Security "max-age=31536000" always;
include /etc/nginx/vhost.d/default;
location / {
proxy_pass http://websitethree.tk;
}
}
The docker-compose for the nginx proxy is
version: '3.6'
services:
nginx:
image: nginx
labels:
com.github.jrcs.letsencrypt_nginx_proxy_companion.nginx_proxy: "true"
container_name: nginx
restart: unless-stopped
ports:
- "80:80"
- "443:443"
volumes:
- ./conf.d:/etc/nginx/conf.d
- ./vhost.d:/etc/nginx/vhost.d
- ./html:/usr/share/nginx/html
- ./certs:/etc/nginx/certs:ro
nginx-gen:
image: jwilder/docker-gen
command: -notify-sighup nginx -watch -wait 5s:30s /etc/docker-gen/templates/nginx.tmpl /etc/nginx/conf.d/default.conf
container_name: nginx-gen
restart: unless-stopped
volumes:
- ./conf.d:/etc/nginx/conf.d
- ./vhost.d:/etc/nginx/vhost.d
- ./html:/usr/share/nginx/html
- ./certs:/etc/nginx/certs:ro
- /var/run/docker.sock:/tmp/docker.sock:ro
- ./nginx.tmpl:/etc/docker-gen/templates/nginx.tmpl:ro
nginx-letsencrypt:
image: jrcs/letsencrypt-nginx-proxy-companion
container_name: nginx-letsencrypt
restart: unless-stopped
volumes:
- ./conf.d:/etc/nginx/conf.d
- ./vhost.d:/etc/nginx/vhost.d
- ./html:/usr/share/nginx/html
- ./certs:/etc/nginx/certs:rw
- /var/run/docker.sock:/var/run/docker.sock:ro
environment:
NGINX_DOCKER_GEN_CONTAINER: "nginx-gen"
NGINX_PROXY_CONTAINER: "nginx"
networks:
default:
external:
name: nginx-proxy
The nginx default.conf for one of the website is
server {
root /application2;
index index.php;
location ~ \.php$ {
fastcgi_pass php-fpm:9000;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_param PHP_VALUE "error_log=/var/log/nginx/application_php_errors.log";
fastcgi_buffers 16 16k;
fastcgi_buffer_size 32k;
include fastcgi_params;
}
}
The docker-compose/yml for one of the website is below.
Websiteone working directory is /application1.
Websitetwo working directory is /application2. etc
version: '3.1'
services:
my-app:
image: 'nginx:alpine'
volumes:
- '.:/application2'
- './phpdocker/nginx/nginx.conf:/etc/nginx/conf.d/default.conf'
restart: always
environment:
- VIRTUAL_HOST=websitetwo.tk
- VIRTUAL_PORT=80
- LETSENCRYPT_HOST=websitetwo.tk
expose:
- 80
mailhog:
image: 'mailhog/mailhog:latest'
ports:
- '21001:8025'
php-fpm:
build: phpdocker/php-fpm
working_dir: /application2
volumes:
- '.:/application2'
- './phpdocker/php-fpm/php-ini-overrides.ini:/etc/php/8.1/fpm/conf.d/99-overrides.ini'
networks:
default:
external:
name: nginx-proxy

Related

Coder running on Laravel Forge can not connect to Websocket endpoint

I've configured Coder and followed this instructions to set it up via Docker Compose.
In order to be able to use a public domain, I've configured a reverse proxy with nginx. Everything works except for the websocket connection which is used to get logs, status updates etc etc.
The error is: wss://workspaces.mydomain.io/api/private/workspaces/623ae5f6-0e4817996a28f4e5e592cb87/watch-stats' failed
The server is managed via Laravel Forge.
Here is my docker-compose.yml:
version: "3.5"
services:
coder:
image: docker.io/codercom/coder:1.28.2
container_name: coderd
restart: unless-stopped
ports:
- 7080:7080/tcp
volumes:
- /var/run/docker.sock:/var/run/docker.sock
- ${HOME}/.coder:/var/run/coder
environment:
DEVURL_HOST: "*.workspaces.mydomain.io"
And here my nginx configuration:
server {
listen 80;
listen [::]:80;
server_name .workspaces.mydomain.io;
server_tokens off;
root /home/forge/workspaces.mydomain.io/coder/public;
# FORGE SSL (DO NOT REMOVE!)
# ssl_certificate;
# ssl_certificate_key;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384;
ssl_prefer_server_ciphers off;
ssl_dhparam /etc/nginx/dhparams.pem;
add_header X-Frame-Options "SAMEORIGIN";
add_header X-XSS-Protection "1; mode=block";
add_header X-Content-Type-Options "nosniff";
index index.html index.htm index.php;
charset utf-8;
# FORGE CONFIG (DO NOT REMOVE!)
include forge-conf/workspaces.mydomain.io/server/*;
location / {
proxy_pass http://127.0.0.1:7080;
}
location = /favicon.ico { access_log off; log_not_found off; }
location = /robots.txt { access_log off; log_not_found off; }
access_log off;
error_log /var/log/nginx/workspaces.mydomain.io-error.log error;
error_page 404 /index.php;
location ~ \.php$ {
fastcgi_split_path_info ^(.+\.php)(/.+)$;
fastcgi_pass unix:/var/run/php/php8.1-fpm.sock;
fastcgi_index index.php;
include fastcgi_params;
}
location ~ /\.(?!well-known).* {
deny all;
}
}

Nginx Behind Traefik Docker "Primary script unknown"

I have this app running on Docker behind a traefik container.
Every time I access a URL from the API an expected response is returned, then an error from Nginx, than an expected, and next time an Nginx error... this loop is forever
This is my URL: http://api.preview-tefm.rtdigital.com.br/v1/me (expected: 401 response)
The error after a expected resposnse: 2021/11/05 14:22:16 [error] 9#9: *1 FastCGI sent in stderr: "Primary script unknown" while reading response header from upstream, client: 172.1.0.2, server: api.preview-tefm.rtdigital.com.br, request: "GET /v1/me HTTP/1.1", upstream: "fastcgi://172.1.0.3:9000", host: "api.preview-tefm.rtdigital.com.br"
Nginx Conf file:
worker_processes 4;
events { worker_connections 1024; }
http {
proxy_cache_path /var/cache/nginx levels=1:2 keys_zone=one:8m max_size=3000m inactive=600m;
proxy_temp_path /var/tmp;
include mime.types;
default_type application/octet-stream;
sendfile on;
keepalive_timeout 65;
gzip on;
gzip_comp_level 6;
gzip_vary on;
gzip_min_length 1000;
gzip_proxied any;
gzip_types text/plain text/css application/json application/x-javascript text/xml application/xml application/xml+rss text/javascript;
gzip_buffers 16 8k;
server {
listen 80;
server_name api.preview-tefm.rtdigital.com.br;
error_log /var/log/nginx/app-error.log debug;
access_log /var/log/nginx/app-access.log;
charset utf-8;
root /usr/share/nginx/html/webapp/public;
location /css/ {
access_log off;
expires 1d;
}
location /img/ {
access_log off;
expires 1d;
}
location /js/ {
access_log off;
expires 1d;
}
location ~ \.php$ {
try_files $uri =404;
fastcgi_split_path_info ^(.+\.php)(/.+)$;
fastcgi_pass app:9000;
fastcgi_index index.php;
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_param PATH_INFO $fastcgi_path_info;
# Hide PHP headers
fastcgi_hide_header X-Powered-By;
fastcgi_hide_header X-CF-Powered-By;
}
location / {
proxy_pass http://app:9000;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade';
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-NginX-Proxy true;
proxy_cache_bypass $http_upgrade;
try_files $uri /index.php?$query_string;
gzip_static on;
}
}
server {
listen 80;
server_name admin.preview-tefm.rtdigital.com.br;
error_log /var/log/nginx/admin-error.log;
access_log /var/log/nginx/admin-access.log;
root /usr/share/nginx/html/admin;
charset utf-8;
location / {
try_files $uri /index.html?$query_string;
gzip_static on;
}
}
}
docker-compose conf:
version: "3.7"
services:
app:
container_name: "tefm-app"
build: "${DOCKER_PHP_BUILD}"
restart: "no"
expose:
- "9000"
volumes:
- "./webapp:/usr/share/nginx/html/webapp"
networks:
- traefik-network
nginx:
container_name: "tef-nginx"
build: "${DOCKER_NGINX_BUILD}"
restart: "no"
tty: true
labels:
- "traefik.enable=true"
- "traefik.http.routers.tefm-nginx.entrypoints=web"
- "traefik.http.routers.tefm-nginx.rule=Host(`admin.preview-tefm.rtdigital.com.br`) || Host(`api.preview-tefm.rtdigital.com.br`)"
volumes:
- "./admin/build:/usr/share/nginx/html/admin"
- "./webapp:/usr/share/nginx/html/webapp"
depends_on:
- app
networks:
- traefik-network
networks:
traefik-network:
external: true
Nginx Dockerfile:
FROM nginx:alpine
COPY ./nginx.conf /etc/nginx/nginx.conf
EXPOSE 80 443
ENTRYPOINT ["nginx"]
CMD ["-g", "daemon off;"]

Enable gzip with docker and bitnami/nginx

I deployed a website with docker and bitnami/nginx as image: https://www.10studio.tech/demo. After deployment, I realized that files like analyzejs.js was not gzipped:
Here is docker-compose.yml:
version: "3"
services:
docusaurus:
image: bitnami/nginx:1.16
restart: always
volumes:
- ./build:/app
- ./certs:/certs:ro
- ./my_server_block.conf:/opt/bitnami/nginx/conf/server_blocks/my_server_block.conf:ro
ports:
- "3001:3001"
- "3002:3002"
Here is my_server_block.conf:
server {
listen 3002;
absolute_redirect off;
root /app;
location = / {
rewrite ^(.*)$ https://$http_host/docs/introduction redirect;
}
location / {
try_files $uri $uri/ =404;
}
}
server {
listen 3001 ssl;
ssl_certificate /certs/server.crt;
ssl_certificate_key /certs/server.key;
ssl_session_cache shared:SSL:1m;
ssl_session_timeout 5m;
ssl_ciphers HIGH:!aNULL:!MD5;
ssl_prefer_server_ciphers on;
location / {
proxy_pass http://localhost:3002;
proxy_redirect off;
proxy_set_header Host $host:$server_port;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Ssl on;
}
}
Here is /opt/bitnami/nginx/conf/nginx.conf, where gzip seems to be enabled:
I have no name!#8317023de7ec:/app$ cat /opt/bitnami/nginx/conf/nginx.conf
# Based on https://www.nginx.com/resources/wiki/start/topics/examples/full/#nginx-conf
# user www www; ## Default: nobody
worker_processes auto;
error_log "/opt/bitnami/nginx/logs/error.log";
pid "/opt/bitnami/nginx/tmp/nginx.pid";
events {
worker_connections 1024;
}
http {
include mime.types;
default_type application/octet-stream;
log_format main '$remote_addr - $remote_user [$time_local] '
'"$request" $status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
access_log "/opt/bitnami/nginx/logs/access.log";
add_header X-Frame-Options SAMEORIGIN;
client_body_temp_path "/opt/bitnami/nginx/tmp/client_body" 1 2;
proxy_temp_path "/opt/bitnami/nginx/tmp/proxy" 1 2;
fastcgi_temp_path "/opt/bitnami/nginx/tmp/fastcgi" 1 2;
scgi_temp_path "/opt/bitnami/nginx/tmp/scgi" 1 2;
uwsgi_temp_path "/opt/bitnami/nginx/tmp/uwsgi" 1 2;
sendfile on;
tcp_nopush on;
tcp_nodelay off;
gzip on;
gzip_http_version 1.0;
gzip_comp_level 2;
gzip_proxied any;
gzip_types text/plain text/css application/x-javascript text/xml application/xml application/xml+rss text/javascript;
keepalive_timeout 65;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
include "/opt/bitnami/nginx/conf/server_blocks/*.conf";
# HTTP Server
server {
# port to listen on. Can also be set to an IP:PORT
listen 8080;
location /status {
stub_status on;
access_log off;
allow 127.0.0.1;
deny all;
}
}
}
Does anyone know what's wrong here and how I could enable gzip?
I also just stumbled over the same problem. It seems like the docker image already has gzip enabled. I also have an nginx deployed for the whole server which acts as reverse proxy for the different docker container in the server. What worked for me is to also enabled gzip in the global nginx configuration /etc/nginx/nginx.conf.
Don't know if you also have a wrapping nginx. Hope this helps.

Nginx refuses connections to flask app, flask app without nginx works fine

I have 2 docker containers deployed using docker compose.
One is nginx and the other is my flask application. I am only using nginx as a static server for let's encrypt certification.
If I deploy my flask app without nginx, I can successfully curl / ping my server. However, the moment nginx is introduced, I am not able to connect.
What I want to do is at least access my server via numeric external ip e.g. xx.xx.xx.xx and then my domain which points to the same ip. (My domain is actually a subdomain e.g. api.domain.com)
My docker compose is:
services:
nginx:
build:
context: ./nginx
dockerfile: Dockerfile
args:
DOMAIN: ${DOMAIN}
FLASK: application
ports:
- 80:80
- 443:443
volumes:
- /etc/letsencrypt:/etc/letsencrypt
depends_on:
- application
application:
build:
context: ./flask_app
dockerfile: Dockerfile
ports:
- 5000:5000
nginx.conf
user nginx;
worker_processes auto;
worker_rlimit_nofile 8192;
error_log /var/log/nginx/error.log warn;
pid /var/run/nginx.pid;
events {
worker_connections 1024;
}
http {
charset utf-8;
sendfile on;
tcp_nopush on;
tcp_nodelay on;
server_tokens off;
log_not_found off;
types_hash_max_size 2048;
client_max_body_size 16M;
include mime.types;
default_type application/octet-stream;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ecdh_curve X25519:sect571r1:secp521r1:secp384r1;
ssl_session_timeout 1d;
ssl_session_cache shared:SSL:50m;
ssl_session_tickets off;
ssl_ciphers 'TLS13+AESGCM+AES128:TLS13+AESGCM+AES256:TLS13+CHACHA20:EECDH+AESGCM:EECDH+CHACHA20';
ssl_stapling on;
ssl_stapling_verify on;
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
access_log /var/log/nginx/access.log main;
include conf.d/*.conf;
}
flask_app.conf
server {
listen 80;
listen [::]:80;
server_name www.${DOMAIN} ${DOMAIN};
location ^~ /.well-known/acme-challenge/ {
root /var/www/_letsencrypt;
}
location / {
return 301 https://${DOMAIN}${DOLLAR}request_uri;
}
}
server {
listen 443 ssl http2 default_server;
listen [::]:443 ssl http2 default_server;
server_name www.${DOMAIN} ${DOMAIN};
ssl_certificate /etc/letsencrypt/live/${DOMAIN}/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/${DOMAIN}/privkey.pem;
ssl_trusted_certificate /etc/letsencrypt/live/${DOMAIN}/chain.pem;
add_header X-Frame-Options "SAMEORIGIN" always;
add_header X-XSS-Protection "1; mode=block" always;
add_header X-Content-Type-Options "nosniff" always;
add_header Referrer-Policy "no-referrer-when-downgrade" always;
# You might want to change the CSP policy to fit your needs - see https://content-security-policy.com/
add_header Content-Security-Policy "default-src 'self'; script-src 'self'; connect-src 'self'; img-src 'self'; style-src 'self';";
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" always;
add_header Allow "GET, POST, HEAD" always;
access_log /var/log/nginx/${DOMAIN}.access.log;
error_log /var/log/nginx/${DOMAIN}.error.log warn;
location / {
proxy_http_version 1.1;
proxy_cache_bypass ${DOLLAR}http_upgrade;
proxy_hide_header X-Powered-By;
proxy_hide_header Server;
proxy_hide_header X-AspNetMvc-Version;
proxy_hide_header X-AspNet-Version;
proxy_set_header Proxy "";
proxy_set_header Upgrade ${DOLLAR}http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Host ${DOLLAR}host;
proxy_set_header X-Real-IP ${DOLLAR}remote_addr;
proxy_set_header X-Forwarded-For ${DOLLAR}proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto ${DOLLAR}scheme;
proxy_set_header X-Forwarded-Host ${DOLLAR}host;
proxy_set_header X-Forwarded-Port ${DOLLAR}server_port;
proxy_pass http://application:5000;
}
location ~* \.(?:css|cur|js|jpe?g|gif|htc|ico|png|html|xml|otf|ttf|eot|woff|woff2|svg)${DOLLAR} {
expires 7d;
add_header Pragma public;
add_header Cache-Control public;
proxy_pass http://application:5000;
}
if ( ${DOLLAR}request_method !~ ^(GET|POST|HEAD)${DOLLAR} ) {
return 405;
}
if (${DOLLAR}http_user_agent ~* LWP::Simple|BBBike|wget) {
return 403;
}
location ~ /\.(?!well-known) {
deny all;
}
gzip on;
gzip_vary on;
gzip_proxied any;
gzip_comp_level 6;
gzip_types text/plain text/css text/xml application/json application/javascript application/rss+xml application/atom+xml image/svg+xml;
}
I'm not sure why your nginx config contains ${DOLLAR} in multiple places. I don't think this is valid syntax, and can't find any documentation relating to this. Lines like:
proxy_set_header Host ${DOLLAR}host;
Should actually be:
proxy_set_header Host $host;
As for using ${DOMAIN} in the nginx conf, I would avoid this and opt for a more simple configuration. Just specify the domain in the nginx config file:
server_name www.example.com example.com;
I'd familiarise yourself with the official nginx image docs under "Complex configuration" it shows you how to copy a working config out of a running container, then modify this to your needs.
Once you have this working, if you really want to specify the domain in your docker-compose file, and treat your nginx config as a template which is modified at container-start time, you could proceed to read the section "Using environment variables in nginx configuration" which shows a workaround to use envsubst to acehive this. This is probably not required for single site deployments however.

Nginx reverse SSL proxy docker-compose

I'm trying to set up nginx as a reverse proxy on my Ubuntu 18.04 server.
I've set up what I thought was correct below, but hitting http://web.service.com lands me on the default nginx welcome screen (whereas it should redirect to https:// and going to https://web.service.com I end up with a 404 error screen.
I've got the following docker-compose.yml configuration:
version: "3"
services:
web_service:
image: "test/webservice"
container_name: "webservice"
hostname: "webservice"
mysql:
image: "mysql:5.7"
container_name: "mysql"
hostname: "mysql"
nginx:
build:
context: .
dockerfile: "Dockerfile"
image: "nginx"
container_name: "nginx"
hostname: "nginx"
ports:
- "80:80"
- "443:443"
volumes:
- "/var/nginx/data/certs:/etc/nginx/certs"
Note: web_service hosts a web page on port 8080
And I've got my default nginx.conf
user nginx;
worker_processes 1;
error_log /var/log/nginx/error.log warn;
pid /var/run/nginx.pid;
events {
worker_connections 1024;
}
http {
include /etc/nginx/mime.types;
default_type application/octet-stream;
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
access_log /var/log/nginx/access.log main;
sendfile on;
#tcp_nopush on;
keepalive_timeout 65;
#gzip on;
include /etc/nginx/conf.d/*.conf;
}
And my custom web_service.conf which is build into the new nginx image.
server {
listen 80;
return 301 https://$host$request_uri;
}
server {
listen 443 ssl default_server;
server_name www.web.server.com web.server.com;
ssl_session_cache builtin:1000 shared:SSL:10m;
ssl_protocols SSLv3 TLSv1;
ssl_ciphers ALL:!aNULL:!ADH:!eNULL:!LOW:!EXP:RC4+RSA:+HIGH:+MEDIUM;
access_log /var/log/nginx/access.log;
error_log /var/log/nginx/error.log info;
keepalive_timeout 75 75;
ssl_certificate /etc/nginx/certs/web_server.com.crt;
ssl_certificate_key /etc/nginx/certs/web_server.com.key;
ssl_session_timeout 5m;
add_header Strict-Transport-Security "max-age=7200";
location / {
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_pass http://webservice:8080;
proxy_read_timeout 90;
proxy_redirect http://webservice:8080 https://web.service.com;
}
}
Previously I just the web_service and mysql in the compose file and I exposed port 80:8080 for web_server.
Any thoughts as to the issue?
Managed to solve my issue using the following config:
upstream docker-webapp {
server webapp:8080;
}
server {
listen 80;
server_name _;
return 301 https://$host$request_uri;
}
server {
listen 443 ssl default_server;
listen [::]:443 ssl default_server;
server_name www.example.com example.com;
## Access and error logs.
access_log /var/log/nginx/access.log;
error_log /var/log/nginx/error.log info;
## Keep alive timeout set to a greater value for SSL/TLS.
keepalive_timeout 75s;
## Server certificate and key.
ssl_certificate /etc/ssl/certs/certificate.crt;
ssl_certificate_key /etc/ssl/certs/certificate.key;
ssl_dhparam /etc/ssl/certs/dhparam.pem;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_prefer_server_ciphers on;
ssl_ciphers EECDH+AESGCM:EDH+AESGCM;
ssl_ecdh_curve secp384r1;
ssl_session_timeout 10m;
ssl_session_cache shared:SSL:10m;
ssl_session_tickets off;
ssl_stapling on;
ssl_stapling_verify on;
add_header Strict-Transport-Security "max-age=63072000; includeSubDomains; preload";
add_header X-Frame-Options DENY;
add_header X-Content-Type-Options nosniff;
add_header X-XSS-Protection "1; mode=block";
location / {
proxy_pass http://docker-webapp;
proxy_redirect off;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Host $server_name;
}
}
as well as info found here: https://cipherli.st/
As a side note, the webapp I deployed needed to healthcheck itself, so I needed to install the public certificate into the webapp container's keystore. On top of that it also only supported up to TLSv1.2 hence why I added TLSv1.2 to the ssl_protocols line.
This doesn't directly answer your question, but you might give this Nginx container a try; it really makes automatically handling SSL a walk in the park.
https://hub.docker.com/r/linuxserver/letsencrypt
Due to in your image you're lacking of config of certificate, so you need to add ca-certificate to docker system certificates to use https (you can check it on the internet).
Another thing about security risk in your config file is SSLv3. You should remove it to avoid POODLE attack .

Resources