Reorganize repository structure and add configuration management

- Create organized directory structure:
  - docs/ for all documentation files
  - config/ for deployment configurations and scripts
- Add CLAUDE.md with project architecture and development workflow
- Update README.md with new structure and current status
- Move all documentation to docs/ directory
- Organize Docker and Nginx configurations under config/

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
2025-08-06 17:24:11 +02:00
parent 7ef8c62324
commit f7b5d26eab
10 changed files with 1706 additions and 12 deletions

95
CLAUDE.md Normal file
View File

@@ -0,0 +1,95 @@
# CLAUDE.md
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
## Project Overview
This is a personal homelab setup repository documenting the migration from cloud services to self-hosted solutions on a ThinkPad running Arch Linux. The project uses Docker for containerized services behind an Nginx reverse proxy.
## Architecture
### Network Infrastructure
- **Domain**: ak-homelab.duckdns.org (DuckDNS dynamic DNS)
- **Static IP**: 192.168.0.100 (dual interface: ethernet enp4s0, WiFi wlp1s0)
- **SSH**: Custom port 2222 for system access
- **Reverse Proxy**: Nginx for path-based routing to services
### Service Architecture
```
Internet → Router → Nginx (80/443) → Services
→ SSH (2222) → System
→ Gitea SSH (2223) → Git operations
```
**Current Services:**
- Gitea Git server: Docker container on port 3000, accessible via `/gitea/` path
- Nginx: Reverse proxy routing to `ak-homelab.duckdns.org/servicename/`
### Configuration Management
All configurations are version controlled in the `config/` directory:
- `config/docker/gitea/`: Gitea container setup and deployment scripts
- `config/nginx/`: Reverse proxy configurations
- `config/scripts/`: Utility scripts for system maintenance
Configuration files include deployment instructions in comments showing target locations (e.g., `/opt/docker/gitea/`, `/etc/nginx/sites-available/`).
## Key Commands
### Docker Service Management
```bash
# Gitea operations (from /opt/docker/gitea/)
docker-compose logs gitea # View logs
docker-compose down # Stop
docker-compose up -d # Start
docker-compose pull && docker-compose up -d # Update
# Deploy from repo
sudo cp config/docker/gitea/docker-compose.yml /opt/docker/gitea/
```
### Nginx Operations
```bash
# Deploy configuration
sudo cp config/nginx/homelab.conf /etc/nginx/sites-available/homelab
sudo ln -s /etc/nginx/sites-available/homelab /etc/nginx/sites-enabled/homelab
# Management
sudo nginx -t # Test config
sudo systemctl reload nginx # Reload
sudo systemctl status nginx # Status
```
### SSL Certificate Management
```bash
sudo certbot --nginx -d ak-homelab.duckdns.org
sudo systemctl enable certbot.timer # Auto-renewal
```
## Development Workflow
### Task Tracking
Use `TODO.md` for centralized task management organized by category (Network & Security, Git & Development, System Configuration, etc.). Mark completed items and update status in documentation.
### Configuration Changes
1. Edit files in `config/` directory
2. Test locally when possible
3. Deploy to target locations with sudo commands included in file headers
4. Update documentation status in `docs/services.md`
5. Commit changes with logical separation
### Documentation Structure
- `docs/`: Technical documentation for setup procedures
- `README.md`: Overview and current status
- `TODO.md`: Active task tracking
- Configuration files self-document deployment locations in headers
### Network Configuration Notes
- System uses dual ethernet ports (enp3s0f0, enp4s0) - stick to enp4s0 consistently
- Port conflicts: SSH (2222), Gitea SSH (2223), Gitea Web (3000)
- Router forwarding: HTTP (80), HTTPS (443), SSH (2222), Git SSH (2223)
### Service URLs
- **Local access**: http://192.168.0.100/servicename/
- **External access**: http://ak-homelab.duckdns.org/servicename/
- **Gitea SSH**: ssh://git@ak-homelab.duckdns.org:2223

View File

@@ -7,9 +7,9 @@ Setting up a personal homelab using a ThinkPad laptop running Arch Linux to move
- [x] Linux installation (Arch Linux on ThinkPad)
- [x] SSH remote access (hostname: homelab)
- [x] Dotfiles and development environment setup
- [ ] Network domain setup
- [x] Network domain setup
- [ ] Self-hosted cloud storage (ownCloud/Nextcloud)
- [ ] Self-hosted git repository (Gitea/Forgejo/GitLab)
- [x] Self-hosted git repository (Gitea/Forgejo/GitLab)
- [ ] Gradual migration from commercial cloud services
## Hardware
@@ -27,25 +27,45 @@ Setting up a personal homelab using a ThinkPad laptop running Arch Linux to move
- ✅ SSH access configured (accessible as `homelab`)
- ✅ Dotfiles management with yadm configured and merged
- ✅ Development environment setup completed
- Next: Network domain setup and self-hosted services
- Network domain setup (DuckDNS + Nginx reverse proxy)
- ✅ Gitea Git server running (Docker container)
- Next: SSL certificates, additional self-hosted services
## Documentation Structure
### Quick Start Guide
1. **System Setup**: Follow [system-setup.md](system-setup.md) for Arch installation and configuration
2. **Network Security**: Configure SSH, DNS, and VPN using [network-security.md](network-security.md)
3. **Services**: Plan and deploy applications from [services.md](services.md)
1. **System Setup**: Follow [docs/system-setup.md](docs/system-setup.md) for Arch installation and configuration
2. **Network Security**: Configure SSH, DNS, and VPN using [docs/network-security.md](docs/network-security.md)
3. **Services**: Plan and deploy applications from [docs/services.md](docs/services.md)
4. **Tasks**: Track progress in [TODO.md](TODO.md)
5. **Issues**: Find solutions in [troubleshooting.md](troubleshooting.md)
5. **Issues**: Find solutions in [docs/troubleshooting.md](docs/troubleshooting.md)
### Repository Structure
```
homelab/
├── README.md # This overview
├── TODO.md # Task tracking
├── docs/ # Detailed documentation
│ ├── system-setup.md # Arch Linux installation & config
│ ├── network-security.md # SSH, DNS, VPN, firewall
│ ├── services.md # Self-hosted services
│ └── troubleshooting.md # Solutions & fixes
└── config/ # Configurations & scripts
├── docker/gitea/ # Gitea container setup
├── nginx/ # Reverse proxy configs
└── scripts/ # Utility scripts
```
### Documentation Files
- **[system-setup.md](system-setup.md)** - Complete Arch Linux installation, TTY config, desktop setup
- **[network-security.md](network-security.md)** - SSH hardening, DuckDNS, WireGuard VPN, firewall setup
- **[services.md](services.md)** - Self-hosted services: Git hosting, cloud storage, media server
- **[docs/system-setup.md](docs/system-setup.md)** - Complete Arch Linux installation, TTY config, desktop setup
- **[docs/network-security.md](docs/network-security.md)** - SSH hardening, DuckDNS, WireGuard VPN, firewall setup
- **[docs/services.md](docs/services.md)** - Self-hosted services: Git hosting, cloud storage, media server
- **[TODO.md](TODO.md)** - Centralized task list with progress tracking by category
- **[troubleshooting.md](troubleshooting.md)** - Hardware issues, software problems, and solutions
- **[docs/troubleshooting.md](docs/troubleshooting.md)** - Hardware issues, software problems, and solutions
### Current Configuration
- **System**: Arch Linux with XFCE desktop, ter-124b TTY font, Colemak layout
- **Security**: SSH hardened, DuckDNS configured (ak-homelab.duckdns.org)
- **Network**: Static IP (192.168.0.100), SSH port 2222, DuckDNS (ak-homelab.duckdns.org)
- **Services**: Nginx reverse proxy, Gitea Git server (Docker)
- **Security**: SSH hardened, firewall planned, SSL certificates pending
- **Development**: yadm dotfiles, tmux with temperature monitoring, zsh with proper history

View File

@@ -0,0 +1,26 @@
# DEPLOYMENT LOCATION: /opt/docker/gitea/docker-compose.yml
# Move this file with: sudo cp gitea-docker-compose.yml /opt/docker/gitea/docker-compose.yml
# Create data directory: sudo mkdir -p /opt/docker/gitea/data
# Set permissions: sudo chown -R hoborg:hoborg /opt/docker/gitea
networks:
gitea:
external: false
services:
server:
image: gitea/gitea:latest
container_name: gitea
environment:
- USER_UID=1000
- USER_GID=1000
restart: always
networks:
- gitea
volumes:
- ./data:/data
- /etc/timezone:/etc/timezone:ro
- /etc/localtime:/etc/localtime:ro
ports:
- "3000:3000"
- "2223:22"

View File

@@ -0,0 +1,40 @@
#!/bin/bash
# Gitea Docker Setup Script
# Run with: sudo bash gitea-setup.sh
set -e
echo "Setting up Gitea Docker environment..."
# Create directory structure
echo "Creating /opt/docker/gitea directory..."
mkdir -p /opt/docker/gitea/data
# Copy docker-compose file
echo "Copying docker-compose.yml..."
cp gitea-docker-compose.yml /opt/docker/gitea/docker-compose.yml
# Set correct permissions
echo "Setting permissions..."
chown -R hoborg:hoborg /opt/docker/gitea
# Start Gitea
echo "Starting Gitea container..."
cd /opt/docker/gitea
docker-compose up -d
echo ""
echo "✅ Gitea setup complete!"
echo ""
echo "🌐 Web interface: http://192.168.0.100:3000"
echo "🌍 External access: http://ak-homelab.duckdns.org:3000 (after router port forwarding)"
echo ""
echo "📋 Next steps:"
echo "1. Configure router port forwarding: 3000 → 192.168.0.100:3000"
echo "2. Access web interface to complete initial setup"
echo "3. Configure admin user and repository settings"
echo ""
echo "🔧 Container management:"
echo " View logs: docker logs gitea"
echo " Stop: docker-compose down"
echo " Update: docker-compose pull && docker-compose up -d"

55
config/nginx/homelab.conf Normal file
View File

@@ -0,0 +1,55 @@
# DEPLOYMENT LOCATION: /etc/nginx/sites-available/homelab
# Deploy with: sudo cp nginx-homelab.conf /etc/nginx/sites-available/homelab
# Enable with: sudo ln -s /etc/nginx/sites-available/homelab /etc/nginx/sites-enabled/homelab
server {
listen 80;
server_name ak-homelab.duckdns.org;
# Security headers
add_header X-Frame-Options "SAMEORIGIN" always;
add_header X-Content-Type-Options "nosniff" always;
add_header X-XSS-Protection "1; mode=block" always;
# Main landing page
location / {
root /var/www/homelab;
index index.html index.htm;
try_files $uri $uri/ =404;
}
# Gitea reverse proxy
location /gitea/ {
proxy_pass http://127.0.0.1:3000/;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
# Handle websockets for live updates
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
# Increase timeout for large repos
proxy_connect_timeout 60s;
proxy_send_timeout 60s;
proxy_read_timeout 60s;
}
# Future services (commented out for now)
# location /cloud/ {
# proxy_pass http://127.0.0.1:8080/;
# proxy_set_header Host $host;
# proxy_set_header X-Real-IP $remote_addr;
# proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
# proxy_set_header X-Forwarded-Proto $scheme;
# }
# location /media/ {
# proxy_pass http://127.0.0.1:8096/;
# proxy_set_header Host $host;
# proxy_set_header X-Real-IP $remote_addr;
# proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
# proxy_set_header X-Forwarded-Proto $scheme;
# }
}

60
config/nginx/setup.sh Normal file
View File

@@ -0,0 +1,60 @@
#!/bin/bash
# Nginx Setup Script for Homelab
# Run with: sudo bash nginx-setup.sh
set -e
echo "Setting up Nginx reverse proxy..."
# Install nginx and SSL tools
echo "Installing nginx and certbot..."
pacman -S --noconfirm nginx certbot certbot-nginx
# Create sites directories (some distributions don't have these)
mkdir -p /etc/nginx/sites-available
mkdir -p /etc/nginx/sites-enabled
# Enable sites-enabled in main nginx.conf if not already
if ! grep -q "sites-enabled" /etc/nginx/nginx.conf; then
echo "Adding sites-enabled include to nginx.conf..."
sed -i '/http {/a \ \ \ \ include /etc/nginx/sites-enabled/*;' /etc/nginx/nginx.conf
fi
# Copy site configuration
echo "Copying site configuration..."
cp nginx-homelab.conf /etc/nginx/sites-available/homelab
# Enable the site
echo "Enabling homelab site..."
ln -sf /etc/nginx/sites-available/homelab /etc/nginx/sites-enabled/homelab
# Create web root directory
echo "Creating web root directory..."
mkdir -p /var/www/homelab
chown -R hoborg:hoborg /var/www/homelab
# Test nginx configuration
echo "Testing nginx configuration..."
nginx -t
# Enable and start nginx
echo "Starting nginx service..."
systemctl enable nginx
systemctl start nginx
echo ""
echo "✅ Nginx setup complete!"
echo ""
echo "📋 Next steps:"
echo "1. Create landing page: sudo nvim /var/www/homelab/index.html"
echo "2. Configure router port forwarding:"
echo " - Port 80 → 192.168.0.100:80"
echo " - Port 443 → 192.168.0.100:443"
echo " - Remove port 3000 forwarding"
echo "3. Test access: http://ak-homelab.duckdns.org/"
echo "4. Set up SSL: sudo certbot --nginx -d ak-homelab.duckdns.org"
echo ""
echo "🔧 Management commands:"
echo " Test config: sudo nginx -t"
echo " Reload: sudo systemctl reload nginx"
echo " Status: sudo systemctl status nginx"

488
docs/network-security.md Normal file
View File

@@ -0,0 +1,488 @@
# Network & Security Configuration
Complete guide for securing and networking your homelab.
## SSH Security Setup
### Initial Configuration
```bash
# Generate SSH key pair
ssh-keygen -t ed25519 -C "homelab-key" -f ~/.ssh/homelab_ed25519
# Copy public key to target
ssh-copy-id -i ~/.ssh/homelab_ed25519.pub user@target
```
### SSH Hardening
**Status:****Complete** - Port changed to 2222
Edit `/etc/ssh/sshd_config`:
```
# Disable root login
PermitRootLogin no
# Use key-based authentication only
PasswordAuthentication no
PubkeyAuthentication yes
# Change default port (CRITICAL - currently still on 22)
Port 2222
# Restrict users
AllowUsers hoborg
# Security settings
Protocol 2
X11Forwarding no
AllowTcpForwarding no
ClientAliveInterval 300
ClientAliveCountMax 2
MaxAuthTries 3
MaxStartups 2
```
**Completed:**
1. ✅ Changed SSH port from 22 to 2222
2. ✅ Updated router port forwarding rules
3. ✅ External access via ak-homelab.duckdns.org:2222 working
Restart SSH: `sudo systemctl restart sshd`
### Mosh Alternative (Investigation Needed)
**Issue:** SSH can be unreliable on WiFi connections with packet loss.
**Mosh Benefits:**
- Maintains connection during network switches (ethernet ↔ WiFi)
- Handles poor WiFi connections better
- Local echo for responsive typing
- Roaming support (IP changes don't break connection)
**Installation:**
```bash
# Server side
sudo pacman -S mosh
# Client side
mosh user@server
```
**Requirements:**
- UDP ports 60000-61000 open on router
- SSH still needed for initial authentication
**Status:****Local use working****External blocked by ISP**
**Key Findings:**
- **Local mosh**: Works perfectly (`mosh localhost`, `mosh 192.168.0.100`)
- **External mosh**: Blocked by ISP UDP port filtering on ports 60000-61000
- **SSH still needed**: Mosh uses SSH for initial authentication, then switches to UDP
**ISP UDP Blocking Issue:**
- Most ISPs block UDP ports 60000-61000 for "security"
- SSH works fine (TCP port 2222) but mosh fails (UDP 60000-61000)
- Router port forwarding is correct, but ISP drops UDP packets
**Current Recommendation:**
- Use mosh for local/internal network connections
- Stick with SSH for external connections until VPN is set up
- VPN tunnel can bypass ISP UDP blocking
### SSH Client Configuration
Create `~/.ssh/config`:
```
Host homelab
HostName ak-homelab.duckdns.org
User hoborg
Port 2222
IdentityFile ~/.ssh/homelab_ed25519
ServerAliveInterval 60
```
**Usage:**
```bash
# Connect via SSH
ssh homelab
# Connect via Mosh (uses SSH config automatically)
mosh homelab
```
## Dynamic DNS with DuckDNS
### Account Setup
1. Create account at duckdns.org
2. Create subdomain: `ak-homelab.duckdns.org`
3. Get token from dashboard
### Automatic IP Updates
Update script at `~/.local/scripts/duckdns.py` (Python implementation)
Cron job for automatic updates:
```bash
# Update every 5 minutes
*/5 * * * * /home/hoborg/.local/scripts/duckdns.py >/dev/null 2>&1
```
### Current Setup (Router-based)
**Status:****Migrated from script to router DynDNS**
**Changes made:**
- ✅ Disabled cron job script (`*/5 * * * *` entry removed)
- ✅ Enabled router Dynamic DNS for ak-homelab.duckdns.org
-**Testing pending** - Cannot force public IP change to verify
**Router DynDNS Benefits:**
- Immediate updates on IP change (vs 5-minute delay)
- Works when server is down
- Lower resource usage
**Limitations:**
- Likely IPv4-only (Sagemcom router limitation)
- Less control over update process
### Testing
```bash
# Check current IP
curl -s https://ipinfo.io/ip
# Verify DNS resolution
nslookup ak-homelab.duckdns.org
# Check IPv6 (likely not updated by router)
nslookup -type=AAAA ak-homelab.duckdns.org
```
**Testing will occur naturally when ISP changes public IP address.**
## VPN Setup with WireGuard
### What is WireGuard?
WireGuard is a modern, lightweight VPN protocol that creates secure tunnels between devices. It encrypts all network traffic and routes it through a VPN server, making your internet connection private and secure.
**Key benefits:**
- **Privacy**: Hides your IP address and encrypts traffic
- **Security**: Protects against man-in-the-middle attacks on public WiFi
- **Access**: Bypass geo-restrictions and enables remote homelab access
- **Performance**: Much faster than OpenVPN with lower battery drain
- **Simplicity**: Easy to configure compared to other VPN protocols
**When you need VPN:**
- Accessing homelab remotely over internet
- Working from public WiFi frequently
- Need to bypass ISP restrictions
- Running public-facing services
**Costs:** WireGuard itself is free. Self-hosted VPN costs $5-20/month for VPS hosting.
**Use cases:**
- Access homelab services remotely (SSH, web interfaces, file shares)
- Secure connection on public WiFi
- Bypass ISP restrictions or geo-blocks
**Performance:** Much faster and lighter than OpenVPN, better battery life on mobile devices.
### Server Configuration
Install WireGuard: `pacman -S wireguard-tools`
Generate keys:
```bash
wg genkey | tee server_private.key | wg pubkey > server_public.key
```
Server config `/etc/wireguard/wg0.conf`:
```ini
[Interface]
PrivateKey = <SERVER_PRIVATE_KEY>
Address = 10.0.0.1/24
ListenPort = 51820
PostUp = iptables -A FORWARD -i %i -j ACCEPT; iptables -A FORWARD -o %i -j ACCEPT; iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
PostDown = iptables -D FORWARD -i %i -j ACCEPT; iptables -D FORWARD -o %i -j ACCEPT; iptables -t nat -D POSTROUTING -o eth0 -j MASQUERADE
[Peer]
PublicKey = <CLIENT_PUBLIC_KEY>
AllowedIPs = 10.0.0.2/32
```
### Client Configuration
Generate client keys:
```bash
wg genkey | tee client_private.key | wg pubkey > client_public.key
```
Client config:
```ini
[Interface]
PrivateKey = <CLIENT_PRIVATE_KEY>
Address = 10.0.0.2/24
DNS = 1.1.1.1
[Peer]
PublicKey = <SERVER_PUBLIC_KEY>
Endpoint = ak-homelab.duckdns.org:51820
AllowedIPs = 0.0.0.0/0
PersistentKeepalive = 25
```
### Enable VPN
```bash
sudo systemctl enable wg-quick@wg0
sudo systemctl start wg-quick@wg0
```
## Firewall Configuration
### UFW (Uncomplicated Firewall)
**What it does:** Controls what network traffic is allowed in/out of your server.
**Key functions:**
- **Default deny**: Blocks all incoming connections by default
- **Port control**: Open only specific ports you need (SSH, HTTP, etc.)
- **Rate limiting**: Prevent brute force attacks
- **Application profiles**: Pre-configured rules for common services
**Why needed:** Without firewall, all services are exposed to network attacks.
### UFW Setup
```bash
# Install and enable UFW
pacman -S ufw
sudo ufw enable
# Default policies
sudo ufw default deny incoming
sudo ufw default allow outgoing
# SSH access
sudo ufw allow 2222/tcp
# WireGuard
sudo ufw allow 51820/udp
# HTTP/HTTPS for services
sudo ufw allow 80/tcp
sudo ufw allow 443/tcp
```
### Advanced Rules
```bash
# Rate limiting for SSH
sudo ufw limit 2222/tcp
# Allow from specific networks
sudo ufw allow from 192.168.1.0/24 to any port 22
# Log denied connections
sudo ufw logging on
```
## Network Security Best Practices
### Port Management
- **Change default ports**: SSH (2222), WireGuard (51820)
- **Close unused ports**: Regular port scans with nmap
- **Port forwarding**: Only forward necessary ports
### Access Control
- **VPN-first approach**: Access services through VPN tunnel
- **IP whitelisting**: Restrict access to known IPs when possible
- **Rate limiting**: Prevent brute force attacks
### Monitoring
- **Log analysis**: Monitor `/var/log/auth.log` for SSH attempts
- **Network monitoring**: Use netstat/ss to check listening ports
- **Intrusion detection**: Use fail2ban for automated blocking
## fail2ban - Intrusion Prevention
### What is fail2ban?
**What it does:** Automatically blocks IP addresses that show malicious behavior.
**Key functions:**
- **Log monitoring**: Watches system logs for suspicious activity
- **Pattern detection**: Identifies failed login attempts, scanning, etc.
- **Automatic blocking**: Temporarily bans offending IP addresses
- **Customizable rules**: Configure what triggers a ban and for how long
**Common protections:**
- SSH brute force attempts
- Web server attacks (404 scanning, etc.)
- Email server abuse
- Custom application attacks
**Example:** After 5 failed SSH login attempts in 10 minutes, ban IP for 1 hour.
**Why important:** Reduces server load and prevents automated attacks from succeeding through persistence.
### fail2ban Installation & Setup
```bash
# Install fail2ban
sudo pacman -S fail2ban
# Enable and start service
sudo systemctl enable fail2ban
sudo systemctl start fail2ban
# Create local configuration
sudo cp /etc/fail2ban/jail.conf /etc/fail2ban/jail.local
```
### Basic SSH Protection Configuration
Edit `/etc/fail2ban/jail.local`:
```ini
[sshd]
enabled = true
port = 2222
filter = sshd
logpath = /var/log/auth.log
maxretry = 5
bantime = 3600
findtime = 600
```
**Configuration explained:**
- `maxretry = 5`: Ban after 5 failed attempts
- `bantime = 3600`: Ban for 1 hour (3600 seconds)
- `findtime = 600`: 5 attempts within 10 minutes triggers ban
- `port = 2222`: Monitor custom SSH port
### Restart and Monitor
```bash
# Restart fail2ban to apply changes
sudo systemctl restart fail2ban
# Check status
sudo fail2ban-client status
sudo fail2ban-client status sshd
# View banned IPs
sudo fail2ban-client get sshd banned
```
## Router Configuration
### Port Forwarding
Forward these ports to your homelab server:
- SSH: External port → Internal 2222
- WireGuard: 51820 → 51820
- Web services: 80/443 → 80/443 (if needed)
### Security Settings
- **Disable WPS**: Turn off WiFi Protected Setup
- **Strong WiFi password**: WPA3 with complex passphrase
- **Guest network**: Separate network for guests
- **Firmware updates**: Keep router firmware current
## Network Planning
### Dual Network Interface Issue (Critical)
**Problem:** Server has both ethernet and WiFi interfaces. When switching between connections, IP address changes from ethernet (192.168.0.22) to different WiFi IP, breaking SSH connections and port forwards.
**Limitation:** Most routers don't allow DHCP reservation of same IP for multiple MAC addresses.
**Solutions:**
**Option 1: Static IP Configuration (Recommended)**
Configure both interfaces with same static IP:
```bash
# Check interface names
ip link show
# Configure ethernet interface
sudo systemctl edit --full systemd-networkd
# Create /etc/systemd/network/20-ethernet.network
[Match]
Name=enp*
[Network]
DHCP=no
Address=192.168.0.100/24
Gateway=192.168.0.1
DNS=192.168.0.1
# Create /etc/systemd/network/25-wifi.network
[Match]
Name=wlp*
[Network]
DHCP=no
Address=192.168.0.100/24
Gateway=192.168.0.1
DNS=192.168.0.1
```
**Option 2: Hostname-based Access**
Use local hostname resolution instead of IP:
```bash
# Access via hostname (works for both interfaces)
ssh hoborg@ak-homelab.local
# or configure local DNS/mDNS
```
**Option 3: Bridge Networking**
Create bridge combining both interfaces for automatic failover:
```bash
# Advanced: Bridge both interfaces
ip link add name br0 type bridge
ip link set enp3s0 master br0
ip link set wlp2s0 master br0
```
**Current Setup:**
- Router: 192.168.0.1
- Ethernet: 192.168.0.100 (static IP achieved)
- WiFi: Static IP needed (same .100)
- External: ak-homelab.duckdns.org ✅
- SSH: Port 2222 ✅
**Network Interface Identification:**
- **enp3s0f0**: First ethernet port (98:fa:9b:f1:06:d5)
- **enp4s0**: Second ethernet port (98:fa:9b:f1:06:d4) ← **Use this one**
- **wlp1s0**: WiFi interface (0c:dd:24:e6:0f:87)
**Issue Solved:** Dual ethernet ports caused MAC address confusion when cable was moved between ports. Stick to enp4s0 consistently.
### IP Address Scheme
- **Router**: 192.168.0.1
- **Homelab server**: 192.168.0.100 (target static IP)
- **Current ethernet**: 192.168.0.22 (can migrate to .100)
- **DHCP range**: 192.168.0.10-99 (excluding static IPs)
- **VPN subnet**: 10.0.0.0/24
### DNS Configuration
- **Primary DNS**: Router (192.168.1.1)
- **Secondary DNS**: 1.1.1.1, 8.8.8.8
- **Local domain**: homelab.local
- **Dynamic DNS**: ak-homelab.duckdns.org
### Service Architecture
```
Internet → Router → Homelab Server
┌─────────────────────────────┐
│ SSH (2222) │
│ WireGuard VPN (51820) │
│ Web Services (80/443) │
│ Monitoring & Logging │
└─────────────────────────────┘
```
## Backup and Recovery
### Configuration Backups
- **SSH keys**: Store securely, separate from server
- **WireGuard configs**: Document peer configurations
- **Firewall rules**: Export UFW rules with `ufw status numbered`
### Network Documentation
- **IP mappings**: Document static assignments
- **Port forwards**: List all forwarded ports and purposes
- **Access credentials**: Secure storage of passwords/keys

440
docs/services.md Normal file
View File

@@ -0,0 +1,440 @@
# Services & Applications
Planning and configuration for self-hosted services and applications.
## Git Repository Hosting
### Service Options
- **Gitea**: Lightweight, Go-based, minimal resource usage ✅ *Recommended*
- **Forgejo**: Gitea fork, community-driven development
- **GitLab CE**: Feature-rich but more resource intensive
- **Gogs**: Simple, lightweight alternative
### Gitea Installation (Docker - Recommended)
**Status:****Container Running** ⚠️ **Configuration Issues** - UI accessible, config needs debugging
**Prerequisites:**
```bash
# Install Docker and Docker Compose
sudo pacman -S docker docker-compose
sudo systemctl enable docker
sudo systemctl start docker
# Add user to docker group (logout/login required)
sudo usermod -aG docker hoborg
```
**Gitea Docker Setup:**
```bash
# Create directories for persistent data
mkdir -p ~/docker/gitea/{data,config}
# Run Gitea container
docker run -d \
--name gitea \
-p 3000:3000 \
-p 2222:22 \
-v ~/docker/gitea/data:/data \
-v ~/docker/gitea/config:/etc/gitea \
-e USER_UID=1000 \
-e USER_GID=1000 \
gitea/gitea:latest
# Alternative: Docker Compose (preferred)
# See docker-compose.yml below
```
**Docker Compose Configuration:**
Create `~/docker/gitea/docker-compose.yml`:
```yaml
version: "3"
networks:
gitea:
external: false
services:
server:
image: gitea/gitea:latest
container_name: gitea
environment:
- USER_UID=1000
- USER_GID=1000
restart: always
networks:
- gitea
volumes:
- ./data:/data
- /etc/timezone:/etc/timezone:ro
- /etc/localtime:/etc/localtime:ro
ports:
- "3000:3000"
- "2223:22" # Gitea SSH (avoid conflict with system SSH on 2222)
```
**Start with Docker Compose:**
```bash
cd ~/docker/gitea
docker-compose up -d
```
### Current Configuration
**Container Status:** ✅ Running at /opt/docker/gitea
**Access URLs:**
- **Local Web**: http://192.168.0.100:3000
- **External Web**: http://ak-homelab.duckdns.org:3000 (requires port forwarding)
- **Git SSH**: ssh://git@ak-homelab.duckdns.org:2223 (requires port forwarding)
**Port Assignments:**
- **System SSH**: 2222 (for server administration)
- **Gitea SSH**: 2223 (for Git operations)
- **Gitea Web**: 3000 (web interface)
**Database**: SQLite (default, stored in container volume)
**Data Location**: /opt/docker/gitea/data (persistent volume)
**Router Port Forwarding Required:**
- 3000 → 192.168.0.100:3000 (web interface)
- 2223 → 192.168.0.100:2223 (Git SSH operations)
**Container Management:**
```bash
cd /opt/docker/gitea
docker-compose logs gitea # View logs
docker-compose down # Stop container
docker-compose up -d # Start container
docker-compose pull && docker-compose up -d # Update
```
### Gitea Configuration Recommendations
**Database Selection:**
-**SQLite** (Recommended for homelab)
- Zero configuration, single file
- Perfect for personal/small team use
- Easy backups and migration
- **PostgreSQL** (Production alternative)
- Better performance for heavy usage
- Requires additional container setup
**Domain & URL Configuration:**
- **Server Domain**: `ak-homelab.duckdns.org`
- **Gitea Base URL**: `http://ak-homelab.duckdns.org/gitea/`
- **SSH Domain**: `ak-homelab.duckdns.org`
- **SSH Port**: `2223`
**Password Hash Algorithm:**
-**Argon2** (Recommended)
- Most secure modern algorithm
- Resistant to GPU/ASIC attacks
- Higher CPU usage but excellent security
- **bcrypt** (Alternative)
- Well-tested, lower resource usage
- Good balance of security and performance
**Setup Progress:**
1. ✅ Gitea container running
2. ✅ Nginx reverse proxy setup complete
3. 📋 Router port forwarding (80, 443) - **Next**
4. ⚠️ Gitea web configuration - **Partially complete, needs debugging**
- Initial setup wizard completed
- Base URL configuration issue (extra space in config)
- UI accessible but routing may be broken
5. 📋 SSL certificate setup - **After router config**
**Current Access:**
- ✅ Local UI working: http://192.168.0.100/gitea/
- ❓ External access: Pending router port forwarding
- ⚠️ Configuration debugging needed
**Debug Tasks:**
- Fix base URL in `/opt/docker/gitea/data/gitea/conf/app.ini`
- Check ROOT_URL setting for extra spaces
- Verify redirect behavior after fix
## Cloud Storage Solutions
### Service Options
- **Copyparty**: Quite new self-hosted file storage solution, must investigate!
- **Nextcloud**: Full-featured, extensive app ecosystem ✅ *Recommended*
- **ownCloud**: Original project, stable and mature
- **Seafile**: Performance-focused file sync
- **Syncthing**: Decentralized sync (no server needed)
### Nextcloud Installation
```bash
# Via snap (recommended)
sudo snap install nextcloud
# Or via Docker
docker run -d \
--name nextcloud \
-p 8080:80 \
-v nextcloud_data:/var/www/html \
nextcloud
```
Personal notes: Not a fan of snap, isn't there an AUR package?
Go with docker otherwise
### Features
- File synchronization across devices
- Video files, game installers -> high prio
- Self-hosted git mirrors of favorite FOSS projects -> medium prio
- Calendar and contacts (CalDAV/CardDAV) -> low prio
- Document editing (OnlyOffice/Collabora) -> low prio
- Photo management and sharing -> low prio
- Mobile apps available?
## Media Management
### Jellyfin Media Server
```bash
# Install via AUR
yay -S jellyfin-server jellyfin-web
# Enable service
sudo systemctl enable jellyfin
sudo systemctl start jellyfin
```
Configuration:
- **Port**: 8096 (web interface)
- **Media paths**: `/data/movies`, `/data/tv`, `/data/music`
- **Transcoding**: Hardware acceleration if available
### Photo Management
- **PhotoPrism**: AI-powered photo management
- **Immich**: Modern photo backup solution
- **LibrePhotos**: Privacy-focused alternative
## Monitoring & Logging
### System Monitoring
```bash
# Prometheus + Grafana stack
docker-compose up -d prometheus grafana node-exporter
```
### Log Management
- **Centralized logging**: rsyslog or journald
- **Log rotation**: logrotate configuration
- **Analysis**: grep, awk, or ELK stack for advanced needs
### Health Checks
- **Uptime monitoring**: Simple HTTP checks
- **Service status**: systemd service monitoring
- **Disk space**: Automated alerts for low space
## Containerization Strategy
### Docker Setup
```bash
# Install Docker
pacman -S docker docker-compose
sudo systemctl enable docker
# Add user to docker group
sudo usermod -aG docker hoborg
```
### Container Management
- **Orchestration**: Docker Compose for multi-service apps
- **Storage**: Named volumes for persistent data
- **Networking**: Custom networks for service isolation
- **Updates**: Watchtower for automated updates
## Reverse Proxy Configuration
### Decision Matrix: Nginx vs Traefik
**Problem:** Multiple services need to be accessible under single domain with path-based routing.
**Solution:** Reverse proxy to route requests based on URL paths.
#### Nginx
**Pros:**
- Mature & battle-tested (decades of production use)
- High performance for static files and caching
- Flexible configuration - handles any routing scenario
- Extensive ecosystem and documentation
- Can handle non-Docker services easily
**Cons:**
- Manual configuration required
- No auto-discovery of services
- Requires config reload for changes
#### Traefik
**Pros:**
- Docker-native auto-discovery via labels
- Automatic HTTPS with Let's Encrypt
- Dynamic configuration (no restarts)
- Modern design for containerized environments
**Cons:**
- Less mature, smaller ecosystem
- Docker-dependent (less flexible)
- Steeper learning curve for complex scenarios
**Decision:****Nginx** - Better for homelab due to reliability, documentation, and flexibility for mixed Docker/non-Docker services.
### URL Architecture Decision
**Options Considered:**
1. **Separate subdomains**: `gitea.ak-homelab.duckdns.org`*DuckDNS doesn't support nested subdomains*
2. **Multiple DuckDNS domains**: `ak-homelab-git.duckdns.org`*Management overhead*
3. **Path-based routing**: `ak-homelab.duckdns.org/gitea/`**Selected**
**Chosen Architecture:**
```
ak-homelab.duckdns.org/ → Landing page/dashboard
ak-homelab.duckdns.org/gitea/ → Gitea Git server
ak-homelab.duckdns.org/cloud/ → Nextcloud file sync
ak-homelab.duckdns.org/media/ → Jellyfin media server
ak-homelab.duckdns.org/monitor/ → System monitoring
```
### Advanced Nginx Options
**Nginx Plus (Commercial):** $2500+/year
- Advanced load balancing, health checks
- API management, JWT validation
- Real-time monitoring dashboard
- **Verdict:** Overkill for homelab
**Nginx + Lua (OpenResty):**
- Embed Lua scripts for dynamic processing
- Complex routing logic, authentication
- API gateway functionality
- **Verdict:** Powerful but complex, not needed initially
### Nginx Setup
**Status:****Complete** - Reverse proxy configured and running
```bash
# Install nginx and SSL tools
sudo pacman -S nginx certbot certbot-nginx
# Create configuration
sudo nano /etc/nginx/sites-available/homelab
# Enable site
sudo ln -s /etc/nginx/sites-available/homelab /etc/nginx/sites-enabled/
# Test and reload
sudo nginx -t
sudo systemctl reload nginx
```
**Configuration Template:**
```nginx
server {
listen 80;
server_name ak-homelab.duckdns.org;
# Main landing page
location / {
root /var/www/homelab;
index index.html;
}
# Gitea reverse proxy
location /gitea/ {
proxy_pass http://127.0.0.1:3000/;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
# Future services
# location /cloud/ {
# proxy_pass http://127.0.0.1:8080/;
# proxy_set_header Host $host;
# }
}
```
### Router Port Forwarding Requirements
- **HTTP**: Port 80 → 192.168.0.100:80
- **HTTPS**: Port 443 → 192.168.0.100:443
- **Remove**: Direct port 3000 forwarding (will go through nginx)
### SSL Certificates
```bash
# Let's Encrypt via certbot (after nginx setup)
sudo certbot --nginx -d ak-homelab.duckdns.org
# Auto-renewal
sudo systemctl enable certbot.timer
```
## Backup Strategy
### Configuration Backups
- **Service configs**: Docker volumes, /etc configs
- **Database dumps**: Regular automated backups
- **Storage**: External drive or cloud backup
### Automated Backups
```bash
#!/bin/bash
# backup-services.sh
DATE=$(date +%Y%m%d)
# Backup Gitea
tar -czf /backup/gitea-$DATE.tar.gz /var/lib/gitea/
# Backup Nextcloud data
rsync -av /var/snap/nextcloud/common/nextcloud/data/ /backup/nextcloud-$DATE/
# Database backup
sudo -u postgres pg_dump gitea > /backup/gitea-db-$DATE.sql
```
## Resource Planning
### Hardware Requirements
- **RAM**: 4GB minimum, 8GB recommended
- **Storage**:
- System: 50GB SSD
- Data: 1TB+ HDD for media/files
- **Network**: Gigabit Ethernet preferred
### Service Resource Usage
| Service | RAM | CPU | Storage | Port |
|---------|-----|-----|---------|------|
| Gitea | 200MB | Low | 5GB+ | 3000 |
| Nextcloud | 512MB | Medium | 10GB+ | 8080 |
| Jellyfin | 1GB | High* | Media | 8096 |
| Monitoring | 500MB | Low | 2GB | 3000/9090 |
*High during transcoding
## Security Considerations
### Service Hardening
- **Regular updates**: Automated security patches
- **Access control**: VPN-only access when possible
- **Authentication**: Strong passwords, 2FA where available
- **Network isolation**: Separate VLANs or containers
### Data Protection
- **Encryption**: Full disk encryption (LUKS)
- **Backups**: Encrypted offsite backups
- **Access logs**: Monitor service access patterns
- **Fail2ban**: Automatic IP blocking for repeated failures
## Future Expansion
### Additional Services to Consider
- **Home Assistant**: ABSOLUTELY NOT
- **Bitwarden/Vaultwarden**: Password management
- How is this better than keepassxc + filesync?
- **Pi-hole**: Network-wide ad blocking
- **Wireguard UI**: Web interface for VPN management
- **Bookstack**: Documentation wiki
- What is this for? How does it compare to Logseq?
- **FreshRSS**: RSS feed aggregator

158
docs/system-setup.md Normal file
View File

@@ -0,0 +1,158 @@
# System Setup Guide
Complete guide for Arch Linux installation and system configuration.
## Initial Installation
### Pre-installation
1. Boot from Arch ISO
2. Verify boot mode: `ls /sys/firmware/efi/efivars`
3. Connect to internet: `iwctl` for WiFi
4. Update system clock: `timedatectl set-ntp true`
### Disk Preparation
1. List disks: `fdisk -l`
2. Partition the disk: `cfdisk /dev/sdX`
- EFI partition: 512M, type EFI System
- Root partition: remaining space, type Linux filesystem
3. Format partitions:
```bash
mkfs.fat -F32 /dev/sdX1 # EFI
mkfs.ext4 /dev/sdX2 # Root
```
4. Mount filesystems:
```bash
mount /dev/sdX2 /mnt
mkdir /mnt/boot
mount /dev/sdX1 /mnt/boot
```
Current partition setup is a quite fragmented leftover from my dual-booting days. Later we should wipe the leftover
Windows drive for extra storage, but first we should confirm there's no essential files there
(unlikely since it wasn't booted for months, mostly using other windows PC)
### System Installation
1. Install base packages: `pacstrap /mnt base linux linux-firmware`
2. Generate fstab: `genfstab -U /mnt >> /mnt/etc/fstab`
3. Chroot: `arch-chroot /mnt`
4. Set timezone: `ln -sf /usr/share/zoneinfo/Europe/Budapest /etc/localtime`
5. Generate hardware clock: `hwclock --systohc`
6. Configure locale:
- Edit `/etc/locale.gen`, uncomment `en_US.UTF-8 UTF-8`
- Run: `locale-gen`
- Create `/etc/locale.conf`: `LANG=en_US.UTF-8`
7. Set hostname: `echo "homelab" > /etc/hostname`
8. Configure hosts file
9. Set root password: `passwd`
10. Install bootloader: `pacman -S grub efibootmgr`
11. Install GRUB: `grub-install --target=x86_64-efi --efi-directory=/boot --bootloader-id=GRUB`
12. Generate config: `grub-mkconfig -o /boot/grub/grub.cfg`
## Post-Installation Setup
### User Management
```bash
# Create user
useradd -m -G wheel -s /bin/bash hoborg
passwd hoborg
# Configure sudo
pacman -S sudo
visudo # Uncomment %wheel ALL=(ALL) ALL
```
### Essential Packages
```bash
pacman -S git base-devel openssh networkmanager
systemctl enable NetworkManager
systemctl enable sshd
```
### AUR Access
```bash
# Install yay AUR helper
git clone https://aur.archlinux.org/yay.git
cd yay
makepkg -si
```
## Desktop Environment
### XFCE Installation
```bash
pacman -S xfce4 xfce4-goodies lightdm lightdm-gtk-greeter
systemctl enable lightdm
```
### Themes and Appearance
- **Window Manager Theme**: Matcha-dark-aliz
- **Icons**: Papirus-Maia
- **Fonts**:
- System: Install Nerd Fonts (`ttf-iosevkaterm-nerd ttf-jetbrains-mono-nerd`)
- TTY: ter-124b (12x24 bold)
## Development Environment
### Dotfiles Management
```bash
# Install yadm
pacman -S yadm
# Clone dotfiles
yadm clone git@gitlab.com:akrejczinger/dotfiles.git
```
### Shell Configuration
- **Shell**: zsh with antidote plugin manager
- **Terminal**: wezterm with Catppuccin theme
- **Multiplexer**: tmux with catppuccin theme and temperature monitoring
- **Editor**: neovim with lazy.nvim plugin manager
### Key Configurations
- **Keyboard Layout**: Colemak (US variant in X11)
- **TTY Layout**: Colemak with caps lock → backspace via systemd service
- **Font Fallbacks**: Noto fonts for Unicode support
## TTY Configuration
### Font and Layout
```bash
# Configure /etc/vconsole.conf
KEYMAP=colemak
FONT=ter-124b
FONT_MAP=8859-1
```
### Caps Lock Fix
Caps lock mapped to backspace via systemd service:
```bash
# /etc/systemd/system/caps-backspace.service
sudo setkeycodes 3a 14 # Map caps scancode to backspace keycode
```
### Color Scheme
TTY colors configured in `.zshrc` for better readability.
## System Maintenance
### Package Management
- Regular updates: `yay -Syu`
- Orphaned packages: `yay -Yc`
- Cache cleanup: `yay -Sc`
### Backup Strategy
- Dotfiles: yadm + git repository
- System configs: Document in this guide
- User data: External backup solution
## Hardware-Specific Notes
### ThinkPad Optimizations
- **Temperature Monitoring**: Available via `sensors` command
- **Battery Management**: TLP for power optimization
- **Trackpad**: libinput with natural scrolling
- **Function Keys**: Media keys work out of box
### Network Configuration
- **WiFi**: NetworkManager with GUI applet
- **Ethernet**: Automatic DHCP
- **Bluetooth**: bluez with pulseaudio integration

312
docs/troubleshooting.md Normal file
View File

@@ -0,0 +1,312 @@
# Bluetooth keeps disconnecting - reconnecting
Solution: Change config in /etc/bluetooth/main.conf
`ControllerMode = bredr`
Then `sudo systemctl restart bluetooth`
UPDATE: It's still not fixed :(
Trying `yay -S pipewire wireplumber`
TODO test it again
# Touchpad scroll direction (libinput)
To change touchpad scroll direction on Arch Linux using libinput driver:
## Investigation steps:
1. Check which driver is used: `pacman -Q | grep -E "(synaptics|libinput)"`
2. Verify libinput config exists: `ls /usr/share/X11/xorg.conf.d/ | grep libinput`
## Solution for libinput:
Create `/etc/X11/xorg.conf.d/30-touchpad.conf`:
```
Section "InputClass"
Identifier "touchpad"
Driver "libinput"
MatchIsTouchpad "on"
Option "NaturalScrolling" "true"
Option "Tapping" "on"
Option "TappingDrag" "on"
Option "DisableWhileTyping" "on"
EndSection
```
Set `NaturalScrolling` to:
- `"true"` for macOS-style (natural) scrolling
- `"false"` for traditional scrolling
Restart X11 (log out/in) or reboot to apply changes.
## Alternative: Synaptics driver (legacy)
If using the older synaptics driver instead of libinput:
### Investigation steps:
1. Check for synaptics: `pacman -Q xf86-input-synaptics`
2. Look for config: `ls /usr/share/X11/xorg.conf.d/ | grep synaptics`
### Solution:
Create `/etc/X11/xorg.conf.d/70-synaptics.conf`:
```
Section "InputClass"
Identifier "touchpad"
Driver "synaptics"
MatchIsTouchpad "on"
MatchDevicePath "/dev/input/event*"
Option "VertScrollDelta" "-111"
Option "HorizScrollDelta" "-111"
Option "TapButton1" "1"
Option "TapButton2" "3"
Option "TapButton3" "2"
Option "PalmDetect" "1"
Option "SHMConfig" "on"
EndSection
```
Synaptics scroll direction options:
- `VertScrollDelta` and `HorizScrollDelta`:
- Positive values (e.g., `"111"`) for traditional scrolling
- Negative values (e.g., `"-111"`) for natural/reversed scrolling
**Note:** libinput is the modern standard. Consider switching from synaptics to libinput for better support and features.
# Theme switching issues
## Cross-application theme synchronization
**Issue:** Need to synchronize theme (light/dark) across tmux, nvim, and other terminal applications.
**Solution:** File-based theme management system using `~/.vim_theme`:
### Setup:
1. **Create theme switcher script** (`~/.config/tmux/themeswitch.sh`):
```bash
#!/bin/bash
if [ -f ~/.vim_theme ] && [ "$(cat ~/.vim_theme)" = "light" ]; then
tmux set -g @catppuccin_flavor "latte"
else
tmux set -g @catppuccin_flavor "mocha"
fi
```
2. **Add to tmux config** (`~/.config/tmux/tmux.conf`):
```bash
# Dynamic theme switching based on ~/.vim_theme file
run 'bash ~/.config/tmux/themeswitch.sh'
```
3. **Add to shell config** (`~/.zshrc`):
```bash
# Export THEME environment variable for nvim and other apps
if [ -f ~/.vim_theme ]; then
export THEME=$(cat ~/.vim_theme)
else
export THEME="dark" # default
fi
```
### Usage:
```bash
# Switch to light theme
echo "light" > ~/.vim_theme
# Switch to dark theme
echo "dark" > ~/.vim_theme
```
### Benefits:
-**Single source of truth:** `~/.vim_theme` file controls all applications
-**Automatic propagation:** New terminals inherit theme via shell config
-**No environment variable issues:** File-based approach avoids tmux env var propagation problems
-**Cross-application support:** nvim reads `$THEME`, tmux uses catppuccin flavors
### Limitations:
- **Tmux live reload:** Changes require tmux config reload or session restart
- **Workaround:** Use tmux-resurrect to quickly restore sessions after restart
## Legacy: Tmux and terminal not updating after theme switch
**Issue:** After running the theme switcher script, tmux sessions and existing terminals don't reflect the new theme until restarted.
**Temporary workaround:**
- Restart tmux sessions: `tmux kill-server && tmux`
- Open new terminal windows
**Status:****Solved** - Use file-based theme management system above
## Tmux window names showing hostname instead of command
**Issue:** Tmux windows show "homelab" (hostname) for inactive tabs but correct command names for active tabs.
**Root cause:** Catppuccin tmux theme with `@catppuccin_window_tabs_enabled on` uses different text formatting for active vs inactive windows.
**Solution:** Disable catppuccin window tabs:
```
set -g @catppuccin_window_tabs_enabled off
```
**Alternative:** Configure explicit window text for both states:
```
set -g @catppuccin_window_default_text "#W"
set -g @catppuccin_window_current_text "#W"
```
Also ensure automatic renaming is enabled:
```
setw -g automatic-rename on
setw -g allow-rename on
```
# Font and Unicode Display Issues
## Missing emoji and unicode symbols
**Issue:** Emojis show as boxes or missing characters, unicode symbols don't display properly.
**Solution:** Install comprehensive unicode font packages:
```bash
sudo pacman -S noto-fonts-emoji noto-fonts-extra
fc-cache -f
```
## Nerd Font icons not displaying
**Issue:** Developer icons (programming languages, git symbols, file types) show as blank spaces or boxes.
**Root cause:** Terminal emulator not configured to use Nerd Font as primary font.
**Solution:**
1. Install Nerd Fonts:
```bash
sudo pacman -S ttf-iosevkaterm-nerd ttf-jetbrains-mono-nerd
fc-cache -f
```
2. Configure terminal to use Nerd Font as primary font
3. For wezterm, ensure config includes:
```lua
config.font = wezterm.font_with_fallback {
'IosevkaTerm Nerd Font',
'JetBrainsMono Nerd Font Mono',
'Noto Color Emoji'
}
```
**Testing:** Use printf with direct codepoints:
```bash
printf "Icons: \\ue702 \\uf121 \\uf015 \\uf07b\\n"
```
## Ancient/exotic script support
**Comprehensive coverage achieved with:**
- `noto-fonts` (base unicode)
- `noto-fonts-cjk` (Chinese/Japanese/Korean)
- `noto-fonts-emoji` (color emoji)
- `noto-fonts-extra` (additional scripts)
Successfully displays: Egyptian hieroglyphs, Cuneiform, Nordic runes, Hungarian rovás, Arabic, Chinese, Japanese, Korean, Thai, Hindi, Hebrew, Greek, Tamil.
# Cannot tile windows by drag and dropping
Keyboard workaround: Go to Settings > Window Manager > Keyboard, set up tiling shortcuts (set to Super+arrow keys)
# Additional Known Issues (TODO Items)
## Tmux battery indicator missing until config reload
**Issue:** Battery indicator doesn't appear in tmux status line immediately after starting tmux.
**Temporary workaround:** Reload tmux config with `Prefix + r` or restart tmux session.
**Status:** Investigation needed
## TTY fallbacks needed
**Issue:** When not in X11/graphical mode, nvim and tmux need proper fallback configurations.
**Status:** Completed
**Solutions implemented:**
-**nvim:** TTY detection and color scheme fallback configured
-**Font:** Selected ter-124b (12x24 bold) for good readability
-**Keyboard:** Colemak layout with caps lock remapped to backspace
-**Caps lock fix:** Uses systemd service with `setkeycodes 3a 14`
**Configuration files:**
- `/etc/systemd/system/caps-backspace.service` - Permanent caps lock remapping
- TTY font testing script: `~/.local/scripts/test-fonts.sh`
## TTY Caps Lock Not Working as Backspace
**Issue:** With colemak keymap loaded, caps lock acts like Control instead of backspace in TTY.
**Root cause:** Colemak keymap maps caps lock to Control, which conflicts with tmux navigation keys.
**Solution:** Use `setkeycodes` to remap at scancode level:
```bash
sudo setkeycodes 3a 14 # Map caps lock scancode to backspace keycode
```
**Permanent fix:** Systemd service created at `/etc/systemd/system/caps-backspace.service`
## Laptop sleeps when lid is closed
Solution:
sudo nvim /etc/systemd/logind.conf
Uncomment and change these lines:
```
HandleLidSwitch=ignore
HandleLidSwitchExternalPower=ignore
HandleLidSwitchDocked=ignore
```
Then restart service:
`sudo systemctl restart systemd-logind`
## IP addresses keep changing
Due to 3 interfaces:
* Wifi
* Ethernet left port (ThinkPad adapter) - Wired Connection 1
* Ethernet right port (regular ethernet cable) - Wired Connection 2
### Proposed solution
* Stick with wired2
● Configure static IP for "Wired connection 2" (enp4s0):
* Set static IP to 192.168.0.100
sudo nmcli connection modify "Wired connection 2" \
ipv4.method manual \
ipv4.addresses 192.168.0.100/24 \
ipv4.gateway 192.168.0.1 \
ipv4.dns 192.168.0.1
* Apply the changes
sudo nmcli connection up "Wired connection 2"
Then configure WiFi with the same static IP:
* First connect to your WiFi if not already
sudo nmcli connection up "Telekom-4b28df-2.4GHz"
* Set same static IP for WiFi
sudo nmcli connection modify "Telekom-4b28df-2.4GHz" \
ipv4.method manual \
ipv4.addresses 192.168.0.100/24 \
ipv4.gateway 192.168.0.1 \
ipv4.dns 192.168.0.1
Verify the configuration:
nmcli connection show "Wired connection 2" | grep ipv4
ip addr show enp4s0
This way both your ethernet (enp4s0) and WiFi will use 192.168.0.100, solving your dual interface IP issue.
Ready to run these commands?