Securing and Setting up your Python Development Environment

This is a guide to setting up a minimal and secure Python development environment for Ubuntu

There are a lot of blog posts out there on learning the basics of programming or how to create your first web app with python, but weirdly not very many on how to setup a secure environment. Not only that, but when I was starting out, I had a hard time finding out how a lot of the various tools interconnected and worked.

For example, what are some basic things I should do after I install Ubuntu to ensure it's secure? How do I configure git and github? What are some basic VSCode extensions / pro tips that could make my life easier?

So - here's to the blog post that I wish I had when I was starting out.

Target Audience: Someone that's familiar with the basics of Python and has maybe completed a few tutorials, and is looking to setup an actual environment/see sample work flows.

Quick Note: Everything at the time of writing this blog should also work with a RaspberryPi and Raspian.

Securing the OS

These are just some general tips that will likely work for most people.

To get started, I typically recommend installing whatever the current LTS is (Long Term Stable Release) and selecting the minimal installation option / LUKS Encryption. This will ensure you have whole disk encryption applied to your HDD should you lose it and reduces the overall attack surface of the laptop by ensuring un-necessary applications are not installed.

On first boot of course update the system with sudo apt update && sudo apt upgrade -y

Basic Firewall Configuration

A good general rule of thumb is to ensure that there is a default deny inbound to your system, and a default deny out of your system so that communication only occurs over authorized ports.

In this we'll use a combination of iptables and ufw (user friendly firewall, an iptables wrapper that simplifies firewall configuration greatly, however has some limitations as we'll see.)

These should both be installed by default, on the off chance ufw isn't, just run sudo apt install ufw and sudo ufw status to ensure that it is working. By default it should show as inactive.

Need to know commands:

  • ufw status displays if the firewall is active or inactive, and if active it's current configuration.
  • ufw enable this will start the firewall (and if not properly configured, potentially limit your ability to connect outbound)
  • ufw disable this will disable it, if you have connection issues from the config not being applied appropriately, this will turn the firewall off so that you can troubleshoot the issue.

ufw Config

This is a good typical configuration that will only allow incoming and outgoing connections if explicitly allowed. This will allow you to browse the web, ssh outbound to remote servers, and connect to a VPN should you use one.

Keep in mind - when developing applications listening on your local system, you will need to add a firewall rule for the port used.

sudo ufw default deny incoming
sudo ufw default deny outgoing
sudo ufw allow out 22/tcp # this will allow ssh comms outbound only
sudo ufw allow out http
sudo ufw allow out https
sudo ufw allow out dns
sudo ufw allow out 1194/udp # this is commonly a default vpn port
sudo ufw enable
sudo ufw start

ping / ICMP configuration

Let's be real, it's common to need to ping something and one of the shortcomings of ufw is that there isn't a way to easily allow it. Thankfully we can use iptables to add two simple rules to allow pings to go outbound of your system only (ICMP echo outbound, ICMP echo response inbound):

iptables -A OUTPUT -p icmp --icmp-type echo-request -j ACCEPT
iptables -A INPUT -p icmp --icmp-type echo-reply -j ACCEPT

Setting up git and Github

I personally enjoy some of the features Github offers (IE: Github pages is great for getting started blogging and free package vulnerability scanning is dope.) Setup a Github account first so that you can enable the feature that provides a private email address that forwards to your personal email for some level of privacy. Once you setup an account - you can find the email privacy settings here.

It will be important to have the private email address that Github offers when generating your SSH / GPG Keys to avoid exposing your personal email address if that is a concern.

Setup and add your SSH / GPG keys and add them to github:

Initial basic git configuration

I typically use and recommend vscode for most basic development needs as it's very popular and easy to find articles on how to setup. Best of all it's fairly lightweight and free. Be sure to install VSCode as we're going to configure git to use it as our default editor.

git config --global user.name "your-github-user"
git config --global user.email "your-private-github-email"
git config --global core.editor "code --wait"

Add the following to your ~/.gitconfig if you'd like it to be your default diff tool as well via nano ~/.gitconfig.

[diff]
    tool = vscode
[difftool "vscode"]
    cmd = code --wait --diff $LOCAL $REMOTE

VSCode Configuration Recommendations

This part is totally optional, however if you're doing development you're likely going to be using VSCode quite frequently - so here are some common extensions that can make it a more pleasant experience.

Sample Workflows

I'm the type of person that occasionally needs to see/learn the whole picture to really understand how things work, and I hope this builds that picture for you.

Using python virtual environments with VSCode

For whatever reason, when I was getting started years ago, it didn't "click" on how to work with python virtual environments within VS Code. Largely in hindsight - was because I didn't understand the flow from start to completion. Be sure to read the docs.

When I got started with virtual environments, I didn't understand how to manage or what files should be committed to git that are included. I didn't understand how to "enable" or use them in a way that VSCode would recognize, and the idea of using the git cli was intimidating.

Create the Repo

Create a new Github Repo, and clone it locally to your system. I typically create new repo's through the Github Web UI as it makes setting up readme's, your .gitignore file, and picking licenses easy.

Clone the Repo

Clone the repo in question to your local system via git clone git@github.com:david-burkett/pmelsonbot5000.git

Start new Terminal Session in VSCode

From within the VSCode, open a terminal where we will create and manage our python virtual environment by selecting Terminal > New Terminal

Validate .gitignore Config

Ensure that all of the new folders/files created from creating the virtual environment are contained within the .gitignore file.

NOTE: This is how you prevent all of the clutter from ending up in your git repo from creating the virtual environments as well as prevent yourself from commiting sensitive materials to your git repo

Create and Activate the virtual environment

From the VSCode Terminal enter:

# The command below will create the virtual environment, and drop the files in the path provided.
$ python3 -m venv pmelsonbot5000/

# Activate the Environment
$ source pmelsonbot5000/bin/activate

Install any external libraries needed

# Install any needed dependancies
$ pip3 install -r requests.txt

Configure the VSCode to use the virtual environment interpreter

Set the VSCode Python Interpreter to use the virtual environments, this way you wont see errors within VSCode for not having the above libraries installed. (By default, VSCode is looking at your global python interpreter, rather than the local virtual environment interpreter so it doesn't see the libraries we pip install in our virtual env)

Start developing!

You're off! Start your python application in your secure virtual environment. When you're finished and you're ready to drop out of the virtual environment simply enter the command deactivate

Here are the above CLI Commands in order in an easier to parse format:

# Cloning the repo we created with the .gitignore file
$ git clone git@github.com:david-burkett/pmelsonbot5000.git

# Create the python virtual environment for our new project using the cloned repo
$ python3 -m venv pmelsonbot5000/

# Activate the python virtual environment
$ source pmelsonbot5000/bin/activate

# Install any needed dependancies
$ pip3 install -r requirements.txt

# When done exit the virtual environment by typing deactivate
$ deactivate

My most commonly used git cli commands

The git cli doesn't need to be scary. In reality, I do things like manage my pull requests / create my repos through the github web interface. Outside of that, I really only use a few commands:

# checking the repo/branch I'm in
$ git status

# creating a new branch before starting (as to not commit direct to master)
$ git branch branch_name

# checking out the above branch, so that you will commit work to it
$ git checkout branch_name

# add any changes to the commit via single file or wildcards
$ git add file_name_here
$ git add *

# Commit and sign the commit -S signs, -m adds message
$ git commit -S -m "descriptive message"

# Push to the new branch - setting the upstream origin is only required the first time you push to a new branch after changing to it. Subsequent pushes do not require it.
$ git push --set-upstream origin branch_name

# If you want to pull just the metadata of changes from the remote git repo (IE: Github)

$ git fetch

# To pull the files associated with said changes from the fetch
$ git pull

# I commonly will run both as a one liner
$ get fetch && git pull

Here's an example flow start to finish:

# We'll clone a repo.
$ git clone git@github.com:david-burkett/pmelsonbot5000.git

# Next we'll create a new branch for our code changes and swap to it.
$ git branch newBranch

# Now we'll check that branch out
$ git checkout newBranch

# Create your virtual environment (.gitignore is typically included with existing repos, be sure to verify that it is!)
$ python3 -m venv pmelsonbot5000/

# Open the git project folder in VSCode and from the terminal enter
$ source bin/activate

# Install any third party depenancies
$ pip3 install -r requirements.txt

# At this point you are ready to code!
# Once your done. Save your changes with ctrl+s
# Lets add the files we changed that we want to commit to git (wild cards supported such as git add * - use with care.)
$ git add filename.py

# Commit the changes we want to send to Github, -S to sign it with the GPG key we created. -m for the git commit message.
$ git commit -S -m "concise change information here"

# Push the files to the branch we created. You'll only need to add the --set-upstream origin after git push the first push you make after checking out a new branch.
$ git push --set-upstream origin newBranch

# Go back to the web ui, and submit your pull request for review to the main branch - and deactivate your virtual environment via the cli.
$ deactivate

Conclusion

BOOM. Now you've gotten a minimal Ubuntu installation setup that has been secured and is ready to start developing. We have a few easy to remember git cli commands so we can speed up our work flow, and we've configured and see how all of these various things connect with a real sample workflow.

If you found this blog helpful, I'd be interesting in hearing about it!


Find a technical error in a blog post?

Contact me on BlueSky @signalblur