How can I reference a variable set by lua in nginx? - nginx

I am using nginx lua docker image firesh/nginx-lua:alpine-3.4. And i tried to use environment variable in nginx.config file. Below is the configuration in /etc/nginx/nginx.conf.
user nginx;
env ES_USERNAME;
env ES_PWD;
worker_processes 1;
events {
worker_connections 10240;
}
http {
server {
listen 8080;
server_name localhost;
set_by_lua $es_username os.getenv("ES_USERNAME");
set_by_lua $es_pwd os.getenv("ES_PWD");
location /health {
proxy_pass http://$es_username:$es_pwd#elk-es-http:9200/_cluster/health;
}
...
After launching the container, I see this error in the log:
2021/11/18 01:07:14 [error] 6#6: *6 failed to load inlined Lua code: set_by_lua:1: unexpected symbol near '"http://"', client: 10.0.4.122, server: localhost, request: "GET /health HTTP/1.1", host: "10.0.2.170:8080"
The problem is that the url after proxy_pass is not reading the variable from lua. It treats the ${es_username} as a string rather than read its value. What is the correct way to use that?

That sounds strange. I rather expect both $es_username and $es_pwd variables will have an empty value. set_by_lua expects a function that should return a value, and your returns nothing. The correct usage is
set_by_lua $es_username 'return os.getenv("ES_USERNAME")';
set_by_lua $es_pwd 'return os.getenv("ES_PWD")';

Related

Return 200 by Nginx without serving a file

I wrote this /etc/nginx/conf.d/apply.conf and started nginx.
server {
location = /hoge {
return 200;
}
}
but the curl command fails.
curl localhost:80/hoge
It says
<html>
<head><title>404 Not Found</title></head>
<body bgcolor="white">
<center><h1>404 Not Found</h1></center>
<hr><center>nginx/1.13.9</center>
</body>
</html>
and the logs are
open() "/usr/share/nginx/html/hoge" failed (2: No such file or directory), client: 127.0.0.1, server: localhost, request: "GET /hoge HTTP/1.1", host: "localhost"
I want to just return the status code without response body or with response body blank.
I changed to this but still not working.
location /hoge {
return 200 'Wow';
add_header Content-Type text/plain;
}
also tried this.
location /hoge {
return 200 'Wow';
default_type text/plain;
}
It is hard to say without context(how your entire nginx config file looks like), because of how nginx processes a request
A config file like the following, should work just fine for what you are looking for:
server {
listen 80;
location /hoge {
return 200;
}
}
However, if your config file has other location blocks(especially if they are regex based) then you may not get the expected solution.
Take an example of this config file:
server {
listen 80;
location /hoge {
return 200;
}
location ~* /ho {
return 418;
}
}
Sending a request to curl localhost:80/hoge would return a http status code 418 instead of 200. This is because the regex location matched before the exact location.
So, the long answer is; it is hard to tell without the context of the whole nginx conf file that you are using. But understanding how nginx processes a request will get you to the answer.

strange behaviour when using captured naming group to define alias

I have a very simple virtualhost configuration:
server {
listen 80 default_server;
server_name datavis.dev.localserver.fr;
root /var/www;
location ~ ^\/datavis\/(?<datarep>[\w]+) {
alias /var/www/data-${datarep}-front;
autoindex on;
}
}
I have 2 index.html in 2 dirs : /var/www/data-test1-front and /var/www/data-test2-front
When i try http://datavis.dev.localserver.fr/datavis/test1/ in my browser i have this return in the error logs:
2016/10/04 17:36:43 [error] 4614#4614: *1 opendir() "/var/www/data-test1-fron" failed (2: No such file or directory), client: 192.168.56.1, server: datavis.dev.localserver.fr, request: "GET /datavis/info/ HTTP/1.1", host: "datavis.dev.localserver.fr"
The last letter is removed... do anyone know why ?
Although not explicit, the example in the manual shows the entire URI being constructed on the alias statement, when enclosed within a regular expression location.
So, although this doesn't directly answer your question, a working alternative configuration could be:
location ~ ^/datavis/(\w+)(.*)$ {
alias /var/www/data-$1-front$2;
autoindex on;
}
Obviously named captures would work too.
You alias doesn't ends with /, but autoindex want it and strip last char from path. index index.html wont work too, because result path will be /var/www/data-test-frontindex.html. So, all you need is to add /:
location ~ ^\/datavis\/(?<datarep>[\w]+)/ {
alias /var/www/data-${datarep}-front/;
autoindex on;
}

NGINX virtual hosts with seperate lua_package_path variables

I'm trying to serve two (Openresty) Lua web applications as virtual hosts from NGINX which both require their own unique lua_package_path, but have a hard time getting the configuration right.
# Failing example.conf
http {
lua_package_path = "/path/to/app/?.lua;;"
server{
listen 80;
server_name example.org
}
}
http {
lua_package_path = "/path/to/dev_app/?.lua;;"
server{
listen 80;
server_name dev.example.org
}
}
If you define the http twice (one for each host), you will receive this error: [emerg] "http" directive is duplicate in example.conf
If you define the lua_package_path inside the server block, you will receive this error: [emerg] "lua_package_path" directive is not allowed here in example.conf
If you define the lua_package_path twice in a http block (which does not make any sense anyway), you will receive this error: [emerg] "lua_package_path" directive is duplicate in example.conf
What is the best practise of serving multiple (Openresty) Lua applications with their own lua_package_path, being virtual hosts on the same IP and port?
I faced this issue several month ago.
I do not recommend no use debug and release projects in the same server. For instance, you launch the one nginx application for both (debug and release) key may lead to unexpectable behaviour.
But, nevertheless, you can setup:
package.path = './mylib/?.lua;' .. package.path inside lua-script.
You can setup your own local DEBUG = false state and manage inside the app.
Obviously, use the other machine for debug. Imo, the best solution.
Execute different my.release.lua or my.debug.lua file:
http {
lua_package_path "./lua/?.lua;/etc/nginx/lua/?.lua;;";
server{
listen 80;
server_name dev.example.org;
lua_code_cache off;
location / {
default_type text/html;
content_by_lua_file './lua/my.debug.lua';
}
}
server{
listen 80;
server_name example.org
location / {
default_type text/html;
content_by_lua_file './lua/my.release.lua';
}
}
}
Fixed it removing the lua_package_path from the NGINX configuration (since the OpenResty bundle already takes care of loading packages) and pointing my content_by_lua_file to the absolute full path of my app: /var/www/app/app.lua
# example.conf
http {
server{
listen 80;
server_name example.org
location / {
content_by_lua_file '/var/www/app/app.lua';
}
}
server{
listen 80;
server_name dev.example.org
location / {
content_by_lua_file '/var/www/app_dev/app.lua';
}
}
}
After that I included this at the top of my app.lua file:
-- app.lua
-- Get the current path of app.lua
local function script_path()
local str = debug.getinfo(2, "S").source:sub(2)
return str:match("(.*/)")
end
-- Add the current path to the package path
package.path = script_path() .. '?.lua;' .. package.path
-- Load the config.lua package
local config = require("config")
-- Use the config
config.env()['redis']['host']
...
This allows me to read the config.lua from the same directory as my app.lua
-- config.lua
module('config', package.seeall)
function env()
return {
env="development",
redis={
host="127.0.0.1",
port="6379"
}
}
end
Using this I can now use multiple virtual hosts with their own package paths.
#Vyacheslav Thank you for the pointer to package.path = './mylib/?.lua;' .. package.path! That was really helpful! Unfortunately it also kept using the NGINX conf root instead of my application root. Even with prepending the . for the path.

nginx upstream does not be recognized by proxy_pass

I want my nginx to pass different uri's to different backends,so I thought I do that:
server {
listen 8090;
access_log /var/log/nginx/nginx_access.log combined;
error_log /var/log/nginx/nginx_error.log debug;
location /bar {
proxy_pass http://backend2;
}
location /foo {
proxy_pass http://backend2;
}
location / {
proxy_pass http://backend1;
}
}
upstream backend1 {
server 10.33.12.41:8080;
server 127.0.0.1:8080 max_fails=3;
}
upstream backend2 {
server 10.33.12.41:8080;
server 10.33.12.43:8080;
}
If I call wget http://mynginxserver:8090/ i get the following:
wget http://mynginxserver:8090/
--2015-09-18 11:58:21-- http://mynginxserver:8090/
Connecting to mynginxserver:8090... connected.
HTTP request sent, awaiting response... 302 Found
Location: http://backend1/
[following]
--2015-09-18 11:58:21-- http://backend1/
Resolving backend1 (backend1)... failed: Temporary failure in name resolution.
wget: unable to resolve host address ‘backend1’
Why does it try to resolve backend1? I don't get it. Please help ;)
Regards,
Snooops
My Fault:
1st it should have been postet here: serverfault.com
and 2nd its already solved here:
https://serverfault.com/questions/590044/nginx-proxy-pass-config

Only one NGINX Server Context works at a time for NGINX sites-enabled

I have the following structure I am working with for NGINX
/etc/nginx
- nginx.conf
- conf.d
- a.conf-disabled (I appended 'disabled' so it wont be used)
- b.conf-disabled (I appended 'disabled' so it wont be used)
- sites-available
- a
- b
- sites-enabled
- a (sym link to sites-available/a)
- b (sym link to sites-available/b)
The nginx.conf file looks like the following:
worker_processes 4;
events {
worker_connections 1024;
}
http {
include /etc/nginx/conf.d/*.conf;
include /etc/nginx/sites-enabled/*;
}
The a file in sites-available looks like the following:
server {
listen 80;
server_name a;
location /a/ {
proxy_pass http://172.17.0.20:5678/;
}
}
and the b file in sites-available looks like the following:
server {
listen 80;
server_name b;
location /b/ {
proxy_pass http://172.17.0.20:5678/;
}
}
I am aware these pointing at the same address, I am just using it because I want to be able to test /a and /b separately.
The problem I am having is that only /a will work and /b fails. If I remove a, then /b works fine.
For example:
curl -X GET http://container-ip/a/ -> WORKS FINE
curl -X GET http://container-ip/b/ -> DOESN'T WORK
I ran logs and its not complaining about anything, but does fail with this when I try to hit /b.
2015/07/13 04:51:59 [error] 235#235: *58 "/etc/nginx/html/b/index.html" is not found (2: No such file or directory), client: 10.0.2.2, server: , request: "GET /b/ HTTP/1.1", host: "localhost:8181"

Resources