Lets Encrypt
Background
SFTP Gateway 3.x comes with a web admin interface for managing SFTP users and settings. This website is hosted on a local web server (Nginx).
The website uses a self-signed SSL certificate. This protects your web traffic out of the box. However, you will encounter SSL warnings each time you visit the site.
If you don't want invalid SSL certificate warnings, you will need to obtain a valid SSL certificate.
Using LetsEncrypt
The best free approach is to use LetsEncrypt, which provides free SSL certificates. These are Domain Validation (DV) level certs.
This article covers how to set up LetsEncrypt on Ubuntu 22.04. It provides step-by-step instructions for the initial set up.
Preparation
(1) In the Google Cloud console, create a static IP address for your VM.
(2) Create a DNS entry (Host A record), which points your domain name to the public IP address of your VM. Allow some time for DNS to propagate.
(3) In the Google Cloud console, change the VM's Firewall setting to Allow HTTP traffic
.
This is required for the validation step.
(4) SSH into your VM, and elevate your privileges to root:
sudo su
(5) Set the domain name on your Nginx conf file.
Edit /etc/nginx/sites-available/website.conf
line 71 (Depending on the version, the line number may be different, but it should be the 4th to last line in the file regardless), and replace the wildcard _
with your domain name.
For example:
server_name robtest.thorn.tech;
(6) Restart Nginx to apply this change.
nginx -t && service nginx restart
Certbot installation
On SFTP Gateway v3.4.0
, LetsEncrypt is already installed on the server. To verify, run the following command:
certbot --version
Otherwise, run the following command to install LetsEncrypt.
snap install --classic certbot
Run the certbot wizard
After you have run the above commands to install LetsEncrypt, you can generate the SSL certificate.
(1) Run this command:
certbot
You will be taken through an interactive wizard.
(2) Enter a valid email address:
Saving debug log to /var/log/letsencrypt/letsencrypt.log
Enter email address (used for urgent renewal and security notices)
(Enter 'c' to cancel): robert.chen@thorntech.com
(3) Agree to the Terms of Service:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Please read the Terms of Service at
https://letsencrypt.org/documents/LE-SA-v1.2-November-15-2017-w-v1.3-notice.pdf.
You must agree in order to register with the ACME server at
https://acme-v02.api.letsencrypt.org/directory
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
(A)gree/(C)ancel: A
(4) You don't need to share your email.
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Would you be willing, once your first certificate is successfully issued, to
share your email address with the Electronic Frontier Foundation, a founding
partner of the Let's Encrypt project and the non-profit organization that
develops Certbot? We'd like to send you email about our work encrypting the web,
EFF news, campaigns, and ways to support digital freedom.
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
(Y)es/(N)o: N
(5) Select your domain. If it doesn't show up on the list,
check your /etc/nginx/conf.d/website.conf
file for the server_name
directive.
Which names would you like to activate HTTPS for?
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1: robtest.thorn.tech
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Select the appropriate numbers separated by commas and/or spaces, or leave input
blank to select all options shown (Enter 'c' to cancel): 1
(6) LetsEncrypt will try to validate your server.
Obtaining a new certificate
Performing the following challenges:
http-01 challenge for robtest.thorn.tech
Using default addresses 80 and [::]:80 ipv6only=on for authentication.
Waiting for verification...
Cleaning up challenges
Deploying Certificate to VirtualHost /etc/nginx/sites-enabled/website.conf
(7) Do not add a redirect, because this will corrupt the existing Nginx configuration.
Please choose whether or not to redirect HTTP traffic to HTTPS, removing HTTP access.
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1: No redirect - Make no further changes to the webserver configuration.
2: Redirect - Make all requests redirect to secure HTTPS access. Choose this for
new sites, or if you're confident your site works on HTTPS. You can undo this
change by editing your web server's configuration.
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Select the appropriate number [1-2] then [enter] (press 'c' to cancel): 1
Once LetsEncrypt has validated your server, navigate back to the Web Admin Interface and you should see the site now has an SSL certificate. You may need to open the site in an incognito tab to have the SSL cert appear for the first time.
Note: If you become stuck on the Setup and login instructions
page, check out the Troubleshooting section at the bottom of this article.
Validation and cleanup
Verify that it works by navigating to your domain via your web browser using HTTPS.
If all is well, you should see a valid SSL certificate.
On your VM Firewall, don't forget to remove the Allow HTTP traffic
rule.
Automatic renewal
The LetsEncrypt SSL certificate only lasts 90 days, so it requires periodic renewal.
To renew the SSL cert, you can run the command:
certbot renew
This will ask you a series of questions in order to renew your existing SSL certificates.
Note: You will not be eligible for renewing the SSL cert until you are within 30 days of expiration. This is to prevent LetsEncrypt from being inundated with daily renewal scripts.
To automate the LetsEncrypt renewal, you can create a cron job:
crontab -e
And add this line of text:
0 4 2 * * /usr/bin/certbot renew --quiet >/dev/null 2>&1
This runs the certbot renew
command non-interactively once a month at 4am on the second day of every month.
Remember that in order to renew the cert, LetsEncrypt needs to access the server over port 80
or via HTTP. So, if port 80 is locked down by default, you'd need to open it up temporarily when the cron job runs, or the cert won't be renewed since it can't be validated from the LetsEncrypt servers.
Troubleshooting
In some cases, certbot will overwrite the website.conf file with their own configuration. Since SFTP Gateway relies on this config file to access the Web Interface on HTTPS, this can lock you out of the Web Interface.
Below, is an example of what a normal website.conf looks like for SFTP Gateway after adding an SSL Cert. Feel free to use this file to replace the conf file added by certbot. The only values that need to be changed are on lines 42, 43 and 68 where the website name (bryce.sftpgw.cloud in this example) is located.
So, when using this conf file, make sure to replace bryce.sftpgw.cloud with your own website name.
server {
listen 80;
listen [::]:80;
server_name _;
# landing page resources
# match on any assets used by the static landing page
location ~* /(index.html|config/|css/|js/|images/) {
try_files $uri $uri/ /index.html?$args;
}
# redirect "Click here" to the web admin portal
if ($request_uri = /admin) {
return 301 https://$host;
}
index index.html index.htm;
root /usr/share/nginx/ui-landing/;
rewrite ^/$ /index.html permanent;
}
log_format with_user_combined '$remote_addr - $http_x_username [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
server {
listen *:443 ssl http2;
listen [::]:443 ssl http2;
access_log /var/log/nginx/access.log with_user_combined;
# Enable HSTS. This forces SSL on clients that respect it, most modern browsers. The includeSubDomains flag is optional.
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains";
# ssl
ssl_session_cache shared:SSL:20m;
ssl_session_timeout 10m;
ssl_protocols TLSv1.2;
ssl_prefer_server_ciphers on;
ssl_ciphers 'ECDH+AESGCM:ECDH+AES256:ECDH+AES128:DH+3DES:!ADH:!AECDH:!MD5';
ssl_certificate /etc/letsencrypt/live/bryce.sftpgw.cloud/fullchain.pem; # managed by Certbot
ssl_certificate_key /etc/letsencrypt/live/bryce.sftpgw.cloud/privkey.pem; # managed by Certbot
location /backend/ {
proxy_pass http://localhost:8080/;
# Disable caching for api layer
add_header 'Cache-Control' 'no-store, no-cache, must-revalidate, proxy-revalidate, max-age=0';
expires off;
proxy_set_header X-Client-IP $proxy_add_x_forwarded_for;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Host $host;
proxy_set_header X-Forwarded-Server $host;
proxy_set_header X-Forwarded-Port $server_port;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_read_timeout 3600;
proxy_http_version 1.1;
proxy_set_header Connection "";
}
location / {
try_files $uri $uri/ /index.html?$args;
}
index index.html index.htm;
server_name bryce.sftpgw.cloud;
root /usr/share/nginx/admin-ui/;
rewrite ^/$ /index.html permanent;
}
After fixing your website.conf file, make sure to run this command to restart nginx:
nginx -t && service nginx restart