Gandi Domain Registrar Skill
Comprehensive Gandi domain registrar integration for Moltbot.
Status: โ Phase 2 Complete - DNS modification & snapshots functional
โ ๏ธ Security Warning
This skill can perform DESTRUCTIVE operations on your Gandi account:
- DNS Modification: Add, update, or delete DNS records (can break websites/email)
- Email Management: Create, modify, or delete email forwards (can intercept emails)
- Domain Registration: Register domains (creates financial transactions)
- Bulk Operations: Replace all DNS records at once (cannot be undone except via snapshots)
Before running ANY script:
- Review the script code to understand what it does
- Create DNS snapshots before bulk changes (
create-snapshot.js) - Use read-only Personal Access Tokens where possible
- Test on non-production domains first
- Understand that some operations cannot be undone
Destructive scripts (โ ๏ธ modify or delete data):
add-dns-record.js,delete-dns-record.js,update-dns-bulk.jsadd-email-forward.js,update-email-forward.js,delete-email-forward.jsrestore-snapshot.js(replaces current DNS)
Read-only scripts (โ safe, no modifications):
list-domains.js,list-dns.js,list-snapshots.jslist-email-forwards.js,check-domain.js,check-ssl.js
๐ For complete script documentation: See SCRIPTS.md for detailed information about:
- What each script does
- Network operations and API calls
- Security implications
- Undo/recovery procedures
- Audit workflow recommendations
Current Capabilities
Phase 1 (Complete)
- โ Personal Access Token authentication
- โ List domains in your account
- โ Get domain details (expiration, status, services)
- โ List DNS records for domains
- โ View domain and DNS information
- โ Domain availability checking (#4)
- โ Smart domain suggestions with variations (#4)
- โ SSL certificate status checker
- โ Error handling and validation
Phase 2 (Complete)
- โ Add/update DNS records (A, AAAA, CNAME, MX, TXT, NS, SRV, CAA, PTR)
- โ Delete DNS records
- โ Bulk DNS operations (replace all records at once)
- โ DNS zone snapshots (create, list, restore)
- โ Email forwarding (create, list, update, delete forwards including catch-all)
- โ Record validation (automatic validation for each record type)
- โ Safety features (automatic snapshots before bulk changes, confirmation prompts)
Coming Soon (Phase 3+)
- Domain registration
- Multi-organization support (#1)
- Gateway Console configuration (#3)
- Domain renewal management
- DNSSEC configuration
- Certificate management
- Email mailbox management (beyond forwarding)
Setup
Step 1: Create Personal Access Token
โ ๏ธ Security Recommendation: Use the minimum required scopes for your use case.
Click "Create a token"
Select your organization
Choose scopes:
Read-Only (Recommended for viewing only):
- โ Domain: read (required for listing domains)
- โ LiveDNS: read (required for viewing DNS records)
- โ Email: read (required for viewing email forwards)
Write Access (Required for modifications - use with caution):
- โ ๏ธ LiveDNS: write (enables DNS modification, deletion, bulk operations)
- โ ๏ธ Email: write (enables email forward creation, updates, deletions)
Copy the token (you won't see it again!)
Security Best Practices:
- Create separate tokens for read-only vs. write operations
- Use read-only tokens for routine checks/monitoring
- Only use write tokens when actively making changes
- Rotate tokens regularly (every 90 days recommended)
- Delete unused tokens immediately
- Never share or commit tokens to version control
Step 2: Store Token
Scripts check for credentials in priority order:
GANDI_API_TOKENenvironment variable (checked first)~/.config/gandi/api_tokenfile (fallback if env var not set)
Choose the method that fits your workflow:
Option A: Environment Variable (Recommended for CI/CD)
# Set environment variable (replace YOUR_PAT with actual token)
export GANDI_API_TOKEN="YOUR_PERSONAL_ACCESS_TOKEN"
# Add to shell profile for persistence (~/.bashrc, ~/.zshrc, etc.)
echo 'export GANDI_API_TOKEN="YOUR_PERSONAL_ACCESS_TOKEN"' >> ~/.bashrc
Benefits:
- โ CI/CD friendly (standard pattern for automation)
- โ Container-ready (no file mounts needed)
- โ Works with secret management tools (1Password, Vault, etc.)
- โ Easy to switch between multiple tokens
Option B: File-based (Recommended for local development)
# Create config directory
mkdir -p ~/.config/gandi
# Store your token (replace YOUR_PAT with actual token)
echo "YOUR_PERSONAL_ACCESS_TOKEN" > ~/.config/gandi/api_token
# Secure the file (owner read-only)
chmod 600 ~/.config/gandi/api_token
Benefits:
- โ Token persists across shell sessions
- โ Secure file permissions (0600 = owner read-only)
- โ No risk of exposing token in process list
- โ Works offline (no external dependencies)
Step 3: Install Dependencies
Required: Node.js >= 18.0.0
cd gandi-skill/scripts
# Install npm dependencies
npm install
# Verify installation
npm list --depth=0
Expected packages:
- axios (HTTP client for Gandi API)
- Any other dependencies listed in package.json
Troubleshooting:
- If
nodeornpmnot found: Install Node.js from nodejs.org - If permission errors: Don't use
sudo- fix npm permissions or use nvm - If package errors: Delete
node_modules/andpackage-lock.json, thennpm installagain
Step 4: Test Authentication
cd gandi-skill/scripts
node test-auth.js
Expected output:
โ
Authentication successful!
Your organizations:
1. Personal Account (uuid-here)
Type: individual
๐ You're ready to use the Gandi skill!
Step 5: Setup Contact Information (Optional, for Domain Registration)
If you plan to register domains, save your contact information once for reuse:
cd gandi-skill/scripts
node setup-contact.js
The script will prompt for:
- Name (first and last)
- Email address
- Phone number (international format: +1.5551234567)
- Street address
- City
- State/Province (for US: 2-letter code like OH, automatically formatted to US-OH)
- ZIP/Postal code
- Country (2-letter code: US, FR, etc.)
- Type (individual or company)
- Privacy preference: Retain or auto-purge contact after registration
Contact information is saved to:
~/.config/gandi/contact.json- Permissions: 600 (owner read-write only)
- Outside the skill directory (never committed to git)
Privacy Options:
RETAIN (default): Keep contact saved for future registrations
- Best for frequent domain registrations
- Setup once, use forever
- Delete manually anytime with
delete-contact.js
PURGE: Auto-delete contact after each registration
- Best for privacy-conscious users
- Contact info only exists during registration
- Must re-enter for next registration
Managing saved contact:
# View current contact
node view-contact.js
# Update contact info or privacy preference
node setup-contact.js
# Delete saved contact manually
node delete-contact.js
# Delete without confirmation
node delete-contact.js --force
One-time purge override:
# Register and delete contact (even if preference is "retain")
node register-domain.js example.com --purge-contact
Usage Examples
List Your Domains
node list-domains.js
Output shows:
- Domain names
- Expiration dates
- Auto-renewal status
- Services (LiveDNS, Email, etc.)
- Organization ownership
List DNS Records
node list-dns.js example.com
Output shows:
- All DNS records grouped by type
- TTL values
- Record names and values
- Nameservers
Using from Moltbot
Once configured, you can use natural language:
"List my Gandi domains"
"Show DNS records for example.com"
"When does example.com expire?"
"Is auto-renewal enabled for example.com?"
Domain Availability Checking
Check Single Domain
Check if a specific domain is available for registration:
node check-domain.js example.com
Features:
- Shows availability status (available/unavailable/pending/error)
- Displays pricing information (registration, renewal, transfer)
- Lists supported features (DNSSEC, LiveDNS, etc.)
- Shows TLD information
Example Output:
๐ Checking availability for: example.com
Domain: example.com
โ
Status: AVAILABLE
๐ฐ Pricing:
1 year: 12.00 EUR (+ 2.40 tax)
2 years: 24.00 EUR (+ 4.80 tax)
๐ Supported Features:
โข create
โข dnssec
โข livedns
๐ TLD Information:
Extension: com
Smart Domain Suggestions
Find available alternatives with TLD variations and name modifications:
# Check all configured TLDs + variations
node suggest-domains.js example
# Check specific TLDs only
node suggest-domains.js example --tlds com,net,io
# Skip name variations (only check TLDs)
node suggest-domains.js example --no-variations
# Output as JSON
node suggest-domains.js example --json
Name Variation Patterns:
- Hyphenated: Adds hyphens between word boundaries (
exampleโex-ample) - Abbreviated: Removes vowels (
exampleโexmpl) - Prefix: Adds common prefixes (
exampleโget-example,my-example) - Suffix: Adds common suffixes (
exampleโexample-app,example-hub) - Numbers: Appends numbers (
exampleโexample2,example3)
Example Output:
๐ Checking availability for: example
๐ Checking 13 TLDs and generating variations...
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
๐ EXACT MATCHES (Different TLDs)
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ
Available:
example.net 12.00 EUR
example.io 39.00 EUR
example.dev 15.00 EUR
โ Unavailable:
example.com (unavailable)
example.org (unavailable)
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
๐จ NAME VARIATIONS
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
Hyphenated:
โ
ex-ample.com 12.00 EUR
Prefix:
โ
get-example.com 12.00 EUR
โ
my-example.com 12.00 EUR
Suffix:
โ
example-app.com 12.00 EUR
โ
example-io.com 12.00 EUR
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
๐ SUMMARY: 8 available domains found
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
Configuration
Domain checker configuration is stored in gandi-skill/config/domain-checker-defaults.json.
Structure:
{
"tlds": {
"mode": "extend",
"defaults": ["com", "net", "org", "info", "io", "dev", "app", "ai", "tech"],
"custom": []
},
"variations": {
"enabled": true,
"patterns": ["hyphenated", "abbreviated", "prefix", "suffix", "numbers"],
"prefixes": ["get", "my", "the", "try"],
"suffixes": ["app", "hub", "io", "ly", "ai", "hq"],
"maxNumbers": 3
},
"rateLimit": {
"maxConcurrent": 3,
"delayMs": 200,
"maxRequestsPerMinute": 100
},
"limits": {
"maxTlds": 5,
"maxVariations": 10
}
}
Rate Limiting & Limits:
- maxConcurrent: Maximum concurrent API requests (default: 3)
- delayMs: Delay between requests in milliseconds (default: 200ms)
- maxRequestsPerMinute: Hard limit on requests per minute (default: 100, Gandi allows 1000)
- maxTlds: Maximum TLDs to check in suggest-domains.js (default: 5)
- maxVariations: Maximum name variations to generate (default: 10)
These limits ensure good API citizenship and prevent overwhelming Gandi's API.
TLD Modes:
"extend": Use defaults + custom TLDs (merged list)"replace": Use only custom TLDs (ignore defaults)
Gateway Console Integration:
When Gateway Console support is added (#3), configuration will be available at:
skills:
entries:
gandi:
config:
domainChecker:
tlds:
mode: extend
defaults: [...]
custom: [...]
variations:
enabled: true
patterns: [...]
See docs/gateway-config-design.md for complete configuration architecture.
DNS Management (Phase 2)
Add or Update DNS Records
Create or update individual DNS records:
# Add an A record for root domain
node add-dns-record.js example.com @ A 192.168.1.1
# Add www subdomain pointing to root
node add-dns-record.js example.com www CNAME @
# Add MX record for email
node add-dns-record.js example.com @ MX "10 mail.example.com."
# Add TXT record for SPF
node add-dns-record.js example.com @ TXT "v=spf1 include:_spf.google.com ~all"
# Add with custom TTL (5 minutes)
node add-dns-record.js example.com api A 192.168.1.10 300
Supported record types: A, AAAA, CNAME, MX, TXT, NS, SRV, CAA, PTR
Delete DNS Records
Remove specific DNS records:
# Delete old A record
node delete-dns-record.js example.com old A
# Delete with confirmation prompt
node delete-dns-record.js example.com test CNAME
# Delete without confirmation
node delete-dns-record.js example.com old A --force
Bulk DNS Operations
Replace all DNS records at once:
# From JSON file
node update-dns-bulk.js example.com new-records.json
# From stdin
cat records.json | node update-dns-bulk.js example.com
# Skip automatic snapshot
node update-dns-bulk.js example.com records.json --no-snapshot
# Skip confirmation
node update-dns-bulk.js example.com records.json --force
JSON format:
[
{
"rrset_name": "@",
"rrset_type": "A",
"rrset_ttl": 10800,
"rrset_values": ["192.168.1.1"]
},
{
"rrset_name": "www",
"rrset_type": "CNAME",
"rrset_ttl": 10800,
"rrset_values": ["@"]
},
{
"rrset_name": "@",
"rrset_type": "MX",
"rrset_ttl": 10800,
"rrset_values": ["10 mail.example.com.", "20 mail2.example.com."]
}
]
DNS Zone Snapshots
Create safety backups before making changes:
# Create a snapshot
node create-snapshot.js example.com "Before migration"
# List all snapshots
node list-snapshots.js example.com
# Restore from a snapshot
node restore-snapshot.js example.com abc123-def456-ghi789
# Restore without confirmation
node restore-snapshot.js example.com abc123-def456-ghi789 --force
Automatic snapshots:
- Bulk updates automatically create snapshots (unless
--no-snapshot) - Snapshots are named with timestamp
- Use snapshots for easy rollback
Common DNS Configuration Examples
Basic Website Setup
# Root domain
node add-dns-record.js example.com @ A 192.168.1.1
# WWW subdomain
node add-dns-record.js example.com www CNAME @
Email Configuration (Google Workspace)
# MX records
node add-dns-record.js example.com @ MX "1 ASPMX.L.GOOGLE.COM."
node add-dns-record.js example.com @ MX "5 ALT1.ASPMX.L.GOOGLE.COM."
node add-dns-record.js example.com @ MX "5 ALT2.ASPMX.L.GOOGLE.COM."
# SPF record
node add-dns-record.js example.com @ TXT "v=spf1 include:_spf.google.com ~all"
Domain Redirect Setup
To redirect one domain to another:
# Point root domain to same server
node add-dns-record.js old-domain.com @ A 192.168.1.1
# Point www to same CNAME
node add-dns-record.js old-domain.com www CNAME @
Then configure HTTP 301 redirect at the server level.
Subdomain Setup
# API subdomain
node add-dns-record.js example.com api A 192.168.1.10
# Staging subdomain
node add-dns-record.js example.com staging A 192.168.1.20
# Wildcard subdomain
node add-dns-record.js example.com "*" A 192.168.1.100
Email Forwarding (Phase 2)
List Email Forwards
See all email forwards configured for a domain:
node list-email-forwards.js example.com
Create Email Forwards
Forward emails to one or more destinations:
# Simple forward
node add-email-forward.js example.com hello [email protected]
# Forward to multiple destinations
node add-email-forward.js example.com support [email protected] [email protected]
# Catch-all forward (forwards all unmatched emails)
node add-email-forward.js example.com @ [email protected]
Update Email Forwards
Change the destination(s) for an existing forward:
# Update single destination
node update-email-forward.js example.com hello [email protected]
# Update to multiple destinations
node update-email-forward.js example.com support [email protected] [email protected]
Note: This replaces all existing destinations with the new ones.
Delete Email Forwards
Remove email forwards:
# Delete with confirmation prompt
node delete-email-forward.js example.com old
# Delete without confirmation
node delete-email-forward.js example.com old --force
# Delete catch-all forward
node delete-email-forward.js example.com @ --force
Common Email Forwarding Use Cases
Basic Email Forwarding
# Forward contact@ to your personal email
node add-email-forward.js example.com contact [email protected]
# Forward sales@ to team
node add-email-forward.js example.com sales [email protected]
Domain Migration Email Forwarding
# Forward all email from old domain to new domain
# Preserves the local part (username before @)
# First, list existing forwards on old domain
node list-email-forwards.js old-domain.com
# Then create matching forwards on new domain
node add-email-forward.js old-domain.com contact [email protected]
node add-email-forward.js old-domain.com support [email protected]
# Or use catch-all to forward everything
node add-email-forward.js old-domain.com @ [email protected]
Team Distribution Lists
# Forward to entire team
node add-email-forward.js example.com team [email protected] [email protected] [email protected]
# Update team members
node update-email-forward.js example.com team [email protected] [email protected]
Catch-All Configuration
# Forward all unmatched emails to one address
node add-email-forward.js example.com @ [email protected]
# Forward all unmatched emails to multiple addresses
node add-email-forward.js example.com @ [email protected] [email protected]
Note: Catch-all forwards only apply to email addresses that don't have specific forwards configured.
Email Forward Management Tips
- Test after creating: Send a test email to verify forwarding works
- Use specific forwards over catch-all: More control and easier to manage
- Multiple destinations: Email is sent to all destinations (not round-robin)
- Order doesn't matter: Gandi processes most specific match first
- Check spam folders: Forwarded emails may be filtered by recipient's spam filter
Example: Complete Domain Email Setup
# 1. Set up MX records (if not already done)
node add-dns-record.js example.com @ MX "10 spool.mail.gandi.net."
node add-dns-record.js example.com @ MX "50 fb.mail.gandi.net."
# 2. Create specific forwards
node add-email-forward.js example.com hello [email protected]
node add-email-forward.js example.com support [email protected]
node add-email-forward.js example.com sales [email protected]
# 3. Set up catch-all for everything else
node add-email-forward.js example.com @ [email protected]
# 4. List all forwards to verify
node list-email-forwards.js example.com
Helper Scripts
All scripts are in gandi-skill/scripts/:
Authentication & Setup
| Script | Purpose |
|---|---|
test-auth.js |
Verify authentication works |
setup-contact.js |
Save contact info for domain registration (run once) |
view-contact.js |
View saved contact information |
delete-contact.js |
Delete saved contact (with optional --force) |
Domain & DNS Viewing
| Script | Purpose |
|---|---|
list-domains.js |
Show all domains in account |
list-dns.js <domain> |
Show DNS records for domain |
check-domain.js <domain> |
Check single domain availability + pricing |
suggest-domains.js <name> |
Smart domain suggestions with variations |
check-ssl.js |
Check SSL certificate status for all domains |
DNS Modification (Phase 2)
| Script | Purpose |
|---|---|
add-dns-record.js <domain> <name> <type> <value> [ttl] |
Add or update a DNS record |
delete-dns-record.js <domain> <name> <type> [--force] |
Delete a DNS record |
update-dns-bulk.js <domain> <records.json> [--no-snapshot] [--force] |
Bulk update all DNS records |
list-snapshots.js <domain> |
List DNS zone snapshots |
create-snapshot.js <domain> [name] |
Create a DNS zone snapshot |
restore-snapshot.js <domain> <snapshot-id> [--force] |
Restore DNS zone from snapshot |
Email Forwarding (Phase 2)
| Script | Purpose |
|---|---|
list-email-forwards.js <domain> |
List all email forwards for a domain |
add-email-forward.js <domain> <mailbox> <destination> [dest2...] |
Create email forward (use @ for catch-all) |
update-email-forward.js <domain> <mailbox> <destination> [dest2...] |
Update email forward destinations |
delete-email-forward.js <domain> <mailbox> [--force] |
Delete email forward |
Core Library
| Script | Purpose |
|---|---|
gandi-api.js |
Core API client (importable) |
Configuration
Default Configuration
- Token file:
~/.config/gandi/api_token(API authentication) - Contact file:
~/.config/gandi/contact.json(domain registration info, optional) - API URL:
https://api.gandi.net(production)
Sandbox Testing
To use Gandi's sandbox environment:
# Create sandbox token at: https://admin.sandbox.gandi.net
echo "YOUR_SANDBOX_TOKEN" > ~/.config/gandi/api_token
echo "https://api.sandbox.gandi.net" > ~/.config/gandi/api_url
Troubleshooting
Token Not Found
# Verify file exists
ls -la ~/.config/gandi/api_token
# Should show: -rw------- (600 permissions)
Authentication Failed (401)
- Token is incorrect or expired
- Create new token at Gandi Admin
- Update stored token file
Permission Denied (403)
- Token doesn't have required scopes
- Create new token with Domain:read and LiveDNS:read
- Verify organization membership
Domain Not Using LiveDNS
If you get "not using Gandi LiveDNS" error:
- Log in to Gandi Admin
- Go to domain management
- Attach LiveDNS service to the domain
Rate Limit (429)
Gandi allows 1000 requests/minute. If exceeded:
- Wait 60 seconds
- Reduce frequency of API calls
API Reference
The skill provides importable functions:
import {
testAuth,
listDomains,
getDomain,
listDnsRecords,
getDnsRecord,
checkAvailability
} from './gandi-api.js';
// Test authentication
const auth = await testAuth();
// List domains
const domains = await listDomains();
// Get domain info
const domain = await getDomain('example.com');
// List DNS records
const records = await listDnsRecords('example.com');
// Get specific DNS record
const record = await getDnsRecord('example.com', '@', 'A');
// Check availability
const available = await checkAvailability(['example.com', 'example.net']);
Security
Token Storage
โ DO:
- Store at
~/.config/gandi/api_token - Use 600 permissions (owner read-only)
- Rotate tokens regularly
- Use minimal required scopes
โ DON'T:
- Commit tokens to repositories
- Share tokens between users
- Give tokens unnecessary permissions
- Store tokens in scripts
Token Scopes
Phase 1 (current):
- Domain: read
- LiveDNS: read
Phase 2+ (future):
- Domain: read, write (for registration, renewal)
- LiveDNS: read, write (for DNS modifications)
- Certificate: read (optional, for SSL certs)
- Email: read, write (optional, for email config)
Architecture
gandi-skill/
โโโ SKILL.md # This file
โโโ references/ # API documentation
โ โโโ api-overview.md
โ โโโ authentication.md
โ โโโ domains.md
โ โโโ livedns.md
โ โโโ setup.md
โโโ scripts/ # Helper utilities
โโโ package.json
โโโ gandi-api.js # Core API client
โโโ test-auth.js # Test authentication
โโโ list-domains.js # List domains
โโโ list-dns.js # List DNS records
Development Roadmap
Phase 1: Read Operations (โ Current)
- Authentication with PAT
- List domains
- Get domain details
- List DNS records
- Basic error handling
Phase 2: DNS Modifications
- Add DNS records
- Update DNS records
- Delete DNS records
- Bulk DNS operations
Phase 3: Domain Management
- Domain registration
- Domain renewal
- Auto-renewal configuration
- Nameserver management
Phase 4: Multi-Organization (#1)
- Profile-based token management
- Organization selection
- Multiple token support
Phase 5: Advanced Features
- DNSSEC management
- Certificate management
- Email/mailbox configuration
- Domain transfer operations
Contributing
See Contributing Guide in the main README.
Support
- Issues: GitHub Issues
- Documentation: Reference Guides
- Gandi Support: help.gandi.net
License
MIT License - See LICENSE