Install and secure phpMyAdmin behind nginx and PHP-FPM
Deploy phpMyAdmin on an isolated FPM pool, protect it with network and HTTP authentication, verify database TLS, deny unsafe paths, and validate updates.
Expose phpMyAdmin only through a controlled management endpoint with separate runtime and access boundaries.
- phpMyAdmin 5.2
- 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
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
- A production-ready phpMyAdmin with MySQL/MariaDB implementation of “Install and secure phpMyAdmin behind nginx and PHP-FPM” 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.
- Expose phpMyAdmin only through a controlled management endpoint with separate runtime and access boundaries. 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.
- Capture effective configuration, versions, listeners, identities, grants, workload health and a recoverable before-state.
- Prepare the phpmyadmin candidate using only official phpMyAdmin with MySQL/MariaDB interfaces, protected secret delivery and the narrowest necessary scope.
- Apply one controlled layer at a time, run the immediate checkpoint and inspect native logs/status before proceeding.
- 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{{adminUser}}Operator-reviewed value used by this tutorial for adminUser; derive it from the target environment and never from untrusted request data.
Example: alice{{phpVersion}}Exact PHP major and minor branch used by the target runtime.
Example: 8.3{{pmaGroup}}Operator-reviewed value used by this tutorial for pmaGroup; derive it from the target environment and never from untrusted request data.
Example: phpmyadmin{{pmaUser}}Operator-reviewed value used by this tutorial for pmaUser; derive it from the target environment and never from untrusted request data.
Example: phpmyadminSecurity 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.
instruction
Define management-only reachability
Choose VPN or allowlisted networks, an admin hostname, TLS identity, database endpoints, and a recovery path that does not depend on phpMyAdmin.
Why this step matters
Define management-only reachability is a separate checkpoint because it establishes one auditable part of expose phpmyadmin only through a controlled management endpoint with separate runtime and access boundaries. Performing it independently keeps a failed prerequisite, syntax error, or compatibility mismatch from being hidden by later actions.
What to understand
Choose VPN or allowlisted networks, an admin hostname, TLS identity, database endpoints, and a recovery path that does not depend on phpMyAdmin. 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 management-only reachability”. The scope must remain limited to the selected application and supported host.
Syntax explained
getent- Invokes the principal tool or configuration operation for “Define management-only reachability”; 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.
Values stay on this page and are never sent or saved.
getent ahosts {{adminDomain}}; sudo nginx -T | grep -n 'server_name'; sudo ss -lntpHostname, client networks, and existing nginx mappings are recorded.
Checkpoint: Checkpoint: Define management-only reachability
Continue whenHostname, client networks, and existing nginx mappings are recorded. 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 getent 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 management-only reachability” 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.
command -v getent 2>/dev/null || truesystemctl --failed --no-pager 2>/dev/null || truejournalctl -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.
command
Install phpMyAdmin and required PHP extensions
Use a distribution package or verified upstream release and record the exact version for update monitoring.
Why this step matters
Install phpMyAdmin and required PHP extensions is a separate checkpoint because it establishes one auditable part of expose phpmyadmin only through a controlled management endpoint with separate runtime and access boundaries. Performing it independently keeps a failed prerequisite, syntax error, or compatibility mismatch from being hidden by later actions.
What to understand
Use a distribution package or verified upstream release and record the exact version for update monitoring. 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 “Install phpMyAdmin and required PHP extensions”. The scope must remain limited to the selected application and supported host.
Syntax explained
apt- Invokes the principal tool or configuration operation for “Install phpMyAdmin and required PHP extensions”; confirm that it resolves to the expected packaged executable or file before using elevated privileges.
&&- Runs the following operation only when the previous command succeeds, preventing a reload or state transition after a failed validation.
sudo apt update && sudo apt install --yes phpmyadmin php-fpm php-mbstring php-zip php-gd php-curlphpMyAdmin and matching PHP dependencies install.
Checkpoint: Checkpoint: Install phpMyAdmin and required PHP extensions
Continue whenphpMyAdmin and matching PHP dependencies install. 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 apt 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 “Install phpMyAdmin and required PHP extensions” 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.
command -v apt 2>/dev/null || truesystemctl --failed --no-pager 2>/dev/null || truejournalctl -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.
config
Create an isolated phpMyAdmin FPM pool
Run under a dedicated non-login identity with a private socket, bounded workers, private sessions/temp, error log, and no application secrets in environment variables.
Why this step matters
Create an isolated phpMyAdmin FPM pool is a separate checkpoint because it establishes one auditable part of expose phpmyadmin only through a controlled management endpoint with separate runtime and access boundaries. Performing it independently keeps a failed prerequisite, syntax error, or compatibility mismatch from being hidden by later actions.
What to understand
Run under a dedicated non-login identity with a private socket, bounded workers, private sessions/temp, error log, and no application secrets in environment variables. 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 an isolated phpMyAdmin FPM pool”. The scope must remain limited to the selected application and supported host.
Syntax explained
sudoedit- Invokes the principal tool or configuration operation for “Create an isolated phpMyAdmin FPM pool”; 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.
/etc/php/{{phpVersion}}/fpm/pool.d/phpmyadmin.conf- Is the persistent configuration boundary changed by this step. Keep an attributable backup and validate the consumer before reload.
/etc/php/{{phpVersion}}/fpm/pool.d/phpmyadmin.confValues stay on this page and are never sent or saved.
sudoedit /etc/php/{{phpVersion}}/fpm/pool.d/phpmyadmin.conf; sudo php-fpm{{phpVersion}} -ttThe pool validates and exposes a unique Unix socket.
Checkpoint: Checkpoint: Create an isolated phpMyAdmin FPM pool
Continue whenThe pool validates and exposes a unique Unix socket. 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 “Create an isolated phpMyAdmin FPM pool” 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.
command -v sudoedit 2>/dev/null || truesystemctl --failed --no-pager 2>/dev/null || truejournalctl -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.
config
Protect phpMyAdmin configuration and database TLS
Set a strong blowfish_secret, temp directory, explicit servers, and CA-verified TLS; keep config.inc.php unreadable to other users.
Why this step matters
Protect phpMyAdmin configuration and database TLS is a separate checkpoint because it establishes one auditable part of expose phpmyadmin only through a controlled management endpoint with separate runtime and access boundaries. Performing it independently keeps a failed prerequisite, syntax error, or compatibility mismatch from being hidden by later actions.
What to understand
Set a strong blowfish_secret, temp directory, explicit servers, and CA-verified TLS; keep config.inc.php unreadable to other users. 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 “Protect phpMyAdmin configuration and database TLS”. The scope must remain limited to the selected application and supported host.
Syntax explained
install- Invokes the principal tool or configuration operation for “Protect phpMyAdmin configuration and database TLS”; 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.
/etc/phpmyadmin/config.inc.php- Is the persistent configuration boundary changed by this step. Keep an attributable backup and validate the consumer before reload.
/etc/phpmyadmin/config.inc.phpValues stay on this page and are never sent or saved.
sudo install -d -o {{pmaUser}} -g {{pmaGroup}} -m 0700 /var/lib/phpmyadmin/tmp; sudoedit /etc/phpmyadmin/config.inc.php; sudo chmod 0640 /etc/phpmyadmin/config.inc.phpConfiguration is protected and remote database certificates are verified.
Checkpoint: Checkpoint: Protect phpMyAdmin configuration and database TLS
Continue whenConfiguration is protected and remote database certificates are verified. 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 install 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 “Protect phpMyAdmin configuration and database TLS” 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.
command -v install 2>/dev/null || truesystemctl --failed --no-pager 2>/dev/null || truejournalctl -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.
config
Create a strict nginx server block
Set an exact server_name, TLS-only listener, root or alias, try_files, versioned FastCGI socket, and deny dotfiles, setup, vendor, templates, libraries, and writable paths.
Why this step matters
Create a strict nginx server block is a separate checkpoint because it establishes one auditable part of expose phpmyadmin only through a controlled management endpoint with separate runtime and access boundaries. Performing it independently keeps a failed prerequisite, syntax error, or compatibility mismatch from being hidden by later actions.
What to understand
Set an exact server_name, TLS-only listener, root or alias, try_files, versioned FastCGI socket, and deny dotfiles, setup, vendor, templates, libraries, and writable paths. 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 strict nginx server block”. The scope must remain limited to the selected application and supported host.
Syntax explained
sudoedit- Invokes the principal tool or configuration operation for “Create a strict nginx server block”; 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.
/etc/nginx/sites-available/{{adminDomain}}- Is the persistent configuration boundary changed by this step. Keep an attributable backup and validate the consumer before reload.
/etc/nginx/sites-available/{{adminDomain}}Values stay on this page and are never sent or saved.
sudoedit /etc/nginx/sites-available/{{adminDomain}}; sudo ln -s /etc/nginx/sites-available/{{adminDomain}} /etc/nginx/sites-enabled/{{adminDomain}}; sudo nginx -tThe server block validates and only intended PHP entry points execute.
Checkpoint: Checkpoint: Create a strict nginx server block
Continue whenThe server block validates and only intended PHP entry points execute. 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 “Create a strict nginx server block” 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.
command -v sudoedit 2>/dev/null || truesystemctl --failed --no-pager 2>/dev/null || truejournalctl -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.
config
Apply network allowlist and HTTP authentication
Use allow/deny for management networks plus auth_basic or an identity proxy; neither replaces phpMyAdmin database authentication.
Why this step matters
Apply network allowlist and HTTP authentication is a separate checkpoint because it establishes one auditable part of expose phpmyadmin only through a controlled management endpoint with separate runtime and access boundaries. Performing it independently keeps a failed prerequisite, syntax error, or compatibility mismatch from being hidden by later actions.
What to understand
Use allow/deny for management networks plus auth_basic or an identity proxy; neither replaces phpMyAdmin database authentication. 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 “Apply network allowlist and HTTP authentication”. The scope must remain limited to the selected application and supported host.
Syntax explained
htpasswd- Invokes the principal tool or configuration operation for “Apply network allowlist and HTTP 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.
Values stay on this page and are never sent or saved.
sudo htpasswd -c /etc/nginx/phpmyadmin.htpasswd {{adminUser}}; sudo chmod 0640 /etc/nginx/phpmyadmin.htpasswd; sudo grep -nE 'allow|deny|auth_basic' /etc/nginx/sites-available/{{adminDomain}}Both network and identity gates are configured.
Checkpoint: Checkpoint: Apply network allowlist and HTTP authentication
Continue whenBoth network and identity gates are configured. 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 htpasswd 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 “Apply network allowlist and HTTP 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.
command -v htpasswd 2>/dev/null || truesystemctl --failed --no-pager 2>/dev/null || truejournalctl -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.
command
Issue HTTPS and reload safely
Issue a valid certificate, configure redirect and defensive headers, test nginx and FPM, then reload both services.
Why this step matters
Issue HTTPS and reload safely is a separate checkpoint because it establishes one auditable part of expose phpmyadmin only through a controlled management endpoint with separate runtime and access boundaries. Performing it independently keeps a failed prerequisite, syntax error, or compatibility mismatch from being hidden by later actions.
What to understand
Issue a valid certificate, configure redirect and defensive headers, test nginx and FPM, then reload both services. 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 “Issue HTTPS and reload safely”. The scope must remain limited to the selected application and supported host.
Syntax explained
certbot- Invokes the principal tool or configuration operation for “Issue HTTPS and reload safely”; 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.
Values stay on this page and are never sent or saved.
sudo certbot --nginx -d {{adminDomain}} --redirect; sudo nginx -t; sudo php-fpm{{phpVersion}} -tt; sudo systemctl reload php{{phpVersion}}-fpm nginxCertificate issuance succeeds and both services remain active.
Checkpoint: Checkpoint: Issue HTTPS and reload safely
Continue whenCertificate issuance succeeds and both services remain active. 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 certbot 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 “Issue HTTPS and reload safely” 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.
command -v certbot 2>/dev/null || truesystemctl --failed --no-pager 2>/dev/null || truejournalctl -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.
verification
Test all security boundaries
Verify external denial, authentication challenge, allowed management access, database TLS, forbidden static paths, upload limits, logs, and restart survival.
Why this step matters
Test all security boundaries is a separate checkpoint because it establishes one auditable part of expose phpmyadmin only through a controlled management endpoint with separate runtime and access boundaries. Performing it independently keeps a failed prerequisite, syntax error, or compatibility mismatch from being hidden by later actions.
What to understand
Verify external denial, authentication challenge, allowed management access, database TLS, forbidden static paths, upload limits, logs, and restart survival. 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 all security boundaries”. The scope must remain limited to the selected application and supported host.
Syntax explained
curl- Invokes the principal tool or configuration operation for “Test all security boundaries”; 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.
Values stay on this page and are never sent or saved.
curl --head https://{{adminDomain}}/; curl --user {{adminUser}} --head https://{{adminDomain}}/; sudo tail -n 50 /var/log/nginx/{{adminDomain}}-error.logOnly authenticated management clients reach the application and unsafe paths remain denied.
Checkpoint: Checkpoint: Test all security boundaries
Continue whenOnly authenticated management clients reach the application and unsafe paths remain denied. 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 all security boundaries” 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.
command -v curl 2>/dev/null || truesystemctl --failed --no-pager 2>/dev/null || truejournalctl -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
for p in setup vendor templates libraries .git; do curl -s -o /dev/null -w "$p=%{http_code}\n" https://{{adminDomain}}/$p/; doneEvery internal or setup path returns 403 or 404.sudo systemctl restart php{{phpVersion}}-fpm nginx && curl --user {{adminUser}} --fail --silent https://{{adminDomain}}/ >/dev/nullServices restart and authorized access succeeds.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.
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.
mysql --print-defaultsopenssl s_client -starttls mysql -connect db.example.com:3306 -servername db.example.com </dev/nullmysql -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.
mysqladmin pingmysql -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.
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
Disable the nginx server block and isolated FPM pool while preserving protected configuration for recovery.
- Remove the enabled server-block symlink, validate nginx, and reload.
- Disable the phpMyAdmin pool, validate FPM, and reload after no site references its socket.
- Keep configuration and database accounts until the alternate administration path is proven.
Evidence