- 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
238 lines
6.3 KiB
Markdown
238 lines
6.3 KiB
Markdown
# Services & Applications
|
|
|
|
Reference for all self-hosted services. Useful for troubleshooting and migrating to a new machine.
|
|
|
|
## Nginx Reverse Proxy
|
|
|
|
**Status**: ✅ Active | **Config**: `config/nginx/homelab.conf` → `/etc/nginx/sites-available/homelab` (symlinked)
|
|
|
|
### Features
|
|
- Path-based routing (`/gitea/`, `/files/`, `/media/`, `/netdata/`, `/portainer/`)
|
|
- SSL termination with Let's Encrypt (auto-renewal via certbot timer)
|
|
- WebDAV support for Copyparty
|
|
- HTTP → HTTPS redirect
|
|
- Security headers
|
|
|
|
### Management
|
|
```bash
|
|
sudo nginx -t # Test config
|
|
sudo systemctl reload nginx # Reload (or restart for major changes)
|
|
sudo journalctl -u nginx -f # Logs
|
|
```
|
|
|
|
### New Machine Setup
|
|
```bash
|
|
sudo pacman -S nginx certbot certbot-nginx
|
|
sudo mkdir -p /etc/nginx/sites-available /etc/nginx/sites-enabled
|
|
sudo ln -s /home/hoborg/homelab/config/nginx/homelab.conf /etc/nginx/sites-available/homelab
|
|
sudo ln -s /etc/nginx/sites-available/homelab /etc/nginx/sites-enabled/homelab
|
|
sudo certbot --nginx -d ak-homelab.duckdns.org
|
|
sudo systemctl enable --now certbot-renew.timer
|
|
```
|
|
|
|
---
|
|
|
|
## Gitea (Git Server)
|
|
|
|
**Status**: ✅ Running | **Docker**: `/opt/docker/gitea/` | **Data**: `/mnt/nas/docker-data/gitea/data`
|
|
|
|
- **Web**: https://ak-homelab.duckdns.org/gitea/
|
|
- **SSH**: `ssh://git@ak-homelab.duckdns.org:2223`
|
|
- **Ports**: 3000 (web, localhost only), 2223 (SSH, public)
|
|
- **UID**: 1024:100 (matches NAS file ownership)
|
|
|
|
### Management
|
|
```bash
|
|
cd /opt/docker/gitea
|
|
docker compose logs -f gitea
|
|
docker compose restart
|
|
docker compose pull && docker compose up -d # Update
|
|
```
|
|
|
|
### New Machine Setup
|
|
```bash
|
|
sudo mkdir -p /opt/docker/gitea
|
|
sudo ln -s /home/hoborg/homelab/config/docker/gitea/docker-compose.yml /opt/docker/gitea/docker-compose.yml
|
|
cd /opt/docker/gitea && docker compose up -d
|
|
```
|
|
|
|
---
|
|
|
|
## Copyparty (File Server / WebDAV)
|
|
|
|
**Status**: ✅ Running | **Type**: systemd | **Config**: `config/systemd/copyparty.service` (symlinked)
|
|
|
|
- **Web / WebDAV**: https://ak-homelab.duckdns.org/files/
|
|
- **Port**: 8082 (behind Nginx)
|
|
- **Config**: `~/.config/copyparty/copyparty.conf`
|
|
|
|
### Volumes
|
|
```
|
|
/shared → /home/hoborg/shared (guest: rw, hoborg: rwmd)
|
|
/documents → /home/hoborg/Documents (hoborg: rwmd)
|
|
/music → /home/hoborg/Music (guest: rw, hoborg: rwmd)
|
|
/videos → /home/hoborg/Videos (guest: rw, hoborg: rwmd)
|
|
/pictures → /home/hoborg/Pictures (guest: rw, hoborg: rwmd)
|
|
/private → /home/hoborg/private (hoborg only: rwmd)
|
|
```
|
|
|
|
### Management
|
|
```bash
|
|
sudo systemctl status copyparty
|
|
sudo systemctl restart copyparty
|
|
journalctl -fu copyparty
|
|
```
|
|
|
|
### WebDAV Clients
|
|
- **X-plore (Android)**: Server `ak-homelab.duckdns.org`, Path `/files/shared/`, Port 443, HTTPS
|
|
- **rclone**: `rclone config create homelab-webdav webdav url=https://ak-homelab.duckdns.org/files/ vendor=other user=hoborg`
|
|
|
|
### New Machine Setup
|
|
```bash
|
|
sudo pacman -S copyparty
|
|
sudo ln -s /home/hoborg/homelab/config/systemd/copyparty.service /etc/systemd/system/copyparty.service
|
|
sudo systemctl daemon-reload && sudo systemctl enable --now copyparty
|
|
```
|
|
|
|
---
|
|
|
|
## Jellyfin (Media Server)
|
|
|
|
**Status**: ✅ Running | **Docker**: `/opt/docker/jellyfin/`
|
|
|
|
- **Local**: http://localhost:8096
|
|
- **External**: https://ak-homelab.duckdns.org/media/
|
|
- **Hardware accel**: VAAPI/QSV via `/dev/dri`
|
|
|
|
### Media Library Paths (inside container)
|
|
```
|
|
/media/music → /home/hoborg/Music
|
|
/media/videos → /home/hoborg/Videos
|
|
/media/pictures → /home/hoborg/Pictures
|
|
/media/shared → /home/hoborg/shared
|
|
/media/private → /home/hoborg/private
|
|
```
|
|
|
|
### Management
|
|
```bash
|
|
cd /opt/docker/jellyfin
|
|
docker compose logs -f jellyfin
|
|
docker compose restart
|
|
docker compose pull && docker compose up -d # Update
|
|
```
|
|
|
|
### ⚠️ Upgrade Warning
|
|
v10.11+ performs a major EF Core DB migration (`library.db` → `jellyfin.db`). Known to hang at "Saving BaseItem entries". **Always back up the Jellyfin data volume before upgrading.**
|
|
|
|
### New Machine Setup
|
|
```bash
|
|
sudo mkdir -p /opt/docker/jellyfin
|
|
sudo ln -s /home/hoborg/homelab/config/docker/jellyfin/docker-compose.yml /opt/docker/jellyfin/docker-compose.yml
|
|
cd /opt/docker/jellyfin && docker compose up -d
|
|
# Visit http://localhost:8096 for setup wizard
|
|
```
|
|
|
|
---
|
|
|
|
## Nextcloud (Cloud Storage)
|
|
|
|
**Status**: ✅ Running | **Docker**: `/opt/docker/nextcloud/` | **Data**: `/mnt/nas/docker-data/nextcloud/`
|
|
|
|
- **Web**: https://ak-homelab.duckdns.org/nextcloud/
|
|
- **Stack**: nextcloud-app + mariadb + redis
|
|
|
|
### Management
|
|
```bash
|
|
cd /opt/docker/nextcloud
|
|
docker compose logs -f
|
|
docker compose restart
|
|
```
|
|
|
|
### New Machine Setup
|
|
```bash
|
|
sudo mkdir -p /opt/docker/nextcloud
|
|
sudo ln -s /home/hoborg/homelab/config/docker/nextcloud/docker-compose.yml /opt/docker/nextcloud/docker-compose.yml
|
|
cd /opt/docker/nextcloud && docker compose up -d
|
|
```
|
|
|
|
---
|
|
|
|
## Portainer (Docker Management)
|
|
|
|
**Status**: ✅ Running | **Docker**: `/opt/docker/portainer/`
|
|
|
|
- **Access**: https://ak-homelab.duckdns.org/portainer/ (built-in auth)
|
|
- **Port**: 9000
|
|
|
|
### Management
|
|
```bash
|
|
cd /opt/docker/portainer && docker compose restart
|
|
```
|
|
|
|
---
|
|
|
|
## Netdata (System Monitoring)
|
|
|
|
**Status**: ✅ Running | **Docker**: `/opt/docker/netdata/`
|
|
|
|
- **Access**: https://ak-homelab.duckdns.org/netdata/ (nginx basic auth)
|
|
- **Port**: 19999
|
|
|
|
---
|
|
|
|
## qBittorrent
|
|
|
|
**Status**: ✅ Running | **Docker**: `/opt/docker/qbittorrent/`
|
|
|
|
- **Access**: https://ak-homelab.duckdns.org/qbt/
|
|
- **Port**: 8080
|
|
- **Downloads**: NAS preferred (use Synology Download Station for direct-to-NAS torrenting)
|
|
|
|
---
|
|
|
|
## SSL Certificates
|
|
|
|
**Status**: ✅ Auto-renewal active
|
|
|
|
```bash
|
|
# Manual renewal test
|
|
sudo certbot renew --dry-run
|
|
|
|
# Check timer
|
|
sudo systemctl status certbot-renew.timer
|
|
journalctl -u certbot-renew.service
|
|
```
|
|
|
|
- **Cert**: `/etc/letsencrypt/live/ak-homelab.duckdns.org/fullchain.pem`
|
|
- **Key**: `/etc/letsencrypt/live/ak-homelab.duckdns.org/privkey.pem`
|
|
- **Renewal**: Every 90 days via systemd timer
|
|
|
|
---
|
|
|
|
## Landing Page
|
|
|
|
**Config**: `config/www/index.html` → `/var/www/homelab/index.html` (symlinked)
|
|
|
|
Edit the file in the repo — changes are live immediately (no restart needed).
|
|
|
|
---
|
|
|
|
## Troubleshooting
|
|
|
|
See `docs/troubleshooting/` for specific issues. Common checks:
|
|
|
|
```bash
|
|
# All containers running?
|
|
docker ps
|
|
|
|
# Nginx config valid?
|
|
sudo nginx -t
|
|
|
|
# NAS mounted?
|
|
mountpoint /mnt/nas
|
|
|
|
# Service logs
|
|
journalctl -fu <service>
|
|
docker compose -f /opt/docker/<service>/docker-compose.yml logs -f
|
|
```
|