Redmine2.6 + Nginx + CentOS7

์†Œ๊ฐœ



๊ฐ€๋” ์„ธ์šธ ์ˆ˜ ์žˆ์œผ๋ฏ€๋กœ ๋ฉ”๋ชจํ•ด ๋‘”๋‹ค.
์ž˜๋ชป๋˜๋ฉด ์ง€์  ๋ถ€ํƒ๋“œ๋ฆฝ๋‹ˆ๋‹ค.

๊ธฐ๋ณธ์ ์œผ๋กœ
htp : // bg. ์–ด d ๋ฏธ๋„ค. jp/์•„๋ฆฌ์น˜ใ‡s/2_6/์ธ sํƒ€์น˜์˜จ_์ „๊ณผ s/
๊ฐ™์€ ์ ˆ์ฐจ.

ํ™˜๊ฒฝ


  • OS: CentOS7
  • Ruby: 2.1.5
  • Redmine: 2.6.1
  • Nginx: nginx/1.6.2
  • Unicorn: 4.8.3

  • Redmine ๊ด€๋ จ Package ์„ค์น˜



    Redmine ์„ค์น˜์— ํ•„์š”ํ•œ ํŒจํ‚ค์ง€ ์„ค์น˜.
    DB์—๋Š” MariaDB๋ฅผ ์ด์šฉ
    $ sudo yum -y groupinstall "Development Tools"
    $ sudo yum -y install openssl-devel readline-devel zlib-devel curl-devel libyaml-devel
    $ sudo yum -y install mariadb-server mariadb-devel
    $ sudo yum -y install ImageMagick ImageMagick-devel ipa-pgothic-fonts
    

    Ruby ์„ค์น˜



    rbenv ํ™˜๊ฒฝ์—์„œ Ruby2.1.5๋ฅผ ์„ค์น˜ํ•ฉ๋‹ˆ๋‹ค.

    install
    $ sudo yum install gcc make openssl openssl-devel
    
    $ cd /usr/local/
    $ sudo git clone git://github.com/sstephenson/rbenv.git rbenv
    $ mkdir -p rbenv/shims rbenv/versions
    $ sudo groupadd /usr/local/rbenv
    $ sudo chgrp -R rbenv rbenv/
    $ sudo git clone git://github.com/sstephenson/ruby-build.git /usr/local/rbenv/ruby-build
    $ cd /usr/local/rbenv/ruby-build
    $ ./install.sh
    

    ํ™˜๊ฒฝ ๋ณ€์ˆ˜ ์„ค์ • ํŒŒ์ผ ์ž‘์„ฑ.

    /etc/profile.d/rbenv.sh
    export RBENV_ROOT="/usr/local/rbenv"
    export PATH="/usr/local/rbenv/bin:$PATH"
    eval "$(rbenv init -)"
    
    $ source /etc/profile.d/rbenv.sh
    $ sudo rbenv install -v 2.1.5
    $ rbenv versions
    * system (set by /usr/local/rbenv/version)
      2.1.3
    $ sudo rbenv global 2.1.3
    $ rbenv versions
      system
    * 2.1.5 (set by /usr/local/rbenv/version)
    $ ruby --version
    ruby 2.1.5p273 (2014-11-13 revision 48405) [x86_64-linux]
    $
    

    Bundler ์„ค์น˜


    $ sudo gem install bundler --no-rdoc --no-ri
    $ bundle --version
    Bundler version 1.7.12
    $
    

    MariaDB ์„ค์ •



    ์šฐ์„ ์€ MariaDB์˜ ์„ค์ •.

    /etc/my.cnf
    [mysqld]
    datadir=/data/mysql # Dataใƒ‡ใ‚ฃใƒฌใ‚ฏใƒˆใƒชใ€ไปปๆ„
    socket=/var/lib/mysql/mysql.sock
    # Disabling symbolic-links is recommended to prevent assorted security risks
    symbolic-links=0
    # Settings user and group are ignored when systemd is used.
    # If you need to run mysqld under a different user or group,
    # customize your systemd unit file for mariadb according to the
    # instructions in http://fedoraproject.org/wiki/Systemd
    
    character-set-server=utf8
    
    [mysqld_safe]
    log-error=/var/log/mariadb/mariadb.log
    pid-file=/var/run/mariadb/mariadb.pid
    
    #
    # include all files from the config directory
    #
    !includedir /etc/my.cnf.d
    
    [mysql]
    default-character-set=utf8
    

    ๋ฐ์ดํ„ฐ ๋””๋ ‰ํ† ๋ฆฌ ์ƒ์„ฑ ๋ฐ ์ž๋™ ์‹œ์ž‘ ์„ค์ •.
    $ sudo mkdir -p /data/mysql # ใƒ‡ใƒผใ‚ฟใƒ‡ใ‚ฃใƒฌใ‚ฏใƒˆใƒชใฎไฝœๆˆ
    $ sudo chown mysql:mysql /data/mysql
    $ sudo service mariadb start
    $ sudo systemctl enable mariadb
    

    ๊ธฐ๋ณธ ์„ค์ •์„ mysql_secure_installation ์—์„œ ๋ฃจํŠธ ์•”ํ˜ธ๋ฅผ ์„ค์ •ํ•ฉ๋‹ˆ๋‹ค.
    $ mysql_secure_installation
    NOTE: RUNNING ALL PARTS OF THIS SCRIPT IS RECOMMENDED FOR ALL MariaDB
          SERVERS IN PRODUCTION USE!  PLEASE READ EACH STEP CAREFULLY!
    
    In order to log into MariaDB to secure it, we'll need the current
    password for the root user.  If you've just installed MariaDB, and
    you haven't set the root password yet, the password will be blank,
    so you should just press enter here.
    
    Enter current password for root (enter for none): 
    OK, successfully used password, moving on...
    
    Setting the root password ensures that nobody can log into the MariaDB
    root user without the proper authorisation.
    
    Set root password? [Y/n] y
    New password: ${root_passwd}
    Re-enter new password: ${root_passwd}
    Password updated successfully!
    Reloading privilege tables..
     ... Success!
    
    
    By default, a MariaDB installation has an anonymous user, allowing anyone
    to log into MariaDB without having to have a user account created for
    them.  This is intended only for testing, and to make the installation
    go a bit smoother.  You should remove them before moving into a
    production environment.
    
    Remove anonymous users? [Y/n] y
     ... Success!
    
    Normally, root should only be allowed to connect from 'localhost'.  This
    ensures that someone cannot guess at the root password from the network.
    
    Disallow root login remotely? [Y/n] y
     ... Success!
    
    By default, MariaDB comes with a database named 'test' that anyone can
    access.  This is also intended only for testing, and should be removed
    before moving into a production environment.
    
    Remove test database and access to it? [Y/n] y
     - Dropping test database...
     ... Success!
     - Removing privileges on test database...
     ... Success!
    
    Reloading the privilege tables will ensure that all changes made so far
    will take effect immediately.
    
    Reload privilege tables now? [Y/n] y
     ... Success!
    
    Cleaning up...
    
    All done!  If you've completed all of the above steps, your MariaDB
    installation should now be secure.
    
    Thanks for using MariaDB!
    $
    

    ์ดˆ๊ธฐ ์„ค์ • ํ›„๋Š” redmine์šฉ์˜ DB redmine ์™€ ๊ด€๋ฆฌ์ž ์œ ์ €์˜ redmine ๋ฅผ ์ž‘์„ฑ.
    $ mysql -uroot -p
    Enter password: ${mysql_root_password}
    Welcome to the MariaDB monitor.  Commands end with ; or \g.
    Your MariaDB connection id is 10
    Server version: 5.5.40-MariaDB MariaDB Server
    
    Copyright (c) 2000, 2014, Oracle, Monty Program Ab and others.
    
    Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
    
    MariaDB [(none)]> 
    MariaDB [(none)]> 
    MariaDB [(none)]> CREATE DATABASE redmine DEFAULT character set utf8;
    Query OK, 1 row affected (0.00 sec)
    
    MariaDB [(none)]> grant all on redmine.* TO redmine@localhost identified by '${redmine_passwd}';
    Query OK, 0 rows affected (0.00 sec)
    
    MariaDB [(none)]> flush privileges;
    Query OK, 0 rows affected (0.00 sec)
    
    MariaDB [(none)]> exit;
    $
    

    Redmine ์„ค์น˜



    ์šฐ์„ ์€ ์†Œ์Šค์˜ ๋‹ค์šด๋กœ๋“œ์™€ ์ „๊ฐœ.
    ๊ทธ ํ›„ ์‹ฌ๋ณผ๋ฆญ ๋งํฌ๋ฅผ ์ž‘์„ฑ.
    $ cd /usr/local/src
    $ sudo curl -O http://www.redmine.org/releases/redmine-2.6.1.tar.gz
    $ sudo tar zxvf redmine-2.6.1.tar.gz
    $ sudo ln -s ./redmine-2.6.1 /opt/redmine # /opt/redmineใซใ‚ทใƒณใƒœใƒชใƒƒใ‚ฏใƒชใƒณใ‚ฏใ‚’ไฝœๆˆ
    

    ๋‹ค์Œ redmine database ์„ค์ •.
    ์šฐ์„  example ํŒŒ์ผ์„ ๋ณต์‚ฌ.
    $ sudo cp -p /opt/redmine/config/database.yml.example /opt/redmine/config/database.yml
    $ 
    

    ๋‹ค์Œ์— ๋ฐฉ๊ธˆ MariaDB๋กœ ์ž‘์„ฑํ•œ ์œ ์ €์™€ DB๋ฅผ ์ง€์ •.

    /opt/redmine/config/database.yml
    # Default setup is given for MySQL with ruby1.9. If you're running Redmine
    # with MySQL and ruby1.8, replace the adapter name with `mysql`.
    # Examples for PostgreSQL, SQLite3 and SQL Server can be found at the end.
    # Line indentation must be 2 spaces (no tabs).
    
    production:
      adapter: mysql2
      database: redmine
      host: localhost
      username: redmine
      password: "${redmine_passwd}"
      encoding: utf8
    

    ์ดํ•˜ DB ํฌํ•จํ•œ ์ดˆ๊ธฐ ์„ค์ •.
    $ cd /opt/redmine
    $ bundle install --without development test --path vendor/bundle
    $ bundle exec rake generate_secret_token
    $ RAILS_ENV=production bundle exec rake db:migrate
    

    Unicorn ์„ค์น˜



    ๋‹ค์Œ์œผ๋กœ Nginx์™€ Redmine์„ ์—ฐ๊ฒฐํ•˜๋Š” Unicorn์„ ์„ค์น˜.
    Gem ํŒŒ์ผ (/opt/redmine) ํŽธ์ง‘ ํ›„,

    /opt/redmine/Gemfile
    gem 'unicorn', '4.8.3'
    

    ์„ค์น˜ํ•ฉ๋‹ˆ๋‹ค.
    $ bundle install
    

    ๋‹ค์Œ์œผ๋กœ redmine์šฉ์˜ ํ™˜๊ฒฝ ๋ณ€์ˆ˜๋ฅผ ์„ค์ •.

    /etc/profile.d/redmine.sh
    RAILS_ROOT=/opt/redmine
    export RAILS_ROOT
    

    ํ™˜๊ฒฝ ๋ณ€์ˆ˜์˜ ๋ฐ˜์˜.
    $ source /etc/profile.d/redmine.sh
    

    ์•„๋ž˜ Unicorn ์„ค์ • ํŒŒ์ผ.

    Scoket ํŒŒ์ผ์— ๋Œ€ํ•ด์„œ์ž…๋‹ˆ๋‹ค๋งŒ,/tmp/ํ•˜ํ•˜์— ๋‘๋ฉด Nginx๋กœ not found ์—๋Ÿฌ๊ฐ€ ๋ฉ๋‹ˆ๋‹ค.
    ใ…‡ใ…‡ใ…‡ใ…‡ใ…‡ใ…‡ใ…ใ…ใ… ์ฝ” m / ์ฟ ์— s ์น˜์˜จ s / 463993 / ๋‹Œ๊ธด x - ์šฐ์— x - ๋„๋งˆ ใƒณ - ์†Œ c t - ์—๋กœ r / 464025 # 464025

    /opt/redmine/config/unicorn.rb
    # -*- coding: utf-8 -*-
    # ใƒฏใƒผใ‚ซใƒผใฎๆ•ฐ
    worker_processes 2
    
    # ใ‚ฝใ‚ฑใƒƒใƒˆ
    listen  '/var/run/unicorn.sock'
    pid     '/var/run/unicorn.pid'
    
    # ใƒญใ‚ฐ
    log = File.expand_path('log/unicorn.log', ENV['RAILS_ROOT'])
    stderr_path File.expand_path('log/unicorn.log', ENV['RAILS_ROOT'])
    stdout_path File.expand_path('log/unicorn.log', ENV['RAILS_ROOT'])
    
    preload_app true
    GC.respond_to?(:copy_on_write_friendly=) and GC.copy_on_write_friendly = true
    
    before_fork do |server, worker|
    defined?(ActiveRecord::Base) and ActiveRecord::Base.connection.disconnect!
    
    old_pid = "#{ server.config[:pid] }.oldbin"
    unless old_pid == server.pid
      begin
       sig = (worker.nr + 1) >= server.worker_processes ? :QUIT : :TTOU
       Process.kill :QUIT, 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
    

    ์•„๋ž˜ ์‹œ์ž‘ ์Šคํฌ๋ฆฝํŠธ.

    /opt/redmine/script/unicorn.sh
    #!/bin/bash
    
    set -e
    
    TIMEOUT=60
    APP_ROOT=${RAILS_ROOT}
    PID=/var/run/unicorn.pid
    RAILS_ENV=production
    CMD="bundle exec unicorn -D -c $APP_ROOT/config/unicorn.rb -E $RAILS_ENV"
    action="$1"
    set -u
    
    old_pid="$PID.oldbin"
    
    cd $APP_ROOT || exit 1
    
    sig () {
        test -s "$PID" && kill -$1 `cat $PID`
    }
    
    oldsig () {
        test -s $old_pid && kill -$1 `cat $old_pid`
    }
    
    case $action in
    start)
        sig 0 && echo >&2 "Already running" && exit 0
        $CMD
        ;;
    stop)
        sig QUIT && rm -f ${PID} && exit 0
        echo >&2 "Not running"
        ;;
    force-stop)
        sig TERM && exit 0
        echo >&2 "Not running"
        ;;
    restart|reload)
        sig HUP && echo reloaded OK && exit 0
        echo >&2 "Couldn't reload, starting '$CMD' instead"
        $CMD
        ;;
    upgrade)
        if sig USR2 && sleep 2 && sig 0 && oldsig QUIT
        then
            n=$TIMEOUT
            while test -s $old_pid && test $n -ge 0
            do
                printf '.' && sleep 1 && n=$(( $n - 1 ))
            done
            echo
    
            if test $n -lt 0 && test -s $old_pid
            then
                echo >&2 "$old_pid still exists after $TIMEOUT seconds"
                exit 1
            fi
            exit 0
        fi
        echo >&2 "Couldn't upgrade, starting '$CMD' instead"
        $CMD
        ;;
    reopen-logs)
        sig USR1
        ;;
    *)
        echo >&2 "Usage: $0 <start|stop|restart|upgrade|force-stop|reopen-logs>"
        exit 1
        ;;
    esac
    

    Redmine์„ http://localhost/redmine/์™€ ๊ฐ™์ด ์„œ๋ธŒ๋””๋ ‰ํ† ๋ฆฌ๋กœ ์ฐธ์กฐํ•œ๋‹ค๋ฉด ๋‹ค์Œ๊ณผ ๊ฐ™์ด config.ru๋ฅผ ํŽธ์ง‘ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

    /opt/redmine/config.ru
    # This file is used by Rack-based servers to start the application.
    RAILS_RELATIVE_URL_ROOT="/redmine"
    require ::File.expand_path('../config/environment',  __FILE__)
    if RAILS_RELATIVE_URL_ROOT then
            map RAILS_RELATIVE_URL_ROOT do
                    run Rails.application
            end
    else
            run Rails.application
    end
    
    /redmine ๋ถ€๋ถ„์€ ์ž์‹ ์˜ ํ™˜๊ฒฝ์œผ๋กœ ๋Œ€์ฒดํ•˜์‹ญ์‹œ์˜ค.

    Nginx ์„ค์น˜



    ํŒจํ‚ค์ง€ ์„ค์น˜.
    $ sudo rpm -Uvh http://nginx.org/packages/centos/7/noarch/RPMS/nginx-release-centos-7-0.el7.ngx.noarch.rpm # Nginxใฎใƒ‘ใƒƒใ‚ฑใƒผใ‚ธใƒ€ใ‚ฆใƒณใƒญใƒผใƒ‰
    $ sudo yum -y install nginx
    

    ์„ค์ •.

    ๋ณธ๋ž˜๋ผ๋ฉด /etc/nginx/conf.d/redmine.conf ์™€ ๊ฐ™์ด ์จ์•ผ ํ•ฉ๋‹ˆ๋‹ค๋งŒ, ์ด๋ฒˆ์€ Ubuntu์™€ ๊ฐ™์ด sites-available, sites-enabled๋ฅผ ์ž‘์„ฑํ•ด ์„ค์ •ํ•ฉ๋‹ˆ๋‹ค.
    $ sudo mkdir -p /etc/nginx/sites-avaliable/ /etc/nginx/sites-enabled/
    

    ์•„๋ž˜ Nginx ๊ตฌ์„ฑ ํŒŒ์ผ.

    /etc/nginx/nginx.conf
    
    user  nginx;
    worker_processes  1;
    
    error_log  /var/log/nginx/error.log warn;
    pid        /var/run/nginx.pid;
    
    
    events {
        worker_connections  1024;
    }
    
    
    http {
        include       /etc/nginx/mime.types;
        default_type  application/octet-stream;
    
        log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
                          '$status $body_bytes_sent "$http_referer" '
                          '"$http_user_agent" "$http_x_forwarded_for"';
    
        access_log  /var/log/nginx/access.log  main;
    
        sendfile        on;
        #tcp_nopush     on;
    
        keepalive_timeout  65;
    
        #gzip  on;
    
        #include /etc/nginx/conf.d/*.conf;
        include /etc/nginx/sites-enabled/*;
    }
    

    ๊ทธ๋Ÿฐ ๋‹ค์Œ Redmine ์šฉ ๊ตฌ์„ฑ ํŒŒ์ผ./redmine ๋ฅผ redmine ์— ํ• ๋‹นํ•œ๋‹ค.
    ๋˜ SSL ํ†ต์‹ ์‹œํ‚ค๊ณ  ์‹ถ๊ธฐ ๋•Œ๋ฌธ์— SSL ๋Œ€์‘ํ•˜๊ณ  ์žˆ๋‹ค.

    /etc/nginx/sites-available/redmine
    upstream rails-unicorn {
        server unix:/var/run/unicorn.sock fail_timeout=0;
    }
    
    server {
        listen 80;
        server_name localhost;
        return 301 https://$host$request_uri;
    }
    
    server {
        listen 443;
        server_name localhost;
    
    
        ssl on;
        ssl_certificate /etc/nginx/ssl/redmine.crt;
        ssl_certificate_key /etc/nginx/ssl/redmine.key;
    
        ssl_session_timeout 5m;
    
        ssl_protocols SSLv3 TLSv1;
        ssl_ciphers ALL:!ADH:!EXPORT56:RC4+RSA:+HIGH:+MEDIUM:+LOW:+SSLv3:+EXP;
        ssl_prefer_server_ciphers on;
    
        #listen   80; ## listen for ipv4; this line is default and implied
        #listen   [::]:80 default ipv6only=on; ## listen for ipv6
    
        root /usr/share/nginx/html/public;
        index index.php index.html index.htm;
    
        # Make site accessible from http://localhost/
        server_name localhost;
    
        location /redmine/ {
            try_files $uri $uri.html $uri/index.html @rails-unicorn;
        }
        location ~ ^/assets/(.*) {
            alias /opt/redmine/public/assets/$1;
        }
    
        location @rails-unicorn {
                   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://rails-unicorn;
        }
    
        # Only for nginx-naxsi : process denied requests
        #location /RequestDenied {
            # For example, return an error code
            #return 418;
        #}
    
        error_page 404 /404.html;
    
        # redirect server error pages to the static page /50x.html
        #
        error_page 500 502 503 504 /50x.html;
        location = /50x.html {
            root /usr/share/nginx/html;
        }
    
    }
    

    ๊ตฌ์„ฑ ํŒŒ์ผ ํ™œ์„ฑํ™”./etc/nginx/sites-enabled/ ์— ์‹ฌ๋ณผ๋ฆญ ๋งํฌ๋ฅผ ๋งŒ๋“ญ๋‹ˆ๋‹ค.
    $ sudo ln -s /etc/nginx/sites-available/redmine /etc/nginx/sites-enabled/
    

    ๋‹ค์Œ์— Redmine์˜ HTML ํŒŒ์ผ์ด๋‚˜ CSS๋“ฑ์ด ์ €์žฅ๋˜์–ด ์žˆ๋‹ค /opt/redmine/public ์˜ ์‹ฌ๋ณผ๋ฆญ ๋งํฌ๋ฅผ ๋ฌธ์„œ ๋ฃจํŠธ ๋ฐ”๋กœ ์•„๋ž˜์— ์ž‘์„ฑ
    $ sudo ln -s /opt/redmine/public/ /usr/share/nginx/html/
    

    Unicorn๊ณผ Nginx ์‹œ์ž‘.
    $ cd /opt/redmine
    $ sudo ./script/unicorn.sh start
    $ sudo service nginx start
    

    ์•ก์„ธ์Šค



    ์ดํ•˜ ๋‚˜์˜ค๋ฉด k.



    ์ดˆ๊ธฐ ๊ด€๋ฆฌ์ž์˜ username/password๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค.
    admin/admin
    

    ๊ฒฐ๋ก 



    Redmine2.6์—์„œ๋Š” Wiki๊ฐ€ Markdown์— ๋Œ€์‘ํ•œ ๊ฒƒ ๊ฐ™๋‹ค.

    ์ถ”๊ฐ€



    ์ƒ๋‹นํžˆ ๋ˆ„๋ฝ์ด ์žˆ์—ˆ๊ธฐ ๋•Œ๋ฌธ์— ์ถ”๊ฐ€ (2015/02/02)
    ์ด ๊ธฐ์‚ฌ๋ฅผ ์ฐธ๊ณ ๋กœ ํ™˜๊ฒฝ์„ ๊ตฌ์ถ•ํ•œ ์‚ฌ๋žŒ ์ฃ„์†กํ•ฉ๋‹ˆ๋‹ค m(_ _)m

    ์ข‹์€ ์›นํŽ˜์ด์ง€ ์ฆ๊ฒจ์ฐพ๊ธฐ