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:
95
CLAUDE.md
Normal file
95
CLAUDE.md
Normal 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
|
||||||
44
README.md
44
README.md
@@ -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] Linux installation (Arch Linux on ThinkPad)
|
||||||
- [x] SSH remote access (hostname: homelab)
|
- [x] SSH remote access (hostname: homelab)
|
||||||
- [x] Dotfiles and development environment setup
|
- [x] Dotfiles and development environment setup
|
||||||
- [ ] Network domain setup
|
- [x] Network domain setup
|
||||||
- [ ] Self-hosted cloud storage (ownCloud/Nextcloud)
|
- [ ] 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
|
- [ ] Gradual migration from commercial cloud services
|
||||||
|
|
||||||
## Hardware
|
## 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`)
|
- ✅ SSH access configured (accessible as `homelab`)
|
||||||
- ✅ Dotfiles management with yadm configured and merged
|
- ✅ Dotfiles management with yadm configured and merged
|
||||||
- ✅ Development environment setup completed
|
- ✅ 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
|
## Documentation Structure
|
||||||
|
|
||||||
### Quick Start Guide
|
### Quick Start Guide
|
||||||
1. **System Setup**: Follow [system-setup.md](system-setup.md) for Arch installation and configuration
|
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 [network-security.md](network-security.md)
|
2. **Network Security**: Configure SSH, DNS, and VPN using [docs/network-security.md](docs/network-security.md)
|
||||||
3. **Services**: Plan and deploy applications from [services.md](services.md)
|
3. **Services**: Plan and deploy applications from [docs/services.md](docs/services.md)
|
||||||
4. **Tasks**: Track progress in [TODO.md](TODO.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
|
### Documentation Files
|
||||||
- **[system-setup.md](system-setup.md)** - Complete Arch Linux installation, TTY config, desktop setup
|
- **[docs/system-setup.md](docs/system-setup.md)** - Complete Arch Linux installation, TTY config, desktop setup
|
||||||
- **[network-security.md](network-security.md)** - SSH hardening, DuckDNS, WireGuard VPN, firewall setup
|
- **[docs/network-security.md](docs/network-security.md)** - SSH hardening, DuckDNS, WireGuard VPN, firewall setup
|
||||||
- **[services.md](services.md)** - Self-hosted services: Git hosting, cloud storage, media server
|
- **[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
|
- **[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
|
### Current Configuration
|
||||||
- **System**: Arch Linux with XFCE desktop, ter-124b TTY font, Colemak layout
|
- **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
|
- **Development**: yadm dotfiles, tmux with temperature monitoring, zsh with proper history
|
||||||
|
|||||||
26
config/docker/gitea/docker-compose.yml
Normal file
26
config/docker/gitea/docker-compose.yml
Normal 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"
|
||||||
40
config/docker/gitea/setup.sh
Normal file
40
config/docker/gitea/setup.sh
Normal 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
55
config/nginx/homelab.conf
Normal 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
60
config/nginx/setup.sh
Normal 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
488
docs/network-security.md
Normal 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
440
docs/services.md
Normal 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
158
docs/system-setup.md
Normal 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
312
docs/troubleshooting.md
Normal 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?
|
||||||
Reference in New Issue
Block a user