AzureのVMでRedmine構築

前回はAWSでRedmineを構築しましたが今回はAzureのVMサービスでRedmineを構築してみました。手順自体は前回とそんな変更ないです。GitからRedmineのソースをcloneしてくるようにしたくらいです。AzureのVMはAWSほど気軽に使える値段でないので少しコスト面で怖い部分もありますが、これから徐々に慣れていきたいところです。
リストアが試せていないので時間あるときに試してみたいです。
*仮想マシンを復活させるだけなのでスムーズなはず。。。


大枠の手順は以下の通り

Ⅰ.OSイメージ作成
Ⅱ.OSイメージ更新
Ⅲ.Redmine構築
Ⅳ.仮想マシンのバックアップ


◆作業手順

Ⅰ.OSイメージ作成

#1.初期設定
#1-1.日本語化
$ sudo sed -i.bak -e "s%http://us.archive.ubuntu.com/ubuntu/%http://ftp.jaist.ac.jp/pub/Linux/ubuntu/%g" /etc/apt/sources.list
$ sudo apt-get -y install language-pack-ja-base language-pack-ja ibus-mozc
$ sudo localectl set-locale LANG=ja_JP.UTF-8 LANGUAGE="ja_JP:ja"
$ source /etc/default/locale
$ echo $LANG
ja_JP.UTF-8

#1-2.タイムロケール変更
$ sudo timedatectl set-timezone Asia/Tokyo
$ timedatectl

#1-3.ソフトウェアアップデート
$ sudo apt-get update
$ sudo apt-get -y upgrade

#1-4.ディストリビューションアップデート
$ sudo apt-get -y update
$ sudo apt-get dist-upgrade

#1-5.デフォルトエディタ変更
$ sudo update-alternatives --config editor
alternative editor (/usr/bin/editor を提供) には 4 個の選択肢があります。

  選択肢    パス              優先度  状態
------------------------------------------------------------
* 0            /bin/nano            40        自動モード
  1            /bin/ed             -100       手動モード
  2            /bin/nano            40        手動モード
  3            /usr/bin/vim.basic   30        手動モード
  4            /usr/bin/vim.tiny    15        手動モード

現在の選択 [*] を保持するには 、さもなければ選択肢の番号のキーを押してく ださい: 4
update-alternatives: /usr/bin/editor (editor) を提供するためにマニュアルモードで /usr/bin/vim.tiny を使います
$ sudo apt -y remove nano

#1-6.ホームディレクトリのアクセス権限設定
$ sudo chmod 750 $HOME
[sudo] password for ope_user:
$ ls -ld $HOME
drwxr-x--- 3 ope_user ope_user 4096 11月 21 11:42 /home/ope_user
$ sudo sed -i "s/DIR_MODE=0755/DIR_MODE=0750/g" /etc/adduser.conf


#2.SSH関連設定
#2-1.sshlogin用ユーザ追加
$ sudo adduser ssh_user
ユーザー `ssh_user' を追加しています...
新しいグループ `ssh_user' (1001) を追加しています...
新しいユーザー `ssh_user' (1001) をグループ `ssh_user' に追加しています...
ホームディレクトリ `/home/ssh_user' を作成しています...
`/etc/skel' からファイルをコピーしています...
新しい UNIX パスワードを入力してください:
新しい UNIX パスワードを再入力してください:
passwd: password updated successfully
Changing the user information for ssh_user
Enter the new value, or press ENTER for the default
        Full Name []:
        Room Number []:
        Work Phone []:
        Home Phone []:
        Other []:
以上で正しいですか? [Y/n] Y

#2-2.sshログイン可能ユーザ限定
$ echo "AllowGroups sshlogin" | sudo tee -a /etc/ssh/sshd_config
AllowGroups sshlogin
$ sudo addgroup sshlogin
グループ `sshlogin' (GID 1002) を追加しています...
完了。
$ sudo gpasswd -a ssh_user sshlogin
Adding user ssh_user to group sshlogin

#2-3.ssh_config修正
$ sudo vi /etc/ssh/sshd_config
-------------------------------
※PermitRootLogin noを追記しその上をコメントアウト
# Authentication:
LoginGraceTime 120
#PermitRootLogin without-password
PermitRootLogin no
StrictModes yes

#2-4.ssh再起動
$ sudo sshd -t
$ sudo service ssh restart

#2-5.ssh用証明書作成
#TeraTermでKey作成後にWinSCP等でpubファイルアップロード後に以下のコマンド実行
$ mkdir .ssh
$ chmod 700 .ssh
$ mv id_rsa.pub .ssh/authorized_keys

#2-6.sshd_config編集
$ su - ope_user
$ sudo sed -i -e "s/#PubkeyAuthentication/PubkeyAuthentication/g" /etc/ssh/sshd_config
$ sudo sed -i -e "s/PasswordAuthentication yes/PasswordAuthentication no/g" /etc/ssh/sshd_config
$ sudo reboot


#3.ネットワーク関連防御設定
#3-1.パケットソースフィルタリング及び偽装IPのログ排出
$ sudo vi /etc/sysctl.conf
-----------------------------------
※IP偽装保護(コメントアウト解除)
# Uncomment the next two lines to enable Spoof protection (reverse-path filter)
# Turn on Source Address Verification in all interfaces to
# prevent some spoofing attacks
net.ipv4.conf.default.rp_filter=1
net.ipv4.conf.all.rp_filter=1

※SYN攻撃ブロック(コメントアウト解除、下3行追加)
# Uncomment the next line to enable TCP/IP SYN cookies
# See http://lwn.net/Articles/277146/
# Note: This may impact IPv6 TCP sessions too
net.ipv4.tcp_syncookies=1
net.ipv4.tcp_max_syn_backlog = 2048
net.ipv4.tcp_synack_retries = 2
net.ipv4.tcp_syn_retries = 5

※リダイレクト送信無視
# Do not accept ICMP redirects (prevent MITM attacks)
net.ipv4.conf.all.accept_redirects = 0
net.ipv6.conf.all.accept_redirects = 0

※ソースパケットルーティング禁止
# Do not accept IP source route packets (we are not a router)
net.ipv4.conf.all.accept_source_route = 0
net.ipv6.conf.all.accept_source_route = 0
net.ipv4.conf.default.accept_source_route = 0
net.ipv6.conf.default.accept_source_route = 0

※ Martiansのログ(コメント解除)
# Log Martian Packets
net.ipv4.conf.all.log_martians = 1

# ICMPブロードキャストリクエストを無視(追記)
net.ipv4.icmp_echo_ignore_broadcasts = 1

# ICMPリダイレクトを無視(追記)
net.ipv4.conf.all.accept_redirects = 0
net.ipv6.conf.all.accept_redirects = 0
net.ipv4.conf.default.accept_redirects = 0
net.ipv6.conf.default.accept_redirects = 0
-----------------------------------
$ sudo sysctl --system
* Applying /etc/sysctl.d/10-console-messages.conf ...
~中略~
net.ipv6.conf.lo.disable_ipv6 = 1

#3-2.ファイアウォールの設定
#ポリシー設定(外部からのパケットはSSH、http、httpsのみを許可)
$ sudo ufw default deny
デフォルトの incoming ポリシーは 'deny' に変更しました
(適用したい内容に基づいて必ずルールを更新してください)
$ sudo ufw default allow outgoing
デフォルトの outgoing ポリシーは 'allow' に変更しました
(適用したい内容に基づいて必ずルールを更新してください)
$ sudo ufw logging low
ログ取得を有効にしました
$ sudo ufw allow ssh
ルールを追加しました
ルールを追加しました (v6)
$ sudo ufw allow http
ルールをアップデートしました
ルールをアップデートしました(v6)
$ sudo ufw allow https
ルールをアップデートしました
ルールをアップデートしました(v6)
$ sudo ufw enable
Command may disrupt existing ssh connections. Proceed with operation (y|n)? y
ファイアウォールはアクティブかつシステムの起動時に有効化されます。

#4.監視系ツール類インストール
#4-1.ntp設定
$ sudo apt -y install ntp
$ sudo vi /etc/ntp.conf
------------------------------------
# Use Ubuntu's ntp server as a fallback.
#pool ntp.ubuntu.com
server ntp1.jst.mfeed.ad.jp
server ntp2.jst.mfeed.ad.jp
server ntp3.jst.mfeed.ad.jp
------------------------------------
$ sudo /etc/init.d/ntp restart
$ sudo ntpq -p
$ date

#4-2.logwatchインストール
・インストール
$ sudo mkdir /var/cache/logwatch
$ sudo chmod 700 /var/cache/logwatch
※GUIが出てくるので[サテライト]を選ぶ)
※後は全部Enterで
$ sudo apt-get -y install logwatch
パッケージリストを読み込んでいます... 完了
依存関係ツリーを作成しています
~中略~
logwatch (7.4.0+svn20130529rev144-1ubuntu1) を設定しています ...
libc-bin (2.19-0ubuntu6.6) のトリガを処理しています ...
$ sudo which postfix
/usr/sbin/postfix

#sendgrid送信確認
$ curl --request POST \
  --url https://api.sendgrid.com/v3/mail/send \
  --header 'Authorization: Bearer YOURTOKEN' \
  --header 'Content-Type: application/json' \
  --data '{"personalizations": [{"to": [{"email": "youremailadress"}]}],"from": {"email": "example@example.com"},"subject": "Hello, World!","content": [{"type": "text/plain", "value": "Heya!"}]}'


#設定ファイル準備
$ sudo vi /etc/postfix/main.cf
※すべて削除して追記
-------------------------
# SendGrid APIkey Settings
smtp_sasl_auth_enable = yes
smtp_sasl_password_maps = hash:/etc/postfix/smtp_apikey_sendgrid
smtp_sasl_security_options = noanonymous
smtp_sasl_tls_security_options = noanonymous
smtp_tls_security_level = encrypt
header_size_limit = 4096000
relayhost = [smtp.sendgrid.net]:587
-------------------------
$ echo "[smtp.sendgrid.net]:587 apikey:YOURETOKEN" | sudo tee -a /etc/postfix/smtp_apikey_sendgrid
$ sudo chmod 600 /etc/postfix/smtp_apikey_sendgrid

#postfix再起動
$ sudo postmap /etc/postfix/smtp_apikey_sendgrid
$ sudo service postfix restart

#aliasesの編集
$ echo "root: yourmailadress" | sudo tee -a /etc/aliases
$ sudo newaliases

#設定ファイル準備
$ sudo cp -p /usr/share/logwatch/default.conf/logwatch.conf /etc/logwatch/logwatch.conf
$ sudo cp /usr/share/logwatch/default.conf/services/* /etc/logwatch/conf/services/
$ sudo vi /etc/logwatch/logwatch.conf
$ sudo shutdown -r now

#送信テスト
$ sudo logwatch -range today
$ sudo logwatch -range today --output mail


#4-3.SNMPインストール
・インストール
$ sudo apt -y install snmpd snmp
・設定ファイル編集
$ sudo vi /etc/snmp/snmpd.conf
-------------------------------
※外部からの接続許可
#Listen for connections from the local system only
#agentAddress  udp:127.0.0.1:161 ←コメントアウト
#  Listen for connections on all interfaces (both IPv4 *and* IPv6)
agentAddress udp:161 ←コメント解除し後半udp6を削除

※コミュニティ設定
# rocommunity public  default    -V systemonly ←コメントアウト
                                                 #  rocommunity6 is for IPv6
# rocommunity6 public  default   -V systemonly ←コメントアウト

                                                 #  Full access from an example network
rocommunity dev-com  localhost ←追記
rocommunity dev-com YOURIPADRESS ←追記
-------------------------------


#5.セキュリティ関連ソフトインストール
#5-1.chkrootkitインストール
#インストール
$ sudo apt -y install chkrootkit

#5-2.Fail2Banインストール
$ sudo apt -y install fail2ban
$ cd /etc/fail2ban
$ sudo cp jail.conf jail.local
$ sudo systemctl restart fail2ban.service
$ sudo systemctl enable fail2ban.service
$ cd

#5-3.改ざん検知ツールインストール(指定フォルダを決定後に再設定必要)
$ sudo apt -y install aide
#設定ファイル編集
$ sudo vi /etc/aide/aide.conf
※最終行に追記(除外ディレクトリ設定)
-----------------------------------
#exclude dir
!/var/agentx/*
!/var/backups/*
!/var/cache/*
!/var/crash/*
!/var/lib/*
!/var/log/*
!/var/mail/*
!/var/snap/*
!/var/spool/*
!/var/tmp/*
!/root
!/home
!/mnt
-----------------------------------
#初期DB作成(※少し時間がかかる)
$ sudo aideinit
Running aide --init...
~略~
End timestamp: 2019-08-10 17:35:26 +0900 (run time: 4m 47s)
$ sudo cp -p /var/lib/aide/aide.db.new /var/lib/aide/aide.db

#5-4.Clamavインストール
$ sudo apt -y install clamav-base clamav-daemon clamav-freshclam
#設定変更
$ sudo rm /var/log/clamav/freshclam.log
$ sudo touch /var/log/clamav/freshclam.log
$ sudo chown clamav:clamav /var/log/clamav/freshclam.log
$ sudo vi /etc/logrotate.d/clamav-freshclam
------------------------------
create 640 clamav adm
  ↓
create 640 clamav clamav
------------------------------
$ sudo chmod 744 /etc/clamav/freshclam.conf
$ sudo vi /etc/clamav/freshclam.conf
-------------------------------
# Check for new database 24 times a day
Checks 24
DatabaseMirror db.local.clamav.net
DatabaseMirror database.clamav.net
# added
DatabaseMirror db.jp.clamav.net
DatabaseMirror db.us.clamav.net
-------------------------------
$ sudo vi /etc/clamav/clamd.conf
-------------------------------
#User clamav    #ユーザをコメントアウト

MaxScanSize 100M
MaxFileSize 4096M  #25Mから書替
MaxRecursion 16
MaxFiles 10000
-------------------------------
$ sudo sed -i -e "s/^NotifyClamd/#NotifyClamd/g" /etc/clamav/freshclam.conf
#サービス再起動
$ sudo /etc/init.d/clamav-freshclam restart
[ ok ] Restarting clamav-freshclam (via systemctl): clamav-freshclam.service.
#スクリプト作成
$ sudo mkdir /var/log/clamav/virus
$ sudo chown clamav:clamav /var/log/clamav/virus
$ sudo touch /etc/cron.daily/clamav
$ sudo chmod 755 /etc/cron.daily/clamav
$ sudo vi /etc/cron.daily/clamav
-----------------------------------
#!/bin/sh
echo =========================================
date
clamscan / \
     --infected \
     --recursive \
     --log=/var/log/clamav/clamav.log \
     --move=/var/log/clamav/virus \
     --exclude-dir=^/boot \
     --exclude-dir=^/sys \
     --exclude-dir=^/proc \
     --exclude-dir=^/dev \
     --exclude-dir=^/var/log/clamav

if [ $? = 0 ]; then
    echo "ウイルス未検出."
    cat /var/log/clamav/clamav.log | mail -s "Clamav scan OK." root
else
    echo "ウイルス検出!!"
    cat /var/log/clamav/clamav.log | mail -s "Clamav scan NG!" root
fi
-----------------------------------


#6.ログ削除
$ sudo find /var/log/ -type f -name \* -exec cp -f /dev/null {} \;
$ history -c
$ sudo shutdown -h now

Ⅱ.OSイメージ更新・ドメイン取得

1.イメージの作成

①[Azure Portal] に移動して、VM イメージを管理します。 [仮想マシン] を検索して選択します。
一覧で VM を選択します。
②VM の [仮想マシン] ページの上部のメニューで、 [キャプチャ] を選択します。
③[イメージの作成] ページが表示されます。
④[名前] で、あらかじめ設定されている名前を受け入れるか、イメージに使用する名前を入力します。
⑤[リソース グループ] で、 [新規作成] を選択して名前を入力するか、使用するリソースグループをドロップダウンリストから選択します。
⑥イメージが作成された後にソース VM を削除する場合、 [イメージの作成後、この仮想マシンを自動的に削除します] を選択します。
いずれかの 可用性ゾーンでイメージを使用する機能が必要な場合、 [Zone resiliency (ゾーンの回復性)] に [オン] を選択します。
⑦[作成] を選択してイメージを作成します。

2.イメージ展開後の注意

①イメージギャラリーからイメージを選択
②VMの作成でVMを作成する
③VM展開後にsudo可能ユーザのパスワードのリセットを行う必要がある

3.ドメイン設定

freenomでドメインを取得する


Ⅲ.Redmine構築

#1.BlobStorageのマウント
$ export AZUREFILES_RGN="VirtualMachineExamination"
$ export AZUREFILES_SA="YOURSTORAGEACCOUNT"
$ export AZUREFILES_FSN="YOURFILESTORAGENAME"
$ export AZUREFILES_MNT="/mnt/$AZUREFILES_SA/$AZUREFILES_FSN"
$ curl -sL https://aka.ms/InstallAzureCLIDeb | sudo bash
$ az login
#接続用スクリプト
$ vi azurefilesconnect.sh
---------------------------
#! /bin/bash
resourceGroupName=$AZUREFILES_RGN
storageAccountName=$AZUREFILES_SA

# This command assumes you have logged in with az login
httpEndpoint=$(az storage account show \
    --resource-group $resourceGroupName \
    --name $storageAccountName \
    --query "primaryEndpoints.file" | tr -d '"')
smbPath=$(echo $httpEndpoint | cut -c7-$(expr length $httpEndpoint))
fileHost=$(echo $smbPath | tr -d "/")

nc -zvw3 $fileHost 445
---------------------------
$ chmod a+x azurefilesconnect.sh
$ ./azurefilesconnect.sh
Connection to XXXX.file.core.windows.net 445 port [tcp/microsoft-ds] succeeded!
#マウント用スクリプト
$ vi azurefilesmount.sh
---------------------------
#! /bin/bash
resourceGroupName=$AZUREFILES_RGN
storageAccountName=$AZUREFILES_SA
fileShareName=$AZUREFILES_FSN

mntPath="/mnt/$storageAccountName/$fileShareName"

sudo mkdir -p $mntPath

if [ ! -d "/etc/smbcredentials" ]; then
    sudo mkdir "/etc/smbcredentials"
fi

storageAccountKey=$(az storage account keys list \
    --resource-group $resourceGroupName \
    --account-name $storageAccountName \
    --query "[0].value" | tr -d '"')

smbCredentialFile="/etc/smbcredentials/$storageAccountName.cred"
if [ ! -f $smbCredentialFile ]; then
    echo "username=$storageAccountName" | sudo tee $smbCredentialFile > /dev/null
    echo "password=$storageAccountKey" | sudo tee -a $smbCredentialFile > /dev/null
else
    echo "The credential file $smbCredentialFile already exists, and was not modified."
fi
sudo chmod 600 $smbCredentialFile
# This command assumes you have logged in with az login
httpEndpoint=$(az storage account show \
    --resource-group $resourceGroupName \
    --name $storageAccountName \
    --query "primaryEndpoints.file" | tr -d '"')
smbPath=$(echo $httpEndpoint | cut -c7-$(expr length $httpEndpoint))$fileShareName

if [ -z "$(grep $smbPath\ $mntPath /etc/fstab)" ]; then
    echo "$smbPath $mntPath cifs nofail,vers=3.0,file_mode=0666,dir_mode=0777,credentials=$smbCredentialFile,serverino" | sudo tee -a /etc/fstab > /dev/null
else
    echo "/etc/fstab was not modified to avoid conflicting entries as this Azure file share was already present. You may want to double check /etc/fstab to ensure the configuration is as desired."
fi
sudo mount -a
---------------------------
$ chmod a+x azurefilesmount.sh
$ ./azurefilesmount.sh


#2.PostgresSQLインストール(dbサーバ
#2-1.インストール
$ sudo apt-get update
$ sudo apt-get -y install postgresql postgresql-contrib
$ sudo systemctl enable postgresql
$ sudo systemctl list-unit-files | grep postgres
$ psql --version
psql (PostgreSQL) 12.6 (Ubuntu 12.6-0ubuntu0.20.04.1)

#2-2.管理ユーザ追加
$ sudo -u postgres psql
=# ALTER ROLE postgres PASSWORD 'YOURPASSWORD';
ALTER ROLE
=# SELECT * FROM pg_shadow;
$ sudo -u postgres createuser -P redmine
Enter password for new role:YOURPASSWORD
Enter it again:YOURPASSWORD

#2-3.DB作成
$ sudo -u postgres createdb -E UTF-8 -l ja_JP.UTF-8 -O redmine -T template0 redmine
$ psql -U redmine -h localhost -d redmine
Password for user redmine:YOURPASSWORD
redmine-> \l
$ sudo systemctl stop postgresql
$ sudo systemctl start postgresql
$ psql -U redmine -h localhost -d redmine


#3.Redmineインストール
#3-1.ネットワークセキュリティグループ設定
あらかじめAzureポータルでネットワークセキュリティグループにてhttpとhttpsをオープンする

#3-2.nginxインストール
$ sudo apt -y install nginx
$ nginx -v
nginx version: nginx/1.18.0 (Ubuntu)

#3-3.Let'sEncrypt設定
$ sudo apt -y install certbot python3-certbot-nginx
$ sudo certbot --nginx -d YOURDOMAIN -d *.YOURDOMAIN
Saving debug log to /var/log/letsencrypt/letsencrypt.log
Plugins selected: Authenticator nginx, Installer nginx
Enter email address (used for urgent renewal and security notices) (Enter 'c' to
cancel):YOURMAILADRESS

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Please read the Terms of Service at
~略~
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
(A)gree/(C)ancel:A

~略~
(Y)es/(N)o:Y
~略~
   Donating to ISRG / Let's Encrypt:   https://letsencrypt.org/donate
   Donating to EFF:                    https://eff.org/donate-le

#3-4.nginx設定ファイル修正
$ sudo vi /etc/nginx/conf.d/local.conf
------------------------------
upstream unicorn-unix-domain-socket {
    server unix:/var/www/redmine/tmp/sockets/unicorn.sock fail_timeout=0;
}

server {
        listen 80; # httpへのアクセスをhttpsへリダイレクトする
        listen [::]:80;
        server_name  YOURDOMAIN;
        if ($http_x_forwarded_proto != https) {
            return 301 https://$host$request_uri;
        }
}

server {
    listen 443 ssl http2;
    listen [::]:443 ssl http2;
    ssl on;
    if ($host != "YOURDOMAIN"){
        return 444;
    }
    server_name  YOURDOMAIN;
    index  index.html index.htm index.php;
    client_max_body_size 1024M;
    ssl_stapling on;
    ssl_stapling_verify on;
    ssl_certificate /etc/letsencrypt/live/YOURDOMAIN/fullchain.pem; # managed by Certbot
    ssl_certificate_key /etc/letsencrypt/live/YOURDOMAIN/privkey.pem; # managed by Certbot
    include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot
    ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot

    location / {
        root /var/www/redmine;
        access_log /var/log/nginx/redmine_access.log;
        error_log /var/log/nginx/redmine_error.log;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header Host $http_host;
        proxy_pass http://unicorn-unix-domain-socket;
    }

}
------------------------------

#3-5.Rubyほか必要ツール類インストール
$ cd
$ git clone https://github.com/sstephenson/rbenv.git ~/.rbenv
$ git clone https://github.com/sstephenson/ruby-build.git ~/.rbenv/plugins/ruby-build
$ echo 'export PATH=~/.rbenv/bin:$PATH' >> ~/.bash_profile
$ echo 'eval "$(rbenv init -)"' >> ~/.bash_profile
$ source ~/.bash_profile
$ rbenv --version
rbenv 1.1.2-44-gd604acb
$ sudo apt -y install build-essential 
$ sudo apt -y install git build-essential libssl-dev libpq-dev
$ sudo apt -y install zlib1g-dev libxslt1-dev libreadline-dev libcurl4-openssl-dev
$ sudo apt -y install imagemagick libmagick++-dev
$ rbenv install 2.6.7
$ rbenv versions
$ rbenv global 2.6.7
$ ruby -v
ruby 2.6.7p197 (2021-04-05 revision 67941) [x86_64-linux]

#3-6.Redmine導入
$ cd /var/www
$ sudo git clone https://github.com/redmine/redmine.git redmine
$ sudo chown -R  ope_user redmine/
$ cd redmine
$ cp config/database.yml.example config/database.yml
$ sudo vi config/database.yml
---------------------------------------
# PostgreSQL configuration example
production:
  adapter: postgresql
  database: redmine
  host: localhost
  username: redmine
  password: YOURPASSWORD
  encoding: utf8
  pool: 5

development:
  adapter: postgresql
  database: redmine
  host: localhost
  username: redmine
  password: YOURPASSWORD
  encoding: utf8
  pool: 5
---------------------------------------
$ vi config/configuration.yml
--------------------------------------------
default:
  email_delivery:
    delivery_method: :smtp
    smtp_settings:
      address: "smtp.sendgrid.net"
      port: 587
      domain: "smtp.sendgrid.net"
      authentication: :login
      user_name: apikey
      password: YOURPASSWORD
  attachments_storage_path: /mnt/YOURSTORAGEACCOUNT/YOURFILESTORAGENAME
--------------------------------------------

#3-7.unicorn関連設定
$ vi Gemfile
※最後尾に追加
------------------
#Unicorn
gem "unicorn"
------------------
$ gem install rubygems-update
Fetching rubygems-update-3.2.16.gem
~中略~
Done installing documentation for rubygems-update after 170 seconds
1 gem installed
$ update_rubygems
$ gem install bundler
$ gem install daemon_controller rack passenger
$ bundle update
$ bundle install --path vendor/bundler --without development test
$ bundle exec rake generate_secret_token
$ bundle exec rake db:migrate RAILS_ENV=production

#3-8.設定ファイル編集
#unicornファイル
$ vi config/unicorn.rb
--------------------------------------------
# Railsのルートパスを求める。(RAILS_ROOT/config/unicorn.rbに配置している場合。)
rails_root = File.expand_path('../../', __FILE__)
# RAILS_ENVを求める。(RAILS_ENV毎に挙動を変更したい場合に使用。今回は使用しません。)
# rails_env = ENV['RAILS_ENV'] || "development"
 
# 追記に記載してます。入れた方がいいです。
ENV['BUNDLE_GEMFILE'] = rails_root + "/Gemfile"
 
# Unicornは複数のワーカーで起動するのでワーカー数を定義
# サーバーのメモリなどによって変更すること。
worker_processes 2
 
# 指定しなくても良い。
# Unicornの起動コマンドを実行するディレクトリを指定します。
# (記載しておけば他のディレクトリでこのファイルを叩けなくなる。)
working_directory rails_root
 
# 接続タイムアウト時間
timeout 30
 
# Unicornのエラーログと通常ログの位置を指定。
stderr_path File.expand_path('../../log/unicorn_stderr.log', __FILE__)
stdout_path File.expand_path('../../log/unicorn_stdout.log', __FILE__)
 
# Nginxで使用する場合は以下の設定を行う(※このパスをNginx側で設定したパスと揃えておく必要があります)。
listen File.expand_path('../../tmp/sockets/unicorn.sock', __FILE__)
# とりあえず起動して動作確認をしたい場合は以下の設定を行う。
#listen 8080
# ※「backlog」や「tcp_nopush」の設定もあるけど、よくわかって無い。
 
# プロセスの停止などに必要なPIDファイルの保存先を指定。
pid File.expand_path('../../tmp/pids/unicorn.pid', __FILE__)
 
# 基本的には`true`を指定する。Unicornの再起動時にダウンタイムなしで再起動が行われる。
preload_app true
# 効果なしとの記事を見たので、コメントアウト。
# GC.respond_to?(:copy_on_write_friendly=) and GC.copy_on_write_friendly = true
 
# USR2シグナルを受けると古いプロセスを止める。
# 後述するが、記述しておくとNginxと連携する時に良いことがある。
before_fork do |server, worker|
  defined?(ActiveRecord::Base) and
      ActiveRecord::Base.connection.disconnect!
 
  old_pid = "#{server.config[:pid]}.oldbin"
  if old_pid != server.pid
    begin
      sig = (worker.nr + 1) >= server.worker_processes ? :QUIT : :TTOU
      Process.kill(sig, File.read(old_pid).to_i)
    rescue Errno::ENOENT, Errno::ESRCH
    end
  end
end
 
after_fork do |server, worker|
  defined?(ActiveRecord::Base) and ActiveRecord::Base.establish_connection
end
--------------------------------------------
$ bundle exec rails generate task unicorn

#unicorn起動コマンド
$ vi lib/tasks/unicorn.rake
----------------------------
namespace :unicorn do
  desc "Start unicorn for production env."
  task(:start) do
    config_path = "/var/www/redmine/config/unicorn.rb"
    sh "unicorn_rails -c #{config_path} -E production -D"
  end

  desc "Stop unicorn"
  task(:stop) { unicorn_signal :QUIT }

  desc "Restart unicorn with USR2"
  task(:restart) { unicorn_signal :USR2 }

  desc "Increment number of worker processes"
  task(:increment) { unicorn_signal :TTIN }

  desc "Decrement number of worker processes"
  task(:decrement) { unicorn_signal :TTOU }

  desc "Unicorn pstree (depends on pstree command)"
  task(:pstree) do
    sh "pstree '#{unicorn_pid}'"
  end

  def unicorn_signal signal
    Process.kill signal, unicorn_pid
  end

  def unicorn_pid
    begin
      File.read("/var/www/redmine/tmp/pids/unicorn.pid").to_i
    rescue Errno::ENOENT
      raise "Unicorn doesn't seem to be running"
    end
  end
end
----------------------------

#unicorn自動起動設定
$ sudo vi /etc/init.d/unicorn
--------------------------------------------
#!/bin/sh
# chkconfig: 345 90 20
# description: Redmine
# processname: unicorn_redmine
 
RAILS_ENV=production
SERVICE=redmine
USER=ope_user
 
RAILS_ROOT_DIR="/var/www/redmine"
 
PID=${RAILS_ROOT_DIR}/tmp/pids/unicorn.pid
UNICORN_CONF=${RAILS_ROOT_DIR}/config/unicorn.rb
 
UNICORN_ALIVE=`ps aux|grep '${UNICORN_CONF}'|grep -v grep|wc -l`
 
start()
{
  if [ $UNICORN_ALIVE = 0 ]; then
    rm -f $PID
  fi
  if [ -e ${PID} ]; then
    echo "${SERVICE} already started"
    exit 1
  fi
  echo "start ${SERVICE}"
  sudo su -l ${USER} -c "cd ${RAILS_ROOT_DIR} && bundle exec unicorn_rails -c ${UNICORN_CONF} -D"
}
 
stop()
{
  if [ ! -e ${PID} ]; then
    echo "${SERVICE} not started"
    exit 1
  fi
  echo "stop ${SERVICE}"
  kill -QUIT `cat ${PID}`
}
 
force_stop()
{
  if [ ! -e ${PID} ]; then
    echo "${SERVICE} not started"
    exit 1
  fi
  echo "stop ${SERVICE}"
  kill -INT `cat ${PID}`
}
 
reload()
{
  if [ ! -e ${PID} ]; then
    echo "${SERVICE} not started"
    start
    exit 0
  fi
  echo "reload ${SERVICE}"
  kill -USR2 `cat ${PID}`
}
 
restart()
{
  if [ -e ${PID} ]; then
    stop
    sleep 3
  fi
  start
}
 
case "$1" in
  start)
    start
    ;;
  stop)
    stop
    ;;
  force-stop)
    force_stop
    ;;
  reload)
    reload
    ;;
  restart)
    restart
    ;;
  *)
    echo "Syntax Error: release [start|stop|force-stop|reload|restart]"
    ;;
esac
--------------------------------------------
$ sudo chmod 755 /etc/init.d/unicorn

#サービス設定ファイル
$ sudo vi /lib/systemd/system/unicorn.service
--------------------------------------------
[Unit]
Description=Unicorn Server
After=postgresql.service

[Service]
WorkingDirectory=/var/www/redmine
Environment=RAILS_ENV=production
SyslogIdentifier=unicorn
PIDFile=/var/www/redmine/tmp/pids/unicorn.pid

ExecStart=/home/ope_user/.rbenv/shims/bundle exec "unicorn_rails -c config/unicorn.rb -E production -D"
ExecStop=/usr/bin/kill -QUIT $MAINPID
ExecReload=/bin/kill -USR2 $MAINPID

[Install]
WantedBy=multi-user.target
--------------------------------------------
$ sudo chmod 755 /lib/systemd/system/unicorn.service
$ sudo ln -s /lib/systemd/system/unicorn.service /etc/systemd/system/multi-user.target.wants/unicorn.service
$ sudo systemctl start unicorn.service
$ sudo systemctl stop unicorn.service
$ sudo systemctl enabled unicorn.service
~エラーが出るが無視しても問題なし~

$ sudo service nginx restart
$ sudo reboot
#4.リマインダーおよびプラグイン関連
#リマインダー
$ crontab -e
-----------------------------
# m h  dom mon dow   command
30 6 * * * cd /var/www/redmine ; bundle exec rake redmine:send_reminders days=3 RAILS_ENV=production
-----------------------------
#プラグインは未導入(検討中)
redmine issue templates
redmine checklists
redmine issue badge
redmine issues tree
redmine absolute dates
redmine work time
redmine slack
view_customize


Ⅳ.仮想マシンのバックアップ

Azureの仮想マシンバックアップの機能を使用する。
※注意点としてリストア後はVMのsudo可能ユーザのパスワードリセットを行う必要がある

1.バックアップ

①バックアップおよびサイトの回復で「作成」を行う
②RecoveryServiceコンテナーの作成で必要事項を入力しコンテナーを作成する
③RecoveryContainerで[+バックアップ]を選択する
④バックアップの目標で[バックアップ]をクリックする
⑤バックアップの構成でバックアップポリシーを作成して、そのバックアップポリシーを選択する
⑥PolicyDetailsの内容を確認する。(自分の意図した設定となっているかを確認する)
⑦[バックアップの有効化]でジョブをデプロイする


◆参照サイト

・Azure関連


・PostgresSQLインストール


・nginxインストール


・Redmine


今回はGitでインストールしているので今後のマイナーバージョンアップの場合は
git pull origin masterで更新が反映できるようになるので少しは楽になるかなぁと。
で、今回色々とやってみて、ことのほかAzureファイル共有のパフォーマンスが
S3と比べて悪くはなかったのでDockerを使ってマウントしてみて
Postgreの永続化ファイルと添付ファイル分をAzureファイル共有に逃がせばもしかしたら
色々と楽できるのではないかと思った次第。
ほかにAzureADと連携させてみても面白そうですな。次回はDockerのネタで色々と試してみようかと思います。

コメント

このブログの人気の投稿

GASでGoogleDriveのサブフォルダとファイル一覧を出力する

証券外務員1種勉強(計算式暗記用メモ)

マクロ経済学(IS-LM分析)