I am using HttpLuaModule for my NGINX server. I want to ask if it is possible to recognize variable in different directives of this module. For example
init_by_lua ' local global_var = 5 ' ;
some config ;
set_by_lua ' print(global_var) ' ;
How is that possible with NGINX and LUA module ?
If you want global_var to be global, don't declare it as local.
From a quick look at NGINX's docs, init_by_lua and set_by_lua work on the same global Lua state and so you'll be able to make them talk if you use global variables. Local variables set in init_by_lua will be lost.
So, it should work if you just remove local in init_by_lua.
Related
I'm newish to LUA and want to practice some LUA scripting using nginx/openrestry.
Is there a workflow where I can use docker that runs openresty, and link my laptops filesystem to my docker container such that when I make a change to my lua script, I can quickly reload openrestry server so I can quickly see my lua changes take effect?
Any help or guidance would be appreciated.
You can disable Lua code cache — https://github.com/openresty/lua-nginx-module#lua_code_cache — add lua_code_cache off inside the http or server directive block. This is not actually “hot reload”, it's more like php request lifecycle:
every request served by ngx_lua will run in a separate Lua VM instance
You can think of it as if the code is hot–reloaded on each request.
However, pay attention to this:
Please note however, that Lua code written inlined within nginx.conf [...] will not be updated
It means that you should move all your Lua code from the nginx config to Lua modules and only require them:
server {
lua_code_cache off;
location /foo {
content_by_lua_block {
-- OK, the module will be imported (recompiled) on each request
require('mymodule').do_foo()
}
}
location /bar {
content_by_lua_block {
-- Bad, this inlined code won't be reloaded unless nginx is reloaded.
-- Move this code to a function inside a Lua module
-- (e.g., `mymodule.lua`).
local method = ngx.req.get_method()
if method == 'GET' then
-- handle GET
elseif method == 'POST' then
-- handle POST
else
return ngx.exit(ngx.HTTP_NOT_ALLOWED)
end
}
}
}
Then you can mount your Lua code from the host to the container using --mount or --volume: https://docs.docker.com/storage/bind-mounts/
I'm using NGINX with lua support to accesses hostnames and other App releated variables from my .env file.
Now i wanted to use the secure_link_md5 var. from a .env file but i dont understand how to put together the string so that nginx can understand it.
This is how my nginx config looks like:
env LINK_SECRET;
set_by_lua $curr_dl_link_secret 'return os.getenv("LINK_SECRET")'; # Needs to be set correctly
secure_link_md5 = "${curr_dl_link_secret}$uri$secure_link_expires";
Normaly i would set the config line like that without the use of lua and env vars:
secure_link_md5 "XGc7YyXERjiSvs4PtzpnBMANuFd22VAmXDc66g6JU$uri$secure_link_expires";
Currently NGINX always returns the following error:
invalid number of arguments in "secure_link_md5"
NGINX counts "=" as an argument. I am not familiar with NGINX with lua, but I think "{}" are also unnecessary.
I guess you want something like this:
secure_link_md5 "$curr_dl_link_secret$uri$secure_link_expires";
I try to add a proxy_pass in the nginx.conf like
location /example/ {
proxy_pass http://example.com;
}
But instead of hard coding http://example.com in the conf file I want to have this value in an environment variable.
How can I use environment variables in nginx.conf? Or is there a better way with nginx no have external configuration?
If you want pure environment variables into nginx config, you will need implements some code in Lua Language:
https://blog.doismellburning.co.uk/environment-variables-in-nginx-config/
If you don't have a high load on this NGinx, I recommend implements this above solution.
In my specific case, to reduce CPU load, I prefer to use separated files with variables and a script in rc.local (or dockerfile) to change these files when launch the machine.
conf.d/exemple.conf
include backends/exemple.host;
location ~ ^/exemple {
proxy_pass $exemple;
}
backends/exemple.host
set $exemple {BACKEND};
rc.local
sed -i "s#set \$exemple.*#set \$exemple $HOSTNAME\;#" /etc/nginx/backends/exemple.host
To the last solution works, I need change the NGinx start order on O.S.
You can use lua.
ex:
set_by_lua $curr_domain_name 'return os.getenv("DOMAIN")';
add_header Content-Security-Policy 'script-src ${curr_domain_name}';
This worked for me.
I have a lua script that uses lua-resty to call another service via co-sockets.
Now I would like to use the information from this call to route the request in nginx.
nginx includes the lua script in access_by_lua*
which sets the var like this:
ngx.var.blocked = '1'
and routes in the location like this:
if ( $blocked ) {
proxy_pass http://haproxy-9001;
break;
}
the problem is now that nginx does not pick up the variable change (in this phase).
if I include the lua script in set_by_lua* phase then the variable passing works but I dont have access to the co-sockets in this phase.
Any idea how to get the variable out of lua land into the nginx variable in the access_by_lua, rewrite_by_lua or content_by_lua phase so that I can use the co-socket api to make a http call?
if nginx directive is implemented by https://nginx.ru/en/docs/http/ngx_http_rewrite_module.html.
Obviously it works on rewrite phase, so your changes at access phase doesn't work.
Just don't use if. Below is snippet from one of my nginx config:
proxy_pass $scheme://$upstream$uri$is_args$args;
Just set $upstream variable at access phase and it will work at content phase (proxy_pass).
Maybe you could capture location with that proxy instead of variable, it works in access_by_lua scope
https://github.com/openresty/lua-nginx-module#ngxlocationcapture
I'm trying to setup response headers on my separate webservers that outputs the physical name of the machine that nginx is running on, so that I can tell which servers are serving the responses to our web clients.
Is there a variable that exists to do this already? Or do I just have to hardcode it per-server :(
You're after the $hostname common variable. Common variables are listed in the variable index.
The nginx access log documentation only shows variables that are specific to the access log:
The log format can contain common variables, and variables that exist
only at the time of a log write.
I guess you're looking for $hostname variable.
At first I thought the answer was to use the ENV variable and pull out the hostname from there https://docs.apitools.com/blog/2014/07/02/using-environment-variables-in-nginx-conf.html. But I couldn't get it to work for some reason.
However, this works like a charm:
perl_set $server_int 'sub { use Sys::Hostname; return hostname; }';
And example usage:
add_header 'Server-Int' "$server_int";
Just have to make sure your nginx is compiled with --with-http_perl_module - just run nginx -V to make sure. And that you have Sys::Hostname installed.
Warning: I at first used hostname to return the hostname in the Perl script, but while that did return the name, it for some reason aborted the rest of the output. I don't know if it's a bug with perl_set but you've been warned - using backticks in perl_set may be deadly.