Skip to content

Game cache – Setup local Steam cache that plays nice with piHole

Having a weak internet connection and a huge Steam game collection at the same time can be hard to manage. Since many years there is the LAN Cache project, which provides a DNS interception between your Steam client and the actual download servers of Steam. But having this play nicely with my piHole setup was not so easy.

Lately I got more into gaming again. Having a properly filled game library within Steam and a quite poor Internet connection makes installation times sometimes hard to handle. I was aware of the LAN Cache project since some years. But I cannot get it to play nicely with my piHole DNS server. Since LAN Cache provides a DNS server on its own, which should then forward DNS traffic to piHole which will then filter and forward it again doesn’t fit my inner self. Then I stumbled over this article (which was released some years ago). It tells from the possiblity, to only reroute some of the many DNS names which Steam uses internally and Steam will then pickup all the other DNS Names from this DNS server.

Let’s get one step back and spare some words on LAN Cache. It works as a caching server in your network which caches game downloads (and many more things) on a configureable storage. So first time download will take as long as your internet connection allow it. But second time download will recognize the local cache and download the game from the caching server. Which will take as long as your local network allows it.

I’ve a real old Synology NAS as spare in my Homelab with 3TB of storage available and nothing to do with it. So I decided to create a network share (CIFS / SMB) there and mount it to my good old Docker host. Cause I planned to run the LAN Cache as Docker containers. During later troubleshooting I came over this issue, so here is the already fixed /etc/fstab entry with the noperm option configured.

//nashomelab2.home.lab/lancache /docker/lancache        cifs    file_mode=0777,dir_mode=0777,noperm,username=myuser,password=Supersecret 0       0

Create the mountpoint and mount the volume:

mkdir -p /docker/lancache
mount -a

df -h
Filesystem                       Size  Used Avail Use% Mounted on
tmpfs                            393M  2,0M  391M   1% /run
/dev/sda5                         69G   51G   15G  78% /
tmpfs                            2,0G     0  2,0G   0% /dev/shm
tmpfs                            5,0M     0  5,0M   0% /run/lock
/dev/sdb1                         30G   14G   15G  50% /docker
/dev/sda1                        511M  4,0K  511M   1% /boot/efi
tmpfs                            393M   72K  393M   1% /run/user/125
//nashomelab2.home.lab/lancache  2,7T   12G  2,7T   1% /docker/lancache

As the next step, we setup a docker-compose.yml and an .env file. Templates for both can be found on the lancache Github repository. I adjusted both as you can find it on my Github repository. It consists out of two files. Place them on your docker host:

## See the "Settings" section in for more details

## Set this to true if you're using a load balancer, or set it to false if you're using seperate IPs for each service.
## If you're using monolithic (the default), leave this set to true

## IP addresses that the lancache monolithic instance is reachable on
## Specify one or more IPs, space separated - these will be used when resolving DNS hostnames through lancachenet-dns. Multiple IPs can improve cache priming performance for some services (e.g. Steam)
## Note: This setting only affects DNS, monolithic and sniproxy will still bind to all IPs by default

## IP address on the host that the DNS server should bind to

## DNS Resolution for forwarded DNS lookups

## Storage path for the cached data
## Note that by default, this will be a folder relative to the docker-compose.yml file

## Change this to customise the size of the disk cache (default 2000000m)
## If you have more storage, you'll likely want to increase this
## The cache server will prune content on a least-recently-used basis if it
## starts approaching this limit.
## Set this to a little bit less than your actual available space

## Change this to allow sufficient index memory for the nginx cache manager (default 500m)
## We recommend 250m of index memory per 1TB of CACHE_DISK_SIZE

## Change this to limit the maximum age of cached content (default 3650d)

## Set the timezone for the docker containers, useful for correct timestamps on logs (default Europe/London)
## Formatted as tz database names. Example: Europe/Oslo or America/Los_Angeles

Adjust the LANCACHE_IP and DNS_BIND_IP to your Docker host IP address.

version: '2'
x-restart-policy: &restart-policy "unless-stopped"
    image: lancachenet/lancache-dns:latest
    env_file: .env
    restart: *restart-policy
      - ${DNS_BIND_IP}:53:53/udp
      - ${DNS_BIND_IP}:53:53/tcp

    image: lancachenet/monolithic:latest
    env_file: .env
    restart: *restart-policy
      - 80:80/tcp
      - 443:443/tcp
      - ${CACHE_ROOT}/cache:/data/cache
      - ${CACHE_ROOT}/logs:/data/logs

Attention: As you can see, the monolithic container will use the ports 80 and 443. The whole setup is real picky on this configuration. You HAVE to use exactly these ports. If they are already used on your Docker host, you have to move the other containers or use a dedicated Docker VM for your LAN Cache.

Now, let’s startup the Docker containers:

docker-compose up -d

We need to adjust our DNS server now to resolve the following DNS names to our Docker hosts IP. In my case, I do this within piHole. It should be also no problem to add the two entries on your Windows Steam client in the C:\Windows\System32\drivers\etc file.

With this done, head to your Steam client machine, flush the DNS cache and check that nslookup resolves to your Docker hosts IP.

ipconfig /flushdns
Server:  pi.hole

Addresses:  2602:801:f00b:101::cdc4:6ae


Server:  pi.hole


Restart your Steam app and start installation of whatever game you find reasonable in your game library. Check your logs of your Steam client. You should see something similar to this:

[2023-02-04 13:34:16] HTTP (SteamCache,81) - ( /, host: ::ffff:c0a8:269/depot/380/manifest/8345042109147019893/5/8090246794566534928 - received 200 (OK) HTTP response
[2023-02-04 13:34:16] HTTP (SteamCache,82) - ( /, host: ::ffff:c0a8:269/depot/389/manifest/6097040002094797798/5/955148860839558890 - received 200 (OK) HTTP response
[2023-02-04 13:34:17] HTTP (SteamCache,150) - ( /, host: ::ffff:c0a8:269/depot/382/manifest/7879117186494235404/5/8206363636568985744 - received 200 (OK) HTTP response
[2023-02-04 13:34:17] HTTP (SteamCache,81) - ( /, host: ::ffff:c0a8:269/depot/222/manifest/2205113853857860085/5/8917195103257777657 - received 200 (OK) HTTP response
[2023-02-04 13:34:17] HTTP (SteamCache,83) - ( /, host: ::ffff:c0a8:269/depot/228/manifest/6436857496404272512/5/16879931256834321045 - received 200 (OK) HTTP response
[2023-02-04 13:34:18] HTTP (SteamCache,250) - ( /, host: ::ffff:c0a8:269/depot/221/manifest/5912055835353841475/5/8880914148206817777 - received 200 (OK) HTTP response
[2023-02-04 13:34:18] HTTP (SteamCache,154) - ( /, host: ::ffff:c0a8:269/depot/420/manifest/473508257818189736/5/14981719781643695185 - received 200 (OK) HTTP response
[2023-02-04 13:34:19] HTTP (SteamCache,154) - ( /, host: ::ffff:c0a8:269/depot/422/manifest/3441685239460551354/5/8662106841395042864 - received 200 (OK) HTTP response

As you can see, all Steam caching servers resolve also on my Docker hosts IP ( You may also want to check the logs of the LAN Cache. You can find error logs in your cache folders logs directory. So lets check the actual first time download speed. In my case, they were what they used to be because of my poor Internet connection.

without cache

After the first download has been finished. I uninstalled the game within Steam and triggered the installation again. Now I was curious what speeds I will reach.

with cache

Ok, those poor speeds are totally related to my ancient NAS I’m using. This could differ obviously in your case. But for me, doubling the download speed and having a new usecase for my old NAS is more than enough.


Leave a Reply

Your email address will not be published. Required fields are marked *