Cloudflare Access Gateway configuration
Why would you use a Cloudflare "Access" gateway?
When you have a NAS running at home, it would of course be very nice if you could access the files and pictures on the NAS from anywhere in the world. Since Google Drive or iCloud allows you access from anywhere, it shouldn't be too difficult, right? There's only one problem: security. If your router and internet service provider allow it, it is very easy to open up your home network to the outside world. However, this is not a good idea unless you are a networking export, and you know what you are doing. Immich clearly recommends against exposing the program directly to the open internet.
In the Immich docs, the different options for reaching a NAS in a closed local network are explained very nicely. The safest option is a direct VPN or tunnel connection between your device (the client) and your server. This is possible using openVPN, Wireguard, Tailscale, or Netbird. The issue with these services is that they require an app or a program to run on the client device. This program needs to be running whenever you want to connect to your NAS, and it can drain your phone battery. I personally really like Netbird, so click here for a tutorial on how to set that up as a backup in case your Cloudflare Gateway stops working.
The third option listed in the Immich docs is setting up a reverse proxy. Cloudflare “Access” is a kind of reverse proxy with powerful security options built-in. You can control who can reach the server behind the reverse proxy, and how these users can join the server. If you don't set any restrictions, a reverse proxy allows all traffic to reach the application, since Immich is listening to all traffic on a certain IP address and port. This would be the same as if you open up this port on the router from your internet service provider. In this situation, the safety of your server and home network depends solely on the security of the application. The immich developers indicate that this is a bad idea.
If you configure the access restrictions properly, you get the best of both worlds: you can reach your server from anywhere on the internet, and no-one else can intrude in your server or home network. The diagram below shows how the Cloudflare Gateway allows traffic to reach the server, even though the server itself is not publicly accessible. This arrangement is an example of a reverse proxy.
What you need to get started
In this tutorial, I will explain a safer alternative to port forwarding. I will guide you through the steps of exposing your server to the open internet, while ensuring that only authorized users can access the server. To achieve this, I use Cloudflare Access as a reverse proxy. This can be useful for all kinds of self-hosted servers, such as a Minecraft server, Immich server, or NAS.
Before you can get started, you will need the following:
A server or NAS running Ubuntu which is located in a closed local network
SSH or CLI access to the server or NAS
A domain name
The first two items are explained in a previous page of this project. You can use an SSH connection on the local network, or if you have set up Netbird, you can even SSH to your server from anywhere and configure the Gateway while you're away from home.
The last item will cost you around $10 per year, but since I am already hosting this website (www.qluyten.com), I am already paying for a domain name. There are many ways to purchase a domain name, but for this tutorial you will need a domain name which is managed by Cloudflare. I also recommend purchasing .com domain names from Cloudflare, since they don't offer deceiving first-year discounts, where the first year costs you $2 and the next year you are charged $35. Also, Cloudflare charges only a little more than the fixed yearly fee that every .com domain needs to pay to Verisign. Verisign is the .com registrar company managing the top-level-domain root server. Of course, you can also buy your domain elsewhere, and transfer it to Cloudflare.
Once you have access to your Cloudflare dashboard and your server, we can start setting up the reverse proxy.
The process consists of the following steps:
Setting up your Cloudflare Access Dashboard
Establish a Cloudflared tunnel
Configure an application with Cloudflare Access
Configure the Access Gateway to allow your traffic to reach the application
Configure service tokens to allow the Immich app to reach your server
- Setting up your Cloudflare Access Dashboard
If you have bought a domain name and transferred it to Cloudflare, you should have this domain listed when you click on the Cloudflare logo in the top left. This is the homepage of the Cloudflared dashboard. Now you are ready to set up Cloudflare Access.
Click “Zero Trust” and follow the onboarding process. The “Team domain” name will become the URL of the authentication page where people can request access to your server. If you go to photos.qluyten.com, you will see my “Team domain” name in the URL. In the next step, you can select the free plan.
Once you are done with the onboarding process, you will end up in the “Zero trust home” dashboard. Notice that Cloudflare really pushes their WARP application. We will not need it for our reverse proxy setup.
2. Establish a Cloudflared tunnel
Navigate to Network → Tunnels
Click + Create a tunnel
Select Cloudflared
Give a name to the tunnel. This name is only for your own administration.
Click Save tunnel
You will be redirected to the overview page of the tunnel you created. Select Debian and arm64-bit to install the Cloudflared tunnel on the Raspberry Pi.
The dashboard will instruct you to follow a series of commands to install the tunnel. Start with the curl command and then unpack the download using dpkg.
The sudo cloudflared service install xxx command includes a personal key to connect the tunnel to your Cloudflare account.
The tunnel will be installed as a systemctl service. This means that the Debian OS of the Raspberry Pi can start the tunnel when the Pi boots up. To manually start the service, use the command: sudo systemctl start cloudflared. You should only need one tunnel, even if you want to proxy multiple services from your home network. If the cloudflared tunnel is running correctly, you will see a Healthy status in the Zero trust dashboard:
3. Configure an application with Cloudflare Access
This step consists of two parts: First, we should tell Cloudflare that you want to have access restrictions on an application. Then, you need to ensure the application is reachable through the tunnel while being protected by these access restrictions. To configure the access restrictions on an application:
Click on Access in the sidebar of the Cloudflare Zero Trust dashboard. Select + Add an application.
Select Self Hosted
Give your application security policy a name. I used Immich for my first policy
The session duration determines how long client devices will be authorized to access the application after authentication. For example, if the duration is 1 week, users will lose access to the server after one week, and they will have to log in with Cloudflare to gain access again.
Under Application Domain, select your Domain name from the dropdown list and optionally enter a subdomain. This will become the publicly accessible URL behind which your Immich server or other application will become available.
No other settings need to be changed. Click Next.
You will be forwarded to the Policy page. Here you can configure who can access your server, and how. Unless you are a professional user, there will only be one method your clients can use for authentication: Users can enter their email address, and if your policies allow them access, they will receive a one-time-pin which can be used to access the server behind the Cloudflare Access Gateway. By default, all traffic is blocked unless a policy explicitly allows a client to reach the server.
Enter a name for a policy. We will create a policy which will whitelist certain email addresses.
Select Allow for the action, and choose Same as application session timeout for the Session duration.
Scroll down to Configure rules. Under Include, select Emails. Enter an email address. If you want to include multiple email addresses, use a new include line for every address by clicking on + Add include.
Click next and click Add application.
If you configured the Access correctly, you should see the Application name in the Cloudflare Zero Trust dashboard under Access → Applications. If you edit the application, you can see the access policies you have set up. If you want to host multiple services on your server, you will have to set up an application for each service you want to host.
4. Configure the Access Gateway to allow your traffic to reach the application
There is one last step we need to do to make the server safely accessible. We need to tell the Cloudflare Gateway that the server should be reachable at the URL we configured in the previous step. We will configure the cloudflared tunnel to route traffic from this URL through the Access authentication page to your server:
Navigate Networks → Tunnels. Find the tunnel you created.
Click the three dots at the right of the page. Select Configure to edit the tunnel.
Click on the Public Hostname tab in the overview page of your tunnel
Click + Add a public hostname
Select your Domain name from the dropdown list and optionally enter a subdomain. Ensure that this URL is the same as the publicly accessible URL used in the previous step to configure the application. Cloudflare will automatically update your DNS records to forward all traffic from this (sub)domain to your tunnel.
Under Service, select the IP address and port of your application. For Immich, use Type HTTPS, and point it to localhost:2283. We can use localhost since the endpoint of the tunnel is running on the same Raspberry Pi as the Immich application. Port 2283 is the default port used by Immich.
Under Additional application Settings, open the menu Access.
Check the box next to Protect with access to allow Access to protect all traffic to your server. Select the application you created in the previous step to choose the rules you want to use to protect your server.
Click Save tunnel.
If everything is configured correctly, you should now be able to navigate to the publicly accessible URL. You will be prompted to enter an email address and a pin. If your login is successful, you will be redirected to the Immich login page. Below, you can see an example of what the Cloudflare Access authentication page looks like. If you want to host multiple services on your server, you will have to set up a public hostname for each service you want to host.
5. Configure service tokens to allow the Immich app to reach your server
If you want the Immich mobile app to reach your Immich server, even when you are not home, you will have to take an extra step. Since the mobile app can't authenticate itself on the Cloudflare Access authentication page, you need to allow the app to bypass this authentication. You can use service tokens to achieve this:
In the Cloudflare Zero Trust dashboard, navigate to Access → Service auth. Click + Create Service Token.
Name your service token, and give it an expiration time. Once a service token has expired, the Immich app or other applications using the token will no longer be able to connect. You will have to generate a new service token and enter it again in your application.
Click Generate Token.
You receive a Header and Client ID and Secret. For example, the Client ID could be:
CF-Access-Client-Id: 12345678901234567890.access
CF-Access-Client-Secret: 123456789012345678901234567890
Watch out! You only get to see the secret once. If you don't safely write it down somewhere, delete the service token and start again.
Click Save.
Open the Immich app, and navigate to Settings (gear icon) → Advanced → Custom proxy headers
Configure the fields as shown in the image below. Now your Immich app should be able to reach your Immich server on the publicly accessible URL you defined earlier.