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
Global Configuration Files
/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
~/.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
$ 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
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
# 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
$ 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
Key Types & Generation
RSA
# Legacy, widely supported
# Minimum 2048 bits recommended
Ed25519
# Modern, secure, efficient
# 256-bit equivalent security
ECDSA
# Elliptic curve variant
# Smaller keys, good performance
Complete SSH Key Workflow
Key Generation & Management
$ 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
$ 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
$ 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
$ 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
$ 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
$ 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
# 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
$ 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
$ 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
$ 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
$ 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
# 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
$ 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
# 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
$ 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
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
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
$ 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
$ 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
$ 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
$ 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
$ 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
$ unset VAR
$ env
$ printenv VAR
$ source ~/.bashrc
SSH & Authentication
$ 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 -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 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
$ pssh -h hosts.txt -i "uptime"
$ parallel ssh {} "cmd" ::: host1 host2
$ ansible all -m ping
$ ansible-playbook site.yml
Configuration Management
$ 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