--- # showcase/webapp-db.yml — MariaDB setup for the webapp blueprint # # Installs MariaDB, creates webapp database and user with random password, # configures remote access, and stores credentials in /etc/webapp-db-creds # for the web tier to read via Incus API. - name: Generate random database password ansible.builtin.set_fact: db_password: "{{ lookup('password', '/dev/null chars=ascii_letters,digits length=20') }}" - name: Generate MariaDB setup script ansible.builtin.set_fact: db_setup_script: | #!/bin/bash set -e echo "=== MariaDB setup starting ===" export DEBIAN_FRONTEND=noninteractive # Install MariaDB apt-get install -y -qq mariadb-server 2>&1 | tail -3 echo "[OK] MariaDB installed" # Start and enable systemctl enable mariadb systemctl start mariadb echo "[OK] MariaDB started" # Configure bind address for remote connections sed -i 's/^bind-address.*=.*/bind-address = 0.0.0.0/' /etc/mysql/mariadb.conf.d/50-server.cnf systemctl restart mariadb echo "[OK] Bind address set to 0.0.0.0" # Create database and user mysql -u root << 'SQL' CREATE DATABASE IF NOT EXISTS webapp; CREATE USER IF NOT EXISTS 'webapp'@'%' IDENTIFIED BY '{{ db_password }}'; GRANT ALL PRIVILEGES ON webapp.* TO 'webapp'@'%'; FLUSH PRIVILEGES; -- Create sample table for the web tier to query USE webapp; CREATE TABLE IF NOT EXISTS visits ( id INT AUTO_INCREMENT PRIMARY KEY, visitor_ip VARCHAR(45), visitor_host VARCHAR(255), visited_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ); INSERT INTO visits (visitor_ip, visitor_host) VALUES ('setup', '{{ ffsdn_instance_name }}'); SQL echo "[OK] Database 'webapp' and user created" # Store credentials for the web tier to read MY_IP=$(hostname -I | awk '{print $1}') cat > /etc/webapp-db-creds << CREDS DB_HOST=${MY_IP} DB_PORT=3306 DB_NAME=webapp DB_USER=webapp DB_PASS={{ db_password }} CREDS chmod 644 /etc/webapp-db-creds echo "[OK] Credentials stored in /etc/webapp-db-creds" echo "=== MariaDB setup complete ===" - name: Push MariaDB setup script ansible.builtin.uri: url: "{{ incus_api }}/1.0/instances/{{ ffsdn_instance_name }}/files?path=/tmp/webapp-db-setup.sh" method: POST client_cert: "{{ incus_cert }}" client_key: "{{ incus_key }}" validate_certs: false body: "{{ db_setup_script }}" headers: Content-Type: "application/octet-stream" X-Incus-type: "file" X-Incus-mode: "0755" status_code: [200] - name: Execute MariaDB setup script ansible.builtin.uri: url: "{{ incus_api }}/1.0/instances/{{ ffsdn_instance_name }}/exec" method: POST client_cert: "{{ incus_cert }}" client_key: "{{ incus_key }}" validate_certs: false body_format: json body: command: ["/bin/bash", "/tmp/webapp-db-setup.sh"] record-output: true interactive: false wait-for-websocket: false environment: DEBIAN_FRONTEND: "noninteractive" status_code: [202] return_content: true register: db_setup_exec - name: Wait for MariaDB setup to complete (up to 5 minutes) ansible.builtin.uri: url: "{{ incus_api }}{{ db_setup_exec.json.operation }}/wait?timeout=300" method: GET client_cert: "{{ incus_cert }}" client_key: "{{ incus_key }}" validate_certs: false return_content: true timeout: 320 register: db_setup_wait failed_when: db_setup_wait.json.metadata.status != "Success" - name: Verify MariaDB setup exit code ansible.builtin.assert: that: - db_setup_wait.json.metadata.metadata.return | int == 0 fail_msg: "MariaDB setup exited with code {{ db_setup_wait.json.metadata.metadata.return }}" success_msg: "MariaDB setup completed successfully" - name: Verify credentials file was written ansible.builtin.uri: url: "{{ incus_api }}/1.0/instances/{{ ffsdn_instance_name }}/files?path=/etc/webapp-db-creds" method: GET client_cert: "{{ incus_cert }}" client_key: "{{ incus_key }}" validate_certs: false return_content: true register: creds_check - name: Display MariaDB configuration ansible.builtin.debug: msg: "MariaDB configured: {{ creds_check.content | trim }}" - name: Clean up setup script ansible.builtin.uri: url: "{{ incus_api }}/1.0/instances/{{ ffsdn_instance_name }}/exec" method: POST client_cert: "{{ incus_cert }}" client_key: "{{ incus_key }}" validate_certs: false body_format: json body: command: ["/bin/rm", "-f", "/tmp/webapp-db-setup.sh"] record-output: false interactive: false wait-for-websocket: false status_code: [202] ignore_errors: true