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) :
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) :
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".
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 !
Related
Consider a site where Rails is used only for API. No server-side rendering.
With server-side rendering it's more or less clear. capybara starts puma, after which tests can connect to puma for pages.
But with no server-side rendering, there's no puma to ask for pages. How do I do that?
Explain yourself when downvoting, please.
Have a look at http://ruby-hyperloop.org. You can drive your client test suite from rspec, and easily integrate with rails
While Server-Side Rendering must be very common these days, I decided to take an alternative approach.
Add the following gems to the Gemfile:
gem 'httparty', '~> 0.16.2'
gem 'childprocess', '~> 0.7.0'
Move the following lines from config/environments/production.rb to config/application.rb to make RAILS_LOG_TO_STDOUT available in the test environment.
if ENV['RAILS_LOG_TO_STDOUT'].present?
config.logger = Logger.new(STDOUT)
end
Regarding webpack, make sure publicPath is set to http://localhost:7777/, and UglifyJsPlugin is not used in the test environment.
And add these two files:
test/application_system_test_case.rb:
# frozen_string_literal: true
require 'uri'
require 'test_helper'
require 'front-end-server'
FRONT_END = ENV.fetch('FRONT_END', 'separate_process')
FRONT_END_PORT = 7777
Capybara.server_port = 7778
Capybara.run_server = ENV.fetch('BACK_END', 'separate_process') == 'separate_thread'
require 'action_dispatch/system_test_case' # force registering and setting server
Capybara.register_server :rails_puma do |app, port, host|
Rack::Handler::Puma.run(app, Port: port, Threads: "0:1",
Verbose: ENV.key?('BACK_END_LOG'))
end
Capybara.server = :rails_puma
DatabaseCleaner.strategy = :truncation
class ApplicationSystemTestCase < ActionDispatch::SystemTestCase
driven_by :selenium, using: :chrome, screen_size: [1400, 1400]
self.use_transactional_tests = false
def setup
DatabaseCleaner.start
end
def teardown
DatabaseCleaner.clean
end
def uri(path)
URI::HTTP.build(host: 'localhost', port: FRONT_END_PORT, path: path)
end
end
unless ENV.key?('NO_WEBPACK')
system(
{'NODE_ENV' => 'test'},
'./node_modules/.bin/webpack', '--config', 'config/webpack/test.js', '--hide-modules') \
or abort
end
if FRONT_END == 'separate_process'
front_srv = ChildProcess.build(
'bundle', 'exec', 'test/front-end-server.rb',
'-f', FRONT_END_PORT.to_s,
'-b', Capybara.server_port.to_s
)
if ENV.key?('FRONT_END_LOG')
front_srv.io.inherit!
end
front_srv.start
Minitest.after_run {
front_srv.stop
}
else
Thread.new do
FrontEndServer.new({
Port: FRONT_END_PORT,
back_end_port: Capybara.server_port,
Logger: Rails.logger,
}).start
end
end
unless Capybara.run_server
back_srv = ChildProcess.build(
'bin/rails', 'server',
'-P', 'tmp/pids/server-test.pid', # to not conflict with dev instance
'-p', Capybara.server_port.to_s
)
back_srv.start
# wait for server to start
begin
socket = TCPSocket.new 'localhost', Capybara.server_port
rescue Errno::ECONNREFUSED
retry
end
socket.close
Minitest.after_run {
back_srv.stop
}
end
test/front-end-server.rb:
#!/usr/bin/env ruby
require 'webrick'
require 'httparty'
require 'uri'
class FrontEndServer < WEBrick::HTTPServer
class FallbackFileHandler < WEBrick::HTTPServlet::FileHandler
def service(req, res)
super
rescue WEBrick::HTTPStatus::NotFound
req.instance_variable_set('#path_info', '/index.html')
super
end
end
class ProxyHandler < WEBrick::HTTPServlet::AbstractServlet
def do_GET(req, res)
req.header.each do |k, v|
#logger.debug("-> #{k}: #{v}");
end
#logger.debug("-> body: #{req.body}");
uri2 = req.request_uri.dup
uri2.port = #config[:back_end_port]
res2 = HTTParty.send(req.request_method.downcase, uri2, {
headers: Hash[req.header.map { |k, v| [k, v.join(', ')] }],
body: req.body,
})
res.content_type = res2.headers['content-type']
res.body = res2.body
res2.headers.each do |k, v|
#logger.debug("<- #{k}: #{v}");
end
if res.body
body = res.body.length < 100 ? res.body : res.body[0,97] + '...'
#logger.debug("<- body: #{req.body}");
end
end
alias do_POST do_GET
alias do_PATCH do_GET
alias do_PUT do_GET
alias do_DELETE do_GET
alias do_MOVE do_GET
alias do_COPY do_GET
alias do_HEAD do_GET
alias do_OPTIONS do_GET
alias do_MKCOL do_GET
end
def initialize(config={}, default=WEBrick::Config::HTTP)
config = {AccessLog: config[:Logger] ? [
[config[:Logger], WEBrick::AccessLog::COMMON_LOG_FORMAT],
] : [
[$stderr, WEBrick::AccessLog::COMMON_LOG_FORMAT],
]}.update(config)
super
if ENV.key?('FRONT_END_LOG_LEVEL')
logger.level = WEBrick::BasicLog.const_get(ENV['FRONT_END_LOG_LEVEL'])
end
mount('/', FallbackFileHandler, 'public')
mount('/api', ProxyHandler)
mount('/uploads', ProxyHandler)
end
end
if __FILE__ == $0
require 'optparse'
options = {}
OptionParser.new do |opt|
opt.on('-f', '--front-end-port PORT', OptionParser::DecimalInteger) { |o|
options[:front_end_port] = o
}
opt.on('-b', '--back-end-port PORT', OptionParser::DecimalInteger) { |o|
options[:back_end_port] = o
}
end.parse!
server = FrontEndServer.new({
Port: options[:front_end_port],
back_end_port: options[:back_end_port],
})
trap('INT') { server.shutdown }
trap('TERM') { server.shutdown }
server.start
end
Tested with rails-5.1.1, webpack-2.4.1.
To run the tests you can use the following commands:
$ xvfb-run TESTOPTS=-h bin/rails test:system
$ xvfb-run bin/rails test -h test/system/application_test.rb:6
$ xvfb-run TEST=test/system/application_test.rb TESTOPTS=-h bin/rake test
You can simplify running tests by adding package scripts:
"scripts": {
"test": "xvfb-run bin/rails test:system",
"test1": "xvfb-run bin/rails test"
}
Then:
$ yarn test
$ yarn test1 test/system/application_test.rb:6
Or so I'd like to say. But unfortunately yarn has an issue where it prepends extra paths to the PATH variable. Particularly, /usr/bin. Which leads to system ruby being executed. With all sorts of outcomes (ruby not finding gems).
To work around it you may use the following script:
#!/usr/bin/env bash
set -eu
# https://github.com/yarnpkg/yarn/issues/5935
s_path=$(printf "%s" "$PATH" | tr : \\n)
_IFS=$IFS
IFS=$'\n'
a_path=($s_path)
IFS=$_IFS
usr_bin=$(dirname -- "$(which node)")
n_usr_bin=$(egrep "^$usr_bin$" <(printf "%s" "$s_path") | wc -l)
r=()
for (( i = 0; i < ${#a_path[#]}; i++ )); do
if [ "${a_path[$i]}" = "$usr_bin" ] && (( n_usr_bin > 1 )); then
(( n_usr_bin-- ))
else
r+=("${a_path[$i]}")
fi
done
PATH=$(
for p in ${r[#]+"${r[#]}"}; do
printf "%s\n" "$p"
done | paste -sd:
)
"$#"
Then the package scripts are to be read as follows:
"scripts": {
"test": "./fix-path.sh xvfb-run bin/rails test:system",
"test1": "./fix-path.sh xvfb-run bin/rails test"
}
By default, rails starts puma in a separate thread to handle api requests while running tests. With this setup it by default runs in a separate process. Since then you can drop byebug line anywhere in your test, and the site in the browser will remain functional (XHR requests will not stuck). You can still make it run in a separate thread if you feel like it by setting BACK_END=separate_thread.
Additionally, another process (or thread, depending on the value of the FRONT_END variable) will start to handle requests for static files (or proxy requests to the back end). For that webrick is used.
To see rails's output, run with RAILS_LOG_TO_STDOUT=1, or see log/test.log. To prevent rails from colorizing the log, add config.colorize_logging = false (which will strip colors in the console as well) to config/environments/test.rb, or use less -R log/test.log. puma's output can be seen by running with BACK_END_LOG=1.
To see webrick's output, run with FRONT_END_LOG=1 (separate process), RAILS_LOG_TO_STDOUT=1 (separate thread), or see log/test.log (separate thread). To make webrick produce more info, set FRONT_END_LOG_LEVEL to DEBUG.
Also, every time you run the tests, webpack starts to compile the bundle. You can avoid that with WEBPACK=1.
Finally, to see Selenium requests:
Selenium::WebDriver.logger.level = :debug # full logging
Selenium::WebDriver.logger.level = :warn # back to normal
Selenium::WebDriver.logger.output = 'selenium.log' # log to file
I keep getting a 503 error 30 seconds after a client sends a message through faye. After the 30 seconds the client then receives the message and it is appended to the chat but the error still occurs and the socket will eventually close. How can i modify my existing code to keep the websocket alive? And how can I get rid of the 30 second delay that heroku throws when a message is sent?
messages/add.js.erb
<% broadcast #path do %>
var $chat = $("#chat<%= #conversation.id %>");
$chat.append("<%= j render(#message) %>");
//Set the scroll bar to the bottom of the chat box
var messageBox = document.getElementById('chat<%= #conversation.id %>');
messageBox.scrollTop = messageBox.scrollHeight;
<% end %>
$("#convoId<%=#conversation.id%>")[0].reset();
application_helper.rb
def broadcast(channel, &block)
message = {:channel => channel, :data => capture(&block), :ext => {:auth_token => FAYE_TOKEN}}
uri = URI.parse(FAYE_END_PT)
Net::HTTP.post_form(uri, :message => message.to_json)
end
application.rb
config.middleware.delete Rack::Lock
config.middleware.use FayeRails::Middleware, mount: '/faye', :timeout => 25
faye.ru
require 'faye'
require File.expand_path('../faye_token.rb', __FILE__)
class ServerAuth
def incoming(message, callback)
if message['channel'] !~ %r{^/meta/}
if message['ext']['auth_token'] != FAYE_TOKEN
message['error'] = 'Invalid authentication token'
end
end
callback.call(message)
end
end
Faye::WebSocket.load_adapter('thin')
faye_server = Faye::RackAdapter.new(:mount => '/faye', :timeout => 45)
faye_server.add_extension(ServerAuth.new)
run faye_server
Procfile
web: bundle exec rails server -p $PORT
worker: bundle exec foreman start -f Procfile.workers
Procile.workers
faye_worker: rackup middlewares/faye.ru -s thin -E production
503 Error
/messages/add Failed to load resource: the server responded with a status of 503 (Service Unavailable)
I tried adding a worker to heroku along with a web dyno with no luck. Everything works fine on my local host when running heroku local. The process on the local host look like
forego | starting web.1 on port 5000
forego | starting worker.1 on port 5100
worker.1 | 20:33:18 faye_worker.1 | started with pid 16534
where as even with the web dyno and worker on heroku
=== web (1X): bundle exec rails server -p $PORT
web.1: up 2015/12/28 20:08:02 (~ 1h ago)
=== worker (1X): bundle exec foreman start -f Procfile.workers
worker.1: up 2015/12/28 21:18:39 (~ 40s ago)
A lot of this code was taken from various tutorials so hopefully if we can solve this issue it will make using Faye with Heroku easier to someone else as well. Thanks!
Heroku has a 30 seconds timeout for all the requests, after that raise an H12 error. https://devcenter.heroku.com/articles/limits#http-timeouts
If your request takes more that 30 seconds you should consider put it into a background job using Delayed_Job or Sidekiq for example.
I'm really stuck here and am worried my mailer config files are all messed up. My app seems to work fine locally, I'm on Nitrous. I can git push heroku master fine and when opened can view the home page, which is just a form(https://nameless-taiga-1654.herokuapp.com/), however once I hit submit I get an error message. I believe all my mailer actions on nitrous are setup correctly, I was planning on using sendgrid via heroku to run the mailing side of things. Basically I'm just lost and need help. Attached are the heroku logs of the form error.
heroku logs -t
2015-08-07T11:00:54.501756+00:00 heroku[router]: at=info method=POST path="/contacts" host=nameless-taiga-1654.herokuapp.com request_id=452df9b2-aef8-4a23-9ffb-3ba6781d80
75 fwd="124.149.33.78" dyno=web.1 connect=1ms service=72ms status=500 bytes=1754
2015-08-07T11:00:54.433019+00:00 app[web.1]: Started POST "/contacts" for 124.149.33.78 at 2015-08-07 11:00:54 +0000
2015-08-07T11:00:54.437794+00:00 app[web.1]: Parameters: {"utf8"=>"✓", "authenticity_token"=>"Z2Qh/GDIycId0uJk2evhblbKisGXNlIzjtz+xfJoyac=", "contact"=>{"name"=>"John D
oe", "phone"=>"040000000", "email"=>"johndoe#gmail.com", "event_type"=>"Corporate", "comments"=>"Test Comments"}, "commit"=>"Submit"}
2015-08-07T11:00:54.491841+00:00 app[web.1]:
2015-08-07T11:00:54.491846+00:00 app[web.1]: Sent mail to justindavidson23#gmail.com (21.8ms)
2015-08-07T11:00:54.491848+00:00 app[web.1]: Completed 500 Internal Server Error in 53ms
2015-08-07T11:00:54.492821+00:00 app[web.1]:
2015-08-07T11:00:54.492824+00:00 app[web.1]: Errno::ECONNREFUSED (Connection refused - connect(2)):
2015-08-07T11:00:54.436340+00:00 app[web.1]: Processing by ContactsController#create as HTML
2015-08-07T11:00:54.492826+00:00 app[web.1]: app/mailers/contact_mailer.rb:8:in `contact_email'
2015-08-07T11:00:54.463333+00:00 app[web.1]: Rendered contact_mailer/contact_email.html.erb (0.3ms)
2015-08-07T11:00:54.492828+00:00 app[web.1]: app/controllers/contacts_controller.rb:9:in `create'
2015-08-07T11:00:54.492831+00:00 app[web.1]:
2015-08-07T11:00:54.492830+00:00 app[web.1]:
2015-08-07T11:00:54.492827+00:00 app[web.1]: app/models/contact.rb:7:in `send_email'
contacts_controller.rb
class ContactsController < ApplicationController
def new
#contact = Contact.new
end
def create
#contact = Contact.new(contact_params)
if #contact.save
flash[:success] = 'Message Sent.'
redirect_to new_contact_path
else
flash[:danger] = 'Error occurred, messgage not sent.'
redirect_to new_contact_path
end
end
end
models/contact.rb
class Contact < ActiveRecord::Base
validates :name, :email, presence: true
after_create :send_email
private
def send_email
ContactMailer.contact_email(self).deliver
end
end
mailers/contact_mailer.rb
class ContactMailer < ActionMailer::Base
default to: 'justindavidson23#gmail.com'
def contact_email(contact)
#contact = contact
mail(from: #contact.email, subject: 'Contact Form Message').deliver
end
end
views/contact_mailer/contact_email.html.erb
<!DOCTYPE html>
<html>
<head>
<title></title>
</head>
<body>
<p>New Message from Hoot and Holla's Contact form, from <%= "#{#contact.name}, #{#contact.email}" %></p>
<p><%= #contact.phone %></p>
<p><%= #contact.event_type %></p>
<p><%= #contact.comments %></p>
</body>
</html>
application.html.erb
<!DOCTYPE html>
<html>
<head>
<title>HootandhollaLp</title>
<%= stylesheet_link_tag 'application', media: 'all', 'data-turbolinks-track' => true %>
<%= javascript_include_tag 'application', 'data-turbolinks-track' => true %>
<%= csrf_meta_tags %>
</head>
<body>
<div class="container">
<% flash.each do |key, value| %>
<div class="alert alert-<%= key %> alert-dismissible">
<button type="button" class="close" data-dismiss="alert" aria-label="Close"><span aria-hidden="true">×</span></button>
<%= value %>
</div>
<% end %>
<%= yield %>
</div>
</body>
</html>
#Pavan #alexsmn I hope this helps?
config/environments/production.rb
Rails.application.configure do
# 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
# Enable Rack::Cache to put a simple HTTP cache in front of your application
# Add `rack-cache` to your Gemfile before enabling this.
# For large-scale production use, consider using a caching reverse proxy like nginx, varnish or squid.
# config.action_dispatch.rack_cache = true
# Disable Rails's static asset server (Apache or nginx will already do this).
config.serve_static_assets = false
# Compress JavaScripts and CSS.
config.assets.js_compressor = :uglifier
# config.assets.css_compressor = :sass
# Do not fallback to assets pipeline if a precompiled asset is missed.
config.assets.compile = false
# Generate digests for assets URLs.
config.assets.digest = true
# Version of your assets, change this if you want to expire all your assets.
config.assets.version = '1.0'
# 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
# Force all access to the app over SSL, use Strict-Transport-Security, and use secure cookies.
# config.force_ssl = true
# Set to :debug to see everything in the log.
config.log_level = :info
# Prepend all log lines with the following tags.
# config.log_tags = [ :subdomain, :uuid ]
# Use a different logger for distributed setups.
# config.logger = ActiveSupport::TaggedLogging.new(SyslogLogger.new)
# Use a different cache store in production.
# config.cache_store = :mem_cache_store
# Enable serving of images, stylesheets, and JavaScripts from an asset server.
# config.action_controller.asset_host = "http://assets.example.com"
# Precompile additional assets.
# application.js, application.css, and all non-JS/CSS in app/assets folder are already added.
# config.assets.precompile += %w( search.js )
# 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
# Send deprecation notices to registered listeners.
config.active_support.deprecation = :notify
# Disable automatic flushing of the log to improve performance.
# config.autoflush_log = false
# Use default logging formatter so that PID and timestamp are not suppressed.
config.log_formatter = ::Logger::Formatter.new
# Do not dump schema after migrations.
config.active_record.dump_schema_after_migration = false
end
config/environment.rb
# Load the Rails application.
require File.expand_path('../application', __FILE__)
# Initialize the Rails application.
Rails.application.initialize!
ActionMailer::Base.smtp_settings = {
:address => 'smtp.sendgrid.net',
:port => '587',
:authentication => :plain,
:user_name => ENV['SENDGRID_USERNAME'],
:password => ENV['SENDGRID_PASSWORD'],
:domain => 'heroku.com',
:enable_startstls_auto => true
}
I have had the same problem working with my current project. Actually, as I found out, this is a Gmail authentication problem. Your app is trying to login into Gmail account and cannot do it because Gmail does not see or recognize encrypted email and password. I temporarily solved this problem by writing necessary values into my smtp_settings directly, like:
smtp_settings = {
...
:user_name => "...your gmail email...",
:password => "...your gmail password...",
...
}
Also, I changed Gmail account security settings: turned off double authentication and allowed my account to be accessed by less secure apps. So, currently the app is deployed on Heroku and working. However, from cyber security point of view my solution is rather dangerous, so I am still looking for better ones.
EDITED!!!
There is a better way to encrypt gmail account settings. In my .bashrc file (is hidden in computer root directory - press Ctrl+H to reveal) I wrote the following lines of code:
export GMAIL_NAME=necessary value here
export GMAIL_PASSWORD=necessary value here
After this I also changed my smtp_settings one more time, like:
smtp_settings = {
...
user_name: ENV['GMAIL_NAME'],
password: ENV['GMAIL_PASSWORD'],
...
}
Finally, I configured repo setting on Heroku: Heroku/Personal apps/myApp/Settings, section "Config variables" via adding two new variables GMAIL_NAME and GMAIL_PASSWORD with necessary values.
It worked.
Try setting the following in your production.rb file:
config.action_mailer.delivery_method = :smtp
config.action_mailer.perform_deliveries = true
config.action_mailer.default_url_options = { host: 'nameless-taiga-1654.herokuapp.com' }
Also, to verify the configuration is correct, you can run heroku config.
I'm having trouble figuring out how to get God to restart resque.
I've got a Rails 3.2.2 stack on a Ubuntu 10.04.3 LTS Linode slice. Its running system Ruby 1.9.3-p194 (no RVM).
There's a God init.d service at /etc/init.d/god-service that contains:
CONF_DIR=/etc/god
GOD_BIN=/var/www/myapp.com/shared/bundle/ruby/1.9.1/bin/god
RUBY_BIN=/usr/local/bin/ruby
RETVAL=0
# Go no further if config directory is missing.
[ -d "$CONF_DIR" ] || exit 0
case "$1" in
start)
# Create pid directory
$RUBY_BIN $GOD_BIN -c $CONF_DIR/master.conf
RETVAL=$?
;;
stop)
$RUBY_BIN $GOD_BIN terminate
RETVAL=$?
;;
restart)
$RUBY_BIN $GOD_BIN terminate
$RUBY_BIN $GOD_BIN -c $CONF_DIR/master.conf
RETVAL=$?
;;
status)
$RUBY_BIN $GOD_BIN status
RETVAL=$?
;;
*)
echo "Usage: god {start|stop|restart|status}"
exit 1
;;
esac
exit $RETVAL
master.conf in the above contains:
load "/var/www/myapp.com/current/config/resque.god"
resque.god in the above contains:
APP_ROOT = "/var/www/myapp.com/current"
God.log_file = "/var/www/myapp.com/shared/log/god.log"
God.watch do |w|
w.name = 'resque'
w.interval = 30.seconds
w.dir = File.expand_path(File.join(File.dirname(__FILE__),'..'))
w.start = "RAILS_ENV=production bundle exec rake resque:work QUEUE=*"
w.uid = "deploy"
w.gid = "deploy"
w.start_grace = 10.seconds
w.log = File.expand_path(File.join(File.dirname(__FILE__), '..','log','resque-worker.log'))
# restart if memory gets too high
w.transition(:up, :restart) do |on|
on.condition(:memory_usage) do |c|
c.above = 200.megabytes
c.times = 2
end
end
# determine the state on startup
w.transition(:init, { true => :up, false => :start }) do |on|
on.condition(:process_running) do |c|
c.running = true
end
end
# determine when process has finished starting
w.transition([:start, :restart], :up) do |on|
on.condition(:process_running) do |c|
c.running = true
c.interval = 5.seconds
end
# failsafe
on.condition(:tries) do |c|
c.times = 5
c.transition = :start
c.interval = 5.seconds
end
end
# start if process is not running
w.transition(:up, :start) do |on|
on.condition(:process_running) do |c|
c.running = false
end
end
end
In deploy.rb I have a reload task:
task :reload_god_config do
run "god stop resque"
run "god load #{File.join(deploy_to, 'current', 'config', 'resque.god')}"
run "god start resque"
end
The problem is whether I deploy, or run god (stop|start|restart|status) resque manually, I get the error message:
The server is not available (or you do not have permissions to access it)
I tried installing god to system gems and pointing to it in god-service:
GOD_BIN=/usr/local/bin/god
but god start rescue gives the same error.
However, I can start the service by doing:
sudo /etc/init.d/god-service start
So its probably a permissions issue, I think, probably related to the fact that the init.d service is owned by root and god is run from the bundle by the deploy user.
What's the best way around this issue?
You're running the god service as a different user (there's a good chance root).
Also check out: God not running: The server is not available (or you do not have permissions to access it)
First you check whether you have installed god in your machine using "god --version" command. If its available just try to run some god script with -D option. Example "god -c sample.god -D" it will give you some type of error messages in the standard output in your console where is the exact issue. I was also getting same error when i try to run the commmand without "-D" option. Then when i tried with "-D" mode it was told some folder write permission issue i could able to find it and fix it.
Ok this is an issue with your config files, check them all of them + the includes somewhere it fails throwing you this error. I checked mine and fixes some errors afterwards it worked perfectly!
I'm using redmine as a ticket manager, and I'd like to configure it to be run automatically when windows starts up.
How can I configure it to be run as a service?
--
Just asked the question to document it, I hope somebody may find it useful...
1. using webrick:
ref: http://www.redmine.org/boards/1/topics/4123
Download and install the Windows NT Resource Kit from
http://www.microsoft.com/downloads/details.aspx?familyid=9d467a69-57ff-4ae7-96ee-b18c4790cffd&displaylang=en
Create the service by running this command:
path\INSTSRV.EXE your_service_name path\SRVANY.EXE
in my case path is:
"C:\Program Files\Windows NT Resource Kit\INSTSRV.EXE" redmine_webrick "C:\Program Files\Windows NT Resource Kit\SRVANY.EXE"
could be also C:\Program Files\Windows Resource Kits\Tools\.
Run regedit (Start -> Run -> regedit)
Add the following registry key if it's not already there:
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\your_service_name
Right click on this registry key and select New -> Key. Name it Parameters.
Add two values to the Parameters key. Right click on the parameters key, New -> String Value. Name it Application. Now create another one named AppParameters. Give them the following values:
Application: PathToRuby.exe, eg. C:\ruby\bin\Ruby.exe
AppParameters: C:\RUBYAPP\script\server -e production, where RUBYAPP is the directory that contains the redmine website.
Example: C:\redmine\script\server -p 2000 -e production (-p indicates the port webrick will be listening to, and -e the environment used)
Now you can go to Administrative Tools -> Services. There you can start your service (the one with name your_service_name) and test whether or not it is working properly. It should be noted that the service will be marked as started prior to WEBrick finishing its boot procedure. You should give it 1min or so before trying to hit the service to verify that it is working correctly.
2. using mongrel:
ref: http://mongrel.rubyforge.org/wiki
ref: http://mongrel.rubyforge.org/wiki/Win32
first install mongrel and mongrel_service gem
gem install mongrel
gem install mongrel_service
then create the service
mongrel_rails service::install -N redmine_mongrel -c c:\redmine -p 3000 -e production
3. using thin:
References:
http://code.macournoyer.com/thin/
http://www.astarbe.com/es/trucos/windows/srvany_convierte_una_aplicacion_en_servicio
Instructions:
First install thin (you'll need to install rack gem, if not already
installed)
gem install rack
gem install thin
Follow the same steps indicated for webrick, but add another value named "AppDirectory". This is needed in order to avoid using c:\ruby\bin\thin.bat If I just pointed to the bat file, I couldn't stop the service.
In HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\redmine_thin\Parameters add the following keys:
Application: c:\ruby\bin\ruby.exe
AppDirectory: c:\redmine
AppParameters: c:\ruby\bin\thin start -p 4000 -e production
------------------------------------------------------------------------------------------
You can control any of your service with the following commands:
net start redmine_xxx
net stop redmine_xxx
sc config redmine_xxx start= auto
sc config redmine_xxx start= auto dependency= MySql
sc delete redmine_xxx
For Rails 3.0.x applications (tested on 3.0.10 & Windows 7)
demo_daemon_ctl.rb
############################################################################
# demo_daemon_ctl.rb
#
# This is a command line script for installing and/or running a small
# Ruby program as a service. The service will simply write a small bit
# of text to a file every 20 seconds. It will also write some text to the
# file during the initialization (service_init) step.
#
# It should take about 10 seconds to start, which is intentional - it's a test
# of the service_init hook, so don't be surprised if you see "one moment,
# start pending" about 10 times on the command line.
#
# The file in question is C:\test.log. Feel free to delete it when finished.
#
# To run the service, you must install it first.
#
# Usage: ruby demo_daemon_ctl.rb <option>
#
# Note that you *must* pass this program an option
#
# Options:
# install - Installs the service. The service name is "DemoSvc"
# and the display name is "Demo".
# start - Starts the service. Make sure you stop it at some point or
# you will eventually fill up your filesystem!.
# stop - Stops the service.
# pause - Pauses the service.
# resume - Resumes the service.
# uninstall - Uninstalls the service.
# delete - Same as uninstall.
#
# You can also used the Windows Services GUI to start and stop the service.
#
# To get to the Windows Services GUI just follow:
# Start -> Control Panel -> Administrative Tools -> Services
############################################################################
require 'win32/service'
require 'rbconfig'
include Win32
include Config
# Make sure you're using the version you think you're using.
puts 'VERSION: ' + Service::VERSION
SERVICE_NAME = 'DemoSvc'
SERVICE_DISPLAYNAME = 'Demo'
# Quote the full path to deal with possible spaces in the path name.
ruby = File.join(CONFIG['bindir'], 'ruby').tr('/', '\\')
path = ' "' + File.dirname(File.expand_path($0)).tr('/', '\\')
path += '\demo_daemon.rb"'
cmd = ruby + path
# You must provide at least one argument.
raise ArgumentError, 'No argument provided' unless ARGV[0]
case ARGV[0].downcase
when 'install'
Service.new(
:service_name => SERVICE_NAME,
:display_name => SERVICE_DISPLAYNAME,
:description => 'Sample Ruby service',
:binary_path_name => cmd
)
puts 'Service ' + SERVICE_NAME + ' installed'
when 'start'
if Service.status(SERVICE_NAME).current_state != 'running'
Service.start(SERVICE_NAME, nil, 'hello', 'world')
while Service.status(SERVICE_NAME).current_state != 'running'
puts 'One moment...' + Service.status(SERVICE_NAME).current_state
sleep 1
end
puts 'Service ' + SERVICE_NAME + ' started'
else
puts 'Already running'
end
when 'stop'
if Service.status(SERVICE_NAME).current_state != 'stopped'
Service.stop(SERVICE_NAME)
while Service.status(SERVICE_NAME).current_state != 'stopped'
puts 'One moment...' + Service.status(SERVICE_NAME).current_state
sleep 1
end
puts 'Service ' + SERVICE_NAME + ' stopped'
else
puts 'Already stopped'
end
when 'uninstall', 'delete'
if Service.status(SERVICE_NAME).current_state != 'stopped'
Service.stop(SERVICE_NAME)
end
while Service.status(SERVICE_NAME).current_state != 'stopped'
puts 'One moment...' + Service.status(SERVICE_NAME).current_state
sleep 1
end
Service.delete(SERVICE_NAME)
puts 'Service ' + SERVICE_NAME + ' deleted'
when 'pause'
if Service.status(SERVICE_NAME).current_state != 'paused'
Service.pause(SERVICE_NAME)
while Service.status(SERVICE_NAME).current_state != 'paused'
puts 'One moment...' + Service.status(SERVICE_NAME).current_state
sleep 1
end
puts 'Service ' + SERVICE_NAME + ' paused'
else
puts 'Already paused'
end
when 'resume'
if Service.status(SERVICE_NAME).current_state != 'running'
Service.resume(SERVICE_NAME)
while Service.status(SERVICE_NAME).current_state != 'running'
puts 'One moment...' + Service.status(SERVICE_NAME).current_state
sleep 1
end
puts 'Service ' + SERVICE_NAME + ' resumed'
else
puts 'Already running'
end
else
raise ArgumentError, 'unknown option: ' + ARGV[0]
end
demo_daemon.rb
APP_ROOT_CUSTOM = 'your app root dir'
LOG_FILE = APP_ROOT_CUSTOM + 'log/win32_daemon_test.log'
APP_PATH = File.expand_path( APP_ROOT_CUSTOM + 'config/application', APP_ROOT_CUSTOM + 'script/rails')
begin
require 'rubygems'
require 'win32/daemon'
include Win32
require File.expand_path( APP_ROOT_CUSTOM + 'config/boot', APP_ROOT_CUSTOM + 'script/rails')
require 'rails/commands/server'
module ::Rails
class Server
def default_options
super.merge({
:Port => 3000,
:environment => (ENV['RAILS_ENV'] || "development").dup,
:daemonize => false,
:debugger => false,
:pid => File.expand_path( APP_ROOT_CUSTOM + "tmp/pids/server.pid" ),
:config => File.expand_path( APP_ROOT_CUSTOM + "config.ru" )
})
end
end
end
class DemoDaemon < Daemon
# This method fires off before the +service_main+ mainloop is entered.
# Any pre-setup code you need to run before your service's mainloop
# starts should be put here. Otherwise the service might fail with a
# timeout error when you try to start it.
#
def service_init
end
# This is the daemon's mainloop. In other words, whatever runs here
# is the code that runs while your service is running. Note that the
# loop is not implicit.
#
# You must setup a loop as I've done here with the 'while running?'
# code, or setup your own loop. Otherwise your service will exit and
# won't be especially useful.
#
# In this particular case, I've setup a loop to append a short message
# and timestamp to a file on your C: drive every 20 seconds. Be sure
# to stop the service when you're done!
#
def service_main(*args)
Rails::Server.new.tap { |server|
require APP_PATH
Dir.chdir( APP_ROOT_CUSTOM )
server.start
}
msg = 'application started at: ' + Time.now.to_s
File.open(LOG_FILE, 'a'){ |f|
f.puts msg
f.puts "Args: " + args.join(',')
}
# While we're in here the daemon is running.
while running?
if state == RUNNING
sleep 20
msg = 'Service is running as of: ' + Time.now.to_s
File.open(LOG_FILE, 'a'){ |f| f.puts msg }
else # PAUSED or IDLE
sleep 0.5
end
end
# We've left the loop, the daemon is about to exit.
File.open(LOG_FILE, 'a'){ |f| f.puts "STATE: #{state}" }
msg = 'service_main left at: ' + Time.now.to_s
File.open(LOG_FILE, 'a'){ |f| f.puts msg }
end
# This event triggers when the service receives a signal to stop. I've
# added an explicit "exit!" here to ensure that the Ruby interpreter exits
# properly. I use 'exit!' instead of 'exit' because otherwise Ruby will
# raise a SystemExitError, which I don't want.
#
def service_stop
msg = 'Received stop signal at: ' + Time.now.to_s
File.open(LOG_FILE, 'a'){ |f| f.puts msg }
exit!
end
# This event triggers when the service receives a signal to pause.
#
def service_pause
msg = 'Received pause signal at: ' + Time.now.to_s
File.open(LOG_FILE, 'a'){ |f| f.puts msg }
end
# This event triggers when the service receives a signal to resume
# from a paused state.
#
def service_resume
msg = 'Received resume signal at: ' + Time.now.to_s
File.open(LOG_FILE, 'a'){ |f| f.puts msg }
end
end
# Create an instance of the Daemon and put it into a loop. I borrowed the
# method name 'mainloop' from Tk, btw.
#
DemoDaemon.mainloop
rescue Exception => err
File.open(LOG_FILE, 'a'){ |fh| fh.puts 'Daemon failure: ' + err }
raise
end
place both files in same dir and run
ruby demo_daemon_ctl.rb install
use http://www.firedaemon.com/
Hope this will help to anyone. I defined the windows service that starts the redmine with the thin server.
Use http://nssm.cc/usage for windows service creation. Set the path to ruby.exe, your redmine's working directory and define the starting parameters:
Path: C:\RailsInstaller\Ruby2.3.3\bin\ruby.exe
Startup directory: C:\Program Files\redmine-3.4.6
Arguments: C:\RailsInstaller\Ruby2.3.3\bin\thin start -e production -p 3000
Some time ago, I tried to install Redmine on Windows as well. But I wasn't able to get it to work, probably because of lack of Rails knowledge.
Then I discovered Bitnami Redmine Stack. They have a Windows installer, which installs Redmine with all needed dependencies, and it just works.
For Rails 4.0.x applications as suggested by Bohdan,
we have to replace
CONFIG['bindir'] with RbConfig::CONFIG['bindir']
Remmber to:
gem install win32-service
gem install win32-service
drop below Ruby code in a service.rb file and update REDMINE_DIR path to fit your Redmine installation
create the service, for example with sc create redmine binPath= "C:\Ruby23-x64\bin\rubyw -C E:\www\redmine-3.3.2\ service.rb" where E:\www\redmine-3.3.2\ is the path of the directory where the service.rb file is located and C:\Ruby23-x64\bin\rubyw your Ruby installation path
begin
require 'win32/daemon'
include Win32
class RedmineService < Daemon
def service_init
File.open(LOG_FILE, 'a'){ |f| f.puts "Initializing service #{Time.now}" }
##server_pid = Process.spawn 'ruby script/rails s -e production', :chdir => REDMINE_DIR, :err => [LOG_FILE, 'a']
# use full path
#server_pid = Process.spawn 'C:\Ruby23-x64\bin\ruby E:\www\redmine-3.3.2\bin\rails s -e production -p 3000', :chdir => REDMINE_DIR, :err => [LOG_FILE, 'a']
end
def service_main
File.open(LOG_FILE, 'a'){ |f| f.puts "Service is running #{Time.now} with pid #{#server_pid}" }
while running?
sleep 10
end
end
def service_stop
File.open(LOG_FILE, 'a'){ |f| f.puts "Stopping server thread #{Time.now}" }
system "taskkill /PID #{#server_pid} /T /F"
Process.waitall
File.open(LOG_FILE, 'a'){ |f| f.puts "Service stopped #{Time.now}" }
exit!
end
end
RedmineService.mainloop
rescue Exception => e
File.open(LOG_FILE,'a+'){ |f| f.puts " ***Daemon failure #{Time.now} exception=#{e.inspect}\n#{e.backtrace.join($/)}" }
raise
end
Note that Process.spawn in the service.rb use the full path.