How To Create a Self-Signed SSL Certificate for Apache in Ubuntu 16.04
How To Create a Self-Signed SSL Certificate for Apache in Ubuntu 16.04

How To Create a Self-Signed SSL Certificate for Apache in Ubuntu 16.04

PostedApril 21, 2016 769.7k views Ubuntu Apache Security Ubuntu 16.04


TLS, or transport layer security, and its predecessor SSL, which stands for secure sockets layer, are web protocols used to wrap normal traffic in a protected, encrypted wrapper.

Using this technology, servers can send traffic safely between the server and clients without the possibility of the messages being intercepted by outside parties. The certificate system also assists users in verifying the identity of the sites that they are connecting with.

In this guide, we will show you how to set up a self-signed SSL certificate for use with an Apache web server on an Ubuntu 16.04 server.

Note: A self-signed certificate will encrypt communication between your server and any clients. However, because it is not signed by any of the trusted certificate authorities included with web browsers, users cannot use the certificate to validate the identity of your server automatically.

A self-signed certificate may be appropriate if you do not have a domain name associated with your server and for instances where the encrypted web interface is not user-facing. If you do have a domain name, in many cases it is better to use a CA-signed certificate. You can find out how to set up a free trusted certificate with the Let’s Encrypt project here.


Before you begin, you should have a non-root user configured with sudo privileges. You can learn how to set up such a user account by following our initial server setup for Ubuntu 16.04.

You will also need to have the Apache web server installed. If you would like to install an entire LAMP (Linux, Apache, MySQL, PHP) stack on your server, you can follow our guide on setting up LAMP on Ubuntu 16.04. If you just want the Apache web server, skip the steps pertaining to PHP and MySQL in the guide.

When you have completed the prerequisites, continue below.

Step 1: Create the SSL Certificate

TLS/SSL works by using a combination of a public certificate and a private key. The SSL key is kept secret on the server. It is used to encrypt content sent to clients. The SSL certificate is publicly shared with anyone requesting the content. It can be used to decrypt the content signed by the associated SSL key.

We can create a self-signed key and certificate pair with OpenSSL in a single command:

  • sudo openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout /etc/ssl/private/apache-selfsigned.key -out /etc/ssl/certs/apache-selfsigned.crt

You will be asked a series of questions. Before we go over that, let’s take a look at what is happening in the command we are issuing:

  • openssl: This is the basic command line tool for creating and managing OpenSSL certificates, keys, and other files.
  • req: This subcommand specifies that we want to use X.509 certificate signing request (CSR) management. The “X.509” is a public key infrastructure standard that SSL and TLS adheres to for its key and certificate management. We want to create a new X.509 cert, so we are using this subcommand.
  • -x509: This further modifies the previous subcommand by telling the utility that we want to make a self-signed certificate instead of generating a certificate signing request, as would normally happen.
  • -nodes: This tells OpenSSL to skip the option to secure our certificate with a passphrase. We need Apache to be able to read the file, without user intervention, when the server starts up. A passphrase would prevent this from happening because we would have to enter it after every restart.
  • -days 365: This option sets the length of time that the certificate will be considered valid. We set it for one year here.
  • -newkey rsa:2048: This specifies that we want to generate a new certificate and a new key at the same time. We did not create the key that is required to sign the certificate in a previous step, so we need to create it along with the certificate. The rsa:2048 portion tells it to make an RSA key that is 2048 bits long.
  • -keyout: This line tells OpenSSL where to place the generated private key file that we are creating.
  • -out: This tells OpenSSL where to place the certificate that we are creating.

As we stated above, these options will create both a key file and a certificate. We will be asked a few questions about our server in order to embed the information correctly in the certificate.

Fill out the prompts appropriately. The most important line is the one that requests the Common Name (e.g. server FQDN or YOUR name). You need to enter the domain name associated with your server or, more likely, your server’s public IP address.

The entirety of the prompts will look something like this:

Country Name (2 letter code) [AU]:US State or Province Name (full name) [Some-State]:New York Locality Name (eg, city) []:New York City Organization Name (eg, company) [Internet Widgits Pty Ltd]:Bouncy Castles, Inc. Organizational Unit Name (eg, section) []:Ministry of Water Slides Common Name (e.g. server FQDN or YOUR name) []:server_IP_address Email Address []

Both of the files you created will be placed in the appropriate subdirectories of the /etc/ssl directory.

While we are using OpenSSL, we should also create a strong Diffie-Hellman group, which is used in negotiating Perfect Forward Secrecy with clients.

We can do this by typing:

  • sudo openssl dhparam -out /etc/ssl/certs/dhparam.pem 2048

This may take a few minutes, but when it’s done you will have a strong DH group at /etc/ssl/certs/dhparam.pem that we can use in our configuration.

Step 2: Configure Apache to Use SSL

We have created our key and certificate files under the /etc/ssl directory. Now we just need to modify our Apache configuration to take advantage of these.

We will make a few adjustments to our configuration:

  1. We will create a configuration snippet to specify strong default SSL settings.
  2. We will modify the included SSL Apache Virtual Host file to point to our generated SSL certificates.
  3. (Recommended) We will modify the unencrypted Virtual Host file to automatically redirect requests to the encrypted Virtual Host.

When we are finished, we should have a secure SSL configuration.

Create an Apache Configuration Snippet with Strong Encryption Settings

First, we will create an Apache configuration snippet to define some SSL settings. This will set Apache up with a strong SSL cipher suite and enable some advanced features that will help keep our server secure. The parameters we will set can be used by any Virtual Hosts enabling SSL.

Create a new snippet in the /etc/apache2/conf-available directory. We will name the file ssl-params.conf to make its purpose clear:

  • sudo nano /etc/apache2/conf-available/ssl-params.conf

To set up Apache SSL securely, we will be using the recommendations by Remy van Elst on the site. This site is designed to provide easy-to-consume encryption settings for popular software. You can read more about his decisions regarding the Apache choices here.

The suggested settings on the site linked to above offer strong security. Sometimes, this comes at the cost of greater client compatibility. If you need to support older clients, there is an alternative list that can be accessed by clicking the link on the page labelled “Yes, give me a ciphersuite that works with legacy / old software.” That list can be substituted for the items copied below.

The choice of which config you use will depend largely on what you need to support. They both will provide great security.

For our purposes, we can copy the provided settings in their entirety. We will just make two small changes.

Set the SSLOpenSSLConfCmd DHParameters directive to point to the Diffie-Hellman file we generated earlier. Also, take a moment to read up on HTTP Strict Transport Security, or HSTS, and specifically about the “preload” functionality. Preloading HSTS provides increased security, but can have far reaching consequences if accidentally enabled or enabled incorrectly. In this guide, we will not preload the settings, but you can modify that if you are sure you understand the implications:

# from
# and

SSLProtocol All -SSLv2 -SSLv3
SSLHonorCipherOrder On
# Disable preloading HSTS for now.  You can use the commented out header line that includes
# the "preload" directive if you understand the implications.
#Header always set Strict-Transport-Security "max-age=63072000; includeSubdomains; preload"
Header always set Strict-Transport-Security "max-age=63072000; includeSubdomains"
Header always set X-Frame-Options DENY
Header always set X-Content-Type-Options nosniff
# Requires Apache >= 2.4
SSLCompression off 
SSLSessionTickets Off
SSLUseStapling on 
SSLStaplingCache "shmcb:logs/stapling-cache(150000)"

SSLOpenSSLConfCmd DHParameters "/etc/ssl/certs/dhparam.pem"

Save and close the file when you are finished.

Modify the Default Apache SSL Virtual Host File

Next, let’s modify /etc/apache2/sites-available/default-ssl.conf, the default Apache SSL Virtual Host file. If you are using a different server block file, substitute it’s name in the commands below.

Before we go any further, let’s back up the original SSL Virtual Host file:

  • sudo cp /etc/apache2/sites-available/default-ssl.conf /etc/apache2/sites-available/default-ssl.conf.bak

Now, open the SSL Virtual Host file to make adjustments:

  • sudo nano /etc/apache2/sites-available/default-ssl.conf

Inside, with most of the comments removed, the Virtual Host file should look something like this by default:

<IfModule mod_ssl.c>
        <VirtualHost _default_:443>
                ServerAdmin webmaster@localhost

                DocumentRoot /var/www/html

                ErrorLog ${APACHE_LOG_DIR}/error.log
                CustomLog ${APACHE_LOG_DIR}/access.log combined

                SSLEngine on

                SSLCertificateFile      /etc/ssl/certs/ssl-cert-snakeoil.pem
                SSLCertificateKeyFile /etc/ssl/private/ssl-cert-snakeoil.key

                <FilesMatch "\.(cgi|shtml|phtml|php)$">
                                SSLOptions +StdEnvVars
                <Directory /usr/lib/cgi-bin>
                                SSLOptions +StdEnvVars

                # BrowserMatch "MSIE [2-6]" \
                #               nokeepalive ssl-unclean-shutdown \
                #               downgrade-1.0 force-response-1.0


We will be making some minor adjustments to the file. We will set the normal things we’d want to adjust in a Virtual Host file (ServerAdmin email address, ServerName, etc.), adjust the SSL directives to point to our certificate and key files, and uncomment one section that provides compatibility for older browsers.

After making these changes, your server block should look similar to this:

<IfModule mod_ssl.c>
        <VirtualHost _default_:443>
                ServerName server_domain_or_IP

                DocumentRoot /var/www/html

                ErrorLog ${APACHE_LOG_DIR}/error.log
                CustomLog ${APACHE_LOG_DIR}/access.log combined

                SSLEngine on

                SSLCertificateFile      /etc/ssl/certs/apache-selfsigned.crt
                SSLCertificateKeyFile /etc/ssl/private/apache-selfsigned.key

                <FilesMatch "\.(cgi|shtml|phtml|php)$">
                                SSLOptions +StdEnvVars
                <Directory /usr/lib/cgi-bin>
                                SSLOptions +StdEnvVars

                BrowserMatch "MSIE [2-6]" \
                               nokeepalive ssl-unclean-shutdown \
                               downgrade-1.0 force-response-1.0


Save and close the file when you are finished.

As it stands now, the server will provide both unencrypted HTTP and encrypted HTTPS traffic. For better security, it is recommended in most cases to redirect HTTP to HTTPS automatically. If you do not want or need this functionality, you can safely skip this section.

To adjust the unencrypted Virtual Host file to redirect all traffic to be SSL encrypted, we can open the /etc/apache2/sites-available/000-default.conf file:

  • sudo nano /etc/apache2/sites-available/000-default.conf

Inside, within the VirtualHost configuration blocks, we just need to add a Redirect directive, pointing all traffic to the SSL version of the site:

<VirtualHost *:80>
        . . .

        Redirect "/" "https://your_domain_or_IP/"

        . . .

Save and close the file when you are finished.

Step 3: Adjust the Firewall

If you have the ufw firewall enabled, as recommended by the prerequisite guides, might need to adjust the settings to allow for SSL traffic. Luckily, Apache registers a few profiles with ufw upon installation.

We can see the available profiles by typing:

  • sudo ufw app list

You should see a list like this:

Available applications: Apache Apache Full Apache Secure OpenSSH

You can see the current setting by typing:

  • sudo ufw status

If you allowed only regular HTTP traffic earlier, your output might look like this:

Status: active To Action From -- ------ ---- OpenSSH ALLOW Anywhere Apache ALLOW Anywhere OpenSSH (v6) ALLOW Anywhere (v6) Apache (v6) ALLOW Anywhere (v6)

To additionally let in HTTPS traffic, we can allow the “Apache Full” profile and then delete the redundant “Apache” profile allowance:

  • sudo ufw allow 'Apache Full'
  • sudo ufw delete allow 'Apache'

Your status should look like this now:

  • sudo ufw status
Status: active To Action From -- ------ ---- OpenSSH ALLOW Anywhere Apache Full ALLOW Anywhere OpenSSH (v6) ALLOW Anywhere (v6) Apache Full (v6) ALLOW Anywhere (v6)

Step 4: Enable the Changes in Apache

Now that we’ve made our changes and adjusted our firewall, we can enable the SSL and headers modules in Apache, enable our SSL-ready Virtual Host, and restart Apache.

We can enable mod_ssl, the Apache SSL module, and mod_headers, needed by some of the settings in our SSL snippet, with the a2enmod command:

  • sudo a2enmod ssl
  • sudo a2enmod headers

Next, we can enable our SSL Virtual Host with the a2ensite command:

  • sudo a2ensite default-ssl

We will also need to enable our ssl-params.conf file, to read in the values we set:

  • sudo a2enconf ssl-params

At this point, our site and the necessary modules are enabled. We should check to make sure that there are no syntax errors in our files. We can do this by typing:

  • sudo apache2ctl configtest

If everything is successful, you will get a result that looks like this:

AH00558: apache2: Could not reliably determine the server's fully qualified domain name, using Set the 'ServerName' directive globally to suppress this message Syntax OK

The first line is just a message telling you that the ServerName directive is not set globally. If you want to get rid of that message, you can set ServerName to your server’s domain name or IP address in /etc/apache2/apache2.conf. This is optional as the message will do no harm.

If your output has Syntax OK in it, your configuration file has no syntax errors. We can safely restart Apache to implement our changes:

  • sudo systemctl restart apache2

Step 5: Test Encryption

Now, we’re ready to test our SSL server.

Open your web browser and type https:// followed by your server’s domain name or IP into the address bar:


Because the certificate we created isn’t signed by one of your browser’s trusted certificate authorities, you will likely see a scary looking warning like the one below:

Apache self-signed cert warning

This is expected and normal. We are only interested in the encryption aspect of our certificate, not the third party validation of our host’s authenticity. Click “ADVANCED” and then the link provided to proceed to your host anyways:

Apache self-signed override

You should be taken to your site. If you look in the browser address bar, you will see a lock with an “x” over it. In this case, this just means that the certificate cannot be validated. It is still encrypting your connection.

If you configured Apache to redirect HTTP to HTTPS, you can also check whether the redirect functions correctly:


If this results in the same icon, this means that your redirect worked correctly.

Step 6: Change to a Permanent Redirect

If your redirect worked correctly and you are sure you want to allow only encrypted traffic, you should modify the unencrypted Apache Virtual Host again to make the redirect permanent.

Open your server block configuration file again:

  • sudo nano /etc/apache2/sites-available/000-default.conf

Find the Redirect line we added earlier. Add permanent to that line, which changes the redirect from a 302 temporary redirect to a 301 permanent redirect:

<VirtualHost *:80>
        . . .

        Redirect permanent "/" "https://your_domain_or_IP/"

        . . .

Save and close the file.

Check your configuration for syntax errors:

  • sudo apache2ctl configtest

When you’re ready, restart Apache to make the redirect permanent:

  • sudo systemctl restart apache2


You have configured your Apache server to use strong encryption for client connections. This will allow you serve requests securely, and will prevent outside parties from reading your traffic.


  • Great tutorial; lots of details & easy to follow.
    Probably should mention we can avoid using self-signed certs, and use Let'sEncrypt CA.

    • @TrevorLaneRay: Thanks for the feedback!

      In case you missed it, there’s a note linking to our Let’s Encrypt guide in the introduction up top. This guide was created to supplement those procedures for times when a signed certificate might not be a good fit (like when testing, internal communications, or for things that Let’s Encrypt doesn’t currently support, like wildcard certificates). We’re definitely excited about Let’s Encrypt though! It makes things really straight forward!

      Thanks again for the comment.

      • Ooh, totally missed that. :D
        Kudos on clearing up when self-signed certs are preferred.
        Completely forgot Let'sEncrypt doesn’t yet do wildcard certs.

    • Thanks for the “Let'sEncrypt” info!

  • I’ve used this on all of the Ubuntu servers I’ve deployed and in a custom installation script for an Ubuntu based ownCloud server.

    The ownCloud server brought something to my attention: the ssl-params.conf file is never enabled. It does not show in conf-enabled after completing an install, and ownCloud complains about the max-age setting not being enabled.

    How is the .conf file being accessed by Apache or the SSL mod to pull the settings for use?

    I’ve taught myself Linux and bash scripting over the course of three months while developing that installation script (it automates nearly every aspect of a 20 page walk-through I wrote for configuring the server based on very high security standards), so I may be making a noob mistake.

    • @kevinruffus: Oh goodness, you’re completely right! That’s a bit embarrassing :). I’ll fix that up in just a minute. In the meantime, you can enable the config by typing:

      • sudo a2enconf ssl-params

      You should see that the link has been added to the `conf-enabled directory:

      • ls /etc/apache2/conf-enabled
      charset.conf other-vhosts-access-log.conf serve-cgi-bin.conf localized-error-pages.conf security.conf ssl-params.conf

      Check to make sure there weren’t any syntax errors and then restart the service:

      • sudo apache2ctl configtest
      • sudo systemctl restart apache2

      The SSL parameters should now be applied.

      Thanks for the heads up! Let me know if you spot anything else.

      • I went through and figured that out, but thank you for getting back to me about it so I know I wasn’t just losing my mind.

        For anyone who runs into trouble with ownCloud using this setup, ownCloud inserts it’s own settings for the nosniff and DENY options, so they may have to disable those in the ownCloud root directory .htaccess file. I’m playing with the settings on a testbed VM to see if that can be worked around.

        • Unless someone knows how to bypass the Header always set X-Frame-Options “DENY” and Header always set X-Content-Type-Options “nosniff” directives for a php based site, users hosting an instance of ownCloud will have to change Header always set X-Frame-Options to SAMEORIGIN and comment out those two lines in owncloud/.htaccess, as the initial settings cause a conflict and will throw errors in ownCloud, and an insane number of issues with mod_security.

          • After further digging, it seems it’s the “always” parts of the settings that cause problems. Removing always seems to set those options by default, but allowing sites to override, which ownCloud does. Since the ssl directives were trying to take precedence, ownCloud was having a fit, and screamed about bad files when altering the .htaccess file.

            Sorry about the string of comments, I’m just plowing my way through learning all of this and figured someone else may run into the same issue.

            If anyone is hosting ownCloud, the always needs to be left out on the x-frame-options and x-content-type-options lines.

  • Why am I getting the following error?

    AH00526: Syntax error on line 12 of /etc/apache2/conf-enabled/ssl-params.conf:
    Invalid command 'SSLSessionTickets', perhaps misspelled or defined by a module not included in the server configuration
    Action 'configtest' failed.
    The Apache error log may have more information.
    • Same here!

      Had to comment out (using #) both SSLSessionTickets and SSLOpenSSLConfCmd lines.

      Could the author please give us some reason why is this happening and the security implications of taking those out?


    • @Debiprasad If the SSLSessionTickets is throwing a configuration error, this may either be an indication that you are not using a high enough version of Apache.

      SSLSessionTickets was introduced as part of mod_ssl in Apache 2.4.11, so it is available in Ubuntu 16.04, which ships with version 2.4.18. If you are running this on the wrong distribution, you’ll probably run into this error. You can check your version of apache by typing:

      • apache2ctl -v

      On Ubuntu 16.04, this should give you something like this:

      Server version: Apache/2.4.18 (Ubuntu) Server built: 2016-04-15T18:00:57

      Hope that helps.

      • Thank you for this information @jellingwood ! That was actually the thing, I’m running Ubuntu 14.04.4 LTS and therefore

        Server version: Apache/2.4.7 (Ubuntu)
        Server built:   May  4 2016 17:05:10

        Kind of embarrasing to miss out this point! Thanks and I think it will help @Debiprasad and @Tayskeno as well.

  • Hello,

    I am getting this kind of error : Could you help to identify the issue ?

    AH00526: Syntax error on line 12 of /etc/apache2/conf-enabled/ssl-params.conf:
    Invalid command 'SSLSessionTickets', perhaps misspelled or defined by a module not included in the server configuration
    Action 'configtest' failed.
    The Apache error log may have more information.
  • I generally appreciate the clarity of your explanations; this is a definite +!

    However, I would need to move one step beyond the “ Redirect ”/“ ”https://your_domain_or_IP"“ line, which works perfectly from the Internet to my web server, but not from clients on the same LAN as the server.

    Can I branch to something like "Redirect ”/“ ”https://my_server_local_IP“ by detecting the origin of the client IP or else?

  • Just Subscribed in order to leave comment. First, thank you for this one and the rest of tutorials on your website.

    I have a file upload/sharing website and after i followed your tutorial i have had a few issues (having to update my apache because of certain rules in ssl-params, i was on Ubuntu 15.10, had to do an upgrade on my server over ssh, which failed at some point because of mysql 5.7 being not able to have blank port with phpmyadmin, well it was painful but at some point i managed to do the upgrade) but the biggest one was the “remote url upload”, Curl, which was not working anymore. I have checked all sort of things to disable verifypeer and verifyhost but found that my file sharing script had already a false status on those. I was kinda lost and at some point i remember we had applied security parameters in ssl-params from a thirdparty that you were sharing here but that they could be the faulty ones. I tried to do an sudo a2disconf ssl-params, restartedapache and BINGO, it was working again. I then commented re-enable the ssl-params conf and isolated the faulty rule after commenting all of them one after the other. I’m here to share my finding, the faulty rule is

    Header always set X-Frame-Options DENY

    So in Shorter terms,

    Comment this rule in /etc/apache2/conf-available/ssl-params.conf

    Header always set X-Frame-Options DENY

    If you need CURL to work with this tutorial.


    • In my earlier comment I determined that it’s the “always” that’s the issue. Removing that word, but leaving the directive in place, will allow individual sites you configure to override that setting if you tell them to, but set it by default. Sort of a happy middle ground.

  • I had hard time to understand the difference between a Self-Signed SSL certificate and a CA one, despite your yellow information note (sorry I am a beginner :).

    So here the stackoverflow answer on the matter that helped me to clearly understand the point:

    The SSL certificate solves two purposes: encryption of traffic (for RSA key exchange, at least) and verification of trust. As you know, you can encrypt traffic with (or without, if we’re talking SSL 3.0 or TLS) any self-signed certificate. But trust is accomplished through a chain of certificates. I don’t know you, but I do trust verisign (or at least Microsoft does, because they’ve been paid lots of money to get it installed in their operating systems by default), and since Verisign trusts you, then I trust you too. As a result, there’s no scary warning when I go to such an SSL page in my Web browser because somebody that I trust has said you are who you are.


  • Great and easy understandable tutorial. Thank you for the invested time on writing it.

    I´ve did all as you well describe on the tutorial, however now I´m facing an issue I´d like to know how to solve.

    Despite it works and I´m able to access via HTTPS

    would like to know how to switch the “red warning” icon into the trustable “green shield” one

    thanks for being patient since I´m newbie on all this server issues

  • First of all, thank you @justin for your great and easily understandable tutorial. It helps me a lot.

    I´ve followed and did all you said on it and finally I achieved to connect the site via HTTPS

    However, I´m not sure how I should do to get switch the “red warning” icon into the “green shield” one more trustable

    Looking forward to hear from you

    • @info8da48d61aaf: Unfortunately, the red warning will remain for all self-signed certificates because web browsers are unable to validate it against a list of trusted certificate authorities that they maintain. This is usually fine for testing sites or for internal usage or if you do not have a domain.

      If you need an SSL certificate for a public-facing site, the Let’s Encrypt project provides free certificates that will be recognized by all modern browsers. You can find out how to set up your server with a Let’s Encrypt certificate with Apache by following this guide. Since browsers are configured to trust certificates provided by Let’s Encrypt by default, the icon should turn to the “green shield” using this method. Hope that helps!

      by Erika Heidi
      This tutorial will show you how to set up a free TLS/SSL certificate from Let’s Encrypt on a Ubuntu 16.04 server running Apache as web server. TLS certificates are used within web servers to encrypt the traffic between server and client, providing extra security for users accessing your application.
      • Thank you so much for the explication. I´d try the guide you recommend to get install the Let´s Encrypt certificate

  • So I have no Idea what I’m doing wrong, I’m getting a redirect loop when trying to go thru this guide with a domain name. Is that my problem? Should I just use the Let'sEncrypt service instead?

    The weirdest part to is on part 4, it says that the syntax is OK. Could it be that I’m using CloudFlare as DNS?

    Could you clarify how your 000-default.conf File looks? As that seems to be my problem… Have you done this with a domain name instead of ip?

    • @FilleFLEX1: I don’t currently have a server configured with this setup running right now, so I don’t have access to the 000-default.conf file right now. I did not use a domain name for this configuration however. I personally use Let’s Encrypt if I’m working with a server that has a domain name, as it’s a better solution in most cases where you’re not doing testing. If your domain is handled by CloudFlare, that could be related too. I don’t have much experience with that though, so I’m unable to confirm

      If you feel like self-signed certs are best for your use-case and have tried to minimize interference from CloudFlare, the first thing I would check in that file would be whether your redirect line uses https instead of http:

      <VirtualHost *:80>
              . . .
              Redirect "/" "https://your_domain_or_IP/"
              . . .

      You can also see if the logs have any details about the redirect. Those would likely be at /var/log/apache2/access.log and /var/log/apache2/error.log.

      Good luck debugging and let me know how it goes. I’m sorry I wasn’t able to provide a direct solution.

      • The problems seems to be with the connection from my server and CloudFlare, when I booted up today it worked locally at least :) Just need to figure out what’s wrong with the CloudFlare end…

        Also my question was, where in the config file did you put the line *Redirect “/” “https://your_domain_or_IP/*, can you put it anywhere? And does those dots mean the rest of the text? Does it matter if you put it first or last in the document? And can you remove all the other bits?

        Great guide anyways :)

        P.S Should I post what I come up regarding the CloudFlare issue? It might be intresting for others, as they have a option to use a self-signed SSL key between your server and theirs, then they encrypt the communications between them and the client. Which results in you getting a greenlock and the communication is encrypted the whole way thru.

        Edit: Well I feel like a fool now, as I forgot to allow the port 443 on my router :P Anyways it the CloudFlare thing works now, and I get greenlock with a self-signed SSL key which is kind of cool, might change to LetsEncrypt later. But this will do for now :)

        • @FilleFLEX1: Oh, sorry I misunderstood you last time. The Redirect line can go anywhere within the virtualhost definition outside of all other blocks (don’t put it in a Directory block for instance). The ordering shouldn’t matter.

          Once again, I’m not too familiar with CloudFlare, but one thing you could try to fix the redirect loop is to only redirect when the request is using HTTP. This part of the Apache docs has a similar example, showing how to direct an “admin” page to SSL. You could probably adapt that a bit.

          I would try to see if something like this works:

          <VirtualHost *:80>
                  . . .
                  <If "%{SERVER_PROTOCOL} != 'HTTPS'">
                          Redirect "/" "https://your_domain_or_IP/"
                  . . .

          Maybe that will short circuit the looping behavior you are seeing.

          This post suggests checking the CloudFlare header as a condition of a rewrite. You may have better luck with that method.

          • Sorry again for being unclear :P

            I got it to work, I got timed out, not redirected. And the reason was because I made the rookie mistake of forgetting to forward the port 443.

            Thanks again for the super quick answers :)

  • Great Tutorial.

    Everything works well, my only issue now being my SSH is broken in that WinSCP doesnt ask for a username or password and gives me 403 error method not allowed.

    Anything specific i need to do in terms of downloading keys to use with WinSCP?

    Not sure what the issue is here.

    Any help would be greatly appreciated.

    NVM i figured it out. changed the port to 22.

    Silly mistake.

    Great job on the Tut though!

  • I have successfuly installed the SSL ceritificate with the process given here.

    But by default firewall was inactivate in apache server. The outcome of command “sudo ufw status” given as “Status: Inactive”. So I enabled the firewall with command “sudo ufw enable”. Now The outcome of command “sudo ufw status” given as

    Status: active

    To Action From

    OpenSSH ALLOW Anywhere
    Apache Full ALLOW Anywhere
    OpenSSH (v6) ALLOW Anywhere (v6)
    Apache Full (v6) ALLOW Anywhere (v6)

    But when I try to connect to my instance from putty. It is trowing the error message** “Network error: Connection timed out”.**

    Please help me how to resolve this error

    Note: Before I install the SSL certificate, I was able to connect to AWS EC2 install from putty. SSH, RDP, HTTPS connections are proper with required port numbers and IPs.

  • Thanks a lot for the tutorial!

  • I got this error in telegram webhook
    SSL error {336134278, error:14090086:SSL routines:ssl3getserver_certificate:certificate verify failed}
    what should i do?

  • I have tried to follow this tutorial as closely as possible starting from a one-click Ubuntu 16.04 LAMP deployment. However, when I go to my ip address in Firefox, I see “SSL received a record that exceeded the maximum permissible length. Error code: SSLERRORRXRECORDTOO_LONG”. Do you know what could be wrong?

  • How to do Apache – Authentication - SSL
    to a client using this self-signed certificate?

  • Great tutorial. Helps me a lot and save my life!!!

  • Great Tutorial. Worked perfectly and saved a reinstall of the OS. Also, after I completed your tutorial and had the default SSL site up, I was able to install Letsencrypt and it configured perfectly. Prior to this tutorial letsencrypt wouldn’t work, etc. Again, thank you for clear and concise writing.

  • Missing:

    chown root:ssl-cert /etc/ssl/private/apache-selfsigned.key
    chmod 640 /etc/ssl/private/apache-selfsigned.key
  • why is SSLStapling on if this is a self-signed certificate? When I leave this on I am getting

    [Fri May 09 23:36:44.055900 2014] [ssl:error] [pid 1491:tid 139921007208320] AH02217: ssl_stapling_init_cert: Can't retrieve issuer certificate!
    [Fri May 09 23:36:44.056018 2014] [ssl:error] [pid 1491:tid 139921007208320] AH02235: Unable to configure server certificate for stapling
  • Hello!
    I followd this tutorial, and I didn’t changed anything (but the domain).
    I get this error in browser:
    What could this be?

  • Hi, I have a question about a situation that I’m having…
    I have a trusted SSL certificate in my website and it’s works fine.
    But when I write in the browser the IP, e.g.: https://IP_ofMy_Web instead of my domain name, It takes me to the view with the SSL not trusted like in your example.
    If I write http://nameOfMyWeb redirects me to the https://nameOfMyWeb, so the redirect works fine, but, how can do I fix this situation with the IP?

  • Hi, great tutorial.

    I followed all the instructions till the end, no errors found!

    However, when trying to access my https://localhost or I’m getting the following error:

    This site can’t provide a secure connection
    localhost sent an invalid response.

    Any help would be very appreciated.

  • Thank you very much for the tremendous guide! Using this in part with the OwnCloud and LAMP setup, I’m looking forward to using this “weekend project” within my day-to-day tasks!

    Thank you again!

  • Thanks for writing this!

    Just a note that cause me to waste a bunch of time. I was trying to set all this up on a vhost as I didn’t know you couldn’t have more than one vhost per ip address and wasn’t aware of SNI. If you whoever is maintaining this put a note about that at the top it might help someone else save a bunch of time!

    Still haven’t gotten it working correctly, but feel like I’m on the right track now.

  • Very good and useful guide thanks a lot!
    Worked first try

  • Great Article. Signed up just to write this comment. Awesome. Lots of thanks.

  • This is really a great tutorial! Thanks for sharing your knowledge with us! (Y)

  • Hello, so it is working

    however, I want to add a new domain…

    but I receive this error:
    SSLCertificateFile: file ’/etc/letsencrypt/live/’ does not exist or is empty

    and indeed, I dont find, read, understand how this file gets created, I really need your help.

  • One last step, so your local computer will trust the certificate

    sudo cp my.crt /usr/local/share/ca-certificates/
    sudo update-ca-certificates

  • I followed this tutorial and Managed to set up the SSL on one of my Droplets However, I am getting this error on my Javascript web app
    Load denied by X-Frame-Options: https://*************************************.php?action=71&productid=1&fee=[{%22feeid%22:%221%22,%22feename%22:%22SIL%20PESA%20PF%22}]&valfutureinterest=1&valaccrueinterest=1&valallowloantopup=0&valpercentageoftopuploanpaid=0 does not permit framing.

    SecurityError: Permission denied to access property “document” on cross-origin object

  • Cheers for the tutorial, although I came upon this error at the sudo apache2ctl configtest part

    AH00526: Syntax error on line 10 of /etc/apache2/conf-enabled/ssl-params.conf:
    Invalid command 'Header', perhaps misspelled or defined by a module not included in the server configuration
    Action 'configtest' failed.
    The Apache error log may have more information.

    Any pointers?

    Full disclosure, I am very new to all this

  • Thanks for this great Tutorial. Got more valuable information. May this link will help you to get more clarity about SSL certificate for apache.

  • thanks for this interesting tutorial

    I’m trying to run an home web server for few web application and a cloud.
    I subscribed to no-ip dns service including a domain registration and several sub domain.

    The aim is to call the web application with the subdomain. Let say this is the arrangement:
    Sub domains:,,
    Server name (the phisical machine) (it is necessary or I can leave locahost or any other name)

    With noip I have all A tape and I could also have * (using wildcard) instead of single entry for each subdomain

    When I need a ssl certificate do I need one for the and one for each sub.domain?

    Similar question if I decide (more try) to get Let’s encrypt certificates

    thanks a lot

  • Hi

    When I run

    foo@bar:apache2ctl configtest

    in the Wordpress 1 Click App, I get the following error

    foo@bar:apache2ctl configtest
    AH00526: Syntax error on line 10 of /etc/apache2/conf-enabled/ssl-params.conf:
    Invalid command 'Header', perhaps misspelled or defined by a module not included in the server configuration
    Action 'configtest' failed.

    I’m not sure how to update my server configuration to fix this. How do I go about it?

    • @hi326408 If Apache complains about not knowing about the “Header” command, make sure you’ve enabled the headers module and try again:

      • sudo a2enmod headers

      Hope that helps.

  • I have a self-signed certificate, but now i have a domain name, and i’d like to set a TLS/SSL certificate from Let’s Encrypt. If i follow this guide, it will overlap the self-signed? If not, how do i remove the self-signed certificate?

    by Erika Heidi
    This tutorial will show you how to set up a free TLS/SSL certificate from Let’s Encrypt on a Ubuntu 16.04 server running Apache as web server. TLS certificates are used within web servers to encrypt the traffic between server and client, providing extra security for users accessing your application.
  • When I activate this conf, I only get erros and it obviosly doesn’t work.
    sudo a2enconf ssl-params

    If I don’t it works perfect.
    So why is it in the doc?

  • After following these instructions and restarting apache my connection times out. Any idea what might be causing this?

  • This did not work for me, but if it did, it is not clear to me why I would want a visitor to a website to think that the connection is not secure. It is also not clear to me how this is supposed to work with LetsEncrypt. I will just undo all of the things that this tutorial setup by editing the files I changed and changing them back. To my thinking, a setup that combines redirection with LetsEncrypt so that users are redirected to a secure site would be useful, but that does not seem to be a part of the LetsEncrypt tutorial, because I have followed that tutorial and that is not what happens.

  • Hi everyone, would someone help/guide me in how to do this without having Diffie Hellman as my cipher please? I am trying to self-teach this and don’t want to guess and leave a step out, only to break the whole thing. I need to test using an IDS that does not support DH, otherwise it won’t decrypt. Thank you in advance :)

  • AH00526: syntax error on line 5. SSLv3 not supported by this version of OpenSSL

  • I have Ubuntu 16.04 and have successfully setup the SSL from Godaddy, but when I go to the site I’m getting a bad request. I have my default-ssl.conf files set with my SSL info, along with my document root information, and 000-default.conf is set to redirect as instructed in the instructions. I’ve setup my file with SSL info as well, and declared my redirects and document roots there as well. Am I missing something?

  • Hello,
    Thanks for making this documentation. I’m able to do the Self Signed SSL to Apache and able to access like https://123.456.12.43, it is showing tomcat server. But https is not working when i try along with port or application like https://123.456.12.43:8080 or https://123.456.12.43:8080/sample-application/ We have placed our application in the /sample-application directory.

    Appreciate if any quick help or suggestions.
    Thank you very much.

  • A remark on ssl-params.conf.

    If your using wordpress you got problems with X-frame which is used by some plugins. It cost me a couple of hours to find out how to correct this.

    Change the line:

    • Header always set X-Frame-Options DENY*

    Header set X-Frame-Options: “sameorigin”

    Header always set X-Frame-Options “allow-from https://<wordpress site>/

    Btw A great tutorial. Thank you for that.

  • Hi, you can check up my video where I show in 10 minutes or so how to setup a free multidomain ssl certificate with certbot on ubuntu.

    Happy to contribute to the DO community,

    All the best,

    José from France

  • I followed the steps on “How To Serve Django Applications with Apache and mod_wsgi on Ubuntu 16.04

    That directed me here. I followed the steps here. The https part was working, but I was getting the Apache2 default “It works!” page, not my Django app. I finally got my Django app to show up by moving the directory and WSGI lines from 000-default.conf to default-ssl.conf

    by Justin Ellingwood
    Django is a powerful web framework that can help you get your Python application or website off the ground quickly. Django includes a simplified development server for testing your code locally, but for anything even slightly production related, a more secure and powerful web...
  • When you can’t install or afford trusted certificates from a certificate authority, you may get by with self-signed certificates. Both trusted, and self-signed certificates are the same and use the same protocols… the only difference is, one is trusted by a third party, and the other is not.

    When you’re ready, run the commands below to generate the private server key as well as the self-signed SSL/TLS certificate for the domain… you’ll be using.

    Note: is my server name

    sudo openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout /etc/ssl/private/ -out /etc/ssl/certs/

    After running the commands above, you’ll be prompted to answer a few questions about the certificate you’re generating… answer them and complete the process.

    Generating a 2048 bit RSA private key

    writing new private key to ‘mydomain.key’

    You are about to be asked to enter information that will be incorporated
    into your certificate request.
    What you are about to enter is what is called a Distinguished Name or a DN.
    There are quite a few fields but you can leave some blank
    For some fields there will be a default value,

    If you enter ’.’, the field will be left blank.

    Country Name (2 letter code) [AU]:IN
    State or Province Name (full name) [Some-State]:Gujarat
    Locality Name (eg, city) []:Vadodara
    Organization Name (eg, company) [Internet Widgits Pty Ltd]:Example Company
    Organizational Unit Name (eg, section) []:SSL Unit
    Common Name (e.g. server FQDN or YOUR name) []
    Email Address []:<email removed by mod>

    Please enter the following 'extra’ attributes
    to be sent with your certificate request
    A challenge password []: LEAVE BLANK
    An optional company name []:

    edited by MattIPv4
  • I got an issue, After applying this certificate. My soapclient is stop working. it is throwing error “could not connect to host”. I try to find but nothing helped me.
    If you guys have any idea about.

    Thanks in advance,

Creative Commons License