Redmineのインストールをいい塩梅に半自動化する
日を置いてから 過去のブログのこれとかこれを参照してRedmine入れようとしてもなかなかうまいこと行かないことが多いのでむかついて、インストールをShellスクリプト化した。
プラグインとかcronの仕込みとかはできていないのと、SendGridでメール飛ぶか試せていないのでそこは今後、試していこうかなと思っていたりする。
ちなみに固定IP取ってDNSに登録すれば
AWS:EC2+RDS、EC2単体
GCP:GCE+CloudSQL(PostgreSQL)、GCE単体
上記2つで動くところまでは見れてます。
細かな部分はチューニングすれば、まぁ最小の労力でRedmine立てれるな。というより4年前に作っとけよって話ですよな・・・・。
◆Shellスクリプト
#!/bin/bash
SHELL_USER=yourexec_user
HOST_NAME=redmine-srv
POSTGRE_VER=postgresql-15
DB_VERSION=15
DATABASE=redmine
MASTER_USER=postgres
DB_USER=redmine
DB_PASSWORD=redmine
MAIL_ADDORESS=smtp.sendgrid.net
MAIL_DOMAIN=smtp.sendgrid.net
PORT=587
MAIL_DOMAIN=smtp.sendgrid.net
MAIL_USER_NAME=apikey
MAIL_PASSWORD=SG.XXXXXXXX
ATTATCHMENT_PATH=/var/www/redmine/files
RUBY_VER=3.2.2
WEB_USER=www-data
SERVER_NAME=web.example.com
SITE_URL=https://web.example.com/
DOCUMENT_ROOT=/var/www/html
ADMIN_MAIL=yourmail@example.com
sudo hostnamectl set-hostname ${HOST_NAME}
# ---------------------------------------------
# 1.nginxインストール
# ---------------------------------------------
read -p "## Do you want to install nginx? (y/n) [y]: " -e -i "y" nginxResponseinput
if [ "$nginxResponseinput" == "y" ] || [ "$nginxResponseinput" == "Y" ]; then
echo "# install nginx process..."
sudo apt install -y curl gnupg2 ca-certificates lsb-release ubuntu-keyring
curl https://nginx.org/keys/nginx_signing.key | gpg --dearmor \
| sudo tee /usr/share/keyrings/nginx-archive-keyring.gpg >/dev/null
echo "deb [signed-by=/usr/share/keyrings/nginx-archive-keyring.gpg] \
http://nginx.org/packages/ubuntu `lsb_release -cs` nginx" \
| sudo tee /etc/apt/sources.list.d/nginx.list
sudo apt update
sudo apt install -y nginx
sudo tee /etc/nginx/nginx.conf <<_EOF_
user ${WEB_USER};
worker_processes auto;
pid /run/nginx.pid;
events {
worker_connections 1024;
}
http {
##
# Basic Settings
##
sendfile on;
tcp_nopush on;
tcp_nodelay on;
keepalive_timeout 65;
types_hash_max_size 2048;
server_tokens off;
# MIME
include /etc/nginx/mime.types;
default_type application/octet-stream;
##
# SSL Settings
##
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers 'TLS_AES_128_GCM_SHA256:TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384';
ssl_prefer_server_ciphers off;
ssl_session_timeout 1d;
ssl_session_cache shared:MozSSL:10m;
ssl_session_tickets off;
ssl_stapling on;
ssl_stapling_verify on;
resolver 8.8.8.8 8.8.4.4 valid=300s;
resolver_timeout 5s;
##
# Security Headers
##
add_header Strict-Transport-Security "max-age=63072000; includeSubDomains; preload";
add_header X-Content-Type-Options nosniff;
add_header X-Frame-Options "SAMEORIGIN";
add_header X-XSS-Protection "1; mode=block";
##
# Logging Settings
##
access_log /var/log/nginx/access.log;
error_log /var/log/nginx/error.log;
##
# Gzip Settings
##
gzip on;
gzip_disable "msie6";
# Virtual Host Configs
include /etc/nginx/conf.d/*.conf;
include /etc/nginx/sites-enabled/*;
}
_EOF_
sudo systemctl enable nginx
sudo systemctl start nginx
echo "# Install nginx done!"
fi
# ---------------------------------------------
# 2.postgreSQLインストール RDS使う場合はnとする必要あり
# ---------------------------------------------
read -p "## Do you want to install postgress? (y/n) [y]: " -e -i "y" pgResponseinput
if [ "$pgResponseinput" == "y" ] || [ "$pgResponseinput" == "Y" ]; then
echo "# install postgres process..."
sudo apt install -y software-properties-common gnupg postgresql-common apt-transport-https lsb-release wget
sudo /usr/share/postgresql-common/pgdg/apt.postgresql.org.sh
echo "deb https://packagecloud.io/timescale/timescaledb/ubuntu/ $(lsb_release -c -s) main" | sudo tee /etc/apt/sources.list.d/timescaledb.list
wget --quiet -O - https://packagecloud.io/timescale/timescaledb/gpgkey | sudo apt-key add -
sudo apt update
sudo apt install -y ${POSTGRE_VER}
#localhost Listenの有効化
sudo sed -i "/#listen_addresses/a listen_addresses = 'localhost'" /etc/postgresql/${DB_VERSION}/main/postgresql.conf
sudo systemctl restart postgresql
echo "# Install Postgres done!"
fi
#
# ホスト名設定
#
read -p "Enter databasehost info: " -e -i "localhost" ENDPOINT
# 入力が空欄の場合は終了
if [ -z "$ENDPOINT" ]; then
echo "Endpoint cannot be empty. Exiting..."
exit 1
fi
#
# ローカルホストDB使用の場合、外部DB使用の場合はn選択
#
read -p "## Do you want to Setting localDataBase? (y/n) [y]: " -e -i "y" localDBResponseinput
if [ "$localDBResponseinput" == "y" ] || [ "$localDBResponseinput" == "Y" ]; then
echo "# Please password input ${DB_PASSWORD} "
sudo -u postgres createuser --pwprompt ${DB_USER}
sudo -u postgres createdb -E UTF-8 -l ja_JP.UTF-8 -O ${DB_USER} ${DATABASE} -T template0 ${DATABASE}
echo "# Setting Postgres done!"
fi
#
# ローカルホスト以外にDBをインストールする場合
#
echo "## RemoteDatabase Setting start"
read -p "## Do you want to use RemoteDatabase? (y/n) [y]: " -e -i "n" remoteDBResponseinput
if [ "$remoteDBResponseinput" == "y" ] || [ "$remoteDBResponseinput" == "Y" ]; then
#
# Postgreクライアントインストール
#
sudo apt install -y software-properties-common gnupg postgresql-common apt-transport-https lsb-release wget
sudo /usr/share/postgresql-common/pgdg/apt.postgresql.org.sh
echo "deb https://packagecloud.io/timescale/timescaledb/ubuntu/ $(lsb_release -c -s) main" | sudo tee /etc/apt/sources.list.d/timescaledb.list
wget --quiet -O - https://packagecloud.io/timescale/timescaledb/gpgkey | sudo apt-key add -
sudo apt update
sudo apt install -y postgresql-client
#
# リモートにDB作成
#
echo "# please password input RemoteDatabase password !"
psql --host=${ENDPOINT} --port=5432 --username=${MASTER_USER} <<_EOF
\set ON_ERROR_STOP on
-- ロールの作成
CREATE ROLE ${DB_USER} WITH PASSWORD '${DB_PASSWORD}' LOGIN;
-- ロールへの権限付与
GRANT ${DB_USER} TO ${MASTER_USER};
-- データベースの作成
CREATE DATABASE ${DATABASE} OWNER ${DB_USER};
_EOF
fi
#---------------------------------------------
# 3.Rubyインストール
#---------------------------------------------
read -p "## Do you want to install Ruby? (y/n) [y]: " -e -i "y" rbResponseinput
if [ "$rbResponseinput" == "y" ] || [ "$rbResponseinput" == "Y" ]; then
echo "# install postgres process..."
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' >> ~/.bashrc
echo 'eval "$(rbenv init -)"' >> ~/.bashrc
sudo apt install -y \
curl \
libssl-dev \
libreadline-dev \
zlib1g-dev \
autoconf \
bison \
build-essential \
libyaml-dev \
libreadline-dev \
libncurses5-dev \
libffi-dev \
libpq-dev \
libgdbm-dev
export PATH=~/.rbenv/bin:$PATH
eval "$(rbenv init -)"
rbenv install ${RUBY_VER}
rbenv global ${RUBY_VER}
echo "# Install Ruby done!"
fi
#---------------------------------------------
# 4.Redmine導入
#---------------------------------------------
read -p "## Do you want to install Redmine? (y/n) [y]: " -e -i "y" rmResponseinput
if [ "$rmResponseinput" == "y" ] || [ "$rmResponseinput" == "Y" ]; then
echo "# install Redmine setting process..."
sudo git clone https://github.com/redmine/redmine.git /var/www/redmine
#
# Database設定
#
sudo tee /var/www/redmine/config/database.yml <<_EOF_
# PostgreSQL configuration example
production:
adapter: postgresql
database: ${DATABASE}
host: ${ENDPOINT}
username: ${DB_USER}
password: ${DB_PASSWORD}
encoding: utf8
pool: 5
development:
adapter: postgresql
database: ${DATABASE}
host: ${ENDPOINT}
username: ${DB_USER}
password: ${DB_PASSWORD}
encoding: utf8
pool: 5
_EOF_
#
# 設定ファイル
#
sudo tee /var/www/redmine/config/configuration.yml <<_EOF_
default:
email_delivery:
delivery_method: :smtp
smtp_settings:
address: "${MAIL_ADDORESS}"
port: ${PORT}
domain: "${MAIL_DOMAIN}"
authentication: :login
user_name: ${MAIL_USER_NAME}
password: ${MAIL_PASSWORD}
attachments_storage_path: ${ATTATCHMENT_PATH}
_EOF_
#
# unicorn設定
#
echo '#Unicorn' | sudo tee -a /var/www/redmine/Gemfile
echo 'gem "unicorn"' | sudo tee -a /var/www/redmine/Gemfile
sudo tee /var/www/redmine/config/unicorn.rb <<_EOF_
# 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
_EOF_
sudo tee /var/www/redmine/lib/tasks/unicorn.rake <<_EOF_
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
_EOF_
# 起動スクリプト
echo "#!/bin/sh
# chkconfig: 345 90 20
# description: Redmine
# processname: unicorn_redmine
RAILS_ENV=production
SERVICE=redmine
USER=${WEB_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 tee /etc/init.d/unicorn
sudo chmod 755 /etc/init.d/unicorn
sudo tee /lib/systemd/system/unicorn.service <<_EOF_
[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/${SHELL_USER}/.rbenv/shims/bundle exec "unicorn_rails -c /var/www/redmine/config/unicorn.rb -E production -D"
ExecStop=/usr/bin/kill -QUIT $MAINPID
ExecReload=/bin/kill -USR2 $MAINPID
[Install]
WantedBy=multi-user.target
_EOF_
# gemインストール
sudo chown -R ${SHELL_USER} /var/www/redmine
cd /var/www/redmine
gem install rubygems-update
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
bundle exec rails generate task unicornlsあー
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 enabled unicorn.service
sudo mkdir ${ATTATCHMENT_PATH}
sudo chown -R ${WEB_USER} ${ATTATCHMENT_PATH}
sudo chown -R ${WEB_USER} /var/www/redmine
fi
# ---------------------------------------------
# 5.SSL設定 Let'sEncrypt使用しない場合はn
# ---------------------------------------------
sudo rm /etc/nginx/conf.d/default.conf
read -p "## Do you want to install Let's Encrypt? (y/n) [y]: " -e -i "y" sslResponseinput
if [ "$sslResponseinput" == "y" ] || [ "$sslResponseinput" == "Y" ]; then
echo "# install Let's Encrypt process..."
sudo mkdir /var/www/redmine/.well-known
sudo chown -R ${WEB_USER}:${WEB_USER} /var/www/redmine
#
# Let'sEncrypt初回用
#
cat <<_EOF_ | sudo tee /etc/nginx/conf.d/local.conf
server {
listen 80;
server_name ${SERVER_NAME};
index index.html index.htm index.php;
root /var/www/redmine;
location ^~ /.well-known/acme-challenge/ {
allow all;
root /var/www/redmine;
default_type "text/plain";
try_files \$uri =404;
}
}
_EOF_
sudo systemctl stop nginx
sudo systemctl start nginx
sudo apt -y install certbot
sudo certbot certonly --webroot -w /var/www/redmine -d ${SERVER_NAME} --agree-tos --email ${ADMIN_MAIL} --non-interactive
#
# config準備
#
cat <<_EOF_ | sudo tee /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 ${SERVER_NAME};
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 != "${SERVER_NAME}"){
return 444;
}
server_name ${SERVER_NAME};
index index.html index.htm index.php;
client_max_body_size 1024M;
ssl_stapling on;
ssl_stapling_verify on;
ssl_certificate /etc/letsencrypt/live/${SERVER_NAME}/fullchain.pem; # managed by Certbot
ssl_certificate_key /etc/letsencrypt/live/${SERVER_NAME}/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;
}
location ^~ /.well-known/acme-challenge/ {
allow all;
root /var/www/redmine;
default_type "text/plain";
try_files \$uri =404;
}
}
_EOF_
echo "# Install Let'sEncrypt done!"
fi
# ---------------------------------------------
# 自己証明書使用時
# ---------------------------------------------
read -p "## Do you want to use self cert? (y/n) [y]: " -e -i "n" selfcertResponseinput
if [ "$selfcertResponseinput" == "y" ] || [ "$selfcertResponseinput" == "Y" ]; then
echo "# install setting self cert process..."
sudo mkdir /etc/nginx/ssl
sudo openssl genrsa -out /etc/nginx/ssl/server.key 2048
sudo openssl req -new -key /etc/nginx/ssl/server.key -out /etc/nginx/ssl/server.csr
sudo openssl x509 -days 3650 -req -signkey /etc/nginx/ssl/server.key -in /etc/nginx/ssl/server.csr -out /etc/nginx/ssl/server.crt
# config準備
cat <<_EOF_ | sudo tee /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 "${SERVER_NAME}";
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 != "${SERVER_NAME}"){
return 444;
}
server_name "${SERVER_NAME}";
index index.html index.htm index.php;
client_max_body_size 1024M;
ssl_certificate /etc/nginx/ssl/server.crt;
ssl_certificate_key /etc/nginx/ssl/server.key;
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;
}
}
_EOF_
echo "# Setting self cert done!"
fi
#
# nginx再起動
#
sudo service nginx restart
というよりDockerですりゃいいだけの話なんですが・・・、中にはDockerじゃダメとかいうなんとやらなところもあるわけでゲフンゲフン
コメント