Self-hosted public site - safe and cheap.
Tags: docker, selfhosted, tutorial, opensource
Published: 2024-06-17 12:06:00

In my first post in the series there where a lot of people that were concerned about exposing local network to public internet, or actually might have a problem with doing that due to ISP limitations like dynamic IP or reverse lookup. That might not be a problem if you order a static IP from your ISP, but not all ISPs make it easy or cheap. There are also several reasons you might want to avoid that.

## Current setup

In my initial post I suggested using Intel NUC to host every tool in the closed off local network that only you have access too. Basically you can install server version of Ubuntu, setup ssh access, install docker, and run any tool you need on that docker (I will post extensive guide in the future). I'm using also Portainer and Traefik as my main containers to actually bind any local address to a new service, so I don't have to jump on different ports, depending on what I want. Now your local address becomes something like portainer.home.local. 


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/yqlxu2h559ejlzhwv8lh.png)


## Moving to public

Now, this type of routing can be incorporated in public environment if you had domain pointing to your static IP, port-forwarded 80 and 443 to your intel NUC from router, and let Traefik take over routing over subdomains. That's classic way of routing traffic. In fact, that's not so different from spinning up EC2 with docker and doing that yourself on external network. Definitely it's safer this way.

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ns5ed3e172ptsgj2l67k.png)

But we are going the economic way, and actually the best of both worlds: tunneling. That's right, we will make a bridge between the domain and our container. This way traffic comes from indirect source instead of directly through our router and local network. You can even set up docker network so it's closed off from the rest of your internal network.

There are several tools that allows tunneling like [ngrok](https://ngrok.com/) or [tunnelmole](https://tunnelmole.com/), however, best option is actually [Cloudflare](https://cloudflare.com/). It's free for small amounts of traffic, and works best in docker environment.

### Step 1. Get the domain
Honestly, you can't go public without domain, if you don't have one, you have to grab one. Keep in mind that you need to point DNS towards Cloudflare nameservers so you can't use one that already is occupied by something else. Best services that provide domains for me are:
- [GoDaddy](https://www.godaddy.com/en-uk) - I've been using them for years. I had good experience with their customer service, and most of my domains sits there. 
- [NameCheap](https://www.namecheap.com/) - Name says it all. Solid alternative, some domains comes cheaper then GoDaddy, some don't. But one of the main benefit is - they have `.xyz` domains for $1 a year!

### Step 2. Set up a domain on cloudflare.

Now let's create account on cloudflare and add our domain. Go to websites and add new domain. 

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/lat5mabm70jxte2qpdzh.png)

After you provide domain you already own, you will be asked to subscribe... don't worry, there is free tier, scroll down:

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/l7hnjg0pg3i5kltk0fg7.png)

Do the quick domain scan, click on next, until you get to activation page:

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/d2heui3wqt20xup325w1.png)

Scroll down until you see nameservers:

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/c0olcuodzwauvqa20jkh.png)

Set up DNS records to point to your cloudflare nameservers (don't copy from me, these can be different for you)

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/o9i40i8d2zca1yzg31vk.png)

Now, you need to wait until domain propagates correctly. Depending on where you have your own DNS servers set up, it can take between 5 minutes up to 24 hours. 

### Step 3: Tunnel your traffic. 

Alright, we have cloudflare account and domain set and ready. Let's setup our proxy bridge. Go to "Zero Trust" section: 

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/zwp772lwz7qofc90jsh5.png)

Now expand "Networks" section and select "Tunnels":

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/tmjhwtt65uwlnmwnxrla.png)

Now click on "Create a tunnel" and on the next screen select "Cloudflared". Name your tunnel on the next screen.

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/0jfpyg9uldw4bfl3ogmd.png)

Your tunnel is created, now you have to install it in your docker. But before we do that, we need to setup our network.

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/qgy0gx62l3mek98poc0z.png)


```bash
$ docker network create -d bridge public_services
$ docker run --network=public_services cloudflare/cloudflared:latest tunnel --no-autoupdate run --token <your-token>
$ docker run --name hello-world --network=public_services -d -p 80:80 strm/helloworld-http
$ docker inspect -f '{{range.NetworkSettings.Networks}}{{.IPAddress}}{{end}}' hello-world
$ # 172.17.0.3
```

This way your tunnel will have access only to services that run on the same network. Last command is what you need to get internal networks container ip. We will need that for tunneling.

Let's get back to cloudflare and let's make new routes. Edit your tunnel and go to "Private Network"

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/20rjp5xt5yemnqf0m2wy.png)

Here set up which networks should be visible in your tunnel. Set up CIDR accordingly to your container's IP.

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/p581iq9ze3u7ynei69h2.png)

Now go to "Public Hostname" tab, and click "Add a public hostname"

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/sepd60wub1ba2jsmus9w.png)

Here we set up our routing to a specific domain. We can run multiple services this way, each with it's own specific subdomain, or we can set up our personal website. The best thing is - there are no limitations to technology you want to use, as long as it's dockerized. 

## Conclusion

Setting up a personal domain and hosting your own services can be a daunting task, especially if you're concerned about security and exposing your local network to the public internet. With docker and Cloudflare however it can be actually quite rewarding and fairly safe. It is good extension of your homelab if you have one, without a need to resort to traditional hosting.

With this setup, you can host a variety of services, from personal websites to custom applications, all while maintaining a secure and isolated environment. The possibilities are endless, and the best part is that you have complete control over your data and services.

So, if you've been hesitant to explore the world of self-hosting due to security concerns or technical challenges, give this method a try. You might be surprised at how easy and rewarding it can be to have your own little corner of the internet, all while keeping your local network safe and sound.