Percio Castelo.
PT Home
How to create and configure DNS templates in HestiaCP
← Back to blog

How to create and configure DNS templates in HestiaCP

6/14/2026 · 6 min · Infrastructure · 286 views

Efficient and standardized DNS zone provisioning is a cornerstone for any hosting provider or system administrator. Within the HestiaCP control panel ecosystem, DNS records are deployed and managed using template files (with the .tpl extension). These models automate the creation of essential zone records (such as A, MX, TXT, and CNAME) whenever a domain is added to a user account.

In this technical systems engineering guide, I dissect the inner workings and anatomy of DNS templates in HestiaCP, detailing local file paths, variable mapping, the step-by-step process of creating and applying custom templates, alongside validation and troubleshooting routines recommended for production.


1. Location and core mechanics#

DNS templates in HestiaCP act as pre-configured database skeletons. When a new zone is created (whether through the graphical interface, the CLI, or via API calls from billing platforms), HestiaCP reads the selected .tpl file, parses the placeholder variables with the server's live parameters, and writes the zone records into the files managed by the BIND9 resolver.

All system-wide and user-defined templates are stored in the following directory:

/usr/local/hestia/data/templates/dns/

To understand the variable schema and parsing boundaries defined by HestiaCP's backend scripts, read the README file in the templates folder:

cat /usr/local/hestia/data/templates/dns/README

2. Directory of native HestiaCP DNS templates#

HestiaCP includes a variety of built-in templates to handle common web service architectures:

  • child-ns.tpl: Sets up child nameservers (Glue Records) mapping ns1.your-domain.com and ns2.your-domain.com using automatic A records.
  • default-nomail.tpl: Provisions standard web hosting records (A, CNAME, TXT) but excludes MX parameters, preventing local mail delivery attempts.
  • default.tpl: The standard template for default hosting packages. It configures standard web records alongside local MX records to route email locally.
  • gmail.tpl: Pre-configures MX records pointing directly to Google Workspace (G Suite) mail routing servers.
  • office365.tpl: Configures the required MX and verification TXT records (SPF and MS-token) for validating email flow with Microsoft Office 365.
  • zoho.tpl: Automates the MX and verification TXT setups needed for Zoho Mail servers.

3. The role of the empty template (blank.tpl)#

One of the most important models in production-grade hosting clusters is the blank.tpl. Unlike others, this template is entirely empty, generating a clean zone with no default resource records.

This structure is highly useful for integrations with automated billing platforms such as WHMCS. In the default dns_only package, the blank.tpl acts as the primary configuration model. When a client purchases a domain and the zone is initialized, the system creates it with no pre-configured records.

This avoids routing conflicts: if a client plans to use third-party mail routing (such as Google Workspace) or point their website to an external CDN (e.g., Cloudflare), the zone will not contain local A or MX records pointing to the local server, eliminating internal email routing loops or incorrect DNS propagation.


4. Anatomy of a template file record#

Every single line in a .tpl template represents a distinct DNS record structured with parameters. The keys processed by the HestiaCP parser are:

AttributeDescriptionExample
IDUnique, sequential numeric identifier inside the file.1
RECORDThe host or subdomain prefix. Use @ for the origin root domain.mail or www
TYPEThe DNS resource record type matching internet standards.A, AAAA, CNAME, MX, TXT
PRIORITYThe priority value. Required for MX records (lower numbers have higher priority).10 or empty
VALUEThe target pointer (IPv4, IPv6, or a fully qualified domain name with a trailing dot).%ip% or %domain%.
TTLTime To Live (caching time) in seconds.300 (5 minutes) or 3600 (1 hour)
SUSPENDEDSuspends the record. When set to yes, it blocks UI modifications.no
DATEDate applied. The %date% placeholder is replaced by the active date when the template is applied to a domain.%date%
TIMEModification time. The %time% placeholder is replaced by the active time when applied.%time%

5. Security and customization best practices#

Golden rules#

  1. > [!WARNING]
NEVER edit HestiaCP native templates (such as default.tpl or gmail.tpl). They are considered core system files and can be completely overwritten and restored to HestiaCP defaults during panel updates. For customizations, create a unique file name (e.g., my-template.tpl).
  1. Using Trailing Dots: When writing FQDN pointers in CNAME or MX records (e.g., %domain%. or mail.domain.com.), ensure you append the trailing dot (.). Without it, the BIND9 resolver will append the base domain recursively, generating incorrect resolution records (e.g., mail.domain.com.domain.com).
  2. Preventive Backup Routine: Before modifying files or creating new templates, make backups of the individual files or the entire templates directory:
    # Complete backup of the DNS templates directory in tar.gz
    sudo tar czf /root/backup-dns-templates-$(date +%Y%m%d).tar.gz /usr/local/hestia/data/templates/dns/
    
    # Individual file backup using absolute paths
    sudo cp -p /usr/local/hestia/data/templates/dns/default.tpl /usr/local/hestia/data/templates/dns/default.tpl.bak

6. Creating a custom DNS template from scratch#

To create and deploy your own standardized set of DNS records:

Step 1: Create the template file#

Create a new .tpl file inside the templates directory with a unique name:

sudo nano /usr/local/hestia/data/templates/dns/my-template.tpl

Step 2: Define template records#

Insert the complete set of records with all required parameters in place. Below is a complete and working custom template model that you can copy and edit:

ID='1' RECORD='@' TYPE='A' PRIORITY='' VALUE='%ip%' TTL='300' SUSPENDED='no' TIME='%time%' DATE='%date%'
ID='2' RECORD='www' TYPE='CNAME' PRIORITY='' VALUE='%domain%.' TTL='300' SUSPENDED='no' TIME='%time%' DATE='%date%'
ID='3' RECORD='mail' TYPE='A' PRIORITY='' VALUE='%ip%' TTL='300' SUSPENDED='no' TIME='%time%' DATE='%date%'
ID='4' RECORD='@' TYPE='MX' PRIORITY='10' VALUE='mail.%domain%.' TTL='300' SUSPENDED='no' TIME='%time%' DATE='%date%'
ID='5' RECORD='@' TYPE='TXT' PRIORITY='' VALUE='v=spf1 a mx ip4:%ip% -all' TTL='300' SUSPENDED='no' TIME='%time%' DATE='%date%'
ID='6' RECORD='ftp' TYPE='CNAME' PRIORITY='' VALUE='%domain%.' TTL='300' SUSPENDED='no' TIME='%time%' DATE='%date%'

Save and exit the file (Ctrl+O, Enter, Ctrl+X in nano).

Step 3: Set correct permissions and ownership#

For HestiaCP to read the file securely, set the correct permissions (ownership to root and public read permission 644):

sudo chown root:root /usr/local/hestia/data/templates/dns/my-template.tpl
sudo chmod 644 /usr/local/hestia/data/templates/dns/my-template.tpl

Step 4: Verify the template file#

List HestiaCP's templates directory to confirm ownership and permissions:

ls -la /usr/local/hestia/data/templates/dns/

The output should include your new template my-template.tpl with 644 permissions.


7. Applying custom templates#

A. When creating a new domain#

  • Via Graphical User Interface (GUI): When adding a new DNS zone, locate the DNS Template dropdown select field and pick your custom template.
  • Via Command Line Interface (CLI): Provision the domain with DNS enabled (yes) and assign the template via HestiaCP CLI:
    v-add-web-domain user domain.com 1.2.3.4 yes
    v-change-dns-domain-tpl user domain.com my-template

B. On an existing domain#

If you need to apply the records of a new template to an existing DNS zone, run HestiaCP's CLI command to change the template and recreate the records:

# Change the template associated with the domain
v-change-dns-domain-tpl user domain.com my-template

# Reload BIND9 resolver settings to propagate the records
sudo systemctl reload bind9
# or via BIND's reload command:
sudo rndc reload

8. Validation and troubleshooting#

Validating template files#

Before using the custom template in production, verify the line syntax to ensure no required attributes are missing:

# Validate line format constraints
grep -E "^ID=.*RECORD=.*TYPE=.*VALUE=" /usr/local/hestia/data/templates/dns/my-template.tpl

Troubleshooting common DNS template faults#

SymptomProbable CauseResolution
Template not listed in templatesIncorrect owner or permissions on the .tpl file.Run: sudo chown root:root file.tpl && sudo chmod 644 file.tpl.
Duplicate records or recursive domain resolutionMissing trailing dot (.) in CNAME/MX value declarations.Set VALUE='%domain%.' with the trailing dot to prevent recursive domain appending.
Custom changes disappeared after updating the panelDirect edits were made on native system templates.Create a new custom file with a unique name instead of modifying default templates.
Changes do not apply to old domainsEditing templates only affects newly created domains.For existing domains, change the template explicitly via v-change-dns-domain-tpl and reload BIND9.

9. Automated backup and validation script#

For administrators managing multi-node infrastructures, the following script automates backup creation, listing, and format validation for all DNS templates on HestiaCP:

#!/bin/bash
# dns_template_manager.sh - Manage HestiaCP DNS Templates safely
# ⚠️ Run this script with root privileges (sudo)

set -e

TEMPLATE_DIR="/usr/local/hestia/data/templates/dns"
BACKUP_DIR="/root/dns-backup-$(date +%Y%m%d-%H%M%S)"

# Terminal colors
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
RED='\033[0;31m'
NC='\033[0m'

log() { echo -e "${GREEN}[INFO]${NC} $1"; }
warn() { echo -e "${YELLOW}[WARN]${NC} $1"; }
error() { echo -e "${RED}[ERROR]${NC} $1"; exit 1; }

# 1. Verify root execution permissions
[[ $EUID -ne 0 ]] && error "This script must be run as root (sudo)"

# 2. Create templates directory backup
log "Creating complete backup of active templates..."
mkdir -p "$BACKUP_DIR"
cp -r "$TEMPLATE_DIR"/* "$BACKUP_DIR/"
log "Backup successfully saved to: ${BACKUP_DIR}"

# 3. List available templates
log "DNS templates found in system:"
ls -la "$TEMPLATE_DIR"/*.tpl 2>/dev/null || warn "No template .tpl files found"

# 4. Validate syntax formats
log "Validating template formatting..."
for tpl in "$TEMPLATE_DIR"/*.tpl; do
    if [[ -f "$tpl" ]]; then
        TOTAL_LINES=$(wc -l < "$tpl")
        # Count lines matching standard parameters
        VALID_LINES=$(grep -c "^ID=.*RECORD=.*TYPE=.*VALUE=" "$tpl" || true)
        # Count invalid lines (ignoring blank lines)
        INVALID_LINES=$(grep -cv "^ID=.*RECORD=.*TYPE=.*VALUE=\|^$" "$tpl" || true)
        
        if [[ $INVALID_LINES -gt 0 ]]; then
            warn "  ⚠️ $(basename "$tpl"): $VALID_LINES valid lines, $INVALID_LINES non-standard lines found!"
        else
            log "  ✅ $(basename "$tpl"): $VALID_LINES valid record lines."
        fi
    fi
done

log "Audit process finished."

Was this article helpful?

Leave a quick reaction to help prioritize future technical guides:

286 reads
Creative Commons Attribution-NonCommercial

This post is licensed under CC BY-NC.

Comments

Join the discussion below.

0 comments