I have a fully qualified domain name pointing to the ip of the droplet with Ubuntu 20.04 and Postgres 12 installed. I need to install SSL on the same. Any help is appreciated.

1 comment
  • Hi All

    Few call outs: The droplet has only Ubuntu 20.04 and Postgres 12 installed along with an app. It does not have apache or nginx (I have checked using nginx -v and apache2 -v). The idea is to only encrypt the traffic between the app and the pg database.

These answers are provided by our Community. If you find them useful, show some love by clicking the heart. If you run into issues leave a comment, or add your own answer to help others.

×
5 answers

Hi @mishrashreya840,
I had to start new answer because we already reached too many replies.

@mishrashreya840 wrote
Can you point me to the relevant tutorial pls?

You can install Nginx on Ubuntu following this tutorial:
https://www.digitalocean.com/community/tutorials/how-to-install-nginx-on-ubuntu-20-04

To configure Nginx as reverse proxy you can base on step 7 of the below tutorial. Obviously, you need to modify settings to fit them to your environment.
https://www.digitalocean.com/community/tutorials/how-to-configure-nginx-as-a-web-server-and-reverse-proxy-for-apache-on-one-ubuntu-20-04-server

@mishrashreya840 wrote
Also, can installing nginx/apache interfere with the running application as that app does not require these running.

I do not know that. I could imagine conflicts between dependent packages, e.g. the app might require elder versions than nginx but it is rather not that likely. It may be conflict in using TCP ports as well but it is configurable, at least on Nginx side.
First, check what adresses and ports the applications listen on:

sudo netstat -tulpn

Look for your app in the result.
Nginx is configured by default to listen on all addresses on TCP port 80.

by Erin Glass
Nginx is one of the most popular web servers in the world and is responsible for hosting some of the largest and highest-traffic sites on the internet. In this guide, we'll discuss how to get Nginx installed on your Ubuntu 20.04 server.
  • Dear @Yannek Thanks so much for the reply. It worked.

    Here’s what I did:
    Steps untill My App running on HTTP
    install Nginx using above tutorial
    Install SSL on Nginx using above Tutorial
    Add entire path including port to Nginx conf files amd voila the https version lives :)

    1 call out - both versions seem to be working albeit on different ports, You’ll need to suppress the http version and open a new port on https for your app.

    • OK. So now, you have an access to your app with both HTTP and HTTPS, don’t you ? I do not know your configuration but I guess that you can access your app with HTTPS on port 443 (via nginx reverse proxy) and with HTTP on the same port as before you started changing droplet’s configuration (having connection directly to your app). That is because your app is still listening on all your droplet’s IP addresses, I mean localhost (127.0.0.1), VPC IP address, and public IP address. In netstat result it would look like

      Output
      Proto Local Address Foreign Address State Program name tcp 0 0.0.0.0:port 0.0.0.0:* LISTEN app

      0.0.0.0 represents all droplet’s IP addresses.

      If it is actually like that, then the best way would be changing your app’s setting to make it listening just on localhost (127.0.0.1). If you are not able to change this setting, then you can close HTTP app port in firewall.

      • @Yannek : Tried the above and something broke, unable to fix :)
        Now unable to execute the installation of my app because nginx+ssl seem to be interfering with postgres (DB connect fails on IP because SSL msg says IP is not configured for SSL and the domain entry in the config file doesn’t seem to be recognizing the domain.

        Can you specifically help with below:
        how to rewrite URL of
        http (and) https://domain.com:9999/subscription/xxxx to https://domain.com/subscription/xxxxx ensuring that both result in same action.

        • @mishrashreya840
          Tried the above and something broke, unable to fix :)

          That is why I strongly recommend to make a droplet’s snapshot before changing anything ;)

          @mishrashreya840
          Now unable to execute the installation of my app because nginx+ssl seem to be interfering with postgres (DB connect fails on IP because SSL msg says IP is not configured for SSL and the domain entry in the config file doesn’t seem to be recognizing the domain.

          It looks like you are trying to connect to your droplet’s database from outside of your droplet now. Am I right ? In that case, you should follow @alexdo’s answer.

          @mishrashreya840
          Can you specifically help with below: how to rewrite URL of http (and) https://domain.com:9999/subscription/xxxx to https://domain.com/subscription/xxxxx ensuring that both result in same action.

          Please, specify the exact reason for that redirection. The solution strongly depends on that.

Edit - There’s a binary app that’s using the Postgres DB and is accessible on the domain:port for which I need SSL installed.

  • Hi,
    How do you access your app ? With internet browser ?

    • Yes, like this: example.com:1234

      • I have just read your idea of encrypting traffic between the app and the database. Is it really needed when the app and the database exist on the same server ? In my opinion, the traffic between clients (internet browsers) and your app/database server (droplet) should be secured (encrypted). If you do not have an idea how to configure SSL certificate in the app, I could suggest installing web server (e.g. Apache or Nginx) and configuring it as reverse proxy for your app. You would have to change the configuration of the app to make it listening on localhost and port different to 80 (http), 443 (https), 5432 (PSQL). Then, when you get your new configuration working, you will be able to install Let’s Encrypt certificate.
        And definitely make a snapshot of your working configuration before you start changing anything.

Hello, @mishrashreya840

I will recommend you to check our existing tutorial on how to secure Apache with Let’s Encrypt:

https://www.digitalocean.com/community/tutorials/how-to-secure-apache-with-let-s-encrypt-on-ubuntu-20-04

If you want to issue and install a LE certificate for your domain name just follow the steps in the article.

Hope that this helps!
Regards,
Alex

by Erika Heidi
Let's Encrypt is a Certificate Authority (CA) that facilitates obtaining and installing free TLS/SSL certificates, thereby enabling encrypted HTTPS on web servers. Currently, the entire process of obtaining and installing a certificate is fully automated on both Apache and Nginx with the use of Certbot. In this guide, we'll use Certbot to obtain a free SSL certificate for Apache on Ubuntu 20.04, and make sure this certificate is set up to renew automatically.

Hi @communityservice,
I had to open new answer again :)
Sorry I left you without response but I dived into DO’s API and almost drowned :D :D :D

@communityservice/@unicornomy wrote
I have an app (public facing) on http://domain.com:6000 which has various sub URLs like http://domain.com:6000/subscribe/3423-23452345-fsd-a345-234 and http://domain.com:6000/unsubscribe/341234-2345-fasdf-1453245 etc. These URLs are also sent out to subscribers via email and when they are clicked by customers the insecure version (http) with port number open up which really does not look secure and neat. Thus I need to move them to https://domain.com/subscribe/3423-23452345-fsd-a345-234 and https://domain.com/unsubscribe/341234-2345-fasdf-1453245 with the action of both the URLs remaining unaffected. I feel this needs to be achieved out of server block setting of nginx, but unable to find a working solution for the same.

What is the website server for your app, working on port 6000 ? Can you provide a result of the command below, pls. ?

sudo netstat -tulpn | grep 6000
  • @yannek - Hope the dive was nice :)

    nginx is the web-server for the app. It does not require nginx but I installed it to manage routing of URLs/SSL etc.

    sudo netstat -tulpn | grep 6000
    

    tcp 0 0 x.x.x.x:6000 0.0.0.0:* LISTEN 34550/./appname

    • @communityservice wrote
      Hope the dive was nice :)

      Can’t complain ;)

      @communityservice wrote
      sudo netstat -tulpn | grep 6000 gives tcp 0 0 x.x.x.x:6000 0.0.0.0:* LISTEN 34550/./appname

      So apparently, your app has embedded web server that listens on tcp 6000. Perform another test, please, unless you did it before. Generate e.g. subscription link with port 6000 included in it, looking like

      http://domain.com:6000/subscribe/3423-23452345-fsd-a345-234
      

      Do not use that link to subscribe but modify it. Remove port number from it and replace protocol prefix (scheme) with https, so it would look like

      https://domain.com/subscribe/3423-23452345-fsd-a345-234
      

      and such modified link use for subscription, entering it in your internet browser’s address bar. Let me know if you can subscribe with such modified link.

        • I think I will have to add the public url of the app and rewrite the same in nginx server block (proxy pass may be) and the same with ssl.

          • That is what I would do - setting up nginx reverse proxy for the app.
            I would…

            1. Set up the app for listening on 127.0.0.1:6000 only (localhost:6000).

            2. Configure server block in nginx to listen on port 6001, serving SSL/TLS connection and reverse proxy for the app.

            3. Configure server block in nginx to listen on port 6000 and to redirect incoming connections to https on port 6001

            Those server block configurations would look like

            server {
              listen droplet_public_ip:6001 ssl;
              server_name domain.com;
            
              location / {
                proxy_pass http://localhost:6000;
                proxy_redirect http://localhost:6000 https://domain.com:6001;
              }
            
              ssl on;
              ssl_certificate /etc/letsencrypt/live/domain.com/fullchain.pem;
              ssl_certificate_key /etc/letsencrypt/live/domain.com/privkey.pem;
              include /etc/letsencrypt/options-ssl-nginx.conf;
            }
            
            server {
                listen droplet_public_ip:6000;
                server_name domain.com;
                return 301 https://domain.com:6001$request_uri;
                return 404;
            }
            
            

            And if I ran

            sudo netstat -tulpn | grep -e 6000 -e 6001
            

            the result would look like

            Output
            tcp 0 0 127.0.0.1:6000 0.0.0.0:* LISTEN 39360/app tcp 0 0 1.2.3.4:6001 0.0.0.0:* LISTEN 39591/nginx tcp 0 0 1.2.3.4:6000 0.0.0.0:* LISTEN 39591/nginx

            I hope you actually do not use port tcp 6000. Communication on this port is blocked by default in some internet browsers (e.g. Firefox, SeaMonkey).
            Do not forget to open port tcp 6001 in your firewall :)

            Let me know if it works, pls.

        • Than you for testing. It shows that simple (?) redirection will not work.

          • @Yannek : Thanks for taking out time to write such a detailed response.

            Here’s where I am:

            • the auto email shot by the app now actually contains url with port number
            • the auto email shot by the app now actually contains url without https

            and the url works as it should

            • app does not load on https (says ssl error)
            • neither is the port gone from the login url of the app
            sudo netstat -tulpn | grep -e 6000 -e 6001 
            

            resulted in below
            tcp 0 0 1.2.3.4:6000 0.0.0.0:* LISTEN 24317/./appname

            Those server block configurations would look like
            

            sudo nginx -t
            nginx: [warn] the “ssl” directive is deprecated, use the “listen … ssl” directive instead in /etc/nginx/sites-enabled/domain.com:48
            nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
            nginx: configuration file /etc/nginx/nginx.conf test is successful

            anything that I did wrong?

            Or was I supposed to add it to some other file? Or maybe creating sym link?

Hi @communityservice,
We reached too many replies, so I started a new answer.

@communityservice wrote
sudo netstat -tulpn | grep -e 6000 -e 6001 resulted in below tcp 0 0 1.2.3.4:6000 0.0.0.0:* LISTEN 24317/./appname

It looks like before. First of all, you need to change the settings in your app configuration to make it listening on localhost (127.0.0.1), not on public IP address (1.2.3.4 in the example). Otherwise, the configuration I sent you will not work, you will have two services listening on your public IP port 6000, the app and nginx.

@communityservice wrote
anything that I did wrong? Or was I supposed to add it to some other file? Or maybe creating sym link?

You can add new server blocks to your existing file as well as to a new file. In the first case you do not have to care about creating a symlink.

@communityservice wrote
nginx: [warn] the “ssl” directive is deprecated, use the “listen … ssl” directive instead in /etc/nginx/sites-enabled/domain.com:48

It is just a warning but it would be good to fix it too. What is your directive in line 48 of the file /etc/nginx/sites-enabled/domain.com ?

And remember to restart nginx service after changing its configuration. First check if the syntax of config files is OK, of course :)

sudo nginx -t

sudo systemctl restart nginx
  • How do I change the listening port of the app? In settings I have configured http://domain.com:6000 as the root URL (I am assuming this is equivalent to localhost)?

    your nginx server block code that you gave above from that the below line is on line 48:

    ssl on;
    

    nginx config check and restart I have done.

    and I have added it to the existing file itself - so sym link is not needed, I guess.

    • @communityservice wrote
      How do I change the listening port of the app? In settings I have configured http://domain.com:6000 as the root URL (I am assuming this is equivalent to localhost)?

      So, you can change settings of the app ? Do you have any settings guide for the app ? Maybe there is an option for SSL certificate ? You could set it up directly in app’s settings then.
      Anyway, I suppose that changing root URL for http://localhost:6000 will break links for subscriptions created by the app. However, you could make a test to check it.

      @communityservice wrote
      your nginx server block code that you gave above from that the below line is on line 48: ssl on;

      Oh, sorry. I put ssl with listen directive, indeed. So, comment line no. 48 or remove it, and restart nginx service. After that, you should get two lines with port 6000 and one line with port 6001 as result of command

      sudo netstat -tulpn | grep -e 6000 -e 6001 
      
      • Anyway, I suppose that changing root URL for http://localhost:6000 will break links for subscriptions created by the app. However, you could make a test to check it.
        

        I tried, links broke. :)

        After that, you should get two lines with port 6000 and one line with port 6001 as result of command
        

        Yes correct.

        But now an interesting problem has come up:
        http://domain.com:6000 results in https://domain.com:6001 and it gives a 502 bad gateway error. I feel we’re very near to a solution :)

        • @communityservice wrote
          But now an interesting problem has come up: http://domain.com:6000 results in https://domain.com:6001 and it gives a 502 bad gateway error. I feel we’re very near to a solution :)

          You can see this error because app does not listen on localhost:6000.
          I have got one more idea but must test it before sharing.

          • This configuration should work finally but it is a bit weird. I strongly recommend you documenting it well to avoid any doubts in the future when you will have to reconfigure website/app environment :)

            Short explanation of this configuration.
            The app listens on public IP address, port 6000 but the firewall rule redirects traffic from port 6000 to 6003. So, HTTP requests, originally addressed to port 6000, come to port 6003, and they are served by Nginx listening on this port. Nginx rewrites their protocol scheme to HTTPS and starts the SSL/TSL sessions on port 6001. Nginx redirect traffic from port 6001 to the app (port 6000), decrypting it to HTTP, as it is reverse proxy for the app.

            Here are the steps to do:

            1. Set up Nginx

            Modify nginx server block to get it as below

            server {
              listen droplet_public_ip:6001 ssl;
            
              server_name domain.com;
            
              location / {
                proxy_pass http://domain.com:6000;
                proxy_redirect http://domain.com:6000 https://domain.com:6001;
              }
            
              ssl_certificate /etc/letsencrypt/live/domain.com/fullchain.pem;
              ssl_certificate_key /etc/letsencrypt/live/domain.com/privkey.pem;
              include /etc/letsencrypt/options-ssl-nginx.conf;
            }
            
            server {
                listen droplet_public_ip:6003;
                server_name domain.com;
                return 301 https://domain.com:6001$request_uri;
                return 404;
            }
            
            

            Replace droplet_public_ip with droplet’s public IP address, and domain.com with your domain name. Double check the paths of ssl files.

            Check the syntax running

            sudo nginx -t
            

            Restart nginx service

            sudo systemctl restart nginx
            

            Then, run

            sudo netstat -tulpn | grep -e 6000 -e 6001 -e 6003
            

            Three lines should be displayed then, similar to the below ones

            Output
            tcp 0 0 1.2.3.4:6000 0.0.0.0:* LISTEN 39360/app tcp 0 0 1.2.3.4:6001 0.0.0.0:* LISTEN 39591/nginx tcp 0 0 1.2.3.4:6000 0.0.0.0:* LISTEN 39591/nginx

            1.2.3.4 represents droplet’s public IP address

            2. Set up a firewall rule

            Open port TCP 6003 in your firewall’s settings in the same way you have done it for port TCP 6001. Then, add a port redirecting rule.
            If you use nftables, modify your ruleset file adding a chain and a rule (or just a rule, if you have appropriate chain already entered).
            A chain and a rule would look like

            # port redirection: TCP 6000 -> TCP 6003
            chain chain_name {
              type nat hook prerouting priority -100
              tcp dport 6000 redirect to 6003
            }
            

            Replace chain_name with the appropriate one.
            You can find more information on port redirection with nftables in this doc:
            https://wiki.nftables.org/wiki-nftables/index.php/Performing_Network_Address_Translation_(NAT)

            If you use iptables, run the following command

            sudo iptables -t nat -A PREROUTING -p tcp --dport 6000 -j REDIRECT --to-port 6003
            

            then save the rules into your ruleset file putting appropriate file name

            sudo iptables-save > your_ruleset_file
            

            Let me know how it works, please.

Submit an Answer