From 0016b318e2b3aa12bcab088cc7a81b436f398465 Mon Sep 17 00:00:00 2001 From: Ethan Paul <24588726+enpaul@users.noreply.github.com> Date: Tue, 8 Dec 2020 22:21:03 -0500 Subject: [PATCH] Implement docker compose app deployment playbook --- en1.yml | 5 +- playbooks/configure-webproxy.yml | 42 +++- playbooks/deploy-compose.yml | 68 ++++++ resources/docker-compose/bitwarden.yaml.j2 | 257 +++++++++++++++++++++ resources/nginx/bitwarden.nginx.conf.j2 | 31 +++ resources/{ => nginx}/nginx.conf | 0 6 files changed, 392 insertions(+), 11 deletions(-) create mode 100644 playbooks/deploy-compose.yml create mode 100644 resources/docker-compose/bitwarden.yaml.j2 create mode 100644 resources/nginx/bitwarden.nginx.conf.j2 rename resources/{ => nginx}/nginx.conf (100%) diff --git a/en1.yml b/en1.yml index 1e39d1e..26e7816 100644 --- a/en1.yml +++ b/en1.yml @@ -7,9 +7,6 @@ all: update: false clean: false - omni_host_swarm_controller: jupiter - omni_host_webproxy: jupiter - children: servers: @@ -59,6 +56,7 @@ all: virtualization: hosts: jupiter: + omni_docker_configs: /etc/omni/compose omni_docker_swarm_iface: eno2 children: virtualization_worker: @@ -73,6 +71,7 @@ all: datastore_arbiter: hosts: jupiter: + omni_datastore_mount: /mnt/datastore omni_gluster_brick: mount: /mnt/brick0 fs: xfs diff --git a/playbooks/configure-webproxy.yml b/playbooks/configure-webproxy.yml index 0385821..64e6c9f 100644 --- a/playbooks/configure-webproxy.yml +++ b/playbooks/configure-webproxy.yml @@ -10,14 +10,6 @@ tasks: - import_tasks: tasks/nginx/install.yml - - name: Install configuration - become: true - copy: - src: nginx.conf - dest: /etc/nginx/nginx.conf - notify: - - restart-nginx - - name: Set required SELinux options become: true seboolean: @@ -26,3 +18,37 @@ state: true notify: - restart-nginx + + +- name: Configure Nginx + hosts: jupiter + vars_files: + - vars/applications.yml + vars: + _letsencrypt_cert_dir: /etc/letsencrypt/live + handlers: + - name: restart-nginx + import_tasks: tasks/nginx/services.yml + tasks: + - name: Install server configuration + become: true + copy: + src: nginx/nginx.conf + dest: /etc/nginx/nginx.conf + notify: + - restart-nginx + + - name: Install application configurations + when: item.value.published.host is defined + become: true + template: + src: nginx/{{ item.key }}.nginx.conf.j2 + dest: /etc/nginx/conf.d/{{ item.key }}.conf + owner: nginx + group: "{{ ansible_user }}" + mode: 0755 + loop: "{{ omni_compose_apps | dict2items }}" + loop_control: + label: "{{ item.key }} ({{ item.value.published.host | default('none') }})" + notify: + - restart-nginx diff --git a/playbooks/deploy-compose.yml b/playbooks/deploy-compose.yml new file mode 100644 index 0000000..2a93b98 --- /dev/null +++ b/playbooks/deploy-compose.yml @@ -0,0 +1,68 @@ +--- +- name: Prompt for input + hosts: all + tags: + - always + gather_facts: false + vars_prompt: + - name: application + prompt: Enter name of application stack to deploy + private: false + vars_files: + - vars/applications.yml + tasks: + - name: Validate user input + assert: + that: application in omni_compose_apps.keys() + + - name: Set facts for usage later + set_fact: + _runtime_application: "{{ application }}" + + +- import_playbook: initialize.yml + + +- name: Configure datastore + hosts: jupiter + vars_files: + - vars/applications.yml + - vars/secrets/applications.yml + tasks: + - name: Create application datastore directory + become: true + file: + path: "{{ omni_datastore_mount }}{{ omni_compose_apps[_runtime_application].datastore }}" + state: directory + owner: "{{ omni_compose_apps[_runtime_application].account.name }}" + group: "{{ omni_compose_apps[_runtime_application].account.name }}" + mode: 0750 + + +- name: Configure docker stack + hosts: jupiter + vars_files: + - vars/applications.yml + - vars/secrets/applications.yml + tasks: + - name: Create compose configuration directory + become: true + file: + path: "{{ omni_docker_configs }}/{{ _runtime_application }}" + state: directory + owner: "{{ ansible_user }}" + group: "{{ ansible_user }}" + mode: 0700 + + - name: Install docker-compose file + become: true + template: + src: docker-compose/bitwarden.yaml.j2 + dest: "{{ omni_docker_configs }}/{{ _runtime_application }}/docker-compose.yaml" + + - name: Deploy the stack + docker_stack: + name: "{{ _runtime_application }}" + state: present + compose: + - "{{ omni_docker_configs }}/{{ _runtime_application }}/docker-compose.yaml" diff --git a/resources/docker-compose/bitwarden.yaml.j2 b/resources/docker-compose/bitwarden.yaml.j2 new file mode 100644 index 0000000..fe84f3d --- /dev/null +++ b/resources/docker-compose/bitwarden.yaml.j2 @@ -0,0 +1,257 @@ +--- +version: "{{ omni_compose_version | string }}" + + +x-global-env: &globalenv + LOCAL_UID: "{{ omni_compose_apps.bitwarden.account.uid | string }}" + LOCAL_GID: "{{ omni_compose_apps.bitwarden.account.uid | string}}" + ASPNETCORE_ENVIRONMENT: Production + globalSettings__selfHosted: "true" + globalSettings__baseServiceUri__vault: https://{{ omni_compose_apps.bitwarden.published.host }} + globalSettings__baseServiceUri__api: https://{{ omni_compose_apps.bitwarden.published.host }}/api + globalSettings__baseServiceUri__identity: https://{{ omni_compose_apps.bitwarden.published.host }}/identity + globalSettings__baseServiceUri__admin: https://{{ omni_compose_apps.bitwarden.published.host }}/admin + globalSettings__baseServiceUri__notifications: https://{{ omni_compose_apps.bitwarden.published.host }}/notifications + globalSettings__baseServiceUri__internalNotifications: http://bitwarden_notifications:5000 + globalSettings__baseServiceUri__internalAdmin: http://bitwarden_admin:5000 + globalSettings__baseServiceUri__internalIdentity: http://bitwarden_identity:5000 + globalSettings__baseServiceUri__internalApi: http://bitwarden_api:5000 + globalSettings__baseServiceUri__internalVault: http://bitwarden_web:5000 + globalSettings__pushRelayBaseUri: https://push.bitwarden.com + globalSettings__installation__identityUri: https://identity.bitwarden.com + globalSettings__sqlServer__connectionString: "Data Source=tcp:mssql,1433;Initial Catalog=vault;Persist Security Info=False;User ID=sa;Password=e934c0bb-3b5a-4e6b-b525-cd6d83004e1a;MultipleActiveResultSets=False;Connect Timeout=30;Encrypt=True;TrustServerCertificate=True" + globalSettings__identityServer__certificatePassword: {{ omni_compose_app_secrets.bitwarden.identity_server_certificate_password }} + globalSettings__attachment__baseDirectory: /etc/bitwarden/core/attachments + globalSettings__attachment__baseUrl: https://{{ omni_compose_apps.bitwarden.published.host }}/attachments + globalSettings__dataProtection__directory: /etc/bitwarden/core/aspnet-dataprotection + globalSettings__logDirectory: /etc/bitwarden/logs + globalSettings__licenseDirectory: /etc/bitwarden/core/licenses + globalSettings__internalIdentityKey: {{ omni_compose_app_secrets.bitwarden.internal_identity_key }} + globalSettings__duo__aKey: {{ omni_compose_app_secrets.bitwarden.duo_akey }} + globalSettings__installation__id: {{ omni_compose_app_secrets.bitwarden.installation_id }} + globalSettings__installation__key: {{ omni_compose_app_secrets.bitwarden.installation_key }} + globalSettings__yubico__clientId: REPLACE + globalSettings__yubico__key: REPLACE + globalSettings__mail__replyToEmail: noreply@enp.one + globalSettings__mail__smtp__host: REPLACE + globalSettings__mail__smtp__port: "587" + globalSettings__mail__smtp__ssl: "false" + globalSettings__mail__smtp__username: REPLACE + globalSettings__mail__smtp__password: REPLACE + globalSettings__disableUserRegistration: "false" + globalSettings__hibpApiKey: REPLACE + adminSettings__admins: "" + + +volumes: + bitwarden-db-data: + name: datastore{{ omni_compose_apps.bitwarden.datastore }}/mssql/data + driver: glusterfs + bitwarden-db-backup: + name: datastore{{ omni_compose_apps.bitwarden.datastore }}/mssql/backup + bitwarden-nginx-data: + name: datastore{{ omni_compose_apps.bitwarden.datastore }}/nginx + driver: glusterfs + bitwarden-web: + name: datastore{{ omni_compose_apps.bitwarden.datastore }}/web + driver: glusterfs + bitwarden-ssl: + name: datastore{{ omni_compose_apps.bitwarden.datastore }}/ssl + driver: glusterfs + bitwarden-ca-certs: + name: datastore{{ omni_compose_apps.bitwarden.datastore }}/ca-certificates + driver: glusterfs + bitwarden-core: + name: datastore{{ omni_compose_apps.bitwarden.datastore }}/core + driver: glusterfs + bitwarden-identity: + name: datastore{{ omni_compose_apps.bitwarden.datastore }}/identity + driver: glusterfs + bitwarden-logs-api: + name: datastore{{ omni_compose_apps.bitwarden.datastore }}/logs/api + driver: glusterfs + bitwarden-logs-db: + name: datastore{{ omni_compose_apps.bitwarden.datastore }}/logs/mssql + driver: glusterfs + bitwarden-logs-identity: + name: datastore{{ omni_compose_apps.bitwarden.datastore }}/logs/identity + driver: glusterfs + bitwarden-logs-nginx: + name: datastore{{ omni_compose_apps.bitwarden.datastore }}/logs/nginx + driver: glusterfs + bitwarden-logs-admin: + name: datastore{{ omni_compose_apps.bitwarden.datastore }}/logs/admin + driver: glusterfs + bitwarden-logs-icons: + name: datastore{{ omni_compose_apps.bitwarden.datastore }}/logs/icons + driver: glusterfs + bitwarden-logs-notifications: + name: datastore{{ omni_compose_apps.bitwarden.datastore }}/logs/notifications + driver: glusterfs + bitwarden-logs-events: + name: datastore{{ omni_compose_apps.bitwarden.datastore }}/logs/events + driver: glusterfs + + +networks: + bitwarden_internal: + internal: true + name: bitwarden_internal + driver: overlay + ipam: + driver: default + config: + - subnet: {{ omni_compose_apps.bitwarden.networks.internal }} + bitwarden_external: + internal: false + name: bitwarden_external + driver: overlay + ipam: + driver: default + config: + - subnet: {{ omni_compose_apps.bitwarden.networks.external }} + + +services: + mssql: + image: bitwarden/mssql:{{ omni_compose_apps.bitwarden.versions.mssql | default(omni_compose_apps.bitwarden.versions.default) }} + stop_grace_period: 60s + networks: + - bitwarden_internal + volumes: + - bitwarden-db-data:/var/opt/mssql/data + - bitwarden-db-backup:/etc/bitwarden/mssql/backups + - bitwarden-logs-db:/var/opt/mssql/log + environment: + LOCAL_UID: "{{ omni_compose_apps.bitwarden.account.uid | string }}" + LOCAL_GID: "{{ omni_compose_apps.bitwarden.account.uid | string }}" + ACCEPT_EULA: "Y" + MSSQL_PID: Express + SA_PASSWORD: {{ omni_compose_app_secrets.bitwarden.mssql_sa_password }} + deploy: + replicas: 1 + + web: + image: bitwarden/web:{{ omni_compose_apps.bitwarden.versions.web | default(omni_compose_apps.bitwarden.versions.default) }} + networks: + - bitwarden_internal + volumes: + - bitwarden-web:/etc/bitwarden/web + environment: *globalenv + deploy: + replicas: 1 + + attachments: + image: bitwarden/attachments:{{ omni_compose_apps.bitwarden.versions.attachments | default(omni_compose_apps.bitwarden.versions.default) }} + networks: + - bitwarden_internal + volumes: + - bitwarden-core:/etc/bitwarden/core + environment: *globalenv + deploy: + replicas: 1 + + api: + image: bitwarden/api:{{ omni_compose_apps.bitwarden.versions.api | default(omni_compose_apps.bitwarden.versions.default) }} + volumes: + - bitwarden-core:/etc/bitwarden/core + - bitwarden-ca-certs:/etc/bitwarden/ca-certificates + - bitwarden-logs-api:/etc/bitwarden/logs + environment: *globalenv + networks: + - bitwarden_external + - bitwarden_internal + deploy: + replicas: 1 + + identity: + image: bitwarden/identity:{{ omni_compose_apps.bitwarden.versions.identity | default(omni_compose_apps.bitwarden.versions.default) }} + volumes: + - bitwarden-identity:/etc/bitwarden/identity + - bitwarden-core:/etc/bitwarden/core + - bitwarden-ca-certs:/etc/bitwarden/ca-certificates + - bitwarden-logs-identity:/etc/bitwarden/logs + environment: *globalenv + networks: + - bitwarden_external + - bitwarden_internal + deploy: + replicas: 1 + + admin: + image: bitwarden/admin:{{ omni_compose_apps.bitwarden.versions.admin | default(omni_compose_apps.bitwarden.versions.default) }} + depends_on: + - mssql + volumes: + - bitwarden-core:/etc/bitwarden/core + - bitwarden-ca-certs:/etc/bitwarden/ca-certificates + - bitwarden-logs-admin:/etc/bitwarden/logs + environment: *globalenv + networks: + - bitwarden_external + - bitwarden_internal + deploy: + replicas: 1 + + icons: + image: bitwarden/icons:{{ omni_compose_apps.bitwarden.versions.icons | default(omni_compose_apps.bitwarden.versions.default) }} + volumes: + - bitwarden-ca-certs:/etc/bitwarden/ca-certificates + - bitwarden-logs-icons:/etc/bitwarden/logs + environment: *globalenv + networks: + - bitwarden_external + - bitwarden_internal + deploy: + replicas: 1 + + notifications: + image: bitwarden/notifications:{{ omni_compose_apps.bitwarden.versions.notifications | default(omni_compose_apps.bitwarden.versions.default) }} + volumes: + - bitwarden-ca-certs:/etc/bitwarden/ca-certificates + - bitwarden-logs-notifications:/etc/bitwarden/logs + environment: *globalenv + networks: + - bitwarden_external + - bitwarden_internal + deploy: + replicas: 1 + + events: + image: bitwarden/events:{{ omni_compose_apps.bitwarden.versions.events | default(omni_compose_apps.bitwarden.versions.default) }} + volumes: + - bitwarden-ca-certs:/etc/bitwarden/ca-certificates + - bitwarden-logs-events:/etc/bitwarden/logs + environment: *globalenv + networks: + - bitwarden_external + - bitwarden_internal + deploy: + replicas: 1 + + nginx: + image: bitwarden/nginx:{{ omni_compose_apps.bitwarden.versions.nginx | default(omni_compose_apps.bitwarden.versions.default) }} + depends_on: + - web + - admin + - api + - identity + ports: + - published: {{ omni_compose_apps.bitwarden.published.ports.8080 }} + target: 8080 + protocol: tcp + mode: ingress + - published: {{ omni_compose_apps.bitwarden.published.ports.8443 }} + target: 8443 + protocol: tcp + mode: ingress + volumes: + - bitwarden-nginx-data:/etc/bitwarden/nginx + - bitwarden-ssl:/etc/ssl + - bitwarden-logs-nginx:/var/log/nginx + environment: *globalenv + networks: + - bitwarden_external + - bitwarden_internal + deploy: + replicas: 1 diff --git a/resources/nginx/bitwarden.nginx.conf.j2 b/resources/nginx/bitwarden.nginx.conf.j2 new file mode 100644 index 0000000..3f3da70 --- /dev/null +++ b/resources/nginx/bitwarden.nginx.conf.j2 @@ -0,0 +1,31 @@ +# Ansible managed file +# DO NOT MANUALLY EDIT +# +server { + server_name {{ omni_compose_apps.bitwarden.published.host }}; + listen 443 ssl; + root /usr/share/nginx/html; + + location / { + proxy_pass http://localhost:{{ omni_compose_apps.bitwarden.published.8080 }}/; + proxy_set_header Host $host; + } + + ssl_certificate /etc/letsencrypt/live/{{ omni_compose_apps.bitwarden.published.host }}/fullchain.pem; + ssl_certificate_key /etc/letsencrypt/live/{{ omni_compose_apps.bitwarden.published.host }}/privkey.pem; + include /etc/letsencrypt/options-ssl-nginx.conf; + ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; +} + +server { + server_name {{ omni_compose_apps.bitwarden.published.host }}; + listen 80; + root /usr/share/nginx/html; + + if ($host = {{ omni_compose_apps.bitwarden.published.host }}) { + return 301 https://$host$request_uri; + } + return 404; +} +# +# EOF diff --git a/resources/nginx.conf b/resources/nginx/nginx.conf similarity index 100% rename from resources/nginx.conf rename to resources/nginx/nginx.conf