Remove dj-beets project

No longer in use. Drops the beets containers (cli/web), build +
autoimport services and timer, the beet CLI wrapper, /opt/dj-beets
tmpfiles entry, firewall port 8337, the Makefile copy step, and the
src/dj-beets tree (which contained a Beatport token) so the repo can
be made public safely.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
2026-07-18 19:50:03 +02:00
parent ad1dd816f4
commit 7f1767345a
11 changed files with 2 additions and 1942 deletions
+1 -5
View File
@@ -40,11 +40,7 @@ deploy-fileserver:
@echo "Deploying fileserver..."
@echo "======================================"
@echo "Syncing files to fileserver..."
rsync -av --delete --exclude '.git' --exclude 'src/dj-beets/poetry.lock' ./ $(FILESERVER_HOST):/tmp/infra-nix/
@echo "Copying dj-beets project to /opt/dj-beets..."
ssh $(FILESERVER_HOST) "sudo mkdir -p /opt/dj-beets"
rsync -av --delete src/dj-beets/ $(FILESERVER_HOST):/tmp/dj-beets-tmp/
ssh $(FILESERVER_HOST) "sudo rsync -a --delete /tmp/dj-beets-tmp/ /opt/dj-beets/ && sudo rm -rf /tmp/dj-beets-tmp"
rsync -av --delete --exclude '.git' ./ $(FILESERVER_HOST):/tmp/infra-nix/
@echo "Building and switching on fileserver..."
ssh -tt $(FILESERVER_HOST) "cd /tmp/infra-nix && sudo nixos-rebuild switch --flake '.#fileserver'"
@echo "✓ Fileserver deployed successfully"
+1 -114
View File
@@ -152,9 +152,6 @@
# Secrets
"d /data/secrets 0700 root root -"
# dj-beets project
"d /opt/dj-beets 0755 root root -"
];
########################################
@@ -199,35 +196,6 @@
};
};
virtualisation.oci-containers.containers.dj-beets-cli = {
image = "dj-beets:latest";
autoStart = false; # Run manually or via systemd service
volumes = [
"/data/daten/DJing:/data/daten/DJing"
"/opt/dj-beets/config.yaml:/etc/beets/config.yaml:ro"
"/opt/dj-beets/beatport_token.json:/opt/dj-beets/beatport_token.json"
];
environment = {
BEETS_CONFIG = "/etc/beets/config.yaml";
};
cmd = [ "tail" "-f" "/dev/null" ]; # Keep container alive
};
virtualisation.oci-containers.containers.dj-beets-web = {
image = "dj-beets:latest";
autoStart = true;
ports = [ "8337:8337" ];
volumes = [
"/data/daten/DJing:/data/daten/DJing"
"/opt/dj-beets/config.yaml:/etc/beets/config.yaml:ro"
"/opt/dj-beets/beatport_token.json:/opt/dj-beets/beatport_token.json"
];
environment = {
BEETS_CONFIG = "/etc/beets/config.yaml";
};
cmd = [ "beet" "web" ];
};
########################################
# Backup Services
########################################
@@ -262,94 +230,13 @@
pkgs.tmux
pkgs.htop
pkgs.podman-compose
# Beets CLI wrapper
(pkgs.writeShellScriptBin "beet" ''
exec ${pkgs.podman}/bin/podman run --rm -it \
-v /data/daten/DJing:/data/daten/DJing \
-v /opt/dj-beets/config.yaml:/etc/beets/config.yaml:ro \
-v /opt/dj-beets/beatport_token.json:/opt/dj-beets/beatport_token.json \
-e BEETS_CONFIG=/etc/beets/config.yaml \
-u $(id -u):$(id -g) \
dj-beets:latest \
beet "$@"
'')
];
########################################
# DJ-Beets Services
########################################
# Systemd service to build dj-beets image on deploy
systemd.services.dj-beets-build = {
description = "Build dj-beets Docker image";
wantedBy = [ "multi-user.target" ];
before = [ "podman-dj-beets-web.service" ];
after = [ "podman.service" ];
wants = [ "podman.service" ];
serviceConfig = {
Type = "oneshot";
RemainAfterExit = true;
ExecStart = pkgs.writeShellScript "build-dj-beets" ''
set -euo pipefail
if [ ! -f /opt/dj-beets/Dockerfile ]; then
echo "ERROR: Dockerfile not found at /opt/dj-beets" >&2
echo "Deploy with 'make deploy-fileserver' first" >&2
exit 1
fi
cd /opt/dj-beets
${pkgs.podman}/bin/podman build -t dj-beets:latest .
echo "dj-beets image built successfully"
'';
User = "root";
};
};
# Auto-import service using Docker container
systemd.services.dj-beets-autoimport = {
description = "Auto-import music into beets library via Docker";
after = [ "dj-beets-build.service" ];
wants = [ "dj-beets-build.service" ];
serviceConfig = {
Type = "oneshot";
ExecStart = pkgs.writeShellScript "beets-autoimport" ''
set -euo pipefail
INBOX="/data/daten/DJing/Inbox"
LOG="/data/daten/DJing/Data/BeetsAutoImport.log"
# Check if inbox has files
if ! find "$INBOX" -mindepth 1 -maxdepth 1 -type f -print -quit | grep -q .; then
echo "[$(date)] No files in Inbox, skipping" >> "$LOG"
exit 0
fi
echo "[$(date)] Starting beets import" >> "$LOG"
${pkgs.podman}/bin/podman run --rm \
-v /data/daten/DJing:/data/daten/DJing \
-v /opt/dj-beets/config.yaml:/etc/beets/config.yaml:ro \
-v /opt/dj-beets/beatport_token.json:/opt/dj-beets/beatport_token.json \
-e BEETS_CONFIG=/etc/beets/config.yaml \
localhost/dj-beets:latest \
beet import -q /data/daten/DJing/Inbox >> "$LOG" 2>&1
'';
# Use root so the service can access the root Podman image storage
User = "root";
Group = "root";
};
};
systemd.timers.dj-beets-autoimport = {
wantedBy = [ "timers.target" ];
timerConfig = {
OnCalendar = "*:0/10"; # Every 10 minutes
Persistent = true;
};
};
########################################
# Firewall
########################################
networking.firewall.enable = true;
networking.firewall.allowedTCPPorts = [ 22 139 445 8080 8337 5357 3000 2222 ]; # 5357 WSD
networking.firewall.allowedTCPPorts = [ 22 139 445 8080 5357 3000 2222 ]; # 5357 WSD
networking.firewall.allowedUDPPorts = [ 137 138 3702 5353 ]; # NetBIOS + WSD (3702) + mDNS (5353)
}
-10
View File
@@ -1,10 +0,0 @@
.git
.venv
__pycache__
*.pyc
*.pyo
*.pyd
.Python
poetry.lock
data/
.DS_Store
-22
View File
@@ -1,22 +0,0 @@
{
// Use IntelliSense to learn about possible attributes.
// Hover to view descriptions of existing attributes.
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": [
{
"name": "Python Debugger: Current File",
"type": "debugpy",
"request": "launch",
"program": "${workspaceFolder}/main.py",
"args": [
"--import",
"/Volumes/daten/DJing/Inbox",
"--config",
"${workspaceFolder}/config.yaml"
],
"console": "integratedTerminal"
}
]
}
-39
View File
@@ -1,39 +0,0 @@
FROM python:3.12-slim
# Install system dependencies for beets plugins
RUN apt-get update && apt-get install -y \
# For chromaprint/acoustid fingerprinting
libchromaprint-tools \
# For media file handling
ffmpeg \
# Build tools for some Python packages
gcc \
g++ \
&& rm -rf /var/lib/apt/lists/*
# Create app directory
WORKDIR /app
# Copy dependency files
COPY pyproject.toml ./
# Install Poetry
RUN pip install --no-cache-dir poetry
# Configure Poetry to not create virtual env (we're in container)
RUN poetry config virtualenvs.create false
# Install dependencies
RUN poetry install --no-root --no-interaction --no-ansi
# Copy config
COPY config.yaml /etc/beets/config.yaml
# Create data directories
RUN mkdir -p /data/Music /data/Inbox
# Set environment
ENV BEETS_CONFIG=/etc/beets/config.yaml
# Default command
CMD ["beet", "--help"]
-128
View File
@@ -1,128 +0,0 @@
# DJ Beets Setup
Diese Poetry-Umgebung ist dein eigenes Projekt als Ersatz für beets.
Hier verwaltest du Versionen und baust eigene Tools ein.
## Verwendung
### Lokal testen
```bash
cd src/dj-beets
poetry install
poetry run beet --version
```
### Deployment auf fileserver
Das komplette `src/dj-beets/` Projekt wird beim Deploy nach `/opt/dj-beets` kopiert:
```bash
make deploy-fileserver
```
Dies:
1. Kopiert dein `src/dj-beets/` nach `/opt/dj-beets` auf dem Server
2. Installiert alle Dependencies via Poetry (beets, beatport4, beetcamp, etc.)
3. Nutzt `poetry run beet` für alle beets-Operationen
**Wichtig**: Dein lokales Projekt ist die einzige Quelle. Kein externes GitHub-Repo mehr!
## Development Workflow
1. **Änderungen lokal testen**:
```bash
cd src/dj-beets
poetry install
poetry run beet --version
# Deine Änderungen testen
```
2. **Änderungen committen & deployen**:
```bash
git add src/dj-beets/
git commit -m "Update dj-beets project"
git push
# Auf fileserver deployen
make deploy-fileserver
```
3. **Auf fileserver nutzen**:
```bash
ssh fileserver
cd /opt/dj-beets
poetry run beet --version
# Auto-Import läuft automatisch alle 10 Minuten via Timer
```
## Plugins
Alle Plugins werden via `pyproject.toml` verwaltet:
- **beets** ^2.3.1: Basis-Library-Manager
- **beets-beatport4** ^0.4.1: Beatport API v4 Integration
- **beetcamp** ^0.9.3: Bandcamp Autotagger
- **requests, beautifulsoup4, html5lib**: Web-Scraping Dependencies
Weitere Plugins kannst du direkt in `pyproject.toml` hinzufügen.
## Konfiguration
Die beets-Config liegt in `config.yaml` (wird nach `/opt/dj-beets/config.yaml` deployed).
### Beatport Authentication
Beatport4 nutzt Token-basierte Authentifizierung. Token wird in `/data/daten/DJing/Data/beatport_token.json` gespeichert.
**Einmalig authentifizieren:**
```bash
# Auf fileserver
ssh danlin@10.202.82.6
beet beatport4 auth
# Folge den Prompts für Beatport Login
# Oder lokal
cd src/dj-beets
poetry run beet beatport4 auth
```
Das Token-File wird automatisch in allen Containern gemountet und bleibt nach Rebuilds erhalten.
### API Tokens
- **Discogs**: Token in `config.yaml` → `discogs.user_token`
- **Beatport**: Token-File → `/data/daten/DJing/Data/beatport_token.json`
Wichtige Pfade:
- **Library**: `/data/daten/DJing/Data/MusicLibrary.db`
- **Music**: `/data/daten/DJing/Music`
- **Inbox**: `/data/daten/DJing/Inbox`
- **Project**: `/opt/dj-beets`
## Updates
### Eigenes Projekt updaten:
```bash
# Lokal ändern
cd src/dj-beets
# z.B. neue Dependency hinzufügen
poetry add some-new-package
# Deployen
make deploy-fileserver
```
### Dependency-Updates:
```bash
cd src/dj-beets
poetry update
make deploy-fileserver
```
## Auto-Import
Der Auto-Import läuft alle 10 Minuten via systemd Timer und nutzt:
```bash
cd /opt/dj-beets
poetry run beet import -q /data/daten/DJing/Inbox
```
-7
View File
@@ -1,7 +0,0 @@
{
"access_token": "mknr9cGYMcVD85uG8m0av2pCXaihUJ",
"expires_in": 36000,
"token_type": "Bearer",
"scope": "app:docs user:dj",
"refresh_token": "CsMC8Ya5EzLup27Y8DGDX8LwkFIvVF"
}
-139
View File
@@ -1,139 +0,0 @@
# Beets config for fileserver
# Paths point to /data/daten/DJing structure
# Where imported music will be organized into
directory: /data/daten/DJing/Music
# Beets SQLite library database
library: /data/daten/DJing/Data/MusicLibrary.db
# State + import log
statefile: /data/daten/DJing/Data/state.pickle
import:
write: yes # write tags to files
move: yes # move files into directory
copy: no
timid: no # don't ask for confirmation on every match
log: /data/daten/DJing/Data/BeetsImport.log
incremental: yes
autotag: yes
resume: no # don't ask to resume
quiet: yes # less output
quiet_fallback: asis # skip if no good match
none_rec_action: skip # skip if no recommendation
duplicate_action: skip # skip duplicates automatically (was: ask)
group_albums: yes
ui:
color: yes
# Friendly filesystem names
asciify_paths: yes
per_disc_numbering: yes
# Replace problematic characters in paths
replace:
"[\\/]": _
":": _
"\\?": _
'"': _
"\\*": _
"<": _
">": _
"\\|": _
# Plugins
plugins:
- fetchart
# - mbsync
# - discogs
- duplicates
- scrub
- convert
- info
- fromfilename
- ftintitle
- web
- zero
- chroma
- beatport4
- bandcamp
- inline
# Cover Art
fetchart:
auto: yes
minwidth: 600
sources: filesystem coverart itunes amazon albumart
# MusicBrainz
# mbsync:
# album_query: ""
# artist_query: ""
# Discogs (token required)
# discogs:
# data_source_mismatch_penalty: 0.5
# user_token: "yZwmWYwexyfIdEYHxkWEEKiFxLIxoTHSKozBHdpp"
# Beatport (beets-beatport4)
beatport4:
data_source_mismatch_penalty: 0.3
art: no
tokenfile: /opt/dj-beets/beatport_token.json
# Bandcamp (beetcamp)
bandcamp:
data_source_mismatch_penalty: 0.2
preferred_media: Digital
search_max: 5
art: no
include_digital_only_tracks: true
# Cleanup noisy tags
scrub:
auto: yes
zero:
fields: comments lyrics
update_database: yes
# Duplicate detection keys
duplicates:
format: "$path"
keys:
- mb_trackid
- isrc
- acoustid_fingerprint
# Acoustic fingerprinting
chroma:
auto: yes
overwrite: no
# Paths with year/month prefix for better chronology
paths:
default: >-
%time{$added,%Y/%m}/%if{$albumartist,$albumartist,$artist}/$year - $album/
$artist - $title %if{$bpm,($bpm BPM%if{$initial_key,, $initial_key})}
singleton: >-
%time{$added,%Y/%m}/Singles/$artist/
$artist - $title %if{$bpm,($bpm BPM%if{$initial_key,, $initial_key})}
comp: >-
%time{$added,%Y/%m}/Compilations/$album ($year)/
$artist - $title %if{$bpm,($bpm BPM%if{$initial_key,, $initial_key})}
# Optional conversion recipe (requires ffmpeg in PATH)
convert:
auto: no
copy_album_art: yes
formats:
mp3:
command: ffmpeg -i $source -codec:a libmp3lame -qscale:a 2 $dest
extension: mp3
# Web UI
web:
host: 0.0.0.0 # Listen on all interfaces for Docker/network access
port: 8337
-28
View File
@@ -1,28 +0,0 @@
services:
beets:
build: .
container_name: dj-beets
volumes:
# Mount local data directory
- ./data:/data
# Mount config (optional override)
- ./config.yaml:/etc/beets/config.yaml:ro
environment:
- BEETS_CONFIG=/etc/beets/config.yaml
# Keep container running for interactive commands
stdin_open: true
tty: true
# Override default command to keep alive
command: tail -f /dev/null
beets-web:
build: .
container_name: dj-beets-web
volumes:
- ./data:/data
- ./config.yaml:/etc/beets/config.yaml:ro
environment:
- BEETS_CONFIG=/etc/beets/config.yaml
ports:
- "8337:8337"
command: beet web
-1425
View File
File diff suppressed because it is too large Load Diff
-25
View File
@@ -1,25 +0,0 @@
[tool.poetry]
name = "dj-beets"
version = "0.1.0"
description = "Beets + DJ-Plugins (Beatport/Bandcamp) für meine Library"
authors = ["Daniel <daniel@lindenfelser.de>"]
package-mode = false
[tool.poetry.dependencies]
# Python 3.10+ (NixOS 25.05)
python = ">=3.10,<3.14"
beets = "^2.3.1"
beets-beatport4 = "^0.4.1"
# Plugin dependencies
python3-discogs-client = "^2.3.15"
flask = "^3.1.0"
pyacoustid = "^1.3.0"
beetcamp = "^0.23.0"
[tool.poetry.extras]
beets = ["chroma", "discogs"]
[tool.poetry.scripts]
beet = "beets.ui:main"