From f2a67540218c624e5ae6cc4466c46293702638c3 Mon Sep 17 00:00:00 2001 From: gwen Date: Mon, 30 Oct 2023 09:07:38 +0100 Subject: [PATCH] first rev --- .gitignore | 2 + MiseEnProd.txt | 105 ++++++++++++ ansible.cfg | 4 + group_vars/all/main.yml | 9 + hosts | 5 + playbook.yml | 14 ++ readme.rst | 82 +++++++++ requirements.txt | 12 ++ roles/archive/readme.rst | 23 +++ roles/archive/tasks/main.yml | 25 +++ roles/archive/vars/main.yml | 3 + roles/certbot/tasks/main.yml | 34 ++++ roles/certbot/vars/main.yml | 7 + roles/common/tasks/main.yml | 37 ++++ roles/datascience/files/.empty | 0 roles/datascience/files/drop_database.py | 31 ++++ roles/datascience/files/telemetry | 1 + roles/datascience/readme.rst | 23 +++ roles/datascience/tasks/main.yml | 100 +++++++++++ roles/datascience/vars/main.yml | 7 + roles/mongodb/files/add_admin_user.py | 26 +++ roles/mongodb/files/check_admin_user.py | 27 +++ roles/mongodb/tasks/main.yml | 158 ++++++++++++++++++ roles/mongodb/vars/main.yml | 4 + roles/nginx/handlers/main.yml | 5 + roles/nginx/tasks/main.yml | 30 ++++ roles/nginx/templates/site.conf.j2 | 16 ++ roles/nginx/vars/main.yml | 2 + roles/pip/readme.txt | 6 + roles/pip/tasks/main.yml | 10 ++ roles/run/tasks/main.yml | 38 +++++ .../run/templates/princelyacts.service.jinja | 20 +++ roles/run/vars/main.yml | 2 + run_playbook.sh | 4 + todo.txt | 21 +++ 35 files changed, 893 insertions(+) create mode 100644 .gitignore create mode 100644 MiseEnProd.txt create mode 100644 ansible.cfg create mode 100644 group_vars/all/main.yml create mode 100644 hosts create mode 100644 playbook.yml create mode 100755 readme.rst create mode 100644 requirements.txt create mode 100644 roles/archive/readme.rst create mode 100755 roles/archive/tasks/main.yml create mode 100755 roles/archive/vars/main.yml create mode 100755 roles/certbot/tasks/main.yml create mode 100644 roles/certbot/vars/main.yml create mode 100755 roles/common/tasks/main.yml create mode 100644 roles/datascience/files/.empty create mode 100644 roles/datascience/files/drop_database.py create mode 100644 roles/datascience/files/telemetry create mode 100644 roles/datascience/readme.rst create mode 100755 roles/datascience/tasks/main.yml create mode 100755 roles/datascience/vars/main.yml create mode 100755 roles/mongodb/files/add_admin_user.py create mode 100755 roles/mongodb/files/check_admin_user.py create mode 100644 roles/mongodb/tasks/main.yml create mode 100644 roles/mongodb/vars/main.yml create mode 100755 roles/nginx/handlers/main.yml create mode 100755 roles/nginx/tasks/main.yml create mode 100755 roles/nginx/templates/site.conf.j2 create mode 100644 roles/nginx/vars/main.yml create mode 100644 roles/pip/readme.txt create mode 100644 roles/pip/tasks/main.yml create mode 100644 roles/run/tasks/main.yml create mode 100644 roles/run/templates/princelyacts.service.jinja create mode 100644 roles/run/vars/main.yml create mode 100755 run_playbook.sh create mode 100644 todo.txt diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..e21965a --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +.venv +roles/archive/files/* diff --git a/MiseEnProd.txt b/MiseEnProd.txt new file mode 100644 index 0000000..90cbb0e --- /dev/null +++ b/MiseEnProd.txt @@ -0,0 +1,105 @@ +Cérémonial de mise en production +=================================== + +Installation +=============== + +Vue d'ensemble +---------------- + +.. important:: Relire attentivement les fichiers `MiseEnProd.txt` dans les trois + dépôts git `webapp`, `datascience` et `deployment`. + +1. **webapp**: tag et paramètrage de l'app dans `webapp` +2. procédure d'installation (dans `deployment`, cf ci-dessous) +3. populate database (dans `datascience`) +4. démarrage de l'application (dans `deployment`) + + +Dans `group_vars/all` +----------------------- + +- renommer `main.yml` en `main.dev.yml` + +:: + + cp main.yml main.dev.yml + +- renommer `main.prod.yml` en `main.yml` + +:: + + cp main.prod.yml main.yml + +- ouvrir le fichier `main.yml`, +- vérifier que la variable `mode` est bien renseignée + +:: + + mode: production + +- vérifier que la variable `action` est bien renseignée + +:: + + action: install + +- vérifier que `application_release_tag` pointe sur le bon tag de release + + +A la racine du projet +------------------------------- + +- lancer `source .venv/bin/activate` à la racine du projet +- vérifier que la procédure de tag de release dans `webapp` a bien été faite +- lancer `./install.sh` + +:: + + ./install.sh + +- aller dans `datascience`, dérouler le cérémonial de prod +- revenir à la racine du projet, lancer `launch_application.sh` + +:: + + ./launch_application.sh + + +Mise à jour de l'application +=============================== + +Vue d'ensemble +-------------- + +1. tag et paramètrage de l'app dans `webapp` +2. procédure de mise à jour (dans `deployment`, cf ci-dessous) +4. re-démarrage de l'application (dans `deployment`) + + +Dans `group_vars/all` +----------------------- + +- renommer `main.yml` en `main.dev.yml` +- renommer `main.prod.yml` en `main.yml` +- ouvrir le fichier `main.yml`, +- vérifier que la variable `mode` est bien renseignée + +:: + + mode: production + +- vérifier que la variable `action` est bien renseignée + **et lui affecter la valeur `publish`** + +:: + + action: publish + +- vérifier que `application_release_tag` pointe sur le bon tag de release +- lancer `source .venv/bin/activate` à la racine du projet +- vérifier que la procédure de tag de release dans `webapp` a bien été faite +- **lancer la commande `./publish.sh`** +- **optionnel** : aller dans `datascience`, dérouler le cérémonial de prod + si les datas ont changées +- revenir à la racine du projet, lancer `launch_application.sh` diff --git a/ansible.cfg b/ansible.cfg new file mode 100644 index 0000000..b291086 --- /dev/null +++ b/ansible.cfg @@ -0,0 +1,4 @@ +[defaults] +host_key_checking = false +inventory = hosts + diff --git a/group_vars/all/main.yml b/group_vars/all/main.yml new file mode 100644 index 0000000..bfa5da4 --- /dev/null +++ b/group_vars/all/main.yml @@ -0,0 +1,9 @@ +# development configuration +domain_name: toto.site +mail_address: toto@free.fr +server_ip: XXXX +dbadmin: XXXX +dbpassword: XXXXXXXX +linux_user: ubuntu +application_release_tag: v0.20beta +datascience_release_tag: v0.1pre-alpha diff --git a/hosts b/hosts new file mode 100644 index 0000000..46864ff --- /dev/null +++ b/hosts @@ -0,0 +1,5 @@ +# set the vps ip address or domain name + +server1 ansible_host="{{ server_ip }}" ansible_ssh_user="{{ linux_user }}" ansible_python_interpreter="/usr/bin/python3" + + diff --git a/playbook.yml b/playbook.yml new file mode 100644 index 0000000..6f672e7 --- /dev/null +++ b/playbook.yml @@ -0,0 +1,14 @@ +- hosts: server1 + #remote_user: debian + become: true + become_method: sudo + + roles: + - common + - nginx + - certbot + - archive + - pip + - mongodb + - datascience + - run diff --git a/readme.rst b/readme.rst new file mode 100755 index 0000000..24fe234 --- /dev/null +++ b/readme.rst @@ -0,0 +1,82 @@ +VPS installation procedure +============================ + +Prerequisites +------------------ + +You must have working copy repositories of the + +- `deployment` +- `webapp` + +projects on your control node machine. + +:: + +─ repositories + ├── deployment + └── webapp + + +.. important:: + + In the webapp project, before launching the installation procedure, + make a `git pull --tags` to retrieve all the tags in the local + working copy webapp repository. + + +Before launching the installation +------------------------------------- + +You must have a `group_vars/all/main.yml` configuration file, wich is NOT +in the working copy repository. Have a look at the `.gitignore` file. + +Installation configuration +----------------------------------------------- + +You need to verify and set some variables before launching the playbook: + +The `group_vars/all/main.yml` shall have these variables set : + +- domain_name +- mail_address +- server_ip +- dbadmin +- dbpassword +- application_release_tag + + +Installation procedure +----------------------------------- + +From this `deployment` project, launch the script:: + + ./install.sh + +The script `install.sh` installs: + +- nginx as a webserver +- https (with a let's encrypt acme challenge) +- usefull python librairies (flask, for example) +- mongodb storage + +Then go to the `datascience` repository and populate the database. +When the database is populated, you can run the app service with:: + + ./launch_application.sh + +which lauches the webapp application service on the remote server. + +Installation method +---------------------- + +we use `ansible `_ + +The target is a VPS with a debian 12 installed, the python version is:: + + Python 3.11.2 (main, Mar 13 2023, 12:18:29) [GCC 12.2.0] on linux + Type "help", "copyright", "credits" or "license" for more information. + >>> import flask + >>> + + diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..effad2f --- /dev/null +++ b/requirements.txt @@ -0,0 +1,12 @@ +ansible==8.3.0 +ansible-core==2.15.3 +cffi==1.15.1 +cryptography==41.0.3 +dnspython==2.4.2 +Jinja2==3.1.2 +MarkupSafe==2.1.3 +packaging==23.1 +pycparser==2.21 +pymongo==4.5.0 +PyYAML==6.0.1 +resolvelib==1.0.1 diff --git a/roles/archive/readme.rst b/roles/archive/readme.rst new file mode 100644 index 0000000..ab1f76f --- /dev/null +++ b/roles/archive/readme.rst @@ -0,0 +1,23 @@ +Deployment from an archive +============================= + +ansible *Unarchive* deployment procedure + +Create the git archive +-------------------------- + +First, let's create the git archive from the actes princier's repository + +git archive command:: + + git archive --format=tgz --prefix='app/' -o actesprinciers.tgz v0.2_maquette + +Place the archive in your `files` folder +------------------------------------------- + +Application archive to be deployed shall be present in the `files` folder:: + + files/actesprinciers.tgz + + + diff --git a/roles/archive/tasks/main.yml b/roles/archive/tasks/main.yml new file mode 100755 index 0000000..2947696 --- /dev/null +++ b/roles/archive/tasks/main.yml @@ -0,0 +1,25 @@ +- name: Deployment - Archive the app for deployment + become: false + ansible.builtin.shell: "git archive --format=tgz --prefix='app/' -o ../deployment/roles/archive/files/{{deployment_repo_name}}.tgz {{ release_tag }}" + args: + chdir: ../{{deployment_repo_name}}/ + delegate_to: 127.0.0.1 + +- name: Deployment - if exists - removes /opt/ directory + shell: rm -rf /opt/ + +- name: Deployment - Creates /opt/ (application) directory + file: + path: /opt + state: directory + +- name: Deployment - extract application archive + ansible.builtin.unarchive: + src: "{{deployment_repo_name}}.tgz" + dest: /opt/ + +- name: Deployment - copies the credentials file from the local app working copy repository + ansible.builtin.copy: + src: "../{{deployment_repo_name}}/params.yaml" + dest: "/opt/app" + mode: '0644' diff --git a/roles/archive/vars/main.yml b/roles/archive/vars/main.yml new file mode 100755 index 0000000..80962c2 --- /dev/null +++ b/roles/archive/vars/main.yml @@ -0,0 +1,3 @@ +--- +release_tag: "{{ application_release_tag }}" +deployment_repo_name: webapp diff --git a/roles/certbot/tasks/main.yml b/roles/certbot/tasks/main.yml new file mode 100755 index 0000000..ce2569f --- /dev/null +++ b/roles/certbot/tasks/main.yml @@ -0,0 +1,34 @@ +- name: Install certbot base + apt: + name: + - certbot + state: present + +- name : Install Let's Encrypt Package + apt: name={{ certbot_package }} update_cache=yes state=latest + +- name: check if pem already exists + stat: + path: "/etc/letsencrypt/live/{{ certbot_site_names['host1'] }}/fullchain.pem" + register: pem + +- debug: + msg: "it looks like the let's encrypt pem exists..." + when: pem.stat.exists + +- debug: + msg: "it looks like the let's encrypt pem does not exist..." + when: not pem.stat.exists + +- name: Create and Install certificates using {{ certbot_plugin }} Plugin + shell: certbot --{{ certbot_plugin }} -d {{ item }} -m {{ certbot_mail_address }} --agree-tos --noninteractive --redirect + when: not pem.stat.exists + with_items: + - "{{ certbot_site_names['host1'] }}" + # TODO: in case of multi-site + #- "{{ certbot_site_names['host2'] }}" + +- name: Set Letsencrypt Cronjob for Certificate Auto Renewal + cron: name=letsencrypt_renewal special_time=monthly job="/usr/bin/certbot renew" + tags: + - cert_renew diff --git a/roles/certbot/vars/main.yml b/roles/certbot/vars/main.yml new file mode 100644 index 0000000..c43911a --- /dev/null +++ b/roles/certbot/vars/main.yml @@ -0,0 +1,7 @@ +certbot_site_names: { + host1: "{{ domain_name }}", + } +# host2: "", +certbot_package: "python3-certbot-nginx" +certbot_plugin: "nginx" +certbot_mail_address: "{{ mail_address }}" diff --git a/roles/common/tasks/main.yml b/roles/common/tasks/main.yml new file mode 100755 index 0000000..1b50259 --- /dev/null +++ b/roles/common/tasks/main.yml @@ -0,0 +1,37 @@ +--- +- name: Update & upgrade system + apt: + update_cache: yes + upgrade: dist + +- name: Install required packages + apt: + name: + - cron + - python3-pip + - python3-virtualenv + - python3-setuptools + - htop + - man + - net-tools + - bash-completion + - locales + - python-is-python3 + - wget + - zip + - bzip2 + - tree + - vim + - vim-common + - screen + - curl + - unzip + state: present + +- name: Remove useless stuff + apt: + name: + - bind9 + - telnet + - ftp + state: absent diff --git a/roles/datascience/files/.empty b/roles/datascience/files/.empty new file mode 100644 index 0000000..e69de29 diff --git a/roles/datascience/files/drop_database.py b/roles/datascience/files/drop_database.py new file mode 100644 index 0000000..9a4962c --- /dev/null +++ b/roles/datascience/files/drop_database.py @@ -0,0 +1,31 @@ +#!/usr/bin/env python +"""Drop database utility +""" +import sys + +import pymongo +from pymongo import MongoClient + +import urllib.parse + +mongo_ip = sys.argv[1] +mongo_admin = sys.argv[2] +mongo_password = sys.argv[3] + +username = urllib.parse.quote_plus(mongo_admin) +password = urllib.parse.quote_plus(mongo_password) + +dbclient = MongoClient('mongodb://%s:%s@%s:27017' % (username, password, mongo_ip)) +#myclient = pymongo.MongoClient("mongodb://dbadmin:Test123@:27017/?authSource=the_database&authMechanism=SCRAM-SHA-1") + +actesdb = dbclient["actesdb"] + +housecol = actesdb["house"] +actecol = actesdb["acte"] +helpers = actesdb["helpers"] + +# remove collections +actecol.drop() +housecol.drop() +helpers.drop() + diff --git a/roles/datascience/files/telemetry b/roles/datascience/files/telemetry new file mode 100644 index 0000000..8fe91bc --- /dev/null +++ b/roles/datascience/files/telemetry @@ -0,0 +1 @@ +consent: false diff --git a/roles/datascience/readme.rst b/roles/datascience/readme.rst new file mode 100644 index 0000000..df2ff04 --- /dev/null +++ b/roles/datascience/readme.rst @@ -0,0 +1,23 @@ +Deployment from an archive +============================= + +ansible *Unarchive* deployment procedure + +Create the git archive +-------------------------- + +First, let's create the git archive from the actes princier's repository + +git archive command:: + + git archive --format=tgz --prefix='datascience/' -o datascience.tgz + +Place the archive in your `files` folder +------------------------------------------- + +Application archive to be deployed shall be present in the `files` folder:: + + files/datascience.tgz + + + diff --git a/roles/datascience/tasks/main.yml b/roles/datascience/tasks/main.yml new file mode 100755 index 0000000..e1ee071 --- /dev/null +++ b/roles/datascience/tasks/main.yml @@ -0,0 +1,100 @@ +- name: Deployment - Archive datascience for pipeline run on the server + become: false + ansible.builtin.shell: "git archive --format=tgz --prefix='datascience/' -o ../deployment/roles/datascience/files/{{datascience_repo_name}}.tgz {{ release_tag }}" + args: + chdir: ../{{datascience_repo_name}}/ + delegate_to: 127.0.0.1 + +- name: Deployment - removes old datascience directory + shell: rm -rf /home/{{ user }}/datascience + +- name: Deployment - Creates datascience directory + become: false + file: + path: /home/{{ user }}/datascience + state: directory + +- name: Deployment - extract datascience archive + become: false + ansible.builtin.unarchive: + src: "{{datascience_repo_name}}.tgz" + dest: /home/{{ user }}/ + +- name: Deployment - copies the credentials file from the local datascience working copy repository + become: false + ansible.builtin.copy: + src: "../{{datascience_repo_name}}/actes-princiers/conf/local/parameters.yml" + dest: "/home/{{ user }}/datascience/actes-princiers/conf/local/" + mode: '0644' + +#- name: Drop all collections in the mongo database +# become: false +# ansible.builtin.script: +# executable: python3 +# cmd: "drop_database.py {{ mongodb_ip }} {{ mongodb_admin }} {{mongodb_password}}" +# delegate_to: 127.0.0.1 +# ignore_errors: true + +- name: Create working directory for mongo admin scripts + become: false + #become_user: "{{ user }}" + ansible.builtin.file: + path: /home/{{ user }}/tmp/ + state: directory + mode: '0755' + +- name: Installing workplace script librairies + become: false + ansible.builtin.pip: + name: pymongo + virtualenv: /home/{{ user }}/tmp/.venv + +- name: Upload drop_database python script + become: false + ansible.builtin.copy: + src: files/drop_database.py + dest: "/home/{{ user }}/tmp/" + mode: '0755' + +- name: Run drop_database script + become: false + ansible.builtin.shell: "cd /home/{{ user }}/tmp && . .venv/bin/activate && ./drop_database.py {{ mongodb_ip }} {{ mongodb_admin }} {{mongodb_password}}" + args: + executable: /bin/bash + ignore_errors: true + +- name: Install python librairies into the specified virtual environment + become: false + ansible.builtin.pip: + requirements: /home/{{ user }}/datascience/actes-princiers/src/requirements.txt + virtualenv: /home/{{ user }}/datascience/.venv + +#- name: Uninstall kedro-telemetry +# become: false +# ansible.builtin.pip: +# name: kedro-telemetry +# virtualenv: /home/{{ user }}/datascience/.venv +# state: absent + +- name: Kedro - copy telemetry file + become: false + ansible.builtin.copy: + src: files/telemetry + dest: "/home/{{ user }}/datascience/actes-princiers/.telemetry" + mode: '0644' + +- name: Install python librairies into the specified virtual environment + become: false + ansible.builtin.pip: + requirements: /home/{{ user }}/datascience/actes-princiers/src/requirements.txt + virtualenv: /home/{{ user }}/datascience/.venv + +- name: Launches the kedro JSON creation pipeline and populates the database + become: false + ansible.builtin.shell: | + cd /home/{{ user }}/datascience/ && . .venv/bin/activate && cd actes-princiers && kedro run --tags="etl_transform" && kedro run --tags="populate_database" + args: + executable: /bin/bash + # chdir: /home/{{ user }}/datascience/actes-princiers/ + # executable: /home/{{ user }}/datascience/.venv/bin/kedro + diff --git a/roles/datascience/vars/main.yml b/roles/datascience/vars/main.yml new file mode 100755 index 0000000..b151058 --- /dev/null +++ b/roles/datascience/vars/main.yml @@ -0,0 +1,7 @@ +--- +release_tag: "{{ datascience_release_tag }}" +datascience_repo_name: datascience +user: "{{ linux_user }}" +mongodb_ip: 127.0.0.1 +mongodb_admin: "{{ dbadmin }}" +mongodb_password: "{{ dbpassword }}" diff --git a/roles/mongodb/files/add_admin_user.py b/roles/mongodb/files/add_admin_user.py new file mode 100755 index 0000000..3ae78c4 --- /dev/null +++ b/roles/mongodb/files/add_admin_user.py @@ -0,0 +1,26 @@ +#!/usr/bin/env python + +"""Mongo create admin user utility +""" +import sys +import urllib.parse + +import pymongo + + +mongo_ip = sys.argv[1] +mongo_admin = sys.argv[2] +mongo_password = sys.argv[3] + +#mongo_admin = urllib.parse.quote_plus(mongo_admin) +#mongo_password = urllib.parse.quote_plus(mongo_password) + + +client = pymongo.MongoClient(f"mongodb://{mongo_ip}:27017/") + +client.admin.command( + 'createUser', mongo_admin, + pwd=mongo_password, + roles=[ { 'role': "userAdminAnyDatabase", 'db': "admin" }, "readWriteAnyDatabase" ] + ) + diff --git a/roles/mongodb/files/check_admin_user.py b/roles/mongodb/files/check_admin_user.py new file mode 100755 index 0000000..e20282e --- /dev/null +++ b/roles/mongodb/files/check_admin_user.py @@ -0,0 +1,27 @@ +#!/usr/bin/env python + +"""Mongo create check if user exists utility +""" +import sys +import urllib.parse + +import pymongo + +mongo_ip = sys.argv[1] +mongo_admin = sys.argv[2] +mongo_password = sys.argv[3] + +mongo_admin = urllib.parse.quote_plus(mongo_admin) +mongo_password = urllib.parse.quote_plus(mongo_password) + +try: + client = pymongo.MongoClient(f"mongodb://{mongo_ip}:27017/") + admin = client['admin'] + userscol = admin['system.users'] + print(userscol.find_one()) + # ok, the user doesn't exist + sys.exit(0) +except pymongo.errors.OperationFailure as err: + # unable to login without password + sys.exit(1) + diff --git a/roles/mongodb/tasks/main.yml b/roles/mongodb/tasks/main.yml new file mode 100644 index 0000000..be4ff3f --- /dev/null +++ b/roles/mongodb/tasks/main.yml @@ -0,0 +1,158 @@ +--- +- name: Install required packages + apt: + name: + - curl + - gnupg + state: present + +#- name: Add mongo ppa key (new way of adding an apt repository key) +# ansible.builtin.get_url: +# url: https://pgp.mongodb.com/server-7.0.asc +# dest: /etc/apt/trusted.gpg.d/mongodb-server-7.0.gpg +# mode: '0644' +# force: true + +- name: Add mongo ppa key (new way of adding an apt repository key) + ansible.builtin.shell: curl -fsSL https://pgp.mongodb.com/server-7.0.asc | gpg --dearmor -o /etc/apt/trusted.gpg.d/mongodb-server-7.0.gpg + args: + creates: /etc/apt/trusted.gpg.d/mongodb-server-7.0.gpg + + +- name: Add the mongo repository to the source list + ansible.builtin.shell: echo "deb [ arch=amd64,arm64 ] https://repo.mongodb.org/apt/ubuntu jammy/mongodb-org/7.0 multiverse" | tee /etc/apt/sources.list.d/mongodb-org-7.0.list + args: + creates: /etc/apt/sources.list.d/mongodb-org-7.0.list + +#- name: Add specified repository into sources list +# ansible.builtin.apt_repository: +# repo: deb-src http://repo.mongodb.org/apt/debian bookworm/mongodb-org/8.0 stable main +# state: present + +#- name: Update system after the addition of the mongo repo +# apt: +# update_cache: yes +# upgrade: dist + +- name: Update all packages after the addition of the mongo repo + ansible.builtin.apt: + name: "*" + state: latest + +- name: Mongodb-org installation + apt: + name: mongodb-org + state: latest + update_cache: yes + +#- name: Add server Ip in mongod.conf +# ansible.builtin.lineinfile: +# path: /etc/mongod.conf +# search_string: ' bindIp: 127.0.0.1' +# line: ' bindIp: 127.0.0.1, {{ mongodb_ip }}' + +- name: Start the mongodb daemon + ansible.builtin.shell: systemctl start mongod + +- name: Verify the mongodb service status + ansible.builtin.systemd: + state: started + name: mongod + register: mongo_status + +- debug: + var: mongo_status.status.ActiveState + +- name: Enable the mongod service and ensure it is not masked + ansible.builtin.systemd: + name: mongod + enabled: true + masked: no + + #- name: Check if user database admin exists + # become: false + # ansible.builtin.script: + # executable: python3 + # cmd: "check_admin_user.py {{ mongodb_ip }} {{ mongodb_admin }} {{mongodb_password}}" + # register: admin_exists + # #delegate_to: 127.0.0.1 + # ignore_errors: true + +# check_admin_user (check if admin user exists) +- name: Create working directory for mongo admin scripts + become: false + ansible.builtin.file: + path: /home/{{ user }}/tmp/ + state: directory + mode: '0755' + +- name: Installing workplace script librairies + become: false + ansible.builtin.pip: + name: pymongo + virtualenv: /home/{{ user }}/tmp/.venv + +- name: Upload check_admin_user python script + become: false + ansible.builtin.copy: + src: files/check_admin_user.py + dest: "/home/{{ user }}/tmp/" + mode: '0755' + +- name: Run check_admin_user python script + become: false + ansible.builtin.shell: "cd /home/{{ user }}/tmp && . .venv/bin/activate && ./check_admin_user.py {{ mongodb_ip }} {{ mongodb_admin }} {{mongodb_password}}" + register: admin_exists + args: + executable: /bin/bash + ignore_errors: true + +- debug: + var: admin_exists + +#- name: Add mongo database admin +# become: false +# ansible.builtin.script: +# executable: python3 +# cmd: "add_admin_user.py {{ mongodb_ip }} {{ mongodb_admin }} {{mongodb_password}}" +# delegate_to: 127.0.0.1 +# when: admin_exists.rc == 0 + +- name: Upload add_admin_user python script + become: false + ansible.builtin.copy: + src: files/add_admin_user.py + dest: "/home/{{ user }}/tmp/" + mode: '0755' + +- name: Installing workplace script librairies + become: false + ansible.builtin.pip: + name: pymongo + virtualenv: /home/{{ user }}/tmp/.venv + +- name: Run add_admin_user python script + ansible.builtin.shell: "cd /home/{{ user }}/tmp && . .venv/bin/activate && ./add_admin_user.py {{ mongodb_ip }} {{ mongodb_admin }} {{mongodb_password}}" + args: + executable: /bin/bash + when: admin_exists.rc == 0 + ignore_errors: true + +- name: Enable restricted authentication over mongodb + ansible.builtin.replace: + path: /etc/mongod.conf + regexp: '#security:' + replace: "security: \n authorization: enabled" + +- name: Restart the mongodb daemon + ansible.builtin.shell: systemctl restart mongod + +- name: Verify the mongodb service status + ansible.builtin.systemd: + state: started + name: mongod + register: mongo_status + +- debug: + var: mongo_status.status.ActiveState + diff --git a/roles/mongodb/vars/main.yml b/roles/mongodb/vars/main.yml new file mode 100644 index 0000000..aa9cb61 --- /dev/null +++ b/roles/mongodb/vars/main.yml @@ -0,0 +1,4 @@ +user: "{{ linux_user }}" +mongodb_ip: 127.0.0.1 +mongodb_admin: "{{ dbadmin }}" +mongodb_password: "{{ dbpassword }}" diff --git a/roles/nginx/handlers/main.yml b/roles/nginx/handlers/main.yml new file mode 100755 index 0000000..2f7e002 --- /dev/null +++ b/roles/nginx/handlers/main.yml @@ -0,0 +1,5 @@ +- name: restart nginx + service: + name: nginx + state: restarted + diff --git a/roles/nginx/tasks/main.yml b/roles/nginx/tasks/main.yml new file mode 100755 index 0000000..85158ff --- /dev/null +++ b/roles/nginx/tasks/main.yml @@ -0,0 +1,30 @@ +--- +- name: Install Nginx + apt: + name: + - nginx + state: present + + #- name: "create www directory" + # file: + # path: /var/www/{{ domain }} + # state: directory + # mode: '0775' + # owner: "{{ ansible_user }}" + # group: "{{ ansible_user }}" + +- name: delete default nginx site + file: + path: /etc/nginx/sites-enabled/default + state: absent + notify: restart nginx + +- name: copy nginx site.conf + template: + src: templates/site.conf.j2 + dest: /etc/nginx/sites-enabled/{{ domain }} + owner: root + group: root + mode: '0644' + notify: restart nginx + diff --git a/roles/nginx/templates/site.conf.j2 b/roles/nginx/templates/site.conf.j2 new file mode 100755 index 0000000..2b899e6 --- /dev/null +++ b/roles/nginx/templates/site.conf.j2 @@ -0,0 +1,16 @@ +server { + listen 80; + listen [::]:80; + server_name {{ domain }}; + #root /var/www/{{ domain }}; + location / { + # try_files $uri $uri/ =404; + proxy_pass http://localhost:5000; + } + + # location /.well-known/acme-challenge/ { + #  root /var/www/{{ domain }}; + # } + +} + diff --git a/roles/nginx/vars/main.yml b/roles/nginx/vars/main.yml new file mode 100644 index 0000000..22f6c7d --- /dev/null +++ b/roles/nginx/vars/main.yml @@ -0,0 +1,2 @@ +--- +domain: "{{ domain_name }}" diff --git a/roles/pip/readme.txt b/roles/pip/readme.txt new file mode 100644 index 0000000..f84bf65 --- /dev/null +++ b/roles/pip/readme.txt @@ -0,0 +1,6 @@ +requirements + pip + virtualenv + setuptools + + diff --git a/roles/pip/tasks/main.yml b/roles/pip/tasks/main.yml new file mode 100644 index 0000000..36059d5 --- /dev/null +++ b/roles/pip/tasks/main.yml @@ -0,0 +1,10 @@ +- name: Install python librairies into the specified virtual environment + ansible.builtin.pip: + requirements: /opt/app/requirements.txt + virtualenv: /opt/app/.venv + +# TODO: a mettre dans les handlers du role +# TODO: utiliser ansible systemctl pour cette task +#- name: Deployment - restart systemd app service +# shell: systemctl restart princelyacts.service + diff --git a/roles/run/tasks/main.yml b/roles/run/tasks/main.yml new file mode 100644 index 0000000..ddf89ae --- /dev/null +++ b/roles/run/tasks/main.yml @@ -0,0 +1,38 @@ +#- name: Execute the flask init command +# ansible.builtin.shell: | +# source bootstrap.sh +# flask db init +# args: +# chdir: /opt/app/ +# creates: actes_princiers.sqlite +# executable: /usr/bin/bash + +#- name: Start the flask run application +# ansible.builtin.shell: | +# source bootstrap.sh +# flask run & +# args: +# chdir: /opt/app/ +# executable: /usr/bin/bash + +- name: Template a file to /etc/file.conf + ansible.builtin.template: + src: templates/princelyacts.service.jinja + dest: /etc/systemd/system/princelyacts.service + #owner: "{{ system_user }}" + #group: "{{ system_user }}" + mode: '0777' + +- name: start systemd app service + systemd: name=princelyacts.service state=restarted enabled=yes + +- name: check if flask app runs + ansible.builtin.shell: netstat -tulnp | grep :5000 + register: flask_status + +- name: check if flask app is up + ansible.builtin.assert: + that: + - flask_status != 0 + fail_msg: "flask web application service is down (status:{!" + success_msg: "flask web application is up and running..." diff --git a/roles/run/templates/princelyacts.service.jinja b/roles/run/templates/princelyacts.service.jinja new file mode 100644 index 0000000..34a2458 --- /dev/null +++ b/roles/run/templates/princelyacts.service.jinja @@ -0,0 +1,20 @@ +[Unit] +Description=Flask Princely-Acts web appliance +After=network.target + +[Service] +User={{ system_user }} +Group={{ system_user }} +WorkingDirectory=/opt/app +Environment="PATH=/opt/app/.env/bin" +Environment="FLASK_ENV=production" +#Environment="FLASK_ENV=development" +# use in development environment +#Environment="FLASK_APP=index.py" +#ExecStart="flask run" +#ExecStart=/opt/app/.venv/bin/flask run +ExecStart=/opt/app/.venv/bin/gunicorn -w 3 -b 127.0.0.1:5000 app:app + +[Install] +WantedBy=multi-user.target + diff --git a/roles/run/vars/main.yml b/roles/run/vars/main.yml new file mode 100644 index 0000000..ed0feda --- /dev/null +++ b/roles/run/vars/main.yml @@ -0,0 +1,2 @@ +system_user: "{{ linux_user }}" + diff --git a/run_playbook.sh b/run_playbook.sh new file mode 100755 index 0000000..8c561f2 --- /dev/null +++ b/run_playbook.sh @@ -0,0 +1,4 @@ +# IMPORTANT : run the script `./vault decrypt` to unlock the encrypted files **before lauching this script** + +# ansible-playbook -i hosts -c local playbook.yml +ansible-playbook playbook.yml diff --git a/todo.txt b/todo.txt new file mode 100644 index 0000000..16a40fc --- /dev/null +++ b/todo.txt @@ -0,0 +1,21 @@ +TODO +=========== + +dernier sprint +--------------- + +à faire ensuite : + +- retirer le tag launch_application et le script et le playbook + +ufw +----- + +- for mongo +- for nginx + + - name: open firewall for nginx + ufw: + rule: allow + name: Nginx Full +