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.
Related
I wanted one of my lua script to get executed whenever nginx server starts or is reloaded. I tried using init_by_lua_block and init_by_lua_file directive but i dont see any log traces for the lua script in init_by_lua_block when i run the nginx docker. My http block looks like below. nginx.config is located in container path/etc/nginx/nginx.conf .
http {
sendfile on;
init_by_lua_block /etc/nginx/lua/init.lua;
include /etc/nginx/conf.d/proxy-config.conf;
}
Can anyone please tell me what I am missing here?
init_by_lua_block
syntax: init_by_lua_block { lua-script }
https://github.com/openresty/lua-nginx-module#init_by_lua_block
init_by_lua_block expects inlined Lua code, not a path to the Lua file.
Use dofile to execute Lua script:
init_by_lua_block {
dofile('/etc/nginx/lua/init.lua')
}
https://www.lua.org/manual/5.1/manual.html#pdf-dofile
or use init_by_lua_file:
init_by_lua_file /etc/nginx/lua/init.lua;
UPD:
You should use the NOTICE logging level (or higher) in init_by_lua_* directives because your error_log configuration is not yet applied in this phase:
Under the hood, the init_by_lua runs in the nginx configuration loading phase, so your error_log configuration in nginx.conf does not take effect until the whole configuration is loaded successfully (due to the bootstrapping requirements: the configuration loading MAY fail). And nginx initially uses a logger with the NOTICE filtering level upon startup which is effect in the whole first configuration loading process (but not subsequent configuration (re)loading triggered by the HUP signal).
https://github.com/openresty/lua-nginx-module/issues/467#issuecomment-82647228
So, use ngx.log(ngx.NOTICE, ...) (or ngx.WARN, ngx.ERR, etc. — see https://github.com/openresty/lua-nginx-module#nginx-log-level-constants) to see the output in the log.
Alternatively you can use print. It's equivalent to ngx.log(ngx.NOTICE, ...) under the hood: https://github.com/openresty/lua-nginx-module#print
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
What I have:
I have a Pyramid application that is built from a Paste ini, served by uWSGI and proxied by nginx. It works great. Here is the nginx config:
server {
listen 80;
server_name localhost;
access_log /var/log/myapp/nginx.access.log;
error_log /var/log/myapp/nginx.error.log warn;
location / {
uwsgi_pass localhost:8080;
include uwsgi_params;
}
}
Here is the uWSGI ini configuration:
[uwsgi]
socket = 127.0.0.1:8080
virtualenv = /srv/myapp/venv
die-on-term = 1
master = 1
logto = /var/log/myapp/uwsgi.log
This configuration is located inside Pyramid's production.ini, such that I serve the application with this command:
uwsgi --ini-paste-logged production.ini
All of this works just fine.
What I want to do:
One simple change. I want to serve this application as a subfolder, rather than as the root. Rather than serving it from http://localhost, I want to serve it from http://localhost/myapp.
And now everything is broken.
If I change the nginx location directive from / to /myapp or /myapp/, I get 404s, because the WSGI application receives uris that are all prepended with /myapp.
The uWSGI solution appears to be to mount the WSGI callable on the subfolder, and then pass the --manage-script-name option, at which point uWSGI should magically strip the subfolder prefix from the uri and fix the issue.
However, the documentation and every other resource I've found have only given examples of the form:
mount = /myapp=myapp.py
I don't have a myapp.py that contains a WSGI callable, because my callable is being built by PasteDeploy.
So, is it possible to mount the WSGI callable from within the Paste ini? Or am I going to have to split the uwsgi configuration out of the Paste ini and also define a separate wsgi.py with a call to paste.deploy.loadapp to generate a wsgi callable that I can mount?
Or is there another way to serve this app as a subfolder from nginx while not messing up the url reversing?
Yes, it's definitely possible to mount your Pyramid as a subdirectory with Nginx. What you'll need to use is the Modifier1 option from uWSGI like so:
location /myapp {
include uwsgi_params;
uwsgi_param SCRIPT_NAME /myapp;
uwsgi_modifier1 30;
uwsgi_pass localhost:8080;
}
The magic value of 30 tells uWSGI to remove the parameter of SCRIPT_NAME from the start of PATH_INFO in the request. Pyramid receives the request and processes it correctly.
As long as you're using the standard Pyramid machinery to generate URLs or paths within your application, SCRIPT_NAME will automatically be incorporated, meaning all URLs for links/resources etc are correct.
The documentation isn't the clearest, but there's more on the modifiers available at: https://uwsgi-docs.readthedocs.org/en/latest/Protocol.html
I wanted to do what you suggest but this is the closest solution I could find: if you are willing to modify your PasteDeploy configuration, you can follow the steps at: http://docs.pylonsproject.org/docs/pyramid/en/1.0-branch/narr/vhosting.html
Rename [app:main] to [app:mypyramidapp] and add a section reading:
[composite:main]
use = egg:Paste#urlmap
/myapp = mypyramidapp
I also had to add this to my nginx configuration:
uwsgi_param SCRIPT_NAME '';
and install the paste module
sudo pip3 install paste
I wonder if there is a way to "mount" a PasteDeploy as to original question asked...
I've hit this very problem with my deployment after switching from Python2 to Python3.
with Python2 I used the uwsgi_modifier1 30; trick, but it doesn't work anymore with Python3, as described here: https://github.com/unbit/uwsgi/issues/876
It is very badly documented (not at all? I know it from reading the uWSGI source code), but --mount option accepts the following syntax:
--mount=/app=config:/path/to/app.ini
Please note: with --mount you also need --manage-script-name option.
There are other problems with it: https://github.com/unbit/uwsgi/issues/2172
It's trivial to write a wrapper script around Paste-Deploy app, which is the way I deploy now:
from paste.script.util.logging_config import fileConfig as configure_logging
from paste.deploy import loadapp as load_app
from os import environ
config_file = environ['INI_FILE']
configure_logging(config_file)
application = load_app('config:' + config_file)
Save it to e.g. app.py and you can use it with --mount /app=app.py, the INI_FILE environment var should point to your .ini file.
As a side note - I consider moving away from uWSGI, it's buggy and documentation lacks a lot.
I'm getting some problems to make spiderable work with PhantomJS on my Ubuntu server. I saw this troubleshooting on Meteorpedia:
Ensure that the ROOT_URL that your Meteor server is configured to use
is accessible from the server itself. (Since v0.8.1.3[1])
I think that this could be a possible answer to why it is not working. What is exactly the purpose of this environment variable?
My application is publicly accessible on http://gentlenode.com/ but my proxy_pass on nginx is set to http://gentlenode/.
# HTTPS Server
server {
listen 443;
server_name gentlenode.com;
# ...
location / {
proxy_pass http://gentlenode/;
proxy_http_version 1.1;
# ...
}
}
Should I set ROOT_URL to http://gentlenode.com/, to http://gentlenode/ or to http://localhost/?
You can find my nginx configuration here: https://gist.github.com/LeCoupa/9877434
The ROOT_URL environment variable should be set to the URL that clients will be accessing your application with. So in your case, it would be http://gentlenode.com or https://gentlenode.com.
The ROOT_URL environment variable is read by Meteor.absoluteUrl, which is used in many (core) packages. Thus, setting ROOT_URL may be a requirement if you use these packages. spiderable is one such package.
// Line 62 of spiderable_server.js
var url = Spiderable._urlForPhantom(Meteor.absoluteUrl(), req.url);
I'll admit that we don't use spiderable so I'm not 100% certain if this will fix your problem, but here's what we do...
We set ROOT_URL to the URL which clients will use to initially connect. In your case, the nginx config automatically upgrades all HTTP requests to HTTPS, so all requests will be seen by your app under https://gentlenode.com. I think you should start your server after:
export ROOT_URL=https://gentlenode.com
Your proxy_pass section may be correct. We manually spell out the name of the local port. So we'd write:
proxy_pass http://localhost:58080;
If you have something that works already, this may not be necessary. I don't know all the quirks of nginx well enough to say if that part matters.
I have a setup where my nginx is in front with apache+PHP behind.
My PHP application cache some page in memcache which are accessed by nginx directly except some dynamic part which are build using SSI in Nginx.
The first problem I had was nginx didnt try to use memcache for ssi URI.
<!--# include virtual="/myuser" -->
So I figured that if I force it to use a full URL, it would do it.
<!--# include virtual="http://www.example.com/myuser" -->
But in logs file (both nginx and apache) I can see that a slash has been added at the beginning of the url
http ssi filter "/http://www.example.com/myuser"
In the source code of the SSI module I see a PREFIX that seems to be added, but I can really tell if I can disable it.
Anybody got this issue?
Nginx version : 0.7.62 on Ubuntu Karmic 64bits
Thanks a lot
You can configure nginx to include remote URLs despite you cannot refer them directly in SSI instructions. In site config create location with local path and named remote location that points where you want to. For example:
server {
....
location /remote {
proxy_pass #long_haul; # or use "try_files" to provide fallback
}
location #long_haul {
proxy_pass http://porno.com;
}
....
}
and in served html use include directive that refers /remote path:
<!--# include virtual="/remote/rest-of-url&and=parameters" -->
Note that you may customize URL that is passed further with variables and regexp. For example:
location ~/remote(.+) {
proxy_pass #long_haul$1?$args;
}
It has nothing about nginx, you just can't do that. SSI doesn't accept remote uri. you can only specify a local file path.
See
http://en.wikipedia.org/wiki/Server_Side_Includes