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
|
||||
|
|
|
|||
|
|
@ -1,4 +1,3 @@
|
|||
---
|
||||
name: Build tests
|
||||
|
||||
on:
|
||||
|
|
|
|||
|
|
@ -1,4 +1,3 @@
|
|||
---
|
||||
name: Deploy docs
|
||||
|
||||
on:
|
||||
|
|
|
|||
|
|
@ -1,8 +1,6 @@
|
|||
---
|
||||
name: Flake check
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
on: [pull_request]
|
||||
|
||||
jobs:
|
||||
flake-check:
|
||||
|
|
@ -13,8 +11,5 @@ jobs:
|
|||
- name: Checkout repository
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Check formatting
|
||||
run: nix fmt -- --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";
|
||||
```
|
||||
|
||||
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
|
||||
|
||||
|
|
|
|||
|
|
@ -11,6 +11,9 @@ HOSTNAME=""
|
|||
# Templates with Home Manager configurations
|
||||
HM_CONFIGS=("hyprland")
|
||||
|
||||
# This will get overwritten by the derivation
|
||||
TEMPLATES_DIR=""
|
||||
|
||||
# Print usage information
|
||||
usage() {
|
||||
cat <<EOF
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@
|
|||
home-manager,
|
||||
hostname,
|
||||
nix,
|
||||
nixos-rebuild-ng,
|
||||
nixos-rebuild,
|
||||
...
|
||||
}:
|
||||
|
||||
|
|
@ -25,6 +25,6 @@ writeShellApplication {
|
|||
home-manager
|
||||
hostname
|
||||
nix
|
||||
nixos-rebuild-ng
|
||||
nixos-rebuild
|
||||
];
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,21 +1,15 @@
|
|||
#!/usr/bin/env bash
|
||||
# NixOS and standalone Home Manager rebuild script
|
||||
|
||||
# Defaults
|
||||
FLAKE_PATH="${REBUILD_FLAKE_PATH:-${FLAKE_PATH:-$HOME/.config/nixos}}" # Default flake path
|
||||
USER="${REBUILD_USER:-$(whoami)}" # Default username
|
||||
HOST="${REBUILD_HOST:-$(hostname)}" # Default hostname
|
||||
BUILD_HOST="${REBUILD_BUILD_HOST:-}" # Default build host
|
||||
TARGET_HOST="${REBUILD_TARGET_HOST:-}" # Default target host
|
||||
UPDATE="${REBUILD_UPDATE:-0}" # Default to not update
|
||||
UPDATE_INPUTS="${REBUILD_UPDATE_INPUTS:-}" # Default list of inputs
|
||||
ROLLBACK="${REBUILD_ROLLBACK:-0}" # Default to not rollback
|
||||
SHOW_TRACE="${REBUILD_SHOW_TRACE:-0}" # Default to not show trace
|
||||
|
||||
# Output functions
|
||||
_status() { echo -e "\033[0;34m> $1\033[0m"; }
|
||||
success() { echo -e "\033[0;32m$1\033[0m"; }
|
||||
error() { echo -e "\033[0;31mError: $1\033[0m" >&2; exit 1; }
|
||||
FLAKE_PATH="$HOME/.config/nixos" # Default flake path
|
||||
HOME_USER="$(whoami)" # Default username. Used to identify the Home Manager configuration
|
||||
NIXOS_HOST="$(hostname)" # Default hostname. Used to identify the NixOS and Home Manager configuration
|
||||
BUILD_HOST="" # Default build host. Empty means localhost
|
||||
TARGET_HOST="" # Default target host. Empty means localhost
|
||||
UPDATE=0 # Default to not update flake repositories
|
||||
UPDATE_INPUTS="" # Default list of inputs to update. Empty means all
|
||||
ROLLBACK=0 # Default to not rollback
|
||||
SHOW_TRACE=0 # Default to not show detailed error messages
|
||||
|
||||
# Function to display the help message
|
||||
Help() {
|
||||
|
|
@ -29,7 +23,7 @@ Help() {
|
|||
echo " help Show this help message"
|
||||
echo
|
||||
echo "Options (for NixOS and Home Manager):"
|
||||
echo " -H, --host <host> Specify the hostname (as in 'nixosConfiguraions.<host>'). Default: $HOST"
|
||||
echo " -H, --host <host> Specify the hostname (as in 'nixosConfiguraions.<host>'). Default: $NIXOS_HOST"
|
||||
echo " -p, --path <path> Set the path to the flake directory. Default: $FLAKE_PATH"
|
||||
echo " -U, --update [inputs] Update all flake inputs. Optionally provide comma-separated list of inputs to update instead."
|
||||
echo " -r, --rollback Don't build the new configuration, but use the previous generation instead"
|
||||
|
|
@ -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
|
||||
echo "Home Manager only options:"
|
||||
echo " -u, --user <user> Specify the username (as in 'homeConfigurations.<user>@<host>'). Default: $USER"
|
||||
echo " -u, --user <user> Specify the username (as in 'homeConfigurations.<user>@<host>'). Default: $HOME_USER"
|
||||
}
|
||||
|
||||
# Function to handle errors
|
||||
error() {
|
||||
echo "Error: $1"
|
||||
exit 1
|
||||
}
|
||||
|
||||
# Function to rebuild NixOS configuration
|
||||
Rebuild_nixos() {
|
||||
local FLAKE="$FLAKE_PATH#$HOST"
|
||||
local FLAKE="$FLAKE_PATH#$NIXOS_HOST"
|
||||
|
||||
# Construct rebuild command
|
||||
local CMD=("nixos-rebuild" "switch" "--sudo")
|
||||
[[ -n "$TARGET_HOST" || -n "$BUILD_HOST" ]] && CMD+=("--ask-sudo-password")
|
||||
CMD+=("--flake" "$FLAKE")
|
||||
[ "$ROLLBACK" = 1 ] && CMD+=("--rollback")
|
||||
[ "$SHOW_TRACE" = 1 ] && CMD+=("--show-trace")
|
||||
[ -n "$BUILD_HOST" ] && CMD+=("--build-host" "$BUILD_HOST")
|
||||
if [ "$HOST" != "$(hostname)" ] && [ -z "$TARGET_HOST" ]; then
|
||||
TARGET_HOST="$HOST"
|
||||
_status "Using '$TARGET_HOST' as target host."
|
||||
if [ "$NIXOS_HOST" != "$(hostname)" ] && [ -z "$TARGET_HOST" ]; then
|
||||
TARGET_HOST="$NIXOS_HOST"
|
||||
echo "Using '$TARGET_HOST' as target host."
|
||||
fi
|
||||
[ -n "$TARGET_HOST" ] && CMD+=("--target-host" "$TARGET_HOST")
|
||||
[[ -n "$TARGET_HOST" || -n "$BUILD_HOST" ]] && CMD+=("--ask-sudo-password")
|
||||
|
||||
# Build config first so we can diff it
|
||||
local BUILD_CMD=("nixos-rebuild" "build" "--no-build-output" "--flake" "$FLAKE")
|
||||
[ "$SHOW_TRACE" = 1 ] && BUILD_CMD+=("--show-trace")
|
||||
[ -n "$BUILD_HOST" ] && BUILD_CMD+=("--build-host" "$BUILD_HOST")
|
||||
|
||||
# Rebuild NixOS configuration
|
||||
if [ "$ROLLBACK" = 0 ]; then
|
||||
_status "Building NixOS configuration '$FLAKE'..."
|
||||
_status "Executing command: ${BUILD_CMD[*]}"
|
||||
"${BUILD_CMD[@]}" || error "NixOS build failed"
|
||||
|
||||
_status "Switching to new NixOS configuration"
|
||||
echo "Rebuilding NixOS configuration '$FLAKE'..."
|
||||
else
|
||||
_status "Rolling back to last NixOS generation"
|
||||
echo "Rolling back to last NixOS generation..."
|
||||
fi
|
||||
|
||||
sudo -v
|
||||
_status "Executing command: ${CMD[*]}"
|
||||
echo "Executing command: ${CMD[*]}"
|
||||
"${CMD[@]}" || error "NixOS rebuild failed"
|
||||
success "NixOS rebuild completed successfully."
|
||||
echo "NixOS rebuild completed successfully."
|
||||
}
|
||||
|
||||
# Function to rebuild Home Manager configuration
|
||||
Rebuild_home() {
|
||||
local FLAKE="$FLAKE_PATH#$USER@$HOST"
|
||||
local FLAKE="$FLAKE_PATH#$HOME_USER@$NIXOS_HOST"
|
||||
|
||||
if [ -n "$BUILD_HOST" ] || [ -n "$TARGET_HOST" ]; then
|
||||
error "Remote building is not supported for Home Manager."
|
||||
|
|
@ -100,27 +91,21 @@ Rebuild_home() {
|
|||
[ "$SHOW_TRACE" = 1 ] && CMD+=("--show-trace")
|
||||
fi
|
||||
|
||||
# Build config first so we can diff it
|
||||
# Rebuild Home Manager configuration
|
||||
if [ "$ROLLBACK" = 0 ]; then
|
||||
local BUILD_CMD=("home-manager" "build" "--no-out-link" "--flake" "$FLAKE")
|
||||
[ "$SHOW_TRACE" = 1 ] && BUILD_CMD+=("--show-trace")
|
||||
_status "Building Home Manager configuration '$FLAKE'..."
|
||||
_status "Executing command: ${BUILD_CMD[*]}"
|
||||
"${BUILD_CMD[@]}" || error "Home Manager build failed"
|
||||
|
||||
_status "Switching to new Home Manager configuration"
|
||||
echo "Rebuilding Home Manager configuration '$FLAKE'..."
|
||||
else
|
||||
_status "Rolling back to last Home Manager generation"
|
||||
echo "Rolling back to last Home Manager generation..."
|
||||
fi
|
||||
|
||||
_status "Executing command: ${CMD[*]}"
|
||||
echo "Executing command: ${CMD[*]}"
|
||||
"${CMD[@]}" || error "Home Manager rebuild failed"
|
||||
success "Home Manager rebuild completed successfully."
|
||||
echo "Home Manager rebuild completed successfully."
|
||||
}
|
||||
|
||||
# Function to update flake repositories
|
||||
# Function to Update flake repositories
|
||||
Update() {
|
||||
_status "Updating flake inputs..."
|
||||
echo "Updating flake inputs..."
|
||||
|
||||
# Construct update command as an array
|
||||
local CMD=("nix" "flake" "update" "--flake" "$FLAKE_PATH")
|
||||
|
|
@ -132,18 +117,17 @@ Update() {
|
|||
done
|
||||
fi
|
||||
|
||||
_status "Executing command: ${CMD[*]}"
|
||||
echo "Executing command: ${CMD[*]}"
|
||||
"${CMD[@]}" || error "Failed to update flake repositories"
|
||||
success "Flake repositories updated successfully."
|
||||
echo "Flake repositories updated successfully."
|
||||
}
|
||||
|
||||
# Parse command-line options
|
||||
if [[ -z "${1:-}" ]]; then
|
||||
echo -e "\033[0;31mError: No command specified. Printing help page.\033[0m" >&2
|
||||
echo "Error: No command specified. Printing help page."
|
||||
Help
|
||||
exit 1
|
||||
fi
|
||||
|
||||
COMMAND=$1
|
||||
shift
|
||||
|
||||
|
|
@ -157,7 +141,7 @@ while [ $# -gt 0 ]; do
|
|||
case "${1:-}" in
|
||||
-H|--host)
|
||||
if [ -n "${2:-}" ]; then
|
||||
HOST="$2"
|
||||
NIXOS_HOST="$2"
|
||||
shift 2
|
||||
else
|
||||
error "-H|--host option requires an argument"
|
||||
|
|
@ -165,7 +149,7 @@ while [ $# -gt 0 ]; do
|
|||
;;
|
||||
-u|--user)
|
||||
if [ -n "${2:-}" ]; then
|
||||
USER="$2"
|
||||
HOME_USER="$2"
|
||||
shift 2
|
||||
else
|
||||
error "-u|--user option requires an argument"
|
||||
|
|
@ -214,7 +198,9 @@ while [ $# -gt 0 ]; do
|
|||
fi
|
||||
;;
|
||||
*)
|
||||
error "Unknown option '$1'"
|
||||
echo "Error: Unknown option '$1'"
|
||||
Help
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
|
@ -241,10 +227,10 @@ fi
|
|||
[ "$UPDATE" = 1 ] && Update
|
||||
|
||||
case "$COMMAND" in
|
||||
nixos|os)
|
||||
nixos)
|
||||
Rebuild_nixos
|
||||
;;
|
||||
home|hm)
|
||||
home)
|
||||
Rebuild_home
|
||||
;;
|
||||
all)
|
||||
|
|
@ -252,6 +238,9 @@ case "$COMMAND" in
|
|||
Rebuild_home
|
||||
;;
|
||||
*)
|
||||
error "Unknown command '$COMMAND'"
|
||||
echo "Error: Unknown command '$COMMAND'"
|
||||
echo "Printing help page:"
|
||||
Help
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
|
|
|
|||
|
|
@ -1,4 +1,3 @@
|
|||
#!/usr/bin/env bash
|
||||
SYSTEM="x86_64-linux"
|
||||
IGNORE_PACKAGES=(
|
||||
"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:
|
||||
|
||||
```bash
|
||||
nix --experimental-features "nix-command flakes" develop git+https://git.sid.ovh/sid/synix#devShells.x86_64-linux.install-hm \
|
||||
--command "rebuild home"
|
||||
nix-shell ~/.config/nixos/shell.nix --run 'rebuild home'
|
||||
```
|
||||
|
||||
### 8. Reboot your System
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@ Provide the following entries to your `secrets.yaml`:
|
|||
```yaml
|
||||
headplane:
|
||||
cookie_secret: abc123
|
||||
api_key: abc123
|
||||
agent_pre_authkey: abc123
|
||||
```
|
||||
|
||||
Generate your cookie secret with:
|
||||
|
|
@ -28,7 +28,7 @@ Generate your cookie secret with:
|
|||
nix-shell -p openssl --run "openssl rand -hex 16"
|
||||
```
|
||||
|
||||
Generate your agent `api_key` with:
|
||||
Generate your agent pre-authkey with:
|
||||
|
||||
```bash
|
||||
sudo headscale users create headplane-agent
|
||||
|
|
|
|||
36
docs/modules/nixos/tailscale.md
Normal file
36
docs/modules/nixos/tailscale.md
Normal file
|
|
@ -0,0 +1,36 @@
|
|||
# Tailscale
|
||||
|
||||
Private WireGuard networks made easy.
|
||||
|
||||
View the [*synix* NixOS module on Forgejo](https://git.sid.ovh/sid/synix/tree/master/modules/nixos/tailscale).
|
||||
|
||||
## References
|
||||
|
||||
- [Website](https://tailscale.com/)
|
||||
- [GitHub](https://github.com/tailscale/tailscale)
|
||||
- [Documents](https://tailscale.com/kb/1017/install)
|
||||
|
||||
## Sops
|
||||
|
||||
Provide the following entries to your `secrets.yaml`:
|
||||
|
||||
> Replace `abc123` with your actual secrets
|
||||
|
||||
```yaml
|
||||
tailscale:
|
||||
auth-key: abc123
|
||||
```
|
||||
|
||||
## Config
|
||||
|
||||
```nix
|
||||
{
|
||||
imports = [ inputs.synix.nixosModules.tailscale ];
|
||||
|
||||
services.tailscale = {
|
||||
enable = true;
|
||||
enableSSH = true;
|
||||
loginServer = "<your-headscale-instance>";
|
||||
};
|
||||
}
|
||||
```
|
||||
36
flake.lock
generated
36
flake.lock
generated
|
|
@ -202,11 +202,11 @@
|
|||
},
|
||||
"flake-schemas": {
|
||||
"locked": {
|
||||
"lastModified": 1776384880,
|
||||
"narHash": "sha256-28Cg9HI/IwFHUm5fZyMEGCQ94L3Il6K4OfHeRf0b+Zw=",
|
||||
"lastModified": 1770913512,
|
||||
"narHash": "sha256-jRC1qRoRCrMjDalVfUMHFlKSkkA2q0RZWTDW0LsquoA=",
|
||||
"owner": "DeterminateSystems",
|
||||
"repo": "flake-schemas",
|
||||
"rev": "b852751d29c6e09919f25c1e10754646bdc181c9",
|
||||
"rev": "3c464b0e09cb44c6e073c41dd1d834980c3e0b24",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
|
|
@ -258,11 +258,11 @@
|
|||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1778507602,
|
||||
"narHash": "sha256-kTwur1wV+01SdqskVMSo6JMEpg71ps3HpbFY2GsflKs=",
|
||||
"lastModified": 1772024342,
|
||||
"narHash": "sha256-+eXlIc4/7dE6EcPs9a2DaSY3fTA9AE526hGqkNID3Wg=",
|
||||
"owner": "cachix",
|
||||
"repo": "git-hooks.nix",
|
||||
"rev": "61ab0e80d9c7ab14c256b5b453d8b3fb0189ba0a",
|
||||
"rev": "6e34e97ed9788b17796ee43ccdbaf871a5c2b476",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
|
|
@ -349,11 +349,11 @@
|
|||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1779506708,
|
||||
"narHash": "sha256-QOD/CNm196nCJRheux/URi4/HE66fthdOMqCJoPP1Y0=",
|
||||
"lastModified": 1772020340,
|
||||
"narHash": "sha256-aqBl3GNpCadMoJ/hVkWTijM1Aeilc278MjM+LA3jK6g=",
|
||||
"owner": "nix-community",
|
||||
"repo": "home-manager",
|
||||
"rev": "3ee51fbdac8c8bdfe1e7e1fcaba6520a563f394f",
|
||||
"rev": "36e38ca0d9afe4c55405fdf22179a5212243eecc",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
|
|
@ -465,11 +465,11 @@
|
|||
},
|
||||
"nixpkgs_2": {
|
||||
"locked": {
|
||||
"lastModified": 1779467186,
|
||||
"narHash": "sha256-nOesoDCiXcUftqbRBMz9tt4blI5PvljMWbm3kuCA+0s=",
|
||||
"lastModified": 1771903837,
|
||||
"narHash": "sha256-sdaqdnsQCv3iifzxwB22tUwN/fSHoN7j2myFW5EIkGk=",
|
||||
"owner": "nixos",
|
||||
"repo": "nixpkgs",
|
||||
"rev": "b77b3de8775677f84492abe84635f87b0e153f0f",
|
||||
"rev": "e764fc9a405871f1f6ca3d1394fb422e0a0c3951",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
|
|
@ -511,11 +511,11 @@
|
|||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1779900588,
|
||||
"narHash": "sha256-b/yda4uMmjpw4uhXI4d0JNv09WtGoXis2JjD5l1Qbts=",
|
||||
"lastModified": 1772140017,
|
||||
"narHash": "sha256-wFUc9tn5Ik11oL009BkVnj4NxsY63UbZjhOyEqCsIQE=",
|
||||
"owner": "nix-community",
|
||||
"repo": "NUR",
|
||||
"rev": "dd8bdde89853bfb3eae0eb28e3d3a9320b3b8a3c",
|
||||
"rev": "be0fea0af0e8cfadb3995dd7bb3a167bc012e935",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
|
|
@ -605,11 +605,11 @@
|
|||
"tinted-zed": "tinted-zed"
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1778680496,
|
||||
"narHash": "sha256-tUq1WASV0dHLv3j18log8V6Esq0NYkXuzNH2EHsstcg=",
|
||||
"lastModified": 1771788390,
|
||||
"narHash": "sha256-RzBpBwn93GWxLjacTte+ngwwg0L/BVOg4G/sSIeK3Rw=",
|
||||
"owner": "nix-community",
|
||||
"repo": "stylix",
|
||||
"rev": "fc5bec2e44678eeaa221d566d447a0257a884737",
|
||||
"rev": "ebb238f14d6f930068be4718472da3105fd5d3bf",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
|
|
|
|||
186
flake.nix
186
flake.nix
|
|
@ -3,6 +3,7 @@
|
|||
nixpkgs.url = "github:nixos/nixpkgs/nixos-25.11";
|
||||
|
||||
nix.url = "github:DeterminateSystems/nix-src/flake-schemas";
|
||||
|
||||
flake-schemas.url = "github:DeterminateSystems/flake-schemas";
|
||||
|
||||
git-hooks.url = "github:cachix/git-hooks.nix";
|
||||
|
|
@ -28,69 +29,50 @@
|
|||
...
|
||||
}@inputs:
|
||||
let
|
||||
inherit (self) outputs;
|
||||
|
||||
systems = [
|
||||
supportedSystems = [
|
||||
"x86_64-linux"
|
||||
"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 =
|
||||
{
|
||||
system,
|
||||
config ? { },
|
||||
}:
|
||||
nixpkgsFor = forAllSystems (
|
||||
system:
|
||||
import nixpkgs {
|
||||
inherit system;
|
||||
inherit config;
|
||||
overlays = [
|
||||
self.overlays.modifications
|
||||
self.overlays.additions
|
||||
self.overlays.default
|
||||
inputs.nix.overlays.default
|
||||
(final: prev: { synix = self.overlays.additions final prev; })
|
||||
];
|
||||
};
|
||||
|
||||
forAllSystems =
|
||||
function:
|
||||
lib.genAttrs systems (
|
||||
system:
|
||||
function (mkPkgs {
|
||||
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;
|
||||
test = {
|
||||
system = "x86_64-linux";
|
||||
lib = nixpkgs.lib.extend (final: prev: self.outputs.lib or { });
|
||||
inputs = inputs // {
|
||||
synix = self;
|
||||
};
|
||||
outputs = { };
|
||||
overlays = [
|
||||
self.overlays.default
|
||||
self.overlays.additions
|
||||
self.overlays.modifications
|
||||
(final: prev: { synix = self.packages."${final.system}"; })
|
||||
];
|
||||
};
|
||||
in
|
||||
{
|
||||
inherit (inputs.flake-schemas) schemas;
|
||||
|
||||
apps = forAllSystems (
|
||||
pkgs:
|
||||
system:
|
||||
let
|
||||
mkApp = name: description: {
|
||||
pkgs = nixpkgs.legacyPackages.${system};
|
||||
mkApp = name: desc: {
|
||||
type = "app";
|
||||
program = pkgs.lib.getExe (pkgs.callPackage ./apps/${name} { });
|
||||
meta.description = description;
|
||||
meta.description = desc;
|
||||
};
|
||||
in
|
||||
{
|
||||
|
|
@ -104,17 +86,13 @@
|
|||
);
|
||||
|
||||
lib = {
|
||||
utils = import ./lib/utils.nix { inherit (nixpkgs) lib; };
|
||||
helpers = {
|
||||
inherit mkPkgs;
|
||||
};
|
||||
utils = import ./lib/utils.nix { lib = nixpkgs.lib; };
|
||||
};
|
||||
|
||||
packages = forAllSystems (
|
||||
pkgs:
|
||||
system:
|
||||
let
|
||||
inherit (pkgs.stdenv.hostPlatform) system;
|
||||
allArchs = import ./pkgs { inherit pkgs; };
|
||||
allArchs = import ./pkgs { pkgs = nixpkgs.legacyPackages.${system}; };
|
||||
x64only =
|
||||
if system == "x86_64-linux" then
|
||||
{
|
||||
|
|
@ -133,21 +111,52 @@
|
|||
|
||||
# test configs
|
||||
nixosConfigurations = {
|
||||
nixos-hyprland = mkNixosConfiguration "x86_64-linux" [ ./tests/build/nixos-hyprland ];
|
||||
nixos-server = mkNixosConfiguration "x86_64-linux" [ ./tests/build/nixos-server ];
|
||||
nixos-hyprland = nixpkgs.lib.nixosSystem {
|
||||
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 = {
|
||||
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 (
|
||||
pkgs:
|
||||
system:
|
||||
let
|
||||
inherit (pkgs.stdenv.hostPlatform) system;
|
||||
inherit (self.checks.${system}.pre-commit-check) shellHook enabledPackages;
|
||||
pkgs = nixpkgsFor.${system};
|
||||
in
|
||||
{
|
||||
default = pkgs.mkShell {
|
||||
default =
|
||||
let
|
||||
inherit (self.checks.${system}.pre-commit-check) shellHook enabledPackages;
|
||||
in
|
||||
pkgs.mkShell {
|
||||
inherit shellHook;
|
||||
nativeBuildInputs = [
|
||||
enabledPackages
|
||||
|
|
@ -164,66 +173,63 @@
|
|||
))
|
||||
]);
|
||||
};
|
||||
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 (
|
||||
pkgs:
|
||||
system:
|
||||
let
|
||||
inherit (pkgs.stdenv.hostPlatform) system;
|
||||
inherit (self.checks.${system}.pre-commit-check.config) package configFile;
|
||||
pkgs = nixpkgs.legacyPackages.${system};
|
||||
config = self.checks.${system}.pre-commit-check.config;
|
||||
inherit (config) package configFile;
|
||||
script = ''
|
||||
${pkgs.lib.getExe package} run --all-files --config ${configFile}
|
||||
'';
|
||||
in
|
||||
pkgs.writeShellScriptBin "pre-commit-run" "${pkgs.lib.getExe package} run --all-files --config ${configFile}"
|
||||
pkgs.writeShellScriptBin "pre-commit-run" script
|
||||
);
|
||||
|
||||
checks = forAllSystems (
|
||||
pkgs:
|
||||
system:
|
||||
let
|
||||
inherit (pkgs.stdenv.hostPlatform) system;
|
||||
pkgs = nixpkgs.legacyPackages.${system};
|
||||
flakePkgs = self.packages.${system};
|
||||
overlaidPkgs = import nixpkgs {
|
||||
inherit system;
|
||||
overlays = [ self.overlays.modifications ];
|
||||
};
|
||||
in
|
||||
{
|
||||
pre-commit-check = inputs.git-hooks.lib.${system}.run {
|
||||
src = ./.;
|
||||
hooks = {
|
||||
actionlint.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}}}";
|
||||
nixfmt.enable = true;
|
||||
};
|
||||
};
|
||||
build-packages = pkgs.linkFarm "flake-packages-${system}" flakePkgs;
|
||||
build-overlays = pkgs.linkFarm "flake-overlays-${system}" {
|
||||
kicad = overlaidPkgs.kicad;
|
||||
};
|
||||
|
||||
build-additions = pkgs.linkFarm "added-packages-${system}" self.packages.${system};
|
||||
build-modifications = pkgs.linkFarm "modified-packages-${system}" (
|
||||
lib.filterAttrs (_: v: lib.isDerivation v) (self.overlays.modifications pkgs pkgs)
|
||||
);
|
||||
|
||||
synapse-test =
|
||||
let
|
||||
testPkgs = mkPkgs {
|
||||
testPkgs = import nixpkgs {
|
||||
inherit system;
|
||||
config.permittedInsecurePackages = [ "olm-3.2.16" ];
|
||||
};
|
||||
in
|
||||
testPkgs.testers.runNixOSTest ./tests/run/synapse.nix;
|
||||
open-webui-oci-test = pkgs.testers.runNixOSTest ./tests/run/open-webui-oci.nix;
|
||||
# librechat-oci-test = pkgs.testers.runNixOSTest ./tests/run/librechat-oci.nix; # FIXME: unable to copy from source docker://quay.io/mongo:7.0
|
||||
|
||||
# NOTE: disabled for now since the test takes too long to execute
|
||||
# open-webui-oci-test =
|
||||
# let
|
||||
# testPkgs = import nixpkgs {
|
||||
# inherit system;
|
||||
# };
|
||||
# in
|
||||
# testPkgs.testers.runNixOSTest ./tests/run/open-webui-oci.nix;
|
||||
}
|
||||
|
||||
);
|
||||
|
||||
hydraJobs = {
|
||||
|
|
@ -283,10 +289,6 @@
|
|||
path = ./templates/dev/rs-hello;
|
||||
description = "Rust hello world template.";
|
||||
};
|
||||
stm32-blink = {
|
||||
path = ./templates/dev/stm32-blink;
|
||||
description = "STM32G4 blink template with libopencm3.";
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,3 @@
|
|||
---
|
||||
site_name: synix docs
|
||||
repo_url: https://git.sid.ovh/sid/synix
|
||||
site_url: https://doc.sid.ovh/synix
|
||||
|
|
@ -59,6 +58,7 @@ nav:
|
|||
- radicale: modules/nixos/radicale.md
|
||||
- rss-bridge: modules/nixos/rss-bridge.md
|
||||
- sops: modules/nixos/sops.md
|
||||
- tailscale: modules/nixos/tailscale.md
|
||||
- virtualisation: modules/nixos/virtualisation.md
|
||||
- webPage: modules/nixos/webpage.md
|
||||
- Home Manager:
|
||||
|
|
|
|||
|
|
@ -1,4 +1,3 @@
|
|||
#!/usr/bin/env bash
|
||||
# change directory with fzf
|
||||
# Usage: cdf [optional_relative_path]
|
||||
# - If no argument, searches from $HOME.
|
||||
|
|
@ -68,8 +67,7 @@ function cdf() {
|
|||
"--preview=tree -C {} | head -50"
|
||||
"--preview-window=right:50%:wrap"
|
||||
)
|
||||
local selected
|
||||
selected=$(find "${find_args[@]}" 2>/dev/null | fzf "${fzf_args[@]}")
|
||||
local selected=$(find "${find_args[@]}" 2>/dev/null | fzf "${fzf_args[@]}")
|
||||
|
||||
if [[ -n "$selected" ]]; then
|
||||
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 {
|
||||
type = types.str;
|
||||
inherit default;
|
||||
default = default;
|
||||
description = "The default application to use for the ${default}.";
|
||||
};
|
||||
bind = mkOption {
|
||||
|
|
@ -38,8 +38,12 @@ let
|
|||
};
|
||||
|
||||
# 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)));
|
||||
windowrules = filter (s: s != "") (builtins.concatLists (map (app: app.windowrule or [ "" ]) (attrValues apps)));
|
||||
binds = filter (s: s != "") (
|
||||
builtins.concatLists (map (app: app.bind or [ "" ]) (attrValues apps))
|
||||
);
|
||||
windowrules = filter (s: s != "") (
|
||||
builtins.concatLists (map (app: app.windowrule or [ "" ]) (attrValues apps))
|
||||
);
|
||||
|
||||
inherit (lib)
|
||||
attrValues
|
||||
|
|
@ -52,10 +56,8 @@ let
|
|||
in
|
||||
{
|
||||
imports = [
|
||||
./bitwarden
|
||||
./bemenu
|
||||
./dmenu-bluetooth
|
||||
./dunst-toggle
|
||||
./element-desktop
|
||||
./feh
|
||||
./kitty
|
||||
|
|
@ -133,11 +135,6 @@ in
|
|||
bind = [ "$mod SHIFT, m, exec, ${terminal} -T ${musicplayer} -e ${musicplayer}" ];
|
||||
};
|
||||
|
||||
notifications = mkAppAttrs {
|
||||
default = "dunst-toggle";
|
||||
bind = [ "$mod, Backspace, exec, ${notifications}" ];
|
||||
};
|
||||
|
||||
networksettings = mkAppAttrs {
|
||||
default = "networkmanager_dmenu";
|
||||
bind = [ "$mod SHIFT, n, exec, ${networksettings}" ];
|
||||
|
|
|
|||
|
|
@ -1,18 +0,0 @@
|
|||
{
|
||||
config,
|
||||
lib,
|
||||
pkgs,
|
||||
...
|
||||
}:
|
||||
|
||||
let
|
||||
cfg = config.wayland.windowManager.hyprland;
|
||||
app = cfg.applications.notifications.default;
|
||||
|
||||
inherit (lib) mkIf;
|
||||
in
|
||||
{
|
||||
config = mkIf (cfg.enable && app == "dunst-toggle") {
|
||||
home.packages = [ (import ./dunst-toggle.nix { inherit config pkgs; }) ];
|
||||
};
|
||||
}
|
||||
|
|
@ -1,11 +0,0 @@
|
|||
{ config, pkgs, ... }:
|
||||
|
||||
let
|
||||
dunst = "${pkgs.dunst}/bin/dunstctl";
|
||||
pkill = "${pkgs.procps}/bin/pkill";
|
||||
signal = "${toString config.programs.waybar.settings.mainBar."custom/notifications".signal}";
|
||||
in
|
||||
pkgs.writeShellScriptBin "dunst-toggle" ''
|
||||
${dunst} set-paused toggle
|
||||
${pkill} -RTMIN+${signal} waybar
|
||||
''
|
||||
|
|
@ -9,7 +9,7 @@ let
|
|||
cfg = config.wayland.windowManager.hyprland;
|
||||
app = cfg.applications.rssreader.default;
|
||||
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;
|
||||
in
|
||||
|
|
@ -27,11 +27,9 @@ in
|
|||
timers.newsboat-reload = {
|
||||
Unit.Description = "Reload newsboat every ${reloadTime} minutes";
|
||||
|
||||
Timer = {
|
||||
OnBootSec = "10sec";
|
||||
OnUnitActiveSec = "${reloadTime}min";
|
||||
Unit = "newsboat-reload.service";
|
||||
};
|
||||
Timer.OnBootSec = "10sec";
|
||||
Timer.OnUnitActiveSec = "${reloadTime}min";
|
||||
Timer.Unit = "newsboat-reload.service";
|
||||
|
||||
Install.WantedBy = [ "timers.target" ];
|
||||
};
|
||||
|
|
|
|||
|
|
@ -5,6 +5,6 @@ let
|
|||
notify = "${pkgs.libnotify}/bin/notify-send";
|
||||
signal = "${toString config.programs.waybar.settings.mainBar."custom/newsboat".signal}";
|
||||
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
|
||||
''
|
||||
'')
|
||||
|
|
|
|||
|
|
@ -14,7 +14,9 @@ in
|
|||
{
|
||||
config = mkIf (cfg.enable && app == "presentation-mode-bemenu") {
|
||||
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
|
||||
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_LEFT="Extend to left of main"
|
||||
MIRROR="Mirror main"
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@
|
|||
let
|
||||
screenshotDir = "${config.xdg.userDirs.pictures}/screenshots";
|
||||
in
|
||||
pkgs.writeShellScriptBin "screenshot" ''
|
||||
(pkgs.writeShellScriptBin "screenshot" ''
|
||||
mkdir -p ${screenshotDir}
|
||||
${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 = {
|
||||
settings = {
|
||||
bind = binds;
|
||||
bindm = import ./mouse.nix;
|
||||
bindm = (import ./mouse.nix);
|
||||
};
|
||||
};
|
||||
};
|
||||
|
|
|
|||
|
|
@ -9,20 +9,18 @@ let
|
|||
inherit (lib) mkForce;
|
||||
in
|
||||
{
|
||||
home = {
|
||||
pointerCursor = {
|
||||
home.pointerCursor = {
|
||||
name = mkForce "Bibata-Original-Ice";
|
||||
size = mkForce 24;
|
||||
package = mkForce pkgs.bibata-cursors;
|
||||
};
|
||||
|
||||
packages = [ pkgs.hyprcursor ];
|
||||
home.packages = [ pkgs.hyprcursor ];
|
||||
|
||||
sessionVariables = {
|
||||
home.sessionVariables = {
|
||||
HYPRCURSOR_THEME = config.home.pointerCursor.name;
|
||||
HYPRCURSOR_SIZE = toString config.home.pointerCursor.size;
|
||||
};
|
||||
};
|
||||
|
||||
# wayland.windowManager.hyprland.cursor.no_hardware_cursors = true;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -78,6 +78,12 @@ in
|
|||
# auto discover fonts in `home.packages`
|
||||
fonts.fontconfig.enable = true;
|
||||
|
||||
# notifications
|
||||
services.dunst = {
|
||||
enable = mkDefault true;
|
||||
waylandDisplay = config.home.sessionVariables.WAYLAND_DISPLAY;
|
||||
};
|
||||
|
||||
# install some applications
|
||||
home.packages = import ./packages.nix { inherit pkgs; }; # use programs.PACKAGE or services.SERVICE when possible
|
||||
|
||||
|
|
@ -88,19 +94,11 @@ in
|
|||
fi
|
||||
'';
|
||||
|
||||
# notifications
|
||||
services = {
|
||||
dunst = {
|
||||
enable = mkDefault true;
|
||||
waylandDisplay = config.home.sessionVariables.WAYLAND_DISPLAY;
|
||||
};
|
||||
|
||||
udiskie = {
|
||||
services.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
|
||||
cfg = config.wayland.windowManager.hyprland;
|
||||
|
||||
nonCenterFloatingClasses = [
|
||||
"Gimp"
|
||||
"steam"
|
||||
"KiCad"
|
||||
];
|
||||
|
||||
nonCenterFloatingClassesRegex = concatStringsSep "|" nonCenterFloatingClasses;
|
||||
|
||||
inherit (builtins) concatStringsSep toString;
|
||||
inherit (builtins) toString;
|
||||
inherit (lib) mkDefault;
|
||||
in
|
||||
{
|
||||
# Do not add binds here. Use `./binds/default.nix` instead.
|
||||
"$mod" = cfg.modifier;
|
||||
|
||||
exec-once = [
|
||||
"dbus-update-activation-environment --systemd WAYLAND_DISPLAY XDG_CURRENT_DESKTOP" # dbus package comes from NixOS module option `services.dbus.dbusPackage` [1]
|
||||
"gnome-keyring-daemon --start --components=secrets" # gnome-keyring package comes from NixOS module `services.gnome.gnome-keyring` [1]
|
||||
];
|
||||
# 1: see Hyprland NixOS module
|
||||
|
||||
windowrule = [
|
||||
# "float, class:^(${nonCenterFloatingClassesRegex})$"
|
||||
"center, floating:1, class:^(?!.*(${nonCenterFloatingClassesRegex})).*$"
|
||||
"center, floating:1, not class:^(Gimp)$, not class:^(steam)$"
|
||||
"float, title:^(Open|Save) Files?$"
|
||||
"noborder, onworkspace:w[t1]"
|
||||
"bordersize ${toString cfg.settings.general.border_size}, floating:1"
|
||||
|
|
@ -39,12 +24,6 @@ in
|
|||
"noblur, class:^(xwaylandvideobridge)$"
|
||||
];
|
||||
|
||||
gesture = [
|
||||
"3, horizontal, workspace"
|
||||
"3, up, dispatcher, exec, bemenu-run" # TODO: move to hyprland.applications
|
||||
"4, swipe, move"
|
||||
];
|
||||
|
||||
# Layouts
|
||||
general.layout = mkDefault "master";
|
||||
master = {
|
||||
|
|
|
|||
|
|
@ -20,10 +20,8 @@ in
|
|||
enable = mkDefault true;
|
||||
createDirectories = mkDefault true;
|
||||
};
|
||||
portal = {
|
||||
enable = mkDefault true;
|
||||
extraPortals = [ portal ];
|
||||
configPackages = [ portal ];
|
||||
};
|
||||
portal.enable = mkDefault true;
|
||||
portal.extraPortals = [ portal ];
|
||||
portal.configPackages = [ portal ];
|
||||
};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -19,13 +19,13 @@ let
|
|||
in
|
||||
{
|
||||
urls = [ { template = engine.url; } ];
|
||||
inherit (engine) icon;
|
||||
icon = engine.icon;
|
||||
updateInterval = if (isUrl engine.icon) then every_day else null;
|
||||
definedAliases = optional (engine ? alias) engine.alias;
|
||||
};
|
||||
|
||||
transformedEngines = mapAttrs' (name: engine: {
|
||||
inherit name;
|
||||
name = name;
|
||||
value = transformEngine engine;
|
||||
}) engines;
|
||||
|
||||
|
|
@ -79,7 +79,7 @@ in
|
|||
profiles.default.search.engines = mapAttrs (_: name: transformedEngines.${name}) (
|
||||
listToAttrs (
|
||||
map (name: {
|
||||
inherit name;
|
||||
name = name;
|
||||
value = name;
|
||||
}) cfg.searchEngines
|
||||
)
|
||||
|
|
|
|||
|
|
@ -1,71 +1,79 @@
|
|||
[
|
||||
# cursor navigation
|
||||
{
|
||||
options.desc = "scroll down, recenter";
|
||||
# scroll down, recenter
|
||||
key = "<C-d>";
|
||||
action = "<C-d>zz";
|
||||
mode = "n";
|
||||
}
|
||||
{
|
||||
options.desc = "scroll up, recenter";
|
||||
# scroll up, recenter
|
||||
key = "<C-u>";
|
||||
action = "<C-u>zz";
|
||||
mode = "n";
|
||||
}
|
||||
|
||||
# searching
|
||||
{
|
||||
options.desc = "center cursor after search next";
|
||||
# center cursor after search next
|
||||
key = "n";
|
||||
action = "nzzzv";
|
||||
mode = "n";
|
||||
}
|
||||
{
|
||||
options.desc = "center cursor after search previous";
|
||||
# center cursor after search previous
|
||||
key = "N";
|
||||
action = "Nzzzv";
|
||||
mode = "n";
|
||||
}
|
||||
{
|
||||
options.desc = "ex command";
|
||||
# ex command
|
||||
key = "<leader>pv";
|
||||
action = "<cmd>Ex<CR>";
|
||||
mode = "n";
|
||||
}
|
||||
|
||||
# search and replace
|
||||
{
|
||||
options.desc = "search and replace word under cursor";
|
||||
# search and replace word under cursor
|
||||
key = "<leader>s";
|
||||
action = ":%s/<C-r><C-w>/<C-r><C-w>/gI<Left><Left><Left>";
|
||||
mode = "n";
|
||||
}
|
||||
# search and replace selected text
|
||||
{
|
||||
key = "<leader>s";
|
||||
action = "y:%s/<C-r>0/<C-r>0/gI<Left><Left><Left>";
|
||||
mode = "v";
|
||||
}
|
||||
|
||||
# clipboard operations
|
||||
{
|
||||
options.desc = "copy to system clipboard in visual mode";
|
||||
# copy to system clipboard in visual mode
|
||||
key = "<C-c>";
|
||||
action = ''"+y '';
|
||||
mode = "v";
|
||||
}
|
||||
{
|
||||
options.desc = "paste from system clipboard in visual mode";
|
||||
# paste from system clipboard in visual mode
|
||||
key = "<C-v>";
|
||||
action = ''"+p '';
|
||||
mode = "v";
|
||||
}
|
||||
{
|
||||
options.desc = "yank to system clipboard";
|
||||
# yank to system clipboard
|
||||
key = "<leader>Y";
|
||||
action = "+Y";
|
||||
mode = "n";
|
||||
}
|
||||
{
|
||||
options.desc = "replace selected text with clipboard content";
|
||||
# replace selected text with clipboard content
|
||||
key = "<leader>p";
|
||||
action = "_dP";
|
||||
mode = "x";
|
||||
}
|
||||
{
|
||||
options.desc = "delete without copying to clipboard";
|
||||
# delete without copying to clipboard
|
||||
key = "<leader>d";
|
||||
action = "_d";
|
||||
mode = [
|
||||
|
|
@ -73,184 +81,267 @@
|
|||
"v"
|
||||
];
|
||||
}
|
||||
|
||||
# line operations
|
||||
{
|
||||
options.desc = "move lines down in visual mode";
|
||||
# move lines down in visual mode
|
||||
key = "J";
|
||||
action = ":m '>+1<CR>gv=gv";
|
||||
mode = "v";
|
||||
}
|
||||
{
|
||||
options.desc = "move lines up in visual mode";
|
||||
# move lines up in visual mode
|
||||
key = "K";
|
||||
action = ":m '<-2<CR>gv=gv";
|
||||
mode = "v";
|
||||
}
|
||||
{
|
||||
options.desc = "join lines";
|
||||
# join lines
|
||||
key = "J";
|
||||
action = "mzJ`z";
|
||||
mode = "n";
|
||||
}
|
||||
|
||||
# quickfix
|
||||
{
|
||||
options.desc = "Run make command";
|
||||
# Run make command
|
||||
key = "<leader>m";
|
||||
action = "<cmd>:make<CR>";
|
||||
mode = "n";
|
||||
}
|
||||
{
|
||||
options.desc = "previous quickfix item";
|
||||
# previous quickfix item
|
||||
key = "<C-A-J>";
|
||||
action = "<cmd>cprev<CR>zz";
|
||||
mode = "n";
|
||||
}
|
||||
{
|
||||
options.desc = "next quickfix item";
|
||||
# next quickfix item
|
||||
key = "<C-A-K>";
|
||||
action = "<cmd>cnext<CR>zz";
|
||||
mode = "n";
|
||||
}
|
||||
|
||||
# location list navigation
|
||||
{
|
||||
options.desc = "previous location list item";
|
||||
# previous location list item
|
||||
key = "<leader>j";
|
||||
action = "<cmd>lprev<CR>zz";
|
||||
mode = "n";
|
||||
}
|
||||
{
|
||||
options.desc = "next location list item";
|
||||
# next location list item
|
||||
key = "<leader>k";
|
||||
action = "<cmd>lnext<CR>zz";
|
||||
mode = "n";
|
||||
}
|
||||
|
||||
# disabling keys
|
||||
{
|
||||
options.desc = "disable the 'Q' key";
|
||||
# disable the 'Q' key
|
||||
key = "Q";
|
||||
action = "<nop>";
|
||||
mode = "n";
|
||||
}
|
||||
|
||||
# text selection
|
||||
{
|
||||
options.desc = "select whole buffer";
|
||||
# select whole buffer
|
||||
key = "<C-a>";
|
||||
action = "ggVG";
|
||||
mode = "n";
|
||||
}
|
||||
|
||||
# window operations
|
||||
{
|
||||
options.desc = "focus next window";
|
||||
# focus next window
|
||||
key = "<C-j>";
|
||||
action = ":wincmd W<CR>";
|
||||
options = {
|
||||
noremap = true;
|
||||
silent = true;
|
||||
};
|
||||
mode = "n";
|
||||
}
|
||||
{
|
||||
options.desc = "focus next window";
|
||||
key = "<Tab>";
|
||||
action = ":wincmd W<CR>";
|
||||
mode = "n";
|
||||
}
|
||||
{
|
||||
options.desc = "focus previous window";
|
||||
# focus previous window
|
||||
key = "<C-k>";
|
||||
action = ":wincmd w<CR>";
|
||||
options = {
|
||||
noremap = true;
|
||||
silent = true;
|
||||
};
|
||||
mode = "n";
|
||||
}
|
||||
|
||||
# window size adjustments
|
||||
{
|
||||
options.desc = "focus previous window";
|
||||
key = "<S-Tab>";
|
||||
action = ":wincmd w<CR>";
|
||||
mode = "n";
|
||||
}
|
||||
{
|
||||
options.desc = "increase window width";
|
||||
# increase window width
|
||||
key = "<C-l>";
|
||||
action = ":vertical resize +5<CR>";
|
||||
options = {
|
||||
noremap = true;
|
||||
silent = true;
|
||||
};
|
||||
mode = "n";
|
||||
}
|
||||
{
|
||||
options.desc = "decrease window width";
|
||||
# decrease window width
|
||||
key = "<C-h>";
|
||||
action = ":vertical resize -5<CR>";
|
||||
options = {
|
||||
noremap = true;
|
||||
silent = true;
|
||||
};
|
||||
mode = "n";
|
||||
}
|
||||
|
||||
# window closing and opening
|
||||
{
|
||||
options.desc = "close current window";
|
||||
# close current window
|
||||
key = "<leader-S>c";
|
||||
action = ":q<CR>";
|
||||
options = {
|
||||
noremap = true;
|
||||
silent = true;
|
||||
};
|
||||
mode = "n";
|
||||
}
|
||||
{
|
||||
options.desc = "new vertical split at $HOME";
|
||||
# new vertical split at $HOME
|
||||
key = "<leader>n";
|
||||
action = ":vsp $HOME<CR>";
|
||||
options = {
|
||||
noremap = true;
|
||||
silent = true;
|
||||
};
|
||||
mode = "n";
|
||||
}
|
||||
|
||||
# window split orientation toggling
|
||||
{
|
||||
options.desc = "toggle split orientation";
|
||||
# toggle split orientation
|
||||
key = "<leader>t";
|
||||
action = ":wincmd T<CR>";
|
||||
options = {
|
||||
noremap = true;
|
||||
silent = true;
|
||||
};
|
||||
mode = "n";
|
||||
}
|
||||
|
||||
# spell checking
|
||||
{
|
||||
options.desc = "toggle spell checking";
|
||||
# toggle spell checking
|
||||
key = "<leader>ss";
|
||||
action = ":setlocal spell!<CR>";
|
||||
options = {
|
||||
noremap = true;
|
||||
silent = true;
|
||||
};
|
||||
mode = "n";
|
||||
}
|
||||
{
|
||||
options.desc = "switch to english spell checking";
|
||||
# switch to english spell checking
|
||||
key = "<leader>se";
|
||||
action = ":setlocal spelllang=en_us<CR>";
|
||||
options = {
|
||||
noremap = true;
|
||||
silent = true;
|
||||
};
|
||||
mode = "n";
|
||||
}
|
||||
{
|
||||
options.desc = "switch to german spell checking";
|
||||
# switch to german spell checking
|
||||
key = "<leader>sg";
|
||||
action = ":setlocal spelllang=de_20<CR>";
|
||||
options = {
|
||||
noremap = true;
|
||||
silent = true;
|
||||
};
|
||||
mode = "n";
|
||||
}
|
||||
{
|
||||
options.desc = "move to next misspelling";
|
||||
# move to next misspelling
|
||||
key = "]s";
|
||||
action = "]szz";
|
||||
options = {
|
||||
noremap = true;
|
||||
silent = true;
|
||||
};
|
||||
mode = "n";
|
||||
}
|
||||
{
|
||||
options.desc = "move to previous misspelling";
|
||||
# move to previous misspelling
|
||||
key = "[s";
|
||||
action = "[szz";
|
||||
options = {
|
||||
noremap = true;
|
||||
silent = true;
|
||||
};
|
||||
mode = "n";
|
||||
}
|
||||
{
|
||||
options.desc = "correction suggestions for a misspelled word";
|
||||
# correction suggestions for a misspelled word
|
||||
key = "z=";
|
||||
action = "z=";
|
||||
options = {
|
||||
noremap = true;
|
||||
silent = true;
|
||||
};
|
||||
mode = "n";
|
||||
}
|
||||
{
|
||||
options.desc = "adding words to the dictionary";
|
||||
# adding words to the dictionary
|
||||
key = "zg";
|
||||
action = "zg";
|
||||
options = {
|
||||
noremap = true;
|
||||
silent = true;
|
||||
};
|
||||
mode = "n";
|
||||
}
|
||||
|
||||
# buffer navigation
|
||||
{
|
||||
options.desc = "next buffer";
|
||||
# next buffer
|
||||
key = "<C-S-J>";
|
||||
action = ":bnext<CR>";
|
||||
options = {
|
||||
noremap = true;
|
||||
silent = true;
|
||||
};
|
||||
mode = "n";
|
||||
}
|
||||
{
|
||||
options.desc = "previous buffer";
|
||||
# previous buffer
|
||||
key = "<C-S-K>";
|
||||
action = ":bprevious<CR>";
|
||||
options = {
|
||||
noremap = true;
|
||||
silent = true;
|
||||
};
|
||||
mode = "n";
|
||||
}
|
||||
{
|
||||
options.desc = "close current buffer";
|
||||
# close current buffer
|
||||
key = "<leader>bd";
|
||||
action = ":bdelete<CR>";
|
||||
options = {
|
||||
noremap = true;
|
||||
silent = true;
|
||||
};
|
||||
mode = "n";
|
||||
}
|
||||
|
||||
{
|
||||
options.desc = "apply code action";
|
||||
# apply code action
|
||||
key = "<leader>ca";
|
||||
action = ":lua vim.lsp.buf.code_action()<CR>";
|
||||
options = {
|
||||
noremap = true;
|
||||
silent = true;
|
||||
};
|
||||
mode = "n";
|
||||
}
|
||||
]
|
||||
|
|
|
|||
|
|
@ -3,17 +3,14 @@
|
|||
{
|
||||
imports = [
|
||||
./cmp.nix
|
||||
./diffview.nix
|
||||
./lsp.nix
|
||||
./gitsigns.nix
|
||||
./lualine.nix
|
||||
./telescope.nix
|
||||
./treesitter.nix
|
||||
# ./treesitter.nix # HOTFIX: does not build
|
||||
./trouble.nix
|
||||
];
|
||||
|
||||
config.programs.nixvim.plugins = {
|
||||
which-key.enable = lib.mkDefault true;
|
||||
markdown-preview.enable = lib.mkDefault true;
|
||||
# warning: Nixvim: `plugins.web-devicons` was enabled automatically because the following plugins are enabled. This behaviour is deprecated. Please explicitly define `plugins.web-devicons.enable`
|
||||
web-devicons.enable = true;
|
||||
|
|
|
|||
|
|
@ -1,59 +0,0 @@
|
|||
{ config, lib, ... }:
|
||||
|
||||
let
|
||||
cfg = config.programs.nixvim;
|
||||
plugin = cfg.plugins.diffview;
|
||||
|
||||
inherit (lib) mkDefault mkIf;
|
||||
in
|
||||
{
|
||||
config = {
|
||||
programs.nixvim = {
|
||||
plugins.diffview = {
|
||||
enable = mkDefault true;
|
||||
};
|
||||
|
||||
# highlight = mkIf plugin.enable {
|
||||
# DiffAdd = {
|
||||
# bg = "#2d4a2d";
|
||||
# fg = "NONE";
|
||||
# };
|
||||
# DiffDelete = {
|
||||
# bg = "#4a2d2d";
|
||||
# fg = "NONE";
|
||||
# };
|
||||
# DiffChange = {
|
||||
# bg = "#2d3a4a";
|
||||
# fg = "NONE";
|
||||
# };
|
||||
# DiffText = {
|
||||
# bg = "#1a5a1a";
|
||||
# fg = "NONE";
|
||||
# };
|
||||
# };
|
||||
|
||||
keymaps = mkIf plugin.enable [
|
||||
{
|
||||
mode = "n";
|
||||
key = "<leader>gd";
|
||||
action.__raw = ''
|
||||
function()
|
||||
local lib = require("diffview.lib")
|
||||
local view = lib.get_current_view()
|
||||
if view then
|
||||
vim.cmd("DiffviewClose")
|
||||
else
|
||||
vim.cmd("DiffviewOpen")
|
||||
end
|
||||
end
|
||||
'';
|
||||
options = {
|
||||
noremap = true;
|
||||
silent = true;
|
||||
desc = "toggle git diff";
|
||||
};
|
||||
}
|
||||
];
|
||||
};
|
||||
};
|
||||
}
|
||||
|
|
@ -1,104 +0,0 @@
|
|||
{ config, lib, ... }:
|
||||
|
||||
let
|
||||
cfg = config.programs.nixvim;
|
||||
plugin = cfg.plugins.gitsigns;
|
||||
|
||||
inherit (lib) mkDefault mkIf;
|
||||
in
|
||||
{
|
||||
config = {
|
||||
programs.nixvim = {
|
||||
plugins.gitsigns = {
|
||||
enable = mkDefault true;
|
||||
settings = {
|
||||
current_line_blame = mkDefault false;
|
||||
current_line_blame_opts = {
|
||||
virt_text = mkDefault true;
|
||||
virt_text_pos = mkDefault "eol";
|
||||
};
|
||||
signcolumn = mkDefault true;
|
||||
signs = {
|
||||
add.text = mkDefault "+";
|
||||
change.text = mkDefault "│";
|
||||
changedelete.text = mkDefault "~";
|
||||
delete.text = mkDefault "-";
|
||||
topdelete.text = mkDefault "-";
|
||||
untracked.text = mkDefault "?";
|
||||
};
|
||||
watch_gitdir.follow_files = mkDefault true;
|
||||
};
|
||||
};
|
||||
keymaps = mkIf plugin.enable [
|
||||
{
|
||||
mode = "n";
|
||||
key = "<leader>hs";
|
||||
action.__raw = "function() require('gitsigns').stage_hunk() end";
|
||||
options = {
|
||||
noremap = true;
|
||||
silent = true;
|
||||
desc = "stage hunk";
|
||||
};
|
||||
}
|
||||
{
|
||||
mode = "v";
|
||||
key = "<leader>hs";
|
||||
action.__raw = ''
|
||||
function()
|
||||
require('gitsigns').stage_hunk({vim.fn.line('.'), vim.fn.line('v')})
|
||||
end
|
||||
'';
|
||||
options = {
|
||||
noremap = true;
|
||||
silent = true;
|
||||
desc = "stage selected hunks";
|
||||
};
|
||||
}
|
||||
{
|
||||
mode = "n";
|
||||
key = "<leader>hu";
|
||||
action.__raw = "function() require('gitsigns').undo_stage_hunk() end";
|
||||
options = {
|
||||
noremap = true;
|
||||
silent = true;
|
||||
desc = "undo stage hunk";
|
||||
};
|
||||
}
|
||||
{
|
||||
mode = "n";
|
||||
key = "<leader>hS";
|
||||
action.__raw = "function() require('gitsigns').stage_buffer() end";
|
||||
options = {
|
||||
noremap = true;
|
||||
silent = true;
|
||||
desc = "stage buffer";
|
||||
};
|
||||
}
|
||||
{
|
||||
mode = "n";
|
||||
key = "<leader>hr";
|
||||
action.__raw = "function() require('gitsigns').reset_hunk() end";
|
||||
options = {
|
||||
noremap = true;
|
||||
silent = true;
|
||||
desc = "reset hunk";
|
||||
};
|
||||
}
|
||||
{
|
||||
mode = "v";
|
||||
key = "<leader>hr";
|
||||
action.__raw = ''
|
||||
function()
|
||||
require('gitsigns').reset_hunk({vim.fn.line('.'), vim.fn.line('v')})
|
||||
end
|
||||
'';
|
||||
options = {
|
||||
noremap = true;
|
||||
silent = true;
|
||||
desc = "reset selected hunks";
|
||||
};
|
||||
}
|
||||
];
|
||||
};
|
||||
};
|
||||
}
|
||||
|
|
@ -16,31 +16,6 @@ in
|
|||
programs.nixvim = {
|
||||
plugins.telescope = {
|
||||
enable = mkDefault true;
|
||||
settings = {
|
||||
defaults = {
|
||||
vimgrep_arguments = [
|
||||
"rg"
|
||||
"--color=never"
|
||||
"--no-heading"
|
||||
"--with-filename"
|
||||
"--line-number"
|
||||
"--column"
|
||||
"--smart-case"
|
||||
"--hidden"
|
||||
];
|
||||
file_ignore_patterns = [
|
||||
"^.git/"
|
||||
"^.direnv/"
|
||||
"^.cache/"
|
||||
"^node_modules/"
|
||||
];
|
||||
};
|
||||
pickers = {
|
||||
find_files = {
|
||||
hidden = true;
|
||||
};
|
||||
};
|
||||
};
|
||||
extensions = {
|
||||
file-browser.enable = mkDefault true;
|
||||
fzf-native.enable = mkDefault true;
|
||||
|
|
|
|||
|
|
@ -16,8 +16,7 @@ in
|
|||
{
|
||||
config = {
|
||||
programs.nixvim = {
|
||||
plugins = {
|
||||
treesitter = {
|
||||
plugins.treesitter = {
|
||||
enable = mkDefault true;
|
||||
nixvimInjections = mkDefault true;
|
||||
settings = {
|
||||
|
|
@ -26,9 +25,8 @@ in
|
|||
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.
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
let
|
||||
spellDir = config.xdg.dataHome + "/nvim/site/spell";
|
||||
baseUrl = "https://vim.ftp.fu-berlin.de/runtime/spell";
|
||||
baseUrl = "http://ftp.de.vim.org/runtime/spell";
|
||||
in
|
||||
{
|
||||
home.file = {
|
||||
|
|
@ -12,7 +12,7 @@ in
|
|||
url = baseUrl + "/de.utf-8.spl";
|
||||
sha256 = "sha256-c8cQfqM5hWzb6SHeuSpFk5xN5uucByYdobndGfaDo9E=";
|
||||
};
|
||||
target = spellDir + "/de.utf-8.spl";
|
||||
target = spellDir + "/de.utf8.spl";
|
||||
};
|
||||
de-sug = {
|
||||
enable = true;
|
||||
|
|
@ -20,7 +20,7 @@ in
|
|||
url = baseUrl + "/de.utf-8.sug";
|
||||
sha256 = "sha256-E9Ds+Shj2J72DNSopesqWhOg6Pm6jRxqvkerqFcUqUg=";
|
||||
};
|
||||
target = spellDir + "/de.utf-8.sug";
|
||||
target = spellDir + "/de.utf8.sug";
|
||||
};
|
||||
};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@
|
|||
let
|
||||
cfg = config.programs.passwordManager;
|
||||
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)
|
||||
mkDefault
|
||||
|
|
|
|||
|
|
@ -17,7 +17,6 @@ let
|
|||
"moonfly"
|
||||
"nord"
|
||||
"oxocarbon"
|
||||
"generate-from-image"
|
||||
];
|
||||
# schemes names in `pkgs.base16-schemes` that need a suffix
|
||||
needsSuffix = [
|
||||
|
|
@ -29,7 +28,13 @@ let
|
|||
"moonfly"
|
||||
"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)
|
||||
mkDefault
|
||||
|
|
@ -51,8 +56,6 @@ in
|
|||
description = ''
|
||||
Base16 color scheme name. Available options are:
|
||||
${toString validSchemes}
|
||||
|
||||
"generate-from-image" generates a color scheme from `stylix.image`
|
||||
'';
|
||||
};
|
||||
};
|
||||
|
|
@ -67,12 +70,7 @@ in
|
|||
|
||||
stylix = {
|
||||
autoEnable = mkDefault true;
|
||||
base16Scheme = mkIf (cfg.scheme != "generate-from-image") (
|
||||
if builtins.elem cfg.scheme customSchemes then
|
||||
./schemes/${schemeName}.yaml
|
||||
else
|
||||
"${pkgs.base16-schemes}/share/themes/${schemeName}.yaml"
|
||||
);
|
||||
base16Scheme = scheme;
|
||||
fonts = {
|
||||
monospace = mkDefault {
|
||||
package = pkgs.hack-font;
|
||||
|
|
|
|||
|
|
@ -1,4 +1,3 @@
|
|||
---
|
||||
system: "base16"
|
||||
name: "Moonfly"
|
||||
description: "A dark theme inspired by the Moonfly color scheme."
|
||||
|
|
|
|||
|
|
@ -1,4 +1,3 @@
|
|||
---
|
||||
system: "base16"
|
||||
name: "Oxocarbon"
|
||||
description: "A dark theme inspired by the Oxocarbon Dark color scheme."
|
||||
|
|
|
|||
|
|
@ -4,13 +4,11 @@ let
|
|||
cfg = config.stylix;
|
||||
target = cfg.targets.nixvim;
|
||||
|
||||
inherit (lib) mkIf optionalAttrs;
|
||||
inherit (lib) mkIf;
|
||||
in
|
||||
{
|
||||
config = mkIf cfg.enable {
|
||||
stylix.targets.nixvim.enable = false;
|
||||
programs.nixvim.colorschemes = optionalAttrs (cfg.scheme != "generate-from-image") {
|
||||
"${cfg.scheme}".enable = !target.enable;
|
||||
};
|
||||
programs.nixvim.colorschemes."${cfg.scheme}".enable = !target.enable;
|
||||
};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -71,11 +71,11 @@ in
|
|||
|
||||
#workspaces {
|
||||
color: ${colors.base05};
|
||||
background: ${colors.base00};
|
||||
}
|
||||
|
||||
#workspaces button {
|
||||
padding: ${halfgaps}px;
|
||||
color: ${colors.base05};
|
||||
}
|
||||
|
||||
#workspaces button.active {
|
||||
|
|
|
|||
|
|
@ -56,7 +56,6 @@ let
|
|||
};
|
||||
|
||||
# Add your custom modules here
|
||||
"custom/notifications" = import ./modules/notifications.nix { inherit lib pkgs; };
|
||||
"custom/newsboat" = import ./modules/newsboat.nix { inherit lib pkgs; };
|
||||
"pulseaudio#input" = import ./modules/pulseaudio/input.nix { inherit lib pkgs; };
|
||||
"pulseaudio#output" = import ./modules/pulseaudio/output.nix { inherit lib pkgs; };
|
||||
|
|
@ -96,13 +95,11 @@ in
|
|||
"disk"
|
||||
"pulseaudio#input"
|
||||
"pulseaudio#output"
|
||||
"custom/notifications"
|
||||
"tray"
|
||||
];
|
||||
|
||||
inherit
|
||||
"custom/newsboat"
|
||||
"custom/notifications"
|
||||
"hyprland/language"
|
||||
"hyprland/workspaces"
|
||||
"pulseaudio#input"
|
||||
|
|
@ -132,7 +129,5 @@ in
|
|||
};
|
||||
};
|
||||
};
|
||||
|
||||
services.batsignal.enable = builtins.elem "battery" cfg.settings.mainBar.modules-right;
|
||||
};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -10,13 +10,13 @@ let
|
|||
let
|
||||
newsboat = "${pkgs.newsboat}/bin/newsboat";
|
||||
in
|
||||
pkgs.writeShellScriptBin "newsboat-print-unread" ''
|
||||
(pkgs.writeShellScriptBin "newsboat-print-unread" ''
|
||||
UNREAD=$(${newsboat} -x print-unread | awk '{print $1}')
|
||||
|
||||
if [[ $UNREAD -gt 0 ]]; then
|
||||
printf " %i" "$UNREAD"
|
||||
fi
|
||||
'';
|
||||
'');
|
||||
|
||||
inherit (lib) mkDefault;
|
||||
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
|
||||
SIGNAL=11 # signal number to send to status bar
|
||||
STATUS_BAR="waybar" # Support for more status bars?
|
||||
|
|
@ -17,7 +16,7 @@ start_timer() {
|
|||
notify-send "Timer Started" "Your countdown timer has been started."
|
||||
|
||||
trap "exit" INT TERM
|
||||
trap 'rm -f -- "$TIMER_FILE"' EXIT
|
||||
trap "rm -f -- '$TIMER_FILE'" EXIT
|
||||
|
||||
while [ $total_seconds -gt 0 ]; do
|
||||
hours=$(( total_seconds / 3600 ))
|
||||
|
|
@ -63,7 +62,7 @@ if [ "$1" = "start" ]; then
|
|||
MINUTES=${MINUTES:-0}
|
||||
SECONDS=${SECONDS:-0}
|
||||
|
||||
start_timer "$HOURS" "$MINUTES" "$SECONDS"
|
||||
start_timer $HOURS $MINUTES $SECONDS
|
||||
|
||||
elif [ "$1" = "stop" ]; then
|
||||
notify-send "Timer Stopped" "Your countdown timer has been stopped."
|
||||
|
|
|
|||
|
|
@ -6,19 +6,19 @@
|
|||
environment.systemPackages = with pkgs; [
|
||||
lact
|
||||
nvtopPackages.amd
|
||||
rocmPackages.clr.icd
|
||||
rocmPackages.hipcc
|
||||
rocmPackages.miopen
|
||||
rocmPackages.rocm-runtime
|
||||
rocmPackages.rocm-smi
|
||||
rocmPackages.rocminfo
|
||||
|
||||
];
|
||||
|
||||
# environment.variables.ROC_ENABLE_PRE_VEGA = "1"; # for Polaris
|
||||
|
||||
hardware.amdgpu.opencl.enable = true;
|
||||
|
||||
hardware.graphics.extraPackages = with pkgs; [ rocmPackages.clr.icd ];
|
||||
|
||||
systemd.packages = with pkgs; [ lact ];
|
||||
systemd.services.lactd.wantedBy = [ "multi-user.target" ];
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,16 +4,10 @@ let
|
|||
inherit (lib) mkDefault;
|
||||
in
|
||||
{
|
||||
hardware = {
|
||||
bluetooth = {
|
||||
enable = mkDefault true;
|
||||
powerOnBoot = mkDefault false;
|
||||
settings.General = {
|
||||
Enable = mkDefault "Source,Sink,Media,Socket";
|
||||
Experimental = mkDefault true;
|
||||
};
|
||||
};
|
||||
};
|
||||
hardware.bluetooth.enable = mkDefault true;
|
||||
hardware.bluetooth.powerOnBoot = mkDefault false;
|
||||
hardware.bluetooth.settings.General.Enable = mkDefault "Source,Sink,Media,Socket";
|
||||
hardware.bluetooth.settings.General.Experimental = mkDefault true;
|
||||
|
||||
environment.systemPackages = with pkgs; [
|
||||
blueman
|
||||
|
|
|
|||
|
|
@ -84,6 +84,8 @@ in
|
|||
) { } cfg.remotes;
|
||||
|
||||
# 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 = [
|
||||
./boot.nix
|
||||
./environment.nix
|
||||
./htop.nix
|
||||
./nationalization.nix
|
||||
|
|
|
|||
|
|
@ -9,8 +9,7 @@ let
|
|||
inherit (lib) mkDefault optionals;
|
||||
in
|
||||
{
|
||||
environment = {
|
||||
systemPackages =
|
||||
environment.systemPackages =
|
||||
with pkgs;
|
||||
[
|
||||
cryptsetup
|
||||
|
|
@ -48,7 +47,7 @@ in
|
|||
pkgs.kitty.terminfo
|
||||
];
|
||||
|
||||
shellAliases = {
|
||||
environment.shellAliases = {
|
||||
l = "ls -lh";
|
||||
ll = "ls -lAh";
|
||||
ports = "ss -tulpn";
|
||||
|
|
@ -57,11 +56,8 @@ in
|
|||
};
|
||||
|
||||
# saves one instance of nixpkgs.
|
||||
ldso32 = null;
|
||||
};
|
||||
environment.ldso32 = null;
|
||||
|
||||
boot = {
|
||||
tmp.cleanOnBoot = mkDefault true;
|
||||
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
|
||||
programs.ssh.knownHosts = {
|
||||
"github.com".hostNames = [ "github.com" ];
|
||||
"github.com".publicKey = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIOMqqnkVzrm0SdG6UOoqKLsabgH5C9okWi0dh2l9GKJl";
|
||||
"github.com".publicKey =
|
||||
"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIOMqqnkVzrm0SdG6UOoqKLsabgH5C9okWi0dh2l9GKJl";
|
||||
|
||||
"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".publicKey = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIMZvRd4EtM7R+IHVMWmDkVU3VLQTSwQDSAvW0t2Tkj60";
|
||||
"git.sr.ht".publicKey =
|
||||
"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIMZvRd4EtM7R+IHVMWmDkVU3VLQTSwQDSAvW0t2Tkj60";
|
||||
};
|
||||
# TODO: add synix
|
||||
}
|
||||
|
|
|
|||
|
|
@ -42,8 +42,12 @@ in
|
|||
static-auth-secret-file = mkIf cfg.sops config.sops.secrets."coturn/static-auth-secret".path;
|
||||
realm = mkDefault "turn.${config.networking.domain}";
|
||||
|
||||
cert = 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";
|
||||
cert =
|
||||
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 = ''
|
||||
# ban private IP ranges
|
||||
|
|
|
|||
|
|
@ -14,7 +14,6 @@
|
|||
i2pd = import ./i2pd;
|
||||
jellyfin = import ./jellyfin;
|
||||
jirafeau = import ./jirafeau;
|
||||
librechat-oci = import ./librechat-oci;
|
||||
mailserver = import ./mailserver;
|
||||
matrix-synapse = import ./matrix-synapse;
|
||||
maubot = import ./maubot;
|
||||
|
|
@ -22,7 +21,6 @@
|
|||
miniflux = import ./miniflux;
|
||||
nginx = import ./nginx;
|
||||
normalUsers = import ./normalUsers;
|
||||
nostr-relay = import ./nostr-relay;
|
||||
nvidia = import ./nvidia;
|
||||
ollama = import ./ollama;
|
||||
open-webui-oci = import ./open-webui-oci;
|
||||
|
|
@ -35,4 +33,5 @@
|
|||
virtualisation = import ./virtualisation;
|
||||
webPage = import ./webPage;
|
||||
windows-oci = import ./windows-oci;
|
||||
zfs = import ./zfs;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -33,13 +33,11 @@ in
|
|||
|
||||
fonts.fontconfig.enable = mkDefault false;
|
||||
|
||||
xdg = {
|
||||
autostart.enable = mkDefault false;
|
||||
icons.enable = mkDefault false;
|
||||
menus.enable = mkDefault false;
|
||||
mime.enable = mkDefault false;
|
||||
sounds.enable = mkDefault false;
|
||||
};
|
||||
xdg.autostart.enable = mkDefault false;
|
||||
xdg.icons.enable = mkDefault false;
|
||||
xdg.menus.enable = mkDefault false;
|
||||
xdg.mime.enable = mkDefault false;
|
||||
xdg.sounds.enable = mkDefault false;
|
||||
|
||||
programs.git.package = mkDefault pkgs.gitMinimal;
|
||||
|
||||
|
|
@ -50,25 +48,22 @@ in
|
|||
viAlias = mkDefault true;
|
||||
};
|
||||
|
||||
systemd = {
|
||||
# emergency mode is useless on headless machines
|
||||
enableEmergencyMode = false;
|
||||
systemd.enableEmergencyMode = false;
|
||||
boot.initrd.systemd.suppressedUnits = mkIf config.systemd.enableEmergencyMode [
|
||||
"emergency.service"
|
||||
"emergency.target"
|
||||
];
|
||||
|
||||
sleep.extraConfig = ''
|
||||
systemd.sleep.extraConfig = ''
|
||||
AllowSuspend=no
|
||||
AllowHibernation=no
|
||||
'';
|
||||
|
||||
# force reboots
|
||||
settings.Manager = {
|
||||
systemd.settings.Manager = {
|
||||
RuntimeWatchdogSec = mkDefault "15s";
|
||||
RebootWatchdogSec = mkDefault "30s";
|
||||
KExecWatchdogSec = mkDefault "1m";
|
||||
};
|
||||
};
|
||||
|
||||
boot.initrd.systemd.suppressedUnits = mkIf config.systemd.enableEmergencyMode [
|
||||
"emergency.service"
|
||||
"emergency.target"
|
||||
];
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,9 +4,7 @@ let
|
|||
inherit (lib) mkDefault;
|
||||
in
|
||||
{
|
||||
services = {
|
||||
qemuGuest.enable = mkDefault true;
|
||||
spice-vdagentd.enable = mkDefault true;
|
||||
spice-webdavd.enable = mkDefault true;
|
||||
};
|
||||
services.qemuGuest.enable = mkDefault true;
|
||||
services.spice-vdagentd.enable = mkDefault true;
|
||||
services.spice-webdavd.enable = mkDefault true;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,9 +2,9 @@
|
|||
|
||||
let
|
||||
cfg = config.services.ftp-webserver;
|
||||
inherit (config.networking) domain;
|
||||
domain = config.networking.domain;
|
||||
fqdn = if (cfg.subdomain != "") then "${cfg.subdomain}.${domain}" else domain;
|
||||
inherit (config.services) nginx;
|
||||
nginx = config.services.nginx;
|
||||
|
||||
inherit (lib)
|
||||
mkEnableOption
|
||||
|
|
@ -35,7 +35,7 @@ in
|
|||
|
||||
config = mkIf cfg.enable {
|
||||
services.nginx.virtualHosts."${fqdn}" = {
|
||||
inherit (cfg) root;
|
||||
root = cfg.root;
|
||||
locations."/" = {
|
||||
extraConfig = ''
|
||||
autoindex on;
|
||||
|
|
@ -43,7 +43,7 @@ in
|
|||
autoindex_localtime on;
|
||||
'';
|
||||
};
|
||||
inherit (cfg) forceSSL;
|
||||
forceSSL = cfg.forceSSL;
|
||||
enableACME = cfg.forceSSL;
|
||||
sslCertificate = mkIf cfg.forceSSL "${config.security.acme.certs."${fqdn}".directory}/cert.pem";
|
||||
sslCertificateKey = mkIf cfg.forceSSL "${config.security.acme.certs."${fqdn}".directory}/key.pem";
|
||||
|
|
|
|||
|
|
@ -7,10 +7,10 @@
|
|||
|
||||
let
|
||||
cfg = config.services.headplane;
|
||||
inherit (config.networking) domain;
|
||||
inherit (cfg.reverseProxy) subdomain;
|
||||
domain = config.networking.domain;
|
||||
subdomain = cfg.reverseProxy.subdomain;
|
||||
fqdn = if (cfg.reverseProxy.enable && subdomain != "") then "${subdomain}.${domain}" else domain;
|
||||
inherit (config.services) headscale;
|
||||
headscale = config.services.headscale;
|
||||
|
||||
inherit (lib)
|
||||
mkDefault
|
||||
|
|
@ -45,17 +45,17 @@ in
|
|||
url = "http://127.0.0.1:${toString headscale.port}";
|
||||
public_url = headscale.settings.server_url;
|
||||
config_path = "/etc/headscale/config.yaml";
|
||||
api_key_path = config.sops.secrets."headplane/api_key".path;
|
||||
};
|
||||
integration.agent = {
|
||||
enabled = mkDefault true;
|
||||
pre_authkey_path = config.sops.secrets."headplane/agent_pre_authkey".path;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
services.nginx.virtualHosts = mkIf cfg.reverseProxy.enable {
|
||||
"${fqdn}" = mkVirtualHost {
|
||||
inherit (cfg.settings.server) port;
|
||||
port = cfg.settings.server.port;
|
||||
ssl = cfg.reverseProxy.forceSSL;
|
||||
};
|
||||
};
|
||||
|
|
@ -63,14 +63,14 @@ in
|
|||
sops.secrets =
|
||||
let
|
||||
owner = headscale.user;
|
||||
inherit (headscale) group;
|
||||
group = headscale.group;
|
||||
mode = "0400";
|
||||
in
|
||||
{
|
||||
"headplane/cookie_secret" = {
|
||||
inherit owner group mode;
|
||||
};
|
||||
"headplane/api_key" = {
|
||||
"headplane/agent_pre_authkey" = {
|
||||
inherit owner group mode;
|
||||
};
|
||||
};
|
||||
|
|
|
|||
|
|
@ -6,8 +6,8 @@
|
|||
|
||||
let
|
||||
cfg = config.services.headscale;
|
||||
inherit (config.networking) domain;
|
||||
inherit (cfg.reverseProxy) subdomain;
|
||||
domain = config.networking.domain;
|
||||
subdomain = cfg.reverseProxy.subdomain;
|
||||
fqdn = if (cfg.reverseProxy.enable && subdomain != "") then "${subdomain}.${domain}" else domain;
|
||||
acl = "headscale/acl.hujson";
|
||||
|
||||
|
|
|
|||
|
|
@ -8,9 +8,20 @@ in
|
|||
|
||||
programs.dconf.enable = true; # fixes nixvim hm module
|
||||
|
||||
services = {
|
||||
flatpak.enable = true;
|
||||
gnome.gnome-keyring.enable = true;
|
||||
udisks2.enable = mkDefault true;
|
||||
xdg.portal = {
|
||||
enable = true;
|
||||
extraPortals = with pkgs; [
|
||||
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
|
||||
cfg = config.services.jellyfin;
|
||||
inherit (config.networking) domain;
|
||||
inherit (cfg.reverseProxy) subdomain;
|
||||
domain = config.networking.domain;
|
||||
subdomain = cfg.reverseProxy.subdomain;
|
||||
fqdn = if (cfg.reverseProxy.enable && subdomain != "") then "${subdomain}.${domain}" else domain;
|
||||
|
||||
inherit (lib)
|
||||
|
|
@ -48,7 +48,9 @@ in
|
|||
];
|
||||
|
||||
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}/libraries 0770 ${cfg.user} ${cfg.group} -"
|
||||
|
|
|
|||
|
|
@ -2,8 +2,8 @@
|
|||
|
||||
let
|
||||
cfg = config.services.jirafeau;
|
||||
inherit (config.networking) domain;
|
||||
inherit (cfg.reverseProxy) subdomain;
|
||||
domain = config.networking.domain;
|
||||
subdomain = cfg.reverseProxy.subdomain;
|
||||
fqdn = if (cfg.reverseProxy.enable && subdomain != "") then "${subdomain}.${domain}" else domain;
|
||||
|
||||
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
|
||||
cfg = config.mailserver;
|
||||
inherit (config.networking) domain;
|
||||
domain = config.networking.domain;
|
||||
fqdn = "${cfg.subdomain}.${domain}";
|
||||
|
||||
inherit (lib)
|
||||
|
|
@ -74,7 +74,7 @@ in
|
|||
nameValuePair "${user}@${domain}" {
|
||||
name = "${user}@${domain}";
|
||||
aliases = map (alias: "${alias}@${domain}") (accConf.aliases or [ ]);
|
||||
inherit (accConf) sendOnly;
|
||||
sendOnly = accConf.sendOnly;
|
||||
quota = mkDefault "5G";
|
||||
hashedPasswordFile = config.sops.secrets."mailserver/accounts/${user}".path;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -23,7 +23,7 @@ let
|
|||
|
||||
services."mautrix-${name}" = {
|
||||
enable = true;
|
||||
inherit (cfg.bridges.${name}) package;
|
||||
package = cfg.bridges.${name}.package;
|
||||
environmentFile = mkIf cfg.sops config.sops.templates."mautrix-${name}/env-file".path;
|
||||
settings = {
|
||||
bridge = {
|
||||
|
|
@ -71,29 +71,33 @@ let
|
|||
mode = "0400";
|
||||
in
|
||||
{
|
||||
secrets = {
|
||||
"mautrix-${name}/encryption-pickle-key" = {
|
||||
secrets."mautrix-${name}/encryption-pickle-key" = {
|
||||
inherit owner group mode;
|
||||
};
|
||||
"mautrix-${name}/provisioning-shared-secret" = {
|
||||
secrets."mautrix-${name}/provisioning-shared-secret" = {
|
||||
inherit owner group mode;
|
||||
};
|
||||
"mautrix-${name}/public-media-signing-key" = {
|
||||
secrets."mautrix-${name}/public-media-signing-key" = {
|
||||
inherit owner group mode;
|
||||
};
|
||||
"mautrix-${name}/direct-media-server-key" = {
|
||||
secrets."mautrix-${name}/direct-media-server-key" = {
|
||||
inherit owner group mode;
|
||||
};
|
||||
};
|
||||
templates."mautrix-${name}/env-file" = {
|
||||
inherit owner group mode;
|
||||
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=${
|
||||
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}_DIRECT_MEDIA_SERVER_KEY=${config.sops.placeholder."mautrix-${name}/direct-media-server-key"}
|
||||
MAUTRIX_${toUpper name}_PUBLIC_MEDIA_SIGNING_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,8 +84,7 @@ in
|
|||
};
|
||||
|
||||
config = mkIf cfg.enable {
|
||||
services = {
|
||||
postgresql = {
|
||||
services.postgresql = {
|
||||
enable = true;
|
||||
initialScript = pkgs.writeText "synapse-init.sql" ''
|
||||
CREATE ROLE "matrix-synapse" WITH LOGIN PASSWORD 'synapse';
|
||||
|
|
@ -96,10 +95,12 @@ in
|
|||
'';
|
||||
};
|
||||
|
||||
matrix-synapse = mkMerge [
|
||||
services.matrix-synapse = mkMerge [
|
||||
{
|
||||
settings = {
|
||||
registration_shared_secret_path = mkIf cfg.sops config.sops.secrets."matrix/registration-shared-secret".path;
|
||||
registration_shared_secret_path =
|
||||
mkIf cfg.sops
|
||||
config.sops.secrets."matrix/registration-shared-secret".path;
|
||||
server_name = config.networking.domain;
|
||||
public_baseurl = baseUrl;
|
||||
listeners = [
|
||||
|
|
@ -141,17 +142,19 @@ in
|
|||
})
|
||||
];
|
||||
|
||||
nginx.virtualHosts."${cfg.settings.server_name}" = {
|
||||
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;
|
||||
"= /.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}";
|
||||
};
|
||||
};
|
||||
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 {
|
||||
|
|
|
|||
|
|
@ -6,14 +6,13 @@
|
|||
|
||||
let
|
||||
cfg = config.services.matrix-synapse;
|
||||
inherit (config.networking) domain;
|
||||
domain = config.networking.domain;
|
||||
|
||||
inherit (lib) mkIf mkDefault;
|
||||
in
|
||||
{
|
||||
config = mkIf cfg.enable {
|
||||
services = {
|
||||
livekit = {
|
||||
services.livekit = {
|
||||
enable = true;
|
||||
settings.port = mkDefault 7880;
|
||||
settings.room.auto_create = mkDefault false;
|
||||
|
|
@ -21,14 +20,16 @@ in
|
|||
keyFile = mkIf cfg.sops config.sops.templates."livekit/key".path;
|
||||
};
|
||||
|
||||
lk-jwt-service = {
|
||||
services.lk-jwt-service = {
|
||||
enable = true;
|
||||
port = mkDefault 8080;
|
||||
livekitUrl = "wss://${domain}/livekit/sfu";
|
||||
keyFile = mkIf cfg.sops config.sops.templates."livekit/key".path;
|
||||
};
|
||||
|
||||
nginx.virtualHosts = {
|
||||
systemd.services.lk-jwt-service.environment.LIVEKIT_FULL_ACCESS_HOMESERVERS = domain;
|
||||
|
||||
services.nginx.virtualHosts = {
|
||||
"${domain}".locations = {
|
||||
"^~ /livekit/jwt/" = {
|
||||
priority = 400;
|
||||
|
|
@ -49,9 +50,6 @@ in
|
|||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
systemd.services.lk-jwt-service.environment.LIVEKIT_FULL_ACCESS_HOMESERVERS = domain;
|
||||
|
||||
sops = mkIf cfg.sops {
|
||||
secrets."livekit/key" = { };
|
||||
|
|
|
|||
|
|
@ -76,7 +76,7 @@ in
|
|||
sops = mkIf cfg.sops (
|
||||
let
|
||||
owner = user.name;
|
||||
inherit (user) group;
|
||||
group = user.group;
|
||||
mode = "0400";
|
||||
in
|
||||
{
|
||||
|
|
@ -98,7 +98,9 @@ in
|
|||
''
|
||||
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;
|
||||
};
|
||||
|
||||
port = mkOption {
|
||||
type = types.port;
|
||||
default = 8000;
|
||||
description = "Port on which the mcpo service should listen.";
|
||||
};
|
||||
|
||||
user = mkOption {
|
||||
type = types.str;
|
||||
description = "The user the mcpo service will run as.";
|
||||
|
|
@ -96,7 +90,7 @@ in
|
|||
|
||||
users.users."${cfg.user}" = {
|
||||
isSystemUser = true;
|
||||
inherit (cfg) group;
|
||||
group = cfg.group;
|
||||
};
|
||||
|
||||
users.groups."${cfg.group}" = { };
|
||||
|
|
@ -106,7 +100,7 @@ in
|
|||
after = [ "network.target" ];
|
||||
wantedBy = [ "multi-user.target" ];
|
||||
serviceConfig = {
|
||||
ExecStart = "${getExe cfg.package} --port ${toString cfg.port} --config ${configFile}";
|
||||
ExecStart = "${getExe cfg.package} --config ${configFile}";
|
||||
Restart = "on-failure";
|
||||
User = cfg.user;
|
||||
Group = cfg.group;
|
||||
|
|
|
|||
|
|
@ -6,8 +6,8 @@
|
|||
|
||||
let
|
||||
cfg = config.services.miniflux;
|
||||
inherit (config.networking) domain;
|
||||
inherit (cfg.reverseProxy) subdomain;
|
||||
domain = config.networking.domain;
|
||||
subdomain = cfg.reverseProxy.subdomain;
|
||||
fqdn = if (cfg.reverseProxy.enable && subdomain != "") then "${subdomain}.${domain}" else domain;
|
||||
port = 8085;
|
||||
|
||||
|
|
|
|||
|
|
@ -50,7 +50,8 @@ in
|
|||
"1.1.1.1"
|
||||
"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
|
||||
map escapeIPv6 resolvers;
|
||||
|
||||
|
|
@ -59,7 +60,7 @@ in
|
|||
virtualHosts = {
|
||||
"${config.networking.domain}" = mkDefault {
|
||||
enableACME = cfg.forceSSL;
|
||||
inherit (cfg) forceSSL;
|
||||
forceSSL = cfg.forceSSL;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
|
|
|||
|
|
@ -21,7 +21,7 @@ in
|
|||
types.submodule {
|
||||
options = {
|
||||
extraGroups = mkOption {
|
||||
type = types.listOf types.str;
|
||||
type = (types.listOf types.str);
|
||||
default = [ ];
|
||||
description = "Extra groups for the user";
|
||||
example = [ "wheel" ];
|
||||
|
|
@ -37,7 +37,7 @@ in
|
|||
description = "Initial password for the user";
|
||||
};
|
||||
sshKeyFiles = mkOption {
|
||||
type = types.listOf types.path;
|
||||
type = (types.listOf types.path);
|
||||
default = [ ];
|
||||
description = "SSH key files for the user";
|
||||
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;
|
||||
in
|
||||
{
|
||||
boot = {
|
||||
blacklistedKernelModules = [ "nouveau" ];
|
||||
extraModulePackages = [ config.hardware.nvidia.package ];
|
||||
initrd.kernelModules = [ "nvidia" ];
|
||||
};
|
||||
boot.blacklistedKernelModules = [ "nouveau" ];
|
||||
boot.extraModulePackages = [ config.hardware.nvidia.package ];
|
||||
boot.initrd.kernelModules = [ "nvidia" ];
|
||||
|
||||
environment.systemPackages = with pkgs; [
|
||||
nvtopPackages.nvidia
|
||||
];
|
||||
|
||||
hardware = {
|
||||
enableRedistributableFirmware = true;
|
||||
graphics.enable = true;
|
||||
nvidia = {
|
||||
modesetting.enable = true;
|
||||
nvidiaSettings = true;
|
||||
open = false;
|
||||
package = mkDefault config.boot.kernelPackages.nvidiaPackages.latest;
|
||||
};
|
||||
};
|
||||
hardware.enableRedistributableFirmware = true;
|
||||
hardware.graphics.enable = true;
|
||||
hardware.nvidia.modesetting.enable = true;
|
||||
hardware.nvidia.nvidiaSettings = true;
|
||||
hardware.nvidia.open = false;
|
||||
hardware.nvidia.package = mkDefault config.boot.kernelPackages.nvidiaPackages.latest;
|
||||
|
||||
nixpkgs.config.cudaSupport = true;
|
||||
|
||||
|
|
|
|||
|
|
@ -2,8 +2,8 @@
|
|||
|
||||
let
|
||||
cfg = config.services.ollama;
|
||||
inherit (config.networking) domain;
|
||||
inherit (cfg.reverseProxy) subdomain;
|
||||
domain = config.networking.domain;
|
||||
subdomain = cfg.reverseProxy.subdomain;
|
||||
fqdn = if (cfg.reverseProxy.enable && subdomain != "") then "${subdomain}.${domain}" else domain;
|
||||
|
||||
inherit (lib)
|
||||
|
|
@ -31,7 +31,7 @@ in
|
|||
|
||||
services.nginx.virtualHosts = mkIf cfg.reverseProxy.enable {
|
||||
"${fqdn}" = mkVirtualHost {
|
||||
inherit (cfg) port;
|
||||
port = cfg.port;
|
||||
ssl = cfg.reverseProxy.forceSSL;
|
||||
recommendedProxySettings = mkForce false;
|
||||
extraConfig = ''
|
||||
|
|
|
|||
|
|
@ -10,10 +10,10 @@ let
|
|||
|
||||
image = pkgs.dockerTools.pullImage {
|
||||
imageName = "ghcr.io/open-webui/open-webui";
|
||||
imageDigest = "sha256:a7e4796ae894d1e2a0c1824860ade472f35c507608a01c3581377b5c19b0ed49";
|
||||
hash = "sha256-uhPlVXSxY6rGbYGvlPVV3zurmbI96mAHEuKKy9FFaD4=";
|
||||
imageDigest = "sha256:2deb90b0423473d8f97febced2e62b8fd898aa3eb61877bb3aa336370214c258";
|
||||
hash = "sha256-2cdKfvZGUyPUm7TFXcf5OcG9ey4BvOZPUOVim1S2C+s=";
|
||||
finalImageName = "ghcr.io/open-webui/open-webui";
|
||||
finalImageTag = "0.9.2";
|
||||
finalImageTag = "0.8.5";
|
||||
};
|
||||
|
||||
defaultEnv = {
|
||||
|
|
@ -83,17 +83,23 @@ in
|
|||
};
|
||||
|
||||
config = mkIf cfg.enable {
|
||||
virtualisation = {
|
||||
podman = {
|
||||
virtualisation.podman = {
|
||||
enable = true;
|
||||
autoPrune.enable = true;
|
||||
dockerCompat = true;
|
||||
};
|
||||
|
||||
oci-containers = {
|
||||
backend = "podman";
|
||||
networking.firewall.interfaces =
|
||||
let
|
||||
matchAll = if !config.networking.nftables.enable then "podman+" else "podman*";
|
||||
in
|
||||
{
|
||||
"${matchAll}".allowedUDPPorts = [ 53 ];
|
||||
};
|
||||
|
||||
containers."open-webui" = {
|
||||
virtualisation.oci-containers.backend = "podman";
|
||||
|
||||
virtualisation.oci-containers.containers."open-webui" = {
|
||||
image = with cfg.image; imageName + ":" + imageTag;
|
||||
imageFile = cfg.image;
|
||||
environment =
|
||||
|
|
@ -119,19 +125,7 @@ in
|
|||
"--network=host"
|
||||
];
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
networking.firewall.interfaces =
|
||||
let
|
||||
matchAll = if !config.networking.nftables.enable then "podman+" else "podman*";
|
||||
in
|
||||
{
|
||||
"${matchAll}".allowedUDPPorts = [ 53 ];
|
||||
};
|
||||
|
||||
systemd = {
|
||||
services."podman-open-webui" = {
|
||||
systemd.services."podman-open-webui" = {
|
||||
serviceConfig = {
|
||||
Restart = mkOverride 90 "always";
|
||||
};
|
||||
|
|
@ -149,7 +143,7 @@ in
|
|||
];
|
||||
};
|
||||
|
||||
services."podman-volume-open-webui_open-webui" = {
|
||||
systemd.services."podman-volume-open-webui_open-webui" = {
|
||||
path = [ pkgs.podman ];
|
||||
serviceConfig = {
|
||||
Type = "oneshot";
|
||||
|
|
@ -162,12 +156,11 @@ in
|
|||
wantedBy = [ "podman-compose-open-webui-root.target" ];
|
||||
};
|
||||
|
||||
targets."podman-compose-open-webui-root" = {
|
||||
systemd.targets."podman-compose-open-webui-root" = {
|
||||
unitConfig = {
|
||||
Description = "Root target generated by compose2nix.";
|
||||
};
|
||||
wantedBy = [ "multi-user.target" ];
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -7,8 +7,8 @@
|
|||
|
||||
let
|
||||
cfg = config.services.print-server;
|
||||
inherit (config.networking) domain;
|
||||
inherit (cfg.reverseProxy) subdomain;
|
||||
domain = config.networking.domain;
|
||||
subdomain = cfg.reverseProxy.subdomain;
|
||||
fqdn = if (cfg.reverseProxy.enable && subdomain != "") then "${subdomain}.${domain}" else domain;
|
||||
port = 631;
|
||||
|
||||
|
|
@ -36,8 +36,7 @@ in
|
|||
};
|
||||
|
||||
config = mkIf cfg.enable {
|
||||
services = {
|
||||
printing = {
|
||||
services.printing = {
|
||||
enable = true;
|
||||
listenAddresses = [ "*:${builtins.toString port}" ];
|
||||
webInterface = true;
|
||||
|
|
@ -47,7 +46,7 @@ in
|
|||
Address @LOCAL
|
||||
'';
|
||||
clientConf = "";
|
||||
inherit (cfg) openFirewall;
|
||||
openFirewall = cfg.openFirewall;
|
||||
drivers = with pkgs; [
|
||||
brlaser
|
||||
brgenml1lpr
|
||||
|
|
@ -68,18 +67,17 @@ in
|
|||
};
|
||||
|
||||
# autodiscovery of network printers
|
||||
avahi = {
|
||||
services.avahi = {
|
||||
enable = true;
|
||||
nssmdns4 = true;
|
||||
inherit (cfg) openFirewall;
|
||||
openFirewall = cfg.openFirewall;
|
||||
};
|
||||
|
||||
nginx.virtualHosts = mkIf cfg.reverseProxy.enable {
|
||||
services.nginx.virtualHosts = mkIf cfg.reverseProxy.enable {
|
||||
${fqdn} = mkVirtualHost {
|
||||
inherit port;
|
||||
ssl = cfg.reverseProxy.forceSSL;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -7,8 +7,8 @@
|
|||
|
||||
let
|
||||
cfg = config.services.radicale;
|
||||
inherit (config.networking) domain;
|
||||
inherit (cfg.reverseProxy) subdomain;
|
||||
domain = config.networking.domain;
|
||||
subdomain = cfg.reverseProxy.subdomain;
|
||||
fqdn = if (cfg.reverseProxy.enable && subdomain != "") then "${subdomain}.${domain}" else domain;
|
||||
port = 5232;
|
||||
|
||||
|
|
@ -63,7 +63,7 @@ in
|
|||
|
||||
services.nginx.virtualHosts = mkIf cfg.reverseProxy.enable {
|
||||
"${fqdn}" = {
|
||||
inherit (cfg.reverseProxy) forceSSL;
|
||||
forceSSL = cfg.reverseProxy.forceSSL;
|
||||
enableACME = cfg.reverseProxy.forceSSL;
|
||||
locations = {
|
||||
"/" = {
|
||||
|
|
|
|||
|
|
@ -2,8 +2,8 @@
|
|||
|
||||
let
|
||||
cfg = config.services.rss-bridge;
|
||||
inherit (config.networking) domain;
|
||||
inherit (cfg.reverseProxy) subdomain;
|
||||
domain = config.networking.domain;
|
||||
subdomain = cfg.reverseProxy.subdomain;
|
||||
fqdn = if (cfg.reverseProxy.enable && subdomain != "") then "${subdomain}.${domain}" else domain;
|
||||
|
||||
inherit (lib)
|
||||
|
|
@ -12,6 +12,7 @@ let
|
|||
|
||||
inherit (lib.utils)
|
||||
mkReverseProxyOption
|
||||
mkVirtualHost
|
||||
;
|
||||
in
|
||||
{
|
||||
|
|
@ -31,9 +32,8 @@ in
|
|||
systemd.tmpfiles.rules = [ "d ${cfg.dataDir} 0755 ${cfg.user} ${cfg.group} -" ];
|
||||
|
||||
services.nginx.virtualHosts = mkIf cfg.reverseProxy.enable {
|
||||
"${fqdn}" = {
|
||||
enableACME = cfg.reverseProxy.forceSSL;
|
||||
inherit (cfg.reverseProxy) forceSSL;
|
||||
"${cfg.virtualHost}" = mkVirtualHost {
|
||||
ssl = cfg.reverseProxy.forceSSL;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
|
|
|||
|
|
@ -1,17 +1,9 @@
|
|||
{
|
||||
config,
|
||||
lib,
|
||||
pkgs,
|
||||
...
|
||||
}:
|
||||
{ config, lib, ... }:
|
||||
|
||||
let
|
||||
cfg = config.services.tailscale;
|
||||
|
||||
inherit (lib)
|
||||
concatStrings
|
||||
filterAttrs
|
||||
mapAttrsToList
|
||||
mkIf
|
||||
mkOption
|
||||
optional
|
||||
|
|
@ -20,122 +12,39 @@ let
|
|||
in
|
||||
{
|
||||
options.services.tailscale = {
|
||||
tailnets = mkOption {
|
||||
default = { };
|
||||
type = types.attrsOf (
|
||||
types.submodule {
|
||||
options = {
|
||||
loginServer = mkOption {
|
||||
type = types.str;
|
||||
description = "Login server for this tailnet.";
|
||||
};
|
||||
authKeyFile = mkOption {
|
||||
type = types.nullOr types.str;
|
||||
default = null;
|
||||
description = "Path to auth key secret.";
|
||||
description = "The Tailscale login server to use.";
|
||||
};
|
||||
enableSSH = mkOption {
|
||||
type = types.bool;
|
||||
default = false;
|
||||
description = "Enable Tailscale SSH functionality.";
|
||||
};
|
||||
acceptDNS = mkOption {
|
||||
type = types.bool;
|
||||
default = true;
|
||||
};
|
||||
default = mkOption {
|
||||
type = types.bool;
|
||||
default = false;
|
||||
description = "Connect to this tailnet on boot.";
|
||||
};
|
||||
};
|
||||
}
|
||||
);
|
||||
description = "Enable Tailscale's MagicDNS and custom DNS configuration.";
|
||||
};
|
||||
};
|
||||
|
||||
config =
|
||||
let
|
||||
defaultTailnets = filterAttrs (_: t: t.default) cfg.tailnets;
|
||||
defaultTailnet = if defaultTailnets == { } then null else builtins.head (builtins.attrValues defaultTailnets);
|
||||
|
||||
entries = mapAttrsToList (name: tcfg: ''
|
||||
TAILNETS["${name}"]="${tcfg.loginServer}|${if tcfg.enableSSH then "true" else "false"}|${
|
||||
if tcfg.acceptDNS then "true" else "false"
|
||||
}|${if tcfg.authKeyFile != null then tcfg.authKeyFile else ""}"
|
||||
'') cfg.tailnets;
|
||||
|
||||
tailnetSwitchCli = pkgs.writeShellScriptBin "tailnet-switch" ''
|
||||
set -euo pipefail
|
||||
|
||||
TAILSCALE="${cfg.package}/bin/tailscale"
|
||||
|
||||
declare -A TAILNETS
|
||||
${concatStrings entries}
|
||||
|
||||
CHOICE="''${1:-}"
|
||||
|
||||
if [[ -z "$CHOICE" ]]; then
|
||||
if [[ -t 0 ]]; then
|
||||
CHOICE=$(printf '%s\n' "''${!TAILNETS[@]}" | sort | ${pkgs.fzf}/bin/fzf --prompt="Switch tailnet: ")
|
||||
else
|
||||
echo "Usage: tailnet-switch <tailnet-name>" >&2
|
||||
printf 'Available tailnets: %s\n' "''${!TAILNETS[@]}" >&2
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
|
||||
if [[ -z "''${TAILNETS[$CHOICE]+x}" ]]; then
|
||||
echo "Unknown tailnet: $CHOICE" >&2
|
||||
printf 'Available tailnets: %s\n' "''${!TAILNETS[@]}" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
IFS='|' read -r LOGIN_SERVER ENABLE_SSH ACCEPT_DNS AUTH_KEY_FILE <<< "''${TAILNETS[$CHOICE]}"
|
||||
|
||||
echo "Switching to: $CHOICE ($LOGIN_SERVER)"
|
||||
|
||||
"$TAILSCALE" down --accept-risk=lose-ssh 2>/dev/null || true
|
||||
"$TAILSCALE" logout 2>/dev/null || true
|
||||
|
||||
UP_FLAGS=("--login-server=$LOGIN_SERVER")
|
||||
[[ "$ENABLE_SSH" == "true" ]] && UP_FLAGS+=("--ssh")
|
||||
[[ "$ACCEPT_DNS" == "true" ]] && UP_FLAGS+=("--accept-dns")
|
||||
[[ -n "$AUTH_KEY_FILE" ]] && UP_FLAGS+=("--auth-key=$(cat "$AUTH_KEY_FILE")")
|
||||
|
||||
"$TAILSCALE" up "''${UP_FLAGS[@]}"
|
||||
|
||||
echo "Switched to tailnet: $CHOICE"
|
||||
'';
|
||||
in
|
||||
mkIf cfg.enable {
|
||||
assertions = [
|
||||
{
|
||||
assertion = (builtins.length (builtins.attrValues (filterAttrs (_: t: t.default) cfg.tailnets))) <= 1;
|
||||
message = "services.tailscale.tailnets: Only one tailnet can be set as default.";
|
||||
}
|
||||
{
|
||||
assertion = cfg.tailnets != { };
|
||||
message = "services.tailscale.tailnets: At least one tailnet must be defined.";
|
||||
}
|
||||
];
|
||||
|
||||
services.tailscale = mkIf (defaultTailnet != null) (
|
||||
with defaultTailnet;
|
||||
{
|
||||
inherit authKeyFile;
|
||||
extraSetFlags = optional enableSSH "--ssh" ++ optional acceptDNS "--accept-dns";
|
||||
config = mkIf cfg.enable {
|
||||
services.tailscale = {
|
||||
authKeyFile = config.sops.secrets."tailscale/auth-key".path;
|
||||
extraSetFlags = optional cfg.enableSSH "--ssh" ++ optional cfg.acceptDNS "--accept-dns";
|
||||
extraUpFlags = [
|
||||
"--login-server=${loginServer}"
|
||||
"--login-server=${cfg.loginServer}"
|
||||
]
|
||||
++ optional enableSSH "--ssh"
|
||||
++ optional acceptDNS "--accept-dns";
|
||||
}
|
||||
);
|
||||
++ optional cfg.enableSSH "--ssh"
|
||||
++ optional cfg.acceptDNS "--accept-dns";
|
||||
};
|
||||
|
||||
environment.systemPackages = [ tailnetSwitchCli ];
|
||||
|
||||
environment.shellAliases.ts = "${cfg.package}/bin/tailscale";
|
||||
environment.shellAliases = {
|
||||
ts = "${cfg.package}/bin/tailscale";
|
||||
};
|
||||
|
||||
networking.firewall.trustedInterfaces = [ cfg.interfaceName ];
|
||||
|
||||
sops.secrets."tailscale/auth-key" = { };
|
||||
};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -58,9 +58,8 @@ in
|
|||
enable = mkDefault true;
|
||||
onBoot = mkDefault "ignore";
|
||||
onShutdown = mkDefault "shutdown";
|
||||
qemu = {
|
||||
runAsRoot = mkDefault false;
|
||||
verbatimConfig = ''
|
||||
qemu.runAsRoot = mkDefault false;
|
||||
qemu.verbatimConfig = ''
|
||||
clear_emulation_capabilities = ${boolToZeroOne cfg.libvirtd.clearEmulationCapabilities}
|
||||
''
|
||||
+ optionalString (cfg.libvirtd.deviceACL != [ ]) ''
|
||||
|
|
@ -68,8 +67,7 @@ in
|
|||
${aclString}
|
||||
]
|
||||
'';
|
||||
swtpm.enable = mkDefault true; # TPM 2.0
|
||||
};
|
||||
qemu.swtpm.enable = mkDefault true; # TPM 2.0
|
||||
};
|
||||
spiceUSBRedirection.enable = mkDefault true;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -1,4 +1,3 @@
|
|||
#!/usr/bin/env bash
|
||||
shopt -s nullglob
|
||||
for d in /sys/kernel/iommu_groups/*/devices/*; do
|
||||
n=${d#*/iommu_groups/*}; n=${n%%/*}
|
||||
|
|
|
|||
|
|
@ -78,7 +78,8 @@ let
|
|||
};
|
||||
};
|
||||
|
||||
deviceType = types.submodule (
|
||||
deviceType = (
|
||||
types.submodule (
|
||||
{ config, options, ... }:
|
||||
{
|
||||
options = {
|
||||
|
|
@ -104,6 +105,7 @@ let
|
|||
size = mkIf (config.resolution != null) (sizeFromResolution config.resolution);
|
||||
};
|
||||
}
|
||||
)
|
||||
);
|
||||
|
||||
inherit (lib)
|
||||
|
|
@ -142,7 +144,7 @@ in
|
|||
'';
|
||||
|
||||
"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 {
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
let
|
||||
cfg = config.services.webPage;
|
||||
inherit (config.networking) domain;
|
||||
domain = config.networking.domain;
|
||||
fqdn = if (cfg.subdomain != "") then "${cfg.subdomain}.${domain}" else domain;
|
||||
nginxUser = config.services.nginx.user;
|
||||
|
||||
|
|
@ -41,7 +41,7 @@ in
|
|||
config = mkIf cfg.enable {
|
||||
services.nginx.virtualHosts."${fqdn}" = {
|
||||
enableACME = cfg.forceSSL;
|
||||
inherit (cfg) forceSSL;
|
||||
forceSSL = cfg.forceSSL;
|
||||
root = cfg.webRoot;
|
||||
locations."/".index = "index.html";
|
||||
sslCertificate = mkIf cfg.forceSSL "${config.security.acme.certs."${fqdn}".directory}/cert.pem";
|
||||
|
|
|
|||
|
|
@ -81,53 +81,9 @@ in
|
|||
};
|
||||
|
||||
config = mkIf cfg.enable {
|
||||
systemd = {
|
||||
tmpfiles.rules = [ "d ${cfg.volume} 0755 root podman -" ];
|
||||
systemd.tmpfiles.rules = [ "d ${cfg.volume} 0755 root podman -" ];
|
||||
|
||||
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"
|
||||
];
|
||||
};
|
||||
|
||||
"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 = {
|
||||
virtualisation.podman = {
|
||||
enable = true;
|
||||
autoPrune.enable = true;
|
||||
dockerCompat = true;
|
||||
|
|
@ -136,9 +92,12 @@ in
|
|||
};
|
||||
};
|
||||
|
||||
oci-containers = {
|
||||
backend = "podman";
|
||||
containers."windows" = {
|
||||
# https://github.com/NixOS/nixpkgs/issues/226365
|
||||
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;
|
||||
|
|
@ -147,6 +106,7 @@ in
|
|||
"DISK_SIZE" = diskSize;
|
||||
"USERNAME" = username;
|
||||
"PASSWORD" = password;
|
||||
"LANGUAGE" = language;
|
||||
"REGION" = region;
|
||||
"KEYBOARD" = keyboard;
|
||||
};
|
||||
|
|
@ -168,10 +128,43 @@ in
|
|||
"--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"
|
||||
];
|
||||
};
|
||||
|
||||
# https://github.com/NixOS/nixpkgs/issues/226365
|
||||
networking.firewall.interfaces."podman+".allowedUDPPorts = [ 53 ];
|
||||
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,11 +14,10 @@ let
|
|||
;
|
||||
in
|
||||
{
|
||||
nix = {
|
||||
package = mkDefault pkgs.nix;
|
||||
nix.package = mkDefault pkgs.nix;
|
||||
|
||||
# for `nix run synix#foo`, `nix build synix#bar`, etc
|
||||
registry = {
|
||||
nix.registry = {
|
||||
synix = {
|
||||
from = {
|
||||
id = "synix";
|
||||
|
|
@ -33,14 +32,11 @@ in
|
|||
};
|
||||
};
|
||||
|
||||
settings = {
|
||||
warn-dirty = mkDefault false;
|
||||
|
||||
# fallback quickly if substituters are not available.
|
||||
connect-timeout = mkDefault 5;
|
||||
fallback = true;
|
||||
nix.settings.connect-timeout = mkDefault 5;
|
||||
nix.settings.fallback = true;
|
||||
|
||||
experimental-features = [
|
||||
nix.settings.experimental-features = [
|
||||
"nix-command"
|
||||
"flakes"
|
||||
]
|
||||
|
|
@ -48,44 +44,42 @@ in
|
|||
config.nix.package != null && versionOlder (versions.majorMinor config.nix.package.version) "2.22"
|
||||
) "repl-flake";
|
||||
|
||||
log-lines = mkDefault 25;
|
||||
nix.settings.log-lines = mkDefault 25;
|
||||
|
||||
# avoid disk full issues
|
||||
max-free = mkDefault (3000 * 1024 * 1024);
|
||||
min-free = mkDefault (512 * 1024 * 1024);
|
||||
nix.settings.max-free = mkDefault (3000 * 1024 * 1024);
|
||||
nix.settings.min-free = mkDefault (512 * 1024 * 1024);
|
||||
|
||||
# avoid copying unnecessary stuff over SSH
|
||||
builders-use-substitutes = true;
|
||||
nix.settings.builders-use-substitutes = true;
|
||||
|
||||
# workaround for https://github.com/NixOS/nix/issues/9574
|
||||
nix-path = config.nix.nixPath;
|
||||
nix.settings.nix-path = config.nix.nixPath;
|
||||
|
||||
download-buffer-size = 524288000; # 500 MiB
|
||||
nix.settings.download-buffer-size = 524288000; # 500 MiB
|
||||
|
||||
# add all wheel users to the trusted-users group
|
||||
trusted-users = [
|
||||
nix.settings.trusted-users = [
|
||||
"@wheel"
|
||||
];
|
||||
|
||||
# binary caches
|
||||
substituters = [
|
||||
nix.settings.substituters = [
|
||||
"https://cache.nixos.org"
|
||||
"https://nix-community.cachix.org"
|
||||
"https://cache.garnix.io"
|
||||
"https://numtide.cachix.org"
|
||||
];
|
||||
trusted-public-keys = [
|
||||
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="
|
||||
];
|
||||
};
|
||||
|
||||
gc = {
|
||||
nix.gc = {
|
||||
automatic = true;
|
||||
dates = "weekly";
|
||||
options = "--delete-older-than 30d";
|
||||
};
|
||||
};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -9,17 +9,11 @@
|
|||
|
||||
modifications = final: prev: {
|
||||
# https://github.com/NixOS/nixpkgs/issues/335003#issuecomment-2755803376
|
||||
kicad = prev.kicad.override {
|
||||
kicad = (
|
||||
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
|
||||
rofi-rbw-wayland = prev.rofi-rbw-wayland.overrideAttrs (oldAttrs: {
|
||||
|
|
|
|||
|
|
@ -1,28 +1,25 @@
|
|||
{
|
||||
lib,
|
||||
python312,
|
||||
python3,
|
||||
fetchPypi,
|
||||
}:
|
||||
|
||||
let
|
||||
python = python312;
|
||||
in
|
||||
python.pkgs.buildPythonApplication rec {
|
||||
python3.pkgs.buildPythonApplication rec {
|
||||
pname = "arxiv-mcp-server";
|
||||
version = "0.5.0";
|
||||
version = "0.3.1";
|
||||
pyproject = true;
|
||||
|
||||
src = fetchPypi {
|
||||
pname = "arxiv_mcp_server";
|
||||
inherit version;
|
||||
hash = "sha256-vxrKyq+uOgVYtWrvikcIidLra6n0GFlFvfKztrc7GH8=";
|
||||
hash = "sha256-yGNetU7el6ZXsavD8uvO17OZtaPuYgzkxiVEk402GUs=";
|
||||
};
|
||||
|
||||
build-system = [
|
||||
python.pkgs.hatchling
|
||||
python3.pkgs.hatchling
|
||||
];
|
||||
|
||||
dependencies = with python.pkgs; [
|
||||
dependencies = with python3.pkgs; [
|
||||
aiofiles
|
||||
aiohttp
|
||||
anyio
|
||||
|
|
@ -39,7 +36,7 @@ python.pkgs.buildPythonApplication rec {
|
|||
uvicorn
|
||||
];
|
||||
|
||||
optional-dependencies = with python.pkgs; {
|
||||
optional-dependencies = with python3.pkgs; {
|
||||
test = [
|
||||
aioresponses
|
||||
pytest
|
||||
|
|
@ -51,7 +48,6 @@ python.pkgs.buildPythonApplication rec {
|
|||
|
||||
pythonRemoveDeps = [
|
||||
"black"
|
||||
"mcp"
|
||||
];
|
||||
|
||||
pythonImportsCheck = [
|
||||
|
|
|
|||
|
|
@ -11,19 +11,17 @@
|
|||
|
||||
rustPlatform.buildRustPackage rec {
|
||||
pname = "baibot";
|
||||
version = "1.19.3";
|
||||
version = "1.14.3";
|
||||
|
||||
src = fetchFromGitHub {
|
||||
owner = "etkecc";
|
||||
repo = "baibot";
|
||||
rev = "v${version}";
|
||||
hash = "sha256-Fr1CvFocb/VAYQGykXXZ6CCfvC31bKB/tr1aoA4oIME=";
|
||||
hash = "sha256-bFUijsvwUQhISjWVoVvoDXNSDPaWZTunqUfxfgaxclM=";
|
||||
};
|
||||
|
||||
cargoHash = "sha256-CNEkge585bzUUPMHCSJ1CAH5wx3Wttq9I3A3oqfBzis=";
|
||||
|
||||
cargoBuildFlags = "--ignore-rust-version";
|
||||
cargoTestFlags = "--ignore-rust-version";
|
||||
useFetchCargoVendor = true;
|
||||
cargoHash = "sha256-/7KSCVWuxTk7gKOYxE/uQ5T0BnYlDYWOvdFXEiU9mB0=";
|
||||
|
||||
nativeBuildInputs = [
|
||||
pkg-config
|
||||
|
|
|
|||
|
|
@ -6,13 +6,13 @@
|
|||
|
||||
python3.pkgs.buildPythonApplication rec {
|
||||
pname = "blender-mcp";
|
||||
version = "1.5.6";
|
||||
version = "1.5.5";
|
||||
pyproject = true;
|
||||
|
||||
src = fetchPypi {
|
||||
pname = "blender_mcp";
|
||||
inherit version;
|
||||
hash = "sha256-9aBGQcMC1ustj3H1WgRFCha6fk+XSASIzcZr6Rrgif4=";
|
||||
hash = "sha256-n8bYnrDVLe5zPvg8rbGgh5U5AeIm/DA6aPgmxS68d7g=";
|
||||
};
|
||||
|
||||
build-system = [
|
||||
|
|
|
|||
|
|
@ -11,20 +11,15 @@
|
|||
cppman = pkgs.callPackage ./cppman { };
|
||||
fetcher-mcp = pkgs.callPackage ./fetcher-mcp { };
|
||||
freecad-mcp = pkgs.callPackage ./freecad-mcp { };
|
||||
jirafeau = pkgs.callPackage ./jirafeau { };
|
||||
jirafeau-cli = pkgs.callPackage ./jirafeau-cli { };
|
||||
kicad-mcp = pkgs.callPackage ./kicad-mcp { };
|
||||
mcpo = pkgs.callPackage ./mcpo { };
|
||||
nerdlog = pkgs.callPackage ./nerdlog { };
|
||||
pass2bw = pkgs.callPackage ./pass2bw { };
|
||||
pyman = pkgs.callPackage ./pyman { };
|
||||
quicknote = pkgs.callPackage ./quicknote { };
|
||||
synapse_change_display_name = pkgs.callPackage ./synapse_change_display_name { };
|
||||
synix-docs = pkgs.callPackage ./synix-docs { };
|
||||
tinyfugue = pkgs.callPackage ./tinyfugue { };
|
||||
trelis-gitingest-mcp = pkgs.callPackage ./trelis-gitingest-mcp { };
|
||||
tunerstudio = pkgs.callPackage ./tunerstudio { };
|
||||
|
||||
# marker-pdf = pkgs.callPackage ./marker-pdf { }; # FIXME
|
||||
# openmv-ide = pkgs.callPackage ./openmv-ide { }; # FIXME
|
||||
}
|
||||
|
|
|
|||
|
|
@ -12,7 +12,9 @@
|
|||
let
|
||||
revision = "1161";
|
||||
|
||||
chromium-headless-shell = playwright-driver.passthru.components."chromium-headless-shell".overrideAttrs (old: {
|
||||
chromium-headless-shell =
|
||||
playwright-driver.passthru.components."chromium-headless-shell".overrideAttrs
|
||||
(old: {
|
||||
inherit revision;
|
||||
});
|
||||
|
||||
|
|
@ -23,9 +25,9 @@ let
|
|||
}
|
||||
];
|
||||
in
|
||||
buildNpmPackage {
|
||||
buildNpmPackage rec {
|
||||
pname = "fetcher-mcp";
|
||||
version = "0.3.9";
|
||||
version = "0.3.6";
|
||||
|
||||
src = fetchFromGitHub {
|
||||
owner = "jae-jae";
|
||||
|
|
@ -60,6 +62,7 @@ buildNpmPackage {
|
|||
description = "MCP server for fetch web page content using Playwright headless browser";
|
||||
homepage = "https://github.com/jae-jae/fetcher-mcp";
|
||||
license = lib.licenses.mit;
|
||||
maintainers = with lib.maintainers; [ ];
|
||||
mainProgram = "fetcher-mcp";
|
||||
platforms = lib.platforms.all;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -6,13 +6,13 @@
|
|||
|
||||
python3.pkgs.buildPythonApplication rec {
|
||||
pname = "freecad-mcp";
|
||||
version = "0.1.17";
|
||||
version = "0.1.16";
|
||||
pyproject = true;
|
||||
|
||||
src = fetchPypi {
|
||||
pname = "freecad_mcp";
|
||||
inherit version;
|
||||
hash = "sha256-DugQWGZizIXO27cjzfyidNTyyahN1BTcDNTl4DHWqN0=";
|
||||
hash = "sha256-eFt7UgJw56C2zY8Vznrg8L0a5nvP0xtiW1oJuJ/fL3Y=";
|
||||
};
|
||||
|
||||
build-system = [
|
||||
|
|
|
|||
|
|
@ -1,20 +0,0 @@
|
|||
{
|
||||
writeShellApplication,
|
||||
coreutils,
|
||||
curl,
|
||||
...
|
||||
}:
|
||||
|
||||
let
|
||||
name = "jirafeau-cli";
|
||||
text = builtins.readFile ./${name}.sh;
|
||||
in
|
||||
writeShellApplication {
|
||||
inherit name text;
|
||||
meta.mainProgram = name;
|
||||
|
||||
runtimeInputs = [
|
||||
coreutils
|
||||
curl
|
||||
];
|
||||
}
|
||||
|
|
@ -1,152 +0,0 @@
|
|||
#!/bin/bash
|
||||
|
||||
# This script has been auto-generated by Jirafeau but you can still edit options below.
|
||||
|
||||
# Config begin
|
||||
proxy='' # Or set JIRAFEAU_PROXY.
|
||||
url='' # Or set JIRAFEAU_URL.
|
||||
time='month' # Or set JIRAFEAU_TIME.
|
||||
one_time='' # Or set JIRAFEAU_ONE_TIME.
|
||||
upload_password='' # Or set JIRAFEAU_UPLOAD_PASSWD
|
||||
# Config end
|
||||
|
||||
if [ -n "${JIRAFEAU_PROXY:-}" ]; then
|
||||
proxy="$JIRAFEAU_PROXY"
|
||||
fi
|
||||
|
||||
if [ -n "${JIRAFEAU_URL:-}" ]; then
|
||||
url="$JIRAFEAU_URL"
|
||||
fi
|
||||
|
||||
if [ -z "$url" ]; then
|
||||
echo "Please set url in script parameters or export JIRAFEAU_URL"
|
||||
fi
|
||||
|
||||
if [ -n "${JIRAFEAU_TIME:-}" ]; then
|
||||
time="$JIRAFEAU_TIME"
|
||||
fi
|
||||
|
||||
if [ -n "${JIRAFEAU_ONE_TIME:-}" ]; then
|
||||
one_time='1'
|
||||
fi
|
||||
|
||||
if [ -n "${JIRAFEAU_UPLOAD_PASSWD:-}" ]; then
|
||||
upload_password="$JIRAFEAU_UPLOAD_PASSWD"
|
||||
fi
|
||||
|
||||
if [ -z "${2:-}" ]; then
|
||||
echo "Jirafeau Bash Script 4.7.1"
|
||||
echo "--------------------------"
|
||||
echo "Usage:"
|
||||
echo " $0 OPTIONS"
|
||||
echo
|
||||
echo "Options:"
|
||||
echo " $0 send FILE [PASSWORD]"
|
||||
echo " $0 get URL [PASSWORD]"
|
||||
echo " $0 delete URL"
|
||||
echo
|
||||
echo "Global variables to export:"
|
||||
echo " JIRAFEAU_PROXY: Domain and port of proxy server, eg. »proxyserver.example.com:3128«"
|
||||
echo " JIRAFEAU_URL : URI to Jirafeau installation with trailing slash, eg. »https://example.com/jirafeau/«"
|
||||
echo " JIRAFEAU_TIME : expiration time, eg. »minute«, »hour«, »day«, »week«, fortnight, »month«, »quarter«, »year« or »none«"
|
||||
echo " JIRAFEAU_ONE_TIME : self-destroy after first download, eg. »1« to enable or »« (empty) to disable"
|
||||
echo " JIRAFEAU_UPLOAD_PASSWD : upload password"
|
||||
|
||||
exit 0
|
||||
fi
|
||||
|
||||
proxy_args=()
|
||||
if [ -n "$proxy" ]; then
|
||||
proxy_args=(-x "$proxy")
|
||||
fi
|
||||
|
||||
options=()
|
||||
if [ -n "$one_time" ]; then
|
||||
options+=(-F one_time_download=1)
|
||||
fi
|
||||
|
||||
if [ -n "$upload_password" ]; then
|
||||
options+=(-F "upload_password=$upload_password")
|
||||
fi
|
||||
|
||||
password=''
|
||||
if [ -n "${3:-}" ]; then
|
||||
password="$3"
|
||||
options+=(-F "key=$password")
|
||||
fi
|
||||
|
||||
apipage='script.php'
|
||||
downloadpage='f.php'
|
||||
|
||||
if [ "$1" == "send" ]; then
|
||||
if [ ! -f "$2" ]; then
|
||||
echo "File \"$2\" does not exist."
|
||||
exit
|
||||
fi
|
||||
|
||||
# Get result
|
||||
res=$(curl -X POST --http1.0 "${proxy_args[@]}" "${options[@]}" \
|
||||
-F "time=$time" \
|
||||
-F "file=@$2" \
|
||||
"${url}${apipage}")
|
||||
|
||||
if [[ "$res" == Error* ]]; then
|
||||
echo "Error while uploading."
|
||||
echo "$res"
|
||||
exit
|
||||
fi
|
||||
|
||||
# Not using head or tail to minimise command dependencies
|
||||
code=$(cnt=0; echo "$res" | while read -r l; do
|
||||
if [[ "$cnt" == "0" ]]; then
|
||||
echo "$l"
|
||||
fi
|
||||
cnt=$(( cnt + 1 ))
|
||||
done)
|
||||
del_code=$(cnt=0; echo "$res" | while read -r l; do
|
||||
if [[ "$cnt" == "1" ]]; then
|
||||
echo "$l"
|
||||
fi
|
||||
cnt=$(( cnt + 1 ))
|
||||
done)
|
||||
key_code=$(cnt=0; echo "$res" | while read -r l; do
|
||||
if [[ "$cnt" == "2" ]]; then
|
||||
echo "$l"
|
||||
fi
|
||||
cnt=$(( cnt + 1 ))
|
||||
done)
|
||||
|
||||
echo
|
||||
echo "Download page:"
|
||||
if [[ $key_code ]]; then
|
||||
echo " ${url}${downloadpage}?h=$code&k=$key_code"
|
||||
else
|
||||
echo " ${url}${downloadpage}?h=$code"
|
||||
fi
|
||||
echo "Direct download:"
|
||||
if [[ $key_code ]]; then
|
||||
echo " ${url}${downloadpage}?h=$code&k=$key_code&d=1"
|
||||
else
|
||||
echo " ${url}${downloadpage}?h=$code&d=1"
|
||||
fi
|
||||
echo "Delete link:"
|
||||
echo " ${url}${downloadpage}?h=$code&d=$del_code"
|
||||
echo
|
||||
echo "Download via API:"
|
||||
if [[ $key_code ]]; then
|
||||
echo " ${0} get ${url}${apipage}?h=$code&k=$key_code [PASSWORD]"
|
||||
else
|
||||
echo " ${0} get ${url}${apipage}?h=$code [PASSWORD]"
|
||||
fi
|
||||
echo "Delete via API:"
|
||||
echo " ${0} delete \"${url}${downloadpage}?h=$code&d=$del_code\""
|
||||
|
||||
elif [ "$1" == "get" ]; then
|
||||
if [ -z "$password" ]; then
|
||||
curl "${proxy_args[@]}" -OJ "$2"
|
||||
else
|
||||
curl "${proxy_args[@]}" -OJ -X POST -F "key=$password" "$2"
|
||||
fi
|
||||
elif [ "$1" == "delete" ]; then
|
||||
curl "${proxy_args[@]}" "$2" --data-raw "do_delete=1%2F" | grep "div class" | sed -e "s/<[^>]\+>//g"
|
||||
fi
|
||||
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