Nginx uWSGI link server_name to domain for flask application - nginx

I have written a Flask website which I hosted with waitress on a Ubuntu 20.04 VM server at port 5000, but now I'd like to do it more properly with uWSGI/Nginx.
To learn uWSGI/Nginx I am following this tutorial: https://www.digitalocean.com/community/tutorials/how-to-serve-flask-applications-with-uwsgi-and-nginx-on-ubuntu-20-04
Here in step 6 it tells my to configure Nginx as follows:
server {
listen 80;
server_name my_domain www.my_domain;
location / {
include uwsgi_params;
uwsgi_pass unix:/home/sammy/myproject/myproject.sock;
}
}
However if I now request the webpage for my domain, it only returns the default Nginx page.
But if I "hardcode" the public IP address of my server to the server_name:
server_name: my_domain www.my_domain MY_IP
Then it does show the correct page. I however have a feeling this is not the intended way to configure the server.
When I used the old waitress server i had told my DNS server redirect to http://MY_IP:5000/, but it is now set to redirect to http://MY_IP/. (with redirect mode 302)
So my question is, how should I set up my Domain name redirect or Nginx config so that it works without a "hardcoded" ip? Or is this something where I just need to wait the 48 hours for the DNS update to propagate?
Also an auxiliary related question, how do I make the browser url bar show the domain name instead of an IP address?
Thanks in advance!

You can go through my answer, hope it helps you as well
Regarding your question for URL name in browser, it will be there once DNS name is propagating properly and it shouldn't take more than 5-10 minutes.
Remove the IP from server name, its not supposed to be entered there.

Related

Redirect domain to different ports based on subdomain - AWS

I have a EC2 instance on which I am running a React App and a domain from Route 53, for example xyz.com.
For this xyz.com I have two subdomains say www.xyz.com and demo.xyz.com.
Now, traditionally my React App serves on PORT 3000 on this instance. I have configured the IP with the PORT using nginx on my instance, something like this 192.1.1:3000. Now whenever I hit this domain (www.xyz.com) I am redirected to 192.1.1:3000.
For example, if I have two versions of my app called dev and prod. dev serves on PORT 3000 and prod serves on PORT 3002.
I want to www.xyz.com to redirect to 3000 and demo.xyz.com redirect to 3002. Both of these are from the same DNS provider.
Is there a away to achieve this?
try this way:
server {
server_name www.xyz.com;
location / {
proxy_pass http://192.1.1:3000;
}
}
server {
server_name demo.xyz.com;
location / {
proxy_pass http://192.1.1:3002;
}
}
( add extra parameters if you want to add regarding the request, header etc )
I hope this answer helps you.
Feel free to comment if you get any errors in this and don't forget to mention the answer as accepted if it works. It'll help the others who is looking for the silimar answer.

NGINX server-name and root for a webserver on a local network without any DNS and without configuring etc/hosts on the client

I am completely new to Nginx and php. I have a Baikal self-hosted webserver on my local network and I do not use a DNS. I would like to use it for synchronizing contacts and calendars with my PC and my Android phone.
I have read Nginx tutorial and googled a lot but I still cannot figure out what to use as server-name in nginx and what to use as URL for the client.
I tried :
server_name baikal in Nginx and http://baikal as URL. This works if etc/hosts on the client PC includes baikal. It fails otherwise.
without configuring etc/hosts on the client I tried :
server_name baikal 192.168.1.27/baikal URl
in the client : http://192.168.1.27/baikal produces a 404 error and in the access log Nginx looks for /baikal
What should I use as server name and as url?
On server side
/etc/nginx/sites-available/baikal file must listen on ip address
server {
listen 192.168.1.27:80;
server_name baikal;
root /var/www/baikal;,....
On client side
just type on your browser the ip address 192.168.1.27 and it works

Redirect to internal local ip and port without using /etc/hosts (nginx)

I have a diy (poor man's) NAS and I can access the file-browser in my home-network by using the ip: 192.168.0.2:1111
I could modify the /etc/hosts in each of my devices to redirect my-fancy-filebrowser-url.com to 192.168.0.2:1111.
However, I want to find an alternative that does not involve modifying the /etc/hosts of each device in my network. I do not want to set up a local dns server either as it will probably slow down the resolution of internet domains, I am using 8.8.8.8 or 1.1.1.1 to resolve domain names quicker.
One of those alternatives I found out, is by using nginx. I have purchased a domain name, let's call it mydomain.com and I have an ipv6 VPS server. I have used cloudflare to redirect a url to my server ipv6 address and I have installed nginx to my VPS and I have created this config file:
http {
# redirect to my router page
server {
listen [d6b6:8760:97ec:ea7a:562c:c954:bb8d:6e41]:80;
return 302 http://192.168.0.1;
}
# redirect to filebrowser
server {
listen [d6b6:8760:97ec:ea7a:562c:c954:bb8d:6e42]:80;
return 302 http://192.168.0.2:1111;
}
}
The redirect to my router admin page is working perfectly as expected (for anyone interested I pointed cloudflare subdomain.mydomain.com to the ipv6 address). But the filebrowser one is not. I suspect it is because I am trying to specify a port to redirect to. Is it possible to do something like this with nginx? Or is there any better alternative that does not involve modifying /etc/hosts or setting your own dns server?
Edit: my bad, I was actually inputting the ipv6 address incorrectly in cloudflare. It was missing 1 digit so it was never going to work. I corrected the ip and it works good. The accepted answer does it more cleverly with urls instead of hardcoding the ipv6 which is a good idea! Just note that if you are using a ipv6 server then you are going to listen in the [::]:80 port
Remove the IPv6 addresses in the listen directive and add server_name directives instead:
http {
# redirect to my router page
server {
listen 80;
server_name router.mydomain.com;
return 302 http://192.168.0.1;
}
# redirect to filebrowser
server {
listen 80;
server_name filebrowser.mydomain.com;
return 302 http://192.168.0.2:1111;
}
}
I do not want to set up a local dns server either as it will probably slow down the resolution of internet domains
This is probably a wrong assumption. Something like dnsmasq is able to resolve local names and forward all other DNS queries to upstream servers (like 8.8.8.8 or 1.1.1.1), caching the results. So when setup properly you wouldn't need a domain or a VPS in this case.

How to redirect trafic to live website if https is provided?

My localhost running on http://localhost:8080. Now, I have a requirement like this, whenever I type http://www.mywebsite.com, it should load my localhost and if I type https://www.mywebsite.com, it should load the live website.
To achieve this I tried the hosts(/etc/hosts) file and Nginx but it also stops loading the live website in my system.
Host file content:
127.0.0.1 www.mywebsite.com
nginx config
server {
listen 80;
server_name www.mywebsite.com;
location / {
proxy_pass http://127.0.0.1:8080;
}
}
Completely agree with the other answers, mapping from nginx on a remote host to your localhost can be difficult unless you know the public IP address of your local machine, ideally it should be static.
Alternatives
I would encourage giving a try to some proxy tools that can be installed on your local machine, i.e. Charles Proxy and its Map Remote feature.
Once installed, follow these steps:
Install and trust the root certificate Help -> SSL Proxying -> Install Charles Root Certificate
Enable Map Remote feature Tools -> Map Remote -> [x] Enable Map Remote
Add a new rule, e.g. http://www.mywebsite.com -> http://localhost:8080
Now you're ready to test:
Navigate to http://www.mywebsite.com (you should see results from your localhost, proxy took over)
Navigate to https://www.mywebsite.com (you should see results from your remote server)
Map Remote - Rule
Map Remote - Result
You need several pieces to make this work. Thinking through the steps of how a request could be handled:
DNS for www.mywebsite.com points to a single IP, there's no way around that. So all requests for that host, no matter the protocol, will come in to the machine with that IP, the public server.
So we need to route those requests, such that a) https requests are handled by nginx on that same machine (the public server), and b) http requests are forwarded to your local machine. nginx can do a) of course, that's a normal config, and nginx can also do b), as a reverse proxy.
Now the problem is how to route traffic from the public server to your local machine, which is probably at home behind a dynamic IP and a router doing NAT. There are services to do this but to use your own domain is usually a paid feature (eg check out ngrok, I guess Traefik probably handles this too, not sure). To do it yourself you can use a reverse SSH tunnel.
To be clear, this routes any request for http://www.mywebsite.com/ to your local machine, not just your own requests. Everyone who visits the http version of that site will end up hitting your local machine, at least while the tunnel is up.
For 1, you just need your DNS set up normally, with a single DNS record for www.mywebsite.com. You don't need any /etc/hosts tricks, remove those (and maybe reboot, to make sure they're not cached and complicating things).
For 2, your nginx config on the public server would look something like this:
# First the http server, which will route requests to your local machine
server {
listen 80;
server_name www.mywebsite.com;
location / {
# Route all http requests to port 8080 on this same server (the
# public server), which we will forward back to your localhost
proxy_pass http://127.0.0.1:8080;
}
}
# Now the https server, handled by this, public server
server {
listen 443 ssl;
server_name www.mywebsite.com;
# SSL config stuff ...
# Normal nginx config ...
root /var/www/html
location / {
# ... etc, your site config
}
}
The nginx config on your local machine should just be a normal http server listening on port 8080 (the port you mentioned it is running on). No proxying, nothing special here.
For 3), lastly, we need to open a tunnel from your local machine to the public server. If you are on Linux, or macOS, you can do that from the command line with something like this:
ssh user#www.mywebsite.com -nNT -R :8080:localhost:8080 &
If you're on Windows you could use something like PuTTY or the built in SSH client on Win 10.
The important parts of this are (copied from the SSH manpage):
-N Do not execute a remote command. This is useful for just forwarding ports.
-R Specifies that connections to the given TCP port or Unix socket on the remote
(server) host are to be forwarded to the local side.
The -R part specifies that connections to remote port 8080 (where nginx is routing http requests) should be forwarded to localhost port 8080 (your local machine). The ports can be anything of course, eg if you wanted to use port 5050 on your public server and port 80 on your local machine, it would instead look like -R :5050:localhost:80.
Of course the tunnel will fail if your public IP address (on your localhost side) changes, or if you reboot, or your local wifi goes down, etc etc ...
NOTE: you should also be aware that you really are opening your local machine up to the public internet, so will be subject to all the same security risks that any server on the public internet faces, like various scripts probing for vulnerabilities etc. Whenever I use reverse tunnels like this I tend to leave them up only while developing, and shut them down immediately when done (and of course the site will not work when the tunnel is down).
As somebody said above but in different words: I don't really get why you want to access two different locations with basically the same address (different protocols). But dude, who are we to tell you not to do it? Don't let anything or anyone stop you! 😉😁
However, we some times need to think outside the box and come up with different ways to achieve the same result. Why don't you go to your domain provider and set up something like this:
Create a subdomain (check if you need to set an A record for your domain) so you can have something like https://local.example.com/.
Forward the new subdomain to your local IP address (perhaps you need to open/forward ports on you router and install DDClient or a similar service to catch your dynamic local/public IP and send it to your domain provider).
Leave your #/naked record pointing to your website as it is.
Whenever you access: https://www.example.com or http://www.example.com, you'll see your website.
And if you access https://local.example.com or http://local.example.com, you'll access whatever you have on your local computer.
Hope it helps, or at least, gives you a different perspective for a solution.
You have to create or it may be already there in your nginx config files, a section for listen 443 (https).
// 443 is the default port for https
server {
listen 443;
....
}
Whatever solution you pick, it should only work exactly once for you. If you configure your live site correctly, it should do HSTS, and the next time you type "http://www.mywebsite.com" your browser will GET "https://www.mywebsite.com" and your nginx won't even hear about the insecure http request.
But if you really, really want this you can let your local nginx proxy the https site and strip the HSTS headers:
server {
listen 443;
server_name www.mywebsite.com;
proxy_pass https://ip_of_live_server;
proxy_set_header Host $host;
[... strip 'Strict-Transport-Security' ...]
}
Of course you will need your local nginx to serve these TLS sessions with a certificate that your browser trusts. Either adding a self-signed Snake Oil one to your browser, or... since we are implementing bad ideas... add a copy of you live secret key material to your localhost... ;)
You can do this by redirecting HTTP connections on your live site to localhost. First remove the record you have in your hosts file.
Then add the following to your live site's nginx.conf.
server {
listen 80;
server_name www.mywebsite.com;
location / {
# change this to your development machine's IP
if ($remote_addr = 1.2.3.4) {
rewrite ^ http://127.0.0.1:8080;
}
}
}

Problem redirecting subdomain to nginx web server

Problem explanation
I want to show one service in my domain and another different service in my subdomain, so I purchased a domain and tried to link it to my Nginx web server.
I have buyed the domain in google domains. And uploaded my web application to a Nginx web server.
When I run my domain for example www.balls.com it's redirected perfectly, but when I try to redirect to my subdomain, there is no way to make it work, I have tried different configurations and received 2 different errors:
-DNS doesn't exist (Checked with DNScheck).
-Google DNS page error.
google domain service config:
Nameservers:
-Using the Google Domains nameservers.
DNSSEC
-Your domain has DNSSEC enabled.
Registered hosts
red.balls.com-->111.11.11.11 (My server Address).
Synthetic records
Domain forward
balls.com, www.balls.com → 111.11.11.11 (My server Address).
Custom resource records (Extracted from exported records)
balls.com.balls.com. 3600 IN A 111.11.11.11
red.balls.com.balls.com. 3600 IN A 111.11.11.11
www.balls.com. 3600 IN A 111.11.11.11
www.balls.com.balls.com. 3600 IN A 111.11.11.11
nginx services config:
Subdomain service:
server {
listen 80;
root /var/www/redballs.com;
index index.html index.htm;
server_name red.balls.com;
}
Subdomain service:
server {
listen 80;
root /var/www/balls.com;
index index.html index.htm;
server_name balls.com;
}
Thanks for your read time, a simple comment pointing what I'm doing wrong will be very appreciated, as I have finished my application but I'm unable to set up this subdomain. Thanks again.
that sounds a lot like a DNS problem to me.
Did you add a DNS record for the subdomain?
Each hostname you want to use needs a mapping in DNS to the IP addresses of the host or a CNAME pointing to another name.
It is a bit hard to debug a DNS Problem without seeing thr actual data.
Sidenote: www.balls.com.balls.com. looks to me like you forgot a dot when creating that entry. In DNS a name always ends with a dot in the configuration (or zone file) if you omit it, the domain name is usually automatically appended.

Resources