diff --git a/artifacts/mlflow_auth_compose.yml b/artifacts/mlflow_auth_compose.yml new file mode 100644 index 0000000..e4bf3c4 --- /dev/null +++ b/artifacts/mlflow_auth_compose.yml @@ -0,0 +1,87 @@ +--- +- hosts: localhost + connection: local + vars: + # defalt pass is "operatorpass" + GOACCESS_PASSWORD: "{{ mlflow_operator_pass | default('$$2y$$05$$lPcMyqoHliTPF5QeAHoPWOGyLFZxGQg.pSfJlHssQJ9Ny7OFcSI3i') }}" + MLFLOW_USERNAME: "{{ mlflow_admin_user | default('admin') }}" + MLFLOW_PASSWORD: "{{ mlflow_admin_password | default('password') }}" + OIDC_AUTHORITY: "{{ mlflow_oidc_auth | default('https://aai-demo.egi.eu/auth/realms/egi') }}" + OIDC_CLIENT_ID: "{{ mlflow_oidc_client_id | default('oidc-client') }}" + OAUTH_USERINFO_ENDPOINT: "{{ mlflow_auth_userinfo_endpoint | default(OIDC_AUTHORITY + '/protocol/openid-connect/userinfo') }}" + SUPPORTED_VO: "{{ mlflow_oidc_vo | default('vo.ai4eosc.eu') }}" + REQUIRED_ENTITLEMENT: "{{ mlflow_required_entitlement | default('urn:mace:egi.eu:group:' + SUPPORTED_VO + ':role=member#aai.egi.eu') }}" + roles: + - role: 'grycap.docker' + tasks: + - name: Clone git repository + git: + repo: https://github.com/m-team-kit/mlflow-auth-gui + dest: /opt/mlflow-auth-gui + version: main + ignore_errors: yes + + - name: Set default DNS name (nip.io) + set_fact: + dns_name: "mlflow.{{ public_ip_address }}.nip.io" + when: mlflow_dns_name is not defined or mlflow_dns_name == "" + - name: Set custom DNS name + set_fact: + dns_name: "{{ mlflow_dns_name }}" + when: mlflow_dns_name is defined and mlflow_dns_name != "" + + - name: Set admin username and password in ini file + ini_file: + path: /opt/mlflow-auth-gui/backend/srv/auth_config.ini + section: "mlflow" + option: "{{ item.option }}" + value: "{{ item.value }}" + loop: + - { "option": "admin_username", "value" "{{ MLFLOW_USERNAME }}" } + - { "option": "admin_password", "value" "{{ MLFLOW_PASSWORD }}" } + + - name: Create .env file + copy: + dest: /opt/mlflow-auth-gui/.env + content: | + # Domain where MLFLOW is hosted + DOMAIN={{ dns_name }} + # POSTGRES CONFIG + DATABASE_NAME=mlflowdb + DATABASE_USER=postgres + DATABASE_PASSWORD=dummypassword + DATABASE_HOST=database + DATABASE_PORT=5432 + # MLFLOW Authentication Database File + AUTH_DB_FILE=basic_auth.db + # Local (host) BASE PATH to store MLFLOW data, e.g. app-data, user-data, artifacts, backup_db. + # Pay attention about subdirectories ownership, may need to set uid:gid of "docker" + MLFLOW_BASE_PATH_LOCAL=. + # MLflow user registration service + MLFLOW_USERNAME={{ MLFLOW_USERNAME }} + MLFLOW_PASSWORD={{ MLFLOW_PASSWORD }} + MLFLOW_HOSTNAME=http://backend:5000 + OIDC_AUTHORITY={{ OIDC_AUTHORITY }} + OIDC_CLIENT_ID={{ OIDC_CLIENT_ID }} + OAUTH_USERINFO_ENDPOINT={{ OAUTH_USERINFO_ENDPOINT }} + REQUIRED_ENTITLEMENT={{ REQUIRED_ENTITLEMENT }} + PRIVACY_POLICY_URL=https://confluence.egi.eu/display/IMPAIP/Privacy+Policy + TERMS_OF_USE_URL=https://confluence.egi.eu/display/IMPAIP/Acceptable+Use+Policy + # can be left blank, but prefer putting one + LETSENCRYPT_EMAIL={{ mlflow_cert_email}} + CORS_ORIGINS=http://localhost,http://foo.bar + # Monitoring based on goaccess + GOACCESS_ETC_PATH_LOCAL=$MLFLOW_BASE_PATH_LOCAL/goaccess-etc + GOACCESS_OUT_PATH_LOCAL=$MLFLOW_BASE_PATH_LOCAL/goaccess-out + GOACCESS_WEB_ROUTE=goaccess + GOACCESS_USER=operator + GOACCESS_PASSWORD={{ GOACCESS_PASSWORD }} # bcrypt encrypted password, use "htpasswd -B -n operator" to generate. use $$ instead of $ in GOACCESS_PASSWORD value + GOACCESS_ACCESSLOG_FORMAT=TRAEFIKCLF + + - name: Exec docker-compose up + docker_compose: + project_src: /opt/mlflow-auth-gui + state: present + files: + - compose.yml + - compose.prod.yml \ No newline at end of file diff --git a/templates/mlflow_authvm.yaml b/templates/mlflow_authvm.yaml new file mode 100644 index 0000000..97faf30 --- /dev/null +++ b/templates/mlflow_authvm.yaml @@ -0,0 +1,133 @@ +tosca_definitions_version: tosca_simple_yaml_1_0 + +imports: + - grycap_custom_types: https://raw.githubusercontent.com/grycap/tosca/main/custom_types.yaml + +metadata: + template_version: "1.0.0" + template_name: MLFlow Auth VM + display_name: Deploy MLFlow Auth GUI on a VM + icon: images/mlflow.png + tabs: + MLFlow: mlflow_.* + parents: + - simple-node-disk.yml + +description: Deploy MLFlow on a VM with the MLFlow Auth GUI. + +topology_template: + + inputs: + + mlflow_admin_user: + type: string + description: MLFlow Admin server Username + default: admin + required: yes + + mlflow_admin_password: + type: string + description: MLFlow Admin server Password + default: password + required: yes + + mlflow_operator_pass: + type: string + description: MLFlow Operator Password + default: 'operatorpass' + required: no + + mlflow_oidc_auth: + type: string + description: MLFlow OIDC Authority + default: 'https://aai-demo.egi.eu/auth/realms/egi' + required: no + + mlflow_oidc_client_id: + type: string + description: MLFlow OIDC Client ID + default: 'oidc-client' + required: no + + mlflow_oidc_vo: + type: string + description: MLFlow OIDC VO name + default: 'vo.ai4eosc.eu' + required: no + + mlflow_dns_name: + type: string + description: MLFlow DNS name (leave empty to use mlflow..nip.io) + default: '' + required: no + + mlflow_cert_email: + type: string + description: MLFlow LetsEncrypt certificate email + default: 'johndoe@server.com' + required: no + + # Restrict some simple-node-disk input values + + storage_size: + type: scalar-unit.size + description: Size of the extra HD added to the instance (Set 0 if disk is not needed) + default: 20 GB + constraints: + - valid_values: [ 20 GB, 50 GB, 100 GB, 200 GB, 500 GB, 1 TB, 2 TB, 10 TB, 20 TB, 40 TB, 100 TB ] + + mount_path: + type: string + description: Path to mount the extra disk + default: /opt/mlflow-auth-gui + + node_templates: + + mlflow: + type: tosca.nodes.ec3.Application + artifacts: + docker_role: + file: grycap.docker + type: tosca.artifacts.AnsibleGalaxy.role + capabilities: + endpoint: + properties: + ports: + https: + protocol: tcp + source: 443 + http: + protocol: tcp + source: 80 + interfaces: + Standard: + configure: + implementation: https://raw.githubusercontent.com/grycap/tosca/main/artifacts/mlflow_compose.yml + inputs: + public_ip_address: + get_attribute: [ simple_node, public_address, 0 ] + mlflow_admin_user: + get_input: mlflow_admin_user + mlflow_admin_password: + get_input: mlflow_admin_password + mlflow_cert_email: + get_input: mlflow_cert_email + mlflow_dns_name: + get_input: mlflow_dns_name + mlflow_oidc_auth: + get_input: mlflow_oidc_auth + mlflow_oidc_client_id: + get_input: mlflow_oidc_client_id + mlflow_oidc_vo: + get_input: mlflow_oidc_vo + mlflow_operator_pass: + get_input: mlflow_operator_pass + + requirements: + - host: simple_node + + outputs: + mlflow_nip_endpoint: + value: { concat: [ 'https://mlflow.', get_attribute: [ simple_node, public_address, 0 ], 'nip.io/signup' ] } + mlflow_dns_endpoint: + value: { concat: [ 'https://', get_input: mlflow_dns_name, '/signup' ] } diff --git a/templates/simple-node-disk.yml b/templates/simple-node-disk.yml index 771321c..55cc616 100644 --- a/templates/simple-node-disk.yml +++ b/templates/simple-node-disk.yml @@ -41,6 +41,7 @@ metadata: - image-service.yaml - ai4eoscvm.yaml - mlflowvm.yaml + - mlflow_authvm.yaml - wget.yml - sgde.yaml - dydns_egi_update_vm.yml