mirror of
https://github.com/nmasur/dotfiles
synced 2026-09-14 18:48:09 +00:00
Compare commits
360
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
db49e746b8 | ||
|
|
7f8400ff58 | ||
|
|
d3914768c8 | ||
|
|
fd9cae9c40 | ||
|
|
f593fdb81f | ||
|
|
01ee98155a | ||
|
|
2a3cbfb5f5 | ||
|
|
ca1343f593 | ||
|
|
a053a9ab0f | ||
|
|
90dc80f7b4 | ||
|
|
aff596aa64 | ||
|
|
6e0f4e2000 | ||
|
|
72c4f4823b | ||
|
|
a93fa75779 | ||
|
|
a50d2c01a9 | ||
|
|
a72e81fcce | ||
|
|
fe2843ead6 | ||
|
|
68320577ae | ||
|
|
38ba019c3d | ||
|
|
e339a4969f | ||
|
|
44f2ca803e | ||
|
|
239b56c1b1 | ||
|
|
4ba1ed807c | ||
|
|
32989f1758 | ||
|
|
b0b08d2475 | ||
|
|
5ecefd4589 | ||
|
|
fffb9d547c | ||
|
|
3c303ccd19 | ||
|
|
d222fef02e | ||
|
|
71ce9689ce | ||
|
|
4047cae211 | ||
|
|
e70661a623 | ||
|
|
a979036462 | ||
|
|
8ae7fd435e | ||
|
|
2d5de254e4 | ||
|
|
d90b45d194 | ||
|
|
d8a29f0267 | ||
|
|
f3a8d45722 | ||
|
|
df38163999 | ||
|
|
31cecf05cc | ||
|
|
59685bf023 | ||
|
|
a3a5c516ce | ||
|
|
033026bff8 | ||
|
|
5929b3201d | ||
|
|
373beb6daf | ||
|
|
8cef9bfb59 | ||
|
|
98d426ce89 | ||
|
|
e107431fa9 | ||
|
|
1960d84e7a | ||
|
|
671a17af76 | ||
|
|
71709776f9 | ||
|
|
829af86dd8 | ||
|
|
e7fd5eb770 | ||
|
|
f0b400d134 | ||
|
|
573c0acd33 | ||
|
|
eec777c0c1 | ||
|
|
638b112db9 | ||
|
|
27917ffede | ||
|
|
73b62e0907 | ||
|
|
b25cfe6877 | ||
|
|
d162df2515 | ||
|
|
396337f74d | ||
|
|
76b50920de | ||
|
|
e04cdab409 | ||
|
|
d238b7a81a | ||
|
|
f3e24c3730 | ||
|
|
5862c7cb29 | ||
|
|
a175acd0ad | ||
|
|
3f3cf65c77 | ||
|
|
35d40ca346 | ||
|
|
e0fb590314 | ||
|
|
2f107ad207 | ||
|
|
b6b0a29a78 | ||
|
|
fd6da7e68d | ||
|
|
28049e9c30 | ||
|
|
d95cdb1385 | ||
|
|
cf8f1fa221 | ||
|
|
8b098f0589 | ||
|
|
12961b19c0 | ||
|
|
455c047607 | ||
|
|
fa307c0f4b | ||
|
|
07a980e937 | ||
|
|
0a4a28d06a | ||
|
|
5fd6593a92 | ||
|
|
8af595b62b | ||
|
|
1e723db068 | ||
|
|
16e42c2021 | ||
|
|
38edf0a1a6 | ||
|
|
15f70dce2c | ||
|
|
1a7633fe8c | ||
|
|
40025b1211 | ||
|
|
f5d9664caf | ||
|
|
7010d6cea3 | ||
|
|
a2a429d286 | ||
|
|
7f5b5eb809 | ||
|
|
f5f3a8336e | ||
|
|
4444a479d4 | ||
|
|
395c4b4348 | ||
|
|
8dbec5f6ab | ||
|
|
f8d79cdf3a | ||
|
|
280082acfe | ||
|
|
1edf9da155 | ||
|
|
8d970103e1 | ||
|
|
d9137ad738 | ||
|
|
4eacca970e | ||
|
|
d09ee3337b | ||
|
|
22e1c9b8eb | ||
|
|
acd71623e4 | ||
|
|
9a97d94ffa | ||
|
|
84bffd13e8 | ||
|
|
774b323837 | ||
|
|
2f2d2c0145 | ||
|
|
6b17248804 | ||
|
|
a7dacb7edf | ||
|
|
dfd3b955c0 | ||
|
|
fd7ddf71f3 | ||
|
|
bba66e3e6a | ||
|
|
be6d6b0d35 | ||
|
|
0239a9925c | ||
|
|
49e35403b6 | ||
|
|
430b522c61 | ||
|
|
a64488093c | ||
|
|
54d2376437 | ||
|
|
cd0a5d5de0 | ||
|
|
10eecfa136 | ||
|
|
b5b3f6cb6a | ||
|
|
810c92a7b8 | ||
|
|
fcb28c8151 | ||
|
|
e2a2d3de14 | ||
|
|
adbc2bd261 | ||
|
|
117fd8a06e | ||
|
|
d9fbdf7bfe | ||
|
|
2d13780d2e | ||
|
|
53a712a217 | ||
|
|
31d34c6540 | ||
|
|
a978e67346 | ||
|
|
a6915a6d2d | ||
|
|
44c4034236 | ||
|
|
a99c14a8c2 | ||
|
|
f1c8e26044 | ||
|
|
29cd253d9c | ||
|
|
603b9a2eff | ||
|
|
9c35744ab9 | ||
|
|
7d6b29c30b | ||
|
|
fd589b66ef | ||
|
|
853aa644fa | ||
|
|
b6e7221cc6 | ||
|
|
235901b3b0 | ||
|
|
7cd74986df | ||
|
|
a6e15b71cd | ||
|
|
2e4467b6ea | ||
|
|
431ebd732c | ||
|
|
2d576bd25d | ||
|
|
a1615eda67 | ||
|
|
444582a5a5 | ||
|
|
fbabdadb32 | ||
|
|
f8dfa2a817 | ||
|
|
e4a8ef15ce | ||
|
|
5c922310f5 | ||
|
|
2f274cd652 | ||
|
|
407e9c3af8 | ||
|
|
c13e029805 | ||
|
|
c56bc30200 | ||
|
|
6064fdb0e0 | ||
|
|
5cf27d6d66 | ||
|
|
ceca1ffd5a | ||
|
|
ebbc9c5a5d | ||
|
|
aea3e95ef5 | ||
|
|
d79c1ba7df | ||
|
|
422131134a | ||
|
|
5d8e10b814 | ||
|
|
fdd5eb6418 | ||
|
|
72c548e707 | ||
|
|
a57207dd5d | ||
|
|
94b4217be3 | ||
|
|
7619ac6ea2 | ||
|
|
7543721020 | ||
|
|
bf52069886 | ||
|
|
839ca079c2 | ||
|
|
b98c3f04ab | ||
|
|
68d8e60b7e | ||
|
|
85f09b1126 | ||
|
|
29c7a27135 | ||
|
|
3523f20665 | ||
|
|
774773c748 | ||
|
|
c85d292d1a | ||
|
|
78cc3559f6 | ||
|
|
a35e758c2f | ||
|
|
72f30cbab1 | ||
|
|
17b30de163 | ||
|
|
8b3ab57b34 | ||
|
|
483833cdcb | ||
|
|
57e593aabc | ||
|
|
b119256ba6 | ||
|
|
54948353dd | ||
|
|
9c4219da40 | ||
|
|
ae3735586e | ||
|
|
cb00bb2e72 | ||
|
|
e64a9f14d0 | ||
|
|
e2e179c0e5 | ||
|
|
e975db7385 | ||
|
|
08ec8ce4b8 | ||
|
|
7388eed876 | ||
|
|
e53d9eb1a9 | ||
|
|
b956f9dd82 | ||
|
|
d7969cc8fc | ||
|
|
21d66d2be1 | ||
|
|
518848181a | ||
|
|
f9bf763f91 | ||
|
|
ca20fa0732 | ||
|
|
56d10c2765 | ||
|
|
3b6b4bd2e6 | ||
|
|
6f06b0a0c5 | ||
|
|
d3e69faf2f | ||
|
|
4755a27089 | ||
|
|
57303d61e9 | ||
|
|
b67c90dae0 | ||
|
|
2ff9254a0e | ||
|
|
59a8a6dc3f | ||
|
|
5943a6682e | ||
|
|
d38f767d03 | ||
|
|
ebd79aa348 | ||
|
|
f778bc58ac | ||
|
|
eb1c08f5da | ||
|
|
3e7afdc0b3 | ||
|
|
45aa5d01e5 | ||
|
|
6a9d1c14a7 | ||
|
|
3fe4843032 | ||
|
|
6a36408416 | ||
|
|
25c7aec532 | ||
|
|
b87db529ae | ||
|
|
d756b0d394 | ||
|
|
c35c2e0104 | ||
|
|
f1f85f97aa | ||
|
|
6dd67fdc58 | ||
|
|
57b40d2b31 | ||
|
|
600e7383d0 | ||
|
|
47b7cce953 | ||
|
|
fb80f6d98d | ||
|
|
98c18420ec | ||
|
|
c0091c3f21 | ||
|
|
43246234b1 | ||
|
|
019f8ae01b | ||
|
|
ee627d4161 | ||
|
|
9d7ce47ac5 | ||
|
|
b15a071782 | ||
|
|
48e714faf3 | ||
|
|
ea20d93079 | ||
|
|
b323723115 | ||
|
|
89b260d12c | ||
|
|
a0f4380c9f | ||
|
|
0a9774f9fa | ||
|
|
c569257f03 | ||
|
|
d709030211 | ||
|
|
ecf6bdda45 | ||
|
|
5e2fca427d | ||
|
|
c5ad3c66ea | ||
|
|
6b5a01262e | ||
|
|
d16ed6a4fc | ||
|
|
6d5b460cb2 | ||
|
|
a5b628dd30 | ||
|
|
5ed6870bdd | ||
|
|
26c1c09402 | ||
|
|
dd00ad6c2e | ||
|
|
192e08a9d9 | ||
|
|
227e6a68af | ||
|
|
444ede2074 | ||
|
|
c31fe46b61 | ||
|
|
28d9806720 | ||
|
|
5dea78926b | ||
|
|
e8571fe6b7 | ||
|
|
a9b3249e20 | ||
|
|
73002607ab | ||
|
|
267134044f | ||
|
|
0621c66981 | ||
|
|
18b489592e | ||
|
|
928be5132a | ||
|
|
11b7587783 | ||
|
|
2704642b3d | ||
|
|
95d86dcdff | ||
|
|
e8bc263081 | ||
|
|
03d2326724 | ||
|
|
5bc980eea9 | ||
|
|
a2866927f3 | ||
|
|
c2100cbc39 | ||
|
|
1d4b79e8f1 | ||
|
|
3974c6ce5d | ||
|
|
67f6eb3a1c | ||
|
|
e0cd3c9d79 | ||
|
|
e7e94a1dc3 | ||
|
|
20fc80c259 | ||
|
|
ae09296f36 | ||
|
|
44f769f5ed | ||
|
|
6e29c95506 | ||
|
|
ac0a8d6c38 | ||
|
|
6f32a0dfa3 | ||
|
|
9feaca58f3 | ||
|
|
3084c90c13 | ||
|
|
f20d477f67 | ||
|
|
c8441fc265 | ||
|
|
23f46e51e6 | ||
|
|
f2e09c9adc | ||
|
|
f0add607e6 | ||
|
|
b38205af93 | ||
|
|
12c9342748 | ||
|
|
5d539abe21 | ||
|
|
cea08761bb | ||
|
|
eea972492e | ||
|
|
9014ca226e | ||
|
|
515859d22d | ||
|
|
aa6c91b65c | ||
|
|
d59692c813 | ||
|
|
88266c9f8d | ||
|
|
a1dfc77790 | ||
|
|
b3a7b280b5 | ||
|
|
e803e6a02a | ||
|
|
61c4e68fef | ||
|
|
faac8f3c8b | ||
|
|
9b30f91b1d | ||
|
|
5966368620 | ||
|
|
820f5afe0b | ||
|
|
bfbacbe93e | ||
|
|
54a073b946 | ||
|
|
8eede16bcd | ||
|
|
11e0992d99 | ||
|
|
562295edb1 | ||
|
|
a719dc4309 | ||
|
|
0aecbd85cd | ||
|
|
28ac5523f8 | ||
|
|
645454cb9a | ||
|
|
b30893d968 | ||
|
|
0ec67df9a3 | ||
|
|
7182ca7cd4 | ||
|
|
fbaa6f8894 | ||
|
|
3873ab7296 | ||
|
|
7b32216684 | ||
|
|
2f042713cc | ||
|
|
011fb57347 | ||
|
|
ce308a6347 | ||
|
|
31e93606f4 | ||
|
|
b7317a721b | ||
|
|
3684ce4b39 | ||
|
|
b8337f1295 | ||
|
|
b78bc5b3bb | ||
|
|
5869e4a6b4 | ||
|
|
2c55912abf | ||
|
|
0be5c026a7 | ||
|
|
d427ccc577 | ||
|
|
3852551ebe | ||
|
|
9727fd6a56 | ||
|
|
e233a2e354 | ||
|
|
5b32f1f211 | ||
|
|
eace1ff3cf | ||
|
|
5397e4e23f | ||
|
|
956fa3184b | ||
|
|
b73867ea27 | ||
|
|
37427204de | ||
|
|
6ee5ade2bc | ||
|
|
043cd8ce5c | ||
|
|
07a0d5185b |
@@ -0,0 +1,13 @@
|
|||||||
|
{
|
||||||
|
"permissions": {
|
||||||
|
"allow": [
|
||||||
|
"WebFetch(domain:github.com)",
|
||||||
|
"WebFetch(domain:raw.githubusercontent.com)",
|
||||||
|
"Bash(gh run *)",
|
||||||
|
"Bash(jj status *)",
|
||||||
|
"Bash(jj new *)",
|
||||||
|
"Bash(jj describe *)",
|
||||||
|
"Bash(nix flake *)"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -3,7 +3,7 @@ name: Arrow (AWS)
|
|||||||
run-name: Arrow (AWS) - ${{ inputs.rebuild && 'Rebuild and ' || '' }}${{ inputs.action == 'create' && 'Create' || ( inputs.action == 'destroy' && 'Destroy' || 'No Action' ) }}
|
run-name: Arrow (AWS) - ${{ inputs.rebuild && 'Rebuild and ' || '' }}${{ inputs.action == 'create' && 'Create' || ( inputs.action == 'destroy' && 'Destroy' || 'No Action' ) }}
|
||||||
|
|
||||||
env:
|
env:
|
||||||
TERRAFORM_DIRECTORY: hosts/arrow/aws
|
TERRAFORM_DIRECTORY: deploy/aws
|
||||||
DEPLOY_IDENTITY_BASE64: ${{ secrets.DEPLOY_IDENTITY_BASE64 }}
|
DEPLOY_IDENTITY_BASE64: ${{ secrets.DEPLOY_IDENTITY_BASE64 }}
|
||||||
ARROW_IDENTITY_BASE64: ${{ secrets.ARROW_IDENTITY_BASE64 }}
|
ARROW_IDENTITY_BASE64: ${{ secrets.ARROW_IDENTITY_BASE64 }}
|
||||||
ZONE_NAME: masu.rs
|
ZONE_NAME: masu.rs
|
||||||
|
|||||||
@@ -0,0 +1,200 @@
|
|||||||
|
name: Flame
|
||||||
|
|
||||||
|
run-name: Flame - ${{ inputs.rebuild && 'Rebuild and ' || '' }}${{ inputs.action == 'create' && 'Create' || ( inputs.action == 'destroy' && 'Destroy' || 'No Action' ) }}
|
||||||
|
|
||||||
|
env:
|
||||||
|
TERRAFORM_DIRECTORY: deploy/oracle
|
||||||
|
DEPLOY_IDENTITY_BASE64: ${{ secrets.DEPLOY_IDENTITY_BASE64 }}
|
||||||
|
FLAME_IDENTITY_BASE64: ${{ secrets.FLAME_IDENTITY_BASE64 }}
|
||||||
|
ZONE_NAME: masu.rs
|
||||||
|
CLOUDFLARE_API_TOKEN: ${{ secrets.CLOUDFLARE_API_TOKEN }}
|
||||||
|
CLOUDFLARE_ZONE_ID: ${{ secrets.CLOUDFLARE_ZONE_ID }}
|
||||||
|
OCI_CLI_USER: "ocid1.user.oc1..aaaaaaaa6lro2eoxdajjypjysepvzcavq5yn4qyozjyebxdiaoqziribuqba"
|
||||||
|
OCI_CLI_TENANCY: "ocid1.tenancy.oc1..aaaaaaaaudwr2ozedhjnrn76ofjgglgug6gexknjisd7gb7tkj3mjdp763da"
|
||||||
|
OCI_CLI_FINGERPRINT: "dd:d0:da:6d:83:46:8b:b3:d9:45:2b:c7:56:ae:30:94"
|
||||||
|
OCI_CLI_KEY_CONTENT: "${{ secrets.OCI_PRIVATE_KEY }}"
|
||||||
|
TF_VAR_oci_private_key: "${{ secrets.OCI_PRIVATE_KEY }}"
|
||||||
|
OCI_CLI_REGION: "us-ashburn-1"
|
||||||
|
|
||||||
|
on:
|
||||||
|
workflow_dispatch:
|
||||||
|
inputs:
|
||||||
|
rebuild:
|
||||||
|
description: Rebuild Image
|
||||||
|
type: boolean
|
||||||
|
default: false
|
||||||
|
action:
|
||||||
|
description: Terraform Action
|
||||||
|
type: choice
|
||||||
|
required: true
|
||||||
|
default: create
|
||||||
|
options:
|
||||||
|
- create
|
||||||
|
- destroy
|
||||||
|
- nothing
|
||||||
|
|
||||||
|
permissions:
|
||||||
|
id-token: write
|
||||||
|
contents: write
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build-deploy:
|
||||||
|
name: Build and Deploy
|
||||||
|
# runs-on: ubuntu-latest
|
||||||
|
runs-on: ubuntu-24.04-arm
|
||||||
|
steps:
|
||||||
|
- name: Checkout Repo Code
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
|
# - name: Write OCI Key to File
|
||||||
|
# run: |
|
||||||
|
# echo "${{ env.OCI_PRIVATE_KEY_BASE64 }}" | base64 -d > OCI_PRIVATE_KEY
|
||||||
|
|
||||||
|
# # Enable access to KVM, required to build an image
|
||||||
|
# - name: Enable KVM group perms
|
||||||
|
# if: inputs.rebuild && inputs.action != 'destroy'
|
||||||
|
# run: |
|
||||||
|
# echo 'KERNEL=="kvm", GROUP="kvm", MODE="0666", OPTIONS+="static_node=kvm"' | sudo tee /etc/udev/rules.d/99-kvm4all.rules
|
||||||
|
# sudo udevadm control --reload-rules
|
||||||
|
# sudo udevadm trigger --name-match=kvm
|
||||||
|
# sudo apt-get install -y qemu-user-static
|
||||||
|
|
||||||
|
# Install Nix
|
||||||
|
- name: Install Nix
|
||||||
|
# if: inputs.rebuild && inputs.action != 'destroy'
|
||||||
|
uses: cachix/[email protected]
|
||||||
|
with:
|
||||||
|
enable_kvm: true
|
||||||
|
extra_nix_config: |
|
||||||
|
system = aarch64-linux
|
||||||
|
system-features = aarch64-linux arm-linux kvm
|
||||||
|
|
||||||
|
# Build the image
|
||||||
|
- name: Build Image
|
||||||
|
if: inputs.rebuild && inputs.action != 'destroy'
|
||||||
|
run: nix build .#flame-qcow --system aarch64-linux
|
||||||
|
|
||||||
|
- name: List Images
|
||||||
|
if: inputs.rebuild && inputs.action != 'destroy'
|
||||||
|
run: |
|
||||||
|
ls -lh result/
|
||||||
|
echo "IMAGE_NAME=$(ls result/nixos.qcow2) >> $GITHUB_ENV
|
||||||
|
|
||||||
|
- name: Upload Image to S3
|
||||||
|
if: inputs.rebuild && inputs.action != 'destroy'
|
||||||
|
# env:
|
||||||
|
# AWS_ACCESS_KEY_ID: "<YOUR_OCI_ACCESS_KEY>"
|
||||||
|
# AWS_SECRET_ACCESS_KEY: "<YOUR_OCI_SECRET_KEY>"
|
||||||
|
# AWS_DEFAULT_REGION: "us-ashburn-1" # e.g., us-ashburn-1, us-phoenix-1
|
||||||
|
# AWS_ENDPOINT_URL: "https://masur.compat.objectstorage.us-ashburn-1.oraclecloud.com"
|
||||||
|
uses: oracle-actions/[email protected]
|
||||||
|
with:
|
||||||
|
command: |
|
||||||
|
os object put \
|
||||||
|
--namespace "idptr5akf9pf" \
|
||||||
|
--bucket-name "noahmasur-images" \
|
||||||
|
--name "nixos.qcow2" \
|
||||||
|
--file "${IMAGE_NAME}" \
|
||||||
|
--part-size 128 \ # Optional: Specify part size in MiB for multipart uploads, default is 128 MiB
|
||||||
|
--parallel-upload-count 5 # Optional: Number of parallel uploads, default is 3
|
||||||
|
|
||||||
|
# Login to AWS
|
||||||
|
- name: AWS Assume Role
|
||||||
|
uses: aws-actions/configure-aws-credentials@v4
|
||||||
|
with:
|
||||||
|
role-to-assume: arn:aws:iam::286370965832:role/github_actions_admin
|
||||||
|
aws-region: us-east-1
|
||||||
|
|
||||||
|
# Installs the Terraform binary and some other accessory functions.
|
||||||
|
- name: Setup Terraform
|
||||||
|
uses: hashicorp/setup-terraform@v2
|
||||||
|
|
||||||
|
# Checks whether Terraform is formatted properly. If this fails, you
|
||||||
|
# should install the pre-commit hook.
|
||||||
|
- name: Check Formatting
|
||||||
|
working-directory: ${{ env.TERRAFORM_DIRECTORY }}
|
||||||
|
run: |
|
||||||
|
terraform fmt -no-color -check -diff -recursive
|
||||||
|
|
||||||
|
# Connects to remote state backend and download providers.
|
||||||
|
- name: Terraform Init
|
||||||
|
working-directory: ${{ env.TERRAFORM_DIRECTORY }}
|
||||||
|
run: terraform init -input=false
|
||||||
|
|
||||||
|
# Deploys infrastructure or changes to infrastructure.
|
||||||
|
- name: Terraform Apply
|
||||||
|
if: inputs.action == 'create'
|
||||||
|
working-directory: ${{ env.TERRAFORM_DIRECTORY }}
|
||||||
|
run: |
|
||||||
|
terraform apply \
|
||||||
|
-auto-approve \
|
||||||
|
-input=false
|
||||||
|
|
||||||
|
# Removes infrastructure.
|
||||||
|
- name: Terraform Destroy
|
||||||
|
if: inputs.action == 'destroy'
|
||||||
|
working-directory: ${{ env.TERRAFORM_DIRECTORY }}
|
||||||
|
run: |
|
||||||
|
terraform destroy \
|
||||||
|
-auto-approve \
|
||||||
|
-input=false
|
||||||
|
|
||||||
|
- name: Get Host IP
|
||||||
|
if: inputs.action == 'create'
|
||||||
|
id: host
|
||||||
|
working-directory: ${{ env.TERRAFORM_DIRECTORY }}
|
||||||
|
run: terraform output -raw host_ip
|
||||||
|
|
||||||
|
- name: Wait on SSH
|
||||||
|
if: inputs.action == 'create'
|
||||||
|
run: |
|
||||||
|
for i in $(seq 1 15); do
|
||||||
|
if $(nc -z -w 3 ${{ steps.host.outputs.stdout }} 22); then
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
sleep 10
|
||||||
|
done
|
||||||
|
|
||||||
|
- name: Write Identity Keys to Files
|
||||||
|
if: inputs.action == 'create'
|
||||||
|
run: |
|
||||||
|
echo "${{ env.DEPLOY_IDENTITY_BASE64 }}" | base64 -d > deploy_ed25519
|
||||||
|
chmod 0600 deploy_ed25519
|
||||||
|
echo "${{ env.FLAME_IDENTITY_BASE64 }}" | base64 -d > flame_ed25519
|
||||||
|
chmod 0600 flame_ed25519
|
||||||
|
mkdir -pv "${HOME}/.ssh/"
|
||||||
|
cp deploy_ed25519 "${HOME}/.ssh/id_ed25519"
|
||||||
|
|
||||||
|
- name: Run nixos-anywhere
|
||||||
|
if: inputs.action == 'create'
|
||||||
|
run: |
|
||||||
|
nix run github:nix-community/nixos-anywhere -- --flake github:nmasur/dotfiles#flame --build-on remote --no-reboot --target-host ubuntu@${{ steps.host.outputs.stdout }}
|
||||||
|
reboot now
|
||||||
|
|
||||||
|
- name: Wait on SSH After Reboot
|
||||||
|
if: inputs.action == 'create'
|
||||||
|
run: |
|
||||||
|
for i in $(seq 1 15); do
|
||||||
|
if $(nc -z -w 3 ${{ steps.host.outputs.stdout }} 22); then
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
sleep 10
|
||||||
|
done
|
||||||
|
|
||||||
|
- name: Copy Identity File to Host
|
||||||
|
if: inputs.action == 'create'
|
||||||
|
run: |
|
||||||
|
ssh -i deploy_ed25519 -o StrictHostKeyChecking=accept-new noah@${{ steps.host.outputs.stdout }} 'mkdir -pv .ssh'
|
||||||
|
scp -i deploy_ed25519 flame_ed25519 noah@${{ steps.host.outputs.stdout }}:~/.ssh/id_ed25519
|
||||||
|
|
||||||
|
# - name: Wipe Records
|
||||||
|
# if: ${{ inputs.action == 'destroy' }}
|
||||||
|
# run: |
|
||||||
|
# RECORD_ID=$(curl --request GET \
|
||||||
|
# --url https://api.cloudflare.com/client/v4/zones/${{ env.CLOUDFLARE_ZONE_ID }}/dns_records \
|
||||||
|
# --header 'Content-Type: application/json' \
|
||||||
|
# --header "Authorization: Bearer ${{ env.CLOUDFLARE_API_TOKEN }}" | jq -r '.result[] | select(.name == "n8n2.${{ env.ZONE_NAME }}") | .id')
|
||||||
|
# curl --request DELETE \
|
||||||
|
# --url https://api.cloudflare.com/client/v4/zones/${{ env.CLOUDFLARE_ZONE_ID }}/dns_records/${RECORD_ID} \
|
||||||
|
# --header 'Content-Type: application/json' \
|
||||||
|
# --header "Authorization: Bearer ${{ env.CLOUDFLARE_API_TOKEN }}"
|
||||||
@@ -0,0 +1,115 @@
|
|||||||
|
terraform {
|
||||||
|
backend "s3" {
|
||||||
|
bucket = "noahmasur-terraform"
|
||||||
|
key = "flame.tfstate"
|
||||||
|
region = "us-east-1"
|
||||||
|
use_lockfile = true
|
||||||
|
}
|
||||||
|
required_version = ">= 1.0.0"
|
||||||
|
required_providers {
|
||||||
|
oci = {
|
||||||
|
source = "oracle/oci"
|
||||||
|
version = "7.7.0"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
provider "oci" {
|
||||||
|
auth = "APIKey"
|
||||||
|
tenancy_ocid = var.compartment_ocid
|
||||||
|
user_ocid = "ocid1.user.oc1..aaaaaaaa6lro2eoxdajjypjysepvzcavq5yn4qyozjyebxdiaoqziribuqba"
|
||||||
|
private_key = var.oci_private_key
|
||||||
|
fingerprint = "dd:d0:da:6d:83:46:8b:b3:d9:45:2b:c7:56:ae:30:94"
|
||||||
|
region = "us-ashburn-1"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Get the latest Ubuntu image OCID
|
||||||
|
# We'll filter for a recent Ubuntu LTS version (e.g., 22.04 or 24.04) and pick the latest.
|
||||||
|
# Note: Image OCIDs are region-specific. This data source helps find the correct one.
|
||||||
|
data "oci_core_images" "ubuntu_image" {
|
||||||
|
compartment_id = var.compartment_ocid
|
||||||
|
operating_system = "Canonical Ubuntu"
|
||||||
|
# Adjust this version if you prefer a different Ubuntu LTS (e.g., "24.04")
|
||||||
|
operating_system_version = "24.04"
|
||||||
|
shape = var.instance_shape # Filter by the shape to ensure compatibility
|
||||||
|
sort_by = "TIMECREATED"
|
||||||
|
sort_order = "DESC"
|
||||||
|
}
|
||||||
|
|
||||||
|
# resource "oci_core_image" "my_custom_image" {
|
||||||
|
# compartment_id = var.compartment_ocid
|
||||||
|
# display_name = "noah-nixos"
|
||||||
|
|
||||||
|
# image_source_details {
|
||||||
|
# source_type = "objectStorageTuple" # Use this if specifying namespace, bucket, and object name
|
||||||
|
# # source_type = "objectStorageUri" # Use this if you have a pre-authenticated request URL (PAR)
|
||||||
|
# namespace_name = var.object_storage_namespace
|
||||||
|
# bucket_name = var.object_storage_bucket_name
|
||||||
|
# object_name = var.object_storage_object_name
|
||||||
|
|
||||||
|
# source_image_type = "QCOW2" # e.g., "QCOW2", "VMDK"
|
||||||
|
|
||||||
|
# # These properties help OCI understand how to launch instances from this image
|
||||||
|
# # Adjust based on your custom image's OS and boot mode
|
||||||
|
# operating_system = "NixOS" # e.g., "CentOS", "Debian", "Windows"
|
||||||
|
# operating_system_version = "25.05" # e.g., "7", "11", "2019"
|
||||||
|
# }
|
||||||
|
|
||||||
|
# launch_mode = "PARAVIRTUALIZED" # Or "NATIVE", "EMULATED", "CUSTOM"
|
||||||
|
# # Optional: for specific launch options if your image requires them
|
||||||
|
# # launch_options {
|
||||||
|
# # boot_volume_type = "PARAVIRTUALIZED"
|
||||||
|
# # firmware = "UEFI_64" # Or "BIOS"
|
||||||
|
# # network_type = "PARAVIRTUALIZED"
|
||||||
|
# # }
|
||||||
|
|
||||||
|
# # Time out for image import operation. Can take a while for large images.
|
||||||
|
# timeouts {
|
||||||
|
# create = "60m" # Default is 20m, often needs to be increased
|
||||||
|
# }
|
||||||
|
# }
|
||||||
|
|
||||||
|
data "oci_identity_availability_domains" "ads" {
|
||||||
|
compartment_id = var.compartment_ocid
|
||||||
|
}
|
||||||
|
|
||||||
|
resource "oci_core_instance" "my_compute_instance" {
|
||||||
|
compartment_id = var.compartment_ocid
|
||||||
|
availability_domain = data.oci_identity_availability_domains.ads.availability_domains[0].name
|
||||||
|
shape = var.instance_shape
|
||||||
|
display_name = var.instance_display_name
|
||||||
|
|
||||||
|
source_details {
|
||||||
|
source_type = "image"
|
||||||
|
# Use the OCID of the latest Ubuntu image found by the data source
|
||||||
|
source_id = data.oci_core_images.ubuntu_image.images[0].id
|
||||||
|
# # Use the OCID of the newly imported custom image
|
||||||
|
# source_id = oci_core_image.my_custom_image.id
|
||||||
|
# Specify the boot volume size
|
||||||
|
boot_volume_size_in_gbs = var.boot_volume_size_in_gbs
|
||||||
|
boot_volume_vpus_per_gb = 20 # Highest free tier option
|
||||||
|
}
|
||||||
|
|
||||||
|
# launch_options {
|
||||||
|
# is_consistent_volume_naming_enabled = true # Sets boot device path to /dev/oracleoci/oraclevda
|
||||||
|
# network_type = "PARAVIRTUALIZED" # I think this is the default?
|
||||||
|
# }
|
||||||
|
|
||||||
|
create_vnic_details {
|
||||||
|
subnet_id = oci_core_subnet.my_public_subnet.id # Use the created subnet's ID
|
||||||
|
display_name = "primary_vnic"
|
||||||
|
assign_public_ip = true
|
||||||
|
hostname_label = "flame"
|
||||||
|
}
|
||||||
|
|
||||||
|
metadata = {
|
||||||
|
ssh_authorized_keys = var.ssh_public_key
|
||||||
|
user_data = base64encode(var.cloud_init_script)
|
||||||
|
}
|
||||||
|
|
||||||
|
# Optional: For flexible shapes (e.g., VM.Standard.E4.Flex), you might need to specify OCPUs and memory
|
||||||
|
shape_config {
|
||||||
|
ocpus = 4
|
||||||
|
memory_in_gbs = 24
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,126 @@
|
|||||||
|
resource "oci_core_vcn" "my_vpc" {
|
||||||
|
compartment_id = var.compartment_ocid
|
||||||
|
display_name = "main"
|
||||||
|
cidr_block = "10.0.0.0/16"
|
||||||
|
is_ipv6enabled = false
|
||||||
|
dns_label = "mainvcn" # Must be unique within your tenancy
|
||||||
|
}
|
||||||
|
|
||||||
|
resource "oci_core_internet_gateway" "my_igw" {
|
||||||
|
compartment_id = var.compartment_ocid
|
||||||
|
vcn_id = oci_core_vcn.my_vpc.id
|
||||||
|
display_name = "main-igw"
|
||||||
|
enabled = true
|
||||||
|
}
|
||||||
|
|
||||||
|
resource "oci_core_route_table" "my_public_route_table" {
|
||||||
|
compartment_id = var.compartment_ocid
|
||||||
|
vcn_id = oci_core_vcn.my_vpc.id
|
||||||
|
display_name = "main-public-rt"
|
||||||
|
|
||||||
|
# Default route to the Internet Gateway
|
||||||
|
route_rules {
|
||||||
|
destination = "0.0.0.0/0"
|
||||||
|
destination_type = "CIDR_BLOCK"
|
||||||
|
network_entity_id = oci_core_internet_gateway.my_igw.id
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
resource "oci_core_security_list" "my_public_security_list" {
|
||||||
|
compartment_id = var.compartment_ocid
|
||||||
|
vcn_id = oci_core_vcn.my_vpc.id
|
||||||
|
display_name = "main-public-sl"
|
||||||
|
|
||||||
|
# Egress Rules (Allow all outbound traffic)
|
||||||
|
egress_security_rules {
|
||||||
|
destination = "0.0.0.0/0"
|
||||||
|
destination_type = "CIDR_BLOCK"
|
||||||
|
protocol = "all"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Ingress Rules
|
||||||
|
ingress_security_rules {
|
||||||
|
# SSH (TCP 22)
|
||||||
|
protocol = "6" # TCP
|
||||||
|
source = "0.0.0.0/0"
|
||||||
|
source_type = "CIDR_BLOCK"
|
||||||
|
tcp_options {
|
||||||
|
min = 22
|
||||||
|
max = 22
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ingress_security_rules {
|
||||||
|
# HTTP (TCP 80)
|
||||||
|
protocol = "6" # TCP
|
||||||
|
source = "0.0.0.0/0"
|
||||||
|
source_type = "CIDR_BLOCK"
|
||||||
|
tcp_options {
|
||||||
|
min = 80
|
||||||
|
max = 80
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ingress_security_rules {
|
||||||
|
# HTTPS (TCP 443)
|
||||||
|
protocol = "6" # TCP
|
||||||
|
source = "0.0.0.0/0"
|
||||||
|
source_type = "CIDR_BLOCK"
|
||||||
|
tcp_options {
|
||||||
|
min = 443
|
||||||
|
max = 443
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ingress_security_rules {
|
||||||
|
# Custom Minecraft
|
||||||
|
protocol = "6" # TCP
|
||||||
|
source = "0.0.0.0/0"
|
||||||
|
source_type = "CIDR_BLOCK"
|
||||||
|
tcp_options {
|
||||||
|
min = 49732
|
||||||
|
max = 49732
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ingress_security_rules {
|
||||||
|
# HTTPS (UDP 443) - For QUIC or specific UDP services
|
||||||
|
protocol = "17" # UDP
|
||||||
|
source = "0.0.0.0/0"
|
||||||
|
source_type = "CIDR_BLOCK"
|
||||||
|
udp_options {
|
||||||
|
min = 443
|
||||||
|
max = 443
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ingress_security_rules {
|
||||||
|
# ICMP (Ping)
|
||||||
|
protocol = "1" # ICMP
|
||||||
|
source = "0.0.0.0/0"
|
||||||
|
source_type = "CIDR_BLOCK"
|
||||||
|
icmp_options {
|
||||||
|
type = 3 # Destination Unreachable (common for connectivity checks)
|
||||||
|
code = 4 # Fragmentation needed
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ingress_security_rules {
|
||||||
|
protocol = "1" # ICMP
|
||||||
|
source = "0.0.0.0/0"
|
||||||
|
source_type = "CIDR_BLOCK"
|
||||||
|
icmp_options {
|
||||||
|
type = 8 # Echo Request (ping)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
resource "oci_core_subnet" "my_public_subnet" {
|
||||||
|
compartment_id = var.compartment_ocid
|
||||||
|
vcn_id = oci_core_vcn.my_vpc.id
|
||||||
|
display_name = "main-public-subnet"
|
||||||
|
cidr_block = "10.0.0.0/24"
|
||||||
|
prohibit_public_ip_on_vnic = false # Allows instances in this subnet to get public IPs
|
||||||
|
route_table_id = oci_core_route_table.my_public_route_table.id
|
||||||
|
security_list_ids = [oci_core_security_list.my_public_security_list.id]
|
||||||
|
dns_label = "mainsub" # Must be unique within the VCN
|
||||||
|
}
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
output "host_ip" {
|
||||||
|
description = "The public IP address of the launched instance."
|
||||||
|
value = oci_core_instance.my_compute_instance.public_ip
|
||||||
|
}
|
||||||
|
|
||||||
|
output "instance_id" {
|
||||||
|
description = "The OCID of the launched instance."
|
||||||
|
value = oci_core_instance.my_compute_instance.id
|
||||||
|
}
|
||||||
|
|
||||||
|
output "vpc_ocid" {
|
||||||
|
description = "The OCID of the created VCN."
|
||||||
|
value = oci_core_vcn.my_vpc.id
|
||||||
|
}
|
||||||
|
|
||||||
|
output "subnet_ocid" {
|
||||||
|
description = "The OCID of the created public subnet."
|
||||||
|
value = oci_core_subnet.my_public_subnet.id
|
||||||
|
}
|
||||||
@@ -0,0 +1,63 @@
|
|||||||
|
variable "boot_volume_size_in_gbs" {
|
||||||
|
description = "The size of the boot volume in GBs."
|
||||||
|
type = number
|
||||||
|
default = 150
|
||||||
|
}
|
||||||
|
|
||||||
|
variable "cloud_init_script" {
|
||||||
|
description = "A cloud-init script to run on instance launch."
|
||||||
|
type = string
|
||||||
|
default = <<-EOF
|
||||||
|
#!/bin/bash
|
||||||
|
echo "Hello from cloud-init!" > /home/ubuntu/cloud-init-output.txt
|
||||||
|
EOF
|
||||||
|
}
|
||||||
|
|
||||||
|
variable "compartment_ocid" {
|
||||||
|
description = "The OCID of the compartment where the instance will be created."
|
||||||
|
type = string
|
||||||
|
default = "ocid1.tenancy.oc1..aaaaaaaaudwr2ozedhjnrn76ofjgglgug6gexknjisd7gb7tkj3mjdp763da"
|
||||||
|
}
|
||||||
|
|
||||||
|
variable "instance_display_name" {
|
||||||
|
description = "A user-friendly name for the instance."
|
||||||
|
type = string
|
||||||
|
default = "noah-nixos"
|
||||||
|
}
|
||||||
|
|
||||||
|
variable "instance_shape" {
|
||||||
|
description = "The shape of the OCI compute instance."
|
||||||
|
type = string
|
||||||
|
default = "VM.Standard.A1.Flex" # Example shape. Choose one available in your region/AD.
|
||||||
|
}
|
||||||
|
|
||||||
|
variable "object_storage_namespace" {
|
||||||
|
description = "Your OCI Object Storage namespace (usually your tenancy name)."
|
||||||
|
type = string
|
||||||
|
default = "idptr5akf9pf"
|
||||||
|
}
|
||||||
|
|
||||||
|
variable "object_storage_bucket_name" {
|
||||||
|
description = "The name of the Object Storage bucket where your custom image is located."
|
||||||
|
type = string
|
||||||
|
default = "noahmasur-images"
|
||||||
|
}
|
||||||
|
|
||||||
|
variable "object_storage_object_name" {
|
||||||
|
description = "The object name (file name) of your custom image in Object Storage."
|
||||||
|
type = string
|
||||||
|
default = "nixos.qcow2"
|
||||||
|
}
|
||||||
|
|
||||||
|
variable "oci_private_key" {
|
||||||
|
type = string
|
||||||
|
description = "API private key for Oracle Cloud management"
|
||||||
|
sensitive = true
|
||||||
|
}
|
||||||
|
|
||||||
|
variable "ssh_public_key" {
|
||||||
|
description = "Your public SSH key content."
|
||||||
|
type = string
|
||||||
|
# default = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIB+AbmjGEwITk5CK9y7+Rg27Fokgj9QEjgc9wST6MA3s personal"
|
||||||
|
default = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIKpPU2G9rSF8Q6waH62IJexDCQ6lY+8ZyVufGE3xMDGw actions-deploy"
|
||||||
|
}
|
||||||
@@ -0,0 +1,151 @@
|
|||||||
|
# Changelog
|
||||||
|
|
||||||
|
## 2026-09-06
|
||||||
|
|
||||||
|
- **Configured OpenID Connect (OIDC) authentication for Immich**:
|
||||||
|
- Configured `services.immich.settings.oauth` with OIDC settings pointing to Pocket ID (`auth.masu.rs`), using client ID `1f4e0f8d-6cee-4d67-8d53-74bf6c18ae09`.
|
||||||
|
- Added secret management for `immich-oidc-secret.age` via `secrets.immich-oidc-secret` with owner `immich` and group `shared` (0440).
|
||||||
|
- Wired client secret substitution using NixOS's native `clientSecret._secret = config.secrets.immich-oidc-secret.dest`, leveraging `utils.genJqSecretsReplacement` with systemd `LoadCredential`.
|
||||||
|
- Configured `systemd.services.immich-server` to order after `immich-oidc-secret-secret.service`.
|
||||||
|
- Updated `docs/oidc-services.md` with the verified configuration and redirect URIs.
|
||||||
|
|
||||||
|
- **Fixed OpenSSH authorized principals certificate authentication for Cloudflare Tunnel**:
|
||||||
|
- Replaced manual `environment.etc."ssh/authorized_principals/${username}"` symlink and `Match User` config with NixOS native `users.users.<name>.openssh.authorizedPrincipals`.
|
||||||
|
- Root cause: `environment.etc` without an explicit `mode` creates symlinks pointing into `/nix/store`, which has group-writable mode `0775` (`nixbld` group). Under `StrictModes yes`, sshd refused authentication with `bad ownership or modes for directory /nix/store`, causing certificate principal matching to fail with `Certificate does not contain an authorized principal`.
|
||||||
|
- Setting `users.users.<name>.openssh.authorizedPrincipals` causes NixOS to generate `/etc/ssh/authorized_principals.d/<name>` with `mode = "0444"`, copying the file instead of symlinking into the store, and automatically configuring `services.openssh.settings.AuthorizedPrincipalsFile = "/etc/ssh/authorized_principals.d/%u"`.
|
||||||
|
- Also added `mode = "0444"` to `/etc/ssh/ca.pub` and moved `TrustedUserCAKeys` into `services.openssh.settings`.
|
||||||
|
|
||||||
|
- **Configured OpenID Connect (OIDC) authentication for Mealie**:
|
||||||
|
- Configured `services.mealie.settings` with OIDC settings pointing to Pocket ID (`auth.masu.rs`), using client ID `040925ed-b39e-4442-b8e8-369c948c0cd2`.
|
||||||
|
- Added secret management for `mealie-oidc-secret.age` via `secrets.mealie-oidc-secret`, using `prefix = "OIDC_CLIENT_SECRET="` to generate an environment file.
|
||||||
|
- Configured `services.mealie.credentialsFile` to load the client secret via systemd's `EnvironmentFile` without exposing it in the world-readable Nix store or systemd unit file.
|
||||||
|
- Configured `systemd.services.mealie` to order after `mealie-oidc-secret-secret.service`.
|
||||||
|
- Updated `docs/oidc-services.md` with the verified configuration and callback URI (`https://cooking.masu.rs/login`).
|
||||||
|
|
||||||
|
- **Configured OpenID Connect (OIDC) authentication for Actual Budget**:
|
||||||
|
- Configured `services.actual.settings` with `loginMethod = "openid"` and `openId` settings pointing to Pocket ID (`auth.masu.rs`), using client ID `92afe9f8-7ef6-42ab-8a06-701df3c7179d`.
|
||||||
|
- Added secret management for `actualbudget-oidc-secret.age` via `secrets.actualbudget-oidc-secret`, set with owner `actualbudget` and group `shared` (0440).
|
||||||
|
- Configured `systemd.services.actual` to order after the decrypted secret service and granted the dynamic unit access via `SupplementaryGroups = [ "shared" ]` and `PrivateUsers = false`.
|
||||||
|
- Updated `docs/oidc-services.md` with the verified callback URI (`https://money.masu.rs/openid/callback`) and NixOS configuration snippet.
|
||||||
|
|
||||||
|
## 2026-08-29 (root cause found and fixed)
|
||||||
|
|
||||||
|
- **Root-caused and fixed the recurring post-TUI typing lag** (fish + Zellij + Ghostty) using a `lag-triage` capture from a live lagging shell plus a deterministic PTY reproduction (`presets/programs/lag-triage/upstream_repro.py`):
|
||||||
|
- **Root cause chain**: (1) fish latches feature flags from its **startup environment**, before `config.fish` runs — so the existing `set -gx fish_features no-query-term` in `shellInit` never applied to the shell that set it, only to its children. (2) Zellij spawns pane shells via `default_shell` with no `fish_features` in the environment, so every pane's fish latched `query-term` **on** (the fish 4.8.1 default; the triage log from the lagging shell confirmed `query-term on` while `$fish_features` was correctly set to `no-query-term`). (3) With query-term on, fish sends OSC 11 + CPR (`\e[6n`) + DA1 (`\e[0c`) after **every** command and waits for replies relayed by Zellij. (4) Reproduced on fish 4.8.1: if the terminal fails to reply during just **one** such cycle — answering everything before and after — that fish process's interactive reader is **permanently degraded** (keystroke echo >3s, never recovers; ~35ms before). In production Zellij drops/mangles a relay during TUI teardown or heavy output (cf. zellij-org/zellij#5158), e.g. after `nh home switch`, nvim, jjui, yazi.
|
||||||
|
- **Why every previous observation finally makes sense**: subshells and `exec fish` were never "resetting" anything — they *inherited* the exported `fish_features=no-query-term` from config.fish, latched query-term off at startup, and were therefore **immune**. The parent zellij-spawned shell never had the variable at startup and stayed vulnerable. Raw keystroke capture in the lagging pane showed instant plain bytes (input path fine) and no stuck terminal modes — the damage was inside the fish process, exactly as the repro shows.
|
||||||
|
- **Fix**: `zellij.nix` now spawns panes through a `fish-no-query-term` wrapper (`export fish_features=no-query-term; exec fish`), so the feature is latched off in every pane shell. Verified: interactive fish through the built wrapper with the real config reports `query-term off`; the PTY repro with `no-query-term` in the environment shows ~35ms echo through all failure phases.
|
||||||
|
- **Correction** to the earlier 2026-08-29 entry: `query-term` does **not** default to off in fish 4.8.1 — it defaults on; it only *appeared* off in non-interactive checks because the user config's `set -gx` takes effect for `fish -c` (no reader latch) but not for interactive shells.
|
||||||
|
- Upstream: fish-shell should bound the reader's wait for query replies instead of degrading permanently (repro script kept at `presets/programs/lag-triage/upstream_repro.py` for filing); Zellij's reply relaying is the trigger (zellij-org/zellij#5158).
|
||||||
|
- `lag-triage` now checks `status features` and calls out `query-term on` as the known root cause, and warns that its `read`-prompt typing tests may not exhibit main-commandline lag (which produced a false "fixed by stage A" in the first capture).
|
||||||
|
|
||||||
|
## 2026-08-29 (later)
|
||||||
|
|
||||||
|
- Added a diagnostic toolkit (`lag-triage` / `unlag` fish functions + `term-probe` binary, `presets/programs/lag-triage/`) for the still-recurring post-TUI typing lag in fish + Zellij + Ghostty, instead of another blind fix. Findings that motivated it:
|
||||||
|
- All three prior fixes were either no-ops or insufficient: `fish_features = no-query-term` is a **no-op** because `query-term` already defaults to *off* in fish 4.8.1 (verified with `status features`); disabling Ghostty's fish integration inside Zellij and setting `support_kitty_keyboard_protocol = false` did not stop recurrence.
|
||||||
|
- PTY captures of fish 4.8.1 (`TERM=xterm-256color`, with and without `$ZELLIJ`) show fish never writes Kitty keyboard sequences to the wire — it uses modifyOtherKeys (`\e[>4;1m`), application keypad (`\e=`), bracketed paste (`?2004`), and color-theme reporting (`?2031`), enabling them at every prompt and disabling them before every external command. Crucially, a fresh subshell's startup bytes are identical to the parent's post-command re-enable bytes, so "a subshell fixes the lag" cannot be explained by a simple terminal-state reset — leaving two competing hypotheses that only live capture can separate: (1) fish-internal reader state poisoned by stray/partial escape bytes (e.g. leaked from a closing floating pane), cleared only by a new fish process; (2) Zellij/Ghostty-level stuck state (Zellij 0.45's `StdinAnsiParser` is already a proven source of input delays — see the Alt-Shift-P fix below).
|
||||||
|
- Also note: the floating-pane TUIs (jjui via Alt-Shift-J, yazi via Alt-Shift-Y, scrollback editor) run in their own panes and never pass through the shell's fish process at all, while `nvim` runs inside the shell pane — the triage log records which path preceded the lag.
|
||||||
|
- **Next occurrence: run `lag-triage` in the lagging shell BEFORE starting a new shell.** It snapshots the environment, queries pane terminal state (kitty flags, modifyOtherKeys, DEC modes, DA1 round-trip latency), captures raw keystroke bytes+timing bypassing fish, then applies staged resets (kitty pop/clear, modifyOtherKeys off, keypad/cursor, mouse/focus/sync, altscreen, stty, DECSTR) — the stage that cures it names the stuck layer. Logs to `~/.local/state/lag-triage/` for an upstream issue. `unlag` is the one-shot convenience version (if `unlag` never helps but `exec fish` does, the bug is fish-internal).
|
||||||
|
|
||||||
|
## 2026-08-29
|
||||||
|
|
||||||
|
- Fixed 1.5-second latency when pressing `Alt-Shift-P` to trigger `zellij-session` in Zellij 0.45.0 + Ghostty:
|
||||||
|
- **Root Cause**: Zellij 0.45.0 introduced `StdinAnsiParser` (`zellij-client/src/stdin_ansi_parser.rs`) using `termwiz::InputParser` to parse ANSI control strings (OSCs, CSIs, DCSs) arriving on stdin. When pressing `Alt-Shift-P` (Option-Shift-P) with `support_kitty_keyboard_protocol = false`, Ghostty sent `\x1bP` (`ESC` + uppercase `P`). In ECMA-48 / VT100 standards, `ESC P` is the 7-bit ASCII representation of `DCS` (Device Control String). `StdinAnsiParser` buffered `\x1bP` waiting for a DCS string payload and string terminator (`ST` / `\x1b\`), hitting a ~1.5-second escape timeout before flushing `\x1bP` as residue to the keyboard handler.
|
||||||
|
- **Fix**: Added `alt+shift+p=text:\x1b[112;4u` and `super+shift+p=text:\x1b[112;4u` in `ghostty.nix` to send the explicit CSI-u sequence for `Alt+Shift+p` (`'p'` with modifier 4 = `ALT | SHIFT`). `StdinAnsiParser` immediately recognizes `\x1b[112;4u` as non-DCS input and passes it straight to the keyboard handler with 0ms latency.
|
||||||
|
|
||||||
|
## 2026-08-26
|
||||||
|
|
||||||
|
- Fixed macOS shortcuts (`Cmd+T`, `Ctrl+Tab`, `Cmd+Shift+]`, `Cmd+Shift+[`, `Cmd+K`, `Cmd+Shift+E`) in Zellij + Ghostty after disabling the Kitty keyboard protocol:
|
||||||
|
- Mapped Ghostty keybindings (`super+t`, `super+shift+]`, `super+shift+[`, `ctrl+tab`, `ctrl+shift+tab`, `super+k`, `super+shift+e`) to send standard `Alt` (`ESC`-prefix) text sequences (`\x1bt`, `\x1b}`, `\x1b{`, `\x1bK`, `\x1bE`).
|
||||||
|
- Added matching `Alt` keybindings (`Alt t`, `Alt ]`, `Alt }`, `Alt [`, `Alt {`, `Alt Shift k`, `Alt Shift e`) in `zellij.nix` for tab creation, tab navigation, scroll mode, and scrollback editing. Symbols like `]` and `}` are parsed by Zellij's termwiz input engine as distinct character codes (`'}'` vs `']'`), so binding both `Alt }` and `Alt Shift ]` ensures `\x1b}` triggers tab navigation correctly.
|
||||||
|
- Keeps Kitty keyboard protocol disabled in Zellij (`support_kitty_keyboard_protocol = false`) so no CSI-u flags leak into Fish shell, guaranteeing zero post-TUI typing lag while restoring all shortcuts.
|
||||||
|
|
||||||
|
- Fixed persistent Fish typing lag after long TUI sessions (Neovim, jjui, Yazi) inside Zellij + Ghostty, which the `no-query-term` / Ghostty-integration fixes from 2026-08-25 did not resolve:
|
||||||
|
- Verified on Fish 4.8.1 that the `query-term` feature already defaults to `off`, so exporting `fish_features = no-query-term` is a no-op on this Fish version — it isn't the cause of (or fix for) this class of lag.
|
||||||
|
- Set `support_kitty_keyboard_protocol = false` in `zellij.nix`. Zellij and Ghostty have several open upstream bugs (zellij-org/zellij#3887, #3723, #4178) where the Kitty keyboard protocol's enhancement-flag stack is left in an elevated state after a full-screen TUI exits without properly popping it. Every subsequent keystroke then arrives as a CSI-u sequence that Fish must wait out an escape-disambiguation timeout to parse, which reads as typing lag that worsens the longer the TUI session ran, and persists until the pane's protocol state resets (e.g. a fresh shell/pane). Disabling the protocol support in Zellij avoids the whole bug class; trades off precise modifier reporting (e.g. distinguishing Ctrl+Shift+key) for TUIs running inside Zellij panes, which this setup doesn't otherwise depend on (Shift+Enter is handled via a literal Ghostty `text:` keybind, not the Kitty protocol).
|
||||||
|
|
||||||
|
## 2026-08-25
|
||||||
|
|
||||||
|
- Fixed Nix evaluation warnings for `stdenv` deprecation and `gemini-cli`:
|
||||||
|
- Replaced deprecated `stdenv.isLinux` and `stdenv.isDarwin` checks across module presets and package definitions with `stdenv.hostPlatform.isLinux` and `stdenv.hostPlatform.isDarwin`.
|
||||||
|
- Replaced deprecated `pkgs.gemini-cli` with `pkgs.antigravity-cli` (and updated binary invocation to `agy`) in `experimental.nix` profile and `daily-summary.nix` launchd service.
|
||||||
|
|
||||||
|
## 2026-08-25
|
||||||
|
|
||||||
|
- Fixed multi-second hang and permanent typing latency in Fish after exiting TUIs inside Zellij and Ghostty:
|
||||||
|
- Exported `fish_features = "no-query-term"` in `home.sessionVariables` and added `set -gx fish_features no-query-term` to Fish's top-level `shellInit`. Previous attempt (`set -a fish_features no-query-term` in `interactiveShellInit`) set a local variable inside an anonymous initialization function block that went out of scope immediately after startup. Furthermore, Fish reads `fish_features` at binary launch before interactive init functions run. Without `no-query-term` exported prior to Fish startup, Fish attempted terminal feature queries (Primary Device Attributes `DA1` / `\e[?c` and termcap) whenever a TUI (e.g. Neovim, Lazygit, Yazi) exited and returned control to Fish. Zellij drops or delays DA1 response sequences, causing Fish to block on a multi-second stdin timeout, followed by severe input reader desynchronization and typing latency on every subsequent keystroke.
|
||||||
|
- Disabled `programs.ghostty.enableFishIntegration` and conditionally sourced Ghostty's shell integration script in `shellInit` only when NOT running inside a multiplexer (`not set -q ZELLIJ` and `not set -q TMUX`). Sourcing Ghostty's shell integration inside Zellij sent duplicate and conflicting OSC 133 prompt markers and DECSCUSR cursor escape sequences to Zellij's PTY parser.
|
||||||
|
|
||||||
|
## 2026-08-16
|
||||||
|
|
||||||
|
- Fixed Zellij new tab directory tracking by adding `__fish_update_cwd_osc` override in `presets/programs/zellij.nix`. Fish's default OSC 7 sequence includes `$hostname`, which on macOS or dynamic network environments evaluates to `Noah-MacBook-Pro.local` or a domain suffix. Zellij compares the OSC 7 hostname against its system hostname (`Noah-MacBook-Pro`), finds a mismatch, and silently ignores the CWD update, leaving new tabs stuck in a previous directory or session default. Overriding `__fish_update_cwd_osc` to send `file://<PWD>` (empty hostname) ensures Zellij always updates its cached CWD on every `cd` and prompt render.
|
||||||
|
- Fixed Firefox "profile cannot be loaded" error on macOS by removing `home.file."Library/Application Support/Firefox/installs.ini"`. Hardcoding an installation hash in `installs.ini` broke whenever Firefox was updated or rebuilt in the Nix store because the nix store path changed, causing Firefox to compute a new installation hash, fail to match or write to the read-only `installs.ini` symlink, and error out. Firefox on macOS uses `profiles.ini` (managed by Home Manager) and `MOZ_LEGACY_PROFILES=1` (exported by nixpkgs' launcher wrapper).
|
||||||
|
|
||||||
|
## 2026-08-03
|
||||||
|
|
||||||
|
- Added `presets/security/corporate-ca.nix` (nix-darwin) and enabled it on the
|
||||||
|
`lookingglass` host to trust a corporate TLS-intercepting proxy's root CA.
|
||||||
|
Behind the corp network, Nix fetches failed with `SSL peer certificate ...
|
||||||
|
self-signed certificate in certificate chain (19)` because Nix's stock Mozilla
|
||||||
|
CA bundle doesn't contain the interception root. The module appends the cert
|
||||||
|
to `security.pki.certificateFiles`, which rebuilds
|
||||||
|
`/etc/ssl/certs/ca-certificates.crt` (read by both the Nix daemon and, via
|
||||||
|
`NIX_SSL_CERT_FILE`, client-side flake fetches).
|
||||||
|
|
||||||
|
The cert is kept **out of this public repo** and referenced by absolute path.
|
||||||
|
It is passed as a string (not a Nix path literal) so pure flake evaluation
|
||||||
|
doesn't read it at eval time, and it lives at a root-owned, world-readable
|
||||||
|
path because the unprivileged `nixbld` build user cannot traverse `$HOME`
|
||||||
|
(mode `0750`) to read it at build time.
|
||||||
|
|
||||||
|
One-time setup on a machine behind the proxy:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
# 1. Extract the self-signed corporate root from any TLS connection it MITMs
|
||||||
|
# (the last cert in the chain, subject == issuer). Any HTTPS host works:
|
||||||
|
echo | openssl s_client -connect example.com:443 -servername example.com \
|
||||||
|
-showcerts 2>/dev/null \
|
||||||
|
| awk '/BEGIN CERT/{c++} c==2' > /tmp/CorpCA.pem
|
||||||
|
openssl x509 -in /tmp/CorpCA.pem -noout -subject -issuer # sanity check
|
||||||
|
|
||||||
|
# 2. Install to the root-owned path the config points at:
|
||||||
|
sudo install -d -m 0755 -o root -g wheel /etc/ssl/corp-ca
|
||||||
|
sudo install -m 0644 -o root -g wheel /tmp/CorpCA.pem \
|
||||||
|
/etc/ssl/corp-ca/CorpCA.pem
|
||||||
|
|
||||||
|
# 3. Bootstrap the first rebuild (which must fetch inputs over the proxy)
|
||||||
|
# with a combined bundle, then it's permanent:
|
||||||
|
cat /etc/ssl/certs/ca-certificates.crt /etc/ssl/corp-ca/CorpCA.pem \
|
||||||
|
> /tmp/combined-ca.crt
|
||||||
|
NIX_SSL_CERT_FILE=/tmp/combined-ca.crt nh darwin switch . --configuration lookingglass
|
||||||
|
```
|
||||||
|
|
||||||
|
- Fixed the `zellij-session` fish function in `presets/programs/zellij.nix`
|
||||||
|
truncating the session name (derived from the target directory basename)
|
||||||
|
to 20 characters. Zellij names each session's Unix-domain IPC socket
|
||||||
|
`$TMPDIR/zellij-<uid>/<version>/<name>`, and on macOS the socket path is
|
||||||
|
capped at 103 bytes. The `/var/folders/...` `$TMPDIR` prefix consumes ~79
|
||||||
|
of those, leaving only ~24 chars for the name, so switching into directories
|
||||||
|
with long basenames overflowed the socket path. Because `switch-session`
|
||||||
|
had already detached from the current session by the time the new one failed
|
||||||
|
to bind, the failure took down the entire terminal instead of erroring
|
||||||
|
gracefully.
|
||||||
|
|
||||||
|
## 2026-09-06
|
||||||
|
|
||||||
|
- Configured Grafana OIDC authentication via Pocket ID in `platforms/nixos/modules/nmasur/presets/services/grafana/grafana.nix`.
|
||||||
|
- Enabled `auth.oauth_allow_insecure_email_lookup = true` in Grafana settings to allow linking an incoming OAuth login to an existing Grafana user account with the same email.
|
||||||
|
|
||||||
|
## 2026-07-25
|
||||||
|
|
||||||
|
- Added jjui config generation to `jujutsu.nix` in Home Manager to include custom GitHub ruleset bypass commands (`ctrl+b` and `ctrl+shift+b`).
|
||||||
|
- Added `overlays/cheetah3.nix` to disable `pythonMetadataCheckPhase` for `cheetah3`.
|
||||||
|
This fixes an issue where the NixOS rebuild fails for `sabnzbd` due to `importlib.metadata.PackageNotFoundError: No package metadata was found for cheetah3` during the Python package evaluation in `nixos-unstable`.
|
||||||
|
|
||||||
|
## 2026-07-20
|
||||||
|
|
||||||
|
- Added `overlays/paho-mqtt.nix` to disable paho-mqtt's flaky, socket-based
|
||||||
|
test suite. Its `checkPhase` hangs in the Nix sandbox and times out with a
|
||||||
|
`KeyboardInterrupt` after ~150s, which was breaking the `flame` rebuild
|
||||||
|
(paho-mqtt is pulled in transitively, e.g. via mealie). The override is
|
||||||
|
applied through `pythonPackagesExtensions` so it covers every Python
|
||||||
|
package set.
|
||||||
@@ -0,0 +1,247 @@
|
|||||||
|
# OIDC Service Analysis & Setup Requirements
|
||||||
|
|
||||||
|
This document analyzes the services defined in this repository (specifically within `platforms/nixos/modules/nmasur/presets/services/` and related server profiles like `flame` and `swan`), evaluates their OpenID Connect (OIDC) compatibility, and details the requirements for configuring OIDC logins.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Identity Provider Context: Pocket ID
|
||||||
|
|
||||||
|
The configuration already includes a central self-hosted identity provider: **Pocket ID** (`platforms/nixos/modules/nmasur/presets/services/pocket-id/pocket-id.nix`), hosted on the communications server (`flame`) behind Caddy at **`https://auth.masu.rs`**.
|
||||||
|
|
||||||
|
Pocket ID is an OpenID Connect (OIDC) provider with WebAuthn/Passkey support. It exposes the following standard OIDC endpoints:
|
||||||
|
- **Issuer URL:** `https://auth.masu.rs`
|
||||||
|
- **Discovery Endpoint:** `https://auth.masu.rs/.well-known/openid-configuration`
|
||||||
|
- **Authorization Endpoint:** `https://auth.masu.rs/authorize`
|
||||||
|
- **Token Endpoint:** `https://auth.masu.rs/api/oidc/token`
|
||||||
|
- **Userinfo Endpoint:** `https://auth.masu.rs/api/oidc/userinfo`
|
||||||
|
- **JWKS Endpoint:** `https://auth.masu.rs/.well-known/jwks.json`
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 1. Service Compatibility Breakdown
|
||||||
|
|
||||||
|
### Tier 1: First-Class / Native OIDC Support
|
||||||
|
|
||||||
|
These services support OpenID Connect natively without requiring external authentication proxies or custom code:
|
||||||
|
|
||||||
|
| Service | Hostname | OIDC Support Level | Configuration Method |
|
||||||
|
| :--- | :--- | :--- | :--- |
|
||||||
|
| **Immich** | `photos.masu.rs` | Native core feature | NixOS config (`services.immich.settings.oauth`) |
|
||||||
|
| **Gitea** | `git.masu.rs` | Native core feature | NixOS config / CLI or Web UI |
|
||||||
|
| **Nextcloud** | `cloud.masu.rs` | Native (official `user_oidc` app) | Nextcloud app + `nextcloud-occ user_oidc:provider` |
|
||||||
|
| **Grafana** | `metrics.masu.rs` | Native (Generic OAuth) | NixOS config (`services.grafana.settings."auth.generic_oauth"`) |
|
||||||
|
| **Paperless-ngx** | `paper.masu.rs` | Native (`django-allauth`) | NixOS env vars (`PAPERLESS_SOCIALACCOUNT_PROVIDERS`) |
|
||||||
|
| **Mealie** | `cooking.masu.rs` | Native core feature | NixOS config (`services.mealie.settings` + `credentialsFile`) |
|
||||||
|
| **Karakeep / Hoarder** | `keep.masu.rs` | Native (NextAuth OIDC) | NixOS env vars (`OAUTH_WELLKNOWN_URL`, etc.) |
|
||||||
|
| **Audiobookshelf** | `read.masu.rs` | Native core feature (v2.3+) | Web UI (Settings → Authentication) |
|
||||||
|
| **Actual Budget** | `money.masu.rs` | Native core feature (v24.3+) | NixOS config (`services.actual.settings.openId`) |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### Tier 2: OIDC via Plugins or Reverse Proxy Header Auth
|
||||||
|
|
||||||
|
These services do not have generic OIDC in their core web UI, but can support single sign-on through plugins or reverse proxy headers (`Remote-User` / `X-Forwarded-User`):
|
||||||
|
|
||||||
|
| Service | Hostname | Strategy | Notes |
|
||||||
|
| :--- | :--- | :--- | :--- |
|
||||||
|
| **Jellyfin** | `stream.masu.rs` | `jellyfin-plugin-sso` | Web clients work well; TV and native apps typically rely on Quick Connect. |
|
||||||
|
| **Calibre-Web** | `books.masu.rs` | Reverse proxy header auth | Set `services.calibre-web.options.reverseProxyAuth.enable = true` behind an authenticating reverse proxy. |
|
||||||
|
| **File Browser** | `files.masu.rs` | Reverse proxy header auth | Set `auth.method = "proxy"` and `auth.header = "X-Forwarded-User"` behind an authenticating reverse proxy. |
|
||||||
|
| **Navidrome** | `music.masu.rs` | Reverse proxy header auth | Supports `ReverseProxyUserHeader` for web UI; Subsonic API clients (Feishin, etc.) still require native user passwords. |
|
||||||
|
| **Stalwart** | `contacts.masu.rs` | OIDC Directory / SASL OAuth | Stalwart supports OIDC directories, but CardDAV/CalDAV clients usually require HTTP Basic Auth or application passwords. |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### Tier 3: Incompatible or No Native OIDC Support
|
||||||
|
|
||||||
|
- **Vaultwarden (`vault.masu.rs`):** Incompatible for vault decryption. Vaultwarden uses client-side zero-knowledge encryption where vault keys are derived from the user's master password. Bitwarden Enterprise SSO relies on a proprietary Key Connector that Vaultwarden does not implement.
|
||||||
|
- **n8n (`n8n.masu.rs`):** SAML/OIDC SSO is an **Enterprise / commercial-only feature**; it is disabled in the free self-hosted Community edition.
|
||||||
|
- **The Arr Stack (`download.masu.rs`):** Radarr, Sonarr, Lidarr, Readarr, Prowlarr, Bazarr, and Sabnzbd only support API keys, Basic Auth, or Forms.
|
||||||
|
- **Transmission (`transmission.masu.rs`):** BitTorrent daemon; supports only HTTP Basic Auth / RPC whitelist.
|
||||||
|
- **Uptime Kuma (`status.masu.rs`), ntfy (`ntfy.masu.rs`), The Lounge (`irc.masu.rs`), Pgweb (`pg.masu.rs`), Mathesar (`mathesar.masu.rs`), Hister (`hister.masu.rs`):** No native generic OIDC login mechanism.
|
||||||
|
- **Infrastructure / Daemon Services:** PostgreSQL, InfluxDB, bind, avahi, cloudflared, wireguard, litestream (no user web UI).
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 2. General Setup Requirements
|
||||||
|
|
||||||
|
Configuring OIDC requires setup across four layers:
|
||||||
|
|
||||||
|
### A. Pocket ID Setup
|
||||||
|
For each service, an OIDC client application must be registered in the Pocket ID admin interface:
|
||||||
|
1. **Client ID:** A unique identifier slug (e.g. `gitea`, `immich`, `paperless`).
|
||||||
|
2. **Client Secret:** A cryptographically secure random token.
|
||||||
|
3. **Redirect URIs / Callback URLs:** The exact target URLs the service exposes for authorization code callbacks.
|
||||||
|
4. **Scopes:** Usually `openid`, `profile`, and `email`.
|
||||||
|
|
||||||
|
### B. Secrets Management (agenix)
|
||||||
|
All client secrets should be encrypted with `agenix` under the respective service directory:
|
||||||
|
- Example: `platforms/nixos/modules/nmasur/presets/services/<service>/<service>-oidc.age`
|
||||||
|
- Defined in NixOS under `config.secrets.<service>-oidc` with appropriate owner/group permissions.
|
||||||
|
|
||||||
|
### C. Network & Reverse Proxy (Caddy)
|
||||||
|
1. **Back-Channel Connectivity:** When a user logs in, the service backend makes a server-to-server HTTPS call to `https://auth.masu.rs/api/oidc/token` to exchange the authorization code for tokens. Services hosted on `swan` (NAS) must be able to resolve and reach `auth.masu.rs` over HTTPS.
|
||||||
|
2. **Proxy Headers:** Caddy's `reverse_proxy` handles `X-Forwarded-Proto`, `X-Forwarded-Host`, and `X-Forwarded-For` by default. Services should have reverse proxy trust enabled (e.g., `trusted_proxies = ["127.0.0.1"]`) so generated redirect URIs preserve the `https://` scheme.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 3. Detailed Setup Requirements for Tier 1 Services
|
||||||
|
|
||||||
|
### 1. Immich (`photos.masu.rs`)
|
||||||
|
- **Pocket ID Redirect URIs:**
|
||||||
|
- Web: `https://photos.masu.rs/auth/login`
|
||||||
|
- Mobile: `app.immich:///oauth-callback`
|
||||||
|
- **Setup in `immich/immich.nix`:**
|
||||||
|
```nix
|
||||||
|
services.immich.settings.oauth = {
|
||||||
|
enabled = true;
|
||||||
|
issuerUrl = "https://${hostnames.auth}";
|
||||||
|
clientId = "1f4e0f8d-6cee-4d67-8d53-74bf6c18ae09";
|
||||||
|
clientSecret._secret = config.secrets.immich-oidc-secret.dest;
|
||||||
|
scope = "openid profile email";
|
||||||
|
autoRegister = true;
|
||||||
|
buttonText = "Login with Pocket ID";
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2. Gitea (`git.masu.rs`)
|
||||||
|
- **Pocket ID Redirect URI:** `https://git.masu.rs/user/oauth2/pocket-id/callback`
|
||||||
|
- **Setup in Gitea:**
|
||||||
|
Can be configured in the Web UI under **Site Administration → Authentication Sources** or via CLI:
|
||||||
|
```bash
|
||||||
|
gitea admin auth add-oauth \
|
||||||
|
--name "Pocket ID" \
|
||||||
|
--provider openidConnect \
|
||||||
|
--key "<client_id>" \
|
||||||
|
--secret "<client_secret>" \
|
||||||
|
--auto-discover-url "https://auth.masu.rs/.well-known/openid-configuration"
|
||||||
|
```
|
||||||
|
- Optional: Enable automatic account linking by matching email.
|
||||||
|
|
||||||
|
### 3. Nextcloud (`cloud.masu.rs`)
|
||||||
|
- **Pocket ID Redirect URI:** `https://cloud.masu.rs/apps/user_oidc/code`
|
||||||
|
- **Setup in `nextcloud/nextcloud.nix`:**
|
||||||
|
1. Add `user_oidc` to `services.nextcloud.extraApps`.
|
||||||
|
2. Configure the provider via `nextcloud-occ`:
|
||||||
|
```bash
|
||||||
|
nextcloud-occ user_oidc:provider pocket-id \
|
||||||
|
--clientid="<client_id>" \
|
||||||
|
--clientsecret="<client_secret>" \
|
||||||
|
--discoveryuri="https://auth.masu.rs/.well-known/openid-configuration" \
|
||||||
|
--scope="openid profile email"
|
||||||
|
```
|
||||||
|
|
||||||
|
### 4. Grafana (`metrics.masu.rs`)
|
||||||
|
- **Pocket ID Redirect URI:** `https://metrics.masu.rs/login/generic_oauth`
|
||||||
|
- **Setup in `grafana/grafana.nix`:**
|
||||||
|
```nix
|
||||||
|
services.grafana.settings = {
|
||||||
|
auth.oauth_allow_insecure_email_lookup = true;
|
||||||
|
"auth.generic_oauth" = {
|
||||||
|
enabled = true;
|
||||||
|
name = "Pocket ID";
|
||||||
|
allow_sign_up = true;
|
||||||
|
client_id = "85d879ed-1a86-4984-b33d-43806500ef98";
|
||||||
|
client_secret = "$__file{${config.secrets.grafana-oidc-secret.dest}}";
|
||||||
|
scopes = "openid profile email";
|
||||||
|
auth_url = "https://${hostnames.auth}/authorize";
|
||||||
|
token_url = "https://${hostnames.auth}/api/oidc/token";
|
||||||
|
api_url = "https://${hostnames.auth}/api/oidc/userinfo";
|
||||||
|
login_attribute_path = "preferred_username";
|
||||||
|
skip_org_role_sync = true;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
|
### 5. Paperless-ngx (`paper.masu.rs`)
|
||||||
|
- **Pocket ID Redirect URI:** `https://paper.masu.rs/accounts/oidc/pocket-id/login/callback/`
|
||||||
|
- **Setup in `paperless/paperless.nix`:**
|
||||||
|
```nix
|
||||||
|
services.paperless.settings = {
|
||||||
|
PAPERLESS_APPS = "allauth.socialaccount.providers.openid_connect";
|
||||||
|
PAPERLESS_SOCIALACCOUNT_PROVIDERS = builtins.toJSON {
|
||||||
|
openid_connect = {
|
||||||
|
SERVERS = [
|
||||||
|
{
|
||||||
|
id = "pocket-id";
|
||||||
|
name = "Pocket ID";
|
||||||
|
server_url = "https://auth.masu.rs";
|
||||||
|
token_auth_method = "client_secret_basic";
|
||||||
|
APP = {
|
||||||
|
client_id = "paperless";
|
||||||
|
secret = "..."; # or via environmentFile
|
||||||
|
};
|
||||||
|
}
|
||||||
|
];
|
||||||
|
};
|
||||||
|
};
|
||||||
|
PAPERLESS_REDIRECT_LOGIN_TO_SSO = "true"; # Optional: bypass local login
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
|
### 6. Mealie (`cooking.masu.rs`)
|
||||||
|
- **Pocket ID Redirect URI:** `https://cooking.masu.rs/login`
|
||||||
|
- **Setup in `mealie/mealie.nix`:**
|
||||||
|
```nix
|
||||||
|
services.mealie = {
|
||||||
|
credentialsFile = config.secrets.mealie-oidc-secret.dest;
|
||||||
|
settings = {
|
||||||
|
OIDC_AUTH_ENABLED = "true";
|
||||||
|
OIDC_SIGNUP_ENABLED = "true";
|
||||||
|
OIDC_CONFIGURATION_URL = "https://${hostnames.auth}/.well-known/openid-configuration";
|
||||||
|
OIDC_CLIENT_ID = "040925ed-b39e-4442-b8e8-369c948c0cd2";
|
||||||
|
OIDC_PROVIDER_NAME = "Pocket ID";
|
||||||
|
OIDC_USER_CLAIM = "email";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
|
### 7. Karakeep / Hoarder (`keep.masu.rs`)
|
||||||
|
- **Pocket ID Redirect URI:** `https://keep.masu.rs/api/auth/callback/custom`
|
||||||
|
- **Setup in `karakeep.nix`:**
|
||||||
|
```nix
|
||||||
|
services.karakeep.extraEnvironment = {
|
||||||
|
OAUTH_WELLKNOWN_URL = "https://auth.masu.rs/.well-known/openid-configuration";
|
||||||
|
OAUTH_CLIENT_ID = "hoarder";
|
||||||
|
OAUTH_CLIENT_SECRET = "...";
|
||||||
|
OAUTH_PROVIDER_NAME = "Pocket ID";
|
||||||
|
OAUTH_ALLOW_DANGEROUS_EMAIL_ACCOUNT_LINKING = "true";
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
|
### 8. Audiobookshelf (`read.masu.rs`)
|
||||||
|
- **Pocket ID Redirect URIs:**
|
||||||
|
- Web: `https://read.masu.rs/auth/openid/callback`
|
||||||
|
- Mobile: `audiobookshelf://oauth`
|
||||||
|
- **Setup in Audiobookshelf:**
|
||||||
|
Configured in the Web UI (**Settings → Authentication → OpenID Connect**):
|
||||||
|
- Issuer URL: `https://auth.masu.rs`
|
||||||
|
- Client ID & Client Secret
|
||||||
|
- Match user by email or username
|
||||||
|
|
||||||
|
### 9. Actual Budget (`money.masu.rs`)
|
||||||
|
- **Pocket ID Redirect URI:** `https://money.masu.rs/openid/callback`
|
||||||
|
- **Setup in `actualbudget/actualbudget.nix`:**
|
||||||
|
```nix
|
||||||
|
services.actual.settings = {
|
||||||
|
loginMethod = "openid";
|
||||||
|
openId = {
|
||||||
|
discoveryURL = "https://${hostnames.auth}/.well-known/openid-configuration";
|
||||||
|
client_id = "92afe9f8-7ef6-42ab-8a06-701df3c7179d";
|
||||||
|
client_secret._secret = config.secrets.actualbudget-oidc-secret.dest;
|
||||||
|
server_hostname = "https://${hostnames.budget}";
|
||||||
|
authMethod = "openid";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
```
|
||||||
|
*Note:* The optional end-to-end budget encryption password remains separate from the server authentication.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 4. Forward Auth Architecture for Remaining Services
|
||||||
|
|
||||||
|
For services without native OIDC support (such as Calibre-Web, File Browser, Uptime Kuma, and the Arr stack), you can implement **Forward Auth via Caddy**:
|
||||||
|
|
||||||
|
1. Deploy an authenticating proxy (such as **OAuth2-Proxy** or **Authelia**) configured with Pocket ID as its OIDC provider.
|
||||||
|
2. Configure Caddy routes using the `forward_auth` directive to verify user sessions with the proxy before forwarding requests to the target service.
|
||||||
|
3. For services supporting reverse proxy authentication (Calibre-Web and File Browser), Caddy injects identity headers (e.g. `Remote-User: noah` or `X-Forwarded-User: noah`), enabling seamless single sign-on without requiring separate logins.
|
||||||
Generated
+313
-161
@@ -1,12 +1,18 @@
|
|||||||
{
|
{
|
||||||
"nodes": {
|
"nodes": {
|
||||||
"cl-nix-lite": {
|
"cl-nix-lite": {
|
||||||
|
"inputs": {
|
||||||
|
"flake-parts": "flake-parts",
|
||||||
|
"nixpkgs": "nixpkgs",
|
||||||
|
"systems": "systems",
|
||||||
|
"treefmt-nix": "treefmt-nix"
|
||||||
|
},
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1728174978,
|
"lastModified": 1782994178,
|
||||||
"narHash": "sha256-Grqqg+xuicANB85j0gNEXxi9SBKY7bzGeTuyi95eGcY=",
|
"narHash": "sha256-VGc3/2fe6hnOmNSLlOygEAbeS69v7A7rjKDKRzAgE2Q=",
|
||||||
"owner": "hraban",
|
"owner": "hraban",
|
||||||
"repo": "cl-nix-lite",
|
"repo": "cl-nix-lite",
|
||||||
"rev": "31cfe6275c341eb3120a99f4b1c8516c49a29d87",
|
"rev": "eb584721e5e799bafe0c6210a8a1a398f90e8ac0",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
@@ -22,11 +28,11 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1742013980,
|
"lastModified": 1786845137,
|
||||||
"narHash": "sha256-34YbfwABU5nb0F5eaaJE3ujldaNDhmyxw7CWqhXJV08=",
|
"narHash": "sha256-oQFip+v0luP8NIxJzmiW4Wu8bILsbFWom5l0zonl8hQ=",
|
||||||
"owner": "lnl7",
|
"owner": "lnl7",
|
||||||
"repo": "nix-darwin",
|
"repo": "nix-darwin",
|
||||||
"rev": "9175b4bb5f127fb7b5784b14f7e01abff24c378f",
|
"rev": "4cff07de74b50e64bdd68cd4e722ab5b6b35ee48",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
@@ -43,11 +49,11 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1741786315,
|
"lastModified": 1781152676,
|
||||||
"narHash": "sha256-VT65AE2syHVj6v/DGB496bqBnu1PXrrzwlw07/Zpllc=",
|
"narHash": "sha256-RxWs5ND31KzTG7wvMM+PMfUjyNpmIEr999lqNARaM5o=",
|
||||||
"owner": "nix-community",
|
"owner": "nix-community",
|
||||||
"repo": "disko",
|
"repo": "disko",
|
||||||
"rev": "0d8c6ad4a43906d14abd5c60e0ffe7b587b213de",
|
"rev": "ff8702b4de27f72b4c78573dfb89ec74e36abdf1",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
@@ -59,11 +65,11 @@
|
|||||||
"flake-compat": {
|
"flake-compat": {
|
||||||
"flake": false,
|
"flake": false,
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1730663653,
|
"lastModified": 1766808011,
|
||||||
"narHash": "sha256-kFCUWettiFHDIqxCWWQ9qY8pVh+Lj+XL0Giyy/kdomg=",
|
"narHash": "sha256-s83BS0abtIj7vzUf8JE0209KphfHA6qRw/92D9k/F+0=",
|
||||||
"owner": "hraban",
|
"owner": "hraban",
|
||||||
"repo": "flake-compat",
|
"repo": "flake-compat",
|
||||||
"rev": "e5b16676185cb7548581c852f51ce7f3a49bba5e",
|
"rev": "6e0aafdc4c4c2043c66f756d5045374b42184fc5",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
@@ -76,11 +82,27 @@
|
|||||||
"flake-compat_2": {
|
"flake-compat_2": {
|
||||||
"flake": false,
|
"flake": false,
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1733328505,
|
"lastModified": 1767039857,
|
||||||
"narHash": "sha256-NeCCThCEP3eCl2l/+27kNNK7QrwZB1IJCrXfrbv5oqU=",
|
"narHash": "sha256-vNpUSpF5Nuw8xvDLj2KCwwksIbjua2LZCqhV1LNRDns=",
|
||||||
|
"owner": "NixOS",
|
||||||
|
"repo": "flake-compat",
|
||||||
|
"rev": "5edf11c44bc78a0d334f6334cdaf7d60d732daab",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"owner": "NixOS",
|
||||||
|
"repo": "flake-compat",
|
||||||
|
"type": "github"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"flake-compat_3": {
|
||||||
|
"flake": false,
|
||||||
|
"locked": {
|
||||||
|
"lastModified": 1767039857,
|
||||||
|
"narHash": "sha256-vNpUSpF5Nuw8xvDLj2KCwwksIbjua2LZCqhV1LNRDns=",
|
||||||
"owner": "edolstra",
|
"owner": "edolstra",
|
||||||
"repo": "flake-compat",
|
"repo": "flake-compat",
|
||||||
"rev": "ff81ac966bb2cae68946d5ed5fc4994f96d0ffec",
|
"rev": "5edf11c44bc78a0d334f6334cdaf7d60d732daab",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
@@ -90,6 +112,24 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"flake-parts": {
|
"flake-parts": {
|
||||||
|
"inputs": {
|
||||||
|
"nixpkgs-lib": "nixpkgs-lib"
|
||||||
|
},
|
||||||
|
"locked": {
|
||||||
|
"lastModified": 1765835352,
|
||||||
|
"narHash": "sha256-XswHlK/Qtjasvhd1nOa1e8MgZ8GS//jBoTqWtrS1Giw=",
|
||||||
|
"owner": "hercules-ci",
|
||||||
|
"repo": "flake-parts",
|
||||||
|
"rev": "a34fae9c08a15ad73f295041fec82323541400a9",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"owner": "hercules-ci",
|
||||||
|
"repo": "flake-parts",
|
||||||
|
"type": "github"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"flake-parts_2": {
|
||||||
"inputs": {
|
"inputs": {
|
||||||
"nixpkgs-lib": [
|
"nixpkgs-lib": [
|
||||||
"nur",
|
"nur",
|
||||||
@@ -132,14 +172,14 @@
|
|||||||
},
|
},
|
||||||
"flake-utils_2": {
|
"flake-utils_2": {
|
||||||
"inputs": {
|
"inputs": {
|
||||||
"systems": "systems_2"
|
"systems": "systems_3"
|
||||||
},
|
},
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1705309234,
|
"lastModified": 1731533236,
|
||||||
"narHash": "sha256-uNRRNRKmJyCRC/8y1RqBkqWBLM034y4qN7EprSdmgyA=",
|
"narHash": "sha256-l0KFg5HjrsfsO/JpG+r7fRrqm12kzFHyUHqHCVpMMbI=",
|
||||||
"owner": "numtide",
|
"owner": "numtide",
|
||||||
"repo": "flake-utils",
|
"repo": "flake-utils",
|
||||||
"rev": "1ef2e671c3b0c19053962c07dbda38332dcebf26",
|
"rev": "11707dc2f618dd54ca8739b309ec4fc024de578b",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
@@ -155,11 +195,11 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1741955947,
|
"lastModified": 1788487777,
|
||||||
"narHash": "sha256-2lbURKclgKqBNm7hVRtWh0A7NrdsibD0EaWhahUVhhY=",
|
"narHash": "sha256-Ro/e1N4ZR8/XaFF+sF9SgfPK79HM5YNEppzFj8p+0Ak=",
|
||||||
"owner": "nix-community",
|
"owner": "nix-community",
|
||||||
"repo": "home-manager",
|
"repo": "home-manager",
|
||||||
"rev": "4e12151c9e014e2449e0beca2c0e9534b96a26b4",
|
"rev": "693e8ce0fb240a73c116a03cfd7b19269c87af88",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
@@ -174,77 +214,64 @@
|
|||||||
"cl-nix-lite": "cl-nix-lite",
|
"cl-nix-lite": "cl-nix-lite",
|
||||||
"flake-compat": "flake-compat",
|
"flake-compat": "flake-compat",
|
||||||
"flake-utils": "flake-utils",
|
"flake-utils": "flake-utils",
|
||||||
|
"nixpkgs": "nixpkgs_3",
|
||||||
|
"systems": "systems_2",
|
||||||
|
"treefmt-nix": "treefmt-nix_2"
|
||||||
|
},
|
||||||
|
"locked": {
|
||||||
|
"lastModified": 1783182903,
|
||||||
|
"narHash": "sha256-7IteXipJZfFepi5zakxe0jQ5i3vRBQguk0+Gtte1Fu4=",
|
||||||
|
"owner": "hraban",
|
||||||
|
"repo": "mac-app-util",
|
||||||
|
"rev": "039f33deef21782d4db97087f426504951239887",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"owner": "hraban",
|
||||||
|
"repo": "mac-app-util",
|
||||||
|
"type": "github"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"nix-caddy-withplugins": {
|
||||||
|
"inputs": {
|
||||||
|
"flake-compat": "flake-compat_2",
|
||||||
|
"nixpkgs": "nixpkgs_5"
|
||||||
|
},
|
||||||
|
"locked": {
|
||||||
|
"lastModified": 1784936738,
|
||||||
|
"narHash": "sha256-X4w9BrFkisfzla3m1WwDJUicUbI7JRdhzq5aS7rrB0k=",
|
||||||
|
"owner": "MichailiK",
|
||||||
|
"repo": "nix-caddy-withplugins",
|
||||||
|
"rev": "70307cfc568e5434cf42067d797b27c38ea69944",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"owner": "MichailiK",
|
||||||
|
"ref": "nixos-unstable",
|
||||||
|
"repo": "nix-caddy-withplugins",
|
||||||
|
"type": "github"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"nix-index-database": {
|
||||||
|
"inputs": {
|
||||||
"nixpkgs": [
|
"nixpkgs": [
|
||||||
"nixpkgs"
|
"nixpkgs"
|
||||||
],
|
]
|
||||||
"systems": "systems"
|
|
||||||
},
|
},
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1739821351,
|
"lastModified": 1788080100,
|
||||||
"narHash": "sha256-QlVtMzAhECs9Esq3txqVW7/vM78ipB5IcI8uyCbTP7A=",
|
"narHash": "sha256-n14luQo3F/ZLfCEHk1QieiI1nGnW92ZQZeZ0UIb0UMQ=",
|
||||||
"owner": "hraban",
|
"owner": "nix-community",
|
||||||
"repo": "mac-app-util",
|
"repo": "nix-index-database",
|
||||||
"rev": "c00d5b21ca1fdab8acef65e696795f0f15ec1158",
|
"rev": "dbb978fa87faf13398e90ccbc52c343d21c7dd6d",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
"owner": "hraban",
|
"owner": "nix-community",
|
||||||
"repo": "mac-app-util",
|
"repo": "nix-index-database",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"nextcloud-cookbook": {
|
|
||||||
"flake": false,
|
|
||||||
"locked": {
|
|
||||||
"lastModified": 1726214817,
|
|
||||||
"narHash": "sha256-Pfa+Xbopg20os+pnGgg+wpEX1MI5fz5JMb0K4a8rBhs=",
|
|
||||||
"type": "tarball",
|
|
||||||
"url": "https://github.com/christianlupus-nextcloud/cookbook-releases/releases/download/v0.11.2/cookbook-0.11.2.tar.gz"
|
|
||||||
},
|
|
||||||
"original": {
|
|
||||||
"type": "tarball",
|
|
||||||
"url": "https://github.com/christianlupus-nextcloud/cookbook-releases/releases/download/v0.11.2/cookbook-0.11.2.tar.gz"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"nextcloud-external": {
|
|
||||||
"flake": false,
|
|
||||||
"locked": {
|
|
||||||
"lastModified": 1729501365,
|
|
||||||
"narHash": "sha256-OV6HhFBzmnQBO5btGEnqmKlaUMY7/t2Qm3XebclpBlM=",
|
|
||||||
"type": "tarball",
|
|
||||||
"url": "https://github.com/nextcloud-releases/external/releases/download/v5.5.2/external-v5.5.2.tar.gz"
|
|
||||||
},
|
|
||||||
"original": {
|
|
||||||
"type": "tarball",
|
|
||||||
"url": "https://github.com/nextcloud-releases/external/releases/download/v5.5.2/external-v5.5.2.tar.gz"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"nextcloud-news": {
|
|
||||||
"flake": false,
|
|
||||||
"locked": {
|
|
||||||
"lastModified": 1729667622,
|
|
||||||
"narHash": "sha256-pnvyMZQ+NYMgH0Unfh5S19HdZSjnghgoUDAoi2KIXNI=",
|
|
||||||
"type": "tarball",
|
|
||||||
"url": "https://github.com/nextcloud/news/releases/download/25.0.0-alpha12/news.tar.gz"
|
|
||||||
},
|
|
||||||
"original": {
|
|
||||||
"type": "tarball",
|
|
||||||
"url": "https://github.com/nextcloud/news/releases/download/25.0.0-alpha12/news.tar.gz"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"nextcloud-snappymail": {
|
|
||||||
"flake": false,
|
|
||||||
"locked": {
|
|
||||||
"lastModified": 1728502660,
|
|
||||||
"narHash": "sha256-oCw6Brs85rINBHvz3UJXheyLVqvA3RgPXG03b30Fx7E=",
|
|
||||||
"type": "tarball",
|
|
||||||
"url": "https://snappymail.eu/repository/nextcloud/snappymail-2.38.2-nextcloud.tar.gz"
|
|
||||||
},
|
|
||||||
"original": {
|
|
||||||
"type": "tarball",
|
|
||||||
"url": "https://snappymail.eu/repository/nextcloud/snappymail-2.38.2-nextcloud.tar.gz"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"nix2vim": {
|
"nix2vim": {
|
||||||
"inputs": {
|
"inputs": {
|
||||||
"flake-utils": "flake-utils_2",
|
"flake-utils": "flake-utils_2",
|
||||||
@@ -253,11 +280,11 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1740943170,
|
"lastModified": 1779563638,
|
||||||
"narHash": "sha256-A0F7T/euSMen004cVQN/ZkMpLkgLXDs+mq/merhd+0Y=",
|
"narHash": "sha256-9CQKxDKDqVYdDhJW+A955AZwpwZjKUgvu0LbfsL6uyI=",
|
||||||
"owner": "gytis-ivaskevicius",
|
"owner": "gytis-ivaskevicius",
|
||||||
"repo": "nix2vim",
|
"repo": "nix2vim",
|
||||||
"rev": "a562f32ff2393d0ed198103c65a3035bcdf83d4d",
|
"rev": "6927414f0de10a18fb6bc9977717088777d50d0d",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
@@ -289,11 +316,11 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1740947705,
|
"lastModified": 1769813415,
|
||||||
"narHash": "sha256-Co2kAD2SZalOm+5zoxmzEVZNvZ17TyafuFsD46BwSdY=",
|
"narHash": "sha256-nnVmNNKBi1YiBNPhKclNYDORoHkuKipoz7EtVnXO50A=",
|
||||||
"owner": "nix-community",
|
"owner": "nix-community",
|
||||||
"repo": "nixos-generators",
|
"repo": "nixos-generators",
|
||||||
"rev": "507911df8c35939050ae324caccc7cf4ffb76565",
|
"rev": "8946737ff703382fda7623b9fab071d037e897d5",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
@@ -304,11 +331,122 @@
|
|||||||
},
|
},
|
||||||
"nixpkgs": {
|
"nixpkgs": {
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1742069588,
|
"lastModified": 1779796641,
|
||||||
"narHash": "sha256-C7jVfohcGzdZRF6DO+ybyG/sqpo1h6bZi9T56sxLy+k=",
|
"narHash": "sha256-ZsIrKmhp4vbBXoXXmR/tBXA/UCsAQiJL9vsgZEduhVY=",
|
||||||
"owner": "nixos",
|
"owner": "nixos",
|
||||||
"repo": "nixpkgs",
|
"repo": "nixpkgs",
|
||||||
"rev": "c80f6a7e10b39afcc1894e02ef785b1ad0b0d7e5",
|
"rev": "25f538306313eae3927264466c70d7001dcea1df",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"owner": "nixos",
|
||||||
|
"ref": "nixos-25.11",
|
||||||
|
"repo": "nixpkgs",
|
||||||
|
"type": "github"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"nixpkgs-lib": {
|
||||||
|
"locked": {
|
||||||
|
"lastModified": 1765674936,
|
||||||
|
"narHash": "sha256-k00uTP4JNfmejrCLJOwdObYC9jHRrr/5M/a/8L2EIdo=",
|
||||||
|
"owner": "nix-community",
|
||||||
|
"repo": "nixpkgs.lib",
|
||||||
|
"rev": "2075416fcb47225d9b68ac469a5c4801a9c4dd85",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"owner": "nix-community",
|
||||||
|
"repo": "nixpkgs.lib",
|
||||||
|
"type": "github"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"nixpkgs-stable": {
|
||||||
|
"locked": {
|
||||||
|
"lastModified": 1788405554,
|
||||||
|
"narHash": "sha256-r2f1oUwixlgq9zOdYLqJLfS/lWBT60/IITjhTKI59JU=",
|
||||||
|
"owner": "nixos",
|
||||||
|
"repo": "nixpkgs",
|
||||||
|
"rev": "a5cc6f2c37bf518436dc8d1c288ccd0c43c2f4c4",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"owner": "nixos",
|
||||||
|
"ref": "nixos-26.05",
|
||||||
|
"repo": "nixpkgs",
|
||||||
|
"type": "github"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"nixpkgs_2": {
|
||||||
|
"locked": {
|
||||||
|
"lastModified": 1761236834,
|
||||||
|
"narHash": "sha256-+pthv6hrL5VLW2UqPdISGuLiUZ6SnAXdd2DdUE+fV2Q=",
|
||||||
|
"owner": "nixos",
|
||||||
|
"repo": "nixpkgs",
|
||||||
|
"rev": "d5faa84122bc0a1fd5d378492efce4e289f8eac1",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"owner": "nixos",
|
||||||
|
"ref": "nixpkgs-unstable",
|
||||||
|
"repo": "nixpkgs",
|
||||||
|
"type": "github"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"nixpkgs_3": {
|
||||||
|
"locked": {
|
||||||
|
"lastModified": 1782999065,
|
||||||
|
"narHash": "sha256-5Dgj5+pIQYZKrXUGaLCk7CKfN3MmpwIhO94++WVxvng=",
|
||||||
|
"owner": "NixOS",
|
||||||
|
"repo": "nixpkgs",
|
||||||
|
"rev": "80d591ed473cfc46329932c2aadac9b435342c7c",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"owner": "NixOS",
|
||||||
|
"ref": "nixos-26.05",
|
||||||
|
"repo": "nixpkgs",
|
||||||
|
"type": "github"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"nixpkgs_4": {
|
||||||
|
"locked": {
|
||||||
|
"lastModified": 1770107345,
|
||||||
|
"narHash": "sha256-tbS0Ebx2PiA1FRW8mt8oejR0qMXmziJmPaU1d4kYY9g=",
|
||||||
|
"owner": "nixos",
|
||||||
|
"repo": "nixpkgs",
|
||||||
|
"rev": "4533d9293756b63904b7238acb84ac8fe4c8c2c4",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"owner": "nixos",
|
||||||
|
"ref": "nixpkgs-unstable",
|
||||||
|
"repo": "nixpkgs",
|
||||||
|
"type": "github"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"nixpkgs_5": {
|
||||||
|
"locked": {
|
||||||
|
"lastModified": 1781074563,
|
||||||
|
"narHash": "sha256-md8WlXOlfnIeHeOScMTTHFyf2d6iaTwPl2apR5EQ3P4=",
|
||||||
|
"owner": "NixOS",
|
||||||
|
"repo": "nixpkgs",
|
||||||
|
"rev": "9ae611a455b90cf061d8f332b977e387bda8e1ca",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"owner": "NixOS",
|
||||||
|
"ref": "nixos-unstable",
|
||||||
|
"repo": "nixpkgs",
|
||||||
|
"type": "github"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"nixpkgs_6": {
|
||||||
|
"locked": {
|
||||||
|
"lastModified": 1788531059,
|
||||||
|
"narHash": "sha256-hLD4l3QOGBQhkVp3mQ2lJ/YbEi99qUgKapb40KovZ88=",
|
||||||
|
"owner": "nixos",
|
||||||
|
"repo": "nixpkgs",
|
||||||
|
"rev": "801bef6abd86b91e51083066b83fb354a11fc640",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
@@ -318,29 +456,13 @@
|
|||||||
"type": "github"
|
"type": "github"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"nixpkgs-stable": {
|
"nixpkgs_7": {
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1735563628,
|
"lastModified": 1744536153,
|
||||||
"narHash": "sha256-OnSAY7XDSx7CtDoqNh8jwVwh4xNL/2HaJxGjryLWzX8=",
|
"narHash": "sha256-awS2zRgF4uTwrOKwwiJcByDzDOdo3Q1rPZbiHQg/N38=",
|
||||||
"owner": "nixos",
|
|
||||||
"repo": "nixpkgs",
|
|
||||||
"rev": "b134951a4c9f3c995fd7be05f3243f8ecd65d798",
|
|
||||||
"type": "github"
|
|
||||||
},
|
|
||||||
"original": {
|
|
||||||
"owner": "nixos",
|
|
||||||
"ref": "nixos-24.05",
|
|
||||||
"repo": "nixpkgs",
|
|
||||||
"type": "github"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"nixpkgs_2": {
|
|
||||||
"locked": {
|
|
||||||
"lastModified": 1728538411,
|
|
||||||
"narHash": "sha256-f0SBJz1eZ2yOuKUr5CA9BHULGXVSn6miBuUWdTyhUhU=",
|
|
||||||
"owner": "NixOS",
|
"owner": "NixOS",
|
||||||
"repo": "nixpkgs",
|
"repo": "nixpkgs",
|
||||||
"rev": "b69de56fac8c2b6f8fd27f2eca01dcda8e0a4221",
|
"rev": "18dd725c29603f582cf1900e0d25f9f1063dbf11",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
@@ -352,18 +474,17 @@
|
|||||||
},
|
},
|
||||||
"nur": {
|
"nur": {
|
||||||
"inputs": {
|
"inputs": {
|
||||||
"flake-parts": "flake-parts",
|
"flake-parts": "flake-parts_2",
|
||||||
"nixpkgs": [
|
"nixpkgs": [
|
||||||
"nixpkgs"
|
"nixpkgs"
|
||||||
],
|
]
|
||||||
"treefmt-nix": "treefmt-nix"
|
|
||||||
},
|
},
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1742145955,
|
"lastModified": 1788594396,
|
||||||
"narHash": "sha256-ju1J45e22ebpLH3eSm0ZZYg7WHkN01ryTFv+4UNwCOA=",
|
"narHash": "sha256-HLvxvUIMxBHl+vv/1OVTLPKrSLTinId97WBIxWWByJ0=",
|
||||||
"owner": "nix-community",
|
"owner": "nix-community",
|
||||||
"repo": "nur",
|
"repo": "nur",
|
||||||
"rev": "d6ba59dd58ebe6c184f955e1d3a4bbca9484c018",
|
"rev": "82ca52a282cd5f90afabcf7c9acd27571b253523",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
@@ -378,15 +499,14 @@
|
|||||||
"disko": "disko",
|
"disko": "disko",
|
||||||
"home-manager": "home-manager",
|
"home-manager": "home-manager",
|
||||||
"mac-app-util": "mac-app-util",
|
"mac-app-util": "mac-app-util",
|
||||||
"nextcloud-cookbook": "nextcloud-cookbook",
|
"nix-caddy-withplugins": "nix-caddy-withplugins",
|
||||||
"nextcloud-external": "nextcloud-external",
|
"nix-index-database": "nix-index-database",
|
||||||
"nextcloud-news": "nextcloud-news",
|
|
||||||
"nextcloud-snappymail": "nextcloud-snappymail",
|
|
||||||
"nix2vim": "nix2vim",
|
"nix2vim": "nix2vim",
|
||||||
"nixos-generators": "nixos-generators",
|
"nixos-generators": "nixos-generators",
|
||||||
"nixpkgs": "nixpkgs",
|
"nixpkgs": "nixpkgs_6",
|
||||||
"nixpkgs-stable": "nixpkgs-stable",
|
"nixpkgs-stable": "nixpkgs-stable",
|
||||||
"nur": "nur",
|
"nur": "nur",
|
||||||
|
"rust-overlay": "rust-overlay",
|
||||||
"wsl": "wsl",
|
"wsl": "wsl",
|
||||||
"zellij-switch": "zellij-switch",
|
"zellij-switch": "zellij-switch",
|
||||||
"zenyd-mpv-scripts": "zenyd-mpv-scripts"
|
"zenyd-mpv-scripts": "zenyd-mpv-scripts"
|
||||||
@@ -394,14 +514,14 @@
|
|||||||
},
|
},
|
||||||
"rust-overlay": {
|
"rust-overlay": {
|
||||||
"inputs": {
|
"inputs": {
|
||||||
"nixpkgs": "nixpkgs_2"
|
"nixpkgs": "nixpkgs_7"
|
||||||
},
|
},
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1736476219,
|
"lastModified": 1788591095,
|
||||||
"narHash": "sha256-+qyv3QqdZCdZ3cSO/cbpEY6tntyYjfe1bB12mdpNFaY=",
|
"narHash": "sha256-Vh+BeLWfbTT9AecazIsQ/Tkg/RzJeX3lEduANf256WA=",
|
||||||
"owner": "oxalica",
|
"owner": "oxalica",
|
||||||
"repo": "rust-overlay",
|
"repo": "rust-overlay",
|
||||||
"rev": "de30cc5963da22e9742bbbbb9a3344570ed237b9",
|
"rev": "c361047d3a538f547f1617bb6b410411929ac9cc",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
@@ -411,21 +531,6 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"systems": {
|
"systems": {
|
||||||
"locked": {
|
|
||||||
"lastModified": 1689347925,
|
|
||||||
"narHash": "sha256-ozenz5bFe1UUqOn7f60HRmgc01BgTGIKZ4Xl+HbocGQ=",
|
|
||||||
"owner": "nix-systems",
|
|
||||||
"repo": "default-darwin",
|
|
||||||
"rev": "2235d7e6cc29ae99878133c95e9fe5e157661ffb",
|
|
||||||
"type": "github"
|
|
||||||
},
|
|
||||||
"original": {
|
|
||||||
"owner": "nix-systems",
|
|
||||||
"repo": "default-darwin",
|
|
||||||
"type": "github"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"systems_2": {
|
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1681028828,
|
"lastModified": 1681028828,
|
||||||
"narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=",
|
"narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=",
|
||||||
@@ -440,6 +545,21 @@
|
|||||||
"type": "github"
|
"type": "github"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"systems_2": {
|
||||||
|
"locked": {
|
||||||
|
"lastModified": 1689347925,
|
||||||
|
"narHash": "sha256-ozenz5bFe1UUqOn7f60HRmgc01BgTGIKZ4Xl+HbocGQ=",
|
||||||
|
"owner": "nix-systems",
|
||||||
|
"repo": "default-darwin",
|
||||||
|
"rev": "2235d7e6cc29ae99878133c95e9fe5e157661ffb",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"owner": "nix-systems",
|
||||||
|
"repo": "default-darwin",
|
||||||
|
"type": "github"
|
||||||
|
}
|
||||||
|
},
|
||||||
"systems_3": {
|
"systems_3": {
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1681028828,
|
"lastModified": 1681028828,
|
||||||
@@ -455,19 +575,49 @@
|
|||||||
"type": "github"
|
"type": "github"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"systems_4": {
|
||||||
|
"locked": {
|
||||||
|
"lastModified": 1681028828,
|
||||||
|
"narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=",
|
||||||
|
"owner": "nix-systems",
|
||||||
|
"repo": "default",
|
||||||
|
"rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"owner": "nix-systems",
|
||||||
|
"repo": "default",
|
||||||
|
"type": "github"
|
||||||
|
}
|
||||||
|
},
|
||||||
"treefmt-nix": {
|
"treefmt-nix": {
|
||||||
"inputs": {
|
"inputs": {
|
||||||
"nixpkgs": [
|
"nixpkgs": "nixpkgs_2"
|
||||||
"nur",
|
|
||||||
"nixpkgs"
|
|
||||||
]
|
|
||||||
},
|
},
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1733222881,
|
"lastModified": 1766000401,
|
||||||
"narHash": "sha256-JIPcz1PrpXUCbaccEnrcUS8jjEb/1vJbZz5KkobyFdM=",
|
"narHash": "sha256-+cqN4PJz9y0JQXfAK5J1drd0U05D5fcAGhzhfVrDlsI=",
|
||||||
"owner": "numtide",
|
"owner": "numtide",
|
||||||
"repo": "treefmt-nix",
|
"repo": "treefmt-nix",
|
||||||
"rev": "49717b5af6f80172275d47a418c9719a31a78b53",
|
"rev": "42d96e75aa56a3f70cab7e7dc4a32868db28e8fd",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"owner": "numtide",
|
||||||
|
"repo": "treefmt-nix",
|
||||||
|
"type": "github"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"treefmt-nix_2": {
|
||||||
|
"inputs": {
|
||||||
|
"nixpkgs": "nixpkgs_4"
|
||||||
|
},
|
||||||
|
"locked": {
|
||||||
|
"lastModified": 1780220602,
|
||||||
|
"narHash": "sha256-eynAfOmbmxJnkp7YewvCEbShNnnYJ9gLLqkzsYtBPeM=",
|
||||||
|
"owner": "numtide",
|
||||||
|
"repo": "treefmt-nix",
|
||||||
|
"rev": "db947814a175b7ca6ded66e21383d938df01c227",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
@@ -478,17 +628,17 @@
|
|||||||
},
|
},
|
||||||
"wsl": {
|
"wsl": {
|
||||||
"inputs": {
|
"inputs": {
|
||||||
"flake-compat": "flake-compat_2",
|
"flake-compat": "flake-compat_3",
|
||||||
"nixpkgs": [
|
"nixpkgs": [
|
||||||
"nixpkgs"
|
"nixpkgs"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1741870048,
|
"lastModified": 1784642409,
|
||||||
"narHash": "sha256-odXRdNZGdXg1LmwlAeWL85kgy/FVHsgKlDwrvbR2BsU=",
|
"narHash": "sha256-hcbDqFuySAJawljt5r0sKBCJKYnbtGD0T/ZIozH1Dq0=",
|
||||||
"owner": "nix-community",
|
"owner": "nix-community",
|
||||||
"repo": "NixOS-WSL",
|
"repo": "NixOS-WSL",
|
||||||
"rev": "5d76001e33ee19644a598ad80e7318ab0957b122",
|
"rev": "eaeb18da90024448a60eb1ec7132eafa4003404e",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
@@ -502,15 +652,17 @@
|
|||||||
"nixpkgs": [
|
"nixpkgs": [
|
||||||
"nixpkgs"
|
"nixpkgs"
|
||||||
],
|
],
|
||||||
"rust-overlay": "rust-overlay",
|
"rust-overlay": [
|
||||||
"systems": "systems_3"
|
"rust-overlay"
|
||||||
|
],
|
||||||
|
"systems": "systems_4"
|
||||||
},
|
},
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1737011317,
|
"lastModified": 1781873766,
|
||||||
"narHash": "sha256-A8VGuw/jIw+NCo5aCYy8MFrWpKzZLf77RApGGMzHxCY=",
|
"narHash": "sha256-V8baEgRBa2SqtCLbQ4EaphIMKsnAogY2oMdttWYhkEs=",
|
||||||
"owner": "mostafaqanbaryan",
|
"owner": "mostafaqanbaryan",
|
||||||
"repo": "zellij-switch",
|
"repo": "zellij-switch",
|
||||||
"rev": "15b02834c8be735fca0d9fb41f48709f97cc9afc",
|
"rev": "ced3c681afe40785b2853e3a976908466786ee79",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
@@ -522,11 +674,11 @@
|
|||||||
"zenyd-mpv-scripts": {
|
"zenyd-mpv-scripts": {
|
||||||
"flake": false,
|
"flake": false,
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1707704915,
|
"lastModified": 1765050776,
|
||||||
"narHash": "sha256-9P/8q/OZXfaJMS08acQP4h3/zUA5mKRQee0JmkXcz1w=",
|
"narHash": "sha256-9gO+GkNoGsxAbMRrBWu0FfXEQtyTmHivlaxlYLpV2YM=",
|
||||||
"owner": "zenyd",
|
"owner": "zenyd",
|
||||||
"repo": "mpv-scripts",
|
"repo": "mpv-scripts",
|
||||||
"rev": "9bdce0050144cb24f92475f7bdd77180e0e4c26b",
|
"rev": "62f4bb313c6cb6366672e78dea940e9da8fec84a",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
|
|||||||
@@ -8,7 +8,7 @@
|
|||||||
nixpkgs.url = "github:nixos/nixpkgs/nixos-unstable";
|
nixpkgs.url = "github:nixos/nixpkgs/nixos-unstable";
|
||||||
|
|
||||||
# Used for specific stable packages
|
# Used for specific stable packages
|
||||||
nixpkgs-stable.url = "github:nixos/nixpkgs/nixos-24.05";
|
nixpkgs-stable.url = "github:nixos/nixpkgs/nixos-26.05";
|
||||||
|
|
||||||
# Used for MacOS system config
|
# Used for MacOS system config
|
||||||
darwin = {
|
darwin = {
|
||||||
@@ -37,7 +37,13 @@
|
|||||||
# Better App install management in macOS
|
# Better App install management in macOS
|
||||||
mac-app-util = {
|
mac-app-util = {
|
||||||
url = "github:hraban/mac-app-util";
|
url = "github:hraban/mac-app-util";
|
||||||
inputs.nixpkgs.follows = "nixpkgs"; # Use system packages list for their inputs
|
# inputs.nixpkgs.follows = "nixpkgs"; # Use system packages list for their inputs
|
||||||
|
};
|
||||||
|
|
||||||
|
# Caddy with decoupled plugin hashes
|
||||||
|
nix-caddy-withplugins = {
|
||||||
|
url = "github:MichailiK/nix-caddy-withplugins/nixos-unstable";
|
||||||
|
# Important: Do not follow nixpkgs here, per the README
|
||||||
};
|
};
|
||||||
|
|
||||||
# Manage disk format and partitioning
|
# Manage disk format and partitioning
|
||||||
@@ -52,6 +58,11 @@
|
|||||||
inputs.nixpkgs.follows = "nixpkgs";
|
inputs.nixpkgs.follows = "nixpkgs";
|
||||||
};
|
};
|
||||||
|
|
||||||
|
nix-index-database = {
|
||||||
|
url = "github:nix-community/nix-index-database";
|
||||||
|
inputs.nixpkgs.follows = "nixpkgs";
|
||||||
|
};
|
||||||
|
|
||||||
# Convert Nix to Neovim config
|
# Convert Nix to Neovim config
|
||||||
nix2vim = {
|
nix2vim = {
|
||||||
url = "github:gytis-ivaskevicius/nix2vim";
|
url = "github:gytis-ivaskevicius/nix2vim";
|
||||||
@@ -64,35 +75,47 @@
|
|||||||
flake = false;
|
flake = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
rust-overlay = {
|
||||||
|
url = "github:oxalica/rust-overlay";
|
||||||
|
};
|
||||||
|
|
||||||
# Zellij Switcher
|
# Zellij Switcher
|
||||||
zellij-switch = {
|
zellij-switch = {
|
||||||
url = "github:mostafaqanbaryan/zellij-switch";
|
url = "github:mostafaqanbaryan/zellij-switch";
|
||||||
inputs.nixpkgs.follows = "nixpkgs";
|
inputs.nixpkgs.follows = "nixpkgs";
|
||||||
|
inputs.rust-overlay.follows = "rust-overlay";
|
||||||
};
|
};
|
||||||
|
|
||||||
# Nextcloud Apps
|
# # Text editor
|
||||||
nextcloud-news = {
|
# helix = {
|
||||||
# https://github.com/nextcloud/news/releases
|
# url = "github:helix-editor/helix";
|
||||||
url = "https://github.com/nextcloud/news/releases/download/25.0.0-alpha12/news.tar.gz";
|
# inputs.nixpkgs.follows = "nixpkgs";
|
||||||
flake = false;
|
# inputs.rust-overlay.follows = "rust-overlay";
|
||||||
};
|
# };
|
||||||
nextcloud-external = {
|
|
||||||
# https://github.com/nextcloud-releases/external/releases
|
# # Nextcloud Apps
|
||||||
url = "https://github.com/nextcloud-releases/external/releases/download/v5.5.2/external-v5.5.2.tar.gz";
|
# nextcloud-news = {
|
||||||
flake = false;
|
# # https://github.com/nextcloud/news/releases
|
||||||
};
|
# url = "https://github.com/nextcloud/news/releases/download/25.0.0-alpha12/news.tar.gz";
|
||||||
nextcloud-cookbook = {
|
# flake = false;
|
||||||
# https://github.com/christianlupus-nextcloud/cookbook-releases/releases/
|
# };
|
||||||
url = "https://github.com/christianlupus-nextcloud/cookbook-releases/releases/download/v0.11.2/cookbook-0.11.2.tar.gz";
|
# nextcloud-external = {
|
||||||
flake = false;
|
# # https://github.com/nextcloud-releases/external/releases
|
||||||
};
|
# url = "https://github.com/nextcloud-releases/external/releases/download/v5.5.2/external-v5.5.2.tar.gz";
|
||||||
nextcloud-snappymail = {
|
# flake = false;
|
||||||
# https://github.com/the-djmaze/snappymail/releases
|
# };
|
||||||
# https://snappymail.eu/repository/nextcloud
|
# nextcloud-cookbook = {
|
||||||
url = "https://snappymail.eu/repository/nextcloud/snappymail-2.38.2-nextcloud.tar.gz";
|
# # https://github.com/christianlupus-nextcloud/cookbook-releases/releases/
|
||||||
# url = "https://github.com/nmasur/snappymail-nextcloud/releases/download/v2.36.3/snappymail-2.36.3-nextcloud.tar.gz";
|
# url = "https://github.com/christianlupus-nextcloud/cookbook-releases/releases/download/v0.11.2/cookbook-0.11.2.tar.gz";
|
||||||
flake = false;
|
# flake = false;
|
||||||
};
|
# };
|
||||||
|
# nextcloud-snappymail = {
|
||||||
|
# # https://github.com/the-djmaze/snappymail/releases
|
||||||
|
# # https://snappymail.eu/repository/nextcloud
|
||||||
|
# url = "https://snappymail.eu/repository/nextcloud/snappymail-2.38.2-nextcloud.tar.gz";
|
||||||
|
# # url = "https://github.com/nmasur/snappymail-nextcloud/releases/download/v2.36.3/snappymail-2.36.3-nextcloud.tar.gz";
|
||||||
|
# flake = false;
|
||||||
|
# };
|
||||||
};
|
};
|
||||||
|
|
||||||
outputs =
|
outputs =
|
||||||
@@ -105,23 +128,32 @@
|
|||||||
in
|
in
|
||||||
{
|
{
|
||||||
audiobooks = "read.${baseName}";
|
audiobooks = "read.${baseName}";
|
||||||
|
auth = "auth.${baseName}";
|
||||||
|
bookmarks = "keep.${baseName}";
|
||||||
books = "books.${baseName}";
|
books = "books.${baseName}";
|
||||||
budget = "money.${baseName}";
|
budget = "money.${baseName}";
|
||||||
|
contacts = "contacts.${baseName}";
|
||||||
content = "cloud.${baseName}";
|
content = "cloud.${baseName}";
|
||||||
download = "download.${baseName}";
|
download = "download.${baseName}";
|
||||||
files = "files.${baseName}";
|
files = "files.${baseName}";
|
||||||
git = "git.${baseName}";
|
git = "git.${baseName}";
|
||||||
|
hister = "hister.${baseName}";
|
||||||
imap = "imap.purelymail.com";
|
imap = "imap.purelymail.com";
|
||||||
influxdb = "influxdb.${baseName}";
|
influxdb = "influxdb.${baseName}";
|
||||||
irc = "irc.${baseName}";
|
irc = "irc.${baseName}";
|
||||||
mail = "noahmasur.com";
|
mail = "noahmasur.com";
|
||||||
|
mathesar = "mathesar.${baseName}";
|
||||||
metrics = "metrics.${baseName}";
|
metrics = "metrics.${baseName}";
|
||||||
minecraft = "minecraft.${baseName}";
|
minecraft = "minecraft.${baseName}";
|
||||||
|
mumble = "mumble.${baseName}";
|
||||||
n8n = "n8n.${baseName}";
|
n8n = "n8n.${baseName}";
|
||||||
|
navidrome = "music.${baseName}";
|
||||||
notifications = "ntfy.${baseName}";
|
notifications = "ntfy.${baseName}";
|
||||||
paperless = "paper.${baseName}";
|
paperless = "paper.${baseName}";
|
||||||
photos = "photos.${baseName}";
|
photos = "photos.${baseName}";
|
||||||
|
postgresql = "pg.${baseName}";
|
||||||
prometheus = "prom.${baseName}";
|
prometheus = "prom.${baseName}";
|
||||||
|
recipes = "cooking.${baseName}";
|
||||||
secrets = "vault.${baseName}";
|
secrets = "vault.${baseName}";
|
||||||
smtp = "smtp.purelymail.com";
|
smtp = "smtp.purelymail.com";
|
||||||
status = "status.${baseName}";
|
status = "status.${baseName}";
|
||||||
@@ -129,32 +161,8 @@
|
|||||||
transmission = "transmission.${baseName}";
|
transmission = "transmission.${baseName}";
|
||||||
};
|
};
|
||||||
|
|
||||||
in
|
|
||||||
rec {
|
|
||||||
|
|
||||||
lib = import ./lib inputs;
|
lib = import ./lib inputs;
|
||||||
|
flattenAttrset = attrs: builtins.foldl' lib.mergeAttrs { } (builtins.attrValues attrs);
|
||||||
nixosConfigurations = builtins.mapAttrs (
|
|
||||||
system: hosts:
|
|
||||||
builtins.mapAttrs (
|
|
||||||
name: module:
|
|
||||||
lib.buildNixos {
|
|
||||||
inherit system module;
|
|
||||||
specialArgs = { inherit hostnames; };
|
|
||||||
}
|
|
||||||
) hosts
|
|
||||||
) lib.linuxHosts;
|
|
||||||
|
|
||||||
darwinConfigurations = builtins.mapAttrs (
|
|
||||||
system: hosts:
|
|
||||||
builtins.mapAttrs (
|
|
||||||
name: module:
|
|
||||||
lib.buildDarwin {
|
|
||||||
inherit system module;
|
|
||||||
specialArgs = { inherit hostnames; };
|
|
||||||
}
|
|
||||||
) hosts
|
|
||||||
) lib.darwinHosts;
|
|
||||||
|
|
||||||
homeModules = builtins.mapAttrs (
|
homeModules = builtins.mapAttrs (
|
||||||
system: hosts:
|
system: hosts:
|
||||||
@@ -163,7 +171,69 @@
|
|||||||
) hosts
|
) hosts
|
||||||
) lib.hosts;
|
) lib.hosts;
|
||||||
|
|
||||||
homeConfigurations = builtins.mapAttrs (
|
# Disk formatting, only used once
|
||||||
|
diskoConfigurations = {
|
||||||
|
root = import ./hosts/x86_64-linux/swan/root.nix;
|
||||||
|
};
|
||||||
|
|
||||||
|
generators = builtins.mapAttrs (
|
||||||
|
# x86_64-linux = { arrow = ...; swan = ...; }
|
||||||
|
system: hosts:
|
||||||
|
(lib.concatMapAttrs (name: module: {
|
||||||
|
"${name}-aws" = lib.generateImage {
|
||||||
|
inherit system module;
|
||||||
|
format = "amazon";
|
||||||
|
specialArgs = { inherit hostnames; };
|
||||||
|
};
|
||||||
|
"${name}-iso" = lib.generateImage {
|
||||||
|
inherit system module;
|
||||||
|
format = "iso";
|
||||||
|
specialArgs = { inherit hostnames; };
|
||||||
|
};
|
||||||
|
"${name}-qcow" = lib.generateImage {
|
||||||
|
inherit system module;
|
||||||
|
format = "qcow-efi";
|
||||||
|
specialArgs = { inherit hostnames; };
|
||||||
|
# extraModules = [ "${nixpkgs}/nixos/modules/virtualisation/oci-image.nix" ];
|
||||||
|
};
|
||||||
|
}) hosts)
|
||||||
|
) lib.linuxHosts # x86_64-linux = { arrow = ...; swan = ...; }
|
||||||
|
;
|
||||||
|
|
||||||
|
in
|
||||||
|
{
|
||||||
|
|
||||||
|
inherit lib;
|
||||||
|
|
||||||
|
nixosConfigurations = flattenAttrset (
|
||||||
|
|
||||||
|
builtins.mapAttrs (
|
||||||
|
system: hosts:
|
||||||
|
builtins.mapAttrs (
|
||||||
|
name: module:
|
||||||
|
lib.buildNixos {
|
||||||
|
inherit system module;
|
||||||
|
specialArgs = { inherit hostnames; };
|
||||||
|
}
|
||||||
|
) hosts
|
||||||
|
) lib.linuxHosts
|
||||||
|
);
|
||||||
|
|
||||||
|
darwinConfigurations = flattenAttrset (
|
||||||
|
builtins.mapAttrs (
|
||||||
|
system: hosts:
|
||||||
|
builtins.mapAttrs (
|
||||||
|
name: module:
|
||||||
|
lib.buildDarwin {
|
||||||
|
inherit system module;
|
||||||
|
specialArgs = { inherit hostnames; };
|
||||||
|
}
|
||||||
|
) hosts
|
||||||
|
) lib.darwinHosts
|
||||||
|
);
|
||||||
|
|
||||||
|
homeConfigurations = flattenAttrset (
|
||||||
|
builtins.mapAttrs (
|
||||||
system: hosts:
|
system: hosts:
|
||||||
builtins.mapAttrs (
|
builtins.mapAttrs (
|
||||||
name: module:
|
name: module:
|
||||||
@@ -172,41 +242,28 @@
|
|||||||
specialArgs = { inherit hostnames; };
|
specialArgs = { inherit hostnames; };
|
||||||
}
|
}
|
||||||
) hosts
|
) hosts
|
||||||
) homeModules;
|
) homeModules
|
||||||
|
);
|
||||||
|
|
||||||
# Disk formatting, only used once
|
# packages =
|
||||||
diskoConfigurations = {
|
# lib.forSystems lib.linuxSystems (
|
||||||
root = import ./hosts/x86_64-linux/swan/root.nix;
|
# system: generateImagesForHosts system // lib.pkgsBySystem.${system}.nmasur
|
||||||
};
|
# )
|
||||||
|
# // lib.forSystems lib.darwinSystems (system: lib.pkgsBySystem.${system}.nmasur);
|
||||||
generators = builtins.mapAttrs (
|
|
||||||
system: hosts:
|
|
||||||
builtins.mapAttrs (name: module: {
|
|
||||||
aws = lib.generateImage {
|
|
||||||
inherit system module;
|
|
||||||
format = "amazon";
|
|
||||||
specialArgs = { inherit hostnames; };
|
|
||||||
};
|
|
||||||
iso = lib.generateImage {
|
|
||||||
inherit system module;
|
|
||||||
format = "iso";
|
|
||||||
specialArgs = { inherit hostnames; };
|
|
||||||
};
|
|
||||||
}) hosts
|
|
||||||
) lib.linuxHosts;
|
|
||||||
|
|
||||||
packages = lib.forAllSystems (
|
packages = lib.forAllSystems (
|
||||||
system:
|
system:
|
||||||
# Get the configurations that we normally use
|
# Share the custom packages that I have placed under the nmasur namespace
|
||||||
{
|
|
||||||
nixosConfigurations = nixosConfigurations.${system};
|
|
||||||
darwinConfigurations = darwinConfigurations.${system};
|
|
||||||
homeConfigurations = homeConfigurations.${system};
|
|
||||||
generators = generators.${system};
|
|
||||||
}
|
|
||||||
//
|
|
||||||
# Get the custom packages that I have placed under the nmasur namespace
|
|
||||||
lib.pkgsBySystem.${system}.nmasur
|
lib.pkgsBySystem.${system}.nmasur
|
||||||
|
//
|
||||||
|
# Share generated images for each relevant host
|
||||||
|
(if (lib.hasInfix "linux" system) then generators.${system} else { })
|
||||||
|
|
||||||
|
# //
|
||||||
|
# # Oracle
|
||||||
|
# {
|
||||||
|
# flame-oci = nixosConfigurations.flame.config.system.build.OCIImage;
|
||||||
|
# }
|
||||||
);
|
);
|
||||||
|
|
||||||
# Development environments
|
# Development environments
|
||||||
@@ -214,30 +271,30 @@
|
|||||||
default = lib.pkgsBySystem.${system}.nmasur.dotfiles-devshell;
|
default = lib.pkgsBySystem.${system}.nmasur.dotfiles-devshell;
|
||||||
});
|
});
|
||||||
|
|
||||||
checks = lib.forAllSystems (
|
# checks = lib.forAllSystems (
|
||||||
system:
|
# system:
|
||||||
let
|
# let
|
||||||
pkgs = import nixpkgs {
|
# pkgs = import nixpkgs {
|
||||||
inherit system;
|
# inherit system;
|
||||||
overlays = lib.overlays;
|
# overlays = lib.overlays;
|
||||||
};
|
# };
|
||||||
in
|
# in
|
||||||
{
|
# {
|
||||||
neovim =
|
# neovim =
|
||||||
pkgs.runCommand "neovim-check-health" { buildInputs = [ inputs.self.packages.${system}.neovim ]; }
|
# pkgs.runCommand "neovim-check-health" { buildInputs = [ inputs.self.packages.${system}.neovim ]; }
|
||||||
''
|
# ''
|
||||||
mkdir -p $out
|
# mkdir -p $out
|
||||||
export HOME=$TMPDIR
|
# export HOME=$TMPDIR
|
||||||
nvim -c "checkhealth" -c "write $out/health.log" -c "quitall"
|
# nvim -c "checkhealth" -c "write $out/health.log" -c "quitall"
|
||||||
|
|
||||||
# Check for errors inside the health log
|
# # Check for errors inside the health log
|
||||||
if $(grep "ERROR" $out/health.log); then
|
# if $(grep "ERROR" $out/health.log); then
|
||||||
cat $out/health.log
|
# cat $out/health.log
|
||||||
exit 1
|
# exit 1
|
||||||
fi
|
# fi
|
||||||
'';
|
# '';
|
||||||
}
|
# }
|
||||||
);
|
# );
|
||||||
|
|
||||||
formatter = lib.forAllSystems (
|
formatter = lib.forAllSystems (
|
||||||
system:
|
system:
|
||||||
@@ -247,10 +304,10 @@
|
|||||||
inherit (lib) overlays;
|
inherit (lib) overlays;
|
||||||
};
|
};
|
||||||
in
|
in
|
||||||
pkgs.nixfmt-rfc-style
|
pkgs.nixfmt
|
||||||
);
|
);
|
||||||
|
|
||||||
# Templates for starting other projects quickly
|
# Templates for starting other projects quickly
|
||||||
templates = (import ./templates nixpkgs.lib);
|
templates = (import ./templates { inherit lib; });
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,23 +12,37 @@ rec {
|
|||||||
|
|
||||||
nmasur.profiles = {
|
nmasur.profiles = {
|
||||||
base.enable = true;
|
base.enable = true;
|
||||||
work.enable = true;
|
# work.enable = true;
|
||||||
extra.enable = true;
|
# extra.enable = true;
|
||||||
gaming.enable = true;
|
# gaming.enable = true;
|
||||||
|
};
|
||||||
|
|
||||||
|
# Corporate network runs a TLS-intercepting proxy. Trust its root CA so Nix
|
||||||
|
# fetches don't fail with "self-signed certificate in certificate chain". The
|
||||||
|
# cert lives outside this public repo at a root-owned, world-readable path so
|
||||||
|
# the unprivileged Nix build user can read it (a copy under $HOME is not
|
||||||
|
# traversable by nixbld). See docs/CHANGELOG.md to extract and install it.
|
||||||
|
nmasur.presets.security.corporateCa = {
|
||||||
|
enable = true;
|
||||||
|
certFile = "/etc/ssl/corp-ca/CorpCA.pem";
|
||||||
};
|
};
|
||||||
|
|
||||||
home-manager.users."Noah.Masur" = {
|
home-manager.users."Noah.Masur" = {
|
||||||
nmasur.settings = {
|
nmasur.settings = {
|
||||||
username = nmasur.settings.username;
|
username = nmasur.settings.username;
|
||||||
fullName = nmasur.settings.fullName;
|
fullName = nmasur.settings.fullName;
|
||||||
|
host = "lookingglass";
|
||||||
};
|
};
|
||||||
nmasur.profiles = {
|
nmasur.profiles = {
|
||||||
common.enable = true;
|
common.enable = true;
|
||||||
darwin-base.enable = true;
|
darwin-base.enable = true;
|
||||||
|
darwin-gaming.enable = true;
|
||||||
|
llm-development.enable = true;
|
||||||
power-user.enable = true;
|
power-user.enable = true;
|
||||||
work.enable = true;
|
work.enable = true;
|
||||||
experimental.enable = true;
|
experimental.enable = true;
|
||||||
};
|
};
|
||||||
|
nmasur.presets.services.mbsync.user = "noah";
|
||||||
nmasur.presets.programs.git-work.work = {
|
nmasur.presets.programs.git-work.work = {
|
||||||
name = "Noah-Masur_1701";
|
name = "Noah-Masur_1701";
|
||||||
email = "${nmasur.settings.username}@take2games.com";
|
email = "${nmasur.settings.username}@take2games.com";
|
||||||
|
|||||||
@@ -23,30 +23,33 @@ rec {
|
|||||||
nmasur.settings = {
|
nmasur.settings = {
|
||||||
username = nmasur.settings.username;
|
username = nmasur.settings.username;
|
||||||
fullName = nmasur.settings.fullName;
|
fullName = nmasur.settings.fullName;
|
||||||
|
host = networking.hostName;
|
||||||
};
|
};
|
||||||
nmasur.profiles = {
|
nmasur.profiles = {
|
||||||
common.enable = true;
|
common.enable = true;
|
||||||
linux-base.enable = true;
|
linux-base.enable = true;
|
||||||
|
llm-development.enable = true;
|
||||||
power-user.enable = true;
|
power-user.enable = true;
|
||||||
};
|
};
|
||||||
home.stateVersion = "23.05";
|
nmasur.presets.programs.helix.enable = true;
|
||||||
|
home.stateVersion = "25.05";
|
||||||
};
|
};
|
||||||
|
|
||||||
system.stateVersion = "23.05";
|
system.stateVersion = "25.05";
|
||||||
# File systems must be declared in order to boot
|
# File systems must be declared in order to boot
|
||||||
|
|
||||||
# This is the root filesystem containing NixOS
|
# # This is the root filesystem containing NixOS
|
||||||
# I forgot to set a clean label for it
|
# # I forgot to set a clean label for it
|
||||||
fileSystems."/" = {
|
# fileSystems."/" = {
|
||||||
device = "/dev/disk/by-uuid/e1b6bd50-306d-429a-9f45-78f57bc597c3";
|
# device = "/dev/disk/by-uuid/e1b6bd50-306d-429a-9f45-78f57bc597c3";
|
||||||
fsType = "ext4";
|
# fsType = "ext4";
|
||||||
};
|
# };
|
||||||
|
|
||||||
# This is the boot filesystem for systemd-boot
|
# # This is the boot filesystem for systemd-boot
|
||||||
fileSystems."/boot" = {
|
# fileSystems."/boot" = {
|
||||||
device = "/dev/disk/by-uuid/D5CA-237A";
|
# device = "/dev/disk/by-uuid/D5CA-237A";
|
||||||
fsType = "vfat";
|
# fsType = "vfat";
|
||||||
};
|
# };
|
||||||
|
|
||||||
# Allows private remote access over the internet
|
# Allows private remote access over the internet
|
||||||
nmasur.presets.services.cloudflared = {
|
nmasur.presets.services.cloudflared = {
|
||||||
@@ -56,4 +59,111 @@ rec {
|
|||||||
ca = "ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBK/6oyVqjFGX3Uvrc3VS8J9sphxzAnRzKC85xgkHfYgR3TK6qBGXzHrknEj21xeZrr3G2y1UsGzphWJd9ZfIcdA= open-ssh-ca@cloudflareaccess.org";
|
ca = "ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBK/6oyVqjFGX3Uvrc3VS8J9sphxzAnRzKC85xgkHfYgR3TK6qBGXzHrknEj21xeZrr3G2y1UsGzphWJd9ZfIcdA= open-ssh-ca@cloudflareaccess.org";
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
# Taken from https://github.com/NixOS/nixpkgs/blob/master/nixos/modules/virtualisation/oci-common.nix
|
||||||
|
|
||||||
|
# fileSystems."/" = {
|
||||||
|
# device = "/dev/disk/by-label/nixos";
|
||||||
|
# fsType = "ext4";
|
||||||
|
# autoResize = true;
|
||||||
|
# };
|
||||||
|
|
||||||
|
# fileSystems."/boot" = {
|
||||||
|
# device = "/dev/disk/by-label/ESP";
|
||||||
|
# fsType = "vfat";
|
||||||
|
# };
|
||||||
|
|
||||||
|
boot.loader.efi.canTouchEfiVariables = false;
|
||||||
|
boot.loader.grub = {
|
||||||
|
device = "nodev";
|
||||||
|
splashImage = null;
|
||||||
|
extraConfig = ''
|
||||||
|
serial --unit=0 --speed=115200 --word=8 --parity=no --stop=1
|
||||||
|
terminal_input --append serial
|
||||||
|
terminal_output --append serial
|
||||||
|
'';
|
||||||
|
efiInstallAsRemovable = true;
|
||||||
|
efiSupport = true;
|
||||||
|
};
|
||||||
|
boot.loader.systemd-boot.enable = false;
|
||||||
|
|
||||||
|
# https://docs.oracle.com/en-us/iaas/Content/Compute/Tasks/configuringntpservice.htm#Configuring_the_Oracle_Cloud_Infrastructure_NTP_Service_for_an_Instance
|
||||||
|
networking.timeServers = [ "169.254.169.254" ];
|
||||||
|
|
||||||
|
boot.growPartition = true;
|
||||||
|
boot.kernelParams = [
|
||||||
|
"net.ifnames=0"
|
||||||
|
|
||||||
|
"nvme.shutdown_timeout=10"
|
||||||
|
"nvme_core.shutdown_timeout=10"
|
||||||
|
"libiscsi.debug_libiscsi_eh=1"
|
||||||
|
"crash_kexec_post_notifiers"
|
||||||
|
|
||||||
|
# aarch64-linux
|
||||||
|
"console=ttyAMA0,115200n8"
|
||||||
|
|
||||||
|
# VNC console
|
||||||
|
"console=tty1"
|
||||||
|
];
|
||||||
|
|
||||||
|
boot.initrd.availableKernelModules = [
|
||||||
|
"virtio_net"
|
||||||
|
"virtio_pci"
|
||||||
|
"virtio_mmio"
|
||||||
|
"virtio_blk"
|
||||||
|
"virtio_scsi"
|
||||||
|
"9p"
|
||||||
|
"9pnet_virtio"
|
||||||
|
];
|
||||||
|
boot.initrd.kernelModules = [
|
||||||
|
"virtio_balloon"
|
||||||
|
"virtio_console"
|
||||||
|
"virtio_rng"
|
||||||
|
"virtio_gpu"
|
||||||
|
];
|
||||||
|
|
||||||
|
networking.useDHCP = true;
|
||||||
|
# networking = {
|
||||||
|
# defaultGateway = "10.0.0.1";
|
||||||
|
# interfaces.eth0 = {
|
||||||
|
# ipAddress = throw "set your own";
|
||||||
|
# prefixLength = 24;
|
||||||
|
# };
|
||||||
|
# };
|
||||||
|
|
||||||
|
disko.devices = {
|
||||||
|
disk = {
|
||||||
|
main = {
|
||||||
|
type = "disk";
|
||||||
|
# device = "/dev/oracleoci/oraclevda"; # Consistent volume naming
|
||||||
|
device = "/dev/sda"; # Consistent volume naming
|
||||||
|
content = {
|
||||||
|
type = "gpt";
|
||||||
|
partitions = {
|
||||||
|
boot = {
|
||||||
|
size = "512M";
|
||||||
|
type = "EF00";
|
||||||
|
content = {
|
||||||
|
type = "filesystem";
|
||||||
|
format = "vfat";
|
||||||
|
mountpoint = "/boot";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
root = {
|
||||||
|
size = "100%";
|
||||||
|
content = {
|
||||||
|
type = "filesystem";
|
||||||
|
format = "ext4";
|
||||||
|
mountpoint = "/";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
# # Otherwise the instance may not have a working network-online.target,
|
||||||
|
# # making the fetch-ssh-keys.service fail
|
||||||
|
# networking.useNetworkd = true;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1 @@
|
|||||||
|
# No x86 Darwin Hosts Currently
|
||||||
@@ -19,6 +19,7 @@ rec {
|
|||||||
nmasur.settings = {
|
nmasur.settings = {
|
||||||
username = nmasur.settings.username;
|
username = nmasur.settings.username;
|
||||||
fullName = nmasur.settings.fullName;
|
fullName = nmasur.settings.fullName;
|
||||||
|
host = networking.hostName;
|
||||||
};
|
};
|
||||||
nmasur.profiles = {
|
nmasur.profiles = {
|
||||||
common.enable = true;
|
common.enable = true;
|
||||||
@@ -29,4 +30,18 @@ rec {
|
|||||||
|
|
||||||
system.stateVersion = "23.05";
|
system.stateVersion = "23.05";
|
||||||
|
|
||||||
|
# These filesystems are ignored by nixos-generators
|
||||||
|
|
||||||
|
# This is the root filesystem containing NixOS
|
||||||
|
fileSystems."/" = {
|
||||||
|
device = "/dev/disk/by-label/nixos";
|
||||||
|
fsType = "ext4";
|
||||||
|
};
|
||||||
|
|
||||||
|
# This is the boot filesystem for Grub
|
||||||
|
fileSystems."/boot" = {
|
||||||
|
device = "/dev/disk/by-label/boot";
|
||||||
|
fsType = "vfat";
|
||||||
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,6 +19,7 @@ rec {
|
|||||||
nmasur.settings = {
|
nmasur.settings = {
|
||||||
username = nmasur.settings.username;
|
username = nmasur.settings.username;
|
||||||
fullName = nmasur.settings.fullName;
|
fullName = nmasur.settings.fullName;
|
||||||
|
host = networking.hostName;
|
||||||
};
|
};
|
||||||
nmasur.profiles = {
|
nmasur.profiles = {
|
||||||
common.enable = true;
|
common.enable = true;
|
||||||
@@ -30,4 +31,24 @@ rec {
|
|||||||
|
|
||||||
system.stateVersion = "23.05";
|
system.stateVersion = "23.05";
|
||||||
|
|
||||||
|
# This is the root filesystem containing NixOS
|
||||||
|
fileSystems."/" = {
|
||||||
|
device = "/dev/disk/by-label/nixos";
|
||||||
|
fsType = "ext4";
|
||||||
|
};
|
||||||
|
|
||||||
|
# This is the boot filesystem for Grub
|
||||||
|
fileSystems."/boot" = {
|
||||||
|
device = "/dev/disk/by-label/boot";
|
||||||
|
fsType = "vfat";
|
||||||
|
};
|
||||||
|
|
||||||
|
# Not sure what's necessary but too afraid to remove anything
|
||||||
|
boot.initrd.availableKernelModules = [
|
||||||
|
"xhci_pci"
|
||||||
|
"ahci"
|
||||||
|
"nvme"
|
||||||
|
"usb_storage"
|
||||||
|
"sd_mod"
|
||||||
|
];
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -23,6 +23,7 @@ rec {
|
|||||||
nmasur.settings = {
|
nmasur.settings = {
|
||||||
username = nmasur.settings.username;
|
username = nmasur.settings.username;
|
||||||
fullName = nmasur.settings.fullName;
|
fullName = nmasur.settings.fullName;
|
||||||
|
host = networking.hostName;
|
||||||
};
|
};
|
||||||
nmasur.profiles = {
|
nmasur.profiles = {
|
||||||
common.enable = true;
|
common.enable = true;
|
||||||
@@ -41,6 +42,9 @@ rec {
|
|||||||
# Not sure what's necessary but too afraid to remove anything
|
# Not sure what's necessary but too afraid to remove anything
|
||||||
# File systems must be declared in order to boot
|
# File systems must be declared in order to boot
|
||||||
|
|
||||||
|
# Required to have a boot loader to work
|
||||||
|
boot.loader.systemd-boot.enable = true;
|
||||||
|
|
||||||
# This is the root filesystem containing NixOS
|
# This is the root filesystem containing NixOS
|
||||||
fileSystems."/" = {
|
fileSystems."/" = {
|
||||||
device = "/dev/disk/by-label/nixos";
|
device = "/dev/disk/by-label/nixos";
|
||||||
|
|||||||
@@ -21,10 +21,12 @@ rec {
|
|||||||
nmasur.settings = {
|
nmasur.settings = {
|
||||||
username = nmasur.settings.username;
|
username = nmasur.settings.username;
|
||||||
fullName = nmasur.settings.fullName;
|
fullName = nmasur.settings.fullName;
|
||||||
|
host = networking.hostName;
|
||||||
};
|
};
|
||||||
nmasur.profiles = {
|
nmasur.profiles = {
|
||||||
common.enable = true;
|
common.enable = true;
|
||||||
linux-base.enable = true;
|
linux-base.enable = true;
|
||||||
|
llm-development.enable = true;
|
||||||
power-user.enable = true;
|
power-user.enable = true;
|
||||||
};
|
};
|
||||||
home.stateVersion = "23.05";
|
home.stateVersion = "23.05";
|
||||||
@@ -32,6 +34,9 @@ rec {
|
|||||||
|
|
||||||
system.stateVersion = "23.05";
|
system.stateVersion = "23.05";
|
||||||
|
|
||||||
|
# Temp: disable while this isn't working
|
||||||
|
services.automatic-timezoned.enable = false;
|
||||||
|
|
||||||
# Not sure what's necessary but too afraid to remove anything
|
# Not sure what's necessary but too afraid to remove anything
|
||||||
boot.initrd.availableKernelModules = [
|
boot.initrd.availableKernelModules = [
|
||||||
"xhci_pci"
|
"xhci_pci"
|
||||||
|
|||||||
@@ -23,12 +23,14 @@ rec {
|
|||||||
nmasur.settings = {
|
nmasur.settings = {
|
||||||
username = nmasur.settings.username;
|
username = nmasur.settings.username;
|
||||||
fullName = nmasur.settings.fullName;
|
fullName = nmasur.settings.fullName;
|
||||||
|
host = networking.hostName;
|
||||||
};
|
};
|
||||||
nmasur.profiles = {
|
nmasur.profiles = {
|
||||||
common.enable = true;
|
common.enable = true;
|
||||||
linux-base.enable = true;
|
linux-base.enable = true;
|
||||||
linux-gui.enable = true;
|
linux-gui.enable = true;
|
||||||
linux-gaming.enable = true;
|
linux-gaming.enable = true;
|
||||||
|
llm-development.enable = true;
|
||||||
power-user.enable = true;
|
power-user.enable = true;
|
||||||
developer.enable = true;
|
developer.enable = true;
|
||||||
experimental.enable = true;
|
experimental.enable = true;
|
||||||
@@ -50,7 +52,7 @@ rec {
|
|||||||
|
|
||||||
# Graphics and VMs
|
# Graphics and VMs
|
||||||
boot.initrd.kernelModules = [ "amdgpu" ];
|
boot.initrd.kernelModules = [ "amdgpu" ];
|
||||||
boot.kernelModules = [ "kvm-amd" ];
|
boot.kernelModules = [ "kvm-amd" "it87" ];
|
||||||
services.xserver.videoDrivers = [ "amdgpu" ];
|
services.xserver.videoDrivers = [ "amdgpu" ];
|
||||||
|
|
||||||
# Required binary blobs to boot on this machine
|
# Required binary blobs to boot on this machine
|
||||||
@@ -67,16 +69,16 @@ rec {
|
|||||||
hardware.fancontrol.config = ''
|
hardware.fancontrol.config = ''
|
||||||
# Configuration file generated by pwmconfig, changes will be lost
|
# Configuration file generated by pwmconfig, changes will be lost
|
||||||
INTERVAL=10
|
INTERVAL=10
|
||||||
DEVPATH=hwmon0=devices/pci0000:00/0000:00:03.1/0000:06:00.0/0000:07:00.0/0000:08:00.0
|
DEVPATH=hwmon1=devices/pci0000:00/0000:00:03.1/0000:06:00.0/0000:07:00.0/0000:08:00.0
|
||||||
DEVNAME=hwmon0=amdgpu
|
DEVNAME=hwmon1=amdgpu
|
||||||
FCTEMPS=hwmon0/pwm1=hwmon0/temp1_input
|
FCTEMPS=hwmon1/pwm1=hwmon1/temp1_input
|
||||||
FCFANS= hwmon0/pwm1=hwmon0/fan1_input
|
FCFANS= hwmon1/pwm1=hwmon1/fan1_input
|
||||||
MINTEMP=hwmon0/pwm1=50
|
MINTEMP=hwmon1/pwm1=50
|
||||||
MAXTEMP=hwmon0/pwm1=70
|
MAXTEMP=hwmon1/pwm1=70
|
||||||
MINSTART=hwmon0/pwm1=100
|
MINSTART=hwmon1/pwm1=100
|
||||||
MINSTOP=hwmon0/pwm1=10
|
MINSTOP=hwmon1/pwm1=10
|
||||||
MINPWM=hwmon0/pwm1=10
|
MINPWM=hwmon1/pwm1=10
|
||||||
MAXPWM=hwmon0/pwm1=240
|
MAXPWM=hwmon1/pwm1=240
|
||||||
'';
|
'';
|
||||||
|
|
||||||
# File systems must be declared in order to boot
|
# File systems must be declared in order to boot
|
||||||
|
|||||||
+49
-19
@@ -66,13 +66,16 @@ lib
|
|||||||
overlays = [
|
overlays = [
|
||||||
inputs.nur.overlays.default
|
inputs.nur.overlays.default
|
||||||
inputs.nix2vim.overlay
|
inputs.nix2vim.overlay
|
||||||
inputs.zellij-switch.overlays.default
|
(final: prev: {
|
||||||
] ++ (importOverlays ../overlays);
|
zellij-switch = inputs.zellij-switch.packages.${prev.stdenv.hostPlatform.system}.default;
|
||||||
|
})
|
||||||
|
# inputs.helix.overlays.default
|
||||||
|
]
|
||||||
|
++ (importOverlays ../overlays);
|
||||||
|
|
||||||
# System types to support.
|
# System types to support.
|
||||||
supportedSystems = [
|
supportedSystems = [
|
||||||
"x86_64-linux"
|
"x86_64-linux"
|
||||||
"x86_64-darwin"
|
|
||||||
"aarch64-linux"
|
"aarch64-linux"
|
||||||
"aarch64-darwin"
|
"aarch64-darwin"
|
||||||
];
|
];
|
||||||
@@ -96,7 +99,14 @@ lib
|
|||||||
system:
|
system:
|
||||||
import inputs.nixpkgs {
|
import inputs.nixpkgs {
|
||||||
inherit system overlays;
|
inherit system overlays;
|
||||||
config.permittedInsecurePackages = [ "litestream-0.3.13" ];
|
config.permittedInsecurePackages = [
|
||||||
|
"litestream-0.3.13"
|
||||||
|
"electron-36.9.5"
|
||||||
|
# Build-time-only dep of karakeep's frontend; CVEs don't reach
|
||||||
|
# the runtime closure. Remove once nixpkgs bumps it.
|
||||||
|
"pnpm-9.15.9"
|
||||||
|
"keybase-gui-6.5.1"
|
||||||
|
];
|
||||||
config.allowUnfree = true;
|
config.allowUnfree = true;
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
@@ -129,7 +139,8 @@ lib
|
|||||||
];
|
];
|
||||||
extraSpecialArgs = {
|
extraSpecialArgs = {
|
||||||
inherit colorscheme;
|
inherit colorscheme;
|
||||||
} // specialArgs;
|
}
|
||||||
|
// specialArgs;
|
||||||
};
|
};
|
||||||
|
|
||||||
buildNixos =
|
buildNixos =
|
||||||
@@ -143,16 +154,20 @@ lib
|
|||||||
pkgs = pkgsBySystem.${system};
|
pkgs = pkgsBySystem.${system};
|
||||||
modules = [
|
modules = [
|
||||||
inputs.home-manager.nixosModules.home-manager
|
inputs.home-manager.nixosModules.home-manager
|
||||||
|
inputs.nix-index-database.nixosModules.default
|
||||||
inputs.disko.nixosModules.disko
|
inputs.disko.nixosModules.disko
|
||||||
inputs.wsl.nixosModules.wsl
|
inputs.wsl.nixosModules.wsl
|
||||||
{ imports = (nixFiles ../platforms/nixos); }
|
{ imports = (nixFiles ../platforms/nixos); }
|
||||||
module
|
module
|
||||||
|
# (builtins.removeAttrs module [ "home-manager" ])
|
||||||
{
|
{
|
||||||
home-manager = {
|
home-manager = {
|
||||||
extraSpecialArgs = {
|
extraSpecialArgs = {
|
||||||
inherit colorscheme;
|
inherit colorscheme;
|
||||||
} // specialArgs;
|
}
|
||||||
} // homeModule.home-manager;
|
// specialArgs;
|
||||||
|
}
|
||||||
|
// homeModule.home-manager;
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
};
|
};
|
||||||
@@ -167,19 +182,21 @@ lib
|
|||||||
inherit system specialArgs;
|
inherit system specialArgs;
|
||||||
modules = [
|
modules = [
|
||||||
inputs.home-manager.darwinModules.home-manager
|
inputs.home-manager.darwinModules.home-manager
|
||||||
|
inputs.nix-index-database.darwinModules.nix-index
|
||||||
inputs.mac-app-util.darwinModules.default
|
inputs.mac-app-util.darwinModules.default
|
||||||
{
|
{
|
||||||
imports = (nixFiles ../platforms/nix-darwin);
|
imports = (nixFiles ../platforms/nix-darwin);
|
||||||
nixpkgs.pkgs = pkgsBySystem.${system};
|
nixpkgs.pkgs = pkgsBySystem.${system};
|
||||||
}
|
}
|
||||||
module
|
# Home Manager is intentionally NOT activated here. It is managed
|
||||||
{
|
# standalone via `nh home switch` (see homeConfigurations, extracted
|
||||||
home-manager = {
|
# from the host module's `home-manager.users`). Strip that attr so
|
||||||
extraSpecialArgs = {
|
# darwin-rebuild doesn't also activate a second, divergent HM
|
||||||
inherit colorscheme;
|
# generation with different store paths (useUserPackages puts packages
|
||||||
} // specialArgs;
|
# in /etc/profiles/per-user vs. ~/.nix-profile standalone) -- that
|
||||||
} // homeModule.home-manager;
|
# mismatch broke the prompt after every darwin-rebuild until the next
|
||||||
}
|
# `nh home switch`.
|
||||||
|
(builtins.removeAttrs module [ "home-manager" ])
|
||||||
];
|
];
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -187,7 +204,15 @@ lib
|
|||||||
amazon = {
|
amazon = {
|
||||||
aws.enable = true;
|
aws.enable = true;
|
||||||
};
|
};
|
||||||
iso = { };
|
iso = {
|
||||||
|
nmasur.profiles.wsl.enable = lib.mkForce false;
|
||||||
|
boot.loader.grub.enable = lib.mkForce false;
|
||||||
|
};
|
||||||
|
qcow-efi = {
|
||||||
|
nmasur.profiles.wsl.enable = lib.mkForce false;
|
||||||
|
boot.loader.grub.enable = lib.mkForce false;
|
||||||
|
fileSystems."/boot".device = lib.mkForce "/dev/disk/by-label/ESP";
|
||||||
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
generateImage =
|
generateImage =
|
||||||
@@ -199,8 +224,10 @@ lib
|
|||||||
}:
|
}:
|
||||||
inputs.nixos-generators.nixosGenerate {
|
inputs.nixos-generators.nixosGenerate {
|
||||||
inherit system format;
|
inherit system format;
|
||||||
|
pkgs = pkgsBySystem.${system};
|
||||||
modules = [
|
modules = [
|
||||||
inputs.home-manager.nixosModules.home-manager
|
inputs.home-manager.nixosModules.home-manager
|
||||||
|
inputs.nix-index-database.nixosModules.default
|
||||||
inputs.disko.nixosModules.disko
|
inputs.disko.nixosModules.disko
|
||||||
inputs.wsl.nixosModules.wsl
|
inputs.wsl.nixosModules.wsl
|
||||||
{
|
{
|
||||||
@@ -212,12 +239,15 @@ lib
|
|||||||
home-manager = {
|
home-manager = {
|
||||||
extraSpecialArgs = {
|
extraSpecialArgs = {
|
||||||
inherit colorscheme;
|
inherit colorscheme;
|
||||||
} // specialArgs;
|
}
|
||||||
} // homeModule.home-manager;
|
// specialArgs;
|
||||||
|
}
|
||||||
|
// homeModule.home-manager;
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
specialArgs = {
|
specialArgs = {
|
||||||
} // specialArgs;
|
}
|
||||||
|
// specialArgs;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,9 @@
|
|||||||
|
_inputs: _final: prev: {
|
||||||
|
pythonPackagesExtensions = prev.pythonPackagesExtensions ++ [
|
||||||
|
(_pyfinal: pyprev: {
|
||||||
|
cheetah3 = pyprev.cheetah3.overridePythonAttrs (_old: {
|
||||||
|
dontCheckPythonMetadata = true;
|
||||||
|
});
|
||||||
|
})
|
||||||
|
];
|
||||||
|
}
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
inputs: final: prev: {
|
||||||
|
|
||||||
|
# Switch firefox to stable or unstable depending on need
|
||||||
|
firefox-unwrapped = final.unstable.firefox-unwrapped;
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
_inputs: _final: prev: {
|
||||||
|
|
||||||
|
kubernetes-helm = prev.kubernetes-helm.overrideAttrs (_old: {
|
||||||
|
doCheck = false;
|
||||||
|
});
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
inputs: inputs.nix-caddy-withplugins.overlays.default
|
||||||
@@ -0,0 +1,20 @@
|
|||||||
|
# Disable paho-mqtt's flaky test suite.
|
||||||
|
#
|
||||||
|
# paho-mqtt's checkPhase runs socket-based integration tests that hang in
|
||||||
|
# the Nix sandbox (they eventually time out with a KeyboardInterrupt after
|
||||||
|
# ~150s, reporting errors and failing the build). This breaks the flame
|
||||||
|
# rebuild, where paho-mqtt is pulled in transitively (e.g. via mealie).
|
||||||
|
#
|
||||||
|
# Applied through pythonPackagesExtensions so it covers every Python
|
||||||
|
# package set (python3Packages, python314Packages, ...).
|
||||||
|
|
||||||
|
_inputs: _final: prev: {
|
||||||
|
pythonPackagesExtensions = prev.pythonPackagesExtensions ++ [
|
||||||
|
(_pyfinal: pyprev: {
|
||||||
|
paho-mqtt = pyprev.paho-mqtt.overridePythonAttrs (_old: {
|
||||||
|
doCheck = false;
|
||||||
|
doInstallCheck = false;
|
||||||
|
});
|
||||||
|
})
|
||||||
|
];
|
||||||
|
}
|
||||||
@@ -21,6 +21,9 @@ let
|
|||||||
# [ package1.drv package2.drv ]
|
# [ package1.drv package2.drv ]
|
||||||
(builtins.map (name: prev.callPackage name { }))
|
(builtins.map (name: prev.callPackage name { }))
|
||||||
|
|
||||||
|
# Filter out packages that return null (e.g. platform-specific packages)
|
||||||
|
(builtins.filter (v: v != null))
|
||||||
|
|
||||||
# Convert the list to an attrset
|
# Convert the list to an attrset
|
||||||
# { package1 = package1.drv, package2 = package2.drv }
|
# { package1 = package1.drv, package2 = package2.drv }
|
||||||
listToAttrsByPnameOrName
|
listToAttrsByPnameOrName
|
||||||
|
|||||||
+2
-1
@@ -4,7 +4,8 @@
|
|||||||
inputs: _final: prev: {
|
inputs: _final: prev: {
|
||||||
# Provides `pkgs.stable`.
|
# Provides `pkgs.stable`.
|
||||||
stable = import inputs.nixpkgs-stable {
|
stable = import inputs.nixpkgs-stable {
|
||||||
inherit (prev) system config;
|
system = prev.stdenv.hostPlatform.system;
|
||||||
|
config = { };
|
||||||
overlays = [
|
overlays = [
|
||||||
# inputs.self.overlays.vim-plugins
|
# inputs.self.overlays.vim-plugins
|
||||||
];
|
];
|
||||||
|
|||||||
@@ -4,7 +4,8 @@
|
|||||||
inputs: _final: prev: {
|
inputs: _final: prev: {
|
||||||
# Provides `pkgs.unstable`.
|
# Provides `pkgs.unstable`.
|
||||||
unstable = import inputs.nixpkgs {
|
unstable = import inputs.nixpkgs {
|
||||||
inherit (prev) system config;
|
system = prev.stdenv.hostPlatform.system;
|
||||||
|
inherit (prev) config;
|
||||||
overlays = [
|
overlays = [
|
||||||
# inputs.self.overlays.vim-plugins
|
# inputs.self.overlays.vim-plugins
|
||||||
];
|
];
|
||||||
|
|||||||
@@ -0,0 +1,44 @@
|
|||||||
|
{
|
||||||
|
lib,
|
||||||
|
buildNpmPackage,
|
||||||
|
fetchFromGitHub,
|
||||||
|
nodejs,
|
||||||
|
}:
|
||||||
|
|
||||||
|
buildNpmPackage rec {
|
||||||
|
pname = "actualtap";
|
||||||
|
version = "1.0.34";
|
||||||
|
|
||||||
|
src = fetchFromGitHub {
|
||||||
|
owner = "MattFaz";
|
||||||
|
repo = "actualtap";
|
||||||
|
rev = "v${version}";
|
||||||
|
hash = "sha256-I2yb3WCOXYx/6RXiKjePlpChrr9G1il44OdON/SeVCw=";
|
||||||
|
};
|
||||||
|
|
||||||
|
npmDepsHash = "sha256-LlTLwUt0Yja4NSBLbaYPV/keawSJKffno/28rtSj/oQ=";
|
||||||
|
|
||||||
|
dontNpmBuild = true;
|
||||||
|
|
||||||
|
postPatch = ''
|
||||||
|
substituteInPlace src/server.js \
|
||||||
|
--replace-fail 'port: 3001' 'port: process.env.PORT || 3001'
|
||||||
|
'';
|
||||||
|
|
||||||
|
postInstall = ''
|
||||||
|
mkdir -p $out/bin
|
||||||
|
cat <<EOF > $out/bin/actualtap
|
||||||
|
#!/bin/sh
|
||||||
|
exec ${lib.getExe nodejs} $out/lib/node_modules/actualtap/src/server.js "\$@"
|
||||||
|
EOF
|
||||||
|
chmod +x $out/bin/actualtap
|
||||||
|
'';
|
||||||
|
|
||||||
|
meta = with lib; {
|
||||||
|
description = "Automatically create transactions in Actual Budget when you use Tap-to-Pay on a mobile device";
|
||||||
|
homepage = "https://github.com/MattFaz/actualtap";
|
||||||
|
license = licenses.gpl3Only;
|
||||||
|
maintainers = [ ];
|
||||||
|
mainProgram = "actualtap";
|
||||||
|
};
|
||||||
|
}
|
||||||
@@ -9,7 +9,7 @@
|
|||||||
# Sets Neovim colors based on Nix colorscheme
|
# Sets Neovim colors based on Nix colorscheme
|
||||||
|
|
||||||
options.colors = lib.mkOption {
|
options.colors = lib.mkOption {
|
||||||
type = lib.types.attrsOf lib.types.str;
|
type = lib.types.nullOr (lib.types.attrsOf lib.types.str);
|
||||||
description = "Attrset of base16 colorscheme key value pairs.";
|
description = "Attrset of base16 colorscheme key value pairs.";
|
||||||
default = {
|
default = {
|
||||||
# Nord
|
# Nord
|
||||||
@@ -32,7 +32,7 @@
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
config = {
|
config = lib.mkIf (config.colors != null) {
|
||||||
plugins = [ pkgs.vimPlugins.base16-nvim ];
|
plugins = [ pkgs.vimPlugins.base16-nvim ];
|
||||||
setup.base16-colorscheme = config.colors;
|
setup.base16-colorscheme = config.colors;
|
||||||
|
|
||||||
|
|||||||
@@ -8,9 +8,9 @@
|
|||||||
{
|
{
|
||||||
|
|
||||||
# Terraform optional because non-free
|
# Terraform optional because non-free
|
||||||
options.terraform = lib.mkEnableOption "Whether to enable Terraform LSP";
|
options.enableTerraform = lib.mkEnableOption "Whether to enable Terraform LSP";
|
||||||
options.github = lib.mkEnableOption "Whether to enable GitHub features";
|
options.enableGithub = lib.mkEnableOption "Whether to enable GitHub features";
|
||||||
options.kubernetes = lib.mkEnableOption "Whether to enable Kubernetes features";
|
options.enableKubernetes = lib.mkEnableOption "Whether to enable Kubernetes features";
|
||||||
|
|
||||||
config = {
|
config = {
|
||||||
plugins = [
|
plugins = [
|
||||||
@@ -54,7 +54,7 @@
|
|||||||
|
|
||||||
use.lspconfig.terraformls.setup = dsl.callWith {
|
use.lspconfig.terraformls.setup = dsl.callWith {
|
||||||
cmd =
|
cmd =
|
||||||
if config.terraform then
|
if config.enableTerraform then
|
||||||
[
|
[
|
||||||
"${pkgs.terraform-ls}/bin/terraform-ls"
|
"${pkgs.terraform-ls}/bin/terraform-ls"
|
||||||
"serve"
|
"serve"
|
||||||
@@ -93,14 +93,14 @@
|
|||||||
nix = [ "nixfmt" ];
|
nix = [ "nixfmt" ];
|
||||||
rust = [ "rustfmt" ];
|
rust = [ "rustfmt" ];
|
||||||
sh = [ "shfmt" ];
|
sh = [ "shfmt" ];
|
||||||
terraform = if config.terraform then [ "terraform_fmt" ] else [ ];
|
terraform = if config.enableTerraform then [ "terraform_fmt" ] else [ ];
|
||||||
hcl = [ "hcl" ];
|
hcl = [ "hcl" ];
|
||||||
};
|
};
|
||||||
formatters = {
|
formatters = {
|
||||||
lua.command = "${pkgs.stylua}/bin/stylua";
|
lua.command = "${pkgs.stylua}/bin/stylua";
|
||||||
black.command = "${pkgs.black}/bin/black";
|
black.command = "${pkgs.black}/bin/black";
|
||||||
fish_indent.command = "${pkgs.fish}/bin/fish_indent";
|
fish_indent.command = "${pkgs.fish}/bin/fish_indent";
|
||||||
nixfmt.command = "${pkgs.nixfmt-rfc-style}/bin/nixfmt";
|
nixfmt.command = "${pkgs.nixfmt}/bin/nixfmt";
|
||||||
rustfmt.command = "${pkgs.rustfmt}/bin/rustfmt";
|
rustfmt.command = "${pkgs.rustfmt}/bin/rustfmt";
|
||||||
shfmt = {
|
shfmt = {
|
||||||
command = "${pkgs.shfmt}/bin/shfmt";
|
command = "${pkgs.shfmt}/bin/shfmt";
|
||||||
@@ -110,7 +110,7 @@
|
|||||||
"-ci"
|
"-ci"
|
||||||
];
|
];
|
||||||
};
|
};
|
||||||
terraform_fmt.command = if config.terraform then "${pkgs.terraform}/bin/terraform" else "";
|
terraform_fmt.command = if config.enableTerraform then "${pkgs.terraform}/bin/terraform" else "";
|
||||||
hcl.command = "${pkgs.hclfmt}/bin/hclfmt";
|
hcl.command = "${pkgs.hclfmt}/bin/hclfmt";
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -3,10 +3,10 @@
|
|||||||
|
|
||||||
plugins = [
|
plugins = [
|
||||||
(pkgs.vimPlugins.nvim-treesitter.withPlugins (_plugins: [
|
(pkgs.vimPlugins.nvim-treesitter.withPlugins (_plugins: [
|
||||||
pkgs.nmasur.ini-grammar
|
pkgs.nmasur.tree-sitter-ini
|
||||||
pkgs.nmasur.puppet-grammar
|
pkgs.nmasur.tree-sitter-puppet
|
||||||
pkgs.nmasur.rasi-grammar
|
pkgs.nmasur.tree-sitter-rasi
|
||||||
pkgs.nmasur.vimdoc-grammar
|
pkgs.nmasur.tree-sitter-vimdoc
|
||||||
pkgs.tree-sitter-grammars.tree-sitter-bash
|
pkgs.tree-sitter-grammars.tree-sitter-bash
|
||||||
pkgs.tree-sitter-grammars.tree-sitter-c
|
pkgs.tree-sitter-grammars.tree-sitter-c
|
||||||
pkgs.tree-sitter-grammars.tree-sitter-fish
|
pkgs.tree-sitter-grammars.tree-sitter-fish
|
||||||
@@ -21,7 +21,6 @@
|
|||||||
pkgs.tree-sitter-grammars.tree-sitter-yaml
|
pkgs.tree-sitter-grammars.tree-sitter-yaml
|
||||||
]))
|
]))
|
||||||
pkgs.vimPlugins.vim-matchup # Better % jumping in languages
|
pkgs.vimPlugins.vim-matchup # Better % jumping in languages
|
||||||
pkgs.vimPlugins.playground # Tree-sitter experimenting
|
|
||||||
pkgs.vimPlugins.nginx-vim
|
pkgs.vimPlugins.nginx-vim
|
||||||
pkgs.vimPlugins.vim-helm
|
pkgs.vimPlugins.vim-helm
|
||||||
# pkgs.vimPlugins.hmts-nvim # Tree-sitter injections for home-manager
|
# pkgs.vimPlugins.hmts-nvim # Tree-sitter injections for home-manager
|
||||||
|
|||||||
@@ -18,7 +18,7 @@
|
|||||||
|
|
||||||
lua = ''
|
lua = ''
|
||||||
${builtins.readFile ./toggleterm.lua}
|
${builtins.readFile ./toggleterm.lua}
|
||||||
${if config.github then (builtins.readFile ./github.lua) else ""}
|
${if config.enableGithub then (builtins.readFile ./github.lua) else ""}
|
||||||
${if config.kubernetes then (builtins.readFile ./kubernetes.lua) else ""}
|
${if config.enableKubernetes then (builtins.readFile ./kubernetes.lua) else ""}
|
||||||
'';
|
'';
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -29,9 +29,9 @@
|
|||||||
{
|
{
|
||||||
pkgs,
|
pkgs,
|
||||||
colors ? null,
|
colors ? null,
|
||||||
terraform ? false,
|
enableTerraform ? false,
|
||||||
github ? false,
|
enableGithub ? false,
|
||||||
kubernetes ? false,
|
enableKubernetes ? false,
|
||||||
...
|
...
|
||||||
}:
|
}:
|
||||||
|
|
||||||
@@ -41,9 +41,9 @@ pkgs.neovimBuilder {
|
|||||||
package = pkgs.neovim-unwrapped;
|
package = pkgs.neovim-unwrapped;
|
||||||
inherit
|
inherit
|
||||||
colors
|
colors
|
||||||
terraform
|
enableTerraform
|
||||||
github
|
enableGithub
|
||||||
kubernetes
|
enableKubernetes
|
||||||
;
|
;
|
||||||
imports = [
|
imports = [
|
||||||
./config/align.nix
|
./config/align.nix
|
||||||
|
|||||||
@@ -1,6 +1,9 @@
|
|||||||
# Fix: Volnoti error: 'volnoti' has been removed due to lack of maintenance upstream.
|
# Fix: Volnoti error: 'volnoti' has been removed due to lack of maintenance upstream.
|
||||||
|
|
||||||
{ pkgs, lib, ... }:
|
{ pkgs, lib, ... }:
|
||||||
|
if !pkgs.stdenv.hostPlatform.isLinux then
|
||||||
|
null
|
||||||
|
else
|
||||||
pkgs.stdenv.mkDerivation {
|
pkgs.stdenv.mkDerivation {
|
||||||
pname = "volnoti";
|
pname = "volnoti";
|
||||||
version = "2013-09-23";
|
version = "2013-09-23";
|
||||||
@@ -27,7 +30,7 @@ pkgs.stdenv.mkDerivation {
|
|||||||
dbus
|
dbus
|
||||||
gdk-pixbuf
|
gdk-pixbuf
|
||||||
glib
|
glib
|
||||||
xorg.libX11
|
libx11
|
||||||
gtk2
|
gtk2
|
||||||
dbus-glib
|
dbus-glib
|
||||||
librsvg
|
librsvg
|
||||||
|
|||||||
@@ -0,0 +1,11 @@
|
|||||||
|
# Caddy with Cloudflare DNS
|
||||||
|
|
||||||
|
{
|
||||||
|
pkgs,
|
||||||
|
...
|
||||||
|
}:
|
||||||
|
|
||||||
|
pkgs.caddy.withPlugins {
|
||||||
|
plugins = [ "github.com/caddy-dns/cloudflare@v0.2.1" ];
|
||||||
|
hash = "sha256-HuVBmiT3kD6RrDejQ6SnjCN8f7pFdZlGtZFbEf47bks=";
|
||||||
|
}
|
||||||
@@ -0,0 +1,41 @@
|
|||||||
|
|
||||||
|
function exportHistory() {
|
||||||
|
const now = new Date();
|
||||||
|
const startTime = new Date(now.getFullYear(), now.getMonth(), now.getDate(), 0, 0, 0, 0); // Beginning of today
|
||||||
|
|
||||||
|
browser.history.search({
|
||||||
|
text: '',
|
||||||
|
startTime: startTime,
|
||||||
|
endTime: now,
|
||||||
|
maxResults: 10000
|
||||||
|
}).then(historyItems => {
|
||||||
|
const historyData = JSON.stringify(historyItems, null, 2);
|
||||||
|
const blob = new Blob([historyData], {type: 'application/json'});
|
||||||
|
const url = URL.createObjectURL(blob);
|
||||||
|
const date = now.toISOString().slice(0, 10); // YYYY-MM-DD
|
||||||
|
const filename = `firefox-history/history-${date}.json`;
|
||||||
|
|
||||||
|
browser.downloads.download({
|
||||||
|
url: url,
|
||||||
|
filename: filename,
|
||||||
|
conflictAction: 'overwrite',
|
||||||
|
saveAs: false
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
browser.alarms.create('daily-export', {
|
||||||
|
periodInMinutes: 60 // every 1 hour
|
||||||
|
});
|
||||||
|
|
||||||
|
browser.alarms.onAlarm.addListener(alarm => {
|
||||||
|
if (alarm.name === 'daily-export') {
|
||||||
|
exportHistory();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
browser.runtime.onMessage.addListener((message, sender, sendResponse) => {
|
||||||
|
if (message.command === "exportHistory") {
|
||||||
|
exportHistory();
|
||||||
|
}
|
||||||
|
});
|
||||||
@@ -0,0 +1,25 @@
|
|||||||
|
{
|
||||||
|
"manifest_version": 3,
|
||||||
|
"name": "History Exporter",
|
||||||
|
"version": "1.1",
|
||||||
|
"description": "Automatically exports today's browsing history.",
|
||||||
|
"permissions": [
|
||||||
|
"history",
|
||||||
|
"downloads",
|
||||||
|
"alarms"
|
||||||
|
],
|
||||||
|
"background": {
|
||||||
|
"scripts": ["background.js"]
|
||||||
|
},
|
||||||
|
"action": {
|
||||||
|
"default_popup": "popup.html"
|
||||||
|
},
|
||||||
|
"browser_specific_settings": {
|
||||||
|
"gecko": {
|
||||||
|
"id": "[email protected]",
|
||||||
|
"data_collection_permissions": {
|
||||||
|
"required": ["none"]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,26 @@
|
|||||||
|
{ pkgs, ... }:
|
||||||
|
|
||||||
|
pkgs.stdenv.mkDerivation rec {
|
||||||
|
pname = "firefox-history-exporter";
|
||||||
|
version = "1.1";
|
||||||
|
src = ./.;
|
||||||
|
|
||||||
|
nativeBuildInputs = [ pkgs.zip ];
|
||||||
|
|
||||||
|
dontUnpack = true;
|
||||||
|
|
||||||
|
installPhase = ''
|
||||||
|
dst="$out/share/mozilla/extensions/{ec8030f7-c20a-464f-9b0e-13a3a9e97384}"
|
||||||
|
mkdir -p "$dst"
|
||||||
|
zip -j "$dst/firefox-history-exporter@nmasur.com.xpi" \
|
||||||
|
"${src}/manifest.json" \
|
||||||
|
"${src}/background.js" \
|
||||||
|
"${src}/popup.html" \
|
||||||
|
"${src}/popup.js"
|
||||||
|
'';
|
||||||
|
|
||||||
|
meta = with pkgs.lib; {
|
||||||
|
description = "Automatically exports today's browsing history.";
|
||||||
|
license = licenses.mit;
|
||||||
|
};
|
||||||
|
}
|
||||||
@@ -0,0 +1,25 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>History Exporter</title>
|
||||||
|
<style>
|
||||||
|
body {
|
||||||
|
width: 200px;
|
||||||
|
text-align: center;
|
||||||
|
font-family: sans-serif;
|
||||||
|
}
|
||||||
|
button {
|
||||||
|
margin-top: 10px;
|
||||||
|
padding: 10px;
|
||||||
|
font-size: 16px;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<h1>History Exporter</h1>
|
||||||
|
<button id="export-button">Export Now</button>
|
||||||
|
<p id="status"></p>
|
||||||
|
<script src="popup.js"></script>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
document.getElementById('export-button').addEventListener('click', () => {
|
||||||
|
browser.runtime.sendMessage({command: "exportHistory"});
|
||||||
|
|
||||||
|
const statusElement = document.getElementById('status');
|
||||||
|
statusElement.textContent = 'Exporting...';
|
||||||
|
setTimeout(() => {
|
||||||
|
statusElement.textContent = 'Export complete!';
|
||||||
|
}, 2000);
|
||||||
|
});
|
||||||
@@ -0,0 +1,302 @@
|
|||||||
|
{
|
||||||
|
runtimeShell,
|
||||||
|
python313,
|
||||||
|
python313Packages,
|
||||||
|
fetchFromGitHub,
|
||||||
|
fetchPypi,
|
||||||
|
fetchurl,
|
||||||
|
gettext,
|
||||||
|
unzip,
|
||||||
|
...
|
||||||
|
}:
|
||||||
|
let
|
||||||
|
|
||||||
|
django-modern-rpc = python313Packages.buildPythonPackage rec {
|
||||||
|
pname = "django_modern_rpc";
|
||||||
|
version = "1.1.0";
|
||||||
|
src = fetchPypi {
|
||||||
|
inherit pname version;
|
||||||
|
hash = "sha256-+LBIfkBxe9lvfZIqPI2lFSshTZBL1NpmCWBAgToyJns=";
|
||||||
|
};
|
||||||
|
doCheck = false;
|
||||||
|
pyproject = true;
|
||||||
|
build-system = [
|
||||||
|
python313Packages.setuptools
|
||||||
|
python313Packages.wheel
|
||||||
|
python313Packages.poetry-core
|
||||||
|
];
|
||||||
|
};
|
||||||
|
django-property-filter = python313Packages.buildPythonPackage rec {
|
||||||
|
pname = "django_property_filter";
|
||||||
|
version = "1.3.0";
|
||||||
|
src = fetchPypi {
|
||||||
|
inherit pname version;
|
||||||
|
hash = "sha256-dpsF4hm0S4lQ6tIRJ0bXgPjWTr1fq1NSCZP0M6L4Efk=";
|
||||||
|
};
|
||||||
|
doCheck = false;
|
||||||
|
pyproject = true;
|
||||||
|
build-system = [
|
||||||
|
python313Packages.setuptools
|
||||||
|
python313Packages.wheel
|
||||||
|
python313Packages.django
|
||||||
|
python313Packages.django-filter
|
||||||
|
];
|
||||||
|
};
|
||||||
|
django-fernet-encrypted-fields = python313Packages.buildPythonPackage rec {
|
||||||
|
pname = "django-fernet-encrypted-fields";
|
||||||
|
version = "0.3.0";
|
||||||
|
src = fetchPypi {
|
||||||
|
inherit pname version;
|
||||||
|
hash = "sha256-OAMb2vFySm6IXuE3zGaivX3DcmxDjhiep+RHmewLqbM=";
|
||||||
|
};
|
||||||
|
doCheck = false;
|
||||||
|
pyproject = true;
|
||||||
|
build-system = [
|
||||||
|
python313Packages.setuptools
|
||||||
|
python313Packages.wheel
|
||||||
|
];
|
||||||
|
propagatedBuildInputs = with python313Packages; [
|
||||||
|
django
|
||||||
|
cryptography
|
||||||
|
];
|
||||||
|
};
|
||||||
|
drf-access-policy = python313Packages.buildPythonPackage rec {
|
||||||
|
pname = "drf-access-policy";
|
||||||
|
version = "1.5.0";
|
||||||
|
src = fetchPypi {
|
||||||
|
inherit pname version;
|
||||||
|
hash = "sha256-EsahQYIgjUBUSi/W8GXbc7pvYLPRJ6kpJg6A3RkrjL8=";
|
||||||
|
};
|
||||||
|
doCheck = false;
|
||||||
|
pyproject = true;
|
||||||
|
build-system = [
|
||||||
|
python313Packages.setuptools
|
||||||
|
python313Packages.wheel
|
||||||
|
];
|
||||||
|
propagatedBuildInputs = with python313Packages; [
|
||||||
|
pyparsing
|
||||||
|
djangorestframework
|
||||||
|
];
|
||||||
|
};
|
||||||
|
|
||||||
|
pythonPkg = python313.override {
|
||||||
|
self = python313;
|
||||||
|
packageOverrides = pyfinal: pyprev: {
|
||||||
|
inherit
|
||||||
|
django-modern-rpc
|
||||||
|
django-property-filter
|
||||||
|
django-fernet-encrypted-fields
|
||||||
|
drf-access-policy
|
||||||
|
# psycopg-binary
|
||||||
|
;
|
||||||
|
# clevercsv's test_encoding_chardet is nondeterministic (chardet
|
||||||
|
# returns None instead of ISO-8859-1/KOI8-R on some platforms),
|
||||||
|
# breaking the build. Skip its test suite.
|
||||||
|
clevercsv = pyprev.clevercsv.overridePythonAttrs (_old: {
|
||||||
|
doCheck = false;
|
||||||
|
doInstallCheck = false;
|
||||||
|
});
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
python = pythonPkg.withPackages (
|
||||||
|
ps: with ps; [
|
||||||
|
gunicorn
|
||||||
|
django
|
||||||
|
clevercsv
|
||||||
|
django
|
||||||
|
dj-database-url
|
||||||
|
django-filter
|
||||||
|
django-modern-rpc
|
||||||
|
django-property-filter
|
||||||
|
djangorestframework
|
||||||
|
django-fernet-encrypted-fields
|
||||||
|
drf-access-policy
|
||||||
|
frozendict
|
||||||
|
gunicorn
|
||||||
|
psycopg
|
||||||
|
# psycopg-binary
|
||||||
|
psycopg2-binary
|
||||||
|
requests
|
||||||
|
sqlalchemy
|
||||||
|
whitenoise
|
||||||
|
]
|
||||||
|
);
|
||||||
|
|
||||||
|
staticAssets = fetchurl {
|
||||||
|
url = "https://github.com/mathesar-foundation/mathesar/releases/download/0.2.2/static_files.zip";
|
||||||
|
sha256 = "sha256-1X2zFpCSwilUxhqHlCw/tg8C5zVcVL6CxDa9yh0ylGA=";
|
||||||
|
};
|
||||||
|
|
||||||
|
in
|
||||||
|
python313Packages.buildPythonApplication rec {
|
||||||
|
pname = "mathesar";
|
||||||
|
version = "0.2.2";
|
||||||
|
src = fetchFromGitHub {
|
||||||
|
owner = "mathesar-foundation";
|
||||||
|
repo = "mathesar";
|
||||||
|
rev = version;
|
||||||
|
sha256 = "sha256-LHxFJpPV0GJfokSPzfZQO44bBg/+QjXsk04Ry9uhUAs=";
|
||||||
|
};
|
||||||
|
format = "other";
|
||||||
|
nativeBuildInputs = [ unzip ];
|
||||||
|
propagatedBuildInputs = [
|
||||||
|
python.pkgs.gunicorn
|
||||||
|
python.pkgs.django
|
||||||
|
];
|
||||||
|
buildInputs = [
|
||||||
|
gettext
|
||||||
|
];
|
||||||
|
dependencies = [
|
||||||
|
pythonPkg.pkgs.clevercsv
|
||||||
|
pythonPkg.pkgs.django
|
||||||
|
pythonPkg.pkgs.dj-database-url
|
||||||
|
pythonPkg.pkgs.django-filter
|
||||||
|
pythonPkg.pkgs.django-modern-rpc
|
||||||
|
pythonPkg.pkgs.django-property-filter
|
||||||
|
pythonPkg.pkgs.djangorestframework
|
||||||
|
pythonPkg.pkgs.django-fernet-encrypted-fields
|
||||||
|
pythonPkg.pkgs.drf-access-policy
|
||||||
|
pythonPkg.pkgs.frozendict
|
||||||
|
pythonPkg.pkgs.gunicorn
|
||||||
|
pythonPkg.pkgs.psycopg
|
||||||
|
pythonPkg.pkgs.psycopg2-binary
|
||||||
|
pythonPkg.pkgs.requests
|
||||||
|
pythonPkg.pkgs.sqlalchemy
|
||||||
|
pythonPkg.pkgs.whitenoise
|
||||||
|
];
|
||||||
|
|
||||||
|
# Manually unzip the extra zip file into a temporary directory
|
||||||
|
postUnpack = ''
|
||||||
|
mkdir -p $TMPDIR/unzipped
|
||||||
|
unzip ${staticAssets} -d $TMPDIR/unzipped
|
||||||
|
'';
|
||||||
|
|
||||||
|
# Override the default build phase to prevent it from looking for setup.py
|
||||||
|
# Add any non-Python build commands here if needed (e.g., building frontend assets)
|
||||||
|
buildPhase = ''
|
||||||
|
runHook preBuild
|
||||||
|
|
||||||
|
echo "Skipping standard Python build phase; application files copied in installPhase."
|
||||||
|
# If you had frontend assets to build, you'd run the command here, e.g.:
|
||||||
|
# npm install
|
||||||
|
# npm run build
|
||||||
|
|
||||||
|
runHook postBuild
|
||||||
|
'';
|
||||||
|
|
||||||
|
# This copies the application code into the Nix store output
|
||||||
|
installPhase = ''
|
||||||
|
runHook preInstall
|
||||||
|
|
||||||
|
# Destination: python's site-packages directory within $out
|
||||||
|
# This makes 'import mathesar', 'import db', etc. work more easily.
|
||||||
|
INSTALL_PATH="$out/lib/${python.libPrefix}/site-packages/${pname}"
|
||||||
|
mkdir -p "$INSTALL_PATH"
|
||||||
|
|
||||||
|
echo "Copying application code to $INSTALL_PATH"
|
||||||
|
|
||||||
|
# Copy all essential source directories needed at runtime
|
||||||
|
# Adjust this list based on mathesar's actual structure and runtime needs!
|
||||||
|
cp -r mathesar "$INSTALL_PATH/"
|
||||||
|
cp -r db "$INSTALL_PATH/"
|
||||||
|
cp -r config "$INSTALL_PATH/"
|
||||||
|
cp -r translations "$INSTALL_PATH/"
|
||||||
|
cp -r mathesar_ui "$INSTALL_PATH/" # If needed
|
||||||
|
|
||||||
|
# Copy the management script
|
||||||
|
cp manage.py "$INSTALL_PATH/"
|
||||||
|
|
||||||
|
# Copy assets from unzipped directory
|
||||||
|
mkdir -p "$INSTALL_PATH/mathesar/static/mathesar"
|
||||||
|
cp -r $TMPDIR/unzipped/static_files/* "$INSTALL_PATH/mathesar/static/mathesar"
|
||||||
|
|
||||||
|
# Create wrapper scripts in $out/bin for easy execution
|
||||||
|
|
||||||
|
mkdir -p $out/bin
|
||||||
|
|
||||||
|
# Wrapper for manage.py
|
||||||
|
# It ensures the app code is in PYTHONPATH and runs manage.py
|
||||||
|
echo "Creating manage.py wrapper..."
|
||||||
|
cat <<EOF > $out/bin/mathesar-manage
|
||||||
|
#!${python.interpreter}
|
||||||
|
import os
|
||||||
|
import sys
|
||||||
|
|
||||||
|
# Add the installation path to the Python path
|
||||||
|
sys.path.insert(0, "$INSTALL_PATH")
|
||||||
|
|
||||||
|
# Set DJANGO_SETTINGS_MODULE environment variable if required by mathesar
|
||||||
|
# You might need to adjust 'config.settings.production' to the actual settings file used
|
||||||
|
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'config.settings.production')
|
||||||
|
|
||||||
|
# Change directory to where manage.py is, if necessary for relative paths
|
||||||
|
# os.chdir("$INSTALL_PATH")
|
||||||
|
|
||||||
|
print(f"Running manage.py from: $INSTALL_PATH/manage.py")
|
||||||
|
print(f"Python path includes: $INSTALL_PATH")
|
||||||
|
print(f"Executing with args: {sys.argv[1:]}")
|
||||||
|
|
||||||
|
# Find manage.py and execute it
|
||||||
|
manage_py_path = os.path.join("$INSTALL_PATH", "manage.py")
|
||||||
|
if not os.path.exists(manage_py_path):
|
||||||
|
print(f"Error: manage.py not found at {manage_py_path}", file=sys.stderr)
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
# Prepare arguments for execute_from_command_line
|
||||||
|
# The first argument should be the script name itself
|
||||||
|
argv = [manage_py_path] + sys.argv[1:]
|
||||||
|
|
||||||
|
try:
|
||||||
|
from django.core.management import execute_from_command_line
|
||||||
|
execute_from_command_line(argv)
|
||||||
|
except Exception as e:
|
||||||
|
print(f"Error executing manage.py: {e}", file=sys.stderr)
|
||||||
|
# Optionally re-raise or exit with error
|
||||||
|
import traceback
|
||||||
|
traceback.print_exc()
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
EOF
|
||||||
|
chmod +x $out/bin/mathesar-manage
|
||||||
|
|
||||||
|
# Wrapper for install
|
||||||
|
echo "Creating install wrapper..."
|
||||||
|
cat <<EOF > $out/bin/mathesar-install
|
||||||
|
#!${runtimeShell}
|
||||||
|
# Add the app to the Python Path
|
||||||
|
export PYTHONPATH="$INSTALL_PATH:\${"PYTHONPATH:-"}"
|
||||||
|
|
||||||
|
# Set Django settings module if needed
|
||||||
|
export DJANGO_SETTINGS_MODULE='config.settings.production'
|
||||||
|
|
||||||
|
# Change to the app directory
|
||||||
|
cd "$INSTALL_PATH"
|
||||||
|
${python}/bin/python -m mathesar.install
|
||||||
|
EOF
|
||||||
|
chmod +x $out/bin/mathesar-install
|
||||||
|
|
||||||
|
# Wrapper for gunicorn (example)
|
||||||
|
# Assumes mathesar uses a standard wsgi entry point, e.g., config/wsgi.py
|
||||||
|
# Adjust 'config.wsgi:application' if necessary
|
||||||
|
echo "Creating gunicorn wrapper..."
|
||||||
|
cat <<EOF > $out/bin/mathesar-gunicorn
|
||||||
|
#!${runtimeShell}
|
||||||
|
# Add the app to the Python Path
|
||||||
|
export PYTHONPATH="$INSTALL_PATH:\${"PYTHONPATH:-"}"
|
||||||
|
|
||||||
|
# Set Django settings module if needed
|
||||||
|
export DJANGO_SETTINGS_MODULE='config.settings.production'
|
||||||
|
|
||||||
|
# Change to the app directory if gunicorn needs it
|
||||||
|
# cd "$INSTALL_PATH"
|
||||||
|
|
||||||
|
# Execute gunicorn, passing along any arguments
|
||||||
|
# Ensure the gunicorn package is in propagatedBuildInputs
|
||||||
|
exec ${python}/bin/gunicorn config.wsgi:application "\$@"
|
||||||
|
EOF
|
||||||
|
chmod +x $out/bin/mathesar-gunicorn
|
||||||
|
|
||||||
|
runHook postInstall
|
||||||
|
'';
|
||||||
|
}
|
||||||
@@ -5,11 +5,11 @@
|
|||||||
|
|
||||||
pkgs.stdenv.mkDerivation rec {
|
pkgs.stdenv.mkDerivation rec {
|
||||||
pname = "bypass-paywalls-clean";
|
pname = "bypass-paywalls-clean";
|
||||||
version = "4.0.6.1";
|
version = "4.1.1.4";
|
||||||
src = builtins.fetchGit {
|
src = builtins.fetchGit {
|
||||||
url = "https://gitflic.ru/project/magnolia1234/bpc_uploads.git";
|
url = "https://git.masu.rs/noah/bpc-uploads.git";
|
||||||
ref = "main";
|
ref = "main";
|
||||||
rev = "85a367220f5ae2181354f65fb1093e2f1ac9e417";
|
rev = "9166b13355721b047878f259e04c2e9b476b4210";
|
||||||
};
|
};
|
||||||
preferLocalBuild = true;
|
preferLocalBuild = true;
|
||||||
allowSubstitutes = true;
|
allowSubstitutes = true;
|
||||||
|
|||||||
@@ -0,0 +1,92 @@
|
|||||||
|
{
|
||||||
|
lib,
|
||||||
|
fetchFromGitHub,
|
||||||
|
nodejs_22,
|
||||||
|
buildNpmPackage,
|
||||||
|
typescript,
|
||||||
|
node-gyp,
|
||||||
|
python3,
|
||||||
|
gcc,
|
||||||
|
gnumake,
|
||||||
|
}:
|
||||||
|
let
|
||||||
|
|
||||||
|
in
|
||||||
|
|
||||||
|
buildNpmPackage (finalAttrs: rec {
|
||||||
|
pname = "prometheus-actual-exporter";
|
||||||
|
|
||||||
|
version = "1.1.5";
|
||||||
|
|
||||||
|
src = fetchFromGitHub {
|
||||||
|
owner = "sakowicz";
|
||||||
|
repo = "actual-budget-prometheus-exporter";
|
||||||
|
tag = version;
|
||||||
|
hash = "sha256-DAmWr1HngxAjhOJW9OnMfDqpxBcZT+Tpew/w/YYJIYU=";
|
||||||
|
};
|
||||||
|
|
||||||
|
patches = [ ./tsconfig.patch ];
|
||||||
|
|
||||||
|
npmDepsHash = "sha256-N8xqRYFelolNGTEhG22M7KJ7B5U/uW7o+/XfLF8rHMg=";
|
||||||
|
|
||||||
|
nativeBuildInputs = [
|
||||||
|
nodejs_22
|
||||||
|
typescript
|
||||||
|
python3
|
||||||
|
node-gyp
|
||||||
|
gcc
|
||||||
|
gnumake
|
||||||
|
];
|
||||||
|
|
||||||
|
postPatch = ''
|
||||||
|
echo "Removing better-sqlite3 install script before npm install"
|
||||||
|
sed -i '/"install"/d' node_modules/better-sqlite3/package.json || true
|
||||||
|
sed -i '/"install"/d' package.json || true
|
||||||
|
'';
|
||||||
|
|
||||||
|
preBuild = ''
|
||||||
|
echo "Disabling prebuilt install script from better-sqlite3"
|
||||||
|
find node_modules/better-sqlite3 -name package.json -exec sed -i '/"install"/d' {} +
|
||||||
|
rm -f node_modules/better-sqlite3/build/Release/better_sqlite3.node || true
|
||||||
|
'';
|
||||||
|
|
||||||
|
buildPhase = ''
|
||||||
|
# export npm_config_build_from_source=true
|
||||||
|
# export npm_config_unsafe_perm=true
|
||||||
|
# export BINARY_SITE=none
|
||||||
|
# export PATH=${node-gyp}/bin:$PATH
|
||||||
|
# export npm_config_node_gyp=${node-gyp}/bin/node-gyp
|
||||||
|
|
||||||
|
# npm rebuild better-sqlite3 --build-from-source --verbose
|
||||||
|
|
||||||
|
npm run build
|
||||||
|
'';
|
||||||
|
|
||||||
|
installPhase = ''
|
||||||
|
mkdir -p $out/{bin,lib}
|
||||||
|
cp -r . $out/lib/prometheus-actual-exporter
|
||||||
|
makeWrapper ${lib.getExe nodejs_22} $out/bin/prometheus-actual-exporter \
|
||||||
|
--add-flags "$out/lib/prometheus-actual-exporter/dist/app.js"
|
||||||
|
'';
|
||||||
|
|
||||||
|
postInstall = ''
|
||||||
|
echo "Removing prebuilt .node and rebuilding better-sqlite3"
|
||||||
|
|
||||||
|
export npm_config_build_from_source=true
|
||||||
|
export npm_config_unsafe_perm=true
|
||||||
|
export BINARY_SITE=none
|
||||||
|
export PATH=${node-gyp}/bin:$PATH
|
||||||
|
export npm_config_node_gyp=${node-gyp}/bin/node-gyp
|
||||||
|
|
||||||
|
sed -i '/"install"/d' node_modules/better-sqlite3/package.json
|
||||||
|
rm -f node_modules/better-sqlite3/build/Release/better_sqlite3.node || true
|
||||||
|
|
||||||
|
npm rebuild better-sqlite3 --build-from-source --verbose
|
||||||
|
'';
|
||||||
|
|
||||||
|
meta = {
|
||||||
|
description = "Prometheus exporter for Actual Budget";
|
||||||
|
homepage = "https://github.com/sakowicz/actual-budget-prometheus-exporter";
|
||||||
|
mainProgram = "prometheus-actual-exporter";
|
||||||
|
};
|
||||||
|
})
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
diff --git a/tsconfig.json b/tsconfig.json
|
||||||
|
index 5106135..3a340f6 100644
|
||||||
|
--- a/tsconfig.json
|
||||||
|
+++ b/tsconfig.json
|
||||||
|
@@ -8,5 +8,6 @@
|
||||||
|
"skipLibCheck": true,
|
||||||
|
"lib": ["es2020"],
|
||||||
|
"outDir": "./dist"
|
||||||
|
- }
|
||||||
|
+ },
|
||||||
|
+ "include": ["src/**/*", "app.ts"]
|
||||||
|
}
|
||||||
@@ -0,0 +1,248 @@
|
|||||||
|
{ fetchNuGet }:
|
||||||
|
[
|
||||||
|
(fetchNuGet {
|
||||||
|
pname = "AngleSharp";
|
||||||
|
version = "1.2.0";
|
||||||
|
hash = "sha256-l8+Var9o773VL6Ybih3boaFf9sYjS7eqtLGd8DCIPsk=";
|
||||||
|
})
|
||||||
|
(fetchNuGet {
|
||||||
|
pname = "EmbedIO";
|
||||||
|
version = "3.5.2";
|
||||||
|
hash = "sha256-e6GfVHXxYeUw3ntCrHokNoAS6mXArO7+vdMeUFnsSo8=";
|
||||||
|
})
|
||||||
|
(fetchNuGet {
|
||||||
|
pname = "Goblinfactory.ProgressBar";
|
||||||
|
version = "1.0.0";
|
||||||
|
hash = "sha256-tV3Fw792zfYhB2dN97VKXBwS5eypqKExgAJy+bcDo8I=";
|
||||||
|
})
|
||||||
|
(fetchNuGet {
|
||||||
|
pname = "Google.Apis";
|
||||||
|
version = "1.69.0";
|
||||||
|
hash = "sha256-/9JN0CZIFZnmGS69ki38RlNzQiwp4yO0MFDeRk1slsg=";
|
||||||
|
})
|
||||||
|
(fetchNuGet {
|
||||||
|
pname = "Google.Apis.Auth";
|
||||||
|
version = "1.69.0";
|
||||||
|
hash = "sha256-T6n3hc+KpgHNqQQeJLOmgHQWkjBvnhIob5giHabREV8=";
|
||||||
|
})
|
||||||
|
(fetchNuGet {
|
||||||
|
pname = "Google.Apis.Core";
|
||||||
|
version = "1.69.0";
|
||||||
|
hash = "sha256-IW1AOY8o6hHkrc/tINsS/VCOUrOSoXb6OCSEF6gamkc=";
|
||||||
|
})
|
||||||
|
(fetchNuGet {
|
||||||
|
pname = "Google.Apis.YouTube.v3";
|
||||||
|
version = "1.69.0.3680";
|
||||||
|
hash = "sha256-3aNScBqmchnDkLejK5HYHiLVVDexrFUtZ6xe8cGP28M=";
|
||||||
|
})
|
||||||
|
(fetchNuGet {
|
||||||
|
pname = "HtmlAgilityPack";
|
||||||
|
version = "1.11.72";
|
||||||
|
hash = "sha256-MRt7yj6+/ORmr2WBERpQ+1gMRzIaPFKddHoB4zZmv2k=";
|
||||||
|
})
|
||||||
|
(fetchNuGet {
|
||||||
|
pname = "Microsoft.ApplicationInsights";
|
||||||
|
version = "2.22.0";
|
||||||
|
hash = "sha256-mUQ63atpT00r49ca50uZu2YCiLg3yd6r3HzTryqcuEA=";
|
||||||
|
})
|
||||||
|
(fetchNuGet {
|
||||||
|
pname = "Microsoft.AspNetCore.App.Ref";
|
||||||
|
version = "6.0.36";
|
||||||
|
hash = "sha256-9jDkWbjw/nd8yqdzVTagCuqr6owJ/DUMi4BlUZT4hWU=";
|
||||||
|
})
|
||||||
|
(fetchNuGet {
|
||||||
|
pname = "Microsoft.Bcl.AsyncInterfaces";
|
||||||
|
version = "9.0.1";
|
||||||
|
hash = "sha256-A3W2Hvhlf1ODx1NYWHwUyziZOGMaDPvXHZ/ubgNLYJA=";
|
||||||
|
})
|
||||||
|
(fetchNuGet {
|
||||||
|
pname = "Microsoft.CodeCoverage";
|
||||||
|
version = "17.9.0";
|
||||||
|
hash = "sha256-OaGa4+jRPHs+T+p/oekm2Miluqfd2IX8Rt+BmUx8kr4=";
|
||||||
|
})
|
||||||
|
(fetchNuGet {
|
||||||
|
pname = "Microsoft.CSharp";
|
||||||
|
version = "4.7.0";
|
||||||
|
hash = "sha256-Enknv2RsFF68lEPdrf5M+BpV1kHoLTVRApKUwuk/pj0=";
|
||||||
|
})
|
||||||
|
(fetchNuGet {
|
||||||
|
pname = "Microsoft.NET.Test.Sdk";
|
||||||
|
version = "17.9.0";
|
||||||
|
hash = "sha256-q/1AJ7eNlk02wvN76qvjl2xBx5iJ+h5ssiE/4akLmtI=";
|
||||||
|
})
|
||||||
|
(fetchNuGet {
|
||||||
|
pname = "Microsoft.NETCore.App.Host.linux-x64";
|
||||||
|
version = "6.0.36";
|
||||||
|
hash = "sha256-VFRDzx7LJuvI5yzKdGmw/31NYVbwHWPKQvueQt5xc10=";
|
||||||
|
})
|
||||||
|
(fetchNuGet {
|
||||||
|
pname = "Microsoft.NETCore.App.Ref";
|
||||||
|
version = "6.0.36";
|
||||||
|
hash = "sha256-9LZgVoIFF8qNyUu8kdJrYGLutMF/cL2K82HN2ywwlx8=";
|
||||||
|
})
|
||||||
|
(fetchNuGet {
|
||||||
|
pname = "Microsoft.Testing.Extensions.Telemetry";
|
||||||
|
version = "1.5.3";
|
||||||
|
hash = "sha256-bIXwPSa3jkr2b6xINOqMUs6/uj/r4oVFM7xq3uVIZDU=";
|
||||||
|
})
|
||||||
|
(fetchNuGet {
|
||||||
|
pname = "Microsoft.Testing.Extensions.TrxReport.Abstractions";
|
||||||
|
version = "1.5.3";
|
||||||
|
hash = "sha256-IfMRfcyaIKEMRtx326ICKtinDBEfGw/Sv8ZHawJ96Yc=";
|
||||||
|
})
|
||||||
|
(fetchNuGet {
|
||||||
|
pname = "Microsoft.Testing.Extensions.VSTestBridge";
|
||||||
|
version = "1.5.3";
|
||||||
|
hash = "sha256-XpM/yFjhLSsuzyDV+xKubs4V1zVVYiV05E0+N4S1h0g=";
|
||||||
|
})
|
||||||
|
(fetchNuGet {
|
||||||
|
pname = "Microsoft.Testing.Platform";
|
||||||
|
version = "1.5.3";
|
||||||
|
hash = "sha256-y61Iih6w5D79dmrj2V675mcaeIiHoj1HSa1FRit2BLM=";
|
||||||
|
})
|
||||||
|
(fetchNuGet {
|
||||||
|
pname = "Microsoft.Testing.Platform.MSBuild";
|
||||||
|
version = "1.5.3";
|
||||||
|
hash = "sha256-YspvjE5Jfi587TAfsvfDVJXNrFOkx1B3y1CKV6m7YLY=";
|
||||||
|
})
|
||||||
|
(fetchNuGet {
|
||||||
|
pname = "Microsoft.TestPlatform.ObjectModel";
|
||||||
|
version = "17.12.0";
|
||||||
|
hash = "sha256-3XBHBSuCxggAIlHXmKNQNlPqMqwFlM952Av6RrLw1/w=";
|
||||||
|
})
|
||||||
|
(fetchNuGet {
|
||||||
|
pname = "Microsoft.TestPlatform.ObjectModel";
|
||||||
|
version = "17.9.0";
|
||||||
|
hash = "sha256-iiXUFzpvT8OWdzMj9FGJDqanwHx40s1TXVY9l3ii+s0=";
|
||||||
|
})
|
||||||
|
(fetchNuGet {
|
||||||
|
pname = "Microsoft.TestPlatform.TestHost";
|
||||||
|
version = "17.9.0";
|
||||||
|
hash = "sha256-1BZIY1z+C9TROgdTV/tq4zsPy7Q71GQksr/LoMKAzqU=";
|
||||||
|
})
|
||||||
|
(fetchNuGet {
|
||||||
|
pname = "MSTest.Analyzers";
|
||||||
|
version = "3.7.3";
|
||||||
|
hash = "sha256-6mNfHtx9FBWA6/QrRUepwbxXWG/54GRyeZYazDiMacg=";
|
||||||
|
})
|
||||||
|
(fetchNuGet {
|
||||||
|
pname = "MSTest.TestAdapter";
|
||||||
|
version = "3.7.3";
|
||||||
|
hash = "sha256-3O/AXeS+3rHWstinivt73oa0QDp+xQpTc9p46EF+Mtc=";
|
||||||
|
})
|
||||||
|
(fetchNuGet {
|
||||||
|
pname = "MSTest.TestFramework";
|
||||||
|
version = "3.7.3";
|
||||||
|
hash = "sha256-RweCMMf14GI6HqjDIP68JM67IaJKYQTZy0jk5Q4DFxs=";
|
||||||
|
})
|
||||||
|
(fetchNuGet {
|
||||||
|
pname = "Newtonsoft.Json";
|
||||||
|
version = "13.0.1";
|
||||||
|
hash = "sha256-K2tSVW4n4beRPzPu3rlVaBEMdGvWSv/3Q1fxaDh4Mjo=";
|
||||||
|
})
|
||||||
|
(fetchNuGet {
|
||||||
|
pname = "Newtonsoft.Json";
|
||||||
|
version = "13.0.3";
|
||||||
|
hash = "sha256-hy/BieY4qxBWVVsDqqOPaLy1QobiIapkbrESm6v2PHc=";
|
||||||
|
})
|
||||||
|
(fetchNuGet {
|
||||||
|
pname = "SmallestCSVParser";
|
||||||
|
version = "1.1.1";
|
||||||
|
hash = "sha256-64E87w+4FcQtYsFIOMGGmYmjXVGBwsBqgLVb7p0wc04=";
|
||||||
|
})
|
||||||
|
(fetchNuGet {
|
||||||
|
pname = "Soulseek";
|
||||||
|
version = "7.1.0";
|
||||||
|
hash = "sha256-n6LUNuPmmy9QYNNALR0ObYyR9LJalf0H8P+SKnoqfFc=";
|
||||||
|
})
|
||||||
|
(fetchNuGet {
|
||||||
|
pname = "SpotifyAPI.Web";
|
||||||
|
version = "7.2.1";
|
||||||
|
hash = "sha256-gbTLJaj7DSXZQlo0xpegZ8HLruMe6WmDyD8+l6YE3hg=";
|
||||||
|
})
|
||||||
|
(fetchNuGet {
|
||||||
|
pname = "SpotifyAPI.Web.Auth";
|
||||||
|
version = "7.2.1";
|
||||||
|
hash = "sha256-uzpyPlXNCuSHrcK4SKH0ydY2HlDKXU51W5ahk2Oqu98=";
|
||||||
|
})
|
||||||
|
(fetchNuGet {
|
||||||
|
pname = "System.Buffers";
|
||||||
|
version = "4.5.1";
|
||||||
|
hash = "sha256-wws90sfi9M7kuCPWkv1CEYMJtCqx9QB/kj0ymlsNaxI=";
|
||||||
|
})
|
||||||
|
(fetchNuGet {
|
||||||
|
pname = "System.CodeDom";
|
||||||
|
version = "7.0.0";
|
||||||
|
hash = "sha256-7IPt39cY+0j0ZcRr/J45xPtEjnSXdUJ/5ai3ebaYQiE=";
|
||||||
|
})
|
||||||
|
(fetchNuGet {
|
||||||
|
pname = "System.Diagnostics.DiagnosticSource";
|
||||||
|
version = "5.0.0";
|
||||||
|
hash = "sha256-6mW3N6FvcdNH/pB58pl+pFSCGWgyaP4hfVtC/SMWDV4=";
|
||||||
|
})
|
||||||
|
(fetchNuGet {
|
||||||
|
pname = "System.IO.Pipelines";
|
||||||
|
version = "9.0.1";
|
||||||
|
hash = "sha256-CnmDanknCGbNnoDjgZw62M/Grg8IMTJDa8x3P07UR2A=";
|
||||||
|
})
|
||||||
|
(fetchNuGet {
|
||||||
|
pname = "System.Management";
|
||||||
|
version = "7.0.2";
|
||||||
|
hash = "sha256-bJ21ILQfbHb8mX2wnVh7WP/Ip7gdVPIw+BamQuifTVY=";
|
||||||
|
})
|
||||||
|
(fetchNuGet {
|
||||||
|
pname = "System.Memory";
|
||||||
|
version = "4.5.5";
|
||||||
|
hash = "sha256-EPQ9o1Kin7KzGI5O3U3PUQAZTItSbk9h/i4rViN3WiI=";
|
||||||
|
})
|
||||||
|
(fetchNuGet {
|
||||||
|
pname = "System.Memory";
|
||||||
|
version = "4.6.0";
|
||||||
|
hash = "sha256-OhAEKzUM6eEaH99DcGaMz2pFLG/q/N4KVWqqiBYUOFo=";
|
||||||
|
})
|
||||||
|
(fetchNuGet {
|
||||||
|
pname = "System.Reflection.Metadata";
|
||||||
|
version = "1.6.0";
|
||||||
|
hash = "sha256-JJfgaPav7UfEh4yRAQdGhLZF1brr0tUWPl6qmfNWq/E=";
|
||||||
|
})
|
||||||
|
(fetchNuGet {
|
||||||
|
pname = "System.Runtime.CompilerServices.Unsafe";
|
||||||
|
version = "6.0.0";
|
||||||
|
hash = "sha256-bEG1PnDp7uKYz/OgLOWs3RWwQSVYm+AnPwVmAmcgp2I=";
|
||||||
|
})
|
||||||
|
(fetchNuGet {
|
||||||
|
pname = "System.Text.Encodings.Web";
|
||||||
|
version = "9.0.1";
|
||||||
|
hash = "sha256-iuAVcTiiZQLCZjDfDqdLLPHqZdZqvFabwLFHiVYdRJo=";
|
||||||
|
})
|
||||||
|
(fetchNuGet {
|
||||||
|
pname = "System.Text.Json";
|
||||||
|
version = "9.0.1";
|
||||||
|
hash = "sha256-2dqE+Mx5eJZ8db74ofUiUXHOSxDCmXw5n9VC9w4fUr0=";
|
||||||
|
})
|
||||||
|
(fetchNuGet {
|
||||||
|
pname = "System.Threading.Tasks.Extensions";
|
||||||
|
version = "4.6.0";
|
||||||
|
hash = "sha256-OwIB0dpcdnyfvTUUj6gQfKW2XF2pWsQhykwM1HNCHqY=";
|
||||||
|
})
|
||||||
|
(fetchNuGet {
|
||||||
|
pname = "System.ValueTuple";
|
||||||
|
version = "4.5.0";
|
||||||
|
hash = "sha256-niH6l2fU52vAzuBlwdQMw0OEoRS/7E1w5smBFoqSaAI=";
|
||||||
|
})
|
||||||
|
(fetchNuGet {
|
||||||
|
pname = "TagLibSharp";
|
||||||
|
version = "2.3.0";
|
||||||
|
hash = "sha256-PD9bVZiPaeC8hNx2D+uDUf701cCaMi2IRi5oPTNN+/w=";
|
||||||
|
})
|
||||||
|
(fetchNuGet {
|
||||||
|
pname = "Unosquare.Swan.Lite";
|
||||||
|
version = "3.1.0";
|
||||||
|
hash = "sha256-PL8N3CqIz/wku8/mkRMC3X868Byv47C20/rBLBhkS3o=";
|
||||||
|
})
|
||||||
|
(fetchNuGet {
|
||||||
|
pname = "YoutubeExplode";
|
||||||
|
version = "6.5.4";
|
||||||
|
hash = "sha256-5sexIiBj5XP9rP5DA0NQ+vHJ9lpjwp00EvVux901WLc=";
|
||||||
|
})
|
||||||
|
]
|
||||||
@@ -0,0 +1,42 @@
|
|||||||
|
{
|
||||||
|
lib,
|
||||||
|
stdenv,
|
||||||
|
buildDotnetModule,
|
||||||
|
fetchFromGitHub,
|
||||||
|
dotnetCorePackages,
|
||||||
|
}:
|
||||||
|
|
||||||
|
if !stdenv.hostPlatform.isLinux then
|
||||||
|
null
|
||||||
|
else
|
||||||
|
buildDotnetModule rec {
|
||||||
|
pname = "slsk-batchdl";
|
||||||
|
version = "2.4.7";
|
||||||
|
|
||||||
|
src = fetchFromGitHub {
|
||||||
|
owner = "fiso64";
|
||||||
|
repo = "slsk-batchdl";
|
||||||
|
rev = "v${version}";
|
||||||
|
sha256 = "sha256-P7V7YJUA1bkfp13Glb1Q+NJ7iTya/xgO1TM88z1Nddc=";
|
||||||
|
};
|
||||||
|
|
||||||
|
projectFile = "slsk-batchdl/slsk-batchdl.csproj";
|
||||||
|
nugetDeps = ./nuget-deps.nix;
|
||||||
|
|
||||||
|
dotnet-sdk = dotnetCorePackages.sdk_8_0;
|
||||||
|
dotnet-runtime = dotnetCorePackages.runtime_8_0;
|
||||||
|
|
||||||
|
postPatch = ''
|
||||||
|
substituteInPlace slsk-batchdl/slsk-batchdl.csproj \
|
||||||
|
--replace-fail "net6.0" "net8.0"
|
||||||
|
'';
|
||||||
|
|
||||||
|
doCheck = false;
|
||||||
|
|
||||||
|
meta = with lib; {
|
||||||
|
description = "A batch downloader for Soulseek";
|
||||||
|
homepage = "https://github.com/fiso64/slsk-batchdl";
|
||||||
|
platforms = platforms.linux;
|
||||||
|
mainProgram = "slsk-batchdl";
|
||||||
|
};
|
||||||
|
}
|
||||||
@@ -19,4 +19,4 @@ aws ec2 describe-instances \
|
|||||||
--layout reverse \
|
--layout reverse \
|
||||||
--header $'Press Enter to start SSM session\nInstance ID - Private IP - Public IP - Name' \
|
--header $'Press Enter to start SSM session\nInstance ID - Private IP - Public IP - Name' \
|
||||||
--preview "aws ec2 describe-instances --instance-ids \"\$(echo {} | cut -d' ' -f1)\" | jq -r '.Reservations[].Instances[0]'" \
|
--preview "aws ec2 describe-instances --instance-ids \"\$(echo {} | cut -d' ' -f1)\" | jq -r '.Reservations[].Instances[0]'" \
|
||||||
--bind "enter:become(aws ssm start-session --target \$(echo {} | cut -d' ' -f1))"
|
--bind "enter:become(aws ssm start-session --document-name 'AWS-StartInteractiveCommand' --parameters '{\"command\": [\"bash\"]}' --target \$(echo {} | cut -d' ' -f1))"
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ pkgs.mkShell {
|
|||||||
buildInputs = with pkgs; [
|
buildInputs = with pkgs; [
|
||||||
git
|
git
|
||||||
stylua
|
stylua
|
||||||
nixfmt-rfc-style
|
nixfmt
|
||||||
shfmt
|
shfmt
|
||||||
shellcheck
|
shellcheck
|
||||||
];
|
];
|
||||||
|
|||||||
@@ -1,9 +1,12 @@
|
|||||||
{ pkgs, ... }:
|
{ pkgs, lib, ... }:
|
||||||
|
|
||||||
# Inspired by https://github.com/cleverca22/nix-tests/blob/master/kexec/justdoit.nix
|
# Inspired by https://github.com/cleverca22/nix-tests/blob/master/kexec/justdoit.nix
|
||||||
# This script will partition and format drives; use at your own risk!
|
# This script will partition and format drives; use at your own risk!
|
||||||
|
|
||||||
pkgs.writeShellScriptBin "installer" ''
|
if !pkgs.stdenv.hostPlatform.isLinux then
|
||||||
|
null
|
||||||
|
else
|
||||||
|
pkgs.writeShellScriptBin "installer" ''
|
||||||
set -e
|
set -e
|
||||||
|
|
||||||
DISK=$1
|
DISK=$1
|
||||||
@@ -41,4 +44,4 @@ pkgs.writeShellScriptBin "installer" ''
|
|||||||
mount /dev/disk/by-label/boot /mnt/boot
|
mount /dev/disk/by-label/boot /mnt/boot
|
||||||
|
|
||||||
${pkgs.nixos-install-tools}/bin/nixos-install --flake github:nmasur/dotfiles#''${FLAKE}
|
${pkgs.nixos-install-tools}/bin/nixos-install --flake github:nmasur/dotfiles#''${FLAKE}
|
||||||
''
|
''
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
{ pkgs, ... }:
|
{ pkgs, ... }:
|
||||||
|
|
||||||
pkgs.writeShellScriptBin "rebuild" ''
|
pkgs.writeShellScriptBin "rebuild" ''
|
||||||
echo ${pkgs.system}
|
echo ${pkgs.stdenv.hostPlatform.system}
|
||||||
SYSTEM=${if pkgs.stdenv.isDarwin then "darwin" else "linux"}
|
SYSTEM=${if pkgs.stdenv.hostPlatform.isDarwin then "darwin" else "linux"}
|
||||||
if [ "$SYSTEM" == "darwin" ]; then
|
if [ "$SYSTEM" == "darwin" ]; then
|
||||||
sudo darwin-rebuild switch --flake ${builtins.toString ../../../../.}
|
sudo darwin-rebuild switch --flake ${builtins.toString ../../../../.}
|
||||||
else
|
else
|
||||||
|
|||||||
@@ -8,6 +8,5 @@ pkgs.rustPlatform.buildRustPackage {
|
|||||||
rev = "50c40172e354caffee48932266edd7c7a76a20fd";
|
rev = "50c40172e354caffee48932266edd7c7a76a20fd";
|
||||||
sha256 = "sha256-zVIt6Xp+Mvym6gySvHIZJt1QgzKVP/wbTGTubWk6kzI=";
|
sha256 = "sha256-zVIt6Xp+Mvym6gySvHIZJt1QgzKVP/wbTGTubWk6kzI=";
|
||||||
};
|
};
|
||||||
useFetchCargoVendor = true;
|
|
||||||
cargoHash = "sha256-lSeO/GaJPZ8zosOIJRXVIEuPXaBg1GBvKBIuXtu1xZg=";
|
cargoHash = "sha256-lSeO/GaJPZ8zosOIJRXVIEuPXaBg1GBvKBIuXtu1xZg=";
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,6 +8,5 @@ pkgs.rustPlatform.buildRustPackage {
|
|||||||
rev = "2a24f95170aa14b5182b2287125664a62f8688ef";
|
rev = "2a24f95170aa14b5182b2287125664a62f8688ef";
|
||||||
sha256 = "sha256-gBxrbGCy6JEHnmgJmcm8sgtEvCAqra8/gPGsfCEfLqg=";
|
sha256 = "sha256-gBxrbGCy6JEHnmgJmcm8sgtEvCAqra8/gPGsfCEfLqg=";
|
||||||
};
|
};
|
||||||
useFetchCargoVendor = true;
|
|
||||||
cargoHash = "sha256-t4tfQaFq4EV4ZWeU+IestSFiSAIeVQslTZhLbpKVoO4=";
|
cargoHash = "sha256-t4tfQaFq4EV4ZWeU+IestSFiSAIeVQslTZhLbpKVoO4=";
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -21,10 +21,12 @@ in
|
|||||||
virtualisation.diskSize = lib.mkDefault (16 * 1024); # In MB
|
virtualisation.diskSize = lib.mkDefault (16 * 1024); # In MB
|
||||||
|
|
||||||
boot.kernelPackages = lib.mkDefault pkgs.linuxKernel.packages.linux_6_6;
|
boot.kernelPackages = lib.mkDefault pkgs.linuxKernel.packages.linux_6_6;
|
||||||
boot.loader.systemd-boot.enable = false;
|
boot.loader.systemd-boot.enable = lib.mkForce false;
|
||||||
boot.loader.efi.canTouchEfiVariables = false;
|
boot.loader.efi.canTouchEfiVariables = lib.mkForce false; # Default, conflicts with tempest
|
||||||
services.amazon-ssm-agent.enable = lib.mkDefault true;
|
services.amazon-ssm-agent.enable = lib.mkDefault true;
|
||||||
users.users.ssm-user.extraGroups = [ "wheel" ];
|
users.users.ssm-user.extraGroups = [ "wheel" ];
|
||||||
|
services.udisks2.enable = lib.mkForce false; # Off by default already; conflicts with gvfs for nautilus
|
||||||
|
boot.loader.grub.device = lib.mkForce "/dev/xvda"; # Default, conflicts with tempest
|
||||||
|
boot.loader.grub.efiSupport = lib.mkForce false; # Default, conflicts with tempest
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,23 +17,27 @@ in
|
|||||||
home.packages = [
|
home.packages = [
|
||||||
pkgs.nerd-fonts.victor-mono # Used for Vim and Terminal
|
pkgs.nerd-fonts.victor-mono # Used for Vim and Terminal
|
||||||
pkgs.nerd-fonts.hack # For Polybar, Rofi
|
pkgs.nerd-fonts.hack # For Polybar, Rofi
|
||||||
|
|
||||||
|
# Maple Mono NF (Ligature unhinted)
|
||||||
|
pkgs.maple-mono.NF-unhinted
|
||||||
];
|
];
|
||||||
fonts.fontconfig = {
|
fonts.fontconfig = {
|
||||||
enable = true;
|
enable = true;
|
||||||
defaultFonts.monospace = [ "Victor Mono" ];
|
defaultFonts.monospace = [ "Maple Mono NF" ];
|
||||||
};
|
};
|
||||||
|
|
||||||
xsession.windowManager.i3.config.fonts = {
|
xsession.windowManager.i3.config.fonts = {
|
||||||
names = [ "pango:Victor Mono" ];
|
# names = [ "pango:Victor Mono" ];
|
||||||
|
names = [ "pango:Maple Mono" ];
|
||||||
# style = "Regular";
|
# style = "Regular";
|
||||||
# size = 11.0;
|
# size = 11.0;
|
||||||
};
|
};
|
||||||
services.polybar.config."bar/main".font-0 = "Hack Nerd Font:size=10;2";
|
services.polybar.config."bar/main".font-0 = "Hack Nerd Font:size=10;2";
|
||||||
programs.rofi.font = "Hack Nerd Font 14";
|
programs.rofi.font = "Hack Nerd Font 14";
|
||||||
programs.alacritty.settings.font.normal.family = "VictorMono";
|
programs.alacritty.settings.font.normal.family = "Maple Mono NF";
|
||||||
programs.kitty.font.name = "VictorMono Nerd Font Mono";
|
programs.kitty.font.name = "Maple Mono NF";
|
||||||
nmasur.presets.programs.wezterm.font = "VictorMono Nerd Font Mono";
|
nmasur.presets.programs.wezterm.font = "Maple Mono NF";
|
||||||
programs.ghostty.settings.font-family = "VictorMono Nerd Font Mono";
|
programs.ghostty.settings.font-family = "Maple Mono NF";
|
||||||
services.dunst.settings.global.font = "Hack Nerd Font 14";
|
services.dunst.settings.global.font = "Hack Nerd Font 14";
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -25,6 +25,7 @@ in
|
|||||||
config = lib.mkIf cfg.enable {
|
config = lib.mkIf cfg.enable {
|
||||||
# Cursor
|
# Cursor
|
||||||
home.pointerCursor = {
|
home.pointerCursor = {
|
||||||
|
enable = true;
|
||||||
name = "Adwaita";
|
name = "Adwaita";
|
||||||
package = pkgs.adwaita-icon-theme;
|
package = pkgs.adwaita-icon-theme;
|
||||||
size = 24;
|
size = 24;
|
||||||
@@ -48,6 +49,7 @@ in
|
|||||||
gtk4.extraConfig = {
|
gtk4.extraConfig = {
|
||||||
gtk-application-prefer-dark-theme = config.theme.mode == "dark";
|
gtk-application-prefer-dark-theme = config.theme.mode == "dark";
|
||||||
};
|
};
|
||||||
|
gtk4.theme = null;
|
||||||
};
|
};
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -18,16 +18,17 @@ in
|
|||||||
"1password"
|
"1password"
|
||||||
"_1password-gui"
|
"_1password-gui"
|
||||||
"1password-cli"
|
"1password-cli"
|
||||||
"onepassword-password-manager" # Firefox extension
|
# "onepassword-password-manager" # Firefox extension
|
||||||
];
|
];
|
||||||
home.packages = [
|
home.packages = [
|
||||||
pkgs._1password-cli
|
pkgs._1password-cli
|
||||||
] ++ (if pkgs.stdenv.isLinux then [ pkgs._1password-gui ] else [ ]);
|
]
|
||||||
|
++ (if pkgs.stdenv.hostPlatform.isLinux then [ pkgs._1password-gui ] else [ ]);
|
||||||
|
|
||||||
# Firefox extension
|
# # Firefox extension
|
||||||
programs.firefox.profiles.default.extensions.packages = [
|
# programs.firefox.profiles.default.extensions.packages = [
|
||||||
pkgs.nur.repos.rycee.firefox-addons.onepassword-password-manager
|
# pkgs.nur.repos.rycee.firefox-addons.onepassword-password-manager
|
||||||
];
|
# ];
|
||||||
};
|
};
|
||||||
|
|
||||||
# # https://1password.community/discussion/135462/firefox-extension-does-not-connect-to-linux-app
|
# # https://1password.community/discussion/135462/firefox-extension-does-not-connect-to-linux-app
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ in
|
|||||||
home.packages = with pkgs; [
|
home.packages = with pkgs; [
|
||||||
w3m # Render HTML
|
w3m # Render HTML
|
||||||
dante # Socksify for rendering HTML
|
dante # Socksify for rendering HTML
|
||||||
|
aba # Address book
|
||||||
];
|
];
|
||||||
|
|
||||||
programs.aerc = {
|
programs.aerc = {
|
||||||
@@ -110,6 +111,7 @@ in
|
|||||||
"<C-j>" = ":next-part<Enter>";
|
"<C-j>" = ":next-part<Enter>";
|
||||||
J = ":next <Enter>";
|
J = ":next <Enter>";
|
||||||
K = ":prev<Enter>";
|
K = ":prev<Enter>";
|
||||||
|
aa = ":pipe -m aba parse --all<Enter>";
|
||||||
};
|
};
|
||||||
|
|
||||||
"view::passthrough" = {
|
"view::passthrough" = {
|
||||||
@@ -172,8 +174,10 @@ in
|
|||||||
filters = {
|
filters = {
|
||||||
"text/plain" = "${pkgs.aerc}/libexec/aerc/filters/colorize";
|
"text/plain" = "${pkgs.aerc}/libexec/aerc/filters/colorize";
|
||||||
"text/calendar" = "${pkgs.gawk}/bin/awk -f ${pkgs.aerc}/libexec/aerc/filters/calendar";
|
"text/calendar" = "${pkgs.gawk}/bin/awk -f ${pkgs.aerc}/libexec/aerc/filters/calendar";
|
||||||
|
# "text/html" =
|
||||||
|
# "${pkgs.aerc}/libexec/aerc/filters/html | ${pkgs.aerc}/libexec/aerc/filters/colorize"; # Requires w3m, dante
|
||||||
"text/html" =
|
"text/html" =
|
||||||
"${pkgs.aerc}/libexec/aerc/filters/html | ${pkgs.aerc}/libexec/aerc/filters/colorize"; # Requires w3m, dante
|
"!${pkgs.chawan}/bin/cha --type text/html --opt display.image-mode=kitty --opt display.columns=100 --opt display.force-columns=true";
|
||||||
# "text/*" =
|
# "text/*" =
|
||||||
# ''${pkgs.bat}/bin/bat -fP --file-name="$AERC_FILENAME "'';
|
# ''${pkgs.bat}/bin/bat -fP --file-name="$AERC_FILENAME "'';
|
||||||
"message/delivery-status" = "${pkgs.aerc}/libexec/aerc/filters/colorize";
|
"message/delivery-status" = "${pkgs.aerc}/libexec/aerc/filters/colorize";
|
||||||
@@ -183,6 +187,10 @@ in
|
|||||||
"audio/*" = "${pkgs.mpv}/bin/mpv -";
|
"audio/*" = "${pkgs.mpv}/bin/mpv -";
|
||||||
"image/*" = "${pkgs.feh}/bin/feh -";
|
"image/*" = "${pkgs.feh}/bin/feh -";
|
||||||
};
|
};
|
||||||
|
compose = {
|
||||||
|
editor = config.home.sessionVariables.EDITOR;
|
||||||
|
address-book-cmd = "aba ls \"%s\"";
|
||||||
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
accounts.email.accounts.home.aerc = {
|
accounts.email.accounts.home.aerc = {
|
||||||
@@ -194,21 +202,33 @@ in
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
xdg.desktopEntries.aerc = lib.mkIf (pkgs.stdenv.isLinux) {
|
# Used for macOS
|
||||||
|
xdg.enable = lib.mkIf pkgs.stdenv.hostPlatform.isDarwin true;
|
||||||
|
|
||||||
|
xdg.desktopEntries.aerc = lib.mkIf (pkgs.stdenv.hostPlatform.isLinux) {
|
||||||
name = "aerc";
|
name = "aerc";
|
||||||
exec = "${lib.getExe config.nmasur.presets.services.i3.terminal} aerc %u";
|
exec = "${lib.getExe config.nmasur.presets.services.i3.terminal} -e aerc %u";
|
||||||
};
|
};
|
||||||
xsession.windowManager.i3.config.keybindings = lib.mkIf pkgs.stdenv.isLinux {
|
xsession.windowManager.i3.config.keybindings = lib.mkIf pkgs.stdenv.hostPlatform.isLinux {
|
||||||
"${config.xsession.windowManager.i3.config.modifier}+Shift+e" = "exec ${
|
"${config.xsession.windowManager.i3.config.modifier}+Shift+e" =
|
||||||
|
let
|
||||||
|
terminal = config.nmasur.presets.services.i3.terminal;
|
||||||
|
startupCommand =
|
||||||
|
if terminal == pkgs.wezterm then
|
||||||
|
"start --class com.noah.aerc -- aerc"
|
||||||
|
else
|
||||||
|
"--class=com.noah.aerc -e aerc";
|
||||||
|
in
|
||||||
|
"exec ${
|
||||||
# Don't name the script `aerc` or it will affect grep
|
# Don't name the script `aerc` or it will affect grep
|
||||||
builtins.toString (
|
builtins.toString (
|
||||||
pkgs.writeShellScript "focus-mail.sh" ''
|
pkgs.writeShellScript "focus-mail.sh" ''
|
||||||
count=$(ps aux | grep -c aerc)
|
count=$(ps aux | grep -c aerc)
|
||||||
if [ "$count" -eq 1 ]; then
|
if [ "$count" -eq 1 ]; then
|
||||||
i3-msg "exec --no-startup-id ${lib.getExe config.nmasur.presets.services.i3.terminal} start --class aerc -- aerc"
|
i3-msg "exec --no-startup-id ${lib.getExe terminal} ${startupCommand}"
|
||||||
sleep 0.25
|
sleep 0.25
|
||||||
fi
|
fi
|
||||||
i3-msg "[class=aerc] focus"
|
i3-msg "[class=com.noah.aerc] focus"
|
||||||
''
|
''
|
||||||
)
|
)
|
||||||
}";
|
}";
|
||||||
|
|||||||
@@ -15,6 +15,7 @@ in
|
|||||||
config = lib.mkIf cfg.enable {
|
config = lib.mkIf cfg.enable {
|
||||||
programs.atuin = {
|
programs.atuin = {
|
||||||
enable = true;
|
enable = true;
|
||||||
|
daemon.enable = true;
|
||||||
flags = [
|
flags = [
|
||||||
"--disable-up-arrow"
|
"--disable-up-arrow"
|
||||||
"--disable-ctrl-r"
|
"--disable-ctrl-r"
|
||||||
@@ -33,6 +34,7 @@ in
|
|||||||
secrets_filter = true;
|
secrets_filter = true;
|
||||||
enter_accept = false;
|
enter_accept = false;
|
||||||
keymap_mode = "vim-normal";
|
keymap_mode = "vim-normal";
|
||||||
|
records = true; # Sync v2
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,19 @@
|
|||||||
|
{ config, lib, ... }:
|
||||||
|
|
||||||
|
let
|
||||||
|
cfg = config.nmasur.presets.programs.aws-ssh;
|
||||||
|
in
|
||||||
|
|
||||||
|
{
|
||||||
|
options.nmasur.presets.programs.aws-ssh.enable = lib.mkEnableOption "AWS SSH tools";
|
||||||
|
|
||||||
|
config = lib.mkIf cfg.enable {
|
||||||
|
|
||||||
|
# Ignore wine directories in searches
|
||||||
|
home.file.".ssh/aws-ssm-ssh-proxy-command.sh" = {
|
||||||
|
text = builtins.readFile ./aws-ssm-ssh-proxy-command.sh;
|
||||||
|
executable = true;
|
||||||
|
};
|
||||||
|
|
||||||
|
};
|
||||||
|
}
|
||||||
+69
@@ -0,0 +1,69 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
set -eu
|
||||||
|
|
||||||
|
################################################################################
|
||||||
|
#
|
||||||
|
# For documentation see https://github.com/qoomon/aws-ssm-ssh-proxy-command
|
||||||
|
#
|
||||||
|
################################################################################
|
||||||
|
|
||||||
|
getInstanceId() {
|
||||||
|
local instance_name="$1"
|
||||||
|
local instance_id=$(aws ec2 describe-instances --filters "Name=tag:Name,Values=${instance_name}" --query "Reservations[].Instances[?State.Name == 'running'].InstanceId" --output text)
|
||||||
|
|
||||||
|
echo "${instance_id}"
|
||||||
|
}
|
||||||
|
|
||||||
|
instance_name="$1"
|
||||||
|
ssh_user="$2"
|
||||||
|
ssh_port="$3"
|
||||||
|
ssh_public_key_path="$4"
|
||||||
|
|
||||||
|
ec2InstanceIdPattern='^m?i-[0-9a-f]{8,17}$'
|
||||||
|
if [[ $instance_name =~ $ec2InstanceIdPattern ]]; then
|
||||||
|
instance_id=$instance_name
|
||||||
|
else
|
||||||
|
instance_id=$(getInstanceId "$instance_name")
|
||||||
|
|
||||||
|
if [[ -z $instance_id ]]; then
|
||||||
|
echo "Found no running instances with name \"${instance_name}\"."
|
||||||
|
exit 1
|
||||||
|
else
|
||||||
|
echo "Instance ID for \"${instance_name}\": \"${instance_id}\""
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
REGION_SEPARATOR='--'
|
||||||
|
if echo "$instance_id" | grep -q -e "${REGION_SEPARATOR}"; then
|
||||||
|
export AWS_REGION="${instance_id##*"${REGION_SEPARATOR}"}"
|
||||||
|
instance_id="${instance_id%%"$REGION_SEPARATOR"*}"
|
||||||
|
fi
|
||||||
|
|
||||||
|
>/dev/stderr echo "Add public key ${ssh_public_key_path} for ${ssh_user} at instance ${instance_id} for 10 seconds"
|
||||||
|
ssh_public_key="$(cat "${ssh_public_key_path}")"
|
||||||
|
aws ssm send-command \
|
||||||
|
--instance-ids "${instance_id}" \
|
||||||
|
--document-name 'AWS-RunShellScript' \
|
||||||
|
--comment "Add an SSH public key to authorized_keys for 10 seconds" \
|
||||||
|
--parameters commands="
|
||||||
|
\"
|
||||||
|
set -eu
|
||||||
|
|
||||||
|
mkdir -p ~${ssh_user}/.ssh && cd ~${ssh_user}/.ssh
|
||||||
|
|
||||||
|
authorized_key='${ssh_public_key} ssm-session'
|
||||||
|
|
||||||
|
echo \\\"\${authorized_key}\\\" >> authorized_keys
|
||||||
|
|
||||||
|
sleep 10
|
||||||
|
|
||||||
|
(grep -v -F \\\"\${authorized_key}\\\" authorized_keys || true) > authorized_keys~
|
||||||
|
mv authorized_keys~ authorized_keys
|
||||||
|
\"
|
||||||
|
"
|
||||||
|
|
||||||
|
>/dev/stderr echo "Start ssm session to instance ${instance_id}"
|
||||||
|
aws ssm start-session \
|
||||||
|
--target "${instance_id}" \
|
||||||
|
--document-name 'AWS-StartSSHSession' \
|
||||||
|
--parameters "portNumber=${ssh_port}"
|
||||||
@@ -32,7 +32,6 @@ in
|
|||||||
config = lib.mkIf cfg.enable {
|
config = lib.mkIf cfg.enable {
|
||||||
|
|
||||||
accounts.calendar.accounts.default = {
|
accounts.calendar.accounts.default = {
|
||||||
basePath = "other/calendars"; # Where to save calendars in ~ directory
|
|
||||||
name = "personal";
|
name = "personal";
|
||||||
local.type = "filesystem";
|
local.type = "filesystem";
|
||||||
primary = true;
|
primary = true;
|
||||||
|
|||||||
@@ -14,9 +14,14 @@ in
|
|||||||
options.nmasur.presets.programs.calibre.enable = lib.mkEnableOption "Calibre e-book manager";
|
options.nmasur.presets.programs.calibre.enable = lib.mkEnableOption "Calibre e-book manager";
|
||||||
|
|
||||||
config = lib.mkIf cfg.enable {
|
config = lib.mkIf cfg.enable {
|
||||||
home.packages = [ pkgs.calibre ];
|
home.packages = lib.mkIf pkgs.stdenv.hostPlatform.isLinux [ pkgs.calibre ];
|
||||||
home.sessionVariables = {
|
home.sessionVariables = {
|
||||||
CALIBRE_USE_DARK_PALETTE = 1;
|
CALIBRE_USE_DARK_PALETTE = 1;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
home.file.".Brewfile".text = lib.mkIf pkgs.stdenv.hostPlatform.isDarwin /* homebrew */ ''
|
||||||
|
cask "calibre" # Nix package broken on macOS
|
||||||
|
'';
|
||||||
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,15 +18,16 @@ in
|
|||||||
ca = "cargo";
|
ca = "cargo";
|
||||||
};
|
};
|
||||||
|
|
||||||
home.packages = with pkgs; [
|
home.packages = [
|
||||||
gcc
|
pkgs.gcc
|
||||||
rustc
|
pkgs.rustc
|
||||||
cargo
|
pkgs.cargo
|
||||||
cargo-watch
|
pkgs.stable.cargo-watch
|
||||||
clippy
|
pkgs.clippy
|
||||||
rustfmt
|
pkgs.rustfmt
|
||||||
pkg-config
|
pkgs.pkg-config
|
||||||
openssl
|
pkgs.openssl
|
||||||
|
pkgs.rust-analyzer
|
||||||
];
|
];
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,34 @@
|
|||||||
|
{
|
||||||
|
config,
|
||||||
|
pkgs,
|
||||||
|
lib,
|
||||||
|
...
|
||||||
|
}:
|
||||||
|
|
||||||
|
let
|
||||||
|
cfg = config.nmasur.presets.programs.chawan;
|
||||||
|
in
|
||||||
|
|
||||||
|
{
|
||||||
|
|
||||||
|
options.nmasur.presets.programs.chawan.enable = lib.mkEnableOption "chawan TUI web browser";
|
||||||
|
|
||||||
|
config = lib.mkIf cfg.enable {
|
||||||
|
|
||||||
|
programs.chawan = {
|
||||||
|
enable = true;
|
||||||
|
settings = {
|
||||||
|
external.copy-cmd = if pkgs.stdenv.hostPlatform.isLinux then "xclip -selection clipboard -in" else "pbcopy";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
# Set Chawan as the default app for manual pages
|
||||||
|
home.sessionVariables = {
|
||||||
|
MANPAGER = "${lib.getExe pkgs.chawan} -T text/x-ansi";
|
||||||
|
};
|
||||||
|
|
||||||
|
programs.fish.shellAbbrs.man = "mancha";
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
@@ -17,6 +17,9 @@ in
|
|||||||
programs.direnv = {
|
programs.direnv = {
|
||||||
enable = true;
|
enable = true;
|
||||||
nix-direnv.enable = true;
|
nix-direnv.enable = true;
|
||||||
|
config = {
|
||||||
|
global.hide_env_diff = true;
|
||||||
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -29,7 +29,7 @@ in
|
|||||||
config = lib.mkIf cfg.enable {
|
config = lib.mkIf cfg.enable {
|
||||||
|
|
||||||
# Always make the dotfiles directory considered safe for git and direnv
|
# Always make the dotfiles directory considered safe for git and direnv
|
||||||
programs.git.extraConfig.safe.directory = cfg.path;
|
programs.git.settings.safe.directory = cfg.path;
|
||||||
programs.direnv.config.whitelist.prefix = [ cfg.path ];
|
programs.direnv.config.whitelist.prefix = [ cfg.path ];
|
||||||
|
|
||||||
home.activation = {
|
home.activation = {
|
||||||
|
|||||||
@@ -0,0 +1,19 @@
|
|||||||
|
{
|
||||||
|
config,
|
||||||
|
pkgs,
|
||||||
|
lib,
|
||||||
|
...
|
||||||
|
}:
|
||||||
|
|
||||||
|
let
|
||||||
|
cfg = config.nmasur.presets.programs.feishin;
|
||||||
|
in
|
||||||
|
|
||||||
|
{
|
||||||
|
|
||||||
|
options.nmasur.presets.programs.feishin.enable = lib.mkEnableOption "Feishin music player";
|
||||||
|
|
||||||
|
config = lib.mkIf cfg.enable {
|
||||||
|
home.packages = [ pkgs.feishin ];
|
||||||
|
};
|
||||||
|
}
|
||||||
@@ -23,7 +23,9 @@ in
|
|||||||
|
|
||||||
programs.firefox = {
|
programs.firefox = {
|
||||||
enable = true;
|
enable = true;
|
||||||
package = if pkgs.stdenv.isDarwin then pkgs.firefox-unwrapped else pkgs.firefox;
|
package = pkgs.firefox;
|
||||||
|
# Use appropriate default path depending on the OS
|
||||||
|
configPath = if pkgs.stdenv.hostPlatform.isDarwin then "Library/Application Support/Firefox" else ".mozilla/firefox";
|
||||||
profiles.default = {
|
profiles.default = {
|
||||||
id = 0;
|
id = 0;
|
||||||
name = "default";
|
name = "default";
|
||||||
@@ -46,6 +48,8 @@ in
|
|||||||
ublacklist
|
ublacklist
|
||||||
vimium
|
vimium
|
||||||
wappalyzer # TODO: only for work profile
|
wappalyzer # TODO: only for work profile
|
||||||
|
# pkgs.nmasur.firefox-history-exporter
|
||||||
|
# copy-as-markdown
|
||||||
# saml-tracer
|
# saml-tracer
|
||||||
# text-fragment
|
# text-fragment
|
||||||
];
|
];
|
||||||
@@ -53,7 +57,7 @@ in
|
|||||||
"app.update.auto" = false;
|
"app.update.auto" = false;
|
||||||
"browser.aboutConfig.showWarning" = false;
|
"browser.aboutConfig.showWarning" = false;
|
||||||
"browser.warnOnQuit" = false;
|
"browser.warnOnQuit" = false;
|
||||||
"browser.quitShortcut.disabled" = if pkgs.stdenv.isLinux then true else false;
|
"browser.quitShortcut.disabled" = if pkgs.stdenv.hostPlatform.isLinux then true else false;
|
||||||
"browser.theme.dark-private-windows" = true;
|
"browser.theme.dark-private-windows" = true;
|
||||||
"browser.toolbars.bookmarks.visibility" = false;
|
"browser.toolbars.bookmarks.visibility" = false;
|
||||||
"browser.startup.page" = 3; # Restore previous session
|
"browser.startup.page" = 3; # Restore previous session
|
||||||
@@ -61,6 +65,7 @@ in
|
|||||||
"trailhead.firstrun.didSeeAboutWelcome" = true; # Disable welcome splash
|
"trailhead.firstrun.didSeeAboutWelcome" = true; # Disable welcome splash
|
||||||
"dom.forms.autocomplete.formautofill" = false; # Disable autofill
|
"dom.forms.autocomplete.formautofill" = false; # Disable autofill
|
||||||
"extensions.formautofill.creditCards.enabled" = false; # Disable credit cards
|
"extensions.formautofill.creditCards.enabled" = false; # Disable credit cards
|
||||||
|
"extensions.autoDisableScopes" = false; # Enable extensions automatically
|
||||||
"dom.payments.defaults.saveAddress" = false; # Disable address save
|
"dom.payments.defaults.saveAddress" = false; # Disable address save
|
||||||
"general.autoScroll" = true; # Drag middle-mouse to scroll
|
"general.autoScroll" = true; # Drag middle-mouse to scroll
|
||||||
"services.sync.prefs.sync.general.autoScroll" = false; # Prevent disabling autoscroll
|
"services.sync.prefs.sync.general.autoScroll" = false; # Prevent disabling autoscroll
|
||||||
@@ -74,6 +79,8 @@ in
|
|||||||
"svg.context-properties.content.enabled" = true; # Sidebery styling
|
"svg.context-properties.content.enabled" = true; # Sidebery styling
|
||||||
"browser.tabs.hoverPreview.enabled" = false; # Disable tab previews
|
"browser.tabs.hoverPreview.enabled" = false; # Disable tab previews
|
||||||
"browser.tabs.hoverPreview.showThumbnails" = false; # Disable tab previews
|
"browser.tabs.hoverPreview.showThumbnails" = false; # Disable tab previews
|
||||||
|
"browser.gesture.swipe.left" = "cmd_scrollLeft"; # Disable swipe to go back
|
||||||
|
"browser.gesture.swipe.right" = "cmd_scrollRight"; # Disable swipe to go forward
|
||||||
};
|
};
|
||||||
userChrome = ''
|
userChrome = ''
|
||||||
:root {
|
:root {
|
||||||
@@ -182,10 +189,10 @@ in
|
|||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
xsession.windowManager.i3.config.keybindings = lib.mkIf pkgs.stdenv.isLinux {
|
xsession.windowManager.i3.config.keybindings = lib.mkIf pkgs.stdenv.hostPlatform.isLinux {
|
||||||
"${config.xsession.windowManager.i3.config.modifier}+Shift+b" = "exec ${
|
"${config.xsession.windowManager.i3.config.modifier}+Shift+b" = "exec ${
|
||||||
# Don't name the script `firefox` or it will affect grep
|
# Don't name the script `firefox` or it will affect grep
|
||||||
builtins.toString (
|
toString (
|
||||||
pkgs.writeShellScript "focus-ff.sh" ''
|
pkgs.writeShellScript "focus-ff.sh" ''
|
||||||
count=$(ps aux | grep -c firefox)
|
count=$(ps aux | grep -c firefox)
|
||||||
if [ "$count" -eq 1 ]; then
|
if [ "$count" -eq 1 ]; then
|
||||||
|
|||||||
@@ -13,13 +13,35 @@ in
|
|||||||
|
|
||||||
options.nmasur.presets.programs.fish-darwin.enable = lib.mkEnableOption {
|
options.nmasur.presets.programs.fish-darwin.enable = lib.mkEnableOption {
|
||||||
description = "Fish macOS options";
|
description = "Fish macOS options";
|
||||||
default = config.nmasur.presets.programs.fish && pkgs.stdenv.isDarwin;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
config = lib.mkIf cfg.enable {
|
config = lib.mkIf cfg.enable {
|
||||||
programs.fish.shellAbbrs = {
|
# Default shell setting doesn't work
|
||||||
|
home.sessionVariables = {
|
||||||
|
SHELL = "${pkgs.fish}/bin/fish";
|
||||||
|
};
|
||||||
|
|
||||||
|
programs.fish = {
|
||||||
|
shellAbbrs = {
|
||||||
# Shortcut to edit hosts file
|
# Shortcut to edit hosts file
|
||||||
hosts = "sudo nvim /etc/hosts";
|
hosts = "sudo hx /etc/hosts";
|
||||||
|
};
|
||||||
|
shellInit = ''
|
||||||
|
set -g __nixos_path_original $PATH
|
||||||
|
function __nixos_path_fix -d "fix PATH value"
|
||||||
|
set -l result (string split ":" $__nixos_path_original)
|
||||||
|
for elt in $PATH
|
||||||
|
if not contains -- $elt $result
|
||||||
|
set -a result $elt
|
||||||
|
end
|
||||||
|
end
|
||||||
|
set -g PATH $result
|
||||||
|
end
|
||||||
|
__nixos_path_fix
|
||||||
|
'';
|
||||||
|
|
||||||
|
# # Speeds up fish launch time on macOS
|
||||||
|
# useBabelfish = true;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -114,10 +114,17 @@ in
|
|||||||
dr = "docker run --rm -it";
|
dr = "docker run --rm -it";
|
||||||
db = "docker build . -t";
|
db = "docker build . -t";
|
||||||
};
|
};
|
||||||
shellInit = "";
|
shellInit = ''
|
||||||
|
# Fix for lagging/hanging after exiting TUIs inside terminal multiplexers like Zellij:
|
||||||
|
# Disable fish terminal querying at startup so fish does not query DA1/termcap on return.
|
||||||
|
set -gx fish_features no-query-term
|
||||||
|
'';
|
||||||
};
|
};
|
||||||
|
|
||||||
home.sessionVariables.fish_greeting = "";
|
home.sessionVariables = {
|
||||||
|
fish_greeting = "";
|
||||||
|
fish_features = "no-query-term";
|
||||||
|
};
|
||||||
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,12 +14,16 @@ in
|
|||||||
options.nmasur.presets.programs.ghostty.enable = lib.mkEnableOption "Ghostty terminal";
|
options.nmasur.presets.programs.ghostty.enable = lib.mkEnableOption "Ghostty terminal";
|
||||||
|
|
||||||
config = lib.mkIf cfg.enable {
|
config = lib.mkIf cfg.enable {
|
||||||
|
|
||||||
|
# Set the i3 terminal
|
||||||
|
nmasur.presets.services.i3.terminal = config.programs.ghostty.package;
|
||||||
|
|
||||||
programs.ghostty = {
|
programs.ghostty = {
|
||||||
enable = true;
|
enable = true;
|
||||||
|
|
||||||
package = if pkgs.stdenv.isDarwin then pkgs.nur.repos.DimitarNestorov.ghostty else pkgs.ghostty;
|
package = if pkgs.stdenv.hostPlatform.isDarwin then pkgs.ghostty-bin else pkgs.ghostty;
|
||||||
|
|
||||||
enableFishIntegration = true;
|
enableFishIntegration = false; # Handled conditionally below to avoid conflicts inside Zellij/TMUX
|
||||||
enableBashIntegration = true;
|
enableBashIntegration = true;
|
||||||
enableZshIntegration = true;
|
enableZshIntegration = true;
|
||||||
installBatSyntax = false; # The file doesn't seem to exist in the pkg
|
installBatSyntax = false; # The file doesn't seem to exist in the pkg
|
||||||
@@ -29,13 +33,21 @@ in
|
|||||||
macos-titlebar-style = "hidden";
|
macos-titlebar-style = "hidden";
|
||||||
window-decoration = false;
|
window-decoration = false;
|
||||||
macos-non-native-fullscreen = true;
|
macos-non-native-fullscreen = true;
|
||||||
fullscreen = true;
|
quit-after-last-window-closed = lib.mkIf pkgs.stdenv.hostPlatform.isDarwin true;
|
||||||
|
fullscreen = if pkgs.stdenv.hostPlatform.isDarwin then true else false;
|
||||||
keybind = [
|
keybind = [
|
||||||
"super+t=unbind" # Pass super-t to underlying tool (e.g. zellij tabs)
|
# Translate Mac Super & Ctrl combinations into Alt (ESC prefix) sequences
|
||||||
"super+shift+]=unbind"
|
# so Zellij receives them without needing Kitty keyboard protocol
|
||||||
"super+shift+[=unbind"
|
"super+t=text:\\x1bt"
|
||||||
"ctrl+tab=unbind"
|
"super+shift+]=text:\\x1b}"
|
||||||
"ctrl+shift+tab=unbind"
|
"super+shift+[=text:\\x1b{"
|
||||||
|
"ctrl+tab=text:\\x1b}"
|
||||||
|
"ctrl+shift+tab=text:\\x1b{"
|
||||||
|
"super+k=text:\\x1bK"
|
||||||
|
"super+shift+e=text:\\x1bE"
|
||||||
|
# Send CSI-u sequence for Alt+Shift+P / Super+Shift+P to bypass Zellij 0.45's DCS (ESC P) parser timeout (~1.5s delay)
|
||||||
|
"alt+shift+p=text:\\x1b[112;4u"
|
||||||
|
"super+shift+p=text:\\x1b[112;4u"
|
||||||
];
|
];
|
||||||
};
|
};
|
||||||
themes."gruvbox" = {
|
themes."gruvbox" = {
|
||||||
@@ -72,5 +84,12 @@ in
|
|||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
# Conditionally enable Ghostty fish shell integration only when NOT running inside multiplexers like Zellij/TMUX
|
||||||
|
programs.fish.shellInit = ''
|
||||||
|
if set -q GHOSTTY_RESOURCES_DIR; and not set -q ZELLIJ; and not set -q TMUX
|
||||||
|
source "$GHOSTTY_RESOURCES_DIR/shell-integration/fish/vendor_conf.d/ghostty-shell-integration.fish"
|
||||||
|
end
|
||||||
|
'';
|
||||||
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
{
|
{
|
||||||
config,
|
config,
|
||||||
pkgs,
|
|
||||||
lib,
|
lib,
|
||||||
...
|
...
|
||||||
}:
|
}:
|
||||||
@@ -40,8 +39,19 @@ in
|
|||||||
config = lib.mkIf cfg.enable {
|
config = lib.mkIf cfg.enable {
|
||||||
|
|
||||||
programs.git = {
|
programs.git = {
|
||||||
userName = lib.mkForce cfg.work.name;
|
settings = {
|
||||||
userEmail = lib.mkForce cfg.work.email;
|
user = {
|
||||||
|
name = lib.mkForce cfg.work.name;
|
||||||
|
email = lib.mkForce cfg.work.email;
|
||||||
|
signingKey = "~/.ssh/work_github";
|
||||||
|
};
|
||||||
|
commit = {
|
||||||
|
gpgsign = true;
|
||||||
|
};
|
||||||
|
tag = {
|
||||||
|
gpgsign = true;
|
||||||
|
};
|
||||||
|
};
|
||||||
includes = [
|
includes = [
|
||||||
{
|
{
|
||||||
path = "${config.home.homeDirectory}/${config.xdg.configFile."git/personal".target}";
|
path = "${config.home.homeDirectory}/${config.xdg.configFile."git/personal".target}";
|
||||||
@@ -51,6 +61,11 @@ in
|
|||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
# Add work to signers file
|
||||||
|
xdg.configFile."git/allowed-signers".text = ''
|
||||||
|
${cfg.work.email} ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIIP7aXbmKHmWUZgwG5HPtwx+nREVeMIRplpAAzxPOFXL
|
||||||
|
'';
|
||||||
|
|
||||||
# Personal git config
|
# Personal git config
|
||||||
xdg.configFile."git/personal".text = lib.generators.toGitINI {
|
xdg.configFile."git/personal".text = lib.generators.toGitINI {
|
||||||
user = {
|
user = {
|
||||||
@@ -58,14 +73,20 @@ in
|
|||||||
email = cfg.personal.email;
|
email = cfg.personal.email;
|
||||||
signingkey = "~/.ssh/id_ed25519";
|
signingkey = "~/.ssh/id_ed25519";
|
||||||
};
|
};
|
||||||
commit = {
|
|
||||||
gpgsign = true;
|
|
||||||
};
|
|
||||||
tag = {
|
|
||||||
gpgsign = true;
|
|
||||||
};
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
# Personal jj config
|
||||||
|
programs.jujutsu.settings = {
|
||||||
|
"--scope" = [
|
||||||
|
{
|
||||||
|
"--when".repositories = [ "~/dev/personal" ];
|
||||||
|
user = {
|
||||||
|
name = cfg.personal.name;
|
||||||
|
email = cfg.personal.email;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
];
|
||||||
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -29,9 +29,11 @@ in
|
|||||||
|
|
||||||
programs.git = {
|
programs.git = {
|
||||||
enable = true;
|
enable = true;
|
||||||
userName = cfg.name;
|
settings = {
|
||||||
userEmail = cfg.email;
|
user = {
|
||||||
extraConfig = {
|
name = cfg.name;
|
||||||
|
email = cfg.email;
|
||||||
|
};
|
||||||
core.pager = "${pkgs.git}/share/git/contrib/diff-highlight/diff-highlight | less --no-init";
|
core.pager = "${pkgs.git}/share/git/contrib/diff-highlight/diff-highlight | less --no-init";
|
||||||
interactive.difffilter = "${pkgs.git}/share/git/contrib/diff-highlight/diff-highlight";
|
interactive.difffilter = "${pkgs.git}/share/git/contrib/diff-highlight/diff-highlight";
|
||||||
pager = {
|
pager = {
|
||||||
@@ -63,7 +65,7 @@ in
|
|||||||
};
|
};
|
||||||
|
|
||||||
xdg.configFile."git/allowed-signers".text = ''
|
xdg.configFile."git/allowed-signers".text = ''
|
||||||
7386960+nmasur@users.noreply.github.com ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIB+AbmjGEwITk5CK9y7+Rg27Fokgj9QEjgc9wST6MA3s
|
${config.nmasur.presets.programs.git.email} ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIB+AbmjGEwITk5CK9y7+Rg27Fokgj9QEjgc9wST6MA3s
|
||||||
'';
|
'';
|
||||||
|
|
||||||
programs.fish.shellAbbrs = {
|
programs.fish.shellAbbrs = {
|
||||||
|
|||||||
@@ -22,7 +22,6 @@ in
|
|||||||
extensions = [
|
extensions = [
|
||||||
pkgs.nmasur.gh-collaborators
|
pkgs.nmasur.gh-collaborators
|
||||||
pkgs.gh-dash
|
pkgs.gh-dash
|
||||||
pkgs.gh-copilot
|
|
||||||
];
|
];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -7,6 +7,62 @@
|
|||||||
|
|
||||||
let
|
let
|
||||||
cfg = config.nmasur.presets.programs.helix;
|
cfg = config.nmasur.presets.programs.helix;
|
||||||
|
|
||||||
|
blame_file_pretty = pkgs.writeShellScriptBin "blame_file_pretty" ''
|
||||||
|
# Source: https://gist.github.com/gloaysa/828707f067e3bb20da18d72fa5d4963a
|
||||||
|
# Utility for Helix: open the patch for the commit that last touched the current line.
|
||||||
|
# If the line isn’t committed yet, it shows the working-tree diff for THIS file only.
|
||||||
|
# The script writes the diff to /tmp and prints the absolute path to stdout
|
||||||
|
# Adjust `context` to see more/fewer unchanged lines around the change (default: 3).
|
||||||
|
#
|
||||||
|
# usage: git-file_pretty.sh <file> <line> [context_lines]
|
||||||
|
# Helix mapping example:
|
||||||
|
# B = ':open %sh{ ~/.config/helix/utils/git-blame-commit.sh "%{buffer_name}" %{cursor_line} 3 }'
|
||||||
|
file="$1"
|
||||||
|
line="$2"
|
||||||
|
ctx="''${3:-3}"
|
||||||
|
|
||||||
|
# blame the exact line
|
||||||
|
porc="$(git blame -L "$line",+1 --porcelain -- "$file")" || exit 1
|
||||||
|
sha="$(printf '%s\n' "$porc" | awk 'NR==1{print $1}')"
|
||||||
|
commit_path="$(printf '%s\n' "$porc" | awk '/^filename /{print substr($0,10); exit}')"
|
||||||
|
|
||||||
|
out="/tmp/hx-blame_$(basename "$file")_''${sha:-wt}.diff"
|
||||||
|
|
||||||
|
if [ -z "$sha" ] || [ "$sha" = 0000000000000000000000000000000000000000 ] || [ "$sha" = "^" ]; then
|
||||||
|
# uncommitted line → working tree diff for this file
|
||||||
|
git --no-pager diff --no-color -U"$ctx" -- "$file" > "$out"
|
||||||
|
else
|
||||||
|
# committed line → only this file’s patch in that commit
|
||||||
|
git --no-pager show --no-color -M -C -U"$ctx" "$sha" -- "''${commit_path:-$file}" > "$out"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# "return" the path for :open %sh{…}
|
||||||
|
printf '%s' "$out"
|
||||||
|
'';
|
||||||
|
|
||||||
|
blame_line_pretty = pkgs.writeShellScriptBin "blame_line_pretty" ''
|
||||||
|
# Source: https://gist.github.com/gloaysa/828707f067e3bb20da18d72fa5d4963a
|
||||||
|
# Utility for Helix: pretty-print blame info for the line under the cursor.
|
||||||
|
# Quite basic.
|
||||||
|
#
|
||||||
|
# usage: blame_line_pretty <file> <line>
|
||||||
|
# Helix mapping example:
|
||||||
|
# b = ":run-shell-command ~/.config/helix/utils/blame_line_pretty.sh %{buffer_name} %{cursor_line}"
|
||||||
|
file="$1"; line="$2"
|
||||||
|
out="$(git blame -L "$line",+1 --porcelain -- "$file")" || return 1
|
||||||
|
|
||||||
|
sha="$(printf '%s\n' "$out" | awk 'NR==1{print $1}')"
|
||||||
|
author="$(printf '%s\n' "$out" | awk -F'author ' '/^author /{print $2; exit}')"
|
||||||
|
epoch="$(printf '%s\n' "$out" | awk '/^author-time /{print $2; exit}')"
|
||||||
|
# dd-mm-yyyy (macOS `date -r`; fallback to gdate if present)
|
||||||
|
date="$( (date -r "$epoch" +%d-%m-%Y\ %H:%M 2>/dev/null) || (gdate -d "@$epoch" +%d-%m-%Y\ %H:%M 2>/dev/null) || printf '%s' "$epoch")"
|
||||||
|
summary="$(printf '%s\n' "$out" | awk -F'summary ' '/^summary /{print $2; exit}')"
|
||||||
|
change="$(printf '%s\n' "$out" | tail -n 1)"
|
||||||
|
|
||||||
|
printf "%s\n%s\n%s\n%s\n%s\n" "$sha" "$author" "$date" "$summary" "$change"
|
||||||
|
'';
|
||||||
|
|
||||||
in
|
in
|
||||||
|
|
||||||
{
|
{
|
||||||
@@ -16,12 +72,15 @@ in
|
|||||||
config = lib.mkIf cfg.enable {
|
config = lib.mkIf cfg.enable {
|
||||||
|
|
||||||
# Use Neovim as the editor for git commit messages
|
# Use Neovim as the editor for git commit messages
|
||||||
programs.git.extraConfig.core.editor = lib.mkForce "${lib.getExe pkgs.helix}";
|
programs.git.settings.core.editor = lib.mkForce "${lib.getExe pkgs.helix}";
|
||||||
programs.jujutsu.settings.ui.editor = lib.mkForce "${lib.getExe pkgs.helix}";
|
programs.jujutsu.settings.ui.editor = lib.mkForce "${lib.getExe pkgs.helix}";
|
||||||
|
|
||||||
# Set Neovim as the default app for text editing and manual pages
|
# Set Neovim as the default app for text editing and manual pages
|
||||||
home.sessionVariables = {
|
home.sessionVariables = {
|
||||||
EDITOR = lib.mkForce "${lib.getExe pkgs.helix}";
|
EDITOR = lib.mkForce "${lib.getExe pkgs.helix}";
|
||||||
|
# MANPAGER = lib.mkForce "sh -c 'col -bx | ${lib.getExe pkgs.helix}'";
|
||||||
|
MANWIDTH = 87;
|
||||||
|
MANROFFOPT = "-c";
|
||||||
};
|
};
|
||||||
|
|
||||||
# Create quick aliases for launching Helix
|
# Create quick aliases for launching Helix
|
||||||
@@ -43,6 +102,10 @@ in
|
|||||||
command = "${pkgs.nixd}/bin/nixd";
|
command = "${pkgs.nixd}/bin/nixd";
|
||||||
};
|
};
|
||||||
|
|
||||||
|
language-server.ty = {
|
||||||
|
command = "${pkgs.ty}/bin/ty";
|
||||||
|
};
|
||||||
|
|
||||||
language-server.fish-lsp = {
|
language-server.fish-lsp = {
|
||||||
command = "${pkgs.fish-lsp}/bin/fish-lsp";
|
command = "${pkgs.fish-lsp}/bin/fish-lsp";
|
||||||
};
|
};
|
||||||
@@ -55,8 +118,14 @@ in
|
|||||||
command = lib.getExe pkgs.marksman;
|
command = lib.getExe pkgs.marksman;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
language-server.rumdl = {
|
||||||
|
command = lib.getExe pkgs.rumdl;
|
||||||
|
args = [ "server" ];
|
||||||
|
};
|
||||||
|
|
||||||
language-server.terraform-ls = {
|
language-server.terraform-ls = {
|
||||||
command = "${lib.getExe pkgs.terraform-ls} serve";
|
command = "${lib.getExe pkgs.terraform-ls}";
|
||||||
|
args = [ "serve" ];
|
||||||
};
|
};
|
||||||
|
|
||||||
language-server.bash-language-server = {
|
language-server.bash-language-server = {
|
||||||
@@ -78,17 +147,40 @@ in
|
|||||||
}
|
}
|
||||||
{
|
{
|
||||||
name = "markdown";
|
name = "markdown";
|
||||||
auto-format = true;
|
auto-format = false;
|
||||||
language-servers = [ "marksman" ];
|
language-servers = [
|
||||||
|
"marksman"
|
||||||
|
"rumdl"
|
||||||
|
];
|
||||||
formatter = {
|
formatter = {
|
||||||
command = lib.getExe pkgs.mdformat;
|
command = lib.getExe pkgs.rumdl;
|
||||||
args = [ "-" ];
|
args = [
|
||||||
|
"fmt"
|
||||||
|
"-"
|
||||||
|
];
|
||||||
};
|
};
|
||||||
|
# Allows return key to continue the token on the next line
|
||||||
|
comment-tokens = [
|
||||||
|
"-"
|
||||||
|
"+"
|
||||||
|
"*"
|
||||||
|
"- [ ]"
|
||||||
|
">"
|
||||||
|
];
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
name = "tfvars";
|
name = "hcl";
|
||||||
|
scope = "source.hcl";
|
||||||
|
# injection-regex = "terraform";
|
||||||
auto-format = true;
|
auto-format = true;
|
||||||
language-servers = [ "terraform-ls" ];
|
language-servers = [ "terraform-ls" ];
|
||||||
|
language-id = "terraform";
|
||||||
|
file-types = [
|
||||||
|
"tf"
|
||||||
|
"tfvars"
|
||||||
|
"terraform"
|
||||||
|
{ glob = "*.auto.tfvars"; }
|
||||||
|
];
|
||||||
formatter = {
|
formatter = {
|
||||||
command = lib.getExe pkgs.terraform;
|
command = lib.getExe pkgs.terraform;
|
||||||
args = [
|
args = [
|
||||||
@@ -98,11 +190,15 @@ in
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
name = "hcl";
|
name = "hcl-packer";
|
||||||
|
scope = "source.hcl-packer";
|
||||||
auto-format = true;
|
auto-format = true;
|
||||||
language-servers = [ "terraform-ls" ];
|
file-types = [
|
||||||
|
"hcl"
|
||||||
|
"pkr.hcl"
|
||||||
|
];
|
||||||
formatter = {
|
formatter = {
|
||||||
command = lib.getExe pkgs.terraform;
|
command = "${pkgs.packer}/bin/packer";
|
||||||
args = [
|
args = [
|
||||||
"fmt"
|
"fmt"
|
||||||
"-"
|
"-"
|
||||||
@@ -117,13 +213,56 @@ in
|
|||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
ignores = [
|
||||||
|
"content/.obsidian/**"
|
||||||
|
".direnv/**"
|
||||||
|
];
|
||||||
|
|
||||||
settings = {
|
settings = {
|
||||||
theme = "base16";
|
theme = "base16";
|
||||||
|
|
||||||
keys.normal = {
|
keys.normal = {
|
||||||
|
|
||||||
|
# Use the enter key to save the file
|
||||||
|
ret = ":write";
|
||||||
|
|
||||||
|
# Get out of multiple cursors and selection
|
||||||
|
esc = [
|
||||||
|
"collapse_selection"
|
||||||
|
"keep_primary_selection"
|
||||||
|
];
|
||||||
|
|
||||||
|
# Quit shortcuts
|
||||||
|
space.q = ":quit-all";
|
||||||
|
space.x = ":quit-all!";
|
||||||
|
|
||||||
# Enable and disable inlay hints
|
# Enable and disable inlay hints
|
||||||
space.H = ":toggle lsp.display-inlay-hints";
|
space.H = ":toggle lsp.display-inlay-hints";
|
||||||
|
|
||||||
|
# Toggle floating pane
|
||||||
|
space.t = ":sh zellij action toggle-floating-panes";
|
||||||
|
|
||||||
|
# Today's note
|
||||||
|
space.n = ":vsplit %sh{fish -c 'generate-today'}";
|
||||||
|
|
||||||
|
# Open lazygit
|
||||||
|
# Unfortunately, this breaks mouse input and the terminal after quitting Helix
|
||||||
|
space.l = [
|
||||||
|
":write-all"
|
||||||
|
":new"
|
||||||
|
":insert-output ${lib.getExe pkgs.lazygit} > /dev/tty"
|
||||||
|
":buffer-close!"
|
||||||
|
":redraw"
|
||||||
|
":reload-all"
|
||||||
|
":set mouse false"
|
||||||
|
":set mouse true"
|
||||||
|
];
|
||||||
|
|
||||||
|
# Commandline git blame
|
||||||
|
# space.B = ":echo %sh{git log -n1 --date=short --pretty=format:'%%h %%ad %%s' $(git blame -L %{cursor_line},+1 \"%{buffer_name}\" | cut -d' ' -f1)}";
|
||||||
|
space.B = '':open %sh{ ${blame_line_pretty}/bin/blame_line_pretty "%{buffer_name}" %{cursor_line} 3 }'';
|
||||||
|
space.i = '':open %sh{ ${blame_file_pretty}/bin/blame_file_pretty "%{buffer_name}" %{cursor_line} 3 }'';
|
||||||
|
|
||||||
# Extend selection above
|
# Extend selection above
|
||||||
X = "select_line_above";
|
X = "select_line_above";
|
||||||
|
|
||||||
@@ -140,19 +279,27 @@ in
|
|||||||
"paste_before"
|
"paste_before"
|
||||||
];
|
];
|
||||||
|
|
||||||
# Copy lines up or down
|
A-S-ret = [
|
||||||
A-J = [
|
"open_above"
|
||||||
"extend_to_line_bounds"
|
"normal_mode"
|
||||||
"yank"
|
];
|
||||||
"paste_after"
|
A-ret = [
|
||||||
|
"open_below"
|
||||||
|
"normal_mode"
|
||||||
];
|
];
|
||||||
|
|
||||||
A-K = [
|
};
|
||||||
"extend_to_line_bounds"
|
|
||||||
"yank"
|
|
||||||
"paste_before"
|
|
||||||
];
|
|
||||||
|
|
||||||
|
keys.insert = {
|
||||||
|
# Allows not continuing the comment
|
||||||
|
"A-ret" = [
|
||||||
|
"insert_newline"
|
||||||
|
"extend_to_line_bounds"
|
||||||
|
"delete_selection"
|
||||||
|
"insert_newline"
|
||||||
|
"move_line_up"
|
||||||
|
"insert_mode"
|
||||||
|
];
|
||||||
};
|
};
|
||||||
|
|
||||||
editor = {
|
editor = {
|
||||||
@@ -174,12 +321,16 @@ in
|
|||||||
|
|
||||||
# Show hidden files
|
# Show hidden files
|
||||||
file-picker = {
|
file-picker = {
|
||||||
hidden = false;
|
hidden = false; # Show hidden files
|
||||||
git-ignore = true;
|
git-ignore = true; # Skip gitignore files
|
||||||
git-global = true;
|
git-global = true; # Skip global gitignore files
|
||||||
git-exclude = true;
|
git-exclude = true; # Skip excluded files
|
||||||
};
|
};
|
||||||
|
|
||||||
|
completion-replace = true; # Replace whole word with completion
|
||||||
|
trim-trailing-whitespace = true;
|
||||||
|
# rainbow-brackets = true; # Make it easier to match parentheses
|
||||||
|
|
||||||
# Show whitespace visible to the user
|
# Show whitespace visible to the user
|
||||||
# Waiting for trailing whitespace option ideally
|
# Waiting for trailing whitespace option ideally
|
||||||
whitespace = {
|
whitespace = {
|
||||||
@@ -193,9 +344,10 @@ in
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
themes."${config.programs.helix.settings.theme}" = {
|
themes.base16 = {
|
||||||
"attributes" = config.theme.colors.base09;
|
"attributes" = config.theme.colors.base09;
|
||||||
"comment" = {
|
"comment" = {
|
||||||
fg = config.theme.colors.base03;
|
fg = config.theme.colors.base03;
|
||||||
@@ -279,7 +431,7 @@ in
|
|||||||
bg = config.theme.colors.base00;
|
bg = config.theme.colors.base00;
|
||||||
};
|
};
|
||||||
"ui.cursor" = {
|
"ui.cursor" = {
|
||||||
fg = config.theme.colors.base0A;
|
fg = config.theme.colors.base04;
|
||||||
modifiers = [ "reversed" ];
|
modifiers = [ "reversed" ];
|
||||||
};
|
};
|
||||||
"ui.cursor.insert" = {
|
"ui.cursor.insert" = {
|
||||||
@@ -291,11 +443,202 @@ in
|
|||||||
bg = config.theme.colors.base01;
|
bg = config.theme.colors.base01;
|
||||||
};
|
};
|
||||||
"ui.cursor.match" = {
|
"ui.cursor.match" = {
|
||||||
fg = config.theme.colors.base0A;
|
fg = config.theme.colors.base03;
|
||||||
modifiers = [ "reversed" ];
|
modifiers = [ "reversed" ];
|
||||||
};
|
};
|
||||||
"ui.cursor.select" = {
|
"ui.cursor.select" = {
|
||||||
|
fg = config.theme.colors.base04;
|
||||||
|
modifiers = [ "reversed" ];
|
||||||
|
};
|
||||||
|
"ui.gutter" = {
|
||||||
|
bg = config.theme.colors.base00;
|
||||||
|
};
|
||||||
|
"ui.help" = {
|
||||||
|
fg = config.theme.colors.base06;
|
||||||
|
bg = config.theme.colors.base01;
|
||||||
|
};
|
||||||
|
"ui.linenr" = {
|
||||||
|
fg = config.theme.colors.base03;
|
||||||
|
bg = config.theme.colors.base00;
|
||||||
|
};
|
||||||
|
"ui.linenr.selected" = {
|
||||||
|
fg = config.theme.colors.base04;
|
||||||
|
bg = config.theme.colors.base01;
|
||||||
|
modifiers = [ "bold" ];
|
||||||
|
};
|
||||||
|
"ui.menu" = {
|
||||||
|
fg = config.theme.colors.base05;
|
||||||
|
bg = config.theme.colors.base01;
|
||||||
|
};
|
||||||
|
"ui.menu.scroll" = {
|
||||||
|
fg = config.theme.colors.base03;
|
||||||
|
bg = config.theme.colors.base01;
|
||||||
|
};
|
||||||
|
"ui.menu.selected" = {
|
||||||
|
fg = config.theme.colors.base01;
|
||||||
|
bg = config.theme.colors.base04;
|
||||||
|
};
|
||||||
|
"ui.popup" = {
|
||||||
|
bg = config.theme.colors.base01;
|
||||||
|
};
|
||||||
|
"ui.selection" = {
|
||||||
|
bg = config.theme.colors.base01;
|
||||||
|
};
|
||||||
|
"ui.selection.primary" = {
|
||||||
|
bg = config.theme.colors.base02;
|
||||||
|
};
|
||||||
|
"ui.statusline" = {
|
||||||
|
fg = config.theme.colors.base04;
|
||||||
|
bg = config.theme.colors.base01;
|
||||||
|
};
|
||||||
|
"ui.statusline.inactive" = {
|
||||||
|
bg = config.theme.colors.base01;
|
||||||
|
fg = config.theme.colors.base03;
|
||||||
|
};
|
||||||
|
"ui.statusline.insert" = {
|
||||||
|
fg = config.theme.colors.base00;
|
||||||
|
bg = config.theme.colors.base0B;
|
||||||
|
};
|
||||||
|
"ui.statusline.normal" = {
|
||||||
|
fg = config.theme.colors.base00;
|
||||||
|
bg = config.theme.colors.base03;
|
||||||
|
};
|
||||||
|
"ui.statusline.select" = {
|
||||||
|
fg = config.theme.colors.base00;
|
||||||
|
bg = config.theme.colors.base0F;
|
||||||
|
};
|
||||||
|
"ui.text" = config.theme.colors.base05;
|
||||||
|
"ui.text.focus" = config.theme.colors.base05;
|
||||||
|
"ui.virtual.indent-guide" = {
|
||||||
|
fg = config.theme.colors.base03;
|
||||||
|
};
|
||||||
|
"ui.virtual.inlay-hint" = {
|
||||||
|
fg = config.theme.colors.base03;
|
||||||
|
};
|
||||||
|
"ui.virtual.ruler" = {
|
||||||
|
bg = config.theme.colors.base01;
|
||||||
|
};
|
||||||
|
"ui.virtual.jump-label" = {
|
||||||
fg = config.theme.colors.base0A;
|
fg = config.theme.colors.base0A;
|
||||||
|
modifiers = [ "bold" ];
|
||||||
|
};
|
||||||
|
"ui.window" = {
|
||||||
|
bg = config.theme.colors.base01;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
themes.alabaster-style = {
|
||||||
|
"attribute" = config.theme.colors.base05;
|
||||||
|
"comment" = {
|
||||||
|
fg = config.theme.colors.base0A;
|
||||||
|
# modifiers = [ "italic" ];
|
||||||
|
};
|
||||||
|
"constant" = config.theme.colors.base0E;
|
||||||
|
"constant.numeric" = config.theme.colors.base0E;
|
||||||
|
"constant.builtin" = config.theme.colors.base0E;
|
||||||
|
"constant.character" = config.theme.colors.base0E;
|
||||||
|
"constant.character.escape" = config.theme.colors.base0C;
|
||||||
|
"constructor" = config.theme.colors.base0D;
|
||||||
|
"debug" = config.theme.colors.base03;
|
||||||
|
"diagnostic" = {
|
||||||
|
modifiers = [ "underlined" ];
|
||||||
|
};
|
||||||
|
"diff.delta" = config.theme.colors.base09;
|
||||||
|
"diff.minus" = config.theme.colors.base08;
|
||||||
|
"diff.plus" = config.theme.colors.base0B;
|
||||||
|
"error" = config.theme.colors.base08;
|
||||||
|
"function" = config.theme.colors.base0D;
|
||||||
|
"hint" = config.theme.colors.base03;
|
||||||
|
"info" = config.theme.colors.base0D;
|
||||||
|
"keyword" = config.theme.colors.base05;
|
||||||
|
"keyword.control" = config.theme.colors.base05;
|
||||||
|
"keyword.operator" = config.theme.colors.base05;
|
||||||
|
"label" = config.theme.colors.base0E;
|
||||||
|
"namespace" = config.theme.colors.base0E;
|
||||||
|
"operator" = config.theme.colors.base05;
|
||||||
|
"punctuation" = config.theme.colors.base04;
|
||||||
|
"punctuation.bracket" = config.theme.colors.base04;
|
||||||
|
"punctuation.delimiter" = config.theme.colors.base04;
|
||||||
|
"special" = config.theme.colors.base0D;
|
||||||
|
"string" = config.theme.colors.base0B;
|
||||||
|
"string.regexp" = config.theme.colors.base0B;
|
||||||
|
"string.special" = config.theme.colors.base0C;
|
||||||
|
"type" = config.theme.colors.base0A;
|
||||||
|
"variable" = config.theme.colors.base05;
|
||||||
|
"variable.parameter" = config.theme.colors.base05;
|
||||||
|
"variable.builtin" = config.theme.colors.base05;
|
||||||
|
"variable.other.member" = config.theme.colors.base05;
|
||||||
|
"warning" = config.theme.colors.base09;
|
||||||
|
"markup.bold" = {
|
||||||
|
fg = config.theme.colors.base0A;
|
||||||
|
modifiers = [ "bold" ];
|
||||||
|
};
|
||||||
|
"markup.heading" = config.theme.colors.base0D;
|
||||||
|
"markup.italic" = {
|
||||||
|
fg = config.theme.colors.base0E;
|
||||||
|
modifiers = [ "italic" ];
|
||||||
|
};
|
||||||
|
"markup.link.text" = config.theme.colors.base08;
|
||||||
|
"markup.link.url" = {
|
||||||
|
fg = config.theme.colors.base09;
|
||||||
|
modifiers = [ "underlined" ];
|
||||||
|
};
|
||||||
|
"markup.list" = config.theme.colors.base08;
|
||||||
|
"markup.quote" = config.theme.colors.base0C;
|
||||||
|
"markup.raw" = config.theme.colors.base0B;
|
||||||
|
"markup.strikethrough" = {
|
||||||
|
modifiers = [ "crossed_out" ];
|
||||||
|
};
|
||||||
|
"diagnostic.hint" = {
|
||||||
|
underline = {
|
||||||
|
style = "curl";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
"diagnostic.info" = {
|
||||||
|
underline = {
|
||||||
|
style = "curl";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
"diagnostic.warning" = {
|
||||||
|
underline = {
|
||||||
|
style = "curl";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
"diagnostic.error" = {
|
||||||
|
underline = {
|
||||||
|
style = "curl";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
"ui.background" = {
|
||||||
|
bg = config.theme.colors.base00;
|
||||||
|
};
|
||||||
|
"ui.bufferline.active" = {
|
||||||
|
fg = config.theme.colors.base00;
|
||||||
|
bg = config.theme.colors.base03;
|
||||||
|
modifiers = [ "bold" ];
|
||||||
|
};
|
||||||
|
"ui.bufferline" = {
|
||||||
|
fg = config.theme.colors.base04;
|
||||||
|
bg = config.theme.colors.base00;
|
||||||
|
};
|
||||||
|
"ui.cursor" = {
|
||||||
|
fg = config.theme.colors.base04;
|
||||||
|
modifiers = [ "reversed" ];
|
||||||
|
};
|
||||||
|
"ui.cursor.insert" = {
|
||||||
|
fg = config.theme.colors.base0A;
|
||||||
|
modifiers = [ "reversed" ];
|
||||||
|
};
|
||||||
|
"ui.cursorline.primary" = {
|
||||||
|
fg = config.theme.colors.base05;
|
||||||
|
bg = config.theme.colors.base01;
|
||||||
|
};
|
||||||
|
"ui.cursor.match" = {
|
||||||
|
fg = config.theme.colors.base03;
|
||||||
|
modifiers = [ "reversed" ];
|
||||||
|
};
|
||||||
|
"ui.cursor.select" = {
|
||||||
|
fg = config.theme.colors.base04;
|
||||||
modifiers = [ "reversed" ];
|
modifiers = [ "reversed" ];
|
||||||
};
|
};
|
||||||
"ui.gutter" = {
|
"ui.gutter" = {
|
||||||
@@ -377,6 +720,27 @@ in
|
|||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
# Create a desktop option for launching Helix from a file manager
|
||||||
|
# (Requires launching the terminal and then executing Helix)
|
||||||
|
xdg.desktopEntries.helix =
|
||||||
|
lib.mkIf (pkgs.stdenv.hostPlatform.isLinux && config.nmasur.presets.services.i3.enable)
|
||||||
|
{
|
||||||
|
name = "Helix wrapper";
|
||||||
|
exec = ''sh -c "${lib.getExe config.nmasur.presets.services.i3.terminal} --command='hx \$1'" _ %F ''; # TODO: change to work for any terminal
|
||||||
|
mimeType = [
|
||||||
|
"text/plain"
|
||||||
|
"text/markdown"
|
||||||
|
];
|
||||||
|
};
|
||||||
|
xdg.mimeApps.defaultApplications = {
|
||||||
|
"text/plain" = lib.mkBefore [ "Helix.desktop" ];
|
||||||
|
"text/markdown" = lib.mkBefore [ "Helix.desktop" ];
|
||||||
|
};
|
||||||
|
|
||||||
|
home.packages = [
|
||||||
|
(pkgs.writers.writeDashBin "xterm" ''${lib.getExe config.nmasur.presets.services.i3.terminal} +new-window --command"$@" '')
|
||||||
|
];
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,83 @@
|
|||||||
|
{
|
||||||
|
config,
|
||||||
|
lib,
|
||||||
|
...
|
||||||
|
}:
|
||||||
|
|
||||||
|
let
|
||||||
|
cfg = config.nmasur.presets.programs.homebrew;
|
||||||
|
in
|
||||||
|
|
||||||
|
{
|
||||||
|
|
||||||
|
options.nmasur.presets.programs.homebrew.enable =
|
||||||
|
lib.mkEnableOption "Homebrew macOS package manager";
|
||||||
|
|
||||||
|
config = lib.mkIf cfg.enable {
|
||||||
|
|
||||||
|
home.file.".Brewfile".text = /* homebrew */ ''
|
||||||
|
# Taps
|
||||||
|
# tap "homebrew/bundle"
|
||||||
|
|
||||||
|
# Brews (CLI Apps)
|
||||||
|
brew "trash" # Delete files and folders to trash instead of rm
|
||||||
|
|
||||||
|
# Casks (GUI Apps)
|
||||||
|
cask "scroll-reverser" # Different scroll style for mouse vs. trackpad
|
||||||
|
cask "notunes" # Don't launch Apple Music with the play button
|
||||||
|
cask "topnotch" # Darkens the menu bar to complete black
|
||||||
|
cask "ghostty" # Terminal application (not buildable on Nix on macOS)
|
||||||
|
cask "discord" # nixpkgs bundle breaks its notarization seal on macOS 26+
|
||||||
|
|
||||||
|
# Mac App Store apps (requires 'mas' CLI, optional)
|
||||||
|
# mas "Tailscale", id: 1475387142
|
||||||
|
'';
|
||||||
|
|
||||||
|
# Add homebrew paths to CLI path
|
||||||
|
home.sessionPath = [
|
||||||
|
"/opt/homebrew/bin/"
|
||||||
|
"/opt/homebrew/opt/trash/bin"
|
||||||
|
];
|
||||||
|
|
||||||
|
programs.fish.shellAbbrs.t = "trash";
|
||||||
|
|
||||||
|
home.activation.backendBrewBundle = /* bash */ ''
|
||||||
|
# Requires Homebrew to be installed
|
||||||
|
if ! /usr/bin/xcode-select --version 2>/dev/null; then
|
||||||
|
$DRY_RUN_CMD /usr/bin/xcode-select --install
|
||||||
|
fi
|
||||||
|
if ! /opt/homebrew/bin/brew --version 2>/dev/null; then
|
||||||
|
$DRY_RUN_CMD /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
|
||||||
|
fi
|
||||||
|
|
||||||
|
verboseEcho "Syncing Homebrew dependencies via Brewfile..."
|
||||||
|
|
||||||
|
# Ensure Homebrew is in the PATH for the script (Apple Silicon path)
|
||||||
|
export PATH="/opt/homebrew/bin:/usr/local/bin:$PATH"
|
||||||
|
|
||||||
|
# Keep activation deterministic and non-interactive. Without this, brew
|
||||||
|
# auto-updates (git-fetches its taps) which can hang forever when there
|
||||||
|
# is no TTY (network stall, credential prompt, or a leftover brew lock).
|
||||||
|
export HOMEBREW_NO_AUTO_UPDATE=1
|
||||||
|
export HOMEBREW_NO_ENV_HINTS=1
|
||||||
|
|
||||||
|
# Point brew at the generated Brewfile in the Nix store directly. This
|
||||||
|
# avoids depending on the ~/.Brewfile symlink being linked first, and
|
||||||
|
# sidesteps the --global vs. inherited HOMEBREW_BUNDLE_FILE conflict.
|
||||||
|
unset HOMEBREW_BUNDLE_FILE
|
||||||
|
brewfile="${config.home.file.".Brewfile".source}"
|
||||||
|
|
||||||
|
if command -v brew &> /dev/null; then
|
||||||
|
# Install/upgrade everything declared in the Brewfile...
|
||||||
|
$DRY_RUN_CMD brew bundle install --file="$brewfile"
|
||||||
|
# ...then uninstall anything NOT listed (replaces deprecated --cleanup).
|
||||||
|
$DRY_RUN_CMD brew bundle cleanup --file="$brewfile" --force
|
||||||
|
else
|
||||||
|
verboseEcho "Warning: Homebrew not found. Actions skipped."
|
||||||
|
fi
|
||||||
|
|
||||||
|
|
||||||
|
'';
|
||||||
|
|
||||||
|
};
|
||||||
|
}
|
||||||
@@ -1,11 +1,13 @@
|
|||||||
{
|
{
|
||||||
config,
|
config,
|
||||||
|
pkgs,
|
||||||
lib,
|
lib,
|
||||||
...
|
...
|
||||||
}:
|
}:
|
||||||
|
|
||||||
let
|
let
|
||||||
cfg = config.nmasur.presets.programs.jujutsu;
|
cfg = config.nmasur.presets.programs.jujutsu;
|
||||||
|
tomlFormat = pkgs.formats.toml { };
|
||||||
in
|
in
|
||||||
|
|
||||||
{
|
{
|
||||||
@@ -19,11 +21,49 @@ in
|
|||||||
# https://github.com/martinvonz/jj/blob/main/docs/config.md
|
# https://github.com/martinvonz/jj/blob/main/docs/config.md
|
||||||
settings = {
|
settings = {
|
||||||
user = {
|
user = {
|
||||||
name = config.programs.git.userName;
|
name = config.programs.git.settings.user.name;
|
||||||
email = config.programs.git.userEmail;
|
email = config.programs.git.settings.user.email;
|
||||||
};
|
};
|
||||||
|
ui.paginate = "never";
|
||||||
|
|
||||||
|
# Automatically snapshot when files change
|
||||||
|
fsmonitor.backend = "watchman";
|
||||||
|
fsmonitor.watchman.register-snapshot-trigger = true;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
xdg.configFile."jjui/config.toml".source = tomlFormat.generate "jjui-config" {
|
||||||
|
actions = [
|
||||||
|
{
|
||||||
|
name = "set-github-bypass";
|
||||||
|
lua = ''
|
||||||
|
exec_shell([[gh api --method PATCH -H "Accept: application/vnd.github+json" /repos/$(gh repo view --json nameWithOwner -q .nameWithOwner)/properties/values -f 'properties[][property_name]=Allow-Ruleset-Bypass' -f 'properties[][value]=true']])
|
||||||
|
flash("Set GitHub rule bypass")
|
||||||
|
'';
|
||||||
|
key = "ctrl+b";
|
||||||
|
scope = "revisions";
|
||||||
|
desc = "Set GitHub rule bypass";
|
||||||
|
}
|
||||||
|
{
|
||||||
|
name = "remove-github-bypass";
|
||||||
|
lua = ''
|
||||||
|
exec_shell([[gh api --method PATCH -H "Accept: application/vnd.github+json" /repos/$(gh repo view --json nameWithOwner -q .nameWithOwner)/properties/values -f 'properties[][property_name]=Allow-Ruleset-Bypass' -f 'properties[][value]=']])
|
||||||
|
flash("Removed GitHub rule bypass")
|
||||||
|
'';
|
||||||
|
key = "ctrl+shift+b";
|
||||||
|
scope = "revisions";
|
||||||
|
desc = "Remove GitHub rule bypass";
|
||||||
|
}
|
||||||
|
];
|
||||||
|
};
|
||||||
|
|
||||||
|
home.packages = [
|
||||||
|
# Required for the fsmonitor to auto-snapshot
|
||||||
|
pkgs.watchman
|
||||||
|
|
||||||
|
# Required to be on path to work in Zellij
|
||||||
|
pkgs.jjui
|
||||||
|
];
|
||||||
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ in
|
|||||||
nmasur.presets.services.i3.terminal = pkgs.kitty;
|
nmasur.presets.services.i3.terminal = pkgs.kitty;
|
||||||
|
|
||||||
# Set the Rofi terminal for running programs
|
# Set the Rofi terminal for running programs
|
||||||
programs.rofi.terminal = lib.mkIf pkgs.stdenv.isLinux (lib.mkDefault "${pkgs.kitty}/bin/kitty");
|
programs.rofi.terminal = lib.mkIf pkgs.stdenv.hostPlatform.isLinux (lib.mkDefault "${pkgs.kitty}/bin/kitty");
|
||||||
|
|
||||||
# Display images in the terminal
|
# Display images in the terminal
|
||||||
programs.fish.interactiveShellInit = # fish
|
programs.fish.interactiveShellInit = # fish
|
||||||
|
|||||||
@@ -0,0 +1,38 @@
|
|||||||
|
{
|
||||||
|
config,
|
||||||
|
pkgs,
|
||||||
|
lib,
|
||||||
|
...
|
||||||
|
}:
|
||||||
|
|
||||||
|
let
|
||||||
|
cfg = config.nmasur.presets.programs.lag-triage;
|
||||||
|
|
||||||
|
term-probe = pkgs.writeScriptBin "term-probe" ''
|
||||||
|
#!${lib.getExe pkgs.python3}
|
||||||
|
${builtins.readFile ./term_probe.py}
|
||||||
|
'';
|
||||||
|
in
|
||||||
|
|
||||||
|
{
|
||||||
|
|
||||||
|
options.nmasur.presets.programs.lag-triage.enable =
|
||||||
|
lib.mkEnableOption "Terminal input-lag triage tools";
|
||||||
|
|
||||||
|
config = lib.mkIf cfg.enable {
|
||||||
|
|
||||||
|
home.packages = [ term-probe ];
|
||||||
|
|
||||||
|
programs.fish.functions = {
|
||||||
|
lag-triage = {
|
||||||
|
description = "Diagnose post-TUI typing lag in the current shell";
|
||||||
|
body = builtins.readFile ./lag-triage.fish;
|
||||||
|
};
|
||||||
|
unlag = {
|
||||||
|
description = "Reset terminal state left behind by a TUI";
|
||||||
|
body = builtins.readFile ./unlag.fish;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
};
|
||||||
|
}
|
||||||
@@ -0,0 +1,182 @@
|
|||||||
|
# Guided diagnosis for the post-TUI typing-lag problem (Ghostty + Zellij + fish).
|
||||||
|
# Run this IN THE LAGGING SHELL the moment you notice the lag, BEFORE starting
|
||||||
|
# a new shell. It captures evidence, then applies targeted resets one at a time
|
||||||
|
# so the stage that cures the lag identifies the layer holding stuck state.
|
||||||
|
# Everything is logged for filing an upstream issue.
|
||||||
|
|
||||||
|
set -l logdir ~/.local/state/lag-triage
|
||||||
|
mkdir -p $logdir
|
||||||
|
set -l logfile $logdir/(date +%Y%m%d-%H%M%S).log
|
||||||
|
|
||||||
|
function _lt --inherit-variable logfile
|
||||||
|
echo $argv | tee -a $logfile
|
||||||
|
end
|
||||||
|
|
||||||
|
function _lt_ask --inherit-variable logfile
|
||||||
|
# usage: _lt_ask VARNAME prompt... -> sets global $VARNAME (default: skip)
|
||||||
|
set -l __name $argv[1]
|
||||||
|
read -g -P "$argv[2..] " $__name
|
||||||
|
or set -g $__name skip
|
||||||
|
test -z "$$__name"; and set -g $__name skip
|
||||||
|
echo "ANSWER $__name: $$__name" >>$logfile
|
||||||
|
end
|
||||||
|
|
||||||
|
_lt "== lag-triage "(date)" =="
|
||||||
|
_lt "Log: $logfile"
|
||||||
|
_lt "Answer y / n, or press Enter to skip a question."
|
||||||
|
_lt ""
|
||||||
|
|
||||||
|
# ---- 1. Context -------------------------------------------------------------
|
||||||
|
_lt_ask ans_tui "Which TUI did you just exit (nvim/jjui/yazi/other)?"
|
||||||
|
_lt_ask ans_launch "Launched via (f)loating-pane keybind or (c)ommand typed in this shell?"
|
||||||
|
|
||||||
|
# ---- 2. Snapshot ------------------------------------------------------------
|
||||||
|
begin
|
||||||
|
echo "-- snapshot --"
|
||||||
|
fish --version
|
||||||
|
echo "fish pid: $fish_pid, started: "(ps -o lstart= -p $fish_pid 2>/dev/null)
|
||||||
|
zellij --version 2>/dev/null
|
||||||
|
echo "escape delay: '$fish_escape_delay_ms' sequence delay: '$fish_sequence_key_delay_ms'"
|
||||||
|
env | grep -iE '^(TERM|ZELLIJ|GHOSTTY|COLORTERM)' | sort
|
||||||
|
echo "-- status features --"
|
||||||
|
status features
|
||||||
|
echo "-- stty -a --"
|
||||||
|
stty -a
|
||||||
|
end >>$logfile 2>&1
|
||||||
|
_lt "Captured shell + environment snapshot."
|
||||||
|
|
||||||
|
# Proven root cause of the 2026-08 lag (see docs/CHANGELOG.md 2026-08-29):
|
||||||
|
# fish latches feature flags from its startup env before config.fish runs, so
|
||||||
|
# a shell with query-term ON sends terminal queries after every command; one
|
||||||
|
# reply zellij fails to relay permanently degrades this process's reader.
|
||||||
|
if status features | string match -qr '^query-term\s+on'
|
||||||
|
_lt ""
|
||||||
|
_lt "!! query-term is ON in this shell: fish did NOT get fish_features="
|
||||||
|
_lt "!! no-query-term in its STARTUP environment (config.fish is too late)."
|
||||||
|
_lt "!! This is the proven root cause of the post-TUI lag — a query reply"
|
||||||
|
_lt "!! lost by zellij permanently degrades this fish process's reader."
|
||||||
|
_lt "!! Fix: spawn fish with the variable exported (zellij default_shell"
|
||||||
|
_lt "!! wrapper fish-no-query-term). Subshells are immune because they"
|
||||||
|
_lt "!! inherit the exported variable — that's why a new shell 'fixes' it."
|
||||||
|
else
|
||||||
|
_lt "query-term is off in this shell (good — the known root cause is ruled out)."
|
||||||
|
end
|
||||||
|
|
||||||
|
# ---- 3. Terminal state below the shell --------------------------------------
|
||||||
|
_lt ""
|
||||||
|
_lt "Querying terminal state (takes a few seconds)..."
|
||||||
|
term-probe report 2>&1 | tee -a $logfile
|
||||||
|
_lt ""
|
||||||
|
_lt " ^ Things to look for: kitty flags with a reply > 0, modifyOtherKeys > 1,"
|
||||||
|
_lt " any mouse/alternate-screen mode SET while at a shell prompt, or a slow"
|
||||||
|
_lt " DA1 round-trip (> 100 ms means the input path itself is delayed)."
|
||||||
|
|
||||||
|
# ---- 4. Raw keystroke capture (bypasses fish entirely) ----------------------
|
||||||
|
_lt ""
|
||||||
|
_lt "Raw input capture: type ~10 characters at a steady pace, including one"
|
||||||
|
_lt "ESC press and one arrow key. This shows the exact bytes this pane delivers"
|
||||||
|
_lt "and their timing, with fish's input handling out of the picture."
|
||||||
|
term-probe keylog 2>&1 | tee -a $logfile
|
||||||
|
_lt_ask ans_keylog_instant "Did each keypress appear INSTANTLY in the capture? (y/n)"
|
||||||
|
_lt_ask ans_keylog_plain "Were plain letters single plain bytes like b'a' (not escape sequences)? (y/n)"
|
||||||
|
|
||||||
|
# ---- 5. Scope ---------------------------------------------------------------
|
||||||
|
_lt ""
|
||||||
|
_lt_ask ans_scope_pane "Optional: open a NEW zellij pane/tab and type — laggy there too? (y/n)"
|
||||||
|
_lt_ask ans_scope_window "Optional: type in a separate Ghostty window (outside this zellij session) — laggy? (y/n)"
|
||||||
|
|
||||||
|
# ---- 6. Staged resets -------------------------------------------------------
|
||||||
|
# Each stage resets one category of state a TUI could have left behind.
|
||||||
|
# The first stage that cures the lag names the culprit.
|
||||||
|
set -l fixed none
|
||||||
|
|
||||||
|
_lt ""
|
||||||
|
_lt "Now applying resets one at a time. After each, type into the test prompt"
|
||||||
|
_lt "to judge whether the lag is gone."
|
||||||
|
_lt "CAVEAT: fish's read prompt may NOT exhibit lag even when the main"
|
||||||
|
_lt "commandline does. If typing at these test prompts never feels laggy at"
|
||||||
|
_lt "all, answer 'u' (unsure) instead of 'y' — a 'y' here is only meaningful"
|
||||||
|
_lt "if you could feel the lag at the test prompts before the reset."
|
||||||
|
|
||||||
|
if test $fixed = none
|
||||||
|
_lt ""
|
||||||
|
_lt "Stage A - kitty keyboard protocol: pop stack + clear all flags"
|
||||||
|
printf '\e[<9u\e[=0;1u'
|
||||||
|
_lt_ask ans_stage_a " Test typing here, then Enter — lag gone? (y/n)"
|
||||||
|
test "$ans_stage_a" = y; and set fixed "A (kitty keyboard state)"
|
||||||
|
end
|
||||||
|
|
||||||
|
if test $fixed = none
|
||||||
|
_lt "Stage B - modifyOtherKeys off"
|
||||||
|
printf '\e[>4;0m'
|
||||||
|
_lt_ask ans_stage_b " Test typing here, then Enter — lag gone? (y/n)"
|
||||||
|
test "$ans_stage_b" = y; and set fixed "B (modifyOtherKeys)"
|
||||||
|
end
|
||||||
|
|
||||||
|
if test $fixed = none
|
||||||
|
_lt "Stage C - normal keypad + normal cursor keys"
|
||||||
|
printf '\e>\e[?1l'
|
||||||
|
_lt_ask ans_stage_c " Test typing here, then Enter — lag gone? (y/n)"
|
||||||
|
test "$ans_stage_c" = y; and set fixed "C (application keypad/cursor mode)"
|
||||||
|
end
|
||||||
|
|
||||||
|
if test $fixed = none
|
||||||
|
_lt "Stage D - disable mouse, focus reporting, synchronized output"
|
||||||
|
printf '\e[?1000l\e[?1001l\e[?1002l\e[?1003l\e[?1005l\e[?1006l\e[?1015l\e[?1016l\e[?1004l\e[?2026l'
|
||||||
|
_lt_ask ans_stage_d " Test typing here, then Enter — lag gone? (y/n)"
|
||||||
|
test "$ans_stage_d" = y; and set fixed "D (mouse/focus/sync modes)"
|
||||||
|
end
|
||||||
|
|
||||||
|
if test $fixed = none
|
||||||
|
_lt "Stage E - leave alternate screen"
|
||||||
|
printf '\e[?1049l'
|
||||||
|
_lt_ask ans_stage_e " Test typing here, then Enter — lag gone? (y/n)"
|
||||||
|
test "$ans_stage_e" = y; and set fixed "E (alternate screen)"
|
||||||
|
end
|
||||||
|
|
||||||
|
if test $fixed = none
|
||||||
|
_lt "Stage F - stty sane (line-discipline reset)"
|
||||||
|
stty sane
|
||||||
|
_lt_ask ans_stage_f " Test typing here, then Enter — lag gone? (y/n)"
|
||||||
|
test "$ans_stage_f" = y; and set fixed "F (termios/line discipline)"
|
||||||
|
end
|
||||||
|
|
||||||
|
if test $fixed = none
|
||||||
|
_lt "Stage G - DECSTR soft terminal reset"
|
||||||
|
printf '\e[!p'
|
||||||
|
_lt_ask ans_stage_g " Test typing here, then Enter — lag gone? (y/n)"
|
||||||
|
test "$ans_stage_g" = y; and set fixed "G (DECSTR-resettable mode)"
|
||||||
|
end
|
||||||
|
|
||||||
|
# ---- 7. Verdict --------------------------------------------------------------
|
||||||
|
_lt ""
|
||||||
|
_lt "== Verdict =="
|
||||||
|
if test $fixed != none
|
||||||
|
_lt "Lag cleared by stage $fixed."
|
||||||
|
_lt "That state was stuck BELOW fish — in the Zellij pane or relayed to"
|
||||||
|
_lt "Ghostty — and the TUI you exited ($ans_tui) failed to restore it, or"
|
||||||
|
_lt "Zellij failed to restore it when the pane closed."
|
||||||
|
_lt "Re-probing terminal state after the fix for comparison:"
|
||||||
|
term-probe report 2>&1 | tee -a $logfile
|
||||||
|
_lt ""
|
||||||
|
_lt "-> File this log against zellij (or ghostty, if a separate window also"
|
||||||
|
_lt " lagged). The before/after probe diff pinpoints the exact stuck mode."
|
||||||
|
else if test "$ans_keylog_instant" = y; and test "$ans_keylog_plain" = y
|
||||||
|
_lt "Raw input reaches this pane instantly as plain bytes, and no terminal"
|
||||||
|
_lt "state reset helps: the lag lives INSIDE this fish process (reader state)."
|
||||||
|
_lt "Confirm now: run 'exec fish' — if that cures it, it is fish-internal."
|
||||||
|
_lt ""
|
||||||
|
_lt "-> To catch it in the act, run your next long-lived shell as:"
|
||||||
|
_lt " FISH_DEBUG='reader,term-support' FISH_DEBUG_OUTPUT=$logdir/fish-debug.log fish"
|
||||||
|
_lt " then re-run lag-triage when it recurs and file both logs to fish-shell."
|
||||||
|
else
|
||||||
|
_lt "Keystrokes were delayed or arrived as escape sequences BEFORE fish saw"
|
||||||
|
_lt "them: the problem is in Zellij (client stdin parser / server) or Ghostty."
|
||||||
|
_lt " new pane also laggy: $ans_scope_pane (y -> session-wide, not this pane)"
|
||||||
|
_lt " separate window laggy: $ans_scope_window (y -> Ghostty itself)"
|
||||||
|
_lt "-> File this log against zellij; include the keylog byte capture."
|
||||||
|
end
|
||||||
|
_lt ""
|
||||||
|
_lt "Full log: $logfile"
|
||||||
|
|
||||||
|
functions -e _lt _lt_ask
|
||||||
@@ -0,0 +1,165 @@
|
|||||||
|
"""Probe the terminal state of the current pane, below the shell.
|
||||||
|
|
||||||
|
Modes:
|
||||||
|
report - query kitty-keyboard flags, modifyOtherKeys, and DEC private
|
||||||
|
modes directly on /dev/tty, reporting each reply (or lack of
|
||||||
|
one) and its round-trip latency. Answers may come from Zellij
|
||||||
|
(pane state) or be relayed from Ghostty (window state).
|
||||||
|
keylog - raw-mode keystroke capture: prints the exact bytes and
|
||||||
|
inter-key latency for every keypress, bypassing the shell's
|
||||||
|
input machinery entirely. Press q to finish.
|
||||||
|
|
||||||
|
Used by the `lag-triage` fish function to pin down which layer
|
||||||
|
(fish / zellij / ghostty) is holding stuck state when typing lags
|
||||||
|
after a TUI exits.
|
||||||
|
"""
|
||||||
|
|
||||||
|
import os
|
||||||
|
import re
|
||||||
|
import select
|
||||||
|
import sys
|
||||||
|
import termios
|
||||||
|
import time
|
||||||
|
import tty
|
||||||
|
|
||||||
|
# DECRQM reply values
|
||||||
|
DECRQM_VALUES = {
|
||||||
|
"0": "not recognized",
|
||||||
|
"1": "SET",
|
||||||
|
"2": "reset",
|
||||||
|
"3": "permanently set",
|
||||||
|
"4": "permanently reset",
|
||||||
|
}
|
||||||
|
|
||||||
|
DEC_MODES = [
|
||||||
|
(1, "application cursor keys (DECCKM)"),
|
||||||
|
(25, "cursor visible"),
|
||||||
|
(1000, "mouse click reporting"),
|
||||||
|
(1002, "mouse drag reporting"),
|
||||||
|
(1003, "mouse all-motion reporting"),
|
||||||
|
(1004, "focus reporting"),
|
||||||
|
(1006, "SGR mouse encoding"),
|
||||||
|
(1049, "alternate screen"),
|
||||||
|
(2004, "bracketed paste"),
|
||||||
|
(2026, "synchronized output"),
|
||||||
|
(2031, "color theme reporting"),
|
||||||
|
]
|
||||||
|
|
||||||
|
QUERIES = [
|
||||||
|
("kitty keyboard flags (\\e[?u)", b"\x1b[?u", rb"\x1b\[\?(\d+)u", None),
|
||||||
|
("modifyOtherKeys (XTQMODKEYS)", b"\x1b[?4m", rb"\x1b\[>4;(\d+)m", None),
|
||||||
|
("background color (OSC 11)", b"\x1b]11;?\x1b\\", rb"\x1b\]11;([^\x07\x1b]+)", None),
|
||||||
|
] + [
|
||||||
|
(
|
||||||
|
f"DEC mode {num} — {desc}",
|
||||||
|
b"\x1b[?%d$p" % num,
|
||||||
|
rb"\x1b\[\?%d;(\d+)\$y" % num,
|
||||||
|
DECRQM_VALUES,
|
||||||
|
)
|
||||||
|
for num, desc in DEC_MODES
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
def read_for(fd, seconds):
|
||||||
|
buf = b""
|
||||||
|
end = time.monotonic() + seconds
|
||||||
|
while True:
|
||||||
|
remaining = end - time.monotonic()
|
||||||
|
if remaining <= 0:
|
||||||
|
break
|
||||||
|
r, _, _ = select.select([fd], [], [], remaining)
|
||||||
|
if not r:
|
||||||
|
break
|
||||||
|
buf += os.read(fd, 4096)
|
||||||
|
return buf
|
||||||
|
|
||||||
|
|
||||||
|
def report(fd):
|
||||||
|
lines = []
|
||||||
|
raw_dump = b""
|
||||||
|
for label, query, pattern, value_names in QUERIES:
|
||||||
|
raw_dump += read_for(fd, 0.02) # drain stragglers
|
||||||
|
start = time.monotonic()
|
||||||
|
os.write(fd, query)
|
||||||
|
buf = b""
|
||||||
|
match = None
|
||||||
|
deadline = time.monotonic() + 0.35
|
||||||
|
while time.monotonic() < deadline:
|
||||||
|
buf += read_for(fd, 0.05)
|
||||||
|
match = re.search(pattern, buf)
|
||||||
|
if match:
|
||||||
|
break
|
||||||
|
raw_dump += buf
|
||||||
|
if match:
|
||||||
|
latency = (time.monotonic() - start) * 1000
|
||||||
|
value = match.group(1).decode("ascii", "replace")
|
||||||
|
if value_names:
|
||||||
|
value = f"{value} ({value_names.get(value, '?')})"
|
||||||
|
lines.append(f" {label:45s} = {value:24s} [{latency:6.1f} ms]")
|
||||||
|
else:
|
||||||
|
lines.append(f" {label:45s} = (no reply)")
|
||||||
|
|
||||||
|
# DA1 as a fence: every terminal answers it, so its round-trip time
|
||||||
|
# measures the whole input path (ghostty -> zellij -> pane -> here).
|
||||||
|
start = time.monotonic()
|
||||||
|
os.write(fd, b"\x1b[c")
|
||||||
|
buf = b""
|
||||||
|
match = None
|
||||||
|
deadline = time.monotonic() + 2.0
|
||||||
|
while time.monotonic() < deadline:
|
||||||
|
buf += read_for(fd, 0.05)
|
||||||
|
match = re.search(rb"\x1b\[\?([0-9;]*)c", buf)
|
||||||
|
if match:
|
||||||
|
break
|
||||||
|
raw_dump += buf
|
||||||
|
if match:
|
||||||
|
latency = (time.monotonic() - start) * 1000
|
||||||
|
lines.append(
|
||||||
|
f" {'device attributes (DA1) round-trip':45s} = "
|
||||||
|
f"{match.group(1).decode():24s} [{latency:6.1f} ms]"
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
lines.append(f" {'device attributes (DA1) round-trip':45s} = (NO REPLY in 2s!)")
|
||||||
|
lines.append(f" raw bytes received: {raw_dump!r}")
|
||||||
|
return lines
|
||||||
|
|
||||||
|
|
||||||
|
def keylog(fd):
|
||||||
|
sys.stdout.write("keylog: capturing raw bytes from the tty. Press q to finish.\r\n")
|
||||||
|
sys.stdout.flush()
|
||||||
|
last = time.monotonic()
|
||||||
|
while True:
|
||||||
|
select.select([fd], [], [], None)
|
||||||
|
data = os.read(fd, 4096)
|
||||||
|
now = time.monotonic()
|
||||||
|
delta_ms = (now - last) * 1000
|
||||||
|
last = now
|
||||||
|
sys.stdout.write(f" +{delta_ms:8.1f} ms {data!r} hex={data.hex(' ')}\r\n")
|
||||||
|
sys.stdout.flush()
|
||||||
|
if data in (b"q", b"\x03", b"\x04"):
|
||||||
|
break
|
||||||
|
|
||||||
|
|
||||||
|
def main():
|
||||||
|
mode = sys.argv[1] if len(sys.argv) > 1 else "report"
|
||||||
|
fd = os.open("/dev/tty", os.O_RDWR)
|
||||||
|
old = termios.tcgetattr(fd)
|
||||||
|
lines = None
|
||||||
|
try:
|
||||||
|
tty.setraw(fd)
|
||||||
|
if mode == "report":
|
||||||
|
lines = report(fd)
|
||||||
|
elif mode == "keylog":
|
||||||
|
keylog(fd)
|
||||||
|
else:
|
||||||
|
raise SystemExit(f"unknown mode: {mode}")
|
||||||
|
finally:
|
||||||
|
termios.tcsetattr(fd, termios.TCSADRAIN, old)
|
||||||
|
os.close(fd)
|
||||||
|
if lines:
|
||||||
|
print("terminal state as seen from this pane:")
|
||||||
|
print("\n".join(lines))
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
# One-shot reset of terminal state a TUI may have left behind (kitty keyboard
|
||||||
|
# flags, modifyOtherKeys, application keypad/cursor, mouse/focus reporting,
|
||||||
|
# alternate screen, termios). fish re-enables the modes it wants at the next
|
||||||
|
# prompt, so this is safe to run any time.
|
||||||
|
#
|
||||||
|
# Diagnostic value: if this cures the lag, the stuck state was below fish
|
||||||
|
# (run lag-triage next time to find which mode). If only `exec fish` cures
|
||||||
|
# it, the lag is inside the fish process itself.
|
||||||
|
printf '\e[<9u\e[=0;1u'
|
||||||
|
printf '\e[>4;0m'
|
||||||
|
printf '\e>\e[?1l'
|
||||||
|
printf '\e[?1000l\e[?1001l\e[?1002l\e[?1003l\e[?1005l\e[?1006l\e[?1015l\e[?1016l\e[?1004l\e[?2026l'
|
||||||
|
printf '\e[?1049l'
|
||||||
|
stty sane
|
||||||
|
echo "terminal state reset — if typing still lags, run lag-triage (before exec fish!)"
|
||||||
@@ -0,0 +1,151 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
"""Deterministic repro of permanent fish reader degradation (fish 4.8.1).
|
||||||
|
|
||||||
|
This is evidence for an upstream fish-shell report, and the proof behind the
|
||||||
|
fish-no-query-term wrapper in presets/programs/zellij.nix. Not installed by
|
||||||
|
the nix module; run directly: python3 upstream_repro.py [queryterm|noqueryterm]
|
||||||
|
|
||||||
|
Finding: with the query-term feature enabled (latched from the startup env,
|
||||||
|
which is fish's default), fish sends OSC 11 + CPR (\e[6n) + DA1 (\e[0c)
|
||||||
|
after every external command and waits for the replies. If the terminal
|
||||||
|
fails to reply during ONE such cycle -- even though it answered every query
|
||||||
|
before and answers every query after -- that fish process's interactive
|
||||||
|
reader is PERMANENTLY degraded: keystrokes are no longer echoed (>3s each,
|
||||||
|
never recovers). In production this happens when zellij drops/mis-relays a
|
||||||
|
reply during TUI teardown or heavy output (cf. zellij-org/zellij#5158), and
|
||||||
|
it presents as permanent typing lag cured only by replacing the process.
|
||||||
|
With fish_features=no-query-term in the startup environment, the same
|
||||||
|
sequence has zero effect (~35ms echo throughout).
|
||||||
|
|
||||||
|
Phases:
|
||||||
|
A. terminal answers all queries -> echo ~35ms (both variants)
|
||||||
|
B. replies dropped for one command -> queryterm: echo dead, permanently
|
||||||
|
C. replies restored, another command -> queryterm: still dead
|
||||||
|
"""
|
||||||
|
import os, pty, re, select, subprocess, sys, time, fcntl, termios
|
||||||
|
|
||||||
|
VARIANT = sys.argv[1] if len(sys.argv) > 1 else "queryterm"
|
||||||
|
|
||||||
|
env = dict(os.environ)
|
||||||
|
env["TERM"] = "xterm-ghostty"
|
||||||
|
env["ZELLIJ"] = "0"
|
||||||
|
env["ZELLIJ_SESSION_NAME"] = "repro"
|
||||||
|
env["FISH_DEBUG"] = "term-support"
|
||||||
|
env["FISH_DEBUG_OUTPUT"] = f"/tmp/fish-lagrepro-{VARIANT}.log"
|
||||||
|
env.pop("fish_features", None)
|
||||||
|
if VARIANT == "noqueryterm":
|
||||||
|
env["fish_features"] = "no-query-term"
|
||||||
|
|
||||||
|
master, slave = pty.openpty()
|
||||||
|
# give it a size
|
||||||
|
fcntl.ioctl(master, termios.TIOCSWINSZ, b"\x00\x28\x00\x78\x00\x00\x00\x00")
|
||||||
|
proc = subprocess.Popen(
|
||||||
|
["fish", "-i", "--no-config"],
|
||||||
|
stdin=slave, stdout=slave, stderr=slave, env=env,
|
||||||
|
preexec_fn=lambda: (os.setsid(), fcntl.ioctl(0, termios.TIOCSCTTY, 0)),
|
||||||
|
close_fds=True,
|
||||||
|
)
|
||||||
|
os.close(slave)
|
||||||
|
|
||||||
|
RESPOND = True
|
||||||
|
transcript = []
|
||||||
|
|
||||||
|
def respond(data):
|
||||||
|
"""Answer terminal queries the way a well-behaved terminal would."""
|
||||||
|
out = b""
|
||||||
|
for m in re.finditer(rb"\x1b\[6n", data):
|
||||||
|
out += b"\x1b[40;1R" # CPR
|
||||||
|
for m in re.finditer(rb"\x1b\[0?c", data):
|
||||||
|
out += b"\x1b[?62;22c" # DA1
|
||||||
|
for m in re.finditer(rb"\x1b\[\?u", data):
|
||||||
|
out += b"\x1b[?0u" # kitty flags
|
||||||
|
for m in re.finditer(rb"\x1b\]11;\?", data):
|
||||||
|
out += b"\x1b]11;rgb:2828/2828/2828\x1b\\" # OSC 11
|
||||||
|
for m in re.finditer(rb"\x1b\[>0?q", data):
|
||||||
|
out += b"\x1bP>|ghostty 1.3.1\x1b\\" # XTVERSION
|
||||||
|
for m in re.finditer(rb"\x1bP\+q[0-9a-fA-F;]+\x1b\\", data):
|
||||||
|
out += b"\x1bP0+r\x1b\\" # XTGETTCAP: not found
|
||||||
|
for m in re.finditer(rb"\x1b\[\?(\d+)\$p", data):
|
||||||
|
out += b"\x1b[?%s;2$y" % m.group(1) # DECRQM: reset
|
||||||
|
return out
|
||||||
|
|
||||||
|
def pump(timeout):
|
||||||
|
"""Read fish output for `timeout` seconds, answering queries if RESPOND."""
|
||||||
|
buf = b""
|
||||||
|
end = time.monotonic() + timeout
|
||||||
|
while time.monotonic() < end:
|
||||||
|
r, _, _ = select.select([master], [], [], 0.03)
|
||||||
|
if r:
|
||||||
|
try:
|
||||||
|
data = os.read(master, 65536)
|
||||||
|
except OSError:
|
||||||
|
return buf
|
||||||
|
buf += data
|
||||||
|
transcript.append(data)
|
||||||
|
if RESPOND:
|
||||||
|
reply = respond(data)
|
||||||
|
if reply:
|
||||||
|
os.write(master, reply)
|
||||||
|
return buf
|
||||||
|
|
||||||
|
def send(s):
|
||||||
|
os.write(master, s if isinstance(s, bytes) else s.encode())
|
||||||
|
|
||||||
|
def measure_echo(chars, settle=0.1):
|
||||||
|
"""Send chars one at a time; measure time until each is echoed."""
|
||||||
|
results = []
|
||||||
|
for ch in chars:
|
||||||
|
pump(settle)
|
||||||
|
t0 = time.monotonic()
|
||||||
|
send(ch)
|
||||||
|
deadline = time.monotonic() + 3.0
|
||||||
|
latency = None
|
||||||
|
buf = b""
|
||||||
|
while time.monotonic() < deadline:
|
||||||
|
buf += pump(0.02)
|
||||||
|
if ch.encode() in buf:
|
||||||
|
latency = (time.monotonic() - t0) * 1000
|
||||||
|
break
|
||||||
|
results.append((ch, latency))
|
||||||
|
return results
|
||||||
|
|
||||||
|
print(f"=== variant: {VARIANT} ===")
|
||||||
|
pump(1.2) # startup, queries answered
|
||||||
|
|
||||||
|
send("echo warmup\r")
|
||||||
|
pump(0.8)
|
||||||
|
|
||||||
|
print("phase A: terminal responsive, echo latency per key:")
|
||||||
|
for ch, ms in measure_echo("abcde"):
|
||||||
|
print(f" {ch}: {ms:.0f} ms" if ms else f" {ch}: NO ECHO in 3s")
|
||||||
|
send("\x15") # ctrl-u clear line
|
||||||
|
pump(0.3)
|
||||||
|
|
||||||
|
# Run external command, then STOP answering queries (simulate lost relay)
|
||||||
|
send("sh -c true\r")
|
||||||
|
time.sleep(0.05)
|
||||||
|
RESPOND = False
|
||||||
|
pump(1.0)
|
||||||
|
|
||||||
|
print("phase B: after external command with query replies DROPPED:")
|
||||||
|
for ch, ms in measure_echo("fghij"):
|
||||||
|
print(f" {ch}: {ms:.0f} ms" if ms else f" {ch}: NO ECHO in 3s")
|
||||||
|
send("\x15")
|
||||||
|
pump(0.3)
|
||||||
|
|
||||||
|
# Does it persist across further commands, with responses restored?
|
||||||
|
RESPOND = True
|
||||||
|
send("sh -c true\r")
|
||||||
|
pump(1.0)
|
||||||
|
print("phase C: responses restored, after another external command:")
|
||||||
|
for ch, ms in measure_echo("klmno"):
|
||||||
|
print(f" {ch}: {ms:.0f} ms" if ms else f" {ch}: NO ECHO in 3s")
|
||||||
|
|
||||||
|
send("\x15")
|
||||||
|
pump(0.2)
|
||||||
|
send("exit\r")
|
||||||
|
pump(0.5)
|
||||||
|
try:
|
||||||
|
proc.wait(timeout=3)
|
||||||
|
except subprocess.TimeoutExpired:
|
||||||
|
proc.kill()
|
||||||
@@ -0,0 +1,96 @@
|
|||||||
|
{
|
||||||
|
config,
|
||||||
|
pkgs,
|
||||||
|
lib,
|
||||||
|
...
|
||||||
|
}:
|
||||||
|
|
||||||
|
let
|
||||||
|
cfg = config.nmasur.presets.programs.lazygit;
|
||||||
|
in
|
||||||
|
|
||||||
|
{
|
||||||
|
options.nmasur.presets.programs.lazygit.enable = lib.mkEnableOption "Lazygit git TUI";
|
||||||
|
|
||||||
|
config = lib.mkIf cfg.enable {
|
||||||
|
programs.lazygit = {
|
||||||
|
enable = true;
|
||||||
|
settings = {
|
||||||
|
git.paging = {
|
||||||
|
# useConfig = true;
|
||||||
|
pager = "${pkgs.git}/share/git/contrib/diff-highlight/diff-highlight";
|
||||||
|
};
|
||||||
|
os = {
|
||||||
|
edit = "${config.home.sessionVariables.EDITOR} {{filename}}";
|
||||||
|
editAtLine = "${config.home.sessionVariables.EDITOR} {{filename}}:{{line}}";
|
||||||
|
editAtLineAndWait = "${config.home.sessionVariables.EDITOR} {{filename}}:{{line}}";
|
||||||
|
openDirInEditor = "${config.home.sessionVariables.EDITOR}";
|
||||||
|
open = "${config.home.sessionVariables.EDITOR} {{filename}}";
|
||||||
|
};
|
||||||
|
customCommands = [
|
||||||
|
{
|
||||||
|
key = "N";
|
||||||
|
context = "files";
|
||||||
|
command = "git add -N {{.SelectedFile.Name}}";
|
||||||
|
}
|
||||||
|
{
|
||||||
|
key = "<a-enter>";
|
||||||
|
context = "global";
|
||||||
|
command =
|
||||||
|
let
|
||||||
|
openGitUrl = pkgs.writeShellScriptBin "open-git-url" ''
|
||||||
|
# Try to get the remote URL using two common methods; suppress stderr for individual commands.
|
||||||
|
# "git remote get-url origin" is generally preferred.
|
||||||
|
# "git config --get remote.origin.url" is a fallback.
|
||||||
|
URL=$(git remote get-url origin 2>/dev/null || git config --get remote.origin.url 2>/dev/null);
|
||||||
|
|
||||||
|
# Check if a URL was actually found.
|
||||||
|
if [ -z "$URL" ]; then
|
||||||
|
# Send error message to stderr so it might appear in lazygit logs or notifications.
|
||||||
|
echo "Lazygit: Could not determine remote URL for 'origin'." >&2;
|
||||||
|
# Exit with an error code.
|
||||||
|
exit 1;
|
||||||
|
fi;
|
||||||
|
|
||||||
|
# Check if the URL is a GitHub SSH URL and convert it to HTTPS.
|
||||||
|
# This uses echo and grep to check for "@github.com" and then sed for transformation.
|
||||||
|
if echo "$URL" | grep -q "@github.com:"; then
|
||||||
|
# Transform git@github.com:user/repo.git to https://github.com/user/repo
|
||||||
|
# The first sed handles the main transformation.
|
||||||
|
# The second sed removes a trailing .git if present, for a cleaner URL.
|
||||||
|
URL=$(echo "$URL" | sed "s|git@github.com:|https://github.com/|" | sed "s|\.git$||");
|
||||||
|
# Optional: Log the transformation for debugging.
|
||||||
|
# echo "Lazygit: Transformed GitHub SSH URL to '$URL'" >&2;
|
||||||
|
fi;
|
||||||
|
|
||||||
|
# Determine the operating system.
|
||||||
|
OS="$(uname -s)";
|
||||||
|
|
||||||
|
# Optional: Echo for debugging. This might appear in lazygit logs or as a brief message.
|
||||||
|
# Remove " >&2" if you want to see it as a potential success message in lazygit UI (if it shows stdout).
|
||||||
|
# echo "Lazygit: Opening URL '$URL' on '$OS'" >&2;
|
||||||
|
|
||||||
|
# Execute the appropriate command to open the URL based on the OS.
|
||||||
|
case "$OS" in
|
||||||
|
Darwin*) # macOS
|
||||||
|
open "$URL";;
|
||||||
|
Linux*) # Linux
|
||||||
|
xdg-open "$URL";;
|
||||||
|
*) # Unsupported OS
|
||||||
|
echo "Lazygit: Unsupported OS ('$OS'). Could not open URL." >&2;
|
||||||
|
exit 1;;
|
||||||
|
esac
|
||||||
|
'';
|
||||||
|
in
|
||||||
|
lib.getExe openGitUrl;
|
||||||
|
}
|
||||||
|
];
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
programs.fish.shellAbbrs = {
|
||||||
|
lg = "lazygit";
|
||||||
|
};
|
||||||
|
|
||||||
|
};
|
||||||
|
}
|
||||||
@@ -26,7 +26,7 @@ let
|
|||||||
-E pr=5000/prompt \
|
-E pr=5000/prompt \
|
||||||
-H "${ldap_scheme}://''${LDAP_HOST}:${builtins.toString ldap_port}" \
|
-H "${ldap_scheme}://''${LDAP_HOST}:${builtins.toString ldap_port}" \
|
||||||
-D "${pkgs.lib.toUpper magic_prefix}2\\${pkgs.lib.toLower config.home.username}" \
|
-D "${pkgs.lib.toUpper magic_prefix}2\\${pkgs.lib.toLower config.home.username}" \
|
||||||
-w "$(${pkgs._1password-cli}/bin/op item get T2 --fields label=password --reveal)" \
|
-w "$(/usr/local/bin/op item get T2 --fields label=password --reveal)" \
|
||||||
-b "dc=''${LDAP_HOST//./,dc=}" \
|
-b "dc=''${LDAP_HOST//./,dc=}" \
|
||||||
-s "sub" -x "(cn=''${SEARCH_FILTER})" \
|
-s "sub" -x "(cn=''${SEARCH_FILTER})" \
|
||||||
| ${jq_parse}/bin/ljq
|
| ${jq_parse}/bin/ljq
|
||||||
|
|||||||
@@ -31,5 +31,9 @@ in
|
|||||||
pkgs.mpvScripts.mpv-delete-file
|
pkgs.mpvScripts.mpv-delete-file
|
||||||
];
|
];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
programs.fish.shellAbbrs = {
|
||||||
|
mpvs = "mpv --shuffle=yes";
|
||||||
|
};
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -38,13 +38,13 @@ in
|
|||||||
);
|
);
|
||||||
|
|
||||||
# Use Neovim as the editor for git commit messages
|
# Use Neovim as the editor for git commit messages
|
||||||
programs.git.extraConfig.core.editor = "${lib.getExe cfg.package}";
|
programs.git.settings.core.editor = "${lib.getExe cfg.package}";
|
||||||
programs.jujutsu.settings.ui.editor = "${lib.getExe cfg.package}";
|
programs.jujutsu.settings.ui.editor = "${lib.getExe cfg.package}";
|
||||||
|
|
||||||
# Set Neovim as the default app for text editing and manual pages
|
# Set Neovim as the default app for text editing and manual pages
|
||||||
home.sessionVariables = {
|
home.sessionVariables = {
|
||||||
EDITOR = "${lib.getExe cfg.package}";
|
EDITOR = "${lib.getExe cfg.package}";
|
||||||
MANPAGER = "${lib.getExe cfg.package} +Man!";
|
# MANPAGER = "${lib.getExe cfg.package} +Man!";
|
||||||
};
|
};
|
||||||
|
|
||||||
# Create quick aliases for launching Neovim
|
# Create quick aliases for launching Neovim
|
||||||
@@ -63,10 +63,10 @@ in
|
|||||||
# Create a desktop option for launching Neovim from a file manager
|
# Create a desktop option for launching Neovim from a file manager
|
||||||
# (Requires launching the terminal and then executing Neovim)
|
# (Requires launching the terminal and then executing Neovim)
|
||||||
xdg.desktopEntries.nvim =
|
xdg.desktopEntries.nvim =
|
||||||
lib.mkIf (pkgs.stdenv.isLinux && config.nmasur.presets.services.i3.enable)
|
lib.mkIf (pkgs.stdenv.hostPlatform.isLinux && config.nmasur.presets.services.i3.enable)
|
||||||
{
|
{
|
||||||
name = "Neovim wrapper";
|
name = "Neovim wrapper";
|
||||||
exec = "${lib.getExe config.nmasur.presets.services.i3.terminal} nvim %F"; # TODO: change to generic
|
exec = ''${lib.getExe config.nmasur.presets.services.i3.terminal} --command="nvim %F"''; # TODO: change to generic
|
||||||
mimeType = [
|
mimeType = [
|
||||||
"text/plain"
|
"text/plain"
|
||||||
"text/markdown"
|
"text/markdown"
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
config,
|
config,
|
||||||
pkgs,
|
# pkgs,
|
||||||
lib,
|
lib,
|
||||||
...
|
...
|
||||||
}:
|
}:
|
||||||
@@ -23,17 +23,18 @@ in
|
|||||||
};
|
};
|
||||||
|
|
||||||
# Create nix-index if doesn't exist
|
# Create nix-index if doesn't exist
|
||||||
home.activation.createNixIndex =
|
# Should not be necessary with the nix-index-database flake
|
||||||
let
|
# home.activation.createNixIndex =
|
||||||
cacheDir = "${config.xdg.cacheHome}/nix-index";
|
# let
|
||||||
in
|
# cacheDir = "${config.xdg.cacheHome}/nix-index";
|
||||||
lib.mkIf config.programs.nix-index.enable (
|
# in
|
||||||
config.lib.dag.entryAfter [ "writeBoundary" ] ''
|
# lib.mkIf config.programs.nix-index.enable (
|
||||||
if [ ! -d ${cacheDir} ]; then
|
# config.lib.dag.entryAfter [ "writeBoundary" ] ''
|
||||||
run ${pkgs.nix-index}/bin/nix-index -f ${pkgs.path}
|
# if [ ! -d ${cacheDir} ]; then
|
||||||
fi
|
# run ${pkgs.nix-index}/bin/nix-index -f ${pkgs.path}
|
||||||
''
|
# fi
|
||||||
);
|
# ''
|
||||||
|
# );
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -15,12 +15,18 @@ in
|
|||||||
description = "Nixpkgs tools for macOS";
|
description = "Nixpkgs tools for macOS";
|
||||||
default =
|
default =
|
||||||
config.nmasur.presets.programs.nixpkgs.enable
|
config.nmasur.presets.programs.nixpkgs.enable
|
||||||
&& pkgs.stdenv.isDarwin
|
&& pkgs.stdenv.hostPlatform.isDarwin
|
||||||
&& config.nmasur.presets.programs.dotfiles.enable;
|
&& config.nmasur.presets.programs.dotfiles.enable;
|
||||||
};
|
};
|
||||||
|
|
||||||
config = lib.mkIf (cfg.enable) {
|
config = lib.mkIf (cfg.enable) {
|
||||||
|
|
||||||
|
# These are useful for triggering from zellij (rather than running directly in the shell)
|
||||||
|
nmasur.presets.programs.nixpkgs.commands.rebuildNixos = pkgs.writeShellScriptBin "rebuild-darwin" ''
|
||||||
|
git -C ${config.nmasur.presets.programs.dotfiles.path} add --intent-to-add --all
|
||||||
|
sudo darwin-rebuild switch --flake "${config.nmasur.presets.programs.dotfiles.path}#${config.nmasur.settings.host}"
|
||||||
|
'';
|
||||||
|
|
||||||
programs.fish = {
|
programs.fish = {
|
||||||
shellAbbrs = lib.mkIf config.nmasur.presets.programs.dotfiles.enable {
|
shellAbbrs = lib.mkIf config.nmasur.presets.programs.dotfiles.enable {
|
||||||
nr = {
|
nr = {
|
||||||
@@ -34,13 +40,13 @@ in
|
|||||||
rebuild-darwin = {
|
rebuild-darwin = {
|
||||||
body = ''
|
body = ''
|
||||||
git -C ${config.nmasur.presets.programs.dotfiles.path} add --intent-to-add --all
|
git -C ${config.nmasur.presets.programs.dotfiles.path} add --intent-to-add --all
|
||||||
echo "darwin-rebuild switch --flake ${config.nmasur.presets.programs.dotfiles.path}#lookingglass"
|
echo "sudo darwin-rebuild switch --flake ${config.nmasur.presets.programs.dotfiles.path}#lookingglass"
|
||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
rebuild-darwin-offline = {
|
rebuild-darwin-offline = {
|
||||||
body = ''
|
body = ''
|
||||||
git -C ${config.nmasur.presets.programs.dotfiles.path} add --intent-to-add --all
|
git -C ${config.nmasur.presets.programs.dotfiles.path} add --intent-to-add --all
|
||||||
echo "darwin-rebuild switch --option substitute false --flake ${config.nmasur.presets.programs.dotfiles.path}#lookingglass"
|
echo "sudo darwin-rebuild switch --option substitute false --flake ${config.nmasur.presets.programs.dotfiles.path}#lookingglass"
|
||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
rebuild-home = lib.mkForce {
|
rebuild-home = lib.mkForce {
|
||||||
|
|||||||
@@ -11,10 +11,47 @@ in
|
|||||||
|
|
||||||
{
|
{
|
||||||
|
|
||||||
options.nmasur.presets.programs.nixpkgs.enable = lib.mkEnableOption "Nixpkgs presets";
|
options.nmasur.presets.programs.nixpkgs = {
|
||||||
|
enable = lib.mkEnableOption "Nixpkgs presets";
|
||||||
|
commands = {
|
||||||
|
# These are useful for triggering from zellij (rather than running directly in the shell)
|
||||||
|
rebuildHome = lib.mkOption {
|
||||||
|
type = lib.types.package;
|
||||||
|
default = pkgs.writeShellScriptBin "rebuild-home" ''
|
||||||
|
git -C ${config.nmasur.presets.programs.dotfiles.path} add --intent-to-add --all
|
||||||
|
${lib.getExe pkgs.home-manager} switch --flake "${config.nmasur.presets.programs.dotfiles.path}#${config.nmasur.settings.host}"
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
rebuildNixos = lib.mkOption {
|
||||||
|
type = lib.types.package;
|
||||||
|
default = pkgs.writeShellScriptBin "rebuild-nixos" ''
|
||||||
|
git -C ${config.nmasur.presets.programs.dotfiles.path} add --intent-to-add --all
|
||||||
|
doas nixos-rebuild switch --flake ${config.nmasur.presets.programs.dotfiles.path}
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
rebuildNixosAndPause = lib.mkOption {
|
||||||
|
type = lib.types.package;
|
||||||
|
default = pkgs.writeShellScriptBin "rebuild-nixos-pause" ''
|
||||||
|
${lib.getExe cfg.commands.rebuildNixos} || read
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
rebuildHomeAndPause = lib.mkOption {
|
||||||
|
type = lib.types.package;
|
||||||
|
default = pkgs.writeShellScriptBin "rebuild-home-pause" ''
|
||||||
|
${lib.getExe cfg.commands.rebuildHome} || read
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
config = lib.mkIf cfg.enable {
|
config = lib.mkIf cfg.enable {
|
||||||
|
|
||||||
|
home.packages = [
|
||||||
|
pkgs.nh # Allows rebuilding with a cleaner TUI
|
||||||
|
cfg.commands.rebuildHome
|
||||||
|
cfg.commands.rebuildNixos
|
||||||
|
];
|
||||||
|
|
||||||
programs.fish = {
|
programs.fish = {
|
||||||
shellAbbrs = {
|
shellAbbrs = {
|
||||||
n = "nix";
|
n = "nix";
|
||||||
|
|||||||
@@ -44,21 +44,22 @@ in
|
|||||||
programs.fish.functions = {
|
programs.fish.functions = {
|
||||||
syncnotes = {
|
syncnotes = {
|
||||||
description = "Full git commit on notes";
|
description = "Full git commit on notes";
|
||||||
body = builtins.readFile lib.getExe (
|
body =
|
||||||
pkgs.writers.writeFishBin "syncnotes" {
|
let
|
||||||
makeWrapperArgs = [
|
git = lib.getExe pkgs.git;
|
||||||
"--prefix"
|
in
|
||||||
"PATH"
|
# fish
|
||||||
":"
|
''
|
||||||
"${lib.makeBinPath [ pkgs.git ]}"
|
${git} -C ${cfg.path} pull
|
||||||
];
|
${git} -C ${cfg.path} add -A
|
||||||
} builtins.readFile ./syncnotes.fish
|
${git} -C ${cfg.path} commit -m autosync
|
||||||
);
|
${git} -C ${cfg.path} push
|
||||||
|
'';
|
||||||
};
|
};
|
||||||
note = {
|
note = {
|
||||||
description = "Edit or create a note";
|
description = "Edit or create a note";
|
||||||
argumentNames = "filename";
|
argumentNames = "filename";
|
||||||
body = builtins.readFile lib.getExe (
|
body = lib.getExe (
|
||||||
pkgs.writers.writeFishBin "note" {
|
pkgs.writers.writeFishBin "note" {
|
||||||
makeWrapperArgs = [
|
makeWrapperArgs = [
|
||||||
"--prefix"
|
"--prefix"
|
||||||
@@ -69,7 +70,44 @@ in
|
|||||||
pkgs.fzf
|
pkgs.fzf
|
||||||
]}"
|
]}"
|
||||||
];
|
];
|
||||||
} builtins.readFile ./note.fish
|
} (builtins.readFile ./note.fish)
|
||||||
|
);
|
||||||
|
};
|
||||||
|
generate-today = {
|
||||||
|
description = "Create today's note";
|
||||||
|
body = # fish
|
||||||
|
''
|
||||||
|
set filename $(date +%Y-%m-%d_%a)
|
||||||
|
set filepath "${cfg.path}/content/journal/$filename.md"
|
||||||
|
if ! test -e "$filepath"
|
||||||
|
echo -e "---\ntitle: $(date +"%A, %B %e %Y") - $(curl "https://wttr.in/New+York+City?u&format=1")\ntags: [ journal ]\n---\n\n" > "$filepath"
|
||||||
|
end
|
||||||
|
echo "$filepath"
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
today = {
|
||||||
|
description = "Edit or create today's note";
|
||||||
|
body = lib.getExe (
|
||||||
|
pkgs.writers.writeFishBin "today"
|
||||||
|
{
|
||||||
|
makeWrapperArgs = [
|
||||||
|
"--prefix"
|
||||||
|
"PATH"
|
||||||
|
":"
|
||||||
|
"${lib.makeBinPath [
|
||||||
|
pkgs.curl
|
||||||
|
pkgs.helix
|
||||||
|
]}"
|
||||||
|
];
|
||||||
|
} # fish
|
||||||
|
''
|
||||||
|
set filename $(date +%Y-%m-%d_%a)
|
||||||
|
set filepath "${cfg.path}/content/journal/$filename.md"
|
||||||
|
if ! test -e "$filepath"
|
||||||
|
echo -e "---\ntitle: $(date +"%A, %B %e %Y") - $(curl "https://wttr.in/New+York+City?u&format=1")\ntags: [ journal ]\n---\n\n" > "$filepath"
|
||||||
|
end
|
||||||
|
hx "$filepath"
|
||||||
|
''
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -13,12 +13,23 @@ in
|
|||||||
|
|
||||||
options.nmasur.presets.programs.noti.enable = lib.mkEnableOption "Noti CLI notifications";
|
options.nmasur.presets.programs.noti.enable = lib.mkEnableOption "Noti CLI notifications";
|
||||||
|
|
||||||
config = lib.mkIf (cfg.enable && (pkgs.stdenv.isDarwin || config.services.dunst.enable)) {
|
config = lib.mkIf (cfg.enable && (pkgs.stdenv.hostPlatform.isDarwin || config.services.dunst.enable)) {
|
||||||
home.packages = [ pkgs.noti ];
|
home.packages = [ pkgs.noti ];
|
||||||
programs.fish.shellAbbrs = {
|
programs.fish = {
|
||||||
|
shellAbbrs = {
|
||||||
# Add noti for ghpr in Darwin
|
# Add noti for ghpr in Darwin
|
||||||
ghpr = lib.mkForce "gh pr create && sleep 3 && noti gh run watch";
|
ghpr = lib.mkForce "gh pr create && sleep 3 && noti gh run watch";
|
||||||
grw = lib.mkForce "noti gh run watch";
|
grw = lib.mkForce "noti gh run watch";
|
||||||
};
|
};
|
||||||
|
functions = {
|
||||||
|
gh-run = {
|
||||||
|
body =
|
||||||
|
lib.mkForce # fish
|
||||||
|
''
|
||||||
|
${lib.getExe pkgs.zellij} action new-pane --start-suspended -- noti gh run watch
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -22,6 +22,6 @@ in
|
|||||||
|
|
||||||
# Broken on 2023-12-11
|
# Broken on 2023-12-11
|
||||||
# https://forum.obsidian.md/t/electron-25-is-now-eol-please-upgrade-to-a-newer-version/72878/8
|
# https://forum.obsidian.md/t/electron-25-is-now-eol-please-upgrade-to-a-newer-version/72878/8
|
||||||
# insecurePackages = [ "electron-25.9.0" ];
|
# allowInsecurePackages = [ "electron-36.9.5" ];
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -24,6 +24,7 @@ in
|
|||||||
.terraform/
|
.terraform/
|
||||||
.target/
|
.target/
|
||||||
/Library/
|
/Library/
|
||||||
|
.jj/
|
||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
|
|
||||||
* {
|
* {
|
||||||
/* General */
|
/* General */
|
||||||
font: "Hack Nerd Font 60";
|
font: "Hack Nerd Font Mono 60";
|
||||||
|
|
||||||
/* option menus: i3-layout, music, power and screenshot
|
/* option menus: i3-layout, music, power and screenshot
|
||||||
*
|
*
|
||||||
@@ -13,7 +13,6 @@
|
|||||||
* around using this character: ■
|
* around using this character: ■
|
||||||
* We then add add 100 actual padding around the icons.
|
* We then add add 100 actual padding around the icons.
|
||||||
* -12px 0px -19px -96px */
|
* -12px 0px -19px -96px */
|
||||||
option-element-padding: 1% 1% 1% 1%;
|
|
||||||
option-5-window-padding: 4% 4%;
|
option-5-window-padding: 4% 4%;
|
||||||
option-5-listview-spacing: 15px;
|
option-5-listview-spacing: 15px;
|
||||||
|
|
||||||
@@ -46,7 +45,7 @@
|
|||||||
layout: horizontal;
|
layout: horizontal;
|
||||||
}
|
}
|
||||||
element {
|
element {
|
||||||
padding: 40px 68px 43px 30px;
|
padding: 40px 62px 40px 36px;
|
||||||
}
|
}
|
||||||
#window {
|
#window {
|
||||||
padding: 20px;
|
padding: 20px;
|
||||||
|
|||||||
@@ -15,10 +15,13 @@ in
|
|||||||
|
|
||||||
config = lib.mkIf cfg.enable {
|
config = lib.mkIf cfg.enable {
|
||||||
|
|
||||||
|
home.packages = [ pkgs.jj-starship ];
|
||||||
|
|
||||||
programs.starship = {
|
programs.starship = {
|
||||||
enable = true;
|
enable = true;
|
||||||
enableFishIntegration = true;
|
enableFishIntegration = true;
|
||||||
enableBashIntegration = true;
|
enableBashIntegration = true;
|
||||||
|
enableTransience = true; # Replace previous prompts with custom string
|
||||||
settings = {
|
settings = {
|
||||||
add_newline = false; # Don't print new line at the start of the prompt
|
add_newline = false; # Don't print new line at the start of the prompt
|
||||||
format = lib.concatStrings [
|
format = lib.concatStrings [
|
||||||
@@ -26,6 +29,7 @@ in
|
|||||||
"$git_branch"
|
"$git_branch"
|
||||||
"$git_commit"
|
"$git_commit"
|
||||||
"$git_status"
|
"$git_status"
|
||||||
|
"\${custom.jj}"
|
||||||
"$hostname"
|
"$hostname"
|
||||||
"$cmd_duration"
|
"$cmd_duration"
|
||||||
"$character"
|
"$character"
|
||||||
@@ -37,23 +41,37 @@ in
|
|||||||
vicmd_symbol = "[❮](bold green)";
|
vicmd_symbol = "[❮](bold green)";
|
||||||
};
|
};
|
||||||
cmd_duration = {
|
cmd_duration = {
|
||||||
min_time = 5000;
|
min_time = 5001;
|
||||||
show_notifications = if pkgs.stdenv.isLinux then false else true;
|
show_notifications = if pkgs.stdenv.hostPlatform.isLinux then false else true;
|
||||||
min_time_to_notify = 30000;
|
min_time_to_notify = 30000;
|
||||||
format = "[$duration]($style) ";
|
format = "[$duration]($style) ";
|
||||||
};
|
};
|
||||||
|
custom = {
|
||||||
|
jj = {
|
||||||
|
when = "jj-starship detect";
|
||||||
|
shell = [
|
||||||
|
"jj-starship"
|
||||||
|
"--no-jj-prefix"
|
||||||
|
"--no-git-prefix"
|
||||||
|
];
|
||||||
|
format = "$output ";
|
||||||
|
};
|
||||||
|
};
|
||||||
directory = {
|
directory = {
|
||||||
truncate_to_repo = true;
|
truncate_to_repo = true;
|
||||||
truncation_length = 100;
|
truncation_length = 100;
|
||||||
};
|
};
|
||||||
git_branch = {
|
git_branch = {
|
||||||
|
disabled = true;
|
||||||
format = "[$symbol$branch]($style)";
|
format = "[$symbol$branch]($style)";
|
||||||
};
|
};
|
||||||
git_commit = {
|
git_commit = {
|
||||||
|
disabled = true;
|
||||||
format = "( @ [$hash]($style) )";
|
format = "( @ [$hash]($style) )";
|
||||||
only_detached = false;
|
only_detached = false;
|
||||||
};
|
};
|
||||||
git_status = {
|
git_status = {
|
||||||
|
disabled = true;
|
||||||
format = "([$all_status$ahead_behind]($style) )";
|
format = "([$all_status$ahead_behind]($style) )";
|
||||||
conflicted = "=";
|
conflicted = "=";
|
||||||
ahead = "⇡";
|
ahead = "⇡";
|
||||||
@@ -80,6 +98,17 @@ in
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
programs.fish = {
|
||||||
|
functions = {
|
||||||
|
# Adjust the prompt in previous commands
|
||||||
|
starship_transient_prompt_func = {
|
||||||
|
body = "echo '$ '";
|
||||||
|
};
|
||||||
|
starship_transient_rprompt_func = {
|
||||||
|
body = "echo ' '";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,17 @@
|
|||||||
|
-----BEGIN AGE ENCRYPTED FILE-----
|
||||||
|
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IHNzaC1lZDI1NTE5IE1nSGFPdyBTYTRy
|
||||||
|
elYzTGpSNDQ3UEcwTXlVeGJleUJmWWhaeDdDQTFRcGpmNlNrQlNVCjA5L2JrS3Vx
|
||||||
|
Q0cyRkk5dTBLOHJXa0xJSG9MTDFnNjV1M0F5L3F5RUlVbW8KLT4gc3NoLWVkMjU1
|
||||||
|
MTkgWXlTVU1RIG5vNm1Xem9lN2pkS25WRi9xSlpZUjhuYmdUVDUvc2o4M0xqYURR
|
||||||
|
UmY0VGcKWVVQc2wyV0Jqbk9JR3N4bW5HOXFTZHpCa25EMC85eThQY05MdHdaeXZy
|
||||||
|
VQotPiBzc2gtZWQyNTUxOSBuanZYNUEgWXRVa3c4STZ3WmFaNThSdE1QdVpiMVR1
|
||||||
|
cm5hYXJsckZiRGtXLzN5RzJEawpkVHBscFd2c0R1SGxnZ3lKUnNnMEZtTUxoQlB4
|
||||||
|
dVBEbTkvUzBJSVRiV1hBCi0+IHNzaC1lZDI1NTE5IENxSU9VQSAvQjhVam1heHNU
|
||||||
|
elVrVGtvaUx1elFCeTdNTkRnN3c5NEc5MWg4dDU3NUhzCm5sUlhHclJrNldnVDhF
|
||||||
|
MTV2cGd3ZFhFdm1rM2ExWVFXbkNJYWlWY0VnUmsKLT4gc3NoLWVkMjU1MTkgejFP
|
||||||
|
Y1p3IGc1QUdkZEp0Z0xEekFjcHd4WVFVam9BZTBEQm9NR3QzQmxNS09VVXpHV2sK
|
||||||
|
c2tYSElVK2prRlF3VlFqKzlVUFRHUWU3TmFXcEdsV2FKWVhKT3pWZkxVNAotLS0g
|
||||||
|
c1cxdk5sL1c3dDZuVGp5VWJrTlBGZTByNjRxMGxTdHd0NFNHV1pyN2k5Ywr7SW9q
|
||||||
|
/FaTTUHB5QiCihA+385sNogq7Q1RvgT2Dwn9NdmMRd/ObESbokJXVSiDDEt6d39s
|
||||||
|
D/uoDY20p3PCk4julNn1
|
||||||
|
-----END AGE ENCRYPTED FILE-----
|
||||||
@@ -0,0 +1,106 @@
|
|||||||
|
{
|
||||||
|
config,
|
||||||
|
pkgs,
|
||||||
|
lib,
|
||||||
|
...
|
||||||
|
}:
|
||||||
|
|
||||||
|
let
|
||||||
|
inherit (config.nmasur.settings) hostnames;
|
||||||
|
cfg = config.nmasur.presets.programs.thunderbird;
|
||||||
|
in
|
||||||
|
|
||||||
|
{
|
||||||
|
|
||||||
|
options.nmasur.presets.programs.thunderbird = {
|
||||||
|
enable = lib.mkEnableOption "Thunderbird email client";
|
||||||
|
calendar = {
|
||||||
|
username = lib.mkOption {
|
||||||
|
type = lib.types.str;
|
||||||
|
description = "Username for the calendar service backend";
|
||||||
|
default = config.nmasur.settings.username;
|
||||||
|
};
|
||||||
|
passwordCommand = lib.mkOption {
|
||||||
|
type = lib.types.str;
|
||||||
|
description = "Password for the calendar service backend";
|
||||||
|
default = config.accounts.email.accounts.home.passwordCommand;
|
||||||
|
};
|
||||||
|
hostname = lib.mkOption {
|
||||||
|
type = lib.types.str;
|
||||||
|
description = "Hostname for the calendar service backend";
|
||||||
|
default = hostnames.content;
|
||||||
|
};
|
||||||
|
url = lib.mkOption {
|
||||||
|
type = lib.types.str;
|
||||||
|
description = "URL for the calendar service backend";
|
||||||
|
default = "https://${cfg.calendar.hostname}/remote.php/dav";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
tasks = {
|
||||||
|
username = lib.mkOption {
|
||||||
|
type = lib.types.str;
|
||||||
|
description = "Username for the tasks service backend";
|
||||||
|
default = config.nmasur.settings.username;
|
||||||
|
};
|
||||||
|
passwordCommand = lib.mkOption {
|
||||||
|
type = lib.types.str;
|
||||||
|
description = "Password for the tasks service backend";
|
||||||
|
default = "${lib.getExe pkgs.age} --decrypt --identity ~/.ssh/id_ed25519 ${pkgs.writeText "taskspass.age" (builtins.readFile ./taskspass.age)}";
|
||||||
|
};
|
||||||
|
hostname = lib.mkOption {
|
||||||
|
type = lib.types.str;
|
||||||
|
description = "Hostname for the tasks service backend";
|
||||||
|
default = hostnames.content;
|
||||||
|
};
|
||||||
|
url = lib.mkOption {
|
||||||
|
type = lib.types.str;
|
||||||
|
description = "URL for the tasks service backend";
|
||||||
|
default = "https://${cfg.tasks.hostname}/remote.php/dav";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
config = lib.mkIf cfg.enable {
|
||||||
|
|
||||||
|
programs.thunderbird = {
|
||||||
|
enable = true;
|
||||||
|
profiles.default = {
|
||||||
|
isDefault = true;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
accounts.email.accounts.home.thunderbird = {
|
||||||
|
enable = true;
|
||||||
|
profiles = [ "default" ];
|
||||||
|
};
|
||||||
|
accounts.calendar.basePath = "other/calendars"; # Where to save calendars in ~ directory
|
||||||
|
# accounts.calendar.accounts.home = {
|
||||||
|
# local.type = "filesystem";
|
||||||
|
# primary = true;
|
||||||
|
# remote = {
|
||||||
|
# passwordCommand = [ cfg.calendar.passwordCommand ];
|
||||||
|
# type = "caldav";
|
||||||
|
# url = cfg.calendar.url;
|
||||||
|
# userName = cfg.calendar.username;
|
||||||
|
# };
|
||||||
|
# thunderbird = {
|
||||||
|
# enable = true;
|
||||||
|
# profiles = [ "default" ];
|
||||||
|
# };
|
||||||
|
# };
|
||||||
|
# accounts.calendar.accounts.tasks = {
|
||||||
|
# local.type = "filesystem";
|
||||||
|
# primary = false;
|
||||||
|
# remote = {
|
||||||
|
# passwordCommand = [ cfg.tasks.passwordCommand ];
|
||||||
|
# type = "caldav";
|
||||||
|
# url = cfg.tasks.url;
|
||||||
|
# userName = cfg.tasks.username;
|
||||||
|
# };
|
||||||
|
# thunderbird = {
|
||||||
|
# enable = true;
|
||||||
|
# profiles = [ "default" ];
|
||||||
|
# };
|
||||||
|
# };
|
||||||
|
|
||||||
|
};
|
||||||
|
}
|
||||||
@@ -105,7 +105,7 @@ in
|
|||||||
}
|
}
|
||||||
|
|
||||||
config.font = wezterm.font('${cfg.font}', { weight = 'Bold'})
|
config.font = wezterm.font('${cfg.font}', { weight = 'Bold'})
|
||||||
config.font_size = ${if pkgs.stdenv.isLinux then "14.0" else "18.0"}
|
config.font_size = ${if pkgs.stdenv.hostPlatform.isLinux then "14.0" else "18.0"}
|
||||||
|
|
||||||
-- Fix color blocks instead of text
|
-- Fix color blocks instead of text
|
||||||
config.front_end = "WebGpu"
|
config.front_end = "WebGpu"
|
||||||
@@ -114,7 +114,7 @@ in
|
|||||||
config.hide_tab_bar_if_only_one_tab = true
|
config.hide_tab_bar_if_only_one_tab = true
|
||||||
config.window_frame = {
|
config.window_frame = {
|
||||||
font = wezterm.font('${cfg.font}', { weight = 'Bold'}),
|
font = wezterm.font('${cfg.font}', { weight = 'Bold'}),
|
||||||
font_size = ${if pkgs.stdenv.isLinux then "12.0" else "16.0"},
|
font_size = ${if pkgs.stdenv.hostPlatform.isLinux then "12.0" else "16.0"},
|
||||||
}
|
}
|
||||||
|
|
||||||
config.colors = {
|
config.colors = {
|
||||||
@@ -191,7 +191,7 @@ in
|
|||||||
-- super-t open new tab in new dir
|
-- super-t open new tab in new dir
|
||||||
{
|
{
|
||||||
key = 't',
|
key = 't',
|
||||||
mods = ${if pkgs.stdenv.isDarwin then "'SUPER'" else "'ALT'"},
|
mods = ${if pkgs.stdenv.hostPlatform.isDarwin then "'SUPER'" else "'ALT'"},
|
||||||
action = wezterm.action.SpawnCommandInNewTab {
|
action = wezterm.action.SpawnCommandInNewTab {
|
||||||
cwd = wezterm.home_dir,
|
cwd = wezterm.home_dir,
|
||||||
},
|
},
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user