The ISPConfig Database Prefix That Broke My WordPress Import

The local WordPress environment was running. The database container was healthy. My credentials came from a working production site.

Then the export failed:

ERROR 1044: Access denied for user ...

The database appeared not to exist under the name I had copied from the WordPress configuration. The credentials were not wrong. I was looking at the wrong layer of the hosting system.

The missing prefix

ISPConfig is designed to manage multiple clients on one server. It prefixes resources so two clients can choose the same friendly database name without colliding.

Conceptually, the server looked like this:

Client 1
  c1socalnomaddb
  c1socalnomadusr

Client 2
  c2clientdb
  c2clientusr

The WordPress configuration and ISPConfig interface did not initially make the distinction obvious to me. I was thinking in terms of the friendly name. MariaDB was enforcing the actual prefixed account and database names.

The useful lesson was simple: when a control panel manages database identities, do not assume the name displayed in one application is the exact server-level name required by every administrative tool.

Finding the authoritative name

There were several ways to verify it.

The safest was ISPConfig itself: open Sites → Databases and inspect the full database and user names.

From the server, an administrator could also list matching databases:

SHOW DATABASES LIKE '%socalnomad%';

The result exposed the c1 prefix.

The ISPConfig filesystem follows a related pattern. A site’s human-readable path may be a symlink:

/var/www/example.com
    -> /var/www/clients/client1/web11

The friendly domain path is easier for humans; the client1/web11 path reflects ISPConfig’s internal ownership model. Database naming follows the same general idea.

Exporting without putting passwords in scripts

My early import script prompted for the production password and interpolated it into a remote shell command. It worked, but embedding passwords in command lines is undesirable: quoting is fragile, and process lists or shell history can expose more than expected.

A better pattern is to use credentials already secured on the server, a restricted defaults file, or WP-CLI under the site’s operating-system account:

ssh user@example-server \
  'wp --path=/var/www/example.com/web db export -' \
  > production.sql

That keeps database credential handling inside WordPress and the server configuration.

The local import remains straightforward:

docker exec -i my-wp-db \
  mariadb -u wpuser -plocal_only_password wordpress_local \
  < production.sql

The production name and the local name do not need to match. The dump contains schema and data; the import target is whichever local database WordPress is configured to use.

Rewriting the site URL

After import, WordPress still believed it lived at the production domain.

Updating only home and siteurl may make the dashboard accessible, but URLs can also appear inside post content, widget settings, and serialized options. WP-CLI is the safer general tool:

docker exec my-wp \
  wp search-replace \
  'https://example.com' \
  'http://localhost:8080' \
  --all-tables \
  --skip-columns=guid

The guid column is normally left unchanged because it is an identifier, not a display URL.

Why the import still was not finished

Once the database loaded, production plugins and settings arrived with it:

  • Security plugins expected production IP addresses and authentication flows.
  • Caching plugins could hide local changes.
  • Email and analytics integrations could accidentally contact external services.
  • Media references still pointed to files that were not part of the database.

A database import is not the same thing as a complete local clone. It is a starting point that needs an environment-specific cleanup pass.

For my setup, that meant:

  1. Confirm the full ISPConfig database identity.
  2. Export through the server’s trusted configuration.
  3. Import into the local MariaDB container.
  4. Rewrite production URLs.
  5. Disable or reconfigure production-only integrations.
  6. Verify the theme against representative content.

Follow The Name Back To Its Owner

The c1 prefix was not an arbitrary obstacle. It was evidence that I was crossing boundaries between three different naming systems:

  • WordPress application configuration
  • ISPConfig’s client-facing resource model
  • MariaDB’s actual server accounts and databases

The import failed because I treated those layers as if they were one.

Once I stopped asking, “Why is this password wrong?” and started asking, “Which system owns this name?”, the problem became much easier to solve.