4

I use nginx with docker-compose and want docker-compose to pass SERVER_NAME to nginx as an environment variable. I created the following nginx configuration file:

myconf.conf:

# Environment variables are used to dynamically set SERVER_NAME
# from docker-defined environment variable. This logic  is stolen from:
#
# https://docs.apitools.com/blog/2014/07/02/using-environment-variables-in-nginx-conf.html
# https://github.com/wantedly/nginx-image-server/blob/master/files/nginx.conf

env SERVER_NAME;

upstream django {
    server workflows-django:8000;
}

server {
    listen 80;
    perl_set $server_name_from_env 'sub { return $ENV{"SERVER_NAME"}; }';
    server_name $server_name_from_env;
    return 301 https://$server_name$request_uri;
}

server {
    listen 443 ssl;
    perl_set $server_name_from_env 'sub { return $ENV{"SERVER_NAME"}; }';

    server_name $server_name_from_env;
    ssl_certificate /etc/ssl/private/bostongene.crt;
    ssl_certificate_key /etc/ssl/private/bostongene.key;
    charset utf-8;

    client_max_body_size 75M;

    location /media {
        alias /srv/workflows/media;
    }

    location /static {
        alias /srv/workflows/static;
    }

    location / {
        # We can talk to upstream django either via uwsgi or just http proxy

        # uwsgi:
        uwsgi_pass django;
        include /etc/nginx/uwsgi_params;


        # http proxy:
        #proxy_set_header Host $host;
        #proxy_pass http://django
    }
}

For some reason, nginx is cursing about that env directive:

2016/08/26 13:02:39 [emerg] 1#0: "env" directive is not allowed here in /etc/nginx/sites-enabled/default:7

Here's my Dockerfile, where you can see that this config is used as nginx default site:

Dockerfile:

FROM debian:latest

RUN apt-get update && apt-get install -y nginx \
                        ca-certificates \
                        gettext-base

COPY myconf.conf /etc/nginx/sites-available/default
COPY myconf.crt /etc/ssl/private/
COPY myconf.key /etc/ssl/private/

# forward request and error logs to docker log collector
RUN ln -sf /dev/stdout /var/log/nginx/access.log \
    && ln -sf /dev/stderr /var/log/nginx/error.log

EXPOSE 80 443

CMD ["/usr/sbin/nginx", "-g", "daemon off;"]

Why?


ANSWER: let me exlain, what was the problem in detail. myconf.conf file was used as /etc/nginx/sites-available/default, which is NOT the root nginx config. The root nginx config isnginx.conf and it includes /etc/nginx/sites-available/default in http context:

http {

    ...
    ##
    # Virtual Host Configs
    ##

    include /etc/nginx/conf.d/*.conf;
    include /etc/nginx/sites-enabled/*;
}

so my env statement is in fact in http context, which is incorrect - it should be written in root context only.

3
  • possible duplicate of serverfault.com/questions/577370/… Commented Aug 26, 2016 at 14:31
  • 1
    @ivan_pozdeev I've read that post 10 times over - there's no direct answer. Seems like there's nothing wrong with env in my config, it's just nginx messed up so that it doesn't recognize its own directives from the core module: stackoverflow.com/questions/15416957/…. Commented Aug 26, 2016 at 14:44
  • If you're interested specifically in what's wrong with your config rather than what you shall do, here's an answer... Commented Aug 26, 2016 at 15:10

1 Answer 1

8

https://bot.ngx.cc/logs/%23nginx/2015/01-January/%23nginx.01-31.log (googled with "nginx bug "env directive is not allowed here"") has given me the answer.

As testified by the presence of the server directive1, this is not your main configuration file but a chunk to be included, most probably in the http context. While env is only valid in the main context.


1as the link shows, there are a few types of the server directive, none of which are valid in the main context

Sign up to request clarification or add additional context in comments.

1 Comment

Ivan, you're right! I replaced /etc/nginx/sites-available/default with this script, but it is indeed imported by nginx.conf in http context. I should've modified nginx.conf instead of default. Thanks a lot!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.