Skip to content
This repository was archived by the owner on Oct 10, 2025. It is now read-only.

Latest commit

 

History

History
77 lines (53 loc) · 2.52 KB

File metadata and controls

77 lines (53 loc) · 2.52 KB

MySQL password in DSN must be URL-encoded (or use URL-safe secrets)

Summary

When configuring the tracker database via a MySQL DSN (for example mysql://user:password@host:3306/db), any reserved URL characters in the password (notably + and /) must be percent-encoded. Otherwise, the DSN may be parsed incorrectly and the tracker will fail to connect to MySQL.

Context in this repository

  • Our application/compose.yaml sets the tracker DSN using environment variables.

  • The DSN is constructed like:

    TORRUST_TRACKER_CONFIG_OVERRIDE_CORE__DATABASE__PATH=
      mysql://${MYSQL_USER}:${MYSQL_PASSWORD}@mysql:3306/${MYSQL_DATABASE}
    
  • If MYSQL_PASSWORD contains reserved characters, the DSN becomes invalid unless the password is URL-encoded first.

  • Resolution applied here: we use URL-safe secrets (alphanumeric plus - and _) in environment files where credentials are embedded in URLs.

Why this happens

The database URL is a standard URI. The password component follows URL-encoding rules. Characters like +, /, @, :, #, ?, &, and % are reserved in URLs and must be percent-encoded inside credentials to avoid ambiguity.

Symptoms

  • Tracker fails to start or cannot connect to MySQL
  • MySQL auth errors despite correct credentials
  • Logs may show DSN/parse or auth failures

Workarounds

  1. Prefer URL-safe secrets for DSN credentials

    • Generate secrets using only unreserved/URL-safe chars (for example A-Za-z0-9_-).
    # 48-char URL-safe secret
    openssl rand -base64 48 | tr '+/' '-_' | tr -d '=' | cut -c1-48
  2. Percent-encode the password for use in the DSN

    • Encode once before injecting into the DSN:
    python3 - << 'PY'
    from urllib.parse import quote
    pw = input().strip()
    print(quote(pw, safe=''))
    PY
    • Then set MYSQL_PASSWORD_ENC=<encoded> and reference that in the DSN instead of the raw password.

Recommended practice (project-wide)

  • Use URL-safe secrets by default for any credential that will be embedded in URLs/DSNs.
  • If non-URL-safe secrets are required, percent-encode them before constructing the DSN.

Status in staging

  • infrastructure/config/environments/staging-hetzner-staging.env updated to use URL-safe MYSQL_ROOT_PASSWORD and MYSQL_PASSWORD.

Proposed upstream documentation (torrust-tracker)

  • Document that MySQL DSNs require URL-encoding of credentials.
  • Optionally provide examples and/or allow alternative config fields where user/password are provided separately from the DSN.