Tuesday, January 13, 2026

Advanced DevOps Topics Guide - Environment Variables, SSH, Remote Management

Advanced DevOps Topics Guide - Environment Variables, SSH, Remote Management

Advanced DevOps Topics Guide

Published: December 2025 | Topic: Environment Variables, SSH, Remote Management & Configuration

Mastering these advanced topics separates junior from senior DevOps engineers. Environment management, secure remote access, efficient file transfer, terminal multiplexing, and configuration management preparation are essential skills for modern infrastructure management.

1. Environment Variables & Profiles

Understanding Shell Startup Files

Shell Startup File Loading Sequence

Login Shell:
/etc/profile → ~/.bash_profile → ~/.bashrc → ~/.profile
Non-Login Shell:
~/.bashrc
Interactive Shell:
~/.bashrc

Global Configuration Files

# System-wide environment variables:
/etc/environment # Simple KEY=value pairs
/etc/profile # System-wide profile (Bash)
/etc/profile.d/ # Directory for scripts
/etc/bash.bashrc # System-wide .bashrc

# Example: /etc/profile.d/custom.sh
export PATH="$PATH:/opt/myapp/bin"
export EDITOR=vim
umask 022

User Configuration Files

# User-specific files (in home directory):
~/.bash_profile # Login shell (Bash)
~/.profile # Login shell (POSIX)
~/.bashrc # Interactive shell (Bash)
~/.bash_logout # Logout actions
~/.bash_aliases # Aliases only
~/.bash_functions # Functions only

# Best practice structure:
# ~/.bash_profile:
[[ -f ~/.bashrc ]] && . ~/.bashrc
[[ -f ~/.profile ]] && . ~/.profile

Environment Variable Management

Setting & Managing Variables

# Set environment variables:
$ export VARNAME="value" # Current shell
$ VARNAME="value" # Current shell only

# View environment variables:
$ env # All environment vars
$ printenv # All environment vars
$ echo $PATH # Single variable
$ printenv PATH # Single variable

# Remove environment variable:
$ unset VARNAME

# Set for single command:
$ VARNAME="value" command args
$ env VARNAME="value" command

Common Environment Variables

# System information:
HOME=/home/username # Home directory
USER=username # Current user
SHELL=/bin/bash # Current shell
PWD=/current/path # Present working directory
OLDPWD=/previous/path # Previous directory

# Application configuration:
PATH=/usr/bin:/usr/local/bin
EDITOR=vim # Default editor
VISUAL=vim # Visual editor
PAGER=less # Pager program

# Language/Regional:
LANG=en_US.UTF-8 # System language
LC_ALL=en_US.UTF-8 # Override all locale
TZ=America/New_York # Timezone

Advanced Profile Management

Professional .bashrc Configuration

# ~/.bashrc - Professional configuration

# If not running interactively, don't do anything
[[ $- != *i* ]] && return

# Load aliases if they exist
[[ -f ~/.bash_aliases ]] && source ~/.bash_aliases

# Load functions if they exist
[[ -f ~/.bash_functions ]] && source ~/.bash_functions

# History configuration
HISTSIZE=10000
HISTFILESIZE=20000
HISTCONTROL=ignoreboth:erasedups
HISTTIMEFORMAT="%F %T "
shopt -s histappend

# Check window size and update if necessary
shopt -s checkwinsize

# Color support
if [ -x /usr/bin/dircolors ]; then
    test -r ~/.dircolors && eval "$(dircolors -b ~/.dircolors)" || eval "$(dircolors -b)"
    alias ls='ls --color=auto'
    alias grep='grep --color=auto'
    alias fgrep='fgrep --color=auto'
    alias egrep='egrep --color=auto'
fi

# Custom prompt
PS1='\[\033[01;32m\]\u@\h\[\033[00m\]:\[\033[01;34m\]\w\[\033[00m\]\$ '

# Environment variables
export EDITOR=vim
export VISUAL=vim
export PAGER='less -R'
export PATH="$PATH:$HOME/bin:$HOME/.local/bin"

# Python virtualenv
export WORKON_HOME=$HOME/.virtualenvs
export VIRTUALENVWRAPPER_PYTHON=/usr/bin/python3

# Docker configuration
export DOCKER_BUILDKIT=1
export COMPOSE_DOCKER_CLI_BUILD=1

# Application-specific variables
export AWS_DEFAULT_REGION=us-east-1
export KUBECONFIG=$HOME/.kube/config
export GOPATH=$HOME/go
export PATH="$PATH:$GOPATH/bin"

# Aliases for productivity
alias ll='ls -alF'
alias la='ls -A'
alias l='ls -CF'
alias ..='cd ..'
alias ...='cd ../..'
alias grep='grep --color=auto'
alias df='df -h'
alias du='du -h'
alias free='free -m'
alias psg='ps aux | grep'
alias hg='history | grep'
alias mkdir='mkdir -p'

# Git aliases
alias gs='git status'
alias ga='git add'
alias gc='git commit'
alias gp='git push'
alias gl='git log --oneline --graph --all'
alias gco='git checkout'

# Safety features
alias rm='rm -i'
alias cp='cp -i'
alias mv='mv -i'

# Source completion scripts
[[ -f /etc/bash_completion ]] && source /etc/bash_completion
[[ -f /usr/share/bash-completion/bash_completion ]] && \
    source /usr/share/bash-completion/bash_completion

# Kubernetes completion
[[ $(command -v kubectl) ]] && source <(kubectl completion bash)

# Docker completion
[[ -f /usr/share/bash-completion/completions/docker ]] && \
    source /usr/share/bash-completion/completions/docker

# Custom functions
mkcd() { mkdir -p "$1" && cd "$1"; }
extract() {
    if [ -f "$1" ]; then
        case "$1" in
            *.tar.bz2) tar xvjf "$1" ;;
            *.tar.gz) tar xvzf "$1" ;;
            *.bz2) bunzip2 "$1" ;;
            *.rar) unrar x "$1" ;;
            *.gz) gunzip "$1" ;;
            *.tar) tar xvf "$1" ;;
            *.tbz2) tar xvjf "$1" ;;
            *.tgz) tar xvzf "$1" ;;
            *.zip) unzip "$1" ;;
            *.Z) uncompress "$1" ;;
            *.7z) 7z x "$1" ;;
            *) echo "'$1' cannot be extracted" ;;
        esac
    else
        echo "'$1' is not a valid file"
    fi
}

Dotfiles Management

# Version control for dotfiles (using Git):
$ mkdir ~/.dotfiles
$ cd ~/.dotfiles
$ git init

# Create symlinks to home directory:
$ ln -sf ~/.dotfiles/.bashrc ~/.bashrc
$ ln -sf ~/.dotfiles/.vimrc ~/.vimrc
$ ln -sf ~/.dotfiles/.gitconfig ~/.gitconfig

# Automate with script:
#!/bin/bash
DOTFILES_DIR="$HOME/.dotfiles"

for file in .bashrc .vimrc .gitconfig .tmux.conf; do
    if [[ -f "$DOTFILES_DIR/$file" ]]; then
        ln -sf "$DOTFILES_DIR/$file" "$HOME/$file"
    fi
done

# Use existing dotfiles managers:
# - chezmoi (https://www.chezmoi.io/)
# - yadm (https://yadm.io/)
# - stow (GNU Stow)

2. SSH Keys & Key-based Authentication

SSH Key Fundamentals

SSH Key Authentication Flow

1. Client generates key pair (public/private)
2. Public key copied to server's ~/.ssh/authorized_keys
3. Client connects to server with private key
4. Server verifies with public key
5. Access granted without password

Key Types & Generation

RSA

$ ssh-keygen -t rsa -b 4096
# Legacy, widely supported
# Minimum 2048 bits recommended

Ed25519

$ ssh-keygen -t ed25519
# Modern, secure, efficient
# 256-bit equivalent security

ECDSA

$ ssh-keygen -t ecdsa -b 521
# Elliptic curve variant
# Smaller keys, good performance

Complete SSH Key Workflow

Key Generation & Management

# Generate new SSH key:
$ ssh-keygen -t ed25519 -C "your_email@example.com"
# -t: type, -b: bits, -C: comment

# With custom filename:
$ ssh-keygen -t ed25519 -f ~/.ssh/id_ed25519_github

# With passphrase (recommended):
$ ssh-keygen -t ed25519 -f ~/.ssh/id_ed25519

# List keys:
$ ls -la ~/.ssh/
$ ssh-add -l # List loaded keys in agent

# Show public key:
$ cat ~/.ssh/id_ed25519.pub
$ ssh-keygen -y -f ~/.ssh/id_ed25519 # Generate public from private

# Change passphrase:
$ ssh-keygen -p -f ~/.ssh/id_ed25519

SSH Agent & Configuration

# Start SSH agent:
$ eval "$(ssh-agent -s)"

# Add key to agent:
$ ssh-add ~/.ssh/id_ed25519
$ ssh-add -l # Verify key added
$ ssh-add -D # Delete all keys from agent

# Auto-start agent in .bashrc:
if [ -z "$SSH_AUTH_SOCK" ]; then
    eval "$(ssh-agent -s)" > /dev/null
    ssh-add ~/.ssh/id_ed25519 2>/dev/null
fi

# SSH config file: ~/.ssh/config
Host github.com
    HostName github.com
    User git
    IdentityFile ~/.ssh/id_ed25519_github
    IdentitiesOnly yes

Host server1
    HostName 192.168.1.100
    User admin
    Port 2222
    IdentityFile ~/.ssh/id_ed25519

Host *.example.com
    User deploy
    IdentityFile ~/.ssh/deploy_key

Server Configuration & Security

Server-side SSH Configuration

# Install public key on server:
$ ssh-copy-id -i ~/.ssh/id_ed25519.pub user@server
# Or manually:
$ cat ~/.ssh/id_ed25519.pub | ssh user@server "mkdir -p ~/.ssh && cat >> ~/.ssh/authorized_keys"

# Secure authorized_keys permissions:
$ chmod 700 ~/.ssh
$ chmod 600 ~/.ssh/authorized_keys

# Server SSH config: /etc/ssh/sshd_config
Port 2222 # Change default port
PermitRootLogin no # Disable root login
PasswordAuthentication no # Disable password auth
PubkeyAuthentication yes # Enable key auth
AllowUsers deploy admin # Restrict users
ClientAliveInterval 300 # Keepalive interval
ClientAliveCountMax 2 # Keepalive count
MaxAuthTries 3 # Max authentication attempts

# Apply changes:
$ sudo systemctl reload sshd
$ sudo systemctl restart sshd

Advanced SSH Features

# Port forwarding (tunneling):
$ ssh -L 8080:localhost:80 user@server # Local port forward
$ ssh -R 9090:localhost:80 user@server # Remote port forward
$ ssh -D 1080 user@server # Dynamic SOCKS proxy

# SSH connection sharing:
$ ssh -o ControlMaster=yes -o ControlPath=~/.ssh/%r@%h:%p user@server
$ ssh -o ControlPath=~/.ssh/%r@%h:%p user@server # Reuse connection

# Execute remote commands:
$ ssh user@server "ls -la"
$ ssh user@server 'bash -s' < local_script.sh

# Copy files using SSH:
$ ssh user@server "cat /path/remote/file" > local/file
$ cat local/file | ssh user@server "cat > /path/remote/file"

# SSH escape sequences:
# ~? - Show escape sequences
# ~. - Disconnect
# ~^Z - Suspend SSH
# ~# - List forwarded connections

3. Managing Remote Servers

Remote Server Management Tools

Basic Remote Operations

# Connect to remote server:
$ ssh user@hostname
$ ssh -p 2222 user@hostname # Custom port
$ ssh -i ~/.ssh/key.pem user@hostname # Specific key

# Execute remote commands:
$ ssh user@hostname "ls -la /var/log"
$ ssh user@hostname "sudo systemctl status nginx"

# Multiple commands:
$ ssh user@hostname "cd /opt/app && git pull && npm install"

# Remote script execution:
$ cat local_script.sh | ssh user@hostname 'bash -s'
$ ssh user@hostname 'bash -s' < local_script.sh

# With variables:
$ VERSION="2.0.1"
$ ssh user@hostname "cd /opt/app && git checkout tags/v$VERSION"

Parallel Execution with pssh

# Install parallel SSH tools:
$ sudo apt install pssh # Debian/Ubuntu
$ sudo yum install pssh # RHEL/CentOS

# Create host file:
$ cat > hosts.txt << EOF
user@server1:2222
user@server2
user@server3
EOF

# Execute on all servers:
$ pssh -h hosts.txt -i "uptime"
$ pssh -h hosts.txt -i "sudo apt update && sudo apt upgrade -y"

# Copy files to all servers:
$ pscp -h hosts.txt local_file /remote/path/

# Alternative: GNU Parallel
$ cat servers.txt | parallel ssh {} "hostname"

Bulk Server Management

Automated Server Management Script

#!/bin/bash
# server_manager.sh - Manage multiple servers

SERVER_LIST=(
    "user@server1.example.com"
    "user@server2.example.com"
    "user@server3.example.com"
    "user@server4.example.com"
)

SSH_OPTIONS="-o ConnectTimeout=10 -o BatchMode=yes -o StrictHostKeyChecking=no"
LOG_FILE="/tmp/server_management_$(date +%Y%m%d_%H%M%S).log"

execute_on_all() {
    local command="$1"
    
    echo "Executing: $command" | tee -a "$LOG_FILE"
    echo "================================" | tee -a "$LOG_FILE"
    
    for server in "${SERVER_LIST[@]}"; do
        local host="${server%@*}"
        local user="${server#*@}"
        
        echo -n "$server: " | tee -a "$LOG_FILE"
        
        if ssh $SSH_OPTIONS "$server" "$command" 2>&1 | tee -a "$LOG_FILE"; then
            echo "✓ Success" | tee -a "$LOG_FILE"
        else
            echo "✗ Failed" | tee -a "$LOG_FILE"
        fi
    done
}

check_server_health() {
    echo "Checking server health..." | tee -a "$LOG_FILE"
    
    for server in "${SERVER_LIST[@]}"; do
        echo "--- $server ---" | tee -a "$LOG_FILE"
        
        # Check disk space
        ssh $SSH_OPTIONS "$server" "df -h /" | tee -a "$LOG_FILE"
        
        # Check memory
        ssh $SSH_OPTIONS "$server" "free -m" | tee -a "$LOG_FILE"
        
        # Check load average
        ssh $SSH_OPTIONS "$server" "uptime" | tee -a "$LOG_FILE"
        
        # Check service status
        ssh $SSH_OPTIONS "$server" "systemctl status nginx docker --no-pager 2>/dev/null || true" | tee -a "$LOG_FILE"
    done
}

deploy_application() {
    local version="$1"
    local artifact="app-$version.tar.gz"
    
    echo "Deploying version $version..." | tee -a "$LOG_FILE"
    
    for server in "${SERVER_LIST[@]}"; do
        echo "Deploying to $server" | tee -a "$LOG_FILE"
        
        # Copy artifact
        scp "$artifact" "$server:/tmp/"
        
        # Deploy commands
        ssh $SSH_OPTIONS "$server" "
            cd /opt/app && \\
            tar xzf /tmp/$artifact && \\
            chown -R appuser:appuser . && \\
            systemctl restart app.service
        "
| tee -a "$LOG_FILE"
    done
}

main() {
    case "$1" in
        health)
            check_server_health
            ;;
        deploy)
            deploy_application "$2"
            ;;
        cmd)
            execute_on_all "$2"
            ;;
        *)
            echo "Usage: $0 {health|deploy|cmd}"
            exit 1
        ;;
    esac
}

main "$@"

4. File Transfer Automation

SCP - Secure Copy Protocol

Basic SCP Operations

# Copy file to remote server:
$ scp file.txt user@server:/remote/path/
$ scp -P 2222 file.txt user@server:/path/ # Custom port
$ scp -i ~/.ssh/key.pem file.txt user@server:/path/

# Copy file from remote server:
$ scp user@server:/remote/file.txt /local/path/
$ scp user@server:/home/user/*.log /local/path/

# Copy directory recursively:
$ scp -r /local/directory user@server:/remote/path/
$ scp -r user@server:/remote/directory /local/path/

# Preserve file attributes:
$ scp -p file.txt user@server:/path/ # Preserve timestamps

# Limit bandwidth:
$ scp -l 1000 file.txt user@server:/path/ # 1000 Kbit/s

# Verbose output:
$ scp -v file.txt user@server:/path/ # Debug information

Advanced SCP Usage

# Copy between two remote servers:
$ scp user1@server1:/path/file.txt user2@server2:/path/

# Use wildcards:
$ scp user@server:/path/*.log /local/path/
$ scp user@server:/path/log_*.tar.gz /local/path/

# Exclude files:
$ scp -r --exclude="*.tmp" --exclude=".git" /local/dir user@server:/path/

# Use compression:
$ scp -C file.txt user@server:/path/ # Compress during transfer

# SSH config integration:
$ scp file.txt myserver:/path/ # Uses ~/.ssh/config

# Background transfer:
$ scp -q largefile.tar.gz user@server:/path/ &

# Check file before copying:
$ ssh user@server "ls -la /path/" && scp file.txt user@server:/path/

rsync - Advanced File Synchronization

Why rsync is better than scp for large transfers:

  • Incremental transfer: Only transfers changed parts of files
  • Resumable transfers: Can continue interrupted transfers
  • Compression: Efficient compression during transfer
  • Preservation: Preserves permissions, timestamps, symlinks
  • Dry-run capability: Preview changes without making them
  • Exclusion patterns: Flexible file filtering

Basic rsync Operations

# Local to local copy:
$ rsync -av /source/ /destination/ # Archive, verbose
$ rsync -av /source/ /destination/ --delete # Delete extras

# Local to remote:
$ rsync -avz /local/path/ user@server:/remote/path/ # Compress
$ rsync -avz -e "ssh -p 2222" /local/path/ user@server:/remote/path/

# Remote to local:
$ rsync -avz user@server:/remote/path/ /local/path/

# Remote to remote:
$ rsync -avz user1@server1:/path/ user2@server2:/path/

# Common options:
# -a: archive mode (preserves everything)
# -v: verbose
# -z: compress during transfer
# -P: show progress, resume partial files
# -h: human-readable numbers
# --delete: delete extraneous files
# --exclude: exclude patterns
# --include: include patterns
# --stats: show transfer statistics

Advanced rsync Patterns

# Dry run (simulation):
$ rsync -avn /source/ /destination/ # -n = dry run

# Exclude files:
$ rsync -av --exclude="*.tmp" --exclude=".git" /source/ user@server:/dest/
$ rsync -av --exclude-from=exclude.txt /source/ user@server:/dest/

# Limit bandwidth:
$ rsync -av --bwlimit=1000 /source/ user@server:/dest/ # KB/s

# Partial transfer with progress:
$ rsync -avzP /source/ user@server:/dest/

# Sync with checksum verification:
$ rsync -avc /source/ /dest/ # -c = checksum

# Update only (skip newer files):
$ rsync -avu /source/ /dest/ # -u = update

# Delete source files after transfer:
$ rsync -av --remove-source-files /source/ user@server:/dest/

# Backup with timestamp:
$ rsync -av --backup --backup-dir=/backups/$(date +%Y%m%d) /source/ /dest/

Automated Backup Script

Production rsync Backup Script

#!/bin/bash
# backup_script.sh - Automated backup with rsync

BACKUP_SOURCE="/data"
BACKUP_DEST="user@backup-server:/backups/"
LOG_FILE="/var/log/backup_$(date +%Y%m%d).log"
EXCLUDE_FILE="/etc/backup_excludes.txt"
RETENTION_DAYS=30

create_exclude_list() {
    cat > "$EXCLUDE_FILE" << EOF
*.tmp
*.log
*.cache
/tmp/*
/cache/*
.git/*
.node_modules/*
__pycache__/*
*.pyc
EOF
}

perform_backup() {
    local timestamp="$(date '+%Y-%m-%d %H:%M:%S')"
    
    echo "[$timestamp] Starting backup..." | tee -a "$LOG_FILE"
    
    # Dry run first
    echo "Performing dry run..." | tee -a "$LOG_FILE"
    rsync -avn \
        --exclude-from="$EXCLUDE_FILE" \
        --delete \
        "$BACKUP_SOURCE" \
        "$BACKUP_DEST/current/" 2>&1 | tee -a "$LOG_FILE"
    
    read -p "Continue with actual backup? (y/N): " -n 1 -r
    echo
    if [[ ! $REPLY =~ ^[Yy]$ ]]; then
        echo "Backup cancelled" | tee -a "$LOG_FILE"
        exit 1
    fi
    
    # Actual backup
    echo "Starting actual backup..." | tee -a "$LOG_FILE"
    
    rsync -avz \
        --exclude-from="$EXCLUDE_FILE" \
        --delete \
        --stats \
        --human-readable \
        --progress \
        "$BACKUP_SOURCE" \
        "$BACKUP_DEST/current/" 2>&1 | tee -a "$LOG_FILE"
    
    timestamp="$(date '+%Y-%m-%d_%H-%M-%S')"
    
    # Create snapshot
    ssh user@backup-server "cp -al /backups/current /backups/snapshot_$timestamp"
    
    echo "Backup completed successfully" | tee -a "$LOG_FILE"
}

cleanup_old_backups() {
    echo "Cleaning up backups older than $RETENTION_DAYS days..." | tee -a "$LOG_FILE"
    
    ssh user@backup-server "find /backups/snapshot_* -maxdepth 0 -type d -mtime +$RETENTION_DAYS -exec rm -rf {} \;"
    
    echo "Cleanup completed" | tee -a "$LOG_FILE"
}

verify_backup() {
    echo "Verifying backup integrity..." | tee -a "$LOG_FILE"
    
    # Generate checksums
    find "$BACKUP_SOURCE" -type f -exec md5sum {} \; > /tmp/local_checksums.txt
    ssh user@backup-server "find /backups/current -type f -exec md5sum {} \;" > /tmp/remote_checksums.txt
    
    # Compare (simplified)
    local local_count="$(wc -l < /tmp/local_checksums.txt)"
    local remote_count="$(wc -l < /tmp/remote_checksums.txt)"
    
    if [[ "$local_count" -eq "$remote_count" ]]; then
        echo "✓ Backup verification passed" | tee -a "$LOG_FILE"
    else
        echo "✗ Backup verification failed" | tee -a "$LOG_FILE"
    fi
}

main() {
    create_exclude_list
    perform_backup
    verify_backup
    cleanup_old_backups
}

main "$@"

5. Using screen and tmux

Screen - Legacy Terminal Multiplexer

Screen Basics

# Start new screen session:
$ screen
$ screen -S session_name # Named session

# Detach from screen:
Ctrl-a d # Detach session
Ctrl-a Ctrl-d # Alternative detach

# List screen sessions:
$ screen -ls
$ screen -list

# Reattach to screen:
$ screen -r
$ screen -r session_name # Specific session
$ screen -x # Attach to running session

# Create new window:
Ctrl-a c # New window

# Navigate windows:
Ctrl-a n # Next window
Ctrl-a p # Previous window
Ctrl-a 0-9 # Window number

# Split screen:
Ctrl-a S # Split horizontally
Ctrl-a | # Split vertically
Ctrl-a Tab # Switch between regions
Ctrl-a Q # Close region

# Other useful commands:
Ctrl-a ? # Show help
Ctrl-a A # Rename window
Ctrl-a k # Kill window
Ctrl-a \ # Kill all windows, exit screen
Ctrl-a [ # Enter copy mode (space to start, enter to copy)

Screen Configuration

# Configuration file: ~/.screenrc

# Status bar:
hardstatus alwayslastline
hardstatus string '%{= kG}[ %{G}%H %{g}][%= %{= kw}%?%-Lw%?%{r}(%{W}%n*%f%t%?(%u)%?%{r})%{w}%?%+Lw%?%?%= %{g}][%{B} %m-%d %{W}%c %{g}]'

# Startup message:
startup_message off

# Visual bell:
vbell off

# Scrollback buffer:
defscrollback 10000

# Mouse support:
termcapinfo xterm* ti@:te@

# Bind keys:
bindkey -k k1 select 1 # F1 to select window 1
bindkey -k k2 select 2 # F2 to select window 2

# Screen session with logging:
$ screen -L -S mysession # Enable logging
$ screen -L -Logfile /path/to/logfile -S session

tmux - Modern Terminal Multiplexer

Why tmux is preferred over screen:

  • Modern architecture: Client-server model
  • Better pane management: More intuitive splits
  • Scriptable: Can be controlled programmatically
  • Status bar: Highly customizable
  • Copy mode: Vi/Emacs keybindings
  • Plugin ecosystem: Extensive plugin support

tmux Basics

# Start new tmux session:
$ tmux
$ tmux new -s session_name # Named session

# Detach from tmux:
Ctrl-b d # Detach session

# List sessions:
$ tmux ls
$ tmux list-sessions

# Attach to session:
$ tmux attach -t session_name
$ tmux a -t session_name # Short form

# Kill session:
$ tmux kill-session -t session_name

# Windows:
Ctrl-b c # Create new window
Ctrl-b , # Rename window
Ctrl-b & # Kill window
Ctrl-b 0-9 # Switch to window
Ctrl-b n # Next window
Ctrl-b p # Previous window
Ctrl-b w # Choose window from list

# Panes:
Ctrl-b % # Split vertically
Ctrl-b " # Split horizontally
Ctrl-b arrow # Move between panes
Ctrl-b o # Switch to next pane
Ctrl-b ; # Toggle last pane
Ctrl-b x # Kill pane
Ctrl-b z # Zoom pane (toggle)
Ctrl-b { # Swap pane with previous
Ctrl-b } # Swap pane with next

Advanced tmux Features

# Copy mode (vi keys by default):
Ctrl-b [ # Enter copy mode
Space # Start selection
Enter # Copy selection
Ctrl-b ] # Paste

# Sessions:
Ctrl-b s # Switch sessions
Ctrl-b $ # Rename session

# Resize panes:
Ctrl-b Alt-arrow # Resize pane
Ctrl-b Ctrl-arrow # Resize by 1 cell

# Synchronize panes:
Ctrl-b : setw synchronize-panes # Toggle sync

# Command mode:
Ctrl-b : # Enter command mode

# Reload config:
Ctrl-b : source-file ~/.tmux.conf

# Send keys to all panes:
Ctrl-b : setw synchronize-panes on

# Layouts:
Ctrl-b Space # Cycle layouts
Ctrl-b Alt-1 # Even-horizontal layout
Ctrl-b Alt-2 # Even-vertical layout
Ctrl-b Alt-3 # Main-horizontal layout
Ctrl-b Alt-4 # Main-vertical layout
Ctrl-b Alt-5 # Tiled layout

Professional tmux Configuration

~/.tmux.conf - Professional Configuration

# Set prefix to Ctrl-a (like screen)
unbind C-b
set -g prefix C-a
bind C-a send-prefix

# Mouse support
set -g mouse on

# Set default terminal
set -g default-terminal "screen-256color"
set -as terminal-overrides ',xterm*:Tc:sitm=\E[3m'

# Start window numbering at 1
set -g base-index 1
setw -g pane-base-index 1

# Enable vi keys
setw -g mode-keys vi
bind-key -T copy-mode-vi v send-keys -X begin-selection
bind-key -T copy-mode-vi y send-keys -X copy-selection
bind-key -T copy-mode-vi r send-keys -X rectangle-toggle

# Easy pane resizing
bind -r H resize-pane -L 5
bind -r J resize-pane -D 5
bind -r K resize-pane -U 5
bind -r L resize-pane -R 5

# Quick window selection
bind -r C-h select-window -t :-
bind -r C-l select-window -t :+

# Status bar customization
set -g status-style bg=black,fg=white
set -g status-left-length 50
set -g status-left "#[fg=green]#S #[fg=yellow]#I:#P"
set -g status-right "#[fg=cyan]%Y-%m-%d %H:%M"
set -g status-interval 60

# Window status
setw -g window-status-current-style fg=black,bg=yellow
setw -g window-status-style fg=cyan,bg=black

# Pane border
set -g pane-border-style fg=green
set -g pane-active-border-style fg=white

# Message display time
set -g display-time 4000

# Escape time for faster response
set -sg escape-time 0

# Increase scrollback buffer
set -g history-limit 10000

# Plugins (using tpm - tmux plugin manager)
set -g @plugin 'tmux-plugins/tpm'
set -g @plugin 'tmux-plugins/tmux-sensible'
set -g @plugin 'tmux-plugins/tmux-resurrect'
set -g @plugin 'tmux-plugins/tmux-continuum'
set -g @plugin 'christoomey/vim-tmux-navigator'

# Restore sessions automatically
set -g @continuum-restore 'on'

# Initialize TMUX plugin manager (keep at bottom)
run '~/.tmux/plugins/tpm/tpm'

6. Config Management Preparation

Configuration Management Overview

Configuration Management Tools

Tool Language Approach
Ansible YAML Agentless, push-based
Puppet Ruby DSL Agent-based, pull-based
Chef Ruby Agent-based, pull-based
SaltStack YAML/Python Agent-based, push-based
Terraform HCL Infrastructure as Code

Common Requirements

  • SSH access to managed nodes
  • Python 2.7+ or 3.5+ (for Ansible)
  • Ruby (for Chef/Puppet)
  • Root/sudo privileges
  • Network connectivity
  • Inventory management
  • Version control system

Infrastructure Preparation

Server Standardization

# Create standard user for automation:
$ sudo useradd -m -s /bin/bash ansible
$ sudo usermod -aG sudo ansible # Debian/Ubuntu
$ sudo usermod -aG wheel ansible # RHEL/CentOS

# Set up SSH keys:
$ sudo -u ansible ssh-keygen -t ed25519
$ sudo -u ansible cat ~ansible/.ssh/id_ed25519.pub

# Configure sudo without password:
$ echo "ansible ALL=(ALL) NOPASSWD:ALL" | sudo tee /etc/sudoers.d/ansible

# Standard packages:
$ sudo apt update && sudo apt install -y python3 python3-pip # Debian
$ sudo yum install -y python3 python3-pip # RHEL

Network & Security Setup

# Configure firewall:
$ sudo ufw allow 22/tcp # Debian/Ubuntu
$ sudo firewall-cmd --permanent --add-service=ssh # RHEL

# Set hostname:
$ sudo hostnamectl set-hostname server01.example.com

# Configure DNS/hosts:
$ echo "192.168.1.10 server01" | sudo tee -a /etc/hosts

# Time synchronization:
$ sudo timedatectl set-timezone UTC
$ sudo systemctl enable --now systemd-timesyncd # Debian
$ sudo systemctl enable --now chronyd # RHEL

# Update system:
$ sudo apt update && sudo apt upgrade -y # Debian
$ sudo yum update -y # RHEL

Ansible Preparation

Ansible Control Node Setup

# Install Ansible:
$ sudo apt update
$ sudo apt install -y software-properties-common
$ sudo add-apt-repository --yes --update ppa:ansible/ansible
$ sudo apt install -y ansible

# Or using pip:
$ sudo pip3 install ansible

# Verify installation:
$ ansible --version

# Create Ansible directory structure:
$ mkdir -p ~/ansible-playbooks/{inventory,group_vars,host_vars,roles}
$ cd ~/ansible-playbooks

# Create inventory file:
$ cat > inventory/hosts << EOF
[all:vars]
ansible_user=ansible
ansible_ssh_private_key_file=~/.ssh/id_ed25519

[webservers]
web01 ansible_host=192.168.1.101
web02 ansible_host=192.168.1.102

[dbservers]
db01 ansible_host=192.168.1.201
db02 ansible_host=192.168.1.202

[load_balancers]
lb01 ansible_host=192.168.1.10

[production:children]
webservers
dbservers
load_balancers
EOF

# Test connection:
$ ansible all -i inventory/hosts -m ping

# Create ansible.cfg:
$ cat > ansible.cfg << EOF
[defaults]
inventory = ./inventory/hosts
host_key_checking = False
retry_files_enabled = False
stdout_callback = yaml

[privilege_escalation]
become = True
become_method = sudo
become_user = root
become_ask_pass = False
EOF

# Create sample playbook:
$ cat > setup_basics.yml << EOF
---
- name: Basic server setup
  hosts: all
  become: yes
  tasks:
    - name: Update apt cache
      apt:
        update_cache: yes
      cache_valid_time: 3600
      when: ansible_os_family == 'Debian'

    - name: Install essential packages
      package:
        name:
          - curl
          - wget
          - vim
          - htop
        state: present

    - name: Set timezone to UTC
      timezone:
        name: UTC
EOF

Infrastructure as Code (IaC) Preparation

Terraform Setup

# Install Terraform:
$ wget https://releases.hashicorp.com/terraform/1.5.0/terraform_1.5.0_linux_amd64.zip
$ unzip terraform_1.5.0_linux_amd64.zip
$ sudo mv terraform /usr/local/bin/

# Verify:
$ terraform version

# Directory structure:
$ mkdir -p terraform-project/{modules,environments}
$ cd terraform-project

# Provider configuration:
$ cat > main.tf << EOF
terraform {
  required_version = ">= 1.0.0"
  required_providers {
    aws = {
      source = "hashicorp/aws"
      version = "~> 4.0"
    }
  }
}

provider "aws" {
  region = "us-east-1"
}
EOF

# Initialize:
$ terraform init

Version Control Setup

# Initialize Git repository:
$ git init
$ git config user.name "DevOps Team"
$ git config user.email "devops@example.com"

# Create .gitignore:
$ cat > .gitignore << EOF
# Terraform
.terraform/
*.tfstate
*.tfstate.*
*.tfvars

# Ansible
*.retry
.vagrant/

# Secrets
*.pem
*.key
secrets.yml

# IDE
.vscode/
.idea/
*.swp
EOF

# Initial commit:
$ git add .
$ git commit -m "Initial commit: Infrastructure as Code setup"

Advanced DevOps Command Reference

Environment Variables

$ export VAR=value
$ unset VAR
$ env
$ printenv VAR
$ source ~/.bashrc

SSH & Authentication

$ ssh-keygen -t ed25519
$ ssh-copy-id user@host
$ ssh-add ~/.ssh/id_ed25519
$ ssh -L 8080:localhost:80 user@host
$ ssh -i key.pem user@host

File Transfer

$ scp file.txt user@host:/path/
$ scp -r dir/ user@host:/path/
$ rsync -avz /local/ user@host:/remote/
$ rsync -avz --delete /src/ /dest/
$ rsync -avzP /large/ user@host:/backup/

Terminal Multiplexers

# tmux:
$ tmux new -s mysession
$ tmux attach -t mysession
$ tmux ls
Ctrl-b d # detach

# screen:
$ screen -S mysession
$ screen -r mysession
Ctrl-a d # detach

Remote Management

$ ssh user@host "command"
$ pssh -h hosts.txt -i "uptime"
$ parallel ssh {} "cmd" ::: host1 host2
$ ansible all -m ping
$ ansible-playbook site.yml

Configuration Management

$ ansible --version
$ terraform init
$ terraform plan
$ terraform apply
$ puppet agent --test
$ chef-client

Best Practices Summary

Environment Variables

  • Use version-controlled dotfiles for consistency across systems
  • Separate sensitive data into environment-specific files
  • Use tools like direnv for directory-specific environments
  • Document all environment variables in README files
  • Use .env files for local development (never commit them)

SSH Security

  • Always use key-based authentication, disable password auth
  • Use ed25519 keys for new deployments (stronger than RSA)
  • Implement SSH bastion/jump hosts for sensitive environments
  • Regularly rotate SSH keys (quarterly or biannually)
  • Use SSH certificates for large-scale deployments

Remote Management

  • Standardize server configurations before automation
  • Use configuration management from day one
  • Implement proper logging for all automated operations
  • Use infrastructure as code for reproducibility
  • Test changes in staging before production

File Transfer

  • Prefer rsync over scp for large or recurring transfers
  • Implement checksum verification for critical transfers
  • Use bandwidth limiting for production transfers
  • Implement proper backup rotation and retention policies
  • Test restore procedures regularly

Terminal Management

  • Use tmux over screen for new deployments
  • Standardize tmux configurations across the team
  • Use session persistence (tmux-resurrect or similar)
  • Implement logging for important terminal sessions
  • Use named sessions for easy identification

Configuration Management

  • Start with Ansible for simplicity and agentless approach
  • Use version control for all configuration code
  • Implement peer review for infrastructure changes
  • Use separate environments (dev/staging/prod)
  • Document all infrastructure decisions and configurations

Mastering these advanced DevOps topics requires both theoretical understanding and practical experience. Start by implementing these practices in your development environment, then gradually introduce them to staging and production. Remember that consistency, documentation, and security should be your guiding principles in all infrastructure management tasks.

No comments:

Post a Comment

Advanced DevOps Topics Guide - Environment Variables, SSH, Remote Management

Advanced DevOps Topics Guide - Environment Variables, SSH, Remote Management Advanced DevOps Topi...