feat: Add backup and security hardening
This commit is contained in:
264
BACKUP-SECURITY-STATUS.md
Normal file
264
BACKUP-SECURITY-STATUS.md
Normal file
@@ -0,0 +1,264 @@
|
|||||||
|
# Backup & Security Implementation Status
|
||||||
|
|
||||||
|
**Last Updated**: 2025-11-07
|
||||||
|
|
||||||
|
## Overview
|
||||||
|
|
||||||
|
Implementation of comprehensive backup system and security hardening for Gentoo workstation.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Part 1: Backup System
|
||||||
|
|
||||||
|
### ✅ Completed Components
|
||||||
|
|
||||||
|
#### Backup Scripts
|
||||||
|
- **backup-setup** - Interactive management script
|
||||||
|
- Location: `/usr/local/bin/backup-setup`
|
||||||
|
- Functions: status, backup, list, logs, test
|
||||||
|
- Status: ✅ Created and installed
|
||||||
|
|
||||||
|
- **backup-full** - Full system backup
|
||||||
|
- Location: `/usr/local/bin/backup-full`
|
||||||
|
- Excludes: caches, tmp, portage build dirs
|
||||||
|
- Status: ✅ Created and installed
|
||||||
|
|
||||||
|
- **backup-home** - Home directory backup
|
||||||
|
- Location: `/usr/local/bin/backup-home`
|
||||||
|
- Backs up: `/home/alexander`
|
||||||
|
- Status: ✅ Created and installed
|
||||||
|
|
||||||
|
- **backup-incremental** - Incremental backup
|
||||||
|
- Location: `/usr/local/bin/backup-incremental`
|
||||||
|
- Uses: rsync --link-dest for space efficiency
|
||||||
|
- Status: ✅ Created and installed
|
||||||
|
|
||||||
|
- **backup-configs** - Configuration backup
|
||||||
|
- Location: `/usr/local/bin/backup-configs`
|
||||||
|
- Backs up: /etc, dotfiles, portage config, custom scripts
|
||||||
|
- Status: ✅ Created and installed
|
||||||
|
|
||||||
|
#### Configuration
|
||||||
|
- **backup.conf.example** - Configuration template
|
||||||
|
- Location: `/usr/local/share/backup-setup/backup.conf.example`
|
||||||
|
- Status: ✅ Created
|
||||||
|
|
||||||
|
- **backup.conf** - Active configuration
|
||||||
|
- Location: `/etc/backup.conf`
|
||||||
|
- Status: ⚠️ **NEEDS CONFIGURATION** - Edit with NAS details
|
||||||
|
|
||||||
|
#### Logging
|
||||||
|
- **Log file**: `/var/log/backup.log`
|
||||||
|
- **State directory**: `/var/lib/backup/`
|
||||||
|
- Status: ✅ Created
|
||||||
|
|
||||||
|
### ⏳ Pending Components
|
||||||
|
|
||||||
|
#### ZSH Completion
|
||||||
|
- **_backup-setup** - ZSH autocompletion
|
||||||
|
- Location: `/usr/local/share/zsh/site-functions/_backup-setup`
|
||||||
|
- Status: ⏳ Not yet created
|
||||||
|
|
||||||
|
#### Network Trigger Service
|
||||||
|
- **backup-monitor** - OpenRC service
|
||||||
|
- Watches for NAS availability on network
|
||||||
|
- Triggers automatic backup when NAS detected
|
||||||
|
- Cooldown mechanism to prevent spam
|
||||||
|
- Status: ⏳ Not yet created
|
||||||
|
|
||||||
|
#### Documentation
|
||||||
|
- **Backup-Setup.md** - Complete backup guide
|
||||||
|
- Installation instructions
|
||||||
|
- Configuration guide
|
||||||
|
- Usage examples
|
||||||
|
- Troubleshooting
|
||||||
|
- Status: ⏳ Not yet created
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Part 2: Security Hardening
|
||||||
|
|
||||||
|
### ⏳ All Components Pending
|
||||||
|
|
||||||
|
#### Firewall (nftables)
|
||||||
|
- **nftables.conf** - Firewall ruleset
|
||||||
|
- Default deny incoming
|
||||||
|
- Allow outgoing
|
||||||
|
- Docker integration
|
||||||
|
- Status: ⏳ Not yet created
|
||||||
|
|
||||||
|
- **nftables OpenRC service**
|
||||||
|
- Auto-start at boot
|
||||||
|
- Status: ⏳ Not yet created
|
||||||
|
|
||||||
|
#### Intrusion Detection
|
||||||
|
- **fail2ban** - SSH brute-force protection
|
||||||
|
- SSH jail configuration
|
||||||
|
- Auto-ban on failed attempts
|
||||||
|
- Status: ⏳ Not yet created
|
||||||
|
|
||||||
|
#### System Hardening
|
||||||
|
- **SSH hardening**
|
||||||
|
- Key-only authentication (optional)
|
||||||
|
- fail2ban integration
|
||||||
|
- Status: ⏳ Not yet created
|
||||||
|
|
||||||
|
- **Audit & Monitoring**
|
||||||
|
- Log aggregation
|
||||||
|
- File integrity monitoring (optional)
|
||||||
|
- Status: ⏳ Not yet created
|
||||||
|
|
||||||
|
#### Documentation
|
||||||
|
- **Security-Hardening.md** - Security guide
|
||||||
|
- Firewall configuration
|
||||||
|
- fail2ban setup
|
||||||
|
- SSH hardening
|
||||||
|
- Monitoring setup
|
||||||
|
- Status: ⏳ Not yet created
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Installation Steps
|
||||||
|
|
||||||
|
### Current Step: Configure and Test Backup
|
||||||
|
|
||||||
|
1. **Install backup scripts** ✅ Done
|
||||||
|
```bash
|
||||||
|
# Scripts installed to /usr/local/bin/
|
||||||
|
# backup-setup, backup-full, backup-home, backup-incremental, backup-configs
|
||||||
|
```
|
||||||
|
|
||||||
|
2. **Configure NAS connection** ⚠️ **DO THIS NOW**
|
||||||
|
```bash
|
||||||
|
sudo nvim /etc/backup.conf
|
||||||
|
|
||||||
|
# Edit these values:
|
||||||
|
# NAS_HOST="your-nas-hostname"
|
||||||
|
# NAS_USER="your-backup-user"
|
||||||
|
# NAS_PATH="/path/to/backup/dir"
|
||||||
|
```
|
||||||
|
|
||||||
|
3. **Set up SSH key authentication** ⚠️ **REQUIRED**
|
||||||
|
```bash
|
||||||
|
# Generate SSH key if you don't have one
|
||||||
|
ssh-keygen -t ed25519 -C "backup@gentoo-workstation"
|
||||||
|
|
||||||
|
# Copy to NAS
|
||||||
|
ssh-copy-id -p 22 backup-user@nas-hostname
|
||||||
|
```
|
||||||
|
|
||||||
|
4. **Test connection**
|
||||||
|
```bash
|
||||||
|
backup-setup test
|
||||||
|
```
|
||||||
|
|
||||||
|
5. **Test backup (configs - lightweight)**
|
||||||
|
```bash
|
||||||
|
backup-setup backup configs
|
||||||
|
```
|
||||||
|
|
||||||
|
6. **Check backup status**
|
||||||
|
```bash
|
||||||
|
backup-setup status
|
||||||
|
backup-setup list
|
||||||
|
backup-setup logs
|
||||||
|
```
|
||||||
|
|
||||||
|
### Next Steps
|
||||||
|
|
||||||
|
After successful backup test:
|
||||||
|
|
||||||
|
1. **Create ZSH completion** - For backup-setup autocompletion
|
||||||
|
2. **Create network trigger** - Automated backups when NAS detected
|
||||||
|
3. **Implement firewall** - nftables configuration
|
||||||
|
4. **Set up fail2ban** - SSH protection
|
||||||
|
5. **Create documentation** - Complete guides
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Testing Checklist
|
||||||
|
|
||||||
|
### Backup System Testing
|
||||||
|
|
||||||
|
- [ ] Configuration file created (`/etc/backup.conf`)
|
||||||
|
- [ ] NAS details configured (host, user, path)
|
||||||
|
- [ ] SSH key authentication set up
|
||||||
|
- [ ] Connection test passes (`backup-setup test`)
|
||||||
|
- [ ] Config backup works (`backup-setup backup configs`)
|
||||||
|
- [ ] Backup appears on NAS (`backup-setup list`)
|
||||||
|
- [ ] Logs are written (`backup-setup logs`)
|
||||||
|
- [ ] Status shows last backup (`backup-setup status`)
|
||||||
|
|
||||||
|
### Security Testing (Future)
|
||||||
|
|
||||||
|
- [ ] Firewall rules applied
|
||||||
|
- [ ] fail2ban active and monitoring
|
||||||
|
- [ ] SSH hardening verified
|
||||||
|
- [ ] Logs monitored
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Quick Reference
|
||||||
|
|
||||||
|
### Backup Commands
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Show status
|
||||||
|
backup-setup status
|
||||||
|
|
||||||
|
# Test connection
|
||||||
|
backup-setup test
|
||||||
|
|
||||||
|
# Run backups
|
||||||
|
backup-setup backup configs # Lightweight: configs only
|
||||||
|
backup-setup backup home # Medium: home directory
|
||||||
|
backup-setup backup incremental # Efficient: incremental changes
|
||||||
|
backup-setup backup full # Complete: entire system
|
||||||
|
|
||||||
|
# View backups
|
||||||
|
backup-setup list
|
||||||
|
|
||||||
|
# View logs
|
||||||
|
backup-setup logs
|
||||||
|
```
|
||||||
|
|
||||||
|
### File Locations
|
||||||
|
|
||||||
|
```
|
||||||
|
/usr/local/bin/backup-setup # Main script
|
||||||
|
/usr/local/bin/backup-{full,home,incremental,configs} # Worker scripts
|
||||||
|
/etc/backup.conf # Configuration
|
||||||
|
/var/log/backup.log # Logs
|
||||||
|
/var/lib/backup/last-backup # Last backup timestamp
|
||||||
|
/usr/local/share/backup-setup/ # Resources
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Progress Summary
|
||||||
|
|
||||||
|
**Backup System**: 60% Complete
|
||||||
|
- ✅ All backup scripts created
|
||||||
|
- ✅ Configuration system created
|
||||||
|
- ✅ Logging set up
|
||||||
|
- ⏳ ZSH completion pending
|
||||||
|
- ⏳ Network trigger pending
|
||||||
|
- ⏳ Documentation pending
|
||||||
|
|
||||||
|
**Security Hardening**: 0% Complete
|
||||||
|
- ⏳ Firewall pending
|
||||||
|
- ⏳ fail2ban pending
|
||||||
|
- ⏳ SSH hardening pending
|
||||||
|
- ⏳ Documentation pending
|
||||||
|
|
||||||
|
**Overall**: 30% Complete
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Notes
|
||||||
|
|
||||||
|
- Backup system is functional and ready for testing
|
||||||
|
- Security hardening will begin after backup system is confirmed working
|
||||||
|
- Network trigger will be implemented using OpenRC service (not systemd)
|
||||||
|
- All scripts are POSIX sh compatible
|
||||||
|
- Follows same pattern as existing scripts (wifi-setup, audio-setup, etc.)
|
||||||
568
Backup-Setup.md
Normal file
568
Backup-Setup.md
Normal file
@@ -0,0 +1,568 @@
|
|||||||
|
# Backup Setup Guide
|
||||||
|
|
||||||
|
Complete guide for the automated backup system on Gentoo workstation.
|
||||||
|
|
||||||
|
## Overview
|
||||||
|
|
||||||
|
This backup system provides automated, network-triggered backups to a NAS via SSH/rsync with multiple safeguards against backup spam and comprehensive logging.
|
||||||
|
|
||||||
|
## Table of Contents
|
||||||
|
|
||||||
|
- [Features](#features)
|
||||||
|
- [Architecture](#architecture)
|
||||||
|
- [Installation](#installation)
|
||||||
|
- [Configuration](#configuration)
|
||||||
|
- [Usage](#usage)
|
||||||
|
- [Backup Types](#backup-types)
|
||||||
|
- [Network Trigger](#network-trigger)
|
||||||
|
- [Troubleshooting](#troubleshooting)
|
||||||
|
- [Advanced Configuration](#advanced-configuration)
|
||||||
|
|
||||||
|
## Features
|
||||||
|
|
||||||
|
✅ **Four backup types**: Full system, home directory, incremental, configs
|
||||||
|
✅ **Network-triggered backups**: Auto-backup when NAS detected
|
||||||
|
✅ **Multiple safeguards**: Rate limiting, cooldown, lock files
|
||||||
|
✅ **Interactive management**: Easy-to-use CLI interface
|
||||||
|
✅ **Comprehensive logging**: Track all backup operations
|
||||||
|
✅ **ZSH completion**: Tab completion for all commands
|
||||||
|
✅ **User-space operation**: No sudo required for backups
|
||||||
|
|
||||||
|
## Architecture
|
||||||
|
|
||||||
|
### Components
|
||||||
|
|
||||||
|
```
|
||||||
|
/usr/local/bin/
|
||||||
|
├── backup-setup # Interactive management script
|
||||||
|
├── backup-full # Full system backup
|
||||||
|
├── backup-home # Home directory backup
|
||||||
|
├── backup-incremental # Incremental backup
|
||||||
|
├── backup-configs # Configuration files backup
|
||||||
|
└── backup-trigger # Network trigger daemon
|
||||||
|
|
||||||
|
/etc/
|
||||||
|
├── backup.conf # Configuration file
|
||||||
|
└── init.d/
|
||||||
|
└── backup-monitor # OpenRC service
|
||||||
|
|
||||||
|
~/.local/var/
|
||||||
|
├── log/
|
||||||
|
│ ├── backup.log # Backup operations log
|
||||||
|
│ └── backup-monitor.log # Monitor daemon log
|
||||||
|
└── backup/
|
||||||
|
├── last-backup # Last backup timestamp
|
||||||
|
├── last-check # Last NAS check timestamp
|
||||||
|
└── backup-in-progress # Active backup marker
|
||||||
|
```
|
||||||
|
|
||||||
|
### Backup Flow
|
||||||
|
|
||||||
|
```
|
||||||
|
1. Network trigger detects NAS
|
||||||
|
↓
|
||||||
|
2. Check safeguards (cooldown, rate limit, lock files)
|
||||||
|
↓
|
||||||
|
3. Trigger backup in background
|
||||||
|
↓
|
||||||
|
4. Backup runs (rsync to NAS)
|
||||||
|
↓
|
||||||
|
5. Update timestamps and markers
|
||||||
|
↓
|
||||||
|
6. Wait for next check (5 minutes)
|
||||||
|
```
|
||||||
|
|
||||||
|
## Installation
|
||||||
|
|
||||||
|
### Prerequisites
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Required packages
|
||||||
|
emerge -av net-misc/rsync net-misc/openssh
|
||||||
|
|
||||||
|
# Verify NAS is accessible
|
||||||
|
ping 192.168.2.171
|
||||||
|
ssh alexander@192.168.2.171
|
||||||
|
```
|
||||||
|
|
||||||
|
### Install Scripts
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cd ~/repository/git.hinrichs.dev/alexander/claude/lenovo-gentoo/scripts/backup-setup
|
||||||
|
sudo ./INSTALL.sh
|
||||||
|
```
|
||||||
|
|
||||||
|
This will:
|
||||||
|
1. Copy all backup scripts to `/usr/local/bin/`
|
||||||
|
2. Set execute permissions
|
||||||
|
3. Create log and state directories
|
||||||
|
4. Show next steps
|
||||||
|
|
||||||
|
### Configure Backup
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Copy example config
|
||||||
|
sudo cp /usr/local/share/backup-setup/backup.conf.example /etc/backup.conf
|
||||||
|
|
||||||
|
# Edit configuration
|
||||||
|
sudo nvim /etc/backup.conf
|
||||||
|
```
|
||||||
|
|
||||||
|
### Install Network Trigger (Optional)
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Install ZSH completion
|
||||||
|
sudo cp _backup-setup /usr/local/share/zsh/site-functions/
|
||||||
|
|
||||||
|
# Install network trigger service
|
||||||
|
sudo cp backup-trigger /usr/local/bin/
|
||||||
|
sudo chmod +x /usr/local/bin/backup-trigger
|
||||||
|
sudo cp backup-monitor /etc/init.d/
|
||||||
|
sudo chmod +x /etc/init.d/backup-monitor
|
||||||
|
|
||||||
|
# Enable at boot
|
||||||
|
sudo rc-update add backup-monitor default
|
||||||
|
|
||||||
|
# Start service
|
||||||
|
sudo rc-service backup-monitor start
|
||||||
|
```
|
||||||
|
|
||||||
|
## Configuration
|
||||||
|
|
||||||
|
### Basic Settings
|
||||||
|
|
||||||
|
Edit `/etc/backup.conf`:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# NAS Connection
|
||||||
|
NAS_HOST="192.168.2.171"
|
||||||
|
NAS_PORT="22"
|
||||||
|
NAS_USER="alexander"
|
||||||
|
NAS_PATH="/DATA/Backup/lenovo-gentoo-machine"
|
||||||
|
|
||||||
|
# Backup Settings
|
||||||
|
RETENTION_DAYS="30"
|
||||||
|
RETENTION_COUNT="10"
|
||||||
|
BACKUP_COOLDOWN="3600" # 1 hour between backups
|
||||||
|
```
|
||||||
|
|
||||||
|
### Exclusion Patterns
|
||||||
|
|
||||||
|
Add paths to exclude from backups:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
EXCLUDE_PATTERNS=(
|
||||||
|
"/dev/*"
|
||||||
|
"/proc/*"
|
||||||
|
"/sys/*"
|
||||||
|
"/tmp/*"
|
||||||
|
"/run/*"
|
||||||
|
"/mnt/*"
|
||||||
|
"/media/*"
|
||||||
|
"/var/tmp/portage/*"
|
||||||
|
"/var/cache/*"
|
||||||
|
"/.cache/*"
|
||||||
|
"/home/*/.cache/*"
|
||||||
|
"/home/*/Downloads/*.iso"
|
||||||
|
)
|
||||||
|
```
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
|
||||||
|
### Interactive Management
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Show backup status
|
||||||
|
backup-setup status
|
||||||
|
|
||||||
|
# Trigger manual backup
|
||||||
|
backup-setup backup [TYPE]
|
||||||
|
|
||||||
|
# List backups on NAS
|
||||||
|
backup-setup list
|
||||||
|
|
||||||
|
# View recent logs
|
||||||
|
backup-setup logs
|
||||||
|
|
||||||
|
# Test NAS connection
|
||||||
|
backup-setup test
|
||||||
|
```
|
||||||
|
|
||||||
|
### Examples
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Check backup status
|
||||||
|
$ backup-setup
|
||||||
|
========================================
|
||||||
|
Backup Status
|
||||||
|
========================================
|
||||||
|
|
||||||
|
Configuration:
|
||||||
|
NAS: alexander@192.168.2.171:22
|
||||||
|
Path: /DATA/Backup/lenovo-gentoo-machine
|
||||||
|
|
||||||
|
Last backup: 2025-11-07 20:48:32 (1h ago)
|
||||||
|
|
||||||
|
✓ NAS is reachable at alexander@192.168.2.171:22
|
||||||
|
✓ Available space on NAS: 2.1T
|
||||||
|
|
||||||
|
# Run config backup
|
||||||
|
$ backup-setup backup configs
|
||||||
|
ℹ Starting configs backup...
|
||||||
|
✓ Config backup completed successfully
|
||||||
|
Backup size: 26MB
|
||||||
|
Duration: 3s
|
||||||
|
|
||||||
|
# View logs
|
||||||
|
$ backup-setup logs
|
||||||
|
[2025-11-07 20:48:29] Starting config backup...
|
||||||
|
[2025-11-07 20:48:32] Backup completed: 26MB in 3s
|
||||||
|
```
|
||||||
|
|
||||||
|
## Backup Types
|
||||||
|
|
||||||
|
### 1. Full System Backup
|
||||||
|
|
||||||
|
**What it backs up**: Entire system excluding caches and temporary files
|
||||||
|
|
||||||
|
**Size**: Large (depends on system, typically 20-50GB)
|
||||||
|
|
||||||
|
**Duration**: Long (20-60 minutes)
|
||||||
|
|
||||||
|
**Use case**: Complete system restore, major changes
|
||||||
|
|
||||||
|
```bash
|
||||||
|
backup-setup backup full
|
||||||
|
```
|
||||||
|
|
||||||
|
**Exclusions**:
|
||||||
|
- `/dev`, `/proc`, `/sys`, `/tmp`, `/run`
|
||||||
|
- `/mnt`, `/media`
|
||||||
|
- `/var/tmp/portage/*` (Portage build directory)
|
||||||
|
- `/var/cache/*`
|
||||||
|
- All `.cache` directories
|
||||||
|
|
||||||
|
### 2. Home Directory Backup
|
||||||
|
|
||||||
|
**What it backs up**: `/home/alexander` only
|
||||||
|
|
||||||
|
**Size**: Medium (depends on data, typically 10-50GB)
|
||||||
|
|
||||||
|
**Duration**: Medium (10-30 minutes)
|
||||||
|
|
||||||
|
**Use case**: Personal files, documents, projects
|
||||||
|
|
||||||
|
```bash
|
||||||
|
backup-setup backup home
|
||||||
|
```
|
||||||
|
|
||||||
|
**Exclusions**:
|
||||||
|
- `.cache` directories
|
||||||
|
- Browser caches
|
||||||
|
- `Downloads/*.iso`, `Downloads/*.mp4`, `Downloads/*.mkv`
|
||||||
|
|
||||||
|
### 3. Incremental Backup
|
||||||
|
|
||||||
|
**What it backs up**: Only changed files since last backup
|
||||||
|
|
||||||
|
**Size**: Small (only changes)
|
||||||
|
|
||||||
|
**Duration**: Fast (1-10 minutes)
|
||||||
|
|
||||||
|
**Use case**: Daily backups, minimal bandwidth
|
||||||
|
|
||||||
|
```bash
|
||||||
|
backup-setup backup incremental
|
||||||
|
```
|
||||||
|
|
||||||
|
**How it works**: Uses rsync's `--link-dest` to hardlink unchanged files,
|
||||||
|
saving space and time.
|
||||||
|
|
||||||
|
### 4. Configuration Backup
|
||||||
|
|
||||||
|
**What it backs up**: System configs, dotfiles, scripts
|
||||||
|
|
||||||
|
**Size**: Tiny (typically <100MB)
|
||||||
|
|
||||||
|
**Duration**: Very fast (<1 minute)
|
||||||
|
|
||||||
|
**Use case**: Quick config snapshots, testing changes
|
||||||
|
|
||||||
|
```bash
|
||||||
|
backup-setup backup configs
|
||||||
|
```
|
||||||
|
|
||||||
|
**Includes**:
|
||||||
|
- `/etc` (system configuration)
|
||||||
|
- `/home/alexander/.config` (user configs)
|
||||||
|
- `/home/alexander/.local` (local data)
|
||||||
|
- `/etc/portage` (Gentoo package config)
|
||||||
|
- `/usr/local/bin` (custom scripts)
|
||||||
|
- `/home/alexander/.zshrc`, `.bashrc`, etc.
|
||||||
|
|
||||||
|
## Network Trigger
|
||||||
|
|
||||||
|
### How It Works
|
||||||
|
|
||||||
|
The network trigger monitors for NAS availability and automatically triggers
|
||||||
|
backups when the NAS is detected. It has multiple safeguards to prevent
|
||||||
|
backup spam:
|
||||||
|
|
||||||
|
1. **Rate Limiting**: Checks for NAS only every 5 minutes
|
||||||
|
2. **Cooldown Period**: Enforces minimum 1 hour between backups
|
||||||
|
3. **Lock File Detection**: Skips if another backup is running
|
||||||
|
4. **In-Progress Marker**: Tracks active backups
|
||||||
|
5. **Stale Marker Cleanup**: Removes markers older than 6 hours
|
||||||
|
|
||||||
|
### Monitor Status
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Check service status
|
||||||
|
sudo rc-service backup-monitor status
|
||||||
|
|
||||||
|
# View monitor logs
|
||||||
|
tail -f ~/.local/var/log/backup-monitor.log
|
||||||
|
|
||||||
|
# View backup logs
|
||||||
|
tail -f ~/.local/var/log/backup.log
|
||||||
|
```
|
||||||
|
|
||||||
|
### Example Log Output
|
||||||
|
|
||||||
|
```
|
||||||
|
[2025-11-07 21:01:43] ==========================================
|
||||||
|
[2025-11-07 21:01:43] Backup monitor started
|
||||||
|
[2025-11-07 21:01:43] Monitoring for NAS: 192.168.2.171
|
||||||
|
[2025-11-07 21:01:43] Check interval: 5 minutes
|
||||||
|
[2025-11-07 21:01:43] Backup cooldown: 3600s (1h)
|
||||||
|
[2025-11-07 21:01:43] ==========================================
|
||||||
|
[2025-11-07 21:06:00] NAS is available at 192.168.2.171
|
||||||
|
[2025-11-07 21:06:00] Cooldown passed, backup allowed
|
||||||
|
[2025-11-07 21:06:00] NAS detected, triggering incremental backup...
|
||||||
|
[2025-11-07 21:06:00] Backup started in background (PID: 12345)
|
||||||
|
```
|
||||||
|
|
||||||
|
### Service Management
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Start monitor
|
||||||
|
sudo rc-service backup-monitor start
|
||||||
|
|
||||||
|
# Stop monitor
|
||||||
|
sudo rc-service backup-monitor stop
|
||||||
|
|
||||||
|
# Restart monitor
|
||||||
|
sudo rc-service backup-monitor restart
|
||||||
|
|
||||||
|
# Enable at boot
|
||||||
|
sudo rc-update add backup-monitor default
|
||||||
|
|
||||||
|
# Disable at boot
|
||||||
|
sudo rc-update del backup-monitor default
|
||||||
|
```
|
||||||
|
|
||||||
|
## Troubleshooting
|
||||||
|
|
||||||
|
### Backup Fails with Permission Denied
|
||||||
|
|
||||||
|
**Problem**: Cannot write to log files or state files
|
||||||
|
|
||||||
|
**Solution**: Ensure directories exist and are writable:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
mkdir -p ~/.local/var/log
|
||||||
|
mkdir -p ~/.local/var/backup
|
||||||
|
chmod 755 ~/.local/var/log
|
||||||
|
chmod 755 ~/.local/var/backup
|
||||||
|
```
|
||||||
|
|
||||||
|
### Lock File Prevents Backup
|
||||||
|
|
||||||
|
**Problem**: Backup shows "already running" but no backup is active
|
||||||
|
|
||||||
|
**Solution**: Remove stale lock file:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
rm /tmp/backup-*.lock
|
||||||
|
```
|
||||||
|
|
||||||
|
### NAS Not Detected
|
||||||
|
|
||||||
|
**Problem**: Network trigger doesn't detect NAS
|
||||||
|
|
||||||
|
**Check connection**:
|
||||||
|
```bash
|
||||||
|
# Test ping
|
||||||
|
ping -c 3 192.168.2.171
|
||||||
|
|
||||||
|
# Test SSH
|
||||||
|
ssh alexander@192.168.2.171 "echo test"
|
||||||
|
|
||||||
|
# Check monitor logs
|
||||||
|
tail -20 ~/.local/var/log/backup-monitor.log
|
||||||
|
```
|
||||||
|
|
||||||
|
**Verify config**:
|
||||||
|
```bash
|
||||||
|
cat /etc/backup.conf
|
||||||
|
```
|
||||||
|
|
||||||
|
### Backup Too Slow
|
||||||
|
|
||||||
|
**Problem**: Backup takes too long
|
||||||
|
|
||||||
|
**Solutions**:
|
||||||
|
|
||||||
|
1. Use incremental backup instead of full:
|
||||||
|
```bash
|
||||||
|
backup-setup backup incremental
|
||||||
|
```
|
||||||
|
|
||||||
|
2. Add more exclusions to `/etc/backup.conf`:
|
||||||
|
```bash
|
||||||
|
EXCLUDE_PATTERNS+=(
|
||||||
|
"/home/*/Videos/*"
|
||||||
|
"/home/*/Music/*"
|
||||||
|
"/home/*/.local/share/Steam/*"
|
||||||
|
)
|
||||||
|
```
|
||||||
|
|
||||||
|
3. Check network speed:
|
||||||
|
```bash
|
||||||
|
# Test transfer speed
|
||||||
|
dd if=/dev/zero bs=1M count=100 | \
|
||||||
|
ssh alexander@192.168.2.171 "cat > /dev/null"
|
||||||
|
```
|
||||||
|
|
||||||
|
### Cooldown Too Short/Long
|
||||||
|
|
||||||
|
**Problem**: Backups happen too frequently or not frequently enough
|
||||||
|
|
||||||
|
**Solution**: Adjust `BACKUP_COOLDOWN` in `/etc/backup.conf`:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 30 minutes
|
||||||
|
BACKUP_COOLDOWN="1800"
|
||||||
|
|
||||||
|
# 2 hours
|
||||||
|
BACKUP_COOLDOWN="7200"
|
||||||
|
|
||||||
|
# 6 hours
|
||||||
|
BACKUP_COOLDOWN="21600"
|
||||||
|
```
|
||||||
|
|
||||||
|
Then restart the monitor:
|
||||||
|
```bash
|
||||||
|
sudo rc-service backup-monitor restart
|
||||||
|
```
|
||||||
|
|
||||||
|
## Advanced Configuration
|
||||||
|
|
||||||
|
### Custom Backup Schedules
|
||||||
|
|
||||||
|
Instead of using the network trigger, use cron for scheduled backups:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Edit crontab
|
||||||
|
crontab -e
|
||||||
|
|
||||||
|
# Daily incremental at 2 AM
|
||||||
|
0 2 * * * /usr/local/bin/backup-incremental
|
||||||
|
|
||||||
|
# Weekly full backup on Sunday at 3 AM
|
||||||
|
0 3 * * 0 /usr/local/bin/backup-full
|
||||||
|
|
||||||
|
# Hourly config backup
|
||||||
|
0 * * * * /usr/local/bin/backup-configs
|
||||||
|
```
|
||||||
|
|
||||||
|
### Multiple NAS Destinations
|
||||||
|
|
||||||
|
Create separate configs for different NAS hosts:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Create configs
|
||||||
|
sudo cp /etc/backup.conf /etc/backup-nas1.conf
|
||||||
|
sudo cp /etc/backup.conf /etc/backup-nas2.conf
|
||||||
|
|
||||||
|
# Edit each config with different NAS_HOST and NAS_PATH
|
||||||
|
|
||||||
|
# Create wrapper scripts
|
||||||
|
cat > ~/.local/bin/backup-nas1 <<'EOF'
|
||||||
|
#!/bin/sh
|
||||||
|
CONFIG_FILE="/etc/backup-nas1.conf" /usr/local/bin/backup-incremental "$@"
|
||||||
|
EOF
|
||||||
|
|
||||||
|
cat > ~/.local/bin/backup-nas2 <<'EOF'
|
||||||
|
#!/bin/sh
|
||||||
|
CONFIG_FILE="/etc/backup-nas2.conf" /usr/local/bin/backup-incremental "$@"
|
||||||
|
EOF
|
||||||
|
|
||||||
|
chmod +x ~/.local/bin/backup-nas*
|
||||||
|
```
|
||||||
|
|
||||||
|
### Backup Verification
|
||||||
|
|
||||||
|
Add verification to backup scripts by editing them:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# After rsync in any backup script, add:
|
||||||
|
|
||||||
|
# Verify backup
|
||||||
|
info "Verifying backup..."
|
||||||
|
if ssh -p "$NAS_PORT" "${NAS_USER}@${NAS_HOST}" \
|
||||||
|
"test -d '$BACKUP_DEST' && du -sh '$BACKUP_DEST'"; then
|
||||||
|
success "Backup verified"
|
||||||
|
else
|
||||||
|
error "Backup verification failed"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
```
|
||||||
|
|
||||||
|
### Email Notifications
|
||||||
|
|
||||||
|
Install and configure email notifications:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Install mail client
|
||||||
|
emerge -av mail-client/mailx
|
||||||
|
|
||||||
|
# Add to backup scripts after completion:
|
||||||
|
echo "Backup completed at $(date)" | \
|
||||||
|
mail -s "Backup: $HOSTNAME" your.email@example.com
|
||||||
|
```
|
||||||
|
|
||||||
|
### Encryption
|
||||||
|
|
||||||
|
Encrypt backups using gpg before sending to NAS:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Install gpg
|
||||||
|
emerge -av app-crypt/gnupg
|
||||||
|
|
||||||
|
# Generate key
|
||||||
|
gpg --gen-key
|
||||||
|
|
||||||
|
# Modify backup scripts to encrypt:
|
||||||
|
# Replace rsync command with:
|
||||||
|
tar czf - / --exclude-from=<(printf '%s\n' "${EXCLUDE_PATTERNS[@]}") | \
|
||||||
|
gpg --encrypt --recipient your@email.com | \
|
||||||
|
ssh -p "$NAS_PORT" "${NAS_USER}@${NAS_HOST}" \
|
||||||
|
"cat > '$BACKUP_DEST/backup.tar.gz.gpg'"
|
||||||
|
```
|
||||||
|
|
||||||
|
## Best Practices
|
||||||
|
|
||||||
|
1. **Test Restores**: Regularly test restoring from backups
|
||||||
|
2. **Monitor Logs**: Check backup logs weekly
|
||||||
|
3. **Verify Space**: Ensure NAS has adequate free space
|
||||||
|
4. **Update Exclusions**: Review and update exclusion patterns
|
||||||
|
5. **Document Changes**: Keep notes on backup configuration changes
|
||||||
|
6. **3-2-1 Rule**: Keep 3 copies, on 2 media types, 1 offsite
|
||||||
|
|
||||||
|
## See Also
|
||||||
|
|
||||||
|
- [USER-GUIDE.md](USER-GUIDE.md) - Quick reference guide
|
||||||
|
- [CLAUDE.md](CLAUDE.md) - System overview
|
||||||
|
- `/etc/backup.conf` - Backup configuration
|
||||||
|
- `~/.local/var/log/backup.log` - Backup logs
|
||||||
811
Dotfiles-Management.md
Normal file
811
Dotfiles-Management.md
Normal file
@@ -0,0 +1,811 @@
|
|||||||
|
# Dotfile Management with chezmoi
|
||||||
|
|
||||||
|
Complete guide to managing your dotfiles with chezmoi on this Gentoo workstation and across multiple machines.
|
||||||
|
|
||||||
|
## Table of Contents
|
||||||
|
|
||||||
|
- [Overview](#overview)
|
||||||
|
- [Quick Reference](#quick-reference)
|
||||||
|
- [Daily Workflow](#daily-workflow)
|
||||||
|
- [Adding New Tools](#adding-new-tools)
|
||||||
|
- [Editing Existing Configs](#editing-existing-configs)
|
||||||
|
- [Templates for Cross-Platform Configs](#templates-for-cross-platform-configs)
|
||||||
|
- [Syncing Across Machines](#syncing-across-machines)
|
||||||
|
- [Advanced Usage](#advanced-usage)
|
||||||
|
- [Troubleshooting](#troubleshooting)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Overview
|
||||||
|
|
||||||
|
### What is chezmoi?
|
||||||
|
|
||||||
|
chezmoi is a cross-platform dotfile manager that allows you to:
|
||||||
|
- Keep your dotfiles in a git repository
|
||||||
|
- Sync configs across multiple machines (Gentoo, macOS, Ubuntu, etc.)
|
||||||
|
- Use templates for machine-specific configurations
|
||||||
|
- Manage secrets securely
|
||||||
|
- Automate setup on new machines
|
||||||
|
|
||||||
|
### Current Setup
|
||||||
|
|
||||||
|
**Dotfiles Repository**: `~/repository/git.hinrichs.dev/alexander/dotfiles`
|
||||||
|
- This is your main git repository
|
||||||
|
- Contains all your dotfiles and chezmoi configuration
|
||||||
|
- Pushed to your Gitea server
|
||||||
|
|
||||||
|
**Chezmoi Source Directory**: `~/.local/share/chezmoi`
|
||||||
|
- Git clone of your dotfiles repository
|
||||||
|
- Working directory for chezmoi
|
||||||
|
- Where you make changes before applying them
|
||||||
|
|
||||||
|
**Chezmoi Config**: `~/.config/chezmoi/chezmoi.yaml`
|
||||||
|
- Generated from `.chezmoi.yaml.tmpl`
|
||||||
|
- Contains your machine-specific values (name, email, work/personal, etc.)
|
||||||
|
|
||||||
|
### How It Works
|
||||||
|
|
||||||
|
```
|
||||||
|
┌─────────────────────────────────────────────────┐
|
||||||
|
│ 1. Edit dotfiles in chezmoi source │
|
||||||
|
│ chezmoi edit ~/.zshrc │
|
||||||
|
│ (edits ~/.local/share/chezmoi/dot_zshrc) │
|
||||||
|
└─────────────────────────────────────────────────┘
|
||||||
|
│
|
||||||
|
▼
|
||||||
|
┌─────────────────────────────────────────────────┐
|
||||||
|
│ 2. Preview changes │
|
||||||
|
│ chezmoi diff │
|
||||||
|
└─────────────────────────────────────────────────┘
|
||||||
|
│
|
||||||
|
▼
|
||||||
|
┌─────────────────────────────────────────────────┐
|
||||||
|
│ 3. Apply to home directory │
|
||||||
|
│ chezmoi apply │
|
||||||
|
│ (copies to ~/.zshrc) │
|
||||||
|
└─────────────────────────────────────────────────┘
|
||||||
|
│
|
||||||
|
▼
|
||||||
|
┌─────────────────────────────────────────────────┐
|
||||||
|
│ 4. Commit and push │
|
||||||
|
│ chezmoi cd │
|
||||||
|
│ git add . && git commit && git push │
|
||||||
|
└─────────────────────────────────────────────────┘
|
||||||
|
│
|
||||||
|
▼
|
||||||
|
┌─────────────────────────────────────────────────┐
|
||||||
|
│ 5. Pull on other machines │
|
||||||
|
│ chezmoi update │
|
||||||
|
└─────────────────────────────────────────────────┘
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Quick Reference
|
||||||
|
|
||||||
|
| Task | Command |
|
||||||
|
|------|---------|
|
||||||
|
| Edit dotfile | `chezmoi edit ~/.zshrc` |
|
||||||
|
| Preview changes | `chezmoi diff` |
|
||||||
|
| Apply changes | `chezmoi apply` |
|
||||||
|
| Add new file | `chezmoi add ~/.newfile` |
|
||||||
|
| Go to source dir | `chezmoi cd` |
|
||||||
|
| Update from git | `chezmoi update` |
|
||||||
|
| List managed files | `chezmoi managed` |
|
||||||
|
| Show status | `chezmoi status` |
|
||||||
|
| View rendered template | `chezmoi cat ~/.zshrc` |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Daily Workflow
|
||||||
|
|
||||||
|
### Scenario 1: Edit Existing Config
|
||||||
|
|
||||||
|
**Goal**: Update your shell configuration
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 1. Edit the file
|
||||||
|
chezmoi edit ~/.zshrc
|
||||||
|
|
||||||
|
# 2. Preview what will change
|
||||||
|
chezmoi diff
|
||||||
|
|
||||||
|
# 3. Apply the changes
|
||||||
|
chezmoi apply
|
||||||
|
|
||||||
|
# 4. Test the changes
|
||||||
|
source ~/.zshrc
|
||||||
|
|
||||||
|
# 5. If everything works, commit
|
||||||
|
chezmoi cd
|
||||||
|
git add dot_zshrc.tmpl # or dot_zshrc if not a template
|
||||||
|
git commit -m "feat: add new shell alias"
|
||||||
|
git push
|
||||||
|
```
|
||||||
|
|
||||||
|
### Scenario 2: Update Neovim Config
|
||||||
|
|
||||||
|
**Goal**: Modify Neovim configuration
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 1. Edit the config
|
||||||
|
chezmoi edit ~/.config/nvim/lua/alxndrhi/options.lua
|
||||||
|
|
||||||
|
# 2. Preview
|
||||||
|
chezmoi diff
|
||||||
|
|
||||||
|
# 3. Apply
|
||||||
|
chezmoi apply
|
||||||
|
|
||||||
|
# 4. Test in neovim
|
||||||
|
nvim
|
||||||
|
|
||||||
|
# 5. Commit
|
||||||
|
chezmoi cd
|
||||||
|
git add dot_config/nvim/lua/alxndrhi/options.lua
|
||||||
|
git commit -m "feat: update neovim tab settings"
|
||||||
|
git push
|
||||||
|
```
|
||||||
|
|
||||||
|
### Scenario 3: Pull Latest Changes
|
||||||
|
|
||||||
|
**Goal**: Sync dotfiles from another machine
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Pull and apply in one command
|
||||||
|
chezmoi update
|
||||||
|
|
||||||
|
# Or step by step:
|
||||||
|
chezmoi cd
|
||||||
|
git pull
|
||||||
|
exit
|
||||||
|
chezmoi apply
|
||||||
|
|
||||||
|
# Restart affected services
|
||||||
|
source ~/.zshrc # If shell config changed
|
||||||
|
# or restart terminal
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Adding New Tools
|
||||||
|
|
||||||
|
When you install a new CLI tool or application with configuration files, here's how to add it to your dotfiles.
|
||||||
|
|
||||||
|
### Example: Adding a New Tool (e.g., 'alacritty')
|
||||||
|
|
||||||
|
**Step 1: Install the tool**
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Install via package manager
|
||||||
|
sudo emerge -av x11-terms/alacritty
|
||||||
|
```
|
||||||
|
|
||||||
|
**Step 2: Create and test the configuration**
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Create config directory
|
||||||
|
mkdir -p ~/.config/alacritty
|
||||||
|
|
||||||
|
# Create config file
|
||||||
|
nvim ~/.config/alacritty/alacritty.toml
|
||||||
|
|
||||||
|
# Test the tool
|
||||||
|
alacritty --version
|
||||||
|
alacritty # Launch and verify config works
|
||||||
|
```
|
||||||
|
|
||||||
|
**Step 3: Add configuration to chezmoi**
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Add the config file
|
||||||
|
chezmoi add ~/.config/alacritty/alacritty.toml
|
||||||
|
|
||||||
|
# Or add entire directory
|
||||||
|
chezmoi add --recursive ~/.config/alacritty
|
||||||
|
```
|
||||||
|
|
||||||
|
**What this does:**
|
||||||
|
- Copies `~/.config/alacritty/` to `~/.local/share/chezmoi/dot_config/alacritty/`
|
||||||
|
- File is now managed by chezmoi
|
||||||
|
|
||||||
|
**Step 4: Verify it was added**
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Check if file is managed
|
||||||
|
chezmoi managed | grep alacritty
|
||||||
|
|
||||||
|
# View the source file
|
||||||
|
chezmoi cd
|
||||||
|
ls -la dot_config/alacritty/
|
||||||
|
```
|
||||||
|
|
||||||
|
**Step 5: Commit to git**
|
||||||
|
|
||||||
|
```bash
|
||||||
|
chezmoi cd
|
||||||
|
git add dot_config/alacritty/
|
||||||
|
git commit -m "feat: add alacritty terminal emulator configuration"
|
||||||
|
git push
|
||||||
|
```
|
||||||
|
|
||||||
|
**Step 6: Test on another machine**
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# On another machine
|
||||||
|
chezmoi update
|
||||||
|
|
||||||
|
# Verify alacritty config is there
|
||||||
|
ls -la ~/.config/alacritty/
|
||||||
|
```
|
||||||
|
|
||||||
|
### Adding Shell Scripts
|
||||||
|
|
||||||
|
If you have custom scripts in `~/bin` or `~/.local/bin`:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Add entire directory
|
||||||
|
chezmoi add --recursive ~/.local/bin
|
||||||
|
|
||||||
|
# Or individual scripts
|
||||||
|
chezmoi add ~/.local/bin/my-script.sh
|
||||||
|
|
||||||
|
# Make sure they're executable
|
||||||
|
chezmoi chattr +executable ~/.local/bin/my-script.sh
|
||||||
|
|
||||||
|
# Commit
|
||||||
|
chezmoi cd
|
||||||
|
git add .
|
||||||
|
git commit -m "feat: add custom shell scripts"
|
||||||
|
git push
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Editing Existing Configs
|
||||||
|
|
||||||
|
### Edit and Apply
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Edit any managed file
|
||||||
|
chezmoi edit ~/.gitconfig
|
||||||
|
|
||||||
|
# This opens: ~/.local/share/chezmoi/dot_gitconfig.tmpl
|
||||||
|
# (or dot_gitconfig if not a template)
|
||||||
|
|
||||||
|
# After editing, preview changes
|
||||||
|
chezmoi diff
|
||||||
|
|
||||||
|
# Apply
|
||||||
|
chezmoi apply
|
||||||
|
|
||||||
|
# Test
|
||||||
|
git config --list
|
||||||
|
```
|
||||||
|
|
||||||
|
### Edit Multiple Files
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Edit several files in your editor
|
||||||
|
chezmoi edit ~/.zshrc ~/.gitconfig ~/.config/starship.toml
|
||||||
|
|
||||||
|
# Preview all changes
|
||||||
|
chezmoi diff
|
||||||
|
|
||||||
|
# Apply all
|
||||||
|
chezmoi apply
|
||||||
|
|
||||||
|
# Commit all
|
||||||
|
chezmoi cd
|
||||||
|
git add .
|
||||||
|
git commit -m "feat: update shell and git configs"
|
||||||
|
git push
|
||||||
|
```
|
||||||
|
|
||||||
|
### Edit Directly in Source Directory
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Go to chezmoi source
|
||||||
|
chezmoi cd
|
||||||
|
|
||||||
|
# Edit files directly
|
||||||
|
nvim dot_zshrc.tmpl
|
||||||
|
nvim dot_config/nvim/init.lua
|
||||||
|
|
||||||
|
# Preview from anywhere
|
||||||
|
chezmoi diff
|
||||||
|
|
||||||
|
# Apply from anywhere
|
||||||
|
chezmoi apply
|
||||||
|
|
||||||
|
# Commit
|
||||||
|
git add .
|
||||||
|
git commit -m "feat: update configs"
|
||||||
|
git push
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Templates for Cross-Platform Configs
|
||||||
|
|
||||||
|
Some configs need to be different on different operating systems or machines. Use templates for this.
|
||||||
|
|
||||||
|
### Convert a File to Template
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Make a file a template
|
||||||
|
chezmoi chattr +template ~/.zshrc
|
||||||
|
|
||||||
|
# This renames: dot_zshrc → dot_zshrc.tmpl
|
||||||
|
```
|
||||||
|
|
||||||
|
### Template Syntax
|
||||||
|
|
||||||
|
Templates use Go's `text/template` syntax:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# OS detection
|
||||||
|
{{ if eq .chezmoi.os "darwin" -}}
|
||||||
|
# macOS-specific config
|
||||||
|
export PATH="/opt/homebrew/bin:$PATH"
|
||||||
|
{{- else if eq .chezmoi.os "linux" -}}
|
||||||
|
# Linux-specific config
|
||||||
|
export PATH="/usr/local/bin:$PATH"
|
||||||
|
{{- end }}
|
||||||
|
|
||||||
|
# Distribution detection
|
||||||
|
{{ if eq .osid "linux-gentoo" -}}
|
||||||
|
# Gentoo-specific config
|
||||||
|
alias emerge-update="sudo emerge --sync && sudo emerge -uDNav @world"
|
||||||
|
{{- else if eq .osid "linux-ubuntu" -}}
|
||||||
|
# Ubuntu-specific config
|
||||||
|
alias apt-update="sudo apt update && sudo apt upgrade"
|
||||||
|
{{- end }}
|
||||||
|
|
||||||
|
# Work vs Personal
|
||||||
|
{{ if .work -}}
|
||||||
|
# Work-specific config
|
||||||
|
export COMPANY_DOMAIN="company.com"
|
||||||
|
{{- else if .personal -}}
|
||||||
|
# Personal config
|
||||||
|
export PROJECTS_DIR="$HOME/repository"
|
||||||
|
{{- end }}
|
||||||
|
|
||||||
|
# Machine-specific
|
||||||
|
{{ if eq .machine "gentoo-workstation" -}}
|
||||||
|
# Workstation config
|
||||||
|
export DISPLAY=:0
|
||||||
|
{{- else if eq .machine "macos-laptop" -}}
|
||||||
|
# Laptop config
|
||||||
|
{{- end }}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Available Template Variables
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# View all available data
|
||||||
|
chezmoi data
|
||||||
|
|
||||||
|
# Common variables:
|
||||||
|
.chezmoi.os # darwin, linux, windows
|
||||||
|
.chezmoi.osRelease.id # gentoo, ubuntu, arch
|
||||||
|
.chezmoi.hostname # lenovo-thinkpad
|
||||||
|
.osid # linux-gentoo, darwin, etc.
|
||||||
|
.machine # gentoo-workstation, macos-laptop
|
||||||
|
.work # true/false
|
||||||
|
.personal # true/false
|
||||||
|
.email # your@email.com
|
||||||
|
.name # Your Name
|
||||||
|
.features.desktop # true/false
|
||||||
|
.features.development # true/false
|
||||||
|
.features.docker # true/false
|
||||||
|
```
|
||||||
|
|
||||||
|
### Example: Cross-Platform .zshrc
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Edit the template
|
||||||
|
chezmoi edit ~/.zshrc
|
||||||
|
|
||||||
|
# Add OS-specific paths
|
||||||
|
{{ if eq .chezmoi.os "darwin" -}}
|
||||||
|
# macOS Homebrew
|
||||||
|
export PATH="/opt/homebrew/bin:$PATH"
|
||||||
|
|
||||||
|
# macOS-specific aliases
|
||||||
|
alias update="brew update && brew upgrade"
|
||||||
|
{{- else if eq .osid "linux-gentoo" -}}
|
||||||
|
# Gentoo paths
|
||||||
|
export PATH="/usr/local/bin:$HOME/.local/bin:$PATH"
|
||||||
|
|
||||||
|
# Gentoo-specific aliases
|
||||||
|
alias update="sudo emerge --sync && sudo emerge -uDNav @world"
|
||||||
|
{{- end }}
|
||||||
|
|
||||||
|
# Common config (works on all platforms)
|
||||||
|
export EDITOR=nvim
|
||||||
|
export VISUAL=nvim
|
||||||
|
|
||||||
|
# Apply
|
||||||
|
chezmoi apply
|
||||||
|
|
||||||
|
# Test
|
||||||
|
echo $PATH
|
||||||
|
```
|
||||||
|
|
||||||
|
### View Rendered Template
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# See how template renders on this machine
|
||||||
|
chezmoi cat ~/.zshrc
|
||||||
|
|
||||||
|
# Test specific template expression
|
||||||
|
chezmoi execute-template "{{ .chezmoi.os }}"
|
||||||
|
chezmoi execute-template "{{ .osid }}"
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Syncing Across Machines
|
||||||
|
|
||||||
|
### Setup on New Machine
|
||||||
|
|
||||||
|
**One-line install** (if you have the bootstrap script):
|
||||||
|
|
||||||
|
```bash
|
||||||
|
sh -c "$(curl -fsLS https://git.hinrichs.dev/alexander/dotfiles/raw/branch/main/install.sh)"
|
||||||
|
```
|
||||||
|
|
||||||
|
**Manual setup**:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 1. Install chezmoi
|
||||||
|
# (see installation instructions for your OS)
|
||||||
|
|
||||||
|
# 2. Initialize with your dotfiles repo
|
||||||
|
chezmoi init https://git.hinrichs.dev/alexander/dotfiles.git
|
||||||
|
|
||||||
|
# 3. Preview what will be applied
|
||||||
|
chezmoi diff
|
||||||
|
|
||||||
|
# 4. Apply dotfiles
|
||||||
|
chezmoi apply
|
||||||
|
|
||||||
|
# 5. Restart shell
|
||||||
|
exec zsh
|
||||||
|
```
|
||||||
|
|
||||||
|
### Keep Machines in Sync
|
||||||
|
|
||||||
|
**On Machine A** (where you made changes):
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Edit configs
|
||||||
|
chezmoi edit ~/.zshrc
|
||||||
|
|
||||||
|
# Apply
|
||||||
|
chezmoi apply
|
||||||
|
|
||||||
|
# Commit and push
|
||||||
|
chezmoi cd
|
||||||
|
git add .
|
||||||
|
git commit -m "feat: update shell config"
|
||||||
|
git push
|
||||||
|
```
|
||||||
|
|
||||||
|
**On Machine B** (pull the changes):
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Pull and apply
|
||||||
|
chezmoi update
|
||||||
|
|
||||||
|
# Or step by step:
|
||||||
|
chezmoi cd
|
||||||
|
git pull
|
||||||
|
exit
|
||||||
|
chezmoi apply
|
||||||
|
|
||||||
|
# Restart shell if needed
|
||||||
|
exec zsh
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Advanced Usage
|
||||||
|
|
||||||
|
### Ignore Files Per Machine
|
||||||
|
|
||||||
|
Edit `.chezmoiignore` to exclude files on specific machines:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
chezmoi cd
|
||||||
|
nvim .chezmoiignore
|
||||||
|
|
||||||
|
# Example content:
|
||||||
|
{{ if not .features.desktop -}}
|
||||||
|
# Ignore desktop configs on servers
|
||||||
|
.config/hypr/
|
||||||
|
.config/waybar/
|
||||||
|
{{- end }}
|
||||||
|
|
||||||
|
{{ if eq .chezmoi.os "darwin" -}}
|
||||||
|
# Ignore Linux-specific configs on macOS
|
||||||
|
.config/systemd/
|
||||||
|
{{- end }}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Run Scripts on Apply
|
||||||
|
|
||||||
|
Create scripts that run when applying dotfiles:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
chezmoi cd
|
||||||
|
nvim .chezmoiscripts/run_once_after_setup-tool.sh
|
||||||
|
|
||||||
|
#!/bin/sh
|
||||||
|
# Install tool if not present
|
||||||
|
if ! command -v tool >/dev/null 2>&1; then
|
||||||
|
echo "Installing tool..."
|
||||||
|
# Installation commands
|
||||||
|
fi
|
||||||
|
```
|
||||||
|
|
||||||
|
Script naming:
|
||||||
|
- `run_once_*` - Runs once (tracked by hash)
|
||||||
|
- `run_onchange_*` - Runs when script content changes
|
||||||
|
- `run_before_*` - Runs before applying
|
||||||
|
- `run_after_*` - Runs after applying
|
||||||
|
|
||||||
|
### Encrypt Sensitive Files
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Add encrypted file
|
||||||
|
chezmoi add --encrypt ~/.ssh/id_rsa
|
||||||
|
|
||||||
|
# chezmoi uses age or gpg for encryption
|
||||||
|
```
|
||||||
|
|
||||||
|
### Dry Run / Testing
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# See what would change without applying
|
||||||
|
chezmoi apply --dry-run --verbose
|
||||||
|
|
||||||
|
# Test on a VM before applying to main machine
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Troubleshooting
|
||||||
|
|
||||||
|
### Warning: Config File Template Changed
|
||||||
|
|
||||||
|
**Error**: `chezmoi: warning: config file template has changed`
|
||||||
|
|
||||||
|
**Solution**:
|
||||||
|
```bash
|
||||||
|
chezmoi init
|
||||||
|
# Answer prompts for name, email, work/personal
|
||||||
|
```
|
||||||
|
|
||||||
|
### Diff Shows Too Much / Opens vim
|
||||||
|
|
||||||
|
The default diff tool is `nvim -d`. To use built-in diff:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Use built-in diff (easier to read)
|
||||||
|
chezmoi diff --use-builtin-diff
|
||||||
|
|
||||||
|
# Or use it with pager
|
||||||
|
chezmoi diff --use-builtin-diff | less
|
||||||
|
```
|
||||||
|
|
||||||
|
### File Conflicts
|
||||||
|
|
||||||
|
**Error**: File already exists and differs
|
||||||
|
|
||||||
|
**Solution**:
|
||||||
|
```bash
|
||||||
|
# Merge manually
|
||||||
|
chezmoi merge ~/.zshrc
|
||||||
|
|
||||||
|
# Or force overwrite
|
||||||
|
chezmoi apply --force
|
||||||
|
|
||||||
|
# Or remove from management and re-add
|
||||||
|
chezmoi forget ~/.zshrc
|
||||||
|
# Fix the file manually
|
||||||
|
chezmoi add ~/.zshrc
|
||||||
|
```
|
||||||
|
|
||||||
|
### Template Errors
|
||||||
|
|
||||||
|
**Error**: Template syntax error
|
||||||
|
|
||||||
|
**Solution**:
|
||||||
|
```bash
|
||||||
|
# View raw template
|
||||||
|
chezmoi cd
|
||||||
|
cat dot_zshrc.tmpl
|
||||||
|
|
||||||
|
# Check template syntax
|
||||||
|
chezmoi cat ~/.zshrc
|
||||||
|
|
||||||
|
# Test specific expression
|
||||||
|
chezmoi execute-template "{{ .chezmoi.os }}"
|
||||||
|
```
|
||||||
|
|
||||||
|
### Reset Everything
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Remove all managed files (DESTRUCTIVE!)
|
||||||
|
chezmoi purge
|
||||||
|
|
||||||
|
# Start fresh
|
||||||
|
chezmoi init https://git.hinrichs.dev/alexander/dotfiles.git
|
||||||
|
chezmoi apply
|
||||||
|
```
|
||||||
|
|
||||||
|
### Re-run Installation Scripts
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Reset script state (scripts will run again)
|
||||||
|
chezmoi state reset --bucket=scriptState
|
||||||
|
|
||||||
|
# Re-apply
|
||||||
|
chezmoi apply
|
||||||
|
```
|
||||||
|
|
||||||
|
### Check Configuration
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# View chezmoi data
|
||||||
|
chezmoi data | less
|
||||||
|
|
||||||
|
# View config file
|
||||||
|
cat ~/.config/chezmoi/chezmoi.yaml
|
||||||
|
|
||||||
|
# Edit config
|
||||||
|
chezmoi edit-config
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Common Patterns
|
||||||
|
|
||||||
|
### Pattern 1: Update Tool on All Machines
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# On your main machine
|
||||||
|
chezmoi edit ~/.config/tool/config
|
||||||
|
chezmoi apply
|
||||||
|
chezmoi cd
|
||||||
|
git add . && git commit -m "feat: update tool config" && git push
|
||||||
|
|
||||||
|
# On other machines
|
||||||
|
chezmoi update
|
||||||
|
```
|
||||||
|
|
||||||
|
### Pattern 2: Add New Tool
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Install and configure
|
||||||
|
sudo emerge tool
|
||||||
|
nvim ~/.config/tool/config
|
||||||
|
|
||||||
|
# Add to chezmoi
|
||||||
|
chezmoi add --recursive ~/.config/tool
|
||||||
|
chezmoi cd
|
||||||
|
git add . && git commit -m "feat: add tool configuration" && git push
|
||||||
|
```
|
||||||
|
|
||||||
|
### Pattern 3: Machine-Specific Config
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Edit template
|
||||||
|
chezmoi edit ~/.zshrc
|
||||||
|
|
||||||
|
# Add machine-specific logic
|
||||||
|
{{ if eq .machine "gentoo-workstation" -}}
|
||||||
|
# Workstation-only config
|
||||||
|
{{- end }}
|
||||||
|
|
||||||
|
# Apply and commit
|
||||||
|
chezmoi apply
|
||||||
|
chezmoi cd && git add . && git commit -m "feat: add workstation config" && git push
|
||||||
|
```
|
||||||
|
|
||||||
|
### Pattern 4: Temporarily Disable Chezmoi
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Edit file directly (bypassing chezmoi)
|
||||||
|
nvim ~/.zshrc
|
||||||
|
|
||||||
|
# Test changes
|
||||||
|
source ~/.zshrc
|
||||||
|
|
||||||
|
# If good, update chezmoi
|
||||||
|
chezmoi add ~/.zshrc
|
||||||
|
chezmoi cd && git add . && git commit -m "feat: update zshrc" && git push
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Best Practices
|
||||||
|
|
||||||
|
1. **Always preview before applying**
|
||||||
|
```bash
|
||||||
|
chezmoi diff # Check what will change
|
||||||
|
chezmoi apply # Then apply
|
||||||
|
```
|
||||||
|
|
||||||
|
2. **Test changes before committing**
|
||||||
|
```bash
|
||||||
|
chezmoi apply
|
||||||
|
# Test the changes
|
||||||
|
# If broken, fix and re-apply
|
||||||
|
# Only commit when working
|
||||||
|
```
|
||||||
|
|
||||||
|
3. **Use templates for cross-platform configs**
|
||||||
|
- OS-specific paths
|
||||||
|
- Package manager commands
|
||||||
|
- Tool locations
|
||||||
|
|
||||||
|
4. **Keep commits atomic and descriptive**
|
||||||
|
```bash
|
||||||
|
# Good
|
||||||
|
git commit -m "feat: add starship prompt configuration"
|
||||||
|
|
||||||
|
# Bad
|
||||||
|
git commit -m "update stuff"
|
||||||
|
```
|
||||||
|
|
||||||
|
5. **Document complex templates**
|
||||||
|
```bash
|
||||||
|
# Add comments in templates
|
||||||
|
# {{ if eq .chezmoi.os "darwin" -}}
|
||||||
|
# macOS uses Homebrew in /opt/homebrew
|
||||||
|
export PATH="/opt/homebrew/bin:$PATH"
|
||||||
|
# {{- end }}
|
||||||
|
```
|
||||||
|
|
||||||
|
6. **Don't commit secrets**
|
||||||
|
- Use `.chezmoiignore` for sensitive files
|
||||||
|
- Or use encryption for files that must be synced
|
||||||
|
|
||||||
|
7. **Test on a VM before deploying widely**
|
||||||
|
- Especially for major changes
|
||||||
|
- Prevents breaking all machines at once
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Resources
|
||||||
|
|
||||||
|
- **Official chezmoi docs**: https://www.chezmoi.io/
|
||||||
|
- **Dotfiles repository**: `~/repository/git.hinrichs.dev/alexander/dotfiles`
|
||||||
|
- **This system's USER-GUIDE.md**: Quick reference for chezmoi commands
|
||||||
|
- **chezmoi GitHub**: https://github.com/twpayne/chezmoi
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Summary
|
||||||
|
|
||||||
|
**Daily workflow:**
|
||||||
|
1. `chezmoi edit ~/.config` - Edit configs
|
||||||
|
2. `chezmoi diff` - Preview changes
|
||||||
|
3. `chezmoi apply` - Apply changes
|
||||||
|
4. `chezmoi cd && git add . && git commit && git push` - Commit
|
||||||
|
5. `chezmoi update` on other machines - Sync
|
||||||
|
|
||||||
|
**Adding new tools:**
|
||||||
|
1. Install and configure the tool
|
||||||
|
2. `chezmoi add ~/.config/tool` - Add to chezmoi
|
||||||
|
3. Commit and push
|
||||||
|
|
||||||
|
**Cross-platform:**
|
||||||
|
1. `chezmoi chattr +template ~/.file` - Make template
|
||||||
|
2. Add `{{ if eq .chezmoi.os "..." }}` logic
|
||||||
|
3. Apply and test on each platform
|
||||||
|
|
||||||
|
Your dotfiles are now version controlled, synced across machines, and managed professionally!
|
||||||
273
Feature-Status.md
Normal file
273
Feature-Status.md
Normal file
@@ -0,0 +1,273 @@
|
|||||||
|
# Feature Status
|
||||||
|
|
||||||
|
## Current State (as of 2025-11-07)
|
||||||
|
|
||||||
|
### Working ✅
|
||||||
|
|
||||||
|
#### Base System
|
||||||
|
- ✅ Base Gentoo installation
|
||||||
|
- ✅ Hyprland window manager running
|
||||||
|
- ✅ ACPI event handling (acpid service)
|
||||||
|
- ✅ Suspend/resume WORKING - elogind integration complete
|
||||||
|
- ✅ Timezone - Europe/Berlin (CET/CEST with automatic DST)
|
||||||
|
- ✅ Kernel optimized - Rebuilt for MediaTek MT7925 WiFi 7 + Bluetooth support
|
||||||
|
|
||||||
|
#### Display & Monitors
|
||||||
|
- ✅ DisplayLink drivers installed and functional
|
||||||
|
- ✅ External monitors detected and working (DVI-I-1, DVI-I-2)
|
||||||
|
- ✅ **DisplayLink artifacts FIXED** - Zero visual glitches
|
||||||
|
- ✅ **Multi-monitor configuration** - 3-monitor mode when docked
|
||||||
|
- ✅ **Lid automation FULLY WORKING** - Smart suspend/monitor switching
|
||||||
|
- ✅ **Monitor Management** - Custom monitor-setup script with swap/reset
|
||||||
|
functionality
|
||||||
|
|
||||||
|
#### Network
|
||||||
|
- ✅ **WiFi Support** - MediaTek MT7925 driver working (interface: wlp194s0)
|
||||||
|
- ✅ **WiFi Management** - Custom wifi-setup script with ZSH autocompletion
|
||||||
|
- ✅ **Waybar WiFi Display** - Shows SSID and signal strength (network module
|
||||||
|
enabled)
|
||||||
|
- ✅ **USB4/Thunderbolt** - Enabled for better dock support
|
||||||
|
|
||||||
|
#### Bluetooth
|
||||||
|
- ✅ **Bluetooth Support** - MediaTek MT7925 Bluetooth 5.4 working (hci0)
|
||||||
|
- ✅ **Bluetooth Management** - Custom bluetooth-setup script with ZSH
|
||||||
|
autocompletion
|
||||||
|
- ✅ **Waybar Bluetooth Display** - Shows connection status and device name
|
||||||
|
|
||||||
|
#### Audio & Media
|
||||||
|
- ✅ **Audio Management** - Custom audio-setup script with ZSH autocompletion
|
||||||
|
- ✅ **Webcam** - Luxvisions Integrated RGB Camera working (640x480@30fps, UVC
|
||||||
|
driver)
|
||||||
|
|
||||||
|
#### Input Devices
|
||||||
|
- ✅ **Touchpad** - ELAN901C I2C HID working (manual kernel compilation with
|
||||||
|
CONFIG_PINCTRL_AMD=y)
|
||||||
|
- ✅ **Touchscreen** - ELAN0678 I2C HID multitouch working (manual kernel
|
||||||
|
compilation with CONFIG_PINCTRL_AMD=y)
|
||||||
|
|
||||||
|
#### Power Management
|
||||||
|
- ✅ **Power Management** - Automatic AC/Battery profiles with ~30-50% battery
|
||||||
|
improvement
|
||||||
|
- ✅ **Battery Conservation** - Charge threshold management (20-80% mode for
|
||||||
|
battery longevity)
|
||||||
|
|
||||||
|
#### UI & Theme
|
||||||
|
- ✅ **Waybar enhanced** - Clear labels, tooltips, auto-adapts to monitors
|
||||||
|
- ✅ **Ghostty Terminal** - Pure Wayland terminal emulator (no X11), set as
|
||||||
|
default
|
||||||
|
- ✅ **Catppuccin Mocha Theme** - Beautiful, cohesive theme applied to Neovim,
|
||||||
|
Hyprland, and Waybar
|
||||||
|
- ✅ **Neovim LSP** - Updated to Neovim 0.11+ native LSP API (vim.lsp.config)
|
||||||
|
|
||||||
|
#### Development Tools
|
||||||
|
- ✅ Go toolchain
|
||||||
|
- ✅ GCC/G++ toolchain
|
||||||
|
- ✅ **Docker** - Container runtime installed
|
||||||
|
|
||||||
|
#### System Management
|
||||||
|
- ✅ **Dotfile Management** - chezmoi installed and configured for
|
||||||
|
cross-platform dotfile sync
|
||||||
|
- ✅ **Backup System** - Automated NAS backups with network trigger (rsync over
|
||||||
|
SSH)
|
||||||
|
- ✅ **Firewall** - nftables firewall installed and running (default deny
|
||||||
|
incoming)
|
||||||
|
|
||||||
|
### In Progress 🔧
|
||||||
|
|
||||||
|
- None currently
|
||||||
|
|
||||||
|
### Incomplete/Missing ⚠️
|
||||||
|
|
||||||
|
- ⚠️ Kotlin toolchain
|
||||||
|
- ⚠️ Android/mobile development environment
|
||||||
|
- ⚠️ IoT tooling (ESP32, Arduino, bare metal flashing tools)
|
||||||
|
- ⚠️ Development environment configuration (IDE setup, shell customization)
|
||||||
|
|
||||||
|
## Requirements - Lid and Monitor Behavior
|
||||||
|
|
||||||
|
1. **Lid closed + External monitors**: Disable laptop screen, continue on
|
||||||
|
externals ✅
|
||||||
|
2. **Lid closed + No externals**: Enter suspend/sleep mode ✅
|
||||||
|
3. **Lid open + Docked**: Three-monitor mode (2 external + laptop) ✅
|
||||||
|
4. **Lid open + Wake from sleep**: Resume all active monitors ✅
|
||||||
|
5. **Dock disconnected**: Switch to mobile-only mode ✅
|
||||||
|
6. **Dock connected**: Auto-detect and enable external monitors ✅
|
||||||
|
7. **Dynamic profiles**: Support different monitor configs ✅
|
||||||
|
8. **Waybar auto-update**: Updates on monitor configuration changes ✅
|
||||||
|
|
||||||
|
## Post-Reboot Checklist (Last Reboot - November 5, 2025)
|
||||||
|
|
||||||
|
All items verified and working! ✅
|
||||||
|
|
||||||
|
### Touchpad and Touchscreen (Latest Addition)
|
||||||
|
- [x] ✅ Touchpad working (ELAN901C I2C HID)
|
||||||
|
- [x] ✅ Touchscreen working (ELAN0678 multitouch)
|
||||||
|
- [x] ✅ i2c-hid-acpi module loads automatically
|
||||||
|
- [x] ✅ Multi-finger gestures working
|
||||||
|
|
||||||
|
### Bluetooth (Auto-Start Verified)
|
||||||
|
- [x] ✅ `bluetoothctl list` shows Bluetooth controller (hci0)
|
||||||
|
- [x] ✅ Bluetooth service starts automatically
|
||||||
|
- [x] ✅ btmtk module loads automatically
|
||||||
|
- [x] ✅ Waybar shows Bluetooth module
|
||||||
|
|
||||||
|
### Existing Features (Regression Testing)
|
||||||
|
- [x] ✅ WiFi connects and shows in waybar
|
||||||
|
- [x] ✅ Power management switches profiles when AC plugged/unplugged
|
||||||
|
- [x] ✅ Lid automation works (close lid → correct behavior)
|
||||||
|
- [x] ✅ Multi-monitor setup works when docked
|
||||||
|
- [x] ✅ Suspend/resume works
|
||||||
|
- [x] ✅ DisplayLink monitors work without artifacts
|
||||||
|
|
||||||
|
## Known Issues
|
||||||
|
|
||||||
|
### None Currently
|
||||||
|
|
||||||
|
All previously identified issues have been resolved:
|
||||||
|
- ✅ Bluetooth controller detection - Fixed (module conflict resolved)
|
||||||
|
- ✅ DisplayLink artifacts - Fixed (Hyprland configuration optimized)
|
||||||
|
- ✅ Lid automation - Fixed (custom ACPI scripts working)
|
||||||
|
- ✅ Power management - Fixed (AC/Battery profiles working)
|
||||||
|
|
||||||
|
## Success Metrics
|
||||||
|
|
||||||
|
- ✅ Zero DisplayLink artifacts
|
||||||
|
- ✅ 100% reliable lid automation
|
||||||
|
- ✅ Waybar survives all transitions
|
||||||
|
- ✅ Three-monitor mode working
|
||||||
|
- ✅ Suspend/resume working
|
||||||
|
- ✅ WiFi working with easy management (WiFi 7)
|
||||||
|
- ✅ Bluetooth working with easy management (BT 5.4)
|
||||||
|
- ✅ Audio management with easy device switching
|
||||||
|
- ✅ Webcam fully functional
|
||||||
|
- ✅ Touchpad fully functional (multi-finger gestures)
|
||||||
|
- ✅ Touchscreen fully functional (multitouch)
|
||||||
|
- ✅ Monitor management with swap/reset functionality
|
||||||
|
- ✅ Ghostty terminal emulator (pure Wayland, no X11)
|
||||||
|
- ✅ Battery conservation system (20-80% for extended lifespan)
|
||||||
|
- ✅ ~30-50% battery life improvement (power profiles)
|
||||||
|
- ✅ Potentially 2x battery lifespan (conservation mode)
|
||||||
|
- ✅ Kernel optimized for exact hardware
|
||||||
|
- ✅ System fully documented
|
||||||
|
- ✅ All critical hardware functional
|
||||||
|
- ✅ Complete suite of management scripts
|
||||||
|
- ✅ **Cohesive Catppuccin Mocha theme** across all applications
|
||||||
|
- ✅ **Neovim LSP** updated to native API (no deprecations)
|
||||||
|
- ✅ **Waybar with Nerd Font icons** and color-coded modules
|
||||||
|
- ✅ **Professional UI** optimized for OLED display
|
||||||
|
- ✅ **Automated backup system** with network trigger and safeguards
|
||||||
|
- ✅ **Firewall protection** blocking all incoming connections
|
||||||
|
|
||||||
|
## Next Tasks
|
||||||
|
|
||||||
|
All core system setup is complete! Remaining tasks are development-specific:
|
||||||
|
|
||||||
|
**Development tools** (User will configure as needed):
|
||||||
|
- Mobile App Development for Ubuntu Touch devices
|
||||||
|
- IoT tooling (ESP32, Arduino, bare metal flashing tools)
|
||||||
|
|
||||||
|
**System is production-ready!** 🚀
|
||||||
|
|
||||||
|
## Session History
|
||||||
|
|
||||||
|
### Session: November 7, 2025
|
||||||
|
|
||||||
|
#### Morning/Afternoon - Backup System Implementation
|
||||||
|
|
||||||
|
**Achievements:**
|
||||||
|
1. ✅ **Backup System** - Complete automated backup system with 4 backup types
|
||||||
|
2. ✅ **Network Trigger** - Auto-backup when NAS detected with multiple
|
||||||
|
safeguards
|
||||||
|
3. ✅ **ZSH Completion** - Tab completion for backup-setup command
|
||||||
|
4. ✅ **Backup Testing** - Successfully tested config backup (26MB to NAS)
|
||||||
|
|
||||||
|
**Technical Details:**
|
||||||
|
- Four backup workers: full, home, incremental, configs
|
||||||
|
- Network trigger daemon with rate limiting and cooldown (1 hour)
|
||||||
|
- Lock file detection and stale marker cleanup (6 hours)
|
||||||
|
- User-space operation (no sudo required for backups)
|
||||||
|
- Logs: `~/.local/var/log/backup.log` and `backup-monitor.log`
|
||||||
|
- OpenRC service: `backup-monitor` running and enabled at boot
|
||||||
|
|
||||||
|
#### Evening - Security Hardening Implementation
|
||||||
|
|
||||||
|
**Achievements:**
|
||||||
|
1. ✅ **nftables Firewall** - Installed and configured (default deny incoming)
|
||||||
|
2. ✅ **fail2ban Configuration** - Created config for SSH protection (optional)
|
||||||
|
3. ✅ **SSH Hardening** - Created hardened config (optional, for SSH server)
|
||||||
|
4. ✅ **Firewall Testing** - Verified internet and NAS connectivity working
|
||||||
|
5. ✅ **Documentation** - Created comprehensive security and backup guides
|
||||||
|
|
||||||
|
**Technical Details:**
|
||||||
|
- nftables with default deny incoming policy
|
||||||
|
- Rate-limited SSH (3 attempts/minute) and ICMP (5/second)
|
||||||
|
- Connection tracking for stateful filtering
|
||||||
|
- Docker support (commented out, ready to enable)
|
||||||
|
- Service running and enabled at boot
|
||||||
|
- Internet and NAS connectivity verified working
|
||||||
|
|
||||||
|
#### Documentation Created
|
||||||
|
|
||||||
|
1. ✅ **Backup-Setup.md** - Complete backup guide (400+ lines)
|
||||||
|
2. ✅ **Security-Hardening.md** - Complete security guide (600+ lines)
|
||||||
|
3. ✅ **USER-GUIDE.md** - Updated with backup and security sections
|
||||||
|
4. ✅ **CLAUDE.md** - Updated with implementation status
|
||||||
|
|
||||||
|
#### Earlier in Session - Dotfile Management
|
||||||
|
|
||||||
|
**Achievements:**
|
||||||
|
- ✅ Dotfile Management - Implemented chezmoi for cross-platform dotfile sync
|
||||||
|
- ✅ Chezmoi Setup - Installed and configured on Gentoo workstation
|
||||||
|
- ✅ Dotfiles Migration - Successfully migrated existing dotfiles
|
||||||
|
- ✅ Dotfiles-Management.md - Created comprehensive chezmoi guide
|
||||||
|
|
||||||
|
**Technical Details:**
|
||||||
|
- Installed chezmoi from GURU repository (version 2.67.0)
|
||||||
|
- Configured chezmoi source at `~/.local/share/chezmoi`
|
||||||
|
- Added existing configs: zsh, git, neovim, tmux, hypr, waybar, bat, starship,
|
||||||
|
ghostty
|
||||||
|
- Created templates for cross-platform configs (.zshrc.tmpl, .gitconfig.tmpl)
|
||||||
|
- Set up git repository integration with Gitea server
|
||||||
|
|
||||||
|
**Documentation Created:**
|
||||||
|
- `Dotfiles-Management.md` - Complete guide with examples and troubleshooting
|
||||||
|
- Updated `USER-GUIDE.md` - Added dotfile management section
|
||||||
|
- Updated `CLAUDE.md` - Added chezmoi to software stack and system scripts
|
||||||
|
|
||||||
|
### Session: November 5, 2025 - Late Evening
|
||||||
|
|
||||||
|
**Achievements:**
|
||||||
|
1. ✅ **Catppuccin Mocha Theme** - Complete system-wide theming for beautiful,
|
||||||
|
cohesive UI
|
||||||
|
2. ✅ **Neovim LSP Migration** - Updated to Neovim 0.11+ native API
|
||||||
|
(vim.lsp.config)
|
||||||
|
3. ✅ **Feline Statusline** - Integrated Catppuccin Mocha colors
|
||||||
|
4. ✅ **Hyprland Theme** - Applied Catppuccin Mocha colors to window borders
|
||||||
|
5. ✅ **Waybar Redesign** - Complete Catppuccin Mocha theme with Nerd Font
|
||||||
|
icons
|
||||||
|
6. ✅ **Documentation** - Comprehensive UI/Theme section added to Claude.md
|
||||||
|
|
||||||
|
**Technical Details:**
|
||||||
|
- Migrated Neovim LSP from deprecated `require('lspconfig')` to native
|
||||||
|
`vim.lsp.config[]` API
|
||||||
|
- Fixed Feline integration with Catppuccin using palette API
|
||||||
|
- Applied Catppuccin Mocha color palette across Hyprland, Waybar, and Neovim
|
||||||
|
- Implemented Nerd Font icons in Waybar using exact UTF-8 glyphs from verified
|
||||||
|
working config
|
||||||
|
- Color-coded all Waybar modules for easy visual identification
|
||||||
|
- Removed obsolete Hyprland shadow settings that caused errors
|
||||||
|
|
||||||
|
**UI/Theme Components:**
|
||||||
|
- Hyprland: Lavender→Mauve gradient on active windows, Surface0 on inactive
|
||||||
|
- Waybar: Full Catppuccin Mocha theme with color-coded modules and Nerd Font
|
||||||
|
icons
|
||||||
|
- Neovim: Updated LSP config, Feline statusline with Mocha colors
|
||||||
|
- Font: Hasklug Nerd Font with proper fallbacks
|
||||||
|
|
||||||
|
### Session: November 5, 2025 - Evening
|
||||||
|
|
||||||
|
**Achievements:**
|
||||||
|
1. ✅ Monitor Management Tool - Interactive monitor-setup script
|
||||||
|
2. ✅ Ghostty Terminal - Pure Wayland terminal (no X11)
|
||||||
|
3. ✅ Battery Conservation - 20-80% charge threshold system
|
||||||
|
4. ✅ Documentation - Comprehensive READMEs
|
||||||
722
Security-Hardening.md
Normal file
722
Security-Hardening.md
Normal file
@@ -0,0 +1,722 @@
|
|||||||
|
# Security Hardening Guide
|
||||||
|
|
||||||
|
Complete guide for hardening the Gentoo workstation with firewall, intrusion
|
||||||
|
prevention, and SSH security.
|
||||||
|
|
||||||
|
## Overview
|
||||||
|
|
||||||
|
This guide covers comprehensive security hardening for a single-user Gentoo
|
||||||
|
development workstation with a focus on practical security without
|
||||||
|
over-engineering.
|
||||||
|
|
||||||
|
## Table of Contents
|
||||||
|
|
||||||
|
- [Security Philosophy](#security-philosophy)
|
||||||
|
- [Threat Model](#threat-model)
|
||||||
|
- [Components](#components)
|
||||||
|
- [Installation](#installation)
|
||||||
|
- [Firewall Configuration](#firewall-configuration)
|
||||||
|
- [Intrusion Prevention](#intrusion-prevention)
|
||||||
|
- [SSH Hardening](#ssh-hardening)
|
||||||
|
- [Additional Security](#additional-security)
|
||||||
|
- [Monitoring](#monitoring)
|
||||||
|
- [Troubleshooting](#troubleshooting)
|
||||||
|
|
||||||
|
## Security Philosophy
|
||||||
|
|
||||||
|
**Pragmatic security approach**:
|
||||||
|
|
||||||
|
1. **Defense in Depth**: Multiple layers of security
|
||||||
|
2. **Minimal Attack Surface**: Only expose what's necessary
|
||||||
|
3. **Fail Securely**: Default deny policies
|
||||||
|
4. **Logging and Monitoring**: Track security events
|
||||||
|
5. **Maintainability**: Keep it simple and documented
|
||||||
|
|
||||||
|
## Threat Model
|
||||||
|
|
||||||
|
### Primary Threats
|
||||||
|
|
||||||
|
1. **Network attacks**: Port scanning, brute force, exploits
|
||||||
|
2. **SSH brute force**: Automated login attempts
|
||||||
|
3. **Malware**: Trojans, backdoors from compromised packages
|
||||||
|
4. **Physical access**: Limited concern (personal workstation)
|
||||||
|
|
||||||
|
### Out of Scope
|
||||||
|
|
||||||
|
- Advanced persistent threats (APTs)
|
||||||
|
- Nation-state actors
|
||||||
|
- Physical security (trusted environment)
|
||||||
|
- Multi-user system hardening (single user)
|
||||||
|
|
||||||
|
## Components
|
||||||
|
|
||||||
|
### 1. nftables Firewall
|
||||||
|
|
||||||
|
Modern Linux firewall with:
|
||||||
|
- Default deny incoming policy
|
||||||
|
- Allow established connections
|
||||||
|
- Rate limiting for services
|
||||||
|
- Connection tracking
|
||||||
|
- Docker support
|
||||||
|
|
||||||
|
### 2. fail2ban
|
||||||
|
|
||||||
|
Intrusion prevention system that:
|
||||||
|
- Monitors SSH login attempts
|
||||||
|
- Automatically bans malicious IPs
|
||||||
|
- Integrates with nftables
|
||||||
|
- Configurable ban times and thresholds
|
||||||
|
|
||||||
|
### 3. SSH Hardening
|
||||||
|
|
||||||
|
Secure SSH configuration:
|
||||||
|
- Modern ciphers only
|
||||||
|
- Key-based authentication
|
||||||
|
- No root login
|
||||||
|
- Connection limits
|
||||||
|
- Logging and monitoring
|
||||||
|
|
||||||
|
## Installation
|
||||||
|
|
||||||
|
### Prerequisites
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Install required packages
|
||||||
|
emerge -av net-firewall/nftables
|
||||||
|
emerge -av net-analyzer/fail2ban
|
||||||
|
emerge -av net-misc/openssh
|
||||||
|
|
||||||
|
# Ensure SSH is configured and working
|
||||||
|
rc-service sshd status
|
||||||
|
```
|
||||||
|
|
||||||
|
### Install Security Components
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cd ~/repository/git.hinrichs.dev/alexander/claude/lenovo-gentoo/scripts/security-setup
|
||||||
|
sudo ./INSTALL.sh
|
||||||
|
```
|
||||||
|
|
||||||
|
**⚠️ CRITICAL**: Keep your current SSH session open until you verify everything
|
||||||
|
works!
|
||||||
|
|
||||||
|
### Installation Steps
|
||||||
|
|
||||||
|
The script will:
|
||||||
|
|
||||||
|
1. ✅ Install nftables firewall configuration
|
||||||
|
2. ✅ Install fail2ban jail configuration
|
||||||
|
3. ✅ Install SSH hardening configuration
|
||||||
|
4. ✅ Backup all existing configs
|
||||||
|
5. ✅ Enable services in OpenRC
|
||||||
|
|
||||||
|
## Firewall Configuration
|
||||||
|
|
||||||
|
### Overview
|
||||||
|
|
||||||
|
The nftables firewall uses a default deny policy with explicit allow rules.
|
||||||
|
|
||||||
|
**Location**: `/etc/nftables.conf`
|
||||||
|
|
||||||
|
### Default Rules
|
||||||
|
|
||||||
|
```
|
||||||
|
INPUT chain (incoming):
|
||||||
|
- DROP everything by default
|
||||||
|
- ACCEPT established/related connections
|
||||||
|
- ACCEPT loopback traffic
|
||||||
|
- ACCEPT ICMP (rate limited)
|
||||||
|
- ACCEPT SSH (rate limited, LAN only)
|
||||||
|
- ACCEPT mDNS (local network discovery)
|
||||||
|
|
||||||
|
FORWARD chain:
|
||||||
|
- DROP everything by default
|
||||||
|
- ACCEPT established/related (for Docker if needed)
|
||||||
|
|
||||||
|
OUTPUT chain:
|
||||||
|
- ACCEPT everything (workstation outgoing)
|
||||||
|
```
|
||||||
|
|
||||||
|
### Key Features
|
||||||
|
|
||||||
|
#### 1. SSH Rate Limiting
|
||||||
|
|
||||||
|
Prevents brute force attacks:
|
||||||
|
|
||||||
|
```nft
|
||||||
|
# Max 3 SSH connections per minute per IP
|
||||||
|
tcp dport 22 ct state new \
|
||||||
|
add @ratelimit_ssh { ip saddr limit rate 3/minute } accept
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 2. ICMP Rate Limiting
|
||||||
|
|
||||||
|
Prevents ping floods:
|
||||||
|
|
||||||
|
```nft
|
||||||
|
# Max 5 pings per second
|
||||||
|
ip protocol icmp icmp type echo-request limit rate 5/second accept
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 3. Connection Tracking
|
||||||
|
|
||||||
|
Tracks connection state for efficient filtering:
|
||||||
|
|
||||||
|
```nft
|
||||||
|
# Allow responses to outgoing connections
|
||||||
|
ct state established,related accept
|
||||||
|
|
||||||
|
# Drop invalid packets
|
||||||
|
ct state invalid drop
|
||||||
|
```
|
||||||
|
|
||||||
|
### Testing Firewall
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Test configuration syntax
|
||||||
|
sudo nft -f /etc/nftables.conf
|
||||||
|
|
||||||
|
# View current rules
|
||||||
|
sudo nft list ruleset
|
||||||
|
|
||||||
|
# Start firewall
|
||||||
|
sudo rc-service nftables start
|
||||||
|
|
||||||
|
# Check status
|
||||||
|
sudo rc-service nftables status
|
||||||
|
```
|
||||||
|
|
||||||
|
### Enable at Boot
|
||||||
|
|
||||||
|
```bash
|
||||||
|
sudo rc-update add nftables default
|
||||||
|
```
|
||||||
|
|
||||||
|
### Customization
|
||||||
|
|
||||||
|
#### Allow Additional Ports
|
||||||
|
|
||||||
|
Edit `/etc/nftables.conf` and add rules in the `input` chain:
|
||||||
|
|
||||||
|
```nft
|
||||||
|
# Allow HTTP/HTTPS
|
||||||
|
tcp dport { 80, 443 } accept
|
||||||
|
|
||||||
|
# Allow custom application
|
||||||
|
tcp dport 8080 accept
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Docker Integration
|
||||||
|
|
||||||
|
Uncomment Docker rules if using Docker:
|
||||||
|
|
||||||
|
```nft
|
||||||
|
# In forward chain:
|
||||||
|
iifname "docker0" accept
|
||||||
|
oifname "docker0" accept
|
||||||
|
|
||||||
|
# In nat table:
|
||||||
|
oifname $lan_interface masquerade
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Block Specific IPs
|
||||||
|
|
||||||
|
```nft
|
||||||
|
# At top of input chain:
|
||||||
|
ip saddr 1.2.3.4 drop
|
||||||
|
ip saddr 5.6.7.0/24 drop
|
||||||
|
```
|
||||||
|
|
||||||
|
## Intrusion Prevention
|
||||||
|
|
||||||
|
### fail2ban Overview
|
||||||
|
|
||||||
|
fail2ban monitors log files and bans IPs with malicious behavior.
|
||||||
|
|
||||||
|
**Location**: `/etc/fail2ban/jail.local`
|
||||||
|
|
||||||
|
### Default Configuration
|
||||||
|
|
||||||
|
```ini
|
||||||
|
[DEFAULT]
|
||||||
|
bantime = 1h # Ban duration
|
||||||
|
findtime = 10m # Time window for maxretry
|
||||||
|
maxretry = 3 # Failed attempts before ban
|
||||||
|
|
||||||
|
[sshd]
|
||||||
|
enabled = true
|
||||||
|
port = ssh
|
||||||
|
maxretry = 3
|
||||||
|
bantime = 1h
|
||||||
|
```
|
||||||
|
|
||||||
|
### Starting fail2ban
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Start service
|
||||||
|
sudo rc-service fail2ban start
|
||||||
|
|
||||||
|
# Check status
|
||||||
|
sudo fail2ban-client status
|
||||||
|
|
||||||
|
# Check SSH jail
|
||||||
|
sudo fail2ban-client status sshd
|
||||||
|
|
||||||
|
# Enable at boot
|
||||||
|
sudo rc-update add fail2ban default
|
||||||
|
```
|
||||||
|
|
||||||
|
### Monitoring
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# View banned IPs
|
||||||
|
sudo fail2ban-client status sshd
|
||||||
|
|
||||||
|
# Unban an IP
|
||||||
|
sudo fail2ban-client set sshd unbanip 1.2.3.4
|
||||||
|
|
||||||
|
# View fail2ban log
|
||||||
|
sudo tail -f /var/log/fail2ban.log
|
||||||
|
```
|
||||||
|
|
||||||
|
### Customization
|
||||||
|
|
||||||
|
#### Adjust Ban Times
|
||||||
|
|
||||||
|
Edit `/etc/fail2ban/jail.local`:
|
||||||
|
|
||||||
|
```ini
|
||||||
|
[sshd]
|
||||||
|
maxretry = 5 # More lenient
|
||||||
|
bantime = 24h # Longer ban
|
||||||
|
findtime = 1h # Longer time window
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Add Email Notifications
|
||||||
|
|
||||||
|
```ini
|
||||||
|
[DEFAULT]
|
||||||
|
destemail = your.email@example.com
|
||||||
|
sendername = Fail2Ban
|
||||||
|
action = %(action_mwl)s # Mail with logs
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Whitelist IPs
|
||||||
|
|
||||||
|
```ini
|
||||||
|
[DEFAULT]
|
||||||
|
ignoreip = 127.0.0.1/8 ::1
|
||||||
|
192.168.1.0/24
|
||||||
|
10.0.0.0/8
|
||||||
|
```
|
||||||
|
|
||||||
|
## SSH Hardening
|
||||||
|
|
||||||
|
### Overview
|
||||||
|
|
||||||
|
Hardened SSH configuration with modern ciphers and security best practices.
|
||||||
|
|
||||||
|
**Location**: `/etc/ssh/sshd_config.d/hardening.conf`
|
||||||
|
|
||||||
|
### Key Security Features
|
||||||
|
|
||||||
|
#### 1. Modern Cryptography
|
||||||
|
|
||||||
|
```
|
||||||
|
# Strong key exchange algorithms
|
||||||
|
KexAlgorithms curve25519-sha256,diffie-hellman-group-exchange-sha256
|
||||||
|
|
||||||
|
# Strong ciphers
|
||||||
|
Ciphers chacha20-poly1305@openssh.com,aes256-gcm@openssh.com
|
||||||
|
|
||||||
|
# Strong MACs
|
||||||
|
MACs hmac-sha2-512-etm@openssh.com,hmac-sha2-256-etm@openssh.com
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 2. Authentication Security
|
||||||
|
|
||||||
|
```
|
||||||
|
PermitRootLogin no # No root login
|
||||||
|
PasswordAuthentication no # Keys only
|
||||||
|
MaxAuthTries 3 # Limit attempts
|
||||||
|
LoginGraceTime 30 # Quick timeout
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 3. Connection Limits
|
||||||
|
|
||||||
|
```
|
||||||
|
MaxSessions 5 # Max concurrent sessions
|
||||||
|
ClientAliveInterval 300 # 5 min keepalive
|
||||||
|
ClientAliveCountMax 2 # 2 missed keepalives = disconnect
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 4. Disable Insecure Features
|
||||||
|
|
||||||
|
```
|
||||||
|
X11Forwarding no # No X11
|
||||||
|
PermitUserEnvironment no # No env manipulation
|
||||||
|
HostbasedAuthentication no # No host-based auth
|
||||||
|
IgnoreRhosts yes # Ignore .rhosts
|
||||||
|
```
|
||||||
|
|
||||||
|
### Testing SSH Configuration
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Test configuration syntax
|
||||||
|
sudo sshd -t
|
||||||
|
|
||||||
|
# Test connection (from another terminal)
|
||||||
|
ssh alexander@localhost
|
||||||
|
|
||||||
|
# View active SSH sessions
|
||||||
|
who
|
||||||
|
|
||||||
|
# View SSH logs
|
||||||
|
sudo tail -f /var/log/auth.log
|
||||||
|
```
|
||||||
|
|
||||||
|
### Apply SSH Changes
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Restart SSH service
|
||||||
|
sudo rc-service sshd restart
|
||||||
|
|
||||||
|
# Or reload configuration
|
||||||
|
sudo kill -HUP $(cat /var/run/sshd.pid)
|
||||||
|
```
|
||||||
|
|
||||||
|
### SSH Key Setup
|
||||||
|
|
||||||
|
If not already using SSH keys:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Generate ED25519 key (modern, secure)
|
||||||
|
ssh-keygen -t ed25519 -C "alexander@lenovo-gentoo"
|
||||||
|
|
||||||
|
# Or RSA 4096 (wider compatibility)
|
||||||
|
ssh-keygen -t rsa -b 4096 -C "alexander@lenovo-gentoo"
|
||||||
|
|
||||||
|
# Copy to remote host
|
||||||
|
ssh-copy-id user@remote-host
|
||||||
|
|
||||||
|
# Test key-based login
|
||||||
|
ssh user@remote-host
|
||||||
|
```
|
||||||
|
|
||||||
|
## Additional Security
|
||||||
|
|
||||||
|
### 1. System Updates
|
||||||
|
|
||||||
|
Keep system updated:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Update package database
|
||||||
|
emerge --sync
|
||||||
|
|
||||||
|
# Check for updates
|
||||||
|
emerge -uDNp @world
|
||||||
|
|
||||||
|
# Install updates
|
||||||
|
emerge -uDN @world
|
||||||
|
|
||||||
|
# Check for security advisories
|
||||||
|
glsa-check -l
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2. Audit Logging
|
||||||
|
|
||||||
|
Enable system auditing:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Install audit daemon
|
||||||
|
emerge -av sys-process/audit
|
||||||
|
|
||||||
|
# Enable service
|
||||||
|
rc-update add auditd default
|
||||||
|
rc-service auditd start
|
||||||
|
|
||||||
|
# View audit logs
|
||||||
|
ausearch -m avc
|
||||||
|
```
|
||||||
|
|
||||||
|
### 3. File Integrity Monitoring
|
||||||
|
|
||||||
|
Use AIDE for file integrity:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Install AIDE
|
||||||
|
emerge -av app-forensics/aide
|
||||||
|
|
||||||
|
# Initialize database
|
||||||
|
aide --init
|
||||||
|
|
||||||
|
# Check for changes
|
||||||
|
aide --check
|
||||||
|
```
|
||||||
|
|
||||||
|
### 4. Kernel Hardening
|
||||||
|
|
||||||
|
Enable kernel security features in `/etc/sysctl.conf`:
|
||||||
|
|
||||||
|
```conf
|
||||||
|
# Prevent IP spoofing
|
||||||
|
net.ipv4.conf.all.rp_filter = 1
|
||||||
|
net.ipv4.conf.default.rp_filter = 1
|
||||||
|
|
||||||
|
# Ignore ICMP redirects
|
||||||
|
net.ipv4.conf.all.accept_redirects = 0
|
||||||
|
net.ipv6.conf.all.accept_redirects = 0
|
||||||
|
|
||||||
|
# Ignore source routed packets
|
||||||
|
net.ipv4.conf.all.accept_source_route = 0
|
||||||
|
net.ipv6.conf.all.accept_source_route = 0
|
||||||
|
|
||||||
|
# Enable SYN cookies
|
||||||
|
net.ipv4.tcp_syncookies = 1
|
||||||
|
|
||||||
|
# Log martian packets
|
||||||
|
net.ipv4.conf.all.log_martians = 1
|
||||||
|
|
||||||
|
# Disable IPv6 if not needed
|
||||||
|
# net.ipv6.conf.all.disable_ipv6 = 1
|
||||||
|
```
|
||||||
|
|
||||||
|
Apply changes:
|
||||||
|
```bash
|
||||||
|
sudo sysctl -p
|
||||||
|
```
|
||||||
|
|
||||||
|
### 5. Automatic Updates (Optional)
|
||||||
|
|
||||||
|
**Note**: Not recommended for Gentoo due to compilation time and potential
|
||||||
|
breakage. Manual updates preferred.
|
||||||
|
|
||||||
|
## Monitoring
|
||||||
|
|
||||||
|
### Security Event Monitoring
|
||||||
|
|
||||||
|
#### 1. Check SSH Login Attempts
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Recent successful logins
|
||||||
|
last -10
|
||||||
|
|
||||||
|
# Failed login attempts
|
||||||
|
sudo grep "Failed password" /var/log/auth.log | tail -20
|
||||||
|
|
||||||
|
# All SSH activity today
|
||||||
|
sudo grep "$(date +%b\ %d)" /var/log/auth.log | grep sshd
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 2. Check Firewall Drops
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# View dropped packets in dmesg
|
||||||
|
sudo dmesg | grep "nftables-drop"
|
||||||
|
|
||||||
|
# View nftables statistics
|
||||||
|
sudo nft list ruleset -a
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 3. Check fail2ban Bans
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Current bans
|
||||||
|
sudo fail2ban-client status sshd
|
||||||
|
|
||||||
|
# Ban history
|
||||||
|
sudo zgrep "Ban " /var/log/fail2ban.log*
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 4. Check Open Ports
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Listening ports
|
||||||
|
sudo ss -tlnp
|
||||||
|
|
||||||
|
# Or with netstat
|
||||||
|
sudo netstat -tlnp
|
||||||
|
```
|
||||||
|
|
||||||
|
### Automated Monitoring Script
|
||||||
|
|
||||||
|
Create `~/bin/security-check`:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
#!/bin/sh
|
||||||
|
# Daily security check script
|
||||||
|
|
||||||
|
echo "Security Status Report - $(date)"
|
||||||
|
echo "======================================"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
echo "SSH Failed Logins (last 24h):"
|
||||||
|
sudo grep "Failed password" /var/log/auth.log | \
|
||||||
|
grep "$(date +%b\ %d)" | wc -l
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
echo "fail2ban Banned IPs:"
|
||||||
|
sudo fail2ban-client status sshd | grep "Banned IP list"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
echo "Open Ports:"
|
||||||
|
sudo ss -tlnp | grep LISTEN
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
echo "Firewall Status:"
|
||||||
|
sudo rc-service nftables status
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
echo "Last 5 Logins:"
|
||||||
|
last -5
|
||||||
|
```
|
||||||
|
|
||||||
|
Make executable:
|
||||||
|
```bash
|
||||||
|
chmod +x ~/bin/security-check
|
||||||
|
```
|
||||||
|
|
||||||
|
Run daily:
|
||||||
|
```bash
|
||||||
|
# Add to crontab
|
||||||
|
crontab -e
|
||||||
|
|
||||||
|
# Daily at 9 AM
|
||||||
|
0 9 * * * ~/bin/security-check | mail -s "Security Report" root
|
||||||
|
```
|
||||||
|
|
||||||
|
## Troubleshooting
|
||||||
|
|
||||||
|
### Firewall Blocks Legitimate Traffic
|
||||||
|
|
||||||
|
**Problem**: Cannot access services after enabling firewall
|
||||||
|
|
||||||
|
**Solution**: Add rules for required services
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Temporarily stop firewall for testing
|
||||||
|
sudo rc-service nftables stop
|
||||||
|
|
||||||
|
# Test service
|
||||||
|
# If it works, firewall is blocking it
|
||||||
|
|
||||||
|
# Add rule to /etc/nftables.conf
|
||||||
|
# Restart firewall
|
||||||
|
sudo rc-service nftables start
|
||||||
|
```
|
||||||
|
|
||||||
|
### Locked Out of SSH
|
||||||
|
|
||||||
|
**Problem**: Cannot SSH after hardening
|
||||||
|
|
||||||
|
**⚠️ Prevention**: Always keep a session open when testing SSH changes!
|
||||||
|
|
||||||
|
**Solution** (requires physical/console access):
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Via console/physical access
|
||||||
|
sudo rc-service sshd stop
|
||||||
|
|
||||||
|
# Restore backup
|
||||||
|
sudo cp /etc/ssh/sshd_config.backup.* /etc/ssh/sshd_config
|
||||||
|
|
||||||
|
# Start SSH
|
||||||
|
sudo rc-service sshd start
|
||||||
|
```
|
||||||
|
|
||||||
|
### fail2ban Not Banning
|
||||||
|
|
||||||
|
**Problem**: fail2ban doesn't ban attackers
|
||||||
|
|
||||||
|
**Check logs**:
|
||||||
|
```bash
|
||||||
|
sudo tail -f /var/log/fail2ban.log
|
||||||
|
```
|
||||||
|
|
||||||
|
**Common issues**:
|
||||||
|
|
||||||
|
1. Wrong log path in jail.local:
|
||||||
|
```bash
|
||||||
|
# Find SSH log location
|
||||||
|
grep "sshd" /var/log/* 2>/dev/null
|
||||||
|
```
|
||||||
|
|
||||||
|
2. Regex doesn't match log format:
|
||||||
|
```bash
|
||||||
|
# Test regex
|
||||||
|
sudo fail2ban-regex /var/log/auth.log /etc/fail2ban/filter.d/sshd.conf
|
||||||
|
```
|
||||||
|
|
||||||
|
3. Service not running:
|
||||||
|
```bash
|
||||||
|
sudo rc-service fail2ban restart
|
||||||
|
```
|
||||||
|
|
||||||
|
### False Positives
|
||||||
|
|
||||||
|
**Problem**: Legitimate IPs getting banned
|
||||||
|
|
||||||
|
**Solution**: Add to whitelist in `/etc/fail2ban/jail.local`:
|
||||||
|
|
||||||
|
```ini
|
||||||
|
[DEFAULT]
|
||||||
|
ignoreip = 127.0.0.1/8 ::1
|
||||||
|
192.168.2.0/24
|
||||||
|
10.0.0.0/8
|
||||||
|
```
|
||||||
|
|
||||||
|
### Performance Issues
|
||||||
|
|
||||||
|
**Problem**: Firewall causing lag
|
||||||
|
|
||||||
|
**Check rules**:
|
||||||
|
```bash
|
||||||
|
# Count rules
|
||||||
|
sudo nft list ruleset | grep -c "rule"
|
||||||
|
|
||||||
|
# Check for expensive operations
|
||||||
|
sudo nft list ruleset -a
|
||||||
|
```
|
||||||
|
|
||||||
|
**Solution**: Optimize rules, reduce logging
|
||||||
|
|
||||||
|
## Security Checklist
|
||||||
|
|
||||||
|
Daily/Weekly tasks:
|
||||||
|
|
||||||
|
- [ ] Check SSH login attempts
|
||||||
|
- [ ] Review fail2ban bans
|
||||||
|
- [ ] Check firewall logs
|
||||||
|
- [ ] Verify services are running
|
||||||
|
- [ ] Review open ports
|
||||||
|
|
||||||
|
Monthly tasks:
|
||||||
|
|
||||||
|
- [ ] Update system packages
|
||||||
|
- [ ] Review firewall rules
|
||||||
|
- [ ] Check for security advisories
|
||||||
|
- [ ] Review user accounts
|
||||||
|
- [ ] Test backup restoration
|
||||||
|
- [ ] Review logs for anomalies
|
||||||
|
|
||||||
|
## Best Practices
|
||||||
|
|
||||||
|
1. **Keep Software Updated**: Regular updates prevent exploits
|
||||||
|
2. **Minimal Services**: Only run what you need
|
||||||
|
3. **Strong Authentication**: Use keys, not passwords
|
||||||
|
4. **Monitor Logs**: Regular log review catches issues early
|
||||||
|
5. **Test Changes**: Always test in safe environment
|
||||||
|
6. **Document Everything**: Keep notes on configuration changes
|
||||||
|
7. **Backup Configs**: Before making changes
|
||||||
|
8. **Defense in Depth**: Multiple security layers
|
||||||
|
9. **Principle of Least Privilege**: Minimal permissions needed
|
||||||
|
10. **Stay Informed**: Follow security news and advisories
|
||||||
|
|
||||||
|
## See Also
|
||||||
|
|
||||||
|
- [Backup-Setup.md](Backup-Setup.md) - Backup system guide
|
||||||
|
- [USER-GUIDE.md](USER-GUIDE.md) - Quick reference guide
|
||||||
|
- [CLAUDE.md](CLAUDE.md) - System overview
|
||||||
|
- `/etc/nftables.conf` - Firewall configuration
|
||||||
|
- `/etc/fail2ban/jail.local` - fail2ban configuration
|
||||||
|
- `/etc/ssh/sshd_config.d/hardening.conf` - SSH hardening
|
||||||
89
System-Overview.md
Normal file
89
System-Overview.md
Normal file
@@ -0,0 +1,89 @@
|
|||||||
|
# System Overview
|
||||||
|
|
||||||
|
## Project Overview
|
||||||
|
|
||||||
|
Setting up a Lenovo ThinkPad as a rock-solid, minimal, high-performance
|
||||||
|
development environment for professional software development.
|
||||||
|
|
||||||
|
## Hardware Specifications
|
||||||
|
|
||||||
|
- **Model**: Lenovo ThinkPad (14")
|
||||||
|
- **CPU**: AMD Ryzen AI 7 PRO 350 (2.0-5.0 GHz)
|
||||||
|
- **RAM**: 96GB DDR5-5600MHz (2x 48GB)
|
||||||
|
- **Storage**: 512GB NVMe PCIe 4.0 TLC Opal SSD
|
||||||
|
- **Display**: 14" 2.8K OLED (2880x1800) @ 30-120Hz VRR, HDR 500
|
||||||
|
- **WiFi**: MediaTek Wi-Fi 7 MT7925 2x2 BE + Bluetooth 5.4
|
||||||
|
- **Dock**: USB-C dock with DisplayLink
|
||||||
|
- **External Monitors**: 2x Shenzhen KTC Q3212RUC (2560x1440 @ 59.95Hz)
|
||||||
|
|
||||||
|
## Software Stack
|
||||||
|
|
||||||
|
- **OS**: Gentoo Linux (OpenRC)
|
||||||
|
- **Kernel**: 6.12.41-gentoo-x86_64 (manual compilation - genkernel NOT used)
|
||||||
|
- **Display Server**: Wayland (no X11)
|
||||||
|
- **Window Manager**: Hyprland 0.49.0 (no XWayland)
|
||||||
|
- **Status Bar**: waybar (with Catppuccin Mocha theme)
|
||||||
|
- **Terminal**: Ghostty (pure Wayland, no X11)
|
||||||
|
- **Editor**: Neovim (with LSP support)
|
||||||
|
- **File Manager**: Midnight Commander (mc)
|
||||||
|
- **Init System**: OpenRC
|
||||||
|
- **Session Manager**: elogind
|
||||||
|
- **Network Manager**: NetworkManager
|
||||||
|
- **Bluetooth**: BlueZ
|
||||||
|
- **Dotfile Management**: chezmoi (cross-platform)
|
||||||
|
- **Theme**: Catppuccin Mocha (consistent across all applications)
|
||||||
|
|
||||||
|
## Development Focus
|
||||||
|
|
||||||
|
- **Backend**: Go services
|
||||||
|
- **Frontend**: Web applications
|
||||||
|
- **Mobile**: Kotlin-based applications
|
||||||
|
- **Systems**: C programming
|
||||||
|
- **IoT**: Embedded electronics, firmware flashing
|
||||||
|
|
||||||
|
## Design Philosophy
|
||||||
|
|
||||||
|
1. **Minimal footprint** - No bloated desktop environments (GNOME/KDE)
|
||||||
|
2. **Performance first** - Slim, fast, responsive
|
||||||
|
3. **Wayland native** - Modern display protocol
|
||||||
|
4. **Single-user system** - Optimized for alexander
|
||||||
|
5. **Rock solid** - Stability and reliability over bleeding edge
|
||||||
|
6. **Development focused** - All tools optimized for professional work
|
||||||
|
|
||||||
|
## System Health
|
||||||
|
|
||||||
|
**Overall Status**: 🟢 Excellent
|
||||||
|
|
||||||
|
**Stability**: Rock solid
|
||||||
|
**Performance**: Optimized
|
||||||
|
**Battery Life**: 30-50% improvement (power profiles) + potentially 2x
|
||||||
|
lifespan (conservation mode)
|
||||||
|
**Hardware Support**: Complete (all input/output devices working)
|
||||||
|
**Management Tools**: Complete suite of interactive scripts
|
||||||
|
**Dotfile Management**: chezmoi configured and syncing across machines
|
||||||
|
**Backup**: Automated NAS backups with network trigger
|
||||||
|
**Security**: nftables firewall running (default deny incoming)
|
||||||
|
**UI/Theme**: Professional Catppuccin Mocha theme with Nerd Font icons
|
||||||
|
**Completeness**: ~99% (all core features complete, only development tools
|
||||||
|
remaining)
|
||||||
|
|
||||||
|
**Ready for production use!** 🚀
|
||||||
|
|
||||||
|
## Documentation
|
||||||
|
|
||||||
|
For complete system information, see:
|
||||||
|
|
||||||
|
**Quick Reference & Status:**
|
||||||
|
- **USER-GUIDE.md** - Quick reference for everyday tasks
|
||||||
|
- **Feature-Status.md** - Current state, working features, session history
|
||||||
|
- **Troubleshooting.md** - Troubleshooting commands and procedures
|
||||||
|
|
||||||
|
**Complete Guides:**
|
||||||
|
- **Backup-Setup.md** - Automated NAS backups, network trigger
|
||||||
|
- **Security-Hardening.md** - Firewall, fail2ban, SSH hardening
|
||||||
|
- **Power-Management-Setup.md** - Power management configuration
|
||||||
|
- **Bluetooth-Setup.md** - Bluetooth setup and troubleshooting
|
||||||
|
- **Dotfiles-Management.md** - Managing dotfiles with chezmoi
|
||||||
|
|
||||||
|
**For Claude Code:**
|
||||||
|
- **CLAUDE.md** - Operational guidelines for working on this project
|
||||||
690
Troubleshooting.md
Normal file
690
Troubleshooting.md
Normal file
@@ -0,0 +1,690 @@
|
|||||||
|
# Troubleshooting Guide
|
||||||
|
|
||||||
|
This guide contains troubleshooting commands and procedures for common issues
|
||||||
|
on the Gentoo ThinkPad system.
|
||||||
|
|
||||||
|
## Bluetooth Issues
|
||||||
|
|
||||||
|
### Check Bluetooth Status
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Check controller
|
||||||
|
bluetoothctl list
|
||||||
|
|
||||||
|
# Check modules
|
||||||
|
lsmod | grep bt
|
||||||
|
|
||||||
|
# Check service
|
||||||
|
rc-service bluetooth status
|
||||||
|
|
||||||
|
# Check kernel messages
|
||||||
|
dmesg | grep -i bluetooth
|
||||||
|
```
|
||||||
|
|
||||||
|
### Full Troubleshooting Guide
|
||||||
|
|
||||||
|
See `Bluetooth-Setup.md` for complete Bluetooth setup, troubleshooting, and
|
||||||
|
technical details.
|
||||||
|
|
||||||
|
## Power Management Issues
|
||||||
|
|
||||||
|
### Check Power Profile Status
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Check logs
|
||||||
|
tail -50 /var/log/power-profile.log
|
||||||
|
|
||||||
|
# Check current state
|
||||||
|
cat /sys/class/power_supply/AC/online # 1 = AC, 0 = battery
|
||||||
|
cat /sys/devices/system/cpu/cpu0/cpufreq/scaling_governor
|
||||||
|
|
||||||
|
# Manual profile test
|
||||||
|
sudo /usr/local/bin/power-profile-ac # Performance mode
|
||||||
|
sudo /usr/local/bin/power-profile-battery # Power saving mode
|
||||||
|
```
|
||||||
|
|
||||||
|
### Full Troubleshooting Guide
|
||||||
|
|
||||||
|
See `Power-Management-Setup.md` for complete details and advanced
|
||||||
|
configuration.
|
||||||
|
|
||||||
|
## WiFi Issues
|
||||||
|
|
||||||
|
### Check WiFi Status
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Check status
|
||||||
|
wifi-setup status
|
||||||
|
|
||||||
|
# Check waybar integration
|
||||||
|
emerge -pv gui-apps/waybar | grep network
|
||||||
|
|
||||||
|
# Check network interface
|
||||||
|
ip link show wlp194s0
|
||||||
|
|
||||||
|
# Check NetworkManager
|
||||||
|
nmcli device status
|
||||||
|
```
|
||||||
|
|
||||||
|
### Full Troubleshooting Guide
|
||||||
|
|
||||||
|
See `scripts/wifi-setup/README.md` for complete setup instructions, usage
|
||||||
|
examples, and troubleshooting.
|
||||||
|
|
||||||
|
## Audio Issues
|
||||||
|
|
||||||
|
### Check Audio Status
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Check status
|
||||||
|
audio-setup status
|
||||||
|
|
||||||
|
# List devices
|
||||||
|
audio-setup list-outputs
|
||||||
|
audio-setup list-inputs
|
||||||
|
|
||||||
|
# Check PulseAudio
|
||||||
|
pactl info
|
||||||
|
|
||||||
|
# Check ALSA
|
||||||
|
aplay -l # List playback devices
|
||||||
|
arecord -l # List recording devices
|
||||||
|
```
|
||||||
|
|
||||||
|
### Full Troubleshooting Guide
|
||||||
|
|
||||||
|
See `scripts/audio-setup/README.md` for complete setup instructions, usage
|
||||||
|
examples, and troubleshooting.
|
||||||
|
|
||||||
|
## Monitor/Lid Issues
|
||||||
|
|
||||||
|
### Check Monitor Configuration
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Check logs
|
||||||
|
cat /tmp/lid-handler.log
|
||||||
|
|
||||||
|
# Check monitor configuration
|
||||||
|
monitor-setup status
|
||||||
|
hyprctl monitors
|
||||||
|
|
||||||
|
# Check ACPI events
|
||||||
|
acpi_listen # Run this, then open/close lid to see events
|
||||||
|
|
||||||
|
# Check elogind
|
||||||
|
loginctl show-session $XDG_SESSION_ID
|
||||||
|
|
||||||
|
# Check Hyprland monitor script
|
||||||
|
/home/alexander/.config/hypr/scripts/monitor-setup.sh
|
||||||
|
```
|
||||||
|
|
||||||
|
### Full Troubleshooting Guides
|
||||||
|
|
||||||
|
- `Lid-Automation-Working-Solution.md` - Lid automation implementation
|
||||||
|
- `Fix-DisplayLink-Artifacts.md` - DisplayLink optimization guide
|
||||||
|
|
||||||
|
## Monitor Management Issues
|
||||||
|
|
||||||
|
### Interactive Monitor Commands
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Check current layout
|
||||||
|
monitor-setup status
|
||||||
|
|
||||||
|
# List all monitors
|
||||||
|
monitor-setup list
|
||||||
|
|
||||||
|
# Swap if order is wrong
|
||||||
|
sudo monitor-setup swap
|
||||||
|
|
||||||
|
# Reset to auto-detection
|
||||||
|
sudo monitor-setup reset
|
||||||
|
```
|
||||||
|
|
||||||
|
### Full Troubleshooting Guide
|
||||||
|
|
||||||
|
See `scripts/monitor-setup/README.md` for complete setup instructions, usage
|
||||||
|
examples, and troubleshooting.
|
||||||
|
|
||||||
|
## Battery Conservation Issues
|
||||||
|
|
||||||
|
### Check Battery Thresholds
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Check current thresholds
|
||||||
|
battery-setup status
|
||||||
|
|
||||||
|
# Check if thresholds are supported
|
||||||
|
ls /sys/class/power_supply/BAT*/charge_control_*_threshold
|
||||||
|
|
||||||
|
# Check OpenRC service
|
||||||
|
rc-service battery-thresholds status
|
||||||
|
|
||||||
|
# Manually set thresholds
|
||||||
|
sudo battery-setup conservation
|
||||||
|
|
||||||
|
# Check battery health
|
||||||
|
cat /sys/class/power_supply/BAT0/capacity
|
||||||
|
cat /sys/class/power_supply/BAT0/cycle_count
|
||||||
|
cat /sys/class/power_supply/BAT0/status
|
||||||
|
|
||||||
|
# Check ThinkPad ACPI module
|
||||||
|
lsmod | grep thinkpad_acpi
|
||||||
|
```
|
||||||
|
|
||||||
|
### Full Troubleshooting Guide
|
||||||
|
|
||||||
|
See `scripts/battery-setup/README.md` for complete setup instructions, battery
|
||||||
|
science, and troubleshooting.
|
||||||
|
|
||||||
|
## Backup Issues
|
||||||
|
|
||||||
|
### Check Backup Status
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Check backup status
|
||||||
|
backup-setup status
|
||||||
|
|
||||||
|
# Check if NAS is reachable
|
||||||
|
ping -c 3 192.168.2.171
|
||||||
|
ssh alexander@192.168.2.171 "echo test"
|
||||||
|
|
||||||
|
# Check network trigger logs
|
||||||
|
tail -20 ~/.local/var/log/backup-monitor.log
|
||||||
|
|
||||||
|
# Check backup logs
|
||||||
|
tail -50 ~/.local/var/log/backup.log
|
||||||
|
|
||||||
|
# Check for active backups
|
||||||
|
ls -la /tmp/backup-*.lock
|
||||||
|
|
||||||
|
# Remove stale lock files (if older than 6 hours)
|
||||||
|
rm /tmp/backup-*.lock
|
||||||
|
|
||||||
|
# Check backup service
|
||||||
|
sudo rc-service backup-monitor status
|
||||||
|
```
|
||||||
|
|
||||||
|
### Manual Backup Commands
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Run manual backup
|
||||||
|
backup-setup full # Full system backup
|
||||||
|
backup-setup home # Home directory only
|
||||||
|
backup-setup configs # Configuration files only
|
||||||
|
backup-setup incremental # Incremental backup
|
||||||
|
|
||||||
|
# Check last backup time
|
||||||
|
cat ~/.local/var/backup/last-backup
|
||||||
|
```
|
||||||
|
|
||||||
|
### Full Troubleshooting Guide
|
||||||
|
|
||||||
|
See `Backup-Setup.md` for complete backup guide - Automated NAS backups,
|
||||||
|
network trigger, troubleshooting.
|
||||||
|
|
||||||
|
## Firewall Issues
|
||||||
|
|
||||||
|
### Check Firewall Status
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Check firewall status
|
||||||
|
sudo rc-service nftables status
|
||||||
|
|
||||||
|
# View firewall rules
|
||||||
|
sudo nft list ruleset
|
||||||
|
|
||||||
|
# Test connectivity
|
||||||
|
ping -c 3 8.8.8.8 # Internet connectivity
|
||||||
|
ping -c 3 192.168.2.171 # NAS connectivity
|
||||||
|
|
||||||
|
# Check if port is blocked
|
||||||
|
sudo nft list ruleset | grep <port_number>
|
||||||
|
|
||||||
|
# Restart firewall
|
||||||
|
sudo rc-service nftables restart
|
||||||
|
|
||||||
|
# Test specific service
|
||||||
|
telnet <host> <port>
|
||||||
|
```
|
||||||
|
|
||||||
|
### Full Troubleshooting Guide
|
||||||
|
|
||||||
|
See `Security-Hardening.md` for complete security guide - Firewall, fail2ban,
|
||||||
|
SSH hardening, monitoring.
|
||||||
|
|
||||||
|
## Ghostty Terminal Issues
|
||||||
|
|
||||||
|
### Check Ghostty Status
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Test if Ghostty works
|
||||||
|
ghostty
|
||||||
|
|
||||||
|
# Check if it's pure Wayland (should show nothing)
|
||||||
|
ldd /usr/bin/ghostty | grep -i x11
|
||||||
|
|
||||||
|
# Check Hyprland keybinding
|
||||||
|
grep ghostty ~/.config/hypr/hyprland.conf
|
||||||
|
|
||||||
|
# Check Ghostty config
|
||||||
|
cat ~/.config/ghostty/config
|
||||||
|
|
||||||
|
# Run Ghostty with debug output
|
||||||
|
ghostty --verbose
|
||||||
|
```
|
||||||
|
|
||||||
|
### Ghostty Configuration
|
||||||
|
|
||||||
|
**Location**: `~/.config/ghostty/config`
|
||||||
|
|
||||||
|
**Package Configuration**: See `CLAUDE.md` section "Ghostty Terminal Emulator"
|
||||||
|
for complete USE flags and build configuration.
|
||||||
|
|
||||||
|
## Neovim/LSP Issues
|
||||||
|
|
||||||
|
### Check LSP Status
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Check LSP servers are working
|
||||||
|
nvim # Open Neovim
|
||||||
|
:LspInfo # Check LSP status
|
||||||
|
|
||||||
|
# Check for LSP errors
|
||||||
|
:messages
|
||||||
|
|
||||||
|
# Verify new API is being used (no deprecation warnings)
|
||||||
|
# Start nvim and check for warnings about lspconfig
|
||||||
|
|
||||||
|
# Test a file with LSP support
|
||||||
|
nvim test.go # Should show LSP features
|
||||||
|
|
||||||
|
# Check Neovim version
|
||||||
|
nvim --version # Should be 0.11+
|
||||||
|
|
||||||
|
# Check LSP config location
|
||||||
|
ls -la ~/.config/nvim/lua/alxndrhi/plugins/lsp.lua
|
||||||
|
```
|
||||||
|
|
||||||
|
### LSP Configuration
|
||||||
|
|
||||||
|
**Location**: `~/.config/nvim/lua/alxndrhi/plugins/lsp.lua`
|
||||||
|
|
||||||
|
**API**: Uses Neovim 0.11+ native `vim.lsp.config[]` API (not deprecated
|
||||||
|
`require('lspconfig')`)
|
||||||
|
|
||||||
|
**Configured Servers**: html, cssls, gopls, clangd, jsonls, yamlls, bashls,
|
||||||
|
dockerls, vimls, lua_ls, ruff, graphql, tailwindcss, vuels, cmake
|
||||||
|
|
||||||
|
## Theme/Waybar Issues
|
||||||
|
|
||||||
|
### Check Waybar Theme
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Check waybar is using correct CSS file
|
||||||
|
# Look for: "Using CSS file /home/alexander/.config/waybar/style.css"
|
||||||
|
killall waybar && waybar 2>&1 | head -20
|
||||||
|
|
||||||
|
# Verify Nerd Font is available
|
||||||
|
fc-list | grep -i hasklug
|
||||||
|
|
||||||
|
# Test icon display in terminal
|
||||||
|
echo "CPU: RAM: WiFi: Volume: "
|
||||||
|
|
||||||
|
# Check if Catppuccin colors are applied
|
||||||
|
cat ~/.config/waybar/style.css | grep "#1e1e2e" # Should show base color
|
||||||
|
|
||||||
|
# Restart waybar to apply changes
|
||||||
|
killall waybar && waybar &
|
||||||
|
|
||||||
|
# Check Hyprland colors
|
||||||
|
hyprctl clients | grep -A 5 "Window" # Should show borders
|
||||||
|
|
||||||
|
# View Hyprland color configuration
|
||||||
|
cat ~/.config/hypr/mocha.conf
|
||||||
|
```
|
||||||
|
|
||||||
|
### Waybar Configuration Files
|
||||||
|
|
||||||
|
- `~/.config/waybar/config` - Module configuration with icon definitions
|
||||||
|
- `~/.config/waybar/style.css` - Catppuccin Mocha theme with color-coded
|
||||||
|
modules
|
||||||
|
- `~/.config/waybar/mocha.css` - Catppuccin Mocha color palette definitions
|
||||||
|
|
||||||
|
### Hyprland Theme Files
|
||||||
|
|
||||||
|
- `~/.config/hypr/hyprland.conf` - Window border colors
|
||||||
|
- `~/.config/hypr/mocha.conf` - Catppuccin Mocha color variables
|
||||||
|
|
||||||
|
## Dotfile Management (chezmoi) Issues
|
||||||
|
|
||||||
|
### Common Chezmoi Problems
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Warning about config template changed
|
||||||
|
chezmoi init
|
||||||
|
|
||||||
|
# Diff shows nothing or just "pppp"
|
||||||
|
chezmoi diff --use-builtin-diff | less
|
||||||
|
|
||||||
|
# File conflicts
|
||||||
|
chezmoi merge ~/.zshrc
|
||||||
|
# Or force overwrite:
|
||||||
|
chezmoi apply --force
|
||||||
|
|
||||||
|
# Template errors
|
||||||
|
chezmoi cat ~/.zshrc # See rendered output
|
||||||
|
chezmoi execute-template "{{ .chezmoi.os }}" # Test expression
|
||||||
|
|
||||||
|
# Re-run installation scripts
|
||||||
|
chezmoi state reset --bucket=scriptState
|
||||||
|
chezmoi apply
|
||||||
|
|
||||||
|
# Check configuration
|
||||||
|
chezmoi data # View all variables
|
||||||
|
cat ~/.config/chezmoi/chezmoi.yaml
|
||||||
|
|
||||||
|
# Remove file from management
|
||||||
|
chezmoi forget ~/.file
|
||||||
|
|
||||||
|
# Complete reset (DESTRUCTIVE - removes all managed files)
|
||||||
|
chezmoi purge
|
||||||
|
```
|
||||||
|
|
||||||
|
### Chezmoi Configuration
|
||||||
|
|
||||||
|
**Source Directory**: `~/.local/share/chezmoi` (git clone of dotfiles repo)
|
||||||
|
|
||||||
|
**Dotfiles Repository**: `~/repository/git.hinrichs.dev/alexander/dotfiles`
|
||||||
|
|
||||||
|
**Config File**: `~/.config/chezmoi/chezmoi.yaml` (generated from
|
||||||
|
`.chezmoi.yaml.tmpl`)
|
||||||
|
|
||||||
|
### Full Troubleshooting Guide
|
||||||
|
|
||||||
|
See `Dotfiles-Management.md` for complete chezmoi guide - Managing dotfiles,
|
||||||
|
adding new tools, editing configs.
|
||||||
|
|
||||||
|
## Kernel Issues
|
||||||
|
|
||||||
|
### Check Kernel Configuration
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Check current kernel version
|
||||||
|
uname -r
|
||||||
|
|
||||||
|
# Extract current running config
|
||||||
|
zcat /proc/config.gz > /tmp/current-config
|
||||||
|
|
||||||
|
# Check specific kernel option
|
||||||
|
zcat /proc/config.gz | grep CONFIG_PINCTRL_AMD
|
||||||
|
|
||||||
|
# Check loaded modules
|
||||||
|
lsmod
|
||||||
|
|
||||||
|
# Check kernel messages
|
||||||
|
dmesg | less
|
||||||
|
|
||||||
|
# Check for kernel errors
|
||||||
|
dmesg | grep -i error
|
||||||
|
dmesg | grep -i fail
|
||||||
|
```
|
||||||
|
|
||||||
|
### Kernel Build Issues
|
||||||
|
|
||||||
|
**⚠️ CRITICAL**: NEVER use genkernel. Always use manual kernel compilation or
|
||||||
|
the automated build script.
|
||||||
|
|
||||||
|
**Build Script**: `scripts/build-kernel.sh`
|
||||||
|
|
||||||
|
**Saved Config**: `kernel-6.12.41-gentoo-x86_64.config`
|
||||||
|
|
||||||
|
**Build Logs**: `logs/kernel-build-TIMESTAMP.log`
|
||||||
|
|
||||||
|
### Manual Kernel Build
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Extract current running config
|
||||||
|
zcat /proc/config.gz > /usr/src/linux/.config
|
||||||
|
|
||||||
|
# Edit config as needed
|
||||||
|
cd /usr/src/linux
|
||||||
|
sudo make menuconfig
|
||||||
|
|
||||||
|
# Or use automated script
|
||||||
|
sudo ./scripts/build-kernel.sh
|
||||||
|
```
|
||||||
|
|
||||||
|
See `CLAUDE.md` section "Kernel Configuration" for complete build process.
|
||||||
|
|
||||||
|
## Touchpad/Touchscreen Issues
|
||||||
|
|
||||||
|
### Check I2C HID Devices
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Check if devices are detected
|
||||||
|
dmesg | grep -i elan
|
||||||
|
|
||||||
|
# Check if modules are loaded
|
||||||
|
lsmod | grep i2c_hid
|
||||||
|
|
||||||
|
# Check device nodes
|
||||||
|
ls -la /dev/input/by-path/ | grep i2c
|
||||||
|
|
||||||
|
# Check Hyprland input devices
|
||||||
|
hyprctl devices
|
||||||
|
|
||||||
|
# Test touchpad events
|
||||||
|
libinput debug-events
|
||||||
|
```
|
||||||
|
|
||||||
|
### Hardware Details
|
||||||
|
|
||||||
|
- **Touchpad**: ELAN901C I2C HID device (ACPI: ELAN901C:00, PNP0C50)
|
||||||
|
- **Touchscreen**: ELAN0678 I2C HID multitouch display (ACPI: ELAN0678:00,
|
||||||
|
PNP0C50)
|
||||||
|
|
||||||
|
### Required Kernel Options
|
||||||
|
|
||||||
|
- `CONFIG_I2C_HID=m`
|
||||||
|
- `CONFIG_I2C_HID_ACPI=m`
|
||||||
|
- `CONFIG_PINCTRL_AMD=y` (CRITICAL for GPIO interrupts on AMD platforms)
|
||||||
|
|
||||||
|
### Full Documentation
|
||||||
|
|
||||||
|
See `Touchpad-Touchscreen-Setup.md` and `POST-REBOOT-CHECKLIST.md`
|
||||||
|
|
||||||
|
## Webcam Issues
|
||||||
|
|
||||||
|
### Check Webcam Status
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Check if webcam is detected
|
||||||
|
lsusb | grep -i camera
|
||||||
|
|
||||||
|
# Check kernel messages
|
||||||
|
dmesg | grep -i uvc
|
||||||
|
|
||||||
|
# List video devices
|
||||||
|
ls -la /dev/video*
|
||||||
|
|
||||||
|
# Check video device capabilities (requires v4l-utils)
|
||||||
|
v4l2-ctl --list-devices
|
||||||
|
v4l2-ctl -d /dev/video0 --list-formats-ext
|
||||||
|
|
||||||
|
# Test capture (requires ffmpeg)
|
||||||
|
ffmpeg -f v4l2 -i /dev/video0 -frames:v 1 test.jpg
|
||||||
|
|
||||||
|
# Check user permissions
|
||||||
|
groups | grep video
|
||||||
|
```
|
||||||
|
|
||||||
|
### Hardware Details
|
||||||
|
|
||||||
|
- **Model**: Luxvisions Innotech Limited Integrated RGB Camera
|
||||||
|
- **USB ID**: 30c9:00f4
|
||||||
|
- **Resolution**: 640x480 @ 30fps (default)
|
||||||
|
- **Driver**: uvcvideo (USB Video Class)
|
||||||
|
- **Device Nodes**: /dev/video0-3
|
||||||
|
|
||||||
|
## Docker Issues
|
||||||
|
|
||||||
|
### Check Docker Status
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Check Docker service
|
||||||
|
rc-service docker status
|
||||||
|
|
||||||
|
# Check Docker version
|
||||||
|
docker --version
|
||||||
|
|
||||||
|
# Test Docker
|
||||||
|
docker run hello-world
|
||||||
|
|
||||||
|
# Check Docker logs
|
||||||
|
docker logs <container_id>
|
||||||
|
|
||||||
|
# Check Docker network
|
||||||
|
docker network ls
|
||||||
|
```
|
||||||
|
|
||||||
|
### Docker Firewall Integration
|
||||||
|
|
||||||
|
If Docker containers cannot reach the internet, check firewall rules:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Check if Docker chain exists in nftables
|
||||||
|
sudo nft list ruleset | grep docker
|
||||||
|
|
||||||
|
# Uncomment Docker forwarding rules in /etc/nftables.conf
|
||||||
|
# Then restart:
|
||||||
|
sudo rc-service nftables restart
|
||||||
|
```
|
||||||
|
|
||||||
|
See `Security-Hardening.md` for Docker firewall integration.
|
||||||
|
|
||||||
|
## General System Troubleshooting
|
||||||
|
|
||||||
|
### Service Management (OpenRC)
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# List all services
|
||||||
|
rc-status -a
|
||||||
|
|
||||||
|
# Start/stop/restart service
|
||||||
|
sudo rc-service <service> start
|
||||||
|
sudo rc-service <service> stop
|
||||||
|
sudo rc-service <service> restart
|
||||||
|
|
||||||
|
# Enable/disable service at boot
|
||||||
|
sudo rc-update add <service> default
|
||||||
|
sudo rc-update del <service> default
|
||||||
|
|
||||||
|
# Check service logs
|
||||||
|
tail -f /var/log/<service>.log
|
||||||
|
```
|
||||||
|
|
||||||
|
### System Logs
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# View system messages
|
||||||
|
dmesg | less
|
||||||
|
|
||||||
|
# View recent errors
|
||||||
|
dmesg | grep -i error | tail -20
|
||||||
|
|
||||||
|
# View kernel ring buffer
|
||||||
|
journalctl -k # If using systemd-journald
|
||||||
|
|
||||||
|
# Check OpenRC logs
|
||||||
|
ls -la /var/log/rc.log
|
||||||
|
```
|
||||||
|
|
||||||
|
### Package Management (Gentoo)
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Search for package
|
||||||
|
emerge --search <package>
|
||||||
|
|
||||||
|
# Check package info
|
||||||
|
emerge --info <package>
|
||||||
|
|
||||||
|
# List installed packages
|
||||||
|
qlist -I
|
||||||
|
|
||||||
|
# Check for config file updates
|
||||||
|
dispatch-conf
|
||||||
|
|
||||||
|
# Rebuild @world
|
||||||
|
emerge -avuDN @world
|
||||||
|
```
|
||||||
|
|
||||||
|
### Performance Monitoring
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# CPU usage
|
||||||
|
top
|
||||||
|
htop
|
||||||
|
|
||||||
|
# Memory usage
|
||||||
|
free -h
|
||||||
|
|
||||||
|
# Disk usage
|
||||||
|
df -h
|
||||||
|
du -sh /*
|
||||||
|
|
||||||
|
# I/O statistics
|
||||||
|
iostat -x 2
|
||||||
|
|
||||||
|
# Network statistics
|
||||||
|
iftop
|
||||||
|
nethogs
|
||||||
|
```
|
||||||
|
|
||||||
|
## Getting Help
|
||||||
|
|
||||||
|
### Documentation Files
|
||||||
|
|
||||||
|
- `USER-GUIDE.md` - Quick reference for everyday tasks
|
||||||
|
- `System-Overview.md` - Hardware specs and software stack
|
||||||
|
- `Feature-Status.md` - Current state and working features
|
||||||
|
- `Backup-Setup.md` - Complete backup guide
|
||||||
|
- `Security-Hardening.md` - Complete security guide
|
||||||
|
- `Power-Management-Setup.md` - Power management guide
|
||||||
|
- `Bluetooth-Setup.md` - Bluetooth setup and troubleshooting
|
||||||
|
- `Dotfiles-Management.md` - Complete chezmoi guide
|
||||||
|
|
||||||
|
### Script Documentation
|
||||||
|
|
||||||
|
- `scripts/wifi-setup/README.md` - WiFi setup tool
|
||||||
|
- `scripts/bluetooth-setup/README.md` - Bluetooth setup tool
|
||||||
|
- `scripts/audio-setup/README.md` - Audio setup tool
|
||||||
|
- `scripts/monitor-setup/README.md` - Monitor setup tool
|
||||||
|
- `scripts/battery-setup/README.md` - Battery conservation tool
|
||||||
|
|
||||||
|
### Emergency Recovery
|
||||||
|
|
||||||
|
If the system becomes unbootable:
|
||||||
|
|
||||||
|
1. Boot from Gentoo LiveCD/USB
|
||||||
|
2. Mount root filesystem: `mount /dev/sdXY /mnt/gentoo`
|
||||||
|
3. Chroot: `chroot /mnt/gentoo /bin/bash`
|
||||||
|
4. Source profile: `source /etc/profile`
|
||||||
|
5. Fix issue (kernel, config, etc.)
|
||||||
|
6. Exit chroot and reboot
|
||||||
|
|
||||||
|
### Backup Restoration
|
||||||
|
|
||||||
|
If you need to restore from backup:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# List available backups on NAS
|
||||||
|
ssh alexander@192.168.2.171 "ls -la /mnt/ssd-pool-a/backups/lenovo-gentoo/"
|
||||||
|
|
||||||
|
# Restore specific backup
|
||||||
|
rsync -avz --progress \
|
||||||
|
alexander@192.168.2.171:/mnt/ssd-pool-a/backups/lenovo-gentoo/YYYY-MM-DD/ \
|
||||||
|
/restore-location/
|
||||||
|
```
|
||||||
|
|
||||||
|
See `Backup-Setup.md` for complete restoration procedures.
|
||||||
385
USER-GUIDE.md
385
USER-GUIDE.md
@@ -8,10 +8,13 @@ Quick reference for everyday tasks on your Gentoo workstation.
|
|||||||
- [Network Management](#network-management)
|
- [Network Management](#network-management)
|
||||||
- [Audio Management](#audio-management)
|
- [Audio Management](#audio-management)
|
||||||
- [Bluetooth Management](#bluetooth-management)
|
- [Bluetooth Management](#bluetooth-management)
|
||||||
|
- [Backup Management](#backup-management)
|
||||||
|
- [Dotfile Management](#dotfile-management)
|
||||||
- [System Updates](#system-updates)
|
- [System Updates](#system-updates)
|
||||||
- [Kernel Management](#kernel-management)
|
- [Kernel Management](#kernel-management)
|
||||||
- [Display & Monitors](#display--monitors)
|
- [Display & Monitors](#display--monitors)
|
||||||
- [Power Management](#power-management)
|
- [Power Management](#power-management)
|
||||||
|
- [Security](#security)
|
||||||
- [System Information](#system-information)
|
- [System Information](#system-information)
|
||||||
|
|
||||||
---
|
---
|
||||||
@@ -314,6 +317,278 @@ exit
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
## Backup Management
|
||||||
|
|
||||||
|
Automated backup system with network trigger and multiple backup types.
|
||||||
|
|
||||||
|
### Using backup-setup Script
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Show backup status
|
||||||
|
backup-setup status
|
||||||
|
|
||||||
|
# Trigger manual backup
|
||||||
|
backup-setup backup [TYPE]
|
||||||
|
|
||||||
|
# List backups on NAS
|
||||||
|
backup-setup list
|
||||||
|
|
||||||
|
# View recent logs
|
||||||
|
backup-setup logs
|
||||||
|
|
||||||
|
# Test NAS connection
|
||||||
|
backup-setup test
|
||||||
|
```
|
||||||
|
|
||||||
|
### Backup Types
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Full system backup (large, slow)
|
||||||
|
backup-setup backup full
|
||||||
|
|
||||||
|
# Home directory only (medium)
|
||||||
|
backup-setup backup home
|
||||||
|
|
||||||
|
# Incremental backup (small, fast)
|
||||||
|
backup-setup backup incremental
|
||||||
|
|
||||||
|
# Configuration files only (tiny, very fast)
|
||||||
|
backup-setup backup configs
|
||||||
|
```
|
||||||
|
|
||||||
|
### Network Trigger Service
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Check monitor status
|
||||||
|
sudo rc-service backup-monitor status
|
||||||
|
|
||||||
|
# View monitor logs
|
||||||
|
tail -f ~/.local/var/log/backup-monitor.log
|
||||||
|
|
||||||
|
# View backup logs
|
||||||
|
tail -f ~/.local/var/log/backup.log
|
||||||
|
|
||||||
|
# Start/stop monitor
|
||||||
|
sudo rc-service backup-monitor start
|
||||||
|
sudo rc-service backup-monitor stop
|
||||||
|
```
|
||||||
|
|
||||||
|
### Manual Backup Scripts
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Run backup scripts directly
|
||||||
|
/usr/local/bin/backup-full
|
||||||
|
/usr/local/bin/backup-home
|
||||||
|
/usr/local/bin/backup-incremental
|
||||||
|
/usr/local/bin/backup-configs
|
||||||
|
```
|
||||||
|
|
||||||
|
For complete backup guide, see: `Backup-Setup.md`
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Dotfile Management
|
||||||
|
|
||||||
|
Dotfiles (configuration files) are managed with **chezmoi** for cross-platform sync across machines.
|
||||||
|
|
||||||
|
### Quick Start
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Edit a dotfile
|
||||||
|
chezmoi edit ~/.zshrc
|
||||||
|
|
||||||
|
# Preview changes
|
||||||
|
chezmoi diff
|
||||||
|
|
||||||
|
# Apply changes
|
||||||
|
chezmoi apply
|
||||||
|
|
||||||
|
# Update from remote repository
|
||||||
|
chezmoi update
|
||||||
|
```
|
||||||
|
|
||||||
|
### Common Tasks
|
||||||
|
|
||||||
|
#### Edit Configuration Files
|
||||||
|
```bash
|
||||||
|
# Edit shell config
|
||||||
|
chezmoi edit ~/.zshrc
|
||||||
|
|
||||||
|
# Edit git config
|
||||||
|
chezmoi edit ~/.gitconfig
|
||||||
|
|
||||||
|
# Edit neovim config
|
||||||
|
chezmoi edit ~/.config/nvim/init.lua
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Add New Configuration Files
|
||||||
|
```bash
|
||||||
|
# Add a new dotfile
|
||||||
|
chezmoi add ~/.newconfig
|
||||||
|
|
||||||
|
# Add entire directory
|
||||||
|
chezmoi add --recursive ~/.config/newtool
|
||||||
|
|
||||||
|
# Add as template (for cross-platform configs)
|
||||||
|
chezmoi add --template ~/.config/tool/config
|
||||||
|
```
|
||||||
|
|
||||||
|
#### View Changes
|
||||||
|
```bash
|
||||||
|
# See what would change
|
||||||
|
chezmoi diff
|
||||||
|
|
||||||
|
# See rendered template
|
||||||
|
chezmoi cat ~/.zshrc
|
||||||
|
|
||||||
|
# Check which files are managed
|
||||||
|
chezmoi managed
|
||||||
|
|
||||||
|
# Show status
|
||||||
|
chezmoi status
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Sync Changes
|
||||||
|
```bash
|
||||||
|
# Pull and apply latest changes from git
|
||||||
|
chezmoi update
|
||||||
|
|
||||||
|
# Apply without pulling
|
||||||
|
chezmoi apply
|
||||||
|
|
||||||
|
# Just pull without applying
|
||||||
|
chezmoi cd
|
||||||
|
git pull
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Commit and Push Changes
|
||||||
|
```bash
|
||||||
|
# Go to chezmoi source directory
|
||||||
|
chezmoi cd
|
||||||
|
|
||||||
|
# Check what changed
|
||||||
|
git status
|
||||||
|
git diff
|
||||||
|
|
||||||
|
# Commit changes
|
||||||
|
git add .
|
||||||
|
git commit -m "feat: update zsh config"
|
||||||
|
git push
|
||||||
|
|
||||||
|
# Return to previous directory
|
||||||
|
exit # or Ctrl+D
|
||||||
|
```
|
||||||
|
|
||||||
|
### Advanced Usage
|
||||||
|
|
||||||
|
#### Convert File to Template
|
||||||
|
```bash
|
||||||
|
# Make a file a template (adds .tmpl extension)
|
||||||
|
chezmoi chattr +template ~/.zshrc
|
||||||
|
|
||||||
|
# Edit the template
|
||||||
|
chezmoi edit ~/.zshrc
|
||||||
|
|
||||||
|
# Add OS-specific logic:
|
||||||
|
# {{ if eq .chezmoi.os "darwin" -}}
|
||||||
|
# macOS-specific config
|
||||||
|
# {{- else if eq .osid "linux-gentoo" -}}
|
||||||
|
# Gentoo-specific config
|
||||||
|
# {{- end }}
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Test Without Applying
|
||||||
|
```bash
|
||||||
|
# Dry run (preview what would happen)
|
||||||
|
chezmoi apply --dry-run --verbose
|
||||||
|
|
||||||
|
# View rendered template
|
||||||
|
chezmoi cat ~/.config/tool/config
|
||||||
|
|
||||||
|
# Execute template expression
|
||||||
|
chezmoi execute-template "{{ .chezmoi.os }}"
|
||||||
|
```
|
||||||
|
|
||||||
|
#### View Configuration
|
||||||
|
```bash
|
||||||
|
# Show chezmoi data (OS, machine type, etc.)
|
||||||
|
chezmoi data
|
||||||
|
|
||||||
|
# Edit chezmoi config
|
||||||
|
chezmoi edit-config
|
||||||
|
|
||||||
|
# Show source path
|
||||||
|
chezmoi source-path
|
||||||
|
```
|
||||||
|
|
||||||
|
### Dotfiles Repository Structure
|
||||||
|
|
||||||
|
```
|
||||||
|
~/repository/git.hinrichs.dev/alexander/dotfiles/ # Main repo
|
||||||
|
~/.local/share/chezmoi/ # Chezmoi working copy
|
||||||
|
~/.config/chezmoi/chezmoi.yaml # Generated config
|
||||||
|
```
|
||||||
|
|
||||||
|
### Adding New Tools
|
||||||
|
|
||||||
|
When you install a new tool with configuration:
|
||||||
|
|
||||||
|
**Step 1: Create the config**
|
||||||
|
```bash
|
||||||
|
# Configure the tool normally
|
||||||
|
nvim ~/.config/newtool/config
|
||||||
|
```
|
||||||
|
|
||||||
|
**Step 2: Test the config**
|
||||||
|
```bash
|
||||||
|
# Make sure it works
|
||||||
|
newtool --version
|
||||||
|
```
|
||||||
|
|
||||||
|
**Step 3: Add to chezmoi**
|
||||||
|
```bash
|
||||||
|
# Add to dotfile management
|
||||||
|
chezmoi add ~/.config/newtool/config
|
||||||
|
|
||||||
|
# Or add entire directory
|
||||||
|
chezmoi add --recursive ~/.config/newtool
|
||||||
|
```
|
||||||
|
|
||||||
|
**Step 4: Commit**
|
||||||
|
```bash
|
||||||
|
# Go to dotfiles repo
|
||||||
|
chezmoi cd
|
||||||
|
|
||||||
|
# Commit
|
||||||
|
git add .
|
||||||
|
git commit -m "feat: add newtool configuration"
|
||||||
|
git push
|
||||||
|
```
|
||||||
|
|
||||||
|
Now the config will sync to all your machines!
|
||||||
|
|
||||||
|
### Troubleshooting
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Reset and regenerate config
|
||||||
|
chezmoi init
|
||||||
|
|
||||||
|
# Force re-apply everything
|
||||||
|
chezmoi apply --force
|
||||||
|
|
||||||
|
# Remove a file from management
|
||||||
|
chezmoi forget ~/.file
|
||||||
|
|
||||||
|
# Purge chezmoi (removes all managed files)
|
||||||
|
chezmoi purge
|
||||||
|
```
|
||||||
|
|
||||||
|
For detailed documentation, see:
|
||||||
|
- `Dotfiles-Management.md` - Complete guide
|
||||||
|
- `~/repository/git.hinrichs.dev/alexander/dotfiles/README.md` - Dotfiles repo docs
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
## System Updates
|
## System Updates
|
||||||
|
|
||||||
### Full System Update
|
### Full System Update
|
||||||
@@ -472,6 +747,88 @@ loginctl suspend
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
## Security
|
||||||
|
|
||||||
|
### Firewall Management (nftables)
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Start firewall
|
||||||
|
sudo rc-service nftables start
|
||||||
|
|
||||||
|
# Check firewall status
|
||||||
|
sudo rc-service nftables status
|
||||||
|
|
||||||
|
# View firewall rules
|
||||||
|
sudo nft list ruleset
|
||||||
|
|
||||||
|
# Reload configuration
|
||||||
|
sudo rc-service nftables restart
|
||||||
|
|
||||||
|
# Enable at boot
|
||||||
|
sudo rc-update add nftables default
|
||||||
|
```
|
||||||
|
|
||||||
|
### Intrusion Prevention (fail2ban)
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Check fail2ban status
|
||||||
|
sudo fail2ban-client status
|
||||||
|
|
||||||
|
# Check SSH jail status
|
||||||
|
sudo fail2ban-client status sshd
|
||||||
|
|
||||||
|
# View banned IPs
|
||||||
|
sudo fail2ban-client status sshd
|
||||||
|
|
||||||
|
# Unban an IP
|
||||||
|
sudo fail2ban-client set sshd unbanip 1.2.3.4
|
||||||
|
|
||||||
|
# View fail2ban log
|
||||||
|
sudo tail -f /var/log/fail2ban.log
|
||||||
|
|
||||||
|
# Enable at boot
|
||||||
|
sudo rc-update add fail2ban default
|
||||||
|
```
|
||||||
|
|
||||||
|
### SSH Security
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Test SSH configuration
|
||||||
|
sudo sshd -t
|
||||||
|
|
||||||
|
# Restart SSH service
|
||||||
|
sudo rc-service sshd restart
|
||||||
|
|
||||||
|
# View SSH logs
|
||||||
|
sudo tail -f /var/log/auth.log
|
||||||
|
|
||||||
|
# View recent SSH logins
|
||||||
|
last -10
|
||||||
|
|
||||||
|
# View failed SSH attempts
|
||||||
|
sudo grep "Failed password" /var/log/auth.log | tail -20
|
||||||
|
```
|
||||||
|
|
||||||
|
### Security Monitoring
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Check open ports
|
||||||
|
sudo ss -tlnp
|
||||||
|
|
||||||
|
# Check SSH login attempts
|
||||||
|
sudo grep "sshd" /var/log/auth.log | tail -20
|
||||||
|
|
||||||
|
# Check for security updates
|
||||||
|
glsa-check -l
|
||||||
|
|
||||||
|
# View system logs
|
||||||
|
sudo tail -f /var/log/messages
|
||||||
|
```
|
||||||
|
|
||||||
|
For complete security hardening guide, see: `Security-Hardening.md`
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
## System Information
|
## System Information
|
||||||
|
|
||||||
### Hardware Information
|
### Hardware Information
|
||||||
@@ -690,6 +1047,9 @@ sudo rm -rf /var/tmp/portage/*
|
|||||||
| WiFi connect | `wifi-setup connect "SSID"` |
|
| WiFi connect | `wifi-setup connect "SSID"` |
|
||||||
| Audio switch | `audio-setup output 2` |
|
| Audio switch | `audio-setup output 2` |
|
||||||
| Bluetooth pair | `bluetooth-setup pair MAC` |
|
| Bluetooth pair | `bluetooth-setup pair MAC` |
|
||||||
|
| Backup status | `backup-setup status` |
|
||||||
|
| Trigger backup | `backup-setup backup incremental` |
|
||||||
|
| Firewall status | `sudo nft list ruleset` |
|
||||||
| Check logs | `tail -f /var/log/messages` |
|
| Check logs | `tail -f /var/log/messages` |
|
||||||
| Disk usage | `df -h` |
|
| Disk usage | `df -h` |
|
||||||
| Free memory | `free -h` |
|
| Free memory | `free -h` |
|
||||||
@@ -715,12 +1075,31 @@ apropos keyword
|
|||||||
- **Package Search**: https://packages.gentoo.org
|
- **Package Search**: https://packages.gentoo.org
|
||||||
|
|
||||||
### Local Documentation
|
### Local Documentation
|
||||||
- Main system overview: `Claude.md`
|
|
||||||
|
**Quick Reference & Overview:**
|
||||||
|
- This guide: `USER-GUIDE.md` - Quick reference for everyday tasks
|
||||||
|
- System overview: `System-Overview.md` - Hardware, software, design
|
||||||
|
- Feature status: `Feature-Status.md` - Working features, session history
|
||||||
|
- Troubleshooting: `Troubleshooting.md` - Troubleshooting all components
|
||||||
|
|
||||||
|
**Complete Guides:**
|
||||||
|
- Backup system: `Backup-Setup.md`
|
||||||
|
- Security hardening: `Security-Hardening.md`
|
||||||
|
- Power management: `Power-Management-Setup.md`
|
||||||
|
- Bluetooth setup: `Bluetooth-Setup.md`
|
||||||
|
- Dotfile management: `Dotfiles-Management.md`
|
||||||
|
- Lid automation: `Lid-Automation-Working-Solution.md`
|
||||||
|
|
||||||
|
**Script Documentation:**
|
||||||
- WiFi setup: `scripts/wifi-setup/README.md`
|
- WiFi setup: `scripts/wifi-setup/README.md`
|
||||||
- Bluetooth setup: `scripts/bluetooth-setup/README.md`
|
- Bluetooth setup: `scripts/bluetooth-setup/README.md`
|
||||||
- Audio setup: `scripts/audio-setup/README.md`
|
- Audio setup: `scripts/audio-setup/README.md`
|
||||||
- Power management: `Power-Management-Setup.md`
|
- Battery conservation: `scripts/battery-setup/README.md`
|
||||||
|
- Monitor management: `scripts/monitor-setup/README.md`
|
||||||
|
|
||||||
|
**For Claude Code:**
|
||||||
|
- Operational guidelines: `CLAUDE.md`
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
**Last Updated**: 2025-11-05
|
**Last Updated**: 2025-11-07
|
||||||
|
|||||||
76
scripts/backup-setup/INSTALL.sh
Executable file
76
scripts/backup-setup/INSTALL.sh
Executable file
@@ -0,0 +1,76 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
# Installation script for backup system
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
|
||||||
|
|
||||||
|
echo "=========================================="
|
||||||
|
echo "Installing Backup System"
|
||||||
|
echo "=========================================="
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# Install backup scripts
|
||||||
|
echo "Installing backup scripts to /usr/local/bin/..."
|
||||||
|
sudo cp "$SCRIPT_DIR/backup-setup" /usr/local/bin/
|
||||||
|
sudo cp "$SCRIPT_DIR/backup-full" /usr/local/bin/
|
||||||
|
sudo cp "$SCRIPT_DIR/backup-home" /usr/local/bin/
|
||||||
|
sudo cp "$SCRIPT_DIR/backup-incremental" /usr/local/bin/
|
||||||
|
sudo cp "$SCRIPT_DIR/backup-configs" /usr/local/bin/
|
||||||
|
|
||||||
|
# Make executable
|
||||||
|
sudo chmod +x /usr/local/bin/backup-setup
|
||||||
|
sudo chmod +x /usr/local/bin/backup-full
|
||||||
|
sudo chmod +x /usr/local/bin/backup-home
|
||||||
|
sudo chmod +x /usr/local/bin/backup-incremental
|
||||||
|
sudo chmod +x /usr/local/bin/backup-configs
|
||||||
|
|
||||||
|
echo "✓ Scripts installed"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# Create directories
|
||||||
|
echo "Creating directories..."
|
||||||
|
sudo mkdir -p /usr/local/share/backup-setup
|
||||||
|
sudo mkdir -p /var/lib/backup
|
||||||
|
sudo touch /var/log/backup.log
|
||||||
|
sudo chmod 644 /var/log/backup.log
|
||||||
|
|
||||||
|
echo "✓ Directories created"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# Copy example config
|
||||||
|
echo "Copying example configuration..."
|
||||||
|
sudo cp "$SCRIPT_DIR/backup.conf.example" /usr/local/share/backup-setup/
|
||||||
|
|
||||||
|
if [ ! -f /etc/backup.conf ]; then
|
||||||
|
sudo cp "$SCRIPT_DIR/backup.conf.example" /etc/backup.conf
|
||||||
|
echo "✓ Configuration file created at /etc/backup.conf"
|
||||||
|
echo ""
|
||||||
|
echo "⚠ IMPORTANT: Edit /etc/backup.conf with your NAS details:"
|
||||||
|
echo " sudo nvim /etc/backup.conf"
|
||||||
|
else
|
||||||
|
echo "✓ Configuration file already exists at /etc/backup.conf"
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "=========================================="
|
||||||
|
echo "Installation Complete!"
|
||||||
|
echo "=========================================="
|
||||||
|
echo ""
|
||||||
|
echo "Next steps:"
|
||||||
|
echo " 1. Configure NAS connection:"
|
||||||
|
echo " sudo nvim /etc/backup.conf"
|
||||||
|
echo ""
|
||||||
|
echo " 2. Set up SSH key authentication:"
|
||||||
|
echo " ssh-keygen -t ed25519 -C \"backup@gentoo-workstation\""
|
||||||
|
echo " ssh-copy-id -p PORT user@nas-host"
|
||||||
|
echo ""
|
||||||
|
echo " 3. Test connection:"
|
||||||
|
echo " backup-setup test"
|
||||||
|
echo ""
|
||||||
|
echo " 4. Run test backup:"
|
||||||
|
echo " backup-setup backup configs"
|
||||||
|
echo ""
|
||||||
|
echo " 5. Check status:"
|
||||||
|
echo " backup-setup status"
|
||||||
|
echo ""
|
||||||
44
scripts/backup-setup/_backup-setup
Normal file
44
scripts/backup-setup/_backup-setup
Normal file
@@ -0,0 +1,44 @@
|
|||||||
|
#compdef backup-setup
|
||||||
|
|
||||||
|
# ZSH completion for backup-setup
|
||||||
|
# Installation: Copy to /usr/local/share/zsh/site-functions/_backup-setup
|
||||||
|
|
||||||
|
_backup-setup() {
|
||||||
|
local -a commands backup_types
|
||||||
|
|
||||||
|
commands=(
|
||||||
|
'status:Show backup status and last backup time'
|
||||||
|
'backup:Trigger a backup'
|
||||||
|
'list:List available backups on NAS'
|
||||||
|
'logs:View recent backup logs'
|
||||||
|
'test:Test NAS connection'
|
||||||
|
'help:Show help message'
|
||||||
|
)
|
||||||
|
|
||||||
|
backup_types=(
|
||||||
|
'full:Full system backup (excludes caches, tmp, build dirs)'
|
||||||
|
'home:Home directory backup only'
|
||||||
|
'incremental:Incremental backup (space-efficient)'
|
||||||
|
'configs:Configuration files backup (lightweight)'
|
||||||
|
)
|
||||||
|
|
||||||
|
_arguments -C \
|
||||||
|
'1:command:->command' \
|
||||||
|
'2:backup-type:->backup_type' \
|
||||||
|
&& return 0
|
||||||
|
|
||||||
|
case $state in
|
||||||
|
command)
|
||||||
|
_describe -t commands 'backup-setup command' commands
|
||||||
|
;;
|
||||||
|
backup_type)
|
||||||
|
if [[ ${words[2]} == "backup" ]]; then
|
||||||
|
_describe -t backup_types 'backup type' backup_types
|
||||||
|
fi
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
_backup-setup "$@"
|
||||||
188
scripts/backup-setup/backup-configs
Normal file
188
scripts/backup-setup/backup-configs
Normal file
@@ -0,0 +1,188 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
# System configuration backup script
|
||||||
|
# Backs up /etc and dotfiles (lightweight backup)
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
# Config
|
||||||
|
CONFIG_FILE="/etc/backup.conf"
|
||||||
|
LOG_DIR="${HOME}/.local/var/log"
|
||||||
|
LOG_FILE="${LOG_DIR}/backup.log"
|
||||||
|
LOCK_FILE="/tmp/backup-configs.lock"
|
||||||
|
|
||||||
|
# Ensure log directory exists
|
||||||
|
mkdir -p "$LOG_DIR"
|
||||||
|
|
||||||
|
# Colors
|
||||||
|
RED='\033[0;31m'
|
||||||
|
GREEN='\033[0;32m'
|
||||||
|
YELLOW='\033[1;33m'
|
||||||
|
BLUE='\033[0;34m'
|
||||||
|
NC='\033[0m'
|
||||||
|
|
||||||
|
log() {
|
||||||
|
echo "[$(date '+%Y-%m-%d %H:%M:%S')] $*" >> "$LOG_FILE"
|
||||||
|
echo "$*"
|
||||||
|
}
|
||||||
|
|
||||||
|
error() {
|
||||||
|
printf "${RED}✖${NC} %s\n" "$1"
|
||||||
|
log "ERROR: $1"
|
||||||
|
}
|
||||||
|
|
||||||
|
info() {
|
||||||
|
printf "${BLUE}ℹ${NC} %s\n" "$1"
|
||||||
|
log "INFO: $1"
|
||||||
|
}
|
||||||
|
|
||||||
|
success() {
|
||||||
|
printf "${GREEN}✓${NC} %s\n" "$1"
|
||||||
|
log "SUCCESS: $1"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Load config
|
||||||
|
if [ ! -f "$CONFIG_FILE" ]; then
|
||||||
|
error "Configuration file not found: $CONFIG_FILE"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# shellcheck source=/dev/null
|
||||||
|
. "$CONFIG_FILE"
|
||||||
|
|
||||||
|
# Create lock file
|
||||||
|
if [ -f "$LOCK_FILE" ]; then
|
||||||
|
error "Config backup already running"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
trap 'rm -f "$LOCK_FILE"' EXIT
|
||||||
|
touch "$LOCK_FILE"
|
||||||
|
|
||||||
|
# Start backup
|
||||||
|
log "=========================================="
|
||||||
|
log "Starting CONFIGURATION BACKUP"
|
||||||
|
log "=========================================="
|
||||||
|
|
||||||
|
# Check NAS connectivity
|
||||||
|
info "Checking NAS connectivity..."
|
||||||
|
if ! ssh -p "$NAS_PORT" -o ConnectTimeout=5 -o BatchMode=yes \
|
||||||
|
"${NAS_USER}@${NAS_HOST}" "echo test" >/dev/null 2>&1; then
|
||||||
|
error "SSH connection to NAS failed"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
success "NAS is reachable"
|
||||||
|
|
||||||
|
# Create backup directory name with timestamp
|
||||||
|
BACKUP_NAME="config-$(date +%Y%m%d-%H%M%S)"
|
||||||
|
BACKUP_DEST="${NAS_USER}@${NAS_HOST}:${NAS_PATH}/${BACKUP_NAME}"
|
||||||
|
|
||||||
|
info "Backup destination: ${BACKUP_DEST}"
|
||||||
|
|
||||||
|
# Create temporary directory for staging
|
||||||
|
TEMP_DIR=$(mktemp -d)
|
||||||
|
trap 'rm -rf "$TEMP_DIR" 2>/dev/null; rm -f "$LOCK_FILE"' EXIT
|
||||||
|
|
||||||
|
CONFIG_STAGE="$TEMP_DIR/configs"
|
||||||
|
mkdir -p "$CONFIG_STAGE"
|
||||||
|
|
||||||
|
# Copy /etc (excluding large/unnecessary files)
|
||||||
|
info "Copying system configs from /etc..."
|
||||||
|
rsync -a --delete \
|
||||||
|
--exclude='ssl/certs' \
|
||||||
|
--exclude='ca-certificates' \
|
||||||
|
/etc/ "$CONFIG_STAGE/etc/" 2>/dev/null || true
|
||||||
|
|
||||||
|
# Copy important dotfiles from home
|
||||||
|
info "Copying dotfiles..."
|
||||||
|
mkdir -p "$CONFIG_STAGE/home"
|
||||||
|
|
||||||
|
# Copy select dotfiles and configs
|
||||||
|
for item in \
|
||||||
|
.zshrc .bashrc .gitconfig .gitmux.conf \
|
||||||
|
.config/nvim \
|
||||||
|
.config/hypr \
|
||||||
|
.config/waybar \
|
||||||
|
.config/tmux \
|
||||||
|
.config/bat \
|
||||||
|
.config/starship.toml \
|
||||||
|
.config/ghostty \
|
||||||
|
.config/alxndrhi \
|
||||||
|
.local/share/chezmoi; do
|
||||||
|
|
||||||
|
if [ -e "/home/alexander/$item" ]; then
|
||||||
|
mkdir -p "$(dirname "$CONFIG_STAGE/home/$item")"
|
||||||
|
cp -r "/home/alexander/$item" "$CONFIG_STAGE/home/$item" 2>/dev/null || true
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
# Copy portage config
|
||||||
|
info "Copying Portage configuration..."
|
||||||
|
if [ -d /etc/portage ]; then
|
||||||
|
mkdir -p "$CONFIG_STAGE/portage"
|
||||||
|
cp -r /etc/portage/* "$CONFIG_STAGE/portage/" 2>/dev/null || true
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Copy system scripts
|
||||||
|
info "Copying custom scripts..."
|
||||||
|
if [ -d /usr/local/bin ]; then
|
||||||
|
mkdir -p "$CONFIG_STAGE/scripts"
|
||||||
|
cp -r /usr/local/bin/* "$CONFIG_STAGE/scripts/" 2>/dev/null || true
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Create a manifest file
|
||||||
|
info "Creating backup manifest..."
|
||||||
|
cat > "$CONFIG_STAGE/MANIFEST.txt" <<EOF
|
||||||
|
Configuration Backup
|
||||||
|
Created: $(date)
|
||||||
|
Hostname: $(hostname)
|
||||||
|
Kernel: $(uname -r)
|
||||||
|
|
||||||
|
Contents:
|
||||||
|
- /etc (system configuration)
|
||||||
|
- Dotfiles from /home/alexander
|
||||||
|
- Portage configuration (/etc/portage)
|
||||||
|
- Custom scripts (/usr/local/bin)
|
||||||
|
|
||||||
|
To restore:
|
||||||
|
rsync -av etc/ /etc/
|
||||||
|
rsync -av home/ /home/alexander/
|
||||||
|
rsync -av portage/ /etc/portage/
|
||||||
|
rsync -av scripts/ /usr/local/bin/
|
||||||
|
EOF
|
||||||
|
|
||||||
|
# Run rsync backup to NAS
|
||||||
|
info "Uploading to NAS..."
|
||||||
|
|
||||||
|
if rsync -avz --delete \
|
||||||
|
--rsync-path="mkdir -p ${NAS_PATH}/${BACKUP_NAME} && rsync" \
|
||||||
|
-e "ssh -p ${NAS_PORT}" \
|
||||||
|
"$CONFIG_STAGE/" \
|
||||||
|
"$BACKUP_DEST" >> "$LOG_FILE" 2>&1; then
|
||||||
|
|
||||||
|
success "Backup completed successfully!"
|
||||||
|
|
||||||
|
# Update last backup timestamp
|
||||||
|
LAST_BACKUP_FILE="${HOME}/.local/var/backup/last-backup"
|
||||||
|
mkdir -p "$(dirname "$LAST_BACKUP_FILE")"
|
||||||
|
date +%s > "$LAST_BACKUP_FILE"
|
||||||
|
|
||||||
|
# Log backup size
|
||||||
|
BACKUP_SIZE=$(ssh -p "$NAS_PORT" "${NAS_USER}@${NAS_HOST}" \
|
||||||
|
"du -sh '${NAS_PATH}/${BACKUP_NAME}' 2>/dev/null | cut -f1" || echo "unknown")
|
||||||
|
info "Backup size: $BACKUP_SIZE"
|
||||||
|
|
||||||
|
# Clean up old backups
|
||||||
|
info "Cleaning up old backups (keeping last ${RETENTION_COUNT})..."
|
||||||
|
ssh -p "$NAS_PORT" "${NAS_USER}@${NAS_HOST}" \
|
||||||
|
"cd '${NAS_PATH}' && ls -t | grep '^config-' | tail -n +$((RETENTION_COUNT + 1)) | xargs -r rm -rf" \
|
||||||
|
>> "$LOG_FILE" 2>&1 || true
|
||||||
|
|
||||||
|
else
|
||||||
|
error "Backup failed! Check $LOG_FILE for details"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
log "=========================================="
|
||||||
|
log "Backup completed at $(date)"
|
||||||
|
log "=========================================="
|
||||||
142
scripts/backup-setup/backup-full
Normal file
142
scripts/backup-setup/backup-full
Normal file
@@ -0,0 +1,142 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
# Full system backup script
|
||||||
|
# Backs up entire system except excluded directories
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
# Config
|
||||||
|
CONFIG_FILE="/etc/backup.conf"
|
||||||
|
LOG_DIR="${HOME}/.local/var/log"
|
||||||
|
LOG_FILE="${LOG_DIR}/backup.log"
|
||||||
|
LOCK_FILE="/tmp/backup-full.lock"
|
||||||
|
|
||||||
|
# Ensure log directory exists
|
||||||
|
mkdir -p "$LOG_DIR"
|
||||||
|
|
||||||
|
# Colors
|
||||||
|
RED='\033[0;31m'
|
||||||
|
GREEN='\033[0;32m'
|
||||||
|
YELLOW='\033[1;33m'
|
||||||
|
BLUE='\033[0;34m'
|
||||||
|
NC='\033[0m'
|
||||||
|
|
||||||
|
log() {
|
||||||
|
echo "[$(date '+%Y-%m-%d %H:%M:%S')] $*" >> "$LOG_FILE"
|
||||||
|
echo "$*"
|
||||||
|
}
|
||||||
|
|
||||||
|
error() {
|
||||||
|
printf "${RED}✖${NC} %s\n" "$1"
|
||||||
|
log "ERROR: $1"
|
||||||
|
}
|
||||||
|
|
||||||
|
info() {
|
||||||
|
printf "${BLUE}ℹ${NC} %s\n" "$1"
|
||||||
|
log "INFO: $1"
|
||||||
|
}
|
||||||
|
|
||||||
|
success() {
|
||||||
|
printf "${GREEN}✓${NC} %s\n" "$1"
|
||||||
|
log "SUCCESS: $1"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Load config
|
||||||
|
if [ ! -f "$CONFIG_FILE" ]; then
|
||||||
|
error "Configuration file not found: $CONFIG_FILE"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# shellcheck source=/dev/null
|
||||||
|
. "$CONFIG_FILE"
|
||||||
|
|
||||||
|
# Create lock file
|
||||||
|
if [ -f "$LOCK_FILE" ]; then
|
||||||
|
error "Backup already running (lock file exists: $LOCK_FILE)"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
trap 'rm -f "$LOCK_FILE"' EXIT
|
||||||
|
touch "$LOCK_FILE"
|
||||||
|
|
||||||
|
# Check cooldown
|
||||||
|
if [ -f "$LAST_BACKUP_FILE" ]; then
|
||||||
|
LAST_BACKUP=$(cat "$LAST_BACKUP_FILE")
|
||||||
|
NOW=$(date +%s)
|
||||||
|
ELAPSED=$((NOW - LAST_BACKUP))
|
||||||
|
|
||||||
|
if [ "$ELAPSED" -lt "$BACKUP_COOLDOWN" ]; then
|
||||||
|
REMAINING=$((BACKUP_COOLDOWN - ELAPSED))
|
||||||
|
error "Backup cooldown active. Wait ${REMAINING}s before next backup"
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Start backup
|
||||||
|
log "=========================================="
|
||||||
|
log "Starting FULL SYSTEM BACKUP"
|
||||||
|
log "=========================================="
|
||||||
|
|
||||||
|
# Check NAS connectivity
|
||||||
|
info "Checking NAS connectivity..."
|
||||||
|
if ! ping -c 1 -W 2 "$NAS_HOST" >/dev/null 2>&1; then
|
||||||
|
error "NAS host $NAS_HOST is not reachable"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if ! ssh -p "$NAS_PORT" -o ConnectTimeout=5 -o BatchMode=yes \
|
||||||
|
"${NAS_USER}@${NAS_HOST}" "echo test" >/dev/null 2>&1; then
|
||||||
|
error "SSH connection to NAS failed"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
success "NAS is reachable"
|
||||||
|
|
||||||
|
# Create backup directory name with timestamp
|
||||||
|
BACKUP_NAME="full-$(date +%Y%m%d-%H%M%S)"
|
||||||
|
BACKUP_DEST="${NAS_USER}@${NAS_HOST}:${NAS_PATH}/${BACKUP_NAME}"
|
||||||
|
|
||||||
|
info "Backup destination: ${BACKUP_DEST}"
|
||||||
|
|
||||||
|
# Build exclude arguments for rsync
|
||||||
|
EXCLUDE_ARGS=""
|
||||||
|
for pattern in "${EXCLUDE_PATTERNS[@]}"; do
|
||||||
|
EXCLUDE_ARGS="$EXCLUDE_ARGS --exclude=$pattern"
|
||||||
|
done
|
||||||
|
|
||||||
|
# Run rsync backup
|
||||||
|
info "Starting rsync (this may take a while)..."
|
||||||
|
|
||||||
|
# shellcheck disable=SC2086
|
||||||
|
if rsync -avz --delete --numeric-ids \
|
||||||
|
--rsync-path="mkdir -p ${NAS_PATH}/${BACKUP_NAME} && rsync" \
|
||||||
|
-e "ssh -p ${NAS_PORT}" \
|
||||||
|
$EXCLUDE_ARGS \
|
||||||
|
/ \
|
||||||
|
"$BACKUP_DEST" >> "$LOG_FILE" 2>&1; then
|
||||||
|
|
||||||
|
success "Backup completed successfully!"
|
||||||
|
|
||||||
|
# Update last backup timestamp
|
||||||
|
LAST_BACKUP_FILE="${HOME}/.local/var/backup/last-backup"
|
||||||
|
mkdir -p "$(dirname "$LAST_BACKUP_FILE")"
|
||||||
|
date +%s > "$LAST_BACKUP_FILE"
|
||||||
|
|
||||||
|
# Log backup size
|
||||||
|
BACKUP_SIZE=$(ssh -p "$NAS_PORT" "${NAS_USER}@${NAS_HOST}" \
|
||||||
|
"du -sh '${NAS_PATH}/${BACKUP_NAME}' 2>/dev/null | cut -f1" || echo "unknown")
|
||||||
|
info "Backup size: $BACKUP_SIZE"
|
||||||
|
|
||||||
|
# Clean up old backups (keep last N)
|
||||||
|
info "Cleaning up old backups (keeping last ${RETENTION_COUNT})..."
|
||||||
|
ssh -p "$NAS_PORT" "${NAS_USER}@${NAS_HOST}" \
|
||||||
|
"cd '${NAS_PATH}' && ls -t | grep '^full-' | tail -n +$((RETENTION_COUNT + 1)) | xargs -r rm -rf" \
|
||||||
|
>> "$LOG_FILE" 2>&1 || true
|
||||||
|
|
||||||
|
else
|
||||||
|
error "Backup failed! Check $LOG_FILE for details"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
log "=========================================="
|
||||||
|
log "Backup completed at $(date)"
|
||||||
|
log "=========================================="
|
||||||
129
scripts/backup-setup/backup-home
Normal file
129
scripts/backup-setup/backup-home
Normal file
@@ -0,0 +1,129 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
# Home directory backup script
|
||||||
|
# Backs up /home/alexander only
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
# Config
|
||||||
|
CONFIG_FILE="/etc/backup.conf"
|
||||||
|
LOG_DIR="${HOME}/.local/var/log"
|
||||||
|
LOG_FILE="${LOG_DIR}/backup.log"
|
||||||
|
LOCK_FILE="/tmp/backup-home.lock"
|
||||||
|
|
||||||
|
# Ensure log directory exists
|
||||||
|
mkdir -p "$LOG_DIR"
|
||||||
|
|
||||||
|
# Colors
|
||||||
|
RED='\033[0;31m'
|
||||||
|
GREEN='\033[0;32m'
|
||||||
|
YELLOW='\033[1;33m'
|
||||||
|
BLUE='\033[0;34m'
|
||||||
|
NC='\033[0m'
|
||||||
|
|
||||||
|
log() {
|
||||||
|
echo "[$(date '+%Y-%m-%d %H:%M:%S')] $*" >> "$LOG_FILE"
|
||||||
|
echo "$*"
|
||||||
|
}
|
||||||
|
|
||||||
|
error() {
|
||||||
|
printf "${RED}✖${NC} %s\n" "$1"
|
||||||
|
log "ERROR: $1"
|
||||||
|
}
|
||||||
|
|
||||||
|
info() {
|
||||||
|
printf "${BLUE}ℹ${NC} %s\n" "$1"
|
||||||
|
log "INFO: $1"
|
||||||
|
}
|
||||||
|
|
||||||
|
success() {
|
||||||
|
printf "${GREEN}✓${NC} %s\n" "$1"
|
||||||
|
log "SUCCESS: $1"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Load config
|
||||||
|
if [ ! -f "$CONFIG_FILE" ]; then
|
||||||
|
error "Configuration file not found: $CONFIG_FILE"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# shellcheck source=/dev/null
|
||||||
|
. "$CONFIG_FILE"
|
||||||
|
|
||||||
|
# Create lock file
|
||||||
|
if [ -f "$LOCK_FILE" ]; then
|
||||||
|
error "Home backup already running"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
trap 'rm -f "$LOCK_FILE"' EXIT
|
||||||
|
touch "$LOCK_FILE"
|
||||||
|
|
||||||
|
# Start backup
|
||||||
|
log "=========================================="
|
||||||
|
log "Starting HOME DIRECTORY BACKUP"
|
||||||
|
log "=========================================="
|
||||||
|
|
||||||
|
# Check NAS connectivity
|
||||||
|
info "Checking NAS connectivity..."
|
||||||
|
if ! ssh -p "$NAS_PORT" -o ConnectTimeout=5 -o BatchMode=yes \
|
||||||
|
"${NAS_USER}@${NAS_HOST}" "echo test" >/dev/null 2>&1; then
|
||||||
|
error "SSH connection to NAS failed"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
success "NAS is reachable"
|
||||||
|
|
||||||
|
# Create backup directory name with timestamp
|
||||||
|
BACKUP_NAME="home-$(date +%Y%m%d-%H%M%S)"
|
||||||
|
BACKUP_DEST="${NAS_USER}@${NAS_HOST}:${NAS_PATH}/${BACKUP_NAME}"
|
||||||
|
|
||||||
|
info "Backup destination: ${BACKUP_DEST}"
|
||||||
|
|
||||||
|
# Exclude cache and temporary files from home
|
||||||
|
HOME_EXCLUDES="
|
||||||
|
--exclude=.cache
|
||||||
|
--exclude=.local/share/Trash
|
||||||
|
--exclude=Downloads/*.iso
|
||||||
|
--exclude=Downloads/*.mp4
|
||||||
|
--exclude=Downloads/*.mkv
|
||||||
|
--exclude=.mozilla/firefox/*/Cache
|
||||||
|
--exclude=.config/google-chrome/*/Cache
|
||||||
|
"
|
||||||
|
|
||||||
|
# Run rsync backup
|
||||||
|
info "Starting rsync (this may take a while)..."
|
||||||
|
|
||||||
|
# shellcheck disable=SC2086
|
||||||
|
if rsync -avz --delete --numeric-ids \
|
||||||
|
--rsync-path="mkdir -p ${NAS_PATH}/${BACKUP_NAME} && rsync" \
|
||||||
|
-e "ssh -p ${NAS_PORT}" \
|
||||||
|
$HOME_EXCLUDES \
|
||||||
|
/home/alexander \
|
||||||
|
"$BACKUP_DEST" >> "$LOG_FILE" 2>&1; then
|
||||||
|
|
||||||
|
success "Backup completed successfully!"
|
||||||
|
|
||||||
|
# Update last backup timestamp
|
||||||
|
LAST_BACKUP_FILE="${HOME}/.local/var/backup/last-backup"
|
||||||
|
mkdir -p "$(dirname "$LAST_BACKUP_FILE")"
|
||||||
|
date +%s > "$LAST_BACKUP_FILE"
|
||||||
|
|
||||||
|
# Log backup size
|
||||||
|
BACKUP_SIZE=$(ssh -p "$NAS_PORT" "${NAS_USER}@${NAS_HOST}" \
|
||||||
|
"du -sh '${NAS_PATH}/${BACKUP_NAME}' 2>/dev/null | cut -f1" || echo "unknown")
|
||||||
|
info "Backup size: $BACKUP_SIZE"
|
||||||
|
|
||||||
|
# Clean up old backups
|
||||||
|
info "Cleaning up old backups (keeping last ${RETENTION_COUNT})..."
|
||||||
|
ssh -p "$NAS_PORT" "${NAS_USER}@${NAS_HOST}" \
|
||||||
|
"cd '${NAS_PATH}' && ls -t | grep '^home-' | tail -n +$((RETENTION_COUNT + 1)) | xargs -r rm -rf" \
|
||||||
|
>> "$LOG_FILE" 2>&1 || true
|
||||||
|
|
||||||
|
else
|
||||||
|
error "Backup failed! Check $LOG_FILE for details"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
log "=========================================="
|
||||||
|
log "Backup completed at $(date)"
|
||||||
|
log "=========================================="
|
||||||
138
scripts/backup-setup/backup-incremental
Normal file
138
scripts/backup-setup/backup-incremental
Normal file
@@ -0,0 +1,138 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
# Incremental backup script
|
||||||
|
# Uses rsync with --link-dest to save space
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
# Config
|
||||||
|
CONFIG_FILE="/etc/backup.conf"
|
||||||
|
LOG_DIR="${HOME}/.local/var/log"
|
||||||
|
LOG_FILE="${LOG_DIR}/backup.log"
|
||||||
|
LOCK_FILE="/tmp/backup-incremental.lock"
|
||||||
|
|
||||||
|
# Ensure log directory exists
|
||||||
|
mkdir -p "$LOG_DIR"
|
||||||
|
|
||||||
|
# Colors
|
||||||
|
RED='\033[0;31m'
|
||||||
|
GREEN='\033[0;32m'
|
||||||
|
YELLOW='\033[1;33m'
|
||||||
|
BLUE='\033[0;34m'
|
||||||
|
NC='\033[0m'
|
||||||
|
|
||||||
|
log() {
|
||||||
|
echo "[$(date '+%Y-%m-%d %H:%M:%S')] $*" >> "$LOG_FILE"
|
||||||
|
echo "$*"
|
||||||
|
}
|
||||||
|
|
||||||
|
error() {
|
||||||
|
printf "${RED}✖${NC} %s\n" "$1"
|
||||||
|
log "ERROR: $1"
|
||||||
|
}
|
||||||
|
|
||||||
|
info() {
|
||||||
|
printf "${BLUE}ℹ${NC} %s\n" "$1"
|
||||||
|
log "INFO: $1"
|
||||||
|
}
|
||||||
|
|
||||||
|
success() {
|
||||||
|
printf "${GREEN}✓${NC} %s\n" "$1"
|
||||||
|
log "SUCCESS: $1"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Load config
|
||||||
|
if [ ! -f "$CONFIG_FILE" ]; then
|
||||||
|
error "Configuration file not found: $CONFIG_FILE"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# shellcheck source=/dev/null
|
||||||
|
. "$CONFIG_FILE"
|
||||||
|
|
||||||
|
# Create lock file
|
||||||
|
if [ -f "$LOCK_FILE" ]; then
|
||||||
|
error "Incremental backup already running"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
trap 'rm -f "$LOCK_FILE"' EXIT
|
||||||
|
touch "$LOCK_FILE"
|
||||||
|
|
||||||
|
# Start backup
|
||||||
|
log "=========================================="
|
||||||
|
log "Starting INCREMENTAL BACKUP"
|
||||||
|
log "=========================================="
|
||||||
|
|
||||||
|
# Check NAS connectivity
|
||||||
|
info "Checking NAS connectivity..."
|
||||||
|
if ! ssh -p "$NAS_PORT" -o ConnectTimeout=5 -o BatchMode=yes \
|
||||||
|
"${NAS_USER}@${NAS_HOST}" "echo test" >/dev/null 2>&1; then
|
||||||
|
error "SSH connection to NAS failed"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
success "NAS is reachable"
|
||||||
|
|
||||||
|
# Find latest backup to use as link-dest
|
||||||
|
LATEST_BACKUP=$(ssh -p "$NAS_PORT" "${NAS_USER}@${NAS_HOST}" \
|
||||||
|
"cd '${NAS_PATH}' && ls -t | grep '^incr-\\|^full-' | head -1" 2>/dev/null || echo "")
|
||||||
|
|
||||||
|
# Create backup directory name with timestamp
|
||||||
|
BACKUP_NAME="incr-$(date +%Y%m%d-%H%M%S)"
|
||||||
|
BACKUP_DEST="${NAS_USER}@${NAS_HOST}:${NAS_PATH}/${BACKUP_NAME}"
|
||||||
|
|
||||||
|
info "Backup destination: ${BACKUP_DEST}"
|
||||||
|
|
||||||
|
# Build exclude arguments
|
||||||
|
EXCLUDE_ARGS=""
|
||||||
|
for pattern in "${EXCLUDE_PATTERNS[@]}"; do
|
||||||
|
EXCLUDE_ARGS="$EXCLUDE_ARGS --exclude=$pattern"
|
||||||
|
done
|
||||||
|
|
||||||
|
# Build link-dest argument if previous backup exists
|
||||||
|
LINK_DEST_ARG=""
|
||||||
|
if [ -n "$LATEST_BACKUP" ]; then
|
||||||
|
info "Using $LATEST_BACKUP as base for incremental backup"
|
||||||
|
LINK_DEST_ARG="--link-dest=${NAS_PATH}/${LATEST_BACKUP}"
|
||||||
|
else
|
||||||
|
info "No previous backup found, creating full backup"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Run rsync backup
|
||||||
|
info "Starting rsync (this may take a while)..."
|
||||||
|
|
||||||
|
# shellcheck disable=SC2086
|
||||||
|
if rsync -avz --numeric-ids \
|
||||||
|
--rsync-path="mkdir -p ${NAS_PATH}/${BACKUP_NAME} && rsync" \
|
||||||
|
-e "ssh -p ${NAS_PORT}" \
|
||||||
|
$LINK_DEST_ARG \
|
||||||
|
$EXCLUDE_ARGS \
|
||||||
|
/ \
|
||||||
|
"$BACKUP_DEST" >> "$LOG_FILE" 2>&1; then
|
||||||
|
|
||||||
|
success "Backup completed successfully!"
|
||||||
|
|
||||||
|
# Update last backup timestamp
|
||||||
|
LAST_BACKUP_FILE="${HOME}/.local/var/backup/last-backup"
|
||||||
|
mkdir -p "$(dirname "$LAST_BACKUP_FILE")"
|
||||||
|
date +%s > "$LAST_BACKUP_FILE"
|
||||||
|
|
||||||
|
# Log backup size
|
||||||
|
BACKUP_SIZE=$(ssh -p "$NAS_PORT" "${NAS_USER}@${NAS_HOST}" \
|
||||||
|
"du -sh '${NAS_PATH}/${BACKUP_NAME}' 2>/dev/null | cut -f1" || echo "unknown")
|
||||||
|
info "Backup size: $BACKUP_SIZE"
|
||||||
|
|
||||||
|
# Clean up old backups
|
||||||
|
info "Cleaning up old backups (keeping last ${RETENTION_COUNT})..."
|
||||||
|
ssh -p "$NAS_PORT" "${NAS_USER}@${NAS_HOST}" \
|
||||||
|
"cd '${NAS_PATH}' && ls -t | grep '^incr-' | tail -n +$((RETENTION_COUNT + 1)) | xargs -r rm -rf" \
|
||||||
|
>> "$LOG_FILE" 2>&1 || true
|
||||||
|
|
||||||
|
else
|
||||||
|
error "Backup failed! Check $LOG_FILE for details"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
log "=========================================="
|
||||||
|
log "Backup completed at $(date)"
|
||||||
|
log "=========================================="
|
||||||
36
scripts/backup-setup/backup-monitor
Normal file
36
scripts/backup-setup/backup-monitor
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
#!/sbin/openrc-run
|
||||||
|
# OpenRC service for backup network trigger
|
||||||
|
# Monitors NAS availability and triggers backups when detected
|
||||||
|
|
||||||
|
name="backup-monitor"
|
||||||
|
description="Backup network trigger service"
|
||||||
|
|
||||||
|
command="/usr/local/bin/backup-trigger"
|
||||||
|
command_background="yes"
|
||||||
|
pidfile="/run/${RC_SVCNAME}.pid"
|
||||||
|
|
||||||
|
depend() {
|
||||||
|
need net
|
||||||
|
use NetworkManager
|
||||||
|
after NetworkManager
|
||||||
|
}
|
||||||
|
|
||||||
|
start_pre() {
|
||||||
|
# Ensure command exists
|
||||||
|
if [ ! -x "$command" ]; then
|
||||||
|
eerror "Backup trigger script not found: $command"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Check config exists
|
||||||
|
if [ ! -f /etc/backup.conf ]; then
|
||||||
|
eerror "Backup configuration not found: /etc/backup.conf"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
ebegin "Starting backup monitor"
|
||||||
|
}
|
||||||
|
|
||||||
|
stop_post() {
|
||||||
|
eend $? "Stopped backup monitor"
|
||||||
|
}
|
||||||
291
scripts/backup-setup/backup-setup
Normal file
291
scripts/backup-setup/backup-setup
Normal file
@@ -0,0 +1,291 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
# Interactive backup management script for Gentoo workstation
|
||||||
|
# Manages backups to NAS via rsync over SSH
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
# Colors for output
|
||||||
|
RED='\033[0;31m'
|
||||||
|
GREEN='\033[0;32m'
|
||||||
|
YELLOW='\033[1;33m'
|
||||||
|
BLUE='\033[0;34m'
|
||||||
|
MAGENTA='\033[0;35m'
|
||||||
|
CYAN='\033[0;36m'
|
||||||
|
NC='\033[0m' # No Color
|
||||||
|
|
||||||
|
# Config file
|
||||||
|
CONFIG_FILE="/etc/backup.conf"
|
||||||
|
|
||||||
|
# Helper functions
|
||||||
|
info() {
|
||||||
|
printf "${BLUE}ℹ${NC} %s\n" "$1"
|
||||||
|
}
|
||||||
|
|
||||||
|
success() {
|
||||||
|
printf "${GREEN}✓${NC} %s\n" "$1"
|
||||||
|
}
|
||||||
|
|
||||||
|
warning() {
|
||||||
|
printf "${YELLOW}⚠${NC} %s\n" "$1"
|
||||||
|
}
|
||||||
|
|
||||||
|
error() {
|
||||||
|
printf "${RED}✖${NC} %s\n" "$1"
|
||||||
|
}
|
||||||
|
|
||||||
|
header() {
|
||||||
|
printf "\n${CYAN}========================================${NC}\n"
|
||||||
|
printf "${CYAN}%s${NC}\n" "$1"
|
||||||
|
printf "${CYAN}========================================${NC}\n\n"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Load configuration
|
||||||
|
load_config() {
|
||||||
|
if [ ! -f "$CONFIG_FILE" ]; then
|
||||||
|
error "Configuration file not found: $CONFIG_FILE"
|
||||||
|
info "Create one based on: /usr/local/share/backup-setup/backup.conf.example"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# shellcheck source=/dev/null
|
||||||
|
. "$CONFIG_FILE"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Check if NAS is reachable
|
||||||
|
check_nas() {
|
||||||
|
info "Checking NAS connectivity..."
|
||||||
|
|
||||||
|
# Check if host is reachable
|
||||||
|
if ! ping -c 1 -W 2 "$NAS_HOST" >/dev/null 2>&1; then
|
||||||
|
error "NAS host $NAS_HOST is not reachable"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Check SSH connectivity
|
||||||
|
if ! ssh -p "$NAS_PORT" -o ConnectTimeout=5 -o BatchMode=yes \
|
||||||
|
"${NAS_USER}@${NAS_HOST}" "echo test" >/dev/null 2>&1; then
|
||||||
|
error "SSH connection to NAS failed"
|
||||||
|
info "Make sure SSH key authentication is set up"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
success "NAS is reachable at ${NAS_USER}@${NAS_HOST}:${NAS_PORT}"
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
# Check available space on NAS
|
||||||
|
check_nas_space() {
|
||||||
|
info "Checking available space on NAS..."
|
||||||
|
|
||||||
|
SPACE=$(ssh -p "$NAS_PORT" "${NAS_USER}@${NAS_HOST}" \
|
||||||
|
"df -h '$NAS_PATH' 2>/dev/null | tail -1 | awk '{print \$4}'" 2>/dev/null || echo "unknown")
|
||||||
|
|
||||||
|
if [ "$SPACE" != "unknown" ]; then
|
||||||
|
success "Available space on NAS: $SPACE"
|
||||||
|
else
|
||||||
|
warning "Could not determine available space"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# Get last backup info
|
||||||
|
get_last_backup() {
|
||||||
|
LAST_BACKUP_FILE="${HOME}/.local/var/backup/last-backup"
|
||||||
|
|
||||||
|
if [ -f "$LAST_BACKUP_FILE" ]; then
|
||||||
|
LAST_TIMESTAMP=$(cat "$LAST_BACKUP_FILE")
|
||||||
|
LAST_DATE=$(date -d "@$LAST_TIMESTAMP" "+%Y-%m-%d %H:%M:%S" 2>/dev/null || echo "unknown")
|
||||||
|
HOURS_AGO=$(( ($(date +%s) - LAST_TIMESTAMP) / 3600 ))
|
||||||
|
|
||||||
|
printf "${GREEN}Last backup:${NC} $LAST_DATE (${HOURS_AGO}h ago)\n"
|
||||||
|
else
|
||||||
|
printf "${YELLOW}No previous backup found${NC}\n"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# Show status
|
||||||
|
show_status() {
|
||||||
|
header "Backup Status"
|
||||||
|
|
||||||
|
# Config
|
||||||
|
printf "${CYAN}Configuration:${NC}\n"
|
||||||
|
printf " NAS: ${NAS_USER}@${NAS_HOST}:${NAS_PORT}\n"
|
||||||
|
printf " Path: ${NAS_PATH}\n"
|
||||||
|
printf "\n"
|
||||||
|
|
||||||
|
# Last backup
|
||||||
|
get_last_backup
|
||||||
|
printf "\n"
|
||||||
|
|
||||||
|
# NAS connectivity
|
||||||
|
if check_nas; then
|
||||||
|
check_nas_space
|
||||||
|
fi
|
||||||
|
|
||||||
|
printf "\n"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Trigger backup
|
||||||
|
trigger_backup() {
|
||||||
|
BACKUP_TYPE="${1:-full}"
|
||||||
|
|
||||||
|
case "$BACKUP_TYPE" in
|
||||||
|
full)
|
||||||
|
SCRIPT="/usr/local/bin/backup-full"
|
||||||
|
;;
|
||||||
|
home)
|
||||||
|
SCRIPT="/usr/local/bin/backup-home"
|
||||||
|
;;
|
||||||
|
incremental)
|
||||||
|
SCRIPT="/usr/local/bin/backup-incremental"
|
||||||
|
;;
|
||||||
|
configs)
|
||||||
|
SCRIPT="/usr/local/bin/backup-configs"
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
error "Unknown backup type: $BACKUP_TYPE"
|
||||||
|
echo "Valid types: full, home, incremental, configs"
|
||||||
|
exit 1
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
if [ ! -f "$SCRIPT" ]; then
|
||||||
|
error "Backup script not found: $SCRIPT"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
info "Starting $BACKUP_TYPE backup..."
|
||||||
|
"$SCRIPT"
|
||||||
|
}
|
||||||
|
|
||||||
|
# List backups on NAS
|
||||||
|
list_backups() {
|
||||||
|
header "Available Backups on NAS"
|
||||||
|
|
||||||
|
if ! check_nas; then
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
info "Listing backups from ${NAS_PATH}..."
|
||||||
|
|
||||||
|
ssh -p "$NAS_PORT" "${NAS_USER}@${NAS_HOST}" \
|
||||||
|
"ls -lh '$NAS_PATH' 2>/dev/null || echo 'No backups found'" || \
|
||||||
|
error "Failed to list backups"
|
||||||
|
}
|
||||||
|
|
||||||
|
# View logs
|
||||||
|
view_logs() {
|
||||||
|
LOG_FILE="${HOME}/.local/var/log/backup.log"
|
||||||
|
|
||||||
|
if [ ! -f "$LOG_FILE" ]; then
|
||||||
|
warning "No log file found at $LOG_FILE"
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
header "Recent Backup Log"
|
||||||
|
tail -50 "$LOG_FILE"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Test connection
|
||||||
|
test_connection() {
|
||||||
|
header "Testing NAS Connection"
|
||||||
|
|
||||||
|
load_config
|
||||||
|
|
||||||
|
info "Testing network connectivity..."
|
||||||
|
if ping -c 3 "$NAS_HOST"; then
|
||||||
|
success "Network connectivity OK"
|
||||||
|
else
|
||||||
|
error "Network connectivity FAILED"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
info "Testing SSH connection..."
|
||||||
|
if ssh -p "$NAS_PORT" -o ConnectTimeout=10 \
|
||||||
|
"${NAS_USER}@${NAS_HOST}" "hostname"; then
|
||||||
|
success "SSH connection OK"
|
||||||
|
else
|
||||||
|
error "SSH connection FAILED"
|
||||||
|
info "Make sure SSH keys are set up:"
|
||||||
|
echo " ssh-copy-id -p $NAS_PORT ${NAS_USER}@${NAS_HOST}"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
info "Testing backup directory..."
|
||||||
|
if ssh -p "$NAS_PORT" "${NAS_USER}@${NAS_HOST}" \
|
||||||
|
"test -d '$NAS_PATH' && echo 'OK' || mkdir -p '$NAS_PATH'"; then
|
||||||
|
success "Backup directory OK"
|
||||||
|
else
|
||||||
|
error "Backup directory test FAILED"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
success "All connection tests passed!"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Show help
|
||||||
|
show_help() {
|
||||||
|
cat <<EOF
|
||||||
|
Usage: backup-setup [COMMAND]
|
||||||
|
|
||||||
|
Interactive backup management for Gentoo workstation
|
||||||
|
|
||||||
|
Commands:
|
||||||
|
status Show backup status (default)
|
||||||
|
backup [TYPE] Trigger backup (full, home, incremental, configs)
|
||||||
|
list List available backups on NAS
|
||||||
|
logs View recent backup logs
|
||||||
|
test Test NAS connection
|
||||||
|
help Show this help message
|
||||||
|
|
||||||
|
Examples:
|
||||||
|
backup-setup # Show status
|
||||||
|
backup-setup backup full # Run full system backup
|
||||||
|
backup-setup backup home # Backup home directory only
|
||||||
|
backup-setup list # List backups on NAS
|
||||||
|
backup-setup test # Test NAS connection
|
||||||
|
|
||||||
|
Configuration:
|
||||||
|
Edit /etc/backup.conf to customize settings
|
||||||
|
|
||||||
|
EOF
|
||||||
|
}
|
||||||
|
|
||||||
|
# Main
|
||||||
|
main() {
|
||||||
|
COMMAND="${1:-status}"
|
||||||
|
|
||||||
|
case "$COMMAND" in
|
||||||
|
status)
|
||||||
|
load_config
|
||||||
|
show_status
|
||||||
|
;;
|
||||||
|
backup)
|
||||||
|
load_config
|
||||||
|
trigger_backup "$2"
|
||||||
|
;;
|
||||||
|
list)
|
||||||
|
load_config
|
||||||
|
list_backups
|
||||||
|
;;
|
||||||
|
logs)
|
||||||
|
view_logs
|
||||||
|
;;
|
||||||
|
test)
|
||||||
|
test_connection
|
||||||
|
;;
|
||||||
|
help|--help|-h)
|
||||||
|
show_help
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
error "Unknown command: $COMMAND"
|
||||||
|
echo ""
|
||||||
|
show_help
|
||||||
|
exit 1
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
}
|
||||||
|
|
||||||
|
main "$@"
|
||||||
182
scripts/backup-setup/backup-trigger
Normal file
182
scripts/backup-setup/backup-trigger
Normal file
@@ -0,0 +1,182 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
# Network-triggered backup daemon
|
||||||
|
# Monitors for NAS availability and triggers backups with safeguards
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
# Config
|
||||||
|
CONFIG_FILE="/etc/backup.conf"
|
||||||
|
LOG_DIR="${HOME}/.local/var/log"
|
||||||
|
LOG_FILE="${LOG_DIR}/backup-monitor.log"
|
||||||
|
STATE_DIR="${HOME}/.local/var/backup"
|
||||||
|
LAST_BACKUP_FILE="${STATE_DIR}/last-backup"
|
||||||
|
LAST_CHECK_FILE="${STATE_DIR}/last-check"
|
||||||
|
BACKUP_IN_PROGRESS_FILE="${STATE_DIR}/backup-in-progress"
|
||||||
|
|
||||||
|
# Ensure directories exist
|
||||||
|
mkdir -p "$LOG_DIR" "$STATE_DIR"
|
||||||
|
|
||||||
|
# Logging
|
||||||
|
log() {
|
||||||
|
echo "[$(date '+%Y-%m-%d %H:%M:%S')] $*" >> "$LOG_FILE"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Load config
|
||||||
|
if [ ! -f "$CONFIG_FILE" ]; then
|
||||||
|
log "ERROR: Configuration file not found: $CONFIG_FILE"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# shellcheck source=/dev/null
|
||||||
|
. "$CONFIG_FILE"
|
||||||
|
|
||||||
|
# Check if backup is already running
|
||||||
|
is_backup_running() {
|
||||||
|
# Check if any backup lock files exist
|
||||||
|
if ls /tmp/backup-*.lock >/dev/null 2>&1; then
|
||||||
|
return 0 # Backup is running
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Check our own in-progress marker
|
||||||
|
if [ -f "$BACKUP_IN_PROGRESS_FILE" ]; then
|
||||||
|
# Check if marker is stale (older than 6 hours)
|
||||||
|
if [ -n "$(find "$BACKUP_IN_PROGRESS_FILE" -mmin +360 2>/dev/null)" ]; then
|
||||||
|
log "WARNING: Stale backup-in-progress marker found, removing"
|
||||||
|
rm -f "$BACKUP_IN_PROGRESS_FILE"
|
||||||
|
return 1 # Not running
|
||||||
|
fi
|
||||||
|
return 0 # Backup is running
|
||||||
|
fi
|
||||||
|
|
||||||
|
return 1 # Not running
|
||||||
|
}
|
||||||
|
|
||||||
|
# Check if cooldown period has passed
|
||||||
|
check_cooldown() {
|
||||||
|
if [ ! -f "$LAST_BACKUP_FILE" ]; then
|
||||||
|
return 0 # No previous backup, proceed
|
||||||
|
fi
|
||||||
|
|
||||||
|
LAST_BACKUP=$(cat "$LAST_BACKUP_FILE")
|
||||||
|
NOW=$(date +%s)
|
||||||
|
ELAPSED=$((NOW - LAST_BACKUP))
|
||||||
|
|
||||||
|
if [ "$ELAPSED" -lt "$BACKUP_COOLDOWN" ]; then
|
||||||
|
REMAINING=$((BACKUP_COOLDOWN - ELAPSED))
|
||||||
|
log "Cooldown active: ${REMAINING}s remaining until next backup allowed"
|
||||||
|
return 1 # Still in cooldown
|
||||||
|
fi
|
||||||
|
|
||||||
|
return 0 # Cooldown passed
|
||||||
|
}
|
||||||
|
|
||||||
|
# Check if we recently checked (prevent spam checks)
|
||||||
|
check_rate_limit() {
|
||||||
|
CHECK_INTERVAL=300 # 5 minutes between checks
|
||||||
|
|
||||||
|
if [ ! -f "$LAST_CHECK_FILE" ]; then
|
||||||
|
date +%s > "$LAST_CHECK_FILE"
|
||||||
|
return 0 # First check, proceed
|
||||||
|
fi
|
||||||
|
|
||||||
|
LAST_CHECK=$(cat "$LAST_CHECK_FILE")
|
||||||
|
NOW=$(date +%s)
|
||||||
|
ELAPSED=$((NOW - LAST_CHECK))
|
||||||
|
|
||||||
|
if [ "$ELAPSED" -lt "$CHECK_INTERVAL" ]; then
|
||||||
|
return 1 # Too soon since last check
|
||||||
|
fi
|
||||||
|
|
||||||
|
date +%s > "$LAST_CHECK_FILE"
|
||||||
|
return 0 # Can check now
|
||||||
|
}
|
||||||
|
|
||||||
|
# Check if NAS is available
|
||||||
|
check_nas_available() {
|
||||||
|
# Quick ping check
|
||||||
|
if ! ping -c 1 -W 2 "$NAS_HOST" >/dev/null 2>&1; then
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# SSH check
|
||||||
|
if ! ssh -p "$NAS_PORT" -o ConnectTimeout=5 -o BatchMode=yes \
|
||||||
|
"${NAS_USER}@${NAS_HOST}" "echo test" >/dev/null 2>&1; then
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
# Trigger backup
|
||||||
|
trigger_backup() {
|
||||||
|
BACKUP_TYPE="${1:-incremental}"
|
||||||
|
|
||||||
|
log "NAS detected, triggering $BACKUP_TYPE backup..."
|
||||||
|
|
||||||
|
# Mark backup in progress
|
||||||
|
touch "$BACKUP_IN_PROGRESS_FILE"
|
||||||
|
|
||||||
|
# Run backup in background
|
||||||
|
(
|
||||||
|
if /usr/local/bin/backup-"$BACKUP_TYPE" >> "$LOG_FILE" 2>&1; then
|
||||||
|
log "Backup completed successfully"
|
||||||
|
else
|
||||||
|
log "ERROR: Backup failed"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Remove in-progress marker
|
||||||
|
rm -f "$BACKUP_IN_PROGRESS_FILE"
|
||||||
|
) &
|
||||||
|
|
||||||
|
# Don't wait for backup to complete
|
||||||
|
log "Backup started in background (PID: $!)"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Main monitoring loop
|
||||||
|
main() {
|
||||||
|
log "=========================================="
|
||||||
|
log "Backup monitor started"
|
||||||
|
log "Monitoring for NAS: ${NAS_HOST}"
|
||||||
|
log "Check interval: 5 minutes"
|
||||||
|
log "Backup cooldown: ${BACKUP_COOLDOWN}s ($(( BACKUP_COOLDOWN / 3600 ))h)"
|
||||||
|
log "=========================================="
|
||||||
|
|
||||||
|
while true; do
|
||||||
|
# Rate limit checks (every 5 minutes)
|
||||||
|
if ! check_rate_limit; then
|
||||||
|
sleep 60
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Skip if backup already running
|
||||||
|
if is_backup_running; then
|
||||||
|
log "Backup already in progress, skipping check"
|
||||||
|
sleep 300 # Sleep 5 minutes
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Check if NAS is available
|
||||||
|
if check_nas_available; then
|
||||||
|
log "NAS is available at ${NAS_HOST}"
|
||||||
|
|
||||||
|
# Check cooldown before triggering
|
||||||
|
if check_cooldown; then
|
||||||
|
log "Cooldown passed, backup allowed"
|
||||||
|
trigger_backup "incremental"
|
||||||
|
else
|
||||||
|
log "Cooldown active, skipping backup"
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
log "NAS not available (offline or not connected)"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Sleep before next check (5 minutes)
|
||||||
|
sleep 300
|
||||||
|
done
|
||||||
|
}
|
||||||
|
|
||||||
|
# Handle signals
|
||||||
|
trap 'log "Received shutdown signal, exiting..."; exit 0' TERM INT
|
||||||
|
|
||||||
|
# Start monitoring
|
||||||
|
main
|
||||||
43
scripts/backup-setup/backup.conf.example
Normal file
43
scripts/backup-setup/backup.conf.example
Normal file
@@ -0,0 +1,43 @@
|
|||||||
|
# Backup Configuration
|
||||||
|
# Copy this to /etc/backup.conf and customize
|
||||||
|
|
||||||
|
# NAS Connection Settings
|
||||||
|
NAS_HOST="nas.example.com"
|
||||||
|
NAS_PORT="22"
|
||||||
|
NAS_USER="backup"
|
||||||
|
NAS_PATH="/volume1/backups/gentoo-workstation"
|
||||||
|
|
||||||
|
# Backup Settings
|
||||||
|
BACKUP_ROOT="/mnt/backup"
|
||||||
|
RETENTION_DAYS="30"
|
||||||
|
RETENTION_COUNT="10"
|
||||||
|
|
||||||
|
# Exclude patterns (one per line, relative to /)
|
||||||
|
EXCLUDE_PATTERNS=(
|
||||||
|
"/dev/*"
|
||||||
|
"/proc/*"
|
||||||
|
"/sys/*"
|
||||||
|
"/tmp/*"
|
||||||
|
"/run/*"
|
||||||
|
"/mnt/*"
|
||||||
|
"/media/*"
|
||||||
|
"/lost+found"
|
||||||
|
"/var/tmp/portage/*"
|
||||||
|
"/var/cache/*"
|
||||||
|
"/.cache/*"
|
||||||
|
"/home/*/.cache/*"
|
||||||
|
"/home/*/Downloads/*.iso"
|
||||||
|
"/home/*/Downloads/*.mp4"
|
||||||
|
"/home/*/Downloads/*.mkv"
|
||||||
|
)
|
||||||
|
|
||||||
|
# Notification Settings
|
||||||
|
NOTIFY_ON_SUCCESS="false"
|
||||||
|
NOTIFY_ON_FAILURE="true"
|
||||||
|
NOTIFY_EMAIL=""
|
||||||
|
|
||||||
|
# Cooldown period (seconds) - prevents backup spam
|
||||||
|
BACKUP_COOLDOWN="3600" # 1 hour
|
||||||
|
|
||||||
|
# Last backup timestamp file (auto-set by scripts)
|
||||||
|
# LAST_BACKUP_FILE="${HOME}/.local/var/backup/last-backup"
|
||||||
163
scripts/security-setup/INSTALL.sh
Executable file
163
scripts/security-setup/INSTALL.sh
Executable file
@@ -0,0 +1,163 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
# Installation script for security hardening components
|
||||||
|
# Run with: sudo ./INSTALL.sh
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
# Colors
|
||||||
|
RED='\033[0;31m'
|
||||||
|
GREEN='\033[0;32m'
|
||||||
|
YELLOW='\033[1;33m'
|
||||||
|
BLUE='\033[0;34m'
|
||||||
|
NC='\033[0m'
|
||||||
|
|
||||||
|
info() {
|
||||||
|
printf "${BLUE}ℹ${NC} %s\n" "$1"
|
||||||
|
}
|
||||||
|
|
||||||
|
success() {
|
||||||
|
printf "${GREEN}✓${NC} %s\n" "$1"
|
||||||
|
}
|
||||||
|
|
||||||
|
warning() {
|
||||||
|
printf "${YELLOW}⚠${NC} %s\n" "$1"
|
||||||
|
}
|
||||||
|
|
||||||
|
error() {
|
||||||
|
printf "${RED}✖${NC} %s\n" "$1"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Check if running as root
|
||||||
|
if [ "$(id -u)" -ne 0 ]; then
|
||||||
|
error "This script must be run as root (use sudo)"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
info "Installing security hardening components..."
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# 1. nftables firewall
|
||||||
|
info "Installing nftables configuration..."
|
||||||
|
if [ ! -f /etc/nftables.conf ]; then
|
||||||
|
warning "No existing /etc/nftables.conf found"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Backup existing config
|
||||||
|
if [ -f /etc/nftables.conf ]; then
|
||||||
|
info "Backing up existing nftables.conf..."
|
||||||
|
cp /etc/nftables.conf "/etc/nftables.conf.backup.$(date +%Y%m%d-%H%M%S)"
|
||||||
|
success "Backup created"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Copy new config
|
||||||
|
cp nftables.conf /etc/nftables.conf
|
||||||
|
chmod 644 /etc/nftables.conf
|
||||||
|
success "nftables configuration installed"
|
||||||
|
|
||||||
|
# Enable nftables service
|
||||||
|
info "Enabling nftables service..."
|
||||||
|
if command -v rc-update >/dev/null 2>&1; then
|
||||||
|
rc-update add nftables default
|
||||||
|
success "nftables service enabled"
|
||||||
|
else
|
||||||
|
warning "OpenRC not found - please enable nftables manually"
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# 2. fail2ban
|
||||||
|
info "Installing fail2ban configuration..."
|
||||||
|
|
||||||
|
# Check if fail2ban is installed
|
||||||
|
if ! command -v fail2ban-server >/dev/null 2>&1; then
|
||||||
|
warning "fail2ban is not installed"
|
||||||
|
info "Install with: emerge -av net-analyzer/fail2ban"
|
||||||
|
info "jail.local will be copied but not activated"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Create fail2ban directory if needed
|
||||||
|
mkdir -p /etc/fail2ban
|
||||||
|
|
||||||
|
# Backup existing jail.local
|
||||||
|
if [ -f /etc/fail2ban/jail.local ]; then
|
||||||
|
info "Backing up existing jail.local..."
|
||||||
|
cp /etc/fail2ban/jail.local \
|
||||||
|
"/etc/fail2ban/jail.local.backup.$(date +%Y%m%d-%H%M%S)"
|
||||||
|
success "Backup created"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Copy new config
|
||||||
|
cp jail.local /etc/fail2ban/jail.local
|
||||||
|
chmod 644 /etc/fail2ban/jail.local
|
||||||
|
success "fail2ban configuration installed"
|
||||||
|
|
||||||
|
# Enable fail2ban service (if installed)
|
||||||
|
if command -v fail2ban-server >/dev/null 2>&1; then
|
||||||
|
info "Enabling fail2ban service..."
|
||||||
|
if command -v rc-update >/dev/null 2>&1; then
|
||||||
|
rc-update add fail2ban default
|
||||||
|
success "fail2ban service enabled"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# 3. SSH hardening
|
||||||
|
info "Installing SSH hardening configuration..."
|
||||||
|
|
||||||
|
# Check if SSH is installed
|
||||||
|
if [ ! -d /etc/ssh ]; then
|
||||||
|
warning "SSH directory not found - skipping SSH hardening"
|
||||||
|
else
|
||||||
|
# Create sshd_config.d directory (modern SSH)
|
||||||
|
mkdir -p /etc/ssh/sshd_config.d
|
||||||
|
|
||||||
|
# Backup existing config
|
||||||
|
if [ -f /etc/ssh/sshd_config ]; then
|
||||||
|
info "Backing up existing sshd_config..."
|
||||||
|
cp /etc/ssh/sshd_config \
|
||||||
|
"/etc/ssh/sshd_config.backup.$(date +%Y%m%d-%H%M%S)"
|
||||||
|
success "Backup created"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Copy hardened config
|
||||||
|
cp sshd_config.hardened /etc/ssh/sshd_config.d/hardening.conf
|
||||||
|
chmod 644 /etc/ssh/sshd_config.d/hardening.conf
|
||||||
|
success "SSH hardening configuration installed"
|
||||||
|
|
||||||
|
warning "SSH config updated - TEST BEFORE CLOSING THIS SESSION!"
|
||||||
|
info "Test with: sshd -t"
|
||||||
|
info "Apply with: rc-service sshd restart"
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# Summary
|
||||||
|
info "Installation complete!"
|
||||||
|
echo ""
|
||||||
|
warning "IMPORTANT NEXT STEPS:"
|
||||||
|
echo ""
|
||||||
|
echo "1. Review nftables configuration:"
|
||||||
|
echo " cat /etc/nftables.conf"
|
||||||
|
echo ""
|
||||||
|
echo "2. Test nftables rules (DRY RUN):"
|
||||||
|
echo " nft -f /etc/nftables.conf"
|
||||||
|
echo ""
|
||||||
|
echo "3. Start nftables:"
|
||||||
|
echo " rc-service nftables start"
|
||||||
|
echo ""
|
||||||
|
echo "4. Verify firewall is working:"
|
||||||
|
echo " nft list ruleset"
|
||||||
|
echo ""
|
||||||
|
echo "5. Test SSH configuration:"
|
||||||
|
echo " sshd -t"
|
||||||
|
echo ""
|
||||||
|
echo "6. If SSH test passes, restart SSH:"
|
||||||
|
echo " rc-service sshd restart"
|
||||||
|
echo ""
|
||||||
|
echo "7. If fail2ban is installed and SSH server is running, start it:"
|
||||||
|
echo " rc-service fail2ban start"
|
||||||
|
echo ""
|
||||||
|
warning "NOTE: SSH hardening only applies if you're running SSH server"
|
||||||
|
warning "For a workstation, SSH server is typically not needed"
|
||||||
|
echo ""
|
||||||
36
scripts/security-setup/jail.local
Normal file
36
scripts/security-setup/jail.local
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
# fail2ban jail configuration for Gentoo workstation
|
||||||
|
# Place in /etc/fail2ban/jail.local
|
||||||
|
|
||||||
|
[DEFAULT]
|
||||||
|
# Ban settings
|
||||||
|
bantime = 1h
|
||||||
|
findtime = 10m
|
||||||
|
maxretry = 3
|
||||||
|
|
||||||
|
# Use nftables for banning
|
||||||
|
banaction = nftables-multiport
|
||||||
|
banaction_allports = nftables-allports
|
||||||
|
|
||||||
|
# Email notifications (configure if needed)
|
||||||
|
destemail = root@localhost
|
||||||
|
sendername = Fail2Ban
|
||||||
|
action = %(action_)s
|
||||||
|
|
||||||
|
[sshd]
|
||||||
|
enabled = true
|
||||||
|
port = ssh
|
||||||
|
logpath = /var/log/auth.log
|
||||||
|
backend = systemd
|
||||||
|
maxretry = 3
|
||||||
|
bantime = 1h
|
||||||
|
findtime = 10m
|
||||||
|
|
||||||
|
# Additional SSH protection for multiple failed attempts
|
||||||
|
[sshd-aggressive]
|
||||||
|
enabled = false
|
||||||
|
port = ssh
|
||||||
|
logpath = /var/log/auth.log
|
||||||
|
backend = systemd
|
||||||
|
maxretry = 5
|
||||||
|
bantime = 24h
|
||||||
|
findtime = 1h
|
||||||
112
scripts/security-setup/nftables.conf
Normal file
112
scripts/security-setup/nftables.conf
Normal file
@@ -0,0 +1,112 @@
|
|||||||
|
#!/usr/sbin/nft -f
|
||||||
|
# nftables configuration for Gentoo workstation
|
||||||
|
# Security-focused firewall with Docker support
|
||||||
|
|
||||||
|
# Flush existing ruleset
|
||||||
|
flush ruleset
|
||||||
|
|
||||||
|
# Define variables
|
||||||
|
define lan_interface = "wlp194s0"
|
||||||
|
define nas_ip = 192.168.2.171
|
||||||
|
define ssh_port = 22
|
||||||
|
|
||||||
|
table inet filter {
|
||||||
|
# Rate limiting for connection attempts
|
||||||
|
set ratelimit_ssh {
|
||||||
|
type ipv4_addr
|
||||||
|
flags timeout
|
||||||
|
timeout 5m
|
||||||
|
}
|
||||||
|
|
||||||
|
set blocklist {
|
||||||
|
type ipv4_addr
|
||||||
|
flags timeout
|
||||||
|
timeout 1h
|
||||||
|
}
|
||||||
|
|
||||||
|
chain input {
|
||||||
|
type filter hook input priority filter; policy drop;
|
||||||
|
|
||||||
|
# Allow established and related connections
|
||||||
|
ct state established,related accept
|
||||||
|
|
||||||
|
# Allow loopback
|
||||||
|
iif "lo" accept
|
||||||
|
|
||||||
|
# Drop invalid packets
|
||||||
|
ct state invalid drop
|
||||||
|
|
||||||
|
# Allow ICMP (ping) with rate limiting
|
||||||
|
ip protocol icmp icmp type {
|
||||||
|
echo-request,
|
||||||
|
destination-unreachable,
|
||||||
|
time-exceeded
|
||||||
|
} limit rate 5/second accept
|
||||||
|
|
||||||
|
# Allow ICMPv6 (if needed in future)
|
||||||
|
ip6 nexthdr icmpv6 icmpv6 type {
|
||||||
|
echo-request,
|
||||||
|
destination-unreachable,
|
||||||
|
packet-too-big,
|
||||||
|
time-exceeded,
|
||||||
|
parameter-problem,
|
||||||
|
nd-router-advert,
|
||||||
|
nd-neighbor-solicit,
|
||||||
|
nd-neighbor-advert
|
||||||
|
} limit rate 5/second accept
|
||||||
|
|
||||||
|
# Allow SSH from LAN only with rate limiting
|
||||||
|
ip saddr @blocklist drop
|
||||||
|
tcp dport $ssh_port ip saddr @ratelimit_ssh drop
|
||||||
|
tcp dport $ssh_port ct state new \
|
||||||
|
add @ratelimit_ssh { ip saddr limit rate 3/minute } accept
|
||||||
|
|
||||||
|
# Allow mDNS for local network discovery
|
||||||
|
udp dport 5353 ip daddr 224.0.0.251 accept
|
||||||
|
udp dport 5353 ip6 daddr ff02::fb accept
|
||||||
|
|
||||||
|
# Allow DHCPv6 client
|
||||||
|
udp sport 546 udp dport 547 accept
|
||||||
|
|
||||||
|
# Log dropped packets (optional - comment out if too noisy)
|
||||||
|
# limit rate 5/minute log prefix "nftables-drop: "
|
||||||
|
|
||||||
|
# Drop everything else
|
||||||
|
drop
|
||||||
|
}
|
||||||
|
|
||||||
|
chain forward {
|
||||||
|
type filter hook forward priority filter; policy drop;
|
||||||
|
|
||||||
|
# Allow established and related connections
|
||||||
|
ct state established,related accept
|
||||||
|
|
||||||
|
# Drop invalid packets
|
||||||
|
ct state invalid drop
|
||||||
|
|
||||||
|
# Docker containers (if needed)
|
||||||
|
# Uncomment if using Docker bridge networking
|
||||||
|
# iifname "docker0" accept
|
||||||
|
# oifname "docker0" accept
|
||||||
|
|
||||||
|
# Drop everything else
|
||||||
|
drop
|
||||||
|
}
|
||||||
|
|
||||||
|
chain output {
|
||||||
|
type filter hook output priority filter; policy accept;
|
||||||
|
|
||||||
|
# Allow all outgoing by default (workstation)
|
||||||
|
accept
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
# Separate table for NAT (if needed for Docker)
|
||||||
|
table ip nat {
|
||||||
|
chain postrouting {
|
||||||
|
type nat hook postrouting priority srcnat; policy accept;
|
||||||
|
|
||||||
|
# Docker NAT (uncomment if using Docker)
|
||||||
|
# oifname $lan_interface masquerade
|
||||||
|
}
|
||||||
|
}
|
||||||
72
scripts/security-setup/sshd_config.hardened
Normal file
72
scripts/security-setup/sshd_config.hardened
Normal file
@@ -0,0 +1,72 @@
|
|||||||
|
# Hardened SSH configuration for Gentoo workstation
|
||||||
|
# Place in /etc/ssh/sshd_config.d/hardening.conf (or merge into main config)
|
||||||
|
|
||||||
|
# Network
|
||||||
|
Port 22
|
||||||
|
AddressFamily any
|
||||||
|
ListenAddress 0.0.0.0
|
||||||
|
ListenAddress ::
|
||||||
|
|
||||||
|
# Protocol
|
||||||
|
Protocol 2
|
||||||
|
|
||||||
|
# Host keys (prefer modern algorithms)
|
||||||
|
HostKey /etc/ssh/ssh_host_ed25519_key
|
||||||
|
HostKey /etc/ssh/ssh_host_rsa_key
|
||||||
|
|
||||||
|
# Ciphers and keying
|
||||||
|
KexAlgorithms curve25519-sha256,curve25519-sha256@libssh.org,diffie-hellman-group-exchange-sha256
|
||||||
|
Ciphers chacha20-poly1305@openssh.com,aes256-gcm@openssh.com,aes128-gcm@openssh.com,aes256-ctr,aes192-ctr,aes128-ctr
|
||||||
|
MACs hmac-sha2-512-etm@openssh.com,hmac-sha2-256-etm@openssh.com,hmac-sha2-512,hmac-sha2-256
|
||||||
|
|
||||||
|
# Logging
|
||||||
|
SyslogFacility AUTH
|
||||||
|
LogLevel VERBOSE
|
||||||
|
|
||||||
|
# Authentication
|
||||||
|
LoginGraceTime 30
|
||||||
|
PermitRootLogin no
|
||||||
|
StrictModes yes
|
||||||
|
MaxAuthTries 3
|
||||||
|
MaxSessions 5
|
||||||
|
|
||||||
|
# Public key authentication
|
||||||
|
PubkeyAuthentication yes
|
||||||
|
AuthorizedKeysFile .ssh/authorized_keys
|
||||||
|
|
||||||
|
# Password authentication (disable for key-only)
|
||||||
|
PasswordAuthentication no
|
||||||
|
PermitEmptyPasswords no
|
||||||
|
|
||||||
|
# Challenge-response authentication
|
||||||
|
KbdInteractiveAuthentication no
|
||||||
|
ChallengeResponseAuthentication no
|
||||||
|
|
||||||
|
# PAM
|
||||||
|
UsePAM yes
|
||||||
|
|
||||||
|
# Disable insecure features
|
||||||
|
PermitUserEnvironment no
|
||||||
|
HostbasedAuthentication no
|
||||||
|
IgnoreRhosts yes
|
||||||
|
X11Forwarding no
|
||||||
|
PrintMotd no
|
||||||
|
PrintLastLog yes
|
||||||
|
TCPKeepAlive yes
|
||||||
|
Compression no
|
||||||
|
|
||||||
|
# Allow client to pass locale environment variables
|
||||||
|
AcceptEnv LANG LC_*
|
||||||
|
|
||||||
|
# Subsystems
|
||||||
|
Subsystem sftp /usr/lib64/misc/sftp-server
|
||||||
|
|
||||||
|
# Connection settings
|
||||||
|
ClientAliveInterval 300
|
||||||
|
ClientAliveCountMax 2
|
||||||
|
|
||||||
|
# Allow only specific users (uncomment and customize)
|
||||||
|
# AllowUsers alexander
|
||||||
|
|
||||||
|
# Deny specific users
|
||||||
|
# DenyUsers root nobody
|
||||||
Reference in New Issue
Block a user