Compare commits
169 Commits
tech/nativ
...
b4caf86628
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b4caf86628
|
||
|
|
80263ea4db
|
||
|
|
3a93db3839
|
||
|
|
3de5679411
|
||
|
|
551fe64603
|
||
|
|
fd29342f58
|
||
|
|
43848028af
|
||
|
|
fb6ebd55c3
|
||
|
|
1ddbce110f
|
||
|
|
bc85dabce0
|
||
|
|
4745fa3d58
|
||
|
|
06778795b2
|
||
|
|
7a0dbb214b
|
||
|
|
9fbe748aa1
|
||
|
|
a05fd03aa8
|
||
|
|
167d446144
|
||
|
|
855f19a19b
|
||
|
|
6878efd7bb
|
||
|
|
7f6fc155c5
|
||
|
|
b1ebf5aff2
|
||
|
|
5bff4d9713
|
||
|
|
13e119a6c3
|
||
|
|
6690b5c1ea
|
||
|
|
c8c5de288f
|
||
|
|
c450f29437
|
||
|
|
abfc978a51
|
||
|
|
bd6132ede5
|
||
|
|
e1f21c2a2a
|
||
|
|
b3bd943175
|
||
|
|
a41c885bb2
|
||
|
|
45ce478dd4
|
||
|
|
49cabcad7a
|
||
|
|
5fec78b813
|
||
|
|
2351971fd4
|
||
|
|
7f7b1ffe08
|
||
|
|
2e53fe0931
|
||
|
|
07f3668d5e
|
||
|
|
8d7c0cd01d
|
||
|
|
ffbe877dff
|
||
|
|
a1325b49c1
|
||
|
|
6aa4abeead
|
||
|
|
8823354606
|
||
|
|
ac61399a18
|
||
|
|
4d09b3546f
|
||
|
|
a88da9b269
|
||
|
|
ea04ee3517
|
||
|
|
832fe0c589
|
||
|
|
fae8bd5b05
|
||
|
|
48ec6fac7c
|
||
|
|
a6e4461954
|
||
|
|
7e909dbc21
|
||
|
|
81bc564228
|
||
|
|
80da9e35cd
|
||
|
|
9818e2c876
|
||
|
|
8e4aea6ccf
|
||
|
|
2c5b597b59
|
||
|
|
0746057d8c
|
||
|
|
5ee300fea7
|
||
|
|
0c988ec5ac
|
||
|
|
f7f3f393de
|
||
|
|
157efae198
|
||
|
|
6fdde36bd8
|
||
|
|
7750db3cbf
|
||
|
|
8f85e5662a
|
||
|
|
71ff276be9
|
||
|
|
d4004bcf8e
|
||
|
|
33253ab0da
|
||
|
|
6c1a8d059f
|
||
|
|
dd4fa5b258
|
||
|
|
14b23c5463
|
||
|
|
52a8dbede0
|
||
|
|
8774faa201
|
||
|
|
fa02a302dc
|
||
|
|
fac2055afc
|
||
|
|
91d5d73002
|
||
|
|
4233c3dabf
|
||
|
|
511f6caad1
|
||
|
|
c6e4f675d5
|
||
|
|
bea16d9a2f
|
||
|
|
f73db13392
|
||
|
|
4a9dcd098f
|
||
|
|
e317f9b0e4
|
||
|
|
40598d20c7
|
||
|
|
5b3ceb239d
|
||
|
|
3e37b4bcbc
|
||
|
|
3a03103fc7
|
||
|
|
6fb5c1ffa5
|
||
|
|
5be24a850a
|
||
|
|
a0f38794b1
|
||
|
|
7f3d6f79d2
|
||
|
|
6e2f424384
|
||
|
|
ebc2976c31
|
||
|
|
405817fa89
|
||
|
|
3e7e960b8a
|
||
|
|
4d267dbde8
|
||
|
|
82298cfb4d
|
||
|
|
8acda612dc
|
||
|
|
d1e1ef60d9
|
||
|
|
02c14d0f0f
|
||
|
|
de0dc03840
|
||
|
|
e2c8ba9c3a
|
||
|
|
584380ef7f
|
||
|
|
269bb6ac6a
|
||
|
|
4d91990ea1
|
||
|
|
0462a0fde9
|
||
|
|
88237acf7c
|
||
|
|
2e2f4e5fdc
|
||
|
|
027ae0bef8
|
||
|
|
d625368bd0
|
||
|
|
68aa04eff3
|
||
|
|
70935eea43
|
||
|
|
ef097ca283
|
||
|
|
d0cb28b8b1
|
||
|
|
e44dba355a
|
||
|
|
9bac7b2da9
|
||
|
|
0ecfaf4d3c
|
||
|
|
5c5f3dd964
|
||
|
|
8586351606
|
||
|
|
0629466bf2
|
||
|
|
d61c0f96c6
|
||
|
|
ab560e41f3
|
||
|
|
06acd91781
|
||
|
|
5c61ebf9ff
|
||
|
|
a1dee56cce
|
||
|
|
177b24d9ce
|
||
|
|
61cacdc817
|
||
|
|
d99a714a41
|
||
|
|
a52861aa40
|
||
|
|
a1f5e2acf7
|
||
|
|
abd970755a
|
||
|
|
7c477722fc
|
||
|
|
f9cb771979
|
||
|
|
4b4464a024
|
||
|
|
173b234f10
|
||
|
|
2248547f92
|
||
|
|
e65c450464
|
||
|
|
62d0963413
|
||
|
|
6cd354885a
|
||
|
|
d41b3757ac
|
||
|
|
f4993fc6b2
|
||
|
|
8dfc9b5a6d
|
||
|
|
a93d4afbcf
|
||
|
|
5c4e161076
|
||
|
|
2df6c1e7a2
|
||
|
|
5f8e14768f
|
||
|
|
af9f07a2fe
|
||
|
|
f3c2316b92
|
||
|
|
83594e09a9
|
||
|
|
6a1244821e
|
||
|
|
484d68c776
|
||
|
|
208d566e14
|
||
|
|
f0e93a837d
|
||
|
|
41bd91deb1
|
||
|
|
83f9e00416
|
||
|
|
18c93e224a
|
||
|
|
da0fab832c
|
||
|
|
4e09c07522
|
||
|
|
48be030ac7
|
||
|
|
75186e2f19
|
||
|
|
c15d518e4a
|
||
|
|
459cae639d
|
||
|
|
ecc02f4b59
|
||
|
|
6a10625d4e
|
||
|
|
1cf3c7d8dd
|
||
|
|
ddc6e6d575
|
||
|
|
309f43a276
|
||
|
|
93a518a6d5
|
||
|
|
b42eae0788
|
||
|
|
94eb995ee7
|
@@ -1,7 +0,0 @@
|
||||
image: nixos/unstable
|
||||
environment:
|
||||
NIX_CONFIG: "experimental-features = nix-command flakes"
|
||||
tasks:
|
||||
- build: |
|
||||
cd NixOS
|
||||
nix build --dry-run '.#nixosConfigurations.apu.config.system.build.toplevel'
|
||||
@@ -1,7 +0,0 @@
|
||||
image: nixos/unstable
|
||||
environment:
|
||||
NIX_CONFIG: "experimental-features = nix-command flakes"
|
||||
tasks:
|
||||
- build: |
|
||||
cd NixOS
|
||||
nix build --dry-run '.#nixosConfigurations.freun-dev.config.system.build.toplevel'
|
||||
@@ -1,7 +0,0 @@
|
||||
image: nixos/unstable
|
||||
environment:
|
||||
NIX_CONFIG: "experimental-features = nix-command flakes"
|
||||
tasks:
|
||||
- build: |
|
||||
cd NixOS
|
||||
nix build --dry-run '.#nixosConfigurations.radish.config.system.build.toplevel'
|
||||
38
.gitea/workflows/build-images.yml
Normal file
38
.gitea/workflows/build-images.yml
Normal file
@@ -0,0 +1,38 @@
|
||||
name: Build Images
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [main]
|
||||
pull_request:
|
||||
branches: [main]
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: nixos-latest
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v6
|
||||
|
||||
- name: Build aarch64 Image
|
||||
run: nix build .#dockerImages.aarch64-linux.node --out-link ./image-aarch64.tar.gz --option build-hook ""
|
||||
|
||||
- name: Push to Gitea Registry
|
||||
if: github.event_name == 'push' && github.ref == 'refs/heads/main'
|
||||
run: |
|
||||
REGISTRY="${{ github.server_url }}"
|
||||
REGISTRY="${REGISTRY#https://}"
|
||||
REGISTRY="${REGISTRY#http://}"
|
||||
|
||||
# Push aarch64 image
|
||||
skopeo copy \
|
||||
--insecure-policy \
|
||||
--dest-creds "${{ github.repository_owner }}:${{ secrets.REGISTRY_TOKEN }}" \
|
||||
"docker-archive:./image-aarch64.tar.gz" \
|
||||
"docker://${REGISTRY}/${{ github.repository }}/node:latest"
|
||||
|
||||
skopeo copy \
|
||||
--insecure-policy \
|
||||
--dest-creds "${{ github.repository_owner }}:${{ secrets.REGISTRY_TOKEN }}" \
|
||||
"docker-archive:./image-aarch64.tar.gz" \
|
||||
"docker://${REGISTRY}/${{ github.repository }}/node:latest-arm64"
|
||||
18
.gitea/workflows/check.yml
Normal file
18
.gitea/workflows/check.yml
Normal file
@@ -0,0 +1,18 @@
|
||||
name: Check
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [main]
|
||||
pull_request:
|
||||
branches: [main]
|
||||
|
||||
jobs:
|
||||
check:
|
||||
runs-on: nixos-latest
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v6
|
||||
|
||||
- name: Check
|
||||
run: nix flake check --all-systems
|
||||
2
.gitignore
vendored
2
.gitignore
vendored
@@ -1,2 +1,4 @@
|
||||
/result
|
||||
/.direnv
|
||||
/.gcroots
|
||||
*.qcow2
|
||||
|
||||
41
.zed/tasks.json
Normal file
41
.zed/tasks.json
Normal file
@@ -0,0 +1,41 @@
|
||||
[
|
||||
{
|
||||
"label": "Apply local",
|
||||
"command": "apply-local",
|
||||
"use_new_terminal": false,
|
||||
"allow_concurrent_runs": true,
|
||||
"reveal": "no_focus",
|
||||
"reveal_target": "dock",
|
||||
"hide": "on_success",
|
||||
},
|
||||
{
|
||||
"label": "Apply remote",
|
||||
"command": "apply",
|
||||
"args": ["--build-on-target"],
|
||||
"use_new_terminal": false,
|
||||
"allow_concurrent_runs": true,
|
||||
"reveal": "no_focus",
|
||||
"reveal_target": "dock",
|
||||
"hide": "on_success",
|
||||
},
|
||||
{
|
||||
"label": "Apply on freun-dev",
|
||||
"command": "apply",
|
||||
"args": ["--on", "freun-dev"],
|
||||
"use_new_terminal": false,
|
||||
"allow_concurrent_runs": true,
|
||||
"reveal": "no_focus",
|
||||
"reveal_target": "dock",
|
||||
"hide": "on_success",
|
||||
},
|
||||
{
|
||||
"label": "Apply on apu",
|
||||
"command": "apply",
|
||||
"args": ["--on", "apu"],
|
||||
"use_new_terminal": false,
|
||||
"allow_concurrent_runs": true,
|
||||
"reveal": "no_focus",
|
||||
"reveal_target": "dock",
|
||||
"hide": "on_success",
|
||||
},
|
||||
]
|
||||
23
AGENTS.md
Normal file
23
AGENTS.md
Normal file
@@ -0,0 +1,23 @@
|
||||
# Agent Guidelines for NixOS Configuration
|
||||
|
||||
## Build & Deploy Commands
|
||||
- `nix flake check` - Validate flake configuration
|
||||
- `build <host>` - Build configuration for specific host (e.g., `build radish`)
|
||||
- `apply <host>` - Deploy to remote host via colmena
|
||||
- `apply-local` - Apply configuration locally using nh
|
||||
- `nix build .#nixosConfigurations.<host>.config.system.build.toplevel` - Build specific host
|
||||
|
||||
## Code Style
|
||||
- **Format**: Use `nixfmt-rfc-style` for all .nix files
|
||||
- **Imports**: List imports first, group by: local modules, external inputs (inputs.*)
|
||||
- **Function args**: Multi-line with trailing comma when >3 args: `{ config, lib, pkgs, ... }:`
|
||||
- **Options**: Define in `options.<service>` block, implement in `config = lib.mkIf cfg.enable { ... }`
|
||||
- **Types**: Use `lib.types.*` for option types (str, bool, int, etc.)
|
||||
- **String interpolation**: Use `"${}"` for Nix expressions, prefer lib.getExe for binaries
|
||||
- **Conditionals**: Use `lib.mkIf`, `lib.mkDefault`, `lib.mkMerge` for NixOS options
|
||||
|
||||
## Structure
|
||||
- Host configs in `hosts/<name>/` with configuration.nix, default.nix, hardware-configuration.nix
|
||||
- Reusable modules in `modules/` and `modules/services/`
|
||||
- Custom packages in `custom-pkgs/` using util.package pattern
|
||||
- Secrets managed via agenix in `secrets/` directory
|
||||
@@ -1,3 +1,3 @@
|
||||
# My NixOS Configurations
|
||||
|
||||
[](https://builds.sr.ht/~repomaa?)
|
||||
[](https://git.freun.dev/repomaa/nixos/actions?workflow=check.yml) [](https://git.freun.dev/repomaa/nixos/actions?workflow=build-images.yml)
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
{ util, inputs, ... }: util.vimPlugin { name = "commander.nvim"; source = inputs.commander-nvim; }
|
||||
@@ -2,8 +2,7 @@
|
||||
let
|
||||
inherit (pkgs) crystal libffi;
|
||||
in
|
||||
crystal.overrideAttrs (oldAttrs:
|
||||
{
|
||||
crystal.overrideAttrs (oldAttrs: {
|
||||
makeFlags = oldAttrs.makeFlags ++ [
|
||||
"interpreter=1"
|
||||
];
|
||||
@@ -12,5 +11,4 @@ crystal.overrideAttrs (oldAttrs:
|
||||
];
|
||||
FLAGS = [ "--single-module" ];
|
||||
doCheck = false;
|
||||
}
|
||||
)
|
||||
})
|
||||
|
||||
@@ -1,9 +1,24 @@
|
||||
{ lib, inputs, ... }:
|
||||
{
|
||||
lib,
|
||||
inputs,
|
||||
pkgs-unstable,
|
||||
...
|
||||
}:
|
||||
let
|
||||
inherit (builtins) attrNames filter readDir;
|
||||
dirs =
|
||||
let files = readDir ./.;
|
||||
in filter (name: files."${name}" == "directory") (attrNames files);
|
||||
let
|
||||
files = readDir ./.;
|
||||
in
|
||||
filter (name: files."${name}" == "directory") (attrNames files);
|
||||
util = import ./util.nix;
|
||||
in
|
||||
lib.composeManyExtensions (map (dir: import ./${dir} { util = util dir; inherit inputs; }) dirs)
|
||||
lib.composeManyExtensions (
|
||||
map (
|
||||
dir:
|
||||
import ./${dir} {
|
||||
util = util dir;
|
||||
inherit inputs lib pkgs-unstable;
|
||||
}
|
||||
) dirs
|
||||
)
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
{ util, ... }: util.package { }
|
||||
@@ -1,22 +0,0 @@
|
||||
{ lib, stdenv, fetchurl, python3, ... }:
|
||||
stdenv.mkDerivation rec {
|
||||
pname = "fb-client";
|
||||
version = "2.3.0";
|
||||
|
||||
src = fetchurl {
|
||||
url = "https://paste.xinu.at/data/client/fb-${version}.tar.gz";
|
||||
sha256 = "sha256-EWTsoG7qy0IQ1GLEuvHEAEJyphl9hz1hFm53k1OdGYM=";
|
||||
};
|
||||
|
||||
buildInputs =
|
||||
[ (python3.withPackages (pyPkgs: with pyPkgs; [ pycurl pyxdg ])) ];
|
||||
|
||||
makeFlags = [ "PREFIX=$(out)" ];
|
||||
|
||||
meta = with lib; {
|
||||
mainProgram = "fb";
|
||||
description = "Client for paste.xinu.at";
|
||||
homepage = "https://paste.xinu.at";
|
||||
license = licenses.gpl3Only;
|
||||
};
|
||||
}
|
||||
@@ -1 +0,0 @@
|
||||
{ util, ... }: util.package { }
|
||||
@@ -1,6 +0,0 @@
|
||||
{ pkgs, ... }:
|
||||
pkgs.writeShellScriptBin "flameshot" ''
|
||||
export XDG_SESSION_TYPE= QT_QPA_PLATFORM=wayland
|
||||
nohup ${pkgs.flameshot}/bin/flameshot >& /dev/null &
|
||||
${pkgs.flameshot}/bin/flameshot "$@"
|
||||
''
|
||||
@@ -1 +0,0 @@
|
||||
{ inputs, util, ... }: util.vimPlugin { name = "gen.nvim"; source = inputs.gen-nvim; }
|
||||
@@ -1 +1,7 @@
|
||||
{ util, inputs, ... }: util.package { inherit inputs; }
|
||||
{
|
||||
util,
|
||||
pkgs-unstable,
|
||||
lib,
|
||||
...
|
||||
}:
|
||||
util.package { inherit pkgs-unstable lib; }
|
||||
|
||||
96
custom-pkgs/otp/otp.cr
Normal file
96
custom-pkgs/otp/otp.cr
Normal file
@@ -0,0 +1,96 @@
|
||||
require "option_parser"
|
||||
|
||||
NOTIFY_ICON = {{env("NOTIFY_ICON")}}
|
||||
NOTIFY_SEND_COMMAND = {{env("NOTIFY_SEND")}}
|
||||
WL_COPY_COMMAND = {{env("WL_COPY")}}
|
||||
YKMAN_COMMAND = {{env("YKMAN")}}
|
||||
SKIM_COMMAND = {{env("SKIM")}}
|
||||
WALKER_COMMAND = {{env("WALKER")}}
|
||||
|
||||
class OTP
|
||||
private property dmenu_command : String = SKIM_COMMAND
|
||||
private property dmenu_args = [] of String
|
||||
|
||||
def run
|
||||
parser = OptionParser.new do |opts|
|
||||
opts.banner = "Usage: #{PROGRAM_NAME} [options]"
|
||||
|
||||
opts.on("-h", "--help", "Display this help message") do
|
||||
puts opts
|
||||
exit
|
||||
end
|
||||
|
||||
opts.on("-w", "--walker", "Use walker as dmenu") do
|
||||
self.dmenu_command = WALKER_COMMAND
|
||||
self.dmenu_args << "--dmenu" << "-p" << "Select account:"
|
||||
end
|
||||
end
|
||||
|
||||
parser.parse
|
||||
|
||||
self.dmenu_args += ["-q", *ARGV] unless ARGV.empty?
|
||||
|
||||
account = select_account
|
||||
code = code_for(account)
|
||||
copy(code)
|
||||
end
|
||||
|
||||
private def notify_send(message, urgency = :normal)
|
||||
return if message.chomp.empty?
|
||||
|
||||
Process.run(NOTIFY_SEND_COMMAND, ["-i", NOTIFY_ICON, "-u", urgency.to_s, "OTP", message.chomp])
|
||||
end
|
||||
|
||||
private def list_accounts
|
||||
error = IO::Memory.new
|
||||
output = IO::Memory.new
|
||||
status = Process.run(YKMAN_COMMAND, %w[oath accounts list], output: output, error: error)
|
||||
errors = error.rewind.gets_to_end.try(&.chomp)
|
||||
notify_send(errors, urgency: status.success? ? :normal : :critical) unless errors.empty?
|
||||
exit status.exit_code unless status.success?
|
||||
|
||||
output.rewind.gets_to_end
|
||||
end
|
||||
|
||||
private def select_account
|
||||
output = IO::Memory.new
|
||||
accounts = list_accounts
|
||||
puts accounts
|
||||
input = IO::Memory.new(accounts)
|
||||
Process.run(dmenu_command, dmenu_args, output: output, input: input)
|
||||
|
||||
account = output.rewind.gets(chomp: true)
|
||||
return account if account
|
||||
|
||||
notify_send("No account selected", urgency: :critical)
|
||||
exit 1
|
||||
end
|
||||
|
||||
private def code_for(account)
|
||||
output = IO::Memory.new
|
||||
|
||||
Process.run(YKMAN_COMMAND, ["oath", "accounts", "code", "-s", account], output: output) do |process|
|
||||
spawn do
|
||||
while line = process.error.gets(chomp: true)
|
||||
notify_send(line)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
exit $?.exit_code unless $?.success?
|
||||
|
||||
code = output.rewind.gets(chomp: true)
|
||||
return code if code
|
||||
|
||||
notify_send("No code generated", urgency: :critical)
|
||||
exit 1
|
||||
end
|
||||
|
||||
private def copy(code)
|
||||
input = IO::Memory.new(code)
|
||||
Process.run(WL_COPY_COMMAND, %w[-n], input: input)
|
||||
notify_send("Copied to clipboard")
|
||||
end
|
||||
end
|
||||
|
||||
OTP.new.run
|
||||
@@ -1,18 +1,22 @@
|
||||
{ pkgs, inputs }:
|
||||
let
|
||||
yubikey-manager = inputs.nixpkgs-unstable.legacyPackages.${pkgs.system}.yubikey-manager;
|
||||
ykman = "${yubikey-manager}/bin/ykman";
|
||||
sk = "${pkgs.skim}/bin/sk";
|
||||
wl-copy = "${pkgs.wl-clipboard}/bin/wl-copy";
|
||||
in
|
||||
pkgs.writeShellScriptBin "otp" ''
|
||||
skim_command=("${sk}")
|
||||
|
||||
if [ -n "$*" ]; then
|
||||
skim_command+=(-q "$*")
|
||||
fi
|
||||
|
||||
account=$(${ykman} oath accounts list | "''${skim_command[@]}")
|
||||
[ -z "$account" ] && exit 1
|
||||
${ykman} oath accounts code -s "$account" | ${wl-copy} -n
|
||||
{
|
||||
pkgs,
|
||||
lib,
|
||||
pkgs-unstable,
|
||||
}:
|
||||
pkgs.runCommand "otp"
|
||||
{
|
||||
code = ./otp.cr;
|
||||
env = {
|
||||
YKMAN = lib.getExe pkgs-unstable.yubikey-manager;
|
||||
SKIM = lib.getExe pkgs.skim;
|
||||
WALKER = lib.getExe pkgs-unstable.walker;
|
||||
WL_COPY = lib.getExe' pkgs.wl-clipboard "wl-copy";
|
||||
NOTIFY_SEND = lib.getExe pkgs.libnotify;
|
||||
NOTIFY_ICON = "${pkgs-unstable.yubioath-flutter}/share/pixmaps/com.yubico.yubioath.png";
|
||||
};
|
||||
nativeBuildInputs = [ pkgs.crystal ];
|
||||
}
|
||||
''
|
||||
mkdir -p $out/bin
|
||||
crystal build $code --release -o $out/bin/otp
|
||||
''
|
||||
|
||||
@@ -1,16 +1,5 @@
|
||||
dir:
|
||||
{
|
||||
vimPlugin = { name, source }:
|
||||
final: prev: {
|
||||
vimPlugins = prev.vimPlugins // {
|
||||
"${dir}" = prev.vimUtils.buildVimPlugin {
|
||||
pname = name;
|
||||
version = source.lastModifiedDate;
|
||||
src = source;
|
||||
doCheck = false;
|
||||
dir: {
|
||||
package = attrs: final: prev: {
|
||||
"${dir}" = final.callPackage ./${dir}/package.nix (attrs // { pkgs = prev; });
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
package = attrs: final: prev: { "${dir}" = final.callPackage ./${dir}/package.nix (attrs // { pkgs = prev; }); };
|
||||
}
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
{ inputs, util, ... }: util.vimPlugin { name = "vimpeccable"; source = inputs.vimpeccable; }
|
||||
@@ -1 +0,0 @@
|
||||
{ inputs, util, ... }: util.vimPlugin { name = "windline.nvim"; source = inputs.windline-nvim; }
|
||||
596
flake.lock
generated
596
flake.lock
generated
@@ -10,11 +10,11 @@
|
||||
"systems": "systems"
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1736955230,
|
||||
"narHash": "sha256-uenf8fv2eG5bKM8C/UvFaiJMZ4IpUFaQxk9OH5t/1gA=",
|
||||
"lastModified": 1770165109,
|
||||
"narHash": "sha256-9VnK6Oqai65puVJ4WYtCTvlJeXxMzAp/69HhQuTdl/I=",
|
||||
"owner": "ryantm",
|
||||
"repo": "agenix",
|
||||
"rev": "e600439ec4c273cf11e06fe4d9d906fb98fa097c",
|
||||
"rev": "b027ee29d959fda4b60b57566d64c98a202e0feb",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
@@ -23,49 +23,37 @@
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"auto-cpufreq": {
|
||||
"colmena": {
|
||||
"inputs": {
|
||||
"flake-compat": "flake-compat",
|
||||
"flake-utils": "flake-utils",
|
||||
"nix-github-actions": "nix-github-actions",
|
||||
"nixpkgs": [
|
||||
"nixpkgs"
|
||||
]
|
||||
],
|
||||
"stable": "stable"
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1737497253,
|
||||
"narHash": "sha256-sOLwi/3oQiNWA2I3WiGneK988YdKVHbH1P5lEjxypIg=",
|
||||
"owner": "AdnanHodzic",
|
||||
"repo": "auto-cpufreq",
|
||||
"rev": "4cee388c1bbea3adc333b597717d5d8d12375705",
|
||||
"lastModified": 1762034856,
|
||||
"narHash": "sha256-QVey3iP3UEoiFVXgypyjTvCrsIlA4ecx6Acaz5C8/PQ=",
|
||||
"owner": "zhaofengli",
|
||||
"repo": "colmena",
|
||||
"rev": "349b035a5027f23d88eeb3bc41085d7ee29f18ed",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "AdnanHodzic",
|
||||
"repo": "auto-cpufreq",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"commander-nvim": {
|
||||
"flake": false,
|
||||
"locked": {
|
||||
"lastModified": 1717816527,
|
||||
"narHash": "sha256-eXOHR+lwHVJze6jvFuDlvcUtFSpV8EJqlWvXLRWeCNI=",
|
||||
"owner": "FeiyouG",
|
||||
"repo": "commander.nvim",
|
||||
"rev": "84101e8eb1613a72bbdec655b734f891d8a00694",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "FeiyouG",
|
||||
"repo": "commander.nvim",
|
||||
"owner": "zhaofengli",
|
||||
"repo": "colmena",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"crane": {
|
||||
"locked": {
|
||||
"lastModified": 1731098351,
|
||||
"narHash": "sha256-HQkYvKvaLQqNa10KEFGgWHfMAbWBfFp+4cAgkut+NNE=",
|
||||
"lastModified": 1771796463,
|
||||
"narHash": "sha256-9bCDuUzpwJXcHMQYMS1yNuzYMmKO/CCwCexpjWOl62I=",
|
||||
"owner": "ipetkov",
|
||||
"repo": "crane",
|
||||
"rev": "ef80ead953c1b28316cc3f8613904edc2eb90c28",
|
||||
"rev": "3d3de3313e263e04894f284ac18177bd26169bad",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
@@ -82,11 +70,11 @@
|
||||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1700795494,
|
||||
"narHash": "sha256-gzGLZSiOhf155FW7262kdHo2YDeugp3VuIFb4/GGng0=",
|
||||
"lastModified": 1744478979,
|
||||
"narHash": "sha256-dyN+teG9G82G+m+PX/aSAagkC+vUv0SgUw3XkPhQodQ=",
|
||||
"owner": "lnl7",
|
||||
"repo": "nix-darwin",
|
||||
"rev": "4b9b83d5a92e8c1fbfd8eb27eda375908c11ec4d",
|
||||
"rev": "43975d782b418ebf4969e9ccba82466728c2851b",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
@@ -96,14 +84,30 @@
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"dnote": {
|
||||
"flake": false,
|
||||
"locked": {
|
||||
"lastModified": 1772691105,
|
||||
"narHash": "sha256-RC18Gi3/dagBitZIRIuPwIokk6pwwv+ZpawLTXSJ18c=",
|
||||
"owner": "dnote",
|
||||
"repo": "dnote",
|
||||
"rev": "f34a96abbe47e8b516ea7cac2bdec06c64c01493",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "dnote",
|
||||
"repo": "dnote",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"flake-compat": {
|
||||
"flake": false,
|
||||
"locked": {
|
||||
"lastModified": 1696426674,
|
||||
"narHash": "sha256-kvjfFW7WAETZlt09AgDn1MrtKzP7t90Vf7vypd3OL1U=",
|
||||
"lastModified": 1650374568,
|
||||
"narHash": "sha256-Z+s0J8/r907g149rllvwhb4pKi8Wam5ij0st8PwAh+E=",
|
||||
"owner": "edolstra",
|
||||
"repo": "flake-compat",
|
||||
"rev": "0f9255e01c2351cc7d116c072cb317785dd33b33",
|
||||
"rev": "b4a34015c698c7793d592d66adbab377907a2be8",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
@@ -112,16 +116,32 @@
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"flake-compat_2": {
|
||||
"flake": false,
|
||||
"locked": {
|
||||
"lastModified": 1767039857,
|
||||
"narHash": "sha256-vNpUSpF5Nuw8xvDLj2KCwwksIbjua2LZCqhV1LNRDns=",
|
||||
"owner": "NixOS",
|
||||
"repo": "flake-compat",
|
||||
"rev": "5edf11c44bc78a0d334f6334cdaf7d60d732daab",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "NixOS",
|
||||
"repo": "flake-compat",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"flake-parts": {
|
||||
"inputs": {
|
||||
"nixpkgs-lib": "nixpkgs-lib"
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1738453229,
|
||||
"narHash": "sha256-7H9XgNiGLKN1G1CgRh0vUL4AheZSYzPm+zmZ7vxbJdo=",
|
||||
"lastModified": 1772408722,
|
||||
"narHash": "sha256-rHuJtdcOjK7rAHpHphUb1iCvgkU3GpfvicLMwwnfMT0=",
|
||||
"owner": "hercules-ci",
|
||||
"repo": "flake-parts",
|
||||
"rev": "32ea77a06711b758da0ad9bd6a844c5740a87abd",
|
||||
"rev": "f20dc5d9b8027381c474144ecabc9034d6a839a3",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
@@ -166,28 +186,22 @@
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"flake-parts_4": {
|
||||
"inputs": {
|
||||
"nixpkgs-lib": [
|
||||
"lanzaboote",
|
||||
"nixpkgs"
|
||||
]
|
||||
},
|
||||
"flake-utils": {
|
||||
"locked": {
|
||||
"lastModified": 1730504689,
|
||||
"narHash": "sha256-hgmguH29K2fvs9szpq2r3pz2/8cJd2LPS+b4tfNFCwE=",
|
||||
"owner": "hercules-ci",
|
||||
"repo": "flake-parts",
|
||||
"rev": "506278e768c2a08bec68eb62932193e341f55c90",
|
||||
"lastModified": 1659877975,
|
||||
"narHash": "sha256-zllb8aq3YO3h8B/U0/J1WBgAL8EX5yWf5pMj3G0NAmc=",
|
||||
"owner": "numtide",
|
||||
"repo": "flake-utils",
|
||||
"rev": "c0e246b9b83f637f4681389ecabcb2681b4f3af0",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "hercules-ci",
|
||||
"repo": "flake-parts",
|
||||
"owner": "numtide",
|
||||
"repo": "flake-utils",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"flake-utils": {
|
||||
"flake-utils_2": {
|
||||
"inputs": {
|
||||
"systems": "systems_2"
|
||||
},
|
||||
@@ -205,7 +219,7 @@
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"flake-utils_2": {
|
||||
"flake-utils_3": {
|
||||
"inputs": {
|
||||
"systems": "systems_3"
|
||||
},
|
||||
@@ -223,7 +237,7 @@
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"flake-utils_3": {
|
||||
"flake-utils_4": {
|
||||
"inputs": {
|
||||
"systems": "systems_4"
|
||||
},
|
||||
@@ -241,9 +255,63 @@
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"flake-utils_5": {
|
||||
"inputs": {
|
||||
"systems": "systems_5"
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1731533236,
|
||||
"narHash": "sha256-l0KFg5HjrsfsO/JpG+r7fRrqm12kzFHyUHqHCVpMMbI=",
|
||||
"owner": "numtide",
|
||||
"repo": "flake-utils",
|
||||
"rev": "11707dc2f618dd54ca8739b309ec4fc024de578b",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "numtide",
|
||||
"repo": "flake-utils",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"flake-utils_6": {
|
||||
"inputs": {
|
||||
"systems": "systems_6"
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1731533236,
|
||||
"narHash": "sha256-l0KFg5HjrsfsO/JpG+r7fRrqm12kzFHyUHqHCVpMMbI=",
|
||||
"owner": "numtide",
|
||||
"repo": "flake-utils",
|
||||
"rev": "11707dc2f618dd54ca8739b309ec4fc024de578b",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "numtide",
|
||||
"repo": "flake-utils",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"flake-utils_7": {
|
||||
"inputs": {
|
||||
"systems": "systems_7"
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1731533236,
|
||||
"narHash": "sha256-l0KFg5HjrsfsO/JpG+r7fRrqm12kzFHyUHqHCVpMMbI=",
|
||||
"owner": "numtide",
|
||||
"repo": "flake-utils",
|
||||
"rev": "11707dc2f618dd54ca8739b309ec4fc024de578b",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "numtide",
|
||||
"repo": "flake-utils",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"frontend": {
|
||||
"inputs": {
|
||||
"flake-utils": "flake-utils",
|
||||
"flake-utils": "flake-utils_2",
|
||||
"nixpkgs": "nixpkgs",
|
||||
"pnpm2nix": "pnpm2nix"
|
||||
},
|
||||
@@ -261,27 +329,11 @@
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"gen-nvim": {
|
||||
"flake": false,
|
||||
"locked": {
|
||||
"lastModified": 1735503365,
|
||||
"narHash": "sha256-s3Ky2uhRviKAaKF3iCF2uHctzk+kFV7BnqyxAGwqhbo=",
|
||||
"owner": "David-Kunz",
|
||||
"repo": "gen.nvim",
|
||||
"rev": "e09a8dbffa139ad60d5b47998fcc8669ead1ebf4",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "David-Kunz",
|
||||
"repo": "gen.nvim",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"gitignore": {
|
||||
"inputs": {
|
||||
"nixpkgs": [
|
||||
"lanzaboote",
|
||||
"pre-commit-hooks-nix",
|
||||
"pre-commit",
|
||||
"nixpkgs"
|
||||
]
|
||||
},
|
||||
@@ -329,11 +381,11 @@
|
||||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1739261575,
|
||||
"narHash": "sha256-MRU+at2TEZ61G1bXJeVYIswJ8mVIaqVmXrKLBNs0lvU=",
|
||||
"lastModified": 1740944656,
|
||||
"narHash": "sha256-SLFmhOqOly5Uz4MiIDLfDUQnwM0FDjthoZPvdFGvOSY=",
|
||||
"owner": "~repomaa",
|
||||
"repo": "hastebin",
|
||||
"rev": "0400c9d3fcfe77dd4bd087c3f1f5ce06a8f29ad9",
|
||||
"rev": "087b64789ebf11a9874c8777c0aee88675a9ceaf",
|
||||
"type": "sourcehut"
|
||||
},
|
||||
"original": {
|
||||
@@ -350,11 +402,11 @@
|
||||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1703113217,
|
||||
"narHash": "sha256-7ulcXOk63TIT2lVDSExj7XzFx09LpdSAPtvgtM7yQPE=",
|
||||
"lastModified": 1745494811,
|
||||
"narHash": "sha256-YZCh2o9Ua1n9uCvrvi5pRxtuVNml8X2a03qIFfRKpFs=",
|
||||
"owner": "nix-community",
|
||||
"repo": "home-manager",
|
||||
"rev": "3bfaacf46133c037bb356193bd2f1765d9dc82c1",
|
||||
"rev": "abfad3d2958c9e6300a883bd443512c55dfeb1be",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
@@ -370,23 +422,23 @@
|
||||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1736373539,
|
||||
"narHash": "sha256-dinzAqCjenWDxuy+MqUQq0I4zUSfaCvN9rzuCmgMZJY=",
|
||||
"lastModified": 1772633058,
|
||||
"narHash": "sha256-SO7JapRy2HPhgmqiLbfnW1kMx5rakPMKZ9z3wtRLQjI=",
|
||||
"owner": "nix-community",
|
||||
"repo": "home-manager",
|
||||
"rev": "bd65bc3cde04c16755955630b344bc9e35272c56",
|
||||
"rev": "080657a04188aca25f8a6c70a0fb2ea7e37f1865",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "nix-community",
|
||||
"ref": "release-24.11",
|
||||
"ref": "release-25.11",
|
||||
"repo": "home-manager",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"ketchup": {
|
||||
"inputs": {
|
||||
"flake-utils": "flake-utils_3",
|
||||
"flake-utils": "flake-utils_4",
|
||||
"nixpkgs": [
|
||||
"nixpkgs"
|
||||
]
|
||||
@@ -405,22 +457,6 @@
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"keycloak-realms": {
|
||||
"locked": {
|
||||
"lastModified": 1721562747,
|
||||
"narHash": "sha256-uHNWpe/j5Q7Ak9+SNQkCPy7t9ayQUDAt+2tZ7OFYv6Q=",
|
||||
"owner": "rorosen",
|
||||
"repo": "nixpkgs",
|
||||
"rev": "79862894befe49e2837e3f5eefe11433eef6611a",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "rorosen",
|
||||
"ref": "keycloak-realm-import",
|
||||
"repo": "nixpkgs",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"ksoloti-pr": {
|
||||
"locked": {
|
||||
"lastModified": 1730719587,
|
||||
@@ -440,18 +476,16 @@
|
||||
"lanzaboote": {
|
||||
"inputs": {
|
||||
"crane": "crane",
|
||||
"flake-compat": "flake-compat",
|
||||
"flake-parts": "flake-parts_4",
|
||||
"nixpkgs": "nixpkgs_3",
|
||||
"pre-commit-hooks-nix": "pre-commit-hooks-nix",
|
||||
"pre-commit": "pre-commit",
|
||||
"rust-overlay": "rust-overlay"
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1737639419,
|
||||
"narHash": "sha256-AEEDktApTEZ5PZXNDkry2YV2k6t0dTgLPEmAZbnigXU=",
|
||||
"lastModified": 1772216104,
|
||||
"narHash": "sha256-1TnGN26vnCEQk5m4AavJZxGZTb/6aZyphemRPRwFUfs=",
|
||||
"owner": "nix-community",
|
||||
"repo": "lanzaboote",
|
||||
"rev": "a65905a09e2c43ff63be8c0e86a93712361f871e",
|
||||
"rev": "dbe5112de965bbbbff9f0729a9789c20a65ab047",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
@@ -460,35 +494,34 @@
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"nextcloud": {
|
||||
"nix-github-actions": {
|
||||
"inputs": {
|
||||
"keycloak-realms": "keycloak-realms",
|
||||
"nixos-shell": "nixos-shell",
|
||||
"nixpkgs": [
|
||||
"colmena",
|
||||
"nixpkgs"
|
||||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1730827799,
|
||||
"narHash": "sha256-79sE72rlztvhx37PYh6m2TLE2J6ybVvDRMQBRWaohqc=",
|
||||
"owner": "onny",
|
||||
"repo": "nixos-nextcloud-testumgebung",
|
||||
"rev": "c3fdbf165814d403a8f8e81ff8e15adcbe7eadd0",
|
||||
"lastModified": 1729742964,
|
||||
"narHash": "sha256-B4mzTcQ0FZHdpeWcpDYPERtyjJd/NIuaQ9+BV1h+MpA=",
|
||||
"owner": "nix-community",
|
||||
"repo": "nix-github-actions",
|
||||
"rev": "e04df33f62cdcf93d73e9a04142464753a16db67",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "onny",
|
||||
"repo": "nixos-nextcloud-testumgebung",
|
||||
"owner": "nix-community",
|
||||
"repo": "nix-github-actions",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"nixos-hardware": {
|
||||
"locked": {
|
||||
"lastModified": 1738816619,
|
||||
"narHash": "sha256-5yRlg48XmpcX5b5HesdGMOte+YuCy9rzQkJz+imcu6I=",
|
||||
"lastModified": 1771969195,
|
||||
"narHash": "sha256-qwcDBtrRvJbrrnv1lf/pREQi8t2hWZxVAyeMo7/E9sw=",
|
||||
"owner": "NixOS",
|
||||
"repo": "nixos-hardware",
|
||||
"rev": "2eccff41bab80839b1d25b303b53d339fbb07087",
|
||||
"rev": "41c6b421bdc301b2624486e11905c9af7b8ec68e",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
@@ -498,24 +531,6 @@
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"nixos-shell": {
|
||||
"inputs": {
|
||||
"nixpkgs": "nixpkgs_4"
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1728308049,
|
||||
"narHash": "sha256-wjAkG8f5orZ4+wgXmEaFAJkVJS6ORqfgM0zzLEvbUNw=",
|
||||
"owner": "Mic92",
|
||||
"repo": "nixos-shell",
|
||||
"rev": "9373ca9522f844a3b8029720c74f340e560e4462",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "Mic92",
|
||||
"repo": "nixos-shell",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"nixpkgs": {
|
||||
"locked": {
|
||||
"lastModified": 1717196966,
|
||||
@@ -534,14 +549,17 @@
|
||||
},
|
||||
"nixpkgs-lib": {
|
||||
"locked": {
|
||||
"lastModified": 1738452942,
|
||||
"narHash": "sha256-vJzFZGaCpnmo7I6i416HaBLpC+hvcURh/BQwROcGIp8=",
|
||||
"type": "tarball",
|
||||
"url": "https://github.com/NixOS/nixpkgs/archive/072a6db25e947df2f31aab9eccd0ab75d5b2da11.tar.gz"
|
||||
"lastModified": 1772328832,
|
||||
"narHash": "sha256-e+/T/pmEkLP6BHhYjx6GmwP5ivonQQn0bJdH9YrRB+Q=",
|
||||
"owner": "nix-community",
|
||||
"repo": "nixpkgs.lib",
|
||||
"rev": "c185c7a5e5dd8f9add5b2f8ebeff00888b070742",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"type": "tarball",
|
||||
"url": "https://github.com/NixOS/nixpkgs/archive/072a6db25e947df2f31aab9eccd0ab75d5b2da11.tar.gz"
|
||||
"owner": "nix-community",
|
||||
"repo": "nixpkgs.lib",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"nixpkgs-lib_2": {
|
||||
@@ -568,29 +586,13 @@
|
||||
"url": "https://github.com/NixOS/nixpkgs/archive/072a6db25e947df2f31aab9eccd0ab75d5b2da11.tar.gz"
|
||||
}
|
||||
},
|
||||
"nixpkgs-stable": {
|
||||
"locked": {
|
||||
"lastModified": 1730741070,
|
||||
"narHash": "sha256-edm8WG19kWozJ/GqyYx2VjW99EdhjKwbY3ZwdlPAAlo=",
|
||||
"owner": "NixOS",
|
||||
"repo": "nixpkgs",
|
||||
"rev": "d063c1dd113c91ab27959ba540c0d9753409edf3",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "NixOS",
|
||||
"ref": "nixos-24.05",
|
||||
"repo": "nixpkgs",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"nixpkgs-unstable": {
|
||||
"locked": {
|
||||
"lastModified": 1738680400,
|
||||
"narHash": "sha256-ooLh+XW8jfa+91F1nhf9OF7qhuA/y1ChLx6lXDNeY5U=",
|
||||
"lastModified": 1772624091,
|
||||
"narHash": "sha256-QKyJ0QGWBn6r0invrMAK8dmJoBYWoOWy7lN+UHzW1jc=",
|
||||
"owner": "NixOS",
|
||||
"repo": "nixpkgs",
|
||||
"rev": "799ba5bffed04ced7067a91798353d360788b30d",
|
||||
"rev": "80bdc1e5ce51f56b19791b52b2901187931f5353",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
@@ -618,54 +620,39 @@
|
||||
},
|
||||
"nixpkgs_3": {
|
||||
"locked": {
|
||||
"lastModified": 1731919951,
|
||||
"narHash": "sha256-vOM6ETpl1yu9KLi/icTmLJIPbbdJCdAVYUXZceO/Ce4=",
|
||||
"lastModified": 1771848320,
|
||||
"narHash": "sha256-0MAd+0mun3K/Ns8JATeHT1sX28faLII5hVLq0L3BdZU=",
|
||||
"owner": "NixOS",
|
||||
"repo": "nixpkgs",
|
||||
"rev": "04386ac325a813047fc314d4b4d838a5b1e3c7fe",
|
||||
"rev": "2fc6539b481e1d2569f25f8799236694180c0993",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "NixOS",
|
||||
"ref": "nixos-unstable-small",
|
||||
"ref": "nixos-unstable",
|
||||
"repo": "nixpkgs",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"nixpkgs_4": {
|
||||
"locked": {
|
||||
"lastModified": 1628465643,
|
||||
"narHash": "sha256-QSNw9bDq9uGUniQQtakRuw4m21Jxugm23SXLVgEV4DM=",
|
||||
"lastModified": 1772598333,
|
||||
"narHash": "sha256-YaHht/C35INEX3DeJQNWjNaTcPjYmBwwjFJ2jdtr+5U=",
|
||||
"owner": "NixOS",
|
||||
"repo": "nixpkgs",
|
||||
"rev": "6ef4f522d63f22b40004319778761040d3197390",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"id": "nixpkgs",
|
||||
"ref": "nixos-unstable",
|
||||
"type": "indirect"
|
||||
}
|
||||
},
|
||||
"nixpkgs_5": {
|
||||
"locked": {
|
||||
"lastModified": 1738702386,
|
||||
"narHash": "sha256-nJj8f78AYAxl/zqLiFGXn5Im1qjFKU8yBPKoWEeZN5M=",
|
||||
"owner": "NixOS",
|
||||
"repo": "nixpkgs",
|
||||
"rev": "030ba1976b7c0e1a67d9716b17308ccdab5b381e",
|
||||
"rev": "fabb8c9deee281e50b1065002c9828f2cf7b2239",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "NixOS",
|
||||
"ref": "nixos-24.11",
|
||||
"ref": "nixos-25.11",
|
||||
"repo": "nixpkgs",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"pnpm2nix": {
|
||||
"inputs": {
|
||||
"flake-utils": "flake-utils_2",
|
||||
"flake-utils": "flake-utils_3",
|
||||
"nixpkgs": "nixpkgs_2"
|
||||
},
|
||||
"locked": {
|
||||
@@ -682,25 +669,21 @@
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"pre-commit-hooks-nix": {
|
||||
"pre-commit": {
|
||||
"inputs": {
|
||||
"flake-compat": [
|
||||
"lanzaboote",
|
||||
"flake-compat"
|
||||
],
|
||||
"flake-compat": "flake-compat_2",
|
||||
"gitignore": "gitignore",
|
||||
"nixpkgs": [
|
||||
"lanzaboote",
|
||||
"nixpkgs"
|
||||
],
|
||||
"nixpkgs-stable": "nixpkgs-stable"
|
||||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1731363552,
|
||||
"narHash": "sha256-vFta1uHnD29VUY4HJOO/D6p6rxyObnf+InnSMT4jlMU=",
|
||||
"lastModified": 1771858127,
|
||||
"narHash": "sha256-Gtre9YoYl3n25tJH2AoSdjuwcqij5CPxL3U3xysYD08=",
|
||||
"owner": "cachix",
|
||||
"repo": "pre-commit-hooks.nix",
|
||||
"rev": "cd1af27aa85026ac759d5d3fccf650abe7e1bbf0",
|
||||
"rev": "49bbbfc218bf3856dfa631cead3b052d78248b83",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
@@ -712,25 +695,48 @@
|
||||
"root": {
|
||||
"inputs": {
|
||||
"agenix": "agenix",
|
||||
"auto-cpufreq": "auto-cpufreq",
|
||||
"commander-nvim": "commander-nvim",
|
||||
"colmena": "colmena",
|
||||
"dnote": "dnote",
|
||||
"flake-parts": "flake-parts",
|
||||
"gen-nvim": "gen-nvim",
|
||||
"gtrackmap": "gtrackmap",
|
||||
"hastebin": "hastebin",
|
||||
"home-manager": "home-manager_2",
|
||||
"ketchup": "ketchup",
|
||||
"ksoloti-pr": "ksoloti-pr",
|
||||
"lanzaboote": "lanzaboote",
|
||||
"nextcloud": "nextcloud",
|
||||
"nixos-hardware": "nixos-hardware",
|
||||
"nixpkgs": "nixpkgs_5",
|
||||
"nixpkgs": "nixpkgs_4",
|
||||
"nixpkgs-unstable": "nixpkgs-unstable",
|
||||
"vimpeccable": "vimpeccable",
|
||||
"windline-nvim": "windline-nvim",
|
||||
"router-dash": "router-dash",
|
||||
"syntax-renderer": "syntax-renderer",
|
||||
"tonearm": "tonearm",
|
||||
"turny": "turny",
|
||||
"voidauth": "voidauth",
|
||||
"voxtype": "voxtype",
|
||||
"workout-sync": "workout-sync"
|
||||
}
|
||||
},
|
||||
"router-dash": {
|
||||
"inputs": {
|
||||
"flake-utils": "flake-utils_5",
|
||||
"nixpkgs": [
|
||||
"nixpkgs-unstable"
|
||||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1771795019,
|
||||
"narHash": "sha256-mcGQMNKVUj/CSGXeejzqHEeU+O0ThzKb4pc7pLjUWN0=",
|
||||
"ref": "refs/heads/main",
|
||||
"rev": "ea315d3a527db870a51d23901037a5d1b37f5780",
|
||||
"revCount": 7,
|
||||
"type": "git",
|
||||
"url": "https://git.freun.dev/repomaa/router-dash"
|
||||
},
|
||||
"original": {
|
||||
"type": "git",
|
||||
"url": "https://git.freun.dev/repomaa/router-dash"
|
||||
}
|
||||
},
|
||||
"rust-overlay": {
|
||||
"inputs": {
|
||||
"nixpkgs": [
|
||||
@@ -739,11 +745,11 @@
|
||||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1731897198,
|
||||
"narHash": "sha256-Ou7vLETSKwmE/HRQz4cImXXJBr/k9gp4J4z/PF8LzTE=",
|
||||
"lastModified": 1771988922,
|
||||
"narHash": "sha256-Fc6FHXtfEkLtuVJzd0B6tFYMhmcPLuxr90rWfb/2jtQ=",
|
||||
"owner": "oxalica",
|
||||
"repo": "rust-overlay",
|
||||
"rev": "0be641045af6d8666c11c2c40e45ffc9667839b5",
|
||||
"rev": "f4443dc3f0b6c5e6b77d923156943ce816d1fcb9",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
@@ -752,6 +758,38 @@
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"stable": {
|
||||
"locked": {
|
||||
"lastModified": 1750133334,
|
||||
"narHash": "sha256-urV51uWH7fVnhIvsZIELIYalMYsyr2FCalvlRTzqWRw=",
|
||||
"owner": "NixOS",
|
||||
"repo": "nixpkgs",
|
||||
"rev": "36ab78dab7da2e4e27911007033713bab534187b",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "NixOS",
|
||||
"ref": "nixos-25.05",
|
||||
"repo": "nixpkgs",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"syntax-renderer": {
|
||||
"flake": false,
|
||||
"locked": {
|
||||
"lastModified": 1740962877,
|
||||
"narHash": "sha256-mmGXYerUnxuTqHEWSueLgvkF4pjo1dfIQ+5QtM/JeJY=",
|
||||
"owner": "~repomaa",
|
||||
"repo": "syntax-renderer",
|
||||
"rev": "2ddbeb7583302ae4b2775686c46826fc8a032e6a",
|
||||
"type": "sourcehut"
|
||||
},
|
||||
"original": {
|
||||
"owner": "~repomaa",
|
||||
"repo": "syntax-renderer",
|
||||
"type": "sourcehut"
|
||||
}
|
||||
},
|
||||
"systems": {
|
||||
"locked": {
|
||||
"lastModified": 1681028828,
|
||||
@@ -812,35 +850,135 @@
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"vimpeccable": {
|
||||
"flake": false,
|
||||
"systems_5": {
|
||||
"locked": {
|
||||
"lastModified": 1640723263,
|
||||
"narHash": "sha256-MnEOCb/0wvvcYnTOROmVO8HUge3dWmuweAXdpx1zbXE=",
|
||||
"owner": "svermeulen",
|
||||
"repo": "vimpeccable",
|
||||
"rev": "bd19b2a86a3d4a0ee184412aa3edb7ed57025d56",
|
||||
"lastModified": 1681028828,
|
||||
"narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=",
|
||||
"owner": "nix-systems",
|
||||
"repo": "default",
|
||||
"rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "svermeulen",
|
||||
"repo": "vimpeccable",
|
||||
"owner": "nix-systems",
|
||||
"repo": "default",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"windline-nvim": {
|
||||
"flake": false,
|
||||
"systems_6": {
|
||||
"locked": {
|
||||
"lastModified": 1720754740,
|
||||
"narHash": "sha256-vvekmr4ApAyvsxC/pdqupLBCqkHr9JZ8+jSjYRb+iYM=",
|
||||
"owner": "windwp",
|
||||
"repo": "windline.nvim",
|
||||
"rev": "bef735787bef64697036774eca6418e7a786100b",
|
||||
"lastModified": 1681028828,
|
||||
"narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=",
|
||||
"owner": "nix-systems",
|
||||
"repo": "default",
|
||||
"rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "windwp",
|
||||
"repo": "windline.nvim",
|
||||
"owner": "nix-systems",
|
||||
"repo": "default",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"systems_7": {
|
||||
"locked": {
|
||||
"lastModified": 1681028828,
|
||||
"narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=",
|
||||
"owner": "nix-systems",
|
||||
"repo": "default",
|
||||
"rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "nix-systems",
|
||||
"repo": "default",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"tonearm": {
|
||||
"inputs": {
|
||||
"flake-utils": "flake-utils_6",
|
||||
"nixpkgs": [
|
||||
"nixpkgs"
|
||||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1769118914,
|
||||
"narHash": "sha256-ASM7MVDWxT+BBtcAJ1z8XNjyNdL5E1Kc0miCWIepf+o=",
|
||||
"rev": "68ea2190d1b37f9030b7586d2030f9dc48915a85",
|
||||
"type": "tarball",
|
||||
"url": "https://codeberg.org/api/v1/repos/dergs/Tonearm/archive/68ea2190d1b37f9030b7586d2030f9dc48915a85.tar.gz"
|
||||
},
|
||||
"original": {
|
||||
"type": "tarball",
|
||||
"url": "https://codeberg.org/dergs/Tonearm/archive/v1.0.0.tar.gz"
|
||||
}
|
||||
},
|
||||
"turny": {
|
||||
"inputs": {
|
||||
"flake-parts": [
|
||||
"flake-parts"
|
||||
],
|
||||
"nixpkgs": [
|
||||
"nixpkgs"
|
||||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1752874301,
|
||||
"narHash": "sha256-A6IZz46Lfopm5UhMtFfBDimepEUt9lGwhWoEIEQHsgk=",
|
||||
"owner": "~repomaa",
|
||||
"repo": "turny",
|
||||
"rev": "133c05151e77616c7973c1c1038506b2fdee8eab",
|
||||
"type": "sourcehut"
|
||||
},
|
||||
"original": {
|
||||
"owner": "~repomaa",
|
||||
"repo": "turny",
|
||||
"type": "sourcehut"
|
||||
}
|
||||
},
|
||||
"voidauth": {
|
||||
"inputs": {
|
||||
"flake-parts": [
|
||||
"flake-parts"
|
||||
],
|
||||
"nixpkgs": [
|
||||
"nixpkgs-unstable"
|
||||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1771599016,
|
||||
"narHash": "sha256-dSOaOlixvFB57trGkqqS1MSCEbeBT13S3sfZK3Hz+bs=",
|
||||
"owner": "repomaa",
|
||||
"repo": "voidauth",
|
||||
"rev": "9823e2de56e12f33df8e8eba79c4f9e891d31842",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "repomaa",
|
||||
"ref": "feat/nix-packaging",
|
||||
"repo": "voidauth",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"voxtype": {
|
||||
"inputs": {
|
||||
"flake-utils": "flake-utils_7",
|
||||
"nixpkgs": [
|
||||
"nixpkgs-unstable"
|
||||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1772443545,
|
||||
"narHash": "sha256-oD3lameQXilKcgxQORR2l0+iDbnCO61+mjYD3MEVbuQ=",
|
||||
"owner": "peteonrails",
|
||||
"repo": "voxtype",
|
||||
"rev": "d011f3ff074a6a14c14e75fefb375a408e9e8887",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "peteonrails",
|
||||
"repo": "voxtype",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
@@ -851,11 +989,11 @@
|
||||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1739133791,
|
||||
"narHash": "sha256-NkaMCUtPVDJgjK7JCEhj3XrG26XAFNoVx0eSMO5LDNM=",
|
||||
"lastModified": 1750085642,
|
||||
"narHash": "sha256-u+A06S7VEMBQskn6XhGCWYTiD6XBOPJ5ZzohDaRskbw=",
|
||||
"owner": "~repomaa",
|
||||
"repo": "workout-sync",
|
||||
"rev": "4db627eed1d4903e6a6f5aff9bcde0b647dd77e2",
|
||||
"rev": "6d8941e1e798eb326169f30c185289b8ed6b0702",
|
||||
"type": "sourcehut"
|
||||
},
|
||||
"original": {
|
||||
|
||||
218
flake.nix
218
flake.nix
@@ -2,42 +2,16 @@
|
||||
inputs = {
|
||||
flake-parts.url = "github:hercules-ci/flake-parts";
|
||||
nixpkgs-unstable.url = "github:NixOS/nixpkgs/nixos-unstable";
|
||||
nixpkgs.url = "github:NixOS/nixpkgs/nixos-24.11";
|
||||
nextcloud = {
|
||||
url = "github:onny/nixos-nextcloud-testumgebung";
|
||||
inputs.nixpkgs.follows = "nixpkgs";
|
||||
};
|
||||
nixpkgs.url = "github:NixOS/nixpkgs/nixos-25.11";
|
||||
gtrackmap = {
|
||||
url = "github:gtrackmap/gtrackmap";
|
||||
inputs.nixpkgs.follows = "nixpkgs";
|
||||
};
|
||||
lanzaboote.url = "github:nix-community/lanzaboote";
|
||||
nixos-hardware.url = "github:NixOS/nixos-hardware/master";
|
||||
auto-cpufreq = {
|
||||
url = "github:AdnanHodzic/auto-cpufreq";
|
||||
inputs.nixpkgs.follows = "nixpkgs";
|
||||
};
|
||||
home-manager = {
|
||||
url = "github:nix-community/home-manager/release-24.11";
|
||||
inputs = {
|
||||
nixpkgs.follows = "nixpkgs";
|
||||
};
|
||||
};
|
||||
commander-nvim = {
|
||||
url = "github:FeiyouG/commander.nvim";
|
||||
flake = false;
|
||||
};
|
||||
vimpeccable = {
|
||||
url = "github:svermeulen/vimpeccable";
|
||||
flake = false;
|
||||
};
|
||||
windline-nvim = {
|
||||
url = "github:windwp/windline.nvim";
|
||||
flake = false;
|
||||
};
|
||||
gen-nvim = {
|
||||
url = "github:David-Kunz/gen.nvim";
|
||||
flake = false;
|
||||
url = "github:nix-community/home-manager/release-25.11";
|
||||
inputs.nixpkgs.follows = "nixpkgs";
|
||||
};
|
||||
ketchup = {
|
||||
url = "github:repomaa/ketchup";
|
||||
@@ -56,48 +30,188 @@
|
||||
url = "github:ryantm/agenix";
|
||||
inputs.nixpkgs.follows = "nixpkgs";
|
||||
};
|
||||
dnote = {
|
||||
url = "github:dnote/dnote";
|
||||
flake = false;
|
||||
};
|
||||
outputs = { flake-parts, agenix, nixpkgs, ... }@inputs:
|
||||
colmena = {
|
||||
url = "github:zhaofengli/colmena";
|
||||
inputs.nixpkgs.follows = "nixpkgs";
|
||||
};
|
||||
syntax-renderer = {
|
||||
url = "sourcehut:~repomaa/syntax-renderer";
|
||||
flake = false;
|
||||
};
|
||||
turny = {
|
||||
url = "sourcehut:~repomaa/turny";
|
||||
inputs.flake-parts.follows = "flake-parts";
|
||||
inputs.nixpkgs.follows = "nixpkgs";
|
||||
};
|
||||
tonearm = {
|
||||
url = "https://codeberg.org/dergs/Tonearm/archive/v1.0.0.tar.gz";
|
||||
inputs.nixpkgs.follows = "nixpkgs";
|
||||
};
|
||||
voidauth = {
|
||||
url = "github:repomaa/voidauth/feat/nix-packaging";
|
||||
inputs.nixpkgs.follows = "nixpkgs-unstable";
|
||||
inputs.flake-parts.follows = "flake-parts";
|
||||
};
|
||||
voxtype = {
|
||||
url = "github:peteonrails/voxtype";
|
||||
inputs.nixpkgs.follows = "nixpkgs-unstable";
|
||||
};
|
||||
};
|
||||
outputs =
|
||||
{
|
||||
flake-parts,
|
||||
agenix,
|
||||
nixpkgs,
|
||||
self,
|
||||
colmena,
|
||||
...
|
||||
}@inputs:
|
||||
flake-parts.lib.mkFlake { inherit inputs; } (
|
||||
{ withSystem, ... }:
|
||||
let
|
||||
ssh.publicKeys.yubikey = "ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBLIUkESu5NnBi1M0+ZjYrkp6/rIFuwc3aguspf98jmOydNce6l65cnS3GRzc9oWx4lu11ahi87ZuE+pYV+gaHm4=";
|
||||
specialArgs = { inherit inputs ssh; };
|
||||
inherit (nixpkgs) lib;
|
||||
ssh.publicKeys = {
|
||||
yubikey = "ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBLIUkESu5NnBi1M0+ZjYrkp6/rIFuwc3aguspf98jmOydNce6l65cnS3GRzc9oWx4lu11ahi87ZuE+pYV+gaHm4=";
|
||||
builder = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIFuQaA6JKCOfsfUBI5tzoiYe3tdpLdPfVzeyByx/149C";
|
||||
};
|
||||
specialArgs = { inherit inputs ssh self; };
|
||||
|
||||
in
|
||||
{
|
||||
systems = [ "x86_64-linux" "x86_64-darwin" "aarch64-linux" "aarch64-darwin" ];
|
||||
perSystem = { pkgs, ... }: {
|
||||
systems = [
|
||||
"x86_64-linux"
|
||||
"x86_64-darwin"
|
||||
"aarch64-linux"
|
||||
"aarch64-darwin"
|
||||
];
|
||||
perSystem =
|
||||
{ pkgs, system, ... }:
|
||||
{
|
||||
devShells.default = pkgs.mkShell {
|
||||
packages = with pkgs; [
|
||||
(writeShellScriptBin "switch" ''
|
||||
${nh}/bin/nh os switch .
|
||||
agenix.packages.${system}.default
|
||||
colmena.packages.${system}.colmena
|
||||
colmena.packages.${system}.manual
|
||||
(writeShellScriptBin "build" ''
|
||||
colmena build --keep-result "$@"
|
||||
'')
|
||||
(writeShellScriptBin "deploy" ''
|
||||
${openssh}/bin/ssh -t "$1" nh os switch sourcehut:~repomaa/NixOS -- --option tarball-ttl 0
|
||||
(writeShellScriptBin "apply" ''
|
||||
colmena apply --keep-result "$@"
|
||||
'')
|
||||
(writeShellScriptBin "evaluate" ''
|
||||
${nix}/bin/nix build --dry-run ".#nixosConfigurations.$1.config.system.build.toplevel" | ${nix-output-monitor}/bin/nom
|
||||
(writeShellScriptBin "apply-local" ''
|
||||
nh os switch .
|
||||
'')
|
||||
agenix.packages.${pkgs.system}.default
|
||||
];
|
||||
};
|
||||
};
|
||||
flake.nixosConfigurations = {
|
||||
freun-dev = lib.nixosSystem {
|
||||
flake = {
|
||||
nixosConfigurations =
|
||||
let
|
||||
mkConfiguration =
|
||||
name:
|
||||
nixpkgs.lib.nixosSystem {
|
||||
inherit specialArgs;
|
||||
modules = [ ./modules ./hosts/freun.dev ];
|
||||
modules = [
|
||||
./modules
|
||||
./hosts/${name}
|
||||
];
|
||||
};
|
||||
in
|
||||
{
|
||||
radish = mkConfiguration "radish";
|
||||
freun-dev = mkConfiguration "freun-dev";
|
||||
apu = mkConfiguration "apu";
|
||||
turny = mkConfiguration "turny";
|
||||
};
|
||||
|
||||
radish = lib.nixosSystem {
|
||||
inherit specialArgs;
|
||||
modules = [ ./modules ./hosts/radish ];
|
||||
};
|
||||
images.turny = self.nixosConfigurations.turny.config.system.build.sdImage;
|
||||
|
||||
apu = nixpkgs.lib.nixosSystem {
|
||||
inherit specialArgs;
|
||||
modules = [ ./modules ./hosts/apu ];
|
||||
dockerImages =
|
||||
nixpkgs.lib.genAttrs
|
||||
[
|
||||
"x86_64-linux"
|
||||
"aarch64-linux"
|
||||
]
|
||||
(
|
||||
system:
|
||||
withSystem system (
|
||||
{ pkgs, ... }:
|
||||
{
|
||||
node =
|
||||
let
|
||||
setupDirs = pkgs.runCommand "setup-dirs" { } ''
|
||||
mkdir -p $out/tmp $out/root $out/var/tmp
|
||||
chmod 1777 $out/tmp $out/var/tmp
|
||||
'';
|
||||
in
|
||||
pkgs.dockerTools.buildLayeredImage {
|
||||
name = "node";
|
||||
tag = "latest";
|
||||
contents = with pkgs; [
|
||||
nodejs
|
||||
nix
|
||||
busybox
|
||||
bash
|
||||
skopeo
|
||||
cacert
|
||||
git
|
||||
setupDirs
|
||||
(writeTextFile {
|
||||
name = "etc-nix-nix-conf";
|
||||
destination = "/etc/nix/nix.conf";
|
||||
text = ''
|
||||
build-users-group =
|
||||
experimental-features = nix-command flakes
|
||||
'';
|
||||
})
|
||||
];
|
||||
config = {
|
||||
Env = [
|
||||
"SSL_CERT_FILE=/etc/ssl/certs/ca-bundle.crt"
|
||||
"NODE_EXTRA_CA_CERTS=/etc/ssl/certs/ca-bundle.crt"
|
||||
"HOME=/root"
|
||||
];
|
||||
};
|
||||
};
|
||||
}
|
||||
)
|
||||
);
|
||||
colmenaHive = colmena.lib.makeHive self.outputs.colmena;
|
||||
|
||||
colmena =
|
||||
let
|
||||
deploymentOptions = {
|
||||
freun-dev = {
|
||||
targetHost = "freun.dev";
|
||||
buildOnTarget = true;
|
||||
};
|
||||
radish = {
|
||||
allowLocalDeployment = true;
|
||||
targetHost = null;
|
||||
};
|
||||
turny = {
|
||||
targetHost = "10.10.1.233";
|
||||
};
|
||||
};
|
||||
in
|
||||
{
|
||||
meta = {
|
||||
inherit specialArgs;
|
||||
|
||||
nixpkgs = import nixpkgs {
|
||||
system = "x86_64-linux";
|
||||
overlays = [ ];
|
||||
};
|
||||
};
|
||||
}
|
||||
// builtins.mapAttrs (name: config: {
|
||||
imports = config._module.args.modules;
|
||||
deployment = if builtins.hasAttr name deploymentOptions then deploymentOptions.${name} else { };
|
||||
}) self.nixosConfigurations;
|
||||
};
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,2 +0,0 @@
|
||||
switch:
|
||||
home-manager switch
|
||||
@@ -1,7 +1,25 @@
|
||||
{ config, lib, pkgs, inputs, ... }:
|
||||
{
|
||||
nixpkgs.config.allowUnfree = true;
|
||||
imports = [ ../gnome ../custom-programs ./neovim ];
|
||||
config,
|
||||
osConfig,
|
||||
lib,
|
||||
pkgs,
|
||||
pkgs-unstable,
|
||||
inputs,
|
||||
self,
|
||||
...
|
||||
}:
|
||||
{
|
||||
imports = [
|
||||
../gnome
|
||||
./dnote.nix
|
||||
../modules/zed
|
||||
../modules/voxtype
|
||||
../modules/elephant
|
||||
./secrets.nix
|
||||
inputs.hastebin.nixosModules.hm
|
||||
inputs.agenix.homeManagerModules.default
|
||||
inputs.voxtype.homeManagerModules.default
|
||||
];
|
||||
|
||||
# This value determines the Home Manager release that your configuration is
|
||||
# compatible with. This helps avoid breakage when a new Home Manager release
|
||||
@@ -15,26 +33,26 @@
|
||||
home.packages = with pkgs; [
|
||||
htop
|
||||
gnupg
|
||||
inputs.nixpkgs-unstable.legacyPackages.${pkgs.system}.yubioath-flutter
|
||||
inputs.nixpkgs-unstable.legacyPackages.${pkgs.system}.yubikey-manager
|
||||
pkgs-unstable.yubioath-flutter
|
||||
pkgs-unstable.yubikey-manager
|
||||
gcc
|
||||
sqlite
|
||||
nerdfonts
|
||||
noto-fonts
|
||||
noto-fonts-cjk-sans
|
||||
noto-fonts-color-emoji
|
||||
source-sans-pro
|
||||
mosh
|
||||
docker-compose
|
||||
signal-desktop
|
||||
(signal-desktop.override {
|
||||
commandLineArgs = "--password-store=gnome-libsecret";
|
||||
})
|
||||
cargo
|
||||
blanket
|
||||
wl-clipboard
|
||||
gnumeric
|
||||
gh
|
||||
neovim-remote
|
||||
flameshot
|
||||
supersonic
|
||||
pkgs-unstable.gradia
|
||||
crystal
|
||||
shards
|
||||
moreutils
|
||||
@@ -49,33 +67,145 @@
|
||||
(writeShellScriptBin "fd" ''
|
||||
${fd}/bin/fd -H "$@"
|
||||
'')
|
||||
rpi-imager
|
||||
pkgs-unstable.rpi-imager
|
||||
picocom
|
||||
imagemagick
|
||||
ghostscript
|
||||
inkscape
|
||||
jless
|
||||
qmapshack
|
||||
scribus
|
||||
dnscontrol
|
||||
protonmail-bridge
|
||||
hydroxide
|
||||
protonmail-desktop
|
||||
tutanota-desktop
|
||||
imapsync
|
||||
nixfmt-rfc-style
|
||||
tree
|
||||
virt-manager
|
||||
pkgs-unstable.ncspot
|
||||
pkgs-unstable.devbox
|
||||
pkgs-unstable.feishin
|
||||
openscad
|
||||
pkgs-unstable.shairport-sync-airplay2
|
||||
(writeShellScriptBin "pw" ''
|
||||
${lib.getExe rbw} ls --fields 'id,folder,name' | \
|
||||
${lib.getExe gawk} -F '\t' '{print $1 "\t" ($2 == "" ? "" : $2 "/") $3}' | \
|
||||
${lib.getExe config.services.walker.package} -d -l 2 | \
|
||||
xargs ${lib.getExe rbw} get "$@" | ${lib.getExe' wl-clipboard "wl-copy"}
|
||||
'')
|
||||
(google-fonts.override { fonts = [ "Tajawal" ]; })
|
||||
pkgs-unstable.opencode
|
||||
(writeShellScriptBin "nr" ''
|
||||
${lib.getExe nix} run "nixpkgs#''${1}" "$@"
|
||||
'')
|
||||
pkgs-unstable.tidal-hifi
|
||||
inputs.tonearm.packages.${pkgs.stdenv.hostPlatform.system}.tonearm
|
||||
blueman
|
||||
pavucontrol
|
||||
(writeShellScriptBin "voxtoggle" ''
|
||||
status=$(${lib.getExe config.programs.voxtype.package} status)
|
||||
pid=$(cat ''${XDG_RUNTIME_DIR}/voxtype/pid)
|
||||
|
||||
if [[ "$status" == "stopped" ]]; then
|
||||
exit 1
|
||||
elif [[ "$status" == "recording" ]]; then
|
||||
kill -SIGUSR2 "$pid"
|
||||
else
|
||||
kill -SIGUSR1 "$pid"
|
||||
fi
|
||||
'')
|
||||
];
|
||||
++ lib.optional osConfig.programs.niri.enable (
|
||||
pkgs.writeShellScriptBin "handle-lid-close" ''
|
||||
alias niri=${lib.getExe osConfig.programs.niri.package}
|
||||
|
||||
output_count=$(niri outputs | ${lib.getExe jq} -r 'length')
|
||||
if [ "$output_count" -eq 1 ]; then
|
||||
niri msg action spawn hyprlock
|
||||
systemctl suspend
|
||||
fi
|
||||
''
|
||||
);
|
||||
|
||||
programs = {
|
||||
ashell = {
|
||||
enable = true;
|
||||
package = pkgs-unstable.ashell;
|
||||
systemd = {
|
||||
enable = true;
|
||||
target = "graphical-session.target";
|
||||
};
|
||||
settings = {
|
||||
modules = {
|
||||
left = [ "Workspaces" ];
|
||||
center = [ "WindowTitle" ];
|
||||
right = [
|
||||
"CustomNotifications"
|
||||
"SystemInfo"
|
||||
[
|
||||
"Clock"
|
||||
"Privacy"
|
||||
"Settings"
|
||||
]
|
||||
];
|
||||
};
|
||||
settings = {
|
||||
lock_cmd = "hyprlock &";
|
||||
logout_cmd = "niri msg action quit";
|
||||
audio_sinks_more_cmd = "pavucontrol -t 3";
|
||||
audio_sources_more_cmd = "pavucontrol -t 4";
|
||||
bluetooth_more_cmd = "blueman-manager";
|
||||
CustomButton =
|
||||
let
|
||||
isDark = lib.getExe (
|
||||
pkgs.writeShellScriptBin "is-dark" ''
|
||||
gsettings get org.gnome.desktop.interface color-scheme | grep -q dark
|
||||
''
|
||||
);
|
||||
toggleDark = lib.getExe (
|
||||
pkgs.writeShellScriptBin "toggle-dark" ''
|
||||
if ${isDark}; then
|
||||
gsettings set org.gnome.desktop.interface color-scheme 'prefer-light'
|
||||
else
|
||||
gsettings set org.gnome.desktop.interface color-scheme 'prefer-dark'
|
||||
fi
|
||||
''
|
||||
);
|
||||
in
|
||||
[
|
||||
{
|
||||
name = "Dark Mode";
|
||||
icon = " ";
|
||||
command = toggleDark;
|
||||
status_command = isDark;
|
||||
}
|
||||
];
|
||||
};
|
||||
CustomModule = [
|
||||
{
|
||||
name = "CustomNotifications";
|
||||
type = "Button";
|
||||
icon = " ";
|
||||
command = "swaync-client -t -sw";
|
||||
listen_cmd = "swaync-client -swb";
|
||||
icons."dnd.*" = " ";
|
||||
alert = ".*notification";
|
||||
}
|
||||
];
|
||||
};
|
||||
};
|
||||
|
||||
nh = {
|
||||
enable = true;
|
||||
flake = "/etc/nixos";
|
||||
flake = self;
|
||||
};
|
||||
dnote.enable = true;
|
||||
home-manager.enable = true;
|
||||
bat = {
|
||||
enable = true;
|
||||
extraPackages = with pkgs.bat-extras; [ batdiff batwatch ];
|
||||
extraPackages = with pkgs.bat-extras; [
|
||||
batdiff
|
||||
batwatch
|
||||
];
|
||||
config = {
|
||||
pager = "less -FR";
|
||||
};
|
||||
@@ -94,17 +224,11 @@
|
||||
gpu-context = "wayland";
|
||||
};
|
||||
};
|
||||
fb-client = {
|
||||
enable = true;
|
||||
pastebin = "https://p.jokke.space";
|
||||
clipboard_cmd = "${pkgs.wl-copy-both}/bin/wl-copy";
|
||||
};
|
||||
kitty = {
|
||||
enable = true;
|
||||
font = {
|
||||
package = pkgs.nerdfonts;
|
||||
name = "IosevkaTerm NFM";
|
||||
size = 12;
|
||||
size = 14;
|
||||
};
|
||||
shellIntegration.enableZshIntegration = true;
|
||||
themeFile = "Tomorrow_Night";
|
||||
@@ -145,12 +269,12 @@
|
||||
vivaldi.enable = true;
|
||||
git = {
|
||||
enable = true;
|
||||
aliases = {
|
||||
settings = {
|
||||
alias = {
|
||||
st = "status";
|
||||
co = "checkout";
|
||||
b = "branch";
|
||||
};
|
||||
extraConfig = {
|
||||
pull = {
|
||||
rebase = "true";
|
||||
};
|
||||
@@ -185,11 +309,24 @@
|
||||
save = 100000;
|
||||
size = 100000;
|
||||
};
|
||||
initExtra = ''
|
||||
initContent = ''
|
||||
. "${config.xdg.configHome}/zsh/init"
|
||||
. "${config.age.secrets.context7.path}"
|
||||
'';
|
||||
};
|
||||
lazygit = {
|
||||
lazygit =
|
||||
let
|
||||
getBaseBranch = pkgs.writeShellScriptBin "git-base-branch" ''
|
||||
current_branch="$(git rev-parse --abbrev-ref HEAD)"
|
||||
if [[ "$current_branch" =~ -review$ ]]; then
|
||||
echo "''${current_branch%-review}"
|
||||
else
|
||||
git config get init.defaultBranch
|
||||
fi
|
||||
'';
|
||||
escapeGoTemplate = builtins.replaceStrings [ "{{" "}}" ] [ ''{{"{{"}}'' ''{{"}}"}}'' ];
|
||||
in
|
||||
{
|
||||
enable = true;
|
||||
settings = {
|
||||
gui = {
|
||||
@@ -198,42 +335,93 @@
|
||||
git = {
|
||||
showUntrackedFiles = "all";
|
||||
branchLogCmd = "git log {{branchName}} --first-parent --color=always --pretty=format:'%Cgreen%h%Creset %Cblue%aN%Creset %C(cyan)%<(14)%ar%Creset %s' --abbrev-commit";
|
||||
overrideGpg = true;
|
||||
};
|
||||
os = {
|
||||
edit = "$EDITOR {{filename}}";
|
||||
editAtLine = "$EDITOR +{{line}} {{filename}}";
|
||||
editAtLineAndWait = "$EDITOR --remote-wait +{{line}} {{filename}}";
|
||||
edit = "\${EDITOR} -- {{filename}}";
|
||||
editAtLine = "\${EDITOR} -- {{filename}}:{{line}}";
|
||||
editAtLineAndWait = "\${EDITOR} --wait -- {{filename}}:{{line}}";
|
||||
openDirInEditor = "\${EDITOR} -- {{dir}}";
|
||||
};
|
||||
promptToReturnFromSubprocess = false;
|
||||
keybinding = {
|
||||
universal = {
|
||||
nextItem = "<disabled>";
|
||||
prevItem = "<disabled>";
|
||||
};
|
||||
commits = {
|
||||
moveDownCommit = "<down>";
|
||||
moveUpCommit = "<up>";
|
||||
};
|
||||
};
|
||||
customCommands = [
|
||||
{
|
||||
key = "<c-p>";
|
||||
key = "<c-r>";
|
||||
context = "global";
|
||||
command = ''
|
||||
git push --force-with-lease --set-upstream origin "{{.SelectedLocalBranch.Name}}" &&
|
||||
gh pr create --title "{{.SelectedLocalBranch.Name}}" --fill ||
|
||||
gh pr create --title "{{.SelectedLocalBranch.Name}}" -B "$(${lib.getExe getBaseBranch})" --fill ||
|
||||
(git log --reverse --no-merges --pretty='- %s' master..HEAD | gh pr edit --body-file -);
|
||||
gh pr view --web
|
||||
'';
|
||||
}
|
||||
{
|
||||
key = "N";
|
||||
context = "localBranches";
|
||||
prompts = [
|
||||
{
|
||||
type = "input";
|
||||
title = "New Branch Name:";
|
||||
key = "BranchName";
|
||||
initialValue = "{{.SelectedLocalBranch.Name}}-review";
|
||||
}
|
||||
];
|
||||
command = ''
|
||||
git checkout -b {{.Form.BranchName | quote}}
|
||||
'';
|
||||
}
|
||||
{
|
||||
key = "G";
|
||||
context = "localBranches";
|
||||
prompts = [
|
||||
{
|
||||
type = "menuFromCommand";
|
||||
title = "PR:";
|
||||
key = "pr";
|
||||
command = escapeGoTemplate "gh pr list --search '-author:@me' --json number,title,author,updatedAt -t '{{range .}}{{tablerow .number .title .author.login}}{{end}}'";
|
||||
filter = "(?<pr_number>[0-9]+)(?<rest>.*)";
|
||||
labelFormat = "{{ .rest }}";
|
||||
valueFormat = "{{ .pr_number }}";
|
||||
}
|
||||
];
|
||||
command = ''
|
||||
gh pr checkout {{.Form.pr | quote}}
|
||||
'';
|
||||
}
|
||||
];
|
||||
};
|
||||
};
|
||||
obs-studio.enable = true;
|
||||
ssh = {
|
||||
enable = true;
|
||||
controlMaster = "auto";
|
||||
controlPersist = "1h";
|
||||
enableDefaultConfig = false;
|
||||
matchBlocks = {
|
||||
"*" = {
|
||||
extraOptions = {
|
||||
ControlPath = "${config.home.homeDirectory}/.ssh/masters-control/%r@%h:%p";
|
||||
};
|
||||
controlMaster = "auto";
|
||||
controlPath = "${config.home.homeDirectory}/.ssh/masters-control/%r@%h:%p";
|
||||
controlPersist = "1h";
|
||||
forwardAgent = false;
|
||||
addKeysToAgent = "no";
|
||||
compression = false;
|
||||
serverAliveInterval = 0;
|
||||
serverAliveCountMax = 3;
|
||||
hashKnownHosts = false;
|
||||
userKnownHostsFile = "${config.home.homeDirectory}/.ssh/known_hosts";
|
||||
setEnv = {
|
||||
TERM = "screen-256color";
|
||||
};
|
||||
};
|
||||
"apu" = {
|
||||
hostname = "apu.tempel-vibes.ts.net";
|
||||
user = "root";
|
||||
};
|
||||
};
|
||||
@@ -269,8 +457,13 @@
|
||||
bright_white = "#ffffff";
|
||||
};
|
||||
component_style = {
|
||||
playback_metadata = { fg = "#8abeb7"; };
|
||||
playback_progress_bar = { bg = "#1d1f21"; fg = "#c5c8c6"; };
|
||||
playback_metadata = {
|
||||
fg = "#8abeb7";
|
||||
};
|
||||
playback_progress_bar = {
|
||||
bg = "#1d1f21";
|
||||
fg = "#c5c8c6";
|
||||
};
|
||||
};
|
||||
}
|
||||
];
|
||||
@@ -285,6 +478,126 @@
|
||||
fork = true;
|
||||
};
|
||||
};
|
||||
hastebin = {
|
||||
enable = true;
|
||||
settings = {
|
||||
host = "https://bin.freun.dev";
|
||||
auth_token_file = "${config.xdg.configHome}/hastebin/auth_token";
|
||||
clipboard_command = "${pkgs.wl-copy-both}/bin/wl-copy";
|
||||
default_renderers =
|
||||
let
|
||||
code = [
|
||||
"js"
|
||||
"ts"
|
||||
"jsx"
|
||||
"tsx"
|
||||
"rs"
|
||||
"nix"
|
||||
"cr"
|
||||
"ecr"
|
||||
"rb"
|
||||
"erb"
|
||||
"yaml"
|
||||
"yml"
|
||||
"json"
|
||||
"toml"
|
||||
"html"
|
||||
"xml"
|
||||
"css"
|
||||
"scss"
|
||||
"sass"
|
||||
"less"
|
||||
"sql"
|
||||
"sh"
|
||||
];
|
||||
in
|
||||
lib.listToAttrs (
|
||||
lib.map (name: {
|
||||
inherit name;
|
||||
value = "hl";
|
||||
}) code
|
||||
);
|
||||
};
|
||||
};
|
||||
zed-editor = {
|
||||
enable = true;
|
||||
defaultEditor = true;
|
||||
};
|
||||
hyprlock = {
|
||||
enable = true;
|
||||
package = pkgs-unstable.hyprlock;
|
||||
settings = {
|
||||
general = {
|
||||
hide_cursor = true;
|
||||
ignore_empty_input = true;
|
||||
};
|
||||
background = {
|
||||
monitor = "";
|
||||
path = "screenshot";
|
||||
blur_passes = 3;
|
||||
};
|
||||
input-field = {
|
||||
size = "20%, 5%";
|
||||
monitor = "";
|
||||
dots_center = true;
|
||||
fade_on_empty = false;
|
||||
rounding = 15;
|
||||
shadow_passes = 2;
|
||||
outline_thickness = 2;
|
||||
placeholder_text = "Password...";
|
||||
fail_text = "$PAMFAIL";
|
||||
dots_spacing = "0.3";
|
||||
position = "0, -20";
|
||||
halign = "center";
|
||||
valign = "center";
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
voxtype = {
|
||||
enable = true;
|
||||
package = inputs.voxtype.packages.${pkgs.stdenv.hostPlatform.system}.vulkan;
|
||||
model.name = "large-v3-turbo";
|
||||
service.enable = true;
|
||||
settings = {
|
||||
hotkey.enabled = false;
|
||||
whisper.language = "auto";
|
||||
output.notification = {
|
||||
on_recording_start = false;
|
||||
on_recording_stop = false;
|
||||
on_transcription = false;
|
||||
};
|
||||
};
|
||||
postProcessing = {
|
||||
enable = true;
|
||||
settings = {
|
||||
model = "qwen3:4b-instruct";
|
||||
commonInstructions = "no quotes, no emojis, no explanations";
|
||||
prompts = [
|
||||
{
|
||||
title = "Clean up";
|
||||
instructions = "Clean up this dictation. Remove filler words, fix grammar and punctuation. Output ONLY the cleaned text";
|
||||
}
|
||||
{
|
||||
title = "Make a title";
|
||||
instructions = "Make a concise and descriptive title for this dictation. Output ONLY the title";
|
||||
}
|
||||
{
|
||||
title = "Summarize";
|
||||
instructions = "Summarize this dictation in a few sentences. Output ONLY the summary";
|
||||
}
|
||||
{
|
||||
title = "Commit message";
|
||||
instructions = "Write a concise and descriptive git commit message for this dictation. Output ONLY the commit message";
|
||||
}
|
||||
{
|
||||
title = "Translate to English";
|
||||
instructions = "Translate this dictation to English. Remove filler words, fix grammar and punctuation. Output ONLY the translation";
|
||||
}
|
||||
];
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
gnome = {
|
||||
@@ -297,8 +610,8 @@
|
||||
custom = [
|
||||
{
|
||||
binding = "Print";
|
||||
command = "flameshot gui";
|
||||
name = "Flameshot";
|
||||
command = "gradia --screenshot";
|
||||
name = "Gradia";
|
||||
}
|
||||
{
|
||||
binding = "<Alt>Print";
|
||||
@@ -314,23 +627,68 @@
|
||||
paperwm = {
|
||||
enable = true;
|
||||
winprops = [
|
||||
{ wm_class = "vivaldi-stable"; preferredWidth = "67%"; }
|
||||
{ wm_class = "yubioath-flutter"; scratch_layer = true; }
|
||||
{ wm_class = "signal"; scratch_layer = true; }
|
||||
{ wm_class = "Slack"; scratch_layer = true; }
|
||||
{ wm_class = "Supersonic"; scratch_layer = true; }
|
||||
{ wm_class = "io.github.seadve.Kooha"; scratch_layer = true; }
|
||||
{ wm_class = "/.*/"; preferredWidth = "33"; }
|
||||
{
|
||||
wm_class = "vivaldi-stable";
|
||||
preferredWidth = "67%";
|
||||
}
|
||||
{
|
||||
wm_class = "yubioath-flutter";
|
||||
scratch_layer = true;
|
||||
}
|
||||
{
|
||||
wm_class = "signal";
|
||||
scratch_layer = true;
|
||||
}
|
||||
{
|
||||
wm_class = "Slack";
|
||||
scratch_layer = true;
|
||||
}
|
||||
{
|
||||
wm_class = "Supersonic";
|
||||
scratch_layer = true;
|
||||
}
|
||||
{
|
||||
wm_class = "io.github.seadve.Kooha";
|
||||
scratch_layer = true;
|
||||
}
|
||||
{
|
||||
wm_class = "/.*/";
|
||||
preferredWidth = "33";
|
||||
}
|
||||
];
|
||||
keybindings = {
|
||||
move-down = [ "<Control><Super>Down" "<Shift><Super>j" ];
|
||||
move-left = [ "<Control><Super>Left" "<Shift><Super>h" ];
|
||||
move-right = [ "<Control><Super>Right" "<Shift><Super>l" ];
|
||||
move-up = [ "<Control><Super>Up" "<Shift><Super>k" ];
|
||||
switch-down = [ "<Super>Down" "<Super>j" ];
|
||||
switch-left = [ "<Super>Left" "<Super>h" ];
|
||||
switch-right = [ "<Super>Right" "<Super>l" ];
|
||||
switch-up = [ "<Super>Up" "<Super>k" ];
|
||||
move-down = [
|
||||
"<Control><Super>Down"
|
||||
"<Shift><Super>j"
|
||||
];
|
||||
move-left = [
|
||||
"<Control><Super>Left"
|
||||
"<Shift><Super>h"
|
||||
];
|
||||
move-right = [
|
||||
"<Control><Super>Right"
|
||||
"<Shift><Super>l"
|
||||
];
|
||||
move-up = [
|
||||
"<Control><Super>Up"
|
||||
"<Shift><Super>k"
|
||||
];
|
||||
switch-down = [
|
||||
"<Super>Down"
|
||||
"<Super>j"
|
||||
];
|
||||
switch-left = [
|
||||
"<Super>Left"
|
||||
"<Super>h"
|
||||
];
|
||||
switch-right = [
|
||||
"<Super>Right"
|
||||
"<Super>l"
|
||||
];
|
||||
switch-up = [
|
||||
"<Super>Up"
|
||||
"<Super>k"
|
||||
];
|
||||
};
|
||||
};
|
||||
freon = {
|
||||
@@ -387,7 +745,8 @@
|
||||
#
|
||||
# /etc/profiles/per-user/jokke/etc/profile.d/hm-session-vars.sh
|
||||
#
|
||||
systemd.user.sessionVariables = {
|
||||
|
||||
home.sessionVariables = {
|
||||
NIXOS_OZONE_WL = 1;
|
||||
NVIM_LISTEN_ADDRESS = "$XDG_RUNTIME_DIR/nvimsocket";
|
||||
PAGER = "bat --paging=always --style=plain";
|
||||
@@ -396,6 +755,9 @@
|
||||
DO_NOT_TRACK = 1;
|
||||
};
|
||||
|
||||
systemd.user.sessionVariables = lib.mapAttrs (_: v: toString v) config.home.sessionVariables;
|
||||
programs.zsh.sessionVariables = config.home.sessionVariables;
|
||||
|
||||
home.shellAliases = {
|
||||
_ = "sudo";
|
||||
icr = "crystal i";
|
||||
@@ -406,20 +768,202 @@
|
||||
ls = "ls --color=auto";
|
||||
};
|
||||
|
||||
services.gpg-agent = with pkgs; {
|
||||
services = {
|
||||
swaync = {
|
||||
enable = true;
|
||||
package = pkgs-unstable.swaynotificationcenter;
|
||||
settings = {
|
||||
scripts = {
|
||||
focus-window =
|
||||
let
|
||||
jq = lib.getExe pkgs.jq;
|
||||
niri = lib.getExe osConfig.programs.niri.package;
|
||||
script = pkgs.writeShellScriptBin "swaync-focus-window" ''
|
||||
set -e
|
||||
|
||||
APP_NAME="''${SWAYNC_APP_NAME:-}"
|
||||
DESKTOP_ENTRY="''${SWAYNC_DESKTOP_ENTRY:-}"
|
||||
|
||||
APP_ID=""
|
||||
if [[ -n "$DESKTOP_ENTRY" ]]; then
|
||||
APP_ID="$DESKTOP_ENTRY"
|
||||
elif [[ -n "$APP_NAME" ]]; then
|
||||
APP_ID=$(echo "$APP_NAME" | tr '[:upper:]' '[:lower:]' | sed 's/ //g')
|
||||
fi
|
||||
|
||||
[[ -z "$APP_ID" ]] && exit
|
||||
|
||||
# Find window ID for this app in niri and focus it
|
||||
${jq} -r --arg app_id "$APP_ID" '.[] | select(.app_id | ascii_downcase | contains($app_id)) | .id' \
|
||||
<(${niri} msg --json windows 2>/dev/null) | head -n1 | while read -r WINDOW_ID; do
|
||||
if [[ -n "$WINDOW_ID" && "$WINDOW_ID" != "null" ]]; then
|
||||
${niri} msg action focus-window --id "$WINDOW_ID"
|
||||
fi
|
||||
done
|
||||
'';
|
||||
in
|
||||
{
|
||||
exec = lib.getExe script;
|
||||
run-on = "action";
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
gpg-agent = with pkgs; {
|
||||
enable = true;
|
||||
enableSshSupport = true;
|
||||
pinentryPackage = pinentry-gnome3;
|
||||
pinentry.package = pinentry-gnome3;
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
services.walker = {
|
||||
enable = true;
|
||||
package = pkgs.symlinkJoin {
|
||||
inherit (pkgs-unstable.walker) name meta;
|
||||
paths = [ pkgs-unstable.walker ];
|
||||
nativeBuildInputs = [ pkgs.makeBinaryWrapper ];
|
||||
postBuild = ''
|
||||
wrapProgram $out/bin/walker \
|
||||
--prefix PATH : ${lib.makeBinPath [ config.services.elephant.package ]}
|
||||
'';
|
||||
};
|
||||
systemd = {
|
||||
enable = true;
|
||||
};
|
||||
settings = {
|
||||
providers = {
|
||||
default = [
|
||||
"desktopapplications"
|
||||
"calc"
|
||||
"websearch"
|
||||
"bitwarden"
|
||||
];
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
services.elephant.enable = true;
|
||||
|
||||
systemd.user.services.walker.Install.WantedBy = lib.mkForce [ "graphical-session.target" ];
|
||||
|
||||
systemd.user.services.shairport-sync = {
|
||||
Unit = {
|
||||
Description = "AirPlay audio server";
|
||||
After = [
|
||||
"pipewire-pulse.service"
|
||||
"network.target"
|
||||
];
|
||||
};
|
||||
Service = {
|
||||
ExecStart = "${lib.getExe pkgs-unstable.shairport-sync-airplay2} -- pw";
|
||||
Restart = "on-failure";
|
||||
};
|
||||
Install = {
|
||||
WantedBy = [ "graphical-session.target" ];
|
||||
};
|
||||
};
|
||||
|
||||
programs.gpg.scdaemonSettings = {
|
||||
disable-ccid = true;
|
||||
};
|
||||
|
||||
xdg.configFile."autostart/gnome-keyring-ssh.desktop".text = lib.strings.concatLines [
|
||||
(builtins.readFile "${pkgs.gnome-keyring}/etc/xdg/autostart/gnome-keyring-ssh.desktop")
|
||||
"X-GNOME-Autostart-enabled=false"
|
||||
programs.rbw.enable = true;
|
||||
programs.rclone.enable = true;
|
||||
programs.firefox.enable = true;
|
||||
|
||||
xdg.configFile."opencode/opencode.jsonc".text = builtins.toJSON {
|
||||
"$schema" = "https://opencode.ai/config.json";
|
||||
model = "opencode-go/glm-5";
|
||||
small_model = "opencode-go/kimi-k2.5";
|
||||
agent = {
|
||||
explore.model = "opencode-go/kimi-k2.5";
|
||||
};
|
||||
theme = "system";
|
||||
lsp = {
|
||||
ruby-lsp = {
|
||||
initialization = {
|
||||
enabledFeatures = {
|
||||
codeActions = true;
|
||||
codeLens = true;
|
||||
completion = true;
|
||||
definition = true;
|
||||
diagnostics = true;
|
||||
documentHighlights = true;
|
||||
documentLink = true;
|
||||
documentSymbols = true;
|
||||
foldingRanges = true;
|
||||
formatting = false;
|
||||
hover = true;
|
||||
inlayHint = true;
|
||||
onTypeFormatting = true;
|
||||
selectionRanges = true;
|
||||
semanticHighlighting = true;
|
||||
signatureHelp = true;
|
||||
typeHierarchy = true;
|
||||
workspaceSymbol = true;
|
||||
};
|
||||
linters = [ "standard" ];
|
||||
};
|
||||
extensions = [
|
||||
".rb"
|
||||
".erb"
|
||||
".haml"
|
||||
];
|
||||
command = [
|
||||
"bundle"
|
||||
"exec"
|
||||
"ruby-lsp"
|
||||
];
|
||||
};
|
||||
rubocop = {
|
||||
command = [
|
||||
"bundle"
|
||||
"exec"
|
||||
"rubocop"
|
||||
"--lsp"
|
||||
];
|
||||
extensions = [
|
||||
".rb"
|
||||
".erb"
|
||||
".haml"
|
||||
];
|
||||
};
|
||||
nil = {
|
||||
command = [
|
||||
(lib.getExe pkgs.nil)
|
||||
];
|
||||
extensions = [ ".nix" ];
|
||||
};
|
||||
ameba-ls = {
|
||||
command = [
|
||||
(lib.getExe pkgs-unstable.ameba-ls)
|
||||
];
|
||||
extensions = [ ".cr" ];
|
||||
};
|
||||
};
|
||||
mcp = {
|
||||
context7 = {
|
||||
type = "remote";
|
||||
url = "https://mcp.context7.com/mcp";
|
||||
headers = {
|
||||
CONTEXT7_API_KEY = "{env:CONTEXT7_API_KEY}";
|
||||
};
|
||||
enabled = true;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
xdg.configFile."niri/config.kdl".source = ./dotfiles/niri.kdl;
|
||||
|
||||
gnome.automaticTimeZone = true;
|
||||
gtk.enable = true;
|
||||
|
||||
home.pointerCursor = {
|
||||
enable = true;
|
||||
name = "Adwaita";
|
||||
package = pkgs.adwaita-icon-theme;
|
||||
gtk.enable = true;
|
||||
};
|
||||
}
|
||||
|
||||
44
home/common/dnote.nix
Normal file
44
home/common/dnote.nix
Normal file
@@ -0,0 +1,44 @@
|
||||
{
|
||||
inputs,
|
||||
lib,
|
||||
pkgs,
|
||||
pkgs-unstable,
|
||||
config,
|
||||
...
|
||||
}:
|
||||
let
|
||||
completion = pkgs.stdenv.mkDerivation {
|
||||
name = "dnote-completion";
|
||||
phases = [
|
||||
"unpackPhase"
|
||||
"installPhase"
|
||||
];
|
||||
src = inputs.dnote;
|
||||
installPhase = ''
|
||||
mkdir -p $out/lib/dnote/zsh-completion/completions
|
||||
cp pkg/cli/dnote-completion.zsh $out/lib/dnote/zsh-completion/completions/_dnote
|
||||
'';
|
||||
};
|
||||
client = pkgs.stdenv.mkDerivation {
|
||||
name = "dnote-client";
|
||||
phases = [ "installPhase" ];
|
||||
installPhase = ''
|
||||
mkdir -p $out/bin
|
||||
cp ${pkgs-unstable.dnote}/bin/dnote-cli $out/bin/dnote
|
||||
'';
|
||||
};
|
||||
cfg = config.programs.dnote;
|
||||
in
|
||||
{
|
||||
options.programs.dnote = {
|
||||
enable = pkgs.lib.mkEnableOption "Enable dnote";
|
||||
};
|
||||
|
||||
config = lib.mkIf cfg.enable {
|
||||
home.packages = [ client ];
|
||||
home.shellAliases.dn = "dnote";
|
||||
programs.zsh.initContent = ''
|
||||
fpath=(${completion}/lib/dnote/zsh-completion/completions $fpath)
|
||||
'';
|
||||
};
|
||||
}
|
||||
641
home/common/dotfiles/niri.kdl
Normal file
641
home/common/dotfiles/niri.kdl
Normal file
@@ -0,0 +1,641 @@
|
||||
// This config is in the KDL format: https://kdl.dev
|
||||
// "/-" comments out the following node.
|
||||
// Check the wiki for a full description of the configuration:
|
||||
// https://niri-wm.github.io/niri/Configuration:-Introduction
|
||||
|
||||
// Input device configuration.
|
||||
// Find the full list of options on the wiki:
|
||||
// https://niri-wm.github.io/niri/Configuration:-Input
|
||||
input {
|
||||
keyboard {
|
||||
xkb {
|
||||
// You can set rules, model, layout, variant and options.
|
||||
// For more information, see xkeyboard-config(7).
|
||||
|
||||
layout "us"
|
||||
variant "altgr-intl"
|
||||
// For example:
|
||||
// layout "us,ru"
|
||||
// options "grp:win_space_toggle,compose:ralt,ctrl:nocaps"
|
||||
|
||||
// If this section is empty, niri will fetch xkb settings
|
||||
// from org.freedesktop.locale1. You can control these using
|
||||
// localectl set-x11-keymap.
|
||||
}
|
||||
|
||||
// Enable numlock on startup, omitting this setting disables it.
|
||||
numlock
|
||||
}
|
||||
|
||||
// Next sections include libinput settings.
|
||||
// Omitting settings disables them, or leaves them at their default values.
|
||||
// All commented-out settings here are examples, not defaults.
|
||||
touchpad {
|
||||
// off
|
||||
tap
|
||||
dwt
|
||||
dwtp
|
||||
// drag false
|
||||
// drag-lock
|
||||
natural-scroll
|
||||
// accel-speed 0.2
|
||||
// accel-profile "flat"
|
||||
// scroll-method "two-finger"
|
||||
// disabled-on-external-mouse
|
||||
}
|
||||
|
||||
mouse {
|
||||
// off
|
||||
// natural-scroll
|
||||
// accel-speed 0.2
|
||||
// accel-profile "flat"
|
||||
// scroll-method "no-scroll"
|
||||
}
|
||||
|
||||
trackpoint {
|
||||
// off
|
||||
// natural-scroll
|
||||
// accel-speed 0.2
|
||||
// accel-profile "flat"
|
||||
// scroll-method "on-button-down"
|
||||
// scroll-button 273
|
||||
// scroll-button-lock
|
||||
// middle-emulation
|
||||
}
|
||||
|
||||
// Uncomment this to make the mouse warp to the center of newly focused windows.
|
||||
// warp-mouse-to-focus
|
||||
|
||||
// Focus windows and outputs automatically when moving the mouse into them.
|
||||
// Setting max-scroll-amount="0%" makes it work only on windows already fully on screen.
|
||||
focus-follows-mouse max-scroll-amount="10%"
|
||||
}
|
||||
|
||||
// You can configure outputs by their name, which you can find
|
||||
// by running `niri msg outputs` while inside a niri instance.
|
||||
// The built-in laptop monitor is usually called "eDP-1".
|
||||
// Find more information on the wiki:
|
||||
// https://niri-wm.github.io/niri/Configuration:-Outputs
|
||||
// Remember to uncomment the node by removing "/-"!
|
||||
output "eDP-1" {
|
||||
// Uncomment this line to disable this output.
|
||||
// off
|
||||
|
||||
// Resolution and, optionally, refresh rate of the output.
|
||||
// The format is "<width>x<height>" or "<width>x<height>@<refresh rate>".
|
||||
// If the refresh rate is omitted, niri will pick the highest refresh rate
|
||||
// for the resolution.
|
||||
// If the mode is omitted altogether or is invalid, niri will pick one automatically.
|
||||
// Run `niri msg outputs` while inside a niri instance to list all outputs and their modes.
|
||||
// mode "1920x1080@120.030"
|
||||
|
||||
// You can use integer or fractional scale, for example use 1.5 for 150% scale.
|
||||
scale 1.5
|
||||
|
||||
// Transform allows to rotate the output counter-clockwise, valid values are:
|
||||
// normal, 90, 180, 270, flipped, flipped-90, flipped-180 and flipped-270.
|
||||
// transform "normal"
|
||||
|
||||
// Position of the output in the global coordinate space.
|
||||
// This affects directional monitor actions like "focus-monitor-left", and cursor movement.
|
||||
// The cursor can only move between directly adjacent outputs.
|
||||
// Output scale and rotation has to be taken into account for positioning:
|
||||
// outputs are sized in logical, or scaled, pixels.
|
||||
// For example, a 3840×2160 output with scale 2.0 will have a logical size of 1920×1080,
|
||||
// so to put another output directly adjacent to it on the right, set its x to 1920.
|
||||
// If the position is unset or results in an overlap, the output is instead placed
|
||||
// automatically.
|
||||
// position x=1280 y=0
|
||||
}
|
||||
|
||||
output "DP-5" {
|
||||
scale 1
|
||||
}
|
||||
|
||||
output "DP-3" {
|
||||
scale 1.2
|
||||
}
|
||||
|
||||
// Settings that influence how windows are positioned and sized.
|
||||
// Find more information on the wiki:
|
||||
// https://niri-wm.github.io/niri/Configuration:-Layout
|
||||
layout {
|
||||
// Set gaps around windows in logical pixels.
|
||||
gaps 5
|
||||
|
||||
// When to center a column when changing focus, options are:
|
||||
// - "never", default behavior, focusing an off-screen column will keep at the left
|
||||
// or right edge of the screen.
|
||||
// - "always", the focused column will always be centered.
|
||||
// - "on-overflow", focusing a column will center it if it doesn't fit
|
||||
// together with the previously focused column.
|
||||
center-focused-column "never"
|
||||
|
||||
// You can customize the widths that "switch-preset-column-width" (Mod+R) toggles between.
|
||||
preset-column-widths {
|
||||
// Proportion sets the width as a fraction of the output width, taking gaps into account.
|
||||
// For example, you can perfectly fit four windows sized "proportion 0.25" on an output.
|
||||
// The default preset widths are 1/3, 1/2 and 2/3 of the output.
|
||||
proportion 0.33333
|
||||
proportion 0.5
|
||||
proportion 0.66667
|
||||
|
||||
// Fixed sets the width in logical pixels exactly.
|
||||
// fixed 1920
|
||||
}
|
||||
|
||||
// You can also customize the heights that "switch-preset-window-height" (Mod+Shift+R) toggles between.
|
||||
// preset-window-heights { }
|
||||
|
||||
// You can change the default width of the new windows.
|
||||
default-column-width { proportion 0.5; }
|
||||
// If you leave the brackets empty, the windows themselves will decide their initial width.
|
||||
// default-column-width {}
|
||||
|
||||
// By default focus ring and border are rendered as a solid background rectangle
|
||||
// behind windows. That is, they will show up through semitransparent windows.
|
||||
// This is because windows using client-side decorations can have an arbitrary shape.
|
||||
//
|
||||
// If you don't like that, you should uncomment `prefer-no-csd` below.
|
||||
// Niri will draw focus ring and border *around* windows that agree to omit their
|
||||
// client-side decorations.
|
||||
//
|
||||
// Alternatively, you can override it with a window rule called
|
||||
// `draw-border-with-background`.
|
||||
|
||||
// You can change how the focus ring looks.
|
||||
focus-ring {
|
||||
// Uncomment this line to disable the focus ring.
|
||||
// off
|
||||
|
||||
// How many logical pixels the ring extends out from the windows.
|
||||
width 4
|
||||
|
||||
// Colors can be set in a variety of ways:
|
||||
// - CSS named colors: "red"
|
||||
// - RGB hex: "#rgb", "#rgba", "#rrggbb", "#rrggbbaa"
|
||||
// - CSS-like notation: "rgb(255, 127, 0)", rgba(), hsl() and a few others.
|
||||
|
||||
// Color of the ring on the active monitor.
|
||||
active-color "#7fc8ff"
|
||||
|
||||
// Color of the ring on inactive monitors.
|
||||
//
|
||||
// The focus ring only draws around the active window, so the only place
|
||||
// where you can see its inactive-color is on other monitors.
|
||||
inactive-color "#505050"
|
||||
|
||||
// You can also use gradients. They take precedence over solid colors.
|
||||
// Gradients are rendered the same as CSS linear-gradient(angle, from, to).
|
||||
// The angle is the same as in linear-gradient, and is optional,
|
||||
// defaulting to 180 (top-to-bottom gradient).
|
||||
// You can use any CSS linear-gradient tool on the web to set these up.
|
||||
// Changing the color space is also supported, check the wiki for more info.
|
||||
//
|
||||
// active-gradient from="#80c8ff" to="#c7ff7f" angle=45
|
||||
|
||||
// You can also color the gradient relative to the entire view
|
||||
// of the workspace, rather than relative to just the window itself.
|
||||
// To do that, set relative-to="workspace-view".
|
||||
//
|
||||
// inactive-gradient from="#505050" to="#808080" angle=45 relative-to="workspace-view"
|
||||
}
|
||||
|
||||
// You can also add a border. It's similar to the focus ring, but always visible.
|
||||
border {
|
||||
// The settings are the same as for the focus ring.
|
||||
// If you enable the border, you probably want to disable the focus ring.
|
||||
off
|
||||
|
||||
width 4
|
||||
active-color "#ffc87f"
|
||||
inactive-color "#505050"
|
||||
|
||||
// Color of the border around windows that request your attention.
|
||||
urgent-color "#9b0000"
|
||||
|
||||
// Gradients can use a few different interpolation color spaces.
|
||||
// For example, this is a pastel rainbow gradient via in="oklch longer hue".
|
||||
//
|
||||
// active-gradient from="#e5989b" to="#ffb4a2" angle=45 relative-to="workspace-view" in="oklch longer hue"
|
||||
|
||||
// inactive-gradient from="#505050" to="#808080" angle=45 relative-to="workspace-view"
|
||||
}
|
||||
|
||||
// You can enable drop shadows for windows.
|
||||
shadow {
|
||||
// Uncomment the next line to enable shadows.
|
||||
// on
|
||||
|
||||
// By default, the shadow draws only around its window, and not behind it.
|
||||
// Uncomment this setting to make the shadow draw behind its window.
|
||||
//
|
||||
// Note that niri has no way of knowing about the CSD window corner
|
||||
// radius. It has to assume that windows have square corners, leading to
|
||||
// shadow artifacts inside the CSD rounded corners. This setting fixes
|
||||
// those artifacts.
|
||||
//
|
||||
// However, instead you may want to set prefer-no-csd and/or
|
||||
// geometry-corner-radius. Then, niri will know the corner radius and
|
||||
// draw the shadow correctly, without having to draw it behind the
|
||||
// window. These will also remove client-side shadows if the window
|
||||
// draws any.
|
||||
//
|
||||
// draw-behind-window true
|
||||
|
||||
// You can change how shadows look. The values below are in logical
|
||||
// pixels and match the CSS box-shadow properties.
|
||||
|
||||
// Softness controls the shadow blur radius.
|
||||
softness 30
|
||||
|
||||
// Spread expands the shadow.
|
||||
spread 5
|
||||
|
||||
// Offset moves the shadow relative to the window.
|
||||
offset x=0 y=5
|
||||
|
||||
// You can also change the shadow color and opacity.
|
||||
color "#0007"
|
||||
}
|
||||
|
||||
// Struts shrink the area occupied by windows, similarly to layer-shell panels.
|
||||
// You can think of them as a kind of outer gaps. They are set in logical pixels.
|
||||
// Left and right struts will cause the next window to the side to always be visible.
|
||||
// Top and bottom struts will simply add outer gaps in addition to the area occupied by
|
||||
// layer-shell panels and regular gaps.
|
||||
struts {
|
||||
// left 64
|
||||
// right 64
|
||||
// top 64
|
||||
// bottom 64
|
||||
}
|
||||
}
|
||||
|
||||
// Add lines like this to spawn processes at startup.
|
||||
// Note that running niri as a session supports xdg-desktop-autostart,
|
||||
// which may be more convenient to use.
|
||||
// See the binds section below for more spawn examples.
|
||||
|
||||
//spawn-at-startup "systemctl start --user niri-session.target"
|
||||
|
||||
// To run a shell command (with variables, pipes, etc.), use spawn-sh-at-startup:
|
||||
// spawn-sh-at-startup "qs -c ~/source/qs/MyAwesomeShell"
|
||||
|
||||
hotkey-overlay {
|
||||
// Uncomment this line to disable the "Important Hotkeys" pop-up at startup.
|
||||
skip-at-startup
|
||||
}
|
||||
|
||||
// Uncomment this line to ask the clients to omit their client-side decorations if possible.
|
||||
// If the client will specifically ask for CSD, the request will be honored.
|
||||
// Additionally, clients will be informed that they are tiled, removing some client-side rounded corners.
|
||||
// This option will also fix border/focus ring drawing behind some semitransparent windows.
|
||||
// After enabling or disabling this, you need to restart the apps for this to take effect.
|
||||
// prefer-no-csd
|
||||
|
||||
// You can change the path where screenshots are saved.
|
||||
// A ~ at the front will be expanded to the home directory.
|
||||
// The path is formatted with strftime(3) to give you the screenshot date and time.
|
||||
screenshot-path "~/Pictures/Screenshots/Screenshot from %Y-%m-%d %H-%M-%S.png"
|
||||
|
||||
// You can also set this to null to disable saving screenshots to disk.
|
||||
// screenshot-path null
|
||||
|
||||
// Animation settings.
|
||||
// The wiki explains how to configure individual animations:
|
||||
// https://niri-wm.github.io/niri/Configuration:-Animations
|
||||
animations {
|
||||
// Uncomment to turn off all animations.
|
||||
// off
|
||||
|
||||
// Slow down all animations by this factor. Values below 1 speed them up instead.
|
||||
// slowdown 3.0
|
||||
}
|
||||
|
||||
// Window rules let you adjust behavior for individual windows.
|
||||
// Find more information on the wiki:
|
||||
// https://niri-wm.github.io/niri/Configuration:-Window-Rules
|
||||
|
||||
// Work around WezTerm's initial configure bug
|
||||
// by setting an empty default-column-width.
|
||||
window-rule {
|
||||
// This regular expression is intentionally made as specific as possible,
|
||||
// since this is the default config, and we want no false positives.
|
||||
// You can get away with just app-id="wezterm" if you want.
|
||||
match app-id=r#"^org\.wezfurlong\.wezterm$"#
|
||||
default-column-width {}
|
||||
}
|
||||
|
||||
// Open the Firefox picture-in-picture player as floating by default.
|
||||
window-rule {
|
||||
// This app-id regular expression will work for both:
|
||||
// - host Firefox (app-id is "firefox")
|
||||
// - Flatpak Firefox (app-id is "org.mozilla.firefox")
|
||||
match app-id=r#"firefox$"# title="^Picture-in-Picture$"
|
||||
open-floating true
|
||||
}
|
||||
|
||||
// Example: block out two password managers from screen capture.
|
||||
// (This example rule is commented out with a "/-" in front.)
|
||||
/-window-rule {
|
||||
match app-id=r#"^org\.keepassxc\.KeePassXC$"#
|
||||
match app-id=r#"^org\.gnome\.World\.Secrets$"#
|
||||
|
||||
block-out-from "screen-capture"
|
||||
|
||||
// Use this instead if you want them visible on third-party screenshot tools.
|
||||
// block-out-from "screencast"
|
||||
}
|
||||
|
||||
// Example: enable rounded corners for all windows.
|
||||
// (This example rule is commented out with a "/-" in front.)
|
||||
window-rule {
|
||||
geometry-corner-radius 14
|
||||
clip-to-geometry true
|
||||
}
|
||||
|
||||
binds {
|
||||
// Keys consist of modifiers separated by + signs, followed by an XKB key name
|
||||
// in the end. To find an XKB name for a particular key, you may use a program
|
||||
// like wev.
|
||||
//
|
||||
// "Mod" is a special modifier equal to Super when running on a TTY, and to Alt
|
||||
// when running as a winit window.
|
||||
//
|
||||
// Most actions that you can bind here can also be invoked programmatically with
|
||||
// `niri msg action do-something`.
|
||||
|
||||
// Mod-Shift-/, which is usually the same as Mod-?,
|
||||
// shows a list of important hotkeys.
|
||||
Mod+Shift+Slash { show-hotkey-overlay; }
|
||||
|
||||
// Suggested binds for running programs: terminal, app launcher, screen locker.
|
||||
Mod+Return hotkey-overlay-title="Open a Terminal: kitty" { spawn "kitty"; }
|
||||
Mod+Z hotkey-overlay-title="Open a launcher: walker" { spawn "walker"; }
|
||||
Mod+Space { spawn "voxtoggle"; }
|
||||
Mod+Alt+L hotkey-overlay-title="Lock the Screen: hyprlock" { spawn "hyprlock"; }
|
||||
|
||||
// Use spawn-sh to run a shell command. Do this if you need pipes, multiple commands, etc.
|
||||
// Note: the entire command goes as a single argument. It's passed verbatim to `sh -c`.
|
||||
// For example, this is a standard bind to toggle the screen reader (orca).
|
||||
// Super+Alt+S allow-when-locked=true hotkey-overlay-title=null { spawn-sh "pkill orca || exec orca"; }
|
||||
|
||||
// Example volume keys mappings for PipeWire & WirePlumber.
|
||||
// The allow-when-locked=true property makes them work even when the session is locked.
|
||||
// Using spawn-sh allows to pass multiple arguments together with the command.
|
||||
// "-l 1.0" limits the volume to 100%.
|
||||
XF86AudioRaiseVolume allow-when-locked=true { spawn-sh "wpctl set-volume @DEFAULT_AUDIO_SINK@ 0.1+ -l 1.0"; }
|
||||
XF86AudioLowerVolume allow-when-locked=true { spawn-sh "wpctl set-volume @DEFAULT_AUDIO_SINK@ 0.1-"; }
|
||||
XF86AudioMute allow-when-locked=true { spawn-sh "wpctl set-mute @DEFAULT_AUDIO_SINK@ toggle"; }
|
||||
XF86AudioMicMute allow-when-locked=true { spawn-sh "wpctl set-mute @DEFAULT_AUDIO_SOURCE@ toggle"; }
|
||||
|
||||
// Example media keys mapping using playerctl.
|
||||
// This will work with any MPRIS-enabled media player.
|
||||
XF86AudioPlay allow-when-locked=true { spawn-sh "playerctl play-pause"; }
|
||||
XF86AudioStop allow-when-locked=true { spawn-sh "playerctl stop"; }
|
||||
XF86AudioPrev allow-when-locked=true { spawn-sh "playerctl previous"; }
|
||||
XF86AudioNext allow-when-locked=true { spawn-sh "playerctl next"; }
|
||||
|
||||
// Example brightness key mappings for brightnessctl.
|
||||
// You can use regular spawn with multiple arguments too (to avoid going through "sh"),
|
||||
// but you need to manually put each argument in separate "" quotes.
|
||||
XF86MonBrightnessUp allow-when-locked=true { spawn "brightnessctl" "--class=backlight" "set" "+10%"; }
|
||||
XF86MonBrightnessDown allow-when-locked=true { spawn "brightnessctl" "--class=backlight" "set" "10%-"; }
|
||||
|
||||
// Open/close the Overview: a zoomed-out view of workspaces and windows.
|
||||
// You can also move the mouse into the top-left hot corner,
|
||||
// or do a four-finger swipe up on a touchpad.
|
||||
Mod+O repeat=false { toggle-overview; }
|
||||
|
||||
Mod+Backspace repeat=false { close-window; }
|
||||
|
||||
Mod+Left { focus-column-left; }
|
||||
Mod+Down { focus-window-down; }
|
||||
Mod+Up { focus-window-up; }
|
||||
Mod+Right { focus-column-right; }
|
||||
|
||||
Mod+H { focus-column-left; }
|
||||
Mod+J { focus-window-or-workspace-down; }
|
||||
Mod+K { focus-window-or-workspace-up; }
|
||||
Mod+L { focus-column-right; }
|
||||
|
||||
Mod+Shift+Left { move-column-left; }
|
||||
Mod+Shift+Down { move-window-down; }
|
||||
Mod+Shift+Up { move-window-up; }
|
||||
Mod+Shift+Right { move-column-right; }
|
||||
Mod+Shift+H { move-column-left; }
|
||||
Mod+Shift+J { move-window-down-or-to-workspace-down; }
|
||||
Mod+Shift+K { move-window-up-or-to-workspace-up; }
|
||||
Mod+Shift+L { move-column-right; }
|
||||
|
||||
|
||||
Mod+Home { focus-column-first; }
|
||||
Mod+End { focus-column-last; }
|
||||
Mod+Shift+Home { move-column-to-first; }
|
||||
Mod+Shift+End { move-column-to-last; }
|
||||
|
||||
Mod+Ctrl+Left { focus-monitor-left; }
|
||||
Mod+Ctrl+Down { focus-monitor-down; }
|
||||
Mod+Ctrl+Up { focus-monitor-up; }
|
||||
Mod+Ctrl+Right { focus-monitor-right; }
|
||||
Mod+Ctrl+H { focus-monitor-left; }
|
||||
Mod+Ctrl+J { focus-monitor-down; }
|
||||
Mod+Ctrl+K { focus-monitor-up; }
|
||||
Mod+Ctrl+L { focus-monitor-right; }
|
||||
|
||||
Mod+Shift+Ctrl+Left { move-column-to-monitor-left; }
|
||||
Mod+Shift+Ctrl+Down { move-column-to-monitor-down; }
|
||||
Mod+Shift+Ctrl+Up { move-column-to-monitor-up; }
|
||||
Mod+Shift+Ctrl+Right { move-column-to-monitor-right; }
|
||||
Mod+Shift+Ctrl+H { move-column-to-monitor-left; }
|
||||
Mod+Shift+Ctrl+J { move-column-to-monitor-down; }
|
||||
Mod+Shift+Ctrl+K { move-column-to-monitor-up; }
|
||||
Mod+Shift+Ctrl+L { move-column-to-monitor-right; }
|
||||
|
||||
// Alternatively, there are commands to move just a single window:
|
||||
// Mod+Shift+Ctrl+Left { move-window-to-monitor-left; }
|
||||
// ...
|
||||
|
||||
// And you can also move a whole workspace to another monitor:
|
||||
// Mod+Shift+Ctrl+Left { move-workspace-to-monitor-left; }
|
||||
// ...
|
||||
|
||||
Mod+Page_Down { focus-workspace-down; }
|
||||
Mod+Page_Up { focus-workspace-up; }
|
||||
Mod+U { focus-workspace-down; }
|
||||
Mod+I { focus-workspace-up; }
|
||||
Mod+Ctrl+Page_Down { move-column-to-workspace-down; }
|
||||
Mod+Ctrl+Page_Up { move-column-to-workspace-up; }
|
||||
Mod+Ctrl+U { move-column-to-workspace-down; }
|
||||
Mod+Ctrl+I { move-column-to-workspace-up; }
|
||||
|
||||
// Alternatively, there are commands to move just a single window:
|
||||
// Mod+Ctrl+Page_Down { move-window-to-workspace-down; }
|
||||
// ...
|
||||
|
||||
Mod+Shift+Page_Down { move-workspace-down; }
|
||||
Mod+Shift+Page_Up { move-workspace-up; }
|
||||
Mod+Shift+U { move-workspace-down; }
|
||||
Mod+Shift+I { move-workspace-up; }
|
||||
|
||||
// You can bind mouse wheel scroll ticks using the following syntax.
|
||||
// These binds will change direction based on the natural-scroll setting.
|
||||
//
|
||||
// To avoid scrolling through workspaces really fast, you can use
|
||||
// the cooldown-ms property. The bind will be rate-limited to this value.
|
||||
// You can set a cooldown on any bind, but it's most useful for the wheel.
|
||||
Mod+WheelScrollDown cooldown-ms=150 { focus-workspace-down; }
|
||||
Mod+WheelScrollUp cooldown-ms=150 { focus-workspace-up; }
|
||||
Mod+Ctrl+WheelScrollDown cooldown-ms=150 { move-column-to-workspace-down; }
|
||||
Mod+Ctrl+WheelScrollUp cooldown-ms=150 { move-column-to-workspace-up; }
|
||||
|
||||
Mod+WheelScrollRight { focus-column-right; }
|
||||
Mod+WheelScrollLeft { focus-column-left; }
|
||||
Mod+Ctrl+WheelScrollRight { move-column-right; }
|
||||
Mod+Ctrl+WheelScrollLeft { move-column-left; }
|
||||
|
||||
// Usually scrolling up and down with Shift in applications results in
|
||||
// horizontal scrolling; these binds replicate that.
|
||||
Mod+Shift+WheelScrollDown { focus-column-right; }
|
||||
Mod+Shift+WheelScrollUp { focus-column-left; }
|
||||
Mod+Ctrl+Shift+WheelScrollDown { move-column-right; }
|
||||
Mod+Ctrl+Shift+WheelScrollUp { move-column-left; }
|
||||
|
||||
// Similarly, you can bind touchpad scroll "ticks".
|
||||
// Touchpad scrolling is continuous, so for these binds it is split into
|
||||
// discrete intervals.
|
||||
// These binds are also affected by touchpad's natural-scroll, so these
|
||||
// example binds are "inverted", since we have natural-scroll enabled for
|
||||
// touchpads by default.
|
||||
// Mod+TouchpadScrollDown { spawn-sh "wpctl set-volume @DEFAULT_AUDIO_SINK@ 0.02+"; }
|
||||
// Mod+TouchpadScrollUp { spawn-sh "wpctl set-volume @DEFAULT_AUDIO_SINK@ 0.02-"; }
|
||||
|
||||
// You can refer to workspaces by index. However, keep in mind that
|
||||
// niri is a dynamic workspace system, so these commands are kind of
|
||||
// "best effort". Trying to refer to a workspace index bigger than
|
||||
// the current workspace count will instead refer to the bottommost
|
||||
// (empty) workspace.
|
||||
//
|
||||
// For example, with 2 workspaces + 1 empty, indices 3, 4, 5 and so on
|
||||
// will all refer to the 3rd workspace.
|
||||
Mod+1 { focus-workspace 1; }
|
||||
Mod+2 { focus-workspace 2; }
|
||||
Mod+3 { focus-workspace 3; }
|
||||
Mod+4 { focus-workspace 4; }
|
||||
Mod+5 { focus-workspace 5; }
|
||||
Mod+6 { focus-workspace 6; }
|
||||
Mod+7 { focus-workspace 7; }
|
||||
Mod+8 { focus-workspace 8; }
|
||||
Mod+9 { focus-workspace 9; }
|
||||
Mod+Shift+1 { move-column-to-workspace 1; }
|
||||
Mod+Shift+2 { move-column-to-workspace 2; }
|
||||
Mod+Shift+3 { move-column-to-workspace 3; }
|
||||
Mod+Shift+4 { move-column-to-workspace 4; }
|
||||
Mod+Shift+5 { move-column-to-workspace 5; }
|
||||
Mod+Shift+6 { move-column-to-workspace 6; }
|
||||
Mod+Shift+7 { move-column-to-workspace 7; }
|
||||
Mod+Shift+8 { move-column-to-workspace 8; }
|
||||
Mod+Shift+9 { move-column-to-workspace 9; }
|
||||
|
||||
// Alternatively, there are commands to move just a single window:
|
||||
// Mod+Ctrl+1 { move-window-to-workspace 1; }
|
||||
|
||||
// Switches focus between the current and the previous workspace.
|
||||
// Mod+Tab { focus-workspace-previous; }
|
||||
|
||||
// The following binds move the focused window in and out of a column.
|
||||
// If the window is alone, they will consume it into the nearby column to the side.
|
||||
// If the window is already in a column, they will expel it out.
|
||||
Mod+BracketLeft { consume-or-expel-window-left; }
|
||||
Mod+BracketRight { consume-or-expel-window-right; }
|
||||
|
||||
// Consume one window from the right to the bottom of the focused column.
|
||||
Mod+Comma { consume-window-into-column; }
|
||||
// Expel the bottom window from the focused column to the right.
|
||||
Mod+Period { expel-window-from-column; }
|
||||
|
||||
Mod+R { switch-preset-column-width; }
|
||||
// Cycling through the presets in reverse order is also possible.
|
||||
// Mod+R { switch-preset-column-width-back; }
|
||||
Mod+Ctrl+R { switch-preset-window-height; }
|
||||
Mod+Shift+R { reset-window-height; }
|
||||
Mod+F { maximize-column; }
|
||||
Mod+Shift+F { fullscreen-window; }
|
||||
|
||||
// While maximize-column leaves gaps and borders around the window,
|
||||
// maximize-window-to-edges doesn't: the window expands to the edges of the screen.
|
||||
// This bind corresponds to normal window maximizing,
|
||||
// e.g. by double-clicking on the titlebar.
|
||||
Mod+M { maximize-window-to-edges; }
|
||||
|
||||
// Expand the focused column to space not taken up by other fully visible columns.
|
||||
// Makes the column "fill the rest of the space".
|
||||
Mod+Ctrl+F { expand-column-to-available-width; }
|
||||
|
||||
Mod+C { center-column; }
|
||||
|
||||
// Center all fully visible columns on screen.
|
||||
Mod+Ctrl+C { center-visible-columns; }
|
||||
|
||||
// Finer width adjustments.
|
||||
// This command can also:
|
||||
// * set width in pixels: "1000"
|
||||
// * adjust width in pixels: "-5" or "+5"
|
||||
// * set width as a percentage of screen width: "25%"
|
||||
// * adjust width as a percentage of screen width: "-10%" or "+10%"
|
||||
// Pixel sizes use logical, or scaled, pixels. I.e. on an output with scale 2.0,
|
||||
// set-column-width "100" will make the column occupy 200 physical screen pixels.
|
||||
Mod+Minus { set-column-width "-10%"; }
|
||||
Mod+Equal { set-column-width "+10%"; }
|
||||
|
||||
// Finer height adjustments when in column with other windows.
|
||||
Mod+Shift+Minus { set-window-height "-10%"; }
|
||||
Mod+Shift+Equal { set-window-height "+10%"; }
|
||||
|
||||
// Move the focused window between the floating and the tiling layout.
|
||||
Mod+V { toggle-window-floating; }
|
||||
Mod+Shift+V { switch-focus-between-floating-and-tiling; }
|
||||
|
||||
// Toggle tabbed column display mode.
|
||||
// Windows in this column will appear as vertical tabs,
|
||||
// rather than stacked on top of each other.
|
||||
Mod+W { toggle-column-tabbed-display; }
|
||||
|
||||
// Actions to switch layouts.
|
||||
// Note: if you uncomment these, make sure you do NOT have
|
||||
// a matching layout switch hotkey configured in xkb options above.
|
||||
// Having both at once on the same hotkey will break the switching,
|
||||
// since it will switch twice upon pressing the hotkey (once by xkb, once by niri).
|
||||
// Mod+Space { switch-layout "next"; }
|
||||
// Mod+Shift+Space { switch-layout "prev"; }
|
||||
|
||||
Print { screenshot; }
|
||||
Ctrl+Print { screenshot-screen; }
|
||||
Alt+Print { screenshot-window; }
|
||||
|
||||
// Applications such as remote-desktop clients and software KVM switches may
|
||||
// request that niri stops processing the keyboard shortcuts defined here
|
||||
// so they may, for example, forward the key presses as-is to a remote machine.
|
||||
// It's a good idea to bind an escape hatch to toggle the inhibitor,
|
||||
// so a buggy application can't hold your session hostage.
|
||||
//
|
||||
// The allow-inhibiting=false property can be applied to other binds as well,
|
||||
// which ensures niri always processes them, even when an inhibitor is active.
|
||||
Mod+Escape allow-inhibiting=false { toggle-keyboard-shortcuts-inhibit; }
|
||||
|
||||
// The quit action will show a confirmation dialog to avoid accidental exits.
|
||||
Mod+Shift+E { quit; }
|
||||
Ctrl+Alt+Delete { quit; }
|
||||
|
||||
// Powers off the monitors. To turn them back on, do any input like
|
||||
// moving the mouse or pressing any other key.
|
||||
Mod+Shift+P { power-off-monitors; }
|
||||
|
||||
}
|
||||
|
||||
switch-events {
|
||||
lid-close {
|
||||
spawn "handle-lid-close";
|
||||
}
|
||||
}
|
||||
@@ -1,433 +0,0 @@
|
||||
{ pkgs, lib, ... }:
|
||||
{
|
||||
imports = [ ../../modules/neovim ];
|
||||
|
||||
programs.neovim =
|
||||
let
|
||||
toLua = lib.generators.toLua { };
|
||||
luaMap = rhs: { rhs = rhs; lua = true; options = { silent = true; }; };
|
||||
in
|
||||
{
|
||||
enable = true;
|
||||
defaultEditor = true;
|
||||
options = {
|
||||
number = true;
|
||||
expandtab = true;
|
||||
tabstop = 2;
|
||||
shiftwidth = 2;
|
||||
softtabstop = 2;
|
||||
signcolumn = "yes";
|
||||
modeline = true;
|
||||
hidden = true;
|
||||
listchars = "tab:▸ ,trail:·";
|
||||
list = true;
|
||||
undofile = true;
|
||||
winblend = 30;
|
||||
};
|
||||
withTreesitterPlugins = p: [
|
||||
p.lua
|
||||
p.vim
|
||||
p.vimdoc
|
||||
p.nix
|
||||
p.query
|
||||
p.make
|
||||
];
|
||||
formatters = [
|
||||
{
|
||||
filetypes = [ "nix" ];
|
||||
globs = [ "*.nix" ];
|
||||
exe = "${pkgs.nixpkgs-fmt}/bin/nixpkgs-fmt";
|
||||
stdin = true;
|
||||
}
|
||||
{
|
||||
filetypes = [ "lua" ];
|
||||
globs = [ "*.lua" ];
|
||||
exe = "${pkgs.stylua}/bin/stylua";
|
||||
args = _: [ "-" ];
|
||||
stdin = true;
|
||||
}
|
||||
{
|
||||
filetypes = [ "crystal" ];
|
||||
globs = [ "*.cr" ];
|
||||
exe = "${pkgs.crystal}/bin/crystal";
|
||||
args = file: [ "tool" "format" ];
|
||||
stdin = false;
|
||||
}
|
||||
];
|
||||
autoCommands = [
|
||||
{
|
||||
event = "FileType";
|
||||
pattern = [ "lua" ];
|
||||
command = "setlocal expandtab";
|
||||
}
|
||||
{
|
||||
event = "FileType";
|
||||
pattern = [
|
||||
"makefile"
|
||||
];
|
||||
command = "setlocal shiftwidth=4 tabstop=4 softtabstop=4 noexpandtab";
|
||||
}
|
||||
{
|
||||
event = "FileType";
|
||||
pattern = [ "gitcommit" "gitrebase" "gitconfig" ];
|
||||
command = "set bufhidden=delete";
|
||||
}
|
||||
{
|
||||
event = "BufWinEnter";
|
||||
pattern = "*";
|
||||
command = "if line2byte(line('$')) > 1000000 | syntax clear | endif";
|
||||
}
|
||||
];
|
||||
signs = {
|
||||
error = "";
|
||||
warning = "";
|
||||
hint = "";
|
||||
info = "";
|
||||
};
|
||||
env = {
|
||||
GIT_EDITOR = "nvr -cc split --remote-wait";
|
||||
EDITOR = "nvr -cc close --remote-wait";
|
||||
};
|
||||
leader = " ";
|
||||
mappings = {
|
||||
normal = {
|
||||
"<C-h>" = "<C-w>h";
|
||||
"<C-j>" = "<C-w>j";
|
||||
"<C-k>" = "<C-w>k";
|
||||
"<C-l>" = "<c-w>l";
|
||||
"n" = "n";
|
||||
};
|
||||
visual = {
|
||||
"<tab>" = ">gv^";
|
||||
"<s-tab>" = "<gv^";
|
||||
};
|
||||
};
|
||||
snippets = {
|
||||
snippets = ./snippets;
|
||||
luasnippets = ./luasnippets;
|
||||
};
|
||||
plug = with pkgs.vimPlugins; [
|
||||
vimpeccable
|
||||
vim-crystal
|
||||
{
|
||||
plugin = telescope-nvim;
|
||||
dependencies = [ plenary-nvim telescope-file-browser-nvim commander-nvim telescope-ui-select-nvim ];
|
||||
config =
|
||||
let
|
||||
commands = [
|
||||
{ cmd = "<cmd>!rails db:migrate<cr>"; desc = "Run rails migrations"; }
|
||||
{ cmd = "<cmd>!yarn codegen --no-watch<cr>"; desc = "Run yarn codegen"; }
|
||||
{ cmd = "<cmd>!rails translations:update<cr>"; desc = "Update i18n translations"; }
|
||||
{ cmd = "<cmd>!deploy staging-v6 -t $(git branch --show-current)<cr>"; desc = "Deploy to staging"; }
|
||||
{ cmd = "<cmd>!db-restore -d db-prod-inc<cr>"; desc = "Restore db from prod-inc"; }
|
||||
];
|
||||
mappings = { i = { "<c-h>" = "which_key"; }; };
|
||||
in
|
||||
''
|
||||
local telescope = require('telescope')
|
||||
local commander = require('commander')
|
||||
|
||||
commander.add(${toLua commands})
|
||||
telescope.load_extension('commander')
|
||||
telescope.load_extension('ui-select')
|
||||
|
||||
telescope.setup({
|
||||
defaults = { mappings = ${toLua mappings}, winblend = 30; },
|
||||
pickers = {
|
||||
find_files = {
|
||||
find_command = { "${pkgs.fd}/bin/fd", "-H", "--type=file", "--type=symlink" }
|
||||
},
|
||||
},
|
||||
extensions = {
|
||||
file_browser = {
|
||||
hidden = true
|
||||
},
|
||||
}
|
||||
})
|
||||
'';
|
||||
mappings = {
|
||||
normal = (
|
||||
lib.attrsets.mapAttrs
|
||||
(key: value: luaMap "require('telescope.builtin').${value}")
|
||||
{
|
||||
"<leader>f" = "find_files";
|
||||
"<leader>r" = "live_grep";
|
||||
"<leader>b" = "buffers";
|
||||
"<leader>h" = "help_tags";
|
||||
"<leader>o" = "oldfiles";
|
||||
"<leader>s" = "git_status";
|
||||
"<leader>/" = "current_buffer_fuzzy_find";
|
||||
"<leader>c" = "git_branches";
|
||||
}
|
||||
) // (
|
||||
lib.attrsets.mapAttrs
|
||||
(key: value: luaMap "require('telescope').extensions.${value}")
|
||||
{
|
||||
"<leader>n" = "file_browser.file_browser";
|
||||
"<leader>:" = "commander.filter";
|
||||
}
|
||||
);
|
||||
};
|
||||
}
|
||||
{
|
||||
plugin = base16-nvim;
|
||||
config = ''
|
||||
vim.opt.termguicolors = true
|
||||
vim.cmd('colorscheme base16-tomorrow-night')
|
||||
'';
|
||||
}
|
||||
{ plugin = octo-nvim; config = "require('octo').setup()"; }
|
||||
{
|
||||
plugin = gitsigns-nvim;
|
||||
dependencies = [ plenary-nvim ];
|
||||
config = ''
|
||||
require('gitsigns').setup(${toLua {
|
||||
current_line_blame = true;
|
||||
}})
|
||||
'';
|
||||
}
|
||||
{ plugin = windline-nvim; config = "require('wlsample.airline')"; }
|
||||
{
|
||||
plugin = luasnip;
|
||||
config = ''
|
||||
require('luasnip.loaders.from_snipmate').lazy_load()
|
||||
require('luasnip.loaders.from_lua').lazy_load()
|
||||
local luasnip = require('luasnip')
|
||||
luasnip.setup({ updateevents = 'TextChanged,TextChangedI' })
|
||||
'';
|
||||
mappings =
|
||||
let
|
||||
mapping = rhs: luaMap "function() ${rhs} end";
|
||||
mappings = {
|
||||
"<c-n>" = mapping "luasnip.jump(1)";
|
||||
"<c-p>" = mapping "luasnip.jump(-1)";
|
||||
"<c-e>" = mapping "if luasnip.choice_active() then luasnip.change_choice(1) end";
|
||||
};
|
||||
in
|
||||
{
|
||||
insert = mappings;
|
||||
select = mappings;
|
||||
};
|
||||
}
|
||||
{ plugin = vim-abolish; }
|
||||
{ plugin = NrrwRgn; }
|
||||
{
|
||||
plugin = trouble-nvim;
|
||||
dependencies = [ nvim-web-devicons ];
|
||||
mappings =
|
||||
let
|
||||
mapping = rhs: luaMap "function() require('trouble').${rhs} end";
|
||||
in
|
||||
{
|
||||
normal = {
|
||||
"<leader>xx" = mapping "open()";
|
||||
"<leader>xd" = mapping "open('document_diagnostics')";
|
||||
"<leader>xl" = mapping "open('loclist')";
|
||||
"gR" = mapping "open('lsp_references')";
|
||||
};
|
||||
};
|
||||
}
|
||||
{ plugin = twilight-nvim; }
|
||||
{ plugin = which-key-nvim; }
|
||||
{ plugin = zen-mode-nvim; }
|
||||
{
|
||||
plugin = diffview-nvim;
|
||||
config =
|
||||
let
|
||||
config = {
|
||||
default = {
|
||||
layout = "diff2_vertical";
|
||||
};
|
||||
merge_tool = {
|
||||
layout = "diff3_vertical";
|
||||
};
|
||||
file_history = {
|
||||
layout = "diff2_vertical";
|
||||
};
|
||||
};
|
||||
in
|
||||
''
|
||||
require('diffview').setup(${toLua config})
|
||||
'';
|
||||
}
|
||||
{
|
||||
plugin = toggleterm-nvim;
|
||||
dependencies = [ plenary-nvim pkgs.lazygit ];
|
||||
config = ''
|
||||
local Terminal = require('toggleterm.terminal').Terminal
|
||||
local lazygit = Terminal:new({
|
||||
cmd = "${pkgs.lazygit}/bin/lazygit",
|
||||
dir = "git_dir",
|
||||
direction = "float",
|
||||
hidden = true,
|
||||
on_open = function (term)
|
||||
vim.cmd('startinsert!')
|
||||
vim.api.nvim_buf_set_keymap(term.bufnr, 'n', 'q', '<cmd>close<cr>', { noremap = true, silent = true })
|
||||
end,
|
||||
on_close = function (term)
|
||||
vim.cmd('startinsert!')
|
||||
end,
|
||||
})
|
||||
'';
|
||||
mappings = {
|
||||
normal = {
|
||||
"<leader>g" = luaMap "function () lazygit:toggle() end";
|
||||
};
|
||||
};
|
||||
}
|
||||
{
|
||||
plugin = copilot-cmp;
|
||||
dependencies = [{
|
||||
plugin = copilot-lua;
|
||||
config = ''
|
||||
require('copilot').setup({
|
||||
suggestion = { enabled = false },
|
||||
panel = { enajkbled = false },
|
||||
copilot_node_command = '${pkgs.nodejs}/bin/node',
|
||||
})
|
||||
'';
|
||||
}];
|
||||
config = ''
|
||||
require('copilot_cmp').setup()
|
||||
'';
|
||||
}
|
||||
{
|
||||
plugin = gen-nvim;
|
||||
config =
|
||||
let
|
||||
config = {
|
||||
model = "llama3";
|
||||
};
|
||||
in
|
||||
''
|
||||
require('gen').setup(${toLua config})
|
||||
'';
|
||||
}
|
||||
{
|
||||
plugin = bufferline-nvim;
|
||||
config =
|
||||
let
|
||||
options = {
|
||||
hover = {
|
||||
enabled = true;
|
||||
delay = 200;
|
||||
reveal = [ "close" ];
|
||||
};
|
||||
};
|
||||
in
|
||||
''
|
||||
require('bufferline').setup({ options = ${toLua options} })
|
||||
'';
|
||||
dependencies = [{
|
||||
plugin = nvim-web-devicons;
|
||||
}];
|
||||
}
|
||||
];
|
||||
lsp = {
|
||||
servers = with pkgs; [
|
||||
{
|
||||
name = "lua_ls";
|
||||
config = {
|
||||
settings = {
|
||||
Lua = {
|
||||
diagnostics = {
|
||||
globals = [ "vim" ];
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
package = lua-language-server;
|
||||
}
|
||||
{
|
||||
name = "yamlls";
|
||||
config = {
|
||||
settings = {
|
||||
redhat = { telemetry = { enabled = false; }; };
|
||||
yaml = {
|
||||
schemas = {
|
||||
"https://json.schemastore.org/github-workflow" = ".github/workflows/*.yml";
|
||||
"https://json.schemastore.org/prettierrc" = ".prettierrc";
|
||||
"https://json.schemastore.org/prettierrc.yml" = ".prettierrc.yml";
|
||||
"https://json.schemastore.org/prettierrc.yaml" = ".prettierrc.yaml";
|
||||
"https://json.schemastore.org/prettier.config.yml" = "prettier.config.yml";
|
||||
"https://json.schemastore.org/prettier.config.yaml" = "prettier.config.yaml";
|
||||
"https://schema.jokke.space/caddy.json" = [ "*caddy*.yml" "*caddy*.yaml" ];
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
package = yaml-language-server;
|
||||
}
|
||||
{
|
||||
name = "tailwindcss";
|
||||
config = {
|
||||
settings = {
|
||||
tailwindCSS = {
|
||||
classAttributes = [ "class" "className" ];
|
||||
};
|
||||
};
|
||||
};
|
||||
package = tailwindcss-language-server;
|
||||
}
|
||||
{
|
||||
name = "ts_ls";
|
||||
package = nodePackages.typescript-language-server;
|
||||
config = {
|
||||
single_file_support = false;
|
||||
};
|
||||
rootPattern = [ "package.json" ];
|
||||
}
|
||||
{ name = "eslint"; package = vscode-langservers-extracted; }
|
||||
{ name = "nixd"; package = nixd; }
|
||||
{
|
||||
name = "bashls";
|
||||
package = nodePackages.bash-language-server.overrideAttrs (oldAttrs: {
|
||||
buildDependencies = [ shellcheck ];
|
||||
afterInstall = ''
|
||||
wrapProgram "$out/bin/bash-language-server" --prefix PATH : "${shellcheck}/bin"
|
||||
'';
|
||||
});
|
||||
}
|
||||
{
|
||||
name = "crystalline";
|
||||
package = crystalline;
|
||||
}
|
||||
{
|
||||
name = "rust_analyzer";
|
||||
package = rust-analyzer;
|
||||
}
|
||||
];
|
||||
mappings = {
|
||||
buf = {
|
||||
declaration = "gD";
|
||||
definition = "gd";
|
||||
hover = "K";
|
||||
implementation = "gi";
|
||||
type_definition = "<leader>D";
|
||||
rename = "<leader>rn";
|
||||
code_action = "<leader>ca";
|
||||
};
|
||||
diagnostic = {
|
||||
show_line_diagnostics = "<leader>e";
|
||||
goto_prev = "[d";
|
||||
goto_next = "]d";
|
||||
set_loclist = "<leader>q";
|
||||
};
|
||||
};
|
||||
};
|
||||
extraLuaConfig = ''
|
||||
local function close_all_other_buffers(opts)
|
||||
local current_buf = vim.api.nvim_get_current_buf()
|
||||
local buffers = vim.api.nvim_list_bufs()
|
||||
|
||||
for _, buf in ipairs(buffers) do
|
||||
if buf ~= current_buf and vim.api.nvim_buf_is_loaded(buf) then
|
||||
vim.api.nvim_buf_delete(buf, { force = opts.bang })
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
vim.api.nvim_create_user_command('CloseOtherBuffers', close_all_other_buffers, { bang = true })
|
||||
'';
|
||||
};
|
||||
}
|
||||
@@ -1,46 +0,0 @@
|
||||
local Formatters = {}
|
||||
|
||||
Formatters.setup = function()
|
||||
local formatter = require('formatter')
|
||||
local util = require('formatter.util')
|
||||
|
||||
local js = {
|
||||
function ()
|
||||
return {
|
||||
exe = "npx",
|
||||
args = {"prettier", "--stdin-filepath", util.escape_path(util.get_current_buffer_file_name())},
|
||||
stdin = true,
|
||||
}
|
||||
end
|
||||
}
|
||||
|
||||
local ruby = {
|
||||
function ()
|
||||
return {
|
||||
exe = "bundle",
|
||||
args = {"exec", "rufo", "-x", "--filename", util.escape_path(util.get_current_buffer_file_name())},
|
||||
stdin = true,
|
||||
}
|
||||
end
|
||||
}
|
||||
|
||||
formatter.setup {
|
||||
filetype = {
|
||||
javascript = js,
|
||||
typescript = js,
|
||||
javascriptreact = js,
|
||||
typescriptreact = js,
|
||||
svelte = js,
|
||||
ruby = ruby,
|
||||
haml = ruby,
|
||||
}
|
||||
}
|
||||
|
||||
vim.api.nvim_create_autocmd("BufWritePost", {
|
||||
pattern = { "*.js", "*.ts", "*.jsx", "*.tsx", "*.svelte", "*.rb", "*.haml", "Gemfile", "*.rake" },
|
||||
command = "FormatWrite",
|
||||
group = vim.api.nvim_create_augroup("FormatAutogroup", { clear = true }),
|
||||
})
|
||||
end
|
||||
|
||||
Formatters.setup()
|
||||
@@ -1,83 +0,0 @@
|
||||
local ls = require("luasnip")
|
||||
local fmt = require("luasnip.extras.fmt").fmt
|
||||
local s = ls.snippet
|
||||
local sn = ls.snippet_node
|
||||
local i = ls.insert_node
|
||||
local f = ls.function_node
|
||||
local d = ls.dynamic_node
|
||||
|
||||
return {
|
||||
s(
|
||||
{ trig = "fc", desc = "React.FC" },
|
||||
fmt(
|
||||
[[
|
||||
import React from "react"
|
||||
|
||||
interface {props_name} {{
|
||||
{prop_types}
|
||||
}}
|
||||
|
||||
const {component_name}: React.FC<{props_name}> = ({props}) => {{
|
||||
return (
|
||||
{markup}
|
||||
)
|
||||
}}
|
||||
|
||||
export default {component_name}
|
||||
]],
|
||||
{
|
||||
props_name = i(3, "Props"),
|
||||
prop_types = i(2),
|
||||
component_name = d(1, function()
|
||||
local filename = vim.api.nvim_buf_get_name(0)
|
||||
local component_name
|
||||
|
||||
if filename == "index.tsx" then
|
||||
component_name = vim.fs.basename(vim.fs.dirname(filename))
|
||||
else
|
||||
component_name = vim.fs.basename(filename):match("(.+)%.tsx")
|
||||
end
|
||||
|
||||
return sn(nil, i(1, component_name))
|
||||
end),
|
||||
props = f(function(prop_types)
|
||||
local props = {}
|
||||
|
||||
for _, prop in ipairs(prop_types[1]) do
|
||||
local parts = vim.split(prop, ":", { plain = true, trimempty = true })
|
||||
local name = parts[1]
|
||||
if name then
|
||||
table.insert(props, vim.trim(name))
|
||||
end
|
||||
end
|
||||
|
||||
return "{ " .. table.concat(props, ", ") .. " }"
|
||||
end, { 2 }),
|
||||
markup = i(0),
|
||||
},
|
||||
{
|
||||
repeat_duplicates = true,
|
||||
}
|
||||
)
|
||||
),
|
||||
s(
|
||||
{ trig = "t", desc = "<tag>" },
|
||||
fmt(
|
||||
[[
|
||||
<{tag}>
|
||||
{children}
|
||||
</{closing_tag}>
|
||||
]],
|
||||
{
|
||||
tag = i(1, "div"),
|
||||
closing_tag = f(function(tag)
|
||||
return vim.split(tag[1][1], " ")[1]
|
||||
end, { 1 }),
|
||||
children = i(0),
|
||||
},
|
||||
{
|
||||
repeat_duplicates = true,
|
||||
}
|
||||
)
|
||||
),
|
||||
}
|
||||
@@ -1,33 +0,0 @@
|
||||
snippet if ruby if statement
|
||||
if $1
|
||||
$0
|
||||
end
|
||||
|
||||
snippet qt graphql query test
|
||||
require "test_helper"
|
||||
|
||||
module Graphql
|
||||
module Queries
|
||||
class $1Test < ActionDispatch::IntegrationTest
|
||||
setup do
|
||||
@user = users(:tobias)
|
||||
rack_login(@user)
|
||||
end
|
||||
|
||||
test "Query$1" do
|
||||
run_query("Query$1") do |json, msg|
|
||||
$0
|
||||
end
|
||||
end
|
||||
|
||||
test "Query$1 without $2 permissions" do
|
||||
@user.permission.update!($2: 0)
|
||||
|
||||
run_query("Query$1") do |json, msg|
|
||||
assert false
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
|
||||
15
home/common/secrets.nix
Normal file
15
home/common/secrets.nix
Normal file
@@ -0,0 +1,15 @@
|
||||
{ lib, ... }:
|
||||
{
|
||||
age.secrets = lib.listToAttrs (
|
||||
map
|
||||
(secret: {
|
||||
name = secret;
|
||||
value = {
|
||||
file = ../../secrets/${secret}.age;
|
||||
};
|
||||
})
|
||||
[
|
||||
"context7"
|
||||
]
|
||||
);
|
||||
}
|
||||
@@ -1,10 +0,0 @@
|
||||
{ ... }:
|
||||
let
|
||||
inherit (builtins) attrNames filter readDir;
|
||||
dirs =
|
||||
let files = readDir ./.;
|
||||
in filter (name: files."${name}" == "directory") (attrNames files);
|
||||
in
|
||||
{
|
||||
imports = map (dir: ./${dir}) dirs;
|
||||
}
|
||||
@@ -1,30 +0,0 @@
|
||||
{ pkgs, config, lib, ... }:
|
||||
let
|
||||
cfg = config.programs.fb-client;
|
||||
in
|
||||
{
|
||||
options.programs.fb-client = let inherit (lib) mkEnableOption mkOption types; in {
|
||||
enable = mkEnableOption { };
|
||||
pastebin = mkOption {
|
||||
type = types.str;
|
||||
default = "https://paste.xinu.at";
|
||||
};
|
||||
clipboard_cmd = mkOption {
|
||||
type = types.pathInStore;
|
||||
default = "${pkgs.wl-clipboard}/bin/wl-copy";
|
||||
};
|
||||
};
|
||||
|
||||
config = lib.mkIf cfg.enable {
|
||||
home.packages = [ pkgs.fb-client ];
|
||||
xdg = {
|
||||
configFile = {
|
||||
"fb-client/config".text = ''
|
||||
pastebin="${cfg.pastebin}"
|
||||
apikey_file="${config.xdg.dataHome}/fb-client/apikey"
|
||||
clipboard_cmd="${cfg.clipboard_cmd}"
|
||||
'';
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
@@ -1,11 +1,16 @@
|
||||
{ inputs, ... }:
|
||||
{
|
||||
inputs,
|
||||
pkgs-unstable,
|
||||
self,
|
||||
...
|
||||
}:
|
||||
{
|
||||
home-manager = {
|
||||
users = {
|
||||
jokke = import ./jokke;
|
||||
moco = import ./moco;
|
||||
};
|
||||
extraSpecialArgs = { inherit inputs; };
|
||||
extraSpecialArgs = { inherit inputs self pkgs-unstable; };
|
||||
sharedModules = [ (import ./common) ];
|
||||
useUserPackages = true;
|
||||
useGlobalPkgs = true;
|
||||
|
||||
@@ -1,4 +1,9 @@
|
||||
{ config, lib, osConfig, ... }:
|
||||
{
|
||||
config,
|
||||
lib,
|
||||
osConfig,
|
||||
...
|
||||
}:
|
||||
let
|
||||
cfg = config.gnome;
|
||||
in
|
||||
@@ -38,7 +43,12 @@ in
|
||||
};
|
||||
power = {
|
||||
powerButton = lib.mkOption {
|
||||
type = enum [ "suspend" "interactive" "hibernate" "nothing" ];
|
||||
type = enum [
|
||||
"suspend"
|
||||
"interactive"
|
||||
"hibernate"
|
||||
"nothing"
|
||||
];
|
||||
default = "interactive";
|
||||
};
|
||||
};
|
||||
@@ -75,23 +85,36 @@ in
|
||||
};
|
||||
|
||||
config = {
|
||||
dconf.settings = with lib.hm.gvariant; {
|
||||
dconf.settings =
|
||||
with lib.hm.gvariant;
|
||||
{
|
||||
"org/gnome/shell/keybindings" = cfg.keybindings.builtin;
|
||||
"org/gnome/settings-daemon/plugins/media-keys" = {
|
||||
custom-keybindings = (
|
||||
lib.lists.imap0
|
||||
(i: _: "/org/gnome/settings-daemon/plugins/media-keys/custom-keybindings/custom${toString i}/")
|
||||
cfg.keybindings.custom
|
||||
lib.lists.imap0 (
|
||||
i: _: "/org/gnome/settings-daemon/plugins/media-keys/custom-keybindings/custom${toString i}/"
|
||||
) cfg.keybindings.custom
|
||||
);
|
||||
};
|
||||
"org/gnome/desktop/input-sources" = {
|
||||
sources = map (source: mkTuple [ "xkb" source ]) cfg.keyboard.sources;
|
||||
sources = map (
|
||||
source:
|
||||
mkTuple [
|
||||
"xkb"
|
||||
source
|
||||
]
|
||||
) cfg.keyboard.sources;
|
||||
};
|
||||
"org/gnome/mutter" = {
|
||||
experimental-features = [ "scale-monitor-framebuffer" ];
|
||||
};
|
||||
"org/gnome/settings-daemon/plugins/xsettings" = {
|
||||
overrides = [ (mkTuple [ "GdkWindowScalingFactor" cfg.scalingFactor ]) ];
|
||||
overrides = [
|
||||
(mkTuple [
|
||||
"GdkWindowScalingFactor"
|
||||
cfg.scalingFactor
|
||||
])
|
||||
];
|
||||
};
|
||||
"org/gnome/desktop/interface" = {
|
||||
scaling-factor = cfg.scalingFactor;
|
||||
@@ -115,16 +138,13 @@ in
|
||||
"system/locale" = {
|
||||
region = cfg.region;
|
||||
};
|
||||
} // (
|
||||
builtins.listToAttrs (
|
||||
lib.lists.imap0
|
||||
(i: keybinding: {
|
||||
}
|
||||
// (builtins.listToAttrs (
|
||||
lib.lists.imap0 (i: keybinding: {
|
||||
name = "org/gnome/settings-daemon/plugins/media-keys/custom-keybindings/custom${toString i}";
|
||||
value = keybinding;
|
||||
})
|
||||
cfg.keybindings.custom
|
||||
)
|
||||
);
|
||||
}) cfg.keybindings.custom
|
||||
));
|
||||
home.file.".face".source = lib.mkIf (!isNull cfg.profilePicture) cfg.profilePicture;
|
||||
};
|
||||
}
|
||||
|
||||
@@ -2,8 +2,10 @@
|
||||
let
|
||||
inherit (builtins) attrNames filter readDir;
|
||||
dirs =
|
||||
let files = readDir ./.;
|
||||
in filter (name: files."${name}" == "directory") (attrNames files);
|
||||
let
|
||||
files = readDir ./.;
|
||||
in
|
||||
filter (name: files."${name}" == "directory") (attrNames files);
|
||||
in
|
||||
{
|
||||
imports = map (dir: ./${dir}) dirs;
|
||||
|
||||
@@ -1,4 +1,9 @@
|
||||
{ config, pkgs, lib, ... }:
|
||||
{
|
||||
config,
|
||||
pkgs,
|
||||
lib,
|
||||
...
|
||||
}:
|
||||
let
|
||||
cfg = config.gnome.extensions.freon;
|
||||
in
|
||||
|
||||
@@ -1,4 +1,9 @@
|
||||
{ config, pkgs, lib, ... }:
|
||||
{
|
||||
config,
|
||||
pkgs,
|
||||
lib,
|
||||
...
|
||||
}:
|
||||
let
|
||||
cfg = config.gnome.extensions;
|
||||
in
|
||||
@@ -10,18 +15,52 @@ in
|
||||
type = package;
|
||||
default = pkgs.gnomeExtensions.paperwm;
|
||||
};
|
||||
cycle-height-steps = lib.mkOption { type = listOf numbers.nonnegative; default = [ 0.33 0.5 0.67 1.0 ]; };
|
||||
cycle-width-steps = lib.mkOption { type = listOf numbers.nonnegative; default = [ 0.33 0.5 0.67 1.0 ]; };
|
||||
horizontal-margin = lib.mkOption { type = ints.unsigned; default = 5; };
|
||||
vertical-margin = lib.mkOption { type = ints.unsigned; default = 5; };
|
||||
window-gap = lib.mkOption { type = ints.unsigned; default = 5; };
|
||||
cycle-height-steps = lib.mkOption {
|
||||
type = listOf numbers.nonnegative;
|
||||
default = [
|
||||
0.33
|
||||
0.5
|
||||
0.67
|
||||
1.0
|
||||
];
|
||||
};
|
||||
cycle-width-steps = lib.mkOption {
|
||||
type = listOf numbers.nonnegative;
|
||||
default = [
|
||||
0.33
|
||||
0.5
|
||||
0.67
|
||||
1.0
|
||||
];
|
||||
};
|
||||
horizontal-margin = lib.mkOption {
|
||||
type = ints.unsigned;
|
||||
default = 5;
|
||||
};
|
||||
vertical-margin = lib.mkOption {
|
||||
type = ints.unsigned;
|
||||
default = 5;
|
||||
};
|
||||
window-gap = lib.mkOption {
|
||||
type = ints.unsigned;
|
||||
default = 5;
|
||||
};
|
||||
winprops = lib.mkOption {
|
||||
type = listOf (submodule {
|
||||
options = {
|
||||
wm_class = lib.mkOption { type = str; default = ""; };
|
||||
title = lib.mkOption { type = str; default = ""; };
|
||||
wm_class = lib.mkOption {
|
||||
type = str;
|
||||
default = "";
|
||||
};
|
||||
title = lib.mkOption {
|
||||
type = str;
|
||||
default = "";
|
||||
};
|
||||
scratch_layer = lib.mkEnableOption { };
|
||||
preferredWidth = lib.mkOption { type = nullOr str; default = null; };
|
||||
preferredWidth = lib.mkOption {
|
||||
type = nullOr str;
|
||||
default = null;
|
||||
};
|
||||
};
|
||||
});
|
||||
default = [ ];
|
||||
@@ -36,13 +75,23 @@ in
|
||||
config = lib.mkIf cfg.paperwm.enable {
|
||||
home.packages = [ cfg.paperwm.package ];
|
||||
dconf.settings = {
|
||||
"org/gnome/shell".enabled-extensions =
|
||||
lib.mkIf cfg.paperwm.enable [ cfg.paperwm.package.extensionUuid ];
|
||||
"org/gnome/shell/extensions/paperwm" = with cfg.paperwm; lib.mkIf cfg.paperwm.enable {
|
||||
inherit cycle-height-steps cycle-width-steps horizontal-margin vertical-margin window-gap;
|
||||
"org/gnome/shell".enabled-extensions = lib.mkIf cfg.paperwm.enable [
|
||||
cfg.paperwm.package.extensionUuid
|
||||
];
|
||||
"org/gnome/shell/extensions/paperwm" =
|
||||
with cfg.paperwm;
|
||||
lib.mkIf cfg.paperwm.enable {
|
||||
inherit
|
||||
cycle-height-steps
|
||||
cycle-width-steps
|
||||
horizontal-margin
|
||||
vertical-margin
|
||||
window-gap
|
||||
;
|
||||
winprops = map (props: builtins.toJSON props) winprops;
|
||||
};
|
||||
"org/gnome/shell/extensions/paperwm/keybindings" = lib.mkIf cfg.paperwm.enable cfg.paperwm.keybindings;
|
||||
"org/gnome/shell/extensions/paperwm/keybindings" =
|
||||
lib.mkIf cfg.paperwm.enable cfg.paperwm.keybindings;
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
@@ -1,4 +1,9 @@
|
||||
{ pkgs, inputs, ... }:
|
||||
{
|
||||
pkgs,
|
||||
pkgs-unstable,
|
||||
inputs,
|
||||
...
|
||||
}:
|
||||
{
|
||||
config = {
|
||||
# Home Manager needs a bit of information about you and the paths it should
|
||||
@@ -18,67 +23,19 @@
|
||||
inkscape
|
||||
wineWowPackages.waylandFull
|
||||
reaper
|
||||
inputs.ksoloti-pr.legacyPackages.${pkgs.system}.ksoloti
|
||||
inputs.ksoloti-pr.legacyPackages.${pkgs.stdenv.hostPlatform.system}.ksoloti
|
||||
calibre
|
||||
jellyfin-media-player
|
||||
darktable
|
||||
openscad
|
||||
shutter
|
||||
git-annex
|
||||
hledger
|
||||
hledger-ui
|
||||
hledger-iadd
|
||||
];
|
||||
|
||||
gnome.profilePicture = ../assets/profile-pictures/jokke.png;
|
||||
|
||||
programs.neovim = {
|
||||
extraPackages = with pkgs; [
|
||||
nodePackages.graphql-language-service-cli
|
||||
];
|
||||
withTreesitterPlugins = p: [
|
||||
p.typescript
|
||||
p.svelte
|
||||
p.prisma
|
||||
p.graphql
|
||||
];
|
||||
formatters = [
|
||||
{
|
||||
filetypes = [ "typescript" "typescriptreact" "svelte" ];
|
||||
globs = [ "*.ts" "*.tsx" "*.svelte" ];
|
||||
exe = "npx";
|
||||
args = file: [ "prettier" "--stdin-filepath" file ];
|
||||
stdin = true;
|
||||
}
|
||||
{
|
||||
filetypes = [ "prisma" ];
|
||||
globs = [ "*.prisma" ];
|
||||
exe = "${pkgs.nodePackages.prisma}/bin/prisma";
|
||||
args = file: [ "format" "--schema" ];
|
||||
stdin = false;
|
||||
}
|
||||
];
|
||||
lsp.servers = with pkgs; [
|
||||
{
|
||||
name = "svelte";
|
||||
package = nodePackages.svelte-language-server;
|
||||
}
|
||||
{
|
||||
name = "denols";
|
||||
package = deno;
|
||||
rootPattern = [ "deno.json" ];
|
||||
}
|
||||
{
|
||||
name = "prismals";
|
||||
package = nodePackages."@prisma/language-server";
|
||||
rootPattern = [ "package.json" "deno.json" ];
|
||||
}
|
||||
{
|
||||
name = "graphql";
|
||||
package = nodePackages.graphql-language-service-cli;
|
||||
config = {
|
||||
filetypes = [ "typescript" "typescriptreact" "graphql" "svelte" ];
|
||||
};
|
||||
}
|
||||
];
|
||||
};
|
||||
|
||||
programs.ssh.matchBlocks = {
|
||||
"alderaan" = {
|
||||
hostname = "alderaan.space";
|
||||
@@ -93,7 +50,7 @@
|
||||
};
|
||||
};
|
||||
|
||||
programs.git.extraConfig.user.email = "joakim@repomaa.com";
|
||||
programs.git.settings.user.email = "joakim@repomaa.com";
|
||||
services.syncthing = {
|
||||
enable = true;
|
||||
};
|
||||
|
||||
@@ -1,4 +1,9 @@
|
||||
{ pkgs, ... }:
|
||||
{
|
||||
pkgs,
|
||||
pkgs-unstable,
|
||||
lib,
|
||||
...
|
||||
}:
|
||||
let
|
||||
homeDirectory = "/home/moco";
|
||||
in
|
||||
@@ -9,6 +14,7 @@ in
|
||||
username = "moco";
|
||||
inherit homeDirectory;
|
||||
packages = with pkgs; [
|
||||
chromium
|
||||
(slack.overrideAttrs (oldAttrs: {
|
||||
fixupPhase = ''
|
||||
sed -i -e 's/,"WebRTCPipeWireCapturer"/,"LebRTCPipeWireCapturer"/' $out/lib/slack/resources/app.asar
|
||||
@@ -20,11 +26,12 @@ in
|
||||
--add-flags "--ozone-platform-hint=auto --enable-features=WaylandWindowDecorations,WebRTCPipeWireCapturer"
|
||||
'';
|
||||
}))
|
||||
pkgs-unstable.chromedriver
|
||||
kooha
|
||||
gnome-pomodoro
|
||||
mitmproxy
|
||||
(writeShellScriptBin "moco-admin-pw" ''
|
||||
password=$(op item get fkj74ou6jfex7a6gcinac6o5oe --reveal --fields label=Kennwort)
|
||||
password=$(op item get n5h4c237tqnnlr5gruxyqmmggy --reveal --fields label=Kennwort)
|
||||
otp=$(ykman oath accounts code -s 'MOCO:Admin')
|
||||
echo "''${password}''${otp}" | wl-copy -n
|
||||
'')
|
||||
@@ -38,7 +45,10 @@ in
|
||||
profilePicture = ../assets/profile-pictures/moco.png;
|
||||
calendar.showWeekNumbers = true;
|
||||
extensions.paperwm.winprops = [
|
||||
{ wm_class = "gnome-pomodoro"; scratch_layer = true; }
|
||||
{
|
||||
wm_class = "gnome-pomodoro";
|
||||
scratch_layer = true;
|
||||
}
|
||||
];
|
||||
};
|
||||
|
||||
@@ -52,6 +62,34 @@ in
|
||||
};
|
||||
};
|
||||
|
||||
programs.ashell.settings.settings.CustomButton =
|
||||
let
|
||||
nmcli = lib.getExe' pkgs.networkmanager "nmcli";
|
||||
ykman = lib.getExe pkgs.yubikey-manager;
|
||||
isMocoVpnActive = lib.getExe (
|
||||
pkgs.writeShellScriptBin "is-moco-vpn-active" ''
|
||||
${nmcli} -t -f NAME connection show --active | grep -q '^moco$'
|
||||
''
|
||||
);
|
||||
toggleMocoVpn = lib.getExe (
|
||||
pkgs.writeShellScriptBin "toggle-moco-vpn" ''
|
||||
if ${isMocoVpnActive}; then
|
||||
${nmcli} c down moco
|
||||
else
|
||||
${ykman} oath accounts code -s 'MOCO Reto' | ${nmcli} c up moco --ask
|
||||
fi
|
||||
''
|
||||
);
|
||||
in
|
||||
[
|
||||
{
|
||||
name = "MOCO VPN";
|
||||
icon = "";
|
||||
command = toggleMocoVpn;
|
||||
status_command = isMocoVpnActive;
|
||||
}
|
||||
];
|
||||
|
||||
programs.zsh = {
|
||||
cdpath = [
|
||||
"${homeDirectory}/Code/mocoapp"
|
||||
@@ -65,58 +103,25 @@ in
|
||||
};
|
||||
};
|
||||
|
||||
programs.git.extraConfig.user.email = "joakim.repomaa@mocoapp.com";
|
||||
|
||||
programs.neovim = {
|
||||
withTreesitterPlugins = p: [
|
||||
p.ruby
|
||||
p.javascript
|
||||
p.typescript
|
||||
p.graphql
|
||||
];
|
||||
formatters = [
|
||||
{
|
||||
filetypes = [ "ruby" ];
|
||||
globs = [ "*.rb" "Gemfile" "*.rake" ];
|
||||
exe = "bundle";
|
||||
args = file: [ "exec" "rufo" "-x" "--filename" file ];
|
||||
stdin = true;
|
||||
}
|
||||
{
|
||||
filetypes = [ "javascript" "typescript" "javascriptreact" "typescriptreact" ];
|
||||
globs = [ "*.js" "*.jsx" "*.ts" "*.tsx" ];
|
||||
exe = "npx";
|
||||
args = file: [ "prettier" "--stdin-filepath" file ];
|
||||
stdin = true;
|
||||
}
|
||||
];
|
||||
lsp.servers = with pkgs; [
|
||||
{
|
||||
name = "ruby_lsp";
|
||||
config = {
|
||||
init_options = {
|
||||
formatter = "auto";
|
||||
};
|
||||
};
|
||||
package = ruby-lsp;
|
||||
}
|
||||
{
|
||||
name = "graphql";
|
||||
package = nodePackages.graphql-language-service-cli;
|
||||
}
|
||||
];
|
||||
};
|
||||
programs.git.settings.user.email = "joakim.repomaa@mocoapp.com";
|
||||
|
||||
programs.ssh.matchBlocks =
|
||||
let
|
||||
aliases = [ "moco" "mocoapp" "mocoapp.com" ];
|
||||
matcher = subdomains:
|
||||
aliases = [
|
||||
"moco"
|
||||
"mocoapp"
|
||||
"mocoapp.com"
|
||||
];
|
||||
matcher =
|
||||
subdomains:
|
||||
builtins.concatStringsSep " " (
|
||||
map (
|
||||
alias:
|
||||
builtins.concatStringsSep " " (
|
||||
map
|
||||
(alias: builtins.concatStringsSep " " (
|
||||
map (subdomain: "*.${subdomain}.${alias} ${subdomain}.${alias}") subdomains
|
||||
))
|
||||
aliases);
|
||||
)
|
||||
) aliases
|
||||
);
|
||||
in
|
||||
{
|
||||
"console.*.moco" = {
|
||||
@@ -126,7 +131,11 @@ in
|
||||
};
|
||||
};
|
||||
|
||||
"${matcher ["reto" "reto.intern"]}" = {
|
||||
"${matcher [
|
||||
"reto"
|
||||
"reto.intern"
|
||||
]}" =
|
||||
{
|
||||
hostname = "reto.intern.mocoapp.com";
|
||||
user = "jokke";
|
||||
};
|
||||
@@ -140,25 +149,45 @@ in
|
||||
"${matcher [ "prod" ]}" = {
|
||||
hostname = "web02.mocoapp";
|
||||
};
|
||||
"${matcher ["pfg" "primeforcegroup"]}" = {
|
||||
"${matcher [
|
||||
"pfg"
|
||||
"primeforcegroup"
|
||||
]}" =
|
||||
{
|
||||
hostname = "primeforcegroup.mocoapp.com";
|
||||
};
|
||||
"${matcher [ "crafft" ]}" = {
|
||||
hostname = "crafft.mocoapp.com";
|
||||
};
|
||||
"${matcher ["bd" "businessdecision"]}" = {
|
||||
"${matcher [
|
||||
"bd"
|
||||
"businessdecision"
|
||||
]}" =
|
||||
{
|
||||
hostname = "businessdecision.mocoapp.com";
|
||||
};
|
||||
"${matcher [ "festland" ]}" = {
|
||||
hostname = "festland.mocoapp.com";
|
||||
};
|
||||
"${matcher ["oi" "one-inside"]}" = {
|
||||
"${matcher [
|
||||
"oi"
|
||||
"one-inside"
|
||||
]}" =
|
||||
{
|
||||
hostname = "one-inside.mocoapp.com";
|
||||
};
|
||||
"${matcher ["se" "scope-engineering"]}" = {
|
||||
"${matcher [
|
||||
"se"
|
||||
"scope-engineering"
|
||||
]}" =
|
||||
{
|
||||
hostname = "scope-engineering.mocoapp.com";
|
||||
};
|
||||
"${matcher ["cpc" "cpc-ag"]}" = {
|
||||
"${matcher [
|
||||
"cpc"
|
||||
"cpc-ag"
|
||||
]}" =
|
||||
{
|
||||
hostname = "cpc-ag.mocoapp.com";
|
||||
};
|
||||
"${matcher [ "weareact3" ]}" = {
|
||||
@@ -185,7 +214,11 @@ in
|
||||
"${matcher [ "staging-v6" ]}" = {
|
||||
hostname = "staging-v6.mocoapp.com";
|
||||
};
|
||||
"${matcher ["prod-db" "production-db"]}" = {
|
||||
"${matcher [
|
||||
"prod-db"
|
||||
"production-db"
|
||||
]}" =
|
||||
{
|
||||
hostname = "production-db.mocoapp";
|
||||
};
|
||||
"${matcher [ "pdf-renderer" ]}" = {
|
||||
|
||||
43
home/modules/elephant/default.nix
Normal file
43
home/modules/elephant/default.nix
Normal file
@@ -0,0 +1,43 @@
|
||||
{
|
||||
config,
|
||||
lib,
|
||||
pkgs,
|
||||
pkgs-unstable,
|
||||
...
|
||||
}:
|
||||
let
|
||||
cfg = config.services.elephant;
|
||||
wrappedPackage = pkgs.symlinkJoin {
|
||||
inherit (cfg.package) name meta;
|
||||
paths = [ cfg.package ];
|
||||
nativeBuildInputs = [ pkgs.makeBinaryWrapper ];
|
||||
postBuild = ''
|
||||
wrapProgram $out/bin/elephant \
|
||||
--prefix PATH : ${lib.makeBinPath [ pkgs.bash ]}
|
||||
'';
|
||||
};
|
||||
in
|
||||
{
|
||||
options.services.elephant = {
|
||||
enable = lib.mkEnableOption "Enable Elephant";
|
||||
package = lib.mkOption {
|
||||
type = lib.types.package;
|
||||
default = pkgs-unstable.elephant;
|
||||
};
|
||||
};
|
||||
|
||||
config = lib.mkIf cfg.enable {
|
||||
systemd.user.services.elephant = {
|
||||
Unit = {
|
||||
Description = "Elephant";
|
||||
After = [ "niri.service" ];
|
||||
Wants = [ "niri.service" ];
|
||||
};
|
||||
Service = {
|
||||
ExecStart = lib.getExe wrappedPackage;
|
||||
Restart = "on-failure";
|
||||
};
|
||||
Install.WantedBy = [ "graphical-session.target" ];
|
||||
};
|
||||
};
|
||||
}
|
||||
@@ -1,392 +0,0 @@
|
||||
{ config, pkgs, lib, ... }:
|
||||
let
|
||||
cfg = config.programs.neovim;
|
||||
toLua = lib.generators.toLua { };
|
||||
buildPluginConfig = p:
|
||||
let
|
||||
pluginConfig = if builtins.hasAttr "plugin" p then p else { plugin = p; };
|
||||
name = pluginConfig.plugin.name;
|
||||
|
||||
config = if (builtins.isNull pluginConfig.config or null) then "" else pluginConfig.config;
|
||||
mappings = if (builtins.isNull pluginConfig.mappings or null) then "" else generateMappings pluginConfig.mappings;
|
||||
mergedConfig = config + mappings;
|
||||
in
|
||||
[
|
||||
{
|
||||
plugin = pluginConfig.plugin;
|
||||
config = lib.modules.mkIf (mergedConfig != "") ''
|
||||
Plugins[${toLua name}] = {}
|
||||
Plugins[${toLua name}].setup = function()
|
||||
${lib.strings.concatMapStrings
|
||||
(line: if line == "" then "" else " ${line}\n")
|
||||
(lib.strings.splitString "\n" mergedConfig)
|
||||
|
||||
}
|
||||
end
|
||||
|
||||
Plugins[${toLua name}].setup()
|
||||
'';
|
||||
type = "lua";
|
||||
}
|
||||
] ++ (
|
||||
lib.lists.concatMap buildPluginConfig pluginConfig.dependencies or [ ]
|
||||
);
|
||||
|
||||
lspPluginConfig = with pkgs.vimPlugins; {
|
||||
plugin = nvim-lspconfig;
|
||||
dependencies = [
|
||||
nvim-cmp
|
||||
cmp-nvim-lsp
|
||||
cmp_luasnip
|
||||
luasnip
|
||||
];
|
||||
|
||||
config = (builtins.readFile ./lsp-config.lua) + ''
|
||||
local capabilities = vim.lsp.protocol.make_client_capabilities()
|
||||
capabilities.workspace.didChangeWatchedFiles.dynamicRegistration = true
|
||||
local lspconfig = require('lspconfig')
|
||||
local util = require('lspconfig.util')
|
||||
|
||||
local on_attach = function (client, bufnr)
|
||||
local function buf_set_option(...) vim.api.nvim_buf_set_option(bufnr, ...) end
|
||||
local map = function (lhs, rhs)
|
||||
print('set mapping ' .. lhs)
|
||||
end
|
||||
|
||||
-- Enable completion triggered by <c-x><c-o>
|
||||
buf_set_option('omnifunc', 'v:lua.vim.lsp.omnifunc')
|
||||
|
||||
-- Mappings.
|
||||
-- See `:help vim.lsp.*` for documentation on any of the below functions
|
||||
|
||||
${lib.strings.concatLines (lib.attrsets.mapAttrsToList (name: value: ''
|
||||
local buf_${name} = vim.lsp.buf[${toLua name}]
|
||||
if buf_${name} then
|
||||
vim.keymap.set('n', ${toLua value}, buf_${name}, { buffer = bufnr })
|
||||
end
|
||||
''
|
||||
) cfg.lsp.mappings.buf)}
|
||||
${lib.strings.concatLines (lib.attrsets.mapAttrsToList (name: value: ''
|
||||
local diagnostic_${name} = vim.lsp.buf[${toLua name}]
|
||||
if diagnostic_${name} then
|
||||
vim.keymap.set('n', ${toLua value}, diagnostic_${name}, { buffer = bufnr })
|
||||
end
|
||||
'') cfg.lsp.mappings.diagnostic)}
|
||||
end
|
||||
|
||||
vim.env.PATH = ${toLua (lib.makeBinPath (map (s: s.package) (builtins.filter (s: builtins.hasAttr "package" s) cfg.lsp.servers)) + ":")} .. vim.env.PATH
|
||||
local servers = ${toLua (map (
|
||||
{ name, config ? {}, rootPattern ? null, ... }: {
|
||||
inherit name;
|
||||
config = config // (if (builtins.isNull rootPattern) then {} else { inherit rootPattern; });
|
||||
}
|
||||
) cfg.lsp.servers)}
|
||||
|
||||
for _, server in ipairs(servers) do
|
||||
local server_config = server.config
|
||||
server_config.on_attach = on_attach
|
||||
server_config.capabilities = capabilities
|
||||
server_config.flags = {
|
||||
debounce_text_changes = 150
|
||||
}
|
||||
|
||||
if server_config.rootPattern then
|
||||
server_config.root_dir = util.root_pattern(
|
||||
unpack(server_config.rootPattern)
|
||||
)
|
||||
end
|
||||
|
||||
lspconfig[server.name].setup(server_config)
|
||||
end
|
||||
'';
|
||||
|
||||
};
|
||||
|
||||
treesitterPluginConfig = with pkgs.vimPlugins; {
|
||||
plugin = nvim-treesitter.withPlugins cfg.withTreesitterPlugins;
|
||||
config = ''
|
||||
require('nvim-treesitter.configs').setup(${toLua {
|
||||
highlight = {
|
||||
enable = true;
|
||||
additional_vim_regex_highlighting = false;
|
||||
};
|
||||
}});
|
||||
'';
|
||||
};
|
||||
|
||||
formatterPluginConfig = with pkgs.vimPlugins; {
|
||||
plugin = formatter-nvim;
|
||||
config = ''
|
||||
local formatter = require('formatter')
|
||||
local util = require('formatter.util')
|
||||
|
||||
formatter.setup({
|
||||
filetype = {
|
||||
${lib.strings.concatMapStringsSep ",\n " ({ exe, args, stdin, no_append, filetypes, ... }:
|
||||
lib.strings.concatMapStringsSep ",\n " (filetype: ''
|
||||
[${toLua filetype}] = {
|
||||
function ()
|
||||
return {
|
||||
exe = ${toLua exe},
|
||||
args = {
|
||||
${lib.strings.concatMapStringsSep ",\n " (arg:
|
||||
if arg == "<<FILE>>"
|
||||
then "util.escape_path(util.get_current_buffer_file_path())"
|
||||
else toLua arg
|
||||
) (args "<<FILE>>")}
|
||||
},
|
||||
stdin = ${toLua stdin},
|
||||
no_append = ${toLua no_append},
|
||||
}
|
||||
end
|
||||
}
|
||||
'') filetypes
|
||||
) cfg.formatters}
|
||||
}
|
||||
})
|
||||
${generateAutoCommand {
|
||||
event = "BufWritePost";
|
||||
pattern = lib.lists.concatMap ({ globs, ... }: globs) cfg.formatters;
|
||||
command = "FormatWrite";
|
||||
group = "FormatAutogroup";
|
||||
}}
|
||||
'';
|
||||
};
|
||||
|
||||
customTypes = let inherit (lib) mkOption mkEnableOption types; in {
|
||||
mapping = types.submodule {
|
||||
options = {
|
||||
rhs = mkOption { type = types.str; };
|
||||
lua = mkEnableOption { };
|
||||
options = mkOption {
|
||||
type = types.nullOr (
|
||||
types.submodule {
|
||||
options = {
|
||||
buffer = mkOption { type = types.nullOr (types.either types.int types.bool); default = null; };
|
||||
nowait = mkOption { type = types.nullOr types.bool; default = null; };
|
||||
silent = mkOption { type = types.nullOr types.bool; default = null; };
|
||||
expr = mkOption { type = types.nullOr types.bool; default = null; };
|
||||
script = mkOption { type = types.nullOr types.bool; default = null; };
|
||||
unique = mkOption { type = types.nullOr types.bool; default = null; };
|
||||
replace_keycodes = mkOption { type = types.nullOr types.bool; default = null; };
|
||||
};
|
||||
}
|
||||
);
|
||||
default = { };
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
modeMappings = types.attrsOf (types.either types.str customTypes.mapping);
|
||||
|
||||
mappings = types.submodule {
|
||||
options = {
|
||||
normal = mkOption { type = customTypes.modeMappings; default = { }; };
|
||||
insert = mkOption { type = customTypes.modeMappings; default = { }; };
|
||||
visual = mkOption { type = customTypes.modeMappings; default = { }; };
|
||||
command = mkOption { type = customTypes.modeMappings; default = { }; };
|
||||
select = mkOption { type = customTypes.modeMappings; default = { }; };
|
||||
};
|
||||
};
|
||||
|
||||
plugin = types.either types.package (types.submodule {
|
||||
options = {
|
||||
plugin = mkOption { type = types.package; };
|
||||
dependencies = mkOption {
|
||||
type = types.listOf customTypes.plugin;
|
||||
default = [ ];
|
||||
};
|
||||
mappings = mkOption { type = customTypes.mappings; default = { }; };
|
||||
config = mkOption { type = types.nullOr types.str; default = null; };
|
||||
};
|
||||
});
|
||||
|
||||
autoCommand = types.submodule {
|
||||
options = {
|
||||
event = mkOption { type = types.either types.str (types.listOf types.str); };
|
||||
pattern = mkOption { type = types.either types.str (types.listOf types.str); };
|
||||
command = mkOption { type = types.str; };
|
||||
};
|
||||
};
|
||||
|
||||
lspServer = types.submodule {
|
||||
options = {
|
||||
name = mkOption { type = types.str; };
|
||||
config = mkOption { type = types.attrs; default = { }; };
|
||||
package = mkOption { type = types.nullOr types.package; default = null; };
|
||||
rootPattern = mkOption { type = types.nullOr (types.listOf types.str); default = null; };
|
||||
};
|
||||
};
|
||||
|
||||
formatter = types.submodule {
|
||||
options = {
|
||||
filetypes = mkOption { type = types.listOf types.str; };
|
||||
globs = mkOption { type = types.listOf types.str; };
|
||||
exe = mkOption { type = types.either types.path types.str; };
|
||||
args = mkOption { type = types.functionTo (types.listOf types.str); default = _: [ ]; };
|
||||
stdin = mkEnableOption { };
|
||||
no_append = mkEnableOption { };
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
generateMappings = mappings: lib.strings.concatLines (
|
||||
lib.attrsets.mapAttrsToList
|
||||
(mode: modeMappings:
|
||||
lib.strings.concatLines (
|
||||
lib.attrsets.mapAttrsToList
|
||||
(name: value:
|
||||
|
||||
let
|
||||
mapping = { lhs = name; lua = false; options = { }; } // (if builtins.isString value then { rhs = value; } else value);
|
||||
args = [
|
||||
(toLua (builtins.substring 0 1 mode))
|
||||
(toLua mapping.lhs)
|
||||
(if mapping.lua then mapping.rhs else toLua mapping.rhs)
|
||||
(
|
||||
toLua (
|
||||
builtins.listToAttrs (
|
||||
builtins.filter ({ value, ... }: !isNull (value)) (lib.attrsets.attrsToList mapping.options)
|
||||
)
|
||||
)
|
||||
)
|
||||
];
|
||||
in
|
||||
"vim.keymap.set(${lib.strings.concatStringsSep ", " args})"
|
||||
)
|
||||
modeMappings
|
||||
)
|
||||
)
|
||||
mappings
|
||||
);
|
||||
|
||||
generateAutoCommand = { event, pattern, command, group ? null }: ''
|
||||
vim.api.nvim_create_autocmd(${toLua event}, {
|
||||
pattern = ${toLua pattern},
|
||||
command = ${toLua command},
|
||||
group = ${if isNull group then toLua group else ''
|
||||
vim.api.nvim_create_augroup(${toLua group}, { clear = true })
|
||||
''},
|
||||
})
|
||||
'';
|
||||
|
||||
generateAutoCommands = autoCommands: lib.strings.concatLines (
|
||||
map generateAutoCommand autoCommands
|
||||
);
|
||||
|
||||
generateSignDefinitions = signs: lib.strings.concatLines (
|
||||
lib.attrsets.mapAttrsToList
|
||||
(name: value:
|
||||
let
|
||||
hl = "DiagnosticSign${lib.strings.toUpper (builtins.substring 0 1 name)}${builtins.substring 1 (-1) name}";
|
||||
in
|
||||
"vim.fn.sign_define(${toLua hl}, ${toLua { text = value; texthl = hl; numhl = ""; }})"
|
||||
)
|
||||
signs
|
||||
);
|
||||
in
|
||||
{
|
||||
options.programs.neovim =
|
||||
let
|
||||
inherit (lib) mkOption types;
|
||||
in
|
||||
{
|
||||
mappings = mkOption { type = customTypes.mappings; default = { }; };
|
||||
plug = mkOption {
|
||||
type = types.listOf customTypes.plugin;
|
||||
default = [ ];
|
||||
};
|
||||
leader = mkOption { type = types.str; default = "\\"; };
|
||||
options = mkOption {
|
||||
type = types.attrs;
|
||||
default = { };
|
||||
};
|
||||
snippets = mkOption {
|
||||
type = types.attrsOf types.path;
|
||||
default = { };
|
||||
};
|
||||
autoCommands = mkOption {
|
||||
type = types.listOf customTypes.autoCommand;
|
||||
default = [ ];
|
||||
};
|
||||
env = mkOption {
|
||||
type = types.attrsOf types.str;
|
||||
default = { };
|
||||
};
|
||||
signs = {
|
||||
error = mkOption { type = types.str; default = ""; };
|
||||
warning = mkOption { type = types.str; default = ""; };
|
||||
info = mkOption { type = types.str; default = ""; };
|
||||
hint = mkOption { type = types.str; default = ""; };
|
||||
};
|
||||
lsp = {
|
||||
servers = mkOption {
|
||||
type = types.listOf customTypes.lspServer;
|
||||
default = [ ];
|
||||
};
|
||||
mappings = {
|
||||
buf = mkOption { type = types.attrsOf types.str; default = { }; };
|
||||
diagnostic = mkOption { type = types.attrsOf types.str; default = { }; };
|
||||
};
|
||||
};
|
||||
withTreesitterPlugins = mkOption {
|
||||
type = types.functionTo (types.listOf types.package);
|
||||
default = _: [ ];
|
||||
};
|
||||
formatters = mkOption {
|
||||
type = types.listOf customTypes.formatter;
|
||||
default = [ ];
|
||||
};
|
||||
};
|
||||
|
||||
config = {
|
||||
programs.neovim = {
|
||||
extraLuaConfig = lib.strings.concatLines [
|
||||
"local Plugins = {}"
|
||||
(generateMappings cfg.mappings)
|
||||
(generateAutoCommands cfg.autoCommands)
|
||||
(lib.strings.concatLines (lib.attrsets.mapAttrsToList (name: value: "vim.env.${name} = ${toLua value}") cfg.env))
|
||||
(lib.strings.concatLines (lib.attrsets.mapAttrsToList (name: value: "vim.opt.${name} = ${toLua value}") cfg.options))
|
||||
(generateSignDefinitions cfg.signs)
|
||||
"vim.g.mapleader = ${toLua cfg.leader}"
|
||||
''
|
||||
local undodir = ${toLua (
|
||||
if builtins.hasAttr "undodir" cfg.options
|
||||
then cfg.options.undodir
|
||||
else "${config.xdg.cacheHome}/nvim/undo"
|
||||
)}
|
||||
vim.opt.undodir = undodir
|
||||
vim.fn.mkdir(undodir, 'p')
|
||||
''
|
||||
];
|
||||
plugins = lib.lists.concatMap buildPluginConfig (
|
||||
cfg.plug ++ [
|
||||
lspPluginConfig
|
||||
treesitterPluginConfig
|
||||
formatterPluginConfig
|
||||
]
|
||||
);
|
||||
vimAlias = lib.mkForce false;
|
||||
vimdiffAlias = lib.mkForce false;
|
||||
};
|
||||
|
||||
xdg.configFile = (
|
||||
lib.attrsets.mapAttrs'
|
||||
(name: value: {
|
||||
name = "nvim/${name}";
|
||||
value = { source = value; };
|
||||
})
|
||||
cfg.snippets
|
||||
);
|
||||
|
||||
home.shellAliases =
|
||||
let
|
||||
nvim = ''nvim --listen "$XDG_RUNTIME_DIR/nvimsocket"'';
|
||||
in
|
||||
{
|
||||
inherit nvim;
|
||||
vim = nvim;
|
||||
vimdiff = "${nvim} -d";
|
||||
};
|
||||
};
|
||||
}
|
||||
@@ -1,89 +0,0 @@
|
||||
local Lsp = {}
|
||||
|
||||
Lsp.setup = function()
|
||||
local luasnip = require("luasnip")
|
||||
local cmp = require("cmp")
|
||||
|
||||
local has_words_before = function()
|
||||
if vim.api.nvim_buf_get_option(0, "buftype") == "prompt" then
|
||||
return false
|
||||
end
|
||||
local line, col = unpack(vim.api.nvim_win_get_cursor(0))
|
||||
return col ~= 0 and vim.api.nvim_buf_get_text(0, line - 1, 0, line - 1, col, {})[1]:match("^%s*$") == nil
|
||||
end
|
||||
|
||||
cmp.setup({
|
||||
snippet = {
|
||||
expand = function(args)
|
||||
luasnip.lsp_expand(args.body)
|
||||
end,
|
||||
},
|
||||
window = {
|
||||
completion = cmp.config.window.bordered(),
|
||||
documentation = cmp.config.window.bordered(),
|
||||
},
|
||||
mapping = {
|
||||
["<C-p>"] = function()
|
||||
if luasnip.jumpable(-1) then
|
||||
luasnip.jump(-1)
|
||||
else
|
||||
cmp.mapping.select_prev_item()
|
||||
end
|
||||
end,
|
||||
["<C-n>"] = function()
|
||||
if luasnip.expand_or_jumpable() then
|
||||
luasnip.expand_or_jump()
|
||||
else
|
||||
cmp.mapping.select_next_item()
|
||||
end
|
||||
end,
|
||||
["<C-d>"] = cmp.mapping.scroll_docs(-4),
|
||||
["<C-f>"] = cmp.mapping.scroll_docs(4),
|
||||
["<C-Space>"] = cmp.mapping.complete(),
|
||||
["<C-e>"] = cmp.mapping.close(),
|
||||
["<CR>"] = cmp.mapping.confirm({
|
||||
behavior = cmp.ConfirmBehavior.Replace,
|
||||
select = true,
|
||||
}),
|
||||
["<Tab>"] = function(fallback)
|
||||
if cmp.visible() and has_words_before() then
|
||||
cmp.select_next_item()
|
||||
else
|
||||
fallback()
|
||||
end
|
||||
end,
|
||||
["<S-Tab>"] = function(fallback)
|
||||
if cmp.visible() and has_words_before() then
|
||||
cmp.select_prev_item()
|
||||
else
|
||||
fallback()
|
||||
end
|
||||
end,
|
||||
},
|
||||
sources = {
|
||||
{ name = "copilot", group_index = 2 },
|
||||
{ name = "nvim_lsp", group_index = 2 },
|
||||
{ name = "luasnip", group_index = 2 },
|
||||
},
|
||||
})
|
||||
|
||||
vim.o.completeopt = "menuone,noselect"
|
||||
vim.o.updatetime = 250
|
||||
vim.cmd([[autocmd CursorHold,CursorHoldI * lua vim.diagnostic.open_float(nil, {focus=false})]])
|
||||
vim.lsp.handlers["textDocument/publishDiagnostics"] = vim.lsp.with(vim.lsp.diagnostic.on_publish_diagnostics, {
|
||||
virtual_text = {
|
||||
source = "if_many",
|
||||
},
|
||||
})
|
||||
|
||||
vim.lsp.handlers["textDocument/hover"] = vim.lsp.with(vim.lsp.handlers.hover, { border = "rounded" })
|
||||
|
||||
vim.lsp.handlers["textDocument/signatureHelp"] =
|
||||
vim.lsp.with(vim.lsp.handlers.signature_help, { border = "rounded" })
|
||||
|
||||
vim.diagnostic.config({
|
||||
float = { border = "rounded", zindex = 1 },
|
||||
})
|
||||
end
|
||||
|
||||
Lsp.setup()
|
||||
92
home/modules/voxtype/default.nix
Normal file
92
home/modules/voxtype/default.nix
Normal file
@@ -0,0 +1,92 @@
|
||||
{
|
||||
config,
|
||||
osConfig,
|
||||
lib,
|
||||
pkgs,
|
||||
pkgs-unstable,
|
||||
...
|
||||
}:
|
||||
let
|
||||
cfg = config.programs.voxtype;
|
||||
postProcessUnwrapped =
|
||||
pkgs.runCommand "voxtype-post-process-unwrapped"
|
||||
{
|
||||
code = ./post-process.cr;
|
||||
nativeBuildInputs = [
|
||||
pkgs-unstable.crystal
|
||||
];
|
||||
}
|
||||
''
|
||||
mkdir -p $out/bin
|
||||
crystal build $code -o $out/bin/voxtype-post-process
|
||||
'';
|
||||
|
||||
postProcess = pkgs.symlinkJoin {
|
||||
name = "voxtype-post-process";
|
||||
paths = [ postProcessUnwrapped ];
|
||||
nativeBuildInputs = [ pkgs.makeBinaryWrapper ];
|
||||
postBuild = ''
|
||||
wrapProgram $out/bin/voxtype-post-process \
|
||||
--set OLLAMA_PORT ${toString osConfig.services.ollama.port} \
|
||||
--set WALKER_BIN ${lib.getExe config.services.walker.package}
|
||||
'';
|
||||
meta.mainProgram = "voxtype-post-process";
|
||||
};
|
||||
in
|
||||
{
|
||||
options.programs.voxtype = {
|
||||
postProcessing = lib.mkOption {
|
||||
type = lib.types.submodule {
|
||||
options = {
|
||||
enable = lib.mkEnableOption "Enable post-processing of transcriptions";
|
||||
settings = lib.mkOption {
|
||||
type = lib.types.submodule {
|
||||
options = {
|
||||
model = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
description = "The ollama model to use for post-processing";
|
||||
};
|
||||
commonInstructions = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = "no quotes, no emojis, no explanations";
|
||||
description = "Instructions to include in every post-processing prompt";
|
||||
};
|
||||
prompts = lib.mkOption {
|
||||
type = lib.types.listOf (
|
||||
lib.types.submodule {
|
||||
options = {
|
||||
title = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
description = "A title for this prompt, used in the selector";
|
||||
};
|
||||
instructions = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
description = "Instructions to include in the post-processing prompt, in addition to the common instructions";
|
||||
};
|
||||
};
|
||||
}
|
||||
);
|
||||
default = [
|
||||
{
|
||||
title = "Clean up";
|
||||
instructions = "Clean up this dictation. Remove filler words, fix grammar and punctuation. Output ONLY the cleaned text";
|
||||
}
|
||||
];
|
||||
};
|
||||
};
|
||||
};
|
||||
default = { };
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
config = lib.mkIf cfg.postProcessing.enable {
|
||||
xdg.configFile."voxtype/post-processing.json".text = builtins.toJSON cfg.postProcessing.settings;
|
||||
programs.voxtype.settings.output.post_process = {
|
||||
command = lib.getExe postProcess;
|
||||
timeout_ms = 5 * 60 * 1000; # 5 minutes
|
||||
};
|
||||
};
|
||||
}
|
||||
54
home/modules/voxtype/post-process.cr
Normal file
54
home/modules/voxtype/post-process.cr
Normal file
@@ -0,0 +1,54 @@
|
||||
require "json"
|
||||
require "http/client"
|
||||
|
||||
struct OllamaResponse
|
||||
include JSON::Serializable
|
||||
|
||||
getter response : String
|
||||
end
|
||||
|
||||
struct Prompt
|
||||
include JSON::Serializable
|
||||
|
||||
getter title : String
|
||||
getter instructions : String
|
||||
end
|
||||
|
||||
struct Config
|
||||
include JSON::Serializable
|
||||
|
||||
getter model : String
|
||||
getter prompts : Array(Prompt)
|
||||
@[JSON::Field(key: "commonInstructions")]
|
||||
getter common_instructions : String
|
||||
end
|
||||
|
||||
config_path = "#{ENV.fetch("XDG_CONFIG_HOME", "~/.config")}/voxtype/post-processing.json"
|
||||
config = File.open(config_path) { |file| Config.from_json(file) }
|
||||
client = HTTP::Client.new("localhost", ENV.fetch("OLLAMA_PORT", "11434").to_i)
|
||||
|
||||
prompt_selection = Process.run(ENV["WALKER_BIN"], ["--dmenu"]) do |process|
|
||||
config.prompts.each do |prompt|
|
||||
process.input.puts prompt.title
|
||||
end
|
||||
|
||||
process.input.close
|
||||
process.output.gets_to_end.chomp
|
||||
end
|
||||
|
||||
instructions = config.prompts.find { |prompt| prompt.title == prompt_selection }.try(&.instructions) || prompt_selection
|
||||
|
||||
payload = {
|
||||
model: config.model,
|
||||
prompt: "#{instructions} - #{config.common_instructions}:\n\n#{STDIN.gets_to_end.chomp}",
|
||||
think: false,
|
||||
stream: false,
|
||||
}
|
||||
|
||||
client.post("/api/generate", body: payload.to_json) do |response|
|
||||
if response.status_code == 200
|
||||
puts OllamaResponse.from_json(response.body_io).response.strip
|
||||
else
|
||||
abort "Ollama API error: #{response.status_code} #{response.body}"
|
||||
end
|
||||
end
|
||||
469
home/modules/zed/default.nix
Normal file
469
home/modules/zed/default.nix
Normal file
@@ -0,0 +1,469 @@
|
||||
{
|
||||
config,
|
||||
lib,
|
||||
pkgs,
|
||||
pkgs-unstable,
|
||||
...
|
||||
}:
|
||||
let
|
||||
cfg = config.programs.zed-editor;
|
||||
ameba-ls = pkgs.stdenv.mkDerivation rec {
|
||||
pname = "ameba-ls";
|
||||
version = "0.1.0";
|
||||
|
||||
src =
|
||||
let
|
||||
selectSystem =
|
||||
attrs:
|
||||
attrs.${pkgs.stdenv.hostPlatform.system}
|
||||
or (throw "Unsupported system: ${pkgs.stdenv.hostPlatform.system}");
|
||||
in
|
||||
pkgs.fetchurl (selectSystem {
|
||||
x86_64-linux = {
|
||||
url = "https://github.com/crystal-lang-tools/ameba-ls/releases/download/v${version}/ameba-ls-${version}-x86_64-linux-musl.tar.gz";
|
||||
hash = "sha256-NtqR8NHytuHT1XIhRVvnp7Lo4Ed9UGbISbTn/BfLGA8=";
|
||||
};
|
||||
aarch64-linux = {
|
||||
url = "https://github.com/crystal-lang-tools/ameba-ls/releases/download/v${version}/ameba-ls-${version}-aarch64-linux-musl.tar.gz";
|
||||
hash = "sha256-77iqdaI+Mqivk0/9jkNdGpluDbz297vsY9wzuipcPOU=";
|
||||
};
|
||||
aarch64-darwin = {
|
||||
url = "https://github.com/crystal-lang-tools/ameba-ls/releases/download/v${version}/ameba-ls-${version}-aarch64-apple-darwin.tar.gz";
|
||||
hash = "sha256-tDB+ZjgjlGjNg3DjX09z1dJnqTv9h/1sXiauBj7uHNc=";
|
||||
};
|
||||
});
|
||||
|
||||
sourceRoot = ".";
|
||||
|
||||
installPhase = ''
|
||||
runHook preInstall
|
||||
mkdir -p $out/bin
|
||||
cp ameba-ls $out/bin/
|
||||
chmod +x $out/bin/ameba-ls
|
||||
runHook postInstall
|
||||
'';
|
||||
|
||||
meta = with lib; {
|
||||
description = "Language server for the Ameba linter for Crystal lang";
|
||||
homepage = "https://github.com/crystal-lang-tools/ameba-ls";
|
||||
license = licenses.mit;
|
||||
platforms = [
|
||||
"x86_64-linux"
|
||||
"aarch64-linux"
|
||||
"aarch64-darwin"
|
||||
];
|
||||
mainProgram = "ameba-ls";
|
||||
};
|
||||
};
|
||||
in
|
||||
{
|
||||
options.programs.zed-editor = {
|
||||
defaultEditor = lib.mkOption {
|
||||
type = lib.types.bool;
|
||||
default = false;
|
||||
};
|
||||
};
|
||||
|
||||
config = lib.mkIf cfg.enable {
|
||||
programs.zed-editor = {
|
||||
package = pkgs-unstable.zed-editor;
|
||||
extensions = [
|
||||
"ruby"
|
||||
"crystal"
|
||||
"nix"
|
||||
"svelte"
|
||||
];
|
||||
userSettings = {
|
||||
node = {
|
||||
path = lib.getExe pkgs.nodejs_latest;
|
||||
npm_path = lib.getExe' pkgs.nodejs_latest "npm";
|
||||
};
|
||||
agent = {
|
||||
enabled = true;
|
||||
default_model = {
|
||||
provider = "openai";
|
||||
model = "kimi-k2.5";
|
||||
};
|
||||
};
|
||||
auto_update = false;
|
||||
telemetry = {
|
||||
diagnostics = false;
|
||||
metrics = false;
|
||||
};
|
||||
vim_mode = true;
|
||||
languages = {
|
||||
Ruby = {
|
||||
language_servers = [
|
||||
"ruby-lsp"
|
||||
"rubocop"
|
||||
"!solargraph"
|
||||
];
|
||||
formatter.external = {
|
||||
command = pkgs.writeShellScript "rufo" ''
|
||||
bundle exec rufo "$@"
|
||||
if [ $? -eq 1 ]; then
|
||||
exit 1
|
||||
fi
|
||||
'';
|
||||
arguments = [
|
||||
"--filename"
|
||||
"{buffer_path}"
|
||||
];
|
||||
};
|
||||
};
|
||||
Nix = {
|
||||
formatter.external = {
|
||||
command = lib.getExe pkgs.nixfmt-rfc-style;
|
||||
arguments = [ "-q" ];
|
||||
};
|
||||
};
|
||||
Rust = {
|
||||
formatter.external = {
|
||||
command = lib.getExe pkgs.rustfmt;
|
||||
arguments = [
|
||||
"--edition"
|
||||
"2018"
|
||||
];
|
||||
};
|
||||
};
|
||||
Crystal = {
|
||||
language_servers = [
|
||||
"crystalline"
|
||||
"ameba-ls"
|
||||
];
|
||||
formatter.external = {
|
||||
command = lib.getExe pkgs.crystal;
|
||||
arguments = [
|
||||
"tool"
|
||||
"format"
|
||||
"--no-color"
|
||||
"-"
|
||||
];
|
||||
};
|
||||
};
|
||||
};
|
||||
lsp = with pkgs; {
|
||||
nixd.binary.path = lib.getExe nixd;
|
||||
nil.binary.path = lib.getExe nil;
|
||||
ruby-lsp = {
|
||||
initialization_options = {
|
||||
enabledFeatures = {
|
||||
codeActions = true;
|
||||
codeLens = true;
|
||||
completion = true;
|
||||
definition = true;
|
||||
diagnostics = true;
|
||||
documentHighlights = true;
|
||||
documentLink = true;
|
||||
documentSymbols = true;
|
||||
foldingRanges = true;
|
||||
formatting = false;
|
||||
hover = true;
|
||||
inlayHint = true;
|
||||
onTypeFormatting = true;
|
||||
selectionRanges = true;
|
||||
semanticHighlighting = true;
|
||||
signatureHelp = true;
|
||||
typeHierarchy = true;
|
||||
workspaceSymbol = true;
|
||||
};
|
||||
linters = [ "standard" ];
|
||||
};
|
||||
settings.use_bundler = true;
|
||||
};
|
||||
rubocop.binary = {
|
||||
path = "bundle";
|
||||
arguments = [
|
||||
"exec"
|
||||
"rubocop"
|
||||
"--lsp"
|
||||
];
|
||||
};
|
||||
yaml-language-server.binary = {
|
||||
path = lib.getExe yaml-language-server;
|
||||
arguments = [ "--stdio" ];
|
||||
};
|
||||
json-language-server.binary = {
|
||||
path = lib.getExe nodePackages.vscode-json-languageserver;
|
||||
arguments = [ "--stdio" ];
|
||||
};
|
||||
package-version-server.binary.path = lib.getExe pkgs-unstable.package-version-server;
|
||||
eslint.settings.onIgnoredFiles = "off";
|
||||
crystalline.binary.path = lib.getExe crystalline;
|
||||
ameba-ls.binary.path = lib.getExe ameba-ls;
|
||||
rust-analyzer.binary.path = lib.getExe rust-analyzer;
|
||||
};
|
||||
load_direnv = "shell_hook";
|
||||
theme = {
|
||||
mode = "system";
|
||||
light = "One Light";
|
||||
dark = "One Dark";
|
||||
};
|
||||
terminal = {
|
||||
line_height = "standard";
|
||||
font_family = "IosevkaTerm Nerd Font";
|
||||
};
|
||||
edit_predictions = {
|
||||
enabled = true;
|
||||
mode = "eager";
|
||||
provider = "copilot";
|
||||
};
|
||||
buffer_font_family = "Iosevka Nerd Font";
|
||||
buffer_font_size = 16;
|
||||
ui_font_size = 17;
|
||||
relative_line_numbers = "enabled";
|
||||
file_types = {
|
||||
JSONC = [
|
||||
"tsconfig.json"
|
||||
"tsconfig.*.json"
|
||||
];
|
||||
};
|
||||
language_models = {
|
||||
openai = {
|
||||
api_url = "https://opencode.ai/zen/v1";
|
||||
available_models = [
|
||||
# Claude models
|
||||
{
|
||||
name = "claude-opus-4-6";
|
||||
display_name = "OpenCode Zen - Claude Opus 4.6";
|
||||
max_tokens = 1048576;
|
||||
}
|
||||
{
|
||||
name = "claude-opus-4-5";
|
||||
display_name = "OpenCode Zen - Claude Opus 4.5";
|
||||
max_tokens = 200000;
|
||||
}
|
||||
{
|
||||
name = "claude-opus-4-1";
|
||||
display_name = "OpenCode Zen - Claude Opus 4.1";
|
||||
max_tokens = 200000;
|
||||
}
|
||||
{
|
||||
name = "claude-sonnet-4";
|
||||
display_name = "OpenCode Zen - Claude Sonnet 4";
|
||||
max_tokens = 1048576;
|
||||
}
|
||||
{
|
||||
name = "claude-sonnet-4-5";
|
||||
display_name = "OpenCode Zen - Claude Sonnet 4.5";
|
||||
max_tokens = 1048576;
|
||||
}
|
||||
{
|
||||
name = "claude-3-5-haiku";
|
||||
display_name = "OpenCode Zen - Claude 3.5 Haiku";
|
||||
max_tokens = 200000;
|
||||
}
|
||||
{
|
||||
name = "claude-haiku-4-5";
|
||||
display_name = "OpenCode Zen - Claude Haiku 4.5";
|
||||
max_tokens = 200000;
|
||||
}
|
||||
# GPT models
|
||||
{
|
||||
name = "gpt-5.2";
|
||||
display_name = "OpenCode Zen - GPT 5.2";
|
||||
max_tokens = 400000;
|
||||
}
|
||||
{
|
||||
name = "gpt-5.2-codex";
|
||||
display_name = "OpenCode Zen - GPT 5.2 Codex";
|
||||
max_tokens = 400000;
|
||||
}
|
||||
{
|
||||
name = "gpt-5.1";
|
||||
display_name = "OpenCode Zen - GPT 5.1";
|
||||
max_tokens = 400000;
|
||||
}
|
||||
{
|
||||
name = "gpt-5.1-codex-max";
|
||||
display_name = "OpenCode Zen - GPT 5.1 Codex Max";
|
||||
max_tokens = 400000;
|
||||
}
|
||||
{
|
||||
name = "gpt-5.1-codex";
|
||||
display_name = "OpenCode Zen - GPT 5.1 Codex";
|
||||
max_tokens = 400000;
|
||||
}
|
||||
{
|
||||
name = "gpt-5.1-codex-mini";
|
||||
display_name = "OpenCode Zen - GPT 5.1 Codex Mini";
|
||||
max_tokens = 400000;
|
||||
}
|
||||
{
|
||||
name = "gpt-5";
|
||||
display_name = "OpenCode Zen - GPT 5";
|
||||
max_tokens = 400000;
|
||||
}
|
||||
{
|
||||
name = "gpt-5-codex";
|
||||
display_name = "OpenCode Zen - GPT 5 Codex";
|
||||
max_tokens = 400000;
|
||||
}
|
||||
{
|
||||
name = "gpt-5-nano";
|
||||
display_name = "OpenCode Zen - GPT 5 Nano";
|
||||
max_tokens = 400000;
|
||||
}
|
||||
# Gemini models
|
||||
{
|
||||
name = "gemini-3-pro";
|
||||
display_name = "OpenCode Zen - Gemini 3 Pro";
|
||||
max_tokens = 1048576;
|
||||
}
|
||||
{
|
||||
name = "gemini-3-flash";
|
||||
display_name = "OpenCode Zen - Gemini 3 Flash";
|
||||
max_tokens = 1048576;
|
||||
}
|
||||
# GLM models
|
||||
{
|
||||
name = "glm-4.7";
|
||||
display_name = "OpenCode Zen - GLM 4.7";
|
||||
max_tokens = 205000;
|
||||
}
|
||||
{
|
||||
name = "glm-4.6";
|
||||
display_name = "OpenCode Zen - GLM 4.6";
|
||||
max_tokens = 205000;
|
||||
}
|
||||
{
|
||||
name = "glm-4.7-free";
|
||||
display_name = "OpenCode Zen - GLM 4.7 Free";
|
||||
max_tokens = 205000;
|
||||
}
|
||||
# Kimi models
|
||||
{
|
||||
name = "kimi-k2.5";
|
||||
display_name = "OpenCode Zen - Kimi K2.5";
|
||||
max_tokens = 262000;
|
||||
}
|
||||
{
|
||||
name = "kimi-k2.5-free";
|
||||
display_name = "OpenCode Zen - Kimi K2.5 Free";
|
||||
max_tokens = 262000;
|
||||
}
|
||||
{
|
||||
name = "kimi-k2";
|
||||
display_name = "OpenCode Zen - Kimi K2";
|
||||
max_tokens = 262000;
|
||||
}
|
||||
{
|
||||
name = "kimi-k2-thinking";
|
||||
display_name = "OpenCode Zen - Kimi K2 Thinking";
|
||||
max_tokens = 262000;
|
||||
}
|
||||
# MiniMax models
|
||||
{
|
||||
name = "minimax-m2.1";
|
||||
display_name = "OpenCode Zen - MiniMax M2.1";
|
||||
max_tokens = 205000;
|
||||
}
|
||||
{
|
||||
name = "minimax-m2.5-free";
|
||||
display_name = "OpenCode Zen - MiniMax M2.5 Free";
|
||||
max_tokens = 205000;
|
||||
}
|
||||
{
|
||||
name = "minimax-m2.1-free";
|
||||
display_name = "OpenCode Zen - MiniMax M2.1 Free";
|
||||
max_tokens = 205000;
|
||||
}
|
||||
# Other models
|
||||
{
|
||||
name = "trinity-large-preview-free";
|
||||
display_name = "OpenCode Zen - Trinity Large Preview Free";
|
||||
max_tokens = 131000;
|
||||
}
|
||||
{
|
||||
name = "big-pickle";
|
||||
display_name = "OpenCode Zen - Big Pickle";
|
||||
max_tokens = 200000;
|
||||
}
|
||||
{
|
||||
name = "alpha-g5";
|
||||
display_name = "OpenCode Zen - Alpha G5";
|
||||
max_tokens = 200000;
|
||||
}
|
||||
];
|
||||
};
|
||||
};
|
||||
};
|
||||
userKeymaps = [
|
||||
{
|
||||
context = "VimControl && !menu";
|
||||
bindings = {
|
||||
"space g" = [
|
||||
"task::Spawn"
|
||||
{
|
||||
task_name = "lazygit";
|
||||
reveal_target = "center";
|
||||
}
|
||||
];
|
||||
"space o" = [
|
||||
"task::Spawn"
|
||||
{
|
||||
task_name = "opencode";
|
||||
reveal_target = "center";
|
||||
}
|
||||
];
|
||||
"space r" = "pane::DeploySearch";
|
||||
"space f" = [
|
||||
"file_finder::Toggle"
|
||||
{ separate_history = true; }
|
||||
];
|
||||
"space :" = "task::Spawn";
|
||||
"g R" = "editor::FindAllReferences";
|
||||
};
|
||||
}
|
||||
{
|
||||
context = "Dock || Pane || Editor";
|
||||
bindings = {
|
||||
"ctrl-h" = "workspace::ActivatePaneLeft";
|
||||
"ctrl-j" = "workspace::ActivatePaneDown";
|
||||
"ctrl-k" = "workspace::ActivatePaneUp";
|
||||
"ctrl-l" = "workspace::ActivatePaneRight";
|
||||
};
|
||||
}
|
||||
{
|
||||
context = "Terminal";
|
||||
bindings = {
|
||||
"ctrl-p" = [
|
||||
"terminal::SendKeystroke"
|
||||
"ctrl-p"
|
||||
];
|
||||
};
|
||||
}
|
||||
];
|
||||
|
||||
userTasks = [
|
||||
{
|
||||
label = "lazygit";
|
||||
command = lib.getExe config.programs.lazygit.package;
|
||||
env = {
|
||||
EDITOR = lib.getExe cfg.package;
|
||||
};
|
||||
args = [
|
||||
"-p"
|
||||
"$ZED_WORKTREE_ROOT"
|
||||
];
|
||||
reveal = "always";
|
||||
allow_concurrent_runs = true;
|
||||
use_new_terminal = false;
|
||||
hide = "on_success";
|
||||
}
|
||||
{
|
||||
label = "opencode";
|
||||
command = lib.getExe pkgs-unstable.opencode;
|
||||
reveal = "always";
|
||||
allow_concurrent_runs = true;
|
||||
use_new_terminal = false;
|
||||
hide = "on_success";
|
||||
}
|
||||
];
|
||||
};
|
||||
|
||||
home.sessionVariables = lib.mkIf cfg.defaultEditor {
|
||||
EDITOR = "${lib.getExe cfg.package} -w";
|
||||
};
|
||||
};
|
||||
}
|
||||
@@ -2,7 +2,13 @@
|
||||
# your system. Help is availanodev";
|
||||
# https://search.nixos.org/options and in the NixOS manual (`nixos-help`).
|
||||
|
||||
{ ssh, pkgs, config, ... }:
|
||||
{
|
||||
ssh,
|
||||
pkgs,
|
||||
config,
|
||||
lib,
|
||||
...
|
||||
}:
|
||||
{
|
||||
boot.loader.grub.enable = true;
|
||||
boot.loader.grub.device = "/dev/sda";
|
||||
@@ -12,7 +18,10 @@
|
||||
|
||||
nix = {
|
||||
settings = {
|
||||
experimental-features = [ "nix-command" "flakes" ];
|
||||
experimental-features = [
|
||||
"nix-command"
|
||||
"flakes"
|
||||
];
|
||||
auto-optimise-store = true;
|
||||
};
|
||||
|
||||
@@ -63,11 +72,28 @@
|
||||
modules.firewall = {
|
||||
enable = true;
|
||||
interfaces = {
|
||||
koti = [ "dhcp" "dns" "ssh" "web" ];
|
||||
gast = [ "dhcp" "dns" ];
|
||||
iot = [ "dhcp" "dns" ];
|
||||
cfg = [ "dhcp" "dns" ];
|
||||
"tailscale*" = [ "ssh" "web" ];
|
||||
koti = [
|
||||
"dhcp"
|
||||
"dns"
|
||||
"ssh"
|
||||
"web"
|
||||
];
|
||||
gast = [
|
||||
"dhcp"
|
||||
"dns"
|
||||
];
|
||||
iot = [
|
||||
"dhcp"
|
||||
"dns"
|
||||
];
|
||||
cfg = [
|
||||
"dhcp"
|
||||
"dns"
|
||||
];
|
||||
"tailscale*" = [
|
||||
"ssh"
|
||||
"web"
|
||||
];
|
||||
};
|
||||
allInterfaces = [ ];
|
||||
};
|
||||
@@ -146,7 +172,9 @@
|
||||
onState = [ "routable" ];
|
||||
script = ''
|
||||
#!${pkgs.runtimeShell}
|
||||
${pkgs.ethtool}/bin/ethtool -K ${config.systemd.network.links."10-extern0".linkConfig.Name} rx-udp-gro-forwarding on rx-gro-list off
|
||||
${pkgs.ethtool}/bin/ethtool -K ${
|
||||
config.systemd.network.links."10-extern0".linkConfig.Name
|
||||
} rx-udp-gro-forwarding on rx-gro-list off
|
||||
'';
|
||||
};
|
||||
};
|
||||
@@ -183,53 +211,73 @@
|
||||
|
||||
services.resolved.enable = false;
|
||||
|
||||
services.nextdns = {
|
||||
modules.services.dhcp-dns-sync = {
|
||||
enable = true;
|
||||
arguments = [ "-profile" "9c4ac9" "-setup-router" "-mdns" "koti" ];
|
||||
interface = "koti";
|
||||
domain = "home.arpa";
|
||||
interval = "30s";
|
||||
};
|
||||
|
||||
services.home-assistant = {
|
||||
services.unbound = {
|
||||
enable = true;
|
||||
extraComponents = [
|
||||
# Components required to complete the onboarding
|
||||
"esphome"
|
||||
"met"
|
||||
"radio_browser"
|
||||
|
||||
"yeelight"
|
||||
"xiaomi_aqara"
|
||||
"shelly"
|
||||
settings = {
|
||||
server = {
|
||||
interface =
|
||||
(lib.map (name: config.systemd.network.networks."30-${name}".dhcpServerConfig.DNS) (
|
||||
lib.attrNames config.modules.vlans.networks
|
||||
))
|
||||
++ [
|
||||
"127.0.0.1"
|
||||
"::1"
|
||||
];
|
||||
extraPackages = python3Packages: with python3Packages; [
|
||||
gtts
|
||||
numpy
|
||||
access-control = [
|
||||
"10.0.0.0/8 allow"
|
||||
"127.0.0.0/8 allow"
|
||||
"::1/128 allow"
|
||||
];
|
||||
config = {
|
||||
homeassistant = {
|
||||
name = "Koti";
|
||||
unit_system = "metric";
|
||||
time_zone = "Europe/Helsinki";
|
||||
verbosity = 2;
|
||||
};
|
||||
http = {
|
||||
use_x_forwarded_for = true;
|
||||
trusted_proxies = "127.0.0.1";
|
||||
};
|
||||
default_config = { };
|
||||
|
||||
forward-zone = [
|
||||
{
|
||||
name = ".";
|
||||
forward-addr = "100.84.105.63#dns.freun.dev";
|
||||
forward-tls-upstream = true;
|
||||
}
|
||||
];
|
||||
|
||||
remote-control.control-enable = true;
|
||||
};
|
||||
};
|
||||
|
||||
services.webserver = {
|
||||
services.avahi = {
|
||||
enable = true;
|
||||
acme.dnsChallenge = true;
|
||||
vHosts."koti.repomaa.com" = {
|
||||
proxyBuffering = false;
|
||||
locations."/".proxyPort = 8123;
|
||||
};
|
||||
nssmdns4 = true;
|
||||
reflector = true;
|
||||
allowInterfaces = [ "lan" ];
|
||||
openFirewall = true;
|
||||
};
|
||||
|
||||
networking.nftables.enable = true;
|
||||
networking.firewall.enable = true;
|
||||
networking.useDHCP = false;
|
||||
services.invidious-companion = {
|
||||
enable = true;
|
||||
host = "0.0.0.0";
|
||||
port = 8282;
|
||||
secretKeyFile = config.age.secrets.invidious-companion.path;
|
||||
binaryHash = "sha256-nZXKpExKCc2zgSdVT3qo05NyFdpM9H9NJB5UWo+MVWI=";
|
||||
};
|
||||
|
||||
networking.firewall = {
|
||||
enable = true;
|
||||
interfaces.tailscale0.allowedTCPPorts = [ 8282 ];
|
||||
};
|
||||
|
||||
security.acme.defaults.environmentFile = config.age.secrets.hetzner.path;
|
||||
|
||||
networking = {
|
||||
nftables.enable = true;
|
||||
useDHCP = false;
|
||||
domain = "apu.home.arpa";
|
||||
};
|
||||
|
||||
system.stateVersion = "24.05";
|
||||
}
|
||||
|
||||
@@ -6,6 +6,7 @@ in
|
||||
imports = [
|
||||
./hardware-configuration.nix
|
||||
./configuration.nix
|
||||
./secrets.nix
|
||||
nixos-hardware.nixosModules.pcengines-apu
|
||||
];
|
||||
}
|
||||
|
||||
@@ -1,38 +1,54 @@
|
||||
# Do not modify this file! It was generated by ‘nixos-generate-config’
|
||||
# and may be overwritten by future invocations. Please make changes
|
||||
# to /etc/nixos/configuration.nix instead.
|
||||
{ config, lib, pkgs, modulesPath, ... }:
|
||||
{
|
||||
config,
|
||||
lib,
|
||||
pkgs,
|
||||
modulesPath,
|
||||
...
|
||||
}:
|
||||
|
||||
{
|
||||
imports =
|
||||
[ (modulesPath + "/installer/scan/not-detected.nix")
|
||||
imports = [
|
||||
(modulesPath + "/installer/scan/not-detected.nix")
|
||||
];
|
||||
|
||||
boot.initrd.availableKernelModules = [ "xhci_pci" "ahci" "ehci_pci" "usb_storage" "sd_mod" "sdhci_pci" ];
|
||||
boot.initrd.availableKernelModules = [
|
||||
"xhci_pci"
|
||||
"ahci"
|
||||
"ehci_pci"
|
||||
"usb_storage"
|
||||
"sd_mod"
|
||||
"sdhci_pci"
|
||||
];
|
||||
boot.initrd.kernelModules = [ ];
|
||||
boot.kernelModules = [ "kvm-amd" ];
|
||||
boot.extraModulePackages = [ ];
|
||||
|
||||
fileSystems."/" =
|
||||
{ device = "/dev/disk/by-uuid/f221c6a7-e05e-40dc-bc85-7970d7c8f22b";
|
||||
fileSystems."/" = {
|
||||
device = "/dev/disk/by-uuid/f221c6a7-e05e-40dc-bc85-7970d7c8f22b";
|
||||
fsType = "btrfs";
|
||||
options = [ "subvol=@" ];
|
||||
};
|
||||
|
||||
fileSystems."/var/log" =
|
||||
{ device = "/dev/disk/by-uuid/f221c6a7-e05e-40dc-bc85-7970d7c8f22b";
|
||||
fileSystems."/var/log" = {
|
||||
device = "/dev/disk/by-uuid/f221c6a7-e05e-40dc-bc85-7970d7c8f22b";
|
||||
fsType = "btrfs";
|
||||
options = [ "subvol=@var_log" ];
|
||||
};
|
||||
|
||||
fileSystems."/boot" =
|
||||
{ device = "/dev/disk/by-uuid/14D2-F8F4";
|
||||
fileSystems."/boot" = {
|
||||
device = "/dev/disk/by-uuid/14D2-F8F4";
|
||||
fsType = "vfat";
|
||||
options = [ "fmask=0022" "dmask=0022" ];
|
||||
options = [
|
||||
"fmask=0022"
|
||||
"dmask=0022"
|
||||
];
|
||||
};
|
||||
|
||||
fileSystems."/swap" =
|
||||
{ device = "/dev/disk/by-uuid/f221c6a7-e05e-40dc-bc85-7970d7c8f22b";
|
||||
fileSystems."/swap" = {
|
||||
device = "/dev/disk/by-uuid/f221c6a7-e05e-40dc-bc85-7970d7c8f22b";
|
||||
fsType = "btrfs";
|
||||
options = [ "subvol=@swap" ];
|
||||
};
|
||||
|
||||
16
hosts/apu/secrets.nix
Normal file
16
hosts/apu/secrets.nix
Normal file
@@ -0,0 +1,16 @@
|
||||
{ lib, ... }:
|
||||
{
|
||||
age.secrets = lib.listToAttrs (
|
||||
map
|
||||
(secret: {
|
||||
name = secret;
|
||||
value = {
|
||||
file = ../../secrets/${secret}.age;
|
||||
};
|
||||
})
|
||||
[
|
||||
"hetzner"
|
||||
"invidious-companion"
|
||||
]
|
||||
);
|
||||
}
|
||||
@@ -2,36 +2,87 @@
|
||||
# your system. Help is available in the configuration.nix(5) man page
|
||||
# and in the NixOS manual (accessible by running `nixos-help`).
|
||||
|
||||
{ config, pkgs, ssh, ... }:
|
||||
|
||||
{
|
||||
config,
|
||||
pkgs,
|
||||
ssh,
|
||||
...
|
||||
}:
|
||||
let
|
||||
ipv4Address = "65.21.145.150";
|
||||
ipv6Address = "2a01:4f9:c011:9ac1::1";
|
||||
in
|
||||
{
|
||||
nix = {
|
||||
settings = {
|
||||
experimental-features = [ "nix-command" "flakes" ];
|
||||
experimental-features = [
|
||||
"nix-command"
|
||||
"flakes"
|
||||
];
|
||||
auto-optimise-store = true;
|
||||
};
|
||||
gc = {
|
||||
automatic = true;
|
||||
dates = "weekly";
|
||||
options = "--delete-older-than 30d";
|
||||
options = "--delete-older-than 7d";
|
||||
};
|
||||
};
|
||||
|
||||
boot.loader.systemd-boot.enable = true;
|
||||
boot.loader.efi.canTouchEfiVariables = true;
|
||||
boot.binfmt.emulatedSystems = [ "x86_64-linux" ];
|
||||
|
||||
networking.hostName = "freun-dev"; # Define your hostname.
|
||||
networking.domain = "freun.dev";
|
||||
networking.useDHCP = false;
|
||||
networking.nftables.enable = true;
|
||||
|
||||
services.octodns.records = {
|
||||
"" = {
|
||||
A = {
|
||||
ttl = 86400;
|
||||
values = [ ipv4Address ];
|
||||
};
|
||||
AAAA = {
|
||||
ttl = 86400;
|
||||
values = [ ipv6Address ];
|
||||
};
|
||||
TXT = {
|
||||
ttl = 86400;
|
||||
values = [
|
||||
"v=spf1 include:spf.uberspace.de ~all"
|
||||
];
|
||||
};
|
||||
};
|
||||
"_dmarc".TXT = {
|
||||
ttl = 86400;
|
||||
values = [ "v=DMARC1\\; p=reject" ];
|
||||
};
|
||||
"uberspace._domainkey".TXT = {
|
||||
ttl = 86400;
|
||||
values = [
|
||||
"v=DKIM1\\;t=s\\;n=core\\;p=MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEArjZrrWhFn/xSH3+aPA3G1eGD5yAeyn7ZhHSCBM7b/9A5Fny9URjEf1La7dcU+oF/d7outgmTCs/umItBCB7ybkMriaLC+RBZJY0blf35bMYWL9NLpbKzVVAZQPgDZJm7R/grbg0nJgb5RCGLYu9iPcRjJtpu2vYaitkNh8WJ4q+iA/YOos2pQmP+6I5zLTVenFfEWJccdtfhJcORSuONN+Xi1+dQxpQzlwxUWz4DgOsfVaE3woDH3RAAQCtiMyk8ZQhhrL85pHH6zT3sNXzzVphJdIIYA+VYAgYYOTkRbdDhYSd5zCDX5f4L1UmBsJS2ommBGvw2qMDhagXsaN32BwIDAQAB"
|
||||
];
|
||||
};
|
||||
"ts" = {
|
||||
A = {
|
||||
ttl = 86400;
|
||||
values = [ "100.84.105.63" ];
|
||||
};
|
||||
AAAA = {
|
||||
ttl = 86400;
|
||||
values = [ "fd7a:115c:a1e0::7901:693f" ];
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
systemd.network = {
|
||||
enable = true;
|
||||
networks.static = {
|
||||
name = "enp1s0";
|
||||
address = [
|
||||
"65.21.145.150/32"
|
||||
"2a01:4f9:c011:9ac1::1/64"
|
||||
"${ipv4Address}/32"
|
||||
"${ipv6Address}/64"
|
||||
];
|
||||
routes = [
|
||||
{ Gateway = "fe80::1"; }
|
||||
@@ -81,21 +132,31 @@
|
||||
# useXkbConfig = true; # use xkbOptions in tty.
|
||||
# };
|
||||
|
||||
|
||||
# Configure keymap in X11
|
||||
services.xserver.xkb.layout = "us";
|
||||
services.xserver.xkb.options = "eurosign:e,caps:escape";
|
||||
|
||||
# Define a user account. Don't forget to set a password with ‘passwd’.
|
||||
users.users.jokke = {
|
||||
users.users = {
|
||||
jokke = {
|
||||
isNormalUser = true;
|
||||
extraGroups = [ "wheel" ]; # Enable ‘sudo’ for the user.
|
||||
packages = [ pkgs.nh ];
|
||||
openssh.authorizedKeys.keys = [ ssh.publicKeys.yubikey ];
|
||||
};
|
||||
users.users.root.openssh.authorizedKeys.keys = [ ssh.publicKeys.yubikey ];
|
||||
|
||||
nix.settings.trusted-users = [ "jokke" ];
|
||||
builder = {
|
||||
isNormalUser = true;
|
||||
openssh.authorizedKeys.keys = [ ssh.publicKeys.builder ];
|
||||
};
|
||||
|
||||
root.openssh.authorizedKeys.keys = [ ssh.publicKeys.yubikey ];
|
||||
};
|
||||
|
||||
nix.settings.trusted-users = [
|
||||
"jokke"
|
||||
"builder"
|
||||
];
|
||||
|
||||
# List packages installed in system profile. To search, run:
|
||||
# $ nix search wget
|
||||
339
hosts/freun-dev/glance.nix
Normal file
339
hosts/freun-dev/glance.nix
Normal file
@@ -0,0 +1,339 @@
|
||||
{ config, ... }:
|
||||
let
|
||||
secrets = config.age.secrets;
|
||||
in
|
||||
{
|
||||
services.tailscaledGlance = {
|
||||
enable = true;
|
||||
subdomain = "glance";
|
||||
settings = {
|
||||
server.port = 4114;
|
||||
pages = [
|
||||
{
|
||||
name = "Home";
|
||||
columns = [
|
||||
{
|
||||
size = "small";
|
||||
widgets = [
|
||||
{
|
||||
type = "clock";
|
||||
hour-format = "24h";
|
||||
timezones = [
|
||||
{
|
||||
timezone = "Europe/Zurich";
|
||||
label = "Zürich";
|
||||
}
|
||||
];
|
||||
}
|
||||
{
|
||||
type = "group";
|
||||
title = "Weather";
|
||||
widgets =
|
||||
let
|
||||
buildWeatherWidget =
|
||||
{ location, title }:
|
||||
{
|
||||
type = "weather";
|
||||
hide-location = true;
|
||||
hour-format = "24h";
|
||||
units = "metric";
|
||||
inherit location title;
|
||||
};
|
||||
in
|
||||
builtins.map buildWeatherWidget [
|
||||
{
|
||||
title = "Espoo";
|
||||
location = "Espoo, Finland";
|
||||
}
|
||||
{
|
||||
title = "Mökki";
|
||||
location = "Pellosniemi, Finland";
|
||||
}
|
||||
{
|
||||
title = "Frankfurt";
|
||||
location = "Frankfurt, Germany";
|
||||
}
|
||||
];
|
||||
}
|
||||
{
|
||||
type = "markets";
|
||||
markets = [
|
||||
{
|
||||
symbol = "KOZ0.F";
|
||||
name = "Kongsberg Gruppen";
|
||||
}
|
||||
{
|
||||
symbol = "AMD";
|
||||
name = "AMD";
|
||||
}
|
||||
];
|
||||
}
|
||||
{
|
||||
type = "group";
|
||||
widgets = [
|
||||
{
|
||||
type = "rss";
|
||||
title = "News";
|
||||
limit = 10;
|
||||
collapse-after = 3;
|
||||
cache = "12h";
|
||||
feeds = [
|
||||
{
|
||||
url = "https://yle.fi/rss/uutiset/paauutiset";
|
||||
title = "Yle";
|
||||
}
|
||||
];
|
||||
}
|
||||
{
|
||||
type = "rss";
|
||||
title = "Tech";
|
||||
limit = 10;
|
||||
collapse-after = 3;
|
||||
cache = "12h";
|
||||
feeds = [
|
||||
{
|
||||
url = "https://nixos.org/blog/announcements-rss.xml";
|
||||
title = "NixOS";
|
||||
}
|
||||
{
|
||||
url = "https://selfh.st/rss";
|
||||
title = "selfh.st";
|
||||
}
|
||||
];
|
||||
}
|
||||
{
|
||||
type = "rss";
|
||||
title = "Blogs";
|
||||
limit = 10;
|
||||
collapse-after = 3;
|
||||
cache = "12h";
|
||||
feeds = [
|
||||
{
|
||||
url = "https://samharris.substack.com/feed";
|
||||
title = "Sam Harris";
|
||||
}
|
||||
];
|
||||
}
|
||||
];
|
||||
}
|
||||
{
|
||||
type = "custom-api";
|
||||
title = "Steam Specials";
|
||||
cache = "12h";
|
||||
url = "https://store.steampowered.com/api/featuredcategories?cc=fi";
|
||||
template = ''
|
||||
<ul class="list list-gap-10 collapsible-container" data-collapse-after="5">
|
||||
{{ range .JSON.Array "specials.items" }}
|
||||
<li>
|
||||
<a class="size-h4 color-highlight block text-truncate" href="https://store.steampowered.com/app/{{ .Int "id" }}/">{{ .String "name" }}</a>
|
||||
<ul class="list-horizontal-text">
|
||||
<li>{{ div (.Int "final_price" | toFloat) 100 | printf "$%.2f" }}</li>
|
||||
{{ $discount := .Int "discount_percent" }}
|
||||
<li{{ if ge $discount 40 }} class="color-positive"{{ end }}>{{ $discount }}% off</li>
|
||||
</ul>
|
||||
</li>
|
||||
{{ end }}
|
||||
</ul>
|
||||
'';
|
||||
}
|
||||
];
|
||||
}
|
||||
{
|
||||
size = "full";
|
||||
widgets = [
|
||||
{
|
||||
type = "group";
|
||||
widgets = [
|
||||
{ type = "hacker-news"; }
|
||||
{ type = "lobsters"; }
|
||||
];
|
||||
}
|
||||
{
|
||||
type = "videos";
|
||||
channels = [
|
||||
"UCXuqSBlHAE6Xw-yeJA0Tunw" # Linus Tech Tips
|
||||
"UCshObcm-nLhbu8MY50EZ5Ng" # Benn Jordan
|
||||
];
|
||||
}
|
||||
{
|
||||
type = "group";
|
||||
widgets =
|
||||
let
|
||||
type = "reddit";
|
||||
show-thumbnails = true;
|
||||
app-auth = {
|
||||
name = "Glance";
|
||||
id = {
|
||||
_secret = secrets."glance/reddit/app-id".path;
|
||||
};
|
||||
secret = {
|
||||
_secret = secrets."glance/reddit/app-secret".path;
|
||||
};
|
||||
};
|
||||
in
|
||||
[
|
||||
{
|
||||
inherit type app-auth show-thumbnails;
|
||||
subreddit = "nixos";
|
||||
}
|
||||
{
|
||||
inherit type app-auth show-thumbnails;
|
||||
subreddit = "technology";
|
||||
}
|
||||
{
|
||||
inherit type app-auth show-thumbnails;
|
||||
subreddit = "selfhosted";
|
||||
}
|
||||
];
|
||||
}
|
||||
];
|
||||
}
|
||||
{
|
||||
size = "small";
|
||||
widgets = [
|
||||
{
|
||||
type = "server-stats";
|
||||
servers = [
|
||||
{
|
||||
type = "local";
|
||||
name = "freun.dev";
|
||||
}
|
||||
];
|
||||
}
|
||||
{
|
||||
type = "group";
|
||||
title = "Services";
|
||||
widgets =
|
||||
let
|
||||
buildSite =
|
||||
domain:
|
||||
{
|
||||
subdomain,
|
||||
title,
|
||||
alt-status-codes ? [ ],
|
||||
}:
|
||||
{
|
||||
inherit title alt-status-codes;
|
||||
url = "https://${subdomain}.${domain}";
|
||||
};
|
||||
buildMonitor =
|
||||
{ domain, sites }:
|
||||
{
|
||||
type = "monitor";
|
||||
cache = "1m";
|
||||
title = domain;
|
||||
style = "compact";
|
||||
sites = builtins.map (buildSite domain) sites;
|
||||
};
|
||||
in
|
||||
builtins.map buildMonitor [
|
||||
{
|
||||
domain = "freun.dev";
|
||||
sites = [
|
||||
{
|
||||
subdomain = "img";
|
||||
title = "Immich";
|
||||
}
|
||||
{
|
||||
subdomain = "pw";
|
||||
title = "Vaultwarden";
|
||||
}
|
||||
{
|
||||
subdomain = "social";
|
||||
title = "Gotosocial";
|
||||
}
|
||||
{
|
||||
subdomain = "graph";
|
||||
title = "Grafana";
|
||||
}
|
||||
{
|
||||
subdomain = "home";
|
||||
title = "Home Assistant";
|
||||
}
|
||||
{
|
||||
subdomain = "cook";
|
||||
title = "Mealie";
|
||||
}
|
||||
{
|
||||
subdomain = "sync";
|
||||
title = "Syncthing";
|
||||
}
|
||||
{
|
||||
subdomain = "bin";
|
||||
title = "Hastebin";
|
||||
alt-status-codes = [ 404 ];
|
||||
}
|
||||
{
|
||||
subdomain = "ledger";
|
||||
title = "Ledger";
|
||||
}
|
||||
{
|
||||
subdomain = "note";
|
||||
title = "Dnote";
|
||||
}
|
||||
{
|
||||
subdomain = "trackmap";
|
||||
title = "Trackmap";
|
||||
}
|
||||
{
|
||||
subdomain = "fit";
|
||||
title = "Workout Tracker";
|
||||
}
|
||||
{
|
||||
subdomain = "stream";
|
||||
title = "Owncast";
|
||||
}
|
||||
{
|
||||
subdomain = "read";
|
||||
title = "Readeck";
|
||||
}
|
||||
];
|
||||
}
|
||||
{
|
||||
domain = "alderaan.space";
|
||||
sites = [
|
||||
{
|
||||
subdomain = "jelly";
|
||||
title = "Jellyfin";
|
||||
}
|
||||
{
|
||||
subdomain = "radarr";
|
||||
title = "Radarr";
|
||||
}
|
||||
{
|
||||
subdomain = "sonarr";
|
||||
title = "Sonarr";
|
||||
}
|
||||
{
|
||||
subdomain = "deluge";
|
||||
title = "qBittorrent";
|
||||
}
|
||||
{
|
||||
subdomain = "lidarr";
|
||||
title = "Lidarr";
|
||||
}
|
||||
{
|
||||
subdomain = "bazarr";
|
||||
title = "Bazarr";
|
||||
}
|
||||
{
|
||||
subdomain = "req";
|
||||
title = "Jellyseer";
|
||||
}
|
||||
];
|
||||
}
|
||||
];
|
||||
}
|
||||
{
|
||||
type = "dns-stats";
|
||||
service = "adguard";
|
||||
url = "http://localhost:3006";
|
||||
}
|
||||
];
|
||||
}
|
||||
];
|
||||
}
|
||||
];
|
||||
};
|
||||
};
|
||||
}
|
||||
@@ -1,34 +1,41 @@
|
||||
# Do not modify this file! It was generated by ‘nixos-generate-config’
|
||||
# and may be overwritten by future invocations. Please make changes
|
||||
# to /etc/nixos/configuration.nix instead.
|
||||
{ config, lib, pkgs, modulesPath, ... }:
|
||||
{
|
||||
lib,
|
||||
modulesPath,
|
||||
...
|
||||
}:
|
||||
|
||||
{
|
||||
imports =
|
||||
[
|
||||
imports = [
|
||||
(modulesPath + "/profiles/qemu-guest.nix")
|
||||
];
|
||||
|
||||
boot.initrd.availableKernelModules = [ "xhci_pci" "virtio_scsi" "sr_mod" ];
|
||||
boot.initrd.availableKernelModules = [
|
||||
"xhci_pci"
|
||||
"virtio_scsi"
|
||||
"sr_mod"
|
||||
];
|
||||
boot.initrd.kernelModules = [ ];
|
||||
boot.kernelModules = [ ];
|
||||
boot.extraModulePackages = [ ];
|
||||
|
||||
fileSystems."/" =
|
||||
{
|
||||
fileSystems."/" = {
|
||||
device = "/dev/disk/by-uuid/f594ffbc-4553-42e4-8206-4d762c94b4c3";
|
||||
fsType = "ext4";
|
||||
};
|
||||
|
||||
fileSystems."/boot" =
|
||||
{
|
||||
fileSystems."/boot" = {
|
||||
device = "/dev/disk/by-uuid/46F1-18E3";
|
||||
fsType = "vfat";
|
||||
options = [ "fmask=0077" "dmask=0077" ];
|
||||
options = [
|
||||
"fmask=0077"
|
||||
"dmask=0077"
|
||||
];
|
||||
};
|
||||
|
||||
swapDevices =
|
||||
[{ device = "/dev/disk/by-uuid/d9955575-d4e0-4a49-a3c5-41f54110d12b"; }];
|
||||
swapDevices = [ { device = "/dev/disk/by-uuid/d9955575-d4e0-4a49-a3c5-41f54110d12b"; } ];
|
||||
|
||||
# Enables DHCP on each ethernet and wireless interface. In case of scripted networking
|
||||
# (the default) this is the recommended approach. When using systemd-networkd it's
|
||||
59
hosts/freun-dev/secrets.nix
Normal file
59
hosts/freun-dev/secrets.nix
Normal file
@@ -0,0 +1,59 @@
|
||||
{ lib, config, ... }:
|
||||
{
|
||||
age.secrets =
|
||||
lib.listToAttrs (
|
||||
map
|
||||
(secret: {
|
||||
name = secret;
|
||||
value = {
|
||||
file = ../../secrets/${secret}.age;
|
||||
};
|
||||
})
|
||||
[
|
||||
"gotosocial"
|
||||
"immich"
|
||||
"readeck"
|
||||
"storage-box-credentials"
|
||||
"vaultwarden"
|
||||
"donetick"
|
||||
"dnote"
|
||||
"mealie"
|
||||
"mosquitto/homie"
|
||||
"mosquitto/telegraf"
|
||||
"mosquitto/openhab"
|
||||
"mosquitto/shelly"
|
||||
"mosquitto/mokkimaatti"
|
||||
"gitlab-runner/default"
|
||||
"gitlab-runner/docker"
|
||||
"glance/reddit/app-id"
|
||||
"glance/reddit/app-secret"
|
||||
"hetzner"
|
||||
"actual"
|
||||
"voidauth"
|
||||
"gitea"
|
||||
"gitea-actions-runner"
|
||||
]
|
||||
)
|
||||
// {
|
||||
smtp-password = {
|
||||
file = ../../secrets/smtp-password.age;
|
||||
owner =
|
||||
if (config.services.grafana.enable) then
|
||||
config.systemd.services.grafana.serviceConfig.User
|
||||
else
|
||||
"root";
|
||||
};
|
||||
hastebin-tokens = {
|
||||
file = ../../secrets/hastebin-tokens.age;
|
||||
owner = if (config.services.hastebin.enable) then config.users.users.hastebin.name else "root";
|
||||
};
|
||||
hledger-basic-auth = {
|
||||
file = ../../secrets/hledger-basic-auth.age;
|
||||
owner = if (config.services.hledger-web.enable) then "nginx" else "root";
|
||||
};
|
||||
invidious = lib.mkIf config.services.invidious.enable {
|
||||
file = ../../secrets/invidious.age;
|
||||
owner = config.systemd.services.invidious.serviceConfig.User;
|
||||
};
|
||||
};
|
||||
}
|
||||
397
hosts/freun-dev/services.nix
Normal file
397
hosts/freun-dev/services.nix
Normal file
@@ -0,0 +1,397 @@
|
||||
{
|
||||
pkgs,
|
||||
pkgs-unstable,
|
||||
config,
|
||||
inputs,
|
||||
lib,
|
||||
...
|
||||
}:
|
||||
let
|
||||
immichDataDir = "/mnt/storage/immich";
|
||||
syncthingDataDir = "/mnt/storage/syncthing";
|
||||
smtp = {
|
||||
host = "horologium.uberspace.de";
|
||||
port = 587;
|
||||
username = "noreply@${config.networking.domain}";
|
||||
from = "noreply@${config.networking.domain}";
|
||||
heloName = config.networking.domain;
|
||||
};
|
||||
secrets = config.age.secrets;
|
||||
in
|
||||
{
|
||||
imports = [
|
||||
./glance.nix
|
||||
];
|
||||
virtualisation.podman.enable = true;
|
||||
virtualisation.oci-containers.backend = "podman";
|
||||
security.acme.defaults.environmentFile = secrets.hetzner.path;
|
||||
|
||||
modules.storageBoxMounts = {
|
||||
${immichDataDir} = {
|
||||
path = "/backup/immich";
|
||||
user = "u407959";
|
||||
uid = config.users.users.${config.services.immich.user}.uid;
|
||||
gid = config.users.groups.${config.services.immich.user}.gid;
|
||||
};
|
||||
|
||||
${syncthingDataDir} = {
|
||||
path = "/backup/syncthing";
|
||||
user = "u407959";
|
||||
uid = config.users.users.${config.services.syncthing.user}.uid;
|
||||
gid = config.users.groups.${config.services.syncthing.user}.gid;
|
||||
};
|
||||
};
|
||||
|
||||
services = {
|
||||
postgresql.package = pkgs.postgresql_16;
|
||||
octodns = {
|
||||
enable = true;
|
||||
records."".MX = {
|
||||
ttl = 86400;
|
||||
values = [ { exchange = "${smtp.host}."; } ];
|
||||
};
|
||||
defaults.CNAME.ttl = 60;
|
||||
};
|
||||
|
||||
hastebin = {
|
||||
enable = true;
|
||||
subdomain = "bin";
|
||||
renderers =
|
||||
with pkgs;
|
||||
let
|
||||
hl = rustPlatform.buildRustPackage {
|
||||
name = "syntax-renderer";
|
||||
src = inputs.syntax-renderer;
|
||||
cargoHash = "sha256-kZy+HVPcUfPDTBQZ8TQ/xlEEqmSIttzdGeRwX9EF4xU=";
|
||||
};
|
||||
in
|
||||
{
|
||||
hl = "${hl}/bin/syntax-renderer";
|
||||
sha = writeShellScript "sha-renderer" ''
|
||||
echo "Content-Type: text/plain"
|
||||
echo "---"
|
||||
${coreutils}/bin/sha256sum - | cut -d' ' -f1
|
||||
'';
|
||||
stl = writeShellScript "stl-renderer" ''
|
||||
echo "Content-Type: model/stl"
|
||||
echo "Content-Disposition: attachment; filename=$(basename "$1" .scad).stl"
|
||||
echo "---"
|
||||
${openscad}/bin/openscad --export-format stl -o - -
|
||||
'';
|
||||
};
|
||||
cleanup.enable = true;
|
||||
};
|
||||
|
||||
readeck = {
|
||||
enable = true;
|
||||
subdomain = "read";
|
||||
settings.email = {
|
||||
host = smtp.host;
|
||||
port = smtp.port;
|
||||
username = smtp.username;
|
||||
encryption = "starttls";
|
||||
from = smtp.from;
|
||||
from_noreply = smtp.from;
|
||||
};
|
||||
};
|
||||
|
||||
donetick = {
|
||||
enable = true;
|
||||
subdomain = "do";
|
||||
settings = {
|
||||
email = {
|
||||
host = smtp.host;
|
||||
port = smtp.port;
|
||||
email = smtp.username;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
grafana = {
|
||||
enable = true;
|
||||
subdomain = "graph";
|
||||
settings = {
|
||||
server.http_port = 3005;
|
||||
smtp = {
|
||||
enabled = true;
|
||||
host = smtp.host;
|
||||
port = smtp.port;
|
||||
user = smtp.username;
|
||||
from_address = smtp.from;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
owncast = {
|
||||
enable = true;
|
||||
subdomain = "stream";
|
||||
};
|
||||
|
||||
gtrackmap = {
|
||||
enable = false;
|
||||
subdomain = "trackmap";
|
||||
port = 3001;
|
||||
};
|
||||
|
||||
invidious = {
|
||||
enable = true;
|
||||
subdomain = "vid";
|
||||
extraSettingsFile = secrets.invidious.path;
|
||||
settings = {
|
||||
invidious_companion = [
|
||||
{ private_url = "http://apu:8282/companion"; }
|
||||
];
|
||||
};
|
||||
};
|
||||
|
||||
syncthing = {
|
||||
enable = true;
|
||||
subdomain = "sync";
|
||||
dataDir = syncthingDataDir;
|
||||
configDir = "/var/lib/syncthing";
|
||||
};
|
||||
|
||||
tailscale.enable = true;
|
||||
|
||||
gotosocial = {
|
||||
enable = true;
|
||||
subdomain = "social";
|
||||
settings = {
|
||||
port = 3002;
|
||||
smtp-host = smtp.host;
|
||||
smtp-port = smtp.port;
|
||||
smtp-username = smtp.username;
|
||||
smtp-from = smtp.from;
|
||||
instance-languages = [
|
||||
"de"
|
||||
"fi"
|
||||
"en"
|
||||
];
|
||||
};
|
||||
};
|
||||
|
||||
vaultwarden = {
|
||||
enable = true;
|
||||
subdomain = "pw";
|
||||
config = {
|
||||
YUBICO_CLIENT_ID = 86799;
|
||||
SMTP_HOST = smtp.host;
|
||||
SMTP_FROM = smtp.from;
|
||||
SMTP_FROM_NAME = "Vaultwarden";
|
||||
SMTP_USERNAME = smtp.username;
|
||||
SMTP_PORT = smtp.port;
|
||||
HELO_NAME = smtp.heloName;
|
||||
};
|
||||
};
|
||||
|
||||
workout-tracker = {
|
||||
enable = true;
|
||||
subdomain = "fit";
|
||||
port = 3004;
|
||||
};
|
||||
|
||||
workout-sync = {
|
||||
enable = true;
|
||||
subdomain = "ws";
|
||||
};
|
||||
|
||||
immich = {
|
||||
enable = true;
|
||||
subdomain = "img";
|
||||
mediaLocation = immichDataDir;
|
||||
timezone = "Europe/Helsinki";
|
||||
settings.job = {
|
||||
thumbnailGeneration.concurrency = 8;
|
||||
videoConversion.concurrency = 2;
|
||||
};
|
||||
};
|
||||
|
||||
dnote = {
|
||||
enable = true;
|
||||
subdomain = "note";
|
||||
environment = {
|
||||
SmtpHost = smtp.host;
|
||||
SmtpPort = smtp.port;
|
||||
SmtpUsername = smtp.username;
|
||||
};
|
||||
environmentFile = secrets.dnote.path;
|
||||
};
|
||||
|
||||
tailscaledAdguardhome = {
|
||||
enable = true;
|
||||
subdomain = "dns";
|
||||
port = 3006;
|
||||
};
|
||||
|
||||
mealie = {
|
||||
enable = true;
|
||||
package = pkgs-unstable.mealie;
|
||||
subdomain = "cook";
|
||||
credentialsFile = secrets.mealie.path;
|
||||
settings = {
|
||||
SMTP_HOST = smtp.host;
|
||||
SMTP_FROM_EMAIL = smtp.from;
|
||||
SMTP_USER = smtp.username;
|
||||
SMTP_PORT = smtp.port;
|
||||
};
|
||||
};
|
||||
|
||||
uptime-kuma = {
|
||||
enable = true;
|
||||
subdomain = "status";
|
||||
settings = {
|
||||
PORT = "3007";
|
||||
};
|
||||
};
|
||||
|
||||
mosquitto = {
|
||||
enable = true;
|
||||
listeners = [
|
||||
{
|
||||
users = {
|
||||
homie = {
|
||||
acl = [
|
||||
"readwrite homie/#"
|
||||
];
|
||||
hashedPasswordFile = secrets."mosquitto/homie".path;
|
||||
};
|
||||
telegraf = {
|
||||
acl = [
|
||||
"read openhab/#"
|
||||
"read homie/#"
|
||||
"read shellies/#"
|
||||
"read mokkimaatti/#"
|
||||
];
|
||||
hashedPasswordFile = secrets."mosquitto/telegraf".path;
|
||||
};
|
||||
openhab = {
|
||||
acl = [
|
||||
"readwrite openhab/#"
|
||||
];
|
||||
hashedPasswordFile = secrets."mosquitto/openhab".path;
|
||||
};
|
||||
shelly = {
|
||||
acl = [
|
||||
"readwrite shellies/#"
|
||||
];
|
||||
hashedPasswordFile = secrets."mosquitto/shelly".path;
|
||||
};
|
||||
mokkimaatti = {
|
||||
acl = [
|
||||
"readwrite mokkimaatti/#"
|
||||
];
|
||||
hashedPasswordFile = secrets."mosquitto/mokkimaatti".path;
|
||||
};
|
||||
};
|
||||
}
|
||||
];
|
||||
openFirewall = true;
|
||||
};
|
||||
|
||||
gitlab-runner = {
|
||||
enable = true;
|
||||
services = {
|
||||
default = {
|
||||
dockerImage = "alpine";
|
||||
authenticationTokenConfigFile = secrets."gitlab-runner/default".path;
|
||||
};
|
||||
docker = {
|
||||
dockerImage = "docker:stable";
|
||||
dockerVolumes = [ "/var/run/docker.sock:/var/run/docker.sock" ];
|
||||
authenticationTokenConfigFile = secrets."gitlab-runner/docker".path;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
weechat = {
|
||||
enable = true;
|
||||
subdomain = "irc";
|
||||
};
|
||||
|
||||
sillytavern = {
|
||||
enable = true;
|
||||
subdomain = "st";
|
||||
listen = true;
|
||||
whitelist = false;
|
||||
port = 3100;
|
||||
};
|
||||
|
||||
nginx.virtualHosts."isarepomaa.com" = {
|
||||
forceSSL = true;
|
||||
enableACME = true;
|
||||
http2 = true;
|
||||
locations."/".root = "/var/www/isas-portfolio";
|
||||
};
|
||||
|
||||
hledger-web = {
|
||||
enable = true;
|
||||
subdomain = "ledger";
|
||||
stateDir = "${syncthingDataDir}/ledger";
|
||||
user = config.systemd.services.syncthing.serviceConfig.User;
|
||||
group = config.systemd.services.syncthing.serviceConfig.Group;
|
||||
extraOptions = [ "--forecast" ];
|
||||
journalFiles = [
|
||||
"main.ldg"
|
||||
];
|
||||
};
|
||||
|
||||
actual = {
|
||||
enable = true;
|
||||
package = pkgs-unstable.actual-server;
|
||||
subdomain = "actual";
|
||||
environmentFile = secrets.actual.path;
|
||||
settings = {
|
||||
port = 3200;
|
||||
openId = {
|
||||
discoveryURL = "https://${config.services.voidauth.subdomain}.${config.networking.domain}/oidc/.well-known/openid-configuration";
|
||||
server_hostname = "https://${config.services.actual.subdomain}.${config.networking.domain}";
|
||||
};
|
||||
loginMethod = "openid";
|
||||
allowedLoginMethods = [ "openid" ];
|
||||
enforceOpenId = true;
|
||||
userCreationMode = "login";
|
||||
};
|
||||
};
|
||||
|
||||
voidauth = {
|
||||
enable = true;
|
||||
subdomain = "auth";
|
||||
environmentFile = secrets.voidauth.path;
|
||||
settings = {
|
||||
APP_PORT = 3300;
|
||||
SMTP_HOST = smtp.host;
|
||||
SMTP_FROM = smtp.from;
|
||||
SMTP_PORT = smtp.port;
|
||||
SMTP_USER = smtp.username;
|
||||
};
|
||||
};
|
||||
|
||||
gitea = {
|
||||
enable = true;
|
||||
subdomain = "git";
|
||||
secrets = secrets.gitea.path;
|
||||
};
|
||||
|
||||
gitea-actions-runner.instances = {
|
||||
default = {
|
||||
enable = true;
|
||||
name = config.networking.domain;
|
||||
labels = [
|
||||
"linux_arm64"
|
||||
"ubuntu-latest:docker://node:latest"
|
||||
"nixos-latest:docker://git.freun.dev/repomaa/nixos/node:latest"
|
||||
];
|
||||
tokenFile = secrets.gitea-actions-runner.path;
|
||||
url = "https://${config.services.gitea.subdomain}.${config.networking.domain}";
|
||||
settings.container.network = "bridge";
|
||||
};
|
||||
};
|
||||
|
||||
webserver = {
|
||||
acme.dnsChallenge = true;
|
||||
tailscaleAuth.expectedTailnet = "tempel-vibes.ts.net";
|
||||
};
|
||||
};
|
||||
|
||||
virtualisation.docker.autoPrune.enable = true;
|
||||
}
|
||||
@@ -1,24 +0,0 @@
|
||||
{ lib, config, ... }:
|
||||
{
|
||||
age.secrets = lib.listToAttrs
|
||||
(
|
||||
map (secret: { name = secret; value = { file = ../../secrets/${secret}.age; }; }) [
|
||||
"gotosocial"
|
||||
"hastebin-tokens"
|
||||
"immich"
|
||||
"readeck"
|
||||
"storage-box-credentials"
|
||||
"vaultwarden"
|
||||
"donetick"
|
||||
]
|
||||
) // {
|
||||
smtp-password = {
|
||||
file = ../../secrets/smtp-password.age;
|
||||
owner =
|
||||
if (config.services.grafana.enable) then
|
||||
config.systemd.services.grafana.serviceConfig.User
|
||||
else
|
||||
"root";
|
||||
};
|
||||
};
|
||||
}
|
||||
@@ -1,144 +0,0 @@
|
||||
{ pkgs, config, ... }:
|
||||
let
|
||||
immichDataDir = "/mnt/storage/immich";
|
||||
syncthingDataDir = "/mnt/storage/syncthing";
|
||||
smtp = {
|
||||
host = "horologium.uberspace.de";
|
||||
port = 587;
|
||||
username = "noreply@${config.networking.domain}";
|
||||
from = "noreply@${config.networking.domain}";
|
||||
heloName = config.networking.domain;
|
||||
};
|
||||
in
|
||||
{
|
||||
services.postgresql.package = pkgs.postgresql_16;
|
||||
virtualisation.podman.enable = true;
|
||||
virtualisation.oci-containers.backend = "podman";
|
||||
|
||||
modules.storageBoxMounts = {
|
||||
${immichDataDir} = {
|
||||
path = "/backup/immich";
|
||||
user = "u407959";
|
||||
uid = config.users.users.${config.services.immich.user}.uid;
|
||||
gid = config.users.groups.${config.services.immich.user}.gid;
|
||||
};
|
||||
|
||||
${syncthingDataDir} = {
|
||||
path = "/backup/syncthing";
|
||||
user = "u407959";
|
||||
uid = config.users.users.${config.services.syncthing.user}.uid;
|
||||
gid = config.users.groups.${config.services.syncthing.user}.gid;
|
||||
};
|
||||
};
|
||||
|
||||
services = {
|
||||
hastebin = {
|
||||
enable = true;
|
||||
subdomain = "bin";
|
||||
};
|
||||
|
||||
readeck = {
|
||||
enable = true;
|
||||
subdomain = "read";
|
||||
settings.email = {
|
||||
host = smtp.host;
|
||||
port = smtp.port;
|
||||
username = smtp.username;
|
||||
encryption = "starttls";
|
||||
from = smtp.from;
|
||||
from_noreply = smtp.from;
|
||||
};
|
||||
};
|
||||
|
||||
donetick = {
|
||||
enable = true;
|
||||
subdomain = "do";
|
||||
settings = {
|
||||
email = {
|
||||
host = smtp.host;
|
||||
port = smtp.port;
|
||||
email = smtp.username;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
grafana = {
|
||||
enable = true;
|
||||
subdomain = "graph";
|
||||
settings.smtp = {
|
||||
enabled = true;
|
||||
host = smtp.host;
|
||||
port = smtp.port;
|
||||
user = smtp.username;
|
||||
from_address = smtp.from;
|
||||
};
|
||||
};
|
||||
|
||||
owncast = {
|
||||
enable = true;
|
||||
subdomain = "stream";
|
||||
};
|
||||
|
||||
gtrackmap = {
|
||||
enable = true;
|
||||
subdomain = "trackmap";
|
||||
port = 3001;
|
||||
};
|
||||
|
||||
invidious = {
|
||||
enable = true;
|
||||
subdomain = "vid";
|
||||
};
|
||||
|
||||
syncthing = {
|
||||
enable = true;
|
||||
subdomain = "sync";
|
||||
dataDir = syncthingDataDir;
|
||||
};
|
||||
|
||||
tailscale.enable = true;
|
||||
|
||||
gotosocial = {
|
||||
enable = true;
|
||||
subdomain = "social";
|
||||
settings = {
|
||||
port = 3002;
|
||||
smtp-host = smtp.host;
|
||||
smtp-port = smtp.port;
|
||||
smtp-username = smtp.username;
|
||||
smtp-from = smtp.from;
|
||||
instance-languages = [ "de" "fi" "en" ];
|
||||
};
|
||||
};
|
||||
|
||||
vaultwarden = {
|
||||
enable = true;
|
||||
subdomain = "pw";
|
||||
config = {
|
||||
YUBICO_CLIENT_ID = 86799;
|
||||
SMTP_HOST = smtp.host;
|
||||
SMTP_FROM = smtp.from;
|
||||
SMTP_FROM_NAME = "Vaultwarden";
|
||||
SMTP_USERNAME = smtp.username;
|
||||
SMTP_PORT = smtp.port;
|
||||
HELO_NAME = smtp.heloName;
|
||||
};
|
||||
};
|
||||
|
||||
workout-tracker = {
|
||||
enable = true;
|
||||
subdomain = "fit";
|
||||
};
|
||||
|
||||
workout-sync = {
|
||||
enable = true;
|
||||
subdomain = "ws";
|
||||
};
|
||||
|
||||
immich = {
|
||||
enable = true;
|
||||
subdomain = "img";
|
||||
mediaLocation = immichDataDir;
|
||||
};
|
||||
};
|
||||
}
|
||||
@@ -1,8 +1,28 @@
|
||||
{ ... }:
|
||||
{
|
||||
nix = {
|
||||
distributedBuilds = true;
|
||||
buildMachines = [
|
||||
{
|
||||
hostName = "freun.dev";
|
||||
maxJobs = 8;
|
||||
protocol = "ssh";
|
||||
sshUser = "builder";
|
||||
systems = [
|
||||
"aarch64-linux"
|
||||
];
|
||||
supportedFeatures = [
|
||||
"kvm"
|
||||
"big-parallel"
|
||||
"nixos-test"
|
||||
];
|
||||
}
|
||||
];
|
||||
settings = {
|
||||
experimental-features = [ "nix-command" "flakes" ];
|
||||
experimental-features = [
|
||||
"nix-command"
|
||||
"flakes"
|
||||
];
|
||||
auto-optimise-store = true;
|
||||
};
|
||||
|
||||
@@ -13,10 +33,6 @@
|
||||
};
|
||||
};
|
||||
|
||||
networking.extraHosts = ''
|
||||
10.10.0.1 warden.apu.repomaa.com
|
||||
'';
|
||||
|
||||
networking.nftables.enable = true;
|
||||
|
||||
# This option defines the first version of NixOS you have installed on this particular machine,
|
||||
|
||||
@@ -1,8 +1,27 @@
|
||||
{ ... }:
|
||||
{ pkgs-unstable, ... }:
|
||||
{
|
||||
virtualisation.docker.storageDriver = "btrfs";
|
||||
virtualisation.docker.rootless = {
|
||||
virtualisation = {
|
||||
containers = {
|
||||
enable = true;
|
||||
setSocketVariable = true;
|
||||
storage.settings.storage.driver = "btrfs";
|
||||
};
|
||||
|
||||
oci-containers.backend = "podman";
|
||||
|
||||
podman = {
|
||||
enable = true;
|
||||
autoPrune.enable = true;
|
||||
defaultNetwork.settings.dns_enabled = true;
|
||||
package = pkgs-unstable.podman;
|
||||
};
|
||||
|
||||
docker = {
|
||||
storageDriver = "btrfs";
|
||||
enable = true;
|
||||
autoPrune.enable = true;
|
||||
};
|
||||
};
|
||||
|
||||
users.users.jokke.extraGroups = [ "docker" ];
|
||||
users.users.moco.extraGroups = [ "docker" ];
|
||||
}
|
||||
|
||||
@@ -1,6 +1,10 @@
|
||||
{ inputs, ... }:
|
||||
let
|
||||
inherit (inputs) lanzaboote nixos-hardware auto-cpufreq home-manager;
|
||||
inherit (inputs)
|
||||
lanzaboote
|
||||
nixos-hardware
|
||||
home-manager
|
||||
;
|
||||
in
|
||||
{
|
||||
imports = [
|
||||
@@ -13,9 +17,9 @@ in
|
||||
./containers.nix
|
||||
./desktop.nix
|
||||
./users.nix
|
||||
./secrets.nix
|
||||
lanzaboote.nixosModules.lanzaboote
|
||||
nixos-hardware.nixosModules.framework-13-7040-amd
|
||||
auto-cpufreq.nixosModules.default
|
||||
home-manager.nixosModules.home-manager
|
||||
../../home
|
||||
];
|
||||
|
||||
@@ -1,12 +1,24 @@
|
||||
{ ... }:
|
||||
{
|
||||
services.xserver = {
|
||||
enable = true;
|
||||
displayManager.gdm.enable = true;
|
||||
desktopManager.gnome.enable = true;
|
||||
};
|
||||
services.displayManager.gdm.enable = true;
|
||||
services.desktopManager.gnome.enable = true;
|
||||
programs.niri.enable = true;
|
||||
|
||||
services.printing.enable = true;
|
||||
services.keyd = {
|
||||
enable = true;
|
||||
keyboards.default = {
|
||||
ids = [ "*" ];
|
||||
settings = {
|
||||
global = {
|
||||
overload_tap_timeout = 200;
|
||||
};
|
||||
main = {
|
||||
leftmeta = "overload(meta, macro(leftmeta+z))";
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
security.rtkit.enable = true;
|
||||
services.pipewire = {
|
||||
@@ -16,7 +28,7 @@
|
||||
pulse.enable = true;
|
||||
jack.enable = true;
|
||||
};
|
||||
hardware.pulseaudio.enable = false;
|
||||
services.pulseaudio.enable = false;
|
||||
|
||||
programs.steam = {
|
||||
enable = true;
|
||||
|
||||
@@ -1,20 +1,31 @@
|
||||
# Do not modify this file! It was generated by ‘nixos-generate-config’
|
||||
# and may be overwritten by future invocations. Please make changes
|
||||
# to /etc/nixos/configuration.nix instead.
|
||||
{ config, lib, pkgs, modulesPath, ... }:
|
||||
{
|
||||
config,
|
||||
lib,
|
||||
modulesPath,
|
||||
...
|
||||
}:
|
||||
|
||||
{
|
||||
imports =
|
||||
[ (modulesPath + "/installer/scan/not-detected.nix")
|
||||
imports = [
|
||||
(modulesPath + "/installer/scan/not-detected.nix")
|
||||
];
|
||||
|
||||
boot.initrd.availableKernelModules = [ "nvme" "xhci_pci" "thunderbolt" "usb_storage" "sd_mod" ];
|
||||
boot.initrd.availableKernelModules = [
|
||||
"nvme"
|
||||
"xhci_pci"
|
||||
"thunderbolt"
|
||||
"usb_storage"
|
||||
"sd_mod"
|
||||
];
|
||||
boot.initrd.kernelModules = [ ];
|
||||
boot.kernelModules = [ "kvm-amd" ];
|
||||
boot.extraModulePackages = [ ];
|
||||
|
||||
fileSystems."/" =
|
||||
{ device = "/dev/disk/by-uuid/a331b669-f5c5-42f7-be58-434873c1b689";
|
||||
fileSystems."/" = {
|
||||
device = "/dev/disk/by-uuid/a331b669-f5c5-42f7-be58-434873c1b689";
|
||||
fsType = "btrfs";
|
||||
options = [ "subvol=@" ];
|
||||
};
|
||||
@@ -24,33 +35,35 @@
|
||||
allowDiscards = true;
|
||||
};
|
||||
|
||||
fileSystems."/var/log" =
|
||||
{ device = "/dev/disk/by-uuid/a331b669-f5c5-42f7-be58-434873c1b689";
|
||||
fileSystems."/var/log" = {
|
||||
device = "/dev/disk/by-uuid/a331b669-f5c5-42f7-be58-434873c1b689";
|
||||
fsType = "btrfs";
|
||||
options = [ "subvol=@var_log" ];
|
||||
};
|
||||
|
||||
fileSystems."/home" =
|
||||
{ device = "/dev/disk/by-uuid/a331b669-f5c5-42f7-be58-434873c1b689";
|
||||
fileSystems."/home" = {
|
||||
device = "/dev/disk/by-uuid/a331b669-f5c5-42f7-be58-434873c1b689";
|
||||
fsType = "btrfs";
|
||||
options = [ "subvol=@home" ];
|
||||
};
|
||||
|
||||
fileSystems."/boot" =
|
||||
{ device = "/dev/disk/by-uuid/01E6-6258";
|
||||
fileSystems."/boot" = {
|
||||
device = "/dev/disk/by-uuid/01E6-6258";
|
||||
fsType = "vfat";
|
||||
};
|
||||
|
||||
fileSystems."/swap" =
|
||||
{ device = "/dev/disk/by-uuid/a331b669-f5c5-42f7-be58-434873c1b689";
|
||||
fileSystems."/swap" = {
|
||||
device = "/dev/disk/by-uuid/a331b669-f5c5-42f7-be58-434873c1b689";
|
||||
fsType = "btrfs";
|
||||
options = [ "subvol=@swap" ];
|
||||
};
|
||||
|
||||
swapDevices = [ {
|
||||
swapDevices = [
|
||||
{
|
||||
device = "/swap/swapfile";
|
||||
size = 64 * 1024;
|
||||
} ];
|
||||
}
|
||||
];
|
||||
|
||||
# Enables DHCP on each ethernet and wireless interface. In case of scripted networking
|
||||
# (the default) this is the recommended approach. When using systemd-networkd it's
|
||||
|
||||
@@ -1,15 +1,19 @@
|
||||
{ pkgs, inputs, lib, config, ... }:
|
||||
let
|
||||
pkgsUnstable = inputs.nixpkgs-unstable.legacyPackages.${pkgs.system};
|
||||
in
|
||||
{
|
||||
pkgs,
|
||||
pkgs-unstable,
|
||||
inputs,
|
||||
lib,
|
||||
config,
|
||||
...
|
||||
}:
|
||||
{
|
||||
hardware.bluetooth.enable = true;
|
||||
hardware.bluetooth.powerOnBoot = true;
|
||||
|
||||
services.udev.packages = [
|
||||
pkgs.zsa-udev-rules
|
||||
pkgsUnstable.yubikey-personalization
|
||||
inputs.ksoloti-pr.legacyPackages.${pkgs.system}.ksoloti
|
||||
pkgs-unstable.yubikey-personalization
|
||||
inputs.ksoloti-pr.legacyPackages.${pkgs.stdenv.hostPlatform.system}.ksoloti
|
||||
];
|
||||
services.usbmuxd = {
|
||||
enable = true;
|
||||
@@ -46,11 +50,11 @@ in
|
||||
hardware.keyboard.zsa.enable = true;
|
||||
|
||||
services.logind = {
|
||||
lidSwitch = "suspend";
|
||||
powerKey = "suspend";
|
||||
extraConfig = ''
|
||||
IdleAction=suspend
|
||||
'';
|
||||
settings.Login = {
|
||||
IdleAction = "suspend";
|
||||
HandleLidSwitch = "suspend";
|
||||
HandlePowerKey = "suspend";
|
||||
};
|
||||
};
|
||||
|
||||
powerManagement = {
|
||||
@@ -59,26 +63,27 @@ in
|
||||
powerUpCommands = "${pkgs.networkmanager}/bin/nmcli radio wifi on";
|
||||
};
|
||||
|
||||
services.power-profiles-daemon.enable = false;
|
||||
|
||||
services.tlp = {
|
||||
enable = true;
|
||||
settings = {
|
||||
CPU_BOOST_ON_BAT = 0;
|
||||
CPU_SCALING_GOVERNOR_ON_BATTERY = "powersave";
|
||||
START_CHARGE_THRESH_BATx = 85;
|
||||
STOP_CHARGE_THRES_BATx = 90;
|
||||
RUNTIME_PM_ON_BAT = "auto";
|
||||
};
|
||||
};
|
||||
|
||||
programs.auto-cpufreq.enable = true;
|
||||
|
||||
services.power-profiles-daemon.enable = true;
|
||||
hardware.amdgpu.opencl.enable = true;
|
||||
hardware.graphics = {
|
||||
enable = true;
|
||||
extraPackages = with pkgs; [ rocmPackages.clr.icd ];
|
||||
};
|
||||
networking.networkmanager.wifi.backend = "iwd";
|
||||
networking.networkmanager = {
|
||||
enable = true;
|
||||
wifi.backend = "iwd";
|
||||
plugins = with pkgs; [
|
||||
networkmanager-openvpn
|
||||
];
|
||||
};
|
||||
security.tpm2.enable = true;
|
||||
|
||||
services.nqptp.enable = true;
|
||||
networking.firewall.allowedTCPPortRanges = [
|
||||
{
|
||||
from = 7000;
|
||||
to = 7010;
|
||||
}
|
||||
];
|
||||
networking.firewall.allowedUDPPorts = [ 5353 ];
|
||||
}
|
||||
|
||||
@@ -3,7 +3,12 @@
|
||||
networking.hostName = "radish";
|
||||
time.timeZone = lib.mkForce null; # allow TZ to be set by desktop user
|
||||
i18n.defaultLocale = "de_DE.UTF-8";
|
||||
i18n.supportedLocales = map (locale: "${locale}.UTF-8/UTF-8") [ "C" "en_US" "de_DE" "fi_FI" ];
|
||||
i18n.supportedLocales = map (locale: "${locale}.UTF-8/UTF-8") [
|
||||
"C"
|
||||
"en_US"
|
||||
"de_DE"
|
||||
"fi_FI"
|
||||
];
|
||||
i18n.extraLocaleSettings.LANG = "en_US.UTF-8";
|
||||
console = {
|
||||
font = "Lat2-Terminus16";
|
||||
|
||||
@@ -1,7 +1,17 @@
|
||||
{ pkgs, lib, inputs, ... }:
|
||||
{
|
||||
pkgs,
|
||||
pkgs-unstable,
|
||||
lib,
|
||||
inputs,
|
||||
config,
|
||||
...
|
||||
}:
|
||||
let
|
||||
secrets = config.age.secrets;
|
||||
in
|
||||
{
|
||||
nixpkgs.config.allowUnfree = true;
|
||||
nixpkgs.overlays = [ (import ../../custom-pkgs { inherit lib inputs; }) ];
|
||||
nixpkgs.overlays = [ (import ../../custom-pkgs { inherit lib inputs pkgs-unstable; }) ];
|
||||
|
||||
environment = {
|
||||
systemPackages = with pkgs; [
|
||||
@@ -18,12 +28,16 @@
|
||||
pathsToLink = [ "/share/zsh" ];
|
||||
};
|
||||
|
||||
services.pcscd = {
|
||||
fonts.packages = with pkgs-unstable; [
|
||||
nerd-fonts.iosevka
|
||||
nerd-fonts.iosevka-term
|
||||
];
|
||||
services = {
|
||||
pcscd = {
|
||||
enable = true;
|
||||
plugins = [ pkgs.ccid ];
|
||||
};
|
||||
|
||||
services = {
|
||||
openssh = {
|
||||
enable = true;
|
||||
openFirewall = false;
|
||||
@@ -32,17 +46,89 @@
|
||||
tailscale = {
|
||||
enable = true;
|
||||
useRoutingFeatures = "client";
|
||||
package = pkgs-unstable.tailscale;
|
||||
};
|
||||
|
||||
ollama = {
|
||||
enable = false; # FIXME: https://github.com/NixOS/nixpkgs/issues/376930
|
||||
acceleration = "rocm";
|
||||
environmentVariables = {
|
||||
HSA_OVERRIDE_GFX_VERSION = "11.0.3";
|
||||
enable = true;
|
||||
package = pkgs-unstable.ollama-vulkan;
|
||||
syncModels = true;
|
||||
loadModels = [
|
||||
"qwen3:4b-instruct"
|
||||
"qwen3:8b"
|
||||
];
|
||||
};
|
||||
|
||||
borgbackup.jobs.root = {
|
||||
paths = "/";
|
||||
exclude = [
|
||||
"/nix"
|
||||
"/var/cache"
|
||||
"/run"
|
||||
"/sys"
|
||||
"/etc"
|
||||
"/swap"
|
||||
"/proc"
|
||||
"**/node_modules"
|
||||
"**/.cargo"
|
||||
"**/ruby/*/gems"
|
||||
"**/.cache"
|
||||
"**/.meteor"
|
||||
"**/.next"
|
||||
"**/.local/share/containers/cache"
|
||||
"**/.local/share/containers/storage/overlay"
|
||||
"**/.local/share/docker/overlay2"
|
||||
"**/log/*.log"
|
||||
"**/.local/share/Trash"
|
||||
];
|
||||
environment = {
|
||||
BORG_RSH = "ssh -i /root/.ssh/id_ed25519.borg";
|
||||
};
|
||||
repo = "ssh://u324815-sub2@u324815.your-storagebox.de:23/./backup";
|
||||
encryption = {
|
||||
mode = "repokey";
|
||||
passphrase = "will be overridden from environment file";
|
||||
};
|
||||
extraCreateArgs = [
|
||||
"--stats"
|
||||
"--progress"
|
||||
];
|
||||
inhibitsSleep = true;
|
||||
compression = "auto,zstd";
|
||||
startAt = "daily";
|
||||
persistentTimer = true;
|
||||
preHook = with pkgs; ''
|
||||
${coreutils}/bin/timeout 60 ${bash}/bin/sh -c '
|
||||
until ${iputils}/bin/ping -c1 your-storagebox.de; do
|
||||
sleep 1
|
||||
done
|
||||
'
|
||||
'';
|
||||
postCreate = with pkgs; ''
|
||||
${curl}/bin/curl "https://status.freun.dev/api/push/''${UPTIME_KUMA_TOKEN}?status=up&msg=OK&ping="
|
||||
'';
|
||||
prune.keep = {
|
||||
within = "3d";
|
||||
daily = 14;
|
||||
weekly = 8;
|
||||
monthly = -1;
|
||||
};
|
||||
};
|
||||
|
||||
locate = {
|
||||
enable = true;
|
||||
package = pkgs.plocate;
|
||||
};
|
||||
|
||||
protonmail-bridge = {
|
||||
enable = true;
|
||||
package = pkgs-unstable.protonmail-bridge;
|
||||
path = [ pkgs.gnome-keyring ];
|
||||
};
|
||||
};
|
||||
|
||||
systemd.services.borgbackup-job-root.serviceConfig.EnvironmentFile = secrets.borgbackup-radish.path;
|
||||
|
||||
programs = {
|
||||
zsh.enable = true;
|
||||
_1password-gui = {
|
||||
@@ -51,4 +137,35 @@
|
||||
};
|
||||
_1password.enable = true;
|
||||
};
|
||||
|
||||
environment.etc."1password/custom_allowed_browsers".text = ''
|
||||
vivaldi
|
||||
'';
|
||||
|
||||
systemd.services.ollama-keep-alive =
|
||||
let
|
||||
ollamaURL = "http://localhost:${toString config.services.ollama.port}/api/generate";
|
||||
payload = {
|
||||
model = lib.elemAt config.services.ollama.loadModels 0;
|
||||
keep_alive = -1;
|
||||
};
|
||||
in
|
||||
{
|
||||
enable = true;
|
||||
description = "Keep Ollama primary model loaded by pinging it";
|
||||
after = [
|
||||
"ollama.service"
|
||||
"network-online.target"
|
||||
];
|
||||
wants = [ "network-online.target" ];
|
||||
bindsTo = [ "ollama.service" ];
|
||||
wantedBy = [
|
||||
"multi-user.target"
|
||||
"ollama.service"
|
||||
];
|
||||
serviceConfig = {
|
||||
Type = "oneshot";
|
||||
ExecStart = "${pkgs.curl}/bin/curl -s '${ollamaURL}' -d '${builtins.toJSON payload}'";
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
15
hosts/radish/secrets.nix
Normal file
15
hosts/radish/secrets.nix
Normal file
@@ -0,0 +1,15 @@
|
||||
{ lib, ... }:
|
||||
{
|
||||
age.secrets = lib.listToAttrs (
|
||||
map
|
||||
(secret: {
|
||||
name = secret;
|
||||
value = {
|
||||
file = ../../secrets/${secret}.age;
|
||||
};
|
||||
})
|
||||
[
|
||||
"borgbackup-radish"
|
||||
]
|
||||
);
|
||||
}
|
||||
@@ -2,16 +2,30 @@
|
||||
{
|
||||
# Define a user account. Don't forget to set a password with ‘passwd’.
|
||||
users.users.jokke = {
|
||||
uid = 1001;
|
||||
isNormalUser = true;
|
||||
extraGroups = [ "wheel" ];
|
||||
shell = pkgs.zsh;
|
||||
initialPassword = "changeme";
|
||||
};
|
||||
|
||||
users.users.moco = {
|
||||
uid = 1000;
|
||||
isNormalUser = true;
|
||||
extraGroups = [ "wheel" ];
|
||||
shell = pkgs.zsh;
|
||||
subUidRanges = [{ startUid = 10000; count = 65536; }];
|
||||
subGidRanges = [{ startGid = 10000; count = 65536; }];
|
||||
initialPassword = "changeme";
|
||||
subUidRanges = [
|
||||
{
|
||||
startUid = 10000;
|
||||
count = 65536;
|
||||
}
|
||||
];
|
||||
subGidRanges = [
|
||||
{
|
||||
startGid = 10000;
|
||||
count = 65536;
|
||||
}
|
||||
];
|
||||
};
|
||||
}
|
||||
|
||||
98
hosts/turny/configuration.nix
Normal file
98
hosts/turny/configuration.nix
Normal file
@@ -0,0 +1,98 @@
|
||||
# Edit this configuration file to define what should be installed on
|
||||
# your system. Help is available in the configuration.nix(5) man page
|
||||
# and in the NixOS manual (accessible by running `nixos-help`).
|
||||
|
||||
{
|
||||
pkgs,
|
||||
ssh,
|
||||
config,
|
||||
inputs,
|
||||
...
|
||||
}:
|
||||
let
|
||||
secrets = config.age.secrets;
|
||||
in
|
||||
{
|
||||
nix = {
|
||||
settings = {
|
||||
experimental-features = [
|
||||
"nix-command"
|
||||
"flakes"
|
||||
];
|
||||
auto-optimise-store = true;
|
||||
};
|
||||
gc = {
|
||||
automatic = true;
|
||||
dates = "weekly";
|
||||
options = "--delete-older-than 30d";
|
||||
};
|
||||
};
|
||||
|
||||
networking = {
|
||||
hostName = "turny"; # Define your hostname.
|
||||
useDHCP = true;
|
||||
useNetworkd = true;
|
||||
nftables.enable = true;
|
||||
wireless = {
|
||||
enable = true;
|
||||
networks = {
|
||||
KotiWLANi.pskRaw = "ext:psk_kotiwlani";
|
||||
};
|
||||
secretsFile = secrets.wpa_supplicant.path;
|
||||
};
|
||||
};
|
||||
|
||||
services.avahi = {
|
||||
publish.enable = true;
|
||||
};
|
||||
|
||||
services.tailscale = {
|
||||
enable = true;
|
||||
useRoutingFeatures = "client";
|
||||
};
|
||||
|
||||
# Set your time zone.
|
||||
time.timeZone = "Europe/Helsinki";
|
||||
|
||||
# Select internationalisation properties.
|
||||
i18n.defaultLocale = "en_US.UTF-8";
|
||||
|
||||
# Define a user account. Don't forget to set a password with ‘passwd’.
|
||||
users.users.jokke = {
|
||||
isNormalUser = true;
|
||||
extraGroups = [ "wheel" ]; # Enable ‘sudo’ for the user.
|
||||
packages = [ pkgs.nh ];
|
||||
openssh.authorizedKeys.keys = [ ssh.publicKeys.yubikey ];
|
||||
initialPassword = "changeme";
|
||||
};
|
||||
users.users.root.openssh.authorizedKeys.keys = [ ssh.publicKeys.yubikey ];
|
||||
|
||||
nix.settings.trusted-users = [ "jokke" ];
|
||||
|
||||
environment.systemPackages = with pkgs; [
|
||||
vim
|
||||
wget
|
||||
htop
|
||||
git
|
||||
inputs.turny.packages.${stdenv.hostPlatform.system}.default
|
||||
];
|
||||
|
||||
# Enable the OpenSSH daemon.
|
||||
services.openssh = {
|
||||
enable = true;
|
||||
settings.PasswordAuthentication = false;
|
||||
};
|
||||
|
||||
modules.firewall = {
|
||||
enable = true;
|
||||
allInterfaces = [ "ssh" ];
|
||||
};
|
||||
|
||||
# This value determines the NixOS release from which the default
|
||||
# settings for stateful data, like file locations and database versions
|
||||
# on your system were taken. It's perfectly fine and recommended to leave
|
||||
# this value at the release version of the first install of this system.
|
||||
# Before changing this value read the documentation for this option
|
||||
# (e.g. man configuration.nix or on https://nixos.org/nixos/options.html).
|
||||
system.stateVersion = "25.05"; # Did you read the comment?
|
||||
}
|
||||
10
hosts/turny/default.nix
Normal file
10
hosts/turny/default.nix
Normal file
@@ -0,0 +1,10 @@
|
||||
{ inputs, ... }:
|
||||
{
|
||||
imports = [
|
||||
./hardware-configuration.nix
|
||||
./configuration.nix
|
||||
./secrets.nix
|
||||
inputs.nixos-hardware.nixosModules.raspberry-pi-3
|
||||
"${inputs.nixpkgs}/nixos/modules/installer/sd-card/sd-image-aarch64.nix"
|
||||
];
|
||||
}
|
||||
4
hosts/turny/hardware-configuration.nix
Normal file
4
hosts/turny/hardware-configuration.nix
Normal file
@@ -0,0 +1,4 @@
|
||||
{ lib, ... }:
|
||||
{
|
||||
nixpkgs.hostPlatform = lib.mkDefault "aarch64-linux";
|
||||
}
|
||||
15
hosts/turny/secrets.nix
Normal file
15
hosts/turny/secrets.nix
Normal file
@@ -0,0 +1,15 @@
|
||||
{ lib, ... }:
|
||||
{
|
||||
age.secrets = lib.listToAttrs (
|
||||
map
|
||||
(secret: {
|
||||
name = secret;
|
||||
value = {
|
||||
file = ../../secrets/${secret}.age;
|
||||
};
|
||||
})
|
||||
[
|
||||
"wpa_supplicant"
|
||||
]
|
||||
);
|
||||
}
|
||||
@@ -1,5 +1,12 @@
|
||||
{ inputs, ... }:
|
||||
{ inputs, config, ... }:
|
||||
{
|
||||
_module.args = {
|
||||
pkgs-unstable = import inputs.nixpkgs-unstable {
|
||||
system = config.nixpkgs.hostPlatform.system;
|
||||
config = config.nixpkgs.config;
|
||||
};
|
||||
};
|
||||
|
||||
imports = [
|
||||
./vlans.nix
|
||||
./firewall.nix
|
||||
|
||||
@@ -1,19 +1,48 @@
|
||||
{ lib, config, ... }:
|
||||
let
|
||||
services = {
|
||||
ssh = { tcp = [ 22 ]; };
|
||||
dhcp = { udp = [ 67 68 ]; };
|
||||
dns = { udp = [ 53 ]; };
|
||||
web = { tcp = [ 80 443 ]; };
|
||||
ssh = {
|
||||
tcp = [ 22 ];
|
||||
};
|
||||
dhcp = {
|
||||
udp = [
|
||||
67
|
||||
68
|
||||
];
|
||||
};
|
||||
dns = {
|
||||
udp = [
|
||||
53
|
||||
853
|
||||
];
|
||||
tcp = [
|
||||
53
|
||||
853
|
||||
];
|
||||
};
|
||||
web = {
|
||||
tcp = [
|
||||
80
|
||||
443
|
||||
];
|
||||
};
|
||||
};
|
||||
|
||||
rulesForServices = enabledServices:
|
||||
rulesForServices =
|
||||
enabledServices:
|
||||
lib.foldr
|
||||
(service: { allowedUDPPorts, allowedTCPPorts }: {
|
||||
(
|
||||
service:
|
||||
{ allowedUDPPorts, allowedTCPPorts }:
|
||||
{
|
||||
allowedUDPPorts = allowedUDPPorts ++ services.${service}.udp or [ ];
|
||||
allowedTCPPorts = allowedTCPPorts ++ services.${service}.tcp or [ ];
|
||||
})
|
||||
{ allowedUDPPorts = [ ]; allowedTCPPorts = [ ]; }
|
||||
}
|
||||
)
|
||||
{
|
||||
allowedUDPPorts = [ ];
|
||||
allowedTCPPorts = [ ];
|
||||
}
|
||||
enabledServices;
|
||||
|
||||
cfg = config.modules.firewall;
|
||||
|
||||
32
modules/services/actual.nix
Normal file
32
modules/services/actual.nix
Normal file
@@ -0,0 +1,32 @@
|
||||
{
|
||||
lib,
|
||||
config,
|
||||
...
|
||||
}:
|
||||
let
|
||||
cfg = config.services.actual;
|
||||
fqdn = "${cfg.subdomain}.${config.networking.domain}";
|
||||
in
|
||||
{
|
||||
options.services.actual = {
|
||||
subdomain = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
};
|
||||
environmentFile = lib.mkOption {
|
||||
type = lib.types.nullOr lib.types.path;
|
||||
};
|
||||
};
|
||||
|
||||
config = lib.mkIf cfg.enable {
|
||||
services = {
|
||||
webserver = {
|
||||
enable = lib.mkDefault true;
|
||||
vHosts.${fqdn}.locations."/".proxyPort = cfg.settings.port;
|
||||
};
|
||||
};
|
||||
|
||||
systemd.services.actual = {
|
||||
serviceConfig.EnvironmentFile = cfg.environmentFile;
|
||||
};
|
||||
};
|
||||
}
|
||||
63
modules/services/adguardhome.nix
Normal file
63
modules/services/adguardhome.nix
Normal file
@@ -0,0 +1,63 @@
|
||||
{ config, lib, ... }:
|
||||
let
|
||||
cfg = config.services.tailscaledAdguardhome;
|
||||
fqdn = "${cfg.subdomain}.${config.networking.domain}";
|
||||
tailscaleIps = [
|
||||
"100.84.105.63"
|
||||
"fd7a:115c:a1e0::7901:693f"
|
||||
];
|
||||
acme = config.security.acme;
|
||||
in
|
||||
{
|
||||
imports = [
|
||||
(lib.mkAliasOptionModule
|
||||
[ "services" "tailscaledAdguardhome" "settings" ]
|
||||
[ "services" "adguardhome" "settings" ]
|
||||
)
|
||||
(lib.mkAliasOptionModule
|
||||
[ "services" "tailscaledAdguardhome" "port" ]
|
||||
[ "services" "adguardhome" "port" ]
|
||||
)
|
||||
];
|
||||
|
||||
options.services.tailscaledAdguardhome = {
|
||||
enable = lib.mkEnableOption "Enable tailscaled adguardhome";
|
||||
subdomain = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
};
|
||||
};
|
||||
|
||||
config = lib.mkIf cfg.enable {
|
||||
services.tailscale.enable = true;
|
||||
modules.firewall.interfaces.${config.services.tailscale.interfaceName} = [ "dns" ];
|
||||
|
||||
systemd.services.adguardhome.serviceConfig.LoadCredential = [
|
||||
"fullchain.pem:${acme.certs.${fqdn}.directory}/fullchain.pem"
|
||||
"key.pem:${acme.certs.${fqdn}.directory}/key.pem"
|
||||
];
|
||||
|
||||
services.adguardhome = {
|
||||
enable = cfg.enable;
|
||||
settings = {
|
||||
tls = {
|
||||
enabled = true;
|
||||
server_name = fqdn;
|
||||
port_https = 4443;
|
||||
certificate_chain_path = "/run/credentials/adguardhome.service/fullchain.pem";
|
||||
private_key_path = "/run/credentials/adguardhome.service/key.pem";
|
||||
};
|
||||
dns.bind_hosts = tailscaleIps;
|
||||
};
|
||||
};
|
||||
|
||||
systemd.services.adguardhome = {
|
||||
requires = [ "tailscaled.service" ];
|
||||
after = [ "tailscaled.service" ];
|
||||
};
|
||||
|
||||
services.webserver.vHosts.${fqdn} = {
|
||||
tailscaleAuth = true;
|
||||
locations."/".proxyPort = cfg.port;
|
||||
};
|
||||
};
|
||||
}
|
||||
@@ -16,5 +16,22 @@
|
||||
./workout-sync.nix
|
||||
./readeck.nix
|
||||
./donetick.nix
|
||||
./dnote.nix
|
||||
./octodns.nix
|
||||
./adguardhome.nix
|
||||
./mealie.nix
|
||||
./uptime-kuma.nix
|
||||
./mosquitto.nix
|
||||
./home-assistant.nix
|
||||
./weechat.nix
|
||||
./hledger-web.nix
|
||||
./glance.nix
|
||||
./sillytavern.nix
|
||||
./nqptp.nix
|
||||
./actual.nix
|
||||
./voidauth.nix
|
||||
./gitea.nix
|
||||
./dhcp-dns-sync
|
||||
./invidious-companion.nix
|
||||
];
|
||||
}
|
||||
|
||||
125
modules/services/dhcp-dns-sync/default.nix
Normal file
125
modules/services/dhcp-dns-sync/default.nix
Normal file
@@ -0,0 +1,125 @@
|
||||
{
|
||||
lib,
|
||||
config,
|
||||
pkgs,
|
||||
...
|
||||
}:
|
||||
let
|
||||
cfg = config.modules.services.dhcp-dns-sync;
|
||||
ownAddress = (
|
||||
lib.elemAt (lib.splitString "/"
|
||||
config.systemd.network.networks."30-${cfg.interface}".networkConfig.Address
|
||||
) 0
|
||||
);
|
||||
|
||||
dhcp-leases-to-unbound =
|
||||
pkgs.runCommand "dhcp-leases-to-unbound"
|
||||
{
|
||||
code = ./dhcp-leases-to-unbound.cr;
|
||||
nativeBuildInputs = [ pkgs.crystal ];
|
||||
meta.mainProgram = "dhcp-leases-to-unbound";
|
||||
}
|
||||
''
|
||||
mkdir -p $out/bin
|
||||
crystal build $code --release -o $out/bin/dhcp-leases-to-unbound
|
||||
'';
|
||||
in
|
||||
{
|
||||
options.modules.services.dhcp-dns-sync = {
|
||||
enable = lib.mkEnableOption "Enable DHCP to DNS synchronization";
|
||||
|
||||
interface = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = "koti";
|
||||
description = "Network interface to monitor for DHCP leases";
|
||||
};
|
||||
|
||||
domain = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = "home.arpa";
|
||||
description = "Domain suffix for DHCP hostnames";
|
||||
};
|
||||
|
||||
unboundConfigPath = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = "/var/lib/unbound/dhcp-hosts.conf";
|
||||
description = "Path to write Unbound include file";
|
||||
};
|
||||
|
||||
interval = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = "30s";
|
||||
description = "Interval for checking DHCP lease updates";
|
||||
};
|
||||
};
|
||||
|
||||
config = lib.mkIf cfg.enable {
|
||||
# Create user and group for the service
|
||||
users.users.dhcp-dns-sync = {
|
||||
isSystemUser = true;
|
||||
group = "dhcp-dns-sync";
|
||||
description = "DHCP DNS sync service user";
|
||||
};
|
||||
|
||||
users.groups.dhcp-dns-sync = { };
|
||||
|
||||
# Ensure directories and files exist with proper permissions
|
||||
# Directory needs to be group-writable for unbound group
|
||||
systemd.tmpfiles.rules = [
|
||||
"d /var/lib/unbound 0775 unbound unbound -"
|
||||
"f ${cfg.unboundConfigPath} 0644 dhcp-dns-sync unbound -"
|
||||
];
|
||||
|
||||
# Extend Unbound configuration to include generated file
|
||||
services.unbound.settings = {
|
||||
server = {
|
||||
local-zone = [ "${cfg.domain}. static" ];
|
||||
include = cfg.unboundConfigPath;
|
||||
local-data = [ ''"apu.home.arpa. IN A ${ownAddress}"'' ];
|
||||
local-data-ptr = [ ''"${ownAddress} apu.home.arpa."'' ];
|
||||
};
|
||||
};
|
||||
|
||||
# Make sure Unbound control is enabled
|
||||
services.unbound.settings.remote-control.control-enable = true;
|
||||
|
||||
# Systemd service
|
||||
systemd.services.dhcp-dns-sync = {
|
||||
description = "Sync DHCP leases to Unbound DNS";
|
||||
after = [
|
||||
"systemd-networkd.service"
|
||||
"unbound.service"
|
||||
];
|
||||
requires = [ "unbound.service" ];
|
||||
wants = [ "unbound-control.socket" ];
|
||||
|
||||
serviceConfig = {
|
||||
Type = "oneshot";
|
||||
User = "dhcp-dns-sync";
|
||||
Group = "unbound";
|
||||
# Allow access to networkctl via D-Bus
|
||||
SupplementaryGroups = [ "systemd-network" ];
|
||||
# Read/write paths
|
||||
ReadWritePaths = [ "/var/lib/unbound" ];
|
||||
ExecStart = lib.concatStringsSep " " [
|
||||
(lib.getExe dhcp-leases-to-unbound)
|
||||
"-i ${cfg.interface}"
|
||||
"-d ${cfg.domain}"
|
||||
"-o ${cfg.unboundConfigPath}"
|
||||
"--networkctl ${lib.getExe' pkgs.systemd "networkctl"}"
|
||||
"--unbound-control ${lib.getExe' pkgs.unbound "unbound-control"}"
|
||||
];
|
||||
};
|
||||
};
|
||||
|
||||
# Systemd timer
|
||||
systemd.timers.dhcp-dns-sync = {
|
||||
description = "Periodic DHCP to DNS sync";
|
||||
wantedBy = [ "timers.target" ];
|
||||
timerConfig = {
|
||||
OnBootSec = "10s";
|
||||
OnUnitActiveSec = cfg.interval;
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
187
modules/services/dhcp-dns-sync/dhcp-leases-to-unbound.cr
Normal file
187
modules/services/dhcp-dns-sync/dhcp-leases-to-unbound.cr
Normal file
@@ -0,0 +1,187 @@
|
||||
#!/usr/bin/env crystal
|
||||
|
||||
require "json"
|
||||
require "file_utils"
|
||||
require "option_parser"
|
||||
|
||||
struct Lease
|
||||
include JSON::Serializable
|
||||
|
||||
@[JSON::Field(key: "Address")]
|
||||
property address_bytes : Array(Int32)
|
||||
|
||||
@[JSON::Field(key: "HardwareAddress")]
|
||||
property hardware_address : Array(Int32)?
|
||||
|
||||
@[JSON::Field(key: "Hostname")]
|
||||
property hostname : String?
|
||||
|
||||
@[JSON::Field(key: "ExpirationUSec")]
|
||||
property expiration_usec : Int64?
|
||||
|
||||
def address : String
|
||||
address_bytes.join('.')
|
||||
end
|
||||
end
|
||||
|
||||
struct DHCPServer
|
||||
include JSON::Serializable
|
||||
|
||||
@[JSON::Field(key: "Leases")]
|
||||
property leases : Array(Lease)?
|
||||
end
|
||||
|
||||
struct NetworkStatus
|
||||
include JSON::Serializable
|
||||
|
||||
@[JSON::Field(key: "DHCPServer")]
|
||||
property dhcp_server : DHCPServer?
|
||||
end
|
||||
|
||||
def sanitize_hostname(hostname : String) : String?
|
||||
# Lowercase and strip invalid characters
|
||||
sanitized = hostname.downcase.gsub(/[^a-z0-9-]/, "-")
|
||||
|
||||
# Collapse multiple dashes into one
|
||||
sanitized = sanitized.gsub(/-+/, "-")
|
||||
|
||||
# Strip leading/trailing dashes
|
||||
sanitized = sanitized.strip('-')
|
||||
|
||||
# Ensure non-empty and not too long (max 63 chars for DNS label)
|
||||
return nil if sanitized.empty?
|
||||
return nil if sanitized.size > 63
|
||||
|
||||
# Ensure starts with letter or number (not dash)
|
||||
return nil if sanitized.starts_with?('-')
|
||||
|
||||
sanitized
|
||||
end
|
||||
|
||||
def generate_unbound_config(leases : Array(Lease), domain : String) : String
|
||||
lines = [] of String
|
||||
|
||||
lines << "# Auto-generated DHCP leases for #{domain}"
|
||||
lines << "# Generated at #{Time.utc}"
|
||||
lines << ""
|
||||
|
||||
leases.each do |lease|
|
||||
next unless hostname = lease.hostname
|
||||
sanitized = sanitize_hostname(hostname)
|
||||
next unless sanitized
|
||||
|
||||
fqdn = "#{sanitized}.#{domain}."
|
||||
|
||||
# A record
|
||||
lines << %{local-data: "#{fqdn} IN A #{lease.address}"}
|
||||
|
||||
# PTR record - local-data-ptr expects IP in normal form, unbound reverses it
|
||||
lines << %{local-data-ptr: "#{lease.address} #{fqdn}"}
|
||||
end
|
||||
|
||||
lines.join("\n") + "\n"
|
||||
end
|
||||
|
||||
def get_leases(interface : String, networkctl_path : String? = nil) : Array(Lease)
|
||||
cmd = networkctl_path ? "#{networkctl_path}" : "networkctl"
|
||||
args = ["status", interface, "--json=short"]
|
||||
|
||||
Process.run(cmd, args, output: Process::Redirect::Pipe, error: Process::Redirect::Pipe) do |process|
|
||||
result = process.wait
|
||||
output = process.output.to_s
|
||||
|
||||
unless result.success?
|
||||
error = process.error.to_s
|
||||
raise "networkctl failed (exit code #{result.exit_code}): #{error.empty? ? output : error}"
|
||||
end
|
||||
|
||||
status = NetworkStatus.from_json(output)
|
||||
status.dhcp_server.try(&.leases) || [] of Lease
|
||||
end
|
||||
end
|
||||
|
||||
def write_if_changed(content : String, path : String) : Bool
|
||||
# Check if content is the same
|
||||
if File.exists?(path)
|
||||
current = File.read(path)
|
||||
return false if current == content
|
||||
end
|
||||
|
||||
# Write to temp file and atomically move
|
||||
temp_path = "#{path}.tmp"
|
||||
File.write(temp_path, content)
|
||||
FileUtils.mv(temp_path, path)
|
||||
true
|
||||
end
|
||||
|
||||
# Configuration
|
||||
interface = "koti"
|
||||
domain = "home.arpa"
|
||||
output_path = "/var/lib/unbound/dhcp-hosts.conf"
|
||||
networkctl_path : String? = nil
|
||||
unbound_control_path : String? = nil
|
||||
|
||||
OptionParser.parse do |parser|
|
||||
parser.banner = "Usage: dhcp-leases-to-unbound [options]"
|
||||
|
||||
parser.on("-i INTERFACE", "Network interface to monitor (default: koti)") do |i|
|
||||
interface = i
|
||||
end
|
||||
|
||||
parser.on("-d DOMAIN", "Domain suffix (default: home.arpa)") do |d|
|
||||
domain = d
|
||||
end
|
||||
|
||||
parser.on("-o PATH", "Output path for unbound config (default: /var/lib/unbound/dhcp-hosts.conf)") do |o|
|
||||
output_path = o
|
||||
end
|
||||
|
||||
parser.on("--networkctl PATH", "Path to networkctl binary (default: networkctl from PATH)") do |path|
|
||||
networkctl_path = path
|
||||
end
|
||||
|
||||
parser.on("--unbound-control PATH", "Path to unbound-control binary (default: unbound-control from PATH)") do |path|
|
||||
unbound_control_path = path
|
||||
end
|
||||
|
||||
parser.on("-h", "--help", "Show this help") do
|
||||
puts parser
|
||||
exit
|
||||
end
|
||||
end
|
||||
|
||||
def reload_unbound(unbound_control_path : String?)
|
||||
cmd = unbound_control_path ? "#{unbound_control_path}" : "unbound-control"
|
||||
puts "Reloading Unbound..."
|
||||
|
||||
Process.run(cmd, ["reload"], output: Process::Redirect::Pipe, error: Process::Redirect::Pipe) do |process|
|
||||
result = process.wait
|
||||
|
||||
unless result.success?
|
||||
raise "unbound reload failed (exit code #{result.exit_code}): #{process.error}"
|
||||
end
|
||||
end
|
||||
|
||||
puts "Unbound reloaded successfully."
|
||||
end
|
||||
|
||||
begin
|
||||
# Get leases from networkd
|
||||
leases = get_leases(interface, networkctl_path)
|
||||
|
||||
# Generate Unbound config
|
||||
config = generate_unbound_config(leases, domain)
|
||||
|
||||
# Write Unbound config if changed
|
||||
changed = write_if_changed(config, output_path)
|
||||
|
||||
# Reload Unbound if config changed
|
||||
if changed
|
||||
reload_unbound(unbound_control_path)
|
||||
else
|
||||
puts "No DHCP lease changes detected."
|
||||
end
|
||||
rescue ex : Exception
|
||||
STDERR.puts "Error: #{ex.message}"
|
||||
exit 1
|
||||
end
|
||||
138
modules/services/dnote.nix
Normal file
138
modules/services/dnote.nix
Normal file
@@ -0,0 +1,138 @@
|
||||
{
|
||||
lib,
|
||||
config,
|
||||
pkgs,
|
||||
pkgs-unstable,
|
||||
...
|
||||
}:
|
||||
let
|
||||
cfg = config.services.dnote;
|
||||
fqdn = "${cfg.subdomain}.${config.networking.domain}";
|
||||
|
||||
types = {
|
||||
environment = lib.types.submodule {
|
||||
options = {
|
||||
DBName = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = "dnote";
|
||||
};
|
||||
SmtpHost = lib.mkOption {
|
||||
type = lib.types.nullOr lib.types.str;
|
||||
default = null;
|
||||
};
|
||||
SmtpPort = lib.mkOption {
|
||||
type = lib.types.nullOr lib.types.int;
|
||||
default = null;
|
||||
};
|
||||
SmtpUsername = lib.mkOption {
|
||||
type = lib.types.nullOr lib.types.str;
|
||||
default = null;
|
||||
};
|
||||
SmtpPassword = lib.mkOption {
|
||||
type = lib.types.nullOr lib.types.str;
|
||||
default = null;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
immutableEnvironment = {
|
||||
GO_ENV = "PRODUCTION";
|
||||
OnPremises = true;
|
||||
DBHost = "/var/run/postgresql";
|
||||
DBPort = config.services.postgresql.settings.port;
|
||||
DBUser = cfg.user;
|
||||
WebURL = "https://${fqdn}";
|
||||
};
|
||||
|
||||
serializeEnvVar =
|
||||
value: if (lib.isBool value) then if value then "true" else "false" else toString value;
|
||||
in
|
||||
{
|
||||
options.services.dnote = {
|
||||
enable = lib.mkEnableOption "Enable dnote server";
|
||||
subdomain = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
};
|
||||
user = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = "dnote";
|
||||
};
|
||||
port = lib.mkOption {
|
||||
type = lib.types.int;
|
||||
default = 3040;
|
||||
};
|
||||
environment = lib.mkOption {
|
||||
type = types.environment;
|
||||
default = { };
|
||||
};
|
||||
environmentFile = lib.mkOption {
|
||||
type = lib.types.nullOr lib.types.path;
|
||||
default = null;
|
||||
};
|
||||
};
|
||||
|
||||
config = lib.mkIf cfg.enable {
|
||||
users = {
|
||||
users.${cfg.user} = {
|
||||
isSystemUser = true;
|
||||
group = cfg.user;
|
||||
};
|
||||
groups.${cfg.user} = { };
|
||||
};
|
||||
|
||||
systemd.services.dnote = {
|
||||
enable = true;
|
||||
description = "Dnote server";
|
||||
environment = lib.mapAttrs (_: value: serializeEnvVar value) (
|
||||
cfg.environment // immutableEnvironment
|
||||
);
|
||||
after = [ "postgresql.service" ];
|
||||
requires = [ "postgresql.service" ];
|
||||
serviceConfig = {
|
||||
ExecStart = "${pkgs-unstable.dnote}/bin/dnote-server -port ${toString cfg.port} start";
|
||||
EnvironmentFile = lib.mkIf (cfg.environmentFile != null) cfg.environmentFile;
|
||||
User = cfg.user;
|
||||
BindPaths = [
|
||||
"/var/run/postgresql"
|
||||
];
|
||||
BindReadOnlyPaths = [
|
||||
/run/systemd/resolve/stub-resolv.conf
|
||||
/etc/ssl
|
||||
/etc/static/ssl
|
||||
/etc/resolv.conf
|
||||
/etc/static/resolv.conf
|
||||
/etc/nsswitch.conf
|
||||
/etc/static/nsswitch.conf
|
||||
/etc/hosts
|
||||
];
|
||||
};
|
||||
confinement = {
|
||||
enable = true;
|
||||
packages = [ pkgs.cacert ];
|
||||
};
|
||||
wantedBy = [ "multi-user.target" ];
|
||||
};
|
||||
|
||||
services = {
|
||||
postgresql = {
|
||||
enable = lib.mkDefault true;
|
||||
ensureDatabases = [ cfg.environment.DBName ];
|
||||
ensureUsers = [
|
||||
{
|
||||
name = cfg.user;
|
||||
ensureDBOwnership = true;
|
||||
}
|
||||
];
|
||||
};
|
||||
|
||||
webserver = {
|
||||
enable = lib.mkDefault true;
|
||||
vHosts.${fqdn} = {
|
||||
proxyBuffering = false;
|
||||
locations."/".proxyPort = cfg.port;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
@@ -1,4 +1,9 @@
|
||||
{ lib, pkgs, config, ... }:
|
||||
{
|
||||
lib,
|
||||
pkgs,
|
||||
config,
|
||||
...
|
||||
}:
|
||||
let
|
||||
types = {
|
||||
jwtSettings = {
|
||||
|
||||
74
modules/services/gitea.nix
Normal file
74
modules/services/gitea.nix
Normal file
@@ -0,0 +1,74 @@
|
||||
{
|
||||
lib,
|
||||
config,
|
||||
...
|
||||
}:
|
||||
let
|
||||
cfg = config.services.gitea;
|
||||
fqdn = "${cfg.subdomain}.${config.networking.domain}";
|
||||
in
|
||||
{
|
||||
options.services.gitea = {
|
||||
subdomain = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
};
|
||||
secrets = lib.mkOption {
|
||||
type = lib.types.nullOr lib.types.path;
|
||||
default = null;
|
||||
};
|
||||
};
|
||||
|
||||
config = lib.mkIf cfg.enable {
|
||||
services.gitea = {
|
||||
database = {
|
||||
type = "postgres";
|
||||
socket = "/run/postgresql";
|
||||
};
|
||||
settings = {
|
||||
server = {
|
||||
ROOT_URL = "https://${fqdn}/";
|
||||
HTTP_ADDR = "127.0.0.1";
|
||||
HTTP_PORT = 3008;
|
||||
SSH_DOMAIN = fqdn;
|
||||
SSH_PORT = 2222;
|
||||
SSH_LISTEN_PORT = 2222;
|
||||
START_SSH_SERVER = true;
|
||||
};
|
||||
service = {
|
||||
DISABLE_REGISTRATION = false;
|
||||
};
|
||||
mailer = {
|
||||
ENABLED = true;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
services = {
|
||||
webserver = {
|
||||
enable = lib.mkDefault true;
|
||||
vHosts.${fqdn}.locations."/" = {
|
||||
proxyPort = 3008;
|
||||
extraConfig = "client_max_body_size 0;";
|
||||
};
|
||||
};
|
||||
postgresql = {
|
||||
enable = lib.mkDefault true;
|
||||
ensureDatabases = [ "gitea" ];
|
||||
ensureUsers = [
|
||||
{
|
||||
name = "gitea";
|
||||
ensureDBOwnership = true;
|
||||
}
|
||||
];
|
||||
};
|
||||
};
|
||||
|
||||
systemd.services.gitea = {
|
||||
serviceConfig = lib.mkIf (cfg.secrets != null) {
|
||||
EnvironmentFile = cfg.secrets;
|
||||
};
|
||||
};
|
||||
|
||||
networking.firewall.allowedTCPPorts = [ 2222 ];
|
||||
};
|
||||
}
|
||||
45
modules/services/glance.nix
Normal file
45
modules/services/glance.nix
Normal file
@@ -0,0 +1,45 @@
|
||||
{ config, lib, ... }:
|
||||
let
|
||||
cfg = config.services.tailscaledGlance;
|
||||
fqdn = "${cfg.subdomain}.${config.networking.domain}";
|
||||
acme = config.security.acme;
|
||||
in
|
||||
{
|
||||
imports = [
|
||||
(lib.mkAliasOptionModule
|
||||
[ "services" "tailscaledGlance" "settings" ]
|
||||
[ "services" "glance" "settings" ]
|
||||
)
|
||||
];
|
||||
|
||||
options.services.tailscaledGlance = {
|
||||
enable = lib.mkEnableOption "Enable tailscaled glance";
|
||||
subdomain = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
};
|
||||
};
|
||||
|
||||
config = lib.mkIf cfg.enable {
|
||||
services.tailscale.enable = true;
|
||||
modules.firewall.interfaces.${config.services.tailscale.interfaceName} = [ "dns" ];
|
||||
|
||||
systemd.services.glance.serviceConfig.LoadCredential = [
|
||||
"fullchain.pem:${acme.certs.${fqdn}.directory}/fullchain.pem"
|
||||
"key.pem:${acme.certs.${fqdn}.directory}/key.pem"
|
||||
];
|
||||
|
||||
services.glance = {
|
||||
enable = cfg.enable;
|
||||
};
|
||||
|
||||
systemd.services.glance = {
|
||||
requires = [ "tailscaled.service" ];
|
||||
after = [ "tailscaled.service" ];
|
||||
};
|
||||
|
||||
services.webserver.vHosts.${fqdn} = {
|
||||
tailscaleAuth = true;
|
||||
locations."/".proxyPort = cfg.settings.server.port;
|
||||
};
|
||||
};
|
||||
}
|
||||
@@ -38,7 +38,8 @@ in
|
||||
value.extraConfig = ''
|
||||
rewrite ^.*$ https://${fqdn}/.well-known/${path} permanent;
|
||||
'';
|
||||
}) [
|
||||
})
|
||||
[
|
||||
"host-meta"
|
||||
"webfinger"
|
||||
"nodeinfo"
|
||||
|
||||
@@ -31,7 +31,8 @@ in
|
||||
};
|
||||
};
|
||||
|
||||
services.prometheus = {
|
||||
services = {
|
||||
prometheus = {
|
||||
enable = true;
|
||||
exporters.node.enable = true;
|
||||
scrapeConfigs = [
|
||||
@@ -44,15 +45,18 @@ in
|
||||
];
|
||||
};
|
||||
|
||||
services.webserver.vHosts.${fqdn}.locations."/".proxyPort = cfg.settings.server.http_port;
|
||||
webserver.vHosts.${fqdn}.locations."/".proxyPort = cfg.settings.server.http_port;
|
||||
|
||||
services.postgresql = {
|
||||
postgresql = {
|
||||
enable = lib.mkDefault true;
|
||||
ensureDatabases = [ "grafana" ];
|
||||
ensureUsers = [{
|
||||
ensureUsers = [
|
||||
{
|
||||
name = "grafana";
|
||||
ensureDBOwnership = true;
|
||||
}];
|
||||
}
|
||||
];
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
@@ -1,4 +1,9 @@
|
||||
{ lib, config, inputs, ... }:
|
||||
{
|
||||
lib,
|
||||
config,
|
||||
inputs,
|
||||
...
|
||||
}:
|
||||
let
|
||||
cfg = config.services.gtrackmap;
|
||||
fqdn = "${cfg.subdomain}.${config.networking.domain}";
|
||||
|
||||
@@ -1,4 +1,9 @@
|
||||
{ lib, config, inputs, ... }:
|
||||
{
|
||||
lib,
|
||||
config,
|
||||
inputs,
|
||||
...
|
||||
}:
|
||||
let
|
||||
cfg = config.services.hastebin;
|
||||
secrets = config.age.secrets;
|
||||
|
||||
72
modules/services/hledger-web.nix
Normal file
72
modules/services/hledger-web.nix
Normal file
@@ -0,0 +1,72 @@
|
||||
{ config, lib, ... }:
|
||||
let
|
||||
cfg = config.services.hledger-web;
|
||||
fqdn = "${cfg.subdomain}.${config.networking.domain}";
|
||||
in
|
||||
{
|
||||
options.services.hledger-web = {
|
||||
subdomain = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
};
|
||||
user = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
};
|
||||
group = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
};
|
||||
};
|
||||
|
||||
config = lib.mkIf cfg.enable {
|
||||
services = {
|
||||
hledger-web = {
|
||||
allow = lib.mkDefault "edit";
|
||||
baseUrl = "https://${fqdn}";
|
||||
serveApi = true;
|
||||
extraOptions = [
|
||||
"--exchange=€"
|
||||
];
|
||||
};
|
||||
|
||||
webserver = {
|
||||
enable = lib.mkDefault true;
|
||||
vHosts.${fqdn} = {
|
||||
tailscaleAuth = true;
|
||||
extraConfig = ''
|
||||
root /var/www/ledgio;
|
||||
add_header Access-Control-Allow-Origin $http_origin always;
|
||||
add_header Access-Control-Allow-Methods 'OPTIONS, GET, PUT' always;
|
||||
add_header Access-Control-Allow-Headers 'Content-Type' always;
|
||||
|
||||
location ~ \.(html|js|css|png|jpg|jpeg|gif|ico|svg|woff|woff2|ttf|eot)$ {
|
||||
try_files $uri =404;
|
||||
}
|
||||
'';
|
||||
|
||||
locations = {
|
||||
"@api" = {
|
||||
proxyPort = cfg.port;
|
||||
};
|
||||
|
||||
"/".extraConfig = ''
|
||||
if ($request_method = OPTIONS) {
|
||||
add_header Content-Type text/plain;
|
||||
add_header Content-Length 0;
|
||||
add_header Access-Control-Allow-Origin $http_origin;
|
||||
add_header Access-Control-Allow-Methods 'OPTIONS, GET, PUT';
|
||||
add_header Access-Control-Allow-Headers 'Content-Type';
|
||||
return 204;
|
||||
}
|
||||
|
||||
try_files $uri $uri/ @api;
|
||||
'';
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
systemd.services.hledger-web.serviceConfig = {
|
||||
User = lib.mkForce cfg.user;
|
||||
Group = lib.mkForce cfg.group;
|
||||
};
|
||||
};
|
||||
}
|
||||
20
modules/services/home-assistant.nix
Normal file
20
modules/services/home-assistant.nix
Normal file
@@ -0,0 +1,20 @@
|
||||
{ config, lib, ... }:
|
||||
let
|
||||
cfg = config.services.home-assistant;
|
||||
fqdn = "${cfg.subdomain}.${config.networking.domain}";
|
||||
in
|
||||
{
|
||||
options.services.home-assistant = {
|
||||
subdomain = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
description = "The subdomain to use for Home Assistant";
|
||||
};
|
||||
};
|
||||
|
||||
config = lib.mkIf cfg.enable {
|
||||
services.webserver = {
|
||||
enable = lib.mkDefault true;
|
||||
vHosts.${fqdn}.locations."/".proxyPort = cfg.config.http.server_port;
|
||||
};
|
||||
};
|
||||
}
|
||||
@@ -31,7 +31,18 @@ in
|
||||
};
|
||||
webserver = {
|
||||
enable = lib.mkDefault true;
|
||||
vHosts.${fqdn}.locations."/".proxyPort = cfg.port;
|
||||
vHosts.${fqdn} = {
|
||||
proxyBuffering = false;
|
||||
locations."/" = {
|
||||
proxyPort = cfg.port;
|
||||
extraConfig = ''
|
||||
client_max_body_size 0;
|
||||
proxy_send_timeout 300;
|
||||
proxy_read_timeout 300;
|
||||
send_timeout 300;
|
||||
'';
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
99
modules/services/invidious-companion.nix
Normal file
99
modules/services/invidious-companion.nix
Normal file
@@ -0,0 +1,99 @@
|
||||
{
|
||||
config,
|
||||
lib,
|
||||
pkgs,
|
||||
...
|
||||
}:
|
||||
let
|
||||
cfg = config.services.invidious-companion;
|
||||
companionRelease = "release-master";
|
||||
hostPlatform = pkgs.stdenv.hostPlatform.system;
|
||||
|
||||
# Invidious Companion package - fetches binary release and patches for NixOS
|
||||
unwrappedCompanion = pkgs.stdenv.mkDerivation {
|
||||
pname = "unwrapped-invidious-companion";
|
||||
version = companionRelease;
|
||||
|
||||
src =
|
||||
let
|
||||
archMap = {
|
||||
x86_64-linux = "x86_64-unknown-linux-gnu";
|
||||
aarch64-linux = "aarch64-unknown-linux-gnu";
|
||||
};
|
||||
platform = archMap.${hostPlatform} or (throw "Unsupported platform: ${hostPlatform}");
|
||||
in
|
||||
pkgs.fetchzip {
|
||||
url = "https://github.com/iv-org/invidious-companion/releases/download/${companionRelease}/invidious_companion-${platform}.tar.gz";
|
||||
sha256 = cfg.binaryHash;
|
||||
};
|
||||
|
||||
dontStrip = true;
|
||||
dontPatchELF = true;
|
||||
|
||||
installPhase = ''
|
||||
mkdir -p $out/bin
|
||||
cp invidious_companion $out/bin/invidious_companion
|
||||
chmod +x $out/bin/invidious_companion
|
||||
'';
|
||||
};
|
||||
|
||||
invidiousCompanion = pkgs.buildFHSEnv {
|
||||
name = "invidious-companion";
|
||||
targetPkgs = pkgs: [ unwrappedCompanion ];
|
||||
runScript = "invidious_companion";
|
||||
meta = {
|
||||
description = "Invidious companion for handling video streams";
|
||||
homepage = "https://github.com/iv-org/invidious-companion";
|
||||
license = lib.licenses.agpl3Only;
|
||||
};
|
||||
};
|
||||
in
|
||||
{
|
||||
options.services.invidious-companion = {
|
||||
enable = lib.mkEnableOption "Enable Invidious Companion service";
|
||||
host = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = "localhost";
|
||||
};
|
||||
port = lib.mkOption {
|
||||
type = lib.types.port;
|
||||
default = 8282;
|
||||
description = "Port for Invidious Companion to listen on";
|
||||
};
|
||||
secretKeyFile = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
description = "Path to file containing the companion secret key";
|
||||
};
|
||||
binaryHash = lib.mkOption {
|
||||
type = lib.types.nullOr lib.types.str;
|
||||
default = null;
|
||||
description = "SHA256 hash of the invidious companion binary release";
|
||||
};
|
||||
};
|
||||
|
||||
config = lib.mkIf cfg.enable {
|
||||
systemd.services.invidious-companion = {
|
||||
description = "Invidious Companion - video stream handler";
|
||||
wantedBy = [ "multi-user.target" ];
|
||||
after = [ "network.target" ];
|
||||
|
||||
serviceConfig = {
|
||||
Type = "simple";
|
||||
User = "invidious";
|
||||
Group = "invidious";
|
||||
DynamicUser = true;
|
||||
ExecStart = lib.getExe invidiousCompanion;
|
||||
Environment = [
|
||||
"HOST=${cfg.host}"
|
||||
"PORT=${toString cfg.port}"
|
||||
"TMPDIR=/var/cache/invidious-companion"
|
||||
];
|
||||
EnvironmentFile = [ cfg.secretKeyFile ];
|
||||
CacheDirectory = "invidious-companion";
|
||||
WorkingDirectory = "%C/invidious-companion";
|
||||
Restart = "always";
|
||||
RestartSec = 5;
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
@@ -1,4 +1,8 @@
|
||||
{ config, lib, ... }:
|
||||
{
|
||||
config,
|
||||
lib,
|
||||
...
|
||||
}:
|
||||
let
|
||||
cfg = config.services.invidious;
|
||||
fqdn = "${cfg.subdomain}.${config.networking.domain}";
|
||||
@@ -11,7 +15,8 @@ in
|
||||
};
|
||||
|
||||
config = lib.mkIf cfg.enable {
|
||||
services.invidious = {
|
||||
services = {
|
||||
invidious = {
|
||||
domain = fqdn;
|
||||
address = "127.0.0.1";
|
||||
|
||||
@@ -24,11 +29,21 @@ in
|
||||
};
|
||||
};
|
||||
|
||||
services.postgresql.enable = lib.mkDefault true;
|
||||
postgresql.enable = lib.mkDefault true;
|
||||
|
||||
services.webserver = {
|
||||
webserver = {
|
||||
enable = lib.mkDefault true;
|
||||
vHosts.${fqdn}.locations."/".proxyPort = cfg.port;
|
||||
};
|
||||
};
|
||||
|
||||
systemd.services.invidious.serviceConfig.DynamicUser = lib.mkForce false;
|
||||
|
||||
users.groups.invidious = { };
|
||||
users.users.invidious = {
|
||||
isSystemUser = true;
|
||||
group = "invidious";
|
||||
description = "Invidious user";
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
37
modules/services/mealie.nix
Normal file
37
modules/services/mealie.nix
Normal file
@@ -0,0 +1,37 @@
|
||||
{ lib, config, ... }:
|
||||
let
|
||||
cfg = config.services.mealie;
|
||||
fqdn = "${cfg.subdomain}.${config.networking.domain}";
|
||||
in
|
||||
{
|
||||
options.services.mealie = {
|
||||
subdomain = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
};
|
||||
};
|
||||
|
||||
config = lib.mkIf cfg.enable {
|
||||
services = {
|
||||
mealie.settings = {
|
||||
BASE_URL = "https://${fqdn}";
|
||||
ALLOW_SIGNUP = true;
|
||||
DB_ENGINE = "postgres";
|
||||
POSTGRES_URL_OVERRIDE = "postgresql://mealie:@mealie?host=/var/run/postgresql";
|
||||
SMTP_FROM_NAME = "Mealie";
|
||||
};
|
||||
|
||||
webserver.vHosts.${fqdn}.locations."/".proxyPort = cfg.port;
|
||||
|
||||
postgresql = {
|
||||
enable = lib.mkDefault true;
|
||||
ensureDatabases = [ "mealie" ];
|
||||
ensureUsers = [
|
||||
{
|
||||
name = "mealie";
|
||||
ensureDBOwnership = true;
|
||||
}
|
||||
];
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
14
modules/services/mosquitto.nix
Normal file
14
modules/services/mosquitto.nix
Normal file
@@ -0,0 +1,14 @@
|
||||
{ config, lib, ... }:
|
||||
let
|
||||
cfg = config.services.mosquitto;
|
||||
in
|
||||
{
|
||||
options = {
|
||||
services.mosquitto = {
|
||||
openFirewall = lib.mkEnableOption "Open firewall port for Mosquitto";
|
||||
};
|
||||
};
|
||||
config = lib.mkIf cfg.enable {
|
||||
networking.firewall.allowedTCPPorts = map ({ port, ... }: port) cfg.listeners;
|
||||
};
|
||||
}
|
||||
64
modules/services/network-status.nix
Normal file
64
modules/services/network-status.nix
Normal file
@@ -0,0 +1,64 @@
|
||||
{
|
||||
lib,
|
||||
config,
|
||||
pkgs,
|
||||
...
|
||||
}:
|
||||
let
|
||||
cfg = config.modules.services.network-status;
|
||||
in
|
||||
{
|
||||
options.modules.services.network-status = {
|
||||
enable = lib.mkEnableOption "Enable network status socket service";
|
||||
|
||||
port = lib.mkOption {
|
||||
type = lib.types.int;
|
||||
default = 8473;
|
||||
description = "TCP port to listen on for network status requests";
|
||||
};
|
||||
|
||||
interface = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = "koti";
|
||||
description = "Network interface to allow access from";
|
||||
};
|
||||
};
|
||||
|
||||
config = lib.mkIf cfg.enable {
|
||||
users.users.network-status = {
|
||||
isSystemUser = true;
|
||||
group = "network-status";
|
||||
description = "Network status socket service user";
|
||||
};
|
||||
|
||||
users.groups.network-status = { };
|
||||
|
||||
systemd.sockets.network-status = {
|
||||
description = "Network Status Socket";
|
||||
wantedBy = [ "sockets.target" ];
|
||||
socketConfig = {
|
||||
ListenStream = cfg.port;
|
||||
Accept = true;
|
||||
};
|
||||
};
|
||||
|
||||
systemd.services."network-status@" = {
|
||||
description = "Network Status Service";
|
||||
serviceConfig = {
|
||||
Type = "simple";
|
||||
User = "network-status";
|
||||
Group = "systemd-network";
|
||||
SupplementaryGroups = [ "systemd-network" ];
|
||||
StandardOutput = "socket";
|
||||
StandardInput = "socket";
|
||||
ExecStart = lib.concatStringsSep " " [
|
||||
(lib.getExe' pkgs.systemd "networkctl")
|
||||
"status"
|
||||
"--json=short"
|
||||
];
|
||||
};
|
||||
};
|
||||
|
||||
modules.firewall.interfaces.${cfg.interface} = lib.mkDefault [ "network-status" ];
|
||||
};
|
||||
}
|
||||
27
modules/services/nqptp.nix
Normal file
27
modules/services/nqptp.nix
Normal file
@@ -0,0 +1,27 @@
|
||||
{
|
||||
lib,
|
||||
pkgs,
|
||||
config,
|
||||
...
|
||||
}:
|
||||
let
|
||||
cfg = config.services.nqptp;
|
||||
in
|
||||
{
|
||||
options.services.nqptp = {
|
||||
enable = lib.mkEnableOption "nqptp service for shairport-sync";
|
||||
};
|
||||
|
||||
config = lib.mkIf cfg.enable {
|
||||
systemd.services.nqptp = {
|
||||
description = "Network Queued PCM Transport Protocol";
|
||||
after = [ "network.target" ];
|
||||
wantedBy = [ "multi-user.target" ];
|
||||
serviceConfig = {
|
||||
Type = "simple";
|
||||
ExecStart = lib.getExe pkgs.nqptp;
|
||||
Restart = "on-failure";
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user