Skip to content

Use the latest Dev Tools on a Stable Debian Linux

Practicalli Debian Linux Logo

I use Debian Linux as there is a huge advantage to having a stable and low maintenance operating system. This allows me to focus and get more things done.

The constraint of a stable operating system is that some of the latest versions of development tools and programming languages may not be available as part of the distributions package manager.

Simple bash scripts were created to install the latest development tools, made effectively one-liner's where the [Download Release Artifacts (DRA)](#Git} project could be used. The scripts were very simple even when falling back to curl with a few basic Linux commands.

These shell scripts and the DRA tool are used to install editors, programming languages (e.g. Clojure, Rust, Node.js), Terminal UI (TUI's) tools for development or system administration and even the odd desktop app.

A debian-linux-post-instal.sh script was created update all the Debian packages, reading packages to add and remove from a plain text file.

A dev-tools-install.sh calls each script that installs the latest versions of each development tool, programming language, TUI and desktop app.

Practicalli dotfiles - Debian-Linux contains all the scripts, along with a few manual steps that have not been scripted (mainly UI / UX configuration).

Debian Packagesλ︎

I created a simple bash script to add packages for tools and applications I commonly use.

The script reads a list of packages from two text files, one listing packages to add and another listing packages to remove.

Each list is just a text file, making it very easy to maintain. I keep both lists in alphabetic order so its easy to check which packages will be added or removed.

The post install script also includes the setup of the clipboard package, based on which windowing system is currently used, i.e. X11 or Wayland.

The script also sets kitty as the default terminal. Kitty would already be installed as it is part of the add package list.

Finally the script tidies up packages not required, autopurge, and deletes all the downloaded packages, autoclean.

NOTE: A Debian Linux install adds a few packages that I do not wish to use, or replaces packages when I have alternative package preferences. E.g. I remove Evolution as I do not need a local mail server, I also use LightDM rather than GDM3 for the GUI greeter and display manager.

Package Post Install Scriptλ︎

A while loop is used to read through a package list file one line at a time, each time calling the apt-get command.

sudo apt-get --yes --ignore-missing install <package-name> is used to install each package in turn.

The --ignore-missing flag skips a package if it is already installed and at the latest version.

The --yes flag automatically confirms the install, even when otherwise prompted to confirm the install of the recommended package dependencies.

NOTE: apt-get is the back-end command used by apt, the Debian Linux package manager. apt-get is ideal for use in scripts and has a little less overhead than apt itself.

Debian Linux Post Install Script
#!/usr/bin/env bash

# Batch install Debian Linux packages used by Practicalli
# Skip packages if they are already installed

# NOTES:
# - apt-get backend used as features of apt UI not required for scripts

# Package lists to process
add="debian-linux-post-install-packages-add.list"
purge="debian-linux-post-install-packages-purge.list"

## Update available Debian packages
echo
echo "# ---------------------------------------"
echo Update available Debian packages
sudo apt update
echo "# ---------------------------------------"
echo

# Install additional Debian packages
while read -r line
do
  echo "# ---------------------------------------"
  echo Install "$line"
  sudo apt-get --yes --ignore-missing install "$line"
  echo "# ---------------------------------------"
done < "$add"
echo

echo "# ---------------------------------------"
echo Install System Clipboard tool - X11 or Wayland
./clipboard.sh
echo "# ---------------------------------------"
echo

echo "# ---------------------------------------"
echo Configure Kitty as default terminal
sudo update-alternatives --set x-terminal-emulator "/usr/bin/kitty"
echo "# ---------------------------------------"
echo

# Remove additional Debian packages
while read -r line
do
  echo
  echo "# ---------------------------------------"
  echo Purge "$line"
  echo "# ---------------------------------------"
  echo
  sudo apt-get purge --yes --ignore-missing "$line"
done < "$purge"
echo

echo "# ---------------------------------------"
echo Uninstall unnecessary Debian packages
sudo apt-get autopurge
echo "# ---------------------------------------"
echo

echo "# ---------------------------------------"
echo Remove Debian package files from cache
sudo apt-get clean
echo "# ---------------------------------------"
echo

Development toolsλ︎

I use Neovim and Emacs editors, a range of development tools and several programming languages.

I created a simple bash script for each each development tool. Each script downloads and installs the binary or AppImage file for that tool.

Where relevant, the script also updates shell completions (for either bash or zsh, depending on which is currently being used).

The following tools are used to simplify the scripts:

  • Download Release Assets (DRA) downloads the latest stable release from a GitHub repository
  • Uv to install python packages, using uv tool install to avoid the need for a Python virtual environment.
  • Curl with a tools specific install script, e.g. Clojure CLI.
  • Curl with a little scripting magic as a fall-back

Practicalli Dotfiles contains a debian-linux directory with the individual tool scripts organised in sub-directories:

  • app for desktop applications
  • cli for command line tools
  • language for programming languages, e.g. Clojure, Rust, Node.js
  • tui terminal UI apps used for system administration and supporting development tools

GitHub Releasesλ︎

Most development tools and TUI's have binaries or AppImages available from their GitHub Release pages.

Download Release Assets (DRA) tool downloads and installs the latest release from the specified GitHub repository.

Unfortunately I cant use DRA to install DRA, so curl is used to download the DRA install script

Alternatively, use curl and a bit of scripting magic to get the URL of the latest Debian package, using curl again to download the Debian package and the Apt package manager to install the downloaded .deb file.

NOTE: dra runs on Linux (x86_64, armv6, arm64), macOS (x86_64, arm64) and Windows.

Use Curl to install DRA via its install script
#!/usr/bin/env bash

echo
echo "# ---------------------------------------"
echo "DRA - Download Release Assests from GitHub"
curl --proto '=https' --tlsv1.2 -sSf https://raw.githubusercontent.com/devmatteini/dra/refs/heads/main/install.sh | sudo bash -s -- --to /usr/local/bin


# Generate shell command completion
if [[ $SHELL == "/bin/bash" ]]; then
  mkdir -p ~/.local/share/bash-completion/completions/
  dra completion bash > ~/.local/share/bash-completion/completions/dra

elif [[ $SHELL == "/usr/bin/zsh" ]]; then
  mkdir -p ~/.local/share/zsh-completion
  dra completion zsh > ~/.local/share/zsh-completion/_dra
else
  echo "Unknown SHELL, Ripgrep completions will not be generated"
  exit
fi

echo
echo "Dra version: $(dra --version)"
echo "# ---------------------------------------"
echo
Use Curl to install DRA via the Debain package

DRA publishes a .deb file as part of each release.

Curl is first used to find the URL of the .deb package from the latest GitHub release.

Use apt the Debian package manager to install the DRA package.

#!/usr/bin/env bash

echo
echo "# ---------------------------------------"
echo "DRA - Download Release Assests from GitHub"

DOWNLOAD_URL=$(curl -s https://api.github.com/repos/devmatteini/dra/releases/latest | grep browser_download_url | grep .deb | cut -d '"' -f 4)

curl -s -L -o ~/tmp/dra.deb "$DOWNLOAD_URL"

sudo apt install /tmp/dra.deb

# Generate shell command completion
if [[ $SHELL == "/bin/bash" ]]; then
  mkdir -p ~/.local/share/bash-completion/completions/
  dra completion bash > ~/.local/share/bash-completion/completions/dra

elif [[ $SHELL == "/usr/bin/zsh" ]]; then
  mkdir -p ~/.local/share/zsh-completion
  dra completion zsh > ~/.local/share/zsh-completion/_dra
else
  echo "Unknown SHELL, Ripgrep completions will not be generated"
  exit
fi

echo
echo "Dra version: $(dra --version)"
echo "# ---------------------------------------"
echo
Deconstructing the Debian package Shell Script
Command Description
curl -s https://api.github.com/repos/USERNAME/REPO/releases/latest Fetch latest release data (JSON) from the GitHub repository
grep browser_download_url Filters JSON output returning only lines including a download URL
grep .deb Filters URLs to only those that are .deb files
cut -d '"' -f 4 Extract URL from the filtered JSON response
curl -s -L -o ~/tmp/filename.deb "$DOWNLOAD_URL" Download .deb file to specified directory

DRA can also be used as a TUI to install a specific version of a tool or automatically install the latest version.

Download Release Assets from GitHub

Neovimλ︎

DRA is used to download the latest AppImage and install it globally, so I can use nvim for the practicalli user account and the root account for operating system administration.

The script explicitly specifies the AppImage asset, otherwise DRA will extract and install only the nvim client and neglects to include the Neovim runtime.

Install latest stable Neovim AppImage
#!/usr/bin/env bash

# Install the current release version of Neovim from GitHub for all users

echo
echo "# ---------------------------------------"
echo "Neovim hyper-configurable editor - installed for all users"

# install the nvim.appimage (automatic only installs nvim and not runtime)
# rename file to `nvim` the standard executable name
sudo dra download --select nvim-linux-x86_64.appimage --install --output /usr/local/bin/nvim neovim/neovim

echo
echo "Neovim version: $(neovim --version)"
echo "# ---------------------------------------"
echo ""

A similar script is used to install a nightly release of the AppImage.

This script specifies --tag nightly to get the latest nightly release.

The script installs the AppImage into ~/.local/bin as it is only needed for the practicalli user account, for testing my Neovim configuration.

Install latest nightly Neovim AppImage
#!/usr/bin/env bash

# Install the pre-release version of Neovim from GitHub, for the current user

echo
echo "# ---------------------------------------"
echo "Neovim hyper-configurable editor"
echo "- installed only for current user"

# Install nvim.appimage nightly release tag and rename to nvim-nightly
dra download --tag nightly --select nvim-linux-x86_64.appimage --install --output ~/.local/bin/nvim-nightly neovim/neovim

echo
echo "Neovim pre-release version: $(nvim-nightly --version)"
echo "# ---------------------------------------"
echo

Emacsλ︎

Emacs usually has the latest version available as a Debian package.

if need a newer version or I want to try bleeding features then I will compile Emacs from its source code, choosing the relevant branch for the version I require.

Building Emacs from source code takes a few simple steps and can be configured to create a customised set of features and even a custom desktop icon.

Emacs Plus is recommended for MacOS users

Emacs Plus is configurable formulae for Homebrew, providing more features and flexibility than Homebrew's own Emacs formulae.

But Arch Linux is Awesomeλ︎

I have used 'rolling' distributions and spent 2025 testing out Arch Linux as an alternative operating system. The initial learning curve was not too steep and getting going only took a weekend. However, the maintenance burden was much greater and became a continual distraction.

Part of the maintenance headache was using Btrfs (failed during a recovery) and Hyprland (which introduced lots of breaking changes).

I found some core Arch Linux tools confusing. packman command options did not feel intuitive and the docs didn't clarify what the flags letters stood for. If I continued to use Arch Linux I would have wrapped pacman with a shell script or Makefile tasks.

Using the AUR community repository I also found confusing, there are several tools to access AUR and it wasn't clear from the official docs how to add these tools without first adding AUR (catch 22 scenario).

The AUR community is a big part of adding the latest development tools. Without the AURA then Arch Linux didn't feel significantly up to date for software development..

Usually the Arch Linux docs are very comprehensive, but can drowned the reader in options (some outdated) and yet not provide enough guidance or a clear and simple approach.

I never did figure out a nice way to manage my SSH Keys in Arch Linux when I wasnt using a Gnome desktop.

Arch Linux meets the needs of many people, but Debian Linux the ideal operating system for me.

NOTE: As I have used Debian Linux since 1995 (30 years at time of writing) I have a strong affinity and confidence using it as my operating system. Debian has never let me down.


Thank you.

🌐 Practical.li Website

Practical.li GitHub Org practicalli-johnny profile

@practicalli@clj.social @practical_li