danlin c4938a6c05 Remove plaintext secrets, update SSH key, and upgrade to NixOS 25.11
Replace initialPassword with hashedPassword for danlin user, move
FileBrowser admin password to external environmentFile with restricted
secrets directory, update SSH authorized key, and bump nixpkgs to 25.11.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-19 17:44:03 +01:00

# infra-nix: NixOS Infrastructure

Dieses Repository enthält die deklarative NixOS-Infrastruktur für:
- **fileserver**: SMB, FileBrowser, rclone-Backup, DJ-Beets Musik-Library
- **gateway**: AdGuardHome (DNS), Caddy (Reverse Proxy)

## Quick Deploy

```bash
# Alle Systeme deployen
make deploy

# Nur fileserver deployen
make deploy-fileserver

# Nur gateway deployen
make deploy-gateway
```

---

## DJ-Beets Projekt (`src/dj-beets/`)

Dein eigenes Projekt als Beets-Ersatz. Wird beim Deploy auf `/opt/dj-beets` kopiert.

**Details siehe:** [src/dj-beets/README.md](src/dj-beets/README.md)

**Workflow:**
1. Lokal in `src/dj-beets/` entwickeln
2. `make deploy-fileserver` → deployed auf Server
3. Auto-Import läuft alle 10 Minuten via Timer

---

## Fileserver: rclone + SMB Quickstart

This guide covers setting up rclone (Google Drive) and setting the SMB password for user `danlin`.

---

## rclone (Google Drive)

The system has `rclone` installed and a systemd job to sync `/data` to a remote named `gdrive`:

- Service: `rclone-backup.service` (oneshot)
- Timer: `rclone-backup.timer` (runs daily 03:00)
- Log: `/var/log/rclone-backup.log`

### 1) Create the remote `gdrive`
Run on the fileserver:

```bash
sudo -i
rclone config
```

Then:
- n) New remote
- name: `gdrive`
- storage: `drive` (Google Drive)
- Use auto config? For headless server choose "No"
  - Follow the printed instructions using another machine, or run on a desktop and copy the token
- Keep defaults unless you need a service account
- y) Yes to save

Verify:
```bash
rclone lsd gdrive:
rclone mkdir gdrive:backup-daten
```

### 2) Test backup manually
```bash
sudo systemctl start rclone-backup.service
sudo journalctl -u rclone-backup -e
sudo tail -n 100 /var/log/rclone-backup.log
```

### 3) Check/enable timer
```bash
systemctl list-timers '*rclone*'
sudo systemctl enable --now rclone-backup.timer
```

---

## SMB password for `danlin`

The share configuration:
- Protected share: `daten` → requires user `danlin`
- Guest share: `daten-share` → guest access allowed

Set the Samba password for `danlin` (independent from system login password):

```bash
sudo smbpasswd -a danlin
```

Useful commands:
```bash
sudo pdbedit -L                   # list Samba users
sudo systemctl status samba
sudo journalctl -u samba -e
```

Access examples:
- Windows: `\\fileserver\daten` or `\\fileserver\daten-share`
- macOS Finder: Go → Connect to Server → `smb://fileserver/daten` or `smb://fileserver/daten-share`

---

## Troubleshooting
- rclone auth on headless: use `rclone authorize 'drive'` on a desktop and paste token
- Permissions: ensure `/data/daten` and `/data/daten/share` exist and are writable (`systemd-tmpfiles` creates them)
- Firewall: SMB ports 139/445 are open by module config

---

## K8s-Server: Docker Registry

The k8s-server runs a private Docker Registry v2 with self-signed TLS certificate. Authentication is handled by Caddy for external access.

**Access:**
- External URL: `https://registry.home.lindenfelser.de` (authenticated via Caddy)
- Internal URL: `https://10.202.82.7:5000` (direct, no auth - K8s pods)
- Default credentials: `admin` / `changeme` (Caddy basic auth)
- Storage: `/var/lib/docker-registry` (root partition)

### 1) Login from external machine

```bash
# Login to registry
docker login registry.home.lindenfelser.de
# Username: admin
# Password: changeme
```

### 2) Push an image

```bash
# Tag your image
docker tag myapp:latest registry.home.lindenfelser.de/myapp:latest

# Push to registry
docker push registry.home.lindenfelser.de/myapp:latest
```

### 3) Pull from Kubernetes pods

The k8s cluster is configured to authenticate automatically. Create a deployment:

```yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: myapp
spec:
  replicas: 1
  selector:
    matchLabels:
      app: myapp
  template:
    metadata:
      labels:
        app: myapp
    spec:
      containers:
      - name: myapp
        image: registry.home.lindenfelser.de/myapp:latest
```

### 4) Change registry password

Authentication is handled by Caddy. Generate new password hash and update:

```bash
# Generate new password hash locally
caddy hash-password --plaintext 'yournewpassword'
```

Then update the hash in [modules/gateway.nix](modules/gateway.nix) in the `basicauth` section and redeploy:

```bash
make deploy-gateway
```

### 5) Monitor storage usage

Check daily storage logs:

```bash
# View growth tracking
sudo journalctl -u docker-registry-growth-tracker

# View last 30 days of size tracking
sudo tail -n 30 /var/log/docker-registry-growth.log

# Check current usage
sudo du -sh /var/lib/docker-registry
df -h /
```

### 6) Manual garbage collection

Garbage collection runs automatically every Sunday at 03:00. To run manually:

```bash
sudo systemctl start docker-registry-garbage-collect
sudo journalctl -u docker-registry-garbage-collect -e
```

### 7) List images in registry

```bash
# List all repositories
curl -u admin:changeme https://registry.home.lindenfelser.de/v2/_catalog

# List tags for a specific image
curl -u admin:changeme https://registry.home.lindenfelser.de/v2/myapp/tags/list
```

### Troubleshooting
- **TLS certificate errors**: Registry uses self-signed certificate. External Docker clients need to add to insecure registries or install the cert
- **Authentication fails**: Verify Caddy basicauth configuration in [modules/gateway.nix](modules/gateway.nix). K8s pods access registry directly without auth.
- **Storage full**: Check root partition usage with `df -h /` and run garbage collection
- **K8s pods can't pull**: Verify `registries.yaml` points to internal registry (10.202.82.7:5000) and restart k3s: `sudo systemctl restart k3s`


rclone (Google Drive)

The system has rclone installed and a systemd job to sync /data to a remote named gdrive:

  • Service: rclone-backup.service (oneshot)
  • Timer: rclone-backup.timer (runs daily 03:00)
  • Log: /var/log/rclone-backup.log

1) Create the remote gdrive

Run on the fileserver:

sudo -i
rclone config

Then:

  • n) New remote
  • name: gdrive
  • storage: drive (Google Drive)
  • Use auto config? For headless server choose "No"
    • Follow the printed instructions using another machine, or run on a desktop and copy the token
  • Keep defaults unless you need a service account
  • y) Yes to save

Verify:

rclone lsd gdrive:
rclone mkdir gdrive:backup-daten

2) Test backup manually

sudo systemctl start rclone-backup.service
sudo journalctl -u rclone-backup -e
sudo tail -n 100 /var/log/rclone-backup.log

3) Check/enable timer

systemctl list-timers '*rclone*'
sudo systemctl enable --now rclone-backup.timer

SMB password for danlin

The share configuration:

  • Protected share: daten → requires user danlin
  • Guest share: daten-share → guest access allowed

Set the Samba password for danlin (independent from system login password):

sudo smbpasswd -a danlin

Useful commands:

sudo pdbedit -L                   # list Samba users
sudo systemctl status samba
sudo journalctl -u samba -e

Access examples:

  • Windows: \\fileserver\daten or \\fileserver\daten-share
  • macOS Finder: Go → Connect to Server → smb://fileserver/daten or smb://fileserver/daten-share

Troubleshooting

  • rclone auth on headless: use rclone authorize 'drive' on a desktop and paste token
  • Permissions: ensure /data/daten and /data/daten/share exist and are writable (systemd-tmpfiles creates them)
  • Firewall: SMB ports 139/445 are open by module config
S
Description
No description provided
Readme 153 KiB
Languages
Nix 66.4%
Shell 19.2%
Makefile 14.4%