在同一個domain下執行多個rails


#1

想請教一下,如何在在同一個domain下執行多個rails專案,我知道前面有人問過類似的並用subdomain的方式解,想知道如何用path的方式解

架構是ubuntu + nginx + rails 4.2


#2

不建議,session/cookie 會互相感染和修改的,且就算 secure key 設一樣,code 不同很多地方也都會出事的,類似 marshal 轉不回來之類的

目前我有用 Rails 加 Sinatra,不過 sinatra 當被動端,cookie 唯讀且把 session 關閉,不然兩個系統會互刪 cookie,問題很多就是了


#3

rails 的session 和 cookie不是各專案各自獨立的嗎?

如果在nginx 調設定讓

www.example.com/project_A => project_A 的站

www.example.com/project_B => project_B 的站

這樣也會嗎?


#4

hmm … cookie 主要用 domain 來做設定,除非另外附加 path 的宣告,但很少人會用 path 來做,我不確定 Rails 是否有設定能加 path 的 cookie

如果混在一起的話,你當然可以設定 session cookie 的 name,但如果沒有設定 path,當 A 站被入侵時,則 A 站會取得 B 站的 session,並且感染登入到 B 站去 … 這是架構問題,而非設定問題,簡單的來說你就算用 nginx proxy 來硬做出這樣的方式,你仍會碰到這樣的風險

所以我這邊還是會建議你用 sub domain 來切開各網站會好點,應該是說你這樣主要的目的是啥?或是為何有這樣的需求?可以提出來做額外的討論看是否有額外的解法

如果有多重登入需求,你可以另外建一個 login server 來做 OAuth provider 或是另外打 API 之類的,也就是 cookie 都存在 C 站,而 A / B 用內部 API 的方式來和 C 站做溝通並分享登入資訊即可,你可以去觀察 Yahoo 或 Google 的網址應該就能觀察到這現象才是


#5

因為我的機器分前後台,且前後台架在不同server上,目前的架構上client端要部分後台資料時目前都是直接用後台的url要資料,如:

http://www.project_A.com/datas.xml => 要project_A 的data的index
http://www.project_B.com/products.xml => 要project_B 的product的index

所以除非設hosts或註冊domain,否則client會取不到資料,且一套後台就有多個rails,每裝一套就要設多個domain name

所以想減少註冊domain name或設定host的數量


#6

這是有趣的地方 … 我之前的專案也有和你完全一樣的問題,但是是用不同的解法,所以我會建議你先把需求提出來,而非直接問你腦中想要的作法之類的

首先,不想維護相同的 code 是宗旨,所以如何在 code 相同之下還達成前後端分離?且切成不同的 project,甚至後端可以看到前端的資料,但不用到前端去?

我剛寫了一篇,你先參考

然後就是 Rails 的進入點,首先要讓 Rails 吃 subdomain,而 Rails 的 route 有處理 subdomain 的能力哩,類似

Rails.application.routes.draw do
  constraints subdomain: ['www' , ''] do
    # client 的 route
  end
  constraints subdomain: ['manage' , 'devmanage'] do
    # manager 的 route
  end
end

之後分別 deploy 到兩台機器的同專案內,建立一個設定值,類似 $settings[:is_client_side] & $settings[:is_manager_side](分離的原因是一個專案可以吃雙方,一個只吃單一,不過廣域的那方可以不用增加判斷,這邊給你考慮),並放到 ApplicationController 內(這邊指的是繼承的最上面的那個 controller),增加 before_action 來判斷該專案是否可以進其中一邊,否則 reject 掉 回 404 error

再來完成上面的動作後 … 你的 manager 那邊就可以取到一般使用者的資料了不是?還可以轉登使用者的帳號之類的,並把這些 session / cookie 限制在該 domain & 該主機身上

然後是安全性的問題, manager 那邊可以在 before_action 內增加 IP limit(請務必製作),再來 manage 這個 sub domain 不應該在 DNS 內出現,你可以在 /etc/hosts(mac / linux)或C:\WINDOWS\system32\drivers\etc\hosts(Windows)內設定,類似

127.0.0.1    devmanage.example.com #開發專用
111.1.1.1    manage.micro$oft.com #正式機
  #(此subdomain建議取亂碼或存在但用不到的domain,類似manage.micro$oft.com)
  # 因為判斷是從最前面判斷,而 example.com / micro$oft.com 會忽略掉
  # 此$是玩笑話,不用當真

要進去 admin 的主機請都加上這樣的設定即可, 所以綜合以上

一個專案可以切離 manager & client side,並把 manager 專用的 API key 不放在 client 那邊($settings),建立 IP limit,建立 domain 分流

按照這樣切法,你甚至可以把 sidekiq 甚至奇怪的輔助系統都切出去哩

這邊唯一的缺點是,如果你的 client side 被攻破了,會取到 manage side 的 code,但這點很有趣的地方是,如果對方已經這樣做了,那他也應該能取得 DB 的控制權和修改其他東西的能力 … 這邊比較危險的是後者,而不是前者才是,而前者的機敏資訊都可以丟在 $settings 內來進行切離就是了

然而如果抱怨 code 太多記憶體吃太多,你可以在 routes 或是一些資料夾增加判斷後才增加 autoload 該資料夾 / load 該 code 之類的,不過這邊就不繼續補述了,給你參考

嗯,剛剛也看到你有說的, client 想反向取到 manager 的資料,則把 client 和 manager 上一樣的 route / controller 即可,之後用背景 API 的方式去 call 對方來做彼此的溝通會好點(一樣把對方 IP / port / url / token 記在 $settings 內),否則你的 manager side 的 url 會曝光的,這樣應該就能達到你的需求才是,以上


#7

抱歉,我要修正下,client是指client端(用戶端),不是指server


#8

嗯,anyway 我只提我想得到的解法給你就是了

Rails.application.routes.draw do
  # 共用的 route
  constraints subdomain: ['manage' , 'devmanage'] do
    # manager 的 route
  end
end

你還可以這樣設定的,所以 A / B 雙站可以合併,而非分離,但如果有 server 對 server 的溝通,我都建議寫成 lib,從相同的 domain 為入口點取到對方的資料,否則一但跨越 domain 除非 CDN,都無法驗證來源的,且很多額外的資訊都會曝光哩 … 金流系統也都是,把操作委派出去後就一直在他家玩,除非結束了否則不送回來,而非雙站同時進行的