I’ve been a localtunnel user for quite some time now and I really love the fact that its a free service, quick to install and easy to expose your development app to the world. There are quite a few worthy alternatives now with showoff.io and pagekite that pretty much do the same thing.
But at times it gets annoying (especially when in the middle of other work) that I’m unable to access localtunnel because its down or I outran the free usage limit for Pagekite.
I generally end up using localtunnel when I have to wait for an IPN from Paypal or Authorize.net (relay response) while working on my development environment. So here is a quick way to roll out a basic version of the service for your own needs.
Before we move to the “how to” here is a quick intro to ssh tunneling
Now, I assume that you have a staging server (or some server you have ssh access to).
The following terminal command does pretty much the same thing we do with the Ruby code that follows:
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
ssh -R0.0.0.0:9999:localhost:3000 sid@abc.example.com |
The -R indicates that you’ll be forwarding your local app running on port 3000 to the remote port 9999 on the remote host abc.example.com so that everyone can access it. Now your application running on localhost:3000 is accessible at abc.example.com:9999
We do the same thing now using the ruby net-ssh library. The following code snippet is customised to my defaults but its simple enough to change those settings.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#! /usr/bin/env ruby | |
require 'rubygems' | |
require 'net/ssh' | |
require "net/ssh/gateway" | |
# Terminal equivalent | |
# #ssh -R0.0.0.0:9999:localhost:3000 sid@abc.idyllic-software.com | |
puts "Enter the remote server name you wish to forward your local port to: (staging.example.com)" | |
remote_host = gets.chomp | |
puts "Enter the remote port you wish your local app to be available on – on the remote server (ex: 9999)" | |
remote_port = gets.chomp | |
puts "Enter remote server user to ssh with" | |
remote_user = gets.chomp | |
puts "Enter local port to forward" | |
local_port = gets.chomp | |
remote_host = "abc.idyllic-software.com" if remote_host.empty? || remote_host.nil? | |
remote_port = 9999 if remote_port.empty? || remote_port.nil? | |
remote_user = "sid" if remote_user.empty? || remote_user.nil? | |
local_port = 3000 if local_port.empty? || local_port.nil? | |
gateway = Net::SSH::Gateway.new(remote_host, remote_user) | |
puts "Forwarding 127.0.0.1:#{local_port} to #{remote_host}:#{remote_port}" | |
#remote_host = "abc.idyllic-software.com" | |
Net::SSH.start(remote_host, remote_user) do |ssh| | |
puts "Connecting…" | |
#puts ssh.inspect | |
ssh.logger.sev_threshold = Logger::Severity::DEBUG | |
#remote forward from remote 127.0.0.1:3000 to 0.0.0.0:9999 established | |
ssh.forward.remote(local_port, '127.0.0.1', remote_port, remote_host) | |
ssh.loop { true } | |
end |
Hope this helps