- Introduction
- 1. System Update & Core Utilities
- 2. Language Runtimes
- 3. Shell Configuration
- 4. systemd-user SSH Agent Service (User)
- 5. Common SSH Use Cases
- 6. Verification Checklist
- Prerequisites for
linaro
User - Part 1: System-Wide Installations and Configurations (executed by
linaro
usingsudo
) - Part 2: User-Specific Installations and Configurations (as
linaro
) - Part 3: Verification Checklist
- Part 4: Understanding Key Features and Use Cases
#Introduction
This guide walks through configuring a robust interactive shell on Debian 11 “Bullseye,” including environment variables (Go, Rust, Python), Flatpak, aliases, and a systemd-user–managed SSH agent. It separates user-level and root-level steps, clarifies placeholders, and includes verification commands.
#1. System Update & Core Utilities
sudo apt update && sudo apt upgrade -y
sudo apt install -y \
build-essential git curl wget unzip zip bash-completion \
python3-pip nodejs npm libpulse-dev flatpak swaks
#2. Language Runtimes
#Go (≥1.20)
GO_VER=1.20.5
wget https://go.dev/dl/go${GO_VER}.linux-amd64.tar.gz
sudo tar -C /usr/local -xzf go${GO_VER}.linux-amd64.tar.gz
rm go${GO_VER}.linux-amd64.tar.gz
#Rust
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y
#3. Shell Configuration
#3.1 ~/.bash_profile (User)
# Source ~/.bashrc for interactive login shells
if [[ $- == *i* ]]; then
source ~/.bashrc
fi
#3.2 ~/.bashrc (User)
# 1. Exit if not interactive
case "$-" in *i*) ;; *) return;; esac
# 2. History
HISTCONTROL=ignoreboth # space-prefixed commands and duplicates are not saved
shopt -s histappend # Append to history file, don't overwrite
HISTSIZE=5000 # Number of commands to keep in memory
HISTFILESIZE=10000 # Number of commands to keep in the history file
# Save history after each command and reload it to make it available across terminals.
# `history -a` appends the current session's history to HISTFILE.
# `PROMPT_COMMAND="history -a; ${PROMPT_COMMAND}"` ensures this happens before each prompt.
# Rely on histappend for merging on shell exit.
PROMPT_COMMAND="history -a; ${PROMPT_COMMAND}"
# 3. XDG directories
export XDG_CONFIG_HOME="${XDG_CONFIG_HOME:-/root/.config}"
export XDG_CACHE_HOME="${XDG_CACHE_HOME:-/root/.cache}"
export XDG_DATA_HOME="${XDG_DATA_HOME:-/root/.local/share}"
# Ensure critical XDG directories exist
mkdir -p "$XDG_CONFIG_HOME" "$XDG_CACHE_HOME" "$XDG_DATA_HOME"
# Append Flatpak XDG data dirs to the system default XDG_DATA_DIRS
_FLATPAK_USER_DATA_DIR="$XDG_DATA_HOME/flatpak/exports/share"
_FLATPAK_SYSTEM_DATA_DIR="/var/lib/flatpak/exports/share"
_SYSTEM_XDG_DATA_DIRS="${XDG_DATA_DIRS:-/usr/local/share/:/usr/share/}"
export XDG_DATA_DIRS="${_FLATPAK_USER_DATA_DIR}:${_FLATPAK_SYSTEM_DATA_DIR}:${_SYSTEM_XDG_DATA_DIRS}"
# Clean up temporary variables
unset _FLATPAK_USER_DATA_DIR _FLATPAK_SYSTEM_DATA_DIR _SYSTEM_XDG_DATA_DIRS
# XDG_RUNTIME_DIR is critical and typically set by pam_systemd.
# If it's not set, it indicates a problem with the system's session management (e.g., pam_systemd).
# Do not attempt to set it manually to a /tmp path here as it can cause issues.
if [ -z "$XDG_RUNTIME_DIR" ]; then
# Log an error or warning if preferred, but avoid setting a non-standard fallback
# echo "Warning: XDG_RUNTIME_DIR is not set. User services may not function correctly." >&2
: # No action, rely on system setup
else
export XDG_RUNTIME_DIR # Ensure it's exported if set by pam_systemd
fi
# 4. PATH updates
export GOPATH="/root/go"
_add_to_path_if_missing() {
local dir_to_add="$1"
local prepend="$2" # "prepend" or "append"
if [ -d "$dir_to_add" ]; then
case ":$PATH:" in
*":$dir_to_add:"*) :;; # Already in PATH
*) if [ "$prepend" = "prepend" ]; then
PATH="$dir_to_add:$PATH" # Prepend for higher priority
else
PATH="$PATH:$dir_to_add" # Append
fi
;;
esac
fi
}
_add_to_path_if_missing "/usr/local/go/bin" "prepend" # Go system binaries
_add_to_path_if_missing "$GOPATH/bin" "prepend" # User-installed Go binaries
_add_to_path_if_missing "/root/.local/bin" "prepend" # User-local pip installs, etc.
# Rust path is handled by sourcing .cargo/env, which also prepends.
unset _add_to_path_if_missing
export PATH
# 5. Rust environment
[ -f "/root/.cargo/env" ] && source "/root/.cargo/env"
# 6. Bash completion
if ! shopt -oq posix; then
if [ -f /usr/share/bash-completion/bash_completion ]; then
source /usr/share/bash-completion/bash_completion
elif [ -f /etc/bash_completion ]; then
source /etc/bash_completion
fi
fi
# 7. SSH agent: Prioritize systemd-user, then GNOME Keyring if in desktop session
# This logic determines which SSH_AUTH_SOCK to use.
# Path for the systemd user ssh-agent socket
_SYSTEMD_SSH_AGENT_SOCK="$XDG_RUNTIME_DIR/ssh-agent.sock"
if [ -n "$XDG_RUNTIME_DIR" ] && [ -S "$_SYSTEMD_SSH_AGENT_SOCK" ]; then
# systemd user agent socket exists, use it.
export SSH_AUTH_SOCK="$_SYSTEMD_SSH_AGENT_SOCK"
elif [ -n "$DESKTOP_SESSION" ] && command -v gnome-keyring-daemon >/dev/null; then
# No systemd user agent socket found (or XDG_RUNTIME_DIR not set),
# but in a desktop session. Attempt to use/start GNOME Keyring.
# GNOME Keyring might already be running via its own systemd user service or XDG autostart.
# This eval will set SSH_AUTH_SOCK if gnome-keyring-daemon starts/is running and manages SSH.
eval "$(gnome-keyring-daemon --start --components=secrets,ssh)"
export SSH_AUTH_SOCK # Ensure it's exported from eval
fi
unset _SYSTEMD_SSH_AGENT_SOCK
# Attempt to add default SSH key (id_rsa) if an agent is running and has no keys.
if command -v ssh-add >/dev/null; then
if ! ssh-add -l &>/dev/null; then # Check if agent has ANY keys
if [ -n "${SSH_AUTH_SOCK}" ] && [ -S "${SSH_AUTH_SOCK}" ] && [ -f "/root/.ssh/id_rsa" ]; then
# Agent seems to be running (socket exists), but no keys listed. Add id_rsa.
# Suppress errors (e.g., passphrase needed but no tty, or key already added by another mechanism).
ssh-add "/root/.ssh/id_rsa" 2>/dev/null || true
fi
fi
fi
# 9. Prompt
if [[ "${EUID}" == "0" ]]; then # Root prompt
PS1='\[\033[01;31m\]\h\[\033[01;34m\] \W \$\[\033[00m\] '
else # User prompt
PS1='\[\033[01;32m\]\u@\h\[\033[00m\]:\[\033[01;34m\]\w\[\033[00m\]\$ '
fi
# 10. Aliases (!!! REVIEW AND REPLACE PLACEHOLDERS !!!)
alias ls='ls --color=auto -hF' # Added -h for human-readable sizes, -F for type indicators
alias ll='ls -alFh' # Added -h
alias la='ls -Ah' # Added -h
alias l='ls -CFh' # Added -h
alias grep='grep --color=auto'
alias egrep='egrep --color=auto'
alias fgrep='fgrep --color=auto'
# Example ping alias (uses default system ping)
alias p='ping -c 4 ib.bsb.br' # Pings example.com 4 times
# Swaks alias for email testing
# !!! REPLACE with your actual email, app password, and possibly SMTP server !!!
# For Gmail, you'll need an "App Password". See Google's help documentation.
# alias Z='swaks -4 -tls -f you@gmail.com -t recipient@example.com -s smtp.gmail.com:587 -au you@gmail.com -ap YOUR_GMAIL_APP_PASSWORD -d'
alias Z='echo "Swaks alias Z not configured. Edit ~/.bashrc with your email details and an App Password for services like Gmail."'
# Git project aliases
# !!! REPLACE 'REPO' with your actual repository directory name if different !!!
# And ensure ~/projects/REPO is a git repository.
PROJECTS_DIR="/root/projects"
# Example: alias project1-pull='(cd "$PROJECTS_DIR/my-actual-project" && git pull) || echo "Failed to cd or pull in $PROJECTS_DIR/my-actual-project"'
alias pullrepo='(cd "$PROJECTS_DIR/REPO" && git pull) || echo "Failed to cd to $PROJECTS_DIR/REPO or pull"'
alias pushrepo='(cd "$PROJECTS_DIR/REPO" && git push) || echo "Failed to cd to $PROJECTS_DIR/REPO or push"'
# Update system
alias update='sudo apt update && sudo apt full-upgrade -y && sudo apt autoremove -y && sudo apt clean && echo "System update process completed."'
# Check for listening ports
alias listports='sudo ss -tulnp'
#4. systemd-user SSH Agent Service (User)
Create ~/.config/systemd/user/ssh-agent.service
:
[Unit]
Description=SSH Agent per user
After=network.target
[Service]
Type=forking
Environment=SSH_AUTH_SOCK=%t/ssh-agent.sock
ExecStart=/usr/bin/ssh-agent -a $SSH_AUTH_SOCK
[Install]
WantedBy=default.target
Enable and start:
systemctl --user daemon-reload
systemctl --user enable ssh-agent.service
systemctl --user start ssh-agent.service
Verify:
systemctl --user status ssh-agent.service
ls -l "$XDG_RUNTIME_DIR/ssh-agent.sock"
ssh-add -l
#5. Common SSH Use Cases
- Passwordless login: Key-based server access.
- Git over SSH: Seamless
git clone/push/pull
. - Agent forwarding: Secure multi-hop SSH.
- Hardware tokens: GNOME Keyring integration.
#6. Verification Checklist
go version
rustc --version
bash --login -ic 'echo interactive'
ssh-add -l
#installing the necessary dependencies
This comprehensive guide will walk you through installing and configuring every dependency and necessity to fully implement the features of your provided .bashrc
configuration and SSH setup on a Debian 11 “Bullseye” system. It assumes your root user is root
and your local user is linaro
.
User Account Assumption:
- Root user:
root
- Local user:
linaro
#Prerequisites for linaro
User
Before starting, ensure the linaro
user has sudo
privileges to execute administrative commands. If not, as the root
user, run:
# As root user
usermod -aG sudo linaro
After running this command, linaro
must log out and log back in for the group change to take effect. All commands prefixed with sudo
below should be run by the linaro
user, leveraging these sudo
privileges.
#Part 1: System-Wide Installations and Configurations (executed by linaro
using sudo
)
These steps involve installing packages and setting up system-level configurations.
#1.1. System Update
First, ensure your system’s package list and installed packages are up-to-date:
sudo apt update && sudo apt upgrade -y
- What: Updates the local package lists from repositories and upgrades all currently installed packages to their newest versions.
- Why: Essential for system stability, security, and to ensure compatibility with new software.
- Verification: The commands complete without errors. You can run
sudo apt list --upgradable
afterwards; it should show no or very few packages.
#1.2. Core Utilities and Essential Packages
Install the core utilities and packages mentioned in your script, plus a few others that are implicitly needed or highly recommended for the setup:
sudo apt install -y \
build-essential \
git \
curl \
wget \
unzip \
zip \
bash-completion \
python3-pip \
nodejs \
npm \
libpulse-dev \
flatpak \
swaks \
openssh-client \
iputils-ping \
gnome-keyring \
libnss-myhostname \
dbus-user-session
Let’s break down why each of these is needed:
build-essential
:- What: A meta-package that installs GCC (C compiler),
make
, and other essential tools for compiling software from source. - Why: Required by Rust’s installation script (
rustup
) and potentially for other software you might build. - Verify:
gcc --version
andmake --version
should display their versions.
- What: A meta-package that installs GCC (C compiler),
git
:- What: A distributed version control system.
- Why: Needed for the
pull
andpush
aliases in your.bashrc
(interacting with~/projects/REPO
) and potentially byrustup
. - Verify:
git --version
should display the installed version.
curl
:- What: A command-line tool for transferring data using various network protocols.
- Why: Used to download the Rust installation script (
sh.rustup.rs
). - Verify:
curl --version
should display its version.
wget
:- What: A command-line tool for downloading files from the web.
- Why: Used to download the Go language tarball.
- Verify:
wget --version
should display its version.
unzip
&zip
:- What: Utilities for decompressing and creating ZIP archives, respectively.
- Why: General-purpose utilities useful for managing compressed files.
- Verify:
unzip -v
andzip -v
should display their versions.
bash-completion
:- What: Provides programmable command-line completion for the Bash shell.
- Why: Your
.bashrc
explicitly sources bash completion scripts, enhancing shell interactivity (e.g., pressing Tab to complete commands or options). - Verify: After setting up
.bashrc
and opening a new terminal, typing a command likeapt ins
and pressing Tab should offerinstall
as a suggestion.
python3-pip
:- What: The package installer for Python 3.
- Why: While not directly called by a
.bashrc
function, it’s useful for Python development. Python scripts installed via pip for the user might go into$HOME/.local/bin
, which is added to yourPATH
. - Verify:
pip3 --version
should display its version.
nodejs
&npm
:- What: Node.js is a JavaScript runtime; npm is its package manager.
- Why: Common tools for web development and various JavaScript-based utilities. Not directly used by
.bashrc
but good for a development setup. - Verify:
node --version
andnpm --version
should display their versions.
libpulse-dev
:- What: Development files for PulseAudio, a sound server.
- Why: Often a dependency for desktop applications or development involving audio. Its inclusion might be related to expectations in a desktop environment where GNOME Keyring is also used.
- Verify:
dpkg -s libpulse-dev | grep Status
should show “install ok installed”.
flatpak
:- What: A system for building, distributing, and running sandboxed desktop applications.
- Why: Your
.bashrc
modifiesXDG_DATA_DIRS
to include Flatpak paths, making applications installed via Flatpak discoverable. - Verify:
flatpak --version
should display its version.
swaks
:- What: “Swiss Army Knife for SMTP,” a command-line SMTP testing tool.
- Why: Used by the
Z
alias in your.bashrc
for sending test emails. - Verify:
swaks --version
should display its version.
openssh-client
:- What: Provides SSH client tools like
ssh
,scp
,ssh-agent
,ssh-add
, andssh-keygen
. - Why: Essential for all SSH functionalities: agent management, key generation, connecting to SSH servers, and for the
ssh-add
command in.bashrc
. - Verify:
ssh -V
should display its version.
- What: Provides SSH client tools like
iputils-ping
:- What: Provides the
ping
utility. - Why: Required for the
p
alias in your.bashrc
. - Verify:
ping -V
should display its version (useCtrl+C
to stop if it starts pinging).
- What: Provides the
gnome-keyring
:- What: A daemon that keeps passwords and other secrets for users. It can also manage SSH keys.
- Why: Your
.bashrc
includes a fallback mechanism to usegnome-keyring-daemon
as an SSH agent if aDESKTOP_SESSION
is active. - Verify:
dpkg -s gnome-keyring | grep Status
should show “install ok installed”.
libnss-myhostname
:- What: A plugin for NSS providing hostname resolution for the locally configured system hostname.
- Why: Crucial for the stability of
systemd --user
services, ensuring the local hostname is consistently resolvable, preventing potential issues with services that rely on it, especially in minimal or containerized environments. - Verify:
dpkg -s libnss-myhostname | grep Status
should show “install ok installed”.
dbus-user-session
:- What: Provides D-Bus session management for user sessions, often launched via
systemd --user
. - Why: Essential for proper functioning of the
systemd
user instance (systemd --user
), which manages user-specific services like thessh-agent.service
. It ensures the user’s D-Bus is available, which many modern applications and services rely on, and helps manageXDG_RUNTIME_DIR
. - Verify:
dpkg -s dbus-user-session | grep Status
should show “install ok installed”.
- What: Provides D-Bus session management for user sessions, often launched via
#1.3. Install Go Language (System Part)
This installs Go into /usr/local/go
, accessible by all users. (Assumes linux-amd64
architecture).
# To find the latest Go version, visit https://go.dev/dl/
# As of May 2025, a recent stable version is 1.22.3. Please check for the latest.
GO_VER="1.22.3" # Example: Update this to the latest desired stable version.
GO_ARCH="amd64" # Adjust if your architecture is different (e.g., arm64)
# Download Go binary tarball (as linaro)
wget "https://go.dev/dl/go${GO_VER}.linux-${GO_ARCH}.tar.gz" -P /tmp
# Extract Go to /usr/local (needs sudo)
sudo tar -C /usr/local -xzf "/tmp/go${GO_VER}.linux-${GO_ARCH}.tar.gz"
# Remove the downloaded tarball (as linaro)
rm "/tmp/go${GO_VER}.linux-${GO_ARCH}.tar.gz"
- What: Installs the Go programming language binaries.
- Why: Your
.bashrc
setsGOPATH
and adds/usr/local/go/bin
to thePATH
for using Go commands. - Verification (later, after
.bashrc
is configured):go version
#Part 2: User-Specific Installations and Configurations (as linaro
)
These steps are performed by the linaro
user and configure their specific environment.
#2.1. Create User-Specific Directories
Your .bashrc
and language tools expect certain directories in linaro
’s home.
# For Go development (GOPATH)
mkdir -p "$HOME/go/bin" "$HOME/go/pkg" "$HOME/go/src"
# For XDG Base Directory Specification & systemd user services
mkdir -p "$HOME/.config/systemd/user"
chmod 0700 "$HOME/.config" # Ensure parent .config dir is secure
chmod 0700 "$HOME/.config/systemd"
chmod 0700 "$HOME/.config/systemd/user" # Secure user service definitions
mkdir -p "$HOME/.local/share/flatpak/exports/share" # For user-installed Flatpak data
mkdir -p "$HOME/.local/bin" # For user-specific executables (pip might install here)
# For project alias examples
mkdir -p "$HOME/projects/REPO" # Replace REPO with your actual project name if desired
# You would then 'git init' or 'git clone' into ~/projects/REPO
- What: Creates standard directory structures used by Go, XDG-compliant applications, Flatpak, pip, and your example aliases. Ensures correct permissions for systemd user directories.
- Why: Ensures these tools and configurations function correctly and securely.
- Verification:
ls -ld "$HOME/go"
,stat -c "%a %n" "$HOME/.config/systemd/user"
etc., should show the created directories with appropriate permissions (e.g.,700
for~/.config/systemd/user
).
#2.2. Install Rust Language
Rust is installed per-user using rustup
.
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y
- What: Downloads and runs
rustup-init.sh
, which installsrustup
(the Rust toolchain manager) and the latest stable Rust toolchain (compilerrustc
, package managercargo
, etc.) into$HOME/.cargo
. - Why: Your
.bashrc
sources$HOME/.cargo/env
to add Rust tools to yourPATH
. - Verification (later, after
.bashrc
is configured):rustc --version
andcargo --version
. You might need to source$HOME/.cargo/env
manually for the current session before editing.bashrc
:source "$HOME/.cargo/env"
.
#2.3. Generate SSH Key Pair
If linaro
doesn’t already have an SSH key, generate one. This key (~/.ssh/id_rsa
) will be added to the SSH agent.
# Check if a key already exists
if [ ! -f "$HOME/.ssh/id_rsa" ]; then
echo "SSH key not found. Generating a new one..."
# Generate with a comment including username and hostname (or 'debian' if hostname fails)
ssh-keygen -t rsa -b 4096 -C "linaro@$(hostname || echo debian)"
echo "SSH key generated."
else
echo "SSH key $HOME/.ssh/id_rsa already exists."
fi
# Ensure correct permissions for .ssh directory and its contents
chmod 700 "$HOME/.ssh"
[ -f "$HOME/.ssh/id_rsa" ] && chmod 600 "$HOME/.ssh/id_rsa"
[ -f "$HOME/.ssh/id_rsa.pub" ] && chmod 644 "$HOME/.ssh/id_rsa.pub"
# Apply strict permissions to other common SSH files if they exist
[ -f "$HOME/.ssh/authorized_keys" ] && chmod 600 "$HOME/.ssh/authorized_keys"
[ -f "$HOME/.ssh/known_hosts" ] && chmod 600 "$HOME/.ssh/known_hosts"
[ -f "$HOME/.ssh/config" ] && chmod 600 "$HOME/.ssh/config"
- What:
ssh-keygen
creates a private (id_rsa
) and public (id_rsa.pub
) key pair. - Why: The private key is used for authenticating to SSH servers (e.g., for passwordless login, Git operations). The
.bashrc
script attempts tossh-add ~/.ssh/id_rsa
. - During generation: You’ll be asked for a file to save the key (press Enter for default) and a passphrase (optional, but highly recommended for security). The SSH agent will help manage this passphrase so you don’t have to type it repeatedly.
- Verification:
ls -al "$HOME/.ssh/id_rsa"
should show the private key file with600
permissions.
#2.4. Configure ~/.bash_profile
This file ensures .bashrc
is loaded for interactive login shells (e.g., when you SSH into the linaro
account or log in on the console).
cat << 'EOF' > "$HOME/.bash_profile"
# Source ~/.bashrc for interactive login shells
# Check if running interactively and if .bashrc exists
if [[ $- == *i* && -f "$HOME/.bashrc" ]]; then
source "$HOME/.bashrc"
fi
# Fallback PATH adjustments (though .bashrc should handle these comprehensively)
# This ensures .local/bin and .cargo/bin are in PATH even if .bashrc is minimal.
_add_to_path_if_missing() {
if [ -d "$1" ]; then
case ":$PATH:" in
*":$1:"*) :;; # Already in PATH
*) PATH="$1:$PATH" ;; # Prepend
esac
fi
}
_add_to_path_if_missing "$HOME/.local/bin"
_add_to_path_if_missing "$HOME/.cargo/bin" # Rustup typically handles this via .profile modification too
unset _add_to_path_if_missing
export PATH
EOF
- What: Configures Bash to source
~/.bashrc
upon login. - Why: Makes your aliases, PATH settings, and other
.bashrc
configurations available immediately after logging in. - Verification (later, after full setup):
bash --login -ic 'type ll'
should show thatll
is an alias.
#2.5. Configure ~/.bashrc
Create or replace ~/.bashrc
with your provided configuration.
Important: Review the aliases section and replace placeholders.
cat << 'EOF' > "$HOME/.bashrc"
# 1. Exit if not interactive
case "$-" in *i*) ;; *) return;; esac
# 2. History
HISTCONTROL=ignoreboth # space-prefixed commands and duplicates are not saved
shopt -s histappend # Append to history file, don't overwrite
HISTSIZE=5000 # Number of commands to keep in memory
HISTFILESIZE=10000 # Number of commands to keep in the history file
# Save history after each command and reload it to make it available across terminals.
# `history -a` appends the current session's history to HISTFILE.
# `PROMPT_COMMAND="history -a; ${PROMPT_COMMAND}"` ensures this happens before each prompt.
# Rely on histappend for merging on shell exit.
PROMPT_COMMAND="history -a; ${PROMPT_COMMAND}"
# 3. XDG directories
export XDG_CONFIG_HOME="${XDG_CONFIG_HOME:-$HOME/.config}"
export XDG_CACHE_HOME="${XDG_CACHE_HOME:-$HOME/.cache}"
export XDG_DATA_HOME="${XDG_DATA_HOME:-$HOME/.local/share}"
# Ensure critical XDG directories exist
mkdir -p "$XDG_CONFIG_HOME" "$XDG_CACHE_HOME" "$XDG_DATA_HOME"
# Append Flatpak XDG data dirs to the system default XDG_DATA_DIRS
_FLATPAK_USER_DATA_DIR="$XDG_DATA_HOME/flatpak/exports/share"
_FLATPAK_SYSTEM_DATA_DIR="/var/lib/flatpak/exports/share"
_SYSTEM_XDG_DATA_DIRS="${XDG_DATA_DIRS:-/usr/local/share/:/usr/share/}"
export XDG_DATA_DIRS="${_FLATPAK_USER_DATA_DIR}:${_FLATPAK_SYSTEM_DATA_DIR}:${_SYSTEM_XDG_DATA_DIRS}"
# Clean up temporary variables
unset _FLATPAK_USER_DATA_DIR _FLATPAK_SYSTEM_DATA_DIR _SYSTEM_XDG_DATA_DIRS
# XDG_RUNTIME_DIR is critical and typically set by pam_systemd.
# If it's not set, it indicates a problem with the system's session management (e.g., pam_systemd).
# Do not attempt to set it manually to a /tmp path here as it can cause issues.
if [ -z "$XDG_RUNTIME_DIR" ]; then
# Log an error or warning if preferred, but avoid setting a non-standard fallback
# echo "Warning: XDG_RUNTIME_DIR is not set. User services may not function correctly." >&2
: # No action, rely on system setup
else
export XDG_RUNTIME_DIR # Ensure it's exported if set by pam_systemd
fi
# 4. PATH updates
export GOPATH="$HOME/go"
_add_to_path_if_missing() {
local dir_to_add="$1"
local prepend="$2" # "prepend" or "append"
if [ -d "$dir_to_add" ]; then
case ":$PATH:" in
*":$dir_to_add:"*) :;; # Already in PATH
*) if [ "$prepend" = "prepend" ]; then
PATH="$dir_to_add:$PATH" # Prepend for higher priority
else
PATH="$PATH:$dir_to_add" # Append
fi
;;
esac
fi
}
_add_to_path_if_missing "/usr/local/go/bin" "prepend" # Go system binaries
_add_to_path_if_missing "$GOPATH/bin" "prepend" # User-installed Go binaries
_add_to_path_if_missing "$HOME/.local/bin" "prepend" # User-local pip installs, etc.
# Rust path is handled by sourcing .cargo/env, which also prepends.
unset _add_to_path_if_missing
export PATH
# 5. Rust environment
[ -f "$HOME/.cargo/env" ] && source "$HOME/.cargo/env"
# 6. Bash completion
if ! shopt -oq posix; then
if [ -f /usr/share/bash-completion/bash_completion ]; then
source /usr/share/bash-completion/bash_completion
elif [ -f /etc/bash_completion ]; then
source /etc/bash_completion
fi
fi
# 7. SSH agent: Prioritize systemd-user, then GNOME Keyring if in desktop session
# This logic determines which SSH_AUTH_SOCK to use.
# Path for the systemd user ssh-agent socket
_SYSTEMD_SSH_AGENT_SOCK="$XDG_RUNTIME_DIR/ssh-agent.sock"
if [ -n "$XDG_RUNTIME_DIR" ] && [ -S "$_SYSTEMD_SSH_AGENT_SOCK" ]; then
# systemd user agent socket exists, use it.
export SSH_AUTH_SOCK="$_SYSTEMD_SSH_AGENT_SOCK"
elif [ -n "$DESKTOP_SESSION" ] && command -v gnome-keyring-daemon >/dev/null; then
# No systemd user agent socket found (or XDG_RUNTIME_DIR not set),
# but in a desktop session. Attempt to use/start GNOME Keyring.
# GNOME Keyring might already be running via its own systemd user service or XDG autostart.
# This eval will set SSH_AUTH_SOCK if gnome-keyring-daemon starts/is running and manages SSH.
eval "$(gnome-keyring-daemon --start --components=secrets,ssh)"
export SSH_AUTH_SOCK # Ensure it's exported from eval
fi
unset _SYSTEMD_SSH_AGENT_SOCK
# Attempt to add default SSH key (id_rsa) if an agent is running and has no keys.
if command -v ssh-add >/dev/null; then
if ! ssh-add -l &>/dev/null; then # Check if agent has ANY keys
if [ -n "${SSH_AUTH_SOCK}" ] && [ -S "${SSH_AUTH_SOCK}" ] && [ -f "$HOME/.ssh/id_rsa" ]; then
# Agent seems to be running (socket exists), but no keys listed. Add id_rsa.
# Suppress errors (e.g., passphrase needed but no tty, or key already added by another mechanism).
ssh-add "$HOME/.ssh/id_rsa" 2>/dev/null || true
fi
fi
fi
# 9. Prompt
if [[ "${EUID}" == "0" ]]; then # Root prompt
PS1='\[\033[01;31m\]\h\[\033[01;34m\] \W \$\[\033[00m\] '
else # User prompt
PS1='\[\033[01;32m\]\u@\h\[\033[00m\]:\[\033[01;34m\]\w\[\033[00m\]\$ '
fi
# 10. Aliases (!!! REVIEW AND REPLACE PLACEHOLDERS !!!)
alias ls='ls --color=auto -hF' # Added -h for human-readable sizes, -F for type indicators
alias ll='ls -alFh' # Added -h
alias la='ls -Ah' # Added -h
alias l='ls -CFh' # Added -h
alias grep='grep --color=auto'
alias egrep='egrep --color=auto'
alias fgrep='fgrep --color=auto'
# Example ping alias (uses default system ping)
alias p='ping -c 4 example.com' # Pings example.com 4 times
# Swaks alias for email testing
# !!! REPLACE with your actual email, app password, and possibly SMTP server !!!
# For Gmail, you'll need an "App Password". See Google's help documentation.
# alias Z='swaks -4 -tls -f you@gmail.com -t recipient@example.com -s smtp.gmail.com:587 -au you@gmail.com -ap YOUR_GMAIL_APP_PASSWORD -d'
alias Z='echo "Swaks alias Z not configured. Edit ~/.bashrc with your email details and an App Password for services like Gmail."'
# Git project aliases
# !!! REPLACE 'REPO' with your actual repository directory name if different !!!
# And ensure ~/projects/REPO is a git repository.
PROJECTS_DIR="$HOME/projects"
# Example: alias project1-pull='(cd "$PROJECTS_DIR/my-actual-project" && git pull) || echo "Failed to cd or pull in $PROJECTS_DIR/my-actual-project"'
alias pullrepo='(cd "$PROJECTS_DIR/REPO" && git pull) || echo "Failed to cd to $PROJECTS_DIR/REPO or pull"'
alias pushrepo='(cd "$PROJECTS_DIR/REPO" && git push) || echo "Failed to cd to $PROJECTS_DIR/REPO or push"'
# Update system
alias update='sudo apt update && sudo apt full-upgrade -y && sudo apt autoremove -y && sudo apt clean && echo "System update process completed."'
# Check for listening ports
alias listports='sudo ss -tulnp'
EOF
Key points about this revised .bashrc
:
- Placeholders in Aliases: Critical for
Z
(swaks) andpullrepo
/pushrepo
. - History: Uses
PROMPT_COMMAND="history -a; ${PROMPT_COMMAND}"
for immediate availability of commands in other terminals, withshopt -s histappend
for merging on exit. - XDG Directories: Uses standard defaults if variables are unset. Avoids risky
XDG_RUNTIME_DIR
fallback. - PATH Management: Robustly adds paths, prepending for priority.
- SSH Agent Logic: Clearly prioritizes the
systemd-user
agent. If its socket$XDG_RUNTIME_DIR/ssh-agent.sock
exists, it’s used. Otherwise, if in aDESKTOP_SESSION
, it attempts to use/startgnome-keyring-daemon
. Then, it tries to add~/.ssh/id_rsa
if an agent is active but has no keys. - Prompt: Colored prompt, different for
root
and regular users. - Aliases: Minor improvements like
-h
for human-readable sizes inls
.
Apply .bashrc
changes:
For the current terminal session, source it:
source "$HOME/.bashrc"
New terminals will load it automatically.
#2.6. Configure systemd-user
SSH Agent Service
This creates a service that automatically starts ssh-agent
for the linaro
user upon login.
Create the service file ~/.config/systemd/user/ssh-agent.service
:
(Ensure ~/.config/systemd/user
exists and has 0700
permissions from step 2.1).
cat << 'EOF' > "$HOME/.config/systemd/user/ssh-agent.service"
[Unit]
Description=SSH Authentication Agent for User Session
# This service should start early if it's going to be used.
# .bashrc will connect to the socket if this service is running.
# It doesn't need to be a hard requirement for default.target if SSH isn't always used
# or if another agent (like GNOME Keyring) is preferred in some sessions.
Documentation=man:ssh-agent(1)
Before=default.target
# Requires XDG_RUNTIME_DIR to be available and the user session to be set up.
After=network.target systemd-user-sessions.service user@$(id -u).service
[Service]
Type=forking
# The Environment variable defines the socket path for *this* ssh-agent instance.
# %t expands to the XDG_RUNTIME_DIR path (e.g., /run/user/1000).
Environment=SSH_AUTH_SOCK=%t/ssh-agent.sock
# ssh-agent with -a creates the socket and forks into the background.
ExecStart=/usr/bin/ssh-agent -a %t/ssh-agent.sock
# Restart=always # Optional: uncomment if you want it to try restarting on failure.
[Install]
WantedBy=default.target
EOF
Enable and start the service:
systemctl --user daemon-reload
systemctl --user enable ssh-agent.service
systemctl --user start ssh-agent.service # Or restart if it was already running: systemctl --user restart ssh-agent.service
- What:
ssh-agent.service
defines howsystemd
managesssh-agent
for userlinaro
. - Why: Provides a reliable, auto-starting SSH agent managed by
systemd
, independent of graphical sessions (unless GNOME Keyring takes precedence as configured in.bashrc
). - Verification (after starting):
systemctl --user status ssh-agent.service # Look for "active (running)" ls -al "$XDG_RUNTIME_DIR/ssh-agent.sock" # Should show the socket file, e.g., srw------- 1 linaro linaro 0 May 8 12:34 /run/user/1000/ssh-agent.sock ssh-add -l # If the .bashrc logic has run and added the key: # Should list your ~/.ssh/id_rsa key or state "The agent has no identities." if .bashrc hasn't run yet in a new shell # or if the key requires a passphrase that hasn't been entered.
#Part 3: Verification Checklist
After completing all steps, and ideally after logging out and logging back in (or rebooting) to ensure all services and profile scripts are loaded correctly:
- Go Version:
go version
- Expected:
go version goX.Y.Z linux/amd64
(your chosen version).
- Expected:
- Rust Version:
rustc --version cargo --version
- Expected: Shows versions like
rustc x.y.z ...
andcargo x.y.z ...
.
- Expected: Shows versions like
- Bash Login Shell &
.bashrc
Sourcing:bash --login -ic 'type ll && echo SSH_AUTH_SOCK is $SSH_AUTH_SOCK'
- Expected:
ll is an alias for ls -alFh
SSH_AUTH_SOCK is /run/user/$(id -u linaro)/ssh-agent.sock
(or a GNOME Keyring path if in a desktop session and it took over).
- Expected:
- SSH Agent Status:
ssh-add -l
- Expected: Lists your
~/.ssh/id_rsa
key (e.g.,4096 SHA256:... linaro@hostname (RSA)
). - If it says “The agent has no identities.” try opening a new terminal. If your key has a passphrase, the
ssh-add
in.bashrc
(if the terminal is interactive and TTY is available) or the first attempt to use the key (e.g.,ssh somehost
) should prompt for it. Once entered, the agent remembers it for the session (or longer if integrated with GNOME Keyring and configured to do so).
- Expected: Lists your
XDG_RUNTIME_DIR
:echo "$XDG_RUNTIME_DIR" stat -c "Permissions: %a, Path: %n" "$XDG_RUNTIME_DIR"
- Expected: A path like
/run/user/1000
(where 1000 islinaro
’s UID). Permissions should be700
(drwx——). If empty or permissions are wrong,systemd-user
services and other applications might fail. This is normally set up bypam_systemd
.
- Expected: A path like
- Aliases:
Test your aliases:
ll # Should list files with details p # Should attempt to ping example.com # Z # Test after configuring with your email details # pullrepo # Test after setting up ~/projects/REPO
#Part 4: Understanding Key Features and Use Cases
- SSH Agent (systemd-user vs. GNOME Keyring):
- Your setup prioritizes the
systemd-user ssh-agent.service
. The socket for this is$XDG_RUNTIME_DIR/ssh-agent.sock
. - If this systemd agent socket isn’t found AND you log into a desktop environment (where
DESKTOP_SESSION
is set), the.bashrc
allowsgnome-keyring-daemon
to be used for SSH agent functions. GNOME Keyring is often auto-started by the desktop environment (e.g., via its own systemd user service or XDG autostart) and can integrate well with desktop login, potentially unlocking your SSH key automatically. - The
ssh-add ~/.ssh/id_rsa
line in.bashrc
attempts to add your default private key to whichever agent’sSSH_AUTH_SOCK
is currently active.
- Your setup prioritizes the
- Passwordless SSH Login:
- Generate your key pair (
ssh-keygen
- done). - Ensure
ssh-agent
is running and has your key added (ssh-add -l
to check - handled by.bashrc
and systemd service). - Copy your public key to the remote server:
ssh-copy-id user@remote_host
. - Now
ssh user@remote_host
should log you in without a password (it uses the key from the agent). If your key has a passphrase, the agent will prompt for it once per session (or as configured) and then remember it.
- Generate your key pair (
- Git over SSH:
- Once your SSH agent is working with your key, Git operations (clone, pull, push) with SSH URLs (e.g.,
git@github.com:user/repo.git
) will automatically use the keys from the agent.
- Once your SSH agent is working with your key, Git operations (clone, pull, push) with SSH URLs (e.g.,
- Agent Forwarding:
- Allows using your local SSH keys on a remote server to connect to another subsequent server, without your private key ever leaving your local machine.
- To use:
ssh -A user@intermediate_host
. Fromintermediate_host
, you can thenssh further_host
. - Security Note: Only use agent forwarding (
-A
orForwardAgent yes
) with trusted intermediate hosts. - Configure per-host in
~/.ssh/config
:Host my_intermediate_server HostName server.example.com User your_user ForwardAgent yes
- Hardware Tokens (e.g., YubiKey for SSH):
- GNOME Keyring might offer some integration for PKCS#11 devices if supported by your desktop environment.
- For direct control, typically packages like
opensc-pkcs11
are installed, and the SSH client is configured to use the hardware token via its PKCS#11 library (e.g., by settingPKCS11Provider
in~/.ssh/config
or usingssh -I /path/to/lib.so
). This is an advanced setup.
- Flatpak Integration (
XDG_DATA_DIRS
):- Adding Flatpak’s
exports/share
directories toXDG_DATA_DIRS
helps your shell and desktop environment discover application metadata (like.desktop
files) for Flatpak applications.
- Adding Flatpak’s
swaks
Alias (Z
):- This alias is a template for sending test emails. You must configure it with your sender email, recipient, SMTP server details, and an App Password if using services like Gmail with 2-Step Verification.