KeijiYONEDA
@KeijiYONEDA (Keiji YONEDA)

Are you sure you want to delete the question?

If your question is resolved, you may close it.

Leaving a resolved question undeleted may help others!

We hope you find it useful!

OpenRestyにて、nginx.confでincludeしているバーチャルホストの設定からLuaで環境変数を参照したかった

OpenRestyにて、nginx.confでincludeしているバーチャルホストの設定からLuaで環境変数を参照したかった

現在、PHPで動作するアプリケーションを、OpenRestyコンテナとPHP−FPMコンテナを利用して構築しています。
稼働環境として、運用環境はAWS ECS、開発環境はdocker-composeを利用しています。
Docker ComposeとECSでは、Nginxの設定が以下の箇所が異なるため、環境変数で差分を埋められないかと考えました。

  • proxy_pass
    • サイトマップファイル等、ドメインが同一である必要があるファイルを、CDNに問い合わせて返却させたい
  • fastcgi_pass
    • ECSでは localhost、docker-composeでは php-fpm としたい

Nginxの設定ファイルから環境変数を参照する方法として、以下の方法を見つけました。

  1. テンプレートファイルを作成し、envsubst で設定ファイルを生成
  2. set_by_luaで環境変数を取得

1の方法を採用したくなかった理由は以下です。

  • ビルド時にテンプレートから設定を生成するする方法では、ビルド環境に環境変数を指定する必要があり複雑さに繋がると考えた
  • コンテナ起動時にテンプレートから設定を生成する方法では、ENTRYPOINT上書きが少し邪道に思えた

そこで、set_by_luaで何とかしたかったのですが、以下の点でつまづきました。

  • includeしているバーチャルホスト設定では、envディレクトリを利用できないため、luaからeturn os.getenvしてもnilが返却される
    • nginx.confでenvディレクティブを指定しても結果は同様
  • includeしているバーチャルホスト設定の内容を、nginx.confの http に入れれば解決するかと考えたが、どうもPHP-FPMに実行を問い合わせできていない
    • 静的ファイルは返却できたのだが。。。

もう諦めて envsubst を利用しようかとは思っているのですが、調査にそれなりに時間をかけた事もあり、不可能か可能かだけでも知りたい思いです。

設定ファイル

以下、一部変更していますが、設定ファイルです。
一旦proxy_pass部分のみ、このようにしたいという形で置いています。

/etc/nginx/nginx.conf
user nginx;
pid /var/run/nginx.pid;
worker_processes auto;
worker_rlimit_nofile 100000;

error_log  /usr/local/openresty/nginx/logs/error.log;
access_log /usr/local/openresty/nginx/logs/access.log;

include /usr/share/nginx/modules/*.conf;

events {
    worker_connections 2048;
    multi_accept on;
    accept_mutex_delay 100ms;
}

env SITEMAP_URL; # ここでしか指定できないけどinclude先では効いてないっぽい

http {
    include /etc/nginx/mime.types;

    server_tokens off;
    charset UTF-8;
    sendfile on;
    default_type application/octet-stream;

    tcp_nopush on;
    tcp_nodelay on;

    keepalive_timeout 50;
    types_hash_max_size 4096;

    gzip on;
    gzip_http_version 1.0;
    gzip_disable "msie6";
    gzip_proxied any;
    gzip_min_length 1024;
    gzip_comp_level 6;
    gzip_types text/plain text/css application/json application/x-javascript text/xml application/xml application/xml+rss text/javascript application/javascript;

    open_file_cache max=1000 inactive=20s;
    open_file_cache_valid 30s;
    open_file_cache_min_uses 2;
    open_file_cache_errors on;

    log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
                      '$status $body_bytes_sent "$http_referer" '
                      '"$http_user_agent" "$http_x_forwarded_for"';

    include /etc/nginx/conf.d/*.conf;

}

/etc/nginx/conf.d/default.conf
server {
    listen       80 default_server;
    server_name localhost
    index index.php index.html;
    root /src/app/webroot;
    client_max_body_size 100M;

    location ~ \.(html|css|js|jpe?g|png|gif|svg|mpg|flv|swf|woff|eot|ttf)$ {
        expires 1m;
        break;
    }
    ### サイトマップはCDN上の内容を返却 <- ここがうまくいかない
    location /sitemap.xml {
        resolver 8.8.8.8;
        set_by_lua $SITEMAP_URL 'return os.getenv("SITEMAP_URL")';
        proxy_pass $SITEMAP_URL;
    }
    location / {
        try_files $uri /index.php?$query_string;
    }
    location ~ \.php$ {
        fastcgi_split_path_info ^(.+\.php)(/.+)$;
        fastcgi_pass php-fpm:9000;
        fastcgi_index index.php;
        include fastcgi_params;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        fastcgi_param PATH_INFO $fastcgi_path_info;
    }
}

結果

ダメポ...
結局、設定ファイルをテンプレート化してenvsubstすることにしました。
正直すこし強引な印象もあるので、ローカルとECSで同じ設定ファイルを利用する方法、もうすこし方法をしらべてみたいところです

021/04/23 13:29:08 [error] 7#7: *1 invalid URL prefix in "", client: 172.xx.0.1, server: localhost, request: "GET /sitemap.xml HTTP/1.1", host: "localhost:80"
0

1Answer

http://nginx.org/en/docs/ngx_core_module.html#env

According to nginx doc, one can only put the env directive in main context, so what you have done is correct.

set_by_lua $SITEMAP_URL 'return os.getenv("SITEMAP_URL")';
proxy_pass $SITEMAP_URL;

And after testing by myself, this is also correct.

*1 invalid URL prefix in "" shows that set_by_lua get the SITEMAP_URL env var, but the value of SITEMAP_URL is "" (empty string).

So the issue may be that you set the env variable SITEMAP_URL incorrectly. Or the user that run nginx work (in your case is user nginx) can not get env variable SITEMAP_URL.

0Like

Your answer might help someone💌