With this PR, password can be read from docker secrets in both compose as well as swarm environment.
```YAML
secrets:
mariadb-root-password:
file: mariadb-root-password.txt
erpnext-admin-password:
file: erpnext-admin-password.txt
services:
erpnext:
image: frappe/erpnext-worker:${ERPNEXT_VERSION:-v12.5.2}
environment:
- SITE_NAME=example.com
- DB_ROOT_USER=root
- MARIADB_HOST=mariadb
- INSTALL_APPS=erpnext
- FORCE=1
- REDIS_CACHE=redis-cache:6379
- REDIS_QUEUE=redis-queue:6379
- REDIS_SOCKETIO=redis-socketio:6379
- SOCKETIO_PORT=9000
- AUTO_MIGRATE=1
- ADMIN_PASSWORD_FILE=/run/secrets/erpnext-admin-password
- MYSQL_ROOT_PASSWORD_FILE=/run/secrets/mariadb-root-password
secrets:
- erpnext-admin-password
- mariadb-root-password
restart: on-failure
volumes:
- erpnext-data:/home/frappe/frappe-bench/sites
- assets-data:/home/frappe/frappe-bench/sites/assets
links:
- redis-cache
- redis-queue
- redis-socketio
- mariadb
depends_on:
- mariadb
- redis-cache
- redis-queue
- redis-socketio
networks:
- erpnext-net
```
Reference: [Addind docker secrets in to your images](https://docs.docker.com/engine/swarm/secrets/#build-support-for-docker-secrets-into-your-images)
Changes to be committed:
modified: ../../README.md
modified: ../common/commands/new.py
modified: ../common/commands/restore_backup.py
modified: ../erpnext-nginx/docker-entrypoint.sh
82 lines
2.7 KiB
Python
82 lines
2.7 KiB
Python
import os, frappe, json
|
|
|
|
from frappe.commands.site import _new_site
|
|
from check_connection import get_config, get_site_config
|
|
|
|
def get_password(env_var, default=None):
|
|
return os.environ.get(env_var) or _get_password_from_secret(f"{env_var}_FILE") or default
|
|
|
|
|
|
def _get_password_from_secret(env_var):
|
|
"""Fetches the secret value from the docker secret file
|
|
usually located inside /run/secrets/
|
|
Arguments:
|
|
env_var {str} -- Name of the environment variable
|
|
containing the path to the secret file.
|
|
Returns:
|
|
[str] -- Secret value
|
|
"""
|
|
passwd = None
|
|
secret_file_path = os.environ.get(env_var)
|
|
if secret_file_path:
|
|
with open(secret_file_path) as secret_file:
|
|
passwd = secret_file.read().strip()
|
|
|
|
return passwd
|
|
|
|
|
|
def main():
|
|
site_name = os.environ.get("SITE_NAME", 'site1.localhost')
|
|
mariadb_root_username = os.environ.get("DB_ROOT_USER", 'root')
|
|
mariadb_root_password = get_password("MYSQL_ROOT_PASSWORD", 'admin')
|
|
force = True if os.environ.get("FORCE", None) else False
|
|
install_apps = os.environ.get("INSTALL_APPS", None)
|
|
install_apps = install_apps.split(',') if install_apps else []
|
|
frappe.init(site_name, new_site=True)
|
|
|
|
_new_site(
|
|
None,
|
|
site_name,
|
|
mariadb_root_username=mariadb_root_username,
|
|
mariadb_root_password=mariadb_root_password,
|
|
admin_password=get_password("ADMIN_PASSWORD", 'admin'),
|
|
verbose=True,
|
|
install_apps=install_apps,
|
|
source_sql=None,
|
|
force=force,
|
|
reinstall=False,
|
|
)
|
|
|
|
config = get_config()
|
|
|
|
site_config = get_site_config(site_name)
|
|
|
|
mysql_command = 'mysql -h{db_host} -u{mariadb_root_username} -p{mariadb_root_password} -e '.format(
|
|
db_host=config.get('db_host'),
|
|
mariadb_root_username=mariadb_root_username,
|
|
mariadb_root_password=mariadb_root_password
|
|
)
|
|
|
|
# update User's host to '%' required to connect from any container
|
|
command = mysql_command + "\"UPDATE mysql.user SET Host = '%' where User = '{db_name}'; FLUSH PRIVILEGES;\"".format(
|
|
db_name=site_config.get('db_name')
|
|
)
|
|
os.system(command)
|
|
|
|
# Set db password
|
|
command = mysql_command + "\"UPDATE mysql.user SET authentication_string = PASSWORD('{db_password}') WHERE User = \'{db_name}\' AND Host = \'%\';\"".format(
|
|
db_name=site_config.get('db_name'),
|
|
db_password=site_config.get('db_password')
|
|
)
|
|
os.system(command)
|
|
|
|
# Grant permission to database
|
|
command = mysql_command + "\"GRANT ALL PRIVILEGES ON \`{db_name}\`.* TO '{db_name}'@'%'; FLUSH PRIVILEGES;\"".format(
|
|
db_name=site_config.get('db_name')
|
|
)
|
|
os.system(command)
|
|
exit(0)
|
|
|
|
if __name__ == "__main__":
|
|
main()
|