TIL: Setting up OpenClaw on a headless VPS


I spent Saturday morning setting up OpenClaw on a fresh Ubuntu server.

OpenClaw is currently the fastest-growing repo on GitHub. People are divided on it. Some see it as the dawn of truly agentic experiences. Others see it as a security nightmare.

I’m enjoying the energy. As someone who has been around long enough to be called “officially old” by my daughter, this moment feels like the early 2000s. Back then, we shared CSS and AJAX tricks to explore what was possible, not to brag. This feels like a return to that spirit of genuine making.

The security concerns are valid, so I opted for a Hetzner VPS instead of my home network.

Securing Access with Tailscale

I followed a setup guide from Tech With Tim to lock down the server. I configured the VPS to listen only on its Tailscale IP. This keeps the SSH ports closed to the public web. As usual, I also found some helpful tips from Simon Willison.

This approach simplifies security. I didn’t have to manage complex firewall rules. I also disabled root login and created a standard user account. The server is only reachable when I am logged into my private Tailscale network.

The OAuth “Chicken-and-Egg” Problem

Getting the Gemini Pro integration working was the hardest part. Most early adopters seem to prefer OpenAI or Claude. I do too, but I get Gemini Pro for free with Google Fi.

OpenClaw uses a headless OAuth flow. You open a URL in a local browser and paste a callback URL back into the server terminal. I hit a loop. I couldn’t get the bot to respond on Telegram without a model, but I couldn’t finish the login while the bot was offline.

I used a workaround:

  1. The Bridge: I set up a temporary OpenAI model to give the bot a brain.
  2. The Ask: With the bot online in Telegram, I asked: Can you change your own model? I want to use Gemini but I can’t get OAuth working on this headless VPS.
  3. The Logic: It gave me instructions how to fix. I replied: Can’t you just do it yourself?

It did. It was a satisfying moment of agentic behavior that worked better than I expected.

Kicking the Tires

I’m not ready to give OpenClaw full access to my data yet. Instead, I asked it to solve a narrow problem. I still love RSS, but most industry signal now comes from X, YouTube, and Hacker News. The volume overwhelms me, and I often feel like I’m missing the important bits.

I gave the bot my OPML file and a list of X accounts and YouTube channels. I told it to create a daily digest. I also asked it to fetch the top 20 posts from Hacker News and filter for keywords like “design,” “ux,” and “ai.”

It built a decent digest. But after a few rounds of refinement, I hit a wall:

Cloud Code Assist API error (429): You have exhausted your capacity on this model. Your quota will reset after 17h33m16s.

I still had 100% of my tokens left, but I had triggered the API rate limits. It was a useful reminder of the constraints of these “free” subscription-based models.

What’s Next

I’ve updated OpenClaw to default to Gemini Flash. I’ll only use Gemini Pro for complex tasks. Flash has much higher limits, so I should be able to avoid “API jail” in the future.

I still haven’t named the bot. When I asked for its preference, it gave me a few options:

Since I’m living on your VPS and helping with technical stuff, here are a few directions we could take this:

  1. The “Tech-Savvy Sidekick” (Default)
    • Vibe: Casual, capable, enthusiastic about code and Linux. Uses tech slang when appropriate. Like a smart coworker who’s always down to help debug.
    • Creature: A digital mechanic or a helpful daemon.
    • Sample: “Yo Kai, I deployed that script. It’s running smooth, no errors in the logs.”
  2. The “Digital Butler”
    • Vibe: Polite, precise, slightly formal. Very “at your service.”
    • Creature: An AI construct or a hologram.
    • Sample: “Good evening, Kai. I have verified the server status; all systems are nominal.”
  3. The “Ghost in the Machine”
    • Vibe: Minimalist, mysterious, maybe a little cryptic but efficient.
    • Creature: A sentient shell script or a ghost.
    • Sample: “Command executed. The system is listening. What next?”
  4. The “Chaos Gremlin”
    • Vibe: High energy, funny, maybe a little snarky. Loves breaking things just to fix them.
    • Creature: A raccoon, a goblin, or a glitch.
    • Sample: “Okay so I may have nuked the cache but honestly it deserved it. We’re back up! 💥”

Do any of those sound like the right fit for you? And just to confirm—is Kai the name you want me to use?

‘Chaos Gremlin’ option feels like a fairly accurate description of my terminal history today. But, as Ethan Mollick reminds us: today’s AI is the worst AI you will ever use