Complete Guide: Creating a Secure, Portable Python Development Environment on a USB Drive (with git)

Complete Guide: Creating a Secure, Portable Python Development Environment on a USB Drive

This guide will walk you through the entire process of setting up a GDPR-compliant, encrypted, and portable Python development environment on a USB stick using Ubuntu. The final result will be a self-contained project, securely linked to a GitHub repository.

Goal: To create a secure space on a USB drive to develop a Python application, manage its dependencies, and version control it with Git and GitHub, ensuring that all code, data, and credentials remain on the encrypted drive.

Prerequisites:

  • An Ubuntu system.

  • A USB drive (at least 8GB recommended). Warning: All data on this drive will be permanently erased.

  • An empty repository created on your GitHub account.

Step 1: Create the Secure Encrypted USB Drive

First, we create a secure "vault" on the USB drive using LUKS, the standard encryption tool for Linux.

  1. Insert the USB drive.

  2. Open the Disks application from your Ubuntu menu.

  3. Carefully select your USB drive from the list on the left.

  4. Click the top-right menu (three dots) and select Format Disk.... Choose GPT partitioning and click Format... to wipe the drive.

  5. You will now see "Free Space". Click the + icon to create a new partition.

  6. In the dialog box:

    • Volume Name: Give it a clear name (e.g., Secure-Vault).

    • Type: Select "Internal disk for use with Linux systems only (Ext4)".

    • Enable Password Protection: Check the box that says "Password protect volume (LUKS)".

  7. Click Next and set a strong password. This password protects all your data. If you lose it, the data is unrecoverable.

  8. Click Create. The drive is now encrypted.

Step 2: Mount the Drive and Create Your Project Folder

  1. Unplug and re-plug the USB drive.

  2. Open the File Manager. You will see your drive with a lock icon. Click it and enter the password you just created to unlock (mount) it.

  3. Open a Terminal window.

  4. Navigate into your newly mounted drive. The path will be similar to this (replace your_username and Secure-Vault accordingly):

    cd /media/your_username/Secure-Vault/
    
  5. Create a directory for your Python project:

    mkdir my_secure_app
    cd my_secure_app/
    

    You are now inside your project folder on the encrypted drive. All subsequent commands should be run from here.

Step 3: Configure Your Git Identity

Tell Git who you are. This identity is used in every commit you make.

  1. Set your name:

    git config --global user.name "Your Name"
    
  2. Set your email address (use the one associated with your GitHub account):

    git config --global user.email "your_email@example.com"
    

Step 4: Initialize the Git Repository

Turn your project folder into a Git repository to start tracking changes.

git init

Step 5: Create the Python Virtual Environment

Create a self-contained environment for your Python packages.

  1. Create the virtual environment folder, named venv:

    python3 -m venv venv
    
  2. Activate the environment. This is a crucial step you must do every time you work on the project.

    source venv/bin/activate
    

    Your terminal prompt will now start with (venv), indicating the environment is active.

Step 6: Link to GitHub with a Secure SSH Key

We will create a new SSH key stored securely on the USB, so you don't need to enter a password to interact with GitHub.

  1. Generate the SSH Key:

    ssh-keygen -t ed25519 -C "your_email@example.com"
    
  2. When prompted Enter file in which to save the key:, provide a path inside your project folder. This keeps the key on the encrypted drive.

    /media/your_username/Secure-Vault/my_secure_app/.ssh/id_ed25519
    
  3. When prompted for a passphrase, press Enter twice to leave it empty. The key is already protected by the drive's encryption.

  4. Add the Public Key to GitHub:

    • Display the public key in your terminal and copy the entire output:

      cat .ssh/id_ed25519.pub
      
    • In your web browser, go to your GitHub Settings > SSH and GPG keys.

    • Click New SSH key, give it a title (e.g., "Secure USB Key"), paste the copied key into the "Key" box, and click Add SSH key.

  5. Link Your Local Repo to GitHub:

    • On your GitHub repository page, click the green < > Code button, select the SSH tab, and copy the URL (e.g., git@github.com:your_username/your_repo.git).

    • Back in your terminal, add this as the remote "origin":

      git remote add origin git@github.com:your_username/your_repo.git
      
  6. Configure Git to Use the New SSH Key (Crucial Step):

    • Because the SSH key is in a non-standard location (inside your project folder), you must tell this specific repository how to find it.

    • Run this command:

      git config core.sshCommand "ssh -i .ssh/id_ed25519"
      

Step 7: Create a .gitignore File

Create a file to tell Git which files and folders to ignore. This is critical for preventing sensitive data and unnecessary files from being uploaded.

  1. Create the file:

    touch .gitignore
    
  2. Open the .gitignore file with a text editor and add the following:

    # Python Virtual Environment & SSH key
    venv/
    .ssh/
    
    # Database files
    *.db
    *.sqlite3
    *.db-journal
    
    # Python cache files
    __pycache__/
    *.pyc
    
    # IDE / Editor folders
    .vscode/
    .idea/
    
    # OS-specific files
    .DS_Store
    lost+found/
    

Step 8: Make Your First Commit and Push

Now, save your work to GitHub for the first time.

  1. Add all your project files to Git's tracking (it will respect the .gitignore rules):

    git add .
    
  2. Commit the files with a message:

    git commit -m "Initial project setup with secure environment"
    
  3. Push your code to GitHub:

    git push -u origin main
    

    (Note: If your repository's default branch is master, use git push -u origin master instead).

Congratulations! You now have a fully functional, secure, and portable Python development environment.

Step 9: Troubleshooting Common First-Time Issues

If you encounter an error during your first git push, it's likely one of these two common issues.

Issue 1: Permission denied (publickey)

If you see this error:

git@github.com: Permission denied (publickey).

fatal: Could not read from remote repository.

  • What it means: Git tried to connect to GitHub, but it didn't present the correct SSH key. This usually happens if you miss or mistype the command in Step 6, part 6.

  • How to fix: Rerun the configuration command from within your project directory to ensure your repository knows which key to use:

    git config core.sshCommand "ssh -i .ssh/id_ed25519"
    

    Then try git push again.

Issue 2: fatal: The current branch ... has no upstream branch

If you see this message:

fatal: The current branch master has no upstream branch.

  • What it means: This isn't an error, but a one-time question from Git. Your local branch (master or main) doesn't know which branch on the remote server (origin) to connect to.

  • How to fix: Simply use the full command that Git suggests. This command pushes your code and permanently "links" your local branch to the remote one.

    git push --set-upstream origin master
    

    (Or replace master with main if that's your branch name). For all future pushes, you will only need to type git push.

Deeper Dive: Understanding the "Why" Behind the Commands

This section explains the concepts behind the steps for those who want to understand the process more deeply.

  • Step 1: Encryption (LUKS)

    • What is LUKS? LUKS (Linux Unified Key Setup) is the standard framework for disk encryption in Linux. It doesn't just encrypt the data; it also securely manages the password and encryption keys. By using the standard, you ensure your drive can be opened by nearly any modern Linux system.

    • Why format the disk? Formatting a disk prepares it for use by creating a new, clean filesystem. We do this to ensure there are no remnants of old data or structures. Choosing GPT (GUID Partition Table) is the modern standard for laying out partitions on a disk.

    • Why is this GDPR compliant? GDPR requires you to take "appropriate technical and organisational measures" to protect personal data. Full-disk encryption is a gold-standard technical measure. If the USB drive is lost or stolen, the data is unreadable without the password, rendering it useless to a thief and preventing a data breach.

  • Step 2: Mounting

    • What is "mounting"? An encrypted volume is just a block of scrambled data. "Mounting" is the process of unlocking that data with your password and making it appear as a normal, accessible folder in your system's file structure (e.g., at /media/your_username/Secure-Vault). When you "unmount" or "eject" the drive, you are locking the vault again.

  • Step 3: Git Identity (git config --global)

    • Why does Git need an identity? Git is a version control system. Every change is logged against a person. This configuration tells Git who "you" are, so every commit you make is stamped with your name and email. The --global flag saves this configuration for your user account on this computer, so you don't have to set it for every new project.

  • Step 4: Git Init

    • What does git init really do? It creates a hidden sub-folder named .git. This folder is the "brain" of your repository. It contains all the snapshots of your code, the full history of every commit, and the configuration for this specific project. All of Git's magic happens inside this .git directory.

  • Step 5: Virtual Environment (venv)

    • Why is this so important? Your main computer has one set of "system" Python packages. If Project A needs version 1.0 of a package, and Project B needs version 2.0, you have a conflict. A virtual environment creates an isolated, private installation of Python and its packages inside your project folder.

    • How does source venv/bin/activate work? It's a clever trick. It temporarily modifies your terminal's PATH variable. The PATH is the list of places your terminal looks for commands. The activate script puts your local venv/bin folder at the very front of this list. So, when you type python, it finds the one in venv/bin first, instead of the system-wide one.

  • Step 6: SSH Keys

    • What is SSH? SSH (Secure Shell) is a secure protocol for communicating with another computer. Public-key cryptography is its core security feature.

    • How do the keys work? You generate a mathematically linked pair: a private key (which you keep secret) and a public key (which you can share freely). The public key acts like an open padlock. You put this "padlock" on your GitHub account. The only key in the universe that can unlock it is your private key. When you git push, your computer uses your private key to prove its identity to GitHub's padlock. This is far more secure than a password, which can be stolen or guessed.

    • Why git config core.sshCommand? Git's default behavior is to look for SSH keys in a standard system location (~/.ssh/). Because we created our key in a special location (my_secure_app/.ssh/), we have to explicitly tell this specific repository, "Don't use the default path; use this special command to point to the key right here in this folder."

  • Step 7: .gitignore

    • Why ignore files? A Git repository should only contain the source code—the essential blueprints needed to build and run the project. You should ignore:

      • Secrets: Like your .ssh/ folder!

      • Dependencies: Like the venv/ folder. The list of dependencies should be saved (e.g., in a requirements.txt file), but not the packages themselves. Anyone else using your project should create their own venv and install the packages from the list.

      • Generated Files: Like databases (.db) or cache files (__pycache__/). These are created by the program when it runs, they are not part of the source.

      • Hidden System Files: Different operating systems create their own hidden files and folders for housekeeping. These are irrelevant to your project's code and can cause issues.

        • lost+found/: This is created by the Linux Ext4 filesystem. It's used for data recovery if the system crashes, but it's not part of your project.

        • .DS_Store: This is created automatically by macOS's Finder to store custom attributes of a folder, like the position of icons. It's useless on other systems.

  • Step 8: Commit and Push

    • The Two-Stage Save: This is the fundamental Git workflow.

      1. git commit: Records a snapshot of your changes to the local .git folder's history. You can do this many times, even when offline. It's like saving a draft of a document.

      2. git push: Uploads your committed changes from your local repository to the remote server (GitHub). This is how you share your work and back it up. The -u (or --set-upstream) flag is a one-time command on the first push to establish the connection between your local branch and the remote one.

Comments

Popular posts from this blog

Code-Gurus Wanted: Bridging the gap - supporting the transition.

Using throw away app to help me get back into the vibe space post stack/structure/perfection enlightenment

Re-finding my coding muse: step 1