Compare commits
11 Commits
c684beed09
...
refactor
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
02b23d63ac
|
||
|
|
a5da268626
|
||
|
|
00cf5b6410
|
||
|
|
dac295ee61
|
||
|
|
26194b9808
|
||
|
|
f64518ff35
|
||
|
|
c309c606a1
|
||
|
|
c0bdcd889b
|
||
|
|
c2bc64ed5c
|
||
|
|
85dbaebc4a
|
||
|
|
be9d398606
|
@@ -1,49 +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: Debug environment
|
|
||||||
run: |
|
|
||||||
echo "=== System Info ==="
|
|
||||||
uname -a
|
|
||||||
nix --version
|
|
||||||
echo "=== Memory ==="
|
|
||||||
free -h || true
|
|
||||||
echo "=== Disk ==="
|
|
||||||
df -h /nix /tmp || true
|
|
||||||
echo "=== Nix Config ==="
|
|
||||||
nix show-config 2>&1 | head -20 || true
|
|
||||||
|
|
||||||
- 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'
|
|
||||||
env:
|
|
||||||
GITEA_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
||||||
run: |
|
|
||||||
# Push aarch64 image
|
|
||||||
skopeo copy \
|
|
||||||
--insecure-policy \
|
|
||||||
--dest-creds "${{ github.actor }}:${GITEA_TOKEN}" \
|
|
||||||
"docker-archive:./image-aarch64.tar.gz" \
|
|
||||||
"docker://${{ github.server_url }}/${{ github.repository }}/node:latest-arm64"
|
|
||||||
|
|
||||||
# Create and push manifest for arm64
|
|
||||||
skopeo manifest create \
|
|
||||||
--insecure-policy \
|
|
||||||
--dest-creds "${{ github.actor }}:${GITEA_TOKEN}" \
|
|
||||||
"docker://${{ github.server_url }}/${{ github.repository }}/node:latest" \
|
|
||||||
"docker://${{ github.server_url }}/${{ 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
|
|
||||||
4
.gitignore
vendored
4
.gitignore
vendored
@@ -1,4 +0,0 @@
|
|||||||
/result
|
|
||||||
/.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": ["--build-on-target", "--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": ["--build-on-target", "--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 +0,0 @@
|
|||||||
# My NixOS Configurations
|
|
||||||
|
|
||||||
[](https://builds.sr.ht/~repomaa/NixOS?)
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
{ util, ... }: util.package { }
|
|
||||||
@@ -1,14 +0,0 @@
|
|||||||
{ 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 +0,0 @@
|
|||||||
{
|
|
||||||
lib,
|
|
||||||
inputs,
|
|
||||||
pkgs-unstable,
|
|
||||||
...
|
|
||||||
}:
|
|
||||||
let
|
|
||||||
inherit (builtins) attrNames filter readDir;
|
|
||||||
dirs =
|
|
||||||
let
|
|
||||||
files = readDir ./.;
|
|
||||||
in
|
|
||||||
filter (name: files."${name}" == "directory") (attrNames files);
|
|
||||||
util = import ./util.nix;
|
|
||||||
in
|
|
||||||
lib.composeManyExtensions (
|
|
||||||
map (
|
|
||||||
dir:
|
|
||||||
import ./${dir} {
|
|
||||||
util = util dir;
|
|
||||||
inherit inputs lib pkgs-unstable;
|
|
||||||
}
|
|
||||||
) dirs
|
|
||||||
)
|
|
||||||
@@ -1,7 +0,0 @@
|
|||||||
{
|
|
||||||
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 +0,0 @@
|
|||||||
{
|
|
||||||
pkgs,
|
|
||||||
lib,
|
|
||||||
pkgs-unstable,
|
|
||||||
}:
|
|
||||||
pkgs.runCommand "otp"
|
|
||||||
{
|
|
||||||
code = ./otp.cr;
|
|
||||||
env = {
|
|
||||||
YKMAN = lib.getExe pkgs-unstable.yubikey-manager;
|
|
||||||
SKIM = lib.getExe pkgs.skim;
|
|
||||||
WALKER = lib.getExe pkgs-unstable.walker;
|
|
||||||
WL_COPY = lib.getExe' pkgs.wl-clipboard "wl-copy";
|
|
||||||
NOTIFY_SEND = lib.getExe pkgs.libnotify;
|
|
||||||
NOTIFY_ICON = "${pkgs-unstable.yubioath-flutter}/share/pixmaps/com.yubico.yubioath.png";
|
|
||||||
};
|
|
||||||
nativeBuildInputs = [ pkgs.crystal ];
|
|
||||||
}
|
|
||||||
''
|
|
||||||
mkdir -p $out/bin
|
|
||||||
crystal build $code --release -o $out/bin/otp
|
|
||||||
''
|
|
||||||
@@ -1,5 +0,0 @@
|
|||||||
dir: {
|
|
||||||
package = attrs: final: prev: {
|
|
||||||
"${dir}" = final.callPackage ./${dir}/package.nix (attrs // { pkgs = prev; });
|
|
||||||
};
|
|
||||||
}
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
{ util, ... }: util.package { }
|
|
||||||
@@ -1,14 +0,0 @@
|
|||||||
{ pkgs }:
|
|
||||||
pkgs.writeShellScriptBin "wl-copy" ''
|
|
||||||
set -euo pipefail
|
|
||||||
copy="${pkgs.wl-clipboard}/bin/wl-copy"
|
|
||||||
paste="${pkgs.wl-clipboard}/bin/wl-paste"
|
|
||||||
|
|
||||||
"$copy" "$@"
|
|
||||||
args="$*"
|
|
||||||
if [[ "$args" =~ /(^| )(-p|--primary)($| )/ ]]; then
|
|
||||||
exit
|
|
||||||
fi
|
|
||||||
|
|
||||||
"$paste" -n | "$copy" -p "$@"
|
|
||||||
''
|
|
||||||
692
flake.lock
generated
692
flake.lock
generated
@@ -1,147 +1,15 @@
|
|||||||
{
|
{
|
||||||
"nodes": {
|
"nodes": {
|
||||||
"agenix": {
|
|
||||||
"inputs": {
|
|
||||||
"darwin": "darwin",
|
|
||||||
"home-manager": "home-manager",
|
|
||||||
"nixpkgs": [
|
|
||||||
"nixpkgs"
|
|
||||||
],
|
|
||||||
"systems": "systems"
|
|
||||||
},
|
|
||||||
"locked": {
|
|
||||||
"lastModified": 1770165109,
|
|
||||||
"narHash": "sha256-9VnK6Oqai65puVJ4WYtCTvlJeXxMzAp/69HhQuTdl/I=",
|
|
||||||
"owner": "ryantm",
|
|
||||||
"repo": "agenix",
|
|
||||||
"rev": "b027ee29d959fda4b60b57566d64c98a202e0feb",
|
|
||||||
"type": "github"
|
|
||||||
},
|
|
||||||
"original": {
|
|
||||||
"owner": "ryantm",
|
|
||||||
"repo": "agenix",
|
|
||||||
"type": "github"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"colmena": {
|
|
||||||
"inputs": {
|
|
||||||
"flake-compat": "flake-compat",
|
|
||||||
"flake-utils": "flake-utils",
|
|
||||||
"nix-github-actions": "nix-github-actions",
|
|
||||||
"nixpkgs": [
|
|
||||||
"nixpkgs"
|
|
||||||
],
|
|
||||||
"stable": "stable"
|
|
||||||
},
|
|
||||||
"locked": {
|
|
||||||
"lastModified": 1762034856,
|
|
||||||
"narHash": "sha256-QVey3iP3UEoiFVXgypyjTvCrsIlA4ecx6Acaz5C8/PQ=",
|
|
||||||
"owner": "zhaofengli",
|
|
||||||
"repo": "colmena",
|
|
||||||
"rev": "349b035a5027f23d88eeb3bc41085d7ee29f18ed",
|
|
||||||
"type": "github"
|
|
||||||
},
|
|
||||||
"original": {
|
|
||||||
"owner": "zhaofengli",
|
|
||||||
"repo": "colmena",
|
|
||||||
"type": "github"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"crane": {
|
|
||||||
"locked": {
|
|
||||||
"lastModified": 1771121070,
|
|
||||||
"narHash": "sha256-aIlv7FRXF9q70DNJPI237dEDAznSKaXmL5lfK/Id/bI=",
|
|
||||||
"owner": "ipetkov",
|
|
||||||
"repo": "crane",
|
|
||||||
"rev": "a2812c19f1ed2e5ed5ce2ef7109798b575c180e1",
|
|
||||||
"type": "github"
|
|
||||||
},
|
|
||||||
"original": {
|
|
||||||
"owner": "ipetkov",
|
|
||||||
"repo": "crane",
|
|
||||||
"type": "github"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"darwin": {
|
|
||||||
"inputs": {
|
|
||||||
"nixpkgs": [
|
|
||||||
"agenix",
|
|
||||||
"nixpkgs"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"locked": {
|
|
||||||
"lastModified": 1744478979,
|
|
||||||
"narHash": "sha256-dyN+teG9G82G+m+PX/aSAagkC+vUv0SgUw3XkPhQodQ=",
|
|
||||||
"owner": "lnl7",
|
|
||||||
"repo": "nix-darwin",
|
|
||||||
"rev": "43975d782b418ebf4969e9ccba82466728c2851b",
|
|
||||||
"type": "github"
|
|
||||||
},
|
|
||||||
"original": {
|
|
||||||
"owner": "lnl7",
|
|
||||||
"ref": "master",
|
|
||||||
"repo": "nix-darwin",
|
|
||||||
"type": "github"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"dnote": {
|
|
||||||
"flake": false,
|
|
||||||
"locked": {
|
|
||||||
"lastModified": 1765604939,
|
|
||||||
"narHash": "sha256-5+grN/dsqRRFzUkz6ksvuEhgi4lYq64Rd0fejqzz8/Y=",
|
|
||||||
"owner": "dnote",
|
|
||||||
"repo": "dnote",
|
|
||||||
"rev": "9fa312e3fc6139788533ca6cd1ada8c16a10519c",
|
|
||||||
"type": "github"
|
|
||||||
},
|
|
||||||
"original": {
|
|
||||||
"owner": "dnote",
|
|
||||||
"repo": "dnote",
|
|
||||||
"type": "github"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"flake-compat": {
|
|
||||||
"flake": false,
|
|
||||||
"locked": {
|
|
||||||
"lastModified": 1650374568,
|
|
||||||
"narHash": "sha256-Z+s0J8/r907g149rllvwhb4pKi8Wam5ij0st8PwAh+E=",
|
|
||||||
"owner": "edolstra",
|
|
||||||
"repo": "flake-compat",
|
|
||||||
"rev": "b4a34015c698c7793d592d66adbab377907a2be8",
|
|
||||||
"type": "github"
|
|
||||||
},
|
|
||||||
"original": {
|
|
||||||
"owner": "edolstra",
|
|
||||||
"repo": "flake-compat",
|
|
||||||
"type": "github"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"flake-compat_2": {
|
|
||||||
"flake": false,
|
|
||||||
"locked": {
|
|
||||||
"lastModified": 1767039857,
|
|
||||||
"narHash": "sha256-vNpUSpF5Nuw8xvDLj2KCwwksIbjua2LZCqhV1LNRDns=",
|
|
||||||
"owner": "NixOS",
|
|
||||||
"repo": "flake-compat",
|
|
||||||
"rev": "5edf11c44bc78a0d334f6334cdaf7d60d732daab",
|
|
||||||
"type": "github"
|
|
||||||
},
|
|
||||||
"original": {
|
|
||||||
"owner": "NixOS",
|
|
||||||
"repo": "flake-compat",
|
|
||||||
"type": "github"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"flake-parts": {
|
"flake-parts": {
|
||||||
"inputs": {
|
"inputs": {
|
||||||
"nixpkgs-lib": "nixpkgs-lib"
|
"nixpkgs-lib": "nixpkgs-lib"
|
||||||
},
|
},
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1769996383,
|
"lastModified": 1719877454,
|
||||||
"narHash": "sha256-AnYjnFWgS49RlqX7LrC4uA+sCCDBj0Ry/WOJ5XWAsa0=",
|
"narHash": "sha256-g5N1yyOSsPNiOlFfkuI/wcUjmtah+nxdImJqrSATjOU=",
|
||||||
"owner": "hercules-ci",
|
"owner": "hercules-ci",
|
||||||
"repo": "flake-parts",
|
"repo": "flake-parts",
|
||||||
"rev": "57928607ea566b5db3ad13af0e57e921e6b12381",
|
"rev": "4e3583423212f9303aa1a6337f8dffb415920e4f",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
@@ -168,42 +36,9 @@
|
|||||||
"type": "github"
|
"type": "github"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"flake-parts_3": {
|
|
||||||
"inputs": {
|
|
||||||
"nixpkgs-lib": "nixpkgs-lib_3"
|
|
||||||
},
|
|
||||||
"locked": {
|
|
||||||
"lastModified": 1738453229,
|
|
||||||
"narHash": "sha256-7H9XgNiGLKN1G1CgRh0vUL4AheZSYzPm+zmZ7vxbJdo=",
|
|
||||||
"owner": "hercules-ci",
|
|
||||||
"repo": "flake-parts",
|
|
||||||
"rev": "32ea77a06711b758da0ad9bd6a844c5740a87abd",
|
|
||||||
"type": "github"
|
|
||||||
},
|
|
||||||
"original": {
|
|
||||||
"owner": "hercules-ci",
|
|
||||||
"repo": "flake-parts",
|
|
||||||
"type": "github"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"flake-utils": {
|
"flake-utils": {
|
||||||
"locked": {
|
|
||||||
"lastModified": 1659877975,
|
|
||||||
"narHash": "sha256-zllb8aq3YO3h8B/U0/J1WBgAL8EX5yWf5pMj3G0NAmc=",
|
|
||||||
"owner": "numtide",
|
|
||||||
"repo": "flake-utils",
|
|
||||||
"rev": "c0e246b9b83f637f4681389ecabcb2681b4f3af0",
|
|
||||||
"type": "github"
|
|
||||||
},
|
|
||||||
"original": {
|
|
||||||
"owner": "numtide",
|
|
||||||
"repo": "flake-utils",
|
|
||||||
"type": "github"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"flake-utils_2": {
|
|
||||||
"inputs": {
|
"inputs": {
|
||||||
"systems": "systems_2"
|
"systems": "systems"
|
||||||
},
|
},
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1710146030,
|
"lastModified": 1710146030,
|
||||||
@@ -219,9 +54,9 @@
|
|||||||
"type": "github"
|
"type": "github"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"flake-utils_3": {
|
"flake-utils_2": {
|
||||||
"inputs": {
|
"inputs": {
|
||||||
"systems": "systems_3"
|
"systems": "systems_2"
|
||||||
},
|
},
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1701680307,
|
"lastModified": 1701680307,
|
||||||
@@ -237,45 +72,9 @@
|
|||||||
"type": "github"
|
"type": "github"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"flake-utils_4": {
|
|
||||||
"inputs": {
|
|
||||||
"systems": "systems_4"
|
|
||||||
},
|
|
||||||
"locked": {
|
|
||||||
"lastModified": 1710146030,
|
|
||||||
"narHash": "sha256-SZ5L6eA7HJ/nmkzGG7/ISclqe6oZdOZTNoesiInkXPQ=",
|
|
||||||
"owner": "numtide",
|
|
||||||
"repo": "flake-utils",
|
|
||||||
"rev": "b1d9ab70662946ef0850d488da1c9019f3a9752a",
|
|
||||||
"type": "github"
|
|
||||||
},
|
|
||||||
"original": {
|
|
||||||
"owner": "numtide",
|
|
||||||
"repo": "flake-utils",
|
|
||||||
"type": "github"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"flake-utils_5": {
|
|
||||||
"inputs": {
|
|
||||||
"systems": "systems_5"
|
|
||||||
},
|
|
||||||
"locked": {
|
|
||||||
"lastModified": 1731533236,
|
|
||||||
"narHash": "sha256-l0KFg5HjrsfsO/JpG+r7fRrqm12kzFHyUHqHCVpMMbI=",
|
|
||||||
"owner": "numtide",
|
|
||||||
"repo": "flake-utils",
|
|
||||||
"rev": "11707dc2f618dd54ca8739b309ec4fc024de578b",
|
|
||||||
"type": "github"
|
|
||||||
},
|
|
||||||
"original": {
|
|
||||||
"owner": "numtide",
|
|
||||||
"repo": "flake-utils",
|
|
||||||
"type": "github"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"frontend": {
|
"frontend": {
|
||||||
"inputs": {
|
"inputs": {
|
||||||
"flake-utils": "flake-utils_2",
|
"flake-utils": "flake-utils",
|
||||||
"nixpkgs": "nixpkgs",
|
"nixpkgs": "nixpkgs",
|
||||||
"pnpm2nix": "pnpm2nix"
|
"pnpm2nix": "pnpm2nix"
|
||||||
},
|
},
|
||||||
@@ -293,28 +92,6 @@
|
|||||||
"type": "github"
|
"type": "github"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"gitignore": {
|
|
||||||
"inputs": {
|
|
||||||
"nixpkgs": [
|
|
||||||
"lanzaboote",
|
|
||||||
"pre-commit",
|
|
||||||
"nixpkgs"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"locked": {
|
|
||||||
"lastModified": 1709087332,
|
|
||||||
"narHash": "sha256-HG2cCnktfHsKV0s4XW83gU3F57gaTljL9KNSuG6bnQs=",
|
|
||||||
"owner": "hercules-ci",
|
|
||||||
"repo": "gitignore.nix",
|
|
||||||
"rev": "637db329424fd7e46cf4185293b9cc8c88c95394",
|
|
||||||
"type": "github"
|
|
||||||
},
|
|
||||||
"original": {
|
|
||||||
"owner": "hercules-ci",
|
|
||||||
"repo": "gitignore.nix",
|
|
||||||
"type": "github"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"gtrackmap": {
|
"gtrackmap": {
|
||||||
"inputs": {
|
"inputs": {
|
||||||
"flake-parts": "flake-parts_2",
|
"flake-parts": "flake-parts_2",
|
||||||
@@ -324,11 +101,11 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1739016132,
|
"lastModified": 1719992292,
|
||||||
"narHash": "sha256-7utkc6OSf4K2PFktxPPPZdBMnl0LoACEOeifOoAkTjM=",
|
"narHash": "sha256-bMKzt/rKkBsI8NbtsmfGG0tHsn/UilZqgOYwHRk45KQ=",
|
||||||
"owner": "gtrackmap",
|
"owner": "gtrackmap",
|
||||||
"repo": "gtrackmap",
|
"repo": "gtrackmap",
|
||||||
"rev": "1db7bb76a486f5ca4f8ce055a3bbee08d9f63775",
|
"rev": "84df36e004cda9bd802e46ed0c814c7b08031807",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
@@ -337,164 +114,6 @@
|
|||||||
"type": "github"
|
"type": "github"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"hastebin": {
|
|
||||||
"inputs": {
|
|
||||||
"flake-parts": "flake-parts_3",
|
|
||||||
"nixpkgs": [
|
|
||||||
"nixpkgs"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"locked": {
|
|
||||||
"lastModified": 1740944656,
|
|
||||||
"narHash": "sha256-SLFmhOqOly5Uz4MiIDLfDUQnwM0FDjthoZPvdFGvOSY=",
|
|
||||||
"owner": "~repomaa",
|
|
||||||
"repo": "hastebin",
|
|
||||||
"rev": "087b64789ebf11a9874c8777c0aee88675a9ceaf",
|
|
||||||
"type": "sourcehut"
|
|
||||||
},
|
|
||||||
"original": {
|
|
||||||
"owner": "~repomaa",
|
|
||||||
"repo": "hastebin",
|
|
||||||
"type": "sourcehut"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"home-manager": {
|
|
||||||
"inputs": {
|
|
||||||
"nixpkgs": [
|
|
||||||
"agenix",
|
|
||||||
"nixpkgs"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"locked": {
|
|
||||||
"lastModified": 1745494811,
|
|
||||||
"narHash": "sha256-YZCh2o9Ua1n9uCvrvi5pRxtuVNml8X2a03qIFfRKpFs=",
|
|
||||||
"owner": "nix-community",
|
|
||||||
"repo": "home-manager",
|
|
||||||
"rev": "abfad3d2958c9e6300a883bd443512c55dfeb1be",
|
|
||||||
"type": "github"
|
|
||||||
},
|
|
||||||
"original": {
|
|
||||||
"owner": "nix-community",
|
|
||||||
"repo": "home-manager",
|
|
||||||
"type": "github"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"home-manager_2": {
|
|
||||||
"inputs": {
|
|
||||||
"nixpkgs": [
|
|
||||||
"nixpkgs"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"locked": {
|
|
||||||
"lastModified": 1770260404,
|
|
||||||
"narHash": "sha256-3iVX1+7YUIt23hBx1WZsUllhbmP2EnXrV8tCRbLxHc8=",
|
|
||||||
"owner": "nix-community",
|
|
||||||
"repo": "home-manager",
|
|
||||||
"rev": "0d782ee42c86b196acff08acfbf41bb7d13eed5b",
|
|
||||||
"type": "github"
|
|
||||||
},
|
|
||||||
"original": {
|
|
||||||
"owner": "nix-community",
|
|
||||||
"ref": "release-25.11",
|
|
||||||
"repo": "home-manager",
|
|
||||||
"type": "github"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"ketchup": {
|
|
||||||
"inputs": {
|
|
||||||
"flake-utils": "flake-utils_4",
|
|
||||||
"nixpkgs": [
|
|
||||||
"nixpkgs"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"locked": {
|
|
||||||
"lastModified": 1718020591,
|
|
||||||
"narHash": "sha256-nNkMX4Fifj4Z1n2ldWAeu1AujaW41ugsEokPrKioNy0=",
|
|
||||||
"owner": "repomaa",
|
|
||||||
"repo": "ketchup",
|
|
||||||
"rev": "7cbff916ad4ebfd983402842569730e63d105de9",
|
|
||||||
"type": "github"
|
|
||||||
},
|
|
||||||
"original": {
|
|
||||||
"owner": "repomaa",
|
|
||||||
"repo": "ketchup",
|
|
||||||
"type": "github"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"ksoloti-pr": {
|
|
||||||
"locked": {
|
|
||||||
"lastModified": 1730719587,
|
|
||||||
"narHash": "sha256-aeQjG4hFCAqnen296tC8XuX2w2gbaorcosP7jde0cqQ=",
|
|
||||||
"owner": "repomaa",
|
|
||||||
"repo": "nixpkgs",
|
|
||||||
"rev": "ea615cc6ccb36c050290e09a5f90a91b78900a81",
|
|
||||||
"type": "github"
|
|
||||||
},
|
|
||||||
"original": {
|
|
||||||
"owner": "repomaa",
|
|
||||||
"ref": "pkg/ksoloti",
|
|
||||||
"repo": "nixpkgs",
|
|
||||||
"type": "github"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"lanzaboote": {
|
|
||||||
"inputs": {
|
|
||||||
"crane": "crane",
|
|
||||||
"nixpkgs": "nixpkgs_3",
|
|
||||||
"pre-commit": "pre-commit",
|
|
||||||
"rust-overlay": "rust-overlay"
|
|
||||||
},
|
|
||||||
"locked": {
|
|
||||||
"lastModified": 1771492583,
|
|
||||||
"narHash": "sha256-nQzvnU4BGu8dA6BsPPCqmVcab/3ebVmHtX3ZWbW3Hxc=",
|
|
||||||
"owner": "nix-community",
|
|
||||||
"repo": "lanzaboote",
|
|
||||||
"rev": "5e9380994665ef66c87ab8e22c913ff837174ce4",
|
|
||||||
"type": "github"
|
|
||||||
},
|
|
||||||
"original": {
|
|
||||||
"owner": "nix-community",
|
|
||||||
"repo": "lanzaboote",
|
|
||||||
"type": "github"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"nix-github-actions": {
|
|
||||||
"inputs": {
|
|
||||||
"nixpkgs": [
|
|
||||||
"colmena",
|
|
||||||
"nixpkgs"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"locked": {
|
|
||||||
"lastModified": 1729742964,
|
|
||||||
"narHash": "sha256-B4mzTcQ0FZHdpeWcpDYPERtyjJd/NIuaQ9+BV1h+MpA=",
|
|
||||||
"owner": "nix-community",
|
|
||||||
"repo": "nix-github-actions",
|
|
||||||
"rev": "e04df33f62cdcf93d73e9a04142464753a16db67",
|
|
||||||
"type": "github"
|
|
||||||
},
|
|
||||||
"original": {
|
|
||||||
"owner": "nix-community",
|
|
||||||
"repo": "nix-github-actions",
|
|
||||||
"type": "github"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"nixos-hardware": {
|
|
||||||
"locked": {
|
|
||||||
"lastModified": 1771423359,
|
|
||||||
"narHash": "sha256-yRKJ7gpVmXbX2ZcA8nFi6CMPkJXZGjie2unsiMzj3Ig=",
|
|
||||||
"owner": "NixOS",
|
|
||||||
"repo": "nixos-hardware",
|
|
||||||
"rev": "740a22363033e9f1bb6270fbfb5a9574067af15b",
|
|
||||||
"type": "github"
|
|
||||||
},
|
|
||||||
"original": {
|
|
||||||
"owner": "NixOS",
|
|
||||||
"ref": "master",
|
|
||||||
"repo": "nixos-hardware",
|
|
||||||
"type": "github"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"nixpkgs": {
|
"nixpkgs": {
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1717196966,
|
"lastModified": 1717196966,
|
||||||
@@ -513,17 +132,14 @@
|
|||||||
},
|
},
|
||||||
"nixpkgs-lib": {
|
"nixpkgs-lib": {
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1769909678,
|
"lastModified": 1719876945,
|
||||||
"narHash": "sha256-cBEymOf4/o3FD5AZnzC3J9hLbiZ+QDT/KDuyHXVJOpM=",
|
"narHash": "sha256-Fm2rDDs86sHy0/1jxTOKB1118Q0O3Uc7EC0iXvXKpbI=",
|
||||||
"owner": "nix-community",
|
"type": "tarball",
|
||||||
"repo": "nixpkgs.lib",
|
"url": "https://github.com/NixOS/nixpkgs/archive/5daf0514482af3f97abaefc78a6606365c9108e2.tar.gz"
|
||||||
"rev": "72716169fe93074c333e8d0173151350670b824c",
|
|
||||||
"type": "github"
|
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
"owner": "nix-community",
|
"type": "tarball",
|
||||||
"repo": "nixpkgs.lib",
|
"url": "https://github.com/NixOS/nixpkgs/archive/5daf0514482af3f97abaefc78a6606365c9108e2.tar.gz"
|
||||||
"type": "github"
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"nixpkgs-lib_2": {
|
"nixpkgs-lib_2": {
|
||||||
@@ -538,34 +154,6 @@
|
|||||||
"url": "https://github.com/NixOS/nixpkgs/archive/5daf0514482af3f97abaefc78a6606365c9108e2.tar.gz"
|
"url": "https://github.com/NixOS/nixpkgs/archive/5daf0514482af3f97abaefc78a6606365c9108e2.tar.gz"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"nixpkgs-lib_3": {
|
|
||||||
"locked": {
|
|
||||||
"lastModified": 1738452942,
|
|
||||||
"narHash": "sha256-vJzFZGaCpnmo7I6i416HaBLpC+hvcURh/BQwROcGIp8=",
|
|
||||||
"type": "tarball",
|
|
||||||
"url": "https://github.com/NixOS/nixpkgs/archive/072a6db25e947df2f31aab9eccd0ab75d5b2da11.tar.gz"
|
|
||||||
},
|
|
||||||
"original": {
|
|
||||||
"type": "tarball",
|
|
||||||
"url": "https://github.com/NixOS/nixpkgs/archive/072a6db25e947df2f31aab9eccd0ab75d5b2da11.tar.gz"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"nixpkgs-unstable": {
|
|
||||||
"locked": {
|
|
||||||
"lastModified": 1771369470,
|
|
||||||
"narHash": "sha256-0NBlEBKkN3lufyvFegY4TYv5mCNHbi5OmBDrzihbBMQ=",
|
|
||||||
"owner": "NixOS",
|
|
||||||
"repo": "nixpkgs",
|
|
||||||
"rev": "0182a361324364ae3f436a63005877674cf45efb",
|
|
||||||
"type": "github"
|
|
||||||
},
|
|
||||||
"original": {
|
|
||||||
"owner": "NixOS",
|
|
||||||
"ref": "nixos-unstable",
|
|
||||||
"repo": "nixpkgs",
|
|
||||||
"type": "github"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"nixpkgs_2": {
|
"nixpkgs_2": {
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1702151865,
|
"lastModified": 1702151865,
|
||||||
@@ -584,11 +172,11 @@
|
|||||||
},
|
},
|
||||||
"nixpkgs_3": {
|
"nixpkgs_3": {
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1771008912,
|
"lastModified": 1719848872,
|
||||||
"narHash": "sha256-gf2AmWVTs8lEq7z/3ZAsgnZDhWIckkb+ZnAo5RzSxJg=",
|
"narHash": "sha256-H3+EC5cYuq+gQW8y0lSrrDZfH71LB4DAf+TDFyvwCNA=",
|
||||||
"owner": "NixOS",
|
"owner": "NixOS",
|
||||||
"repo": "nixpkgs",
|
"repo": "nixpkgs",
|
||||||
"rev": "a82ccc39b39b621151d6732718e3e250109076fa",
|
"rev": "00d80d13810dbfea8ab4ed1009b09100cca86ba8",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
@@ -598,25 +186,9 @@
|
|||||||
"type": "github"
|
"type": "github"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"nixpkgs_4": {
|
|
||||||
"locked": {
|
|
||||||
"lastModified": 1771419570,
|
|
||||||
"narHash": "sha256-bxAlQgre3pcQcaRUm/8A0v/X8d2nhfraWSFqVmMcBcU=",
|
|
||||||
"owner": "NixOS",
|
|
||||||
"repo": "nixpkgs",
|
|
||||||
"rev": "6d41bc27aaf7b6a3ba6b169db3bd5d6159cfaa47",
|
|
||||||
"type": "github"
|
|
||||||
},
|
|
||||||
"original": {
|
|
||||||
"owner": "NixOS",
|
|
||||||
"ref": "nixos-25.11",
|
|
||||||
"repo": "nixpkgs",
|
|
||||||
"type": "github"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"pnpm2nix": {
|
"pnpm2nix": {
|
||||||
"inputs": {
|
"inputs": {
|
||||||
"flake-utils": "flake-utils_3",
|
"flake-utils": "flake-utils_2",
|
||||||
"nixpkgs": "nixpkgs_2"
|
"nixpkgs": "nixpkgs_2"
|
||||||
},
|
},
|
||||||
"locked": {
|
"locked": {
|
||||||
@@ -633,102 +205,11 @@
|
|||||||
"type": "github"
|
"type": "github"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"pre-commit": {
|
|
||||||
"inputs": {
|
|
||||||
"flake-compat": "flake-compat_2",
|
|
||||||
"gitignore": "gitignore",
|
|
||||||
"nixpkgs": [
|
|
||||||
"lanzaboote",
|
|
||||||
"nixpkgs"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"locked": {
|
|
||||||
"lastModified": 1770726378,
|
|
||||||
"narHash": "sha256-kck+vIbGOaM/dHea7aTBxdFYpeUl/jHOy5W3eyRvVx8=",
|
|
||||||
"owner": "cachix",
|
|
||||||
"repo": "pre-commit-hooks.nix",
|
|
||||||
"rev": "5eaaedde414f6eb1aea8b8525c466dc37bba95ae",
|
|
||||||
"type": "github"
|
|
||||||
},
|
|
||||||
"original": {
|
|
||||||
"owner": "cachix",
|
|
||||||
"repo": "pre-commit-hooks.nix",
|
|
||||||
"type": "github"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"root": {
|
"root": {
|
||||||
"inputs": {
|
"inputs": {
|
||||||
"agenix": "agenix",
|
|
||||||
"colmena": "colmena",
|
|
||||||
"dnote": "dnote",
|
|
||||||
"flake-parts": "flake-parts",
|
"flake-parts": "flake-parts",
|
||||||
"gtrackmap": "gtrackmap",
|
"gtrackmap": "gtrackmap",
|
||||||
"hastebin": "hastebin",
|
"nixpkgs": "nixpkgs_3"
|
||||||
"home-manager": "home-manager_2",
|
|
||||||
"ketchup": "ketchup",
|
|
||||||
"ksoloti-pr": "ksoloti-pr",
|
|
||||||
"lanzaboote": "lanzaboote",
|
|
||||||
"nixos-hardware": "nixos-hardware",
|
|
||||||
"nixpkgs": "nixpkgs_4",
|
|
||||||
"nixpkgs-unstable": "nixpkgs-unstable",
|
|
||||||
"syntax-renderer": "syntax-renderer",
|
|
||||||
"tonearm": "tonearm",
|
|
||||||
"turny": "turny",
|
|
||||||
"voidauth": "voidauth",
|
|
||||||
"workout-sync": "workout-sync"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"rust-overlay": {
|
|
||||||
"inputs": {
|
|
||||||
"nixpkgs": [
|
|
||||||
"lanzaboote",
|
|
||||||
"nixpkgs"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"locked": {
|
|
||||||
"lastModified": 1771125043,
|
|
||||||
"narHash": "sha256-ldf/s49n6rOAxl7pYLJGGS1N/assoHkCOWdEdLyNZkc=",
|
|
||||||
"owner": "oxalica",
|
|
||||||
"repo": "rust-overlay",
|
|
||||||
"rev": "4912f951a26dc8142b176be2c2ad834319dc06e8",
|
|
||||||
"type": "github"
|
|
||||||
},
|
|
||||||
"original": {
|
|
||||||
"owner": "oxalica",
|
|
||||||
"repo": "rust-overlay",
|
|
||||||
"type": "github"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"stable": {
|
|
||||||
"locked": {
|
|
||||||
"lastModified": 1750133334,
|
|
||||||
"narHash": "sha256-urV51uWH7fVnhIvsZIELIYalMYsyr2FCalvlRTzqWRw=",
|
|
||||||
"owner": "NixOS",
|
|
||||||
"repo": "nixpkgs",
|
|
||||||
"rev": "36ab78dab7da2e4e27911007033713bab534187b",
|
|
||||||
"type": "github"
|
|
||||||
},
|
|
||||||
"original": {
|
|
||||||
"owner": "NixOS",
|
|
||||||
"ref": "nixos-25.05",
|
|
||||||
"repo": "nixpkgs",
|
|
||||||
"type": "github"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"syntax-renderer": {
|
|
||||||
"flake": false,
|
|
||||||
"locked": {
|
|
||||||
"lastModified": 1740962877,
|
|
||||||
"narHash": "sha256-mmGXYerUnxuTqHEWSueLgvkF4pjo1dfIQ+5QtM/JeJY=",
|
|
||||||
"owner": "~repomaa",
|
|
||||||
"repo": "syntax-renderer",
|
|
||||||
"rev": "2ddbeb7583302ae4b2775686c46826fc8a032e6a",
|
|
||||||
"type": "sourcehut"
|
|
||||||
},
|
|
||||||
"original": {
|
|
||||||
"owner": "~repomaa",
|
|
||||||
"repo": "syntax-renderer",
|
|
||||||
"type": "sourcehut"
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"systems": {
|
"systems": {
|
||||||
@@ -760,137 +241,6 @@
|
|||||||
"repo": "default",
|
"repo": "default",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
}
|
}
|
||||||
},
|
|
||||||
"systems_3": {
|
|
||||||
"locked": {
|
|
||||||
"lastModified": 1681028828,
|
|
||||||
"narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=",
|
|
||||||
"owner": "nix-systems",
|
|
||||||
"repo": "default",
|
|
||||||
"rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e",
|
|
||||||
"type": "github"
|
|
||||||
},
|
|
||||||
"original": {
|
|
||||||
"owner": "nix-systems",
|
|
||||||
"repo": "default",
|
|
||||||
"type": "github"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"systems_4": {
|
|
||||||
"locked": {
|
|
||||||
"lastModified": 1681028828,
|
|
||||||
"narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=",
|
|
||||||
"owner": "nix-systems",
|
|
||||||
"repo": "default",
|
|
||||||
"rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e",
|
|
||||||
"type": "github"
|
|
||||||
},
|
|
||||||
"original": {
|
|
||||||
"owner": "nix-systems",
|
|
||||||
"repo": "default",
|
|
||||||
"type": "github"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"systems_5": {
|
|
||||||
"locked": {
|
|
||||||
"lastModified": 1681028828,
|
|
||||||
"narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=",
|
|
||||||
"owner": "nix-systems",
|
|
||||||
"repo": "default",
|
|
||||||
"rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e",
|
|
||||||
"type": "github"
|
|
||||||
},
|
|
||||||
"original": {
|
|
||||||
"owner": "nix-systems",
|
|
||||||
"repo": "default",
|
|
||||||
"type": "github"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"tonearm": {
|
|
||||||
"inputs": {
|
|
||||||
"flake-utils": "flake-utils_5",
|
|
||||||
"nixpkgs": [
|
|
||||||
"nixpkgs"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"locked": {
|
|
||||||
"lastModified": 1769118914,
|
|
||||||
"narHash": "sha256-ASM7MVDWxT+BBtcAJ1z8XNjyNdL5E1Kc0miCWIepf+o=",
|
|
||||||
"rev": "68ea2190d1b37f9030b7586d2030f9dc48915a85",
|
|
||||||
"type": "tarball",
|
|
||||||
"url": "https://codeberg.org/api/v1/repos/dergs/Tonearm/archive/68ea2190d1b37f9030b7586d2030f9dc48915a85.tar.gz"
|
|
||||||
},
|
|
||||||
"original": {
|
|
||||||
"type": "tarball",
|
|
||||||
"url": "https://codeberg.org/dergs/Tonearm/archive/v1.0.0.tar.gz"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"turny": {
|
|
||||||
"inputs": {
|
|
||||||
"flake-parts": [
|
|
||||||
"flake-parts"
|
|
||||||
],
|
|
||||||
"nixpkgs": [
|
|
||||||
"nixpkgs"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"locked": {
|
|
||||||
"lastModified": 1752874301,
|
|
||||||
"narHash": "sha256-A6IZz46Lfopm5UhMtFfBDimepEUt9lGwhWoEIEQHsgk=",
|
|
||||||
"owner": "~repomaa",
|
|
||||||
"repo": "turny",
|
|
||||||
"rev": "133c05151e77616c7973c1c1038506b2fdee8eab",
|
|
||||||
"type": "sourcehut"
|
|
||||||
},
|
|
||||||
"original": {
|
|
||||||
"owner": "~repomaa",
|
|
||||||
"repo": "turny",
|
|
||||||
"type": "sourcehut"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"voidauth": {
|
|
||||||
"inputs": {
|
|
||||||
"flake-parts": [
|
|
||||||
"flake-parts"
|
|
||||||
],
|
|
||||||
"nixpkgs": [
|
|
||||||
"nixpkgs-unstable"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"locked": {
|
|
||||||
"lastModified": 1771599016,
|
|
||||||
"narHash": "sha256-dSOaOlixvFB57trGkqqS1MSCEbeBT13S3sfZK3Hz+bs=",
|
|
||||||
"owner": "repomaa",
|
|
||||||
"repo": "voidauth",
|
|
||||||
"rev": "9823e2de56e12f33df8e8eba79c4f9e891d31842",
|
|
||||||
"type": "github"
|
|
||||||
},
|
|
||||||
"original": {
|
|
||||||
"owner": "repomaa",
|
|
||||||
"ref": "feat/nix-packaging",
|
|
||||||
"repo": "voidauth",
|
|
||||||
"type": "github"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"workout-sync": {
|
|
||||||
"inputs": {
|
|
||||||
"nixpkgs": [
|
|
||||||
"nixpkgs"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"locked": {
|
|
||||||
"lastModified": 1750085642,
|
|
||||||
"narHash": "sha256-u+A06S7VEMBQskn6XhGCWYTiD6XBOPJ5ZzohDaRskbw=",
|
|
||||||
"owner": "~repomaa",
|
|
||||||
"repo": "workout-sync",
|
|
||||||
"rev": "6d8941e1e798eb326169f30c185289b8ed6b0702",
|
|
||||||
"type": "sourcehut"
|
|
||||||
},
|
|
||||||
"original": {
|
|
||||||
"owner": "~repomaa",
|
|
||||||
"repo": "workout-sync",
|
|
||||||
"type": "sourcehut"
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"root": "root",
|
"root": "root",
|
||||||
|
|||||||
208
flake.nix
208
flake.nix
@@ -1,213 +1,27 @@
|
|||||||
{
|
{
|
||||||
inputs = {
|
inputs = {
|
||||||
|
nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
|
||||||
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.url = "github:NixOS/nixpkgs/nixos-25.11";
|
|
||||||
gtrackmap = {
|
gtrackmap = {
|
||||||
url = "github:gtrackmap/gtrackmap";
|
url = "github:gtrackmap/gtrackmap";
|
||||||
inputs.nixpkgs.follows = "nixpkgs";
|
inputs.nixpkgs.follows = "nixpkgs";
|
||||||
};
|
};
|
||||||
lanzaboote.url = "github:nix-community/lanzaboote";
|
|
||||||
nixos-hardware.url = "github:NixOS/nixos-hardware/master";
|
|
||||||
home-manager = {
|
|
||||||
url = "github:nix-community/home-manager/release-25.11";
|
|
||||||
inputs.nixpkgs.follows = "nixpkgs";
|
|
||||||
};
|
};
|
||||||
ketchup = {
|
outputs = { flake-parts, nixpkgs, gtrackmap, ... }@inputs: (
|
||||||
url = "github:repomaa/ketchup";
|
flake-parts.lib.mkFlake { inherit inputs; } {
|
||||||
inputs.nixpkgs.follows = "nixpkgs";
|
flake.nixosConfigurations = {
|
||||||
};
|
freun-dev = nixpkgs.lib.nixosSystem {
|
||||||
workout-sync = {
|
system = "x86_64-linux";
|
||||||
url = "sourcehut:~repomaa/workout-sync";
|
specialArgs = inputs;
|
||||||
inputs.nixpkgs.follows = "nixpkgs";
|
modules = [
|
||||||
};
|
./hosts/freun-dev
|
||||||
hastebin = {
|
gtrackmap.nixosModules.default
|
||||||
url = "sourcehut:~repomaa/hastebin";
|
];
|
||||||
inputs.nixpkgs.follows = "nixpkgs";
|
|
||||||
};
|
|
||||||
ksoloti-pr.url = "github:repomaa/nixpkgs/pkg/ksoloti";
|
|
||||||
agenix = {
|
|
||||||
url = "github:ryantm/agenix";
|
|
||||||
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";
|
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
outputs =
|
|
||||||
{
|
|
||||||
flake-parts,
|
|
||||||
agenix,
|
|
||||||
nixpkgs,
|
|
||||||
self,
|
|
||||||
colmena,
|
|
||||||
...
|
|
||||||
}@inputs:
|
|
||||||
flake-parts.lib.mkFlake { inherit inputs; } (
|
|
||||||
{ withSystem, ... }:
|
|
||||||
let
|
|
||||||
ssh.publicKeys = {
|
|
||||||
yubikey = "ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBLIUkESu5NnBi1M0+ZjYrkp6/rIFuwc3aguspf98jmOydNce6l65cnS3GRzc9oWx4lu11ahi87ZuE+pYV+gaHm4=";
|
|
||||||
builder = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIFuQaA6JKCOfsfUBI5tzoiYe3tdpLdPfVzeyByx/149C";
|
|
||||||
};
|
|
||||||
specialArgs = { inherit inputs ssh self; };
|
|
||||||
|
|
||||||
in
|
|
||||||
{
|
|
||||||
systems = [
|
systems = [
|
||||||
"x86_64-linux"
|
"x86_64-linux"
|
||||||
"x86_64-darwin"
|
|
||||||
"aarch64-linux"
|
|
||||||
"aarch64-darwin"
|
|
||||||
];
|
];
|
||||||
perSystem =
|
|
||||||
{ pkgs, system, ... }:
|
|
||||||
{
|
|
||||||
devShells.default = pkgs.mkShell {
|
|
||||||
packages = with pkgs; [
|
|
||||||
agenix.packages.${system}.default
|
|
||||||
colmena.packages.${system}.colmena
|
|
||||||
colmena.packages.${system}.manual
|
|
||||||
(writeShellScriptBin "build" ''
|
|
||||||
colmena build --keep-result "$@"
|
|
||||||
'')
|
|
||||||
(writeShellScriptBin "apply" ''
|
|
||||||
colmena apply --keep-result "$@"
|
|
||||||
'')
|
|
||||||
(writeShellScriptBin "apply-local" ''
|
|
||||||
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;
|
|
||||||
|
|
||||||
dockerImages =
|
|
||||||
nixpkgs.lib.genAttrs
|
|
||||||
[
|
|
||||||
"x86_64-linux"
|
|
||||||
"aarch64-linux"
|
|
||||||
]
|
|
||||||
(
|
|
||||||
system:
|
|
||||||
withSystem system (
|
|
||||||
{ pkgs, ... }:
|
|
||||||
{
|
|
||||||
node =
|
|
||||||
let
|
|
||||||
setupDirs = pkgs.runCommand "setup-dirs" { } ''
|
|
||||||
mkdir -p $out/tmp $out/root $out/var/tmp
|
|
||||||
chmod 1777 $out/tmp $out/var/tmp
|
|
||||||
'';
|
|
||||||
in
|
|
||||||
pkgs.dockerTools.buildLayeredImage {
|
|
||||||
name = "node";
|
|
||||||
tag = "latest";
|
|
||||||
contents = with pkgs; [
|
|
||||||
nodejs
|
|
||||||
nix
|
|
||||||
busybox
|
|
||||||
bash
|
|
||||||
skopeo
|
|
||||||
cacert
|
|
||||||
git
|
|
||||||
setupDirs
|
|
||||||
(writeTextFile {
|
|
||||||
name = "etc-nix-nix-conf";
|
|
||||||
destination = "/etc/nix/nix.conf";
|
|
||||||
text = ''
|
|
||||||
build-users-group =
|
|
||||||
experimental-features = nix-command flakes
|
|
||||||
'';
|
|
||||||
})
|
|
||||||
];
|
|
||||||
config = {
|
|
||||||
Env = [
|
|
||||||
"SSL_CERT_FILE=/etc/ssl/certs/ca-bundle.crt"
|
|
||||||
"NODE_EXTRA_CA_CERTS=/etc/ssl/certs/ca-bundle.crt"
|
|
||||||
"HOME=/root"
|
|
||||||
];
|
|
||||||
};
|
|
||||||
};
|
|
||||||
}
|
|
||||||
)
|
|
||||||
);
|
|
||||||
colmenaHive = colmena.lib.makeHive self.outputs.colmena;
|
|
||||||
|
|
||||||
colmena =
|
|
||||||
let
|
|
||||||
deploymentOptions = {
|
|
||||||
freun-dev = {
|
|
||||||
targetHost = "freun.dev";
|
|
||||||
buildOnTarget = true;
|
|
||||||
};
|
|
||||||
radish = {
|
|
||||||
allowLocalDeployment = true;
|
|
||||||
targetHost = null;
|
|
||||||
};
|
|
||||||
turny = {
|
|
||||||
targetHost = "10.10.1.233";
|
|
||||||
};
|
|
||||||
};
|
|
||||||
in
|
|
||||||
{
|
|
||||||
meta = {
|
|
||||||
inherit specialArgs;
|
|
||||||
|
|
||||||
nixpkgs = import nixpkgs {
|
|
||||||
system = "x86_64-linux";
|
|
||||||
overlays = [ ];
|
|
||||||
};
|
|
||||||
};
|
|
||||||
}
|
|
||||||
// builtins.mapAttrs (name: config: {
|
|
||||||
imports = config._module.args.modules;
|
|
||||||
deployment = if builtins.hasAttr name deploymentOptions then deploymentOptions.${name} else { };
|
|
||||||
}) self.nixosConfigurations;
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
Binary file not shown.
|
Before Width: | Height: | Size: 1.1 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 5.9 KiB |
@@ -1,725 +0,0 @@
|
|||||||
{
|
|
||||||
config,
|
|
||||||
lib,
|
|
||||||
pkgs,
|
|
||||||
pkgs-unstable,
|
|
||||||
inputs,
|
|
||||||
self,
|
|
||||||
...
|
|
||||||
}:
|
|
||||||
{
|
|
||||||
imports = [
|
|
||||||
../gnome
|
|
||||||
./dnote.nix
|
|
||||||
../modules/zed
|
|
||||||
./secrets.nix
|
|
||||||
inputs.hastebin.nixosModules.hm
|
|
||||||
inputs.agenix.homeManagerModules.default
|
|
||||||
];
|
|
||||||
|
|
||||||
# This value determines the Home Manager release that your configuration is
|
|
||||||
# compatible with. This helps avoid breakage when a new Home Manager release
|
|
||||||
# introduces backwards incompatible changes.
|
|
||||||
#
|
|
||||||
# You should not change this value, even if you update Home Manager. If you do
|
|
||||||
# want to update the value, then make sure to first check the Home Manager
|
|
||||||
# release notes.
|
|
||||||
home.stateVersion = "23.11"; # Please read the comment before changing.
|
|
||||||
|
|
||||||
home.packages = with pkgs; [
|
|
||||||
htop
|
|
||||||
gnupg
|
|
||||||
pkgs-unstable.yubioath-flutter
|
|
||||||
pkgs-unstable.yubikey-manager
|
|
||||||
gcc
|
|
||||||
sqlite
|
|
||||||
noto-fonts
|
|
||||||
noto-fonts-cjk-sans
|
|
||||||
noto-fonts-color-emoji
|
|
||||||
source-sans-pro
|
|
||||||
mosh
|
|
||||||
docker-compose
|
|
||||||
signal-desktop
|
|
||||||
cargo
|
|
||||||
blanket
|
|
||||||
wl-clipboard
|
|
||||||
gnumeric
|
|
||||||
gh
|
|
||||||
neovim-remote
|
|
||||||
pkgs-unstable.gradia
|
|
||||||
crystal
|
|
||||||
shards
|
|
||||||
moreutils
|
|
||||||
keymapp
|
|
||||||
gnumake
|
|
||||||
tig
|
|
||||||
jq
|
|
||||||
yt-dlp
|
|
||||||
ffmpeg
|
|
||||||
otp
|
|
||||||
manix
|
|
||||||
(writeShellScriptBin "fd" ''
|
|
||||||
${fd}/bin/fd -H "$@"
|
|
||||||
'')
|
|
||||||
pkgs-unstable.rpi-imager
|
|
||||||
picocom
|
|
||||||
imagemagick
|
|
||||||
ghostscript
|
|
||||||
inkscape
|
|
||||||
jless
|
|
||||||
scribus
|
|
||||||
dnscontrol
|
|
||||||
protonmail-bridge
|
|
||||||
hydroxide
|
|
||||||
imapsync
|
|
||||||
nixfmt-rfc-style
|
|
||||||
tree
|
|
||||||
virt-manager
|
|
||||||
pkgs-unstable.ncspot
|
|
||||||
pkgs-unstable.devbox
|
|
||||||
pkgs-unstable.feishin
|
|
||||||
openscad
|
|
||||||
pkgs-unstable.walker
|
|
||||||
pkgs-unstable.shairport-sync-airplay2
|
|
||||||
(writeShellScriptBin "pw" ''
|
|
||||||
${lib.getExe rbw} ls --fields 'id,folder,name' | \
|
|
||||||
${lib.getExe gawk} -F '\t' '{print $1 "\t" ($2 == "" ? "" : $2 "/") $3}' | \
|
|
||||||
${lib.getExe pkgs-unstable.walker} -d -l 2 | \
|
|
||||||
xargs ${lib.getExe rbw} get "$@" | ${lib.getExe' wl-clipboard "wl-copy"}
|
|
||||||
'')
|
|
||||||
(google-fonts.override { fonts = [ "Tajawal" ]; })
|
|
||||||
pkgs-unstable.opencode
|
|
||||||
(writeShellScriptBin "nr" ''
|
|
||||||
${lib.getExe nix} run "nixpkgs#''${1}" "$@"
|
|
||||||
'')
|
|
||||||
pkgs-unstable.tidal-hifi
|
|
||||||
inputs.tonearm.packages.${pkgs.stdenv.hostPlatform.system}.tonearm
|
|
||||||
];
|
|
||||||
|
|
||||||
programs = {
|
|
||||||
nh = {
|
|
||||||
enable = true;
|
|
||||||
flake = self;
|
|
||||||
};
|
|
||||||
dnote.enable = true;
|
|
||||||
home-manager.enable = true;
|
|
||||||
bat = {
|
|
||||||
enable = true;
|
|
||||||
extraPackages = with pkgs.bat-extras; [
|
|
||||||
batdiff
|
|
||||||
batwatch
|
|
||||||
];
|
|
||||||
config = {
|
|
||||||
pager = "less -FR";
|
|
||||||
};
|
|
||||||
};
|
|
||||||
direnv = {
|
|
||||||
enable = true;
|
|
||||||
nix-direnv.enable = true;
|
|
||||||
enableZshIntegration = true;
|
|
||||||
};
|
|
||||||
mpv = {
|
|
||||||
enable = true;
|
|
||||||
config = {
|
|
||||||
hwdec = "auto-safe";
|
|
||||||
vo = "gpu";
|
|
||||||
profile = "gpu-hq";
|
|
||||||
gpu-context = "wayland";
|
|
||||||
};
|
|
||||||
};
|
|
||||||
kitty = {
|
|
||||||
enable = true;
|
|
||||||
font = {
|
|
||||||
name = "IosevkaTerm NFM";
|
|
||||||
size = 14;
|
|
||||||
};
|
|
||||||
shellIntegration.enableZshIntegration = true;
|
|
||||||
themeFile = "Tomorrow_Night";
|
|
||||||
settings = {
|
|
||||||
hide_window_decorations = true;
|
|
||||||
enabled_layouts = "splits,stack";
|
|
||||||
};
|
|
||||||
keybindings = {
|
|
||||||
"kitty_mod+q" = "";
|
|
||||||
"kitty_mod+w" = "";
|
|
||||||
"kitty_mod+t" = "new_tab_with_cwd";
|
|
||||||
"kitty_mod+tab" = "next_tab";
|
|
||||||
"kitty_mod+enter" = "launch --location=hsplit --cwd=current";
|
|
||||||
"kitty_mod+space" = "launch --location=vsplit --cwd=current";
|
|
||||||
"kitty_mod+h" = "neighboring_window left";
|
|
||||||
"kitty_mod+l" = "neighboring_window right";
|
|
||||||
"kitty_mod+k" = "neighboring_window up";
|
|
||||||
"kitty_mod+j" = "neighboring_window down";
|
|
||||||
"kitty_mod+1" = "goto_tab 1";
|
|
||||||
"kitty_mod+2" = "goto_tab 2";
|
|
||||||
"kitty_mod+3" = "goto_tab 3";
|
|
||||||
"kitty_mod+4" = "goto_tab 4";
|
|
||||||
"kitty_mod+5" = "goto_tab 5";
|
|
||||||
"kitty_mod+6" = "goto_tab 6";
|
|
||||||
"kitty_mod+7" = "goto_tab 7";
|
|
||||||
"kitty_mod+8" = "goto_tab 8";
|
|
||||||
"kitty_mod+9" = "goto_tab 9";
|
|
||||||
"kitty_mod+0" = "goto_tab 10";
|
|
||||||
"kitty_mod+f" = "toggle_layout stack";
|
|
||||||
"kitty_mod+/" = "show_scrollback";
|
|
||||||
"ctrl+alt+h" = "move_window left";
|
|
||||||
"ctrl+alt+l" = "move_window right";
|
|
||||||
"ctrl+alt+k" = "move_window up";
|
|
||||||
"ctrl+alt+j" = "move_window down";
|
|
||||||
"ctrl+alt+enter" = "layout_action rotate";
|
|
||||||
};
|
|
||||||
};
|
|
||||||
vivaldi.enable = true;
|
|
||||||
git = {
|
|
||||||
enable = true;
|
|
||||||
settings = {
|
|
||||||
alias = {
|
|
||||||
st = "status";
|
|
||||||
co = "checkout";
|
|
||||||
b = "branch";
|
|
||||||
};
|
|
||||||
pull = {
|
|
||||||
rebase = "true";
|
|
||||||
};
|
|
||||||
push = {
|
|
||||||
autoSetupRemote = true;
|
|
||||||
};
|
|
||||||
init = {
|
|
||||||
defaultBranch = "main";
|
|
||||||
};
|
|
||||||
user = {
|
|
||||||
name = "Joakim Repomaa";
|
|
||||||
signingKey = "F0AF1CE34733B22317A8937D05557F53CD3C6458";
|
|
||||||
};
|
|
||||||
commit.gpgSign = true;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
gpg = {
|
|
||||||
enable = true;
|
|
||||||
};
|
|
||||||
zsh = {
|
|
||||||
enable = true;
|
|
||||||
enableVteIntegration = true;
|
|
||||||
cdpath = [
|
|
||||||
"${config.xdg.configHome}/home-manager"
|
|
||||||
];
|
|
||||||
defaultKeymap = "viins";
|
|
||||||
dirHashes = {
|
|
||||||
hm = "${config.xdg.configHome}/home-manager";
|
|
||||||
};
|
|
||||||
history = {
|
|
||||||
path = "${config.home.homeDirectory}/.cache/zsh/history";
|
|
||||||
save = 100000;
|
|
||||||
size = 100000;
|
|
||||||
};
|
|
||||||
initContent = ''
|
|
||||||
. "${config.xdg.configHome}/zsh/init"
|
|
||||||
. "${config.age.secrets.context7.path}"
|
|
||||||
'';
|
|
||||||
};
|
|
||||||
lazygit =
|
|
||||||
let
|
|
||||||
getBaseBranch = pkgs.writeShellScriptBin "git-base-branch" ''
|
|
||||||
current_branch="$(git rev-parse --abbrev-ref HEAD)"
|
|
||||||
if [[ "$current_branch" =~ -review$ ]]; then
|
|
||||||
echo "''${current_branch%-review}"
|
|
||||||
else
|
|
||||||
git config get init.defaultBranch
|
|
||||||
fi
|
|
||||||
'';
|
|
||||||
escapeGoTemplate = builtins.replaceStrings [ "{{" "}}" ] [ ''{{"{{"}}'' ''{{"}}"}}'' ];
|
|
||||||
in
|
|
||||||
{
|
|
||||||
enable = true;
|
|
||||||
settings = {
|
|
||||||
gui = {
|
|
||||||
nerdFontsVersion = "3";
|
|
||||||
};
|
|
||||||
git = {
|
|
||||||
showUntrackedFiles = "all";
|
|
||||||
branchLogCmd = "git log {{branchName}} --first-parent --color=always --pretty=format:'%Cgreen%h%Creset %Cblue%aN%Creset %C(cyan)%<(14)%ar%Creset %s' --abbrev-commit";
|
|
||||||
overrideGpg = true;
|
|
||||||
};
|
|
||||||
os = {
|
|
||||||
edit = "\${EDITOR} -- {{filename}}";
|
|
||||||
editAtLine = "\${EDITOR} -- {{filename}}:{{line}}";
|
|
||||||
editAtLineAndWait = "\${EDITOR} --wait -- {{filename}}:{{line}}";
|
|
||||||
openDirInEditor = "\${EDITOR} -- {{dir}}";
|
|
||||||
};
|
|
||||||
promptToReturnFromSubprocess = false;
|
|
||||||
keybinding = {
|
|
||||||
universal = {
|
|
||||||
nextItem = "<disabled>";
|
|
||||||
prevItem = "<disabled>";
|
|
||||||
};
|
|
||||||
commits = {
|
|
||||||
moveDownCommit = "<down>";
|
|
||||||
moveUpCommit = "<up>";
|
|
||||||
};
|
|
||||||
};
|
|
||||||
customCommands = [
|
|
||||||
{
|
|
||||||
key = "<c-r>";
|
|
||||||
context = "global";
|
|
||||||
command = ''
|
|
||||||
git push --force-with-lease --set-upstream origin "{{.SelectedLocalBranch.Name}}" &&
|
|
||||||
gh pr create --title "{{.SelectedLocalBranch.Name}}" -B "$(${lib.getExe getBaseBranch})" --fill ||
|
|
||||||
(git log --reverse --no-merges --pretty='- %s' master..HEAD | gh pr edit --body-file -);
|
|
||||||
gh pr view --web
|
|
||||||
'';
|
|
||||||
}
|
|
||||||
{
|
|
||||||
key = "N";
|
|
||||||
context = "localBranches";
|
|
||||||
prompts = [
|
|
||||||
{
|
|
||||||
type = "input";
|
|
||||||
title = "New Branch Name:";
|
|
||||||
key = "BranchName";
|
|
||||||
initialValue = "{{.SelectedLocalBranch.Name}}-review";
|
|
||||||
}
|
|
||||||
];
|
|
||||||
command = ''
|
|
||||||
git checkout -b {{.Form.BranchName | quote}}
|
|
||||||
'';
|
|
||||||
}
|
|
||||||
{
|
|
||||||
key = "G";
|
|
||||||
context = "localBranches";
|
|
||||||
prompts = [
|
|
||||||
{
|
|
||||||
type = "menuFromCommand";
|
|
||||||
title = "PR:";
|
|
||||||
key = "pr";
|
|
||||||
command = escapeGoTemplate "gh pr list --search '-author:@me' --json number,title,author,updatedAt -t '{{range .}}{{tablerow .number .title .author.login}}{{end}}'";
|
|
||||||
filter = "(?<pr_number>[0-9]+)(?<rest>.*)";
|
|
||||||
labelFormat = "{{ .rest }}";
|
|
||||||
valueFormat = "{{ .pr_number }}";
|
|
||||||
}
|
|
||||||
];
|
|
||||||
command = ''
|
|
||||||
gh pr checkout {{.Form.pr | quote}}
|
|
||||||
'';
|
|
||||||
}
|
|
||||||
];
|
|
||||||
};
|
|
||||||
};
|
|
||||||
obs-studio.enable = true;
|
|
||||||
ssh = {
|
|
||||||
enable = true;
|
|
||||||
enableDefaultConfig = false;
|
|
||||||
matchBlocks = {
|
|
||||||
"*" = {
|
|
||||||
controlMaster = "auto";
|
|
||||||
controlPath = "${config.home.homeDirectory}/.ssh/masters-control/%r@%h:%p";
|
|
||||||
controlPersist = "1h";
|
|
||||||
forwardAgent = false;
|
|
||||||
addKeysToAgent = "no";
|
|
||||||
compression = false;
|
|
||||||
serverAliveInterval = 0;
|
|
||||||
serverAliveCountMax = 3;
|
|
||||||
hashKnownHosts = false;
|
|
||||||
userKnownHostsFile = "${config.home.homeDirectory}/.ssh/known_hosts";
|
|
||||||
setEnv = {
|
|
||||||
TERM = "screen-256color";
|
|
||||||
};
|
|
||||||
};
|
|
||||||
"apu" = {
|
|
||||||
hostname = "apu.tempel-vibes.ts.net";
|
|
||||||
user = "root";
|
|
||||||
};
|
|
||||||
};
|
|
||||||
};
|
|
||||||
spotify-player = {
|
|
||||||
enable = true;
|
|
||||||
settings = {
|
|
||||||
enable_streaming = "Always";
|
|
||||||
theme = "tomorrow_night";
|
|
||||||
copy_command = "wl-copy";
|
|
||||||
};
|
|
||||||
themes = [
|
|
||||||
{
|
|
||||||
name = "tomorrow_night";
|
|
||||||
palette = {
|
|
||||||
background = "#1d1f21";
|
|
||||||
foreground = "#c5c8c6";
|
|
||||||
black = "#000000";
|
|
||||||
red = "#cc6666";
|
|
||||||
green = "#b5bd68";
|
|
||||||
yellow = "#f0c674";
|
|
||||||
blue = "#81a2be";
|
|
||||||
magenta = "#b294bb";
|
|
||||||
cyan = "#8abeb7";
|
|
||||||
white = "#ffffff";
|
|
||||||
bright_black = "#000000";
|
|
||||||
bright_red = "#cc6666";
|
|
||||||
bright_green = "#b5bd68";
|
|
||||||
bright_yellow = "#f0c674";
|
|
||||||
bright_blue = "#81a2be";
|
|
||||||
bright_magenta = "#b294bb";
|
|
||||||
bright_cyan = "#8abeb7";
|
|
||||||
bright_white = "#ffffff";
|
|
||||||
};
|
|
||||||
component_style = {
|
|
||||||
playback_metadata = {
|
|
||||||
fg = "#8abeb7";
|
|
||||||
};
|
|
||||||
playback_progress_bar = {
|
|
||||||
bg = "#1d1f21";
|
|
||||||
fg = "#c5c8c6";
|
|
||||||
};
|
|
||||||
};
|
|
||||||
}
|
|
||||||
];
|
|
||||||
};
|
|
||||||
neovide = {
|
|
||||||
enable = true;
|
|
||||||
settings = {
|
|
||||||
font = {
|
|
||||||
normal = [ "IosevkaTerm NFM" ];
|
|
||||||
size = 12.0;
|
|
||||||
};
|
|
||||||
fork = true;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
hastebin = {
|
|
||||||
enable = true;
|
|
||||||
settings = {
|
|
||||||
host = "https://bin.freun.dev";
|
|
||||||
auth_token_file = "${config.xdg.configHome}/hastebin/auth_token";
|
|
||||||
clipboard_command = "${pkgs.wl-copy-both}/bin/wl-copy";
|
|
||||||
default_renderers =
|
|
||||||
let
|
|
||||||
code = [
|
|
||||||
"js"
|
|
||||||
"ts"
|
|
||||||
"jsx"
|
|
||||||
"tsx"
|
|
||||||
"rs"
|
|
||||||
"nix"
|
|
||||||
"cr"
|
|
||||||
"ecr"
|
|
||||||
"rb"
|
|
||||||
"erb"
|
|
||||||
"yaml"
|
|
||||||
"yml"
|
|
||||||
"json"
|
|
||||||
"toml"
|
|
||||||
"html"
|
|
||||||
"xml"
|
|
||||||
"css"
|
|
||||||
"scss"
|
|
||||||
"sass"
|
|
||||||
"less"
|
|
||||||
"sql"
|
|
||||||
"sh"
|
|
||||||
];
|
|
||||||
in
|
|
||||||
lib.listToAttrs (
|
|
||||||
lib.map (name: {
|
|
||||||
inherit name;
|
|
||||||
value = "hl";
|
|
||||||
}) code
|
|
||||||
);
|
|
||||||
};
|
|
||||||
};
|
|
||||||
zed-editor = {
|
|
||||||
enable = true;
|
|
||||||
defaultEditor = true;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
gnome = {
|
|
||||||
keyboard.sources = [ "us+altgr-intl" ];
|
|
||||||
keybindings = {
|
|
||||||
builtin = {
|
|
||||||
screenshot-window = [ ];
|
|
||||||
show-screenshot-ui = [ ];
|
|
||||||
};
|
|
||||||
custom = [
|
|
||||||
{
|
|
||||||
binding = "Print";
|
|
||||||
command = "gradia --screenshot";
|
|
||||||
name = "Gradia";
|
|
||||||
}
|
|
||||||
{
|
|
||||||
binding = "<Alt>Print";
|
|
||||||
command = "kooha";
|
|
||||||
name = "Kooha";
|
|
||||||
}
|
|
||||||
];
|
|
||||||
};
|
|
||||||
power = {
|
|
||||||
powerButton = "hibernate";
|
|
||||||
};
|
|
||||||
extensions = {
|
|
||||||
paperwm = {
|
|
||||||
enable = true;
|
|
||||||
winprops = [
|
|
||||||
{
|
|
||||||
wm_class = "vivaldi-stable";
|
|
||||||
preferredWidth = "67%";
|
|
||||||
}
|
|
||||||
{
|
|
||||||
wm_class = "yubioath-flutter";
|
|
||||||
scratch_layer = true;
|
|
||||||
}
|
|
||||||
{
|
|
||||||
wm_class = "signal";
|
|
||||||
scratch_layer = true;
|
|
||||||
}
|
|
||||||
{
|
|
||||||
wm_class = "Slack";
|
|
||||||
scratch_layer = true;
|
|
||||||
}
|
|
||||||
{
|
|
||||||
wm_class = "Supersonic";
|
|
||||||
scratch_layer = true;
|
|
||||||
}
|
|
||||||
{
|
|
||||||
wm_class = "io.github.seadve.Kooha";
|
|
||||||
scratch_layer = true;
|
|
||||||
}
|
|
||||||
{
|
|
||||||
wm_class = "/.*/";
|
|
||||||
preferredWidth = "33";
|
|
||||||
}
|
|
||||||
];
|
|
||||||
keybindings = {
|
|
||||||
move-down = [
|
|
||||||
"<Control><Super>Down"
|
|
||||||
"<Shift><Super>j"
|
|
||||||
];
|
|
||||||
move-left = [
|
|
||||||
"<Control><Super>Left"
|
|
||||||
"<Shift><Super>h"
|
|
||||||
];
|
|
||||||
move-right = [
|
|
||||||
"<Control><Super>Right"
|
|
||||||
"<Shift><Super>l"
|
|
||||||
];
|
|
||||||
move-up = [
|
|
||||||
"<Control><Super>Up"
|
|
||||||
"<Shift><Super>k"
|
|
||||||
];
|
|
||||||
switch-down = [
|
|
||||||
"<Super>Down"
|
|
||||||
"<Super>j"
|
|
||||||
];
|
|
||||||
switch-left = [
|
|
||||||
"<Super>Left"
|
|
||||||
"<Super>h"
|
|
||||||
];
|
|
||||||
switch-right = [
|
|
||||||
"<Super>Right"
|
|
||||||
"<Super>l"
|
|
||||||
];
|
|
||||||
switch-up = [
|
|
||||||
"<Super>Up"
|
|
||||||
"<Super>k"
|
|
||||||
];
|
|
||||||
};
|
|
||||||
};
|
|
||||||
freon = {
|
|
||||||
enable = true;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
nightLight.enable = true;
|
|
||||||
};
|
|
||||||
|
|
||||||
fonts.fontconfig = {
|
|
||||||
enable = true;
|
|
||||||
defaultFonts = {
|
|
||||||
emoji = [ "Noto Color Emoji" ];
|
|
||||||
monospace = [ "IosevkaTerm NFM" ];
|
|
||||||
sansSerif = [ "Source Sans Pro" ];
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
targets.genericLinux.enable = true;
|
|
||||||
xdg.mime.enable = true;
|
|
||||||
|
|
||||||
xdg = {
|
|
||||||
enable = true;
|
|
||||||
configFile = {
|
|
||||||
tmux.source = dotfiles/tmux;
|
|
||||||
zsh.source = dotfiles/zsh;
|
|
||||||
"fd/ignore".text = ''
|
|
||||||
/.git/
|
|
||||||
'';
|
|
||||||
"vivaldi/NativeMessagingHosts/ff2mpv.json".text = builtins.toJSON {
|
|
||||||
name = "ff2mpv";
|
|
||||||
description = "ff2mpv's external manifest";
|
|
||||||
path = "${pkgs.ff2mpv-rust}/bin/ff2mpv-rust";
|
|
||||||
type = "stdio";
|
|
||||||
allowed_origins = [
|
|
||||||
"chrome-extension://ephjcajbkgplkjmelpglennepbpmdpjg/"
|
|
||||||
];
|
|
||||||
};
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
# Home Manager can also manage your environment variables through
|
|
||||||
# 'home.sessionVariables'. If you don't want to manage your shell through Home
|
|
||||||
# Manager then you have to manually source 'hm-session-vars.sh' located at
|
|
||||||
# either
|
|
||||||
#
|
|
||||||
# ~/.nix-profile/etc/profile.d/hm-session-vars.sh
|
|
||||||
#
|
|
||||||
# or
|
|
||||||
#
|
|
||||||
# ~/.local/state/nix/profiles/profile/etc/profile.d/hm-session-vars.sh
|
|
||||||
#
|
|
||||||
# or
|
|
||||||
#
|
|
||||||
# /etc/profiles/per-user/jokke/etc/profile.d/hm-session-vars.sh
|
|
||||||
#
|
|
||||||
systemd.user.sessionVariables = {
|
|
||||||
NIXOS_OZONE_WL = 1;
|
|
||||||
NVIM_LISTEN_ADDRESS = "$XDG_RUNTIME_DIR/nvimsocket";
|
|
||||||
PAGER = "bat --paging=always --style=plain";
|
|
||||||
MANPAGER = "sh -c 'col -bx | bat -l man -p'";
|
|
||||||
MANROFFOPT = "-c";
|
|
||||||
DO_NOT_TRACK = 1;
|
|
||||||
};
|
|
||||||
|
|
||||||
home.shellAliases = {
|
|
||||||
_ = "sudo";
|
|
||||||
icr = "crystal i";
|
|
||||||
hm = "home-manager";
|
|
||||||
chat = "ssh root@ipv4.jokke.space pkill mosh; mosh weechat@ipv4.jokke.space";
|
|
||||||
wget = " wget --content-disposition";
|
|
||||||
pj = "jq | bat -l json";
|
|
||||||
ls = "ls --color=auto";
|
|
||||||
};
|
|
||||||
|
|
||||||
services.gpg-agent = with pkgs; {
|
|
||||||
enable = true;
|
|
||||||
enableSshSupport = true;
|
|
||||||
pinentry.package = pinentry-gnome3;
|
|
||||||
};
|
|
||||||
|
|
||||||
systemd.user.services.shairport-sync = {
|
|
||||||
Unit = {
|
|
||||||
Description = "AirPlay audio server";
|
|
||||||
After = [
|
|
||||||
"pipewire-pulse.service"
|
|
||||||
"network.target"
|
|
||||||
];
|
|
||||||
};
|
|
||||||
Service = {
|
|
||||||
ExecStart = "${lib.getExe pkgs-unstable.shairport-sync-airplay2} -- pw";
|
|
||||||
Restart = "on-failure";
|
|
||||||
};
|
|
||||||
Install = {
|
|
||||||
WantedBy = [ "graphical-session.target" ];
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
programs.gpg.scdaemonSettings = {
|
|
||||||
disable-ccid = true;
|
|
||||||
};
|
|
||||||
|
|
||||||
programs.rbw.enable = true;
|
|
||||||
programs.rclone.enable = true;
|
|
||||||
programs.firefox.enable = true;
|
|
||||||
|
|
||||||
xdg.configFile."opencode/opencode.jsonc".text = builtins.toJSON {
|
|
||||||
"$schema" = "https://opencode.ai/config.json";
|
|
||||||
model = "opencode/kimi-k2.5";
|
|
||||||
small_model = "opencode/minimax-m2.1";
|
|
||||||
agent = {
|
|
||||||
explore.model = "opencode/minimax-m2.1";
|
|
||||||
};
|
|
||||||
lsp = {
|
|
||||||
ruby-lsp = {
|
|
||||||
initialization = {
|
|
||||||
enabledFeatures = {
|
|
||||||
codeActions = true;
|
|
||||||
codeLens = true;
|
|
||||||
completion = true;
|
|
||||||
definition = true;
|
|
||||||
diagnostics = true;
|
|
||||||
documentHighlights = true;
|
|
||||||
documentLink = true;
|
|
||||||
documentSymbols = true;
|
|
||||||
foldingRanges = true;
|
|
||||||
formatting = false;
|
|
||||||
hover = true;
|
|
||||||
inlayHint = true;
|
|
||||||
onTypeFormatting = true;
|
|
||||||
selectionRanges = true;
|
|
||||||
semanticHighlighting = true;
|
|
||||||
signatureHelp = true;
|
|
||||||
typeHierarchy = true;
|
|
||||||
workspaceSymbol = true;
|
|
||||||
};
|
|
||||||
linters = [ "standard" ];
|
|
||||||
};
|
|
||||||
extensions = [
|
|
||||||
".rb"
|
|
||||||
".erb"
|
|
||||||
".haml"
|
|
||||||
];
|
|
||||||
command = [
|
|
||||||
"bundle"
|
|
||||||
"exec"
|
|
||||||
"ruby-lsp"
|
|
||||||
"--lsp"
|
|
||||||
];
|
|
||||||
};
|
|
||||||
rubocop = {
|
|
||||||
command = [
|
|
||||||
"bundle"
|
|
||||||
"exec"
|
|
||||||
"rubocop"
|
|
||||||
"--lsp"
|
|
||||||
];
|
|
||||||
extensions = [
|
|
||||||
".rb"
|
|
||||||
".erb"
|
|
||||||
".haml"
|
|
||||||
];
|
|
||||||
};
|
|
||||||
};
|
|
||||||
mcp = {
|
|
||||||
memory = {
|
|
||||||
type = "local";
|
|
||||||
command = [
|
|
||||||
"npx"
|
|
||||||
"-y"
|
|
||||||
"@modelcontextprotocol/server-memory"
|
|
||||||
];
|
|
||||||
};
|
|
||||||
browser = {
|
|
||||||
type = "local";
|
|
||||||
command = [
|
|
||||||
"npx"
|
|
||||||
"-y"
|
|
||||||
"@agent-infra/mcp-server-browser"
|
|
||||||
"--headless"
|
|
||||||
"--executable-path"
|
|
||||||
(lib.getExe pkgs-unstable.chromium)
|
|
||||||
];
|
|
||||||
};
|
|
||||||
context7 = {
|
|
||||||
type = "remote";
|
|
||||||
url = "https://mcp.context7.com/mcp";
|
|
||||||
headers = {
|
|
||||||
CONTEXT7_API_KEY = "{env:CONTEXT7_API_KEY}";
|
|
||||||
};
|
|
||||||
enabled = true;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
gnome.automaticTimeZone = true;
|
|
||||||
gtk.enable = true;
|
|
||||||
|
|
||||||
home.pointerCursor = {
|
|
||||||
enable = true;
|
|
||||||
name = "Adwaita";
|
|
||||||
package = pkgs.adwaita-icon-theme;
|
|
||||||
gtk.enable = true;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
@@ -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)
|
|
||||||
'';
|
|
||||||
};
|
|
||||||
}
|
|
||||||
@@ -1,69 +0,0 @@
|
|||||||
# vim: ft=tmux
|
|
||||||
# original from bl1nk
|
|
||||||
# Styles
|
|
||||||
setw -g mode-style "fg=yellow,bg=default,bright"
|
|
||||||
setw -g window-status-style "fg=default,bg=default,dim"
|
|
||||||
setw -g window-status-current-style "fg=yellow,bg=default,dim"
|
|
||||||
set -g message-style "fg=red,bg=default,bright"
|
|
||||||
set -g status-style "fg=default,bg=black,bright"
|
|
||||||
set -g pane-active-border-style "fg=blue,bg=black"
|
|
||||||
set -g allow-passthrough 1
|
|
||||||
set-option -g set-titles on
|
|
||||||
set-option -g focus-events on
|
|
||||||
# set set-titles-string "#{session_name}"
|
|
||||||
|
|
||||||
# Options
|
|
||||||
set -g bell-action any
|
|
||||||
set -g history-limit 50000
|
|
||||||
set -g status on
|
|
||||||
#set -g status-keys vi
|
|
||||||
#set -g status-utf8 on
|
|
||||||
set -g set-titles on
|
|
||||||
|
|
||||||
set -g default-terminal "tmux-256color"
|
|
||||||
set -as terminal-features ",foot*:RGB,alacritty*:RGB,gnome*:RGB"
|
|
||||||
set -g set-titles-string "tmux:#I [ #W ]"
|
|
||||||
set -g base-index 1
|
|
||||||
set -g pane-base-index 1
|
|
||||||
set -g @plugin 'base16-project/base16-tmux'
|
|
||||||
|
|
||||||
set -g update-environment "DISPLAY SSH_ASKPASS SSH_AGENT_PID SSH_CONNECTION WINDOWID XAUTHORITY BASE16_SHELL"
|
|
||||||
|
|
||||||
set -g status-left-length 30
|
|
||||||
set -g status-left '[#[fg=white]#S]#[fg=black,bright] #[default]'
|
|
||||||
set -sg escape-time 0
|
|
||||||
|
|
||||||
#setw -g utf8 on
|
|
||||||
setw -g automatic-rename on
|
|
||||||
setw -g clock-mode-style 24
|
|
||||||
#setw -g mode-keys vi
|
|
||||||
setw -g mouse on
|
|
||||||
|
|
||||||
bind-key q confirm kill-pane
|
|
||||||
bind-key Q confirm kill-session
|
|
||||||
bind-key Tab next-window
|
|
||||||
|
|
||||||
bind-key > switchc -n
|
|
||||||
bind-key > switchc -p
|
|
||||||
|
|
||||||
bind-key C-n new-window -c "#{pane_current_path}"
|
|
||||||
bind-key C-t new-window -c "#{pane_current_path}" "~/bin/share-tty $(tmux display -p '#S')"
|
|
||||||
|
|
||||||
bind-key u run tmux-url-select
|
|
||||||
|
|
||||||
bind-key o split-window -h -c '#{pane_current_path}'
|
|
||||||
bind-key u split-window -v -c '#{pane_current_path}'
|
|
||||||
bind-key C-o split-window -h -c '#{pane_current_path}'
|
|
||||||
bind-key C-u split-window -v -c '#{pane_current_path}'
|
|
||||||
|
|
||||||
bind-key -r C-h select-pane -L
|
|
||||||
bind-key -r C-j select-pane -D
|
|
||||||
bind-key -r C-k select-pane -U
|
|
||||||
bind-key -r C-l select-pane -R
|
|
||||||
|
|
||||||
bind-key f resize-pane -Z
|
|
||||||
bind-key r source-file ~/.config/tmux/tmux.conf
|
|
||||||
|
|
||||||
bind-key -T copy-mode-vi MouseDragEnd1Pane send-keys -X copy-pipe-and-cancel "xclip -i"
|
|
||||||
bind -T root MouseDown2Pane select-pane -t =\; run -b "xclip -o | tmux load-buffer - && tmux paste-buffer -s ' '"
|
|
||||||
run '~/.tmux/plugins/tpm/tpm'
|
|
||||||
File diff suppressed because it is too large
Load Diff
@@ -1,30 +0,0 @@
|
|||||||
#!/bin/zsh
|
|
||||||
# The following lines were added by compinstall
|
|
||||||
|
|
||||||
zstyle ':completion:*' completer _expand _complete _ignored _approximate
|
|
||||||
zstyle ':completion:*' completions 1
|
|
||||||
zstyle ':completion:*' expand prefix
|
|
||||||
zstyle ':completion:*' format '%BCompleting %d%b'
|
|
||||||
zstyle ':completion:*' glob 1
|
|
||||||
zstyle ':completion:*' group-name ''
|
|
||||||
zstyle ':completion:*' ignore-parents parent pwd
|
|
||||||
zstyle ':completion:*' insert-unambiguous true
|
|
||||||
zstyle ':completion:*' list-colors ${(s.:.)LS_COLORS}
|
|
||||||
zstyle ':completion:*' list-prompt %SAt %p: Hit TAB for more, or the character to insert%s
|
|
||||||
zstyle ':completion:*' list-suffixes true
|
|
||||||
zstyle ':completion:*' matcher-list '' 'm:{[:lower:][:upper:]}={[:upper:][:lower:]}' 'r:|[._-]=** r:|=**' 'l:|=* r:|=*'
|
|
||||||
zstyle ':completion:*' max-errors 1
|
|
||||||
zstyle ':completion:*' menu select=3
|
|
||||||
zstyle ':completion:*' original true
|
|
||||||
zstyle ':completion:*' preserve-prefix '//[^/]##/'
|
|
||||||
zstyle ':completion:*' prompt 'Did you mean...'
|
|
||||||
zstyle ':completion:*' select-prompt %SScrolling active: current selection at %p%s
|
|
||||||
zstyle ':completion:*' squeeze-slashes true
|
|
||||||
zstyle ':completion:*' substitute 1
|
|
||||||
zstyle ':completion:*' verbose true
|
|
||||||
zstyle ':completion:*' word true
|
|
||||||
zstyle :compinstall filename "$ZDOTDIR/completion"
|
|
||||||
|
|
||||||
autoload -Uz compinit
|
|
||||||
compinit
|
|
||||||
# End of lines added by compinstall
|
|
||||||
@@ -1,64 +0,0 @@
|
|||||||
#!/usr/bin/zsh
|
|
||||||
|
|
||||||
scratch () {
|
|
||||||
nvim -c ":set ft=$1" $(mktemp)
|
|
||||||
}
|
|
||||||
|
|
||||||
tsessions() {
|
|
||||||
tmux list-sessions -F '#{session_name} #{?session_attached,,not_attached}' | \
|
|
||||||
awk '/not_attached/{print $1}'
|
|
||||||
}
|
|
||||||
|
|
||||||
tkill() {
|
|
||||||
tsessions | fzf | xargs tmux kill-session -t
|
|
||||||
}
|
|
||||||
|
|
||||||
tswitch() {
|
|
||||||
tsessions | fzf | xargs tmux switch-client -t
|
|
||||||
}
|
|
||||||
|
|
||||||
tnew() {
|
|
||||||
tmux new -d -s "$@"
|
|
||||||
tmux switch-client -t $1
|
|
||||||
}
|
|
||||||
|
|
||||||
asciirec() {
|
|
||||||
local tempfile=$(mktemp /tmp/asciirec.XXXXX.asciinema.json)
|
|
||||||
asciinema rec "$tempfile"
|
|
||||||
fb "$tempfile"
|
|
||||||
rm "$tempfile"
|
|
||||||
}
|
|
||||||
|
|
||||||
fbs() {
|
|
||||||
local url=$1
|
|
||||||
local time=${2-5}
|
|
||||||
|
|
||||||
fb <<-HTML | rev | cut -c 2- | rev | xclip
|
|
||||||
<html>
|
|
||||||
<head>
|
|
||||||
<meta http-equiv="refresh" content="${time}; url=${url}" />
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<h3>Redirect</h3>
|
|
||||||
<p>Redirecting you to <a href="${url}">${url}</a></p>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
||||||
HTML
|
|
||||||
|
|
||||||
xclip -o
|
|
||||||
}
|
|
||||||
|
|
||||||
qrshow() {
|
|
||||||
local url=$1
|
|
||||||
[[ -z "$url" ]] && read url
|
|
||||||
qrencode -o - "$url" | feh -
|
|
||||||
}
|
|
||||||
|
|
||||||
envy() {
|
|
||||||
env $(cat .env | sed '/^\s*#/d') "$@"
|
|
||||||
}
|
|
||||||
|
|
||||||
add-hash() {
|
|
||||||
hash -d "$@=$PWD"
|
|
||||||
echo "hash -d '$@=$PWD'" >> "$ZDOTDIR/hashes"
|
|
||||||
}
|
|
||||||
@@ -1,79 +0,0 @@
|
|||||||
#!/bin/zsh
|
|
||||||
|
|
||||||
# History {{{
|
|
||||||
HISTFILE="$XDG_CACHE_HOME/zsh/history"
|
|
||||||
HISTSIZE=100000
|
|
||||||
SAVEHIST=100000
|
|
||||||
setopt hist_ignore_dups
|
|
||||||
setopt hist_ignore_space
|
|
||||||
setopt share_history
|
|
||||||
setopt autopushd
|
|
||||||
|
|
||||||
mkdir -p $(dirname "$HISTFILE")
|
|
||||||
# }}}
|
|
||||||
|
|
||||||
# Various options {{{
|
|
||||||
setopt autocd extendedglob nomatch notify histfindnodups
|
|
||||||
unsetopt beep
|
|
||||||
setopt interactive_comments
|
|
||||||
# }}}
|
|
||||||
|
|
||||||
# Vim mode
|
|
||||||
bindkey -v
|
|
||||||
|
|
||||||
# Keybindings {{{
|
|
||||||
bindkey '^?' backward-delete-char
|
|
||||||
bindkey '^h' backward-delete-char
|
|
||||||
bindkey '^w' backward-kill-word
|
|
||||||
bindkey '^r' history-incremental-pattern-search-backward
|
|
||||||
bindkey '^k' history-beginning-search-backward
|
|
||||||
bindkey '^j' history-beginning-search-forward
|
|
||||||
bindkey '^p' push-input
|
|
||||||
bindkey '^ ' fzf-cd-widget
|
|
||||||
# }}}
|
|
||||||
|
|
||||||
# Prompt {{{
|
|
||||||
autoload -Uz vcs_info
|
|
||||||
precmd_functions+=( vcs_info )
|
|
||||||
setopt prompt_subst
|
|
||||||
PROMPT="%#$([ -n "$IN_NIX_SHELL" ] && echo '%F{blue}ns%f') %1~%(0?..%F{red})>%f "
|
|
||||||
RPROMPT=\$vcs_info_msg_0_
|
|
||||||
zstyle ':vcs_info:git:*' check-for-changes true
|
|
||||||
zstyle ':vcs_info:git:*' formats '<%b> [%u%c]'
|
|
||||||
# }}}
|
|
||||||
|
|
||||||
# Safe rm {{{
|
|
||||||
alias rm='rm -I '
|
|
||||||
setopt rm_star_silent
|
|
||||||
# }}}
|
|
||||||
|
|
||||||
for file in completion functions; do
|
|
||||||
[ -f "$XDG_CONFIG_HOME/zsh/$file" ] || touch "$XDG_CONFIG_HOME/zsh/$file"
|
|
||||||
. "$XDG_CONFIG_HOME/zsh/$file"
|
|
||||||
done
|
|
||||||
|
|
||||||
# GPG Agent {{{
|
|
||||||
export GPG_TTY=$(tty)
|
|
||||||
gpg-connect-agent updatestartuptty /bye >/dev/null
|
|
||||||
# }}}
|
|
||||||
|
|
||||||
# Base16 {{{
|
|
||||||
export BASE16_SHELL="$HOME/.config/base16-shell/"
|
|
||||||
[ -n "$PS1" ] && \
|
|
||||||
[ -s "$BASE16_SHELL/profile_helper.sh" ] && \
|
|
||||||
eval "$("$BASE16_SHELL/profile_helper.sh")"
|
|
||||||
# }}}
|
|
||||||
|
|
||||||
|
|
||||||
# NVM {{{
|
|
||||||
#if [ -f /usr/share/nvm/init-nvm.sh ]; then
|
|
||||||
# source /usr/share/nvm/init-nvm.sh
|
|
||||||
#fi
|
|
||||||
# }}}
|
|
||||||
|
|
||||||
# ENVS {{{
|
|
||||||
#eval "$(rbenv init -)"
|
|
||||||
#. /usr/share/nvm/nvm.sh
|
|
||||||
# }}}
|
|
||||||
|
|
||||||
# vim: set foldmethod=marker
|
|
||||||
@@ -1,15 +0,0 @@
|
|||||||
{ lib, ... }:
|
|
||||||
{
|
|
||||||
age.secrets = lib.listToAttrs (
|
|
||||||
map
|
|
||||||
(secret: {
|
|
||||||
name = secret;
|
|
||||||
value = {
|
|
||||||
file = ../../secrets/${secret}.age;
|
|
||||||
};
|
|
||||||
})
|
|
||||||
[
|
|
||||||
"context7"
|
|
||||||
]
|
|
||||||
);
|
|
||||||
}
|
|
||||||
@@ -1,18 +0,0 @@
|
|||||||
{
|
|
||||||
inputs,
|
|
||||||
pkgs-unstable,
|
|
||||||
self,
|
|
||||||
...
|
|
||||||
}:
|
|
||||||
{
|
|
||||||
home-manager = {
|
|
||||||
users = {
|
|
||||||
jokke = import ./jokke;
|
|
||||||
moco = import ./moco;
|
|
||||||
};
|
|
||||||
extraSpecialArgs = { inherit inputs self pkgs-unstable; };
|
|
||||||
sharedModules = [ (import ./common) ];
|
|
||||||
useUserPackages = true;
|
|
||||||
useGlobalPkgs = true;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
@@ -1,150 +0,0 @@
|
|||||||
{
|
|
||||||
config,
|
|
||||||
lib,
|
|
||||||
osConfig,
|
|
||||||
...
|
|
||||||
}:
|
|
||||||
let
|
|
||||||
cfg = config.gnome;
|
|
||||||
in
|
|
||||||
{
|
|
||||||
imports = [ ./extensions ];
|
|
||||||
|
|
||||||
options.gnome = with lib.types; {
|
|
||||||
profilePicture = lib.mkOption {
|
|
||||||
type = nullOr path;
|
|
||||||
default = null;
|
|
||||||
};
|
|
||||||
keyboard = {
|
|
||||||
sources = lib.mkOption {
|
|
||||||
type = listOf str;
|
|
||||||
default = [ "us" ];
|
|
||||||
};
|
|
||||||
};
|
|
||||||
keybindings = {
|
|
||||||
builtin = lib.mkOption {
|
|
||||||
type = attrsOf (listOf str);
|
|
||||||
default = { };
|
|
||||||
};
|
|
||||||
custom = lib.mkOption {
|
|
||||||
type = listOf (submodule {
|
|
||||||
options = {
|
|
||||||
binding = lib.mkOption { type = str; };
|
|
||||||
command = lib.mkOption { type = str; };
|
|
||||||
name = lib.mkOption { type = str; };
|
|
||||||
};
|
|
||||||
});
|
|
||||||
default = [ ];
|
|
||||||
};
|
|
||||||
};
|
|
||||||
scalingFactor = lib.mkOption {
|
|
||||||
type = numbers.positive;
|
|
||||||
default = 1;
|
|
||||||
};
|
|
||||||
power = {
|
|
||||||
powerButton = lib.mkOption {
|
|
||||||
type = enum [
|
|
||||||
"suspend"
|
|
||||||
"interactive"
|
|
||||||
"hibernate"
|
|
||||||
"nothing"
|
|
||||||
];
|
|
||||||
default = "interactive";
|
|
||||||
};
|
|
||||||
};
|
|
||||||
nightLight = {
|
|
||||||
enable = lib.mkEnableOption { };
|
|
||||||
temperature = lib.mkOption {
|
|
||||||
type = ints.between 1700 4700;
|
|
||||||
default = 2700;
|
|
||||||
};
|
|
||||||
schedule = lib.mkOption {
|
|
||||||
type = nullOr (submodule {
|
|
||||||
options = {
|
|
||||||
from = lib.mkOption {
|
|
||||||
type = numbers.between 0 23.99;
|
|
||||||
default = 20.0;
|
|
||||||
};
|
|
||||||
to = lib.mkOption {
|
|
||||||
type = numbers.between 0 23.99;
|
|
||||||
default = 8.0;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
});
|
|
||||||
default = null;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
calendar = {
|
|
||||||
showWeekNumbers = lib.mkEnableOption { };
|
|
||||||
};
|
|
||||||
automaticTimeZone = lib.mkEnableOption { };
|
|
||||||
region = lib.mkOption {
|
|
||||||
type = str;
|
|
||||||
default = osConfig.i18n.defaultLocale;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
config = {
|
|
||||||
dconf.settings =
|
|
||||||
with lib.hm.gvariant;
|
|
||||||
{
|
|
||||||
"org/gnome/shell/keybindings" = cfg.keybindings.builtin;
|
|
||||||
"org/gnome/settings-daemon/plugins/media-keys" = {
|
|
||||||
custom-keybindings = (
|
|
||||||
lib.lists.imap0 (
|
|
||||||
i: _: "/org/gnome/settings-daemon/plugins/media-keys/custom-keybindings/custom${toString i}/"
|
|
||||||
) cfg.keybindings.custom
|
|
||||||
);
|
|
||||||
};
|
|
||||||
"org/gnome/desktop/input-sources" = {
|
|
||||||
sources = map (
|
|
||||||
source:
|
|
||||||
mkTuple [
|
|
||||||
"xkb"
|
|
||||||
source
|
|
||||||
]
|
|
||||||
) cfg.keyboard.sources;
|
|
||||||
};
|
|
||||||
"org/gnome/mutter" = {
|
|
||||||
experimental-features = [ "scale-monitor-framebuffer" ];
|
|
||||||
};
|
|
||||||
"org/gnome/settings-daemon/plugins/xsettings" = {
|
|
||||||
overrides = [
|
|
||||||
(mkTuple [
|
|
||||||
"GdkWindowScalingFactor"
|
|
||||||
cfg.scalingFactor
|
|
||||||
])
|
|
||||||
];
|
|
||||||
};
|
|
||||||
"org/gnome/desktop/interface" = {
|
|
||||||
scaling-factor = cfg.scalingFactor;
|
|
||||||
};
|
|
||||||
"org/gnome/settings-daemon/plugins/power" = {
|
|
||||||
"power-button-action" = cfg.power.powerButton;
|
|
||||||
};
|
|
||||||
"org/gnome/settings-daemon/plugins/color" = with cfg.nightLight; {
|
|
||||||
night-light-enabled = enable;
|
|
||||||
night-light-temperature = temperature;
|
|
||||||
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/calendar" = {
|
|
||||||
show-weekdate = cfg.calendar.showWeekNumbers;
|
|
||||||
};
|
|
||||||
"org/gnome/desktop/datetime" = {
|
|
||||||
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;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
@@ -1,12 +0,0 @@
|
|||||||
{ ... }:
|
|
||||||
let
|
|
||||||
inherit (builtins) attrNames filter readDir;
|
|
||||||
dirs =
|
|
||||||
let
|
|
||||||
files = readDir ./.;
|
|
||||||
in
|
|
||||||
filter (name: files."${name}" == "directory") (attrNames files);
|
|
||||||
in
|
|
||||||
{
|
|
||||||
imports = map (dir: ./${dir}) dirs;
|
|
||||||
}
|
|
||||||
@@ -1,29 +0,0 @@
|
|||||||
{
|
|
||||||
config,
|
|
||||||
pkgs,
|
|
||||||
lib,
|
|
||||||
...
|
|
||||||
}:
|
|
||||||
let
|
|
||||||
cfg = config.gnome.extensions.freon;
|
|
||||||
in
|
|
||||||
{
|
|
||||||
options.gnome.extensions = with lib.types; {
|
|
||||||
freon = {
|
|
||||||
enable = lib.mkEnableOption { };
|
|
||||||
package = lib.mkOption {
|
|
||||||
type = package;
|
|
||||||
default = pkgs.gnomeExtensions.freon;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
config = lib.mkIf cfg.enable {
|
|
||||||
dconf.settings = {
|
|
||||||
"org/gnome/shell".enabled-extensions = [
|
|
||||||
cfg.package.extensionUuid
|
|
||||||
];
|
|
||||||
};
|
|
||||||
home.packages = [ cfg.package ];
|
|
||||||
};
|
|
||||||
}
|
|
||||||
@@ -1,97 +0,0 @@
|
|||||||
{
|
|
||||||
config,
|
|
||||||
pkgs,
|
|
||||||
lib,
|
|
||||||
...
|
|
||||||
}:
|
|
||||||
let
|
|
||||||
cfg = config.gnome.extensions;
|
|
||||||
in
|
|
||||||
{
|
|
||||||
options.gnome.extensions = with lib.types; {
|
|
||||||
paperwm = {
|
|
||||||
enable = lib.mkEnableOption { };
|
|
||||||
package = lib.mkOption {
|
|
||||||
type = package;
|
|
||||||
default = pkgs.gnomeExtensions.paperwm;
|
|
||||||
};
|
|
||||||
cycle-height-steps = lib.mkOption {
|
|
||||||
type = listOf numbers.nonnegative;
|
|
||||||
default = [
|
|
||||||
0.33
|
|
||||||
0.5
|
|
||||||
0.67
|
|
||||||
1.0
|
|
||||||
];
|
|
||||||
};
|
|
||||||
cycle-width-steps = lib.mkOption {
|
|
||||||
type = listOf numbers.nonnegative;
|
|
||||||
default = [
|
|
||||||
0.33
|
|
||||||
0.5
|
|
||||||
0.67
|
|
||||||
1.0
|
|
||||||
];
|
|
||||||
};
|
|
||||||
horizontal-margin = lib.mkOption {
|
|
||||||
type = ints.unsigned;
|
|
||||||
default = 5;
|
|
||||||
};
|
|
||||||
vertical-margin = lib.mkOption {
|
|
||||||
type = ints.unsigned;
|
|
||||||
default = 5;
|
|
||||||
};
|
|
||||||
window-gap = lib.mkOption {
|
|
||||||
type = ints.unsigned;
|
|
||||||
default = 5;
|
|
||||||
};
|
|
||||||
winprops = lib.mkOption {
|
|
||||||
type = listOf (submodule {
|
|
||||||
options = {
|
|
||||||
wm_class = lib.mkOption {
|
|
||||||
type = str;
|
|
||||||
default = "";
|
|
||||||
};
|
|
||||||
title = lib.mkOption {
|
|
||||||
type = str;
|
|
||||||
default = "";
|
|
||||||
};
|
|
||||||
scratch_layer = lib.mkEnableOption { };
|
|
||||||
preferredWidth = lib.mkOption {
|
|
||||||
type = nullOr str;
|
|
||||||
default = null;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
});
|
|
||||||
default = [ ];
|
|
||||||
};
|
|
||||||
keybindings = lib.mkOption {
|
|
||||||
type = attrsOf (listOf str);
|
|
||||||
default = { };
|
|
||||||
};
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
config = lib.mkIf cfg.paperwm.enable {
|
|
||||||
home.packages = [ cfg.paperwm.package ];
|
|
||||||
dconf.settings = {
|
|
||||||
"org/gnome/shell".enabled-extensions = lib.mkIf cfg.paperwm.enable [
|
|
||||||
cfg.paperwm.package.extensionUuid
|
|
||||||
];
|
|
||||||
"org/gnome/shell/extensions/paperwm" =
|
|
||||||
with cfg.paperwm;
|
|
||||||
lib.mkIf cfg.paperwm.enable {
|
|
||||||
inherit
|
|
||||||
cycle-height-steps
|
|
||||||
cycle-width-steps
|
|
||||||
horizontal-margin
|
|
||||||
vertical-margin
|
|
||||||
window-gap
|
|
||||||
;
|
|
||||||
winprops = map (props: builtins.toJSON props) winprops;
|
|
||||||
};
|
|
||||||
"org/gnome/shell/extensions/paperwm/keybindings" =
|
|
||||||
lib.mkIf cfg.paperwm.enable cfg.paperwm.keybindings;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
}
|
|
||||||
@@ -1,58 +0,0 @@
|
|||||||
{
|
|
||||||
pkgs,
|
|
||||||
pkgs-unstable,
|
|
||||||
inputs,
|
|
||||||
...
|
|
||||||
}:
|
|
||||||
{
|
|
||||||
config = {
|
|
||||||
# Home Manager needs a bit of information about you and the paths it should
|
|
||||||
# manage.
|
|
||||||
home.username = "jokke";
|
|
||||||
home.homeDirectory = "/home/jokke";
|
|
||||||
home.packages = with pkgs; [
|
|
||||||
ffmpeg
|
|
||||||
mediainfo
|
|
||||||
git-lfs
|
|
||||||
telegram-desktop
|
|
||||||
shards
|
|
||||||
deno
|
|
||||||
virt-manager
|
|
||||||
gimp
|
|
||||||
lftp
|
|
||||||
inkscape
|
|
||||||
wineWowPackages.waylandFull
|
|
||||||
reaper
|
|
||||||
inputs.ksoloti-pr.legacyPackages.${pkgs.stdenv.hostPlatform.system}.ksoloti
|
|
||||||
calibre
|
|
||||||
jellyfin-media-player
|
|
||||||
darktable
|
|
||||||
shutter
|
|
||||||
git-annex
|
|
||||||
hledger
|
|
||||||
hledger-ui
|
|
||||||
hledger-iadd
|
|
||||||
];
|
|
||||||
|
|
||||||
gnome.profilePicture = ../assets/profile-pictures/jokke.png;
|
|
||||||
|
|
||||||
programs.ssh.matchBlocks = {
|
|
||||||
"alderaan" = {
|
|
||||||
hostname = "alderaan.space";
|
|
||||||
user = "root";
|
|
||||||
};
|
|
||||||
"base.alderaan" = {
|
|
||||||
hostname = "base.alderaan.space";
|
|
||||||
user = "luke";
|
|
||||||
};
|
|
||||||
"jokke.space" = {
|
|
||||||
user = "root";
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
programs.git.settings.user.email = "joakim@repomaa.com";
|
|
||||||
services.syncthing = {
|
|
||||||
enable = true;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
}
|
|
||||||
@@ -1,201 +0,0 @@
|
|||||||
{ pkgs, pkgs-unstable, ... }:
|
|
||||||
let
|
|
||||||
homeDirectory = "/home/moco";
|
|
||||||
in
|
|
||||||
{
|
|
||||||
# Home Manager needs a bit of information about you and the paths it should
|
|
||||||
# manage.
|
|
||||||
home = {
|
|
||||||
username = "moco";
|
|
||||||
inherit homeDirectory;
|
|
||||||
packages = with pkgs; [
|
|
||||||
chromium
|
|
||||||
(slack.overrideAttrs (oldAttrs: {
|
|
||||||
fixupPhase = ''
|
|
||||||
sed -i -e 's/,"WebRTCPipeWireCapturer"/,"LebRTCPipeWireCapturer"/' $out/lib/slack/resources/app.asar
|
|
||||||
|
|
||||||
rm $out/bin/slack
|
|
||||||
makeWrapper $out/lib/slack/slack $out/bin/slack \
|
|
||||||
--prefix XDG_DATA_DIRS : $GSETTINGS_SCHEMAS_PATH \
|
|
||||||
--suffix PATH : ${lib.makeBinPath [ xdg-utils ]} \
|
|
||||||
--add-flags "--ozone-platform-hint=auto --enable-features=WaylandWindowDecorations,WebRTCPipeWireCapturer"
|
|
||||||
'';
|
|
||||||
}))
|
|
||||||
pkgs-unstable.chromedriver
|
|
||||||
kooha
|
|
||||||
gnome-pomodoro
|
|
||||||
mitmproxy
|
|
||||||
(writeShellScriptBin "moco-admin-pw" ''
|
|
||||||
password=$(op item get n5h4c237tqnnlr5gruxyqmmggy --reveal --fields label=Kennwort)
|
|
||||||
otp=$(ykman oath accounts code -s 'MOCO:Admin')
|
|
||||||
echo "''${password}''${otp}" | wl-copy -n
|
|
||||||
'')
|
|
||||||
(writeShellScriptBin "moco-reto-otp" ''
|
|
||||||
ykman oath accounts code -s 'MOCO Reto' | wl-copy -n
|
|
||||||
'')
|
|
||||||
];
|
|
||||||
};
|
|
||||||
|
|
||||||
gnome = {
|
|
||||||
profilePicture = ../assets/profile-pictures/moco.png;
|
|
||||||
calendar.showWeekNumbers = true;
|
|
||||||
extensions.paperwm.winprops = [
|
|
||||||
{
|
|
||||||
wm_class = "gnome-pomodoro";
|
|
||||||
scratch_layer = true;
|
|
||||||
}
|
|
||||||
];
|
|
||||||
};
|
|
||||||
|
|
||||||
programs.poetry = {
|
|
||||||
enable = true;
|
|
||||||
settings = {
|
|
||||||
virtualenvs = {
|
|
||||||
create = true;
|
|
||||||
inProject = true;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
programs.zsh = {
|
|
||||||
cdpath = [
|
|
||||||
"${homeDirectory}/Code/mocoapp"
|
|
||||||
"${homeDirectory}/Code/mocoapp-promo"
|
|
||||||
"${homeDirectory}/Code/mocoapp-llama"
|
|
||||||
];
|
|
||||||
dirHashes = {
|
|
||||||
moco = "${homeDirectory}/Code/mocoapp";
|
|
||||||
promo = "${homeDirectory}/Code/mocoapp-promo";
|
|
||||||
llama = "${homeDirectory}/Code/mocoapp-llama";
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
programs.git.settings.user.email = "joakim.repomaa@mocoapp.com";
|
|
||||||
|
|
||||||
programs.ssh.matchBlocks =
|
|
||||||
let
|
|
||||||
aliases = [
|
|
||||||
"moco"
|
|
||||||
"mocoapp"
|
|
||||||
"mocoapp.com"
|
|
||||||
];
|
|
||||||
matcher =
|
|
||||||
subdomains:
|
|
||||||
builtins.concatStringsSep " " (
|
|
||||||
map (
|
|
||||||
alias:
|
|
||||||
builtins.concatStringsSep " " (
|
|
||||||
map (subdomain: "*.${subdomain}.${alias} ${subdomain}.${alias}") subdomains
|
|
||||||
)
|
|
||||||
) aliases
|
|
||||||
);
|
|
||||||
in
|
|
||||||
{
|
|
||||||
"console.*.moco" = {
|
|
||||||
extraOptions = {
|
|
||||||
RequestTTY = "force";
|
|
||||||
RemoteCommand = "./rails-console.sh";
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
"${matcher [
|
|
||||||
"reto"
|
|
||||||
"reto.intern"
|
|
||||||
]}" =
|
|
||||||
{
|
|
||||||
hostname = "reto.intern.mocoapp.com";
|
|
||||||
user = "jokke";
|
|
||||||
};
|
|
||||||
|
|
||||||
"${matcher [ "web" ]}" = {
|
|
||||||
hostname = "mocoapp.com";
|
|
||||||
};
|
|
||||||
"${matcher [ "prod-inc" ]}" = {
|
|
||||||
hostname = "prod-inc.mocoapp.com";
|
|
||||||
};
|
|
||||||
"${matcher [ "prod" ]}" = {
|
|
||||||
hostname = "web02.mocoapp";
|
|
||||||
};
|
|
||||||
"${matcher [
|
|
||||||
"pfg"
|
|
||||||
"primeforcegroup"
|
|
||||||
]}" =
|
|
||||||
{
|
|
||||||
hostname = "primeforcegroup.mocoapp.com";
|
|
||||||
};
|
|
||||||
"${matcher [ "crafft" ]}" = {
|
|
||||||
hostname = "crafft.mocoapp.com";
|
|
||||||
};
|
|
||||||
"${matcher [
|
|
||||||
"bd"
|
|
||||||
"businessdecision"
|
|
||||||
]}" =
|
|
||||||
{
|
|
||||||
hostname = "businessdecision.mocoapp.com";
|
|
||||||
};
|
|
||||||
"${matcher [ "festland" ]}" = {
|
|
||||||
hostname = "festland.mocoapp.com";
|
|
||||||
};
|
|
||||||
"${matcher [
|
|
||||||
"oi"
|
|
||||||
"one-inside"
|
|
||||||
]}" =
|
|
||||||
{
|
|
||||||
hostname = "one-inside.mocoapp.com";
|
|
||||||
};
|
|
||||||
"${matcher [
|
|
||||||
"se"
|
|
||||||
"scope-engineering"
|
|
||||||
]}" =
|
|
||||||
{
|
|
||||||
hostname = "scope-engineering.mocoapp.com";
|
|
||||||
};
|
|
||||||
"${matcher [
|
|
||||||
"cpc"
|
|
||||||
"cpc-ag"
|
|
||||||
]}" =
|
|
||||||
{
|
|
||||||
hostname = "cpc-ag.mocoapp.com";
|
|
||||||
};
|
|
||||||
"${matcher [ "weareact3" ]}" = {
|
|
||||||
hostname = "weareact3.mocoapp.com";
|
|
||||||
};
|
|
||||||
"${matcher [ "avenit" ]}" = {
|
|
||||||
hostname = "avenit.mocoapp.com";
|
|
||||||
};
|
|
||||||
"${matcher [ "staging" ]}" = {
|
|
||||||
hostname = "staging.mocoapp.com";
|
|
||||||
};
|
|
||||||
"${matcher [ "staging-v2" ]}" = {
|
|
||||||
hostname = "staging-v2.mocoapp.com";
|
|
||||||
};
|
|
||||||
"${matcher [ "staging-v3" ]}" = {
|
|
||||||
hostname = "staging-v3.mocoapp.com";
|
|
||||||
};
|
|
||||||
"${matcher [ "staging-v4" ]}" = {
|
|
||||||
hostname = "staging-v4.mocoapp.com";
|
|
||||||
};
|
|
||||||
"${matcher [ "staging-v5" ]}" = {
|
|
||||||
hostname = "staging-v5.mocoapp.com";
|
|
||||||
};
|
|
||||||
"${matcher [ "staging-v6" ]}" = {
|
|
||||||
hostname = "staging-v6.mocoapp.com";
|
|
||||||
};
|
|
||||||
"${matcher [
|
|
||||||
"prod-db"
|
|
||||||
"production-db"
|
|
||||||
]}" =
|
|
||||||
{
|
|
||||||
hostname = "production-db.mocoapp";
|
|
||||||
};
|
|
||||||
"${matcher [ "pdf-renderer" ]}" = {
|
|
||||||
hostname = "mocoapp-pdf-renderer01.mocoapp.com";
|
|
||||||
};
|
|
||||||
"*.moco *.mocoapp *.mocoapp.com" = {
|
|
||||||
forwardAgent = true;
|
|
||||||
};
|
|
||||||
"*.moco !reto.moco *.mocoapp.com !reto.mocoapp.com" = {
|
|
||||||
user = "butler";
|
|
||||||
};
|
|
||||||
};
|
|
||||||
}
|
|
||||||
@@ -1,454 +0,0 @@
|
|||||||
{
|
|
||||||
config,
|
|
||||||
lib,
|
|
||||||
pkgs,
|
|
||||||
pkgs-unstable,
|
|
||||||
...
|
|
||||||
}:
|
|
||||||
let
|
|
||||||
cfg = config.programs.zed-editor;
|
|
||||||
ameba-ls = pkgs.stdenv.mkDerivation rec {
|
|
||||||
pname = "ameba-ls";
|
|
||||||
version = "0.1.0";
|
|
||||||
|
|
||||||
src =
|
|
||||||
let
|
|
||||||
selectSystem =
|
|
||||||
attrs:
|
|
||||||
attrs.${pkgs.stdenv.hostPlatform.system}
|
|
||||||
or (throw "Unsupported system: ${pkgs.stdenv.hostPlatform.system}");
|
|
||||||
in
|
|
||||||
pkgs.fetchurl (selectSystem {
|
|
||||||
x86_64-linux = {
|
|
||||||
url = "https://github.com/crystal-lang-tools/ameba-ls/releases/download/v${version}/ameba-ls-${version}-x86_64-linux-musl.tar.gz";
|
|
||||||
hash = "sha256-NtqR8NHytuHT1XIhRVvnp7Lo4Ed9UGbISbTn/BfLGA8=";
|
|
||||||
};
|
|
||||||
aarch64-linux = {
|
|
||||||
url = "https://github.com/crystal-lang-tools/ameba-ls/releases/download/v${version}/ameba-ls-${version}-aarch64-linux-musl.tar.gz";
|
|
||||||
hash = "sha256-77iqdaI+Mqivk0/9jkNdGpluDbz297vsY9wzuipcPOU=";
|
|
||||||
};
|
|
||||||
aarch64-darwin = {
|
|
||||||
url = "https://github.com/crystal-lang-tools/ameba-ls/releases/download/v${version}/ameba-ls-${version}-aarch64-apple-darwin.tar.gz";
|
|
||||||
hash = "sha256-tDB+ZjgjlGjNg3DjX09z1dJnqTv9h/1sXiauBj7uHNc=";
|
|
||||||
};
|
|
||||||
});
|
|
||||||
|
|
||||||
sourceRoot = ".";
|
|
||||||
|
|
||||||
installPhase = ''
|
|
||||||
runHook preInstall
|
|
||||||
mkdir -p $out/bin
|
|
||||||
cp ameba-ls $out/bin/
|
|
||||||
chmod +x $out/bin/ameba-ls
|
|
||||||
runHook postInstall
|
|
||||||
'';
|
|
||||||
|
|
||||||
meta = with lib; {
|
|
||||||
description = "Language server for the Ameba linter for Crystal lang";
|
|
||||||
homepage = "https://github.com/crystal-lang-tools/ameba-ls";
|
|
||||||
license = licenses.mit;
|
|
||||||
platforms = [
|
|
||||||
"x86_64-linux"
|
|
||||||
"aarch64-linux"
|
|
||||||
"aarch64-darwin"
|
|
||||||
];
|
|
||||||
mainProgram = "ameba-ls";
|
|
||||||
};
|
|
||||||
};
|
|
||||||
in
|
|
||||||
{
|
|
||||||
options.programs.zed-editor = {
|
|
||||||
defaultEditor = lib.mkOption {
|
|
||||||
type = lib.types.bool;
|
|
||||||
default = false;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
config = lib.mkIf cfg.enable {
|
|
||||||
programs.zed-editor = {
|
|
||||||
package = pkgs-unstable.zed-editor;
|
|
||||||
extensions = [
|
|
||||||
"ruby"
|
|
||||||
"crystal"
|
|
||||||
"nix"
|
|
||||||
"svelte"
|
|
||||||
];
|
|
||||||
userSettings = {
|
|
||||||
node = {
|
|
||||||
path = lib.getExe pkgs.nodejs_latest;
|
|
||||||
npm_path = lib.getExe' pkgs.nodejs_latest "npm";
|
|
||||||
};
|
|
||||||
agent = {
|
|
||||||
enabled = true;
|
|
||||||
default_model = {
|
|
||||||
provider = "openai";
|
|
||||||
model = "kimi-k2.5";
|
|
||||||
};
|
|
||||||
};
|
|
||||||
auto_update = false;
|
|
||||||
telemetry = {
|
|
||||||
diagnostics = false;
|
|
||||||
metrics = false;
|
|
||||||
};
|
|
||||||
vim_mode = true;
|
|
||||||
languages = {
|
|
||||||
Ruby = {
|
|
||||||
language_servers = [
|
|
||||||
"ruby-lsp"
|
|
||||||
"rubocop"
|
|
||||||
"!solargraph"
|
|
||||||
];
|
|
||||||
formatter.external = {
|
|
||||||
command = pkgs.writeShellScript "rufo" ''
|
|
||||||
bundle exec rufo "$@"
|
|
||||||
if [ $? -eq 1 ]; then
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
'';
|
|
||||||
arguments = [
|
|
||||||
"--filename"
|
|
||||||
"{buffer_path}"
|
|
||||||
];
|
|
||||||
};
|
|
||||||
};
|
|
||||||
Nix = {
|
|
||||||
formatter.external = {
|
|
||||||
command = lib.getExe pkgs.nixfmt-rfc-style;
|
|
||||||
arguments = [ "-q" ];
|
|
||||||
};
|
|
||||||
};
|
|
||||||
Rust = {
|
|
||||||
formatter.external = {
|
|
||||||
command = lib.getExe pkgs.rustfmt;
|
|
||||||
arguments = [
|
|
||||||
"--edition"
|
|
||||||
"2018"
|
|
||||||
];
|
|
||||||
};
|
|
||||||
};
|
|
||||||
Crystal = {
|
|
||||||
language_servers = [
|
|
||||||
"crystalline"
|
|
||||||
"ameba-ls"
|
|
||||||
];
|
|
||||||
formatter.external = {
|
|
||||||
command = lib.getExe pkgs.crystal;
|
|
||||||
arguments = [
|
|
||||||
"tool"
|
|
||||||
"format"
|
|
||||||
"--no-color"
|
|
||||||
"-"
|
|
||||||
];
|
|
||||||
};
|
|
||||||
};
|
|
||||||
};
|
|
||||||
lsp = with pkgs; {
|
|
||||||
nixd.binary.path = lib.getExe nixd;
|
|
||||||
nil.binary.path = lib.getExe nil;
|
|
||||||
ruby-lsp = {
|
|
||||||
initialization_options = {
|
|
||||||
enabledFeatures = {
|
|
||||||
codeActions = true;
|
|
||||||
codeLens = true;
|
|
||||||
completion = true;
|
|
||||||
definition = true;
|
|
||||||
diagnostics = true;
|
|
||||||
documentHighlights = true;
|
|
||||||
documentLink = true;
|
|
||||||
documentSymbols = true;
|
|
||||||
foldingRanges = true;
|
|
||||||
formatting = false;
|
|
||||||
hover = true;
|
|
||||||
inlayHint = true;
|
|
||||||
onTypeFormatting = true;
|
|
||||||
selectionRanges = true;
|
|
||||||
semanticHighlighting = true;
|
|
||||||
signatureHelp = true;
|
|
||||||
typeHierarchy = true;
|
|
||||||
workspaceSymbol = true;
|
|
||||||
};
|
|
||||||
linters = [ "standard" ];
|
|
||||||
};
|
|
||||||
settings.use_bundler = true;
|
|
||||||
};
|
|
||||||
rubocop.binary = {
|
|
||||||
path = "bundle";
|
|
||||||
arguments = [
|
|
||||||
"exec"
|
|
||||||
"rubocop"
|
|
||||||
"--lsp"
|
|
||||||
];
|
|
||||||
};
|
|
||||||
yaml-language-server.binary = {
|
|
||||||
path = lib.getExe yaml-language-server;
|
|
||||||
arguments = [ "--stdio" ];
|
|
||||||
};
|
|
||||||
json-language-server.binary = {
|
|
||||||
path = lib.getExe nodePackages.vscode-json-languageserver;
|
|
||||||
arguments = [ "--stdio" ];
|
|
||||||
};
|
|
||||||
package-version-server.binary.path = lib.getExe pkgs-unstable.package-version-server;
|
|
||||||
eslint.settings.onIgnoredFiles = "off";
|
|
||||||
crystalline.binary.path = lib.getExe crystalline;
|
|
||||||
ameba-ls.binary.path = lib.getExe ameba-ls;
|
|
||||||
rust-analyzer.binary.path = lib.getExe rust-analyzer;
|
|
||||||
};
|
|
||||||
load_direnv = "shell_hook";
|
|
||||||
theme = {
|
|
||||||
mode = "system";
|
|
||||||
light = "One Light";
|
|
||||||
dark = "One Dark";
|
|
||||||
};
|
|
||||||
terminal = {
|
|
||||||
line_height = "standard";
|
|
||||||
font_family = "IosevkaTerm Nerd Font";
|
|
||||||
};
|
|
||||||
edit_predictions = {
|
|
||||||
enabled = true;
|
|
||||||
mode = "eager";
|
|
||||||
provider = "copilot";
|
|
||||||
};
|
|
||||||
buffer_font_family = "Iosevka Nerd Font";
|
|
||||||
buffer_font_size = 16;
|
|
||||||
ui_font_size = 17;
|
|
||||||
relative_line_numbers = "enabled";
|
|
||||||
file_types = {
|
|
||||||
JSONC = [
|
|
||||||
"tsconfig.json"
|
|
||||||
"tsconfig.*.json"
|
|
||||||
];
|
|
||||||
};
|
|
||||||
language_models = {
|
|
||||||
openai = {
|
|
||||||
api_url = "https://opencode.ai/zen/v1";
|
|
||||||
available_models = [
|
|
||||||
# Claude models
|
|
||||||
{
|
|
||||||
name = "claude-opus-4-6";
|
|
||||||
display_name = "OpenCode Zen - Claude Opus 4.6";
|
|
||||||
max_tokens = 1048576;
|
|
||||||
}
|
|
||||||
{
|
|
||||||
name = "claude-opus-4-5";
|
|
||||||
display_name = "OpenCode Zen - Claude Opus 4.5";
|
|
||||||
max_tokens = 200000;
|
|
||||||
}
|
|
||||||
{
|
|
||||||
name = "claude-opus-4-1";
|
|
||||||
display_name = "OpenCode Zen - Claude Opus 4.1";
|
|
||||||
max_tokens = 200000;
|
|
||||||
}
|
|
||||||
{
|
|
||||||
name = "claude-sonnet-4";
|
|
||||||
display_name = "OpenCode Zen - Claude Sonnet 4";
|
|
||||||
max_tokens = 1048576;
|
|
||||||
}
|
|
||||||
{
|
|
||||||
name = "claude-sonnet-4-5";
|
|
||||||
display_name = "OpenCode Zen - Claude Sonnet 4.5";
|
|
||||||
max_tokens = 1048576;
|
|
||||||
}
|
|
||||||
{
|
|
||||||
name = "claude-3-5-haiku";
|
|
||||||
display_name = "OpenCode Zen - Claude 3.5 Haiku";
|
|
||||||
max_tokens = 200000;
|
|
||||||
}
|
|
||||||
{
|
|
||||||
name = "claude-haiku-4-5";
|
|
||||||
display_name = "OpenCode Zen - Claude Haiku 4.5";
|
|
||||||
max_tokens = 200000;
|
|
||||||
}
|
|
||||||
# GPT models
|
|
||||||
{
|
|
||||||
name = "gpt-5.2";
|
|
||||||
display_name = "OpenCode Zen - GPT 5.2";
|
|
||||||
max_tokens = 400000;
|
|
||||||
}
|
|
||||||
{
|
|
||||||
name = "gpt-5.2-codex";
|
|
||||||
display_name = "OpenCode Zen - GPT 5.2 Codex";
|
|
||||||
max_tokens = 400000;
|
|
||||||
}
|
|
||||||
{
|
|
||||||
name = "gpt-5.1";
|
|
||||||
display_name = "OpenCode Zen - GPT 5.1";
|
|
||||||
max_tokens = 400000;
|
|
||||||
}
|
|
||||||
{
|
|
||||||
name = "gpt-5.1-codex-max";
|
|
||||||
display_name = "OpenCode Zen - GPT 5.1 Codex Max";
|
|
||||||
max_tokens = 400000;
|
|
||||||
}
|
|
||||||
{
|
|
||||||
name = "gpt-5.1-codex";
|
|
||||||
display_name = "OpenCode Zen - GPT 5.1 Codex";
|
|
||||||
max_tokens = 400000;
|
|
||||||
}
|
|
||||||
{
|
|
||||||
name = "gpt-5.1-codex-mini";
|
|
||||||
display_name = "OpenCode Zen - GPT 5.1 Codex Mini";
|
|
||||||
max_tokens = 400000;
|
|
||||||
}
|
|
||||||
{
|
|
||||||
name = "gpt-5";
|
|
||||||
display_name = "OpenCode Zen - GPT 5";
|
|
||||||
max_tokens = 400000;
|
|
||||||
}
|
|
||||||
{
|
|
||||||
name = "gpt-5-codex";
|
|
||||||
display_name = "OpenCode Zen - GPT 5 Codex";
|
|
||||||
max_tokens = 400000;
|
|
||||||
}
|
|
||||||
{
|
|
||||||
name = "gpt-5-nano";
|
|
||||||
display_name = "OpenCode Zen - GPT 5 Nano";
|
|
||||||
max_tokens = 400000;
|
|
||||||
}
|
|
||||||
# Gemini models
|
|
||||||
{
|
|
||||||
name = "gemini-3-pro";
|
|
||||||
display_name = "OpenCode Zen - Gemini 3 Pro";
|
|
||||||
max_tokens = 1048576;
|
|
||||||
}
|
|
||||||
{
|
|
||||||
name = "gemini-3-flash";
|
|
||||||
display_name = "OpenCode Zen - Gemini 3 Flash";
|
|
||||||
max_tokens = 1048576;
|
|
||||||
}
|
|
||||||
# GLM models
|
|
||||||
{
|
|
||||||
name = "glm-4.7";
|
|
||||||
display_name = "OpenCode Zen - GLM 4.7";
|
|
||||||
max_tokens = 205000;
|
|
||||||
}
|
|
||||||
{
|
|
||||||
name = "glm-4.6";
|
|
||||||
display_name = "OpenCode Zen - GLM 4.6";
|
|
||||||
max_tokens = 205000;
|
|
||||||
}
|
|
||||||
{
|
|
||||||
name = "glm-4.7-free";
|
|
||||||
display_name = "OpenCode Zen - GLM 4.7 Free";
|
|
||||||
max_tokens = 205000;
|
|
||||||
}
|
|
||||||
# Kimi models
|
|
||||||
{
|
|
||||||
name = "kimi-k2.5";
|
|
||||||
display_name = "OpenCode Zen - Kimi K2.5";
|
|
||||||
max_tokens = 262000;
|
|
||||||
}
|
|
||||||
{
|
|
||||||
name = "kimi-k2.5-free";
|
|
||||||
display_name = "OpenCode Zen - Kimi K2.5 Free";
|
|
||||||
max_tokens = 262000;
|
|
||||||
}
|
|
||||||
{
|
|
||||||
name = "kimi-k2";
|
|
||||||
display_name = "OpenCode Zen - Kimi K2";
|
|
||||||
max_tokens = 262000;
|
|
||||||
}
|
|
||||||
{
|
|
||||||
name = "kimi-k2-thinking";
|
|
||||||
display_name = "OpenCode Zen - Kimi K2 Thinking";
|
|
||||||
max_tokens = 262000;
|
|
||||||
}
|
|
||||||
# MiniMax models
|
|
||||||
{
|
|
||||||
name = "minimax-m2.1";
|
|
||||||
display_name = "OpenCode Zen - MiniMax M2.1";
|
|
||||||
max_tokens = 205000;
|
|
||||||
}
|
|
||||||
{
|
|
||||||
name = "minimax-m2.5-free";
|
|
||||||
display_name = "OpenCode Zen - MiniMax M2.5 Free";
|
|
||||||
max_tokens = 205000;
|
|
||||||
}
|
|
||||||
{
|
|
||||||
name = "minimax-m2.1-free";
|
|
||||||
display_name = "OpenCode Zen - MiniMax M2.1 Free";
|
|
||||||
max_tokens = 205000;
|
|
||||||
}
|
|
||||||
# Other models
|
|
||||||
{
|
|
||||||
name = "trinity-large-preview-free";
|
|
||||||
display_name = "OpenCode Zen - Trinity Large Preview Free";
|
|
||||||
max_tokens = 131000;
|
|
||||||
}
|
|
||||||
{
|
|
||||||
name = "big-pickle";
|
|
||||||
display_name = "OpenCode Zen - Big Pickle";
|
|
||||||
max_tokens = 200000;
|
|
||||||
}
|
|
||||||
{
|
|
||||||
name = "alpha-g5";
|
|
||||||
display_name = "OpenCode Zen - Alpha G5";
|
|
||||||
max_tokens = 200000;
|
|
||||||
}
|
|
||||||
];
|
|
||||||
};
|
|
||||||
};
|
|
||||||
};
|
|
||||||
userKeymaps = [
|
|
||||||
{
|
|
||||||
context = "VimControl && !menu";
|
|
||||||
bindings = {
|
|
||||||
"space g" = [
|
|
||||||
"task::Spawn"
|
|
||||||
{
|
|
||||||
task_name = "lazygit";
|
|
||||||
reveal_target = "center";
|
|
||||||
}
|
|
||||||
];
|
|
||||||
"space 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";
|
|
||||||
}
|
|
||||||
];
|
|
||||||
};
|
|
||||||
|
|
||||||
home.sessionVariables = lib.mkIf cfg.defaultEditor {
|
|
||||||
EDITOR = "${lib.getExe cfg.package} -w";
|
|
||||||
};
|
|
||||||
};
|
|
||||||
}
|
|
||||||
@@ -1,319 +0,0 @@
|
|||||||
# Edit this configuration file to define what should be installed on
|
|
||||||
# your system. Help is availanodev";
|
|
||||||
# https://search.nixos.org/options and in the NixOS manual (`nixos-help`).
|
|
||||||
|
|
||||||
{
|
|
||||||
ssh,
|
|
||||||
pkgs,
|
|
||||||
config,
|
|
||||||
lib,
|
|
||||||
...
|
|
||||||
}:
|
|
||||||
{
|
|
||||||
boot.loader.grub.enable = true;
|
|
||||||
boot.loader.grub.device = "/dev/sda";
|
|
||||||
|
|
||||||
networking.hostName = "apu";
|
|
||||||
networking.useNetworkd = true;
|
|
||||||
|
|
||||||
nix = {
|
|
||||||
settings = {
|
|
||||||
experimental-features = [
|
|
||||||
"nix-command"
|
|
||||||
"flakes"
|
|
||||||
];
|
|
||||||
auto-optimise-store = true;
|
|
||||||
};
|
|
||||||
|
|
||||||
gc = {
|
|
||||||
automatic = true;
|
|
||||||
dates = "daily";
|
|
||||||
options = "--delete-older-than 7d";
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
modules.vlans = {
|
|
||||||
enable = true;
|
|
||||||
networks = {
|
|
||||||
koti = {
|
|
||||||
id = 10;
|
|
||||||
ipv6 = true;
|
|
||||||
};
|
|
||||||
|
|
||||||
gast = {
|
|
||||||
id = 20;
|
|
||||||
ipv6 = true;
|
|
||||||
staticLeases = {
|
|
||||||
"dc:a6:32:05:08:5d" = "10.20.1.235";
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
iot = {
|
|
||||||
id = 30;
|
|
||||||
};
|
|
||||||
|
|
||||||
cfg = {
|
|
||||||
id = 40;
|
|
||||||
staticLeases = {
|
|
||||||
"8c:3b:ad:c5:b8:ee" = "10.40.0.10";
|
|
||||||
};
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
bridge = {
|
|
||||||
enable = true;
|
|
||||||
pvid = config.modules.vlans.networks.cfg.id;
|
|
||||||
netdev = "20-lan";
|
|
||||||
network = "30-lan";
|
|
||||||
bindNetwork = "30-bind-lan";
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
modules.firewall = {
|
|
||||||
enable = true;
|
|
||||||
interfaces = {
|
|
||||||
koti = [
|
|
||||||
"dhcp"
|
|
||||||
"dns"
|
|
||||||
"ssh"
|
|
||||||
"web"
|
|
||||||
];
|
|
||||||
gast = [
|
|
||||||
"dhcp"
|
|
||||||
"dns"
|
|
||||||
];
|
|
||||||
iot = [
|
|
||||||
"dhcp"
|
|
||||||
"dns"
|
|
||||||
];
|
|
||||||
cfg = [
|
|
||||||
"dhcp"
|
|
||||||
"dns"
|
|
||||||
];
|
|
||||||
"tailscale*" = [
|
|
||||||
"ssh"
|
|
||||||
"web"
|
|
||||||
];
|
|
||||||
};
|
|
||||||
allInterfaces = [ ];
|
|
||||||
};
|
|
||||||
|
|
||||||
systemd.network = {
|
|
||||||
enable = true;
|
|
||||||
config.networkConfig.IPv6Forwarding = true;
|
|
||||||
|
|
||||||
links = {
|
|
||||||
"10-extern0" = {
|
|
||||||
matchConfig.Path = "pci-0000:01:00.0";
|
|
||||||
linkConfig.Name = "extern0";
|
|
||||||
};
|
|
||||||
"10-intern0" = {
|
|
||||||
matchConfig.Path = "pci-0000:02:00.0";
|
|
||||||
linkConfig.Name = "intern0";
|
|
||||||
};
|
|
||||||
"10-intern1" = {
|
|
||||||
matchConfig.Path = "pci-0000:03:00.0";
|
|
||||||
linkConfig.Name = "intern1";
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
netdevs = {
|
|
||||||
"20-lan" = {
|
|
||||||
netdevConfig = {
|
|
||||||
Name = "lan";
|
|
||||||
Kind = "bridge";
|
|
||||||
};
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
networks = {
|
|
||||||
"30-bind-lan" = {
|
|
||||||
matchConfig = {
|
|
||||||
Name = "intern*";
|
|
||||||
};
|
|
||||||
networkConfig = {
|
|
||||||
Bridge = "lan";
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
"30-lan" = {
|
|
||||||
matchConfig = {
|
|
||||||
Name = "lan";
|
|
||||||
};
|
|
||||||
networkConfig = {
|
|
||||||
IPv6AcceptRA = false;
|
|
||||||
ConfigureWithoutCarrier = true;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
"30-wan" = {
|
|
||||||
matchConfig = {
|
|
||||||
Name = "extern0";
|
|
||||||
};
|
|
||||||
networkConfig = {
|
|
||||||
DHCP = true;
|
|
||||||
DNS = "127.0.0.1";
|
|
||||||
IPv6AcceptRA = true;
|
|
||||||
IPv4Forwarding = true;
|
|
||||||
};
|
|
||||||
dhcpV6Config = {
|
|
||||||
PrefixDelegationHint = "::/56";
|
|
||||||
};
|
|
||||||
dhcpV4Config = {
|
|
||||||
Use6RD = true;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
services.networkd-dispatcher = {
|
|
||||||
enable = true;
|
|
||||||
rules."50-tailscale" = {
|
|
||||||
onState = [ "routable" ];
|
|
||||||
script = ''
|
|
||||||
#!${pkgs.runtimeShell}
|
|
||||||
${pkgs.ethtool}/bin/ethtool -K ${
|
|
||||||
config.systemd.network.links."10-extern0".linkConfig.Name
|
|
||||||
} rx-udp-gro-forwarding on rx-gro-list off
|
|
||||||
'';
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
time.timeZone = "Europe/Helsinki";
|
|
||||||
|
|
||||||
users.users.jokke = {
|
|
||||||
isNormalUser = true;
|
|
||||||
extraGroups = [ "wheel" ]; # Enable ‘sudo’ for the user.
|
|
||||||
packages = [ pkgs.nh ];
|
|
||||||
openssh.authorizedKeys.keys = [ ssh.publicKeys.yubikey ];
|
|
||||||
initialPassword = "change-me";
|
|
||||||
};
|
|
||||||
|
|
||||||
environment.systemPackages = with pkgs; [
|
|
||||||
wget
|
|
||||||
curl
|
|
||||||
dig
|
|
||||||
neovim
|
|
||||||
vim
|
|
||||||
htop
|
|
||||||
];
|
|
||||||
|
|
||||||
services.openssh = {
|
|
||||||
enable = true;
|
|
||||||
openFirewall = false;
|
|
||||||
settings.PasswordAuthentication = false;
|
|
||||||
};
|
|
||||||
|
|
||||||
services.tailscale = {
|
|
||||||
enable = true;
|
|
||||||
useRoutingFeatures = "both";
|
|
||||||
};
|
|
||||||
|
|
||||||
services.resolved.enable = false;
|
|
||||||
|
|
||||||
modules.services.dhcp-dns-sync = {
|
|
||||||
enable = true;
|
|
||||||
interface = "koti";
|
|
||||||
domain = "home.arpa";
|
|
||||||
interval = "30s";
|
|
||||||
};
|
|
||||||
|
|
||||||
services.unbound = {
|
|
||||||
enable = true;
|
|
||||||
settings = {
|
|
||||||
server = {
|
|
||||||
interface =
|
|
||||||
(lib.map (name: config.systemd.network.networks."30-${name}".dhcpServerConfig.DNS) (
|
|
||||||
lib.attrNames config.modules.vlans.networks
|
|
||||||
))
|
|
||||||
++ [
|
|
||||||
"127.0.0.1"
|
|
||||||
"::1"
|
|
||||||
];
|
|
||||||
access-control = [
|
|
||||||
"10.0.0.0/8 allow"
|
|
||||||
"127.0.0.0/8 allow"
|
|
||||||
"::1/128 allow"
|
|
||||||
];
|
|
||||||
verbosity = 2;
|
|
||||||
};
|
|
||||||
|
|
||||||
forward-zone = [
|
|
||||||
{
|
|
||||||
name = ".";
|
|
||||||
forward-addr = "100.84.105.63#dns.freun.dev";
|
|
||||||
forward-tls-upstream = true;
|
|
||||||
}
|
|
||||||
];
|
|
||||||
|
|
||||||
remote-control.control-enable = true;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
services.avahi = {
|
|
||||||
enable = true;
|
|
||||||
nssmdns4 = true;
|
|
||||||
reflector = true;
|
|
||||||
allowInterfaces = [ "lan" ];
|
|
||||||
openFirewall = true;
|
|
||||||
};
|
|
||||||
|
|
||||||
services.home-assistant = {
|
|
||||||
enable = true;
|
|
||||||
extraComponents = [
|
|
||||||
# Components required to complete the onboarding
|
|
||||||
"esphome"
|
|
||||||
"met"
|
|
||||||
"radio_browser"
|
|
||||||
|
|
||||||
"yeelight"
|
|
||||||
"xiaomi_aqara"
|
|
||||||
"shelly"
|
|
||||||
];
|
|
||||||
subdomain = "home";
|
|
||||||
extraPackages =
|
|
||||||
python3Packages: with python3Packages; [
|
|
||||||
gtts
|
|
||||||
numpy
|
|
||||||
];
|
|
||||||
config = {
|
|
||||||
homeassistant = {
|
|
||||||
name = "Koti";
|
|
||||||
unit_system = "metric";
|
|
||||||
time_zone = "Europe/Helsinki";
|
|
||||||
};
|
|
||||||
http = {
|
|
||||||
use_x_forwarded_for = true;
|
|
||||||
trusted_proxies = "127.0.0.1";
|
|
||||||
};
|
|
||||||
default_config = { };
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
services = {
|
|
||||||
webserver = {
|
|
||||||
enable = true;
|
|
||||||
acme.dnsChallenge = true;
|
|
||||||
vHosts."koti.repomaa.com" = {
|
|
||||||
proxyBuffering = false;
|
|
||||||
locations."/".proxyPort = 8123;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
invidious = {
|
|
||||||
enable = true;
|
|
||||||
subdomain = "vid";
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
security.acme.defaults.environmentFile = config.age.secrets.hetzner.path;
|
|
||||||
|
|
||||||
networking = {
|
|
||||||
nftables.enable = true;
|
|
||||||
firewall.enable = true;
|
|
||||||
useDHCP = false;
|
|
||||||
domain = "repomaa.com";
|
|
||||||
};
|
|
||||||
|
|
||||||
system.stateVersion = "24.05";
|
|
||||||
}
|
|
||||||
@@ -1,12 +0,0 @@
|
|||||||
{ inputs, ... }:
|
|
||||||
let
|
|
||||||
inherit (inputs) nixos-hardware;
|
|
||||||
in
|
|
||||||
{
|
|
||||||
imports = [
|
|
||||||
./hardware-configuration.nix
|
|
||||||
./configuration.nix
|
|
||||||
./secrets.nix
|
|
||||||
nixos-hardware.nixosModules.pcengines-apu
|
|
||||||
];
|
|
||||||
}
|
|
||||||
@@ -1,69 +0,0 @@
|
|||||||
# Do not modify this file! It was generated by ‘nixos-generate-config’
|
|
||||||
# and may be overwritten by future invocations. Please make changes
|
|
||||||
# to /etc/nixos/configuration.nix instead.
|
|
||||||
{
|
|
||||||
config,
|
|
||||||
lib,
|
|
||||||
pkgs,
|
|
||||||
modulesPath,
|
|
||||||
...
|
|
||||||
}:
|
|
||||||
|
|
||||||
{
|
|
||||||
imports = [
|
|
||||||
(modulesPath + "/installer/scan/not-detected.nix")
|
|
||||||
];
|
|
||||||
|
|
||||||
boot.initrd.availableKernelModules = [
|
|
||||||
"xhci_pci"
|
|
||||||
"ahci"
|
|
||||||
"ehci_pci"
|
|
||||||
"usb_storage"
|
|
||||||
"sd_mod"
|
|
||||||
"sdhci_pci"
|
|
||||||
];
|
|
||||||
boot.initrd.kernelModules = [ ];
|
|
||||||
boot.kernelModules = [ "kvm-amd" ];
|
|
||||||
boot.extraModulePackages = [ ];
|
|
||||||
|
|
||||||
fileSystems."/" = {
|
|
||||||
device = "/dev/disk/by-uuid/f221c6a7-e05e-40dc-bc85-7970d7c8f22b";
|
|
||||||
fsType = "btrfs";
|
|
||||||
options = [ "subvol=@" ];
|
|
||||||
};
|
|
||||||
|
|
||||||
fileSystems."/var/log" = {
|
|
||||||
device = "/dev/disk/by-uuid/f221c6a7-e05e-40dc-bc85-7970d7c8f22b";
|
|
||||||
fsType = "btrfs";
|
|
||||||
options = [ "subvol=@var_log" ];
|
|
||||||
};
|
|
||||||
|
|
||||||
fileSystems."/boot" = {
|
|
||||||
device = "/dev/disk/by-uuid/14D2-F8F4";
|
|
||||||
fsType = "vfat";
|
|
||||||
options = [
|
|
||||||
"fmask=0022"
|
|
||||||
"dmask=0022"
|
|
||||||
];
|
|
||||||
};
|
|
||||||
|
|
||||||
fileSystems."/swap" = {
|
|
||||||
device = "/dev/disk/by-uuid/f221c6a7-e05e-40dc-bc85-7970d7c8f22b";
|
|
||||||
fsType = "btrfs";
|
|
||||||
options = [ "subvol=@swap" ];
|
|
||||||
};
|
|
||||||
|
|
||||||
swapDevices = [ ];
|
|
||||||
|
|
||||||
# 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
|
|
||||||
# still possible to use this option, but it's recommended to use it in conjunction
|
|
||||||
# with explicit per-interface declarations with `networking.interfaces.<interface>.useDHCP`.
|
|
||||||
networking.useDHCP = lib.mkDefault true;
|
|
||||||
# networking.interfaces.enp1s0.useDHCP = lib.mkDefault true;
|
|
||||||
# networking.interfaces.enp2s0.useDHCP = lib.mkDefault true;
|
|
||||||
# networking.interfaces.enp3s0.useDHCP = lib.mkDefault true;
|
|
||||||
|
|
||||||
nixpkgs.hostPlatform = lib.mkDefault "x86_64-linux";
|
|
||||||
hardware.cpu.amd.updateMicrocode = lib.mkDefault config.hardware.enableRedistributableFirmware;
|
|
||||||
}
|
|
||||||
@@ -1,15 +0,0 @@
|
|||||||
{ lib, ... }:
|
|
||||||
{
|
|
||||||
age.secrets = lib.listToAttrs (
|
|
||||||
map
|
|
||||||
(secret: {
|
|
||||||
name = secret;
|
|
||||||
value = {
|
|
||||||
file = ../../secrets/${secret}.age;
|
|
||||||
};
|
|
||||||
})
|
|
||||||
[
|
|
||||||
"hetzner"
|
|
||||||
]
|
|
||||||
);
|
|
||||||
}
|
|
||||||
@@ -2,86 +2,50 @@
|
|||||||
# 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`).
|
||||||
|
|
||||||
{
|
{ pkgs, ... }:
|
||||||
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;
|
system.autoUpgrade = {
|
||||||
boot.loader.efi.canTouchEfiVariables = true;
|
enable = true;
|
||||||
|
flake = "/etc/nixos";
|
||||||
|
flags = [
|
||||||
|
"--update-input"
|
||||||
|
"nixpkgs"
|
||||||
|
"-L" # print build logs
|
||||||
|
];
|
||||||
|
dates = "02:00";
|
||||||
|
randomizedDelaySec = "45min";
|
||||||
|
};
|
||||||
|
|
||||||
|
# Use the GRUB 2 boot loader.
|
||||||
|
boot.loader.grub.enable = true;
|
||||||
|
boot.loader.grub.efiSupport = false;
|
||||||
|
# boot.loader.grub.efiInstallAsRemovable = true;
|
||||||
|
# boot.loader.efi.efiSysMountPoint = "/boot/efi";
|
||||||
|
# Define on which hard drive you want to install Grub.
|
||||||
|
boot.loader.grub.device = "/dev/sda"; # or "nodev" for efi only
|
||||||
|
|
||||||
networking.hostName = "freun-dev"; # Define your hostname.
|
networking.hostName = "freun-dev"; # Define your hostname.
|
||||||
networking.domain = "freun.dev";
|
|
||||||
networking.useDHCP = false;
|
networking.useDHCP = false;
|
||||||
networking.nftables.enable = true;
|
|
||||||
|
|
||||||
services.octodns.records = {
|
|
||||||
"" = {
|
|
||||||
A = {
|
|
||||||
ttl = 86400;
|
|
||||||
values = [ ipv4Address ];
|
|
||||||
};
|
|
||||||
AAAA = {
|
|
||||||
ttl = 86400;
|
|
||||||
values = [ ipv6Address ];
|
|
||||||
};
|
|
||||||
TXT = {
|
|
||||||
ttl = 86400;
|
|
||||||
values = [
|
|
||||||
"v=spf1 include:spf.uberspace.de ~all"
|
|
||||||
];
|
|
||||||
};
|
|
||||||
};
|
|
||||||
"_dmarc".TXT = {
|
|
||||||
ttl = 86400;
|
|
||||||
values = [ "v=DMARC1\\; p=reject" ];
|
|
||||||
};
|
|
||||||
"uberspace._domainkey".TXT = {
|
|
||||||
ttl = 86400;
|
|
||||||
values = [
|
|
||||||
"v=DKIM1\\;t=s\\;n=core\\;p=MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEArjZrrWhFn/xSH3+aPA3G1eGD5yAeyn7ZhHSCBM7b/9A5Fny9URjEf1La7dcU+oF/d7outgmTCs/umItBCB7ybkMriaLC+RBZJY0blf35bMYWL9NLpbKzVVAZQPgDZJm7R/grbg0nJgb5RCGLYu9iPcRjJtpu2vYaitkNh8WJ4q+iA/YOos2pQmP+6I5zLTVenFfEWJccdtfhJcORSuONN+Xi1+dQxpQzlwxUWz4DgOsfVaE3woDH3RAAQCtiMyk8ZQhhrL85pHH6zT3sNXzzVphJdIIYA+VYAgYYOTkRbdDhYSd5zCDX5f4L1UmBsJS2ommBGvw2qMDhagXsaN32BwIDAQAB"
|
|
||||||
];
|
|
||||||
};
|
|
||||||
"ts" = {
|
|
||||||
A = {
|
|
||||||
ttl = 86400;
|
|
||||||
values = [ "100.84.105.63" ];
|
|
||||||
};
|
|
||||||
AAAA = {
|
|
||||||
ttl = 86400;
|
|
||||||
values = [ "fd7a:115c:a1e0::7901:693f" ];
|
|
||||||
};
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
systemd.network = {
|
systemd.network = {
|
||||||
enable = true;
|
enable = true;
|
||||||
networks.static = {
|
networks.static = {
|
||||||
name = "enp1s0";
|
name = "enp1s0";
|
||||||
address = [
|
address = [
|
||||||
"${ipv4Address}/32"
|
"95.217.223.61/32"
|
||||||
"${ipv6Address}/64"
|
"2a01:4f9:c012:5e97::1/64"
|
||||||
];
|
];
|
||||||
routes = [
|
routes = [
|
||||||
{ Gateway = "fe80::1"; }
|
{ Gateway = "fe80::1"; }
|
||||||
@@ -105,17 +69,6 @@ in
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
services.networkd-dispatcher = {
|
|
||||||
enable = true;
|
|
||||||
rules."50-tailscale" = {
|
|
||||||
onState = [ "routable" ];
|
|
||||||
script = ''
|
|
||||||
#!${pkgs.runtimeShell}
|
|
||||||
${pkgs.ethtool}/bin/ethtool -K ${config.systemd.network.networks.static.name} rx-udp-gro-forwarding on rx-gro-list off
|
|
||||||
'';
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
# Set your time zone.
|
# Set your time zone.
|
||||||
time.timeZone = "Europe/Helsinki";
|
time.timeZone = "Europe/Helsinki";
|
||||||
|
|
||||||
@@ -131,31 +84,23 @@ 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 = with pkgs; [
|
||||||
openssh.authorizedKeys.keys = [ ssh.publicKeys.yubikey ];
|
# firefox
|
||||||
};
|
# tree
|
||||||
|
# ];
|
||||||
builder = {
|
openssh.authorizedKeys.keys = [
|
||||||
isNormalUser = true;
|
"ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBLIUkESu5NnBi1M0+ZjYrkp6/rIFuwc3aguspf98jmOydNce6l65cnS3GRzc9oWx4lu11ahi87ZuE+pYV+gaHm4="
|
||||||
openssh.authorizedKeys.keys = [ ssh.publicKeys.builder ];
|
|
||||||
};
|
|
||||||
|
|
||||||
root.openssh.authorizedKeys.keys = [ ssh.publicKeys.yubikey ];
|
|
||||||
};
|
|
||||||
|
|
||||||
nix.settings.trusted-users = [
|
|
||||||
"jokke"
|
|
||||||
"builder"
|
|
||||||
];
|
];
|
||||||
|
};
|
||||||
|
|
||||||
# List packages installed in system profile. To search, run:
|
# List packages installed in system profile. To search, run:
|
||||||
# $ nix search wget
|
# $ nix search wget
|
||||||
@@ -163,7 +108,6 @@ in
|
|||||||
vim # Do not forget to add an editor to edit configuration.nix! The Nano editor is also installed by default.
|
vim # Do not forget to add an editor to edit configuration.nix! The Nano editor is also installed by default.
|
||||||
wget
|
wget
|
||||||
htop
|
htop
|
||||||
git
|
|
||||||
];
|
];
|
||||||
|
|
||||||
# Some programs need SUID wrappers, can be configured further or are
|
# Some programs need SUID wrappers, can be configured further or are
|
||||||
@@ -182,10 +126,11 @@ in
|
|||||||
settings.PasswordAuthentication = false;
|
settings.PasswordAuthentication = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
modules.firewall = {
|
# Open ports in the firewall.
|
||||||
enable = true;
|
networking.firewall.allowedTCPPorts = [ 22 ];
|
||||||
allInterfaces = [ "ssh" ];
|
# networking.firewall.allowedUDPPorts = [ ... ];
|
||||||
};
|
# Or disable the firewall altogether.
|
||||||
|
# networking.firewall.enable = false;
|
||||||
|
|
||||||
# Copy the NixOS configuration file and link it from the resulting system
|
# Copy the NixOS configuration file and link it from the resulting system
|
||||||
# (/run/current-system/configuration.nix). This is useful in case you
|
# (/run/current-system/configuration.nix). This is useful in case you
|
||||||
@@ -198,5 +143,5 @@ in
|
|||||||
# this value at the release version of the first install of this system.
|
# this value at the release version of the first install of this system.
|
||||||
# Before changing this value read the documentation for this option
|
# Before changing this value read the documentation for this option
|
||||||
# (e.g. man configuration.nix or on https://nixos.org/nixos/options.html).
|
# (e.g. man configuration.nix or on https://nixos.org/nixos/options.html).
|
||||||
system.stateVersion = "24.11"; # Did you read the comment?
|
system.stateVersion = "23.05"; # Did you read the comment?
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,9 +1,7 @@
|
|||||||
{ ... }:
|
{ ... }: {
|
||||||
{
|
|
||||||
imports = [
|
imports = [
|
||||||
./hardware-configuration.nix
|
|
||||||
./configuration.nix
|
./configuration.nix
|
||||||
|
./hardware-configuration.nix
|
||||||
./services.nix
|
./services.nix
|
||||||
./secrets.nix
|
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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,41 +1,33 @@
|
|||||||
# 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 = [ "ahci" "xhci_pci" "virtio_pci" "virtio_scsi" "sd_mod" "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";
|
{ device = "/dev/disk/by-uuid/8456c7de-2116-4cbe-8deb-76cafbd3e6dd";
|
||||||
fsType = "ext4";
|
fsType = "btrfs";
|
||||||
|
options = [ "subvol=@" ];
|
||||||
};
|
};
|
||||||
|
|
||||||
fileSystems."/boot" = {
|
fileSystems."/var" =
|
||||||
device = "/dev/disk/by-uuid/46F1-18E3";
|
{ device = "/dev/disk/by-uuid/8456c7de-2116-4cbe-8deb-76cafbd3e6dd";
|
||||||
fsType = "vfat";
|
fsType = "btrfs";
|
||||||
options = [
|
options = [ "subvol=@var" ];
|
||||||
"fmask=0077"
|
};
|
||||||
"dmask=0077"
|
|
||||||
|
swapDevices =
|
||||||
|
[ { device = "/dev/disk/by-uuid/614a1b7f-04aa-478c-9011-8b81f133da98"; }
|
||||||
];
|
];
|
||||||
};
|
|
||||||
|
|
||||||
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
|
||||||
@@ -44,5 +36,5 @@
|
|||||||
networking.useDHCP = lib.mkDefault true;
|
networking.useDHCP = lib.mkDefault true;
|
||||||
# networking.interfaces.enp1s0.useDHCP = lib.mkDefault true;
|
# networking.interfaces.enp1s0.useDHCP = lib.mkDefault true;
|
||||||
|
|
||||||
nixpkgs.hostPlatform = lib.mkDefault "aarch64-linux";
|
nixpkgs.hostPlatform = lib.mkDefault "x86_64-linux";
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,55 +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"
|
|
||||||
]
|
|
||||||
)
|
|
||||||
// {
|
|
||||||
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";
|
|
||||||
};
|
|
||||||
};
|
|
||||||
}
|
|
||||||
@@ -1,469 +1,63 @@
|
|||||||
{
|
{ pkgs, ... }:
|
||||||
pkgs,
|
rec {
|
||||||
pkgs-unstable,
|
networking.firewall.allowedTCPPorts = [ 80 443 ];
|
||||||
config,
|
|
||||||
inputs,
|
services.caddy = {
|
||||||
...
|
enable = true;
|
||||||
}:
|
enableReload = true;
|
||||||
let
|
email = "admin@pimeys.pm";
|
||||||
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
|
services.postgresql.enable = true;
|
||||||
{
|
|
||||||
imports = [
|
virtualisation.podman = {
|
||||||
./glance.nix
|
enable = true;
|
||||||
];
|
autoPrune.enable = true;
|
||||||
virtualisation.podman.enable = true;
|
dockerCompat = true;
|
||||||
|
defaultNetwork.settings = {
|
||||||
|
# Required for container networking to be able to use names.
|
||||||
|
dns_enabled = true;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
virtualisation.oci-containers.backend = "podman";
|
virtualisation.oci-containers.backend = "podman";
|
||||||
security.acme.defaults.environmentFile = secrets.hetzner.path;
|
|
||||||
|
|
||||||
modules.storageBoxMounts = {
|
networking.firewall = {
|
||||||
${immichDataDir} = {
|
trustedInterfaces = [ "podman1" ];
|
||||||
path = "/backup/immich";
|
interfaces.podman1.allowedUDPPorts = [ 53 ];
|
||||||
user = "u407959";
|
|
||||||
uid = config.users.users.${config.services.immich.user}.uid;
|
|
||||||
gid = config.users.groups.${config.services.immich.user}.gid;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
${syncthingDataDir} = {
|
imports = [
|
||||||
path = "/backup/syncthing";
|
../../modules/services/vaultwarden.nix
|
||||||
user = "u407959";
|
../../modules/services/immich.nix
|
||||||
uid = config.users.users.${config.services.syncthing.user}.uid;
|
../../modules/services/syncthing.nix
|
||||||
gid = config.users.groups.${config.services.syncthing.user}.gid;
|
../../modules/services/invidious.nix
|
||||||
};
|
../../modules/services/grafana.nix
|
||||||
};
|
../../modules/services/gtrackmap.nix
|
||||||
|
../../modules/services/owncast.nix
|
||||||
|
../../modules/services/hydra.nix
|
||||||
|
../../modules/services/wireguard.nix
|
||||||
|
];
|
||||||
|
|
||||||
services = {
|
services.immich = {
|
||||||
postgresql.package = pkgs.postgresql_16;
|
|
||||||
octodns = {
|
|
||||||
enable = true;
|
enable = true;
|
||||||
records."".MX = {
|
fqdn = "img.freun.dev";
|
||||||
ttl = 86400;
|
data_dir = fileSystems.immich_data.mountPoint;
|
||||||
values = [ { exchange = "${smtp.host}."; } ];
|
secrets = "/var/secrets/immich";
|
||||||
};
|
|
||||||
defaults.CNAME.ttl = 60;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
hastebin = {
|
fileSystems.immich_data = {
|
||||||
enable = true;
|
mountPoint = "/mnt/storage/immich";
|
||||||
subdomain = "bin";
|
device = "//u407959.your-storagebox.de/backup/immich";
|
||||||
renderers =
|
fsType = "cifs";
|
||||||
with pkgs;
|
options =
|
||||||
let
|
let
|
||||||
hl = rustPlatform.buildRustPackage {
|
# this line prevents hanging on network split
|
||||||
name = "syntax-renderer";
|
automount_opts = "x-systemd.automount,auto,x-systemd.device-timeout=5s,x-systemd.mount-timeout=5s";
|
||||||
src = inputs.syntax-renderer;
|
|
||||||
cargoHash = "sha256-kZy+HVPcUfPDTBQZ8TQ/xlEEqmSIttzdGeRwX9EF4xU=";
|
|
||||||
};
|
|
||||||
in
|
in
|
||||||
{
|
[ "${automount_opts},credentials=/var/secrets/smb-storage" ];
|
||||||
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 = {
|
environment.systemPackages = [ pkgs.cifs-utils ];
|
||||||
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 = false;
|
|
||||||
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";
|
|
||||||
port = 3004;
|
|
||||||
};
|
|
||||||
|
|
||||||
workout-sync = {
|
|
||||||
enable = true;
|
|
||||||
subdomain = "ws";
|
|
||||||
};
|
|
||||||
|
|
||||||
immich = {
|
|
||||||
enable = true;
|
|
||||||
subdomain = "img";
|
|
||||||
mediaLocation = immichDataDir;
|
|
||||||
timezone = "Europe/Helsinki";
|
|
||||||
settings.job = {
|
|
||||||
thumbnailGeneration.concurrency = 8;
|
|
||||||
videoConversion.concurrency = 2;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
dnote = {
|
|
||||||
enable = true;
|
|
||||||
subdomain = "note";
|
|
||||||
environment = {
|
|
||||||
SmtpHost = smtp.host;
|
|
||||||
SmtpPort = smtp.port;
|
|
||||||
SmtpUsername = smtp.username;
|
|
||||||
};
|
|
||||||
environmentFile = secrets.dnote.path;
|
|
||||||
};
|
|
||||||
|
|
||||||
tailscaledAdguardhome = {
|
|
||||||
enable = true;
|
|
||||||
subdomain = "dns";
|
|
||||||
port = 3006;
|
|
||||||
};
|
|
||||||
|
|
||||||
mealie = {
|
|
||||||
enable = true;
|
|
||||||
package = pkgs-unstable.mealie;
|
|
||||||
subdomain = "cook";
|
|
||||||
credentialsFile = secrets.mealie.path;
|
|
||||||
settings = {
|
|
||||||
SMTP_HOST = smtp.host;
|
|
||||||
SMTP_FROM_EMAIL = smtp.from;
|
|
||||||
SMTP_USER = smtp.username;
|
|
||||||
SMTP_PORT = smtp.port;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
uptime-kuma = {
|
|
||||||
enable = true;
|
|
||||||
subdomain = "status";
|
|
||||||
settings = {
|
|
||||||
PORT = "3007";
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
mosquitto = {
|
|
||||||
enable = true;
|
|
||||||
listeners = [
|
|
||||||
{
|
|
||||||
users = {
|
|
||||||
homie = {
|
|
||||||
acl = [
|
|
||||||
"readwrite homie/#"
|
|
||||||
];
|
|
||||||
hashedPasswordFile = secrets."mosquitto/homie".path;
|
|
||||||
};
|
|
||||||
telegraf = {
|
|
||||||
acl = [
|
|
||||||
"read openhab/#"
|
|
||||||
"read homie/#"
|
|
||||||
"read shellies/#"
|
|
||||||
"read mokkimaatti/#"
|
|
||||||
];
|
|
||||||
hashedPasswordFile = secrets."mosquitto/telegraf".path;
|
|
||||||
};
|
|
||||||
openhab = {
|
|
||||||
acl = [
|
|
||||||
"readwrite openhab/#"
|
|
||||||
];
|
|
||||||
hashedPasswordFile = secrets."mosquitto/openhab".path;
|
|
||||||
};
|
|
||||||
shelly = {
|
|
||||||
acl = [
|
|
||||||
"readwrite shellies/#"
|
|
||||||
];
|
|
||||||
hashedPasswordFile = secrets."mosquitto/shelly".path;
|
|
||||||
};
|
|
||||||
mokkimaatti = {
|
|
||||||
acl = [
|
|
||||||
"readwrite mokkimaatti/#"
|
|
||||||
];
|
|
||||||
hashedPasswordFile = secrets."mosquitto/mokkimaatti".path;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
}
|
|
||||||
];
|
|
||||||
openFirewall = true;
|
|
||||||
};
|
|
||||||
|
|
||||||
gitlab-runner = {
|
|
||||||
enable = true;
|
|
||||||
services = {
|
|
||||||
default = {
|
|
||||||
dockerImage = "alpine";
|
|
||||||
authenticationTokenConfigFile = secrets."gitlab-runner/default".path;
|
|
||||||
};
|
|
||||||
docker = {
|
|
||||||
dockerImage = "docker:stable";
|
|
||||||
dockerVolumes = [ "/var/run/docker.sock:/var/run/docker.sock" ];
|
|
||||||
authenticationTokenConfigFile = secrets."gitlab-runner/docker".path;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
home-assistant = {
|
|
||||||
enable = false;
|
|
||||||
subdomain = "home";
|
|
||||||
config = {
|
|
||||||
homeassistant = {
|
|
||||||
name = "Koti";
|
|
||||||
unit_system = "metric";
|
|
||||||
time_zone = "Europe/Helsinki";
|
|
||||||
};
|
|
||||||
http = {
|
|
||||||
server_port = 8123;
|
|
||||||
use_x_forwarded_for = true;
|
|
||||||
trusted_proxies = [
|
|
||||||
"127.0.0.1"
|
|
||||||
"::1"
|
|
||||||
];
|
|
||||||
};
|
|
||||||
mqtt = [
|
|
||||||
{
|
|
||||||
climate = {
|
|
||||||
unique_id = "nappula";
|
|
||||||
name = "Nappula";
|
|
||||||
current_humidity_topic = "homie/nappula/humidity/value";
|
|
||||||
current_humidity_template = "{{ value | float }}";
|
|
||||||
current_temperature_topic = "homie/nappula/temperature/value";
|
|
||||||
current_temperature_template = "{{ value | float }}";
|
|
||||||
mode_state_topic = "homie/nappula/ac/trigger";
|
|
||||||
mode_state_template = "{% if value == 'true' %}heat{% else %}off{% endif %}";
|
|
||||||
availability = {
|
|
||||||
topic = "homie/nappula/$online";
|
|
||||||
payload_available = "true";
|
|
||||||
payload_not_available = "false";
|
|
||||||
};
|
|
||||||
modes = [
|
|
||||||
"off"
|
|
||||||
"heat"
|
|
||||||
];
|
|
||||||
};
|
|
||||||
}
|
|
||||||
{
|
|
||||||
button = {
|
|
||||||
unique_id = "nappula_button";
|
|
||||||
name = "Nappula anschalten";
|
|
||||||
command_topic = "homie/nappula/button/trigger/set";
|
|
||||||
payload_press = "true";
|
|
||||||
availability = {
|
|
||||||
topic = "homie/nappula/$online";
|
|
||||||
payload_available = "true";
|
|
||||||
payload_not_available = "false";
|
|
||||||
};
|
|
||||||
icon = "mdi:power";
|
|
||||||
};
|
|
||||||
}
|
|
||||||
{
|
|
||||||
sensor = {
|
|
||||||
unique_id = "nappula_pressure";
|
|
||||||
name = "Luftdruck";
|
|
||||||
state_topic = "homie/nappula/pressure/value";
|
|
||||||
device_class = "atmospheric_pressure";
|
|
||||||
unit_of_measurement = "hPa";
|
|
||||||
state_class = "measurement";
|
|
||||||
value_template = "{{ value | float // 100 }}";
|
|
||||||
};
|
|
||||||
}
|
|
||||||
];
|
|
||||||
};
|
|
||||||
extraComponents = [
|
|
||||||
"default_config"
|
|
||||||
"esphome"
|
|
||||||
"met"
|
|
||||||
"radio_browser"
|
|
||||||
"mqtt"
|
|
||||||
];
|
|
||||||
extraPackages = (
|
|
||||||
python3Packages: with python3Packages; [
|
|
||||||
paho-mqtt
|
|
||||||
]
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
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://repomaa/node:latest"
|
|
||||||
];
|
|
||||||
tokenFile = secrets.gitea-actions-runner.path;
|
|
||||||
url = "https://${config.services.gitea.subdomain}.${config.networking.domain}";
|
|
||||||
settings.container.network = "bridge";
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
webserver = {
|
|
||||||
acme.dnsChallenge = true;
|
|
||||||
tailscaleAuth.expectedTailnet = "tempel-vibes.ts.net";
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
virtualisation.docker.autoPrune.enable = true;
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,31 +0,0 @@
|
|||||||
{ lib, pkgs, ... }:
|
|
||||||
{
|
|
||||||
boot = {
|
|
||||||
loader.systemd-boot.enable = lib.mkForce false;
|
|
||||||
lanzaboote = {
|
|
||||||
enable = true;
|
|
||||||
pkiBundle = "/etc/secureboot";
|
|
||||||
configurationLimit = 10;
|
|
||||||
settings = {
|
|
||||||
editor = false;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
loader.efi.canTouchEfiVariables = true;
|
|
||||||
bootspec.enable = true;
|
|
||||||
kernelPackages = pkgs.linuxPackages_latest;
|
|
||||||
kernelParams = [
|
|
||||||
"amdgpu.sg_display=0"
|
|
||||||
"resume_offset=533760"
|
|
||||||
];
|
|
||||||
|
|
||||||
resumeDevice = "/dev/disk/by-uuid/a331b669-f5c5-42f7-be58-434873c1b689";
|
|
||||||
tmp.useTmpfs = true;
|
|
||||||
kernel.sysctl = {
|
|
||||||
"vm.max_map_count" = 262144;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
environment.systemPackages = with pkgs; [
|
|
||||||
efibootmgr
|
|
||||||
];
|
|
||||||
}
|
|
||||||
@@ -1,48 +0,0 @@
|
|||||||
{ ... }:
|
|
||||||
{
|
|
||||||
nix = {
|
|
||||||
distributedBuilds = true;
|
|
||||||
buildMachines = [
|
|
||||||
{
|
|
||||||
hostName = "freun.dev";
|
|
||||||
maxJobs = 8;
|
|
||||||
protocol = "ssh";
|
|
||||||
sshUser = "builder";
|
|
||||||
system = "aarch64-linux";
|
|
||||||
}
|
|
||||||
];
|
|
||||||
settings = {
|
|
||||||
experimental-features = [
|
|
||||||
"nix-command"
|
|
||||||
"flakes"
|
|
||||||
];
|
|
||||||
auto-optimise-store = true;
|
|
||||||
};
|
|
||||||
|
|
||||||
gc = {
|
|
||||||
automatic = true;
|
|
||||||
dates = "daily";
|
|
||||||
options = "--delete-older-than 7d";
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
networking.nftables.enable = true;
|
|
||||||
|
|
||||||
# This option defines the first version of NixOS you have installed on this particular machine,
|
|
||||||
# and is used to maintain compatibility with application data (e.g. databases) created on older NixOS versions.
|
|
||||||
#
|
|
||||||
# Most users should NEVER change this value after the initial install, for any reason,
|
|
||||||
# even if you've upgraded your system to a new NixOS release.
|
|
||||||
#
|
|
||||||
# This value does NOT affect the Nixpkgs version your packages and OS are pulled from,
|
|
||||||
# so changing it will NOT upgrade your system.
|
|
||||||
#
|
|
||||||
# This value being lower than the current NixOS release does NOT mean your system is
|
|
||||||
# out of date, out of support, or vulnerable.
|
|
||||||
#
|
|
||||||
# Do NOT change this value unless you have manually inspected all the changes it would make to your configuration,
|
|
||||||
# and migrated your data accordingly.
|
|
||||||
#
|
|
||||||
# For more information, see `man configuration.nix` or https://nixos.org/manual/nixos/stable/options#opt-system.stateVersion .
|
|
||||||
system.stateVersion = "23.11"; # Did you read the comment?
|
|
||||||
}
|
|
||||||
@@ -1,11 +0,0 @@
|
|||||||
{ ... }:
|
|
||||||
{
|
|
||||||
virtualisation.docker = {
|
|
||||||
storageDriver = "btrfs";
|
|
||||||
enable = true;
|
|
||||||
autoPrune.enable = true;
|
|
||||||
};
|
|
||||||
|
|
||||||
users.users.jokke.extraGroups = [ "docker" ];
|
|
||||||
users.users.moco.extraGroups = [ "docker" ];
|
|
||||||
}
|
|
||||||
@@ -1,26 +0,0 @@
|
|||||||
{ inputs, ... }:
|
|
||||||
let
|
|
||||||
inherit (inputs)
|
|
||||||
lanzaboote
|
|
||||||
nixos-hardware
|
|
||||||
home-manager
|
|
||||||
;
|
|
||||||
in
|
|
||||||
{
|
|
||||||
imports = [
|
|
||||||
./hardware-configuration.nix
|
|
||||||
./configuration.nix
|
|
||||||
./host.nix
|
|
||||||
./boot.nix
|
|
||||||
./hardware.nix
|
|
||||||
./packages.nix
|
|
||||||
./containers.nix
|
|
||||||
./desktop.nix
|
|
||||||
./users.nix
|
|
||||||
./secrets.nix
|
|
||||||
lanzaboote.nixosModules.lanzaboote
|
|
||||||
nixos-hardware.nixosModules.framework-13-7040-amd
|
|
||||||
home-manager.nixosModules.home-manager
|
|
||||||
../../home
|
|
||||||
];
|
|
||||||
}
|
|
||||||
@@ -1,23 +0,0 @@
|
|||||||
{ ... }:
|
|
||||||
{
|
|
||||||
services.displayManager.gdm.enable = true;
|
|
||||||
services.desktopManager.gnome.enable = true;
|
|
||||||
|
|
||||||
services.printing.enable = true;
|
|
||||||
|
|
||||||
security.rtkit.enable = true;
|
|
||||||
services.pipewire = {
|
|
||||||
enable = true;
|
|
||||||
alsa.enable = true;
|
|
||||||
alsa.support32Bit = true;
|
|
||||||
pulse.enable = true;
|
|
||||||
jack.enable = true;
|
|
||||||
};
|
|
||||||
services.pulseaudio.enable = false;
|
|
||||||
|
|
||||||
programs.steam = {
|
|
||||||
enable = true;
|
|
||||||
remotePlay.openFirewall = true;
|
|
||||||
dedicatedServer.openFirewall = true;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
@@ -1,77 +0,0 @@
|
|||||||
# Do not modify this file! It was generated by ‘nixos-generate-config’
|
|
||||||
# and may be overwritten by future invocations. Please make changes
|
|
||||||
# to /etc/nixos/configuration.nix instead.
|
|
||||||
{
|
|
||||||
config,
|
|
||||||
lib,
|
|
||||||
modulesPath,
|
|
||||||
...
|
|
||||||
}:
|
|
||||||
|
|
||||||
{
|
|
||||||
imports = [
|
|
||||||
(modulesPath + "/installer/scan/not-detected.nix")
|
|
||||||
];
|
|
||||||
|
|
||||||
boot.initrd.availableKernelModules = [
|
|
||||||
"nvme"
|
|
||||||
"xhci_pci"
|
|
||||||
"thunderbolt"
|
|
||||||
"usb_storage"
|
|
||||||
"sd_mod"
|
|
||||||
];
|
|
||||||
boot.initrd.kernelModules = [ ];
|
|
||||||
boot.kernelModules = [ "kvm-amd" ];
|
|
||||||
boot.extraModulePackages = [ ];
|
|
||||||
|
|
||||||
fileSystems."/" = {
|
|
||||||
device = "/dev/disk/by-uuid/a331b669-f5c5-42f7-be58-434873c1b689";
|
|
||||||
fsType = "btrfs";
|
|
||||||
options = [ "subvol=@" ];
|
|
||||||
};
|
|
||||||
|
|
||||||
boot.initrd.luks.devices."cryptroot" = {
|
|
||||||
device = "/dev/disk/by-uuid/43895585-8899-4e94-a413-889127c214f8";
|
|
||||||
allowDiscards = true;
|
|
||||||
};
|
|
||||||
|
|
||||||
fileSystems."/var/log" = {
|
|
||||||
device = "/dev/disk/by-uuid/a331b669-f5c5-42f7-be58-434873c1b689";
|
|
||||||
fsType = "btrfs";
|
|
||||||
options = [ "subvol=@var_log" ];
|
|
||||||
};
|
|
||||||
|
|
||||||
fileSystems."/home" = {
|
|
||||||
device = "/dev/disk/by-uuid/a331b669-f5c5-42f7-be58-434873c1b689";
|
|
||||||
fsType = "btrfs";
|
|
||||||
options = [ "subvol=@home" ];
|
|
||||||
};
|
|
||||||
|
|
||||||
fileSystems."/boot" = {
|
|
||||||
device = "/dev/disk/by-uuid/01E6-6258";
|
|
||||||
fsType = "vfat";
|
|
||||||
};
|
|
||||||
|
|
||||||
fileSystems."/swap" = {
|
|
||||||
device = "/dev/disk/by-uuid/a331b669-f5c5-42f7-be58-434873c1b689";
|
|
||||||
fsType = "btrfs";
|
|
||||||
options = [ "subvol=@swap" ];
|
|
||||||
};
|
|
||||||
|
|
||||||
swapDevices = [
|
|
||||||
{
|
|
||||||
device = "/swap/swapfile";
|
|
||||||
size = 64 * 1024;
|
|
||||||
}
|
|
||||||
];
|
|
||||||
|
|
||||||
# Enables DHCP on each ethernet and wireless interface. In case of scripted networking
|
|
||||||
# (the default) this is the recommended approach. When using systemd-networkd it's
|
|
||||||
# still possible to use this option, but it's recommended to use it in conjunction
|
|
||||||
# with explicit per-interface declarations with `networking.interfaces.<interface>.useDHCP`.
|
|
||||||
networking.useDHCP = lib.mkDefault true;
|
|
||||||
# networking.interfaces.wlp1s0.useDHCP = lib.mkDefault true;
|
|
||||||
|
|
||||||
nixpkgs.hostPlatform = lib.mkDefault "x86_64-linux";
|
|
||||||
hardware.cpu.amd.updateMicrocode = lib.mkDefault config.hardware.enableRedistributableFirmware;
|
|
||||||
}
|
|
||||||
@@ -1,89 +0,0 @@
|
|||||||
{
|
|
||||||
pkgs,
|
|
||||||
pkgs-unstable,
|
|
||||||
inputs,
|
|
||||||
lib,
|
|
||||||
config,
|
|
||||||
...
|
|
||||||
}:
|
|
||||||
{
|
|
||||||
hardware.bluetooth.enable = true;
|
|
||||||
hardware.bluetooth.powerOnBoot = true;
|
|
||||||
|
|
||||||
services.udev.packages = [
|
|
||||||
pkgs.zsa-udev-rules
|
|
||||||
pkgs-unstable.yubikey-personalization
|
|
||||||
inputs.ksoloti-pr.legacyPackages.${pkgs.stdenv.hostPlatform.system}.ksoloti
|
|
||||||
];
|
|
||||||
services.usbmuxd = {
|
|
||||||
enable = true;
|
|
||||||
package = pkgs.usbmuxd;
|
|
||||||
};
|
|
||||||
services.fwupd = {
|
|
||||||
enable = true;
|
|
||||||
};
|
|
||||||
services.fprintd.enable = true;
|
|
||||||
services.fstrim.enable = true;
|
|
||||||
|
|
||||||
security.pam.services.login.fprintAuth = false;
|
|
||||||
# similarly to how other distributions handle the fingerprinting login
|
|
||||||
security.pam.services.gdm-fingerprint = lib.mkIf (config.services.fprintd.enable) {
|
|
||||||
text = ''
|
|
||||||
auth required pam_shells.so
|
|
||||||
auth requisite pam_nologin.so
|
|
||||||
auth requisite pam_faillock.so preauth
|
|
||||||
auth required ${pkgs.fprintd}/lib/security/pam_fprintd.so
|
|
||||||
auth optional pam_permit.so
|
|
||||||
auth required pam_env.so
|
|
||||||
auth [success=ok default=1] ${pkgs.gdm}/lib/security/pam_gdm.so
|
|
||||||
auth optional ${pkgs.gnome-keyring}/lib/security/pam_gnome_keyring.so
|
|
||||||
|
|
||||||
account include login
|
|
||||||
|
|
||||||
password required pam_deny.so
|
|
||||||
|
|
||||||
session include login
|
|
||||||
session optional ${pkgs.gnome-keyring}/lib/security/pam_gnome_keyring.so auto_start
|
|
||||||
'';
|
|
||||||
};
|
|
||||||
|
|
||||||
hardware.keyboard.zsa.enable = true;
|
|
||||||
|
|
||||||
services.logind = {
|
|
||||||
settings.Login = {
|
|
||||||
IdleAction = "suspend";
|
|
||||||
HandleLidSwitch = "suspend";
|
|
||||||
HandlePowerKey = "suspend";
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
powerManagement = {
|
|
||||||
enable = true;
|
|
||||||
powerDownCommands = "${pkgs.networkmanager}/bin/nmcli radio wifi off";
|
|
||||||
powerUpCommands = "${pkgs.networkmanager}/bin/nmcli radio wifi on";
|
|
||||||
};
|
|
||||||
|
|
||||||
services.power-profiles-daemon.enable = true;
|
|
||||||
hardware.amdgpu.opencl.enable = true;
|
|
||||||
hardware.graphics = {
|
|
||||||
enable = true;
|
|
||||||
extraPackages = with pkgs; [ rocmPackages.clr.icd ];
|
|
||||||
};
|
|
||||||
networking.networkmanager = {
|
|
||||||
enable = true;
|
|
||||||
wifi.backend = "iwd";
|
|
||||||
plugins = with pkgs; [
|
|
||||||
networkmanager-openvpn
|
|
||||||
];
|
|
||||||
};
|
|
||||||
security.tpm2.enable = true;
|
|
||||||
|
|
||||||
services.nqptp.enable = true;
|
|
||||||
networking.firewall.allowedTCPPortRanges = [
|
|
||||||
{
|
|
||||||
from = 7000;
|
|
||||||
to = 7010;
|
|
||||||
}
|
|
||||||
];
|
|
||||||
networking.firewall.allowedUDPPorts = [ 5353 ];
|
|
||||||
}
|
|
||||||
@@ -1,17 +0,0 @@
|
|||||||
{ lib, ... }:
|
|
||||||
{
|
|
||||||
networking.hostName = "radish";
|
|
||||||
time.timeZone = lib.mkForce null; # allow TZ to be set by desktop user
|
|
||||||
i18n.defaultLocale = "de_DE.UTF-8";
|
|
||||||
i18n.supportedLocales = map (locale: "${locale}.UTF-8/UTF-8") [
|
|
||||||
"C"
|
|
||||||
"en_US"
|
|
||||||
"de_DE"
|
|
||||||
"fi_FI"
|
|
||||||
];
|
|
||||||
i18n.extraLocaleSettings.LANG = "en_US.UTF-8";
|
|
||||||
console = {
|
|
||||||
font = "Lat2-Terminus16";
|
|
||||||
keyMap = "us";
|
|
||||||
};
|
|
||||||
}
|
|
||||||
@@ -1,142 +0,0 @@
|
|||||||
{
|
|
||||||
pkgs,
|
|
||||||
pkgs-unstable,
|
|
||||||
lib,
|
|
||||||
inputs,
|
|
||||||
config,
|
|
||||||
...
|
|
||||||
}:
|
|
||||||
let
|
|
||||||
secrets = config.age.secrets;
|
|
||||||
in
|
|
||||||
{
|
|
||||||
nixpkgs.config.allowUnfree = true;
|
|
||||||
nixpkgs.overlays = [ (import ../../custom-pkgs { inherit lib inputs pkgs-unstable; }) ];
|
|
||||||
|
|
||||||
environment = {
|
|
||||||
systemPackages = with pkgs; [
|
|
||||||
vim
|
|
||||||
wget
|
|
||||||
curl
|
|
||||||
htop
|
|
||||||
tmux
|
|
||||||
libimobiledevice
|
|
||||||
ripgrep
|
|
||||||
fd
|
|
||||||
];
|
|
||||||
|
|
||||||
pathsToLink = [ "/share/zsh" ];
|
|
||||||
};
|
|
||||||
|
|
||||||
fonts.packages = with pkgs-unstable; [
|
|
||||||
nerd-fonts.iosevka
|
|
||||||
nerd-fonts.iosevka-term
|
|
||||||
];
|
|
||||||
services = {
|
|
||||||
pcscd = {
|
|
||||||
enable = true;
|
|
||||||
plugins = [ pkgs.ccid ];
|
|
||||||
};
|
|
||||||
|
|
||||||
openssh = {
|
|
||||||
enable = true;
|
|
||||||
openFirewall = false;
|
|
||||||
};
|
|
||||||
|
|
||||||
tailscale = {
|
|
||||||
enable = true;
|
|
||||||
useRoutingFeatures = "client";
|
|
||||||
package = pkgs-unstable.tailscale;
|
|
||||||
};
|
|
||||||
|
|
||||||
ollama = {
|
|
||||||
enable = true;
|
|
||||||
acceleration = "rocm";
|
|
||||||
environmentVariables = {
|
|
||||||
HSA_OVERRIDE_GFX_VERSION = "11.0.3";
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
borgbackup.jobs.root = {
|
|
||||||
paths = "/";
|
|
||||||
exclude = [
|
|
||||||
"/nix"
|
|
||||||
"/var/cache"
|
|
||||||
"/run"
|
|
||||||
"/sys"
|
|
||||||
"/etc"
|
|
||||||
"/swap"
|
|
||||||
"/proc"
|
|
||||||
"**/node_modules"
|
|
||||||
"**/.cargo"
|
|
||||||
"**/ruby/*/gems"
|
|
||||||
"**/.cache"
|
|
||||||
"**/.meteor"
|
|
||||||
"**/.next"
|
|
||||||
"**/.local/share/containers/cache"
|
|
||||||
"**/.local/share/containers/storage/overlay"
|
|
||||||
"**/.local/share/docker/overlay2"
|
|
||||||
"**/log/*.log"
|
|
||||||
"**/.local/share/Trash"
|
|
||||||
];
|
|
||||||
environment = {
|
|
||||||
BORG_RSH = "ssh -i /root/.ssh/id_ed25519.borg";
|
|
||||||
};
|
|
||||||
repo = "ssh://u324815-sub2@u324815.your-storagebox.de:23/./backup";
|
|
||||||
encryption = {
|
|
||||||
mode = "repokey";
|
|
||||||
passphrase = "will be overridden from environment file";
|
|
||||||
};
|
|
||||||
extraCreateArgs = [
|
|
||||||
"--stats"
|
|
||||||
"--progress"
|
|
||||||
];
|
|
||||||
inhibitsSleep = true;
|
|
||||||
compression = "auto,zstd";
|
|
||||||
startAt = "daily";
|
|
||||||
persistentTimer = true;
|
|
||||||
preHook = with pkgs; ''
|
|
||||||
${coreutils}/bin/timeout 60 ${bash}/bin/sh -c '
|
|
||||||
until ${iputils}/bin/ping -c1 your-storagebox.de; do
|
|
||||||
sleep 1
|
|
||||||
done
|
|
||||||
'
|
|
||||||
'';
|
|
||||||
postCreate = with pkgs; ''
|
|
||||||
${curl}/bin/curl "https://status.freun.dev/api/push/''${UPTIME_KUMA_TOKEN}?status=up&msg=OK&ping="
|
|
||||||
'';
|
|
||||||
prune.keep = {
|
|
||||||
within = "3d";
|
|
||||||
daily = 14;
|
|
||||||
weekly = 8;
|
|
||||||
monthly = -1;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
locate = {
|
|
||||||
enable = true;
|
|
||||||
package = pkgs.plocate;
|
|
||||||
};
|
|
||||||
|
|
||||||
protonmail-bridge = {
|
|
||||||
enable = true;
|
|
||||||
package = pkgs-unstable.protonmail-bridge;
|
|
||||||
path = [ pkgs.gnome-keyring ];
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
systemd.services.borgbackup-job-root.serviceConfig.EnvironmentFile = secrets.borgbackup-radish.path;
|
|
||||||
|
|
||||||
programs = {
|
|
||||||
zsh.enable = true;
|
|
||||||
_1password-gui = {
|
|
||||||
enable = true;
|
|
||||||
polkitPolicyOwners = [ "moco" ];
|
|
||||||
};
|
|
||||||
_1password.enable = true;
|
|
||||||
};
|
|
||||||
|
|
||||||
environment.etc."1password/custom_allowed_browsers".text = ''
|
|
||||||
vivaldi
|
|
||||||
'';
|
|
||||||
}
|
|
||||||
@@ -1,15 +0,0 @@
|
|||||||
{ lib, ... }:
|
|
||||||
{
|
|
||||||
age.secrets = lib.listToAttrs (
|
|
||||||
map
|
|
||||||
(secret: {
|
|
||||||
name = secret;
|
|
||||||
value = {
|
|
||||||
file = ../../secrets/${secret}.age;
|
|
||||||
};
|
|
||||||
})
|
|
||||||
[
|
|
||||||
"borgbackup-radish"
|
|
||||||
]
|
|
||||||
);
|
|
||||||
}
|
|
||||||
@@ -1,31 +0,0 @@
|
|||||||
{ pkgs, ... }:
|
|
||||||
{
|
|
||||||
# Define a user account. Don't forget to set a password with ‘passwd’.
|
|
||||||
users.users.jokke = {
|
|
||||||
uid = 1001;
|
|
||||||
isNormalUser = true;
|
|
||||||
extraGroups = [ "wheel" ];
|
|
||||||
shell = pkgs.zsh;
|
|
||||||
initialPassword = "changeme";
|
|
||||||
};
|
|
||||||
|
|
||||||
users.users.moco = {
|
|
||||||
uid = 1000;
|
|
||||||
isNormalUser = true;
|
|
||||||
extraGroups = [ "wheel" ];
|
|
||||||
shell = pkgs.zsh;
|
|
||||||
initialPassword = "changeme";
|
|
||||||
subUidRanges = [
|
|
||||||
{
|
|
||||||
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"
|
|
||||||
]
|
|
||||||
);
|
|
||||||
}
|
|
||||||
202
immich.nix
Normal file
202
immich.nix
Normal file
@@ -0,0 +1,202 @@
|
|||||||
|
{ pkgs, lib, ... }:
|
||||||
|
|
||||||
|
let
|
||||||
|
immich_version = "release";
|
||||||
|
storage_dir = "/mnt/storage/syncthing";
|
||||||
|
immich_data_dir = "/mnt/storage/immich";
|
||||||
|
|
||||||
|
volumeServices = names: (
|
||||||
|
lib.lists.foldl (services: name:
|
||||||
|
services // {
|
||||||
|
"podman-volume-immich_${name}" = {
|
||||||
|
path = [ pkgs.podman ];
|
||||||
|
serviceConfig = {
|
||||||
|
Type = "oneshot";
|
||||||
|
RemainAfterExit = true;
|
||||||
|
};
|
||||||
|
script = ''
|
||||||
|
podman volume inspect immich_${name} || podman volume create immich_${name}
|
||||||
|
'';
|
||||||
|
partOf = [ "podman-compose-immich-root.target" ];
|
||||||
|
wantedBy = [ "podman-compose-immich-root.target" ];
|
||||||
|
};
|
||||||
|
}
|
||||||
|
) {} names
|
||||||
|
);
|
||||||
|
|
||||||
|
containerServices = services: (
|
||||||
|
lib.lists.foldl (acc: { name, volumes ? [], ... }:
|
||||||
|
let
|
||||||
|
volume_services = map (volume: "podman-volume-immich_${volume}.service") volumes;
|
||||||
|
dependent_services = [ "podman-network-immich_default.service" ] ++ volume_services;
|
||||||
|
in
|
||||||
|
|
||||||
|
acc // {
|
||||||
|
"podman-immich_${name}" = {
|
||||||
|
serviceConfig = {
|
||||||
|
Restart = lib.mkOverride 500 "always";
|
||||||
|
};
|
||||||
|
after = dependent_services;
|
||||||
|
requires = dependent_services;
|
||||||
|
partOf = [
|
||||||
|
"podman-compose-immich-root.target"
|
||||||
|
];
|
||||||
|
wantedBy = [
|
||||||
|
"podman-compose-immich-root.target"
|
||||||
|
];
|
||||||
|
};
|
||||||
|
}
|
||||||
|
)
|
||||||
|
{} services
|
||||||
|
);
|
||||||
|
in {
|
||||||
|
# Containers
|
||||||
|
virtualisation.oci-containers.containers = {
|
||||||
|
"immich_machine_learning" = {
|
||||||
|
image = "ghcr.io/immich-app/immich-machine-learning:${immich_version}";
|
||||||
|
environmentFiles = [
|
||||||
|
"/var/secrets/immich.env"
|
||||||
|
];
|
||||||
|
volumes = [
|
||||||
|
"immich_model_cache:/cache:rw"
|
||||||
|
];
|
||||||
|
log-driver = "journald";
|
||||||
|
extraOptions = [
|
||||||
|
"--network-alias=immich-machine-learning"
|
||||||
|
"--network=immich_default"
|
||||||
|
];
|
||||||
|
};
|
||||||
|
|
||||||
|
"immich_microservices" = {
|
||||||
|
image = "ghcr.io/immich-app/immich-server:${immich_version}";
|
||||||
|
environmentFiles = [
|
||||||
|
"/var/secrets/immich.env"
|
||||||
|
];
|
||||||
|
volumes = [
|
||||||
|
"/etc/localtime:/etc/localtime:ro"
|
||||||
|
"${immich_data_dir}:/usr/src/app/upload:rw"
|
||||||
|
"${storage_dir}:${storage_dir}:ro"
|
||||||
|
];
|
||||||
|
cmd = [ "start.sh" "microservices" ];
|
||||||
|
dependsOn = [
|
||||||
|
"immich_postgres"
|
||||||
|
"immich_redis"
|
||||||
|
];
|
||||||
|
log-driver = "journald";
|
||||||
|
extraOptions = [
|
||||||
|
"--network-alias=immich-microservices"
|
||||||
|
"--network=immich_default"
|
||||||
|
];
|
||||||
|
};
|
||||||
|
|
||||||
|
"immich_postgres" = {
|
||||||
|
image = "registry.hub.docker.com/tensorchord/pgvecto-rs:pg14-v0.2.0";
|
||||||
|
environmentFiles = [
|
||||||
|
"/var/secrets/immich.env"
|
||||||
|
];
|
||||||
|
environment = {
|
||||||
|
POSTGRES_INITDB_ARGS = "--data-checksums";
|
||||||
|
};
|
||||||
|
volumes = [
|
||||||
|
"immich_db_data:/var/lib/postgresql/data:rw"
|
||||||
|
];
|
||||||
|
cmd = [ "postgres" "-c" "shared_preload_libraries=vectors.so" "-c" "search_path=\"$user\", public, vectors" "-c" "logging_collector=on" "-c" "max_wal_size=2GB" "-c" "shared_buffers=512MB" "-c" "wal_compression=on" ];
|
||||||
|
log-driver = "journald";
|
||||||
|
extraOptions = [
|
||||||
|
"--network-alias=database"
|
||||||
|
"--network=immich_default"
|
||||||
|
];
|
||||||
|
};
|
||||||
|
|
||||||
|
"immich_redis" = {
|
||||||
|
image = "registry.hub.docker.com/library/redis:6.2-alpine";
|
||||||
|
environmentFiles = [
|
||||||
|
"/var/secrets/immich.env"
|
||||||
|
];
|
||||||
|
log-driver = "journald";
|
||||||
|
extraOptions = [
|
||||||
|
"--network-alias=redis"
|
||||||
|
"--network=immich_default"
|
||||||
|
];
|
||||||
|
};
|
||||||
|
|
||||||
|
"immich_server" = {
|
||||||
|
image = "ghcr.io/immich-app/immich-server:${immich_version}";
|
||||||
|
environmentFiles = [
|
||||||
|
"/var/secrets/immich.env"
|
||||||
|
];
|
||||||
|
volumes = [
|
||||||
|
"/etc/localtime:/etc/localtime:ro"
|
||||||
|
"${immich_data_dir}:/usr/src/app/upload:rw"
|
||||||
|
"${storage_dir}:${storage_dir}:ro"
|
||||||
|
];
|
||||||
|
ports = [
|
||||||
|
"2283:3001/tcp"
|
||||||
|
];
|
||||||
|
cmd = [ "start.sh" "immich" ];
|
||||||
|
dependsOn = [
|
||||||
|
"immich_postgres"
|
||||||
|
"immich_redis"
|
||||||
|
];
|
||||||
|
log-driver = "journald";
|
||||||
|
extraOptions = [
|
||||||
|
"--network-alias=immich-server"
|
||||||
|
"--network=immich_default"
|
||||||
|
];
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
systemd.services = (containerServices [
|
||||||
|
{ name = "machine_learning"; volumes = [ "model_cache" ]; }
|
||||||
|
{ name = "postgres"; volumes = [ "db_data" ]; }
|
||||||
|
{ name = "redis"; }
|
||||||
|
{ name = "server"; }
|
||||||
|
{ name = "microservices"; }
|
||||||
|
]) // {
|
||||||
|
# Networks
|
||||||
|
"podman-network-immich_default" = {
|
||||||
|
path = [ pkgs.podman ];
|
||||||
|
serviceConfig = {
|
||||||
|
Type = "oneshot";
|
||||||
|
RemainAfterExit = true;
|
||||||
|
ExecStop = "${pkgs.podman}/bin/podman network rm -f immich_default";
|
||||||
|
};
|
||||||
|
script = ''
|
||||||
|
podman network inspect immich_default || podman network create immich_default
|
||||||
|
'';
|
||||||
|
partOf = [ "podman-compose-immich-root.target" ];
|
||||||
|
wantedBy = [ "podman-compose-immich-root.target" ];
|
||||||
|
};
|
||||||
|
} // (volumeServices [
|
||||||
|
"db_data"
|
||||||
|
"model_cache"
|
||||||
|
]);
|
||||||
|
|
||||||
|
# Root service
|
||||||
|
# When started, this will automatically create all resources and start
|
||||||
|
# the containers. When stopped, this will teardown all resources.
|
||||||
|
systemd.targets."podman-compose-immich-root" = {
|
||||||
|
unitConfig = {
|
||||||
|
Description = "Root target generated by compose2nix.";
|
||||||
|
};
|
||||||
|
wantedBy = [ "multi-user.target" ];
|
||||||
|
};
|
||||||
|
|
||||||
|
services.caddy.virtualHosts = {
|
||||||
|
"img.freun.dev".extraConfig = ''
|
||||||
|
reverse_proxy localhost:2283
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
fileSystems."${immich_data_dir}" = {
|
||||||
|
device = "//u407959.your-storagebox.de/backup/immich";
|
||||||
|
fsType = "cifs";
|
||||||
|
options = let
|
||||||
|
# this line prevents hanging on network split
|
||||||
|
automount_opts = "x-systemd.automount,auto,x-systemd.device-timeout=5s,x-systemd.mount-timeout=5s";
|
||||||
|
|
||||||
|
in ["${automount_opts},credentials=/var/secrets/smb-storage"];
|
||||||
|
};
|
||||||
|
|
||||||
|
environment.systemPackages = [ pkgs.cifs-utils ];
|
||||||
|
}
|
||||||
@@ -1,17 +0,0 @@
|
|||||||
{ inputs, config, ... }:
|
|
||||||
{
|
|
||||||
_module.args = {
|
|
||||||
pkgs-unstable = import inputs.nixpkgs-unstable {
|
|
||||||
system = config.nixpkgs.hostPlatform.system;
|
|
||||||
config = config.nixpkgs.config;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
imports = [
|
|
||||||
./vlans.nix
|
|
||||||
./firewall.nix
|
|
||||||
./storage-box-mounts.nix
|
|
||||||
./services
|
|
||||||
inputs.agenix.nixosModules.default
|
|
||||||
];
|
|
||||||
}
|
|
||||||
@@ -1,69 +0,0 @@
|
|||||||
{ lib, config, ... }:
|
|
||||||
let
|
|
||||||
services = {
|
|
||||||
ssh = {
|
|
||||||
tcp = [ 22 ];
|
|
||||||
};
|
|
||||||
dhcp = {
|
|
||||||
udp = [
|
|
||||||
67
|
|
||||||
68
|
|
||||||
];
|
|
||||||
};
|
|
||||||
dns = {
|
|
||||||
udp = [
|
|
||||||
53
|
|
||||||
853
|
|
||||||
];
|
|
||||||
tcp = [
|
|
||||||
53
|
|
||||||
853
|
|
||||||
];
|
|
||||||
};
|
|
||||||
web = {
|
|
||||||
tcp = [
|
|
||||||
80
|
|
||||||
443
|
|
||||||
];
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
rulesForServices =
|
|
||||||
enabledServices:
|
|
||||||
lib.foldr
|
|
||||||
(
|
|
||||||
service:
|
|
||||||
{ allowedUDPPorts, allowedTCPPorts }:
|
|
||||||
{
|
|
||||||
allowedUDPPorts = allowedUDPPorts ++ services.${service}.udp or [ ];
|
|
||||||
allowedTCPPorts = allowedTCPPorts ++ services.${service}.tcp or [ ];
|
|
||||||
}
|
|
||||||
)
|
|
||||||
{
|
|
||||||
allowedUDPPorts = [ ];
|
|
||||||
allowedTCPPorts = [ ];
|
|
||||||
}
|
|
||||||
enabledServices;
|
|
||||||
|
|
||||||
cfg = config.modules.firewall;
|
|
||||||
in
|
|
||||||
{
|
|
||||||
options.modules.firewall = {
|
|
||||||
enable = lib.mkEnableOption "Enable the firewall";
|
|
||||||
interfaces = lib.mkOption {
|
|
||||||
type = lib.types.attrsOf (lib.types.listOf (lib.types.enum (lib.attrNames services)));
|
|
||||||
default = { };
|
|
||||||
};
|
|
||||||
allInterfaces = lib.mkOption {
|
|
||||||
type = lib.types.listOf (lib.types.enum (lib.attrNames services));
|
|
||||||
default = [ ];
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
config = lib.mkIf cfg.enable {
|
|
||||||
networking.firewall = {
|
|
||||||
enable = true;
|
|
||||||
interfaces = lib.mapAttrs (_: enabledServices: rulesForServices enabledServices) cfg.interfaces;
|
|
||||||
} // rulesForServices cfg.allInterfaces;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
@@ -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,63 +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;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
systemd.services.adguardhome = {
|
|
||||||
requires = [ "tailscaled.service" ];
|
|
||||||
after = [ "tailscaled.service" ];
|
|
||||||
};
|
|
||||||
|
|
||||||
services.webserver.vHosts.${fqdn} = {
|
|
||||||
tailscaleAuth = true;
|
|
||||||
locations."/".proxyPort = cfg.port;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
}
|
|
||||||
@@ -1,36 +0,0 @@
|
|||||||
{ ... }:
|
|
||||||
{
|
|
||||||
imports = [
|
|
||||||
./webserver.nix
|
|
||||||
./vaultwarden.nix
|
|
||||||
./immich.nix
|
|
||||||
./syncthing.nix
|
|
||||||
./invidious.nix
|
|
||||||
./grafana.nix
|
|
||||||
./gtrackmap.nix
|
|
||||||
./owncast.nix
|
|
||||||
./tailscale.nix
|
|
||||||
./workout-tracker.nix
|
|
||||||
./gotosocial.nix
|
|
||||||
./hastebin.nix
|
|
||||||
./workout-sync.nix
|
|
||||||
./readeck.nix
|
|
||||||
./donetick.nix
|
|
||||||
./dnote.nix
|
|
||||||
./octodns.nix
|
|
||||||
./adguardhome.nix
|
|
||||||
./mealie.nix
|
|
||||||
./uptime-kuma.nix
|
|
||||||
./mosquitto.nix
|
|
||||||
./home-assistant.nix
|
|
||||||
./weechat.nix
|
|
||||||
./hledger-web.nix
|
|
||||||
./glance.nix
|
|
||||||
./sillytavern.nix
|
|
||||||
./nqptp.nix
|
|
||||||
./actual.nix
|
|
||||||
./voidauth.nix
|
|
||||||
./gitea.nix
|
|
||||||
./dhcp-dns-sync
|
|
||||||
];
|
|
||||||
}
|
|
||||||
@@ -1,117 +0,0 @@
|
|||||||
{
|
|
||||||
lib,
|
|
||||||
config,
|
|
||||||
pkgs,
|
|
||||||
...
|
|
||||||
}:
|
|
||||||
let
|
|
||||||
cfg = config.modules.services.dhcp-dns-sync;
|
|
||||||
|
|
||||||
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
|
|
||||||
systemd.tmpfiles.rules = [
|
|
||||||
"d /var/lib/unbound 0755 unbound unbound -"
|
|
||||||
"f ${cfg.unboundConfigPath} 0644 dhcp-dns-sync dhcp-dns-sync -"
|
|
||||||
];
|
|
||||||
|
|
||||||
# Extend Unbound configuration to include generated file
|
|
||||||
services.unbound.settings = {
|
|
||||||
server = {
|
|
||||||
local-zone = [ "${cfg.domain}. static" ];
|
|
||||||
include = cfg.unboundConfigPath;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
# 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 = "dhcp-dns-sync";
|
|
||||||
# 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,182 +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 reverse_ptr(ip : String) : String?
|
|
||||||
parts = ip.split('.')
|
|
||||||
return nil unless parts.size == 4
|
|
||||||
|
|
||||||
"#{parts[3]}.#{parts[2]}.#{parts[1]}.#{parts[0]}.in-addr.arpa."
|
|
||||||
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
|
|
||||||
if ptr = reverse_ptr(lease.address)
|
|
||||||
lines << %{local-data-ptr: "#{ptr} #{fqdn}"}
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
lines.join("\n") + "\n"
|
|
||||||
end
|
|
||||||
|
|
||||||
def get_leases(interface : String, networkctl_path : String? = nil) : Array(Lease)
|
|
||||||
cmd = networkctl_path ? "#{networkctl_path} status #{interface} --json=short" : "networkctl status #{interface} --json=short"
|
|
||||||
output = `#{cmd}`
|
|
||||||
raise "networkctl failed (exit code #{$?.exit_status}): #{output}" unless $?.success?
|
|
||||||
|
|
||||||
status = NetworkStatus.from_json(output)
|
|
||||||
status.dhcp_server.try(&.leases) || [] of Lease
|
|
||||||
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} reload" : "unbound-control reload"
|
|
||||||
puts "Reloading Unbound..."
|
|
||||||
result = system(cmd)
|
|
||||||
unless result
|
|
||||||
# Fallback to systemctl
|
|
||||||
system("systemctl reload unbound")
|
|
||||||
end
|
|
||||||
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,138 +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 = {
|
|
||||||
GO_ENV = "PRODUCTION";
|
|
||||||
OnPremises = true;
|
|
||||||
DBHost = "/var/run/postgresql";
|
|
||||||
DBPort = config.services.postgresql.settings.port;
|
|
||||||
DBUser = cfg.user;
|
|
||||||
WebURL = "https://${fqdn}";
|
|
||||||
};
|
|
||||||
|
|
||||||
serializeEnvVar =
|
|
||||||
value: if (lib.isBool value) then if value then "true" else "false" else toString value;
|
|
||||||
in
|
|
||||||
{
|
|
||||||
options.services.dnote = {
|
|
||||||
enable = lib.mkEnableOption "Enable dnote server";
|
|
||||||
subdomain = lib.mkOption {
|
|
||||||
type = lib.types.str;
|
|
||||||
};
|
|
||||||
user = lib.mkOption {
|
|
||||||
type = lib.types.str;
|
|
||||||
default = "dnote";
|
|
||||||
};
|
|
||||||
port = lib.mkOption {
|
|
||||||
type = lib.types.int;
|
|
||||||
default = 3040;
|
|
||||||
};
|
|
||||||
environment = lib.mkOption {
|
|
||||||
type = types.environment;
|
|
||||||
default = { };
|
|
||||||
};
|
|
||||||
environmentFile = lib.mkOption {
|
|
||||||
type = lib.types.nullOr lib.types.path;
|
|
||||||
default = null;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
config = lib.mkIf cfg.enable {
|
|
||||||
users = {
|
|
||||||
users.${cfg.user} = {
|
|
||||||
isSystemUser = true;
|
|
||||||
group = cfg.user;
|
|
||||||
};
|
|
||||||
groups.${cfg.user} = { };
|
|
||||||
};
|
|
||||||
|
|
||||||
systemd.services.dnote = {
|
|
||||||
enable = true;
|
|
||||||
description = "Dnote server";
|
|
||||||
environment = lib.mapAttrs (_: value: serializeEnvVar value) (
|
|
||||||
cfg.environment // immutableEnvironment
|
|
||||||
);
|
|
||||||
after = [ "postgresql.service" ];
|
|
||||||
requires = [ "postgresql.service" ];
|
|
||||||
serviceConfig = {
|
|
||||||
ExecStart = "${pkgs-unstable.dnote}/bin/dnote-server -port ${toString cfg.port} start";
|
|
||||||
EnvironmentFile = lib.mkIf (cfg.environmentFile != null) cfg.environmentFile;
|
|
||||||
User = cfg.user;
|
|
||||||
BindPaths = [
|
|
||||||
"/var/run/postgresql"
|
|
||||||
];
|
|
||||||
BindReadOnlyPaths = [
|
|
||||||
/run/systemd/resolve/stub-resolv.conf
|
|
||||||
/etc/ssl
|
|
||||||
/etc/static/ssl
|
|
||||||
/etc/resolv.conf
|
|
||||||
/etc/static/resolv.conf
|
|
||||||
/etc/nsswitch.conf
|
|
||||||
/etc/static/nsswitch.conf
|
|
||||||
/etc/hosts
|
|
||||||
];
|
|
||||||
};
|
|
||||||
confinement = {
|
|
||||||
enable = true;
|
|
||||||
packages = [ pkgs.cacert ];
|
|
||||||
};
|
|
||||||
wantedBy = [ "multi-user.target" ];
|
|
||||||
};
|
|
||||||
|
|
||||||
services = {
|
|
||||||
postgresql = {
|
|
||||||
enable = lib.mkDefault true;
|
|
||||||
ensureDatabases = [ cfg.environment.DBName ];
|
|
||||||
ensureUsers = [
|
|
||||||
{
|
|
||||||
name = cfg.user;
|
|
||||||
ensureDBOwnership = true;
|
|
||||||
}
|
|
||||||
];
|
|
||||||
};
|
|
||||||
|
|
||||||
webserver = {
|
|
||||||
enable = lib.mkDefault true;
|
|
||||||
vHosts.${fqdn} = {
|
|
||||||
proxyBuffering = false;
|
|
||||||
locations."/".proxyPort = cfg.port;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
};
|
|
||||||
};
|
|
||||||
}
|
|
||||||
@@ -1,217 +0,0 @@
|
|||||||
{
|
|
||||||
lib,
|
|
||||||
pkgs,
|
|
||||||
config,
|
|
||||||
...
|
|
||||||
}:
|
|
||||||
let
|
|
||||||
types = {
|
|
||||||
jwtSettings = {
|
|
||||||
session_time = lib.mkOption {
|
|
||||||
type = lib.types.str;
|
|
||||||
default = "168h";
|
|
||||||
};
|
|
||||||
max_refresh = lib.mkOption {
|
|
||||||
type = lib.types.str;
|
|
||||||
default = "168h";
|
|
||||||
};
|
|
||||||
};
|
|
||||||
serverSettings = {
|
|
||||||
port = lib.mkOption {
|
|
||||||
type = lib.types.int;
|
|
||||||
default = 2021;
|
|
||||||
};
|
|
||||||
read_timeout = lib.mkOption {
|
|
||||||
type = lib.types.str;
|
|
||||||
default = "10s";
|
|
||||||
};
|
|
||||||
write_timeout = lib.mkOption {
|
|
||||||
type = lib.types.str;
|
|
||||||
default = "10s";
|
|
||||||
};
|
|
||||||
rate_period = lib.mkOption {
|
|
||||||
type = lib.types.str;
|
|
||||||
default = "60s";
|
|
||||||
};
|
|
||||||
rate_limit = lib.mkOption {
|
|
||||||
type = lib.types.int;
|
|
||||||
default = 300;
|
|
||||||
};
|
|
||||||
cors_allow_origins = lib.mkOption {
|
|
||||||
type = lib.types.listOf lib.types.str;
|
|
||||||
default = [
|
|
||||||
"http://localhost:5173"
|
|
||||||
"http://localhost:7926"
|
|
||||||
"https://localhost"
|
|
||||||
"capacitor://localhost"
|
|
||||||
];
|
|
||||||
};
|
|
||||||
serve_frontend = lib.mkOption {
|
|
||||||
type = lib.types.bool;
|
|
||||||
default = true;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
schedulerSettings = {
|
|
||||||
due_job = lib.mkOption {
|
|
||||||
type = lib.types.str;
|
|
||||||
default = "30m";
|
|
||||||
};
|
|
||||||
overdue_job = lib.mkOption {
|
|
||||||
type = lib.types.str;
|
|
||||||
default = "3h";
|
|
||||||
};
|
|
||||||
pre_due_job = lib.mkOption {
|
|
||||||
type = lib.types.str;
|
|
||||||
default = "3h";
|
|
||||||
};
|
|
||||||
};
|
|
||||||
emailSettings = {
|
|
||||||
host = lib.mkOption {
|
|
||||||
type = lib.types.str;
|
|
||||||
default = "";
|
|
||||||
};
|
|
||||||
port = lib.mkOption {
|
|
||||||
type = lib.types.int;
|
|
||||||
default = 587;
|
|
||||||
};
|
|
||||||
email = lib.mkOption {
|
|
||||||
type = lib.types.str;
|
|
||||||
default = "";
|
|
||||||
};
|
|
||||||
key = lib.mkOption {
|
|
||||||
type = lib.types.str;
|
|
||||||
default = "";
|
|
||||||
};
|
|
||||||
};
|
|
||||||
oauth2Settings = {
|
|
||||||
client_id = lib.mkOption {
|
|
||||||
type = lib.types.str;
|
|
||||||
default = "";
|
|
||||||
};
|
|
||||||
client_secret = lib.mkOption {
|
|
||||||
type = lib.types.str;
|
|
||||||
default = "";
|
|
||||||
};
|
|
||||||
auth_url = lib.mkOption {
|
|
||||||
type = lib.types.str;
|
|
||||||
default = "";
|
|
||||||
};
|
|
||||||
token_url = lib.mkOption {
|
|
||||||
type = lib.types.str;
|
|
||||||
default = "";
|
|
||||||
};
|
|
||||||
user_info_url = lib.mkOption {
|
|
||||||
type = lib.types.str;
|
|
||||||
default = "";
|
|
||||||
};
|
|
||||||
redirect_url = lib.mkOption {
|
|
||||||
type = lib.types.str;
|
|
||||||
default = "";
|
|
||||||
};
|
|
||||||
name = lib.mkOption {
|
|
||||||
type = lib.types.str;
|
|
||||||
default = "";
|
|
||||||
};
|
|
||||||
};
|
|
||||||
settings = lib.types.submodule {
|
|
||||||
options = {
|
|
||||||
is_user_creation_disabled = lib.mkEnableOption "Disable user creation";
|
|
||||||
telegram.token = lib.mkOption {
|
|
||||||
type = lib.types.str;
|
|
||||||
default = "";
|
|
||||||
};
|
|
||||||
pushover.token = lib.mkOption {
|
|
||||||
type = lib.types.str;
|
|
||||||
default = "";
|
|
||||||
};
|
|
||||||
jwt = types.jwtSettings;
|
|
||||||
server = types.serverSettings;
|
|
||||||
scheduler_jobs = types.schedulerSettings;
|
|
||||||
email = types.emailSettings;
|
|
||||||
oauth2 = types.oauth2Settings;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
};
|
|
||||||
version = "0.0.33";
|
|
||||||
|
|
||||||
package = pkgs.stdenv.mkDerivation {
|
|
||||||
name = "donetick";
|
|
||||||
src = pkgs.fetchurl {
|
|
||||||
url = "https://github.com/donetick/donetick/releases/download/v${version}/donetick_Linux_arm64.tar.gz";
|
|
||||||
hash = "sha256-o5PcONv+fxBMToOCwBcr2fnSpsHn5bdfujyUTuMKTbI=";
|
|
||||||
};
|
|
||||||
nativeBuildInputs = [
|
|
||||||
pkgs.autoPatchelfHook
|
|
||||||
];
|
|
||||||
sourceRoot = ".";
|
|
||||||
installPhase = ''
|
|
||||||
runHook preInstall
|
|
||||||
install -Dm755 donetick $out/bin/donetick
|
|
||||||
runHook postInstall
|
|
||||||
'';
|
|
||||||
meta = with pkgs.lib; {
|
|
||||||
description = "A self-hosted task and chore manager";
|
|
||||||
license = licenses.mit;
|
|
||||||
mainProgram = "donetick";
|
|
||||||
};
|
|
||||||
};
|
|
||||||
cfg = config.services.donetick;
|
|
||||||
fqdn = "${cfg.subdomain}.${config.networking.domain}";
|
|
||||||
|
|
||||||
immutableSettings = {
|
|
||||||
name = "selfhosted";
|
|
||||||
is_done_tick_dot_com = false;
|
|
||||||
email.appHost = "https://${fqdn}";
|
|
||||||
database = {
|
|
||||||
type = "sqlite";
|
|
||||||
migration = true;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
settings = (pkgs.formats.yaml { }).generate "selfhosted.yaml" (cfg.settings // immutableSettings);
|
|
||||||
secrets = config.age.secrets;
|
|
||||||
in
|
|
||||||
{
|
|
||||||
options.services.donetick = {
|
|
||||||
enable = lib.mkEnableOption "Enable donetick";
|
|
||||||
subdomain = lib.mkOption {
|
|
||||||
type = lib.types.str;
|
|
||||||
};
|
|
||||||
settings = lib.mkOption {
|
|
||||||
type = types.settings;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
config = lib.mkIf cfg.enable {
|
|
||||||
systemd.services.donetick = {
|
|
||||||
enable = true;
|
|
||||||
environment = {
|
|
||||||
DT_ENV = "selfhosted";
|
|
||||||
};
|
|
||||||
serviceConfig = {
|
|
||||||
DynamicUser = true;
|
|
||||||
ExecStart = "${package}/bin/donetick";
|
|
||||||
BindReadOnlyPaths = [
|
|
||||||
"${settings}:/var/lib/donetick/config/selfhosted.yaml"
|
|
||||||
/run/systemd/resolve/stub-resolv.conf
|
|
||||||
/etc/ssl
|
|
||||||
/etc/static/ssl
|
|
||||||
/etc/resolv.conf
|
|
||||||
/etc/static/resolv.conf
|
|
||||||
/etc/nsswitch.conf
|
|
||||||
/etc/static/nsswitch.conf
|
|
||||||
/etc/hosts
|
|
||||||
];
|
|
||||||
WorkingDirectory = "/var/lib/donetick";
|
|
||||||
StateDirectory = "donetick";
|
|
||||||
EnvironmentFile = secrets.donetick.path;
|
|
||||||
};
|
|
||||||
wantedBy = [ "multi-user.target" ];
|
|
||||||
confinement.enable = true;
|
|
||||||
};
|
|
||||||
|
|
||||||
services.webserver = {
|
|
||||||
enable = lib.mkDefault true;
|
|
||||||
vHosts.${fqdn}.locations."/".proxyPort = cfg.settings.server.port;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
}
|
|
||||||
@@ -1,71 +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;
|
|
||||||
};
|
|
||||||
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;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
}
|
|
||||||
@@ -1,53 +0,0 @@
|
|||||||
{ config, lib, ... }:
|
|
||||||
let
|
|
||||||
cfg = config.services.gotosocial;
|
|
||||||
secrets = config.age.secrets;
|
|
||||||
domain = config.networking.domain;
|
|
||||||
fqdn = "${cfg.subdomain}.${domain}";
|
|
||||||
port = cfg.settings.port;
|
|
||||||
in
|
|
||||||
{
|
|
||||||
options.services.gotosocial = {
|
|
||||||
subdomain = lib.mkOption {
|
|
||||||
type = lib.types.str;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
config = lib.mkIf cfg.enable {
|
|
||||||
services = {
|
|
||||||
gotosocial = {
|
|
||||||
environmentFile = secrets.gotosocial.path;
|
|
||||||
settings = {
|
|
||||||
host = fqdn;
|
|
||||||
account-domain = domain;
|
|
||||||
protocol = "https";
|
|
||||||
bind-address = "localhost";
|
|
||||||
instance-inject-mastodon-version = true;
|
|
||||||
accounts-registration-open = true;
|
|
||||||
instance-expose-public-timeline = true;
|
|
||||||
letsencrypt-enabled = false;
|
|
||||||
};
|
|
||||||
setupPostgresqlDB = true;
|
|
||||||
};
|
|
||||||
|
|
||||||
webserver.vHosts = {
|
|
||||||
${domain}.locations = lib.listToAttrs (
|
|
||||||
lib.map
|
|
||||||
(path: {
|
|
||||||
name = "/.well-known/${path}";
|
|
||||||
value.extraConfig = ''
|
|
||||||
rewrite ^.*$ https://${fqdn}/.well-known/${path} permanent;
|
|
||||||
'';
|
|
||||||
})
|
|
||||||
[
|
|
||||||
"host-meta"
|
|
||||||
"webfinger"
|
|
||||||
"nodeinfo"
|
|
||||||
]
|
|
||||||
);
|
|
||||||
|
|
||||||
"${fqdn}".locations."/".proxyPort = port;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
};
|
|
||||||
}
|
|
||||||
@@ -1,21 +1,16 @@
|
|||||||
{ lib, config, ... }:
|
{ ... }:
|
||||||
let
|
let
|
||||||
cfg = config.services.grafana;
|
fqdn = "graph.freun.dev";
|
||||||
secrets = config.age.secrets;
|
port = 3300;
|
||||||
fqdn = "${cfg.subdomain}.${config.networking.domain}";
|
|
||||||
in
|
in
|
||||||
{
|
{
|
||||||
options.services.grafana = {
|
|
||||||
subdomain = lib.mkOption {
|
|
||||||
type = lib.types.str;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
config = lib.mkIf cfg.enable {
|
|
||||||
services.grafana = {
|
services.grafana = {
|
||||||
|
enable = true;
|
||||||
|
|
||||||
settings = {
|
settings = {
|
||||||
server = {
|
server = {
|
||||||
root_url = "https://${fqdn}";
|
root_url = "https://${fqdn}";
|
||||||
|
http_port = port;
|
||||||
};
|
};
|
||||||
|
|
||||||
database = {
|
database = {
|
||||||
@@ -25,14 +20,17 @@ in
|
|||||||
};
|
};
|
||||||
|
|
||||||
smtp = {
|
smtp = {
|
||||||
from_name = "Grafana";
|
enabled = true;
|
||||||
password = "$__file{${secrets.smtp-password.path}}";
|
host = "horologium.uberspace.de";
|
||||||
|
from_address = "noreply@freun.dev";
|
||||||
|
from_name = "Vaultwarden";
|
||||||
|
user = "noreply@freun.dev";
|
||||||
|
password = "$__file{/var/secrets/smtp-password}";
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
services = {
|
services.prometheus = {
|
||||||
prometheus = {
|
|
||||||
enable = true;
|
enable = true;
|
||||||
exporters.node.enable = true;
|
exporters.node.enable = true;
|
||||||
scrapeConfigs = [
|
scrapeConfigs = [
|
||||||
@@ -45,18 +43,18 @@ in
|
|||||||
];
|
];
|
||||||
};
|
};
|
||||||
|
|
||||||
webserver.vHosts.${fqdn}.locations."/".proxyPort = cfg.settings.server.http_port;
|
services.caddy.virtualHosts = {
|
||||||
|
"${fqdn}".extraConfig = ''
|
||||||
|
reverse_proxy localhost:${builtins.toString port}
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
postgresql = {
|
services.postgresql = {
|
||||||
enable = lib.mkDefault true;
|
|
||||||
ensureDatabases = [ "grafana" ];
|
ensureDatabases = [ "grafana" ];
|
||||||
ensureUsers = [
|
ensureUsers = [{
|
||||||
{
|
|
||||||
name = "grafana";
|
name = "grafana";
|
||||||
ensureDBOwnership = true;
|
ensureDBOwnership = true;
|
||||||
}
|
}];
|
||||||
];
|
|
||||||
};
|
|
||||||
};
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,25 +1,16 @@
|
|||||||
{
|
{ config, ... }:
|
||||||
lib,
|
|
||||||
config,
|
|
||||||
inputs,
|
|
||||||
...
|
|
||||||
}:
|
|
||||||
let
|
let
|
||||||
cfg = config.services.gtrackmap;
|
fqdn = "trackmap.freun.dev";
|
||||||
fqdn = "${cfg.subdomain}.${config.networking.domain}";
|
|
||||||
in
|
in
|
||||||
{
|
{
|
||||||
imports = [
|
services.gtrackmap = {
|
||||||
inputs.gtrackmap.nixosModules.default
|
enable = true;
|
||||||
];
|
port = 3200;
|
||||||
|
|
||||||
options.services.gtrackmap = {
|
|
||||||
subdomain = lib.mkOption {
|
|
||||||
type = lib.types.str;
|
|
||||||
};
|
|
||||||
};
|
};
|
||||||
|
|
||||||
config = lib.mkIf cfg.enable {
|
services.caddy.virtualHosts = {
|
||||||
services.webserver.vHosts.${fqdn}.locations."/".proxyPort = cfg.port;
|
"${fqdn}".extraConfig = ''
|
||||||
|
reverse_proxy localhost:${toString config.services.gtrackmap.port}
|
||||||
|
'';
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,61 +0,0 @@
|
|||||||
{
|
|
||||||
lib,
|
|
||||||
config,
|
|
||||||
inputs,
|
|
||||||
...
|
|
||||||
}:
|
|
||||||
let
|
|
||||||
cfg = config.services.hastebin;
|
|
||||||
secrets = config.age.secrets;
|
|
||||||
fqdn = "${cfg.subdomain}.${config.networking.domain}";
|
|
||||||
in
|
|
||||||
{
|
|
||||||
imports = [
|
|
||||||
inputs.hastebin.nixosModules.default
|
|
||||||
];
|
|
||||||
|
|
||||||
options.services.hastebin.subdomain = lib.mkOption {
|
|
||||||
type = lib.types.str;
|
|
||||||
};
|
|
||||||
|
|
||||||
config = lib.mkIf cfg.enable {
|
|
||||||
services.hastebin.settings = lib.mkDefault {
|
|
||||||
max_size = "1 GiB";
|
|
||||||
host = "::1";
|
|
||||||
port = 3600;
|
|
||||||
mime_overrides = {
|
|
||||||
"text/plain" = [
|
|
||||||
"log"
|
|
||||||
"txt"
|
|
||||||
"diff"
|
|
||||||
"sh"
|
|
||||||
"rs"
|
|
||||||
"toml"
|
|
||||||
"cr"
|
|
||||||
"nix"
|
|
||||||
"rb"
|
|
||||||
"ts"
|
|
||||||
"tsx"
|
|
||||||
"jsx"
|
|
||||||
];
|
|
||||||
};
|
|
||||||
auth_tokens_file = secrets.hastebin-tokens.path;
|
|
||||||
};
|
|
||||||
|
|
||||||
services.webserver = {
|
|
||||||
enable = lib.mkDefault true;
|
|
||||||
vHosts.${fqdn} = {
|
|
||||||
proxyBuffering = false;
|
|
||||||
locations."/" = {
|
|
||||||
proxyPort = cfg.settings.port;
|
|
||||||
extraConfig = ''
|
|
||||||
client_max_body_size 0;
|
|
||||||
proxy_send_timeout 300;
|
|
||||||
proxy_read_timeout 300;
|
|
||||||
send_timeout 300;
|
|
||||||
'';
|
|
||||||
};
|
|
||||||
};
|
|
||||||
};
|
|
||||||
};
|
|
||||||
}
|
|
||||||
@@ -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;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
}
|
|
||||||
21
modules/services/hydra.nix
Normal file
21
modules/services/hydra.nix
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
{ ... }:
|
||||||
|
let
|
||||||
|
fqdn = "ci.freun.dev";
|
||||||
|
port = 3400;
|
||||||
|
in
|
||||||
|
{
|
||||||
|
services.hydra = {
|
||||||
|
enable = true;
|
||||||
|
hydraURL = "https://${fqdn}";
|
||||||
|
notificationSender = "Hydra <noreply@freun.dev>";
|
||||||
|
buildMachinesFiles = [];
|
||||||
|
useSubstitutes = true;
|
||||||
|
inherit port;
|
||||||
|
};
|
||||||
|
|
||||||
|
services.caddy.virtualHosts = {
|
||||||
|
"${fqdn}".extraConfig = ''
|
||||||
|
reverse_proxy localhost:${builtins.toString port}
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
}
|
||||||
@@ -1,52 +1,110 @@
|
|||||||
{ lib, config, ... }:
|
{ lib, config, ... }:
|
||||||
let
|
let
|
||||||
cfg = config.services.immich;
|
cfg = config.services.immich;
|
||||||
fqdn = "${cfg.subdomain}.${config.networking.domain}";
|
|
||||||
in
|
in
|
||||||
{
|
{
|
||||||
options.services.immich = {
|
options.services.immich = with lib; {
|
||||||
subdomain = lib.mkOption {
|
enable = mkEnableOption "Enable immich";
|
||||||
type = lib.types.str;
|
|
||||||
|
fqdn = mkOption {
|
||||||
|
type = types.str;
|
||||||
|
description = "FQDN to use for the immich server";
|
||||||
};
|
};
|
||||||
timezone = lib.mkOption {
|
data_dir = mkOption {
|
||||||
type = lib.types.str;
|
type = types.str;
|
||||||
default = "UTC";
|
description = "The directory to store immich data in";
|
||||||
};
|
};
|
||||||
uid = lib.mkOption {
|
secrets = mkOption {
|
||||||
type = lib.types.int;
|
type = types.str;
|
||||||
default = 990;
|
description = "Path to file with secrets";
|
||||||
};
|
};
|
||||||
gid = lib.mkOption {
|
version = mkOption {
|
||||||
type = lib.types.int;
|
type = types.str;
|
||||||
default = 997;
|
default = "release";
|
||||||
|
description = "The version (docker image tag) of immich to use";
|
||||||
|
};
|
||||||
|
mounts = mkOption {
|
||||||
|
type = types.listOf types.str;
|
||||||
|
description = "Additional mounts to add to the immich container";
|
||||||
|
default = [ ];
|
||||||
|
};
|
||||||
|
port = mkOption {
|
||||||
|
type = types.int;
|
||||||
|
default = 2283;
|
||||||
|
description = "Port to expose the immich server on";
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
config = lib.mkIf cfg.enable {
|
|
||||||
|
imports = [
|
||||||
|
../util/container-services.nix
|
||||||
|
];
|
||||||
|
|
||||||
|
config = lib.mkIf cfg.enable rec {
|
||||||
|
container-services.immich = {
|
||||||
|
description = "Immich image server";
|
||||||
services = {
|
services = {
|
||||||
immich = {
|
server = {
|
||||||
|
image = "ghcr.io/immich-app/immich-server:${cfg.version}";
|
||||||
|
environmentFiles = [
|
||||||
|
cfg.secrets
|
||||||
|
];
|
||||||
|
volumes = [
|
||||||
|
"${cfg.data_dir}:/usr/src/app/upload:rw"
|
||||||
|
"/etc/localtime:/etc/localtime:ro"
|
||||||
|
] ++ cfg.mounts;
|
||||||
|
ports = [ "${builtins.toString cfg.port}:3001/tcp" ];
|
||||||
|
dependsOn = [
|
||||||
|
container-services.immich.services.redis
|
||||||
|
container-services.immich.services.postgres
|
||||||
|
];
|
||||||
|
};
|
||||||
|
machine_learning = {
|
||||||
|
image = "ghcr.io/immich-app/immich-machine-learning:${cfg.version}";
|
||||||
|
environmentFiles = [
|
||||||
|
cfg.secrets
|
||||||
|
];
|
||||||
|
volumes = [
|
||||||
|
"model_cache:/cache:rw"
|
||||||
|
];
|
||||||
|
};
|
||||||
|
redis = {
|
||||||
|
image = "registry.hub.docker.com/library/redis:6.2-alpine";
|
||||||
|
healthCheck.test = "redis-cli ping || exit 1";
|
||||||
|
environmentFiles = [
|
||||||
|
cfg.secrets
|
||||||
|
];
|
||||||
|
};
|
||||||
|
postgres = {
|
||||||
|
image = "registry.hub.docker.com/tensorchord/pgvecto-rs:pg14-v0.2.0";
|
||||||
|
environmentFiles = [
|
||||||
|
cfg.secrets
|
||||||
|
];
|
||||||
environment = {
|
environment = {
|
||||||
TZ = cfg.timezone;
|
POSTGRES_INITDB_ARGS = "--data-checksums";
|
||||||
};
|
};
|
||||||
settings.server.externalDomain = "https://${fqdn}";
|
volumes = [
|
||||||
};
|
"db_data:/var/lib/postgresql/data:rw"
|
||||||
webserver = {
|
];
|
||||||
enable = lib.mkDefault true;
|
cmd = [ "postgres" "-c" "shared_preload_libraries=vectors.so" "-c" "search_path=\"$user\", public, vectors" "-c" "logging_collector=on" "-c" "max_wal_size=2GB" "-c" "shared_buffers=512MB" "-c" "wal_compression=on" ];
|
||||||
vHosts.${fqdn} = {
|
healthCheck = {
|
||||||
proxyBuffering = false;
|
test = ''
|
||||||
locations."/" = {
|
pg_isready --dbname='$\{DB_DATABASE_NAME}' || exit 1
|
||||||
proxyPort = cfg.port;
|
Chksum="$(psql --dbname='$\{DB_DATABASE_NAME}' --username='$\{DB_USERNAME}' --tuples-only --no-align --command='SELECT COALESCE(SUM(checksum_failures), 0) FROM pg_stat_database')"
|
||||||
extraConfig = ''
|
echo "checksum failure count is $Chksum"
|
||||||
client_max_body_size 0;
|
[ "$Chksum" = '0' ] || exit 1
|
||||||
proxy_send_timeout 300;
|
|
||||||
proxy_read_timeout 300;
|
|
||||||
send_timeout 300;
|
|
||||||
'';
|
'';
|
||||||
|
interval = "5m";
|
||||||
|
startInterval = "30s";
|
||||||
|
startPeriod = "5m";
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
users.users.${cfg.user}.uid = cfg.uid;
|
services.caddy.virtualHosts = {
|
||||||
users.groups.${cfg.user}.gid = cfg.gid;
|
"${cfg.fqdn}".extraConfig = ''
|
||||||
|
reverse_proxy localhost:${builtins.toString cfg.port}
|
||||||
|
'';
|
||||||
|
};
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,20 +1,11 @@
|
|||||||
{ config, lib, ... }:
|
{ ... }:
|
||||||
let
|
let
|
||||||
cfg = config.services.invidious;
|
fqdn = "vid.freun.dev";
|
||||||
fqdn = "${cfg.subdomain}.${config.networking.domain}";
|
|
||||||
in
|
in
|
||||||
{
|
{
|
||||||
options.services.invidious = {
|
services.invidious = {
|
||||||
subdomain = lib.mkOption {
|
enable = true;
|
||||||
type = lib.types.str;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
config = lib.mkIf cfg.enable {
|
|
||||||
services = {
|
|
||||||
invidious = {
|
|
||||||
domain = fqdn;
|
domain = fqdn;
|
||||||
address = "127.0.0.1";
|
|
||||||
|
|
||||||
settings = {
|
settings = {
|
||||||
external_port = 443;
|
external_port = 443;
|
||||||
@@ -25,12 +16,10 @@ in
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
postgresql.enable = lib.mkDefault true;
|
services.caddy.virtualHosts = {
|
||||||
|
"${fqdn}".extraConfig = ''
|
||||||
|
reverse_proxy localhost:3000
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
webserver = {
|
|
||||||
enable = lib.mkDefault true;
|
|
||||||
vHosts.${fqdn}.locations."/".proxyPort = cfg.port;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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,14 +0,0 @@
|
|||||||
{ config, lib, ... }:
|
|
||||||
let
|
|
||||||
cfg = config.services.mosquitto;
|
|
||||||
in
|
|
||||||
{
|
|
||||||
options = {
|
|
||||||
services.mosquitto = {
|
|
||||||
openFirewall = lib.mkEnableOption "Open firewall port for Mosquitto";
|
|
||||||
};
|
|
||||||
};
|
|
||||||
config = lib.mkIf cfg.enable {
|
|
||||||
networking.firewall.allowedTCPPorts = map ({ port, ... }: port) cfg.listeners;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
@@ -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";
|
|
||||||
};
|
|
||||||
};
|
|
||||||
};
|
|
||||||
}
|
|
||||||
@@ -1,248 +0,0 @@
|
|||||||
{
|
|
||||||
pkgs,
|
|
||||||
pkgs-unstable,
|
|
||||||
lib,
|
|
||||||
config,
|
|
||||||
...
|
|
||||||
}:
|
|
||||||
let
|
|
||||||
cfg = config.services.octodns;
|
|
||||||
secrets = config.age.secrets;
|
|
||||||
|
|
||||||
types = {
|
|
||||||
ttlOptions = default: {
|
|
||||||
ttl = lib.mkOption {
|
|
||||||
type = lib.types.int;
|
|
||||||
default = default;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
defaults = lib.types.submodule {
|
|
||||||
options = {
|
|
||||||
A = lib.mkOption {
|
|
||||||
type = lib.types.submodule {
|
|
||||||
options = types.ttlOptions cfg.defaults.ttl;
|
|
||||||
};
|
|
||||||
default = { };
|
|
||||||
};
|
|
||||||
AAAA = lib.mkOption {
|
|
||||||
type = lib.types.submodule {
|
|
||||||
options = types.ttlOptions cfg.defaults.ttl;
|
|
||||||
};
|
|
||||||
default = { };
|
|
||||||
};
|
|
||||||
CNAME = lib.mkOption {
|
|
||||||
type = lib.types.submodule {
|
|
||||||
options = types.ttlOptions cfg.defaults.ttl;
|
|
||||||
};
|
|
||||||
default = { };
|
|
||||||
};
|
|
||||||
MX = lib.mkOption {
|
|
||||||
type = lib.types.submodule {
|
|
||||||
options = types.ttlOptions cfg.defaults.ttl;
|
|
||||||
};
|
|
||||||
default = { };
|
|
||||||
};
|
|
||||||
TXT = lib.mkOption {
|
|
||||||
type = lib.types.submodule {
|
|
||||||
options = types.ttlOptions cfg.defaults.ttl;
|
|
||||||
};
|
|
||||||
default = { };
|
|
||||||
};
|
|
||||||
}
|
|
||||||
// (types.ttlOptions 3600);
|
|
||||||
};
|
|
||||||
aRecord = lib.types.submodule {
|
|
||||||
options = {
|
|
||||||
values = lib.mkOption {
|
|
||||||
type = lib.types.listOf lib.types.str;
|
|
||||||
default = [ ];
|
|
||||||
};
|
|
||||||
ttl = lib.mkOption {
|
|
||||||
type = lib.types.int;
|
|
||||||
default = cfg.defaults.A.ttl;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
};
|
|
||||||
aaaaRecord = lib.types.submodule {
|
|
||||||
options = {
|
|
||||||
values = lib.mkOption {
|
|
||||||
type = lib.types.listOf lib.types.str;
|
|
||||||
default = [ ];
|
|
||||||
};
|
|
||||||
ttl = lib.mkOption {
|
|
||||||
type = lib.types.int;
|
|
||||||
default = cfg.defaults.AAAA.ttl;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
};
|
|
||||||
cnameRecord = lib.types.submodule {
|
|
||||||
options = {
|
|
||||||
target = lib.mkOption {
|
|
||||||
type = lib.types.nullOr lib.types.str;
|
|
||||||
default = null;
|
|
||||||
};
|
|
||||||
toRoot = lib.mkOption {
|
|
||||||
type = lib.types.bool;
|
|
||||||
default = false;
|
|
||||||
};
|
|
||||||
ttl = lib.mkOption {
|
|
||||||
type = lib.types.int;
|
|
||||||
default = cfg.defaults.CNAME.ttl;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
};
|
|
||||||
mxValue = lib.types.submodule {
|
|
||||||
options = {
|
|
||||||
exchange = lib.mkOption {
|
|
||||||
type = lib.types.str;
|
|
||||||
};
|
|
||||||
preference = lib.mkOption {
|
|
||||||
type = lib.types.int;
|
|
||||||
default = 10;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
};
|
|
||||||
mxRecord = lib.types.submodule {
|
|
||||||
options = {
|
|
||||||
values = lib.mkOption {
|
|
||||||
type = lib.types.listOf types.mxValue;
|
|
||||||
default = [ ];
|
|
||||||
};
|
|
||||||
ttl = lib.mkOption {
|
|
||||||
type = lib.types.int;
|
|
||||||
default = cfg.defaults.MX.ttl;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
};
|
|
||||||
txtRecord = lib.types.submodule {
|
|
||||||
options = {
|
|
||||||
values = lib.mkOption {
|
|
||||||
type = lib.types.listOf lib.types.str;
|
|
||||||
default = [ ];
|
|
||||||
};
|
|
||||||
ttl = lib.mkOption {
|
|
||||||
type = lib.types.int;
|
|
||||||
default = cfg.defaults.AAAA.ttl;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
};
|
|
||||||
records = lib.types.submodule {
|
|
||||||
options = {
|
|
||||||
A = lib.mkOption {
|
|
||||||
type = types.aRecord;
|
|
||||||
default = { };
|
|
||||||
};
|
|
||||||
AAAA = lib.mkOption {
|
|
||||||
type = types.aaaaRecord;
|
|
||||||
default = { };
|
|
||||||
};
|
|
||||||
CNAME = lib.mkOption {
|
|
||||||
type = types.cnameRecord;
|
|
||||||
default = { };
|
|
||||||
};
|
|
||||||
MX = lib.mkOption {
|
|
||||||
type = types.mxRecord;
|
|
||||||
default = { };
|
|
||||||
};
|
|
||||||
TXT = lib.mkOption {
|
|
||||||
type = types.txtRecord;
|
|
||||||
default = { };
|
|
||||||
};
|
|
||||||
};
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
yamlFormat = pkgs.formats.yaml { };
|
|
||||||
|
|
||||||
zoneFile = yamlFormat.generate "octodns-zone" (
|
|
||||||
lib.filterAttrs (_: records: (lib.length records) > 0) (
|
|
||||||
lib.mapAttrs (
|
|
||||||
_: types:
|
|
||||||
lib.filter
|
|
||||||
(
|
|
||||||
{
|
|
||||||
values ? [ ],
|
|
||||||
value ? null,
|
|
||||||
...
|
|
||||||
}:
|
|
||||||
(lib.length values) > 0 || !(builtins.isNull value)
|
|
||||||
)
|
|
||||||
(
|
|
||||||
lib.mapAttrsToList (
|
|
||||||
type:
|
|
||||||
{ ttl, ... }@options:
|
|
||||||
if (type == "CNAME") then
|
|
||||||
let
|
|
||||||
inherit (options) target toRoot;
|
|
||||||
value = if toRoot then "${config.networking.domain}." else target;
|
|
||||||
in
|
|
||||||
{
|
|
||||||
inherit type ttl value;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
inherit type ttl;
|
|
||||||
inherit (options) values;
|
|
||||||
}
|
|
||||||
) types
|
|
||||||
)
|
|
||||||
) cfg.records
|
|
||||||
)
|
|
||||||
);
|
|
||||||
|
|
||||||
zonesDir = pkgs.linkFarm "octodns-zones" {
|
|
||||||
"${config.networking.domain}.yaml" = zoneFile;
|
|
||||||
};
|
|
||||||
|
|
||||||
configFile = yamlFormat.generate "octodns-config.yaml" {
|
|
||||||
providers = {
|
|
||||||
config = {
|
|
||||||
class = "octodns.provider.yaml.YamlProvider";
|
|
||||||
directory = zonesDir;
|
|
||||||
default_ttl = cfg.defaults.ttl;
|
|
||||||
};
|
|
||||||
hetzner = {
|
|
||||||
class = "octodns_hetzner.HetznerProvider";
|
|
||||||
token = "env/HETZNER_API_TOKEN";
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
zones."*" = {
|
|
||||||
sources = [ "config" ];
|
|
||||||
targets = [ "hetzner" ];
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
octodns = pkgs-unstable.octodns.withProviders (_: [
|
|
||||||
pkgs-unstable.octodns-providers.hetzner
|
|
||||||
]);
|
|
||||||
in
|
|
||||||
{
|
|
||||||
options.services.octodns = {
|
|
||||||
enable = lib.mkEnableOption "Enable octodns";
|
|
||||||
records = lib.mkOption {
|
|
||||||
type = lib.types.attrsOf types.records;
|
|
||||||
default = { };
|
|
||||||
};
|
|
||||||
defaults = lib.mkOption {
|
|
||||||
type = types.defaults;
|
|
||||||
default = { };
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
config = lib.mkIf cfg.enable {
|
|
||||||
systemd.services.octodns = {
|
|
||||||
enable = true;
|
|
||||||
description = "OctoDNS";
|
|
||||||
serviceConfig = {
|
|
||||||
Type = "oneshot";
|
|
||||||
ExecStart = "${octodns}/bin/octodns-sync --config-file ${configFile} --doit";
|
|
||||||
DynamicUser = true;
|
|
||||||
EnvironmentFile = secrets.hetzner.path;
|
|
||||||
RemainAfterExit = true;
|
|
||||||
};
|
|
||||||
wantedBy = lib.optionals config.services.nginx.enable [ "nginx.service" ];
|
|
||||||
before = lib.optionals config.services.nginx.enable [ "nginx.service" ];
|
|
||||||
};
|
|
||||||
};
|
|
||||||
}
|
|
||||||
@@ -1,22 +1,16 @@
|
|||||||
{ lib, config, ... }:
|
{ ... }:
|
||||||
let
|
let
|
||||||
cfg = config.services.owncast;
|
fqdn = "stream.freun.dev";
|
||||||
fqdn = "${cfg.subdomain}.${config.networking.domain}";
|
|
||||||
in
|
in
|
||||||
{
|
{
|
||||||
options.services.owncast = {
|
services.owncast = {
|
||||||
subdomain = lib.mkOption {
|
enable = true;
|
||||||
type = lib.types.str;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
config = lib.mkIf cfg.enable {
|
|
||||||
services = {
|
|
||||||
owncast = {
|
|
||||||
openFirewall = true;
|
openFirewall = true;
|
||||||
};
|
};
|
||||||
|
|
||||||
webserver.vHosts.${fqdn}.locations."/".proxyPort = cfg.port;
|
services.caddy.virtualHosts = {
|
||||||
};
|
"${fqdn}".extraConfig = ''
|
||||||
|
reverse_proxy localhost:8080
|
||||||
|
'';
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,52 +0,0 @@
|
|||||||
{
|
|
||||||
lib,
|
|
||||||
config,
|
|
||||||
pkgs,
|
|
||||||
...
|
|
||||||
}:
|
|
||||||
let
|
|
||||||
cfg = config.services.readeck;
|
|
||||||
secrets = config.age.secrets;
|
|
||||||
fqdn = "${cfg.subdomain}.${config.networking.domain}";
|
|
||||||
in
|
|
||||||
{
|
|
||||||
options.services.readeck = {
|
|
||||||
subdomain = lib.mkOption {
|
|
||||||
type = lib.types.str;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
config = lib.mkIf cfg.enable {
|
|
||||||
services = {
|
|
||||||
readeck = {
|
|
||||||
package = pkgs.readeck;
|
|
||||||
environmentFile = secrets.readeck.path;
|
|
||||||
settings = {
|
|
||||||
server.port = lib.mkDefault 8090;
|
|
||||||
database.source = "postgres://readeck:@readeck?host=/var/run/postgresql";
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
webserver = {
|
|
||||||
enable = lib.mkDefault true;
|
|
||||||
vHosts.${fqdn} = {
|
|
||||||
proxyBuffering = false;
|
|
||||||
locations."/" = {
|
|
||||||
proxyPort = cfg.settings.server.port;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
postgresql = {
|
|
||||||
enable = lib.mkDefault true;
|
|
||||||
ensureDatabases = [ "readeck" ];
|
|
||||||
ensureUsers = [
|
|
||||||
{
|
|
||||||
name = "readeck";
|
|
||||||
ensureDBOwnership = true;
|
|
||||||
}
|
|
||||||
];
|
|
||||||
};
|
|
||||||
};
|
|
||||||
};
|
|
||||||
}
|
|
||||||
@@ -1,28 +0,0 @@
|
|||||||
{
|
|
||||||
config,
|
|
||||||
lib,
|
|
||||||
...
|
|
||||||
}:
|
|
||||||
let
|
|
||||||
cfg = config.services.sillytavern;
|
|
||||||
fqdn = "${cfg.subdomain}.${config.networking.domain}";
|
|
||||||
in
|
|
||||||
{
|
|
||||||
options.services.sillytavern = {
|
|
||||||
subdomain = lib.mkOption {
|
|
||||||
type = lib.types.str;
|
|
||||||
default = "sillytavern";
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
config = lib.mkIf cfg.enable {
|
|
||||||
services.webserver = {
|
|
||||||
enable = lib.mkDefault true;
|
|
||||||
vHosts.${fqdn} = {
|
|
||||||
tailscaleAuth = true;
|
|
||||||
proxyBuffering = false;
|
|
||||||
locations."/".proxyPort = cfg.port;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
};
|
|
||||||
}
|
|
||||||
@@ -1,31 +1,33 @@
|
|||||||
{ config, lib, ... }:
|
{ pkgs, config, lib, ... }:
|
||||||
let
|
let
|
||||||
cfg = config.services.syncthing;
|
storage_dir = "/mnt/storage/syncthing";
|
||||||
fqdn = "${cfg.subdomain}.${config.networking.domain}";
|
|
||||||
in
|
in
|
||||||
{
|
{
|
||||||
options.services.syncthing = {
|
services.syncthing = {
|
||||||
subdomain = lib.mkOption {
|
enable = true;
|
||||||
type = lib.types.str;
|
dataDir = "/mnt/storage/syncthing";
|
||||||
};
|
|
||||||
port = lib.mkOption {
|
|
||||||
type = lib.types.int;
|
|
||||||
default = 8384;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
config = lib.mkIf cfg.enable {
|
|
||||||
services = {
|
|
||||||
syncthing = {
|
|
||||||
openDefaultPorts = true;
|
openDefaultPorts = true;
|
||||||
guiAddress = "[::1]:${toString cfg.port}";
|
|
||||||
settings.gui.insecureSkipHostCheck = true;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
webserver = {
|
services.caddy.virtualHosts = {
|
||||||
enable = lib.mkDefault true;
|
"sync.freun.dev".extraConfig = ''
|
||||||
vHosts.${fqdn}.locations."/".proxyPort = cfg.port;
|
reverse_proxy localhost:8384 {
|
||||||
};
|
header_up Host {upstream_hostport}
|
||||||
};
|
}
|
||||||
};
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
fileSystems."${storage_dir}" = {
|
||||||
|
device = "//u407959.your-storagebox.de/backup/syncthing";
|
||||||
|
fsType = "cifs";
|
||||||
|
options = let
|
||||||
|
# this line prevents hanging on network split
|
||||||
|
automount_opts = "x-systemd.automount,auto,x-systemd.device-timeout=5s,x-systemd.mount-timeout=5s";
|
||||||
|
uid = builtins.toString config.users.users.syncthing.uid;
|
||||||
|
gid = builtins.toString config.users.groups.syncthing.gid;
|
||||||
|
in ["${automount_opts},credentials=/var/secrets/smb-storage,uid=${uid},gid=${gid}"];
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
environment.systemPackages = [ pkgs.cifs-utils ];
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,9 +0,0 @@
|
|||||||
{ lib, config, ... }:
|
|
||||||
let
|
|
||||||
cfg = config.services.tailscale;
|
|
||||||
in
|
|
||||||
{
|
|
||||||
config = lib.mkIf cfg.enable {
|
|
||||||
services.tailscale.useRoutingFeatures = lib.mkDefault "server";
|
|
||||||
};
|
|
||||||
}
|
|
||||||
@@ -1,16 +0,0 @@
|
|||||||
{ lib, config, ... }:
|
|
||||||
let
|
|
||||||
cfg = config.services.uptime-kuma;
|
|
||||||
fqdn = "${cfg.subdomain}.${config.networking.domain}";
|
|
||||||
in
|
|
||||||
{
|
|
||||||
options.services.uptime-kuma = {
|
|
||||||
subdomain = lib.mkOption {
|
|
||||||
type = lib.types.str;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
config = lib.mkIf cfg.enable {
|
|
||||||
services.webserver.vHosts.${fqdn}.locations."/".proxyPort = lib.toInt cfg.settings.PORT;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
@@ -1,48 +1,42 @@
|
|||||||
{ lib, config, ... }:
|
{ ... }:
|
||||||
let
|
|
||||||
cfg = config.services.vaultwarden;
|
|
||||||
secrets = config.age.secrets;
|
|
||||||
fqdn = "${cfg.subdomain}.${config.networking.domain}";
|
|
||||||
port = config.services.vaultwarden.config.ROCKET_PORT;
|
|
||||||
in
|
|
||||||
{
|
{
|
||||||
options.services.vaultwarden = {
|
services.vaultwarden = {
|
||||||
subdomain = lib.mkOption {
|
enable = true;
|
||||||
type = lib.types.str;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
config = lib.mkIf cfg.enable {
|
|
||||||
services = {
|
|
||||||
vaultwarden = {
|
|
||||||
dbBackend = "postgresql";
|
dbBackend = "postgresql";
|
||||||
environmentFile = secrets.vaultwarden.path;
|
environmentFile = "/var/secrets/vaultwarden.env";
|
||||||
config = {
|
config = {
|
||||||
DOMAIN = "https://${fqdn}";
|
DOMAIN = "https://pw.freun.dev";
|
||||||
DATABASE_URL = "postgres://%2Fvar%2Frun%2Fpostgresql/vaultwarden";
|
DATABASE_URL = "postgres://%2Fvar%2Frun%2Fpostgresql/vaultwarden";
|
||||||
WEBSOCKET_ENABLED = true;
|
WEBSOCKET_ENABLED = true;
|
||||||
|
WEBSOCKET_ADDRESS = "127.0.0.1";
|
||||||
|
WEBSOCKET_PORT = 3012;
|
||||||
SIGNUPS_VERIFY = true;
|
SIGNUPS_VERIFY = true;
|
||||||
PASSWORD_ITERATIONS = 600000;
|
PASSWORD_ITERATIONS = 600000;
|
||||||
|
YUBICO_CLIENT_ID = 86799;
|
||||||
|
SMTP_HOST = "horologium.uberspace.de";
|
||||||
|
SMTP_FROM = "noreply@freun.dev";
|
||||||
|
SMTP_FROM_NAME = "Vaultwarden";
|
||||||
|
SMTP_USERNAME = "noreply@freun.dev";
|
||||||
|
SMTP_PORT = 587;
|
||||||
|
HELO_NAME = "freun.dev";
|
||||||
ROCKET_LIMITS = "{json=10485760}";
|
ROCKET_LIMITS = "{json=10485760}";
|
||||||
ROCKET_PORT = 8000;
|
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
webserver = {
|
services.caddy.virtualHosts = {
|
||||||
enable = lib.mkDefault true;
|
"pw.freun.dev".extraConfig = ''
|
||||||
vHosts.${fqdn}.locations."/".proxyPort = port;
|
reverse_proxy /notifications/hub localhost:3012
|
||||||
|
reverse_proxy localhost:8000 {
|
||||||
|
header_up X-Real-IP {remote_host}
|
||||||
|
}
|
||||||
|
'';
|
||||||
};
|
};
|
||||||
|
|
||||||
postgresql = {
|
services.postgresql = {
|
||||||
enable = lib.mkDefault true;
|
|
||||||
ensureDatabases = [ "vaultwarden" ];
|
ensureDatabases = [ "vaultwarden" ];
|
||||||
ensureUsers = [
|
ensureUsers = [{
|
||||||
{
|
|
||||||
name = "vaultwarden";
|
name = "vaultwarden";
|
||||||
ensureDBOwnership = true;
|
ensureDBOwnership = true;
|
||||||
}
|
}];
|
||||||
];
|
|
||||||
};
|
|
||||||
};
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,50 +0,0 @@
|
|||||||
{
|
|
||||||
lib,
|
|
||||||
config,
|
|
||||||
inputs,
|
|
||||||
...
|
|
||||||
}:
|
|
||||||
let
|
|
||||||
cfg = config.services.voidauth;
|
|
||||||
fqdn = "${cfg.subdomain}.${config.networking.domain}";
|
|
||||||
port = cfg.settings.APP_PORT or 3000;
|
|
||||||
in
|
|
||||||
{
|
|
||||||
options.services.voidauth = {
|
|
||||||
subdomain = lib.mkOption {
|
|
||||||
type = lib.types.str;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
imports = [
|
|
||||||
inputs.voidauth.nixosModules.voidauth
|
|
||||||
];
|
|
||||||
|
|
||||||
config = lib.mkIf cfg.enable {
|
|
||||||
services = {
|
|
||||||
voidauth = {
|
|
||||||
settings = {
|
|
||||||
APP_URL = "https://${fqdn}";
|
|
||||||
DB_SOCKET_PATH = "/run/postgresql";
|
|
||||||
DB_NAME = "voidauth";
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
webserver = {
|
|
||||||
enable = lib.mkDefault true;
|
|
||||||
vHosts.${fqdn}.locations."/".proxyPort = port;
|
|
||||||
};
|
|
||||||
|
|
||||||
postgresql = {
|
|
||||||
enable = lib.mkDefault true;
|
|
||||||
ensureDatabases = [ "voidauth" ];
|
|
||||||
ensureUsers = [
|
|
||||||
{
|
|
||||||
name = "voidauth";
|
|
||||||
ensureDBOwnership = true;
|
|
||||||
}
|
|
||||||
];
|
|
||||||
};
|
|
||||||
};
|
|
||||||
};
|
|
||||||
}
|
|
||||||
@@ -1,156 +0,0 @@
|
|||||||
{ lib, config, ... }:
|
|
||||||
let
|
|
||||||
cfg = config.services.webserver;
|
|
||||||
|
|
||||||
types = {
|
|
||||||
location = lib.types.submodule {
|
|
||||||
options = {
|
|
||||||
proxyPort = lib.mkOption {
|
|
||||||
type = lib.types.nullOr lib.types.int;
|
|
||||||
default = null;
|
|
||||||
};
|
|
||||||
root = lib.mkOption {
|
|
||||||
type = lib.types.nullOr lib.types.path;
|
|
||||||
default = null;
|
|
||||||
};
|
|
||||||
basicAuthFile = lib.mkOption {
|
|
||||||
type = lib.types.nullOr lib.types.path;
|
|
||||||
default = null;
|
|
||||||
};
|
|
||||||
extraConfig = lib.mkOption {
|
|
||||||
type = lib.types.str;
|
|
||||||
default = "";
|
|
||||||
};
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
vhost = lib.types.submodule {
|
|
||||||
options = {
|
|
||||||
proxyBuffering = lib.mkOption {
|
|
||||||
type = lib.types.bool;
|
|
||||||
default = true;
|
|
||||||
};
|
|
||||||
locations = lib.mkOption {
|
|
||||||
type = lib.types.attrsOf types.location;
|
|
||||||
};
|
|
||||||
tailscaleAuth = lib.mkOption {
|
|
||||||
type = lib.types.bool;
|
|
||||||
default = false;
|
|
||||||
};
|
|
||||||
extraConfig = lib.mkOption {
|
|
||||||
type = lib.types.lines;
|
|
||||||
default = "";
|
|
||||||
};
|
|
||||||
};
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
tailscaleAuthVhosts = lib.attrNames (
|
|
||||||
lib.filterAttrs (name: { tailscaleAuth, ... }: tailscaleAuth) cfg.vHosts
|
|
||||||
);
|
|
||||||
in
|
|
||||||
{
|
|
||||||
options.services.webserver = {
|
|
||||||
enable = lib.mkEnableOption "Enable nginx";
|
|
||||||
acme = {
|
|
||||||
dnsChallenge = lib.mkEnableOption "Enable DNS challenge";
|
|
||||||
dnsProvider = lib.mkOption {
|
|
||||||
type = lib.types.str;
|
|
||||||
default = "hetzner";
|
|
||||||
};
|
|
||||||
};
|
|
||||||
vHosts = lib.mkOption {
|
|
||||||
type = lib.types.attrsOf types.vhost;
|
|
||||||
default = { };
|
|
||||||
};
|
|
||||||
tailscaleAuth.expectedTailnet = lib.mkOption {
|
|
||||||
type = lib.types.str;
|
|
||||||
default = "";
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
config = lib.mkIf cfg.enable {
|
|
||||||
services = {
|
|
||||||
nginx = {
|
|
||||||
enable = lib.mkDefault true;
|
|
||||||
recommendedProxySettings = true;
|
|
||||||
recommendedTlsSettings = true;
|
|
||||||
recommendedBrotliSettings = true;
|
|
||||||
recommendedGzipSettings = true;
|
|
||||||
recommendedOptimisation = true;
|
|
||||||
|
|
||||||
tailscaleAuth = {
|
|
||||||
enable = (lib.length tailscaleAuthVhosts) > 0;
|
|
||||||
virtualHosts = tailscaleAuthVhosts;
|
|
||||||
expectedTailnet = cfg.tailscaleAuth.expectedTailnet;
|
|
||||||
};
|
|
||||||
|
|
||||||
virtualHosts = lib.mapAttrs (
|
|
||||||
_:
|
|
||||||
{
|
|
||||||
proxyBuffering,
|
|
||||||
locations,
|
|
||||||
extraConfig,
|
|
||||||
...
|
|
||||||
}:
|
|
||||||
{
|
|
||||||
forceSSL = true;
|
|
||||||
enableACME = true;
|
|
||||||
http2 = true;
|
|
||||||
acmeRoot = lib.mkIf cfg.acme.dnsChallenge null;
|
|
||||||
extraConfig = lib.concatLines [
|
|
||||||
(lib.optionalString (!proxyBuffering) "proxy_buffering off;")
|
|
||||||
"charset utf-8;"
|
|
||||||
extraConfig
|
|
||||||
];
|
|
||||||
locations = lib.mapAttrs (
|
|
||||||
_:
|
|
||||||
{
|
|
||||||
proxyPort,
|
|
||||||
extraConfig,
|
|
||||||
root,
|
|
||||||
basicAuthFile,
|
|
||||||
}:
|
|
||||||
lib.mergeAttrsList [
|
|
||||||
{ inherit extraConfig root basicAuthFile; }
|
|
||||||
(
|
|
||||||
if (lib.isInt proxyPort) then
|
|
||||||
{
|
|
||||||
proxyWebsockets = true;
|
|
||||||
proxyPass = "http://localhost:${toString proxyPort}";
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{ }
|
|
||||||
)
|
|
||||||
]
|
|
||||||
) locations;
|
|
||||||
}
|
|
||||||
) cfg.vHosts;
|
|
||||||
};
|
|
||||||
|
|
||||||
octodns.records = lib.filterAttrs (name: _: name != config.networking.domain) (
|
|
||||||
lib.mapAttrs' (
|
|
||||||
fqdn:
|
|
||||||
{ tailscaleAuth, ... }:
|
|
||||||
{
|
|
||||||
name = lib.removeSuffix ".${config.networking.domain}" fqdn;
|
|
||||||
value = {
|
|
||||||
CNAME =
|
|
||||||
if tailscaleAuth then { target = "ts.${config.networking.domain}."; } else { toRoot = true; };
|
|
||||||
};
|
|
||||||
}
|
|
||||||
) cfg.vHosts
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
security.acme = {
|
|
||||||
acceptTerms = true;
|
|
||||||
defaults = {
|
|
||||||
email = "admin@j.repomaa.com";
|
|
||||||
dnsProvider = lib.mkIf cfg.acme.dnsChallenge cfg.acme.dnsProvider;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
modules.firewall.allInterfaces = [ "web" ];
|
|
||||||
};
|
|
||||||
}
|
|
||||||
@@ -1,41 +0,0 @@
|
|||||||
{
|
|
||||||
config,
|
|
||||||
lib,
|
|
||||||
pkgs,
|
|
||||||
...
|
|
||||||
}:
|
|
||||||
let
|
|
||||||
cfg = config.services.weechat;
|
|
||||||
fqdn = cfg.subdomain + "." + config.networking.domain;
|
|
||||||
in
|
|
||||||
{
|
|
||||||
options.services.weechat = {
|
|
||||||
subdomain = lib.mkOption {
|
|
||||||
type = lib.types.str;
|
|
||||||
description = "The subdomain for the weechat service";
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
config = lib.mkIf cfg.enable {
|
|
||||||
services = {
|
|
||||||
weechat = {
|
|
||||||
# binary = lib.mkDefault "${pkgs.weechat}/bin/weechat-headless";
|
|
||||||
};
|
|
||||||
|
|
||||||
webserver = {
|
|
||||||
enable = lib.mkDefault true;
|
|
||||||
vHosts.${fqdn}.locations = {
|
|
||||||
"/".root = pkgs.glowing-bear;
|
|
||||||
"/weechat".proxyPort = 9001;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
networking.firewall.allowedTCPPorts = [ 9001 ];
|
|
||||||
|
|
||||||
systemd.services.weechat = {
|
|
||||||
environment.HOME = "%S/weechat";
|
|
||||||
serviceConfig.StateDirectory = "weechat";
|
|
||||||
};
|
|
||||||
};
|
|
||||||
}
|
|
||||||
41
modules/services/wireguard.nix
Normal file
41
modules/services/wireguard.nix
Normal file
@@ -0,0 +1,41 @@
|
|||||||
|
{ config, pkgs, lib, ... }:
|
||||||
|
let
|
||||||
|
port = 51820;
|
||||||
|
name = "wg0";
|
||||||
|
peers = [
|
||||||
|
{
|
||||||
|
PublicKey = "XI0/k2j20CVSfevwjkmo4IddVoA2VY2fN6feauXYEXU=";
|
||||||
|
AllowedIPs = [ "10.100.0.2" ];
|
||||||
|
} # radish
|
||||||
|
];
|
||||||
|
address = [ "10.100.0.1/24" ];
|
||||||
|
in
|
||||||
|
{
|
||||||
|
networking.firewall.allowedUDPPorts = [ port ];
|
||||||
|
networking.useNetworkd = true;
|
||||||
|
|
||||||
|
systemd.network = {
|
||||||
|
enable = true;
|
||||||
|
netdevs.${name} = {
|
||||||
|
netdevConfig = {
|
||||||
|
Kind = "wireguard";
|
||||||
|
Name = "${name}";
|
||||||
|
MTUBytes = "1300";
|
||||||
|
};
|
||||||
|
wireguardConfig = {
|
||||||
|
PrivateKeyFile = "/var/secrets/wireguard-privkey";
|
||||||
|
ListenPort = port;
|
||||||
|
};
|
||||||
|
wireguardPeers = peers;
|
||||||
|
};
|
||||||
|
|
||||||
|
networks.${name} = {
|
||||||
|
matchConfig.Name = name;
|
||||||
|
inherit address;
|
||||||
|
networkConfig = {
|
||||||
|
IPMasquerade = "ipv4";
|
||||||
|
IPForward = true;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
||||||
@@ -1,70 +0,0 @@
|
|||||||
{
|
|
||||||
pkgs,
|
|
||||||
inputs,
|
|
||||||
config,
|
|
||||||
lib,
|
|
||||||
...
|
|
||||||
}:
|
|
||||||
let
|
|
||||||
cfg = config.services.workout-sync;
|
|
||||||
fqdn = "${cfg.subdomain}.${config.networking.domain}";
|
|
||||||
port = cfg.port;
|
|
||||||
workout-sync = inputs.workout-sync.packages.${pkgs.stdenv.hostPlatform.system}.default;
|
|
||||||
in
|
|
||||||
{
|
|
||||||
options.services.workout-sync = {
|
|
||||||
enable = lib.mkEnableOption "Enable Workout Sync";
|
|
||||||
subdomain = lib.mkOption {
|
|
||||||
type = lib.types.str;
|
|
||||||
};
|
|
||||||
port = lib.mkOption {
|
|
||||||
type = lib.types.int;
|
|
||||||
default = 3344;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
config = lib.mkIf cfg.enable {
|
|
||||||
services.workout-tracker.enable = lib.mkDefault true;
|
|
||||||
|
|
||||||
systemd.services.workout-sync = {
|
|
||||||
enable = true;
|
|
||||||
description = "Workout sync service";
|
|
||||||
environment = {
|
|
||||||
PORT = toString port;
|
|
||||||
WORKOUT_TRACKER_URL = "http://localhost:${toString config.services.workout-tracker.port}";
|
|
||||||
};
|
|
||||||
serviceConfig = {
|
|
||||||
ExecStart = "${workout-sync}/bin/workout-sync";
|
|
||||||
Restart = "always";
|
|
||||||
DynamicUser = true;
|
|
||||||
BindReadOnlyPaths = [
|
|
||||||
/run/systemd/resolve/stub-resolv.conf
|
|
||||||
/etc/ssl
|
|
||||||
/etc/static/ssl
|
|
||||||
/etc/resolv.conf
|
|
||||||
/etc/static/resolv.conf
|
|
||||||
/etc/nsswitch.conf
|
|
||||||
/etc/static/nsswitch.conf
|
|
||||||
/etc/hosts
|
|
||||||
];
|
|
||||||
};
|
|
||||||
wantedBy = [ "multi-user.target" ];
|
|
||||||
confinement.enable = true;
|
|
||||||
};
|
|
||||||
|
|
||||||
services = {
|
|
||||||
webserver = {
|
|
||||||
enable = lib.mkDefault true;
|
|
||||||
vHosts.${fqdn}.locations."/" = {
|
|
||||||
proxyPort = port;
|
|
||||||
extraConfig = ''
|
|
||||||
client_max_body_size 50m;
|
|
||||||
proxy_send_timeout 300;
|
|
||||||
proxy_read_timeout 300;
|
|
||||||
send_timeout 300;
|
|
||||||
'';
|
|
||||||
};
|
|
||||||
};
|
|
||||||
};
|
|
||||||
};
|
|
||||||
}
|
|
||||||
@@ -1,30 +0,0 @@
|
|||||||
{
|
|
||||||
pkgs-unstable,
|
|
||||||
config,
|
|
||||||
lib,
|
|
||||||
...
|
|
||||||
}:
|
|
||||||
let
|
|
||||||
cfg = config.services.workout-tracker;
|
|
||||||
fqdn = "${cfg.subdomain}.${config.networking.domain}";
|
|
||||||
port = cfg.port;
|
|
||||||
package = pkgs-unstable.workout-tracker;
|
|
||||||
in
|
|
||||||
{
|
|
||||||
options.services.workout-tracker = {
|
|
||||||
subdomain = lib.mkOption {
|
|
||||||
type = lib.types.str;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
config = lib.mkIf cfg.enable {
|
|
||||||
services = {
|
|
||||||
workout-tracker = { inherit package; };
|
|
||||||
|
|
||||||
webserver = {
|
|
||||||
enable = lib.mkDefault true;
|
|
||||||
vHosts.${fqdn}.locations."/".proxyPort = port;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
};
|
|
||||||
}
|
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user