harryg
harryg

Reputation: 24077

Nginx on kubernetes docker doing infinite redirect when generating conf

I have an nginx pod deployed in my kubernetes cluster to serve static files. In order to set a specific header in different environments I have followed the instructions in the official nginx docker image docs which uses envsubst to generate the config file from a template before running nginx.

This is my nginx template (nginx.conf.template):

events {
  worker_connections 1024;
}

http {

  include mime.types;
  default_type application/octet-stream;
  sendfile on;

  access_log /var/log/nginx/access.log;
  error_log /var/log/nginx/error.log;

  gzip on;

  server {
    listen 443 ssl;

    ssl_certificate /etc/nginx/ssl/nginx.crt;
    ssl_certificate_key /etc/nginx/ssl/nginx.key;

    root /usr/share/nginx/html;

    #charset koi8-r;
    #access_log  /var/log/nginx/log/host.access.log  main;

    location ~ \.css {

      add_header Content-Type text/css;
    }

    location ~ \.js {

      add_header Content-Type application/x-javascript;
    }

    location / {
      add_header x-myapp-env $MYAPP_ENV;
      index index.html index.htm;
      try_files $uri $uri/ /index.html;
    }

    #error_page  404              /404.html;

    # redirect server error pages to the static page /50x.html
    #
    error_page 500 502 503 504 /50x.html;
    location = /50x.html {

      root /usr/share/nginx/html;
    }
  }

  server {
    listen      80;
    server_name _;
    return 301 https://$host$request_uri;
  }
}

I use the default command override feature of Kubernetes to initially generate the nginx conf file before starting nginx. This is the relevant part of the config:

 command: ["/bin/sh"]
 args: ["-c", "envsubst < /etc/nginx/nginx.conf.template > /etc/nginx/nginx.conf && nginx -g 'daemon off;'" ]

Kubernetes successfully deploys the pod however when I make a request I get a ERR_TOO_MANY_REDIRECTS error in my browser.

Strangely, when I deploy the container without running the command override using an nginx.conf almost identical to the above (but without the add_header directive) it works fine.

(All SSL certs and files to be served are happily copied onto the container at build time so there should be no issue there)

Any help appreciated.

Upvotes: 2

Views: 1034

Answers (1)

Janos Lenart
Janos Lenart

Reputation: 27080

I am pretty sure envsubst is biting you by making try_files $uri $uri/ /index.html; into try_files / /index.html; and return 301 https://$host$request_uri; into return 301 https://;. This results in a loop of redirections.

I suggest you run envsubst '$MYAPP_ENV' <template >nginx.conf instead. That will only replace that single variable and not the unintended ones. (Note the escaping around the variable in the sample command!) If later on you need to add variables you can specify them all like envsubsts '$VAR1$VAR2$VAR3'.

If you want to replace all environment variables you can use this snippet:

envsubst `declare -x | sed 's/^declare -x \([^=]*\)=.*/$\1/' | tr -d '\n'` <template >nginx.conf

Also, while it's not asked in the question you can save yourself some trouble by using ... && exec nginx -g 'daemon off;'. The exec will replace the running shell (pid 1) with the nginx process instead of forking it. This also means that signals will be received by nginx, etc.

Upvotes: 3

Related Questions