Public Nginx Server on Ubuntu
Purpose
This guide describes installing and configuring Nginx on an Ubuntu 22.04 or 24.04 server to host static websites on the public Internet.
The sites are secured using SSL/TLS with LetsEncrypt as the Certificate Authority.
GoAccess will be used to produce utilization statistics for each hosted site.
Requirements
To complete this guide, you'll need:
- an Ubuntu 22.04 or 24.04 instance running on the public Internet
- a static IP address for each hosted site. each site can have multiple DNS names
- control over the DNS resource records for the names your site(s) will use
- ssh access to the system
- root or
sudo
access
Procedure
DNS Configuration
This guide will show how to set up a website that is available at mysite.com and www.mysite.com.
Log into your DNS provider and set up A record for your domain name that points to the IP address on which you will be hosting your site.
mydomain.com. A --> 42.33.8.62
Create a second record of type CNAME that maps the 'www' hostname to your domain name.
www.mydomain.com. CNAME --> mydomain.com.
You should be able to resolve the domain name and the hostname from your local machine and get the correct IP address.
> host mydomain.com
mydomain.com has address 42.33.8.62
> host www.mydomain.com
www.mydomain.com is an alias for mydomain.com.
mydomain.com has address 42.33.8.62
Configure Firewall
If you are using Ubuntu's UFW as a firewall, allow ingress connections on ports tcp/80 (HTTP) and tcp/443 (HTTPS).
Determine if UFW is active:
If it's active, allow traffic to the system on HTTP and HTTPS ports:
View the UFW ruleset to ensure your rules were applied:
root@www:~ # ufw status
Status: active
To Action From
-- ------ ----
22/tcp ALLOW Anywhere
Nginx Full ALLOW Anywhere
443 ALLOW Anywhere
22/tcp (v6) ALLOW Anywhere (v6)
Nginx Full (v6) ALLOW Anywhere (v6)
443 (v6) ALLOW Anywhere (v6)
Install Nginx
The operating system's repositories include Nginx. Install it by running apt
:
The Nginx configuration file is /etc/nginx/nginx.conf
. Don't edit this file, or when apt upgrade
is run, differences will be complained about when Nginx is upgraded. Instead of editing the file directly, add new configuration options and overrides to /etc/nginx/conf.d/myconfig.conf
. Usually, leaving all of the defaults is fine.
Website configuration files for Nginx on Ubuntu are in /etc/nginx/sites-available/
. To enable a site, create a symlink to it in /etc/nginx/sites-enabled/
. For example:
Restart Nginx after changing configuration parameters to pick up the changes:
Disable Log Rotation
Ubuntu's Nginx package installs a log rotation script that rolls and compresses logs daily. Disable this by backing up the file that rotates the Nginx logs:
Disable Default Site
Nginx ships with a default "Hello World!" site. Disable this by deleting the symlink in /etc/nginx/sites-enabled/
and restart Nginx to pick up the changes:
# disable the default site
rm -f /etc/nginx/sites-enabled/default
# restart nginx
systemctl restart nginx
Install Site Data
Nginx expects each hosted site maps to a directory on the filesystem. Multiple names can map to a site.
In this example, mysite.com
and www.mysite.com
will both serve the same website. Both names will be served from a single directory on the filesystem.
Create Webroot
Do not put websites in directories like /home/
or under them. Create a directory under the root of the filesystem named 'webroot' to store the site data in:
Create Website Directories and Users
Each hosted site's data will be contained in a sub-directory under /webroot/
.
Create the directory that will hold the website data for the hosted site:
Upload Data and Set Ownership
Change the ownership of the website container directory if a non-root user should be able to update the website data:
Upload the website data to the server's directory using rsync
over ssh
or whatever method you are comfortable with:
# on local system
cd path/to/website-data
# upload data to webroot
rsync -e ssh -avP --delete . [email protected]:/webroot/www.mysite.com/
Write Nginx Configs
Configure Nginx to host the website.
If you are adding a new website to an existing Nginx server, ensure your site's IP address is unique and not being used to host other sites on the server.
Create a new file named /etc/nginx/sites-available/www.mysite.com
with the contents:
server {
server_name mysite.com www.mysite.com;
root /webroot/www.mysite.com;
listen 42.33.8.62:80;
access_log /var/log/nginx/www.mysite.com_access.log;
error_log /var/log/nginx/www.mysite.com_error.log;
error_page 500 502 503 504 /50x.html;
}
Enable the site's configuration by creating a symlink in /etc/nginx/sites-enabled/
:
Restart Nginx to pick up the configuration changes:
Testing with No SSL/TLS
You should now be able to reach your site using HTTP.
Tail your website's Nginx logs to verify Nginx is serving your requests and that there are no errors:
Secure Site(s) with SSL/TLS
Install Certbot
Certbot is the EFF's tool to interact with the free SSL/TLS provider LetsEncrypt.
LetsEncrypt provides free SSL certificates to publicly accessible websites.
Install Certbot from Ubuntu's repositories:
Secure a Site with LetsEncrypt
Run Certbot in a shell as the root user to request an SSL certificate from LetsEncrypt:
Answer any questions the script asks you. Note the expiration date of the newly signed certificate for your site.
Re-run the command to request an updated certificate within a month of its expiration.
Once complete, your Nginx configuration file for your site in /etc/nginx/sites-enabled/www.mysite.com
will have modifications that enables HTTPS and rewrites HTTP requests to HTTPS.
Restart Nginx to pick up the changes:
Testing with SSL/TLS
Your site should be available via HTTPS. Accessing your site via HTTP should rewrite the request to HTTPS. If Nginx doesn't rewrite HTTP to HTTPS requests for your site, ensure these lines exist in your site's configuration file in /etc/nginx/sites-available/www.mysite.com
:
server {
if ($host = www.mysite.com) {
return 301 https://$host$request_uri;
} # managed by Certbot
if ($host = mysite.com) {
return 301 https://$host$request_uri;
} # managed by Certbot
Website Statistics
Install GoAccess
GoAccess is a nice and clean website statistics generator.
Install it by running:
Configure GoAccess
GoAccess's configuration file is /etc/goaccess/goaccess.conf
, but this can be left alone. The default values work well enough.
GoAccess is run for each hosted site. It reads in the website's logfile and produces a static HTML report. The report will be written to _report/
in the website's webroot. Go to www.mysite.com/_report/ to access it.
To run GoAccess on a single site, run:
# make sure the report dir exists
mkdir /webroot/www.mysite.com/_report
# run goaccess on the site's log file
goaccess /var/log/www.mysite.com --log-format=COMBINED \
-o /webroot/www.mysite.com/_report/index.html
If multiple sites are being hosted, loop through each one in a bash script:
#!/usr/bin/env bash
DATE=$(date '+%Y%m%d')
LOGDIR=/var/log/nginx
# a list of dirs in /webroot
SITES='www.mysite.com www.otherhostedsite.com'
for SITE in ${SITES[@]}; do
OUTDIR=/webroot/${SITE}/_reports
goaccess ${LOGDIR}/${SITE}_access.log --log-format=COMBINED -o ${OUTDIR}/${SITE}.html;
done
Reports will be written to the hosted site's base URL with /_report
added to it. Adjust as needed.
Cron Jobs for GoAccess
Make cron run the report script at the top of every hour.
If there is only a single hosted site, add a file named /etc/cron.d/update-webstats
with the contents:
# run webstats for www.mysite.com
0 * * * * root /usr/sbin/goaccess /var/log/nginx/www.mysite.com --log-format=COMBINED -o /webroot/www.mysite.com/_report/index.html
If there are multiple hosted sites, save the script above into /root/bin/update-webstats.sh
, set it executable with chmod +x /root/bin/update-webstats.sh
, and add a file named /etc/cron.d/update-webstats
with the contents: