Refactor Nix package definition and enhance README for lidarr-mb-gap
- Updated `flake.nix` to import the new Nix package definition from `nix/package.nix`, streamlining the build process for the lidarr-mb-gap application. - Enhanced the README.md to include new features such as NixOS module support for automated deployment, detailed deployment instructions, and configuration options for SSH and output directories. - Added sections for troubleshooting output file issues and clarified the structure of the project, including new files for deployment and web serving.
This commit is contained in:
50
README.md
50
README.md
@@ -13,6 +13,8 @@ A tool to identify missing albums on MusicBrainz from Deezer releases for artist
|
|||||||
- 🎨 **Interactive HTML Report**: Filter by type (add/update) and by artist
|
- 🎨 **Interactive HTML Report**: Filter by type (add/update) and by artist
|
||||||
- 🐍 **Python-based**: Clean, functional codebase with proper logging
|
- 🐍 **Python-based**: Clean, functional codebase with proper logging
|
||||||
- ❄️ **Nix Support**: Fully packaged with Nix flake for reproducible builds
|
- ❄️ **Nix Support**: Fully packaged with Nix flake for reproducible builds
|
||||||
|
- 🚀 **NixOS Module**: Automated deployment with systemd service and timer
|
||||||
|
- 🌐 **Web Serving**: Ready for deployment with Caddy or any web server
|
||||||
|
|
||||||
## Requirements
|
## Requirements
|
||||||
|
|
||||||
@@ -58,6 +60,7 @@ LIDARR_API_KEY=your-api-key-here
|
|||||||
# Optional
|
# Optional
|
||||||
SAMBL_URL=https://sambl.lioncat6.com
|
SAMBL_URL=https://sambl.lioncat6.com
|
||||||
MAX_ARTISTS=5 # Limit number of artists processed (0 = no limit)
|
MAX_ARTISTS=5 # Limit number of artists processed (0 = no limit)
|
||||||
|
OUTPUT_DIR=. # Directory where output files will be written (default: current directory)
|
||||||
```
|
```
|
||||||
|
|
||||||
### Getting Your Lidarr API Key
|
### Getting Your Lidarr API Key
|
||||||
@@ -82,7 +85,7 @@ The script will:
|
|||||||
1. Fetch all artists from Lidarr with `monitorNewItems` set to "new" or "all"
|
1. Fetch all artists from Lidarr with `monitorNewItems` set to "new" or "all"
|
||||||
2. For each artist, query SAMBL to find missing albums on MusicBrainz
|
2. For each artist, query SAMBL to find missing albums on MusicBrainz
|
||||||
3. Generate submission links (a-tisket and Harmony)
|
3. Generate submission links (a-tisket and Harmony)
|
||||||
4. Create two output files:
|
4. Create two output files in the directory specified by `OUTPUT_DIR` (or current directory):
|
||||||
- `missing_albums.json` - Machine-readable JSON report
|
- `missing_albums.json` - Machine-readable JSON report
|
||||||
- `missing_albums.html` - Interactive HTML report with filters
|
- `missing_albums.html` - Interactive HTML report with filters
|
||||||
|
|
||||||
@@ -110,7 +113,13 @@ Interactive HTML report with:
|
|||||||
│ ├── main.py # Main application logic
|
│ ├── main.py # Main application logic
|
||||||
│ ├── html_report.py # HTML report generation
|
│ ├── html_report.py # HTML report generation
|
||||||
│ └── pyproject.toml # Python package configuration
|
│ └── pyproject.toml # Python package configuration
|
||||||
|
├── nix/
|
||||||
|
│ └── package.nix # Shared Nix package definition
|
||||||
|
├── nixos/
|
||||||
|
│ ├── lidarr-mb-gap.nix # NixOS module for automated deployment
|
||||||
|
│ └── DEPLOYMENT.md # Detailed deployment guide
|
||||||
├── flake.nix # Nix flake definition
|
├── flake.nix # Nix flake definition
|
||||||
|
├── Caddyfile # Caddy configuration for serving reports
|
||||||
├── .env # Environment variables (create this)
|
├── .env # Environment variables (create this)
|
||||||
└── README.md
|
└── README.md
|
||||||
```
|
```
|
||||||
@@ -136,6 +145,40 @@ The application uses Python's logging module with systemd-friendly output:
|
|||||||
|
|
||||||
Perfect for running as a systemd service.
|
Perfect for running as a systemd service.
|
||||||
|
|
||||||
|
## Deployment
|
||||||
|
|
||||||
|
### NixOS Automated Deployment
|
||||||
|
|
||||||
|
This project includes a NixOS module for automated deployment with:
|
||||||
|
- Systemd service for report generation
|
||||||
|
- Systemd timer for periodic execution (configurable)
|
||||||
|
- Optional automatic rsync sync to VPS
|
||||||
|
- SSH key management for secure VPS access
|
||||||
|
- Caddy configuration for serving the HTML report
|
||||||
|
|
||||||
|
See [nixos/DEPLOYMENT.md](nixos/DEPLOYMENT.md) for detailed deployment instructions.
|
||||||
|
|
||||||
|
### Quick Start with NixOS
|
||||||
|
|
||||||
|
```nix
|
||||||
|
# In your NixOS configuration
|
||||||
|
services.lidarr-mb-gap = {
|
||||||
|
enable = true;
|
||||||
|
package = lidarr-mb-gap.packages.${system}.lidarr-mb-gap; # From flake
|
||||||
|
reportDir = "/var/lib/lidarr-mb-gap/reports";
|
||||||
|
envFile = "/var/lib/lidarr-mb-gap/.env";
|
||||||
|
runInterval = "daily";
|
||||||
|
|
||||||
|
# Optional: Auto-sync to VPS
|
||||||
|
syncToVPS = true;
|
||||||
|
vpsHost = "user@vps";
|
||||||
|
vpsPath = "/var/www/html";
|
||||||
|
sshKeyFile = "/var/lib/lidarr-mb-gap/.ssh/id_ed25519";
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
|
For complete setup instructions, including SSH key configuration and Caddy setup, see the [deployment guide](nixos/DEPLOYMENT.md).
|
||||||
|
|
||||||
## Example Output
|
## Example Output
|
||||||
|
|
||||||
```
|
```
|
||||||
@@ -166,6 +209,11 @@ Perfect for running as a systemd service.
|
|||||||
- Make sure you're running from the project root
|
- Make sure you're running from the project root
|
||||||
- If using Nix, ensure the flake is properly built
|
- If using Nix, ensure the flake is properly built
|
||||||
|
|
||||||
|
### Output files not appearing
|
||||||
|
- Check that `OUTPUT_DIR` environment variable points to a writable directory
|
||||||
|
- Ensure the directory exists and has proper permissions
|
||||||
|
- Check logs for any permission errors
|
||||||
|
|
||||||
## Contributing
|
## Contributing
|
||||||
|
|
||||||
1. Format code with `black src/`
|
1. Format code with `black src/`
|
||||||
|
|||||||
13
flake.nix
13
flake.nix
@@ -21,18 +21,9 @@
|
|||||||
let
|
let
|
||||||
pkgs = import nixpkgs { inherit system; };
|
pkgs = import nixpkgs { inherit system; };
|
||||||
lib = pkgs.lib;
|
lib = pkgs.lib;
|
||||||
lidarr-mb-gap = pkgs.python3Packages.buildPythonApplication {
|
lidarr-mb-gap = import ./nix/package.nix {
|
||||||
pname = "lidarr-mb-gap";
|
inherit pkgs lib;
|
||||||
version = "1.0.0";
|
|
||||||
src = lib.cleanSource ./src;
|
src = lib.cleanSource ./src;
|
||||||
format = "pyproject";
|
|
||||||
nativeBuildInputs = with pkgs.python3Packages; [
|
|
||||||
setuptools
|
|
||||||
];
|
|
||||||
propagatedBuildInputs = with pkgs.python3Packages; [
|
|
||||||
requests
|
|
||||||
python-dotenv
|
|
||||||
];
|
|
||||||
};
|
};
|
||||||
in
|
in
|
||||||
{
|
{
|
||||||
|
|||||||
16
nix/package.nix
Normal file
16
nix/package.nix
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
{ pkgs, lib, src }:
|
||||||
|
|
||||||
|
pkgs.python3Packages.buildPythonApplication {
|
||||||
|
pname = "lidarr-mb-gap";
|
||||||
|
version = "1.0.0";
|
||||||
|
inherit src;
|
||||||
|
format = "pyproject";
|
||||||
|
nativeBuildInputs = with pkgs.python3Packages; [
|
||||||
|
setuptools
|
||||||
|
];
|
||||||
|
propagatedBuildInputs = with pkgs.python3Packages; [
|
||||||
|
requests
|
||||||
|
python-dotenv
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
@@ -34,6 +34,13 @@ Add the module to your NixOS configuration. You have two options:
|
|||||||
syncToVPS = true;
|
syncToVPS = true;
|
||||||
vpsHost = "user@vps"; # Your SSH host alias
|
vpsHost = "user@vps"; # Your SSH host alias
|
||||||
vpsPath = "/var/www/html";
|
vpsPath = "/var/www/html";
|
||||||
|
sshKeyFile = "/var/lib/lidarr-mb-gap/.ssh/id_ed25519";
|
||||||
|
sshKnownHosts = {
|
||||||
|
vps = {
|
||||||
|
hostNames = [ "vps" "vps.example.com" ];
|
||||||
|
publicKey = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAI..."; # Get from ssh-keyscan
|
||||||
|
};
|
||||||
|
};
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
@@ -62,6 +69,18 @@ Add the module to your NixOS configuration. You have two options:
|
|||||||
services.lidarr-mb-gap.reportDir = "/var/lib/lidarr-mb-gap/reports";
|
services.lidarr-mb-gap.reportDir = "/var/lib/lidarr-mb-gap/reports";
|
||||||
services.lidarr-mb-gap.envFile = "/var/lib/lidarr-mb-gap/.env";
|
services.lidarr-mb-gap.envFile = "/var/lib/lidarr-mb-gap/.env";
|
||||||
services.lidarr-mb-gap.runInterval = "daily";
|
services.lidarr-mb-gap.runInterval = "daily";
|
||||||
|
|
||||||
|
# Optional: SSH configuration for VPS sync
|
||||||
|
services.lidarr-mb-gap.syncToVPS = true;
|
||||||
|
services.lidarr-mb-gap.vpsHost = "user@vps";
|
||||||
|
services.lidarr-mb-gap.vpsPath = "/var/www/html";
|
||||||
|
services.lidarr-mb-gap.sshKeyFile = "/var/lib/lidarr-mb-gap/.ssh/id_ed25519";
|
||||||
|
services.lidarr-mb-gap.sshKnownHosts = {
|
||||||
|
vps = {
|
||||||
|
hostNames = [ "vps" "vps.example.com" ];
|
||||||
|
publicKey = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAI...";
|
||||||
|
};
|
||||||
|
};
|
||||||
}
|
}
|
||||||
./configuration.nix
|
./configuration.nix
|
||||||
];
|
];
|
||||||
@@ -100,20 +119,96 @@ sudo chmod 600 /var/lib/lidarr-mb-gap/.env
|
|||||||
|
|
||||||
### 3. Configure SSH for rsync (if using auto-sync)
|
### 3. Configure SSH for rsync (if using auto-sync)
|
||||||
|
|
||||||
If you enabled `syncToVPS`, set up SSH key authentication:
|
If you enabled `syncToVPS`, you need to set up SSH key authentication for the `lidarr-mb-gap` user.
|
||||||
|
|
||||||
|
#### Step 1: Generate SSH Key Pair
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
# On the server
|
# Generate a dedicated SSH key for the service
|
||||||
ssh-keygen -t ed25519 -f ~/.ssh/id_ed25519_lidarr
|
sudo -u lidarr-mb-gap ssh-keygen -t ed25519 -f /var/lib/lidarr-mb-gap/.ssh/id_ed25519 -N ""
|
||||||
ssh-copy-id -i ~/.ssh/id_ed25519_lidarr.pub user@vps
|
|
||||||
|
|
||||||
# Add to ~/.ssh/config
|
# Or generate as your user and copy it
|
||||||
Host vps
|
ssh-keygen -t ed25519 -f ~/.ssh/id_ed25519_lidarr -N ""
|
||||||
HostName your-vps-ip-or-domain
|
sudo mkdir -p /var/lib/lidarr-mb-gap/.ssh
|
||||||
User your-username
|
sudo cp ~/.ssh/id_ed25519_lidarr /var/lib/lidarr-mb-gap/.ssh/id_ed25519
|
||||||
IdentityFile ~/.ssh/id_ed25519_lidarr
|
sudo cp ~/.ssh/id_ed25519_lidarr.pub /var/lib/lidarr-mb-gap/.ssh/id_ed25519.pub
|
||||||
|
sudo chown -R lidarr-mb-gap:lidarr-mb-gap /var/lib/lidarr-mb-gap/.ssh
|
||||||
|
sudo chmod 600 /var/lib/lidarr-mb-gap/.ssh/id_ed25519
|
||||||
|
sudo chmod 644 /var/lib/lidarr-mb-gap/.ssh/id_ed25519.pub
|
||||||
```
|
```
|
||||||
|
|
||||||
|
#### Step 2: Add Public Key to VPS
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Copy the public key to your VPS
|
||||||
|
sudo -u lidarr-mb-gap cat /var/lib/lidarr-mb-gap/.ssh/id_ed25519.pub | ssh user@vps "mkdir -p ~/.ssh && cat >> ~/.ssh/authorized_keys"
|
||||||
|
|
||||||
|
# Or manually:
|
||||||
|
# 1. Display the public key:
|
||||||
|
sudo -u lidarr-mb-gap cat /var/lib/lidarr-mb-gap/.ssh/id_ed25519.pub
|
||||||
|
|
||||||
|
# 2. On your VPS, add it to ~/.ssh/authorized_keys (or the target user's authorized_keys)
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Step 3: Get VPS Host Key (for known_hosts)
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Get the VPS host key fingerprint
|
||||||
|
ssh-keyscan -t ed25519 your-vps-hostname-or-ip
|
||||||
|
|
||||||
|
# This will output something like:
|
||||||
|
# your-vps-hostname ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAI...
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Step 4: Configure in NixOS
|
||||||
|
|
||||||
|
Add SSH configuration to your NixOS config:
|
||||||
|
|
||||||
|
```nix
|
||||||
|
services.lidarr-mb-gap = {
|
||||||
|
enable = true;
|
||||||
|
# ... other options ...
|
||||||
|
|
||||||
|
syncToVPS = true;
|
||||||
|
vpsHost = "user@vps-hostname"; # or "user@vps.example.com"
|
||||||
|
vpsPath = "/var/www/html";
|
||||||
|
|
||||||
|
# Path to SSH private key (optional, defaults to ~/.ssh/id_ed25519)
|
||||||
|
sshKeyFile = "/var/lib/lidarr-mb-gap/.ssh/id_ed25519";
|
||||||
|
|
||||||
|
# SSH known hosts (prevents host key verification prompts)
|
||||||
|
sshKnownHosts = {
|
||||||
|
vps = {
|
||||||
|
hostNames = [ "vps-hostname" "vps.example.com" "1.2.3.4" ]; # All possible hostnames/IPs
|
||||||
|
publicKey = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAI..."; # From ssh-keyscan output
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
|
**Alternative: Manual Setup (if not using NixOS config)**
|
||||||
|
|
||||||
|
If you prefer to set up SSH keys manually without NixOS configuration:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# The service will use default SSH key location: /var/lib/lidarr-mb-gap/.ssh/id_ed25519
|
||||||
|
# Just ensure the key exists and is properly configured
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Step 5: Test SSH Connection
|
||||||
|
|
||||||
|
Before enabling the service, test that SSH works:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Test SSH connection as the service user
|
||||||
|
sudo -u lidarr-mb-gap ssh -i /var/lib/lidarr-mb-gap/.ssh/id_ed25519 user@vps "echo 'SSH connection successful'"
|
||||||
|
|
||||||
|
# Or if using default key location:
|
||||||
|
sudo -u lidarr-mb-gap ssh user@vps "echo 'SSH connection successful'"
|
||||||
|
```
|
||||||
|
|
||||||
|
If this works, rsync should work too. If you get host key verification errors, make sure you've configured `sshKnownHosts` in your NixOS config.
|
||||||
|
|
||||||
### 4. Build and Switch
|
### 4. Build and Switch
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
|
|||||||
@@ -3,6 +3,17 @@
|
|||||||
let
|
let
|
||||||
reportDir = "/var/lib/lidarr-mb-gap/reports";
|
reportDir = "/var/lib/lidarr-mb-gap/reports";
|
||||||
envFile = "/var/lib/lidarr-mb-gap/.env";
|
envFile = "/var/lib/lidarr-mb-gap/.env";
|
||||||
|
|
||||||
|
# Determine which package to use
|
||||||
|
lidarrMbGapPackage = if config.services.lidarr-mb-gap.package != null
|
||||||
|
then config.services.lidarr-mb-gap.package
|
||||||
|
else if config.services.lidarr-mb-gap.src != null
|
||||||
|
then import ../nix/package.nix {
|
||||||
|
inherit pkgs;
|
||||||
|
lib = pkgs.lib;
|
||||||
|
src = config.services.lidarr-mb-gap.src;
|
||||||
|
}
|
||||||
|
else throw "services.lidarr-mb-gap: Either 'package' or 'src' must be set.";
|
||||||
in
|
in
|
||||||
{
|
{
|
||||||
options.services.lidarr-mb-gap = {
|
options.services.lidarr-mb-gap = {
|
||||||
@@ -55,11 +66,35 @@ in
|
|||||||
default = "/var/www/html";
|
default = "/var/www/html";
|
||||||
description = "Path on VPS where reports should be synced";
|
description = "Path on VPS where reports should be synced";
|
||||||
};
|
};
|
||||||
|
|
||||||
|
sshKeyFile = lib.mkOption {
|
||||||
|
type = lib.types.nullOr lib.types.str;
|
||||||
|
default = null;
|
||||||
|
description = "Path to SSH private key file for rsync. If null, uses default SSH key location.";
|
||||||
|
};
|
||||||
|
|
||||||
|
sshKnownHosts = lib.mkOption {
|
||||||
|
type = lib.types.attrsOf (lib.types.submodule {
|
||||||
|
options = {
|
||||||
|
hostNames = lib.mkOption {
|
||||||
|
type = lib.types.listOf lib.types.str;
|
||||||
|
description = "List of hostnames/IPs for this known host";
|
||||||
|
};
|
||||||
|
publicKey = lib.mkOption {
|
||||||
|
type = lib.types.str;
|
||||||
|
description = "SSH public key for the host";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
});
|
||||||
|
default = {};
|
||||||
|
description = "SSH known hosts configuration for the VPS (same format as programs.ssh.knownHosts)";
|
||||||
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
config = lib.mkIf config.services.lidarr-mb-gap.enable {
|
config = lib.mkIf config.services.lidarr-mb-gap.enable {
|
||||||
systemd.tmpfiles.rules = [
|
systemd.tmpfiles.rules = [
|
||||||
"d ${config.services.lidarr-mb-gap.reportDir} 0755 lidarr-mb-gap lidarr-mb-gap -"
|
"d ${config.services.lidarr-mb-gap.reportDir} 0755 lidarr-mb-gap lidarr-mb-gap -"
|
||||||
|
"d /var/lib/lidarr-mb-gap/.ssh 0700 lidarr-mb-gap lidarr-mb-gap -"
|
||||||
];
|
];
|
||||||
|
|
||||||
users.users.lidarr-mb-gap = {
|
users.users.lidarr-mb-gap = {
|
||||||
@@ -71,6 +106,8 @@ in
|
|||||||
|
|
||||||
users.groups.lidarr-mb-gap = {};
|
users.groups.lidarr-mb-gap = {};
|
||||||
|
|
||||||
|
programs.ssh.knownHosts = config.services.lidarr-mb-gap.sshKnownHosts;
|
||||||
|
|
||||||
systemd.services.lidarr-mb-gap = {
|
systemd.services.lidarr-mb-gap = {
|
||||||
description = "Generate Lidarr MusicBrainz Gap Report";
|
description = "Generate Lidarr MusicBrainz Gap Report";
|
||||||
after = [ "network.target" ];
|
after = [ "network.target" ];
|
||||||
@@ -96,7 +133,15 @@ in
|
|||||||
|
|
||||||
# Sync to VPS if enabled
|
# Sync to VPS if enabled
|
||||||
${lib.optionalString (config.services.lidarr-mb-gap.syncToVPS && config.services.lidarr-mb-gap.vpsHost != null) ''
|
${lib.optionalString (config.services.lidarr-mb-gap.syncToVPS && config.services.lidarr-mb-gap.vpsHost != null) ''
|
||||||
|
# Set up SSH options
|
||||||
|
SSH_OPTS=""
|
||||||
|
${lib.optionalString (config.services.lidarr-mb-gap.sshKeyFile != null) ''
|
||||||
|
SSH_OPTS="-i ${config.services.lidarr-mb-gap.sshKeyFile}"
|
||||||
|
''}
|
||||||
|
|
||||||
|
# Use SSH options with rsync
|
||||||
${pkgs.rsync}/bin/rsync -avz --delete \
|
${pkgs.rsync}/bin/rsync -avz --delete \
|
||||||
|
-e "ssh $SSH_OPTS -o StrictHostKeyChecking=yes" \
|
||||||
${config.services.lidarr-mb-gap.reportDir}/ \
|
${config.services.lidarr-mb-gap.reportDir}/ \
|
||||||
${config.services.lidarr-mb-gap.vpsHost}:${config.services.lidarr-mb-gap.vpsPath}/
|
${config.services.lidarr-mb-gap.vpsHost}:${config.services.lidarr-mb-gap.vpsPath}/
|
||||||
''}
|
''}
|
||||||
|
|||||||
Reference in New Issue
Block a user