I recently sat down to write a BASH script to automate my database backups. Everything was going great until I hit a wall: passwords.
We’ve all been there. The easiest thing to do is just slap -p'my_password' right into the command. But if you’ve spent any time in Linux, you know that’s a disaster waiting to happen—anyone running ps -ef on the server can see your password in plain text.
I wanted to do it the right way so I did some digging into best practices, first for MySQL/MariaDB and then for more generic applications. Here is what I found.
MariaDB/MySQL
If you’re specifically dealing with MySQL or MariaDB, you have a few options depending on how paranoid (or professional) you want to be.
Option A: The .my.cnf File
MariaDB can look for a configuration file in the user’s home directory. It’s clean and keeps your script looking tidy.
How to do it: Create a file at ~/.my.cnf with this content:
[client] user = backup_user password = "your_secure_password"
Important: Restrict the permissions so other users can’t read your password: chmod 600 ~/.my.cnf
Now, your script is incredibly simple because mysqldump just finds the credentials automatically:
#!/bin/bash mysqldump --all-databases > /backups/db_backup_$(date +%F).sql
Option B: mysql_config_editor
If you hate the idea of your password sitting in a plain text file (even with restricted permissions), MariaDB has a tool called mysql_config_editor. This creates an obfuscated login file (.mylogin.cnf) that humans can’t read.
Run this once manually:
mysql_config_editor set --login-path=backup_service --host=localhost --user=backup_user --password
Then, your script just references the “path”:
#!/bin/bash mysqldump --login-path=backup_service --all-databases > /backups/db_backup_$(date +%F).sql
Option C: Environment Variables
In Docker or Kubernetes, config files are a pain. The standard here is to use environment variables injected by a Secret Manager (like HashiCorp Vault or AWS Secrets Manager).
#!/bin/bash
export MYSQL_PWD="${DB_PASSWORD}"
mysqldump -u backup_user --all-databases > /backups/db_backup.sql
unset MYSQL_PWD
Tips for DB Backups:
- Don’t use
root: Create a dedicatedbackup_userwith only the permissions they need (SELECT, LOCK TABLES, etc.). - Compress on the fly: Don’t waste disk space. Pipe your dump straight into gzip:
mysqldump --login-path=backup_service --all-databases | gzip > /backups/db_$(date +%F).sql.gz
Everything Else
While I was researching the database stuff, I wondered: “What do I do for my other API keys and passwords?” Since those tools don’t always have a built-in .my.cnf equivalent, I found three common patterns.
A Secrets File
Similar to the .my.cnf method, you create a generic config file and source it into your script.
Create ~/.secrets.conf:
API_KEY="sk_live_51Mz..." FTP_PASSWORD="my-ftp-password"
Secure it with chmod 600 ~/.secrets.conf
Then, in your script:
#!/bin/bash
if [ -f ~/.secrets.conf ]; then
source ~/.secrets.conf
else
echo "Error: Secret file not found."
exit 1
fi
curl -H "Authorization: Bearer $API_KEY" https://api.example.com/data
The pass Utility
If you want real encryption, check out pass. It uses GPG to encrypt your passwords on disk. They only exist in plain text in your memory for the split second they are called.
Once set up, your script looks like this:
#!/bin/bash API_KEY=$(pass backup/api_key) curl -H "Authorization: Bearer $API_KEY" https://api.example.com/data
Secret Managers
If you’re working in AWS, Azure, or GCP, stop storing passwords on the hard drive entirely. Use a Secret Manager. Your script makes an API call to the vault at runtime to grab the secret.
Example using the AWS CLI:
#!/bin/bash DB_PASS=$(aws secretsmanager get-secret-value --secret-id prod/db/password --query SecretString --output text) my_custom_tool --password "$DB_PASS"
Which one should you choose?
It really comes down to your environment:
- If you’re running a small project or a single VPS, the
secrets.conf+chmod 600method seems perfectly fine. It’s simple and miles better than hard-coding. - Personally, I started using pass as a result of this investigation; it’s not that hard to set up and you end up with at-rest encryption.
- If you’re running something like Docker Swarm or Kubernetes, use Environment Variables injected by your orchestrator.
- In a corporate setting, I’d use a dedicated Secret Manager (Vault, AWS Secrets Mgr) for the auditing and rotation features.
One last warning: Be careful how you use the variable once you have it. Avoid passing passwords as command-line arguments if possible (like my_tool --pass $API_KEY), because those are still visible in the process list (ps -ef). Whenever possible, use environment variables or password files.
Stay secure! 🤓