ruby-on-railsubuntuattachmentproductionactiontext

action text images attachments woking locally but not on production


my question is similar to this one but my hardware is different.

I'm working on a Ubuntu dedicated private server (not on AWS)

I've implemented action_text in my Rails app, and locally (in development) it works fine.

But in production, images attachments are only correctly displayed while editing form, but after form validation, in show views, the image attachments can't be displayed.


while editing (image ok) :

appli edit

edit image url looks like this :

https://www.deviaweb.fr/rails/active_storage/blobs/redirect/eyJfcmFpbHMiOnsibWVzc2FnZSI6IkJBaHBRQT09IiwiZXhwIjpudWxsLCJwdXIiOiJibG9iX2lkIn19--3926192ea6a92df6336b784d3dea6ac43028ca83/anonymous.png

in show views (image can't be displayed) :

appli show

show image url looks like this :

https://www.deviaweb.fr/rails/active_storage/representations/redirect/eyJfcmFpbHMiOnsibWVzc2FnZSI6IkJBaHBRQT09IiwiZXhwIjpudWxsLCJwdXIiOiJibG9iX2lkIn19--3926192ea6a92df6336b784d3dea6ac43028ca83/eyJfcmFpbHMiOnsibWVzc2FnZSI6IkJBaDdCem9MWm05eWJXRjBTU0lJY0c1bkJqb0dSVlE2RkhKbGMybDZaVjkwYjE5c2FXMXBkRnNIYVFJQUJHa0NBQU09IiwiZXhwIjpudWxsLCJwdXIiOiJ2YXJpYXRpb24ifX0=--060997ce63768510108f6e5dec3e2f5b17d3dc9c/anonymous.png

the urls for image are different in edit page and in show page ! why ????

What am I doing wrong ?

Do I have to configure CORS on my Ubuntu dedicated server ? If yes, How ?

Thanks in advance for your help.


here are my files :

config/routes.rb

Rails.application.routes.draw do
  resources :applis
  root to: "pages#home"
end

app/models/appli.rb

class Appli < ApplicationRecord
  has_rich_text :description
end

app/controllers/applis_controller.rb

class ApplisController < ApplicationController
  before_action :set_appli, only: %i[ show edit update destroy ]
  before_action :authenticate_user!, except: [:show, :index]

  def index
    @applis = Appli.all
  end

  def show
  end

  def new
    @appli = Appli.new
  end

  def edit
  end

  def create
    @appli = Appli.new(appli_params)

    respond_to do |format|
      if @appli.save
        format.html { redirect_to appli_url(@appli), notice: "Appli was successfully created." }
        format.json { render :show, status: :created, location: @appli }
      else
        format.html { render :new, status: :unprocessable_entity }
        format.json { render json: @appli.errors, status: :unprocessable_entity }
      end
    end
  end

  def update
    respond_to do |format|
      if @appli.update(appli_params)
        format.html { redirect_to applis_path, notice: "Appli was successfully updated." }
        format.json { render :show, status: :ok, location: @appli }
      else
        format.html { render :edit, status: :unprocessable_entity }
        format.json { render json: @appli.errors, status: :unprocessable_entity }
      end
    end
  end

  def destroy
    @appli.destroy

    respond_to do |format|
      format.html { redirect_to applis_url, notice: "Appli was successfully destroyed." }
      format.json { head :no_content }
    end
  end

  private
    def set_appli
      @appli = Appli.find(params[:id])
    end

    def appli_params
      params.require(:appli).permit(:title, :description)
    end
end

app/views/applis/_form.html.erb

<%= form_with(model: appli) do |form| %>
  <% if appli.errors.any? %>
    <div style="color: red">
      <h3><%= pluralize(appli.errors.count, "error") %> prohibited this appli from being saved:</h3>

      <ul>
        <% appli.errors.each do |error| %>
          <li><%= error.full_message %></li>
        <% end %>
      </ul>
    </div>
  <% end %>

  <div>
    <%= form.label :title, style: "display: block" %>
    <%= form.text_field :title %>
  </div>

  <div>
    <%= form.label :description, style: "display: block" %>
    <%= form.rich_text_area :description %>
  </div>

  <div class="actions">
    <%= form.submit %>
  </div>
<% end %>

app/views/applis/_appli.html.erb

<div id="<%= dom_id appli %>">
  <h2><%= appli.title %></h2>
  <div><%= appli.description %></div>
</div>

config/environments/production.rb

require "active_support/core_ext/integer/time"

Rails.application.configure do

  config.action_mailer.default_url_options = { host: "https://www.deviaweb.fr" }

  config.default_url_options = { host: "https://www.deviaweb.fr" }

  # Settings specified here will take precedence over those in config/application.rb.

  # Code is not reloaded between requests.
  config.cache_classes = true

  # Eager load code on boot. This eager loads most of Rails and
  # your application in memory, allowing both threaded web servers
  # and those relying on copy on write to perform better.
  # Rake tasks automatically ignore this option for performance.
  config.eager_load = true

  # Full error reports are disabled and caching is turned on.
  config.consider_all_requests_local       = false
  config.action_controller.perform_caching = true

  # Ensures that a master key has been made available in either ENV["RAILS_MASTER_KEY"]
  # or in config/master.key. This key is used to decrypt credentials (and other encrypted files).
  # config.require_master_key = true

  # Disable serving static files from the `/public` folder by default since
  # Apache or NGINX already handles this.
  config.public_file_server.enabled = ENV["RAILS_SERVE_STATIC_FILES"].present?

  # Compress CSS using a preprocessor.
  # config.assets.css_compressor = :sass


  # Do not fallback to assets pipeline if a precompiled asset is missed.
  config.assets.compile = true
  config.serve_static_assets = true

  # Enable serving of images, stylesheets, and JavaScripts from an asset server.
  # config.asset_host = "http://assets.example.com"

  # Specifies the header that your server uses for sending files.
  # config.action_dispatch.x_sendfile_header = "X-Sendfile" # for Apache
  config.action_dispatch.x_sendfile_header = "X-Accel-Redirect" # for NGINX

  # Store uploaded files on the local file system (see config/storage.yml for options).
  config.active_storage.service = :local

  # Mount Action Cable outside main process or domain.
  # config.action_cable.mount_path = nil
  # config.action_cable.url = "wss://example.com/cable"
  # config.action_cable.allowed_request_origins = [ "http://example.com", /http:\/\/example.*/ ]

  # Force all access to the app over SSL, use Strict-Transport-Security, and use secure cookies.
  # config.force_ssl = true

  # Include generic and useful information about system operation, but avoid logging too much
  # information to avoid inadvertent exposure of personally identifiable information (PII).
  config.log_level = :info

  # Prepend all log lines with the following tags.
  config.log_tags = [ :request_id ]

  # Use a different cache store in production.
  # config.cache_store = :mem_cache_store

  # Use a real queuing backend for Active Job (and separate queues per environment).
  # config.active_job.queue_adapter     = :resque
  # config.active_job.queue_name_prefix = "deviaweb_fr_production"

  config.action_mailer.perform_caching = false

  # Ignore bad email addresses and do not raise email delivery errors.
  # Set this to true and configure the email server for immediate delivery to raise delivery errors.
  # config.action_mailer.raise_delivery_errors = false

  # Enable locale fallbacks for I18n (makes lookups for any locale fall back to
  # the I18n.default_locale when a translation cannot be found).
  config.i18n.fallbacks = true

  # Don't log any deprecations.
  config.active_support.report_deprecations = false

  # Use default logging formatter so that PID and timestamp are not suppressed.
  config.log_formatter = ::Logger::Formatter.new

  # Use a different logger for distributed setups.
  # require "syslog/logger"
  # config.logger = ActiveSupport::TaggedLogging.new(Syslog::Logger.new "app-name")

  if ENV["RAILS_LOG_TO_STDOUT"].present?
    logger           = ActiveSupport::Logger.new(STDOUT)
    logger.formatter = config.log_formatter
    config.logger    = ActiveSupport::TaggedLogging.new(logger)
  end

  config.active_record.dump_schema_after_migration = false
end

config/storage.yml

test:
  service: Disk
  root: <%= Rails.root.join("tmp/storage") %>

local:
  service: Disk
  root: <%= Rails.root.join("storage") %>

app/javascript/application.js

import "trix"
import "@rails/actiontext"

app/assets/stylesheets/application.scss

@import "trix/dist/trix";
@import "actiontext";

I'm deploying to production using Capistrano, but I've failed commands and a warning message while deploying :

capistrano.log (only the failed and warnings logs)


 DEBUG [dd561607] Running [ -L /home/deploy/deviaweb/releases/20221022121910/log ] as deploy@my_server_ip
 DEBUG [dd561607] Command: [ -L /home/deploy/deviaweb/releases/20221022121910/log ]
 DEBUG [dd561607] Finished in 0.121 seconds with exit status 1 (failed).
 DEBUG [db9d98cb] Running [ -L /home/deploy/deviaweb/releases/20221022121910/tmp/pids ] as deploy@my_server_ip
 DEBUG [db9d98cb] Command: [ -L /home/deploy/deviaweb/releases/20221022121910/tmp/pids ]
 DEBUG [db9d98cb] Finished in 0.121 seconds with exit status 1 (failed).
 DEBUG [e1a94393] Running [ -L /home/deploy/deviaweb/releases/20221022121910/tmp/cache ] as deploy@my_server_ip
 DEBUG [e1a94393] Command: [ -L /home/deploy/deviaweb/releases/20221022121910/tmp/cache ]
 DEBUG [e1a94393] Finished in 0.128 seconds with exit status 1 (failed).
 DEBUG [8505c6a7] Running [ -d /home/deploy/deviaweb/releases/20221022121910/tmp/cache ] as deploy@my_server_ip
 DEBUG [8505c6a7] Command: [ -d /home/deploy/deviaweb/releases/20221022121910/tmp/cache ]
 DEBUG [8505c6a7] Finished in 0.122 seconds with exit status 1 (failed).
 DEBUG [7726cad7] Running [ -L /home/deploy/deviaweb/releases/20221022121910/tmp/sockets ] as deploy@my_server_ip
 DEBUG [7726cad7] Command: [ -L /home/deploy/deviaweb/releases/20221022121910/tmp/sockets ]
 DEBUG [7726cad7] Finished in 0.121 seconds with exit status 1 (failed).
 DEBUG [22766157] Running [ -d /home/deploy/deviaweb/releases/20221022121910/tmp/sockets ] as deploy@my_server_ip
 DEBUG [22766157] Command: [ -d /home/deploy/deviaweb/releases/20221022121910/tmp/sockets ]
 DEBUG [22766157] Finished in 0.123 seconds with exit status 1 (failed).
 DEBUG [b010a982] Running [ -L /home/deploy/deviaweb/releases/20221022121910/vendor/bundle ] as deploy@my_server_ip
 DEBUG [b010a982] Command: [ -L /home/deploy/deviaweb/releases/20221022121910/vendor/bundle ]
 DEBUG [b010a982] Finished in 0.122 seconds with exit status 1 (failed).
 DEBUG [0fba4998] Running [ -d /home/deploy/deviaweb/releases/20221022121910/vendor/bundle ] as deploy@my_server_ip
 DEBUG [0fba4998] Command: [ -d /home/deploy/deviaweb/releases/20221022121910/vendor/bundle ]
 DEBUG [0fba4998] Finished in 0.123 seconds with exit status 1 (failed).
 DEBUG [e14770e8] Running [ -L /home/deploy/deviaweb/releases/20221022121910/.bundle ] as deploy@my_server_ip
 DEBUG [e14770e8] Command: [ -L /home/deploy/deviaweb/releases/20221022121910/.bundle ]
 DEBUG [e14770e8] Finished in 0.122 seconds with exit status 1 (failed).
 DEBUG [88e8095e] Running [ -d /home/deploy/deviaweb/releases/20221022121910/.bundle ] as deploy@my_server_ip
 DEBUG [88e8095e] Command: [ -d /home/deploy/deviaweb/releases/20221022121910/.bundle ]
 DEBUG [88e8095e] Finished in 0.123 seconds with exit status 1 (failed).
 DEBUG [8fc5e0b3] Running [ -L /home/deploy/deviaweb/releases/20221022121910/public/system ] as deploy@my_server_ip
 DEBUG [8fc5e0b3] Command: [ -L /home/deploy/deviaweb/releases/20221022121910/public/system ]
 DEBUG [8fc5e0b3] Finished in 0.173 seconds with exit status 1 (failed).
 DEBUG [30611cdb] Running [ -d /home/deploy/deviaweb/releases/20221022121910/public/system ] as deploy@my_server_ip
 DEBUG [30611cdb] Command: [ -d /home/deploy/deviaweb/releases/20221022121910/public/system ]
 DEBUG [30611cdb] Finished in 0.128 seconds with exit status 1 (failed).
 DEBUG [d3504989] Running [ -L /home/deploy/deviaweb/releases/20221022121910/public/uploads ] as deploy@my_server_ip
 DEBUG [d3504989] Command: [ -L /home/deploy/deviaweb/releases/20221022121910/public/uploads ]
 DEBUG [d3504989] Finished in 0.151 seconds with exit status 1 (failed).
 DEBUG [b7ab3a35] Running [ -d /home/deploy/deviaweb/releases/20221022121910/public/uploads ] as deploy@my_server_ip
 DEBUG [b7ab3a35] Command: [ -d /home/deploy/deviaweb/releases/20221022121910/public/uploads ]
 DEBUG [b7ab3a35] Finished in 0.125 seconds with exit status 1 (failed).
 DEBUG [ddd629a2] Running [ -L /home/deploy/deviaweb/releases/20221022121910/storage ] as deploy@my_server_ip
 DEBUG [ddd629a2] Command: [ -L /home/deploy/deviaweb/releases/20221022121910/storage ]
 DEBUG [ddd629a2] Finished in 0.125 seconds with exit status 1 (failed).
 DEBUG [abf6dda9] Running [ -L /home/deploy/deviaweb/releases/20221022121910/public/assets ] as deploy@my_server_ip
 DEBUG [abf6dda9] Command: [ -L /home/deploy/deviaweb/releases/20221022121910/public/assets ]
 DEBUG [abf6dda9] Finished in 0.126 seconds with exit status 1 (failed).
 DEBUG [edb6d951] Running [ -d /home/deploy/deviaweb/releases/20221022121910/public/assets ] as deploy@my_server_ip
 DEBUG [edb6d951] Command: [ -d /home/deploy/deviaweb/releases/20221022121910/public/assets ]
 DEBUG [edb6d951] Finished in 0.125 seconds with exit status 1 (failed).

 DEBUG [5703ad55]   warning " > @rails/actiontext@7.0.4" has incorrect peer dependency "trix@^1.3.1".


Solution

  • I solved the problem !

    my production server was running Ubuntu 18.04, but locally I was using Ubuntu 20.04.

    The problem was with libvips. On Ubuntu 18.04, you can not install Vips with a version superior than vips-8.4 (or something similar). But loccaly (Ubuntu 20.04) I was using vips-8.9.1.

    I upgraded my server to Ubuntu 20.04 to be able to use latest version of Vips (8.9.1) and now everything works fine.

    Hope this helped !