Linux OS/관리

Ansible를 이용한 Apache 서버 제어 (VirtualHost, SSL)

서버엔지니어 2023. 11. 13.
728x90

서버 : Ansible 마스터서버 1대

호스트서버 : WEB 서버 1대 / 추후 DB 서버 1대

OS = Ubuntu 22.04

 

[마스터서버, 호스트공통사항]

apt update -y
apt upgrade -y
apt install -y ansible sshpass

 

[마스터서버]
ssh-keygen
ssh-copy-id root@호스트서버IP

 

mkdir /root//ansible_project

 

 

 

vi /root/ansible_project/inventory.ini

[master]
master ansible_host=10.0.0.2

[web]
web ansible_host=10.0.0.3

[db]
db ansible_host=10.0.0.4

 

디렉토리 구조 만들기

mkdir -p playbooks/handlers/ playbooks/templates/ playbooks/roles/common/tasks playbooks/roles/web/tasks playbooks/db/common/tasks

 

 

playbooks 설정

 

 

vi /root/ansible_project/playbooks/configure_web.yml

- name: Configure Web Server
  hosts: web
  become: true
  roles:
    - common
    - web
  handlers:
  - name: Reload Apache
    import_tasks: handlers/main.yml

 

 

vi /root/ansible_project/playbooks/configure_db.yml

- name: Configure Database Server
  hosts: db
  become: true
  roles:
    - common
    - db

 

 

Apache Virtual Host 설정

vi /root/ansible_project/playbooks/add_vhost.yml

- name: Add Virtual Hosts
  hosts: web
  become: true
  vars:
    domain_name: "93it-serverengineer.kr"
    document_root: "/home/93it/www"
  tasks:
    - name: Create directory for the virtual host
      file:
        path: "{{ document_root }}"
        state: directory
        mode: '0755'
      become: true

    - name: Create index.html file
      copy:
   web     content: "93it-serverengineer.kr index.html"
        dest: "{{ document_root }}/index.html"
      become: true

    - name: Create phpinfo.php file
      copy:
        content: "93it-serverengineer.kr phpinfo.php <?php phpinfo();?>"
        dest: "{{ document_root }}/phpinfo.php"
      become: true

    - name: Create Apache virtual host configuration
      template:
        src: vhost.conf.j2
        dest: "/etc/apache2/sites-available/{{ domain_name }}.conf"
      notify:
        - Reload Apache

    - name: Enable the virtual host
      command: "a2ensite {{ domain_name }}"
      args:
        creates: "/etc/apache2/sites-enabled/{{ domain_name }}.conf"
      notify:
        - Reload Apache
  handlers:
  - name: Reload Apache
    import_tasks: handlers/main.yml

 

 

SSL 노트 설정

vi /root/ansible_project/playbooks/letsencrypt.yml

---
- name: Add Virtual Hosts and SSL Certificates
  hosts: web
  become: true
  vars:
    domains:
      - "93it-serverengineer.kr"
    document_root: "/home/93it/www"

# letsencrypt.yml

  handlers:
    - import_tasks: handlers/main.yml

  tasks:
    - name: Install Certbot and Apache plugin
      apt:
        name:
          - certbot
          - python3-certbot-apache
        state: present

    - name: Check if Certbot renewal configuration file exists
      stat:
        path: "/etc/letsencrypt/renewal/{{ item }}.conf"
      register: certbot_renewal_info
      with_items: "{{ domains }}"
      ignore_errors: yes

    - debug:
        var: certbot_renewal_info

    - name: Renew Let's Encrypt SSL certificates if domains.conf doesn't exist
      command: "certbot certonly --webroot -w {{ document_root }} -d {{ item }} --email resave177@naver.com --agree-tos --no-eff-email --rsa-key-size 4096"
      with_items: "{{ domains }}"
      when: "not certbot_renewal_info is defined or (certbot_renewal_info.results | default([]) | map(attribute='stat.exists') | bool)"
      ignore_errors: yes

    - name: Create SSL virtual host configuration
      template:
        src: ssl_vhost.conf.j2
        dest: "/etc/apache2/sites-available/{{ item }}-ssl.conf"
      with_items: "{{ domains }}"
      notify:
        - Reload Apache

    - name: Enable SSL virtual host
      command: "a2ensite {{ item }}-ssl.conf"
      args:
        creates: "/etc/apache2/sites-enabled/{{ item }}-ssl.conf"
      with_items: "{{ domains }}"
      notify:
        - Reload Apache

  handlers:
    - name: Restart Cron
      systemd:
        name: cron
        state: restarted

    - name: Add Certbot renewal and Apache reload to /etc/crontab
      blockinfile:
        path: "/etc/crontab"
        block: |
          0 4 * * * root certbot renew --quiet
          1 4 * * * root systemctl reload apache2
        marker: "# {mark} Ansible managed block"
      notify:
        - Restart Cron

 

 

Apache 재시작 핸들러

vi /root/ansible_project/playbooks/handlers/main.yml

---
- name: Reload Apache
  service:
    name: apache2
    state: reloaded

 

Vhost 설정 생성할때 설정

vi /root/ansible_project/playbooks/templates/vhost.conf.j2

vi /root/ansible_project/playbooks/roles/web/templates/vhost.conf.j2

<VirtualHost *:80>
    ServerAdmin webmaster@{{ domain_name }}
    ServerName {{ domain_name }}
    DocumentRoot {{ document_root }}

    ErrorLog ${APACHE_LOG_DIR}/{{ domain_name }}_error.log
    CustomLog ${APACHE_LOG_DIR}/{{ domain_name }}_access.log combined

    <Directory {{ document_root }}>
        Options Indexes FollowSymLinks
        AllowOverride None
        Require all granted

        # PHP settings
        <FilesMatch \.php$>
            SetHandler application/x-httpd-php
        </FilesMatch>
    </Directory>

</VirtualHost>

 

 

vi /root/ansible_project/playbooks/templates/ssl_vhost.conf.j2

vi /root/ansible_project/playbooks/roles/web/templates/vhost.conf.j2

<IfModule mod_ssl.c>
    {% for domain in domains %}
    <VirtualHost *:443>
        ServerAdmin webmaster@{{ domain }}
        ServerName {{ domain }}
        DocumentRoot {{ document_root }}

        ErrorLog ${APACHE_LOG_DIR}/{{ domain }}_ssl_error.log
        CustomLog ${APACHE_LOG_DIR}/{{ domain }}_ssl_access.log combined

        SSLEngine on
        SSLCertificateFile /etc/letsencrypt/live/{{ domain }}/fullchain.pem
        SSLCertificateKeyFile /etc/letsencrypt/live/{{ domain }}/privkey.pem
        SSLCertificateChainFile /etc/letsencrypt/live/{{ domain }}/fullchain.pem

    <Directory {{ document_root }}>
        Options Indexes FollowSymLinks
        AllowOverride None
        Require all granted

        # PHP settings
        <FilesMatch \.php$>
            SetHandler application/x-httpd-php
        </FilesMatch>
    </Directory>

    </VirtualHost>
    {% endfor %}
</IfModule>

 

 

vi /root/ansible_project/playbooks/roles/common/tasks/main.yml

---
- name: Install common packages
  apt:
    name: "{{ item }}"
    state: present
  with_items:
    - curl
    - vim
    # Add other common packages as needed

- name: Ensure time is synchronized
  apt:
    name: ntp
    state: present
  become: true

 

 

vi /root/ansible_project/playbooks/roles/db/tasks/main.yml

---
- name: Install MariaDB Server
  apt:
    name: mariadb-server
    state: present

- name: Enable MariaDB service
  service:
    name: mariadb
    enabled: yes
    state: started

 

 

vi /root/ansible_project/playbooks/roles/web/tasks/main.yml

---
- name: Install Apache
  apt:
    name: apache2
    state: present

- name: Enable Apache service
  service:
    name: apache2
    enabled: yes
    state: started

- name: Ensure Apache modules are enabled
  apache2_module:
    state: present
    name: "{{ item }}"
  with_items:
    - rewrite
    - headers
    - ssl
    - socache_shmcb
    - socache_dbm
  notify:
    - Reload Apache

- name: Install PHP 8.1 and Apache PHP module
  apt:
    name:
      - php8.1
      - libapache2-mod-php8.1
    state: present
  notify:
    - Reload Apache

 

 

vi /root/ansible_project/playbooks/roles/web/templates/php.ini.j2

vi /root/ansible_project/playbooks/templates/php.ini.j2

; PHP settings
display_errors = On
error_reporting = E_ALL & ~E_NOTICE & ~E_STRICT & ~E_DEPRECATED
date.timezone = UTC

 

ansible로 호스트 WEB서버 VirtualHost , SSL 인증서 적용시키기

 

cd /root/ansible_project

ansible-playbook -i inventory.ini playbooks/configure_web.yml

ansible-playbook -i inventory.ini playbooks/configure_db.yml

ansible-playbook -i inventory.ini playbooks/add_vhost.yml

ansible-playbook -i inventory.ini playbooks/letsencrypt.yml

 

호스트 WEB 서버에서 확인

 

 

WEB 서버에서 Virtual 도메인과 SSL인증서 발급되었습니다.

 

 

댓글