Python and JS development from the iPad with AWS EC2

Don’t ask me what it is about turning an iPad into a development environment, but it comes back to haunt me every couple of months. And this time, it seems like we’ve actually come one step closer.

While I don’t mind VSCode, for most of my development these days I stick to vim. I have not bothered with more heavyweight IDEs, mostly because I found no noticeable improvement in productivity, at least for Python and JS. Sticking with the shell and not having to bother with a UI makes the whole thing a lot simpler already.

Here’s our minimal setup:

  • Ipad 6 w/ USB adapter
  • External keyboard (+ mouse)
  • AWS EC2 t3.micro machine running ubuntu server
  • Blink
  • AWS Console App

The AWS Console App on the iPad is rather minimal, so don’t expect to be able to set up an EC2 machine from the app. But it is able to turn an EC2 machine on/off, it even supports SAML authentication. So, good enough :)

Blink is used to connect to our EC2 machine via Mosh, which has a couple of advantages over traditional SSH on mobile devices. It’s an upgrade, but if you want to stick to traditional SSH, that’s fine, too.

Alright, so after having created your EC2 machine and having transferred the SSH key to your iPad, let’s hop onto an SSH session. Obviously, the first steps are to run a quick update of your OS:

sudo apt update
sudo apt upgrade -y

From that point onwards, let’s dive into what we need:

sudo apt install git neovim awscli direnv curl editorconfig git jq nmap curl tmux tmate wget pv make ruby zsh ruby python3 python-is-python3 python3-pip mosh

With these tools installed, let’s add version management for Python, Rust and Node.js

For Node.js, we’ll be using n and install the latest version of Node.js:

curl -L https://raw.githubusercontent.com/tj/n/master/bin/n -o /usr/local/bin/
chmod +x usr/local/bin/n
n latest
npm install -g standard npm-check-updates yarn

For Python, we will be using Pipenv and Pyenv:

sudo -H pip3 install -U pipenv
curl https://pyenv.run | bash

Please note that this is not the recommended way to install pipenv, but it’s my preferred method to install it.

Thirdly, let’s install Rust:

https://sh.rustup.rs -sSf | sh

rustup install nightly
rustup default nightly
rustup update
rustup component add rls-preview rust-analysis rust-src
rustup show

Alright, now that our SDKs are out of the way, let’s set up Neovim:

pip3 install pynvim
mkdir -p .config/nvim
mkdir -p ~/.nvim/undo
mkdir -p ~/.nvim/swp
mkdir -p ~/.nvim/backup
curl https://raw.githubusercontent.com/felixhammerl/vim/master/init.vim -o ~/.config/nvim/init.vim
curl https://raw.githubusercontent.com/felixhammerl/vim/master/coc-settings.json -o ~/.config/nvim/coc-settings.json

I will leave it up to the reader’s preference whether you wish to symlink nvim to /usr/local/bin/vi and /usr/local/bin/vim to non-destructively replace the default vim.

Given that we’ll be working remotely, we will be using tmux. Let’s set it up in a way that takes out some of the rough edges:

curl https://raw.githubusercontent.com/felixhammerl/deps/master/.tmux.conf -o ~/.tmux.conf

And of course, we need a good CLI, in case this will be zsh.

curl https://raw.githubusercontent.com/felixhammerl/deps/master/.zshrc -o ~/.zshrc

You can switch from the default bash to zsh via chsh -s $(which zsh), but there is a caveat where this might fail. Please see this stackoverflow post for help how to solve this issue.

If you want a more powerful CTRL-R search (and a couple of other boons), let’s set up fzf:

git clone --depth 1 https://github.com/junegunn/fzf.git ~/.fzf
~/.fzf/install

The last thing before we sign off is to take a couple of rough edges off of git via scm-breeze:

- git clone git://github.com/scmbreeze/scm_breeze.git ~/.scm_breeze
~/.scm_breeze/install.sh
curl https://raw.githubusercontent.com/felixhammerl/deps/master/.gitconfig -o ~/.gitconfig

At this point, we’re mostly done. You have a fully functioning edevelopment environment. If you need ssh connectivity, you will need to make a choice whether you wish to leverage SSH client-forwarding, or rather have a key pair on the machine. For the latter, just run ssh-keygen to create a key pair.

Those of you who have used Cloud9 will be familiar with a super helpful feature to keep your AWS bill low. Cloud9 has an auto-shutdown feature that, if your machine sits idle for half an hour, will initiate a shutdown. AWS has never bothered to make this generally available for EC2, but there is a simple workaround in a couple lines of shell code.

When it comes to doing stuff on AWS, you now have two options:

  • Assign an IAM role to the development machine
  • Use temporary STS credentials, e.g. via SAML.

In my case, I use saml2aws and assume-role to assume a role configured in your AWS configuration (~/.aws/config) like so: saml2aws login && eval $(assume-role <YOUR AWS CONFIGURATION PROFILE NAME HERE>)

cd download
CURRENT_VERSION=2.27.1
wget https://github.com/Versent/saml2aws/releases/download/v${CURRENT_VERSION}/saml2aws_${CURRENT_VERSION}_linux_amd64.tar.gz
tar -xzvf saml2aws_${CURRENT_VERSION}_linux_amd64.tar.gz -C ~/.local/bin
chmod u+x ~/.local/bin/saml2aws
saml2aws configure

curl -O https://dl.google.com/go/go1.15.7.linux-amd64.tar.gz
tar xzfv go1.15.7.linux-amd64.tar.gz
mv go /usr/local/lib
ls /usr/local/lib/go
go get -u github.com/remind101/assume-role

Before we close here, did you know that you can debug Python from the CLI with pudb and pytest-pudb?