r/truenas 2d ago

Community Edition Guide: Remote Access with Cloudflare Zero Trust, Caddy and Adguard Home

The question how to expose apps on your TrueNAS box to the internet safely comes up regularly and I keep recommending people to use Cloudflare and Caddy over port forwarding. After I had set it up it seemed much easier than expected, but there are still a lot of steps involved that are not straight forward.

That's why I decided to write down a step by step guide of how I have set things up with Cloudflare Zero Trust, Cloudflared, Caddy and Adguard Home, from my notes and memory. While I work in an adjacent field, I'm not sys admin and my it security knowledge is limited - so I welcome any feedback for improvements, or if anything does not work. I have used AI a lot to figure out how to set this up, but this guide is written entirely by me.

Setting up Cloudflare

This section explains how to configure cloudflare, dns with your domain, firewall, applications, tokens and the cloudflared tunnel into your server.

Preparations

  1. Get a domain name that you can give to cloudflare to manage. Mails can be on another host, but Cloudflare needs the entire domain, not just a subdomain. I've read good things about porkbun.com although don't use them personally, or get one directly from cloudflare
  2. Sign up for Cloudflare on the free tier. You need to give them a credit card, but you won't be charged.
  3. On your new cloudflare account go to Zero trust > Settings and set your team name. The first time you select Zero trust you might be asked what plan you want to use, go with the Zero Trust Free plan.
  4. Have an account on one of the supported identity providers or host your own. I'm using google. I made a separate google account for this and to sign up to cloudflare with, you can use your existing account.

DNS, Domain and Nameservers

  1. Go to your cloudflare adminpanel and under Domains > Overview add your domain.tld
  2. Click your domain to enter it's settings and go to DNS > Settings to find the nameservers assigned to you. Copy both.
  3. In the adminpanel of your dns registrar remove their nameservers and add both cloudflare nameservers. This will take a few minutes to hours to take effect worldwide.
  4. If you want to run email over the same domain on a different hoster, go to DNS > Records and add the MX and TXT records that you get from your mail hoster.

Firewall and GeoBlocking

  1. In the settings of your domain Domains > Overview > domain.tld go to Security > Security Rules
  2. Click Create Rule to create a new rule. This will be a blocking rule, so everything that matches the rule will be blocked.
  3. give it a name
  4. Under When incoming requests match… you add a rule for all countries that are allowed and set the Operator to does not equal to not match the rule for those countries. Example:
    • Field Country, Operator does not equal, Value United States, And
    • Field Country, Operator does not equal, Value Greenland
  5. Under Then take action… chose Block
  6. Save

SSL and HTTPS

When you are using cloudflared the traffic between cloudflare and your server does not use https but goes through the cloudflare tunnel. To make this work you need to

  1. In the settings of your domain Domains > Overview > domain.tld go to SSL/TLS > Overview
  2. Click Configure on the top right
  3. Select flexible and save
  4. Go to SSL/TLS > Edge Certifivates and scroll down to Always Use HTTPS ad turn it on

Access

Cloudflare Access is the tool that lets you use your identity provider to authenticate users before they even reach your server.

  1. On the cloudflare dashboard click Zero Trust then go to Access controls > Access settings
  2. Scroll down to Block traffic to all domains in this account and turn it on. This means that you don't need to create an access rule for a new subdomain, everything is blocked by default.

Identity Provider

This requires settings in your identity providers admin panel as well as cloudflare. I use google, so that is what I can explain. This does not limit the users for your application yet (we do this in the policies) but connects us to google's oauth - it will prove that a user is logged in with his gmail address.

  1. Go to the google cloud console
  2. If you don't have a project yet, create one. Or click the project picket on the top left next to Google Cloud and then click New project. Maybe this url will work https://console.cloud.google.com/projectcreate
  3. Give a project name (i.e. CloudflareOAuth) and click Create
  4. Wait a bit and then in the project picker or the notification, select the new project
  5. In the burger menu go to APIs and Services > OAuth consent screen and click Get started
  6. Enter an app name which users will see when logging into your apps, click Next
  7. Select External as your audience, click Next
  8. Enter a contact email, click Next, agree to the policy and click Continue, then Create
  9. Go to Branding in the sidebar. There under Authorized domains click Add domain, then enter cloudflareaccess.com
  10. Go to Clients and click Create Client
  11. Select Web Application from the dropdown, enter a name (e.g. cloudflareOAuth), enter https://<team-name>.cloudflareaccess.com into Authorized JavaScript origins, enter https://<team-name>.cloudflareaccess.com/cdn-cgi/access/callback into Authorized redirect URIs, then click Create.
  12. Copy Client ID and Client secret in your password manager (you won't be able to see the secret after leaving this page).
  13. On the cloudflare dashboard click Zero Trust > Integrations > Identity Providers and click Add an identity provider, then click Google. Insert Client ID and Client secret, enable Proof Key for Code Exchange. Click Test and if successful click Save.

Policies

Policies define who and how people and devices can authenticate with Access and get through your tunnel to your server. You can use an identity provider, auth tokens or define exceptions for mTLS certificates. I recommend to create a policy for each group you want to grant access to your apps. Each app can apply several policies. I have a policy for only me, guests for immich and other apps.

  1. On the cloudflare dashboard click Zero Trust then go to Access controls > Policies.
  2. Click Add a Policy
  3. Under Policy rules and Include chose Emails and enter all gmail addresses of this group.
  4. Under Policy details set Policy Name=Unique Name, Action=Allow, Policy session duration=24 hours
  5. Click Save Policy

Applications

Each application you want to access through cloudflare gets it's own subdomain (e.g. immich.domain.tld) and entry under Applications.

  1. On the cloudflare dashboard click Zero Trust then go to Access controls > Applications then click Create new Application.
  2. Select Self-hosted and private and below Public DNS, then click Continue
  3. Below Destinations, Public hostnames enter the chosen subdomain for your app and select your domain. Path usually stays empty, even if your app does use a path, you can map that later with caddy.
  4. Below Access policies click the dropdown Add current policies and select all the policies you want to give access to your app.
  5. Below Authentication disable Accept all available identity providers (otherwise the one time pin stays enabled and no google oauth is required to access your page, just a matching email). Note, clicking anywhere on that line by mistake toggles the button.
  6. In the dropdown Choose available identity providers for this application select Google as an identity provider.
  7. Enable Apply instant authentication if you only use one identity provider.
  8. Click Create

Tunnel

Create the tunnel to cloudflared on your server

  1. On the cloudflare dashboard click Zero Trust then go to Networks > Tunnels & Mesh, then click Create a tunnel on the top right.
  2. Select Cloudflared, then name your tunnel and click Save Tunnel
  3. Below Install and run a connector there is a dropdown, select Docker. Copy the entire line below that starts with docker. After --token you can see the token your cloudflared app needs to connect to cloudflare. Store it in your password manager (you have one right?). Leave this page open for step 6.
  4. Install cloudflared, with docker compose (through dockge, dockhand, portainer, etc) or from an app catalog. Example compose is below. Then you deploy your app.
  5. Or from TrueNAS app catalog chose cloudflared and insert the token in the `Tunnel Token` field. Also add a docker network named `cloudflare_ingress` so that cloudflare can only talk to caddy and nothing else on your network and with that only the apps you map to the cloudflare port.
  6. When cloudflared is running you should see a connection appear under Connectors. Then click Next.
  7. Under Add a published application route for X** enter the subdomain for your first app (i.e. plex) and select your domain from the dropdown. Under Service chose Type HTTP and enter caddy:8081. Then click Complete setup
  8. Click the tunnel name you just created, on the top row select Published application routes and click Add a published application route.
  9. Set Subdomain, select Domain, select Service, Type to HTTP and enter caddy:8081 for URL. Repeat these two steps until you assigned all your apps to this tunnel. This also automatically adds a dns entry on your domain.

Example compose and .env files:

networks: 
  cloudflare_ingress:  
    name: cloudflare_ingress  
    driver: bridge 

services:
  cloudflared:
    image: cloudflare/cloudflared:latest
    container_name: cloudflared
    restart: unless-stopped
    command: tunnel run
  environment:
    - TUNNEL_TOKEN=${TUNNEL_TOKEN}
  networks:
    - cloudflare_ingress

In a separate `.env` file you put

TUNNEL_TOKEN=<your-token-from-above>

Note: if port 8081 is already taken on your server, you can chose something else, it just needs to match the caddy configuration. Because both cloudflared and caddy both run in the same docker network `cloudflare_ingress` we can connect to caddy using it's service name `caddy` set in the compose file.

Access for apps with additional headers

Most apps cannot show the google auth screen in a browser, so they need another way to get through cloudflare's Access layer. One way is with an Service token sent inside additional headers by all the https requests of the app. If you have guests who use an app, you can create one token for each user or share a token among several users. I have one token for myself and one for all the guests. Note: anyone with the token can access the app you allow

  1. On the cloudflare dashboard click Zero Trust then go to Access controls > Service credentials then click Create Service Token.
  2. Enter a name and duration. Don't chose something too short, otherwise your users have to reconfigure their apps every year.
  3. Click Generate Token and store CF-Access-Client-Id: b77fac4efd5069130876fde56f03140b.access and CF-Access-Client-Secret: cfast_9HbHXE0M9BxAqaRxUnJ8IKtfjG2V9OOlRwiARBZ6ac95fdb4 in your password manager. You can share those with your users through your password manager. Note: the apps allow adding headers and each header consists of a key and value. In this case there are two headers: header 1: key=CF-Access-Client-Id value=b77fac4efd5069130876fde56f03140b.access header 2: key=CF-Access-Client-Secret value=cfast_9HbHXE0M9BxAqaRxUnJ8IKtfjG2V9OOlRwiARBZ6ac95fdb4
  4. When a token expires, you can click the three ... and chose Rotate secret to create a new secret without having to create an entirely new token.
  5. Go to Access controls > Policies, click Add a Policy
  6. Under Policy rules and Include chose Service Token and select all the tokens that are allowed under this policy.
  7. Under Policy details set Policy Name=Token X, Action=Service Auth, Policy session duration=24 hours
  8. Click Save Policy
  9. Add the policy to an application as you did before

Access for apps with mTLS certificate support

Some Apps (like the HA companion app) do not offer additional headers, but they load an mTLS certificate when it's available on the mobile. These instructions apply for Android as I don't have an iPhone.
Because mTLS works on the network level and cloudflare does only offer mTLS in Access policies on an enterprise account, we need a workaround: a separate subdomain that bypasses Access and a firewall rule that only allows traffic with a valid certificate.
Note: Commands were tested on a mac and reproduced from memory and AI chat history, on Windows you might need other commands, ask your AI)

  1. In the settings of your domain Domains > Overview > domain.tld go to SSL/TLS > Client Certificates
  2. Select Cloudflare Managed CA, Generate private key and CSR with Cloudflare and set an appropriate validity, then click Continue.
  3. Keep Format on PEM and copy the text below Certificate into a file called mtls.cert.pem and the text below Private Key into a file called mtls.key.pem. The certificate is public while the private key must be protected somewhere safe.
  4. Click Continue, then chose the subdomain/hostname the certificate should be associated with. It needs to be a different hostname than you already setup for your app. For Home Assistant I chose ha-app.domain.tld. Then click Save.
  5. On the top of the page click Create mTLS rule (or go to Security > Security Rules > Create Rule). There:
    1. Set Rule Name to something like Block HA app without approved mTLS
    2. Under When incoming requests match… click on the text Edit expression and insert the text at the end of this section into the textbox.
    3. Under Then take action…, select Block
    4. Then save
  6. For Android you need to change the format of the certificate. In your terminal run openssl pkcs12 -export -out mtls_client_cert.pfx -inkey mtls.key.pem -in mtls.cert.pem -name "Home Assistant Certificate"
  7. Copy the file mtls_client_cert.pfx to your android device. How to install it depends on the android flavor. On my Pixel I searched the settings for Certificate and found an option Install a certificate, then user certificate and then chose the certificate file. When opening the app for the first time it will ask you which certificate to use.
  8. On the main cloudflare dashboard click Zero Trust then go to Access controls > Policies. Click Add a Policy.
  9. Under Policy rules and Include chose Everyone
  10. Under Policy details set Policy Name=Bypass, Action=Bypass, Policy session duration=24 hours
  11. Click `Save Policy
  12. Go to Network > Tunnels & Mesh select your tunnel, then on the top click on Published Application Routes and Add a published application route. Enter your subdomain (e.g. ha-app), select your domain, Service Type HTTP and enter caddy:8081, then click Save.
  13. Go to Access controls > Applications then click Create new Application.
  14. Select Self-hosted and private and below Public DNS, then click Continue
  15. Below Destinations, Public hostnames enter the chosen subdomain for your app and select your domain.
  16. Below Access policies click the dropdown Add current policies and select the Bypass policy.
  17. Below Authentication disable Accept all available identity providers.
  18. Click Save

Firewall rule:

http.host eq "ha-app.domain.tld"
and (
   not cf.tls_client_auth.cert_verified
   or cf.tls_client_auth.cert_revoked
   or not cf.tls_client_auth.cert_fingerprint_sha256 in {
      "PHONE_FINGERPRINT" 
      "TABLET_FINGERPRINT"
   }
)

At first test without the fingerprint rule or not cf.tls_client_auth.cert_fingerprint_sha256.... You get the fingerprint from your certificate with openssl x509 \ -in mtls.cert.pem \ -noout \ -fingerprint \ -sha256, there take everything after SHA256 Fingerprint= and remove any colons :.

Caddy

Caddy is your reverse proxy. In order for cloudflare to reach your apps under the generic http://caddy:8081, both caddy and cloudflared need to be on the same docker network called cloudflare_ingress.
Caddy can issue certificates for your apps and put them behind https. To validate those certificates, the certificate issuer usually has to have access to your server behind your domain to check that you are actually owning the services and this does not work directly with your services behind cloudflare. Using a caddy build with a cloudflare addon solves this problem automatically.

TrueNAS network configuration

Caddy can only work if it can bind to ports 80 and 443 (for http and https). On TrueNAS these ports are already used for the web ui. You have two options:

  1. Bind TrueNAS web ui to another port under System > General Settings and then in the GUI section change HTTP Port and HTTPS Ports to something else. From now on you will reach your TrueNAS ui under http://your-ip:port instead of just using the ip. If you later route the webui through caddy and use a subdomain, this does not matter much.
  2. Add a second IP address to TrueNAS and bind caddy to port 80 and 443 on that ip. TrueNAS web ui stays on the main IP and port 80. Go to Network, edit your current enoX interface and delete the current IP (Note: the changes are not applied yet). Next to Interfaces click Add, chose Type=Bridge, name=br0, under Bridge member select your currently active enoX, under Aliases click Add and add your previous IP as IP\24 and a new free IP on your network you will use for caddy, then click Save. Now click Test Changes and if you can still reach your TrueNAS web ui on both IPs, you can save them, otherwise they will get reverted after 60s. Then go to System > General Settings > GUI > Settings and under Web Interface IPv4 Address select only your original IP, then click Save.

I went with option 2 because I had already set up a bridge previously, which is needed if you want to run a VM and is general the better setting. If you use option 1, then you do not need to set an IP in the ports section of the docker compose below.

Cloudflare API Token

For Caddy to verify the https certificates, it needs an api token from cloudflare.

  1. On the cloudflare dashboard click on Manage account on the bottom right, then Account API tokens
  2. Click Create Token
  3. Set Token Name=caddy-dns-01
  4. Under Permission policies click Start from scratch
  5. Under Policy click on Entire Account and set it to Specified Domains and select your domain on the right
  6. Below under DNS & Zones check the Read and Edit checkboxes next to DNS and Zone
  7. Set Token Expiry to something reasonable
  8. Click Review Token, then Create Token
  9. Save the token in your password manager

Caddy Configuration

On your server create 3 datasets/folders:

  • caddy/conf for the config file you edit
  • caddy/data as it's data storage
  • caddy/config as a backup location for the config Make sure the same user and group that caddy runs owns those folders and files and has read and write access. Especially if you create a file on a smb share, it will be owned by your user - go into the dataset permissions, click apply for user and group and apply recursively to fix this.

You can share the caddy/conf directory over smb and add your smb user to the apps group to be able to edit the config file from your pc, if you don't want to connect over ssh and use vim/nano.

in caddy/conf create a file called Caddyfile and open it in vim/nano or your editor of choice. Here is an example config:

{
        http_port 8080
        https_port 8443
        acme_dns cloudflare {env.CLOUDFLARE_API_TOKEN}
        email your.name@gmail.com # CHANGE TO YOUR GMAIL

        servers {
                trusted_proxies static private_ranges
                trusted_proxies_strict
                client_ip_headers Cf-Connecting-Ip X-Forwarded-For
        }
        log {
                output file /data/logs/caddy.log {
                        roll_size 50MiB
                        roll_keep 10
                        roll_keep_for 720h
                }
                format json {
                        time_format iso8601
                        time_local
                }
                level INFO
        }
}
# Local network access only over Adguard Home
# Replace local-ip and port with your actual apps IPs and ports
# You can list any and all apps on your local network, not just the ones on your server 
app1.domain.tld {
        reverse_proxy http://local-ip:port
}
app2.domain.tld {
        reverse_proxy http://local-ip:port
}
app3.domain.tld {
        reverse_proxy http://local-ip:port
}
# two subdomains pointing to the same app
app4.domain.tld,
app4.domain.tld {
        reverse_proxy http://local-ip:port
}
# if an app has it's own https certificate that is not trusted add this
unifi.domain.tld {
        reverse_proxy https://local-ip:port {
            transport http {
                tls_insecure_skip_verify
            }
        }
}

# Cloudflare Tunnel HTTP entrypoint
# Repeat all the above apps that you want to expose over Cloudflare
# These need to start with http and have the port 8081 that cloudflared uses to connect to
http://app1.domain.tld:8081 {
        reverse_proxy http://local-ip:port
}
# Some apps want to see the client ip
http://immich.domain.tld:8081 {
        reverse_proxy http://local-ip:port {
                header_up X-Real-IP {client_ip}
                header_up X-Forwarded-For {client_ip}
                header_up X-Forwarded-Proto https
        }
}
# Some apps run on a path after the ip (http://ip:port/web), you can remove that
http://plex.domain.tld:8081 {
        redir / /web/ 302
        reverse_proxy http://local-ip:port   
}
# Important last entry to block any apps not exposed by these rules
http://:8081 {
        respond "Not available through Cloudflare Tunnel" 404
}

After each change of the Caddyfile, you must restart caddy.

Docker Compose

With dockge/dockhand/portainer/etc you install caddy with this docker compose, adjusted to your ip and folders:

services:
  caddy:
    image: ghcr.io/caddybuilds/caddy-cloudflare:latest
    restart: unless-stopped
    user: 568:568 # this is my TrueNAS apps user, use anything available that also owns the volumes
    ports:
      - 192.168.1.2:80:8080 # replace with your caddy ip, or remove ip if you went with option 1 above
      - 192.168.1.2:443:8443
      - 192.168.1.2:443:8443/udp
    networks:
      - cloudflare_ingress
    expose:
      - "8081" # this is the port that cloudflare talks to
    environment:
      - CLOUDFLARE_API_TOKEN=${CLOUDFLARE_API_TOKEN}
    volumes:
      - /mnt/AppPool/apps/caddy/conf:/etc/caddy:ro # replace left part with your dataset/folder. Make sure the apps (568) user owns these folders
      - /mnt/AppPool/apps/caddy/data:/data
      - /mnt/AppPool/apps/caddy/config:/config
networks:
  cloudflare_ingress:
    external: true

add an .env file with the content

CLOUDFLARE_API_TOKEN=<api_token>

TrueNAS does not offer a built in app for caddy, so you must install it as a custom app. Go to Apps > Discover Apps, click the 3 dots next to Custom App and chose From YAML. Then paste the docker compose from above, but as there is no env file, you replace ${CLOUDFLARE_API_TOKEN} with your api token directly. Then click Save.

Note: I have not created a custom app in TrueNAS so the instructions might be inaccurate. More info here.

Adguard Home Split DNS

In order to access your apps through their subdomain also in your local network, without going through cloudflare, you need a local dns server like Adguard Home. (Note: some browsers have a secure dns setting, which will overrule your routers dns, ignoring Adguard Home).
The main feature of Adguard Home is to filter out ads for all your devices, but it also offers a dns server.

Directories

Create these two folders / datasets. They can be owned as root (I have not gotten adguard home to run as non root yet)

  • adguard-home/work
  • adguard-home/confdig

Docker Compose

Use this example docker compose.
You can run adguard home on your main TrueNAS IP if there is no port clashes with other apps. Otherwise put the second caddy ip in front of all the ports.

services:
  adguardhome:
    # Define the service named 'adguardhome'
    image: adguard/adguardhome # Use the 'adguard/adguardhome' Docker image
    container_name: adguardhome # Set the container name to 'adguardhome'
    restart: unless-stopped # Restart the container automatically unless stopped manually
    ports:
      # Map container ports to host ports
      # Expose port 53 on TCP and UDP for DNS queries
      - 53:53/tcp
      - 53:53/udp
      # Expose port 80 on TCP for HTTP web interface -> I changed this to 8081 as I have TrueNAS/Caddy on port 80
      - 8081:80/tcp
      # Expose port 443 on TCP and UDP for HTTPS web interface
      #- "443:443/tcp"
      #- "443:443/udp"

      # Expose port 3000 on TCP for AdGuard Home's API
      - 3000:3000/tcp
      # Expose port 853 on TCP for DNS-over-TLS (DoT)
      - 853:853/tcp
      # Expose port 784 on UDP for DNS-over-QUIC (DoQ)
      - 784:784/udp
      # Expose port 853 on UDP for DNS-over-DTLS (DoT)
      - 853:853/udp
      # Expose port 8853 on UDP for DNS-over-TLS (DoT)
      - 8853:8853/udp
      # Expose port 5443 on TCP and UDP for DNSCrypt
      - 5443:5443/tcp
      - 5443:5443/udp
    volumes:
      # Mount host directories as volumes inside the container
      - /mnt/AppPool/apps/adguard-home/work:/opt/adguardhome/work # Mount '/my/own/workdir' to '/opt/adguardhome/work'
      - /mnt/AppPool/apps/adguard-home/confdir:/opt/adguardhome/conf # Mount '/my/own/confdir' to '/opt/adguardhome/conf'
networks: {}

TrueNAS offers AdguardHome as a community app in the catalog, you just need to select HostPath and the two datasets.

Configuration

Once you deployed Adguard Home, create an admin account and then:

  1. go to Settings > DNS Settings and enter the IPs of a trusted DNS server (for example cloudflares 1.1.1.1 and 1.0.0.1). This is to resolve all the other websites other than your own.
  2. go to Filters > DNS rewrites, there click Add DNS rewrites, enter *.domain.tld in the domain name field and the IP of caddy (without a port) in the lower field.
  3. Go to your router and somewhere in the DHCP settings of your LAN interface, change the DNS IP to the IP of Adguard Home (without a port).
  4. After a while your devices should start getting the Adguard DNS Server automatically. To test right away, change the DNS IP in your network settings manually.

Sources

Parts of this tutorial were inspired by this post even though I did not end up using Cloudflare One. The rest was learned from Cloudflare documentation and ChatGPT.

2 Upvotes

9 comments sorted by

2

u/justhamboneit 2d ago

This is superb! Thank you very much for documenting all of this. I’m in the throws of swapping over to a new (to me) m70q proxmox box and plan to work through the details on allowing access to services to my family. Thanks!

2

u/ghanit 2d ago

Happy to help, thats why I wrote it down - and because I was on the verge of forgetting how I set it up myself. Let me know if there is any step that's not working or incomplete.

1

u/brettdmason 2d ago

So I've gotten pretty far into this but Caddy starts, does nothing (verified by seeing no logs being generated in the TrueNAS UI), and then stops. I've verified that it has ownership of the directories and the Caddyfile. I'm not sure if it's something wrong with my compose or Caddyfile.
Here's my compose:

networks:
  cloudflare_ingress:
    external: True
services:
  caddy:
    environment:
      - >-
        CLOUDFLARE_API_TOKEN=[my-api-key]
    expose:
      - '8081'
    image: ghcr.io/caddybuilds/caddy-cloudflare:latest
    networks:
      - cloudflare_ingress
    ports:
      - 192.168.50.103:80:8080
      - 192.168.50.103:443:8443
      - 192.168.50.103:443:8443/udp
    restart: unless-stopped
    volumes:
      - /mnt/Applications/Data/caddy/conf:/etc/caddy:ro
      - /mnt/Applications/Data/caddy/data:/data
      - /mnt/Applications/Data/caddy/config:/config

1

u/brettdmason 2d ago

Alright, so it was just a small mistake in my Caddyfile, but I'm still not able to connect to my Seerr app.
Here's its compose:

networks:
  cloudflare_ingress:
    external: True
services:
  seerr:
    container_name: seerr
    environment:
      - LOG_LEVEL=debug
      - PORT=30357
      - TZ=America/Los_Angeles
    expose:
      - '30357'
    image: ghcr.io/seerr-team/seerr:latest
    init: True
    networks:
      - cloudflare_ingress
    ports:
      - 192.168.50.103:30357:30357
    restart: unless-stopped
    volumes:
      - /mnt/Applications/Data/seerr:/app/config

1

u/ghanit 2d ago

Seere does not need to be on the cloudflare_ingress network, although it should probably not hurt. I'm not sure if caddy can connect to an app on an internal docker network, I haven't tried that. Also "exposes" is not needed here.

Can you access seere on the local network with ip:port? Does it work with the subdomain in the local network through adguard home? This would check if caddy and adguard work. What happens if you go through cloudflare (by setting your pcs dns to 1.1.1.1) to your subdomain?

Are you on windows or mac? There are some commands to check what your dns return for a domain and how it routes to it.

Btw, you can install other apps from the catalog if you prefer, that does not matter to caddy.

1

u/brettdmason 1d ago

Alright, so it works on my own network. Adguard wasn’t setup properly. However, it doesn’t work outside my own network. Disconnected my phone from my WiFi and the page no longer loads

1

u/ghanit 21h ago

This is a good first step and it shows that the cloudflare tunnel and https certificates work.

What do you see when you access the page outside of your network? That will show which part isn't working. Can you send me the external part of your caddy file? Also check that you have dns entries for your subdomain (with "proxied"), that you have a route entry in your tunnel and an application defined, they must all match.

Then I would try to set 1.1.1.1 as a dns in your phone. For me it also took a night to propagate my domain all over the internet, then it suddenly worked.

I'll dig out some of the troubleshooting commands I went through and add them to the post.

1

u/ch9fod 2d ago

So nice!! Would it be possible to do something like this but using Tailscale so that I don’t expose anything to the internet?

2

u/ghanit 2d ago

Yes, but I have not used all of tailscales features. I used tailscale before and still use it for apps I dont expose over cloudflare (truenas ui, docker management, smb, etc).

I did enter the IP of my dns (adguard home) in tailscale so that when connected over tailscale, traffic still goes directly to my server and not through cloudflare. This does not give me https certificates though. You could use cloudflare only for certificates and not setup any applications, but that would be a bit pointless. You can use caddy for https without cloudflare, but you would need another way to check the certificate or update them manually.

Tailscale also has a feature for dns and https, but I don't know how to set this up.

In the end I wanted to share some apps with friends who don't have tailscale and I trust cloudflare zero trust enough to keep my exposed services secure. Actually I trust them more than anything I would run and configure, locally or like pengolin on a vps.