Deployment guide

LanCache

Overview

LanCache is a self-hosted caching server for large game and content downloads. It transparently caches HTTP downloads from an allow-listed set of game-content CDNs (Steam, Epic Games, Riot, Blizzard/Battle.net, Origin/EA, GOG, Windows Update and more). A file downloaded once is then served to every other machine at LAN speed, instead of being pulled over the internet again and again.

This guide covers the deployment and use of LanCache on Ubuntu 24.04 on Azure, using SecureAnyCloud Azure Marketplace images. LanCache has two parts, and this image ships both as the official, pinned upstream containers running under Docker:

  • The cache: lancachenet/monolithic, an nginx transparent cache on ports 80 (HTTP) and 443 (HTTPS SNI passthrough).
  • The DNS: lancachenet/lancache-dns, which answers the cached CDN domains with the cache's own IP so clients are steered to the cache automatically. This image runs it in a hardened, closed configuration.

There is no login and no credential of any kind, because a cache and DNS service has no user interface. The appliance is reachable on the network by design, so SecureAnyCloud closes the two ways an internet-facing cache could be abused. Both are proven on every build before the image is captured:

  • It is not an open DNS resolver. The DNS answers only the allow-listed CDN domains (authoritatively, with this VM's IP) and returns REFUSED for every other name. There is no recursion and no forwarding, so it cannot be used for DNS amplification.
  • It is not an open proxy or TLS relay. The cache proxies only allow-listed CDN hosts on port 80, and relays only allow-listed SNIs on port 443. An arbitrary HTTP Host is refused and an arbitrary TLS SNI is dropped.

At first boot, lancache-firstboot.service resolves this VM's own public IP, writes the per-VM DNS zone so the cached domains resolve to it, and starts both containers. Cache data lives on the OS disk under /var/lib/lancache.

What you get:

  • The official lancachenet/monolithic cache and lancachenet/lancache-dns DNS, pulled and pinned by SHA-256 digest (never :latest) and verified against the pin at build time
  • lancache-firstboot.service, a systemd oneshot that resolves the per-VM public IP, renders the DNS zone and starts both containers on the first customer boot
  • A closed DNS with authoritative-only zones for the cached CDN domains and recursion no, so arbitrary names are REFUSED
  • A hardened cache with an nginx allow-list guard on port 80 and an SNI allow-list on port 443, so only the cached CDNs are served
  • The allow-list of game-content CDN domains, extracted from the official lancache-dns image (the uklans/cache-domains data)
  • Cache storage on a 64 GiB OS disk under /var/lib/lancache, expandable for larger caches
  • Ubuntu 24.04 LTS base with the latest security patches applied at build time and unattended security updates enabled
  • Azure Linux Agent for cloud integration and SSH key injection
  • 24/7 SecureAnyCloud support with a guaranteed 24-hour response SLA

Prerequisites

  • An active Azure subscription
  • A subscription to the LanCache on Ubuntu 24.04 listing on Azure Marketplace
  • An SSH public key for VM authentication
  • A virtual network and subnet in the target region, reachable by the client machines you want to serve

Recommended virtual machine size: Standard_B2s (2 vCPU, 4 GB RAM). LanCache is very light on CPU and memory. The two containers together use well under 100 MB of RAM at idle.

The resource that matters for a cache is disk. The more storage you give it, the more content it can hold. For a large LAN party or a busy venue, move the cache data to a larger disk (see Step 7).

Network security group (NSG) ports. Open these to the client networks that will use the cache:

  • UDP and TCP 53: DNS (clients point their resolver here)
  • TCP 80: HTTP cache
  • TCP 443: HTTPS (SNI passthrough) cache
  • TCP 22: SSH, from your management IP range only

Scope ports 53/80/443 to your LAN or client source ranges. The appliance is hardened against open-resolver and open-proxy abuse, but there is no reason to expose a download cache to the whole internet.

1

Deploy from the Azure Portal

Open Marketplace in the Azure Portal, search for LanCache, select the SecureAnyCloud publisher entry, and choose Create.

On the Networking tab, attach a network security group. It must allow inbound TCP 22 from your management IP range, and inbound UDP+TCP 53, TCP 80 and TCP 443 from your client source ranges.

Choose Review + create, wait for validation, then choose Create. Deployment takes around two minutes.

2

Deploy from the Azure CLI

RG="lancache-prod" LOCATION="eastus" VM_NAME="lancache-01" ADMIN_USER="azureuser" IMAGE_URN="sac1647283583153:lancache-ubuntu-24-04:default:latest" SSH_KEY="$(cat ~/.ssh/id_rsa.pub)" az group create --name "$RG" --location "$LOCATION"
# Accept the Marketplace terms once per subscription (required before the first CLI deploy)
az vm image terms accept --urn sac1647283583153:lancache-ubuntu-24-04:default:latest
az vm create \
  --resource-group "$RG" \
  --name "$VM_NAME" \
  --image "$IMAGE_URN" \
  --size Standard_B2s \
  --admin-username "$ADMIN_USER" \
  --ssh-key-values "$SSH_KEY" \
  --public-ip-sku Standard
# Open the LanCache ports (scope the source ranges to your client networks)
az vm open-port --resource-group "$RG" --name "$VM_NAME" --port 53 --priority 1010
az vm open-port --resource-group "$RG" --name "$VM_NAME" --port 80 --priority 1020
az vm open-port --resource-group "$RG" --name "$VM_NAME" --port 443 --priority 1030

Once the VM is running, connect over SSH as your admin user.

ssh azureuser@<vm-ip>
3

Confirm both containers are running

First boot resolves this VM's public IP and starts the cache and the DNS. Confirm that the two containers are up, that the DNS/HTTP/HTTPS ports are listening, and that the cache heartbeat is healthy.

sudo docker ps --format '{{.Names}} {{.Status}}' systemctl is-active docker lancache-firstboot
sudo ss -lntup | grep -E ':53 |:80 |:443 ' curl -s -o /dev/null -w 'heartbeat -> HTTP %{http_code}\n' http://127.0.0.1/lancache-heartbeat

You should see lancache-monolithic and lancache-dns both Up, docker and lancache-firstboot both active, sockets listening on 53, 80 and 443, and the heartbeat returning HTTP 204.

4

Confirm the DNS is closed to abuse

The DNS answers the cached CDN domains with this VM's IP and refuses everything else. Run the commands below. They use the first domain from the shipped allow-list, and the appliance serves well over a hundred CDN domains.

CACHE_IP=$(sudo grep '^LANCACHE_IP=' /root/lancache-credentials.txt | cut -d= -f2-)
CDN=$(head -1 /var/lib/lancache/dns/cache-domains.txt)
echo "cache IP = $CACHE_IP sample cached domain = $CDN"
# A cached CDN domain (and any subdomain of it) resolves to this cache dig +short @127.0.0.1 "$CDN" A dig +short @127.0.0.1 "sub.$CDN" A
# An arbitrary domain is REFUSED - this is NOT an open resolver dig @127.0.0.1 example.com A | grep -E 'status:'

The two dig +short lookups return the cache IP. The example.com lookup returns status: REFUSED with no answer. That is the appliance refusing to recurse for anything outside its allow-list.

5

Confirm the cache is closed to abuse

The cache serves the allow-listed CDNs only. An arbitrary HTTP Host is refused (not proxied), and an arbitrary TLS SNI is dropped (not relayed). Run the commands below to check both.

CDN=$(head -1 /var/lib/lancache/dns/cache-domains.txt)
# A request for a cached CDN domain is handled by the lancache cache (X-LanCache header)
curl -s -D - -o /dev/null -H "Host: $CDN" http://127.0.0.1/lancache-heartbeat | grep -iE 'HTTP/|X-LanCache'
# An arbitrary HTTP Host is refused - the connection is closed, so curl exits non-zero curl -s -o /dev/null -H 'Host: example.com' http://127.0.0.1/ ; echo "arbitrary HTTP Host -> curl exit $? (non-zero / refused = not an open proxy)"
# An arbitrary TLS SNI relays no upstream certificate
CERTS=$(timeout 8 openssl s_client -connect 127.0.0.1:443 -servername example.com </dev/null 2>/dev/null | grep -c 'BEGIN CERTIFICATE')
echo "arbitrary TLS SNI -> certificates relayed: $CERTS (0 = not an open TLS relay)"
6

Point your network at the cache

Point your clients' DNS at this VM to start caching. The appliance answers only the cached CDN domains (with its own IP) and refuses everything else, so it is not a general-purpose resolver. There are two common ways to use it:

  • Conditional forwarding (recommended): On your existing DNS server or router, forward only the lancache CDN domains to this VM. Keep your normal resolver for everything else, so general browsing keeps working through your usual DNS.
  • Per-client: Set the DNS server on the machines you want to cache to this VM's IP. Add a secondary DNS for general name resolution.

The per-VM appliance info file records this VM's IP and how to use it. The container images are pinned by digest. Read both below.

sudo cat /root/lancache-credentials.txt
sudo docker images --digests --format '{{.Repository}} {{.Digest}}' | grep lancachenet df -h /

Once clients resolve a cached CDN through this VM, their first download of a given file fills the cache (a MISS). Every later machine that downloads the same file gets it from the cache at LAN speed (a HIT). No client-side software is needed, because the caching is transparent.

7

Sizing and expanding the cache

Cache data lives under /var/lib/lancache on the OS disk, which ships at 64 GiB. A game or content cache can grow large, so give it more storage for anything beyond casual use. Choose one of these options:

  • Resize the OS disk in the Azure Portal (VM > Disks > the OS disk > Size), then reboot. Ubuntu grows the root filesystem automatically.
  • Attach a data disk, format and mount it at /var/lib/lancache, then reboot so first boot re-populates the cache directory on the larger volume.

The cache manages its own size. It evicts the least-recently-used objects to stay within its configured limit and keeps a minimum amount of free disk, so it will not fill the disk completely.

Troubleshooting

  • A client is not being cached. Confirm that the client's DNS points at this VM and that the CDN domain is in the allow-list. dig @<vm-ip> <cdn-domain> should return the cache IP. Check that the NSG allows UDP+TCP 53 from the client.
  • Downloads fail after pointing DNS here. Make sure ports 80 and 443 are open in the NSG to your clients. HTTPS CDNs need 443, and HTTP CDNs need 80.
  • Container logs: sudo docker logs lancache-monolithic and sudo docker logs lancache-dns.
  • Restart the stack: sudo docker restart lancache-monolithic lancache-dns.

Support

SecureAnyCloud provides 24/7 support with a guaranteed 24-hour response SLA for all Azure Marketplace images. For assistance with this image, contact support through the SecureAnyCloud listing on Azure Marketplace or visit secureanycloud.com.

Deploy on Azure

Launch LanCache on Ubuntu 24.04 LTS on Azure with 24/7 support from SecureAnyCloud.

View this image

Need Help?

Our support team is available 24/7.

sales@secureanycloud.com

Deploy on Azure