diff --git a/.ansible-lint b/.ansible-lint new file mode 100644 index 0000000..6ff89a9 --- /dev/null +++ b/.ansible-lint @@ -0,0 +1,7 @@ +--- +# created by 'IntelliJ Ansible Lint Plugin' +# +# check this website for detailed configuration options: +# https://ansible-lint.readthedocs.io/configuring/#ansible-lint-configuration + +profile: null diff --git a/defaults/main.yml b/defaults/main.yml index c30331f..c57a3c2 100644 --- a/defaults/main.yml +++ b/defaults/main.yml @@ -1,2 +1,7 @@ --- # defaults file for ansible_role_chill +add_postgres: false +database_version: 17 +database_image: "postgis/postgis:{{ database_version }}-3.4-alpine" +chill_image_nginx_name: nginx +chill_image_php_name: php diff --git a/handlers/main.yml b/handlers/main.yml index a08d64f..03a24d8 100644 --- a/handlers/main.yml +++ b/handlers/main.yml @@ -1,2 +1,13 @@ --- # handlers file for ansible_role_chill + +- name: Restart traefik + community.docker.docker_compose_v2: + project_src: "{{ install_dir }}/traefik" + state: present + recreate: auto + +# - name: Restart chill {{ item.chill_environment }} +# community.docker.docker_compose_v2: +# project_src: "{{ install_dir }}/{{ item['chill_environment'] }}" +# state: restarted diff --git a/meta/main.yml b/meta/main.yml index b123448..0353e4c 100644 --- a/meta/main.yml +++ b/meta/main.yml @@ -1,5 +1,7 @@ galaxy_info: - author: Julien Fastré + role_name: ansible_role_chill + namespace: champs-libres + author: Julien Fastré description: Install Chill using docker compose company: Champs-Libres @@ -8,9 +10,9 @@ galaxy_info: # issue_tracker_url: http://example.com/issue/tracker # Choose a valid license ID from https://spdx.org - license: AGPL-3.0-or-later + license: AGPL-3.0-or-later - min_ansible_version: 2.9 + min_ansible_version: '2.9' galaxy_tags: [] # List tags for your role here, one per line. A tag is a keyword that describes @@ -19,6 +21,3 @@ galaxy_info: # # NOTE: A tag is limited to a single word comprised of alphanumeric characters. # Maximum 20 tags per role. - - dependencies: - - geerlingguy.docker \ No newline at end of file diff --git a/tasks/chill/main.yml b/tasks/chill/main.yml index 48a19ed..65c6885 100644 --- a/tasks/chill/main.yml +++ b/tasks/chill/main.yml @@ -1,3 +1,58 @@ - name: Debug task ansible.builtin.debug: var: item + +- name: Create directories to store compose project + ansible.builtin.file: + path: "{{ install_dir }}/{{ item['chill_environment'] }}" + state: directory + mode: '0755' + owner: "{{ as_user }}" + +- name: Add compose.yml file + ansible.builtin.template: + src: compose.yaml + dest: "{{ install_dir }}/{{ item['chill_environment'] }}/compose.yaml" + owner: "{{ as_user }}" + mode: '0444' + +- name: Add application environment file + ansible.builtin.template: + src: env_file.env + dest: "{{ install_dir }}/{{ item['chill_environment'] }}/env_file.env" + owner: "{{ as_user }}" + mode: '0400' + +- name: Add postgresql environment file if need + ansible.builtin.template: + src: postgres.env + dest: "{{ install_dir }}/{{ item['chill_environment'] }}/postgres.env" + owner: "{{ as_user }}" + mode: '0400' + +- name: Add rabbitmq environment file + ansible.builtin.template: + src: rabbitmq.env + dest: "{{ install_dir }}/{{ item['chill_environment'] }}/rabbitmq.env" + owner: "{{ as_user }}" + mode: '0400' + +- name: Create directory for storing configuration + ansible.builtin.file: + path: "{{ install_dir }}/{{ item['chill_environment'] }}/config/prod" + state: directory + owner: "{{ as_user }}" + mode: '0400' + +- name: Copy configuration files + ansible.builtin.template: + src: "config/prod/{{ file }}" + dest: "{{ install_dir }}/{{ item['chill_environment'] }}/config/prod/{{ file }}" + owner: "{{ as_user }}" + mode: '0444' + loop: + - lexik_jwt_authentication.yaml + - messenger.yaml + - monolog.yaml + loop_control: + loop_var: file diff --git a/tasks/main.yml b/tasks/main.yml index 034f329..070dad8 100644 --- a/tasks/main.yml +++ b/tasks/main.yml @@ -1,7 +1,6 @@ # code: language=ansible --- -# install docker on the machine - name: Install docker and docker compose plugin ansible.builtin.include_role: name: geerlingguy.docker @@ -14,6 +13,33 @@ docker_install_compose_plugin: true docker_add_repo: true +- name: Print all available facts + ansible.builtin.debug: + var: ansible_facts + +- name: Authenticate against private docker registry + community.docker.docker_login: + registry_url: "{{ registry_url }}" + username: "{{ registry_username }}" + password: "{{ registry_password }}" + +- name: Authenticate against docker hub + community.docker.docker_login: + username: "{{ docker_hub_username }}" + password: "{{ docker_hub_token }}" + + +- name: Create log directory + ansible.builtin.file: + path: /var/logs/chill + state: directory + owner: 33 + group: 33 + mode: '0444' + +- name: Install traefik + ansible.builtin.include_tasks: traefik.yml + - name: Install individual chill ansible.builtin.include_tasks: chill/main.yml with_items: "{{ chills }}" diff --git a/tasks/traefik.yml b/tasks/traefik.yml new file mode 100644 index 0000000..739579c --- /dev/null +++ b/tasks/traefik.yml @@ -0,0 +1,15 @@ +- name: Create directories to store compose project + ansible.builtin.file: + path: "{{ install_dir }}/traefik" + state: directory + mode: '0755' + owner: "{{ as_user }}" + +- name: Install compose file for traefik + ansible.builtin.template: + src: traefik-compose.yaml + dest: "{{ install_dir }}/traefik/compose.yaml" + mode: '0444' + owner: "{{ as_user }}" + notify: + - Restart traefik diff --git a/templates/compose.yaml b/templates/compose.yaml new file mode 100644 index 0000000..ddd5eb6 --- /dev/null +++ b/templates/compose.yaml @@ -0,0 +1,104 @@ +services: + + frontend: + image: {{ registry_url }}/{{ registry_project }}/{{ chill_image_nginx_name }}:{{ item.chill_image_tag }} + links: + - app:php + labels: + - "traefik.enable=true" + - "traefik.http.routers.frontend.rule=Host(`{{ item.host }}`)" + - "traefik.http.routers.frontend.entrypoints=web" + - "traefik.docker.network=traefik" + networks: + - traefik + - default + + app: + image: {{ registry_url }}/{{ registry_project }}/{{ chill_image_php_name }}:{{ item.chill_image_tag }} + env_file: + - env_file.env + volumes: + - './config/prod:/var/www/app/config/packages/prod:ro' + - './var:/var/www/app/var:rw' + - '/var/logs/chill:/var/www/app/logs' + links: + - redis + - relatorio + - rabbitmq + {% if item.add_postgres -%} + - database + {%- endif %} + + networks: + - default + + {% if item.add_postgres %} + + database: + image: "{{ database_image }}" + env_file: + - postgres.env + environment: + POSTGRES_DB: ${POSTGRES_DB:-app} + # You should definitely change the password in production + POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:-!ChangeMe!} + POSTGRES_USER: ${POSTGRES_USER:-app} + volumes: + - ./docker/db/data:/var/lib/postgresql/data:rw + networks: + - default + + {% endif %} + + ###> chill-project/chill-bundles ### + redis: + image: redis + networks: + - default + + relatorio: + image: registry.gitlab.com/champs-libres/public/relatorio-tornado/app:latest + networks: + - default + ###< chill-project/chill-bundles ### + +# sign-worker: +# image: h3m6q87t.gra7.container-registry.ovh.net/sign-pdf-worker/worker:latest +# environment: +# AMQP_URL: amqp://guest:guest@rabbitmq:5672/%2f/to_python_sign +# LOG_LEVEL: INFO +# PKCS12_PATH: /etc/sign-pdf/dummy.p12 +# TIMESTAMP_URL: http://freetsa.org/tsr +# QUEUE_IN: to_python_sign +# EXCHANGE_OUT: signed_docs +# OUT_ROUTING_KEY: signed_doc +# TSA_CERT_CHAIN: /etc/sign-pdf/tsa/tsa-chain.pem +# TSA_CONFIG_PATH: /etc/sign-pdf/rootca.conf +# TSA_KEY_PASSWORD: "5678" +# volumes: +# - "./resources/dev-certificate/dummy.p12:/etc/sign-pdf/dummy.p12:ro" +# - "./resources/dev-certificate/rootca.conf:/etc/sign-pdf/rootca.conf:ro" +# - "./resources/dev-certificate/tsa:/etc/sign-pdf/tsa:ro" +# - "./resources/dev-certificate/tsa_serial:/var/lib/tsa/tsa_serial:rw" +# links: +# - rabbitmq +# depends_on: +# rabbitmq: +# condition: service_healthy + + rabbitmq: + image: rabbitmq:3-management-alpine + env_file: + - rabbitmq.env + healthcheck: + test: rabbitmq-diagnostics -q ping + interval: 30s + timeout: 30s + retries: 3 + networks: + - default + +networks: + traefik: + external: true + default: \ No newline at end of file diff --git a/templates/compose.yml b/templates/compose.yml deleted file mode 100644 index 6eee553..0000000 --- a/templates/compose.yml +++ /dev/null @@ -1,58 +0,0 @@ -services: - ###> doctrine/doctrine-bundle ### - database: - image: postgis/postgis:${POSTGRES_VERSION:-16}-3.4-alpine - environment: - POSTGRES_DB: ${POSTGRES_DB:-app} - # You should definitely change the password in production - POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:-!ChangeMe!} - POSTGRES_USER: ${POSTGRES_USER:-app} - volumes: - # - database_data:/var/lib/postgresql/data:rw - # You may use a bind-mounted host directory instead, so that it is harder to accidentally remove the volume and lose all your data! - - ./docker/db/data:/var/lib/postgresql/data:rw - ###< doctrine/doctrine-bundle ### - - ###> chill-project/chill-bundles ### - redis: - image: redis - relatorio: - image: registry.gitlab.com/champs-libres/public/relatorio-tornado/app:latest - ###< chill-project/chill-bundles ### - - sign-worker: - image: h3m6q87t.gra7.container-registry.ovh.net/sign-pdf-worker/worker:latest - environment: - AMQP_URL: amqp://guest:guest@rabbitmq:5672/%2f/to_python_sign - LOG_LEVEL: INFO - PKCS12_PATH: /etc/sign-pdf/dummy.p12 - TIMESTAMP_URL: http://freetsa.org/tsr - QUEUE_IN: to_python_sign - EXCHANGE_OUT: signed_docs - OUT_ROUTING_KEY: signed_doc - TSA_CERT_CHAIN: /etc/sign-pdf/tsa/tsa-chain.pem - TSA_CONFIG_PATH: /etc/sign-pdf/rootca.conf - TSA_KEY_PASSWORD: "5678" - volumes: - - "./resources/dev-certificate/dummy.p12:/etc/sign-pdf/dummy.p12:ro" - - "./resources/dev-certificate/rootca.conf:/etc/sign-pdf/rootca.conf:ro" - - "./resources/dev-certificate/tsa:/etc/sign-pdf/tsa:ro" - - "./resources/dev-certificate/tsa_serial:/var/lib/tsa/tsa_serial:rw" - links: - - rabbitmq - depends_on: - rabbitmq: - condition: service_healthy - - rabbitmq: - image: rabbitmq:3-management-alpine - healthcheck: - test: rabbitmq-diagnostics -q ping - interval: 30s - timeout: 30s - retries: 3 - -volumes: - ###> doctrine/doctrine-bundle ### - database_data: -###< doctrine/doctrine-bundle ### diff --git a/templates/config/prod/lexik_jwt_authentication.yaml b/templates/config/prod/lexik_jwt_authentication.yaml new file mode 100644 index 0000000..d17e32a --- /dev/null +++ b/templates/config/prod/lexik_jwt_authentication.yaml @@ -0,0 +1,9 @@ +lexik_jwt_authentication: + # in production, the secret must be located in an environment variable + # for converting the file to a raw variable, use this command: + # + # cat path/to/private_or_public.pem | base64 -w0 + # + # then copy past the printed string into the dedicated environment variable + secret_key: '%env(base64:resolve:JWT_SECRET_KEY)%' + public_key: '%env(base64:resolve:JWT_PUBLIC_KEY)%' diff --git a/templates/config/prod/messenger.yaml b/templates/config/prod/messenger.yaml new file mode 100644 index 0000000..04f95a0 --- /dev/null +++ b/templates/config/prod/messenger.yaml @@ -0,0 +1,15 @@ +framework: + messenger: + transports: + async: + dsn: '%env(RABBITMQ_URL)%/async' + options: + exchange: + name: async + type: fanout + queues: + async: ~ + auto_setup: true + priority: '%env(RABBITMQ_URL)%/priority' + failed: 'doctrine://default?queue_name=failed' + sync: 'sync://' \ No newline at end of file diff --git a/templates/config/prod/monolog.yaml b/templates/config/prod/monolog.yaml new file mode 100644 index 0000000..916479b --- /dev/null +++ b/templates/config/prod/monolog.yaml @@ -0,0 +1,19 @@ +parameters: + log_prefix: {{ item.chill_environment }} +monolog: + handlers: + default_log: + type: stream + path: "%kernel.logs_dir%/%log_prefix%-privacy.log" + level: info + channels: ['chill'] + chill_log: + type: stream + path: "%kernel.logs_dir%/%log_prefix%-default.log" + level: info + channels: ['!event', '!doctrine', '!console', '!chill'] + console: + type: console + process_psr_3_messages: false + channels: ['!event', '!doctrine', '!console'] + bubble: false diff --git a/templates/env_file.env b/templates/env_file.env new file mode 100644 index 0000000..c1d835a --- /dev/null +++ b/templates/env_file.env @@ -0,0 +1,35 @@ +APP_ENV=prod +APP_DEBUG=false +TRUSTED_PROXIES=10.0.0.0/8,192.168.0.0/16,172.16.0.0/16 +# GELF_HOST=gelf +REDIS_HOST=redis +REDIS_PORT=6379 +REDIS_URL=redis://redis:6379 +RELATORIO_HOST=relatorio +RELATORIO_PORT=8888 +TRUSTED_HOSTS={{ item.chill_config.trusted_hosts }} +DATABASE_HOST={{ item.chill_config.database_host }} +DATABASE_PORT={{ item.chill_config.database_port }} +DATABASE_NAME={{ item.chill_config.database_name }} +DATABASE_USER={{ item.chill_config.database_user }} +DATABASE_VERSION={{ item.chill_config.database_version }} +LOCALE=fr +MAILER_PROTOCOL=smtp +MAILER_USER={{ item.chill_config.mailer_user }} +MAILER_HOST={{ item.chill_config.mailer_host }} +MAILER_PORT={{ item.chill_config.mailer_port }} +NOTIFICATION_HOST={{ item.chill_config.notification_host }} +NOTIFICATION_FROM_EMAIL={{ item.chill_config.notification_from_email }} +ASYNC_UPLOAD_TEMP_URL_BASE_PATH= +ASYNC_UPLOAD_TEMP_URL_CONTAINER= +ASYNC_UPLOAD_TEMP_URL_KEY= +DEFAULT_CARRIER_CODE=FR +APP_SECRET={{ item.chill_config.app_secret }} +ADMIN_PASSWORD={{ item.chill_config.admin_password }} +MAILER_DSN={{ item.chill_config.mailer_dsn }} +MAILER_URL={{ item.chill_config.mailer_url }} +JWT_PASSPHRASE={{ item.chill_config.jwt_passphrase }} +JWT_SECRET_KEY={{ item.chill_config.jwt_secret_key }} +JWT_PUBLIC_KEY={{ item.chill_config.jwt_public_key }} +RABBITMQ_URL=amqp://{{ item.chill_config.rabbitmq_user }}:{{ item.chill_config.rabbitmq_password }}@rabbitmq/%2f +DATABASE_URL=postgres://{{ item.chill_config.database_user }}:{{ item.chill_config.database_password }}@{% if item.add_postgres %}database:5432{% else %}{{ item.chill_config.database_url }}{% endif %}/{{ item.chill_config.database_name }}?sslmode=disable&charset=utf8&serverVersion={{ item.chill_config.database_version }} \ No newline at end of file diff --git a/templates/jwt_private.pem b/templates/jwt_private.pem new file mode 100644 index 0000000..e69de29 diff --git a/templates/jwt_public.pem b/templates/jwt_public.pem new file mode 100644 index 0000000..e69de29 diff --git a/templates/postgres.env b/templates/postgres.env new file mode 100644 index 0000000..0483cf6 --- /dev/null +++ b/templates/postgres.env @@ -0,0 +1,3 @@ +POSTGRES_DB={{ item.chill_config.database_name }} +POSTGRES_USER={{ item.chill_config.database_user }} +POSTGRES_PASSWORD={{ item.chill_config.database_password }} diff --git a/templates/rabbitmq.env b/templates/rabbitmq.env new file mode 100644 index 0000000..b77ad08 --- /dev/null +++ b/templates/rabbitmq.env @@ -0,0 +1,2 @@ +RABBITMQ_DEFAULT_USER={{ item.chill_config.rabbitmq_user }} +RABBITMQ_DEFAULT_PASS={{ item.chill_config.rabbitmq_password }} \ No newline at end of file diff --git a/templates/traefik-compose.yaml b/templates/traefik-compose.yaml new file mode 100644 index 0000000..ecef904 --- /dev/null +++ b/templates/traefik-compose.yaml @@ -0,0 +1,25 @@ +services: + reverse-proxy: + # The official v3 Traefik docker image + image: traefik:v3.2 + # Enables the web UI and tells Traefik to listen to docker + command: + - "--log.level=debug" + - "--api.insecure=true" + - "--providers.docker=true" + - "--providers.docker.exposedByDefault=false" + - "--entryPoints.web.address=:80" + ports: + # The HTTP port + - "80:80" + # The Web UI (enabled by --api.insecure=true) + - "8080:8080" + volumes: + # So that Traefik can listen to the Docker events + - /var/run/docker.sock:/var/run/docker.sock + networks: + - traefik + +networks: + traefik: + name: traefik \ No newline at end of file