Mykal Machon

Security Disclosure Recommendation: Rotate MySQL Database Credentials

This guide is part of Railway's response to the security disclosure published on October 21, 2026.

If you use MySQL on Railway, regenerate its password, redeploy every service that uses it, and confirm nothing is still connecting with the old credential.

If your MySQL password or MYSQL_URL may have been exposed, rotate your credentials. This guide applies if your database uses the Railway MySQL template. The fastest path is Regenerate in the Database View, which changes the password inside MySQL and updates the service variables in one step.

Before you rotate

Three checks tell you how exposed the credential is and what you must update afterwards.

  1. Find every consumer. Open the MySQL service's Variables tab. Services that use reference variables such as ${{ MySQL.MYSQL_URL }} pick up the new password on their next deploy. Services with a pasted connection string don't, so note them.
  2. Check public access. Open the MySQL service's Settings and find Networking. If Public Access is enabled, the credential is usable from anywhere through the TCP proxy until you rotate. Remove public access now if nothing outside the project needs it.
  3. List external consumers. Anything that uses MYSQL_PUBLIC_URL (local development, CI, BI tools) needs the new value pasted in by hand.

Regenerate the password

Regenerate is the supported way to change a database password on Railway. It keeps the database and the variables in sync.

  1. Open the MySQL service and click the Database tab, then Config.
  2. In the Connection section, click Regenerate next to the password. Railway changes the password inside MySQL and updates MYSQL_ROOT_PASSWORD. In the template, MYSQLPASSWORD, MYSQL_URL, and MYSQL_PUBLIC_URL reference it, so they change too. See Database View: Connection.
  3. Railway restarts the database to apply the new password, so every open session drops, including any an attacker had open. Your services can't reconnect until you redeploy them in the next section. During an incident, that is the goal.

⚠️ Don't edit MYSQLPASSWORD or MYSQL_ROOT_PASSWORD by hand and don't run ALTER USER yourself. Each changes only one side and leaves the variable and the database out of sync. If that already happened, see how to recover.

Redeploy the services that use it

Containers read variables only at startup, so every service that uses the credential must be redeployed.

  1. Redeploy every service that references the MySQL variables. Regenerate redeploys only the database, so these services keep the old password until you do.
  2. If a service has a pasted connection string, replace it with the reference ${{ MySQL.MYSQL_URL }} so the next rotation reaches it automatically, then deploy.
  3. Optional: redeploy one service from the CLI with railway redeploy.
    railway redeploy --service api
    
  4. Update external consumers with the new MYSQL_PUBLIC_URL.

Verify the rotation

Confirm the new credential works and nothing is still connected with the old one.

  1. Check each dependent service's deploy logs for a successful connection and no Access denied for user errors.
  2. Open the Database tab and confirm the Data view loads tables.
  3. Connect with the new credential using railway connect.
    railway connect MySQL
    
  4. List open sessions. The restart dropped every session from before the rotation, so a session you don't recognize connected with the new password. Find out where it got it.
    SELECT id, user, host, db, command, time, state
    FROM information_schema.processlist;
    
  5. If you find sessions you don't recognize, kill them with KILL <id>;.

Look for misuse

A rotated password stops future access. These checks show whether the old credential was used.

  • Railway audit logs show who viewed or changed variables on the MySQL service and when. Retention depends on your plan.
  • The MySQL service's deploy logs include auth failures. Use the log filter to search for Access denied and for unfamiliar hosts.
  • Inside MySQL, look for accounts you didn't create and for widened privileges.
    SELECT user, host FROM mysql.user;
    SHOW GRANTS FOR 'root'@'%';
    
  • Compare row counts and UPDATE_TIME in information_schema.tables against what you expect.
  • If data was altered, preserve the evidence first, then use point-in-time recovery to restore to a moment before the exposure.

If you have any other questions, contact Railway support at support@railway.com.