#author("2020-09-02T12:16:53+09:00","default:jomura","jomura")
#author("2020-09-04T10:51:33+09:00","default:jomura","jomura")
#contents

#br

* Redmineの導入 [#wa722c9e]

 Redmineについては、下記3種の導入方法を検討した。
+ 公式サイトの本体コード一式 + RHELのRPM + gemコマンドによるライブラリ導入
-- 各々のライブラリ依存性管理が非常に大変。特にnokogiriとopensslが鬼門。
+ bitnami-redmineを用いた一括導入
-- Git, Redmine, PhpMyAdminなども導入されるが、今回は使わない
-- Redmine公式ではない
+ 公式dockerイメージを用いた導入
-- dockerを意識して維持管理する手間が生じる
-- ライブラリ間の依存性に悩む必要がなくなる
-- cf. https://qiita.com/bezeklik/items/b9d75ee74e0ae4c6d42c

 今回は「公式dockerイメージを用いた導入」を採用する。

** 導入サーバの前提条件 [#la5e25ea]
+ OSはRHEL7(or CentOS7)とする。RHEL8にはdockerイメージが対応していない?
+ 事前導入するソフトウェアパッケージは最小構成。
+ インターネットに接続可能   ※必要ならproxy設定
 /etc/yum.conf
 proxy=http://proxy.jomura.net:8080/     #as your own
 ~/.bashrc
 export HTTP_PROXY=http://proxy.jomura.net:8080/     #as your own
 export HTTPS_PROXY=${HTTP_PROXY}
+ パッケージの更新が事前に実行されている
 yum clean all && yum -y update && reboot
+ Redmine Webサイト用のFully Qualified Domain Name(FQDN)が用意されている。
+ Redmineの導入パス: /srv/redmine

** configuration.ymlの作成 [#z6fa156d]
- Ansibleサーバ上の一般ユーザで実行
- SMTP情報は as your own で
 cat << "_EOF_" > configuration.yml
 default:
   email_delivery:
     delivery_method: :smtp
     smtp_settings:
 #      tls: true
       enable_starttls_auto: true
       address: "smtp.gmail.com"
       port: 587
       domain: "jomura.net"
       authentication: :login
       user_name: "user@jomura.net"
       password: "********"
 _EOF_

** docker-compose.ymlファイルの作成 [#z4d0976f]
- Ansibleサーバ上の一般ユーザで実行
 cat << "_EOF_" > docker-compose.yml
           version: '3.7'
           services:
             redmine:
               container_name: ${REDMINE:-redmine}
               image: redmine:4-passenger
               restart: always
               ports:
                 - 80:3000
               depends_on:
                 - ${REDMINE_DB_MYSQL:-mysql}
                 - ${REDMINE_MEMCACHED:-memcached}
               environment:
                 TZ: ${TZ}
                 REDMINE_DB_MYSQL: ${REDMINE_DB_MYSQL:-mysql}
                 REDMINE_DB_DATABASE: ${REDMINE_DB_DATABASE}
                 REDMINE_DB_USERNAME: ${REDMINE_DB_USERNAME}
                 REDMINE_DB_PASSWORD: ${REDMINE_DB_PASSWORD}
                 REDMINE_DB_ENCODING: ${REDMINE_DB_ENCODING:-utf8mb4}
                 VIRTUAL_HOST: ${VIRTUAL_HOST}
                 VIRTUAL_PORT: ${VIRTUAL_PORT:-3000}
 {% if proxy_env.http_proxy is defined %}
                 HTTP_PROXY: {{ proxy_env.http_proxy }}
                 HTTPS_PROXY: {{ proxy_env.https_proxy }}
 {% endif %}
               volumes:
                 - ${REDMINE_PATH:-.}/config/additional_environment.rb:/usr/src/redmine/config/additional_environment.rb
                 - ${REDMINE_PATH:-.}/config/configuration.yml:/usr/src/redmine/config/configuration.yml
                 - ${REDMINE_PATH:-.}/Gemfile.local:/usr/src/redmine/Gemfile.local
                 - ${REDMINE_PATH:-.}/files:/usr/src/redmine/files:z
                 - ${REDMINE_PATH:-.}/log:/usr/src/redmine/log:Z
                 - ${REDMINE_PATH:-.}/plugins:/usr/src/redmine/plugins
                 - ${REDMINE_PATH:-.}/public/themes:/usr/src/redmine/public/themes
             mysql:
               container_name: ${REDMINE_DB_MYSQL:-mysql}
               image: mysql:8
               command: --default-authentication-plugin=mysql_native_password
               restart: always
               ports:
                 - 3306:3306
               environment:
                 TZ: ${TZ}
                 MYSQL_ROOT_PASSWORD: ${MYSQL_ROOT_PASSWORD}
                 MYSQL_DATABASE: ${REDMINE_DB_DATABASE}
                 MYSQL_USER: ${REDMINE_DB_USERNAME}
                 MYSQL_PASSWORD: ${REDMINE_DB_PASSWORD}
               volumes:
                 - mysql:/var/lib/mysql
             memcached:
               container_name: ${REDMINE_MEMCACHED:-memcached}
               image: memcached
               restart: always
           #    ports:
           #      - 11211:11211
           volumes:
             mysql:
               name: ${REDMINE_DB_MYSQL:-mysql}
 _EOF_

** docker用環境変数ファイルの作成 [#mef56985]
- Ansibleサーバ上の一般ユーザで実行
 cat << _EOF_ > docker-env
 REDMINE_PATH={{ redmine_path }}
 TZ=Asia/Tokyo
 MYSQL_ROOT_PASSWORD=$(< /dev/urandom tr -dc 'A-Za-z0-9!$%&()*+,-./:;<=>?@[\]^_{|}~' | head -c 16; echo)
 REDMINE_DB_MYSQL=mysql
 REDMINE_DB_DATABASE=redmine
 REDMINE_DB_USERNAME=redmine
 REDMINE_DB_PASSWORD=$(< /dev/urandom tr -dc 'A-Za-z0-9!$%&()*+,-./:;<=>?@[\]^_{|}~' | head -c 16; echo)
 REDMINE_DB_ENCODING=utf8mb4
 REDMINE_MEMCACHED=memcached
 VIRTUAL_HOST={{ inventory_hostname }}
 VIRTUAL_PORT=3000
 _EOF_
- catに指定する _EOF_ を"でくくってはいけない。urandamコマンド等が実行されなくなる。

** playbookの作成 [#y22e4e40]
- Ansibleサーバ上の一般ユーザで実行
- sudoの場合、become_method: sudo
 cat << "_EOF_" > pb_redmine_server.yml
 # install redmine
 
 - hosts: redmine_servers
   become: true
   become_method: su
   environment: "{{ proxy_env }}"
 
   tasks:
     - name: facts check
       fail:
         msg: "Not compatible with [{{ ansible_os_family }}] {{ ansible_distribution }} {{ ansible_distribution_major_version }}."
       when: ansible_os_family != 'RedHat' or ansible_distribution_major_version|int != 7
 
     - name: install yum-utils
       yum:
         name: yum-utils
         state: latest
     - name: add docker repo
       shell: yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo
       changed_when: False
     - name: install Docker
       yum:
         name:
           - docker-ce
         state: latest
       notify:
         - restart Docker
     - name: /etc/systemd/system/docker.service.d
       file: path=/etc/systemd/system/docker.service.d state=directory
     - name: docker set proxy
       copy:
         dest: /etc/systemd/system/docker.service.d/http-proxy.conf
         force: no
         content: "[Service]\nEnvironment = \"http_proxy={{ proxy_env.http_proxy }}\" \"https_proxy={{ proxy_env.https_proxy }}\"\n"
       when: proxy_env.http_proxy is defined
 
     - meta: flush_handlers
 
     - name: check docker-compose
       stat:
         path: /usr/local/bin/docker-compose
       register: docker_compose
     - name: install docker-compose
       shell: |
         curl --location --output /usr/local/bin/docker-compose \
           $(curl --silent --show-error \
             https://api.github.com/repos/docker/compose/releases/latest \
             | grep 'Linux-x86_64"' \
             | grep url \
             | cut --delimiter='"' --fields=4 \
            )
         chmod +x /usr/local/bin/docker-compose
       args:
         warn: false
       when: docker_compose.stat.exists == False
 
     - name: install-path
       file: path={{ redmine_path }} state=directory
       register: install_path
     - name: for SELinux
       shell: |
         /usr/sbin/matchpathcon {{ redmine_path }}
         /usr/sbin/semanage fcontext --add --type container_file_t {{ redmine_path }}
         /usr/sbin/restorecon -v {{ redmine_path }}
         /usr/sbin/matchpathcon {{ redmine_path }}
       args:
         warn: false
       when: install_path.changed == True
 
     - name: "{{ redmine_path }}/config/"
       file: path={{ redmine_path }}/config state=directory
 
     - name: redmine configuration.yml
       copy:
         src: configuration.yml
         dest: "{{ redmine_path }}/config/configuration.yml"
         force: no
 
     - name: redmine additional_environment.rb
       copy:
         dest: "{{ redmine_path }}/config/additional_environment.rb"
         force: no
         content: |
           config.cache_store = :mem_cache_store, "memcached"
 
     - name: memcached Gemfile.local
       copy:
         dest: "{{ redmine_path }}/Gemfile.local"
         force: no
         content: "gem 'dalli'\n"
 
     - name: docker docker-compose.yml
       template:
         src: docker-compose.yml
         dest: "{{ redmine_path }}/docker-compose.yml"
         force: no
 
     - name: docker .env
       template:
         src: docker-env
         dest: "{{ redmine_path }}/.env"
         force: no
         mode: 0444
 
     - name: docker-compose up
       shell: docker-compose --project-directory {{ redmine_path }} up --detach
       args:
         chdir: "{{ redmine_path }}"
       register: result
       changed_when: '" is up-to-date" not in result.stderr'
     - name: wait for Completed 200 OK
       shell: docker container logs redmine 2>/dev/null | tail -5
       shell: docker container logs redmine 2>/dev/null | tail -15
       register: result
       changed_when: False
       until: '"Completed 200 OK " in result.stdout'
       retries: 100
       delay: 5
 
     - name: redmine default data
       shell: docker exec {% if proxy_env.http_proxy is defined -%}
         -e HTTP_PROXY={{ proxy_env.http_proxy }} -e HTTPS_PROXY={{ proxy_env.https_proxy }} {% endif -%}
         redmine bundle exec rake redmine:load_default_data RAILS_ENV=production REDMINE_LANG=ja
       register: result
       changed_when: '" is already loaded." not in result.stdout'
 
     - name: db pass
       slurp:
         src: "{{ redmine_path }}/.env"
       register: result
     - name: create .my.cnf.org
       copy:
         dest: ~/.my.cnf.org
         force: no
         content: "[client]\nuser = redmine\npassword = {{ result['content'] | b64decode | regex_findall('REDMINE_DB_PASSWORD=(.+)\\n') | first }}\nhost = localhost\n"
       register: result
     - name: docker cp .my.cnf
       shell: docker cp ~/.my.cnf.org mysql:root/.my.cnf
       when: result.changed
 
     - name: redmine roles
       shell: |
         cat << '_EOQ_' | docker exec -i mysql mysql redmine
         UPDATE `roles` SET `permissions` = NULL WHERE `id` = '1' OR `id` = '2';
         _EOQ_
       changed_when: false
 
     - name: redmine settings count
       shell: |
         cat << '_EOQ_' | docker exec -i mysql mysql redmine
         SELECT count(*) FROM `settings`
         _EOQ_
       changed_when: false
       register: result
 
     - name: redmine init config
       shell: |
         cat << '_EOQ_' | docker exec --interactive mysql mysql redmine && \
         docker exec redmine passenger-config restart-app /usr/src/redmine
         INSERT INTO `settings` (`name`, `value`) VALUES
         ('search_results_per_page','30'), -- ページごとの検索結果表示件数 (10)
         ('host_name','cxits.tg-group.tokyo-gas.co.jp'), -- ホスト名とパス (localhost:3000)
         ('protocol','http'), -- プロトコル (http)
         ('text_formatting','textile'), -- テキスト書式 (textile)
         ('default_language','ja'), -- デフォルトの言語 (en)
         ('force_default_language_for_anonymous','0'), -- 匿名ユーザーにデフォルトの言語を強制 (0)
         ('force_default_language_for_loggedin','0'), -- ログインユーザーにデフォルトの言語を強制 (0)
         ('user_format','lastname_firstname'), -- ユーザー名の表示形式 (firstname_lastname)
         ('thumbnails_enabled','1'), -- 添付ファイルのサムネイル画像を表示 (0)
         ('login_required','1'), -- 認証が必要 (0)
         ('autologin','7'), -- 自動ログイン (0)
         ('max_additional_emails','3'), -- 追加メールアドレス数の上限 (5)
         ('session_lifetime','86400'), -- 有効期間の最大値 (0)
         ('session_timeout','240'), -- 無操作タイムアウト (0)
         ('default_users_time_zone','Tokyo'), -- タイムゾーン ()
         ('rest_api_enabled','1'), -- RESTによるWebサービスを有効にする (0)
         ('jsonp_enabled','1'), -- JSONPを有効にする (0)
         ('default_projects_public','0'), -- デフォルトで新しいプロジェクトは公開にする (1)
         ('default_projects_modules','---
         - issue_tracking
         - time_tracking
         - wiki
         - repository
         - calendar
         - gantt
         '), -- 新規プロジェクトにおいてデフォルトで有効になるモジュールチケットトラッキング
         ('default_projects_tracker_ids','---
         - \'1\'
         - \'2\'
         - \'3\'
         '), -- 新規プロジェクトにおいてデフォルトで有効になるトラッカー
         ('cross_project_issue_relations','1'), -- 異なるプロジェクトのチケット間で関連の設定を許可 (0)
         ('default_issue_start_date_to_creation_date','1'), -- 現在の日付を新しいチケットの開始日とする (1)
         ('issue_done_ratio','issue_status'), -- 進捗率の算出方法 (issue_field)
         ('issue_list_default_totals','---
         - estimated_hours
         - spent_hours
         '), -- チケットの一覧で表示する項目(合計)
         ('attachment_max_size','51200'), -- 添付ファイルサイズの上限 (5120)
         ('repositories_encodings','utf-8,cp932,euc-jp'), -- 添付ファイルとリポジトリのエンコーディング ()
         ('mail_from','noreply_cirius@tg-inet.co.jp'), -- 送信元メールアドレス (redmine@example.net)
         ('mail_from','user@jomura.net'), -- 送信元メールアドレス (redmine@example.net)
         ('enabled_scm','---
         - Git
         '), -- 使用するバージョン管理システム
         ('commit_ref_keywords','refs,references,IssueID,*'), -- 参照用キーワード (refs,references,IssueID)
         ('commit_cross_project_ref','1'); -- 異なるプロジェクトのチケットの参照/修正を許可 (0)
         _EOQ_
       when: result.stdout_lines[1] == "0"
 
     - name: Rails.cache.clear
       shell: docker exec {% if proxy_env.http_proxy is defined -%}
         -e HTTP_PROXY={{ proxy_env.http_proxy }} -e HTTPS_PROXY={{ proxy_env.https_proxy }} {% endif -%}
         redmine bundle exec rails runner 'Rails.cache.clear'
       changed_when: False
 
     - name: bundle install
       shell: docker exec {% if proxy_env.http_proxy is defined -%}
         -e HTTP_PROXY={{ proxy_env.http_proxy }} -e HTTPS_PROXY={{ proxy_env.https_proxy }} {% endif -%}
         redmine bundle install
       changed_when: False
 
     - name: passenger restart
       shell: docker exec {% if proxy_env.http_proxy is defined -%}
         -e HTTP_PROXY={{ proxy_env.http_proxy }} -e HTTPS_PROXY={{ proxy_env.https_proxy }} {% endif -%}
         redmine passenger-config restart-app /usr/src/redmine
       changed_when: False
  
   handlers:
     - name: restart Docker
       systemd:
         name: docker
         state: started
         daemon_reload: yes
         enabled: yes
 
 _EOF_
- docker_composeはRPMパッケージではなく最新版を使う

** playbookの実行 [#x17c57c6]
- Ansibleサーバ上の一般ユーザで実行
 ansible-playbook -i inventory.yml pb_redmine_server.yml


トップ   新規 一覧 単語検索 最終更新   ヘルプ   最終更新のRSS