Adding security (HTTPS) to your web server easily

The hard task in developing a web server or microservice is to bring in TLS to ensure the communication is secure. Most of the browsers mandate to have an HTTPS website, else the webpage wouldn’t get loaded in the browser. You will have multiple scenarios like below to have an HTTPS.
1. Hosting a public domain website.
2. Communicate between two microservices that are not in the safe domain (packets routed via the internet).
Now the issues in bringing security to your systems are,
1. Different kinds of security implementation for each language and web-server libraries.
2. Generating new certificates, configuring, and renewing it.
3. Cost involved in purchasing a public certificate.
The solution for all these is a Caddy Server. Caddy is a powerful, enterprise-ready, open source web server with automatic HTTPS written in Go. Caddy server will run independently before your web server and work as a proxy.

For simplicity, we run the Caddy server in docker container, and you can run the application either as a container or a process in the same machine. You need to provide the configuration to the caddy server to connect to the application backend. For the below scenario, we are using a python server as an application and listening on 8080 port.
Deploy caddy server locally
- First run your application
root@vm-001:~/caddy/files$ python3 -m http.server 8080
Serving HTTP on 0.0.0.0 port 8080 (http://0.0.0.0:8080/) …
root@vm-001:~/caddy/files$
2. Test the server is running
root@vm-001:~/caddy$ curl http://localhost:8080
<!DOCTYPE HTML PUBLIC “-//W3C//DTD HTML 4.01//EN” “http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
<meta http-equiv=”Content-Type” content=”text/html; charset=utf-8">
<title>Directory listing for /</title>
</head>
<body>
<h1>Directory listing for /</h1>
<hr>
<ul>
</ul>
<hr>
</body>
</html>
3. Now get the IP of the machine where your application is running.
root@vm-001:~$ ifconfig enp0s25
enp0s25: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
inet 10.0.0.4 netmask 255.255.255.0 broadcast 10.0.0.255
inet6 fe80::1ea9:deb0:7a91:205c prefixlen 64 scopeid 0x20<link>
ether xx:xx:xx:xx:xx:xx txqueuelen 1000 (Ethernet)The IP address for the machine is 10.0.0.4
4. Now create a configuration file named ‘Caddyfile’. And replace the IP and destination in the configuration file.
root@vm-001:~/caddy$ cat Caddyfile
10.0.0.4 {
reverse_proxy /* localhost:8080
}
root@vm-001:~/caddy$
5. Run the caddy server
root@vm-001:~/caddy$ docker run — rm -it — network host -v $PWD/Caddyfile:/etc/caddy/Caddyfile caddy
2022/01/09 09:19:47.052 INFO using provided configuration {“config_file”: “/etc/caddy/Caddyfile”, “config_adapter”: “caddyfile”}
2022/01/09 09:19:47.056 INFO admin admin endpoint started {“address”: “tcp/localhost:2019”, “enforce_origin”: false, “origins”: [“127.0.0.1:2019”, “localhost:2019”, “[::1]:2019”]}
2022/01/09 09:19:47.059 INFO http server is listening only on the HTTPS port but has no TLS connection policies; adding one to enable TLS {“server_name”: “srv0”, “https_port”: 443}
2022/01/09 09:19:47.059 INFO http enabling automatic HTTP->HTTPS redirects {“server_name”: “srv0”}
2022/01/09 09:19:47.060 INFO tls.cache.maintenance started background certificate maintenance {“cache”: “0xc00021c000”}
2022/01/09 09:19:47.062 INFO tls cleaning storage unit {“description”: “FileStorage:/data/caddy”}
2022/01/09 09:19:47.062 INFO tls finished cleaning storage units
2022/01/09 09:19:47.105 WARN pki.ca.local installing root certificate (you might be prompted for password) {“path”: “storage:pki/authorities/local/root.crt”}
2022/01/09 09:19:47 Warning: “certutil” is not available, install “certutil” with “apt install libnss3-tools” or “yum install nss-tools” and try again
2022/01/09 09:19:47 define JAVA_HOME environment variable to use the Java trust
2022/01/09 09:19:47 certificate installed properly in linux trusts
2022/01/09 09:19:47.175 INFO http enabling automatic TLS certificate management {“domains”: [“10.0.0.4”]}
2022/01/09 09:19:47.175 INFO autosaved config (load with — resume flag) {“file”: “/config/caddy/autosave.json”}
2022/01/09 09:19:47.175 INFO serving initial configuration
2022/01/09 09:19:47.176 INFO tls.obtain acquiring lock {“identifier”: “10.0.0.4”}
2022/01/09 09:19:47.181 INFO tls.obtain lock acquired {“identifier”: “10.0.0.4”}
2022/01/09 09:19:47.183 INFO tls.obtain certificate obtained successfully {“identifier”: “10.0.0.4”}
2022/01/09 09:19:47.183 INFO tls.obtain releasing lock {“identifier”: “10.0.0.4”}
2022/01/09 09:19:47.183 WARN tls stapling OCSP {“error”: “no OCSP stapling for [10.0.0.4]: no OCSP server specified in certificate”}
6. Test your HTTPS web server from another machine.
root@vm-02:~ root$ curl -k https://10.0.0.4/
<!DOCTYPE HTML PUBLIC “-//W3C//DTD HTML 4.01//EN” “http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
<meta http-equiv=”Content-Type” content=”text/html; charset=utf-8">
<title>Directory listing for /</title>
</head>
<body>
<h1>Directory listing for /</h1>
<hr>
<ul>
</ul>
<hr>
</body>
</html>
root@vm-02:~ root$
Public-facing web server
Now, for production deployment, you can use the domain name you have purchased instead of the IP address. But, before starting the caddy server, make sure that someone already configured the domain name you purchased to route to your VM where caddy server is running.
sampledomain.com {
reverse_proxy /* localhost:8080
}
There are a lot more options available to configure the caddy server, you can find it here.