Deploy Poweradmin using Docker Compose with a complete PowerDNS backend stack. This setup includes PowerDNS Authoritative Server with database backend and Poweradmin web interface.
See Docker installation: Docker
This Docker Compose setup deploys:
Create a project directory:
mkdir -p /opt/poweradmin
cd /opt/poweradmin
Create docker-compose.yml:
version: '3.8'
services:
# PowerDNS Authoritative Server
powerdns:
image: powerdns/pdns-auth-50:5.0.3
container_name: powerdns-auth
restart: unless-stopped
ports:
- "53:53/udp"
- "53:53/tcp"
- "8081:8081" # API/Web interface
cap_add:
- NET_BIND_SERVICE
environment:
- PDNS_AUTH_API_KEY=${PDNS_API_KEY:-change_me_api_key}
- PDNS_webserver=yes
- PDNS_webserver-address=0.0.0.0
- PDNS_webserver-port=8081
- PDNS_webserver-password=${PDNS_WEB_PASSWORD:-change_me_web_password}
- PDNS_launch=gmysql
- PDNS_gmysql-host=pdns-mysql
- PDNS_gmysql-user=pdns
- PDNS_gmysql-password=${PDNS_DB_PASSWORD:-change_me_pdns_db_password}
- PDNS_gmysql-dbname=pdns
- PDNS_default-soa-name=a.misconfigured.dns.server.example.com
- PDNS_default-soa-mail=hostmaster.example.com
- PDNS_enable-dnssec=yes
volumes:
- ./pdns-logs:/var/log/pdns
depends_on:
pdns-mysql:
condition: service_healthy
networks:
- poweradmin-net
healthcheck:
test: ["CMD", "wget", "--quiet", "--tries=1", "--spider", "http://localhost:8081/api/v1/servers/localhost"]
interval: 30s
timeout: 10s
retries: 3
start_period: 40s
# PowerDNS Database (MySQL)
pdns-mysql:
image: mysql:8.0
container_name: pdns-mysql
restart: unless-stopped
environment:
MYSQL_ROOT_PASSWORD: ${MYSQL_ROOT_PASSWORD:-change_me_root_password}
MYSQL_DATABASE: pdns
MYSQL_USER: pdns
MYSQL_PASSWORD: ${PDNS_DB_PASSWORD:-change_me_pdns_db_password}
volumes:
- pdns-mysql-data:/var/lib/mysql
- ./init-pdns:/docker-entrypoint-initdb.d
networks:
- poweradmin-net
healthcheck:
test: ["CMD", "mysqladmin", "ping", "-h", "localhost", "-u", "pdns", "-p${PDNS_DB_PASSWORD:-change_me_pdns_db_password}"]
interval: 10s
timeout: 5s
retries: 5
# Poweradmin Web Interface
poweradmin:
image: poweradmin/poweradmin:latest
container_name: poweradmin
restart: unless-stopped
ports:
- "8080:80" # Web interface
environment:
# Poweradmin Database Settings
- POWERADMIN_DB_HOST=poweradmin-mysql
- POWERADMIN_DB_PORT=3306
- POWERADMIN_DB_NAME=poweradmin
- POWERADMIN_DB_USER=poweradmin
- POWERADMIN_DB_PASS=${POWERADMIN_DB_PASSWORD:-change_me_poweradmin_db_password}
- POWERADMIN_DB_TYPE=mysql
# PowerDNS Database Settings (for zone access)
- POWERADMIN_PDNS_DB_HOST=pdns-mysql
- POWERADMIN_PDNS_DB_PORT=3306
- POWERADMIN_PDNS_DB_NAME=pdns
- POWERADMIN_PDNS_DB_USER=pdns
- POWERADMIN_PDNS_DB_PASS=${PDNS_DB_PASSWORD:-change_me_pdns_db_password}
- POWERADMIN_PDNS_DB_TYPE=mysql
# PowerDNS API Settings (recommended for DNSSEC)
- POWERADMIN_PDNS_API_ENABLED=true
- POWERADMIN_PDNS_API_HOST=powerdns
- POWERADMIN_PDNS_API_PORT=8081
- POWERADMIN_PDNS_API_KEY=${PDNS_API_KEY:-change_me_api_key}
- POWERADMIN_PDNS_API_PROTOCOL=http
# Security Settings
- POWERADMIN_PASSWORD_HASH_ALGO=PASSWORD_DEFAULT
- POWERADMIN_SESSION_TIMEOUT=3600
# Optional: LDAP Authentication
# - POWERADMIN_LDAP_HOST=ldap.example.com
# - POWERADMIN_LDAP_PORT=389
# - POWERADMIN_LDAP_BASE_DN=dc=example,dc=com
# - POWERADMIN_LDAP_BIND_DN=cn=admin,dc=example,dc=com
# - POWERADMIN_LDAP_BIND_PASS=ldap_password
# - POWERADMIN_LDAP_USER_FILTER=(uid=%s)
# Optional: Reverse Proxy Settings
# - POWERADMIN_TRUSTED_PROXIES=10.0.0.0/8,172.16.0.0/12,192.168.0.0/16
depends_on:
poweradmin-mysql:
condition: service_healthy
powerdns:
condition: service_healthy
networks:
- poweradmin-net
healthcheck:
test: ["CMD", "wget", "--quiet", "--tries=1", "--spider", "http://localhost:80"]
interval: 30s
timeout: 10s
retries: 3
start_period: 30s
# Poweradmin Database (MariaDB)
poweradmin-mysql:
image: mariadb:10.11
container_name: poweradmin-mysql
restart: unless-stopped
environment:
MYSQL_ROOT_PASSWORD: ${MARIADB_ROOT_PASSWORD:-change_me_root_password}
MYSQL_DATABASE: poweradmin
MYSQL_USER: poweradmin
MYSQL_PASSWORD: ${POWERADMIN_DB_PASSWORD:-change_me_poweradmin_db_password}
volumes:
- poweradmin-mysql-data:/var/lib/mysql
networks:
- poweradmin-net
healthcheck:
test: ["CMD", "mysqladmin", "ping", "-h", "localhost", "-u", "poweradmin", "-p${POWERADMIN_DB_PASSWORD:-change_me_poweradmin_db_password}"]
interval: 10s
timeout: 5s
retries: 5
volumes:
pdns-mysql-data:
poweradmin-mysql-data:
networks:
poweradmin-net:
driver: bridge
Create a .env file for sensitive credentials:
# .env - Add to .gitignore!
# PowerDNS Settings
PDNS_API_KEY=your_secure_api_key_here
PDNS_WEB_PASSWORD=your_secure_web_password_here
PDNS_DB_PASSWORD=your_secure_pdns_db_password
# MySQL Root Passwords
MYSQL_ROOT_PASSWORD=your_secure_mysql_root_password
MARIADB_ROOT_PASSWORD=your_secure_mariadb_root_password
# Poweradmin Settings
POWERADMIN_DB_PASSWORD=your_secure_poweradmin_db_password
Create the PowerDNS schema initialization script:
mkdir -p init-pdns
# Download PowerDNS MySQL schema
curl -fsSL https://raw.githubusercontent.com/PowerDNS/pdns/master/modules/gmysqlbackend/schema.mysql.sql > init-pdns/schema.sql
# Start all services
docker compose up -d
# Check status
docker compose ps
# View logs
docker compose logs -f poweradmin
docker compose logs -f powerdns
Navigate to: http://localhost:8080 (or your server IP)
First-time setup:
adminadmin (change immediately!)Login and configure:
For production, use HTTPS with a reverse proxy:
# Add to docker-compose.yml
nginx-proxy:
image: nginx:alpine
container_name: poweradmin-proxy
restart: unless-stopped
ports:
- "80:80"
- "443:443"
volumes:
- ./nginx.conf:/etc/nginx/nginx.conf:ro
- ./ssl:/etc/nginx/ssl:ro
depends_on:
- poweradmin
networks:
- poweradmin-net
Create nginx.conf:
events {
worker_connections 1024;
}
http {
server {
listen 80;
server_name dns-admin.example.com;
return 301 https://$server_name$request_uri;
}
server {
listen 443 ssl http2;
server_name dns-admin.example.com;
ssl_certificate /etc/nginx/ssl/fullchain.pem;
ssl_certificate_key /etc/nginx/ssl/privkey.pem;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers HIGH:!aNULL:!MD5;
location / {
proxy_pass http://poweradmin:80;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
# Security headers
add_header X-Frame-Options "SAMEORIGIN" always;
add_header X-Content-Type-Options "nosniff" always;
add_header X-XSS-Protection "1; mode=block" always;
}
}
For automatic Let’s Encrypt certificates:
# Add to docker-compose.yml
traefik:
image: traefik:v2.10
container_name: traefik
restart: unless-stopped
ports:
- "80:80"
- "443:443"
volumes:
- /var/run/docker.sock:/var/run/docker.sock:ro
- ./traefik.yml:/etc/traefik/traefik.yml:ro
- ./letsencrypt:/letsencrypt
networks:
- poweradmin-net
poweradmin:
# Add to poweradmin service
labels:
- "traefik.enable=true"
- "traefik.http.routers.poweradmin.rule=Host(`dns-admin.example.com`)"
- "traefik.http.routers.poweradmin.entrypoints=websecure"
- "traefik.http.routers.poweradmin.tls.certresolver=letsencrypt"
- "traefik.http.services.poweradmin.loadbalancer.server.port=80"
#!/bin/bash
# backup.sh
BACKUP_DIR="./backups"
DATE=$(date +%Y%m%d_%H%M%S)
mkdir -p $BACKUP_DIR
# Backup PowerDNS database
docker exec pdns-mysql mysqldump -u root -p${MYSQL_ROOT_PASSWORD} pdns > $BACKUP_DIR/pdns_$DATE.sql
# Backup Poweradmin database
docker exec poweradmin-mysql mysqldump -u root -p${MARIADB_ROOT_PASSWORD} poweradmin > $BACKUP_DIR/poweradmin_$DATE.sql
# Keep only last 7 backups
find $BACKUP_DIR -name "*.sql" -mtime +7 -delete
echo "Backup completed: $DATE"
# Restore PowerDNS
cat pdns_20260210_120000.sql | docker exec -i pdns-mysql mysql -u root -p${MYSQL_ROOT_PASSWORD} pdns
# Restore Poweradmin
cat poweradmin_20260210_120000.sql | docker exec -i poweradmin-mysql mysql -u root -p${MARIADB_ROOT_PASSWORD} poweradmin
Poweradmin cannot connect to PowerDNS
# Check network connectivity
docker compose exec poweradmin ping powerdns
# Verify API access
docker compose exec poweradmin curl -H "X-API-Key: your_key" http://powerdns:8081/api/v1/servers/localhost
Port 53 already in use
# Stop systemd-resolved if conflicting
sudo systemctl stop systemd-resolved
sudo systemctl disable systemd-resolved
Database initialization fails
# Check schema was loaded
docker compose exec pdns-mysql mysql -u pdns -p -e "SHOW TABLES;" pdns
# Manually load schema if needed
cat init-pdns/schema.sql | docker exec -i pdns-mysql mysql -u root -p pdns
Poweradmin shows blank page
# Check logs
docker compose logs poweradmin
# Verify database connection
docker compose exec poweradmin-mysql mysql -u poweradmin -p -e "SHOW DATABASES;"
Running Poweradmin in containers? We can help with Docker Compose configurations, Kubernetes deployments, and production-ready container orchestration. Contact office@linux-server-admin.com or visit our contact page.