Recently we worked for a client that needed to block external IPs. We had a lot of back-and-forth asking to whitelist the various IPs we might be connecting from, so to make that easier I kicked off an experiment I’d been thinking about for a while.
Working hypothesis
Using a remote machine, located on a hosted platform that one can access from anywhere, a developer can develop with Ruby on Rails (and other languages) from anywhere with an Internet connection and SSH.
Platform
You can use any Linux platform, hosted or otherwise, that allows you full root access (ideally) to accomplish this (even a RaspberryPi!). I chose Digital Ocean because of the low cost of entry for a single droplet with Ubuntu 14.04 pre-installed.
Creating a droplet
Log in to your Digital Ocean account and select “Create Droplet”.
Set the droplet hostname to any name you’d like.
Choose the size of your droplet. For this experiment I chose the $10/mo option, but this can be accomplished on anything from their $5/mo option and up.
Choose a region for your droplet. It is usually best to select the location closest to where you are working most of the time to avoid any latency problems.
Note: none of the “Available Settings” (shown above) are needed for this experiment.
Choose an SSH key to install on to your droplet. This is the most secure way to access your droplet and is highly recommended over password only protection. See their documentation for more details.
Once you have reviewed all of your choices, click “Create Droplet”.
Your droplet will now be configured.
Once your droplet has been created you will be brought to the droplet details page. Please take note of your
IP ADDRESS
.
Initial user setup
- First, you will need to connect to your droplet via SSH. For now, just open
up your terminal app and type:
ssh root@<IP-ADDRESS-OF-DROPLET>
(substituting theIP-ADDRESS
that you noted before).
Note: you will need to respond with ‘yes’ to allow your droplet’s IP address to be added to the list of known hosts on your machine.
- Before doing any kind of configuration on the droplet, let’s first create a
user that you can use other than
root
. Type inadduser USER_NAME
(substitutingUSER_NAME
with the username of your choice).
Note: you will also need to provide a new password for this user, and any details that you wish to add.
Now that we have created a new user, let’s make sure that we lock down
sshd
from allowing that user to connect with a password and continue to use the same SSH key to connect. First we will copy the key from the root user to the newly created user. Type:mkdir /home/USER_NAME/.ssh && cat ~/.ssh/authorized_keys >> /home/USER_NAME/.ssh/authorized_keys
(remember to substituteUSER_NAME
with the username that you chose earlier).Next, we need to
chown
that directory that we just created so that theUSER_NAME
can write to it later. Execute this command:chown -R USER_NAME:USER_NAME /home/USER_NAME/.ssh
Since we now have the SSH key authorized for the new user, let’s lock down
sshd
from allowing any user to authenticate with a password. Open/etc/ssh/sshd_config
with your editor of choice and change#PasswordAuthentication yes
toPasswordAuthentication no
.
Note: once you have saved this change, execute restart ssh
to reload the
configuration.
Now we can add this new user to the
sudoers
file. This will allow this user to execute thesudo
command. Replicate the lineroot ALL=(ALL:ALL) ALL
, replacing root with your new username, and save the file. (If you’re in vim, you’ll need to save with:w!
since the file is readonly.)Log out of your SSH session and log in again, but this time use your new username:
ssh USER_NAME@<IP-ADDRESS-OF-DROPLET>
Initial development environment setup
There are a few ways that you can go about setting up your environment. I created (with the help of an older thoughtbot laptop script) a small script to setup my environment. We are going to use it here by typing:
bash <(wget -qO- https://raw.githubusercontent.com/kenyonj/init/master/init.sh)
2>&1 | tee ~/init.log
Note: you will need to enter your password to install aptitude
as well as
changing your default shell to zsh
.
This process will take about 10-15 minutes depending on the speed of the machine you are executing it on. It will need to be customized for other environments other than Ubuntu 14.04 on DigitalOcean, but works great there.
Personalizing your environment
Once our environment contains all of our Ruby on Rails development tools, we can start customizing it.
For this, I like to start out with thoughtbot/dotfiles.
- First, make sure that you are starting in your home folder by typing:
cd
.
(Note: before completing the next step you will need to add your new user’s SSH key to your GitHub account
From your home folder, clone the thoughtbot dotfiles repo by executing this command:
git clone git@github.com:thoughtbot/dotfiles.git
Next,
cd
into thedotfiles
directory and executeenv RCRC=$HOME/dotfiles/rcrc rcup
You can customize and override further using the
.local
convention explained here.
Finishing up
Now that you have completed the above steps you should have a fully working environment on a remote server that you can access anywhere with an Internet connection and a terminal.
Make sure to close out your current session and reconnect so that all of your
new dotfiles are sourced and you are using zsh
as your default shell.
Wins
- I am not reliant on my laptop’s state (I can reboot or update my laptop without worrying about my development environment).
- I am not tied to a single machine or its capabilities (I see this working very well from a chromebook).
- I can share my rails development server very easily with fellow devs
(
http://<IP-ADDRESS-OF-DROPLET>:3000
). - It has taken me deeper into working in a Linux environment which is relatively new for me.
Losses
- There is a little bit of lag compared to a local terminal session. It is really nothing serious, and you will notice what I am referring to if you follow the above guide, or work in an SSH session often.
- I have yet to enable clipboard sharing from my machine to the remote session through SSH.
- You always need an Internet connection to have this work.
Overall thoughts
This is something that I am going to continue to experiment with over the next month or so. Some of the negative issues I have come across have not been severe enough for me to halt the experiment which I feel is very promising.
Here is a screen shot of my dev environment running completely inside Chrome (using the Secure Shell chrome extension):