OneLinersCommand workbench
Guides
Databases & Data / Security

Configure phpMyAdmin for multiple database servers and two-factor authentication

Define explicit TLS-verified database targets, hide arbitrary server entry, enable configuration storage and 2FA, constrain privileges, and test fail-closed behavior.

70 min8 stepsChanges system stateRevision 2
Save or explore
Save to collectionCreate a collection in the sidebar first.
0 of 8 steps completed
Goal

Provide one controlled administration portal for approved databases without allowing users to redirect it to arbitrary hosts.

Supported environments
  • phpMyAdmin 5.2
Prerequisites
  • Recovery access and maintenance window Keep console access and schedule write-affecting work so an interrupted package, grant, backup, or replication change can be recovered.
  • Verified backup Create a fresh backup and prove that its format, encryption key, and restore procedure are available before changing production data.
  • Capacity and compatibility Check database version, storage headroom, character sets, application driver compatibility, and expected downtime.df -h; df -i; free -m
Operating boundary

OneLiners never runs these steps or stores secrets. Review placeholders, versions, current state, and change-control requirements before using a command.

Full guide

What you will build

System
  • A production-ready phpMyAdmin with MySQL/MariaDB implementation of “Configure phpMyAdmin for multiple database servers and two-factor authentication” with explicit identities, configuration ownership, observable checkpoints and a tested reversal path.
  • A before-state, native validation sequence and concrete evidence set covering the database service, client behavior, data or administrative surface affected by this procedure.
  • A least-privilege operational runbook that keeps secrets out of commands and verifies both the required success path and an expected denial or failure boundary.
Observable outcome
  • Provide one controlled administration portal for approved databases without allowing users to redirect it to arbitrary hosts. The result is demonstrated through the guide's native verification commands and representative application or restore evidence.
  • Unrelated databases, accounts, listeners and services remain unchanged; operators can identify the exact revision, artifact and rollback action for this change.

Architecture

How the parts fit together

phpMyAdmin is a privileged PHP application placed behind a dedicated administrative hostname, TLS and an outer access-control boundary. The package or pinned upstream artifact feeds a dedicated FPM/web configuration; database credentials are entered by the operator and not embedded as administrative secrets. Restrictive network/authentication policy, two-factor support, logs, session security and a removal path compensate for the enlarged web attack surface.

Dedicated admin hostnameKeeps the interface separate from public applications.
Web server and PHP-FPMServe the pinned application through a restricted execution boundary.
Outer access controlsRequire trusted network and additional authentication before phpMyAdmin.
Database authenticationUses individual database accounts without embedded root credentials.
  1. Capture effective configuration, versions, listeners, identities, grants, workload health and a recoverable before-state.
  2. Prepare the phpmyadmin candidate using only official phpMyAdmin with MySQL/MariaDB interfaces, protected secret delivery and the narrowest necessary scope.
  3. Apply one controlled layer at a time, run the immediate checkpoint and inspect native logs/status before proceeding.
  4. Perform end-to-end success and expected-failure tests; retain rollback evidence and schedule recurring verification.

Assumptions

  • The installed phpMyAdmin with MySQL/MariaDB family and version are supported by the official sources linked below, and package/configuration provenance is known.
  • A maintenance or canary window, current recoverable backup and console-level recovery path exist before state-changing database work begins.
  • Operator, application, backup, replication and web-administration identities are separate; secrets are supplied by protected option files, environment injection with appropriate controls, or a secret manager.
  • Representative schema size, workload, storage capacity, network policy and recovery objectives are documented for the target environment.

Key concepts

user@host identity
MySQL-family authorization matches both an account name and its permitted client origin, not the name alone.
effective configuration
The final runtime values after packaged defaults and ordered configuration fragments have been combined.
consistent state
Data and metadata captured at one valid transactional or recovery point rather than a mixture of moments.
recovery objective
The acceptable data-loss window and restoration time that drive backup, replication and validation design.
positive and negative verification
Proving an intended operation succeeds and an operation outside the granted/security boundary fails.

Before you copy

Values used in this guide

{{adminDomain}}

Operator-reviewed value used by this tutorial for adminDomain; derive it from the target environment and never from untrusted request data.

Example: db-admin.example.com
{{caFile}}

Operator-reviewed value used by this tutorial for caFile; derive it from the target environment and never from untrusted request data.

Example: /etc/mysql/ca/organization-root.pem
{{controlDatabase}}

Operator-reviewed value used by this tutorial for controlDatabase; derive it from the target environment and never from untrusted request data.

Example: phpmyadmin
{{controlHost}}

Operator-reviewed value used by this tutorial for controlHost; derive it from the target environment and never from untrusted request data.

Example: db-control.example.com
{{databaseHosts}}

Operator-reviewed value used by this tutorial for databaseHosts; derive it from the target environment and never from untrusted request data.

Example: db-a.example.com,db-b.example.com
{{outerUser}}

Operator-reviewed value used by this tutorial for outerUser; derive it from the target environment and never from untrusted request data.

Example: db-admin
{{phpVersion}}

Exact PHP major and minor branch used by the target runtime.

Example: 8.3
{{pmaErrorLog}}

Operator-reviewed value used by this tutorial for pmaErrorLog; derive it from the target environment and never from untrusted request data.

Example: /var/log/phpmyadmin/error.log
{{twoFactorEnrollmentReport}}

Operator-reviewed value used by this tutorial for twoFactorEnrollmentReport; derive it from the target environment and never from untrusted request data.

Example: example-twofactorenrollmentreport

Security and production boundaries

  • Never place database passwords, encryption keys, recovery codes or private certificates directly in reusable shell history or repository files.
  • Do not use `%`, global grants, disabled TLS verification, public administrative interfaces or world-readable dumps as troubleshooting shortcuts.
  • Treat backups, slow logs and phpMyAdmin sessions as sensitive data; encrypt, restrict, rotate and monitor them according to the same or stronger policy as production.

Stop before continuing if

  • Stop if the server version/config family is ambiguous, the backup cannot be restored, secrets would be exposed, or a proposed command affects databases/accounts beyond the declared scope.
  • Do not continue when native validation, representative workload, expected-denial test, TLS identity, replication continuity or storage capacity evidence is incomplete for this procedure.
  • Immediately isolate or revert a change that broadens a listener/grant, breaks application health, introduces replication error, loses recoverability or produces unbounded sensitive logs.
01

instruction

Inventory approved database targets

read-only

For each target record DNS identity, port, CA, server certificate name, database version, owner, network path, and emergency access.

Why this step matters

Inventory approved database targets is a separate checkpoint because it establishes one auditable part of provide one controlled administration portal for approved databases without allowing users to redirect it to arbitrary hosts. Performing it independently keeps a failed prerequisite, syntax error, or compatibility mismatch from being hidden by later actions.

What to understand

For each target record DNS identity, port, CA, server certificate name, database version, owner, network path, and emergency access. Read the complete command or configuration before execution, replace the documented placeholders, and compare the target host with the supported environments listed at the beginning of this tutorial.

Capture the before-state and the exact output in the change record. If this step modifies a file or service, validate the candidate with its native checker before any reload; a successful process exit alone does not prove that the application uses the intended value.

Use a representative staging or canary host first. Repeat the stated checkpoint immediately, because proceeding with ambiguous evidence makes the later end-to-end verification and rollback materially harder.

System changes

  • This step may affect the files, packages, identities, services, or runtime policy named in “Inventory approved database targets”. The scope must remain limited to the selected application and supported host.

Syntax explained

for
Invokes the principal tool or configuration operation for “Inventory approved database targets”; confirm that it resolves to the expected packaged executable or file before using elevated privileges.
{{…}}
Marks an operator-supplied value. Replace every placeholder deliberately; do not paste untrusted text or leave braces in the production command.
|
Passes standard output to the next read-only inspection stage; review each stage separately if the combined result is surprising.
Command
Fill variables0/1 ready

Values stay on this page and are never sent or saved.

for h in {{databaseHosts}}; do getent ahosts "$h"; timeout 3 openssl s_client -connect "$h:3306" -starttls mysql -servername "$h" </dev/null 2>/dev/null | openssl x509 -noout -subject -issuer -dates || true; done
Example output / evidence
Every target has an approved identity and reachable encrypted path.

Checkpoint: Checkpoint: Inventory approved database targets

Continue whenEvery target has an approved identity and reachable encrypted path. Treat this concrete evidence as the minimum success signal and also confirm that unrelated services and the previous healthy path remain unchanged.

Stop whenStop before the next step when for reports an error, the output differs materially from the example, an unexpected package/service/path is affected, or the required before-state and rollback artifact are missing.

If this step fails

The command for “Inventory approved database targets” fails, produces no useful evidence, or the expected service/configuration state is absent.

Likely causeA placeholder targets the wrong environment, the installed version uses another path or unit name, permissions are insufficient, or an earlier prerequisite was not satisfied.

Safe checks
  • command -v for 2>/dev/null || true
  • systemctl --failed --no-pager 2>/dev/null || true
  • journalctl -p warning -n 50 --no-pager 2>/dev/null || true

ResolutionDo not improvise a privileged workaround. Re-read the environment and variable table, inspect the official source for the installed version, restore the candidate file if necessary, and repeat only this checkpoint.

Security notes

  • Keep secrets out of shell history, process arguments, screenshots, logs, and tutorial placeholders. Elevate only the narrow command that requires it and preserve package signature and TLS verification.

Alternatives

  • When the host layout or software version differs, use the vendor-supported equivalent in a disposable staging environment and document the mapping before touching production.

Stop conditions

  • Stop if the action broadens network exposure, permissions, package sources, writable paths, or service privileges beyond the tutorial's declared architecture.
02

instruction

Back up phpMyAdmin configuration and storage schema

caution

Archive config.inc.php, web-server policy, FPM pool, and configuration-storage database before changing authentication behavior.

Why this step matters

Back up phpMyAdmin configuration and storage schema is a separate checkpoint because it establishes one auditable part of provide one controlled administration portal for approved databases without allowing users to redirect it to arbitrary hosts. Performing it independently keeps a failed prerequisite, syntax error, or compatibility mismatch from being hidden by later actions.

What to understand

Archive config.inc.php, web-server policy, FPM pool, and configuration-storage database before changing authentication behavior. Read the complete command or configuration before execution, replace the documented placeholders, and compare the target host with the supported environments listed at the beginning of this tutorial.

Capture the before-state and the exact output in the change record. If this step modifies a file or service, validate the candidate with its native checker before any reload; a successful process exit alone does not prove that the application uses the intended value.

Use a representative staging or canary host first. Repeat the stated checkpoint immediately, because proceeding with ambiguous evidence makes the later end-to-end verification and rollback materially harder.

System changes

  • This step may affect the files, packages, identities, services, or runtime policy named in “Back up phpMyAdmin configuration and storage schema”. The scope must remain limited to the selected application and supported host.

Syntax explained

tar
Invokes the principal tool or configuration operation for “Back up phpMyAdmin configuration and storage schema”; confirm that it resolves to the expected packaged executable or file before using elevated privileges.
{{…}}
Marks an operator-supplied value. Replace every placeholder deliberately; do not paste untrusted text or leave braces in the production command.
Command
Fill variables0/3 ready

Values stay on this page and are never sent or saved.

sudo tar -czf /root/phpmyadmin-before-2fa-$(date +%F-%H%M).tgz /etc/phpmyadmin /etc/nginx /etc/apache2 /etc/php 2>/dev/null; mysqldump --host={{controlHost}} --ssl-mode=VERIFY_IDENTITY --ssl-ca={{caFile}} {{controlDatabase}} > /root/phpmyadmin-control.sql
Example output / evidence
Configuration and control database backups are non-empty.

Checkpoint: Checkpoint: Back up phpMyAdmin configuration and storage schema

Continue whenConfiguration and control database backups are non-empty. Treat this concrete evidence as the minimum success signal and also confirm that unrelated services and the previous healthy path remain unchanged.

Stop whenStop before the next step when tar reports an error, the output differs materially from the example, an unexpected package/service/path is affected, or the required before-state and rollback artifact are missing.

If this step fails

The command for “Back up phpMyAdmin configuration and storage schema” fails, produces no useful evidence, or the expected service/configuration state is absent.

Likely causeA placeholder targets the wrong environment, the installed version uses another path or unit name, permissions are insufficient, or an earlier prerequisite was not satisfied.

Safe checks
  • command -v tar 2>/dev/null || true
  • systemctl --failed --no-pager 2>/dev/null || true
  • journalctl -p warning -n 50 --no-pager 2>/dev/null || true

ResolutionDo not improvise a privileged workaround. Re-read the environment and variable table, inspect the official source for the installed version, restore the candidate file if necessary, and repeat only this checkpoint.

Security notes

  • Keep secrets out of shell history, process arguments, screenshots, logs, and tutorial placeholders. Elevate only the narrow command that requires it and preserve package signature and TLS verification.

Alternatives

  • When the host layout or software version differs, use the vendor-supported equivalent in a disposable staging environment and document the mapping before touching production.

Stop conditions

  • Stop if the action broadens network exposure, permissions, package sources, writable paths, or service privileges beyond the tutorial's declared architecture.
03

config

Define each approved server explicitly

caution

Add one config entry per host with a stable verbose name, hostname rather than IP, port, auth_type=cookie, and TLS CA verification.

Why this step matters

Define each approved server explicitly is a separate checkpoint because it establishes one auditable part of provide one controlled administration portal for approved databases without allowing users to redirect it to arbitrary hosts. Performing it independently keeps a failed prerequisite, syntax error, or compatibility mismatch from being hidden by later actions.

What to understand

Add one config entry per host with a stable verbose name, hostname rather than IP, port, auth_type=cookie, and TLS CA verification. Read the complete command or configuration before execution, replace the documented placeholders, and compare the target host with the supported environments listed at the beginning of this tutorial.

Capture the before-state and the exact output in the change record. If this step modifies a file or service, validate the candidate with its native checker before any reload; a successful process exit alone does not prove that the application uses the intended value.

Use a representative staging or canary host first. Repeat the stated checkpoint immediately, because proceeding with ambiguous evidence makes the later end-to-end verification and rollback materially harder.

System changes

  • This step may affect the files, packages, identities, services, or runtime policy named in “Define each approved server explicitly”. The scope must remain limited to the selected application and supported host.

Syntax explained

sudoedit
Invokes the principal tool or configuration operation for “Define each approved server explicitly”; confirm that it resolves to the expected packaged executable or file before using elevated privileges.
|
Passes standard output to the next read-only inspection stage; review each stage separately if the combined result is surprising.
/etc/phpmyadmin/config.inc.php
Is the persistent configuration boundary changed by this step. Keep an attributable backup and validate the consumer before reload.
File /etc/phpmyadmin/config.inc.php
Configuration
sudoedit /etc/phpmyadmin/config.inc.php; sudo grep -nE "verbose|host|port|auth_type|ssl_verify" /etc/phpmyadmin/config.inc.php
Example output / evidence
Only approved servers are present and every remote target verifies TLS.

Checkpoint: Checkpoint: Define each approved server explicitly

Continue whenOnly approved servers are present and every remote target verifies TLS. Treat this concrete evidence as the minimum success signal and also confirm that unrelated services and the previous healthy path remain unchanged.

Stop whenStop before the next step when sudoedit reports an error, the output differs materially from the example, an unexpected package/service/path is affected, or the required before-state and rollback artifact are missing.

If this step fails

The command for “Define each approved server explicitly” fails, produces no useful evidence, or the expected service/configuration state is absent.

Likely causeA placeholder targets the wrong environment, the installed version uses another path or unit name, permissions are insufficient, or an earlier prerequisite was not satisfied.

Safe checks
  • command -v sudoedit 2>/dev/null || true
  • systemctl --failed --no-pager 2>/dev/null || true
  • journalctl -p warning -n 50 --no-pager 2>/dev/null || true

ResolutionDo not improvise a privileged workaround. Re-read the environment and variable table, inspect the official source for the installed version, restore the candidate file if necessary, and repeat only this checkpoint.

Security notes

  • Keep secrets out of shell history, process arguments, screenshots, logs, and tutorial placeholders. Elevate only the narrow command that requires it and preserve package signature and TLS verification.

Alternatives

  • When the host layout or software version differs, use the vendor-supported equivalent in a disposable staging environment and document the mapping before touching production.

Stop conditions

  • Stop if the action broadens network exposure, permissions, package sources, writable paths, or service privileges beyond the tutorial's declared architecture.
04

config

Disable arbitrary server selection

caution

Keep AllowArbitraryServer false and do not accept a user-supplied host parameter; network egress should also allow only approved database targets.

Why this step matters

Disable arbitrary server selection is a separate checkpoint because it establishes one auditable part of provide one controlled administration portal for approved databases without allowing users to redirect it to arbitrary hosts. Performing it independently keeps a failed prerequisite, syntax error, or compatibility mismatch from being hidden by later actions.

What to understand

Keep AllowArbitraryServer false and do not accept a user-supplied host parameter; network egress should also allow only approved database targets. Read the complete command or configuration before execution, replace the documented placeholders, and compare the target host with the supported environments listed at the beginning of this tutorial.

Capture the before-state and the exact output in the change record. If this step modifies a file or service, validate the candidate with its native checker before any reload; a successful process exit alone does not prove that the application uses the intended value.

Use a representative staging or canary host first. Repeat the stated checkpoint immediately, because proceeding with ambiguous evidence makes the later end-to-end verification and rollback materially harder.

System changes

  • This step may affect the files, packages, identities, services, or runtime policy named in “Disable arbitrary server selection”. The scope must remain limited to the selected application and supported host.

Syntax explained

grep
Invokes the principal tool or configuration operation for “Disable arbitrary server selection”; confirm that it resolves to the expected packaged executable or file before using elevated privileges.
|
Passes standard output to the next read-only inspection stage; review each stage separately if the combined result is surprising.
configuration file
Is the persistent configuration boundary changed by this step. Keep an attributable backup and validate the consumer before reload.
Configuration
sudo grep -n 'AllowArbitraryServer' /etc/phpmyadmin/config.inc.php; sudo nft list ruleset 2>/dev/null | grep -n 3306 || true
Example output / evidence
Arbitrary server selection is disabled and egress is bounded.

Checkpoint: Checkpoint: Disable arbitrary server selection

Continue whenArbitrary server selection is disabled and egress is bounded. Treat this concrete evidence as the minimum success signal and also confirm that unrelated services and the previous healthy path remain unchanged.

Stop whenStop before the next step when grep reports an error, the output differs materially from the example, an unexpected package/service/path is affected, or the required before-state and rollback artifact are missing.

If this step fails

The command for “Disable arbitrary server selection” fails, produces no useful evidence, or the expected service/configuration state is absent.

Likely causeA placeholder targets the wrong environment, the installed version uses another path or unit name, permissions are insufficient, or an earlier prerequisite was not satisfied.

Safe checks
  • command -v grep 2>/dev/null || true
  • systemctl --failed --no-pager 2>/dev/null || true
  • journalctl -p warning -n 50 --no-pager 2>/dev/null || true

ResolutionDo not improvise a privileged workaround. Re-read the environment and variable table, inspect the official source for the installed version, restore the candidate file if necessary, and repeat only this checkpoint.

Security notes

  • Keep secrets out of shell history, process arguments, screenshots, logs, and tutorial placeholders. Elevate only the narrow command that requires it and preserve package signature and TLS verification.

Alternatives

  • When the host layout or software version differs, use the vendor-supported equivalent in a disposable staging environment and document the mapping before touching production.

Stop conditions

  • Stop if the action broadens network exposure, permissions, package sources, writable paths, or service privileges beyond the tutorial's declared architecture.
05

command

Create a least-privilege configuration-storage account

caution

Import phpMyAdmin's official storage schema and grant the control user only required privileges on that schema from the phpMyAdmin host.

Why this step matters

Create a least-privilege configuration-storage account is a separate checkpoint because it establishes one auditable part of provide one controlled administration portal for approved databases without allowing users to redirect it to arbitrary hosts. Performing it independently keeps a failed prerequisite, syntax error, or compatibility mismatch from being hidden by later actions.

What to understand

Import phpMyAdmin's official storage schema and grant the control user only required privileges on that schema from the phpMyAdmin host. Read the complete command or configuration before execution, replace the documented placeholders, and compare the target host with the supported environments listed at the beginning of this tutorial.

Capture the before-state and the exact output in the change record. If this step modifies a file or service, validate the candidate with its native checker before any reload; a successful process exit alone does not prove that the application uses the intended value.

Use a representative staging or canary host first. Repeat the stated checkpoint immediately, because proceeding with ambiguous evidence makes the later end-to-end verification and rollback materially harder.

System changes

  • This step may affect the files, packages, identities, services, or runtime policy named in “Create a least-privilege configuration-storage account”. The scope must remain limited to the selected application and supported host.

Syntax explained

mysql
Invokes the principal tool or configuration operation for “Create a least-privilege configuration-storage account”; confirm that it resolves to the expected packaged executable or file before using elevated privileges.
{{…}}
Marks an operator-supplied value. Replace every placeholder deliberately; do not paste untrusted text or leave braces in the production command.
Command
Fill variables0/2 ready

Values stay on this page and are never sent or saved.

mysql --host={{controlHost}} --ssl-mode=VERIFY_IDENTITY --ssl-ca={{caFile}} < /usr/share/phpmyadmin/sql/create_tables.sql; mysql --host={{controlHost}} --ssl-mode=VERIFY_IDENTITY --ssl-ca={{caFile}}
Example output / evidence
The control database exists and the host-scoped control user has only its schema privileges.

Checkpoint: Checkpoint: Create a least-privilege configuration-storage account

Continue whenThe control database exists and the host-scoped control user has only its schema privileges. Treat this concrete evidence as the minimum success signal and also confirm that unrelated services and the previous healthy path remain unchanged.

Stop whenStop before the next step when mysql reports an error, the output differs materially from the example, an unexpected package/service/path is affected, or the required before-state and rollback artifact are missing.

If this step fails

The command for “Create a least-privilege configuration-storage account” fails, produces no useful evidence, or the expected service/configuration state is absent.

Likely causeA placeholder targets the wrong environment, the installed version uses another path or unit name, permissions are insufficient, or an earlier prerequisite was not satisfied.

Safe checks
  • command -v mysql 2>/dev/null || true
  • systemctl --failed --no-pager 2>/dev/null || true
  • journalctl -p warning -n 50 --no-pager 2>/dev/null || true

ResolutionDo not improvise a privileged workaround. Re-read the environment and variable table, inspect the official source for the installed version, restore the candidate file if necessary, and repeat only this checkpoint.

Security notes

  • Keep secrets out of shell history, process arguments, screenshots, logs, and tutorial placeholders. Elevate only the narrow command that requires it and preserve package signature and TLS verification.

Alternatives

  • When the host layout or software version differs, use the vendor-supported equivalent in a disposable staging environment and document the mapping before touching production.

Stop conditions

  • Stop if the action broadens network exposure, permissions, package sources, writable paths, or service privileges beyond the tutorial's declared architecture.
06

config

Connect configuration storage without exposing secrets

caution

Reference controlhost, controlport, controluser, controlpass, pmadb, and table names from a root-protected configuration include or supported secret injection.

Why this step matters

Connect configuration storage without exposing secrets is a separate checkpoint because it establishes one auditable part of provide one controlled administration portal for approved databases without allowing users to redirect it to arbitrary hosts. Performing it independently keeps a failed prerequisite, syntax error, or compatibility mismatch from being hidden by later actions.

What to understand

Reference controlhost, controlport, controluser, controlpass, pmadb, and table names from a root-protected configuration include or supported secret injection. Read the complete command or configuration before execution, replace the documented placeholders, and compare the target host with the supported environments listed at the beginning of this tutorial.

Capture the before-state and the exact output in the change record. If this step modifies a file or service, validate the candidate with its native checker before any reload; a successful process exit alone does not prove that the application uses the intended value.

Use a representative staging or canary host first. Repeat the stated checkpoint immediately, because proceeding with ambiguous evidence makes the later end-to-end verification and rollback materially harder.

System changes

  • This step may affect the files, packages, identities, services, or runtime policy named in “Connect configuration storage without exposing secrets”. The scope must remain limited to the selected application and supported host.

Syntax explained

grep
Invokes the principal tool or configuration operation for “Connect configuration storage without exposing secrets”; confirm that it resolves to the expected packaged executable or file before using elevated privileges.
|
Passes standard output to the next read-only inspection stage; review each stage separately if the combined result is surprising.
configuration file
Is the persistent configuration boundary changed by this step. Keep an attributable backup and validate the consumer before reload.
Configuration
sudo grep -nE "controlhost|controluser|pmadb|userconfig|usergroups" /etc/phpmyadmin/config.inc.php
Example output / evidence
Configuration storage is enabled with protected credentials.

Checkpoint: Checkpoint: Connect configuration storage without exposing secrets

Continue whenConfiguration storage is enabled with protected credentials. Treat this concrete evidence as the minimum success signal and also confirm that unrelated services and the previous healthy path remain unchanged.

Stop whenStop before the next step when grep reports an error, the output differs materially from the example, an unexpected package/service/path is affected, or the required before-state and rollback artifact are missing.

If this step fails

The command for “Connect configuration storage without exposing secrets” fails, produces no useful evidence, or the expected service/configuration state is absent.

Likely causeA placeholder targets the wrong environment, the installed version uses another path or unit name, permissions are insufficient, or an earlier prerequisite was not satisfied.

Safe checks
  • command -v grep 2>/dev/null || true
  • systemctl --failed --no-pager 2>/dev/null || true
  • journalctl -p warning -n 50 --no-pager 2>/dev/null || true

ResolutionDo not improvise a privileged workaround. Re-read the environment and variable table, inspect the official source for the installed version, restore the candidate file if necessary, and repeat only this checkpoint.

Security notes

  • Keep secrets out of shell history, process arguments, screenshots, logs, and tutorial placeholders. Elevate only the narrow command that requires it and preserve package signature and TLS verification.

Alternatives

  • When the host layout or software version differs, use the vendor-supported equivalent in a disposable staging environment and document the mapping before touching production.

Stop conditions

  • Stop if the action broadens network exposure, permissions, package sources, writable paths, or service privileges beyond the tutorial's declared architecture.
07

config

Enable and enroll two-factor authentication

caution

Enable 2FA through phpMyAdmin configuration storage, enroll administrators with TOTP or approved WebAuthn where supported, and store recovery codes outside the portal.

Why this step matters

Enable and enroll two-factor authentication is a separate checkpoint because it establishes one auditable part of provide one controlled administration portal for approved databases without allowing users to redirect it to arbitrary hosts. Performing it independently keeps a failed prerequisite, syntax error, or compatibility mismatch from being hidden by later actions.

What to understand

Enable 2FA through phpMyAdmin configuration storage, enroll administrators with TOTP or approved WebAuthn where supported, and store recovery codes outside the portal. Read the complete command or configuration before execution, replace the documented placeholders, and compare the target host with the supported environments listed at the beginning of this tutorial.

Capture the before-state and the exact output in the change record. If this step modifies a file or service, validate the candidate with its native checker before any reload; a successful process exit alone does not prove that the application uses the intended value.

Use a representative staging or canary host first. Repeat the stated checkpoint immediately, because proceeding with ambiguous evidence makes the later end-to-end verification and rollback materially harder.

System changes

  • This step may affect the files, packages, identities, services, or runtime policy named in “Enable and enroll two-factor authentication”. The scope must remain limited to the selected application and supported host.

Syntax explained

grep
Invokes the principal tool or configuration operation for “Enable and enroll two-factor authentication”; confirm that it resolves to the expected packaged executable or file before using elevated privileges.
{{…}}
Marks an operator-supplied value. Replace every placeholder deliberately; do not paste untrusted text or leave braces in the production command.
|
Passes standard output to the next read-only inspection stage; review each stage separately if the combined result is surprising.
configuration file
Is the persistent configuration boundary changed by this step. Keep an attributable backup and validate the consumer before reload.
Configuration
Fill variables0/1 ready

Values stay on this page and are never sent or saved.

sudo grep -nE 'TwoFactor|2fa|userconfig' /etc/phpmyadmin/config.inc.php; sudo systemctl reload php{{phpVersion}}-fpm
Example output / evidence
Enrolled administrators are prompted for a second factor.

Checkpoint: Checkpoint: Enable and enroll two-factor authentication

Continue whenEnrolled administrators are prompted for a second factor. Treat this concrete evidence as the minimum success signal and also confirm that unrelated services and the previous healthy path remain unchanged.

Stop whenStop before the next step when grep reports an error, the output differs materially from the example, an unexpected package/service/path is affected, or the required before-state and rollback artifact are missing.

If this step fails

The command for “Enable and enroll two-factor authentication” fails, produces no useful evidence, or the expected service/configuration state is absent.

Likely causeA placeholder targets the wrong environment, the installed version uses another path or unit name, permissions are insufficient, or an earlier prerequisite was not satisfied.

Safe checks
  • command -v grep 2>/dev/null || true
  • systemctl --failed --no-pager 2>/dev/null || true
  • journalctl -p warning -n 50 --no-pager 2>/dev/null || true

ResolutionDo not improvise a privileged workaround. Re-read the environment and variable table, inspect the official source for the installed version, restore the candidate file if necessary, and repeat only this checkpoint.

Security notes

  • Keep secrets out of shell history, process arguments, screenshots, logs, and tutorial placeholders. Elevate only the narrow command that requires it and preserve package signature and TLS verification.

Alternatives

  • When the host layout or software version differs, use the vendor-supported equivalent in a disposable staging environment and document the mapping before touching production.

Stop conditions

  • Stop if the action broadens network exposure, permissions, package sources, writable paths, or service privileges beyond the tutorial's declared architecture.
08

verification

Test target selection and fail-closed behavior

read-only

Verify correct TLS connections to every server, reject wrong CA or hostname, reject arbitrary host parameters, require 2FA, and confirm control-user outage does not grant access.

Why this step matters

Test target selection and fail-closed behavior is a separate checkpoint because it establishes one auditable part of provide one controlled administration portal for approved databases without allowing users to redirect it to arbitrary hosts. Performing it independently keeps a failed prerequisite, syntax error, or compatibility mismatch from being hidden by later actions.

What to understand

Verify correct TLS connections to every server, reject wrong CA or hostname, reject arbitrary host parameters, require 2FA, and confirm control-user outage does not grant access. Read the complete command or configuration before execution, replace the documented placeholders, and compare the target host with the supported environments listed at the beginning of this tutorial.

Capture the before-state and the exact output in the change record. If this step modifies a file or service, validate the candidate with its native checker before any reload; a successful process exit alone does not prove that the application uses the intended value.

Use a representative staging or canary host first. Repeat the stated checkpoint immediately, because proceeding with ambiguous evidence makes the later end-to-end verification and rollback materially harder.

System changes

  • This step may affect the files, packages, identities, services, or runtime policy named in “Test target selection and fail-closed behavior”. The scope must remain limited to the selected application and supported host.

Syntax explained

curl
Invokes the principal tool or configuration operation for “Test target selection and fail-closed behavior”; confirm that it resolves to the expected packaged executable or file before using elevated privileges.
{{…}}
Marks an operator-supplied value. Replace every placeholder deliberately; do not paste untrusted text or leave braces in the production command.
Command
Fill variables0/3 ready

Values stay on this page and are never sent or saved.

curl --fail --silent --user {{outerUser}} https://{{adminDomain}}/ >/dev/null; sudo tail -n 100 {{pmaErrorLog}}
Example output / evidence
Approved targets work; invalid TLS, arbitrary hosts, and missing second factor are rejected.

Checkpoint: Checkpoint: Test target selection and fail-closed behavior

Continue whenApproved targets work; invalid TLS, arbitrary hosts, and missing second factor are rejected. Treat this concrete evidence as the minimum success signal and also confirm that unrelated services and the previous healthy path remain unchanged.

Stop whenStop before the next step when curl reports an error, the output differs materially from the example, an unexpected package/service/path is affected, or the required before-state and rollback artifact are missing.

If this step fails

The command for “Test target selection and fail-closed behavior” fails, produces no useful evidence, or the expected service/configuration state is absent.

Likely causeA placeholder targets the wrong environment, the installed version uses another path or unit name, permissions are insufficient, or an earlier prerequisite was not satisfied.

Safe checks
  • command -v curl 2>/dev/null || true
  • systemctl --failed --no-pager 2>/dev/null || true
  • journalctl -p warning -n 50 --no-pager 2>/dev/null || true

ResolutionDo not improvise a privileged workaround. Re-read the environment and variable table, inspect the official source for the installed version, restore the candidate file if necessary, and repeat only this checkpoint.

Security notes

  • Keep secrets out of shell history, process arguments, screenshots, logs, and tutorial placeholders. Elevate only the narrow command that requires it and preserve package signature and TLS verification.

Alternatives

  • When the host layout or software version differs, use the vendor-supported equivalent in a disposable staging environment and document the mapping before touching production.

Stop conditions

  • Stop if the action broadens network exposure, permissions, package sources, writable paths, or service privileges beyond the tutorial's declared architecture.

Finish line

Verification checklist

Configuration policyphp -l /etc/phpmyadmin/config.inc.php && grep -n "AllowArbitraryServer.*false" /etc/phpmyadmin/config.inc.phpPHP syntax succeeds and arbitrary server access is explicitly false.
Two-factor enforcementcat {{twoFactorEnrollmentReport}}Every privileged portal user has an enrolled second factor and protected recovery procedure.

Recovery guidance

Common problems and safe checks

The native client reports access denied even though a similarly named account has grants.

Likely causeDatabase identities include a host component and authentication plugin; the connection matched another user@host row or transport.

Safe checks
  • mysql -e 'SELECT USER(), CURRENT_USER();'
  • mysql -e "SELECT User,Host,plugin FROM mysql.user ORDER BY User,Host;"
  • mysql -e 'SHOW GRANTS FOR CURRENT_USER;'

ResolutionIdentify the exact matched account and create or modify only the intended user@host identity; do not broaden it to '%' as a shortcut.

TLS is enabled but the client still connects with an unexpected identity or without hostname verification.

Likely causeThe client uses encryption-only mode, connects by an address absent from the SAN, trusts a broad system CA set, or another option file overrides policy.

Safe checks
  • mysql --print-defaults
  • openssl s_client -starttls mysql -connect db.example.com:3306 -servername db.example.com </dev/null
  • mysql -e "SHOW STATUS LIKE 'Ssl_%';"

ResolutionUse the documented hostname, intended CA and VERIFY_IDENTITY-equivalent mode; remove conflicting client options and retest expected failure with a wrong hostname.

A change passes syntax checks but application errors, lag, latency or disk use increases.

Likely causeThe candidate is syntactically valid but workload, lock, cache, rotation, privilege or version assumptions are wrong.

Safe checks
  • mysqladmin ping
  • mysql -e 'SHOW PROCESSLIST;'
  • journalctl -u mariadb -u mysql -p warning --since '-10 min' --no-pager

ResolutionStop promotion, preserve evidence, revert the smallest changed configuration/account/routing layer and reproduce with a safe representative workload.

After the procedure

Alternatives and next steps

Consider these alternatives

  • Use a managed database only after private connectivity, identity, encryption, monitoring, backup restoration and responsibility boundaries are proven.
  • Use immutable configuration automation and a disposable recovery environment when it produces stronger review, repeatability and rollback than manual host edits.

Operate it safely

  • Automate health, capacity, certificate, replication, backup and restore-test alerts with an owner and response runbook.
  • Review accounts, grants, package support, encryption material and recovery evidence after every major release and at least every 90–180 days.
  • Practice the rollback or restore from recorded artifacts on an isolated host so the documented time and dependencies remain credible.

Reference

Frequently asked questions

Does a successful command mean the procedure is complete?

No. Database tools may return success before application compatibility, replica replay, restore integrity, TLS identity or expected denials are proven. Use every checkpoint and final verification.

Can an administrator use the application account for convenience?

No. Separate identities make least privilege, rotation, audit and incident containment possible; the application should not hold administrative capabilities.

Why test restoration or negative access separately?

A backup that cannot restore and a grant that was never tested for denial are assumptions, not controls. Isolation makes those tests safe and repeatable.

Recovery

Rollback

Restore the prior phpMyAdmin configuration and control database while retaining the external access gate.

  1. Restore config.inc.php and the prior configuration-storage database, validate PHP, and reload FPM.
  2. Do not disable the web-server authentication or network allowlist during 2FA rollback.
  3. Revoke the new control user only after the restored version no longer uses it.

Evidence

Sources and review

Verified 2026-07-25Review due 2026-10-23
phpMyAdmin configurationofficialphpMyAdmin two-factor authenticationofficialphpMyAdmin security policyofficialphpMyAdmin setupofficial