Privacy and Security "A painting on a wall..." by Tobias Tullius is licensed under Unsplash.

Nginx Logging Privacy and Security

GeekThis remains completely ad-free with zero trackers for your convenience and privacy. If you would like to support the site, please consider giving a small contribution at Buy Me a Coffee.

Below you will learn how to configure Nginx to stop logging sensitive information and help protect the privacy of your users along with protect authorization keys and query strings from being logged. Each section below outlines how to stop logging a specific page or piece of information. Multiple sections below can be combined to fully customize how you log visitors to your website.

Basics to Nginx Log Options

Before actually modifying any configuration files, here is an overview of the Nginx log options we will be using. Quickly, Nginx configuration files are generally stored in the directory /etc/nginx/, with site specific configuration options beings stored in separate files inside the directory /etc/nginx/sites-available/. The main Nginx configuration file is /etc/nginx/nginx.conf.

There are three main directives that affect logging, access_log, log_format, and error_log. Another directive that will be used frequently is the location directive; It allows directives to be set for a particular page instead of having it set site or server wide. Nginx directives have to be set in their correct context for them to work. The access_log and error_log directives can be set in the http, server, and location context. But the log_format directive has to be set in the http context, which is generally defined in the nginx.conf file. All of this information is available in the Nginx documentation.

When changing or creating the log format, you will set a name for the log format that will later be used by the access_log directive. The default log_format name used is “combined” and it cannot be overwritten. The access_log directive then sets the file location of the log and what log format to use. It’s also possible to specify additional options for the access log, such as buffer size, flush duration, and if logs should be compressed using gzip while writing the log file.

Using the Settings Below

To keep this tutorial condensed and not to repeat the same information in every section, each section will outline the settings and directives you need to add to your Nginx configuration files. You will generally have to modify multiple files unless you want to apply settings to all Nginx web sites you are serving. The code blocks below outline the context (e.g. http, server, location) the directives must be applied to for them to work. You will want to copy the directives from inside of each context and not the context itself, except for the location context in some cases where you are only applying a directive to a specific location.

The log_format directive will always be applied in the nginx.conf file inside of the http context. As for the access_log directive, this tutorial assumes each site has unique logging and the access_log will be applied to an individual website configuration file /etc/nginx/sites-available/example.com.conf. The access_log directive will be placed inside of the server or location context. If you want all websites to use the new log format, you will set the access_log directive inside of the http context, but it’s still possible for it to be overwritten by individual websites.

Stop Logging IP Addresses

Using the below log format, you can continue logging requests on your website but not log the visitors remote IP address. Many websites that care about your privacy will not log your IP address. There are some cases where this can backfire. If your site has a security flaw and has been compromised, you will not have the IP address of the attacker. An alternative route you can take (not outlined in this tutorial) is to either delete logs after a week or remove IP address from logs after a certain amount of time.

The log format replaces the users IP address with the IP address “0.0.0.0”. This is done to allow log parsers to continue working and not to disrupt the log format.

# /etc/nginx/nginx.conf
http {
	log_format hide_ip '0.0.0.0 - $remote_user [$time_local] '
	                   '"$request" $status $body_bytes_sent '
	                   '"$http_referer" "$http_user_agent"';
}

# /etc/nginx/sites-available/example.com.conf
server {
	access_log /var/log/nginx/example.com.log hide_ip;
}

Stop Logging Sensitive URLs

When your website allows users to sign in through other services using OAuth (e.g. Google, Facebook, Twitter), the callback URL could possibly contain authorization tokens that you don’t want to end up in logs. You can stop logging specific URLs all together by using the settings below. If you would still like to log these URLs but without the query string, look at the next section.

# /etc/nginx/sites-available/example.com.conf
server {
	location /authorization {
		access_log off;
	}
}

Stop Logging Query Strings

Query strings inside of URLs can contain sensitive information, such as authorization tokens from Oauth, or some forms may submit GET requests instead of POST and show personal information in your server logs. It’s possible to stop this on your whole site or for individual pages. If your site uses SEO friendly URLs, applying this setting site wide should work fine, but in cases where pages change based on query parameters, you will want to limit what locations will use this new log format. A good example of pages would be authorization callback URLs, form processing pages, search results, etc.

# /etc/nginx/nginx.conf
http {
	log_format hide_query '$remote_addr - $remote_user [$time_local] '
	                      '"$request_method $uri $server_protocol" $status '
	                      '$body_bytes_sent "$http_referer" "$http_user_agent"';
}

# /etc/nginx/sites-available/example.com.conf
server {
	access_log /var/log/nginx/example.com.log hide_query;
}

Testing and Restarting Nginx

Once your configuration files have been modified, you will first want to test the configuration changes before applying them. Improperly configuring your files can prevent Nginx from starting, or the worse case is that the web server acts in a way it’s not supposed to. If possible, test the changes on a staging server before moving them onto your production server.

To test if the configuration files do not contain any syntax errors, you will run the command below as root or an administrative account. If there is an error, the command below will warn you and you can check the error log at /var/log/nginx/error.log for more information.

$ service nginx configtest
[ ok ] Testing nginx configuration:.

If there are no errors, you can now start Nginx with the new changes. Once you restart Nginx, check your website and verify that files are still being served correctly; also take a look at the logs and see if your changes have been applied.

$ service nginx reload

With the information above you can make other changes to the log format and set different log formats for different pages. Keeping all of your log formats similar is a good idea if you use parsers or any scripts that read your log files. It’s also important to remember that error logs may contain some of the private information you are trying to hide. It’s not possible to change the format of error logs but you can disable them, which is probably a bad idea.

Related Posts

Automatically Start Docker Container

Automatically start Docker containers when your server or computer boots using restart policies and avoiding systemd service files.

How to Train SpamAssassin

Learn about the different methods used to train SpamAssassin, along with initial spam data sources to use with SpamAssassin. Update your bayes database easily with existing data.

SpamAssassin SA-Update Tool

Learn what SpamAssassin's sa-update tool does, how it works, and if you should keep it running and modifying the configuration files on your server.

Incremental MySQL Backup with Binary Log

Learn how to properly perform an incremental MySQL backup using binary logs without having a gap between backups and overall improve the speed of database backups.