Setting up a fully remote development environment: a tutorial

This tutorial will guide you through a solution of creating a remote development environment. This is particularly useful for remote working (e.g. with a remote PC using a laptop), cloud computing (within a virtual container), and many other scenarios.

Prerequisites

Knowledge of these great tools would be very helpful:

  • SSH command lines. It’s the backbone of everything.
  • A terminal multiplexer, Tmux, GNU Screen, etc. They are useful for controling remote sessions.
  • A text editor, or an IDE with remote support. For example, VS Code (with Remote SSH extension), Emacs (Tramp mode), or even Jupyter Lab.
  • The remote machine is supposed to be running a Debian-based Linux distro (e.g. Ubuntu).
  • The local machine, usually a laptop, can run any mainstream operating system.

1. Install and enable SSH on remote server

First of all, you need to verify if an SSH server is running on the remote machine. To do this, open a terminal on the remote machine and type the following command:

1
sudo systemctl status ssh

The output should tell if the SSH service is running. If this is the case, jump to the next step of this tutorial. Otherwise you need to install the openssh-server package:

1
2
sudo apt update
sudo apt install openssh-server

Once the installation is complete, the SSH service should start automatically.

Ubuntu ships with a firewall configuration tool called UFW. If the firewall is enabled on your system, make sure to open the SSH port:

1
sudo ufw allow ssh

To disable the SSH server on your Ubuntu system, type:

1
sudo systemctl disable --now ssh

To re-enable it, you can use:

1
sudo systemctl enable --now ssh

2. Configure router with port forwarding

You can probabliy skip this step if you work in a company as IT support should have done the job. But if you wish to connect to a home machine over the Internet, you will need to configure the router.

Each router has a different way to setup port forwarding, then you should consult the router manuals to learn how to do it. In general there are two things that need to be done:

  1. Enter the port number where requests will be made (Default SSH port is 22);
  2. Enter the private IP address of the server PC. To find the private IP address, type the command:
    1
    ip a
    which will print something like this:

    in which the private IP is highlighted in red.

Once you have configured the router, you can log in to the PC using:

1
ssh <username>@<public_ip>

in which the <public_ip> of the PC you are SSH-ing to can be found from https://api.ipify.org.

2.bis. Security issues

Running an SSH server on the Internet will put your remote machine at risk. If the remote server is a home PC, then you should apply some measurements to protect the server against bots and hackers:

  • Change the config file in /etc/ssh/sshd_config, for example:
    1
    2
    3
    4
    # Disable remote root login
    PermitRootLogin no
    # Disable password login (use SSH key-based authentication instead)
    PasswordAuthentication no
    Remember to restart SSH after modification using
    1
    /etc/init.d/ssh restart
  • Monitor regularly the SSH log using the command:
    1
    less -n /var/log/auth.log
  • Monitor regularly who have connected to the your server with success:
    1
    who /var/log/wtmp
  • White- or black-listing IP addresses using these files: /etc/hosts.allow and /etc/hosts.deny.

3. Set up an SSH key-based authentication

To connect to the remote machine without a password, and also for security reasons, it is higly recommended to set up SSH key-based authentication. To do this, firstly check if an SSH key already exists on your local device since you don’t want to overwrite it. Try to print the public key:

1
cat ~/.ssh/id_rsa.pub

If No such file or directory then it’s safe to generate a new SSH key:

1
ssh-keygen -t rsa -b 4096 -C "your_email@example.com"

Now put the public key to the remote machine. There are multiple ways to do this:

  • On the local device, type the command ssh-copy-id <username>@<public_ip>
  • Or copy the contents of ~/.ssh/id_rsa.pub on the local device, and paste it to ~/.ssh/authorized_keys on the remote machine.

4. SSH to the remote machine with port forwarding (aka SSH tunneling)

SSH port forwarding allows you to forward any TCP port on the local (ssh client) device to remote (ssh server) machine. This feature allows us to visualize from the local device the GUI of any Web browser based application running on the remote.

To enable SSH tunneling, pass the -L option each time you connect to the remote:

1
ssh -L <local_port>:<remote_ip>:<remote_port> <username>@<public_ip>

Here is a concrete example (with random ip and user name )

1
ssh -L 7000:localhost:4000 foo@130.16.239.193

The above example forwards the port 7000 on the local device to the port 4000 on the remote machine. Any application rendering at http://localhost:4000/ on the remote can be found at http://localhost:7000/ on the local device.

You can forward any number of ports you want. Here is another concrete example of mine:

1
ssh -L 7000:localhost:7000 -L 8888:localhost:8888 leap

In this example, I am forwarding two ports, 7000 and 8888, between the local and the remote while connecting to my remote machine leap. The port 7000 is dedicated to Mashcat (a WebGL based 3D viewer) and the port 8888 is for Jupyter Lab (a Web brower based IDE for Python).

5. Work on the remote machine with terminal multiplexers

Remote processes running through SSH connection can be interrupted by Internet outage, SSH connection timeout, local device shut down, etc. Terminal multiplexers such as Tmux and GNU Screen are created to target this kind of problems. They can keep processes running in the remote machine when we disconnect from the session, letting us re-attach to it at a later time.

I’m giving an example workflow using Tmux:

1
2
3
4
5
6
7
# SSH to the remote machine 'leap' with tunneling
zong@MacBook-Pro:~% ssh -L 7000:localhost:7000 -L 8888:localhost:8888 leap
# On the remote machine, create a new Tmux session using
zongmian@leap:~$ tmux new -s mysession
# In the Tmux shell, you can launch jupyter lab
zongmian@leap:~$ jupyter lab
...

Open the url with a Web browser to have the GUI. Then you can type Ctrl-b d to detach from mysession.

1
2
3
...
[detached (from session mysession)]
zongmian@leap:~$

You can open more Tmux sessions for testing code. To re-attach previous session, type:

1
tmux a

For more commands visit Tmux Cheat Sheet & Quick Reference.

References

Comments