Dockerized Rails 7+Puma SSL fails with 'PR_END_OF_FILE_ERROR' - ruby-on-rails

I'm trying to dockerize a rails 7 app using the default puma server with ssl enabled using a self-signed cert. Launching the app natively works as expected.
When running as a container, I get a 'PR_END_OF_FILE_ERROR' error in Firefox. Testing with other browsers results in 'This site can'be reached. localhost unexepectedly closed the connection'.
docker run command: docker run --rm -it -p 3000:3000 my-app-image
Dockerfile CMD: CMD [ "rails", "s" ]
Troubleshooting steps:
Machine reboot
Update Docker
Map host port 443 to container port 3000
$RAILS_ENV both as development and production
Variations of rails command in docker file:
CMD [ "bundle", "exec", "rails", "s", "-b", "0.0.0.0" ]
CMD [ "rails", "s", "-b", "127.0.0.1" ]
CMD [ "rails", "s", "-u", "puma", "-b", "'ssl://127.0.0.1/?key=server.key&cert=server.crt&verify_mode=none'" ]
config/application.rb
...
# Enable SSL
config.force_ssl = true
...
config/puma.rb
...
environment ENV.fetch("RAILS_ENV") { "development" }
# SSL Configuration
localhost_key = 'server.key'
localhost_crt = 'server.crt'
ssl_bind 'localhost', 3000, {
key: localhost_key,
cert: localhost_crt,
verify_mode: 'none'
}
...
Since it works when run natively, I think the issue lies with either docker or puma, but I'm not sure what it could be or how to troubleshoot further.

The issue was binding the ssl port in the puma.rb config file to localhost, which isn't available outside of the running container.
Changing:
ssl_bind 'localhost', 3000, {
To:
ssl_bind '0.0.0.0', 3000, {
resolved the issue.

Related

Configure Apache and Passenger to use websocket

I'm trying to setup apache to use ruby on rails web socket with passenger. I know that Action Cable is not supported on Passenger + Apache, so I'm tryng to use the reverse proxy solution:
https://www.phusionpassenger.com/library/deploy/standalone/reverse_proxy.html
The main application should continue to use the Passenger Apache module while the websocket should use passenger standalone.
I enabled the reverse proxy and changed the vhost config.
<VirtualHost *:80>
...
PassengerRuby /home/rails/.rvm/gems/ruby-2.5.1/wrappers/ruby
<Location "/cable">
ProxyPass "ws://127.0.0.1:4000/cable"
ProxyPassReverse http://127.0.0.1:4000/
ProxyPreserveHost on
</Location>
...
</VirtualHost>
When I start the passenger from the command line
bundle exec passenger start --daemonize --address 127.0.0.1 --port 4000
it works fine, but when I create a service using systemd in Ubuntu 18.04.5 LTS
...
[Service]
Type=forking
WorkingDirectory=/mnt/xfeature/srv/www/f3.xxxx.xxx/current
Environment=RAILS_ENV=feature
User=rails
Group=www-data
UMask=0002
ExecStart=/home/rails/.rvm/bin/rvm-shell -c 'bundle exec passenger start --daemonize -e feature --address 127.0.0.1 --port 4000 --log-level 5'
ExecStop=/home/rails/.rvm/bin/rvm-shell -c 'bundle exec passenger stop --port 4000'
....
it fails usually with this error.
[ E 2021-05-13 09:52:13.3607 21447/Tz age/Cor/App/Implementation.cpp:221 ]: Could not spawn process for application /mnt/xfeature/srv/www/f3.xxx.xxx/releases/20210513094622: An operating system error occurred while preparing to start a preloader process: Cannot change the directory '/tmp/passenger.spawn.XXXXgMx55z/envdump' its UID to 1001 and GID to 1001: Operation not permitted (errno=1)
Error ID: 847da63a
Error details saved to: /tmp/passenger-error-5S5Syq.html
and the websocket connection cannot be established. I checked the /tmp permission and are OK.
Any suggestion?
We had some strange issues with Apache and Passenger recently. It turns out Apache automatically updated and changed the PrivateTmp setting to true, which caused a similar error message.
I'm not sure if that is what is causing your error, but you could check that to verify that PrivateTmp is set to false.
Our configuration is:
/etc/systemd/system/apache2.service.d/override.conf
override.conf Contents:
PrivateTmp=false
I'm not certain how that override.conf file is loaded. I assume there is a configuration somewhere looking for an override file and it is using it.

Puma server inside heroku container fails to connect to port

I have a docker container: (called Dockerfile.web, relevant parts)
ARG PORT=3000
ENV PORT=$PORT
EXPOSE $PORT
ENTRYPOINT ["docker-entrypoint.sh"]
CMD ["rails", "server"]
Puma: config/puma.rb
before_fork do
ActiveRecord::Base.connection_pool.disconnect! if defined? ActiveRecord
end
on_worker_boot do
ActiveRecord::Base.establish_connection if defined? ActiveRecord
end
preload_app!
So when I run heroku container:push web followed by heroku container:release web, the app deploys, but the puma server doesn't come up b/c the port cannot be connected to:
Booting Puma
Rails 5.2.2 application starting in development
Run `rails server -h` for more startup options
Puma starting in cluster mode...
* Version 3.12.0 (ruby 2.6.0-p0), codename: Llamas in Pajamas
* Min threads: 5, max threads: 5
* Environment: development
* Process workers: 1
* Preloading application
* Listening on tcp://localhost:41626
Use Ctrl-C to stop
- Worker 0 (pid: 28) booted, phase: 0
Error R10 (Boot timeout) -> Web process failed to bind to $PORT within 60 seconds of launch
Stopping process with SIGKILL
I'm following the official guide but I haven't added the sections:
rackup DefaultRackup
port ENV['PORT'] || 3000
environment ENV['RACK_ENV'] || 'development'
Where could my error be? Any ideas?
I'm not sure why you left this part out:
port ENV['PORT'] || 3000
You can't pick your own port. Use the $PORT that Heroku gives you.
For people arriving here, the solution was to invoke the puma server directly from the docker CMD so that all the settings in the config file are applied. The reason is that on heroku, stuff like port is added dynamically, so container images (which are built out earlier) will not have those images. Somehow using the $PORT values inside Dockerfile also did not help. The solution was to do
CMD ["bundle", "exec", "puma", "-C", "config/puma.rb"]
# or if you prefer the bash style
CMD bundle exec puma -C config/puma.rb

How do i run two rails projects on my machine simultaneously

I want to be able to run two rails servers on one machine via vagrant and virtual box. I have the first set up and when i run
rails s
it returns the following with the site accessibly in my browser at http://localhost:3000/
=> Booting Thin
=> Rails 3.2.22.2 application starting in development on http://0.0.0.0:3000
=> Call with -d to detach
=> Ctrl-C to shutdown server
installing dummy notifier
Thin web server (v1.7.0 codename Dunder Mifflin)
Maximum connections set to 1024
Listening on 0.0.0.0:3000, CTRL+C to stop
Heres the vagrantfile for this instance:
Vagrant.configure("2") do |config|
config.vm.box = "hashicorp/precise64"
config.vm.network "forwarded_port", guest: 3000, host: 3000
end
I now have the second project in a different folder on my local machine. I have navigated to it initiated my vagrant box, completed all the set up steps and ran rails s again. Here I get:
=> Booting Puma
=> Rails 4.2.3 application starting in development on http://localhost:3000
=> Run `rails server -h` for more startup options
=> Ctrl-C to shutdown server
Puma 2.12.2 starting...
* Min threads: 0, max threads: 16
* Environment: development
* Listening on tcp://localhost:3000
Heres the vagrantfile for this instance:
Vagrant.configure("2") do |config|
config.vm.box = "hashicorp/precise64"
config.vm.network "forwarded_port", guest: 80, host: 8080
end
I have been trying to investigate the the fact that it says "listening on tcp://localhost:3000" but if anyone can give me some pointers as to how exactly I can run the two projects from the same machine it would be much appreciated.
You have to run them on different ports. rails s takes a port argument.
rails s -p 3001
will give you a server at port 3001 and so on.
Perhaps try running the second server at port 8080, not 3001, since your second vagrant machine is set up like :
config.vm.network "forwarded_port", guest: 80, host: 8080
I ended up running
puma -b tcp://0.0.0.0:3001
and my vagrantfile had the following:
config.vm.network "forwarded_port", guest: 3001, host: 3001
Thanks for the pointers though as they helped me to better understand the problem and find the solution.

rails 2.3 server running inside vagrant environment not accessible in host machine mac os x browsers

in vagrant I am using:
box 'prorail/centos-5.8-x86_64'
in vagrant i am running rails 2.3 server like:
[vagrant#localhost myapp]$ script/server
=> Booting Mongrel
=> Rails 2.3.5 application starting on http://0.0.0.0:3000
=> Call with -d to detach
=> Ctrl-C to shutdown server
in my hosts file i have added this line at the bottom
192.168.60.110 www.example.dev example.dev dev.example.com
in Vagrantfile i have added this ip:
config.vm.network :private_network, ip: "192.168.60.110"
in all browsers i have tried following urls
dev.example.com:3000/
dev.example.com
in browser nothing happens . i hav tried all browsers
chrome
tor
firefox
safari
i have tried several other commands to run rails 2.3 server inside vagrant environment but still nothing happens
script/server -b 0.0.0.0
script/server -b 0.0.0.0 -p 3000
script/server -p 3000
log into vagrant environment:
vagrant ssh
than type or copy/paste the following command:
sudo /sbin/iptables -I INPUT -p tcp --dport 3000 -j ACCEPT
this command will allow port to be accessible by host machine. than type:
exit
login again into vagrant and goto your project root. than run:
script/server
now you can access it in browser
www.example.dev

Rails 4.2 Server port forwarding on Vagrant does not work

I have a Vagrant VM with Rails installed with a sample app. The VM is configured to forward the port 3000 (of Rails Webrick server) to my host 3000 port.
config.vm.network "forwarded_port", guest: 3000, host: 3000
Everything is configured as seen in a lot of examples.
But, when I try to access http://localhost:3000 nothing happens. I've also tried to forward to other random ports like 8081, 25600, without success. Doing a curl request also does not get anything (just a Connection reset by the peer message), and a curl request inside VM works perfectly (as expected).
Both my PC and my VM runs Ubuntu 12.04. I'm using Ruby 2.2.0 and Rails 4.2.0.
An important point is that Apache works normally. I forwarded the port 80 to port 8080 and everything works. It seems that the problem is just with the Rails server, even if when I use other ports (rails server -p 4000, for example)
Rails 4.2 now binds to 127.0.0.1 by default and not 0.0.0.0.
Start the server using bin/rails server -b 0.0.0.0 and that should sort it.
To run on a specific port :
rails server -b 0.0.0.0 -p 8520
Use:
rails s -b 0.0.0.0
or
Add to config/boot.rb:
require 'rails/commands/server'
module Rails
class Server
new_defaults = Module.new do
def default_options
default_host = Rails.env == 'development' ? '0.0.0.0' : '127.0.0.1'
super.merge( Host: default_host )
end
end
# Note: Module#prepend requires Ruby 2.0 or later
prepend new_defaults
end
end
and work with rails s
You can use an alias, on Ubuntu put it in ~/.bash_aliasesI use:alias rs="rails server -b 0.0.0.0"You have to reload the terminal before you can use it
Really nice explanation found here: Rails 4.2.0.beta2 - Can't connect to LocalHost?
I had exactly the same problem, with the exception that my PC is Mac machine. I've used this vagrantfile to get it working (with virtualbox 4.3.36)
# -*- mode: ruby -*-
# vi: set ft=ruby :
VAGRANTFILE_API_VERSION = "2"
Vagrant.configure(VAGRANTFILE_API_VERSION) do |config|
# Use Ubuntu 14.04 Trusty Tahr 64-bit as our operating system
config.vm.box = "ubuntu/trusty64"
# Configurate the virtual machine to use 2GB of RAM
config.vm.provider :virtualbox do |vb|
vb.customize ["modifyvm", :id, "--memory", "2048"]
end
config.vm.provision "shell", inline: <<-SHELL
## Install necessary dependencies
sudo apt-get --assume-yes install libsqlite3-dev libcurl4-openssl-dev git
## Install GPG keys and download rvm, ruby and rails
curl -sSL https://rvm.io/mpapis.asc | gpg --import -
curl -L https://get.rvm.io | bash -s stable --ruby
curl -L https://get.rvm.io | bash -s stable --rails
echo "[[ ls \"$HOME/.rvm/scripts/rvm\" ]] && . \"$HOME/.rvm/scripts/rvm\"" >> ~/.profile
## Adding vagrant user to the group that can access rvm
usermod -G rvm vagrant
SHELL
# Forward the Rails server default port to the host
config.vm.network :forwarded_port, guest: 3000, host: 3000
end
after having the VM up and running, I would run bundle install in my project repo and then rails server -b 0.0.0.0.
As pointed out in linked answer above:
127.0.0.1:3000 will only allow connections from that address on port 3000, whereas 0.0.0.0:3000 will allow connections from any address at
port 3000.
Since Rails 4.2 only accepts connections from localhost by default,
you can only access the server from localhost (eg. inside the VM);
connections from another machine (eg. VM's host) will not work.

Resources