Compare commits

..

12 Commits

Author SHA1 Message Date
0d0ed5445a moved models 2026-04-19 21:05:56 -04:00
9e4c6f6f56 adding qwen3.6 2026-04-19 21:05:56 -04:00
1cf4b99d18 updating signing.format for programs.git 2026-04-19 10:35:48 -04:00
b536fb9f09 removed fallbackToPassword = true; 2026-04-19 08:08:33 -04:00
github-actions[bot]
c41a2ce3bd flake.lock: Update
Flake lock file updates:

• Updated input 'firefox-addons':
    'gitlab:rycee/nur-expressions/81e28f4?dir=pkgs/firefox-addons' (2026-03-20)
  → 'gitlab:rycee/nur-expressions/0581568?dir=pkgs/firefox-addons' (2026-04-17)
• Updated input 'home-manager':
    'github:nix-community/home-manager/9670de2' (2026-03-20)
  → 'github:nix-community/home-manager/565e534' (2026-04-17)
• Updated input 'nixos-hardware':
    'github:nixos/nixos-hardware/2d4b471' (2026-03-20)
  → 'github:nixos/nixos-hardware/c775c27' (2026-04-06)
• Updated input 'nixpkgs':
    'github:nixos/nixpkgs/b40629e' (2026-03-18)
  → 'github:nixos/nixpkgs/4bd9165' (2026-04-14)
• Updated input 'nixpkgs-master':
    'github:nixos/nixpkgs/8620c0b' (2026-03-21)
  → 'github:nixos/nixpkgs/025c852' (2026-04-17)
• Updated input 'sops-nix':
    'github:Mic92/sops-nix/29b6519' (2026-03-19)
  → 'github:Mic92/sops-nix/d4971dd' (2026-04-13)
2026-04-19 08:08:33 -04:00
8ef776f859 updating download-buffer-size 2026-04-18 22:12:47 -04:00
d350c2d074 adding codex 2026-04-18 20:14:11 -04:00
93d6914e9d enabling appimages 2026-04-18 20:14:11 -04:00
7db063a240 setting up whisper transcriber 2026-04-18 19:09:02 -04:00
dfe5997e0b removing brain_substituter.nix from bob 2026-04-18 12:00:59 -04:00
68671a1e84 adding steve 2026-04-18 11:56:56 -04:00
bcc2227cfd updating syncthing phone id 2026-04-18 11:53:20 -04:00
35 changed files with 598 additions and 33 deletions

View File

@@ -34,6 +34,7 @@ in
warn-dirty = false;
flake-registry = ""; # disable global flake registries
connect-timeout = 10;
download-buffer-size = 536870912;
fallback = true;
};

View File

@@ -12,7 +12,7 @@
brain.id = "SSCGIPI-IV3VYKB-TRNIJE3-COV4T2H-CDBER7F-I2CGHYA-NWOEUDU-3T5QAAN"; # cspell:disable-line
ipad.id = "KI76T3X-SFUGV2L-VSNYTKR-TSIUV5L-SHWD3HE-GQRGRCN-GY4UFMD-CW6Z6AX"; # cspell:disable-line
jeeves.id = "ICRHXZW-ECYJCUZ-I4CZ64R-3XRK7CG-LL2HAAK-FGOHD22-BQA4AI6-5OAL6AG"; # cspell:disable-line
phone.id = "TBRULKD-7DZPGGZ-F6LLB7J-MSO54AY-7KLPBIN-QOFK6PX-W2HBEWI-PHM2CQI"; # cspell:disable-line
phone.id = "JPVQKQW-CFXOJXT-Q5G5F3H-QIDHDRE-GKHPTQB-GXZUQSP-U7FR7F7-INP3AAH"; # cspell:disable-line
rhapsody-in-green.id = "ASL3KC4-3XEN6PA-7BQBRKE-A7JXLI6-DJT43BY-Q4WPOER-7UALUAZ-VTPQ6Q4"; # cspell:disable-line
};
};

36
flake.lock generated
View File

@@ -8,11 +8,11 @@
},
"locked": {
"dir": "pkgs/firefox-addons",
"lastModified": 1773979456,
"narHash": "sha256-9kBMJ5IvxqNlkkj/swmE8uK1Sc7TL/LIRUI958m7uBM=",
"lastModified": 1776398575,
"narHash": "sha256-WArU6WOdWxzbzGqYk4w1Mucg+bw/SCl6MoSp+/cZMio=",
"owner": "rycee",
"repo": "nur-expressions",
"rev": "81e28f47ac18d9e89513929c77e711e657b64851",
"rev": "05815686caf4e3678f5aeb5fd36e567886ab0d30",
"type": "gitlab"
},
"original": {
@@ -29,11 +29,11 @@
]
},
"locked": {
"lastModified": 1774007980,
"narHash": "sha256-FOnZjElEI8pqqCvB6K/1JRHTE8o4rer8driivTpq2uo=",
"lastModified": 1776454077,
"narHash": "sha256-7zSUFWsU0+jlD7WB3YAxQ84Z/iJurA5hKPm8EfEyGJk=",
"owner": "nix-community",
"repo": "home-manager",
"rev": "9670de2921812bc4e0452f6e3efd8c859696c183",
"rev": "565e5349208fe7d0831ef959103c9bafbeac0681",
"type": "github"
},
"original": {
@@ -44,11 +44,11 @@
},
"nixos-hardware": {
"locked": {
"lastModified": 1774018263,
"narHash": "sha256-HHYEwK1A22aSaxv2ibhMMkKvrDGKGlA/qObG4smrSqc=",
"lastModified": 1775490113,
"narHash": "sha256-2ZBhDNZZwYkRmefK5XLOusCJHnoeKkoN95hoSGgMxWM=",
"owner": "nixos",
"repo": "nixos-hardware",
"rev": "2d4b4717b2534fad5c715968c1cece04a172b365",
"rev": "c775c2772ba56e906cbeb4e0b2db19079ef11ff7",
"type": "github"
},
"original": {
@@ -60,11 +60,11 @@
},
"nixpkgs": {
"locked": {
"lastModified": 1773821835,
"narHash": "sha256-TJ3lSQtW0E2JrznGVm8hOQGVpXjJyXY2guAxku2O9A4=",
"lastModified": 1776169885,
"narHash": "sha256-l/iNYDZ4bGOAFQY2q8y5OAfBBtrDAaPuRQqWaFHVRXM=",
"owner": "nixos",
"repo": "nixpkgs",
"rev": "b40629efe5d6ec48dd1efba650c797ddbd39ace0",
"rev": "4bd9165a9165d7b5e33ae57f3eecbcb28fb231c9",
"type": "github"
},
"original": {
@@ -76,11 +76,11 @@
},
"nixpkgs-master": {
"locked": {
"lastModified": 1774051532,
"narHash": "sha256-d3CGMweyYIcPuTj5BKq+1Lx4zwlgL31nVtN647tOZKo=",
"lastModified": 1776469842,
"narHash": "sha256-sqzM6PKMQoGk8Sl+uv2sbP1qiS2SPQhA2yn5zgZINMc=",
"owner": "nixos",
"repo": "nixpkgs",
"rev": "8620c0b5cc8fbe76502442181be1d0514bc3a1b7",
"rev": "025c852a89be820b3117f604c8ace42e9b4caa08",
"type": "github"
},
"original": {
@@ -125,11 +125,11 @@
]
},
"locked": {
"lastModified": 1773889674,
"narHash": "sha256-+ycaiVAk3MEshJTg35cBTUa0MizGiS+bgpYw/f8ohkg=",
"lastModified": 1776119890,
"narHash": "sha256-Zm6bxLNnEOYuS/SzrAGsYuXSwk3cbkRQZY0fJnk8a5M=",
"owner": "Mic92",
"repo": "sops-nix",
"rev": "29b6519f3e0780452bca0ac0be4584f04ac16cc5",
"rev": "d4971dd58c6627bfee52a1ad4237637c0a2fb0cd",
"type": "github"
},
"original": {

View File

@@ -23,6 +23,7 @@
apscheduler
fastapi
fastapi-cli
faster-whisper
httpx
mypy
orjson

View File

@@ -26,6 +26,7 @@ dependencies = [
[project.scripts]
database = "python.database_cli:app"
van-inventory = "python.van_inventory.main:serve"
whisper-transcribe = "python.tools.whisper.transcribe:main"
[dependency-groups]
dev = [
@@ -50,6 +51,7 @@ lint.ignore = [
"COM812", # (TEMP) conflicts when used with the formatter
"ISC001", # (TEMP) conflicts when used with the formatter
"S603", # (PERM) This is known to cause a false positive
"S607", # (PERM) This is becoming a consistent annoyance
]
[tool.ruff.lint.per-file-ignores]
@@ -78,9 +80,7 @@ lint.ignore = [
"python/congress_tracker/**" = [
"TC003", # (perm) this creates issues because sqlalchemy uses these at runtime
]
"python/eval_warnings/**" = [
"S607", # (perm) gh and git are expected on PATH in the runner environment
]
"python/alembic/**" = [
"INP001", # (perm) this creates LSP issues for alembic
]

View File

@@ -0,0 +1,17 @@
FROM nvidia/cuda:12.4.1-cudnn-runtime-ubuntu22.04
ENV DEBIAN_FRONTEND=noninteractive \
PYTHONDONTWRITEBYTECODE=1 \
PYTHONUNBUFFERED=1
RUN apt-get update \
&& apt-get install -y --no-install-recommends python3 python3-pip ffmpeg \
&& rm -rf /var/lib/apt/lists/*
RUN pip3 install --no-cache-dir --upgrade pip \
&& pip3 install --no-cache-dir faster-whisper requests
WORKDIR /app
COPY python/tools/whisper/inference.py /app/inference.py
ENTRYPOINT ["python3", "/app/inference.py"]

View File

@@ -0,0 +1,2 @@
*
!python/tools/whisper/inference.py

View File

@@ -0,0 +1 @@
"""Whisper transcription tools (host orchestrator and container entrypoint)."""

View File

@@ -0,0 +1,136 @@
"""Container entrypoint that transcribes a directory of audio files with faster-whisper.
Run inside the whisper-transcribe docker image; segment timestamps are grouped
into one-minute buckets so the output reads as ``[HH:MM:00] text``.
"""
from __future__ import annotations
import argparse
import logging
from pathlib import Path
from faster_whisper import WhisperModel
logger = logging.getLogger(__name__)
AUDIO_EXTENSIONS = {".mp3", ".wav", ".m4a", ".flac", ".ogg", ".opus", ".mp4", ".mkv", ".webm", ".aac"}
BUCKET_SECONDS = 60
BEAM_SIZE = 5
SECONDS_PER_HOUR = 3600
SECONDS_PER_MINUTE = 60
def format_timestamp(total_seconds: float) -> str:
"""Render a whole-minute timestamp as ``HH:MM:00``.
Args:
total_seconds: Offset in seconds from the start of the audio.
Returns:
A zero-padded ``HH:MM:00`` string.
"""
hours = int(total_seconds // SECONDS_PER_HOUR)
minutes = int((total_seconds % SECONDS_PER_HOUR) // SECONDS_PER_MINUTE)
return f"{hours:02d}:{minutes:02d}:00"
def transcribe_file(model: WhisperModel, audio_path: Path, output_path: Path) -> None:
"""Transcribe one audio file and write the bucketed transcript to disk.
Args:
model: Loaded faster-whisper model.
audio_path: Source audio file.
output_path: Destination ``.txt`` path.
"""
logger.info("Transcribing %s", audio_path)
segments, info = model.transcribe(
str(audio_path),
language="en",
beam_size=BEAM_SIZE,
vad_filter=True,
)
logger.info("Duration %.1fs", info.duration)
buckets: dict[int, list[str]] = {}
for segment in segments:
bucket = int(segment.start // BUCKET_SECONDS)
buckets.setdefault(bucket, []).append(segment.text.strip())
lines = [f"[{format_timestamp(bucket * BUCKET_SECONDS)}] {' '.join(buckets[bucket])}" for bucket in sorted(buckets)]
output_path.write_text("\n\n".join(lines) + "\n", encoding="utf-8")
logger.info("Wrote %s", output_path)
def find_audio_files(input_directory: Path) -> list[Path]:
"""Collect every audio file under ``input_directory``.
Args:
input_directory: Directory to walk recursively.
Returns:
Sorted list of audio file paths.
"""
return sorted(
path for path in input_directory.rglob("*") if path.is_file() and path.suffix.lower() in AUDIO_EXTENSIONS
)
def configure_container_logger() -> None:
"""Configure logging for the container (stdout, INFO)."""
logging.basicConfig(
level=logging.INFO,
format="%(asctime)s %(levelname)s %(message)s",
)
def parse_arguments() -> argparse.Namespace:
"""Parse CLI arguments for the container entrypoint.
Returns:
Parsed argparse namespace.
"""
parser = argparse.ArgumentParser(description=__doc__)
parser.add_argument("--input", type=Path, default=Path("/audio"))
parser.add_argument("--output", type=Path, default=Path("/output"))
parser.add_argument("--model", default="large-v3")
parser.add_argument(
"--download-only",
action="store_true",
help="Download the model into the cache volume and exit without transcribing.",
)
return parser.parse_args()
def main() -> None:
"""Load the model, then either exit (download-only) or transcribe the directory."""
configure_container_logger()
arguments = parse_arguments()
logger.info("Loading model %s on CUDA", arguments.model)
model = WhisperModel(arguments.model, device="cuda", compute_type="float16")
if arguments.download_only:
logger.info("Model ready; exiting (download-only mode)")
return
arguments.output.mkdir(parents=True, exist_ok=True)
audio_files = find_audio_files(arguments.input)
if not audio_files:
logger.warning("No audio files found in %s", arguments.input)
return
logger.info("Found %d audio file(s)", len(audio_files))
for audio_path in audio_files:
relative = audio_path.relative_to(arguments.input)
output_path = arguments.output / relative.with_suffix(".txt")
output_path.parent.mkdir(parents=True, exist_ok=True)
if output_path.exists():
logger.info("Skip %s (already transcribed)", relative)
continue
transcribe_file(model, audio_path, output_path)
if __name__ == "__main__":
main()

View File

@@ -0,0 +1,167 @@
"""Build and run the whisper transcription docker container on demand.
The container is started fresh for each invocation and removed on exit
(``docker run --rm``). The model is cached in a named docker volume so
only the first run pays the download cost.
"""
from __future__ import annotations
import logging
import subprocess
from pathlib import Path
from typing import Annotated
import typer
from python.common import configure_logger
logger = logging.getLogger(__name__)
class Config:
"""Paths and names for the whisper-transcribe Docker workflow."""
image_tag = "whisper-transcribe:latest"
model_volume = "whisper-models"
repo_root = Path(__file__).resolve().parents[3]
dockerfile = Path(__file__).resolve().parent / "Dockerfile"
huggingface_cache = "/root/.cache/huggingface"
def run_docker(arguments: list[str]) -> None:
"""Run a docker subcommand, streaming output and raising on failure.
Args:
arguments: Arguments to pass to the ``docker`` binary.
Raises:
subprocess.CalledProcessError: If docker exits non-zero.
"""
logger.info("docker %s", " ".join(arguments))
subprocess.run(["docker", *arguments], check=True)
def build_image() -> None:
"""Build the whisper-transcribe image using the repo root as build context."""
logger.info("Building image %s", Config.image_tag)
run_docker(
[
"build",
"--tag",
Config.image_tag,
"--file",
str(Config.dockerfile),
str(Config.repo_root),
],
)
def model_cache_present(model: str) -> bool:
"""Check whether the given model is already downloaded in the cache volume.
Args:
model: faster-whisper model name (e.g. ``large-v3``).
Returns:
True if the HuggingFace cache directory for the model exists in the volume.
"""
cache_directory = f"hub/models--Systran--faster-whisper-{model}"
completed = subprocess.run(
[
"docker",
"run",
"--rm",
"--volume",
f"{Config.model_volume}:/cache",
"alpine",
"test",
"-d",
f"/cache/{cache_directory}",
],
check=False,
)
return completed.returncode == 0
def download_model(model: str) -> None:
"""Download the model into the cache volume and exit.
Args:
model: faster-whisper model name.
"""
logger.info("Downloading model %s into volume %s", model, Config.model_volume)
run_docker(
[
"run",
"--rm",
"--device=nvidia.com/gpu=all",
"--ipc=host",
"--volume",
f"{Config.model_volume}:{Config.huggingface_cache}",
Config.image_tag,
"--model",
model,
"--download-only",
],
)
def transcribe(input_directory: Path, output_directory: Path, model: str) -> None:
"""Run transcription on every audio file under ``input_directory``.
Args:
input_directory: Host path containing audio files (mounted read-only).
output_directory: Host path for ``.txt`` transcripts.
model: faster-whisper model name.
"""
logger.info("Transcribing %s -> %s (model=%s)", input_directory, output_directory, model)
run_docker(
[
"run",
"--rm",
"--device=nvidia.com/gpu=all",
"--ipc=host",
"--volume",
f"{input_directory}:/audio:ro",
"--volume",
f"{output_directory}:/output",
"--volume",
f"{Config.model_volume}:{Config.huggingface_cache}",
Config.image_tag,
"--model",
model,
],
)
def main(
input_directory: Annotated[Path, typer.Argument(help="Directory of audio files to transcribe.")],
output_directory: Annotated[Path, typer.Argument(help="Directory to write .txt transcripts to.")],
model: Annotated[str, typer.Option(help="faster-whisper model name.")] = "large-v3",
*,
force_download: Annotated[
bool,
typer.Option("--force-download", help="Re-download the model even if already cached."),
] = False,
) -> None:
"""Build the image, ensure the model is cached, then transcribe and stop."""
configure_logger()
resolved_input = input_directory.resolve(strict=True)
output_directory.mkdir(parents=True, exist_ok=True)
resolved_output = output_directory.resolve()
build_image()
if force_download or not model_cache_present(model):
download_model(model)
else:
logger.info("Model %s already cached in volume %s", model, Config.model_volume)
transcribe(resolved_input, resolved_output, model)
logger.info("Done. Container stopped.")
if __name__ == "__main__":
typer.run(main)

View File

@@ -1,8 +1,9 @@
{ inputs, pkgs, ... }:
{
imports = [
"${inputs.self}/users/richie"
"${inputs.self}/users/math"
"${inputs.self}/users/richie"
"${inputs.self}/users/steve"
"${inputs.self}/common/global"
"${inputs.self}/common/optional/docker.nix"
"${inputs.self}/common/optional/scanner.nix"
@@ -12,7 +13,6 @@
"${inputs.self}/common/optional/update.nix"
"${inputs.self}/common/optional/yubikey.nix"
"${inputs.self}/common/optional/zerotier.nix"
"${inputs.self}/common/optional/brain_substituter.nix"
"${inputs.self}/common/optional/nvidia.nix"
./hardware.nix
./syncthing.nix

View File

@@ -28,7 +28,6 @@
allowDiscards = true;
keyFileSize = 4096;
keyFile = "/dev/disk/by-id/usb-Samsung_Flash_Drive_FIT_0374620080067131-0:0";
fallbackToPassword = true;
};
};
kernelModules = [ "kvm-amd" ];

View File

@@ -42,11 +42,13 @@
"qwen3:8b"
"qwen3.5:27b"
"qwen3.5:35b"
"qwen3.6:35b"
"translategemma:12b"
"translategemma:27b"
"translategemma:4b"
"rinex20/translategemma3:12b"
];
models = "/zfs/models";
models = "/zfs/storage/models";
openFirewall = true;
};
}

View File

@@ -31,5 +31,15 @@
];
fsWatcherEnabled = true;
};
"recordings" = {
path = "/home/richie/recordings";
devices = [
"jeeves"
"phone"
"rhapsody-in-green"
];
fsWatcherEnabled = true;
};
};
}

View File

@@ -26,7 +26,6 @@
allowDiscards = true;
keyFileSize = 4096;
keyFile = "/dev/disk/by-id/usb-USB_SanDisk_3.2Gen1_03021630090925173333-0:0";
fallbackToPassword = true;
};
};
kernelModules = [ "kvm-intel" ];

View File

@@ -4,9 +4,10 @@ let
in
{
imports = [
"${inputs.self}/users/richie"
"${inputs.self}/users/math"
"${inputs.self}/users/dov"
"${inputs.self}/users/math"
"${inputs.self}/users/richie"
"${inputs.self}/users/steve"
"${inputs.self}/common/global"
"${inputs.self}/common/optional/docker.nix"
"${inputs.self}/common/optional/ssh_decrypt.nix"

View File

@@ -9,7 +9,6 @@ let
inherit device;
keyFileSize = 4096;
keyFile = "/dev/disk/by-id/usb-XIAO_USB_Drive_24587CE29074-0:0";
fallbackToPassword = true;
};
makeLuksSSD =
device:

View File

@@ -89,7 +89,16 @@ in
];
fsWatcherEnabled = true;
};
#
"recordings" = {
path = "/home/richie/recordings";
devices = [
"bob"
"phone"
"rhapsody-in-green"
];
fsWatcherEnabled = true;
};
# davids-server
"davids-backup1" = {
id = "8229p-8z3tm"; # cspell:disable-line
path = "${vars.syncthing}/davids_backups/1";

View File

@@ -24,11 +24,19 @@
hostId = "6404140d";
firewall = {
enable = true;
allowedTCPPorts = [ ];
allowedTCPPorts = [
8000
8080
];
};
networkmanager.enable = true;
};
programs.appimage = {
enable = true;
binfmt = true; # allows *.AppImage to be run directly
};
services = {
openssh.ports = [ 922 ];
flatpak.enable = true;

View File

@@ -55,6 +55,15 @@
];
fsWatcherEnabled = true;
};
"recordings" = {
path = "/home/richie/recordings";
devices = [
"bob"
"jeeves"
"phone"
];
fsWatcherEnabled = true;
};
"vault" = {
path = "/home/richie/vault";
devices = [

View File

@@ -1,6 +1,7 @@
{
programs.git = {
enable = true;
signing.format = null;
settings = {
user = {
email = "dov.kruger@gmail.com";

View File

@@ -1,6 +1,7 @@
{
programs.git = {
enable = true;
signing.format = null;
settings = {
user = {
email = "DumbPuppy208@gmail.com";

View File

@@ -1,6 +1,7 @@
{
programs.git = {
enable = true;
signing.format = null;
settings = {
user = {
email = "matthew.michal11@gmail.com";

View File

@@ -1,6 +1,7 @@
{
programs.git = {
enable = true;
signing.format = null;
settings = {
user = {
email = "Richie@tmmworkshop.com";

View File

@@ -22,9 +22,10 @@
chromium
# dev tools
claude-code
codex
gparted
jetbrains.datagrip
proxychains
opencode
proxychains
];
}

44
users/steve/default.nix Normal file
View File

@@ -0,0 +1,44 @@
{
pkgs,
config,
...
}:
let
ifTheyExist = groups: builtins.filter (group: builtins.hasAttr group config.users.groups) groups;
in
{
users = {
users.steve = {
isNormalUser = true;
shell = pkgs.zsh;
group = "steve";
openssh.authorizedKeys.keys = [
"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIJH03VzDbUhzfhvwD+OsYh6GobODYaI9jdNdzWQoqFsp matth@Jove" # cspell:disable-line
];
extraGroups = [
"audio"
"video"
"wheel"
"users"
]
++ ifTheyExist [
"dialout"
"docker"
"hass"
"libvirtd"
"networkmanager"
"plugdev"
"scanner"
"transmission"
"uaccess"
"wireshark"
];
uid = 1005;
};
groups.steve.gid = 1005;
};
home-manager.users.steve = import ./systems/${config.networking.hostName}.nix;
}

View File

@@ -0,0 +1,9 @@
{
imports = [
./direnv.nix
./git.nix
./zsh.nix
];
programs.starship.enable = true;
}

View File

@@ -0,0 +1,8 @@
{
programs.direnv = {
enable = true;
enableZshIntegration = true;
nix-direnv.enable = true;
};
}

View File

@@ -0,0 +1,15 @@
{
programs.git = {
enable = true;
signing.format = null;
settings = {
user = {
email = "matthew.michal11@gmail.com";
name = "Matthew Michal";
};
pull.rebase = true;
color.ui = true;
};
lfs.enable = true;
};
}

View File

@@ -0,0 +1,28 @@
{
programs.zsh = {
enable = true;
syntaxHighlighting.enable = true;
history.size = 10000;
oh-my-zsh = {
enable = true;
plugins = [
"git"
"docker"
"docker-compose"
"colored-man-pages"
"rust"
"systemd"
"tmux"
"ufw"
"z"
];
};
shellAliases = {
"lrt" = "eza --icons -lsnew";
"ls" = "eza";
"ll" = "eza --long --group";
"la" = "eza --all";
};
};
}

View File

@@ -0,0 +1,22 @@
{ config, ... }:
{
imports = [
./cli
./programs.nix
./ssh_config.nix
];
programs = {
home-manager.enable = true;
git.enable = true;
};
home = {
username = "steve";
homeDirectory = "/home/${config.home.username}";
stateVersion = "24.05";
sessionVariables = {
FLAKE = "$HOME/dotfiles";
};
};
}

View File

@@ -0,0 +1,57 @@
{ pkgs, ... }:
{
home.packages = with pkgs; [
# cli
bat
btop
eza
fd
ffmpegthumbnailer
fzf
git
gnupg
imagemagick
jq
ncdu
ouch
p7zip
poppler
rar
ripgrep
starship
tmux
unzip
yazi
zoxide
# system info
hwloc
lynis
pciutils
smartmontools
usbutils
# networking
iperf3
nmap
wget
# python
poetry
ruff
uv
# nodejs
nodejs
# Rust packages
trunk
wasm-pack
cargo-watch
cargo-generate
cargo-audit
cargo-update
# nix
nix-init
nix-output-monitor
nix-prefetch
nix-tree
nixfmt
treefmt
];
}

View File

@@ -0,0 +1,6 @@
{
programs.ssh = {
enable = true;
enableDefaultConfig = false;
};
}

View File

@@ -0,0 +1,5 @@
{
imports = [
../home/global.nix
];
}

View File

@@ -0,0 +1,5 @@
{
imports = [
../home/global.nix
];
}