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じゃダメとかいうなんとやらなところもあるわけでゲフンゲフン
コメント