Compare commits
1 Commits
0e664c51f5
...
tech/nativ
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f58c878ef9
|
7
.builds/apu.yml
Normal file
7
.builds/apu.yml
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
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'
|
||||||
7
.builds/freun-dev.yml
Normal file
7
.builds/freun-dev.yml
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
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'
|
||||||
7
.builds/radish.yml
Normal file
7
.builds/radish.yml
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
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'
|
||||||
@@ -1,38 +0,0 @@
|
|||||||
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"
|
|
||||||
@@ -1,18 +0,0 @@
|
|||||||
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,4 +1,2 @@
|
|||||||
/result
|
/result
|
||||||
/.direnv
|
/.direnv
|
||||||
/.gcroots
|
|
||||||
*.qcow2
|
|
||||||
|
|||||||
@@ -1,41 +0,0 @@
|
|||||||
[
|
|
||||||
{
|
|
||||||
"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
23
AGENTS.md
@@ -1,23 +0,0 @@
|
|||||||
# 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
|
# My NixOS Configurations
|
||||||
|
|
||||||
[](https://git.freun.dev/repomaa/nixos/actions?workflow=check.yml) [](https://git.freun.dev/repomaa/nixos/actions?workflow=build-images.yml)
|
[](https://builds.sr.ht/~repomaa?)
|
||||||
|
|||||||
1
custom-pkgs/commander-nvim/default.nix
Normal file
1
custom-pkgs/commander-nvim/default.nix
Normal file
@@ -0,0 +1 @@
|
|||||||
|
{ util, inputs, ... }: util.vimPlugin { name = "commander.nvim"; source = inputs.commander-nvim; }
|
||||||
1
custom-pkgs/crystal/default.nix
Normal file
1
custom-pkgs/crystal/default.nix
Normal file
@@ -0,0 +1 @@
|
|||||||
|
{ util, ... }: util.package { }
|
||||||
16
custom-pkgs/crystal/package.nix
Normal file
16
custom-pkgs/crystal/package.nix
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
{ pkgs, ... }:
|
||||||
|
let
|
||||||
|
inherit (pkgs) crystal libffi;
|
||||||
|
in
|
||||||
|
crystal.overrideAttrs (oldAttrs:
|
||||||
|
{
|
||||||
|
makeFlags = oldAttrs.makeFlags ++ [
|
||||||
|
"interpreter=1"
|
||||||
|
];
|
||||||
|
buildInputs = oldAttrs.buildInputs ++ [
|
||||||
|
libffi
|
||||||
|
];
|
||||||
|
FLAGS = ["--single-module"];
|
||||||
|
doCheck = false;
|
||||||
|
}
|
||||||
|
)
|
||||||
@@ -1,24 +1,9 @@
|
|||||||
{
|
{ lib, inputs, ... }:
|
||||||
lib,
|
|
||||||
inputs,
|
|
||||||
pkgs-unstable,
|
|
||||||
...
|
|
||||||
}:
|
|
||||||
let
|
let
|
||||||
inherit (builtins) attrNames filter readDir;
|
inherit (builtins) attrNames filter readDir;
|
||||||
dirs =
|
dirs =
|
||||||
let
|
let files = readDir ./.;
|
||||||
files = readDir ./.;
|
in filter (name: files."${name}" == "directory") (attrNames files);
|
||||||
in
|
|
||||||
filter (name: files."${name}" == "directory") (attrNames files);
|
|
||||||
util = import ./util.nix;
|
util = import ./util.nix;
|
||||||
in
|
in
|
||||||
lib.composeManyExtensions (
|
lib.composeManyExtensions (map (dir: import ./${dir} { util = util dir; inherit inputs; }) dirs)
|
||||||
map (
|
|
||||||
dir:
|
|
||||||
import ./${dir} {
|
|
||||||
util = util dir;
|
|
||||||
inherit inputs lib pkgs-unstable;
|
|
||||||
}
|
|
||||||
) dirs
|
|
||||||
)
|
|
||||||
|
|||||||
1
custom-pkgs/fb-client/default.nix
Normal file
1
custom-pkgs/fb-client/default.nix
Normal file
@@ -0,0 +1 @@
|
|||||||
|
{ util, ... }: util.package { }
|
||||||
22
custom-pkgs/fb-client/package.nix
Normal file
22
custom-pkgs/fb-client/package.nix
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
{ 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
custom-pkgs/flameshot/default.nix
Normal file
1
custom-pkgs/flameshot/default.nix
Normal file
@@ -0,0 +1 @@
|
|||||||
|
{ util, ... }: util.package { }
|
||||||
6
custom-pkgs/flameshot/package.nix
Normal file
6
custom-pkgs/flameshot/package.nix
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
{ pkgs, ... }:
|
||||||
|
pkgs.writeShellScriptBin "flameshot" ''
|
||||||
|
export XDG_SESSION_TYPE= QT_QPA_PLATFORM=wayland
|
||||||
|
nohup ${pkgs.flameshot}/bin/flameshot >& /dev/null &
|
||||||
|
${pkgs.flameshot}/bin/flameshot "$@"
|
||||||
|
''
|
||||||
1
custom-pkgs/gen-nvim/default.nix
Normal file
1
custom-pkgs/gen-nvim/default.nix
Normal file
@@ -0,0 +1 @@
|
|||||||
|
{ inputs, util, ... }: util.vimPlugin { name = "gen.nvim"; source = inputs.gen-nvim; }
|
||||||
@@ -1,7 +1 @@
|
|||||||
{
|
{ util, inputs, ... }: util.package { inherit inputs; }
|
||||||
util,
|
|
||||||
pkgs-unstable,
|
|
||||||
lib,
|
|
||||||
...
|
|
||||||
}:
|
|
||||||
util.package { inherit pkgs-unstable lib; }
|
|
||||||
|
|||||||
@@ -1,96 +0,0 @@
|
|||||||
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,22 +1,18 @@
|
|||||||
{
|
{ pkgs, inputs }:
|
||||||
pkgs,
|
let
|
||||||
lib,
|
yubikey-manager = inputs.nixpkgs-unstable.legacyPackages.${pkgs.system}.yubikey-manager;
|
||||||
pkgs-unstable,
|
ykman = "${yubikey-manager}/bin/ykman";
|
||||||
}:
|
sk = "${pkgs.skim}/bin/sk";
|
||||||
pkgs.runCommand "otp"
|
wl-copy = "${pkgs.wl-clipboard}/bin/wl-copy";
|
||||||
{
|
in
|
||||||
code = ./otp.cr;
|
pkgs.writeShellScriptBin "otp" ''
|
||||||
env = {
|
skim_command=("${sk}")
|
||||||
YKMAN = lib.getExe pkgs-unstable.yubikey-manager;
|
|
||||||
SKIM = lib.getExe pkgs.skim;
|
if [ -n "$*" ]; then
|
||||||
WALKER = lib.getExe pkgs-unstable.walker;
|
skim_command+=(-q "$*")
|
||||||
WL_COPY = lib.getExe' pkgs.wl-clipboard "wl-copy";
|
fi
|
||||||
NOTIFY_SEND = lib.getExe pkgs.libnotify;
|
|
||||||
NOTIFY_ICON = "${pkgs-unstable.yubioath-flutter}/share/pixmaps/com.yubico.yubioath.png";
|
account=$(${ykman} oath accounts list | "''${skim_command[@]}")
|
||||||
};
|
[ -z "$account" ] && exit 1
|
||||||
nativeBuildInputs = [ pkgs.crystal ];
|
${ykman} oath accounts code -s "$account" | ${wl-copy} -n
|
||||||
}
|
''
|
||||||
''
|
|
||||||
mkdir -p $out/bin
|
|
||||||
crystal build $code --release -o $out/bin/otp
|
|
||||||
''
|
|
||||||
|
|||||||
@@ -1,5 +1,16 @@
|
|||||||
dir: {
|
dir:
|
||||||
package = attrs: final: prev: {
|
{
|
||||||
"${dir}" = final.callPackage ./${dir}/package.nix (attrs // { pkgs = prev; });
|
vimPlugin = { name, source }:
|
||||||
};
|
final: prev: {
|
||||||
|
vimPlugins = prev.vimPlugins // {
|
||||||
|
"${dir}" = prev.vimUtils.buildVimPlugin {
|
||||||
|
pname = name;
|
||||||
|
version = source.lastModifiedDate;
|
||||||
|
src = source;
|
||||||
|
doCheck = false;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
package = attrs: final: prev: { "${dir}" = final.callPackage ./${dir}/package.nix (attrs // { pkgs = prev; }); };
|
||||||
}
|
}
|
||||||
|
|||||||
1
custom-pkgs/vimpeccable/default.nix
Normal file
1
custom-pkgs/vimpeccable/default.nix
Normal file
@@ -0,0 +1 @@
|
|||||||
|
{ inputs, util, ... }: util.vimPlugin { name = "vimpeccable"; source = inputs.vimpeccable; }
|
||||||
1
custom-pkgs/windline-nvim/default.nix
Normal file
1
custom-pkgs/windline-nvim/default.nix
Normal file
@@ -0,0 +1 @@
|
|||||||
|
{ inputs, util, ... }: util.vimPlugin { name = "windline.nvim"; source = inputs.windline-nvim; }
|
||||||
856
flake.lock
generated
856
flake.lock
generated
File diff suppressed because it is too large
Load Diff
265
flake.nix
265
flake.nix
@@ -2,22 +2,42 @@
|
|||||||
inputs = {
|
inputs = {
|
||||||
flake-parts.url = "github:hercules-ci/flake-parts";
|
flake-parts.url = "github:hercules-ci/flake-parts";
|
||||||
nixpkgs-unstable.url = "github:NixOS/nixpkgs/nixos-unstable";
|
nixpkgs-unstable.url = "github:NixOS/nixpkgs/nixos-unstable";
|
||||||
nixpkgs.url = "github:NixOS/nixpkgs/nixos-25.11";
|
nixpkgs.url = "github:NixOS/nixpkgs/nixos-24.11";
|
||||||
|
nextcloud = {
|
||||||
|
url = "github:onny/nixos-nextcloud-testumgebung";
|
||||||
|
inputs.nixpkgs.follows = "nixpkgs";
|
||||||
|
};
|
||||||
gtrackmap = {
|
gtrackmap = {
|
||||||
url = "github:gtrackmap/gtrackmap";
|
url = "github:gtrackmap/gtrackmap";
|
||||||
inputs.nixpkgs.follows = "nixpkgs";
|
inputs.nixpkgs.follows = "nixpkgs";
|
||||||
};
|
};
|
||||||
lanzaboote = {
|
lanzaboote.url = "github:nix-community/lanzaboote";
|
||||||
url = "github:nix-community/lanzaboote";
|
nixos-hardware.url = "github:NixOS/nixos-hardware/master";
|
||||||
inputs.nixpkgs.follows = "nixpkgs";
|
auto-cpufreq = {
|
||||||
};
|
url = "github:AdnanHodzic/auto-cpufreq";
|
||||||
nixos-hardware = {
|
|
||||||
url = "github:NixOS/nixos-hardware/master";
|
|
||||||
inputs.nixpkgs.follows = "nixpkgs";
|
inputs.nixpkgs.follows = "nixpkgs";
|
||||||
};
|
};
|
||||||
home-manager = {
|
home-manager = {
|
||||||
url = "github:nix-community/home-manager/release-25.11";
|
url = "github:nix-community/home-manager/release-24.11";
|
||||||
inputs.nixpkgs.follows = "nixpkgs";
|
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;
|
||||||
};
|
};
|
||||||
ketchup = {
|
ketchup = {
|
||||||
url = "github:repomaa/ketchup";
|
url = "github:repomaa/ketchup";
|
||||||
@@ -36,208 +56,47 @@
|
|||||||
url = "github:ryantm/agenix";
|
url = "github:ryantm/agenix";
|
||||||
inputs.nixpkgs.follows = "nixpkgs";
|
inputs.nixpkgs.follows = "nixpkgs";
|
||||||
};
|
};
|
||||||
dnote = {
|
|
||||||
url = "github:dnote/dnote";
|
|
||||||
flake = false;
|
|
||||||
};
|
|
||||||
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";
|
|
||||||
};
|
|
||||||
tree_hugger = {
|
|
||||||
url = "git+ssh://git@github.com/everii-Group/tree_hugger";
|
|
||||||
inputs.nixpkgs.follows = "nixpkgs-unstable";
|
|
||||||
};
|
|
||||||
models-dev = {
|
|
||||||
url = "github:anomalyco/models.dev";
|
|
||||||
flake = false;
|
|
||||||
};
|
|
||||||
noctalia = {
|
|
||||||
url = "github:noctalia-dev/noctalia-shell";
|
|
||||||
inputs.nixpkgs.follows = "nixpkgs-unstable";
|
|
||||||
};
|
|
||||||
niri-flake = {
|
|
||||||
url = "github:sodiboo/niri-flake";
|
|
||||||
inputs.nixpkgs.follows = "nixpkgs-unstable";
|
|
||||||
};
|
|
||||||
nix-flatpak.url = "github:gmodena/nix-flatpak/?ref=latest";
|
|
||||||
llm-agents = {
|
|
||||||
url = "github:numtide/llm-agents.nix";
|
|
||||||
inputs.nixpkgs.follows = "nixpkgs-unstable";
|
|
||||||
};
|
|
||||||
};
|
};
|
||||||
outputs =
|
outputs = { flake-parts, agenix, nixpkgs, ... }@inputs:
|
||||||
{
|
|
||||||
flake-parts,
|
|
||||||
agenix,
|
|
||||||
nixpkgs,
|
|
||||||
self,
|
|
||||||
colmena,
|
|
||||||
...
|
|
||||||
}@inputs:
|
|
||||||
flake-parts.lib.mkFlake { inherit inputs; } (
|
flake-parts.lib.mkFlake { inherit inputs; } (
|
||||||
{ withSystem, ... }:
|
|
||||||
let
|
let
|
||||||
ssh.publicKeys = {
|
ssh.publicKeys.yubikey = "ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBLIUkESu5NnBi1M0+ZjYrkp6/rIFuwc3aguspf98jmOydNce6l65cnS3GRzc9oWx4lu11ahi87ZuE+pYV+gaHm4=";
|
||||||
yubikey = "ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBLIUkESu5NnBi1M0+ZjYrkp6/rIFuwc3aguspf98jmOydNce6l65cnS3GRzc9oWx4lu11ahi87ZuE+pYV+gaHm4=";
|
specialArgs = { inherit inputs ssh; };
|
||||||
builder = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIFuQaA6JKCOfsfUBI5tzoiYe3tdpLdPfVzeyByx/149C";
|
inherit (nixpkgs) lib;
|
||||||
};
|
|
||||||
specialArgs = { inherit inputs ssh self; };
|
|
||||||
|
|
||||||
in
|
in
|
||||||
{
|
{
|
||||||
systems = [
|
systems = [ "x86_64-linux" "x86_64-darwin" "aarch64-linux" "aarch64-darwin" ];
|
||||||
"x86_64-linux"
|
perSystem = { pkgs, ... }: {
|
||||||
"x86_64-darwin"
|
devShells.default = pkgs.mkShell {
|
||||||
"aarch64-linux"
|
packages = with pkgs; [
|
||||||
"aarch64-darwin"
|
(writeShellScriptBin "switch" ''
|
||||||
];
|
${nh}/bin/nh os switch .
|
||||||
perSystem =
|
'')
|
||||||
{ pkgs, system, ... }:
|
(writeShellScriptBin "deploy" ''
|
||||||
{
|
${openssh}/bin/ssh -t "$1" nh os switch sourcehut:~repomaa/NixOS -- --option tarball-ttl 0
|
||||||
devShells.default = pkgs.mkShell {
|
'')
|
||||||
packages = with pkgs; [
|
(writeShellScriptBin "evaluate" ''
|
||||||
agenix.packages.${system}.default
|
${nix}/bin/nix build --dry-run ".#nixosConfigurations.$1.config.system.build.toplevel" | ${nix-output-monitor}/bin/nom
|
||||||
colmena.packages.${system}.colmena
|
'')
|
||||||
colmena.packages.${system}.manual
|
agenix.packages.${pkgs.system}.default
|
||||||
(writeShellScriptBin "build" ''
|
];
|
||||||
colmena build --keep-result "$@"
|
};
|
||||||
'')
|
};
|
||||||
(writeShellScriptBin "apply" ''
|
flake.nixosConfigurations = {
|
||||||
colmena apply --keep-result "$@"
|
freun-dev = lib.nixosSystem {
|
||||||
'')
|
inherit specialArgs;
|
||||||
(writeShellScriptBin "apply-local" ''
|
modules = [ ./modules ./hosts/freun.dev ];
|
||||||
nh os switch .
|
|
||||||
'')
|
|
||||||
];
|
|
||||||
};
|
|
||||||
};
|
};
|
||||||
flake = {
|
|
||||||
nixosConfigurations =
|
|
||||||
let
|
|
||||||
mkConfiguration =
|
|
||||||
name:
|
|
||||||
nixpkgs.lib.nixosSystem {
|
|
||||||
inherit specialArgs;
|
|
||||||
modules = [
|
|
||||||
./modules
|
|
||||||
./hosts/${name}
|
|
||||||
];
|
|
||||||
};
|
|
||||||
in
|
|
||||||
{
|
|
||||||
radish = mkConfiguration "radish";
|
|
||||||
freun-dev = mkConfiguration "freun-dev";
|
|
||||||
apu = mkConfiguration "apu";
|
|
||||||
turny = mkConfiguration "turny";
|
|
||||||
};
|
|
||||||
|
|
||||||
images.turny = self.nixosConfigurations.turny.config.system.build.sdImage;
|
radish = lib.nixosSystem {
|
||||||
|
inherit specialArgs;
|
||||||
|
modules = [ ./modules ./hosts/radish ];
|
||||||
|
};
|
||||||
|
|
||||||
dockerImages =
|
apu = nixpkgs.lib.nixosSystem {
|
||||||
nixpkgs.lib.genAttrs
|
inherit specialArgs;
|
||||||
[
|
modules = [ ./modules ./hosts/apu ];
|
||||||
"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;
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|||||||
2
home/Makefile
Normal file
2
home/Makefile
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
switch:
|
||||||
|
home-manager switch
|
||||||
File diff suppressed because it is too large
Load Diff
@@ -1,44 +0,0 @@
|
|||||||
{
|
|
||||||
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)
|
|
||||||
'';
|
|
||||||
};
|
|
||||||
}
|
|
||||||
433
home/common/neovim/default.nix
Normal file
433
home/common/neovim/default.nix
Normal file
@@ -0,0 +1,433 @@
|
|||||||
|
{ 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 })
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
}
|
||||||
46
home/common/neovim/formatters.lua
Normal file
46
home/common/neovim/formatters.lua
Normal file
@@ -0,0 +1,46 @@
|
|||||||
|
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()
|
||||||
83
home/common/neovim/luasnippets/typescriptreact.lua
Normal file
83
home/common/neovim/luasnippets/typescriptreact.lua
Normal file
@@ -0,0 +1,83 @@
|
|||||||
|
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,
|
||||||
|
}
|
||||||
|
)
|
||||||
|
),
|
||||||
|
}
|
||||||
33
home/common/neovim/snippets/ruby.snippets
Normal file
33
home/common/neovim/snippets/ruby.snippets
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
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
home/common/neovim/snippets/typescriptreact.snippets
Normal file
1
home/common/neovim/snippets/typescriptreact.snippets
Normal file
@@ -0,0 +1 @@
|
|||||||
|
|
||||||
@@ -1,15 +0,0 @@
|
|||||||
{ lib, ... }:
|
|
||||||
{
|
|
||||||
age.secrets = lib.listToAttrs (
|
|
||||||
map
|
|
||||||
(secret: {
|
|
||||||
name = secret;
|
|
||||||
value = {
|
|
||||||
file = ../../secrets/${secret}.age;
|
|
||||||
};
|
|
||||||
})
|
|
||||||
[
|
|
||||||
"context7"
|
|
||||||
]
|
|
||||||
);
|
|
||||||
}
|
|
||||||
10
home/custom-programs/default.nix
Normal file
10
home/custom-programs/default.nix
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
{ ... }:
|
||||||
|
let
|
||||||
|
inherit (builtins) attrNames filter readDir;
|
||||||
|
dirs =
|
||||||
|
let files = readDir ./.;
|
||||||
|
in filter (name: files."${name}" == "directory") (attrNames files);
|
||||||
|
in
|
||||||
|
{
|
||||||
|
imports = map (dir: ./${dir}) dirs;
|
||||||
|
}
|
||||||
30
home/custom-programs/fb-client/default.nix
Normal file
30
home/custom-programs/fb-client/default.nix
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
{ 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,16 +1,11 @@
|
|||||||
{
|
{ inputs, ... }:
|
||||||
inputs,
|
|
||||||
pkgs-unstable,
|
|
||||||
self,
|
|
||||||
...
|
|
||||||
}:
|
|
||||||
{
|
{
|
||||||
home-manager = {
|
home-manager = {
|
||||||
users = {
|
users = {
|
||||||
jokke = import ./jokke;
|
jokke = import ./jokke;
|
||||||
moco = import ./moco;
|
moco = import ./moco;
|
||||||
};
|
};
|
||||||
extraSpecialArgs = { inherit inputs self pkgs-unstable; };
|
extraSpecialArgs = { inherit inputs; };
|
||||||
sharedModules = [ (import ./common) ];
|
sharedModules = [ (import ./common) ];
|
||||||
useUserPackages = true;
|
useUserPackages = true;
|
||||||
useGlobalPkgs = true;
|
useGlobalPkgs = true;
|
||||||
|
|||||||
@@ -1,9 +1,4 @@
|
|||||||
{
|
{ config, lib, osConfig, ... }:
|
||||||
config,
|
|
||||||
lib,
|
|
||||||
osConfig,
|
|
||||||
...
|
|
||||||
}:
|
|
||||||
let
|
let
|
||||||
cfg = config.gnome;
|
cfg = config.gnome;
|
||||||
in
|
in
|
||||||
@@ -43,12 +38,7 @@ in
|
|||||||
};
|
};
|
||||||
power = {
|
power = {
|
||||||
powerButton = lib.mkOption {
|
powerButton = lib.mkOption {
|
||||||
type = enum [
|
type = enum [ "suspend" "interactive" "hibernate" "nothing" ];
|
||||||
"suspend"
|
|
||||||
"interactive"
|
|
||||||
"hibernate"
|
|
||||||
"nothing"
|
|
||||||
];
|
|
||||||
default = "interactive";
|
default = "interactive";
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
@@ -85,66 +75,56 @@ in
|
|||||||
};
|
};
|
||||||
|
|
||||||
config = {
|
config = {
|
||||||
dconf.settings =
|
dconf.settings = with lib.hm.gvariant; {
|
||||||
with lib.hm.gvariant;
|
"org/gnome/shell/keybindings" = cfg.keybindings.builtin;
|
||||||
{
|
"org/gnome/settings-daemon/plugins/media-keys" = {
|
||||||
"org/gnome/shell/keybindings" = cfg.keybindings.builtin;
|
custom-keybindings = (
|
||||||
"org/gnome/settings-daemon/plugins/media-keys" = {
|
lib.lists.imap0
|
||||||
custom-keybindings = (
|
(i: _: "/org/gnome/settings-daemon/plugins/media-keys/custom-keybindings/custom${toString i}/")
|
||||||
lib.lists.imap0 (
|
cfg.keybindings.custom
|
||||||
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;
|
||||||
"org/gnome/desktop/input-sources" = {
|
};
|
||||||
sources = map (
|
"org/gnome/mutter" = {
|
||||||
source:
|
experimental-features = [ "scale-monitor-framebuffer" ];
|
||||||
mkTuple [
|
};
|
||||||
"xkb"
|
"org/gnome/settings-daemon/plugins/xsettings" = {
|
||||||
source
|
overrides = [ (mkTuple [ "GdkWindowScalingFactor" cfg.scalingFactor ]) ];
|
||||||
]
|
};
|
||||||
) cfg.keyboard.sources;
|
"org/gnome/desktop/interface" = {
|
||||||
};
|
scaling-factor = cfg.scalingFactor;
|
||||||
"org/gnome/mutter" = {
|
};
|
||||||
experimental-features = [ "scale-monitor-framebuffer" ];
|
"org/gnome/settings-daemon/plugins/power" = {
|
||||||
};
|
"power-button-action" = cfg.power.powerButton;
|
||||||
"org/gnome/settings-daemon/plugins/xsettings" = {
|
};
|
||||||
overrides = [
|
"org/gnome/settings-daemon/plugins/color" = with cfg.nightLight; {
|
||||||
(mkTuple [
|
night-light-enabled = enable;
|
||||||
"GdkWindowScalingFactor"
|
night-light-temperature = temperature;
|
||||||
cfg.scalingFactor
|
night-light-schedule-automatic = isNull schedule;
|
||||||
])
|
night-light-schedule-from = lib.mkIf (!isNull schedule) schedule.from;
|
||||||
];
|
night-light-schedule-to = lib.mkIf (!isNull schedule) schedule.to;
|
||||||
};
|
};
|
||||||
"org/gnome/desktop/interface" = {
|
"org/gnome/desktop/calendar" = {
|
||||||
scaling-factor = cfg.scalingFactor;
|
show-weekdate = cfg.calendar.showWeekNumbers;
|
||||||
};
|
};
|
||||||
"org/gnome/settings-daemon/plugins/power" = {
|
"org/gnome/desktop/datetime" = {
|
||||||
"power-button-action" = cfg.power.powerButton;
|
automatic-timezone = cfg.automaticTimeZone;
|
||||||
};
|
};
|
||||||
"org/gnome/settings-daemon/plugins/color" = with cfg.nightLight; {
|
"system/locale" = {
|
||||||
night-light-enabled = enable;
|
region = cfg.region;
|
||||||
night-light-temperature = temperature;
|
};
|
||||||
night-light-schedule-automatic = isNull schedule;
|
} // (
|
||||||
night-light-schedule-from = lib.mkIf (!isNull schedule) schedule.from;
|
builtins.listToAttrs (
|
||||||
night-light-schedule-to = lib.mkIf (!isNull schedule) schedule.to;
|
lib.lists.imap0
|
||||||
};
|
(i: keybinding: {
|
||||||
"org/gnome/desktop/calendar" = {
|
name = "org/gnome/settings-daemon/plugins/media-keys/custom-keybindings/custom${toString i}";
|
||||||
show-weekdate = cfg.calendar.showWeekNumbers;
|
value = keybinding;
|
||||||
};
|
})
|
||||||
"org/gnome/desktop/datetime" = {
|
cfg.keybindings.custom
|
||||||
automatic-timezone = cfg.automaticTimeZone;
|
)
|
||||||
};
|
);
|
||||||
"system/locale" = {
|
|
||||||
region = cfg.region;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
// (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
|
|
||||||
));
|
|
||||||
home.file.".face".source = lib.mkIf (!isNull cfg.profilePicture) cfg.profilePicture;
|
home.file.".face".source = lib.mkIf (!isNull cfg.profilePicture) cfg.profilePicture;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,11 +2,9 @@
|
|||||||
let
|
let
|
||||||
inherit (builtins) attrNames filter readDir;
|
inherit (builtins) attrNames filter readDir;
|
||||||
dirs =
|
dirs =
|
||||||
let
|
let files = readDir ./.;
|
||||||
files = readDir ./.;
|
in filter (name: files."${name}" == "directory") (attrNames files);
|
||||||
in
|
|
||||||
filter (name: files."${name}" == "directory") (attrNames files);
|
|
||||||
in
|
in
|
||||||
{
|
{
|
||||||
imports = map (dir: ./${dir}) dirs;
|
imports = map (dir: ./${dir}) dirs;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,9 +1,4 @@
|
|||||||
{
|
{ config, pkgs, lib, ... }:
|
||||||
config,
|
|
||||||
pkgs,
|
|
||||||
lib,
|
|
||||||
...
|
|
||||||
}:
|
|
||||||
let
|
let
|
||||||
cfg = config.gnome.extensions.freon;
|
cfg = config.gnome.extensions.freon;
|
||||||
in
|
in
|
||||||
|
|||||||
@@ -1,9 +1,4 @@
|
|||||||
{
|
{ config, pkgs, lib, ... }:
|
||||||
config,
|
|
||||||
pkgs,
|
|
||||||
lib,
|
|
||||||
...
|
|
||||||
}:
|
|
||||||
let
|
let
|
||||||
cfg = config.gnome.extensions;
|
cfg = config.gnome.extensions;
|
||||||
in
|
in
|
||||||
@@ -15,52 +10,18 @@ in
|
|||||||
type = package;
|
type = package;
|
||||||
default = pkgs.gnomeExtensions.paperwm;
|
default = pkgs.gnomeExtensions.paperwm;
|
||||||
};
|
};
|
||||||
cycle-height-steps = lib.mkOption {
|
cycle-height-steps = lib.mkOption { type = listOf numbers.nonnegative; default = [ 0.33 0.5 0.67 1.0 ]; };
|
||||||
type = listOf numbers.nonnegative;
|
cycle-width-steps = lib.mkOption { type = listOf numbers.nonnegative; default = [ 0.33 0.5 0.67 1.0 ]; };
|
||||||
default = [
|
horizontal-margin = lib.mkOption { type = ints.unsigned; default = 5; };
|
||||||
0.33
|
vertical-margin = lib.mkOption { type = ints.unsigned; default = 5; };
|
||||||
0.5
|
window-gap = lib.mkOption { type = ints.unsigned; default = 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 {
|
winprops = lib.mkOption {
|
||||||
type = listOf (submodule {
|
type = listOf (submodule {
|
||||||
options = {
|
options = {
|
||||||
wm_class = lib.mkOption {
|
wm_class = lib.mkOption { type = str; default = ""; };
|
||||||
type = str;
|
title = lib.mkOption { type = str; default = ""; };
|
||||||
default = "";
|
|
||||||
};
|
|
||||||
title = lib.mkOption {
|
|
||||||
type = str;
|
|
||||||
default = "";
|
|
||||||
};
|
|
||||||
scratch_layer = lib.mkEnableOption { };
|
scratch_layer = lib.mkEnableOption { };
|
||||||
preferredWidth = lib.mkOption {
|
preferredWidth = lib.mkOption { type = nullOr str; default = null; };
|
||||||
type = nullOr str;
|
|
||||||
default = null;
|
|
||||||
};
|
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
default = [ ];
|
default = [ ];
|
||||||
@@ -75,23 +36,13 @@ in
|
|||||||
config = lib.mkIf cfg.paperwm.enable {
|
config = lib.mkIf cfg.paperwm.enable {
|
||||||
home.packages = [ cfg.paperwm.package ];
|
home.packages = [ cfg.paperwm.package ];
|
||||||
dconf.settings = {
|
dconf.settings = {
|
||||||
"org/gnome/shell".enabled-extensions = lib.mkIf cfg.paperwm.enable [
|
"org/gnome/shell".enabled-extensions =
|
||||||
cfg.paperwm.package.extensionUuid
|
lib.mkIf cfg.paperwm.enable [ cfg.paperwm.package.extensionUuid ];
|
||||||
];
|
"org/gnome/shell/extensions/paperwm" = with cfg.paperwm; lib.mkIf cfg.paperwm.enable {
|
||||||
"org/gnome/shell/extensions/paperwm" =
|
inherit cycle-height-steps cycle-width-steps horizontal-margin vertical-margin window-gap;
|
||||||
with cfg.paperwm;
|
winprops = map (props: builtins.toJSON props) winprops;
|
||||||
lib.mkIf cfg.paperwm.enable {
|
};
|
||||||
inherit
|
"org/gnome/shell/extensions/paperwm/keybindings" = lib.mkIf cfg.paperwm.enable cfg.paperwm.keybindings;
|
||||||
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;
|
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,9 +1,4 @@
|
|||||||
{
|
{ pkgs, inputs, ... }:
|
||||||
pkgs,
|
|
||||||
pkgs-unstable,
|
|
||||||
inputs,
|
|
||||||
...
|
|
||||||
}:
|
|
||||||
{
|
{
|
||||||
config = {
|
config = {
|
||||||
# Home Manager needs a bit of information about you and the paths it should
|
# Home Manager needs a bit of information about you and the paths it should
|
||||||
@@ -14,6 +9,7 @@
|
|||||||
ffmpeg
|
ffmpeg
|
||||||
mediainfo
|
mediainfo
|
||||||
git-lfs
|
git-lfs
|
||||||
|
telegram-desktop
|
||||||
shards
|
shards
|
||||||
deno
|
deno
|
||||||
virt-manager
|
virt-manager
|
||||||
@@ -22,19 +18,67 @@
|
|||||||
inkscape
|
inkscape
|
||||||
wineWowPackages.waylandFull
|
wineWowPackages.waylandFull
|
||||||
reaper
|
reaper
|
||||||
inputs.ksoloti-pr.legacyPackages.${pkgs.stdenv.hostPlatform.system}.ksoloti
|
inputs.ksoloti-pr.legacyPackages.${pkgs.system}.ksoloti
|
||||||
calibre
|
calibre
|
||||||
jellyfin-media-player
|
jellyfin-media-player
|
||||||
darktable
|
darktable
|
||||||
|
openscad
|
||||||
shutter
|
shutter
|
||||||
git-annex
|
|
||||||
hledger
|
|
||||||
hledger-ui
|
|
||||||
hledger-iadd
|
|
||||||
];
|
];
|
||||||
|
|
||||||
gnome.profilePicture = ../assets/profile-pictures/jokke.png;
|
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 = {
|
programs.ssh.matchBlocks = {
|
||||||
"alderaan" = {
|
"alderaan" = {
|
||||||
hostname = "alderaan.space";
|
hostname = "alderaan.space";
|
||||||
@@ -49,7 +93,7 @@
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
programs.git.settings.user.email = "joakim@repomaa.com";
|
programs.git.extraConfig.user.email = "joakim@repomaa.com";
|
||||||
services.syncthing = {
|
services.syncthing = {
|
||||||
enable = true;
|
enable = true;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,18 +1,6 @@
|
|||||||
{
|
{ pkgs, ... }:
|
||||||
pkgs,
|
|
||||||
pkgs-unstable,
|
|
||||||
lib,
|
|
||||||
...
|
|
||||||
}:
|
|
||||||
let
|
let
|
||||||
homeDirectory = "/home/moco";
|
homeDirectory = "/home/moco";
|
||||||
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$'
|
|
||||||
''
|
|
||||||
);
|
|
||||||
in
|
in
|
||||||
{
|
{
|
||||||
# Home Manager needs a bit of information about you and the paths it should
|
# Home Manager needs a bit of information about you and the paths it should
|
||||||
@@ -21,7 +9,6 @@ in
|
|||||||
username = "moco";
|
username = "moco";
|
||||||
inherit homeDirectory;
|
inherit homeDirectory;
|
||||||
packages = with pkgs; [
|
packages = with pkgs; [
|
||||||
chromium
|
|
||||||
(slack.overrideAttrs (oldAttrs: {
|
(slack.overrideAttrs (oldAttrs: {
|
||||||
fixupPhase = ''
|
fixupPhase = ''
|
||||||
sed -i -e 's/,"WebRTCPipeWireCapturer"/,"LebRTCPipeWireCapturer"/' $out/lib/slack/resources/app.asar
|
sed -i -e 's/,"WebRTCPipeWireCapturer"/,"LebRTCPipeWireCapturer"/' $out/lib/slack/resources/app.asar
|
||||||
@@ -33,25 +20,17 @@ in
|
|||||||
--add-flags "--ozone-platform-hint=auto --enable-features=WaylandWindowDecorations,WebRTCPipeWireCapturer"
|
--add-flags "--ozone-platform-hint=auto --enable-features=WaylandWindowDecorations,WebRTCPipeWireCapturer"
|
||||||
'';
|
'';
|
||||||
}))
|
}))
|
||||||
pkgs-unstable.chromedriver
|
|
||||||
kooha
|
kooha
|
||||||
gnome-pomodoro
|
gnome-pomodoro
|
||||||
mitmproxy
|
mitmproxy
|
||||||
(writeShellScriptBin "moco-admin-pw" ''
|
(writeShellScriptBin "moco-admin-pw" ''
|
||||||
password=$(op item get n5h4c237tqnnlr5gruxyqmmggy --reveal --fields label=Kennwort)
|
password=$(op item get fkj74ou6jfex7a6gcinac6o5oe --reveal --fields label=Kennwort)
|
||||||
otp=$(ykman oath accounts code -s 'MOCO:Admin')
|
otp=$(ykman oath accounts code -s 'MOCO:Admin')
|
||||||
echo "''${password}''${otp}" | wl-copy -n
|
echo "''${password}''${otp}" | wl-copy -n
|
||||||
'')
|
'')
|
||||||
(writeShellScriptBin "moco-reto-otp" ''
|
(writeShellScriptBin "moco-reto-otp" ''
|
||||||
ykman oath accounts code -s 'MOCO Reto' | wl-copy -n
|
ykman oath accounts code -s 'MOCO Reto' | wl-copy -n
|
||||||
'')
|
'')
|
||||||
(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
|
|
||||||
'')
|
|
||||||
];
|
];
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -59,10 +38,7 @@ in
|
|||||||
profilePicture = ../assets/profile-pictures/moco.png;
|
profilePicture = ../assets/profile-pictures/moco.png;
|
||||||
calendar.showWeekNumbers = true;
|
calendar.showWeekNumbers = true;
|
||||||
extensions.paperwm.winprops = [
|
extensions.paperwm.winprops = [
|
||||||
{
|
{ wm_class = "gnome-pomodoro"; scratch_layer = true; }
|
||||||
wm_class = "gnome-pomodoro";
|
|
||||||
scratch_layer = true;
|
|
||||||
}
|
|
||||||
];
|
];
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -89,25 +65,58 @@ in
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
programs.git.settings.user.email = "joakim.repomaa@mocoapp.com";
|
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.ssh.matchBlocks =
|
programs.ssh.matchBlocks =
|
||||||
let
|
let
|
||||||
aliases = [
|
aliases = [ "moco" "mocoapp" "mocoapp.com" ];
|
||||||
"moco"
|
matcher = subdomains:
|
||||||
"mocoapp"
|
|
||||||
"mocoapp.com"
|
|
||||||
];
|
|
||||||
matcher =
|
|
||||||
subdomains:
|
|
||||||
builtins.concatStringsSep " " (
|
builtins.concatStringsSep " " (
|
||||||
map (
|
map
|
||||||
alias:
|
(alias: builtins.concatStringsSep " " (
|
||||||
builtins.concatStringsSep " " (
|
|
||||||
map (subdomain: "*.${subdomain}.${alias} ${subdomain}.${alias}") subdomains
|
map (subdomain: "*.${subdomain}.${alias} ${subdomain}.${alias}") subdomains
|
||||||
)
|
))
|
||||||
) aliases
|
aliases);
|
||||||
);
|
|
||||||
in
|
in
|
||||||
{
|
{
|
||||||
"console.*.moco" = {
|
"console.*.moco" = {
|
||||||
@@ -117,97 +126,69 @@ in
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
"${matcher [
|
"${matcher ["reto" "reto.intern"]}" = {
|
||||||
"reto"
|
hostname = "reto.intern.mocoapp.com";
|
||||||
"reto.intern"
|
user = "jokke";
|
||||||
]}" =
|
};
|
||||||
{
|
|
||||||
hostname = "reto.intern.mocoapp.com";
|
|
||||||
user = "jokke";
|
|
||||||
};
|
|
||||||
|
|
||||||
"${matcher [ "web" ]}" = {
|
"${matcher ["web"]}" = {
|
||||||
hostname = "mocoapp.com";
|
hostname = "mocoapp.com";
|
||||||
};
|
};
|
||||||
"${matcher [ "prod-inc" ]}" = {
|
"${matcher ["prod-inc"]}" = {
|
||||||
hostname = "prod-inc.mocoapp.com";
|
hostname = "prod-inc.mocoapp.com";
|
||||||
};
|
};
|
||||||
"${matcher [ "prod" ]}" = {
|
"${matcher ["prod"]}" = {
|
||||||
hostname = "web02.mocoapp";
|
hostname = "web02.mocoapp";
|
||||||
};
|
};
|
||||||
"${matcher [
|
"${matcher ["pfg" "primeforcegroup"]}" = {
|
||||||
"pfg"
|
hostname = "primeforcegroup.mocoapp.com";
|
||||||
"primeforcegroup"
|
};
|
||||||
]}" =
|
"${matcher ["crafft"]}" = {
|
||||||
{
|
|
||||||
hostname = "primeforcegroup.mocoapp.com";
|
|
||||||
};
|
|
||||||
"${matcher [ "crafft" ]}" = {
|
|
||||||
hostname = "crafft.mocoapp.com";
|
hostname = "crafft.mocoapp.com";
|
||||||
};
|
};
|
||||||
"${matcher [
|
"${matcher ["bd" "businessdecision"]}" = {
|
||||||
"bd"
|
hostname = "businessdecision.mocoapp.com";
|
||||||
"businessdecision"
|
};
|
||||||
]}" =
|
"${matcher ["festland"]}" = {
|
||||||
{
|
|
||||||
hostname = "businessdecision.mocoapp.com";
|
|
||||||
};
|
|
||||||
"${matcher [ "festland" ]}" = {
|
|
||||||
hostname = "festland.mocoapp.com";
|
hostname = "festland.mocoapp.com";
|
||||||
};
|
};
|
||||||
"${matcher [
|
"${matcher ["oi" "one-inside"]}" = {
|
||||||
"oi"
|
hostname = "one-inside.mocoapp.com";
|
||||||
"one-inside"
|
};
|
||||||
]}" =
|
"${matcher ["se" "scope-engineering"]}" = {
|
||||||
{
|
hostname = "scope-engineering.mocoapp.com";
|
||||||
hostname = "one-inside.mocoapp.com";
|
};
|
||||||
};
|
"${matcher ["cpc" "cpc-ag"]}" = {
|
||||||
"${matcher [
|
hostname = "cpc-ag.mocoapp.com";
|
||||||
"se"
|
};
|
||||||
"scope-engineering"
|
"${matcher ["weareact3"]}" = {
|
||||||
]}" =
|
|
||||||
{
|
|
||||||
hostname = "scope-engineering.mocoapp.com";
|
|
||||||
};
|
|
||||||
"${matcher [
|
|
||||||
"cpc"
|
|
||||||
"cpc-ag"
|
|
||||||
]}" =
|
|
||||||
{
|
|
||||||
hostname = "cpc-ag.mocoapp.com";
|
|
||||||
};
|
|
||||||
"${matcher [ "weareact3" ]}" = {
|
|
||||||
hostname = "weareact3.mocoapp.com";
|
hostname = "weareact3.mocoapp.com";
|
||||||
};
|
};
|
||||||
"${matcher [ "avenit" ]}" = {
|
"${matcher ["avenit"]}" = {
|
||||||
hostname = "avenit.mocoapp.com";
|
hostname = "avenit.mocoapp.com";
|
||||||
};
|
};
|
||||||
"${matcher [ "staging" ]}" = {
|
"${matcher ["staging"]}" = {
|
||||||
hostname = "staging.mocoapp.com";
|
hostname = "staging.mocoapp.com";
|
||||||
};
|
};
|
||||||
"${matcher [ "staging-v2" ]}" = {
|
"${matcher ["staging-v2"]}" = {
|
||||||
hostname = "staging-v2.mocoapp.com";
|
hostname = "staging-v2.mocoapp.com";
|
||||||
};
|
};
|
||||||
"${matcher [ "staging-v3" ]}" = {
|
"${matcher ["staging-v3"]}" = {
|
||||||
hostname = "staging-v3.mocoapp.com";
|
hostname = "staging-v3.mocoapp.com";
|
||||||
};
|
};
|
||||||
"${matcher [ "staging-v4" ]}" = {
|
"${matcher ["staging-v4"]}" = {
|
||||||
hostname = "staging-v4.mocoapp.com";
|
hostname = "staging-v4.mocoapp.com";
|
||||||
};
|
};
|
||||||
"${matcher [ "staging-v5" ]}" = {
|
"${matcher ["staging-v5"]}" = {
|
||||||
hostname = "staging-v5.mocoapp.com";
|
hostname = "staging-v5.mocoapp.com";
|
||||||
};
|
};
|
||||||
"${matcher [ "staging-v6" ]}" = {
|
"${matcher ["staging-v6"]}" = {
|
||||||
hostname = "staging-v6.mocoapp.com";
|
hostname = "staging-v6.mocoapp.com";
|
||||||
};
|
};
|
||||||
"${matcher [
|
"${matcher ["prod-db" "production-db"]}" = {
|
||||||
"prod-db"
|
hostname = "production-db.mocoapp";
|
||||||
"production-db"
|
};
|
||||||
]}" =
|
"${matcher ["pdf-renderer"]}" = {
|
||||||
{
|
|
||||||
hostname = "production-db.mocoapp";
|
|
||||||
};
|
|
||||||
"${matcher [ "pdf-renderer" ]}" = {
|
|
||||||
hostname = "mocoapp-pdf-renderer01.mocoapp.com";
|
hostname = "mocoapp-pdf-renderer01.mocoapp.com";
|
||||||
};
|
};
|
||||||
"*.moco *.mocoapp *.mocoapp.com" = {
|
"*.moco *.mocoapp *.mocoapp.com" = {
|
||||||
|
|||||||
@@ -1,43 +0,0 @@
|
|||||||
{
|
|
||||||
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" ];
|
|
||||||
};
|
|
||||||
};
|
|
||||||
}
|
|
||||||
392
home/modules/neovim/default.nix
Normal file
392
home/modules/neovim/default.nix
Normal file
@@ -0,0 +1,392 @@
|
|||||||
|
{ 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";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
||||||
89
home/modules/neovim/lsp-config.lua
Normal file
89
home/modules/neovim/lsp-config.lua
Normal file
@@ -0,0 +1,89 @@
|
|||||||
|
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()
|
||||||
@@ -1,100 +0,0 @@
|
|||||||
{
|
|
||||||
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";
|
|
||||||
};
|
|
||||||
|
|
||||||
postProcessingConfig = pkgs.writeText "voxtype-post-processing.json" (
|
|
||||||
builtins.toJSON cfg.postProcessing.settings
|
|
||||||
);
|
|
||||||
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".source = postProcessingConfig;
|
|
||||||
programs.voxtype.settings.output.post_process = {
|
|
||||||
command = lib.getExe postProcess;
|
|
||||||
timeout_ms = 5 * 60 * 1000; # 5 minutes
|
|
||||||
};
|
|
||||||
|
|
||||||
systemd.user.services.voxtype.Service.X-Reload-If-Changed = [
|
|
||||||
postProcess
|
|
||||||
];
|
|
||||||
};
|
|
||||||
}
|
|
||||||
@@ -1,54 +0,0 @@
|
|||||||
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
|
|
||||||
@@ -1,374 +0,0 @@
|
|||||||
{
|
|
||||||
config,
|
|
||||||
lib,
|
|
||||||
pkgs,
|
|
||||||
pkgs-unstable,
|
|
||||||
inputs,
|
|
||||||
...
|
|
||||||
}:
|
|
||||||
let
|
|
||||||
cfg = config.programs.zed-editor;
|
|
||||||
models-dev = inputs.models-dev;
|
|
||||||
|
|
||||||
getModelsFromProvider =
|
|
||||||
provider:
|
|
||||||
let
|
|
||||||
providerPath = "${models-dev}/providers/${provider}";
|
|
||||||
modelsPath = "${providerPath}/models";
|
|
||||||
providerToml = builtins.fromTOML (builtins.readFile "${providerPath}/provider.toml");
|
|
||||||
|
|
||||||
findAllTomlFiles =
|
|
||||||
path:
|
|
||||||
let
|
|
||||||
entries = builtins.readDir path;
|
|
||||||
files = builtins.filter (name: builtins.match ".*\\.toml$" name != null) (
|
|
||||||
builtins.attrNames (lib.filterAttrs (_: type: type == "regular") entries)
|
|
||||||
);
|
|
||||||
dirs = builtins.attrNames (lib.filterAttrs (_: type: type == "directory") entries);
|
|
||||||
nestedFiles = builtins.concatMap (
|
|
||||||
dir:
|
|
||||||
let
|
|
||||||
nestedPath = "${path}/${dir}";
|
|
||||||
nestedTomlFiles = findAllTomlFiles nestedPath;
|
|
||||||
in
|
|
||||||
map (file: "${dir}/${file}") nestedTomlFiles
|
|
||||||
) dirs;
|
|
||||||
in
|
|
||||||
files ++ nestedFiles;
|
|
||||||
|
|
||||||
modelFiles = findAllTomlFiles modelsPath;
|
|
||||||
modelEntries = map (
|
|
||||||
file:
|
|
||||||
let
|
|
||||||
filePath = "${modelsPath}/${file}";
|
|
||||||
parsed = builtins.fromTOML (builtins.readFile filePath);
|
|
||||||
modelName = builtins.substring 0 (builtins.stringLength file - 5) file;
|
|
||||||
in
|
|
||||||
{
|
|
||||||
name = modelName;
|
|
||||||
display_name = parsed.name or modelName;
|
|
||||||
max_tokens = parsed.limit.context or parsed.limit.output or 128000;
|
|
||||||
}
|
|
||||||
) modelFiles;
|
|
||||||
in
|
|
||||||
{
|
|
||||||
api_url = providerToml.api;
|
|
||||||
available_models = builtins.sort (a: b: a.name < b.name) modelEntries;
|
|
||||||
name = providerToml.name;
|
|
||||||
};
|
|
||||||
|
|
||||||
opencodeProviders = map getModelsFromProvider [
|
|
||||||
"opencode"
|
|
||||||
"opencode-go"
|
|
||||||
"fireworks-ai"
|
|
||||||
"firepass"
|
|
||||||
];
|
|
||||||
|
|
||||||
openaiCompatibleProviders = builtins.listToAttrs (
|
|
||||||
map (p: lib.nameValuePair p.name p) opencodeProviders
|
|
||||||
);
|
|
||||||
|
|
||||||
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 = "opencode-go";
|
|
||||||
model = "glm-5";
|
|
||||||
};
|
|
||||||
};
|
|
||||||
agent_servers = {
|
|
||||||
OpenCode = {
|
|
||||||
command = "opencode";
|
|
||||||
args = [ "acp" ];
|
|
||||||
type = "custom";
|
|
||||||
};
|
|
||||||
};
|
|
||||||
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"
|
|
||||||
"-"
|
|
||||||
];
|
|
||||||
};
|
|
||||||
};
|
|
||||||
TypeScript.language_servers = [
|
|
||||||
"tsgo"
|
|
||||||
"vtsls"
|
|
||||||
];
|
|
||||||
};
|
|
||||||
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 = {
|
|
||||||
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_compatible = openaiCompatibleProviders;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
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 = "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,13 +2,7 @@
|
|||||||
# your system. Help is availanodev";
|
# your system. Help is availanodev";
|
||||||
# https://search.nixos.org/options and in the NixOS manual (`nixos-help`).
|
# 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.enable = true;
|
||||||
boot.loader.grub.device = "/dev/sda";
|
boot.loader.grub.device = "/dev/sda";
|
||||||
@@ -18,10 +12,7 @@
|
|||||||
|
|
||||||
nix = {
|
nix = {
|
||||||
settings = {
|
settings = {
|
||||||
experimental-features = [
|
experimental-features = [ "nix-command" "flakes" ];
|
||||||
"nix-command"
|
|
||||||
"flakes"
|
|
||||||
];
|
|
||||||
auto-optimise-store = true;
|
auto-optimise-store = true;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -72,28 +63,11 @@
|
|||||||
modules.firewall = {
|
modules.firewall = {
|
||||||
enable = true;
|
enable = true;
|
||||||
interfaces = {
|
interfaces = {
|
||||||
koti = [
|
koti = [ "dhcp" "dns" "ssh" "web" ];
|
||||||
"dhcp"
|
gast = [ "dhcp" "dns" ];
|
||||||
"dns"
|
iot = [ "dhcp" "dns" ];
|
||||||
"ssh"
|
cfg = [ "dhcp" "dns" ];
|
||||||
"web"
|
"tailscale*" = [ "ssh" "web" ];
|
||||||
];
|
|
||||||
gast = [
|
|
||||||
"dhcp"
|
|
||||||
"dns"
|
|
||||||
];
|
|
||||||
iot = [
|
|
||||||
"dhcp"
|
|
||||||
"dns"
|
|
||||||
];
|
|
||||||
cfg = [
|
|
||||||
"dhcp"
|
|
||||||
"dns"
|
|
||||||
];
|
|
||||||
"tailscale*" = [
|
|
||||||
"ssh"
|
|
||||||
"web"
|
|
||||||
];
|
|
||||||
};
|
};
|
||||||
allInterfaces = [ ];
|
allInterfaces = [ ];
|
||||||
};
|
};
|
||||||
@@ -172,9 +146,7 @@
|
|||||||
onState = [ "routable" ];
|
onState = [ "routable" ];
|
||||||
script = ''
|
script = ''
|
||||||
#!${pkgs.runtimeShell}
|
#!${pkgs.runtimeShell}
|
||||||
${pkgs.ethtool}/bin/ethtool -K ${
|
${pkgs.ethtool}/bin/ethtool -K ${config.systemd.network.links."10-extern0".linkConfig.Name} rx-udp-gro-forwarding on rx-gro-list off
|
||||||
config.systemd.network.links."10-extern0".linkConfig.Name
|
|
||||||
} rx-udp-gro-forwarding on rx-gro-list off
|
|
||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
@@ -211,73 +183,53 @@
|
|||||||
|
|
||||||
services.resolved.enable = false;
|
services.resolved.enable = false;
|
||||||
|
|
||||||
modules.services.dhcp-dns-sync = {
|
services.nextdns = {
|
||||||
enable = true;
|
enable = true;
|
||||||
interface = "koti";
|
arguments = [ "-profile" "9c4ac9" "-setup-router" "-mdns" "koti" ];
|
||||||
domain = "home.arpa";
|
|
||||||
interval = "30s";
|
|
||||||
};
|
};
|
||||||
|
|
||||||
services.unbound = {
|
services.home-assistant = {
|
||||||
enable = true;
|
enable = true;
|
||||||
settings = {
|
extraComponents = [
|
||||||
server = {
|
# Components required to complete the onboarding
|
||||||
interface =
|
"esphome"
|
||||||
(lib.map (name: config.systemd.network.networks."30-${name}".dhcpServerConfig.DNS) (
|
"met"
|
||||||
lib.attrNames config.modules.vlans.networks
|
"radio_browser"
|
||||||
))
|
|
||||||
++ [
|
"yeelight"
|
||||||
"127.0.0.1"
|
"xiaomi_aqara"
|
||||||
"::1"
|
"shelly"
|
||||||
];
|
];
|
||||||
access-control = [
|
extraPackages = python3Packages: with python3Packages; [
|
||||||
"10.0.0.0/8 allow"
|
gtts
|
||||||
"127.0.0.0/8 allow"
|
numpy
|
||||||
"::1/128 allow"
|
];
|
||||||
];
|
config = {
|
||||||
verbosity = 2;
|
homeassistant = {
|
||||||
|
name = "Koti";
|
||||||
|
unit_system = "metric";
|
||||||
|
time_zone = "Europe/Helsinki";
|
||||||
};
|
};
|
||||||
|
http = {
|
||||||
forward-zone = [
|
use_x_forwarded_for = true;
|
||||||
{
|
trusted_proxies = "127.0.0.1";
|
||||||
name = ".";
|
};
|
||||||
forward-addr = "100.84.105.63#dns.freun.dev";
|
default_config = { };
|
||||||
forward-tls-upstream = true;
|
|
||||||
}
|
|
||||||
];
|
|
||||||
|
|
||||||
remote-control.control-enable = true;
|
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
services.avahi = {
|
services.webserver = {
|
||||||
enable = true;
|
enable = true;
|
||||||
nssmdns4 = true;
|
acme.dnsChallenge = true;
|
||||||
reflector = true;
|
vHosts."koti.repomaa.com" = {
|
||||||
allowInterfaces = [ "lan" ];
|
proxyBuffering = false;
|
||||||
openFirewall = true;
|
locations."/".proxyPort = 8123;
|
||||||
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
services.invidious-companion = {
|
networking.nftables.enable = true;
|
||||||
enable = true;
|
networking.firewall.enable = true;
|
||||||
host = "0.0.0.0";
|
networking.useDHCP = false;
|
||||||
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";
|
system.stateVersion = "24.05";
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,7 +6,6 @@ in
|
|||||||
imports = [
|
imports = [
|
||||||
./hardware-configuration.nix
|
./hardware-configuration.nix
|
||||||
./configuration.nix
|
./configuration.nix
|
||||||
./secrets.nix
|
|
||||||
nixos-hardware.nixosModules.pcengines-apu
|
nixos-hardware.nixosModules.pcengines-apu
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,57 +1,41 @@
|
|||||||
# Do not modify this file! It was generated by ‘nixos-generate-config’
|
# Do not modify this file! It was generated by ‘nixos-generate-config’
|
||||||
# and may be overwritten by future invocations. Please make changes
|
# and may be overwritten by future invocations. Please make changes
|
||||||
# to /etc/nixos/configuration.nix instead.
|
# to /etc/nixos/configuration.nix instead.
|
||||||
{
|
{ config, lib, pkgs, modulesPath, ... }:
|
||||||
config,
|
|
||||||
lib,
|
|
||||||
pkgs,
|
|
||||||
modulesPath,
|
|
||||||
...
|
|
||||||
}:
|
|
||||||
|
|
||||||
{
|
{
|
||||||
imports = [
|
imports =
|
||||||
(modulesPath + "/installer/scan/not-detected.nix")
|
[ (modulesPath + "/installer/scan/not-detected.nix")
|
||||||
];
|
];
|
||||||
|
|
||||||
boot.initrd.availableKernelModules = [
|
boot.initrd.availableKernelModules = [ "xhci_pci" "ahci" "ehci_pci" "usb_storage" "sd_mod" "sdhci_pci" ];
|
||||||
"xhci_pci"
|
|
||||||
"ahci"
|
|
||||||
"ehci_pci"
|
|
||||||
"usb_storage"
|
|
||||||
"sd_mod"
|
|
||||||
"sdhci_pci"
|
|
||||||
];
|
|
||||||
boot.initrd.kernelModules = [ ];
|
boot.initrd.kernelModules = [ ];
|
||||||
boot.kernelModules = [ "kvm-amd" ];
|
boot.kernelModules = [ "kvm-amd" ];
|
||||||
boot.extraModulePackages = [ ];
|
boot.extraModulePackages = [ ];
|
||||||
|
|
||||||
fileSystems."/" = {
|
fileSystems."/" =
|
||||||
device = "/dev/disk/by-uuid/f221c6a7-e05e-40dc-bc85-7970d7c8f22b";
|
{ device = "/dev/disk/by-uuid/f221c6a7-e05e-40dc-bc85-7970d7c8f22b";
|
||||||
fsType = "btrfs";
|
fsType = "btrfs";
|
||||||
options = [ "subvol=@" ];
|
options = [ "subvol=@" ];
|
||||||
};
|
};
|
||||||
|
|
||||||
fileSystems."/var/log" = {
|
fileSystems."/var/log" =
|
||||||
device = "/dev/disk/by-uuid/f221c6a7-e05e-40dc-bc85-7970d7c8f22b";
|
{ device = "/dev/disk/by-uuid/f221c6a7-e05e-40dc-bc85-7970d7c8f22b";
|
||||||
fsType = "btrfs";
|
fsType = "btrfs";
|
||||||
options = [ "subvol=@var_log" ];
|
options = [ "subvol=@var_log" ];
|
||||||
};
|
};
|
||||||
|
|
||||||
fileSystems."/boot" = {
|
fileSystems."/boot" =
|
||||||
device = "/dev/disk/by-uuid/14D2-F8F4";
|
{ device = "/dev/disk/by-uuid/14D2-F8F4";
|
||||||
fsType = "vfat";
|
fsType = "vfat";
|
||||||
options = [
|
options = [ "fmask=0022" "dmask=0022" ];
|
||||||
"fmask=0022"
|
};
|
||||||
"dmask=0022"
|
|
||||||
];
|
|
||||||
};
|
|
||||||
|
|
||||||
fileSystems."/swap" = {
|
fileSystems."/swap" =
|
||||||
device = "/dev/disk/by-uuid/f221c6a7-e05e-40dc-bc85-7970d7c8f22b";
|
{ device = "/dev/disk/by-uuid/f221c6a7-e05e-40dc-bc85-7970d7c8f22b";
|
||||||
fsType = "btrfs";
|
fsType = "btrfs";
|
||||||
options = [ "subvol=@swap" ];
|
options = [ "subvol=@swap" ];
|
||||||
};
|
};
|
||||||
|
|
||||||
swapDevices = [ ];
|
swapDevices = [ ];
|
||||||
|
|
||||||
|
|||||||
@@ -1,16 +0,0 @@
|
|||||||
{ lib, ... }:
|
|
||||||
{
|
|
||||||
age.secrets = lib.listToAttrs (
|
|
||||||
map
|
|
||||||
(secret: {
|
|
||||||
name = secret;
|
|
||||||
value = {
|
|
||||||
file = ../../secrets/${secret}.age;
|
|
||||||
};
|
|
||||||
})
|
|
||||||
[
|
|
||||||
"hetzner"
|
|
||||||
"invidious-companion"
|
|
||||||
]
|
|
||||||
);
|
|
||||||
}
|
|
||||||
@@ -1,339 +0,0 @@
|
|||||||
{ 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,62 +0,0 @@
|
|||||||
{ 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"
|
|
||||||
"searx"
|
|
||||||
"open-webui"
|
|
||||||
"open-terminal-api-key"
|
|
||||||
]
|
|
||||||
)
|
|
||||||
// {
|
|
||||||
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;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
}
|
|
||||||
@@ -1,478 +0,0 @@
|
|||||||
{
|
|
||||||
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
|
|
||||||
{
|
|
||||||
nixpkgs.config.allowUnfree = true;
|
|
||||||
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;
|
|
||||||
subdomain = "mqtt";
|
|
||||||
listeners = [
|
|
||||||
{
|
|
||||||
users = {
|
|
||||||
homie = {
|
|
||||||
acl = [
|
|
||||||
"readwrite homie/#"
|
|
||||||
];
|
|
||||||
hashedPasswordFile = secrets."mosquitto/homie".path;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
port = 8084;
|
|
||||||
settings = {
|
|
||||||
protocol = "websockets";
|
|
||||||
cafile = "/run/credentials/mosquitto.service/fullchain.pem";
|
|
||||||
certfile = "/run/credentials/mosquitto.service/fullchain.pem";
|
|
||||||
keyfile = "/run/credentials/mosquitto.service/key.pem";
|
|
||||||
};
|
|
||||||
}
|
|
||||||
{
|
|
||||||
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";
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
searx = {
|
|
||||||
enable = true;
|
|
||||||
subdomain = "q";
|
|
||||||
port = 3400;
|
|
||||||
environmentFile = secrets.searx.path;
|
|
||||||
settings = {
|
|
||||||
general = {
|
|
||||||
instance_name = "freun.dev SearXNG";
|
|
||||||
};
|
|
||||||
server = {
|
|
||||||
public_instance = true;
|
|
||||||
image_proxy = true;
|
|
||||||
method = "GET";
|
|
||||||
secret_key = "$SEARX_SECRET_KEY";
|
|
||||||
};
|
|
||||||
engines = lib.mapAttrsToList (name: value: { inherit name; } // value) {
|
|
||||||
"google".disabled = true;
|
|
||||||
"duckduckgo".disabled = false;
|
|
||||||
"duckduckgo images".disabled = false;
|
|
||||||
"wolframalpha".disabled = false;
|
|
||||||
};
|
|
||||||
search = {
|
|
||||||
formats = [
|
|
||||||
"html"
|
|
||||||
"json"
|
|
||||||
];
|
|
||||||
};
|
|
||||||
enabled_plugins = [
|
|
||||||
"Basic Calculator"
|
|
||||||
"Hash plugin"
|
|
||||||
"Open Access DOI rewrite"
|
|
||||||
"Hostnames plugin"
|
|
||||||
"Unit converter plugin"
|
|
||||||
"Tracker URL remover"
|
|
||||||
];
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
open-webui = {
|
|
||||||
enable = true;
|
|
||||||
port = 3500;
|
|
||||||
environmentFile = secrets.open-webui.path;
|
|
||||||
environment = {
|
|
||||||
ENABLE_WEB_SEARCH = "True";
|
|
||||||
ENABLE_OLLAMA_API = "False";
|
|
||||||
};
|
|
||||||
subdomain = "owu";
|
|
||||||
};
|
|
||||||
|
|
||||||
webserver = {
|
|
||||||
acme.dnsChallenge = true;
|
|
||||||
tailscaleAuth.expectedTailnet = "tempel-vibes.ts.net";
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
virtualisation.oci-containers.containers.open-terminal = {
|
|
||||||
image = "ghcr.io/open-webui/open-terminal:latest";
|
|
||||||
autoStart = true;
|
|
||||||
ports = [ "127.0.0.1:3700:8000" ];
|
|
||||||
environmentFiles = [ config.age.secrets."open-terminal-api-key".path ];
|
|
||||||
environment = {
|
|
||||||
OPEN_TERMINAL_MULTI_USER = "true";
|
|
||||||
};
|
|
||||||
volumes = [
|
|
||||||
"open-terminal-data:/home/user"
|
|
||||||
];
|
|
||||||
};
|
|
||||||
|
|
||||||
virtualisation.docker.autoPrune.enable = true;
|
|
||||||
}
|
|
||||||
@@ -2,87 +2,36 @@
|
|||||||
# your system. Help is available in the configuration.nix(5) man page
|
# your system. Help is available in the configuration.nix(5) man page
|
||||||
# and in the NixOS manual (accessible by running `nixos-help`).
|
# 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 = {
|
nix = {
|
||||||
settings = {
|
settings = {
|
||||||
experimental-features = [
|
experimental-features = [ "nix-command" "flakes" ];
|
||||||
"nix-command"
|
|
||||||
"flakes"
|
|
||||||
];
|
|
||||||
auto-optimise-store = true;
|
auto-optimise-store = true;
|
||||||
};
|
};
|
||||||
gc = {
|
gc = {
|
||||||
automatic = true;
|
automatic = true;
|
||||||
dates = "weekly";
|
dates = "weekly";
|
||||||
options = "--delete-older-than 7d";
|
options = "--delete-older-than 30d";
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
boot.loader.systemd-boot.enable = true;
|
boot.loader.systemd-boot.enable = true;
|
||||||
boot.loader.efi.canTouchEfiVariables = true;
|
boot.loader.efi.canTouchEfiVariables = true;
|
||||||
boot.binfmt.emulatedSystems = [ "x86_64-linux" ];
|
|
||||||
|
|
||||||
networking.hostName = "freun-dev"; # Define your hostname.
|
networking.hostName = "freun-dev"; # Define your hostname.
|
||||||
networking.domain = "freun.dev";
|
networking.domain = "freun.dev";
|
||||||
networking.useDHCP = false;
|
networking.useDHCP = false;
|
||||||
networking.nftables.enable = true;
|
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 = {
|
systemd.network = {
|
||||||
enable = true;
|
enable = true;
|
||||||
networks.static = {
|
networks.static = {
|
||||||
name = "enp1s0";
|
name = "enp1s0";
|
||||||
address = [
|
address = [
|
||||||
"${ipv4Address}/32"
|
"65.21.145.150/32"
|
||||||
"${ipv6Address}/64"
|
"2a01:4f9:c011:9ac1::1/64"
|
||||||
];
|
];
|
||||||
routes = [
|
routes = [
|
||||||
{ Gateway = "fe80::1"; }
|
{ Gateway = "fe80::1"; }
|
||||||
@@ -106,12 +55,6 @@ in
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
services.resolved = {
|
|
||||||
enable = true;
|
|
||||||
dnsovertls = "opportunistic";
|
|
||||||
dnssec = "allow-downgrade";
|
|
||||||
};
|
|
||||||
|
|
||||||
services.networkd-dispatcher = {
|
services.networkd-dispatcher = {
|
||||||
enable = true;
|
enable = true;
|
||||||
rules."50-tailscale" = {
|
rules."50-tailscale" = {
|
||||||
@@ -138,31 +81,21 @@ in
|
|||||||
# useXkbConfig = true; # use xkbOptions in tty.
|
# useXkbConfig = true; # use xkbOptions in tty.
|
||||||
# };
|
# };
|
||||||
|
|
||||||
|
|
||||||
# Configure keymap in X11
|
# Configure keymap in X11
|
||||||
services.xserver.xkb.layout = "us";
|
services.xserver.xkb.layout = "us";
|
||||||
services.xserver.xkb.options = "eurosign:e,caps:escape";
|
services.xserver.xkb.options = "eurosign:e,caps:escape";
|
||||||
|
|
||||||
# Define a user account. Don't forget to set a password with ‘passwd’.
|
# Define a user account. Don't forget to set a password with ‘passwd’.
|
||||||
users.users = {
|
users.users.jokke = {
|
||||||
jokke = {
|
isNormalUser = true;
|
||||||
isNormalUser = true;
|
extraGroups = [ "wheel" ]; # Enable ‘sudo’ for the user.
|
||||||
extraGroups = [ "wheel" ]; # Enable ‘sudo’ for the user.
|
packages = [ pkgs.nh ];
|
||||||
packages = [ pkgs.nh ];
|
openssh.authorizedKeys.keys = [ ssh.publicKeys.yubikey ];
|
||||||
openssh.authorizedKeys.keys = [ ssh.publicKeys.yubikey ];
|
|
||||||
};
|
|
||||||
|
|
||||||
builder = {
|
|
||||||
isNormalUser = true;
|
|
||||||
openssh.authorizedKeys.keys = [ ssh.publicKeys.builder ];
|
|
||||||
};
|
|
||||||
|
|
||||||
root.openssh.authorizedKeys.keys = [ ssh.publicKeys.yubikey ];
|
|
||||||
};
|
};
|
||||||
|
users.users.root.openssh.authorizedKeys.keys = [ ssh.publicKeys.yubikey ];
|
||||||
|
|
||||||
nix.settings.trusted-users = [
|
nix.settings.trusted-users = [ "jokke" ];
|
||||||
"jokke"
|
|
||||||
"builder"
|
|
||||||
];
|
|
||||||
|
|
||||||
# List packages installed in system profile. To search, run:
|
# List packages installed in system profile. To search, run:
|
||||||
# $ nix search wget
|
# $ nix search wget
|
||||||
@@ -1,41 +1,34 @@
|
|||||||
# Do not modify this file! It was generated by ‘nixos-generate-config’
|
# Do not modify this file! It was generated by ‘nixos-generate-config’
|
||||||
# and may be overwritten by future invocations. Please make changes
|
# and may be overwritten by future invocations. Please make changes
|
||||||
# to /etc/nixos/configuration.nix instead.
|
# to /etc/nixos/configuration.nix instead.
|
||||||
{
|
{ config, lib, pkgs, modulesPath, ... }:
|
||||||
lib,
|
|
||||||
modulesPath,
|
|
||||||
...
|
|
||||||
}:
|
|
||||||
|
|
||||||
{
|
{
|
||||||
imports = [
|
imports =
|
||||||
(modulesPath + "/profiles/qemu-guest.nix")
|
[
|
||||||
];
|
(modulesPath + "/profiles/qemu-guest.nix")
|
||||||
|
];
|
||||||
|
|
||||||
boot.initrd.availableKernelModules = [
|
boot.initrd.availableKernelModules = [ "xhci_pci" "virtio_scsi" "sr_mod" ];
|
||||||
"xhci_pci"
|
|
||||||
"virtio_scsi"
|
|
||||||
"sr_mod"
|
|
||||||
];
|
|
||||||
boot.initrd.kernelModules = [ ];
|
boot.initrd.kernelModules = [ ];
|
||||||
boot.kernelModules = [ ];
|
boot.kernelModules = [ ];
|
||||||
boot.extraModulePackages = [ ];
|
boot.extraModulePackages = [ ];
|
||||||
|
|
||||||
fileSystems."/" = {
|
fileSystems."/" =
|
||||||
device = "/dev/disk/by-uuid/f594ffbc-4553-42e4-8206-4d762c94b4c3";
|
{
|
||||||
fsType = "ext4";
|
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";
|
device = "/dev/disk/by-uuid/46F1-18E3";
|
||||||
options = [
|
fsType = "vfat";
|
||||||
"fmask=0077"
|
options = [ "fmask=0077" "dmask=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
|
# 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
|
# (the default) this is the recommended approach. When using systemd-networkd it's
|
||||||
24
hosts/freun.dev/secrets.nix
Normal file
24
hosts/freun.dev/secrets.nix
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
{ 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";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
||||||
144
hosts/freun.dev/services.nix
Normal file
144
hosts/freun.dev/services.nix
Normal file
@@ -0,0 +1,144 @@
|
|||||||
|
{ 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,28 +1,8 @@
|
|||||||
{ ... }:
|
{ ... }:
|
||||||
{
|
{
|
||||||
nix = {
|
nix = {
|
||||||
distributedBuilds = true;
|
|
||||||
buildMachines = [
|
|
||||||
{
|
|
||||||
hostName = "freun.dev";
|
|
||||||
maxJobs = 8;
|
|
||||||
protocol = "ssh";
|
|
||||||
sshUser = "builder";
|
|
||||||
systems = [
|
|
||||||
"aarch64-linux"
|
|
||||||
];
|
|
||||||
supportedFeatures = [
|
|
||||||
"kvm"
|
|
||||||
"big-parallel"
|
|
||||||
"nixos-test"
|
|
||||||
];
|
|
||||||
}
|
|
||||||
];
|
|
||||||
settings = {
|
settings = {
|
||||||
experimental-features = [
|
experimental-features = [ "nix-command" "flakes" ];
|
||||||
"nix-command"
|
|
||||||
"flakes"
|
|
||||||
];
|
|
||||||
auto-optimise-store = true;
|
auto-optimise-store = true;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -33,6 +13,10 @@
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
networking.extraHosts = ''
|
||||||
|
10.10.0.1 warden.apu.repomaa.com
|
||||||
|
'';
|
||||||
|
|
||||||
networking.nftables.enable = true;
|
networking.nftables.enable = true;
|
||||||
|
|
||||||
# This option defines the first version of NixOS you have installed on this particular machine,
|
# This option defines the first version of NixOS you have installed on this particular machine,
|
||||||
|
|||||||
@@ -1,20 +1,8 @@
|
|||||||
{ pkgs-unstable, ... }:
|
{ ... }:
|
||||||
{
|
{
|
||||||
virtualisation = {
|
virtualisation.docker.storageDriver = "btrfs";
|
||||||
containers = {
|
virtualisation.docker.rootless = {
|
||||||
enable = true;
|
enable = true;
|
||||||
storage.settings.storage.driver = "btrfs";
|
setSocketVariable = true;
|
||||||
containersConf.settings.compose_warning_logs = false;
|
|
||||||
};
|
|
||||||
|
|
||||||
oci-containers.backend = "podman";
|
|
||||||
|
|
||||||
podman = {
|
|
||||||
enable = true;
|
|
||||||
autoPrune.enable = true;
|
|
||||||
defaultNetwork.settings.dns_enabled = true;
|
|
||||||
package = pkgs-unstable.podman;
|
|
||||||
dockerCompat = true;
|
|
||||||
};
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,10 +1,6 @@
|
|||||||
{ inputs, ... }:
|
{ inputs, ... }:
|
||||||
let
|
let
|
||||||
inherit (inputs)
|
inherit (inputs) lanzaboote nixos-hardware auto-cpufreq home-manager;
|
||||||
lanzaboote
|
|
||||||
nixos-hardware
|
|
||||||
home-manager
|
|
||||||
;
|
|
||||||
in
|
in
|
||||||
{
|
{
|
||||||
imports = [
|
imports = [
|
||||||
@@ -17,9 +13,9 @@ in
|
|||||||
./containers.nix
|
./containers.nix
|
||||||
./desktop.nix
|
./desktop.nix
|
||||||
./users.nix
|
./users.nix
|
||||||
./secrets.nix
|
|
||||||
lanzaboote.nixosModules.lanzaboote
|
lanzaboote.nixosModules.lanzaboote
|
||||||
nixos-hardware.nixosModules.framework-13-7040-amd
|
nixos-hardware.nixosModules.framework-13-7040-amd
|
||||||
|
auto-cpufreq.nixosModules.default
|
||||||
home-manager.nixosModules.home-manager
|
home-manager.nixosModules.home-manager
|
||||||
../../home
|
../../home
|
||||||
];
|
];
|
||||||
|
|||||||
@@ -1,24 +1,12 @@
|
|||||||
{ pkgs-unstable, ... }:
|
{ ... }:
|
||||||
{
|
{
|
||||||
services.displayManager.gdm.enable = true;
|
services.xserver = {
|
||||||
services.desktopManager.gnome.enable = true;
|
enable = true;
|
||||||
services.displayManager.sessionPackages = [ pkgs-unstable.niri ];
|
displayManager.gdm.enable = true;
|
||||||
|
desktopManager.gnome.enable = true;
|
||||||
|
};
|
||||||
|
|
||||||
services.printing.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;
|
security.rtkit.enable = true;
|
||||||
services.pipewire = {
|
services.pipewire = {
|
||||||
@@ -28,7 +16,7 @@
|
|||||||
pulse.enable = true;
|
pulse.enable = true;
|
||||||
jack.enable = true;
|
jack.enable = true;
|
||||||
};
|
};
|
||||||
services.pulseaudio.enable = false;
|
hardware.pulseaudio.enable = false;
|
||||||
|
|
||||||
programs.steam = {
|
programs.steam = {
|
||||||
enable = true;
|
enable = true;
|
||||||
|
|||||||
@@ -1,69 +1,56 @@
|
|||||||
# Do not modify this file! It was generated by ‘nixos-generate-config’
|
# Do not modify this file! It was generated by ‘nixos-generate-config’
|
||||||
# and may be overwritten by future invocations. Please make changes
|
# and may be overwritten by future invocations. Please make changes
|
||||||
# to /etc/nixos/configuration.nix instead.
|
# to /etc/nixos/configuration.nix instead.
|
||||||
{
|
{ config, lib, pkgs, modulesPath, ... }:
|
||||||
config,
|
|
||||||
lib,
|
|
||||||
modulesPath,
|
|
||||||
...
|
|
||||||
}:
|
|
||||||
|
|
||||||
{
|
{
|
||||||
imports = [
|
imports =
|
||||||
(modulesPath + "/installer/scan/not-detected.nix")
|
[ (modulesPath + "/installer/scan/not-detected.nix")
|
||||||
];
|
];
|
||||||
|
|
||||||
boot.initrd.availableKernelModules = [
|
boot.initrd.availableKernelModules = [ "nvme" "xhci_pci" "thunderbolt" "usb_storage" "sd_mod" ];
|
||||||
"nvme"
|
|
||||||
"xhci_pci"
|
|
||||||
"thunderbolt"
|
|
||||||
"usb_storage"
|
|
||||||
"sd_mod"
|
|
||||||
];
|
|
||||||
boot.initrd.kernelModules = [ ];
|
boot.initrd.kernelModules = [ ];
|
||||||
boot.kernelModules = [ "kvm-amd" ];
|
boot.kernelModules = [ "kvm-amd" ];
|
||||||
boot.extraModulePackages = [ ];
|
boot.extraModulePackages = [ ];
|
||||||
|
|
||||||
fileSystems."/" = {
|
fileSystems."/" =
|
||||||
device = "/dev/disk/by-uuid/a331b669-f5c5-42f7-be58-434873c1b689";
|
{ device = "/dev/disk/by-uuid/a331b669-f5c5-42f7-be58-434873c1b689";
|
||||||
fsType = "btrfs";
|
fsType = "btrfs";
|
||||||
options = [ "subvol=@" ];
|
options = [ "subvol=@" ];
|
||||||
};
|
};
|
||||||
|
|
||||||
boot.initrd.luks.devices."cryptroot" = {
|
boot.initrd.luks.devices."cryptroot" = {
|
||||||
device = "/dev/disk/by-uuid/43895585-8899-4e94-a413-889127c214f8";
|
device = "/dev/disk/by-uuid/43895585-8899-4e94-a413-889127c214f8";
|
||||||
allowDiscards = true;
|
allowDiscards = true;
|
||||||
};
|
};
|
||||||
|
|
||||||
fileSystems."/var/log" = {
|
fileSystems."/var/log" =
|
||||||
device = "/dev/disk/by-uuid/a331b669-f5c5-42f7-be58-434873c1b689";
|
{ device = "/dev/disk/by-uuid/a331b669-f5c5-42f7-be58-434873c1b689";
|
||||||
fsType = "btrfs";
|
fsType = "btrfs";
|
||||||
options = [ "subvol=@var_log" ];
|
options = [ "subvol=@var_log" ];
|
||||||
};
|
};
|
||||||
|
|
||||||
fileSystems."/home" = {
|
fileSystems."/home" =
|
||||||
device = "/dev/disk/by-uuid/a331b669-f5c5-42f7-be58-434873c1b689";
|
{ device = "/dev/disk/by-uuid/a331b669-f5c5-42f7-be58-434873c1b689";
|
||||||
fsType = "btrfs";
|
fsType = "btrfs";
|
||||||
options = [ "subvol=@home" ];
|
options = [ "subvol=@home" ];
|
||||||
};
|
};
|
||||||
|
|
||||||
fileSystems."/boot" = {
|
fileSystems."/boot" =
|
||||||
device = "/dev/disk/by-uuid/01E6-6258";
|
{ device = "/dev/disk/by-uuid/01E6-6258";
|
||||||
fsType = "vfat";
|
fsType = "vfat";
|
||||||
};
|
};
|
||||||
|
|
||||||
fileSystems."/swap" = {
|
fileSystems."/swap" =
|
||||||
device = "/dev/disk/by-uuid/a331b669-f5c5-42f7-be58-434873c1b689";
|
{ device = "/dev/disk/by-uuid/a331b669-f5c5-42f7-be58-434873c1b689";
|
||||||
fsType = "btrfs";
|
fsType = "btrfs";
|
||||||
options = [ "subvol=@swap" ];
|
options = [ "subvol=@swap" ];
|
||||||
};
|
};
|
||||||
|
|
||||||
swapDevices = [
|
swapDevices = [ {
|
||||||
{
|
device = "/swap/swapfile";
|
||||||
device = "/swap/swapfile";
|
size = 64*1024;
|
||||||
size = 64 * 1024;
|
} ];
|
||||||
}
|
|
||||||
];
|
|
||||||
|
|
||||||
# Enables DHCP on each ethernet and wireless interface. In case of scripted networking
|
# 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
|
# (the default) this is the recommended approach. When using systemd-networkd it's
|
||||||
|
|||||||
@@ -1,19 +1,15 @@
|
|||||||
{
|
{ pkgs, inputs, lib, config, ... }:
|
||||||
pkgs,
|
let
|
||||||
pkgs-unstable,
|
pkgsUnstable = inputs.nixpkgs-unstable.legacyPackages.${pkgs.system};
|
||||||
inputs,
|
in
|
||||||
lib,
|
|
||||||
config,
|
|
||||||
...
|
|
||||||
}:
|
|
||||||
{
|
{
|
||||||
hardware.bluetooth.enable = true;
|
hardware.bluetooth.enable = true;
|
||||||
hardware.bluetooth.powerOnBoot = true;
|
hardware.bluetooth.powerOnBoot = true;
|
||||||
|
|
||||||
services.udev.packages = [
|
services.udev.packages = [
|
||||||
pkgs.zsa-udev-rules
|
pkgs.zsa-udev-rules
|
||||||
pkgs-unstable.yubikey-personalization
|
pkgsUnstable.yubikey-personalization
|
||||||
inputs.ksoloti-pr.legacyPackages.${pkgs.stdenv.hostPlatform.system}.ksoloti
|
inputs.ksoloti-pr.legacyPackages.${pkgs.system}.ksoloti
|
||||||
];
|
];
|
||||||
services.usbmuxd = {
|
services.usbmuxd = {
|
||||||
enable = true;
|
enable = true;
|
||||||
@@ -50,11 +46,11 @@
|
|||||||
hardware.keyboard.zsa.enable = true;
|
hardware.keyboard.zsa.enable = true;
|
||||||
|
|
||||||
services.logind = {
|
services.logind = {
|
||||||
settings.Login = {
|
lidSwitch = "suspend";
|
||||||
IdleAction = "suspend";
|
powerKey = "suspend";
|
||||||
HandleLidSwitch = "suspend";
|
extraConfig = ''
|
||||||
HandlePowerKey = "suspend";
|
IdleAction=suspend
|
||||||
};
|
'';
|
||||||
};
|
};
|
||||||
|
|
||||||
powerManagement = {
|
powerManagement = {
|
||||||
@@ -63,79 +59,26 @@
|
|||||||
powerUpCommands = "${pkgs.networkmanager}/bin/nmcli radio wifi on";
|
powerUpCommands = "${pkgs.networkmanager}/bin/nmcli radio wifi on";
|
||||||
};
|
};
|
||||||
|
|
||||||
services.power-profiles-daemon.enable = true;
|
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;
|
||||||
|
|
||||||
hardware.amdgpu.opencl.enable = true;
|
hardware.amdgpu.opencl.enable = true;
|
||||||
hardware.graphics = {
|
hardware.graphics = {
|
||||||
enable = true;
|
enable = true;
|
||||||
extraPackages = with pkgs; [ rocmPackages.clr.icd ];
|
extraPackages = with pkgs; [ rocmPackages.clr.icd ];
|
||||||
};
|
};
|
||||||
services.resolved = {
|
networking.networkmanager.wifi.backend = "iwd";
|
||||||
enable = true;
|
|
||||||
dnsovertls = "opportunistic";
|
|
||||||
dnssec = "allow-downgrade";
|
|
||||||
};
|
|
||||||
networking.networkmanager = {
|
|
||||||
enable = true;
|
|
||||||
wifi.backend = "iwd";
|
|
||||||
dns = "systemd-resolved";
|
|
||||||
plugins = with pkgs; [
|
|
||||||
networkmanager-openvpn
|
|
||||||
];
|
|
||||||
};
|
|
||||||
security.tpm2.enable = true;
|
security.tpm2.enable = true;
|
||||||
|
|
||||||
services.nqptp.enable = true;
|
|
||||||
networking.firewall.allowedTCPPortRanges = [
|
|
||||||
{
|
|
||||||
from = 7000;
|
|
||||||
to = 7010;
|
|
||||||
}
|
|
||||||
];
|
|
||||||
networking.firewall.allowedUDPPorts = [ 5353 ];
|
|
||||||
|
|
||||||
networking.wg-quick.interfaces = lib.mkMerge (
|
|
||||||
lib.map
|
|
||||||
(
|
|
||||||
{
|
|
||||||
region,
|
|
||||||
ipOctet,
|
|
||||||
publicKey,
|
|
||||||
}:
|
|
||||||
{
|
|
||||||
"everii-${region}" = {
|
|
||||||
address = [ "10.${toString ipOctet}.8.48/22" ];
|
|
||||||
dns = [ "10.${toString ipOctet}.1.1" ];
|
|
||||||
privateKeyFile = config.age.secrets."everii-vpn/${region}.key".path;
|
|
||||||
peers = [
|
|
||||||
{
|
|
||||||
allowedIPs = [ "10.${toString ipOctet}.0.0/16" ];
|
|
||||||
endpoint = "vpn.${region}.infra.everii.io:51821";
|
|
||||||
inherit publicKey;
|
|
||||||
}
|
|
||||||
];
|
|
||||||
postUp = ''
|
|
||||||
${pkgs.systemd}/bin/resolvectl domain everii-${region} ~${region}.everii ~${toString ipOctet}.10.in-addr.arpa
|
|
||||||
${pkgs.systemd}/bin/resolvectl dnssec everii-${region} no
|
|
||||||
'';
|
|
||||||
};
|
|
||||||
}
|
|
||||||
)
|
|
||||||
[
|
|
||||||
{
|
|
||||||
region = "de1";
|
|
||||||
ipOctet = 13;
|
|
||||||
publicKey = "uBUgSTZb6WbfE960S3qFP/UUMtdsgNWqtkTaBkp6Xxo=";
|
|
||||||
}
|
|
||||||
{
|
|
||||||
region = "fi1";
|
|
||||||
ipOctet = 14;
|
|
||||||
publicKey = "Yoakl0lrL6IK1nT8x5SGpaS39fQxRAsP9Zjpu8/1RRs=";
|
|
||||||
}
|
|
||||||
{
|
|
||||||
region = "ch1";
|
|
||||||
ipOctet = 15;
|
|
||||||
publicKey = "gfciqAk+X02zoEKXSvRamx5+TGL3i4GpT7oUvHMD0xo=";
|
|
||||||
}
|
|
||||||
]
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,12 +3,7 @@
|
|||||||
networking.hostName = "radish";
|
networking.hostName = "radish";
|
||||||
time.timeZone = lib.mkForce null; # allow TZ to be set by desktop user
|
time.timeZone = lib.mkForce null; # allow TZ to be set by desktop user
|
||||||
i18n.defaultLocale = "de_DE.UTF-8";
|
i18n.defaultLocale = "de_DE.UTF-8";
|
||||||
i18n.supportedLocales = map (locale: "${locale}.UTF-8/UTF-8") [
|
i18n.supportedLocales = map (locale: "${locale}.UTF-8/UTF-8") [ "C" "en_US" "de_DE" "fi_FI" ];
|
||||||
"C"
|
|
||||||
"en_US"
|
|
||||||
"de_DE"
|
|
||||||
"fi_FI"
|
|
||||||
];
|
|
||||||
i18n.extraLocaleSettings.LANG = "en_US.UTF-8";
|
i18n.extraLocaleSettings.LANG = "en_US.UTF-8";
|
||||||
console = {
|
console = {
|
||||||
font = "Lat2-Terminus16";
|
font = "Lat2-Terminus16";
|
||||||
|
|||||||
@@ -1,17 +1,7 @@
|
|||||||
{
|
{ pkgs, lib, inputs, ... }:
|
||||||
pkgs,
|
|
||||||
pkgs-unstable,
|
|
||||||
lib,
|
|
||||||
inputs,
|
|
||||||
config,
|
|
||||||
...
|
|
||||||
}:
|
|
||||||
let
|
|
||||||
secrets = config.age.secrets;
|
|
||||||
in
|
|
||||||
{
|
{
|
||||||
nixpkgs.config.allowUnfree = true;
|
nixpkgs.config.allowUnfree = true;
|
||||||
nixpkgs.overlays = [ (import ../../custom-pkgs { inherit lib inputs pkgs-unstable; }) ];
|
nixpkgs.overlays = [ (import ../../custom-pkgs { inherit lib inputs; }) ];
|
||||||
|
|
||||||
environment = {
|
environment = {
|
||||||
systemPackages = with pkgs; [
|
systemPackages = with pkgs; [
|
||||||
@@ -28,18 +18,12 @@ in
|
|||||||
pathsToLink = [ "/share/zsh" ];
|
pathsToLink = [ "/share/zsh" ];
|
||||||
};
|
};
|
||||||
|
|
||||||
fonts.packages = with pkgs-unstable; [
|
services.pcscd = {
|
||||||
nerd-fonts.iosevka
|
enable = true;
|
||||||
nerd-fonts.iosevka-term
|
plugins = [ pkgs.ccid ];
|
||||||
];
|
};
|
||||||
services = {
|
|
||||||
gnome.evolution-data-server.enable = true;
|
|
||||||
flatpak.enable = true;
|
|
||||||
pcscd = {
|
|
||||||
enable = true;
|
|
||||||
plugins = [ pkgs.ccid ];
|
|
||||||
};
|
|
||||||
|
|
||||||
|
services = {
|
||||||
openssh = {
|
openssh = {
|
||||||
enable = true;
|
enable = true;
|
||||||
openFirewall = false;
|
openFirewall = false;
|
||||||
@@ -48,89 +32,17 @@ in
|
|||||||
tailscale = {
|
tailscale = {
|
||||||
enable = true;
|
enable = true;
|
||||||
useRoutingFeatures = "client";
|
useRoutingFeatures = "client";
|
||||||
package = pkgs-unstable.tailscale;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
ollama = {
|
ollama = {
|
||||||
enable = true;
|
enable = false; # FIXME: https://github.com/NixOS/nixpkgs/issues/376930
|
||||||
package = pkgs-unstable.ollama-vulkan;
|
acceleration = "rocm";
|
||||||
syncModels = true;
|
environmentVariables = {
|
||||||
loadModels = [
|
HSA_OVERRIDE_GFX_VERSION = "11.0.3";
|
||||||
"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 = {
|
programs = {
|
||||||
zsh.enable = true;
|
zsh.enable = true;
|
||||||
_1password-gui = {
|
_1password-gui = {
|
||||||
@@ -139,35 +51,4 @@ in
|
|||||||
};
|
};
|
||||||
_1password.enable = true;
|
_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}'";
|
|
||||||
};
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,18 +0,0 @@
|
|||||||
{ lib, ... }:
|
|
||||||
{
|
|
||||||
age.secrets = lib.listToAttrs (
|
|
||||||
map
|
|
||||||
(secret: {
|
|
||||||
name = secret;
|
|
||||||
value = {
|
|
||||||
file = ../../secrets/${secret}.age;
|
|
||||||
};
|
|
||||||
})
|
|
||||||
[
|
|
||||||
"borgbackup-radish"
|
|
||||||
"everii-vpn/de1.key"
|
|
||||||
"everii-vpn/ch1.key"
|
|
||||||
"everii-vpn/fi1.key"
|
|
||||||
]
|
|
||||||
);
|
|
||||||
}
|
|
||||||
@@ -2,36 +2,16 @@
|
|||||||
{
|
{
|
||||||
# Define a user account. Don't forget to set a password with ‘passwd’.
|
# Define a user account. Don't forget to set a password with ‘passwd’.
|
||||||
users.users.jokke = {
|
users.users.jokke = {
|
||||||
uid = 1001;
|
|
||||||
isNormalUser = true;
|
isNormalUser = true;
|
||||||
extraGroups = [
|
extraGroups = [ "wheel" ];
|
||||||
"wheel"
|
|
||||||
"networkmanager"
|
|
||||||
];
|
|
||||||
shell = pkgs.zsh;
|
shell = pkgs.zsh;
|
||||||
initialPassword = "changeme";
|
|
||||||
};
|
};
|
||||||
|
|
||||||
users.users.moco = {
|
users.users.moco = {
|
||||||
uid = 1000;
|
|
||||||
isNormalUser = true;
|
isNormalUser = true;
|
||||||
extraGroups = [
|
extraGroups = [ "wheel" ];
|
||||||
"wheel"
|
|
||||||
"networkmanager"
|
|
||||||
];
|
|
||||||
shell = pkgs.zsh;
|
shell = pkgs.zsh;
|
||||||
initialPassword = "changeme";
|
subUidRanges = [{ startUid = 10000; count = 65536; }];
|
||||||
subUidRanges = [
|
subGidRanges = [{ startGid = 10000; count = 65536; }];
|
||||||
{
|
|
||||||
startUid = 10000;
|
|
||||||
count = 65536;
|
|
||||||
}
|
|
||||||
];
|
|
||||||
subGidRanges = [
|
|
||||||
{
|
|
||||||
startGid = 10000;
|
|
||||||
count = 65536;
|
|
||||||
}
|
|
||||||
];
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,98 +0,0 @@
|
|||||||
# 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?
|
|
||||||
}
|
|
||||||
@@ -1,10 +0,0 @@
|
|||||||
{ 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"
|
|
||||||
];
|
|
||||||
}
|
|
||||||
@@ -1,4 +0,0 @@
|
|||||||
{ lib, ... }:
|
|
||||||
{
|
|
||||||
nixpkgs.hostPlatform = lib.mkDefault "aarch64-linux";
|
|
||||||
}
|
|
||||||
@@ -1,15 +0,0 @@
|
|||||||
{ lib, ... }:
|
|
||||||
{
|
|
||||||
age.secrets = lib.listToAttrs (
|
|
||||||
map
|
|
||||||
(secret: {
|
|
||||||
name = secret;
|
|
||||||
value = {
|
|
||||||
file = ../../secrets/${secret}.age;
|
|
||||||
};
|
|
||||||
})
|
|
||||||
[
|
|
||||||
"wpa_supplicant"
|
|
||||||
]
|
|
||||||
);
|
|
||||||
}
|
|
||||||
@@ -1,12 +1,5 @@
|
|||||||
{ inputs, config, ... }:
|
{ inputs, ... }:
|
||||||
{
|
{
|
||||||
_module.args = {
|
|
||||||
pkgs-unstable = import inputs.nixpkgs-unstable {
|
|
||||||
system = config.nixpkgs.hostPlatform.system;
|
|
||||||
config = config.nixpkgs.config;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
imports = [
|
imports = [
|
||||||
./vlans.nix
|
./vlans.nix
|
||||||
./firewall.nix
|
./firewall.nix
|
||||||
|
|||||||
@@ -1,48 +1,19 @@
|
|||||||
{ lib, config, ... }:
|
{ lib, config, ... }:
|
||||||
let
|
let
|
||||||
services = {
|
services = {
|
||||||
ssh = {
|
ssh = { tcp = [ 22 ]; };
|
||||||
tcp = [ 22 ];
|
dhcp = { udp = [ 67 68 ]; };
|
||||||
};
|
dns = { udp = [ 53 ]; };
|
||||||
dhcp = {
|
web = { tcp = [ 80 443 ]; };
|
||||||
udp = [
|
|
||||||
67
|
|
||||||
68
|
|
||||||
];
|
|
||||||
};
|
|
||||||
dns = {
|
|
||||||
udp = [
|
|
||||||
53
|
|
||||||
853
|
|
||||||
];
|
|
||||||
tcp = [
|
|
||||||
53
|
|
||||||
853
|
|
||||||
];
|
|
||||||
};
|
|
||||||
web = {
|
|
||||||
tcp = [
|
|
||||||
80
|
|
||||||
443
|
|
||||||
];
|
|
||||||
};
|
|
||||||
};
|
};
|
||||||
|
|
||||||
rulesForServices =
|
rulesForServices = enabledServices:
|
||||||
enabledServices:
|
|
||||||
lib.foldr
|
lib.foldr
|
||||||
(
|
(service: { allowedUDPPorts, allowedTCPPorts }: {
|
||||||
service:
|
allowedUDPPorts = allowedUDPPorts ++ services.${service}.udp or [ ];
|
||||||
{ allowedUDPPorts, allowedTCPPorts }:
|
allowedTCPPorts = allowedTCPPorts ++ services.${service}.tcp or [ ];
|
||||||
{
|
})
|
||||||
allowedUDPPorts = allowedUDPPorts ++ services.${service}.udp or [ ];
|
{ allowedUDPPorts = [ ]; allowedTCPPorts = [ ]; }
|
||||||
allowedTCPPorts = allowedTCPPorts ++ services.${service}.tcp or [ ];
|
|
||||||
}
|
|
||||||
)
|
|
||||||
{
|
|
||||||
allowedUDPPorts = [ ];
|
|
||||||
allowedTCPPorts = [ ];
|
|
||||||
}
|
|
||||||
enabledServices;
|
enabledServices;
|
||||||
|
|
||||||
cfg = config.modules.firewall;
|
cfg = config.modules.firewall;
|
||||||
|
|||||||
@@ -1,32 +0,0 @@
|
|||||||
{
|
|
||||||
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;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
}
|
|
||||||
@@ -1,74 +0,0 @@
|
|||||||
{ 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;
|
|
||||||
upstream_dns = [
|
|
||||||
"https://dns10.quad9.net/dns-query"
|
|
||||||
"https://cloudflare-dns.com/dns-query"
|
|
||||||
"https://dns.google/dns-query"
|
|
||||||
];
|
|
||||||
fallback_dns = [
|
|
||||||
"https://cloudflare-dns.com/dns-query"
|
|
||||||
"https://dns.google/dns-query"
|
|
||||||
];
|
|
||||||
};
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
systemd.services.adguardhome = {
|
|
||||||
requires = [ "tailscaled.service" ];
|
|
||||||
after = [ "tailscaled.service" ];
|
|
||||||
};
|
|
||||||
|
|
||||||
services.webserver.vHosts.${fqdn} = {
|
|
||||||
tailscaleAuth = true;
|
|
||||||
locations."/".proxyPort = cfg.port;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
}
|
|
||||||
@@ -16,24 +16,5 @@
|
|||||||
./workout-sync.nix
|
./workout-sync.nix
|
||||||
./readeck.nix
|
./readeck.nix
|
||||||
./donetick.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
|
|
||||||
./searx.nix
|
|
||||||
./open-webui.nix
|
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,125 +0,0 @@
|
|||||||
{
|
|
||||||
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;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
};
|
|
||||||
}
|
|
||||||
@@ -1,187 +0,0 @@
|
|||||||
#!/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
|
|
||||||
@@ -1,125 +0,0 @@
|
|||||||
{
|
|
||||||
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 = {
|
|
||||||
HOME = "/var/lib/dnote";
|
|
||||||
XDG_DATA_HOME = "/var/lib/dnote";
|
|
||||||
XDG_CONFIG_HOME = "/var/lib/dnote";
|
|
||||||
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 start --port ${toString cfg.port}";
|
|
||||||
EnvironmentFile = lib.mkIf (cfg.environmentFile != null) cfg.environmentFile;
|
|
||||||
User = cfg.user;
|
|
||||||
StateDirectory = "dnote";
|
|
||||||
};
|
|
||||||
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,9 +1,4 @@
|
|||||||
{
|
{ lib, pkgs, config, ... }:
|
||||||
lib,
|
|
||||||
pkgs,
|
|
||||||
config,
|
|
||||||
...
|
|
||||||
}:
|
|
||||||
let
|
let
|
||||||
types = {
|
types = {
|
||||||
jwtSettings = {
|
jwtSettings = {
|
||||||
@@ -211,7 +206,7 @@ in
|
|||||||
|
|
||||||
services.webserver = {
|
services.webserver = {
|
||||||
enable = lib.mkDefault true;
|
enable = lib.mkDefault true;
|
||||||
vHosts.${fqdn}.locations."/".proxyPort = cfg.settings.server.port;
|
vHosts.${fqdn}.locations."/" .proxyPort = cfg.settings.server.port;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,74 +0,0 @@
|
|||||||
{
|
|
||||||
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 ];
|
|
||||||
};
|
|
||||||
}
|
|
||||||
@@ -1,45 +0,0 @@
|
|||||||
{ 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,12 +38,11 @@ in
|
|||||||
value.extraConfig = ''
|
value.extraConfig = ''
|
||||||
rewrite ^.*$ https://${fqdn}/.well-known/${path} permanent;
|
rewrite ^.*$ https://${fqdn}/.well-known/${path} permanent;
|
||||||
'';
|
'';
|
||||||
})
|
}) [
|
||||||
[
|
"host-meta"
|
||||||
"host-meta"
|
"webfinger"
|
||||||
"webfinger"
|
"nodeinfo"
|
||||||
"nodeinfo"
|
]
|
||||||
]
|
|
||||||
);
|
);
|
||||||
|
|
||||||
"${fqdn}".locations."/".proxyPort = port;
|
"${fqdn}".locations."/".proxyPort = port;
|
||||||
|
|||||||
@@ -31,32 +31,28 @@ in
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
services = {
|
services.prometheus = {
|
||||||
prometheus = {
|
enable = true;
|
||||||
enable = true;
|
exporters.node.enable = true;
|
||||||
exporters.node.enable = true;
|
scrapeConfigs = [
|
||||||
scrapeConfigs = [
|
{
|
||||||
{
|
job_name = "node";
|
||||||
job_name = "node";
|
static_configs = [
|
||||||
static_configs = [
|
{ targets = [ "localhost:9100" ]; }
|
||||||
{ targets = [ "localhost:9100" ]; }
|
];
|
||||||
];
|
}
|
||||||
}
|
];
|
||||||
];
|
};
|
||||||
};
|
|
||||||
|
|
||||||
webserver.vHosts.${fqdn}.locations."/".proxyPort = cfg.settings.server.http_port;
|
services.webserver.vHosts.${fqdn}.locations."/".proxyPort = cfg.settings.server.http_port;
|
||||||
|
|
||||||
postgresql = {
|
services.postgresql = {
|
||||||
enable = lib.mkDefault true;
|
enable = lib.mkDefault true;
|
||||||
ensureDatabases = [ "grafana" ];
|
ensureDatabases = [ "grafana" ];
|
||||||
ensureUsers = [
|
ensureUsers = [{
|
||||||
{
|
name = "grafana";
|
||||||
name = "grafana";
|
ensureDBOwnership = true;
|
||||||
ensureDBOwnership = true;
|
}];
|
||||||
}
|
|
||||||
];
|
|
||||||
};
|
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,9 +1,4 @@
|
|||||||
{
|
{ lib, config, inputs, ... }:
|
||||||
lib,
|
|
||||||
config,
|
|
||||||
inputs,
|
|
||||||
...
|
|
||||||
}:
|
|
||||||
let
|
let
|
||||||
cfg = config.services.gtrackmap;
|
cfg = config.services.gtrackmap;
|
||||||
fqdn = "${cfg.subdomain}.${config.networking.domain}";
|
fqdn = "${cfg.subdomain}.${config.networking.domain}";
|
||||||
|
|||||||
@@ -1,9 +1,4 @@
|
|||||||
{
|
{ lib, config, inputs, ... }:
|
||||||
lib,
|
|
||||||
config,
|
|
||||||
inputs,
|
|
||||||
...
|
|
||||||
}:
|
|
||||||
let
|
let
|
||||||
cfg = config.services.hastebin;
|
cfg = config.services.hastebin;
|
||||||
secrets = config.age.secrets;
|
secrets = config.age.secrets;
|
||||||
|
|||||||
@@ -1,72 +0,0 @@
|
|||||||
{ 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;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
}
|
|
||||||
@@ -1,20 +0,0 @@
|
|||||||
{ 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,18 +31,7 @@ in
|
|||||||
};
|
};
|
||||||
webserver = {
|
webserver = {
|
||||||
enable = lib.mkDefault true;
|
enable = lib.mkDefault true;
|
||||||
vHosts.${fqdn} = {
|
vHosts.${fqdn}.locations."/".proxyPort = cfg.port;
|
||||||
proxyBuffering = false;
|
|
||||||
locations."/" = {
|
|
||||||
proxyPort = cfg.port;
|
|
||||||
extraConfig = ''
|
|
||||||
client_max_body_size 0;
|
|
||||||
proxy_send_timeout 300;
|
|
||||||
proxy_read_timeout 300;
|
|
||||||
send_timeout 300;
|
|
||||||
'';
|
|
||||||
};
|
|
||||||
};
|
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -1,99 +0,0 @@
|
|||||||
{
|
|
||||||
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,8 +1,4 @@
|
|||||||
{
|
{ config, lib, ... }:
|
||||||
config,
|
|
||||||
lib,
|
|
||||||
...
|
|
||||||
}:
|
|
||||||
let
|
let
|
||||||
cfg = config.services.invidious;
|
cfg = config.services.invidious;
|
||||||
fqdn = "${cfg.subdomain}.${config.networking.domain}";
|
fqdn = "${cfg.subdomain}.${config.networking.domain}";
|
||||||
@@ -15,35 +11,24 @@ in
|
|||||||
};
|
};
|
||||||
|
|
||||||
config = lib.mkIf cfg.enable {
|
config = lib.mkIf cfg.enable {
|
||||||
services = {
|
services.invidious = {
|
||||||
invidious = {
|
domain = fqdn;
|
||||||
domain = fqdn;
|
address = "127.0.0.1";
|
||||||
address = "127.0.0.1";
|
|
||||||
|
|
||||||
settings = {
|
settings = {
|
||||||
external_port = 443;
|
external_port = 443;
|
||||||
db = {
|
db = {
|
||||||
dbname = "invidious";
|
dbname = "invidious";
|
||||||
user = "invidious";
|
user = "invidious";
|
||||||
};
|
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
postgresql.enable = lib.mkDefault true;
|
|
||||||
|
|
||||||
webserver = {
|
|
||||||
enable = lib.mkDefault true;
|
|
||||||
vHosts.${fqdn}.locations."/".proxyPort = cfg.port;
|
|
||||||
};
|
|
||||||
};
|
};
|
||||||
|
|
||||||
systemd.services.invidious.serviceConfig.DynamicUser = lib.mkForce false;
|
services.postgresql.enable = lib.mkDefault true;
|
||||||
|
|
||||||
users.groups.invidious = { };
|
services.webserver = {
|
||||||
users.users.invidious = {
|
enable = lib.mkDefault true;
|
||||||
isSystemUser = true;
|
vHosts.${fqdn}.locations."/".proxyPort = cfg.port;
|
||||||
group = "invidious";
|
|
||||||
description = "Invidious user";
|
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,37 +0,0 @@
|
|||||||
{ 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;
|
|
||||||
}
|
|
||||||
];
|
|
||||||
};
|
|
||||||
};
|
|
||||||
};
|
|
||||||
}
|
|
||||||
@@ -1,39 +0,0 @@
|
|||||||
{
|
|
||||||
config,
|
|
||||||
lib,
|
|
||||||
...
|
|
||||||
}:
|
|
||||||
let
|
|
||||||
cfg = config.services.mosquitto;
|
|
||||||
fqdn = "${cfg.subdomain}.${config.networking.domain}";
|
|
||||||
acme = config.security.acme;
|
|
||||||
in
|
|
||||||
{
|
|
||||||
options = {
|
|
||||||
services.mosquitto = {
|
|
||||||
openFirewall = lib.mkEnableOption "Open firewall port for Mosquitto";
|
|
||||||
subdomain = lib.mkOption {
|
|
||||||
type = lib.types.nullOr lib.types.str;
|
|
||||||
default = null;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
};
|
|
||||||
config = lib.mkIf cfg.enable (
|
|
||||||
lib.mkMerge [
|
|
||||||
{ networking.firewall.allowedTCPPorts = map ({ port, ... }: port) cfg.listeners; }
|
|
||||||
(lib.mkIf (cfg.subdomain != null) {
|
|
||||||
security.acme.certs.${fqdn}.postRun = ''
|
|
||||||
systemctl restart mosquitto
|
|
||||||
'';
|
|
||||||
|
|
||||||
systemd.services.mosquitto = {
|
|
||||||
requires = [ "acme-${fqdn}.service" ];
|
|
||||||
serviceConfig.LoadCredential = [
|
|
||||||
"fullchain.pem:${acme.certs.${fqdn}.directory}/fullchain.pem"
|
|
||||||
"key.pem:${acme.certs.${fqdn}.directory}/key.pem"
|
|
||||||
];
|
|
||||||
};
|
|
||||||
})
|
|
||||||
]
|
|
||||||
);
|
|
||||||
}
|
|
||||||
@@ -1,64 +0,0 @@
|
|||||||
{
|
|
||||||
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" ];
|
|
||||||
};
|
|
||||||
}
|
|
||||||
@@ -1,27 +0,0 @@
|
|||||||
{
|
|
||||||
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