User Guide

Welcome to the User Guide for Pharos Advanced Blocking (pab). This guide covers setup, credentials, the interactive TUI, and command-line operations.


Quickstart: From Zero to a Confirmed Block

1. Bootstrap Your Configuration (First Time Only)

If you don’t already have a dnsApp.config file, point pab at your running Technitium server — no copy-paste, no blank JSON file:

pab init

pab init resolves your Technitium credentials, fetches the server’s live Advanced Blocking configuration (or falls back to a starter template if the server has none yet), previews what it found, and asks you to confirm before writing anything to disk. See Installation & Credentials below for how to set up TECHNITIUM_URL/TECHNITIUM_TOKEN (one node) or secrets.json (two or more nodes) — or just run pab init with nothing set up yet and it will prompt you for them.

2. Run pab (Interactive Mode)

Open your terminal in the directory containing your Technitium dnsApp.config file and type:

pab

If you’re in a terminal (TTY), the interactive TUI dashboard opens immediately.

In non-TTY environments (CI/CD pipelines, container orchestration, cron jobs):

pab will exit with a helpful error message explaining that the TUI requires an interactive terminal. Use CLI commands instead:

This is by design: the TUI is built for humans exploring interactively; CLI commands are designed for scripts, automation, and non-interactive environments. You get the full power of pab in either mode—just pick the right tool for your workflow.

3. Explore Your Configuration

The TUI shows:

4. Use Slash Commands

Type /help to see all available commands, or try:

5. Use Tab Completion for Command Names

Type /v[Tab] — it auto-completes to /view (with trailing space). Tab completion works for command names only (e.g., /e[Tab]/exit ). Group name autocomplete in search mode is coming in a future release—for now, Tab navigates through filtered results.

6. Exit

Press Ctrl+C or type /exit to close the TUI.

7. Confirm It Worked

Once you’ve mapped devices and deployed with pab deploy, confirm blocking actually took effect by querying the live server directly:

pab verify --domain ads.example.com

See Mapping & Deploying below for the full map → dry-run → deploy → verify workflow.

Next Steps: Explore the Interactive Mode section to master slash commands, or jump to Mapping & Deploying to assign devices programmatically.


TUI Interface Preview

When you run pab, you’ll see a title bar, an empty content area, a search prompt, and a footer of keyboard hints — your command center for managing DNS blocking policies:

╭──────────────────────────────────────────────────────────────────╮
│ Pharos Advanced Blocking                                         │
│                                                                  │
│                                                                  │
│                                                                  │
│   > Search or type /help for commands                            │
│                                                                  │
│  ctrl+c / esc: exit | /help: commands | /clear: reset            │
╰──────────────────────────────────────────────────────────────────╯

There’s no welcome banner or first-run tips on the opening screen today — type /help to see the full command list. (A first-run welcome banner exists in the codebase but is currently disabled pending a rendering fix, so it isn’t part of the current release.)

Key Interface Elements

The interface is built with Bubbletea (Go TUI framework) and uses responsive sizing to fit your terminal. All interactions are keyboard-driven for speed and efficiency.


When to Use: Interactive Mode (TUI) vs. Command Line

Pharos Advanced Blocking offers two ways to manage your DNS configuration. Choose the right tool for your task:

Interactive Mode (TUI) — Use When…

Launch with: pab (no arguments)

Command Line (CLI) — Use When…

Commands: pab init, pab map, pab unmap, pab deploy, pab verify, pab --help

Summary

Task Use TUI Use CLI
Explore configuration
Debug a specific client
Assign one client Either
Bulk-assign 100+ clients
Deploy to production ✓ (with –dry-run)
Automate with CI/CD

First-time users: Start with the TUI (pab) to get familiar with your groups and clients. Once you understand your setup, you’re ready for CLI commands and automation.


Installation & Credentials

Install pab

Follow the Installation guide to install the CLI.

Set Up Credentials

pab does NOT require credentials to start up or use interactive mode (reads local dnsApp.config). Credentials are only needed when deploying to a Technitium server via the pab deploy command (or fetching one via pab init).

How you supply credentials depends on how many Technitium nodes you manage — that’s the whole decision:

You manage… Use Works in
1 node Environment variables Any environment, including CI/CD
2+ nodes secrets.json Any environment, including CI/CD

The easiest way to set either one up is pab init — it prompts for credentials, asks whether you manage more than one node, and either prints the export lines for you to add to your shell profile (1 node) or writes secrets.json with chmod 600 for you (2+ nodes). The manual steps below are what pab init automates.

Here’s exactly what you’ll see when you run pab init with nothing set up yet. Answer “n” if you manage a single Technitium instance:

No Technitium credentials found via environment variables or secrets.json.
Technitium server URL (e.g. https://dns.example.com:5380): https://dns.example.com:5380
API token: your-api-token-here
Do you manage more than one Technitium node? [y/N]: n

Single-node setup. pab cannot persist environment variables for you;
add the following to your shell profile (e.g. ~/.bashrc, ~/.zshrc):

  export TECHNITIUM_URL="https://dns.example.com:5380"
  export TECHNITIUM_TOKEN="your-api-token-here"

Answer “y” if you manage two or more nodes — you’ll be asked to name and enter each one (the “Add another node?” prompt repeats until you decline), and pab init writes them straight to secrets.json at chmod 600:

No Technitium credentials found via environment variables or secrets.json.
Technitium server URL (e.g. https://dns.example.com:5380): https://dns1.example.com:5380
API token: token-for-dns1
Do you manage more than one Technitium node? [y/N]: y
Name for this node (e.g. dns1, prod): dns1
Add another node? [y/N]: y
  Node URL: https://dns2.example.com:5380
  API token: token-for-dns2
  Node name: dns2
Add another node? [y/N]: n

Wrote 2 node(s) to /home/user/.config/pab/secrets.json (chmod 600).

Either way, the rest is automated — no manual file editing needed.

1 node: Environment Variables

export TECHNITIUM_URL="https://dns.example.com:5380"
export TECHNITIUM_TOKEN="your_api_token_here"

TECHNITIUM_URL/TECHNITIUM_TOKEN configure exactly one node (registered internally as "default"). There is no multi-node environment variable pattern — as soon as you’re managing a second node, move to secrets.json below.

pab deploy --dry-run  # Validate first
pab deploy -f         # Deploy without a confirmation prompt

2+ nodes: Secrets File

Create a secrets file at ~/.config/pab/secrets.json with mode chmod 600. Each node can optionally carry a name (falls back to node-0, node-1, … when omitted) so pab list-nodes and pab deploy --node <name> have something stable to target:

{
  "nodes": [
    {
      "name": "dns1",
      "url": "https://dns1.example.com:5380",
      "token": "token_for_dns1"
    },
    {
      "name": "dns2",
      "url": "https://dns2.example.com:5380",
      "token": "token_for_dns2"
    }
  ]
}

Then deploy to all nodes with:

pab deploy --dry-run  # Validate first
pab deploy -f         # Deploy to all nodes simultaneously

Using secrets.json in CI/CD: since 2+ nodes always means secrets.json, write it from a CI secret to a temp path immediately before deploying, keeping it off disk the rest of the time:

export XDG_CONFIG_HOME=/tmp/pab-config
umask 077
mkdir -p "$XDG_CONFIG_HOME/pab"
printf '%s' "$SECRETS_JSON" > "$XDG_CONFIG_HOME/pab/secrets.json"
chmod 600 "$XDG_CONFIG_HOME/pab/secrets.json"
pab deploy -f
rm -rf "$XDG_CONFIG_HOME"

(Store the file’s JSON contents as a single CI secret, e.g. SECRETS_JSON — pab reads $XDG_CONFIG_HOME/pab/secrets.json on Linux, so pointing XDG_CONFIG_HOME at a scratch directory keeps the real credentials off disk outside the job.)

Security: Environment variables are simplest for a single node and never touch disk. secrets.json is required once you have two or more nodes, and pab refuses to run if its permissions are weaker than chmod 600.


Interactive Mode — Slash Commands

When you run pab (with no arguments), you enter interactive mode. The TUI accepts slash commands for powerful, terminal-native operations.

Command Reference

Command Aliases Description Example
/help /?, /h Show all available slash commands /help
/exit /quit, /q Exit the TUI /exit
/clear /c Clear search input and reset all filters /clear
/view groups /v groups List all configured groups with device count per group /view groups
/view group <name> /v group <name> Show all details for a specific group (allowed domains, blocked domains, blocklists) /view group Kids
/view group <name> blocklists /v group <name> blocklists Show only blocked domains for a group /view group Kids blocklists
/view group <name> allowed /v group <name> allowed Show only allowed domains for a group /view group Kids allowed
/view networkGroupMap /v networkGroupMap Show all IP-to-group mappings (same as empty search) /view networkGroupMap

Usage Patterns

List all groups:

/view groups

Output:

Group Name                 Devices
Kids                             3
IoT                              5
Do-Not-Block                     1

View Kids group details:

/view group Kids

See only blocklists for a group:

/view group IoT blocklists

View all IP → group assignments:

/view networkGroupMap

Search Typeahead (IP & Group Filtering)

While in search mode (before typing /), Pharos filters results in real-time as you type. Press Tab to navigate through filtered results.

What Works

Example Workflow

Type:     192.0[Tab]
Result:   Highlights first matching IP (e.g., 192.0.2.50)
Press Tab again: Cycles to next IP match (e.g., 192.0.2.51)
Press Enter:     Filters table to show that IP's details

Group Filtering with Tab Navigation

Here’s what happens step-by-step when you search for a group:

You:    Type 'kid' in search mode
Result: TUI filters to groups containing "kid":
        - Kids
        - Device-Kids
        - Streaming-Kids
        (First match "Kids" is automatically highlighted)

You:    Press Tab
Result: Highlights cycle to the next match
        Kids → Device-Kids (now highlighted)

You:    Press Tab again
Result: Highlights cycle to the next match
        Device-Kids → Streaming-Kids (now highlighted)

You:    Press Tab again
Result: Wraps around to beginning
        Streaming-Kids → Kids (now highlighted)

You:    Press Enter on "Device-Kids"
Result: Shows details for the Device-Kids group

Key Point: This is navigation through filtered results, not autocomplete. Typing kid[Tab] does NOT auto-fill to “Kids”—it filters the list and lets you navigate through matches with Tab, then press Enter to confirm your choice.

What’s NOT Available (Yet)

Power-User Tips

  1. Case-insensitive: Type kids or KIDS to find the “Kids” group
  2. Partial matching: Type 192 to filter to all IPs containing 192
  3. Multiple matches: If multiple items match, use Tab to cycle through them, then Enter to confirm

How This Differs from Tab Completion

→ See Tab Completion below for IDE-style command name autocomplete (different from search navigation).


Tab Completion (Command Names Only)

→ See Search Typeahead above for search mode Tab navigation (different from command autocomplete).

Press Tab to auto-complete slash command names. This is true IDE-style completion—the command name fills in completely with a trailing space, ready for arguments.

What Works

Single Command Match:

Type a partial command that matches exactly one slash command, then press Tab. The command completes fully with a space:

/e[Tab]  →  /exit 
/q[Tab]  →  /exit 
/h[Tab]  →  /help 

Multiple Command Matches:

Type a partial command that matches multiple commands, then press Tab. The TUI highlights the first match:

/v[Tab]                    →  Highlights "/view" (multiple matches)
Press ↓ to select a match  →  Navigate to desired command
Press Tab                  →  Completes highlighted command to "/view "

Entering Arguments After Completion:

After Tab-completing a command, start typing arguments immediately without pressing Tab again:

/v[Tab]
groups
[Enter]  →  Executes "/view groups"

What’s NOT Available (Yet)

Power-User Tips

  1. Aliases work too: /v and /view both match; Tab-complete either one
  2. Case-insensitive: /EXIT and /exit are equivalent
  3. After completion, you’re in argument mode: The space is already there—just start typing your arguments

Advanced Workflows

Command History Navigation

After executing commands, use ↑↓ arrow keys to scroll through command history. This is perfect for repeating common operations without retyping:

Execute: /view groups
Press ↑: Returns to /view groups in input
Press ↑: Returns to previous command

Useful for: Rapid multi-group inspection, repeated deployments, testing workflows.

Search is case-insensitive, so any of these find the “Kids” group:

Type: kids[Enter]
Type: KIDS[Enter]
Type: KiDs[Enter]

All three filter identically to the Kids group.

Multi-Node Deployment Pattern

For active-active setups, deploy to all nodes with a single command:

pab deploy --dry-run          # Preview all changes
pab deploy -f                 # Deploy to all configured nodes simultaneously

Or target a specific node:

pab deploy -f --node secondary

This pattern scales from 1 to N nodes without workflow changes.


Mapping & Deploying

Once your configuration is ready, manage updates using the CLI commands:

Workflow Overview

  1. Map Policies (pab map): Assign client IPs to blocking groups
  2. Preview Changes (pab deploy --dry-run): Validate and inspect what will change
  3. Deploy (pab deploy): Sync to your Technitium instances
  4. Verify (pab verify): Confirm blocking actually took effect on the live server

Step 1: Map a Client IP

Add or update a device mapping:

pab map --ip 192.0.2.50 --group Kids

Validate succeeds instantly (local schema validation). If validation fails, the mapping is rejected and the config remains unchanged.

Step 2: Preview with Dry-Run

Before deploying, see what will change:

pab deploy --dry-run

Output shows:

Nothing is written to the server during dry-run.

Step 3: Deploy to Technitium

Once you’re confident, deploy:

pab deploy

By default, you’ll be prompted to confirm before deploying to all nodes. Use -f/--force to skip the confirmation prompt:

pab deploy -f

Or target a specific node:

pab deploy -f --node production

Step 4: Verify It Worked

Deploying successfully means the config was written to the API — it doesn’t guarantee Technitium is actually blocking the domain yet. Close the loop with a live DNS query:

pab verify --domain ads.example.com

pab verify queries the target node’s DNS resolver directly and checks the response against that domain’s group’s configured blocking behavior. It reports blocked, not-blocked, inconclusive (e.g. a sinkhole-style group with no blockingAddresses configured, so pab has nothing to compare the response against), or error, and exits non-zero unless the result is exactly blocked — safe to chain directly after deploy in a script or CI job:

pab deploy -f && pab verify --domain ads.example.com

If the domain is only covered by a remote block-list URL (not a literal entry in blockedDomains/blockedRegex), pass --group explicitly — pab verify doesn’t fetch and search remote lists to attribute a domain automatically:

pab verify --domain doubleclick.net --group Default

When you manage more than one node, pass --node to pick which one to query — pab verify checks exactly one node per run, unlike pab deploy’s fan-out to all configured nodes:

pab verify --domain ads.example.com --node production

Multi-Device Example

Map several devices, then deploy and verify once:

pab map --ip 192.0.2.50 --group Kids
pab map --ip 192.0.2.51 --group Kids
pab map --ip 203.0.113.10 --group IoT
pab deploy --dry-run
pab deploy -f
pab verify --domain ads.example.com

Safety Features


Configuration File Format

The fastest way to get a valid dnsApp.config is pab init (see Quickstart above) — it fetches your server’s live configuration, or falls back to a starter template if the server has none yet, and writes it to disk only after you confirm.

If you’d rather build or edit dnsApp.config by hand, here’s the schema pab understands (matching Technitium’s own Advanced Blocking App schema):

{
  "enableBlocking": true,
  "blockingAnswerTtl": 60,
  "blockListUrlUpdateIntervalHours": 24,
  "blockListUrlUpdateIntervalMinutes": 0,
  "networkGroupMap": {
    "192.0.2.50": "Kids",
    "203.0.113.10": "IoT"
  },
  "groups": [
    {
      "name": "Kids",
      "enableBlocking": true,
      "allowTxtBlockingReport": false,
      "blockAsNxDomain": true,
      "blockingAddresses": [],
      "allowedDomains": ["youtube.com"],
      "blockedDomains": ["ads.example.com"],
      "allowListUrls": [],
      "blockLists": ["https://raw.githubusercontent.com/StevenBlack/hosts/master/hosts"],
      "allowedRegex": [],
      "blockedRegex": [],
      "regexAllowListUrls": [],
      "regexBlockListUrls": [],
      "adblockListUrls": []
    },
    {
      "name": "IoT",
      "enableBlocking": true,
      "allowTxtBlockingReport": false,
      "blockAsNxDomain": false,
      "blockingAddresses": ["0.0.0.0"],
      "allowedDomains": [],
      "blockedDomains": [],
      "allowListUrls": [],
      "blockLists": [],
      "allowedRegex": [],
      "blockedRegex": [],
      "regexAllowListUrls": [],
      "regexBlockListUrls": [],
      "adblockListUrls": []
    }
  ]
}

A full working example lives at dnsApp.config.example in the repository root. You can edit the file manually, fetch it with pab init, or edit specific fields with pab map/pab unmap — all three paths respect the same schema validation.


Troubleshooting

“Configuration file not found”

Ensure dnsApp.config exists in your current directory, or specify --config:

pab --config /etc/technitium/dnsApp.config map --ip 192.0.2.50 --group Kids

No config yet? Run pab init to fetch one from your Technitium server (or generate a starter template) instead of creating one by hand.

“Failed to deploy to node”

Check:

  1. Node URL and token are correct (via environment variables or ~/.config/pab/secrets.json)
  2. Technitium API is reachable (test with curl -k https://your-node:5380/api/)
  3. API token has permission to write configuration

“IP validation failed”

Ensure your IP is:

“Group not found”

The group name must exist in your dnsApp.config. Use /view groups in interactive mode to see all available groups.

pab verify reports “not-blocked” or “inconclusive”


See Also