Nginx: Difference between revisions

Jump to navigation Jump to search
509 bytes added ,  14 March 2022
Add syntax highlighting.
imported>Sjwhitak
(Add flask)
imported>Sjwhitak
(Add syntax highlighting.)
 
Let's say you only want to return a single file: <code>This is intentionally left blank.</code>, then in your <code>/etc/nginx/nginx.conf</code> configuration, you can add:
 
location / {
<syntaxhighlight lang="nginx">
return 200 'This is intentionally left blank.'
location / {
}
return 200 'This is intentionally left blank.'
}
</syntaxhighlight>
 
If that's all you want, don't use nginx; it'd be easier to write a [https://funprojects.blog/2021/04/11/a-web-server-in-1-line-of-bash/ single-lined Bash script] to run a single page.
 
You own the domain <code>example.com</code> and you want to serve your amazing blog to the Internet. Create the file: <code>/etc/nginx/conf.d/example.com.conf</code> or <code>/etc/nginx/sites-enabled/example.com.conf</code> or just edit <code>/etc/nginx/nginx.conf</code> directly. You'll need to point your DNS records to the IP that nginx is running.
<syntaxhighlight lang="nginx">
 
server {
server_name example.com;
root /var/www/html;
index index.html;
listen 80;
listen [::]:80;
}
</syntaxhighlight>
The [https://nginx.org/en/docs/http/ngx_http_core_module.html#server_name <code>server_name</code>] tells nginx to use only this domain. For example, when there are subdomains or multiple domains running on a single nginx instance, you'll want correctly get the right content corresponding to each domain.
 
Say you want a blog, a forum, a wiki, a streaming service, etc. If you want each of these to be in different root folders to keep these neat:
 
<syntaxhighlight lang="nginx">
server {
server {
root /var/www/blog;
root index index.html/var/www/blog;
index index.html;
server_name blog.example.com;
server_name blog.example.com;
listen 80;
listen [::]:80;
listen [::]:80;
}
}
server {
server {
root /var/www/phpbb;
root index index.html/var/www/phpbb;
index index.html;
server_name forum.example.com;
server_name forum.example.com;
listen 80;
listen [::]:80;
listen [::]:80;
}
}
server {
server {
root /var/www/mediawiki;
root index index.html/var/www/mediawiki;
index index.html;
server_name wiki.example.com;
server_name wiki.example.com;
listen 80;
listen [::]:80;
listen [::]:80;
}
}
</syntaxhighlight>
Please note that you'll need [https://shell.lug.mtu.edu/wiki/index.php?title=Nginx&action=submit#fastcgi php add-ons] and more configurations to have [https://www.phpbb.com/ phpbb] and [https://www.mediawiki.org/wiki/MediaWiki mediawiki] to run, but this is just a basic example.
 
If you want to protect your server from people access your IP (typically if they're crawling via IPs, they're probably not up to something good), you can up a configuration:
<syntaxhighlight lang="nginx">
server {
server {
listen 80;
listen [::]:80;
listen server_name _[::]:80;
server_name return 444_;
return 444;
}
}
</syntaxhighlight>
that rejects them.
 
 
To use a reverse proxy, remember the port your service is running on, and then add it into your nginx configuration:
<syntaxhighlight lang="nginx">
<pre>
server {
server_name example.com;
}
}
</syntaxhighlight>
</pre>
This is a simple set up for an executable running on port 8080. I would ensure your firewall does not allow outside access to these ports, else anyone can directly access the service without nginx's protection.
 
Suppose you want multiple webapps, then:
<syntaxhighlight lang="nginx">
<pre>
server {
server_name example.com;
...
}
</syntaxhighlight>
</pre>
If someone navigates to <code>example.com</code>, nginx serves them data from the service running on port <code>8080</code>.
 
 
Running a simple flask server can be done in Python:
<syntaxhighlight lang="python">
<pre>
from flask import Flask
app = Flask(__name__)
 
app.run(port=9999)
</syntaxhighlight>
</pre>
 
And in nginx, the configuration should be:
<syntaxhighlight lang="nginx">
<pre>
server {
location /flask {
}
}
</syntaxhighlight>
</pre>
 
== <code>fastcgi</code> ==
In your nginx configuration, you'll need to set up:
 
<syntaxhighlight lang="nginx">
server {
server {
listen 80;
listen 80;
server_name example.com;
server_name example.com;
root /var/www/;
root index index.php/var/www/;
index location ~ \index.php$ {;
location ~ try_files \.php$uri = 404;{
try_files $uri = 404;
fastcgi_pass unix:/var/run/php5-fpm.sock;
fastcgi_pass fastcgi_index indexunix:/var/run/php5-fpm.phpsock;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
include fastcgi_params;
}
}
}
}
</syntaxhighlight>
This allows any php file to be passed through the <code>fastcgi</code> module, which executes the php file in accordance to <code>/etc/php/<version num>/fpm/php-fpm.conf</code> (note that the bottom of <code>php-fpm.conf</code> includes <code>pool.d/www.conf</code> which is actually where the user configurations are set up).
 
= TLS =
In order to get an [https://www.openssl.org/ https] in your domain, you need to set up SSL (HTTPS = HTTP SSL), which is now changed to TLS. In nginx, running over https is simple:
<syntaxhighlight lang="nginx">
server {
server {
listen 443 ssl; # IPv4
listen [::]:443 ssl; # IPV6IPv4
listen [::]:443 ssl; # IPV6
# ... rest of configuration
# ... rest of configuration
}
}
</syntaxhighlight>
If you've got a domain name (<code>example.com</code>), this won't get browsers happy. This configuration has an SSL connection, but it does not have a certificate yet. You can generate your own certificate using a [https://stackoverflow.com/a/41366949/14089008 self-signed certificate], but no one is going to trust this self-signed certificate.
 
Instead, we can use a free service, [https://letsencrypt.org/ Let's Encrypt], [https://dehydrated.io/ Dehydrated], or [https://zerossl.com/ ZeroSSL]. Let's Encrypt is the most common, and is a straightforward set up.
<syntaxhighlight lang="bash">
apt install certbot python3-certbot-nginx
apt install certbot python3-certbot-nginx
</syntaxhighlight>
Once certbot is installed, ensure your domain is pointed to the correct nginx server, then run:
<syntaxhighlight lang="bash">
certbot --nginx -d example.com -d ...
certbot --nginx -d example.com -d ...
</syntaxhighlight>
Where you can keep chaining <code>-d <domain></code> for each domain you have. <code>python3-certbot-nginx</code> will find the right nginx configuration to call, and <code>certbot</code> will make sure you've got rights to that domain. You can't just run certbot on google.com, you need to own the domain and the IP that domain is connected to. At this point, <code>python3-certbot-nginx</code> should have edited your nginx configuration to have certbot's certificate auto-configured. If you force https, you'll see:
<syntaxhighlight lang="nginx" line>
1 server {
server {
2 listen 443 ssl;
3 listen [::]:443 ssl;
listen [::]:443 ssl;
4 ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
5 ssl_certificate_keyssl_certificate /etc/letsencrypt/live/example.com/privkeyfullchain.pem;
6 includessl_certificate_key /etc/letsencrypt/options-ssl-nginxlive/example.com/privkey.confpem;
7 ssl_dhparaminclude /etc/letsencrypt/options-ssl-dhparamsnginx.pemconf;
ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;
8 root /var/www;
root /var/www;
9 }
}
10 server {
server {
11 if ($host = example.com) {
if ($host = example.com) {
12 return 301 https://$host$request_uri;
return 301 https://$host$request_uri;
13 }
14 listen 80;}
15 listen [::]:80;
listen [::]:80;
16 server_name example.com;
server_name example.com;
17 return 404;
18 return root /var/www404;
root /var/www;
19 }
}
When you request <code>example.com</code>, you'll pass through the server starting on line <code>9</code>, as specified by <code>server_name</code> on line <code>15</code>.
</syntaxhighlight>
When you request <code>example.com</code>, you'll pass through the server starting on line <code>10</code>, as specified by <code>server_name</code> on line <code>16</code>.
 
You'll get redirected to the https version of <code>example.com</code>, specified by line <code>1112</code>, which sends you to the server starting on line <code>1</code>.
 
These two servers are loading the same data, both are pointing to <code>/var/www</code>, but one runs http, while the other runs https.
 
Let's Encrypt allows you to not redirect to https, which gives you:
<syntaxhighlight lang="nginx">
 
server {
listen 80;
listen [::]:80;
listen 443 ssl;
listen [::]:443 ssl;
ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
include /etc/letsencrypt/options-ssl-nginx.conf;
ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;
root /var/www;
}
</syntaxhighlight>
== ACME ==
Automatic certificate management environment. Certificates expire after a period of time to prevent certificates being valid when your site or server has been dead for a long time.
 
[https://letsencrypt.org/ Let's Encrypt]'s certificates are valid for 3 months, so you can update this every 3 months when it expires. Or, have a cronjob do it for you! Type <code>crontab -e</code> and then add:
 
0 12 * * * /usr/bin/certbot renew --quiet
 
Anonymous user

Navigation menu