Ansible/Redmineの導入 のバックアップ(No.5) |
|
Redmineについては、下記3種の導入方法を検討した。
今回は「公式dockerイメージを用いた導入」を採用する。
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
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_
cat << "_EOF_" > settings.sql 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','user@jomura.net'), -- 送信元メールアドレス (redmine@example.net) ('enabled_scm','--- - Git '), -- 使用するバージョン管理システム ('commit_ref_keywords','refs,references,IssueID,*'), -- 参照用キーワード (refs,references,IssueID) ('commit_cross_project_ref','1'); -- 異なるプロジェクトのチケットの参照/修正を許可 (0) _EOF_
cat << "_EOF_" > docker-compose.yml version: '3.7' services: redmine: container_name: ${REDMINE:-redmine} image: redmine:4-passenger restart: always ports: - 3000: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} {% 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 - /var/lib/git:/var/lib/git:z 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-data:/var/lib/mysql - ${REDMINE_PATH:-.}/../mysql/conf.d/redmine.cnf:/etc/mysql/conf.d/redmine.cnf memcached: container_name: ${REDMINE_MEMCACHED:-memcached} image: memcached restart: always volumes: mysql-data: name: mysql-data _EOF_
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 _EOF_ chmod go-rwx docker-env
cat << "_EOF_" > pb_redmine_server-1.yml # install redmine - hosts: redmine_servers become: true become_method: su environment: "{{ proxy_env }}" vars: redmine_path: /srv/redmine tasks: - name: check facts 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 RPMs yum: name: - yum-utils - httpd state: latest - name: install docker shell: yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo changed_when: False - yum: name=docker-ce state=latest notify: - restart Docker - name: set proxy for docker file: path=/etc/systemd/system/docker.service.d state=directory when: proxy_env.http_proxy is defined - copy: dest: /etc/systemd/system/docker.service.d/http-proxy.conf force: no content: "[Service]\n Environment = \"http_proxy={{ proxy_env.http_proxy }}\" \"https_proxy={{ proxy_env.https_proxy }}\"\n " when: proxy_env.http_proxy is defined - meta: flush_handlers - name: install docker-compose stat: path=/usr/local/bin/docker-compose register: result01 - 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: result01.stat.exists == false - name: "create {{ redmine_path }}" file: path={{ redmine_path }} state=directory register: result02 - 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: result02.changed == true - name: create config files file: path={{ redmine_path }}/config state=directory - copy: src: configuration.yml dest: "{{ redmine_path }}/config/configuration.yml" force: no - copy: dest: "{{ redmine_path }}/config/additional_environment.rb" force: no content: | config.cache_store = :mem_cache_store, "memcached" config.logger = Logger.new("#{Rails.root}/log/#{ENV['RAILS_ENV']}.log", 50, 1000000) config.logger.level = Logger::INFO - copy: dest: "{{ redmine_path }}/Gemfile.local" force: no content: "gem 'dalli'\n " - file: path={{ redmine_path }}/../mysql/conf.d state=directory - copy: dest: "{{ redmine_path }}/../mysql/conf.d/redmine.cnf" force: no content: | [mysqld] innodb_buffer_pool_size = 536870912 innodb_log_file_size = 201326592 - name: create a parent dir of git-repos file: path: /var/lib/git owner: nobody group: users state: directory mode: 02775 register: result03 - shell: | /usr/sbin/semanage fcontext -a -t httpd_git_content_t "/var/lib/git(/.*)?" /usr/sbin/restorecon -Rv /var/lib/git args: warn: false when: result03.changed == true - name: docker-compose up template: src: docker-compose.yml dest: "{{ redmine_path }}/docker-compose.yml" force: no - template: src: docker-env dest: "{{ redmine_path }}/.env" force: no mode: 0400 - shell: docker-compose --project-directory {{ redmine_path }} up --detach args: chdir: "{{ redmine_path }}" register: result04 changed_when: '" is up-to-date" not in result04.stderr' - name: wait for Completed 200 OK shell: docker container logs redmine 2>/dev/null | tail -15 register: result05 changed_when: false until: '"Completed 200 OK " in result05.stdout' retries: 100 delay: 5 - name: set db password file slurp: src: "{{ redmine_path }}/.env" register: result06 - copy: dest: ~/.my.cnf.org force: no mode: 0400 content: "[client]\nuser = redmine\npassword = {{ result06['content'] | b64decode | regex_findall('REDMINE_DB_PASSWORD=(.+)\\n') | first }}\nhost = localhost\n" register: result07 - shell: docker cp ~/.my.cnf.org mysql:root/.my.cnf when: result07.changed - name: load 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: result08 changed_when: '" is already loaded." not in result08.stdout' - name: update 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: insert settings shell: | cat << '_EOQ_' | docker exec -i mysql mysql redmine SELECT count(*) FROM `settings` _EOQ_ changed_when: false register: result09 - shell: | cat settings.sql | docker exec --interactive mysql mysql redmine && \ docker exec redmine passenger-config restart-app /usr/src/redmine when: result09.stdout_lines[1] == "0" - name: clear rails cache 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: restart passenger 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 - name: modify httpd.conf for redmine copy: dest: /etc/httpd/conf.d/proxy-redmine.conf force: no mode: 0644 content: | <IfModule !proxy_module> LoadModule proxy_module modules/mod_proxy.so </IfModule> <IfModule !proxy_http_module> LoadModule proxy_http_module modules/mod_proxy_http.so </IfModule> ProxyPassMatch /git.* ! ProxyPass / http://localhost:3000/ ProxyPassReverse / http://localhost:3000/ register: result10 - shell: /usr/sbin/setsebool -P httpd_can_network_connect 1 when: result10.changed == true notify: - restart Apache - name: open ports firewalld: service: "{{ item }}" permanent: true state: enabled immediate: yes loop: - http - https handlers: - name: restart Docker systemd: name: docker state: restarted daemon_reload: yes enabled: yes - name: restart Apache systemd: name: httpd state: restarted daemon_reload: yes enabled: yes _EOF_
ansible-playbook -i inventory.yml pb_redmine_server-1.yml --syntax-check
ansible-playbook -i inventory.yml pb_redmine_server-1.yml
GitLabは「Redmineとの連携は結構面倒」なのと「リソース(主にメモリ)を大量に消費し、しばしば動作不安定を招くほど」との評判があることから、導入を断念。CGI"git-http-backend"とRedmine.pmを用いた、従来どおりのGitリポジトリサービスを選択。ついでに、GitWebも導入。
cat << "_EOF_" > gitrepos.conf <IfModule mod_rewrite.c> RewriteEngine On RewriteCond %{REQUEST_URI} ^/git/?$ RewriteRule ^/git /gitweb [R=301,L] # RewriteRule ^/git/$ /gitweb/ [L,R] </IfModule> PerlLoadModule Apache::Authn::Redmine SetEnv GIT_PROJECT_ROOT /var/lib/git SetEnv GIT_HTTP_EXPORT_ALL ScriptAlias /git/ /usr/libexec/git-core/git-http-backend/ #<IfModule mod_rewrite.c> # RewriteEngine On # RewriteCond %{HTTPS} ^off$ # RewriteRule ^/git/(.*)$ /usr/libexec/git-core/git-http-backend/$1 [E=REMOTE_USER:$REDIRECT_REMOTE_USER,H=cgi-script,L] #</IfModule> #<Directory /usr/libexec/git-core> # <Files "git-http-backend"> # Options +ExecCGI # </Files> #</Directory> <Location /git/> Order allow,deny Allow from all PerlAccessHandler Apache::Authn::Redmine::access_handler PerlAuthenHandler Apache::Authn::Redmine::authen_handler AuthType Basic AuthName Git # <LimitExcept GET PROPFIND OPTIONS REPORT> # SSLRequireSSL # </LimitExcept> # for Redmine Authentication RedmineDSN "DBI:mysql:database=redmine;host=127.0.0.1" RedmineDbUser "redmine" RedmineDbPass "" RedmineGitSmartHttp yes Require valid-user # SetEnvIf Request_URI "^/git/$" allow # Order allow,deny # Allow from env=allow # Satisfy any </Location> _EOF_
cat << "_EOF_" > pb_redmine_server-2.yml # install git # dependencies: pb_redmine_server-1.yml - hosts: redmine_servers become: true become_method: su environment: "{{ proxy_env }}" vars: redmine_path: /srv/redmine tasks: - name: check facts 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: check redmine stat: path={{ redmine_path }} register: result01 - fail: msg: "pb_redmine_server.yml has been executed yet." when: result01.stat.exists == false - name: install RPMs yum: name: - httpd - git - mod_perl - perl-Digest-SHA - perl-DBI - perl-DBD-mysql - gitweb state: latest - name: modify apache user for git user: name=apache groups=users append=yes notify: - restart Apache - copy: dest: /etc/systemd/system/httpd.service force: no content: ".include /lib/systemd/system/httpd.service\n[Service]\nUMask=002\n" notify: - restart Apache - name: copy Redmine.pm file: path=/etc/httpd/Apache/Authn state=directory - shell: docker cp redmine:/usr/src/redmine/extra/svn/Redmine.pm /etc/httpd/Apache/Authn/Redmine.pm - name: create gitrepos.conf copy: src: gitrepos.conf dest: /etc/httpd/conf.d/gitrepos.conf force: no mode: 0640 - slurp: src: "{{ redmine_path }}/.env" register: result03 - lineinfile: dest: /etc/httpd/conf.d/gitrepos.conf regexp: "^ RedmineDbPass" line: " RedmineDbPass {{ result03['content'] | b64decode | regex_findall('REDMINE_DB_PASSWORD=(.+)\\n') | first }}" - name: modify gitweb lineinfile: dest: /etc/httpd/conf.d/git.conf regexp: '^Alias /git /var/www/git$' line: 'Alias /gitweb /var/www/git' handlers: - name: restart Apache systemd: name: httpd state: restarted daemon_reload: yes enabled: yes _EOF_
ansible-playbook -i inventory.yml pb_redmine_server-2.yml