Streamline AI docs, add skills, enforce symlink-everything policy
- Add .claude/skills/: homelab-context (auto-loads key facts each session), homelab-status (/homelab-status command), deploy-config (symlink setup guide) - Remove AGENTS.md and ai/sessions/: superseded by plan mode + skill system - Remove 4 obsolete session commands (session-start/list/switch, reload-instructions) - Rewrite CLAUDE.md: remove duplicate content, enforce symlink policy, clarify sudo pattern - Trim docs/services.md from 946 to ~230 lines: remove planning-era content, keep install steps and current status for migration reference - Strip stale "sudo cp" deploy header from ssh-honeypot.service (now symlinked to repo) - Update TODO.md: mark NAS migration and symlink tasks done, add jellyfin upgrade warning
This commit is contained in:
52
.claude/skills/deploy-config/SKILL.md
Normal file
52
.claude/skills/deploy-config/SKILL.md
Normal file
@@ -0,0 +1,52 @@
|
||||
---
|
||||
name: deploy-config
|
||||
description: Set up symlinks from system config locations to this repo. Use when setting up on a new machine, or when a config file is found to be a real file instead of a symlink (config drift). Not for routine config changes — just edit the repo file directly.
|
||||
disable-model-invocation: true
|
||||
allowed-tools: Write, Bash(chmod *), Bash(diff *), Bash(ls *)
|
||||
---
|
||||
|
||||
All system configs should be symlinked to this repo. Editing the repo file IS editing the live config.
|
||||
|
||||
## Symlink Map
|
||||
|
||||
| System location | Repo source |
|
||||
|---|---|
|
||||
| `/etc/nginx/sites-available/homelab` | `config/nginx/homelab.conf` |
|
||||
| `/var/www/homelab/index.html` | `config/www/index.html` |
|
||||
| `/etc/systemd/system/copyparty.service` | `config/systemd/copyparty.service` |
|
||||
| `/etc/systemd/system/glances-web.service` | `config/systemd/glances-web.service` |
|
||||
| `/etc/systemd/system/ssh-honeypot.service` | `config/systemd/ssh-honeypot.service` |
|
||||
| `/opt/docker/<service>/docker-compose.yml` | `config/docker/<service>/docker-compose.yml` |
|
||||
|
||||
## When to use this skill
|
||||
|
||||
- **New machine setup**: Create all symlinks from scratch
|
||||
- **Drift detected**: A system file is a real file instead of a symlink — replace it with a symlink
|
||||
- **New config added to repo**: Create the initial symlink for it
|
||||
|
||||
## How to create/fix a symlink
|
||||
|
||||
Generate a script in `scripts/tmp/symlink-<name>.sh`:
|
||||
|
||||
```bash
|
||||
#!/bin/bash
|
||||
set -e
|
||||
REPO="/home/hoborg/homelab/<repo-path>"
|
||||
SYSTEM="<system-path>"
|
||||
|
||||
# Back up if it's a real file (not already a symlink)
|
||||
[ ! -L "$SYSTEM" ] && cp "$SYSTEM" "${SYSTEM}.backup.$(date +%Y%m%d)" && echo "Backup created"
|
||||
|
||||
ln -sf "$REPO" "$SYSTEM" && echo "Symlink created"
|
||||
# Add post-link steps here (e.g. nginx -t && systemctl reload nginx, systemctl daemon-reload)
|
||||
```
|
||||
|
||||
Tell the user to run: `sudo bash ~/homelab/scripts/tmp/symlink-<name>.sh`
|
||||
|
||||
## Routine config changes
|
||||
|
||||
Just edit `config/<path>` in the repo. The symlink means it's already live. Then:
|
||||
- Nginx: `sudo nginx -t && sudo systemctl reload nginx`
|
||||
- Systemd unit: `sudo systemctl daemon-reload && sudo systemctl restart <service>`
|
||||
- Docker: `cd /opt/docker/<service> && docker compose restart`
|
||||
- www/index.html: no action needed (served directly)
|
||||
98
.claude/skills/homelab-context/SKILL.md
Normal file
98
.claude/skills/homelab-context/SKILL.md
Normal file
@@ -0,0 +1,98 @@
|
||||
---
|
||||
name: homelab-context
|
||||
description: Background reference for the homelab repo. Auto-loads key facts about services, ports, paths, and operational rules when working in this project.
|
||||
user-invocable: false
|
||||
---
|
||||
|
||||
## Architecture
|
||||
|
||||
- **Domain**: ak-homelab.duckdns.org (DuckDNS)
|
||||
- **Static IP**: 192.168.0.100 (interface: enp4s0)
|
||||
- **SSH**: port 2222 (system), port 2223 (Gitea git)
|
||||
- **NAS**: 192.168.0.101, mounted at `/mnt/nas/`
|
||||
|
||||
## Services & Ports
|
||||
|
||||
| Service | Port | Type | Path |
|
||||
|-------------|-------|----------|-----------------|
|
||||
| Nginx | 80/443| systemd | reverse proxy |
|
||||
| Gitea | 3000 | Docker | /gitea/ |
|
||||
| Jellyfin | 8096 | Docker | /media/ |
|
||||
| Copyparty | 8082 | systemd | /files/ |
|
||||
| Netdata | 19999 | Docker | /netdata/ |
|
||||
| Portainer | 9000 | Docker | /portainer/ |
|
||||
| qBittorrent | 8080 | Docker | /qbt/ |
|
||||
|
||||
## Key Paths
|
||||
|
||||
All configs are **symlinked** from system locations to this repo — editing the repo file is editing the live config:
|
||||
|
||||
| System location | Repo source |
|
||||
|---|---|
|
||||
| `/opt/docker/<service>/docker-compose.yml` | `config/docker/<service>/docker-compose.yml` |
|
||||
| `/etc/nginx/sites-available/homelab` | `config/nginx/homelab.conf` |
|
||||
| `/var/www/homelab/index.html` | `config/www/index.html` |
|
||||
| `/etc/systemd/system/copyparty.service` | `config/systemd/copyparty.service` |
|
||||
| `/etc/systemd/system/glances-web.service` | `config/systemd/glances-web.service` |
|
||||
| `/etc/systemd/system/ssh-honeypot.service` | `config/systemd/ssh-honeypot.service` |
|
||||
|
||||
- NAS docker data: `/mnt/nas/docker-data/<service>/`
|
||||
|
||||
## Critical Rules
|
||||
|
||||
### Docker UID for NAS-mounted volumes
|
||||
Services with data on NAS (`/mnt/nas/`) must use `USER_UID=1024 USER_GID=100` to match NAS file ownership. Services with local storage use `1000:1000`.
|
||||
|
||||
### Docker config changes
|
||||
Edit `config/docker/<service>/docker-compose.yml` in repo → restart container. No copy needed (symlinked).
|
||||
|
||||
### After editing a config in repo
|
||||
- **Docker**: `cd /opt/docker/<service> && docker compose restart`
|
||||
- **Nginx**: `sudo nginx -t && sudo systemctl reload nginx`
|
||||
- **Systemd unit**: `sudo systemctl daemon-reload && sudo systemctl restart <service>`
|
||||
- **www/index.html**: no action needed
|
||||
|
||||
### Sudo scripts
|
||||
Never run sudo directly. Generate a script in `scripts/tmp/` and run `sudo bash ~/homelab/scripts/tmp/<script>.sh`.
|
||||
The sudoers rule `/etc/sudoers.d/homelab-scripts` grants NOPASSWD for `scripts/tmp/*` — no password needed.
|
||||
|
||||
### s6-overlay containers (Gitea)
|
||||
Do NOT set `user:` directive in docker-compose. Use `USER_UID`/`USER_GID` env vars instead — s6-overlay needs root to start, then drops privileges.
|
||||
|
||||
### Never copy any config files
|
||||
All configs are symlinked. Copying a file breaks the link and causes drift from the repo.
|
||||
|
||||
## NAS Services Currently Using 1024:100
|
||||
- Gitea (`/mnt/nas/docker-data/gitea/data`)
|
||||
- Nextcloud app + db (`/mnt/nas/docker-data/nextcloud/`)
|
||||
|
||||
## Management Quick Reference
|
||||
|
||||
```bash
|
||||
# Docker service (from anywhere)
|
||||
cd /opt/docker/<service> && docker compose logs -f
|
||||
cd /opt/docker/<service> && docker compose restart
|
||||
cd /opt/docker/<service> && docker compose down && docker compose up -d
|
||||
|
||||
# Systemd services
|
||||
sudo systemctl status nginx copyparty netdata
|
||||
sudo systemctl restart nginx
|
||||
|
||||
# Nginx
|
||||
sudo nginx -t && sudo systemctl reload nginx
|
||||
|
||||
# NAS mount check
|
||||
mountpoint /mnt/nas && echo mounted
|
||||
```
|
||||
|
||||
## Keeping Skills Up To Date
|
||||
|
||||
After any change to service configuration, ports, paths, Docker UIDs, or operational rules:
|
||||
- Update this skill file (`homelab-context/SKILL.md`) to reflect the new state
|
||||
- Update `homelab-status/SKILL.md` if services are added or removed
|
||||
- This ensures future sessions always have accurate context without re-reading files
|
||||
|
||||
## Docs Reference
|
||||
- Full service install steps (for migration): `docs/services.md`
|
||||
- Network & security: `docs/network-security.md`
|
||||
- Troubleshooting: `docs/troubleshooting/`
|
||||
15
.claude/skills/homelab-status/SKILL.md
Normal file
15
.claude/skills/homelab-status/SKILL.md
Normal file
@@ -0,0 +1,15 @@
|
||||
---
|
||||
name: homelab-status
|
||||
description: Check status of all homelab services at once.
|
||||
disable-model-invocation: true
|
||||
allowed-tools: Bash(docker *), Bash(systemctl *), Bash(mountpoint *), Bash(nginx *)
|
||||
---
|
||||
|
||||
Check and report status of all homelab services:
|
||||
|
||||
1. Run `docker ps --format "table {{.Names}}\t{{.Status}}\t{{.Ports}}"` to show all containers
|
||||
2. Run `systemctl is-active nginx copyparty netdata` to show systemd service states
|
||||
3. Run `mountpoint /mnt/nas` to confirm NAS is mounted
|
||||
4. Run `sudo nginx -t` to verify nginx config is valid
|
||||
5. Report any services that are stopped, failed, or unhealthy
|
||||
6. Note any containers not running that should be (gitea, jellyfin, portainer, qbittorrent, nextcloud)
|
||||
76
AGENTS.md
76
AGENTS.md
@@ -1,76 +0,0 @@
|
||||
# AI Agent Instructions and Restrictions
|
||||
|
||||
## CRITICAL SECURITY RESTRICTIONS
|
||||
|
||||
### ❌ SUDO COMMAND PROHIBITION
|
||||
|
||||
**NEVER, UNDER ANY CIRCUMSTANCES, RUN SUDO COMMANDS**
|
||||
|
||||
The AI agent MUST NOT execute any commands that require elevated privileges:
|
||||
- ❌ `sudo` commands
|
||||
- ❌ `su` commands
|
||||
- ❌ Commands that modify system files directly
|
||||
- ❌ Commands that require root privileges
|
||||
|
||||
### ✅ APPROVED ALTERNATIVES
|
||||
|
||||
Instead of running sudo commands, the AI should:
|
||||
1. **Create scripts** that the user can run with `sudo -A`
|
||||
2. **Document commands** for the user to execute manually
|
||||
3. **Explain what needs to be done** and why
|
||||
4. **Provide step-by-step instructions** for the user
|
||||
|
||||
### EXAMPLES
|
||||
|
||||
**❌ WRONG:**
|
||||
```bash
|
||||
sudo systemctl restart nginx
|
||||
sudo chmod 755 /etc/nginx/conf.d/
|
||||
```
|
||||
|
||||
**✅ CORRECT:**
|
||||
```bash
|
||||
# Create a script for the user to run
|
||||
echo "systemctl restart nginx" > /tmp/restart-nginx.sh
|
||||
chmod +x /tmp/restart-nginx.sh
|
||||
|
||||
# Then tell the user:
|
||||
# "Run: sudo -A /tmp/restart-nginx.sh"
|
||||
```
|
||||
|
||||
### RATIONALE
|
||||
|
||||
- User explicitly denied AI access to sudo
|
||||
- Security best practice: AI should not have root privileges
|
||||
- User prefers manual control over system changes
|
||||
- Prevents accidental system modifications
|
||||
|
||||
### VERIFICATION
|
||||
|
||||
This restriction has been tested and verified:
|
||||
- ✅ AI cannot run sudo commands via bash tool
|
||||
- ✅ AI will create scripts instead
|
||||
- ✅ User maintains full control over privileged operations
|
||||
|
||||
## OTHER OPERATIONAL GUIDELINES
|
||||
|
||||
### File Operations
|
||||
- ✅ Read files in user directories
|
||||
- ✅ Write files in user directories
|
||||
- ✅ Create scripts in `/tmp` or user directories
|
||||
- ❌ Modify system configuration files directly
|
||||
|
||||
### Network Operations
|
||||
- ✅ Check network status with unprivileged commands
|
||||
- ✅ Test connectivity
|
||||
- ❌ Modify firewall rules directly
|
||||
- ❌ Bind to privileged ports (< 1024)
|
||||
|
||||
### Service Management
|
||||
- ❌ Start/stop/restart system services directly
|
||||
- ✅ Check service status with unprivileged commands
|
||||
- ✅ Create systemd service files for user to deploy
|
||||
|
||||
---
|
||||
|
||||
**REMEMBER: When in doubt, create a script and let the user run it with sudo.**
|
||||
250
CLAUDE.md
250
CLAUDE.md
@@ -4,236 +4,106 @@ This file provides guidance to Claude Code (claude.ai/code) when working with co
|
||||
|
||||
## 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.
|
||||
Personal homelab on a ThinkPad running Arch Linux. Docker services behind an Nginx reverse proxy. Full context is in `.claude/skills/homelab-context/SKILL.md`.
|
||||
|
||||
## 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
|
||||
- **Domain**: ak-homelab.duckdns.org (DuckDNS)
|
||||
- **Static IP**: 192.168.0.100 (interface: enp4s0)
|
||||
- **NAS**: 192.168.0.101, mounted at `/mnt/nas/`
|
||||
- **Reverse Proxy**: Nginx → path-based routing to services
|
||||
|
||||
## Configuration Management
|
||||
|
||||
All configs are version-controlled in `config/`. Docker compose files are **always symlinked** — never copied:
|
||||
|
||||
### Service Architecture
|
||||
```
|
||||
Internet → Router → Nginx (80/443) → Services
|
||||
→ SSH (2222) → System
|
||||
→ Gitea SSH (2223) → Git operations
|
||||
/opt/docker/<service>/docker-compose.yml → ~/homelab/config/docker/<service>/docker-compose.yml
|
||||
```
|
||||
|
||||
**Current Services:**
|
||||
- Gitea Git server: Docker container on port 3000, accessible via `/gitea/` path
|
||||
- Copyparty file server: Systemd service on port 8082, accessible via `/files/` path with WebDAV support
|
||||
- Jellyfin media server: Docker container on port 8096, accessible via `/media/` path
|
||||
- Nginx: Reverse proxy routing to `ak-homelab.duckdns.org/servicename/`
|
||||
Editing the repo file is editing the live config. Restart the container to apply changes.
|
||||
|
||||
### Configuration Management
|
||||
All configs — Docker, nginx, systemd units, www — are symlinked to this repo. Editing a file in `config/` is editing the live config. Use `/deploy-config` only on a new machine to create symlinks from scratch, or if drift is detected (a real file exists instead of a symlink).
|
||||
|
||||
All configurations are version controlled in the `config/` directory:
|
||||
- `config/docker/gitea/`: Gitea container setup and deployment scripts
|
||||
- `config/docker/jellyfin/`: Jellyfin media server configuration
|
||||
- `config/nginx/`: Reverse proxy configurations with SSL and WebDAV support
|
||||
- `config/scripts/`: Utility scripts for system maintenance
|
||||
- `~/.config/copyparty/`: Copyparty file server configuration
|
||||
## Sudo Access
|
||||
|
||||
Configuration files include deployment instructions in comments showing target locations (e.g., `/opt/docker/gitea/`, `/etc/nginx/sites-available/`).
|
||||
A sudoers rule at `/etc/sudoers.d/homelab-scripts` grants NOPASSWD for scripts in `scripts/tmp/`:
|
||||
```
|
||||
hoborg ALL=(ALL) NOPASSWD: /bin/bash /home/hoborg/homelab/scripts/tmp/*
|
||||
```
|
||||
Scripts generated there can be run with `sudo bash ~/homelab/scripts/tmp/<script>.sh` — no password needed.
|
||||
|
||||
Never run sudo commands directly. Always create a script in `scripts/tmp/`.
|
||||
|
||||
## Docker Guidelines
|
||||
|
||||
- **NAS-mounted volumes** (`/mnt/nas/`): use `USER_UID=1024 USER_GID=100` to match NAS file ownership
|
||||
- **Local volumes**: use `USER_UID=1000 USER_GID=1000`
|
||||
- **s6-overlay containers** (Gitea): do NOT set `user:` directive — use `USER_UID`/`USER_GID` env vars only
|
||||
- **Never copy docker-compose files** — they are symlinked; copying breaks the link and causes config drift
|
||||
|
||||
## Key Commands
|
||||
|
||||
### Docker Service Management
|
||||
### Docker
|
||||
```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
|
||||
|
||||
# Jellyfin operations (from /opt/docker/jellyfin/)
|
||||
docker-compose logs jellyfin # 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/
|
||||
sudo cp config/docker/jellyfin/docker-compose.yml /opt/docker/jellyfin/
|
||||
cd /opt/docker/<service>
|
||||
docker compose logs -f # View logs
|
||||
docker compose restart # Restart
|
||||
docker compose down && docker compose up -d # Full restart
|
||||
```
|
||||
|
||||
### Copyparty File Server Management
|
||||
### Nginx
|
||||
```bash
|
||||
# Service operations
|
||||
sudo systemctl status copyparty # Check status
|
||||
sudo systemctl start copyparty # Start service
|
||||
sudo systemctl stop copyparty # Stop service
|
||||
sudo systemctl restart copyparty # Restart (reload config)
|
||||
|
||||
# Configuration
|
||||
sudo cp ~/.config/copyparty/copyparty.conf ~/.config/copyparty/copyparty.conf.backup
|
||||
# Edit config and restart service to reload
|
||||
```
|
||||
|
||||
### 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
|
||||
sudo systemctl reload nginx # Reload (use restart for major changes)
|
||||
```
|
||||
|
||||
### SSL Certificate Management
|
||||
### Systemd Services
|
||||
```bash
|
||||
sudo certbot --nginx -d ak-homelab.duckdns.org
|
||||
sudo systemctl enable certbot.timer # Auto-renewal
|
||||
sudo systemctl status nginx copyparty
|
||||
sudo systemctl restart <service>
|
||||
```
|
||||
|
||||
## 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.
|
||||
1. Edit files in `config/` (these are the live configs for Docker via symlink)
|
||||
2. For non-Docker configs: use `/deploy-config` skill or write a `scripts/tmp/` script
|
||||
3. Update `docs/` if the change affects setup or architecture
|
||||
4. Update `.claude/skills/homelab-context/SKILL.md` if ports, paths, or rules changed
|
||||
5. Commit with a clear message
|
||||
|
||||
### 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
|
||||
|
||||
### 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
|
||||
- `docs/` — Human-readable reference. Keep for migration and troubleshooting.
|
||||
- `README.md` — Overview and current status
|
||||
- `TODO.md` — Active task tracking
|
||||
- `.claude/skills/homelab-context/SKILL.md` — AI-optimized operational facts (keep in sync with reality)
|
||||
|
||||
### 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**: https://ak-homelab.duckdns.org/servicename/
|
||||
- **Gitea SSH**: ssh://git@ak-homelab.duckdns.org:2223
|
||||
- **Voice Assistant**: http://127.0.0.1:8880 (local TTS server)
|
||||
- **Copyparty WebDAV**: https://ak-homelab.duckdns.org/files/ (for X-plore, rclone, etc.)
|
||||
|
||||
### Voice Assistant Commands
|
||||
```bash
|
||||
# Enable voice mode (starts server and configures voice-mode)
|
||||
./scripts/enable-voice.sh
|
||||
|
||||
# Disable voice mode (stops server)
|
||||
./scripts/disable-voice.sh
|
||||
|
||||
# Manual voice server management
|
||||
cd voice-server
|
||||
poetry run voice-server # Start server
|
||||
poetry install # Install dependencies
|
||||
poetry run pytest # Run tests
|
||||
|
||||
# Test TTS directly
|
||||
curl -X POST "http://127.0.0.1:8880/v1/audio/speech" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{"input": "Hello world!", "voice": "ryan"}' \
|
||||
--output test.wav
|
||||
```
|
||||
|
||||
### Disk Usage Analysis Tools
|
||||
```bash
|
||||
# System-level disk space overview (recommended for regular checks)
|
||||
duf # Modern df with colors and progress bars
|
||||
|
||||
# Directory size analysis
|
||||
dust /home/hoborg # Quick visual summary with tree view
|
||||
dust /home/hoborg --depth 3 # Limit depth for large directories
|
||||
|
||||
# Interactive cleanup and detailed analysis
|
||||
ncdu /home/hoborg # Navigate with arrow keys, delete with 'd'
|
||||
ncdu /opt/docker # Analyze Docker data usage
|
||||
ncdu ~ # Scan home directory for large files
|
||||
|
||||
# Usage patterns:
|
||||
# 1. duf - Quick system health check (like htop for disk space)
|
||||
# 2. dust - Fast overview of directory sizes (like tree with sizes)
|
||||
# 3. ncdu - Deep dive cleanup and file management (like htop for files)
|
||||
```
|
||||
|
||||
### WebDAV Client Setup
|
||||
```bash
|
||||
# X-plore File Manager (Android)
|
||||
# Server: ak-homelab.duckdns.org
|
||||
# Path: /files/
|
||||
# Port: 443 (HTTPS)
|
||||
# Username: hoborg
|
||||
# Password: AdminPass2024!
|
||||
|
||||
# rclone configuration
|
||||
rclone config create homelab-webdav webdav \
|
||||
url=https://ak-homelab.duckdns.org/files/ \
|
||||
vendor=other \
|
||||
user=hoborg \
|
||||
pass=$(rclone obscure "AdminPass2024!")
|
||||
|
||||
# Mount with rclone
|
||||
rclone mount homelab-webdav: ~/homelab-files --daemon
|
||||
|
||||
# Test WebDAV
|
||||
curl -X PROPFIND https://hoborg:AdminPass2024!@ak-homelab.duckdns.org/files/ \
|
||||
-H "Depth: 1" -H "Content-Type: text/xml"
|
||||
```
|
||||
- Always edit the local configs before when possible, and then copy them to the proper location. Instead of editing system files directly (and then losing the config and it won't be in this repo)
|
||||
- Never run sudo commands, instead create a script in scripts/tmp and ask the user to run it.
|
||||
For detailed install steps per service, see `docs/services.md`.
|
||||
|
||||
## Security Hardening Guidelines
|
||||
- When working on security hardening, make sure you **understand the service needs** first, to ensure the security doesn't interfre with normal operations (e.g. some services need read/write filesystem access, not just read)
|
||||
- Some containers (like Gitea with s6-overlay) need root start then privilege drop via USER_UID/USER_GID environment variables
|
||||
|
||||
- Understand service needs before applying restrictions (some need rw filesystem access)
|
||||
- Test each security change individually, not in batches
|
||||
- Network access patterns matter: SSH Git needs direct access, HTTP can be proxied through localhost
|
||||
- DO NOT set Docker user: directive for services using s6-overlay init systems (breaks initialization)
|
||||
- Network access patterns matter: SSH Git needs direct access, HTTP can go through localhost proxy
|
||||
|
||||
## Claude Development Guidelines
|
||||
|
||||
### CRITICAL: Anti-Pattern Reminders
|
||||
**BEFORE writing ANY script or solution, Claude MUST:**
|
||||
|
||||
1. **RESEARCH FIRST, CODE NEVER** - Always research existing solutions in this exact order:
|
||||
- **pacman** (official Arch packages) - HIGHEST PREFERENCE
|
||||
- **AUR** (yay/paru) - SECOND PREFERENCE
|
||||
- **GitHub/manual installs** - LOWEST PREFERENCE, last resort only
|
||||
|
||||
2. **VERIFY SYNTAX BEFORE WRITING** - Never generate scripts with broken syntax:
|
||||
- Use `--help` to check command syntax BEFORE using it
|
||||
- Test commands in small parts first
|
||||
- Never assume argument names or formats
|
||||
|
||||
3. **STICK TO THE CHOSEN SOLUTION** - Don't drift away from proven solutions:
|
||||
- If research finds tool X works, USE tool X
|
||||
- Don't randomly switch to tool Y mid-implementation
|
||||
- Finish what you start before considering alternatives
|
||||
|
||||
4. **PREFER SIMPLE OVER COMPLEX**:
|
||||
- Use existing tools rather than writing custom scripts
|
||||
- Bash for simple tasks, Python only when complexity requires it
|
||||
- One working solution beats three broken attempts
|
||||
|
||||
5. **CHECK PACKAGE REPOSITORIES FIRST**:
|
||||
- Always check `pacman -Ss` before any manual installation
|
||||
- Always check `yay -Ss` before downloading random scripts
|
||||
- Maintained packages > GitHub scripts > custom solutions
|
||||
1. **RESEARCH FIRST** — Check existing solutions in order: pacman → AUR → GitHub
|
||||
2. **VERIFY SYNTAX BEFORE WRITING** — Use `--help`, test in parts, never assume argument formats
|
||||
3. **STICK TO THE CHOSEN SOLUTION** — Don't drift mid-implementation
|
||||
4. **PREFER SIMPLE OVER COMPLEX** — Existing tools > custom scripts; bash > python for simple tasks
|
||||
5. **CHECK PACKAGE REPOS FIRST** — `pacman -Ss` before any manual installation
|
||||
|
||||
### Failure Patterns to Avoid
|
||||
- ❌ Writing broken syntax without testing commands first
|
||||
- ❌ Switching solutions mid-implementation without reason
|
||||
- ❌ Broken syntax without testing commands first
|
||||
- ❌ Switching solutions mid-implementation
|
||||
- ❌ Overcomplicating when simple solutions exist
|
||||
- ❌ Installing random scripts before checking packages
|
||||
- ❌ Creating custom tools when proven ones exist
|
||||
|
||||
### Success Pattern to Follow
|
||||
### Success Pattern
|
||||
- ✅ Research → Choose → Verify syntax → Implement → Test
|
||||
- ✅ pacman → AUR → GitHub (in that preference order)
|
||||
- ✅ pacman → AUR → GitHub (preference order)
|
||||
- ✅ Use proven, maintained tools over custom scripts
|
||||
- ✅ Test command syntax with `--help` first
|
||||
- ✅ Stay focused on the chosen solution
|
||||
22
TODO.md
22
TODO.md
@@ -1,5 +1,13 @@
|
||||
# Homelab TODO List
|
||||
|
||||
## HIGH PRIO
|
||||
|
||||
- [ ] Move all bigger storages to NAS if it isn't there already
|
||||
- Gitea
|
||||
- Nextcloud
|
||||
- [ ] Unify YADM configs across different systems
|
||||
- use YADM alternatives method if needed for conflicts
|
||||
|
||||
## Network & Security
|
||||
- [x] DuckDNS dynamic DNS setup *(completed - ak-homelab.duckdns.org)*
|
||||
- [x] SSH security hardening *(documented in network-security.md)*
|
||||
@@ -7,7 +15,7 @@
|
||||
- [x] Router port forwarding configuration
|
||||
- [x] !!! Set up geoblocking for SSH. Rest of SSH hardening already done.
|
||||
- [ ] !!! Modify syncthing to sync the NAS folders where appropriate (e.g. Logseq)
|
||||
- [ ] Dockerize everything and use symlinks for dockerfiles (tired of constantly copying stuff over)
|
||||
- [x] Dockerize everything and use symlinks for dockerfiles — all docker-compose files symlinked from `/opt/docker/` to repo `config/docker/`
|
||||
- [ ] !!! IMPORTANT: Run setup scripts made by security reviewer agent
|
||||
- [ ] Ran out of AI quota mid-security review so continue where we left off. Some scripts created but it's not
|
||||
complete yet
|
||||
@@ -117,6 +125,18 @@ Lower priority - mostly using SSH or TTY anyways
|
||||
- [x] Figure out drag and drop window tiling solution -> workaround with keyboard shortcuts
|
||||
- [ ] Install multimedia codecs and applications
|
||||
|
||||
## Docker Storage Migration
|
||||
- [x] Move Gitea storage to NAS — migrated to `/mnt/nas/docker-data/gitea/data` (USER_UID=1024:100 to match NAS ownership)
|
||||
- [x] Move Nextcloud storage to NAS — migrated to `/mnt/nas/docker-data/nextcloud/`
|
||||
- [ ] Persist copyparty index database to NAS — currently rebuilt from scratch on every restart (slow, scans entire NAS); mount `/mnt/nas/.copyparty-db` into the container so the index survives restarts
|
||||
- [ ] Clean up old leftover data: `/opt/docker/gitea/data/`, `/opt/docker/gitea/data.old/`, Docker volumes `gitea_gitea`, `nextcloud_nextcloud_data`, `nextcloud_nextcloud_db`
|
||||
|
||||
## Docker Image Upgrades
|
||||
See `docs/docker-upgrade-plan.md` for full plan. Key warnings:
|
||||
- **Jellyfin**: v10.11+ does a major EF Core DB migration (`library.db` → `jellyfin.db`). Known to hang at "Saving BaseItem entries". **Back up jellyfin data volume before upgrading.**
|
||||
- **Redis**: Stay on `7-alpine` — Redis 8 has ACL breaking changes, not worth upgrading for a cache role
|
||||
- All containers are behind on updates as of 2026-02-27 (see plan doc for details)
|
||||
|
||||
## Security & Maintenance
|
||||
- [ ] Configure automatic security updates
|
||||
- [ ] Set up system monitoring and alerting
|
||||
|
||||
@@ -1,12 +1,3 @@
|
||||
# SSH Honeypot Service
|
||||
# Deploy to: /etc/systemd/system/ssh-honeypot.service
|
||||
#
|
||||
# Setup commands:
|
||||
# sudo cp config/systemd/ssh-honeypot.service /etc/systemd/system/
|
||||
# sudo systemctl daemon-reload
|
||||
# sudo systemctl enable ssh-honeypot.service
|
||||
# sudo systemctl start ssh-honeypot.service
|
||||
|
||||
[Unit]
|
||||
Description=SSH Honeypot (Port 22)
|
||||
After=network.target
|
||||
|
||||
993
docs/services.md
993
docs/services.md
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user