This project aims to enable the deployment of a dockerised workstation that can be SSH'd into
To be able to deploy your own workstation, you will need some prerequisites installed:
package.json
in the repository, it's recommended to run npm install
in the repository root and make use of npx <command>
rather than globally installing AWS CDKIf you're developing on MacOS, all of the above (apart from AWS CDK) can be installed using homebrew
If you're developing on Windows, we'd recommend using either Git BASH or Windows Subsystem for Linux
If you only intend on deploying the infrastructure as is, you can install only the dependencies required for deployment with:
$ make install
However, if you intend on developing on this project and making contributions, you can install all deployment and development dependencies with:
$ make install-dev
$ ssh-keygen -b 2048 -t rsa -f <a-path-to-save-the-file-to> -q -N ""
To perform some actions, this project requires a .env
file to be present in the base of the project with some variables present.
An example .env
file is provided: example.env
, copy and rename this to .env
and populate it with your own values.
Below is a table explaining the values we expect (and that can be used additionally) in your .env
file:
Variable | Value(s) | Required | Default | Description |
---|---|---|---|---|
SSH_PRIVATE_KEY_LOCATION |
<path/to/the/private/key> |
â | N/A | You created this in Step 3 |
SSH_PUBLIC_KEY_LOCATION |
<path/to/the/public/key> |
â | N/A | You created this in Step 3 |
AWS_PROFILE |
<Your named AWS CLI profile> |
đŤ | default | The AWS Profile to deploy to |
IDENTIFIER |
<An identifier for your deployment, e.g. 'my-dev'> |
đŤ | dev | This is unique to your deployed stack - If a conflict occurs, your deployment will fail |
SSH_CONFIG_LOCATION |
<path/to/your/ssh/config/file> |
đŤ | No value will result in a .ssh/config file created in the repo root | The SSH Config file to add the remote workstations details to |
INSTANCE_CPU |
<A value of 256/512/1024/2048/4096> |
đŤ | 256 | See container CPU & Memory mappings here |
INSTANCE_MEMORY |
<A value of 512/1024/2048/...increments of 1024 till 30720> |
đŤ | 512 | See container CPU & Memory mappings here |
CONTAINER_ECR_REPOSITORY |
<The value of an ECR repository name, e.g. 'my-magical-repo'> |
đŤ | N/A | The name of an ECR repository in the region and account you're deploying into - Note: See Customising the container image |
CONTAINER_DOCKER_REPOSITORY |
<The value of an Dockerhub/other registry repo, e.g. 'docker/whalesay:latest'> |
đŤ | N/A | Must be public - Credentials are currently not supported within this project - Note : See Customising the container image |
CONTAINER_LOCAL_PATH |
<path/to/your/Dockerfile/folder - not the file itself> |
đŤ | N/A | The file used to build the image must be called Dockerfile - Note : See Customising the container image |
TAGS_<Any value> |
<A value to assign to this tag> |
đŤ | N/A | You can add as many tags as AWS allows. To add a tag, add an entry to your .env file like TAGS_MY_COOL_TAG="thisiscool" - Your AWS tag will be named with a Pascal case name like: MyCoolTag with the value you provided. You can read more about tags for AWS billing and tracking infrastructure here |
$ make deploy
$ make ssh-to-instance
VS Code has an extension called VS Code Remote SSH - Available here - With this extension you can SSH onto a machine and develop on it in VS Code (locally). It also provides other utitilies such as SSH Port Forwarding.
To use the extension, install it and then make sure you've done Steps 1-4 under General usage
With the plugin enabled, either open the actions menu in VS Code (MacOS is CMD + Shift + P
), or select the little icon to the bottom left, selecting Remote-SSH: Connect to Host...
You should now see a prompt with the contents of your SSH Config file (listing the hosts), you should see remote-workstation-<IDENTIFIER>
- select that.
Note: You might not see your workstation here, this is usually the case if you A: do not have an SSH Host config file in the default location or B: didn't provide one and the deployment has generated you one in .ssh/config
in the root of the repository.
You can remedy this by selecting Configure SSH Hosts...
and then Settings
and providing the path to the non standard location
The setting name is remote.SSH.configFile
, if you'd rather search for it
Now that you have established a connection to the instance, you can open files/folders on it like you would normally in VS Code: File -> Open...
Because VS Code Remote SSH bootstraps an VS Code server on the running instance, we can install any VS Code extension inside it, allowing us access to language support, enhanced debugging, and various other features.
If you're running a service that you'd like to access via localhost
- say a webapp or a Jupyter Notebook, VS Code Remote SSH comes with SSH Port Forwarding built in.
A very easy example you can peform on the docker/Dockerfile
image is:
# On the instance
$ echo "Hello Remote Workspace!" > index.html
$ python -m http.server 8181
When you then look at the Remote SSH pane, you'll see Ports
which shows you which ports have services running on them in the instance, you can then select them to forward them on
Then you can access it on localhost:<a-port>
:
Note: you might also notice a prompt appear in VS Code asking if you'd like to visit the forwarded application, providing you a link to click on:
If your image has Jupyter Notebook installed (or if you run pip3 install jupyter
on the provided docker/Dockerfile
), you
can setup port forwarding for a notebook instance:
# On the instance
$ jupyter-notebook --no-browser --port=<a-port>
Similarly to the Simple Example, you will see the port you provided appear in the Ports
selection, you can then forward it, navigate to localhost:<a-port>
and access your notebook!
This project revolves around the ability to add a SSH client to a Docker container that we then serve via AWS Fargate
Below is a high level diagram of what is happening architecturally:
The user runs make deploy
, under the hood this does:
docker/
. As part of this, the users public IP is added to a security group to allow SSH access to the instance. The public key the user provided is also added into the instanceutils/generate_ssh_config.py
script is called. This first identifies the public IP address of the Fargate instance, then generates an SSH config entry for the host. If a location is provided for the config file, the entry is either added or overwritten. If the location is not provided, the .ssh/config
file is created and the entry is addedmake deploy
), the user SSH's onto the Fargate instanceTo use this project, the only essential components to ensure a Docker image has are:
openssh-server
)curl
docker/docker-entrypoint.sh
) that takes the public key and adds it to the authorised keys area. It should also start the SSH daemonFrom then on, whatever you do with the container is up to you (Setting up users, workspaces, dependencies, etc.)
You can remove the Dockerfile
that is currently in the docker/
directory and add your own, just make sure it does the same setup steps
If you have a Docker Image or a Dockerfile
elsewhere external to this project, we use a heirarchy of values from .env
to get which image to use, the order is from top to bottom:
CONTAINER_ECR_REPOSITORY
- Highest priorityCONTAINER_DOCKER_REPOSITORY
CONTAINER_LOCAL_PATH
docker/
in this repositoryBy default, the project deploys a container with 0.25 vCPU
and 0.5GB RAM
- These can be altered by using INSTANCE_CPU
and INSTANCE_MEMORY
in your .env
file. NOTE: CPU and Memory are tied, you can get more information about these mappings here
A Makefile
is provided to abstract commonly used commands away for ease of use, a breakdown of the commands is:
make install
This will run
npm install
andpipenv install
on the repo root, installing only the dependencies needed for a production deployment
make install-dev
This will run
npm install
andpipenv install --dev
on the repo root, installing the dependencies needed for development of this project
make lint
This will perform a dry run of
flake8
,isort
, andblack
and let you know what issues were found
make format
This will peform a run of
isort
andblack
, this will modify files if issues were found
make diff
This will run a
cdk diff
using the contents of your.env
file
make deploy
This will run a
cdk deploy
using the contents of your.env
file. The deployment is auto-approved, so make sure you know what you're changing with your deployment first! (Best to runmake diff
to check!)
make destroy
This will run a
cdk destroy
using the contents of your.env
file. The destroy is auto-approved, so make sure you know what you're destroying first!
make ssh-config
This will generate the SSH config entry (only really useful if for some reason the Fargate instance is re-created)
make ssh-to-instance
This will SSH to the instance, if the values of
SSH_CONFIG_LOCATION
andIDENTIFIER
are not present in.env
, the default values of./.ssh/config
anddev
will be used respectively