SSH from Heroku into remote server with Mysql Db

浪子不回头ぞ 提交于 2019-12-24 23:00:12

问题


I'm looking at an Rails app that would require establishing a remote SSH session (SSH Tunnel?) from Heroku to a remote Mysql database as part of an background, ActiveRecord session. The goal would be to migrate data at different times via this channel into the app. Connecting to the remote mysql database over the web would not be an option.

Few questions:

  1. Does Heroku permit SSHing off their Dyno?
  2. What would be the downsides of doing so?
  3. Would I have to be concerned about SSH session persistence (job could take 1 hour)?
  4. Lastly, how can I configure Rails and Heroku to enable remote connections for a database.yml mysql endpoint?

回答1:


Well, I'm now able to answer my own question after digging around for a few days. In short, yes.

class LegacyAccount < ActiveRecord::Base

 self.table_name = "account"

 def self.test_connection

      # net-ssh-gateway gem
      gateway = Net::SSH::Gateway.new("ip_address","ssh_user_name",
          password: "password",
          port: "port if different from 22",
          verbose: :debug
          )

      port = gateway.open('127.0.0.1', 3306, 3307)

      establish_connection :legacy_production

      result = LegacyAccount.first
      puts "Record: #{result.to_yaml}"

      gateway.close(port)
      gateway.shutdown!

      result
  end

end

and in your database.yml:

legacy_production:
  adapter: "mysql2"
  host: "127.0.0.1"
  username: "root"
  password: "password"
  database: "legacydb"
  port: 3307
  secure_auth: false



回答2:


I tried @user1322092's approach and got into trouble when multiple clients tried to access the db, since each one would attempt to open a connection (all but the first would get an error).

I created a monstrous solution involving spawning an SSH process on the dyno and using that for all communications. Gory details are in https://stackoverflow.com/a/27361295/558639. Aside from being really kludgy, it incurs a delay every time a process starts up, whether or not you're accessing the remote database.

update

So here's a better approach that appears to work well: just trap (and ignore) Errno::EADDRINUSE errors. Here's the code:

require 'net/ssh/gateway'

class Mole

  TUNNEL_HOST = <redacted>
  TUNNEL_USER = <redacted>
  AWS_HOST = <redacted>
  TUNNEL_PORT_NUMBER = 3307

  attr_reader :tunnel_gateway, :tunnel_port

  # Call this to open an SSH tunnel from the current machine.  If the
  # the tunnel was already opened (e.g. by another process) , you'll
  # get a warning message
  def open_tunnel
    @tunnel_gateway = Net::SSH::Gateway.new(TUNNEL_HOST, TUNNEL_USER)
    begin
      @tunnel_port = @tunnel_gateway.open(AWS_HOST, 3306, TUNNEL_PORT_NUMBER)
    rescue Errno::EADDRINUSE => e
      $stderr.puts("Warning: #{e.class}: #{e.message}")
    end
  end

  # You won't normally call this, because the tunnel is a system wide
  # resource; you don't know when other processes want to release it.
  def close_tunnel
    r = @tunnel_gateway.close(@tunnel_port) if @tunnel_gateway
    @tunnel_gateway.shutdown!
    r
  end

end


来源:https://stackoverflow.com/questions/26457941/ssh-from-heroku-into-remote-server-with-mysql-db

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!