A visual way to view your ACL and Grant rules for Tailscale
Project description
Tailscale Network Topology Mapper
A visual way to view your ACL and Grant rules for Tailscale
I occasionally find myself just wanting to get a glance of how my ACL rules look without reading through the code. This is also useful for showing how our policies are set up to people who are not devs by trade.
What Is This?
The Tailscale Network Topology Mapper is a tool for visualizing your network access rules. It turns your Tailscale ACL and Grant configurations into a self-contained, interactive HTML map—making it easier to understand and share your network layout.
Key Features
Network Visualization
- Interactive Graph: Generates a
network_topology.htmlfile you can open or host anywhere. - Color-Coded Nodes:
- 🟡 Groups
- 🟢 Tags
- 🔴 Hosts
- Shape-Coded Rule Types:
- Circles (●) - ACL-only
- Triangles (▲) - Grant-only
- Hexagons (⬢) - Nodes in both ACL and Grant rules
Advanced Search & Filtering
- Keyword Search: Find nodes by name, port, protocol, routing, posture checks, or group membership.
- Highlighting: Matching nodes are visually marked and highlighted.
Detailed Tooltips
Hover over nodes to see:
- Rule references (with line numbers)
- Protocols (e.g.,
tcp:443,udp:53) - Via-routing information
- Posture check requirements
- App-level access controls
- Group memberships
Access Relationships
- Directional Edges: Arrows show who can talk to whom.
- Legacy + Modern Rule Support: Handles ACLs and Grant rules simultaneously.
- Protocol Display: Shows IP protocol details for destination nodes.
Interactive UI
- Movable search box (drag-and-drop)
- Smooth zoom controls (configurable)
- Connected node highlighting when selected
Supported Tailscale Features
- Policy Formats: JSON and HuJSON (Human JSON)
- Modern Grant Support:
- IP protocols (
tcp,udp,icmp, etc.) - Via-routing
- Posture checks
- Application-level access controls
- IP protocols (
- Legacy ACL Compatibility: Full support for traditional ACL rules
🛠️ Setup Instructions
Requirements
- Python 3.10+
- Git
- uv (recommended) or pip
Installation Methods
Option 1: Using uvx (Recommended - No Installation Required!)
The fastest way to run the mapper without any installation:
# Add your policy.hujson file to current directory (see configuration section below)
# Then run directly with uvx
uvx tailscale-network-topology-mapper
This will run the latest version of the mapper against the policy file (policy.hujson). You will now have a network_topology.html file in the current directory that you can open in your browser.
Optionally, you can point the tool to a specific policy file:
uvx tailscale-network-topology-mapper --policy-file /path/to/your/policy.hujson
To use Tailscale's API for validation instead of the built-in offline sanity checks, see the Using Tailscale's API for Validation section below.
View all the available commands
uvx tailscale-network-topology-mapper --help
Option 2: Using uv (Recommended for Development)
Show uv installation
-
Install uv if you haven't already:
# macOS/Linux curl -LsSf https://astral.sh/uv/install.sh | sh # Windows powershell -c "irm https://astral.sh/uv/install.ps1 | iex"
-
Clone and set up:
git clone https://github.com/SimplyMinimal/tailscale-network-topology-mapper cd tailscale-network-topology-mapper # Install dependencies uv pip install -r requirements.txt
Option 3: Using pip (Traditional Method)
Show Traditional pip installation
-
Clone the repo:
git clone https://github.com/SimplyMinimal/tailscale-network-topology-mapper cd tailscale-network-topology-mapper
-
Install dependencies:
pip install -r requirements.txt
Configuration
Click to show Optional configuration
-
Add your policy:
- Replace the contents of
policy.hujsonwith your actual Tailscale ACL.
- Replace the contents of
-
Set your company domain:
- Edit
config.pyand change:
COMPANY_DOMAIN = "example.com"
- Or set an environment variable:
export TS_COMPANY_DOMAIN=yourcompany.com
- Edit
-
Set your Tailscale API key and tailnet environment variables for Tailscale API validation:
export TAILSCALE_API_KEY=your-api-key export TAILSCALE_TAILNET=your-tailnet
Using Tailscale's API for Validation
Click to show setup for Tailscale API Validation
By default, the tool validates your policy using local structure validation without an API key as a best-effort validation. However, you can optionally configure the tool to use Tailscale's API for validation. This provides a more accurate validation but requires setting up environment variables for your Tailscale API key and tailnet. It's recommended to protect the environment variables which is out of the scope of this tool for now.
Setup
-
Get your Tailscale API Key:
- Go to the Tailscale Admin Console
- Create a new API access token
-
Get your Tailnet Name:
- This is typically your organization name (e.g.,
example.cominhttps://login.tailscale.com/admin/settings/general). You can use either Tailnet ID or Legacy ID.
- This is typically your organization name (e.g.,
-
Set Environment Variables (or use command line flags):
macOS/Linux
# Set your API key export TAILSCALE_API_KEY=tskey-api-xxxxx # Set your tailnet export TAILSCALE_TAILNET=yourcompany.com
Windows
# Set your API key set TAILSCALE_API_KEY=tskey-api-xxxxx # Set your tailnet set TAILSCALE_TAILNET=yourcompany.com
Command Line Flags
You can also use command line flags to control validation and provide credentials:
--validate-with-tailscale-api/--tv: Enable using Tailscale API for validation. If not used, falls back to local offline validation.--tailscale-api-key: Provide API key via command line (overrides environment variableTAILSCALE_API_KEY).--tailscale-tailnet: Provide tailnet via command line (overrides environment variableTAILSCALE_TAILNET).
Example:
python3 main.py --validate-with-tailscale-api --tailscale-api-key tskey-api-xxxxx --tailscale-tailnet yourcompany.com
Usage
Once the environment variables (or command line flags) are set, the tool will automatically use Tailscale's API for validation:
# The tool will now validate via Tailscale's API
uvx tailscale-network-topology-mapper
# or
python3 main.py
If the environment variables are not set and no command line flags are provided, the tool falls back to internal sanity checks for policy validation.
Fetching Policy File from Tailscale API
Click to show remote policy file setup
Instead of using a local policy file, you can fetch the policy file directly from the Tailscale API. This requires the same API credentials as validation.
Command Line Flags
--use-remote-tailscale-policy-file/--tpf: Fetch policy file via Tailscale API (default: false). Cannot be used together with--policy-file.
Usage
# Fetch policy from Tailscale API and generate map
python3 main.py --use-remote-tailscale-policy-file --tailscale-api-key tskey-api-xxxxx --tailscale-tailnet yourcompany.com
When using remote policy file, validation is skipped entirely (the policy fetched from the API is already validated by Tailscale).
Note: You cannot specify both --use-remote-tailscale-policy-file and --policy-file. The tool will exit with an error if both are provided.
Generate the Map
# Using uvx (no installation needed)
uvx tailscale-network-topology-mapper
# Using uv
uv run python main.py
# Using traditional Python
python3 main.py
# Enable debug logging with any method by adding --debug
python3 main.py --debug
# Use Tailscale API for validation with command line credentials
python3 main.py --validate-with-tailscale-api --tailscale-api-key tskey-api-xxxxx --tailscale-tailnet yourcompany.com
# Fetch policy file directly from Tailscale API (skips local file)
python3 main.py --use-remote-tailscale-policy-file --tailscale-api-key tskey-api-xxxxx --tailscale-tailnet yourcompany.com
# Use remote policy file with debug logging
# This assumes you already have environment variables set for `TAILSCALE_API_KEY` and `TAILSCALE_TAILNET`
python3 main.py --use-remote-tailscale-policy-file --debug
# Custom output path
python3 main.py --output custom-output.html
This creates (or updates) network_topology.html. Open it in any browser.
🐳 Running with Docker
Docker instructions
If you prefer Docker:Prerequisites
- Docker
make
Run It
make build run
Then open http://localhost:8080 in your browser.
Use the filter bar or click on any node to narrow down the view.
🔁 Automate with GitHub Actions
Want your map to update automatically when you change your ACL?
Check out this sample workflow:
.github/workflows/tailscale.yml
⚠️ Limitations
- Still in alpha—expect some rough edges.
- Only parses what’s in
policy.hujson. It doesn’t actively discover devices. - Currently focused only on ACL and Grant rules (other policy sections may be supported in future versions).
🧪 Experimental & TODOs
- Integrate
tailscale debug netmapfor deeper insights - Add view toggles: ports, hosts, users/groups
- Improve the visual design and layout
📢 Disclaimer
This is an independent project and not affiliated with Tailscale.
It’s designed as a companion tool to better understand and visualize your Tailscale network policies.
🙌 Contributions Welcome!
Pull requests, suggestions, and feedback are appreciated!
Project details
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file tailscale_network_topology_mapper-3.1.4.tar.gz.
File metadata
- Download URL: tailscale_network_topology_mapper-3.1.4.tar.gz
- Upload date:
- Size: 40.1 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
47344027881b34877d9118f449a6a783cea7bcf327721a60b382fe5ec371160b
|
|
| MD5 |
0ac5f0cceee7a1d1fa382c47030b897c
|
|
| BLAKE2b-256 |
e1f72e7cffb7d06349bbd29cfb1c16f2a7ffc7857df6b4780c1f2d31cf43bda9
|
Provenance
The following attestation bundles were made for tailscale_network_topology_mapper-3.1.4.tar.gz:
Publisher:
publish-pypi.yml on SimplyMinimal/tailscale-network-topology-mapper
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
tailscale_network_topology_mapper-3.1.4.tar.gz -
Subject digest:
47344027881b34877d9118f449a6a783cea7bcf327721a60b382fe5ec371160b - Sigstore transparency entry: 1189047313
- Sigstore integration time:
-
Permalink:
SimplyMinimal/tailscale-network-topology-mapper@4065c0bc1c643ae995462984706524acf87b3819 -
Branch / Tag:
refs/tags/v3.1.4 - Owner: https://github.com/SimplyMinimal
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish-pypi.yml@4065c0bc1c643ae995462984706524acf87b3819 -
Trigger Event:
release
-
Statement type:
File details
Details for the file tailscale_network_topology_mapper-3.1.4-py3-none-any.whl.
File metadata
- Download URL: tailscale_network_topology_mapper-3.1.4-py3-none-any.whl
- Upload date:
- Size: 58.6 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
f1376427270996da781560d9e274ea1ae84064909c46dd5c3df240920e707cdb
|
|
| MD5 |
a0fdee1abfd6abea57c8b6b3e7bb0d77
|
|
| BLAKE2b-256 |
ffd8796bcc7f9f2c5eb2e541afaa325b9f1b2cea6fd8cbd47c0bbb2dc7cbc01a
|
Provenance
The following attestation bundles were made for tailscale_network_topology_mapper-3.1.4-py3-none-any.whl:
Publisher:
publish-pypi.yml on SimplyMinimal/tailscale-network-topology-mapper
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
tailscale_network_topology_mapper-3.1.4-py3-none-any.whl -
Subject digest:
f1376427270996da781560d9e274ea1ae84064909c46dd5c3df240920e707cdb - Sigstore transparency entry: 1189047318
- Sigstore integration time:
-
Permalink:
SimplyMinimal/tailscale-network-topology-mapper@4065c0bc1c643ae995462984706524acf87b3819 -
Branch / Tag:
refs/tags/v3.1.4 - Owner: https://github.com/SimplyMinimal
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish-pypi.yml@4065c0bc1c643ae995462984706524acf87b3819 -
Trigger Event:
release
-
Statement type: