Assume we have a web site engine (web server, blog, shellinabox, you name it) running in your private network at ip 10.10.10.10 port 3500, serving http.

We want to expose this local/intern web service to the internet, without giving the internet access to our local machine. We want to use the https-protocol and proxy via web server nginx or Apache, using a (sub)domain that we own, let’s assume for simplifying reasons that this is https://sub.example.com.

Here we look at two very basic proxy setups to realize this task.

nginx

So, given that nginx is already installed, for the proxy functionality, at the server that serves https://sub.example.com, we configure a nginx site as /etc/nginx/sites-available/sub.example.com:

#
# Virtual Host configuration nginx
#

server {
        listen 80;
        server_name sub.example.com;
        
        location / {
                proxy_pass http://10.10.10.10:3500/;
                proxy_set_header Host $host;
        }
}

Next, we install certbot for obtaining SSL certificates for our server:

sudo apt-get install certbot python3-certbot-nginx 

Now we have to make our website public, in order that certbot can obtain a certificate from Let’s Encrypt via the ACME protocol. We do that by making the site available:

sudo ln -s /etc/nginx/sites-available/sub.example.com /etc/nginx/sites-enabled

After that, we have to reload the nginx configuration:

sudo service nginx reload

Now we should be able to access our server via http://sub.example.comwhich is internally served by http://10.10.10.10:3500.

To obtain the certificate, we now run

sudo certbot --nginx -d sub.example.com

This will provide our server with a Let’s Encrypt certificate, create and enable a new nginx ssl configuration /etc/nginx/sites-available/sub.example.com-ssl, and modify the original config enable SSL. The automatically changed config file should now read like

#
# Virtual Host configuration nginx
#

server {
        server_name sub.example.com;
        
        location / {
                proxy_pass http://10.10.10.10:3500/;
                proxy_set_header Host $host;
        }

    listen 443 ssl; # managed by Certbot
    ssl_certificate /etc/letsencrypt/live/sub.example.com/fullchain.pem; # managed by Certbot
    ssl_certificate_key /etc/letsencrypt/live/sub.example.com/privkey.pem; # managed by Certbot
    include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot
    ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot
}

server {
    if ($host = sub.example.com) {
        return 301 https://$host$request_uri;
    } # managed by Certbot

        listen 80;
        server_name sub.example.com;
    return 404; # managed by Certbot
}

That’s it! Now we have a local/intern web service exposed to the internet using the https-protocol via nginx.

Apache

Again we assume that the web server itself is already installed. So we configure at the server that serves https://sub.example.com an Apache site as /etc/apache2/sites-available/sub.example.com.conf:

#
# Virtual Host configuration Apache
#
<VirtualHost *:80>
        ServerAdmin webmaster@localhost
        ServerName sub.example.com
        ServerAlias sub.example.com
        ProxyPreserveHost On
        
        ProxyPass / http://10.10.10.10:3500/
        ProxyPassReverse / http://10.10.10.10:3500/
</VirtualHost>

For the proxy configuration to work, we want to be sure to have proxy functionality enabled:

sudo a2enmod proxy
sudo a2enmod proxy_http
sudo systemctl restart apache2

Next, we install certbot for obtaining SSL certificates for our server:

sudo apt-get install certbot python3-certbot-apache 

Now we have to make our website public, in order that certbot can obtain a certificate from Let’s Encrypt via the ACME protocol. We do that by making the site available:

sudo a2ensite sub.example.com.conf

After that, we have to restart Apache:

sudo service apache2 restart

Now we should be able to access our server via http://sub.example.comwhich is internally served by http://10.10.10.10:3500.

To obtain the certificate, we now run

sudo certbot --apache -d sub.example.com

This will provide our server with a Let’s Encrypt certificate, create and enable a new Apache ssl configuration /etc/apache/sites-available/sub.example.com-le-ssl.conf, and modify the original config to redirect from http to https. The automatically created config file should read like

#
# Virtual Host configuration Apache
#
<IfModule mod_ssl.c>
<VirtualHost *:443>
        ServerAdmin webmaster@localhost
        ServerName sub.example.com
        ServerAlias sub.example.com
        ProxyPreserveHost On
        
        ProxyPass / http://10.10.10.10:3500/
        ProxyPassReverse / http://10.10.10.10:3500/

SSLCertificateFile /etc/letsencrypt/live/sub.example.com/fullchain.pem;
SSLCertificateKeyFile /etc/letsencrypt/live/sub.example.com/privkey.pem;
Include /etc/letsencrypt/options-ssl-apache.conf
</VirtualHost>
</IfModule>

That’s it! Now we have a local/intern web service exposed to the internet using the https-protocol via Apache.