49
46

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

【備忘録】nginx, Rails連携時にassets配下のファイルにアクセスできない場合の解決方法

Last updated at Posted at 2017-07-30

はじめに

nginx, Rails連携させている環境において、assets配下のファイルにアクセスできない場合があるので解決方法をメモしておきます。

原因
ケース1:productionモードでassets配下のアクセスをRailsへ転送している
ケース2:アクセス権が原因でnginxがassets配下のファイルにアクセスできない
ケース3:SELinuxが原因でnginxがassets配下のファイルにアクセスできない

環境
CentOS 7.3.1611
Rails 5.1.2
nginx 1.10.2

事前準備
Rails : 3000ポートでサーバ起動しておく
nginx : アクセスを3000ポートへ転送する

問題点

Railsへアクセスした際にcss, jsが読み込まれない

ケース1:productionモードでassets配下のアクセスをRailsへ転送している

調査

このケースではアクセス時にnginxのエラーログは出力されない

$ sudo tail /var/log/nginx/hello-app_error.log

Railsのログでcss, jsへのアクセス時にNo route matchesと出力される

tail -f log/production.log 

F, [2017-07-30T05:39:40.310181 #4934] FATAL -- : [f8ec5376-7c17-4aa0-b46b-e3669b834c5e] ActionController::R
outingError (No route matches [GET] "/assets/application-35729bfbaf9967f119234595ed222f7ab14859f304ab0acc54
51afb387f637fa.css"):

F, [2017-07-30T05:39:40.439806 #4934] FATAL -- : [6bfdd3a1-fbae-4cf3-9566-c8865ee56988] ActionController::R
outingError (No route matches [GET] "/assets/application-a0c66820a1b25b7b91aab7fb553a37bc0728f9b1df860c3660
e590597bf9cafa.js"):

暫定対処/ローカル環境

config/environments/production.rbconfig.public_file_server.enabledを有効にする

config/environments/production.rb
config.public_file_server.enabled = true

解決方法

nginxからassets配下のファイルへアクセスさせる

nginxの設定ファイルを編集

/etc/nginx/sites-available/hello-app
upstream hello-app {
  server unix:/home/xxx/hello-app/tmp/sockets/puma.sock;
}
server {
  listen 80;
  server_name hello-app;
  root /path/hello-app/public;
  access_log  /var/log/nginx/helllo-app_access.log;
  error_log   /var/log/nginx/hello-app_error.log;

  # ==追記ここから===
  location ~ ^/assets/ {
    root   /home/xxx/hello-app/public;
  }
  # ==追記ここまで===

  location / {
    client_max_body_size 0;
    gzip off;
    proxy_read_timeout      300;
    proxy_connect_timeout   300;
    proxy_redirect          off;
    proxy_http_version 1.1;
    proxy_set_header    Host                $http_host;
    proxy_set_header    X-Real-IP           $remote_addr;
    proxy_set_header    X-Forwarded-For     $proxy_add_x_forwarded_for;
    proxy_set_header    X-Forwarded-Proto   $scheme;
    proxy_pass http://127.0.0.1:3000;
  }
}

nginxに設定ファイルを再読込させる

# nginxを手動起動していた場合
$ sudo nginx -s reload

# nginxをサービス起動していた場合
$ sudo service nginx reload

アクセス確認
http://xxx.xxx.xxx.xxx

→ css, jsが読み込めたらOK
→ css, jsが404エラーとなる場合はpublicディレクトリへのパスを再確認
→ css, jsが403エラーとなる場合はケース2〜3も確認する

ケース2:アクセス権が原因でnginxがassets配下のファイルにアクセスできない

調査

このケースではアクセス時にnginxのエラーログにopen() "/home/xxx/hello-app/public/assets/xxx.css" failed (13: Permission denied)と出力される

$ sudo tail /var/log/nginx/hello-app_error.log

2017/07/30 06:00:12 [error] 5175#0: *215 open() "/home/xxx/hello-app/public/assets/application-3572
9bfbaf9967f119234595ed222f7ab14859f304ab0acc5451afb387f637fa.css" failed (13: Permission denied), client: 1
xxx.xxx.xxx.xxx, server: hello-app, request: "GET /assets/application-35729bfbaf9967f119234595ed222f7ab14859
f304ab0acc5451afb387f637fa.css HTTP/1.1", host: "xxx.xxx.xxx.xxx", referrer: "http://xxx.xxx.xxx.xxx/"

解決方法

/から/publicまでのディレクトリにnginx実行ユーザへのアクセス権が付与されてるか確認する。付与されてないディレクトリにはアクセス権を付与する

# アクセス権を確認
$ ls -l /home/xxx

# アクセス権を付与
$ chmod 755 /home/xxx

アクセス確認
http://xxx.xxx.xxx.xxx

→ css, jsが読み込めたらOK
→ css, jsが403エラーとなる場合は3も確認する

ケース3:SELinuxが原因でnginxがassets配下のファイルにアクセスできない

調査

このケースでもアクセス時にnginxのエラーログにopen() "/home/xxx/hello-app/public/assets/xxx.css" failed (13: Permission denied)と出力される

$ sudo tail /var/log/nginx/hello-app_error.log

2017/07/30 06:00:12 [error] 5175#0: *215 open() "/home/xxx/hello-app/public/assets/application-3572
9bfbaf9967f119234595ed222f7ab14859f304ab0acc5451afb387f637fa.css" failed (13: Permission denied), client: 1
xxx.xxx.xxx.xxx, server: hello-app, request: "GET /assets/application-35729bfbaf9967f119234595ed222f7ab14859
f304ab0acc5451afb387f637fa.css HTTP/1.1", host: "xxx.xxx.xxx.xxx", referrer: "http://xxx.xxx.xxx.xxx/"

解決方法

SELinuxのモジュールを追加・更新する
(過去にモジュールを追加していた場合でも下記コマンドの結果と設定済みモジュールに差分がないか確認する)

# ポリシー確認
$ sudo cat /var/log/audit/audit.log | grep nginx | audit2allow -m nginx

module nginx 1.0;
require {
        type httpd_t;
        type user_home_t;
        type ntop_port_t;
        class tcp_socket name_connect;
        class file { open read };
}
#============= httpd_t ==============
#!!!! This avc is allowed in the current policy
allow httpd_t ntop_port_t:tcp_socket name_connect;
#!!!! This avc can be allowed using the boolean 'httpd_read_user_content'
allow httpd_t user_home_t:file read;

# モジュール作成
$ sudo cat /var/log/audit/audit.log | audit2allow -M nginx

# インストール
$ sudo semodule -i nginx.pp

アクセス確認
http://xxx.xxx.xxx.xxx

→ css, jsが読み込めたらOK
→ css, jsが403エラーとなる場合は再度ポリシー確認を実施する

補足:
作成されるポリシーの内容はaudit.logの内容によって変わる
SELinuxを無効にして解決する場合はモジュールの更新を実施する

今回は環境構築中に以下のように変化した

require {
        type httpd_t;
        type ntop_port_t;
        class tcp_socket name_connect;
}

 ↓

require {
        type httpd_t;
        type user_home_t;
        type ntop_port_t;
        class tcp_socket name_connect;
        class file { open read };
}

補足:
SELinuxセキュリティコンテキストはlsコマンドの-Zオプションで確認できる

$ ls -Z

最終手段

SELinuxを一時的に無効にする

# SELinuxの無効化
$ sudo setenforce 0

# SELinuxの状態確認
$ sudo getenforce

Permissive

SELinuxの無効を永続化する

# 設定変更
$ sudo vi /etc/selinux/config
/etc/selinux/config
SELINUX=disabled
# 再起動
$ sudo reboot
49
46
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
49
46

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?