Compare commits

...

No commits in common. "9a53ca1cea4bbf5b929306924a55a1f8f2589a79" and "507d20390c294466a22ad8722341e7510f28222c" have entirely different histories.

90 changed files with 1047 additions and 4959 deletions

2
.clang-format Normal file
View file

@ -0,0 +1,2 @@
---
BasedOnStyle: LLVM

8
.gdbinit Normal file
View file

@ -0,0 +1,8 @@
file /nix/store/ijxm784gr0sx5p4d92rlag0ippyd0mvm-am-kernel-riscv32-none-elf-2024-07-10/libexec/am-kernels/demo
set substitute-path /build/am-kernels /home/xin/repo/ysyx-workbench/am-kernels
set substitute-path /build/abstract-machine /home/xin/repo/ysyx-workbench/abstract-machine
# set debug remote 1
target remote /tmp/gdbstub-diffu.sock
break *halt + 24

1
.gitattributes vendored
View file

@ -1 +0,0 @@
eval_secrets.nix diff=sops

View file

@ -0,0 +1,20 @@
name: Build nix packages
on: [push]
jobs:
build-matrix:
runs-on: nix
strategy:
matrix:
package: [ "default" ]
steps:
- uses: https://github.com/cachix/cachix-action@v14
with:
name: ysyx
authToken: '${{ secrets.CACHIX_SIGNING_KEY }}'
- uses: actions/checkout@v4
- name: Build
run: |
nix build -L .#${{ matrix.package }}

141
.gitignore vendored
View file

@ -1,3 +1,138 @@
.direnv
.vscode
result
.cache/
.vscode/
.direnv/
build/
.pre-commit-config.yaml
# Created by https://www.toptal.com/developers/gitignore/api/c++,c,cmake
# Edit at https://www.toptal.com/developers/gitignore?templates=c++,c,cmake
### C ###
# Prerequisites
*.d
# Object files
*.o
*.ko
*.obj
*.elf
# Linker output
*.ilk
*.map
*.exp
# Precompiled Headers
*.gch
*.pch
# Libraries
*.lib
*.a
*.la
*.lo
# Shared objects (inc. Windows DLLs)
*.dll
*.so
*.so.*
*.dylib
# Executables
*.exe
*.out
*.app
*.i*86
*.x86_64
*.hex
# Debug files
*.dSYM/
*.su
*.idb
*.pdb
# Kernel Module Compile Results
*.mod*
*.cmd
.tmp_versions/
modules.order
Module.symvers
Mkfile.old
dkms.conf
### C++ ###
# Prerequisites
# Compiled Object files
*.slo
# Precompiled Headers
# Compiled Dynamic libraries
# Fortran module files
*.mod
*.smod
# Compiled Static libraries
*.lai
# Executables
### CMake ###
CMakeLists.txt.user
CMakeCache.txt
CMakeFiles
CMakeScripts
Testing
Makefile
cmake_install.cmake
install_manifest.txt
compile_commands.json
CTestTestfile.cmake
_deps
### CMake Patch ###
# External projects
*-prefix/
# End of https://www.toptal.com/developers/gitignore/api/c++,c,cmake
# Created by https://www.toptal.com/developers/gitignore/api/c++
# Edit at https://www.toptal.com/developers/gitignore?templates=c++
### C++ ###
# Prerequisites
*.d
# Compiled Object files
*.slo
*.lo
*.o
*.obj
# Precompiled Headers
*.gch
*.pch
# Compiled Dynamic libraries
*.so
*.dylib
*.dll
# Fortran module files
*.mod
*.smod
# Compiled Static libraries
*.lai
*.la
*.a
*.lib
# Executables
*.exe
*.out
*.app
# End of https://www.toptal.com/developers/gitignore/api/c++

View file

@ -1,61 +0,0 @@
keys:
- &xin age1uw059wcwfvd9xuj0hpqzqpeg7qemecspjrsatg37wc7rs2pumfdsgken0c
- &host-calcite age1ytwfqfeez3dqtazyjltn7mznccwx3ua8djhned7n8mxqhw4p6e5s97skfa
- &host-raspite age1nugzw24upk8pz5lyz2z89qk8se4gpcsg3ypcs58nykncr56sevrsm8qpvj
- &host-sgp-00 age13s6rwd3wjk2x5wkn69tdczhl3l5d7mfmlv90efsv4q67jne43qss9tcakx
- &host-tok-00 age1t5nw2jx4dw67jkf72uxcxt72j7lq3xyj35lvl09f8kala90h2g2s2a5yvj
- &host-la-00 age1fw2sqaa5s9c8ml6ncsexkj8ar4288387ju92ytjys4awf9aw6smqqz94dh
- &host-massicot age1jle2auermhswqtehww9gqada8car5aczrx43ztzqf9wtcld0sfmqzaecta
- &host-weilite age17r3fxfmt6hgwe984w4lds9u0cnkf5ttq8hnqt800ayfmx7t8t5gqjddyml
creation_rules:
- path_regex: machines/calcite/secrets.yaml
key_groups:
- age:
- *xin
- *host-calcite
- path_regex: machines/raspite/secrets.yaml
key_groups:
- age:
- *xin
- *host-raspite
- path_regex: machines/massicot/secrets.yaml
key_groups:
- age:
- *xin
- *host-massicot
- path_regex: machines/dolomite/secrets/sgp-00.yaml
key_groups:
- age:
- *xin
- *host-sgp-00
- path_regex: machines/dolomite/secrets/tok-00.yaml
key_groups:
- age:
- *xin
- *host-tok-00
- path_regex: machines/dolomite/secrets/la-00.yaml
key_groups:
- age:
- *xin
- *host-la-00
- path-regex: machines/weilite/secrets.yaml
key_groups:
- age:
- *xin
- *host-weilite
- path_regex: machines/secrets.yaml
key_groups:
- age:
- *xin
- *host-calcite
- *host-raspite
- *host-sgp-00
- *host-tok-00
- *host-la-00
- *host-massicot
- path_regex: home/xin/secrets.yaml
key_groups:
- age:
- *xin
- *host-raspite
- *host-calcite

12
CMakeLists.txt Normal file
View file

@ -0,0 +1,12 @@
cmake_minimum_required(VERSION 3.26)
project(difftest)
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_C_STANDARD 17)
include(GNUInstallDirs)
find_package(spdlog REQUIRED)
include_directories(include)
add_subdirectory(src)

24
LICENSE
View file

@ -1,24 +0,0 @@
This is free and unencumbered software released into the public domain.
Anyone is free to copy, modify, publish, use, compile, sell, or
distribute this software, either in source code form or as a compiled
binary, for any purpose, commercial or non-commercial, and by any
means.
In jurisdictions that recognize copyright laws, the author or authors
of this software dedicate any and all copyright interest in the
software to the public domain. We make this dedication for the benefit
of the public at large and to the detriment of our heirs and
successors. We intend this dedication to be an overt act of
relinquishment in perpetuity of all present and future rights to this
software under copyright law.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
OTHER DEALINGS IN THE SOFTWARE.
For more information, please refer to <https://unlicense.org>

1
README.md Normal file
View file

@ -0,0 +1 @@
# diffu

19
default.nix Normal file
View file

@ -0,0 +1,19 @@
{ lib
, stdenv
, cmake
, mini-gdbstub
, cli11
, spdlog
}: stdenv.mkDerivation {
pname = "diffu";
version = "0.0.0";
src = ./.;
nativeBuildInputs = [
cmake
mini-gdbstub
cli11
spdlog
];
}

17
difftest.toml Normal file
View file

@ -0,0 +1,17 @@
# ref = "/home/xin/repo/spike-diff/build/lib/libspike-diff.so"
# ref-prefix = "spike_"
ref= "/home/xin/repo/ysyx-workbench/nemu/build/riscv32-nemu-interpreter-so"
ref-prefix = "nemu_"
# dut = "/home/xin/repo/ysyx-workbench/nemu/build/riscv32-nemu-interpreter-so"
# dut-prefix = "nemu_"
dut = "/home/xin/repo/ysyx-workbench/npc/build/csrc/Flow/libFlow.so"
dut-prefix = "npc_"
# dut = "/home/xin/repo/ysyx-workbench/nemu/build/riscv32-nemu-interpreter-so"
# dut-prefix = "nemu_"
listen = "/tmp/gdbstub-diffu.sock"
# listen = "127.0.0.1:1234"
images-path = "/nix/store/z7mc0y608145cfwlb2g1gsii7bij7li1-am-kernel-riscv32-none-elf-2024-07-10/share/am-kernels"
memory = "bench.bin"
# g = true

View file

@ -1,100 +1,6 @@
{
"nodes": {
"catppuccin": {
"locked": {
"lastModified": 1724156255,
"narHash": "sha256-rpUCeS/QZwQdJmDrvCm0hRi8bFvQNQKAnIMK5ZDBfpM=",
"owner": "catppuccin",
"repo": "nix",
"rev": "8886a68edadb1d93c7101337f995ffce4b410ff2",
"type": "github"
},
"original": {
"owner": "catppuccin",
"repo": "nix",
"type": "github"
}
},
"colmena": {
"inputs": {
"flake-compat": "flake-compat",
"flake-utils": [
"flake-utils"
],
"nixpkgs": [
"nixpkgs"
],
"stable": [
"nixpkgs"
]
},
"locked": {
"lastModified": 1711386353,
"narHash": "sha256-gWEpb8Hybnoqb4O4tmpohGZk6+aerAbJpywKcFIiMlg=",
"owner": "zhaofengli",
"repo": "colmena",
"rev": "cd65ef7a25cdc75052fbd04b120aeb066c3881db",
"type": "github"
},
"original": {
"owner": "zhaofengli",
"repo": "colmena",
"type": "github"
}
},
"devshell": {
"inputs": {
"nixpkgs": [
"my-nixvim",
"nixvim",
"nixpkgs"
]
},
"locked": {
"lastModified": 1722113426,
"narHash": "sha256-Yo/3loq572A8Su6aY5GP56knpuKYRvM2a1meP9oJZCw=",
"owner": "numtide",
"repo": "devshell",
"rev": "67cce7359e4cd3c45296fb4aaf6a19e2a9c757ae",
"type": "github"
},
"original": {
"owner": "numtide",
"repo": "devshell",
"type": "github"
}
},
"flake-compat": {
"flake": false,
"locked": {
"lastModified": 1650374568,
"narHash": "sha256-Z+s0J8/r907g149rllvwhb4pKi8Wam5ij0st8PwAh+E=",
"owner": "edolstra",
"repo": "flake-compat",
"rev": "b4a34015c698c7793d592d66adbab377907a2be8",
"type": "github"
},
"original": {
"owner": "edolstra",
"repo": "flake-compat",
"type": "github"
}
},
"flake-compat_2": {
"locked": {
"lastModified": 1696426674,
"narHash": "sha256-kvjfFW7WAETZlt09AgDn1MrtKzP7t90Vf7vypd3OL1U=",
"rev": "0f9255e01c2351cc7d116c072cb317785dd33b33",
"revCount": 57,
"type": "tarball",
"url": "https://api.flakehub.com/f/pinned/edolstra/flake-compat/1.0.1/018afb31-abd1-7bff-a5e4-cff7e18efb7a/source.tar.gz"
},
"original": {
"type": "tarball",
"url": "https://flakehub.com/f/edolstra/flake-compat/1.tar.gz"
}
},
"flake-compat_3": {
"flake": false,
"locked": {
"lastModified": 1696426674,
@ -110,46 +16,6 @@
"type": "github"
}
},
"flake-parts": {
"inputs": {
"nixpkgs-lib": "nixpkgs-lib"
},
"locked": {
"lastModified": 1722555600,
"narHash": "sha256-XOQkdLafnb/p9ij77byFQjDf5m5QYl9b2REiVClC+x4=",
"owner": "hercules-ci",
"repo": "flake-parts",
"rev": "8471fe90ad337a8074e957b69ca4d0089218391d",
"type": "github"
},
"original": {
"owner": "hercules-ci",
"repo": "flake-parts",
"type": "github"
}
},
"flake-parts_2": {
"inputs": {
"nixpkgs-lib": [
"my-nixvim",
"nixvim",
"nixpkgs"
]
},
"locked": {
"lastModified": 1722555600,
"narHash": "sha256-XOQkdLafnb/p9ij77byFQjDf5m5QYl9b2REiVClC+x4=",
"owner": "hercules-ci",
"repo": "flake-parts",
"rev": "8471fe90ad337a8074e957b69ca4d0089218391d",
"type": "github"
},
"original": {
"owner": "hercules-ci",
"repo": "flake-parts",
"type": "github"
}
},
"flake-utils": {
"inputs": {
"systems": "systems"
@ -186,45 +52,10 @@
"type": "github"
}
},
"git-hooks": {
"inputs": {
"flake-compat": [
"my-nixvim",
"nixvim",
"flake-compat"
],
"gitignore": "gitignore",
"nixpkgs": [
"my-nixvim",
"nixvim",
"nixpkgs"
],
"nixpkgs-stable": [
"my-nixvim",
"nixvim",
"nixpkgs"
]
},
"locked": {
"lastModified": 1723803910,
"narHash": "sha256-yezvUuFiEnCFbGuwj/bQcqg7RykIEqudOy/RBrId0pc=",
"owner": "cachix",
"repo": "git-hooks.nix",
"rev": "bfef0ada09e2c8ac55bbcd0831bd0c9d42e651ba",
"type": "github"
},
"original": {
"owner": "cachix",
"repo": "git-hooks.nix",
"type": "github"
}
},
"gitignore": {
"inputs": {
"nixpkgs": [
"my-nixvim",
"nixvim",
"git-hooks",
"pre-commit-hooks",
"nixpkgs"
]
},
@ -242,159 +73,13 @@
"type": "github"
}
},
"home-manager": {
"inputs": {
"nixpkgs": [
"nixpkgs"
]
},
"locked": {
"lastModified": 1723986931,
"narHash": "sha256-Fy+KEvDQ+Hc8lJAV3t6leXhZJ2ncU5/esxkgt3b8DEY=",
"owner": "nix-community",
"repo": "home-manager",
"rev": "2598861031b78aadb4da7269df7ca9ddfc3e1671",
"type": "github"
},
"original": {
"owner": "nix-community",
"repo": "home-manager",
"type": "github"
}
},
"home-manager_2": {
"inputs": {
"nixpkgs": [
"my-nixvim",
"nixvim",
"nixpkgs"
]
},
"locked": {
"lastModified": 1723986931,
"narHash": "sha256-Fy+KEvDQ+Hc8lJAV3t6leXhZJ2ncU5/esxkgt3b8DEY=",
"owner": "nix-community",
"repo": "home-manager",
"rev": "2598861031b78aadb4da7269df7ca9ddfc3e1671",
"type": "github"
},
"original": {
"owner": "nix-community",
"repo": "home-manager",
"type": "github"
}
},
"my-nixvim": {
"inputs": {
"flake-parts": "flake-parts",
"nixpkgs": [
"nixpkgs"
],
"nixvim": "nixvim"
},
"locked": {
"lastModified": 1724158316,
"narHash": "sha256-cz2N0vPfe0jmjxqKWh7dgVecLqmPLHQrvxGJk0atDbg=",
"ref": "refs/heads/master",
"rev": "a5eb7fe89ee8ba654f339d8f75cecb39851743ec",
"revCount": 4,
"type": "git",
"url": "https://git.xinyang.life/xin/nixvim"
},
"original": {
"type": "git",
"url": "https://git.xinyang.life/xin/nixvim"
}
},
"nix-darwin": {
"inputs": {
"nixpkgs": [
"my-nixvim",
"nixvim",
"nixpkgs"
]
},
"locked": {
"lastModified": 1723859949,
"narHash": "sha256-kiaGz4deGYKMjJPOji/JVvSP/eTefrIA3rAjOnOpXl4=",
"owner": "lnl7",
"repo": "nix-darwin",
"rev": "076b9a905af8a52b866c8db068d6da475839d97b",
"type": "github"
},
"original": {
"owner": "lnl7",
"repo": "nix-darwin",
"type": "github"
}
},
"nix-index-database": {
"inputs": {
"nixpkgs": [
"nixpkgs"
]
},
"locked": {
"lastModified": 1723950649,
"narHash": "sha256-dHMkGjwwCGj0c2MKyCjRXVBXq2Sz3TWbbM23AS7/5Hc=",
"owner": "Mic92",
"repo": "nix-index-database",
"rev": "392828aafbed62a6ea6ccab13728df2e67481805",
"type": "github"
},
"original": {
"owner": "Mic92",
"repo": "nix-index-database",
"type": "github"
}
},
"nix-vscode-extensions": {
"inputs": {
"flake-compat": "flake-compat_3",
"flake-utils": [
"flake-utils"
],
"nixpkgs": [
"nixpkgs"
]
},
"locked": {
"lastModified": 1724117347,
"narHash": "sha256-/nfm6P0owPtCRjT8ktq/8OChtg2HpkrvNaDJGm9N1Lk=",
"owner": "nix-community",
"repo": "nix-vscode-extensions",
"rev": "2ef60116ef361d988317cbe52a09acfeda7d3416",
"type": "github"
},
"original": {
"owner": "nix-community",
"repo": "nix-vscode-extensions",
"type": "github"
}
},
"nixos-hardware": {
"locked": {
"lastModified": 1724067415,
"narHash": "sha256-WJBAEFXAtA41RMpK8mvw0cQ62CJkNMBtzcEeNIJV7b0=",
"owner": "NixOS",
"repo": "nixos-hardware",
"rev": "b09c46430ffcf18d575acf5c339b38ac4e1db5d2",
"type": "github"
},
"original": {
"owner": "NixOS",
"ref": "master",
"repo": "nixos-hardware",
"type": "github"
}
},
"nixpkgs": {
"locked": {
"lastModified": 1723991338,
"narHash": "sha256-Grh5PF0+gootJfOJFenTTxDTYPidA3V28dqJ/WV7iis=",
"lastModified": 1711703276,
"narHash": "sha256-iMUFArF0WCatKK6RzfUJknjem0H9m4KgorO/p3Dopkk=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "8a3354191c0d7144db9756a74755672387b702ba",
"rev": "d8fe5e6c92d0d190646fb9f1056741a229980089",
"type": "github"
},
"original": {
@ -404,165 +89,72 @@
"type": "github"
}
},
"nixpkgs-lib": {
"locked": {
"lastModified": 1722555339,
"narHash": "sha256-uFf2QeW7eAHlYXuDktm9c25OxOyCoUOQmh5SZ9amE5Q=",
"type": "tarball",
"url": "https://github.com/NixOS/nixpkgs/archive/a5d394176e64ab29c852d03346c1fc9b0b7d33eb.tar.gz"
},
"original": {
"type": "tarball",
"url": "https://github.com/NixOS/nixpkgs/archive/a5d394176e64ab29c852d03346c1fc9b0b7d33eb.tar.gz"
}
},
"nixpkgs-stable": {
"locked": {
"lastModified": 1723938990,
"narHash": "sha256-9tUadhnZQbWIiYVXH8ncfGXGvkNq3Hag4RCBEMUk7MI=",
"owner": "nixos",
"repo": "nixpkgs",
"rev": "c42fcfbdfeae23e68fc520f9182dde9f38ad1890",
"type": "github"
},
"original": {
"owner": "nixos",
"ref": "nixos-24.05",
"repo": "nixpkgs",
"type": "github"
}
},
"nixpkgs-stable_2": {
"locked": {
"lastModified": 1721524707,
"narHash": "sha256-5NctRsoE54N86nWd0psae70YSLfrOek3Kv1e8KoXe/0=",
"lastModified": 1710695816,
"narHash": "sha256-3Eh7fhEID17pv9ZxrPwCLfqXnYP006RKzSs0JptsN84=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "556533a23879fc7e5f98dd2e0b31a6911a213171",
"rev": "614b4613980a522ba49f0d194531beddbb7220d3",
"type": "github"
},
"original": {
"owner": "NixOS",
"ref": "release-24.05",
"ref": "nixos-23.11",
"repo": "nixpkgs",
"type": "github"
}
},
"nixpkgs_2": {
"locked": {
"lastModified": 1724160083,
"narHash": "sha256-ROiCJNYSbjO45ajyTfRxp+aqvX+R1M3xwlWOLtfD0iw=",
"owner": "xinyangli",
"repo": "nixpkgs",
"rev": "885d5117645517b70eb3922acfbb83226fc77dbb",
"type": "github"
},
"original": {
"owner": "xinyangli",
"ref": "deploy",
"repo": "nixpkgs",
"type": "github"
}
},
"nixvim": {
"nur-xin": {
"inputs": {
"devshell": "devshell",
"flake-compat": "flake-compat_2",
"flake-parts": "flake-parts_2",
"git-hooks": "git-hooks",
"home-manager": "home-manager_2",
"nix-darwin": "nix-darwin",
"nixpkgs": "nixpkgs",
"nuschtosSearch": "nuschtosSearch",
"treefmt-nix": "treefmt-nix"
},
"locked": {
"lastModified": 1724127528,
"narHash": "sha256-fKtsvNQeLhPuz1O53x6Xxkd/yYecpolNXRq7mfvnXQk=",
"owner": "nix-community",
"repo": "nixvim",
"rev": "cb413995e1e101c76d755b7f131ce60c7ea3985d",
"type": "github"
},
"original": {
"owner": "nix-community",
"repo": "nixvim",
"type": "github"
}
},
"nur": {
"locked": {
"lastModified": 1724159175,
"narHash": "sha256-3z9wRL+h+gTVFtecCUGrRaW6nvPPAtBCIDE9KAmZj7c=",
"owner": "nix-community",
"repo": "NUR",
"rev": "0b86d5643d99e3982471f0d79e553871c6f35396",
"type": "github"
},
"original": {
"owner": "nix-community",
"repo": "NUR",
"type": "github"
}
},
"nuschtosSearch": {
"inputs": {
"flake-utils": "flake-utils_2",
"nixpkgs": [
"my-nixvim",
"nixvim",
"nixpkgs"
]
},
"locked": {
"lastModified": 1723969429,
"narHash": "sha256-BuewfNEXEf11MIkJY+uvWsdLu1dIvgJqntWChvNdALg=",
"owner": "NuschtOS",
"repo": "search",
"rev": "a05d1805f2a2bc47d230e5e92aecbf69f784f3d0",
"lastModified": 1721891452,
"narHash": "sha256-2c9nDuXXARzoRXE67lte5kKBeFb1XmTNsvdiIbRUEgE=",
"ref": "refs/heads/master",
"rev": "de8ad578fc4fe527772cec23a7f660bde14c8570",
"revCount": 152,
"type": "git",
"url": "https://git.xinyang.life/xin/nur.git"
},
"original": {
"type": "git",
"url": "https://git.xinyang.life/xin/nur.git"
}
},
"pre-commit-hooks": {
"inputs": {
"flake-compat": "flake-compat",
"flake-utils": "flake-utils_2",
"gitignore": "gitignore",
"nixpkgs": [
"nixpkgs"
],
"nixpkgs-stable": "nixpkgs-stable"
},
"locked": {
"lastModified": 1712055707,
"narHash": "sha256-4XLvuSIDZJGS17xEwSrNuJLL7UjDYKGJSbK1WWX2AK8=",
"owner": "cachix",
"repo": "pre-commit-hooks.nix",
"rev": "e35aed5fda3cc79f88ed7f1795021e559582093a",
"type": "github"
},
"original": {
"owner": "NuschtOS",
"repo": "search",
"owner": "cachix",
"repo": "pre-commit-hooks.nix",
"type": "github"
}
},
"root": {
"inputs": {
"catppuccin": "catppuccin",
"colmena": "colmena",
"flake-utils": "flake-utils",
"home-manager": "home-manager",
"my-nixvim": "my-nixvim",
"nix-index-database": "nix-index-database",
"nix-vscode-extensions": "nix-vscode-extensions",
"nixos-hardware": "nixos-hardware",
"nixpkgs": "nixpkgs_2",
"nixpkgs-stable": "nixpkgs-stable",
"nur": "nur",
"sops-nix": "sops-nix"
}
},
"sops-nix": {
"inputs": {
"nixpkgs": [
"nixpkgs"
],
"nixpkgs-stable": "nixpkgs-stable_2"
},
"locked": {
"lastModified": 1723501126,
"narHash": "sha256-N9IcHgj/p1+2Pvk8P4Zc1bfrMwld5PcosVA0nL6IGdE=",
"owner": "Mic92",
"repo": "sops-nix",
"rev": "be0eec2d27563590194a9206f551a6f73d52fa34",
"type": "github"
},
"original": {
"owner": "Mic92",
"repo": "sops-nix",
"type": "github"
"nixpkgs": "nixpkgs",
"nur-xin": "nur-xin",
"pre-commit-hooks": "pre-commit-hooks"
}
},
"systems": {
@ -594,28 +186,6 @@
"repo": "default",
"type": "github"
}
},
"treefmt-nix": {
"inputs": {
"nixpkgs": [
"my-nixvim",
"nixvim",
"nixpkgs"
]
},
"locked": {
"lastModified": 1723808491,
"narHash": "sha256-rhis3qNuGmJmYC/okT7Dkc4M8CeUuRCSvW6kC2f3hBc=",
"owner": "numtide",
"repo": "treefmt-nix",
"rev": "1d07739554fdc4f8481068f1b11d6ab4c1a4167a",
"type": "github"
},
"original": {
"owner": "numtide",
"repo": "treefmt-nix",
"type": "github"
}
}
},
"root": "root",

257
flake.nix
View file

@ -1,232 +1,57 @@
{
inputs = {
# Pin nixpkgs to a specific commit
nixpkgs.url = "github:xinyangli/nixpkgs/deploy";
nixpkgs-stable.url = "github:nixos/nixpkgs/nixos-24.05";
home-manager = {
url = "github:nix-community/home-manager";
nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
flake-utils.url = "github:numtide/flake-utils";
nur-xin = {
url = "git+https://git.xinyang.life/xin/nur.git";
inputs.nixpkgs.follows = "nixpkgs";
};
nix-vscode-extensions = {
url = "github:nix-community/nix-vscode-extensions";
inputs.nixpkgs.follows = "nixpkgs";
inputs.flake-utils.follows = "flake-utils";
};
nur = {
url = "github:nix-community/NUR";
};
nixos-hardware = {
url = "github:NixOS/nixos-hardware/master";
};
sops-nix = {
url = "github:Mic92/sops-nix";
pre-commit-hooks = {
url = "github:cachix/pre-commit-hooks.nix";
inputs.nixpkgs.follows = "nixpkgs";
};
flake-utils = {
url = "github:numtide/flake-utils";
};
colmena = {
url = "github:zhaofengli/colmena";
inputs.stable.follows = "nixpkgs";
inputs.nixpkgs.follows = "nixpkgs";
inputs.flake-utils.follows = "flake-utils";
};
nix-index-database = {
url = "github:Mic92/nix-index-database";
inputs.nixpkgs.follows = "nixpkgs";
};
my-nixvim = {
url = "git+https://git.xinyang.life/xin/nixvim";
inputs.nixpkgs.follows = "nixpkgs";
};
catppuccin.url = "github:catppuccin/nix";
};
outputs =
{ self
, home-manager
, nixpkgs
, nixos-hardware
, flake-utils
, nur
, catppuccin
, my-nixvim
, ...
}@inputs:
let
nixvimOverlay = (final: prev: {
nixvim = self.packages.${prev.stdenv.system}.nixvim;
});
overlayModule = { ... }: {
nixpkgs.overlays = [
nixvimOverlay
(import ./overlays/add-pkgs.nix)
outputs = { self, ... }@inputs: with inputs;
flake-utils.lib.eachDefaultSystem (system:
let
pkgs = import nixpkgs {
inherit system; overlays = [
(self: super: {
mini-gdbstub = nur-xin.legacyPackages.${system}.mini-gdbstub;
})
];
};
deploymentModule = {
deployment.targetUser = "xin";
};
sharedColmenaModules = [
self.nixosModules.default
deploymentModule
];
sharedHmModules = [
inputs.sops-nix.homeManagerModules.sops
inputs.nix-index-database.hmModules.nix-index
catppuccin.homeManagerModules.catppuccin
self.homeManagerModules
];
mkHome = user: host: { ... }: {
imports = [
home-manager.nixosModules.home-manager
{
home-manager = {
sharedModules = sharedHmModules;
useGlobalPkgs = true;
useUserPackages = true;
extraSpecialArgs = { inherit inputs; };
};
in
{
checks = {
pre-commit-check = pre-commit-hooks.lib.${system}.run {
src = ./.;
hooks = {
trim-trailing-whitespace.enable = true;
clang-format = {
enable = true;
types_or = pkgs.lib.mkForce [ "c" "c++" ];
};
nil.enable = true;
nixpkgs-fmt.enable = true;
};
home-manager.users.${user} = (import ./home).${user}.${host};
}
];
};
mkHomeConfiguration = user: host: {
name = user;
value = home-manager.lib.homeManagerConfiguration {
pkgs = import nixpkgs { system = "x86_64-linux"; };
modules = [
(import ./home).${user}.${host}
overlayModule
] ++ sharedHmModules;
extraSpecialArgs = {
inherit inputs;
};
};
};
mkNixos = { system, modules, specialArgs ? { } }: nixpkgs.lib.nixosSystem {
inherit system;
specialArgs = specialArgs // { inherit inputs system; };
modules = [
self.nixosModules.default
nur.nixosModules.nur
] ++ modules;
};
in
{
nixpkgs = nixpkgs;
nixosModules.default = { imports = [ ./modules/nixos overlayModule ]; };
homeManagerModules = import ./modules/home-manager;
homeConfigurations = builtins.listToAttrs [ (mkHomeConfiguration "xin" "calcite") ];
colmenaHive = inputs.colmena.lib.makeHive {
meta = {
nixpkgs = import nixpkgs {
system = "x86_64-linux";
};
specialArgs = {
inherit inputs;
};
};
massicot = { ... }: {
deployment.targetHost = "49.13.13.122";
deployment.buildOnTarget = true;
imports = [
{ nixpkgs.system = "aarch64-linux"; }
machines/massicot
] ++ sharedColmenaModules;
};
tok-00 = { ... }: {
imports = [
machines/dolomite
] ++ sharedColmenaModules;
nixpkgs.system = "x86_64-linux";
networking.hostName = "tok-00";
system.stateVersion = "23.11";
deployment = {
targetHost = "video01.namely.icu";
buildOnTarget = false;
tags = [ "proxy" ];
};
};
la-00 = { ... }: {
imports = [
machines/dolomite
] ++ sharedColmenaModules;
nixpkgs.system = "x86_64-linux";
networking.hostName = "la-00";
system.stateVersion = "21.05";
deployment = {
targetHost = "la-00.video.namely.icu";
buildOnTarget = false;
tags = [ "proxy" ];
};
};
raspite = { ... }: {
deployment = {
targetHost = "raspite.local";
buildOnTarget = false;
};
nixpkgs.system = "aarch64-linux";
imports = [
"${nixpkgs}/nixos/modules/installer/sd-card/sd-image-aarch64.nix"
nixos-hardware.nixosModules.raspberry-pi-4
machines/raspite/configuration.nix
] ++ sharedColmenaModules;
};
weilite = { ... }: {
imports = [
machines/weilite
] ++ sharedColmenaModules;
deployment = {
targetHost = "weilite.coho-tet.ts.net";
targetPort = 22;
buildOnTarget = false;
};
nixpkgs.system = "x86_64-linux";
};
};
nixosConfigurations = {
calcite = mkNixos {
system = "x86_64-linux";
modules = [
nixos-hardware.nixosModules.asus-zephyrus-ga401
machines/calcite/configuration.nix
(mkHome "xin" "calcite")
devShells.default = with pkgs; (mkShell.override { stdenv = ccacheStdenv; }) {
inherit (self.checks.${system}.pre-commit-check) shellHook;
buildInputs = self.checks.${system}.pre-commit-check.enabledPackages;
packages = [
clang-tools
cmake
ninja
gdb
cli11
spdlog
mini-gdbstub
];
};
} // self.colmenaHive.nodes;
} // flake-utils.lib.eachDefaultSystem (system:
let pkgs = nixpkgs.legacyPackages.${system}; in
{
devShells = {
default = pkgs.mkShell {
packages = with pkgs; [ nix git colmena sops nix-output-monitor nil nvd ];
};
};
packages = {
nixvim = my-nixvim.packages.${system}.default;
};
}
packages.default = pkgs.callPackage ./default.nix { };
}
);
}

View file

@ -1,5 +0,0 @@
{
xin = {
calcite = import ./xin/calcite.nix;
};
}

View file

@ -1,77 +0,0 @@
{ config, pkgs, ... }@inputs:
{
imports = [
./common
];
programs.nix-index-database.comma.enable = true;
home.username = "xin";
home.homeDirectory = "/home/xin";
home.stateVersion = "23.05";
# Let Home Manager install and manage itself.
programs.home-manager.enable = true;
accounts.email.accounts.gmail = {
primary = true;
address = "lixinyang411@gmail.com";
flavor = "gmail.com";
realName = "Xinyang Li";
};
accounts.email.accounts.whu = {
address = "lixinyang411@whu.edu.cn";
};
accounts.email.accounts.foxmail = {
address = "lixinyang411@foxmail.com";
};
home.packages = with pkgs; [
thunderbird
remmina
];
# Theme
catppuccin = {
enable = true;
flavor = "mocha";
};
xdg.enable = true;
i18n.inputMethod = {
enabled = "fcitx5";
fcitx5.addons = with pkgs; [ fcitx5-rime ];
};
custom-hm = {
alacritty = { enable = true; };
direnv = { enable = true; };
fish = { enable = true; };
git = { enable = true; signing.enable = true; };
neovim = { enable = true; };
vscode = { enable = true; languages = { cxx = true; python = true; scala = true; latex = true; }; llm = true; };
zellij = { enable = true; };
};
programs.atuin = {
enable = true;
flags = [ "--disable-up-arrow" ];
};
programs.firefox.enable = true;
programs.firefox.policies = {
DefaultDownloadDirectory = "/media/data/Downloads";
};
programs.firefox.profiles.default = {
isDefault = true;
userChrome = builtins.readFile "${pkgs.fetchgit {
url = "https://gist.github.com/0ded98af9fe3da35f3688f81364d8c14.git";
rev = "11bb4f428382052bcbbceb6cc3fef97f3c939481";
hash = "sha256-J11indzEGdUA0HSW8eFe5AjesOxCL/G05KwkJk9GZSY=";
}}/userChrome.css";
};
}

View file

@ -1,25 +0,0 @@
{ inputs, pkgs, lib, ... }: {
imports = [ ];
home.packages = with pkgs; [
dig
du-dust # du + rust
zoxide # autojumper
ripgrep
file
man-pages
unar
tree
wget
tmux
ffmpeg
tealdeer
rclone
wl-clipboard
inetutils
];
# Required for standalone home configuration
nix.package = lib.mkForce pkgs.nixVersions.latest;
}

View file

@ -1,15 +0,0 @@
{ pkgs, home-manager, ... }:
home-manager.lib.homeManagerConfiguration {
inherit pkgs;
modules = [
../common
{
home.username = "xin";
home.homeDirectory = "/home/xin";
home.stateVersion = "23.05";
# Let Home Manager install and manage itself.
programs.home-manager.enable = true;
}
];
}

View file

@ -1,28 +0,0 @@
{ config, pkgs, ... }:
{
imports = [
../common
];
home.username = "xin";
home.homeDirectory = "/home/xin";
home.stateVersion = "23.05";
# Let Home Manager install and manage itself.
programs.home-manager.enable = true;
accounts.email.accounts.gmail = {
primary = true;
address = "lixinyang411@gmail.com";
flavor = "gmail.com";
};
accounts.email.accounts.whu = {
address = "lixinyang411@whu.edu.cn";
};
accounts.email.accounts.foxmail = {
address = "lixinyang411@foxmail.com";
};
}

72
include/api.hpp Normal file
View file

@ -0,0 +1,72 @@
#ifndef _DIFFTEST_API_H_
#define _DIFFTEST_API_H_
#include <cstddef>
#include <filesystem>
#include <string>
#include <vector>
extern "C" {
#include <gdbstub.h>
}
// Target dynamic library has to implement these functions
struct DiffTargetApi {
typedef void (*cont_t)(void *args, gdb_action_t *res);
cont_t cont;
typedef void (*stepi_t)(void *args, gdb_action_t *res);
stepi_t stepi;
typedef int (*read_reg_t)(void *args, int regno, size_t *value);
read_reg_t read_reg;
typedef int (*write_reg_t)(void *args, int regno, size_t value);
write_reg_t write_reg;
typedef int (*read_mem_t)(void *args, size_t addr, size_t len, void *val);
read_mem_t read_mem;
typedef int (*write_mem_t)(void *args, size_t addr, size_t len, void *val);
write_mem_t write_mem;
typedef bool (*set_bp_t)(void *args, size_t addr, bp_type_t type);
set_bp_t set_bp;
typedef bool (*del_bp_t)(void *args, size_t addr, bp_type_t type);
del_bp_t del_bp;
typedef void (*on_interrupt_t)(void *args);
on_interrupt_t on_interrupt;
typedef void (*init_t)(void *args);
init_t init;
};
struct TargetMeta {
std::string name;
std::filesystem::path libpath;
void *dlhandle;
};
class Target {
public:
DiffTargetApi ops;
TargetMeta meta;
std::vector<uint8_t> args; // used as a buffer to store target specific values
bool *do_difftest;
arch_info_t *isa_arch_info;
size_t *dbg_state_size;
gdb_action_t last_res;
Target(){};
Target(const std::string &name, const std::string &prefix,
const std::filesystem::path &path);
~Target();
bool is_on_breakpoint() const;
bool is_on_breakpoint(const gdb_action_t &res) const;
};
#endif

20
include/config.hpp Normal file
View file

@ -0,0 +1,20 @@
#include <CLI/App.hpp>
#include <CLI/CLI.hpp>
#include <CLI/Validators.hpp>
#include <filesystem>
#include <vector>
struct Config {
std::filesystem::path images_path = "./";
std::filesystem::path memory_file;
std::vector<std::filesystem::path> refs;
std::vector<std::string> refs_prefix;
std::filesystem::path dut;
std::string dut_prefix = "";
std::string gdbstub_addr = "/tmp/gdbstub-diffu.sock";
bool use_debugger = false;
int cli_parse(int argc, char **argv);
};
extern Config config;

115
include/difftest.hpp Normal file
View file

@ -0,0 +1,115 @@
#ifndef _DIFFTEST_DIFFTEST_H_
#define _DIFFTEST_DIFFTEST_H_
#include "api.hpp"
#include <filesystem>
#include <spdlog/spdlog.h>
#include <vector>
extern "C" {
#include <gdbstub.h>
}
class Difftest {
private:
Target dut;
std::vector<Target> refs;
// target used for read_reg, write_reg, read_mem, write_mem
Target *current_target = &dut;
bool halt_status = false;
inline void start_run() {
__atomic_store_n(&halt_status, false, __ATOMIC_RELAXED);
};
inline bool is_halt() {
return __atomic_load_n(&halt_status, __ATOMIC_RELAXED);
};
public:
Difftest(Target &&dut, std::vector<Target> &&refs);
void setup(const std::filesystem::path &memory_file);
// Export API for gdbstub
gdb_action_t cont();
gdb_action_t stepi();
int read_reg(int regno, size_t *value);
int write_reg(int regno, size_t value);
int read_mem(size_t addr, size_t len, void *val);
int write_mem(size_t addr, size_t len, void *val);
bool set_bp(size_t addr, bp_type_t type);
bool del_bp(size_t addr, bp_type_t type);
struct ExecRet {
bool at_breakpoint;
bool do_difftest;
bool check_failed;
};
ExecRet exec(size_t n, gdb_action_t *ret);
bool check_all();
int sync_regs_to_ref(void);
std::string list_targets(void);
std::string switch_target(int index);
inline void halt() {
__atomic_store_n(&halt_status, true, __ATOMIC_RELAXED);
};
arch_info_t get_arch() const { return *dut.isa_arch_info; }
static bool check(Target &dut, Target &ref) {
size_t pcref, pcdut;
bool passed = true;
dut.ops.read_reg(dut.args.data(), 32, &pcdut);
ref.ops.read_reg(ref.args.data(), 32, &pcref);
for (int r = 0; r < dut.isa_arch_info->reg_num; r++) {
size_t regdut = 0, regref = 0;
dut.ops.read_reg(dut.args.data(), r, &regdut);
ref.ops.read_reg(ref.args.data(), r, &regref);
if (regdut != regref) {
spdlog::error("Reg {} different: \n\tPC:\t(ref) {:x}\t(dut) {:x}\n\t"
"value:\t(ref) {:x}\t(dut) {:x}",
r, pcref, pcdut, regref, regdut);
passed = false;
}
}
return passed;
};
class Iterator {
private:
Difftest &difftest;
size_t index;
bool on_dut;
public:
Iterator(Difftest &difftest, size_t index, bool on_dut)
: difftest(difftest), index(index), on_dut(on_dut) {}
Iterator &operator++() {
if (on_dut) {
on_dut = false;
} else {
++index;
}
return *this;
}
bool operator!=(const Iterator &other) const {
return index != other.index || on_dut != other.on_dut;
}
Target &operator*() {
if (on_dut) {
return difftest.dut;
} else {
return difftest.refs.at(index);
}
}
};
Iterator begin() { return Iterator(*this, 0, true); }
Iterator end() { return Iterator(*this, refs.size(), false); }
};
#endif

View file

@ -1,328 +0,0 @@
{ config, pkgs, lib, ... }:
{
imports =
[
# Include the results of the hardware scan.
./hardware-configuration.nix
./network.nix
../sops.nix
];
commonSettings = {
auth.enable = true;
nix = {
enableMirrors = true;
signing.enable = true;
};
};
# Bootloader.
boot.loader.systemd-boot.enable = true;
boot.loader.efi.canTouchEfiVariables = true;
boot.loader.efi.efiSysMountPoint = "/boot/efi";
# boot.kernelPackages = pkgs.linuxPackages_latest;
boot.kernelModules = [ "nvidia" "nvidia_modeset" "nvidia_uvm" ];
boot.supportedFilesystems = [ "ntfs" ];
boot.binfmt.emulatedSystems = [ "aarch64-linux" ];
security.tpm2 = {
enable = true;
# expose /run/current-system/sw/lib/libtpm2_pkcs11.so
pkcs11.enable = true;
# TODO: Need this until fapi-config is fixed in NixOS
pkcs11.package = pkgs.tpm2-pkcs11.override { fapiSupport = false; };
# TPM2TOOLS_TCTI and TPM2_PKCS11_TCTI env variables
tctiEnvironment.enable = true;
};
services.gnome.gnome-keyring.enable = lib.mkForce false;
security.pam.services.login.enableGnomeKeyring = lib.mkForce false;
services.ssh-tpm-agent.enable = true;
programs.ssh.agentPKCS11Whitelist = "${config.security.tpm2.pkcs11.package}/lib/libtpm_pkcs11.so";
networking.hostName = "calcite";
programs.steam = {
enable = true;
gamescopeSession = { enable = true; };
};
programs.oidc-agent.enable = true;
programs.oidc-agent.providers = [
{
issuer = "https://home.xinyang.life:9201";
pubclient = {
client_id = "xdXOt13JKxym1B1QcEncf2XDkLAexMBFwiT9j6EfhhHFJhs2KM9jbjTmf8JBXE69";
client_secret = "UBntmLjC2yYCeHwsyj73Uwo9TAaecAetRwMw0xYcvNL9yRdLSUi0hUAHfvCHFeFh";
scope = "openid offline_access profile email";
};
}
];
programs.vim.defaultEditor = true;
# Keep this even if enabled in home manager
programs.fish.enable = true;
environment.shells = [ pkgs.fish ];
users.defaultUserShell = pkgs.fish;
# Setup wireguard
# Set your time zone.
time.timeZone = "Asia/Shanghai";
# Select internationalisation properties.
i18n.defaultLocale = "en_US.utf8";
i18n.extraLocaleSettings = {
LC_ADDRESS = "zh_CN.utf8";
LC_IDENTIFICATION = "zh_CN.utf8";
LC_MEASUREMENT = "zh_CN.utf8";
LC_MONETARY = "zh_CN.utf8";
LC_NAME = "zh_CN.utf8";
LC_NUMERIC = "zh_CN.utf8";
LC_PAPER = "zh_CN.utf8";
LC_TELEPHONE = "zh_CN.utf8";
LC_TIME = "en_US.utf8";
};
# Enable the X11 windowing system.
services.xserver.enable = true;
# Enable the GNOME Desktop Environment.
services.xserver.displayManager.gdm.enable = true;
services.xserver.desktopManager.gnome.enable = true;
# Configure keymap in X11
services.xserver = {
xkb.layout = "us";
xkb.variant = "";
};
# Keyboard mapping on internal keyboard
services.keyd = {
enable = true;
keyboards = {
"internal" = {
ids = [ "0b05:1866" ];
settings = {
main = {
capslock = "overload(control, esc)";
leftcontrol = "capslock";
};
};
};
};
};
# Enable CUPS to print documents.
services.printing.enable = true;
# services.printing.drivers = [ pkgs.hplip ];
hardware.pulseaudio.enable = false;
security.rtkit.enable = true;
services.pipewire = {
enable = true;
wireplumber.enable = true;
alsa.enable = true;
alsa.support32Bit = true;
pulse.enable = true;
# If you want to use JACK applications, uncomment this
jack.enable = true;
};
# Define a user account. Don't forget to set a password with passwd.
users.users.xin = {
isNormalUser = true;
description = "xin";
extraGroups = [ "networkmanager" "wheel" "wireshark" "tss" ];
};
services.kanidm = {
enableClient = true;
clientSettings = {
uri = "https://auth.xinyang.life";
};
};
# Enable automatic login for the user.
services.displayManager.autoLogin.enable = true;
services.displayManager.autoLogin.user = "xin";
# Smart services
services.smartd.enable = true;
# Workaround for GNOME autologin: https://github.com/NixOS/nixpkgs/issues/103746#issuecomment-945091229
systemd.services."getty@tty1".enable = false;
systemd.services."autovt@tty1".enable = false;
# Allow unfree packages
nixpkgs.config.allowUnfree = true;
nixpkgs.config.permittedInsecurePackages = [
"openssl-1.1.1w"
# FIXME: Waiting for https://github.com/NixOS/nixpkgs/pull/335753
"jitsi-meet-1.0.8043"
];
# List packages installed in system profile. To search, run:
# $ nix search wget
environment.systemPackages = with pkgs; [
oidc-agent
# Filesystem
owncloud-client
nfs-utils
# tesseract5 # ocr
ocrmypdf # pdfocr
# ==== Development ==== #
# Python
# reference: https://nixos.wiki/wiki/Python
(
let
my-python-packages = python-packages: with python-packages; [
pandas
requests
numpy
pyyaml
setuptools
];
python-with-my-packages = python3.withPackages my-python-packages;
in
python-with-my-packages
)
# ==== GUI Softwares ==== #
# Gnome tweaks
gnomeExtensions.paperwm
gnomeExtensions.search-light
gnomeExtensions.appindicator
gnomeExtensions.pano
gnome-tweaks
gnome-themes-extra
gnome.gnome-remote-desktop
bibata-cursors
gthumb
oculante
# Multimedia
vlc
obs-studio
spotify
# IM
element-desktop
tdesktop
qq
wechat-uos
feishu
# Password manager
bitwarden
# Browser
(chromium.override {
commandLineArgs = [
"--ozone-platform-hint=auto"
"--enable-wayland-ime"
];
})
brave
# Writting
zotero
# onlyoffice-bin
wpsoffice
zed-editor
config.nur.repos.linyinfeng.wemeet
virt-manager
];
system.stateVersion = "22.05";
nix.extraOptions = ''
!include "${config.sops.secrets.github_public_token.path}"
'';
sops.secrets = {
restic_repo_calcite_password = {
owner = "xin";
sopsFile = ./secrets.yaml;
};
restic_repo_calcite = {
owner = "xin";
sopsFile = ./secrets.yaml;
};
sing_box_url = {
owner = "root";
sopsFile = ./secrets.yaml;
};
"gitea/envfile" = {
owner = "root";
sopsFile = ./secrets.yaml;
};
};
custom.restic.enable = true;
custom.restic.repositoryFile = config.sops.secrets.restic_repo_calcite.path;
custom.restic.passwordFile = config.sops.secrets.restic_repo_calcite_password.path;
custom.forgejo-actions-runner.enable = true;
custom.forgejo-actions-runner.tokenFile = config.sops.secrets."gitea/envfile".path;
custom.prometheus = {
enable = true;
exporters.blackbox.enable = true;
};
services.ollama = {
enable = true;
acceleration = "cuda";
};
# MTP support
services.gvfs.enable = true;
# Fonts
fonts = {
packages = with pkgs; [
(nerdfonts.override { fonts = [ "FiraCode" ]; })
noto-fonts
noto-fonts-emoji
liberation_ttf
mplus-outline-fonts.githubRelease
dina-font
proggyfonts
ubuntu_font_family
# Chinese
wqy_microhei
wqy_zenhei
noto-fonts-cjk-sans
noto-fonts-cjk-serif
source-han-sans
source-han-serif
];
fontconfig = {
defaultFonts = {
serif = [ "Noto Serif CJK SC" "Ubuntu" ];
sansSerif = [ "Noto Sans CJK SC" "Ubuntu" ];
monospace = [ "FiraCode NerdFont Mono" "Noto Sans Mono CJK SC" "Ubuntu" ];
};
};
enableDefaultPackages = true;
};
# Virtualization
virtualisation = {
libvirtd.enable = true;
podman = {
enable = true;
};
docker = {
enable = true;
autoPrune.enable = true;
};
};
services.nixseparatedebuginfod.enable = true;
}

View file

@ -1,61 +0,0 @@
# Do not modify this file! It was generated by nixos-generate-config
# and may be overwritten by future invocations. Please make changes
# to /etc/nixos/configuration.nix instead.
{ config, lib, pkgs, modulesPath, ... }:
{
imports =
[ (modulesPath + "/installer/scan/not-detected.nix")
];
boot.initrd.availableKernelModules = [ "xhci_pci" "nvme" "ahci" "usbhid" ];
boot.initrd.kernelModules = [ ];
boot.initrd.luks.devices.cryptroot = {
device = "/dev/disk/by-uuid/5a51f623-6fbd-4843-9f83-c895067e8e7d";
};
boot.kernelModules = [ "kvm-amd" ];
boot.extraModulePackages = [ ];
fileSystems."/" =
{ # device = "/dev/disk/by-label/NIXROOT";
device = "/dev/mapper/cryptroot";
fsType = "btrfs";
};
fileSystems."/boot/efi" =
{ device = "/dev/disk/by-label/EFIBOOT";
fsType = "vfat";
};
fileSystems."/media/data" =
{ device = "/dev/nvme0n1p7";
fsType = "ntfs-3g";
options = [ "rw" "uid=1000" "nofail" "x-systemd.device-timeout=2" ];
};
swapDevices =
[ { device = "/dev/disk/by-label/NIXSWAP"; }
];
# Enables DHCP on each ethernet and wireless interface. In case of scripted networking
# (the default) this is the recommended approach. When using systemd-networkd it's
# still possible to use this option, but it's recommended to use it in conjunction
# with explicit per-interface declarations with `networking.interfaces.<interface>.useDHCP`.
networking.useDHCP = lib.mkDefault true;
# networking.interfaces.tailscale0.useDHCP = lib.mkDefault true;
# networking.interfaces.virbr0.useDHCP = lib.mkDefault true;
# networking.interfaces.wg0.useDHCP = lib.mkDefault true;
# networking.interfaces.wlp2s0.useDHCP = lib.mkDefault true;
nixpkgs.hostPlatform = lib.mkDefault "x86_64-linux";
hardware.cpu.amd.updateMicrocode = lib.mkDefault config.hardware.enableRedistributableFirmware;
hardware.graphics = {
enable = true;
enable32Bit = true;
};
hardware.nvidia = {
powerManagement.enable = true;
dynamicBoost.enable = lib.mkForce false;
};
}

View file

@ -1,57 +0,0 @@
{ config, pkgs, ...}:
{
imports = [ ];
# Enable networking
networking = {
networkmanager = {
enable = true;
dns = "systemd-resolved";
};
};
services.resolved = {
enable = true;
extraConfig = ''
Cache=no
'';
};
# Enable Tailscale
services.tailscale.enable = true;
# services.tailscale.useRoutingFeatures = "both";
services.dae.enable = true;
services.dae.configFile = "/var/lib/dae/config.dae";
custom.sing-box = {
enable = false;
configFile = {
urlFile = config.sops.secrets.sing_box_url.path;
hash = "6ca5bc8a16f8c413227690aceeee2c12c02cab09473c216b849af1e854b98588";
};
overrideSettings.experimental.clash_api.external_ui = "${config.nur.repos.linyinfeng.yacd}";
};
# Open ports in the firewall.
networking.firewall.enable = true;
networking.firewall.allowedTCPPorts = [ 3389 ];
networking.firewall.allowedUDPPorts = [ 3389 41641 ];
networking.firewall.trustedInterfaces = [
"tailscale0"
];
# Use nftables to manager firewall
networking.nftables.enable = true;
# Add gsconnect, open firewall
programs.kdeconnect = {
enable = true;
package = pkgs.gnomeExtensions.gsconnect;
};
programs.wireshark = {
enable = true;
package = pkgs.wireshark-qt;
};
}

View file

@ -1,34 +0,0 @@
restic_repo_calcite_password: ENC[AES256_GCM,data:9ALTQULAMyLY4FIxuVztf9r3,iv:fObBBeqpHAVYl8YUopz9fZd3YWB+0sc8l+sR12rmxb4=,tag:l3xDc2/cpQr38X/cd7qMXA==,type:str]
restic_repo_calcite: ENC[AES256_GCM,data:+m9cjMXrZoCPg/S+/wV4WFBmg6pbFpqJ7JOdwOX0Z37bgoQXh4wcVPKK3CLd7G/iQjpO8SXaqJ1/d8r4Ydk21Gp1WqkB8g==,iv:DweDUujXp6i5XwwxeFjUsLDOJQJlRIT6GKPPxABNWiY=,tag:hdBHIjAcDQ1Ky/8hIv3+Ow==,type:str]
sing_box_url: ENC[AES256_GCM,data:2z2bDKdn51o1eaqhgE0pTg4FWcO8wcLNlnBZ69Q3Jm5GCxkXxsxN7DgqQvRVeakOHvaenQotF+nc6tlhKPsyzdQeG0yl3YYhGb9o3DkmpUjC6lalMSoiw1rSMVyBg4KYCWxmhR9iRurun62+5INGZwwHVqAjgWJhy/9+pdIFtgKyd/t0JhSU,iv:gIGbvRd88vZu3cVW7e4emZmmNO8QcubLrxS1sCwi4Co=,tag:AzLLtcA9jAbeuo6eWU6ilw==,type:str]
gitea:
envfile: ENC[AES256_GCM,data:bO1aMYm0kPTBbyPD5cweVRzNjiDK2WlWDsxz52L3faFg5HSVmBoi5DZC17XBXYw=,iv:lo9XEcwY4FPD/rRbnuiUviioMIiiphS26UgPro56DIU=,tag:0eKfsS0pYw+FPW+Y5dgisg==,type:str]
sops:
kms: []
gcp_kms: []
azure_kv: []
hc_vault: []
age:
- recipient: age1uw059wcwfvd9xuj0hpqzqpeg7qemecspjrsatg37wc7rs2pumfdsgken0c
enc: |
-----BEGIN AGE ENCRYPTED FILE-----
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBQMDdkc2RUVlR5aEFtZ01l
d3EzaG9RNFd1QTVrNFIrZlJmOXNVWG1jRFJNCnFqL2VrUFljdGdGMW02RnJkNGxm
dmhUS0pMOURyWWkyVlp1UDQ5ZG11U2cKLS0tIDBiNnI0Qm5QN04zQ3NpTVMzNGpY
eFlOKzdGa0FRZ0R5Um12bUE2T0ZzbHMK62B0QniOnaUKLGrrRV934PqbCbUKtK3u
hN+53kRiitkL1gmaGqRbfu4FMns9VPKdoyfECcJ39HyScl9ZEj8mMw==
-----END AGE ENCRYPTED FILE-----
- recipient: age1ytwfqfeez3dqtazyjltn7mznccwx3ua8djhned7n8mxqhw4p6e5s97skfa
enc: |
-----BEGIN AGE ENCRYPTED FILE-----
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBycTBkMWlWMncybUFraS9R
ZWFjOGdDRlFLV2RlZHVFSEhMdExaekJWMFQwCk5hbFJhQ3cvbG9qdERnbFhLTnFs
NXQvcndjNHBMdk1XOTYydVlDMzk0Y0UKLS0tIGpLM20zTnREdllxRlc1SnJEVFBZ
WGlLdXVoZlp3bEFXZjlMdG1VOUZDNUkKQ2NNTE3OsNUr2pOI7qeNFSCVkUIVRS+g
FG5FbJJcFihXqr+Qo0nZkq+xq07vIia7mKoqyoIfkKwweiVzDKyrkQ==
-----END AGE ENCRYPTED FILE-----
lastmodified: "2024-08-14T01:46:18Z"
mac: ENC[AES256_GCM,data:+RuyHG1wLykJX792bkHvRXEiW7vDYj7i2tbR0MnZZUuFcr3xQDIuCW0/XnzxeX643k4iq+h/YUer/v7tIbCh75UXTG7oxQpfJhI8zMfaxKcCZBntD+wDhEmpWhgonOR/RwOAPMPz7FntJVvt9BHnpSLVjZC7KqVPohob0DRJs2Q=,iv:p6Lov35M8SN9RIV9I3D+3cO+wi3Kd2pVe08xgWYi/tM=,tag:aOMQauv2FFEsdwaS7WOraQ==,type:str]
pgp: []
unencrypted_suffix: _unencrypted
version: 3.9.0

View file

@ -1,37 +0,0 @@
{ config, lib, pkgs, modulesPath, ... }:
let
cfg = config.isBandwagon;
in
{
imports = [ (modulesPath + "/profiles/qemu-guest.nix") ];
options = {
isBandwagon = lib.mkEnableOption "Bandwagon instance";
};
config = lib.mkIf cfg {
boot.initrd.availableKernelModules = [ "ata_piix" "xhci_pci" "virtio_pci" "virtio_scsi" "sd_mod" "sr_mod" ];
boot.initrd.kernelModules = [ ];
boot.kernelModules = [ ];
boot.extraModulePackages = [ ];
fileSystems."/" =
{ device = "/dev/disk/by-label/NIXROOT";
fsType = "xfs";
};
fileSystems."/boot" =
{ device = "/dev/disk/by-label/NIXBOOT";
fsType = "vfat";
};
swapDevices = [ ];
boot.loader.grub.enable = true;
boot.loader.grub.device = "/dev/sda";
networking.useDHCP = false;
networking.interfaces.ens18.useDHCP = true;
networking.interfaces.ens19.useDHCP = true;
};
}

View file

@ -1,193 +0,0 @@
{ config, lib, ... }:
let
awsHosts = [ "tok-00"];
bwgHosts = [ "la-00" ];
in
{
imports = [
../sops.nix
./bandwagon.nix
./lightsail.nix
];
config = {
isBandwagon = builtins.elem config.networking.hostName bwgHosts;
isLightsail = builtins.elem config.networking.hostName awsHosts;
sops = {
secrets = {
wg_private_key = {
owner = "root";
sopsFile = ./secrets + "/${config.networking.hostName}.yaml";
};
wg_ipv6_local_addr = {
owner = "root";
sopsFile = ./secrets + "/${config.networking.hostName}.yaml";
};
};
};
boot.kernel.sysctl = {
"net.core.default_qdisc" = "fq";
"net.ipv4.tcp_congestion_control" = "bbr";
};
networking.firewall.trustedInterfaces = [ "tun0" ];
security.acme = {
acceptTerms = true;
certs.${config.deployment.targetHost} = {
email = "me@namely.icu";
listenHTTP = ":80";
};
};
networking.firewall.allowedTCPPorts = [ 80 8080 ];
networking.firewall.allowedUDPPorts = [ ] ++ (lib.range 6311 6314);
custom.prometheus = {
enable = true;
exporters.blackbox.enable = true;
};
custom.kanidm-client = {
enable = true;
uri = "https://auth.xinyang.life/";
asSSHAuth = {
enable = true;
allowedGroups = [ "linux_users" ];
};
sudoers = [ "xin@auth.xinyang.life" ];
};
services.openssh = {
settings = {
PasswordAuthentication = false;
KbdInteractiveAuthentication = false;
PermitRootLogin = lib.mkForce "no";
GSSAPIAuthentication = "no";
KerberosAuthentication = "no";
};
};
services.fail2ban.enable = true;
programs.mosh.enable = true;
security.sudo = {
execWheelOnly = true;
wheelNeedsPassword = false;
};
services.sing-box = let
singTls = {
enabled = true;
server_name = config.deployment.targetHost;
key_path = config.security.acme.certs.${config.deployment.targetHost}.directory + "/key.pem";
certificate_path = config.security.acme.certs.${config.deployment.targetHost}.directory + "/cert.pem";
};
password = {
_secret = config.sops.secrets.singbox_password.path;
};
uuid = {
_secret = config.sops.secrets.singbox_uuid.path;
};
in
{
enable = true;
settings = {
dns = {
servers = [
{
tag = "warp";
address = "1.1.1.1";
detour = "wg-out";
}
{
tag = "directdns";
address = "h3://8.8.8.8/dns-query";
}
];
rules = [
{
outbound = "wg-out";
server = "warp";
}
{
outbound = "direct";
server = "directdns";
}
];
};
inbounds = [
{
tag = "sg0";
type = "trojan";
listen = "::";
listen_port = 8080;
users = [
{ name = "proxy";
password = password;
}
];
tls = singTls;
}
] ++ lib.forEach (lib.range 6311 6314) (port: {
tag = "sg" + toString (port - 6310);
type = "tuic";
listen = "::";
listen_port = port;
congestion_control = "bbr";
users = [
{ name = "proxy";
uuid = uuid;
password = password;
}
];
tls = singTls;
});
outbounds = [
{
type = "wireguard";
tag = "wg-out";
private_key = {
_secret = config.sops.secrets.wg_private_key.path;
};
local_address = [
"172.16.0.2/32"
{ _secret = config.sops.secrets.wg_ipv6_local_addr.path; }
];
peers = [
{ public_key= "bmXOC+F1FxEMF9dyiK2H5/1SUtzH0JuVo51h2wPfgyo=";
allowed_ips = [ "0.0.0.0/0" "::/0" ];
server = "162.159.192.1";
server_port = 500;
}
];
}
{
type = "direct";
tag = "direct";
}
{
type = "dns";
tag = "dns-out";
}
];
route = {
rules = [
{
outbound = "dns-out";
protocol = "dns";
}
{
inbound = "sg0";
outbound = "direct";
}
{
inbound = "sg4";
outbound = "direct";
}
];
};
};
};
};
}

View file

@ -1,66 +0,0 @@
metaDir=/etc/ec2-metadata
mkdir -m 0755 -p "$metaDir"
rm -f "$metaDir/*"
get_imds_token() {
# retry-delay of 1 selected to give the system a second to get going,
# but not add a lot to the bootup time
curl \
--silent \
--show-error \
--retry 3 \
--retry-delay 1 \
--fail \
-X PUT \
--connect-timeout 1 \
-H "X-aws-ec2-metadata-token-ttl-seconds: 600" \
http://169.254.169.254/latest/api/token
}
preflight_imds_token() {
# retry-delay of 1 selected to give the system a second to get going,
# but not add a lot to the bootup time
curl \
--silent \
--show-error \
--retry 3 \
--retry-delay 1 \
--fail \
--connect-timeout 1 \
-H "X-aws-ec2-metadata-token: $IMDS_TOKEN" \
-o /dev/null \
http://169.254.169.254/1.0/meta-data/instance-id
}
try=1
while [ $try -le 3 ]; do
echo "(attempt $try/3) getting an EC2 instance metadata service v2 token..."
IMDS_TOKEN=$(get_imds_token) && break
try=$((try + 1))
sleep 1
done
if [ "x$IMDS_TOKEN" == "x" ]; then
echo "failed to fetch an IMDS2v token."
fi
try=1
while [ $try -le 10 ]; do
echo "(attempt $try/10) validating the EC2 instance metadata service v2 token..."
preflight_imds_token && break
try=$((try + 1))
sleep 1
done
echo "getting EC2 instance metadata..."
get_imds() {
# --fail to avoid populating missing files with 404 HTML response body
# || true to allow the script to continue even when encountering a 404
curl --silent --show-error --fail --header "X-aws-ec2-metadata-token: $IMDS_TOKEN" "$@" || true
}
get_imds -o "$metaDir/ami-manifest-path" http://169.254.169.254/1.0/meta-data/ami-manifest-path
(umask 077 && get_imds -o "$metaDir/user-data" http://169.254.169.254/1.0/user-data)
get_imds -o "$metaDir/hostname" http://169.254.169.254/1.0/meta-data/hostname
get_imds -o "$metaDir/public-keys-0-openssh-key" http://169.254.169.254/1.0/meta-data/public-keys/0/openssh-key

View file

@ -1,102 +0,0 @@
{ config, lib, pkgs, modulesPath, ... }:
with lib;
let
cfg = config.ec2;
in
{
imports = [
"${modulesPath}/profiles/headless.nix"
# Note: While we do use the headless profile, we also explicitly
# turn on the serial console on ttyS0 below. This is because
# AWS does support accessing the serial console:
# https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/configure-access-to-serial-console.html
"${modulesPath}/virtualisation/ec2-data.nix"
"${modulesPath}/virtualisation/amazon-init.nix"
];
options = {
isLightsail = mkEnableOption "Lightsail instance";
};
config = mkIf config.isLightsail {
boot.loader.grub.device = "/dev/nvme0n1";
# from nixpkgs amazon-image.nix
assertions = [ ];
boot.growPartition = true;
fileSystems."/" = {
device = "/dev/disk/by-label/nixos";
fsType = "ext4";
autoResize = true;
};
fileSystems."/boot" = {
# The ZFS image uses a partition labeled ESP whether or not we're
# booting with EFI.
device = "/dev/disk/by-label/ESP";
fsType = "vfat";
};
boot.extraModulePackages = [
config.boot.kernelPackages.ena
];
boot.initrd.kernelModules = [ "xen-blkfront" ];
boot.initrd.availableKernelModules = [ "nvme" ];
boot.kernelParams = [ "console=ttyS0,115200n8" "random.trust_cpu=on" ];
# Prevent the nouveau kernel module from being loaded, as it
# interferes with the nvidia/nvidia-uvm modules needed for CUDA.
# Also blacklist xen_fbfront to prevent a 30 second delay during
# boot.
boot.blacklistedKernelModules = [ "nouveau" "xen_fbfront" ];
boot.loader.grub.efiSupport = cfg.efi;
boot.loader.grub.efiInstallAsRemovable = cfg.efi;
boot.loader.timeout = 1;
boot.loader.grub.extraConfig = ''
serial --unit=0 --speed=115200 --word=8 --parity=no --stop=1
terminal_output console serial
terminal_input console serial
'';
systemd.services.fetch-ec2-metadata = {
wantedBy = [ "multi-user.target" ];
wants = [ "network-online.target" ];
after = ["network-online.target"];
path = [ pkgs.curl ];
script = builtins.readFile ./ec2-metadata-fetcher.sh;
serviceConfig.Type = "oneshot";
serviceConfig.StandardOutput = "journal+console";
};
# Amazon-issued AMIs include the SSM Agent by default, so we do the same.
# https://docs.aws.amazon.com/systems-manager/latest/userguide/ami-preinstalled-agent.html
services.amazon-ssm-agent.enable = true;
# Allow root logins only using the SSH key that the user specified
# at instance creation time.
services.openssh.enable = true;
services.openssh.settings.PermitRootLogin = "prohibit-password";
# Enable the serial console on ttyS0
systemd.services."serial-getty@ttyS0".enable = true;
# Creates symlinks for block device names.
services.udev.packages = [ pkgs.amazon-ec2-utils ];
# Force getting the hostname from EC2.
# networking.hostName = mkDefault "";
# Always include cryptsetup so that Charon can use it.
environment.systemPackages = [ pkgs.cryptsetup ];
# EC2 has its own NTP server provided by the hypervisor
networking.timeServers = [ "169.254.169.123" ];
# udisks has become too bloated to have in a headless system
# (e.g. it depends on GTK).
services.udisks2.enable = false;
};
}

View file

@ -1,31 +0,0 @@
wg_private_key: ENC[AES256_GCM,data:jz/03kP/dj625Jweu0MEw9aGm3Z3M1f43cZqGy2eElCIDhD78n+zZAqOM8c=,iv:fZxuvZLx97YyDoafQXbqVYjqRYzZq90PJiri9vdjwro=,tag:0A9sGnSl3y3gpEuvsdRtGg==,type:str]
wg_ipv6_local_addr: ENC[AES256_GCM,data:W/uR+9kAKdXViAbZ0vEhC2eNwlzqX0x+LpzLrLCmQuVgRbZAtJCqfeE=,iv:pMZumU7fMV5MYX59hO7SEMLlG4m8DdPXeAiNgLxNzZk=,tag:xdGBpOBdWlc8Q9BDMv04sA==,type:str]
sops:
kms: []
gcp_kms: []
azure_kv: []
hc_vault: []
age:
- recipient: age1uw059wcwfvd9xuj0hpqzqpeg7qemecspjrsatg37wc7rs2pumfdsgken0c
enc: |
-----BEGIN AGE ENCRYPTED FILE-----
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSB4WjRVY3BKdVU1WERrVzla
L1NNYWp2SFZEaW84b0h1clFGRHVmRDhnM3o0CkUrZjZKNHp2TGtrTXpyOHNVckJw
VURjOEVaR3VQU1pJY2NaOFBQRjVIdWcKLS0tIFBQRWRnNnk4aWxsQVhhdUdVWWpy
aG9Oa3lOY0JjY2tFU3ZTazcyZW5SM0kKRfTrM65aI5LMOHoGsls3PWChrY5pEz91
EERpRd552+PxYBKvumI59mtdlD263d5kmlTxIIZXTOJ2fcl1bii2bg==
-----END AGE ENCRYPTED FILE-----
- recipient: age1fw2sqaa5s9c8ml6ncsexkj8ar4288387ju92ytjys4awf9aw6smqqz94dh
enc: |
-----BEGIN AGE ENCRYPTED FILE-----
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBTdzk4ajV5ekNpZXNGTHdD
aVBLZDlSbzE1aG5LT0cvVVVlVDBNOWtackNVCjVnZDhYZmFoT21DZHNYT2pMVDF6
ZW5UY1ZFRFdtbDdPZHZIWUVuWjhJMk0KLS0tIGR4UUYwcjJtZUFYYlJSS2d6Q3hZ
WVJYSWhOaTEvNUdYTXV6OThPenJaY0UKv3WK6gacUxO6PFklkW+jDMG5FgIUuEvN
RvvI9ZXRD4QwKW1mpVrxbC+fRqlKawyyyyikvHFGJvpts4/88IcgUQ==
-----END AGE ENCRYPTED FILE-----
lastmodified: "2024-04-15T11:37:57Z"
mac: ENC[AES256_GCM,data:iCgvJMijsUjdBT9hMQx4owYkbp2nV1jORB5HGtz5IPHgI9A5FXAAPFtaSGgQSI3twSkYMU94NULjumCyyWt3syH5KK9itHgHwONyVFieyXLiWozqpN2Z0SA5G4SnK3E6X273br9gwNAj33I2MdS/3K8b4EOO2yEzilWmrW7f3rk=,iv:UD7uHrtq4O6+EsWFrjegTXHtQUFcnhKsu4J0e0srDtk=,tag:b0eJEeUJPwi4+rDPeBY7oA==,type:str]
pgp: []
unencrypted_suffix: _unencrypted
version: 3.8.1

View file

@ -1,31 +0,0 @@
wg_private_key: ENC[AES256_GCM,data:UjxZ3iC5hxVcVJdEUJ3+myaQ/6MvghDw6eKa2flSuxMwFS31WB7r3evjlI0=,iv:BjgXCps6gx1ISghEO42x5aKb+c/n0P1V8FMVlPxAyLY=,tag:IkxCkpyVre+sFoBlRSFpMA==,type:str]
wg_ipv6_local_addr: ENC[AES256_GCM,data:ejDYuZjZCKcsvyUUKdXtxgBqWloIwYHmpc/YwCYq7O2thsxvOou6iSHf,iv:HDrMlec4svxHpZXMyRDzpdSKeJbTmkZPd98SHv2ZLhQ=,tag:LjpapuaJ6sl4USZC8xEU5w==,type:str]
sops:
kms: []
gcp_kms: []
azure_kv: []
hc_vault: []
age:
- recipient: age1uw059wcwfvd9xuj0hpqzqpeg7qemecspjrsatg37wc7rs2pumfdsgken0c
enc: |
-----BEGIN AGE ENCRYPTED FILE-----
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBtUkpVa0dCSE1rTjZpaWR1
cjJjc25iOEV4TnhQUWE4SjI4QWVZYXdVcHdBCkIrNlVrV2xJRURVSG9sUHozeE5s
NitsV1MvcENZTHhmU01CSTRVNENXUFEKLS0tIGgxakQ2cGIzdzg5QzRoT3ZSaXUx
TkN5MkNTNitWMzVKZWdhNGRIZ3VNNDgKQ6lwM6EowuGOrskUpwD8VGirravE+e3/
Hkv5jLvvfVjmg0kvKlNRotTHrRUGV04JsbW7T9FfbKyYpmEb6oCrsg==
-----END AGE ENCRYPTED FILE-----
- recipient: age13s6rwd3wjk2x5wkn69tdczhl3l5d7mfmlv90efsv4q67jne43qss9tcakx
enc: |
-----BEGIN AGE ENCRYPTED FILE-----
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBjSUlkQzhYSGwyNnYvNHpQ
UktKOUZiYk56S0piVy9ZMFdYVFdsN1FEVkhVCnZETEM5MW84TlNpbm1hSXJtR2Yy
OEdrSi9lcmJOR2F1cUZqc0NyQjl4RDgKLS0tIHVLcnRicmVNd2MwVjB4cGFXTlBu
VkJCcXdqTkUzejNzSjIvV2YrVUc5Sm8KutTATsWJ5+yB/CFoGwTNshyI5LzwH4x5
i5EIIkVPdxSIHrXUp0j6+RPWMJvEOFIE3dVwxz+MxqqHqtmEny1WKA==
-----END AGE ENCRYPTED FILE-----
lastmodified: "2023-12-19T12:31:51Z"
mac: ENC[AES256_GCM,data:AY0/qJ1ZXv4mQlHnG3uY2zQ0FhIYjHBWKyXXpv2/Q6yZkuSu6nIQk039nd+nk7lczXy2cylTHyjYv5vDF6BJARhu4jeYov6yMqYR8ye8rXjZKcOfrN5yv7LV6jyuzBRBkCWTQsaoR8ycKHlrMe+vkAGu50epdAQjAG+Qv6RkBiM=,iv:dMi2CququdEIg+g8NMUb8ioKwEkUqTP+nrivtsUYUUY=,tag:drHI6oJUUwN3JadCHbWWkg==,type:str]
pgp: []
unencrypted_suffix: _unencrypted
version: 3.8.1

View file

@ -1,31 +0,0 @@
wg_private_key: ENC[AES256_GCM,data:jz/03kP/dj625Jweu0MEw9aGm3Z3M1f43cZqGy2eElCIDhD78n+zZAqOM8c=,iv:fZxuvZLx97YyDoafQXbqVYjqRYzZq90PJiri9vdjwro=,tag:0A9sGnSl3y3gpEuvsdRtGg==,type:str]
wg_ipv6_local_addr: ENC[AES256_GCM,data:W/uR+9kAKdXViAbZ0vEhC2eNwlzqX0x+LpzLrLCmQuVgRbZAtJCqfeE=,iv:pMZumU7fMV5MYX59hO7SEMLlG4m8DdPXeAiNgLxNzZk=,tag:xdGBpOBdWlc8Q9BDMv04sA==,type:str]
sops:
kms: []
gcp_kms: []
azure_kv: []
hc_vault: []
age:
- recipient: age1uw059wcwfvd9xuj0hpqzqpeg7qemecspjrsatg37wc7rs2pumfdsgken0c
enc: |
-----BEGIN AGE ENCRYPTED FILE-----
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBkYTc2a2J3ZXRXTlRxQTAx
UjZVTTVPa0FjbS9jekI5eXhLOTdUQTlBS2pJCnVPL2Q1d05QR2NpTDVZeDFpSCs3
Yjh3aXkvdTBIOThVMGMzcUZmUWhtTjgKLS0tIFZvcy9zRVBRcDN0ekp0MEV5cEph
ZURTL3hnSHgwQTlSNklCK25icEM0SGsKq2jM6jXLfK38BgV0calwKLuHIcGw0zed
lT19Mt9jFsqmIkpJh1U9Ddpz63WND+7ruMdTZt6RWStIxww4m7pevg==
-----END AGE ENCRYPTED FILE-----
- recipient: age1t5nw2jx4dw67jkf72uxcxt72j7lq3xyj35lvl09f8kala90h2g2s2a5yvj
enc: |
-----BEGIN AGE ENCRYPTED FILE-----
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBiSXBqdXcxUDNkS29Gd3ZY
dTA3bmNUVThtTFJtdnFpSjZQT01TTXhpYUc4CkFhcm14eUw1YXIyWEViMSsyc3pr
VUJqWWdHMCtoRGQ1T3dMQlg3ZTZ5dGMKLS0tIGQvbGpFZTdrVUFURE9tdENCZGwr
aDBKbitCTmhxNXVNRGh6TVBvbkNhTUEKIuj7B4RdueX7BfExgzVoo6YJf59GsUHa
j5kIJ5UeTqWEBGBaXcPjhHMEQjYqwSBsVz2XJmsxLhi8WxejLio8FA==
-----END AGE ENCRYPTED FILE-----
lastmodified: "2023-12-19T12:30:24Z"
mac: ENC[AES256_GCM,data:f+7+O2ZVSZJhr0fJlfO/AtZC2N/7gsNu1f4cnUoXYFb1wobyU6tLkbwGqeyIulokgIDAU5lJ62TJXAjybe+kE+PGtpr61KS7dyiO0LjzcT/X898oBYvJ9jtkuxDzKM4ve570U7ZmS7Jbxt2NJEkcBvSUJRdJHH5l0sDrvmW8cwY=,iv:mno6jVUDUWxsO353hbCqGub+NYfk0XFsWzmWCBUt6Gg=,tag:KOw7HTy+pETha5pzx5Pf8Q==,type:str]
pgp: []
unencrypted_suffix: _unencrypted
version: 3.8.1

View file

@ -1,94 +0,0 @@
{ inputs, config, libs, pkgs, ... }:
{
imports = [
inputs.sops-nix.nixosModules.sops
./hardware-configuration.nix
./networking.nix
./services.nix
];
sops = {
defaultSopsFile = ./secrets.yaml;
age.sshKeyPaths = [ "/etc/ssh/ssh_host_ed25519_key" ];
secrets = {
storage_box_mount = {
owner = "root";
};
gts_env = {
owner = "gotosocial";
};
hedgedoc_env = {
owner = "hedgedoc";
};
grafana_cloud_api = {
owner = "prometheus";
sopsFile = ../secrets.yaml;
};
grafana_oauth_secret = {
owner = "grafana";
};
"miniflux/oauth2_secret" = {
owner = "root";
};
"forgejo/env" = {
owner = "forgejo";
};
};
};
boot.loader.efi.canTouchEfiVariables = true;
boot.loader.efi.efiSysMountPoint = "/boot";
boot.loader.grub = {
enable = true;
efiSupport = true;
configurationLimit = 5;
};
fileSystems."/mnt/storage" = {
device = "//u380335-sub1.your-storagebox.de/u380335-sub1";
fsType = "cifs";
options = [ "credentials=${config.sops.secrets.storage_box_mount.path}" ];
};
environment.systemPackages = with pkgs; [
cifs-utils
git
];
system.stateVersion = "22.11";
networking = {
hostName = "massicot";
};
custom.kanidm-client = {
enable = true;
uri = "https://auth.xinyang.life/";
asSSHAuth = {
enable = true;
allowedGroups = [ "linux_users" ];
};
sudoers = [ "xin@auth.xinyang.life" ];
};
security.sudo = {
execWheelOnly = true;
wheelNeedsPassword = false;
};
services.openssh = {
enable = true;
settings = {
PasswordAuthentication = false;
KbdInteractiveAuthentication = false;
PermitRootLogin = "no";
GSSAPIAuthentication = "no";
KerberosAuthentication = "no";
};
};
services.fail2ban.enable = true;
programs.mosh.enable = true;
systemd.services.sshd.wantedBy = pkgs.lib.mkForce [ "multi-user.target" ];
}

View file

@ -1,13 +0,0 @@
{ modulesPath, ... }:
{
imports = [ (modulesPath + "/profiles/qemu-guest.nix") ];
boot.loader.grub = {
efiSupport = true;
device = "nodev";
};
fileSystems."/boot" = { device = "/dev/disk/by-uuid/AC27-D9D6"; fsType = "vfat"; };
boot.initrd.availableKernelModules = [ "ata_piix" "uhci_hcd" "xen_blkfront" ];
boot.initrd.kernelModules = [ "nvme" ];
fileSystems."/" = { device = "/dev/sda1"; fsType = "ext4"; };
}

View file

@ -1,143 +0,0 @@
{
enable = true;
autoRemove = true;
groups = {
forgejo-access = {
members = [ "xin" ];
};
forgejo-admin = {
members = [ "xin" ];
};
gts-users = {
members = [ "xin" ];
};
ocis-users = {
members = [ "xin" ];
};
linux_users = {
members = [ "xin" ];
};
hedgedoc-users = {
members = [ "xin" ];
};
immich-users = {
members = [ "xin" "zhuo" "ycm" ];
};
grafana-superadmins = {
members = [ "xin" ];
};
grafana-admins = {
members = [ "xin" ];
};
grafana-editors = {
members = [ "xin" ];
};
grafana-users = {
members = [ "xin" ];
};
miniflux-users = {
members = [ "xin" ];
};
idm_people_self_mail_write = {
members = [ ];
};
};
persons = {
xin = {
displayName = "Xinyang Li";
mailAddresses = [ "lixinyang411@gmail.com" ];
};
zhuo = {
displayName = "Zhuo";
mailAddresses = [ "13681104320@163.com" ];
};
ycm = {
displayName = "Chunming";
mailAddresses = [ "chunmingyou@gmail.com" ];
};
};
systems.oauth2 = {
forgejo = {
displayName = "ForgeJo";
originUrl = "https://git.xinyang.life/";
originLanding = "https://git.xinyang.life/user/oauth2/kandim";
allowInsecureClientDisablePkce = true;
scopeMaps = {
forgejo-access = [ "openid" "email" "profile" "groups" ];
};
claimMaps = {
forgejo_role = {
joinType = "array";
valuesByGroup = {
forgejo-access = [ "Access" ];
forgejo-admin = [ "Admin" ];
};
};
};
};
gts = {
displayName = "GoToSocial";
originUrl = "https://xinyang.life/";
originLanding = "https://xinyang.life/";
allowInsecureClientDisablePkce = true;
scopeMaps = {
gts-users = [ "openid" "email" "profile" "groups" ];
};
};
owncloud = {
displayName = "ownCloud";
originUrl = "https://home.xinyang.life:9201/";
originLanding = "https://home.xinyang.life:9201/";
public = true;
scopeMaps = {
ocis-users = [ "openid" "email" "profile" ];
};
};
hedgedoc = {
displayName = "HedgeDoc";
originUrl = "https://docs.xinyang.life/";
originLanding = "https://docs.xinyang.life/auth/oauth2";
allowInsecureClientDisablePkce = true;
scopeMaps = {
hedgedoc-users = [ "openid" "email" "profile" ];
};
};
immich-mobile = {
displayName = "Immich";
originUrl = "https://immich.xinyang.life:8000/api/oauth/mobile-redirect/";
originLanding = "https://immich.xinyang.life:8000/api/oauth/mobile-redirect/";
allowInsecureClientDisablePkce = true;
scopeMaps = {
immich-users = [ "openid" "email" "profile" ];
};
};
miniflux = {
displayName = "Miniflux";
originUrl = "https://rss.xinyang.life/";
originLanding = "https://rss.xinyang.life/";
scopeMaps = {
miniflux-users = [ "openid" "email" "profile" ];
};
};
grafana = {
displayName = "Grafana";
originUrl = "https://grafana.xinyang.life/";
originLanding = "https://grafana.xinyang.life/";
scopeMaps = {
grafana-users = [ "openid" "email" "profile" "groups" ];
};
claimMaps = {
grafana_role = {
joinType = "array";
valuesByGroup = {
grafana-superadmins = [ "GrafanaAdmin" ];
grafana-admins = [ "Admin" ];
grafana-editors = [ "Editor" ];
};
};
};
};
};
}

View file

@ -1,16 +0,0 @@
{ pkgs, ... }: {
networking = {
interfaces = {
eth0.useDHCP = true;
eth0.ipv6.addresses = [{
address = "2a01:4f8:c17:345f::1";
prefixLength = 64;
}];
};
defaultGateway6 = {
address = "fe80::1";
interface = "eth0";
};
nameservers = [ ];
};
}

View file

@ -1,37 +0,0 @@
storage_box_mount: ENC[AES256_GCM,data:9lOAL3tkfB0pN4/cuM4SX0xoMrW0UUEzTN8spw3MQ3BWrfsRc3Stsce3puXz1sRf,iv:7Q9wzpBgQ3tqcfy0n/c6Ya84Kg60nhR/e2H0pVntWsY=,tag:9a0xvNBGQpCvhxgmV3hrww==,type:str]
gts_env: ENC[AES256_GCM,data:StggMdJPevrDbrVDrBDETdQYnSOaTESkgSqpGKrSHXhS21nyCE5ya7/X4l0GVTXoGCyfWG7vK+PDW22mJxpYcj2CBaVUYDu/,iv:2fqWDaWAWxTXdG7w5HU6jBcappFEByNtYs0Jd6PaYnA=,tag:KGhrMemao6g4FkEAZmmacg==,type:str]
hedgedoc_env: ENC[AES256_GCM,data:zwAA+zKSJT0tZyYArCaa1lfL0y8DNHDp/thS11DrVxNvjmk38o0ydsKArfZKzFYye+qNBzz1B4sPCdW4cFgQUNgbM+n9AvoMB8CssdmQ+sALKmozA5aEV23q+khZSGlHocP6WA==,iv:SgZruOS1nanK64Ex1dvgoD1HzbGbNa4DFSBuVoaNgEc=,tag:R+I8m1AloDCXs5PdpEpS0w==,type:str]
grafana_oauth_secret: ENC[AES256_GCM,data:43+EBnN912eK/08MdJokWPxi2Lxn/D4hSHPhNmHOk9awWQ7ut/el0vaAa+Epqnui3le2p4VuotQT6XlIuDLrixIomrc6Qw5HERAEdZmbrGvDlrrNhw==,iv:Pfn8rL0LtG3hym9EdSZRjaPLMlWlut/nt2FEtRWnULo=,tag:moDWqF3aBbnO4aG0Cysfcw==,type:str]
miniflux:
oauth2_secret: ENC[AES256_GCM,data:jcZR9E9jXNKfkAoGgBI19qQeaz26R6qiAWjP4XrftHSCQV974tjJl+fiU8Xgi0bViA==,iv:/aY0bL/oAAHBhohy3FHB/UEDYryw7A7JOKvEbLtDHJg=,tag:Fn/6NurNkRphXySR+y9S9Q==,type:str]
forgejo:
env: ENC[AES256_GCM,data:TMeguXfanISeyvsay9SBqm3SSGKpp5nCkqhHblf0QHNzHWGQKwpORmWfOtVfgOh9qdDqq8wYBpXznmbvixjV,iv:IR/rMoAIvZCw9FURmau4+g8c3pvI9BRs7v1NJ5ia4jI=,tag:kjwf6RN5HN8I2sUhDcr4UQ==,type:str]
sops:
kms: []
gcp_kms: []
azure_kv: []
hc_vault: []
age:
- recipient: age1uw059wcwfvd9xuj0hpqzqpeg7qemecspjrsatg37wc7rs2pumfdsgken0c
enc: |
-----BEGIN AGE ENCRYPTED FILE-----
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSB1aGRvUUtjcDU2bnhaNDJD
K3c5TnFJeHQzM2VpeHphR2dGeS9NYzcyYjJnCnNrQ3dxL1hqR2MyQXhldUZ1VEJp
N25nVHZ1QjRydW9hTWE5d0x2M2pPNkkKLS0tIFpiRW8rZ1Q1R1RCZGN1ZGs3ek45
UENaRjJPWFJqUlpzd3dHSC9pdnZ6STQKQaaY28FYUk3O9TTkX9LQTzlrqZVojgxY
M+N6LApfdoioQCmXduDbj18i0eUbECTBXR/uEFEIHbn6AJVD/vx7iw==
-----END AGE ENCRYPTED FILE-----
- recipient: age1jle2auermhswqtehww9gqada8car5aczrx43ztzqf9wtcld0sfmqzaecta
enc: |
-----BEGIN AGE ENCRYPTED FILE-----
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBRY0lIeE9tWDA3Q21IWk1E
YnlaQUJybFB2bmFpbG1UZ0UyNG16WkRkZlNVCmUySHVBcXpWekpVN3R5dGs5ODY1
V1ZlUk4zRSs1NkVjY3JSMVVQSXJ1OEkKLS0tIFMzeUNaYVpoNnV3TE1oamEwTEo2
dnFBa0lDWWZtS1BHdzBoVzNTaGNkSEEKi/W1n7RT8NpTp00SBMwxsUJAPDhumJ/i
V2VnaSNwouD3SswTcoBzqQpBP9XrqzjIYGke90ZODFQbMY9WDQ+O0g==
-----END AGE ENCRYPTED FILE-----
lastmodified: "2024-08-21T05:54:31Z"
mac: ENC[AES256_GCM,data:oNBabsDRuHjMBXynr8ytCLmv5NPyA0mRUcPJfFZjjAb9ZbGP+pquwJT3S0l2yo4Nsd0YQP8X1pGS3PEv9v+N538bxmMJJCERR7iZ5U5G4h0AvKi+UkjkveDdhPWBXhC1O+Up7reT/LLzOiZ1WUHCYRQfcb9R1RL3G2NpeYuOShk=,iv:FLmtKyZjZuGDnMjOgJdoIU9EXLQSZavs8f4q2C+Sxbk=,tag:sGoJNppCTYxZ2u2l0eMHgg==,type:str]
pgp: []
unencrypted_suffix: _unencrypted
version: 3.9.0

View file

@ -1,299 +0,0 @@
{ config, pkgs, lib, ... }:
let
kanidm_listen_port = 5324;
in
{
networking.firewall.allowedTCPPorts = [ 80 443 2222 8448 ];
networking.firewall.allowedUDPPorts = [ 80 443 8448 ];
custom.vaultwarden = {
enable = true;
domain = "vaultwarden.xinyang.life";
};
custom.hedgedoc = {
enable = true;
caddy = true;
domain = "docs.xinyang.life";
mediaPath = "/mnt/storage/hedgedoc";
oidc = {
enable = true;
baseURL = "https://auth.xinyang.life/oauth2/openid/hedgedoc";
authorizationURL = "https://auth.xinyang.life/ui/oauth2";
tokenURL = "https://auth.xinyang.life/oauth2/token";
userProfileURL = "https://auth.xinyang.life/oauth2/openid/hedgedoc/userinfo";
};
environmentFile = config.sops.secrets.hedgedoc_env.path;
};
custom.prometheus = {
enable = true;
exporters.blackbox.enable = true;
exporters.miniflux.enable = true;
};
systemd.mounts = map
(share: {
what = "//u380335-sub1.your-storagebox.de/u380335-sub1/${share}";
where = "/mnt/storage/${share}";
type = "cifs";
options = "rw,uid=${share},gid=${share},credentials=${config.sops.secrets.storage_box_mount.path},_netdev,fsc";
before = [ "${share}.service" ];
after = [ "cachefilesd.service" ];
wantedBy = [ "${share}.service" ];
}) [ "forgejo" "gotosocial" "conduit" "hedgedoc" ];
services.cachefilesd.enable = true;
system.activationScripts = {
conduit-media-link.text = ''
mkdir -m 700 -p /var/lib/private/matrix-conduit/media
chown conduit:conduit /var/lib/private/matrix-conduit/media
mount --bind --verbose /mnt/storage/conduit/media /var/lib/private/matrix-conduit/media
'';
};
security.acme = {
acceptTerms = true;
certs."auth.xinyang.life" = {
email = "lixinyang411@gmail.com";
listenHTTP = "127.0.0.1:1360";
group = "kanidm";
};
};
services.ntfy-sh = {
enable = true;
group = "caddy";
settings = {
listen-unix = "/var/run/ntfy-sh/ntfy.sock";
listen-unix-mode = 432; # octal 0660
base-url = "https://ntfy.xinyang.life";
};
};
systemd.services.ntfy-sh.serviceConfig.RuntimeDirectory = "ntfy-sh";
services.kanidm = {
package = pkgs.kanidm.withSecretProvisioning;
enableServer = true;
serverSettings = {
domain = "auth.xinyang.life";
origin = "https://auth.xinyang.life";
bindaddress = "[::]:${toString kanidm_listen_port}";
tls_key = ''${config.security.acme.certs."auth.xinyang.life".directory}/key.pem'';
tls_chain = ''${config.security.acme.certs."auth.xinyang.life".directory}/fullchain.pem'';
# db_path = "/var/lib/kanidm/kanidm.db";
};
provision = import ./kanidm-provision.nix;
};
custom.miniflux = {
enable = true;
environment = {
LOG_LEVEL = "debug";
LISTEN_ADDR = "127.0.0.1:58173";
BASE_URL = "https://rss.xinyang.life/";
OAUTH2_PROVIDER = "oidc";
OAUTH2_CLIENT_ID = "miniflux";
OAUTH2_REDIRECT_URL = "https://rss.xinyang.life/oauth2/oidc/callback";
OAUTH2_OIDC_DISCOVERY_ENDPOINT = "https://auth.xinyang.life/oauth2/openid/miniflux";
OAUTH2_USER_CREATION = 1;
};
oauth2SecretFile = config.sops.secrets."miniflux/oauth2_secret".path;
};
services.matrix-conduit = {
enable = true;
# package = inputs.conduit.packages.${pkgs.system}.default;
package = pkgs.matrix-conduit;
settings.global = {
server_name = "xinyang.life";
port = 6167;
# database_path = "/var/lib/matrix-conduit/";
max_concurrent_requests = 100;
log = "info";
database_backend = "rocksdb";
allow_registration = false;
well_known = {
client = "https://msg.xinyang.life";
server = "msg.xinyang.life:443";
};
};
};
services.gotosocial = {
enable = true;
settings = {
log-level = "debug";
host = "xinyang.life";
letsencrypt-enabled = false;
bind-address = "localhost";
instance-expose-public-timeline = true;
oidc-enabled = true;
oidc-idp-name = "Kanidm";
oidc-issuer = "https://auth.xinyang.life/oauth2/openid/gts";
oidc-client-id = "gts";
oidc-link-existing = true;
storage-local-base-path = "/mnt/storage/gotosocial/storage";
};
environmentFile = config.sops.secrets.gts_env.path;
};
services.forgejo = {
enable = true;
# Use cutting edge instead of lts
package = pkgs.forgejo;
repositoryRoot = "/mnt/storage/forgejo/repositories";
lfs = {
enable = true;
contentDir = "/mnt/storage/forgejo/lfs";
};
settings = {
service.DISABLE_REGISTRATION = true;
server = {
ROOT_URL = "https://git.xinyang.life/";
START_SSH_SERVER = false;
SSH_USER = config.services.forgejo.user;
SSH_DOMAIN = "ssh.xinyang.life";
SSH_PORT = 22;
LFS_MAX_FILE_SIZE = 10737418240;
LANDING_PAGE = "/explore/repos";
};
repository = {
ENABLE_PUSH_CREATE_USER = true;
};
service = {
ENABLE_BASIC_AUTHENTICATION = false;
};
oauth2 = {
ENABLED = false; # Disable forgejo as oauth2 provider
};
oauth2_client = {
ACCOUNT_LINKING = "auto";
USERNAME = "email";
ENABLE_AUTO_REGISTRATION = true;
UPDATE_AVATAR = false;
OPENID_CONNECT_SCOPES = "openid profile email groups";
};
other = {
SHOW_FOOTER_VERSION = false;
};
};
};
systemd.services.forgejo = {
serviceConfig = {
EnvironmentFile = config.sops.secrets."forgejo/env".path;
ExecStartPost = ''
${lib.getExe config.services.forgejo.package} admin auth update-oauth \
--id 1 \
--name kanidm \
--provider openidConnect \
--key forgejo \
--secret $CLIENT_SECRET \
--icon-url https://auth.xinyang.life/pkg/img/favicon.png \
--group-claim-name forgejo_role --admin-group Admin
'';
};
};
services.grafana = {
enable = true;
settings = {
server = {
http_addr = "127.0.0.1";
http_port = 3003;
root_url = "https://grafana.xinyang.life";
domain = "grafana.xinyang.life";
};
"auth.generic_oauth" = {
enabled = true;
name = "Kanidm";
client_id = "grafana";
scopes = "openid,profile,email,groups";
auth_url = "https://auth.xinyang.life/ui/oauth2";
token_url = "https://auth.xinyang.life/oauth2/token";
api_url = "https://auth.xinyang.life/oauth2/openid/grafana/userinfo";
use_pkce = true;
use_refresh_token = true;
allow_sign_up = true;
login_attribute_path = "preferred_username";
groups_attribute_path = "groups";
role_attribute_path = "contains(grafana_role[*], 'GrafanaAdmin') && 'GrafanaAdmin' || contains(grafana_role[*], 'Admin') && 'Admin' || contains(grafana_role[*], 'Editor') && 'Editor' || 'Viewer'";
allow_assign_grafana_admin = true;
auto_login = true;
};
"auth" = { disable_login_form = true; };
};
};
systemd.services.grafana.serviceConfig.EnvironmentFile = config.sops.secrets.grafana_oauth_secret.path;
users.users.git = {
isSystemUser = true;
useDefaultShell = true;
group = "git";
extraGroups = [ "forgejo" ];
};
users.groups.git = { };
users.users = {
${config.services.caddy.user}.extraGroups = [
config.services.ntfy-sh.group
];
};
services.caddy = {
enable = true;
virtualHosts."xinyang.life:443".extraConfig = ''
tls internal
encode zstd gzip
reverse_proxy /.well-known/matrix/* localhost:6167
reverse_proxy * http://localhost:8080 {
flush_interval -1
}
'';
virtualHosts."https://msg.xinyang.life:443".extraConfig = ''
reverse_proxy /_matrix/* localhost:6167
'';
virtualHosts."https://git.xinyang.life:443".extraConfig = ''
reverse_proxy http://${config.services.gitea.settings.server.DOMAIN}:${toString config.services.gitea.settings.server.HTTP_PORT}
'';
virtualHosts."http://auth.xinyang.life:80".extraConfig = ''
reverse_proxy ${config.security.acme.certs."auth.xinyang.life".listenHTTP}
'';
virtualHosts."https://auth.xinyang.life".extraConfig = ''
reverse_proxy https://127.0.0.1:${toString kanidm_listen_port} {
header_up Host {upstream_hostport}
header_down Access-Control-Allow-Origin "*"
transport http {
tls_server_name ${config.services.kanidm.serverSettings.domain}
}
}
'';
virtualHosts."https://rss.xinyang.life".extraConfig = ''
reverse_proxy ${config.custom.miniflux.environment.LISTEN_ADDR}
'';
virtualHosts."https://ntfy.xinyang.life".extraConfig = ''
reverse_proxy unix/${config.services.ntfy-sh.settings.listen-unix}
@httpget {
protocol http
method GET
path_regexp ^/([-_a-z0-9]{0,64}$|docs/|static/)
}
redir @httpget https://{host}{uri}
'';
virtualHosts."https://grafana.xinyang.life".extraConfig =
let
grafanaSettings = config.services.grafana.settings.server;
in
''
reverse_proxy http://${grafanaSettings.http_addr}:${toString grafanaSettings.http_port}
'';
};
}

View file

@ -1,22 +0,0 @@
{ pkgs, config, ... }:
{
sops.secrets = {
autofs-nas = {
owner = "davfs2";
};
autofs-nas-secret = {
path = "/etc/davfs2/secrets";
};
};
fileSystems."/media/nas" = {
device = "https://home.xinyang.life:5244/dav";
fsType = "davfs";
options = [
"uid=1000"
"gid=1000"
"rw"
"_netdev"
];
};
}

View file

@ -1,55 +0,0 @@
{ config, lib, pkgs, ... }:
{
imports = [
./hass.nix
];
commonSettings.nix.enableMirrors = true;
nixpkgs.overlays = [
# Workaround https://github.com/NixOS/nixpkgs/issues/126755#issuecomment-869149243
(final: super: {
makeModulesClosure = x:
super.makeModulesClosure (x // { allowMissing = true; });
})
];
environment.systemPackages = with pkgs; [
git
libraspberrypi
raspberrypi-eeprom
];
system.stateVersion = "24.05";
networking = {
hostName = "raspite";
useDHCP = false;
interfaces.eth0.useDHCP = true;
};
# boot.kernelPackages = pkgs.linuxPackages_stable;
custom.kanidm-client = {
enable = true;
uri = "https://auth.xinyang.life";
asSSHAuth = {
enable = true;
allowedGroups = [ "linux_users" ];
hardening = true;
};
sudoers = [ "xin@auth.xinyang.life" ];
};
security.sudo = {
execWheelOnly = true;
wheelNeedsPassword = false;
};
# fileSystems."/".fsType = lib.mkForce "btrfs";
boot.supportedFilesystems.zfs = lib.mkForce false;
services.dae.enable = false;
services.dae.configFile = "/var/lib/dae/config.dae";
}

View file

@ -1,50 +0,0 @@
{ config, pkgs, ... }: {
services.home-assistant = {
enable = true;
extraComponents = [
"default_config"
"esphome"
"met"
"radio_browser"
];
openFirewall = false;
config = {
default_config = {};
http = {
server_host = "::1";
base_url = "raspite.local:1000";
use_x_forward_for = true;
trusted_proxies = [
"::1"
];
};
};
};
services.esphome = {
enable = true;
openFirewall = false;
};
users.groups.dialout.members = config.users.groups.wheel.members;
environment.systemPackages = with pkgs; [
zigbee2mqtt
];
networking.firewall.allowedTCPPorts = [ 1000 1001 ];
services.caddy = {
enable = true;
virtualHosts = {
# reverse_proxy ${config.services.home-assistant.config.http.server_host}:${toString config.services.home-assistant.config.http.server_port}
"raspite.local:1000".extraConfig = ''
reverse_proxy http://[::1]:8123
'';
"raspite.local:1001".extraConfig = ''
reverse_proxy ${config.services.esphome.address}:${toString config.services.esphome.port}
'';
};
};
}

View file

@ -1,30 +0,0 @@
password: ENC[AES256_GCM,data:QHPNTvjNjrcUaV7aVvnFQFF+1bA+g1Y2emYIabBgHQ7Dmg7SuOwVpBsZCvsh+BgrWLykK3Gcf+huTMzixjaqXbGHrpqx9Eq9wi1O1alVG8bJ/UvWr7H3qBCuye85KUopBxXLF93skT7H1Q==,iv:Iq/s+AuMJN/Z/Pbc5UsZQA6gvnPXxihKJzWYl+N6Gmc=,tag:6UvNTQlLrl1ay3BI6vPqTw==,type:str]
sops:
kms: []
gcp_kms: []
azure_kv: []
hc_vault: []
age:
- recipient: age1uw059wcwfvd9xuj0hpqzqpeg7qemecspjrsatg37wc7rs2pumfdsgken0c
enc: |
-----BEGIN AGE ENCRYPTED FILE-----
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBieXZQcFZ6R0ZBQUdTMWtL
QXM2djdBNThrNnpuT1lpNDU1R3NIM2FRNnhZCkZqbUtrWldFMS9oOTE3T2ZCTklm
emxsL21pQThiMDJIUXA1Y0RKSVBRWFUKLS0tIE1qK0dySHZHUVZ1aDZoZ1lEZHoy
dnBLOWV4NjBrZzM5VkhRZFFrNFByVFkKK7j/rDiD7WbCU/Z1+FRuxjOitS6Y9cc1
L2oW35AJluG27tdwe39nBORzeLwDrcFy5TpUSV9hMEBbeDBlhLNSiA==
-----END AGE ENCRYPTED FILE-----
- recipient: age1nugzw24upk8pz5lyz2z89qk8se4gpcsg3ypcs58nykncr56sevrsm8qpvj
enc: |
-----BEGIN AGE ENCRYPTED FILE-----
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBPb0RxTHFhZjZ5bEtpblo1
VHJkeDFpNjhoc294eWs5TmxxcEMwOTQ4SmxVCmp1dnFXSlNiUzdtWm9WSmlMa3BR
RDFmWVdxcXJzRmdzbzVOMkUvNDd4Y1UKLS0tIDVkNHBrYWFmNWtkNllidUlPdFJ1
djhXQ2RzM0JEdnRvUkxVNm9MdFNJUHMKmacD8MIV7r92c5KbJtg7CbnI09QMclQl
5rIF5vcgaRRpS6zXq22OgxSjsjIHg7jDOkUJdueGNHzc4f9F91+0yQ==
-----END AGE ENCRYPTED FILE-----
lastmodified: "2023-04-23T03:02:43Z"
mac: ENC[AES256_GCM,data:7k+Eoua6DviF6XN5QiVOXE4LHr0gggvvYY9EMBU4J6RsA9hzi0L3DjdofppAvG2928mCd/SYiZC3vGU8UFohXbZuxFLq9YJGkE1P+VxvlggkMKoJkIbE2d2t78zm2gt4nd60tDyJgYINqbbgfs2qOdnm8Y/WShRkmNs/ggf5Azo=,iv:cXoP6GYOzhfXov/l9rSg/2GIGI4aeJonAXCQ6k6YuaQ=,tag:Tv/JYpj6DfhddSzSkh8zcQ==,type:str]
pgp: []
unencrypted_suffix: _unencrypted
version: 3.7.3

View file

@ -1,84 +0,0 @@
clash_subscription_link: ENC[AES256_GCM,data:Vwy0c8gOeR1XG/QNp8TGuBe/5kezD7SSStN/iCnihbbJYW78LNfPfvmVAEXjQlf5Ycts2Cb2JHGtWp3rmQQtWBx8LfIewqhNDk9fCywqIv7uSmqVpJNTHfYhjpF6PLvtz51VfTKph+fplZ9dMu23P9g7Wn6dzVizo8DX6xHWN2jDyHza5zkiNrzbmiaLwbLu1dAzvNSI67A=,iv:pZ189IPPCBjscXzEdgQCRdFlls3TniwDfNCd+H1FFaQ=,tag:dpt+3kdx8m1f0X0SHm+ATA==,type:str]
autofs-nas: ENC[AES256_GCM,data:wcrA2t8/i9PaxA1PQ3CDVJZUhVchGV4vCfa5j/ReNahKV3cfDf2owbpeB827sMpjYyyvSH6nri7mra/BLMAPcgySCpZNAgdR9DQZXAQ=,iv:QJzsS5a6vWeoBxkB13yXdVbyn0tt2QTvqj0LaHn6S2g=,tag:TtgubLgWBBzl67MVal5BvQ==,type:str]
autofs-nas-secret: ENC[AES256_GCM,data:OBh8h5CFv1Z4G6bMesna4zmXNASKhYdjFBvg47T9aKBCLDp/xVWnnQj8N7AFGg49wJ+0gYuqb33lIqpSnQ==,iv:UCaGeE8j4RqJzA0xhu3oB2xvzombzQD3fjLKCWd5fDg=,tag:+Oc78ddpLH7R2aT7gW3Ouw==,type:str]
github_public_token: ENC[AES256_GCM,data:AmAfmq5mDGxmHUUlGzD7k50jRTCcnZqqFdYdrMtYysmw6FUjPc1YgsEVNqHOjiEMYbr8Gs+wjVu8BYIuh1wuDzOOfE+ejIbosrOtK4dCapmIzZFlRiK/AyrUCm2qDWUObhJDPMJN4px947VFJ5to5GLifGEXdUGm,iv:PJSFtJBelyc3rzd6hqjMp+ciU2Q3FTOEXsiq5F2KKTY=,tag:MjrTl+4+8SZeBDJpUJtsiw==,type:str]
singbox_sg_server: ENC[AES256_GCM,data:5rogqKm5yiy5Yvz4Vo1a6Q==,iv:Vx9wNTdVHkReux4YeQY+0VkC1Wqg/CRkY7frVY/3e50=,tag:9fVlCP/DadcOvhO3c1oCzw==,type:str]
singbox_jp_server: ENC[AES256_GCM,data:xKTcxkcu1WIsT/wlMpEoqGJK,iv:nXetY339YuOi2jFEb3xkPTglHRMk/quIrQL4ko+8MxY=,tag:+Nwsx65/gdrDhL1ZurR5Ng==,type:str]
singbox_password: ENC[AES256_GCM,data:0tBIzwtNSQqbGlD+CDnQfJigbFVBChEL,iv:W2HaHeSkvmS6jHSnfOJ6tD2QXuUq1A+mfZf7sEXB++E=,tag:5BtYAv1NO70IL4m/uG8QKA==,type:str]
singbox_uuid: ENC[AES256_GCM,data:ufN+vDl/rDASoQL23tHwlr3ybMyrlC/Kd7bT0c5+SP+bc6Zj,iv:+uwt/N9LpFaJK6MjoczyrZ039MDZn4kRmtEoq4OvdFU=,tag:6Yma9+yrISwQoSRDgUbuwA==,type:str]
grafana_cloud_api: ENC[AES256_GCM,data:Pz+tE09dcJa+ZEWS3vtpOtitGCA9Cg/+gOd/0FsF8ooxzPyN9/UMuTcP02aIPW5v7yZCkGJOAXufIyechNf0crgAV/KmwGGwixH7I+1f3sDtGiFZEMnQgrysyfJo0KIrIZ8XP0SyXDs3vKjDU8cUI4+IyucHacWQ1kWdEtINjcPNHRPS2yaMUIvsRn0z8Cs2byMD3ghUHHHOz40CuO6r4A==,iv:cHvbeCmLFmJPNKsl1BBYx9WJP7ZJWi+8c9yHZWc6FTs=,tag:yWXtPokYE4frCmzzzyEqEg==,type:str]
private_dns_address: ENC[AES256_GCM,data:m/u3oc+6ef8dLa7Dpu+5T9TTSdXqJjS9ecA+sPj0r8qX06+QgiQnpmEW4w==,iv:8+qG5rQXAKfrykEjt9qrbtyNaBuKvi7EaIWouRqEipY=,tag:XlMccTKL239/NnAprtqYrg==,type:str]
sops:
kms: []
gcp_kms: []
azure_kv: []
hc_vault: []
age:
- recipient: age1uw059wcwfvd9xuj0hpqzqpeg7qemecspjrsatg37wc7rs2pumfdsgken0c
enc: |
-----BEGIN AGE ENCRYPTED FILE-----
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBMdjlhNVZpUjYzRTVXNG9Y
S0lEUVdoM003YVZoeXYyOXdwY3Rla3VJSkZvCkl0a3FPeVpMY1JTWkdCb3NaeVBQ
dHVSVzg1cDNIS3JnMmYxbUlzbjFicG8KLS0tIHFENDNaZENzSzJQZDVLSVJ5VHBP
aVpJN1dkbEQ2djQyWVdRTUx4NGdaaTgKgfcGovmMgVFHkPLHT7C5bg75LXg8MFK0
s8IL8qhHif4uzMuFjdw9MzyuQc1bqGzazX5YC1MYLYCOWHRlLq9mXw==
-----END AGE ENCRYPTED FILE-----
- recipient: age1ytwfqfeez3dqtazyjltn7mznccwx3ua8djhned7n8mxqhw4p6e5s97skfa
enc: |
-----BEGIN AGE ENCRYPTED FILE-----
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBWQXdMdzMxNzE3SHpZR09w
OTFtNzJLdVk5bWlyNGl4RzA4NWFUQTlvbUQ4ClhGZHI3ekJWYnNwamJXWWVtc3do
TXpoWERqT24rMjRtQUJUb2RKSm9BUjQKLS0tIHd6QXUrWVJ5aU52VEtDL01Kd2d2
V3U4cTNoVzYzdmt5YkpNUmsyUWtCaEkKhxEQVVt2zvVGFGtlfPr0sQ7b0yUDRDOV
CN8nxyO0NiuvEKSkw+KCkcNWNQZDnHTQ3pwWyAohRZk3vB/RSuApCg==
-----END AGE ENCRYPTED FILE-----
- recipient: age1nugzw24upk8pz5lyz2z89qk8se4gpcsg3ypcs58nykncr56sevrsm8qpvj
enc: |
-----BEGIN AGE ENCRYPTED FILE-----
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBsdlh1Kyt4KzlFR2RkTmFo
S00zK1RDNnJwVzQ4Um93TDBEcnJZUjJLUG00CjloMFdaNm5LU2lRRVpnM0RpN3BR
Ly9pUkxuZHd3NHJRSG1Ha3ZVcE50RkUKLS0tIDN1K0xnb01EL2Q3aG5RV0grdmdl
TWh3ZStZQ3lNYkh2cjJ1RWhLRDJ0KzQK/+R6hFg8ErtT/rkSOCwRdArTPIE/J9Yv
2qZmREM7q99L5w6lEBTn9SRekowk0ncwIoTxRfn576wyl++b8gBv9Q==
-----END AGE ENCRYPTED FILE-----
- recipient: age13s6rwd3wjk2x5wkn69tdczhl3l5d7mfmlv90efsv4q67jne43qss9tcakx
enc: |
-----BEGIN AGE ENCRYPTED FILE-----
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBJelptN09Oa0NRdTFER2du
clZGM09uMlhpMlZDQ2VvTTZOZ09VWGNwaWpjCmRuMjM3VTRpT3hRaWpEYW5HaWRr
K2pEM3dLYjhSS25hSUtrYkRvYXpCd2MKLS0tIHU2eDlXdVBlZUFTMjYxRTladVJV
cjZ0dGtmM29YdXI5Z1RpVVdRSktBU2MKdR5d6fb2EHX5j51qE5gg0GXKjy4fCpT0
Q+fZslCPDZqaOX/9kGT874TuW4CC1wttpsCDNIEzrX54SvIGfsVPgg==
-----END AGE ENCRYPTED FILE-----
- recipient: age1t5nw2jx4dw67jkf72uxcxt72j7lq3xyj35lvl09f8kala90h2g2s2a5yvj
enc: |
-----BEGIN AGE ENCRYPTED FILE-----
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBmRUhOaVhSMFJFcC9qYytK
dHJ1ZUg1SWRBeTVSeFhDRW1VbG1HWUJaUEhvCnBOaENFUXlJWHAxQ0ZGVGFxQkpC
b3dwb0VJVTR1MUNDT3VQR0tsNE5vUDQKLS0tIEJkbWN5MWRtKzRveldvT2dMR2k1
djdBQzNvSFNPRDZwN1B1dG5sUzlRdzgK35bNxRGDQw+dtnXcXSXk67kJFce52vqn
srABR9FOYmSfesLKXOdKItLAGffkfB7kuiXO7CvyVTkgJOjBgK6Tnw==
-----END AGE ENCRYPTED FILE-----
- recipient: age1fw2sqaa5s9c8ml6ncsexkj8ar4288387ju92ytjys4awf9aw6smqqz94dh
enc: |
-----BEGIN AGE ENCRYPTED FILE-----
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBNb2JOOUlGL1pCVXVYZk1j
cWg0NE13WnBUWDA4VTNRdlNmWktRN0lJbkVBCkpHTklwbnFsd0NBOTY5V0JCTVJN
alVFeW41ajlZR2dHZDlrL2FtazB6QU0KLS0tIDhoTXppS0lnZmFJY1lhSDBudVB4
NHFLdnorOUtJSzVPWldYakppZFJwdlEKbZnT7m6R7H/yLG+tDbQECgQVGX0xT4jC
67z8k6xbnsT2srhhXk/NHi+/j7AcHhPG6cTO1z8MrxkMikk8ihU1Iw==
-----END AGE ENCRYPTED FILE-----
- recipient: age1jle2auermhswqtehww9gqada8car5aczrx43ztzqf9wtcld0sfmqzaecta
enc: |
-----BEGIN AGE ENCRYPTED FILE-----
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBIaHFOa1ArRW5xWFAyWXlh
enpQUzZKbFFFUzN1cisrd2JGelpXSWppRnhvCmY5VDlSTFhJakt3aU8zYjRrZXVQ
b3o2NlpCeGZZU1ROeW5XOFVpdEZnZXcKLS0tIGZ5M2IxNHp0Qm8rckROdy96a0pG
NjVEaWN3cU1rRjQ2a29wV1g1NzE0UTAKNefzj+p+U735LHqm5lnWGHCARuqvFmgA
6bxJN9frAMZQIXZSwOTrfpYrTmKcBLcfWxq7LUPluw9HinQnkFpWqg==
-----END AGE ENCRYPTED FILE-----
lastmodified: "2024-07-17T03:43:42Z"
mac: ENC[AES256_GCM,data:5dnJSeY8lZrIo/bl8MECwmaQo+fQ+BEun9BQ7tFHUo1lzk4wn2N1RuPMuPLPE1wARfOJR2lUyh+o3froFqQT6EGDhA68ETHxm+NqxbstouK+pSu0WJzg7ImuAuzd8B81xXBTQj6umOZy6oRsgvAYo2C8aEfzs19+kYrAM4bXo7k=,iv:YvtOVDD347fCFvqyTljHOQm6ewSR01WlYVBNVdm/BNc=,tag:r/HzESO6csxzLJMHTRC7bA==,type:str]
pgp: []
unencrypted_suffix: _unencrypted
version: 3.9.0

View file

@ -1,34 +0,0 @@
{ inputs, config, lib, ... }:
{
imports = [ inputs.sops-nix.nixosModules.sops ];
config = {
sops = {
defaultSopsFile = ./secrets.yaml;
# TODO: How to generate this key when bootstrap?
age.sshKeyPaths = [ "/etc/ssh/ssh_host_ed25519_key" ];
secrets = {
github_public_token = {
owner = "root";
};
singbox_sg_server = {
owner = "root";
};
singbox_jp_server = {
owner = "root";
};
singbox_password = {
owner = "root";
};
singbox_uuid = {
owner = "root";
};
private_dns_address = {
owner = "root";
};
};
secrets.grafana_cloud_api = lib.mkIf config.services.prometheus.enable {
owner = "prometheus";
};
};
};
}

View file

@ -1,132 +0,0 @@
{ inputs, config, pkgs, lib, modulesPath, ... }:
with lib;
{
imports = [
inputs.sops-nix.nixosModules.sops
(modulesPath + "/profiles/qemu-guest.nix")
];
config = {
networking.hostName = "weilite";
commonSettings = {
auth.enable = true;
nix = {
enable = true;
enableMirrors = true;
};
};
boot = {
loader = {
systemd-boot.enable = true;
efi.canTouchEfiVariables = true;
};
initrd.availableKernelModules = [ "uhci_hcd" "ehci_pci" "ahci" "usb_storage" "sd_mod" ];
kernelModules = [ "kvm-intel" ];
};
environment.systemPackages = [
pkgs.virtiofsd
];
sops = {
defaultSopsFile = ./secrets.yaml;
age.sshKeyPaths = [ "/etc/ssh/ssh_host_ed25519_key" ];
secrets = {
cloudflare_dns_token = {
owner = "caddy";
mode = "400";
};
};
};
custom.prometheus = {
enable = true;
};
systemd.mounts = [
{ what = "immich";
where = "/mnt/XinPhotos/immich";
type = "virtiofs";
options = "rw";
wantedBy = [ "immich-server.service" ];
}
{ what = "originals";
where = "/mnt/XinPhotos/originals";
type = "virtiofs";
options = "ro,nodev,nosuid";
wantedBy = [ "immich-server.service" ];
}
];
services.openssh.ports = [ 22 2222 ];
services.immich = {
enable = true;
mediaLocation = "/mnt/XinPhotos/immich";
host = "127.0.0.1";
port = 3001;
openFirewall = true;
machine-learning.enable = false;
environment = {
IMMICH_MACHINE_LEARNING_ENABLED = "false";
};
};
services.dae = {
enable = true;
configFile = "/var/lib/dae/config.dae";
};
services.tailscale = {
enable = true;
openFirewall = true;
permitCertUid = "caddy";
};
services.caddy = {
enable = true;
package = pkgs.caddy.withPlugins {
caddyModules = [
{ repo = "github.com/caddy-dns/cloudflare"; version = "89f16b99c18ef49c8bb470a82f895bce01cbaece"; }
];
vendorHash = "sha256-fTcMtg5GGEgclIwJCav0jjWpqT+nKw2OF1Ow0MEEitk=";
};
virtualHosts."weilite.coho-tet.ts.net:8080".extraConfig = ''
reverse_proxy 127.0.0.1:${toString config.services.immich.port}
'';
# API Token must be added in systemd environment file
virtualHosts."immich.xinyang.life:8000".extraConfig = ''
tls {
dns cloudflare {env.CLOUDFLARE_API_TOKEN}
}
reverse_proxy 127.0.0.1:${toString config.services.immich.port}
'';
};
networking.firewall.allowedTCPPorts = [ 8000 ];
systemd.services.caddy = {
serviceConfig = {
EnvironmentFile = config.sops.secrets.cloudflare_dns_token.path;
};
};
time.timeZone = "Asia/Shanghai";
fileSystems."/" = {
device = "/dev/disk/by-label/nixos";
fsType = "btrfs";
};
fileSystems."/boot" = {
device = "/dev/sda1";
fsType = "vfat";
options = [ "fmask=0022" "dmask=0022" ];
};
system.stateVersion = "24.11";
};
}

View file

@ -1,30 +0,0 @@
cloudflare_dns_token: ENC[AES256_GCM,data:m4euSkxxJmiMk9UPyeni/hwpl1W9A4MM0ssg71eOBsX4fFyG39NJeKbNTddW7omBx3gKJtnrRuDdOj5wpg==,iv:eRVzsGwz8hWC42jM+VeSUWCS9Gi8VGSY8Fyh+En0jEI=,tag:NNE8VeNQ8kp9KyziVokyuQ==,type:str]
sops:
kms: []
gcp_kms: []
azure_kv: []
hc_vault: []
age:
- recipient: age1uw059wcwfvd9xuj0hpqzqpeg7qemecspjrsatg37wc7rs2pumfdsgken0c
enc: |
-----BEGIN AGE ENCRYPTED FILE-----
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBtYkRNYmtjUkpoOXhRY1Yz
UkxnSEJiSXRvMy9WQWx5R1VHYVlnL1R2Tm1jCk8yUi80MG9kTWtSRndXRThuVThv
bERaUGwzaVJDem9IeFFIb2hiT1ZjTzQKLS0tIHo4bDJQa2dVbTl1aWxyYVd6bkl0
c0g5TW03TU51L1hiSk95S05Eaks5TEEKBfA6XNAtcl7bKgDyVmuO6M45x9IJ7gqV
Nd+BvOK+iomEubZqsyMPLM3NfOL1dwSOnmwSdUZasUzuGCaw6IdlOA==
-----END AGE ENCRYPTED FILE-----
- recipient: age17r3fxfmt6hgwe984w4lds9u0cnkf5ttq8hnqt800ayfmx7t8t5gqjddyml
enc: |
-----BEGIN AGE ENCRYPTED FILE-----
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBBZlVTY1hhcC95RExJL1Jn
blBncWxlWmxsQS8vQ3dhd1pXR1VCbXltUEQ4ClE0NEZweERYK3cyelpDRjkrNlBH
RHBIQTI0M2pnNm5qdnorNWFmMmd0ZFUKLS0tIEE4cFVteUZjT04wbk1RSWlmOU1P
V0thRjU4WGpQRGFpcnoxSjZTZHhTTkUKzNMHh9p7GUY3hL5XZ9S4x20CwaItsXFV
RKujsFVVBd8Kuq/jyOCBTRCscuHI4LW/wYeZYHFEZFSTK2liAqspgw==
-----END AGE ENCRYPTED FILE-----
lastmodified: "2024-07-29T09:05:41Z"
mac: ENC[AES256_GCM,data:4RX5WtJnI4R2OAKNljo8IhBNTR+PSSFsT4rE0mjS4pEdWyJilAgLwcVU0DEDp7thHeT+YyjDQ9d3z1aeGALlJ3sV57azu4F9/KXixvZMKJtmFRsC74OTSBzFfnA4W9MjOTn95L+RQOJ/3UH1FAZ7UHAe3Os98kNW98D/Nv4S9us=,iv:En7RNovlF1yRURu9fGHRgWvsr3FzpeLtrKELtqkJUb8=,tag:4eVlLsraN17rBbAL7xOHnQ==,type:str]
pgp: []
unencrypted_suffix: _unencrypted
version: 3.9.0

View file

@ -1,32 +0,0 @@
{ config, pkgs, lib, ... }:
with lib;
let
cfg = config.custom-hm.alacritty;
in
{
options.custom-hm.alacritty = {
enable = mkEnableOption "alacritty";
};
config = mkIf cfg.enable {
programs.alacritty = {
enable = true;
settings = {
shell = {
program = config.programs.zellij.package + "/bin/zellij";
args = [
"attach"
"-c"
"alacritty-zellij"
];
};
font.size = 10.0;
window = {
resize_increments = true;
dynamic_padding = true;
};
};
};
};
}

View file

@ -1,12 +0,0 @@
{
imports = [
./alacritty.nix
./direnv.nix
./fish.nix
./git.nix
./tmux.nix
./vim.nix
./vscode.nix
./zellij.nix
];
}

View file

@ -1,30 +0,0 @@
{ config, lib, ... }:
with lib;
let
cfg = config.custom-hm.direnv;
changeCacheDir = ''
declare -A direnv_layout_dirs
direnv_layout_dir() {
local hash path
echo "''${direnv_layout_dirs[$PWD]:=$(
hash="$(sha1sum - <<< "$PWD" | head -c40)"
path="''${PWD//[^a-zA-Z0-9]/-}"
echo "''${XDG_CACHE_HOME}/direnv/layouts/''${hash}''${path}"
)}"
}
'';
in
{
options.custom-hm.direnv = {
enable = mkEnableOption "direnv";
};
config = {
programs = mkIf cfg.enable {
direnv = {
enable = true;
stdlib = changeCacheDir;
};
};
};
}

View file

@ -1,72 +0,0 @@
{ config, pkgs, lib, ... }:
with lib;
let
cfg = config.custom-hm.fish;
in
{
options.custom-hm.fish = {
enable = mkEnableOption "fish";
plugins = mkOption {
type = types.listOf types.str;
default = [ "pisces" "done" "hydro" "grc" ];
};
functions = {
enable = mkOption {
type = types.bool;
default = true;
};
};
alias = {
enable = mkOption {
type = types.bool;
default = true;
};
};
};
config = mkIf cfg.enable {
home.packages = [ pkgs.grc ];
programs.fish = {
enable = true;
plugins = with pkgs; (filter (
e: hasAttr e.name (builtins.listToAttrs # { "xxx" = true; }
(map (p: { name = p; value = true; }) cfg.plugins) # { name = "xxx"; value = true; }
)) [
{ name = "pisces";
src = fishPlugins.pisces.src;
}
{ name = "done";
src = fishPlugins.done.src;
}
{ name = "hydro";
src = fishPlugins.hydro.src;
}
{ name = "grc";
src = fishPlugins.grc.src;
}
]);
interactiveShellInit = let
extraInit = if cfg.functions.enable then ''
${pkgs.nix-your-shell}/bin/nix-your-shell fish | source
function fish_right_prompt
if test -n "$IN_NIX_SHELL"
echo -n "<nix-shell>"
else if test $SHLVL -ge 3
echo -n "<🚀lv$SHLVL>"
end
end
function fish_command_not_found
${pkgs.comma}/bin/comma $argv
end
'' else "";
in ''
fish_config prompt choose arrow
'' + extraInit;
functions = mkIf cfg.functions.enable {
gitignore = "curl -sL https://www.gitignore.io/api/$argv";
};
};
};
}

View file

@ -1,47 +0,0 @@
{ config, pkgs, lib, ... }:
with lib;
let
cfg = config.custom-hm.git;
in
{
options.custom-hm.git = {
enable = mkEnableOption "Enable git configuration";
signing = mkOption {
type = types.submodule {
options = {
enable = mkEnableOption "Git ssh signing";
keyFile = mkOption {
type = types.str;
default = "~/.ssh/id_ecdsa.pub";
};
};
};
};
};
config = {
programs.git = mkIf cfg.enable {
enable = true;
delta.enable = true;
userName = "Xinyang Li";
userEmail = "lixinyang411@gmail.com";
aliases = {
graph = "log --all --oneline --graph --decorate";
a = "add";
d = "diff";
s = "status";
};
signing = mkIf cfg.signing.enable {
signByDefault = true;
key = cfg.signing.keyFile;
};
extraConfig.user = mkIf cfg.signing.enable {
signingkey = cfg.signing.keyFile;
};
extraConfig.gpg = mkIf cfg.signing.enable {
format = "ssh";
};
};
};
}

View file

@ -1 +0,0 @@
{}

View file

@ -1,22 +0,0 @@
{ config, pkgs, lib, ... }:
let
inherit (lib) mkIf mkEnableOption getExe;
cfg = config.custom-hm.neovim;
tomlFormat = pkgs.formats.toml { };
neovideConfig = {
neovim-bin = getExe pkgs.nixvim;
fork = true;
};
in
{
options.custom-hm.neovim = {
enable = mkEnableOption "neovim configurations";
};
config = mkIf cfg.enable {
home.packages = with pkgs; [ nixvim neovide ];
programs.neovim.enable = false;
home.file.".config/neovide/config.toml" = {
source = tomlFormat.generate "neovide-config" neovideConfig;
};
};
}

View file

@ -1,190 +0,0 @@
{ inputs, config, lib, pkgs, ... }:
with lib;
let
cfg = config.custom-hm.vscode;
packages = {
nixPackages = {
systemPackages = with pkgs; [ nixd nixpkgs-fmt ];
extension = with inputs.nix-vscode-extensions.extensions.${pkgs.system}.vscode-marketplace; [
jnoortheen.nix-ide
];
settings = {
"nix.enableLanguageServer" = true;
"nix.formatterPath" = "nixpkgs-fmt";
"nix.serverPath" = "nixd";
};
};
cxxPackages = {
systemPackages = with pkgs; [ clang-tools cmake-format ];
extension = with inputs.nix-vscode-extensions.extensions.${pkgs.system}.vscode-marketplace; [
llvm-vs-code-extensions.vscode-clangd
(ms-vscode.cmake-tools.overrideAttrs (_: { sourceRoot = "extension"; }))
twxs.cmake
ms-vscode.cpptools
];
settings = {
"cmake.configureOnEdit" = false;
"cmake.showOptionsMovedNotification" = false;
"cmake.showNotAllDocumentsSavedQuestion" = false;
"cmake.pinnedCommands" = [
"workbench.action.tasks.configureTaskRunner"
"workbench.action.tasks.runTask"
];
"C_Cpp.intelliSenseEngine" = "Disabled";
};
};
pythonPackages = {
systemPackages = with pkgs; [ ];
extension = with inputs.nix-vscode-extensions.extensions.${pkgs.system}.vscode-marketplace; [
ms-python.python
];
settings = { };
};
scalaPackages = {
systemPackages = with pkgs; [ coursier metals ];
extension = with inputs.nix-vscode-extensions.extensions.${pkgs.system}.vscode-marketplace; [
scala-lang.scala
scalameta.metals
];
settings = { };
};
latexPackages = {
systemPackages = with pkgs; [ texliveSmall ];
extension = with inputs.nix-vscode-extensions.extensions.${pkgs.system}.vscode-marketplace; [
james-yu.latex-workshop
];
settings = {
"latex-workshop.latex.autoBuild.run" = "never";
"latex-workshop.latex.tools" = [
{
"name" = "xelatex";
"command" = "xelatex";
"args" = [ "-synctex=1" "-interaction=nonstopmode" "-file-line-error" "%DOCFILE%" ];
}
{
"name" = "pdflatex";
"command" = "pdflatex";
"args" = [ "-synctex=1" "-interaction=nonstopmode" "-file-line-error" "%DOCFILE%" ];
}
{ "name" = "bibtex"; "command" = "bibtex"; "args" = [ "%DOCFILE%" ]; }
];
"latex-workshop.latex.recipes" = [
{ "name" = "xelatex"; "tools" = [ "xelatex" ]; }
{ "name" = "pdflatex"; "tools" = [ "pdflatex" ]; }
{ "name" = "xe->bib->xe->xe"; "tools" = [ "xelatex" "bibtex" "xelatex" "xelatex" ]; }
{ "name" = "pdf->bib->pdf->pdf"; "tools" = [ "pdflatex" "bibtex" "pdflatex" "pdflatex" ]; }
];
"[latex]" = {
"editor.formatOnPaste" = false;
"editor.suggestSelection" = "recentlyusedbyprefix";
"editor.wordWrap" = "bounded";
"editor.wordWrapColumn" = 80;
"editor.unicodeHighlight.ambiguousCharacters" = false;
};
};
};
};
llmExtensions = [ pkgs.vscode-extensions.continue.continue ];
languages = [ "nix" "cxx" "python" "scala" "latex" ];
zipAttrsWithLanguageOption = (attr:
(map (l: (lib.mkIf cfg.languages.${l} packages."${l}Packages".${attr})) languages)
);
in
{
options.custom-hm.vscode = {
enable = mkEnableOption "Vscode config";
languages = {
nix = mkOption {
type = lib.types.bool;
default = true;
};
cxx = mkEnableOption "C++";
python = mkEnableOption "Python";
scala = mkEnableOption "Scala";
latex = mkEnableOption "Latex";
};
llm = mkEnableOption "tab completion with Continue and ollama";
};
config = mkIf cfg.enable {
nixpkgs.config.allowUnfree = true;
home.packages = lib.mkMerge ([
[ pkgs.clang-tools ]
(mkIf cfg.llm [ pkgs.ollama ])
] ++ zipAttrsWithLanguageOption "systemPackages");
programs.vscode = {
enable = true;
package = pkgs.vscode.override { commandLineArgs = "--enable-wayland-ime"; };
enableUpdateCheck = false;
enableExtensionUpdateCheck = false;
mutableExtensionsDir = false;
extensions = lib.mkMerge ([
(with inputs.nix-vscode-extensions.extensions.${pkgs.system}.vscode-marketplace; [
mkhl.direnv
ms-azuretools.vscode-docker
ms-vscode-remote.remote-ssh
vscodevim.vim
github.vscode-pull-request-github
gruntfuggly.todo-tree # todo highlight
# Markdown
davidanson.vscode-markdownlint
# Latex
# Scale / chisel
sterben.fpga-support
ms-vscode-remote.remote-ssh-edit
mushan.vscode-paste-image
])
(with pkgs.vscode-extensions; [
waderyan.gitblame
catppuccin.catppuccin-vsc
# Rust
rust-lang.rust-analyzer
])
(mkIf cfg.llm llmExtensions)
] ++ zipAttrsWithLanguageOption "extension");
userSettings = lib.mkMerge ([
{
"workbench.colorTheme" = "Catppuccin Macchiato";
"terminal.integrated.sendKeybindingsToShell" = true;
"extensions.ignoreRecommendations" = true;
"files.autoSave" = "afterDelay";
"editor.inlineSuggest.enabled" = true;
"editor.rulers" = [
80
];
"editor.mouseWheelZoom" = true;
"git.autofetch" = false;
"window.zoomLevel" = -1;
"extensions.experimental.affinity" = {
"vscodevim.vim" = 1;
};
}
] ++ zipAttrsWithLanguageOption "settings");
};
home.file.".continue/config.json".text = lib.generators.toJSON { } {
models = [
{
model = "AUTODETECT";
provider = "ollama";
title = "Ollama";
}
];
tabAutocompleteModel = {
model ="deepseek-coder:6.7b-base";
provider = "ollama";
title = "codegemma";
};
};
};
}

View file

@ -1,33 +0,0 @@
{ config, pkgs, lib, ... }:
with lib;
let
cfg = config.custom-hm.zellij;
in
{
options.custom-hm.zellij = {
enable = mkEnableOption "zellij configurations";
};
config = {
programs.zellij = mkIf cfg.enable {
enable = true;
settings = {
default_shell = "fish";
keybinds = {
unbind = [
"Ctrl p"
"Ctrl n"
];
shared_except = {
_args = [ "pane" "locked" ];
bind = {
_args = [ "Ctrl b"];
SwitchToMode = "Pane";
};
};
};
};
};
};
}

View file

@ -1,41 +0,0 @@
{ config, lib, pkgs, ... }:
let
inherit (lib) mkIf mkEnableOption mkOption types;
cfg = config.commonSettings.auth;
in
{
options.commonSettings.auth = {
enable = mkEnableOption "Common auth settings for servers";
};
config = mkIf cfg.enable {
custom.kanidm-client = {
enable = true;
uri = "https://auth.xinyang.life";
asSSHAuth = {
enable = true;
allowedGroups = [ "linux_users" ];
};
sudoers = [ "xin@auth.xinyang.life" ];
};
services.openssh = {
settings = {
PasswordAuthentication = false;
KbdInteractiveAuthentication = false;
PermitRootLogin = "no";
GSSAPIAuthentication = "no";
KerberosAuthentication = "no";
};
};
services.fail2ban.enable = true;
security.sudo = {
execWheelOnly = true;
wheelNeedsPassword = false;
};
};
}

View file

@ -1,61 +0,0 @@
{ config, lib, pkgs, ... }:
let
inherit (lib) mkIf mkEnableOption mkOption types;
cfg = config.commonSettings.nix;
in
{
options.commonSettings.nix = {
enable = mkOption {
default = true;
type = types.bool;
};
enableMirrors = mkEnableOption "cache.nixos.org mirrors in Mainland China";
signing = {
enable = mkEnableOption "Sign locally-built paths";
keyFile = mkOption {
default = "/etc/nix/key.private";
type = types.str;
};
};
};
config = mkIf cfg.enable {
nix.package = pkgs.nixVersions.latest;
nix.gc = {
automatic = true;
dates = "weekly";
options = "--delete-older-than 30d";
};
nix.optimise.automatic = true;
nix.settings = {
experimental-features = [ "nix-command" "flakes" ];
auto-optimise-store = true;
trusted-users = [ "root" ];
substituters = [
"https://nix-community.cachix.org"
"https://cache.garnix.io"
];
extra-substituters = mkIf cfg.enableMirrors [
"https://mirrors.cernet.edu.cn/nix-channels/store?priority=20"
];
trusted-public-keys = [
"nix-community.cachix.org-1:mB9FSh9qf2dCimDSUo8Zy7bkq5CX+/rkCWyvRCYg3Fs="
"cache.garnix.io:CTFPyKSLcx5RMJKfLo5EEPUObbA78b0YQ2DTCJXqr9g="
"xin-1:8/ul1IhdWLswERF/8RfeAw8VZqjwHrJ1x55y1yjxQ+Y="
];
secret-key-files = mkIf cfg.signing.enable [
cfg.signing.keyFile
];
};
};
}

View file

@ -1,17 +0,0 @@
{ config, pkgs, ... }:
{
imports = [
./common-settings/auth.nix
./common-settings/nix-conf.nix
./restic.nix
./vaultwarden.nix
./prometheus
./hedgedoc.nix
./sing-box.nix
./kanidm-client.nix
./ssh-tpm-agent.nix # FIXME: Waiting for upstream merge
./forgejo-actions-runner.nix
./oidc-agent.nix
./miniflux.nix
];
}

View file

@ -1,34 +0,0 @@
{ config, pkgs, lib, ... }:
let
cfg = config.custom.forgejo-actions-runner;
in
{
options = {
custom.forgejo-actions-runner = {
enable = lib.mkEnableOption "TPM supported ssh agent in go";
tokenFile = lib.mkOption {
type = lib.types.path;
};
};
};
config = lib.mkIf cfg.enable {
virtualisation.docker.enable = true;
services.gitea-actions-runner.package = pkgs.forgejo-actions-runner;
services.gitea-actions-runner.instances = {
"git.xinyang.life" = {
enable = true;
url = "https://git.xinyang.life";
tokenFile = cfg.tokenFile;
name = config.networking.hostName;
labels = [
"debian-latest:docker://node:18-bullseye"
"ubuntu-latest:docker://node:18-bullseye"
"nix:docker://xiny/nix-runner:2.21.0-pkgs-23.11"
];
settings = {
container.network = "host";
};
};
};
};
}

View file

@ -1,83 +0,0 @@
{ config, pkgs, lib, ... }:
with lib;
let
cfg = config.custom.hedgedoc;
in
{
options = {
custom.hedgedoc = {
enable = mkEnableOption "HedgeDoc Markdown Editor";
domain = mkOption {
type = types.str;
default = "docs.example.com";
description = "Domain name of the HedgeDoc server";
};
caddy = mkOption {
type = types.bool;
default = true;
description = "Enable Caddy as reverse proxy";
};
mediaPath = mkOption {
type = types.path;
default = /var/lib/hedgedoc/uploads;
description = "Directory for storing medias";
};
oidc = {
enable = mkEnableOption "OIDC support for HedgeDoc";
baseURL = mkOption {
type = types.str;
};
authorizationURL = mkOption {
type = types.str;
};
tokenURL = mkOption {
type = types.str;
};
userProfileURL = mkOption {
type = types.str;
};
};
environmentFile = mkOption {
type = types.path;
};
};
};
config = mkIf cfg.enable {
services.hedgedoc = {
enable = true;
environmentFile = cfg.environmentFile;
settings = {
domain = cfg.domain;
protocolUseSSL = cfg.caddy;
uploadsPath = cfg.mediaPath;
path = "/run/hedgedoc/hedgedoc.sock";
email = false;
allowEmailRegister = false;
oauth2 = mkIf cfg.oidc.enable {
baseURL = cfg.oidc.baseURL;
authorizationURL = cfg.oidc.authorizationURL;
tokenURL = cfg.oidc.tokenURL;
userProfileURL = cfg.oidc.userProfileURL;
userProfileEmailAttr = "email";
userProfileUsernameAttr = "name";
userProfileDisplayNameAttr = "preferred_name";
scope = "openid email profile";
clientID = "$HEDGEDOC_CLIENT_ID";
clientSecret = "$HEDGEDOC_CLIENT_SECRET";
};
allowAnonymous = false;
defaultPermission = "private";
};
};
services.caddy = mkIf cfg.caddy {
enable = true;
virtualHosts."https://${cfg.domain}".extraConfig = ''
reverse_proxy unix/${config.services.hedgedoc.settings.path}
'';
};
users.users.caddy.extraGroups = mkIf cfg.caddy [ "hedgedoc" ];
};
}

View file

@ -1,126 +0,0 @@
{ config
, lib
, ... }:
let
cfg = config.custom.sing-box-server;
secretFileType = lib.types.submodule {
_secret = lib.types.path;
};
singTls = {
enabled = true;
server_name = config.deployment.targetHost;
key_path = config.security.acme.certs.${config.deployment.targetHost}.directory + "/key.pem";
certificate_path = config.security.acme.certs.${config.deployment.targetHost}.directory + "/cert.pem";
};
in
{
options = {
enable = lib.mkEnableOption "sing-box proxy server";
users = lib.types.listOf lib.types.submodule {
name = lib.mkOption {
type = lib.types.str;
default = "proxy";
};
password = lib.mkOption {
type = secretFileType;
};
uuid = lib.mkOption {
type = secretFileType;
};
};
wgOut = {
privKeyFile = lib.mkOption {
type = lib.types.path;
};
pubkey = lib.mkOption {
type = lib.types.str;
default = "bmXOC+F1FxEMF9dyiK2H5/1SUtzH0JuVo51h2wPfgyo=";
};
};
inbounds = {
trojan = {
enable = lib.mkOption {
type = lib.types.bool;
default = true;
};
};
tuic = {
enable = lib.mkOption {
type = lib.types.bool;
default = true;
};
ports = lib.mkOption {
type = lib.types.listOf lib.types.int;
default = lib.range 6311 6313;
};
directPorts = lib.mkOption {
type = lib.types.listOf lib.types.int;
default = [ 6314 ];
};
};
};
};
config = lib.mkIf cfg.enable {
services.sing-box = {
enable = true;
settings = {
dns = {
servers = [
{
address = "1.1.1.1";
detour = "wg-out";
}
];
};
inbounds = [
# TODO: Trojan and tuic enable
{
tag = "trojan-in";
type = "trojan";
listen = "::";
listen_port = 8080;
users = map (u: removeAttrs u [ "uuid" ]) cfg.users;
tls = singTls;
}
] ++ lib.forEach (cfg.tuic.ports ++ cfg.tuic.directPorts) (port: {
tag = "tuic-in" + toString port;
type = "tuic";
listen = "::";
listen_port = port;
congestion_control = "bbr";
users = cfg.users;
tls = singTls;
});
outbounds = [
{
type = "wireguard";
tag = "wg-out";
private_key = cfg.wgOut.privKeyFile;
local_address = [
"172.16.0.2/32"
"2606:4700:110:82ed:a443:3c62:6cbc:b59b/128"
];
peers = [
{ public_key= cfg.wgOut.pubkey;
allowed_ips = [ "0.0.0.0/0" "::/0" ];
server = "162.159.192.1";
server_port = 500;
}
];
}
{ type = "direct"; tag = "direct-out"; }
{ type = "dns"; tag = "dns-out"; }
];
route = {
rules = [
{ outbound = "dns-out"; protocol = "dns"; }
] ++ lib.forEach cfg.tuic.directPorts (port: {
inbound = "tuic-in" + toString port;
outbound = "direct-out";
});
};
};
};
};
}

View file

@ -1,77 +0,0 @@
{ config, pkgs, lib, ... }:
with lib;
let
cfg = config.custom.kanidm-client;
in
{
options = {
custom.kanidm-client = {
enable = mkEnableOption "Kanidm client service";
asSSHAuth = mkOption {
type = types.submodule {
options = {
enable = mkEnableOption "Kanidm as system authentication source";
allowedGroups = mkOption {
type = types.listOf types.str;
example = [ "linux_users" ];
};
hardening = mkOption {
type = types.bool;
default = false;
};
};
};
};
sudoers = mkOption {
type = types.listOf types.str;
default = [ ];
};
uri = mkOption {
type = types.str;
};
};
};
config = mkIf cfg.enable {
services.kanidm = mkMerge
[ (mkIf cfg.enable {
enableClient = true;
clientSettings = {
uri = cfg.uri;
};
})
(mkIf cfg.asSSHAuth.enable {
enablePam = true;
unixSettings = {
pam_allowed_login_groups = cfg.asSSHAuth.allowedGroups;
default_shell = "/bin/sh";
};
})
];
services.openssh = mkIf cfg.asSSHAuth.enable {
enable = true;
authorizedKeysCommand = "/etc/ssh/auth %u";
authorizedKeysCommandUser = "kanidm-ssh-runner";
settings = mkIf cfg.asSSHAuth.enable {
PasswordAuthentication = false;
KbdInteractiveAuthentication = false;
PermitRootLogin = lib.mkForce "no";
GSSAPIAuthentication = "no";
KerberosAuthentication = "no";
};
};
environment.etc."ssh/auth" = mkIf cfg.asSSHAuth.enable {
mode = "0555";
text = ''
#!${pkgs.stdenv.shell}
${pkgs.kanidm}/bin/kanidm_ssh_authorizedkeys $1
'';
};
users.groups.wheel.members = cfg.sudoers;
users.groups.kanidm-ssh-runner = { };
users.users.kanidm-ssh-runner = { isSystemUser = true; group = "kanidm-ssh-runner"; };
};
}

View file

@ -1,133 +0,0 @@
{ config, pkgs, lib, ... }:
let
inherit (lib) mkEnableOption mkPackageOption mkOption types literalExpression mkIf mkDefault;
cfg = config.custom.miniflux;
defaultAddress = "localhost:8080";
pgbin = "${config.services.postgresql.package}/bin";
preStart = pkgs.writeScript "miniflux-pre-start" ''
#!${pkgs.runtimeShell}
${pgbin}/psql "miniflux" -c "CREATE EXTENSION IF NOT EXISTS hstore"
'';
in
{
options = {
custom.miniflux = {
enable = mkEnableOption "miniflux";
package = mkPackageOption pkgs "miniflux" { };
oauth2SecretFile = mkOption {
type = types.path;
};
environment = mkOption {
type = with types; attrsOf (oneOf [ int str ]);
};
createDatabaseLocally = mkOption {
type = types.bool;
default = true;
description = ''
Whether a PostgreSQL database should be automatically created and
configured on the local host. If set to `false`, you need provision a
database yourself and make sure to create the hstore extension in it.
'';
};
};
};
config = lib.mkIf cfg.enable {
services.miniflux.enable = false;
custom.miniflux.environment = {
LISTEN_ADDR = mkDefault defaultAddress;
RUN_MIGRATIONS = mkDefault 1;
DATABASE_URL = lib.mkIf cfg.createDatabaseLocally "user=miniflux host=/run/postgresql dbname=miniflux";
OAUTH2_CLIENT_SECRET_FILE = "%d/oauth2_secret";
WATCHDOG = mkDefault 1;
};
services.postgresql = lib.mkIf cfg.createDatabaseLocally {
enable = true;
ensureUsers = [{
name = "miniflux";
ensureDBOwnership = true;
}];
ensureDatabases = [ "miniflux" ];
};
systemd.services.miniflux-dbsetup = lib.mkIf cfg.createDatabaseLocally {
description = "Miniflux database setup";
requires = [ "postgresql.service" ];
after = [ "network.target" "postgresql.service" ];
serviceConfig = {
Type = "oneshot";
User = config.services.postgresql.superUser;
ExecStart = preStart;
};
};
systemd.services.miniflux = {
description = "Miniflux service";
wantedBy = [ "multi-user.target" ];
requires = lib.optional cfg.createDatabaseLocally "miniflux-dbsetup.service";
after = [ "network.target" ]
++ lib.optionals cfg.createDatabaseLocally [ "postgresql.service" "miniflux-dbsetup.service" ];
serviceConfig = {
Type = "notify";
ExecStart = lib.getExe cfg.package;
User = "miniflux";
DynamicUser = true;
LoadCredential = [ "oauth2_secret:${cfg.oauth2SecretFile}" ];
RuntimeDirectory = "miniflux";
RuntimeDirectoryMode = "0750";
WatchdogSec = 60;
WatchdogSignal = "SIGKILL";
Restart = "always";
RestartSec = 5;
# Hardening
CapabilityBoundingSet = [ "" ];
DeviceAllow = [ "" ];
LockPersonality = true;
MemoryDenyWriteExecute = true;
PrivateDevices = true;
PrivateUsers = true;
ProcSubset = "pid";
ProtectClock = true;
ProtectControlGroups = true;
ProtectHome = true;
ProtectHostname = true;
ProtectKernelLogs = true;
ProtectKernelModules = true;
ProtectKernelTunables = true;
ProtectProc = "invisible";
RestrictAddressFamilies = [ "AF_INET" "AF_INET6" "AF_UNIX" ];
RestrictNamespaces = true;
RestrictRealtime = true;
RestrictSUIDSGID = true;
SystemCallArchitectures = "native";
SystemCallFilter = [ "@system-service" "~@privileged" ];
UMask = "0077";
};
environment = lib.mapAttrs (_: toString) cfg.environment;
};
environment.systemPackages = [ cfg.package ];
security.apparmor.policies."bin.miniflux".profile = ''
include <tunables/global>
${cfg.package}/bin/miniflux {
include <abstractions/base>
include <abstractions/nameservice>
include <abstractions/ssl_certs>
include "${pkgs.apparmorRulesFromClosure { name = "miniflux"; } cfg.package}"
r ${cfg.package}/bin/miniflux,
r @{sys}/kernel/mm/transparent_hugepage/hpage_pmd_size,
rw /run/miniflux/**,
}
'';
};
}

View file

@ -1,50 +0,0 @@
{ config, lib, pkgs, ... }:
let
inherit (lib) mkIf mkEnableOption mkOption types;
cfg = config.programs.oidc-agent;
providerFormat = pkgs.formats.json {};
in
{
options.programs.oidc-agent = {
enable = mkEnableOption "OpenID Connect Agent";
package = mkOption {
type = types.package;
default = pkgs.oidc-agent;
description = ''
Which oidc-agent package to use
'';
};
providers = mkOption {
type = providerFormat.type;
default = {};
description = ''
Configuration of providers which contains a json array of json objects
each describing an issuer, see https://indigo-dc.gitbook.io/oidc-agent/configuration/issuers
'';
};
};
config = mkIf cfg.enable {
systemd.user.services.oidc-agent = {
unitConfig = {
Description = "OpenID Connect Agent";
Documentation = "man:oidc-agent(1)";
};
serviceConfig = {
ExecStart = "${cfg.package}/bin/oidc-agent -d --log-stderr -a %t/oidc-agent";
};
};
# environment.etc."oidc-agent/config".source = "${pkgs.oidc-agent}/etc/oidc-agent/config";
# environment.etc."oidc-agent/issuer.config.d".source =
# "${pkgs.oidc-agent}/etc/oidc-agent/issuer.config.d";
# environment.etc."oidc-agent/issuer.config".source =
# providerFormat.generate "oidc-agent-issuer.config" cfg.providers;
environment.extraInit = ''export OIDC_SOCK="$XDG_RUNTIME_DIR/oidc-agent"'';
};
}

View file

@ -1,83 +0,0 @@
{ config, lib, pkgs, ... }:
let
cfg = config.custom.prometheus;
in
{
config = lib.mkIf (cfg.enable && cfg.exporters.blackbox.enable) {
services.prometheus.exporters.blackbox = {
enable = true;
listenAddress = "127.0.0.1";
configFile = pkgs.writeText "blackbox.config.yaml" (
lib.generators.toYAML {} {
modules = {
tcp4_connect = {
prober = "tcp";
tcp = {
ip_protocol_fallback = false;
preferred_ip_protocol = "ip4";
tls = false;
};
timeout = "15s";
};
};
}
);
};
services.prometheus.scrapeConfigs = [
{
job_name = "blackbox";
scrape_interval = "1m";
metrics_path = "/probe";
params = {
module = [ "tcp4_connect" ];
};
static_configs = [
{
targets = [
"tok-00.namely.icu:8080"
"la-00.video.namely.icu:8080"
"auth.xinyang.life:443"
"home.xinyang.life:8000"
];
}
];
relabel_configs = [
{
source_labels = [ "__address__" ];
target_label = "__param_target";
}
{
source_labels = [ "__param_target" ];
target_label = "instance";
}
{
target_label = "__address__";
replacement = "127.0.0.1:${toString config.services.prometheus.exporters.blackbox.port}";
}
];
}
{
job_name = "blackbox_exporter";
static_configs = [
{ targets = [ "127.0.0.1:${toString config.services.prometheus.exporters.blackbox.port}" ]; }
];
}
];
custom.prometheus.ruleModules = [
{
name = "probe_alerts";
rules = [
{
alert = "HighProbeLatency";
expr = "probe_duration_seconds > 0.5";
for = "2m";
labels = { severity = "warning"; };
annotations = { summary = "High request latency on {{ $labels.instance }}"; description = "95th percentile of request latency is above 0.5 seconds for the last 2 minutes."; };
}
];
}
];
};
}

View file

@ -1,38 +0,0 @@
{ config, lib, ... }:
let
cfg = config.custom.prometheus;
in
{
config = lib.mkIf (cfg.enable && cfg.exporters.caddy.enable) {
services.caddy.globalConfig = lib.mkIf cfg.exporters.caddy.enable ''
servers {
metrics
}
'';
services.prometheus.scrapeConfigs = [
{
job_name = "caddy";
static_configs = [
{ targets = [ "127.0.0.1:2019" ]; }
];
}
];
custom.prometheus.ruleModules = [
{
name = "caddy_alerts";
rules = [
{
alert = "UpstreamHealthy";
expr = "caddy_reverse_proxy_upstreams_healthy != 1";
for = "5m";
labels = { severity = "critical"; };
annotations = { summary = "Upstream {{ $labels.unstream }} not healthy"; };
}
];
}
];
};
}

View file

@ -1,206 +0,0 @@
{ config, pkgs, lib, ... }:
with lib;
let
cfg = config.custom.prometheus;
mkExporterOption = enableOption: (mkOption {
type = types.bool;
default = enableOption;
description = "Enable this exporter";
});
mkRulesOption = mkOption {
type = types.listOf (types.submodule {
options = {
name = mkOption {
type = lib.types.str;
};
rules = mkOption {
type = lib.types.listOf lib.types.attrs;
};
};
});
};
in
{
imports = [
./blackbox.nix
./caddy.nix
./gotosocial.nix
./immich.nix
./miniflux.nix
./ntfy-sh.nix
./restic.nix
];
options = {
custom.prometheus = {
enable = mkEnableOption "Prometheus instance";
exporters = {
enable = mkOption {
type = types.bool;
default = false;
description = "Enable Prometheus exporter on every supported services";
};
restic.enable = mkExporterOption config.services.restic.server.enable;
blackbox.enable = mkExporterOption false;
caddy.enable = mkExporterOption config.services.caddy.enable;
gotosocial.enable = mkExporterOption config.services.gotosocial.enable;
immich.enable = mkExporterOption config.services.immich.enable;
miniflux.enable = mkExporterOption config.services.miniflux.enable;
ntfy-sh.enable = mkExporterOption config.services.ntfy-sh.enable;
};
grafana = {
enable = mkEnableOption "Grafana Cloud";
password_file = mkOption {
type = types.path;
};
};
ruleModules = mkRulesOption;
};
};
config = mkIf cfg.enable
{
services.tailscale = {
enable = true;
permitCertUid = config.services.caddy.user;
openFirewall = true;
};
services.caddy = {
enable = true;
virtualHosts."${config.networking.hostName}.coho-tet.ts.net".extraConfig = ''
reverse_proxy 127.0.0.1:${toString config.services.prometheus.port}
'';
};
services.prometheus = mkIf cfg.enable
{
enable = true;
port = 9091;
globalConfig.external_labels = { hostname = config.networking.hostName; };
remoteWrite = mkIf cfg.grafana.enable [
{
name = "grafana";
url = "https://prometheus-prod-24-prod-eu-west-2.grafana.net/api/prom/push";
basic_auth = {
username = "1340065";
password_file = cfg.grafana.password_file;
};
}
];
exporters = {
node = {
enable = true;
enabledCollectors = [
"loadavg"
"time"
"systemd"
];
listenAddress = "127.0.0.1";
port = 9100;
};
};
scrapeConfigs = [
{
job_name = "prometheus";
static_configs = [
{ targets = [ "localhost:${toString config.services.prometheus.port}" ]; }
];
}
{
job_name = "node";
static_configs = [
{ targets = [ "localhost:${toString config.services.prometheus.exporters.node.port}" ]; }
];
}
];
alertmanager = {
enable = true;
listenAddress = "127.0.0.1";
logLevel = "debug";
configuration = {
route = {
receiver = "ntfy";
};
receivers = [
{
name = "ntfy";
webhook_configs = [
{
url = "https://ntfy.xinyang.life/prometheus-alerts?tpl=yes&m=${lib.escapeURL ''
Alert {{.status}}
{{range .alerts}}-----{{range $k,$v := .labels}}
{{$k}}={{$v}}{{end}}
{{end}}
''}";
send_resolved = true;
}
];
}
];
};
};
alertmanagers = [
{
scheme = "http";
static_configs = [
{
targets = [
"${config.services.prometheus.alertmanager.listenAddress}:${toString config.services.prometheus.alertmanager.port}"
];
}
];
}
];
rules = [ (lib.generators.toYAML { } { groups = cfg.ruleModules; }) ];
};
custom.prometheus.ruleModules = [
{
name = "system_alerts";
rules = [
{
alert = "SystemdFailedUnits";
expr = "node_systemd_unit_state{state=\"failed\"} > 0";
for = "5m";
labels = { severity = "critical"; };
annotations = { summary = "Systemd has failed units on {{ $labels.instance }}"; description = "There are {{ $value }} failed units on {{ $labels.instance }}. Immediate attention required!"; };
}
{
alert = "HighLoadAverage";
expr = "node_load1 > 0.8 * count without (cpu) (node_cpu_seconds_total{mode=\"idle\"})";
for = "1m";
labels = { severity = "warning"; };
annotations = { summary = "High load average detected on {{ $labels.instance }}"; description = "The 1-minute load average ({{ $value }}) exceeds 80% the number of CPUs."; };
}
{
alert = "HighTransmitTraffic";
expr = "rate(node_network_transmit_bytes_total{device!=\"lo\"}[5m]) > 100000000";
for = "1m";
labels = { severity = "warning"; };
annotations = { summary = "High network transmit traffic on {{ $labels.instance }} ({{ $labels.device }})"; description = "The network interface {{ $labels.device }} on {{ $labels.instance }} is transmitting data at a rate exceeding 100 MB/s for the last 1 minute."; };
}
{
alert = "NetworkTrafficExceedLimit";
expr = ''increase(node_network_transmit_bytes_total{device!="lo",device!~"tailscale.*",device!~"wg.*",device!~"br.*"}[30d]) > 322122547200'';
for = "0m";
labels = { severity = "critical"; };
annotations = { summary = "Outbound network traffic exceed 300GB for last 30 day"; };
}
{
alert = "JobDown";
expr = "up == 0";
for = "1m";
labels = { severity = "critical"; };
annotations = { summary = "Job {{ $labels.job }} down for 1m."; };
}
];
}
];
};
}

View file

@ -1,19 +0,0 @@
{ config, lib, ... }:
let
cfg = config.custom.prometheus;
in
{
config = lib.mkIf (cfg.enable && cfg.exporters.gotosocial.enable) {
services.gotosocial.settings = {
metrics-enabled = true;
};
services.prometheus.scrapeConfigs = [
{
job_name = "gotosocial";
static_configs = [
{ targets = [ "localhost:8080" ]; }
];
}
];
};
}

View file

@ -1,26 +0,0 @@
{ config, lib, ... }:
let
cfg = config.custom.prometheus;
immichEnv = config.services.immich.environment;
metricPort =
if builtins.hasAttr "IMMICH_API_METRICS_PORT" immichEnv
then immichEnv.IMMICH_API_METRICS_PORT
else 8081;
in
{
config = lib.mkIf (cfg.enable && cfg.exporters.immich.enable) {
services.immich.environment = {
IMMICH_METRICS = "true";
};
services.prometheus.scrapeConfigs = [
{
job_name = "immich";
static_configs = [
{ targets = [ "127.0.0.1:${toString metricPort}" ]; }
];
}
];
};
}

View file

@ -1,17 +0,0 @@
{ config, lib, ... }:
let
cfg = config.custom.prometheus;
in
{
config = lib.mkIf (cfg.enable && cfg.exporters.miniflux.enable) {
systemd.services.miniflux.environment.METRICS_COLLECTOR = "1";
services.prometheus.scrapeConfigs = [
{
job_name = "miniflux";
static_configs = [
{ targets = [ config.systemd.services.miniflux.environment.LISTEN_ADDR ]; }
];
}
];
};
}

View file

@ -1,17 +0,0 @@
{ config, lib, ... }:
let
cfg = config.custom.prometheus;
in
{
config = lib.mkIf (cfg.enable && cfg.exporters.ntfy-sh.enable) {
services.ntfy-sh.settings.enable-metrics = true;
services.prometheus.scrapeConfigs = [
{
job_name = "ntfy-sh";
static_configs = [
{ targets = [ "ntfy.xinyang.life" ]; }
];
}
];
};
}

View file

@ -1,41 +0,0 @@
{ config, lib, ... }:
let
cfg = config.custom.prometheus;
in
{
config = lib.mkIf (cfg.enable && cfg.exporters.restic.enable) {
services.restic.server.prometheus = true;
services.prometheus.scrapeConfigs = [
(lib.mkIf cfg.exporters.restic.enable {
job_name = "restic";
static_configs = [
{ targets = [ config.services.restic.server.listenAddress ]; }
];
})
];
custom.prometheus.ruleModules = [
{
name = "restic_alerts";
rules = [
{
alert = "ResticCheckFailed";
expr = "restic_check_success == 0";
for = "5m";
labels = { severity = "critical"; };
annotations = { summary = "Restic check failed (instance {{ $labels.instance }})"; description = "Restic check failed\\n VALUE = {{ $value }}\\n LABELS = {{ $labels }}"; };
}
{
alert = "ResticOutdatedBackup";
expr = "time() - restic_backup_timestamp > 518400";
for = "0m";
labels = { severity = "critical"; };
annotations = { summary = "Restic {{ $labels.client_hostname }} / {{ $labels.client_username }} backup is outdated"; description = "Restic backup is outdated\\n VALUE = {{ $value }}\\n LABELS = {{ $labels }}"; };
}
];
}
];
};
}

View file

@ -1,48 +0,0 @@
{ config, pkgs, lib, ... }:
let
cfg = config.custom.restic;
in
{
options = {
custom.restic = {
enable = lib.mkEnableOption "restic";
repositoryFile = lib.mkOption {
type = lib.types.str;
default = "";
};
passwordFile = lib.mkOption {
type = lib.types.str;
default = "";
};
};
};
config = lib.mkIf cfg.enable {
services.restic.backups = {
remotebackup = {
repositoryFile = cfg.repositoryFile;
passwordFile = cfg.passwordFile;
paths = [
"/home"
"/var/lib"
];
exclude = [
"/home/*/.cache"
"/home/*/.cargo"
"/home/*/.local/share/Steam"
"/home/*/.local/share/flatpak"
];
timerConfig = {
OnCalendar = "00:05";
RandomizedDelaySec = "5h";
};
pruneOpts = [
"--keep-daily 7"
"--keep-weekly 5"
"--keep-monthly 12"
"--keep-yearly 75"
];
};
};
};
}

View file

@ -1,84 +0,0 @@
{ config, pkgs, lib, utils, ... }:
let
cfg = config.custom.sing-box;
settingsFormat = pkgs.formats.json { };
in
{
options = {
custom.sing-box = {
enable = lib.mkEnableOption "sing-box";
package = lib.mkPackageOption pkgs "sing-box" { };
stateDir = lib.mkOption {
type = lib.types.path;
default = "/var/lib/sing-box";
};
configFile = {
urlFile = lib.mkOption {
type = lib.types.path;
};
name = lib.mkOption {
type = lib.types.str;
default = "config.json";
};
hash = lib.mkOption {
type = lib.types.str;
example = "9a304bcb87d4c3f1e50f6281f25dd78635255ebde06cd4d2555729ecda43aed4";
};
};
overrideSettings = lib.mkOption {
type = lib.types.submodule {
freeformType = settingsFormat.type;
options = {
route = {
geoip.path = lib.mkOption {
type = lib.types.path;
default = "${pkgs.sing-geoip}/share/sing-box/geoip.db";
defaultText = lib.literalExpression "\${pkgs.sing-geoip}/share/sing-box/geoip.db";
description = lib.mdDoc ''
The path to the sing-geoip database.
'';
};
geosite.path = lib.mkOption {
type = lib.types.path;
default = "${pkgs.sing-geosite}/share/sing-box/geosite.db";
defaultText = lib.literalExpression "\${pkgs.sing-geosite}/share/sing-box/geosite.db";
description = lib.mdDoc ''
The path to the sing-geosite database.
'';
};
};
};
};
default = { };
};
};
};
config = lib.mkIf cfg.enable {
networking.firewall.trustedInterfaces = [ "tun0" ];
systemd.packages = [ cfg.package ];
systemd.services.sing-box =
let
configFile = cfg.stateDir + "/${cfg.configFile.name}";
in
{
preStart = ''
umask 0077
mkdir -p /etc/sing-box
if ! [ -e ${configFile} ]; then
${pkgs.curl}/bin/curl "$(${pkgs.coreutils}/bin/cat ${cfg.configFile.urlFile})" > '${configFile}'
test "${cfg.configFile.hash}" $(${pkgs.coreutils}/bin/sha256sum '${configFile}' | ${pkgs.coreutils}/bin/cut -d ' ' -f 1)
fi
${utils.genJqSecretsReplacementSnippet cfg.overrideSettings "/etc/sing-box/config.json"}
${cfg.package}/bin/sing-box merge -c '${configFile}' -c /etc/sing-box/config.json /etc/sing-box/config.json
'';
wantedBy = [ "multi-user.target" ];
};
};
}

View file

@ -1,48 +0,0 @@
# Temporary workaround
{ config, pkgs, lib, ... }:
let
cfg = config.services.ssh-tpm-agent;
in
{
options = {
services.ssh-tpm-agent.enable = lib.mkEnableOption "TPM supported ssh agent in go";
};
config = lib.mkIf cfg.enable {
systemd.user.services.ssh-tpm-agent = {
enable = true;
unitConfig = {
Description = "SSH TPM agent service";
Documentation = "man:ssh-agent(1) man:ssh-add(1) man:ssh(1)";
Requires = "ssh-tpm-agent.socket";
ConditionEnvironment = "!SSH_AGENT_PID";
};
serviceConfig = {
Environment = "SSH_AUTH_SOCK=%t/ssh-tpm-agent.socket";
ExecStart = "${pkgs.ssh-tpm-agent}/bin/ssh-tpm-agent";
PassEnvironment = "SSH_AGENT_PID";
SuccessExitStatus = 2;
Type = "simple";
};
wants = [ "ssh-tpm-agent.socket" ];
};
systemd.user.sockets.ssh-tpm-agent = {
enable = true;
description = "SSH TPM agent socket";
socketConfig = {
ListenStream = "%t/ssh-tpm-agent.sock";
SocketMode = "0600";
Service = "ssh-tpm-agent.service";
};
wantedBy = [ "sockets.target" ];
};
environment = {
systemPackages = [ pkgs.ssh-tpm-agent ];
extraInit = ''
export SSH_AUTH_SOCK="$XDG_RUNTIME_DIR/ssh-tpm-agent.sock"
'';
};
};
}

View file

@ -1,47 +0,0 @@
{ config, pkgs, lib, ... }:
with lib;
let
cfg = config.custom.vaultwarden;
in
{
options = {
custom.vaultwarden = {
enable = mkEnableOption "vaultwarden server";
domain = mkOption {
type = types.str;
default = "bitwarden.example.com";
description = "Domain name of the vaultwarden server";
};
caddy = mkOption {
type = types.bool;
default = true;
description = "Enable Caddy as reverse proxy";
};
# TODO: mailserver support
};
};
config = mkIf cfg.enable {
services.vaultwarden = {
enable = true;
dbBackend = "sqlite";
config = {
DOMAIN = "https://${cfg.domain}";
SIGNUPS_ALLOWED = false;
ROCKET_ADDRESS = "127.0.0.1";
ROCKET_PORT = 8222;
ROCKET_LOG = "critical";
};
};
services.caddy = mkIf cfg.caddy {
enable = true;
virtualHosts."https://${cfg.domain}".extraConfig = ''
reverse_proxy ${config.services.vaultwarden.config.ROCKET_ADDRESS}:${toString config.services.vaultwarden.config.ROCKET_PORT}
'';
};
};
}

View file

@ -1 +0,0 @@
ssh-ng://eu.nixbuild.net aarch64-linux - 100 1 big-parallel,benchmark

View file

@ -1,3 +0,0 @@
# nix-tree
Demonstrate disk usage by nix-store path.

View file

@ -1,134 +0,0 @@
{
"nodes": {
"flake-compat": {
"flake": false,
"locked": {
"lastModified": 1673956053,
"narHash": "sha256-4gtG9iQuiKITOjNQQeQIpoIB6b16fm+504Ch3sNKLd8=",
"owner": "edolstra",
"repo": "flake-compat",
"rev": "35bb57c0c8d8b62bbfd284272c928ceb64ddbde9",
"type": "github"
},
"original": {
"owner": "edolstra",
"repo": "flake-compat",
"type": "github"
}
},
"flake-utils": {
"inputs": {
"systems": "systems"
},
"locked": {
"lastModified": 1710146030,
"narHash": "sha256-SZ5L6eA7HJ/nmkzGG7/ISclqe6oZdOZTNoesiInkXPQ=",
"owner": "numtide",
"repo": "flake-utils",
"rev": "b1d9ab70662946ef0850d488da1c9019f3a9752a",
"type": "github"
},
"original": {
"owner": "numtide",
"repo": "flake-utils",
"type": "github"
}
},
"libgit2": {
"flake": false,
"locked": {
"lastModified": 1697646580,
"narHash": "sha256-oX4Z3S9WtJlwvj0uH9HlYcWv+x1hqp8mhXl7HsLu2f0=",
"owner": "libgit2",
"repo": "libgit2",
"rev": "45fd9ed7ae1a9b74b957ef4f337bc3c8b3df01b5",
"type": "github"
},
"original": {
"owner": "libgit2",
"repo": "libgit2",
"type": "github"
}
},
"nix": {
"inputs": {
"flake-compat": "flake-compat",
"libgit2": "libgit2",
"nixpkgs": [
"nixpkgs"
],
"nixpkgs-regression": "nixpkgs-regression"
},
"locked": {
"lastModified": 1710178469,
"narHash": "sha256-9b9qJ+7rGjLKbIswMf0/2pgUWH/xOlYLk7P4WYNcGDs=",
"owner": "nixos",
"repo": "nix",
"rev": "34807c8906a61219ec2e9132c9cf0bd4d29e1d12",
"type": "github"
},
"original": {
"owner": "nixos",
"ref": "2.21.0",
"repo": "nix",
"type": "github"
}
},
"nixpkgs": {
"locked": {
"lastModified": 1711124224,
"narHash": "sha256-l0zlN/3CiodvWDtfBOVxeTwYSRz93muVbXWSpaMjXxM=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "56528ee42526794d413d6f244648aaee4a7b56c0",
"type": "github"
},
"original": {
"owner": "NixOS",
"ref": "nixos-23.11",
"repo": "nixpkgs",
"type": "github"
}
},
"nixpkgs-regression": {
"locked": {
"lastModified": 1643052045,
"narHash": "sha256-uGJ0VXIhWKGXxkeNnq4TvV3CIOkUJ3PAoLZ3HMzNVMw=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "215d4d0fd80ca5163643b03a33fde804a29cc1e2",
"type": "github"
},
"original": {
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "215d4d0fd80ca5163643b03a33fde804a29cc1e2",
"type": "github"
}
},
"root": {
"inputs": {
"flake-utils": "flake-utils",
"nix": "nix",
"nixpkgs": "nixpkgs"
}
},
"systems": {
"locked": {
"lastModified": 1681028828,
"narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=",
"owner": "nix-systems",
"repo": "default",
"rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e",
"type": "github"
},
"original": {
"owner": "nix-systems",
"repo": "default",
"type": "github"
}
}
},
"root": "root",
"version": 7
}

View file

@ -1,77 +0,0 @@
{
inputs = {
nix.url = "github:/nixos/nix?ref=2.21.0";
nix.inputs.nixpkgs.follows = "nixpkgs";
nixpkgs.url = "github:NixOS/nixpkgs/nixos-23.11";
flake-utils.url = "github:numtide/flake-utils";
};
outputs = {
self,
flake-utils,
nix,
nixpkgs,
...
}:
flake-utils.lib.eachDefaultSystem (system: let
pkgs = (import nixpkgs) {
inherit system;
};
lib = pkgs.lib;
in rec {
packages = rec {
# a modified version of the nixos/nix image
# re-using the upstream nix docker image generation code
base = import (nix + "/docker.nix") {
inherit pkgs;
name = "nix-ci-base";
maxLayers = 10;
extraPkgs = with pkgs; [
nodejs_20 # nodejs is needed for running most 3rdparty actions
# add any other pre-installed packages here
curl
xz
openssl
coreutils-full
cmake
gnumake
gcc
];
# change this is you want
channelURL = "https://nixos.org/channels/nixpkgs-23.11";
nixConf = {
substituters = [
"https://mirrors.bfsu.edu.cn/nix-channels/store"
"https://mirrors.ustc.edu.cn/nix-channels/store"
"https://cache.nixos.org/"
"https://nix-community.cachix.org"
];
accept-flake-config = "true";
log-lines = "300";
trusted-public-keys = [
"cache.nixos.org-1:6NCHdD59X431o0gWypbMrAURkbJ16ZPMQFGspcDShjY="
"nix-community.cachix.org-1:mB9FSh9qf2dCimDSUo8Zy7bkq5CX+/rkCWyvRCYg3Fs="
];
# allow using the new flake commands in our workflows
experimental-features = ["nix-command" "flakes"];
};
};
# make /bin/sleep available on the image
runner = pkgs.dockerTools.buildImage {
name = "nix-runner";
tag = "2.21.0-pkgs-23.11";
fromImage = base;
fromImageName = null;
fromImageTag = "latest";
copyToRoot = pkgs.buildEnv {
name = "image-root";
paths = [pkgs.coreutils-full];
pathsToLink = ["/bin"]; # add coreutuls (which includes sleep) to /bin
};
};
};
});
}

View file

@ -1,9 +0,0 @@
{ config, pkgs, lib, ... }:
{
nixpkgs.overlays = [
(self: super: {
element-desktop = super.element-desktop.override { commandLineArgs = "--enable-wayland-ime"; };
})
];
}

View file

@ -1,3 +0,0 @@
(final: prev: {
oidc-agent = prev.callPackage ./pkgs/oidc-agent { };
})

View file

@ -1 +0,0 @@
final: prev: (import ./add-pkgs.nix)

View file

@ -1,58 +0,0 @@
{ lib
, stdenv
, fetchFromGitHub
, curl
, webkitgtk
, libmicrohttpd
, libsecret
, qrencode
, libsodium
, pkg-config
, help2man
}:
stdenv.mkDerivation rec {
pname = "oidc-agent";
version = "5.1.0";
src = fetchFromGitHub {
owner = "indigo-dc";
repo = "oidc-agent";
rev = "v${version}";
sha256 = "sha256-cOK/rZ/jnyALLuhDM3+qvwwe4Fjkv8diQBkw7NfVo0c="
;
};
buildInputs = [
pkg-config
help2man
];
nativeBuildInputs = [
curl
webkitgtk
libmicrohttpd
libsecret
qrencode
libsodium
];
enableParallelBuilding = true;
installPhase = ''
make -j $NIX_BUILD_CORES PREFIX=$out BIN_PATH=$out LIB_PATH=$out/lib \
install_bin install_lib install_conf
'';
postFixup = ''
# Override with patched binary to be used by help2man
cp -r $out/bin/* bin
make install_man PREFIX=$out
'';
meta = with lib; {
description = "oidc-agent for managing OpenID Connect tokens on the command line";
homepage = "https://github.com/indigo-dc/oidc-agent";
maintainers = [ ];
license = licenses.mit;
};
}

3
src/CMakeLists.txt Normal file
View file

@ -0,0 +1,3 @@
add_executable(diffu cli.cpp difftest.cpp gdbstub.cpp loader.cpp main.cpp)
target_link_libraries(diffu PRIVATE gdbstub spdlog::spdlog)
install ( TARGETS diffu )

55
src/cli.cpp Normal file
View file

@ -0,0 +1,55 @@
#include "config.hpp"
#include <CLI/App.hpp>
#include <CLI/Error.hpp>
#include <CLI/Validators.hpp>
#include <cerrno>
int Config::cli_parse(int argc, char **argv) {
CLI::App app;
app.add_option(
"--images-path", images_path,
"Directory containing image files. Search image files in this path.")
->envname("DIFFU_IMAGES_PATH")
->check(CLI::ExistingPath);
app.add_option("-m,--memory", memory_file,
"Image file used to fill up the memory. Relative path to "
"--images-path")
->required();
app.add_option("--ref", refs, "Reference dynamic library")->required();
app.add_option("--ref-prefix", refs_prefix,
"Optional prefix for each reference library");
app.add_option("--dut", dut, "Design under test")->required();
app.add_option("--dut-prefix", dut_prefix,
"Optional prefix for design under test");
app.add_option("--listen", gdbstub_addr, "Gdb remote listen address");
app.add_flag("-g", use_debugger, "Launch gdb remote stub");
app.set_config("-c,--config")
->transform(CLI::FileOnDefaultPath("difftest.toml"));
// Default value for refs_prefix
app.callback([&]() {
if (refs_prefix.size() == 0) {
refs_prefix.insert(refs_prefix.end(), refs.size(), "");
}
});
// Check if refs_prefix matches refs.
app.callback([&]() {
if (refs_prefix.size() != refs.size()) {
throw CLI::ParseError(
"Same number of --ref and --ref-prefix must be provided.", EINVAL);
}
});
CLI11_PARSE(app, argc, argv);
return 0;
}

205
src/difftest.cpp Normal file
View file

@ -0,0 +1,205 @@
#include "api.hpp"
#include <cerrno>
#include <difftest.hpp>
#include <fstream>
#include <gdbstub.h>
#include <spdlog/spdlog.h>
#include <sstream>
#include <stdexcept>
#include <string>
Difftest::Difftest(Target &&dut, std::vector<Target> &&refs) {
this->dut = std::move(dut);
this->refs = std::move(refs);
for (const auto &ref : refs) {
if (dut.isa_arch_info->reg_byte != ref.isa_arch_info->reg_byte ||
dut.isa_arch_info->reg_num != ref.isa_arch_info->reg_num) {
throw std::runtime_error("Ref and dut must have the same architecture");
}
}
}
void Difftest::setup(const std::filesystem::path &memory_file) {
std::ifstream is = std::ifstream(memory_file, std::ios::binary);
spdlog::debug("Reading image file: {}", memory_file.c_str());
// Seek to the end to determine the file size
is.seekg(0, std::ios::end);
std::streampos memsize = is.tellg();
is.seekg(0, std::ios::beg);
std::vector<char> membuf(memsize);
is.read(membuf.data(), memsize);
is.close();
// Initialize memory
// TODO: reset vector should not be hardcoded
// for(auto target : *this) {
for (auto it = this->begin(); it != this->end(); ++it) {
auto &target = *it;
target.ops.init(target.args.data());
target.ops.write_reg(target.args.data(), 32, 0x80000000UL);
if (target.ops.write_mem(target.args.data(), 0x80000000UL, membuf.size(),
membuf.data()) != 0)
throw std::runtime_error("write_mem failed");
}
}
bool Difftest::check_all() {
bool passed = true;
for (auto &ref : refs) {
if (check(dut, ref) == false)
passed = false;
}
return passed;
}
Difftest::ExecRet Difftest::exec(size_t n, gdb_action_t *ret) {
ExecRet exec_ret = {
.at_breakpoint = false, .do_difftest = true, .check_failed = false};
while (n--) {
Target *pbreak = &(*(this->begin()));
// TODO: For improvement, use ThreadPool here for concurrent execution?
for (auto it = this->begin(); it != this->end(); ++it) {
auto &target = *it;
*target.do_difftest = true;
target.ops.stepi(target.args.data(), &target.last_res);
spdlog::trace("{} stepped once", target.meta.name);
if (target.is_on_breakpoint()) {
exec_ret.at_breakpoint = true;
pbreak = &target;
spdlog::trace("{} on breakpoint", target.meta.name);
continue;
}
exec_ret.do_difftest = *target.do_difftest && exec_ret.do_difftest;
}
// Do difftest, or sync registers to ref
if (exec_ret.do_difftest) {
if (!check_all()) {
exec_ret.check_failed = true;
}
} else {
size_t pc = 0;
read_reg(32, &pc);
spdlog::debug("Difftest skipped at {}", (void *)pc);
sync_regs_to_ref();
}
if (exec_ret.check_failed) {
ret->reason = gdb_action_t::ACT_SHUTDOWN;
}
if (exec_ret.at_breakpoint) {
ret->reason = pbreak->last_res.reason;
ret->data = pbreak->last_res.data;
break;
}
}
return exec_ret;
}
gdb_action_t Difftest::stepi() {
gdb_action_t ret = {.reason = gdb_action_t::ACT_NONE};
ExecRet exec_result = exec(1, &ret);
return ret;
}
gdb_action_t Difftest::cont() {
gdb_action_t ret = {.reason = gdb_action_t::ACT_NONE};
ExecRet exec_ret;
start_run();
while (!is_halt()) {
exec_ret = exec(1, &ret);
if (exec_ret.at_breakpoint)
break;
};
return ret;
}
int Difftest::read_reg(int regno, size_t *value) {
return current_target->ops.read_reg(current_target->args.data(), regno,
value);
}
int Difftest::write_reg(int regno, size_t value) {
return current_target->ops.write_reg(current_target->args.data(), regno,
value);
}
int Difftest::sync_regs_to_ref(void) {
std::vector<size_t> regs;
int ret = 0;
for (int i = 0; i <= get_arch().reg_num; i++) {
size_t r;
ret = dut.ops.read_reg(dut.args.data(), i, &r);
if (ret)
return ret;
regs.push_back(r);
}
for (auto &ref : refs) {
for (int i = 0; i <= get_arch().reg_num; i++) {
ret = ref.ops.write_reg(ref.args.data(), i, regs.at(i));
if (ret)
return ret;
}
}
spdlog::trace("Applied registers value from dut to ref");
return ret;
}
std::string Difftest::list_targets(void) {
std::ostringstream os;
int i = 0;
for (auto it = this->begin(); it != this->end(); ++it, ++i) {
auto &target = *it;
os << i << ": " << target.meta.name << std::endl;
}
os << "current: " << current_target->meta.name << std::endl;
return os.str();
}
std::string Difftest::switch_target(int index) {
std::ostringstream os;
int i = 0;
for (auto it = this->begin(); it != this->end(); ++it, ++i) {
auto &target = *it;
if (i == index) {
current_target = &target;
os << "Switched to " << current_target->meta.name << std::endl;
return os.str();
}
}
os << "Invalid target target index: " << index << std::endl;
return os.str();
}
int Difftest::read_mem(size_t addr, size_t len, void *val) {
return current_target->ops.read_mem(current_target->args.data(), addr, len,
val);
}
int Difftest::write_mem(size_t addr, size_t len, void *val) {
return current_target->ops.write_mem(current_target->args.data(), addr, len,
val);
}
bool Difftest::set_bp(size_t addr, bp_type_t type) {
bool ret = true;
for (auto it = this->begin(); it != this->end(); ++it) {
auto &target = *it;
ret = target.ops.set_bp(target.args.data(), addr, type) && ret;
}
return ret;
}
bool Difftest::del_bp(size_t addr, bp_type_t type) {
bool ret = true;
for (auto it = this->begin(); it != this->end(); ++it) {
auto &target = *it;
ret = target.ops.del_bp(target.args.data(), addr, type) && ret;
}
return ret;
}

151
src/gdbstub.cpp Normal file
View file

@ -0,0 +1,151 @@
#include <CLI/App.hpp>
#include <CLI/Error.hpp>
#include <cstring>
#include <difftest.hpp>
#include <spdlog/spdlog.h>
#include <sstream>
extern "C" {
#include <gdbstub.h>
}
static std::vector<std::string> split_into_args(const std::string &command) {
std::istringstream iss(command);
std::vector<std::string> args;
std::string token;
while (iss >> token) {
args.push_back(token);
}
return args;
}
extern "C" {
static void difftest_cont(void *args, gdb_action_t *res) {
Difftest *diff = (Difftest *)args;
*res = diff->cont();
};
static void difftest_stepi(void *args, gdb_action_t *res) {
Difftest *diff = (Difftest *)args;
*res = diff->stepi();
};
static int difftest_read_reg(void *args, int regno, size_t *value) {
Difftest *diff = (Difftest *)args;
return diff->read_reg(regno, value);
};
static int difftest_write_reg(void *args, int regno, size_t value) {
Difftest *diff = (Difftest *)args;
return diff->write_reg(regno, value);
}
static int difftest_read_mem(void *args, size_t addr, size_t len, void *val) {
Difftest *diff = (Difftest *)args;
return diff->read_mem(addr, len, val);
}
static int difftest_write_mem(void *args, size_t addr, size_t len, void *val) {
Difftest *diff = (Difftest *)args;
return diff->write_mem(addr, len, val);
}
static bool difftest_set_bp(void *args, size_t addr, bp_type_t type) {
Difftest *diff = (Difftest *)args;
return diff->set_bp(addr, type);
}
static bool difftest_del_bp(void *args, size_t addr, bp_type_t type) {
Difftest *diff = (Difftest *)args;
return diff->del_bp(addr, type);
}
static void difftest_on_interrupt(void *args) {
Difftest *diff = (Difftest *)args;
puts("interrupt");
diff->halt();
}
static char *gdbstub_monitor(void *args, const char *s) {
Difftest *diff = (Difftest *)args;
spdlog::trace("monitor");
CLI::App parser;
std::string ret = "";
auto sync = parser.add_subcommand("sync", "Sync states between targets")
->callback([&]() { diff->sync_regs_to_ref(); });
parser.add_subcommand("list", "List targets.")->callback([&]() {
ret = diff->list_targets();
});
parser.add_subcommand("help", "Print help message")->callback([&]() {
ret = parser.help();
});
int target_index = -1;
parser.add_subcommand("switch", "Switch to another target")
->callback([&]() { ret = diff->switch_target(target_index); })
->add_option("target_index", target_index, "Index of the target");
std::string cmdstr;
int slen = strlen(s);
int ch;
for (int i = 0; i < slen; i += 2) {
sscanf(&s[i], "%02x", &ch);
cmdstr.push_back(ch);
}
auto arglist = split_into_args(cmdstr);
std::vector<const char *> argv = {""};
for (const auto &arg : arglist) {
argv.push_back(static_cast<const char *>(arg.c_str()));
}
try {
(parser).parse((argv.size()), (argv.data()));
} catch (const CLI ::ParseError &e) {
std::ostringstream os;
os << "Failed to parse " << cmdstr << std::endl
<< parser.help() << std::endl;
ret = os.str();
}
if (ret[0] == '\0') {
return NULL;
} else {
std::ostringstream ret_stream;
// Set formatting options for the stream
ret_stream << std::hex << std::setfill('0');
for (unsigned char c : ret) {
ret_stream << std::setw(2) << static_cast<int>(c);
}
return strdup(ret_stream.str().c_str());
}
}
}
int gdbstub_loop(Difftest *diff, std::string socket_addr) {
target_ops gdbstub_ops = {.cont = difftest_cont,
.stepi = difftest_stepi,
.read_reg = difftest_read_reg,
.write_reg = difftest_write_reg,
.read_mem = difftest_read_mem,
.write_mem = difftest_write_mem,
.set_bp = difftest_set_bp,
.del_bp = difftest_del_bp,
.on_interrupt = difftest_on_interrupt,
.monitor = gdbstub_monitor};
gdbstub_t gdbstub_priv;
arch_info_t arch = diff->get_arch();
if (!gdbstub_init(&gdbstub_priv, &gdbstub_ops, arch, nullptr,
socket_addr.c_str())) {
spdlog::error("Failed to init socket at: {}", socket_addr);
return false;
}
spdlog::info("Connected to gdb at {}", socket_addr);
bool success = gdbstub_run(&gdbstub_priv, diff);
gdbstub_close(&gdbstub_priv);
return !success;
}

71
src/loader.cpp Normal file
View file

@ -0,0 +1,71 @@
#include "api.hpp"
#include <dlfcn.h>
#include <gdbstub.h>
#include <spdlog/spdlog.h>
#include <stdexcept>
Target::Target(const std::string &name, const std::string &func_prefix,
const std::filesystem::path &path) {
meta = {.name = name,
.libpath = path,
.dlhandle = dlopen(path.c_str(), RTLD_NOW)};
spdlog::info("Found dlopen API handle for {} at {}", meta.name,
meta.dlhandle);
if (!meta.dlhandle) {
throw std::runtime_error(dlerror());
}
#define LOAD_SYMBOL(ops, handle, prefix, name) \
do { \
std::string symbol_name = func_prefix + #name; \
(ops).name = reinterpret_cast<decltype((ops).name)>( \
dlsym((handle), symbol_name.c_str())); \
if (!((ops).name)) \
goto load_error; \
spdlog::debug("Found {} at {}", symbol_name, ((void *)((ops).name))); \
} while (0);
LOAD_SYMBOL(ops, meta.dlhandle, func_prefix, cont);
LOAD_SYMBOL(ops, meta.dlhandle, func_prefix, stepi);
LOAD_SYMBOL(ops, meta.dlhandle, func_prefix, read_reg);
LOAD_SYMBOL(ops, meta.dlhandle, func_prefix, write_reg);
LOAD_SYMBOL(ops, meta.dlhandle, func_prefix, read_mem);
LOAD_SYMBOL(ops, meta.dlhandle, func_prefix, write_mem);
LOAD_SYMBOL(ops, meta.dlhandle, func_prefix, set_bp);
LOAD_SYMBOL(ops, meta.dlhandle, func_prefix, del_bp);
LOAD_SYMBOL(ops, meta.dlhandle, func_prefix, on_interrupt);
LOAD_SYMBOL(ops, meta.dlhandle, func_prefix, init);
LOAD_SYMBOL(*this, meta.dlhandle, func_prefix, do_difftest);
*do_difftest = true;
LOAD_SYMBOL(*this, meta.dlhandle, func_prefix, dbg_state_size);
args.resize(*dbg_state_size);
LOAD_SYMBOL(*this, meta.dlhandle, func_prefix, isa_arch_info);
#undef LOAD_SYMBOL
return;
load_error:
std::string err = std::string(dlerror());
dlclose(meta.dlhandle);
throw std::runtime_error(err);
}
Target::~Target() { dlclose(meta.dlhandle); }
bool Target::is_on_breakpoint() const { return is_on_breakpoint(last_res); }
bool Target::is_on_breakpoint(const gdb_action_t &res) const {
if (res.reason == gdb_action_t::ACT_BREAKPOINT ||
res.reason == gdb_action_t::ACT_RWATCH ||
res.reason == gdb_action_t::ACT_WATCH ||
res.reason == gdb_action_t::ACT_WWATCH ||
res.reason == gdb_action_t::ACT_SHUTDOWN) {
return true;
}
return false;
}

54
src/main.cpp Normal file
View file

@ -0,0 +1,54 @@
#include "api.hpp"
#include "config.hpp"
#include "difftest.hpp"
#include <filesystem>
#include <spdlog/cfg/env.h>
#include <spdlog/spdlog.h>
int gdbstub_loop(Difftest *, std::string);
int main(int argc, char **argv) {
spdlog::cfg::load_env_levels();
Config config;
int ret = 0;
ret = config.cli_parse(argc, argv);
if (ret)
return ret;
std::vector<Target> refs;
Target *dut = new Target{"dut", config.dut_prefix, config.dut};
auto ref_libpath = config.refs.begin();
auto ref_prefix = config.refs_prefix.begin();
while (ref_libpath != config.refs.end() &&
ref_prefix != config.refs_prefix.end()) {
refs.emplace_back(ref_libpath->string(), *ref_prefix, *ref_libpath);
ref_libpath++;
ref_prefix++;
}
Difftest difftest{std::move(*dut), std::move(refs)};
std::filesystem::path image_file = config.images_path / config.memory_file;
if (!std::filesystem::exists(image_file)) {
spdlog::error("Cannot find {} in {}.", config.memory_file.c_str(),
config.images_path.c_str());
}
difftest.setup(image_file);
if (config.use_debugger) {
gdbstub_loop(&difftest, config.gdbstub_addr);
} else {
gdb_action_t ret = {.reason = gdb_action_t::ACT_NONE};
Difftest::ExecRet exec_ret;
while (1) {
exec_ret = difftest.exec(1, &ret);
if (exec_ret.check_failed)
return 1;
if (exec_ret.at_breakpoint)
break;
};
return 0;
}
return 0;
}