If you ever want to run a website, you may have heard that you need to buy a web domain for your website. The same idea can help if you want to expose any application running on your home computer to the internet. An example is a VPN server, in case you want to want access to your home server from anywhere in the world.
All data on the internet is exchanged using IP addresses. And to connect to your application, you need to know the IP address of your (home) server since the application is hosted on it. IP addresses are assigned by your internet service provider and can change at any time. You can buy static IPs as well from your service provider. You can check yours using Google here. A custom domain name solves the problem of remembering IP address by providing a human readable text for the same IP address. Domain name service or DNS is used to resolve domain names to their IP address. DNS is free to use and the servers providing this service are maintained by international organizations. In fact, Pi-hole works on the same principle blocking DNS requests for ad-domains.
I wanted to block ads on the go using my home Pi-Hole device. My Pi-hole was hosted on my Raspberry Pi 4 which sits nicely behind the apartment TV. To access it, I needed to install OpenVPN server so that I could access my home network. To install the VPN server, I used an existing script famously known as Road-Warrior. This is a simple helper script installs OpenVPN server and also configures it for you. While configuring, it asks for a public IP address or a domain name so that the VPN server can be accessed from anywhere on the internet.
Since the public IP address of home internet connection(s) can change any time, I used a free domain name service with Dynamic DNS(DDNS) support to overcome IP addresses change issue. DDNS provides the ability to keep updating domain names with IP addresses. I used a famous provider called NO-IP. NO-IP gives up-to 3 free domain names with DDNS support. You need to install a client on your application server which keeps updating the IP address to domain name mapping in the DNS servers. While this service is great, there are certain drawbacks. You only get to choose the subdomain for your website. The main domain is owned by NO-IP itself. I was using a domain called piman.ddns.net to reach my application server. ddns.net is owned by NO-IP and piman is the subdomain that was given for free.
So I started looking at some of the commercial options for custom domains and found Google Domains. This is the cheapest option which I could find to buy domain for as little as $12/year. The other advantage of buying a custom domain name is that you can have unlimited number of subdomains for free. I am currently running this blog as a subdomain on hmehra.dev. Another thing that is of importance is that Google can mark a domain to use Secure Sockets Layer(SSL) by default. This means that the websites hosted using on this custom domain should use SSL for connections. So, SSL comes for free. Extra security is always good.
With SSL came another problem, the web server that I was using was not configured to use SSL and I did not want to perform some manual steps to configure it. I wanted to use a full fledged solution in a docker container with a web server that has SSL already configured. And I did find one with the same criteria. Lets Encrypt by linuxserver.io fits this description.
A little background on the name of the container. Lets Encrypt is a famous certificate authority(CA) that gives free SSL certificates to websites using automated clients. Clients can use the ACME protocol for verification and ownership of the custom domain. Without getting into the details, the docker container mentioned above has a web server and a client which talks this ACME protocol. It will automatically configure your web server to use the certificates provided by Lets Encrypt.
And boom, you can now have a website that is secured using SSL and is hosted on your own home server. You can also use sub-domains to run multiple websites on the same top domain. I am using the web-server as a reverse proxy which just forwards connections to different applications based on the subdomain. The container ships with multiple subdomains examples that can be used on the web server. These can be found in the config folder.
Here is the sample YAML for docker-compose that can be used to create the web server with SSL.
# Docker compose file for LetsEncrypt with Nginx
version: "3.5"
services:
letsencrypt:
image: linuxserver/letsencrypt
container_name: letsencrypt
cap_add:
- NET_ADMIN
environment:
- PUID=1000
- PGID=1000
- TZ=America/Los_Angeles
- URL=<your custom domain>
- SUBDOMAINS=blog
- VALIDATION=http
- EMAIL=<user-email>
volumes:
- ./config/:/config
ports:
- 192.168.0.179:443:443
- 192.168.0.179:80:80
restart: always
networks:
- nginx
networks:
nginx:
name: nginx
And that’s pretty much it. Using this you can run a website and multiple applications on your home server, secure them with SSL and expose them to the internet so that they can be accessed from anywhere in the world. Go Docker and linuxserver.io