Nginx Gunicorn socket issue? Unresponsive - nginx

I'm trying to deploy a Django project to a AWS Lightsail server.
I followed mostly this tutorial. I added some SSL protocols for additional security.
This projects runs perfectly on my Ubuntu 18.04 VirtualBox with exact same setup and exact same components, same SSL protocols. However on the Lightsail it doesn't respond to the browser request. It will redirect me to https but then will die... I wasn't able to identify any errors in any of the logs. Which leaves me guessing
/etc/systemd/system/webrock.socket:
[Unit]
Description=gunicorn socket
[Socket]
ListenStream=/run/webrock.sock
[Install]
WantedBy=sockets.target
/etc/systemd/system/webrock.service:
[Unit]
Description=gunicorn daemon
Requires=webrock.socket
After=network.target
[Service]
User=ubuntu
Group=www-data
WorkingDirectory=/home/ubuntu/django/webrock
ExecStart=/home/ubuntu/django/webrock/venv/bin/gunicorn \
--access-logfile - \
--workers 3 \
--bind unix:/run/webrock.sock \
core.wsgi:application
[Install]
WantedBy=multi-user.target
/etc/nginx/sites-available/webrock:
server {
listen 443 ssl http2;
listen [::]:443 ssl http2 ipv6only=on;
include snippets/signed.conf; # path to certs
include snippets/params.conf; # cert related params
index index.html index.htm index.nginx-debian.html;
server_name mydomain.com www.mydomain.com; #changed this line by replacing domain name with dummy
location = /favicon.ico {access_log off; log_not_found off;}
location /static/ {
root /home/ubuntu/django/webrock;
}
location / {
include proxy_params;
proxy_pass http://unix:/run/webrock.sock;
try_files $uri $uri/ =404;
}
}
server {
listen 80;
listen [::]:80;
server_name mydomain.com www.mydomain.com; #changed this line by replacing domain name with dummy
return 302 https://$server_name$request_uri;
}
I left the nginx default file alone. Now every time I visit the page by punching in the server IP, I see the nginx default page. When I use the domain name I get redirected to HTTPS, but then... nothing. I assume that there is some disruption between gunicorn and nginx, but I'm not experienced enough to troubleshoot there or solve to solve it.
As I mentioned above, exact the same setup runs flawless on the similar system in my VirtualBox.
I'm very thankful for suggestions and hints.
Update:
I disabled the redirect portion in nginx and made it listen to port 80. It worked. Now I'm trying to figure out how to introduce HTTP2 and port 443 back to the setup. BTW my ufw looks like this:

After two days banging my head against this issue here is the solution.
So Amazon Lightsail has an additional firewall in front of the UFW on the actual server.
You can access Lightsail firewall by clicking on...
Menue of your instance > Manage > Networking
You will see a summarized networking for your instance like IP addresses, Firewall, Loadbalancer. In that firewall you need to add an additional port (In my case HTTPS).
Why would they put an additional firewall in front of UFW beats me.

Related

nginx: 502 bad gateway if /index.html is not in URL

i don't understand what i'm doing wrong so i hope somebody can help :)
When i access http://10.0.0.54/index.html i get the right page but if i try to access http://10.0.0.54 instead of showing the index file it redirects me to https://10.0.0.54 showing error 502 bad gateway.
This is the configuration /etc/nginx/sites-available/default
server {
listen 80 default_server;
listen [::]:80 default_server;
root /var/www/html/salvaderi;
index index.html;
server_name _;
location ~ /.well-known/acme-challenge {
allow all;
root /var/www/html/salvaderi;
}
location / {
root /var/www/html/salvaderi;
index index.html;
}
}
I am running nginx 1.18.0 on ubuntu 22.04
i tried changing parameters inside location /{} but i always get the same result. I also changed the root directory and made sure permission where set right. Searching on for the solution i saw other people having problems about PHP and FastCGI but i am not using it.
Your configuration about to be right.
Possible there is some kind of proxy or load-balancer is placed between you and nginx you configuring since you got redirect to HTTPS whether there is no any redirection instructions in your config and, in the same time, there is no listen 443 ssl in config, but you still got response on HTTPS request.
I'd check next:
Is 10.0.0.54 in fact IP of your server?
Is there any return 301, return 302 or rewrite instructions in your nginx config (the better
way is to dump config with nginx -T command and look over).
Didn't
you previously have configured some redirects that may have been
cached by your web client previously? Try to send GET request with
curl instead of web browser (if browser been used for tests).

How to use nginx to direct traffic to two different ports on the same device?

I am currently working on a FPV robotics project that has two servers, flask/werkzeug and streamserver, serving http traffic and streaming video to an external web server, located on a different machine.
The way it is currently configured is like this:
http://1.2.3.4:5000 is the "web" traffic (command and control) served by flask/werkzeug
http://1.2.3.4:5001 is the streaming video channel served by streamserver.
I want to place them behind a https reverse proxy so that I can connect to this via https://example.com where "example.com" is set to 1.2.3.4 in my external system's hosts file.
I would like to:
Pass traffic to the internal connection at 1.2.3.4:5000 through as a secure connection. (certain services, like the gamepad, won't work unless it's a secure connection.)
Pass traffic to 1.2.3.4:5001 as a plain-text connection on the inside as "streamserver" does not support HTTPS connections.
. . . such that the "external" connection (to ports 5000 and 5001 are both secure connections as far as the outside world is concerned, such that:
[external system]-https://example.com:5000/5001----nginx----https://example.com:5000
\---http://example.com:5001
http://example.com:5000 or 5001 redirects to https.
All of the literature I have seen so far talks about:
Routing/load-balancing to different physical servers.
Doing everything within a Kubernates and/or Docker container.
My application is just an every-day plain vanilla server type configuration, and the only reason I am even messing with https is because of the really annoying problems with things not working except in a secure context which prevents me from completing my project.
I am sure this is possible, but the literature is either hideously confusing or appears to talk to a different use case.
A reference to a simple how-to would be the most usefull choice.
Clear and unambiguous steps would also be appreciated.
Thanks in advance for any help you can provide.
This minimal config should provide public endpoints:
http://example.com/* => https://example.com/*
https://example.com/stream => http://1.2.3.4:5001/
https://example.com/* => https://1.2.3.4:5000/
# redirect to HTTPS
server {
listen 80;
listen [::]:80;
server_name example.com
www.example.com;
return 301 https://example.com$request_uri;
}
server {
listen 443 ssl http2;
listen [::]:443 ssl http2;
server_name example.com
www.example.com;
ssl_certificate /etc/nginx/ssl/server.cer;
ssl_certificate_key /etc/nginx/ssl/server.key;
location /stream {
proxy_pass http://1.2.3.4:5001/; # HTTP
}
# fallback location
location / {
proxy_pass https://1.2.3.4:5000/; # HTTPS
}
}
First, credit where credit is due: #AnthumChris's answer is essentially correct.  However, if you've never done this before, the following additional information may be useful:
There is actually too much information online, most of which is contradictory, possibly wrong, and unnecessarily complicated.
It is not necessary to edit the nginx.conf file.  In fact, that's probably a bad idea.
The current open-source version of nginx can be used as a reverse proxy, despite the comments on the nginx web-site saying you need the Pro version.  As of this instant date, the current version for the Raspberry Pi is 1.14.
After sorting through the reams of information, I discovered that setting up a reverse proxy to multiple backend devices/server instances is remarkably simple.  Much simpler than the on-line documentation would lead you to believe.
 
Installing nginx:
When you install nginx for the first time, it will report that the installation has failed.  This is a bogus warning.  You get this warning because the installation process tries to start the nginx service(s) and there isn't a valid configuration yet - so the startup of the services fails, however the installation is (likey) correct and proper.
 
Configuring the systems using nginx and connecting to it:
 
Note: This is a special case unique to my use-case as this is running on a stand-alone robot for development purposes and my domain is not a "live" domain on a web-facing server.  It is a "real" domain with a "real" and trusted certificate to avoid browser warnings while development progresses.
It was necessary for me to make entries in the robot's and remote system's HOSTS file to automagically redirect references to my domain to the correct device, (the robot's fixed IP address), instead of directnic's servers where the domain is parked.
 
Configuring nginx:
The correct place to put your configuration file, (on the raspberry pi), is /etc/nginx/sites-available and create a symlink to that file in /etc/nginx/sites-enabled
It does not matter what you name it as nginx.conf blindly imports whatever is in that directory.  The other side of that is if there is anything already in that directory, you should remove it or rename it with a leading dot.
nginx -T is your friend!  You can use this to "test" your configuration for problems before you try to start it.
sudo systemctl restart nginx will attempt to restart nginx, (which as you begin configuration, will likely fail.)
sudo systemctl status nginx.service > ./[path]/log.txt 2>&1 is also your friend.  This allows you to collect error messages at runtime that will prevent the service from starting.  In my case, the majority of the problems were caused by other services using ports I had selected, or silly mis-configurations.
Once you have nginx started, and the status returns no problems, try sudo netstat -tulpn | grep nginx to make sure it's listening on the correct ports.
 
Troubleshooting nginx after you have it running:
Most browsers, (Firefox and Chrome at least) support a "developer mode" that you enter by pressing F-12.  The console messages can be very helpful.
 
SSL certificates:
Unlike other SSL servers, nginx requires the site certificate to be combined with the intermediate certificate bundle received from the certificate authority by using cat mycert.crt bundle.file > combined.crt to create it.
 
Ultimately I ended up with the following configuration file:
Note that I commented out the HTTP redirect as there was a service using port 80 on my device.  Under normal conditions, you will want to automatically re-direct port 80 to the secure connection.
Also note that I did not use hard-coded IP addresses in the config file.  This allows you to reconfigure the target IP address if necessary.
A corollary to that is - if you're redirecting to an internal secure device configured with the same certificates, you have to pass it through as the domain instead of the IP address, otherwise the secure connection will fail.
 
#server {
# listen example.com:80;
# server_name example.com;
# return 301 https://example.com$request_uri;
# }
# This is the "web" server (command and control), running Flask/Werkzeug
# that must be passed through as a secure connection so that the
# joystick/gamepad works.
#
# Note that the internal Flask server must be configured to use a
# secure connection too. (Actually, that may not be true, but that's
# how I set it up. . .)
#
server {
listen example.com:443 ssl;
server_name example.com;
ssl_certificate /usr/local/share/ca-certificates/extra/combined.crt;
ssl_certificate_key /usr/local/share/ca-certificates/extra/example.com.key;
ssl_prefer_server_ciphers on;
location / {
proxy_pass https://example.com:5000;
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;
}
}
# This is the video streaming port/server running streamserver
# which is not, and cannot be, secured. However, since most
# modern browsers will not mix insecure and secure content on
# the same page, the outward facing connection must be secure.
#
server {
listen example.com:5001 ssl;
server_name example.com;
ssl_certificate /usr/local/share/ca-certificates/extra/combined.crt;
ssl_certificate_key /usr/local/share/ca-certificates/extra/www.example.com.key;
ssl_prefer_server_ciphers on;
# After securing the outward facing connection, pass it through
# as an insecure connection so streamserver doesn't barf.
location / {
proxy_pass http://example.com:5002;
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;
}
}
Hopefully this will help the next person who encounters this problem.

Basic proxy_pass from nginx from one local ip to another local ip

I am a new user of nginx and I am following a video guide from Linode on youtube (How to Set Up an NGINX Reverse Proxy).
I have a working nginx and apache server both on port 80. I know that because when I type the ip address of both in firefox, it directs me to nginx/apache welcome page.
The youtube video configuration template is as follow (where the server_name is the linode ip) :
server {
listen 80;
listen [..]:80;
server_name 172.105.104.226;
location / {
proxy_pass http://localhost:3000/;
}
On my Proxmox machine, the nginx server is on a VM at 192.168.1.241 and the apache server on another VM at 192.168.1.243.
Looking at nginx documentation we find that this :
location /some/path/ {
proxy_pass http://www.example.com/link/;
}
should proxy all the traffic received on the nginx listening port and redirect it to the address specified by proxy pass.
With all these information, my configuration file is like this :
server {
listen 80;
listen [::]:80;
server_name 192.168.1.241;
location / {
proxy_pass http://192.168.1.243;
}
}
My understanding is that this configuration file should listen at the address 192.168.1.241 on port 80 (nginx server) and redirect it to the specified address 192.168.1.243 (apache server)/
If i understand correctly, Location / should take the request as is received on the nginx server and redirect it to the apache server.
However, when I enter 192.168.1.241 in my browser, it doesn't show the apache welcome message but shows the nginx welcome message. That means that the proxy isn't working.
My nginx understanding is extremely limited as I am just starting to learn, but to me it seems like this should work but doesn't.
Thank you for your help
It turns out that the configuration is correct.
The problem was that the webpage was cached. By forcing a full refresh, 192.168.1.241 redirected to 192.168.1.243 successfully.

nginx + cloudflare + digitalocean = 521

I'm trying host a website with multiple subdomains (created with Cloudflare, which also provides SSL) hosted on DigitalOcean with Nginx serving as a reverse proxy.
My Cloudflare Configs
DNS setup:
Type ~ Name ~ Value
A ~ api ~ MyDigitalOceanIPv4
A ~ example.com ~ MyDigitalOceanIPv4
A ~ www ~ MyDigitalOceanIPv4
Crypto setup:
SSL: Full (strict)
Always use HTTPS: On
Automatic HTTPS Rewrites: On
I've also used Cloudflare to Create Certificate (and followed their instructions to set it up with Nginx)
My Nginx config:
server {
listen 443;
server_name example.com www.example.com;
ssl on;
ssl_certificate /srv/example.com/cloudflare.pem;
ssl_certificate_key /srv/example.com/cloudflare.key;
location / {
proxy_pass http://localhost:8000;
}
}
server {
listen 443;
server_name api.example.com;
ssl on;
ssl_certificate /srv/example.com/cloudflare.pem;
ssl_certificate_key /srv/example.com/cloudflare.key;
location / {
proxy_pass http://localhost:8080;
}
}
I have opened for all TCP ports on DigitalOcean, and if I try to open MyDigitalOceanIPv4:8000 in my browser then my website (hosted in a Docker container) successfully loads. However, if I try to open my website "example.com" then I get Cloudflare's 521 web server is down message.
I have also verified that the Cloudflare SSL key paths and content are correct, nginx -t shows no errors, and I've made sure to restart nginx after making changes.
I have also tried to whitelist Cloudflare's IPs using my Nginx config file but it didn't work.
If I try to telnet MyDigitalOceanIPv4 443 or 80 then I get telnet: Unable to connect to remote host: Connection refused.
Inside my DigitalOcean instance I have tried to curl http://localhost:8000 which successfully prints my website content.
I suspect there's some DigitalOcean setting I need to configure, or there's something wrong with my Nginx file (even though I've successfully used same Nginx config on a different cloud provider), but feel like I've tried everything..

How to test nginx subdomains on localhost

I want to test nginx subdomains before uploading config to the server. Can i test it on localhost? I try
server {
listen 80;
server_name localhost;
location / {
proxy_pass http://localhost:8080;
}
}
server {
listen 80;
server_name sub.localhost;
location / {
proxy_pass http://localhost:8080/sub;
}
}
And it does not work. Shoulld i change my hosts file in order to make it work? Also, after uploading site to the server should i change DNS records and add sub.mydomain.com?
Yes, add '127.0.0.1 sub.localhost' to your hosts file. That sub has to be resolved somehow. That should work.
Then once you're ready to go to the net, yes, add an a or cname record for the subdomain sub.
When I use proxy_pass I also include the proxy.conf from nginx.
http://wiki.nginx.org/HttpProxyModule
In Linux based OS just to edit as sudo /etc/hosts file and change 127.0.0.1 localhost to 127.0.0.1 *.localhost.
So at /etc/nginx/sites-enabled/<environment>/<your_project_name> edit server_name key as <subdomain>.localhost.
Reload nginx and networking service.
$ sudo service nginx reload
$ sudo service networking reload
And then try http://<subdomain>.localhost at url bar.
It works for me.
UPDATE
In my opinion, a better solution is creating a virtual server that only responds if subdomain doesn’t exist, at /etc/nginx/sites-enabled/development/default, as default server (remember that you can define only one server as default).
server {
listen 80 default_server;
root /var/www/html/errors/404;
server_name *.localhost *.<host-name>;
location / {
index subdomain.html;
}
}
Make sure that in nginx.conf (generally at /etc/nginx/nginx.conf) contain include /etc/nginx/sites-enabled/**/*; to this virtual server work. If not, put it and then run $ sudo service nginx reload.
In this case isn't necessary put *.localhost in /etc/hosts, but only localhost.
For your public webserver with its own domain name, you just need to add a Canonical name using a CNAME record in your DNS configuration:
CNAME * example.com.
Once this is done, set your nginx setting
server_name *.example.com example.com;
In your local setup you can keep the same configuration for nginx but unless you have a local DNS setup, you will have to edit your /etc/hosts file and add each subdomain manually. wildcards don't work in the /etc/hosts file.
127.0.0.1 abc.example.com def.example.com ghi.example.com
It is generally recommended to use .local as the namespace for your local domains.
With an Nginx configuration like shown by the OP, all that is needed is to configure the local DNS resolution. I run Linux containers on a VM with a local DHCP IP but test them on Windows 10 browsers.
The DNS configuration can be done by editing "C:\Windows\System32\drivers\etc\hosts" as Administrator.
192.168.100.50 sub.example.local
192.168.100.50 example.local
Of course, use 127.0.0.1 or other appropriate IP as needed.

Resources