Compare commits

...

173 Commits

Author SHA1 Message Date
Yorick van Pelt 9f48c7206f
ignore some forgejo dirs in borgbackup 2024-04-28 22:12:03 +02:00
Yorick van Pelt e08cba43d1
bump yobot 2024-04-27 11:12:44 +02:00
Yorick van Pelt fab5decd21
move yobot to pennyworth 2024-04-27 10:56:26 +02:00
Yorick van Pelt 1e86a647bc
cog for mickey 2024-04-25 10:26:40 +02:00
Yorick van Pelt b98abbf2af
move dk-stage to datakami server 2024-04-25 10:26:23 +02:00
Yorick van Pelt 04fa58722a
Add bram to mickey account :) 2024-04-24 16:57:58 +02:00
Yorick van Pelt 945576120e
Make datakami vpn 2024-04-24 16:57:50 +02:00
Yorick van Pelt 470b3fcafe
fix nr speed 2024-04-20 14:28:13 +02:00
Yorick van Pelt da512d3eed
bump llm 2024-04-20 10:13:51 +02:00
Yorick van Pelt b739f0430b
nix flake update 2024-04-20 09:30:49 +02:00
Yorick van Pelt a9e7fedca0
ledger udev rules 2024-04-20 09:29:22 +02:00
Yorick van Pelt ddac59807b
increase mako height 2024-04-20 09:29:16 +02:00
Yorick van Pelt badcc0faee
Add user+keys for mickey 2024-04-20 09:28:59 +02:00
Yorick van Pelt f141a1b6b2
Fix emacs fonts 2024-03-23 10:07:45 +01:00
Yorick van Pelt 9e1bf078b1
Fix evaluation warnings 2024-03-23 10:01:27 +01:00
Yorick van Pelt 6fe32ef833
Fix all-day events overriding useful meetings, add gather.town 2024-03-21 10:27:37 +01:00
Yorick van Pelt 1f553ac33b
bump cuda drivers on blackadder to work with 12.4 2024-03-15 10:02:16 +01:00
Yorick van Pelt 1f40b30d87
Install llm via dream2nix 2024-03-15 10:01:03 +01:00
Yorick van Pelt 6cb0ee6eec
Use nix copy -s for deployment 2024-03-10 14:37:51 +01:00
Yorick van Pelt 9bb17c1137
flake update 2024-03-10 13:43:08 +01:00
Yorick van Pelt dc70f3059f
Add localtuya/midea_ac_lan/cast to hass 2024-03-10 11:18:30 +01:00
Yorick van Pelt 6da94bc2a4
Update home-assistant config 2024-02-18 12:51:04 +01:00
Yorick van Pelt 7723bc0df1
Add attic server 2024-02-17 15:14:16 +01:00
Yorick van Pelt 8a89d26e08
switch gitea to forgejo 2024-02-17 12:01:06 +01:00
Yorick van Pelt 26cbd9d468
bump nats to 2.10.11 2024-02-17 10:46:50 +01:00
Yorick van Pelt a26cf98158
nix flake update 2024-02-17 10:28:01 +01:00
Yorick van Pelt 7b3c42a634
Speed up alacritty window creation 2024-02-17 10:00:16 +01:00
Yorick van Pelt c4530f2dfb
lumi-cache: change prio to 50 since default cache is at 40 2024-02-17 10:00:06 +01:00
Yorick van Pelt 8757aa5273
r8-cog: 0.9.0-beta11 -> 0.9.4 2024-02-17 09:59:56 +01:00
Yorick van Pelt 3d82efbc4c
update xwaylandvideobridge 2024-02-17 09:57:31 +01:00
Yorick van Pelt 6943046de7
mv docuseal yori.cc -> datakami.nl 2024-02-16 11:14:04 +01:00
Yorick van Pelt 79bbc93738
Deploy docuseal 2024-02-07 11:21:24 +01:00
Yorick van Pelt 51adc8e340
Add auth for marvin-tracker 2024-01-02 12:07:34 +01:00
Yorick van Pelt 4c6da8be94
home: add nats tools 2024-01-02 11:44:43 +01:00
Yorick van Pelt c0845cb2ae
r8-cog: 0.8.6 -> 0.9.0-beta11 2024-01-02 11:44:33 +01:00
Yorick van Pelt 8fa27408dc
switch from rabbitmq to nats 2024-01-02 11:42:04 +01:00
Yorick van Pelt 8ac041ba0d
pennyworth: fix weechat relay port gone missing 2024-01-02 11:32:34 +01:00
Yorick van Pelt 5726f480d0
workstation: decrease lumi cache priority 2024-01-01 16:45:59 +01:00
Yorick van Pelt 3f0cfa3e08
rewrite frumar.nix, pennyworth.nix, remove some vpn proxies 2024-01-01 16:44:54 +01:00
Yorick van Pelt 2086d63e8e
remove comment 2024-01-01 16:08:32 +01:00
Yorick van Pelt 8026261f86
Move to upstream calibre-web module 2024-01-01 15:48:25 +01:00
Yorick van Pelt bd67172ea0
Add noulith 2023-12-28 13:41:27 +01:00
Yorick van Pelt 47e7b45a24
another flake update 2023-12-26 10:36:57 +01:00
Yorick van Pelt f0a403bd0b
23.11 upgrade 2023-12-20 13:32:18 +01:00
Yorick van Pelt b5d30b39fd
some emacs tweaks 2023-12-20 11:22:21 +01:00
Yorick van Pelt 1a7ceebcdd
Deploy fooocus 2023-11-14 21:57:30 +01:00
Yorick van Pelt e47eb158af
Update fooocus and add as subflake 2023-11-14 21:57:15 +01:00
Yorick van Pelt 070d64145e
upgrade fooocus 2023-11-14 18:12:50 +01:00
Yorick van Pelt af881d6f0e
frumar: enable rasdaemon 2023-11-01 10:39:24 +01:00
Yorick van Pelt a1232c38e2
Add paperless 2023-10-30 10:32:26 +01:00
Yorick van Pelt 6dec267bcf
Fooocus subflake 2023-10-29 21:40:42 +01:00
Yorick van Pelt f248439c6a
home: install mutagen and zoom-us 2023-10-18 09:56:46 +02:00
Yorick van Pelt 0b97df2b57
Update timesync + fix emacs warning 2023-10-18 09:50:45 +02:00
Yorick van Pelt a8abf3354e
remove tweag account from calendar 2023-10-18 09:43:55 +02:00
Yorick van Pelt c2f882e2e4
Remove Tweag 2023-10-18 09:24:33 +02:00
Yorick van Pelt 220befc4a5
wayland-push-to-talk-fix: update to upstream 2023-10-07 19:14:57 +02:00
Yorick van Pelt 140b4bdb3e
apply review comments 2023-10-01 12:22:54 +02:00
Yorick van Pelt 4b8df27c6f
add dep-drill script 2023-10-01 12:17:42 +02:00
Yorick van Pelt a65543bb58
smithers: almost flicker-free boot 2023-09-30 19:57:13 +02:00
Yorick van Pelt 3393f27d30
priv.yori.cc: add a mediashare dir 2023-09-30 19:50:04 +02:00
Yorick van Pelt 3ef30eba9a
absorb: use tmp file so the store is always correct 2023-09-30 19:49:46 +02:00
Yorick van Pelt 9bcb751696
set `hub` checkout protocol to ssh 2023-09-24 22:26:24 +02:00
Yorick van Pelt a5abf4c545
minor cleanup 2023-09-24 22:26:11 +02:00
Yorick van Pelt 4f60bf4168
webhook for amazing marvin status 2023-09-24 22:20:41 +02:00
Yorick van Pelt 4adbb2de9e
dashy: fix 2023-09-24 21:38:39 +02:00
Yorick van Pelt e3d980fd40
dashy: add 2048 2023-09-24 13:06:00 +02:00
Yorick van Pelt 67343c641d
Add dashy to priv.yori.cc 2023-09-24 11:51:26 +02:00
Yorick van Pelt 17c351c5b6
add priv.yori.cc behind oauth2-proxy 2023-09-24 11:50:46 +02:00
Yorick van Pelt f251a891fb
frumar: split out home-automation and media 2023-09-23 16:36:53 +02:00
Yorick van Pelt a15ea5ff17
frumar: split out selfsigned module 2023-09-23 16:15:41 +02:00
Yorick van Pelt 734a2fc02f
frumar: move from acme.sh to lego 2023-09-23 16:02:44 +02:00
Yorick van Pelt ca432e86f1
Add agenix to the dotfiles devshell 2023-09-23 15:57:07 +02:00
Yorick van Pelt e3a579d345
blackadder: fix docker size and permissions 2023-09-23 15:56:04 +02:00
Yorick van Pelt de857eaeca
remove element desktop entry 2023-09-23 15:55:34 +02:00
Yorick van Pelt 074388893a
add replicate ssh alias 2023-09-23 15:55:23 +02:00
Yorick van Pelt 332bee9638
package replicate's cog 2023-09-23 15:53:36 +02:00
Yorick van Pelt 492739eca9
calendar widget: escape html in popup 2023-09-23 15:53:06 +02:00
Yorick van Pelt a72d2cdb64
(temporary) add marvin tracker 2023-09-23 15:52:49 +02:00
Yorick van Pelt 7eafb75963
wl-clipboard: fix version 2023-09-21 10:02:33 +02:00
Yorick van Pelt 3835d482b0
notion-desktop: switch to electron 27 2023-09-21 10:02:02 +02:00
Yorick van Pelt 891de416da
install notion-desktop 2023-09-18 10:57:35 +02:00
Yorick van Pelt e9d0cdc4da
package notion-desktop 2023-09-18 10:57:19 +02:00
Yorick van Pelt f0d66cff0f
remove old notion 2023-09-17 19:27:14 +02:00
Yorick van Pelt 69b0a1be63
update frumar 2023-09-17 19:26:46 +02:00
Yorick van Pelt 20a15cd20a
update smithers 2023-09-17 19:12:14 +02:00
Yorick van Pelt 1e7be7c9c0
Comment out NIXOS_OZONE_WL, element hates it 2023-09-17 18:17:39 +02:00
Yorick van Pelt bb93ffa6b7
Add gdk-pixbuf webp loader 2023-09-17 18:17:29 +02:00
Yorick van Pelt edf890f141
flake update 2023-09-17 18:17:14 +02:00
Yorick van Pelt 0ac58b8dbc
cal: attempt to fix "jump into video call" link 2023-08-28 10:52:47 +02:00
Yorick van Pelt bdfa5d1777
make firefox sharing indicator floating 2023-08-21 15:34:26 +02:00
Yorick van Pelt 463e217630
work around acmesh-official/acme.sh#2350 2023-08-21 11:24:53 +02:00
Yorick van Pelt 050d2692b6
flake update 2023-08-04 13:26:32 +02:00
Yorick van Pelt 9ca91cac81
switch to X11 element-desktop 2023-08-04 10:39:29 +02:00
Yorick van Pelt 10cc75e067
frumar: add torrent config 2023-08-04 10:39:22 +02:00
Yorick van Pelt 13344f0ecc
frumar: send emails from zed 2023-07-22 13:10:55 +02:00
Yorick van Pelt 5c58117001
frumar: enable smartd with mailer 2023-07-22 12:46:47 +02:00
Yorick van Pelt b96139868c
frumar: enable sending mail 2023-07-22 12:28:50 +02:00
Yorick van Pelt b19cf6f2f6
frumar: switch main disk to ssdpool 2023-07-22 12:28:33 +02:00
Yorick van Pelt dd3fcc85b2
nix flake update 2023-07-20 15:29:02 +02:00
Yorick van Pelt eca493154e
home: install notion-app-enhanced 2023-07-05 14:51:25 +02:00
Yorick van Pelt 2f3557afeb
home: add Element desktop entry 2023-07-05 14:51:16 +02:00
Yorick van Pelt 98959934ff
frumar: move paperless stuff to separate file, fix scanner firewall 2023-07-05 14:50:43 +02:00
Yorick van Pelt 4adf2f5ab3
fix emacs 2023-07-03 15:03:52 +02:00
Yorick van Pelt c7ef710cd4
datakami: add .html to try_files 2023-07-03 15:03:27 +02:00
Yorick van Pelt 6dd744bcab
s/mullvad/azire 2023-07-03 15:02:42 +02:00
Yorick van Pelt cfb4b07eb8
alacritty: update font name 2023-06-04 17:44:44 +02:00
Yorick van Pelt 43c0ad1608
cal: add dk account 2023-06-04 17:44:34 +02:00
Yorick van Pelt e506793ddc
update xwaylandvideobridge 2023-06-04 17:44:21 +02:00
Yorick van Pelt 8260b1f88f
s/pyroscope/pyrosimple 2023-06-04 16:52:53 +02:00
Yorick van Pelt f16972bd81
extract calibre-web into service 2023-06-04 16:48:25 +02:00
Yorick van Pelt 1be66fd2bc
update to nixos 23.05 2023-06-04 16:48:03 +02:00
Yorick van Pelt f0f16dc7b2
blackadder: move boot fs and swap to 980pro ssd 2023-06-04 15:18:26 +02:00
Yorick van Pelt 414abe46cd
blackadder: exchange thunderbolt card for gpu 2023-06-04 15:18:08 +02:00
Yorick van Pelt d546964c07
playerctl: add kdeconnect -> android icon 2023-06-04 15:17:26 +02:00
Yorick van Pelt ee9fd330b1
pennyworth: calibre-web kobo support 2023-06-04 15:15:17 +02:00
Yorick van Pelt 9bfc712fcf
mako: implement do-not-disturb 2023-05-26 16:38:03 +02:00
Yorick van Pelt 300c2b3310
pass: set x-kde-passwordManagerHint to sensitive 2023-05-22 11:48:01 +02:00
Yorick van Pelt aab0617367
some cleanups 2023-05-20 13:40:41 +02:00
Yorick van Pelt 93af9bd368
enable KDEconnect on workstations 2023-05-20 13:40:23 +02:00
Yorick van Pelt 8daefcef2c
mutt: move to home manager module 2023-05-20 13:39:59 +02:00
Yorick van Pelt 3c81a5b5ed
pennyworth: deploy calibre-web 2023-05-15 12:23:11 +02:00
Yorick van Pelt bab00a2482
switch from starship to tide 2023-05-10 20:48:13 +02:00
Yorick van Pelt 9f6bb6a011
backup: update rsync server and username 2023-05-10 20:48:04 +02:00
Yorick van Pelt 5a5ba8ac8d
blackadder: add user account for Judith 2023-05-10 20:46:11 +02:00
Yorick van Pelt 8b39e5e7bb
pennyworth: host dk-stage.yori.cc with rsync deploy key 2023-05-10 20:45:04 +02:00
Yorick van Pelt d898d87210
install marvin-timesync 2023-05-01 14:35:39 +02:00
Yorick van Pelt c17199d87a
xwaylandvideobridge: add 2023-04-29 12:52:24 +02:00
Yorick van Pelt 9130e4602a
deployer: add settings 2023-04-23 12:50:31 +02:00
Yorick van Pelt 036c5a7488
home-assistant: add some auto-discovered deps 2023-04-23 12:26:08 +02:00
Yorick van Pelt a8ee5359f2
update laptops 2023-04-23 12:25:48 +02:00
Yorick van Pelt 3a1c468c06
update deployer to fix some bugs I found 2023-04-23 10:32:27 +02:00
Yorick van Pelt d2f5ba3ca2
deployer: use typescript constructor args 2023-04-23 09:43:11 +02:00
Yorick van Pelt 795df06ff1
update nixpkgs 2023-04-23 09:42:35 +02:00
Yorick van Pelt 3851e23343
fzf-pass: kill after 30s 2023-04-16 16:52:24 +02:00
Yorick van Pelt 43b19c3935
fix torrent-wg after server rotation 2023-04-15 12:28:40 +02:00
Yorick van Pelt 8fd5d8fbd4
frumar: znapzend frumar-new dataset 2023-04-11 15:39:27 +02:00
Yorick van Pelt ffd4ff9fe9
add readmes 2023-04-09 21:42:26 +02:00
Yorick van Pelt d299913a3c
add esphome data 2023-04-09 16:46:59 +02:00
Yorick van Pelt 9b476cfbeb
countfftabs: add --json flag to just dump the session 2023-04-05 12:49:01 +02:00
Yorick van Pelt 211f519def
fftabcount: default firefox path 2023-04-03 17:29:36 +02:00
Yorick van Pelt 28b2f7b05a
package grott, libscrc 2023-04-03 16:26:25 +02:00
Yorick van Pelt 3043279dd5
unit for wayland-push-to-talk-fix 2023-04-03 16:01:22 +02:00
Yorick van Pelt 42cb5ccb2d
ydeployer via direnv 2023-04-03 15:51:46 +02:00
Yorick van Pelt 44f4bbb79f
pennyworth: add weechat relay 2023-03-22 12:55:13 +01:00
Yorick van Pelt 25bee6dd76
Add wayland-push-to-talk-fix 2023-03-22 11:35:37 +01:00
Yorick van Pelt d2bf5334ce
blackadder: auto-optimise nix store at night 2023-03-08 12:58:58 +01:00
Yorick van Pelt 6a62e97ac3
deployer: switch to @cmd, use nix --json output 2023-03-01 11:40:56 +01:00
Yorick van Pelt bcb93ac28a
yori-cc: fix links 2023-03-01 11:29:09 +01:00
Yorick van Pelt 8b9c6a1f17
Create home-assistant.yori.cc 2023-02-22 13:09:11 +01:00
Yorick van Pelt b40d20c445
frumar: add self-signed ssl cert 2023-02-22 12:51:08 +01:00
Yorick van Pelt a5f62702b2
nix-index cache is now updated by flake 2023-02-18 22:44:09 +01:00
Yorick van Pelt a3810e8392
stop logging screenshot_public 2023-02-18 22:44:00 +01:00
Yorick van Pelt 63a9a72ade
git: globally ignore direnv and friends 2023-02-18 22:43:50 +01:00
Yorick van Pelt a4ca1bc5f0
smithers: switch from iwd to wpa_supplicant 2023-02-18 22:43:15 +01:00
Yorick van Pelt 299e8aa05c
screenshot-public: strip out slashes 2023-02-18 22:42:58 +01:00
Yorick van Pelt 4e3a8a9625
deployer: initial commit 2023-01-26 19:24:29 +01:00
Yorick van Pelt 50c0592c9f
Add nix-index-database flake 2023-01-26 19:22:24 +01:00
Yorick van Pelt 19ec9327d3
sway: fix bg 2023-01-20 12:40:37 +01:00
Yorick van Pelt 41f796390e
purify latest.firefox-bin 2023-01-20 12:29:59 +01:00
Yorick van Pelt 7f4c56cd5d
frumar: jdk17_headless does work 2023-01-18 22:05:39 +01:00
Yorick van Pelt fbcf6ef1e4
Frumar: open minecraft port 2023-01-18 21:30:45 +01:00
Yorick van Pelt b073bcbacb
Add some pkgs to nix config 2023-01-18 21:30:31 +01:00
Yorick van Pelt ef16511f9a
Add some stuff 2023-01-18 18:03:59 +01:00
Yorick van Pelt d8fe793685
Flake update 2023-01-18 18:03:48 +01:00
Yorick van Pelt 7795b10680
Update headphones mac 2023-01-18 18:03:30 +01:00
Yorick van Pelt 253c20bd20
temporarily switch to firefox beta to fix wayland crash 1805464 2022-12-20 12:00:54 +01:00
Yorick van Pelt fd6f4ed8fb
emacs: nativecomp is default now 2022-12-20 12:00:36 +01:00
Yorick van Pelt c58d2b8cc8
flake update 2022-12-19 16:35:41 +01:00
Yorick van Pelt a06313ed04
frumar: add some home-assistant plugins 2022-12-19 15:56:40 +01:00
Yorick van Pelt ad1d80f3b7
flake update 2022-11-19 17:55:30 +01:00
Yorick van Pelt f0f99d714d
home-assistant: add tado and homewizard 2022-11-19 17:01:33 +01:00
Yorick van Pelt 64839f51a9
smithers: add flatpak 2022-11-19 16:59:46 +01:00
Yorick van Pelt 55ac883860
nginx: downgrade to openssl 1.1 2022-11-01 14:09:30 +01:00
119 changed files with 8659 additions and 1085 deletions

2
.gitignore vendored
View File

@ -2,3 +2,5 @@ result
*~
/mutt/.mutt/hcache-lock
/emacs/emacs.el
.direnv
/pkgs/marvin-tracker/node_modules

29
README.md Normal file
View File

@ -0,0 +1,29 @@
This repo contains code and specs for my personal infrastructure.
There is a centralized action runner tool 'ydeployer', which is accessible
from `nix develop` or using `direnv` (or using `nix run`).
# Computers
Configuration for all x86/arm systems is stored in [./nixos](). Specs are available in [./nixos/README.md]()
# bin
Assorted scripts in various states of deprecation.
# deployer
Deployment tool, written in typescript.
# emacs
.org files making up my daily editor configuration.
# esphome
Contains yaml configuration for esphome esp32 nodes.
# home-manager
nix configuration for my user profile on my desktop and laptops. Contains list of installed user-space programs.
# pkgs
Collection of nix files for packages that are not in nixpkgs, or patches for them.
# secrets
Secrets encrypted using agenix.

View File

@ -32,6 +32,11 @@ window.padding:
x: 0
y: 0
# Background opacity
window:
opacity: 0.9
# When true, bold text is drawn using the bright variant of colors.
draw_bold_text_with_bright_colors: true
@ -55,44 +60,11 @@ draw_bold_text_with_bright_colors: true
# * https://wiki.archlinux.org/index.php/font_configuration#Fontconfig_configuration
# * file:///usr/share/doc/fontconfig/fontconfig-user.html
font:
# The normal (roman) font face to use.
normal:
family: monospace # should be "Menlo" or something on macOS.
# Style can be specified to pick a specific face.
# style: Regular
family: "DejaVuSansM Nerd Font" # should be "Menlo" or something on macOS.
# The bold font face
bold:
family: monospace # should be "Menlo" or something on macOS.
# Style can be specified to pick a specific face.
# style: Bold
# The italic font face
italic:
family: monospace # should be "Menlo" or something on macOS.
# Style can be specified to pick a specific face.
# style: Italic
# Point size of the font
size: 12.0
# Offset is the extra space around each character. offset.y can be thought of
# as modifying the linespacing, and offset.x as modifying the letter spacing.
offset:
x: 0
y: 0
# Glyph offset determines the locations of the glyphs within their cells with
# the default being at the bottom. Increase the x offset to move the glyph to
# the right, increase the y offset to move the glyph upward.
glyph_offset:
x: 0
y: 0
# Should display the render timer
debug:
render_timer: false
# Use custom cursor colors. If true, display the cursor in the cursor.foreground
# and cursor.background colors, otherwise invert the colors of the cursor.
@ -100,103 +72,76 @@ debug:
colors:
# Default colors
primary:
background: '0xfdf6e3'
foreground: '0x586e75'
background: '0xeeeeee'
foreground: '0x4d4d4c'
# Colors the cursor will use if `custom_cursor_colors` is true
cursor:
text: '0xf3f3f3'
cursor: '0x4d4d4c'
# Normal colors
normal:
black: '0x073642'
red: '0xdc322f'
green: '0x859900'
yellow: '0xb58900'
blue: '0x268bd2'
magenta: '0xd33682'
cyan: '0x2aa198'
white: '0xeee8d5'
black: '0xededed'
red: '0xd7005f'
green: '0x718c00'
yellow: '0xd75f00'
blue: '0x4271ae'
magenta: '0x8959a8'
cyan: '0x3e999f'
white: '0x4d4d4c'
# Bright colors
bright:
black: '0x002b36'
red: '0xcb4b16'
green: '0x586e75'
yellow: '0x657b83'
blue: '0x839496'
magenta: '0x6c71c4'
cyan: '0x93a1a1'
white: '0xfdf6e3'
black: '0x949494'
red: '0xd7005f'
green: '0x718c00'
yellow: '0xd75f00'
blue: '0x4271ae'
magenta: '0x8959a8'
cyan: '0x3e999f'
white: '0xf5f5f5'
# Colors (Solarized Dark)
colors-alt:
# Default colors
primary:
background: '0x002b36'
foreground: '0x839496'
# Normal colors
normal:
black: '0x073642'
red: '0xdc322f'
green: '0x859900'
yellow: '0xb58900'
blue: '0x268bd2'
magenta: '0xd33682'
cyan: '0x2aa198'
white: '0xeee8d5'
# Bright colors
bright:
black: '0x002b36'
red: '0xcb4b16'
green: '0x586e75'
yellow: '0x657b83'
blue: '0x839496'
magenta: '0x6c71c4'
cyan: '0x93a1a1'
white: '0xfdf6e3'
# Colors (Tomorrow Night Bright)
colors_default:
# Default colors
primary:
background: '0x000000'
foreground: '0xeaeaea'
background: '0x1c1c1c'
foreground: '0x808080'
# Colors the cursor will use if `custom_cursor_colors` is true
cursor:
text: '0x000000'
cursor: '0xffffff'
text: '0x1c1c1c'
cursor: '0x808080'
# Normal colors
normal:
black: '0x000000'
red: '0xd54e53'
green: '0xb9ca4a'
yellow: '0xe6c547'
blue: '0x7aa6da'
magenta: '0xc397d8'
cyan: '0x70c0ba'
white: '0xffffff'
black: '0xededed'
red: '0xd7005f'
green: '0x718c00'
yellow: '0xd75f00'
blue: '0x4271ae'
magenta: '0x8959a8'
cyan: '0x3e999f'
white: '0x4d4d4c'
# Bright colors
bright:
black: '0x666666'
red: '0xff3334'
green: '0x9ec400'
yellow: '0xe7c547'
blue: '0x7aa6da'
magenta: '0xb77ee0'
cyan: '0x54ced6'
white: '0xffffff'
# Dim colors (Optional)
dim:
black: '0x333333'
red: '0xf2777a'
green: '0x99cc99'
yellow: '0xffcc66'
blue: '0x6699cc'
magenta: '0xcc99cc'
cyan: '0x66cccc'
white: '0xdddddd'
black: '0x949494'
red: '0xd7005f'
green: '0x718c00'
yellow: '0xd75f00'
blue: '0x4271ae'
magenta: '0x8959a8'
cyan: '0x3e999f'
white: '0xf5f5f5'
indexed_colors:
- { index: 16, color: '0x5faf5f' }
- { index: 17, color: '0x5f8787' }
- { index: 18, color: '0xaf005f' }
- { index: 19, color: '0x5faf00' }
- { index: 20, color: '0x5fafd7' }
- { index: 21, color: '0xd7875f' }
# Visual Bell
#
# Any time the BEL code is received, Alacritty "rings" the visual bell. Once
@ -223,8 +168,6 @@ bell:
animation: EaseOutSine
duration: 0
# Background opacity
background_opacity: 0.9
# Mouse bindings
#

View File

@ -10,13 +10,3 @@ nix build .#yorick-home --no-link
nix run .#update-home
nixos-rebuild switch --flake .# --target-host root@localhost
rm -f result
set +x
echo "Updating nix-index cache"
(
filename="index-x86_64-$(uname | tr A-Z a-z)"
mkdir -p ~/.cache/nix-index
cd ~/.cache/nix-index
# -N will only download a new version if there is an update.
wget -q -N https://github.com/Mic92/nix-index-database/releases/latest/download/$filename
ln -f $filename files
)

99
bin/absorb.py Normal file
View File

@ -0,0 +1,99 @@
#!/usr/bin/env nix-shell
#!nix-shell -i python3 -p python3 python3.pkgs.requests -I nixpkgs=channel:nixos-22.05
import json, os, sys, hashlib
from pathlib import Path
import shutil
import tempfile
import requests
if len(sys.argv) < 3:
print(f"Usage: sudo {sys.argv[0]} [dest] [files..]", file=sys.stderr)
sys.exit(2)
if os.geteuid() != 0:
print("Please run as root", file=sys.stderr)
sys.exit(1)
plexmedia = Path("/data/plexmedia")
dest = plexmedia / sys.argv[1]
sections = {
"movies": 1,
"series": 2,
"anime-movies": 3,
"anime-series": 4,
"talks": 5
}
if not dest.is_dir():
print(f"Error: {dest} is not a directory/does not exist")
sys.exit(1)
sid = sections[sys.argv[1]]
def hashfile(path: Path) -> str:
hash = hashlib.sha256()
buf = bytearray(128 * 1024) # 128kb
mv = memoryview(buf)
with path.open('rb') as f:
while n := f.readinto(mv):
hash.update(mv[:n])
return hash.hexdigest()
def symlink_force(name: Path, target: Path) -> None:
try:
name.symlink_to(target)
except FileExistsError:
tmp = Path(tempfile.mktemp(dir=name.parent))
tmp.symlink_to(target)
tmp.replace(name)
def ca_import(source: Path) -> Path:
if not sourcepath.is_file() or sourcepath.is_symlink():
print(f"{sourcepath} is not a regular file")
if sourcepath.is_symlink():
rsv = sourcepath.resolve()
if rsv.parent == plexmedia / "ca":
return rsv
else:
sys.exit(2)
return
# CA import
print(f"[{source.name}] hash")
hash = hashfile(sourcepath)
print(hash)
ca_dest = (plexmedia / "ca" / hash).with_suffix(sourcepath.suffix)
print(f"[{source.name}] copy")
if ca_dest.exists():
print(f"warning: skipping copy, already in store")
else:
tmp_path = ca_dest.with_suffix(ca_dest.suffix + ".tmp")
tmp_path.unlink(missing_ok=True)
try:
shutil.copyfile(sourcepath, tmp_path)
except shutil.SameFileError:
print(f"warning: skipping copy, already in place")
tmp_path.rename(ca_dest)
#print(f"chown plex:plex {ca_dest}")
shutil.chown(ca_dest, user="plex", group="plex")
return ca_dest
for sourcefile in sys.argv[2:]:
sourcepath = Path(sourcefile)
print("CA", sourcepath)
ca_dest = ca_import(sourcepath)
# plex import
destpath = dest / sourcepath.name
print(f"ln -s {ca_dest} {destpath}")
symlink_force(destpath, ca_dest)
shutil.chown(destpath, user="plex", group="plex")
# torrent link
symlink_force(sourcepath, ca_dest)
with open("/home/yorick/plex_token", 'r') as f:
PLEX_TOKEN = f.read().splitlines()[0]
requests.get(f"https://plex.yori.cc/library/sections/{sid}/refresh", headers={
"X-Plex-Token": PLEX_TOKEN
})

View File

@ -1,5 +1,5 @@
#!/usr/bin/env bash
export BORG_REPO='14337@ch-s012.rsync.net:jarvis'
export BORG_REPO='zh3213@zh3213.rsync.net:jarvis'
export BORG_REMOTE_PATH=borg1
export BORG_PASSCOMMAND="pass sysadmin/jarvis-borg"
exec borg "$@"

View File

@ -1,4 +1,4 @@
#!/usr/bin/env bash
MAC=94:DB:56:79:7D:86
MAC=88:C9:E8:AD:73:E8
bluetoothctl info "$MAC" | grep -q 'Connected: yes' &&
bluetoothctl disconnect "$MAC" || bluetoothctl connect "$MAC"

View File

@ -10,6 +10,7 @@ import json
import subprocess
import sys
import i3ipc
import html
from pathlib import Path
if not Path("~/.gcalcli_oauth").expanduser().exists():
@ -18,10 +19,10 @@ if not Path("~/.gcalcli_oauth").expanduser().exists():
i3 = i3ipc.Connection()
accounts = ["yorickvanpelt@gmail.com", "yorick@datakami.nl", "yorick@replicate.com"]
gcal = GoogleCalendarInterface(
cal_names=parse_cal_names(["yorickvanpelt@gmail.com", "yorick.vanpelt@tweag.io"]),
cal_names=parse_cal_names(accounts),
config_folder=None, refresh_cache=False,
use_cache=True,
ignore_started=False,
@ -38,33 +39,50 @@ events = gcal._search_for_events(start=datetime.now(tzlocal()), end=start_date +
opt = sys.argv[1]
def authuser(evt):
if evt["gcalcli_cal"]["id"] == "yorickvanpelt@gmail.com":
return 0
else:
try:
return accounts.index(evt["gcalcli_cal"]["id"])
except ValueError:
return 1
def tooltip(evt):
# todo: location
return f"""
<b>{evt["summary"]}</b>
<b>{html.escape(evt["summary"])}</b>
{evt["s"].strftime("%b %d %H:%M")} - {evt["e"].strftime("%H:%M")}
"""
def openURI(uri):
subprocess.call(["systemd-run", "--user", "chromium", uri])
def getEventURL(evt):
""" Get URL that jumps into video call """
if 'location' in evt and evt['location'].startswith("https://app.gather.town"):
return evt['location']
elif 'hangoutLink' in evt:
# jump into video call
return evt["hangoutLink"] + "?authuser=" + str(authuser(evt))
return None
def click(evt):
# todo: only on certain time before
if 'hangoutLink' in evt:
# jump into video call
url = evt["hangoutLink"] + "?authuser=" + str(authuser(evt))
url = getEventURL(evt)
if url is not None:
subprocess.call(["playerctl", "pause"])
i3.command("focus output 'DVI-D-1', workspace --no-auto-back-and-forth 9")
subprocess.call(["chromium", url])
openURI(url)
else:
subprocess.call(["xdg-open", evt["htmlLink"]])
openURI(evt["htmlLink"])
def rightclick(evt):
subprocess.call(["xdg-open", "https://calendar.google.com"])
openURI("https://calendar.google.com")
events = [e for e in events if not gcal._DeclinedEvent(e)]
def interestedEvent(evt):
# ignore started all-day
if "date" in evt['start'] and evt['s'] < gcal.now:
return False
return not gcal._DeclinedEvent(evt) and evt['eventType'] == "default"
events = [e for e in events if interestedEvent(e)]
if opt == "dump":
print(json.dumps(events, default=str))
@ -81,6 +99,9 @@ if opt == "list": # todo: rename to first
for evt in events:
icon = ""
# todo: tooltip
if 'location' in evt and evt['location'].startswith("https://app.gather.town"):
# md-town_hall
icon = '\U000f1875'
if 'hangoutLink' in evt:
icon = ""
print(json.dumps({

View File

@ -26,4 +26,7 @@ in lib.mapAttrs (k: f: f k) {
y-cal-widget = makeWrap ./cal.py "${
python3.withPackages (p: [ (p.toPythonModule gcalcli) p.i3ipc ])
}/bin/python";
absorb = makeWrap ./absorb.py "${
python3.withPackages (p: [ p.requests ])
}/bin/python";
}

47
bin/dep-drill.sh Executable file
View File

@ -0,0 +1,47 @@
#!/usr/bin/env nix-shell
#!nix-shell -I nixpkgs=flake:nixpkgs -p bkt fzf moreutils ncdu -i bash
set -euo pipefail
# todo's:
# - preserve(track) selection when hitting ctrl-s
# https://github.com/junegunn/fzf/issues/3460
# - truncate nix store paths to fit terminal width
# awk?
# - prevent hitting left-arrow on an empty stack
STATE=$(mktemp -d --suffix .nixfzf)
function cleanup {
rm -rf "$STATE"
}
trap cleanup EXIT
if [ $# -ne 1 ]; then
echo "Usage: dep-drill.sh /nix/store/..."
exit 1
fi
# 3: sort -hk3 - sort by closure size, 2: sort -hk2 - own size
echo 3 > "$STATE"/sort
echo "$1" > "$STATE"/path
export SHELL=bash
export BKT_CACHE_DIR="$STATE/cache"
export BKT_TTL=10m
export FZF_DEFAULT_COMMAND='bkt -- nix path-info -rSsh $(tail -1 '"$STATE/path"') | sort -hk$(cat '"$STATE/sort"') | cut -c12-'
fzf --no-sort \
--layout=reverse-list \
--bind=load:last \
--track \
--preview 'bkt -- nix why-depends $(tail -1 '"$STATE/path"') /nix/store/{1} --precise --all' \
--preview-window=down,30%,border-top \
--preview-label=why-depends \
--info=inline \
--nth=1 \
--bind 'ctrl-s:execute-silent(sed -i "s/2/4/g; s/3/2/g; s/4/3/g" '"$STATE/sort"')+track+reload-sync<'"$FZF_DEFAULT_COMMAND"'>+transform-border-label(sed -n "s/2/sorted by own size/p; s/3/sorted by closure size/p" '"$STATE/sort"')' \
--bind 'ctrl-n:execute:ncdu /nix/store/{1}' \
--bind 'right:execute-silent(echo /nix/store/{1} >> '"$STATE/path"')+reload-sync<'"$FZF_DEFAULT_COMMAND"'>+clear-query' \
--bind 'left:execute-silent(uniq '"$STATE/path"' | head -n-1 | sponge '"$STATE/path"')+reload-sync<'"$FZF_DEFAULT_COMMAND"'>+clear-query' \
--border-label="sorted by closure size" \
--border=top \
--header="ctrl-s: toggle sort, ctrl-n: ncdu"

View File

@ -5,9 +5,11 @@ if [ -z "$ENTRY" ]; then
exit 1
fi
PASSENTRY=$(pass "$ENTRY")
# todo: kill after 30s
builtin echo "$PASSENTRY" | head -n1 | nohup wl-copy -f &
disown
builtin echo "$PASSENTRY" | head -n1 | nohup wl-copy -f -n --sensitive &
WLCOPY_PID=$!
disown -h
nohup bash -c "sleep 30s; kill $WLCOPY_PID" &
disown -h
NOTIFICATION=$(builtin echo "$PASSENTRY" | sed 1d)
notify-send -t 6000 "$NOTIFICATION"

4
bin/marvin-sub.sh Executable file
View File

@ -0,0 +1,4 @@
#!/bin/sh
set -euo pipefail
export PATH=$HOME/.nix-profile/bin:$PATH
mosquitto_sub -h frumar.home.yori.cc -u iot -P asdf -t "yorick/marvin/tracking" | jq --unbuffered -r 'if .task then if .started then "▶ \(.task.title)" else "⏸ \(.task.title)" end else "" end'

View File

@ -2,7 +2,7 @@
set -e
# Setup filename for the screenshot
myfile="$(openssl rand -base64 9)_$(date +%y%m%d%H%M%S).webp"
myfile="$(openssl rand -base64 9 | tr / -)_$(date +%y%m%d%H%M%S).webp"
webpath="https://pub.yori.cc/s/"
fileurl="$webpath$myfile"

1
deployer/.envrc Normal file
View File

@ -0,0 +1 @@
use flake ..#deployer

2
deployer/.gitignore vendored Normal file
View File

@ -0,0 +1,2 @@
node_modules/
dist/

5
deployer/.yarnignore Normal file
View File

@ -0,0 +1,5 @@
yarn-cache
index.ts
nix.ts
ssh.ts

2
deployer/bin/ydeployer.js Executable file
View File

@ -0,0 +1,2 @@
#!/usr/bin/env node
import "../dist/index.js"

240
deployer/index.ts Normal file
View File

@ -0,0 +1,240 @@
import { ssh, SSH } from './ssh.js'
import { Expression } from './nix.js'
type Dictionary<T> = Record<string, T>
type Command = () => Promise<void>
type Setter = (props: Dictionary<string | boolean | number>) => void
class Cmd {
registry: Dictionary<Command> = {};
settings: Dictionary<Setter> = {};
register(obj: string, action: string, fn: Command) {
this.registry[`${obj}.${action}`] = fn
}
registerAll(obj: string, intf: Object & { _commands?: string[], set?: Setter }) {
if (!intf._commands) return
if (intf.set) this.settings[obj] = intf.set.bind(intf)
const proto = Object.getPrototypeOf(intf)
for (const name of intf._commands) {
if (name != "constructor" && typeof proto[name] === "function") {
this.register(obj, name, proto[name].bind(intf))
}
}
}
async run() {
const opt = argv._[0]
for (const k of Object.keys(argv)) {
if (k === "_") continue
if (this.settings[k]) {
this.settings[k](argv[k])
} else {
throw new Error("unknown object " + k)
}
}
if (opt == "__autocompletes") {
for (const k of Object.keys(this.registry)) {
console.log(k)
}
return
}
if (opt && this.registry[opt]) await this.registry[opt]()
else {
console.log("Possible options: \n")
for (const k of Object.keys(this.registry)) {
console.log("-", k)
}
}
}
}
const action = new Cmd()
async function ping(hostname: string) {
return await $`ping -Anqc3 ${hostname}`.exitCode == 0
}
class Machine {
name: string;
hasHome: boolean = false;
hostname?: string;
constructor({name = "", hasHome = false, hostname}: {name?: string, hasHome?: boolean, hostname?: string}) {
this.name = name
this.hasHome = hasHome
this.hostname = hostname
// name can be set later
}
isLocal() {
return os.hostname() == this.name
}
get attr(): Expression {
return new Expression(`.#nixosConfigurations.${this.name}.toplevel`)
}
private async sshTarget() {
if (this.isLocal()) return "localhost"
if (this.hostname && await ping(this.hostname)) {
return this.hostname
} else {
// todo: directify
return `${this.name}.home.yori.cc`
}
}
async findIP(): Promise<typeof Machine.prototype.ssh> {
const host = await this.sshTarget()
return <R>(user?: string, cb?: () => Promise<R>): Promise<SSH|R> => {
const sshTarget = user ? `${user}@${host}` : host
if (cb !== undefined) return ssh(sshTarget, cb)
return ssh(sshTarget)
}
}
ssh(user?: string): Promise<SSH>
ssh<R>(user?: string, cb?: () => Promise<R>): Promise<R>
async ssh<R>(user?: string, cb?: () => Promise<R>) {
return (await this.findIP())(user, cb)
}
get targets() {
if (this.hasHome) return [this.attr, Home]
else return [this.attr]
}
}
const machines = {
frumar: new Machine({hostname: "frumar.home.yori.cc"}),
pennyworth: new Machine({hostname: "pennyworth.yori.cc"}),
blackadder: new Machine({hasHome: true}),
jarvis: new Machine({hasHome: true}),
smithers: new Machine({hasHome: true}),
}
for (const [name, machine] of Object.entries(machines))
machine.name = name
function cmd(target: { _commands?: string[] }, propertyKey: string, _descriptor: PropertyDescriptor): void {
if (target._commands == undefined) target._commands = []
target._commands.push(propertyKey)
}
class MachineInterface {
_commands?: string[]
constructor(public machine: Machine) {
// hack:
delete this._commands
}
set(props: Dictionary<string | boolean | number>) {
console.log("setting", props)
Object.assign(this.machine, props)
}
@cmd
async ssh() {
(await this.machine.ssh()).interactive()
}
@cmd
gc() {
return this.machine.ssh("root", () => $`nix-collect-garbage -d`)
}
@cmd
eval() {
return Promise.all(this.machine.targets.map(x => x.derive()))
}
@cmd
build() {
return Promise.all(this.machine.targets.map(x => x.build()))
}
@cmd
status() {
return this.machine.ssh(undefined, async () => {
await $`systemctl is-system-running`
await $`zpool status -x`
await $`realpath /run/current-system /nix/var/nix/profiles/system`
})
}
@cmd
async copy() {
const machineSSH = await this.machine.findIP()
const outputs = (await Promise.all(this.machine.targets.map(x => x.build().then(Object.values)))).flat()
if (this.machine.isLocal()) {
console.log("skipping copy, is localhost")
return
}
const conn = await machineSSH()
await Promise.all(Object.values(outputs).map(x => x.copy(conn)))
// machine.toplevel.buildAndCopy(machine.ssh)
// Home.buildAndCopy(machine.ssh)
}
@cmd
async "boot-deploy"() {
const machineSSH = await this.machine.findIP()
const path = (await this.machine.attr.build()).out
if (!this.machine.isLocal()) {
const conn = await machineSSH()
await path.copy(conn)
}
// machine.toplevel.buildAndCopy(machine.ssh)
// machine.ssh.within(machine.toplevel.activate("boot"))
await machineSSH("root", async () => {
await $`nix-env -p /nix/var/nix/profiles/system --set ${path.path}`
await $`${path.path as string}/bin/switch-to-configuration boot`
})
}
@cmd
async "switch"() {
const machineSSH = await this.machine.findIP()
const path = (await this.machine.attr.build()).out
if (!this.machine.isLocal()) {
const conn = await machineSSH()
await path.copy(conn)
}
const new_kernel = (await $`readlink ${path.path}/kernel`).stdout
await machineSSH("root", async () => {
const old_kernel = (await $`readlink /run/booted-system/kernel`).stdout
if (new_kernel !== old_kernel) {
console.error(`[${this.machine.name}] requires reboot because of kernel update`)
process.exit(1)
}
await $`nix-env -p /nix/var/nix/profiles/system --set ${path.path}`
await $`${path.path}/bin/switch-to-configuration switch`
})
}
}
class MachineInterfaceHome extends MachineInterface {
@cmd
async "update-home"() {
const new_path = (await Home.build()).out
if (this.machine.isLocal()) {
await $`${new_path.path}/activate`
} else {
const conn = await this.machine.ssh()
await new_path.copy(conn)
await conn.within(() => $`${new_path.path}/activate`)
}
}
}
for (const machine of Object.values(machines)) {
action.registerAll(machine.name, machine.hasHome ? new MachineInterfaceHome(machine) : new MachineInterface(machine))
}
action.register("all", "build", async () => {
console.log(await (new Expression(".#")).build())
})
const Home = new Expression(".#yorick-home")
action.register("home", "build", async () => {
console.log(await Home.build())
})
action.register("home", "eval", async () => {
console.log(await Home.derive())
})
action.register("local", "boot-deploy", async () => {
await action.registry[`${os.hostname()}.boot-deploy`]()
})
action.register("local", "status", async () => {
await action.registry[`${os.hostname()}.status`]()
})
await action.run()

137
deployer/nix.ts Normal file
View File

@ -0,0 +1,137 @@
import 'zx/globals';
import { SSH } from './ssh.js'
type DrvPath = string
type OutPath = string
type NixPath = DrvPath | OutPath
type ShownDerivation = {
args: Array<string>,
builder: string,
env: Record<string, string>,
inputDrvs: Record<DrvPath, string[]>,
inputSrcs: Array<OutPath>,
outputs: Record<string, { path: OutPath }>,
system: "x86-64_linux"
};
type ShowDerivationOutput = Record<DrvPath, ShownDerivation>
type OutputSpec<R> = { out: R } & Record<string, R>
type BuildOutput = {
drvPath: DrvPath,
outputs: OutputSpec<OutPath>,
startTime?: number,
stopTime?: number
}
export class Expression {
expr: string
constructor(expr: string) {
this.expr = expr
}
async derive(): Promise<Derivation> {
const {drvPath} = await nix.derive(this.expr)
const drv = await nix.showDerivation(drvPath)
return new Derivation(drvPath, drv[drvPath])
}
async build(): Promise<OutputSpec<BuiltOutput>> {
const outputs = await nix.build(this.expr)
const drvMetaJson = await nix.showDerivation(outputs.drvPath)
const [drvPath, drvMeta] = Object.entries(drvMetaJson)[0]
const drv = new Derivation(drvPath, drvMeta)
const ret: Record<string, BuiltOutput> = {}
for (const [k, v] of Object.entries(outputs.outputs)) {
ret[k] = new BuiltOutput(v, drv)
}
return Object.assign(ret, { out: ret.out })
}
}
export class Derivation {
path: string
//outputs?: Array<BuiltOutput>
meta: ShownDerivation
constructor(path: string, meta: ShownDerivation) {
this.path = path
this.meta = meta
}
async build(): Promise<{out: BuiltOutput} & Array<BuiltOutput>> {
const outputs: BuildOutput = await nix.build(this.path)
const ret = Object.values(outputs.outputs).map(x => new BuiltOutput(x, this))
return Object.assign(ret, { out: new BuiltOutput(this.meta.outputs.out.path, this) })
}
}
export class BuiltOutput {
path: string
drv: Derivation
constructor(path: string, drv: Derivation) {
this.path = path
this.drv = drv
}
async copy(target: SSH): Promise<void> {
return nix.copy(this.path, target)
}
}
function dedupe<A, B, Rest extends any[]>(fn: (xs: A[], ...rest: Rest) => Promise<B[]>):
{ (x: A, ...rest: Rest): Promise<B>; (x: A[], ...rest: Rest): Promise<B[]>; } {
type QueueEntry = {
x: A,
resolve: (res: B) => void,
reject: (err: any) => void
}
const queues = new Map<string, QueueEntry[]>()
function inner(x: A, ...rest: Rest): Promise<B>
function inner(x: A[], ...rest: Rest): Promise<B[]>
function inner(x: A | A[], ...rest: Rest) {
// todo: also dedupe array results
if (Array.isArray(x)) return fn(x, ...rest)
// map queue by rest
const stringified = JSON.stringify(rest)
const had = queues.has(stringified)
const queue = queues.get(stringified) || []
const ret = new Promise<B>((resolve, reject) => {
queue.push({x, resolve, reject})
})
if (!had) {
queues.set(stringified, queue)
setImmediate(() => {
queues.delete(stringified)
fn(queue.map(({x}) => x), ...rest)
.then(results => {
for (const [i, {resolve}] of queue.entries()) resolve(results[i])
})
.catch(e => {
for (const {reject} of queue) reject(e)
})
})
}
return ret
}
return inner
}
//function nixBuild(attr: string[]): Promise<BuildOutput[]>
//function nixBuild(attr: string): Promise<BuildOutput>
async function nixBuild(attr: string[]): Promise<BuildOutput[]> {
const tmp = (await $`mktemp -d`).stdout.trim()
process.on('exit', () => fs.removeSync(tmp))
const ret = JSON.parse((await $`nom build --json ${attr} -o ${tmp}/result`).stdout)
if (Array.isArray(attr)) return ret
return ret[0]
}
namespace nix {
export const build = dedupe(nixBuild)
export async function showDerivation(path: NixPath): Promise<ShowDerivationOutput> {
return JSON.parse((await $`nix show-derivation ${path}`.quiet()).stdout)
}
export const derive = dedupe(async (attr: string[]): Promise<BuildOutput[]> => {
return JSON.parse((await $`nom build --json --dry-run ${attr}`).stdout)
})
export const copy = dedupe(async (attrs: string[], target: SSH): Promise<void[]> => {
process.env.NIX_SSHOPTS = "-o compression=no";
await $`nix copy ${attrs} -s --to ssh://${target.host}`
return Array(attrs.length)
})
}

32
deployer/package.json Normal file
View File

@ -0,0 +1,32 @@
{
"name": "deployer",
"private": true,
"version": "1.0.0",
"description": "",
"main": "index.js",
"directories": {
"test": "test"
},
"type": "module",
"bin": {
"ydeployer": "./bin/ydeployer.js"
},
"scripts": {
"watch": "exec tsc --noEmit -w",
"start": "exec tsx ./index.ts",
"test": "echo \"Error: no test specified\" && exit 1",
"prepare": "exec tsup ./*.ts --dts --format esm"
},
"repository": {
"type": "git",
"url": "https://git.yori.cc/yorick/dotfiles"
},
"author": "",
"license": "ISC",
"dependencies": {
"tsup": "^6.7.0",
"tsx": "^3.12.2",
"typescript": "^4.9.4",
"zx": "^7.1.1"
}
}

13
deployer/package.nix Normal file
View File

@ -0,0 +1,13 @@
{ buildYarnPackage }:
buildYarnPackage {
src = ./.;
postBuild = ''
yarn install --production --ignore-scripts --prefer-offline
'';
postInstall = ''
rm $out/bin/yarn
sed -i '/^cd /d' $out/bin/ydeployer
'';
meta.mainProgram = "ydeployer";
passthru.exePath = "/bin/ydeployer";
}

102
deployer/ssh.ts Normal file
View File

@ -0,0 +1,102 @@
import 'zx/globals';
import { spawn, ChildProcess } from 'child_process'
import { Socket } from 'node:net'
async function promiseWithTimeout<T>(timeoutMs: number, promise: Promise<T>, failureMessage?: string) {
let timeoutHandle: NodeJS.Timeout | null = null
const timeoutPromise = new Promise<never>((_resolve, reject) => {
timeoutHandle = setTimeout(() => reject(new Error(failureMessage)), timeoutMs)
})
const result = await Promise.race([promise, timeoutPromise])
if (timeoutHandle) clearTimeout(timeoutHandle)
return result
}
const to_kill: ProcessPromise[] = []
// sad that I can't chain these
process.on("uncaughtException", err => {
console.error("uncaught exception", err)
console.log("killing", to_kill.length, "child processes")
for (const k of to_kill) if (k.child?.pid) process.kill(k.child.pid)
to_kill.length = 0
process.exit(1)
})
export function ssh(host: string): Promise<SSH>
export function ssh<R>(host: string, cb: () => Promise<R>): Promise<R>
export async function ssh<R>(host: string, cb?: () => Promise<R>) {
const ret = new SSH(host)
try {
await ($`ssh ${host} -O check`).quiet()
} catch (p) {
if (p instanceof ProcessOutput && p.exitCode == 255) {
console.log("Spawning ssh master")
const x = $`ssh ${host} -M -N -o Compression=no -o PermitLocalCommand=yes -o LocalCommand="echo connected"`
to_kill.push(x)
await promiseWithTimeout(60000, new Promise<void>((resolve, _reject) => {
x.stdout.on('data', (d: Buffer) => {
if (d.toString('utf8').trim() == "connected")
resolve()
})
}))
if (x.child) {
x.child.unref()
if (x.child.stderr instanceof Socket) x.child.stderr.unref()
if (x.child.stdout instanceof Socket) x.child.stdout.unref()
ret.child = x.child
process.on('beforeExit', () => {
ret.stop()
})
} else {
console.warn("Failed to spawn SSH master, but someone else did")
}
} else {
throw p
}
}
if (cb !== undefined) return ret.within(cb)
else return ret
}
export class SSH {
child?: ChildProcess | null;
constructor(public host: string) { }
within<R>(cb: () => Promise<R>): Promise<R> {
return within(async () => {
// todo: the default options.shell is set to local which.sync('bash')
// which doesn't neccesarily work on the remote
$.shell = "bash"
$.spawn = (command: string, options: any): any => {
const stdio = ["pipe", options.stdio[1], options.stdio[2]]
const proc: ChildProcess = spawn("ssh", [this.host, options.shell],
Object.assign({}, options, {shell: false, stdio}))
// todo: type safety
if (!proc.stdin) throw new Error("Failed to spawn input pipe")
proc.stdin.write(command + "; exit $?\n")
if (options.stdio[0] == 'inherit') process.stdin.pipe(proc.stdin)
return proc
}
$.log = (entry) => {
switch(entry.kind) {
case 'cmd':
if (entry.verbose) process.stderr.write(`[${this.host}] `)
break;
}
log(entry)
}
return cb()
})
}
interactive() {
$`ssh ${this.host}`
}
stop() {
if (this.child) {
$`ssh ${this.host} -O stop`
this.child = null
}
}
}

15
deployer/tsconfig.json Normal file
View File

@ -0,0 +1,15 @@
{
"compilerOptions": {
"module": "es2022",
"allowSyntheticDefaultImports": true,
"moduleResolution": "nodenext",
"target": "es2022",
"strict": true,
"experimentalDecorators": true
},
"files": [
"ssh.ts",
"nix.ts",
"index.ts",
]
}

1006
deployer/yarn.lock Normal file

File diff suppressed because it is too large Load Diff

View File

@ -13,7 +13,14 @@
(:name "all mail" :query "*" :key "a")
(:name "inbox" :query "tag:inbox")))
'(safe-local-variable-values
'((flycheck-gcc-language-standard . "c++11")
'((transient-values
(magit-commit "--signoff"))
(magit-status-mode
(transient-values
(magit-commit "--signoff")))
(magit-commit-signoff quote t)
(magit-commit-signoff 't)
(flycheck-gcc-language-standard . "c++11")
(flycheck-clang-language-standard . "c++11")
(c-block-comment-prefix . " ")
(eval c-set-offset 'inlambda 0)

View File

@ -366,6 +366,8 @@ from https://vickychijwani.me/nuggets-from-my-emacs-part-i/
:config
;; use copilot
(delq 'company-preview-if-just-one-frontend company-frontends))
(use-package company-box
:hook (company-mode . company-box-mode))
#+END_SRC
** Indentation
#+BEGIN_SRC emacs-lisp

10
esphome/.gitignore vendored Normal file
View File

@ -0,0 +1,10 @@
# Gitignore settings for ESPHome
# This is an example and may include too much for your use-case.
# You can modify this file to suit your needs.
/.esphome/
**/.pioenvs/
**/.piolibdeps/
**/lib/
**/src/
**/platformio.ini
/secrets.yaml

10
esphome/pvvx.yaml Normal file
View File

@ -0,0 +1,10 @@
platform: pvvx_mithermometer
mac_address: ${mac}
temperature:
name: "${name} temperature"
humidity:
name: "${name} humidity"
battery_level:
name: "${name} Battery-Level"
battery_voltage:
name: "${name} Battery-Voltage"

11
esphome/secrets.yaml.age Normal file
View File

@ -0,0 +1,11 @@
-----BEGIN AGE ENCRYPTED FILE-----
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBvMXJHdFNZNVpBbHo4c0J6
cnlONGYyMlhLNG9yMTN4azgvWWFIQlJXMTJnCldmTlppNlY1KzVma2tLNS9XRW80
a04zaStaODZhU1JNREtpTWJobC9iRGcKLS0tIGkreVJLOVY5Z01WOXRwc0hKZUFU
V3FFU0pSVE1VU2JBZ3RFcElUemFuS2MK3mAi5/6HU+TfA9vaTWpB5pZPGw+F5Enq
iuCQKK6I5SCjoFfjOglTwte/2CqbNwgECV+TsDiAZDqSVBohW9eyxe8m9g2ioYLw
4wfiGo3j99ITNss6bNeisdhV5qsZW3o7RDxeTv3U03Tj102Q9ciY31Q7hzvQmZ3Z
280GrkxUdrwGe7JlWRDvqlmKZdOmi2GRQJ7KTkNIJSSIvv1rzQ3sWTenvUJAljul
LtzTkxV8SCOfVWeqZMvi1aBrc2r2rkE/a/TRqVBb7wFrvN7Uh1ZTst71tLG7EsyQ
qrncLc63Y8XgHQ3kdNE=
-----END AGE ENCRYPTED FILE-----

69
esphome/werkkamer.yaml Normal file
View File

@ -0,0 +1,69 @@
substitutions:
devicename: werkkamer
esphome:
name: ${devicename}
platform: ESP32
board: nodemcu-32s
wifi:
ssid: !secret wifi_ssid
password: !secret wifi_password
# Enable fallback hotspot (captive portal) in case wifi connection fails
ap:
ssid: "${devicename} Fallback Hotspot"
password: !secret fallback_password
captive_portal:
web_server:
prometheus:
esp32_ble_tracker:
uart:
- rx_pin: GPIO16
tx_pin: GPIO17
baud_rate: 9600
sensor:
- <<: !include
file: pvvx.yaml
vars:
mac: "A4:C1:38:70:C4:53"
name: "werkkamer"
- <<: !include
file: pvvx.yaml
vars:
name: "larswerk"
mac: "A4:C1:38:89:D8:C2"
- <<: !include
file: pvvx.yaml
vars:
name: "zolder"
mac: "A4:C1:38:F6:5C:72"
- platform: ble_rssi
mac_address: "E4:A8:DB:C1:F5:B9"
name: "Yoricks watch"
- platform: mhz19
co2:
name: "MH-Z19 CO2 Value"
temperature:
name: "MH-Z19 Temperature"
update_interval: 60s
automatic_baseline_calibration: false
id: mhz_19
# woonkamer: A4:C1:38:2B:03:1F (not enough power)
api:
services:
- service: mhz19_calibrate_zero
then:
- mhz19.calibrate_zero: mhz_19
# Enable logging
logger:
# Enable Home Assistant API
# api:
mqtt:
broker: 192.168.2.127
username: !secret mqtt_username
password: !secret mqtt_password
ota:

View File

@ -0,0 +1,6 @@
nvs, data, nvs, 0x009000, 0x005000,
otadata, data, ota, 0x00e000, 0x002000,
app0, app, ota_0, 0x010000, 0x1C0000,
app1, app, ota_1, 0x1D0000, 0x1C0000,
eeprom, data, 0x99, 0x390000, 0x001000,
spiffs, data, spiffs, 0x391000, 0x00F000
1 nvs, data, nvs, 0x009000, 0x005000,
2 otadata, data, ota, 0x00e000, 0x002000,
3 app0, app, ota_0, 0x010000, 0x1C0000,
4 app1, app, ota_1, 0x1D0000, 0x1C0000,
5 eeprom, data, 0x99, 0x390000, 0x001000,
6 spiffs, data, spiffs, 0x391000, 0x00F000

View File

@ -1,13 +1,16 @@
(pkgs: super: {
electrum = super.electrum.overrideAttrs (o: {
# todo: remove (194112)
postPatch = ''
# make compatible with protobuf4 by easing dependencies ...
substituteInPlace ./contrib/requirements/requirements.txt \
--replace "protobuf>=3.12,<4" "protobuf>=3.12"
# ... and regenerating the paymentrequest_pb2.py file
protoc --python_out=. electrum/paymentrequest.proto
'';
});
# https://github.com/NixOS/nixpkgs/pull/278153
nats-server = super.buildGoModule rec {
pname = "nats-server";
version = "2.10.11";
src = pkgs.fetchFromGitHub {
owner = "nats-io";
repo = pname;
rev = "v${version}";
hash = "sha256-fRbjAqu1tFLUUk7aeIkEifcWkDUhNCbVZ957b2ntD+o=";
};
doCheck = false;
vendorHash = "sha256-lVCWTZvzLkYl+o+EUQ0kzIhgl9C236w9i3RRA5o+IAw=";
};
# todo re-enable cachix
})

1050
flake.lock

File diff suppressed because it is too large Load Diff

View File

@ -1,20 +1,43 @@
{
description = "Yoricks dotfiles";
inputs = {
nixpkgs.url = "github:nixos/nixpkgs/nixos-unstable";
nixpkgs.url = "github:nixos/nixpkgs/nixos-23.11";
home-manager.url = "github:nix-community/home-manager/release-23.11";
home-manager.inputs.nixpkgs.follows = "nixpkgs";
nixpkgs-mozilla.url = "github:mozilla/nixpkgs-mozilla";
emacs-overlay.inputs.nixpkgs.follows = "nixpkgs";
nixpkgs-wayland.url = "github:nix-community/nixpkgs-wayland";
nixpkgs-wayland.inputs.nixpkgs.follows = "nixpkgs";
nixpkgs-stable.url = "github:nixos/nixpkgs/nixos-21.05";
nixos-mailserver.url = "gitlab:simple-nixos-mailserver/nixos-mailserver";
nixos-mailserver.url = "gitlab:simple-nixos-mailserver/nixos-mailserver/nixos-23.11";
nixos-mailserver.inputs.nixpkgs.follows = "nixpkgs";
agenix.url = "github:ryantm/agenix";
agenix.inputs.nixpkgs.follows = "nixpkgs";
nix-index-database.url = "github:Mic92/nix-index-database";
nix-index-database.inputs.nixpkgs.follows = "nixpkgs";
nix-npm-buildpackage.url = "github:serokell/nix-npm-buildpackage";
nix-npm-buildpackage.inputs.nixpkgs.follows = "nixpkgs";
yobot.url = "git+https://git.yori.cc/yorick/yobot.git";
attic = {
url = "github:zhaofengli/attic";
inputs = {
nixpkgs-stable.follows = "nixpkgs";
nixpkgs.follows = "nixpkgs";
flake-utils.follows = "flake-utils";
};
};
timesync = {
url = "github:datakami/timesync";
inputs.nixpkgs.follows = "nixpkgs";
};
fooocus.url = "path:./pkgs/fooocus";
dream2nix.url = "github:nix-community/dream2nix";
dream2nix.inputs.nixpkgs.follows = "nixpkgs";
};
outputs = inputs@{ nixpkgs, home-manager, nixpkgs-mozilla, emacs-overlay
, nixpkgs-wayland, nixpkgs-stable, nixos-hardware, agenix, flake-utils, self
, nixpkgs-wayland, nixos-hardware, agenix, flake-utils
, nix-index-database, nix-npm-buildpackage, timesync
, attic, dream2nix, yobot
, self
, ... }:
(flake-utils.lib.eachSystem [ "x86_64-linux" ] (system:
let pkgs = self.legacyPackages.${system};
@ -24,6 +47,7 @@
allowUnfree = true;
# chromium.vaapiSupport = true;
android_sdk.accept_license = true;
permittedInsecurePackages = [];
};
inherit system;
overlays = [ self.overlays.default ];
@ -44,6 +68,7 @@
inherit pkgs;
modules = [
./home-manager/home.nix
nix-index-database.hmModules.nix-index
{
home = {
username = "yorick";
@ -54,6 +79,22 @@
];
};
devShells.default = pkgs.mkShell {
buildInputs = with pkgs; [
y-deployer
pkgs.agenix
];
};
devShells.deployer = pkgs.mkShell {
buildInputs = with pkgs; [
yarn
nodePackages.typescript-language-server
];
};
apps.default = flake-utils.lib.mkApp {
drv = pkgs.y-deployer;
};
# updater script for home profile
# works around https://github.com/nix-community/home-manager/issues/2848
apps.update-home = flake-utils.lib.mkApp {
@ -69,20 +110,20 @@
};
})) // {
overlays.default = nixpkgs.lib.composeManyExtensions [
nixpkgs-wayland.overlay
#nixpkgs-mozilla.overlay
#nixpkgs-wayland.overlay
nixpkgs-mozilla.overlay
emacs-overlay.overlay
agenix.overlay
agenix.overlays.default
attic.overlays.default
(import ./fixups.nix)
(import ./pkgs)
(import ./pkgs/mdr.nix)
(final: prev: {
nixpkgs-stable = import nixpkgs-stable {
system = prev.stdenv.system;
config = { };
overlays = [ ];
};
flake-inputs = inputs;
nix-npm-buildpackage = nix-npm-buildpackage.legacyPackages."${final.system}";
fooocus = inputs.fooocus.packages.${final.system}.default;
inherit (nixpkgs-wayland.packages.${final.system}) wldash;
})
(import ./nixos/overlay.nix)
];

View File

@ -0,0 +1,520 @@
{ config, lib, pkgs, ... }:
with lib;
let
cfg = config.accounts.email;
gpgModule = types.submodule {
options = {
key = mkOption {
type = types.str;
description = ''
The key to use as listed in <command>gpg --list-keys</command>.
'';
};
signByDefault = mkOption {
type = types.bool;
default = false;
description = "Sign messages by default.";
};
encryptByDefault = mkOption {
type = types.bool;
default = false;
description = "Encrypt outgoing messages by default.";
};
};
};
signatureModule = types.submodule {
options = {
text = mkOption {
type = types.str;
default = "";
example = ''
--
Luke Skywalker
May the force be with you.
'';
description = ''
Signature content.
'';
};
delimiter = mkOption {
type = types.str;
default = ''
--
'';
example = literalExpression ''
~*~*~*~*~*~*~*~*~*~*~*~
'';
description = ''
The delimiter used between the document and the signature.
'';
};
command = mkOption {
type = with types; nullOr path;
default = null;
example = literalExpression ''
pkgs.writeScript "signature" "echo This is my signature"
'';
description = "A command that generates a signature.";
};
showSignature = mkOption {
type = types.enum [ "append" "attach" "none" ];
default = "none";
description = "Method to communicate the signature.";
};
};
};
tlsModule = types.submodule {
options = {
enable = mkOption {
type = types.bool;
default = true;
description = ''
Whether to enable TLS/SSL.
'';
};
useStartTls = mkOption {
type = types.bool;
default = false;
description = ''
Whether to use STARTTLS.
'';
};
certificatesFile = mkOption {
type = types.nullOr types.path;
default = config.accounts.email.certificatesFile;
defaultText = "config.accounts.email.certificatesFile";
description = ''
Path to file containing certificate authorities that should
be used to validate the connection authenticity. If
<literal>null</literal> then the system default is used.
Note, if set then the system default may still be accepted.
'';
};
};
};
imapModule = types.submodule {
options = {
host = mkOption {
type = types.str;
example = "imap.example.org";
description = ''
Hostname of IMAP server.
'';
};
port = mkOption {
type = types.nullOr types.port;
default = null;
example = 993;
description = ''
The port on which the IMAP server listens. If
<literal>null</literal> then the default port is used.
'';
};
tls = mkOption {
type = tlsModule;
default = { };
description = ''
Configuration for secure connections.
'';
};
};
};
jmapModule = types.submodule {
options = {
host = mkOption {
type = types.nullOr types.str;
default = null;
example = "jmap.example.org";
description = ''
Hostname of JMAP server.
</para><para>
If both this option and <xref
linkend="opt-accounts.email.accounts._name_.jmap.sessionUrl"/> are specified,
<code>host</code> is preferred by applications when establishing a
session.
'';
};
sessionUrl = mkOption {
type = types.nullOr types.str;
default = null;
example = "https://jmap.example.org:443/.well-known/jmap";
description = ''
URL for the JMAP Session resource.
</para><para>
If both this option and <xref
linkend="opt-accounts.email.accounts._name_.jmap.host"/> are specified,
<code>host</code> is preferred by applications when establishing a
session.
'';
};
};
};
smtpModule = types.submodule {
options = {
host = mkOption {
type = types.str;
example = "smtp.example.org";
description = ''
Hostname of SMTP server.
'';
};
port = mkOption {
type = types.nullOr types.port;
default = null;
example = 465;
description = ''
The port on which the SMTP server listens. If
<literal>null</literal> then the default port is used.
'';
};
tls = mkOption {
type = tlsModule;
default = { };
description = ''
Configuration for secure connections.
'';
};
};
};
maildirModule = types.submodule ({ config, ... }: {
options = {
path = mkOption {
type = types.str;
description = ''
Path to maildir directory where mail for this account is
stored. This is relative to the base maildir path.
'';
};
absPath = mkOption {
type = types.str;
default = "${cfg.maildirBasePath}/${config.path}";
description = ''
A convenience option whose value is the absolute path of
this maildir.
'';
};
};
});
mailAccountOpts = { name, config, ... }: {
options = {
name = mkOption {
type = types.str;
readOnly = true;
description = ''
Unique identifier of the account. This is set to the
attribute name of the account configuration.
'';
};
primary = mkOption {
type = types.bool;
default = false;
description = ''
Whether this is the primary account. Only one account may be
set as primary.
'';
};
flavor = mkOption {
type = types.enum [
"plain"
"gmail.com"
"runbox.com"
"fastmail.com"
"yandex.com"
"outlook.office365.com"
];
default = "plain";
description = ''
Some email providers have peculiar behavior that require
special treatment. This option is therefore intended to
indicate the nature of the provider.
</para><para>
When this indicates a specific provider then, for example,
the IMAP, SMTP, and JMAP server configuration may be set
automatically.
'';
};
address = mkOption {
type = types.strMatching ".*@.*";
example = "jane.doe@example.org";
description = "The email address of this account.";
};
aliases = mkOption {
type = types.listOf (types.strMatching ".*@.*");
default = [ ];
example = [ "webmaster@example.org" "admin@example.org" ];
description = "Alternative email addresses of this account.";
};
realName = mkOption {
type = types.str;
example = "Jane Doe";
description = "Name displayed when sending mails.";
};
userName = mkOption {
type = types.nullOr types.str;
default = null;
description = ''
The server username of this account. This will be used as
the SMTP, IMAP, and JMAP user name.
'';
};
passwordCommand = mkOption {
type = types.nullOr (types.either types.str (types.listOf types.str));
default = null;
apply = p: if isString p then splitString " " p else p;
example = "secret-tool lookup email me@example.org";
description = ''
A command, which when run writes the account password on
standard output.
'';
};
folders = mkOption {
type = types.submodule {
options = {
inbox = mkOption {
type = types.str;
default = "Inbox";
description = ''
Relative path of the inbox mail.
'';
};
sent = mkOption {
type = types.nullOr types.str;
default = "Sent";
description = ''
Relative path of the sent mail folder.
'';
};
drafts = mkOption {
type = types.nullOr types.str;
default = "Drafts";
description = ''
Relative path of the drafts mail folder.
'';
};
trash = mkOption {
type = types.str;
default = "Trash";
description = ''
Relative path of the deleted mail folder.
'';
};
};
};
default = { };
description = ''
Standard email folders.
'';
};
imap = mkOption {
type = types.nullOr imapModule;
default = null;
description = ''
The IMAP configuration to use for this account.
'';
};
jmap = mkOption {
type = types.nullOr jmapModule;
default = null;
description = ''
The JMAP configuration to use for this account.
'';
};
signature = mkOption {
type = signatureModule;
default = { };
description = ''
Signature configuration.
'';
};
gpg = mkOption {
type = types.nullOr gpgModule;
default = null;
description = ''
GPG configuration.
'';
};
smtp = mkOption {
type = types.nullOr smtpModule;
default = null;
description = ''
The SMTP configuration to use for this account.
'';
};
maildir = mkOption {
type = types.nullOr maildirModule;
defaultText = { path = "\${name}"; };
description = ''
Maildir configuration for this account.
'';
};
};
config = mkMerge [
{
name = name;
maildir = mkOptionDefault { path = "${name}"; };
}
(mkIf (config.flavor == "yandex.com") {
userName = mkDefault config.address;
imap = {
host = "imap.yandex.com";
port = 993;
tls.enable = true;
};
smtp = {
host = "smtp.yandex.com";
port = 465;
tls.enable = true;
};
})
(mkIf (config.flavor == "outlook.office365.com") {
userName = mkDefault config.address;
imap = {
host = "outlook.office365.com";
port = 993;
tls.enable = true;
};
smtp = {
host = "smtp.office365.com";
port = 587;
tls = {
enable = true;
useStartTls = true;
};
};
})
(mkIf (config.flavor == "fastmail.com") {
userName = mkDefault config.address;
imap = {
host = "imap.fastmail.com";
port = 993;
};
smtp = {
host = "smtp.fastmail.com";
port = if config.smtp.tls.useStartTls then 587 else 465;
};
jmap = {
host = "fastmail.com";
sessionUrl = "https://jmap.fastmail.com/.well-known/jmap";
};
})
(mkIf (config.flavor == "gmail.com") {
userName = mkDefault config.address;
imap = {
host = "imap.gmail.com";
port = 993;
};
smtp = {
host = "smtp.gmail.com";
port = if config.smtp.tls.useStartTls then 587 else 465;
};
})
(mkIf (config.flavor == "runbox.com") {
imap = { host = "mail.runbox.com"; };
smtp = { host = "mail.runbox.com"; };
})
];
};
in {
options.accounts.email = {
certificatesFile = mkOption {
type = types.nullOr types.path;
default = "/etc/ssl/certs/ca-certificates.crt";
description = ''
Path to default file containing certificate authorities that
should be used to validate the connection authenticity. This
path may be overridden on a per-account basis.
'';
};
maildirBasePath = mkOption {
type = types.str;
default = "${config.home.homeDirectory}/Maildir";
defaultText = "$HOME/Maildir";
apply = p:
if hasPrefix "/" p then p else "${config.home.homeDirectory}/${p}";
description = ''
The base directory for account maildir directories. May be a
relative path, in which case it is relative the home
directory.
'';
};
accounts = mkOption {
type = types.attrsOf (types.submodule mailAccountOpts);
default = { };
description = "List of email accounts.";
};
};
config = mkIf (cfg.accounts != { }) {
assertions = [
(let
primaries =
catAttrs "name" (filter (a: a.primary) (attrValues cfg.accounts));
in {
assertion = length primaries == 1;
message = "Must have exactly one primary mail account but found "
+ toString (length primaries) + optionalString (length primaries > 1)
(", namely " + concatStringsSep ", " primaries);
})
];
};
}

View File

@ -11,7 +11,7 @@ let
};
bg = {
xps9360 = "/home/yorick/wp/thorns__4k__by_kasperja-daqi5g7.jpg fill";
desktop = "/home/yorick/wp/beyond-4k-2560×1440.jpg fill";
desktop = "/home/yorick/wp/leonid5-high.webp fill";
x11carbon = "/home/yorick/wp/lawn_forest_mountains_144578_3840x2400.jpg fill";
};
in {
@ -22,16 +22,21 @@ in {
onChange = "systemctl --user restart waybar";
};
systemd.user.services.waybar.Service.Environment = [
"PATH=${lib.makeBinPath (with pkgs; [ pavucontrol xdg-utils bin.y-cal-widget playerctl bluez gnugrep bash ])}"
"PATH=${lib.makeBinPath (with pkgs; [ pavucontrol xdg-utils bin.y-cal-widget playerctl bluez gnugrep bash systemd chromium ])}"
];
programs.waybar = {
enable = true;
style = ./waybar.css;
systemd.enable = true;
};
programs.mako = {
services.mako = {
enable = true;
defaultTimeout = 60 * 1000; # ms
height = 200;
extraConfig = ''
[mode=do-not-disturb]
invisible=1
'';
};
services.gpg-agent.pinentryFlavor = "gnome3";
wayland.windowManager.sway = {
@ -61,8 +66,8 @@ in {
"exec --no-startup-id bash /home/yorick/dotfiles/bin/invert.sh";
#"${mod}+ctrl+l" = "exec --no-startup-id loginctl lock-session";
"${mod}+ctrl+l" =
"exec --no-startup-id \"playerctl -a pause; (bluetoothctl disconnect 94:DB:56:79:7D:86 &) && sleep 1s && pkill -USR1 swayidle\"";
"${mod}+Return" = "exec alacritty";
"exec --no-startup-id \"playerctl -a pause; (bluetoothctl disconnect 88:C9:E8:AD:73:E8 &) && sleep 1s && pkill -USR1 swayidle\"";
"${mod}+Return" = "exec alacritty msg create-window || alacritty";
"${mod}+Escape" = "workspace back_and_forth";
"${mod}+0" = "workspace 10";
"${mod}+Shift+0" = "move container to workspace 10";
@ -84,7 +89,7 @@ in {
"XF86AudioMute" = exec alsa-utils "amixer set Master toggle";
"XF86AudioPause" = "exec playerctl pause";
"XF86AudioPlay" = "exec playerctl play";
"${mod}+Shift+s" = exec bin.screenshot_public "screenshot_public >> ~/screenshot-public.log";
"${mod}+Shift+s" = exec bin.screenshot_public "screenshot_public";
"Print" = exec bin.screenshot_public "screenshot_public";
"${mod}+Shift+t" =
"exec --no-startup-id /home/yorick/dotfiles/bin/toggle_solarized.sh";
@ -109,16 +114,21 @@ in {
output."Sharp Corporation 0x144A Unknown".bg = bg.xps9360;
# desk
output."HYC CO., LTD. DUAL-DVI Unknown" = {
position = "0 0";
bg = bg.desktop;
max_render_time = "4";
};
output."HYC CO., LTD. Unknown" = {
position = "0 0";
bg = bg.desktop;
max_render_time = "4";
};
output."HYC CO., LTD. " = {
output."HYC CO., LTD. DUAL-DVI" = {
position = "0 0";
bg = bg.desktop;
};
output."BenQ Corporation BenQ GW2765 36H03689019" = {
output."BNQ BenQ GW2765 36H03689019" = {
position = "2560 0";
bg = bg.desktop;
max_render_time = "4";
@ -126,7 +136,7 @@ in {
# x11 carbon
input."2:10:TPPS/2_Elan_TrackPoint".accel_profile = "flat";
output."California Institute of Technology 0x1403 Unknown".bg = bg.x11carbon;
output."California Institute of Technology 0x1403".bg = bg.x11carbon;
input."1739:30383:DLL075B:01_06CB:76AF_Touchpad" = {
natural_scroll = "enabled";
tap = "enabled";
@ -146,6 +156,10 @@ in {
criteria.app_id = "emacs";
command = "opacity 0.95";
}
{
criteria.title = "Firefox Sharing Indicator";
command = "floating enable";
}
];
startup = [
{ command = "mako"; }
@ -155,20 +169,15 @@ in {
}
];
};
systemdIntegration = true;
systemd.enable = true;
# fix pinentry-gnome3
extraConfig = ''
include /etc/sway/config.d/*
'';
};
programs.firefox = {
enable = true;
package = pkgs.wrapFirefox pkgs.firefox-bin.unwrapped {
forceWayland = true;
applicationName = "firefox";
};
};
programs.firefox.enable = true;
home.sessionVariables = {
MOZ_USE_XINPUT2 = "1";
MOZ_ENABLE_WAYLAND = "1";
@ -181,6 +190,21 @@ in {
XCURSOR_THEME = "Adwaita";
XCURSOR_PATH = "${pkgs.gnome.adwaita-icon-theme}/share/icons";
XDG_CURRENT_DESKTOP = "sway";
#NIXOS_OZONE_WL = "1";
};
systemd.user.services.wayland-push-to-talk-fix = let
kbd = "/dev/input/by-id/usb-Kinesis_Advantage2_Keyboard_314159265359-if01-event-kbd";
in {
Unit.ConditionPathExists = kbd;
Install.WantedBy = [ "graphical-session.target" ];
Unit = {
PartOf = [ "graphical-session.target" ];
After = [ "graphical-session.target" ];
};
Service = {
ExecStart = "${pkgs.wayland-push-to-talk-fix}/bin/wayland-push-to-talk-fix ${kbd} -k KEY_LEFTALT -n Alt_L";
Restart = "on-failure";
};
};
# todo: use home-manager unit
systemd.user.services.gmi = {
@ -218,6 +242,15 @@ in {
# '';
# };
# };
services.kdeconnect = {
enable = true;
indicator = true;
};
programs.obs-studio = {
enable = true;
plugins = [ pkgs.obs-studio-plugins.wlrobs ];
};
# systemd.user.services.kdeconnect-indicator.Unit.After = [ "waybar.service" ];
home.packages = with pkgs; [
gtk-engine-murrine
hicolor-icon-theme
@ -231,10 +264,8 @@ in {
libwebp
gebaar-libinput
grim
element-desktop-wayland
element-desktop
libreoffice
obs-studio
obs-wlrobs
fixed_slack
slurp
sway-contrib.grimshot
@ -247,5 +278,8 @@ in {
wldash
# zoom-us
bin.y-cal-widget
obsidian
#xwaylandvideobridge
];
}

View File

@ -1,24 +1,24 @@
{ lib, config, options, pkgs, ... }: let
epkgs = pkgs.emacsPackagesFor pkgs.emacsPgtkNativeComp;
epkgs = pkgs.emacsPackagesFor pkgs.emacs-unstable-pgtk;
in {
programs.emacs = {
enable = true;
package = pkgs.emacsPgtkNativeComp;
package = pkgs.emacs29-pgtk;
extraConfig = ''
(setq copilot-node-executable "${pkgs.nodejs-slim-16_x}/bin/node")
(setq copilot-node-executable "${pkgs.nodejs-slim-18_x}/bin/node")
(setq lsp-nix-server-path "${pkgs.nil}/bin/nil")
'';
overrides = final: prev: {
copilot = final.melpaBuild rec {
pname = "copilot";
version = "20220916.1";
commit = "f316299bab75a380ee04e7ca49c79baf0fb296d6";
version = "20231220";
commit = "d4fa14cea818e041b4a536c5052cf6d28c7223d7";
src = pkgs.fetchFromGitHub {
owner = "zerolfx";
repo = "copilot.el";
rev = commit;
sha256 = "sha256-n4bXnlNfCC00jVeODUlqZNThf7i8rj69zzMMfXBy8tk=";
hash = "sha256-Tzs0Dawqa+OD0RSsf66ORbH6MdBp7BMXX7z+5UuNwq4=";
};
packageRequires = with final; [ dash editorconfig s ];
@ -35,9 +35,11 @@ in {
};
extraPackages = p:
(with p; [
treesit-grammars.with-all-grammars
all-the-icons
avy
company
company-box
counsel
counsel-projectile
copilot
@ -62,6 +64,7 @@ in {
lua-mode
linum-relative
lsp-haskell
lsp-pyright
lsp-ivy
lsp-mode
lsp-ui

56
home-manager/email.nix Normal file
View File

@ -0,0 +1,56 @@
{ lib, pkgs, options, config, ... }:
{
imports = [./accounts-email.nix];
disabledModules = ["accounts/email.nix"];
config = {
programs.neomutt = {
enable = true;
settings = {
auto_tag = "yes";
crypt_reply_sign = "yes";
delete = "ask-yes";
imap_passive = "no";
mail_check = "60";
sort_aux = "reverse-last-date-received";
sort_browser = "date";
edit_headers = "yes";
implicit_autoview = "no";
};
binds = [
{ map = [ "index" ]; key = "G"; action = "imap-fetch-mail"; }
{ map = [ "pager" ]; key = "<up>"; action = "previous-line"; }
{ map = [ "pager" ]; key = "<down>"; action = "next-line"; }
];
extraConfig = "source ${./mutt-colors}";
};
xdg.configFile."neomutt/neomuttrc".text = lib.mkBefore ''
set imap_user = "yorick@yori.cc"
set imap_pass = "`pass sysadmin/yori.ccMail | head -n1`"
'';
accounts.email.accounts = {
yori-cc = rec {
primary = true;
userName = "yorick@yori.cc";
passwordCommand = "pass sysadmin/yori.ccMail | head -n1";
realName = "Yorick van Pelt";
address = "Yorick van Pelt <yorick@yorickvanpelt.nl>";
imap.host = "pennyworth.yori.cc";
smtp.host = "pennyworth.yori.cc";
gpg.key = "6EFD1053ADB6ABF50DF64792A36E70F9DC014A15";
neomutt.enable = true;
neomutt.extraMailboxes = [ "Archive" "Sent" "Spam" "Trash" ];
neomutt.extraConfig = ''
set pgp_sign_as = "${gpg.key}"
'';
maildir.absPath = "imaps://pennyworth.yori.cc";
folders = {
inbox = "INBOX";
trash = "Archive";
};
};
};
};
}

View File

@ -5,14 +5,11 @@ let
TF_SHELL = shell;
HOME = "/build";
} "${pkgs.thefuck}/bin/thefuck -a > $out";
headphones = "88:C9:E8:AD:73:E8";
in {
imports = [ ./desktop.nix ./emacs.nix ./lumi.nix ];
imports = [ ./desktop.nix ./emacs.nix ./lumi.nix ./email.nix ];
programs = {
nix-index.enable = true;
starship = {
enable = true;
settings.nix_shell.disabled = false;
};
# todo: .aws/config default region
gh = {
enable = true;
@ -28,14 +25,16 @@ in {
userEmail = "yorick@yorickvanpelt.nl";
signing.key = "A36E70F9DC014A15";
signing.signByDefault = true;
includes = [{
condition = "gitdir:~/tweag";
contents.user.email = "yorick.vanpelt@tweag.io";
}];
extraConfig.merge.conflictStyle = "diff3";
extraConfig.help.autocorrect = 5;
extraConfig.push.default = "simple";
extraConfig.pull.ff = "only";
extraConfig.hub.protocol = "ssh";
ignores = [
"/.envrc"
"/.cache"
"/.direnv"
];
aliases = {
lg =
"log --graph --pretty=format:'%Cred%h%Creset -%C(yellow)%d%Creset %s %Cgreen(%cr) %C(bold blue)<%an>%Creset' --abbrev-commit --date=relative";
@ -78,6 +77,7 @@ in {
frumar.hostname = "frumar.local";
pennyworth.hostname = "pennyworth.yori.cc";
smithers.hostname = "10.209.0.8";
replicate.hostname = "216.153.63.208";
# "192.168.178.*" = {
# only if wired
# extraOptions.Compression = "no";
@ -92,21 +92,24 @@ in {
enable = true;
shellAliases = {
l = "ls";
ls = "exa";
ls = "eza";
nr = ''nix repl --file "/home/yorick/dotfiles/repl.nix"'';
"n." = "nix repl --file .";
nsd = "nix show-derivation";
nb = "nix build";
nl = "nix log";
g = "git";
bc = "bluetoothctl connect 94:DB:56:79:7D:86";
bd = "bluetoothctl disconnect 94:DB:56:79:7D:86";
bc = "bluetoothctl connect ${headphones}";
bd = "bluetoothctl disconnect ${headphones}";
};
interactiveShellInit = ''
set fish_greeting
source ${thefuck-alias "fish"}
source ~/dotfiles/nr.fish
'';
plugins = [
{ inherit (pkgs.fishPlugins.tide) name src; }
];
};
bash = {
enable = true;
@ -167,6 +170,7 @@ in {
borgbackup
bup
# catdoc
trurl
expect
fzf
fx
@ -176,6 +180,7 @@ in {
imagemagick
iodine
jo
jless
jq
lnav
magic-wormhole
@ -209,6 +214,7 @@ in {
python3
silver-searcher
sqlite
noulith
## nix
nix-tree
@ -219,7 +225,7 @@ in {
nix-du
nix-top
nix-diff
cachix
#cachix
cached-nix-shell
## js
@ -235,7 +241,7 @@ in {
## misc
asciinema
cargo
exa
eza
linuxPackages.perf
ltrace
lz4json
@ -244,6 +250,7 @@ in {
unzip
vim
xdg-utils
countfftabs
#wlrctl
## coins
@ -254,20 +261,22 @@ in {
calibre
chromium
discord
wayland-push-to-talk-fix
fanficfare
feh
gimp
gopass
hledger
neomutt
spotify
tdesktop
signal-desktop
virt-manager
wireshark
yubioath-desktop
notion-desktop
#yubioath-flutter
## games
minecraft
prismlauncher
steam
# minecraft
# nottetris2
@ -275,6 +284,16 @@ in {
# wine
# winetricks
# work
timesync
r8-cog
mutagen
zoom-us
llm
# admin
nsc
natscli
]);
home.file.".gnupg/gpg.conf".text = ''
@ -284,10 +303,6 @@ in {
keyserver hkps://keys.openpgp.org
#keyserver-options auto-key-retrieve
'';
home.file.".mutt" = {
source = ../mutt/.mutt;
recursive = true;
};
home.sessionVariables = {
FLAKE_CONFIG_URI = "/home/yorick/dotfiles#homeConfigurations.${pkgs.stdenv.system}.activationPackage";
};

View File

@ -29,7 +29,7 @@ window#waybar {
border-bottom: 3px solid white;
}
#clock, #battery, #cpu, #memory, #network, #disk, #pulseaudio, #custom-spotify, #tray, #mode, #custom-cal {
#clock, #battery, #cpu, #memory, #network, #disk, #pulseaudio, #custom-spotify, #tray, #mode, #custom-cal, #custom-marvin {
padding: 0 10px;
margin: 0 5px;
}
@ -104,7 +104,15 @@ window#waybar {
background: #4285f4;
}
#custom-cal.user-1 {
background: #f67755;
background: #33b679;
}
#custom-cal.user-2 {
background: #9e69af;
}
#custom-marvin {
background: #5ec0bc;
color: white;
}
#tray {

View File

@ -2,7 +2,7 @@ layer = "top"
height = 26
modules-left = [ "sway/workspaces", "sway/mode", "custom/spotify" ]
modules-center = [ "sway/window" ]
modules-right = [ "custom/cal", "pulseaudio", "network", "disk", "battery", "clock", "tray" ]
modules-right = [ "custom/marvin", "custom/cal", "pulseaudio", "network", "disk", "battery", "clock", "tray" ]
["sway/workspaces"]
all-outputs = false
@ -82,3 +82,9 @@ escape = true
max-length = 40
on-click = "playerctl play-pause"
exec = "$HOME/dotfiles/bin/spotify_meta.sh 2> /dev/null"
["custom/marvin"]
format = "{}"
escape = true
max-length = 40
exec = "$HOME/dotfiles/bin/marvin-sub.sh"

View File

@ -1,2 +0,0 @@
msg_cache/
hcache

View File

@ -1,9 +0,0 @@
set imap_user=yorick@yori.cc
set imap_pass = "`pass sysadmin/yori.ccMail | head -n1`"
set folder = "imaps://yorick@yori.cc@pennyworth.yori.cc/"
set spoolfile = "=INBOX"
set realname = "Yorick van Pelt"
set from = "Yorick van Pelt <yorick@yorickvanpelt.nl>"
set smtp_url = "smtp://yorick@yori.cc@pennyworth.yori.cc:587/"
set smtp_pass = "$imap_pass"

View File

@ -1,88 +0,0 @@
# -*-muttrc-*-
#
# Command formats for gpg.
#
# This version uses gpg-2comp from
# http://70t.de/download/gpg-2comp.tar.gz
#
# $Id$
#
# %p The empty string when no passphrase is needed,
# the string "PGPPASSFD=0" if one is needed.
#
# This is mostly used in conditional % sequences.
#
# %f Most PGP commands operate on a single file or a file
# containing a message. %f expands to this file's name.
#
# %s When verifying signatures, there is another temporary file
# containing the detached signature. %s expands to this
# file's name.
#
# %a In "signing" contexts, this expands to the value of the
# configuration variable $pgp_sign_as. You probably need to
# use this within a conditional % sequence.
#
# %r In many contexts, mutt passes key IDs to pgp. %r expands to
# a list of key IDs.
# Note that we explicitly set the comment armor header since GnuPG, when used
# in some localiaztion environments, generates 8bit data in that header, thereby
# breaking PGP/MIME.
# decode application/pgp
set pgp_decode_command="gpg --status-fd=2 %?p?--passphrase-fd 0? --no-verbose --quiet --batch --output - %f"
# verify a pgp/mime signature
set pgp_verify_command="gpg --status-fd=2 --no-verbose --quiet --batch --output - --verify %s %f"
# decrypt a pgp/mime attachment
set pgp_decrypt_command="gpg --status-fd=2 %?p?--passphrase-fd 0? --no-verbose --quiet --batch --output - %f"
# create a pgp/mime signed attachment
# set pgp_sign_command="gpg-2comp --comment '' --no-verbose --batch --output - %?p?--passphrase-fd 0? --armor --detach-sign --textmode %?a?-u %a? %f"
set pgp_sign_command="gpg --no-verbose --batch --quiet --output - %?p?--passphrase-fd 0? --armor --detach-sign --textmode %?a?-u %a? %f"
# create a application/pgp signed (old-style) message
# set pgp_clearsign_command="gpg-2comp --comment '' --no-verbose --batch --output - %?p?--passphrase-fd 0? --armor --textmode --clearsign %?a?-u %a? %f"
set pgp_clearsign_command="gpg --no-verbose --batch --quiet --output - %?p?--passphrase-fd 0? --armor --textmode --clearsign %?a?-u %a? %f"
# create a pgp/mime encrypted attachment
# set pgp_encrypt_only_command="pgpewrap gpg-2comp -v --batch --output - --encrypt --textmode --armor --always-trust -- -r %r -- %f"
set pgp_encrypt_only_command="pgpewrap gpg --batch --quiet --no-verbose --output - --encrypt --textmode --armor --always-trust -- -r %r -- %f"
# create a pgp/mime encrypted and signed attachment
# set pgp_encrypt_sign_command="pgpewrap gpg-2comp %?p?--passphrase-fd 0? -v --batch --output - --encrypt --sign %?a?-u %a? --armor --always-trust -- -r %r -- %f"
set pgp_encrypt_sign_command="pgpewrap gpg %?p?--passphrase-fd 0? --batch --quiet --no-verbose --textmode --output - --encrypt --sign %?a?-u %a? --armor --always-trust -- -r %r -- %f"
# import a key into the public key ring
set pgp_import_command="gpg --no-verbose --import %f"
# export a key from the public key ring
set pgp_export_command="gpg --no-verbose --export --armor %r"
# verify a key
set pgp_verify_key_command="gpg --verbose --batch --fingerprint --check-sigs %r"
# read in the public key ring
set pgp_list_pubring_command="gpg --no-verbose --batch --quiet --with-colons --with-fingerprint --with-fingerprint --list-keys %r"
# read in the secret key ring
set pgp_list_secring_command="gpg --no-verbose --batch --quiet --with-colons --with-fingerprint --with-fingerprint --list-secret-keys %r"
# fetch keys
# set pgp_getkeys_command="pkspxycwrap %r"
# pattern for good signature - may need to be adapted to locale!
# set pgp_good_sign="^gpgv?: Good signature from "
# OK, here's a version which uses gnupg's message catalog:
# set pgp_good_sign="`gettext -d gnupg -s 'Good signature from "' | tr -d '"'`"
# This version uses --status-fd messages
set pgp_good_sign="^\\[GNUPG:\\] GOODSIG"
# pattern to verify a decryption occurred
set pgp_decryption_okay="^\\[GNUPG:\\] DECRYPTION_OKAY"

View File

@ -1,4 +0,0 @@
set record="=Sent"
set postponed="=Drafts"
set trash="=Archive"
mailboxes =INBOX =Archive =Sent =Spam =Trash

View File

@ -1,4 +0,0 @@
text/html; w3m -I %{charset} -T text/html; copiousoutput;
application/pdf; pdftotext -layout -l 10 -nopgbrk /dev/stdin -; copiousoutput
content/pdf; pdftotext -layout -l 10 -nopgbrk /dev/stdin -; copiousoutput

View File

@ -1,38 +0,0 @@
source ~/.mutt/creds
source ~/.mutt/colors
source ~/.mutt/gpg
source ~/.mutt/mailboxes
set edit_headers
set auto_tag
bind pager <up> previous-line
bind pager <down> next-line
set smart_wrap
set sleep_time = 0 # gotta go faster
set imap_servernoise
unset imap_passive
set mail_check = 60
set header_cache = ~/.mutt/hcache
set message_cachedir = ~/.mutt/msg_cache
set net_inc = 5
set sort = threads
set sort_browser = date
set sort_aux = reverse-last-date-received
set sidebar_width= 10
set pgp_verify_sig
set pgp_replysign
set pgp_sign_as = DC014A15
ifdef ENCRYPT_SELF set pgp_encrypt_self
set pgp_use_gpg_agent
bind index G imap-fetch-mail
auto_view text/html # view html automatically
alternative_order text/plain text/enriched text/html # save html for last
set mailcap_path=~/.mutt/mailcap

View File

@ -1,25 +1,42 @@
My nixos configurations.
This directory contains Nix code to deploy all of my machines. The main way to use this is via `ydeployer`.
Systems
=======
[blackadder](https://en.wikipedia.org/wiki/Edmund_Blackadder#Edmund_Blackadder_Esq._(Regency_Britain))
--------
Desktop [workstation](./roles/workstation.nix).
ryzen 9 3950x (RAM: 64GB, storage: 1TB ssd, 16 cores + hyperthreading)
There is a [list of components](https://tweakers.net/gallery/468325/inventaris/?inv_id=2583112) on tweakers.
- Main desktop with two 2560x1440 27" screens.
- It has a camera (sony alpha 6000) mounted on top of the left screen using a [smallrig super clamp](https://www.amazon.nl/-/en/gp/product/B08B63WXWN/).
- It has a Tobii Eye Tracker 4c attached to the left screen.
[frumar](https://en.wikipedia.org/wiki/Frumar)
--------
Physical [server](./roles/server.nix). Mostly used for files. (storage: 30 TB hdd + 256GB ssd, RAM: 16GB, 2 cores ht)
Physical NAS [server](./roles/homeserver.nix). Mostly used for files. (storage: 30 TB hdd + 256GB ssd, RAM: 64GB, 4 cpu cores). As of 2022-04-09, there is 12TB usable storage remaining.
There is a [list of components](https://tweakers.net/gallery/468325/inventaris/?inv_id=459811) on tweakers.
- prometheus
- grafana
- rabbitmq
- torrents
- torrent client
- plex
- home-assistant
- unifi controller
[pennyworth](https://en.wikipedia.org/wiki/Alfred_Pennyworth)
----------
[Server](./roles/server.nix).
Hetzner cloud VPS (Storage: 20GB, RAM: 2GB, 1 core)
Hetzner [CX11](https://www.hetzner.com/cloud) cloud VPS (Storage: 20GB, RAM: 2GB, 1 core)
- [website](./services/website.nix)
- [email](./services/mail.nix)
@ -31,25 +48,14 @@ Hetzner cloud VPS (Storage: 20GB, RAM: 2GB, 1 core)
--------
[workstation](./roles/workstation.nix).
dell xps 13 (RAM: 16GB, storage: 512GB ssd, 2 cores ht)
dell xps 13 (RAM: 16GB, storage: 512GB ssd, 2 cores + hyperthreading)
[blackadder](https://en.wikipedia.org/wiki/Edmund_Blackadder#Edmund_Blackadder_Esq._(Regency_Britain))
smithers
--------
[workstation](./roles/workstation.nix).
https://tweakers.net/productcollectie/wijzig/2583112/
ryzen 9 (RAM: 64GB, storage: 1TB ssd, 16 cores ht)
Maintenance
===========
Main laptop.
Generating tor keys:
thinkpad x1 carbon (gen 9) (RAM: 24GB, storage: 256GB ssd, 4 cores + hyperthreading)
```
$(nix-build packages/shallot.nix --no-out-link)/bin/shallot -f tmp ^PATTERN
head -n3 tmp
tail -n +4 tmp > keys/ssh.HOSTNAME.key
shred tmp && rm tmp
```

View File

@ -28,12 +28,15 @@
};
fileSystems."/boot" = {
device = "/dev/disk/by-uuid/5D0A-7902";
# device = "/dev/disk/by-uuid/5D0A-7902"; # mp600
device = "/dev/disk/by-uuid/897D-8245"; # 980pro
fsType = "vfat";
};
swapDevices =
[{ device = "/dev/disk/by-uuid/61a23e27-2cd4-4456-bcde-aec68be04239"; }];
swapDevices = [
# { device = "/dev/disk/by-uuid/61a23e27-2cd4-4456-bcde-aec68be04239"; } # mp600
{ device = "/dev/disk/by-uuid/15057589-6483-4e10-9f87-67ed7e314d26"; } # 980pro
];
nix.settings.max-jobs = lib.mkDefault 32;
# High-DPI console

View File

@ -25,10 +25,12 @@
# matchConfig.OriginalName = "*";
# linkConfig.NamePolicy = "mac kernel database onboard slot path";
# };
boot.kernelParams = [
# thunderbolt
"pcie_ports=native"
"pci=assign-busses,hpbussize=0x33,realloc"
];
environment.systemPackages = [ pkgs.openrgb ];
environment.systemPackages = [ pkgs.openrgb pkgs.egl-wayland ];
services.xserver.videoDrivers = [ "modesetting" "nvidia" ];
hardware.nvidia.powerManagement.finegrained = true;
hardware.nvidia.prime.offload.enable = true;
hardware.nvidia.prime = {
nvidiaBusId = "PCI:5:0:0";
amdgpuBusId = "PCI:15:0:0";
};
}

View File

@ -1,3 +1,6 @@
let
sshkeys = import ../../sshkeys.nix;
in
{ config, pkgs, lib, ... }: {
imports = [ ./3950x.nix ../../roles/workstation.nix ];
@ -31,18 +34,41 @@
# lars user
nix.settings.trusted-users = [ "lars" ];
users.users.lars = {
isNormalUser = true;
openssh.authorizedKeys.keys = [
"ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQCbieYUtRGQ4nf4glQvrZDn72doP6W2uw2z9VqFq5sZLROXYa4jW8nwx4h+BiArGs+VPwn6lfsP19PX6yNIk74C/SkO26S1Zvbe7ffNusi6PH2BQIOWeAYKk+eZH+ZOeD8z07uDB7QffwRLwzSaPFg+zfRzsMFoXH/GE9qOQ4lnfk8czTZL7zbZf/yS7mDFztClXFciYsVwgRXNiFpfc+9mOkU0oBWtGo/WGUhB0Hds3a4ylyjjVAcC/l1H2bvc/Q3d6bbn23pUFl2V78Yg1B4b1MT34qbBV6whXAQd7KM9tND2ZhpF2XQ7Spi1QlOac0jup+sE+3bbvcjNqTI05DwJO/dX5F2gSAFkvSY4ZPqSX5ilE/hj4DQuhRgLmQdbVl5IFV9aLYqUvJcCqX9jRFMly4YTFXsFz18rGkxOYGZabcE1usBM2zRVDTtEP6Si5ii76Ocvp8aNFBB2Kf1whg8tziTv3kQEQ9fd2sRtE2J3xveJiwXjUBU2uikSOKe8JP47Tb6PYlv7Ty/6OI51aUQn++R72VNajdBJ1r1osp7leqTJ+sXuLlWLo/a7lDpDmgEI7dbxqmpjLcMce0JzqLKlP1Q2U/nkYy86xkjSTH1rNUI2JAbJx3iTcGy7bq12yfjNfcGAqY4GVXvisK1cpbF0RCjaFExwtmzorljHh6ZHjQ== openpgp:0x60F7D1FD"
"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIOvdQ963wjgWyFMp6djRTqVwZr3/PQ/V+Qm5JTcxRTdY lumi@channelwood"
];
users.users = {
lars = {
isNormalUser = true;
openssh.authorizedKeys.keys = sshkeys.lars;
};
mickey = {
isNormalUser = true;
openssh.authorizedKeys.keys = sshkeys.mickey ++ sshkeys.bram;
packages = with pkgs; [
git cmake gnumake gcc python3 python3.pkgs.pip screen vim r8-cog
];
extraGroups = [ "docker" ];
};
judith = {
isNormalUser = true;
openssh.authorizedKeys.keys = sshkeys.judith;
packages = with pkgs; [ r8-cog ];
# packages = with pkgs; [
# git cmake gnumake gcc python3 python3.pkgs.pip screen vim
# ];
extraGroups = [ "docker" ];
};
};
# docker
virtualisation.docker.enable = true;
virtualisation.docker = {
enable = true;
enableNvidia = true;
storageDriver = "overlay2";
};
users.users.yorick.extraGroups = [ "docker" ];
nix.optimise.automatic = true;
# headphone control
systemd.services.mdrd = {
serviceConfig = {
@ -53,4 +79,18 @@
wantedBy = [ "graphical-session.target" ];
};
services.dbus.packages = [ pkgs.mdrd ];
services.fooocus = {
enable = true;
listen = "0.0.0.0";
};
networking.firewall.allowedTCPPorts = [ config.services.fooocus.port ];
hardware.nvidia.package = config.boot.kernelPackages.nvidiaPackages.mkDriver {
version = "550.54.14";
sha256_64bit = "sha256-jEl/8c/HwxD7h1FJvDD6pP0m0iN7LLps0uiweAFXz+M=";
sha256_aarch64 = "sha256-sProBhYziFwk9rDAR2SbRiSaO7RMrf+/ZYryj4BkLB0=";
openSha256 = "sha256-F+9MWtpIQTF18F2CftCJxQ6WwpA8BVmRGEq3FhHLuYw=";
settingsSha256 = "sha256-m2rNASJp0i0Ez2OuqL+JpgEF0Yd8sYVCyrOoo/ln2a4=";
persistencedSha256 = "sha256-XaPN8jVTjdag9frLPgBtqvO/goB5zxeGzaTU0CdL6C4=";
#patches = config.boot.kernelPackages.nvidiaPackages.latest.patches;
};
}

View File

@ -0,0 +1,56 @@
{ config, pkgs, lib, inputs, ... }: {
imports = [
inputs.attic.nixosModules.atticd
];
age.secrets.attic.file = ../../../secrets/attic.env.age;
services.nginx.virtualHosts."cache.yori.cc" = {
onlySSL = true;
useACMEHost = "wildcard.yori.cc";
locations."/" = {
proxyPass = "http://[::]:8091";
recommendedProxySettings = true;
};
extraConfig = ''
client_max_body_size 8000M;
proxy_request_buffering off;
proxy_read_timeout 600s;
'';
};
services.atticd = {
enable = true;
credentialsFile = config.age.secrets.attic.path;
settings = {
storage = {
type = "local";
path = "/attic";
};
database.url = "postgresql:///atticd";
listen = "[::]:8091";
chunking = {
nar-size-threshold = 128 * 1024;
min-size = 32 * 1024;
avg-size = 128 * 1024;
max-size = 512 * 1024;
};
};
};
systemd.tmpfiles.rules = with config.services.atticd; [
"d /attic 0770 ${user} ${group}"
];
users.users.${config.services.atticd.user} = {
isSystemUser = true;
createHome = false;
group = config.services.atticd.group;
};
users.groups.${config.services.atticd.group} = {};
services.postgresql = {
enable = true;
package = pkgs.postgresql_15;
ensureDatabases = [ "atticd" ];
ensureUsers = [ {
name = "atticd";
ensureDBOwnership = true;
} ];
};
}

View File

@ -3,6 +3,10 @@
./fractal.nix
../../roles/server.nix
../../roles/homeserver.nix
./paperless.nix
./media.nix
./home-automation.nix
./cache.nix
];
system.stateVersion = "15.09";
@ -13,44 +17,87 @@
};
}) ];
security.y-selfsigned.enable = true;
services.nginx = let
cert = config.services.acme-sh.certs.wildcard-yori-cc;
sslCertificate = cert.certPath;
sslCertificateKey = cert.keyPath;
sslForward = proxyPass: extra: lib.mkMerge [ {
onlySSL = true;
useACMEHost = "wildcard.yori.cc";
locations."/" = {
inherit proxyPass;
proxyWebsockets = true;
};
} extra ];
in {
enable = true;
recommendedOptimisation = true;
recommendedTlsSettings = true;
recommendedProxySettings = true;
recommendedGzipSettings = true;
virtualHosts."unifi.yori.cc" = {
onlySSL = true;
inherit sslCertificate sslCertificateKey;
locations."/" = {
proxyPass = "https://[::1]:8443";
proxyWebsockets = true;
extraConfig = ''
virtualHosts = {
"unifi.yori.cc" = sslForward "https://[::1]:8443" {
locations."/".extraConfig = ''
proxy_ssl_verify off;
proxy_ssl_session_reuse on;
'';
};
};
virtualHosts."frumar.yori.cc" = {
enableACME = lib.mkForce false;
forceSSL = lib.mkForce false;
default = true;
"grafana.yori.cc" = sslForward "http://127.0.0.1:3000" {};
"prometheus.yori.cc" = sslForward "http://127.0.0.1:9090" {
# only over VPN
listen = [ { addr = "10.209.0.3"; port = 443; ssl = true; } ];
};
"plex.yori.cc" = sslForward "http://127.0.0.1:32400" {
extraConfig = ''
gzip on;
gzip_vary on;
gzip_min_length 1000;
gzip_proxied any;
gzip_types text/plain text/css text/xml application/xml text/javascript application/x-javascript image/svg+xml;
proxy_http_version 1.1;
proxy_buffering off;
'';
};
"fooocus.yori.cc" = sslForward "http://192.168.2.135:7860" {};
"priv.yori.cc" = let
oauth2Block = ''
auth_request /oauth2/auth;
error_page 401 = /oauth2/sign_in;
# pass information via X-User and X-Email headers to backend,
# requires running with --set-xauthrequest flag
auth_request_set $user $upstream_http_x_auth_request_user;
auth_request_set $email $upstream_http_x_auth_request_email;
proxy_set_header X-User $user;
proxy_set_header X-Email $email;
# if you enabled --cookie-refresh, this is needed for it to work with auth_request
auth_request_set $auth_cookie $upstream_http_set_cookie;
add_header Set-Cookie $auth_cookie;
'';
proxyOauth2 = proxyPass: {
inherit proxyPass;
extraConfig = oauth2Block;
};
in {
onlySSL = true;
useACMEHost = "wildcard.yori.cc";
# TODO remove dashy
locations."/".proxyPass = "http://127.0.0.1:4000";
locations."/sonarr" = proxyOauth2 "http://127.0.0.1:8989";
locations."/radarr" = proxyOauth2 "http://127.0.0.1:7878";
locations."/marvin-tracker/" = {
proxyPass = "http://[::1]:4001/";
# handles auth using arg
};
locations."/paperless/" = proxyOauth2 "http://127.0.0.1:${toString config.services.paperless.port}/";
locations."/media/" = {
root = "/var/mediashare";
};
};
"frumar.yori.cc" = {
enableACME = lib.mkForce false;
inherit (config.security.y-selfsigned) sslCertificate sslCertificateKey;
};
};
};
systemd.services.nginx.serviceConfig.BindReadOnlyPaths = [ "/data/plexmedia/ca" "/var/mediashare" ];
boot.supportedFilesystems = [ "zfs" ];
services.yorick.torrent-vpn = {
enable = true;
name = "mullvad-nl4";
namespace = "torrent";
};
services.plex = {
enable = true;
openFirewall = true;
};
services.iperf3 = {
enable = true;
openFirewall = true;
@ -59,6 +106,7 @@
enable = true;
openFirewall = true;
jrePackage = pkgs.jre8_headless;
unifiPackage = pkgs.unifiStable;
};
services.victoriametrics = {
enable = true;
@ -69,150 +117,56 @@
extraFlags = [ "--web.enable-admin-api" ];
# victoriametrics
remoteWrite = [{ url = "http://127.0.0.1:8428/api/v1/write"; }];
scrapeConfigs = [
# {
# job_name = "smartmeter";
# # prometheus doesn't support mdns :thinking_face:
# static_configs = [{ targets = [ "192.168.178.30" ]; }];
# scrape_interval = "10s";
# }
{
job_name = "node";
static_configs = [{ targets = [ "localhost:9100" ]; }];
# } {
# job_name = "unifi";
# static_configs = [ { targets = [ "localhost:9130" ]; } ];
}
# {
# job_name = "thermometer";
# static_configs = [{ targets = [ "192.168.178.21:8000" ]; }];
# }
# {
# job_name = "esphome";
# static_configs = [{ targets = [ "192.168.178.77" ]; }];
# }
];
scrapeConfigs = [{
job_name = "node";
static_configs = [{ targets = [ "localhost:9100" ]; }];
}];
exporters.node.enable = true;
# exporters.unifi = {
# enable = true;
# unifiAddress = "https://localhost:8443";
# unifiInsecure = true;
# unifiUsername = "ReadOnlyUser";
# unifiPassword = "ReadOnlyPassword";
# };
};
services.yorick.paperless = {
enable = true;
openFirewall = true;
scanner_ip = "192.168.2.49";
};
boot.zfs.requestEncryptionCredentials = false;
networking.firewall.interfaces.wg-y.allowedTCPPorts = [ 3000 9090 8443 ];
networking.firewall.allowedTCPPorts = [ 1883 5357 443 ];
networking.firewall.allowedUDPPorts = [ 1883 3702 ];
services.rabbitmq = {
enable = true;
plugins = [ "rabbitmq_mqtt" "rabbitmq_management" ];
networking.firewall = {
interfaces.wg-y.allowedTCPPorts = [ 3000 9090 ]; # grafana and prometheus via pennyworth
# mqtt, nats
allowedTCPPorts = [ 1883 4222 ];
# mqtt
allowedUDPPorts = [ 1883 ];
};
services.grafana = {
enable = true;
addr = "0.0.0.0";
domain = "grafana.yori.cc";
rootUrl = "https://grafana.yori.cc/";
extraOptions = {
AUTH_BASIC_ENABLED = "false";
AUTH_DISABLE_LOGIN_FORM = "true";
AUTH_GOOGLE_ENABLED = "true";
AUTH_GOOGLE_ALLOW_SIGN_UP = "false";
};
};
services.zigbee2mqtt = {
enable = true;
settings.availability = true;
settings.device_options = {
retain = true;
legacy = false;
};
settings.serial.port = "/dev/ttyUSB0";
};
services.home-assistant = {
enable = true;
openFirewall = true;
extraComponents = [
"default_config"
"androidtv"
"esphome"
"met"
"unifi" "yeelight" "plex" "frontend"
"automation" "device_automation"
];
config = {
media_player = [
{
platform = "androidtv";
host = "192.168.2.181";
name = "shield";
device_class = "androidtv";
}
];
mobile_app = {};
default_config = {};
system_log = {};
"map" = {};
frontend.themes = "!include_dir_merge_named themes";
automation = "!include automations.yaml";
homeassistant = {
name = "Home";
latitude = "51.84";
longitude = "5.85";
elevation = "0";
unit_system = "metric";
time_zone = "Europe/Amsterdam";
settings = {
server.http_addr = "0.0.0.0";
server.domain = "grafana.yori.cc";
server.root_url = "https://grafana.yori.cc/";
"auth.basic".enabled = false;
"auth.google" = {
enabled = true;
allow_sign_up = false;
};
auth.disable_login_form = true;
};
};
age.secrets = {
grafana.file = ../../../secrets/grafana.env.age;
transip-key = {
acme-transip-key = {
file = ../../../secrets/transip-key.age;
mode = "770";
owner = "nginx";
group = "nginx";
group = "acme";
};
frumar-mail-pass.file = ../../../secrets/frumar-mail-pass.age;
grafana.file = ../../../secrets/grafana.env.age;
oauth2-proxy.file = ../../../secrets/oauth2-proxy.age;
zigbee2mqtt.file = ../../../secrets/zigbee2mqtt.env.age;
marvin-tracker.file = ../../../secrets/marvin-tracker.env.age;
};
systemd.services.grafana.serviceConfig.EnvironmentFile = config.age.secrets.grafana.path;
services.zfs = {
trim.enable = false; # no ssd's
autoScrub = {
enable = true;
interval = "*-*-01 02:00:00"; # monthly + 2 hours
};
};
services.samba = {
enable = false;
openFirewall = false;
shares.public = {
path = "/data/plexmedia";
browseable = "yes";
"guest ok" = "yes";
"hosts allow" = "192.168.178.0/255.255.255.0";
"writeable" = "yes";
"force user" = "nobody";
"force directory mode" = "2777";
};
};
services.samba-wsdd = {
systemd.services.zigbee2mqtt.serviceConfig.EnvironmentFile = config.age.secrets.zigbee2mqtt.path;
services.zfs.autoScrub = {
enable = true;
interface = "eno1";
hostname = "NAS";
};
services.sonarr = {
enable = true;
group = "plex";
user = "plex";
openFirewall = true;
};
services.radarr = {
enable = true;
group = "plex";
user = "plex";
openFirewall = true;
interval = "*-*-01 02:00:00"; # monthly + 2 hours
};
services.znapzend = {
enable = true;
@ -222,14 +176,24 @@
sendRaw = true;
};
zetup = {
"frumar-new" = {
plan = "1w=>6h,1m=>1w,1y=>1m,2y=>6m,50y=>1y";
};
"frumar-new/plexmedia" = {
plan = "1w=>6h,1m=>1w,1y=>1m,2y=>6m,50y=>1y";
};
"ssdpool/root" = {
plan = "2d=>1d";
};
"ssdpool/root/var" = {
plan = "1w=>1d";
destinations.frumar-new = {
dataset = "frumar-new/backup/ssdpool-root-var";
plan = "1w=>1d,1m=>1w,1y=>1m,10y=>6m,50y=>1y";
};
};
};
};
users.users.plex.packages = with pkgs; [
ffmpeg
];
users.users.yorick.packages = with pkgs; [
borgbackup
bup
@ -238,19 +202,96 @@
magic-wormhole
python3
ranger
pyroscope
rtorrent
jq
unzip
];
services.acme-sh.certs.wildcard-yori-cc = {
mainDomain = "*.yori.cc";
dns = "dns_transip";
production = true;
postRun = "systemctl reload nginx || true";
inherit (config.services.nginx) user group;
security.acme.certs."wildcard.yori.cc" = {
domain = "*.yori.cc";
dnsProvider = "transip";
reloadServices = [ "nginx.service" ];
};
systemd.services.acme-sh-wildcard-yori-cc.environment = {
TRANSIP_Username = "yorickvp";
TRANSIP_Key_File = config.age.secrets.transip-key.path;
users.users.nginx.extraGroups = [ "acme" ];
systemd.services."acme-wildcard.yori.cc".environment = {
TRANSIP_ACCOUNT_NAME = "yorickvp";
TRANSIP_PRIVATE_KEY_PATH = config.age.secrets.acme-transip-key.path;
};
programs.msmtp = {
enable = true;
accounts.default = {
auth = true;
tls = true;
from = "frumar@yori.cc";
host = "pennyworth.yori.cc";
user = "frumar@yori.cc";
passwordeval = "${pkgs.coreutils}/bin/cat ${config.age.secrets.frumar-mail-pass.path}";
};
};
services.smartd = {
enable = true;
notifications.mail = {
enable = true;
sender = "frumar@yori.cc";
recipient = "yorickvanpelt@gmail.com";
};
};
services.zfs.zed.settings = {
ZED_EMAIL_ADDR = [ "yorickvanpelt@gmail.com" ];
ZED_EMAIL_PROG = "/run/wrappers/bin/sendmail";
ZED_EMAIL_OPTS = "@ADDRESS@";
ZED_NOTIFY_INTERVAL_SECS = 3600;
ZED_NOTIFY_VERBOSE = true;
ZED_SCRUB_AFTER_RESILVER = true;
};
services.oauth2_proxy = {
enable = true;
email.addresses = "yorickvanpelt@gmail.com";
redirectURL = "https://priv.yori.cc/oauth2/callback";
reverseProxy = true;
keyFile = config.age.secrets.oauth2-proxy.path;
setXauthrequest = true;
nginx.virtualHosts = [ "priv.yori.cc" ];
extraConfig.whitelist-domain = ["priv.yori.cc"];
};
services.nats = {
enable = true;
jetstream = true;
settings = {
mqtt.port = 1883;
system_account = "SYS";
accounts = {
SYS.users = [ {
user = "admin";
password = "$2y$10$TWoKGC7/VKQRnIK163akm.0JRdhSA00lMMVn8fa1tPyKBgbED0BL2";
} ];
default = {
jetstream = "enabled";
users = [
{
user = "yorick";
password = "$2y$10$EtQh8YX0I91X774PhDxhKOSGSc0IAAvGwZErVKV3z.IfeHTcT1.yy";
}
{
user = "iot";
password = "$2y$10$.JF/0CQ1PYCFPITsSXGj..k5v60rZvDc.LWCIDhZpoc93NyyIa5wS";
allowed_connection_types = [ "MQTT" ];
}
{
user = "zigbee2mqtt";
password = "$2a$11$CC5NVYiTUeoa4A4w94NFMORO/0jhMR60JWgPUgjct8c2vg29wwIGG";
allowed_connection_types = [ "MQTT" ];
}
{
user = "marvin-tracker";
password = "$2a$11$V9G2gT52obCsDOBwibHfMudnibwP/s3NwUjwvtsnlHfkn5kJHOOEe";
allowed_connection_types = [ "MQTT" ];
}
];
};
};
};
};
services.yorick.marvin-tracker = {
enable = true;
secretFile = config.age.secrets.marvin-tracker.path;
};
}

View File

@ -4,23 +4,26 @@
hardware.enableRedistributableFirmware = true;
boot.initrd.availableKernelModules =
[ "xhci_pci" "ehci_pci" "ahci" "usb_storage" "sd_mod" ];
[ "nvme" "xhci_pci" "ehci_pci" "ahci" "usb_storage" "sd_mod" ];
# Use the GRUB 2 boot loader.
boot.loader.grub = {
enable = true;
version = 2;
# Define on which hard drive you want to install Grub.
device = "/dev/disk/by-id/ata-Samsung_SSD_850_EVO_250GB_S21PNXAG441016B";
efiSupport = true;
efiInstallAsRemovable = true;
mirroredBoots = [
{ path = "/boot1"; devices = [ "nodev" ]; }
{ path = "/boot2"; devices = [ "nodev" ]; }
];
};
fileSystems."/" = {
device = "/dev/disk/by-uuid/ba95c638-f243-48ee-ae81-0c70884e7e74";
fsType = "ext4";
options = [ "defaults" "relatime" "discard" ];
};
# fileSystems."/" = {
# device = "/dev/disk/by-uuid/ba95c638-f243-48ee-ae81-0c70884e7e74";
# fsType = "ext4";
# options = [ "defaults" "relatime" "discard" ];
# };
swapDevices = [{ device = "/dev/disk/by-label/ssd-swap"; }];
swapDevices = [{ device = "/dev/disk/by-label/nixos-swap"; }];
fileSystems."/data" = {
device = "frumar-new";
fsType = "zfs";
@ -31,6 +34,63 @@
fsType = "zfs";
};
fileSystems."/boot1" = {
device = "/dev/disk/by-label/EFI1";
fsType = "vfat";
};
fileSystems."/boot2" = {
device = "/dev/disk/by-label/EFI2";
fsType = "vfat";
};
fileSystems."/" = {
device = "ssdpool/root";
fsType = "zfs";
};
fileSystems."/var" = {
device = "ssdpool/root/var";
fsType = "zfs";
};
fileSystems."/torrent" = {
device = "ssdpool/torrent";
fsType = "zfs";
};
nix.settings.max-jobs = 4;
services.avahi.interfaces = [ "enp2s0" ];
services.avahi.allowInterfaces = [ "enp2s0" ];
hardware.rasdaemon.enable = true;
}
## disk layout
# 1x SATA Samsung 850 Evo, 250GB (old ssd)
# - 248GB root ext4
# - 1.9GB swap
# - 0.1GB bios_grub
# 3x SATA WDC WD100EMAZ-00WJTA0, 10.0TB
# - 9.1TiB zfs, frumar-new
# - 8MiB empty
# 1x nvme Corsair Force MP510, 960G
# - 2 GiB "EFI1" boot, ESP
# - 858GB "ssdpart1" zfs, ssdpool
# - 100GB "buf1" empty, future use (metadata device?)
# 1x nvme Samsung Evo 980, 1000G
# - 2GiB "EFI2" boot, ESP
# - 858GB "ssdpart2" zfs, ssdpool
# - 100GB "buf2" empty, future use (metadata device?)
# - 8GiB "swap" swap
# - 31.4GB "scratch" empty, future use
## zfs layout
### frumar-new
# frumar-new: 30T, 20T usable, mountpoint=/data, snapshotted
# frumar-new/backup, mount=none
# frumar-new/backup/blackadder, mount=none
# znapzends from blackadder:rpool/home-enc, encrypted and compressed at-rest there
# frumar-new/plexmedia, mountpoint=/data/plexmedia, snapshotted, different blocksize
### ssdpool
# ssdpool: 858G
# ssdpool/root: compressed
# ssdpool/root/var: compressed, snapshotted
# ssdpool/torrent: not compressed, not snapshottend

View File

@ -0,0 +1,88 @@
{ config, pkgs, lib, ... }: {
services.nginx.virtualHosts."home-assistant.yori.cc" = {
onlySSL = true;
useACMEHost = "wildcard.yori.cc";
locations."/" = {
proxyPass = "http://[::1]:8123";
proxyWebsockets = true;
};
};
services.zigbee2mqtt = {
enable = true;
settings = {
availability = true;
device_options.legacy = false;
serial.port = "/dev/ttyUSB0";
};
};
services.home-assistant = {
enable = true;
openFirewall = true;
extraComponents = [
"default_config"
"androidtv"
"esphome"
"met"
"unifi" "yeelight" "plex" "frontend"
"tado"
"automation" "device_automation"
"homewizard"
"github" "backup"
"mqtt"
"brother"
"spotify"
"yamaha_musiccast" "cast"
"ipp"
"homekit_controller"
"tuya" "ffmpeg"
#"unifiprotect"
];
customComponents = [
(pkgs.buildHomeAssistantComponent rec {
owner = "georgezhao2010";
domain = "midea_ac_lan";
version = "0.3.22";
src = pkgs.fetchFromGitHub {
inherit owner;
repo = domain;
rev = "v${version}";
hash = "sha256-xTnbA4GztHOE61QObEJbzUSdbuSrhbcJ280DUDdM+n4=";
};
})
(pkgs.buildHomeAssistantComponent rec {
owner = "rospogrigio";
domain = "localtuya";
version = "5.2.1";
src = pkgs.fetchFromGitHub {
owner = "rospogrigio";
repo = "localtuya";
rev = "v${version}";
hash = "sha256-hA/1FxH0wfM0jz9VqGCT95rXlrWjxV5oIkSiBf0G0ac=";
};
})
# todo: adaptive-lighting?
];
config = {
mobile_app = {};
default_config = {};
system_log = {};
"map" = {};
frontend.themes = "!include_dir_merge_named themes";
automation = "!include automations.yaml";
homeassistant = {
name = "Home";
latitude = "51.84";
longitude = "5.85";
elevation = "0";
unit_system = "metric";
time_zone = "Europe/Amsterdam";
country = "NL";
};
http = {
use_x_forwarded_for = true;
trusted_proxies = [ "::1" ];
};
};
};
}

View File

@ -0,0 +1,42 @@
{ config, pkgs, lib, ... }: {
users.users.torrent = {
isSystemUser = true;
createHome = false;
group = "torrent";
home = "/torrent";
};
users.groups.torrent = {};
systemd.tmpfiles.rules = [
"d /torrent 770 torrent torrent"
];
users.users.yorick.extraGroups = [ "torrent" ];
services.yorick.torrent-vpn = {
enable = true;
name = "mullvad-nl4";
namespace = "torrent";
};
services.plex = {
enable = true;
openFirewall = true;
};
systemd.services.plex.after = [ "data-plexmedia.mount" ];
services.sonarr = {
enable = true;
group = "plex";
user = "plex";
};
services.radarr = {
enable = true;
group = "plex";
user = "plex";
};
users.users.plex.packages = with pkgs; [
ffmpeg
];
users.users.yorick.packages = with pkgs; [
pyrosimple
rtorrent
yscripts.absorb
];
}

View File

@ -0,0 +1,54 @@
{ config, lib, pkgs, ... }:
let cfg = config.services.yorick.paperless;
in {
options.services.yorick.paperless = with lib; {
enable = mkEnableOption "yorick paperless";
openFirewall = mkEnableOption "open firewall for scanner";
scanner_ip = mkOption {
type = types.str;
};
};
config = lib.mkIf cfg.enable {
networking.firewall = lib.mkIf cfg.openFirewall {
connectionTrackingModules = [ "ftp" ];
extraCommands = ''
iptables -t raw -A PREROUTING -i eno1 -s ${cfg.scanner_ip}/32 -p tcp --dport 21 -j CT --helper ftp
iptables -A nixos-fw -p tcp -m tcp --dport 21 -s ${cfg.scanner_ip}/32 -j nixos-fw-accept
'';
extraStopCommands = ''
iptables -t raw -D PREROUTING -i eno1 -s ${cfg.scanner_ip}/32 -p tcp --dport 21 -j CT --helper ftp
iptables -D nixos-fw -p tcp -m tcp --dport 21 -s ${cfg.scanner_ip}/32 -j nixos-fw-accept
'';
};
users.users.ads1600w = {
home = "/var/ads1600w";
group = "ads1600w";
initialHashedPassword =
"$6$q7E6hnTHHt9v.$OHZjuWISanANGwfhznWwfDlHAqbXBjqcr/q0lGe9ff2r.X9xCSoLP4giME5J9WoEUNuWssMLGBPMfXowBjXg70";
isSystemUser = true;
shell = "${pkgs.shadow}/bin/nologin";
createHome = true;
};
users.groups.ads1600w = { };
services.vsftpd = {
enable = true;
localUsers = true;
writeEnable = true;
chrootlocalUser = true;
allowWriteableChroot = true;
extraConfig = "local_umask=007";
userlist = [ "ads1600w" ];
};
# todo: back up this dir
services.paperless.enable = true;
services.paperless.extraConfig = {
# todo: PAPERLESS_ENABLE_HTTP_REMOTE_USER, PAPERLESS_LOGOUT_REDIRECT_URL
PAPERLESS_URL = "https://priv.yori.cc";
PAPERLESS_FORCE_SCRIPT_NAME = "/paperless";
PAPERLESS_STATIC_URL = "/paperless/static/";
};
users.users.paperless.extraGroups = [ "ads1600w" ];
};
}

View File

@ -0,0 +1,91 @@
#############################################################################
# A minimal rTorrent configuration that provides the basic features
# you want to have in addition to the built-in defaults.
#
# See https://github.com/rakshasa/rtorrent/wiki/CONFIG-Template
# for an up-to-date version.
#############################################################################
# Instance layout (base paths)
method.insert = cfg.basedir, private|const|string, "/torrent/"
method.insert = cfg.download, private|const|string, (cat,(cfg.basedir),"work/")
method.insert = cfg.logs, private|const|string, (cat,(cfg.basedir),"log/")
method.insert = cfg.logfile, private|const|string, (cat,(cfg.logs),"rtorrent-",(system.time),".log")
method.insert = cfg.session, private|const|string, (cat,(cfg.basedir),"session/")
# method.insert = cfg.watch, private|const|string, (cat,(cfg.basedir),"watch/")
# Create instance directories
execute.throw = sh, -c, (cat,\
"mkdir -p \"",(cfg.download),"\" ",\
"\"",(cfg.logs),"\" ",\
"\"",(cfg.session),"\" ")
# Listening port for incoming peer traffic (fixed; you can also randomize it)
network.port_range.set = 58572-58572
network.port_random.set = no
# Tracker-less torrent and UDP tracker support
# (conservative settings for 'private' trackers, change for 'public')
dht.mode.set = auto
protocol.pex.set = yes
trackers.use_udp.set = yes
# Peer settings
throttle.max_uploads.set = 100
throttle.max_uploads.global.set = 250
throttle.min_peers.normal.set = 20
throttle.max_peers.normal.set = 60
throttle.min_peers.seed.set = 30
throttle.max_peers.seed.set = 80
trackers.numwant.set = 80
protocol.encryption.set = allow_incoming,try_outgoing,enable_retry
# Limits for file handle resources, this is optimized for
# an `ulimit` of 1024 (a common default). You MUST leave
# a ceiling of handles reserved for rTorrent's internal needs!
network.http.max_open.set = 50
network.max_open_files.set = 600
network.max_open_sockets.set = 300
# Memory resource usage (increase if you have a large number of items loaded,
# and/or the available resources to spend)
pieces.memory.max.set = 3600M
network.xmlrpc.size_limit.set = 4M
# Basic operational settings (no need to change these)
session.path.set = (cat, (cfg.session))
directory.default.set = (cat, (cfg.download))
log.execute = (cat, (cfg.logs), "execute.log")
##log.xmlrpc = (cat, (cfg.logs), "xmlrpc.log")
execute.nothrow = sh, -c, (cat, "echo >",\
(session.path), "rtorrent.pid", " ", (system.pid))
# Other operational settings (check & adapt)
encoding.add = utf8
system.umask.set = 0007
system.cwd.set = (directory.default)
network.http.dns_cache_timeout.set = 25
schedule2 = monitor_diskspace, 15, 60, ((close_low_diskspace, 1000M))
dht.port.set = 10523
system.file.allocate.set = yes
# Run the rTorrent process as a daemon in the background
# (and control via XMLRPC sockets)
#system.daemon.set = true
network.scgi.open_local = (cat,(session.path),".rtorrent.sock")
execute.nothrow = chmod,770,(cat,(session.path),".rtorrent.sock")
# Logging:
# Levels = critical error warn notice info debug
# Groups = connection_* dht_* peer_* rpc_* storage_* thread_* tracker_* torrent_*
print = (cat, "Logging to ", (cfg.logfile))
log.open_file = "log", (cfg.logfile)
log.add_output = "info", "log"
method.insert = get_public_ip_address, simple|private, "execute.capture=curl,-f,-4,https://ifconfig.me/ip"
# The IP address reported to the tracker. (ip) This handles dynamic IP's as well.
schedule2 = ip_tick, 0, 1800, "network.local_address.set=(get_public_ip_address)"

View File

@ -3,6 +3,8 @@
system.stateVersion = "17.09";
yorick.lumi-vpn.name = "yorick";
yorick.lumi-vpn.ip = "10.109.0.10";
yorick.lumi-vpn = {
name = "yorick";
ip = "10.109.0.10";
};
}

View File

@ -27,6 +27,4 @@
nix.settings.max-jobs = lib.mkDefault 4;
powerManagement.cpuFreqGovernor = lib.mkDefault "powersave";
# high-resolution display
hardware.video.hidpi.enable = lib.mkDefault true;
}

View File

@ -2,28 +2,18 @@
# your system. Help is available in the configuration.nix(5) man page
# and in the NixOS manual (accessible by running nixos-help).
{ config, pkgs, lib, ... }:
let
sslforward = proxyPass: {
forceSSL = true;
enableACME = true;
locations."/" = {
inherit proxyPass;
proxyWebsockets = true;
};
};
vpn = import ../../vpn.nix;
in {
{ config, pkgs, lib, inputs, ... }: {
imports = [
./hetznercloud.nix
../../roles/server.nix
../../roles/datakami.nix
../../services/backup.nix
../../services/email.nix
inputs.yobot.nixosModules.default
];
system.stateVersion = "19.03";
services.nginx.enable = true;
services.yorick = {
public = {
enable = true;
@ -41,6 +31,11 @@ in {
enable = true;
vhost = "muflax.church";
};
calibre-web = {
enable = true;
vhost = "calibre.yori.cc";
};
vpn-host.enable = true;
};
age.secrets.muflax.file = ../../../secrets/http.muflax.age;
@ -52,57 +47,49 @@ in {
private_key = config.age.secrets.muflax.path;
};
};
services.nginx.commonHttpConfig = ''
access_log off;
'';
services.nginx.virtualHosts = {
"yori.cc" = {
enableACME = true;
forceSSL = true;
globalRedirect = "yorickvanpelt.nl";
};
"yorickvanpelt.nl".locations."/p1".return =
"301 https://git.yori.cc/yorick/meterkast";
"grafana.yori.cc" = sslforward "http://${vpn.ips.frumar}:3000";
#"ubiquiti.yori.cc" = sslforward "https://${vpn.ips.frumar}:8443";
"prometheus.yori.cc" = {
# only over vpn
listen = [{
addr = "10.209.0.1";
port = 80;
}];
locations."/".proxyPass = "http://10.209.0.3:9090";
};
"pub.yori.cc".locations."/muflax/".extraConfig = ''
rewrite ^/muflax/(.*)$ https://alt.muflax.church/$1 permanent;
'';
"plex.yori.cc" = (sslforward "http://${vpn.ips.frumar}:32400") // {
extraConfig = ''
gzip on;
gzip_vary on;
gzip_min_length 1000;
gzip_proxied any;
gzip_types text/plain text/css text/xml application/xml text/javascript application/x-javascript image/svg+xml;
proxy_http_version 1.1;
proxy_buffering off;
services.nginx = {
enable = true;
commonHttpConfig = "access_log off;";
virtualHosts = {
"yori.cc" = {
enableACME = true;
forceSSL = true;
globalRedirect = "yorickvanpelt.nl";
};
"yorickvanpelt.nl".locations."/p1".return =
"301 https://git.yori.cc/yorick/meterkast";
"pub.yori.cc".locations."/muflax/".extraConfig = ''
rewrite ^/muflax/(.*)$ https://alt.muflax.church/$1 permanent;
'';
"docuseal.datakami.nl" = {
enableACME = true;
forceSSL = true;
locations."/" = {
recommendedProxySettings = true;
proxyPass = "http://127.0.0.1:3001";
};
};
};
"media.yori.cc" = sslforward "http://${vpn.ips.frumar}:32001";
};
networking.firewall.allowedUDPPorts = [ 31790 ]; # wg
networking.wireguard.interfaces.wg-y.peers = lib.mkForce (lib.mapAttrsToList
(machine: publicKey: {
inherit publicKey;
allowedIPs = [ "${vpn.ips.${machine}}/32" ];
}) vpn.keys);
services.prometheus.exporters.wireguard = { enable = true; };
networking.firewall.interfaces.wg-y.allowedTCPPorts = [ 9586 ];
boot.kernel.sysctl."net.ipv4.ip_forward" = 1;
environment.noXlibs = true;
users.users.yorick.packages = with pkgs; [
sshfs-fuse
weechat
ripgrep
];
# TODO: reload cert in weechat
security.acme.certs."pennyworth.yori.cc".postRun = ''
cat fullchain.pem key.pem > /home/yorick/.weechat/ssl/relay.pem
chown yorick:users /home/yorick/.weechat/ssl/relay.pem
chmod 0600 $_
'';
users.users.yorick.packages = with pkgs; [ sshfs-fuse weechat ripgrep ];
networking.firewall.allowedTCPPorts = [ 60307 ]; # weechat relay
virtualisation.oci-containers.containers.docuseal = {
image = "docuseal/docuseal:latest";
ports = [ "127.0.0.1:3001:3000" ];
volumes = [ "docuseal:/data" ];
};
age.secrets.yobot.file = ../../../secrets/yobot.toml.age;
services.yobot = {
enable = true;
configFile = config.age.secrets.yobot.path;
};
}

View File

@ -9,7 +9,6 @@
boot.extraModulePackages = [ ];
boot.loader.grub = {
enable = true;
version = 2;
device = "/dev/sda";
};
@ -22,7 +21,7 @@
nix.settings.max-jobs = lib.mkDefault 1;
#services.nscd.enable = false;
networking.dhcpcd.enable = false;
networking.useDHCP = false;
systemd.network.enable = true;
systemd.network.networks."40-hetzner" = {
DHCP = "ipv4";

View File

@ -7,4 +7,5 @@
yorick.lumi-cache.enable = lib.mkForce false;
system.stateVersion = "21.05";
services.flatpak.enable = true;
}

View File

@ -36,6 +36,4 @@
swapDevices = [ ];
powerManagement.cpuFreqGovernor = lib.mkDefault "powersave";
# high-resolution display
hardware.video.hidpi.enable = lib.mkDefault true;
}

View File

@ -13,7 +13,10 @@
boot.supportedFilesystems = [ "zfs" ];
boot.kernelPackages = pkgs.zfs.latestCompatibleLinuxPackages;
networking.wireless.iwd.enable = true;
networking.wireless = {
enable = false;
iwd.enable = true;
};
networking.hostId = "54a8968e";
services.zfs.autoScrub.enable = true;
@ -21,8 +24,16 @@
hardware.bluetooth.enable = true;
services.fprintd.enable = true;
boot.initrd.availableKernelModules = [ "i915" ];
boot.loader.timeout = 1;
boot.kernelParams = [ "i915.fastboot=1" ];
#boot.plymouth.enable = true;
boot = {
initrd.availableKernelModules = [ "i915" ];
# flickerfree
initrd.systemd.enable = true;
initrd.verbose = false;
plymouth.enable = true;
consoleLogLevel = 0;
kernelParams = [ "quiet" "udev.log_level=3" "i915.fastboot=1" ];
};
boot.loader.timeout = 0;
networking.dhcpcd.extraConfig = "noarp";
}

View File

@ -1,166 +0,0 @@
# SPDX-FileCopyrightText: 2020 Serokell <https://serokell.io/>
#
# SPDX-License-Identifier: MPL-2.0
{ config, lib, pkgs, ... }:
let
cfg = config.services.acme-sh;
# todo: upstream into serokell.nix
dnstype = lib.types.enum [ "dns_aws" "dns_dnsimple" "dns_transip" ];
submod = with lib; config: {
domains = mkOption {
type = types.coercedTo
(types.listOf types.str)
(f: lib.genAttrs f (x: config.dns)) (types.attrsOf dnstype);
default = { "${config.mainDomain}" = config.dns; };
};
mainDomain = mkOption {
type = types.str;
description = "domain to use as primary domain for the cert";
};
postRun = mkOption {
type = types.str;
default = "true";
};
keyFile = mkOption {
type = types.str;
default = "/dev/null";
};
user = mkOption {
type = types.str;
default = "root";
description = "User running the ACME client.";
};
group = mkOption {
type = types.str;
default = "root";
description = "Group running the ACME client.";
};
server = mkOption {
type = types.str;
default = "letsencrypt";
description = "Certificate Authority to use";
};
dns = mkOption {
type = dnstype;
};
renewInterval = mkOption {
type = types.str;
default = "weekly";
description = ''
Systemd calendar expression when to check for renewal. See
<citerefentry><refentrytitle>systemd.time</refentrytitle>
<manvolnum>7</manvolnum></citerefentry>.
'';
};
production = mkOption {
type = types.bool;
default = true;
};
statePath = mkOption {
readOnly = true;
type = types.str;
};
keyPath = mkOption {
readOnly = true;
type = types.str;
};
certPath = mkOption {
readOnly = true;
type = types.str;
};
consulLock = mkOption {
type = types.nullOr types.str;
default = null;
example = "vault";
};
};
in
{
options.services.acme-sh = with lib; {
stateDir = lib.mkOption {
type = types.str;
default = "/var/lib/acme.sh";
};
certs = lib.mkOption {
type = types.attrsOf (types.submodule ({config, name, ...}: (with config; {
options = submod config;
config.statePath = "${cfg.stateDir}/${name}";
config.keyPath = "${statePath}/${mainDomain}/${mainDomain}.key";
config.certPath = "${statePath}/${mainDomain}/fullchain.cer";
})));
default = {};
};
};
config = {
systemd.services = lib.mapAttrs' (name: value: lib.nameValuePair "acme-sh-${name}" (with value; {
description = "Renew ACME Certificate for ${name}";
after =
[ "network.target" "network-online.target" ]
# wait for consul if we use it for locking
++ lib.optionals (consulLock != null) [ "consul.service" ];
wants = [ "network-online.target" ];
serviceConfig = {
Type = "oneshot";
PermissionsStartOnly = true;
User = user;
Group = group;
PrivateTmp = true;
EnvironmentFile = keyFile;
SuccessExitStatus = "0 2";
};
path = with pkgs; [ acme-sh systemd util-linuxMinimal procps ];
preStart = ''
mkdir -p ${cfg.stateDir}
chown 'root:root' ${cfg.stateDir}
chmod 755 ${cfg.stateDir}
mkdir -p "${statePath}"
chown -R '${user}:${group}' "${statePath}"
chmod 750 "${statePath}"
rm -f "${statePath}/renewed"
'';
environment.LE_WORKING_DIR = statePath;
environment.SHELL = "${pkgs.bash}/bin/bash";
script = let
mapDomain = name: dns: ''-d "${name}" --dns ${dns}'';
primary = mapDomain mainDomain domains."${mainDomain}";
domainsStr = lib.concatStringsSep " " ([primary] ++ (lib.remove primary (lib.mapAttrsToList mapDomain domains)));
cmd = ''acme.sh --server ${server} --issue ${lib.optionalString (!production) "--test"} ${domainsStr} --reloadcmd "touch ${statePath}/renewed" --syslog 6 > /dev/null'';
in
if consulLock == null then ''
${cmd}
rm -f "$LE_WORKING_DIR/account.conf"
'' else ''
# consul lock does not expose the exit code, because of platform compatiblity or something
# write it to the 'ecode' file, or exit 1 if it fails altogether
if ${config.services.consul.package}/bin/consul lock -verbose "${consulLock}" '${cmd}; echo $? > ${statePath}/ecode'; then
rm -f "$LE_WORKING_DIR/account.conf"
exit $(cat ${statePath}/ecode)
else
rm -f "$LE_WORKING_DIR/account.conf"
exit 1
fi
'';
postStart = ''
if [ -e "${statePath}/renewed" ]; then
${postRun}
rm -f "${statePath}/renewed"
fi
'';
})) cfg.certs;
systemd.timers = lib.mapAttrs' (name: value: lib.nameValuePair "acme-sh-${name}" (with value; {
wantedBy = [ "timers.target" ];
timerConfig = {
OnCalendar = renewInterval;
Unit = "acme-sh-${name}.service";
Persistent = "yes";
AccuracySec = "5m";
RandomizedDelaySec = "1h";
};
})) cfg.certs;
};
}

View File

@ -7,10 +7,10 @@ in {
};
config = lib.mkIf cfg.enable {
age.secrets.nix-netrc.file = ../../secrets/nix-netrc.age;
nix = {
settings.substituters = [ "https://cache.lumi.guide/" ];
settings.netrc-file = config.age.secrets.nix-netrc.path;
settings.trusted-public-keys = [
nix.settings = {
substituters = [ "https://cache.lumi.guide/?priority=50" ];
netrc-file = lib.mkForce config.age.secrets.nix-netrc.path;
trusted-public-keys = [
"cache.lumi.guide-1:z813xH+DDlh+wvloqEiihGvZqLXFmN7zmyF8wR47BHE="
];
};

View File

@ -0,0 +1,55 @@
{ config, lib, pkgs, ... }:
let cfg = config.services.yorick.marvin-tracker; in
{
options.services.yorick.marvin-tracker = with lib; {
enable = mkEnableOption "Marvin Tracker server";
host = mkOption {
default = "::1";
type = types.str;
};
port = mkOption {
default = 4001;
type = types.port;
};
package = mkOption {
default = pkgs.marvin-tracker;
type = types.package;
};
mqtt.topic = mkOption {
default = "yorick/marvin/tracking";
type = types.str;
};
mqtt.host = mkOption {
default = "localhost";
type = types.str;
};
secretFile = mkOption {
type = types.path;
default = "/dev/null";
};
api_hash = mkOption {
type = types.str;
default = "z6mzC2TGdVCRuFE+oCrwj1GCHyP6OzYcPKZDiO/yLdqpmChC6S7ijCEUSY5gtqhpXhtYeDRyBjNeVJ/0Se4jQQ==";
description = "public key for the secret header value";
};
};
config = lib.mkIf cfg.enable {
systemd.services.marvin-tracker = {
after = [ "network.target" ];
wantedBy = [ "multi-user.target" ];
serviceConfig = {
Type = "simple";
DynamicUser = true;
Restart = "on-failure";
ExecStart = "${cfg.package}/index.js";
EnvironmentFile = cfg.secretFile;
};
environment = {
HOST = cfg.host;
PORT = toString cfg.port;
TOPIC = cfg.mqtt.topic;
API_HASH = cfg.api_hash;
};
};
};
}

View File

@ -1,14 +1,6 @@
{ config, lib, pkgs, ... }:
let
sslcfg = dir: ''
ssl on;
ssl_certificate_key ${dir}/key.pem;
ssl_certificate ${dir}/fullchain.pem;
ssl_trusted_certificate ${dir}/fullchain.pem;
add_header Strict-Transport-Security max-age=15768000;
'';
in {
{
config = lib.mkIf config.services.nginx.enable {
services.nginx = {
recommendedTlsSettings = true;

View File

@ -0,0 +1,65 @@
{ pkgs, config, lib, ...}: let
cfg = config.security.y-selfsigned;
in {
options.security.y-selfsigned = with lib; {
enable = mkEnableOption "Enable generating a self-signed certificate";
directory = mkOption {
type = types.str;
default = "/var/lib/selfsign";
description = "Directory to store the self-signed certificate";
};
domain = mkOption {
type = types.str;
default = "selfsigned.local";
description = "Domain to generate the self-signed certificate for";
};
sslCertificate = mkOption {
type = types.str;
readOnly = true;
default = "${cfg.directory}/${cfg.domain}/cert.pem";
description = "Path to the self-signed certificate";
};
sslCertificateKey = mkOption {
type = types.str;
readOnly = true;
default = "${cfg.directory}/${cfg.domain}/key.pem";
description = "Path to the self-signed certificate key";
};
user = mkOption {
type = types.str;
default = "nginx";
description = "User to run the self-signed certificate generator as";
};
group = mkOption {
type = types.str;
default = "nginx";
description = "Group to run the self-signed certificate generator as";
};
};
config = lib.mkIf cfg.enable {
systemd.tmpfiles.rules = lib.mkAfter [
"d ${cfg.directory} 0700 ${cfg.user} ${cfg.group}"
];
systemd.services."y-selfsigned-ca" = {
description = "Generate self-signed fallback";
path = with pkgs; [ minica ];
unitConfig = {
ConditionPathExists = "!${cfg.sslCertificateKey}";
StartLimitIntervalSec = 0;
};
serviceConfig = {
User = cfg.user;
Group = cfg.group;
UMask = "0077";
Type = "oneshot";
PrivateTmp = true;
WorkingDirectory = cfg.directory;
};
script = "minica --domains ${cfg.domain}";
};
systemd.services.nginx = {
requires = [ "y-selfsigned-ca.service" ];
after = [ "y-selfsigned-ca.service" ];
};
};
}

7
nixos/roles/datakami.nix Normal file
View File

@ -0,0 +1,7 @@
{ lib, ... }: {
services.nginx.virtualHosts."dk-stage.yori.cc" = {
forceSSL = true;
enableACME = true;
globalRedirect = "staging.datakami.nl";
};
}

View File

@ -4,18 +4,21 @@ let
vpn = import ../vpn.nix;
in {
imports = [
inputs.agenix.nixosModule
../modules/acme-sh.nix
inputs.agenix.nixosModules.default
inputs.fooocus.nixosModules.default
../modules/tor-hidden-service.nix
../modules/nginx.nix
../modules/lumi-cache.nix
../modules/lumi-vpn.nix
../modules/marvin-tracker.nix
../modules/muflax-blog.nix
../modules/selfsigned.nix
../services
];
age.secrets = {
root-user-pass.file = ../../secrets/root-user-pass.age;
yorick-user-pass.file = ../../secrets/yorick-user-pass.age;
nix-netrc-yorick.file = ../../secrets/nix-netrc-yorick.age;
};
nix.nixPath = [];# "nixpkgs=${pkgs.path}" ];
@ -29,7 +32,7 @@ in {
openssh.authorizedKeys.keys =
config.users.users.yorick.openssh.authorizedKeys.keys;
# root password is useful from console, ssh has password logins disabled
passwordFile = config.age.secrets.root-user-pass.path; # TODO: generate own
hashedPasswordFile = config.age.secrets.root-user-pass.path; # TODO: generate own
};
services.timesyncd.enable = true;
@ -39,12 +42,12 @@ in {
extraGroups = [ "wheel" ];
group = "users";
openssh.authorizedKeys.keys = with (import ../sshkeys.nix); yorick;
passwordFile = config.age.secrets.yorick-user-pass.path;
hashedPasswordFile = config.age.secrets.yorick-user-pass.path;
createHome = true;
};
# Nix
nixpkgs.config.allowUnfree = true;
# nixpkgs.config.allowUnfree = true;
#nix.buildCores = config.nix.maxJobs;
nix.extraOptions = ''
@ -56,8 +59,8 @@ in {
services.openssh = {
enable = true;
passwordAuthentication = false;
kbdInteractiveAuthentication = false;
settings.PasswordAuthentication = false;
settings.KbdInteractiveAuthentication = false;
};
environment.systemPackages = with pkgs; [
@ -79,6 +82,7 @@ in {
hdparm
lm_sensors
ncdu
attic
# utils
file
@ -126,8 +130,6 @@ in {
};
security.acme.defaults.email = "acme@yori.cc";
security.acme.acceptTerms = true;
nix.settings.trusted-public-keys =
[ "yorick:Pmd0gyrTvVdzpQyb/raHJKdoOag8RLaj434qBgMm4I0=" ];
nix.settings.trusted-users = [ "@wheel" ];
services.prometheus.exporters.node = {
@ -137,4 +139,12 @@ in {
};
networking.firewall.interfaces.wg-y.allowedTCPPorts = [ 9100 ];
xdg.autostart.enable = false;
nix.settings = {
substituters = [ "https://cache.yori.cc/yorick" ];
netrc-file = config.age.secrets.nix-netrc-yorick.path;
trusted-public-keys = [
"yorick:sWqvIllvDhMS9vcWyk4+zSk9L6zq8UgcLPEEQJsAdW4="
];
};
}

View File

@ -3,14 +3,21 @@
services.sshguard.enable = true;
programs.mosh.enable = true;
environment.noXlibs = true;
# environment.noXlibs = true;
networking.firewall.logRefusedConnections =
false; # Silence logging of scanners and knockers
nix.settings.allowed-users = [ "@wheel" ];
# TODO: upstream with noXlibs
nixpkgs.overlays = [
(self: super: {
libdecor = null;
imagemagick = super.imagemagick.override {
libheifSupport = false;
ghostscript = super.ghostscript.override {
cupsSupport = false;
};
};
})
];
}

View File

@ -1,6 +1,7 @@
{ config, lib, pkgs, ... }:
{
services.fwupd.enable = true;
programs.fish.enable = true;
users.users.yorick = {
extraGroups = [ "input" "wireshark" "dialout" "video" "libvirtd" ];
shell = pkgs.fish;
@ -17,18 +18,7 @@
"${gsettings-desktop-schemas}/share/gsettings-schemas/${gsettings-desktop-schemas.name}"
# emacs?
];
nix = {
gc.automatic = pkgs.lib.mkOverride 30 false;
settings.substituters = [
"https://cache.nixos.org"
#"s3://yori-nix?endpoint=s3.eu-central-003.backblazeb2.com&profile=backblaze-read"
#"https://nixpkgs-wayland.cachix.org"
];
settings.trusted-public-keys = [
#"nixpkgs-wayland.cachix.org-1:3lwxaILxMRkVhehr5StQprHdEo4IrE8sRho9R9HOLYA="
"yorick:Pmd0gyrTvVdzpQyb/raHJKdoOag8RLaj434qBgMm4I0="
];
};
nix.gc.automatic = lib.mkOverride 30 false;
virtualisation.libvirtd.enable = true;
# fix glasgow, fomu, backlight
services.udev.extraRules = ''
@ -47,28 +37,29 @@
# development
services.postgresql = {
enable = true;
enable = false;
enableTCPIP = true;
package = pkgs.postgresql_10;
package = pkgs.postgresql_11;
};
# git
boot.kernel.sysctl."fs.inotify.max_user_watches" = 1024000000;
yorick.lumi-vpn.enable = true;
yorick.lumi-vpn.enable = false;
yorick.lumi-cache.enable = true;
security.rtkit.enable = true;
services.pipewire = {
enable = true;
# TODO (segfaults, 192044)
package = pkgs.pipewire.override { libcameraSupport = false; };
alsa.enable = true;
alsa.support32Bit = true; # todo: support32bit?
pulse.enable = true;
};
# attempted to get bluetooth battery indicator
hardware.bluetooth.package = pkgs.bluez5-experimental;
# bluetooth battery indicator
hardware.bluetooth = {
package = pkgs.bluez5-experimental;
settings.General.Experimental = true;
};
xdg.portal = {
enable = true;
wlr.enable = true;
@ -82,12 +73,19 @@
fonts = {
fontDir.enable = true;
enableGhostscriptFonts = true;
fonts = with pkgs; [
packages = with pkgs; [
corefonts # Micrsoft free fonts
inconsolata # monospaced
source-code-pro
ubuntu_font_family # Ubuntu fonts
source-han-sans
(nerdfonts.override {
fonts = [
"DejaVuSansMono"
"Noto"
"NerdFontsSymbolsOnly"
];
})
iosevka
emojione
font-awesome
@ -104,6 +102,7 @@
dconf.enable = true;
noisetorch.enable = true;
wireshark.enable = true;
kdeconnect.enable = true;
sway = {
enable = true;
extraSessionCommands = ''
@ -114,4 +113,18 @@
};
};
services.pcscd.enable = true;
services.xserver.gdk-pixbuf.modulePackages = [ pkgs.webp-pixbuf-loader ];
hardware.ledger.enable = true;
networking.wireguard.interfaces.wg-dk = {
privateKeyFile =
"/home/yorick/datakami/infra/keys/wg.yorick.key";
ips = [ "10.100.0.4/32" ];
peers = [{
publicKey = "teCEYc4KWT6rGchNOp6sIFO0jmkhwTjv6reOzGscAm8=";
endpoint = "dk-1.datakami.nl:51820";
allowedIPs = [ "10.100.0.0/24" ];
persistentKeepalive = 25;
}];
};
}

View File

@ -20,7 +20,7 @@
# Define schedule
startAt = "hourly";
repo = "14337@ch-s012.rsync.net:${name}";
repo = "zh3213@zh3213.rsync.net:${name}";
paths = [ "/home" "/root" "/var/lib" ];
prune.keep = {

View File

@ -0,0 +1,36 @@
{ config, lib, pkgs, ... }:
let
cfg = config.services.yorick.calibre-web;
in {
options.services.yorick.calibre-web = with lib; {
enable = mkEnableOption "calibre-web";
vhost = mkOption { type = types.str; };
};
config = lib.mkIf cfg.enable {
services.calibre-web = {
enable = true;
options = {
enableBookUploading = true;
#enableBookConversion = true;
enableKepubify = true;
};
};
services.nginx.virtualHosts.${cfg.vhost} = {
forceSSL = true;
enableACME = true;
locations."/" = {
proxyPass = "http://[::1]:8083";
proxyWebsockets = true;
};
locations."/kobo/" = {
proxyPass = "http://[::1]:8083/kobo/";
extraConfig = ''
proxy_buffer_size 128k;
proxy_buffers 4 256k;
proxy_busy_buffers_size 256k;
'';
};
};
};
}

View File

@ -1,4 +1,11 @@
{
imports =
[ ./git.nix ./muflax-church.nix ./pub.nix ./website.nix ./torrent-wg.nix ];
imports = [
./calibre-web.nix
./git.nix
./muflax-church.nix
./pub.nix
./vpn-host.nix
./website.nix
./torrent-wg.nix
];
}

View File

@ -2,6 +2,7 @@
{
imports = [ inputs.nixos-mailserver.nixosModule ];
age.secrets.yorick-mail-pass.file = ../../secrets/yorick-mail-pass.age;
age.secrets.frumar-mail-pass-hash.file = ../../secrets/frumar-mail-pass-hash.age;
mailserver = rec {
enable = true;
@ -13,8 +14,12 @@
catchAll = domains;
aliases = [ "@yori.cc" "@yorickvanpelt.nl" ];
};
"frumar@yori.cc" = {
hashedPasswordFile = config.age.secrets.frumar-mail-pass-hash.path;
sendOnly = true;
};
};
certificateScheme = 3;
certificateScheme = "acme-nginx";
enableImapSsl = true;
};

View File

@ -11,34 +11,38 @@ in {
config = lib.mkIf cfg.enable {
users.extraUsers.git = {
createHome = true;
home = config.services.gitea.stateDir;
home = config.services.forgejo.stateDir;
group = "git";
useDefaultShell = true;
isSystemUser = true;
};
users.groups.git = {};
services.gitea = {
services.forgejo = {
enable = true;
user = "git";
database.user = "root";
database.name = "gogs";
database.createDatabase = false;
#dump.enable = true; TODO: backups
domain = cfg.vhost;
rootUrl = "https://${cfg.vhost}/";
httpAddress = "localhost";
settings.log.LEVEL = "Warn";
settings.service = {
DISABLE_REGISTRATION = true;
REGISTER_EMAIL_CONFIRM = false;
COOKIE_SECURE = true;
ENABLE_NOTIFY_MAIL = false;
REQUIRE_SIGNIN_VIEW = false;
};
settings.picture.DISABLE_GRAVATAR = false;
settings.mailer = {
ENABLED = false;
AVATAR_UPLOAD_PATH = "${config.services.gitea.stateDir}/data/avatars";
settings = {
server = {
ROOT_URL = "https://${cfg.vhost}/";
HTTP_ADDR = "localhost";
DOMAIN = cfg.vhost;
};
log.LEVEL = "Warn";
service = {
DISABLE_REGISTRATION = true;
REGISTER_EMAIL_CONFIRM = false;
COOKIE_SECURE = true;
ENABLE_NOTIFY_MAIL = false;
REQUIRE_SIGNIN_VIEW = false;
};
picture.DISABLE_GRAVATAR = false;
mailer = {
ENABLED = false;
AVATAR_UPLOAD_PATH = "${config.services.forgejo.stateDir}/data/avatars";
};
};
};
services.nginx.virtualHosts.${vhost} = {
@ -46,11 +50,20 @@ in {
enableACME = true;
locations."/" = {
proxyPass =
"http://127.0.0.1:${toString config.services.gitea.httpPort}";
"http://127.0.0.1:${toString config.services.forgejo.settings.server.HTTP_PORT}";
extraConfig = ''
proxy_buffering off;
'';
};
};
services.borgbackup.jobs.backup.exclude = let
sd = config.services.forgejo.stateDir;
in [
"${sd}/data/tmp"
"${sd}/tmp"
"${sd}/data/repo-archive"
"${sd}/log"
];
};
}

View File

@ -9,13 +9,12 @@ in {
config = lib.mkIf cfg.enable {
age.secrets.wg-torrent.file = ../../secrets/wg.${cfg.name}.age;
networking.wireguard.interfaces.${cfg.name} = {
# curl -s https://api.mullvad.net/www/relays/all/ | jq '.[] | select(.type == "wireguard" and .country_code == "nl")'
ips = [ "10.66.30.26/32" "fc00:bbbb:bbbb:bb01::3:1e19/128" ];
ips = [ "10.0.34.127/32" "2a0e:1c80:1337:1:10:0:34:127/128" ];
privateKeyFile = config.age.secrets.wg-torrent.path;
peers = [{
publicKey = "hnRyse6QxPPcZOoSwRsHUtK1W+APWXnIoaDTmH6JsHQ=";
publicKey = "W+LE+uFRyMRdYFCf7Jw0OPERNd1bcIm0gTKf/traIUk=";
allowedIPs = [ "0.0.0.0/0" "::0/0" ];
endpoint = "[2a03:1b20:3:f011::a04f]:51820";
endpoint = "nl-ams.azirevpn.net:51820";
}];
interfaceNamespace = cfg.namespace;
preSetup = ''
@ -23,7 +22,9 @@ in {
'';
};
environment.etc."netns/torrent/resolv.conf".text = ''
nameserver 193.138.218.74
nameserver 91.231.153.2
nameserver 192.211.0.2
nameserver 2a0e:1c80:1337:1:10:0:0:1
'';
};
}

View File

@ -0,0 +1,25 @@
{ config, lib, pkgs, ... }:
let cfg = config.services.yorick.vpn-host;
in {
options.services.yorick.vpn-host = with lib; {
enable = mkEnableOption "vpn-host";
};
config = lib.mkIf cfg.enable {
services.prometheus.exporters.wireguard.enable = true;
networking = {
firewall = {
allowedUDPPorts = [ 31790 ]; # wg
interfaces.wg-y.allowedTCPPorts = [ 9586 ]; # wireguard exporter
};
wireguard.interfaces.wg-y.peers = let vpn = import ../vpn.nix;
in lib.mkForce (lib.mapAttrsToList (machine: publicKey: {
inherit publicKey;
allowedIPs = [ "${vpn.ips.${machine}}/32" ];
}) vpn.keys);
};
boot.kernel.sysctl."net.ipv4.ip_forward" = 1;
};
}

View File

@ -6,6 +6,20 @@
"ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQDFQm2OJ8PlnDHfI7FV3hddXP0t2jgKAiCnnuWIc+LK4dnyGmlC/ihIe9KhSENZEnzVAXnYAMOoOvpkVa5p0Itf1n0anCK3k2vDq0Jz9nY3ZXmkSHE09QGCpSG8kU6j+zWJPo2jWYNtxYMRmmHAuzzOdlPY9Q199PEvHVaqzpSVhIdhqhEcmap8oqHW6KbJu+17nLGGQB5XiTB1SlTxbg62copA9KMcvQzNGIooKs5QyrU/B0g05EfbogH7xOLbwYAK676DTUBEcKpEUYFMMv+DBcU4cH2EI6UTLxI5ohrS1pxk20zu5nTRMlQRUETpWN4EbEPfOzF8FW1YOwdttfCas8D6Y6t9gA4o8GpylBG9AElVw7VyOFeBR+AtchormH+wH6nZEvzs6wg2d84I8xo5qYGUJIQS7OYxypjlY01IFCCa/7rjzXGDmdWAP/UEu85ys9FSryn9Ey5DXDQOqhMHguOwQDUyaArWyRCCBzKbx6cPZw2D9bLfDxbnaC2/5dVyxHJXoWmwneX2E/UT5QwtG1nyLShIZhYgO9lfDpO61Mz9Jjap3sj6mJPxHZc5SGye0j47xV6kX4vbSgfoSHHnasaI3fR2ZBS7tnfq1ebxXqFFSPHK6uHjLgDHtkMisvjOVZnybuXB296pjv6K1o2G3qlUnImOqfxZxvuy4Xl/mw== cardno:000607186578"
];
lars = [
"ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQCbieYUtRGQ4nf4glQvrZDn72doP6W2uw2z9VqFq5sZLROXYa4jW8nwx4h+BiArGs+VPwn6lfsP19PX6yNIk74C/SkO26S1Zvbe7ffNusi6PH2BQIOWeAYKk+eZH+ZOeD8z07uDB7QffwRLwzSaPFg+zfRzsMFoXH/GE9qOQ4lnfk8czTZL7zbZf/yS7mDFztClXFciYsVwgRXNiFpfc+9mOkU0oBWtGo/WGUhB0Hds3a4ylyjjVAcC/l1H2bvc/Q3d6bbn23pUFl2V78Yg1B4b1MT34qbBV6whXAQd7KM9tND2ZhpF2XQ7Spi1QlOac0jup+sE+3bbvcjNqTI05DwJO/dX5F2gSAFkvSY4ZPqSX5ilE/hj4DQuhRgLmQdbVl5IFV9aLYqUvJcCqX9jRFMly4YTFXsFz18rGkxOYGZabcE1usBM2zRVDTtEP6Si5ii76Ocvp8aNFBB2Kf1whg8tziTv3kQEQ9fd2sRtE2J3xveJiwXjUBU2uikSOKe8JP47Tb6PYlv7Ty/6OI51aUQn++R72VNajdBJ1r1osp7leqTJ+sXuLlWLo/a7lDpDmgEI7dbxqmpjLcMce0JzqLKlP1Q2U/nkYy86xkjSTH1rNUI2JAbJx3iTcGy7bq12yfjNfcGAqY4GVXvisK1cpbF0RCjaFExwtmzorljHh6ZHjQ=="
"ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQCbieYUtRGQ4nf4glQvrZDn72doP6W2uw2z9VqFq5sZLROXYa4jW8nwx4h+BiArGs+VPwn6lfsP19PX6yNIk74C/SkO26S1Zvbe7ffNusi6PH2BQIOWeAYKk+eZH+ZOeD8z07uDB7QffwRLwzSaPFg+zfRzsMFoXH/GE9qOQ4lnfk8czTZL7zbZf/yS7mDFztClXFciYsVwgRXNiFpfc+9mOkU0oBWtGo/WGUhB0Hds3a4ylyjjVAcC/l1H2bvc/Q3d6bbn23pUFl2V78Yg1B4b1MT34qbBV6whXAQd7KM9tND2ZhpF2XQ7Spi1QlOac0jup+sE+3bbvcjNqTI05DwJO/dX5F2gSAFkvSY4ZPqSX5ilE/hj4DQuhRgLmQdbVl5IFV9aLYqUvJcCqX9jRFMly4YTFXsFz18rGkxOYGZabcE1usBM2zRVDTtEP6Si5ii76Ocvp8aNFBB2Kf1whg8tziTv3kQEQ9fd2sRtE2J3xveJiwXjUBU2uikSOKe8JP47Tb6PYlv7Ty/6OI51aUQn++R72VNajdBJ1r1osp7leqTJ+sXuLlWLo/a7lDpDmgEI7dbxqmpjLcMce0JzqLKlP1Q2U/nkYy86xkjSTH1rNUI2JAbJx3iTcGy7bq12yfjNfcGAqY4GVXvisK1cpbF0RCjaFExwtmzorljHh6ZHjQ== openpgp:0x60F7D1FD"
"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIOvdQ963wjgWyFMp6djRTqVwZr3/PQ/V+Qm5JTcxRTdY lumi@channelwood"
];
judith = [
"ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAgEAsov+RwE8719rmgk+wRnnw7rN6vybOc4fwKXmXZqVHv5hg0Q1Eoz8N4WC+qL4VXqyIm2mkfctUKhF5DKR8IGZs/k/ZmQ09jTZskB2Cm9oVhuGztgWLwXJcgARxaDYqVXYTwOCoMto67uHhGj9ZWyHSoo7FrinSOpBivBXYQl/y7QVVnSmGIS5dp4Ph1+fLrUxl744h+BxmrFEWt3+qaz0T6s7l6HjaoE5Yb6EWmxPunDtKz9HqsBM4Ixsv24//7gCi9AZkM3agODIEKnFVcgg1gxcgX5HwruHT6r/dwHEUlXs2Aka4uZRRaCcIdg/cvYvVDlmstKoVgzWhyZKZRgTHiVO4NHPMTyNMxB0R02myZYE097EC4yhVhvMxSC1JmEB2E40QoxdDPwi7YMQIGsDVsynRRDgp4MOExnuHXqxtb7PcYtG8jh4kRcO8jtW0EsuFOmP5QEui3NWSaF97DlMDQYm7Xmk/VuXg/Hnzz9xBKW/0/bAfLyp5ka9Y5WSGiyrAv0IkuUwGJQYYH2BZ6ua/aL1z+xoHBYF5BmIuahLPMkdWdAiUUAqvvSCJgDVd8n1W9zJ4LF7i3hwr1gg3/dgRjr7HczEiQyfc41SPlhQ93ZVIhE9oV11Xaq3d3VwA7tqTP6VE8IeLNBqqsLT9YnYdhg87d5ctXiq/I4sqxF5gNs="
];
dk-stage-deploy = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIHevKDi9QRssz0gUWGMg/s6SLU9mAdwvZDTbrD7EXoII";
mickey = [
"ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQDFEWVdhA7qgkHZogaGcCwmt6mqSUOtZoPbK6mCt0jWACj18eLZgjWHCzp+/YUtlmuJdNu9FyJZT2dbhJRwka34k69mFvg/z7mRgXlc9LbgRClDdynnK5SvBwfB7oswDzD7OKKopHENlSd7qB+KYTIx8+YIHmMGZVkpjDJXDXNksFWBlHldGvulj1pzFj29L0CdpFJGxLsfbSuuWWKB1tvKAMPiqKoJIEL/wkX0HsfCYSLF7aAVKtuqAZ2MVK+zZeeyIb7fHl2IOIq+wWJW6uUS2btxd0VDHbUUM6KyYqqYwRgCVDvijF/Q8nI0/3wf7vhjWu3LTr4F5M+UEVyUX8eNXRvFwdVcwJOk7Vz8giAqtU3s+4ypx4o3DmaxjQgqlpwSC0WUPx4UCXYKQDwpvN+T8Q3OMNYDBomUlMCSHsVSP1bUg/lSSdRq9H/behrMynF2/I7ZqH9lEK6SYEw/581qCozB56DIUME3frMq794fIkG+tayn08NsERYVKV9ETGZozvxYUpyLhpb1H6ISKqDJ27RVxSNMTSEeDSz8oMnOPHPajB/oPlTuLM57sYeBEp6unz5DUYXMZF0FaMW1KDyJwLtedz8GIHkaP7UqwDUqyDr5SDGmxeST1BDWAdS1ohg8/t4+aOrCkzCf1IQ9xDi6nWGHbvDXkKgDqbVIbd0XHQ=="
"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIFvR12391V0zxBU6qp9+2R8XUtHL/MzvTjz1622XKuiL"
"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIDP0iSb0fe09IfnggNi0Ybs1KQW2hSfc17TH+aBDN76z"
"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIG5lZzAhmhzXWgx+BJDepeMTYqZdKMpKsbUaoZhWNYo5"
];
bram = [
"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIPojRFgeDYvDHOShfw3Rd3nB9RaZ3vxjiFNfejqjDiWM"
];
}

View File

@ -37,19 +37,67 @@ padded_string read_mozlz4a_file(const std::string& file) {
return out;
}
std::string get_default_firefox_profile_path() {
std::string path = std::string(std::getenv("HOME")) + "/.mozilla/firefox/profiles.ini";
std::ifstream file(path);
if (file.is_open()) {
std::string line;
bool found = false;
std::string default_profile;
while (std::getline(file, line)) {
if (line.find("[General]") == 0) {
found = true;
} else if (found && line.find("Default=") == 0) {
default_profile = line.substr(8);
break;
}
}
file.close();
if (!default_profile.empty()) {
std::stringstream ss;
ss << std::string(std::getenv("HOME")) << "/.mozilla/firefox/" << default_profile;
return ss.str();
}
}
return "";
}
int main(int ac, char **av) {
ondemand::parser parser;
if (ac < 2) {
std::cerr << "usage: " << av[0] << " .mozilla/firefox/*.default/sessionstore-backups/recovery.jsonlz4" << std::endl;
exit(1);
std::string path = get_default_firefox_profile_path();
bool print_json = false;
std::string json_file;
// Check for --json flag
for (int i = 1; i < ac; i++) {
if (std::string(av[i]) == "--json") {
print_json = true;
if (i + 1 < ac) {
json_file = av[i + 1];
}
break;
}
}
padded_string json = read_mozlz4a_file(av[1]);
if (ac < 2 && path.empty() && !print_json) {
std::cerr << "Could not find default Firefox profile" << std::endl;
std::cerr << "usage: " << av[0] << " .mozilla/firefox/*.default/sessionstore-backups/recovery.jsonlz4" << std::endl;
exit(1);
}
if (print_json) {
padded_string json = read_mozlz4a_file(json_file.empty() ? (ac > 2 ? av[2] : path + "/sessionstore-backups/recovery.jsonlz4") : json_file);
std::cout << json << std::endl;
exit(0);
}
padded_string json = read_mozlz4a_file(ac > 1 ? av[1] : path + "/sessionstore-backups/recovery.jsonlz4");
ondemand::document session = parser.iterate(json);
ondemand::array windows = session["windows"];
size_t n = 0;
for (auto i : windows) {
ondemand::array tabs = i["tabs"];
n += tabs.count_elements();
ondemand::array tabs = i["tabs"];
n += tabs.count_elements();
}
std::cout << n << std::endl;
}

View File

@ -3,8 +3,6 @@
yori-cc = super.callPackage ./yori-cc.nix { };
ftb = super.callPackage ./ftb.nix {};
# todo: python 2 -> 3
pyroscope = self.nixpkgs-stable.callPackage ./pyroscope {};
yscripts = super.callPackage ../bin {};
factorio = super.factorio.override {
@ -33,5 +31,72 @@
runHook postInstall
'';
});
wayland-push-to-talk-fix = self.callPackage ./wayland-push-to-talk-fix.nix {};
y-deployer = self.callPackage ../deployer/package.nix {};
inherit (self.nix-npm-buildpackage) buildYarnPackage;
marvin-tracker = self.callPackage ./marvin-tracker {};
grott = self.callPackage ./grott.nix {};
python3 = super.python3.override {
packageOverrides = pyself: pysuper: {
libscrc = pyself.callPackage ./libscrc.nix {};
};
};
xwaylandvideobridge = self.libsForQt5.callPackage ./xwaylandvideobridge.nix {};
timesync = self.flake-inputs.timesync.packages.${self.system}.default;
wl-clipboard = super.wl-clipboard.overrideAttrs (o: {
# todo: upstream
patches = (o.patches or []) ++ [
(self.fetchpatch {
url = "https://puck.moe/up/zapap-suhih.patch";
hash = "sha256-YiFDeBN1k2+lxVnWnU5sMpIJ7/zsVPEm5OZf0nHhzJA=";
})
];
});
notion-desktop = self.callPackage ./notion-desktop {
electron_26 = self.electron_27;
};
r8-cog = self.stdenvNoCC.mkDerivation rec {
pname = "cog";
version = "0.9.5";
src = self.fetchurl {
url = "https://github.com/replicate/cog/releases/download/v${version}/cog_linux_x86_64";
hash = "sha256-xrtK0zx2dOwafRxbL/+NA217uPEACC0QHMKQURUhlms=";
};
dontUnpack = true;
installPhase = ''
install -Dm 755 $src $out/bin/cog
mkdir -p $out/share/{fish/vendor_completions.d,bash-completion/completions,zsh/site-functions}
$out/bin/cog completion bash > $out/share/bash-completion/completions/cog
$out/bin/cog completion fish > $out/share/fish/vendor_completions.d/cog.fish
$out/bin/cog completion zsh > $out/share/zsh/site-functions/_cog
'';
};
obsidian = with self.lib; throwIf (versionOlder "1.4.16" super.obsidian.version) "Obsidian no longer requires EOL Electron" (
super.obsidian.override {
electron = self.electron_25.overrideAttrs (_: {
preFixup = "patchelf --add-needed ${self.libglvnd}/lib/libEGL.so.1 $out/bin/electron"; # NixOS/nixpkgs#272912
meta.knownVulnerabilities = [ ]; # NixOS/nixpkgs#273611
});
}
);
noulith = self.rustPlatform.buildRustPackage rec {
pname = "noulith";
version = "20231228";
src = self.fetchFromGitHub {
owner = "betaveros";
rev = "3bce693335d8170895407846c237b6dad10ef7ec";
repo = pname;
hash = "sha256-Ye/Htcp9lrRo80ix4QQ+lDZSmpDSA6t1MCcWL6yTvGg=";
};
buildFeatures = [ "cli" "request" "crypto" ];
cargoHash = "sha256-N/BeeJIkbEccELqZhTFkHiaWJZgNiBazQLRqkqtPfJY=";
nativeBuildInputs = [ self.pkg-config ];
buildInputs = [ self.openssl.dev ];
};
llm = super.callPackage ./llm.nix {
python3 = self.python312;
};
})

232
pkgs/fooocus/flake.lock Normal file
View File

@ -0,0 +1,232 @@
{
"nodes": {
"devshell": {
"flake": false,
"locked": {
"lastModified": 1663445644,
"narHash": "sha256-+xVlcK60x7VY1vRJbNUEAHi17ZuoQxAIH4S4iUFUGBA=",
"owner": "numtide",
"repo": "devshell",
"rev": "e3dc3e21594fe07bdb24bdf1c8657acaa4cb8f66",
"type": "github"
},
"original": {
"owner": "numtide",
"repo": "devshell",
"type": "github"
}
},
"dream2nix": {
"inputs": {
"devshell": "devshell",
"flake-compat": "flake-compat",
"flake-parts": "flake-parts",
"nix-unit": "nix-unit",
"nixpkgs": "nixpkgs",
"pre-commit-hooks": "pre-commit-hooks"
},
"locked": {
"lastModified": 1697623956,
"narHash": "sha256-/YfNW+FYOcfcrT3RmvVZMipP9S/F5DFRZ/Hs7lIxD+M=",
"owner": "yorickvP",
"repo": "dream2nix",
"rev": "372c3e8fe1f4ae909cb198dff0b9c6d6127b92eb",
"type": "github"
},
"original": {
"owner": "yorickvP",
"repo": "dream2nix",
"type": "github"
}
},
"flake-compat": {
"flake": false,
"locked": {
"lastModified": 1673956053,
"narHash": "sha256-4gtG9iQuiKITOjNQQeQIpoIB6b16fm+504Ch3sNKLd8=",
"owner": "edolstra",
"repo": "flake-compat",
"rev": "35bb57c0c8d8b62bbfd284272c928ceb64ddbde9",
"type": "github"
},
"original": {
"owner": "edolstra",
"repo": "flake-compat",
"type": "github"
}
},
"flake-parts": {
"inputs": {
"nixpkgs-lib": [
"dream2nix",
"nixpkgs"
]
},
"locked": {
"lastModified": 1675933616,
"narHash": "sha256-/rczJkJHtx16IFxMmAWu5nNYcSXNg1YYXTHoGjLrLUA=",
"owner": "hercules-ci",
"repo": "flake-parts",
"rev": "47478a4a003e745402acf63be7f9a092d51b83d7",
"type": "github"
},
"original": {
"owner": "hercules-ci",
"repo": "flake-parts",
"type": "github"
}
},
"flake-utils": {
"inputs": {
"systems": "systems"
},
"locked": {
"lastModified": 1689068808,
"narHash": "sha256-6ixXo3wt24N/melDWjq70UuHQLxGV8jZvooRanIHXw0=",
"owner": "numtide",
"repo": "flake-utils",
"rev": "919d646de7be200f3bf08cb76ae1f09402b6f9b4",
"type": "github"
},
"original": {
"owner": "numtide",
"repo": "flake-utils",
"type": "github"
}
},
"nix-github-actions": {
"inputs": {
"nixpkgs": [
"dream2nix",
"nix-unit",
"nixpkgs"
]
},
"locked": {
"lastModified": 1688870561,
"narHash": "sha256-4UYkifnPEw1nAzqqPOTL2MvWtm3sNGw1UTYTalkTcGY=",
"owner": "nix-community",
"repo": "nix-github-actions",
"rev": "165b1650b753316aa7f1787f3005a8d2da0f5301",
"type": "github"
},
"original": {
"owner": "nix-community",
"repo": "nix-github-actions",
"type": "github"
}
},
"nix-unit": {
"inputs": {
"flake-parts": [
"dream2nix",
"flake-parts"
],
"nix-github-actions": "nix-github-actions",
"nixpkgs": [
"dream2nix",
"nixpkgs"
],
"treefmt-nix": "treefmt-nix"
},
"locked": {
"lastModified": 1694670962,
"narHash": "sha256-HvMq0TJGYSx37zHm4j2d+JUZx4/6X7xKEt/0DeCiwjQ=",
"owner": "adisbladis",
"repo": "nix-unit",
"rev": "3ed2378bddad85257fc508a291408f9ed9673d01",
"type": "github"
},
"original": {
"owner": "adisbladis",
"repo": "nix-unit",
"type": "github"
}
},
"nixpkgs": {
"locked": {
"lastModified": 1698318101,
"narHash": "sha256-gUihHt3yPD7bVqg+k/UVHgngyaJ3DMEBchbymBMvK1E=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "63678e9f3d3afecfeafa0acead6239cdb447574c",
"type": "github"
},
"original": {
"id": "nixpkgs",
"ref": "nixos-unstable",
"type": "indirect"
}
},
"pre-commit-hooks": {
"inputs": {
"flake-utils": "flake-utils",
"nixpkgs": [
"dream2nix",
"nixpkgs"
]
},
"locked": {
"lastModified": 1646153636,
"narHash": "sha256-AlWHMzK+xJ1mG267FdT8dCq/HvLCA6jwmx2ZUy5O8tY=",
"owner": "cachix",
"repo": "pre-commit-hooks.nix",
"rev": "b6bc0b21e1617e2b07d8205e7fae7224036dfa4b",
"type": "github"
},
"original": {
"owner": "cachix",
"repo": "pre-commit-hooks.nix",
"type": "github"
}
},
"root": {
"inputs": {
"dream2nix": "dream2nix",
"nixpkgs": [
"dream2nix",
"nixpkgs"
]
}
},
"systems": {
"locked": {
"lastModified": 1681028828,
"narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=",
"owner": "nix-systems",
"repo": "default",
"rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e",
"type": "github"
},
"original": {
"owner": "nix-systems",
"repo": "default",
"type": "github"
}
},
"treefmt-nix": {
"inputs": {
"nixpkgs": [
"dream2nix",
"nix-unit",
"nixpkgs"
]
},
"locked": {
"lastModified": 1689620039,
"narHash": "sha256-BtNwghr05z7k5YMdq+6nbue+nEalvDepuA7qdQMAKoQ=",
"owner": "numtide",
"repo": "treefmt-nix",
"rev": "719c2977f958c41fa60a928e2fbc50af14844114",
"type": "github"
},
"original": {
"owner": "numtide",
"repo": "treefmt-nix",
"type": "github"
}
}
},
"root": "root",
"version": 7
}

27
pkgs/fooocus/flake.nix Normal file
View File

@ -0,0 +1,27 @@
{
inputs = {
dream2nix.url = "github:yorickvP/dream2nix";
#dream2nix.inputs.nixpkgs.follows = "nixpkgs";
nixpkgs.follows = "dream2nix/nixpkgs";
};
outputs = { self, dream2nix, nixpkgs }:
let
nixpkgs' = import nixpkgs {
config.allowUnfree = true;
system = "x86_64-linux";
};
package = dream2nix.lib.evalModules {
modules = [ {
paths.projectRoot = ./.;
paths.projectRootFile = "flake.nix";
paths.package = ".";
} ./package.nix ];
packageSets.nixpkgs = nixpkgs';
};
in {
packages.x86_64-linux.default = package;
devShells.x86_64-linux.default = package.devShell;
packages.x86_64-linux.lock = package.config.lock.refresh;
nixosModules.default = ./module.nix;
};
}

839
pkgs/fooocus/lock.json Normal file
View File

@ -0,0 +1,839 @@
{
"fetchPipMetadata": {
"sources": {
"accelerate": {
"sha256": "e2609d37f2c6a56e36a0612feae6ff6d9daac9759f4899432b86b1dc97024ebb",
"type": "url",
"url": "https://files.pythonhosted.org/packages/70/f9/c381bcdd0c3829d723aa14eec8e75c6c377b4ca61ec68b8093d9f35fc7a7/accelerate-0.21.0-py3-none-any.whl",
"version": "0.21.0"
},
"aiofiles": {
"sha256": "19297512c647d4b27a2cf7c34caa7e405c0d60b5560618a29a9fe027b18b0107",
"type": "url",
"url": "https://files.pythonhosted.org/packages/c5/19/5af6804c4cc0fed83f47bff6e413a98a36618e7d40185cd36e69737f3b0e/aiofiles-23.2.1-py3-none-any.whl",
"version": "23.2.1"
},
"aiohttp": {
"sha256": "96603a562b546632441926cd1293cfcb5b69f0b4159e6077f7c7dbdfb686af4d",
"type": "url",
"url": "https://files.pythonhosted.org/packages/37/d6/747aca77b7f0a76abf1133e4193a840f57b925609fcf2c1a18058748493d/aiohttp-3.8.6-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl",
"version": "3.8.6"
},
"aiosignal": {
"sha256": "f8376fb07dd1e86a584e4fcdec80b36b7f81aac666ebc724e2c090300dd83b17",
"type": "url",
"url": "https://files.pythonhosted.org/packages/76/ac/a7305707cb852b7e16ff80eaf5692309bde30e2b1100a1fcacdc8f731d97/aiosignal-1.3.1-py3-none-any.whl",
"version": "1.3.1"
},
"altair": {
"sha256": "7219708ec33c152e53145485040f428954ed15fd09b2a2d89e543e6d111dae7f",
"type": "url",
"url": "https://files.pythonhosted.org/packages/17/16/b12fca347ff9d062e3c44ad9641d2ec50364570a059f3078ada3a5119d7a/altair-5.1.2-py3-none-any.whl",
"version": "5.1.2"
},
"annotated-types": {
"sha256": "0641064de18ba7a25dee8f96403ebc39113d0cb953a01429249d5c7564666a43",
"type": "url",
"url": "https://files.pythonhosted.org/packages/28/78/d31230046e58c207284c6b2c4e8d96e6d3cb4e52354721b944d3e1ee4aa5/annotated_types-0.6.0-py3-none-any.whl",
"version": "0.6.0"
},
"antlr4-python3-runtime": {
"sha256": "f224469b4168294902bb1efa80a8bf7855f24c99aef99cbefc1bcd3cce77881b",
"type": "url",
"url": "https://files.pythonhosted.org/packages/3e/38/7859ff46355f76f8d19459005ca000b6e7012f2f1ca597746cbcd1fbfe5e/antlr4-python3-runtime-4.9.3.tar.gz",
"version": "4.9.3"
},
"anyio": {
"sha256": "91dee416e570e92c64041bd18b900d1d6fa78dff7048769ce5ac5ddad004fbb5",
"type": "url",
"url": "https://files.pythonhosted.org/packages/19/24/44299477fe7dcc9cb58d0a57d5a7588d6af2ff403fdd2d47a246c91a3246/anyio-3.7.1-py3-none-any.whl",
"version": "3.7.1"
},
"async-timeout": {
"sha256": "7405140ff1230c310e51dc27b3145b9092d659ce68ff733fb0cefe3ee42be028",
"type": "url",
"url": "https://files.pythonhosted.org/packages/a7/fa/e01228c2938de91d47b307831c62ab9e4001e747789d0b05baf779a6488c/async_timeout-4.0.3-py3-none-any.whl",
"version": "4.0.3"
},
"attrs": {
"sha256": "1f28b4522cdc2fb4256ac1a020c78acf9cba2c6b461ccd2c126f3aa8e8335d04",
"type": "url",
"url": "https://files.pythonhosted.org/packages/f0/eb/fcb708c7bf5056045e9e98f62b93bd7467eb718b0202e7698eb11d66416c/attrs-23.1.0-py3-none-any.whl",
"version": "23.1.0"
},
"boltons": {
"sha256": "f716a1b57698a5b19062f3146cb5ce3549904028a2f267c2c0cf584eea3ad75b",
"type": "url",
"url": "https://files.pythonhosted.org/packages/22/f0/d81d7f6688d25cfb8b8fce60504c3cbf5d5890b9a1d71911047aa89707c2/boltons-23.0.0-py2.py3-none-any.whl",
"version": "23.0.0"
},
"certifi": {
"sha256": "92d6037539857d8206b8f6ae472e8b77db8058fec5937a1ef3f54304089edbb9",
"type": "url",
"url": "https://files.pythonhosted.org/packages/4c/dd/2234eab22353ffc7d94e8d13177aaa050113286e93e7b40eae01fbf7c3d9/certifi-2023.7.22-py3-none-any.whl",
"version": "2023.7.22"
},
"cffi": {
"sha256": "7b78010e7b97fef4bee1e896df8a4bbb6712b7f05b7ef630f9d1da00f6444d2e",
"type": "url",
"url": "https://files.pythonhosted.org/packages/9b/89/a31c81e36bbb793581d8bba4406a8aac4ba84b2559301c44eef81f4cf5df/cffi-1.16.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl",
"version": "1.16.0"
},
"charset-normalizer": {
"sha256": "ae55d592b02c4349525b6ed8f74c692509e5adffa842e582c0f861751701a673",
"type": "url",
"url": "https://files.pythonhosted.org/packages/ae/e5/8c290f1dd50aae55d1ec20420a6df3c051d6f5ad78ee5b88b1a7ef26634b/charset_normalizer-3.3.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl",
"version": "3.3.1"
},
"click": {
"sha256": "ae74fb96c20a0277a1d615f1e4d73c8414f5a98db8b799a7931d1582f3390c28",
"type": "url",
"url": "https://files.pythonhosted.org/packages/00/2e/d53fa4befbf2cfa713304affc7ca780ce4fc1fd8710527771b58311a3229/click-8.1.7-py3-none-any.whl",
"version": "8.1.7"
},
"contourpy": {
"sha256": "b04c2f0adaf255bf756cf08ebef1be132d3c7a06fe6f9877d55640c5e60c72c5",
"type": "url",
"url": "https://files.pythonhosted.org/packages/b7/f6/78f60fa0b6ae64971178e2542e8b3ad3ba5f4f379b918ab7b18038a3f897/contourpy-1.1.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl",
"version": "1.1.1"
},
"cycler": {
"sha256": "85cef7cff222d8644161529808465972e51340599459b8ac3ccbac5a854e0d30",
"type": "url",
"url": "https://files.pythonhosted.org/packages/e7/05/c19819d5e3d95294a6f5947fb9b9629efb316b96de511b418c53d245aae6/cycler-0.12.1-py3-none-any.whl",
"version": "0.12.1"
},
"einops": {
"sha256": "932b12bb3176caef629cc513fc8a442338fdbfe1e560794a6e7306dcee65a8af",
"type": "url",
"url": "https://files.pythonhosted.org/packages/df/bf/18c6c753fe699c44e3d6013d75074e15f139f9a9adbaeb108f61d73d18d1/einops-0.4.1-py3-none-any.whl",
"version": "0.4.1"
},
"fastapi": {
"sha256": "456482c1178fb7beb2814b88e1885bc49f9a81f079665016feffe3e1c6a7663e",
"type": "url",
"url": "https://files.pythonhosted.org/packages/db/30/b8d323119c37e15b7fa639e65e0eb7d81eb675ba166ac83e695aad3bd321/fastapi-0.104.0-py3-none-any.whl",
"version": "0.104.0"
},
"ffmpy": {
"sha256": "a173b8f42c7c669ff722df7fb31e1e870067713697f745224fa6e621b82f0004",
"type": "url",
"url": "https://files.pythonhosted.org/packages/9a/06/49b275a312eb207e2a2718a7414dedfded05088437352b67aaa9a355f948/ffmpy-0.3.1.tar.gz",
"version": "0.3.1"
},
"filelock": {
"sha256": "a552f4fde758f4eab33191e9548f671970f8b06d436d31388c9aa1e5861a710f",
"type": "url",
"url": "https://files.pythonhosted.org/packages/ea/c8/407364710cb9631ce306a97abff2d61836d603b258b5e5399b5f12a7f787/filelock-3.13.0-py3-none-any.whl",
"version": "3.13.0"
},
"fonttools": {
"sha256": "7bbbf8174501285049e64d174e29f9578495e1b3b16c07c31910d55ad57683d8",
"type": "url",
"url": "https://files.pythonhosted.org/packages/72/2c/7634a6c16b29d0c31cf54051beefab796abdfe8f52abead6d09e5403696e/fonttools-4.43.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl",
"version": "4.43.1"
},
"frozenlist": {
"sha256": "261b9f5d17cac914531331ff1b1d452125bf5daa05faf73b71d935485b0c510b",
"type": "url",
"url": "https://files.pythonhosted.org/packages/e6/7e/74b176a5580e1a41da326d07cf47a0032923fb3eeec9afbd92bb5c6457df/frozenlist-1.4.0-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl",
"version": "1.4.0"
},
"fsspec": {
"sha256": "346a8f024efeb749d2a5fca7ba8854474b1ff9af7c3faaf636a4548781136529",
"type": "url",
"url": "https://files.pythonhosted.org/packages/e8/f6/3eccfb530aac90ad1301c582da228e4763f19e719ac8200752a4841b0b2d/fsspec-2023.10.0-py3-none-any.whl",
"version": "2023.10.0"
},
"gradio": {
"sha256": "ea5c7b2996156d9e1587505e2fd988ed84f5ff29725ebfce663ecee4872edcd3",
"type": "url",
"url": "https://files.pythonhosted.org/packages/df/e7/e0b548208ff5db6323ad974f094e9435adb0a377f35274196fb74adaf58a/gradio-3.41.2-py3-none-any.whl",
"version": "3.41.2"
},
"gradio-client": {
"sha256": "8e07bddd4c21f76fd218897703df8012c7e95dc74e3660edde78ac89fe4cf284",
"type": "url",
"url": "https://files.pythonhosted.org/packages/fe/85/ec0323f39192c4bee04e8e06e64213aff816b9d1b61c3c8367e75b1c7e10/gradio_client-0.5.0-py3-none-any.whl",
"version": "0.5.0"
},
"h11": {
"sha256": "e3fe4ac4b851c468cc8363d500db52c2ead036020723024a109d37346efaa761",
"type": "url",
"url": "https://files.pythonhosted.org/packages/95/04/ff642e65ad6b90db43e668d70ffb6736436c7ce41fcc549f4e9472234127/h11-0.14.0-py3-none-any.whl",
"version": "0.14.0"
},
"httpcore": {
"sha256": "c2789b767ddddfa2a5782e3199b2b7f6894540b17b16ec26b2c4d8e103510b87",
"type": "url",
"url": "https://files.pythonhosted.org/packages/94/2c/2bde7ff8dd2064395555220cbf7cba79991172bf5315a07eb3ac7688d9f1/httpcore-0.17.3-py3-none-any.whl",
"version": "0.17.3"
},
"httpx": {
"sha256": "06781eb9ac53cde990577af654bd990a4949de37a28bdb4a230d434f3a30b9bd",
"type": "url",
"url": "https://files.pythonhosted.org/packages/ec/91/e41f64f03d2a13aee7e8c819d82ee3aa7cdc484d18c0ae859742597d5aa0/httpx-0.24.1-py3-none-any.whl",
"version": "0.24.1"
},
"huggingface-hub": {
"sha256": "ee0b6b68acbf6aeb6d083ea081e981c277a1104b82ab67fdf6780ff5396830af",
"type": "url",
"url": "https://files.pythonhosted.org/packages/ef/b5/b6107bd65fa4c96fdf00e4733e2fe5729bb9e5e09997f63074bb43d3ab28/huggingface_hub-0.18.0-py3-none-any.whl",
"version": "0.18.0"
},
"idna": {
"sha256": "90b77e79eaa3eba6de819a0c442c0b4ceefc341a7a2ab77d7562bf49f425c5c2",
"type": "url",
"url": "https://download.pytorch.org/whl/idna-3.4-py3-none-any.whl",
"version": "3.4"
},
"importlib-resources": {
"sha256": "aa50258bbfa56d4e33fbd8aa3ef48ded10d1735f11532b8df95388cc6bdb7e83",
"type": "url",
"url": "https://files.pythonhosted.org/packages/65/6e/09d8816b5cb7a4006ef8ad1717a2703ad9f331dae9717d9f22488a2d6469/importlib_resources-6.1.0-py3-none-any.whl",
"version": "6.1.0"
},
"jinja2": {
"sha256": "6088930bfe239f0e6710546ab9c19c9ef35e29792895fed6e6e31a023a182a61",
"type": "url",
"url": "https://download.pytorch.org/whl/Jinja2-3.1.2-py3-none-any.whl",
"version": "3.1.2"
},
"jsonschema": {
"sha256": "cd5f1f9ed9444e554b38ba003af06c0a8c2868131e56bfbef0550fb450c0330e",
"type": "url",
"url": "https://files.pythonhosted.org/packages/0f/bf/a84bc75f069f4f156e1c0d9892fb7325945106c6ecaad9f29d24360872af/jsonschema-4.19.1-py3-none-any.whl",
"version": "4.19.1"
},
"jsonschema-specifications": {
"sha256": "05adf340b659828a004220a9613be00fa3f223f2b82002e273dee62fd50524b1",
"type": "url",
"url": "https://files.pythonhosted.org/packages/1c/24/83349ac2189cc2435e84da3f69ba3c97314d3c0622628e55171c6798ed80/jsonschema_specifications-2023.7.1-py3-none-any.whl",
"version": "2023.7.1"
},
"kiwisolver": {
"sha256": "040c1aebeda72197ef477a906782b5ab0d387642e93bda547336b8957c61022e",
"type": "url",
"url": "https://files.pythonhosted.org/packages/17/ba/17a706b232308e65f57deeccae503c268292e6a091313f6ce833a23093ea/kiwisolver-1.4.5-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl",
"version": "1.4.5"
},
"lightning-utilities": {
"sha256": "918dd90c775719e3855631db6282ad75c14da4c5727c4cebdd1589d865fad03d",
"type": "url",
"url": "https://files.pythonhosted.org/packages/46/ee/8641eeb6a062f383b7d6875604e1f3f83bd2c93a0b4dbcabd3150b32de6e/lightning_utilities-0.9.0-py3-none-any.whl",
"version": "0.9.0"
},
"markupsafe": {
"sha256": "bfce63a9e7834b12b87c64d6b155fdd9b3b96191b6bd334bf37db7ff1fe457f2",
"type": "url",
"url": "https://download.pytorch.org/whl/MarkupSafe-2.1.3-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl",
"version": "2.1.3"
},
"matplotlib": {
"sha256": "eee482731c8c17d86d9ddb5194d38621f9b0f0d53c99006275a12523ab021732",
"type": "url",
"url": "https://files.pythonhosted.org/packages/65/5b/3b8fd7d66043f0638a35fa650570cbe69efd42fe169e5024f9307598b47e/matplotlib-3.8.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl",
"version": "3.8.0"
},
"mpmath": {
"sha256": "a0b2b9fe80bbcd81a6647ff13108738cfb482d481d826cc0e02f5b35e5c88d2c",
"type": "url",
"url": "https://download.pytorch.org/whl/mpmath-1.3.0-py3-none-any.whl",
"version": "1.3.0"
},
"multidict": {
"sha256": "11bdf3f5e1518b24530b8241529d2050014c884cf18b6fc69c0c2b30ca248710",
"type": "url",
"url": "https://files.pythonhosted.org/packages/9d/5a/34bd606569178ad8a931ea4d59cda926b046cfa4c01b0191c2e04cfd44c2/multidict-6.0.4-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl",
"version": "6.0.4"
},
"networkx": {
"sha256": "f18c69adc97877c42332c170849c96cefa91881c99a7cb3e95b7c659ebdc1ec2",
"type": "url",
"url": "https://files.pythonhosted.org/packages/d5/f0/8fbc882ca80cf077f1b246c0e3c3465f7f415439bdea6b899f6b19f61f70/networkx-3.2.1-py3-none-any.whl",
"version": "3.2.1"
},
"numpy": {
"sha256": "58f545efd1108e647604a1b5aa809591ccd2540f468a880bedb97247e72db387",
"type": "url",
"url": "https://files.pythonhosted.org/packages/e8/ad/b935c7421657a032fd2a5332eed098f3b9993a155afceb1daa280ff6611f/numpy-1.23.5-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl",
"version": "1.23.5"
},
"omegaconf": {
"sha256": "d6f2cbf79a992899eb76c6cb1aedfcf0fe7456a8654382edd5ee0c1b199c0657",
"type": "url",
"url": "https://files.pythonhosted.org/packages/98/c3/f00dcd6935c11555db6ad55bdada58706120974cacf9a861a7b948ea0619/omegaconf-2.2.3-py3-none-any.whl",
"version": "2.2.3"
},
"opencv-contrib-python": {
"sha256": "24be748f935552ed22fa23f001d684fdf48035599b1ad8a225f0f3b592e63659",
"type": "url",
"url": "https://files.pythonhosted.org/packages/d6/ca/f109e0a8f33074f0f74cf2677ee0b9bdc025d7fc07b2280afdf7fad38b47/opencv_contrib_python-4.8.0.74-cp37-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl",
"version": "4.8.0.74"
},
"orjson": {
"sha256": "1d0dc4310da8b5f6415949bd5ef937e60aeb0eb6b16f95041b5e43e6200821fb",
"type": "url",
"url": "https://files.pythonhosted.org/packages/5a/23/42d1db93fd31ee9fea79c448ddb511fa574f6f281d3bdfa9e2c7d943296a/orjson-3.9.10-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl",
"version": "3.9.10"
},
"packaging": {
"sha256": "8c491190033a9af7e1d931d0b5dacc2ef47509b34dd0de67ed209b5203fc88c7",
"type": "url",
"url": "https://files.pythonhosted.org/packages/ec/1a/610693ac4ee14fcdf2d9bf3c493370e4f2ef7ae2e19217d7a237ff42367d/packaging-23.2-py3-none-any.whl",
"version": "23.2"
},
"pandas": {
"sha256": "52867d69a54e71666cd184b04e839cff7dfc8ed0cd6b936995117fdae8790b69",
"type": "url",
"url": "https://files.pythonhosted.org/packages/f1/c5/1e9c317a5e6af9280ad86a523ab6efe2ca70a0eb4bfb2220d8d08e255ae1/pandas-2.1.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl",
"version": "2.1.2"
},
"pillow": {
"sha256": "bdd0de2d64688ecae88dd8935012c4a72681e5df632af903a1dca8c5e7aa871a",
"type": "url",
"url": "https://files.pythonhosted.org/packages/f4/2c/aa1eefda3538b661c1fd2310f19e82b7ee09c5362ab1f8f03b6e69ef5bfb/Pillow-9.2.0-cp311-cp311-manylinux_2_28_x86_64.whl",
"version": "9.2.0"
},
"psutil": {
"sha256": "89518112647f1276b03ca97b65cc7f64ca587b1eb0278383017c2a0dcc26cbe4",
"type": "url",
"url": "https://files.pythonhosted.org/packages/af/4d/389441079ecef400e2551a3933224885a7bde6b8a4810091d628cdd75afe/psutil-5.9.5-cp36-abi3-manylinux_2_12_x86_64.manylinux2010_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl",
"version": "5.9.5"
},
"pycparser": {
"sha256": "8ee45429555515e1f6b185e78100aea234072576aa43ab53aefcae078162fca9",
"type": "url",
"url": "https://files.pythonhosted.org/packages/62/d5/5f610ebe421e85889f2e55e33b7f9a6795bd982198517d912eb1c76e1a53/pycparser-2.21-py2.py3-none-any.whl",
"version": "2.21"
},
"pydantic": {
"sha256": "bc3ddf669d234f4220e6e1c4d96b061abe0998185a8d7855c0126782b7abc8c1",
"type": "url",
"url": "https://files.pythonhosted.org/packages/73/66/0a72c9fcde42e5650c8d8d5c5c1873b9a3893018020c77ca8eb62708b923/pydantic-2.4.2-py3-none-any.whl",
"version": "2.4.2"
},
"pydantic-core": {
"sha256": "caa48fc31fc7243e50188197b5f0c4228956f97b954f76da157aae7f67269ae8",
"type": "url",
"url": "https://files.pythonhosted.org/packages/39/09/120c06a52ed4bb1022d060bec0a16e5deb4ce79a1c4c11ef9519bc32b59f/pydantic_core-2.10.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl",
"version": "2.10.1"
},
"pydub": {
"sha256": "65617e33033874b59d87db603aa1ed450633288aefead953b30bded59cb599a6",
"type": "url",
"url": "https://files.pythonhosted.org/packages/a6/53/d78dc063216e62fc55f6b2eebb447f6a4b0a59f55c8406376f76bf959b08/pydub-0.25.1-py2.py3-none-any.whl",
"version": "0.25.1"
},
"pygit2": {
"sha256": "ec04c27be5d5af1ceecdcc0464e07081222f91f285f156dc53b23751d146569a",
"type": "url",
"url": "https://files.pythonhosted.org/packages/4c/e1/612235c7111452a417b4bb53a55aa6c1a59d18d2b18b51bf9ee26eae32d3/pygit2-1.12.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl",
"version": "1.12.2"
},
"pyparsing": {
"sha256": "32c7c0b711493c72ff18a981d24f28aaf9c1fb7ed5e9667c9e84e3db623bdbfb",
"type": "url",
"url": "https://files.pythonhosted.org/packages/39/92/8486ede85fcc088f1b3dba4ce92dd29d126fd96b0008ea213167940a2475/pyparsing-3.1.1-py3-none-any.whl",
"version": "3.1.1"
},
"python-dateutil": {
"sha256": "961d03dc3453ebbc59dbdea9e4e11c5651520a876d0f4db161e8674aae935da9",
"type": "url",
"url": "https://files.pythonhosted.org/packages/36/7a/87837f39d0296e723bb9b62bbb257d0355c7f6128853c78955f57342a56d/python_dateutil-2.8.2-py2.py3-none-any.whl",
"version": "2.8.2"
},
"python-multipart": {
"sha256": "ee698bab5ef148b0a760751c261902cd096e57e10558e11aca17646b74ee1c18",
"type": "url",
"url": "https://files.pythonhosted.org/packages/b4/ff/b1e11d8bffb5e0e1b6d27f402eeedbeb9be6df2cdbc09356a1ae49806dbf/python_multipart-0.0.6-py3-none-any.whl",
"version": "0.0.6"
},
"pytorch-lightning": {
"sha256": "a2d2bd7657716087c294b076fe385ed17879764d6daaad0a541394a8f7164f93",
"type": "url",
"url": "https://files.pythonhosted.org/packages/ce/ac/09980114432e759e56e8ff35c16d05dd7c8c0f512c9a88a91c5110272a1f/pytorch_lightning-1.9.4-py3-none-any.whl",
"version": "1.9.4"
},
"pytz": {
"sha256": "ce42d816b81b68506614c11e8937d3aa9e41007ceb50bfdcb0749b921bf646c7",
"type": "url",
"url": "https://files.pythonhosted.org/packages/32/4d/aaf7eff5deb402fd9a24a1449a8119f00d74ae9c2efa79f8ef9994261fc2/pytz-2023.3.post1-py2.py3-none-any.whl",
"version": "2023.3.post1"
},
"pyyaml": {
"sha256": "432557aa2c09802be39460360ddffd48156e30721f5e8d917f01d31694216782",
"type": "url",
"url": "https://files.pythonhosted.org/packages/56/8f/e8b49ad21d26111493dc2d5cae4d7efbd0e2e065440665f5023515f87f64/PyYAML-6.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl",
"version": "6.0"
},
"referencing": {
"sha256": "449b6669b6121a9e96a7f9e410b245d471e8d48964c67113ce9afe50c8dd7bdf",
"type": "url",
"url": "https://files.pythonhosted.org/packages/be/8e/56d6f1e2d591f4d6cbcba446cac4a1b0dc4f584537e2071d9bcee8eeab6b/referencing-0.30.2-py3-none-any.whl",
"version": "0.30.2"
},
"regex": {
"sha256": "8d1f21af4c1539051049796a0f50aa342f9a27cde57318f2fc41ed50b0dbc4ac",
"type": "url",
"url": "https://files.pythonhosted.org/packages/f2/b8/b1ec82fce93064a73ba67f2bb158ec9cac4a0e8f0b6942268ec963947329/regex-2023.10.3-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl",
"version": "2023.10.3"
},
"requests": {
"sha256": "58cd2187c01e70e6e26505bca751777aa9f2ee0b7f4300988b709f44e013003f",
"type": "url",
"url": "https://files.pythonhosted.org/packages/70/8e/0e2d847013cb52cd35b38c009bb167a1a26b2ce6cd6965bf26b47bc0bf44/requests-2.31.0-py3-none-any.whl",
"version": "2.31.0"
},
"rpds-py": {
"sha256": "7bf347b495b197992efc81a7408e9a83b931b2f056728529956a4d0858608b80",
"type": "url",
"url": "https://files.pythonhosted.org/packages/ae/40/1904de90ca6d27fa05a47ff455e751da6ad3933de2dbadd31776f8c48101/rpds_py-0.10.6-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl",
"version": "0.10.6"
},
"safetensors": {
"sha256": "997a2cc14023713f423e6d16536d55cb16a3d72850f142e05f82f0d4c76d383b",
"type": "url",
"url": "https://files.pythonhosted.org/packages/a9/3e/28bd47b8d0f709b680d9e5d5ff715df187adb1f806fde72478049d691873/safetensors-0.3.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl",
"version": "0.3.1"
},
"scipy": {
"sha256": "abaf921531b5aeaafced90157db505e10345e45038c39e5d9b6c7922d68085cb",
"type": "url",
"url": "https://files.pythonhosted.org/packages/92/f9/7ae2c1ae200212bc84b5a8369a10d644aa8b588140fe292d59db3b4a2545/scipy-1.9.3-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl",
"version": "1.9.3"
},
"semantic-version": {
"sha256": "de78a3b8e0feda74cabc54aab2da702113e33ac9d9eb9d2389bcf1f58b7d9177",
"type": "url",
"url": "https://files.pythonhosted.org/packages/6a/23/8146aad7d88f4fcb3a6218f41a60f6c2d4e3a72de72da1825dc7c8f7877c/semantic_version-2.10.0-py2.py3-none-any.whl",
"version": "2.10.0"
},
"setuptools": {
"sha256": "b454a35605876da60632df1a60f736524eb73cc47bbc9f3f1ef1b644de74fd2a",
"type": "url",
"url": "https://files.pythonhosted.org/packages/bb/26/7945080113158354380a12ce26873dd6c1ebd88d47f5bc24e2c5bb38c16a/setuptools-68.2.2-py3-none-any.whl",
"version": "68.2.2"
},
"six": {
"sha256": "8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254",
"type": "url",
"url": "https://files.pythonhosted.org/packages/d9/5a/e7c31adbe875f2abbb91bd84cf2dc52d792b5a01506781dbcf25c91daf11/six-1.16.0-py2.py3-none-any.whl",
"version": "1.16.0"
},
"sniffio": {
"sha256": "eecefdce1e5bbfb7ad2eeaabf7c1eeb404d7757c379bd1f7e5cce9d8bf425384",
"type": "url",
"url": "https://files.pythonhosted.org/packages/c3/a0/5dba8ed157b0136607c7f2151db695885606968d1fae123dc3391e0cfdbf/sniffio-1.3.0-py3-none-any.whl",
"version": "1.3.0"
},
"starlette": {
"sha256": "918416370e846586541235ccd38a474c08b80443ed31c578a418e2209b3eef91",
"type": "url",
"url": "https://files.pythonhosted.org/packages/58/f8/e2cca22387965584a409795913b774235752be4176d276714e15e1a58884/starlette-0.27.0-py3-none-any.whl",
"version": "0.27.0"
},
"sympy": {
"sha256": "c3588cd4295d0c0f603d0f2ae780587e64e2efeedb3521e46b9bb1d08d184fa5",
"type": "url",
"url": "https://download.pytorch.org/whl/sympy-1.12-py3-none-any.whl",
"version": "1.12"
},
"tokenizers": {
"sha256": "9ba2b0bf01777c9b9bc94b53764d6684554ce98551fec496f71bc5be3a03e98b",
"type": "url",
"url": "https://files.pythonhosted.org/packages/e9/d9/660f08ecd88bed54df9f85cab44e01184733c8e42d79b583fb985f1dc412/tokenizers-0.13.3-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl",
"version": "0.13.3"
},
"toolz": {
"sha256": "2059bd4148deb1884bb0eb770a3cde70e7f954cfbbdc2285f1f2de01fd21eb6f",
"type": "url",
"url": "https://files.pythonhosted.org/packages/7f/5c/922a3508f5bda2892be3df86c74f9cf1e01217c2b1f8a0ac4841d903e3e9/toolz-0.12.0-py3-none-any.whl",
"version": "0.12.0"
},
"torch": {
"sha256": "aa984599c2c4ffbc57c48d0d965cbe832e610c967e8179d4ac0a582c733fe112",
"type": "url",
"url": "https://download.pytorch.org/whl/cu121/torch-2.1.0%2Bcu121-cp311-cp311-linux_x86_64.whl",
"version": "2.1.0+cu121"
},
"torchmetrics": {
"sha256": "da2cb18822b285786d082c40efb9e1d861aac425f58230234fe6ce233cf002f8",
"type": "url",
"url": "https://files.pythonhosted.org/packages/a3/88/cc27059747ddecff744826e38014822023cbfff4ca079a6ee9a96602dd0b/torchmetrics-1.2.0-py3-none-any.whl",
"version": "1.2.0"
},
"torchsde": {
"sha256": "4c34373a94a357bdf60bbfee00c850f3563d634491555820b900c9a4f7eff300",
"type": "url",
"url": "https://files.pythonhosted.org/packages/73/8d/efd3e7b31ea854d0bd6886aa3cf44914adce113a6d460850af41ac1dd4dd/torchsde-0.2.5-py3-none-any.whl",
"version": "0.2.5"
},
"torchvision": {
"sha256": "7a325270c7806571ceddbd27c8ece5c163cceb476f09dcca7eb5157073216b22",
"type": "url",
"url": "https://download.pytorch.org/whl/cu121/torchvision-0.16.0%2Bcu121-cp311-cp311-linux_x86_64.whl",
"version": "0.16.0+cu121"
},
"tqdm": {
"sha256": "6fee160d6ffcd1b1c68c65f14c829c22832bc401726335ce92c52d395944a6a1",
"type": "url",
"url": "https://download.pytorch.org/whl/tqdm-4.64.1-py2.py3-none-any.whl",
"version": "4.64.1"
},
"trampoline": {
"sha256": "36cc9a4ff9811843d177fc0e0740efbd7da39eadfe6e50c9e2937cbc06d899d9",
"type": "url",
"url": "https://files.pythonhosted.org/packages/73/54/d2805324fb746d8da86d3844bee4f55c0cfd6c136de61b713772d44c5bea/trampoline-0.1.2-py3-none-any.whl",
"version": "0.1.2"
},
"transformers": {
"sha256": "c332e3a3097f9ed89ce556b403251235931c00237b8bc2d7adaa19d226c13f1d",
"type": "url",
"url": "https://files.pythonhosted.org/packages/5b/0b/e45d26ccd28568013523e04f325432ea88a442b4e3020b757cf4361f0120/transformers-4.30.2-py3-none-any.whl",
"version": "4.30.2"
},
"triton": {
"sha256": "919b06453f0033ea52c13eaf7833de0e57db3178d23d4e04f9fc71c4f2c32bf8",
"type": "url",
"url": "https://download.pytorch.org/whl/triton-2.1.0-0-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.whl",
"version": "2.1.0"
},
"typing-extensions": {
"sha256": "8f92fc8806f9a6b641eaa5318da32b44d401efaac0f6678c9bc448ba3605faa0",
"type": "url",
"url": "https://files.pythonhosted.org/packages/24/21/7d397a4b7934ff4028987914ac1044d3b7d52712f30e2ac7a2ae5bc86dd0/typing_extensions-4.8.0-py3-none-any.whl",
"version": "4.8.0"
},
"tzdata": {
"sha256": "7e65763eef3120314099b6939b5546db7adce1e7d6f2e179e3df563c70511eda",
"type": "url",
"url": "https://files.pythonhosted.org/packages/d5/fb/a79efcab32b8a1f1ddca7f35109a50e4a80d42ac1c9187ab46522b2407d7/tzdata-2023.3-py2.py3-none-any.whl",
"version": "2023.3"
},
"urllib3": {
"sha256": "fdb6d215c776278489906c2f8916e6e7d4f5a9b602ccbcfdf7f016fc8da0596e",
"type": "url",
"url": "https://files.pythonhosted.org/packages/d2/b2/b157855192a68541a91ba7b2bbcb91f1b4faa51f8bae38d8005c034be524/urllib3-2.0.7-py3-none-any.whl",
"version": "2.0.7"
},
"uvicorn": {
"sha256": "1f9be6558f01239d4fdf22ef8126c39cb1ad0addf76c40e760549d2c2f43ab53",
"type": "url",
"url": "https://files.pythonhosted.org/packages/79/96/b0882a1c3f7ef3dd86879e041212ae5b62b4bd352320889231cc735a8e8f/uvicorn-0.23.2-py3-none-any.whl",
"version": "0.23.2"
},
"websockets": {
"sha256": "def07915168ac8f7853812cc593c71185a16216e9e4fa886358a17ed0fd9fcf6",
"type": "url",
"url": "https://files.pythonhosted.org/packages/a9/5e/b25c60067d700e811dccb4e3c318eeadd3a19d8b3620de9f97434af777a7/websockets-11.0.3-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl",
"version": "11.0.3"
},
"xformers": {
"sha256": "479a42055ab23a9cfc0d329656d12cc7e6a6e71b49ae4874bd01d8276dfd47ef",
"type": "url",
"url": "https://download.pytorch.org/whl/cu121/xformers-0.0.22.post7-cp311-cp311-manylinux2014_x86_64.whl",
"version": "0.0.22.post7"
},
"yarl": {
"sha256": "159d81f22d7a43e6eabc36d7194cb53f2f15f498dbbfa8edc8a3239350f59fe7",
"type": "url",
"url": "https://files.pythonhosted.org/packages/ee/8d/55467943a172b97c1b5d9569433c1a70f86f1f9b0f1c6574285f8ad02fc2/yarl-1.9.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl",
"version": "1.9.2"
}
},
"targets": {
"default": {
"accelerate": [
"numpy",
"packaging",
"psutil",
"pyyaml",
"torch"
],
"aiofiles": [],
"aiohttp": [
"aiosignal",
"async-timeout",
"attrs",
"charset-normalizer",
"frozenlist",
"multidict",
"yarl"
],
"aiosignal": [
"frozenlist"
],
"altair": [
"jinja2",
"jsonschema",
"numpy",
"packaging",
"pandas",
"toolz"
],
"annotated-types": [],
"antlr4-python3-runtime": [],
"anyio": [
"idna",
"sniffio"
],
"async-timeout": [],
"attrs": [],
"boltons": [],
"certifi": [],
"cffi": [
"pycparser"
],
"charset-normalizer": [],
"click": [],
"contourpy": [
"numpy"
],
"cycler": [],
"einops": [],
"fastapi": [
"anyio",
"pydantic",
"starlette",
"typing-extensions"
],
"ffmpy": [],
"filelock": [],
"fonttools": [],
"frozenlist": [],
"fsspec": [],
"gradio": [
"aiofiles",
"altair",
"fastapi",
"ffmpy",
"gradio-client",
"httpx",
"huggingface-hub",
"importlib-resources",
"jinja2",
"markupsafe",
"matplotlib",
"numpy",
"orjson",
"packaging",
"pandas",
"pillow",
"pydantic",
"pydub",
"python-multipart",
"pyyaml",
"requests",
"semantic-version",
"typing-extensions",
"uvicorn",
"websockets"
],
"gradio-client": [
"fsspec",
"httpx",
"huggingface-hub",
"packaging",
"requests",
"typing-extensions",
"websockets"
],
"h11": [],
"httpcore": [
"anyio",
"certifi",
"h11",
"sniffio"
],
"httpx": [
"certifi",
"httpcore",
"idna",
"sniffio"
],
"huggingface-hub": [
"filelock",
"fsspec",
"packaging",
"pyyaml",
"requests",
"tqdm",
"typing-extensions"
],
"idna": [],
"importlib-resources": [],
"jinja2": [
"markupsafe"
],
"jsonschema": [
"attrs",
"jsonschema-specifications",
"referencing",
"rpds-py"
],
"jsonschema-specifications": [
"referencing"
],
"kiwisolver": [],
"lightning-utilities": [
"packaging",
"typing-extensions"
],
"markupsafe": [],
"matplotlib": [
"contourpy",
"cycler",
"fonttools",
"kiwisolver",
"numpy",
"packaging",
"pillow",
"pyparsing",
"python-dateutil"
],
"mpmath": [],
"multidict": [],
"networkx": [],
"numpy": [],
"omegaconf": [
"antlr4-python3-runtime",
"pyyaml"
],
"opencv-contrib-python": [
"numpy"
],
"orjson": [],
"packaging": [],
"pandas": [
"numpy",
"python-dateutil",
"pytz",
"tzdata"
],
"pillow": [],
"psutil": [],
"pycparser": [],
"pydantic": [
"annotated-types",
"pydantic-core",
"typing-extensions"
],
"pydantic-core": [
"typing-extensions"
],
"pydub": [],
"pygit2": [
"cffi"
],
"pyparsing": [],
"python-dateutil": [
"six"
],
"python-multipart": [],
"pytorch-lightning": [
"fsspec",
"lightning-utilities",
"numpy",
"packaging",
"pyyaml",
"torch",
"torchmetrics",
"tqdm",
"typing-extensions"
],
"pytz": [],
"pyyaml": [],
"referencing": [
"attrs",
"rpds-py"
],
"regex": [],
"requests": [
"certifi",
"charset-normalizer",
"idna",
"urllib3"
],
"rpds-py": [],
"safetensors": [],
"scipy": [
"numpy"
],
"semantic-version": [],
"setuptools": [],
"six": [],
"sniffio": [],
"starlette": [
"anyio"
],
"sympy": [
"mpmath"
],
"tokenizers": [],
"toolz": [],
"torch": [
"filelock",
"fsspec",
"jinja2",
"networkx",
"sympy",
"triton",
"typing-extensions"
],
"torchmetrics": [
"lightning-utilities",
"numpy",
"torch"
],
"torchsde": [
"boltons",
"numpy",
"scipy",
"torch",
"trampoline"
],
"torchvision": [
"numpy",
"pillow",
"requests",
"torch"
],
"tqdm": [],
"trampoline": [],
"transformers": [
"filelock",
"huggingface-hub",
"numpy",
"packaging",
"pyyaml",
"regex",
"requests",
"safetensors",
"tokenizers",
"tqdm"
],
"triton": [
"filelock"
],
"typing-extensions": [],
"tzdata": [],
"urllib3": [],
"uvicorn": [
"click",
"h11"
],
"websockets": [],
"xformers": [
"numpy",
"torch"
],
"yarl": [
"idna",
"multidict"
]
}
}
},
"invalidationHash": "2bd5c51c4d88ceae32116991fa55c3c4c616cee249a9e6e9dba7fe433194079c"
}

139
pkgs/fooocus/module.nix Normal file
View File

@ -0,0 +1,139 @@
{ config, lib, pkgs, ... }:
let cfg = config.services.fooocus; in
{
options.services.fooocus = with lib; {
enable = mkEnableOption "Fooocus";
package = mkOption {
type = types.package;
description = "The package name of the Fooocus server";
default = pkgs.fooocus;
};
port = mkOption {
type = types.int;
description = "The port to run the Fooocus server on";
default = 7860;
};
listen = mkOption {
type = types.str;
description = "The address to listen on";
default = "127.0.0.1";
};
path = {
models = mkOption {
type = types.path;
description = "The path to the models directory";
default = "/var/models/Fooocus/models";
};
outputs = mkOption {
type = types.path;
description = "The path to the outputs directory";
default = "/var/sd/outputs/sdxl";
};
checkpoints = mkOption {
type = types.path;
description = "The path to the checkpoints directory";
default = "${cfg.path.models}/checkpoints";
};
loras = mkOption {
type = types.path;
description = "The path to the loras directory";
default = "${cfg.path.models}/loras";
};
embeddings = mkOption {
type = types.path;
description = "The path to the embeddings directory";
default = "${cfg.path.models}/embeddings";
};
vae_approx = mkOption {
type = types.path;
description = "The path to the vae_approx directory";
default = "${cfg.path.models}/vae_approx";
};
upscale_models = mkOption {
type = types.path;
description = "The path to the upscale_models directory";
default = "${cfg.path.models}/upscale_models";
};
inpaint = mkOption {
type = types.path;
description = "The path to the inpaint directory";
default = "${cfg.path.models}/inpaint";
};
controlnet = mkOption {
type = types.path;
description = "The path to the controlnet directory";
default = "${cfg.path.models}/controlnet";
};
clip_vision = mkOption {
type = types.path;
description = "The path to the clip_vision directory";
default = "${cfg.path.models}/clip_vision";
};
fooocus_expansion = mkOption {
type = types.path;
description = "The path to the fooocus_expansion directory";
default = "${cfg.path.models}/prompt_expansion/fooocus_expansion";
};
};
config = mkOption {
type = types.attrsOf types.str;
description = "The configuration for the Fooocus server";
default = {
"path_checkpoints" = "${cfg.path.checkpoints}";
"path_loras" = "${cfg.path.loras}";
"path_embeddings" = "${cfg.path.embeddings}";
"path_vae_approx" = "${cfg.path.vae_approx}";
"path_upscale_models" = "${cfg.path.upscale_models}";
"path_inpaint" = "${cfg.path.inpaint}";
"path_controlnet" = "${cfg.path.controlnet}";
"path_clip_vision" = "${cfg.path.clip_vision}";
"path_fooocus_expansion" = "${cfg.path.fooocus_expansion}";
"path_outputs" = "${cfg.path.outputs}";
};
};
};
config = let
configFile = pkgs.writeText "config.json" (builtins.toJSON cfg.config);
in lib.mkIf cfg.enable {
systemd.services.fooocus = {
description = "Fooocus server";
after = [ "network.target" ];
wantedBy = [ "multi-user.target" ];
serviceConfig = {
Type = "simple";
# it wants to write for no good reason
# todo: remove these symlinks
ExecStartPre = pkgs.writeShellScript "pre-start" ''
cp ${configFile} /var/lib/fooocus/config.txt
chmod +w /var/lib/fooocus/config.txt
mkdir /tmp/fooocus
ln -sfn ${cfg.package}/javascript /var/lib/fooocus/javascript
ln -sfn ${cfg.package}/css /var/lib/fooocus/css
'';
ExecStart = "${cfg.package}/webui.py --port ${toString cfg.port} --disable-auto-launch --listen ${cfg.listen}";
Restart = "always";
RestartSec = "10";
User = "fooocus";
Group = "fooocus";
PrivateTmp = true;
ProtectSystem = "full";
ProtectHome = true;
NoNewPrivileges = true;
WorkingDirectory = "/var/lib/fooocus";
ReadWritePaths = [
"/var/lib/fooocus"
"/var/models/Fooocus"
"/var/sd/outputs/sdxl"
];
};
};
users.users.fooocus = {
isSystemUser = true;
createHome = true;
group = "fooocus";
home = "/var/lib/fooocus";
};
users.groups.fooocus = {};
};
}

72
pkgs/fooocus/package.nix Normal file
View File

@ -0,0 +1,72 @@
{ dream2nix, config, lib, ... }: {
imports = [ dream2nix.modules.dream2nix.pip ];
name = "Fooocus";
version = "2.1.807";
mkDerivation = {
src = config.deps.fetchFromGitHub {
owner = "yorickvP";
repo = config.name;
rev = "cc11a770ea8db7573ae58b9b8fc30edabaa4a146";
hash = "sha256-9DV9r1GG3vVwsx+0KYXL3Sd8g5qjSShbBWa1j74BnUs=";
};
buildPhase = "true";
installPhase = ''
mkdir $out
cp -r ./* $out
ln -s /tmp/fooocus $out/input
for f in $out/{launch,webui}.py; do
chmod +x $f
sed -i '1s;^;#!/usr/bin/env python\n;' $f
wrapProgram $f --set PYTHONPATH "$PYTHONPATH:$out/backend/headless"
done
'';
};
buildPythonPackage.format = "other";
deps = { nixpkgs, ... }: {
inherit (nixpkgs) fetchFromGitHub;
inherit (nixpkgs.cudaPackages_12_1) cudatoolkit cudnn;
};
pip = {
drvs = {
torch.env.appendRunpaths = [ "/run/opengl-driver/lib" "$ORIGIN" ];
# libnvToolsExt.so
torch.mkDerivation.buildInputs = [ config.deps.cudatoolkit ];
# libcudart.so.12
torchvision.mkDerivation.buildInputs = [ config.deps.cudatoolkit.lib ];
# libcudart.so.12
xformers.mkDerivation.buildInputs = [ config.deps.cudatoolkit.lib ];
};
pypiSnapshotDate = "2023-10-29";
flattenDependencies = true;
buildDependencies.setuptools = false;
requirementsList = [
"torchsde==0.2.5"
"einops==0.4.1"
"transformers==4.30.2"
"safetensors==0.3.1"
"accelerate==0.21.0"
"pyyaml==6.0"
"Pillow==9.2.0"
"scipy==1.9.3"
"tqdm==4.64.1"
"psutil==5.9.5"
"numpy==1.23.5"
"pytorch_lightning==1.9.4"
"omegaconf==2.2.3"
"gradio==3.41.2"
"pygit2==1.12.2"
"opencv-contrib-python==4.8.0.74"
"torch==2.1.0+cu121"
"torchvision==0.16.0"
"xformers>=0.0.20"
"triton"
"setuptools"
"httpx==0.24.1"
"--extra-index-url" "https://download.pytorch.org/whl/cu121"
];
};
}

26
pkgs/grott.nix Normal file
View File

@ -0,0 +1,26 @@
{ stdenv, python3, fetchFromGitHub, makeWrapper }:
let
python = python3.withPackages (p: [ p.paho-mqtt p.libscrc ]);
in
stdenv.mkDerivation (o: {
pname = "grott";
version = "2.7.8";
src = fetchFromGitHub {
owner = "johanmeijer";
repo = o.pname;
rev = "cb7e3db8a9ea2ab11fad062d68a3e98e6a87cedf";
sha256 = "rFxSQZypa+G45jj/ktJLlqfMIp1yHoEmfzB1BvHLeLo=";
};
nativeBuildInputs = [ makeWrapper ];
buildPhase = "true";
installPhase = ''
mkdir -p $out/share/grott
cp *.py examples/recwl.txt examples/Home\ Assistent/grott_ha.py $out/share/grott/
makeWrapper ${python}/bin/python3 $out/bin/grott \
--add-flags $out/share/grott/grott.py
'';
meta = with stdenv.lib; {
description = "Grott is a program to read data from a Growatt inverter and send it to a MQTT broker";
homepage = o.src.homePage;
};
})

22
pkgs/libscrc.nix Normal file
View File

@ -0,0 +1,22 @@
{ lib, buildPythonPackage, fetchPypi }:
buildPythonPackage rec {
pname = "libscrc";
version = "1.8.1";
src = fetchPypi {
inherit pname version;
hash = "sha256-17pr8jz96ztynQrTeV9sb5fY6kFVJS48qfFHWHArp8g=";
};
propagatedBuildInputs = [];
pythonImportsCheck = [ "libscrc" ];
meta = with lib; {
description = "A library for calculating CRC, CRC-ITU, CRC-32, CRC-16, CRC-CCITT";
homepage = "https://github.com/hex-in/libscrc";
license = licenses.mit;
maintainers = with maintainers; [ yorickvp ];
};
}

29
pkgs/llm.nix Normal file
View File

@ -0,0 +1,29 @@
{ flake-inputs, pkgs, python3, runCommand }:
let
dream2nix = flake-inputs.dream2nix;
module = { dream2nix, config, lib, ... }: {
imports = [ dream2nix.modules.dream2nix.pip ];
name = "llm-env";
deps.python = python3;
version = "0.13.1";
pip.requirementsList = [
"llm==0.13.1"
"llm-claude-3==0.3"
"llm-replicate==0.3.1"
];
pip.flattenDependencies = true;
public = config.pip.env;
paths.projectRoot = ./..;
paths.package = "pkgs/llm";
};
packages = dream2nix.lib.evalModules {
packageSets.nixpkgs = pkgs;
modules = [ module ];
};
pyEnv = packages.config.public.pyEnv;
in
runCommand "llm" {} ''
mkdir -p $out/bin
cp ${pyEnv}/bin/llm $_
''

397
pkgs/llm/lock.json Normal file
View File

@ -0,0 +1,397 @@
{
"fetchPipMetadata": {
"sources": {
"annotated-types": {
"sha256": "0641064de18ba7a25dee8f96403ebc39113d0cb953a01429249d5c7564666a43",
"type": "url",
"url": "https://files.pythonhosted.org/packages/28/78/d31230046e58c207284c6b2c4e8d96e6d3cb4e52354721b944d3e1ee4aa5/annotated_types-0.6.0-py3-none-any.whl",
"version": "0.6.0"
},
"anthropic": {
"sha256": "c4736402953c99b643ac452306ff0d33bdd2368a793d5c61fdcecd3331a0a103",
"type": "url",
"url": "https://files.pythonhosted.org/packages/3e/60/0d7f235251d01a4754dbc1430b76a05d3ba9e34bbc5206a033a824900969/anthropic-0.25.6-py3-none-any.whl",
"version": "0.25.6"
},
"anyio": {
"sha256": "048e05d0f6caeed70d731f3db756d35dcc1f35747c8c403364a8332c630441b8",
"type": "url",
"url": "https://files.pythonhosted.org/packages/14/fd/2f20c40b45e4fb4324834aea24bd4afdf1143390242c0b33774da0e2e34f/anyio-4.3.0-py3-none-any.whl",
"version": "4.3.0"
},
"certifi": {
"sha256": "dc383c07b76109f368f6106eee2b593b04a011ea4d55f652c6ca24a754d1cdd1",
"type": "url",
"url": "https://files.pythonhosted.org/packages/ba/06/a07f096c664aeb9f01624f858c3add0a4e913d6c96257acb4fce61e7de14/certifi-2024.2.2-py3-none-any.whl",
"version": "2024.2.2"
},
"charset-normalizer": {
"sha256": "90d558489962fd4918143277a773316e56c72da56ec7aa3dc3dbbe20fdfed15b",
"type": "url",
"url": "https://files.pythonhosted.org/packages/ee/fb/14d30eb4956408ee3ae09ad34299131fb383c47df355ddb428a7331cfa1e/charset_normalizer-3.3.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl",
"version": "3.3.2"
},
"click": {
"sha256": "ae74fb96c20a0277a1d615f1e4d73c8414f5a98db8b799a7931d1582f3390c28",
"type": "url",
"url": "https://files.pythonhosted.org/packages/00/2e/d53fa4befbf2cfa713304affc7ca780ce4fc1fd8710527771b58311a3229/click-8.1.7-py3-none-any.whl",
"version": "8.1.7"
},
"click-default-group": {
"sha256": "9b60486923720e7fc61731bdb32b617039aba820e22e1c88766b1125592eaa5f",
"type": "url",
"url": "https://files.pythonhosted.org/packages/2c/1a/aff8bb287a4b1400f69e09a53bd65de96aa5cee5691925b38731c67fc695/click_default_group-1.2.4-py2.py3-none-any.whl",
"version": "1.2.4"
},
"distro": {
"sha256": "7bffd925d65168f85027d8da9af6bddab658135b840670a223589bc0c8ef02b2",
"type": "url",
"url": "https://files.pythonhosted.org/packages/12/b3/231ffd4ab1fc9d679809f356cebee130ac7daa00d6d6f3206dd4fd137e9e/distro-1.9.0-py3-none-any.whl",
"version": "1.9.0"
},
"filelock": {
"sha256": "404e5e9253aa60ad457cae1be07c0f0ca90a63931200a47d9b6a6af84fd7b45f",
"type": "url",
"url": "https://files.pythonhosted.org/packages/6e/b5/15b3b36f298bcbc0be82a371ac744f4f5a10309ade0b8bbde286598dd612/filelock-3.13.4-py3-none-any.whl",
"version": "3.13.4"
},
"fsspec": {
"sha256": "918d18d41bf73f0e2b261824baeb1b124bcf771767e3a26425cd7dec3332f512",
"type": "url",
"url": "https://files.pythonhosted.org/packages/93/6d/66d48b03460768f523da62a57a7e14e5e95fdf339d79e996ce3cecda2cdb/fsspec-2024.3.1-py3-none-any.whl",
"version": "2024.3.1"
},
"h11": {
"sha256": "e3fe4ac4b851c468cc8363d500db52c2ead036020723024a109d37346efaa761",
"type": "url",
"url": "https://files.pythonhosted.org/packages/95/04/ff642e65ad6b90db43e668d70ffb6736436c7ce41fcc549f4e9472234127/h11-0.14.0-py3-none-any.whl",
"version": "0.14.0"
},
"httpcore": {
"sha256": "421f18bac248b25d310f3cacd198d55b8e6125c107797b609ff9b7a6ba7991b5",
"type": "url",
"url": "https://files.pythonhosted.org/packages/78/d4/e5d7e4f2174f8a4d63c8897d79eb8fe2503f7ecc03282fee1fa2719c2704/httpcore-1.0.5-py3-none-any.whl",
"version": "1.0.5"
},
"httpx": {
"sha256": "71d5465162c13681bff01ad59b2cc68dd838ea1f10e51574bac27103f00c91a5",
"type": "url",
"url": "https://files.pythonhosted.org/packages/41/7b/ddacf6dcebb42466abd03f368782142baa82e08fc0c1f8eaa05b4bae87d5/httpx-0.27.0-py3-none-any.whl",
"version": "0.27.0"
},
"huggingface-hub": {
"sha256": "3429e25f38ccb834d310804a3b711e7e4953db5a9e420cc147a5e194ca90fd17",
"type": "url",
"url": "https://files.pythonhosted.org/packages/05/c0/779afbad8e75565c09ffa24a88b5dd7e293c92b74eb09df6435fc58ac986/huggingface_hub-0.22.2-py3-none-any.whl",
"version": "0.22.2"
},
"idna": {
"sha256": "82fee1fc78add43492d3a1898bfa6d8a904cc97d8427f683ed8e798d07761aa0",
"type": "url",
"url": "https://files.pythonhosted.org/packages/e5/3e/741d8c82801c347547f8a2a06aa57dbb1992be9e948df2ea0eda2c8b79e8/idna-3.7-py3-none-any.whl",
"version": "3.7"
},
"llm": {
"sha256": "05e468e3723097a07dba9d2b87d05f2359e7e436e8b8bd6743074021f4d8169c",
"type": "url",
"url": "https://files.pythonhosted.org/packages/b1/c5/0576fc2698a78c0e47550a1ac19899dee504b74986447fcdb1f8cd00b817/llm-0.13.1-py3-none-any.whl",
"version": "0.13.1"
},
"llm-claude": {
"sha256": "66780648bef588aff6d15aa37596d80ab427879a84272889f45b574c83bcef36",
"type": "url",
"url": "https://files.pythonhosted.org/packages/75/3d/be9dac40df5c4c4ea40188252f6dfa541cd86d3591c28ba04ae2c3fd64a6/llm_claude-0.4.0-py3-none-any.whl",
"version": "0.4.0"
},
"llm-claude-3": {
"sha256": "c7bd1ca94f012137a1c002dff84f34735028b02123003a68ad1ebcc1cf5ab8a5",
"type": "url",
"url": "https://files.pythonhosted.org/packages/bb/7b/c32053b853c2fc6dad705064a942a6b81566ca867bd0e5ac4c28d1093ce6/llm_claude_3-0.3-py3-none-any.whl",
"version": "0.3"
},
"llm-replicate": {
"sha256": "7ae240d7390f0f557b249f3d3889c7cd3015b4a6818747495ca48f31a8a4a177",
"type": "url",
"url": "https://files.pythonhosted.org/packages/7d/b7/2bf20e72b57d463dd3b759773f1a5c675e229c7cb03e7737f9f2f560cfb1/llm_replicate-0.3.1-py3-none-any.whl",
"version": "0.3.1"
},
"openai": {
"sha256": "293a36effde29946eb221040c89c46a4850f2f2e30b37ef09ff6d75226d71b42",
"type": "url",
"url": "https://files.pythonhosted.org/packages/f9/d2/d093a77ae88abaf71ba92db2285d38fcd408961126351fc82d3a6e90f87b/openai-1.23.2-py3-none-any.whl",
"version": "1.23.2"
},
"packaging": {
"sha256": "2ddfb553fdf02fb784c234c7ba6ccc288296ceabec964ad2eae3777778130bc5",
"type": "url",
"url": "https://files.pythonhosted.org/packages/49/df/1fceb2f8900f8639e278b056416d49134fb8d84c5942ffaa01ad34782422/packaging-24.0-py3-none-any.whl",
"version": "24.0"
},
"pip": {
"sha256": "ba0d021a166865d2265246961bec0152ff124de910c5cc39f1156ce3fa7c69dc",
"type": "url",
"url": "https://files.pythonhosted.org/packages/8a/6a/19e9fe04fca059ccf770861c7d5721ab4c2aebc539889e97c7977528a53b/pip-24.0-py3-none-any.whl",
"version": "24.0"
},
"pluggy": {
"sha256": "7db9f7b503d67d1c5b95f59773ebb58a8c1c288129a88665838012cfb07b8981",
"type": "url",
"url": "https://files.pythonhosted.org/packages/a5/5b/0cc789b59e8cc1bf288b38111d002d8c5917123194d45b29dcdac64723cc/pluggy-1.4.0-py3-none-any.whl",
"version": "1.4.0"
},
"pydantic": {
"sha256": "9dee74a271705f14f9a1567671d144a851c675b072736f0a7b2608fd9e495352",
"type": "url",
"url": "https://files.pythonhosted.org/packages/16/ca/330c4f3bd983bb24ac12c7fd1e08c26c8aed70bc64498cf38c770321067f/pydantic-2.7.0-py3-none-any.whl",
"version": "2.7.0"
},
"pydantic-core": {
"sha256": "684d840d2c9ec5de9cb397fcb3f36d5ebb6fa0d94734f9886032dd796c1ead06",
"type": "url",
"url": "https://files.pythonhosted.org/packages/24/a2/4b135f51ca5c0f91fa3cb5b880068e10b23f1bada653f9c14cb5154842db/pydantic_core-2.18.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl",
"version": "2.18.1"
},
"python-dateutil": {
"sha256": "a8b2bc7bffae282281c8140a97d3aa9c14da0b136dfe83f850eea9a5f7470427",
"type": "url",
"url": "https://files.pythonhosted.org/packages/ec/57/56b9bcc3c9c6a792fcbaf139543cee77261f3651ca9da0c93f5c1221264b/python_dateutil-2.9.0.post0-py2.py3-none-any.whl",
"version": "2.9.0.post0"
},
"python-ulid": {
"sha256": "e2c739e27e6d760136e5f411f311cdd3ec9c4c89696932fe803fa09a4dcd6ebe",
"type": "url",
"url": "https://files.pythonhosted.org/packages/05/2f/bfeb04d9cc0fee8738be404e2535eb67f5d8fd78e0c3df5dbad26ecb93bf/python_ulid-2.4.0.post0-py3-none-any.whl",
"version": "2.4.0.post0"
},
"pyyaml": {
"sha256": "6c22bec3fbe2524cde73d7ada88f6566758a8f7227bfbf93a408a9d86bcc12a0",
"type": "url",
"url": "https://files.pythonhosted.org/packages/b4/33/720548182ffa8344418126017aa1d4ab4aeec9a2275f04ce3f3573d8ace8/PyYAML-6.0.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl",
"version": "6.0.1"
},
"replicate": {
"sha256": "9d4caa333d2734ff9fabfb37a882689fb2320dcbef5d5a15eb3113fd2975d88f",
"type": "url",
"url": "https://files.pythonhosted.org/packages/0d/7a/b011aed4b62eb6b40f8a478b05e9946e977ce0ecbb40adec150d6f8ecd4a/replicate-0.25.2-py3-none-any.whl",
"version": "0.25.2"
},
"requests": {
"sha256": "58cd2187c01e70e6e26505bca751777aa9f2ee0b7f4300988b709f44e013003f",
"type": "url",
"url": "https://files.pythonhosted.org/packages/70/8e/0e2d847013cb52cd35b38c009bb167a1a26b2ce6cd6965bf26b47bc0bf44/requests-2.31.0-py3-none-any.whl",
"version": "2.31.0"
},
"requests-mock": {
"sha256": "b1e37054004cdd5e56c84454cc7df12b25f90f382159087f4b6915aaeef39563",
"type": "url",
"url": "https://files.pythonhosted.org/packages/97/ec/889fbc557727da0c34a33850950310240f2040f3b1955175fdb2b36a8910/requests_mock-1.12.1-py2.py3-none-any.whl",
"version": "1.12.1"
},
"setuptools": {
"sha256": "c636ac361bc47580504644275c9ad802c50415c7522212252c033bd15f301f32",
"type": "url",
"url": "https://files.pythonhosted.org/packages/f7/29/13965af254e3373bceae8fb9a0e6ea0d0e571171b80d6646932131d6439b/setuptools-69.5.1-py3-none-any.whl",
"version": "69.5.1"
},
"six": {
"sha256": "8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254",
"type": "url",
"url": "https://files.pythonhosted.org/packages/d9/5a/e7c31adbe875f2abbb91bd84cf2dc52d792b5a01506781dbcf25c91daf11/six-1.16.0-py2.py3-none-any.whl",
"version": "1.16.0"
},
"sniffio": {
"sha256": "2f6da418d1f1e0fddd844478f41680e794e6051915791a034ff65e5f100525a2",
"type": "url",
"url": "https://files.pythonhosted.org/packages/e9/44/75a9c9421471a6c4805dbf2356f7c181a29c1879239abab1ea2cc8f38b40/sniffio-1.3.1-py3-none-any.whl",
"version": "1.3.1"
},
"sqlite-fts4": {
"sha256": "0359edd8dea6fd73c848989e1e2b1f31a50fe5f9d7272299ff0e8dbaa62d035f",
"type": "url",
"url": "https://files.pythonhosted.org/packages/51/29/0096e8b1811aaa78cfb296996f621f41120c21c2f5cd448ae1d54979d9fc/sqlite_fts4-1.0.3-py3-none-any.whl",
"version": "1.0.3"
},
"sqlite-migrate": {
"sha256": "a4125e35e1de3dc56b6b6ec60e9833ce0ce20192b929ddcb2d4246c5098859c6",
"type": "url",
"url": "https://files.pythonhosted.org/packages/df/92/994545b912e6d6feb40323047f02ca039321e690aa2c27afcd5c4105e37b/sqlite_migrate-0.1b0-py3-none-any.whl",
"version": "0.1b0"
},
"sqlite-utils": {
"sha256": "b71e829755c2efbdcd6931a31968dee4e8bd71b3c14f0fe648b22377027c5bec",
"type": "url",
"url": "https://files.pythonhosted.org/packages/3a/70/c1917860d717d50c9cbb3c616afbf5c124e90a1609dccde4540375da3a2d/sqlite_utils-3.36-py3-none-any.whl",
"version": "3.36"
},
"tabulate": {
"sha256": "024ca478df22e9340661486f85298cff5f6dcdba14f3813e8830015b9ed1948f",
"type": "url",
"url": "https://files.pythonhosted.org/packages/40/44/4a5f08c96eb108af5cb50b41f76142f0afa346dfa99d5296fe7202a11854/tabulate-0.9.0-py3-none-any.whl",
"version": "0.9.0"
},
"tokenizers": {
"sha256": "7c9d5b6c0e7a1e979bec10ff960fae925e947aab95619a6fdb4c1d8ff3708ce3",
"type": "url",
"url": "https://files.pythonhosted.org/packages/80/54/12047a69f5b382d7ee72044dc89151a2dd0d13b2c9bdcc22654883704d31/tokenizers-0.19.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl",
"version": "0.19.1"
},
"tqdm": {
"sha256": "1ee4f8a893eb9bef51c6e35730cebf234d5d0b6bd112b0271e10ed7c24a02bd9",
"type": "url",
"url": "https://files.pythonhosted.org/packages/2a/14/e75e52d521442e2fcc9f1df3c5e456aead034203d4797867980de558ab34/tqdm-4.66.2-py3-none-any.whl",
"version": "4.66.2"
},
"typing-extensions": {
"sha256": "c1f94d72897edaf4ce775bb7558d5b79d8126906a14ea5ed1635921406c0387a",
"type": "url",
"url": "https://files.pythonhosted.org/packages/01/f3/936e209267d6ef7510322191003885de524fc48d1b43269810cd589ceaf5/typing_extensions-4.11.0-py3-none-any.whl",
"version": "4.11.0"
},
"urllib3": {
"sha256": "450b20ec296a467077128bff42b73080516e71b56ff59a60a02bef2232c4fa9d",
"type": "url",
"url": "https://files.pythonhosted.org/packages/a2/73/a68704750a7679d0b6d3ad7aa8d4da8e14e151ae82e6fee774e6e0d05ec8/urllib3-2.2.1-py3-none-any.whl",
"version": "2.2.1"
}
},
"targets": {
"default": {
"annotated-types": [],
"anthropic": [
"anyio",
"distro",
"httpx",
"pydantic",
"sniffio",
"tokenizers",
"typing-extensions"
],
"anyio": [
"idna",
"sniffio"
],
"certifi": [],
"charset-normalizer": [],
"click": [],
"click-default-group": [
"click"
],
"distro": [],
"filelock": [],
"fsspec": [],
"h11": [],
"httpcore": [
"certifi",
"h11"
],
"httpx": [
"anyio",
"certifi",
"httpcore",
"idna",
"sniffio"
],
"huggingface-hub": [
"filelock",
"fsspec",
"packaging",
"pyyaml",
"requests",
"tqdm",
"typing-extensions"
],
"idna": [],
"llm": [
"click",
"click-default-group",
"openai",
"pip",
"pluggy",
"pydantic",
"python-ulid",
"pyyaml",
"setuptools",
"sqlite-migrate",
"sqlite-utils"
],
"llm-claude": [
"anthropic",
"llm"
],
"llm-claude-3": [
"anthropic",
"llm",
"llm-claude"
],
"llm-replicate": [
"llm",
"replicate",
"requests-mock"
],
"openai": [
"anyio",
"distro",
"httpx",
"pydantic",
"sniffio",
"tqdm",
"typing-extensions"
],
"packaging": [],
"pip": [],
"pluggy": [],
"pydantic": [
"annotated-types",
"pydantic-core",
"typing-extensions"
],
"pydantic-core": [
"typing-extensions"
],
"python-dateutil": [
"six"
],
"python-ulid": [],
"pyyaml": [],
"replicate": [
"httpx",
"packaging",
"pydantic",
"typing-extensions"
],
"requests": [
"certifi",
"charset-normalizer",
"idna",
"urllib3"
],
"requests-mock": [
"requests"
],
"setuptools": [],
"six": [],
"sniffio": [],
"sqlite-fts4": [],
"sqlite-migrate": [
"sqlite-utils"
],
"sqlite-utils": [
"click",
"click-default-group",
"pluggy",
"python-dateutil",
"sqlite-fts4",
"tabulate"
],
"tabulate": [],
"tokenizers": [
"huggingface-hub"
],
"tqdm": [],
"typing-extensions": [],
"urllib3": []
}
}
},
"invalidationHash": "a0a90a9472b71c79316bbb8602702c9335922aa7f197096042a38f79d632f247"
}

View File

@ -0,0 +1,7 @@
{ lib, buildYarnPackage }:
buildYarnPackage {
src = ./.;
postInstall = ''
rm -rf $out/yarn-cache $out/bin/yarn
'';
}

153
pkgs/marvin-tracker/index.js Executable file
View File

@ -0,0 +1,153 @@
#!/usr/bin/env node
import http from 'node:http';
import * as mqtt from "mqtt"
import { createHash, timingSafeEqual } from "node:crypto"
const settings = {
mqtt_host: process.env.MQTT_HOST || "localhost",
mqtt_username: process.env.MQTT_USER || "guest",
mqtt_password: process.env.MQTT_PASSWORD || "guest",
topic: process.env.TOPIC || "yorick/marvin/tracking",
api_hash: process.env.API_HASH || "z6mzC2TGdVCRuFE+oCrwj1GCHyP6OzYcPKZDiO/yLdqpmChC6S7ijCEUSY5gtqhpXhtYeDRyBjNeVJ/0Se4jQQ==",
listen_port: +process.env.PORT || 3000,
listen_host: process.env.HOST || "::",
}
const client = mqtt.connect(`mqtt://${settings.mqtt_host}`, {
username: settings.mqtt_username,
password: settings.mqtt_password
});
let currently_tracking = {}
client.subscribe(settings.topic)
client.on("connect", () => {
console.log("mqtt connected")
})
client.on("message", (topic, message) => {
if (topic == settings.topic) {
try {
currently_tracking = JSON.parse(message)
} catch(e) {
console.warn("unable to parse message", msg)
}
}
})
function checkKey(password) {
if (typeof password !== "string") return false
// would be nice if this took salt
const h = createHash("blake2b512")
// salt
h.update("O9yn_qX_jz68H-B6BrkEzRGAWfInzgeOmsCajTJVwcw=")
h.update(password)
// more salt
h.update("LHVV58vOGu7pKSV_Ofmes2joHCal6-F9UuhNLvOK7HM=")
const d = h.digest()
return timingSafeEqual(Buffer.from(settings.api_hash, "base64"), d)
}
async function waitForJSON(req, max_size) {
return new Promise((resolve, reject) => {
let body = [];
let accumulatedSize = 0;
req.on('data', (chunk) => {
accumulatedSize += chunk.length;
if (accumulatedSize > max_size) {
reject({statusCode: 413, message: 'Payload too large'});
req.connection.destroy();
} else {
body.push(chunk);
}
});
req.on('end', () => {
try {
const parsedBody = JSON.parse(Buffer.concat(body).toString());
resolve(parsedBody);
} catch (e) {
reject({statusCode: 400, message: 'Bad Request'});
}
});
req.on('error', (err) => {
reject({statusCode: 500, message: 'Internal Server Error'});
});
});
}
const supported_urls = ["startTracking", "stopTracking", "markDoneTask", "deleteTask", "editTask"]
async function setTrack(track) {
track.time = Date.now()
currently_tracking = track
await client.publishAsync(settings.topic, JSON.stringify(track), {
retain: true
})
}
const endpoints = {
async startTracking(task) {
await setTrack({ task, started: true })
},
async stopTracking(task) {
if (task.done) {
await setTrack({})
} else {
await setTrack({ task, started: false })
}
},
async markDoneTask(task) {
if (task._id == currently_tracking.task?._id)
await setTrack({})
},
async deleteTask(task) {
if (task._id == currently_tracking.task?._id)
await setTrack({})
},
async editTask(task) {
if (task._id == currently_tracking.task?._id)
await setTrack({ task, started: currently_tracking.started })
}
}
// todo: check headers
async function handle(req, res) {
console.log(req.method, req.url)
if (endpoints[req.url.slice(1)]) {
res.setHeader('Access-Control-Allow-Origin', '*');
res.setHeader('Access-Control-Allow-Methods', 'POST');
res.setHeader('Access-Control-Allow-Headers', 'Content-Type, X-Marv-Key');
if (req.method == "OPTIONS") {}
else if (req.method == "POST") {
if (!checkKey(req.headers["x-marv-key"])) {
throw { statusCode: 403, message: "auth required" }
}
const body = await waitForJSON(req, 1024 * 512) // 512 kb
await endpoints[req.url.slice(1)](body)
res.end()
} else {
throw { statusCode: 405, message: "Method not supported" }
}
res.end()
} else {
throw { statusCode: 404, message: "Unknown endpoint" }
}
}
const server = http.createServer(async (req, res) => {
try {
await handle(req, res);
} catch (err) {
console.warn("error in request", err)
res.writeHead(err.statusCode || 500, {'Content-Type': 'text/plain'}).end(err.message || 'Internal Server Error');
}
})
server.listen(settings.listen_port, settings.listen_host, () => {
console.log(`Server running on http://${settings.listen_host}:${settings.listen_port}/`);
});

View File

@ -0,0 +1,14 @@
{
"name": "marvin-tracker",
"version": "1.0.0",
"main": "index.js",
"license": "MIT",
"type": "module",
"dependencies": {
"mqtt": "^5.0.5"
},
"private": true,
"bin": {
"server": "./index.js"
}
}

View File

@ -0,0 +1,320 @@
# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
# yarn lockfile v1
"@types/node@*":
version "20.6.4"
resolved "https://registry.yarnpkg.com/@types/node/-/node-20.6.4.tgz#7882cb8b8adc3106c352dac9c02d4d3ebb95cf3e"
integrity sha512-nU6d9MPY0NBUMiE/nXd2IIoC4OLvsLpwAjheoAeuzgvDZA1Cb10QYg+91AF6zQiKWRN5i1m07x6sMe0niBznoQ==
"@types/readable-stream@^4.0.1":
version "4.0.2"
resolved "https://registry.yarnpkg.com/@types/readable-stream/-/readable-stream-4.0.2.tgz#5199cfeef35ea16d0e85076b1c6daa15766634c0"
integrity sha512-hhzOsMEISZ+mX1l+01F0duYt9wHEbCGmjARed0PcQoVS5zAdu7u5YbWYuNGhw09M1MgGr3kfsto+ut/MnAdKqA==
dependencies:
"@types/node" "*"
safe-buffer "~5.1.1"
"@types/ws@^8.5.5":
version "8.5.5"
resolved "https://registry.yarnpkg.com/@types/ws/-/ws-8.5.5.tgz#af587964aa06682702ee6dcbc7be41a80e4b28eb"
integrity sha512-lwhs8hktwxSjf9UaZ9tG5M03PGogvFaH8gUgLNbN9HKIg0dvv6q+gkSuJ8HN4/VbyxkuLzCjlN7GquQ0gUJfIg==
dependencies:
"@types/node" "*"
abort-controller@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/abort-controller/-/abort-controller-3.0.0.tgz#eaf54d53b62bae4138e809ca225c8439a6efb392"
integrity sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==
dependencies:
event-target-shim "^5.0.0"
balanced-match@^1.0.0:
version "1.0.2"
resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee"
integrity sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==
base64-js@^1.3.1:
version "1.5.1"
resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.5.1.tgz#1b1b440160a5bf7ad40b650f095963481903930a"
integrity sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==
bl@^5.0.0:
version "5.1.0"
resolved "https://registry.yarnpkg.com/bl/-/bl-5.1.0.tgz#183715f678c7188ecef9fe475d90209400624273"
integrity sha512-tv1ZJHLfTDnXE6tMHv73YgSJaWR2AFuPwMntBe7XL/GBFHnT0CLnsHMogfk5+GzCDC5ZWarSCYaIGATZt9dNsQ==
dependencies:
buffer "^6.0.3"
inherits "^2.0.4"
readable-stream "^3.4.0"
brace-expansion@^2.0.1:
version "2.0.1"
resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-2.0.1.tgz#1edc459e0f0c548486ecf9fc99f2221364b9a0ae"
integrity sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==
dependencies:
balanced-match "^1.0.0"
buffer-from@^1.0.0:
version "1.1.2"
resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.2.tgz#2b146a6fd72e80b4f55d255f35ed59a3a9a41bd5"
integrity sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==
buffer@^6.0.3:
version "6.0.3"
resolved "https://registry.yarnpkg.com/buffer/-/buffer-6.0.3.tgz#2ace578459cc8fbe2a70aaa8f52ee63b6a74c6c6"
integrity sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==
dependencies:
base64-js "^1.3.1"
ieee754 "^1.2.1"
commist@^3.2.0:
version "3.2.0"
resolved "https://registry.yarnpkg.com/commist/-/commist-3.2.0.tgz#da9c8e5f245ac21510badc4b10c46b5bcc9b56cd"
integrity sha512-4PIMoPniho+LqXmpS5d3NuGYncG6XWlkBSVGiWycL22dd42OYdUGil2CWuzklaJoNxyxUSpO4MKIBU94viWNAw==
concat-stream@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/concat-stream/-/concat-stream-2.0.0.tgz#414cf5af790a48c60ab9be4527d56d5e41133cb1"
integrity sha512-MWufYdFw53ccGjCA+Ol7XJYpAlW6/prSMzuPOTRnJGcGzuhLn4Scrz7qf6o8bROZ514ltazcIFJZevcfbo0x7A==
dependencies:
buffer-from "^1.0.0"
inherits "^2.0.3"
readable-stream "^3.0.2"
typedarray "^0.0.6"
debug@^4.1.1, debug@^4.3.1, debug@^4.3.4:
version "4.3.4"
resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.4.tgz#1319f6579357f2338d3337d2cdd4914bb5dcc865"
integrity sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==
dependencies:
ms "2.1.2"
duplexify@^4.1.2:
version "4.1.2"
resolved "https://registry.yarnpkg.com/duplexify/-/duplexify-4.1.2.tgz#18b4f8d28289132fa0b9573c898d9f903f81c7b0"
integrity sha512-fz3OjcNCHmRP12MJoZMPglx8m4rrFP8rovnk4vT8Fs+aonZoCwGg10dSsQsfP/E62eZcPTMSMP6686fu9Qlqtw==
dependencies:
end-of-stream "^1.4.1"
inherits "^2.0.3"
readable-stream "^3.1.1"
stream-shift "^1.0.0"
end-of-stream@^1.4.1:
version "1.4.4"
resolved "https://registry.yarnpkg.com/end-of-stream/-/end-of-stream-1.4.4.tgz#5ae64a5f45057baf3626ec14da0ca5e4b2431eb0"
integrity sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==
dependencies:
once "^1.4.0"
event-target-shim@^5.0.0:
version "5.0.1"
resolved "https://registry.yarnpkg.com/event-target-shim/-/event-target-shim-5.0.1.tgz#5d4d3ebdf9583d63a5333ce2deb7480ab2b05789"
integrity sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==
events@^3.3.0:
version "3.3.0"
resolved "https://registry.yarnpkg.com/events/-/events-3.3.0.tgz#31a95ad0a924e2d2c419a813aeb2c4e878ea7400"
integrity sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==
fs.realpath@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f"
integrity sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==
glob@^8.0.0:
version "8.1.0"
resolved "https://registry.yarnpkg.com/glob/-/glob-8.1.0.tgz#d388f656593ef708ee3e34640fdfb99a9fd1c33e"
integrity sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ==
dependencies:
fs.realpath "^1.0.0"
inflight "^1.0.4"
inherits "2"
minimatch "^5.0.1"
once "^1.3.0"
help-me@^4.2.0:
version "4.2.0"
resolved "https://registry.yarnpkg.com/help-me/-/help-me-4.2.0.tgz#50712bfd799ff1854ae1d312c36eafcea85b0563"
integrity sha512-TAOnTB8Tz5Dw8penUuzHVrKNKlCIbwwbHnXraNJxPwf8LRtE2HlM84RYuezMFcwOJmoYOCWVDyJ8TQGxn9PgxA==
dependencies:
glob "^8.0.0"
readable-stream "^3.6.0"
ieee754@^1.2.1:
version "1.2.1"
resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.2.1.tgz#8eb7a10a63fff25d15a57b001586d177d1b0d352"
integrity sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==
inflight@^1.0.4:
version "1.0.6"
resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9"
integrity sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==
dependencies:
once "^1.3.0"
wrappy "1"
inherits@2, inherits@^2.0.3, inherits@^2.0.4:
version "2.0.4"
resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c"
integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==
js-sdsl@4.3.0:
version "4.3.0"
resolved "https://registry.yarnpkg.com/js-sdsl/-/js-sdsl-4.3.0.tgz#aeefe32a451f7af88425b11fdb5f58c90ae1d711"
integrity sha512-mifzlm2+5nZ+lEcLJMoBK0/IH/bDg8XnJfd/Wq6IP+xoCjLZsTOnV2QpxlVbX9bMnkl5PdEjNtBJ9Cj1NjifhQ==
lru-cache@^7.18.3:
version "7.18.3"
resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-7.18.3.tgz#f793896e0fd0e954a59dfdd82f0773808df6aa89"
integrity sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==
minimatch@^5.0.1:
version "5.1.6"
resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-5.1.6.tgz#1cfcb8cf5522ea69952cd2af95ae09477f122a96"
integrity sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==
dependencies:
brace-expansion "^2.0.1"
minimist@^1.2.8:
version "1.2.8"
resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.8.tgz#c1a464e7693302e082a075cee0c057741ac4772c"
integrity sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==
mqtt-packet@^8.2.0:
version "8.2.0"
resolved "https://registry.yarnpkg.com/mqtt-packet/-/mqtt-packet-8.2.0.tgz#07cfdf72771f2c17c5689183162d1e4ad613438f"
integrity sha512-21Vo7XdRXUw2qhdTfk8GeOl2jtb8Dkwd4dKxn/epvf37mxTxHodvBJoozTPZGVwh57JXlsh2ChsaxMsAfqxp+A==
dependencies:
bl "^5.0.0"
debug "^4.1.1"
process-nextick-args "^2.0.1"
mqtt@^5.0.5:
version "5.0.5"
resolved "https://registry.yarnpkg.com/mqtt/-/mqtt-5.0.5.tgz#645819f48d6f3dba7962c28c5392e9b696c7081a"
integrity sha512-Ahbzk7nddvYg0aOezbYl/d9o8wcEbZw1NjiH+CmGObxiHsG4HgL7+IaRkph5yxwH679GVMAwtfsyUY2dFBSVSw==
dependencies:
"@types/readable-stream" "^4.0.1"
"@types/ws" "^8.5.5"
commist "^3.2.0"
concat-stream "^2.0.0"
debug "^4.3.4"
duplexify "^4.1.2"
help-me "^4.2.0"
lru-cache "^7.18.3"
minimist "^1.2.8"
mqtt-packet "^8.2.0"
number-allocator "^1.0.14"
readable-stream "^4.4.2"
reinterval "^1.1.0"
rfdc "^1.3.0"
split2 "^4.2.0"
ws "^8.13.0"
ms@2.1.2:
version "2.1.2"
resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009"
integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==
number-allocator@^1.0.14:
version "1.0.14"
resolved "https://registry.yarnpkg.com/number-allocator/-/number-allocator-1.0.14.tgz#1f2e32855498a7740dcc8c78bed54592d930ee4d"
integrity sha512-OrL44UTVAvkKdOdRQZIJpLkAdjXGTRda052sN4sO77bKEzYYqWKMBjQvrJFzqygI99gL6Z4u2xctPW1tB8ErvA==
dependencies:
debug "^4.3.1"
js-sdsl "4.3.0"
once@^1.3.0, once@^1.4.0:
version "1.4.0"
resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1"
integrity sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==
dependencies:
wrappy "1"
process-nextick-args@^2.0.1:
version "2.0.1"
resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-2.0.1.tgz#7820d9b16120cc55ca9ae7792680ae7dba6d7fe2"
integrity sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==
process@^0.11.10:
version "0.11.10"
resolved "https://registry.yarnpkg.com/process/-/process-0.11.10.tgz#7332300e840161bda3e69a1d1d91a7d4bc16f182"
integrity sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A==
readable-stream@^3.0.2, readable-stream@^3.1.1, readable-stream@^3.4.0, readable-stream@^3.6.0:
version "3.6.2"
resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.6.2.tgz#56a9b36ea965c00c5a93ef31eb111a0f11056967"
integrity sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==
dependencies:
inherits "^2.0.3"
string_decoder "^1.1.1"
util-deprecate "^1.0.1"
readable-stream@^4.4.2:
version "4.4.2"
resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-4.4.2.tgz#e6aced27ad3b9d726d8308515b9a1b98dc1b9d13"
integrity sha512-Lk/fICSyIhodxy1IDK2HazkeGjSmezAWX2egdtJnYhtzKEsBPJowlI6F6LPb5tqIQILrMbx22S5o3GuJavPusA==
dependencies:
abort-controller "^3.0.0"
buffer "^6.0.3"
events "^3.3.0"
process "^0.11.10"
string_decoder "^1.3.0"
reinterval@^1.1.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/reinterval/-/reinterval-1.1.0.tgz#3361ecfa3ca6c18283380dd0bb9546f390f5ece7"
integrity sha512-QIRet3SYrGp0HUHO88jVskiG6seqUGC5iAG7AwI/BV4ypGcuqk9Du6YQBUOUqm9c8pw1eyLoIaONifRua1lsEQ==
rfdc@^1.3.0:
version "1.3.0"
resolved "https://registry.yarnpkg.com/rfdc/-/rfdc-1.3.0.tgz#d0b7c441ab2720d05dc4cf26e01c89631d9da08b"
integrity sha512-V2hovdzFbOi77/WajaSMXk2OLm+xNIeQdMMuB7icj7bk6zi2F8GGAxigcnDFpJHbNyNcgyJDiP+8nOrY5cZGrA==
safe-buffer@~5.1.1:
version "5.1.2"
resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d"
integrity sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==
safe-buffer@~5.2.0:
version "5.2.1"
resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6"
integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==
split2@^4.2.0:
version "4.2.0"
resolved "https://registry.yarnpkg.com/split2/-/split2-4.2.0.tgz#c9c5920904d148bab0b9f67145f245a86aadbfa4"
integrity sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg==
stream-shift@^1.0.0:
version "1.0.1"
resolved "https://registry.yarnpkg.com/stream-shift/-/stream-shift-1.0.1.tgz#d7088281559ab2778424279b0877da3c392d5a3d"
integrity sha512-AiisoFqQ0vbGcZgQPY1cdP2I76glaVA/RauYR4G4thNFgkTqr90yXTo4LYX60Jl+sIlPNHHdGSwo01AvbKUSVQ==
string_decoder@^1.1.1, string_decoder@^1.3.0:
version "1.3.0"
resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.3.0.tgz#42f114594a46cf1a8e30b0a84f56c78c3edac21e"
integrity sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==
dependencies:
safe-buffer "~5.2.0"
typedarray@^0.0.6:
version "0.0.6"
resolved "https://registry.yarnpkg.com/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777"
integrity sha512-/aCDEGatGvZ2BIk+HmLf4ifCJFwvKFNb9/JeZPMulfgFracn9QFcAf5GO8B/mweUjSoblS5In0cWhqpfs/5PQA==
util-deprecate@^1.0.1:
version "1.0.2"
resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf"
integrity sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==
wrappy@1:
version "1.0.2"
resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f"
integrity sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==
ws@^8.13.0:
version "8.14.2"
resolved "https://registry.yarnpkg.com/ws/-/ws-8.14.2.tgz#6c249a806eb2db7a20d26d51e7709eab7b2e6c7f"
integrity sha512-wEBG1ftX4jcglPxgFCMJmZ2PLtSbJ2Peg6TmpJFTbe9GZYOQCDPdMYu/Tm0/bGZkw8paZnJY45J4K2PZrLYq8g==

View File

@ -0,0 +1,95 @@
{ stdenv, lib, p7zip, fetchurl, electron_26, makeWrapper, buildYarnPackage, python3
, nodejs, makeDesktopItem, copyDesktopItems, jq, runCommand, gzip, xz }:
let
env = buildYarnPackage {
src = lib.sourceByRegex ./. [ "^package\.json$" "^yarn\.lock$" ];
postBuild = "yarn install --production --ignore-scripts --prefer-offline";
};
# version should match the version in the electron package
better-sqlite3 = fetchurl {
url = "https://registry.npmjs.org/better-sqlite3/-/better-sqlite3-8.5.1.tgz";
hash = "sha256-AdP6+GiuEne2GMdevHLGciFsubGR9Gczr2QK3W0xO/s=";
};
in stdenv.mkDerivation rec {
pname = "notion-desktop";
version = "2.2.0";
src = fetchurl {
url = "https://desktop-release.notion-static.com/Notion%20Setup%20${version}.exe";
hash = "sha256-bRFW3Dh/Nqh46/F35ANA8wQNQ4T7Kf5Lx9+IpNoBjtE=";
};
nativeBuildInputs = [ p7zip makeWrapper python3 nodejs copyDesktopItems jq ];
npm_config_tarball = electron_26.headers;
unpackPhase = ''
runHook preUnpack
7z e $src \$PLUGINSDIR/app-64.7z
7z x app-64.7z resources/ version
rm app-64.7z
mkdir ./better-sqlite3-source
tar xzf ${better-sqlite3} -C $_
runHook postUnpack
'';
buildPhase = ''
runHook preBuild
${env}/node_modules/.bin/asar extract resources/app.asar resources/app/
# replace better-sqlite3 with source
# check better-sqlite3 version match
if [ $(jq .version resources/app/node_modules/better-sqlite3/package.json) != $(jq .version ./better-sqlite3-source/package/package.json) ]; then
echo "better-sqlite3 version mismatch"
echo "please update to" $(jq .version resources/app/node_modules/better-sqlite3/package.json)
exit 1
fi
rm -r resources/app/node_modules/better-sqlite3
mv ./better-sqlite3-source/package resources/app/node_modules/better-sqlite3
# rebuild
${env}/node_modules/.bin/electron-rebuild --version ${electron_26.version} --module-dir resources/app/
# move back into asar.unpacked dir, then discard the unpacked app
mv ./resources/app/node_modules/better-sqlite3/build/Release/* ./resources/app.asar.unpacked/node_modules/better-sqlite3/build/Release/
runHook postBuild
'';
installPhase = ''
runHook preInstall
mkdir -p $out/libexec/resources $out/bin
mv resources/{app.asar,app.asar.unpacked} $out/libexec/resources
install -Dm755 ./resources/app/icon.ico $out/share/icons/hicolor/32x32/apps/notion-desktop.ico
makeWrapper ${electron_26}/bin/electron $out/bin/notion-desktop \
--argv0 notion-desktop \
--add-flags "$out/libexec/resources/app.asar"
runHook postInstall
'';
desktopItems = [
(makeDesktopItem {
name = "Notion";
exec = "notion-desktop";
icon = "notion-desktop";
desktopName = "Notion";
categories = [ "Office" ];
})
];
meta = with lib; {
description = "Desktop application for Notion.so";
homepage = "https://www.notion.so/desktop";
license = licenses.unfree;
platforms = platforms.linux;
maintainers = with maintainers; [ yorickvP ];
mainProgram = "notion-desktop";
sourceProvenance = [ sourceTypes.fromSource ];
};
}

View File

@ -0,0 +1,10 @@
{
"name": "notion-desktop-buildenv",
"version": "1.0.0",
"main": "index.js",
"license": "MIT",
"dependencies": {
"@electron/asar": "^3.2.4",
"@electron/rebuild": "^3.3.0"
}
}

Some files were not shown because too many files have changed in this diff Show More