Compare commits
1 commit
release-25
...
feature/zf
| Author | SHA1 | Date | |
|---|---|---|---|
| 951182f6df |
164 changed files with 1778 additions and 3412 deletions
1
.envrc
1
.envrc
|
|
@ -1,2 +1 @@
|
||||||
# shellcheck shell=bash
|
|
||||||
use flake
|
use flake
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,3 @@
|
||||||
---
|
|
||||||
name: Build tests
|
name: Build tests
|
||||||
|
|
||||||
on:
|
on:
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,3 @@
|
||||||
---
|
|
||||||
name: Deploy docs
|
name: Deploy docs
|
||||||
|
|
||||||
on:
|
on:
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,6 @@
|
||||||
---
|
|
||||||
name: Flake check
|
name: Flake check
|
||||||
|
|
||||||
on:
|
on: [pull_request]
|
||||||
pull_request:
|
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
flake-check:
|
flake-check:
|
||||||
|
|
@ -13,8 +11,5 @@ jobs:
|
||||||
- name: Checkout repository
|
- name: Checkout repository
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
- name: Check formatting
|
|
||||||
run: nix fmt -- --check
|
|
||||||
|
|
||||||
- name: Run flake check
|
- name: Run flake check
|
||||||
run: nix flake check --impure --all-systems
|
run: nix flake check --impure
|
||||||
|
|
|
||||||
|
|
@ -27,7 +27,7 @@ Add this repo to your flake inputs:
|
||||||
inputs.synix.url = "git+https://git.sid.ovh/sid/synix.git";
|
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
|
## Templates
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -11,6 +11,9 @@ HOSTNAME=""
|
||||||
# Templates with Home Manager configurations
|
# Templates with Home Manager configurations
|
||||||
HM_CONFIGS=("hyprland")
|
HM_CONFIGS=("hyprland")
|
||||||
|
|
||||||
|
# This will get overwritten by the derivation
|
||||||
|
TEMPLATES_DIR=""
|
||||||
|
|
||||||
# Print usage information
|
# Print usage information
|
||||||
usage() {
|
usage() {
|
||||||
cat <<EOF
|
cat <<EOF
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,7 @@
|
||||||
home-manager,
|
home-manager,
|
||||||
hostname,
|
hostname,
|
||||||
nix,
|
nix,
|
||||||
nixos-rebuild-ng,
|
nixos-rebuild,
|
||||||
...
|
...
|
||||||
}:
|
}:
|
||||||
|
|
||||||
|
|
@ -25,6 +25,6 @@ writeShellApplication {
|
||||||
home-manager
|
home-manager
|
||||||
hostname
|
hostname
|
||||||
nix
|
nix
|
||||||
nixos-rebuild-ng
|
nixos-rebuild
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,21 +1,15 @@
|
||||||
#!/usr/bin/env bash
|
|
||||||
# NixOS and standalone Home Manager rebuild script
|
# NixOS and standalone Home Manager rebuild script
|
||||||
|
|
||||||
# Defaults
|
# Defaults
|
||||||
FLAKE_PATH="${REBUILD_FLAKE_PATH:-${FLAKE_PATH:-$HOME/.config/nixos}}" # Default flake path
|
FLAKE_PATH="$HOME/.config/nixos" # Default flake path
|
||||||
USER="${REBUILD_USER:-$(whoami)}" # Default username
|
HOME_USER="$(whoami)" # Default username. Used to identify the Home Manager configuration
|
||||||
HOST="${REBUILD_HOST:-$(hostname)}" # Default hostname
|
NIXOS_HOST="$(hostname)" # Default hostname. Used to identify the NixOS and Home Manager configuration
|
||||||
BUILD_HOST="${REBUILD_BUILD_HOST:-}" # Default build host
|
BUILD_HOST="" # Default build host. Empty means localhost
|
||||||
TARGET_HOST="${REBUILD_TARGET_HOST:-}" # Default target host
|
TARGET_HOST="" # Default target host. Empty means localhost
|
||||||
UPDATE="${REBUILD_UPDATE:-0}" # Default to not update
|
UPDATE=0 # Default to not update flake repositories
|
||||||
UPDATE_INPUTS="${REBUILD_UPDATE_INPUTS:-}" # Default list of inputs
|
UPDATE_INPUTS="" # Default list of inputs to update. Empty means all
|
||||||
ROLLBACK="${REBUILD_ROLLBACK:-0}" # Default to not rollback
|
ROLLBACK=0 # Default to not rollback
|
||||||
SHOW_TRACE="${REBUILD_SHOW_TRACE:-0}" # Default to not show trace
|
SHOW_TRACE=0 # Default to not show detailed error messages
|
||||||
|
|
||||||
# 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; }
|
|
||||||
|
|
||||||
# Function to display the help message
|
# Function to display the help message
|
||||||
Help() {
|
Help() {
|
||||||
|
|
@ -29,7 +23,7 @@ Help() {
|
||||||
echo " help Show this help message"
|
echo " help Show this help message"
|
||||||
echo
|
echo
|
||||||
echo "Options (for NixOS and Home Manager):"
|
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 " -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 " -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"
|
echo " -r, --rollback Don't build the new configuration, but use the previous generation instead"
|
||||||
|
|
@ -40,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 " -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
|
||||||
echo "Home Manager only options:"
|
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
|
# Function to rebuild NixOS configuration
|
||||||
Rebuild_nixos() {
|
Rebuild_nixos() {
|
||||||
local FLAKE="$FLAKE_PATH#$HOST"
|
local FLAKE="$FLAKE_PATH#$NIXOS_HOST"
|
||||||
|
|
||||||
# Construct rebuild command
|
# Construct rebuild command
|
||||||
local CMD=("nixos-rebuild" "switch" "--sudo")
|
local CMD=("nixos-rebuild" "switch" "--sudo")
|
||||||
|
[[ -n "$TARGET_HOST" || -n "$BUILD_HOST" ]] && CMD+=("--ask-sudo-password")
|
||||||
CMD+=("--flake" "$FLAKE")
|
CMD+=("--flake" "$FLAKE")
|
||||||
[ "$ROLLBACK" = 1 ] && CMD+=("--rollback")
|
[ "$ROLLBACK" = 1 ] && CMD+=("--rollback")
|
||||||
[ "$SHOW_TRACE" = 1 ] && CMD+=("--show-trace")
|
[ "$SHOW_TRACE" = 1 ] && CMD+=("--show-trace")
|
||||||
[ -n "$BUILD_HOST" ] && CMD+=("--build-host" "$BUILD_HOST")
|
[ -n "$BUILD_HOST" ] && CMD+=("--build-host" "$BUILD_HOST")
|
||||||
if [ "$HOST" != "$(hostname)" ] && [ -z "$TARGET_HOST" ]; then
|
if [ "$NIXOS_HOST" != "$(hostname)" ] && [ -z "$TARGET_HOST" ]; then
|
||||||
TARGET_HOST="$HOST"
|
TARGET_HOST="$NIXOS_HOST"
|
||||||
_status "Using '$TARGET_HOST' as target host."
|
echo "Using '$TARGET_HOST' as target host."
|
||||||
fi
|
fi
|
||||||
[ -n "$TARGET_HOST" ] && CMD+=("--target-host" "$TARGET_HOST")
|
[ -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
|
# Rebuild NixOS configuration
|
||||||
local BUILD_CMD=("nixos-rebuild" "build" "--no-build-output" "--flake" "$FLAKE")
|
if [ "$ROLLBACK" = 0 ]; then
|
||||||
[ "$SHOW_TRACE" = 1 ] && BUILD_CMD+=("--show-trace")
|
echo "Rebuilding NixOS configuration '$FLAKE'..."
|
||||||
[ -n "$BUILD_HOST" ] && BUILD_CMD+=("--build-host" "$BUILD_HOST")
|
|
||||||
|
|
||||||
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"
|
|
||||||
else
|
else
|
||||||
_status "Rolling back to last NixOS generation"
|
echo "Rolling back to last NixOS generation..."
|
||||||
fi
|
fi
|
||||||
|
|
||||||
sudo -v
|
echo "Executing command: ${CMD[*]}"
|
||||||
_status "Executing command: ${CMD[*]}"
|
|
||||||
"${CMD[@]}" || error "NixOS rebuild failed"
|
"${CMD[@]}" || error "NixOS rebuild failed"
|
||||||
success "NixOS rebuild completed successfully."
|
echo "NixOS rebuild completed successfully."
|
||||||
}
|
}
|
||||||
|
|
||||||
# Function to rebuild Home Manager configuration
|
# Function to rebuild Home Manager configuration
|
||||||
Rebuild_home() {
|
Rebuild_home() {
|
||||||
local FLAKE="$FLAKE_PATH#$USER@$HOST"
|
local FLAKE="$FLAKE_PATH#$HOME_USER@$NIXOS_HOST"
|
||||||
|
|
||||||
if [ -n "$BUILD_HOST" ] || [ -n "$TARGET_HOST" ]; then
|
if [ -n "$BUILD_HOST" ] || [ -n "$TARGET_HOST" ]; then
|
||||||
error "Remote building is not supported for Home Manager."
|
error "Remote building is not supported for Home Manager."
|
||||||
|
|
@ -100,27 +91,21 @@ Rebuild_home() {
|
||||||
[ "$SHOW_TRACE" = 1 ] && CMD+=("--show-trace")
|
[ "$SHOW_TRACE" = 1 ] && CMD+=("--show-trace")
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Build config first so we can diff it
|
# Rebuild Home Manager configuration
|
||||||
if [ "$ROLLBACK" = 0 ]; then
|
if [ "$ROLLBACK" = 0 ]; then
|
||||||
local BUILD_CMD=("home-manager" "build" "--no-out-link" "--flake" "$FLAKE")
|
echo "Rebuilding Home Manager configuration '$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"
|
|
||||||
else
|
else
|
||||||
_status "Rolling back to last Home Manager generation"
|
echo "Rolling back to last Home Manager generation..."
|
||||||
fi
|
fi
|
||||||
|
|
||||||
_status "Executing command: ${CMD[*]}"
|
echo "Executing command: ${CMD[*]}"
|
||||||
"${CMD[@]}" || error "Home Manager rebuild failed"
|
"${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() {
|
Update() {
|
||||||
_status "Updating flake inputs..."
|
echo "Updating flake inputs..."
|
||||||
|
|
||||||
# Construct update command as an array
|
# Construct update command as an array
|
||||||
local CMD=("nix" "flake" "update" "--flake" "$FLAKE_PATH")
|
local CMD=("nix" "flake" "update" "--flake" "$FLAKE_PATH")
|
||||||
|
|
@ -132,18 +117,17 @@ Update() {
|
||||||
done
|
done
|
||||||
fi
|
fi
|
||||||
|
|
||||||
_status "Executing command: ${CMD[*]}"
|
echo "Executing command: ${CMD[*]}"
|
||||||
"${CMD[@]}" || error "Failed to update flake repositories"
|
"${CMD[@]}" || error "Failed to update flake repositories"
|
||||||
success "Flake repositories updated successfully."
|
echo "Flake repositories updated successfully."
|
||||||
}
|
}
|
||||||
|
|
||||||
# Parse command-line options
|
# Parse command-line options
|
||||||
if [[ -z "${1:-}" ]]; then
|
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
|
Help
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
COMMAND=$1
|
COMMAND=$1
|
||||||
shift
|
shift
|
||||||
|
|
||||||
|
|
@ -157,7 +141,7 @@ while [ $# -gt 0 ]; do
|
||||||
case "${1:-}" in
|
case "${1:-}" in
|
||||||
-H|--host)
|
-H|--host)
|
||||||
if [ -n "${2:-}" ]; then
|
if [ -n "${2:-}" ]; then
|
||||||
HOST="$2"
|
NIXOS_HOST="$2"
|
||||||
shift 2
|
shift 2
|
||||||
else
|
else
|
||||||
error "-H|--host option requires an argument"
|
error "-H|--host option requires an argument"
|
||||||
|
|
@ -165,7 +149,7 @@ while [ $# -gt 0 ]; do
|
||||||
;;
|
;;
|
||||||
-u|--user)
|
-u|--user)
|
||||||
if [ -n "${2:-}" ]; then
|
if [ -n "${2:-}" ]; then
|
||||||
USER="$2"
|
HOME_USER="$2"
|
||||||
shift 2
|
shift 2
|
||||||
else
|
else
|
||||||
error "-u|--user option requires an argument"
|
error "-u|--user option requires an argument"
|
||||||
|
|
@ -214,7 +198,9 @@ while [ $# -gt 0 ]; do
|
||||||
fi
|
fi
|
||||||
;;
|
;;
|
||||||
*)
|
*)
|
||||||
error "Unknown option '$1'"
|
echo "Error: Unknown option '$1'"
|
||||||
|
Help
|
||||||
|
exit 1
|
||||||
;;
|
;;
|
||||||
esac
|
esac
|
||||||
done
|
done
|
||||||
|
|
@ -241,10 +227,10 @@ fi
|
||||||
[ "$UPDATE" = 1 ] && Update
|
[ "$UPDATE" = 1 ] && Update
|
||||||
|
|
||||||
case "$COMMAND" in
|
case "$COMMAND" in
|
||||||
nixos|os)
|
nixos)
|
||||||
Rebuild_nixos
|
Rebuild_nixos
|
||||||
;;
|
;;
|
||||||
home|hm)
|
home)
|
||||||
Rebuild_home
|
Rebuild_home
|
||||||
;;
|
;;
|
||||||
all)
|
all)
|
||||||
|
|
@ -252,6 +238,9 @@ case "$COMMAND" in
|
||||||
Rebuild_home
|
Rebuild_home
|
||||||
;;
|
;;
|
||||||
*)
|
*)
|
||||||
error "Unknown command '$COMMAND'"
|
echo "Error: Unknown command '$COMMAND'"
|
||||||
|
echo "Printing help page:"
|
||||||
|
Help
|
||||||
|
exit 1
|
||||||
;;
|
;;
|
||||||
esac
|
esac
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,3 @@
|
||||||
#!/usr/bin/env bash
|
|
||||||
SYSTEM="x86_64-linux"
|
SYSTEM="x86_64-linux"
|
||||||
IGNORE_PACKAGES=(
|
IGNORE_PACKAGES=(
|
||||||
"pyman"
|
"pyman"
|
||||||
|
|
|
||||||
|
|
@ -114,8 +114,7 @@ git clone YOUR_GIT_REPO_URL ~/.config/nixos
|
||||||
Home Manager is not installed by default. Enter the development shell to apply the configuration:
|
Home Manager is not installed by default. Enter the development shell to apply the configuration:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
nix --experimental-features "nix-command flakes" develop git+https://git.sid.ovh/sid/synix#devShells.x86_64-linux.install-hm \
|
nix-shell ~/.config/nixos/shell.nix --run 'rebuild home'
|
||||||
--command "rebuild home"
|
|
||||||
```
|
```
|
||||||
|
|
||||||
### 8. Reboot your System
|
### 8. Reboot your System
|
||||||
|
|
|
||||||
|
|
@ -19,7 +19,7 @@ Provide the following entries to your `secrets.yaml`:
|
||||||
```yaml
|
```yaml
|
||||||
headplane:
|
headplane:
|
||||||
cookie_secret: abc123
|
cookie_secret: abc123
|
||||||
api_key: abc123
|
agent_pre_authkey: abc123
|
||||||
```
|
```
|
||||||
|
|
||||||
Generate your cookie secret with:
|
Generate your cookie secret with:
|
||||||
|
|
@ -28,7 +28,7 @@ Generate your cookie secret with:
|
||||||
nix-shell -p openssl --run "openssl rand -hex 16"
|
nix-shell -p openssl --run "openssl rand -hex 16"
|
||||||
```
|
```
|
||||||
|
|
||||||
Generate your agent `api_key` with:
|
Generate your agent pre-authkey with:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
sudo headscale users create headplane-agent
|
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": {
|
"flake-schemas": {
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1776384880,
|
"lastModified": 1770913512,
|
||||||
"narHash": "sha256-28Cg9HI/IwFHUm5fZyMEGCQ94L3Il6K4OfHeRf0b+Zw=",
|
"narHash": "sha256-jRC1qRoRCrMjDalVfUMHFlKSkkA2q0RZWTDW0LsquoA=",
|
||||||
"owner": "DeterminateSystems",
|
"owner": "DeterminateSystems",
|
||||||
"repo": "flake-schemas",
|
"repo": "flake-schemas",
|
||||||
"rev": "b852751d29c6e09919f25c1e10754646bdc181c9",
|
"rev": "3c464b0e09cb44c6e073c41dd1d834980c3e0b24",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
|
|
@ -258,11 +258,11 @@
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1778507602,
|
"lastModified": 1772024342,
|
||||||
"narHash": "sha256-kTwur1wV+01SdqskVMSo6JMEpg71ps3HpbFY2GsflKs=",
|
"narHash": "sha256-+eXlIc4/7dE6EcPs9a2DaSY3fTA9AE526hGqkNID3Wg=",
|
||||||
"owner": "cachix",
|
"owner": "cachix",
|
||||||
"repo": "git-hooks.nix",
|
"repo": "git-hooks.nix",
|
||||||
"rev": "61ab0e80d9c7ab14c256b5b453d8b3fb0189ba0a",
|
"rev": "6e34e97ed9788b17796ee43ccdbaf871a5c2b476",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
|
|
@ -349,11 +349,11 @@
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1779506708,
|
"lastModified": 1772020340,
|
||||||
"narHash": "sha256-QOD/CNm196nCJRheux/URi4/HE66fthdOMqCJoPP1Y0=",
|
"narHash": "sha256-aqBl3GNpCadMoJ/hVkWTijM1Aeilc278MjM+LA3jK6g=",
|
||||||
"owner": "nix-community",
|
"owner": "nix-community",
|
||||||
"repo": "home-manager",
|
"repo": "home-manager",
|
||||||
"rev": "3ee51fbdac8c8bdfe1e7e1fcaba6520a563f394f",
|
"rev": "36e38ca0d9afe4c55405fdf22179a5212243eecc",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
|
|
@ -465,11 +465,11 @@
|
||||||
},
|
},
|
||||||
"nixpkgs_2": {
|
"nixpkgs_2": {
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1779467186,
|
"lastModified": 1771903837,
|
||||||
"narHash": "sha256-nOesoDCiXcUftqbRBMz9tt4blI5PvljMWbm3kuCA+0s=",
|
"narHash": "sha256-sdaqdnsQCv3iifzxwB22tUwN/fSHoN7j2myFW5EIkGk=",
|
||||||
"owner": "nixos",
|
"owner": "nixos",
|
||||||
"repo": "nixpkgs",
|
"repo": "nixpkgs",
|
||||||
"rev": "b77b3de8775677f84492abe84635f87b0e153f0f",
|
"rev": "e764fc9a405871f1f6ca3d1394fb422e0a0c3951",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
|
|
@ -511,11 +511,11 @@
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1779900588,
|
"lastModified": 1772140017,
|
||||||
"narHash": "sha256-b/yda4uMmjpw4uhXI4d0JNv09WtGoXis2JjD5l1Qbts=",
|
"narHash": "sha256-wFUc9tn5Ik11oL009BkVnj4NxsY63UbZjhOyEqCsIQE=",
|
||||||
"owner": "nix-community",
|
"owner": "nix-community",
|
||||||
"repo": "NUR",
|
"repo": "NUR",
|
||||||
"rev": "dd8bdde89853bfb3eae0eb28e3d3a9320b3b8a3c",
|
"rev": "be0fea0af0e8cfadb3995dd7bb3a167bc012e935",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
|
|
@ -605,11 +605,11 @@
|
||||||
"tinted-zed": "tinted-zed"
|
"tinted-zed": "tinted-zed"
|
||||||
},
|
},
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1778680496,
|
"lastModified": 1771788390,
|
||||||
"narHash": "sha256-tUq1WASV0dHLv3j18log8V6Esq0NYkXuzNH2EHsstcg=",
|
"narHash": "sha256-RzBpBwn93GWxLjacTte+ngwwg0L/BVOg4G/sSIeK3Rw=",
|
||||||
"owner": "nix-community",
|
"owner": "nix-community",
|
||||||
"repo": "stylix",
|
"repo": "stylix",
|
||||||
"rev": "fc5bec2e44678eeaa221d566d447a0257a884737",
|
"rev": "ebb238f14d6f930068be4718472da3105fd5d3bf",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
|
|
|
||||||
224
flake.nix
224
flake.nix
|
|
@ -3,6 +3,7 @@
|
||||||
nixpkgs.url = "github:nixos/nixpkgs/nixos-25.11";
|
nixpkgs.url = "github:nixos/nixpkgs/nixos-25.11";
|
||||||
|
|
||||||
nix.url = "github:DeterminateSystems/nix-src/flake-schemas";
|
nix.url = "github:DeterminateSystems/nix-src/flake-schemas";
|
||||||
|
|
||||||
flake-schemas.url = "github:DeterminateSystems/flake-schemas";
|
flake-schemas.url = "github:DeterminateSystems/flake-schemas";
|
||||||
|
|
||||||
git-hooks.url = "github:cachix/git-hooks.nix";
|
git-hooks.url = "github:cachix/git-hooks.nix";
|
||||||
|
|
@ -28,69 +29,50 @@
|
||||||
...
|
...
|
||||||
}@inputs:
|
}@inputs:
|
||||||
let
|
let
|
||||||
inherit (self) outputs;
|
supportedSystems = [
|
||||||
|
|
||||||
systems = [
|
|
||||||
"x86_64-linux"
|
"x86_64-linux"
|
||||||
"aarch64-linux" # For testing only. Use at your own risk.
|
"aarch64-linux" # For testing only. Use at your own risk.
|
||||||
];
|
];
|
||||||
|
|
||||||
lib = nixpkgs.lib.extend (_final: _prev: { inherit (self.lib) utils; });
|
forAllSystems = nixpkgs.lib.genAttrs supportedSystems;
|
||||||
|
|
||||||
mkPkgs =
|
nixpkgsFor = forAllSystems (
|
||||||
{
|
system:
|
||||||
system,
|
|
||||||
config ? { },
|
|
||||||
}:
|
|
||||||
import nixpkgs {
|
import nixpkgs {
|
||||||
inherit system;
|
inherit system;
|
||||||
inherit config;
|
|
||||||
overlays = [
|
overlays = [
|
||||||
self.overlays.modifications
|
self.overlays.default
|
||||||
self.overlays.additions
|
|
||||||
inputs.nix.overlays.default
|
inputs.nix.overlays.default
|
||||||
(final: prev: { synix = self.overlays.additions final prev; })
|
|
||||||
];
|
];
|
||||||
};
|
}
|
||||||
|
);
|
||||||
|
|
||||||
forAllSystems =
|
test = {
|
||||||
function:
|
system = "x86_64-linux";
|
||||||
lib.genAttrs systems (
|
lib = nixpkgs.lib.extend (final: prev: self.outputs.lib or { });
|
||||||
system:
|
inputs = inputs // {
|
||||||
function (mkPkgs {
|
synix = self;
|
||||||
inherit system;
|
|
||||||
})
|
|
||||||
);
|
|
||||||
|
|
||||||
mkNixosConfiguration =
|
|
||||||
system: modules:
|
|
||||||
nixpkgs.lib.nixosSystem {
|
|
||||||
inherit system modules;
|
|
||||||
specialArgs = {
|
|
||||||
inherit inputs outputs lib;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
mkHomeConfiguration =
|
|
||||||
system: modules:
|
|
||||||
inputs.home-manager.lib.homeManagerConfiguration {
|
|
||||||
pkgs = mkPkgs { inherit system; };
|
|
||||||
inherit modules;
|
|
||||||
extraSpecialArgs = {
|
|
||||||
inherit inputs outputs;
|
|
||||||
};
|
|
||||||
};
|
};
|
||||||
|
outputs = { };
|
||||||
|
overlays = [
|
||||||
|
self.overlays.default
|
||||||
|
self.overlays.additions
|
||||||
|
self.overlays.modifications
|
||||||
|
(final: prev: { synix = self.packages."${final.system}"; })
|
||||||
|
];
|
||||||
|
};
|
||||||
in
|
in
|
||||||
{
|
{
|
||||||
inherit (inputs.flake-schemas) schemas;
|
inherit (inputs.flake-schemas) schemas;
|
||||||
|
|
||||||
apps = forAllSystems (
|
apps = forAllSystems (
|
||||||
pkgs:
|
system:
|
||||||
let
|
let
|
||||||
mkApp = name: description: {
|
pkgs = nixpkgs.legacyPackages.${system};
|
||||||
|
mkApp = name: desc: {
|
||||||
type = "app";
|
type = "app";
|
||||||
program = pkgs.lib.getExe (pkgs.callPackage ./apps/${name} { });
|
program = pkgs.lib.getExe (pkgs.callPackage ./apps/${name} { });
|
||||||
meta.description = description;
|
meta.description = desc;
|
||||||
};
|
};
|
||||||
in
|
in
|
||||||
{
|
{
|
||||||
|
|
@ -104,17 +86,13 @@
|
||||||
);
|
);
|
||||||
|
|
||||||
lib = {
|
lib = {
|
||||||
utils = import ./lib/utils.nix { inherit (nixpkgs) lib; };
|
utils = import ./lib/utils.nix { lib = nixpkgs.lib; };
|
||||||
helpers = {
|
|
||||||
inherit mkPkgs;
|
|
||||||
};
|
|
||||||
};
|
};
|
||||||
|
|
||||||
packages = forAllSystems (
|
packages = forAllSystems (
|
||||||
pkgs:
|
system:
|
||||||
let
|
let
|
||||||
inherit (pkgs.stdenv.hostPlatform) system;
|
allArchs = import ./pkgs { pkgs = nixpkgs.legacyPackages.${system}; };
|
||||||
allArchs = import ./pkgs { inherit pkgs; };
|
|
||||||
x64only =
|
x64only =
|
||||||
if system == "x86_64-linux" then
|
if system == "x86_64-linux" then
|
||||||
{
|
{
|
||||||
|
|
@ -133,97 +111,125 @@
|
||||||
|
|
||||||
# test configs
|
# test configs
|
||||||
nixosConfigurations = {
|
nixosConfigurations = {
|
||||||
nixos-hyprland = mkNixosConfiguration "x86_64-linux" [ ./tests/build/nixos-hyprland ];
|
nixos-hyprland = nixpkgs.lib.nixosSystem {
|
||||||
nixos-server = mkNixosConfiguration "x86_64-linux" [ ./tests/build/nixos-server ];
|
inherit (test) system;
|
||||||
|
modules = [
|
||||||
|
./tests/build/nixos-hyprland
|
||||||
|
{ nixpkgs.overlays = test.overlays; }
|
||||||
|
];
|
||||||
|
specialArgs = {
|
||||||
|
inherit (test) inputs outputs lib;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
nixos-server = nixpkgs.lib.nixosSystem {
|
||||||
|
inherit (test) system;
|
||||||
|
modules = [
|
||||||
|
./tests/build/nixos-server
|
||||||
|
{ nixpkgs.overlays = test.overlays; }
|
||||||
|
];
|
||||||
|
specialArgs = {
|
||||||
|
inherit (test) inputs outputs lib;
|
||||||
|
};
|
||||||
|
};
|
||||||
};
|
};
|
||||||
homeConfigurations = {
|
homeConfigurations = {
|
||||||
hm-hyprland = mkHomeConfiguration "x86_64-linux" [ ./tests/build/hm-hyprland ];
|
hm-hyprland = inputs.home-manager.lib.homeManagerConfiguration {
|
||||||
|
pkgs = import nixpkgs {
|
||||||
|
inherit (test) overlays system;
|
||||||
|
};
|
||||||
|
extraSpecialArgs = {
|
||||||
|
inherit (test) inputs outputs;
|
||||||
|
};
|
||||||
|
modules = [
|
||||||
|
./tests/build/hm-hyprland
|
||||||
|
];
|
||||||
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
devShells = forAllSystems (
|
devShells = forAllSystems (
|
||||||
pkgs:
|
system:
|
||||||
let
|
let
|
||||||
inherit (pkgs.stdenv.hostPlatform) system;
|
pkgs = nixpkgsFor.${system};
|
||||||
inherit (self.checks.${system}.pre-commit-check) shellHook enabledPackages;
|
|
||||||
in
|
in
|
||||||
{
|
{
|
||||||
default = pkgs.mkShell {
|
default =
|
||||||
inherit shellHook;
|
let
|
||||||
nativeBuildInputs = [
|
inherit (self.checks.${system}.pre-commit-check) shellHook enabledPackages;
|
||||||
enabledPackages
|
in
|
||||||
pkgs.nix
|
pkgs.mkShell {
|
||||||
]
|
inherit shellHook;
|
||||||
++ (with pkgs; [
|
nativeBuildInputs = [
|
||||||
(python313.withPackages (
|
enabledPackages
|
||||||
p: with p; [
|
pkgs.nix
|
||||||
mkdocs
|
]
|
||||||
mkdocs-material
|
++ (with pkgs; [
|
||||||
mkdocs-material-extensions
|
(python313.withPackages (
|
||||||
pygments
|
p: with p; [
|
||||||
]
|
mkdocs
|
||||||
))
|
mkdocs-material
|
||||||
]);
|
mkdocs-material-extensions
|
||||||
};
|
pygments
|
||||||
nix-config = pkgs.mkShell {
|
]
|
||||||
inherit shellHook;
|
))
|
||||||
nativeBuildInputs = [ enabledPackages ];
|
]);
|
||||||
};
|
};
|
||||||
install-hm = pkgs.mkShell {
|
|
||||||
NIX_CONFIG = "extra-experimental-features = nix-command flakes";
|
|
||||||
nativeBuildInputs = [ pkgs.home-manager ];
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
formatter = forAllSystems (
|
formatter = forAllSystems (
|
||||||
pkgs:
|
system:
|
||||||
let
|
let
|
||||||
inherit (pkgs.stdenv.hostPlatform) system;
|
pkgs = nixpkgs.legacyPackages.${system};
|
||||||
inherit (self.checks.${system}.pre-commit-check.config) package configFile;
|
config = self.checks.${system}.pre-commit-check.config;
|
||||||
|
inherit (config) package configFile;
|
||||||
|
script = ''
|
||||||
|
${pkgs.lib.getExe package} run --all-files --config ${configFile}
|
||||||
|
'';
|
||||||
in
|
in
|
||||||
pkgs.writeShellScriptBin "pre-commit-run" "${pkgs.lib.getExe package} run --all-files --config ${configFile}"
|
pkgs.writeShellScriptBin "pre-commit-run" script
|
||||||
);
|
);
|
||||||
|
|
||||||
checks = forAllSystems (
|
checks = forAllSystems (
|
||||||
pkgs:
|
system:
|
||||||
let
|
let
|
||||||
inherit (pkgs.stdenv.hostPlatform) system;
|
pkgs = nixpkgs.legacyPackages.${system};
|
||||||
|
flakePkgs = self.packages.${system};
|
||||||
|
overlaidPkgs = import nixpkgs {
|
||||||
|
inherit system;
|
||||||
|
overlays = [ self.overlays.modifications ];
|
||||||
|
};
|
||||||
in
|
in
|
||||||
{
|
{
|
||||||
pre-commit-check = inputs.git-hooks.lib.${system}.run {
|
pre-commit-check = inputs.git-hooks.lib.${system}.run {
|
||||||
src = ./.;
|
src = ./.;
|
||||||
hooks = {
|
hooks = {
|
||||||
actionlint.enable = true;
|
nixfmt.enable = true;
|
||||||
nixfmt = {
|
|
||||||
enable = true;
|
|
||||||
settings.width = 120;
|
|
||||||
};
|
|
||||||
shellcheck.enable = true;
|
|
||||||
statix.enable = true;
|
|
||||||
yamllint = {
|
|
||||||
enable = true;
|
|
||||||
excludes = [ "secrets.yaml" ];
|
|
||||||
settings.configData = "{rules: {line-length: {max: 120}}}";
|
|
||||||
};
|
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
build-packages = pkgs.linkFarm "flake-packages-${system}" flakePkgs;
|
||||||
build-additions = pkgs.linkFarm "added-packages-${system}" self.packages.${system};
|
build-overlays = pkgs.linkFarm "flake-overlays-${system}" {
|
||||||
build-modifications = pkgs.linkFarm "modified-packages-${system}" (
|
kicad = overlaidPkgs.kicad;
|
||||||
lib.filterAttrs (_: v: lib.isDerivation v) (self.overlays.modifications pkgs pkgs)
|
};
|
||||||
);
|
|
||||||
|
|
||||||
synapse-test =
|
synapse-test =
|
||||||
let
|
let
|
||||||
testPkgs = mkPkgs {
|
testPkgs = import nixpkgs {
|
||||||
inherit system;
|
inherit system;
|
||||||
config.permittedInsecurePackages = [ "olm-3.2.16" ];
|
config.permittedInsecurePackages = [ "olm-3.2.16" ];
|
||||||
};
|
};
|
||||||
in
|
in
|
||||||
testPkgs.testers.runNixOSTest ./tests/run/synapse.nix;
|
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 = {
|
hydraJobs = {
|
||||||
|
|
@ -283,10 +289,6 @@
|
||||||
path = ./templates/dev/rs-hello;
|
path = ./templates/dev/rs-hello;
|
||||||
description = "Rust hello world template.";
|
description = "Rust hello world template.";
|
||||||
};
|
};
|
||||||
stm32-blink = {
|
|
||||||
path = ./templates/dev/stm32-blink;
|
|
||||||
description = "STM32G4 blink template with libopencm3.";
|
|
||||||
};
|
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,3 @@
|
||||||
---
|
|
||||||
site_name: synix docs
|
site_name: synix docs
|
||||||
repo_url: https://git.sid.ovh/sid/synix
|
repo_url: https://git.sid.ovh/sid/synix
|
||||||
site_url: https://doc.sid.ovh/synix
|
site_url: https://doc.sid.ovh/synix
|
||||||
|
|
@ -21,7 +20,7 @@ markdown_extensions:
|
||||||
- pymdownx.superfences
|
- pymdownx.superfences
|
||||||
|
|
||||||
nav:
|
nav:
|
||||||
- Home: index.md # do not change
|
- Home: index.md # do not change
|
||||||
- Introduction to Nix:
|
- Introduction to Nix:
|
||||||
- Overview: introduction-to-nix/overview.md
|
- Overview: introduction-to-nix/overview.md
|
||||||
- Install Nix: introduction-to-nix/install-nix.md
|
- Install Nix: introduction-to-nix/install-nix.md
|
||||||
|
|
@ -59,6 +58,7 @@ nav:
|
||||||
- radicale: modules/nixos/radicale.md
|
- radicale: modules/nixos/radicale.md
|
||||||
- rss-bridge: modules/nixos/rss-bridge.md
|
- rss-bridge: modules/nixos/rss-bridge.md
|
||||||
- sops: modules/nixos/sops.md
|
- sops: modules/nixos/sops.md
|
||||||
|
- tailscale: modules/nixos/tailscale.md
|
||||||
- virtualisation: modules/nixos/virtualisation.md
|
- virtualisation: modules/nixos/virtualisation.md
|
||||||
- webPage: modules/nixos/webpage.md
|
- webPage: modules/nixos/webpage.md
|
||||||
- Home Manager:
|
- Home Manager:
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,3 @@
|
||||||
#!/usr/bin/env bash
|
|
||||||
# change directory with fzf
|
# change directory with fzf
|
||||||
# Usage: cdf [optional_relative_path]
|
# Usage: cdf [optional_relative_path]
|
||||||
# - If no argument, searches from $HOME.
|
# - If no argument, searches from $HOME.
|
||||||
|
|
@ -68,8 +67,7 @@ function cdf() {
|
||||||
"--preview=tree -C {} | head -50"
|
"--preview=tree -C {} | head -50"
|
||||||
"--preview-window=right:50%:wrap"
|
"--preview-window=right:50%:wrap"
|
||||||
)
|
)
|
||||||
local selected
|
local selected=$(find "${find_args[@]}" 2>/dev/null | fzf "${fzf_args[@]}")
|
||||||
selected=$(find "${find_args[@]}" 2>/dev/null | fzf "${fzf_args[@]}")
|
|
||||||
|
|
||||||
if [[ -n "$selected" ]]; then
|
if [[ -n "$selected" ]]; then
|
||||||
cd "$selected" || echo "Failed to cd into '$selected'"
|
cd "$selected" || echo "Failed to cd into '$selected'"
|
||||||
|
|
|
||||||
|
|
@ -1,48 +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;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
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;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
librewolf = mkIf config.programs.librewolf.enable {
|
|
||||||
profiles.default.extensions.packages =
|
|
||||||
with inputs.nur.legacyPackages."${pkgs.stdenv.hostPlatform.system}".repos.rycee.firefox-addons; [
|
|
||||||
bitwarden
|
|
||||||
];
|
|
||||||
};
|
|
||||||
};
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
@ -22,7 +22,7 @@ let
|
||||||
{
|
{
|
||||||
default = mkOption {
|
default = mkOption {
|
||||||
type = types.str;
|
type = types.str;
|
||||||
inherit default;
|
default = default;
|
||||||
description = "The default application to use for the ${default}.";
|
description = "The default application to use for the ${default}.";
|
||||||
};
|
};
|
||||||
bind = mkOption {
|
bind = mkOption {
|
||||||
|
|
@ -38,8 +38,12 @@ let
|
||||||
};
|
};
|
||||||
|
|
||||||
# generate lists of all binds and window rules and remove empty strings
|
# generate lists of all binds and window rules and remove empty strings
|
||||||
binds = filter (s: s != "") (builtins.concatLists (map (app: app.bind or [ "" ]) (attrValues apps)));
|
binds = filter (s: s != "") (
|
||||||
windowrules = filter (s: s != "") (builtins.concatLists (map (app: app.windowrule or [ "" ]) (attrValues apps)));
|
builtins.concatLists (map (app: app.bind or [ "" ]) (attrValues apps))
|
||||||
|
);
|
||||||
|
windowrules = filter (s: s != "") (
|
||||||
|
builtins.concatLists (map (app: app.windowrule or [ "" ]) (attrValues apps))
|
||||||
|
);
|
||||||
|
|
||||||
inherit (lib)
|
inherit (lib)
|
||||||
attrValues
|
attrValues
|
||||||
|
|
@ -52,10 +56,8 @@ let
|
||||||
in
|
in
|
||||||
{
|
{
|
||||||
imports = [
|
imports = [
|
||||||
./bitwarden
|
|
||||||
./bemenu
|
./bemenu
|
||||||
./dmenu-bluetooth
|
./dmenu-bluetooth
|
||||||
./dunst-toggle
|
|
||||||
./element-desktop
|
./element-desktop
|
||||||
./feh
|
./feh
|
||||||
./kitty
|
./kitty
|
||||||
|
|
@ -133,11 +135,6 @@ in
|
||||||
bind = [ "$mod SHIFT, m, exec, ${terminal} -T ${musicplayer} -e ${musicplayer}" ];
|
bind = [ "$mod SHIFT, m, exec, ${terminal} -T ${musicplayer} -e ${musicplayer}" ];
|
||||||
};
|
};
|
||||||
|
|
||||||
notifications = mkAppAttrs {
|
|
||||||
default = "dunst-toggle";
|
|
||||||
bind = [ "$mod, Backspace, exec, ${notifications}" ];
|
|
||||||
};
|
|
||||||
|
|
||||||
networksettings = mkAppAttrs {
|
networksettings = mkAppAttrs {
|
||||||
default = "networkmanager_dmenu";
|
default = "networkmanager_dmenu";
|
||||||
bind = [ "$mod SHIFT, n, exec, ${networksettings}" ];
|
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
|
|
||||||
''
|
|
||||||
|
|
@ -9,7 +9,7 @@ let
|
||||||
cfg = config.wayland.windowManager.hyprland;
|
cfg = config.wayland.windowManager.hyprland;
|
||||||
app = cfg.applications.rssreader.default;
|
app = cfg.applications.rssreader.default;
|
||||||
reloadTime = "${toString config.programs.newsboat.reloadTime}";
|
reloadTime = "${toString config.programs.newsboat.reloadTime}";
|
||||||
newsboat-reload = import ./newsboat-reload.nix { inherit config pkgs; };
|
newsboat-reload = (import ./newsboat-reload.nix { inherit config pkgs; });
|
||||||
|
|
||||||
inherit (lib) mkIf;
|
inherit (lib) mkIf;
|
||||||
in
|
in
|
||||||
|
|
@ -27,11 +27,9 @@ in
|
||||||
timers.newsboat-reload = {
|
timers.newsboat-reload = {
|
||||||
Unit.Description = "Reload newsboat every ${reloadTime} minutes";
|
Unit.Description = "Reload newsboat every ${reloadTime} minutes";
|
||||||
|
|
||||||
Timer = {
|
Timer.OnBootSec = "10sec";
|
||||||
OnBootSec = "10sec";
|
Timer.OnUnitActiveSec = "${reloadTime}min";
|
||||||
OnUnitActiveSec = "${reloadTime}min";
|
Timer.Unit = "newsboat-reload.service";
|
||||||
Unit = "newsboat-reload.service";
|
|
||||||
};
|
|
||||||
|
|
||||||
Install.WantedBy = [ "timers.target" ];
|
Install.WantedBy = [ "timers.target" ];
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,6 @@ let
|
||||||
notify = "${pkgs.libnotify}/bin/notify-send";
|
notify = "${pkgs.libnotify}/bin/notify-send";
|
||||||
signal = "${toString config.programs.waybar.settings.mainBar."custom/newsboat".signal}";
|
signal = "${toString config.programs.waybar.settings.mainBar."custom/newsboat".signal}";
|
||||||
in
|
in
|
||||||
pkgs.writeShellScriptBin "newsboat-reload" ''
|
(pkgs.writeShellScriptBin "newsboat-reload" ''
|
||||||
${notify} -u low 'Newsboat' 'Reloading RSS feeds...' && ${newsboat} -x reload && ${notify} -u low 'Newsboat' 'RSS feeds reloaded.' && pkill -RTMIN+${signal} waybar
|
${notify} -u low 'Newsboat' 'Reloading RSS feeds...' && ${newsboat} -x reload && ${notify} -u low 'Newsboat' 'RSS feeds reloaded.' && pkill -RTMIN+${signal} waybar
|
||||||
''
|
'')
|
||||||
|
|
|
||||||
|
|
@ -14,7 +14,9 @@ in
|
||||||
{
|
{
|
||||||
config = mkIf (cfg.enable && app == "presentation-mode-bemenu") {
|
config = mkIf (cfg.enable && app == "presentation-mode-bemenu") {
|
||||||
home.packages = [
|
home.packages = [
|
||||||
(pkgs.writeShellScriptBin "presentation-mode-bemenu" (builtins.readFile ./presentation-mode-bemenu.sh))
|
(pkgs.writeShellScriptBin "presentation-mode-bemenu" (
|
||||||
|
builtins.readFile ./presentation-mode-bemenu.sh
|
||||||
|
))
|
||||||
];
|
];
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,5 @@
|
||||||
#!/usr/bin/env bash
|
|
||||||
# Variables
|
# Variables
|
||||||
mapfile -t DISPLAYS < <(hyprctl monitors | grep -E '^Monitor' | awk '{print $2}')
|
DISPLAYS=( $(hyprctl monitors | grep -E '^Monitor' | awk '{print $2}') )
|
||||||
EXTEND_RIGHT="Extend to right of main"
|
EXTEND_RIGHT="Extend to right of main"
|
||||||
EXTEND_LEFT="Extend to left of main"
|
EXTEND_LEFT="Extend to left of main"
|
||||||
MIRROR="Mirror main"
|
MIRROR="Mirror main"
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,7 @@
|
||||||
let
|
let
|
||||||
screenshotDir = "${config.xdg.userDirs.pictures}/screenshots";
|
screenshotDir = "${config.xdg.userDirs.pictures}/screenshots";
|
||||||
in
|
in
|
||||||
pkgs.writeShellScriptBin "screenshot" ''
|
(pkgs.writeShellScriptBin "screenshot" ''
|
||||||
mkdir -p ${screenshotDir}
|
mkdir -p ${screenshotDir}
|
||||||
${pkgs.hyprshot}/bin/hyprshot --mode $1 --output-folder ${screenshotDir} --filename screenshot_$(date +"%Y-%m-%d_%H-%M-%S").png
|
${pkgs.hyprshot}/bin/hyprshot --mode $1 --output-folder ${screenshotDir} --filename screenshot_$(date +"%Y-%m-%d_%H-%M-%S").png
|
||||||
''
|
'')
|
||||||
|
|
|
||||||
|
|
@ -27,7 +27,7 @@ in
|
||||||
wayland.windowManager.hyprland = {
|
wayland.windowManager.hyprland = {
|
||||||
settings = {
|
settings = {
|
||||||
bind = binds;
|
bind = binds;
|
||||||
bindm = import ./mouse.nix;
|
bindm = (import ./mouse.nix);
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -9,19 +9,17 @@ let
|
||||||
inherit (lib) mkForce;
|
inherit (lib) mkForce;
|
||||||
in
|
in
|
||||||
{
|
{
|
||||||
home = {
|
home.pointerCursor = {
|
||||||
pointerCursor = {
|
name = mkForce "Bibata-Original-Ice";
|
||||||
name = mkForce "Bibata-Original-Ice";
|
size = mkForce 24;
|
||||||
size = mkForce 24;
|
package = mkForce pkgs.bibata-cursors;
|
||||||
package = mkForce pkgs.bibata-cursors;
|
};
|
||||||
};
|
|
||||||
|
|
||||||
packages = [ pkgs.hyprcursor ];
|
home.packages = [ pkgs.hyprcursor ];
|
||||||
|
|
||||||
sessionVariables = {
|
home.sessionVariables = {
|
||||||
HYPRCURSOR_THEME = config.home.pointerCursor.name;
|
HYPRCURSOR_THEME = config.home.pointerCursor.name;
|
||||||
HYPRCURSOR_SIZE = toString config.home.pointerCursor.size;
|
HYPRCURSOR_SIZE = toString config.home.pointerCursor.size;
|
||||||
};
|
|
||||||
};
|
};
|
||||||
|
|
||||||
# wayland.windowManager.hyprland.cursor.no_hardware_cursors = true;
|
# wayland.windowManager.hyprland.cursor.no_hardware_cursors = true;
|
||||||
|
|
|
||||||
|
|
@ -78,6 +78,12 @@ in
|
||||||
# auto discover fonts in `home.packages`
|
# auto discover fonts in `home.packages`
|
||||||
fonts.fontconfig.enable = true;
|
fonts.fontconfig.enable = true;
|
||||||
|
|
||||||
|
# notifications
|
||||||
|
services.dunst = {
|
||||||
|
enable = mkDefault true;
|
||||||
|
waylandDisplay = config.home.sessionVariables.WAYLAND_DISPLAY;
|
||||||
|
};
|
||||||
|
|
||||||
# install some applications
|
# install some applications
|
||||||
home.packages = import ./packages.nix { inherit pkgs; }; # use programs.PACKAGE or services.SERVICE when possible
|
home.packages = import ./packages.nix { inherit pkgs; }; # use programs.PACKAGE or services.SERVICE when possible
|
||||||
|
|
||||||
|
|
@ -88,19 +94,11 @@ in
|
||||||
fi
|
fi
|
||||||
'';
|
'';
|
||||||
|
|
||||||
# notifications
|
services.udiskie = {
|
||||||
services = {
|
enable = mkDefault true;
|
||||||
dunst = {
|
tray = mkDefault "never";
|
||||||
enable = mkDefault true;
|
|
||||||
waylandDisplay = config.home.sessionVariables.WAYLAND_DISPLAY;
|
|
||||||
};
|
|
||||||
|
|
||||||
udiskie = {
|
|
||||||
enable = mkDefault true;
|
|
||||||
tray = mkDefault "never";
|
|
||||||
};
|
|
||||||
|
|
||||||
network-manager-applet.enable = mkDefault true;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
services.network-manager-applet.enable = mkDefault true;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -3,30 +3,15 @@
|
||||||
let
|
let
|
||||||
cfg = config.wayland.windowManager.hyprland;
|
cfg = config.wayland.windowManager.hyprland;
|
||||||
|
|
||||||
nonCenterFloatingClasses = [
|
inherit (builtins) toString;
|
||||||
"Gimp"
|
|
||||||
"steam"
|
|
||||||
"KiCad"
|
|
||||||
];
|
|
||||||
|
|
||||||
nonCenterFloatingClassesRegex = concatStringsSep "|" nonCenterFloatingClasses;
|
|
||||||
|
|
||||||
inherit (builtins) concatStringsSep toString;
|
|
||||||
inherit (lib) mkDefault;
|
inherit (lib) mkDefault;
|
||||||
in
|
in
|
||||||
{
|
{
|
||||||
# Do not add binds here. Use `./binds/default.nix` instead.
|
# Do not add binds here. Use `./binds/default.nix` instead.
|
||||||
"$mod" = cfg.modifier;
|
"$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 = [
|
windowrule = [
|
||||||
# "float, class:^(${nonCenterFloatingClassesRegex})$"
|
"center, floating:1, not class:^(Gimp)$, not class:^(steam)$"
|
||||||
"center, floating:1, class:^(?!.*(${nonCenterFloatingClassesRegex})).*$"
|
|
||||||
"float, title:^(Open|Save) Files?$"
|
"float, title:^(Open|Save) Files?$"
|
||||||
"noborder, onworkspace:w[t1]"
|
"noborder, onworkspace:w[t1]"
|
||||||
"bordersize ${toString cfg.settings.general.border_size}, floating:1"
|
"bordersize ${toString cfg.settings.general.border_size}, floating:1"
|
||||||
|
|
@ -39,12 +24,6 @@ in
|
||||||
"noblur, class:^(xwaylandvideobridge)$"
|
"noblur, class:^(xwaylandvideobridge)$"
|
||||||
];
|
];
|
||||||
|
|
||||||
gesture = [
|
|
||||||
"3, horizontal, workspace"
|
|
||||||
"3, up, dispatcher, exec, bemenu-run" # TODO: move to hyprland.applications
|
|
||||||
"4, swipe, move"
|
|
||||||
];
|
|
||||||
|
|
||||||
# Layouts
|
# Layouts
|
||||||
general.layout = mkDefault "master";
|
general.layout = mkDefault "master";
|
||||||
master = {
|
master = {
|
||||||
|
|
|
||||||
|
|
@ -20,10 +20,8 @@ in
|
||||||
enable = mkDefault true;
|
enable = mkDefault true;
|
||||||
createDirectories = mkDefault true;
|
createDirectories = mkDefault true;
|
||||||
};
|
};
|
||||||
portal = {
|
portal.enable = mkDefault true;
|
||||||
enable = mkDefault true;
|
portal.extraPortals = [ portal ];
|
||||||
extraPortals = [ portal ];
|
portal.configPackages = [ portal ];
|
||||||
configPackages = [ portal ];
|
|
||||||
};
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -19,13 +19,13 @@ let
|
||||||
in
|
in
|
||||||
{
|
{
|
||||||
urls = [ { template = engine.url; } ];
|
urls = [ { template = engine.url; } ];
|
||||||
inherit (engine) icon;
|
icon = engine.icon;
|
||||||
updateInterval = if (isUrl engine.icon) then every_day else null;
|
updateInterval = if (isUrl engine.icon) then every_day else null;
|
||||||
definedAliases = optional (engine ? alias) engine.alias;
|
definedAliases = optional (engine ? alias) engine.alias;
|
||||||
};
|
};
|
||||||
|
|
||||||
transformedEngines = mapAttrs' (name: engine: {
|
transformedEngines = mapAttrs' (name: engine: {
|
||||||
inherit name;
|
name = name;
|
||||||
value = transformEngine engine;
|
value = transformEngine engine;
|
||||||
}) engines;
|
}) engines;
|
||||||
|
|
||||||
|
|
@ -79,7 +79,7 @@ in
|
||||||
profiles.default.search.engines = mapAttrs (_: name: transformedEngines.${name}) (
|
profiles.default.search.engines = mapAttrs (_: name: transformedEngines.${name}) (
|
||||||
listToAttrs (
|
listToAttrs (
|
||||||
map (name: {
|
map (name: {
|
||||||
inherit name;
|
name = name;
|
||||||
value = name;
|
value = name;
|
||||||
}) cfg.searchEngines
|
}) cfg.searchEngines
|
||||||
)
|
)
|
||||||
|
|
|
||||||
|
|
@ -1,71 +1,79 @@
|
||||||
[
|
[
|
||||||
|
# cursor navigation
|
||||||
{
|
{
|
||||||
options.desc = "scroll down, recenter";
|
# scroll down, recenter
|
||||||
key = "<C-d>";
|
key = "<C-d>";
|
||||||
action = "<C-d>zz";
|
action = "<C-d>zz";
|
||||||
mode = "n";
|
mode = "n";
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
options.desc = "scroll up, recenter";
|
# scroll up, recenter
|
||||||
key = "<C-u>";
|
key = "<C-u>";
|
||||||
action = "<C-u>zz";
|
action = "<C-u>zz";
|
||||||
mode = "n";
|
mode = "n";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# searching
|
||||||
{
|
{
|
||||||
options.desc = "center cursor after search next";
|
# center cursor after search next
|
||||||
key = "n";
|
key = "n";
|
||||||
action = "nzzzv";
|
action = "nzzzv";
|
||||||
mode = "n";
|
mode = "n";
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
options.desc = "center cursor after search previous";
|
# center cursor after search previous
|
||||||
key = "N";
|
key = "N";
|
||||||
action = "Nzzzv";
|
action = "Nzzzv";
|
||||||
mode = "n";
|
mode = "n";
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
options.desc = "ex command";
|
# ex command
|
||||||
key = "<leader>pv";
|
key = "<leader>pv";
|
||||||
action = "<cmd>Ex<CR>";
|
action = "<cmd>Ex<CR>";
|
||||||
mode = "n";
|
mode = "n";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# search and replace
|
||||||
{
|
{
|
||||||
options.desc = "search and replace word under cursor";
|
# search and replace word under cursor
|
||||||
key = "<leader>s";
|
key = "<leader>s";
|
||||||
action = ":%s/<C-r><C-w>/<C-r><C-w>/gI<Left><Left><Left>";
|
action = ":%s/<C-r><C-w>/<C-r><C-w>/gI<Left><Left><Left>";
|
||||||
mode = "n";
|
mode = "n";
|
||||||
}
|
}
|
||||||
|
# search and replace selected text
|
||||||
{
|
{
|
||||||
key = "<leader>s";
|
key = "<leader>s";
|
||||||
action = "y:%s/<C-r>0/<C-r>0/gI<Left><Left><Left>";
|
action = "y:%s/<C-r>0/<C-r>0/gI<Left><Left><Left>";
|
||||||
mode = "v";
|
mode = "v";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# clipboard operations
|
||||||
{
|
{
|
||||||
options.desc = "copy to system clipboard in visual mode";
|
# copy to system clipboard in visual mode
|
||||||
key = "<C-c>";
|
key = "<C-c>";
|
||||||
action = ''"+y '';
|
action = ''"+y '';
|
||||||
mode = "v";
|
mode = "v";
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
options.desc = "paste from system clipboard in visual mode";
|
# paste from system clipboard in visual mode
|
||||||
key = "<C-v>";
|
key = "<C-v>";
|
||||||
action = ''"+p '';
|
action = ''"+p '';
|
||||||
mode = "v";
|
mode = "v";
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
options.desc = "yank to system clipboard";
|
# yank to system clipboard
|
||||||
key = "<leader>Y";
|
key = "<leader>Y";
|
||||||
action = "+Y";
|
action = "+Y";
|
||||||
mode = "n";
|
mode = "n";
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
options.desc = "replace selected text with clipboard content";
|
# replace selected text with clipboard content
|
||||||
key = "<leader>p";
|
key = "<leader>p";
|
||||||
action = "_dP";
|
action = "_dP";
|
||||||
mode = "x";
|
mode = "x";
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
options.desc = "delete without copying to clipboard";
|
# delete without copying to clipboard
|
||||||
key = "<leader>d";
|
key = "<leader>d";
|
||||||
action = "_d";
|
action = "_d";
|
||||||
mode = [
|
mode = [
|
||||||
|
|
@ -73,184 +81,267 @@
|
||||||
"v"
|
"v"
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# line operations
|
||||||
{
|
{
|
||||||
options.desc = "move lines down in visual mode";
|
# move lines down in visual mode
|
||||||
key = "J";
|
key = "J";
|
||||||
action = ":m '>+1<CR>gv=gv";
|
action = ":m '>+1<CR>gv=gv";
|
||||||
mode = "v";
|
mode = "v";
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
options.desc = "move lines up in visual mode";
|
# move lines up in visual mode
|
||||||
key = "K";
|
key = "K";
|
||||||
action = ":m '<-2<CR>gv=gv";
|
action = ":m '<-2<CR>gv=gv";
|
||||||
mode = "v";
|
mode = "v";
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
options.desc = "join lines";
|
# join lines
|
||||||
key = "J";
|
key = "J";
|
||||||
action = "mzJ`z";
|
action = "mzJ`z";
|
||||||
mode = "n";
|
mode = "n";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# quickfix
|
||||||
{
|
{
|
||||||
options.desc = "Run make command";
|
# Run make command
|
||||||
key = "<leader>m";
|
key = "<leader>m";
|
||||||
action = "<cmd>:make<CR>";
|
action = "<cmd>:make<CR>";
|
||||||
mode = "n";
|
mode = "n";
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
options.desc = "previous quickfix item";
|
# previous quickfix item
|
||||||
key = "<C-A-J>";
|
key = "<C-A-J>";
|
||||||
action = "<cmd>cprev<CR>zz";
|
action = "<cmd>cprev<CR>zz";
|
||||||
mode = "n";
|
mode = "n";
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
options.desc = "next quickfix item";
|
# next quickfix item
|
||||||
key = "<C-A-K>";
|
key = "<C-A-K>";
|
||||||
action = "<cmd>cnext<CR>zz";
|
action = "<cmd>cnext<CR>zz";
|
||||||
mode = "n";
|
mode = "n";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# location list navigation
|
||||||
{
|
{
|
||||||
options.desc = "previous location list item";
|
# previous location list item
|
||||||
key = "<leader>j";
|
key = "<leader>j";
|
||||||
action = "<cmd>lprev<CR>zz";
|
action = "<cmd>lprev<CR>zz";
|
||||||
mode = "n";
|
mode = "n";
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
options.desc = "next location list item";
|
# next location list item
|
||||||
key = "<leader>k";
|
key = "<leader>k";
|
||||||
action = "<cmd>lnext<CR>zz";
|
action = "<cmd>lnext<CR>zz";
|
||||||
mode = "n";
|
mode = "n";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# disabling keys
|
||||||
{
|
{
|
||||||
options.desc = "disable the 'Q' key";
|
# disable the 'Q' key
|
||||||
key = "Q";
|
key = "Q";
|
||||||
action = "<nop>";
|
action = "<nop>";
|
||||||
mode = "n";
|
mode = "n";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# text selection
|
||||||
{
|
{
|
||||||
options.desc = "select whole buffer";
|
# select whole buffer
|
||||||
key = "<C-a>";
|
key = "<C-a>";
|
||||||
action = "ggVG";
|
action = "ggVG";
|
||||||
mode = "n";
|
mode = "n";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# window operations
|
||||||
{
|
{
|
||||||
options.desc = "focus next window";
|
# focus next window
|
||||||
key = "<C-j>";
|
key = "<C-j>";
|
||||||
action = ":wincmd W<CR>";
|
action = ":wincmd W<CR>";
|
||||||
|
options = {
|
||||||
|
noremap = true;
|
||||||
|
silent = true;
|
||||||
|
};
|
||||||
mode = "n";
|
mode = "n";
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
options.desc = "focus next window";
|
# focus previous window
|
||||||
key = "<Tab>";
|
|
||||||
action = ":wincmd W<CR>";
|
|
||||||
mode = "n";
|
|
||||||
}
|
|
||||||
{
|
|
||||||
options.desc = "focus previous window";
|
|
||||||
key = "<C-k>";
|
key = "<C-k>";
|
||||||
action = ":wincmd w<CR>";
|
action = ":wincmd w<CR>";
|
||||||
|
options = {
|
||||||
|
noremap = true;
|
||||||
|
silent = true;
|
||||||
|
};
|
||||||
mode = "n";
|
mode = "n";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# window size adjustments
|
||||||
{
|
{
|
||||||
options.desc = "focus previous window";
|
# increase window width
|
||||||
key = "<S-Tab>";
|
|
||||||
action = ":wincmd w<CR>";
|
|
||||||
mode = "n";
|
|
||||||
}
|
|
||||||
{
|
|
||||||
options.desc = "increase window width";
|
|
||||||
key = "<C-l>";
|
key = "<C-l>";
|
||||||
action = ":vertical resize +5<CR>";
|
action = ":vertical resize +5<CR>";
|
||||||
|
options = {
|
||||||
|
noremap = true;
|
||||||
|
silent = true;
|
||||||
|
};
|
||||||
mode = "n";
|
mode = "n";
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
options.desc = "decrease window width";
|
# decrease window width
|
||||||
key = "<C-h>";
|
key = "<C-h>";
|
||||||
action = ":vertical resize -5<CR>";
|
action = ":vertical resize -5<CR>";
|
||||||
|
options = {
|
||||||
|
noremap = true;
|
||||||
|
silent = true;
|
||||||
|
};
|
||||||
mode = "n";
|
mode = "n";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# window closing and opening
|
||||||
{
|
{
|
||||||
options.desc = "close current window";
|
# close current window
|
||||||
key = "<leader-S>c";
|
key = "<leader-S>c";
|
||||||
action = ":q<CR>";
|
action = ":q<CR>";
|
||||||
|
options = {
|
||||||
|
noremap = true;
|
||||||
|
silent = true;
|
||||||
|
};
|
||||||
mode = "n";
|
mode = "n";
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
options.desc = "new vertical split at $HOME";
|
# new vertical split at $HOME
|
||||||
key = "<leader>n";
|
key = "<leader>n";
|
||||||
action = ":vsp $HOME<CR>";
|
action = ":vsp $HOME<CR>";
|
||||||
|
options = {
|
||||||
|
noremap = true;
|
||||||
|
silent = true;
|
||||||
|
};
|
||||||
mode = "n";
|
mode = "n";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# window split orientation toggling
|
||||||
{
|
{
|
||||||
options.desc = "toggle split orientation";
|
# toggle split orientation
|
||||||
key = "<leader>t";
|
key = "<leader>t";
|
||||||
action = ":wincmd T<CR>";
|
action = ":wincmd T<CR>";
|
||||||
|
options = {
|
||||||
|
noremap = true;
|
||||||
|
silent = true;
|
||||||
|
};
|
||||||
mode = "n";
|
mode = "n";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# spell checking
|
||||||
{
|
{
|
||||||
options.desc = "toggle spell checking";
|
# toggle spell checking
|
||||||
key = "<leader>ss";
|
key = "<leader>ss";
|
||||||
action = ":setlocal spell!<CR>";
|
action = ":setlocal spell!<CR>";
|
||||||
|
options = {
|
||||||
|
noremap = true;
|
||||||
|
silent = true;
|
||||||
|
};
|
||||||
mode = "n";
|
mode = "n";
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
options.desc = "switch to english spell checking";
|
# switch to english spell checking
|
||||||
key = "<leader>se";
|
key = "<leader>se";
|
||||||
action = ":setlocal spelllang=en_us<CR>";
|
action = ":setlocal spelllang=en_us<CR>";
|
||||||
|
options = {
|
||||||
|
noremap = true;
|
||||||
|
silent = true;
|
||||||
|
};
|
||||||
mode = "n";
|
mode = "n";
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
options.desc = "switch to german spell checking";
|
# switch to german spell checking
|
||||||
key = "<leader>sg";
|
key = "<leader>sg";
|
||||||
action = ":setlocal spelllang=de_20<CR>";
|
action = ":setlocal spelllang=de_20<CR>";
|
||||||
|
options = {
|
||||||
|
noremap = true;
|
||||||
|
silent = true;
|
||||||
|
};
|
||||||
mode = "n";
|
mode = "n";
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
options.desc = "move to next misspelling";
|
# move to next misspelling
|
||||||
key = "]s";
|
key = "]s";
|
||||||
action = "]szz";
|
action = "]szz";
|
||||||
|
options = {
|
||||||
|
noremap = true;
|
||||||
|
silent = true;
|
||||||
|
};
|
||||||
mode = "n";
|
mode = "n";
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
options.desc = "move to previous misspelling";
|
# move to previous misspelling
|
||||||
key = "[s";
|
key = "[s";
|
||||||
action = "[szz";
|
action = "[szz";
|
||||||
|
options = {
|
||||||
|
noremap = true;
|
||||||
|
silent = true;
|
||||||
|
};
|
||||||
mode = "n";
|
mode = "n";
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
options.desc = "correction suggestions for a misspelled word";
|
# correction suggestions for a misspelled word
|
||||||
key = "z=";
|
key = "z=";
|
||||||
action = "z=";
|
action = "z=";
|
||||||
|
options = {
|
||||||
|
noremap = true;
|
||||||
|
silent = true;
|
||||||
|
};
|
||||||
mode = "n";
|
mode = "n";
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
options.desc = "adding words to the dictionary";
|
# adding words to the dictionary
|
||||||
key = "zg";
|
key = "zg";
|
||||||
action = "zg";
|
action = "zg";
|
||||||
|
options = {
|
||||||
|
noremap = true;
|
||||||
|
silent = true;
|
||||||
|
};
|
||||||
mode = "n";
|
mode = "n";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# buffer navigation
|
||||||
{
|
{
|
||||||
options.desc = "next buffer";
|
# next buffer
|
||||||
key = "<C-S-J>";
|
key = "<C-S-J>";
|
||||||
action = ":bnext<CR>";
|
action = ":bnext<CR>";
|
||||||
|
options = {
|
||||||
|
noremap = true;
|
||||||
|
silent = true;
|
||||||
|
};
|
||||||
mode = "n";
|
mode = "n";
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
options.desc = "previous buffer";
|
# previous buffer
|
||||||
key = "<C-S-K>";
|
key = "<C-S-K>";
|
||||||
action = ":bprevious<CR>";
|
action = ":bprevious<CR>";
|
||||||
|
options = {
|
||||||
|
noremap = true;
|
||||||
|
silent = true;
|
||||||
|
};
|
||||||
mode = "n";
|
mode = "n";
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
options.desc = "close current buffer";
|
# close current buffer
|
||||||
key = "<leader>bd";
|
key = "<leader>bd";
|
||||||
action = ":bdelete<CR>";
|
action = ":bdelete<CR>";
|
||||||
|
options = {
|
||||||
|
noremap = true;
|
||||||
|
silent = true;
|
||||||
|
};
|
||||||
mode = "n";
|
mode = "n";
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
options.desc = "apply code action";
|
# apply code action
|
||||||
key = "<leader>ca";
|
key = "<leader>ca";
|
||||||
action = ":lua vim.lsp.buf.code_action()<CR>";
|
action = ":lua vim.lsp.buf.code_action()<CR>";
|
||||||
|
options = {
|
||||||
|
noremap = true;
|
||||||
|
silent = true;
|
||||||
|
};
|
||||||
mode = "n";
|
mode = "n";
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|
|
||||||
|
|
@ -3,17 +3,14 @@
|
||||||
{
|
{
|
||||||
imports = [
|
imports = [
|
||||||
./cmp.nix
|
./cmp.nix
|
||||||
./diffview.nix
|
|
||||||
./lsp.nix
|
./lsp.nix
|
||||||
./gitsigns.nix
|
|
||||||
./lualine.nix
|
./lualine.nix
|
||||||
./telescope.nix
|
./telescope.nix
|
||||||
./treesitter.nix
|
# ./treesitter.nix # HOTFIX: does not build
|
||||||
./trouble.nix
|
./trouble.nix
|
||||||
];
|
];
|
||||||
|
|
||||||
config.programs.nixvim.plugins = {
|
config.programs.nixvim.plugins = {
|
||||||
which-key.enable = lib.mkDefault true;
|
|
||||||
markdown-preview.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`
|
# 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;
|
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 = {
|
programs.nixvim = {
|
||||||
plugins.telescope = {
|
plugins.telescope = {
|
||||||
enable = mkDefault true;
|
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 = {
|
extensions = {
|
||||||
file-browser.enable = mkDefault true;
|
file-browser.enable = mkDefault true;
|
||||||
fzf-native.enable = mkDefault true;
|
fzf-native.enable = mkDefault true;
|
||||||
|
|
|
||||||
|
|
@ -16,19 +16,17 @@ in
|
||||||
{
|
{
|
||||||
config = {
|
config = {
|
||||||
programs.nixvim = {
|
programs.nixvim = {
|
||||||
plugins = {
|
plugins.treesitter = {
|
||||||
treesitter = {
|
enable = mkDefault true;
|
||||||
enable = mkDefault true;
|
nixvimInjections = mkDefault true;
|
||||||
nixvimInjections = mkDefault true;
|
settings = {
|
||||||
settings = {
|
folding.enable = mkDefault true;
|
||||||
folding.enable = mkDefault true;
|
highlight.enable = mkDefault true;
|
||||||
highlight.enable = mkDefault true;
|
indent.enable = mkDefault true;
|
||||||
indent.enable = mkDefault true;
|
|
||||||
};
|
|
||||||
};
|
};
|
||||||
treesitter-context = mkIf plugin.enable { enable = mkDefault true; };
|
|
||||||
treesitter-textobjects = mkIf plugin.enable { enable = mkDefault true; };
|
|
||||||
};
|
};
|
||||||
|
plugins.treesitter-context = mkIf plugin.enable { enable = mkDefault true; };
|
||||||
|
plugins.treesitter-textobjects = mkIf plugin.enable { enable = mkDefault true; };
|
||||||
};
|
};
|
||||||
|
|
||||||
# Fix for: ERROR `cc` executable not found.
|
# Fix for: ERROR `cc` executable not found.
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
let
|
let
|
||||||
spellDir = config.xdg.dataHome + "/nvim/site/spell";
|
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
|
in
|
||||||
{
|
{
|
||||||
home.file = {
|
home.file = {
|
||||||
|
|
@ -12,7 +12,7 @@ in
|
||||||
url = baseUrl + "/de.utf-8.spl";
|
url = baseUrl + "/de.utf-8.spl";
|
||||||
sha256 = "sha256-c8cQfqM5hWzb6SHeuSpFk5xN5uucByYdobndGfaDo9E=";
|
sha256 = "sha256-c8cQfqM5hWzb6SHeuSpFk5xN5uucByYdobndGfaDo9E=";
|
||||||
};
|
};
|
||||||
target = spellDir + "/de.utf-8.spl";
|
target = spellDir + "/de.utf8.spl";
|
||||||
};
|
};
|
||||||
de-sug = {
|
de-sug = {
|
||||||
enable = true;
|
enable = true;
|
||||||
|
|
@ -20,7 +20,7 @@ in
|
||||||
url = baseUrl + "/de.utf-8.sug";
|
url = baseUrl + "/de.utf-8.sug";
|
||||||
sha256 = "sha256-E9Ds+Shj2J72DNSopesqWhOg6Pm6jRxqvkerqFcUqUg=";
|
sha256 = "sha256-E9Ds+Shj2J72DNSopesqWhOg6Pm6jRxqvkerqFcUqUg=";
|
||||||
};
|
};
|
||||||
target = spellDir + "/de.utf-8.sug";
|
target = spellDir + "/de.utf8.sug";
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -9,7 +9,7 @@
|
||||||
let
|
let
|
||||||
cfg = config.programs.passwordManager;
|
cfg = config.programs.passwordManager;
|
||||||
passmenuScript = pkgs.writeShellScriptBin "passmenu-bemenu" (builtins.readFile ./passmenu); # TODO: override original passmenu script coming from pass itself
|
passmenuScript = pkgs.writeShellScriptBin "passmenu-bemenu" (builtins.readFile ./passmenu); # TODO: override original passmenu script coming from pass itself
|
||||||
inherit (pkgs) passff-host;
|
passff-host = pkgs.passff-host;
|
||||||
|
|
||||||
inherit (lib)
|
inherit (lib)
|
||||||
mkDefault
|
mkDefault
|
||||||
|
|
|
||||||
|
|
@ -17,7 +17,6 @@ let
|
||||||
"moonfly"
|
"moonfly"
|
||||||
"nord"
|
"nord"
|
||||||
"oxocarbon"
|
"oxocarbon"
|
||||||
"generate-from-image"
|
|
||||||
];
|
];
|
||||||
# schemes names in `pkgs.base16-schemes` that need a suffix
|
# schemes names in `pkgs.base16-schemes` that need a suffix
|
||||||
needsSuffix = [
|
needsSuffix = [
|
||||||
|
|
@ -29,7 +28,13 @@ let
|
||||||
"moonfly"
|
"moonfly"
|
||||||
"oxocarbon"
|
"oxocarbon"
|
||||||
];
|
];
|
||||||
schemeName = if builtins.elem cfg.scheme needsSuffix then "${cfg.scheme}-${cfg.polarity}" else cfg.scheme;
|
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)
|
inherit (lib)
|
||||||
mkDefault
|
mkDefault
|
||||||
|
|
@ -51,8 +56,6 @@ in
|
||||||
description = ''
|
description = ''
|
||||||
Base16 color scheme name. Available options are:
|
Base16 color scheme name. Available options are:
|
||||||
${toString validSchemes}
|
${toString validSchemes}
|
||||||
|
|
||||||
"generate-from-image" generates a color scheme from `stylix.image`
|
|
||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
@ -67,12 +70,7 @@ in
|
||||||
|
|
||||||
stylix = {
|
stylix = {
|
||||||
autoEnable = mkDefault true;
|
autoEnable = mkDefault true;
|
||||||
base16Scheme = mkIf (cfg.scheme != "generate-from-image") (
|
base16Scheme = scheme;
|
||||||
if builtins.elem cfg.scheme customSchemes then
|
|
||||||
./schemes/${schemeName}.yaml
|
|
||||||
else
|
|
||||||
"${pkgs.base16-schemes}/share/themes/${schemeName}.yaml"
|
|
||||||
);
|
|
||||||
fonts = {
|
fonts = {
|
||||||
monospace = mkDefault {
|
monospace = mkDefault {
|
||||||
package = pkgs.hack-font;
|
package = pkgs.hack-font;
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,3 @@
|
||||||
---
|
|
||||||
system: "base16"
|
system: "base16"
|
||||||
name: "Moonfly"
|
name: "Moonfly"
|
||||||
description: "A dark theme inspired by the Moonfly color scheme."
|
description: "A dark theme inspired by the Moonfly color scheme."
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,3 @@
|
||||||
---
|
|
||||||
system: "base16"
|
system: "base16"
|
||||||
name: "Oxocarbon"
|
name: "Oxocarbon"
|
||||||
description: "A dark theme inspired by the Oxocarbon Dark color scheme."
|
description: "A dark theme inspired by the Oxocarbon Dark color scheme."
|
||||||
|
|
|
||||||
|
|
@ -4,13 +4,11 @@ let
|
||||||
cfg = config.stylix;
|
cfg = config.stylix;
|
||||||
target = cfg.targets.nixvim;
|
target = cfg.targets.nixvim;
|
||||||
|
|
||||||
inherit (lib) mkIf optionalAttrs;
|
inherit (lib) mkIf;
|
||||||
in
|
in
|
||||||
{
|
{
|
||||||
config = mkIf cfg.enable {
|
config = mkIf cfg.enable {
|
||||||
stylix.targets.nixvim.enable = false;
|
stylix.targets.nixvim.enable = false;
|
||||||
programs.nixvim.colorschemes = optionalAttrs (cfg.scheme != "generate-from-image") {
|
programs.nixvim.colorschemes."${cfg.scheme}".enable = !target.enable;
|
||||||
"${cfg.scheme}".enable = !target.enable;
|
|
||||||
};
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -71,11 +71,11 @@ in
|
||||||
|
|
||||||
#workspaces {
|
#workspaces {
|
||||||
color: ${colors.base05};
|
color: ${colors.base05};
|
||||||
|
background: ${colors.base00};
|
||||||
}
|
}
|
||||||
|
|
||||||
#workspaces button {
|
#workspaces button {
|
||||||
padding: ${halfgaps}px;
|
padding: ${halfgaps}px;
|
||||||
color: ${colors.base05};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#workspaces button.active {
|
#workspaces button.active {
|
||||||
|
|
|
||||||
|
|
@ -56,7 +56,6 @@ let
|
||||||
};
|
};
|
||||||
|
|
||||||
# Add your custom modules here
|
# Add your custom modules here
|
||||||
"custom/notifications" = import ./modules/notifications.nix { inherit lib pkgs; };
|
|
||||||
"custom/newsboat" = import ./modules/newsboat.nix { inherit lib pkgs; };
|
"custom/newsboat" = import ./modules/newsboat.nix { inherit lib pkgs; };
|
||||||
"pulseaudio#input" = import ./modules/pulseaudio/input.nix { inherit lib pkgs; };
|
"pulseaudio#input" = import ./modules/pulseaudio/input.nix { inherit lib pkgs; };
|
||||||
"pulseaudio#output" = import ./modules/pulseaudio/output.nix { inherit lib pkgs; };
|
"pulseaudio#output" = import ./modules/pulseaudio/output.nix { inherit lib pkgs; };
|
||||||
|
|
@ -96,13 +95,11 @@ in
|
||||||
"disk"
|
"disk"
|
||||||
"pulseaudio#input"
|
"pulseaudio#input"
|
||||||
"pulseaudio#output"
|
"pulseaudio#output"
|
||||||
"custom/notifications"
|
|
||||||
"tray"
|
"tray"
|
||||||
];
|
];
|
||||||
|
|
||||||
inherit
|
inherit
|
||||||
"custom/newsboat"
|
"custom/newsboat"
|
||||||
"custom/notifications"
|
|
||||||
"hyprland/language"
|
"hyprland/language"
|
||||||
"hyprland/workspaces"
|
"hyprland/workspaces"
|
||||||
"pulseaudio#input"
|
"pulseaudio#input"
|
||||||
|
|
@ -132,7 +129,5 @@ in
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
services.batsignal.enable = builtins.elem "battery" cfg.settings.mainBar.modules-right;
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -10,13 +10,13 @@ let
|
||||||
let
|
let
|
||||||
newsboat = "${pkgs.newsboat}/bin/newsboat";
|
newsboat = "${pkgs.newsboat}/bin/newsboat";
|
||||||
in
|
in
|
||||||
pkgs.writeShellScriptBin "newsboat-print-unread" ''
|
(pkgs.writeShellScriptBin "newsboat-print-unread" ''
|
||||||
UNREAD=$(${newsboat} -x print-unread | awk '{print $1}')
|
UNREAD=$(${newsboat} -x print-unread | awk '{print $1}')
|
||||||
|
|
||||||
if [[ $UNREAD -gt 0 ]]; then
|
if [[ $UNREAD -gt 0 ]]; then
|
||||||
printf " %i" "$UNREAD"
|
printf " %i" "$UNREAD"
|
||||||
fi
|
fi
|
||||||
'';
|
'');
|
||||||
|
|
||||||
inherit (lib) mkDefault;
|
inherit (lib) mkDefault;
|
||||||
in
|
in
|
||||||
|
|
|
||||||
|
|
@ -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;
|
|
||||||
}
|
|
||||||
|
|
@ -1,4 +1,3 @@
|
||||||
#!/usr/bin/env bash
|
|
||||||
TIMER_FILE="/tmp/timer" # file to store the current time
|
TIMER_FILE="/tmp/timer" # file to store the current time
|
||||||
SIGNAL=11 # signal number to send to status bar
|
SIGNAL=11 # signal number to send to status bar
|
||||||
STATUS_BAR="waybar" # Support for more status bars?
|
STATUS_BAR="waybar" # Support for more status bars?
|
||||||
|
|
@ -17,7 +16,7 @@ start_timer() {
|
||||||
notify-send "Timer Started" "Your countdown timer has been started."
|
notify-send "Timer Started" "Your countdown timer has been started."
|
||||||
|
|
||||||
trap "exit" INT TERM
|
trap "exit" INT TERM
|
||||||
trap 'rm -f -- "$TIMER_FILE"' EXIT
|
trap "rm -f -- '$TIMER_FILE'" EXIT
|
||||||
|
|
||||||
while [ $total_seconds -gt 0 ]; do
|
while [ $total_seconds -gt 0 ]; do
|
||||||
hours=$(( total_seconds / 3600 ))
|
hours=$(( total_seconds / 3600 ))
|
||||||
|
|
@ -63,7 +62,7 @@ if [ "$1" = "start" ]; then
|
||||||
MINUTES=${MINUTES:-0}
|
MINUTES=${MINUTES:-0}
|
||||||
SECONDS=${SECONDS:-0}
|
SECONDS=${SECONDS:-0}
|
||||||
|
|
||||||
start_timer "$HOURS" "$MINUTES" "$SECONDS"
|
start_timer $HOURS $MINUTES $SECONDS
|
||||||
|
|
||||||
elif [ "$1" = "stop" ]; then
|
elif [ "$1" = "stop" ]; then
|
||||||
notify-send "Timer Stopped" "Your countdown timer has been stopped."
|
notify-send "Timer Stopped" "Your countdown timer has been stopped."
|
||||||
|
|
|
||||||
|
|
@ -6,19 +6,19 @@
|
||||||
environment.systemPackages = with pkgs; [
|
environment.systemPackages = with pkgs; [
|
||||||
lact
|
lact
|
||||||
nvtopPackages.amd
|
nvtopPackages.amd
|
||||||
|
rocmPackages.clr.icd
|
||||||
rocmPackages.hipcc
|
rocmPackages.hipcc
|
||||||
rocmPackages.miopen
|
rocmPackages.miopen
|
||||||
rocmPackages.rocm-runtime
|
rocmPackages.rocm-runtime
|
||||||
rocmPackages.rocm-smi
|
rocmPackages.rocm-smi
|
||||||
rocmPackages.rocminfo
|
rocmPackages.rocminfo
|
||||||
|
|
||||||
];
|
];
|
||||||
|
|
||||||
# environment.variables.ROC_ENABLE_PRE_VEGA = "1"; # for Polaris
|
# environment.variables.ROC_ENABLE_PRE_VEGA = "1"; # for Polaris
|
||||||
|
|
||||||
hardware.amdgpu.opencl.enable = true;
|
hardware.amdgpu.opencl.enable = true;
|
||||||
|
|
||||||
hardware.graphics.extraPackages = with pkgs; [ rocmPackages.clr.icd ];
|
|
||||||
|
|
||||||
systemd.packages = with pkgs; [ lact ];
|
systemd.packages = with pkgs; [ lact ];
|
||||||
systemd.services.lactd.wantedBy = [ "multi-user.target" ];
|
systemd.services.lactd.wantedBy = [ "multi-user.target" ];
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -4,16 +4,10 @@ let
|
||||||
inherit (lib) mkDefault;
|
inherit (lib) mkDefault;
|
||||||
in
|
in
|
||||||
{
|
{
|
||||||
hardware = {
|
hardware.bluetooth.enable = mkDefault true;
|
||||||
bluetooth = {
|
hardware.bluetooth.powerOnBoot = mkDefault false;
|
||||||
enable = mkDefault true;
|
hardware.bluetooth.settings.General.Enable = mkDefault "Source,Sink,Media,Socket";
|
||||||
powerOnBoot = mkDefault false;
|
hardware.bluetooth.settings.General.Experimental = mkDefault true;
|
||||||
settings.General = {
|
|
||||||
Enable = mkDefault "Source,Sink,Media,Socket";
|
|
||||||
Experimental = mkDefault true;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
environment.systemPackages = with pkgs; [
|
environment.systemPackages = with pkgs; [
|
||||||
blueman
|
blueman
|
||||||
|
|
|
||||||
|
|
@ -84,6 +84,8 @@ in
|
||||||
) { } cfg.remotes;
|
) { } cfg.remotes;
|
||||||
|
|
||||||
# Ensure that all cifs-mount services are started with the graphical session
|
# Ensure that all cifs-mount services are started with the graphical session
|
||||||
systemd.user.targets.graphical-session.wants = map (remote: "cifs-mount-${remote.shareName}.service") cfg.remotes;
|
systemd.user.targets.graphical-session.wants = map (
|
||||||
|
remote: "cifs-mount-${remote.shareName}.service"
|
||||||
|
) cfg.remotes;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,20 +0,0 @@
|
||||||
{ lib, pkgs, ... }:
|
|
||||||
|
|
||||||
{
|
|
||||||
boot = {
|
|
||||||
# fix CVE-2026-31431
|
|
||||||
kernelPackages = lib.mkIf (lib.versionOlder pkgs.linux.version "6.18.22") (lib.mkDefault pkgs.linuxPackages_6_18);
|
|
||||||
|
|
||||||
# fix CVE-2026-43500
|
|
||||||
extraModprobeConfig = ''
|
|
||||||
install esp4 ${pkgs.coreutils}/bin/false
|
|
||||||
install esp6 ${pkgs.coreutils}/bin/false
|
|
||||||
install rxrpc ${pkgs.coreutils}/bin/false
|
|
||||||
'';
|
|
||||||
blacklistedKernelModules = [
|
|
||||||
"esp4"
|
|
||||||
"esp6"
|
|
||||||
"rxrpc"
|
|
||||||
];
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
@ -1,6 +1,5 @@
|
||||||
{
|
{
|
||||||
imports = [
|
imports = [
|
||||||
./boot.nix
|
|
||||||
./environment.nix
|
./environment.nix
|
||||||
./htop.nix
|
./htop.nix
|
||||||
./nationalization.nix
|
./nationalization.nix
|
||||||
|
|
|
||||||
|
|
@ -9,59 +9,55 @@ let
|
||||||
inherit (lib) mkDefault optionals;
|
inherit (lib) mkDefault optionals;
|
||||||
in
|
in
|
||||||
{
|
{
|
||||||
environment = {
|
environment.systemPackages =
|
||||||
systemPackages =
|
with pkgs;
|
||||||
with pkgs;
|
[
|
||||||
[
|
cryptsetup
|
||||||
cryptsetup
|
curl
|
||||||
curl
|
dig
|
||||||
dig
|
dnsutils
|
||||||
dnsutils
|
fzf
|
||||||
fzf
|
gptfdisk
|
||||||
gptfdisk
|
iproute2
|
||||||
iproute2
|
jq
|
||||||
jq
|
lm_sensors
|
||||||
lm_sensors
|
lsof
|
||||||
lsof
|
netcat-openbsd
|
||||||
netcat-openbsd
|
nettools
|
||||||
nettools
|
nixos-container
|
||||||
nixos-container
|
nmap
|
||||||
nmap
|
nurl
|
||||||
nurl
|
p7zip
|
||||||
p7zip
|
pciutils
|
||||||
pciutils
|
psmisc
|
||||||
psmisc
|
rclone
|
||||||
rclone
|
rsync
|
||||||
rsync
|
tcpdump
|
||||||
tcpdump
|
tmux
|
||||||
tmux
|
tree
|
||||||
tree
|
unzip
|
||||||
unzip
|
usbutils
|
||||||
usbutils
|
wget
|
||||||
wget
|
xxd
|
||||||
xxd
|
zip
|
||||||
zip
|
|
||||||
|
|
||||||
(callPackage ../../../apps/rebuild { })
|
(callPackage ../../../apps/rebuild { })
|
||||||
]
|
]
|
||||||
++ optionals (pkgs.stdenv.hostPlatform == pkgs.stdenv.buildPlatform) [
|
++ optionals (pkgs.stdenv.hostPlatform == pkgs.stdenv.buildPlatform) [
|
||||||
pkgs.kitty.terminfo
|
pkgs.kitty.terminfo
|
||||||
];
|
];
|
||||||
|
|
||||||
shellAliases = {
|
environment.shellAliases = {
|
||||||
l = "ls -lh";
|
l = "ls -lh";
|
||||||
ll = "ls -lAh";
|
ll = "ls -lAh";
|
||||||
ports = "ss -tulpn";
|
ports = "ss -tulpn";
|
||||||
publicip = "curl ifconfig.me/all";
|
publicip = "curl ifconfig.me/all";
|
||||||
sudo = "sudo "; # make aliases work with `sudo`
|
sudo = "sudo "; # make aliases work with `sudo`
|
||||||
};
|
|
||||||
|
|
||||||
# saves one instance of nixpkgs.
|
|
||||||
ldso32 = null;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
boot = {
|
# saves one instance of nixpkgs.
|
||||||
tmp.cleanOnBoot = mkDefault true;
|
environment.ldso32 = null;
|
||||||
initrd.systemd.enable = mkDefault (!config.boot.swraid.enable && !config.boot.isContainer);
|
|
||||||
};
|
boot.tmp.cleanOnBoot = mkDefault true;
|
||||||
|
boot.initrd.systemd.enable = mkDefault (!config.boot.swraid.enable && !config.boot.isContainer);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -2,13 +2,16 @@
|
||||||
# avoid TOFU MITM
|
# avoid TOFU MITM
|
||||||
programs.ssh.knownHosts = {
|
programs.ssh.knownHosts = {
|
||||||
"github.com".hostNames = [ "github.com" ];
|
"github.com".hostNames = [ "github.com" ];
|
||||||
"github.com".publicKey = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIOMqqnkVzrm0SdG6UOoqKLsabgH5C9okWi0dh2l9GKJl";
|
"github.com".publicKey =
|
||||||
|
"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIOMqqnkVzrm0SdG6UOoqKLsabgH5C9okWi0dh2l9GKJl";
|
||||||
|
|
||||||
"gitlab.com".hostNames = [ "gitlab.com" ];
|
"gitlab.com".hostNames = [ "gitlab.com" ];
|
||||||
"gitlab.com".publicKey = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIAfuCHKVTjquxvt6CM6tdG4SLp1Btn/nOeHHE5UOzRdf";
|
"gitlab.com".publicKey =
|
||||||
|
"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIAfuCHKVTjquxvt6CM6tdG4SLp1Btn/nOeHHE5UOzRdf";
|
||||||
|
|
||||||
"git.sr.ht".hostNames = [ "git.sr.ht" ];
|
"git.sr.ht".hostNames = [ "git.sr.ht" ];
|
||||||
"git.sr.ht".publicKey = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIMZvRd4EtM7R+IHVMWmDkVU3VLQTSwQDSAvW0t2Tkj60";
|
"git.sr.ht".publicKey =
|
||||||
|
"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIMZvRd4EtM7R+IHVMWmDkVU3VLQTSwQDSAvW0t2Tkj60";
|
||||||
};
|
};
|
||||||
# TODO: add synix
|
# TODO: add synix
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -42,8 +42,12 @@ in
|
||||||
static-auth-secret-file = mkIf cfg.sops config.sops.secrets."coturn/static-auth-secret".path;
|
static-auth-secret-file = mkIf cfg.sops config.sops.secrets."coturn/static-auth-secret".path;
|
||||||
realm = mkDefault "turn.${config.networking.domain}";
|
realm = mkDefault "turn.${config.networking.domain}";
|
||||||
|
|
||||||
cert = mkIf (!cfg.no-tls && cfg.sops) "${config.security.acme.certs.${cfg.realm}.directory}/full.pem";
|
cert =
|
||||||
pkey = mkIf (!cfg.no-tls && cfg.sops) "${config.security.acme.certs.${cfg.realm}.directory}/key.pem";
|
mkIf (!cfg.no-tls && cfg.sops)
|
||||||
|
"${config.security.acme.certs.${cfg.realm}.directory}/full.pem";
|
||||||
|
pkey =
|
||||||
|
mkIf (!cfg.no-tls && cfg.sops)
|
||||||
|
"${config.security.acme.certs.${cfg.realm}.directory}/key.pem";
|
||||||
|
|
||||||
extraConfig = ''
|
extraConfig = ''
|
||||||
# ban private IP ranges
|
# ban private IP ranges
|
||||||
|
|
|
||||||
|
|
@ -14,7 +14,6 @@
|
||||||
i2pd = import ./i2pd;
|
i2pd = import ./i2pd;
|
||||||
jellyfin = import ./jellyfin;
|
jellyfin = import ./jellyfin;
|
||||||
jirafeau = import ./jirafeau;
|
jirafeau = import ./jirafeau;
|
||||||
librechat-oci = import ./librechat-oci;
|
|
||||||
mailserver = import ./mailserver;
|
mailserver = import ./mailserver;
|
||||||
matrix-synapse = import ./matrix-synapse;
|
matrix-synapse = import ./matrix-synapse;
|
||||||
maubot = import ./maubot;
|
maubot = import ./maubot;
|
||||||
|
|
@ -22,7 +21,6 @@
|
||||||
miniflux = import ./miniflux;
|
miniflux = import ./miniflux;
|
||||||
nginx = import ./nginx;
|
nginx = import ./nginx;
|
||||||
normalUsers = import ./normalUsers;
|
normalUsers = import ./normalUsers;
|
||||||
nostr-relay = import ./nostr-relay;
|
|
||||||
nvidia = import ./nvidia;
|
nvidia = import ./nvidia;
|
||||||
ollama = import ./ollama;
|
ollama = import ./ollama;
|
||||||
open-webui-oci = import ./open-webui-oci;
|
open-webui-oci = import ./open-webui-oci;
|
||||||
|
|
@ -35,4 +33,5 @@
|
||||||
virtualisation = import ./virtualisation;
|
virtualisation = import ./virtualisation;
|
||||||
webPage = import ./webPage;
|
webPage = import ./webPage;
|
||||||
windows-oci = import ./windows-oci;
|
windows-oci = import ./windows-oci;
|
||||||
|
zfs = import ./zfs;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -33,13 +33,11 @@ in
|
||||||
|
|
||||||
fonts.fontconfig.enable = mkDefault false;
|
fonts.fontconfig.enable = mkDefault false;
|
||||||
|
|
||||||
xdg = {
|
xdg.autostart.enable = mkDefault false;
|
||||||
autostart.enable = mkDefault false;
|
xdg.icons.enable = mkDefault false;
|
||||||
icons.enable = mkDefault false;
|
xdg.menus.enable = mkDefault false;
|
||||||
menus.enable = mkDefault false;
|
xdg.mime.enable = mkDefault false;
|
||||||
mime.enable = mkDefault false;
|
xdg.sounds.enable = mkDefault false;
|
||||||
sounds.enable = mkDefault false;
|
|
||||||
};
|
|
||||||
|
|
||||||
programs.git.package = mkDefault pkgs.gitMinimal;
|
programs.git.package = mkDefault pkgs.gitMinimal;
|
||||||
|
|
||||||
|
|
@ -50,25 +48,22 @@ in
|
||||||
viAlias = mkDefault true;
|
viAlias = mkDefault true;
|
||||||
};
|
};
|
||||||
|
|
||||||
systemd = {
|
# emergency mode is useless on headless machines
|
||||||
# emergency mode is useless on headless machines
|
systemd.enableEmergencyMode = false;
|
||||||
enableEmergencyMode = false;
|
|
||||||
|
|
||||||
sleep.extraConfig = ''
|
|
||||||
AllowSuspend=no
|
|
||||||
AllowHibernation=no
|
|
||||||
'';
|
|
||||||
|
|
||||||
# force reboots
|
|
||||||
settings.Manager = {
|
|
||||||
RuntimeWatchdogSec = mkDefault "15s";
|
|
||||||
RebootWatchdogSec = mkDefault "30s";
|
|
||||||
KExecWatchdogSec = mkDefault "1m";
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
boot.initrd.systemd.suppressedUnits = mkIf config.systemd.enableEmergencyMode [
|
boot.initrd.systemd.suppressedUnits = mkIf config.systemd.enableEmergencyMode [
|
||||||
"emergency.service"
|
"emergency.service"
|
||||||
"emergency.target"
|
"emergency.target"
|
||||||
];
|
];
|
||||||
|
|
||||||
|
systemd.sleep.extraConfig = ''
|
||||||
|
AllowSuspend=no
|
||||||
|
AllowHibernation=no
|
||||||
|
'';
|
||||||
|
|
||||||
|
# force reboots
|
||||||
|
systemd.settings.Manager = {
|
||||||
|
RuntimeWatchdogSec = mkDefault "15s";
|
||||||
|
RebootWatchdogSec = mkDefault "30s";
|
||||||
|
KExecWatchdogSec = mkDefault "1m";
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -4,9 +4,7 @@ let
|
||||||
inherit (lib) mkDefault;
|
inherit (lib) mkDefault;
|
||||||
in
|
in
|
||||||
{
|
{
|
||||||
services = {
|
services.qemuGuest.enable = mkDefault true;
|
||||||
qemuGuest.enable = mkDefault true;
|
services.spice-vdagentd.enable = mkDefault true;
|
||||||
spice-vdagentd.enable = mkDefault true;
|
services.spice-webdavd.enable = mkDefault true;
|
||||||
spice-webdavd.enable = mkDefault true;
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -2,9 +2,9 @@
|
||||||
|
|
||||||
let
|
let
|
||||||
cfg = config.services.ftp-webserver;
|
cfg = config.services.ftp-webserver;
|
||||||
inherit (config.networking) domain;
|
domain = config.networking.domain;
|
||||||
fqdn = if (cfg.subdomain != "") then "${cfg.subdomain}.${domain}" else domain;
|
fqdn = if (cfg.subdomain != "") then "${cfg.subdomain}.${domain}" else domain;
|
||||||
inherit (config.services) nginx;
|
nginx = config.services.nginx;
|
||||||
|
|
||||||
inherit (lib)
|
inherit (lib)
|
||||||
mkEnableOption
|
mkEnableOption
|
||||||
|
|
@ -35,7 +35,7 @@ in
|
||||||
|
|
||||||
config = mkIf cfg.enable {
|
config = mkIf cfg.enable {
|
||||||
services.nginx.virtualHosts."${fqdn}" = {
|
services.nginx.virtualHosts."${fqdn}" = {
|
||||||
inherit (cfg) root;
|
root = cfg.root;
|
||||||
locations."/" = {
|
locations."/" = {
|
||||||
extraConfig = ''
|
extraConfig = ''
|
||||||
autoindex on;
|
autoindex on;
|
||||||
|
|
@ -43,7 +43,7 @@ in
|
||||||
autoindex_localtime on;
|
autoindex_localtime on;
|
||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
inherit (cfg) forceSSL;
|
forceSSL = cfg.forceSSL;
|
||||||
enableACME = cfg.forceSSL;
|
enableACME = cfg.forceSSL;
|
||||||
sslCertificate = mkIf cfg.forceSSL "${config.security.acme.certs."${fqdn}".directory}/cert.pem";
|
sslCertificate = mkIf cfg.forceSSL "${config.security.acme.certs."${fqdn}".directory}/cert.pem";
|
||||||
sslCertificateKey = mkIf cfg.forceSSL "${config.security.acme.certs."${fqdn}".directory}/key.pem";
|
sslCertificateKey = mkIf cfg.forceSSL "${config.security.acme.certs."${fqdn}".directory}/key.pem";
|
||||||
|
|
|
||||||
|
|
@ -7,10 +7,10 @@
|
||||||
|
|
||||||
let
|
let
|
||||||
cfg = config.services.headplane;
|
cfg = config.services.headplane;
|
||||||
inherit (config.networking) domain;
|
domain = config.networking.domain;
|
||||||
inherit (cfg.reverseProxy) subdomain;
|
subdomain = cfg.reverseProxy.subdomain;
|
||||||
fqdn = if (cfg.reverseProxy.enable && subdomain != "") then "${subdomain}.${domain}" else domain;
|
fqdn = if (cfg.reverseProxy.enable && subdomain != "") then "${subdomain}.${domain}" else domain;
|
||||||
inherit (config.services) headscale;
|
headscale = config.services.headscale;
|
||||||
|
|
||||||
inherit (lib)
|
inherit (lib)
|
||||||
mkDefault
|
mkDefault
|
||||||
|
|
@ -45,17 +45,17 @@ in
|
||||||
url = "http://127.0.0.1:${toString headscale.port}";
|
url = "http://127.0.0.1:${toString headscale.port}";
|
||||||
public_url = headscale.settings.server_url;
|
public_url = headscale.settings.server_url;
|
||||||
config_path = "/etc/headscale/config.yaml";
|
config_path = "/etc/headscale/config.yaml";
|
||||||
api_key_path = config.sops.secrets."headplane/api_key".path;
|
|
||||||
};
|
};
|
||||||
integration.agent = {
|
integration.agent = {
|
||||||
enabled = mkDefault true;
|
enabled = mkDefault true;
|
||||||
|
pre_authkey_path = config.sops.secrets."headplane/agent_pre_authkey".path;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
services.nginx.virtualHosts = mkIf cfg.reverseProxy.enable {
|
services.nginx.virtualHosts = mkIf cfg.reverseProxy.enable {
|
||||||
"${fqdn}" = mkVirtualHost {
|
"${fqdn}" = mkVirtualHost {
|
||||||
inherit (cfg.settings.server) port;
|
port = cfg.settings.server.port;
|
||||||
ssl = cfg.reverseProxy.forceSSL;
|
ssl = cfg.reverseProxy.forceSSL;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
@ -63,14 +63,14 @@ in
|
||||||
sops.secrets =
|
sops.secrets =
|
||||||
let
|
let
|
||||||
owner = headscale.user;
|
owner = headscale.user;
|
||||||
inherit (headscale) group;
|
group = headscale.group;
|
||||||
mode = "0400";
|
mode = "0400";
|
||||||
in
|
in
|
||||||
{
|
{
|
||||||
"headplane/cookie_secret" = {
|
"headplane/cookie_secret" = {
|
||||||
inherit owner group mode;
|
inherit owner group mode;
|
||||||
};
|
};
|
||||||
"headplane/api_key" = {
|
"headplane/agent_pre_authkey" = {
|
||||||
inherit owner group mode;
|
inherit owner group mode;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -6,8 +6,8 @@
|
||||||
|
|
||||||
let
|
let
|
||||||
cfg = config.services.headscale;
|
cfg = config.services.headscale;
|
||||||
inherit (config.networking) domain;
|
domain = config.networking.domain;
|
||||||
inherit (cfg.reverseProxy) subdomain;
|
subdomain = cfg.reverseProxy.subdomain;
|
||||||
fqdn = if (cfg.reverseProxy.enable && subdomain != "") then "${subdomain}.${domain}" else domain;
|
fqdn = if (cfg.reverseProxy.enable && subdomain != "") then "${subdomain}.${domain}" else domain;
|
||||||
acl = "headscale/acl.hujson";
|
acl = "headscale/acl.hujson";
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -8,9 +8,20 @@ in
|
||||||
|
|
||||||
programs.dconf.enable = true; # fixes nixvim hm module
|
programs.dconf.enable = true; # fixes nixvim hm module
|
||||||
|
|
||||||
services = {
|
xdg.portal = {
|
||||||
flatpak.enable = true;
|
enable = true;
|
||||||
gnome.gnome-keyring.enable = true;
|
extraPortals = with pkgs; [
|
||||||
udisks2.enable = mkDefault true;
|
xdg-desktop-portal-gtk
|
||||||
|
];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
services.gnome.gnome-keyring.enable = true;
|
||||||
|
security.pam.services = {
|
||||||
|
login = {
|
||||||
|
enableGnomeKeyring = true;
|
||||||
|
};
|
||||||
|
hyprlock = { };
|
||||||
|
};
|
||||||
|
|
||||||
|
services.udisks2.enable = mkDefault true;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -7,8 +7,8 @@
|
||||||
|
|
||||||
let
|
let
|
||||||
cfg = config.services.jellyfin;
|
cfg = config.services.jellyfin;
|
||||||
inherit (config.networking) domain;
|
domain = config.networking.domain;
|
||||||
inherit (cfg.reverseProxy) subdomain;
|
subdomain = cfg.reverseProxy.subdomain;
|
||||||
fqdn = if (cfg.reverseProxy.enable && subdomain != "") then "${subdomain}.${domain}" else domain;
|
fqdn = if (cfg.reverseProxy.enable && subdomain != "") then "${subdomain}.${domain}" else domain;
|
||||||
|
|
||||||
inherit (lib)
|
inherit (lib)
|
||||||
|
|
@ -48,7 +48,9 @@ in
|
||||||
];
|
];
|
||||||
|
|
||||||
systemd.tmpfiles.rules =
|
systemd.tmpfiles.rules =
|
||||||
(map (library: "d ${cfg.dataDir}/libraries/${library} 0770 ${cfg.user} ${cfg.group} -") cfg.libraries)
|
(map (
|
||||||
|
library: "d ${cfg.dataDir}/libraries/${library} 0770 ${cfg.user} ${cfg.group} -"
|
||||||
|
) cfg.libraries)
|
||||||
++ [
|
++ [
|
||||||
"z ${cfg.dataDir} 0770 ${cfg.user} ${cfg.group} -"
|
"z ${cfg.dataDir} 0770 ${cfg.user} ${cfg.group} -"
|
||||||
"Z ${cfg.dataDir}/libraries 0770 ${cfg.user} ${cfg.group} -"
|
"Z ${cfg.dataDir}/libraries 0770 ${cfg.user} ${cfg.group} -"
|
||||||
|
|
|
||||||
|
|
@ -2,8 +2,8 @@
|
||||||
|
|
||||||
let
|
let
|
||||||
cfg = config.services.jirafeau;
|
cfg = config.services.jirafeau;
|
||||||
inherit (config.networking) domain;
|
domain = config.networking.domain;
|
||||||
inherit (cfg.reverseProxy) subdomain;
|
subdomain = cfg.reverseProxy.subdomain;
|
||||||
fqdn = if (cfg.reverseProxy.enable && subdomain != "") then "${subdomain}.${domain}" else domain;
|
fqdn = if (cfg.reverseProxy.enable && subdomain != "") then "${subdomain}.${domain}" else domain;
|
||||||
|
|
||||||
inherit (lib)
|
inherit (lib)
|
||||||
|
|
|
||||||
|
|
@ -1,535 +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};
|
|
||||||
inherit 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;
|
|
||||||
};
|
|
||||||
|
|
||||||
oci-containers = {
|
|
||||||
backend = "podman";
|
|
||||||
|
|
||||||
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"
|
|
||||||
];
|
|
||||||
};
|
|
||||||
|
|
||||||
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"
|
|
||||||
];
|
|
||||||
};
|
|
||||||
|
|
||||||
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"
|
|
||||||
];
|
|
||||||
};
|
|
||||||
|
|
||||||
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"
|
|
||||||
];
|
|
||||||
};
|
|
||||||
|
|
||||||
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"
|
|
||||||
];
|
|
||||||
};
|
|
||||||
};
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
networking.firewall.interfaces =
|
|
||||||
let
|
|
||||||
matchAll = if !config.networking.nftables.enable then "podman+" else "podman*";
|
|
||||||
in
|
|
||||||
{
|
|
||||||
"${matchAll}".allowedUDPPorts = [ 53 ];
|
|
||||||
};
|
|
||||||
|
|
||||||
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" ];
|
|
||||||
};
|
|
||||||
|
|
||||||
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" ];
|
|
||||||
};
|
|
||||||
|
|
||||||
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" ];
|
|
||||||
};
|
|
||||||
|
|
||||||
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" ];
|
|
||||||
};
|
|
||||||
|
|
||||||
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" ];
|
|
||||||
};
|
|
||||||
|
|
||||||
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" ];
|
|
||||||
};
|
|
||||||
|
|
||||||
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" ];
|
|
||||||
};
|
|
||||||
|
|
||||||
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" ];
|
|
||||||
};
|
|
||||||
|
|
||||||
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" ];
|
|
||||||
};
|
|
||||||
|
|
||||||
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" ];
|
|
||||||
};
|
|
||||||
|
|
||||||
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" ];
|
|
||||||
};
|
|
||||||
|
|
||||||
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" ];
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
targets.podman-compose-librechat-root = {
|
|
||||||
unitConfig.Description = "Root target generated by compose2nix.";
|
|
||||||
wantedBy = [ "multi-user.target" ];
|
|
||||||
};
|
|
||||||
};
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
@ -8,7 +8,7 @@
|
||||||
|
|
||||||
let
|
let
|
||||||
cfg = config.mailserver;
|
cfg = config.mailserver;
|
||||||
inherit (config.networking) domain;
|
domain = config.networking.domain;
|
||||||
fqdn = "${cfg.subdomain}.${domain}";
|
fqdn = "${cfg.subdomain}.${domain}";
|
||||||
|
|
||||||
inherit (lib)
|
inherit (lib)
|
||||||
|
|
@ -74,7 +74,7 @@ in
|
||||||
nameValuePair "${user}@${domain}" {
|
nameValuePair "${user}@${domain}" {
|
||||||
name = "${user}@${domain}";
|
name = "${user}@${domain}";
|
||||||
aliases = map (alias: "${alias}@${domain}") (accConf.aliases or [ ]);
|
aliases = map (alias: "${alias}@${domain}") (accConf.aliases or [ ]);
|
||||||
inherit (accConf) sendOnly;
|
sendOnly = accConf.sendOnly;
|
||||||
quota = mkDefault "5G";
|
quota = mkDefault "5G";
|
||||||
hashedPasswordFile = config.sops.secrets."mailserver/accounts/${user}".path;
|
hashedPasswordFile = config.sops.secrets."mailserver/accounts/${user}".path;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -23,7 +23,7 @@ let
|
||||||
|
|
||||||
services."mautrix-${name}" = {
|
services."mautrix-${name}" = {
|
||||||
enable = true;
|
enable = true;
|
||||||
inherit (cfg.bridges.${name}) package;
|
package = cfg.bridges.${name}.package;
|
||||||
environmentFile = mkIf cfg.sops config.sops.templates."mautrix-${name}/env-file".path;
|
environmentFile = mkIf cfg.sops config.sops.templates."mautrix-${name}/env-file".path;
|
||||||
settings = {
|
settings = {
|
||||||
bridge = {
|
bridge = {
|
||||||
|
|
@ -71,29 +71,33 @@ let
|
||||||
mode = "0400";
|
mode = "0400";
|
||||||
in
|
in
|
||||||
{
|
{
|
||||||
secrets = {
|
secrets."mautrix-${name}/encryption-pickle-key" = {
|
||||||
"mautrix-${name}/encryption-pickle-key" = {
|
inherit owner group mode;
|
||||||
inherit owner group mode;
|
};
|
||||||
};
|
secrets."mautrix-${name}/provisioning-shared-secret" = {
|
||||||
"mautrix-${name}/provisioning-shared-secret" = {
|
inherit owner group mode;
|
||||||
inherit owner group mode;
|
};
|
||||||
};
|
secrets."mautrix-${name}/public-media-signing-key" = {
|
||||||
"mautrix-${name}/public-media-signing-key" = {
|
inherit owner group mode;
|
||||||
inherit owner group mode;
|
};
|
||||||
};
|
secrets."mautrix-${name}/direct-media-server-key" = {
|
||||||
"mautrix-${name}/direct-media-server-key" = {
|
inherit owner group mode;
|
||||||
inherit owner group mode;
|
|
||||||
};
|
|
||||||
};
|
};
|
||||||
templates."mautrix-${name}/env-file" = {
|
templates."mautrix-${name}/env-file" = {
|
||||||
inherit owner group mode;
|
inherit owner group mode;
|
||||||
content = ''
|
content = ''
|
||||||
MAUTRIX_${toUpper name}_ENCRYPTION_PICKLE_KEY=${config.sops.placeholder."mautrix-${name}/encryption-pickle-key"}
|
MAUTRIX_${toUpper name}_ENCRYPTION_PICKLE_KEY=${
|
||||||
|
config.sops.placeholder."mautrix-${name}/encryption-pickle-key"
|
||||||
|
}
|
||||||
MAUTRIX_${toUpper name}_PROVISIONING_SHARED_SECRET=${
|
MAUTRIX_${toUpper name}_PROVISIONING_SHARED_SECRET=${
|
||||||
config.sops.placeholder."mautrix-${name}/provisioning-shared-secret"
|
config.sops.placeholder."mautrix-${name}/provisioning-shared-secret"
|
||||||
}
|
}
|
||||||
MAUTRIX_${toUpper name}_PUBLIC_MEDIA_SIGNING_KEY=${config.sops.placeholder."mautrix-${name}/public-media-signing-key"}
|
MAUTRIX_${toUpper name}_PUBLIC_MEDIA_SIGNING_KEY=${
|
||||||
MAUTRIX_${toUpper name}_DIRECT_MEDIA_SERVER_KEY=${config.sops.placeholder."mautrix-${name}/direct-media-server-key"}
|
config.sops.placeholder."mautrix-${name}/public-media-signing-key"
|
||||||
|
}
|
||||||
|
MAUTRIX_${toUpper name}_DIRECT_MEDIA_SERVER_KEY=${
|
||||||
|
config.sops.placeholder."mautrix-${name}/direct-media-server-key"
|
||||||
|
}
|
||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -84,74 +84,77 @@ in
|
||||||
};
|
};
|
||||||
|
|
||||||
config = mkIf cfg.enable {
|
config = mkIf cfg.enable {
|
||||||
services = {
|
services.postgresql = {
|
||||||
postgresql = {
|
enable = true;
|
||||||
enable = true;
|
initialScript = pkgs.writeText "synapse-init.sql" ''
|
||||||
initialScript = pkgs.writeText "synapse-init.sql" ''
|
CREATE ROLE "matrix-synapse" WITH LOGIN PASSWORD 'synapse';
|
||||||
CREATE ROLE "matrix-synapse" WITH LOGIN PASSWORD 'synapse';
|
CREATE DATABASE "matrix-synapse" WITH OWNER "matrix-synapse"
|
||||||
CREATE DATABASE "matrix-synapse" WITH OWNER "matrix-synapse"
|
TEMPLATE template0
|
||||||
TEMPLATE template0
|
LC_COLLATE = 'C'
|
||||||
LC_COLLATE = 'C'
|
LC_CTYPE = 'C';
|
||||||
LC_CTYPE = 'C';
|
'';
|
||||||
'';
|
};
|
||||||
};
|
|
||||||
|
|
||||||
matrix-synapse = mkMerge [
|
services.matrix-synapse = mkMerge [
|
||||||
{
|
{
|
||||||
settings = {
|
settings = {
|
||||||
registration_shared_secret_path = mkIf cfg.sops config.sops.secrets."matrix/registration-shared-secret".path;
|
registration_shared_secret_path =
|
||||||
server_name = config.networking.domain;
|
mkIf cfg.sops
|
||||||
public_baseurl = baseUrl;
|
config.sops.secrets."matrix/registration-shared-secret".path;
|
||||||
listeners = [
|
server_name = config.networking.domain;
|
||||||
{
|
public_baseurl = baseUrl;
|
||||||
inherit (cfg) port;
|
listeners = [
|
||||||
bind_addresses = [ "127.0.0.1" ];
|
{
|
||||||
resources = [
|
inherit (cfg) port;
|
||||||
{
|
bind_addresses = [ "127.0.0.1" ];
|
||||||
compress = true;
|
resources = [
|
||||||
names = [ "client" ];
|
{
|
||||||
}
|
compress = true;
|
||||||
{
|
names = [ "client" ];
|
||||||
compress = false;
|
}
|
||||||
names = [ "federation" ];
|
{
|
||||||
}
|
compress = false;
|
||||||
];
|
names = [ "federation" ];
|
||||||
tls = false;
|
}
|
||||||
type = "http";
|
];
|
||||||
x_forwarded = true;
|
tls = false;
|
||||||
}
|
type = "http";
|
||||||
];
|
x_forwarded = true;
|
||||||
};
|
}
|
||||||
}
|
];
|
||||||
(mkIf cfg.coturn.enable {
|
|
||||||
settings = {
|
|
||||||
turn_uris = with cfg.coturn; [
|
|
||||||
"turn:${realm}:${toString listening-port}?transport=udp"
|
|
||||||
"turn:${realm}:${toString listening-port}?transport=tcp"
|
|
||||||
"turn:${realm}:${toString tls-listening-port}?transport=udp"
|
|
||||||
"turn:${realm}:${toString tls-listening-port}?transport=tcp"
|
|
||||||
"turn:${realm}:${toString alt-listening-port}?transport=udp"
|
|
||||||
"turn:${realm}:${toString alt-listening-port}?transport=tcp"
|
|
||||||
"turn:${realm}:${toString alt-tls-listening-port}?transport=udp"
|
|
||||||
"turn:${realm}:${toString alt-tls-listening-port}?transport=tcp"
|
|
||||||
];
|
|
||||||
extraConfigFiles = mkIf cfg.sops [ config.sops.templates."coturn/static-auth-secret.env".path ];
|
|
||||||
turn_user_lifetime = "1h";
|
|
||||||
};
|
|
||||||
})
|
|
||||||
];
|
|
||||||
|
|
||||||
nginx.virtualHosts."${cfg.settings.server_name}" = {
|
|
||||||
enableACME = true;
|
|
||||||
forceSSL = true;
|
|
||||||
|
|
||||||
locations = {
|
|
||||||
"= /.well-known/matrix/server".extraConfig = mkWellKnown serverConfig;
|
|
||||||
"= /.well-known/matrix/client".extraConfig = mkWellKnown clientConfig;
|
|
||||||
"/_matrix".proxyPass = "http://127.0.0.1:${toString cfg.port}";
|
|
||||||
"/_synapse".proxyPass = "http://127.0.0.1:${toString cfg.port}";
|
|
||||||
};
|
};
|
||||||
};
|
}
|
||||||
|
(mkIf cfg.coturn.enable {
|
||||||
|
settings = {
|
||||||
|
turn_uris = with cfg.coturn; [
|
||||||
|
"turn:${realm}:${toString listening-port}?transport=udp"
|
||||||
|
"turn:${realm}:${toString listening-port}?transport=tcp"
|
||||||
|
"turn:${realm}:${toString tls-listening-port}?transport=udp"
|
||||||
|
"turn:${realm}:${toString tls-listening-port}?transport=tcp"
|
||||||
|
"turn:${realm}:${toString alt-listening-port}?transport=udp"
|
||||||
|
"turn:${realm}:${toString alt-listening-port}?transport=tcp"
|
||||||
|
"turn:${realm}:${toString alt-tls-listening-port}?transport=udp"
|
||||||
|
"turn:${realm}:${toString alt-tls-listening-port}?transport=tcp"
|
||||||
|
];
|
||||||
|
extraConfigFiles = mkIf cfg.sops [ config.sops.templates."coturn/static-auth-secret.env".path ];
|
||||||
|
turn_user_lifetime = "1h";
|
||||||
|
};
|
||||||
|
})
|
||||||
|
];
|
||||||
|
|
||||||
|
environment.shellAliases = mkIf cfg.sops {
|
||||||
|
register_new_matrix_user = "${cfg.package}/bin/register_new_matrix_user -k $(sudo cat ${cfg.settings.registration_shared_secret_path})";
|
||||||
|
};
|
||||||
|
|
||||||
|
services.nginx.virtualHosts."${cfg.settings.server_name}" = {
|
||||||
|
enableACME = true;
|
||||||
|
forceSSL = true;
|
||||||
|
|
||||||
|
locations."= /.well-known/matrix/server".extraConfig = mkWellKnown serverConfig;
|
||||||
|
locations."= /.well-known/matrix/client".extraConfig = mkWellKnown clientConfig;
|
||||||
|
|
||||||
|
locations."/_matrix".proxyPass = "http://127.0.0.1:${toString cfg.port}";
|
||||||
|
locations."/_synapse".proxyPass = "http://127.0.0.1:${toString cfg.port}";
|
||||||
};
|
};
|
||||||
|
|
||||||
sops = mkIf cfg.sops {
|
sops = mkIf cfg.sops {
|
||||||
|
|
|
||||||
|
|
@ -6,53 +6,51 @@
|
||||||
|
|
||||||
let
|
let
|
||||||
cfg = config.services.matrix-synapse;
|
cfg = config.services.matrix-synapse;
|
||||||
inherit (config.networking) domain;
|
domain = config.networking.domain;
|
||||||
|
|
||||||
inherit (lib) mkIf mkDefault;
|
inherit (lib) mkIf mkDefault;
|
||||||
in
|
in
|
||||||
{
|
{
|
||||||
config = mkIf cfg.enable {
|
config = mkIf cfg.enable {
|
||||||
services = {
|
services.livekit = {
|
||||||
livekit = {
|
enable = true;
|
||||||
enable = true;
|
settings.port = mkDefault 7880;
|
||||||
settings.port = mkDefault 7880;
|
settings.room.auto_create = mkDefault false;
|
||||||
settings.room.auto_create = mkDefault false;
|
openFirewall = mkDefault true;
|
||||||
openFirewall = mkDefault true;
|
keyFile = mkIf cfg.sops config.sops.templates."livekit/key".path;
|
||||||
keyFile = mkIf cfg.sops config.sops.templates."livekit/key".path;
|
};
|
||||||
};
|
|
||||||
|
|
||||||
lk-jwt-service = {
|
services.lk-jwt-service = {
|
||||||
enable = true;
|
enable = true;
|
||||||
port = mkDefault 8080;
|
port = mkDefault 8080;
|
||||||
livekitUrl = "wss://${domain}/livekit/sfu";
|
livekitUrl = "wss://${domain}/livekit/sfu";
|
||||||
keyFile = mkIf cfg.sops config.sops.templates."livekit/key".path;
|
keyFile = mkIf cfg.sops config.sops.templates."livekit/key".path;
|
||||||
};
|
|
||||||
|
|
||||||
nginx.virtualHosts = {
|
|
||||||
"${domain}".locations = {
|
|
||||||
"^~ /livekit/jwt/" = {
|
|
||||||
priority = 400;
|
|
||||||
proxyPass = "http://127.0.0.1:${toString config.services.lk-jwt-service.port}/";
|
|
||||||
};
|
|
||||||
"^~ /livekit/sfu/" = {
|
|
||||||
priority = 400;
|
|
||||||
proxyPass = "http://127.0.0.1:${toString config.services.livekit.settings.port}/";
|
|
||||||
proxyWebsockets = true;
|
|
||||||
extraConfig = ''
|
|
||||||
proxy_send_timeout 120;
|
|
||||||
proxy_read_timeout 120;
|
|
||||||
proxy_buffering off;
|
|
||||||
proxy_set_header Accept-Encoding gzip;
|
|
||||||
proxy_set_header Upgrade $http_upgrade;
|
|
||||||
proxy_set_header Connection "upgrade";
|
|
||||||
'';
|
|
||||||
};
|
|
||||||
};
|
|
||||||
};
|
|
||||||
};
|
};
|
||||||
|
|
||||||
systemd.services.lk-jwt-service.environment.LIVEKIT_FULL_ACCESS_HOMESERVERS = domain;
|
systemd.services.lk-jwt-service.environment.LIVEKIT_FULL_ACCESS_HOMESERVERS = domain;
|
||||||
|
|
||||||
|
services.nginx.virtualHosts = {
|
||||||
|
"${domain}".locations = {
|
||||||
|
"^~ /livekit/jwt/" = {
|
||||||
|
priority = 400;
|
||||||
|
proxyPass = "http://127.0.0.1:${toString config.services.lk-jwt-service.port}/";
|
||||||
|
};
|
||||||
|
"^~ /livekit/sfu/" = {
|
||||||
|
priority = 400;
|
||||||
|
proxyPass = "http://127.0.0.1:${toString config.services.livekit.settings.port}/";
|
||||||
|
proxyWebsockets = true;
|
||||||
|
extraConfig = ''
|
||||||
|
proxy_send_timeout 120;
|
||||||
|
proxy_read_timeout 120;
|
||||||
|
proxy_buffering off;
|
||||||
|
proxy_set_header Accept-Encoding gzip;
|
||||||
|
proxy_set_header Upgrade $http_upgrade;
|
||||||
|
proxy_set_header Connection "upgrade";
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
sops = mkIf cfg.sops {
|
sops = mkIf cfg.sops {
|
||||||
secrets."livekit/key" = { };
|
secrets."livekit/key" = { };
|
||||||
templates."livekit/key".content = ''
|
templates."livekit/key".content = ''
|
||||||
|
|
|
||||||
|
|
@ -76,7 +76,7 @@ in
|
||||||
sops = mkIf cfg.sops (
|
sops = mkIf cfg.sops (
|
||||||
let
|
let
|
||||||
owner = user.name;
|
owner = user.name;
|
||||||
inherit (user) group;
|
group = user.group;
|
||||||
mode = "0400";
|
mode = "0400";
|
||||||
in
|
in
|
||||||
{
|
{
|
||||||
|
|
@ -98,7 +98,9 @@ in
|
||||||
''
|
''
|
||||||
admins:
|
admins:
|
||||||
''
|
''
|
||||||
+ concatLines (map (admin: " ${admin}: ${config.sops.placeholder."maubot/admins/${admin}"}") cfg.admins)
|
+ concatLines (
|
||||||
|
map (admin: " ${admin}: ${config.sops.placeholder."maubot/admins/${admin}"}") cfg.admins
|
||||||
|
)
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -28,12 +28,6 @@ in
|
||||||
default = null;
|
default = null;
|
||||||
};
|
};
|
||||||
|
|
||||||
port = mkOption {
|
|
||||||
type = types.port;
|
|
||||||
default = 8000;
|
|
||||||
description = "Port on which the mcpo service should listen.";
|
|
||||||
};
|
|
||||||
|
|
||||||
user = mkOption {
|
user = mkOption {
|
||||||
type = types.str;
|
type = types.str;
|
||||||
description = "The user the mcpo service will run as.";
|
description = "The user the mcpo service will run as.";
|
||||||
|
|
@ -96,7 +90,7 @@ in
|
||||||
|
|
||||||
users.users."${cfg.user}" = {
|
users.users."${cfg.user}" = {
|
||||||
isSystemUser = true;
|
isSystemUser = true;
|
||||||
inherit (cfg) group;
|
group = cfg.group;
|
||||||
};
|
};
|
||||||
|
|
||||||
users.groups."${cfg.group}" = { };
|
users.groups."${cfg.group}" = { };
|
||||||
|
|
@ -106,7 +100,7 @@ in
|
||||||
after = [ "network.target" ];
|
after = [ "network.target" ];
|
||||||
wantedBy = [ "multi-user.target" ];
|
wantedBy = [ "multi-user.target" ];
|
||||||
serviceConfig = {
|
serviceConfig = {
|
||||||
ExecStart = "${getExe cfg.package} --port ${toString cfg.port} --config ${configFile}";
|
ExecStart = "${getExe cfg.package} --config ${configFile}";
|
||||||
Restart = "on-failure";
|
Restart = "on-failure";
|
||||||
User = cfg.user;
|
User = cfg.user;
|
||||||
Group = cfg.group;
|
Group = cfg.group;
|
||||||
|
|
|
||||||
|
|
@ -6,8 +6,8 @@
|
||||||
|
|
||||||
let
|
let
|
||||||
cfg = config.services.miniflux;
|
cfg = config.services.miniflux;
|
||||||
inherit (config.networking) domain;
|
domain = config.networking.domain;
|
||||||
inherit (cfg.reverseProxy) subdomain;
|
subdomain = cfg.reverseProxy.subdomain;
|
||||||
fqdn = if (cfg.reverseProxy.enable && subdomain != "") then "${subdomain}.${domain}" else domain;
|
fqdn = if (cfg.reverseProxy.enable && subdomain != "") then "${subdomain}.${domain}" else domain;
|
||||||
port = 8085;
|
port = 8085;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -50,7 +50,8 @@ in
|
||||||
"1.1.1.1"
|
"1.1.1.1"
|
||||||
"2606:4700:4700::1111"
|
"2606:4700:4700::1111"
|
||||||
];
|
];
|
||||||
resolvers = if config.networking.nameservers == [ ] then cloudflare else config.networking.nameservers;
|
resolvers =
|
||||||
|
if config.networking.nameservers == [ ] then cloudflare else config.networking.nameservers;
|
||||||
in
|
in
|
||||||
map escapeIPv6 resolvers;
|
map escapeIPv6 resolvers;
|
||||||
|
|
||||||
|
|
@ -59,7 +60,7 @@ in
|
||||||
virtualHosts = {
|
virtualHosts = {
|
||||||
"${config.networking.domain}" = mkDefault {
|
"${config.networking.domain}" = mkDefault {
|
||||||
enableACME = cfg.forceSSL;
|
enableACME = cfg.forceSSL;
|
||||||
inherit (cfg) forceSSL;
|
forceSSL = cfg.forceSSL;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -21,7 +21,7 @@ in
|
||||||
types.submodule {
|
types.submodule {
|
||||||
options = {
|
options = {
|
||||||
extraGroups = mkOption {
|
extraGroups = mkOption {
|
||||||
type = types.listOf types.str;
|
type = (types.listOf types.str);
|
||||||
default = [ ];
|
default = [ ];
|
||||||
description = "Extra groups for the user";
|
description = "Extra groups for the user";
|
||||||
example = [ "wheel" ];
|
example = [ "wheel" ];
|
||||||
|
|
@ -37,7 +37,7 @@ in
|
||||||
description = "Initial password for the user";
|
description = "Initial password for the user";
|
||||||
};
|
};
|
||||||
sshKeyFiles = mkOption {
|
sshKeyFiles = mkOption {
|
||||||
type = types.listOf types.path;
|
type = (types.listOf types.path);
|
||||||
default = [ ];
|
default = [ ];
|
||||||
description = "SSH key files for the user";
|
description = "SSH key files for the user";
|
||||||
example = [ "/path/to/id_rsa.pub" ];
|
example = [ "/path/to/id_rsa.pub" ];
|
||||||
|
|
|
||||||
|
|
@ -1,56 +0,0 @@
|
||||||
{ config, lib, ... }:
|
|
||||||
|
|
||||||
let
|
|
||||||
cfg = config.services.nostr-relay;
|
|
||||||
inherit (config.networking) domain;
|
|
||||||
inherit (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;
|
|
||||||
inherit (cfg.reverseProxy) forceSSL;
|
|
||||||
locations."/".proxyPass = "http://127.0.0.1:${toString config.services.nostr-rs-relay.settings.network.port}";
|
|
||||||
};
|
|
||||||
};
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
@ -9,26 +9,20 @@ let
|
||||||
inherit (lib) mkDefault;
|
inherit (lib) mkDefault;
|
||||||
in
|
in
|
||||||
{
|
{
|
||||||
boot = {
|
boot.blacklistedKernelModules = [ "nouveau" ];
|
||||||
blacklistedKernelModules = [ "nouveau" ];
|
boot.extraModulePackages = [ config.hardware.nvidia.package ];
|
||||||
extraModulePackages = [ config.hardware.nvidia.package ];
|
boot.initrd.kernelModules = [ "nvidia" ];
|
||||||
initrd.kernelModules = [ "nvidia" ];
|
|
||||||
};
|
|
||||||
|
|
||||||
environment.systemPackages = with pkgs; [
|
environment.systemPackages = with pkgs; [
|
||||||
nvtopPackages.nvidia
|
nvtopPackages.nvidia
|
||||||
];
|
];
|
||||||
|
|
||||||
hardware = {
|
hardware.enableRedistributableFirmware = true;
|
||||||
enableRedistributableFirmware = true;
|
hardware.graphics.enable = true;
|
||||||
graphics.enable = true;
|
hardware.nvidia.modesetting.enable = true;
|
||||||
nvidia = {
|
hardware.nvidia.nvidiaSettings = true;
|
||||||
modesetting.enable = true;
|
hardware.nvidia.open = false;
|
||||||
nvidiaSettings = true;
|
hardware.nvidia.package = mkDefault config.boot.kernelPackages.nvidiaPackages.latest;
|
||||||
open = false;
|
|
||||||
package = mkDefault config.boot.kernelPackages.nvidiaPackages.latest;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
nixpkgs.config.cudaSupport = true;
|
nixpkgs.config.cudaSupport = true;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -2,8 +2,8 @@
|
||||||
|
|
||||||
let
|
let
|
||||||
cfg = config.services.ollama;
|
cfg = config.services.ollama;
|
||||||
inherit (config.networking) domain;
|
domain = config.networking.domain;
|
||||||
inherit (cfg.reverseProxy) subdomain;
|
subdomain = cfg.reverseProxy.subdomain;
|
||||||
fqdn = if (cfg.reverseProxy.enable && subdomain != "") then "${subdomain}.${domain}" else domain;
|
fqdn = if (cfg.reverseProxy.enable && subdomain != "") then "${subdomain}.${domain}" else domain;
|
||||||
|
|
||||||
inherit (lib)
|
inherit (lib)
|
||||||
|
|
@ -31,7 +31,7 @@ in
|
||||||
|
|
||||||
services.nginx.virtualHosts = mkIf cfg.reverseProxy.enable {
|
services.nginx.virtualHosts = mkIf cfg.reverseProxy.enable {
|
||||||
"${fqdn}" = mkVirtualHost {
|
"${fqdn}" = mkVirtualHost {
|
||||||
inherit (cfg) port;
|
port = cfg.port;
|
||||||
ssl = cfg.reverseProxy.forceSSL;
|
ssl = cfg.reverseProxy.forceSSL;
|
||||||
recommendedProxySettings = mkForce false;
|
recommendedProxySettings = mkForce false;
|
||||||
extraConfig = ''
|
extraConfig = ''
|
||||||
|
|
|
||||||
|
|
@ -10,10 +10,10 @@ let
|
||||||
|
|
||||||
image = pkgs.dockerTools.pullImage {
|
image = pkgs.dockerTools.pullImage {
|
||||||
imageName = "ghcr.io/open-webui/open-webui";
|
imageName = "ghcr.io/open-webui/open-webui";
|
||||||
imageDigest = "sha256:a7e4796ae894d1e2a0c1824860ade472f35c507608a01c3581377b5c19b0ed49";
|
imageDigest = "sha256:2deb90b0423473d8f97febced2e62b8fd898aa3eb61877bb3aa336370214c258";
|
||||||
hash = "sha256-uhPlVXSxY6rGbYGvlPVV3zurmbI96mAHEuKKy9FFaD4=";
|
hash = "sha256-2cdKfvZGUyPUm7TFXcf5OcG9ey4BvOZPUOVim1S2C+s=";
|
||||||
finalImageName = "ghcr.io/open-webui/open-webui";
|
finalImageName = "ghcr.io/open-webui/open-webui";
|
||||||
finalImageTag = "0.9.2";
|
finalImageTag = "0.8.5";
|
||||||
};
|
};
|
||||||
|
|
||||||
defaultEnv = {
|
defaultEnv = {
|
||||||
|
|
@ -83,43 +83,10 @@ in
|
||||||
};
|
};
|
||||||
|
|
||||||
config = mkIf cfg.enable {
|
config = mkIf cfg.enable {
|
||||||
virtualisation = {
|
virtualisation.podman = {
|
||||||
podman = {
|
enable = true;
|
||||||
enable = true;
|
autoPrune.enable = true;
|
||||||
autoPrune.enable = true;
|
dockerCompat = true;
|
||||||
dockerCompat = true;
|
|
||||||
};
|
|
||||||
|
|
||||||
oci-containers = {
|
|
||||||
backend = "podman";
|
|
||||||
|
|
||||||
containers."open-webui" = {
|
|
||||||
image = with cfg.image; imageName + ":" + imageTag;
|
|
||||||
imageFile = cfg.image;
|
|
||||||
environment =
|
|
||||||
defaultEnv
|
|
||||||
// cfg.environment
|
|
||||||
// {
|
|
||||||
PORT = "${toString cfg.port}";
|
|
||||||
CORS_ALLOW_ORIGIN = concatStringsSep ";" (
|
|
||||||
[
|
|
||||||
"http://localhost:${toString cfg.port}"
|
|
||||||
"http://127.0.0.1:${toString cfg.port}"
|
|
||||||
"http://0.0.0.0:${toString cfg.port}"
|
|
||||||
]
|
|
||||||
++ optional (cfg.externalUrl != null) cfg.externalUrl
|
|
||||||
);
|
|
||||||
};
|
|
||||||
environmentFiles = optional (cfg.environmentFile != null) cfg.environmentFile;
|
|
||||||
volumes = [
|
|
||||||
"open-webui_open-webui:/app/backend/data:rw"
|
|
||||||
];
|
|
||||||
log-driver = "journald";
|
|
||||||
extraOptions = [
|
|
||||||
"--network=host"
|
|
||||||
];
|
|
||||||
};
|
|
||||||
};
|
|
||||||
};
|
};
|
||||||
|
|
||||||
networking.firewall.interfaces =
|
networking.firewall.interfaces =
|
||||||
|
|
@ -130,44 +97,70 @@ in
|
||||||
"${matchAll}".allowedUDPPorts = [ 53 ];
|
"${matchAll}".allowedUDPPorts = [ 53 ];
|
||||||
};
|
};
|
||||||
|
|
||||||
systemd = {
|
virtualisation.oci-containers.backend = "podman";
|
||||||
services."podman-open-webui" = {
|
|
||||||
serviceConfig = {
|
|
||||||
Restart = mkOverride 90 "always";
|
|
||||||
};
|
|
||||||
after = [
|
|
||||||
"podman-volume-open-webui_open-webui.service"
|
|
||||||
];
|
|
||||||
requires = [
|
|
||||||
"podman-volume-open-webui_open-webui.service"
|
|
||||||
];
|
|
||||||
partOf = [
|
|
||||||
"podman-compose-open-webui-root.target"
|
|
||||||
];
|
|
||||||
wantedBy = [
|
|
||||||
"podman-compose-open-webui-root.target"
|
|
||||||
];
|
|
||||||
};
|
|
||||||
|
|
||||||
services."podman-volume-open-webui_open-webui" = {
|
virtualisation.oci-containers.containers."open-webui" = {
|
||||||
path = [ pkgs.podman ];
|
image = with cfg.image; imageName + ":" + imageTag;
|
||||||
serviceConfig = {
|
imageFile = cfg.image;
|
||||||
Type = "oneshot";
|
environment =
|
||||||
RemainAfterExit = true;
|
defaultEnv
|
||||||
|
// cfg.environment
|
||||||
|
// {
|
||||||
|
PORT = "${toString cfg.port}";
|
||||||
|
CORS_ALLOW_ORIGIN = concatStringsSep ";" (
|
||||||
|
[
|
||||||
|
"http://localhost:${toString cfg.port}"
|
||||||
|
"http://127.0.0.1:${toString cfg.port}"
|
||||||
|
"http://0.0.0.0:${toString cfg.port}"
|
||||||
|
]
|
||||||
|
++ optional (cfg.externalUrl != null) cfg.externalUrl
|
||||||
|
);
|
||||||
};
|
};
|
||||||
script = ''
|
environmentFiles = optional (cfg.environmentFile != null) cfg.environmentFile;
|
||||||
podman volume inspect open-webui_open-webui || podman volume create open-webui_open-webui
|
volumes = [
|
||||||
'';
|
"open-webui_open-webui:/app/backend/data:rw"
|
||||||
partOf = [ "podman-compose-open-webui-root.target" ];
|
];
|
||||||
wantedBy = [ "podman-compose-open-webui-root.target" ];
|
log-driver = "journald";
|
||||||
|
extraOptions = [
|
||||||
|
"--network=host"
|
||||||
|
];
|
||||||
|
};
|
||||||
|
systemd.services."podman-open-webui" = {
|
||||||
|
serviceConfig = {
|
||||||
|
Restart = mkOverride 90 "always";
|
||||||
};
|
};
|
||||||
|
after = [
|
||||||
|
"podman-volume-open-webui_open-webui.service"
|
||||||
|
];
|
||||||
|
requires = [
|
||||||
|
"podman-volume-open-webui_open-webui.service"
|
||||||
|
];
|
||||||
|
partOf = [
|
||||||
|
"podman-compose-open-webui-root.target"
|
||||||
|
];
|
||||||
|
wantedBy = [
|
||||||
|
"podman-compose-open-webui-root.target"
|
||||||
|
];
|
||||||
|
};
|
||||||
|
|
||||||
targets."podman-compose-open-webui-root" = {
|
systemd.services."podman-volume-open-webui_open-webui" = {
|
||||||
unitConfig = {
|
path = [ pkgs.podman ];
|
||||||
Description = "Root target generated by compose2nix.";
|
serviceConfig = {
|
||||||
};
|
Type = "oneshot";
|
||||||
wantedBy = [ "multi-user.target" ];
|
RemainAfterExit = true;
|
||||||
};
|
};
|
||||||
|
script = ''
|
||||||
|
podman volume inspect open-webui_open-webui || podman volume create open-webui_open-webui
|
||||||
|
'';
|
||||||
|
partOf = [ "podman-compose-open-webui-root.target" ];
|
||||||
|
wantedBy = [ "podman-compose-open-webui-root.target" ];
|
||||||
|
};
|
||||||
|
|
||||||
|
systemd.targets."podman-compose-open-webui-root" = {
|
||||||
|
unitConfig = {
|
||||||
|
Description = "Root target generated by compose2nix.";
|
||||||
|
};
|
||||||
|
wantedBy = [ "multi-user.target" ];
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -7,8 +7,8 @@
|
||||||
|
|
||||||
let
|
let
|
||||||
cfg = config.services.print-server;
|
cfg = config.services.print-server;
|
||||||
inherit (config.networking) domain;
|
domain = config.networking.domain;
|
||||||
inherit (cfg.reverseProxy) subdomain;
|
subdomain = cfg.reverseProxy.subdomain;
|
||||||
fqdn = if (cfg.reverseProxy.enable && subdomain != "") then "${subdomain}.${domain}" else domain;
|
fqdn = if (cfg.reverseProxy.enable && subdomain != "") then "${subdomain}.${domain}" else domain;
|
||||||
port = 631;
|
port = 631;
|
||||||
|
|
||||||
|
|
@ -36,49 +36,47 @@ in
|
||||||
};
|
};
|
||||||
|
|
||||||
config = mkIf cfg.enable {
|
config = mkIf cfg.enable {
|
||||||
services = {
|
services.printing = {
|
||||||
printing = {
|
enable = true;
|
||||||
enable = true;
|
listenAddresses = [ "*:${builtins.toString port}" ];
|
||||||
listenAddresses = [ "*:${builtins.toString port}" ];
|
webInterface = true;
|
||||||
webInterface = true;
|
tempDir = "/tmp/cups";
|
||||||
tempDir = "/tmp/cups";
|
allowFrom = [ "all" ];
|
||||||
allowFrom = [ "all" ];
|
snmpConf = ''
|
||||||
snmpConf = ''
|
Address @LOCAL
|
||||||
Address @LOCAL
|
'';
|
||||||
'';
|
clientConf = "";
|
||||||
clientConf = "";
|
openFirewall = cfg.openFirewall;
|
||||||
inherit (cfg) openFirewall;
|
drivers = with pkgs; [
|
||||||
drivers = with pkgs; [
|
brlaser
|
||||||
brlaser
|
brgenml1lpr
|
||||||
brgenml1lpr
|
brgenml1cupswrapper # Brother
|
||||||
brgenml1cupswrapper # Brother
|
postscript-lexmark # Lexmark
|
||||||
postscript-lexmark # Lexmark
|
hplip
|
||||||
hplip
|
hplipWithPlugin # HP
|
||||||
hplipWithPlugin # HP
|
splix
|
||||||
splix
|
samsung-unified-linux-driver # Samsung
|
||||||
samsung-unified-linux-driver # Samsung
|
gutenprint
|
||||||
gutenprint
|
gutenprintBin # different vendors
|
||||||
gutenprintBin # different vendors
|
];
|
||||||
];
|
defaultShared = true;
|
||||||
defaultShared = true;
|
browsing = true;
|
||||||
browsing = true;
|
browsedConf = ''
|
||||||
browsedConf = ''
|
BrowsePoll ${fqdn}
|
||||||
BrowsePoll ${fqdn}
|
'';
|
||||||
'';
|
};
|
||||||
};
|
|
||||||
|
|
||||||
# autodiscovery of network printers
|
# autodiscovery of network printers
|
||||||
avahi = {
|
services.avahi = {
|
||||||
enable = true;
|
enable = true;
|
||||||
nssmdns4 = true;
|
nssmdns4 = true;
|
||||||
inherit (cfg) openFirewall;
|
openFirewall = cfg.openFirewall;
|
||||||
};
|
};
|
||||||
|
|
||||||
nginx.virtualHosts = mkIf cfg.reverseProxy.enable {
|
services.nginx.virtualHosts = mkIf cfg.reverseProxy.enable {
|
||||||
${fqdn} = mkVirtualHost {
|
${fqdn} = mkVirtualHost {
|
||||||
inherit port;
|
inherit port;
|
||||||
ssl = cfg.reverseProxy.forceSSL;
|
ssl = cfg.reverseProxy.forceSSL;
|
||||||
};
|
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -7,8 +7,8 @@
|
||||||
|
|
||||||
let
|
let
|
||||||
cfg = config.services.radicale;
|
cfg = config.services.radicale;
|
||||||
inherit (config.networking) domain;
|
domain = config.networking.domain;
|
||||||
inherit (cfg.reverseProxy) subdomain;
|
subdomain = cfg.reverseProxy.subdomain;
|
||||||
fqdn = if (cfg.reverseProxy.enable && subdomain != "") then "${subdomain}.${domain}" else domain;
|
fqdn = if (cfg.reverseProxy.enable && subdomain != "") then "${subdomain}.${domain}" else domain;
|
||||||
port = 5232;
|
port = 5232;
|
||||||
|
|
||||||
|
|
@ -63,7 +63,7 @@ in
|
||||||
|
|
||||||
services.nginx.virtualHosts = mkIf cfg.reverseProxy.enable {
|
services.nginx.virtualHosts = mkIf cfg.reverseProxy.enable {
|
||||||
"${fqdn}" = {
|
"${fqdn}" = {
|
||||||
inherit (cfg.reverseProxy) forceSSL;
|
forceSSL = cfg.reverseProxy.forceSSL;
|
||||||
enableACME = cfg.reverseProxy.forceSSL;
|
enableACME = cfg.reverseProxy.forceSSL;
|
||||||
locations = {
|
locations = {
|
||||||
"/" = {
|
"/" = {
|
||||||
|
|
|
||||||
|
|
@ -2,8 +2,8 @@
|
||||||
|
|
||||||
let
|
let
|
||||||
cfg = config.services.rss-bridge;
|
cfg = config.services.rss-bridge;
|
||||||
inherit (config.networking) domain;
|
domain = config.networking.domain;
|
||||||
inherit (cfg.reverseProxy) subdomain;
|
subdomain = cfg.reverseProxy.subdomain;
|
||||||
fqdn = if (cfg.reverseProxy.enable && subdomain != "") then "${subdomain}.${domain}" else domain;
|
fqdn = if (cfg.reverseProxy.enable && subdomain != "") then "${subdomain}.${domain}" else domain;
|
||||||
|
|
||||||
inherit (lib)
|
inherit (lib)
|
||||||
|
|
@ -12,6 +12,7 @@ let
|
||||||
|
|
||||||
inherit (lib.utils)
|
inherit (lib.utils)
|
||||||
mkReverseProxyOption
|
mkReverseProxyOption
|
||||||
|
mkVirtualHost
|
||||||
;
|
;
|
||||||
in
|
in
|
||||||
{
|
{
|
||||||
|
|
@ -31,9 +32,8 @@ in
|
||||||
systemd.tmpfiles.rules = [ "d ${cfg.dataDir} 0755 ${cfg.user} ${cfg.group} -" ];
|
systemd.tmpfiles.rules = [ "d ${cfg.dataDir} 0755 ${cfg.user} ${cfg.group} -" ];
|
||||||
|
|
||||||
services.nginx.virtualHosts = mkIf cfg.reverseProxy.enable {
|
services.nginx.virtualHosts = mkIf cfg.reverseProxy.enable {
|
||||||
"${fqdn}" = {
|
"${cfg.virtualHost}" = mkVirtualHost {
|
||||||
enableACME = cfg.reverseProxy.forceSSL;
|
ssl = cfg.reverseProxy.forceSSL;
|
||||||
inherit (cfg.reverseProxy) forceSSL;
|
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -1,17 +1,9 @@
|
||||||
{
|
{ config, lib, ... }:
|
||||||
config,
|
|
||||||
lib,
|
|
||||||
pkgs,
|
|
||||||
...
|
|
||||||
}:
|
|
||||||
|
|
||||||
let
|
let
|
||||||
cfg = config.services.tailscale;
|
cfg = config.services.tailscale;
|
||||||
|
|
||||||
inherit (lib)
|
inherit (lib)
|
||||||
concatStrings
|
|
||||||
filterAttrs
|
|
||||||
mapAttrsToList
|
|
||||||
mkIf
|
mkIf
|
||||||
mkOption
|
mkOption
|
||||||
optional
|
optional
|
||||||
|
|
@ -20,122 +12,39 @@ let
|
||||||
in
|
in
|
||||||
{
|
{
|
||||||
options.services.tailscale = {
|
options.services.tailscale = {
|
||||||
tailnets = mkOption {
|
loginServer = mkOption {
|
||||||
default = { };
|
type = types.str;
|
||||||
type = types.attrsOf (
|
description = "The Tailscale login server to use.";
|
||||||
types.submodule {
|
};
|
||||||
options = {
|
enableSSH = mkOption {
|
||||||
loginServer = mkOption {
|
type = types.bool;
|
||||||
type = types.str;
|
default = false;
|
||||||
description = "Login server for this tailnet.";
|
description = "Enable Tailscale SSH functionality.";
|
||||||
};
|
};
|
||||||
authKeyFile = mkOption {
|
acceptDNS = mkOption {
|
||||||
type = types.nullOr types.str;
|
type = types.bool;
|
||||||
default = null;
|
default = true;
|
||||||
description = "Path to auth key secret.";
|
description = "Enable Tailscale's MagicDNS and custom DNS configuration.";
|
||||||
};
|
|
||||||
enableSSH = mkOption {
|
|
||||||
type = types.bool;
|
|
||||||
default = false;
|
|
||||||
};
|
|
||||||
acceptDNS = mkOption {
|
|
||||||
type = types.bool;
|
|
||||||
default = true;
|
|
||||||
};
|
|
||||||
default = mkOption {
|
|
||||||
type = types.bool;
|
|
||||||
default = false;
|
|
||||||
description = "Connect to this tailnet on boot.";
|
|
||||||
};
|
|
||||||
};
|
|
||||||
}
|
|
||||||
);
|
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
config =
|
config = mkIf cfg.enable {
|
||||||
let
|
services.tailscale = {
|
||||||
defaultTailnets = filterAttrs (_: t: t.default) cfg.tailnets;
|
authKeyFile = config.sops.secrets."tailscale/auth-key".path;
|
||||||
defaultTailnet = if defaultTailnets == { } then null else builtins.head (builtins.attrValues defaultTailnets);
|
extraSetFlags = optional cfg.enableSSH "--ssh" ++ optional cfg.acceptDNS "--accept-dns";
|
||||||
|
extraUpFlags = [
|
||||||
entries = mapAttrsToList (name: tcfg: ''
|
"--login-server=${cfg.loginServer}"
|
||||||
TAILNETS["${name}"]="${tcfg.loginServer}|${if tcfg.enableSSH then "true" else "false"}|${
|
]
|
||||||
if tcfg.acceptDNS then "true" else "false"
|
++ optional cfg.enableSSH "--ssh"
|
||||||
}|${if tcfg.authKeyFile != null then tcfg.authKeyFile else ""}"
|
++ optional cfg.acceptDNS "--accept-dns";
|
||||||
'') 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";
|
|
||||||
extraUpFlags = [
|
|
||||||
"--login-server=${loginServer}"
|
|
||||||
]
|
|
||||||
++ optional enableSSH "--ssh"
|
|
||||||
++ optional acceptDNS "--accept-dns";
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
environment.systemPackages = [ tailnetSwitchCli ];
|
|
||||||
|
|
||||||
environment.shellAliases.ts = "${cfg.package}/bin/tailscale";
|
|
||||||
|
|
||||||
networking.firewall.trustedInterfaces = [ cfg.interfaceName ];
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
environment.shellAliases = {
|
||||||
|
ts = "${cfg.package}/bin/tailscale";
|
||||||
|
};
|
||||||
|
|
||||||
|
networking.firewall.trustedInterfaces = [ cfg.interfaceName ];
|
||||||
|
|
||||||
|
sops.secrets."tailscale/auth-key" = { };
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -58,18 +58,16 @@ in
|
||||||
enable = mkDefault true;
|
enable = mkDefault true;
|
||||||
onBoot = mkDefault "ignore";
|
onBoot = mkDefault "ignore";
|
||||||
onShutdown = mkDefault "shutdown";
|
onShutdown = mkDefault "shutdown";
|
||||||
qemu = {
|
qemu.runAsRoot = mkDefault false;
|
||||||
runAsRoot = mkDefault false;
|
qemu.verbatimConfig = ''
|
||||||
verbatimConfig = ''
|
clear_emulation_capabilities = ${boolToZeroOne cfg.libvirtd.clearEmulationCapabilities}
|
||||||
clear_emulation_capabilities = ${boolToZeroOne cfg.libvirtd.clearEmulationCapabilities}
|
''
|
||||||
''
|
+ optionalString (cfg.libvirtd.deviceACL != [ ]) ''
|
||||||
+ optionalString (cfg.libvirtd.deviceACL != [ ]) ''
|
cgroup_device_acl = [
|
||||||
cgroup_device_acl = [
|
${aclString}
|
||||||
${aclString}
|
]
|
||||||
]
|
'';
|
||||||
'';
|
qemu.swtpm.enable = mkDefault true; # TPM 2.0
|
||||||
swtpm.enable = mkDefault true; # TPM 2.0
|
|
||||||
};
|
|
||||||
};
|
};
|
||||||
spiceUSBRedirection.enable = mkDefault true;
|
spiceUSBRedirection.enable = mkDefault true;
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,3 @@
|
||||||
#!/usr/bin/env bash
|
|
||||||
shopt -s nullglob
|
shopt -s nullglob
|
||||||
for d in /sys/kernel/iommu_groups/*/devices/*; do
|
for d in /sys/kernel/iommu_groups/*/devices/*; do
|
||||||
n=${d#*/iommu_groups/*}; n=${n%%/*}
|
n=${d#*/iommu_groups/*}; n=${n%%/*}
|
||||||
|
|
|
||||||
|
|
@ -78,32 +78,34 @@ let
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
deviceType = types.submodule (
|
deviceType = (
|
||||||
{ config, options, ... }:
|
types.submodule (
|
||||||
{
|
{ config, options, ... }:
|
||||||
options = {
|
{
|
||||||
resolution = mkOption {
|
options = {
|
||||||
type = types.nullOr resolutionType;
|
resolution = mkOption {
|
||||||
default = null;
|
type = types.nullOr resolutionType;
|
||||||
description = "Automatically calculate the minimum device size for a specific resolution. Overrides `size` if set.";
|
default = null;
|
||||||
|
description = "Automatically calculate the minimum device size for a specific resolution. Overrides `size` if set.";
|
||||||
|
};
|
||||||
|
|
||||||
|
size = mkOption {
|
||||||
|
type = types.number;
|
||||||
|
description = "Size for the kvmfr device in megabytes.";
|
||||||
|
};
|
||||||
|
|
||||||
|
permissions = mkOption {
|
||||||
|
type = permissionsType;
|
||||||
|
default = { };
|
||||||
|
description = "Permissions of the kvmfr device.";
|
||||||
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
size = mkOption {
|
config = {
|
||||||
type = types.number;
|
size = mkIf (config.resolution != null) (sizeFromResolution config.resolution);
|
||||||
description = "Size for the kvmfr device in megabytes.";
|
|
||||||
};
|
};
|
||||||
|
}
|
||||||
permissions = mkOption {
|
)
|
||||||
type = permissionsType;
|
|
||||||
default = { };
|
|
||||||
description = "Permissions of the kvmfr device.";
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
config = {
|
|
||||||
size = mkIf (config.resolution != null) (sizeFromResolution config.resolution);
|
|
||||||
};
|
|
||||||
}
|
|
||||||
);
|
);
|
||||||
|
|
||||||
inherit (lib)
|
inherit (lib)
|
||||||
|
|
@ -142,7 +144,7 @@ in
|
||||||
'';
|
'';
|
||||||
|
|
||||||
"modprobe.d/kvmfr.conf".text = ''
|
"modprobe.d/kvmfr.conf".text = ''
|
||||||
options kvmfr static_size_mb=${concatStringsSep "," (map toString deviceSizes)}
|
options kvmfr static_size_mb=${concatStringsSep "," (map (size: toString size) deviceSizes)}
|
||||||
'';
|
'';
|
||||||
|
|
||||||
"apparmor.d/local/abstractions/libvirt-qemu" = mkIf config.security.apparmor.enable {
|
"apparmor.d/local/abstractions/libvirt-qemu" = mkIf config.security.apparmor.enable {
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
let
|
let
|
||||||
cfg = config.services.webPage;
|
cfg = config.services.webPage;
|
||||||
inherit (config.networking) domain;
|
domain = config.networking.domain;
|
||||||
fqdn = if (cfg.subdomain != "") then "${cfg.subdomain}.${domain}" else domain;
|
fqdn = if (cfg.subdomain != "") then "${cfg.subdomain}.${domain}" else domain;
|
||||||
nginxUser = config.services.nginx.user;
|
nginxUser = config.services.nginx.user;
|
||||||
|
|
||||||
|
|
@ -41,7 +41,7 @@ in
|
||||||
config = mkIf cfg.enable {
|
config = mkIf cfg.enable {
|
||||||
services.nginx.virtualHosts."${fqdn}" = {
|
services.nginx.virtualHosts."${fqdn}" = {
|
||||||
enableACME = cfg.forceSSL;
|
enableACME = cfg.forceSSL;
|
||||||
inherit (cfg) forceSSL;
|
forceSSL = cfg.forceSSL;
|
||||||
root = cfg.webRoot;
|
root = cfg.webRoot;
|
||||||
locations."/".index = "index.html";
|
locations."/".index = "index.html";
|
||||||
sslCertificate = mkIf cfg.forceSSL "${config.security.acme.certs."${fqdn}".directory}/cert.pem";
|
sslCertificate = mkIf cfg.forceSSL "${config.security.acme.certs."${fqdn}".directory}/cert.pem";
|
||||||
|
|
|
||||||
|
|
@ -81,97 +81,90 @@ in
|
||||||
};
|
};
|
||||||
|
|
||||||
config = mkIf cfg.enable {
|
config = mkIf cfg.enable {
|
||||||
systemd = {
|
systemd.tmpfiles.rules = [ "d ${cfg.volume} 0755 root podman -" ];
|
||||||
tmpfiles.rules = [ "d ${cfg.volume} 0755 root podman -" ];
|
|
||||||
|
|
||||||
services = {
|
virtualisation.podman = {
|
||||||
"podman-windows" = {
|
enable = true;
|
||||||
serviceConfig = {
|
autoPrune.enable = true;
|
||||||
Restart = mkOverride 90 "always";
|
dockerCompat = true;
|
||||||
};
|
defaultNetwork.settings = {
|
||||||
after = [
|
dns_enabled = true;
|
||||||
"podman-network-windows_default.service"
|
|
||||||
];
|
|
||||||
requires = [
|
|
||||||
"podman-network-windows_default.service"
|
|
||||||
];
|
|
||||||
partOf = [
|
|
||||||
"podman-compose-windows-root.target"
|
|
||||||
];
|
|
||||||
wantedBy = [
|
|
||||||
"podman-compose-windows-root.target"
|
|
||||||
];
|
|
||||||
};
|
|
||||||
|
|
||||||
"podman-network-windows_default" = {
|
|
||||||
path = [ pkgs.podman ];
|
|
||||||
serviceConfig = {
|
|
||||||
Type = "oneshot";
|
|
||||||
RemainAfterExit = true;
|
|
||||||
ExecStop = "podman network rm -f windows_default";
|
|
||||||
};
|
|
||||||
script = ''
|
|
||||||
podman network inspect windows_default || podman network create windows_default
|
|
||||||
'';
|
|
||||||
partOf = [ "podman-compose-windows-root.target" ];
|
|
||||||
wantedBy = [ "podman-compose-windows-root.target" ];
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
targets."podman-compose-windows-root" = {
|
|
||||||
unitConfig = {
|
|
||||||
Description = "Root target generated by compose2nix.";
|
|
||||||
};
|
|
||||||
wantedBy = [ "multi-user.target" ];
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
virtualisation = {
|
|
||||||
podman = {
|
|
||||||
enable = true;
|
|
||||||
autoPrune.enable = true;
|
|
||||||
dockerCompat = true;
|
|
||||||
defaultNetwork.settings = {
|
|
||||||
dns_enabled = true;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
oci-containers = {
|
|
||||||
backend = "podman";
|
|
||||||
containers."windows" = {
|
|
||||||
image = "dockurr/windows";
|
|
||||||
environment = with cfg.settings; {
|
|
||||||
"VERSION" = version;
|
|
||||||
"RAM_SIZE" = ramSize;
|
|
||||||
"CPU_CORES" = cpuCores;
|
|
||||||
"DISK_SIZE" = diskSize;
|
|
||||||
"USERNAME" = username;
|
|
||||||
"PASSWORD" = password;
|
|
||||||
"REGION" = region;
|
|
||||||
"KEYBOARD" = keyboard;
|
|
||||||
};
|
|
||||||
volumes = [
|
|
||||||
"${cfg.volume}:/storage:rw"
|
|
||||||
]
|
|
||||||
++ optional (cfg.sharedVolume != null) "${cfg.sharedVolume}:/shared:rw";
|
|
||||||
ports = [
|
|
||||||
"8006:8006/tcp"
|
|
||||||
"3389:3389/tcp"
|
|
||||||
"3389:3389/udp"
|
|
||||||
];
|
|
||||||
log-driver = "journald";
|
|
||||||
extraOptions = [
|
|
||||||
"--cap-add=NET_ADMIN"
|
|
||||||
"--device=/dev/kvm:/dev/kvm:rwm"
|
|
||||||
"--device=/dev/net/tun:/dev/net/tun:rwm"
|
|
||||||
"--network-alias=windows"
|
|
||||||
"--network=windows_default"
|
|
||||||
];
|
|
||||||
};
|
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
# https://github.com/NixOS/nixpkgs/issues/226365
|
# https://github.com/NixOS/nixpkgs/issues/226365
|
||||||
networking.firewall.interfaces."podman+".allowedUDPPorts = [ 53 ];
|
networking.firewall.interfaces."podman+".allowedUDPPorts = [ 53 ];
|
||||||
|
|
||||||
|
virtualisation.oci-containers.backend = "podman";
|
||||||
|
|
||||||
|
virtualisation.oci-containers.containers."windows" = {
|
||||||
|
image = "dockurr/windows";
|
||||||
|
environment = with cfg.settings; {
|
||||||
|
"VERSION" = version;
|
||||||
|
"RAM_SIZE" = ramSize;
|
||||||
|
"CPU_CORES" = cpuCores;
|
||||||
|
"DISK_SIZE" = diskSize;
|
||||||
|
"USERNAME" = username;
|
||||||
|
"PASSWORD" = password;
|
||||||
|
"LANGUAGE" = language;
|
||||||
|
"REGION" = region;
|
||||||
|
"KEYBOARD" = keyboard;
|
||||||
|
};
|
||||||
|
volumes = [
|
||||||
|
"${cfg.volume}:/storage:rw"
|
||||||
|
]
|
||||||
|
++ optional (cfg.sharedVolume != null) "${cfg.sharedVolume}:/shared:rw";
|
||||||
|
ports = [
|
||||||
|
"8006:8006/tcp"
|
||||||
|
"3389:3389/tcp"
|
||||||
|
"3389:3389/udp"
|
||||||
|
];
|
||||||
|
log-driver = "journald";
|
||||||
|
extraOptions = [
|
||||||
|
"--cap-add=NET_ADMIN"
|
||||||
|
"--device=/dev/kvm:/dev/kvm:rwm"
|
||||||
|
"--device=/dev/net/tun:/dev/net/tun:rwm"
|
||||||
|
"--network-alias=windows"
|
||||||
|
"--network=windows_default"
|
||||||
|
];
|
||||||
|
};
|
||||||
|
systemd.services."podman-windows" = {
|
||||||
|
serviceConfig = {
|
||||||
|
Restart = mkOverride 90 "always";
|
||||||
|
};
|
||||||
|
after = [
|
||||||
|
"podman-network-windows_default.service"
|
||||||
|
];
|
||||||
|
requires = [
|
||||||
|
"podman-network-windows_default.service"
|
||||||
|
];
|
||||||
|
partOf = [
|
||||||
|
"podman-compose-windows-root.target"
|
||||||
|
];
|
||||||
|
wantedBy = [
|
||||||
|
"podman-compose-windows-root.target"
|
||||||
|
];
|
||||||
|
};
|
||||||
|
|
||||||
|
systemd.services."podman-network-windows_default" = {
|
||||||
|
path = [ pkgs.podman ];
|
||||||
|
serviceConfig = {
|
||||||
|
Type = "oneshot";
|
||||||
|
RemainAfterExit = true;
|
||||||
|
ExecStop = "podman network rm -f windows_default";
|
||||||
|
};
|
||||||
|
script = ''
|
||||||
|
podman network inspect windows_default || podman network create windows_default
|
||||||
|
'';
|
||||||
|
partOf = [ "podman-compose-windows-root.target" ];
|
||||||
|
wantedBy = [ "podman-compose-windows-root.target" ];
|
||||||
|
};
|
||||||
|
|
||||||
|
systemd.targets."podman-compose-windows-root" = {
|
||||||
|
unitConfig = {
|
||||||
|
Description = "Root target generated by compose2nix.";
|
||||||
|
};
|
||||||
|
wantedBy = [ "multi-user.target" ];
|
||||||
|
};
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
||||||
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."
|
||||||
|
|
@ -14,78 +14,72 @@ let
|
||||||
;
|
;
|
||||||
in
|
in
|
||||||
{
|
{
|
||||||
nix = {
|
nix.package = mkDefault pkgs.nix;
|
||||||
package = mkDefault pkgs.nix;
|
|
||||||
|
|
||||||
# for `nix run synix#foo`, `nix build synix#bar`, etc
|
# for `nix run synix#foo`, `nix build synix#bar`, etc
|
||||||
registry = {
|
nix.registry = {
|
||||||
synix = {
|
synix = {
|
||||||
from = {
|
from = {
|
||||||
id = "synix";
|
id = "synix";
|
||||||
type = "indirect";
|
type = "indirect";
|
||||||
};
|
};
|
||||||
to = {
|
to = {
|
||||||
owner = "sid";
|
owner = "sid";
|
||||||
repo = "synix";
|
repo = "synix";
|
||||||
host = "git.sid.ovh";
|
host = "git.sid.ovh";
|
||||||
type = "gitea";
|
type = "gitea";
|
||||||
};
|
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
};
|
||||||
|
|
||||||
settings = {
|
# fallback quickly if substituters are not available.
|
||||||
warn-dirty = mkDefault false;
|
nix.settings.connect-timeout = mkDefault 5;
|
||||||
|
nix.settings.fallback = true;
|
||||||
|
|
||||||
# fallback quickly if substituters are not available.
|
nix.settings.experimental-features = [
|
||||||
connect-timeout = mkDefault 5;
|
"nix-command"
|
||||||
fallback = true;
|
"flakes"
|
||||||
|
]
|
||||||
|
++ optional (
|
||||||
|
config.nix.package != null && versionOlder (versions.majorMinor config.nix.package.version) "2.22"
|
||||||
|
) "repl-flake";
|
||||||
|
|
||||||
experimental-features = [
|
nix.settings.log-lines = mkDefault 25;
|
||||||
"nix-command"
|
|
||||||
"flakes"
|
|
||||||
]
|
|
||||||
++ optional (
|
|
||||||
config.nix.package != null && versionOlder (versions.majorMinor config.nix.package.version) "2.22"
|
|
||||||
) "repl-flake";
|
|
||||||
|
|
||||||
log-lines = mkDefault 25;
|
# avoid disk full issues
|
||||||
|
nix.settings.max-free = mkDefault (3000 * 1024 * 1024);
|
||||||
|
nix.settings.min-free = mkDefault (512 * 1024 * 1024);
|
||||||
|
|
||||||
# avoid disk full issues
|
# avoid copying unnecessary stuff over SSH
|
||||||
max-free = mkDefault (3000 * 1024 * 1024);
|
nix.settings.builders-use-substitutes = true;
|
||||||
min-free = mkDefault (512 * 1024 * 1024);
|
|
||||||
|
|
||||||
# avoid copying unnecessary stuff over SSH
|
# workaround for https://github.com/NixOS/nix/issues/9574
|
||||||
builders-use-substitutes = true;
|
nix.settings.nix-path = config.nix.nixPath;
|
||||||
|
|
||||||
# workaround for https://github.com/NixOS/nix/issues/9574
|
nix.settings.download-buffer-size = 524288000; # 500 MiB
|
||||||
nix-path = config.nix.nixPath;
|
|
||||||
|
|
||||||
download-buffer-size = 524288000; # 500 MiB
|
# add all wheel users to the trusted-users group
|
||||||
|
nix.settings.trusted-users = [
|
||||||
|
"@wheel"
|
||||||
|
];
|
||||||
|
|
||||||
# add all wheel users to the trusted-users group
|
# binary caches
|
||||||
trusted-users = [
|
nix.settings.substituters = [
|
||||||
"@wheel"
|
"https://cache.nixos.org"
|
||||||
];
|
"https://nix-community.cachix.org"
|
||||||
|
"https://cache.garnix.io"
|
||||||
|
"https://numtide.cachix.org"
|
||||||
|
];
|
||||||
|
nix.settings.trusted-public-keys = [
|
||||||
|
"cache.nixos.org-1:6NCHdD59X431o0gWypbMrAURkbJ16ZPMQFGspcDShjY="
|
||||||
|
"nix-community.cachix.org-1:mB9FSh9qf2dCimDSUo8Zy7bkq5CX+/rkCWyvRCYg3Fs="
|
||||||
|
"cache.garnix.io:CTFPyKSLcx5RMJKfLo5EEPUObbA78b0YQ2DTCJXqr9g="
|
||||||
|
"numtide.cachix.org-1:2ps1kLBUWjxIneOy1Ik6cQjb41X0iXVXeHigGmycPPE="
|
||||||
|
];
|
||||||
|
|
||||||
# binary caches
|
nix.gc = {
|
||||||
substituters = [
|
automatic = true;
|
||||||
"https://cache.nixos.org"
|
dates = "weekly";
|
||||||
"https://nix-community.cachix.org"
|
options = "--delete-older-than 30d";
|
||||||
"https://cache.garnix.io"
|
|
||||||
"https://numtide.cachix.org"
|
|
||||||
];
|
|
||||||
trusted-public-keys = [
|
|
||||||
"cache.nixos.org-1:6NCHdD59X431o0gWypbMrAURkbJ16ZPMQFGspcDShjY="
|
|
||||||
"nix-community.cachix.org-1:mB9FSh9qf2dCimDSUo8Zy7bkq5CX+/rkCWyvRCYg3Fs="
|
|
||||||
"cache.garnix.io:CTFPyKSLcx5RMJKfLo5EEPUObbA78b0YQ2DTCJXqr9g="
|
|
||||||
"numtide.cachix.org-1:2ps1kLBUWjxIneOy1Ik6cQjb41X0iXVXeHigGmycPPE="
|
|
||||||
];
|
|
||||||
};
|
|
||||||
|
|
||||||
gc = {
|
|
||||||
automatic = true;
|
|
||||||
dates = "weekly";
|
|
||||||
options = "--delete-older-than 30d";
|
|
||||||
};
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -9,17 +9,11 @@
|
||||||
|
|
||||||
modifications = final: prev: {
|
modifications = final: prev: {
|
||||||
# https://github.com/NixOS/nixpkgs/issues/335003#issuecomment-2755803376
|
# https://github.com/NixOS/nixpkgs/issues/335003#issuecomment-2755803376
|
||||||
kicad = prev.kicad.override {
|
kicad = (
|
||||||
stable = true;
|
prev.kicad.override {
|
||||||
};
|
stable = true;
|
||||||
|
}
|
||||||
python312 = prev.python312.override {
|
);
|
||||||
packageOverrides = pyFinal: pyPrev: {
|
|
||||||
arxiv = pyPrev.arxiv.overridePythonAttrs (old: {
|
|
||||||
pythonRemoveDeps = (old.pythonRemoveDeps or [ ]) ++ [ "requests" ];
|
|
||||||
});
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
# bemenu is not a valid selector in v1.5.1
|
# bemenu is not a valid selector in v1.5.1
|
||||||
rofi-rbw-wayland = prev.rofi-rbw-wayland.overrideAttrs (oldAttrs: {
|
rofi-rbw-wayland = prev.rofi-rbw-wayland.overrideAttrs (oldAttrs: {
|
||||||
|
|
|
||||||
|
|
@ -1,28 +1,25 @@
|
||||||
{
|
{
|
||||||
lib,
|
lib,
|
||||||
python312,
|
python3,
|
||||||
fetchPypi,
|
fetchPypi,
|
||||||
}:
|
}:
|
||||||
|
|
||||||
let
|
python3.pkgs.buildPythonApplication rec {
|
||||||
python = python312;
|
|
||||||
in
|
|
||||||
python.pkgs.buildPythonApplication rec {
|
|
||||||
pname = "arxiv-mcp-server";
|
pname = "arxiv-mcp-server";
|
||||||
version = "0.5.0";
|
version = "0.3.1";
|
||||||
pyproject = true;
|
pyproject = true;
|
||||||
|
|
||||||
src = fetchPypi {
|
src = fetchPypi {
|
||||||
pname = "arxiv_mcp_server";
|
pname = "arxiv_mcp_server";
|
||||||
inherit version;
|
inherit version;
|
||||||
hash = "sha256-vxrKyq+uOgVYtWrvikcIidLra6n0GFlFvfKztrc7GH8=";
|
hash = "sha256-yGNetU7el6ZXsavD8uvO17OZtaPuYgzkxiVEk402GUs=";
|
||||||
};
|
};
|
||||||
|
|
||||||
build-system = [
|
build-system = [
|
||||||
python.pkgs.hatchling
|
python3.pkgs.hatchling
|
||||||
];
|
];
|
||||||
|
|
||||||
dependencies = with python.pkgs; [
|
dependencies = with python3.pkgs; [
|
||||||
aiofiles
|
aiofiles
|
||||||
aiohttp
|
aiohttp
|
||||||
anyio
|
anyio
|
||||||
|
|
@ -39,7 +36,7 @@ python.pkgs.buildPythonApplication rec {
|
||||||
uvicorn
|
uvicorn
|
||||||
];
|
];
|
||||||
|
|
||||||
optional-dependencies = with python.pkgs; {
|
optional-dependencies = with python3.pkgs; {
|
||||||
test = [
|
test = [
|
||||||
aioresponses
|
aioresponses
|
||||||
pytest
|
pytest
|
||||||
|
|
@ -51,7 +48,6 @@ python.pkgs.buildPythonApplication rec {
|
||||||
|
|
||||||
pythonRemoveDeps = [
|
pythonRemoveDeps = [
|
||||||
"black"
|
"black"
|
||||||
"mcp"
|
|
||||||
];
|
];
|
||||||
|
|
||||||
pythonImportsCheck = [
|
pythonImportsCheck = [
|
||||||
|
|
|
||||||
|
|
@ -11,19 +11,17 @@
|
||||||
|
|
||||||
rustPlatform.buildRustPackage rec {
|
rustPlatform.buildRustPackage rec {
|
||||||
pname = "baibot";
|
pname = "baibot";
|
||||||
version = "1.19.3";
|
version = "1.14.3";
|
||||||
|
|
||||||
src = fetchFromGitHub {
|
src = fetchFromGitHub {
|
||||||
owner = "etkecc";
|
owner = "etkecc";
|
||||||
repo = "baibot";
|
repo = "baibot";
|
||||||
rev = "v${version}";
|
rev = "v${version}";
|
||||||
hash = "sha256-Fr1CvFocb/VAYQGykXXZ6CCfvC31bKB/tr1aoA4oIME=";
|
hash = "sha256-bFUijsvwUQhISjWVoVvoDXNSDPaWZTunqUfxfgaxclM=";
|
||||||
};
|
};
|
||||||
|
|
||||||
cargoHash = "sha256-CNEkge585bzUUPMHCSJ1CAH5wx3Wttq9I3A3oqfBzis=";
|
useFetchCargoVendor = true;
|
||||||
|
cargoHash = "sha256-/7KSCVWuxTk7gKOYxE/uQ5T0BnYlDYWOvdFXEiU9mB0=";
|
||||||
cargoBuildFlags = "--ignore-rust-version";
|
|
||||||
cargoTestFlags = "--ignore-rust-version";
|
|
||||||
|
|
||||||
nativeBuildInputs = [
|
nativeBuildInputs = [
|
||||||
pkg-config
|
pkg-config
|
||||||
|
|
|
||||||
|
|
@ -6,13 +6,13 @@
|
||||||
|
|
||||||
python3.pkgs.buildPythonApplication rec {
|
python3.pkgs.buildPythonApplication rec {
|
||||||
pname = "blender-mcp";
|
pname = "blender-mcp";
|
||||||
version = "1.5.6";
|
version = "1.5.5";
|
||||||
pyproject = true;
|
pyproject = true;
|
||||||
|
|
||||||
src = fetchPypi {
|
src = fetchPypi {
|
||||||
pname = "blender_mcp";
|
pname = "blender_mcp";
|
||||||
inherit version;
|
inherit version;
|
||||||
hash = "sha256-9aBGQcMC1ustj3H1WgRFCha6fk+XSASIzcZr6Rrgif4=";
|
hash = "sha256-n8bYnrDVLe5zPvg8rbGgh5U5AeIm/DA6aPgmxS68d7g=";
|
||||||
};
|
};
|
||||||
|
|
||||||
build-system = [
|
build-system = [
|
||||||
|
|
|
||||||
|
|
@ -11,20 +11,15 @@
|
||||||
cppman = pkgs.callPackage ./cppman { };
|
cppman = pkgs.callPackage ./cppman { };
|
||||||
fetcher-mcp = pkgs.callPackage ./fetcher-mcp { };
|
fetcher-mcp = pkgs.callPackage ./fetcher-mcp { };
|
||||||
freecad-mcp = pkgs.callPackage ./freecad-mcp { };
|
freecad-mcp = pkgs.callPackage ./freecad-mcp { };
|
||||||
jirafeau = pkgs.callPackage ./jirafeau { };
|
|
||||||
jirafeau-cli = pkgs.callPackage ./jirafeau-cli { };
|
|
||||||
kicad-mcp = pkgs.callPackage ./kicad-mcp { };
|
kicad-mcp = pkgs.callPackage ./kicad-mcp { };
|
||||||
mcpo = pkgs.callPackage ./mcpo { };
|
mcpo = pkgs.callPackage ./mcpo { };
|
||||||
nerdlog = pkgs.callPackage ./nerdlog { };
|
|
||||||
pass2bw = pkgs.callPackage ./pass2bw { };
|
pass2bw = pkgs.callPackage ./pass2bw { };
|
||||||
pyman = pkgs.callPackage ./pyman { };
|
pyman = pkgs.callPackage ./pyman { };
|
||||||
quicknote = pkgs.callPackage ./quicknote { };
|
quicknote = pkgs.callPackage ./quicknote { };
|
||||||
synapse_change_display_name = pkgs.callPackage ./synapse_change_display_name { };
|
synapse_change_display_name = pkgs.callPackage ./synapse_change_display_name { };
|
||||||
synix-docs = pkgs.callPackage ./synix-docs { };
|
synix-docs = pkgs.callPackage ./synix-docs { };
|
||||||
tinyfugue = pkgs.callPackage ./tinyfugue { };
|
|
||||||
trelis-gitingest-mcp = pkgs.callPackage ./trelis-gitingest-mcp { };
|
trelis-gitingest-mcp = pkgs.callPackage ./trelis-gitingest-mcp { };
|
||||||
tunerstudio = pkgs.callPackage ./tunerstudio { };
|
tunerstudio = pkgs.callPackage ./tunerstudio { };
|
||||||
|
|
||||||
# marker-pdf = pkgs.callPackage ./marker-pdf { }; # FIXME
|
# marker-pdf = pkgs.callPackage ./marker-pdf { }; # FIXME
|
||||||
# openmv-ide = pkgs.callPackage ./openmv-ide { }; # FIXME
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -12,9 +12,11 @@
|
||||||
let
|
let
|
||||||
revision = "1161";
|
revision = "1161";
|
||||||
|
|
||||||
chromium-headless-shell = playwright-driver.passthru.components."chromium-headless-shell".overrideAttrs (old: {
|
chromium-headless-shell =
|
||||||
inherit revision;
|
playwright-driver.passthru.components."chromium-headless-shell".overrideAttrs
|
||||||
});
|
(old: {
|
||||||
|
inherit revision;
|
||||||
|
});
|
||||||
|
|
||||||
browsers-headless-only = linkFarm "playwright-browsers-headless-only" [
|
browsers-headless-only = linkFarm "playwright-browsers-headless-only" [
|
||||||
{
|
{
|
||||||
|
|
@ -23,9 +25,9 @@ let
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
in
|
in
|
||||||
buildNpmPackage {
|
buildNpmPackage rec {
|
||||||
pname = "fetcher-mcp";
|
pname = "fetcher-mcp";
|
||||||
version = "0.3.9";
|
version = "0.3.6";
|
||||||
|
|
||||||
src = fetchFromGitHub {
|
src = fetchFromGitHub {
|
||||||
owner = "jae-jae";
|
owner = "jae-jae";
|
||||||
|
|
@ -60,6 +62,7 @@ buildNpmPackage {
|
||||||
description = "MCP server for fetch web page content using Playwright headless browser";
|
description = "MCP server for fetch web page content using Playwright headless browser";
|
||||||
homepage = "https://github.com/jae-jae/fetcher-mcp";
|
homepage = "https://github.com/jae-jae/fetcher-mcp";
|
||||||
license = lib.licenses.mit;
|
license = lib.licenses.mit;
|
||||||
|
maintainers = with lib.maintainers; [ ];
|
||||||
mainProgram = "fetcher-mcp";
|
mainProgram = "fetcher-mcp";
|
||||||
platforms = lib.platforms.all;
|
platforms = lib.platforms.all;
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -6,13 +6,13 @@
|
||||||
|
|
||||||
python3.pkgs.buildPythonApplication rec {
|
python3.pkgs.buildPythonApplication rec {
|
||||||
pname = "freecad-mcp";
|
pname = "freecad-mcp";
|
||||||
version = "0.1.17";
|
version = "0.1.16";
|
||||||
pyproject = true;
|
pyproject = true;
|
||||||
|
|
||||||
src = fetchPypi {
|
src = fetchPypi {
|
||||||
pname = "freecad_mcp";
|
pname = "freecad_mcp";
|
||||||
inherit version;
|
inherit version;
|
||||||
hash = "sha256-DugQWGZizIXO27cjzfyidNTyyahN1BTcDNTl4DHWqN0=";
|
hash = "sha256-eFt7UgJw56C2zY8Vznrg8L0a5nvP0xtiW1oJuJ/fL3Y=";
|
||||||
};
|
};
|
||||||
|
|
||||||
build-system = [
|
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
|
|
||||||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue