Using environment variables for databases hooks #382
Loading…
x
Reference in New Issue
Block a user
No description provided.
Delete Branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
What I'm trying to do and why
I would like to use borgmatic to make backups of the databases of my current services. Currently, I have (for example) a docker compose with a wordpress and a mysql service. I want to use borgmatic to automatically backup the mysql database.
I do not want to expose the database port on the host, so I want to include borgmatic as an additional service within the docker compose.
All the sensitive data (users and passwords) are wihin a
.env
file that is read by the docker compose file.Currently, I did not find a way to reuse this
.env
file for theborgmatic-config.yaml
file.So far, I tried:
.env
files with the database user and password at the same level ofborgmatic-config.yaml
borgmatic-config.yaml
in the same directory that the.env
file used bydocker-compose.yaml
Other notes / implementation ideas
Database tables, users and passwords could be passed to borgmatic as environment variables
Environment
operating system and version: Ubuntu 20.10
Related: #370
Checking the sourcecode, I saw here that the variable
MYSQL_PWD
is assigned based on the database dictionary.Using that variable within the
docker-compose.yaml
makes the trick:docker-compose.yaml
If we could do the same with an environment variable called, for example,
MYSQL_USER
we could reuse the sensitive data from within thedocker-compose.yaml
file.I'll make a pull request about this with the suggested change to illustrate the changes that I suggest.
I do not have the rights to write into the borgmatic repo for pushing a branch with the suggested changes. Here is the code that would allow to use environment variables from the Dockerfile:
borgmatic/hooks/mysql.py:77
borgmatic/hooks/mysql.py:156 (After inserting previous one)
I would need some help for writting a good test for this. I would use a PyTest fixture for trying different configurations (both Dockerfile and borgmatic-config.yaml) but I saw that they are setup in a different way, and I'm not sure about the best way to proceed without big changes.
Sorry for the delay here. This seems like a nice addition, with the caveat that all borgmatic databases would have to have the same credentials if you want to pass them in via
MYSQL_USER
andMYSQL_PWD
. As long as that works for your use case and/or you only have a single database to backup, then this would be a good solution.As for testing, I could see two different ways to proceed:
dump_databases()
andrestore_database_dump()
that tests that whenMYSQL_USER
is passed in, the appropriate command is issued with--user
. This would be intests/unit/hooks/test_mysql.py
, and you can look attest_dump_databases_runs_mysqldump_with_username_and_password()
for inspiration. You would run these tests just withtox
.tests/end-to-end/test_database.py
, but may be overkill for this type of change. You would run these tests withtox -e end-to-end
.In terms of making a pull request, I think the traditional way is to make a fork of the repository, and then you should be able to submit a PR with any changes you make there (either in your master or in a branch).
Please let me know if that makes sense. Thanks!
I'd like to do the exact same thing as described above: reuse the exising database credentials in the environment and pass them to borgmatic. Though in my case I would need to support multiple different combinations of user and password for different databases.
Any idea how to solve this?
I think the best option from the user's perspective would be to pass arbitrary (or limited to some prefix like
DB_USER_*
andDB_PWD_*
) environment variables toconfig.yaml
so I could just use them inside the config. Is this possible?Or maybe letting borgmatic check for the env variables
MYSQL_PWD_<dbname>
andMYSQL_USER_<dbname>
automatically would be a solution?On second thought, the name of the db is not unique and there is also no other unique property that could be used to differentiate the different db configs.
I'm curious how you have this working! Here's a quote from the borgmatic database docs under limitations: "borgmatic does not currently support backing up or restoring multiple databases that share the exact same name on different hosts."
If that limitation were kept in place, then I could envision making the database name part of the environment variable name as you suggest. E.g., for a database called
invoices
, the corresponding environment variable could be calledMYSQL_PWD_INVOICES
. But that sounds like it may not work for your use case if you've got multiple databases with the same name.Actually I don't have databases with the same name and I didn't know of that limitation. I just assumed there could me multiple databases with the same name.
Indeed. Still, building that feature on that borgmatic limitation doesn't sound like the best idea, but maybe it's good enough for now. If the limitation will ever be removed this will break.
Would it be possible to add an arbitrary key as additional property in the database config and use this in the environment variable?
Just for some background: That limitation is there because the database name is used as part of the filename constructed when dumping, restoring, and backing up a database. So that filename is contained in the created Borg archive, and that filename is looked up when restoring a backup.
Your idea of supporting an additional (optional) arbitrary identifier could help here though! If not specified, then borgmatic could continue using the database name to construct dump filenames. But if an identifier is specified, then borgmatic could use that instead when constructing the filename. The only potential issue I see is that, to maintain backwards compatibility, a user could not add an identifier to an existing database configuration that already has backups they want to be restorable.
So this is all a longwinded way to say that your idea sounds like it'll work!
I had a look at the code to see how the two things (using optional identifier for database configs and check environment for db user/password) could be implemented. It doesn't look too complicated and one part might look something like this:
But I'm struggling to understand the unit testing. I had a look at
test_dump_databases_runs_mysqldump_for_each_database()
and simply changed the following and the test still succeeds.Shouldn't the test fail in this case, as the dump generated by borgmatic doesn't match the reference anymore? Could you enlighten me? What am I missing?
I think what's going on in this case is that there are enough other functions mocked out—and returning the "correct" value of
bar
regardless of thedatabases
value—that even with an "incorrect" database name indatabases
, the tests still pass. But if you try changingbar
tobaz
in one of those intermediate mocks instead, you will see that tests do indeed fail.A more "correct" test might be to put the
bar
orbaz
value into a constant and then refer to that everywhere it's used. You know, for consistency and to sidestep the sort of testing issue you've found here. But personally, I think that's probably more hassle than it's worth.Hope that makes sense!
Some relevant discussion with another proposed solution on #546.
I think with #546 implemented now, the general ask of this ticket (using environment variables to set borgmatic database passwords) is supported in borgmatic master. It'll be part of the next release. See the documentation for more information: https://torsion.org/borgmatic/docs/how-to/provide-your-passwords/
If there are any details still to do, please feel free to follow up here or file a separate ticket.
Released in borgmatic 1.6.4!