Elasticbeanstalk Nginx Reverse Proxy Conf for Different Server - amazon-web-services

I am looking to reverse proxy a different server IP from my application when a user goes to /blog on my website. I have set up what I believe to be the correct nginx location block configuration and successfully deployed an ebextension with the configuration, but when I navigate to /blog I receive the 404 page that is rendered from my application's server. On further inspection the request shows that the request was made to the application IP and not the IP address found in the /blog location block in my nginx setup. Can anyone help determine what might be wrong with either my ebextension, nginx or application setup that is preventing the nginx location block to work? I'm not sure how to test beyond requesting the url and checking the network resource tab in my develop tools.
Here is my ebextensions folder setup:
> ebextensions
=> nginx
==> conf.d
==- 01_nginx_blog_rp.config
-00_nginx_https_rw.config
-02_sequelize_db_migration.config
01_nginx_blog_rp.config:
files:
"/etc/nginx/conf.d/01_blog_proxy.conf":
mode: "000644"
owner: root
group: root
content: |
client_max_body_size 10M;
"/etc/nginx/conf.d/02_blog_location_block.conf":
mode: "000644"
owner: root
group: root
content: |
server {
location /blog {
proxy_pass http://xxx.xxx.xxx.xxx:2368;
proxy_set_header Host $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;
}
}
container_commands:
01_reload_nginx:
command: "sudo service nginx reload"

What you trying to achieve is not possible with just adding simple location block in conf.d.
You basically defining a new server block with location inside. This new server block is never used by nginx because you already have default server config generated by ElasticBeanstalk with configured listen and server_name directives. This two directives are used by nginx to decide where to forward request, therefore all incoming requests going to your application server and ignoring your customizations.
What you really need to do is to modify existing server block and add your location into it.
This can be done in a few different ways:
- Create new nginx config and delete default one.
In this aws documentation example they just adding a new .ebextensions/proxy.config and replace default nginx config with the custom one. Using this approach you can have a full control of your nginx configuration.
- Create new config and make it processed before default one.
If you still want to keep default config around you can just keep using your 00_nginx_https_rw.config name of config, this way nginx will process your config first, and if in your config you will have correct server_name and listen it will be used by nginx to process incoming request.
- Add hook to modify default config.
On AWS forum you can find another solution - add bash script hook to
modify existing config.

Related

Reverse proxy on Elastic Beanstalk to forward a subdirectory to subdomain

We use Elastic Beanstalk for our frontend: https://tutorspot.co.uk. We also have a Wordpress blog at https://blog.tutorspot.co.uk but I'd like that to be available at https://tutorspot.co.uk/blog. I'm trying to configure a reverse proxy in Nginx on EB but am not having any luck getting the app deployed with the config.
I don't want to override the entire Nginx configuration, just extend it to include a new location block for the /blog path.
Here's the config I'm trying to get working:
location /blog/ {
proxy_pass https://blog.tutorspot.co.uk;
proxy_set_header Host $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;
}
The Elastic Beanstalk docs suggest this should go in a *.conf file in .platform/nginx/conf.d/, however I'm running into the following issue when deploying the new config:
Unsuccessful command execution on instance id(s) 'i-xxxxxxxxxxx'. Aborting the operation.
I'm unsure whether this is the correct config and it's just in the wrong place, or whether the config itself is incorrect. For example, does the location block need to be wrapped in either a server or http context?
Any help would be greatly appreciated!
NB 1:
In production, we're using Amazon AMI, however, I'm taking this opportunity to upgrade us to Amazon Linux 2.
NB 2:
Here's the folder structure showing the location of the config file relative to .ebextensions etc.:

Django won't get https header

Intro
I am building a web app using the latest Django version along with python3.7. The app is dockerized and I plan to deploy with docker-compose. Inside the container, I use nginx to proxy traffic to the application and not expose it directly. Also, I use apache in server level to proxy traffic to various other containers hosted on the same machine.
In the Django application, I use oauth2 to authenticate to Fitbit Web API and the issue I am facing is that the django-social-auth is passing the hostname automatically as a redirect_uri which now, after a lot of configuration with all those proxies, works perfectly in HTTP but when I use HTTPS although the app responds normally the redirect_uri is still http which obviously is not allowed by fitbit and very risky.
Although it is very hard for me to locate in which level the problem occurs I have tried various things but nothing seems to work out.
What I have tried
First
I tried to make my container listen to https request which seemed the most appropriate solution to me but ended getting 502 errors from the Apache.
I tried to find a solution on this by adding some configuration to the virtual host file like
#Solution 1
SSLProxyEngine on
SSLProxyVerify none
SSLProxyCheckPeerCN off
SSLProxyCheckPeerName off
SSLProxyCheckPeerExpire off
ProxyPass / https://localhost:83/ Keepalive=On #Solution 2 (keep alive)
ProxyPassReverse / https://localhost:83
But at last, I found out that it was not an apache issue but that the nginx inside the container was not responding although the traffic was routed to 443 port using HTTPS
Second
I tried to route traffic from the apache https to containerd nginx HTTP ( which does not make so much sense to me ) which makes the application respond normally but and results the redirect_uri error I mentioned above
As you can see I more or less confused and any kind of hint or help could be very useful
Update 1
The nginx configuration as requested in the comments
server {
listen 80;
listen 443 default_server ssl;
server_name localhost;
charset utf-8;
location /static {
alias /app/static/;
}
location /upload {
alias /app/media/;
}
location / {
proxy_pass http://web:8000;
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;
}
}
I was able to fix the issue by adding the following configuration on the settings.py. I also added a control conditional in order to be able to run the container in development.
# Was already present before the issue resolved but is also needed
USE_X_FORWARDED_HOST = True
# The actual solution
if eval(os.environ.get('DEPLOY', default=False)):
SECURE_PROXY_SSL_HEADER = ('HTTP_X_FORWARDED_PROTO', 'https')
SECURE_SSL_REDIRECT = True
SESSION_COOKIE_SECURE = True
CSRF_COOKIE_SECURE = True

nginx connection refused after config

I was setting up nginx on my aws ubuntu instance. At first every time went well, but after I config nginx and try to connect django, I can't even see the welcome page from either public ip nor the localhost(which was able to access from both sides). The nginx status command shows nginx is running.
Here's my nginx config:
/nginx/sites-available/mysite.com
server{
charset utf-8;
listen 80;
server_name my_aws_ip;
location /static{
alias my_django_static_path;
}
location / {
proxy_set_header Host $host;
proxy_pass http://unix:tmp/mysite.socket;
}
}
And I made a link to /nginx/sites-enabled/
It appears that every time I restarted nginx, I will be able to see the welcome page. However, after that, nginx refuses connections.
I didn't change anything in nginx.conf. Do I need to?
server_name should be your domain name, IP address should be specified as part of the listen directive
proxy_pass http://unix:tmp/mysite.socket;
Not sure where you are hoping this will end up, but you need to decide if you are sending it via http or to a socket. Not both. Having said that if it's for django then it's not proxy_pass you want at all
I'm guessing you mean:
uwsgi_pass unix:/tmp/mysite.socket;
You'll also need to include these somewhere in your config

letsencrypt django webroot

I am trying to setup my nginx and django to be able to renew certificates.
However something goes wrong with my webroot-plugin
in nginx:
location ~ /.well-known {
allow all;
}
But when I run the renewal command:
./letsencrypt-auto certonly -a webroot --agree-tos --renew-by-default --webroot-path=/home/sult/huppels -d huppels.nl -d www.huppels.nl
However it seems that the cert renewal wants to retrieve a file from my server cause i get the following error.
The following errors were reported by the server:
Failed authorization procedure. www.huppels.nl (http-01): urn:acme:error:unauthorized :: The client lacks sufficient authorization :: Invalid response from http://www.huppels.nl/.well-known/acme-challenge/some_long_hash [51.254.101.239]: 400
How do i make this possible with nginx or django?
I have my Django app running with gunicorn. I followed the instructions here.
I made sure to include the proper location blocks:
location /static {
alias /home/user/webapp;
}
location / {
proxy_pass http://127.0.0.1:8000;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
Making sure to include any template location alias as well.
I set the .well-known location block like this;
location /.well-known {
alias /home/user/webapp/.well-known;
}
Pointing it directly do the root of the webapp instead of using the allow all.
I did have to make sure that I only used the non ssl block until the certificate was generated then I used a different nginx config based on h5bps nginx configs.
Note: Make sure you have proper A records for you domain pointing to www if you are going to use h5bp to redirect to www.

How to proxy proxy domain name to internal app server URL in Nginx?

I have an internal app server (Django+gunicorn) running behind an Nginx reverse proxy on a private port (listening on port 5000, for example.)
There are several Django apps installed in the app server, mapped to separate base paths. Example:
/app1
/app2
Where /app1 serves up content for domain1.com and /app2 serves content for domain2.com.
I'd like to silently reverse proxy incoming requests for specific hostnames to the related backend app, while preserving the path forwarded to the internal app server:
http://domain1.com/foo --> /app1/foo
http://domain1.com/bar/bletch --> /app1/bar/bletch
http://domain2.com/alpha/bravo --> /app2/alpha/bravo
I suppose you could say I'm trying to set up a simple 'virtual hosting' configuration but I want to use a shared back-end app server instance.
Key point: I don't want the visitor's browser to see the redirected URL structure. So when the client browser hits http://domain1.com/foo, the correct content is served up but the browser doesn't see a redirect.
I've done some basic work with Nginx (still learning) and I'm looking for example Nginx configurations demonstrating secure and efficient ways to accomplish this goal.
Based on this answer here's a configuration that seems to work as desired.
For app1 running on http://localhost:8000/app1_path :
upstream app1 {
server 127.0.0.1:8000 fail_timeout=0;
}
server {
listen 80;
server_name example.com
access_log /var/log/nginx/example.com.access.log;
error_log /var/log/nginx/example.com.error.log;
location / {
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $http_host;
rewrite ^(.*)$ /app1_path$1 break;
proxy_pass http://app1;
}
}
So, one could repeat this pattern as many times as desired for each hostname->app/path pair.