Adding GDPR Compliance to My Rails App and Technical Blog

GDPR EU regulations represented by a hammer

New data privacy GDPR EU regulations are going live in less than two weeks. In this blog post, I will describe actions I took to add GDPR compliance to my Ruby on Rails SAAS app and this blog itself.

Your apps must comply with new regulations even if you are not located in the EU. It is enough that you have European users.

Disclaimer: I am not a lawyer, and this article does not constitute legal advice.

What needed GDPR compliance

General Data Protection Regulation focuses on so-called Personally Identifiable Information (“PII”). It is every piece of information which allows you to directly or indirectly determine user’s identity.

After auditing my apps I found out that following piece of data that they collect can be classified as PII and should be taken care of:

  • IP addresses stored in application logs
  • IP addresses collected by Google Analytics
  • email addresses of my mailing list subscribers
  • email addresses of users who purchased Abot subscription

I will explain what I did with each of those data types:

Logs and GDPR

NGINX logs rotation

NGINX access logs contain IP address of the users. According to the regulation, it is a piece of information which can be used to identify users and therefore should be protected and removed when no longer needed.

To comply with new regulations I added an information to Abot privacy policy informing users that their IP addresses are collected and stored for maintenance purposes.

I decided to retain access logs for two weeks to be able to investigate if anything goes wrong with the app. To automatically remove all the NGINX logs older than 14 days, just add this line to /etc/crontab file on your VPS server:

@daily root find '/var/log/nginx/' -mtime +14 -type f -delete

How long you want to keep your access logs depends on your particular use case. New regulations don’t specify the “correct” retention period.

Anonymize NGINX access logs

Optionally you could consider anonymizing NGINX access logs. I would not bet my 2 million €€ GDPR infringement fine on that, but logs without IP might no longer be interpreted as Personally Identifiable Information.

To remove users IP from access logs you can use the following NGINX directives in http config context:

log_format anonymized ' - [$time_local]  '
    '"$request" $status $body_bytes_sent '
    '"$http_referer" "$http_user_agent" $request_time';

access_log /var/log/nginx/access.log anonymized;

Rails app logs

Standard application logs might contain information which allows idenitfying users.

In Rails apps you can limit what is included in application logs by adding an initializer file:


Rails.application.config.filter_parameters += %i(
  password text
  user_name user_id
  token payload

Obviously, it is always a tradeoff between logs usefulness and anonymity.

Location of your Rails application logs storage depends on your infrastructure configuration. I use Dokku. In that case, logs are stored in this path:


To obtain the CONTAINER_ID you have to run the following command:

dokku ps

If your particular use case requires you to keep your logs for a longer period of time you are probably exporting them to Amazon S3 buckets. In that case double check that your bucket is located in a European Union AWS data center. GDPR treats EU located servers as more secure. Also make sure to encrypt contents of the bucket.

Google Analytics privacy and GDPR

Google Analytics default settings include users IP address. You can increase the privacy of Google Analytics tracking by adding the following line of code:

ga('set', 'anonymizeIp', true);

It anonymizes the requests IPs, so that they no longer allow you to identify the users. Keep in mind that adding this setting reduces the geographic accuracy of your analytics data.

Static landing pages

I’ve been using Google Analytics on landing page for my iOS app:

I decided that user tracking on this site has little value for me and removed it all together. I deleted the tracking code and scheduled data deletion in Google Analytics panel. I did not feel like adding terms and policy for such simple static page.

This blog and Abot landing page

I still want to track traffic on my technical blog and the landing page of my Abot. It required me to make changes to Abot terms and privacy policy and to add terms to my blog.

I’ve added information about which information is stored exactly. Terms also explain that users can contact me with a request to delete all their data. I’ve also added automatic data removal to Abot, for teams who deleted bot integration from their Slack teams.

Blog and Abot are not very complex in terms of personal data stored. You can check out terms of Konfeo online event registration system to see how it looks in a more advanced software project.

Monthly subscription payments

This project uses subscription based payments after 2 weeks long trial is over. Paddle is my payments provider. They have a GDPR compliant checkout form.

Users can optionally check if they allow me to send them marketing information and I can segment my mailings based on this attribute.

GDPR regulations meme funny

Paddle checkout form with an explicit marketing consent opt-in

Blog mailing list

I am building a mailing list on my blog using Mailchimp. They offer a GDPR compliant forms which collect optional marketing consents from users. The same as in case of Paddle I can segment my users based on whether they provided the consent and send appropriate mailings.

GDPR regulations meme funny

As for the previous subscribers, Mailchimp offers a GDPR consent email template. It allows users to update their marketing consent permission or unsubscribe.

Mailchimp GDPR consent email

You’ve probably received a couple of those recently.

GDPR regulations meme funny


I am still in the process of adding a full GDPR compliance to all my projects. It is a bit of a hassle for me as a one-man show. If you notice some serious GDPR related loopholes in what I do an advice on how to fix them is more than welcome.

Back to index