andycaramba
@andycaramba
Web Developer (JavaScript, PHP, Anything else)

Nginx + 2 RoR3 приложения, один из которых на Sub Uri. Как совместить?

Приветствую!

Уже мозг сломал со следующей проблемой.
Есть две виртуалки — одна с Nginx, другая с парой RoR3 приложений запущенных через Unicorn (каждое приложение на отдельном TCP порту). Необходимо, чтоб к первому приложению был доступ через поддомен (типа app.domain.tld), а ко второму через sub uri на этом же домене (app.domain.tld/app2).
Вроде нашёл как сделать — во втором приложении в application.rb прописал config.action_controller.relative_url_root = "/app2".
При наборе uri в браузере всё срабатывает корректно и все ассеты подгружает. Но, все ссылки на странице формируются относительно рут директории поддомена (/), а не /app2. То есть, для примера, должно быть /app2/users/login, а формирует просто /users/login.
Такое ощущение, что при формировании ссылок не учитывается тот самый config.action_controller.relative_url_root. Как можно исправить данное недоразумение?

Если это что либо значит, то приложения эти — Redmine и GitLab соответственно
Ниже привожу конфиги

nginx.vhost.conf
upstream app {
        server IP:PORT1;
}

upstream app2 {
        server IP:PORT2;
}

server {
        server_name app.domain.tld;

        client_max_body_size 8m;
        keepalive_timeout 5;

        access_log  /var/log/nginx/app.domain.tld_access.log;
        error_log   /var/log/nginx/app.domain.tld_error.log;

        # redmine
        location / {
                try_files $uri $uri/index.html $uri.html @redmine;
        }

        location @redmine {
                proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
                proxy_set_header X-Real-IP $remote_addr;
                proxy_set_header Host $http_host;
                proxy_redirect off;

                proxy_pass http://app;
        }

        # gitlab web interface
        location /app2 {
                try_files $uri $uri/index.html $uri.html @gitlab;
        }

        location @gitlab {
                rewrite /app2/(.*) /$1 break;
                proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
                proxy_set_header X-Real-IP $remote_addr;
                proxy_set_header Host $http_host;
                proxy_redirect off;

                proxy_pass http://app2;
        }

        location ~ ^/(conf|includes)/ {
                return 404;
        }

        location ~ /\. {
                deny  all;
        }
}



redmine.unicorn.rb
rails_env = ENV['RAILS_ENV'] || 'production'

app_dir = "/path-to-redmine"
worker_processes 2

user "redmine", "redmine"
working_directory app_dir

listen PORT1, :tcp_nopush => true

timeout 30

pid "#{app_dir}/tmp/pids/unicorn.pid"
stderr_path "#{app_dir}/log/unicorn.stderr.log"
stdout_path "#{app_dir}/log/unicorn.stdout.log"

# Preload Rails App for Performance
preload_app true

before_fork do |server, worker|
  defined?(ActiveRecord::Base) and
    ActiveRecord::Base.connection.disconnect!
end

after_fork do |server, worker|
  defined?(ActiveRecord::Base) and
    ActiveRecord::Base.establish_connection
end



gitlab.unicorn.rb
app_dir = "/path-to-gitlab"
worker_processes 2

user "gitlab", "gitlab"
working_directory app_dir

preload_app true

timeout 30

listen PORT2

pid "#{app_dir}/tmp/pids/unicorn.pid"
stderr_path "#{app_dir}/log/unicorn.stderr.log"
stdout_path "#{app_dir}/log/unicorn.stdout.log"

before_fork do |server, worker|
  defined?(ActiveRecord::Base) and ActiveRecord::Base.connection.disconnect!

  old_pid = "#{server.config[:pid]}.oldbin"

  if File.exists?(old_pid) && server.pid != old_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
      # someone else did our job for us
    end
  end
end

after_fork do |server, worker|
  defined?(ActiveRecord::Base) and ActiveRecord::Base.establish_connection
end


Вроде читал, что подобное легко решается через Passenger, но так же читал про него не особо лестные отзывы, да и к Юникорну привязался уже, люблю единорогов ))
  • Вопрос задан
  • 3242 просмотра
Решения вопроса 1
@dibrovsd
Аналогичная проблема.
Решил так:

1. config/environment.rb

Внизу

RedmineApp::Application.routes.default_scope = { :path => '/redmine', :shallow_path => '/redmine' }

# Это в конфиге есть
RedmineApp::Application.initialize!

Redmine::Utils::relative_url_root = "/redmine"


Таким образом, приложение ожидает запросы не от корня, а от префикса /redmine
И ссылки формирует соответсвенно, не /users/login, а /redmine/users/login

2. unicorn.rb не интересен особо, но, на всякий случай, приведу
orker_processes 2
working_directory "/home/www/redmine/"

preload_app true

timeout 30

listen "/home/www/redmine/tmp/sockets/unicorn.sock", :backlog => 64

pid "/home/www/redmine/tmp/pids/unicorn.pid"

stderr_path "/home/www/redmine/log/unicorn.stderr.log"
stdout_path "/home/www/redmine/log/unicorn.stdout.log"

before_fork do |server, worker|
    defined?(ActiveRecord::Base) and
        ActiveRecord::Base.connection.disconnect!
end

after_fork do |server, worker|
    defined?(ActiveRecord::Base) and
        ActiveRecord::Base.establish_connection
end
~                                                                         


3. Конфиг nginx
Запросы с префиксом /redmine проксируем на socket через upstream
rewrite тут не нужно, потому что redmine и так ждет от нас префикса /redmine (чтоб ссылки работали)

В вот статику отдаем через nginx напрямую.

upstream unicorn_server { 
        server unix:/home/www/redmine/tmp/sockets/unicorn.sock;         
} 

server {
        server_name docflow.soglasie.ru;

        client_max_body_size 8m;
        keepalive_timeout 5;

        # apache
        location / {
                proxy_pass http://127.0.0.1:8181;
        }

        # redmine
        location /redmine {
                proxy_pass http://unicorn_server;
        }

        # redmine static
        location ~* /redmine/.+\.(ico|css|js|png) {
                rewrite /redmine/(.*) /$1 break;
                root /home/www/redmine/public/;
        } 

}



Не претендую на качественный конфиг. Это первый опыт использования nginx.
Не пишу скрипты автозапуска и т.п. Предполагается, что они у вас есть.

Главное, что работает.
Возможно кому-то пригодится (даже мне самому, через какое-то время)
Ответ написан
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы