Upgrading to Version 4.5.0
!!! warning "Not yet released"
Version 4.5.0 is still in development on the develop branch. This guide is prepared in advance and the steps below will only work once v4.5.0 is tagged and published. The current stable release is v4.3.4.
Overview
Version 4.5.0 centers on serial handling and delegation. SOA-EDIT and SOA-EDIT-API serial policies can be managed from the UI, zone lists can show the signed serial PowerDNS actually serves, and zone templates understand serial placeholders. Access control gets finer-grained: dedicated permissions for viewing logs, zone metadata, and zone ownership, a DNSSEC key-management permission separate from zone editing, delegation NS editing below the apex, and granular API keys (read-only, operation-restricted, zone-scoped).
Also new: a structured record change log with before/after snapshots, per-record-type default TTLs, trusted proxy support, LDAP user-info sync and auto-provisioning, OIDC form_post response mode, and per-request API logging.
Database Schema Update
The 4.5.0 migration is larger than usual. It adds four tables:
| Table | Purpose |
|---|---|
log_record_changes |
Structured before/after snapshots of record and zone changes, backing the diff-style change log |
record_type_defaults |
Per-record-type default TTLs managed in the admin UI |
api_key_zones |
Zone scoping for granular API keys |
records_zone_templ_api |
Template-record mapping for API-backend zones with encoded record IDs |
Column changes:
| Change | Purpose |
|---|---|
api_keys.is_readonly, api_keys.allowed_operations |
Granular API key restrictions; existing keys stay unrestricted |
login_attempts.attempt_type |
Separate throttling for password and MFA stages |
password_reset_tokens.token widened |
Hashed (sha256) token storage |
zones.zone_templ_id explicit DEFAULT 0 |
Consistent "no template" sentinel |
oidc_user_links / saml_user_links binary collation |
Byte-exact subject matching (already shipped in 4.2.5/4.3.4; included for upgrades from 4.4.0) |
The migration also registers eleven new permissions (see below) and auto-grants the four metadata/ownership view permissions to templates that already hold the matching zone_content_view_* permission, so nothing users could see before the upgrade disappears.
The migration scripts are:
sql/poweradmin-mysql-update-to-4.5.0.sqlsql/poweradmin-pgsql-update-to-4.5.0.sqlsql/poweradmin-sqlite-update-to-4.5.0.sql
Upgrade Instructions
Prerequisites
- Poweradmin v4.4.0
- PHP 8.2 or later
- Database backup
If you are upgrading from an older release, run the intermediate migration scripts first (4.3.0, then 4.4.0, then 4.5.0). Do not skip versions.
Step 1: Backup Your Data
# MySQL/MariaDB
mysqldump -u username -p poweradmin_db > poweradmin_backup_$(date +%Y%m%d).sql
# PostgreSQL
pg_dump -h localhost -U username poweradmin_db > poweradmin_backup_$(date +%Y%m%d).sql
# SQLite
cp /path/to/poweradmin.db /path/to/poweradmin_backup_$(date +%Y%m%d).db
Step 2: Download and Extract
cd /tmp
wget https://github.com/poweradmin/poweradmin/archive/refs/tags/v4.5.0.tar.gz
tar -xzf v4.5.0.tar.gz
rsync -av poweradmin-4.5.0/ /var/www/poweradmin/ --exclude=config/settings.php
Step 3: Run Database Update
MySQL/MariaDB:
mysql -u username -p poweradmin_db < sql/poweradmin-mysql-update-to-4.5.0.sql
PostgreSQL:
psql -h localhost -U username -d poweradmin_db -f sql/poweradmin-pgsql-update-to-4.5.0.sql
SQLite:
sqlite3 /path/to/poweradmin.db < sql/poweradmin-sqlite-update-to-4.5.0.sql
Step 4: Clear Cache and Restart
sudo systemctl restart php-fpm
# or
sudo systemctl restart apache2
New Features
Serial Policies (SOA-EDIT / SOA-EDIT-API)
PowerDNS rewrites zone serials according to the SOA-EDIT and SOA-EDIT-API metadata kinds. Poweradmin can now manage both from the metadata editor and preset them for new zones:
return [
'dns' => [
'soa_edit' => '', // e.g. 'INCEPTION-INCREMENT'; empty = not set
'soa_edit_api' => '', // e.g. 'EPOCH'; 'OFF' disables, empty = server default
'soa_edit_options' => null, // values offered in the metadata editor; null = all, [] hides the kind
'soa_edit_api_options' => null, // values offered in the add-zone selector and editor
],
];
Related serial features:
- Signed serial in zone lists - with
interface.display_signed_serial_in_zone_listenabled (API backend required), zone lists show the serial PowerDNS actually serves after SOA-EDIT, next to the stored one when they differ. - Serial placeholders in templates - zone template SOA records understand
[UNIXTIME]and[COUNTER]placeholders for the serial field. - Presigned zones - zones with the
PRESIGNEDmetadata are recognized, and DNSSEC operations that don't apply to them are gated off.
Record Change Log
Record and zone mutations are now captured with structured before/after snapshots in the new log_record_changes table, powering a diff-style change log view. The existing activity feed (log_zones) is unchanged and continues to work as before.
Granular API Keys
API keys can be restricted along three independent axes (#795):
- Read-only - the key can only perform read operations.
- Allowed operations - an explicit list of permitted operation groups.
- Zone scoping - the key only works against an explicit set of zones.
Existing keys are unrestricted after the upgrade - identical to their previous behavior. Restrictions are edited on the API key pages.
New Permissions
Eleven permissions were added; except for the auto-granted view split (see Breaking Changes), none are granted automatically - admins opt in per permission template:
zone_dnssec_manage_own- manage DNSSEC keys for owned zones without full ueberuser rights.zone_logs_view_own/zone_logs_view_others- access zone activity logs without ueberuser.user_logs_view/group_logs_view- access user and group activity logs.zone_content_edit_ns_subzone- edit delegation NS records below the zone apex while apex NS and SOA stay protected.zone_metadata_view_own/zone_metadata_view_othersandzone_ownership_view_own/zone_ownership_view_others- split out ofzone_content_view_*(auto-granted on upgrade).
Per-Record-Type Default TTLs
Administrators can define a default TTL per record type in the UI (stored in record_type_defaults). When a record is created without an explicit TTL, the type-specific default applies first, then the legacy chain (dns.ttl_reverse for PTR, then dns.ttl).
Trusted Proxies
Deployments behind a CDN or load balancer with a public peer address can now declare it:
return [
'security' => [
'trusted_proxies' => ['203.0.113.10', '198.51.100.0/24'],
],
];
Forwarded IP headers (X-Forwarded-For, X-Real-IP) are honored only from these peers; private and loopback peers are always trusted, matching the previous behavior for same-host reverse proxies.
LDAP: User-Info Sync, Auto-Provisioning, Group Mapping
ldap.sync_user_info- sync fullname/email from the directory on every login (fullname_attribute,email_attributeconfigurable). When enabled, those fields become read-only in the user editor, like OIDC/SAML accounts.ldap.auto_provision- create missing users on first successful LDAP login, withdefault_permission_templateas the fallback template.- LDAP group memberships (
groups_attribute, defaultmemberOf) can map to permission templates and to Poweradmin groups, with the same 1:n mapping semantics as OIDC/SAML.
Authentication and MFA
- OIDC
form_postresponse mode - per-provider opt-in (response_mode => 'form_post', HTTPS only) for providers or proxy setups where query-mode callbacks are problematic. - MFA verification is now rate limited - a six-digit second factor is small enough to guess, so wrong codes are counted and verification is refused once the limit is reached. This applies whenever MFA is enabled and does not require
security.account_lockout.enable_lockout, which ships disabled. Tune it withsecurity.mfa.max_verify_attempts(default5) andsecurity.mfa.verify_lockout_duration(default15minutes). Existing installations gain the limit on upgrade with no configuration change. - MFA stage throttling - failed MFA codes are counted separately from password failures, so a wrong code never blocks a later password login and a fresh password success no longer resets the MFA counter. Unlike password lockout, MFA failures are counted per account across all source addresses and are not exempted by
whitelist_ip_addresses. security.mfa.skip_for_external_auth- skip Poweradmin's MFA enforcement for LDAP/OIDC/SAML logins when the IdP already enforces it.
API Request Logging
With misc.api_request_logging enabled, every public API request is logged to the API log; permission violations (401/403) are logged regardless of the setting. misc.api_log_retention_days prunes old rows (0 keeps everything).
Zone List and UI
- Owner, group, and record-count columns in zone lists can be toggled (
interface.display_owner_in_zone_list,display_group_in_zone_list,show_zone_record_count). - Zone lists in API backend mode are considerably faster on installations with many zones: record counts are now fetched only for the zones on the current page instead of for every zone, and repeated reads of the same PowerDNS data are reused within a request. This changes how the Records column sorts, see Other changes.
- Record comments show author and last-modified time in a tooltip.
- API-backend zone lists indicate zones with a pending NOTIFY.
- The "Permission templates" menu item is now labeled "Permissions".
dns.parent_zone_ownership_check(default on) blocks creating a zone that overlaps an existing zone owned by another user.
Breaking Changes
interface.application_url is now required for OIDC and SAML
Poweradmin no longer derives a host from the request when building URLs that leave the application. Under the official Docker image (FrankenPHP/Caddy) and under Apache's default UseCanonicalName Off, the web server takes SERVER_NAME from the client's Host header, so the previous fallback let a forged header steer the OAuth redirect_uri and the SAML entityID/ACS to another host.
If OIDC or SAML is enabled and interface.application_url is empty, single sign-on stops working until you set it. Set it to the full public URL of the install before upgrading:
return [
'interface' => [
'application_url' => 'https://dns.example.com/poweradmin',
],
];
The value must match the redirect URI already registered with your identity provider. For deployments that were working before the upgrade this is the host users already reach Poweradmin on, so no provider-side change is needed.
What changes per feature when application_url is empty:
| Feature | Behaviour |
|---|---|
| OIDC login | Fails with interface.application_url must be configured before OIDC can be used |
SAML login and /saml/metadata |
Fail unless sp.entity_id, sp.assertion_consumer_service_url and sp.single_logout_service_url are all set explicitly |
| OIDC logout | Still redirects to the provider, but without post_logout_redirect_uri, so users are not returned to the login page |
| Zone-access notification email | Still sent, with the "Manage Zone" link omitted |
| API docs page | Still works; the embedded spec URL becomes relative |
This also ships in the 4.2.x, 4.3.x and 4.4.x patch releases. See OIDC and SAML.
Password reset tokens are stored hashed
Reset tokens are now stored as sha256 hashes. Plaintext tokens issued before the upgrade cannot be validated afterwards - affected users simply request a new reset link; old rows expire within the token lifetime (1 hour by default).
Metadata and ownership view permissions are split out of content view
zone_content_view_own/zone_content_view_others no longer imply seeing zone metadata or zone owners. The migration auto-grants the new zone_metadata_view_* and zone_ownership_view_* permissions to every template holding the matching content-view permission, so nothing changes visibly on upgrade - but new templates need the permissions granted explicitly, and admins can now revoke them to hide those sections.
LDAP identity fields become read-only when sync is enabled
With ldap.sync_user_info enabled, fullname and email of LDAP accounts are managed by the directory and read-only in the user editor. With sync disabled (the default), they remain editable as before.
Lua-enabling zone metadata is restricted to administrators
ENABLE-LUA-RECORDS and LUA-AXFR-SCRIPT make PowerDNS evaluate Lua, which reaches
every zone the server hosts, so they can now only be set by a user holding
user_is_ueberuser. Zone-level editors keep full access to every other metadata kind.
Values an administrator has already set are left alone: the editor compares what was
submitted against what is stored and only rejects an actual change, so a zone editor
is not locked out of saving unrelated metadata on a zone that has these kinds set.
LUA records are restricted to editors above client level
LUA joins SOA and NS as a record type that zone_content_edit_own_as_client may
not create, edit or delete. PowerDNS executes the script content of a LUA record, so it
is not something a client-level tenant should be able to introduce. Owners and
administrators (zone_content_edit_own / zone_content_edit_others) are unaffected, and
existing LUA records keep resolving - only editing them through Poweradmin is gated.
Note this only ever mattered where the server has LUA enabled, either globally with
enable-lua-records=yes or per zone via ENABLE-LUA-RECORDS - which the same release
restricts to administrators.
The same restriction ships in 4.4.1 and 4.3.5, so it is not exclusive to this release.
It also covers zone templates: a template record is written straight to the backend when
the template is applied, so it never passes the record-level checks. Storing a LUA
record in a template therefore requires zone_content_edit_own or
zone_content_edit_others, a stricter bar than the client rule alone. Saving an existing
zone as a template skips record types the caller may not author and names them in the
resulting message rather than failing the whole save.
Identity providers can no longer grant administrator rights
oidc/saml/ldap.allow_superuser_provisioning defaults to false. With it unset,
Poweradmin refuses to provision superuser from an IdP assertion in either of the two ways
that previously worked:
- a
permission_template_mappingentry resolving to a template that grantsuser_is_ueberuser, and - a
group_mappingentry resolving to a group whose template grants it - note the installer ships anAdministratorsgroup bound to exactly such a template.
If your deployment relies on the IdP deciding who is an administrator, those logins will
stop being administrators after this upgrade. Both refusals are logged, so a login that
silently loses rights can be traced. Either set the flag to true, or grant administrator
rights inside Poweradmin, where an existing administrator has to act.
user_edit_templ_perm no longer hands out administrator rights
The permission delegates template management, not the granting of administrator rights. A
holder who is not themselves an administrator can no longer assign a template that grants
user_is_ueberuser - on the user editor, the user create form, or the REST API user
endpoints - and can only change their own template if they also hold user_edit_others.
Assigning any ordinary template is unaffected, so a delegated user administrator keeps
working as before unless they were relying on handing out the Administrator template.
This ships across the supported lines, not only here: 4.4.1, 4.3.5, 4.2.6 and 3.9.12 carry the same rule.
Other changes
- The Records column in zone lists is no longer sortable in API backend mode. Record counts are now resolved only for the zones on the current page, so ordering by them would sort just that page rather than the whole list. The column header is plain text instead of a sort link, and a stale
count_recordssort carried over in a session falls back to sorting by name. SQL backend mode is unaffected and still sorts by record count. - The MFA failure counter is tracked per authentication stage; repeated wrong MFA codes can lock an account even after a correct password.
- All other new features are additive or opt-in: new tables start empty, new settings default to prior behavior, and new permissions (except the auto-granted view split) are not assigned to any template.
Rollback
To roll back to v4.4.0:
- Restore your database backup.
- Restore your file backup.
- Restart the web server.
The new tables and columns are harmless in earlier versions - they are simply unused. Note that password reset tokens issued by 4.5.0 (hashed) cannot be validated by 4.4.0; users would need to request a new link after a rollback.