Cloudflare Tunnels
So, I came across a situation where I wanted to expose web services through my cloudflare-managed domain without opening ports or messing with proxy hosts, etc. I came across info for “Cloudflare Argo Tunnels”, or the cloudflared
dameon, and decided to look into it.
Turns out, you can get this as a docker container, though documentation is slim. I’ll be providing how I got it working below.
An Example Service:
Let’s take my jellyfin instance below:
version: "3"
services:
jellyfin:
image: jellyfin/jellyfin
container_name: jellyfin
user: 0:0
# network_mode: "host"
restart: "unless-stopped"
volumes:
- ${PWD}/data/config:/config
- ${PWD}/data/cache:/cache
- /wolf/media/:/media
ports:
- "8096:8096"
So, this service exposes the jellyfin instance to my local network on port 8096. How about getting it on the internet without opening ports?
This is where the next service definition in the file comes in:
cloudflared:
container_name: jellyfin_cloudflared
image: cloudflare/cloudflared:2021.12.3-amd64
volumes:
- '${PWD}/cloudflared/:/home/nonroot/.cloudflared/'
links:
- jellyfin
command: 'tunnel --config /home/nonroot/.cloudflared/config.yml run'
I’ve gone ahead and added the links
section so that our cloudflared container can reference the jellyfin container by name and regardless of other host networking.
But, it’s not that easy. This does require some setup. There are a few commands that need to be run in the docker container to get the right configs and certificate from cloudflare.
- Create the
cloudflared
folder in the same directory as thedocker-compose.yml
, and also dochown 65532:65532 cloudlared
to give it the right permissions for the container. docker-compose run cloudflared tunnel login
to authorize this container to login to your cloudflare account and manage one or more of your zones. This’ll give you a URL to open in browser to complete the authorization there.docker-compose run cloudflared tunnel create media
to create a configuration for this tunneldocker-compose run cloudflared tunnel route dns media media.nyxx.me
to create/manage a CNAME in your cloudflare zone to point to this tunnel in cloudflare’s system.
These commands talk with cloudflare to configure the tunnel and create a couple files in the cloudflared
folder from the docker-compose.yml file:
5e6231ce-6b54-11ec-90d6-0242ac120003.json
- a json file named with a UUID for the cloudflare tunnel (My 5e62 is just an example, yours will be different). This contains the account ID and tunnel authenticationcert.pem
for securing the tunnel with cloudflare.
Now, we’ll want to create a config file ourselves in the cloudflared
folder called config.yml
:
url: http://jellyfin:8096
tunnel: 5e6231ce-6b54-11ec-90d6-0242ac120003
credentials-file: /home/nonroot/.cloudflared/5e6231ce-6b54-11ec-90d6-0242ac120003.json
url:
sets up what endpoint to point the tunnel totunnel
- this is the UUID of the tunnel, which we get from the filename of the generated .json file. from thedocker-compose run
commands earlier.credentials-file:
- we point this at the file location inside the container that corresponds to that generated json file. Now, if we just do adocker-compose run
in the directory of ourdocker-compose.yml
file, this should spin up a cloudflared docker container with our configurations and get our service online.