Compare commits
1 commit
release-25
...
feature/zf
| Author | SHA1 | Date | |
|---|---|---|---|
| 951182f6df |
66 changed files with 549 additions and 2130 deletions
|
|
@ -27,7 +27,7 @@ Add this repo to your flake inputs:
|
|||
inputs.synix.url = "git+https://git.sid.ovh/sid/synix.git";
|
||||
```
|
||||
|
||||
See the [documentation](https://doc.sid.ovh) for a full setup guide.
|
||||
See the [documentation](https://doc.sid.ovh/synix) for a full setup guide.
|
||||
|
||||
## Templates
|
||||
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@
|
|||
home-manager,
|
||||
hostname,
|
||||
nix,
|
||||
nixos-rebuild-ng,
|
||||
nixos-rebuild,
|
||||
...
|
||||
}:
|
||||
|
||||
|
|
@ -25,6 +25,6 @@ writeShellApplication {
|
|||
home-manager
|
||||
hostname
|
||||
nix
|
||||
nixos-rebuild-ng
|
||||
nixos-rebuild
|
||||
];
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,20 +1,15 @@
|
|||
# NixOS and standalone Home Manager rebuild script
|
||||
|
||||
# Defaults
|
||||
FLAKE_PATH="${REBUILD_FLAKE_PATH:-${FLAKE_PATH:-$HOME/.config/nixos}}" # Default flake path
|
||||
USER="${REBUILD_USER:-$(whoami)}" # Default username
|
||||
HOST="${REBUILD_HOST:-$(hostname)}" # Default hostname
|
||||
BUILD_HOST="${REBUILD_BUILD_HOST:-}" # Default build host
|
||||
TARGET_HOST="${REBUILD_TARGET_HOST:-}" # Default target host
|
||||
UPDATE="${REBUILD_UPDATE:-0}" # Default to not update
|
||||
UPDATE_INPUTS="${REBUILD_UPDATE_INPUTS:-}" # Default list of inputs
|
||||
ROLLBACK="${REBUILD_ROLLBACK:-0}" # Default to not rollback
|
||||
SHOW_TRACE="${REBUILD_SHOW_TRACE:-0}" # Default to not show trace
|
||||
|
||||
# Output functions
|
||||
_status() { echo -e "\033[0;34m> $1\033[0m"; }
|
||||
success() { echo -e "\033[0;32m$1\033[0m"; }
|
||||
error() { echo -e "\033[0;31mError: $1\033[0m" >&2; exit 1; }
|
||||
FLAKE_PATH="$HOME/.config/nixos" # Default flake path
|
||||
HOME_USER="$(whoami)" # Default username. Used to identify the Home Manager configuration
|
||||
NIXOS_HOST="$(hostname)" # Default hostname. Used to identify the NixOS and Home Manager configuration
|
||||
BUILD_HOST="" # Default build host. Empty means localhost
|
||||
TARGET_HOST="" # Default target host. Empty means localhost
|
||||
UPDATE=0 # Default to not update flake repositories
|
||||
UPDATE_INPUTS="" # Default list of inputs to update. Empty means all
|
||||
ROLLBACK=0 # Default to not rollback
|
||||
SHOW_TRACE=0 # Default to not show detailed error messages
|
||||
|
||||
# Function to display the help message
|
||||
Help() {
|
||||
|
|
@ -28,7 +23,7 @@ Help() {
|
|||
echo " help Show this help message"
|
||||
echo
|
||||
echo "Options (for NixOS and Home Manager):"
|
||||
echo " -H, --host <host> Specify the hostname (as in 'nixosConfiguraions.<host>'). Default: $HOST"
|
||||
echo " -H, --host <host> Specify the hostname (as in 'nixosConfiguraions.<host>'). Default: $NIXOS_HOST"
|
||||
echo " -p, --path <path> Set the path to the flake directory. Default: $FLAKE_PATH"
|
||||
echo " -U, --update [inputs] Update all flake inputs. Optionally provide comma-separated list of inputs to update instead."
|
||||
echo " -r, --rollback Don't build the new configuration, but use the previous generation instead"
|
||||
|
|
@ -39,50 +34,47 @@ Help() {
|
|||
echo " -T, --target-host <user@example.com> Deploy the configuration to a remote host via SSH. If '--host' is specified, it will be used as the target host."
|
||||
echo
|
||||
echo "Home Manager only options:"
|
||||
echo " -u, --user <user> Specify the username (as in 'homeConfigurations.<user>@<host>'). Default: $USER"
|
||||
echo " -u, --user <user> Specify the username (as in 'homeConfigurations.<user>@<host>'). Default: $HOME_USER"
|
||||
}
|
||||
|
||||
# Function to handle errors
|
||||
error() {
|
||||
echo "Error: $1"
|
||||
exit 1
|
||||
}
|
||||
|
||||
# Function to rebuild NixOS configuration
|
||||
Rebuild_nixos() {
|
||||
local FLAKE="$FLAKE_PATH#$HOST"
|
||||
local FLAKE="$FLAKE_PATH#$NIXOS_HOST"
|
||||
|
||||
# Construct rebuild command
|
||||
local CMD=("nixos-rebuild" "switch" "--sudo")
|
||||
[[ -n "$TARGET_HOST" || -n "$BUILD_HOST" ]] && CMD+=("--ask-sudo-password")
|
||||
CMD+=("--flake" "$FLAKE")
|
||||
[ "$ROLLBACK" = 1 ] && CMD+=("--rollback")
|
||||
[ "$SHOW_TRACE" = 1 ] && CMD+=("--show-trace")
|
||||
[ -n "$BUILD_HOST" ] && CMD+=("--build-host" "$BUILD_HOST")
|
||||
if [ "$HOST" != "$(hostname)" ] && [ -z "$TARGET_HOST" ]; then
|
||||
TARGET_HOST="$HOST"
|
||||
_status "Using '$TARGET_HOST' as target host."
|
||||
if [ "$NIXOS_HOST" != "$(hostname)" ] && [ -z "$TARGET_HOST" ]; then
|
||||
TARGET_HOST="$NIXOS_HOST"
|
||||
echo "Using '$TARGET_HOST' as target host."
|
||||
fi
|
||||
[ -n "$TARGET_HOST" ] && CMD+=("--target-host" "$TARGET_HOST")
|
||||
[[ -n "$TARGET_HOST" || -n "$BUILD_HOST" ]] && CMD+=("--ask-sudo-password")
|
||||
|
||||
# Build config first so we can diff it
|
||||
local BUILD_CMD=("nixos-rebuild" "build" "--no-build-output" "--flake" "$FLAKE")
|
||||
[ "$SHOW_TRACE" = 1 ] && BUILD_CMD+=("--show-trace")
|
||||
[ -n "$BUILD_HOST" ] && BUILD_CMD+=("--build-host" "$BUILD_HOST")
|
||||
|
||||
# Rebuild NixOS configuration
|
||||
if [ "$ROLLBACK" = 0 ]; then
|
||||
_status "Building NixOS configuration '$FLAKE'..."
|
||||
_status "Executing command: ${BUILD_CMD[*]}"
|
||||
"${BUILD_CMD[@]}" || error "NixOS build failed"
|
||||
|
||||
_status "Switching to new NixOS configuration"
|
||||
echo "Rebuilding NixOS configuration '$FLAKE'..."
|
||||
else
|
||||
_status "Rolling back to last NixOS generation"
|
||||
echo "Rolling back to last NixOS generation..."
|
||||
fi
|
||||
|
||||
sudo -v
|
||||
_status "Executing command: ${CMD[*]}"
|
||||
echo "Executing command: ${CMD[*]}"
|
||||
"${CMD[@]}" || error "NixOS rebuild failed"
|
||||
success "NixOS rebuild completed successfully."
|
||||
echo "NixOS rebuild completed successfully."
|
||||
}
|
||||
|
||||
# Function to rebuild Home Manager configuration
|
||||
Rebuild_home() {
|
||||
local FLAKE="$FLAKE_PATH#$USER@$HOST"
|
||||
local FLAKE="$FLAKE_PATH#$HOME_USER@$NIXOS_HOST"
|
||||
|
||||
if [ -n "$BUILD_HOST" ] || [ -n "$TARGET_HOST" ]; then
|
||||
error "Remote building is not supported for Home Manager."
|
||||
|
|
@ -99,27 +91,21 @@ Rebuild_home() {
|
|||
[ "$SHOW_TRACE" = 1 ] && CMD+=("--show-trace")
|
||||
fi
|
||||
|
||||
# Build config first so we can diff it
|
||||
# Rebuild Home Manager configuration
|
||||
if [ "$ROLLBACK" = 0 ]; then
|
||||
local BUILD_CMD=("home-manager" "build" "--no-out-link" "--flake" "$FLAKE")
|
||||
[ "$SHOW_TRACE" = 1 ] && BUILD_CMD+=("--show-trace")
|
||||
_status "Building Home Manager configuration '$FLAKE'..."
|
||||
_status "Executing command: ${BUILD_CMD[*]}"
|
||||
"${BUILD_CMD[@]}" || error "Home Manager build failed"
|
||||
|
||||
_status "Switching to new Home Manager configuration"
|
||||
echo "Rebuilding Home Manager configuration '$FLAKE'..."
|
||||
else
|
||||
_status "Rolling back to last Home Manager generation"
|
||||
echo "Rolling back to last Home Manager generation..."
|
||||
fi
|
||||
|
||||
_status "Executing command: ${CMD[*]}"
|
||||
echo "Executing command: ${CMD[*]}"
|
||||
"${CMD[@]}" || error "Home Manager rebuild failed"
|
||||
success "Home Manager rebuild completed successfully."
|
||||
echo "Home Manager rebuild completed successfully."
|
||||
}
|
||||
|
||||
# Function to update flake repositories
|
||||
# Function to Update flake repositories
|
||||
Update() {
|
||||
_status "Updating flake inputs..."
|
||||
echo "Updating flake inputs..."
|
||||
|
||||
# Construct update command as an array
|
||||
local CMD=("nix" "flake" "update" "--flake" "$FLAKE_PATH")
|
||||
|
|
@ -131,18 +117,17 @@ Update() {
|
|||
done
|
||||
fi
|
||||
|
||||
_status "Executing command: ${CMD[*]}"
|
||||
echo "Executing command: ${CMD[*]}"
|
||||
"${CMD[@]}" || error "Failed to update flake repositories"
|
||||
success "Flake repositories updated successfully."
|
||||
echo "Flake repositories updated successfully."
|
||||
}
|
||||
|
||||
# Parse command-line options
|
||||
if [[ -z "${1:-}" ]]; then
|
||||
echo -e "\033[0;31mError: No command specified. Printing help page.\033[0m" >&2
|
||||
echo "Error: No command specified. Printing help page."
|
||||
Help
|
||||
exit 1
|
||||
fi
|
||||
|
||||
COMMAND=$1
|
||||
shift
|
||||
|
||||
|
|
@ -156,7 +141,7 @@ while [ $# -gt 0 ]; do
|
|||
case "${1:-}" in
|
||||
-H|--host)
|
||||
if [ -n "${2:-}" ]; then
|
||||
HOST="$2"
|
||||
NIXOS_HOST="$2"
|
||||
shift 2
|
||||
else
|
||||
error "-H|--host option requires an argument"
|
||||
|
|
@ -164,7 +149,7 @@ while [ $# -gt 0 ]; do
|
|||
;;
|
||||
-u|--user)
|
||||
if [ -n "${2:-}" ]; then
|
||||
USER="$2"
|
||||
HOME_USER="$2"
|
||||
shift 2
|
||||
else
|
||||
error "-u|--user option requires an argument"
|
||||
|
|
@ -213,7 +198,9 @@ while [ $# -gt 0 ]; do
|
|||
fi
|
||||
;;
|
||||
*)
|
||||
error "Unknown option '$1'"
|
||||
echo "Error: Unknown option '$1'"
|
||||
Help
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
|
@ -240,10 +227,10 @@ fi
|
|||
[ "$UPDATE" = 1 ] && Update
|
||||
|
||||
case "$COMMAND" in
|
||||
nixos|os)
|
||||
nixos)
|
||||
Rebuild_nixos
|
||||
;;
|
||||
home|hm)
|
||||
home)
|
||||
Rebuild_home
|
||||
;;
|
||||
all)
|
||||
|
|
@ -251,6 +238,9 @@ case "$COMMAND" in
|
|||
Rebuild_home
|
||||
;;
|
||||
*)
|
||||
error "Unknown command '$COMMAND'"
|
||||
echo "Error: Unknown command '$COMMAND'"
|
||||
echo "Printing help page:"
|
||||
Help
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@ Provide the following entries to your `secrets.yaml`:
|
|||
```yaml
|
||||
headplane:
|
||||
cookie_secret: abc123
|
||||
api_key: abc123
|
||||
agent_pre_authkey: abc123
|
||||
```
|
||||
|
||||
Generate your cookie secret with:
|
||||
|
|
@ -28,7 +28,7 @@ Generate your cookie secret with:
|
|||
nix-shell -p openssl --run "openssl rand -hex 16"
|
||||
```
|
||||
|
||||
Generate your agent `api_key` with:
|
||||
Generate your agent pre-authkey with:
|
||||
|
||||
```bash
|
||||
sudo headscale users create headplane-agent
|
||||
|
|
|
|||
36
docs/modules/nixos/tailscale.md
Normal file
36
docs/modules/nixos/tailscale.md
Normal file
|
|
@ -0,0 +1,36 @@
|
|||
# Tailscale
|
||||
|
||||
Private WireGuard networks made easy.
|
||||
|
||||
View the [*synix* NixOS module on Forgejo](https://git.sid.ovh/sid/synix/tree/master/modules/nixos/tailscale).
|
||||
|
||||
## References
|
||||
|
||||
- [Website](https://tailscale.com/)
|
||||
- [GitHub](https://github.com/tailscale/tailscale)
|
||||
- [Documents](https://tailscale.com/kb/1017/install)
|
||||
|
||||
## Sops
|
||||
|
||||
Provide the following entries to your `secrets.yaml`:
|
||||
|
||||
> Replace `abc123` with your actual secrets
|
||||
|
||||
```yaml
|
||||
tailscale:
|
||||
auth-key: abc123
|
||||
```
|
||||
|
||||
## Config
|
||||
|
||||
```nix
|
||||
{
|
||||
imports = [ inputs.synix.nixosModules.tailscale ];
|
||||
|
||||
services.tailscale = {
|
||||
enable = true;
|
||||
enableSSH = true;
|
||||
loginServer = "<your-headscale-instance>";
|
||||
};
|
||||
}
|
||||
```
|
||||
36
flake.lock
generated
36
flake.lock
generated
|
|
@ -202,11 +202,11 @@
|
|||
},
|
||||
"flake-schemas": {
|
||||
"locked": {
|
||||
"lastModified": 1776384880,
|
||||
"narHash": "sha256-28Cg9HI/IwFHUm5fZyMEGCQ94L3Il6K4OfHeRf0b+Zw=",
|
||||
"lastModified": 1770913512,
|
||||
"narHash": "sha256-jRC1qRoRCrMjDalVfUMHFlKSkkA2q0RZWTDW0LsquoA=",
|
||||
"owner": "DeterminateSystems",
|
||||
"repo": "flake-schemas",
|
||||
"rev": "b852751d29c6e09919f25c1e10754646bdc181c9",
|
||||
"rev": "3c464b0e09cb44c6e073c41dd1d834980c3e0b24",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
|
|
@ -258,11 +258,11 @@
|
|||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1776796298,
|
||||
"narHash": "sha256-PcRvlWayisPSjd0UcRQbhG8Oqw78AcPE6x872cPRHN8=",
|
||||
"lastModified": 1772024342,
|
||||
"narHash": "sha256-+eXlIc4/7dE6EcPs9a2DaSY3fTA9AE526hGqkNID3Wg=",
|
||||
"owner": "cachix",
|
||||
"repo": "git-hooks.nix",
|
||||
"rev": "3cfd774b0a530725a077e17354fbdb87ea1c4aad",
|
||||
"rev": "6e34e97ed9788b17796ee43ccdbaf871a5c2b476",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
|
|
@ -349,11 +349,11 @@
|
|||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1777851538,
|
||||
"narHash": "sha256-Gp8qwTEYNoy2yvmErVGlvLOQvrtEECCAKbonW7VJef8=",
|
||||
"lastModified": 1772020340,
|
||||
"narHash": "sha256-aqBl3GNpCadMoJ/hVkWTijM1Aeilc278MjM+LA3jK6g=",
|
||||
"owner": "nix-community",
|
||||
"repo": "home-manager",
|
||||
"rev": "cc09c0f9b7eaa95c2d9827338a5eb03d32505ca5",
|
||||
"rev": "36e38ca0d9afe4c55405fdf22179a5212243eecc",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
|
|
@ -465,11 +465,11 @@
|
|||
},
|
||||
"nixpkgs_2": {
|
||||
"locked": {
|
||||
"lastModified": 1777673416,
|
||||
"narHash": "sha256-5c2POKPOjU40Kh0MirOdScBLG0bu9TAuPYAtPRNZMBs=",
|
||||
"lastModified": 1771903837,
|
||||
"narHash": "sha256-sdaqdnsQCv3iifzxwB22tUwN/fSHoN7j2myFW5EIkGk=",
|
||||
"owner": "nixos",
|
||||
"repo": "nixpkgs",
|
||||
"rev": "26ef669cffa904b6f6832ab57b77892a37c1a671",
|
||||
"rev": "e764fc9a405871f1f6ca3d1394fb422e0a0c3951",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
|
|
@ -511,11 +511,11 @@
|
|||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1777906128,
|
||||
"narHash": "sha256-ei9g+4pCXhacUwnYuljs9v75hwfTqnfU+J6s6s8hfvc=",
|
||||
"lastModified": 1772140017,
|
||||
"narHash": "sha256-wFUc9tn5Ik11oL009BkVnj4NxsY63UbZjhOyEqCsIQE=",
|
||||
"owner": "nix-community",
|
||||
"repo": "NUR",
|
||||
"rev": "c278c296b010e2a32838c8d4539a2d72c1686d4d",
|
||||
"rev": "be0fea0af0e8cfadb3995dd7bb3a167bc012e935",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
|
|
@ -605,11 +605,11 @@
|
|||
"tinted-zed": "tinted-zed"
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1777581180,
|
||||
"narHash": "sha256-JcDBTZkkz68WlZKYDoD+MZG8b3dnIJXqMvyuVx3Wkdg=",
|
||||
"lastModified": 1771788390,
|
||||
"narHash": "sha256-RzBpBwn93GWxLjacTte+ngwwg0L/BVOg4G/sSIeK3Rw=",
|
||||
"owner": "nix-community",
|
||||
"repo": "stylix",
|
||||
"rev": "a2538cd28ae2140ffce9cee9108b8d569a9c4fed",
|
||||
"rev": "ebb238f14d6f930068be4718472da3105fd5d3bf",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
|
|
|
|||
16
flake.nix
16
flake.nix
|
|
@ -219,9 +219,17 @@
|
|||
};
|
||||
in
|
||||
testPkgs.testers.runNixOSTest ./tests/run/synapse.nix;
|
||||
open-webui-oci-test = pkgs.testers.runNixOSTest ./tests/run/open-webui-oci.nix;
|
||||
# librechat-oci-test = pkgs.testers.runNixOSTest ./tests/run/librechat-oci.nix; # FIXME: unable to copy from source docker://quay.io/mongo:7.0
|
||||
|
||||
# NOTE: disabled for now since the test takes too long to execute
|
||||
# open-webui-oci-test =
|
||||
# let
|
||||
# testPkgs = import nixpkgs {
|
||||
# inherit system;
|
||||
# };
|
||||
# in
|
||||
# testPkgs.testers.runNixOSTest ./tests/run/open-webui-oci.nix;
|
||||
}
|
||||
|
||||
);
|
||||
|
||||
hydraJobs = {
|
||||
|
|
@ -281,10 +289,6 @@
|
|||
path = ./templates/dev/rs-hello;
|
||||
description = "Rust hello world template.";
|
||||
};
|
||||
stm32-blink = {
|
||||
path = ./templates/dev/stm32-blink;
|
||||
description = "STM32G4 blink template with libopencm3.";
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -58,6 +58,7 @@ nav:
|
|||
- radicale: modules/nixos/radicale.md
|
||||
- rss-bridge: modules/nixos/rss-bridge.md
|
||||
- sops: modules/nixos/sops.md
|
||||
- tailscale: modules/nixos/tailscale.md
|
||||
- virtualisation: modules/nixos/virtualisation.md
|
||||
- webPage: modules/nixos/webpage.md
|
||||
- Home Manager:
|
||||
|
|
|
|||
|
|
@ -1,46 +0,0 @@
|
|||
{
|
||||
inputs,
|
||||
config,
|
||||
lib,
|
||||
pkgs,
|
||||
...
|
||||
}:
|
||||
|
||||
let
|
||||
cfg = config.wayland.windowManager.hyprland;
|
||||
app = cfg.applications.password-manager.default;
|
||||
|
||||
inherit (lib) mkDefault mkIf;
|
||||
in
|
||||
{
|
||||
imports = [ ../../../rofi-rbw ];
|
||||
|
||||
config = mkIf (cfg.enable && app == "rofi-rbw") {
|
||||
programs.rbw = {
|
||||
enable = true;
|
||||
settings = {
|
||||
# email = "you@example.tld"; # You have to set this in your config
|
||||
pinentry = mkDefault pkgs.pinentry-gnome3;
|
||||
lock_timeout = mkDefault 3600;
|
||||
};
|
||||
};
|
||||
|
||||
programs.rofi-rbw = {
|
||||
enable = true;
|
||||
package = mkDefault pkgs.rofi-rbw-wayland;
|
||||
settings = {
|
||||
selector = mkDefault "bemenu";
|
||||
selector-args = mkDefault "-i -l 20";
|
||||
action = mkDefault "copy";
|
||||
typing-key-delay = mkDefault 0;
|
||||
};
|
||||
};
|
||||
|
||||
programs.librewolf = mkIf config.programs.librewolf.enable {
|
||||
profiles.default.extensions.packages =
|
||||
with inputs.nur.legacyPackages."${pkgs.stdenv.hostPlatform.system}".repos.rycee.firefox-addons; [
|
||||
bitwarden
|
||||
];
|
||||
};
|
||||
};
|
||||
}
|
||||
|
|
@ -56,10 +56,8 @@ let
|
|||
in
|
||||
{
|
||||
imports = [
|
||||
./bitwarden
|
||||
./bemenu
|
||||
./dmenu-bluetooth
|
||||
./dunst-toggle
|
||||
./element-desktop
|
||||
./feh
|
||||
./kitty
|
||||
|
|
@ -137,11 +135,6 @@ in
|
|||
bind = [ "$mod SHIFT, m, exec, ${terminal} -T ${musicplayer} -e ${musicplayer}" ];
|
||||
};
|
||||
|
||||
notifications = mkAppAttrs {
|
||||
default = "dunst-toggle";
|
||||
bind = [ "$mod, Backspace, exec, ${notifications}" ];
|
||||
};
|
||||
|
||||
networksettings = mkAppAttrs {
|
||||
default = "networkmanager_dmenu";
|
||||
bind = [ "$mod SHIFT, n, exec, ${networksettings}" ];
|
||||
|
|
|
|||
|
|
@ -1,18 +0,0 @@
|
|||
{
|
||||
config,
|
||||
lib,
|
||||
pkgs,
|
||||
...
|
||||
}:
|
||||
|
||||
let
|
||||
cfg = config.wayland.windowManager.hyprland;
|
||||
app = cfg.applications.notifications.default;
|
||||
|
||||
inherit (lib) mkIf;
|
||||
in
|
||||
{
|
||||
config = mkIf (cfg.enable && app == "dunst-toggle") {
|
||||
home.packages = [ (import ./dunst-toggle.nix { inherit config pkgs; }) ];
|
||||
};
|
||||
}
|
||||
|
|
@ -1,11 +0,0 @@
|
|||
{ config, pkgs, ... }:
|
||||
|
||||
let
|
||||
dunst = "${pkgs.dunst}/bin/dunstctl";
|
||||
pkill = "${pkgs.procps}/bin/pkill";
|
||||
signal = "${toString config.programs.waybar.settings.mainBar."custom/notifications".signal}";
|
||||
in
|
||||
(pkgs.writeShellScriptBin "dunst-toggle" ''
|
||||
${dunst} set-paused toggle
|
||||
${pkill} -RTMIN+${signal} waybar
|
||||
'')
|
||||
|
|
@ -3,30 +3,15 @@
|
|||
let
|
||||
cfg = config.wayland.windowManager.hyprland;
|
||||
|
||||
nonCenterFloatingClasses = [
|
||||
"Gimp"
|
||||
"steam"
|
||||
"KiCad"
|
||||
];
|
||||
|
||||
nonCenterFloatingClassesRegex = concatStringsSep "|" nonCenterFloatingClasses;
|
||||
|
||||
inherit (builtins) concatStringsSep toString;
|
||||
inherit (builtins) toString;
|
||||
inherit (lib) mkDefault;
|
||||
in
|
||||
{
|
||||
# Do not add binds here. Use `./binds/default.nix` instead.
|
||||
"$mod" = cfg.modifier;
|
||||
|
||||
exec-once = [
|
||||
"dbus-update-activation-environment --systemd WAYLAND_DISPLAY XDG_CURRENT_DESKTOP" # dbus package comes from NixOS module option `services.dbus.dbusPackage` [1]
|
||||
"gnome-keyring-daemon --start --components=secrets" # gnome-keyring package comes from NixOS module `services.gnome.gnome-keyring` [1]
|
||||
];
|
||||
# 1: see Hyprland NixOS module
|
||||
|
||||
windowrule = [
|
||||
# "float, class:^(${nonCenterFloatingClassesRegex})$"
|
||||
"center, floating:1, class:^(?!.*(${nonCenterFloatingClassesRegex})).*$"
|
||||
"center, floating:1, not class:^(Gimp)$, not class:^(steam)$"
|
||||
"float, title:^(Open|Save) Files?$"
|
||||
"noborder, onworkspace:w[t1]"
|
||||
"bordersize ${toString cfg.settings.general.border_size}, floating:1"
|
||||
|
|
@ -39,12 +24,6 @@ in
|
|||
"noblur, class:^(xwaylandvideobridge)$"
|
||||
];
|
||||
|
||||
gesture = [
|
||||
"3, horizontal, workspace"
|
||||
"3, up, dispatcher, exec, bemenu-run" # TODO: move to hyprland.applications
|
||||
"4, swipe, move"
|
||||
];
|
||||
|
||||
# Layouts
|
||||
general.layout = mkDefault "master";
|
||||
master = {
|
||||
|
|
|
|||
|
|
@ -1,71 +1,79 @@
|
|||
[
|
||||
# cursor navigation
|
||||
{
|
||||
options.desc = "scroll down, recenter";
|
||||
# scroll down, recenter
|
||||
key = "<C-d>";
|
||||
action = "<C-d>zz";
|
||||
mode = "n";
|
||||
}
|
||||
{
|
||||
options.desc = "scroll up, recenter";
|
||||
# scroll up, recenter
|
||||
key = "<C-u>";
|
||||
action = "<C-u>zz";
|
||||
mode = "n";
|
||||
}
|
||||
|
||||
# searching
|
||||
{
|
||||
options.desc = "center cursor after search next";
|
||||
# center cursor after search next
|
||||
key = "n";
|
||||
action = "nzzzv";
|
||||
mode = "n";
|
||||
}
|
||||
{
|
||||
options.desc = "center cursor after search previous";
|
||||
# center cursor after search previous
|
||||
key = "N";
|
||||
action = "Nzzzv";
|
||||
mode = "n";
|
||||
}
|
||||
{
|
||||
options.desc = "ex command";
|
||||
# ex command
|
||||
key = "<leader>pv";
|
||||
action = "<cmd>Ex<CR>";
|
||||
mode = "n";
|
||||
}
|
||||
|
||||
# search and replace
|
||||
{
|
||||
options.desc = "search and replace word under cursor";
|
||||
# search and replace word under cursor
|
||||
key = "<leader>s";
|
||||
action = ":%s/<C-r><C-w>/<C-r><C-w>/gI<Left><Left><Left>";
|
||||
mode = "n";
|
||||
}
|
||||
# search and replace selected text
|
||||
{
|
||||
key = "<leader>s";
|
||||
action = "y:%s/<C-r>0/<C-r>0/gI<Left><Left><Left>";
|
||||
mode = "v";
|
||||
}
|
||||
|
||||
# clipboard operations
|
||||
{
|
||||
options.desc = "copy to system clipboard in visual mode";
|
||||
# copy to system clipboard in visual mode
|
||||
key = "<C-c>";
|
||||
action = ''"+y '';
|
||||
mode = "v";
|
||||
}
|
||||
{
|
||||
options.desc = "paste from system clipboard in visual mode";
|
||||
# paste from system clipboard in visual mode
|
||||
key = "<C-v>";
|
||||
action = ''"+p '';
|
||||
mode = "v";
|
||||
}
|
||||
{
|
||||
options.desc = "yank to system clipboard";
|
||||
# yank to system clipboard
|
||||
key = "<leader>Y";
|
||||
action = "+Y";
|
||||
mode = "n";
|
||||
}
|
||||
{
|
||||
options.desc = "replace selected text with clipboard content";
|
||||
# replace selected text with clipboard content
|
||||
key = "<leader>p";
|
||||
action = "_dP";
|
||||
mode = "x";
|
||||
}
|
||||
{
|
||||
options.desc = "delete without copying to clipboard";
|
||||
# delete without copying to clipboard
|
||||
key = "<leader>d";
|
||||
action = "_d";
|
||||
mode = [
|
||||
|
|
@ -73,184 +81,267 @@
|
|||
"v"
|
||||
];
|
||||
}
|
||||
|
||||
# line operations
|
||||
{
|
||||
options.desc = "move lines down in visual mode";
|
||||
# move lines down in visual mode
|
||||
key = "J";
|
||||
action = ":m '>+1<CR>gv=gv";
|
||||
mode = "v";
|
||||
}
|
||||
{
|
||||
options.desc = "move lines up in visual mode";
|
||||
# move lines up in visual mode
|
||||
key = "K";
|
||||
action = ":m '<-2<CR>gv=gv";
|
||||
mode = "v";
|
||||
}
|
||||
{
|
||||
options.desc = "join lines";
|
||||
# join lines
|
||||
key = "J";
|
||||
action = "mzJ`z";
|
||||
mode = "n";
|
||||
}
|
||||
|
||||
# quickfix
|
||||
{
|
||||
options.desc = "Run make command";
|
||||
# Run make command
|
||||
key = "<leader>m";
|
||||
action = "<cmd>:make<CR>";
|
||||
mode = "n";
|
||||
}
|
||||
{
|
||||
options.desc = "previous quickfix item";
|
||||
# previous quickfix item
|
||||
key = "<C-A-J>";
|
||||
action = "<cmd>cprev<CR>zz";
|
||||
mode = "n";
|
||||
}
|
||||
{
|
||||
options.desc = "next quickfix item";
|
||||
# next quickfix item
|
||||
key = "<C-A-K>";
|
||||
action = "<cmd>cnext<CR>zz";
|
||||
mode = "n";
|
||||
}
|
||||
|
||||
# location list navigation
|
||||
{
|
||||
options.desc = "previous location list item";
|
||||
# previous location list item
|
||||
key = "<leader>j";
|
||||
action = "<cmd>lprev<CR>zz";
|
||||
mode = "n";
|
||||
}
|
||||
{
|
||||
options.desc = "next location list item";
|
||||
# next location list item
|
||||
key = "<leader>k";
|
||||
action = "<cmd>lnext<CR>zz";
|
||||
mode = "n";
|
||||
}
|
||||
|
||||
# disabling keys
|
||||
{
|
||||
options.desc = "disable the 'Q' key";
|
||||
# disable the 'Q' key
|
||||
key = "Q";
|
||||
action = "<nop>";
|
||||
mode = "n";
|
||||
}
|
||||
|
||||
# text selection
|
||||
{
|
||||
options.desc = "select whole buffer";
|
||||
# select whole buffer
|
||||
key = "<C-a>";
|
||||
action = "ggVG";
|
||||
mode = "n";
|
||||
}
|
||||
|
||||
# window operations
|
||||
{
|
||||
options.desc = "focus next window";
|
||||
# focus next window
|
||||
key = "<C-j>";
|
||||
action = ":wincmd W<CR>";
|
||||
options = {
|
||||
noremap = true;
|
||||
silent = true;
|
||||
};
|
||||
mode = "n";
|
||||
}
|
||||
{
|
||||
options.desc = "focus next window";
|
||||
key = "<Tab>";
|
||||
action = ":wincmd W<CR>";
|
||||
mode = "n";
|
||||
}
|
||||
{
|
||||
options.desc = "focus previous window";
|
||||
# focus previous window
|
||||
key = "<C-k>";
|
||||
action = ":wincmd w<CR>";
|
||||
options = {
|
||||
noremap = true;
|
||||
silent = true;
|
||||
};
|
||||
mode = "n";
|
||||
}
|
||||
|
||||
# window size adjustments
|
||||
{
|
||||
options.desc = "focus previous window";
|
||||
key = "<S-Tab>";
|
||||
action = ":wincmd w<CR>";
|
||||
mode = "n";
|
||||
}
|
||||
{
|
||||
options.desc = "increase window width";
|
||||
# increase window width
|
||||
key = "<C-l>";
|
||||
action = ":vertical resize +5<CR>";
|
||||
options = {
|
||||
noremap = true;
|
||||
silent = true;
|
||||
};
|
||||
mode = "n";
|
||||
}
|
||||
{
|
||||
options.desc = "decrease window width";
|
||||
# decrease window width
|
||||
key = "<C-h>";
|
||||
action = ":vertical resize -5<CR>";
|
||||
options = {
|
||||
noremap = true;
|
||||
silent = true;
|
||||
};
|
||||
mode = "n";
|
||||
}
|
||||
|
||||
# window closing and opening
|
||||
{
|
||||
options.desc = "close current window";
|
||||
# close current window
|
||||
key = "<leader-S>c";
|
||||
action = ":q<CR>";
|
||||
options = {
|
||||
noremap = true;
|
||||
silent = true;
|
||||
};
|
||||
mode = "n";
|
||||
}
|
||||
{
|
||||
options.desc = "new vertical split at $HOME";
|
||||
# new vertical split at $HOME
|
||||
key = "<leader>n";
|
||||
action = ":vsp $HOME<CR>";
|
||||
options = {
|
||||
noremap = true;
|
||||
silent = true;
|
||||
};
|
||||
mode = "n";
|
||||
}
|
||||
|
||||
# window split orientation toggling
|
||||
{
|
||||
options.desc = "toggle split orientation";
|
||||
# toggle split orientation
|
||||
key = "<leader>t";
|
||||
action = ":wincmd T<CR>";
|
||||
options = {
|
||||
noremap = true;
|
||||
silent = true;
|
||||
};
|
||||
mode = "n";
|
||||
}
|
||||
|
||||
# spell checking
|
||||
{
|
||||
options.desc = "toggle spell checking";
|
||||
# toggle spell checking
|
||||
key = "<leader>ss";
|
||||
action = ":setlocal spell!<CR>";
|
||||
options = {
|
||||
noremap = true;
|
||||
silent = true;
|
||||
};
|
||||
mode = "n";
|
||||
}
|
||||
{
|
||||
options.desc = "switch to english spell checking";
|
||||
# switch to english spell checking
|
||||
key = "<leader>se";
|
||||
action = ":setlocal spelllang=en_us<CR>";
|
||||
options = {
|
||||
noremap = true;
|
||||
silent = true;
|
||||
};
|
||||
mode = "n";
|
||||
}
|
||||
{
|
||||
options.desc = "switch to german spell checking";
|
||||
# switch to german spell checking
|
||||
key = "<leader>sg";
|
||||
action = ":setlocal spelllang=de_20<CR>";
|
||||
options = {
|
||||
noremap = true;
|
||||
silent = true;
|
||||
};
|
||||
mode = "n";
|
||||
}
|
||||
{
|
||||
options.desc = "move to next misspelling";
|
||||
# move to next misspelling
|
||||
key = "]s";
|
||||
action = "]szz";
|
||||
options = {
|
||||
noremap = true;
|
||||
silent = true;
|
||||
};
|
||||
mode = "n";
|
||||
}
|
||||
{
|
||||
options.desc = "move to previous misspelling";
|
||||
# move to previous misspelling
|
||||
key = "[s";
|
||||
action = "[szz";
|
||||
options = {
|
||||
noremap = true;
|
||||
silent = true;
|
||||
};
|
||||
mode = "n";
|
||||
}
|
||||
{
|
||||
options.desc = "correction suggestions for a misspelled word";
|
||||
# correction suggestions for a misspelled word
|
||||
key = "z=";
|
||||
action = "z=";
|
||||
options = {
|
||||
noremap = true;
|
||||
silent = true;
|
||||
};
|
||||
mode = "n";
|
||||
}
|
||||
{
|
||||
options.desc = "adding words to the dictionary";
|
||||
# adding words to the dictionary
|
||||
key = "zg";
|
||||
action = "zg";
|
||||
options = {
|
||||
noremap = true;
|
||||
silent = true;
|
||||
};
|
||||
mode = "n";
|
||||
}
|
||||
|
||||
# buffer navigation
|
||||
{
|
||||
options.desc = "next buffer";
|
||||
# next buffer
|
||||
key = "<C-S-J>";
|
||||
action = ":bnext<CR>";
|
||||
options = {
|
||||
noremap = true;
|
||||
silent = true;
|
||||
};
|
||||
mode = "n";
|
||||
}
|
||||
{
|
||||
options.desc = "previous buffer";
|
||||
# previous buffer
|
||||
key = "<C-S-K>";
|
||||
action = ":bprevious<CR>";
|
||||
options = {
|
||||
noremap = true;
|
||||
silent = true;
|
||||
};
|
||||
mode = "n";
|
||||
}
|
||||
{
|
||||
options.desc = "close current buffer";
|
||||
# close current buffer
|
||||
key = "<leader>bd";
|
||||
action = ":bdelete<CR>";
|
||||
options = {
|
||||
noremap = true;
|
||||
silent = true;
|
||||
};
|
||||
mode = "n";
|
||||
}
|
||||
|
||||
{
|
||||
options.desc = "apply code action";
|
||||
# apply code action
|
||||
key = "<leader>ca";
|
||||
action = ":lua vim.lsp.buf.code_action()<CR>";
|
||||
options = {
|
||||
noremap = true;
|
||||
silent = true;
|
||||
};
|
||||
mode = "n";
|
||||
}
|
||||
]
|
||||
|
|
|
|||
|
|
@ -3,17 +3,14 @@
|
|||
{
|
||||
imports = [
|
||||
./cmp.nix
|
||||
./diffview.nix
|
||||
./lsp.nix
|
||||
./gitsigns.nix
|
||||
./lualine.nix
|
||||
./telescope.nix
|
||||
./treesitter.nix
|
||||
# ./treesitter.nix # HOTFIX: does not build
|
||||
./trouble.nix
|
||||
];
|
||||
|
||||
config.programs.nixvim.plugins = {
|
||||
which-key.enable = lib.mkDefault true;
|
||||
markdown-preview.enable = lib.mkDefault true;
|
||||
# warning: Nixvim: `plugins.web-devicons` was enabled automatically because the following plugins are enabled. This behaviour is deprecated. Please explicitly define `plugins.web-devicons.enable`
|
||||
web-devicons.enable = true;
|
||||
|
|
|
|||
|
|
@ -1,59 +0,0 @@
|
|||
{ config, lib, ... }:
|
||||
|
||||
let
|
||||
cfg = config.programs.nixvim;
|
||||
plugin = cfg.plugins.diffview;
|
||||
|
||||
inherit (lib) mkDefault mkIf;
|
||||
in
|
||||
{
|
||||
config = {
|
||||
programs.nixvim = {
|
||||
plugins.diffview = {
|
||||
enable = mkDefault true;
|
||||
};
|
||||
|
||||
# highlight = mkIf plugin.enable {
|
||||
# DiffAdd = {
|
||||
# bg = "#2d4a2d";
|
||||
# fg = "NONE";
|
||||
# };
|
||||
# DiffDelete = {
|
||||
# bg = "#4a2d2d";
|
||||
# fg = "NONE";
|
||||
# };
|
||||
# DiffChange = {
|
||||
# bg = "#2d3a4a";
|
||||
# fg = "NONE";
|
||||
# };
|
||||
# DiffText = {
|
||||
# bg = "#1a5a1a";
|
||||
# fg = "NONE";
|
||||
# };
|
||||
# };
|
||||
|
||||
keymaps = mkIf plugin.enable [
|
||||
{
|
||||
mode = "n";
|
||||
key = "<leader>gd";
|
||||
action.__raw = ''
|
||||
function()
|
||||
local lib = require("diffview.lib")
|
||||
local view = lib.get_current_view()
|
||||
if view then
|
||||
vim.cmd("DiffviewClose")
|
||||
else
|
||||
vim.cmd("DiffviewOpen")
|
||||
end
|
||||
end
|
||||
'';
|
||||
options = {
|
||||
noremap = true;
|
||||
silent = true;
|
||||
desc = "toggle git diff";
|
||||
};
|
||||
}
|
||||
];
|
||||
};
|
||||
};
|
||||
}
|
||||
|
|
@ -1,104 +0,0 @@
|
|||
{ config, lib, ... }:
|
||||
|
||||
let
|
||||
cfg = config.programs.nixvim;
|
||||
plugin = cfg.plugins.gitsigns;
|
||||
|
||||
inherit (lib) mkDefault mkIf;
|
||||
in
|
||||
{
|
||||
config = {
|
||||
programs.nixvim = {
|
||||
plugins.gitsigns = {
|
||||
enable = mkDefault true;
|
||||
settings = {
|
||||
current_line_blame = mkDefault false;
|
||||
current_line_blame_opts = {
|
||||
virt_text = mkDefault true;
|
||||
virt_text_pos = mkDefault "eol";
|
||||
};
|
||||
signcolumn = mkDefault true;
|
||||
signs = {
|
||||
add.text = mkDefault "+";
|
||||
change.text = mkDefault "│";
|
||||
changedelete.text = mkDefault "~";
|
||||
delete.text = mkDefault "-";
|
||||
topdelete.text = mkDefault "-";
|
||||
untracked.text = mkDefault "?";
|
||||
};
|
||||
watch_gitdir.follow_files = mkDefault true;
|
||||
};
|
||||
};
|
||||
keymaps = mkIf plugin.enable [
|
||||
{
|
||||
mode = "n";
|
||||
key = "<leader>hs";
|
||||
action.__raw = "function() require('gitsigns').stage_hunk() end";
|
||||
options = {
|
||||
noremap = true;
|
||||
silent = true;
|
||||
desc = "stage hunk";
|
||||
};
|
||||
}
|
||||
{
|
||||
mode = "v";
|
||||
key = "<leader>hs";
|
||||
action.__raw = ''
|
||||
function()
|
||||
require('gitsigns').stage_hunk({vim.fn.line('.'), vim.fn.line('v')})
|
||||
end
|
||||
'';
|
||||
options = {
|
||||
noremap = true;
|
||||
silent = true;
|
||||
desc = "stage selected hunks";
|
||||
};
|
||||
}
|
||||
{
|
||||
mode = "n";
|
||||
key = "<leader>hu";
|
||||
action.__raw = "function() require('gitsigns').undo_stage_hunk() end";
|
||||
options = {
|
||||
noremap = true;
|
||||
silent = true;
|
||||
desc = "undo stage hunk";
|
||||
};
|
||||
}
|
||||
{
|
||||
mode = "n";
|
||||
key = "<leader>hS";
|
||||
action.__raw = "function() require('gitsigns').stage_buffer() end";
|
||||
options = {
|
||||
noremap = true;
|
||||
silent = true;
|
||||
desc = "stage buffer";
|
||||
};
|
||||
}
|
||||
{
|
||||
mode = "n";
|
||||
key = "<leader>hr";
|
||||
action.__raw = "function() require('gitsigns').reset_hunk() end";
|
||||
options = {
|
||||
noremap = true;
|
||||
silent = true;
|
||||
desc = "reset hunk";
|
||||
};
|
||||
}
|
||||
{
|
||||
mode = "v";
|
||||
key = "<leader>hr";
|
||||
action.__raw = ''
|
||||
function()
|
||||
require('gitsigns').reset_hunk({vim.fn.line('.'), vim.fn.line('v')})
|
||||
end
|
||||
'';
|
||||
options = {
|
||||
noremap = true;
|
||||
silent = true;
|
||||
desc = "reset selected hunks";
|
||||
};
|
||||
}
|
||||
];
|
||||
};
|
||||
};
|
||||
}
|
||||
|
|
@ -16,31 +16,6 @@ in
|
|||
programs.nixvim = {
|
||||
plugins.telescope = {
|
||||
enable = mkDefault true;
|
||||
settings = {
|
||||
defaults = {
|
||||
vimgrep_arguments = [
|
||||
"rg"
|
||||
"--color=never"
|
||||
"--no-heading"
|
||||
"--with-filename"
|
||||
"--line-number"
|
||||
"--column"
|
||||
"--smart-case"
|
||||
"--hidden"
|
||||
];
|
||||
file_ignore_patterns = [
|
||||
"^.git/"
|
||||
"^.direnv/"
|
||||
"^.cache/"
|
||||
"^node_modules/"
|
||||
];
|
||||
};
|
||||
pickers = {
|
||||
find_files = {
|
||||
hidden = true;
|
||||
};
|
||||
};
|
||||
};
|
||||
extensions = {
|
||||
file-browser.enable = mkDefault true;
|
||||
fzf-native.enable = mkDefault true;
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
let
|
||||
spellDir = config.xdg.dataHome + "/nvim/site/spell";
|
||||
baseUrl = "https://vim.ftp.fu-berlin.de/runtime/spell";
|
||||
baseUrl = "http://ftp.de.vim.org/runtime/spell";
|
||||
in
|
||||
{
|
||||
home.file = {
|
||||
|
|
@ -12,7 +12,7 @@ in
|
|||
url = baseUrl + "/de.utf-8.spl";
|
||||
sha256 = "sha256-c8cQfqM5hWzb6SHeuSpFk5xN5uucByYdobndGfaDo9E=";
|
||||
};
|
||||
target = spellDir + "/de.utf-8.spl";
|
||||
target = spellDir + "/de.utf8.spl";
|
||||
};
|
||||
de-sug = {
|
||||
enable = true;
|
||||
|
|
@ -20,7 +20,7 @@ in
|
|||
url = baseUrl + "/de.utf-8.sug";
|
||||
sha256 = "sha256-E9Ds+Shj2J72DNSopesqWhOg6Pm6jRxqvkerqFcUqUg=";
|
||||
};
|
||||
target = spellDir + "/de.utf-8.sug";
|
||||
target = spellDir + "/de.utf8.sug";
|
||||
};
|
||||
};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -17,7 +17,6 @@ let
|
|||
"moonfly"
|
||||
"nord"
|
||||
"oxocarbon"
|
||||
"generate-from-image"
|
||||
];
|
||||
# schemes names in `pkgs.base16-schemes` that need a suffix
|
||||
needsSuffix = [
|
||||
|
|
@ -31,6 +30,11 @@ let
|
|||
];
|
||||
schemeName =
|
||||
if builtins.elem cfg.scheme needsSuffix then "${cfg.scheme}-${cfg.polarity}" else cfg.scheme;
|
||||
scheme =
|
||||
if builtins.elem cfg.scheme customSchemes then
|
||||
./schemes/${schemeName}.yaml
|
||||
else
|
||||
"${pkgs.base16-schemes}/share/themes/${schemeName}.yaml";
|
||||
|
||||
inherit (lib)
|
||||
mkDefault
|
||||
|
|
@ -52,8 +56,6 @@ in
|
|||
description = ''
|
||||
Base16 color scheme name. Available options are:
|
||||
${toString validSchemes}
|
||||
|
||||
"generate-from-image" generates a color scheme from `stylix.image`
|
||||
'';
|
||||
};
|
||||
};
|
||||
|
|
@ -68,12 +70,7 @@ in
|
|||
|
||||
stylix = {
|
||||
autoEnable = mkDefault true;
|
||||
base16Scheme = mkIf (cfg.scheme != "generate-from-image") (
|
||||
if builtins.elem cfg.scheme customSchemes then
|
||||
./schemes/${schemeName}.yaml
|
||||
else
|
||||
"${pkgs.base16-schemes}/share/themes/${schemeName}.yaml"
|
||||
);
|
||||
base16Scheme = scheme;
|
||||
fonts = {
|
||||
monospace = mkDefault {
|
||||
package = pkgs.hack-font;
|
||||
|
|
|
|||
|
|
@ -4,13 +4,11 @@ let
|
|||
cfg = config.stylix;
|
||||
target = cfg.targets.nixvim;
|
||||
|
||||
inherit (lib) mkIf optionalAttrs;
|
||||
inherit (lib) mkIf;
|
||||
in
|
||||
{
|
||||
config = mkIf cfg.enable {
|
||||
stylix.targets.nixvim.enable = false;
|
||||
programs.nixvim.colorschemes = optionalAttrs (cfg.scheme != "generate-from-image") {
|
||||
"${cfg.scheme}".enable = !target.enable;
|
||||
};
|
||||
programs.nixvim.colorschemes."${cfg.scheme}".enable = !target.enable;
|
||||
};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -71,11 +71,11 @@ in
|
|||
|
||||
#workspaces {
|
||||
color: ${colors.base05};
|
||||
background: ${colors.base00};
|
||||
}
|
||||
|
||||
#workspaces button {
|
||||
padding: ${halfgaps}px;
|
||||
color: ${colors.base05};
|
||||
}
|
||||
|
||||
#workspaces button.active {
|
||||
|
|
|
|||
|
|
@ -56,7 +56,6 @@ let
|
|||
};
|
||||
|
||||
# Add your custom modules here
|
||||
"custom/notifications" = import ./modules/notifications.nix { inherit lib pkgs; };
|
||||
"custom/newsboat" = import ./modules/newsboat.nix { inherit lib pkgs; };
|
||||
"pulseaudio#input" = import ./modules/pulseaudio/input.nix { inherit lib pkgs; };
|
||||
"pulseaudio#output" = import ./modules/pulseaudio/output.nix { inherit lib pkgs; };
|
||||
|
|
@ -96,13 +95,11 @@ in
|
|||
"disk"
|
||||
"pulseaudio#input"
|
||||
"pulseaudio#output"
|
||||
"custom/notifications"
|
||||
"tray"
|
||||
];
|
||||
|
||||
inherit
|
||||
"custom/newsboat"
|
||||
"custom/notifications"
|
||||
"hyprland/language"
|
||||
"hyprland/workspaces"
|
||||
"pulseaudio#input"
|
||||
|
|
@ -132,7 +129,5 @@ in
|
|||
};
|
||||
};
|
||||
};
|
||||
|
||||
services.batsignal.enable = builtins.elem "battery" cfg.settings.mainBar.modules-right;
|
||||
};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,27 +0,0 @@
|
|||
{ pkgs, lib, ... }:
|
||||
|
||||
let
|
||||
inherit (lib) mkDefault;
|
||||
dunst = "${pkgs.dunst}/bin/dunstctl";
|
||||
in
|
||||
{
|
||||
format = mkDefault "{icon}";
|
||||
format-icons = {
|
||||
unmuted = mkDefault "";
|
||||
muted = mkDefault "";
|
||||
};
|
||||
return-type = mkDefault "json";
|
||||
exec = mkDefault (
|
||||
pkgs.writeShellScript "notifications" ''
|
||||
is_paused=$(${dunst} is-paused)
|
||||
if [ "$is_paused" = "true" ]; then
|
||||
echo '{"alt": "muted", "class": "muted"}'
|
||||
else
|
||||
echo '{"alt": "unmuted", "class": "unmuted"}'
|
||||
fi
|
||||
''
|
||||
);
|
||||
on-click = mkDefault "dunst-toggle";
|
||||
interval = mkDefault "once";
|
||||
signal = mkDefault 12;
|
||||
}
|
||||
|
|
@ -6,19 +6,19 @@
|
|||
environment.systemPackages = with pkgs; [
|
||||
lact
|
||||
nvtopPackages.amd
|
||||
rocmPackages.clr.icd
|
||||
rocmPackages.hipcc
|
||||
rocmPackages.miopen
|
||||
rocmPackages.rocm-runtime
|
||||
rocmPackages.rocm-smi
|
||||
rocmPackages.rocminfo
|
||||
|
||||
];
|
||||
|
||||
# environment.variables.ROC_ENABLE_PRE_VEGA = "1"; # for Polaris
|
||||
|
||||
hardware.amdgpu.opencl.enable = true;
|
||||
|
||||
hardware.graphics.extraPackages = with pkgs; [ rocmPackages.clr.icd ];
|
||||
|
||||
systemd.packages = with pkgs; [ lact ];
|
||||
systemd.services.lactd.wantedBy = [ "multi-user.target" ];
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,20 +0,0 @@
|
|||
{ lib, pkgs, ... }:
|
||||
|
||||
{
|
||||
# fix CVE-2026-31431
|
||||
boot.kernelPackages = lib.mkIf (lib.versionOlder pkgs.linux.version "6.18.22") (
|
||||
lib.mkDefault pkgs.linuxPackages_6_18
|
||||
);
|
||||
|
||||
# fix CVE-2026-43500
|
||||
boot.extraModprobeConfig = ''
|
||||
install esp4 ${pkgs.coreutils}/bin/false
|
||||
install esp6 ${pkgs.coreutils}/bin/false
|
||||
install rxrpc ${pkgs.coreutils}/bin/false
|
||||
'';
|
||||
boot.blacklistedKernelModules = [
|
||||
"esp4"
|
||||
"esp6"
|
||||
"rxrpc"
|
||||
];
|
||||
}
|
||||
|
|
@ -1,6 +1,5 @@
|
|||
{
|
||||
imports = [
|
||||
./boot.nix
|
||||
./environment.nix
|
||||
./htop.nix
|
||||
./nationalization.nix
|
||||
|
|
|
|||
|
|
@ -14,7 +14,6 @@
|
|||
i2pd = import ./i2pd;
|
||||
jellyfin = import ./jellyfin;
|
||||
jirafeau = import ./jirafeau;
|
||||
librechat-oci = import ./librechat-oci;
|
||||
mailserver = import ./mailserver;
|
||||
matrix-synapse = import ./matrix-synapse;
|
||||
maubot = import ./maubot;
|
||||
|
|
@ -22,7 +21,6 @@
|
|||
miniflux = import ./miniflux;
|
||||
nginx = import ./nginx;
|
||||
normalUsers = import ./normalUsers;
|
||||
nostr-relay = import ./nostr-relay;
|
||||
nvidia = import ./nvidia;
|
||||
ollama = import ./ollama;
|
||||
open-webui-oci = import ./open-webui-oci;
|
||||
|
|
@ -35,4 +33,5 @@
|
|||
virtualisation = import ./virtualisation;
|
||||
webPage = import ./webPage;
|
||||
windows-oci = import ./windows-oci;
|
||||
zfs = import ./zfs;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -45,10 +45,10 @@ in
|
|||
url = "http://127.0.0.1:${toString headscale.port}";
|
||||
public_url = headscale.settings.server_url;
|
||||
config_path = "/etc/headscale/config.yaml";
|
||||
api_key_path = config.sops.secrets."headplane/api_key".path;
|
||||
};
|
||||
integration.agent = {
|
||||
enabled = mkDefault true;
|
||||
pre_authkey_path = config.sops.secrets."headplane/agent_pre_authkey".path;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
|
@ -70,7 +70,7 @@ in
|
|||
"headplane/cookie_secret" = {
|
||||
inherit owner group mode;
|
||||
};
|
||||
"headplane/api_key" = {
|
||||
"headplane/agent_pre_authkey" = {
|
||||
inherit owner group mode;
|
||||
};
|
||||
};
|
||||
|
|
|
|||
|
|
@ -8,14 +8,11 @@ in
|
|||
|
||||
programs.dconf.enable = true; # fixes nixvim hm module
|
||||
|
||||
services.flatpak.enable = true;
|
||||
|
||||
xdg.portal = {
|
||||
enable = true;
|
||||
extraPortals = with pkgs; [
|
||||
xdg-desktop-portal-gtk
|
||||
];
|
||||
config.common.default = "gtk";
|
||||
};
|
||||
|
||||
services.gnome.gnome-keyring.enable = true;
|
||||
|
|
|
|||
|
|
@ -1,527 +0,0 @@
|
|||
{
|
||||
config,
|
||||
lib,
|
||||
pkgs,
|
||||
...
|
||||
}:
|
||||
|
||||
let
|
||||
cfg = config.services.librechat-oci;
|
||||
|
||||
defaultImages = {
|
||||
librechat = pkgs.dockerTools.pullImage {
|
||||
imageName = "ghcr.io/danny-avila/librechat";
|
||||
imageDigest = "sha256:a46254938507971e0d4f7ed3f9d116bd9b118f4810b5b75eb716baf575645068";
|
||||
hash = "sha256-zevUN6vrs3hymwCGFmk/YXlUzYjN37H+EO5aLxYchyc=";
|
||||
finalImageName = "ghcr.io/danny-avila/librechat";
|
||||
finalImageTag = "v0.8.5";
|
||||
};
|
||||
|
||||
meilisearch = pkgs.dockerTools.pullImage {
|
||||
imageName = "getmeili/meilisearch";
|
||||
imageDigest = "sha256:b839a48d008d4e67e57f78dcff5b21d5e8b8fa066bacd11f97824d6307abb0dd";
|
||||
hash = "sha256-+hypvjFDSdnnWAO4tARTnjNd/6HlF6pMg1L6UUffdYM=";
|
||||
finalImageName = "getmeili/meilisearch";
|
||||
finalImageTag = "v1.44.0";
|
||||
};
|
||||
|
||||
mongodb = pkgs.dockerTools.pullImage {
|
||||
imageName = "mongo";
|
||||
imageDigest = "sha256:098862b1339f031900ca66cf8fef799e616d6324fa41b9a263f2ec899552c1ef";
|
||||
hash = "sha256-XuWnvcqAAkAGshdQtnngKOOJP2Bd33FXTbGHTRX3nUc=";
|
||||
finalImageName = "mongo";
|
||||
finalImageTag = "8.0.20";
|
||||
};
|
||||
|
||||
vectordb = pkgs.dockerTools.pullImage {
|
||||
imageName = "pgvector/pgvector";
|
||||
imageDigest = "sha256:8809cfffff0082cf260c9ac752f1dd1afc77f6f0a55c4e6411321e78efc3d9a5";
|
||||
hash = "sha256-rc6gQLMzv8UOZVLmWKGUESNIo+iPf5DR7T79AmbzWc4=";
|
||||
finalImageName = "pgvector/pgvector";
|
||||
finalImageTag = "0.8.0-pg15-trixie";
|
||||
};
|
||||
|
||||
ragApi = pkgs.dockerTools.pullImage {
|
||||
imageName = "registry.librechat.ai/danny-avila/librechat-rag-api-dev-lite";
|
||||
imageDigest = "sha256:6dfb6832661ff9c26fa329c823ce266059e33567670a763e9ecb9b566b8daa68";
|
||||
hash = "sha256-k8pkEgbqT4NU2+2ZjdRFlfFvMUk/1p+pkysbELh95pM=";
|
||||
finalImageName = "registry.librechat.ai/danny-avila/librechat-rag-api-dev-lite";
|
||||
finalImageTag = "latest";
|
||||
};
|
||||
};
|
||||
|
||||
defaultEnv = {
|
||||
# Server
|
||||
HOST = "0.0.0.0";
|
||||
PORT = toString cfg.port;
|
||||
NO_INDEX = "true";
|
||||
TRUST_PROXY = "1";
|
||||
|
||||
# Logging
|
||||
CONSOLE_JSON = "false";
|
||||
DEBUG_LOGGING = "true";
|
||||
DEBUG_CONSOLE = "false";
|
||||
AGENT_DEBUG_LOGGING = "false";
|
||||
DEBUG_OPENAI = "false";
|
||||
|
||||
# Node
|
||||
NODE_MAX_OLD_SPACE_SIZE = "6144";
|
||||
|
||||
# Search
|
||||
SEARCH = "true";
|
||||
MEILI_NO_ANALYTICS = "true";
|
||||
|
||||
# Moderation
|
||||
OPENAI_MODERATION = "false";
|
||||
BAN_VIOLATIONS = "true";
|
||||
BAN_DURATION = "1000 * 60 * 60 * 2";
|
||||
BAN_INTERVAL = "20";
|
||||
LOGIN_VIOLATION_SCORE = "1";
|
||||
REGISTRATION_VIOLATION_SCORE = "1";
|
||||
CONCURRENT_VIOLATION_SCORE = "1";
|
||||
MESSAGE_VIOLATION_SCORE = "1";
|
||||
NON_BROWSER_VIOLATION_SCORE = "20";
|
||||
TTS_VIOLATION_SCORE = "0";
|
||||
STT_VIOLATION_SCORE = "0";
|
||||
FORK_VIOLATION_SCORE = "0";
|
||||
IMPORT_VIOLATION_SCORE = "0";
|
||||
FILE_UPLOAD_VIOLATION_SCORE = "0";
|
||||
LOGIN_MAX = "7";
|
||||
LOGIN_WINDOW = "5";
|
||||
REGISTER_MAX = "5";
|
||||
REGISTER_WINDOW = "60";
|
||||
LIMIT_CONCURRENT_MESSAGES = "true";
|
||||
CONCURRENT_MESSAGE_MAX = "2";
|
||||
LIMIT_MESSAGE_IP = "true";
|
||||
MESSAGE_IP_MAX = "40";
|
||||
MESSAGE_IP_WINDOW = "1";
|
||||
LIMIT_MESSAGE_USER = "false";
|
||||
MESSAGE_USER_MAX = "40";
|
||||
MESSAGE_USER_WINDOW = "1";
|
||||
ILLEGAL_MODEL_REQ_SCORE = "5";
|
||||
|
||||
# Registration and login
|
||||
ALLOW_EMAIL_LOGIN = "true";
|
||||
ALLOW_REGISTRATION = "false";
|
||||
ALLOW_SOCIAL_LOGIN = "false";
|
||||
ALLOW_SOCIAL_REGISTRATION = "false";
|
||||
ALLOW_PASSWORD_RESET = "false";
|
||||
ALLOW_UNVERIFIED_EMAIL_LOGIN = "true";
|
||||
SESSION_EXPIRY = "1000 * 60 * 15";
|
||||
REFRESH_TOKEN_EXPIRY = "(1000 * 60 * 60 * 24) * 7";
|
||||
|
||||
# OpenID
|
||||
OPENID_SCOPE = "openid profile email";
|
||||
OPENID_CALLBACK_URL = "/oauth/openid/callback";
|
||||
OPENID_AUTO_REDIRECT = "false";
|
||||
OPENID_USE_PKCE = "false";
|
||||
OPENID_ON_BEHALF_FLOW_USERINFO_SCOPE = "user.read";
|
||||
|
||||
# OAuth callback URLs
|
||||
DISCORD_CALLBACK_URL = "/oauth/discord/callback";
|
||||
FACEBOOK_CALLBACK_URL = "/oauth/facebook/callback";
|
||||
GITHUB_CALLBACK_URL = "/oauth/github/callback";
|
||||
GOOGLE_CALLBACK_URL = "/oauth/google/callback";
|
||||
APPLE_CALLBACK_URL = "/oauth/apple/callback";
|
||||
SAML_CALLBACK_URL = "/oauth/saml/callback";
|
||||
|
||||
# Entra ID
|
||||
USE_ENTRA_ID_FOR_PEOPLE_SEARCH = "false";
|
||||
ENTRA_ID_INCLUDE_OWNERS_AS_MEMBERS = "false";
|
||||
OPENID_GRAPH_SCOPES = "User.Read,People.Read,GroupMember.Read.All";
|
||||
|
||||
# Shared links
|
||||
ALLOW_SHARED_LINKS = "true";
|
||||
ALLOW_SHARED_LINKS_PUBLIC = "false";
|
||||
|
||||
# UI
|
||||
APP_TITLE = "LibreChat";
|
||||
HELP_AND_FAQ_URL = "https://librechat.ai";
|
||||
|
||||
# Flux
|
||||
FLUX_API_BASE_URL = "https://api.us1.bfl.ai";
|
||||
|
||||
# Email
|
||||
EMAIL_PORT = "25";
|
||||
EMAIL_FROM = "noreply@librechat.ai";
|
||||
|
||||
# Azure Blob Storage
|
||||
AZURE_STORAGE_PUBLIC_ACCESS = "false";
|
||||
AZURE_CONTAINER_NAME = "files";
|
||||
};
|
||||
|
||||
mkImageOption =
|
||||
name: description:
|
||||
mkOption {
|
||||
type = types.package;
|
||||
default = defaultImages.${name};
|
||||
description = description;
|
||||
};
|
||||
|
||||
inherit (lib)
|
||||
literalExpression
|
||||
mkEnableOption
|
||||
mkIf
|
||||
mkOption
|
||||
mkOverride
|
||||
optional
|
||||
types
|
||||
;
|
||||
in
|
||||
{
|
||||
options.services.librechat-oci = {
|
||||
enable = mkEnableOption "LibreChat container with Podman.";
|
||||
|
||||
images = {
|
||||
librechat = mkImageOption "librechat" "The LibreChat Docker image (`pkgs.dockerTools.pullImage`).";
|
||||
meilisearch = mkImageOption "meilisearch" "The Meilisearch Docker image (`pkgs.dockerTools.pullImage`).";
|
||||
mongodb = mkImageOption "mongodb" "The MongoDB Docker image (`pkgs.dockerTools.pullImage`).";
|
||||
vectordb = mkImageOption "vectordb" "The pgvector Docker image (`pkgs.dockerTools.pullImage`).";
|
||||
ragApi = mkImageOption "ragApi" "The LibreChat RAG API Docker image (`pkgs.dockerTools.pullImage`).";
|
||||
};
|
||||
|
||||
configFile = mkOption {
|
||||
type = types.nullOr types.path;
|
||||
default = null;
|
||||
example = literalExpression "./librechat.yaml";
|
||||
description = "Path to the `librechat.yaml` configuration file.";
|
||||
};
|
||||
|
||||
externalUrl = mkOption {
|
||||
type = types.nullOr types.str;
|
||||
default = null;
|
||||
example = literalExpression ''"https://chat.example.com"'';
|
||||
description = "Public URL to configure for LibreChat (sets DOMAIN_CLIENT and DOMAIN_SERVER).";
|
||||
};
|
||||
|
||||
port = mkOption {
|
||||
type = types.port;
|
||||
default = 3080;
|
||||
description = "Which port the LibreChat server listens on.";
|
||||
};
|
||||
|
||||
meiliPort = mkOption {
|
||||
type = types.port;
|
||||
default = 7700;
|
||||
description = "Which port Meilisearch listens on.";
|
||||
};
|
||||
|
||||
ragPort = mkOption {
|
||||
type = types.port;
|
||||
default = 8000;
|
||||
description = "Which port the RAG API listens on.";
|
||||
};
|
||||
|
||||
environment = mkOption {
|
||||
default = { };
|
||||
type = types.attrsOf types.str;
|
||||
description = ''
|
||||
Extra environment variables for LibreChat.
|
||||
These are merged on top of the defaults and can override them.
|
||||
For secrets use <option>environmentFile</option> instead.
|
||||
See <https://docs.librechat.ai/docs/configuration/dotenv>.
|
||||
'';
|
||||
};
|
||||
|
||||
environmentFile = mkOption {
|
||||
type = types.nullOr types.path;
|
||||
default = null;
|
||||
example = literalExpression "config.sops.templates.librechat-env.path";
|
||||
description = ''
|
||||
Environment file passed to the LibreChat, Meilisearch, and RAG API
|
||||
containers. Use this for secrets such as JWT_SECRET, CREDS_KEY,
|
||||
MEILI_MASTER_KEY, and API keys.
|
||||
'';
|
||||
};
|
||||
};
|
||||
|
||||
config = mkIf cfg.enable {
|
||||
virtualisation.podman = {
|
||||
enable = true;
|
||||
autoPrune.enable = true;
|
||||
dockerCompat = true;
|
||||
};
|
||||
|
||||
networking.firewall.interfaces =
|
||||
let
|
||||
matchAll = if !config.networking.nftables.enable then "podman+" else "podman*";
|
||||
in
|
||||
{
|
||||
"${matchAll}".allowedUDPPorts = [ 53 ];
|
||||
};
|
||||
|
||||
virtualisation.oci-containers.backend = "podman";
|
||||
|
||||
virtualisation.oci-containers.containers.librechat-mongodb = {
|
||||
image = with cfg.images.mongodb; "${imageName}:${imageTag}";
|
||||
imageFile = cfg.images.mongodb;
|
||||
cmd = [
|
||||
"mongod"
|
||||
"--noauth"
|
||||
];
|
||||
volumes = [
|
||||
"librechat_mongodb_data:/data/db:rw"
|
||||
];
|
||||
log-driver = "journald";
|
||||
extraOptions = [
|
||||
"--network-alias=mongodb"
|
||||
"--network=librechat_default"
|
||||
];
|
||||
};
|
||||
|
||||
virtualisation.oci-containers.containers.librechat-meilisearch = {
|
||||
image = with cfg.images.meilisearch; "${imageName}:${imageTag}";
|
||||
imageFile = cfg.images.meilisearch;
|
||||
environment = {
|
||||
MEILI_NO_ANALYTICS = "true";
|
||||
MEILI_HOST = "http://meilisearch:${toString cfg.meiliPort}";
|
||||
};
|
||||
environmentFiles = optional (cfg.environmentFile != null) cfg.environmentFile;
|
||||
volumes = [
|
||||
"librechat_meili_data:/meili_data:rw"
|
||||
];
|
||||
log-driver = "journald";
|
||||
extraOptions = [
|
||||
"--network-alias=meilisearch"
|
||||
"--network=librechat_default"
|
||||
];
|
||||
};
|
||||
|
||||
virtualisation.oci-containers.containers.librechat-vectordb = {
|
||||
image = with cfg.images.vectordb; "${imageName}:${imageTag}";
|
||||
imageFile = cfg.images.vectordb;
|
||||
environment = {
|
||||
POSTGRES_DB = "mydatabase";
|
||||
POSTGRES_USER = "myuser";
|
||||
POSTGRES_PASSWORD = "mypassword";
|
||||
};
|
||||
volumes = [
|
||||
"librechat_pgdata:/var/lib/postgresql/data:rw"
|
||||
];
|
||||
log-driver = "journald";
|
||||
extraOptions = [
|
||||
"--network-alias=vectordb"
|
||||
"--network=librechat_default"
|
||||
];
|
||||
};
|
||||
|
||||
virtualisation.oci-containers.containers.librechat-rag-api = {
|
||||
image = with cfg.images.ragApi; "${imageName}:${imageTag}";
|
||||
imageFile = cfg.images.ragApi;
|
||||
environment = {
|
||||
DB_HOST = "vectordb";
|
||||
RAG_PORT = toString cfg.ragPort;
|
||||
};
|
||||
environmentFiles = optional (cfg.environmentFile != null) cfg.environmentFile;
|
||||
dependsOn = [ "librechat-vectordb" ];
|
||||
log-driver = "journald";
|
||||
extraOptions = [
|
||||
"--network-alias=rag_api"
|
||||
"--network=librechat_default"
|
||||
];
|
||||
};
|
||||
|
||||
virtualisation.oci-containers.containers.librechat = {
|
||||
image = with cfg.images.librechat; "${imageName}:${imageTag}";
|
||||
imageFile = cfg.images.librechat;
|
||||
environment =
|
||||
defaultEnv
|
||||
// {
|
||||
MONGO_URI = "mongodb://mongodb:27017/LibreChat";
|
||||
MEILI_HOST = "http://meilisearch:${toString cfg.meiliPort}";
|
||||
RAG_PORT = toString cfg.ragPort;
|
||||
RAG_API_URL = "http://rag_api:${toString cfg.ragPort}";
|
||||
DOMAIN_CLIENT =
|
||||
if cfg.externalUrl != null then cfg.externalUrl else "http://localhost:${toString cfg.port}";
|
||||
DOMAIN_SERVER =
|
||||
if cfg.externalUrl != null then cfg.externalUrl else "http://localhost:${toString cfg.port}";
|
||||
}
|
||||
// cfg.environment;
|
||||
environmentFiles = optional (cfg.environmentFile != null) cfg.environmentFile;
|
||||
volumes = [
|
||||
"librechat_images:/app/client/public/images:rw"
|
||||
"librechat_uploads:/app/uploads:rw"
|
||||
"librechat_logs:/app/logs:rw"
|
||||
]
|
||||
++ optional (cfg.configFile != null) "${cfg.configFile}:/app/librechat.yaml:ro";
|
||||
|
||||
ports = [
|
||||
"0.0.0.0:${toString cfg.port}:${toString cfg.port}/tcp"
|
||||
];
|
||||
dependsOn = [
|
||||
"librechat-mongodb"
|
||||
"librechat-rag-api"
|
||||
];
|
||||
log-driver = "journald";
|
||||
extraOptions = [
|
||||
"--network-alias=api"
|
||||
"--network=librechat_default"
|
||||
];
|
||||
};
|
||||
|
||||
systemd.services.podman-librechat-mongodb = {
|
||||
serviceConfig.Restart = mkOverride 90 "always";
|
||||
after = [
|
||||
"podman-network-librechat_default.service"
|
||||
"podman-volume-librechat_mongodb_data.service"
|
||||
];
|
||||
requires = [
|
||||
"podman-network-librechat_default.service"
|
||||
"podman-volume-librechat_mongodb_data.service"
|
||||
];
|
||||
partOf = [ "podman-compose-librechat-root.target" ];
|
||||
wantedBy = [ "podman-compose-librechat-root.target" ];
|
||||
};
|
||||
|
||||
systemd.services.podman-librechat-meilisearch = {
|
||||
serviceConfig.Restart = mkOverride 90 "always";
|
||||
after = [
|
||||
"podman-network-librechat_default.service"
|
||||
"podman-volume-librechat_meili_data.service"
|
||||
];
|
||||
requires = [
|
||||
"podman-network-librechat_default.service"
|
||||
"podman-volume-librechat_meili_data.service"
|
||||
];
|
||||
partOf = [ "podman-compose-librechat-root.target" ];
|
||||
wantedBy = [ "podman-compose-librechat-root.target" ];
|
||||
};
|
||||
|
||||
systemd.services.podman-librechat-vectordb = {
|
||||
serviceConfig.Restart = mkOverride 90 "always";
|
||||
after = [
|
||||
"podman-network-librechat_default.service"
|
||||
"podman-volume-librechat_pgdata.service"
|
||||
];
|
||||
requires = [
|
||||
"podman-network-librechat_default.service"
|
||||
"podman-volume-librechat_pgdata.service"
|
||||
];
|
||||
partOf = [ "podman-compose-librechat-root.target" ];
|
||||
wantedBy = [ "podman-compose-librechat-root.target" ];
|
||||
};
|
||||
|
||||
systemd.services.podman-librechat-rag-api = {
|
||||
serviceConfig.Restart = mkOverride 90 "always";
|
||||
after = [
|
||||
"podman-network-librechat_default.service"
|
||||
"podman-librechat-vectordb.service"
|
||||
];
|
||||
requires = [
|
||||
"podman-network-librechat_default.service"
|
||||
"podman-librechat-vectordb.service"
|
||||
];
|
||||
partOf = [ "podman-compose-librechat-root.target" ];
|
||||
wantedBy = [ "podman-compose-librechat-root.target" ];
|
||||
};
|
||||
|
||||
systemd.services.podman-librechat = {
|
||||
serviceConfig.Restart = mkOverride 90 "always";
|
||||
after = [
|
||||
"podman-network-librechat_default.service"
|
||||
"podman-volume-librechat_images.service"
|
||||
"podman-volume-librechat_uploads.service"
|
||||
"podman-volume-librechat_logs.service"
|
||||
"podman-librechat-mongodb.service"
|
||||
"podman-librechat-meilisearch.service"
|
||||
"podman-librechat-rag-api.service"
|
||||
];
|
||||
requires = [
|
||||
"podman-network-librechat_default.service"
|
||||
"podman-volume-librechat_images.service"
|
||||
"podman-volume-librechat_uploads.service"
|
||||
"podman-volume-librechat_logs.service"
|
||||
"podman-librechat-mongodb.service"
|
||||
"podman-librechat-meilisearch.service"
|
||||
"podman-librechat-rag-api.service"
|
||||
];
|
||||
partOf = [ "podman-compose-librechat-root.target" ];
|
||||
wantedBy = [ "podman-compose-librechat-root.target" ];
|
||||
};
|
||||
|
||||
systemd.services.podman-network-librechat_default = {
|
||||
path = [ pkgs.podman ];
|
||||
serviceConfig = {
|
||||
Type = "oneshot";
|
||||
RemainAfterExit = true;
|
||||
ExecStop = "podman network rm -f librechat_default";
|
||||
};
|
||||
script = ''
|
||||
podman network inspect librechat_default || podman network create librechat_default
|
||||
'';
|
||||
partOf = [ "podman-compose-librechat-root.target" ];
|
||||
wantedBy = [ "podman-compose-librechat-root.target" ];
|
||||
};
|
||||
|
||||
systemd.services.podman-volume-librechat_mongodb_data = {
|
||||
path = [ pkgs.podman ];
|
||||
serviceConfig = {
|
||||
Type = "oneshot";
|
||||
RemainAfterExit = true;
|
||||
};
|
||||
script = "podman volume inspect librechat_mongodb_data || podman volume create librechat_mongodb_data";
|
||||
partOf = [ "podman-compose-librechat-root.target" ];
|
||||
wantedBy = [ "podman-compose-librechat-root.target" ];
|
||||
};
|
||||
|
||||
systemd.services.podman-volume-librechat_meili_data = {
|
||||
path = [ pkgs.podman ];
|
||||
serviceConfig = {
|
||||
Type = "oneshot";
|
||||
RemainAfterExit = true;
|
||||
};
|
||||
script = "podman volume inspect librechat_meili_data || podman volume create librechat_meili_data";
|
||||
partOf = [ "podman-compose-librechat-root.target" ];
|
||||
wantedBy = [ "podman-compose-librechat-root.target" ];
|
||||
};
|
||||
|
||||
systemd.services.podman-volume-librechat_pgdata = {
|
||||
path = [ pkgs.podman ];
|
||||
serviceConfig = {
|
||||
Type = "oneshot";
|
||||
RemainAfterExit = true;
|
||||
};
|
||||
script = "podman volume inspect librechat_pgdata || podman volume create librechat_pgdata";
|
||||
partOf = [ "podman-compose-librechat-root.target" ];
|
||||
wantedBy = [ "podman-compose-librechat-root.target" ];
|
||||
};
|
||||
|
||||
systemd.services.podman-volume-librechat_images = {
|
||||
path = [ pkgs.podman ];
|
||||
serviceConfig = {
|
||||
Type = "oneshot";
|
||||
RemainAfterExit = true;
|
||||
};
|
||||
script = "podman volume inspect librechat_images || podman volume create librechat_images";
|
||||
partOf = [ "podman-compose-librechat-root.target" ];
|
||||
wantedBy = [ "podman-compose-librechat-root.target" ];
|
||||
};
|
||||
|
||||
systemd.services.podman-volume-librechat_uploads = {
|
||||
path = [ pkgs.podman ];
|
||||
serviceConfig = {
|
||||
Type = "oneshot";
|
||||
RemainAfterExit = true;
|
||||
};
|
||||
script = "podman volume inspect librechat_uploads || podman volume create librechat_uploads";
|
||||
partOf = [ "podman-compose-librechat-root.target" ];
|
||||
wantedBy = [ "podman-compose-librechat-root.target" ];
|
||||
};
|
||||
|
||||
systemd.services.podman-volume-librechat_logs = {
|
||||
path = [ pkgs.podman ];
|
||||
serviceConfig = {
|
||||
Type = "oneshot";
|
||||
RemainAfterExit = true;
|
||||
};
|
||||
script = "podman volume inspect librechat_logs || podman volume create librechat_logs";
|
||||
partOf = [ "podman-compose-librechat-root.target" ];
|
||||
wantedBy = [ "podman-compose-librechat-root.target" ];
|
||||
};
|
||||
|
||||
systemd.targets.podman-compose-librechat-root = {
|
||||
unitConfig.Description = "Root target generated by compose2nix.";
|
||||
wantedBy = [ "multi-user.target" ];
|
||||
};
|
||||
};
|
||||
}
|
||||
|
|
@ -28,12 +28,6 @@ in
|
|||
default = null;
|
||||
};
|
||||
|
||||
port = mkOption {
|
||||
type = types.port;
|
||||
default = 8000;
|
||||
description = "Port on which the mcpo service should listen.";
|
||||
};
|
||||
|
||||
user = mkOption {
|
||||
type = types.str;
|
||||
description = "The user the mcpo service will run as.";
|
||||
|
|
@ -106,7 +100,7 @@ in
|
|||
after = [ "network.target" ];
|
||||
wantedBy = [ "multi-user.target" ];
|
||||
serviceConfig = {
|
||||
ExecStart = "${getExe cfg.package} --port ${toString cfg.port} --config ${configFile}";
|
||||
ExecStart = "${getExe cfg.package} --config ${configFile}";
|
||||
Restart = "on-failure";
|
||||
User = cfg.user;
|
||||
Group = cfg.group;
|
||||
|
|
|
|||
|
|
@ -1,57 +0,0 @@
|
|||
{ config, lib, ... }:
|
||||
|
||||
let
|
||||
cfg = config.services.nostr-relay;
|
||||
domain = config.networking.domain;
|
||||
subdomain = cfg.reverseProxy.subdomain;
|
||||
fqdn = if (cfg.reverseProxy.enable && subdomain != "") then "${subdomain}.${domain}" else domain;
|
||||
|
||||
inherit (lib)
|
||||
mkDefault
|
||||
mkIf
|
||||
;
|
||||
|
||||
inherit (lib.utils)
|
||||
mkReverseProxyOption
|
||||
;
|
||||
in
|
||||
{
|
||||
options.services.nostr-relay = {
|
||||
reverseProxy = mkReverseProxyOption "Nostr Relay" "nostr";
|
||||
};
|
||||
|
||||
config = mkIf cfg.enable {
|
||||
services.nostr-rs-relay = {
|
||||
settings = {
|
||||
network = {
|
||||
port = mkDefault 12849;
|
||||
host = mkDefault (if cfg.reverseProxy.enable then "127.0.0.1" else "0.0.0.0");
|
||||
};
|
||||
limits = {
|
||||
max_event_size = mkDefault 65536;
|
||||
max_subscriptions = mkDefault 20;
|
||||
max_filters = mkDefault 10;
|
||||
max_subid_length = mkDefault 128;
|
||||
max_event_tags = mkDefault 2000;
|
||||
max_content_length = mkDefault 32768;
|
||||
};
|
||||
federation = {
|
||||
enabled = mkDefault true;
|
||||
max_message_size = mkDefault 1048576;
|
||||
};
|
||||
database = {
|
||||
max_query_time_ms = mkDefault 5000;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
services.nginx.virtualHosts = mkIf cfg.reverseProxy.enable {
|
||||
"${fqdn}" = {
|
||||
enableACME = cfg.reverseProxy.forceSSL;
|
||||
forceSSL = cfg.reverseProxy.forceSSL;
|
||||
locations."/".proxyPass =
|
||||
"http://127.0.0.1:${toString config.services.nostr-rs-relay.settings.network.port}";
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
|
|
@ -10,10 +10,10 @@ let
|
|||
|
||||
image = pkgs.dockerTools.pullImage {
|
||||
imageName = "ghcr.io/open-webui/open-webui";
|
||||
imageDigest = "sha256:a7e4796ae894d1e2a0c1824860ade472f35c507608a01c3581377b5c19b0ed49";
|
||||
hash = "sha256-uhPlVXSxY6rGbYGvlPVV3zurmbI96mAHEuKKy9FFaD4=";
|
||||
imageDigest = "sha256:2deb90b0423473d8f97febced2e62b8fd898aa3eb61877bb3aa336370214c258";
|
||||
hash = "sha256-2cdKfvZGUyPUm7TFXcf5OcG9ey4BvOZPUOVim1S2C+s=";
|
||||
finalImageName = "ghcr.io/open-webui/open-webui";
|
||||
finalImageTag = "0.9.2";
|
||||
finalImageTag = "0.8.5";
|
||||
};
|
||||
|
||||
defaultEnv = {
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@ let
|
|||
|
||||
inherit (lib.utils)
|
||||
mkReverseProxyOption
|
||||
mkVirtualHost
|
||||
;
|
||||
in
|
||||
{
|
||||
|
|
@ -31,9 +32,8 @@ in
|
|||
systemd.tmpfiles.rules = [ "d ${cfg.dataDir} 0755 ${cfg.user} ${cfg.group} -" ];
|
||||
|
||||
services.nginx.virtualHosts = mkIf cfg.reverseProxy.enable {
|
||||
"${fqdn}" = {
|
||||
enableACME = cfg.reverseProxy.forceSSL;
|
||||
forceSSL = cfg.reverseProxy.forceSSL;
|
||||
"${cfg.virtualHost}" = mkVirtualHost {
|
||||
ssl = cfg.reverseProxy.forceSSL;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
|
|
|||
|
|
@ -1,17 +1,9 @@
|
|||
{
|
||||
config,
|
||||
lib,
|
||||
pkgs,
|
||||
...
|
||||
}:
|
||||
{ config, lib, ... }:
|
||||
|
||||
let
|
||||
cfg = config.services.tailscale;
|
||||
|
||||
inherit (lib)
|
||||
concatStrings
|
||||
filterAttrs
|
||||
mapAttrsToList
|
||||
mkIf
|
||||
mkOption
|
||||
optional
|
||||
|
|
@ -20,124 +12,39 @@ let
|
|||
in
|
||||
{
|
||||
options.services.tailscale = {
|
||||
tailnets = mkOption {
|
||||
default = { };
|
||||
type = types.attrsOf (
|
||||
types.submodule {
|
||||
options = {
|
||||
loginServer = mkOption {
|
||||
type = types.str;
|
||||
description = "Login server for this tailnet.";
|
||||
};
|
||||
authKeyFile = mkOption {
|
||||
type = types.nullOr types.str;
|
||||
default = null;
|
||||
description = "Path to auth key secret.";
|
||||
description = "The Tailscale login server to use.";
|
||||
};
|
||||
enableSSH = mkOption {
|
||||
type = types.bool;
|
||||
default = false;
|
||||
description = "Enable Tailscale SSH functionality.";
|
||||
};
|
||||
acceptDNS = mkOption {
|
||||
type = types.bool;
|
||||
default = true;
|
||||
};
|
||||
default = mkOption {
|
||||
type = types.bool;
|
||||
default = false;
|
||||
description = "Connect to this tailnet on boot.";
|
||||
};
|
||||
};
|
||||
}
|
||||
);
|
||||
description = "Enable Tailscale's MagicDNS and custom DNS configuration.";
|
||||
};
|
||||
};
|
||||
|
||||
config =
|
||||
let
|
||||
defaultTailnets = filterAttrs (_: t: t.default) cfg.tailnets;
|
||||
defaultTailnet =
|
||||
if defaultTailnets == { } then null else builtins.head (builtins.attrValues defaultTailnets);
|
||||
|
||||
entries = mapAttrsToList (name: tcfg: ''
|
||||
TAILNETS["${name}"]="${tcfg.loginServer}|${if tcfg.enableSSH then "true" else "false"}|${
|
||||
if tcfg.acceptDNS then "true" else "false"
|
||||
}|${if tcfg.authKeyFile != null then tcfg.authKeyFile else ""}"
|
||||
'') cfg.tailnets;
|
||||
|
||||
tailnetSwitchCli = pkgs.writeShellScriptBin "tailnet-switch" ''
|
||||
set -euo pipefail
|
||||
|
||||
TAILSCALE="${cfg.package}/bin/tailscale"
|
||||
|
||||
declare -A TAILNETS
|
||||
${concatStrings entries}
|
||||
|
||||
CHOICE="''${1:-}"
|
||||
|
||||
if [[ -z "$CHOICE" ]]; then
|
||||
if [[ -t 0 ]]; then
|
||||
CHOICE=$(printf '%s\n' "''${!TAILNETS[@]}" | sort | ${pkgs.fzf}/bin/fzf --prompt="Switch tailnet: ")
|
||||
else
|
||||
echo "Usage: tailnet-switch <tailnet-name>" >&2
|
||||
printf 'Available tailnets: %s\n' "''${!TAILNETS[@]}" >&2
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
|
||||
if [[ -z "''${TAILNETS[$CHOICE]+x}" ]]; then
|
||||
echo "Unknown tailnet: $CHOICE" >&2
|
||||
printf 'Available tailnets: %s\n' "''${!TAILNETS[@]}" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
IFS='|' read -r LOGIN_SERVER ENABLE_SSH ACCEPT_DNS AUTH_KEY_FILE <<< "''${TAILNETS[$CHOICE]}"
|
||||
|
||||
echo "Switching to: $CHOICE ($LOGIN_SERVER)"
|
||||
|
||||
"$TAILSCALE" down --accept-risk=lose-ssh 2>/dev/null || true
|
||||
"$TAILSCALE" logout 2>/dev/null || true
|
||||
|
||||
UP_FLAGS=("--login-server=$LOGIN_SERVER")
|
||||
[[ "$ENABLE_SSH" == "true" ]] && UP_FLAGS+=("--ssh")
|
||||
[[ "$ACCEPT_DNS" == "true" ]] && UP_FLAGS+=("--accept-dns")
|
||||
[[ -n "$AUTH_KEY_FILE" ]] && UP_FLAGS+=("--auth-key=$(cat "$AUTH_KEY_FILE")")
|
||||
|
||||
"$TAILSCALE" up "''${UP_FLAGS[@]}"
|
||||
|
||||
echo "Switched to tailnet: $CHOICE"
|
||||
'';
|
||||
in
|
||||
mkIf cfg.enable {
|
||||
assertions = [
|
||||
{
|
||||
assertion =
|
||||
(builtins.length (builtins.attrValues (filterAttrs (_: t: t.default) cfg.tailnets))) <= 1;
|
||||
message = "services.tailscale.tailnets: Only one tailnet can be set as default.";
|
||||
}
|
||||
{
|
||||
assertion = cfg.tailnets != { };
|
||||
message = "services.tailscale.tailnets: At least one tailnet must be defined.";
|
||||
}
|
||||
];
|
||||
|
||||
services.tailscale = mkIf (defaultTailnet != null) (
|
||||
with defaultTailnet;
|
||||
{
|
||||
inherit authKeyFile;
|
||||
extraSetFlags = optional enableSSH "--ssh" ++ optional acceptDNS "--accept-dns";
|
||||
config = mkIf cfg.enable {
|
||||
services.tailscale = {
|
||||
authKeyFile = config.sops.secrets."tailscale/auth-key".path;
|
||||
extraSetFlags = optional cfg.enableSSH "--ssh" ++ optional cfg.acceptDNS "--accept-dns";
|
||||
extraUpFlags = [
|
||||
"--login-server=${loginServer}"
|
||||
"--login-server=${cfg.loginServer}"
|
||||
]
|
||||
++ optional enableSSH "--ssh"
|
||||
++ optional acceptDNS "--accept-dns";
|
||||
}
|
||||
);
|
||||
++ optional cfg.enableSSH "--ssh"
|
||||
++ optional cfg.acceptDNS "--accept-dns";
|
||||
};
|
||||
|
||||
environment.systemPackages = [ tailnetSwitchCli ];
|
||||
|
||||
environment.shellAliases.ts = "${cfg.package}/bin/tailscale";
|
||||
environment.shellAliases = {
|
||||
ts = "${cfg.package}/bin/tailscale";
|
||||
};
|
||||
|
||||
networking.firewall.trustedInterfaces = [ cfg.interfaceName ];
|
||||
|
||||
sops.secrets."tailscale/auth-key" = { };
|
||||
};
|
||||
}
|
||||
|
|
|
|||
55
modules/nixos/zfs/default.nix
Normal file
55
modules/nixos/zfs/default.nix
Normal file
|
|
@ -0,0 +1,55 @@
|
|||
{
|
||||
config,
|
||||
pkgs,
|
||||
lib,
|
||||
...
|
||||
}:
|
||||
|
||||
# Set `networking.hostId` to:
|
||||
# $ head -c 8 /etc/machine-id
|
||||
|
||||
# Mark datasets to snapshot:
|
||||
# $ sudo zfs set com.sun:auto-snapshot:daily=true dpool/data/backup
|
||||
|
||||
# Generate SSH key for replication (empty passphrase):
|
||||
# $ sudo -i ssh-keygen -t rsa -b 4096 -f /root/.ssh/zfs-replication
|
||||
|
||||
let
|
||||
cfg = config.services.zfs;
|
||||
|
||||
inherit (lib) mkDefault mkForce;
|
||||
in
|
||||
{
|
||||
boot.supportedFilesystems = [ "zfs" ];
|
||||
boot.loader.systemd-boot.enable = mkForce false;
|
||||
boot.loader.grub.enable = mkForce true;
|
||||
boot.loader.grub.zfsSupport = mkForce true;
|
||||
|
||||
services.zfs.trim = {
|
||||
enable = mkDefault true;
|
||||
interval = mkDefault "weekly";
|
||||
};
|
||||
|
||||
services.zfs.scrub = {
|
||||
enable = mkDefault true;
|
||||
interval = mkDefault "monthly";
|
||||
};
|
||||
|
||||
services.zfs.autoSnapshot = {
|
||||
enable = mkDefault true;
|
||||
flags = mkDefault "-k -p --utc";
|
||||
frequent = mkDefault 0;
|
||||
hourly = mkDefault 24;
|
||||
daily = mkDefault 7;
|
||||
weekly = mkDefault 4;
|
||||
monthly = mkDefault 0;
|
||||
};
|
||||
|
||||
services.zfs.autoReplication = {
|
||||
username = mkDefault "root";
|
||||
identityFilePath = mkDefault "/root/.ssh/zfs-replication";
|
||||
followDelete = mkDefault true;
|
||||
};
|
||||
|
||||
environment.systemPackages = with pkgs; [ lz4 ];
|
||||
}
|
||||
151
modules/nixos/zfs/disks.sh
Normal file
151
modules/nixos/zfs/disks.sh
Normal file
|
|
@ -0,0 +1,151 @@
|
|||
#!/usr/bin/env bash
|
||||
declare -a SSDs=(
|
||||
# '/dev/disk/by-id/abc123'
|
||||
)
|
||||
|
||||
declare -a HDDs=(
|
||||
# '/dev/disk/by-id/def456'
|
||||
)
|
||||
|
||||
declare -a DATA_DATASETS=(
|
||||
# 'dataset'
|
||||
)
|
||||
|
||||
MNT='/mnt'
|
||||
SWAP_GB=32
|
||||
|
||||
# Helper function to wait for devices
|
||||
wait_for_device() {
|
||||
local device=$1
|
||||
echo "Waiting for device: $device ..."
|
||||
while [[ ! -e $device ]]; do
|
||||
sleep 1
|
||||
done
|
||||
echo "Device $device is ready."
|
||||
}
|
||||
|
||||
# Function to install a package if it's not already installed
|
||||
install_if_missing() {
|
||||
local cmd="$1"
|
||||
local package="$2"
|
||||
if ! command -v "$cmd" &> /dev/null; then
|
||||
echo "$cmd not found, installing $package..."
|
||||
nix-env -iA "nixos.$package"
|
||||
fi
|
||||
}
|
||||
|
||||
install_if_missing "sgdisk" "gptfdisk"
|
||||
install_if_missing "partprobe" "parted"
|
||||
|
||||
# Ensure swap parts are off
|
||||
swapoff --all
|
||||
udevadm settle
|
||||
|
||||
### SSDs ###
|
||||
echo "Setting up SSDs..."
|
||||
|
||||
# Wait for SSD devices to be ready
|
||||
for ssd in "${SSDs[@]}"; do
|
||||
wait_for_device "$ssd"
|
||||
done
|
||||
|
||||
# Wipe and partition SSDs
|
||||
for i in "${!SSDs[@]}"; do
|
||||
ssd="${SSDs[$i]}"
|
||||
ssd_num=$((i + 1))
|
||||
|
||||
echo "Processing SSD $ssd_num: $ssd"
|
||||
|
||||
# Wipe filesystems
|
||||
wipefs -a "$ssd"
|
||||
|
||||
# Clear part tables
|
||||
sgdisk --zap-all "$ssd"
|
||||
|
||||
# Partition disk
|
||||
sgdisk -n1:1M:+1G -t1:EF00 -c1:BOOT$ssd_num "$ssd"
|
||||
sgdisk -n2:0:+"$SWAP_GB"G -t2:8200 -c2:SWAP$ssd_num "$ssd"
|
||||
sgdisk -n3:0:0 -t3:BF00 -c3:ROOT$ssd_num "$ssd"
|
||||
|
||||
partprobe -s "$ssd"
|
||||
udevadm settle
|
||||
wait_for_device "${ssd}-part3"
|
||||
done
|
||||
|
||||
# Create root pool
|
||||
echo "Creating root pool..."
|
||||
zpool create -f -o ashift=12 -o autotrim=on -R "$MNT" -O acltype=posixacl -O canmount=off -O dnodesize=auto -O normalization=formD -O relatime=on -O xattr=sa -O mountpoint=none rpool mirror "${SSDs[0]}"-part3 "${SSDs[1]}"-part3
|
||||
|
||||
# Create and mount root system container
|
||||
zfs create -o canmount=noauto -o mountpoint=legacy rpool/root
|
||||
mount -o X-mount.mkdir -t zfs rpool/root "$MNT"
|
||||
|
||||
# Create root datasets
|
||||
declare -a ROOT_DATASETS=('home' 'nix' 'tmp' 'var')
|
||||
for dataset in "${ROOT_DATASETS[@]}"; do
|
||||
zfs create -o mountpoint=legacy "rpool/$dataset"
|
||||
mount -o X-mount.mkdir -t zfs "rpool/$dataset" "$MNT/$dataset"
|
||||
done
|
||||
|
||||
# Format boot and swap partitions
|
||||
for i in "${!SSDs[@]}"; do
|
||||
ssd="${SSDs[$i]}"
|
||||
ssd_num=$((i + 1))
|
||||
|
||||
mkfs.vfat -F 32 -n BOOT$ssd_num "${ssd}"-part1
|
||||
mkswap -L SWAP$ssd_num "${ssd}"-part2
|
||||
swapon -L SWAP$ssd_num
|
||||
done
|
||||
|
||||
# Mount first boot partition
|
||||
mount -t vfat -o fmask=0077,dmask=0077,iocharset=iso8859-1,X-mount.mkdir -L BOOT1 "$MNT"/boot
|
||||
|
||||
### HDDs ###
|
||||
echo "Setting up HDDs..."
|
||||
|
||||
# Wait for HDD devices to be ready
|
||||
for hdd in "${HDDs[@]}"; do
|
||||
wait_for_device "$hdd"
|
||||
done
|
||||
|
||||
# Wipe and partition HDDs
|
||||
for i in "${!HDDs[@]}"; do
|
||||
hdd="${HDDs[$i]}"
|
||||
hdd_num=$((i + 1))
|
||||
|
||||
echo "Processing HDD $hdd_num: $hdd"
|
||||
|
||||
wipefs -a "$hdd"
|
||||
sgdisk --zap-all "$hdd"
|
||||
sgdisk -n1:0:0 -t1:BF00 -c1:DATA$hdd_num "$hdd"
|
||||
done
|
||||
|
||||
udevadm settle
|
||||
|
||||
# Wait for all HDD partitions to appear
|
||||
for hdd in "${HDDs[@]}"; do
|
||||
wait_for_device "${hdd}-part1"
|
||||
done
|
||||
|
||||
# Create data pool
|
||||
echo "Creating data pool..."
|
||||
mkdir -p "$MNT"/data
|
||||
|
||||
hdd_partitions=()
|
||||
for hdd in "${HDDs[@]}"; do
|
||||
hdd_partitions+=("${hdd}-part1")
|
||||
done
|
||||
|
||||
zpool create -f -o ashift=12 -o autotrim=on -R "$MNT" -O acltype=posixacl -O xattr=sa -O dnodesize=auto -O compression=lz4 -O normalization=formD -O relatime=on -O mountpoint=none dpool raidz "${hdd_partitions[@]}"
|
||||
|
||||
# Create and mount data root container
|
||||
zfs create -o canmount=noauto -o mountpoint=legacy dpool/data
|
||||
mount -o X-mount.mkdir -t zfs dpool/data "$MNT"/data
|
||||
|
||||
# Create and mount data datasets
|
||||
for dataset in "${DATA_DATASETS[@]}"; do
|
||||
zfs create -o mountpoint=legacy "dpool/data/$dataset"
|
||||
mount -o X-mount.mkdir -t zfs "dpool/data/$dataset" "$MNT/data/$dataset"
|
||||
done
|
||||
|
||||
echo "Setup complete."
|
||||
|
|
@ -32,8 +32,6 @@ in
|
|||
};
|
||||
};
|
||||
|
||||
nix.settings.warn-dirty = mkDefault false;
|
||||
|
||||
# fallback quickly if substituters are not available.
|
||||
nix.settings.connect-timeout = mkDefault 5;
|
||||
nix.settings.fallback = true;
|
||||
|
|
|
|||
|
|
@ -6,13 +6,13 @@
|
|||
|
||||
python3.pkgs.buildPythonApplication rec {
|
||||
pname = "arxiv-mcp-server";
|
||||
version = "0.4.12";
|
||||
version = "0.3.1";
|
||||
pyproject = true;
|
||||
|
||||
src = fetchPypi {
|
||||
pname = "arxiv_mcp_server";
|
||||
inherit version;
|
||||
hash = "sha256-khY63SfUKgNjyACNESEQpY9q3uJSlLhuJBEaBKGmZy8=";
|
||||
hash = "sha256-yGNetU7el6ZXsavD8uvO17OZtaPuYgzkxiVEk402GUs=";
|
||||
};
|
||||
|
||||
build-system = [
|
||||
|
|
|
|||
|
|
@ -11,17 +11,17 @@
|
|||
|
||||
rustPlatform.buildRustPackage rec {
|
||||
pname = "baibot";
|
||||
version = "1.18.0";
|
||||
version = "1.14.3";
|
||||
|
||||
src = fetchFromGitHub {
|
||||
owner = "etkecc";
|
||||
repo = "baibot";
|
||||
rev = "v${version}";
|
||||
hash = "sha256-TwtN8tEml/z0Js78jjWzEYV58Dg8a5YKxdEU9hBDtNs=";
|
||||
hash = "sha256-bFUijsvwUQhISjWVoVvoDXNSDPaWZTunqUfxfgaxclM=";
|
||||
};
|
||||
|
||||
useFetchCargoVendor = true;
|
||||
cargoHash = "sha256-2TJsFT+I7JG1DauEOvB8HluMDb1vW0qXD/mzzSlAfew=";
|
||||
cargoHash = "sha256-/7KSCVWuxTk7gKOYxE/uQ5T0BnYlDYWOvdFXEiU9mB0=";
|
||||
|
||||
nativeBuildInputs = [
|
||||
pkg-config
|
||||
|
|
|
|||
|
|
@ -6,13 +6,13 @@
|
|||
|
||||
python3.pkgs.buildPythonApplication rec {
|
||||
pname = "blender-mcp";
|
||||
version = "1.5.6";
|
||||
version = "1.5.5";
|
||||
pyproject = true;
|
||||
|
||||
src = fetchPypi {
|
||||
pname = "blender_mcp";
|
||||
inherit version;
|
||||
hash = "sha256-9aBGQcMC1ustj3H1WgRFCha6fk+XSASIzcZr6Rrgif4=";
|
||||
hash = "sha256-n8bYnrDVLe5zPvg8rbGgh5U5AeIm/DA6aPgmxS68d7g=";
|
||||
};
|
||||
|
||||
build-system = [
|
||||
|
|
|
|||
|
|
@ -11,20 +11,15 @@
|
|||
cppman = pkgs.callPackage ./cppman { };
|
||||
fetcher-mcp = pkgs.callPackage ./fetcher-mcp { };
|
||||
freecad-mcp = pkgs.callPackage ./freecad-mcp { };
|
||||
jirafeau = pkgs.callPackage ./jirafeau { };
|
||||
jirafeau-cli = pkgs.callPackage ./jirafeau-cli { };
|
||||
kicad-mcp = pkgs.callPackage ./kicad-mcp { };
|
||||
mcpo = pkgs.callPackage ./mcpo { };
|
||||
nerdlog = pkgs.callPackage ./nerdlog { };
|
||||
pass2bw = pkgs.callPackage ./pass2bw { };
|
||||
pyman = pkgs.callPackage ./pyman { };
|
||||
quicknote = pkgs.callPackage ./quicknote { };
|
||||
synapse_change_display_name = pkgs.callPackage ./synapse_change_display_name { };
|
||||
synix-docs = pkgs.callPackage ./synix-docs { };
|
||||
tinyfugue = pkgs.callPackage ./tinyfugue { };
|
||||
trelis-gitingest-mcp = pkgs.callPackage ./trelis-gitingest-mcp { };
|
||||
tunerstudio = pkgs.callPackage ./tunerstudio { };
|
||||
|
||||
# marker-pdf = pkgs.callPackage ./marker-pdf { }; # FIXME
|
||||
# openmv-ide = pkgs.callPackage ./openmv-ide { }; # FIXME
|
||||
}
|
||||
|
|
|
|||
|
|
@ -25,9 +25,9 @@ let
|
|||
}
|
||||
];
|
||||
in
|
||||
buildNpmPackage {
|
||||
buildNpmPackage rec {
|
||||
pname = "fetcher-mcp";
|
||||
version = "0.3.9";
|
||||
version = "0.3.6";
|
||||
|
||||
src = fetchFromGitHub {
|
||||
owner = "jae-jae";
|
||||
|
|
|
|||
|
|
@ -6,13 +6,13 @@
|
|||
|
||||
python3.pkgs.buildPythonApplication rec {
|
||||
pname = "freecad-mcp";
|
||||
version = "0.1.17";
|
||||
version = "0.1.16";
|
||||
pyproject = true;
|
||||
|
||||
src = fetchPypi {
|
||||
pname = "freecad_mcp";
|
||||
inherit version;
|
||||
hash = "sha256-DugQWGZizIXO27cjzfyidNTyyahN1BTcDNTl4DHWqN0=";
|
||||
hash = "sha256-eFt7UgJw56C2zY8Vznrg8L0a5nvP0xtiW1oJuJ/fL3Y=";
|
||||
};
|
||||
|
||||
build-system = [
|
||||
|
|
|
|||
|
|
@ -1,20 +0,0 @@
|
|||
{
|
||||
writeShellApplication,
|
||||
coreutils,
|
||||
curl,
|
||||
...
|
||||
}:
|
||||
|
||||
let
|
||||
name = "jirafeau-cli";
|
||||
text = builtins.readFile ./${name}.sh;
|
||||
in
|
||||
writeShellApplication {
|
||||
inherit name text;
|
||||
meta.mainProgram = name;
|
||||
|
||||
runtimeInputs = [
|
||||
coreutils
|
||||
curl
|
||||
];
|
||||
}
|
||||
|
|
@ -1,152 +0,0 @@
|
|||
#!/bin/bash
|
||||
|
||||
# This script has been auto-generated by Jirafeau but you can still edit options below.
|
||||
|
||||
# Config begin
|
||||
proxy='' # Or set JIRAFEAU_PROXY.
|
||||
url='' # Or set JIRAFEAU_URL.
|
||||
time='month' # Or set JIRAFEAU_TIME.
|
||||
one_time='' # Or set JIRAFEAU_ONE_TIME.
|
||||
upload_password='' # Or set JIRAFEAU_UPLOAD_PASSWD
|
||||
# Config end
|
||||
|
||||
if [ -n "${JIRAFEAU_PROXY:-}" ]; then
|
||||
proxy="$JIRAFEAU_PROXY"
|
||||
fi
|
||||
|
||||
if [ -n "${JIRAFEAU_URL:-}" ]; then
|
||||
url="$JIRAFEAU_URL"
|
||||
fi
|
||||
|
||||
if [ -z "$url" ]; then
|
||||
echo "Please set url in script parameters or export JIRAFEAU_URL"
|
||||
fi
|
||||
|
||||
if [ -n "${JIRAFEAU_TIME:-}" ]; then
|
||||
time="$JIRAFEAU_TIME"
|
||||
fi
|
||||
|
||||
if [ -n "${JIRAFEAU_ONE_TIME:-}" ]; then
|
||||
one_time='1'
|
||||
fi
|
||||
|
||||
if [ -n "${JIRAFEAU_UPLOAD_PASSWD:-}" ]; then
|
||||
upload_password="$JIRAFEAU_UPLOAD_PASSWD"
|
||||
fi
|
||||
|
||||
if [ -z "${2:-}" ]; then
|
||||
echo "Jirafeau Bash Script 4.7.1"
|
||||
echo "--------------------------"
|
||||
echo "Usage:"
|
||||
echo " $0 OPTIONS"
|
||||
echo
|
||||
echo "Options:"
|
||||
echo " $0 send FILE [PASSWORD]"
|
||||
echo " $0 get URL [PASSWORD]"
|
||||
echo " $0 delete URL"
|
||||
echo
|
||||
echo "Global variables to export:"
|
||||
echo " JIRAFEAU_PROXY: Domain and port of proxy server, eg. »proxyserver.example.com:3128«"
|
||||
echo " JIRAFEAU_URL : URI to Jirafeau installation with trailing slash, eg. »https://example.com/jirafeau/«"
|
||||
echo " JIRAFEAU_TIME : expiration time, eg. »minute«, »hour«, »day«, »week«, fortnight, »month«, »quarter«, »year« or »none«"
|
||||
echo " JIRAFEAU_ONE_TIME : self-destroy after first download, eg. »1« to enable or »« (empty) to disable"
|
||||
echo " JIRAFEAU_UPLOAD_PASSWD : upload password"
|
||||
|
||||
exit 0
|
||||
fi
|
||||
|
||||
proxy_args=()
|
||||
if [ -n "$proxy" ]; then
|
||||
proxy_args=(-x "$proxy")
|
||||
fi
|
||||
|
||||
options=()
|
||||
if [ -n "$one_time" ]; then
|
||||
options+=(-F one_time_download=1)
|
||||
fi
|
||||
|
||||
if [ -n "$upload_password" ]; then
|
||||
options+=(-F "upload_password=$upload_password")
|
||||
fi
|
||||
|
||||
password=''
|
||||
if [ -n "${3:-}" ]; then
|
||||
password="$3"
|
||||
options+=(-F "key=$password")
|
||||
fi
|
||||
|
||||
apipage='script.php'
|
||||
downloadpage='f.php'
|
||||
|
||||
if [ "$1" == "send" ]; then
|
||||
if [ ! -f "$2" ]; then
|
||||
echo "File \"$2\" does not exist."
|
||||
exit
|
||||
fi
|
||||
|
||||
# Get result
|
||||
res=$(curl -X POST --http1.0 "${proxy_args[@]}" "${options[@]}" \
|
||||
-F "time=$time" \
|
||||
-F "file=@$2" \
|
||||
"${url}${apipage}")
|
||||
|
||||
if [[ "$res" == Error* ]]; then
|
||||
echo "Error while uploading."
|
||||
echo "$res"
|
||||
exit
|
||||
fi
|
||||
|
||||
# Not using head or tail to minimise command dependencies
|
||||
code=$(cnt=0; echo "$res" | while read -r l; do
|
||||
if [[ "$cnt" == "0" ]]; then
|
||||
echo "$l"
|
||||
fi
|
||||
cnt=$(( cnt + 1 ))
|
||||
done)
|
||||
del_code=$(cnt=0; echo "$res" | while read -r l; do
|
||||
if [[ "$cnt" == "1" ]]; then
|
||||
echo "$l"
|
||||
fi
|
||||
cnt=$(( cnt + 1 ))
|
||||
done)
|
||||
key_code=$(cnt=0; echo "$res" | while read -r l; do
|
||||
if [[ "$cnt" == "2" ]]; then
|
||||
echo "$l"
|
||||
fi
|
||||
cnt=$(( cnt + 1 ))
|
||||
done)
|
||||
|
||||
echo
|
||||
echo "Download page:"
|
||||
if [[ $key_code ]]; then
|
||||
echo " ${url}${downloadpage}?h=$code&k=$key_code"
|
||||
else
|
||||
echo " ${url}${downloadpage}?h=$code"
|
||||
fi
|
||||
echo "Direct download:"
|
||||
if [[ $key_code ]]; then
|
||||
echo " ${url}${downloadpage}?h=$code&k=$key_code&d=1"
|
||||
else
|
||||
echo " ${url}${downloadpage}?h=$code&d=1"
|
||||
fi
|
||||
echo "Delete link:"
|
||||
echo " ${url}${downloadpage}?h=$code&d=$del_code"
|
||||
echo
|
||||
echo "Download via API:"
|
||||
if [[ $key_code ]]; then
|
||||
echo " ${0} get ${url}${apipage}?h=$code&k=$key_code [PASSWORD]"
|
||||
else
|
||||
echo " ${0} get ${url}${apipage}?h=$code [PASSWORD]"
|
||||
fi
|
||||
echo "Delete via API:"
|
||||
echo " ${0} delete \"${url}${downloadpage}?h=$code&d=$del_code\""
|
||||
|
||||
elif [ "$1" == "get" ]; then
|
||||
if [ -z "$password" ]; then
|
||||
curl "${proxy_args[@]}" -OJ "$2"
|
||||
else
|
||||
curl "${proxy_args[@]}" -OJ -X POST -F "key=$password" "$2"
|
||||
fi
|
||||
elif [ "$1" == "delete" ]; then
|
||||
curl "${proxy_args[@]}" "$2" --data-raw "do_delete=1%2F" | grep "div class" | sed -e "s/<[^>]\+>//g"
|
||||
fi
|
||||
|
|
@ -1,43 +0,0 @@
|
|||
{
|
||||
lib,
|
||||
stdenv,
|
||||
fetchFromGitLab,
|
||||
writeText,
|
||||
nixosTests,
|
||||
}:
|
||||
|
||||
let
|
||||
localConfig = writeText "config.local.php" ''
|
||||
<?php
|
||||
return require(getenv('JIRAFEAU_CONFIG'));
|
||||
?>
|
||||
'';
|
||||
in
|
||||
stdenv.mkDerivation rec {
|
||||
pname = "jirafeau";
|
||||
version = "4.7.1";
|
||||
|
||||
src = fetchFromGitLab {
|
||||
owner = "jirafeau";
|
||||
repo = "Jirafeau";
|
||||
rev = version;
|
||||
hash = "sha256-jXUO+tj6VFNjJkT0vkCCtG7yNWf3QeCx7izZPekAng8=";
|
||||
};
|
||||
|
||||
installPhase = ''
|
||||
mkdir $out
|
||||
cp -r * $out/
|
||||
cp ${localConfig} $out/lib/config.local.php
|
||||
'';
|
||||
|
||||
passthru.tests = { inherit (nixosTests) jirafeau; };
|
||||
|
||||
meta = {
|
||||
description = "Jirafeau: a simple way to upload a file";
|
||||
homepage = "https://gitlab.com/jirafeau/Jirafeau";
|
||||
changelog = "https://gitlab.com/jirafeau/Jirafeau/-/blob/${src.rev}/CHANGELOG.md";
|
||||
license = lib.licenses.agpl3Plus;
|
||||
mainProgram = "jirafeau";
|
||||
platforms = lib.platforms.all;
|
||||
};
|
||||
}
|
||||
|
|
@ -35,11 +35,11 @@ buildNpmPackage rec {
|
|||
src = fetchFromGitHub {
|
||||
owner = "mixelpixx";
|
||||
repo = "KiCAD-MCP-Server";
|
||||
rev = "216d3f189d194cdd539b274264b8b7ec00cbb13e";
|
||||
hash = "sha256-73yDzYlWMDnnytf/IcUuwQp/P7YYaxrNr+JsGrgMI40=";
|
||||
rev = "b5a1483fc20dd1201a1d275522904aac914157e8";
|
||||
hash = "sha256-63Ef34YjniMY+ZPpDrWZpPx8bUbNA0XE+7Jlgm8KJv8=";
|
||||
};
|
||||
|
||||
npmDepsHash = "sha256-qR43NvSK28RLt5sL9BZQzSyFRszYMt2CC0wTs9jf/hU=";
|
||||
npmDepsHash = "sha256-nz73qj8CK2LyFixoF14ET2wq407YyuJUw/4VTDc80cQ=";
|
||||
|
||||
buildScript = "build";
|
||||
|
||||
|
|
|
|||
|
|
@ -7,14 +7,14 @@
|
|||
|
||||
python3.pkgs.buildPythonApplication rec {
|
||||
pname = "mcpo";
|
||||
version = "0.0.20";
|
||||
version = "0.0.19";
|
||||
pyproject = true;
|
||||
|
||||
src = fetchFromGitHub {
|
||||
owner = "open-webui";
|
||||
repo = "mcpo";
|
||||
rev = "v${version}";
|
||||
hash = "sha256-tA1KdcfmNPuqPbwE66jRY85tsrOKjPImsxSoGsW5ZD4=";
|
||||
hash = "sha256-ZfTVMrXXEsEKHmeG4850Hq3MEpQA/3WMpAVZS0zvp1I=";
|
||||
};
|
||||
|
||||
build-system = [
|
||||
|
|
|
|||
|
|
@ -1,83 +0,0 @@
|
|||
{
|
||||
lib,
|
||||
buildGoModule,
|
||||
fetchFromGitHub,
|
||||
stdenv,
|
||||
darwin,
|
||||
xorg,
|
||||
pkg-config,
|
||||
wayland,
|
||||
libGL,
|
||||
libxkbcommon,
|
||||
makeWrapper,
|
||||
}:
|
||||
|
||||
buildGoModule rec {
|
||||
pname = "nerdlog";
|
||||
version = "1.10.0";
|
||||
|
||||
src = fetchFromGitHub {
|
||||
owner = "dimonomid";
|
||||
repo = "nerdlog";
|
||||
rev = "v${version}";
|
||||
hash = "sha256-XlzWNeyd+Ar4ArFcN1wkQ0aod6ckAiIb12odK7cf4+s=";
|
||||
};
|
||||
|
||||
vendorHash = "sha256-hvv0dsE1yz85VLaBOE7RWbux8L8kVTihcA1HyyHRYAM=";
|
||||
|
||||
subPackages = [
|
||||
"cmd/nerdlog"
|
||||
"cmd/generate_syslog"
|
||||
];
|
||||
|
||||
doCheck = false;
|
||||
|
||||
nativeBuildInputs = [
|
||||
pkg-config
|
||||
makeWrapper
|
||||
];
|
||||
|
||||
buildInputs =
|
||||
lib.optionals stdenv.isDarwin [
|
||||
darwin.apple_sdk.frameworks.Cocoa
|
||||
]
|
||||
++ lib.optionals stdenv.isLinux [
|
||||
xorg.libX11
|
||||
xorg.libXext
|
||||
xorg.libXfixes
|
||||
wayland
|
||||
libGL
|
||||
libxkbcommon
|
||||
];
|
||||
|
||||
postInstall = lib.optionalString stdenv.isLinux ''
|
||||
wrapProgram $out/bin/nerdlog \
|
||||
--prefix LD_LIBRARY_PATH : ${
|
||||
lib.makeLibraryPath [
|
||||
xorg.libX11
|
||||
xorg.libXext
|
||||
xorg.libXfixes
|
||||
wayland
|
||||
libGL
|
||||
libxkbcommon
|
||||
]
|
||||
}
|
||||
'';
|
||||
|
||||
ldflags = [
|
||||
"-s"
|
||||
"-w"
|
||||
"-X=github.com/dimonomid/nerdlog/version.version=${version}"
|
||||
"-X=github.com/dimonomid/nerdlog/version.commit=${src.rev}"
|
||||
"-X=github.com/dimonomid/nerdlog/version.date=1970-01-01T00:00:00Z"
|
||||
"-X=github.com/dimonomid/nerdlog/version.builtBy=goreleaser"
|
||||
];
|
||||
|
||||
meta = {
|
||||
description = "Nerdlog: fast, remote-first, multi-host TUI log viewer with timeline histogram and no central server";
|
||||
homepage = "https://github.com/dimonomid/nerdlog";
|
||||
changelog = "https://github.com/dimonomid/nerdlog/blob/${src.rev}/CHANGELOG.md";
|
||||
license = lib.licenses.bsd2;
|
||||
mainProgram = "nerdlog";
|
||||
};
|
||||
}
|
||||
|
|
@ -1,132 +0,0 @@
|
|||
{
|
||||
lib,
|
||||
stdenv,
|
||||
fetchurl,
|
||||
|
||||
at-spi2-atk,
|
||||
autoPatchelfHook,
|
||||
cairo,
|
||||
cups,
|
||||
dbus,
|
||||
fontconfig,
|
||||
freetype,
|
||||
gdk-pixbuf,
|
||||
glib,
|
||||
gtk3,
|
||||
libGL,
|
||||
libdrm,
|
||||
libxcb-cursor,
|
||||
libxkbcommon,
|
||||
makeWrapper,
|
||||
pango,
|
||||
wayland,
|
||||
xorg,
|
||||
zlib,
|
||||
}:
|
||||
|
||||
stdenv.mkDerivation rec {
|
||||
pname = "openmv-ide";
|
||||
version = "4.8.9";
|
||||
|
||||
src = fetchurl {
|
||||
url = "https://github.com/openmv/openmv-ide/releases/download/v${version}/openmv-ide-linux-x86_64-${version}.tar.gz";
|
||||
hash = "sha256-D0Uunb6IIX8gkirZIISjjhvrrCsR5bgRBcXidtjN/n0=";
|
||||
};
|
||||
|
||||
nativeBuildInputs = [
|
||||
autoPatchelfHook
|
||||
makeWrapper
|
||||
];
|
||||
|
||||
buildInputs = [
|
||||
at-spi2-atk
|
||||
cairo
|
||||
cups
|
||||
dbus.lib
|
||||
fontconfig
|
||||
freetype
|
||||
gdk-pixbuf
|
||||
glib
|
||||
gtk3
|
||||
libGL
|
||||
libdrm
|
||||
libxcb-cursor
|
||||
libxkbcommon
|
||||
pango
|
||||
stdenv.cc.cc.lib
|
||||
wayland
|
||||
xorg.libX11
|
||||
xorg.libxcb
|
||||
xorg.xcbutil
|
||||
xorg.xcbutilimage
|
||||
xorg.xcbutilkeysyms
|
||||
xorg.xcbutilrenderutil
|
||||
xorg.xcbutilwm
|
||||
zlib
|
||||
];
|
||||
|
||||
autoPatchelfIgnoreMissingDeps = [
|
||||
"libQt6Designer.so.6"
|
||||
"libQt6Labs*.so.6"
|
||||
"libQt6OpenGLWidgets.so.6"
|
||||
"libQt6Qml*.so.6"
|
||||
"libQt6Quick*.so.6"
|
||||
"libQt6ShaderTools.so.6"
|
||||
"libgssapi_krb5.so.2"
|
||||
"libicudata.so.56"
|
||||
"libicui18n.so.56"
|
||||
"libicuuc.so.56"
|
||||
"libmysqlclient.so.21"
|
||||
"libodbc.so.2"
|
||||
"libpq.so.5"
|
||||
];
|
||||
|
||||
dontAutoPatchelf = true;
|
||||
dontBuild = true;
|
||||
dontConfigure = true;
|
||||
dontStrip = true;
|
||||
|
||||
installPhase = ''
|
||||
runHook preInstall
|
||||
|
||||
mkdir -p $out/share/openmv-ide
|
||||
cp -r bin lib share $out/share/openmv-ide/
|
||||
|
||||
chmod -R u+w $out/share/openmv-ide/
|
||||
|
||||
mkdir -p $out/share/applications
|
||||
cp share/applications/io.openmv.openmvide.desktop $out/share/applications/
|
||||
|
||||
mkdir -p $out/share/icons
|
||||
cp -r share/icons/hicolor $out/share/icons/
|
||||
|
||||
substituteInPlace $out/share/applications/io.openmv.openmvide.desktop \
|
||||
--replace "Exec=openmvide" "Exec=$out/bin/openmvide"
|
||||
|
||||
mkdir -p $out/bin
|
||||
makeWrapper $out/share/openmv-ide/bin/openmvide $out/bin/openmvide \
|
||||
--prefix LD_LIBRARY_PATH : "$out/share/openmv-ide/lib:$out/share/openmv-ide/lib/qtcreator:$out/share/openmv-ide/lib/Qt/lib" \
|
||||
--add-flags "-user-library-path \"\$LD_LIBRARY_PATH\""
|
||||
|
||||
runHook postInstall
|
||||
'';
|
||||
|
||||
postFixup = ''
|
||||
addAutoPatchelfSearchPath $out/share/openmv-ide/lib/Qt/lib
|
||||
addAutoPatchelfSearchPath $out/share/openmv-ide/lib/qtcreator
|
||||
|
||||
# skip embedded third-party toolchains and tools under share/
|
||||
autoPatchelf -- \
|
||||
$out/share/openmv-ide/bin \
|
||||
$out/share/openmv-ide/lib
|
||||
'';
|
||||
|
||||
meta = {
|
||||
description = "QtCreator based IDE for the OpenMV Cam";
|
||||
homepage = "https://openmv.io/";
|
||||
license = lib.licenses.gpl3Plus;
|
||||
mainProgram = "openmvide";
|
||||
platforms = [ "x86_64-linux" ];
|
||||
sourceProvenance = [ lib.sourceTypes.binaryNativeCode ];
|
||||
};
|
||||
}
|
||||
|
|
@ -43,20 +43,13 @@ def process_csv(input_file, output_file):
|
|||
if col not in new_row:
|
||||
new_row[col] = default_val
|
||||
|
||||
folder = new_row.get('folder', '')
|
||||
name = new_row.get('name', '')
|
||||
if folder.startswith('www') and name:
|
||||
if not name.startswith('http://') and not name.startswith('https://'):
|
||||
new_row['login_uri'] = f'https://{name}'
|
||||
else:
|
||||
new_row['login_uri'] = name
|
||||
|
||||
if new_row['notes']:
|
||||
new_row['notes'] = new_row['notes'].replace('\n', ' ').replace('\r', ' ')
|
||||
new_row['notes'] = re.sub(r'\s+', ' ', new_row['notes']).strip()
|
||||
|
||||
notes = new_row['notes']
|
||||
if notes:
|
||||
# Look for pattern: "login: USERNAME"
|
||||
match = re.search(r'login:\s*(\S+)', notes, re.IGNORECASE)
|
||||
if match:
|
||||
username = match.group(1)
|
||||
|
|
|
|||
|
|
@ -2,8 +2,6 @@
|
|||
stdenv,
|
||||
lib,
|
||||
makeWrapper,
|
||||
pass,
|
||||
pass2csv,
|
||||
python3,
|
||||
...
|
||||
}:
|
||||
|
|
@ -22,18 +20,13 @@ stdenv.mkDerivation rec {
|
|||
installPhase = ''
|
||||
mkdir -p $out/bin
|
||||
|
||||
cp ${src}/pass2bw.sh $out/bin/${pname}
|
||||
sed -e "s|python ./convert_csvs.py|python $out/bin/convert_csvs.py|" \
|
||||
${src}/${pname}.sh > $out/bin/${pname}
|
||||
chmod +x $out/bin/${pname}
|
||||
|
||||
cp ${src}/convert_csvs.py $out/bin/
|
||||
|
||||
wrapProgram $out/bin/${pname} \
|
||||
--prefix PATH : ${
|
||||
lib.makeBinPath [
|
||||
pass
|
||||
pass2csv
|
||||
python3
|
||||
]
|
||||
}
|
||||
--prefix PATH : ${lib.makeBinPath [ python3 ]}
|
||||
'';
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,5 +4,5 @@ if [ "$#" -ne 2 ]; then
|
|||
fi
|
||||
|
||||
pass2csv "$1" /tmp/pass.csv
|
||||
python3 "$(dirname "$0")/convert_csvs.py" /tmp/pass.csv "$2"
|
||||
python ./convert_csvs.py /tmp/pass.csv "$2"
|
||||
rm /tmp/pass.csv
|
||||
|
|
|
|||
|
|
@ -1,61 +0,0 @@
|
|||
{
|
||||
lib,
|
||||
stdenv,
|
||||
fetchFromGitHub,
|
||||
ncurses,
|
||||
openssl,
|
||||
pcre2,
|
||||
zlib,
|
||||
|
||||
lua5_4,
|
||||
python3,
|
||||
icu,
|
||||
|
||||
enableLua ? true,
|
||||
enablePython ? true,
|
||||
enableWidechar ? true,
|
||||
}:
|
||||
|
||||
stdenv.mkDerivation rec {
|
||||
pname = "tinyfugue";
|
||||
version = "5.2.2";
|
||||
|
||||
src = fetchFromGitHub {
|
||||
owner = "ingwarsw";
|
||||
repo = "tinyfugue";
|
||||
rev = version;
|
||||
hash = "sha256-nHgu0XJ2Nd0JYrs3o/NLZ9gq1D4ubdPyowQLyhOzDDA=";
|
||||
};
|
||||
|
||||
buildInputs = [
|
||||
ncurses
|
||||
openssl
|
||||
pcre2
|
||||
zlib
|
||||
]
|
||||
++ lib.optional enableLua lua5_4
|
||||
++ lib.optional enablePython python3
|
||||
++ lib.optional enableWidechar icu;
|
||||
|
||||
env.NIX_CFLAGS_COMPILE = "-D_DEFAULT_SOURCE";
|
||||
|
||||
configureFlags = [
|
||||
"--enable-termcap=ncurses"
|
||||
]
|
||||
++ lib.optional enableLua "--enable-lua"
|
||||
++ lib.optional enablePython "--enable-python"
|
||||
++ lib.optional (!enableWidechar) "--disable-widechar";
|
||||
|
||||
installPhase = ''
|
||||
make install
|
||||
'';
|
||||
|
||||
meta = {
|
||||
description = "TinyFugue - Rebirth";
|
||||
homepage = "https://github.com/ingwarsw/tinyfugue";
|
||||
changelog = "https://github.com/ingwarsw/tinyfugue/blob/${src.rev}/CHANGES";
|
||||
license = lib.licenses.gpl2Only;
|
||||
mainProgram = "tf";
|
||||
platforms = lib.platforms.all;
|
||||
};
|
||||
}
|
||||
|
|
@ -1 +0,0 @@
|
|||
use flake
|
||||
5
templates/dev/stm32-blink/.gitignore
vendored
5
templates/dev/stm32-blink/.gitignore
vendored
|
|
@ -1,5 +0,0 @@
|
|||
.cache/
|
||||
.direnv/
|
||||
build/
|
||||
compile_commands.json
|
||||
result
|
||||
|
|
@ -1,67 +0,0 @@
|
|||
PREFIX ?= arm-none-eabi-
|
||||
CC = $(PREFIX)gcc
|
||||
OBJCOPY = $(PREFIX)objcopy
|
||||
SIZE = $(PREFIX)size
|
||||
|
||||
PNAME := blink
|
||||
BUILD := build
|
||||
|
||||
# libopencm3 is provided by the Nix shell
|
||||
OPENCM3_DIR ?= ""
|
||||
|
||||
SRCS := src/main.c
|
||||
OBJS := $(addprefix $(BUILD)/, $(SRCS:.c=.o))
|
||||
|
||||
# STM32G4
|
||||
CPU_FLAGS := -mcpu=cortex-m4 -mthumb -mfloat-abi=hard -mfpu=fpv4-sp-d16
|
||||
|
||||
CFLAGS := $(CPU_FLAGS) \
|
||||
-DSTM32G4 \
|
||||
-Os -Wall -Wextra \
|
||||
-ffunction-sections -fdata-sections \
|
||||
-I$(OPENCM3_DIR)/include
|
||||
|
||||
LDFLAGS := $(CPU_FLAGS) \
|
||||
-nostartfiles \
|
||||
-Wl,--gc-sections \
|
||||
-L$(OPENCM3_DIR)/lib \
|
||||
-lopencm3_stm32g4
|
||||
|
||||
ELF := $(BUILD)/$(PNAME).elf
|
||||
BIN := $(BUILD)/$(PNAME).bin
|
||||
HEX := $(BUILD)/$(PNAME).hex
|
||||
|
||||
.PHONY: all clean flash size
|
||||
|
||||
all: $(BIN) $(HEX) size
|
||||
|
||||
$(BUILD)/%.o: %.c
|
||||
@mkdir -p $(@D)
|
||||
$(CC) $(CFLAGS) -c $< -o $@
|
||||
|
||||
LDSCRIPT := $(BUILD)/stm32g474xe.ld
|
||||
|
||||
$(LDSCRIPT):
|
||||
@mkdir -p $(@D)
|
||||
$(CC) -I$(OPENCM3_DIR)/include $(shell python3 $(OPENCM3_DIR)/scripts/genlink.py $(OPENCM3_DIR)/ld/devices.data stm32g474xe DEFS) -P -E $(OPENCM3_DIR)/ld/linker.ld.S -o $@
|
||||
|
||||
$(ELF): $(OBJS) $(LDSCRIPT)
|
||||
$(CC) $(OBJS) $(LDFLAGS) -T$(LDSCRIPT) -o $@
|
||||
|
||||
$(BIN): $(ELF)
|
||||
$(OBJCOPY) -O binary $< $@
|
||||
|
||||
$(HEX): $(ELF)
|
||||
$(OBJCOPY) -O ihex $< $@
|
||||
|
||||
size: $(ELF)
|
||||
$(SIZE) $<
|
||||
|
||||
flash: $(BIN)
|
||||
openocd \
|
||||
-f interface/stlink.cfg \
|
||||
-f target/stm32g4x.cfg \
|
||||
-c "program $(BIN) verify reset exit 0x08000000"
|
||||
|
||||
clean:
|
||||
rm -rf $(BUILD)
|
||||
|
|
@ -1,28 +0,0 @@
|
|||
# STM32G4 blink template
|
||||
|
||||
Blinks the LD2 LED (PA5) on a [Nucleo-G474RE](https://www.st.com/en/evaluation-tools/nucleo-g474re.html) using [libopencm3](https://github.com/libopencm3/libopencm3).
|
||||
|
||||
Set `BLINK_PORT` / `BLINK_PIN` for your board in [`src/main.c`](./src/main.c).
|
||||
|
||||
## Toolchain
|
||||
|
||||
The Nix dev shell provides:
|
||||
|
||||
- `arm-none-eabi-gcc` (via `gcc-arm-embedded`)
|
||||
- `openocd` for flashing and debugging
|
||||
- `stlink` utilities (`st-flash`, `st-info`)
|
||||
- `libopencm3` built for `stm32/g4` (exposed as `$LIBOPENCM3_DIR`)
|
||||
|
||||
## Build
|
||||
|
||||
```bash
|
||||
make
|
||||
```
|
||||
|
||||
## Flash
|
||||
|
||||
```bash
|
||||
make flash
|
||||
```
|
||||
|
||||
This uses OpenOCD with the built-in ST-Link interface config.
|
||||
|
|
@ -1,6 +0,0 @@
|
|||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
make clean
|
||||
mkdir -p build
|
||||
bear -- make
|
||||
|
|
@ -1,161 +0,0 @@
|
|||
{
|
||||
description = "A blink template for STM32G4";
|
||||
|
||||
inputs = {
|
||||
nixpkgs.url = "nixpkgs/nixpkgs-unstable";
|
||||
utils.url = "github:numtide/flake-utils";
|
||||
libopencm3-src = {
|
||||
url = "github:libopencm3/libopencm3";
|
||||
flake = false;
|
||||
};
|
||||
pre-commit-hooks = {
|
||||
url = "github:cachix/pre-commit-hooks.nix";
|
||||
inputs.nixpkgs.follows = "nixpkgs";
|
||||
};
|
||||
};
|
||||
|
||||
outputs =
|
||||
{
|
||||
self,
|
||||
nixpkgs,
|
||||
utils,
|
||||
libopencm3-src,
|
||||
pre-commit-hooks,
|
||||
...
|
||||
}:
|
||||
{
|
||||
overlays.default = final: prev: {
|
||||
libopencm3-stm32 = final.stdenvNoCC.mkDerivation {
|
||||
pname = "libopencm3-stm32";
|
||||
version = "latest";
|
||||
|
||||
src = libopencm3-src;
|
||||
|
||||
postPatch = ''
|
||||
patchShebangs scripts
|
||||
'';
|
||||
|
||||
nativeBuildInputs = [
|
||||
final.gcc-arm-embedded
|
||||
final.python3
|
||||
final.gnumake
|
||||
];
|
||||
|
||||
enableParallelBuilding = true;
|
||||
|
||||
makeFlags = [
|
||||
"PREFIX=arm-none-eabi-"
|
||||
];
|
||||
|
||||
TARGETS = "stm32/f0 stm32/f1 stm32/f2 stm32/f3 stm32/f4 stm32/f7 stm32/l0 stm32/l1 stm32/l4 stm32/g0 stm32/g4 stm32/h7 stm32/u5";
|
||||
|
||||
installPhase = ''
|
||||
runHook preInstall
|
||||
|
||||
mkdir -p $out
|
||||
cp -r include lib mk scripts ld $out/
|
||||
|
||||
patchShebangs $out/scripts
|
||||
|
||||
runHook postInstall
|
||||
'';
|
||||
|
||||
meta = with final.lib; {
|
||||
description = "Open source ARM Cortex-M microcontroller library (STM32 targets)";
|
||||
homepage = "http://libopencm3.org/";
|
||||
license = licenses.lgpl3Plus;
|
||||
platforms = platforms.all;
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
// utils.lib.eachDefaultSystem (
|
||||
system:
|
||||
let
|
||||
pkgs = import nixpkgs {
|
||||
inherit system;
|
||||
overlays = [ self.overlays.default ];
|
||||
};
|
||||
pname = "blink";
|
||||
version = "0.1.0";
|
||||
in
|
||||
{
|
||||
packages = {
|
||||
inherit (pkgs) libopencm3-stm32;
|
||||
default = pkgs.stdenvNoCC.mkDerivation {
|
||||
inherit pname version;
|
||||
src = pkgs.lib.cleanSource ./.;
|
||||
|
||||
nativeBuildInputs = with pkgs; [
|
||||
gcc-arm-embedded
|
||||
gnumake
|
||||
python3
|
||||
];
|
||||
|
||||
makeFlags = [
|
||||
"OPENCM3_DIR=${pkgs.libopencm3-stm32}"
|
||||
"PREFIX=arm-none-eabi-"
|
||||
];
|
||||
|
||||
installPhase = ''
|
||||
runHook preInstall
|
||||
mkdir -p $out/bin
|
||||
cp build/${pname}.elf $out/bin/
|
||||
cp build/${pname}.bin $out/bin/
|
||||
cp build/${pname}.hex $out/bin/
|
||||
runHook postInstall
|
||||
'';
|
||||
};
|
||||
};
|
||||
|
||||
devShells.default =
|
||||
let
|
||||
# FIXME: 'gnu/stubs-32.h' file not found
|
||||
clangdWrapper = pkgs.writeShellScriptBin "clangd" ''
|
||||
exec ${pkgs.clang-tools}/bin/clangd \
|
||||
--query-driver=${pkgs.gcc-arm-embedded}/bin/arm-none-eabi-* \
|
||||
"$@"
|
||||
'';
|
||||
in
|
||||
pkgs.mkShell {
|
||||
name = "stm32-blink";
|
||||
packages = self.packages.${system}.default.nativeBuildInputs ++ [
|
||||
clangdWrapper
|
||||
|
||||
pkgs.bear
|
||||
pkgs.openocd
|
||||
pkgs.stlink
|
||||
];
|
||||
OPENCM3_DIR = pkgs.libopencm3-stm32;
|
||||
PREFIX = "arm-none-eabi-";
|
||||
};
|
||||
|
||||
formatter =
|
||||
let
|
||||
inherit (self.checks.${system}.pre-commit-check.config) package configFile;
|
||||
script = ''
|
||||
${pkgs.lib.getExe package} run --all-files --config ${configFile}
|
||||
'';
|
||||
in
|
||||
pkgs.writeShellScriptBin "pre-commit-run" script;
|
||||
|
||||
checks = {
|
||||
build-packages = pkgs.linkFarm "flake-packages-${system}" self.packages.${system};
|
||||
|
||||
pre-commit-check = pre-commit-hooks.lib.${system}.run {
|
||||
src = ./.;
|
||||
hooks = {
|
||||
nixfmt.enable = true;
|
||||
clang-format = {
|
||||
enable = true;
|
||||
types_or = pkgs.lib.mkForce [
|
||||
"c"
|
||||
"c++"
|
||||
];
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
);
|
||||
}
|
||||
|
|
@ -1,50 +0,0 @@
|
|||
#include <libopencm3/cm3/systick.h>
|
||||
#include <libopencm3/stm32/gpio.h>
|
||||
#include <libopencm3/stm32/rcc.h>
|
||||
|
||||
/* Nucleo-G474RE: LD2 is on PA5 */
|
||||
#define BLINK_PORT GPIOA
|
||||
#define BLINK_PIN GPIO5
|
||||
#define BLINK_PERIOD_MS 1000
|
||||
|
||||
static volatile uint32_t s_ticks = 0;
|
||||
|
||||
void sys_tick_handler(void) { s_ticks++; }
|
||||
|
||||
static void delay_ms(uint32_t ms) {
|
||||
uint32_t until = s_ticks + ms;
|
||||
while (s_ticks < until)
|
||||
;
|
||||
}
|
||||
|
||||
static void clock_setup(void) {
|
||||
rcc_clock_setup_pll(&rcc_hsi_configs[RCC_CLOCK_3V3_170MHZ]);
|
||||
}
|
||||
|
||||
static void systick_setup(void) {
|
||||
/* 1 ms tick at 170 MHz core clock */
|
||||
systick_set_reload(rcc_ahb_frequency / 1000 - 1);
|
||||
systick_set_clocksource(STK_CSR_CLKSOURCE_AHB);
|
||||
systick_counter_enable();
|
||||
systick_interrupt_enable();
|
||||
}
|
||||
|
||||
static void gpio_setup(void) {
|
||||
rcc_periph_clock_enable(RCC_GPIOA);
|
||||
gpio_mode_setup(BLINK_PORT, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, BLINK_PIN);
|
||||
gpio_set_output_options(BLINK_PORT, GPIO_OTYPE_PP, GPIO_OSPEED_LOW,
|
||||
BLINK_PIN);
|
||||
}
|
||||
|
||||
int main(void) {
|
||||
clock_setup();
|
||||
systick_setup();
|
||||
gpio_setup();
|
||||
|
||||
while (1) {
|
||||
gpio_toggle(BLINK_PORT, BLINK_PIN);
|
||||
delay_ms(BLINK_PERIOD_MS);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -23,8 +23,6 @@
|
|||
};
|
||||
|
||||
stylix.enable = true;
|
||||
stylix.scheme = "generate-from-image";
|
||||
stylix.image = ./wallpaper.png;
|
||||
|
||||
home.stateVersion = "25.11";
|
||||
}
|
||||
|
|
|
|||
Binary file not shown.
|
Before Width: | Height: | Size: 2.1 MiB |
|
|
@ -1,38 +0,0 @@
|
|||
let
|
||||
port = 3080;
|
||||
in
|
||||
{
|
||||
name = "librechat-oci-test";
|
||||
|
||||
nodes.machine =
|
||||
{ ... }:
|
||||
{
|
||||
imports = [
|
||||
../../modules/nixos/librechat-oci
|
||||
];
|
||||
|
||||
config = {
|
||||
virtualisation.diskSize = 32768;
|
||||
virtualisation.memorySize = 8192;
|
||||
|
||||
services.librechat-oci = {
|
||||
enable = true;
|
||||
inherit port;
|
||||
};
|
||||
|
||||
networking.firewall.enable = false;
|
||||
};
|
||||
};
|
||||
|
||||
testScript = ''
|
||||
start_all()
|
||||
|
||||
machine.wait_for_unit("default.target")
|
||||
|
||||
machine.wait_for_unit("podman-librechat-mongodb.service")
|
||||
machine.wait_for_unit("podman-librechat.service")
|
||||
machine.wait_for_open_port(${toString port})
|
||||
|
||||
machine.succeed("curl --fail --retry 10 --retry-delay 5 --retry-connrefused http://localhost:${toString port}/")
|
||||
'';
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue