193 lines
6.3 KiB
Nix
193 lines
6.3 KiB
Nix
{
|
|
description = "Movie Map - Visualize media origin countries from Radarr/Sonarr/Lidarr";
|
|
|
|
inputs = {
|
|
nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
|
|
};
|
|
|
|
outputs = { self, nixpkgs }:
|
|
let
|
|
system = "x86_64-linux";
|
|
pkgs = import nixpkgs { inherit system; };
|
|
|
|
# Python dependencies
|
|
pythonEnv = pkgs.python3.withPackages (ps: with ps; [
|
|
fastapi
|
|
uvicorn
|
|
psycopg
|
|
psycopg-pool
|
|
alembic
|
|
sqlalchemy
|
|
httpx
|
|
pydantic
|
|
pydantic-settings
|
|
python-multipart
|
|
]);
|
|
|
|
# Node.js for frontend
|
|
nodejs = pkgs.nodejs_20;
|
|
|
|
# Frontend build
|
|
frontend = pkgs.buildNpmPackage {
|
|
name = "moviemap-frontend";
|
|
src = ./frontend;
|
|
npmDepsHash = "sha256-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA="; # Update after first build
|
|
buildPhase = ''
|
|
npm run build
|
|
'';
|
|
installPhase = ''
|
|
mkdir -p $out
|
|
cp -r dist/* $out/
|
|
'';
|
|
};
|
|
|
|
# Backend package
|
|
backend = pkgs.stdenv.mkDerivation {
|
|
name = "moviemap-backend";
|
|
src = ./backend;
|
|
buildInputs = [ pythonEnv ];
|
|
installPhase = ''
|
|
mkdir -p $out/backend
|
|
cp -r . $out/backend/
|
|
chmod +x $out/backend/run.sh
|
|
# Make Python scripts executable
|
|
find $out/backend -name "*.py" -exec chmod +x {} \;
|
|
'';
|
|
};
|
|
|
|
# Combined package
|
|
app = pkgs.stdenv.mkDerivation {
|
|
name = "moviemap";
|
|
buildInputs = [ backend frontend ];
|
|
buildPhase = "true";
|
|
installPhase = ''
|
|
mkdir -p $out/backend
|
|
cp -r ${backend}/backend/* $out/backend/
|
|
# Copy frontend dist to backend for serving
|
|
mkdir -p $out/backend/frontend/dist
|
|
cp -r ${frontend}/* $out/backend/frontend/dist/
|
|
'';
|
|
};
|
|
in
|
|
{
|
|
packages.${system} = {
|
|
default = app;
|
|
backend = backend;
|
|
frontend = frontend;
|
|
};
|
|
|
|
devShells.${system}.default = pkgs.mkShell {
|
|
buildInputs = [
|
|
pythonEnv
|
|
nodejs
|
|
pkgs.nodePackages.npm
|
|
pkgs.postgresql
|
|
pkgs.alejandra # Nix formatter
|
|
];
|
|
shellHook = ''
|
|
echo "Movie Map development environment"
|
|
echo "Python: $(python --version)"
|
|
echo "Node: $(node --version)"
|
|
'';
|
|
};
|
|
|
|
nixosModules.default = { config, lib, pkgs, ... }:
|
|
with lib;
|
|
let
|
|
cfg = config.services.moviemap;
|
|
appPackage = self.packages.x86_64-linux.default;
|
|
|
|
# Check if a value is a file path (starts with /)
|
|
isPath = v: lib.hasPrefix "/" (toString v);
|
|
|
|
# Build environment variables - use file paths directly for secrets
|
|
# The run.sh script will read from files at runtime
|
|
envVars = [
|
|
"PORT=${toString cfg.port}"
|
|
"POSTGRES_SOCKET_PATH=${cfg.postgresSocketPath}"
|
|
] ++ [
|
|
# API keys - if path, pass as-is; if string, pass directly
|
|
(if isPath cfg.sonarrApiKey
|
|
then "SONARR_API_KEY_FILE=${toString cfg.sonarrApiKey}"
|
|
else "SONARR_API_KEY=${toString cfg.sonarrApiKey}")
|
|
(if isPath cfg.radarrApiKey
|
|
then "RADARR_API_KEY_FILE=${toString cfg.radarrApiKey}"
|
|
else "RADARR_API_KEY=${toString cfg.radarrApiKey}")
|
|
(if isPath cfg.lidarrApiKey
|
|
then "LIDARR_API_KEY_FILE=${toString cfg.lidarrApiKey}"
|
|
else "LIDARR_API_KEY=${toString cfg.lidarrApiKey}")
|
|
] ++ lib.optional (cfg.adminToken != null)
|
|
(if isPath cfg.adminToken
|
|
then "MOVIEMAP_ADMIN_TOKEN_FILE=${toString cfg.adminToken}"
|
|
else "MOVIEMAP_ADMIN_TOKEN=${toString cfg.adminToken}");
|
|
in
|
|
{
|
|
options.services.moviemap = {
|
|
enable = mkEnableOption "Movie Map service";
|
|
|
|
port = mkOption {
|
|
type = types.int;
|
|
default = 8080;
|
|
description = "Port to bind the backend server";
|
|
};
|
|
|
|
postgresSocketPath = mkOption {
|
|
type = types.str;
|
|
default = "/run/postgresql";
|
|
description = "PostgreSQL socket directory";
|
|
};
|
|
|
|
sonarrApiKey = mkOption {
|
|
type = types.either types.str types.path;
|
|
description = "Sonarr API key (string or path to file, e.g., /run/secrets/sonarr-api-key)";
|
|
};
|
|
|
|
radarrApiKey = mkOption {
|
|
type = types.either types.str types.path;
|
|
description = "Radarr API key (string or path to file, e.g., /run/secrets/radarr-api-key)";
|
|
};
|
|
|
|
lidarrApiKey = mkOption {
|
|
type = types.either types.str types.path;
|
|
description = "Lidarr API key (string or path to file, e.g., /run/secrets/lidarr-api-key)";
|
|
};
|
|
|
|
adminToken = mkOption {
|
|
type = types.nullOr (types.either types.str types.path);
|
|
default = null;
|
|
description = "Optional admin token for sync endpoint (string or path to file)";
|
|
};
|
|
};
|
|
|
|
config = mkIf cfg.enable {
|
|
systemd.services.moviemap-backend = {
|
|
description = "Movie Map Backend";
|
|
wantedBy = [ "multi-user.target" ];
|
|
after = [ "network.target" "postgresql.service" ];
|
|
|
|
serviceConfig = {
|
|
Type = "simple";
|
|
ExecStart = "${appPackage}/backend/run.sh";
|
|
Restart = "always";
|
|
RestartSec = "10s";
|
|
|
|
Environment = envVars;
|
|
|
|
User = "moviemap";
|
|
Group = "moviemap";
|
|
};
|
|
};
|
|
|
|
users.users.moviemap = {
|
|
isSystemUser = true;
|
|
group = "moviemap";
|
|
description = "Movie Map service user";
|
|
};
|
|
|
|
users.groups.moviemap = {};
|
|
};
|
|
};
|
|
};
|
|
}
|
|
|