Skip to content

TechButton/pangolin-debug-skill

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

3 Commits
 
 
 
 
 
 
 
 

Repository files navigation

pangolin-debug-skill · v0.0.2

A Claude Code skill and repair scripts for debugging and fixing Pangolin EE self-hosted tunnel installations.

Covers every issue discovered running Pangolin EE in production — empty dashboards, 404s, 502s, SSO errors, WireGuard tunnel failures, and more — with root cause explanations and copy-paste fixes.


What's included

File Purpose
.claude/commands/pangolin-debug.md Claude Code /pangolin-debug skill
scripts/fix_pangolin.cjs Comprehensive DB repair (9 fixes, runs inside Pangolin container)
scripts/add_resource.cjs Register an HTTP resource in Pangolin's DB without using the API
scripts/setup_pangolin.cjs Zero-API initial setup (admin user, org, role, site, newt)

Installing the Claude Code skill

Prerequisites

  • Claude Code installed (npm install -g @anthropic-ai/claude-code)
  • A terminal open in any project directory

Option A — Global install (recommended)

Makes /pangolin-debug available in every Claude Code session on your machine.

# 1. Clone this repo
git clone https://github.com/TechButton/pangolin-debug-skill.git
cd pangolin-debug-skill

# 2. Create the global commands directory if it doesn't exist
mkdir -p ~/.claude/commands

# 3. Copy the skill file
cp .claude/commands/pangolin-debug.md ~/.claude/commands/pangolin-debug.md

Done. Open any Claude Code session and type /pangolin-debug.


Option B — Project-level install

Makes /pangolin-debug available only when Claude Code is running inside a specific project directory.

# 1. Clone this repo
git clone https://github.com/TechButton/pangolin-debug-skill.git

# 2. Copy the commands folder into your project
cp -r pangolin-debug-skill/.claude /path/to/your/project/

Or if you're already inside your project:

mkdir -p .claude/commands
curl -o .claude/commands/pangolin-debug.md \
  https://raw.githubusercontent.com/TechButton/pangolin-debug-skill/main/.claude/commands/pangolin-debug.md

Option C — One-liner (no clone required)

mkdir -p ~/.claude/commands && curl -o ~/.claude/commands/pangolin-debug.md \
  https://raw.githubusercontent.com/TechButton/pangolin-debug-skill/main/.claude/commands/pangolin-debug.md

Using the skill

Once installed, open a Claude Code session in any directory and type /pangolin-debug followed by a description of your problem.

Starting the skill

/pangolin-debug my dashboard shows no sites or resources after login
/pangolin-debug all my apps are returning 404
/pangolin-debug the newt tunnel won't connect

Claude will load the full knowledge base from the skill file and then diagnose and fix the issue — SSHing to your VPS, running DB queries, and applying targeted fixes.

Example interactions

Empty dashboard after setup:

/pangolin-debug I just set up Pangolin and the dashboard loads but shows
no sites or resources. I can log in fine but everything is empty.

→ Claude will check roleActions (the most common cause), grant all actions to the admin role, and verify the fix via the API.

404 on all resources:

/pangolin-debug every resource returns 404. The tunnel is connected
(I can see the site online in the DB) but no apps are reachable.

→ Claude will check resources.domainId for nulls, query the domains table, and link them.

SSO blocking apps it shouldn't:

/pangolin-debug Pangolin is showing "you're not allowed to access this resource"
for portainer even though I set sso=0 for it.

→ Claude will check the sso column (defaults to 1 in EE, must be written explicitly), fix the value, and explain the root cause.

WireGuard not connecting:

/pangolin-debug the newt agent connects but the WireGuard tunnel fails.
My domain is behind Cloudflare.

→ Claude will check your Gerbil config for the WireGuard endpoint, explain the CF proxy/UDP issue, and walk you through creating the DNS-only wg.<domain> record.

General debugging:

/pangolin-debug something is wrong with my Pangolin setup, I'm not sure what

→ Claude will run the full diagnostic script, dump the DB state, and identify any issues against the healthy-state checklist.


Using the scripts directly (no Claude Code required)

The scripts in scripts/ work standalone — no Claude Code needed. They run inside the Pangolin Docker container.

Repair an existing install

If your Pangolin dashboard is broken, run the repair script first:

# Copy script into the container
sudo docker cp scripts/fix_pangolin.cjs pangolin:/app/fix_pangolin.cjs

# Preview what would change (safe, no DB writes)
sudo docker exec pangolin node /app/fix_pangolin.cjs --dry-run

# Apply all fixes
sudo docker exec pangolin node /app/fix_pangolin.cjs

What fix_pangolin.cjs fixes

# Fix Symptom resolved
1 isShareableSite = 0 UI infinite redirect loop
2 enableProxy = 1 Tunnel not active on resources
3 enabled = 1 Resources / targets disabled
4 targets.method = http 502 / TLS handshake failure on plain-HTTP backends
5 domains table 404 on all resources (null domainId)
6 roleResources "Not allowed to access this resource" (SSO)
7 userResources Empty connections/settings in dashboard
8 roleActions + userActions Empty dashboard / 403 on every API call
9 termsAcceptedTimestamp Dashboard blocked after login

Register a new resource

Use this when you want to expose a new service through Pangolin without going through the dashboard or API:

sudo docker cp scripts/add_resource.cjs pangolin:/app/add_resource.cjs

sudo docker exec pangolin node /app/add_resource.cjs \
  --site-id 1 \
  --name myapp \
  --subdomain myapp.example.com \
  --http-port 65400 \
  --target-port 8080 \
  --target-host 192.168.1.100 \
  [--method http|https] \
  [--sso 1]
Argument Required Description
--site-id Yes ID of the Newt site (find with SELECT siteId FROM sites in the DB)
--name Yes Display name for the resource
--subdomain Yes Full domain for this resource (e.g. app.example.com)
--http-port Yes Proxy port Pangolin/Traefik will listen on (unique per resource — script exits if already taken)
--target-port Yes Port your service listens on behind the tunnel
--target-host Yes LAN IP of the host running the service
--method No http (default) or https if backend serves TLS
--sso No 1 to require Pangolin login gate, 0 (default) to bypass

Note: isShareableSite is always set to 0 and tlsServerName is always set to NULL for HTTP resources. Both were previously incorrect (defaulting to 1 and the FQDN respectively), causing the dashboard redirect loop and incorrect TLS config on new resources.


Fresh install / initial setup

Use when setting up Pangolin from scratch and the dashboard isn't accessible yet:

# 1. Get the setup token from Pangolin's startup logs
sudo docker logs pangolin 2>&1 | grep -i "setup"

# 2. Create a config file
cat > /tmp/setup-config.json << 'EOF'
{
  "email": "admin@example.com",
  "password": "your-secure-password",
  "setupToken": "token-from-logs",
  "orgId": "myorg",
  "orgName": "My Organisation",
  "siteName": "homeserver",
  "newtId": "your-newt-id",
  "newtSecret": "your-newt-secret"
}
EOF

# 3. Run setup
sudo docker cp scripts/setup_pangolin.cjs pangolin:/app/setup_pangolin.cjs
sudo docker cp /tmp/setup-config.json pangolin:/tmp/setup-config.json
sudo docker exec pangolin node /app/setup_pangolin.cjs /tmp/setup-config.json \
  --secret-file /tmp/pangolin-newt-secret.txt

The script creates: admin user → org → admin role (with all actions) → site → newt record. Stdout emits SETUP_RESULT org_id=... site_id=... role_id=... newt_id=... (no secret). The raw newt secret is written to the path given by --secret-file (mode 0600). Without --secret-file the secret falls back to stdout with a warning — avoid this in logged environments.

Security notes:

  • The config file is deleted automatically after setup. A warning is printed to stderr if deletion fails — delete it manually.
  • New sites are created with dockerSocketEnabled = 0. Enable Docker socket access explicitly in the Pangolin dashboard only if needed.

Pangolin EE — key things to know

These are the most common sources of confusion when working with Pangolin EE's SQLite database directly:

Issue Detail
user table Singular (not users). PK is id, but FK columns in child tables are always named userId
roleActions Must be populated for all actions even on isAdmin=1 roles — empty = 403 on every API call
sso column Defaults to 1 in EE — always write it explicitly in INSERT, never rely on the column default
isShareableSite column Defaults to 1 in EE — always set to 0 for proxy resources; 1 + enableProxy=1 causes an infinite UI redirect loop
domainId Resources with null domainId generate no Traefik routing — all requests return 404
session.id Stores a SHA256 hash of the raw cookie token (Lucia auth). Don't use DB values as cookies
CSRF All mutating API calls require header X-CSRF-Token: x-csrf-protection
sites.pubKey Must be NULL before Newt first connects — pre-seeding causes "Public key mismatch"
WireGuard + CF WireGuard uses UDP; Cloudflare only proxies TCP. The WG endpoint must be a DNS-only record

Requirements

  • Pangolin EE 1.16 or later
  • better-sqlite3 and oslo node packages (present in all official Pangolin EE container images)
  • Node.js 18+ inside the container

Related

  • Pangolin — self-hosted tunnel server by Fossorial
  • portless — homelab installer that uses these scripts for automated Pangolin setup

License

MIT

About

Claude Code skill + repair scripts for debugging Pangolin EE self-hosted tunnel installations

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors