Skip to main content

07. Tailscale Networking & Security

Overview​

We rely on Tailscale to create a flat, secure mesh network. This allows valid devices (developers' laptops, AI agent runners) to access the services without exposing public ports.

Concepts​

  • Tailnet: Your private network.
  • ACLs (Access Control Lists): Rules defining who can talk to whom.
  • MagicDNS: Automatic hostname resolution (e.g., http://rag-mcp-node).

Configuration Strategy​

1. Installation​

In cloud-init, we installed Tailscale and advertised the machine as an exit node (optional) but primarily purely as a node.

2. Interface binding​

The Docker services bind to 0.0.0.0 inside the container.

Current Implementation (docker-compose.yml): We use a Tailscale Sidecar to handle authentication and networking, ensuring the RAG service is not exposed constantly to the public internet.

3. Tailscale Sidecar (Implemented)​

To strictly restrict access to the MCP server, we run a ts-serve sidecar (named ts-proxy).

  # 3. Tailscale Sidecar (Auth Proxy)
ts-proxy:
image: tailscale/tailscale:latest
hostname: rag-internal
restart: always
environment:
- TS_AUTHKEY=${TS_AUTHKEY_PROXY}
- TS_STATE_DIR=/var/lib/tailscale
- TS_DEST_IP=rag-service
volumes:
- ts-state:/var/lib/tailscale
cap_add:
- NET_ADMIN
- NET_RAW
networks:
- internal-net

The Application Service (rag-service) binds only to localhost:

    ports:
- "127.0.0.1:8082:8080"

JSON ACLs (Tailscale Console)​

Enforce that only "devs" tag can reach the "prod" tag.

{
"groups": {
"group:admins": ["alice@email.com"],
"group:bots": ["tag:ai-agent"]
},
"acls": [
{
"action": "accept",
"src": ["group:admins"],
"dst": ["*:*"]
},
{
"action": "accept",
"src": ["group:bots"],
"dst": ["tag:prod:8080"] // Only MCP port
}
]
}

Connecting the AI Agent​

To let a local AI agent (like Cursor/Windsurf) use the remote tool:

  1. Ensure laptop is on Tailscale.
  2. Config MCP tool URL: http://rag-mcp-node:8080/sse (or http://rag-internal:8080 if using MagicDNS). The secure tunnel is transparent.