Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mint.skeptrune.com/llms.txt

Use this file to discover all available pages before exploring further.

My most valuable skill as a hacker/entrepreneur is that I’m confident deploying arbitrary programs that work locally to the internet. Sounds simple, but it’s really the core of what got me into Y-Combinator and later helped me raise a seed round. This post is about how I got there—and a concrete tutorial to prove the point by building an LLM-over-DNS proxy on a bare VPS in under 30 minutes.

Being on the struggle bus early

When I was starting out hacking as a kid, one of the first complete things I built was a weather reply bot for Twitter. It read from the firehouse API, monitored for mentions and city names, then replied with current weather conditions when it got @‘ed. My parents got me a Raspberry Pi for Christmas and I found a tutorial online. I got it working locally and then got completely stuck on deployment. The obvious next step was using my Pi as a server, but that was a disaster. My program had bugs and would crash while I was away. Then I couldn’t SSH back in because my house didn’t have a static IP and Tailscale wasn’t a thing yet. It only worked on and off when I was home and could babysit it.

Skipping straight to PaaS hell

When I started building web applications, I somehow skipped VPS entirely and went straight to Platform as a Service solutions like Vercel and Render. I was googling “how do I deploy my create react app” and somehow the top answer was to deploy to some third-party service that handled build steps, managed SSL, and was incredibly complicated and time-consuming. There was always some weird limitation: memory constraints during build, Puppeteer couldn’t run because they didn’t have the right apt packages. Then I was stuck configuring Docker images, and since AI wasn’t a thing yet and I’d never used Docker at a real job, it was all a disaster. I wasted more time trying to deploy my crappy React app than building it.

Getting saved by a VPS maximalist

During college, I got lucky and met a hacky startup entrepreneur who was hiring. I decided to take a chance and join, even though the whole operation seemed barely legitimate. Going into the job, I had this assumption that the “right” way to deploy was on AWS or some other hyperscaler. But this guy’s mindset was the complete opposite—he was a VPS maximalist with a beautifully simple philosophy: rent a VPS, SSH in, do the same thing you did locally (yarn dev or whatever), throw up a reverse proxy, and call it a day. I watched him deploy like this over and over, and eventually he walked me through it myself a few times. It was all so small and easy to learn, but it made me exponentially more confident as a builder. I never directly thought, “I can’t build this because I won’t be able to deploy it,” but the general insecurity definitely caused a hesitancy and procrastination that immediately went away.

Paying it forward

I’ve become an evangelist for this approach and wanted to write about it for a long time, but didn’t know how to frame it entertainingly. Then on X, I got inspiration when levelsio posted a tweet about deploying a DNS server on Hetzner that lets you talk to an LLM. Want to see it in action? Try this:
dig @llm.skeptrune.com "what is the meaning of life?" TXT +short
Getting that setup is probably more interesting than my rambling. Here’s how to deploy your own LLM-over-DNS proxy on a VPS in less than half an hour with nothing other than a rented server.

Tutorial: LLM-over-DNS on a bare VPS

The architecture is simple: a Python DNS server that listens on port 53, treats incoming DNS query names as LLM prompts, calls the OpenRouter API, and returns the response as a TXT record. The client is just dig.
You’ll need a VPS with a public IP address (Hetzner, DigitalOcean, Linode, or similar), an OpenRouter API key, and Python 3 on the server. Any Linux image works.
1

Access your VPS

After purchasing your VPS, you’ll receive an IP address and login credentials (usually via email). Connect to your server:
ssh root@<your-vps-ip>
Replace <your-vps-ip> with your actual server IP address.
2

Clear existing DNS services

Many VPS images come with systemd-resolved or bind9 pre-installed. These will conflict with a DNS server running on port 53. Remove or disable them first:
# Check for running DNS services
systemctl list-units --type=service | grep -E 'bind|dns|systemd-resolved'

# Stop and disable systemd-resolved (if present)
systemctl stop systemd-resolved
systemctl disable systemd-resolved

# Remove bind9 (if present)
apt-get remove --purge bind9 -y
3

Install Python dependencies

Install the required Python packages:
pip install dnslib requests
4

Create the DNS-to-LLM proxy script

Create a file called llm_dns.py with the following content. The script listens for DNS queries, extracts the query name as a prompt, sends it to the OpenRouter API, and returns the response in one or more TXT records:
from dnslib.server import DNSServer, BaseResolver
from dnslib import RR, QTYPE, TXT
import requests
import codecs

OPENROUTER_API_KEY = ""  # Add your OpenRouter API key here
LLM_API_URL = "https://openrouter.ai/api/v1/chat/completions"

class LLMResolver(BaseResolver):
    def resolve(self, request, handler):
        qname = request.q.qname
        qtype = QTYPE[request.q.qtype]
        prompt = str(qname).rstrip('.')

        # Forward prompt to LLM
        try:
            response = requests.post(
                LLM_API_URL,
                headers={
                    "Authorization": f"Bearer {OPENROUTER_API_KEY}",
                    "Content-Type": "application/json"
                },
                json={
                    "model": "openai/gpt-3.5-turbo",
                    "messages": [{"role": "user", "content": prompt}]
                },
                timeout=10
            )
            response.raise_for_status()
            raw_answer = response.json()["choices"][0]["message"]["content"]
        except Exception as e:
            raw_answer = f"Error: {str(e)}"

        try:
            answer = codecs.decode(raw_answer.encode('utf-8'), 'unicode_escape')
        except Exception:
            answer = raw_answer.replace('\\010', '\n').replace('\\n', '\n')

        reply = request.reply()
        if qtype == "TXT":
            # Split long responses into chunks of 200 chars (safe limit)
            chunk_size = 200
            if len(answer) > chunk_size:
                chunks = [answer[i:i+chunk_size] for i in range(0, len(answer), chunk_size)]
                for i, chunk in enumerate(chunks):
                    reply.add_answer(RR(qname, QTYPE.TXT, rdata=TXT(f"[{i+1}/{len(chunks)}] {chunk}")))
            else:
                reply.add_answer(RR(qname, QTYPE.TXT, rdata=TXT(answer)))
        return reply

if __name__ == "__main__":
    resolver = LLMResolver()
    server = DNSServer(resolver, port=53, address="0.0.0.0")
    server.start_thread()
    import time
    while True:
        time.sleep(1)
Before running, paste your OpenRouter API key into the OPENROUTER_API_KEY variable. For anything more serious than a demo, use an environment variable to keep your key out of the source code.
This is a proof-of-concept. For production use you’d want proper process management (systemd), structured logging, rate limiting, and to avoid storing API keys in plaintext.
5

Run the DNS-LLM proxy

Start the DNS server. Port 53 requires root privileges:
sudo python3 llm_dns.py
6

Test your service

From another machine, send a DNS TXT query directly to your server’s IP:
dig @<your-vps-ip> "what is the meaning of life" TXT +short
The LLM’s response should appear in the terminal output.
7

Secure your setup (recommended)

Use UFW (Uncomplicated Firewall) to restrict access. Allow SSH so you don’t lock yourself out, allow port 53 for DNS queries, and block everything else:
ufw allow ssh
ufw allow 53
ufw enable
UFW is literally called “uncomplicated” because that’s what a VPS is—uncomplicated. This setup runs as root and stores your API key in plaintext. For anything beyond experimentation, use environment variables, a non-root user, and a process manager like systemd.

Troubleshooting

Make sure you’re running with sudo. Port 53 requires root privileges.
Check your VPS firewall settings and ensure port 53 (UDP and TCP) is open. Most VPS providers have a cloud-level firewall in addition to the OS-level one—check both.
Verify your OpenRouter API key and confirm your account has credits. You can test the API directly with curl before running the DNS server.
Run systemctl status systemd-resolved to confirm it’s actually stopped. If it’s still running, it will bind port 53 and your script will fail to start (or silently fail to receive queries).

References

That’s it. You now have your own LLM-over-DNS proxy running on a simple VPS. No complex infrastructure needed—just SSH in, install dependencies, and run your code. This is the beauty of keeping things simple.