Nginx: Difference between revisions
Jump to navigation
Jump to search
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:
<syntaxhighlight lang="nginx">
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">
</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 {
root
index index.html;
server_name blog.example.com;
listen [::]:80;
}
server {
root
index index.html;
server_name forum.example.com;
listen [::]:80;
}
server {
root
index index.html;
server_name wiki.example.com;
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 {
listen
server_name
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">
server {
server_name example.com;
}
}
</syntaxhighlight>
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">
server {
server_name example.com;
...
}
</syntaxhighlight>
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">
from flask import Flask
app = Flask(__name__)
app.run(port=9999)
</syntaxhighlight>
And in nginx, the configuration should be:
<syntaxhighlight lang="nginx">
server {
location /flask {
}
}
</syntaxhighlight>
== <code>fastcgi</code> ==
In your nginx configuration, you'll need to set up:
<syntaxhighlight lang="nginx">
server {
listen 80;
server_name example.com;
root
index
location ~
try_files $uri = 404;
fastcgi_pass
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
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 {
listen [::]:443 ssl; # IPV6
# ... 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
</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 ...
</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>
server {
listen [::]:443 ssl;
ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;
root /var/www;
}
server {
if ($host = example.com) {
return 301 https://$host$request_uri;
listen [::]:80;
server_name example.com;
root /var/www;
}
</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>
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">
</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
|