Accessing WSO2-APIM using Nginx - nginx

I am accessing my wso2 apim,store and publisher using Nginx.
and want to access using the following:
wso2 api manager to be accessed using nginx url as:
https://nginx-ip/wso2am/carbon
wso2 store to be accessed using nginx url as:
https://nginx-ip/wso2am/store
wso2 store to be accessed using nginx url as:
https://nginx-ip/wso2am/publisher
I tried using nested location block inside location block but wasn't successful.
So, now I am working by having a location block for all of them separately but the same also doesn't works.
Here is my nginx configuration file for store:
location /wso2am/store/
{
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_pass https://wso2-ip:9443/store/;
proxy_redirect https://$http_host/store/ /wso2am/store/;
proxy_cookie_path / /wso2am/;
limit_rate 25M;
#limit_req zone=wso2am burst=100 nodelay;
}
For the above configuration the GUI for store doesn't appears properly.
Similarly for publisher and carbon(for apim management console).
And the nested nginx configuration is as follows:
location /wso2am/ {
location /wso2am/store/
{
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_pass https://wso2-ip:9443/store/;
proxy_redirect https://$http_host/oauth2/callback /oauth2/callback;
proxy_redirect https://$http_host/ /wso2am/store/;
proxy_redirect https://$http_host/wso2am/ /wso2am/store/;
proxy_redirect https://$http_host/store/ /wso2am/store/;
proxy_cookie_path / /wso2am/;
limit_rate 25M;
}
}
Where do I have to change in headers or any other location to go correct?
Update 1:
My wso2am store and publisher are working after incorporating the comments and using the following nginx conf:
location /wso2am/ {
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_pass https://wso2-apim-ip:9443/;
proxy_redirect https://$http_host/carbon/ /wso2am/carbon/;
proxy_redirect https://$http_host/store/ /wso2am/store/;
proxy_redirect https://$http_host/publisher/ /wso2am/publisher/;
proxy_cookie_path / /wso2am/;
}
Note: But using the above configuration,I login to apim-carbon,I get logged in and then if I click on any of the options on the home page such as list,add.I get logged out and the reason behind it after investigation was the CSRF token is not being sent in the request while accessing it using Nginx.
How can the csrfprevention.js issue be resolved keeping it true.?

Disclamer: this is an incomplete answer, for I am myself digging into this question
I faced the very same issue with both wso2am and wso2ei. I am pretty sure that we need to edit /repository/conf/carbon.xml in this section (I must admit that the comments are not crystal clear):
<!--
Webapp context root of WSO2 Carbon management console.
-->
<WebContextRoot>/wso2am</WebContextRoot>
<!--
Proxy context path is a useful parameter to add a proxy path when a Carbon server is fronted by reverse proxy. In addition
to the proxy host and proxy port this parameter allows you add a path component to external URLs. e.g.
URL of the Carbon server -> https://10.100.1.1:9443/carbon
URL of the reverse proxy -> https://prod.abc.com/appserver/carbon
appserver - proxy context path. This specially required whenever you are generating URLs to displace in
Carbon UI components.
-->
<MgtProxyContextPath>/</MgtProxyContextPath>
<ProxyContextPath>/wso2am</ProxyContextPath>
The following works if your Nginx listen to 443 in SSL mode (couldn't do it with HTTP because of the redirections -> make a self signed certificate if you plan to use it on a local network)
location /wso2am {
proxy_pass https://wso2_apimanager_container:9443;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-Host $host;
proxy_ssl_verify off;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
location /wso2am/store {
proxy_pass https://wso2_apimanager:9443/store;
}
location /wso2am/publisher {
proxy_pass https://wso2_apimanager:9443/publisher;
}
location /wso2am/admin {
proxy_pass https://wso2_apimanager:9443/admin;
}
}
It works but I am not completely sure why. Can someone explain to me in which aspect <MgtProxyContextPath> differs from </MgtProxyContextPath> and from <WebContextRoot>?
allow proxy for admin publisher and store: to make /publisher, /store and /admin accessible, you need to edit the end of their respective site.json located in /repository/deployment/server/jaggeryapps/name_of_the_service/site/conf/site.json . For /publisher, you would write:
"reverseProxy" : {
"enabled" : "auto", // values true , false , "auto" - will look for X-Forwarded-* headers
"host" : "some.ip.or.domain", // If reverse proxy do not have a domain name use IP
"context":"/wso2am/publisher",
//"regContext":"" // Use only if different path is used for registry
},
Still have issue with the login though

You can follow this guide [1] to configure WSO2 API Manager with Nginx.
[1] -
https://docs.wso2.com/display/AM260/Configuring+the+Proxy+Server+and+the+Load+Balancer

Related

Nginx Location Regex for keycloak

I have a keycloak, react web and a spring boot app are living behind nginx.
The frontend (react) and the backend (spring boot) are calling the keycloak service over the nginx proxy at the flowing urls:
realms/.../..etc
admin/.../..etc
js/.../.../..etc
resources/.../...etc
All those urls are reverse proxing to:
Http://keylock:8180
I don't want to implements multiple locations in nginx for all those urls!
I am thinking about url rewriting to
auth/realms/...
auth/dmin/..
...
Or another clean solution with regex, but i don't know how.
You can use the rewrite module for this.
location /auth {
rewrite ^/auth(/|$)(.*) /$2/ break;
proxy_pass http://keylock:8180;
}
In fact, with this method, I get the second part of the url and proxy it.
For example, when request send to /auth/realms/... the url rewrite to /realms/... and send it to keycloak http://keylock:8180/realms/...
this worked for me
location ~ ^/(realms|js|resources|admin)/ {
proxy_set_header Referer $http_referer;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Forwarded-Port $server_port;
proxy_set_header Host $http_host;
proxy_pass http://keycloak;
proxy_redirect off;
}

Return website host url instead of api url

I have a Nginx server with reverse proxy for my API. How can I return the website host URL instead of returning the API URL api.example.com, because when I make a request from website it returns the API URL not the website URL app.example.com.
location /api/1 {
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto https;
proxy_set_header X-Forwarded-Port 443;
proxy_set_header Connection 'updgrade';
proxy_set_header Host $host;
proxy_pass https://api.example.com/rest;
proxy_ssl_server_name on;
}
p/s: sorry for my bad english
if you want to change url in returned your application code and your application behind the proxy makes references to api.example.com instead of app.example.com, you need to change your application logic to return correct URL in this use case.
Or use sub_filter module, But you need to check your nginx was built with this module.

Nginx location to FLASK route

I have 2 docker containers running. 1 is FLASK and 2 is Nginx.
This is the configuration of the Nginx location
location /search/?(.*) {
proxy_pass http://backend:8080/search/;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade';
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_pass_request_headers on;
}
The FLASK is running on port 8080 and the route #app.route('/search', methods=['GET']) and running with app.config['SERVER_NAME'] = 'mydomain.com'
When I try to send a GET request to "mydomain.com" (going through the NGINX) from external I get
Cannot GET /search
When I remove app.config['SERVER_NAME'] = 'mydomain.com' from the FLASK I can send GET to EXTERNAL_IP:8080 (Directly to the backend not though the NGINX).
But when I leave the app.config['SERVER_NAME'] = 'mydomain.com' and try to GET mydomain.com:8080 I get 404 Not Found
What am I missing here?
I want all requests to go though the NGINX and I want to use mydomain.com
I think your main mistake is that you trying to match the whole request URI including the query part while location directive (as well as the rewrite one) works with the normalized URI which doesn't include the query part at all (check the location directive documentation to find out what URI normalization is). Looks like you are also trying to use a regex while regex location should be declared using a ~ (or ~*) modifier. Nevertheless you don't need any regex locations at all for your particular case. To proxy a single API endpoint preservig the Host HTTP header value, you can try this one:
location = /search {
proxy_pass http://backend:8080;
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
You don't need to specify an URI with the proxy_pass directive since you are not changing your request URI. If your API endpoint is /search/ rather than /search, change the location accordingly. If it is an URI path prefix rather than a single API endpoint, use a prefix location /search/ { ... } instead of exact match location.

Proxy_pass to url NGINX with a Meteor Server

I have configured a meteor server and setup the nginx configuration. The route works however when configuring dynamic subdomains to point to a specific part of the web app it produces a 404 error on the browser when loading the meteor file.
I am attempting to direct all *.domain.com to http://localhost:3000/booking/
My configuration is:
server {
server_name *.domain.com;
listen 80;
location / {
proxy_pass http://localhost:3000/booking/;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade; #for websockets
proxy_set_header Connection $connection_upgrade;
proxy_set_header X-Forwarded-For $remote_addr;
proxy_set_header Host $host;
}
}
The 404 occurs in the Meteor JS file.
If I remove the above nginx subdomain configuration and go to a subdomain it works perfectly, loading the route application. I assume I am missing something to load the application correctly.
The issue only occurs when I proxy_pass to a route within the URL <url>/booking
There are different ways of solving the issue.
1 - In case of 404 try a fallback option without booking in url
server {
server_name *.domain.com;
listen 80;
location / {
proxy_pass http://localhost:3000/booking/;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade; #for websockets
proxy_set_header Connection $connection_upgrade;
proxy_set_header X-Forwarded-For $remote_addr;
proxy_set_header Host $host;
error_page 404 = #fallback;
}
location #fallback {
proxy_pass http://localhost:3000/$request_uri;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade; #for websockets
proxy_set_header Connection $connection_upgrade;
proxy_set_header X-Forwarded-For $remote_addr;
proxy_set_header Host $host;
}
}
2 - Have a separate block for js and css
server {
server_name *.domain.com;
listen 80;
location / {
proxy_pass http://localhost:3000/booking/;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade; #for websockets
proxy_set_header Connection $connection_upgrade;
proxy_set_header X-Forwarded-For $remote_addr;
proxy_set_header Host $host;
}
location ~ \.(js|css|font)$ {
proxy_pass http://localhost:3000/$request_uri;
proxy_http_version 1.1;
proxy_set_header X-Forwarded-For $remote_addr;
proxy_set_header Host $host;
}
}
I have a similar setup, where I have configured different Meteor applications on several subdomains plus a static website on the domain root, all pointing interlly to different ports.
Here is my setup step by step.
Folder structure, location and proxy pass
First thing to think about is the folder strucutre. Depending on your subdomain's VHost-root directory there is a relative path to your subdomain's application folder.
Imagine the following setup:
/www (dir, usually under /var)
/domain (dir)
/websitexy (dir, a static website is deployed under this dir)
/subdomain (dir)
/books (dir, subdomain app is deployed under this dir)
For such a setup I made my nginx config to point to the app's location within the subdomain:
location /books {
I had a similar issue when first time starting my app. One thing I found out is, that my config worked, when setting proxy_pass on my private ip/port combination:
proxy_pass http://172.x.x.x:3000;
This also involves to remove the route name (/books) adter the port number on this entry. Now your proxy pass involves all routing within your subdomain.
Note on routing
Note, that there can be confusion about routing here. By setting the location property you set the routing on the nginx level (server's directory structure), which is why there is no route within your proxy pass.
Your application may have it's own internal routing defined. It is important, that you app's internal router retrieves all requests based from it's application ur root. This is why it is important to have the proxy pass not to include any path after the port number.
Websocket
I have read some articles on nginx and websocket connections. Basically my initial settings came from this article and looked like from this documentation article:
location /app {
proxy_pass 172.x.x.x;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;
}
I also had to add a proxy_read_timeout and proxy_send_timeout because there was an issue with the websocket protocol otherwise:
By default, the connection will be closed if the proxied server does
not transmit any data within 60 seconds. This timeout can be increased
with the proxy_read_timeout directive
So I also set the timeout values:
proxy_read_timeout 36000s;
proxy_send_timeout 36000s;
proxy_set_header Connection "upgrade";
Read more on this here and here.
Summarizing my setup looks like the following (using your app credentials):
location /books {
proxy_pass http://172.x.x.x:3000;
proxy_http_version 1.1;
proxy_read_timeout 36000s;
proxy_send_timeout 36000s;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header X-Forwarded-For $remote_addr;
proxy_set_header Host $host;
}
So to solve your case, you may check on your vhost directory (the one where your app is deployed, see folder structure above) and change your location and proxy_pass setting accordingly.
If this is not working, you may need to add some more output of your errors, e.g. a excerpt of the log when attempt to connect.

nginx reverse proxy images and css are not loaded

I try to configure an nginx reverse proxy to access a Jenkins instance. I can open the authentication page but there is no CSS and no image. It works perfectly when direct access.
All works as if the reverse proxy does not rewrite correctly URLs defined in the html source page. Have I missed something ?
Here is my nginx configuration :
location /jenkins {
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $http_host;
proxy_redirect false;
proxy_pass http://jenkins:8080/;
}
I found the solution. The nginx reverse proxy works well but Jenkins need some customization to work with reverse proxy.
The final nginx configuration :
location /jenkins/ {
proxy_pass http://jenkins:8080/jenkins/;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
And the tutorial to configure jenkins behind nginx reverse proxy which solved my problem
I don't know if above statement worked for OP but I know that altering location name line did the trick for me:
location ^~ /jenkins/ {
proxy_pass http://jenkins:8080/jenkins/;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
If you use the Jenkins with docker. You can add the environment part of compose file as below:
environment:
JENKINS_OPTS: "--prefix=/jenkins"
in the nginx conf file. proxy_pass must refer to the http://IP-ADDRESS:PORT/jenkins/. As mentioned before, the link as a reference is very usefull.

Resources