$ chmod 600 ~/.ssh/test_app_key.pem
$ ssh ec2-user@53.11.132.42 -i ~/.ssh/test_app_key.pem
The authenticity of host '53.11.132.42 (53.11.132.42)' can't be established.
RSA key fingerprint is ca:32:e4:cb:3b:dc:51:27:27:9b:c4:d8:39:f0:24:6a.
Are you sure you want to continue connecting (yes/no)? yes
__| __|_ )
_| ( / Amazon Linux AMI
___|\___|___|
https://aws.amazon.com/amazon-linux-ami/2015.09-release-notes/
[ec2-user@ip-172-32-26-98 ~]$
看到上面的畫面表示你已經成功的連線至EC2。
$ sudo yum install mysql
$ mysql -P 5678 -h test-app.jfkwohjdwioj8.us-west-2.rds.amazonaws.com -u mysqluser -p
Enter password:
Welcome to the MySQL monitor. Commands end with ; or \g.
Your MySQL connection id is 20
Server version: 5.6.23-log MySQL Community Server (GPL)
Copyright (c) 2000, 2015, Oracle and/or its affiliates. All rights reserved.
Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.
Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
mysql>
理論上mysql的管理帳號不應該拿來做為平常連線之用,所以我們會開另一個帳號並設定比較低的權限。這時候我們要決定幾個東西:連線帳號(例如:test_app_user)、帳號密碼(例如:test_app_pw)與資料庫的名稱(例如:test_app_db)。另外我們也可以順便建立網站所需要的資料庫,雖然也可以用rails的rake db:create來建,不過還要下載repo實在有點麻煩,所以這邊就直接下指令來建db嘍。
CREATE USER 'test_app_user'@'%' IDENTIFIED BY 'test_app_pw';
GRANT ALL PRIVILEGES ON 'test_app_db' . * TO 'test_app_user'@'%';
FLUSH PRIVILEGES;
CREATE DATABASE IF NOT EXISTS test_app_db DEFAULT CHARACTER SET = 'utf8' DEFAULT COLLATE 'utf8_general_ci';
$ mysql -P 5678 -h test-app.jfkwohjdwioj8.us-west-2.rds.amazonaws.com -u test_app_user -p
$ sudo yum update
Loaded plugins: priorities, update-motd, upgrade-helper
No packages marked for update
appuser會具有sudo權限操作server,用來取代root與ec2-user。
$ sudo adduser appuser
$ sudo passwd appuser
$ sudo visudo
# ...
root ALL=(ALL) ALL
appuser ALL=(ALL) ALL
# ...
只要將本地端的 public key 加到 appuser 的 .ssh/authorized_keys 即可。
$ sudo su - appuser
$ chmod 700 .ssh
$ chmod 600 .ssh/authorized_keys
$ ssh appuser@53.11.132.42 -i ~/.ssh/id_rsa
Port 1234
PermitRootLogin no
PasswordAuthentication no
X11Forwarding no
AllowUsers appuser
說明一下:
Port 1234:更改ssh連線時的port為1234。
PermitRootLogin no:表示不允許使用root進行登入。
PasswordAuthentication no:表示不能使用帳號密碼的方式登入。
X11Forwarding no:不使用X11 Forwarding,因為我們不會用到圖形界面。
AllowUsers appuser:只允許 appuser 可以ssh連線。
$ sudo /etc/init.d/sshd reload
$ ssh appuser@53.11.132.42 -i ~/.ssh/id_rsa -p 1234
deployuser是專門用來做deploy用的,與appuser最大的不同是,appuser具有sudo權限,而deployuser則沒有。所以任何安裝的流程,應該是由appuser來做,而deploy是由deployuser來做。
sudo adduser deployuser
sudo mkdir /home/deployuser/.ssh
sudo chown -R deployuser /home/deployuser/.ssh
sudo chgrp -R deployuser /home/deployuser/.ssh
sudo chmod -R 700 /home/deployuser/.ssh
sudo cp .ssh/authorized_keys /home/deployuser/.ssh/authorized_keys
sudo chown deployuser /home/deployuser/.ssh/authorized_keys
sudo chgrp deployuser /home/deployuser/.ssh/authorized_keys
sudo usermod -a -G deployuser appuser
AllowUsers appuser deployuser
$ sudo /etc/init.d/sshd reload
$ ssh deployuser@53.11.132.42 -i ~/.ssh/id_rsa -p 1234
rvm的功能是用來切換ruby的版本,在日後要升級ruby時會省事很多。另外我們會使用multi-user的模式來安裝,也就是rvm是安裝在系統之下,所有的使用者用的都是同一套rvm。要注意的是,執行一般的rvm指令時不需要sudo權限,但如果要安裝ruby,就必須要有sudo權限。
$ \curl -sSL https://get.rvm.io | sudo bash -s stable
[sudo] password for appuser:
Downloading https://github.com/rvm/rvm/archive/1.26.11.tar.gz
Downloading https://github.com/rvm/rvm/releases/download/1.26.11/1.26.11.tar.gz.asc
gpg: directory `/root/.gnupg' created
gpg: new configuration file `/root/.gnupg/gpg.conf' created
gpg: WARNING: options in `/root/.gnupg/gpg.conf' are not yet active during this run
gpg: keyring `/root/.gnupg/pubring.gpg' created
gpg: Signature made Mon 30 Mar 2015 09:52:13 PM UTC using RSA key ID BF04FF17
gpg: Can't check signature: No public key
Warning, RVM 1.26.0 introduces signed releases and automated check of signatures when GPG software found.
Assuming you trust Michal Papis import the mpapis public key (downloading the signatures).
GPG signature verification failed for '/usr/local/rvm/archives/rvm-1.26.11.tgz' - 'https://github.com/rvm/rvm/releases/download/1.26.11/1.26.11.tar.gz.asc'!
try downloading the signatures:
sudo gpg2 --keyserver hkp://keys.gnupg.net --recv-keys 409B6B1796C275462A1703113804BB82D39DC0E3
or if it fails:
command curl -sSL https://rvm.io/mpapis.asc | sudo gpg2 --import -
the key can be compared with:
https://rvm.io/mpapis.asc
https://keybase.io/mpapis
$ sudo gpg2 --keyserver hkp://keys.gnupg.net --recv-keys 409B6B1796C275462A1703113804BB82D39DC0E3
gpg: keyring `/root/.gnupg/secring.gpg' created
gpg: requesting key D39DC0E3 from hkp server keys.gnupg.net
gpg: /root/.gnupg/trustdb.gpg: trustdb created
gpg: key D39DC0E3: public key "Michal Papis (RVM signing) <mpapis@gmail.com>" imported
gpg: no ultimately trusted keys found
gpg: Total number processed: 1
gpg: imported: 1 (RSA: 1)
$ \curl -sSL https://get.rvm.io | sudo bash -s stable
Downloading https://github.com/rvm/rvm/archive/1.26.11.tar.gz
Downloading https://github.com/rvm/rvm/releases/download/1.26.11/1.26.11.tar.gz.asc
gpg: Signature made Mon 30 Mar 2015 09:52:13 PM UTC using RSA key ID BF04FF17
gpg: Good signature from "Michal Papis (RVM signing) <mpapis@gmail.com>" [unknown]
gpg: WARNING: This key is not certified with a trusted signature!
gpg: There is no indication that the signature belongs to the owner.
Primary key fingerprint: 409B 6B17 96C2 7546 2A17 0311 3804 BB82 D39D C0E3
Subkey fingerprint: 62C9 E5F4 DA30 0D94 AC36 166B E206 C29F BF04 FF17
GPG verified '/usr/local/rvm/archives/rvm-1.26.11.tgz'
Creating group 'rvm'
Installing RVM to /usr/local/rvm/
Installation of RVM in /usr/local/rvm/ is almost complete:
* First you need to add all users that will be using rvm to 'rvm' group,
and logout - login again, anyone using rvm will be operating with `umask u=rwx,g=rwx,o=rx`.
* To start using RVM you need to run `source /etc/profile.d/rvm.sh`
in all your open shell windows, in rare cases you need to reopen all shell windows.
# appuser,
#
# Thank you for using RVM!
# We sincerely hope that RVM helps to make your life easier and more enjoyable!!!
#
# ~Wayne, Michal & team.
In case of problems: http://rvm.io/help and https://twitter.com/rvm_io
sudo usermod -a -G rvm appuser
$ rvm -v
rvm 1.26.11 (latest) by Wayne E. Seguin <wayneeseguin@gmail.com>, Michal Papis <mpapis@gmail.com> [https://rvm.io/]
$ rvmsudo rvm get stable
Downloading https://get.rvm.io
Downloading https://raw.githubusercontent.com/wayneeseguin/rvm/master/binscripts/rvm-installer.asc
Verifying /usr/local/rvm/archives/rvm-installer.asc
gpg: Signature made Tue 14 Apr 2015 12:05:41 AM UTC using RSA key ID BF04FF17
gpg: Good signature from "Michal Papis (RVM signing) <mpapis@gmail.com>" [unknown]
gpg: WARNING: This key is not certified with a trusted signature!
gpg: There is no indication that the signature belongs to the owner.
Primary key fingerprint: 409B 6B17 96C2 7546 2A17 0311 3804 BB82 D39D C0E3
Subkey fingerprint: 62C9 E5F4 DA30 0D94 AC36 166B E206 C29F BF04 FF17
GPG verified '/usr/local/rvm/archives/rvm-installer'
Downloading https://github.com/rvm/rvm/archive/1.26.11.tar.gz
Downloading https://github.com/rvm/rvm/releases/download/1.26.11/1.26.11.tar.gz.asc
gpg: Signature made Mon 30 Mar 2015 09:52:13 PM UTC using RSA key ID BF04FF17
gpg: Good signature from "Michal Papis (RVM signing) <mpapis@gmail.com>" [unknown]
gpg: WARNING: This key is not certified with a trusted signature!
gpg: There is no indication that the signature belongs to the owner.
Primary key fingerprint: 409B 6B17 96C2 7546 2A17 0311 3804 BB82 D39D C0E3
Subkey fingerprint: 62C9 E5F4 DA30 0D94 AC36 166B E206 C29F BF04 FF17
GPG verified '/usr/local/rvm/archives/rvm-1.26.11.tgz'
Upgrading the RVM installation in /usr/local/rvm/
Upgrade of RVM in /usr/local/rvm/ is complete.
# appuser,
#
# Thank you for using RVM!
# We sincerely hope that RVM helps to make your life easier and more enjoyable!!!
#
# ~Wayne, Michal & team.
In case of problems: http://rvm.io/help and https://twitter.com/rvm_io
Upgrade Notes:
* No new notes to display.
RVM reloaded!
$ rvmsudo rvm install 2.2.3
Searching for binary rubies, this might take some time.
No binary rubies available for: amazon/2015.09/x86_64/ruby-2.2.3.
Continuing with compilation. Please read 'rvm help mount' to get more information on binary rubies.
Checking requirements for amazon.
Installing requirements for amazon.
Installing required packages: patch, libyaml-devel, glibc-headers, autoconf, gcc-c++, glibc-devel, patch, readline-devel, zlib-devel, libffi-devel, openssl-devel, automake, libtool, bison, sqlite-devel........................
Requirements installation successful.
Installing Ruby from source to: /usr/local/rvm/rubies/ruby-2.2.3, this may take a while depending on your cpu(s)...
ruby-2.2.3 - #downloading ruby-2.2.3, this may take a while depending on your connection...
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
100 12.7M 100 12.7M 0 0 8096k 0 0:00:01 0:00:01 --:--:-- 8092k
No checksum for downloaded archive, recording checksum in user configuration.
ruby-2.2.3 - #extracting ruby-2.2.3 to /usr/local/rvm/src/ruby-2.2.3....
ruby-2.2.3 - #configuring.........................................................
ruby-2.2.3 - #post-configuration..
ruby-2.2.3 - #compiling...............................................................................
ruby-2.2.3 - #installing.............................
ruby-2.2.3 - #making binaries executable..
ruby-2.2.3 - #downloading rubygems-2.4.8
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
100 437k 100 437k 0 0 706k 0 --:--:-- --:--:-- --:--:-- 707k
No checksum for downloaded archive, recording checksum in user configuration.
ruby-2.2.3 - #extracting rubygems-2.4.8....
ruby-2.2.3 - #removing old rubygems.........
ruby-2.2.3 - #installing rubygems-2.4.8......................
ruby-2.2.3 - #gemset created /usr/local/rvm/gems/ruby-2.2.3@global
ruby-2.2.3 - #importing gemset /usr/local/rvm/gemsets/global.gems...............................................
ruby-2.2.3 - #generating global wrappers........
ruby-2.2.3 - #gemset created /usr/local/rvm/gems/ruby-2.2.3
ruby-2.2.3 - #importing gemsetfile /usr/local/rvm/gemsets/default.gems evaluated to empty gem list
ruby-2.2.3 - #generating default wrappers........
ruby-2.2.3 - #adjusting #shebangs for (gem irb erb ri rdoc testrb rake).
Install of ruby-2.2.3 - #complete
Ruby was built without documentation, to build it run: rvm docs generate-ri
$ rvm ls
rvm rubies
ruby-2.2.3 [ x86_64 ]
# Default ruby not set. Try 'rvm alias create default <ruby>'.
# => - current
# =* - current && default
# * - default
$ rvm use 2.2.3 --default
Using /usr/local/rvm/gems/ruby-2.2.3
$ gem install bundler --no-ri --no-rdoc
Fetching: bundler-1.10.6.gem (100%)
Successfully installed bundler-1.10.6
1 gem installed
$ sudo mkdir -p /opt/www/test-app
$ sudo chown -R deployuser /opt/www/test-app
$ sudo chgrp -R deployuser /opt/www/test-app
$ sudo chmod -R 775 /opt/www/test-app
sudo yum install nginx
$ sudo mkdir /etc/nginx/sites-available
$ sudo mkdir /etc/nginx/sites-enabled
上面的動作會在/etc/nginx建兩個目錄,這麼做的目的是我們想將不同的網站設定檔分開,將網站相關的設定檔放在sites-available之下,如果要上線,就建一個link到sites-enabled。
/etc/nginx/nginx.conf
http {
# ...
include /etc/nginx/sites-enabled/*;
# ...
}
/etc/nginx/sites-available/test_app
upstream unicorn_test_app {
server unix:/tmp/unicorn.test_app.sock fail_timeout=0;
}
server {
listen 80 default deferred;
server_name test-app.com;
root /opt/www/test-app/current/public;
location ~ ^/assets/ {
gzip_static on;
expires max;
add_header Cache-Control public;
}
try_files $uri/index.html $uri @unicorn;
location @unicorn {
proxy_set_header Host $http_host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_redirect off;
proxy_pass http://unicorn_test_app;
}
error_page 500 502 503 504 /500.html;
client_max_body_size 4G;
keepalive_timeout 10;
}
$ sudo ln -s /etc/nginx/sites-available/test_app /etc/nginx/sites-enabled/test_app
$ sudo service nginx start
真見鬼了,yum的nodejs版本也太舊了吧(0.10.36,現在5.0.0都要出了耶),只好硬的頭皮自己裝了。還好有這篇可以參考:How to install & setup Node.js on Amazon EC2 – complete guide
$ sudo yum install gcc-c++ make openssl-devel
mkdir temp
cd temp
wget https://nodejs.org/dist/v4.2.2/node-v4.2.2.tar.gz
tar -xf node-v4.2.2.tar.gz
cd node-v4.2.2
./configure
make
sudo make install
$ node -v
v4.2.2
$ npm -v
2.14.7
這裡就跟據你的需求安裝需要的package,如果少安裝了,在deploy做bundle install的時候就會出錯,到時候再回來安裝也可以。這邊只記錄我自已有用到的package
secrets.yml與database.yml是rails中最重要的兩個設定檔,理論上這兩個檔案都不應該commit到repo中。在做production deploy的時候會從/opt/www/test-app/shared/config的目錄中複製(精確來說是建立link)到實際運作的app目錄中,所以在deploy之前,我們要先在server上對應的目錄下手動建立這兩個檔案。
production:
adapter: mysql2
encoding: utf8
pool: 5
host: test-app.jfkwohjdwioj8.us-west-2.rds.amazonaws.com
port: 5678
database: test_app_db
username: test_app_user
password: test_app_pw
因為我們是用nginx + unicorn,所以unicorn是一定要裝的。另外我們是用capistrano來做deploy,所以一些相關的gem也要加進來,不過會放在development的group中。
# ...
gem 'unicorn'
# ...
group :development do
# ...
gem 'capistrano-rails'
gem 'capistrano-rvm'
gem 'capistrano-npm'
gem 'capistrano3-unicorn'
# ...
end
capistrano是專門做deploy的工具,基本上它的設定檔決定了整個deploy的流程。下面是一個範例:
config/deploy.rb
# config valid only for current version of Capistrano
lock '3.4.0'
set :application, 'app'
set :repo_url, '[your repo]'
set :user, 'deployuser'
set :rails_env, 'production'
set :assets_roles, [:app]
set :npm_roles, [:app]
set :unicorn_roles, [:app]
set :ssh_options, { forward_agent: true, port: 1234 }
set :deploy_to, '/opt/www/test-app'
set :linked_files, fetch(:linked_files, []).push('config/database.yml', 'config/secrets.yml')
set :linked_dirs, fetch(:linked_dirs, []).push('log', 'tmp/pids', 'tmp/cache', 'tmp/sockets', 'vendor/bundle', 'public/system')
set :npm_flags, '--silent --no-spin'
namespace :deploy do
after :restart, :clear_cache do
on roles(:app), in: :groups, limit: 3, wait: 10 do
# Here we can do anything such as:
# within release_path do
# execute :rake, 'cache:clear'
# end
end
end
task :restart_unicorn do
invoke 'unicorn:reload'
end
after :publishing, :restart_unicorn
end
config/deploy/production.rb
role :app, %w{53.11.132.42}
role :web, %w{53.11.132.42}
role :db, %w{53.11.132.42}
unicorn是連接web server與rails app的rack http server。有了capistrano3-unicorn,我們可以在config/unicorn/[environment].rb中加上unicorn的設定。
config/unicorn/production.rb
root = "/opt/www/test-app/current"
working_directory rootpid "#{root}/tmp/pids/unicorn.pid"
stderr_path "#{root}/log/unicorn.log"
stdout_path "#{root}/log/unicorn.log"
listen "/tmp/unicorn.test_app.sock"
worker_processes 1
timeout 30