リバースプロキシを使って1つのグローバルIPアドレスで複数のウェブサーバーへ振り分ける【UbuntuでNginxのリバースプロキシを設定する】
自宅で複数のウェブサーバーなどを運用するようになり、ウェブサーバーごとにドメインを設定したくなりました。
今まで公開したいウェブサーバーが1台だったので、ルーターのポートフォワードで運用していました。 ルーターのポートフォワード設定だと、WAN側のポートとLAN側のサーバーのIPアドレス・ポートを紐付けています。 そのため、ウェブサーバーで絶対的に使われる80番ポートが割当可能なサーバーは1台のみで、2台目以降はポートを変える必要があり、運用の観点で現実的ではありません。
そこで、アクセスされるホスト名でウェブサーバーへの振り分けを行う方法を探していたらリバースプロキシが最もメジャーな方法でした。
今回は、リバースプロキシの概要と、Ubuntu環境へのインストール・設定方法について説明します。
リバースプロキシとは
一般的に、クライアントがウェブサーバーへアクセスすると、ルータがウェブサーバへリクエストを直接振り分けてウェブサーバーがクライアントへ直接応答を返していました。。
リバースプロキシは、クライアントとウェブサーバの間に立って要求を代理で処理します。
この時、ウェブサーバはクライアントではなくリバースプロキシに応答を返し、リバースプロキシがクライアントに応答を返します。
間にリバースプロキシが挟まることによるメリットを以下に記載します。
リバースプロキシのメリット
簡単に言うと、アクセス速度が向上します。
リバースプロキシの代表格NginxやApache、Squidなどには、キャッシュが用いられています。 1度目のアクセスで、リバースプロキシサーバーからウェブサーバーへリクエストを発行し、結果をリバースプロキシサーバーにキャッシュします。 2度目以降のリクエストは、リバースプロキシサーバーのキャッシュを返すため、応答速度が向上します。
次章から、Nginxのインストールから、リバースプロキシの設定方法について説明します。
Nginxによるリバースプロキシ設定
環境
- OS: Ubuntu 16.04 Server Edition
- サーバー構成
- リバースプロキシサーバー(rproxy/192.168.1.10)
- ウェブサーバーA(serverA/192.168.1.100/a.com)
- ウェブサーバーB(serverB/192.168.1.200/b.com)
インストール手順
リバースプロキシサーバーにNginxをインストールします。
$ sudo apt-get install nginx
インストールされたnginxのバージョンを確認します。
$ nginx -v
nginx version: nginx/1.10.0 (Ubuntu)
リバースプロキシの設定
リバースプロキシサーバーにおいて、Nginxの設定ファイルを編集します。
ウェブサーバーAに振り分ける設定
リバースプロキシを設定します。
$ sudo vi /etc/nginx/sites-available/web_serverA
server {
server_name serverA.example.com; #クライアントがアクセスするURL
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $http_host;
location / {
proxy_pass http://192.168.1.100; #ウェブサーバーAのIPアドレス(/etc/hostsに記載しているホスト名も可)
}
}
設定ファイルを有効化します。
$ sudo ln -s /etc/nginx/sites-available/web_serverA /etc/nginx/sites-enabled/
ウェブサーバーBに振り分ける設定
リバースプロキシを設定します。
$ sudo vi /etc/nginx/sites-available/web_serverB
server {
server_name serverB.example.com; #クライアントがアクセスするURL
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $http_host;
location / {
proxy_pass http://192.168.1.200; #ウェブサーバーBのIPアドレス(/etc/hostsに記載しているホスト名も可)
}
}
$ sudo ln -s /etc/nginx/sites-available/web_serverB /etc/nginx/sites-enabled/
設定の反映
以下のコマンドで設定を反映します。
$ sudo systemctl reload nginx
エラーがでた場合は、設定ファイルを見直して、再度上記コマンドを実行してください。
アクセス確認
server_nameに設定したアドレスにアクセスして、それぞれのウェブサーバーのページが表示されていれば、正しく設定されています。
まとめ
Nginxによるリバースプロキシ設定手順について説明しました。 リバースプロキシを使えば、1つのグローバルIPアドレスで、複数サーバーへの振り分けが実現可能です。
Ubuntu16.04でCANONのプリンターMG8130を使うためのドライバーセットアップ
今回は、Ubuntu16.04 Desktop版で、CanonのプリンターMG8130を使うための環境セットアップについて説明します。
背景
Ubuntu16.04でcanonの公式ページからドライバーをインストールすると、以下のようなエラーがでる。
.../cnijfilter-mg8100series_3.40-1_amd64.deb を展開する準備をしています ...
cnijfilter-mg8100series (3.40-1) を展開しています...
dpkg: 依存関係の問題により cnijfilter-mg8100series の設定ができません:
cnijfilter-mg8100series は以下に依存 (depends) します: libtiff4 ...しかし:
パッケージ libtiff4 はまだインストールされていません。
dpkg: パッケージ cnijfilter-mg8100series の処理中にエラーが発生しました (--install):
依存関係の問題 - 設定を見送ります
処理中にエラーが発生しました:
目標
Ubuntu16.04 Desktop版から、CanonのプリンターMG8130へ印刷できること
手順
ソフトウェアのダウンロード
キヤノン:ダウンロード|ソフトウエアダウンロードにアクセスし、画面の案内に従って、目的の複合機を選択します。
OSの一覧が表示されたら、Linuxを選択します。
プリンタドライバとスキャナドライバの圧縮ファイルをダウンロードします(debianを選んでダウンロードしてください)。
Ubuntu – precise の libtiff4 パッケージに関する詳細にアクセスし、自分のPCのアーキテクチャに合ったlibtiff4のパッケージをダウンロードします。アーキテクチャはuname -aで調べます。以下に私の環境の例を記載します。
$ uname -a Linux versapro 4.4.0-59-generic #80-Ubuntu SMP Fri Jan 6 17:47:47 UTC 2017 x86_64 x86_64 x86_64 GNU/Linux # 64bitなので、アーキテクチャがamd64のパッケージを選択しました。
ダウンロードしたパッケージをインストールします。
$ sudo dpkg -i libtiff4_3.9.5-2ubuntu1.9_amd64.deb
1でダウンロードしたプリンタードライバーをインストールします。
$ tar vxf cnijfilter-mg8100series-3.40-1-deb $ cd cnijfilter-mg8100series-3.40-1-deb/ $ sudo ./install.sh
以下の画面が表示されるので、プリンターをネットワークに接続してEnterを押してください。
#=========================================================# # プリンターの登録 #=========================================================# 続いて、プリンターの登録を行います。 プリンターを接続して、電源を入れてください。 ネットワーク接続で使用する場合は、プリンターをネットワークに接続してください。 準備が整ったら、Enterキーを押してください。 >
接続タイプを選択します。私はネットワークなので、2を押してEnter
#=========================================================# # 接続方法の選択 #=========================================================# 1) USB 2) ネットワーク 接続方法を選択してください。[1]2 プリンターを検索しています..
表示された自分のプリンターの番号を押してEnter。
#=========================================================# # プリンターの選択 #=========================================================# プリンターを選択してください。 使用したいプリンターが表示されていない場合は、再検索[0]を選択してもう一度プリンターを検索してください。 キャンセルする場合は、[Q]を入力してください。 ----------------------------------------------------------- 0) 再検索 ----------------------------------------------------------- 検出された対象プリンター (MACアドレス IPアドレス) 1) Canon MG8100 series (00-00-00-00-00-00 192.168.1.111) ----------------------------------------------------------- 現在の選択値:[1] Canon MG8100 series (00-00-00-00-00-00 192.168.1.111) 番号を入力してください。 [1]1
あとは、表示に従って設定します。
最終的に以下のメッセージが表示されれば、ドライバーのインストール完了です。
#=========================================================#
インストールが完了しました。
プリンター名 : MG8100LAN
印刷時には、このプリンター名を選択してください。
#=========================================================#
確認
確認と言っても適当なメモやWebページを印刷するだけです。
印刷する際に使用するプリンターは、ドライバーインストールの最後に表示されたプリンター名を選択します。
例ではMG8100LANとなっています。
まとめ
Windowsと違い面倒です。
ただ、プリンターは多々使うことが多いので、きちんと設定しておいたほうがよいですね。。
Ubuntu 16.04 ServerにRuby On Railsをインストール
Ubuntu 16.04にrbenvを使ってRuby On Railsを導入
環境
OS: ubuntu 16.04 64bit
$ cat /etc/lsb-release
DISTRIB_ID=Ubuntu
DISTRIB_RELEASE=16.04
DISTRIB_CODENAME=xenial
DISTRIB_DESCRIPTION="Ubuntu 16.04.1 LTS"
ruby: 2.3.1
rails: 2.4.6
手順
パッケージインストール
必要なパッケージをインストール
$ sudo apt-get install git -y
$ sudo apt-get install git-core curl zlib1g-dev build-essential libssl-dev libreadline-dev libyaml-dev libsqlite3-dev sqlite3 libpq-dev libxml2-dev libxslt1-dev libcurl4-openssl-dev python-software-properties libffi-dev
Rubyのインストール
Rubyのバージョン管理ソフト「rbenv」をインストール
$ cd
$ git clone https://github.com/rbenv/rbenv.git ~/.rbenv
初期化コマンドを記述しておく
$ echo 'export PATH="$HOME/.rbenv/bin:$PATH"' >> ~/.bashrc
$ echo 'eval "$(rbenv init -)"' >> ~/.bashrc
$ exec $SHELL
ruby-buildのインストール
$ git clone https://github.com/rbenv/ruby-build.git ~/.rbenv/plugins/ruby-build
$ echo 'export PATH="$HOME/.rbenv/plugins/ruby-build/bin:$PATH"' >> ~/.bashrc
$ exec $SHELL
rbenvでインストール可能なリストを表示
$ rbenv install -l
.
.
2.1.1
2.1.2
2.1.3
2.1.4
2.1.5
2.2.0-dev
.
.
rbenvで特定バージョンのrubyをインストール
$ rbenv install 2.3.1
アンインストールしたい時は以下のコマンド
$ rbenv uninstall 2.3.1
システムで使用しているrubyのバージョンを確認
$ rbenv global
system
現在はシステム標準のrubyが割り当てられているので変更する
$ rbenv global 2.3.1
$ rbenv global
2.3.1
$ rbenv rehash
gemをインストールした後のrbenv rehashを自動化する
このままではgemをインストールまたはアンインストールするたびにrbenv rehashする必要がある
これを自動化してくれるrbenv-rehashというgemがあるのでインストール
https://github.com/ryansouza/rbenv-rehash
$ gem i rbenv-rehash
Ruby On Railsのインストール
依存関係の解決のためNode.jsをインストール
$ curl -sL https://deb.nodesource.com/setup_4.x | sudo -E bash -
$ sudo apt-get install -y nodejs
gemが自動で作成するri rdocドキュメントを無効化する
$ echo 'install: --no-rdoc --no-ri' >> ~/.gemrc
$ echo 'update: --no-rdoc --no-ri' >> ~/.gemrc
railsのインストール(version 4.2.6)
$ gem install rails -v 4.2.6
$ vi .ruby-version
2.3.1
PostgreSQLのインストール
公式リポジトリを追加し、最新のバージョンをインストール
$ sudo sh -c "echo 'deb http://apt.postgresql.org/pub/repos/apt/ xenial-pgdg main' > /etc/apt/sources.list.d/pgdg.list"
$ wget --quiet -O - http://apt.postgresql.org/pub/repos/apt/ACCC4CF8.asc | sudo apt-key add -
$ sudo apt-get update
$ sudo apt-get install postgresql-common
$ sudo apt-get install postgresql-9.5 libpq-dev
DBにユーザーを作成
$ sudo -u postgres createuser hoge -s
# ユーザーにパスワードを設定する場合は以下
$ sudo -u postgres psql
$ postgres=# \password hoge
Railsプロジェクトの作成
SQLiteを使う場合 (性能的に非推奨)
$ rails new myapp
PostgreSQLを使う場合
# Note that this will expect a postgres user with the same username
# as your app, you may need to edit config/database.yml to match the
# user you created earlier
$ rails new myapp -d postgresql
# Move into the application directory
$ cd myapp
# If you setup MySQL or Postgres with a username/password, modify the
# config/database.yml file to contain the username/password that you specified
# Create the database
$ rake db:create
# rails s -b 0.0.0.0
アクセスを確認
以下のURLにアクセスできれば構築完了
http://<railsサーバーのIPアドレス>:3000
アンインストール
rubyもRailsを消したい場合、 gem, apt-getで入れたものを削除することに加え以下を実行
$ gem uninstall railties '4.2.6'
$ rm -rf /usr/local/lib/ruby
$ rm -rf /usr/lib/ruby
$ rm -f /usr/local/bin/ruby
$ rm -f /usr/bin/ruby
$ rm -f /usr/local/bin/irb
$ rm -f /usr/bin/irb
$ rm -f /usr/local/bin/gem
$ rm -f /usr/bin/gem
豆知識
rbenvで特定のプロジェクトで使用するrubyのバージョンを指定する
$ mkdir rbenv-test
$ cd rbenv-test
$ vi .ruby-version
2.3.1を追記
これで、rbenv-testディレクトリの中ではバージョン2.3.1が使用されるようになる
rbenvのアップグレード
$ cd ~/.rbenv
$ git pull
参考
Ruby on Railsでleaflet-routing-machineを使う
Railsでleafleのプラグインleaflet-routing-machineを動かす。
まずはデモ
http://workshops.ddns.net/routes/new
環境
Rails: 4.1.8
ruby: 2.1.5p273 (2014-11-13 revision 48405) [x86_64-linux]
leaflet: v0.7.7
ソース
まずはrails
maps/show.html.erb
<%= stylesheet_link_tag 'leaflet/leaflet' %> <%= stylesheet_link_tag 'leaflet-routing-machine/leaflet-routing-machine' %> <div id="map" class="map"> </div> <%= javascript_include_tag 'leaflet/leaflet' %> <%= javascript_include_tag 'leaflet-routing-machine/leaflet-routing-machine' %> <%= javascript_include_tag 'leaflet-routing-machine/Control.Geocoder' %>
読み込んでいるcssとjsはleafletとleaflet-routing-plugin 以下からダウンロードできる。
leaflet http://leafletjs.com/
leaflet-routing-machine http://www.liedman.net/leaflet-routing-machine/
次にCSS 地図とルーティングの表示領域を定義
.map { height: 500px; width:100%; } .results { background-color: white; opacity: 0.8; position: absolute; top: 12px; right: 12px; width: 320px; height: 480px; overflow-y: scroll; }
最後にjavascript
leaflet-routing-pluginで表示されるピン画像がデフォルトではうまく表示されないため 設定を変更する必要がある。
以下の例では、public/images/leaflet以下にピン画像がある場合を記載している。
var map = L.map('map'); L.Icon.Default.imagePath = (function () { var scripts = document.getElementsByTagName('script'), leafletRe = /[\/^]leaflet[\-\._]?([\w\-\._]*)\.js\??/; var i, len, src, matches, path; for (i = 0, len = scripts.length; i < len; i++) { src = scripts[i].src; matches = src.match(leafletRe); if (matches) { path = src.split(leafletRe)[0]; return '/' + 'images/leaflet'; /* ピン画像へのパス */ } } }()); //ここからはチュートリアル通り L.tileLayer('http://{s}.tile.osm.org/{z}/{x}/{y}.png', { attribution: '© <a href="http://osm.org/copyright">OpenStreetMap</a> contributors' }).addTo(map); var control = L.Routing.control({ createMarker: function(i, wp) { var options = { draggable: this.draggableWaypoints }, marker = L.marker(wp.latLng, options); return marker; }, waypoints: [ L.latLng(35.46222222, 139.62444444), L.latLng(35.681298, 139.766247) ], geocoder: L.Control.Geocoder.nominatim(), routeWhileDragging: true, reverseWaypoints: true, showAlternatives: true, altLineOptions: { styles: [ {color: 'black', opacity: 0.15, weight: 9}, {color: 'white', opacity: 0.8, weight: 6}, {color: 'blue', opacity: 0.5, weight: 2} ] } }).addTo(map); L.Routing.errorControl(control).addTo(map);
以上
【Ruby on Rails4】dropzone.jsを使ってファイルアップロード・削除機能を実装
はじめに
rails環境でdropzone.jsを導入してファイルアップロード機能を実装する
概要
まずはデモ画像
実際の動作は以下から
http://workshops.ddns.net/albums/upload_photos/4160
dropzoneの説明は本家ページを参照
構成
Album has many Pictureの関係
事前準備
Gemfileに以下を追加してbundle install
gem 'dropzonejs-rails'
手順
アップロードフォームを作る
app/views/albums/upload_photos.html.erb
<h1>画像アップロード</h1> <%= render partial: 'upload_photos_form', locals: { album_id: @album_id } %> <br> <%= link_to 'アルバムへ戻る', {:controller => 'albums',:action => 'show_pictures'}, {:class => 'btn btn-default btn-sm'} %> <%= link_to 'トップページに戻る', {:controller => 'top_pages',:action => 'home'}, {:class => 'btn btn-default btn-sm'} %>
アップロードフォームを部分テンプレートとして作成。
app/views/albums/_upload_photos_form.html.erb
<%= stylesheet_link_tag 'dropzone/basic' %> <%= stylesheet_link_tag 'dropzone/dropzone' %> <style> .dropzone { border: 2px dashed #b4bcc2; @include border-radius(4px); .dz-message { font-size: 16px; text-align: center; margin: 0 } } </style> <%= form_tag(@albums, class: 'dropzone', id: 'upload-dropzone', remote: true, authenticity_token: true) do %> <div class="fallback"> <%= file_field_tag('picture[image]') %> </div> <% end %> <%= javascript_include_tag 'dropzone' %>
dropzoneの動作を定義するjsを編集する。
app/assets/javascripts/dropzone.js
Dropzone.autoDiscover = false; var headlineDropzone = new Dropzone("#upload-dropzone", { url: "/api/v1/albums/upload_photo", // You can override url of form in here. params: { album_id: <%= album_id %>, }, maxFilesize: 5, // in MB addRemoveLinks: true, parallelUploads: 2, acceptedFiles:'.jpg, .png, .jpeg, .gif', // type of files init: function(){ this.on('addedfile', function(file) { // Called when a file is added to the list. }); this.on('sending', function(file, xhr, formData) { // Called just before each file is sent. }); //json is picture object whitch server return this.on('success', function(file, json) { // Called when file uploaded successfully. console.log(json); $(file.previewTemplate).find('.dz-remove').attr('id', json.id); }); }, removedfile: function(file){ // grap the id of the uploaded file we set earlier var id = $(file.previewTemplate).find('.dz-remove').attr('id'); var delete_file = file // make a DELETE ajax request to delete the file $.ajax({ type: 'DELETE', url: '/api/v1/pictures/' + id, success: function(res){ $(delete_file.previewTemplate).fadeOut(); } }); } });
apiのルートを設定
namespace :api, { format: 'json' } do namespace :v1 do post "albums/upload_photo" resources :pictures end end
画像を保存する処理を実装
app/controllers/api/v1/albums_controller.rb
def upload_photo @picture = Picture.create( #パラメーターを設定 ) picture.save! render status: 200, json: @picture, nothing: true end
画像を削除する処理を実装
app/controllers/api/v1/pictures_controller.rb
def destroy @picture = Picture.find(params[:id]) @picture.destroy respond_to do |format| format.html format.json { render :json => true } end end
これで完成
【Jquery】【Ruby on Rails】select2でAjaxを使う
select2の説明は至るところにあるので省きます。
最初に作成したもののデモ
手順
まずは、APIを返す側のコントローラーのルートを設定。 私はこんな感じ
# vi config/routes.rb
get "api/v1/addresses/select2"
コントローラーの設定
# vi app/controllers/api/v1/addresses_controller.rb def select2 if params[:term] @addresses = Address.where('full_text LIKE ?', '%' + params[:term].to_s + '%') @address = @addresses.page(params[:page]).per(params[:page_limit]) end puts @address.count respond_to do |format| format.json { render :json => { :addresses => @address, :total => @addresses.count, :links => { :self => @address.current_page , :next => @address.next_page} } } end end
APIの返却値は以下のような住所を返すよう設計
{
"addresses":[
{"id": 10589, "state": "千葉県", "city": "松戸市", "street_number": "",…},
{"id": 11030, "state": "千葉県", "city": "いすみ市", "street_number": "",…},
{"id": 11253, "state": "千葉県", "city": "印西市", "street_number": "",…},
(略)
],
"total": 2219,
"links":{
"self": 1,
"next": 2
}
}
次にJavaScript側
$("#address-search").select2({ ajax: { url: "http://workshops.ddns.net/api/v1/addresses/select2", dataType: 'json', delay: 250, data: function (params, page) { return { term: params, // ?term=params page_limit: 10, page: page, }; }, results: function (data, page) { var more = (page * 10) < data.total; return {results: data.addresses, more: more}; } }, formatResult: addressFormatResult, formatSelection: addressFormatSelection, minimumInputLength: 1, }); function addressFormatResult(address) { var markup = "<table class='address-result'><tr>"; markup += "<td class='address-info'><div class='address-value'>" + address.state +' '+ address.city + "</div>"; markup += "</td></tr></table>" return markup; } function addressFormatSelection(address) { return (address.state + ' ' + address.city); }
最後にフォーム
<input type="hidden" name="address" id="address-search" placeholder="東京">
以上
Ruby on RailsでSEO対策【meta tag】
facebookでogpなる設定が必要(今更。。)なので、content_forを利用して設定してみる。
たとえば、album#showページで個別に設定したい内容があったとして、以下のように記述できる。
# vi app/views/album/show.html.erb
<% content_for :ogp do %>
<meta property="og:title" content="<%= @album.title %>" />
<meta property="og:type" content="article" />
<meta property="og:url" content="<%= @album.url %>" />
<meta property="og:image" content="<%= @album.image %>" />
<% end %>
あとは共通レイアウトに以下を記述するだけ。
# vi app/views/layouts/application.html.erb
<head>
(略)
<!-- meta tag for each page -->
<%= yield :ogp %>
<%= csrf_meta_tags %>
<%= stylesheet_link_tag "application", :media => "all" %>
(略)
</head>
以上