Compare commits
89 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 5222077eac | |||
| d122263dfa | |||
| 86e020936c | |||
| c00b9dc204 | |||
| 2505485996 | |||
| f41ef34361 | |||
| 4cacb69c9c | |||
| 9880ba23aa | |||
| 628dfaba31 | |||
| 9a93834dbb | |||
| 81cfe4ff2b | |||
| 7f3b6be59b | |||
| c49a0f1420 | |||
| 323ed6ec9e | |||
| 2eb594b625 | |||
| 15f6a5d7d3 | |||
| a92ff8fe58 | |||
| c242370ae8 | |||
| 3cbabde86a | |||
| aa673196ff | |||
| 8125de7ce6 | |||
| 42e80ea537 | |||
| a24be3309b | |||
| d2ad80da6f | |||
| 49606c8711 | |||
| 48260c392b | |||
| e1cf4f3647 | |||
| 9640b433a4 | |||
| f9f9816fe9 | |||
| 297589362f | |||
| 9c3cb1f360 | |||
| d8e6a816c9 | |||
| 923cb64277 | |||
| e9c223259b | |||
| b021b555eb | |||
| 59ebcab94f | |||
| 7a25ac669f | |||
| 9f2dc8314a | |||
| aaf1a17b33 | |||
| 97f475f131 | |||
| 48eedcabd3 | |||
| 0cf4401813 | |||
| 888264a491 | |||
| c812ceb37f | |||
| 967bb17c28 | |||
| c4e3b755ce | |||
| c335f105a5 | |||
| 289cc5f423 | |||
| 1ba87bb462 | |||
| d517e877f0 | |||
| e7267282b6 | |||
| 93034af158 | |||
| 7f0bf6c219 | |||
| c344fbbe0e | |||
| d84b2e882d | |||
| 42868908a6 | |||
| 2a28574058 | |||
| 3cf375ea00 | |||
| 49ca63c450 | |||
| 490f334f8a | |||
| d320552330 | |||
| d23d7dc79e | |||
| 5ae6b29e15 | |||
| cb078522bd | |||
| 3464e55e0e | |||
| ecafb32328 | |||
| c12da16d00 | |||
| ebcb37773a | |||
| 72d9a66b4f | |||
| 94ddd0c3b6 | |||
| 8201bc4bf5 | |||
| c0b0d89fcf | |||
| 8064f499a8 | |||
| cb297406ea | |||
| 56f5c4dc8e | |||
| dddb070b69 | |||
| 66c24c9192 | |||
| 982941940e | |||
| 159487e2f3 | |||
| 788aff4158 | |||
| dc721a79bc | |||
| dcf492209b | |||
| f29335096a | |||
| 67bcf57992 | |||
| 2740d04253 | |||
| a32a2800f7 | |||
| 870ead1994 | |||
| 5baa98329d | |||
| b4327b2740 |
@@ -0,0 +1,31 @@
|
||||
name: CI
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: ["main"]
|
||||
pull_request:
|
||||
|
||||
jobs:
|
||||
check:
|
||||
runs-on: nix
|
||||
env:
|
||||
PATH: "/run/wrappers/bin:/nix/var/nix/profiles/default/bin:/run/current-system/sw/bin:/usr/bin:/bin"
|
||||
NIXPKGS_ALLOW_UNFREE: "1"
|
||||
steps:
|
||||
- name: Checkout
|
||||
run: git clone https://git.cyperpunk.de/DerGrumpf/cyper-nix.git .
|
||||
|
||||
- name: Format check
|
||||
run: nix fmt -- --ci
|
||||
|
||||
- name: Nix flake check
|
||||
run: nix flake check --impure
|
||||
|
||||
- name: Build NixOS configs (dry-run)
|
||||
run: |
|
||||
nix build .#nixosConfigurations.cyper-desktop.config.system.build.toplevel --dry-run
|
||||
nix build .#nixosConfigurations.cyper-controller.config.system.build.toplevel --dry-run
|
||||
nix build .#nixosConfigurations.cyper-proxy.config.system.build.toplevel --dry-run
|
||||
nix build .#nixosConfigurations.cyper-node-1.config.system.build.toplevel --dry-run
|
||||
nix build .#nixosConfigurations.cyper-node-2.config.system.build.toplevel --dry-run
|
||||
|
||||
@@ -0,0 +1,46 @@
|
||||
name: Release ISOs
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
workflows: ["CI"]
|
||||
types:
|
||||
- completed
|
||||
branches: ["main"]
|
||||
|
||||
jobs:
|
||||
build-isos:
|
||||
runs-on: nix
|
||||
env:
|
||||
NIXPKGS_ALLOW_UNFREE: "1"
|
||||
steps:
|
||||
- name: Checkout
|
||||
run: git clone https://git.cyperpunk.de/DerGrumpf/cyper-nix.git .
|
||||
|
||||
- name: Build ISOs
|
||||
run: |
|
||||
nix build .#packages.x86_64-linux.cyper-desktop-iso --out-link result-desktop
|
||||
nix build .#packages.x86_64-linux.cyper-controller-iso --out-link result-controller
|
||||
nix build .#packages.x86_64-linux.cyper-proxy-iso --out-link result-proxy
|
||||
nix build .#packages.x86_64-linux.cyper-node-1-iso --out-link result-node-1
|
||||
nix build .#packages.x86_64-linux.cyper-node-2-iso --out-link result-node-2
|
||||
|
||||
- name: Create release and upload ISOs
|
||||
run: |
|
||||
TAG="iso-$(date +%Y%m%d-%H%M%S)"
|
||||
COMMIT=$(git -C . rev-parse --short HEAD)
|
||||
|
||||
RELEASE=$(curl -s -X POST \
|
||||
-H "Authorization: token ${{ secrets.CI_TOKEN }}" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d "{\"tag_name\":\"${TAG}\",\"name\":\"ISOs ${TAG}\",\"body\":\"Automated ISO build from commit ${COMMIT}\"}" \
|
||||
"https://git.cyperpunk.de/api/v1/repos/DerGrumpf/cyper-nix/releases")
|
||||
|
||||
RELEASE_ID=$(echo $RELEASE | grep -o '"id":[0-9]*' | head -1 | cut -d: -f2)
|
||||
|
||||
for result in result-desktop result-controller result-proxy result-node-1 result-node-2; do
|
||||
iso=$(readlink -f $(find $result -name "*.iso" | head -1))
|
||||
curl -s -X POST \
|
||||
-H "Authorization: token ${{ secrets.CI_TOKEN }}" \
|
||||
-F "attachment=@${iso};filename=${result}.iso" \
|
||||
"https://git.cyperpunk.de/api/v1/repos/DerGrumpf/cyper-nix/releases/${RELEASE_ID}/assets"
|
||||
done
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 1.9 MiB |
Binary file not shown.
|
After Width: | Height: | Size: 1.9 MiB |
@@ -8,14 +8,8 @@
|
||||
./settings.nix
|
||||
./homebrew.nix
|
||||
./yabai.nix
|
||||
./fonts.nix
|
||||
];
|
||||
|
||||
home-manager.users.${primaryUser}.targets.darwin = {
|
||||
linkApps.enable = true;
|
||||
copyApps.enable = false;
|
||||
};
|
||||
|
||||
# nix config
|
||||
nix = {
|
||||
settings = {
|
||||
@@ -56,9 +50,6 @@
|
||||
info.enable = false; # Skip info pages
|
||||
};
|
||||
|
||||
nixpkgs.config = {
|
||||
allowUnfree = true;
|
||||
};
|
||||
# homebrew installation manager
|
||||
nix-homebrew = {
|
||||
user = primaryUser;
|
||||
|
||||
+32
-31
@@ -1,27 +1,27 @@
|
||||
{ self, ... }:
|
||||
{ self, primaryUser, ... }:
|
||||
let
|
||||
hmApps = app: "/Users/${primaryUser}/Applications/Home Manager Apps/${app}.app";
|
||||
sysApps = app: "/System/Applications/${app}.app";
|
||||
apps = app: "/Applications/${app}.app";
|
||||
in
|
||||
{
|
||||
# touch ID for sudo
|
||||
security.pam.services.sudo_local.touchIdAuth = true;
|
||||
|
||||
# system defaults and preferences
|
||||
system = {
|
||||
stateVersion = 6;
|
||||
configurationRevision = self.rev or self.dirtyRev or null;
|
||||
|
||||
startup.chime = false;
|
||||
|
||||
activationScripts = {
|
||||
setWallpaper.text = ''
|
||||
/usr/bin/osascript <<EOF
|
||||
tell application "System Events"
|
||||
tell every desktop
|
||||
set picture to "/Users/phil/Pictures/Wallpapers/Ghost_in_the_Shell.png"
|
||||
end tell
|
||||
activationScripts.setWallpaper.text = ''
|
||||
/usr/bin/osascript <<EOF
|
||||
tell application "System Events"
|
||||
tell every desktop
|
||||
set picture to "/Users/${primaryUser}/Pictures/Wallpapers/Ghost_in_the_Shell.png"
|
||||
end tell
|
||||
EOF
|
||||
'';
|
||||
|
||||
};
|
||||
end tell
|
||||
EOF
|
||||
'';
|
||||
|
||||
defaults = {
|
||||
ActivityMonitor = {
|
||||
@@ -37,20 +37,21 @@
|
||||
launchanim = true;
|
||||
mru-spaces = false;
|
||||
orientation = "left";
|
||||
persistent-apps = [
|
||||
{ app = "/Users/phil/Applications/Home Manager Apps/kitty.app"; }
|
||||
{ app = "/Users/phil/Applications/Home Manager Apps/Vesktop.app"; }
|
||||
{ app = "/Users/phil/Applications/Home Manager Apps/Spotify.app"; }
|
||||
{ app = "/Users/phil/Applications/Home Manager Apps/Floorp.app"; }
|
||||
{ app = "/Users/phil/Applications/Home Manager Apps/Obsidian.app"; }
|
||||
{ app = "/Users/phil/Applications/Home Manager Apps/OpenSCAD.app"; }
|
||||
{ app = "/Applications/okular.app"; }
|
||||
{ app = "/Applications/Affinity.app"; }
|
||||
{ app = "/System/Applications/Mail.app"; }
|
||||
{ app = "/System/Applications/Launchpad.app"; }
|
||||
];
|
||||
show-recents = false;
|
||||
mineffect = "genie";
|
||||
persistent-apps = map (app: { inherit app; }) [
|
||||
(hmApps "kitty")
|
||||
(hmApps "Vesktop")
|
||||
(hmApps "Spotify")
|
||||
(hmApps "Floorp")
|
||||
(hmApps "Obsidian")
|
||||
(hmApps "OpenSCAD")
|
||||
(apps "okular")
|
||||
(apps "Affinity")
|
||||
(apps "Element")
|
||||
(sysApps "Mail")
|
||||
(sysApps "Launchpad")
|
||||
];
|
||||
};
|
||||
|
||||
loginwindow = {
|
||||
@@ -59,11 +60,11 @@
|
||||
};
|
||||
|
||||
finder = {
|
||||
AppleShowAllFiles = true; # hidden files
|
||||
AppleShowAllExtensions = true; # file extensions
|
||||
_FXShowPosixPathInTitle = true; # title bar full path
|
||||
ShowPathbar = true; # breadcrumb nav at bottom
|
||||
ShowStatusBar = true; # file count & disk space
|
||||
AppleShowAllFiles = true;
|
||||
AppleShowAllExtensions = true;
|
||||
_FXShowPosixPathInTitle = true;
|
||||
ShowPathbar = true;
|
||||
ShowStatusBar = true;
|
||||
};
|
||||
|
||||
NSGlobalDomain = {
|
||||
|
||||
+1
-64
@@ -1,4 +1,4 @@
|
||||
{ pkgs, ... }: {
|
||||
_: {
|
||||
services = {
|
||||
yabai = {
|
||||
enable = true;
|
||||
@@ -38,68 +38,5 @@
|
||||
mouse_drop_action = "swap";
|
||||
};
|
||||
};
|
||||
|
||||
# skhd = {
|
||||
# enable = true;
|
||||
# skhdConfig = ''
|
||||
# Application Bindings
|
||||
# cmd - q : open -a kitty
|
||||
# cmd - e : ${pkgs.kitty}/bin/kitty yazi
|
||||
# cmd - o : open -a "Obsidian"
|
||||
# cmd - i : open -a "Floorp"
|
||||
# cmd - g : open -a "Mail"
|
||||
|
||||
# Window Management (using yabai if installed, otherwise basic macOS)
|
||||
#cmd + shift - c : yabai -m window --close || osascript -e 'tell application "System Events" to keystroke "w" using command down'
|
||||
#cmd + shift - v : yabai -m window --toggle float
|
||||
|
||||
# Focus windows (vim-like)
|
||||
# cmd - left : yabai -m window --focus west
|
||||
# cmd - right : yabai -m window --focus east
|
||||
# cmd - up : yabai -m window --focus north
|
||||
# cmd - down : yabai -m window --focus south
|
||||
|
||||
# Move windows to spaces (workspaces)
|
||||
# cmd + shift - 1 : yabai -m window --space 1
|
||||
# cmd + shift - 2 : yabai -m window --space 2
|
||||
# cmd + shift - 3 : yabai -m window --space 3
|
||||
# cmd + shift - 4 : yabai -m window --space 4
|
||||
# cmd + shift - 5 : yabai -m window --space 5
|
||||
# cmd + shift - 6 : yabai -m window --space 6
|
||||
# cmd + shift - 7 : yabai -m window --space 7
|
||||
# cmd + shift - 8 : yabai -m window --space 8
|
||||
# cmd + shift - 9 : yabai -m window --space 9
|
||||
# cmd + shift - 0 : yabai -m window --space 10
|
||||
|
||||
# Switch to spaces (workspaces)
|
||||
# cmd - 1 : yabai -m space --focus 1
|
||||
# cmd - 2 : yabai -m space --focus 2
|
||||
# cmd - 3 : yabai -m space --focus 3
|
||||
# cmd - 4 : yabai -m space --focus 4
|
||||
# cmd - 5 : yabai -m space --focus 5
|
||||
# cmd - 6 : yabai -m space --focus 6
|
||||
# cmd - 7 : yabai -m space --focus 7
|
||||
# cmd - 8 : yabai -m space --focus 8
|
||||
# cmd - 9 : yabai -m space --focus 9
|
||||
# cmd - 0 : yabai -m space --focus 10
|
||||
|
||||
# Screenshot (macOS native)
|
||||
# cmd - z : screencapture -i ~/Pictures/Screenshots/$(date +%s).png
|
||||
# cmd - u : screencapture ~/Pictures/Screenshots/$(date +%s).png
|
||||
|
||||
# Launcher (using Raycast or Spotlight as Rofi alternative)
|
||||
# cmd - r : open -a "Raycast" || osascript -e 'tell application "System Events" to keystroke space using command down'
|
||||
|
||||
# Lock screen
|
||||
# cmd - m : pmset displaysleepnow
|
||||
|
||||
# Toggle layout (if using yabai)
|
||||
# cmd - j : yabai -m space --layout $(yabai -m query --spaces --space | jq -r 'if .type == "bsp" then "float" else "bsp" end')
|
||||
# cmd - p : yabai -m window --toggle split
|
||||
|
||||
# Reload skhd config
|
||||
# cmd + shift - r : skhd --reload
|
||||
# '';
|
||||
# };
|
||||
};
|
||||
}
|
||||
|
||||
Generated
+1020
-1
File diff suppressed because it is too large
Load Diff
@@ -16,10 +16,15 @@
|
||||
inputs.nixpkgs.follows = "nixpkgs";
|
||||
};
|
||||
|
||||
# NIX User Repositorys
|
||||
nur = {
|
||||
url = "github:nix-community/NUR";
|
||||
inputs.nixpkgs.follows = "nixpkgs";
|
||||
};
|
||||
|
||||
# declarative Hyprland
|
||||
hyprland = {
|
||||
url = "github:hyprwm/Hyprland";
|
||||
inputs.nixpkgs.follows = "nixpkgs";
|
||||
};
|
||||
|
||||
hyprland-plugins = {
|
||||
@@ -85,10 +90,66 @@
|
||||
hyprland,
|
||||
sops-nix,
|
||||
nixos-generators,
|
||||
nur,
|
||||
...
|
||||
}@inputs:
|
||||
let
|
||||
primaryUser = "phil";
|
||||
|
||||
mkIso =
|
||||
{
|
||||
hostName,
|
||||
isDarwin ? false,
|
||||
isServer ? false,
|
||||
}:
|
||||
nixos-generators.nixosGenerate {
|
||||
system = "x86_64-linux";
|
||||
format = "iso";
|
||||
specialArgs = {
|
||||
inherit
|
||||
inputs
|
||||
primaryUser
|
||||
self
|
||||
hostName
|
||||
isDarwin
|
||||
isServer
|
||||
;
|
||||
};
|
||||
modules = [
|
||||
{
|
||||
nixpkgs.overlays = [
|
||||
inputs.nur.overlays.default
|
||||
(import ./overlays { inherit (inputs) nur; })
|
||||
];
|
||||
}
|
||||
{ nixpkgs.config.allowUnfree = true; }
|
||||
{ nixpkgs.hostPlatform = "x86_64-linux"; }
|
||||
{ networking.hostName = hostName; }
|
||||
./hosts/${hostName}/configuration.nix
|
||||
./nixos
|
||||
inputs.sops-nix.nixosModules.sops
|
||||
inputs.home-manager.nixosModules.home-manager
|
||||
{
|
||||
home-manager = {
|
||||
extraSpecialArgs = {
|
||||
inherit
|
||||
inputs
|
||||
primaryUser
|
||||
self
|
||||
hostName
|
||||
isDarwin
|
||||
isServer
|
||||
;
|
||||
};
|
||||
users.${primaryUser} = import ./home;
|
||||
backupFileExtension = "backup";
|
||||
useGlobalPkgs = true;
|
||||
useUserPackages = true;
|
||||
};
|
||||
}
|
||||
];
|
||||
};
|
||||
|
||||
mkSystem =
|
||||
{
|
||||
hostName,
|
||||
@@ -113,6 +174,12 @@
|
||||
|
||||
sharedModules = [
|
||||
{ networking.hostName = hostName; }
|
||||
{
|
||||
nixpkgs = {
|
||||
overlays = [ (import ./overlays { inherit (inputs) nur; }) ];
|
||||
config.allowUnfree = true;
|
||||
};
|
||||
}
|
||||
./hosts/${hostName}/configuration.nix
|
||||
inputs.sops-nix.${platformModuleSet}.sops
|
||||
inputs.home-manager.${platformModuleSet}.home-manager
|
||||
@@ -120,7 +187,9 @@
|
||||
home-manager = {
|
||||
extraSpecialArgs = sharedSpecialArgs;
|
||||
users.${primaryUser} = import ./home;
|
||||
backupFileExtension = "backup";
|
||||
backupFileExtension = "hm-backup";
|
||||
useGlobalPkgs = true;
|
||||
useUserPackages = true;
|
||||
};
|
||||
}
|
||||
];
|
||||
@@ -182,36 +251,26 @@
|
||||
isDarwin = true;
|
||||
};
|
||||
|
||||
# NEW: flashable image for cyper-controller
|
||||
packages.x86_64-linux.cyper-controller-image = nixos-generators.nixosGenerate {
|
||||
system = "x86_64-linux";
|
||||
format = "raw-efi";
|
||||
specialArgs = {
|
||||
inherit inputs primaryUser self;
|
||||
packages.x86_64-linux = {
|
||||
cyper-desktop-iso = mkIso { hostName = "cyper-desktop"; };
|
||||
cyper-controller-iso = mkIso {
|
||||
hostName = "cyper-controller";
|
||||
isDarwin = false;
|
||||
isServer = true;
|
||||
};
|
||||
modules = [
|
||||
{ nixpkgs.hostPlatform = "x86_64-linux"; }
|
||||
{ networking.hostName = "cyper-controller"; }
|
||||
./hosts/cyper-controller/configuration.nix
|
||||
./nixos
|
||||
inputs.sops-nix.nixosModules.sops
|
||||
inputs.home-manager.nixosModules.home-manager
|
||||
{
|
||||
home-manager = {
|
||||
extraSpecialArgs = {
|
||||
inherit inputs primaryUser self;
|
||||
hostName = "cyper-controller";
|
||||
isDarwin = false;
|
||||
isServer = true;
|
||||
};
|
||||
users.${primaryUser} = import ./home;
|
||||
backupFileExtension = "backup";
|
||||
};
|
||||
}
|
||||
];
|
||||
cyper-proxy-iso = mkIso {
|
||||
hostName = "cyper-proxy";
|
||||
isServer = true;
|
||||
};
|
||||
cyper-node-1-iso = mkIso {
|
||||
hostName = "cyper-node-1";
|
||||
isServer = true;
|
||||
};
|
||||
cyper-node-2-iso = mkIso {
|
||||
hostName = "cyper-node-2";
|
||||
isServer = true;
|
||||
};
|
||||
};
|
||||
|
||||
formatter.x86_64-linux = nixpkgs.legacyPackages.x86_64-linux.nixfmt-tree;
|
||||
};
|
||||
}
|
||||
|
||||
+4
-2
@@ -8,7 +8,8 @@
|
||||
imports = [ inputs.catppuccin.homeModules.catppuccin ];
|
||||
|
||||
catppuccin = {
|
||||
enable = false;
|
||||
enable = true;
|
||||
autoEnable = false;
|
||||
accent = "sky";
|
||||
flavor = "mocha";
|
||||
eza.enable = true;
|
||||
@@ -31,7 +32,7 @@
|
||||
enable = true;
|
||||
accent = "sapphire";
|
||||
};
|
||||
hyprland = lib.mkIf (!isDarwin) { enable = true; };
|
||||
hyprland = lib.mkIf (!isDarwin) { enable = false; };
|
||||
hyprlock = lib.mkIf (!isDarwin) {
|
||||
enable = true;
|
||||
useDefaultConfig = false;
|
||||
@@ -49,5 +50,6 @@
|
||||
enable = true;
|
||||
apply = true;
|
||||
};
|
||||
opencode.enable = true;
|
||||
};
|
||||
}
|
||||
|
||||
+6
-3
@@ -17,12 +17,16 @@
|
||||
./xdg.nix
|
||||
./neovim
|
||||
./python.nix
|
||||
./fonts.nix
|
||||
inputs.sops-nix.homeManagerModules.sops
|
||||
]
|
||||
++ lib.optionals (!isDarwin && !isServer) [
|
||||
./desktop
|
||||
./catppuccin.nix
|
||||
]
|
||||
++ lib.optionals (!isDarwin) [
|
||||
./opencode.nix
|
||||
]
|
||||
++ lib.optionals isDarwin [
|
||||
./desktop/sketchybar
|
||||
./catppuccin.nix
|
||||
@@ -30,14 +34,13 @@
|
||||
++ lib.optionals (!isServer) [
|
||||
./nixcord.nix
|
||||
./spicetify.nix
|
||||
./floorp.nix
|
||||
./floorp
|
||||
./obsidian.nix
|
||||
];
|
||||
|
||||
nixpkgs.config.allowUnfree = true;
|
||||
|
||||
home = {
|
||||
username = primaryUser;
|
||||
enableNixpkgsReleaseCheck = false;
|
||||
stateVersion = "26.05";
|
||||
sessionVariables = lib.mkIf (!isDarwin && !isServer) {
|
||||
GROQ_API_KEY = config.sops.secrets.GROQ_API_KEY.path;
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
{ pkgs, ... }:
|
||||
{
|
||||
_: {
|
||||
imports = [
|
||||
./hyprland
|
||||
./rofi
|
||||
@@ -10,11 +9,6 @@
|
||||
|
||||
_module.args.compositor = "hyprland";
|
||||
|
||||
home.packages = with pkgs; [
|
||||
waypaper
|
||||
awww
|
||||
onlyoffice-desktopeditors
|
||||
];
|
||||
home.file.".config/waypaper/config.ini".source = ./waypaper.ini;
|
||||
|
||||
programs = {
|
||||
|
||||
@@ -1,16 +1,5 @@
|
||||
{ inputs, pkgs, ... }:
|
||||
let
|
||||
super = "SUPER";
|
||||
terminal = "kitty";
|
||||
fileManager = "yazi";
|
||||
theme = "-theme $HOME/.config/rofi/custom.rasi";
|
||||
menu = "rofi -show drun ${theme}";
|
||||
filebrowser = "rofi -show filebrowser ${theme}";
|
||||
power = "rofi -show p -modi p:rofi-power-menu -theme $HOME/.config/rofi/power.rasi";
|
||||
apps = "rofi -show window ${theme}";
|
||||
in
|
||||
{ pkgs, ... }:
|
||||
{
|
||||
|
||||
imports = [
|
||||
./hypridle.nix
|
||||
./hyprlock.nix
|
||||
@@ -30,8 +19,10 @@ in
|
||||
|
||||
systemd.user.targets.hyprland-session.Unit.Wants = [ "xdg-desktop-autostart.target" ];
|
||||
|
||||
services.awww.enable = true;
|
||||
|
||||
wayland.windowManager.hyprland = {
|
||||
package = inputs.hyprland.packages.${pkgs.stdenv.hostPlatform.system}.hyprland;
|
||||
package = null;
|
||||
enable = true;
|
||||
|
||||
xwayland.enable = true;
|
||||
@@ -42,256 +33,6 @@ in
|
||||
enableXdgAutostart = false;
|
||||
};
|
||||
|
||||
plugins = with inputs.hyprland-plugins.packages.${pkgs.stdenv.hostPlatform.system}; [
|
||||
#hyprbars
|
||||
# hyprexpo
|
||||
];
|
||||
|
||||
settings = {
|
||||
env = [
|
||||
"NIXOS_OZONE_WL,1"
|
||||
"MOZ_ENABLE_WAYLAND,1"
|
||||
"MOZ_WEBRENDER,1"
|
||||
"_JAVA_AWT_WM_NONREPARENTING,1"
|
||||
"QT_WAYLAND_DISABLE_WINDOWDECORATION,1"
|
||||
"QT_QPA_PLATFORM,wayland"
|
||||
"SDL_VIDEODRIVER,wayland"
|
||||
"GDK_BACKEND,wayland,x11"
|
||||
"XCURSOR_SIZE,24"
|
||||
"EDITOR,nvim"
|
||||
"GSK_RENDERER,gl"
|
||||
"HYPRCURSOR_THEME,catppuccin-mocha-dark"
|
||||
"HYPRCURSOR_SIZE,24"
|
||||
"XCURSOR_THEME,catppuccin-mocha-dark"
|
||||
"XCURSOR_SIZE,24"
|
||||
];
|
||||
|
||||
monitor = [
|
||||
"DP-1, 1920x1080@60, 1920x0, 1"
|
||||
"HDMI-A-2, 1920x1080@60, 0x0, 1"
|
||||
];
|
||||
|
||||
input = {
|
||||
kb_layout = "de";
|
||||
kb_variant = "mac";
|
||||
kb_options = "apple:fn_lock";
|
||||
repeat_rate = 50;
|
||||
repeat_delay = 300;
|
||||
|
||||
accel_profile = "flat";
|
||||
follow_mouse = 1;
|
||||
mouse_refocus = false;
|
||||
sensitivity = 0; # -1.0 to 1.0, 0 means no modification.
|
||||
|
||||
numlock_by_default = 1;
|
||||
touchpad = {
|
||||
natural_scroll = true;
|
||||
tap-to-click = true;
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
general = {
|
||||
# See https://wiki.hyprland.org/Configuring/Variables/ for more
|
||||
gaps_in = 2;
|
||||
gaps_out = 0;
|
||||
border_size = 4;
|
||||
|
||||
"col.active_border" = "$green";
|
||||
"col.inactive_border" = "$red";
|
||||
|
||||
layout = "dwindle";
|
||||
|
||||
# Please see https://wiki.hyprland.org/Configuring/Tearing/ before you turn this on
|
||||
allow_tearing = false;
|
||||
};
|
||||
|
||||
decoration = {
|
||||
rounding = 1;
|
||||
|
||||
shadow = {
|
||||
enabled = false;
|
||||
range = 16;
|
||||
render_power = 4;
|
||||
ignore_window = true;
|
||||
color = "$green";
|
||||
color_inactive = "$red";
|
||||
};
|
||||
|
||||
blur = {
|
||||
enabled = false;
|
||||
size = 1;
|
||||
passes = 3;
|
||||
new_optimizations = 1;
|
||||
noise = 4.0e-2;
|
||||
};
|
||||
};
|
||||
|
||||
animations = {
|
||||
enabled = "yes";
|
||||
bezier = "myBezier, 0.05, 0.9, 0.1, 1.05";
|
||||
animation = [
|
||||
"windows, 1, 7, myBezier"
|
||||
"windowsOut, 1, 7, default, popin 80%"
|
||||
"border, 1, 10, default"
|
||||
"borderangle, 1, 8, default"
|
||||
"fade, 1, 7, default"
|
||||
"workspaces, 1, 6, default"
|
||||
];
|
||||
};
|
||||
|
||||
# layerrule = [
|
||||
# "ignorezero,notifications"
|
||||
# "ignorezero,rofi"
|
||||
# ];
|
||||
|
||||
dwindle = {
|
||||
pseudotile = "yes";
|
||||
preserve_split = "yes";
|
||||
};
|
||||
|
||||
# gestures = {
|
||||
# See https://wiki.hyprland.org/Configuring/Variables/ for more
|
||||
# workspace_swipe = true;
|
||||
# workspace_swipe_fingers = 3;
|
||||
# workspace_swipe_distance = 300;
|
||||
# workspace_swipe_invert = false;
|
||||
# workspace_swipe_cancel_ratio = 0.5;
|
||||
# };
|
||||
|
||||
misc = {
|
||||
force_default_wallpaper = 0;
|
||||
disable_hyprland_logo = true;
|
||||
disable_splash_rendering = true;
|
||||
mouse_move_enables_dpms = true;
|
||||
key_press_enables_dpms = true;
|
||||
# vfr = true;
|
||||
vrr = 0;
|
||||
};
|
||||
|
||||
device = {
|
||||
name = "usb-optical-mouse-";
|
||||
sensitivity = 0;
|
||||
};
|
||||
#deprecated
|
||||
# windowrulev2 = [
|
||||
# "suppressevent maximize, class:.*"
|
||||
# "float, class:^(com.obsproject.Studio)$"
|
||||
# "size 1280 800, class:^(com.obsproject.Studio)$"
|
||||
# "float, class:^(xdg-desktop-portal-gtk)$"
|
||||
# "center, class:^(xdg-desktop-portal-gtk)$"
|
||||
# ];
|
||||
|
||||
# windowrule = [
|
||||
# "opacity 0.0 override, class:^(xwaylandvideobridge)$"
|
||||
# "noanim, class:^(xwaylandvideobridge)$"
|
||||
# "noinitialfocus, class:^(xwaylandvideobridge)$"
|
||||
# "maxsize 1 1, class:^(xwaylandvideobridge)$"
|
||||
# "noblur, class:^(xwaylandvideobridge)$"
|
||||
# "nofocus, class:^(xwaylandvideobridge)$"
|
||||
# "noblur, class:^(org\\.gnome\\.|io\\.github\\.|org\\.gtk\\.)"
|
||||
# ];
|
||||
|
||||
exec-once = [
|
||||
"awww-daemon --no-cache & disown"
|
||||
"awww img ~/Pictures/Wallpapers/Ghost_in_the_Shell.png"
|
||||
"waybar &"
|
||||
];
|
||||
|
||||
# Keybindings
|
||||
bind = [
|
||||
|
||||
# Application Bindings
|
||||
"${super}, Q, exec, ${terminal}"
|
||||
"${super}, E, exec, ${fileManager}"
|
||||
"${super}, O, exec, obsidian"
|
||||
"${super}, I, exec, floorp"
|
||||
"${super}, G, exec, thunderbird"
|
||||
", XF86Mail, exec, thunderbird"
|
||||
"${super}, N, exec, nautilus"
|
||||
", XF86Search, exec, nautilus"
|
||||
|
||||
# Lock Screen
|
||||
"${super}, M, exit, "
|
||||
|
||||
# Rofi bindings
|
||||
"${super}, F, exec, ${filebrowser}"
|
||||
"${super}, A, exec, ${apps}"
|
||||
", Menu, exec, ${apps}"
|
||||
"${super}, R, exec, ${menu}"
|
||||
", XF86LaunchA, exec, ${menu}"
|
||||
"${super}, S, exec, ${power}"
|
||||
", XF86LaunchB, exec, ${power}"
|
||||
|
||||
# Move focus with mainMod + arrow keys
|
||||
"${super}, left, movefocus, l"
|
||||
"${super}, right, movefocus, r"
|
||||
"${super}, up, movefocus, u"
|
||||
"${super}, down, movefocus, d"
|
||||
|
||||
# Window Modifiers
|
||||
"${super}, P, pseudo, " # dwindle
|
||||
# "${super}, J, togglesplit, " # dwindle doenst exist
|
||||
"${super}, V, togglefloating, " # dwindle
|
||||
"${super}, C, killactive, "
|
||||
|
||||
# Switch workspaces with mainMod + [0-9]
|
||||
"${super}, 1, workspace, 1"
|
||||
"${super}, 2, workspace, 2"
|
||||
"${super}, 3, workspace, 3"
|
||||
"${super}, 4, workspace, 4"
|
||||
"${super}, 5, workspace, 5"
|
||||
"${super}, 6, workspace, 6"
|
||||
"${super}, 7, workspace, 7"
|
||||
"${super}, 8, workspace, 8"
|
||||
"${super}, 9, workspace, 9"
|
||||
"${super}, 0, workspace, 10"
|
||||
|
||||
# Move active window to a workspace with mainMod + SHIFT + [0-9]
|
||||
"${super} SHIFT, 1, movetoworkspace, 1"
|
||||
"${super} SHIFT, 2, movetoworkspace, 2"
|
||||
"${super} SHIFT, 3, movetoworkspace, 3"
|
||||
"${super} SHIFT, 4, movetoworkspace, 4"
|
||||
"${super} SHIFT, 5, movetoworkspace, 5"
|
||||
"${super} SHIFT, 6, movetoworkspace, 6"
|
||||
"${super} SHIFT, 7, movetoworkspace, 7"
|
||||
"${super} SHIFT, 8, movetoworkspace, 8"
|
||||
"${super} SHIFT, 9, movetoworkspace, 9"
|
||||
"${super} SHIFT, 0, movetoworkspace, 10"
|
||||
|
||||
# Example special workspace (scratchpad)
|
||||
#"${super}, S, togglespecialworkspace, magic"
|
||||
"${super} SHIFT, S, movetoworkspace, special:magic"
|
||||
|
||||
# Scroll through existing workspaces with mainMod + scroll
|
||||
"${super}, mouse_down, workspace, e+1"
|
||||
"${super}, mouse_up, workspace, e-1"
|
||||
|
||||
# Screenshot
|
||||
''${super}, Z, exec, grim -g "$(slurp)" $HOME/Pictures/Screenshots/$(date +'%s_grim.png')''
|
||||
"${super}, U, exec, grim $HOME/Pictures/Screenshots/$(date +'%s_grim.png')"
|
||||
];
|
||||
|
||||
bindl = [
|
||||
#", XF86AudioMute, exec, amixer set Master toggle
|
||||
", XF86AudioMute, exec, pamixer -t"
|
||||
", XF86AudioPlay, exec, playerctl play-pause" # the stupid key is called play , but it toggles
|
||||
", XF86AudioNext, exec, playerctl next"
|
||||
", XF86AudioPrev, exec, playerctl previous"
|
||||
];
|
||||
|
||||
bindle = [
|
||||
# Multi Media Control
|
||||
", XF86AudioRaiseVolume, exec, pamixer -i 5"
|
||||
", XF86AudioLowerVolume, exec, pamixer -d 5"
|
||||
", XF86MonBrightnessUp, exec, brightnessctl set +5%"
|
||||
", XF86MonBrightnessDown, exec, brightnessctl set 5%-"
|
||||
];
|
||||
|
||||
bindm = [
|
||||
"${super}, mouse:272, movewindow"
|
||||
"${super}, mouse:273, resizewindow"
|
||||
];
|
||||
};
|
||||
extraConfig = builtins.readFile ./hyprland-scrolling.lua;
|
||||
};
|
||||
}
|
||||
|
||||
@@ -0,0 +1,310 @@
|
||||
-- hyprland.lua — migrated from hyprlang for Hyprland 0.55+
|
||||
-- https://wiki.hypr.land/Configuring/Start/
|
||||
|
||||
-- ── Variables ────────────────────────────────────────────────────────────────
|
||||
|
||||
local super = "SUPER"
|
||||
local terminal = "kitty"
|
||||
local fileManager = "yazi"
|
||||
local theme = "-theme $HOME/.config/rofi/custom.rasi"
|
||||
local menu = "rofi -show drun " .. theme
|
||||
local filebrowser = "rofi -show filebrowser " .. theme
|
||||
local power = "rofi -show p -modi p:rofi-power-menu -theme $HOME/.config/rofi/power.rasi"
|
||||
local apps = "rofi -show window " .. theme
|
||||
local screenshot = "$HOME/Pictures/Screenshots/$(date +'%s_grim.png')"
|
||||
|
||||
-- ── Helpers ───────────────────────────────────────────────────────────────────
|
||||
|
||||
-- Bind a list of { key, action [, opts] } entries
|
||||
local function bind_all(list)
|
||||
for _, b in ipairs(list) do
|
||||
hl.bind(b[1], b[2], b[3])
|
||||
end
|
||||
end
|
||||
|
||||
-- Bind a list of { key, cmd [, opts] } entries as exec_cmd actions
|
||||
local function bind_exec(list)
|
||||
for _, b in ipairs(list) do
|
||||
hl.bind(b[1], hl.dsp.exec_cmd(b[2]), b[3])
|
||||
end
|
||||
end
|
||||
|
||||
-- Bind a list of { key, layout_msg } entries as layout actions
|
||||
local function bind_layout(list)
|
||||
for _, b in ipairs(list) do
|
||||
hl.bind(b[1], hl.dsp.layout(b[2]))
|
||||
end
|
||||
end
|
||||
|
||||
-- ── Monitors ─────────────────────────────────────────────────────────────────
|
||||
|
||||
local monitors = {
|
||||
{ output = "DP-1", mode = "1920x1080@60", position = "1920x0", scale = 1 },
|
||||
{ output = "HDMI-A-2", mode = "1920x1080@60", position = "0x0", scale = 1 },
|
||||
}
|
||||
|
||||
for _, m in ipairs(monitors) do
|
||||
hl.monitor(m)
|
||||
end
|
||||
|
||||
-- ── Environment ──────────────────────────────────────────────────────────────
|
||||
|
||||
local env_vars = {
|
||||
NIXOS_OZONE_WL = "1",
|
||||
MOZ_ENABLE_WAYLAND = "1",
|
||||
MOZ_WEBRENDER = "1",
|
||||
_JAVA_AWT_WM_NONREPARENTING = "1",
|
||||
QT_WAYLAND_DISABLE_WINDOWDECORATION = "1",
|
||||
QT_QPA_PLATFORM = "wayland",
|
||||
SDL_VIDEODRIVER = "wayland",
|
||||
GDK_BACKEND = "wayland,x11",
|
||||
XCURSOR_SIZE = "24",
|
||||
XCURSOR_THEME = "catppuccin-mocha-dark",
|
||||
EDITOR = "nvim",
|
||||
GSK_RENDERER = "gl",
|
||||
HYPRCURSOR_THEME = "catppuccin-mocha-dark",
|
||||
HYPRCURSOR_SIZE = "24",
|
||||
}
|
||||
|
||||
for k, v in pairs(env_vars) do
|
||||
hl.env(k, v)
|
||||
end
|
||||
|
||||
-- ── Autostart ────────────────────────────────────────────────────────────────
|
||||
|
||||
local wallpaper = "$HOME/Pictures/Wallpapers/Ghost_in_the_Shell.png"
|
||||
|
||||
local autostart = {
|
||||
"sleep 2 && waybar & disown",
|
||||
}
|
||||
|
||||
hl.on("hyprland.start", function()
|
||||
for _, cmd in ipairs(autostart) do
|
||||
hl.exec_cmd(cmd)
|
||||
end
|
||||
end)
|
||||
|
||||
-- ── Config ───────────────────────────────────────────────────────────────────
|
||||
|
||||
hl.config({
|
||||
debug = {
|
||||
disable_logs = false,
|
||||
enable_stdout_logs = false,
|
||||
},
|
||||
|
||||
input = {
|
||||
kb_layout = "de",
|
||||
kb_variant = "mac",
|
||||
kb_options = "apple:fn_lock",
|
||||
repeat_rate = 50,
|
||||
repeat_delay = 300,
|
||||
accel_profile = "flat",
|
||||
follow_mouse = 1,
|
||||
mouse_refocus = false,
|
||||
sensitivity = 0,
|
||||
numlock_by_default = true,
|
||||
touchpad = {
|
||||
natural_scroll = true,
|
||||
tap_to_click = true,
|
||||
},
|
||||
},
|
||||
|
||||
general = {
|
||||
gaps_in = 2,
|
||||
gaps_out = 0,
|
||||
border_size = 4,
|
||||
col = {
|
||||
active_border = "rgba(a6e3a1ff)",
|
||||
inactive_border = "rgba(f38ba8ff)",
|
||||
},
|
||||
layout = "scrolling",
|
||||
allow_tearing = false,
|
||||
},
|
||||
|
||||
decoration = {
|
||||
rounding = 1,
|
||||
shadow = {
|
||||
enabled = false,
|
||||
range = 16,
|
||||
render_power = 4,
|
||||
color = "rgba(a6e3a1ff)",
|
||||
color_inactive = "rgba(f38ba8ff)",
|
||||
},
|
||||
blur = {
|
||||
enabled = false,
|
||||
size = 1,
|
||||
passes = 3,
|
||||
new_optimizations = true,
|
||||
noise = 0.04,
|
||||
},
|
||||
},
|
||||
|
||||
animations = {
|
||||
enabled = true,
|
||||
},
|
||||
|
||||
scrolling = {
|
||||
column_width = 0.5,
|
||||
fullscreen_on_one_column = true,
|
||||
focus_fit_method = 1,
|
||||
follow_focus = true,
|
||||
follow_min_visible = 0.4,
|
||||
explicit_column_widths = "0.333, 0.5, 0.667, 1.0",
|
||||
wrap_focus = true,
|
||||
wrap_swapcol = true,
|
||||
direction = "right",
|
||||
},
|
||||
|
||||
misc = {
|
||||
force_default_wallpaper = 0,
|
||||
disable_hyprland_logo = true,
|
||||
disable_splash_rendering = true,
|
||||
mouse_move_enables_dpms = true,
|
||||
key_press_enables_dpms = true,
|
||||
vrr = 0,
|
||||
},
|
||||
})
|
||||
|
||||
-- ── Animations ───────────────────────────────────────────────────────────────
|
||||
|
||||
hl.curve("myBezier", { type = "bezier", points = { { 0.05, 0.9 }, { 0.1, 1.05 } } })
|
||||
hl.curve("mySpring", { type = "spring", mass = 0.6, stiffness = 70.00, dampening = 10.00 })
|
||||
|
||||
local animations = {
|
||||
{ leaf = "windows", enabled = true, speed = 10, spring = "mySpring" },
|
||||
{ leaf = "windowsOut", enabled = true, speed = 10, spring = "mySpring", style = "popin 80%" },
|
||||
{ leaf = "border", enabled = true, speed = 10, spring = "mySpring" },
|
||||
{ leaf = "borderangle", enabled = true, speed = 10, spring = "mySpring" },
|
||||
{ leaf = "fade", enabled = true, speed = 10, spring = "mySpring" },
|
||||
{ leaf = "workspaces", enabled = true, speed = 10, spring = "mySpring" },
|
||||
}
|
||||
|
||||
for _, anim in ipairs(animations) do
|
||||
hl.animation(anim)
|
||||
end
|
||||
|
||||
-- ── Devices ──────────────────────────────────────────────────────────────────
|
||||
|
||||
local devices = {
|
||||
{ name = "usb-optical-mouse-", sensitivity = 0 },
|
||||
}
|
||||
|
||||
for _, d in ipairs(devices) do
|
||||
hl.device(d)
|
||||
end
|
||||
|
||||
-- ── Window Rules ─────────────────────────────────────────────────────────────
|
||||
|
||||
local window_rules = {
|
||||
{ name = "kitty_width", match = { class = "kitty" }, scrolling_width = 0.5 },
|
||||
{ name = "browser_width", match = { class = "floorp" }, scrolling_width = 0.667 },
|
||||
{ name = "obsidian_width", match = { class = "obsidian" }, scrolling_width = 0.5 },
|
||||
{ name = "nautilus_width", match = { class = "nautilus" }, scrolling_width = 0.333 },
|
||||
{ name = "thunderbird_width", match = { class = "thunderbird" }, scrolling_width = 0.667 },
|
||||
}
|
||||
|
||||
for _, rule in ipairs(window_rules) do
|
||||
hl.window_rule(rule)
|
||||
end
|
||||
|
||||
-- ── Binds ────────────────────────────────────────────────────────────────────
|
||||
|
||||
-- Applications & launchers
|
||||
bind_exec({
|
||||
{ super .. " + Q", terminal },
|
||||
{ super .. " + E", fileManager },
|
||||
{ super .. " + O", "obsidian" },
|
||||
{ super .. " + I", "floorp" },
|
||||
{ super .. " + G", "thunderbird" },
|
||||
{ "XF86Mail", "thunderbird" },
|
||||
{ super .. " + N", "nautilus" },
|
||||
{ "XF86Search", "nautilus" },
|
||||
-- Rofi
|
||||
{ super .. " + F", filebrowser },
|
||||
{ super .. " + A", apps },
|
||||
{ "Menu", apps },
|
||||
{ super .. " + R", menu },
|
||||
{ "XF86LaunchA", menu },
|
||||
{ super .. " + S", power },
|
||||
{ "XF86LaunchB", power },
|
||||
-- Screenshots
|
||||
{ super .. " + Z", 'grim -g "$(slurp)" ' .. screenshot },
|
||||
{ super .. " + U", "grim " .. screenshot },
|
||||
-- Media & brightness (locked = works on lockscreen, repeating = held key)
|
||||
{ "XF86AudioMute", "pamixer -t", { locked = true } },
|
||||
{ "XF86AudioPlay", "playerctl play-pause", { locked = true } },
|
||||
{ "XF86AudioNext", "playerctl next", { locked = true } },
|
||||
{ "XF86AudioPrev", "playerctl previous", { locked = true } },
|
||||
{ "XF86AudioRaiseVolume", "pamixer -i 5", { locked = true, repeating = true } },
|
||||
{ "XF86AudioLowerVolume", "pamixer -d 5", { locked = true, repeating = true } },
|
||||
{ "XF86MonBrightnessUp", "brightnessctl set +5%", { locked = true, repeating = true } },
|
||||
{ "XF86MonBrightnessDown", "brightnessctl set 5%-", { locked = true, repeating = true } },
|
||||
})
|
||||
|
||||
-- Window actions
|
||||
bind_all({
|
||||
{ super .. " + M", hl.dsp.exit() },
|
||||
{ super .. " + V", hl.dsp.window.float({ action = "toggle" }) },
|
||||
{ super .. " + C", hl.dsp.window.close() },
|
||||
-- Mouse move/resize
|
||||
{ super .. " + mouse:272", hl.dsp.window.drag() },
|
||||
{ super .. " + mouse:273", hl.dsp.window.drag({ resize = true }) },
|
||||
-- Switch workspaces with mouse wheel
|
||||
{ super .. " + mouse_down", hl.dsp.focus({ workspace = "e+1" }) },
|
||||
{ super .. " + mouse_up", hl.dsp.focus({ workspace = "e-1" }) },
|
||||
})
|
||||
|
||||
-- Directional focus (up/down move within a column; left/right scroll between columns)
|
||||
for _, dir in ipairs({ "left", "right", "up", "down" }) do
|
||||
hl.bind(super .. " + " .. dir, hl.dsp.layout("focus " .. dir))
|
||||
end
|
||||
|
||||
-- Scrolling layout commands
|
||||
bind_layout({
|
||||
-- Column navigation
|
||||
{ super .. " + period", "move +col" },
|
||||
{ super .. " + comma", "move -col" },
|
||||
-- Column swap
|
||||
{ super .. " + SHIFT + period", "swapcol r" },
|
||||
{ super .. " + SHIFT + comma", "swapcol l" },
|
||||
-- Column resize (cycle through explicit_column_widths)
|
||||
{ super .. " + equal", "colresize +conf" },
|
||||
{ super .. " + minus", "colresize -conf" },
|
||||
-- Fine-grained resize
|
||||
{ super .. " + SHIFT + equal", "colresize +0.05" },
|
||||
{ super .. " + SHIFT + minus", "colresize -0.05" },
|
||||
-- Fit operations
|
||||
{ super .. " + F1", "fit active" },
|
||||
{ super .. " + F2", "fit visible" },
|
||||
{ super .. " + F3", "fit all" },
|
||||
-- Promote window to its own column / consume into previous
|
||||
{ super .. " + RETURN", "promote" },
|
||||
{ super .. " + SHIFT + RETURN", "consume_or_expel prev" },
|
||||
-- Expel/consume explicitly
|
||||
{ super .. " + bracketright", "expel" },
|
||||
{ super .. " + bracketleft", "consume" },
|
||||
-- Toggle scroll lock for active workspace
|
||||
{ super .. " + SHIFT + S", "inhibit_scroll" },
|
||||
})
|
||||
|
||||
-- Workspaces 1–10 (key 0 maps to workspace 10)
|
||||
for i = 1, 10 do
|
||||
local key = tostring(i % 10)
|
||||
hl.bind(super .. " + " .. key, hl.dsp.focus({ workspace = i }))
|
||||
hl.bind(super .. " + SHIFT + " .. key, hl.dsp.window.move({ workspace = i }))
|
||||
end
|
||||
|
||||
-- Special workspace (scratchpad)
|
||||
hl.bind(super .. " + grave", hl.dsp.window.move({ workspace = "special:magic" }))
|
||||
|
||||
-- ── Workspace Rules ───────────────────────────────────────────────────────────
|
||||
|
||||
local workspace_rules = {
|
||||
{ workspace = "1", layout_opts = { direction = "right" } },
|
||||
{ workspace = "2", layout_opts = { direction = "right" } },
|
||||
{ workspace = "3", layout_opts = { direction = "right" } },
|
||||
}
|
||||
|
||||
for _, rule in ipairs(workspace_rules) do
|
||||
hl.workspace_rule(rule)
|
||||
end
|
||||
@@ -0,0 +1,282 @@
|
||||
-- hyprland.lua — migrated from hyprlang for Hyprland 0.55+
|
||||
-- https://wiki.hypr.land/Configuring/Start/
|
||||
|
||||
-- ── Variables ────────────────────────────────────────────────────────────────
|
||||
|
||||
local super = "SUPER"
|
||||
local terminal = "kitty"
|
||||
local fileManager = "yazi"
|
||||
local theme = "-theme $HOME/.config/rofi/custom.rasi"
|
||||
local menu = "rofi -show drun " .. theme
|
||||
local filebrowser = "rofi -show filebrowser " .. theme
|
||||
local power = "rofi -show p -modi p:rofi-power-menu -theme $HOME/.config/rofi/power.rasi"
|
||||
local apps = "rofi -show window " .. theme
|
||||
local screenshot = "$HOME/Pictures/Screenshots/$(date +'%s_grim.png')"
|
||||
|
||||
-- ── Helpers ───────────────────────────────────────────────────────────────────
|
||||
|
||||
-- Bind a list of { key, action [, opts] } entries
|
||||
local function bind_all(list)
|
||||
for _, b in ipairs(list) do
|
||||
hl.bind(b[1], b[2], b[3])
|
||||
end
|
||||
end
|
||||
|
||||
-- Bind a list of { key, cmd [, opts] } entries as exec_cmd actions
|
||||
local function bind_exec(list)
|
||||
for _, b in ipairs(list) do
|
||||
hl.bind(b[1], hl.dsp.exec_cmd(b[2]), b[3])
|
||||
end
|
||||
end
|
||||
|
||||
-- Bind a list of { key, layout_cmd } entries as layout actions
|
||||
local function bind_layout(list)
|
||||
for _, b in ipairs(list) do
|
||||
hl.bind(b[1], hl.dsp.layout(b[2]))
|
||||
end
|
||||
end
|
||||
|
||||
-- ── Monitors ─────────────────────────────────────────────────────────────────
|
||||
|
||||
local monitors = {
|
||||
{ output = "DP-1", mode = "1920x1080@60", position = "1920x0", scale = 1 },
|
||||
{ output = "HDMI-A-2", mode = "1920x1080@60", position = "0x0", scale = 1 },
|
||||
}
|
||||
|
||||
for _, m in ipairs(monitors) do
|
||||
hl.monitor(m)
|
||||
end
|
||||
|
||||
-- ── Environment ──────────────────────────────────────────────────────────────
|
||||
|
||||
local env_vars = {
|
||||
NIXOS_OZONE_WL = "1",
|
||||
MOZ_ENABLE_WAYLAND = "1",
|
||||
MOZ_WEBRENDER = "1",
|
||||
_JAVA_AWT_WM_NONREPARENTING = "1",
|
||||
QT_WAYLAND_DISABLE_WINDOWDECORATION = "1",
|
||||
QT_QPA_PLATFORM = "wayland",
|
||||
SDL_VIDEODRIVER = "wayland",
|
||||
GDK_BACKEND = "wayland,x11",
|
||||
XCURSOR_SIZE = "24",
|
||||
XCURSOR_THEME = "catppuccin-mocha-dark",
|
||||
EDITOR = "nvim",
|
||||
GSK_RENDERER = "gl",
|
||||
HYPRCURSOR_THEME = "catppuccin-mocha-dark",
|
||||
HYPRCURSOR_SIZE = "24",
|
||||
}
|
||||
|
||||
for k, v in pairs(env_vars) do
|
||||
hl.env(k, v)
|
||||
end
|
||||
|
||||
-- ── Autostart ────────────────────────────────────────────────────────────────
|
||||
|
||||
local autostart = {
|
||||
"awww-daemon --no-cache & disown",
|
||||
"awww img ~/Pictures/Wallpapers/Ghost_in_the_Shell.png",
|
||||
"waybar &",
|
||||
}
|
||||
|
||||
hl.on("hyprland.start", function()
|
||||
for _, cmd in ipairs(autostart) do
|
||||
hl.exec_cmd(cmd)
|
||||
end
|
||||
end)
|
||||
|
||||
-- ── Config ───────────────────────────────────────────────────────────────────
|
||||
|
||||
hl.config({
|
||||
debug = {
|
||||
disable_logs = false,
|
||||
enable_stdout_logs = false,
|
||||
},
|
||||
|
||||
input = {
|
||||
kb_layout = "de",
|
||||
kb_variant = "mac",
|
||||
kb_options = "apple:fn_lock",
|
||||
repeat_rate = 50,
|
||||
repeat_delay = 300,
|
||||
accel_profile = "flat",
|
||||
follow_mouse = 1,
|
||||
mouse_refocus = false,
|
||||
sensitivity = 0,
|
||||
numlock_by_default = true,
|
||||
touchpad = {
|
||||
natural_scroll = true,
|
||||
tap_to_click = true,
|
||||
},
|
||||
},
|
||||
|
||||
general = {
|
||||
gaps_in = 2,
|
||||
gaps_out = 0,
|
||||
border_size = 4,
|
||||
col = {
|
||||
active_border = "rgba(a6e3a1ff)",
|
||||
inactive_border = "rgba(f38ba8ff)",
|
||||
},
|
||||
layout = "master",
|
||||
allow_tearing = false,
|
||||
},
|
||||
|
||||
decoration = {
|
||||
rounding = 1,
|
||||
shadow = {
|
||||
enabled = false,
|
||||
range = 16,
|
||||
render_power = 4,
|
||||
color = "rgba(a6e3a1ff)",
|
||||
color_inactive = "rgba(f38ba8ff)",
|
||||
},
|
||||
blur = {
|
||||
enabled = false,
|
||||
size = 1,
|
||||
passes = 3,
|
||||
new_optimizations = true,
|
||||
noise = 0.04,
|
||||
},
|
||||
},
|
||||
|
||||
animations = {
|
||||
enabled = true,
|
||||
},
|
||||
|
||||
master = {
|
||||
new_status = "slave",
|
||||
new_on_top = false,
|
||||
new_on_active = "after",
|
||||
orientation = "left",
|
||||
mfact = 0.55,
|
||||
allow_small_split = false,
|
||||
smart_resizing = true,
|
||||
drop_at_cursor = true,
|
||||
focus_master_on_close = false,
|
||||
},
|
||||
|
||||
misc = {
|
||||
force_default_wallpaper = 0,
|
||||
disable_hyprland_logo = true,
|
||||
disable_splash_rendering = true,
|
||||
mouse_move_enables_dpms = true,
|
||||
key_press_enables_dpms = true,
|
||||
vrr = 0,
|
||||
},
|
||||
})
|
||||
|
||||
-- ── Animations ───────────────────────────────────────────────────────────────
|
||||
|
||||
hl.curve("myBezier", { type = "bezier", points = { { 0.05, 0.9 }, { 0.1, 1.05 } } })
|
||||
|
||||
local animations = {
|
||||
{ leaf = "windows", enabled = true, speed = 7, bezier = "myBezier" },
|
||||
{ leaf = "windowsOut", enabled = true, speed = 7, bezier = "default", style = "popin 80%" },
|
||||
{ leaf = "border", enabled = true, speed = 10, bezier = "default" },
|
||||
{ leaf = "borderangle", enabled = true, speed = 8, bezier = "default" },
|
||||
{ leaf = "fade", enabled = true, speed = 7, bezier = "default" },
|
||||
{ leaf = "workspaces", enabled = true, speed = 6, bezier = "default" },
|
||||
}
|
||||
|
||||
for _, anim in ipairs(animations) do
|
||||
hl.animation(anim)
|
||||
end
|
||||
|
||||
-- ── Devices ──────────────────────────────────────────────────────────────────
|
||||
|
||||
local devices = {
|
||||
{ name = "usb-optical-mouse-", sensitivity = 0 },
|
||||
}
|
||||
|
||||
for _, d in ipairs(devices) do
|
||||
hl.device(d)
|
||||
end
|
||||
|
||||
-- ── Binds ────────────────────────────────────────────────────────────────────
|
||||
|
||||
-- Applications & launchers
|
||||
bind_exec({
|
||||
{ super .. " + Q", terminal },
|
||||
{ super .. " + E", fileManager },
|
||||
{ super .. " + O", "obsidian" },
|
||||
{ super .. " + I", "floorp" },
|
||||
{ super .. " + G", "thunderbird" },
|
||||
{ "XF86Mail", "thunderbird" },
|
||||
{ super .. " + N", "nautilus" },
|
||||
{ "XF86Search", "nautilus" },
|
||||
-- Rofi
|
||||
{ super .. " + F", filebrowser },
|
||||
{ super .. " + A", apps },
|
||||
{ "Menu", apps },
|
||||
{ super .. " + R", menu },
|
||||
{ "XF86LaunchA", menu },
|
||||
{ super .. " + S", power },
|
||||
{ "XF86LaunchB", power },
|
||||
-- Screenshots
|
||||
{ super .. " + Z", 'grim -g "$(slurp)" ' .. screenshot },
|
||||
{ super .. " + U", "grim " .. screenshot },
|
||||
-- Media & brightness (locked = works on lockscreen, repeating = held key)
|
||||
{ "XF86AudioMute", "pamixer -t", { locked = true } },
|
||||
{ "XF86AudioPlay", "playerctl play-pause", { locked = true } },
|
||||
{ "XF86AudioNext", "playerctl next", { locked = true } },
|
||||
{ "XF86AudioPrev", "playerctl previous", { locked = true } },
|
||||
{ "XF86AudioRaiseVolume", "pamixer -i 5", { locked = true, repeating = true } },
|
||||
{ "XF86AudioLowerVolume", "pamixer -d 5", { locked = true, repeating = true } },
|
||||
{ "XF86MonBrightnessUp", "brightnessctl set +5%", { locked = true, repeating = true } },
|
||||
{ "XF86MonBrightnessDown", "brightnessctl set 5%-", { locked = true, repeating = true } },
|
||||
})
|
||||
|
||||
-- Window actions
|
||||
bind_all({
|
||||
{ super .. " + M", hl.dsp.exit() },
|
||||
{ super .. " + P", hl.dsp.window.pseudo() },
|
||||
{ super .. " + V", hl.dsp.window.float({ action = "toggle" }) },
|
||||
{ super .. " + C", hl.dsp.window.close() },
|
||||
-- Mouse move/resize
|
||||
{ super .. " + mouse:272", hl.dsp.window.drag() },
|
||||
{ super .. " + mouse:273", hl.dsp.window.drag({ resize = true }) },
|
||||
-- Scroll through workspaces
|
||||
{ super .. " + mouse_down", hl.dsp.focus({ workspace = "e+1" }) },
|
||||
{ super .. " + mouse_up", hl.dsp.focus({ workspace = "e-1" }) },
|
||||
})
|
||||
|
||||
-- Directional focus
|
||||
for _, dir in ipairs({ "left", "right", "up", "down" }) do
|
||||
hl.bind(super .. " + " .. dir, hl.dsp.focus({ direction = dir }))
|
||||
end
|
||||
|
||||
-- Master layout commands
|
||||
bind_layout({
|
||||
{ super .. " + RETURN", "swapwithmaster auto" },
|
||||
{ super .. " + SHIFT + RETURN", "focusmaster auto" },
|
||||
{ super .. " + TAB", "cyclenext" },
|
||||
{ super .. " + SHIFT + TAB", "cycleprev" },
|
||||
{ super .. " + bracketright", "swapnext" },
|
||||
{ super .. " + bracketleft", "swapprev" },
|
||||
{ super .. " + period", "addmaster" },
|
||||
{ super .. " + comma", "removemaster" },
|
||||
{ super .. " + SHIFT + O", "orientationcycle left top right bottom" },
|
||||
{ super .. " + equal", "mfact +0.05" },
|
||||
{ super .. " + minus", "mfact -0.05" },
|
||||
})
|
||||
|
||||
-- Workspaces 1–10 (key 0 maps to workspace 10)
|
||||
for i = 1, 10 do
|
||||
local key = tostring(i % 10)
|
||||
hl.bind(super .. " + " .. key, hl.dsp.focus({ workspace = i }))
|
||||
hl.bind(super .. " + SHIFT + " .. key, hl.dsp.window.move({ workspace = i }))
|
||||
end
|
||||
|
||||
-- Special workspace (scratchpad)
|
||||
hl.bind(super .. " + SHIFT + S", hl.dsp.window.move({ workspace = "special:magic" }))
|
||||
|
||||
-- ── Workspace Rules ───────────────────────────────────────────────────────────
|
||||
|
||||
local workspace_rules = {
|
||||
{ workspace = "1", layout_opts = { orientation = "left" } },
|
||||
{ workspace = "2", layout_opts = { orientation = "top" } },
|
||||
}
|
||||
|
||||
for _, rule in ipairs(workspace_rules) do
|
||||
hl.workspace_rule(rule)
|
||||
end
|
||||
@@ -1,110 +0,0 @@
|
||||
{ ... }:
|
||||
{
|
||||
services.swaync = {
|
||||
enable = true;
|
||||
settings = {
|
||||
positionX = "center";
|
||||
positionY = "center";
|
||||
layer = "overlay";
|
||||
control-center-layer = "top";
|
||||
layer-shell = true;
|
||||
cssPriority = "user";
|
||||
control-center-margin-top = 100;
|
||||
control-center-margin-bottom = 200;
|
||||
control-center-margin-right = 0;
|
||||
control-center-margin-left = 0;
|
||||
notification-2fa-action = true;
|
||||
notification-inline-replies = false;
|
||||
notification-icon-size = 64;
|
||||
notification-body-image-height = 100;
|
||||
notification-body-image-width = 200;
|
||||
widgets = [
|
||||
"mpris"
|
||||
"volume"
|
||||
"inhibitors"
|
||||
"title"
|
||||
"dnd"
|
||||
"notifications"
|
||||
];
|
||||
widget-config = {
|
||||
|
||||
mpris = {
|
||||
blacklist = [ ];
|
||||
autohide = false;
|
||||
show-album-art = "always";
|
||||
loop-carousel = false;
|
||||
image-size = 96;
|
||||
image-radius = 12;
|
||||
};
|
||||
|
||||
volume = {
|
||||
label = "gain";
|
||||
show-per-app = false;
|
||||
empty-list-label = "Nothin' is playin'";
|
||||
expand-button-label = "⤢";
|
||||
collaps-button-label = "⤡";
|
||||
};
|
||||
|
||||
title = {
|
||||
text = "Hollerin'";
|
||||
clear-all-button = true;
|
||||
button-text = "Sheriff's Pardon";
|
||||
};
|
||||
|
||||
dnd = {
|
||||
text = "Let'er rest";
|
||||
};
|
||||
|
||||
menubar = {
|
||||
"menu#power" = {
|
||||
label = "Power";
|
||||
position = "right";
|
||||
animation-type = "slide_down";
|
||||
animation-duration = 250;
|
||||
actions = [
|
||||
{
|
||||
label = "Bolt It";
|
||||
command = "hyprlock";
|
||||
}
|
||||
{
|
||||
label = "Ride Out";
|
||||
command = "hyprctl dispatch exit";
|
||||
}
|
||||
{
|
||||
label = "Circle Back";
|
||||
command = "systemctl reboot";
|
||||
}
|
||||
{
|
||||
label = "Bet Down the Horses";
|
||||
command = "systemctl poweroff";
|
||||
}
|
||||
];
|
||||
};
|
||||
|
||||
"buttons#media" = {
|
||||
position = "left";
|
||||
actions = [
|
||||
{
|
||||
label = "Play/Pause";
|
||||
command = "playerctl play-pause";
|
||||
}
|
||||
{
|
||||
label = "Next";
|
||||
command = "playerctl next";
|
||||
}
|
||||
{
|
||||
label = "Previous";
|
||||
command = "playerctl previous";
|
||||
}
|
||||
];
|
||||
};
|
||||
};
|
||||
|
||||
notifications = {
|
||||
vexpand = true;
|
||||
};
|
||||
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
@@ -1,6 +1,11 @@
|
||||
{ pkgs, lib, ... }: {
|
||||
home.packages =
|
||||
lib.mkIf (!pkgs.stdenv.isDarwin) (with pkgs; [ rofi-power-menu rofi-calc ]);
|
||||
home.packages = lib.mkIf (!pkgs.stdenv.isDarwin) (
|
||||
with pkgs;
|
||||
[
|
||||
rofi-power-menu
|
||||
rofi-calc
|
||||
]
|
||||
);
|
||||
|
||||
programs.rofi = lib.mkIf (!pkgs.stdenv.isDarwin) {
|
||||
enable = true;
|
||||
|
||||
@@ -1,4 +1,10 @@
|
||||
{ pkgs, lib, isDarwin, ... }: {
|
||||
{
|
||||
pkgs,
|
||||
lib,
|
||||
isDarwin,
|
||||
...
|
||||
}:
|
||||
{
|
||||
programs.sketchybar = lib.mkIf isDarwin {
|
||||
enable = true;
|
||||
configType = "lua";
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
-- Save this in ~/.config/sketchybar/
|
||||
|
||||
-- SketchyBar Lua API
|
||||
sbar = require("sketchybar")
|
||||
local sbar = require("sketchybar")
|
||||
|
||||
-- Colors (Catppuccin Mocha theme)
|
||||
local colors = {
|
||||
@@ -52,8 +52,8 @@ sbar.default({
|
||||
background = {
|
||||
border_width = 2,
|
||||
corner_radius = 9,
|
||||
border_color = colors.accent,
|
||||
color = colors.bg,
|
||||
border_color = colors.pink,
|
||||
color = colors.base,
|
||||
padding_right = 12,
|
||||
},
|
||||
},
|
||||
@@ -67,14 +67,14 @@ sbar.bar({
|
||||
padding_left = 12,
|
||||
padding_right = 12,
|
||||
margin = 12,
|
||||
color = colors.bg,
|
||||
border_color = colors.accent,
|
||||
color = colors.base,
|
||||
border_color = colors.pink,
|
||||
border_width = 2,
|
||||
corner_radius = 60,
|
||||
})
|
||||
|
||||
-- Apple logo menu
|
||||
local apple_logo = sbar.add("item", "apple.logo", {
|
||||
sbar.add("item", "apple.logo", {
|
||||
icon = {
|
||||
string = " ",
|
||||
padding_left = 6,
|
||||
@@ -125,7 +125,7 @@ sbar.add("item", "apple.lock", {
|
||||
})
|
||||
|
||||
-- Spaces
|
||||
local space_icons = { " ", " ", " ", " ", " ", " ", "7", "8", "9", "10" }
|
||||
local space_icons = { " ", " ", " ", " ", " ", " ", "7", "8", "9", "10" }
|
||||
for i = 1, #space_icons do
|
||||
local space = sbar.add("space", "space." .. i, {
|
||||
space = i,
|
||||
@@ -133,7 +133,7 @@ for i = 1, #space_icons do
|
||||
string = space_icons[i],
|
||||
padding_left = 2,
|
||||
padding_right = 2,
|
||||
highlight_color = colors.green,
|
||||
highlight_color = colors.red,
|
||||
},
|
||||
label = { drawing = false },
|
||||
padding_right = 4,
|
||||
|
||||
@@ -150,11 +150,11 @@
|
||||
format = "{}";
|
||||
return-type = "json";
|
||||
exec = ''
|
||||
curl -s -X GET "https://api.openweathermap.org/data/2.5/weather?lat=52.281311&lon=10.527029&appid=$(cat $OPENWEATHER_API_KEY)&units=metric&lang=en" | jq -c '{text: "\(.name) \(.main.temp)C°"}'
|
||||
curl -sf --max-time 10 "https://api.openweathermap.org/data/2.5/weather?lat=52.281311&lon=10.527029&appid=$(cat ~/.config/sops-nix/secrets/OPENWEATHER_API_KEY)&units=metric&lang=en" | jq -c '{text: "\(.name) \(.main.temp)C°"}'
|
||||
'';
|
||||
interval = 120;
|
||||
on-click = ''
|
||||
data=$(curl -s -X GET "https://api.openweathermap.org/data/2.5/weather?lat=52.281311&lon=10.527029&appid=$(cat $OPENWEATHER_API_KEY)&units=metric&lang=en")
|
||||
data=$(curl -sf --max-time 10 "https://api.openweathermap.org/data/2.5/weather?lat=52.281311&lon=10.527029&appid=$(cat ~/.config/sops-nix/secrets/OPENWEATHER_API_KEY)&units=metric&lang=en")
|
||||
city=$(echo "$data" | jq -r '.name')
|
||||
temp=$(echo "$data" | jq -r '.main.temp')
|
||||
feels=$(echo "$data" | jq -r '.main.feels_like')
|
||||
|
||||
@@ -1,8 +1,17 @@
|
||||
{ pkgs, lib, compositor ? "hyprland", ... }: {
|
||||
programs.waybar = lib.mkIf (!pkgs.stdenv.isDarwin) ({
|
||||
enable = true;
|
||||
package = pkgs.waybar;
|
||||
} // (import ./dual.nix { inherit compositor; }));
|
||||
{
|
||||
pkgs,
|
||||
lib,
|
||||
compositor ? "hyprland",
|
||||
...
|
||||
}:
|
||||
{
|
||||
programs.waybar = lib.mkIf (!pkgs.stdenv.isDarwin) (
|
||||
{
|
||||
enable = true;
|
||||
package = pkgs.waybar;
|
||||
}
|
||||
// (import ./dual.nix { inherit compositor; })
|
||||
);
|
||||
|
||||
home.packages = lib.mkIf (!pkgs.stdenv.isDarwin) (with pkgs; [ cava ]);
|
||||
|
||||
|
||||
@@ -1,5 +0,0 @@
|
||||
_: {
|
||||
programs.floorp = {
|
||||
enable = true;
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,168 @@
|
||||
{ pkgs, ... }:
|
||||
let
|
||||
addons = pkgs.nur.repos.rycee.firefox-addons;
|
||||
readJson = path: builtins.readFile path;
|
||||
buildXpi =
|
||||
{
|
||||
name,
|
||||
addonId,
|
||||
version,
|
||||
url,
|
||||
sha256,
|
||||
}:
|
||||
pkgs.nur.repos.rycee.firefox-addons.buildFirefoxXpiAddon {
|
||||
pname = name;
|
||||
inherit
|
||||
addonId
|
||||
version
|
||||
url
|
||||
sha256
|
||||
;
|
||||
meta = { };
|
||||
};
|
||||
in
|
||||
{
|
||||
programs.floorp = {
|
||||
enable = true;
|
||||
|
||||
policies.ExtensionSettings = {
|
||||
"adguardadblocker@adguard.com" = {
|
||||
installation_mode = "force_installed";
|
||||
install_url = "https://addons.mozilla.org/firefox/downloads/file/4805625/adguard_adblocker-5.4.3.1.xpi";
|
||||
default_area = "navbar";
|
||||
};
|
||||
"{446900e4-71c2-419f-a6a7-df9c091e268b}" = {
|
||||
installation_mode = "force_installed";
|
||||
default_area = "navbar";
|
||||
}; # Bitwarden
|
||||
"{7a7a4a92-a2a0-41d1-9fd7-1e92480d612d}" = {
|
||||
installation_mode = "force_installed";
|
||||
default_area = "navbar";
|
||||
}; # Stylus
|
||||
"newtaboverride@agenedia.com" = {
|
||||
installation_mode = "force_installed";
|
||||
};
|
||||
"{3c078156-979c-498b-8990-85f7987dd929}" = {
|
||||
installation_mode = "force_installed";
|
||||
};
|
||||
"firefox@tampermonkey.net" = {
|
||||
installation_mode = "force_installed";
|
||||
};
|
||||
"{7aa7c68a-141f-45c9-a1c6-6e7382debbe1}" = {
|
||||
installation_mode = "force_installed";
|
||||
install_url = "https://addons.mozilla.org/firefox/downloads/file/4147586/catppuccin_mocha-1.0.xpi";
|
||||
};
|
||||
};
|
||||
|
||||
profiles.default = {
|
||||
isDefault = true;
|
||||
|
||||
extraConfig = ''
|
||||
user_pref("extensions.activeThemeID", "{7aa7c68a-141f-45c9-a1c6-6e7382debbe1}");
|
||||
'';
|
||||
|
||||
settings = {
|
||||
# Startup
|
||||
"browser.startup.homepage" = "https://www.cyperpunk.de";
|
||||
|
||||
# UI
|
||||
"browser.ctrlTab.sortByRecentlyUsed" = true;
|
||||
"browser.tabs.closeWindowWithLastTab" = false;
|
||||
"browser.toolbars.bookmarks.visibility" = "never";
|
||||
"browser.toolbars.bookmarks.showOtherBookmarks" = false;
|
||||
"browser.download.useDownloadDir" = false;
|
||||
"general.autoScroll" = true;
|
||||
"intl.locale.requested" = "en";
|
||||
"browser.search.region" = "DE";
|
||||
|
||||
# New tab
|
||||
"browser.newtabpage.activity-stream.feeds.topsites" = false;
|
||||
"browser.newtabpage.activity-stream.showSponsoredTopSites" = false;
|
||||
"browser.newtabpage.activity-stream.showSponsoredCheckboxes" = false;
|
||||
"browser.newtab.extensionControlled" = true;
|
||||
|
||||
# Privacy
|
||||
"signon.rememberSignons" = false;
|
||||
"privacy.clearOnShutdown_v2.formdata" = true;
|
||||
"dom.disable_open_during_load" = false;
|
||||
|
||||
# Devtools
|
||||
"devtools.cache.disabled" = true;
|
||||
|
||||
# Media
|
||||
"media.eme.enabled" = true;
|
||||
|
||||
# Font
|
||||
"font.name.serif.x-western" = "FiraMono Nerd Font";
|
||||
|
||||
# URL bar
|
||||
"browser.urlbar.shortcuts.actions" = false;
|
||||
"browser.urlbar.shortcuts.bookmarks" = false;
|
||||
"browser.urlbar.shortcuts.history" = false;
|
||||
"browser.urlbar.suggest.bookmark" = false;
|
||||
|
||||
# Extensions — skip manual enable prompt on fresh install
|
||||
"extensions.autoDisableScopes" = 0;
|
||||
|
||||
# Floorp specific
|
||||
"floorp.browser.tabs.openNewTabPosition" = -1;
|
||||
"floorp.commandPalette.enabled" = true;
|
||||
"floorp.mousegesture.enabled" = false;
|
||||
"floorp.panelSidebar.enabled" = true;
|
||||
"floorp.workspaces.enabled" = true;
|
||||
"floorp.zenmode.enabled" = false;
|
||||
"floorp.design.configs" = readJson ./design.json;
|
||||
"floorp.panelSidebar.config" = readJson ./panel-sidebar.json;
|
||||
"floorp.panelSidebar.data" = readJson ./panel-sidebar-data.json;
|
||||
"floorp.tabs.sleep.exclusion" = readJson ./tabs-sleep-exclusion.json;
|
||||
};
|
||||
|
||||
search = {
|
||||
force = true;
|
||||
default = "SearXNG";
|
||||
engines = {
|
||||
"SearXNG" = {
|
||||
urls = [ { template = "https://search.cyperpunk.de/search?q={searchTerms}"; } ];
|
||||
definedAliases = [ "@sx" ];
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
extensions = {
|
||||
force = true;
|
||||
packages = [
|
||||
addons.bitwarden
|
||||
addons.sidebery
|
||||
addons.tampermonkey
|
||||
addons.stylus
|
||||
addons.new-tab-override
|
||||
|
||||
(buildXpi {
|
||||
name = "adguard-adblocker";
|
||||
addonId = "adguardadblocker@adguard.com";
|
||||
version = "5.4.3.1";
|
||||
url = "https://addons.mozilla.org/firefox/downloads/file/4805625/adguard_adblocker-5.4.3.1.xpi";
|
||||
sha256 = "1rqp8qcc0p6qgqfgpshiqnll5mrl9jyfnks4zygzim436k0k781l";
|
||||
})
|
||||
|
||||
(buildXpi {
|
||||
name = "catppuccin-mocha";
|
||||
addonId = "{7aa7c68a-141f-45c9-a1c6-6e7382debbe1}";
|
||||
version = "1.0";
|
||||
url = "https://addons.mozilla.org/firefox/downloads/file/4147586/catppuccin_mocha-1.0.xpi";
|
||||
sha256 = "04lw5dirdv5636i52gfgyd5l0mkd74qjs2p23mimga3xv8hk1dzl";
|
||||
})
|
||||
];
|
||||
settings = {
|
||||
"{3c078156-979c-498b-8990-85f7987dd929}".settings = builtins.fromJSON (
|
||||
builtins.readFile ./sidebery.json
|
||||
);
|
||||
"newtaboverride@agenedia.com".settings = {
|
||||
type = "custom_url";
|
||||
url = "https://www.cyperpunk.de/";
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
{"globalConfigs":{"userInterface":"fluerial","faviconColor":true,"appliedUserJs":""},"tabbar":{"tabbarStyle":"horizontal","tabbarPosition":"optimise-to-vertical-tabbar","multiRowTabBar":{"maxRowEnabled":false,"maxRow":3}},"tab":{"tabScroll":{"enabled":false,"reverse":false,"wrap":false},"tabMinHeight":30,"tabMinWidth":76,"tabPinTitle":false,"tabDubleClickToClose":false,"tabOpenPosition":-1},"uiCustomization":{"navbar":{"position":"top","searchBarTop":false},"display":{"disableFullscreenNotification":false,"deleteBrowserBorder":false},"special":{"optimizeForTreeStyleTab":false,"hideForwardBackwardButton":false,"stgLikeWorkspaces":false},"multirowTab":{"newtabInsideEnabled":false},"bookmarkBar":{"focusExpand":false,"position":"bottom"},"qrCode":{"disableButton":false},"disableFloorpStart":true}}
|
||||
@@ -0,0 +1 @@
|
||||
{"data":[{"id":"default-panel-history","url":"floorp//history","width":0,"type":"static"},{"id":"default-panel-downloads","url":"floorp//downloads","width":0,"type":"static"},{"id":"default-panel-notes","url":"floorp//notes","width":0,"type":"static"},{"type":"web","id":"18849706-ce97-41ce-b6c0-007436e81dad","width":450,"url":"https://cinny.cyperpunk.de/home/","userContextId":0,"userAgent":false}]}
|
||||
@@ -0,0 +1 @@
|
||||
{"autoUnload":false,"position_start":true,"globalWidth":400,"displayed":true,"webExtensionRunningEnabled":false}
|
||||
@@ -0,0 +1 @@
|
||||
{"sidebarCSS":"#root.root {--nav-btn-width: 32px;}\n#root.root {--nav-btn-height: 32px;}\n#root.root {--nav-btn-margin: 4px;}\n#root.root {--nav-btn-len-margin: 0px;}\n#root.root {--nav-btn-border-radius: 5px;}\n#root.root {--toolbar-scrollbar-color: #cdd6f4;}\n#root.root {--general-margin: 4px;}\n#root.root {--general-border-radius: 5px;}","ver":"5.5.2","keybindings":{"_execute_sidebar_action":"Ctrl+E","activate":"Alt+Space","reset_selection":"Alt+R","next_panel":"Alt+Period","prev_panel":"Alt+Comma","new_tab_on_panel":"Ctrl+Space","new_tab_in_group":"Ctrl+Shift+Space","up":"Alt+Up","down":"Alt+Down","up_shift":"Alt+Shift+Up","down_shift":"Alt+Shift+Down"}}
|
||||
+24070
File diff suppressed because one or more lines are too long
@@ -0,0 +1 @@
|
||||
{"enabled":true,"patterns":["cyperpunk.de"]}
|
||||
@@ -1,7 +1,8 @@
|
||||
# TODO: Duplicate file
|
||||
{ pkgs, ... }:
|
||||
{
|
||||
fonts.packages = with pkgs; [
|
||||
fonts.fontconfig.enable = true;
|
||||
|
||||
home.packages = with pkgs; [
|
||||
nerd-fonts.fira-code
|
||||
nerd-fonts.fira-mono
|
||||
nerd-fonts.hack
|
||||
+37
-8
@@ -46,10 +46,14 @@
|
||||
{
|
||||
type = "button";
|
||||
val = "[+] New file";
|
||||
on_press.__raw =
|
||||
"function() vim.cmd[[ene]] vim.cmd[[startinsert]] end";
|
||||
on_press.__raw = "function() vim.cmd[[ene]] vim.cmd[[startinsert]] end";
|
||||
opts = {
|
||||
keymap = [ "n" "e" ":ene <BAR> startinsert <CR>" { } ];
|
||||
keymap = [
|
||||
"n"
|
||||
"e"
|
||||
":ene <BAR> startinsert <CR>"
|
||||
{ }
|
||||
];
|
||||
shortcut = "e";
|
||||
position = "center";
|
||||
cursor = 3;
|
||||
@@ -63,7 +67,12 @@
|
||||
val = "[?] Find file";
|
||||
on_press.__raw = "function() vim.cmd[[Telescope find_files]] end";
|
||||
opts = {
|
||||
keymap = [ "n" "f" ":Telescope find_files <CR>" { } ];
|
||||
keymap = [
|
||||
"n"
|
||||
"f"
|
||||
":Telescope find_files <CR>"
|
||||
{ }
|
||||
];
|
||||
shortcut = "f";
|
||||
position = "center";
|
||||
cursor = 3;
|
||||
@@ -77,7 +86,12 @@
|
||||
val = "[~] Recent files";
|
||||
on_press.__raw = "function() vim.cmd[[Telescope oldfiles]] end";
|
||||
opts = {
|
||||
keymap = [ "n" "r" ":Telescope oldfiles <CR>" { } ];
|
||||
keymap = [
|
||||
"n"
|
||||
"r"
|
||||
":Telescope oldfiles <CR>"
|
||||
{ }
|
||||
];
|
||||
shortcut = "r";
|
||||
position = "center";
|
||||
cursor = 3;
|
||||
@@ -91,7 +105,12 @@
|
||||
val = "[Y] Yazi";
|
||||
on_press.__raw = "function() require('yazi').yazi() end";
|
||||
opts = {
|
||||
keymap = [ "n" "y" ":Yazi<CR>" { } ];
|
||||
keymap = [
|
||||
"n"
|
||||
"y"
|
||||
":Yazi<CR>"
|
||||
{ }
|
||||
];
|
||||
shortcut = "y";
|
||||
position = "center";
|
||||
cursor = 3;
|
||||
@@ -105,7 +124,12 @@
|
||||
val = "[A] Open Prompt";
|
||||
#on_press.__raw = "function() require('yazi').yazi() end";
|
||||
opts = {
|
||||
keymap = [ "n" "a" ":AvanteChatNew<CR>" { } ];
|
||||
keymap = [
|
||||
"n"
|
||||
"a"
|
||||
":AvanteChatNew<CR>"
|
||||
{ }
|
||||
];
|
||||
shortcut = "a";
|
||||
position = "center";
|
||||
cursor = 3;
|
||||
@@ -119,7 +143,12 @@
|
||||
val = "[X] Quit";
|
||||
on_press.__raw = "function() vim.cmd[[qa]] end";
|
||||
opts = {
|
||||
keymap = [ "n" "q" ":qa<CR>" { } ];
|
||||
keymap = [
|
||||
"n"
|
||||
"q"
|
||||
":qa<CR>"
|
||||
{ }
|
||||
];
|
||||
shortcut = "q";
|
||||
position = "center";
|
||||
cursor = 3;
|
||||
|
||||
+30
-27
@@ -5,34 +5,45 @@
|
||||
plugins = {
|
||||
markdown-preview.enable = true;
|
||||
render-markdown.enable = true;
|
||||
#extraConfigLuaPre = ''
|
||||
# vim.env.GROQ_API_KEY = os.getenv("GROQ_API_KEY")
|
||||
#'';
|
||||
# TODO: Integrate CoPilot https://github.com/settings/copilot/features
|
||||
avante = {
|
||||
enable = true;
|
||||
autoLoad = true;
|
||||
settings = {
|
||||
provider = "groq";
|
||||
provider = "ollama";
|
||||
|
||||
providers.groq = {
|
||||
__inherited_from = "openai";
|
||||
api_key_name = "cmd:cat /home/phil/.config/sops-nix/secrets/GROQ_API_KEY";
|
||||
endpoint = "https://api.groq.com/openai/v1/";
|
||||
model = "qwen/qwen3-32b"; # "llama-3.3-70b-versatile";
|
||||
system_promt = "You are a helpful coding assistant. Always respond in plain markdown format without using tool calls or JSON structures.";
|
||||
disable_tools = true;
|
||||
extra_request_body = {
|
||||
temperature = 1;
|
||||
max_tokens = 2000;
|
||||
response_format = {
|
||||
type = "text";
|
||||
providers = {
|
||||
groq = {
|
||||
__inherited_from = "openai";
|
||||
api_key_name = "cmd:cat /home/phil/.config/sops-nix/secrets/GROQ_API_KEY";
|
||||
endpoint = "https://api.groq.com/openai/v1/";
|
||||
model = "qwen/qwen3-32b";
|
||||
system_promt = "You are a helpful coding assistant. Always respond in plain markdown format without using tool calls or JSON structures.";
|
||||
disable_tools = true;
|
||||
extra_request_body = {
|
||||
temperature = 1;
|
||||
max_tokens = 2000;
|
||||
response_format = {
|
||||
type = "text";
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
ollama = {
|
||||
endpoint = "http://100.109.179.25:11434"; # tailscale IP, no /v1 suffix
|
||||
model = "qwen2.5:3b"; # swap for "llama3.2:3b" or "deepseek-r1:1.5b"
|
||||
timeout = 60000; # local + small model can be slow on first load
|
||||
disable_tools = true; # these small models aren't reliable at tool calling
|
||||
is_env_set.__raw = ''require("avante.providers.ollama").check_endpoint_alive'';
|
||||
extra_request_body = {
|
||||
options = {
|
||||
temperature = 0.7;
|
||||
num_ctx = 8192;
|
||||
keep_alive = "5m";
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
# auto_suggestions_provider = "copilot";
|
||||
|
||||
render = {
|
||||
markdown = true;
|
||||
syntax = true;
|
||||
@@ -40,7 +51,6 @@
|
||||
code = true;
|
||||
link = true;
|
||||
};
|
||||
|
||||
behaviour = {
|
||||
enable_cursor_planning_mode = false;
|
||||
auto_suggestions = false;
|
||||
@@ -51,7 +61,6 @@
|
||||
use_selection_as_context = true;
|
||||
max_context_tokens = 2000;
|
||||
};
|
||||
|
||||
mappings = {
|
||||
ask = "<leader>aa";
|
||||
edit = "<leader>ae";
|
||||
@@ -84,11 +93,9 @@
|
||||
reverse_switch_windows = "<S-Tab>";
|
||||
};
|
||||
};
|
||||
|
||||
hints = {
|
||||
enabled = true;
|
||||
};
|
||||
|
||||
windows = {
|
||||
position = "right";
|
||||
wrap = true;
|
||||
@@ -98,22 +105,18 @@
|
||||
rounded = true;
|
||||
};
|
||||
};
|
||||
|
||||
highlights = {
|
||||
diff = {
|
||||
current = "DiffText";
|
||||
incoming = "DiffAdd";
|
||||
};
|
||||
};
|
||||
|
||||
diff = {
|
||||
autojump = true;
|
||||
list_opener = "copen";
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
extraPackages = with pkgs; [ curl ];
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
{ pkgs, ... }:
|
||||
{
|
||||
_: {
|
||||
# Catppuccin: Soothing pastel theme for Neovim
|
||||
# Provides consistent theming across plugins with transparency support.
|
||||
programs.nixvim = {
|
||||
@@ -20,6 +19,7 @@
|
||||
mini = {
|
||||
enabled = true;
|
||||
};
|
||||
lualine = true;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
@@ -1,4 +1,8 @@
|
||||
{ pkgs, inputs, ... }:
|
||||
{
|
||||
pkgs,
|
||||
inputs,
|
||||
...
|
||||
}:
|
||||
{
|
||||
imports = [
|
||||
inputs.nixvim.homeModules.nixvim
|
||||
@@ -14,8 +18,10 @@
|
||||
./alpha.nix
|
||||
./avante.nix
|
||||
#./openscad.nix
|
||||
./molten.nix
|
||||
#./molten.nix
|
||||
./which-key.nix
|
||||
./diffview.nix
|
||||
./live-server.nix
|
||||
];
|
||||
|
||||
home.packages = with pkgs; [
|
||||
@@ -27,6 +33,7 @@
|
||||
programs.nixvim = {
|
||||
enable = true;
|
||||
defaultEditor = true;
|
||||
enableMan = false;
|
||||
|
||||
# Leader key
|
||||
globals.mapleader = " ";
|
||||
|
||||
@@ -0,0 +1,33 @@
|
||||
_: {
|
||||
programs.nixvim = {
|
||||
plugins.diffview = {
|
||||
enable = true;
|
||||
settings.keymaps.view = [
|
||||
{
|
||||
mode = "n";
|
||||
key = "]x";
|
||||
action = "<cmd>DiffviewConflictNext<CR>";
|
||||
description = "Next conflict";
|
||||
}
|
||||
{
|
||||
mode = "n";
|
||||
key = "[x";
|
||||
action = "<cmd>DiffviewConflictPrev<CR>";
|
||||
description = "Previous conflict";
|
||||
}
|
||||
{
|
||||
mode = "n";
|
||||
key = "do";
|
||||
action = "<cmd>DiffviewFocusOurs<CR>";
|
||||
description = "Focus ours";
|
||||
}
|
||||
{
|
||||
mode = "n";
|
||||
key = "dt";
|
||||
action = "<cmd>DiffviewFocusTheirs<CR>";
|
||||
description = "Focus theirs";
|
||||
}
|
||||
];
|
||||
};
|
||||
};
|
||||
}
|
||||
@@ -1,4 +1,3 @@
|
||||
# TODO: Remove; nodePackages is unmaintained inside nixpkgs
|
||||
{ pkgs, ... }:
|
||||
{
|
||||
# Live Server: Auto-reload browser for web development
|
||||
@@ -13,6 +12,6 @@
|
||||
}
|
||||
];
|
||||
|
||||
extraPackages = with pkgs; [ nodePackages.browser-sync ];
|
||||
extraPackages = with pkgs; [ browser-sync ];
|
||||
};
|
||||
}
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
{ pkgs, ... }:
|
||||
{
|
||||
_: {
|
||||
# Lualine: Fast and customizable statusline for Neovim
|
||||
# Displays file info, git status, diagnostics, and mode at the bottom of the editor.
|
||||
programs.nixvim.plugins.lualine = {
|
||||
@@ -7,7 +6,6 @@
|
||||
|
||||
settings = {
|
||||
options = {
|
||||
theme = "catppuccin";
|
||||
component_separators = {
|
||||
left = "|";
|
||||
right = "|";
|
||||
|
||||
@@ -2,8 +2,8 @@
|
||||
programs.nixvim = lib.mkIf (!isDarwin) {
|
||||
plugins.molten = {
|
||||
enable = true;
|
||||
python3Dependencies = p:
|
||||
with p; [
|
||||
python3Dependencies =
|
||||
p: with p; [
|
||||
pynvim
|
||||
jupyter-client
|
||||
cairosvg
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
# cheatsheet, snippets, offline manual and fuzzy help
|
||||
programs.nixvim = {
|
||||
plugins.openscad = {
|
||||
enable = true;
|
||||
enable = false;
|
||||
autoLoad = true;
|
||||
settings = {
|
||||
fuzzy_finder = "fzf";
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
|
||||
settings = {
|
||||
highlight = {
|
||||
enable = true;
|
||||
enable = false;
|
||||
additional_vim_regex_highlighting = false;
|
||||
};
|
||||
};
|
||||
|
||||
+44
-3
@@ -1,4 +1,45 @@
|
||||
_: {
|
||||
# TODO: Add Automatic Vault pull and detection
|
||||
programs.obsidian.enable = true;
|
||||
{
|
||||
config,
|
||||
pkgs,
|
||||
lib,
|
||||
...
|
||||
}:
|
||||
let
|
||||
vaultRepo = "ssh://gitea@git.cyperpunk.de:12222/DerGrumpf/Notes.git";
|
||||
vaultPath = "${config.home.homeDirectory}/Notes";
|
||||
sshBinary = "${pkgs.openssh}/bin/ssh";
|
||||
gitBin = "${pkgs.git}/bin";
|
||||
gitLfsBin = "${pkgs.git-lfs}/bin";
|
||||
in
|
||||
{
|
||||
programs.obsidian = {
|
||||
enable = true;
|
||||
vaults.notes = {
|
||||
target = "Notes";
|
||||
settings = { };
|
||||
};
|
||||
};
|
||||
|
||||
home.packages = with pkgs; [
|
||||
git
|
||||
git-lfs
|
||||
openssh
|
||||
];
|
||||
|
||||
home.activation.obsidianVault = lib.hm.dag.entryAfter [ "writeBoundary" ] ''
|
||||
export PATH="${gitBin}:${gitLfsBin}:$PATH"
|
||||
export GIT_SSH_COMMAND="${sshBinary} -o StrictHostKeyChecking=accept-new"
|
||||
export GIT_LFS_SKIP_SMUDGE=1
|
||||
|
||||
if [ ! -d "${vaultPath}/.git" ]; then
|
||||
echo "Cloning Obsidian vault (LFS objects will be pulled separately)..."
|
||||
${gitBin}/git clone "${vaultRepo}" "${vaultPath}"
|
||||
${gitLfsBin}/git-lfs install --local "${vaultPath}"
|
||||
${gitBin}/git -C "${vaultPath}" lfs pull
|
||||
else
|
||||
echo "Pulling latest changes for Obsidian vault..."
|
||||
${gitBin}/git -C "${vaultPath}" pull
|
||||
${gitBin}/git -C "${vaultPath}" lfs pull
|
||||
fi
|
||||
'';
|
||||
}
|
||||
|
||||
+1
-2
@@ -1,4 +1,3 @@
|
||||
{ pkgs, ... }: {
|
||||
programs.onlyoffice =
|
||||
pkgs.lib.mkIf (!pkgs.stdenv.isDarwin) { enable = true; };
|
||||
programs.onlyoffice = pkgs.lib.mkIf (!pkgs.stdenv.isDarwin) { enable = true; };
|
||||
}
|
||||
|
||||
@@ -0,0 +1,35 @@
|
||||
_: {
|
||||
programs.opencode = {
|
||||
enable = true;
|
||||
|
||||
settings = {
|
||||
enabled_providers = [ "ollama" ];
|
||||
|
||||
model = "ollama/llama3.2:3b";
|
||||
|
||||
provider = {
|
||||
ollama = {
|
||||
npm = "@ai-sdk/openai-compatible";
|
||||
name = "Ollama (tailscale)";
|
||||
options = {
|
||||
baseURL = "http://100.109.179.25:11434/v1";
|
||||
};
|
||||
models = {
|
||||
"llama3.2:3b" = {
|
||||
name = "Llama 3.2 3B";
|
||||
};
|
||||
"qwen2.5:3b" = {
|
||||
name = "Qwen 2.5 3B";
|
||||
};
|
||||
"deepseek-r1:1.5b" = {
|
||||
name = "DeepSeek-R1 1.5B";
|
||||
};
|
||||
"gemma4:e2b" = {
|
||||
name = "Gemma 4 2B Edge";
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
+6
-3
@@ -18,7 +18,7 @@
|
||||
jq
|
||||
yq-go
|
||||
# GUI
|
||||
openscad
|
||||
# openscad
|
||||
fstl
|
||||
# PDF Tools
|
||||
pandoc
|
||||
@@ -33,8 +33,11 @@
|
||||
gnutar
|
||||
unrar
|
||||
sops
|
||||
age
|
||||
# Nix tools
|
||||
nix-index
|
||||
ncdu
|
||||
tty-solitaire
|
||||
]
|
||||
++ lib.optionals (!pkgs.stdenv.isDarwin) [
|
||||
# dev tools
|
||||
@@ -48,7 +51,6 @@
|
||||
which
|
||||
libnotify
|
||||
# encryption
|
||||
age
|
||||
ssh-to-age
|
||||
]
|
||||
++ lib.optionals (!pkgs.stdenv.isDarwin && !isServer) [
|
||||
@@ -64,7 +66,8 @@
|
||||
xonotic
|
||||
irssi
|
||||
blender
|
||||
cinny-desktop
|
||||
nixpkgs-review
|
||||
netradiant-custom
|
||||
]
|
||||
++ lib.optionals pkgs.stdenv.isDarwin [ graphite-cli ];
|
||||
};
|
||||
|
||||
+9
-7
@@ -1,17 +1,19 @@
|
||||
{ pkgs, ... }: {
|
||||
{ pkgs, ... }:
|
||||
{
|
||||
home.packages = with pkgs; [
|
||||
# Python 3.14 (newest stable)
|
||||
python314
|
||||
python314Packages.pip
|
||||
python314Packages.virtualenv
|
||||
|
||||
# Additional useful tools
|
||||
python314Packages.pipx # Install Python apps in isolated environments
|
||||
uv # Fast Python package installer (alternative to pip)
|
||||
(python314Packages.pipx.overridePythonAttrs (_: {
|
||||
doCheck = false;
|
||||
}))
|
||||
uv
|
||||
];
|
||||
|
||||
# Set up default Python version
|
||||
home.sessionVariables = { PYTHON = "${pkgs.python313}/bin/python3"; };
|
||||
home.sessionVariables = {
|
||||
PYTHON = "${pkgs.python313}/bin/python3";
|
||||
};
|
||||
|
||||
programs.fish.shellAliases = {
|
||||
venv = "python3 -m venv";
|
||||
|
||||
+234
-302
@@ -15,326 +15,258 @@
|
||||
fd # find alternative
|
||||
bat # cat alternative
|
||||
ripgrep # grep alternative
|
||||
doas # sudo alternative
|
||||
dnsutils
|
||||
|
||||
# LLM in the Terminal
|
||||
(pkgs.llm.withPlugins { llm-groq = true; })
|
||||
|
||||
# Fun stuff
|
||||
zoxide
|
||||
lolcat
|
||||
cmatrix
|
||||
];
|
||||
|
||||
programs.kitty = {
|
||||
enable = true;
|
||||
programs = {
|
||||
kitty = {
|
||||
enable = true;
|
||||
|
||||
font = {
|
||||
name = "Fira Code Nerd Font";
|
||||
size = 10;
|
||||
};
|
||||
font = {
|
||||
name = "Fira Code Nerd Font";
|
||||
size = 10;
|
||||
};
|
||||
|
||||
settings = {
|
||||
confirm_os_window_close = 0;
|
||||
dynamic_background_opacity = true; # ctrl+shift+a>m/l
|
||||
enable_audio_bell = false;
|
||||
mouse_hide_wait = 3.0;
|
||||
window_padding_width = 10;
|
||||
|
||||
background_opacity = 0.8;
|
||||
background_blur = 5;
|
||||
|
||||
tab_bar_min_tabs = 1;
|
||||
tab_bar_edge = "bottom";
|
||||
tab_bar_style = "custom"; # Should be changed to custom
|
||||
tab_title_template = "{fmt.fg.red}{bell_symbol}{activity_symbol}{fmt.fg.tab}{title}";
|
||||
|
||||
symbol_map =
|
||||
let
|
||||
mappings = [
|
||||
"U+23FB-U+23FE"
|
||||
"U+2B58"
|
||||
"U+E200-U+E2A9"
|
||||
"U+E0A0-U+E0A3"
|
||||
"U+E0B0-U+E0BF"
|
||||
"U+E0C0-U+E0C8"
|
||||
"U+E0CC-U+E0CF"
|
||||
"U+E0D0-U+E0D2"
|
||||
"U+E0D4"
|
||||
"U+E700-U+E7C5"
|
||||
"U+F000-U+F2E0"
|
||||
"U+2665"
|
||||
"U+26A1"
|
||||
"U+F400-U+F4A8"
|
||||
"U+F67C"
|
||||
"U+E000-U+E00A"
|
||||
"U+F300-U+F313"
|
||||
"U+E5FA-U+E62B"
|
||||
];
|
||||
in
|
||||
(builtins.concatStringsSep "," mappings) + " Symbols Nerd Font Mono";
|
||||
};
|
||||
};
|
||||
|
||||
# Doenst work
|
||||
programs.iamb = {
|
||||
enable = false;
|
||||
settings = {
|
||||
default_profile = "personal";
|
||||
settings = {
|
||||
notifications.enabled = true;
|
||||
image_preview.protocol = {
|
||||
type = "kitty";
|
||||
size = {
|
||||
height = 10;
|
||||
width = 66;
|
||||
};
|
||||
confirm_os_window_close = 0;
|
||||
dynamic_background_opacity = true; # ctrl+shift+a>m/l
|
||||
enable_audio_bell = false;
|
||||
mouse_hide_wait = 3.0;
|
||||
window_padding_width = 10;
|
||||
|
||||
background_opacity = 0.8;
|
||||
background_blur = 5;
|
||||
|
||||
tab_bar_min_tabs = 1;
|
||||
tab_bar_edge = "bottom";
|
||||
tab_bar_style = "custom"; # Should be changed to custom
|
||||
tab_title_template = "{fmt.fg.red}{bell_symbol}{activity_symbol}{fmt.fg.tab}{title}";
|
||||
|
||||
symbol_map =
|
||||
let
|
||||
mappings = [
|
||||
"U+23FB-U+23FE"
|
||||
"U+2B58"
|
||||
"U+E200-U+E2A9"
|
||||
"U+E0A0-U+E0A3"
|
||||
"U+E0B0-U+E0BF"
|
||||
"U+E0C0-U+E0C8"
|
||||
"U+E0CC-U+E0CF"
|
||||
"U+E0D0-U+E0D2"
|
||||
"U+E0D4"
|
||||
"U+E700-U+E7C5"
|
||||
"U+F000-U+F2E0"
|
||||
"U+2665"
|
||||
"U+26A1"
|
||||
"U+F400-U+F4A8"
|
||||
"U+F67C"
|
||||
"U+E000-U+E00A"
|
||||
"U+F300-U+F313"
|
||||
"U+E5FA-U+E62B"
|
||||
];
|
||||
in
|
||||
(builtins.concatStringsSep "," mappings) + " Symbols Nerd Font Mono";
|
||||
};
|
||||
};
|
||||
|
||||
cava = lib.mkIf (!isDarwin) { enable = true; };
|
||||
|
||||
yazi = {
|
||||
enable = true;
|
||||
enableBashIntegration = true;
|
||||
enableZshIntegration = true;
|
||||
enableFishIntegration = true;
|
||||
|
||||
settings = {
|
||||
ration = [
|
||||
1
|
||||
3
|
||||
4
|
||||
];
|
||||
};
|
||||
};
|
||||
|
||||
fzf = {
|
||||
enable = true;
|
||||
enableBashIntegration = true;
|
||||
enableZshIntegration = true;
|
||||
enableFishIntegration = true;
|
||||
defaultCommand = "fd --type f --strip-cwd-prefix --hidden --exclude .git";
|
||||
fileWidgetCommand = "fd --type f --strip-cwd-prefix --hidden --exclude .git";
|
||||
defaultOptions = [
|
||||
"--height 100%"
|
||||
"--border sharp"
|
||||
"--layout=reverse"
|
||||
"--inline-info"
|
||||
"--preview 'bat --color=always --style=numbers {}'"
|
||||
];
|
||||
};
|
||||
|
||||
nushell = {
|
||||
enable = true;
|
||||
shellAliases = {
|
||||
la = "ls -la";
|
||||
i = "kitty +kitten icat";
|
||||
grep = "rg";
|
||||
};
|
||||
extraConfig = ''
|
||||
$env.config = {
|
||||
show_banner: false
|
||||
}
|
||||
# Starship
|
||||
$env.STARSHIP_SHELL = "nu"
|
||||
mkdir ~/.cache/starship
|
||||
starship init nu | save -f ~/.cache/starship/init.nu
|
||||
# fzf picker for nvim
|
||||
def f [] { nvim (fzf) }
|
||||
'';
|
||||
extraEnv = ''
|
||||
starship init nu | save -f ~/.cache/starship/init.nu
|
||||
use ~/.cache/starship/init.nu
|
||||
'';
|
||||
};
|
||||
|
||||
fish = {
|
||||
enable = true;
|
||||
|
||||
shellAliases = {
|
||||
ls = "eza --icons=always";
|
||||
la = "eza -la --icons=always";
|
||||
f = "nvim $(fzf)";
|
||||
tree = "eza --icons=always -T";
|
||||
i = "kitty +kitten icat";
|
||||
bat = "bat --color=always --style=numbers";
|
||||
grep = "rg";
|
||||
cp = "rsync -ah --progress";
|
||||
nix-switch =
|
||||
if isDarwin then
|
||||
"sudo darwin-rebuild switch --flake ~/.config/nix#(hostname -s)"
|
||||
else
|
||||
"sudo nixos-rebuild switch --flake ~/.config/nix#(hostname -s)";
|
||||
|
||||
nix-check =
|
||||
if isDarwin then
|
||||
"nix eval ~/.config/nix#darwinConfigurations.(hostname -s).config.system.build.toplevel.outPath"
|
||||
else
|
||||
"nix flake check --no-build ~/.config/nix";
|
||||
};
|
||||
|
||||
interactiveShellInit = ''
|
||||
starship init fish | source
|
||||
fzf --fish | source
|
||||
zoxide init fish --cmd cd | source
|
||||
function fish_greeting
|
||||
echo " _ _ ";
|
||||
echo " | | | | ";
|
||||
echo " ___ _ _ _ __ ___ _ __ _ __ _ _ _ __ | | __ __| | ___ ";
|
||||
echo " / __| | | | '_ \\ / _ \\ '__| '_ \\| | | | '_ \\| |/ / / _\` |/ _ \\";
|
||||
echo "| (__| |_| | |_) | __/ | | |_) | |_| | | | | < | (_| | __/";
|
||||
echo " \\___|\\__, | .__/ \\___|_| | .__/ \\__,_|_| |_|_|\\_(_)__,_|\\___|";
|
||||
echo " __/ | | | | ";
|
||||
echo " |___/|_| |_| ";
|
||||
end
|
||||
'';
|
||||
};
|
||||
|
||||
starship = {
|
||||
enable = true;
|
||||
settings = {
|
||||
add_newline = true;
|
||||
command_timeout = 500;
|
||||
|
||||
format = ''
|
||||
$username$hostname $directory $git_branch$git_status
|
||||
$character '';
|
||||
right_format = "$cmd_duration";
|
||||
|
||||
username = {
|
||||
style_user = "bold #cba6f7";
|
||||
style_root = "bold #f38ba8";
|
||||
format = "[┌](bold #a6e3a1)[$user]($style)";
|
||||
show_always = true;
|
||||
};
|
||||
|
||||
hostname = {
|
||||
style = "bold #74c7ec";
|
||||
format = "[@](bold #fab387)[$hostname]($style)";
|
||||
ssh_only = false;
|
||||
};
|
||||
|
||||
directory = {
|
||||
style = "bold #a6e3a1";
|
||||
truncation_length = 0;
|
||||
truncation_symbol = "";
|
||||
format = "[⤇ ](bold #f38ba8)[《$path 》]($style)";
|
||||
};
|
||||
|
||||
git_branch = {
|
||||
format = "[⟦$branch⟧]($style)";
|
||||
style = "bold #f9e2af";
|
||||
};
|
||||
|
||||
# Git status module settings
|
||||
git_status = {
|
||||
format = "[[(*$conflicted$untracked$modified$staged$renamed$deleted)](red) ($ahead_behind$stashed)]($style)";
|
||||
style = "bold #a6e3a1";
|
||||
conflicted = "";
|
||||
untracked = "";
|
||||
modified = "";
|
||||
staged = "";
|
||||
renamed = "";
|
||||
deleted = "";
|
||||
};
|
||||
|
||||
# Command duration module
|
||||
cmd_duration = {
|
||||
format = "[$duration]($style)";
|
||||
style = "bold #cdd6f4";
|
||||
min_time = 5000; # Only show if command takes longer than 5 seconds
|
||||
};
|
||||
|
||||
# Character module (prompt symbol)
|
||||
character = {
|
||||
success_symbol = "[└──────⇴ ](bold #a6e3a1)";
|
||||
error_symbol = "[└──────⇴ ](bold #f38ba8)";
|
||||
};
|
||||
|
||||
nix_shell = {
|
||||
format = "[$symbol$state( ($name))]($style)";
|
||||
symbol = "U+02744";
|
||||
style = "bold #89dceb";
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
programs.newsboat = {
|
||||
enable = true;
|
||||
autoReload = true;
|
||||
browser = if isDarwin then "open" else "xdg-open";
|
||||
urls = [
|
||||
{
|
||||
url = "https://www.tagesschau.de/xml/rss2";
|
||||
tags = [
|
||||
"news"
|
||||
"de"
|
||||
];
|
||||
}
|
||||
{
|
||||
url = "https://www.spiegel.de/schlagzeilen/index.rss";
|
||||
tags = [
|
||||
"news"
|
||||
"de"
|
||||
];
|
||||
}
|
||||
{
|
||||
url = "https://www.focus.de/rss";
|
||||
tags = [
|
||||
"news"
|
||||
"de"
|
||||
];
|
||||
}
|
||||
{
|
||||
url = "https://feeds.feedburner.com/blogspot/rkEL";
|
||||
tags = [ "blog" ];
|
||||
}
|
||||
];
|
||||
};
|
||||
home = {
|
||||
file = {
|
||||
".config/fastfetch/config.jsonc".source = ./fastfetch.jsonc;
|
||||
".config/tabiew/theme.toml".source = ./tabiew.toml;
|
||||
".config/kitty/tab_bar.py".source = ./tab_bar.py;
|
||||
".hushlogin" = lib.mkIf isDarwin { text = ""; }; # Suppress Login
|
||||
|
||||
programs.cava = lib.mkIf (!isDarwin) { enable = true; };
|
||||
|
||||
programs.yazi = {
|
||||
enable = true;
|
||||
enableBashIntegration = true;
|
||||
enableZshIntegration = true;
|
||||
enableFishIntegration = true;
|
||||
|
||||
settings = {
|
||||
ration = [
|
||||
1
|
||||
3
|
||||
4
|
||||
];
|
||||
};
|
||||
};
|
||||
|
||||
programs.fzf = {
|
||||
enable = true;
|
||||
enableBashIntegration = true;
|
||||
enableZshIntegration = true;
|
||||
enableFishIntegration = true;
|
||||
defaultCommand = "fd --type f --strip-cwd-prefix --hidden --exclude .git";
|
||||
fileWidgetCommand = "fd --type f --strip-cwd-prefix --hidden --exclude .git";
|
||||
defaultOptions = [
|
||||
"--height 100%"
|
||||
"--border sharp"
|
||||
"--layout=reverse"
|
||||
"--inline-info"
|
||||
"--preview 'bat --color=always --style=numbers {}'"
|
||||
];
|
||||
};
|
||||
|
||||
# TODO: Install OpenCode
|
||||
programs.nushell = {
|
||||
enable = true;
|
||||
|
||||
shellAliases = {
|
||||
# ls = "eza --icons=always";
|
||||
la = "ls -la";
|
||||
#tree = "eza --icons=always -T";
|
||||
i = "kitty +kitten icat";
|
||||
# cat = "bat --color=always --style=numbers";
|
||||
grep = "rg";
|
||||
};
|
||||
|
||||
extraConfig = ''
|
||||
$env.config = {
|
||||
show_banner: false
|
||||
}
|
||||
|
||||
# Starship
|
||||
$env.STARSHIP_SHELL = "nu"
|
||||
mkdir ~/.cache/starship
|
||||
starship init nu | save -f ~/.cache/starship/init.nu
|
||||
|
||||
# fzf picker for nvim
|
||||
def f [] { nvim (fzf) }
|
||||
|
||||
# llm | glow
|
||||
def l [...args] { llm prompt -m groq/llama-3.3-70b-versatile -t std ...$args | glow }
|
||||
|
||||
# Fastfetch on shell start
|
||||
fastfetch
|
||||
'';
|
||||
|
||||
extraEnv = ''
|
||||
starship init nu | save -f ~/.cache/starship/init.nu
|
||||
use ~/.cache/starship/init.nu
|
||||
'';
|
||||
};
|
||||
|
||||
programs.fish = {
|
||||
enable = true;
|
||||
|
||||
shellAliases = {
|
||||
ls = "eza --icons=always";
|
||||
la = "eza -la --icons=always";
|
||||
f = "nvim $(fzf)";
|
||||
tree = "eza --icons=always -T";
|
||||
i = "kitty +kitten icat";
|
||||
bat = "bat --color=always --style=numbers";
|
||||
grep = "rg";
|
||||
cp = "rsync -ah --progress";
|
||||
nix-switch =
|
||||
if isDarwin then
|
||||
"sudo darwin-rebuild switch --flake ~/.config/nix#(hostname -s)"
|
||||
else
|
||||
"sudo nixos-rebuild switch --flake ~/.config/nix#(hostname -s)";
|
||||
|
||||
nix-check =
|
||||
if isDarwin then
|
||||
"nix eval ~/.config/nix#darwinConfigurations.(hostname -s).config.system.build.toplevel.outPath"
|
||||
else
|
||||
"nix flake check --no-build ~/.config/nix";
|
||||
};
|
||||
|
||||
interactiveShellInit = ''
|
||||
starship init fish | source
|
||||
fzf --fish | source
|
||||
zoxide init fish --cmd cd | source
|
||||
function fish_greeting
|
||||
fastfetch
|
||||
end
|
||||
'';
|
||||
|
||||
functions.l = {
|
||||
body = ''
|
||||
if test -f "$GROQ_API_KEY"
|
||||
set -x GROQ_API_KEY (cat $GROQ_API_KEY)
|
||||
end
|
||||
llm prompt -m groq/llama-3.3-70b-versatile -t std $argv | glow
|
||||
# Link LLM std template
|
||||
".config/io.datasette.llm/templates/std.yaml".text = ''
|
||||
system: |
|
||||
You are a concise technical assistant running on an Intel Mac (x86_64-darwin)
|
||||
with nix-darwin and home-manager.
|
||||
|
||||
Rules:
|
||||
- Always respond in valid markdown
|
||||
- Be concise and direct, no unnecessary explanation
|
||||
- Prefer code blocks for commands and code
|
||||
- You have access to these tools in the shell: nvim, fish, git,
|
||||
eza, bat, ripgrep, fzf, yazi, glow, llm, zoxide, fastfetch,
|
||||
nix, darwin-rebuild, brew
|
||||
- When suggesting nix config changes, use the nix language
|
||||
- nix-switch rebuilds the system config
|
||||
- nix-check validates the flake without building
|
||||
'';
|
||||
};
|
||||
};
|
||||
|
||||
# Link LLM std template
|
||||
home.file.".config/io.datasette.llm/templates/std.yaml".text = ''
|
||||
system: |
|
||||
You are a concise technical assistant running on an Intel Mac (x86_64-darwin)
|
||||
with nix-darwin and home-manager.
|
||||
|
||||
Rules:
|
||||
- Always respond in valid markdown
|
||||
- Be concise and direct, no unnecessary explanation
|
||||
- Prefer code blocks for commands and code
|
||||
- You have access to these tools in the shell: nvim, fish, git,
|
||||
eza, bat, ripgrep, fzf, yazi, glow, llm, zoxide, fastfetch,
|
||||
nix, darwin-rebuild, brew
|
||||
- When suggesting nix config changes, use the nix language
|
||||
- nix-switch rebuilds the system config
|
||||
- nix-check validates the flake without building
|
||||
'';
|
||||
|
||||
programs.starship = {
|
||||
enable = true;
|
||||
settings = {
|
||||
add_newline = true;
|
||||
command_timeout = 500;
|
||||
|
||||
format = ''
|
||||
$username$hostname $directory $git_branch$git_status
|
||||
$character '';
|
||||
right_format = "$cmd_duration";
|
||||
|
||||
username = {
|
||||
style_user = "bold #cba6f7";
|
||||
style_root = "bold #f38ba8";
|
||||
format = "[┌](bold #a6e3a1)[$user]($style)";
|
||||
show_always = true;
|
||||
};
|
||||
|
||||
hostname = {
|
||||
style = "bold #74c7ec";
|
||||
format = "[@](bold #fab387)[$hostname]($style)";
|
||||
ssh_only = false;
|
||||
};
|
||||
|
||||
directory = {
|
||||
style = "bold #a6e3a1";
|
||||
truncation_length = 0;
|
||||
truncation_symbol = "";
|
||||
format = "[⤇ ](bold #f38ba8)[《$path 》]($style)";
|
||||
};
|
||||
|
||||
git_branch = {
|
||||
format = "[⟦$branch⟧]($style)";
|
||||
style = "bold #f9e2af";
|
||||
};
|
||||
|
||||
# Git status module settings
|
||||
git_status = {
|
||||
format = "[[(*$conflicted$untracked$modified$staged$renamed$deleted)](red) ($ahead_behind$stashed)]($style)";
|
||||
style = "bold #a6e3a1";
|
||||
conflicted = "";
|
||||
untracked = "";
|
||||
modified = "";
|
||||
staged = "";
|
||||
renamed = "";
|
||||
deleted = "";
|
||||
};
|
||||
|
||||
# Command duration module
|
||||
cmd_duration = {
|
||||
format = "[$duration]($style)";
|
||||
style = "bold #cdd6f4";
|
||||
min_time = 5000; # Only show if command takes longer than 5 seconds
|
||||
};
|
||||
|
||||
# Character module (prompt symbol)
|
||||
character = {
|
||||
success_symbol = "[└──────⇴ ](bold #a6e3a1)";
|
||||
error_symbol = "[└──────⇴ ](bold #f38ba8)";
|
||||
};
|
||||
|
||||
nix_shell = {
|
||||
format = "[$symbol$state( ($name))]($style)";
|
||||
symbol = "U+02744";
|
||||
style = "bold #89dceb";
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
home.file = {
|
||||
".config/fastfetch/config.jsonc".source = ./fastfetch.jsonc;
|
||||
".config/tabiew/theme.toml".source = ./tabiew.toml;
|
||||
".config/kitty/tab_bar.py".source = ./tab_bar.py;
|
||||
".hushlogin" = lib.mkIf isDarwin { text = ""; }; # Suppress Login
|
||||
};
|
||||
}
|
||||
|
||||
+22
-6
@@ -3,19 +3,35 @@
|
||||
programs.ssh = {
|
||||
enable = true;
|
||||
enableDefaultConfig = false;
|
||||
matchBlocks = {
|
||||
settings = {
|
||||
"*" = {
|
||||
addKeysToAgent = "yes";
|
||||
AddKeysToAgent = "yes";
|
||||
};
|
||||
|
||||
"*.cyperpunk.de" = {
|
||||
identityFile =
|
||||
IdentityFile =
|
||||
if isDarwin then "/Users/${primaryUser}/.ssh/ssh" else "/home/${primaryUser}/.ssh/ssh";
|
||||
user = primaryUser;
|
||||
User = primaryUser;
|
||||
};
|
||||
|
||||
"github.com" = {
|
||||
identityFile =
|
||||
IdentityFile =
|
||||
if isDarwin then "/Users/${primaryUser}/.ssh/github" else "/home/${primaryUser}/.ssh/github";
|
||||
user = "git";
|
||||
User = "git";
|
||||
};
|
||||
|
||||
"git.rz.tu-bs.de" = {
|
||||
IdentityFile =
|
||||
if isDarwin then "/Users/${primaryUser}/.ssh/github" else "/home/${primaryUser}/.ssh/github";
|
||||
User = "git";
|
||||
};
|
||||
|
||||
"git.cyperpunk.de" = {
|
||||
HostName = "git.cyperpunk.de";
|
||||
Port = 12222;
|
||||
User = "gitea";
|
||||
IdentityFile =
|
||||
if isDarwin then "/Users/${primaryUser}/.ssh/ssh" else "/home/${primaryUser}/.ssh/ssh";
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
@@ -11,8 +11,11 @@
|
||||
../../nixos/roles/gitea.nix
|
||||
../../nixos/roles/vaultwarden.nix
|
||||
../../nixos/roles/frontpage
|
||||
../../nixos/roles/paperless-ngx.nix
|
||||
#../../nixos/roles/paperless-ngx.nix
|
||||
../../nixos/roles/octoprint.nix
|
||||
../../nixos/roles/matrix/postgres-backup.nix
|
||||
../../nixos/roles/kanidm.nix
|
||||
../../nixos/roles/ollama.nix
|
||||
];
|
||||
|
||||
networking = {
|
||||
@@ -42,6 +45,5 @@
|
||||
};
|
||||
efi.canTouchEfiVariables = true;
|
||||
};
|
||||
|
||||
system.stateVersion = "26.05";
|
||||
}
|
||||
|
||||
@@ -38,7 +38,6 @@
|
||||
];
|
||||
};
|
||||
|
||||
# TODO: Add External Devices as by-label with no necessity for boot
|
||||
"/storage/internal" = {
|
||||
device = "/dev/disk/by-label/STORAGE";
|
||||
fsType = "btrfs";
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
{ ... }:
|
||||
{
|
||||
imports = [ ./hardware-configuration.nix ];
|
||||
|
||||
@@ -32,5 +33,21 @@
|
||||
efi.canTouchEfiVariables = true;
|
||||
};
|
||||
|
||||
system.stateVersion = "26.05";
|
||||
services = {
|
||||
desktopManager.plasma6.enable = false;
|
||||
displayManager.sddm = {
|
||||
enable = false;
|
||||
wayland.enable = true;
|
||||
};
|
||||
};
|
||||
|
||||
environment.pathsToLink = [
|
||||
"/share/applications"
|
||||
"/share/xdg-desktop-portal"
|
||||
];
|
||||
|
||||
system.stateVersion = "26.11";
|
||||
|
||||
virtualisation.docker.enable = true;
|
||||
users.users.phil.extraGroups = [ "docker" ];
|
||||
}
|
||||
|
||||
@@ -1,11 +1,6 @@
|
||||
{
|
||||
imports = [
|
||||
./hardware-configuration.nix
|
||||
../../nixos/roles/monitoring.nix
|
||||
../../nixos/roles/matrix.nix
|
||||
../../nixos/roles/postgresql.nix
|
||||
../../nixos/roles/wyl.nix
|
||||
../../nixos/roles/adguard.nix
|
||||
];
|
||||
|
||||
networking = {
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
{
|
||||
imports = [
|
||||
./hardware-configuration.nix
|
||||
../../nixos/roles/gitea.nix
|
||||
../../nixos/roles/filebrowser.nix
|
||||
];
|
||||
|
||||
networking = {
|
||||
|
||||
@@ -17,8 +17,20 @@
|
||||
prefixLength = 23;
|
||||
}
|
||||
];
|
||||
ipv6.addresses = [
|
||||
{
|
||||
address = "2a00:6800:3:1094::1";
|
||||
prefixLength = 64;
|
||||
}
|
||||
];
|
||||
};
|
||||
defaultGateway = "178.254.8.1";
|
||||
|
||||
defaultGateway6 = {
|
||||
address = "2a00:6800:3::1";
|
||||
interface = "ens3";
|
||||
};
|
||||
|
||||
nameservers = [
|
||||
"178.254.16.151"
|
||||
"178.254.16.141"
|
||||
@@ -34,6 +46,11 @@
|
||||
"cyperpunk.de"
|
||||
"matrix.cyperpunk.de"
|
||||
];
|
||||
|
||||
"2a00:6800:3:1094::1" = [
|
||||
"cyperpunk.de"
|
||||
"matrix.cyperpunk.de"
|
||||
];
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
@@ -5,38 +5,41 @@
|
||||
];
|
||||
|
||||
boot = {
|
||||
loader.grub = {
|
||||
enable = true;
|
||||
device = "/dev/vda";
|
||||
};
|
||||
loader.grub = {
|
||||
enable = true;
|
||||
device = "/dev/vda";
|
||||
};
|
||||
|
||||
initrd = {
|
||||
availableKernelModules = [
|
||||
"ata_piix"
|
||||
"virtio_pci"
|
||||
"virtio_scsi"
|
||||
"virtio_blk"
|
||||
"xhci_pci"
|
||||
"sr_mod"
|
||||
];
|
||||
kernelModules = [ ];
|
||||
};
|
||||
kernelModules = [ ];
|
||||
extraModulePackages = [ ];
|
||||
};
|
||||
initrd = {
|
||||
availableKernelModules = [
|
||||
"ata_piix"
|
||||
"virtio_pci"
|
||||
"virtio_scsi"
|
||||
"virtio_blk"
|
||||
"xhci_pci"
|
||||
"sr_mod"
|
||||
];
|
||||
kernelModules = [ ];
|
||||
};
|
||||
kernelModules = [ ];
|
||||
extraModulePackages = [ ];
|
||||
};
|
||||
|
||||
fileSystems = {
|
||||
"/" = {
|
||||
device = "/dev/disk/by-label/NIXROOT";
|
||||
fsType = "ext4";
|
||||
};
|
||||
"/" = {
|
||||
device = "/dev/disk/by-label/NIXROOT";
|
||||
fsType = "ext4";
|
||||
};
|
||||
|
||||
"/boot" = {
|
||||
device = "/dev/disk/by-label/NIXBOOT";
|
||||
fsType = "vfat";
|
||||
options = [ "fmask=0022" "dmask=0022" ];
|
||||
"/boot" = {
|
||||
device = "/dev/disk/by-label/NIXBOOT";
|
||||
fsType = "vfat";
|
||||
options = [
|
||||
"fmask=0022"
|
||||
"dmask=0022"
|
||||
];
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
swapDevices = [ ];
|
||||
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
|
||||
catppuccin = {
|
||||
enable = true;
|
||||
autoEnable = false;
|
||||
accent = "sky";
|
||||
flavor = "mocha";
|
||||
cache.enable = true;
|
||||
@@ -11,9 +12,5 @@
|
||||
enable = true;
|
||||
accent = "sapphire";
|
||||
};
|
||||
fcitx5.enable = false;
|
||||
forgejo.enable = false;
|
||||
gitea.enable = false;
|
||||
sddm.enable = false;
|
||||
};
|
||||
}
|
||||
|
||||
+31
-55
@@ -2,13 +2,13 @@
|
||||
pkgs,
|
||||
inputs,
|
||||
lib,
|
||||
config,
|
||||
primaryUser,
|
||||
isServer,
|
||||
...
|
||||
}:
|
||||
{
|
||||
imports = [
|
||||
./fonts.nix
|
||||
./sops.nix
|
||||
./locale.nix
|
||||
./tailscale.nix
|
||||
@@ -18,13 +18,16 @@
|
||||
./regreet.nix
|
||||
./plymouth.nix
|
||||
./audio.nix
|
||||
./webcam.nix
|
||||
./virt.nix
|
||||
./catppuccin.nix
|
||||
];
|
||||
|
||||
nix = {
|
||||
settings = {
|
||||
trusted-users = [
|
||||
"root"
|
||||
primaryUser
|
||||
];
|
||||
experimental-features = [
|
||||
"nix-command"
|
||||
"flakes"
|
||||
@@ -37,12 +40,15 @@
|
||||
"https://cache.nixos.org"
|
||||
"https://hyprland.cachix.org"
|
||||
"https://nix-community.cachix.org"
|
||||
"https://cyper-cache.cachix.org"
|
||||
];
|
||||
trusted-public-keys = [
|
||||
"cache.nixos.org-1:6NCHdD59X431o0gWypbMrAURkbJ16ZPMQFGspcDShjY="
|
||||
"hyprland.cachix.org-1:a7pgxzMz7+chwVL3/pzj6jIBMioiJM7ypFP8PwtkuGc="
|
||||
"nix-community.cachix.org-1:mB9FSh9qf2dCimDSUo8Zy7bkq5CX+/rkCWyvRCYg3Fs="
|
||||
"cyper-cache.cachix.org-1:pOpeWFEjGHg9XvqRg+DQpYnGRQNp+z+QEF8Ev2mbSoM="
|
||||
];
|
||||
auto-optimise-store = true;
|
||||
};
|
||||
gc = {
|
||||
automatic = true;
|
||||
@@ -51,33 +57,9 @@
|
||||
};
|
||||
};
|
||||
|
||||
# TODO: Get rid of this
|
||||
virtualisation = lib.mkIf isServer {
|
||||
vmVariant = {
|
||||
virtualisation = {
|
||||
forwardPorts = [
|
||||
{
|
||||
from = "host";
|
||||
host.port = 2222;
|
||||
guest.port = 22;
|
||||
}
|
||||
];
|
||||
qemu.networkingOptions = [
|
||||
"-device virtio-net-pci,netdev=net0"
|
||||
"-netdev user,id=net0,net=10.0.2.0/24,dhcpstart=10.0.2.15"
|
||||
];
|
||||
};
|
||||
|
||||
systemd.network.networks."10-ethernet" = lib.mkForce {
|
||||
matchConfig.Name = "ens*";
|
||||
networkConfig = {
|
||||
Address = "10.0.2.15/24";
|
||||
Gateway = "10.0.2.2";
|
||||
DNS = "8.8.8.8";
|
||||
DHCP = "no";
|
||||
};
|
||||
};
|
||||
};
|
||||
nixpkgs.config = {
|
||||
allowUnfree = true;
|
||||
permittedInsecurePackages = [ "olm-3.2.16" ];
|
||||
};
|
||||
|
||||
documentation = {
|
||||
@@ -87,24 +69,24 @@
|
||||
info.enable = false;
|
||||
};
|
||||
|
||||
nixpkgs.config.allowUnfree = true;
|
||||
|
||||
programs = {
|
||||
fish.enable = true;
|
||||
}
|
||||
// lib.optionalAttrs (!isServer) {
|
||||
dconf.enable = true;
|
||||
hyprland = {
|
||||
enable = true;
|
||||
package = inputs.hyprland.packages.${pkgs.stdenv.hostPlatform.system}.hyprland;
|
||||
};
|
||||
steam.enable = true;
|
||||
appimage = {
|
||||
enable = true;
|
||||
binfmt = true;
|
||||
};
|
||||
hyprland = {
|
||||
enable = true;
|
||||
package = inputs.hyprland.packages.${pkgs.stdenv.hostPlatform.system}.hyprland;
|
||||
};
|
||||
};
|
||||
|
||||
environment.systemPackages = with pkgs; [ git ];
|
||||
|
||||
security = lib.mkIf (!isServer) {
|
||||
pam.services.swaylock = { };
|
||||
polkit.enable = true;
|
||||
@@ -117,32 +99,25 @@
|
||||
port = 9002;
|
||||
};
|
||||
|
||||
alloy = {
|
||||
enable = true;
|
||||
extraFlags = [ "--stability.level=public-preview" ];
|
||||
configPath = pkgs.writeText "config.alloy" ''
|
||||
loki.write "default" {
|
||||
endpoint {
|
||||
url = "http://192.168.2.2:3100/loki/api/v1/push"
|
||||
}
|
||||
}
|
||||
|
||||
loki.source.journal "journal" {
|
||||
forward_to = [loki.write.default.receiver]
|
||||
labels = {
|
||||
job = "systemd-journal",
|
||||
host = sys.env("HOSTNAME"),
|
||||
}
|
||||
}
|
||||
'';
|
||||
};
|
||||
|
||||
gnome = lib.mkIf (!isServer) {
|
||||
tinysparql.enable = true;
|
||||
localsearch.enable = true;
|
||||
};
|
||||
};
|
||||
|
||||
sops.secrets.cachix_auth_token = { };
|
||||
|
||||
systemd.services.cachix-push = {
|
||||
description = "Push new store paths to Cachix";
|
||||
after = [ "multi-user.target" ];
|
||||
wantedBy = [ "multi-user.target" ];
|
||||
serviceConfig = {
|
||||
Type = "oneshot";
|
||||
RemainAfterExit = true;
|
||||
ExecStart = "${pkgs.bash}/bin/bash -c 'CACHIX_AUTH_TOKEN=$(cat ${config.sops.secrets.cachix_auth_token.path}) ${pkgs.nix}/bin/nix path-info --recursive /run/current-system | CACHIX_AUTH_TOKEN=$(cat ${config.sops.secrets.cachix_auth_token.path}) ${pkgs.cachix}/bin/cachix push cyper-cache'";
|
||||
};
|
||||
};
|
||||
|
||||
networking.firewall.allowedTCPPorts = [
|
||||
9002
|
||||
3100
|
||||
@@ -159,6 +134,7 @@
|
||||
"video"
|
||||
"audio"
|
||||
"libvirtd"
|
||||
"input"
|
||||
];
|
||||
};
|
||||
}
|
||||
|
||||
@@ -1,9 +0,0 @@
|
||||
# TODO: Duplicate file
|
||||
{ pkgs, ... }:
|
||||
{
|
||||
fonts.packages = with pkgs; [
|
||||
nerd-fonts.fira-code
|
||||
nerd-fonts.fira-mono
|
||||
nerd-fonts.hack
|
||||
];
|
||||
}
|
||||
+2
-2
@@ -1,4 +1,4 @@
|
||||
{ ... }:
|
||||
{ lib, ... }:
|
||||
{
|
||||
boot = {
|
||||
plymouth = {
|
||||
@@ -15,6 +15,6 @@
|
||||
"udev.log_priority=3"
|
||||
"rd.systemd.show_status=auto"
|
||||
];
|
||||
loader.timeout = 0;
|
||||
loader.timeout = lib.mkDefault 0;
|
||||
};
|
||||
}
|
||||
|
||||
+16
-1
@@ -1,5 +1,6 @@
|
||||
{
|
||||
lib,
|
||||
pkgs,
|
||||
...
|
||||
}:
|
||||
{
|
||||
@@ -13,7 +14,7 @@
|
||||
};
|
||||
|
||||
programs.regreet = {
|
||||
enable = true;
|
||||
enable = false;
|
||||
|
||||
cageArgs = [
|
||||
"-s"
|
||||
@@ -63,4 +64,18 @@
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
services.greetd = {
|
||||
enable = true;
|
||||
settings = {
|
||||
default_session = {
|
||||
command = "${pkgs.tuigreet}/bin/tuigreet --cmd start-hyprland";
|
||||
user = "greeter";
|
||||
};
|
||||
initial_session = {
|
||||
command = "Hyprland";
|
||||
user = "phil";
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
@@ -5,19 +5,18 @@
|
||||
|
||||
let
|
||||
primaryInterface = config.systemd.network.networks."10-ethernet".matchConfig.Name;
|
||||
adguardPort = 3000;
|
||||
adguardPort = 3010;
|
||||
in
|
||||
{
|
||||
services = {
|
||||
resolved.enable = false;
|
||||
adguardhome = {
|
||||
enable = true;
|
||||
mutableSettings = true;
|
||||
mutableSettings = false;
|
||||
allowDHCP = true;
|
||||
port = adguardPort;
|
||||
|
||||
settings = {
|
||||
http.address = "0.0.0.0:${toString adguardPort}";
|
||||
|
||||
users = [
|
||||
{
|
||||
name = "DerGrumpf";
|
||||
@@ -50,7 +49,7 @@ in
|
||||
};
|
||||
|
||||
dhcp = {
|
||||
enabled = true;
|
||||
enabled = false;
|
||||
interface_name = primaryInterface;
|
||||
local_domain_name = "lan";
|
||||
dhcpv4 = {
|
||||
|
||||
+191
-146
@@ -2,6 +2,7 @@
|
||||
pkgs,
|
||||
lib,
|
||||
config,
|
||||
primaryUser,
|
||||
...
|
||||
}:
|
||||
|
||||
@@ -13,7 +14,7 @@ let
|
||||
stripRoot = false;
|
||||
};
|
||||
|
||||
domain = "git.cyperpunk.de"; # swap to git.cyperpunk.de for prod
|
||||
domain = "git.cyperpunk.de";
|
||||
httpPort = 9000;
|
||||
sshPort = 12222;
|
||||
in
|
||||
@@ -36,165 +37,209 @@ in
|
||||
owner = "gitea";
|
||||
group = "gitea";
|
||||
};
|
||||
};
|
||||
|
||||
services.postgresql = {
|
||||
enable = true;
|
||||
package = pkgs.postgresql_14;
|
||||
ensureDatabases = [ "gitea" ];
|
||||
ensureUsers = [
|
||||
{
|
||||
name = "gitea";
|
||||
ensureDBOwnership = true;
|
||||
}
|
||||
];
|
||||
authentication = lib.mkOverride 10 ''
|
||||
local all all trust
|
||||
host all all 127.0.0.1/32 md5
|
||||
host all all ::1/128 md5
|
||||
'';
|
||||
};
|
||||
|
||||
systemd.services.gitea-db-password = {
|
||||
description = "Set gitea postgres user password";
|
||||
requires = [ "postgresql.service" ];
|
||||
after = [ "postgresql.service" ];
|
||||
before = [ "gitea.service" ];
|
||||
wantedBy = [ "gitea.service" ];
|
||||
serviceConfig = {
|
||||
Type = "oneshot";
|
||||
User = "postgres";
|
||||
RemainAfterExit = true;
|
||||
"gitea/runnerToken" = {
|
||||
mode = "0444";
|
||||
};
|
||||
script = ''
|
||||
pass=$(cat ${config.sops.secrets."gitea/dbPassword".path})
|
||||
${pkgs.postgresql_14}/bin/psql -c \
|
||||
"ALTER USER gitea WITH PASSWORD '$pass';"
|
||||
"kanidm_gitea_secret" = {
|
||||
owner = "gitea";
|
||||
group = "gitea";
|
||||
mode = "0444";
|
||||
};
|
||||
};
|
||||
|
||||
systemd.services = {
|
||||
gitea-db-password = {
|
||||
description = "Set gitea postgres user password";
|
||||
requires = [ "postgresql.service" ];
|
||||
after = [ "postgresql.service" ];
|
||||
before = [ "gitea.service" ];
|
||||
wantedBy = [ "gitea.service" ];
|
||||
serviceConfig = {
|
||||
Type = "oneshot";
|
||||
User = "postgres";
|
||||
RemainAfterExit = true;
|
||||
};
|
||||
script = ''
|
||||
pass=$(cat ${config.sops.secrets."gitea/dbPassword".path})
|
||||
${pkgs.postgresql_14}/bin/psql -c \
|
||||
"ALTER USER gitea WITH PASSWORD '$pass';"
|
||||
'';
|
||||
};
|
||||
|
||||
gitea.preStart = lib.mkAfter ''
|
||||
themeDir="${config.services.gitea.stateDir}/custom/public/assets/css"
|
||||
mkdir -p "$themeDir"
|
||||
for f in ${giteaTheme}/*.css; do
|
||||
name=$(basename "$f")
|
||||
ln -sf "$f" "$themeDir/$name"
|
||||
done
|
||||
'';
|
||||
};
|
||||
|
||||
services.gitea = {
|
||||
enable = true;
|
||||
package = pkgs.gitea;
|
||||
user = "gitea";
|
||||
group = "gitea";
|
||||
services = {
|
||||
postgresql = {
|
||||
enable = true;
|
||||
package = pkgs.postgresql_14;
|
||||
ensureDatabases = [ "gitea" ];
|
||||
ensureUsers = [
|
||||
{
|
||||
name = "gitea";
|
||||
ensureDBOwnership = true;
|
||||
}
|
||||
];
|
||||
authentication = lib.mkOverride 10 ''
|
||||
local all all trust
|
||||
host all all 127.0.0.1/32 md5
|
||||
host all all ::1/128 md5
|
||||
'';
|
||||
};
|
||||
|
||||
database = {
|
||||
type = "postgres";
|
||||
host = "127.0.0.1";
|
||||
port = 5432;
|
||||
name = "gitea";
|
||||
gitea = {
|
||||
enable = true;
|
||||
package = pkgs.gitea;
|
||||
user = "gitea";
|
||||
passwordFile = config.sops.secrets."gitea/dbPassword".path;
|
||||
group = "gitea";
|
||||
|
||||
lfs = {
|
||||
enable = true;
|
||||
contentDir = "/storage/fast/lfs";
|
||||
};
|
||||
|
||||
database = {
|
||||
type = "postgres";
|
||||
host = "127.0.0.1";
|
||||
port = 5432;
|
||||
name = "gitea";
|
||||
user = "gitea";
|
||||
passwordFile = config.sops.secrets."gitea/dbPassword".path;
|
||||
};
|
||||
|
||||
settings = {
|
||||
server = {
|
||||
DOMAIN = domain;
|
||||
HTTP_ADDR = "0.0.0.0";
|
||||
HTTP_PORT = httpPort;
|
||||
SSH_PORT = sshPort;
|
||||
SSH_LISTEN_PORT = sshPort;
|
||||
ROOT_URL = "https://${domain}/";
|
||||
DISABLE_SSH = false;
|
||||
START_SSH_SERVER = true;
|
||||
LFS_START_SERVER = true;
|
||||
};
|
||||
|
||||
metrics = {
|
||||
ENABLED = true;
|
||||
ENABLED_ISSUE_BY_LABEL = true;
|
||||
ENABLED_ISSUE_BY_REPOSITORY = true;
|
||||
};
|
||||
|
||||
ui = {
|
||||
DEFAULT_THEME = "catppuccin-mocha-green";
|
||||
THEMES = lib.concatStringsSep "," [
|
||||
# built-in
|
||||
"gitea"
|
||||
"arc-green"
|
||||
# latte
|
||||
"catppuccin-latte-blue"
|
||||
"catppuccin-latte-flamingo"
|
||||
"catppuccin-latte-green"
|
||||
"catppuccin-latte-lavender"
|
||||
"catppuccin-latte-maroon"
|
||||
"catppuccin-latte-mauve"
|
||||
"catppuccin-latte-peach"
|
||||
"catppuccin-latte-pink"
|
||||
"catppuccin-latte-red"
|
||||
"catppuccin-latte-rosewater"
|
||||
"catppuccin-latte-sapphire"
|
||||
"catppuccin-latte-sky"
|
||||
"catppuccin-latte-teal"
|
||||
"catppuccin-latte-yellow"
|
||||
# frappe
|
||||
"catppuccin-frappe-blue"
|
||||
"catppuccin-frappe-flamingo"
|
||||
"catppuccin-frappe-green"
|
||||
"catppuccin-frappe-lavender"
|
||||
"catppuccin-frappe-maroon"
|
||||
"catppuccin-frappe-mauve"
|
||||
"catppuccin-frappe-peach"
|
||||
"catppuccin-frappe-pink"
|
||||
"catppuccin-frappe-red"
|
||||
"catppuccin-frappe-rosewater"
|
||||
"catppuccin-frappe-sapphire"
|
||||
"catppuccin-frappe-sky"
|
||||
"catppuccin-frappe-teal"
|
||||
"catppuccin-frappe-yellow"
|
||||
# macchiato
|
||||
"catppuccin-macchiato-blue"
|
||||
"catppuccin-macchiato-flamingo"
|
||||
"catppuccin-macchiato-green"
|
||||
"catppuccin-macchiato-lavender"
|
||||
"catppuccin-macchiato-maroon"
|
||||
"catppuccin-macchiato-mauve"
|
||||
"catppuccin-macchiato-peach"
|
||||
"catppuccin-macchiato-pink"
|
||||
"catppuccin-macchiato-red"
|
||||
"catppuccin-macchiato-rosewater"
|
||||
"catppuccin-macchiato-sapphire"
|
||||
"catppuccin-macchiato-sky"
|
||||
"catppuccin-macchiato-teal"
|
||||
"catppuccin-macchiato-yellow"
|
||||
# mocha
|
||||
"catppuccin-mocha-blue"
|
||||
"catppuccin-mocha-flamingo"
|
||||
"catppuccin-mocha-green"
|
||||
"catppuccin-mocha-lavender"
|
||||
"catppuccin-mocha-maroon"
|
||||
"catppuccin-mocha-mauve"
|
||||
"catppuccin-mocha-peach"
|
||||
"catppuccin-mocha-pink"
|
||||
"catppuccin-mocha-red"
|
||||
"catppuccin-mocha-rosewater"
|
||||
"catppuccin-mocha-sapphire"
|
||||
"catppuccin-mocha-sky"
|
||||
"catppuccin-mocha-teal"
|
||||
"catppuccin-mocha-yellow"
|
||||
];
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
settings = {
|
||||
server = {
|
||||
DOMAIN = domain;
|
||||
HTTP_ADDR = "0.0.0.0";
|
||||
HTTP_PORT = httpPort;
|
||||
SSH_PORT = sshPort;
|
||||
SSH_LISTEN_PORT = sshPort;
|
||||
ROOT_URL = "https://${domain}/";
|
||||
DISABLE_SSH = false;
|
||||
START_SSH_SERVER = true;
|
||||
};
|
||||
gitea-actions-runner.instances."cyper_nix" = {
|
||||
enable = true;
|
||||
url = "https://git.cyperpunk.de";
|
||||
tokenFile = config.sops.secrets."gitea/runnerToken".path;
|
||||
name = "cyper-controller";
|
||||
labels = [ "nix:host" ];
|
||||
|
||||
metrics = {
|
||||
ENABLED = true;
|
||||
ENABLED_ISSUE_BY_LABEL = true;
|
||||
ENABLED_ISSUE_BY_REPOSITORY = true;
|
||||
};
|
||||
|
||||
ui = {
|
||||
DEFAULT_THEME = "catppuccin-mocha-green";
|
||||
THEMES = lib.concatStringsSep "," [
|
||||
# built-in
|
||||
"gitea"
|
||||
"arc-green"
|
||||
# latte
|
||||
"catppuccin-latte-blue"
|
||||
"catppuccin-latte-flamingo"
|
||||
"catppuccin-latte-green"
|
||||
"catppuccin-latte-lavender"
|
||||
"catppuccin-latte-maroon"
|
||||
"catppuccin-latte-mauve"
|
||||
"catppuccin-latte-peach"
|
||||
"catppuccin-latte-pink"
|
||||
"catppuccin-latte-red"
|
||||
"catppuccin-latte-rosewater"
|
||||
"catppuccin-latte-sapphire"
|
||||
"catppuccin-latte-sky"
|
||||
"catppuccin-latte-teal"
|
||||
"catppuccin-latte-yellow"
|
||||
# frappe
|
||||
"catppuccin-frappe-blue"
|
||||
"catppuccin-frappe-flamingo"
|
||||
"catppuccin-frappe-green"
|
||||
"catppuccin-frappe-lavender"
|
||||
"catppuccin-frappe-maroon"
|
||||
"catppuccin-frappe-mauve"
|
||||
"catppuccin-frappe-peach"
|
||||
"catppuccin-frappe-pink"
|
||||
"catppuccin-frappe-red"
|
||||
"catppuccin-frappe-rosewater"
|
||||
"catppuccin-frappe-sapphire"
|
||||
"catppuccin-frappe-sky"
|
||||
"catppuccin-frappe-teal"
|
||||
"catppuccin-frappe-yellow"
|
||||
# macchiato
|
||||
"catppuccin-macchiato-blue"
|
||||
"catppuccin-macchiato-flamingo"
|
||||
"catppuccin-macchiato-green"
|
||||
"catppuccin-macchiato-lavender"
|
||||
"catppuccin-macchiato-maroon"
|
||||
"catppuccin-macchiato-mauve"
|
||||
"catppuccin-macchiato-peach"
|
||||
"catppuccin-macchiato-pink"
|
||||
"catppuccin-macchiato-red"
|
||||
"catppuccin-macchiato-rosewater"
|
||||
"catppuccin-macchiato-sapphire"
|
||||
"catppuccin-macchiato-sky"
|
||||
"catppuccin-macchiato-teal"
|
||||
"catppuccin-macchiato-yellow"
|
||||
# mocha
|
||||
"catppuccin-mocha-blue"
|
||||
"catppuccin-mocha-flamingo"
|
||||
"catppuccin-mocha-green"
|
||||
"catppuccin-mocha-lavender"
|
||||
"catppuccin-mocha-maroon"
|
||||
"catppuccin-mocha-mauve"
|
||||
"catppuccin-mocha-peach"
|
||||
"catppuccin-mocha-pink"
|
||||
"catppuccin-mocha-red"
|
||||
"catppuccin-mocha-rosewater"
|
||||
"catppuccin-mocha-sapphire"
|
||||
"catppuccin-mocha-sky"
|
||||
"catppuccin-mocha-teal"
|
||||
"catppuccin-mocha-yellow"
|
||||
];
|
||||
};
|
||||
hostPackages = with pkgs; [
|
||||
bash
|
||||
coreutils
|
||||
curl
|
||||
gawk
|
||||
gitMinimal
|
||||
gnused
|
||||
nodejs
|
||||
wget
|
||||
nix
|
||||
];
|
||||
};
|
||||
};
|
||||
|
||||
# symlink catppuccin css files into gitea's custom dir on every service start
|
||||
systemd.services.gitea.preStart = lib.mkAfter ''
|
||||
themeDir="${config.services.gitea.stateDir}/custom/public/assets/css"
|
||||
mkdir -p "$themeDir"
|
||||
for f in ${giteaTheme}/*.css; do
|
||||
name=$(basename "$f")
|
||||
ln -sf "$f" "$themeDir/$name"
|
||||
done
|
||||
'';
|
||||
users = {
|
||||
users = {
|
||||
gitea = {
|
||||
isSystemUser = true;
|
||||
group = "gitea";
|
||||
home = "/var/lib/gitea";
|
||||
createHome = true;
|
||||
};
|
||||
|
||||
users.users.gitea = {
|
||||
isSystemUser = true;
|
||||
group = "gitea";
|
||||
home = "/var/lib/gitea";
|
||||
createHome = true;
|
||||
postgres.extraGroups = [ "gitea" ];
|
||||
};
|
||||
groups = {
|
||||
gitea = { };
|
||||
};
|
||||
};
|
||||
users.groups.gitea = { };
|
||||
users.users.postgres.extraGroups = [ "gitea" ];
|
||||
|
||||
networking.firewall.allowedTCPPorts = [
|
||||
httpPort
|
||||
|
||||
@@ -0,0 +1,177 @@
|
||||
{
|
||||
config,
|
||||
lib,
|
||||
pkgs,
|
||||
...
|
||||
}:
|
||||
let
|
||||
cfg = config.services.gs1200-exporter;
|
||||
|
||||
instanceOpts =
|
||||
{ name, ... }:
|
||||
{
|
||||
options = {
|
||||
address = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
description = "IP address or hostname of the GS1200 switch.";
|
||||
example = "192.168.1.3";
|
||||
};
|
||||
|
||||
port = lib.mkOption {
|
||||
type = lib.types.port;
|
||||
default = 9934;
|
||||
description = "Port on which to expose Prometheus metrics.";
|
||||
};
|
||||
|
||||
password = lib.mkOption {
|
||||
type = lib.types.nullOr lib.types.str;
|
||||
default = null;
|
||||
description = ''
|
||||
Password to log in to the GS1200 web interface.
|
||||
Use passwordFile instead to avoid storing the password in the Nix store.
|
||||
'';
|
||||
};
|
||||
|
||||
passwordFile = lib.mkOption {
|
||||
type = lib.types.nullOr lib.types.path;
|
||||
default = null;
|
||||
description = ''
|
||||
Path to a file containing the password to log in to the GS1200 web interface.
|
||||
This is the recommended option as it avoids storing the password in the Nix store.
|
||||
Compatible with sops-nix and agenix.
|
||||
'';
|
||||
example = "/run/secrets/gs1200-password";
|
||||
};
|
||||
|
||||
debug = lib.mkOption {
|
||||
type = lib.types.bool;
|
||||
default = false;
|
||||
description = "Enable debug logging. Logs are accessible via journalctl -u gs1200-exporter-<name>.";
|
||||
};
|
||||
|
||||
verbose = lib.mkOption {
|
||||
type = lib.types.bool;
|
||||
default = false;
|
||||
description = "Enable verbose logging. Logs are accessible via journalctl -u gs1200-exporter-<name>.";
|
||||
};
|
||||
|
||||
json = lib.mkOption {
|
||||
type = lib.types.bool;
|
||||
default = false;
|
||||
description = "Output logs in JSON format. Logs are accessible via journalctl -u gs1200-exporter-<name>.";
|
||||
};
|
||||
|
||||
user = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = "gs1200-exporter-${name}";
|
||||
description = "User under which the service runs.";
|
||||
};
|
||||
|
||||
group = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = "gs1200-exporter-${name}";
|
||||
description = "Group under which the service runs.";
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
mkService = name: icfg: {
|
||||
"gs1200-exporter-${name}" = {
|
||||
description = "Prometheus exporter for Zyxel GS1200 switch '${name}'";
|
||||
wantedBy = [ "multi-user.target" ];
|
||||
after = [ "network.target" ];
|
||||
|
||||
serviceConfig = {
|
||||
User = icfg.user;
|
||||
Group = icfg.group;
|
||||
Restart = "always";
|
||||
RestartSec = "10s";
|
||||
|
||||
# Hardening
|
||||
NoNewPrivileges = true;
|
||||
PrivateTmp = true;
|
||||
ProtectSystem = "strict";
|
||||
ProtectHome = true;
|
||||
CapabilityBoundingSet = "";
|
||||
};
|
||||
|
||||
script =
|
||||
let
|
||||
args = lib.concatStringsSep " " (
|
||||
[
|
||||
"--address ${icfg.address}"
|
||||
"--port ${toString icfg.port}"
|
||||
]
|
||||
++ lib.optional icfg.debug "--debug"
|
||||
++ lib.optional icfg.verbose "--verbose"
|
||||
++ lib.optional icfg.json "--json"
|
||||
);
|
||||
in
|
||||
if icfg.passwordFile != null then
|
||||
''
|
||||
export GS1200_PASSWORD=$(cat ${icfg.passwordFile})
|
||||
exec ${lib.getExe pkgs.gs1200-exporter} ${args}
|
||||
''
|
||||
else
|
||||
''
|
||||
export GS1200_PASSWORD=${lib.escapeShellArg icfg.password}
|
||||
exec ${lib.getExe pkgs.gs1200-exporter} ${args}
|
||||
'';
|
||||
};
|
||||
};
|
||||
|
||||
in
|
||||
{
|
||||
options.services.gs1200-exporter = {
|
||||
instances = lib.mkOption {
|
||||
type = lib.types.attrsOf (lib.types.submodule instanceOpts);
|
||||
default = { };
|
||||
description = ''
|
||||
Each attribute defines a separate gs1200-exporter instance for one switch.
|
||||
Use this to monitor multiple GS1200 switches on the same host.
|
||||
'';
|
||||
example = lib.literalExpression ''
|
||||
{
|
||||
switch-1 = {
|
||||
address = "192.168.1.3";
|
||||
port = 9934;
|
||||
passwordFile = "/run/secrets/gs1200-password";
|
||||
};
|
||||
switch-2 = {
|
||||
address = "192.168.1.4";
|
||||
port = 9935;
|
||||
passwordFile = "/run/secrets/gs1200-password";
|
||||
};
|
||||
}
|
||||
'';
|
||||
};
|
||||
};
|
||||
|
||||
config = lib.mkIf (cfg.instances != { }) {
|
||||
assertions = lib.flatten (
|
||||
lib.mapAttrsToList (name: icfg: [
|
||||
{
|
||||
assertion = icfg.address != "";
|
||||
message = "services.gs1200-exporter.instances.${name}: address must be set.";
|
||||
}
|
||||
{
|
||||
assertion = (icfg.password == null) != (icfg.passwordFile == null);
|
||||
message = "services.gs1200-exporter.instances.${name}: exactly one of password or passwordFile must be set.";
|
||||
}
|
||||
]) cfg.instances
|
||||
);
|
||||
|
||||
users.users = lib.mapAttrs' (
|
||||
name: icfg:
|
||||
lib.nameValuePair icfg.user {
|
||||
isSystemUser = true;
|
||||
inherit (icfg) group;
|
||||
description = "gs1200-exporter '${name}' service user";
|
||||
}
|
||||
) cfg.instances;
|
||||
|
||||
users.groups = lib.mapAttrs' (_name: icfg: lib.nameValuePair icfg.group { }) cfg.instances;
|
||||
|
||||
systemd.services = lib.mkMerge (lib.mapAttrsToList mkService cfg.instances);
|
||||
};
|
||||
}
|
||||
@@ -1,117 +0,0 @@
|
||||
{
|
||||
pkgs,
|
||||
...
|
||||
}:
|
||||
|
||||
let
|
||||
domain = "jitsi.cyperpunk.de";
|
||||
in
|
||||
{
|
||||
nixpkgs.config.permittedInsecurePackages = [
|
||||
"jitsi-meet-1.0.8792"
|
||||
];
|
||||
|
||||
services.jitsi-meet = {
|
||||
enable = true;
|
||||
hostName = domain;
|
||||
|
||||
config = {
|
||||
enableWelcomePage = true;
|
||||
prejoinPageEnabled = true;
|
||||
enableInsecureRoomNameWarning = true;
|
||||
disableAudioLevels = false;
|
||||
enableLayerSuspension = true;
|
||||
p2p.enabled = true;
|
||||
analytics.disabled = true;
|
||||
};
|
||||
|
||||
interfaceConfig = {
|
||||
SHOW_JITSI_WATERMARK = false;
|
||||
SHOW_WATERMARK_FOR_GUESTS = false;
|
||||
DEFAULT_REMOTE_DISPLAY_NAME = "Meeting @ Virtual";
|
||||
TOOLBAR_BUTTONS = [
|
||||
"microphone"
|
||||
"camera"
|
||||
"desktop"
|
||||
"fullscreen"
|
||||
"fodeviceselection"
|
||||
"hangup"
|
||||
"profile"
|
||||
"chat"
|
||||
"recording"
|
||||
"livestreaming"
|
||||
"etherpad"
|
||||
"sharedvideo"
|
||||
"settings"
|
||||
"raisehand"
|
||||
"videoquality"
|
||||
"filmstrip"
|
||||
"invite"
|
||||
"feedback"
|
||||
"stats"
|
||||
"shortcuts"
|
||||
"tileview"
|
||||
"select-background"
|
||||
"mute-everyone"
|
||||
"security"
|
||||
];
|
||||
};
|
||||
|
||||
# Enable Jibri for recording/livestreaming support
|
||||
jibri = {
|
||||
enable = true;
|
||||
};
|
||||
|
||||
# Enable Jigasi for SIP/telephony support (optional, comment out if not needed)
|
||||
# jigasi.enable = true;
|
||||
|
||||
nginx.enable = true;
|
||||
prosody.enable = true;
|
||||
};
|
||||
|
||||
# Jitsi Videobridge — handles the actual media routing
|
||||
services.jitsi-videobridge = {
|
||||
enable = true;
|
||||
openFirewall = true;
|
||||
|
||||
config = {
|
||||
videobridge = {
|
||||
ice.udp.port = 10000;
|
||||
apis.rest.enabled = true;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
networking.firewall = {
|
||||
allowedTCPPorts = [
|
||||
5222 # XMPP client (Prosody)
|
||||
5269 # XMPP federation (Prosody)
|
||||
];
|
||||
allowedUDPPorts = [
|
||||
10000 # Jitsi Videobridge RTP media
|
||||
];
|
||||
allowedUDPPortRanges = [
|
||||
{
|
||||
from = 49152;
|
||||
to = 65535;
|
||||
} # WebRTC ephemeral ports
|
||||
];
|
||||
};
|
||||
|
||||
# Prosody needs this for XMPP
|
||||
networking.extraHosts = ''
|
||||
127.0.0.1 ${domain}
|
||||
127.0.0.1 auth.${domain}
|
||||
127.0.0.1 focus.${domain}
|
||||
127.0.0.1 jitsi-videobridge.${domain}
|
||||
'';
|
||||
|
||||
# Jibri requires Chromium for recording
|
||||
environment.systemPackages = with pkgs; [
|
||||
chromium
|
||||
ffmpeg
|
||||
];
|
||||
|
||||
# ALSA loopback device — required by Jibri for audio capture during recording
|
||||
boot.kernelModules = [ "snd-aloop" ];
|
||||
}
|
||||
@@ -0,0 +1,64 @@
|
||||
{ pkgs, ... }:
|
||||
let
|
||||
domain = "auth.cyperpunk.de";
|
||||
port = 8444;
|
||||
certDir = "/var/lib/kanidm/tls";
|
||||
in
|
||||
{
|
||||
systemd.services.kanidm-selfsigned-cert = {
|
||||
description = "Generate self-signed TLS certificate for Kanidm";
|
||||
wantedBy = [ "kanidm.service" ];
|
||||
before = [ "kanidm.service" ];
|
||||
serviceConfig = {
|
||||
Type = "oneshot";
|
||||
RemainAfterExit = true;
|
||||
};
|
||||
script = ''
|
||||
if [ ! -f ${certDir}/cert.pem ]; then
|
||||
mkdir -p ${certDir}
|
||||
${pkgs.openssl}/bin/openssl req -x509 \
|
||||
-newkey rsa:4096 \
|
||||
-keyout ${certDir}/key.pem \
|
||||
-out ${certDir}/cert.pem \
|
||||
-days 3650 \
|
||||
-nodes \
|
||||
-subj "/CN=${domain}"
|
||||
chown -R kanidm:kanidm ${certDir}
|
||||
chmod 750 ${certDir}
|
||||
chmod 640 ${certDir}/cert.pem ${certDir}/key.pem
|
||||
fi
|
||||
'';
|
||||
};
|
||||
|
||||
services.kanidm = {
|
||||
package = pkgs.kanidm_1_10;
|
||||
|
||||
server = {
|
||||
enable = true;
|
||||
settings = {
|
||||
inherit domain;
|
||||
origin = "https://${domain}";
|
||||
|
||||
tls_chain = "${certDir}/cert.pem";
|
||||
tls_key = "${certDir}/key.pem";
|
||||
|
||||
bindaddress = "0.0.0.0:${toString port}";
|
||||
|
||||
log_level = "info";
|
||||
|
||||
online_backup = {
|
||||
versions = 7;
|
||||
path = "/var/lib/kanidm/backups";
|
||||
schedule = "00 22 * * *";
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
client = {
|
||||
enable = true;
|
||||
settings.uri = "https://${domain}";
|
||||
};
|
||||
};
|
||||
|
||||
networking.firewall.allowedTCPPorts = [ port ];
|
||||
}
|
||||
@@ -0,0 +1,121 @@
|
||||
async function submitRegistration() {
|
||||
const usernameInput = document.getElementById("reg-username");
|
||||
const emailInput = document.getElementById("reg-email");
|
||||
const btn = document.getElementById("reg-btn");
|
||||
const status = document.getElementById("reg-status");
|
||||
|
||||
const username = usernameInput.value.trim();
|
||||
const email = emailInput.value.trim();
|
||||
|
||||
// Validierung
|
||||
status.className = "reg-status";
|
||||
status.style.display = "none";
|
||||
|
||||
if (!username || !email) {
|
||||
status.className = "reg-status error";
|
||||
status.textContent = "⚠️ Bitte Benutzernamen und E-Mail-Adresse eingeben.";
|
||||
return;
|
||||
}
|
||||
if (!/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email)) {
|
||||
status.className = "reg-status error";
|
||||
status.textContent = "⚠️ Bitte eine gültige E-Mail-Adresse eingeben.";
|
||||
return;
|
||||
}
|
||||
|
||||
btn.disabled = true;
|
||||
btn.textContent = "Wird übertragen...";
|
||||
|
||||
try {
|
||||
const res = await fetch("register.php", {
|
||||
method: "POST",
|
||||
headers: { "Content-Type": "application/json" },
|
||||
body: JSON.stringify({
|
||||
username,
|
||||
email,
|
||||
website: document.getElementById("reg-website").value,
|
||||
}),
|
||||
});
|
||||
|
||||
const data = await res.json().catch(() => ({}));
|
||||
|
||||
if (res.ok && data.success) {
|
||||
status.className = "reg-status success";
|
||||
status.innerHTML =
|
||||
"✅ <strong>Anfrage erfolgreich gesendet!</strong><br>" +
|
||||
"Die Administration wurde benachrichtigt. Du erhältst deine Login-Daten in Kürze an die angegebene E-Mail-Adresse.";
|
||||
usernameInput.value = "";
|
||||
emailInput.value = "";
|
||||
} else {
|
||||
throw new Error(
|
||||
data.error ||
|
||||
(res.status === 429
|
||||
? "Zu viele Anfragen. Bitte warte einige Minuten."
|
||||
: `HTTP ${res.status}`),
|
||||
);
|
||||
}
|
||||
} catch (e) {
|
||||
status.className = "reg-status error";
|
||||
status.textContent = `❌ Übertragung fehlgeschlagen: ${e.message}`;
|
||||
} finally {
|
||||
btn.disabled = false;
|
||||
btn.textContent = "Zugang anfordern";
|
||||
}
|
||||
}
|
||||
|
||||
// Enter-Taste in Feldern
|
||||
document.addEventListener("DOMContentLoaded", () => {
|
||||
["reg-username", "reg-email"].forEach((id) => {
|
||||
document.getElementById(id).addEventListener("keydown", (e) => {
|
||||
if (e.key === "Enter") submitRegistration();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
const canvas = document.getElementById("matrix-bg");
|
||||
const ctx = canvas.getContext("2d");
|
||||
|
||||
function resizeCanvas() {
|
||||
canvas.width = window.innerWidth;
|
||||
canvas.height = window.innerHeight;
|
||||
}
|
||||
resizeCanvas();
|
||||
window.addEventListener("resize", resizeCanvas);
|
||||
|
||||
const katakana =
|
||||
"アイウエオカキクケコサシスセソタチツテトナニヌネノハヒフヘホマミムメモヤユヨラリルレロワン1234567890ABCDEFGHIJKLMNOPQRSTUVWXYZ";
|
||||
const alphabet = katakana.split("");
|
||||
|
||||
const fontSize = 16;
|
||||
let columns = canvas.width / fontSize;
|
||||
|
||||
const rainDrops = [];
|
||||
for (let x = 0; x < columns; x++) {
|
||||
rainDrops[x] = 1;
|
||||
}
|
||||
|
||||
window.addEventListener("resize", () => {
|
||||
columns = canvas.width / fontSize;
|
||||
for (let x = rainDrops.length; x < columns; x++) {
|
||||
rainDrops[x] = 1;
|
||||
}
|
||||
});
|
||||
|
||||
function drawMatrixRain() {
|
||||
ctx.fillStyle = "rgba(0, 0, 0, 0.05)";
|
||||
ctx.fillRect(0, 0, canvas.width, canvas.height);
|
||||
|
||||
ctx.fillStyle = "#0f0";
|
||||
ctx.font = fontSize + "px monospace";
|
||||
|
||||
for (let i = 0; i < rainDrops.length; i++) {
|
||||
const text = alphabet[Math.floor(Math.random() * alphabet.length)];
|
||||
ctx.fillText(text, i * fontSize, rainDrops[i] * fontSize);
|
||||
|
||||
if (rainDrops[i] * fontSize > canvas.height && Math.random() > 0.975) {
|
||||
rainDrops[i] = 0;
|
||||
}
|
||||
rainDrops[i]++;
|
||||
}
|
||||
}
|
||||
|
||||
setInterval(drawMatrixRain, 30);
|
||||
@@ -0,0 +1,191 @@
|
||||
{ pkgs, lib, ... }:
|
||||
let
|
||||
flavours = [
|
||||
{
|
||||
name = "Latte";
|
||||
slug = "latte";
|
||||
is_dark = false;
|
||||
}
|
||||
{
|
||||
name = "Frappé";
|
||||
slug = "frappe";
|
||||
is_dark = true;
|
||||
}
|
||||
{
|
||||
name = "Macchiato";
|
||||
slug = "macchiato";
|
||||
is_dark = true;
|
||||
}
|
||||
{
|
||||
name = "Mocha";
|
||||
slug = "mocha";
|
||||
is_dark = true;
|
||||
}
|
||||
];
|
||||
accents = [
|
||||
"rosewater"
|
||||
"flamingo"
|
||||
"pink"
|
||||
"mauve"
|
||||
"red"
|
||||
"maroon"
|
||||
"peach"
|
||||
"yellow"
|
||||
"green"
|
||||
"teal"
|
||||
"sky"
|
||||
"sapphire"
|
||||
"blue"
|
||||
"lavender"
|
||||
];
|
||||
themeHashes = {
|
||||
"latte/rosewater" = "0l1m4bhaxdam07rfqag6pjbzhdpyi5w3i14vp6rq7aj59pildw3a";
|
||||
"latte/flamingo" = "1m8hh2l87xv2rfgpnnl5vzddmam0n82h25fwadb37blgab08vhsr";
|
||||
"latte/pink" = "0ambrc42mvg0vdspfmnl31ka1nsxpdyv1p3nh045822y02q20wwh";
|
||||
"latte/mauve" = "1nnn2w6nsr24a45jy497c2vhi8v64bwg99fj2dyhpfsn89c63lhn";
|
||||
"latte/red" = "14lmw4c4llfz6zqvfymkc6k3msxcml2gwq9rhwsixdpc5mjjbn8n";
|
||||
"latte/maroon" = "0ydpng9451mpn7hv5ag1ck8hryx8pdvrml3zksvzm2fiwzzjkpcf";
|
||||
"latte/peach" = "1fn5804wv9z9iv65ikyv015b01a7c546rsaaks2a2sq2c37n75l0";
|
||||
"latte/yellow" = "0hzgiyhqmwgp3h3v1y23sx3x5qp712sw106472lbnxbywqlavcza";
|
||||
"latte/green" = "194kxv6d9hc4nixy16hy9nvf32qs3v214nr2r2qf2z9l89rk5pnp";
|
||||
"latte/teal" = "12n25d38zpqxsskglymhmza972klg2hj3c23v2nb3jfj82llw6v4";
|
||||
"latte/sky" = "0yghds3xpmbhkbcj2jkh8df82j6vrn9q1z0s2129nca7l5g5f9w2";
|
||||
"latte/sapphire" = "18dl1srxp3xccvvy56za6kp05n68d918l0wrxga11746g9sib7r3";
|
||||
"latte/blue" = "1zv9nap21d80flvd1jwmjph05jgykxngv5kqbhk95mvqh962ygnf";
|
||||
"latte/lavender" = "03j4fwbscip1qm6px1qxkha0c5csq2wwvzg9vwjkc2ja48v1mp9k";
|
||||
"frappe/rosewater" = "032qbgj32mvgpankl9777x2lxk18451kglsxg5215k8zrwcg9y95";
|
||||
"frappe/flamingo" = "1grhgynn8q7isv18981km5k8ll72ihsjw2ciy8widl6wikv29j8p";
|
||||
"frappe/pink" = "0h33g721bph8ihd6lmbc7szxy4dq85ng1cgg5cxjb5y2m7wpdbsy";
|
||||
"frappe/mauve" = "121jmznc9q3p7crsy9p2khw8xnzvz4lxms26g1h5wqa67wqvalc4";
|
||||
"frappe/red" = "07wm4h1giyy6a5nlh0d3qdarfsp6ikyr5nmg94n13lj4q03d0cn0";
|
||||
"frappe/maroon" = "08vg70nr918n4ffi1wnbba4xrx5ak5vfgq7m5ik0rpkb2wdb4x6k";
|
||||
"frappe/peach" = "1cg753w2dxs0sx97d8y0g62s8aw3w6b9hrll0lsrw3bc1bvm23fl";
|
||||
"frappe/yellow" = "0g43g2if1pcm25i261zfw43bawqqdlgg2f6q2bqhyqvafk9yb3dy";
|
||||
"frappe/green" = "1n71mndzds3zldb271g8hdw1yn29s68svzvh8ckjcsz4sb9h1i74";
|
||||
"frappe/teal" = "0b6m9cibfwf8csh1pk5i76xi3wx3v2aqwgffzsidw8nwc7c1a3wk";
|
||||
"frappe/sky" = "1l4d44399ixshlc9fdsx7iqwxm6kdkp6k4z3z6bdyyx6adw3z4q5";
|
||||
"frappe/sapphire" = "03fa9rnclvs5ljd0lzz15vnkzpqpbrhfppg3zwfchs9fvak0n3ni";
|
||||
"frappe/blue" = "0r4jjn3pab77w1aanlv3143ch60400q44mdzaqmcjbcr6l2knmjh";
|
||||
"frappe/lavender" = "1mrkaz72w6j9hh4dpxwgd6ks5wsnq9ydgy6f9gms4jx1611aab96";
|
||||
"macchiato/rosewater" = "001akfnhlvwaiz5faahl4qi0qp6as6ilvkbja6bjy9f5iasr4ygp";
|
||||
"macchiato/flamingo" = "06xq3pbx4cb3pyblx2vydr4bp0ylm7866d66agg5wg5qnr356wb3";
|
||||
"macchiato/pink" = "1hb32dj0n3wx4f1wxa4n7fib2mazghwsg2ljycza9macfn2n87qn";
|
||||
"macchiato/mauve" = "1yrnp162blizc10fz2n6ls1x0di1sdjk53vpsl7mifrkcr1k2nq7";
|
||||
"macchiato/red" = "1g9s39q7459lk830vhdrfqkbzz88p3fp8k98a2ygj2hz8sycpryq";
|
||||
"macchiato/maroon" = "0ad7rx8sbkygvsgywhpjvvzmyflyhz7jlm13dr7cxj3801rxhl6d";
|
||||
"macchiato/peach" = "1m5m6afcl8s1ghn2b9n1d20fhsygnhgn0205nhpxh4bih3kg8c8m";
|
||||
"macchiato/yellow" = "0zcc26d28jaq71mz8nqssz8p0hylczirjwjxr2dkha1133vjmvy5";
|
||||
"macchiato/green" = "055xdb5jilp5fq3a1g8773rv52zr68fp4l3hs56yj6dy3bq3q22v";
|
||||
"macchiato/teal" = "1sfci2g2nvmj0v72gnxqbj0k8053qz0rl6iphfxs3pgpi1b0rczq";
|
||||
"macchiato/sky" = "0vhfmdliy8cbb0vqq3v26isvcz4sxzq0xrb4p5a6gibvxaqi6bf3";
|
||||
"macchiato/sapphire" = "1744jiv57aqz4qi52n92nrx0s1rhylgg08qqc31jr2clk9h6bw18";
|
||||
"macchiato/blue" = "1arp8r2g8ivs1xipq39d3l6cvx0zrr1vwv9yac5j33d6c93wbb2i";
|
||||
"macchiato/lavender" = "0kak1f574c07gqjfafg3w5avrci584iqxjkmvrl2pv1879g84nn3";
|
||||
"mocha/rosewater" = "0p3ck9crskrhk1za6knaznjlj464mx4sdkkadna6k2152m3czjpz";
|
||||
"mocha/flamingo" = "04xx1mky230saqxxqin2fph8cnnz1jhmvb9qd9f5yc3pai3q5wdw";
|
||||
"mocha/pink" = "1cj9zdd72vcc45ziav625yq6hrp1zw21f7xsic0ip065xcqzdl3p";
|
||||
"mocha/mauve" = "1wb0ibmdv6vn07bk570pikm43qdxj3n2zsqr5sip17ay05j5l6dm";
|
||||
"mocha/red" = "1mnzrk57ar2cphyi2ry2lg5ilmb26gm4pr7ixch2ls0hk8ilp9p9";
|
||||
"mocha/maroon" = "1mcpwz3yrg3kk0hkqv5nykxj07bm70403yyl8r60pqlh74dnhkbf";
|
||||
"mocha/peach" = "0jglpcs41rfqxcm45mvnbdqhma0bv4h07nc7c3nrwz3g3h2djmzr";
|
||||
"mocha/yellow" = "0jqkvcjiwid1zdvrj2ikqf5winm08qyd51nfsawfdspbfhqnzmis";
|
||||
"mocha/green" = "0bg0014a77yx7f2r6n4mxm7rqgdnymqq7cq6bvpgkfk2z1gyr38l";
|
||||
"mocha/teal" = "0kzvi3gfirpcxdhgsilm51lk3j1z6lavb7160chgd9jhzk0xg97c";
|
||||
"mocha/sky" = "057nmp2aywdxzrkmzi65bh2mvf1a9cnri0g0jdyzdnrn7f8bbsiw";
|
||||
"mocha/sapphire" = "0nfklzb0a7mxv6nzav7m2g0y9plm72vwadm06445myv3k9j3ffmj";
|
||||
"mocha/blue" = "06ay46x2aq1q5ghz2zhzhn6qyqkrrf4p9j59qywnxh1jvv728ns8";
|
||||
"mocha/lavender" = "0iip063f6km17998c7ak0lb3kq6iskyi3xv2phn618mhslnxhwm5";
|
||||
};
|
||||
|
||||
catppuccinThemes = lib.concatMap (
|
||||
flavour:
|
||||
map (
|
||||
accent:
|
||||
builtins.fromJSON (
|
||||
builtins.readFile (
|
||||
pkgs.fetchurl {
|
||||
url = "https://element.catppuccin.com/${flavour.slug}/${accent}.json";
|
||||
sha256 = themeHashes."${flavour.slug}/${accent}";
|
||||
}
|
||||
)
|
||||
)
|
||||
) accents
|
||||
) flavours;
|
||||
|
||||
elementConfig = builtins.toFile "element-config.json" (
|
||||
builtins.toJSON {
|
||||
default_server_config = {
|
||||
"m.homeserver" = {
|
||||
base_url = "https://matrix.cyperpunk.de";
|
||||
server_name = "cyperpunk.de";
|
||||
};
|
||||
};
|
||||
setting_defaults = {
|
||||
custom_themes = catppuccinThemes;
|
||||
feature_custom_themes = true;
|
||||
};
|
||||
}
|
||||
);
|
||||
|
||||
elementWebConfigured = pkgs.element-web.overrideAttrs (old: {
|
||||
postInstall = (old.postInstall or "") + ''
|
||||
cp ${elementConfig} $out/config.json
|
||||
'';
|
||||
});
|
||||
|
||||
cinnyConfigured = pkgs.cinny-unwrapped.overrideAttrs (_: {
|
||||
postInstall = ''
|
||||
cp ${
|
||||
builtins.toFile "cinny-config.json" (
|
||||
builtins.toJSON {
|
||||
defaultHomeserver = 0;
|
||||
homeserverList = [ "cyperpunk.de" ];
|
||||
allowCustomHomeservers = false;
|
||||
}
|
||||
)
|
||||
} $out/config.json
|
||||
'';
|
||||
});
|
||||
|
||||
in
|
||||
{
|
||||
services.nginx.virtualHosts = {
|
||||
"cinny.cyperpunk.de" = {
|
||||
forceSSL = true;
|
||||
enableACME = true;
|
||||
root = "${cinnyConfigured}";
|
||||
locations."/" = {
|
||||
tryFiles = "$uri $uri/ /index.html";
|
||||
};
|
||||
};
|
||||
"element.cyperpunk.de" = {
|
||||
forceSSL = true;
|
||||
enableACME = true;
|
||||
root = "${elementWebConfigured}";
|
||||
};
|
||||
|
||||
"fluffy.cyperpunk.de" = {
|
||||
forceSSL = true;
|
||||
enableACME = true;
|
||||
locations."/" = {
|
||||
proxyPass = "http://127.0.0.1:8082";
|
||||
proxyWebsockets = true;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
virtualisation.oci-containers.containers.fluffychat = {
|
||||
image = "ghcr.io/krille-chan/fluffychat:latest";
|
||||
ports = [ "127.0.0.1:8082:80" ];
|
||||
volumes = [
|
||||
"${
|
||||
builtins.toFile "fluffychat-config.json" (
|
||||
builtins.toJSON {
|
||||
default_homeserver = "matrix.cyperpunk.de";
|
||||
preset_homeserver = "matrix.cyperpunk.de";
|
||||
}
|
||||
)
|
||||
}:/app/config.json:ro"
|
||||
];
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,95 @@
|
||||
{ config, lib, ... }:
|
||||
{
|
||||
sops.secrets = {
|
||||
coturn_static_auth_secret = {
|
||||
owner = "turnserver";
|
||||
group = "turnserver";
|
||||
};
|
||||
|
||||
coturn_static_auth_secret_synapse = {
|
||||
owner = "matrix-synapse";
|
||||
group = "matrix-synapse";
|
||||
key = "coturn_static_auth_secret";
|
||||
};
|
||||
};
|
||||
|
||||
services = {
|
||||
coturn = rec {
|
||||
enable = true;
|
||||
no-cli = true;
|
||||
no-tcp-relay = true;
|
||||
min-port = 49000;
|
||||
max-port = 50000;
|
||||
use-auth-secret = true;
|
||||
static-auth-secret-file = config.sops.secrets.coturn_static_auth_secret.path;
|
||||
realm = "turn.cyperpunk.de";
|
||||
cert = "${config.security.acme.certs.${realm}.directory}/full.pem";
|
||||
pkey = "${config.security.acme.certs.${realm}.directory}/key.pem";
|
||||
extraConfig = ''
|
||||
no-multicast-peers
|
||||
denied-peer-ip=0.0.0.0-0.255.255.255
|
||||
denied-peer-ip=10.0.0.0-10.255.255.255
|
||||
denied-peer-ip=100.64.0.0-100.127.255.255
|
||||
denied-peer-ip=127.0.0.0-127.255.255.255
|
||||
denied-peer-ip=169.254.0.0-169.254.255.255
|
||||
denied-peer-ip=172.16.0.0-172.31.255.255
|
||||
denied-peer-ip=192.0.0.0-192.0.0.255
|
||||
denied-peer-ip=192.0.2.0-192.0.2.255
|
||||
denied-peer-ip=192.88.99.0-192.88.99.255
|
||||
denied-peer-ip=192.168.0.0-192.168.255.255
|
||||
denied-peer-ip=198.18.0.0-198.19.255.255
|
||||
denied-peer-ip=198.51.100.0-198.51.100.255
|
||||
denied-peer-ip=203.0.113.0-203.0.113.255
|
||||
denied-peer-ip=240.0.0.0-255.255.255.255
|
||||
denied-peer-ip=::1
|
||||
denied-peer-ip=64:ff9b::-64:ff9b::ffff:ffff
|
||||
denied-peer-ip=::ffff:0.0.0.0-::ffff:255.255.255.255
|
||||
denied-peer-ip=100::-100::ffff:ffff:ffff:ffff
|
||||
denied-peer-ip=2001::-2001:1ff:ffff:ffff:ffff:ffff:ffff:ffff
|
||||
denied-peer-ip=2002::-2002:ffff:ffff:ffff:ffff:ffff:ffff:ffff
|
||||
denied-peer-ip=fc00::-fdff:ffff:ffff:ffff:ffff:ffff:ffff:ffff
|
||||
denied-peer-ip=fe80::-febf:ffff:ffff:ffff:ffff:ffff:ffff:ffff
|
||||
'';
|
||||
relay-ips = [ "178.254.8.35" ];
|
||||
};
|
||||
|
||||
nginx.virtualHosts."turn.cyperpunk.de" = {
|
||||
forceSSL = true;
|
||||
enableACME = true;
|
||||
};
|
||||
|
||||
matrix-synapse.settings = with config.services.coturn; {
|
||||
turn_uris = [
|
||||
"turn:${realm}:3478?transport=udp"
|
||||
"turn:${realm}:3478?transport=tcp"
|
||||
];
|
||||
turn_shared_secret_path = config.sops.secrets.coturn_static_auth_secret_synapse.path;
|
||||
turn_user_lifetime = "1h";
|
||||
};
|
||||
};
|
||||
|
||||
security.acme.certs."turn.cyperpunk.de".group = "nginx";
|
||||
|
||||
users.users.turnserver.extraGroups = [ "nginx" ];
|
||||
|
||||
networking.firewall.interfaces.ens3 =
|
||||
let
|
||||
range =
|
||||
with config.services.coturn;
|
||||
lib.singleton {
|
||||
from = min-port;
|
||||
to = max-port;
|
||||
};
|
||||
in
|
||||
{
|
||||
allowedUDPPortRanges = range;
|
||||
allowedUDPPorts = [
|
||||
3478
|
||||
5349
|
||||
];
|
||||
allowedTCPPorts = [
|
||||
3478
|
||||
5349
|
||||
];
|
||||
};
|
||||
}
|
||||
@@ -4,28 +4,13 @@
|
||||
{
|
||||
imports = [
|
||||
./synapse.nix
|
||||
./lk-jwt.nix
|
||||
./livekit.nix
|
||||
./clients.nix
|
||||
./mjolnir.nix
|
||||
./coturn.nix
|
||||
./maubot.nix
|
||||
./discord-bridge.nix
|
||||
./whatsapp-bridge.nix
|
||||
./meta-bridge.nix
|
||||
];
|
||||
|
||||
#networking.firewall = {
|
||||
# allowedTCPPorts = [
|
||||
# 8008 # Matrix Synapse
|
||||
# 8009 # Cinny
|
||||
# 8010 # Element
|
||||
# 8011 # Synapse Admin
|
||||
# 8012 # FluffyChat
|
||||
# 8448 # Matrix federation
|
||||
# 3478 # TURN (coturn)
|
||||
# ];
|
||||
# allowedUDPPorts = [
|
||||
# 3478 # TURN (coturn)
|
||||
# ];
|
||||
# allowedUDPPortRanges = [
|
||||
# {
|
||||
# from = 49152;
|
||||
# to = 65535; # TURN relay ports (coturn)
|
||||
# }
|
||||
# ];
|
||||
#};
|
||||
}
|
||||
|
||||
@@ -0,0 +1,104 @@
|
||||
{ config, lib, ... }:
|
||||
{
|
||||
sops.secrets = {
|
||||
discord_bot_token = {
|
||||
owner = "mautrix-discord";
|
||||
group = "mautrix-discord";
|
||||
};
|
||||
discord_client_id = {
|
||||
owner = "mautrix-discord";
|
||||
group = "mautrix-discord";
|
||||
};
|
||||
discord_pickle_key = {
|
||||
owner = "mautrix-discord";
|
||||
group = "mautrix-discord";
|
||||
};
|
||||
};
|
||||
|
||||
systemd = {
|
||||
services = {
|
||||
mautrix-discord-env = {
|
||||
before = [ "mautrix-discord-registration.service" ];
|
||||
wantedBy = [ "multi-user.target" ];
|
||||
serviceConfig = {
|
||||
Type = "oneshot";
|
||||
RemainAfterExit = true;
|
||||
};
|
||||
script = ''
|
||||
mkdir -p /run/mautrix-discord
|
||||
echo "DISCORD_BOT_TOKEN=$(cat ${config.sops.secrets.discord_bot_token.path})" > /run/mautrix-discord/env
|
||||
echo "DISCORD_CLIENT_ID=$(cat ${config.sops.secrets.discord_client_id.path})" >> /run/mautrix-discord/env
|
||||
echo "DISCORD_PICKLE_KEY=$(cat ${config.sops.secrets.discord_pickle_key.path})" >> /run/mautrix-discord/env
|
||||
chmod 600 /run/mautrix-discord/env
|
||||
chown mautrix-discord:mautrix-discord /run/mautrix-discord/env
|
||||
'';
|
||||
};
|
||||
|
||||
mautrix-discord-registration.serviceConfig.UMask = lib.mkForce "0750";
|
||||
};
|
||||
tmpfiles.rules = [
|
||||
"z /var/lib/mautrix-discord/discord-registration.yaml 0640 mautrix-discord mautrix-discord -"
|
||||
];
|
||||
};
|
||||
|
||||
services = {
|
||||
postgresql = {
|
||||
ensureUsers = [
|
||||
{
|
||||
name = "mautrix-discord";
|
||||
ensureDBOwnership = true;
|
||||
}
|
||||
];
|
||||
ensureDatabases = [ "mautrix-discord" ];
|
||||
};
|
||||
|
||||
mautrix-discord = {
|
||||
enable = true;
|
||||
environmentFile = "/run/mautrix-discord/env";
|
||||
settings = {
|
||||
homeserver = {
|
||||
address = "http://127.0.0.1:8008";
|
||||
domain = "cyperpunk.de";
|
||||
};
|
||||
appservice.database = {
|
||||
type = "postgres";
|
||||
uri = "postgres:///mautrix-discord?host=/run/postgresql&sslmode=disable";
|
||||
};
|
||||
bridge = {
|
||||
permissions = {
|
||||
"cyperpunk.de" = "user";
|
||||
"@dergrumpf:cyperpunk.de" = "admin";
|
||||
};
|
||||
|
||||
backfill = {
|
||||
limits = {
|
||||
initial = {
|
||||
channel = 10000;
|
||||
thread = 500;
|
||||
};
|
||||
missed = {
|
||||
channel = 500;
|
||||
};
|
||||
};
|
||||
};
|
||||
encryption = {
|
||||
allow = true;
|
||||
default = true;
|
||||
pickle_key = "$DISCORD_PICKLE_KEY";
|
||||
verification_levels = {
|
||||
receive = "unverified";
|
||||
send = "unverified";
|
||||
share = "cross-signed-tofu";
|
||||
};
|
||||
};
|
||||
};
|
||||
discord = {
|
||||
client_id = "$DISCORD_CLIENT_ID";
|
||||
bot_token = "$DISCORD_BOT_TOKEN";
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
users.users.matrix-synapse.extraGroups = [ "mautrix-discord" ];
|
||||
}
|
||||
@@ -0,0 +1,617 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="de">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>Matrix Guide - cyperpunk.de</title>
|
||||
<link
|
||||
rel="icon"
|
||||
type="image/png"
|
||||
href="https://img.icons8.com/glyph-neue/64/trinity.png"
|
||||
/>
|
||||
<link rel="stylesheet" href="style.css" />
|
||||
|
||||
<!-- SEO & Meta -->
|
||||
<meta
|
||||
name="description"
|
||||
content="Einstiegspunkt für den cyperpunk.de Matrix-Server. Hier kannst du einen Account beantragen und erfährst alles über Clients, mobile Apps und Server-Funktionen."
|
||||
/>
|
||||
<meta name="robots" content="index, follow" />
|
||||
|
||||
<!-- Open Graph -->
|
||||
<meta property="og:type" content="website" />
|
||||
<meta property="og:url" content="https://matrix.cyperpunk.de/" />
|
||||
<meta property="og:title" content="Matrix Guide - cyperpunk.de" />
|
||||
<meta
|
||||
property="og:description"
|
||||
content="Einstiegspunkt für den cyperpunk.de Matrix-Server. Hier kannst du einen Account beantragen und erfährst alles über Clients, mobile Apps und Server-Funktionen."
|
||||
/>
|
||||
<meta property="og:locale" content="de_DE" />
|
||||
</head>
|
||||
<body>
|
||||
<a href="#main-content" class="skip-link">Zum Inhalt springen</a>
|
||||
<canvas id="matrix-bg" aria-hidden="true"></canvas>
|
||||
|
||||
<main class="container" id="main-content">
|
||||
|
||||
<!-- Header -->
|
||||
<header>
|
||||
<h1>Matrix Guide</h1>
|
||||
<p class="subtitle">Systemstatus: Aktiv auf Host cyperpunk.de</p>
|
||||
<p class="admin-tag">Grid-Operator: @dergrumpf:cyperpunk.de</p>
|
||||
</header>
|
||||
|
||||
<!-- Abstract -->
|
||||
<div class="abstract" role="note" aria-label="Was ist Matrix?">
|
||||
<p>
|
||||
<strong>Was ist Matrix?</strong> Matrix ist ein offenes,
|
||||
verschlüsseltes Kommunikationsnetzwerk – wie WhatsApp oder Discord,
|
||||
aber ohne zentrales Unternehmen dahinter. Jeder Nutzer hat eine eigene
|
||||
Adresse (z. B. <code class="code--white">@name:cyperpunk.de</code>), Nachrichten
|
||||
sind Ende-zu-Ende-verschlüsselt, und verschiedene Server können
|
||||
miteinander kommunizieren. Dieser Server wird privat betrieben und
|
||||
ist kostenlos nutzbar.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<!-- Sektion 1: Registrierung -->
|
||||
<section id="registration" aria-labelledby="heading-registration">
|
||||
<h2 id="heading-registration">1. Identitäts-Allokation (Registrierung)</h2>
|
||||
<p>
|
||||
Zugangsdaten für diesen Server werden exklusiv durch den
|
||||
Administrator <code class="code--white">@dergrumpf:cyperpunk.de</code> vergeben. Das untenstehende Formular sendet eine
|
||||
Anfrage direkt in den internen Koordinationskanal.
|
||||
</p>
|
||||
|
||||
<form class="reg-form" id="reg-form" novalidate aria-label="Registrierungsanfrage">
|
||||
<label for="reg-username">Gewünschter Benutzername</label>
|
||||
<input
|
||||
type="text"
|
||||
id="reg-username"
|
||||
name="username"
|
||||
placeholder="z.B. neo"
|
||||
autocomplete="off"
|
||||
spellcheck="false"
|
||||
required
|
||||
aria-required="true"
|
||||
/>
|
||||
|
||||
<label for="reg-email">E-Mail-Adresse (für Login-Daten)</label>
|
||||
<input
|
||||
type="email"
|
||||
id="reg-email"
|
||||
name="email"
|
||||
placeholder="z.B. neo@example.com"
|
||||
autocomplete="off"
|
||||
required
|
||||
aria-required="true"
|
||||
/>
|
||||
|
||||
<!-- Honeypot: muss leer bleiben -->
|
||||
<label for="reg-website" class="honeypot" aria-hidden="true">Website</label>
|
||||
<input
|
||||
type="text"
|
||||
id="reg-website"
|
||||
name="website"
|
||||
class="honeypot"
|
||||
tabindex="-1"
|
||||
autocomplete="off"
|
||||
aria-hidden="true"
|
||||
/>
|
||||
|
||||
<button
|
||||
type="button"
|
||||
class="reg-submit"
|
||||
id="reg-btn"
|
||||
onclick="submitRegistration()"
|
||||
>
|
||||
Zugang anfordern
|
||||
</button>
|
||||
|
||||
<div
|
||||
class="reg-status"
|
||||
id="reg-status"
|
||||
role="status"
|
||||
aria-live="polite"
|
||||
aria-atomic="true"
|
||||
></div>
|
||||
</form>
|
||||
</section>
|
||||
|
||||
<!-- Sektion 2: App oder Browser wählen -->
|
||||
<section id="clients" aria-labelledby="heading-clients">
|
||||
<h2 id="heading-clients">2. App oder Browser wählen</h2>
|
||||
<p>
|
||||
Du kannst Matrix entweder direkt im Browser nutzen oder eine App auf
|
||||
deinem Smartphone installieren. Sobald dein Login abgeschlossen ist,
|
||||
findest du den Homeserver unter
|
||||
<code class="code--white">#cyperpunk:cyperpunk.de</code>.
|
||||
</p>
|
||||
|
||||
<h3>Im Browser starten</h3>
|
||||
<p>Wähle eine der drei gehosteten Web-Schnittstellen:</p>
|
||||
|
||||
<div class="linktree-container">
|
||||
<a
|
||||
href="https://element.cyperpunk.de/"
|
||||
target="_blank"
|
||||
rel="noopener"
|
||||
aria-label="Element starten (öffnet neuen Tab)"
|
||||
class="linktree-btn"
|
||||
>
|
||||
<img src="https://img.icons8.com/keek-line/96/physics.png" alt="" aria-hidden="true" />
|
||||
Terminal: Element starten
|
||||
</a>
|
||||
<a
|
||||
href="https://cinny.cyperpunk.de/"
|
||||
target="_blank"
|
||||
rel="noopener"
|
||||
aria-label="Cinny starten (öffnet neuen Tab)"
|
||||
class="linktree-btn"
|
||||
>
|
||||
<img src="https://img.icons8.com/ios/100/bird--v1.png" alt="" aria-hidden="true" />
|
||||
Terminal: Cinny starten
|
||||
</a>
|
||||
<a
|
||||
href="https://fluffy.cyperpunk.de/"
|
||||
target="_blank"
|
||||
rel="noopener"
|
||||
aria-label="FluffyChat starten (öffnet neuen Tab)"
|
||||
class="linktree-btn"
|
||||
>
|
||||
<img src="https://img.icons8.com/pastel-glyph/64/cat--v3.png" alt="" aria-hidden="true" />
|
||||
Terminal: FluffyChat starten
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<h3>Welches Programm soll ich wählen?</h3>
|
||||
<div class="cards-grid">
|
||||
<div class="card">
|
||||
<h3 class="card-title">
|
||||
<img src="https://img.icons8.com/keek-line/96/physics.png" alt="" aria-hidden="true" class="card-icon" />
|
||||
Element
|
||||
</h3>
|
||||
<p class="card-text">
|
||||
Der mächtige <strong>Allrounder</strong>. Klassisches Interface mit
|
||||
vollem Funktionsumfang. Geeignet für alle, die Räume selbst
|
||||
verwalten möchten.
|
||||
<strong>Unterstützt Sprach- und Videoanrufe</strong> direkt im
|
||||
Browser.
|
||||
</p>
|
||||
</div>
|
||||
<div class="card">
|
||||
<h3 class="card-title">
|
||||
<img src="https://img.icons8.com/ios/100/bird--v1.png" alt="" aria-hidden="true" class="card-icon" />
|
||||
Cinny
|
||||
</h3>
|
||||
<p class="card-text">
|
||||
Der <strong>moderne Chat</strong>. Schnell, übersichtlich, am
|
||||
Design von Discord und Slack orientiert. Empfohlen für alle, die
|
||||
einfach schreiben möchten.
|
||||
<strong>Unterstützt Sprach- und Videoanrufe</strong> direkt im
|
||||
Browser.
|
||||
</p>
|
||||
</div>
|
||||
<div class="card card--highlight">
|
||||
<h3 class="card-title card-title--highlight">
|
||||
<img src="https://img.icons8.com/pastel-glyph/64/cat--v3.png" alt="" aria-hidden="true" class="card-icon" />
|
||||
FluffyChat
|
||||
</h3>
|
||||
<p class="card-text">
|
||||
Der <strong>einfache Messenger</strong>. Bunt und unkompliziert,
|
||||
vergleichbar mit WhatsApp oder Signal.
|
||||
<strong class="text--danger">Achtung:</strong>
|
||||
Diese Web-Version unterstützt <strong>keinen Sprach-Chat</strong>.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<h3>Auf dem Smartphone nutzen</h3>
|
||||
<p>
|
||||
Möchtest du von unterwegs auf Matrix zugreifen? Lade dir eine
|
||||
passende App herunter:
|
||||
</p>
|
||||
|
||||
<div class="app-download-box">
|
||||
<div class="app-row">
|
||||
<div class="app-info">
|
||||
<span class="app-name">FluffyChat</span>
|
||||
<p>Bunt, einsteigerfreundlich und ideal für das Smartphone.</p>
|
||||
</div>
|
||||
<div class="app-buttons">
|
||||
<a
|
||||
href="https://play.google.com/store/apps/details?id=chat.fluffy.fluffychat&hl=de_DE"
|
||||
target="_blank"
|
||||
rel="noopener"
|
||||
aria-label="FluffyChat im Google Play Store herunterladen (öffnet neuen Tab)"
|
||||
class="app-btn"
|
||||
><img src="https://img.icons8.com/ios/100/google-play--v1.png" alt="" aria-hidden="true" />Google Play</a
|
||||
>
|
||||
<a
|
||||
href="https://apps.apple.com/us/app/fluffychat/id1551469600"
|
||||
target="_blank"
|
||||
rel="noopener"
|
||||
aria-label="FluffyChat im App Store herunterladen (öffnet neuen Tab)"
|
||||
class="app-btn"
|
||||
><img src="https://img.icons8.com/ios/100/apple-app-store--v2.png" alt="" aria-hidden="true" />App Store</a
|
||||
>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="app-row">
|
||||
<div class="app-info">
|
||||
<span class="app-name">Element X</span>
|
||||
<p>Die App der nächsten Generation: Extrem schnell, modern und sicher.</p>
|
||||
</div>
|
||||
<div class="app-buttons">
|
||||
<a
|
||||
href="https://play.google.com/store/apps/details?id=io.element.android.x&hl=de_DE"
|
||||
target="_blank"
|
||||
rel="noopener"
|
||||
aria-label="Element X im Google Play Store herunterladen (öffnet neuen Tab)"
|
||||
class="app-btn"
|
||||
><img src="https://img.icons8.com/ios/100/google-play--v1.png" alt="" aria-hidden="true" />Google Play</a
|
||||
>
|
||||
<a
|
||||
href="https://apps.apple.com/us/app/element-x-secure-chat-call/id1631335820"
|
||||
target="_blank"
|
||||
rel="noopener"
|
||||
aria-label="Element X im App Store herunterladen (öffnet neuen Tab)"
|
||||
class="app-btn"
|
||||
><img src="https://img.icons8.com/ios/100/apple-app-store--v2.png" alt="" aria-hidden="true" />App Store</a
|
||||
>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<p class="mt-28"><strong>Wichtig beim ersten App-Start:</strong></p>
|
||||
<ul>
|
||||
<li>Überspringe die automatische Registrierung in der App.</li>
|
||||
<li>
|
||||
Suche nach der Option <strong>„Heimserver ändern"</strong>
|
||||
(oder Homeserver wechseln).
|
||||
</li>
|
||||
<li>
|
||||
Trage dort die Server-Adresse ein:
|
||||
<code class="code--white">cyperpunk.de</code>
|
||||
</li>
|
||||
<li>
|
||||
Logge dich erst danach wie gewohnt mit deinen Zugangsdaten oder
|
||||
per SSO ein.
|
||||
</li>
|
||||
</ul>
|
||||
</section>
|
||||
|
||||
<!-- Sektion 3: Erster Login & Sicherheit -->
|
||||
<section id="first-login" aria-labelledby="heading-first-login">
|
||||
<h2 id="heading-first-login">3. Erster Login & Sicherheitsschlüssel</h2>
|
||||
|
||||
<div class="matrix-alert" role="alert" aria-label="Sicherheitswarnung">
|
||||
<h3>⚠️ WARNUNG: Kryptografische Schlüssel sichern</h3>
|
||||
<p>
|
||||
Diese Matrix Instanz erzwingt standardmäßig eine vollständige
|
||||
Ende-zu-Ende-Verschlüsselung (E2EE). Bei der ersten Verbindung
|
||||
generiert dein Client eine
|
||||
<strong>Passphrase als Sicherheitsschlüssel</strong>.
|
||||
Sichere diesen Schlüssel extern! Solltest du dich abmelden
|
||||
oder das Gerät wechseln und diesen Schlüssel verlieren, sind deine
|
||||
Daten unwiderruflich verschlüsselt. Die
|
||||
Administration hat keinerlei Backdoors, um deine Daten
|
||||
wiederherzustellen.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<h3>Schritt-für-Schritt-Protokoll:</h3>
|
||||
<ol>
|
||||
<li>Wähle einen Client aus dem vorherigen Abschnitt.</li>
|
||||
<li>
|
||||
Der Zugriff ist entweder über klassische
|
||||
<strong>User-Credentials (Nutzername & Passwort)</strong> oder über das
|
||||
<strong>Single-Sign-On-Protokoll (SSO)</strong> möglich.
|
||||
</li>
|
||||
<li>
|
||||
Bei der Nutzung von SSO wirst du automatisch zum zentralen
|
||||
Identitäts-Server unter
|
||||
<a
|
||||
href="https://auth.cyperpunk.de/"
|
||||
target="_blank"
|
||||
rel="noopener"
|
||||
aria-label="auth.cyperpunk.de (öffnet neuen Tab)"
|
||||
><strong>auth.cyperpunk.de</strong></a
|
||||
>
|
||||
(powered by Kanidm) umgeleitet.
|
||||
</li>
|
||||
<li>
|
||||
Nach erfolgreicher Authentifizierung wird deine Session für Matrix freigeschaltet.
|
||||
</li>
|
||||
</ol>
|
||||
</section>
|
||||
|
||||
<!-- Sektion 4: Wie ist Matrix aufgebaut? -->
|
||||
<section id="server-structures" aria-labelledby="heading-server-structures">
|
||||
<h2 id="heading-server-structures">4. Wie ist Matrix aufgebaut?</h2>
|
||||
<p>
|
||||
Damit alles ordentlich bleibt und du dich gut zurechtfindest, ist
|
||||
Matrix logisch aufgeteilt. Es gibt im Grunde zwei Ebenen:
|
||||
</p>
|
||||
<ol>
|
||||
<li>
|
||||
<strong>Spaces (Bereiche / Ordner):</strong> Der übergeordnete
|
||||
Bereich – wie ein kompletter Server bei Discord. Ein Space sammelt
|
||||
verschiedene Rooms (Chats) an einem Ort.
|
||||
</li>
|
||||
<li>
|
||||
<strong>Rooms (Räume / Chats):</strong> Die eigentlichen Text- oder
|
||||
Sprachkanäle innerhalb eines Bereichs. Hier wird geschrieben,
|
||||
telefoniert und Material geteilt.
|
||||
</li>
|
||||
</ol>
|
||||
|
||||
<p><strong>Tipps für Admins und Moderatoren:</strong></p>
|
||||
<ul>
|
||||
<li>
|
||||
Erstelle zuerst einen <strong>Space (Bereich)</strong>, dann packst
|
||||
du die einzelnen Chats geordnet dort hinein.
|
||||
</li>
|
||||
<li>
|
||||
Verwende klare, einfache Namen für deine Räume – das erleichtert
|
||||
allen die Übersicht in der Seitenleiste.
|
||||
</li>
|
||||
</ul>
|
||||
</section>
|
||||
|
||||
<!-- Sektion 5: Sprachkanäle & Dateilimits -->
|
||||
<section id="infrastructure" aria-labelledby="heading-infrastructure">
|
||||
<h2 id="heading-infrastructure">5. Sprachkanäle & Speicherplatzlimits</h2>
|
||||
<p>
|
||||
Der Server stellt Kanäle bereit, mit denen du direkt über das
|
||||
Internet mit anderen Mitgliedern sprechen oder Dateien austauschen
|
||||
kannst.
|
||||
</p>
|
||||
|
||||
<div class="cards-grid">
|
||||
<div class="card">
|
||||
<h3 class="card-title">Anrufe in Gruppen</h3>
|
||||
<p class="card-text">
|
||||
Bei Gruppengesprächen in einem Raum übernimmt der Server im
|
||||
Hintergrund automatisch die Audio- und Bildübertragung für eine
|
||||
stabile Verbindung.
|
||||
</p>
|
||||
</div>
|
||||
<div class="card">
|
||||
<h3 class="card-title">Direktanrufe (1:1)</h3>
|
||||
<p class="card-text">
|
||||
Telefonate mit nur einer Person werden sicher und direkt
|
||||
aufgebaut. Ein integrierter Hilfsdienst (Coturn) sorgt dafür, dass die
|
||||
Verbindung auch durch Firewalls hinweg klappt.
|
||||
</p>
|
||||
</div>
|
||||
<div class="card full-width-card card--warning">
|
||||
<h3 class="card-title card-title--warning">Dateigröße & faires Teilen</h3>
|
||||
<p class="card-text">
|
||||
Das Hochladen von Bildern, Videos oder Dokumenten ist auf maximal
|
||||
<strong>50 MB pro Datei</strong> begrenzt. Der verfügbare
|
||||
Festplattenplatz ist begrenzt – ein sparsamer Umgang mit großen
|
||||
Dateien wird empfohlen.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Sektion 6: FAQ -->
|
||||
<section id="faq" aria-labelledby="heading-faq">
|
||||
<h2 id="heading-faq">6. FAQ – Häufige Fragen</h2>
|
||||
|
||||
<h3>Was ist Matrix?</h3>
|
||||
<p>
|
||||
Matrix ist ein offenes, dezentrales Kommunikationsprotokoll – ähnlich
|
||||
wie E-Mail, aber für Echtzeit-Chat und Anrufe. Jeder kann seinen
|
||||
eigenen Server betreiben, und Server können miteinander kommunizieren.
|
||||
</p>
|
||||
|
||||
<h3>Warum kein Discord?</h3>
|
||||
<p>
|
||||
Discord ist ein zentralisierter Dienst, der Nutzerdaten speichert und
|
||||
auswerten kann. Matrix ist Open Source, selbst gehostet und
|
||||
Ende-zu-Ende-verschlüsselt – du behältst die Kontrolle über deine
|
||||
Daten.
|
||||
</p>
|
||||
|
||||
<h3>Kann ich meinen bestehenden Matrix-Account verwenden?</h3>
|
||||
<p>
|
||||
Ja. Von jedem Matrix-Server aus lässt sich dem Raum
|
||||
<code class="code--white">#cyperpunk:cyperpunk.de</code> beitreten – einfach die eigene
|
||||
Adresse <code class="code--white">@deinname:deinserver.de</code> verwenden.
|
||||
</p>
|
||||
|
||||
<h3>Wie bekomme ich einen Account auf diesem Server?</h3>
|
||||
<p>
|
||||
Fülle das Registrierungsformular oben aus. Der Administrator prüft
|
||||
deine Anfrage und schickt dir die Zugangsdaten per E-Mail.
|
||||
</p>
|
||||
|
||||
<h3>Sind meine Nachrichten verschlüsselt?</h3>
|
||||
<p>
|
||||
Ja. Dieser Server erzwingt Ende-zu-Ende-Verschlüsselung (E2EE) in
|
||||
allen privaten Chats. Stelle sicher, dass du deinen
|
||||
Sicherheitsschlüssel beim ersten Login sicherst.
|
||||
</p>
|
||||
|
||||
<h3>Was kostet das?</h3>
|
||||
<p>Nichts. Der Server wird privat betrieben und ist kostenlos nutzbar.</p>
|
||||
</section>
|
||||
|
||||
<!-- Trennbereich: Für Fortgeschrittene -->
|
||||
<div
|
||||
class="advanced-separator"
|
||||
role="note"
|
||||
aria-label="Beginn des Fortgeschrittenen-Bereichs"
|
||||
>
|
||||
<h2>Für Fortgeschrittene</h2>
|
||||
<p>
|
||||
Die folgenden Abschnitte richten sich an Nutzer, die den Server aktiv
|
||||
mitgestalten oder erweitern möchten – z. B. Bots einbinden,
|
||||
Discord-Kanäle verbinden oder Matrix-Begriffe mit Discord vergleichen.
|
||||
Als normaler Nutzer brauchst du das nicht.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<!-- Sektion 7: Maubots -->
|
||||
<section id="maubots" aria-labelledby="heading-maubots">
|
||||
<h2 id="heading-maubots">7. Aktive Automatisierungs-Bots (Maubot)</h2>
|
||||
<p>
|
||||
Das <strong>Maubot</strong>-Framework ermöglicht die Integration
|
||||
automatisierter Skripte in das Raum-Netzwerk. Die Instanz dieses
|
||||
Servers ist erreichbar unter:
|
||||
<code class="code--white">@maubot:cyperpunk.de</code>.
|
||||
</p>
|
||||
<p>
|
||||
<strong>Bedienung:</strong> Die Entität kann
|
||||
<strong>in jeden beliebigen Raum eingeladen</strong> werden, um die
|
||||
geladenen Module per Textbefehl zu aktivieren. Aktive Subroutinen:
|
||||
</p>
|
||||
|
||||
<div class="cards-grid">
|
||||
<div class="card">
|
||||
<h3 class="card-title">Urban Dictionary</h3>
|
||||
<p class="card-text">
|
||||
Analysiert Slang-Begriffe, Definitionen und sprachliche Variablen
|
||||
direkt im Raum-Feed.<br />
|
||||
<a
|
||||
href="https://github.com/dvdgsng/UrbanMaubot/blob/master/README.md"
|
||||
target="_blank"
|
||||
rel="noopener"
|
||||
aria-label="Urban Dictionary Maubot Dokumentation (öffnet neuen Tab)"
|
||||
>Dokumentation</a
|
||||
>
|
||||
</p>
|
||||
</div>
|
||||
<div class="card">
|
||||
<h3 class="card-title">RSS News-Feeds</h3>
|
||||
<p class="card-text">
|
||||
Abonniert externe Informations-Feeds und speist Updates
|
||||
vollautomatisch in den Chat-Stream ein.<br />
|
||||
<a
|
||||
href="https://github.com/maubot/rss/blob/master/README.md"
|
||||
target="_blank"
|
||||
rel="noopener"
|
||||
aria-label="RSS Maubot Dokumentation (öffnet neuen Tab)"
|
||||
>Dokumentation</a
|
||||
>
|
||||
</p>
|
||||
</div>
|
||||
<div class="card">
|
||||
<h3 class="card-title">Reminder</h3>
|
||||
<p class="card-text">
|
||||
Ermöglicht das Setzen von Timern, Cron-Triggern und
|
||||
zeitgesteuerten Alarmen im Raum.<br />
|
||||
<a
|
||||
href="https://github.com/maubot/reminder/blob/master/README.md"
|
||||
target="_blank"
|
||||
rel="noopener"
|
||||
aria-label="Reminder Maubot Dokumentation (öffnet neuen Tab)"
|
||||
>Dokumentation</a
|
||||
>
|
||||
</p>
|
||||
</div>
|
||||
<div class="card">
|
||||
<h3 class="card-title">Wetter-Array</h3>
|
||||
<p class="card-text">
|
||||
Fragt aktuelle Klimadaten und meteorologische Berichte für globale
|
||||
Koordinaten ab.<br />
|
||||
<a
|
||||
href="https://github.com/kellya/maubot-weather/blob/main/README.md"
|
||||
target="_blank"
|
||||
rel="noopener"
|
||||
aria-label="Weather Maubot Dokumentation (öffnet neuen Tab)"
|
||||
>Dokumentation</a
|
||||
>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Sektion 8: Discord Bridge -->
|
||||
<section id="discord-bridge" aria-labelledby="heading-discord-bridge">
|
||||
<h2 id="heading-discord-bridge">8. Discord Bridge</h2>
|
||||
<p>
|
||||
Die Mautrix Discord Bridge spiegelt Nachrichten nahtlos zwischen Matrix
|
||||
und externen Discord-Gilden.
|
||||
</p>
|
||||
<p>
|
||||
<strong>Ident-ID der Discord-Bridge:</strong>
|
||||
<code class="code--white">@discordbot:cyperpunk.de</code>
|
||||
</p>
|
||||
|
||||
<h3>Befehlssatz:</h3>
|
||||
<ul>
|
||||
<li>
|
||||
Öffne eine Direktnachricht (DM) mit dem Bridge-Bot, um Befehle
|
||||
einzuspeisen.
|
||||
</li>
|
||||
<li>
|
||||
Im DM-Kanal versteht der Bot das Kommando
|
||||
<code class="code--white">help</code> direkt.
|
||||
</li>
|
||||
<li>
|
||||
In geteilten Räumen muss das Präfix vorangestellt werden:
|
||||
<code class="code--white">!discord help</code>.
|
||||
</li>
|
||||
</ul>
|
||||
</section>
|
||||
|
||||
<!-- Sektion 9: Discord-zu-Matrix Referenz -->
|
||||
<section id="codex" aria-labelledby="heading-codex">
|
||||
<h2 id="heading-codex">9. Discord-zu-Matrix Referenz-Codex</h2>
|
||||
<p>
|
||||
Diese Tabelle zeigt, wie bekannte Discord-Konzepte in Matrix heißen:
|
||||
</p>
|
||||
|
||||
<table class="codex-table" aria-label="Discord-zu-Matrix Vergleichstabelle">
|
||||
<thead>
|
||||
<tr>
|
||||
<th scope="col">Discord-Konstrukt</th>
|
||||
<th scope="col">Matrix-Spezifikation</th>
|
||||
<th scope="col">Funktion im Netz</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>Server / Gilde</td>
|
||||
<td><strong>Space</strong></td>
|
||||
<td>Ein virtueller Container, der Räume unter einem Thema bündelt.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Text- / Sprachkanal</td>
|
||||
<td><strong>Room</strong></td>
|
||||
<td>Der Endpunkt für Textnachrichten, Bilddaten oder Telefonie.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Direktnachricht (DM)</td>
|
||||
<td><strong>Direkt-Chat</strong></td>
|
||||
<td>Ein kryptografisch isolierter 1:1-Kanal zwischen zwei Accounts.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Rollen & Rechte</td>
|
||||
<td><strong>Power Levels</strong></td>
|
||||
<td>Ein numerischer Berechtigungswert (0–100) zur Steuerung von Moderations-Rechten.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Nitro Emojis</td>
|
||||
<td><strong>Emote-Packs</strong></td>
|
||||
<td>Serverweite Sticker- und Emoji-Bibliotheken – dezentral und kostenfrei.</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</section>
|
||||
|
||||
</main>
|
||||
|
||||
<!-- Footer -->
|
||||
<footer>
|
||||
<p class="footer-line">[ EOF ] /////// TRANSMISSION COMPLETE ///////</p>
|
||||
<p class="footer-credit">GENERATED BY <span>CLAUDE</span> // ANTHROPIC · <span>claude-sonnet-4-6</span></p>
|
||||
</footer>
|
||||
<script src="app.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,54 +1,19 @@
|
||||
{ config, lib, ... }:
|
||||
{ config, ... }:
|
||||
{
|
||||
sops.secrets.livekit_key_sfu = { };
|
||||
sops.secrets.livekit_key_file = { };
|
||||
|
||||
services.livekit = {
|
||||
enable = true;
|
||||
openFirewall = true;
|
||||
keyFile = config.sops.secrets.livekit_key_sfu.path;
|
||||
settings = {
|
||||
rtc = {
|
||||
tcp_port = 7881;
|
||||
#udp_port = 7882;
|
||||
port_range_start = 50000;
|
||||
port_range_end = 60000;
|
||||
use_external_ip = true;
|
||||
node_ip = "178.254.8.35";
|
||||
};
|
||||
room = {
|
||||
auto_create = true;
|
||||
enabled_codecs = [
|
||||
{ mime = "video/VP8"; }
|
||||
{ mime = "video/VP9"; }
|
||||
{ mime = "video/H264"; }
|
||||
{ mime = "audio/opus"; }
|
||||
];
|
||||
enable_remote_unmute = true;
|
||||
};
|
||||
};
|
||||
};
|
||||
networking.firewall.allowedTCPPorts = [ 7881 ];
|
||||
|
||||
systemd.services.livekit.serviceConfig = {
|
||||
PrivateUsers = lib.mkForce false;
|
||||
DynamicUser = lib.mkForce false;
|
||||
User = "livekit";
|
||||
Group = "livekit";
|
||||
RestrictAddressFamilies = lib.mkForce [
|
||||
"AF_INET"
|
||||
"AF_INET6"
|
||||
"AF_NETLINK"
|
||||
"AF_UNIX"
|
||||
];
|
||||
SystemCallFilter = lib.mkForce [ "@system-service" ];
|
||||
settings.room.auto_create = false;
|
||||
keyFile = config.sops.secrets.livekit_key_file.path;
|
||||
};
|
||||
|
||||
users = {
|
||||
users.livekit = {
|
||||
isSystemUser = true;
|
||||
group = "livekit";
|
||||
};
|
||||
groups.livekit = { };
|
||||
services.lk-jwt-service = {
|
||||
enable = true;
|
||||
livekitUrl = "wss://cyperpunk.de/livekit/sfu";
|
||||
keyFile = config.sops.secrets.livekit_key_file.path;
|
||||
};
|
||||
|
||||
systemd.services.lk-jwt-service.environment.LIVEKIT_FULL_ACCESS_HOMESERVERS = "cyperpunk.de";
|
||||
}
|
||||
|
||||
@@ -1,25 +0,0 @@
|
||||
{ config, lib, ... }:
|
||||
let
|
||||
domain = "cyperpunk.de";
|
||||
synapseUrl = "http://localhost:8008";
|
||||
in
|
||||
{
|
||||
sops.secrets.livekit_key_jwt = { };
|
||||
|
||||
networking.firewall.allowedTCPPorts = [ 18080 ];
|
||||
|
||||
services.lk-jwt-service = {
|
||||
enable = true;
|
||||
keyFile = config.sops.secrets.livekit_key_jwt.path;
|
||||
livekitUrl = "wss://cyperpunk.de/livekit/sfu";
|
||||
};
|
||||
|
||||
systemd.services.lk-jwt-service = {
|
||||
environment = {
|
||||
LIVEKIT_FULL_ACCESS_HOMESERVERS = domain;
|
||||
MATRIX_BASE_URL = synapseUrl;
|
||||
LIVEKIT_JWT_BIND = lib.mkForce ":18080";
|
||||
LIVEKIT_INSECURE_SKIP_VERIFY_TLS = "YES_I_KNOW_WHAT_I_AM_DOING";
|
||||
};
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
{ config, pkgs, ... }:
|
||||
{
|
||||
environment.systemPackages = with pkgs; [
|
||||
maubot
|
||||
];
|
||||
|
||||
services = {
|
||||
maubot = {
|
||||
enable = true;
|
||||
plugins = with config.services.maubot.package.plugins; [
|
||||
weather
|
||||
rss
|
||||
reminder
|
||||
urban
|
||||
wolframalpha
|
||||
dice
|
||||
];
|
||||
settings = {
|
||||
database = "postgresql:///maubot?host=/run/postgresql";
|
||||
homeservers = {
|
||||
"cyperpunk.de" = {
|
||||
url = "https://matrix.cyperpunk.de";
|
||||
};
|
||||
};
|
||||
admins = {
|
||||
root = "";
|
||||
dergrumpf = "$2b$12$62kYoqsSloK3hco/N/EZUupD/JOjTMMVhUf064cqveBJYXGJJF8Hi";
|
||||
};
|
||||
plugin_directories = {
|
||||
upload = "/var/lib/maubot/plugins";
|
||||
load = [ "/var/lib/maubot/plugins" ];
|
||||
trash = "/var/lib/maubot/trash";
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
postgresql = {
|
||||
ensureUsers = [
|
||||
{
|
||||
name = "maubot";
|
||||
ensureDBOwnership = true;
|
||||
}
|
||||
];
|
||||
ensureDatabases = [ "maubot" ];
|
||||
};
|
||||
|
||||
nginx.virtualHosts."cyperpunk.de".locations."/_matrix/maubot/" = {
|
||||
proxyPass = "http://127.0.0.1:29316";
|
||||
proxyWebsockets = true;
|
||||
};
|
||||
};
|
||||
|
||||
systemd.tmpfiles.rules = [
|
||||
"d /var/lib/maubot/plugins 0750 maubot maubot -"
|
||||
"d /var/lib/maubot/trash 0750 maubot maubot -"
|
||||
];
|
||||
}
|
||||
@@ -0,0 +1,125 @@
|
||||
{ config, lib, ... }:
|
||||
{
|
||||
sops.secrets = {
|
||||
meta_as_token = {
|
||||
owner = "mautrix-meta-facebook";
|
||||
group = "mautrix-meta";
|
||||
};
|
||||
meta_hs_token = {
|
||||
owner = "mautrix-meta-facebook";
|
||||
group = "mautrix-meta";
|
||||
};
|
||||
instagram_as_token = {
|
||||
owner = "mautrix-meta-instagram";
|
||||
group = "mautrix-meta";
|
||||
};
|
||||
instagram_hs_token = {
|
||||
owner = "mautrix-meta-instagram";
|
||||
group = "mautrix-meta";
|
||||
};
|
||||
};
|
||||
|
||||
systemd.services = {
|
||||
mautrix-meta-facebook-env = {
|
||||
before = [ "mautrix-meta-facebook-registration.service" ];
|
||||
wantedBy = [ "multi-user.target" ];
|
||||
serviceConfig = {
|
||||
Type = "oneshot";
|
||||
RemainAfterExit = true;
|
||||
};
|
||||
script = ''
|
||||
mkdir -p /run/mautrix-meta-facebook
|
||||
echo "META_AS_TOKEN=$(cat ${config.sops.secrets.meta_as_token.path})" > /run/mautrix-meta-facebook/env
|
||||
echo "META_HS_TOKEN=$(cat ${config.sops.secrets.meta_hs_token.path})" >> /run/mautrix-meta-facebook/env
|
||||
chmod 600 /run/mautrix-meta-facebook/env
|
||||
chown mautrix-meta-facebook:mautrix-meta /run/mautrix-meta-facebook/env
|
||||
'';
|
||||
};
|
||||
|
||||
mautrix-meta-instagram-env = {
|
||||
before = [ "mautrix-meta-instagram-registration.service" ];
|
||||
wantedBy = [ "multi-user.target" ];
|
||||
serviceConfig = {
|
||||
Type = "oneshot";
|
||||
RemainAfterExit = true;
|
||||
};
|
||||
script = ''
|
||||
mkdir -p /run/mautrix-meta-instagram
|
||||
echo "INSTAGRAM_AS_TOKEN=$(cat ${config.sops.secrets.instagram_as_token.path})" > /run/mautrix-meta-instagram/env
|
||||
echo "INSTAGRAM_HS_TOKEN=$(cat ${config.sops.secrets.instagram_hs_token.path})" >> /run/mautrix-meta-instagram/env
|
||||
chmod 600 /run/mautrix-meta-instagram/env
|
||||
chown mautrix-meta-instagram:mautrix-meta /run/mautrix-meta-instagram/env
|
||||
'';
|
||||
};
|
||||
|
||||
mautrix-meta-facebook-registration.serviceConfig.UMask = lib.mkForce "0022";
|
||||
mautrix-meta-instagram-registration.serviceConfig.UMask = lib.mkForce "0022";
|
||||
};
|
||||
|
||||
services = {
|
||||
postgresql = {
|
||||
ensureUsers = [
|
||||
{
|
||||
name = "mautrix-meta-facebook";
|
||||
ensureDBOwnership = true;
|
||||
}
|
||||
{
|
||||
name = "mautrix-meta-instagram";
|
||||
ensureDBOwnership = true;
|
||||
}
|
||||
];
|
||||
ensureDatabases = [
|
||||
"mautrix-meta-facebook"
|
||||
"mautrix-meta-instagram"
|
||||
];
|
||||
};
|
||||
|
||||
mautrix-meta.instances = {
|
||||
facebook = {
|
||||
enable = true;
|
||||
environmentFile = "/run/mautrix-meta-facebook/env";
|
||||
settings = {
|
||||
homeserver = {
|
||||
address = "http://127.0.0.1:8008";
|
||||
domain = "cyperpunk.de";
|
||||
};
|
||||
database = {
|
||||
type = "postgres";
|
||||
uri = "postgres:///mautrix-meta-facebook?host=/run/postgresql&sslmode=disable";
|
||||
};
|
||||
appservice = {
|
||||
as_token = "$META_AS_TOKEN";
|
||||
hs_token = "$META_HS_TOKEN";
|
||||
};
|
||||
bridge.permissions = {
|
||||
"cyperpunk.de" = "user";
|
||||
"@dergrumpf:cyperpunk.de" = "admin";
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
instagram = {
|
||||
enable = true;
|
||||
environmentFile = "/run/mautrix-meta-instagram/env";
|
||||
settings = {
|
||||
homeserver = {
|
||||
address = "http://127.0.0.1:8008";
|
||||
domain = "cyperpunk.de";
|
||||
};
|
||||
database = {
|
||||
type = "postgres";
|
||||
uri = "postgres:///mautrix-meta-instagram?host=/run/postgresql&sslmode=disable";
|
||||
};
|
||||
appservice = {
|
||||
as_token = "$INSTAGRAM_AS_TOKEN";
|
||||
hs_token = "$INSTAGRAM_HS_TOKEN";
|
||||
};
|
||||
bridge.permissions = {
|
||||
"cyperpunk.de" = "user";
|
||||
"@dergrumpf:cyperpunk.de" = "admin";
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
{ config, ... }:
|
||||
{
|
||||
sops.secrets.mjolnir_access_token = { };
|
||||
|
||||
services.draupnir = {
|
||||
enable = true;
|
||||
secrets.accessToken = config.sops.secrets.mjolnir_access_token.path;
|
||||
settings = {
|
||||
homeserverUrl = "https://matrix.cyperpunk.de";
|
||||
managementRoom = "!eErCimyDjLSebHjpJA:cyperpunk.de";
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
#curl -X POST https://matrix.cyperpunk.de/_matrix/client/v3/login \
|
||||
# -H "Content-Type: application/json" \
|
||||
# -d '{"type":"m.login.password ","user":"mjolnir","password":"i318HXBRkt)Lh$nOPwq#6n9z&<W[XJ&2c4$Zf>7jV}-uQCE{<plwk;LZ)10*N<~1"}'
|
||||
@@ -0,0 +1,114 @@
|
||||
{
|
||||
config,
|
||||
pkgs,
|
||||
lib,
|
||||
...
|
||||
}:
|
||||
{
|
||||
sops.secrets = {
|
||||
pg_replication_password = {
|
||||
owner = "root";
|
||||
group = "root";
|
||||
};
|
||||
};
|
||||
|
||||
virtualisation.docker.enable = true;
|
||||
|
||||
systemd.services.postgresql-replica = {
|
||||
description = "PostgreSQL WAL streaming replica (Docker)";
|
||||
requires = [
|
||||
"docker.service"
|
||||
"tailscaled.service"
|
||||
"network-online.target"
|
||||
];
|
||||
after = [
|
||||
"docker.service"
|
||||
"tailscaled.service"
|
||||
"network-online.target"
|
||||
];
|
||||
wantedBy = [ "multi-user.target" ];
|
||||
|
||||
serviceConfig = {
|
||||
Type = "simple";
|
||||
Restart = "on-failure";
|
||||
RestartSec = "10s";
|
||||
};
|
||||
|
||||
preStart = ''
|
||||
DATADIR="/storage/backup/postgresql-replica"
|
||||
PG_PASS=$(cat ${config.sops.secrets.pg_replication_password.path})
|
||||
|
||||
${pkgs.docker}/bin/docker pull postgres:17
|
||||
|
||||
if [ ! -f "$DATADIR/PG_VERSION" ]; then
|
||||
echo "No data dir found — running pg_basebackup..."
|
||||
rm -rf "$DATADIR"
|
||||
|
||||
${pkgs.docker}/bin/docker run --rm \
|
||||
-e PGPASSWORD="$PG_PASS" \
|
||||
-v "/storage/backup:/out" \
|
||||
--network host \
|
||||
postgres:17 \
|
||||
pg_basebackup \
|
||||
--host=100.109.10.91 \
|
||||
--port=5432 \
|
||||
--username=replicator \
|
||||
--pgdata=/out/postgresql-replica \
|
||||
--wal-method=stream \
|
||||
--checkpoint=fast \
|
||||
--progress \
|
||||
--verbose
|
||||
|
||||
# standby signal
|
||||
touch "$DATADIR/standby.signal"
|
||||
|
||||
# primary conninfo
|
||||
cat > "$DATADIR/postgresql.auto.conf" <<EOF
|
||||
primary_conninfo = 'host=100.109.10.91 port=5432 user=replicator password=$PG_PASS application_name=cyper-controller sslmode=require'
|
||||
EOF
|
||||
|
||||
# minimal postgresql.conf
|
||||
cat > "$DATADIR/postgresql.conf" <<EOF
|
||||
hot_standby = on
|
||||
hot_standby_feedback = on
|
||||
wal_receiver_timeout = '60s'
|
||||
port = 5434
|
||||
listen_addresses = '*'
|
||||
EOF
|
||||
|
||||
chown -R 999:999 "$DATADIR"
|
||||
fi
|
||||
|
||||
# ensure postgresql.conf exists on subsequent starts
|
||||
if [ ! -f "$DATADIR/postgresql.conf" ]; then
|
||||
cat > "$DATADIR/postgresql.conf" <<EOF
|
||||
hot_standby = on
|
||||
hot_standby_feedback = on
|
||||
wal_receiver_timeout = '60s'
|
||||
port = 5434
|
||||
listen_addresses = '*'
|
||||
EOF
|
||||
chown 999:999 "$DATADIR/postgresql.conf"
|
||||
fi
|
||||
'';
|
||||
|
||||
script = ''
|
||||
${pkgs.docker}/bin/docker run --rm \
|
||||
--name postgresql-replica \
|
||||
-v /storage/backup/postgresql-replica:/var/lib/postgresql/data \
|
||||
--network host \
|
||||
postgres:17
|
||||
'';
|
||||
|
||||
postStop = ''
|
||||
${pkgs.docker}/bin/docker rm -f postgresql-replica 2>/dev/null || true
|
||||
'';
|
||||
};
|
||||
|
||||
services.prometheus.exporters.postgres = {
|
||||
enable = true;
|
||||
port = 9188;
|
||||
runAsLocalSuperUser = false;
|
||||
dataSourceName = "postgresql://postgres@localhost:5434/postgres?sslmode=disable";
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,159 @@
|
||||
<?php
|
||||
// Nur POST-Requests erlauben
|
||||
if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
|
||||
http_response_code(405);
|
||||
exit(json_encode(['error' => 'Method not allowed']));
|
||||
}
|
||||
|
||||
header('Content-Type: application/json');
|
||||
|
||||
// --- Konfiguration ---
|
||||
define('MATRIX_HOMESERVER', 'https://cyperpunk.de');
|
||||
define('MATRIX_ACCESS_TOKEN', 'syt_cmVnaXN0cmF0aW9uLWJvdA_tWjAfJOYDoJSuoCWoYIQ_4YuoMw');
|
||||
define('MATRIX_ROOM_ID', '!xBizjYatXLfpCorAXt:cyperpunk.de');
|
||||
|
||||
// Rate-Limit: max. Anfragen pro Zeitfenster
|
||||
define('RATE_LIMIT_MAX', 5); // Anfragen
|
||||
define('RATE_LIMIT_WINDOW', 300); // Sekunden (5 Minuten)
|
||||
define('RATE_LIMIT_DIR', sys_get_temp_dir() . '/matrix_reg_rl');
|
||||
|
||||
// --- IP ermitteln (auch hinter Proxies) ---
|
||||
function getClientIP(): string {
|
||||
$headers = ['HTTP_CF_CONNECTING_IP', 'HTTP_X_FORWARDED_FOR', 'HTTP_X_REAL_IP', 'REMOTE_ADDR'];
|
||||
foreach ($headers as $header) {
|
||||
if (!empty($_SERVER[$header])) {
|
||||
$ip = explode(',', $_SERVER[$header])[0];
|
||||
$ip = trim($ip);
|
||||
if (filter_var($ip, FILTER_VALIDATE_IP)) {
|
||||
return $ip;
|
||||
}
|
||||
}
|
||||
}
|
||||
return 'unknown';
|
||||
}
|
||||
|
||||
// --- Rate-Limiting (dateibasiert) ---
|
||||
function checkRateLimit(string $ip): bool {
|
||||
$dir = RATE_LIMIT_DIR;
|
||||
if (!is_dir($dir)) {
|
||||
mkdir($dir, 0700, true);
|
||||
}
|
||||
|
||||
$file = $dir . '/' . hash('sha256', $ip) . '.json';
|
||||
$now = time();
|
||||
$data = ['count' => 0, 'window_start' => $now];
|
||||
|
||||
if (file_exists($file)) {
|
||||
$data = json_decode(file_get_contents($file), true) ?? $data;
|
||||
// Zeitfenster abgelaufen → zurücksetzen
|
||||
if ($now - $data['window_start'] > RATE_LIMIT_WINDOW) {
|
||||
$data = ['count' => 0, 'window_start' => $now];
|
||||
}
|
||||
}
|
||||
|
||||
if ($data['count'] >= RATE_LIMIT_MAX) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$data['count']++;
|
||||
file_put_contents($file, json_encode($data), LOCK_EX);
|
||||
return true;
|
||||
}
|
||||
|
||||
// --- Honeypot prüfen ---
|
||||
$input = json_decode(file_get_contents('php://input'), true);
|
||||
|
||||
if (!empty($input['website'])) {
|
||||
// Bot hat das versteckte Feld ausgefüllt – still ablehnen
|
||||
http_response_code(200);
|
||||
exit(json_encode(['success' => true]));
|
||||
}
|
||||
|
||||
// --- Rate-Limit prüfen ---
|
||||
$ip = getClientIP();
|
||||
if (!checkRateLimit($ip)) {
|
||||
http_response_code(429);
|
||||
exit(json_encode(['error' => 'Zu viele Anfragen. Bitte warte einige Minuten.']));
|
||||
}
|
||||
|
||||
// --- Eingabe validieren ---
|
||||
$username = isset($input['username']) ? trim($input['username']) : '';
|
||||
$email = isset($input['email']) ? trim($input['email']) : '';
|
||||
|
||||
if (empty($username) || empty($email)) {
|
||||
http_response_code(400);
|
||||
exit(json_encode(['error' => 'Benutzername und E-Mail sind erforderlich.']));
|
||||
}
|
||||
|
||||
if (!filter_var($email, FILTER_VALIDATE_EMAIL)) {
|
||||
http_response_code(400);
|
||||
exit(json_encode(['error' => 'Ungültige E-Mail-Adresse.']));
|
||||
}
|
||||
|
||||
// Eingaben bereinigen
|
||||
$username = htmlspecialchars($username, ENT_QUOTES, 'UTF-8');
|
||||
$email = htmlspecialchars($email, ENT_QUOTES, 'UTF-8');
|
||||
|
||||
// --- Nachricht zusammenstellen ---
|
||||
$timestamp = date('d.m.Y H:i:s T');
|
||||
$userAgent = $_SERVER['HTTP_USER_AGENT'] ?? 'Unbekannt';
|
||||
|
||||
$message = "🔐 Registration Request\n\n"
|
||||
. "Username: {$username}\n"
|
||||
. "E-Mail: {$email}\n"
|
||||
. "IP: {$ip}\n"
|
||||
. "Zeitstempel: {$timestamp}\n"
|
||||
. "User-Agent: {$userAgent}";
|
||||
|
||||
$formattedMessage = "🔐 <strong>Registration Request</strong><br><br>"
|
||||
. "<strong>Username:</strong> {$username}<br>"
|
||||
. "<strong>E-Mail:</strong> {$email}<br>"
|
||||
. "<strong>IP:</strong> {$ip}<br>"
|
||||
. "<strong>Zeitstempel:</strong> {$timestamp}<br>"
|
||||
. "<strong>User-Agent:</strong> {$userAgent}";
|
||||
|
||||
// --- An Matrix senden ---
|
||||
$txnId = 'reg_' . time() . '_' . bin2hex(random_bytes(8));
|
||||
$url = MATRIX_HOMESERVER
|
||||
. '/_matrix/client/v3/rooms/'
|
||||
. urlencode(MATRIX_ROOM_ID)
|
||||
. '/send/m.room.message/'
|
||||
. $txnId;
|
||||
|
||||
$payload = json_encode([
|
||||
'msgtype' => 'm.text',
|
||||
'body' => $message,
|
||||
'format' => 'org.matrix.custom.html',
|
||||
'formatted_body' => $formattedMessage,
|
||||
]);
|
||||
|
||||
$ch = curl_init($url);
|
||||
curl_setopt_array($ch, [
|
||||
CURLOPT_CUSTOMREQUEST => 'PUT',
|
||||
CURLOPT_POSTFIELDS => $payload,
|
||||
CURLOPT_RETURNTRANSFER => true,
|
||||
CURLOPT_HTTPHEADER => [
|
||||
'Authorization: Bearer ' . MATRIX_ACCESS_TOKEN,
|
||||
'Content-Type: application/json',
|
||||
],
|
||||
CURLOPT_TIMEOUT => 10,
|
||||
]);
|
||||
|
||||
$response = curl_exec($ch);
|
||||
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
|
||||
$curlError = curl_error($ch);
|
||||
curl_close($ch);
|
||||
|
||||
if ($curlError) {
|
||||
http_response_code(502);
|
||||
exit(json_encode(['error' => 'Verbindung zum Matrix-Server fehlgeschlagen.']));
|
||||
}
|
||||
|
||||
if ($httpCode >= 200 && $httpCode < 300) {
|
||||
http_response_code(200);
|
||||
exit(json_encode(['success' => true]));
|
||||
} else {
|
||||
$matrixError = json_decode($response, true);
|
||||
http_response_code(502);
|
||||
exit(json_encode(['error' => 'Matrix-Fehler: ' . ($matrixError['error'] ?? "HTTP {$httpCode}")]));
|
||||
}
|
||||
@@ -0,0 +1,676 @@
|
||||
/* Basis-Styles & Reset */
|
||||
*,
|
||||
*::before,
|
||||
*::after {
|
||||
box-sizing: border-box;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
body {
|
||||
background-color: #000;
|
||||
color: #00ff41; /* Klassisches Matrix-Grün */
|
||||
font-family: "Courier New", Courier, monospace;
|
||||
overflow-x: hidden;
|
||||
min-height: 100vh;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
/* Skip-to-content Link für Tastaturnavigation */
|
||||
.skip-link {
|
||||
position: absolute;
|
||||
top: -100%;
|
||||
left: 0;
|
||||
background: #00ff41;
|
||||
color: #000;
|
||||
padding: 10px 20px;
|
||||
font-weight: bold;
|
||||
text-decoration: none;
|
||||
z-index: 9999;
|
||||
border-radius: 0 0 4px 0;
|
||||
}
|
||||
|
||||
.skip-link:focus {
|
||||
top: 0;
|
||||
}
|
||||
|
||||
/* Matrix-Regen Canvas Hintergrund */
|
||||
#matrix-bg {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
z-index: -1;
|
||||
opacity: 0.12; /* Gedimmter Hintergrund für optimale Lesbarkeit */
|
||||
}
|
||||
|
||||
/* Hauptcontainer */
|
||||
.container {
|
||||
max-width: 950px;
|
||||
margin: 0 auto;
|
||||
padding: 40px 20px;
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
/* Header / Titel */
|
||||
header {
|
||||
text-align: center;
|
||||
margin-bottom: 50px;
|
||||
}
|
||||
|
||||
h1 {
|
||||
font-size: 3rem;
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 4px;
|
||||
color: #fff;
|
||||
text-shadow:
|
||||
0 0 10px #00ff41,
|
||||
0 0 20px #00ff41,
|
||||
0 0 30px #00ff41;
|
||||
margin-bottom: 10px;
|
||||
animation: glitch 1s linear infinite alternate;
|
||||
}
|
||||
|
||||
.subtitle {
|
||||
font-size: 1.1rem;
|
||||
color: #00ff41;
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 2px;
|
||||
color: #00e63a;
|
||||
margin-bottom: 15px;
|
||||
}
|
||||
|
||||
.admin-tag {
|
||||
display: inline-block;
|
||||
background: rgba(0, 255, 65, 0.1);
|
||||
border: 1px dashed #00ff41;
|
||||
padding: 6px 12px;
|
||||
font-size: 0.9rem;
|
||||
color: #fff;
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
/* Sektionen-Styling */
|
||||
section {
|
||||
margin-bottom: 60px;
|
||||
background: rgba(0, 5, 0, 0.85);
|
||||
border: 1px solid #00ff41;
|
||||
border-radius: 6px;
|
||||
padding: 20px 30px 30px;
|
||||
box-shadow: 0 0 15px rgba(0, 255, 65, 0.1);
|
||||
}
|
||||
|
||||
h2 {
|
||||
font-size: 1.6rem;
|
||||
border-bottom: 2px solid #00ff41;
|
||||
padding-bottom: 8px;
|
||||
margin-bottom: 25px;
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 2px;
|
||||
color: #fff;
|
||||
text-shadow: 0 0 5px #00ff41;
|
||||
}
|
||||
|
||||
h3 {
|
||||
font-size: 1.2rem;
|
||||
color: #fff;
|
||||
margin-top: 25px;
|
||||
margin-bottom: 10px;
|
||||
text-transform: uppercase;
|
||||
}
|
||||
|
||||
p {
|
||||
font-size: 0.95rem;
|
||||
line-height: 1.6;
|
||||
color: #a3ffa3;
|
||||
margin-bottom: 15px;
|
||||
}
|
||||
|
||||
ol,
|
||||
ul {
|
||||
margin-left: 20px;
|
||||
margin-bottom: 15px;
|
||||
color: #a3ffa3;
|
||||
}
|
||||
|
||||
li {
|
||||
margin-bottom: 8px;
|
||||
line-height: 1.5;
|
||||
}
|
||||
|
||||
strong {
|
||||
color: #fff;
|
||||
text-shadow: 0 0 2px #00ff41;
|
||||
}
|
||||
|
||||
a {
|
||||
color: #fff;
|
||||
text-decoration: underline;
|
||||
}
|
||||
a:hover {
|
||||
color: #00ff41;
|
||||
}
|
||||
|
||||
/* --- Linktree-Clients & App-Links --- */
|
||||
.linktree-container {
|
||||
max-width: 600px;
|
||||
margin: 0 auto;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
gap: 15px;
|
||||
margin-bottom: 30px;
|
||||
}
|
||||
|
||||
.linktree-btn {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
gap: 12px;
|
||||
width: 100%;
|
||||
padding: 16px 20px;
|
||||
background: transparent;
|
||||
border: 2px solid #00ff41;
|
||||
color: #00ff41;
|
||||
text-decoration: none;
|
||||
font-size: 1.1rem;
|
||||
font-weight: bold;
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 2px;
|
||||
border-radius: 4px;
|
||||
transition: all 0.3s ease;
|
||||
box-shadow: inset 0 0 0 0 rgba(0, 255, 65, 0.2);
|
||||
}
|
||||
|
||||
.linktree-btn img {
|
||||
height: 24px;
|
||||
width: auto;
|
||||
object-fit: contain;
|
||||
filter: invert(53%) sepia(93%) saturate(1353%) hue-rotate(87deg)
|
||||
brightness(119%) contrast(119%);
|
||||
transition: all 0.3s ease;
|
||||
}
|
||||
|
||||
.linktree-btn:hover {
|
||||
background: #00ff41;
|
||||
color: #000;
|
||||
box-shadow: 0 0 15px #00ff41;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.linktree-btn:hover img {
|
||||
filter: invert(0%) brightness(0%);
|
||||
}
|
||||
|
||||
/* Mobile Download Bereich */
|
||||
.app-download-box {
|
||||
background: rgba(0, 20, 0, 0.4);
|
||||
border: 1px dashed #00ff41;
|
||||
border-radius: 4px;
|
||||
padding: 20px;
|
||||
margin-top: 20px;
|
||||
}
|
||||
|
||||
.app-row {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
gap: 15px;
|
||||
padding: 15px 0;
|
||||
}
|
||||
|
||||
.app-row:not(:last-child) {
|
||||
border-bottom: 1px solid rgba(0, 255, 65, 0.2);
|
||||
}
|
||||
|
||||
.app-info {
|
||||
flex: 1;
|
||||
min-width: 200px;
|
||||
}
|
||||
|
||||
.app-name {
|
||||
font-weight: bold;
|
||||
color: #fff;
|
||||
font-size: 1.1rem;
|
||||
}
|
||||
|
||||
.app-buttons {
|
||||
display: flex;
|
||||
gap: 10px;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
.app-btn {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
padding: 8px 16px;
|
||||
border: 1px solid #00ff41;
|
||||
color: #00ff41;
|
||||
text-decoration: none;
|
||||
font-size: 0.85rem;
|
||||
border-radius: 4px;
|
||||
text-transform: uppercase;
|
||||
transition: all 0.2s ease;
|
||||
}
|
||||
|
||||
.app-btn:hover {
|
||||
background: rgba(0, 255, 65, 0.2);
|
||||
color: #fff;
|
||||
box-shadow: 0 0 8px rgba(0, 255, 65, 0.5);
|
||||
}
|
||||
|
||||
/* --- Karten-Raster (Cards Grid) --- */
|
||||
.cards-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
|
||||
gap: 20px;
|
||||
margin-top: 15px;
|
||||
}
|
||||
|
||||
.card {
|
||||
background: rgba(0, 0, 0, 0.9);
|
||||
border: 1px solid #00ff41;
|
||||
border-radius: 4px;
|
||||
padding: 20px;
|
||||
transition: all 0.3s ease;
|
||||
}
|
||||
|
||||
.card:hover {
|
||||
transform: translateY(-3px);
|
||||
box-shadow: 0 0 15px rgba(0, 255, 65, 0.4);
|
||||
border-color: #fff;
|
||||
}
|
||||
|
||||
.card.full-width-card {
|
||||
grid-column: 1 / -1;
|
||||
}
|
||||
|
||||
/* Card title icons */
|
||||
.card-title {
|
||||
font-size: 1.15rem;
|
||||
color: #fff;
|
||||
margin-bottom: 10px;
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 1px;
|
||||
border-bottom: 1px dashed #00ff41;
|
||||
padding-bottom: 5px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
}
|
||||
.card-icon {
|
||||
height: 20px;
|
||||
width: auto;
|
||||
object-fit: contain;
|
||||
filter: invert(53%) sepia(93%) saturate(1353%) hue-rotate(87deg)
|
||||
brightness(119%) contrast(119%);
|
||||
flex-shrink: 0;
|
||||
}
|
||||
.card-title--highlight .card-icon {
|
||||
filter: invert(40%) sepia(80%) saturate(500%) hue-rotate(95deg) brightness(110%);
|
||||
}
|
||||
|
||||
.card-text {
|
||||
font-size: 0.9rem;
|
||||
line-height: 1.5;
|
||||
color: #a3ffa3;
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
/* --- Registrierungs-Widget --- */
|
||||
.reg-form {
|
||||
padding: 10px 0;
|
||||
margin-top: 15px;
|
||||
}
|
||||
|
||||
.reg-form label {
|
||||
display: block;
|
||||
font-size: 0.85rem;
|
||||
color: #00ff41;
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 1px;
|
||||
margin-bottom: 6px;
|
||||
}
|
||||
|
||||
.reg-form input {
|
||||
width: 100%;
|
||||
background: rgba(0, 0, 0, 0.8);
|
||||
border: 1px solid #00ff41;
|
||||
color: #fff;
|
||||
font-family: "Courier New", Courier, monospace;
|
||||
font-size: 1rem;
|
||||
padding: 10px 14px;
|
||||
border-radius: 3px;
|
||||
margin-bottom: 20px;
|
||||
outline: none;
|
||||
transition:
|
||||
border-color 0.2s,
|
||||
box-shadow 0.2s;
|
||||
}
|
||||
|
||||
.reg-form input:focus {
|
||||
border-color: #fff;
|
||||
box-shadow: 0 0 8px rgba(0, 255, 65, 0.4);
|
||||
}
|
||||
|
||||
.reg-submit {
|
||||
width: 100%;
|
||||
padding: 14px;
|
||||
background: transparent;
|
||||
border: 2px solid #00ff41;
|
||||
color: #00ff41;
|
||||
font-family: "Courier New", Courier, monospace;
|
||||
font-size: 1rem;
|
||||
font-weight: bold;
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 2px;
|
||||
border-radius: 3px;
|
||||
cursor: pointer;
|
||||
transition: all 0.3s ease;
|
||||
}
|
||||
|
||||
.reg-submit:hover:not(:disabled) {
|
||||
background: #00ff41;
|
||||
color: #000;
|
||||
box-shadow: 0 0 15px #00ff41;
|
||||
}
|
||||
|
||||
.reg-submit:disabled {
|
||||
opacity: 0.5;
|
||||
cursor: not-allowed;
|
||||
}
|
||||
|
||||
.reg-status {
|
||||
margin-top: 20px;
|
||||
padding: 15px;
|
||||
border-radius: 3px;
|
||||
font-size: 0.9rem;
|
||||
display: none;
|
||||
}
|
||||
|
||||
.reg-status.success {
|
||||
display: block;
|
||||
background: rgba(0, 255, 65, 0.1);
|
||||
border: 1px solid #00ff41;
|
||||
color: #a3ffa3;
|
||||
}
|
||||
|
||||
.reg-status.error {
|
||||
display: block;
|
||||
background: rgba(255, 0, 0, 0.1);
|
||||
border: 1px solid #ff0000;
|
||||
color: #ff9999;
|
||||
}
|
||||
|
||||
/* --- Warnungen / Alerts --- */
|
||||
.matrix-alert {
|
||||
background: rgba(255, 0, 0, 0.1);
|
||||
border: 1px solid #ff0000;
|
||||
color: #ff9999;
|
||||
padding: 20px;
|
||||
border-radius: 4px;
|
||||
margin-bottom: 25px;
|
||||
}
|
||||
.matrix-alert h3 {
|
||||
color: #ff3333;
|
||||
margin-bottom: 8px;
|
||||
margin-top: 0;
|
||||
}
|
||||
|
||||
/* --- Codex Tabellen-Styling --- */
|
||||
.codex-table {
|
||||
width: 100%;
|
||||
border-collapse: collapse;
|
||||
margin-top: 15px;
|
||||
font-size: 0.95rem;
|
||||
}
|
||||
|
||||
.codex-table th,
|
||||
.codex-table td {
|
||||
border: 1px solid #00ff41;
|
||||
padding: 12px;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.codex-table th {
|
||||
background: rgba(0, 255, 65, 0.15);
|
||||
color: #fff;
|
||||
text-transform: uppercase;
|
||||
}
|
||||
|
||||
.codex-table tr:nth-child(even) {
|
||||
background: rgba(0, 255, 65, 0.03);
|
||||
}
|
||||
|
||||
/* --- Footer --- */
|
||||
/* (styles moved to end of file) */
|
||||
|
||||
/* Fokus-Styles für Tastaturnavigation */
|
||||
a:focus-visible,
|
||||
button:focus-visible,
|
||||
input:focus-visible {
|
||||
outline: 2px solid #fff;
|
||||
outline-offset: 3px;
|
||||
box-shadow: 0 0 0 4px rgba(0, 255, 65, 0.4);
|
||||
}
|
||||
|
||||
/* Opacity-fix: sicherstellen dass gedimmter Text ausreichend Kontrast hat */
|
||||
.app-info p {
|
||||
opacity: 1;
|
||||
color: #a3ffa3;
|
||||
}
|
||||
|
||||
/* Glitch Animations-Effekt */
|
||||
@keyframes glitch {
|
||||
0% {
|
||||
text-shadow:
|
||||
2px 2px 0px #ff0000,
|
||||
-2px -2px 0px #0000ff;
|
||||
}
|
||||
50% {
|
||||
text-shadow:
|
||||
-2px 2px 0px #00ff41,
|
||||
2px -2px 0px #ff0000;
|
||||
}
|
||||
100% {
|
||||
text-shadow:
|
||||
2px -2px 0px #0000ff,
|
||||
-2px 2px 0px #00ff41;
|
||||
}
|
||||
}
|
||||
|
||||
/* Animationen deaktivieren für Nutzer die das bevorzugen */
|
||||
@media (prefers-reduced-motion: reduce) {
|
||||
h1 {
|
||||
animation: none;
|
||||
text-shadow: 0 0 10px #00ff41;
|
||||
}
|
||||
#matrix-bg {
|
||||
display: none;
|
||||
}
|
||||
*,
|
||||
*::before,
|
||||
*::after {
|
||||
transition: none !important;
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 768px) {
|
||||
.container {
|
||||
padding: 20px 14px;
|
||||
}
|
||||
h1 {
|
||||
font-size: 2rem;
|
||||
letter-spacing: 2px;
|
||||
}
|
||||
h2 {
|
||||
font-size: 1.2rem;
|
||||
letter-spacing: 1px;
|
||||
}
|
||||
h3 {
|
||||
font-size: 1rem;
|
||||
}
|
||||
section {
|
||||
padding: 14px 16px 20px;
|
||||
margin-bottom: 30px;
|
||||
}
|
||||
.cards-grid {
|
||||
grid-template-columns: 1fr;
|
||||
}
|
||||
.linktree-btn {
|
||||
font-size: 0.95rem;
|
||||
padding: 14px 16px;
|
||||
letter-spacing: 1px;
|
||||
}
|
||||
.codex-table {
|
||||
font-size: 0.82rem;
|
||||
display: block;
|
||||
overflow-x: auto;
|
||||
-webkit-overflow-scrolling: touch;
|
||||
}
|
||||
.codex-table th,
|
||||
.codex-table td {
|
||||
padding: 8px 10px;
|
||||
white-space: nowrap;
|
||||
}
|
||||
.app-row {
|
||||
flex-direction: column;
|
||||
align-items: flex-start;
|
||||
}
|
||||
.app-buttons {
|
||||
width: 100%;
|
||||
}
|
||||
.app-btn {
|
||||
flex: 1;
|
||||
justify-content: center;
|
||||
}
|
||||
.advanced-separator {
|
||||
margin: 30px 0 20px 0;
|
||||
padding: 14px 16px;
|
||||
}
|
||||
.abstract {
|
||||
padding: 12px 14px;
|
||||
margin-bottom: 24px;
|
||||
}
|
||||
}
|
||||
|
||||
/* --- Abstract Block --- */
|
||||
.abstract {
|
||||
border-left: 3px solid #00aa41;
|
||||
padding: 16px 20px;
|
||||
margin: 0 0 40px 0;
|
||||
background: rgba(0, 170, 65, 0.05);
|
||||
border-radius: 0 4px 4px 0;
|
||||
}
|
||||
.abstract p {
|
||||
margin: 0;
|
||||
color: #a3ffa3;
|
||||
line-height: 1.7;
|
||||
}
|
||||
|
||||
/* --- Fortgeschrittenen-Trennbereich --- */
|
||||
.advanced-separator {
|
||||
border-left: 3px solid #5a7a5a;
|
||||
border-radius: 0 4px 4px 0;
|
||||
background: rgba(0, 170, 65, 0.03);
|
||||
padding: 16px 20px;
|
||||
margin: 48px 0 32px 0;
|
||||
}
|
||||
.advanced-separator h2 {
|
||||
margin: 0 0 8px 0;
|
||||
font-size: 1rem;
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 0.12em;
|
||||
color: #5a7a5a;
|
||||
border-bottom: none;
|
||||
text-shadow: none;
|
||||
padding-bottom: 0;
|
||||
}
|
||||
.advanced-separator p {
|
||||
margin: 0;
|
||||
color: #5a7a5a;
|
||||
font-size: 0.9rem;
|
||||
line-height: 1.6;
|
||||
}
|
||||
|
||||
/* --- Hilfsklassen für inline-style Ersatz --- */
|
||||
.card--highlight {
|
||||
border-color: #00aa41;
|
||||
}
|
||||
.card-title--highlight {
|
||||
color: #00aa41;
|
||||
}
|
||||
.card--warning {
|
||||
border-color: #ff9900;
|
||||
background: rgba(20, 10, 0, 0.6);
|
||||
}
|
||||
.card-title--warning {
|
||||
color: #ff9900;
|
||||
}
|
||||
.text--danger {
|
||||
color: #ff3333;
|
||||
text-shadow: none;
|
||||
}
|
||||
.honeypot {
|
||||
position: absolute;
|
||||
left: -9999px;
|
||||
width: 1px;
|
||||
height: 1px;
|
||||
overflow: hidden;
|
||||
visibility: hidden;
|
||||
pointer-events: none;
|
||||
}
|
||||
.code--white {
|
||||
color: #fff;
|
||||
}
|
||||
.mt-20 {
|
||||
margin-top: 20px;
|
||||
}
|
||||
.mt-28 {
|
||||
margin-top: 28px;
|
||||
}
|
||||
|
||||
/* App store button icons */
|
||||
.app-btn img {
|
||||
height: 18px;
|
||||
width: auto;
|
||||
object-fit: contain;
|
||||
filter: invert(53%) sepia(93%) saturate(1353%) hue-rotate(87deg)
|
||||
brightness(119%) contrast(119%);
|
||||
transition: filter 0.2s ease;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
.app-btn:hover img {
|
||||
filter: invert(100%) brightness(200%);
|
||||
}
|
||||
|
||||
/* Footer matrix style */
|
||||
footer {
|
||||
text-align: center;
|
||||
padding: 20px;
|
||||
background: rgba(0, 5, 0, 0.9);
|
||||
border-top: 1px dashed #00ff41;
|
||||
font-size: 0.8rem;
|
||||
color: rgba(0, 255, 65, 0.7);
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
letter-spacing: 1px;
|
||||
}
|
||||
.footer-line {
|
||||
color: rgba(0, 255, 65, 0.35);
|
||||
margin-bottom: 4px;
|
||||
}
|
||||
.footer-credit {
|
||||
color: rgba(0, 255, 65, 0.7);
|
||||
letter-spacing: 0.15em;
|
||||
}
|
||||
.footer-credit span {
|
||||
color: #00ff41;
|
||||
text-shadow: 0 0 6px #00ff41;
|
||||
}
|
||||
+201
-27
@@ -1,21 +1,75 @@
|
||||
{
|
||||
config,
|
||||
pkgs,
|
||||
lib,
|
||||
...
|
||||
}:
|
||||
let
|
||||
wellKnownMatrix = {
|
||||
"= /.well-known/matrix/client" = {
|
||||
extraConfig = ''
|
||||
default_type application/json;
|
||||
add_header Access-Control-Allow-Origin *;
|
||||
return 200 '{"m.homeserver":{"base_url":"https://matrix.cyperpunk.de"},"org.matrix.msc4143.rtc_foci":[{"type":"livekit","livekit_service_url":"https://cyperpunk.de/livekit/jwt/"}]}';
|
||||
'';
|
||||
};
|
||||
"= /.well-known/matrix/server" = {
|
||||
extraConfig = ''
|
||||
default_type application/json;
|
||||
add_header Access-Control-Allow-Origin *;
|
||||
return 200 '{"m.server":"matrix.cyperpunk.de:443"}';
|
||||
'';
|
||||
};
|
||||
};
|
||||
|
||||
synapseAdmin = pkgs.ketesa.withConfig {
|
||||
restrictBaseUrl = [ "https://matrix.cyperpunk.de" ];
|
||||
loginFlows = [ "password" ];
|
||||
};
|
||||
|
||||
matrixIndexHtml = pkgs.writeText "matrix-index.html" (builtins.readFile ./index.html);
|
||||
matrixRegisterPhp = pkgs.writeText "matrix-register.php" (builtins.readFile ./register.php);
|
||||
matrixStyleCss = pkgs.writeText "matrix-style.css" (builtins.readFile ./style.css);
|
||||
matrixAppJs = pkgs.writeText "matrix-app.js" (builtins.readFile ./app.js);
|
||||
in
|
||||
{
|
||||
|
||||
networking.firewall.allowedTCPPorts = [
|
||||
8008 # Matrix Synapse
|
||||
8448 # Matrix federation
|
||||
];
|
||||
|
||||
sops.secrets = {
|
||||
matrix_macaroon_secret = { };
|
||||
matrix_registration_secret = {
|
||||
owner = "matrix-synapse";
|
||||
group = "matrix-synapse";
|
||||
};
|
||||
pg_replication_password = {
|
||||
owner = "postgres";
|
||||
group = "postgres";
|
||||
};
|
||||
kanidm_synapse_secret = {
|
||||
owner = "matrix-synapse";
|
||||
group = "matrix-synapse";
|
||||
};
|
||||
};
|
||||
|
||||
systemd.tmpfiles.rules = [
|
||||
"d /var/www/matrix 0755 nginx nginx -"
|
||||
"L+ /var/www/matrix/index.html 0644 nginx nginx - ${matrixIndexHtml}"
|
||||
"L+ /var/www/matrix/register.php 0644 nginx nginx - ${matrixRegisterPhp}"
|
||||
"L+ /var/www/matrix/style.css 0644 nginx nginx - ${matrixStyleCss}"
|
||||
"L+ /var/www/matrix/app.js 0644 nginx nginx - ${matrixAppJs}"
|
||||
];
|
||||
|
||||
services.phpfpm.pools.matrix = {
|
||||
user = "nginx";
|
||||
group = "nginx";
|
||||
settings = {
|
||||
"listen.owner" = "nginx";
|
||||
"listen.group" = "nginx";
|
||||
"pm" = "dynamic";
|
||||
"pm.max_children" = 10;
|
||||
"pm.start_servers" = 2;
|
||||
"pm.min_spare_servers" = 1;
|
||||
"pm.max_spare_servers" = 3;
|
||||
};
|
||||
phpPackage = pkgs.php.withExtensions ({ enabled, all }: enabled ++ [ all.curl ]);
|
||||
};
|
||||
|
||||
services = {
|
||||
@@ -24,24 +78,43 @@
|
||||
settings = {
|
||||
server_name = "cyperpunk.de";
|
||||
public_baseurl = "https://matrix.cyperpunk.de";
|
||||
enable_registration = false; # TODO: disable
|
||||
enable_registration_without_verification = false;
|
||||
enable_registration = false;
|
||||
trusted_key_servers = [ { server_name = "matrix.org"; } ];
|
||||
suppress_key_server_warning = true;
|
||||
registration_shared_secret_path = config.sops.secrets.matrix_registration_secret.path;
|
||||
macaroon_secret_key = "$__file{${config.sops.secrets.matrix_macaroon_secret.path}}";
|
||||
experimental_features = {
|
||||
"msc3266_enabled" = true;
|
||||
"msc3779_enabled" = true;
|
||||
"msc3401_enabled" = true;
|
||||
"msc4143_enabled" = true;
|
||||
"msc4195_enabled" = true;
|
||||
"msc4222_enabled" = true;
|
||||
matrix_rtc = {
|
||||
enabled = true;
|
||||
transports = [
|
||||
{
|
||||
type = "livekit";
|
||||
livekit_service_url = "https://cyperpunk.de/livekit/jwt/";
|
||||
}
|
||||
];
|
||||
};
|
||||
|
||||
rc_login = {
|
||||
address = {
|
||||
per_second = 0.17;
|
||||
burst_count = 10;
|
||||
};
|
||||
account = {
|
||||
per_second = 0.17;
|
||||
burst_count = 10;
|
||||
};
|
||||
failed_attempts = {
|
||||
per_second = 0.17;
|
||||
burst_count = 10;
|
||||
};
|
||||
};
|
||||
|
||||
listeners = [
|
||||
{
|
||||
port = 8008;
|
||||
bind_addresses = [ "0.0.0.0" ];
|
||||
bind_addresses = [
|
||||
"127.0.0.1"
|
||||
"::1"
|
||||
];
|
||||
type = "http";
|
||||
tls = false;
|
||||
x_forwarded = true;
|
||||
@@ -52,7 +125,7 @@
|
||||
"federation"
|
||||
"openid"
|
||||
];
|
||||
compress = false;
|
||||
compress = true;
|
||||
}
|
||||
];
|
||||
}
|
||||
@@ -60,20 +133,92 @@
|
||||
port = 9009;
|
||||
tls = false;
|
||||
type = "metrics";
|
||||
bind_addresses = [ "127.0.0.1" ];
|
||||
bind_addresses = [
|
||||
"127.0.0.1"
|
||||
"100.109.10.91"
|
||||
];
|
||||
resources = [ ];
|
||||
}
|
||||
];
|
||||
matrix_rtc = {
|
||||
enabled = true;
|
||||
transports = [
|
||||
{
|
||||
type = "livekit";
|
||||
livekit_service_url = "https://cyperpunk.de/livekit/jwt/";
|
||||
}
|
||||
];
|
||||
};
|
||||
enable_metrics = true;
|
||||
|
||||
oidc_providers = [
|
||||
{
|
||||
idp_id = "kanidm";
|
||||
idp_name = "Kanidm";
|
||||
issuer = "https://auth.cyperpunk.de/oauth2/openid/synapse";
|
||||
client_id = "synapse";
|
||||
client_secret_path = config.sops.secrets.kanidm_synapse_secret.path;
|
||||
scopes = [
|
||||
"openid"
|
||||
"profile"
|
||||
"email"
|
||||
];
|
||||
allow_existing_users = true;
|
||||
user_mapping_provider.config = {
|
||||
localpart_template = "{{ user.preferred_username.split('@')[0] }}";
|
||||
display_name_template = "{{ user.displayname }}";
|
||||
};
|
||||
}
|
||||
];
|
||||
};
|
||||
};
|
||||
|
||||
nginx.virtualHosts = {
|
||||
"cyperpunk.de" = {
|
||||
forceSSL = true;
|
||||
enableACME = true;
|
||||
serverAliases = [ "matrix.cyperpunk.de" ];
|
||||
http2 = true;
|
||||
locations = wellKnownMatrix // {
|
||||
"/_matrix".proxyPass = "http://127.0.0.1:8008";
|
||||
"/_synapse/client".proxyPass = "http://127.0.0.1:8008";
|
||||
"/_synapse/admin".proxyPass = "http://127.0.0.1:8008";
|
||||
"/metrics" = {
|
||||
proxyPass = "http://127.0.0.1:9009";
|
||||
extraConfig = ''
|
||||
allow 127.0.0.1;
|
||||
deny all;
|
||||
'';
|
||||
};
|
||||
"/admin/" = {
|
||||
alias = "${synapseAdmin}/";
|
||||
tryFiles = "$uri $uri/ /admin/index.html";
|
||||
};
|
||||
"^~ /livekit/jwt/" = {
|
||||
priority = 400;
|
||||
proxyPass = "http://127.0.0.1:${toString config.services.lk-jwt-service.port}/";
|
||||
};
|
||||
"^~ /livekit/sfu/" = {
|
||||
priority = 400;
|
||||
proxyPass = "http://127.0.0.1:${toString config.services.livekit.settings.port}/";
|
||||
proxyWebsockets = true;
|
||||
extraConfig = ''
|
||||
proxy_send_timeout 120;
|
||||
proxy_read_timeout 120;
|
||||
proxy_buffering off;
|
||||
proxy_set_header Accept-Encoding gzip;
|
||||
proxy_set_header Upgrade $http_upgrade;
|
||||
proxy_set_header Connection "upgrade";
|
||||
'';
|
||||
};
|
||||
"/" = {
|
||||
root = "/var/www/matrix";
|
||||
extraConfig = ''
|
||||
index index.html;
|
||||
try_files $uri $uri/ =404;
|
||||
'';
|
||||
};
|
||||
"~ \\.php$" = {
|
||||
root = "/var/www/matrix";
|
||||
extraConfig = ''
|
||||
fastcgi_pass unix:${config.services.phpfpm.pools.matrix.socket};
|
||||
fastcgi_index index.php;
|
||||
include ${pkgs.nginx}/conf/fastcgi_params;
|
||||
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
|
||||
'';
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
@@ -81,11 +226,40 @@
|
||||
enable = true;
|
||||
initialScript = pkgs.writeText "synapse-init.sql" ''
|
||||
CREATE ROLE "matrix-synapse" WITH LOGIN PASSWORD 'synapse';
|
||||
CREATE ROLE replicator WITH REPLICATION LOGIN;
|
||||
CREATE DATABASE "matrix-synapse" WITH OWNER "matrix-synapse"
|
||||
TEMPLATE template0
|
||||
LC_COLLATE = "C"
|
||||
LC_CTYPE = "C";
|
||||
'';
|
||||
settings = {
|
||||
wal_level = "replica";
|
||||
max_wal_senders = 5;
|
||||
wal_keep_size = "512MB";
|
||||
listen_addresses = lib.mkForce "127.0.0.1,100.109.10.91";
|
||||
};
|
||||
authentication = lib.mkAfter ''
|
||||
host replication replicator 100.0.0.0/8 scram-sha-256
|
||||
'';
|
||||
};
|
||||
|
||||
prometheus.exporters.postgres = {
|
||||
enable = true;
|
||||
port = 9188;
|
||||
runAsLocalSuperUser = true;
|
||||
dataSourceName = "postgresql:///postgres?host=/run/postgresql&sslmode=disable";
|
||||
};
|
||||
};
|
||||
|
||||
systemd.services = {
|
||||
matrix-synapse.serviceConfig.ReadOnlyPaths = [
|
||||
"/var/lib/mautrix-discord"
|
||||
"/var/lib/mautrix-whatsapp"
|
||||
];
|
||||
postgresql.postStart = lib.mkAfter ''
|
||||
PG_PASS=$(cat ${config.sops.secrets.pg_replication_password.path})
|
||||
${config.services.postgresql.package}/bin/psql -U postgres -c \
|
||||
"ALTER ROLE replicator WITH PASSWORD '$PG_PASS';"
|
||||
'';
|
||||
};
|
||||
}
|
||||
|
||||
@@ -0,0 +1,30 @@
|
||||
{ ... }:
|
||||
{
|
||||
services.postgresql = {
|
||||
ensureUsers = [
|
||||
{
|
||||
name = "mautrix-whatsapp";
|
||||
ensureDBOwnership = true;
|
||||
}
|
||||
];
|
||||
ensureDatabases = [ "mautrix-whatsapp" ];
|
||||
};
|
||||
|
||||
services.mautrix-whatsapp = {
|
||||
enable = true;
|
||||
settings = {
|
||||
homeserver = {
|
||||
address = "http://127.0.0.1:8008";
|
||||
domain = "cyperpunk.de";
|
||||
};
|
||||
database = {
|
||||
type = "postgres";
|
||||
uri = "postgres:///mautrix-whatsapp?host=/run/postgresql&sslmode=disable";
|
||||
};
|
||||
bridge.permissions = {
|
||||
"cyperpunk.de" = "user";
|
||||
"@dergrumpf:cyperpunk.de" = "admin";
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
+83
-94
@@ -21,54 +21,28 @@ let
|
||||
"cyper-node-2" = "192.168.2.31";
|
||||
"cyper-proxy" = "178.254.8.35";
|
||||
};
|
||||
|
||||
mkWeatherScrapeConfigs =
|
||||
cities:
|
||||
map (city: {
|
||||
job_name = "weather_${lib.strings.toLower (lib.strings.replaceStrings [ " " ] [ "_" ] city)}";
|
||||
scrape_interval = "5m";
|
||||
scrape_timeout = "30s";
|
||||
metrics_path = "/${city}";
|
||||
params.format = [ "p1" ];
|
||||
static_configs = [ { targets = [ "wttr.in" ]; } ];
|
||||
scheme = "https";
|
||||
metric_relabel_configs = [
|
||||
{
|
||||
target_label = "location";
|
||||
replacement = city;
|
||||
}
|
||||
];
|
||||
}) cities;
|
||||
|
||||
weatherCities = [
|
||||
# Braunschweig itself
|
||||
"Braunschweig"
|
||||
|
||||
# Immediate surroundings (~15km)
|
||||
"Wolfenbuettel"
|
||||
"Salzgitter"
|
||||
"Peine"
|
||||
"Cremlingen"
|
||||
"Wendeburg"
|
||||
"Sickte"
|
||||
|
||||
# Greater region (~50km)
|
||||
"Wolfsburg"
|
||||
"Gifhorn"
|
||||
"Goslar"
|
||||
"Hildesheim"
|
||||
"Hannover"
|
||||
];
|
||||
in
|
||||
{
|
||||
|
||||
imports = [ ./gs-exporter.nix ];
|
||||
|
||||
sops.secrets = {
|
||||
grafana_secret_key = {
|
||||
owner = "grafana";
|
||||
group = "grafana";
|
||||
};
|
||||
|
||||
kanidm_grafana_secret = {
|
||||
owner = "grafana";
|
||||
group = "grafana";
|
||||
};
|
||||
zyxel_pass = {
|
||||
group = "gs1200-exporter";
|
||||
mode = "0440";
|
||||
};
|
||||
};
|
||||
|
||||
users.groups.gs1200-exporter = { };
|
||||
|
||||
services = {
|
||||
grafana = {
|
||||
enable = true;
|
||||
@@ -83,29 +57,46 @@ in
|
||||
url = "http://127.0.0.1:${toString config.services.prometheus.port}";
|
||||
isDefault = true;
|
||||
}
|
||||
{
|
||||
name = "Loki";
|
||||
type = "loki";
|
||||
url = "http://127.0.0.1:${toString config.services.loki.configuration.server.http_listen_port}";
|
||||
isDefault = false;
|
||||
}
|
||||
];
|
||||
};
|
||||
};
|
||||
settings = {
|
||||
server = {
|
||||
domain = "www.cyperpunk.de"; # serverIP; # "grafana.cyperpunk.de";
|
||||
domain = "www.cyperpunk.de";
|
||||
http_port = 2342;
|
||||
http_addr = "0.0.0.0";
|
||||
root_url = "http://www.cyperpunk.de/grafana/";
|
||||
root_url = "https://www.cyperpunk.de/grafana/";
|
||||
serve_from_sub_path = true;
|
||||
};
|
||||
security = {
|
||||
secret_key = "$__file{${config.sops.secrets.grafana_secret_key.path}}";
|
||||
allow_embedding = true;
|
||||
cookie_samesite = "none";
|
||||
cookie_secure = true;
|
||||
};
|
||||
auth = {
|
||||
disable_login_form = false;
|
||||
oauth_allow_insecure_email_lookup = true;
|
||||
};
|
||||
"auth.generic_oauth" = {
|
||||
enabled = true;
|
||||
name = "Kanidm";
|
||||
client_id = "grafana";
|
||||
client_secret = "$__file{${config.sops.secrets.kanidm_grafana_secret.path}}";
|
||||
scopes = "openid profile email";
|
||||
auth_url = "https://auth.cyperpunk.de/ui/oauth2";
|
||||
token_url = "https://auth.cyperpunk.de/oauth2/token";
|
||||
api_url = "https://auth.cyperpunk.de/oauth2/openid/grafana/userinfo";
|
||||
use_pkce = false;
|
||||
allow_sign_up = true;
|
||||
auto_assign_org = true;
|
||||
auto_assign_org_id = 1;
|
||||
auto_assign_org_role = "Admin";
|
||||
skip_org_role_sync = true;
|
||||
};
|
||||
"auth.anonymous" = {
|
||||
enabled = true;
|
||||
org_role = "Viewer";
|
||||
};
|
||||
};
|
||||
};
|
||||
@@ -134,59 +125,61 @@ in
|
||||
metrics_path = "/_synapse/metrics";
|
||||
static_configs = [
|
||||
{
|
||||
targets = [ "127.0.0.1:9009" ];
|
||||
targets = [ "100.109.10.91:9009" ];
|
||||
labels = {
|
||||
instance = config.networking.hostName;
|
||||
instance = "cyper-proxy";
|
||||
job = "master";
|
||||
index = "1";
|
||||
};
|
||||
}
|
||||
];
|
||||
}
|
||||
{
|
||||
job_name = "postgresql-replica";
|
||||
static_configs = [
|
||||
{
|
||||
targets = [ "localhost:9188" ];
|
||||
labels = {
|
||||
instance = config.networking.hostName;
|
||||
};
|
||||
}
|
||||
];
|
||||
}
|
||||
{
|
||||
job_name = "postgresql-proxy";
|
||||
static_configs = [
|
||||
{
|
||||
targets = [ "100.109.10.91:9188" ];
|
||||
labels = {
|
||||
instance = "cyper-proxy";
|
||||
};
|
||||
}
|
||||
];
|
||||
}
|
||||
{
|
||||
job_name = "gs1200-zyxel1";
|
||||
static_configs = [ { targets = [ "localhost:9934" ]; } ];
|
||||
}
|
||||
{
|
||||
job_name = "gs1200-zyxel2";
|
||||
static_configs = [ { targets = [ "localhost:9935" ]; } ];
|
||||
}
|
||||
]
|
||||
++ (lib.mapAttrsToList mkNodeJob extraNodes)
|
||||
++ (mkWeatherScrapeConfigs weatherCities);
|
||||
++ (lib.mapAttrsToList mkNodeJob extraNodes);
|
||||
};
|
||||
|
||||
loki = {
|
||||
enable = true;
|
||||
configuration = {
|
||||
auth_enabled = false;
|
||||
server.http_listen_port = 3100;
|
||||
ingester = {
|
||||
lifecycler = {
|
||||
address = "127.0.0.1";
|
||||
ring = {
|
||||
kvstore.store = "inmemory";
|
||||
replication_factor = 1;
|
||||
};
|
||||
};
|
||||
chunk_idle_period = "5m";
|
||||
chunk_retain_period = "30s";
|
||||
};
|
||||
schema_config.configs = [
|
||||
{
|
||||
from = "2024-01-01";
|
||||
store = "tsdb";
|
||||
object_store = "filesystem";
|
||||
schema = "v13";
|
||||
index = {
|
||||
prefix = "index_";
|
||||
period = "24h";
|
||||
};
|
||||
}
|
||||
];
|
||||
storage_config = {
|
||||
tsdb_shipper = {
|
||||
active_index_directory = "/var/lib/loki/tsdb-index";
|
||||
cache_location = "/var/lib/loki/tsdb-cache";
|
||||
};
|
||||
filesystem.directory = "/var/lib/loki/chunks";
|
||||
};
|
||||
limits_config = {
|
||||
reject_old_samples = true;
|
||||
reject_old_samples_max_age = "168h";
|
||||
};
|
||||
gs1200-exporter.instances = {
|
||||
zyxel1 = {
|
||||
address = "192.168.2.3";
|
||||
port = 9934;
|
||||
passwordFile = config.sops.secrets.zyxel_pass.path;
|
||||
group = "gs1200-exporter";
|
||||
};
|
||||
zyxel2 = {
|
||||
address = "192.168.2.4";
|
||||
port = 9935;
|
||||
passwordFile = config.sops.secrets.zyxel_pass.path;
|
||||
group = "gs1200-exporter";
|
||||
};
|
||||
};
|
||||
};
|
||||
@@ -196,8 +189,4 @@ in
|
||||
9001
|
||||
3100
|
||||
];
|
||||
|
||||
systemd.tmpfiles.rules = [
|
||||
"d /var/loki 0700 loki loki -"
|
||||
];
|
||||
}
|
||||
|
||||
+40
-297
@@ -1,4 +1,4 @@
|
||||
{ pkgs, lib, ... }:
|
||||
_:
|
||||
let
|
||||
upstream = "100.109.179.25";
|
||||
|
||||
@@ -20,214 +20,24 @@ let
|
||||
};
|
||||
};
|
||||
|
||||
matrixConfig = ''
|
||||
client_max_body_size 50M;
|
||||
proxy_set_header X-Forwarded-For $remote_addr;
|
||||
proxy_set_header X-Forwarded-Proto $scheme;
|
||||
proxy_set_header Host $host;
|
||||
'';
|
||||
|
||||
wellKnownMatrix = {
|
||||
"/.well-known/matrix/client" = {
|
||||
extraConfig = ''
|
||||
default_type application/json;
|
||||
add_header Access-Control-Allow-Origin *;
|
||||
return 200 '{
|
||||
"m.homeserver":{
|
||||
"base_url":"https://matrix.cyperpunk.de"
|
||||
},
|
||||
"org.matrix.msc4143.rtc_foci":[
|
||||
{
|
||||
"type":"livekit",
|
||||
"livekit_service_url":"https://cyperpunk.de/livekit/jwt/"
|
||||
}
|
||||
]
|
||||
}';
|
||||
'';
|
||||
};
|
||||
"/.well-known/matrix/server" = {
|
||||
extraConfig = ''
|
||||
default_type application/json;
|
||||
add_header Access-Control-Allow-Origin *;
|
||||
return 200 '{"m.server":"matrix.cyperpunk.de:443"}';
|
||||
'';
|
||||
mkHttpsProxy = port: {
|
||||
forceSSL = true;
|
||||
enableACME = true;
|
||||
locations."/" = {
|
||||
proxyPass = "https://${upstream}:${toString port}";
|
||||
extraConfig = "proxy_ssl_verify off;";
|
||||
};
|
||||
};
|
||||
|
||||
flavours = [
|
||||
{
|
||||
name = "Latte";
|
||||
slug = "latte";
|
||||
is_dark = false;
|
||||
}
|
||||
{
|
||||
name = "Frappé";
|
||||
slug = "frappe";
|
||||
is_dark = true;
|
||||
}
|
||||
{
|
||||
name = "Macchiato";
|
||||
slug = "macchiato";
|
||||
is_dark = true;
|
||||
}
|
||||
{
|
||||
name = "Mocha";
|
||||
slug = "mocha";
|
||||
is_dark = true;
|
||||
}
|
||||
];
|
||||
accents = [
|
||||
"rosewater"
|
||||
"flamingo"
|
||||
"pink"
|
||||
"mauve"
|
||||
"red"
|
||||
"maroon"
|
||||
"peach"
|
||||
"yellow"
|
||||
"green"
|
||||
"teal"
|
||||
"sky"
|
||||
"sapphire"
|
||||
"blue"
|
||||
"lavender"
|
||||
];
|
||||
themeHashes = {
|
||||
"latte/rosewater" = "0l1m4bhaxdam07rfqag6pjbzhdpyi5w3i14vp6rq7aj59pildw3a";
|
||||
"latte/flamingo" = "1m8hh2l87xv2rfgpnnl5vzddmam0n82h25fwadb37blgab08vhsr";
|
||||
"latte/pink" = "0ambrc42mvg0vdspfmnl31ka1nsxpdyv1p3nh045822y02q20wwh";
|
||||
"latte/mauve" = "1nnn2w6nsr24a45jy497c2vhi8v64bwg99fj2dyhpfsn89c63lhn";
|
||||
"latte/red" = "14lmw4c4llfz6zqvfymkc6k3msxcml2gwq9rhwsixdpc5mjjbn8n";
|
||||
"latte/maroon" = "0ydpng9451mpn7hv5ag1ck8hryx8pdvrml3zksvzm2fiwzzjkpcf";
|
||||
"latte/peach" = "1fn5804wv9z9iv65ikyv015b01a7c546rsaaks2a2sq2c37n75l0";
|
||||
"latte/yellow" = "0hzgiyhqmwgp3h3v1y23sx3x5qp712sw106472lbnxbywqlavcza";
|
||||
"latte/green" = "194kxv6d9hc4nixy16hy9nvf32qs3v214nr2r2qf2z9l89rk5pnp";
|
||||
"latte/teal" = "12n25d38zpqxsskglymhmza972klg2hj3c23v2nb3jfj82llw6v4";
|
||||
"latte/sky" = "0yghds3xpmbhkbcj2jkh8df82j6vrn9q1z0s2129nca7l5g5f9w2";
|
||||
"latte/sapphire" = "18dl1srxp3xccvvy56za6kp05n68d918l0wrxga11746g9sib7r3";
|
||||
"latte/blue" = "1zv9nap21d80flvd1jwmjph05jgykxngv5kqbhk95mvqh962ygnf";
|
||||
"latte/lavender" = "03j4fwbscip1qm6px1qxkha0c5csq2wwvzg9vwjkc2ja48v1mp9k";
|
||||
"frappe/rosewater" = "032qbgj32mvgpankl9777x2lxk18451kglsxg5215k8zrwcg9y95";
|
||||
"frappe/flamingo" = "1grhgynn8q7isv18981km5k8ll72ihsjw2ciy8widl6wikv29j8p";
|
||||
"frappe/pink" = "0h33g721bph8ihd6lmbc7szxy4dq85ng1cgg5cxjb5y2m7wpdbsy";
|
||||
"frappe/mauve" = "121jmznc9q3p7crsy9p2khw8xnzvz4lxms26g1h5wqa67wqvalc4";
|
||||
"frappe/red" = "07wm4h1giyy6a5nlh0d3qdarfsp6ikyr5nmg94n13lj4q03d0cn0";
|
||||
"frappe/maroon" = "08vg70nr918n4ffi1wnbba4xrx5ak5vfgq7m5ik0rpkb2wdb4x6k";
|
||||
"frappe/peach" = "1cg753w2dxs0sx97d8y0g62s8aw3w6b9hrll0lsrw3bc1bvm23fl";
|
||||
"frappe/yellow" = "0g43g2if1pcm25i261zfw43bawqqdlgg2f6q2bqhyqvafk9yb3dy";
|
||||
"frappe/green" = "1n71mndzds3zldb271g8hdw1yn29s68svzvh8ckjcsz4sb9h1i74";
|
||||
"frappe/teal" = "0b6m9cibfwf8csh1pk5i76xi3wx3v2aqwgffzsidw8nwc7c1a3wk";
|
||||
"frappe/sky" = "1l4d44399ixshlc9fdsx7iqwxm6kdkp6k4z3z6bdyyx6adw3z4q5";
|
||||
"frappe/sapphire" = "03fa9rnclvs5ljd0lzz15vnkzpqpbrhfppg3zwfchs9fvak0n3ni";
|
||||
"frappe/blue" = "0r4jjn3pab77w1aanlv3143ch60400q44mdzaqmcjbcr6l2knmjh";
|
||||
"frappe/lavender" = "1mrkaz72w6j9hh4dpxwgd6ks5wsnq9ydgy6f9gms4jx1611aab96";
|
||||
"macchiato/rosewater" = "001akfnhlvwaiz5faahl4qi0qp6as6ilvkbja6bjy9f5iasr4ygp";
|
||||
"macchiato/flamingo" = "06xq3pbx4cb3pyblx2vydr4bp0ylm7866d66agg5wg5qnr356wb3";
|
||||
"macchiato/pink" = "1hb32dj0n3wx4f1wxa4n7fib2mazghwsg2ljycza9macfn2n87qn";
|
||||
"macchiato/mauve" = "1yrnp162blizc10fz2n6ls1x0di1sdjk53vpsl7mifrkcr1k2nq7";
|
||||
"macchiato/red" = "1g9s39q7459lk830vhdrfqkbzz88p3fp8k98a2ygj2hz8sycpryq";
|
||||
"macchiato/maroon" = "0ad7rx8sbkygvsgywhpjvvzmyflyhz7jlm13dr7cxj3801rxhl6d";
|
||||
"macchiato/peach" = "1m5m6afcl8s1ghn2b9n1d20fhsygnhgn0205nhpxh4bih3kg8c8m";
|
||||
"macchiato/yellow" = "0zcc26d28jaq71mz8nqssz8p0hylczirjwjxr2dkha1133vjmvy5";
|
||||
"macchiato/green" = "055xdb5jilp5fq3a1g8773rv52zr68fp4l3hs56yj6dy3bq3q22v";
|
||||
"macchiato/teal" = "1sfci2g2nvmj0v72gnxqbj0k8053qz0rl6iphfxs3pgpi1b0rczq";
|
||||
"macchiato/sky" = "0vhfmdliy8cbb0vqq3v26isvcz4sxzq0xrb4p5a6gibvxaqi6bf3";
|
||||
"macchiato/sapphire" = "1744jiv57aqz4qi52n92nrx0s1rhylgg08qqc31jr2clk9h6bw18";
|
||||
"macchiato/blue" = "1arp8r2g8ivs1xipq39d3l6cvx0zrr1vwv9yac5j33d6c93wbb2i";
|
||||
"macchiato/lavender" = "0kak1f574c07gqjfafg3w5avrci584iqxjkmvrl2pv1879g84nn3";
|
||||
"mocha/rosewater" = "0p3ck9crskrhk1za6knaznjlj464mx4sdkkadna6k2152m3czjpz";
|
||||
"mocha/flamingo" = "04xx1mky230saqxxqin2fph8cnnz1jhmvb9qd9f5yc3pai3q5wdw";
|
||||
"mocha/pink" = "1cj9zdd72vcc45ziav625yq6hrp1zw21f7xsic0ip065xcqzdl3p";
|
||||
"mocha/mauve" = "1wb0ibmdv6vn07bk570pikm43qdxj3n2zsqr5sip17ay05j5l6dm";
|
||||
"mocha/red" = "1mnzrk57ar2cphyi2ry2lg5ilmb26gm4pr7ixch2ls0hk8ilp9p9";
|
||||
"mocha/maroon" = "1mcpwz3yrg3kk0hkqv5nykxj07bm70403yyl8r60pqlh74dnhkbf";
|
||||
"mocha/peach" = "0jglpcs41rfqxcm45mvnbdqhma0bv4h07nc7c3nrwz3g3h2djmzr";
|
||||
"mocha/yellow" = "0jqkvcjiwid1zdvrj2ikqf5winm08qyd51nfsawfdspbfhqnzmis";
|
||||
"mocha/green" = "0bg0014a77yx7f2r6n4mxm7rqgdnymqq7cq6bvpgkfk2z1gyr38l";
|
||||
"mocha/teal" = "0kzvi3gfirpcxdhgsilm51lk3j1z6lavb7160chgd9jhzk0xg97c";
|
||||
"mocha/sky" = "057nmp2aywdxzrkmzi65bh2mvf1a9cnri0g0jdyzdnrn7f8bbsiw";
|
||||
"mocha/sapphire" = "0nfklzb0a7mxv6nzav7m2g0y9plm72vwadm06445myv3k9j3ffmj";
|
||||
"mocha/blue" = "06ay46x2aq1q5ghz2zhzhn6qyqkrrf4p9j59qywnxh1jvv728ns8";
|
||||
"mocha/lavender" = "0iip063f6km17998c7ak0lb3kq6iskyi3xv2phn618mhslnxhwm5";
|
||||
};
|
||||
catppuccinThemes = lib.concatMap (
|
||||
flavour:
|
||||
map (
|
||||
accent:
|
||||
builtins.fromJSON (
|
||||
builtins.readFile (
|
||||
pkgs.fetchurl {
|
||||
url = "https://element.catppuccin.com/${flavour.slug}/${accent}.json";
|
||||
sha256 = themeHashes."${flavour.slug}/${accent}";
|
||||
}
|
||||
)
|
||||
)
|
||||
) accents
|
||||
) flavours;
|
||||
|
||||
elementConfig = builtins.toFile "element-config.json" (
|
||||
builtins.toJSON {
|
||||
default_server_config = {
|
||||
"m.homeserver" = {
|
||||
base_url = "https://matrix.cyperpunk.de";
|
||||
server_name = "cyperpunk.de";
|
||||
};
|
||||
};
|
||||
jitsi.preferred_domain = "jitsi.cyperpunk.de";
|
||||
element_call = {
|
||||
url = "https://element-call.cyperpunk.de";
|
||||
use_exclusively = true;
|
||||
participant_limit = 8;
|
||||
brand = "Cyperpunk Call";
|
||||
encryption = "None";
|
||||
};
|
||||
livekit.livekit_service_url = "https://cyperpunk.de/livekit/jwt/";
|
||||
setting_defaults = {
|
||||
custom_themes = catppuccinThemes;
|
||||
feature_custom_themes = true;
|
||||
};
|
||||
features = {
|
||||
feature_group_calls = true;
|
||||
feature_disable_call_per_sender_encryption = true;
|
||||
feature_sliding_sync = true;
|
||||
};
|
||||
}
|
||||
);
|
||||
|
||||
elementWebConfigured = pkgs.element-web.overrideAttrs (old: {
|
||||
postInstall = (old.postInstall or "") + ''
|
||||
cp ${elementConfig} $out/config.json
|
||||
'';
|
||||
});
|
||||
|
||||
synapseAdmin = pkgs.ketesa.withConfig {
|
||||
restrictBaseUrl = [ "https://matrix.cyperpunk.de" ];
|
||||
loginFlows = [ "password" ];
|
||||
};
|
||||
|
||||
elementCallConfigured = pkgs.element-call.overrideAttrs (old: {
|
||||
postInstall = (old.postInstall or "") + ''
|
||||
cp ${
|
||||
builtins.toFile "element-call-config.json" (
|
||||
builtins.toJSON {
|
||||
default_server_config = {
|
||||
"m.homeserver" = {
|
||||
base_url = "https://matrix.cyperpunk.de";
|
||||
server_name = "cyperpunk.de";
|
||||
};
|
||||
};
|
||||
livekit_service_url = "https://cyperpunk.de/livekit/jwt/";
|
||||
e2ee.default = false;
|
||||
}
|
||||
)
|
||||
} $out/config.json
|
||||
'';
|
||||
});
|
||||
in
|
||||
{
|
||||
networking.firewall.allowedTCPPorts = [
|
||||
80
|
||||
443
|
||||
12222
|
||||
];
|
||||
|
||||
systemd.tmpfiles.rules = [
|
||||
"d /var/www/home.cyperpunk.de 0755 nginx nginx -"
|
||||
];
|
||||
|
||||
security.acme = {
|
||||
@@ -242,14 +52,38 @@ in
|
||||
recommendedOptimisation = true;
|
||||
recommendedGzipSettings = true;
|
||||
|
||||
# Git ssh
|
||||
streamConfig = ''
|
||||
server {
|
||||
listen 12222;
|
||||
proxy_pass ${upstream}:12222;
|
||||
}
|
||||
'';
|
||||
|
||||
virtualHosts = {
|
||||
# controller services
|
||||
"git.cyperpunk.de" = mkProxy 9000;
|
||||
# controller services (proxied to upstream tailscale node)
|
||||
"git.cyperpunk.de" = (mkProxy 9000) // {
|
||||
extraConfig = ''
|
||||
client_max_body_size 500m;
|
||||
'';
|
||||
};
|
||||
"search.cyperpunk.de" = mkProxy 11080;
|
||||
"file.cyperpunk.de" = mkProxy 10000;
|
||||
"ngx.cyperpunk.de" = mkWsProxy 28101;
|
||||
"vault.cyperpunk.de" = mkWsProxy 8222;
|
||||
"calvin.cyperpunk.de" = mkWsProxy 15006;
|
||||
"auth.cyperpunk.de" = mkHttpsProxy 8444;
|
||||
|
||||
#"home.cyperpunk.de" = {
|
||||
# forceSSL = true;
|
||||
# enableACME = true;
|
||||
# locations."/" = {
|
||||
# root = "/var/www/home.cyperpunk.de";
|
||||
# extraConfig = ''
|
||||
# try_files $uri $uri/ =404;
|
||||
# '';
|
||||
# };
|
||||
#};
|
||||
|
||||
"www.cyperpunk.de" = {
|
||||
forceSSL = true;
|
||||
@@ -262,104 +96,13 @@ in
|
||||
"/grafana" = {
|
||||
proxyPass = "http://${upstream}:2342";
|
||||
proxyWebsockets = true;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
# local static clients
|
||||
"cinny.cyperpunk.de" = {
|
||||
forceSSL = true;
|
||||
enableACME = true;
|
||||
root = "${pkgs.cinny}";
|
||||
};
|
||||
|
||||
"element.cyperpunk.de" = {
|
||||
forceSSL = true;
|
||||
enableACME = true;
|
||||
root = "${elementWebConfigured}";
|
||||
};
|
||||
|
||||
"element-call.cyperpunk.de" = {
|
||||
forceSSL = true;
|
||||
enableACME = true;
|
||||
root = "${elementCallConfigured}";
|
||||
extraConfig = ''
|
||||
add_header Cross-Origin-Opener-Policy "same-origin";
|
||||
add_header Cross-Origin-Embedder-Policy "require-corp";
|
||||
add_header Cross-Origin-Resource-Policy "cross-origin";
|
||||
'';
|
||||
};
|
||||
|
||||
"fluffy.cyperpunk.de" = {
|
||||
forceSSL = true;
|
||||
enableACME = true;
|
||||
locations."/" = {
|
||||
proxyPass = "http://127.0.0.1:8082";
|
||||
proxyWebsockets = true;
|
||||
};
|
||||
};
|
||||
|
||||
"admin.cyperpunk.de" = {
|
||||
forceSSL = true;
|
||||
enableACME = true;
|
||||
root = "${synapseAdmin}";
|
||||
};
|
||||
|
||||
# matrix + livekit
|
||||
"cyperpunk.de" = {
|
||||
forceSSL = true;
|
||||
enableACME = true;
|
||||
serverAliases = [ "matrix.cyperpunk.de" ];
|
||||
http2 = true;
|
||||
extraConfig = matrixConfig;
|
||||
locations = wellKnownMatrix // {
|
||||
"/" = {
|
||||
proxyPass = "http://127.0.0.1:8008";
|
||||
proxyWebsockets = true;
|
||||
};
|
||||
"^~ /livekit/jwt/" = {
|
||||
priority = 400;
|
||||
proxyPass = "http://127.0.0.1:18080/";
|
||||
};
|
||||
"^~ /livekit/sfu/" = {
|
||||
priority = 400;
|
||||
proxyPass = "http://127.0.0.1:7880/";
|
||||
proxyWebsockets = true;
|
||||
extraConfig = ''
|
||||
proxy_set_header Host $host;
|
||||
proxy_set_header X-Real-IP $remote_addr;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
proxy_set_header X-Forwarded-Proto $scheme;
|
||||
proxy_read_timeout 86400s;
|
||||
proxy_send_timeout 86400s;
|
||||
'';
|
||||
};
|
||||
"/_matrix/client/unstable/org.matrix.msc4143/rtc/transports" = {
|
||||
extraConfig = ''
|
||||
default_type application/json;
|
||||
add_header Access-Control-Allow-Origin *;
|
||||
add_header Access-Control-Allow-Headers "Authorization, Content-Type";
|
||||
add_header Access-Control-Allow-Methods "GET, OPTIONS";
|
||||
return 200 '{"rtc_transports":[{"type":"livekit","livekit_service_url":"https://cyperpunk.de/livekit/jwt/"}]}';
|
||||
add_header X-Frame-Options "";
|
||||
add_header Content-Security-Policy "frame-ancestors *";
|
||||
'';
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
virtualisation.oci-containers.containers.fluffychat = {
|
||||
image = "ghcr.io/krille-chan/fluffychat:latest";
|
||||
ports = [ "127.0.0.1:8082:80" ];
|
||||
volumes = [
|
||||
"${
|
||||
builtins.toFile "fluffychat-config.json" (
|
||||
builtins.toJSON {
|
||||
default_homeserver = "matrix.cyperpunk.de";
|
||||
preset_homeserver = "matrix.cyperpunk.de";
|
||||
}
|
||||
)
|
||||
}:/app/config.json:ro"
|
||||
];
|
||||
};
|
||||
}
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
_: {
|
||||
services.ollama = {
|
||||
enable = true;
|
||||
|
||||
host = "0.0.0.0";
|
||||
port = 11434;
|
||||
|
||||
openFirewall = true;
|
||||
|
||||
loadModels = [
|
||||
"llama3.2:3b"
|
||||
"qwen2.5:3b"
|
||||
"deepseek-r1:1.5b"
|
||||
"gemma4:e2b"
|
||||
];
|
||||
|
||||
syncModels = true;
|
||||
|
||||
environmentVariables = {
|
||||
OLLAMA_CONTEXT_LENGTH = "16384";
|
||||
};
|
||||
};
|
||||
}
|
||||
@@ -1,9 +1,15 @@
|
||||
{ config, ... }:
|
||||
{
|
||||
|
||||
sops.secrets.paperless_admin = {
|
||||
owner = "paperless";
|
||||
sops.secrets = {
|
||||
paperless_admin = {
|
||||
owner = "paperless";
|
||||
};
|
||||
paperless_oidc_secret = {
|
||||
owner = "paperless";
|
||||
};
|
||||
};
|
||||
|
||||
services.paperless = {
|
||||
enable = true;
|
||||
address = "0.0.0.0";
|
||||
@@ -23,6 +29,7 @@
|
||||
];
|
||||
PAPERLESS_OCR_LANGUAGE = "deu+eng";
|
||||
PAPERLESS_CONSUMER_POLLING = 60;
|
||||
PAPERLESS_APPS = "allauth.socialaccount.providers.openid_connect";
|
||||
};
|
||||
|
||||
exporter = {
|
||||
@@ -41,9 +48,14 @@
|
||||
"d /storage/backup/paperless 0775 root users -"
|
||||
];
|
||||
|
||||
services.paperless-scheduler = {
|
||||
after = [ "systemd-tmpfiles-setup.service" ];
|
||||
requires = [ "systemd-tmpfiles-setup.service" ];
|
||||
services = {
|
||||
paperless-scheduler = {
|
||||
after = [ "systemd-tmpfiles-setup.service" ];
|
||||
requires = [ "systemd-tmpfiles-setup.service" ];
|
||||
};
|
||||
paperless-web = {
|
||||
serviceConfig.EnvironmentFiles = [ config.sops.secrets.paperless_oidc_secret.path ];
|
||||
};
|
||||
};
|
||||
};
|
||||
networking.firewall.allowedTCPPorts = [ 28101 ];
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
{ pkgs, ... }:
|
||||
|
||||
{
|
||||
nixpkgs.config.allowUnfree = true;
|
||||
|
||||
services.unifi = {
|
||||
enable = true;
|
||||
unifiPackage = pkgs.unifi;
|
||||
|
||||
@@ -0,0 +1,374 @@
|
||||
/* ===== Catppuccin for Vaultwarden ===== */
|
||||
/* Light: Latte | Dark: Mocha */
|
||||
|
||||
:root {
|
||||
/* ---------- Palette ---------- */
|
||||
--ctp-rosewater: #dc8a78;
|
||||
--ctp-flamingo: #dd7878;
|
||||
--ctp-pink: #ea76cb;
|
||||
--ctp-mauve: #8839ef;
|
||||
--ctp-red: #d20f39;
|
||||
--ctp-maroon: #e64553;
|
||||
--ctp-peach: #fe640b;
|
||||
--ctp-yellow: #df8e1d;
|
||||
--ctp-green: #40a02b;
|
||||
--ctp-teal: #179299;
|
||||
--ctp-sky: #04a5e5;
|
||||
--ctp-sapphire: #209fb5;
|
||||
--ctp-blue: #1e66f5;
|
||||
--ctp-lavender: #7287fd;
|
||||
--ctp-text: #4c4f69;
|
||||
--ctp-subtext1: #5c5f77;
|
||||
--ctp-subtext0: #6c6f85;
|
||||
--ctp-overlay2: #7c7f93;
|
||||
--ctp-overlay1: #8c8fa1;
|
||||
--ctp-overlay0: #9ca0b0;
|
||||
--ctp-surface2: #acb0be;
|
||||
--ctp-surface1: #bcc0cc;
|
||||
--ctp-surface0: #ccd0da;
|
||||
--ctp-base: #eff1f5;
|
||||
--ctp-mantle: #e6e9ef;
|
||||
--ctp-crust: #dce0e8;
|
||||
|
||||
/* ---------- Semantic mappings ---------- */
|
||||
--color-white: #ffffff;
|
||||
--color-black: #000000;
|
||||
--color-white-rgb: 255, 255, 255;
|
||||
--color-black-rgb: 0, 0, 0;
|
||||
|
||||
/* Grays (using Catppuccin surface hierarchy) */
|
||||
--color-gray-050: var(--ctp-base);
|
||||
--color-gray-100: var(--ctp-mantle);
|
||||
--color-gray-200: var(--ctp-crust);
|
||||
--color-gray-300: var(--ctp-surface0);
|
||||
--color-gray-400: var(--ctp-surface1);
|
||||
--color-gray-400-rgb: 188, 192, 204; /* approx surface1 */
|
||||
--color-gray-500: var(--ctp-surface2);
|
||||
--color-gray-600: var(--ctp-overlay0);
|
||||
--color-gray-700: var(--ctp-overlay1);
|
||||
--color-gray-800: var(--ctp-overlay2);
|
||||
--color-gray-900: var(--ctp-text);
|
||||
--color-gray-950: var(--ctp-subtext0);
|
||||
--color-gray-950-rgb: 108, 111, 133; /* subtext0 */
|
||||
|
||||
/* Brand / Primary (using Blue) */
|
||||
--color-brand-050: #eef6ff; /* keep similar, but we’ll use surface tints? We'll just leave as is or tint */
|
||||
--color-brand-100: var(--ctp-surface0);
|
||||
--color-brand-200: var(--ctp-surface1);
|
||||
--color-brand-300: #8ec5ff;
|
||||
--color-brand-400: #6baefa;
|
||||
--color-brand-500: var(--ctp-blue);
|
||||
--color-brand-600: var(--ctp-blue);
|
||||
--color-brand-700: var(--ctp-blue);
|
||||
--color-brand-800: #0d43af; /* keep a dark blue for contrast */
|
||||
--color-brand-900: #0c3276;
|
||||
--color-brand-950: #162455;
|
||||
--color-brand-950-rgb: 22, 36, 85;
|
||||
|
||||
/* Red */
|
||||
--color-red-050: var(--ctp-surface0);
|
||||
--color-red-100: var(--ctp-mantle);
|
||||
--color-red-200: var(--ctp-crust);
|
||||
--color-red-300: var(--ctp-red);
|
||||
--color-red-400: var(--ctp-red);
|
||||
--color-red-500: var(--ctp-red);
|
||||
--color-red-600: var(--ctp-red);
|
||||
--color-red-700: var(--ctp-red);
|
||||
--color-red-800: var(--ctp-maroon);
|
||||
--color-red-900: var(--ctp-maroon);
|
||||
--color-red-950: var(--ctp-maroon);
|
||||
|
||||
/* Orange / Warning */
|
||||
--color-orange-050: var(--ctp-surface0);
|
||||
--color-orange-100: var(--ctp-mantle);
|
||||
--color-orange-200: var(--ctp-crust);
|
||||
--color-orange-300: var(--ctp-peach);
|
||||
--color-orange-400: var(--ctp-peach);
|
||||
--color-orange-500: var(--ctp-peach);
|
||||
--color-orange-600: var(--ctp-peach);
|
||||
--color-orange-700: var(--ctp-peach);
|
||||
--color-orange-800: var(--ctp-yellow);
|
||||
--color-orange-900: var(--ctp-yellow);
|
||||
--color-orange-950: var(--ctp-yellow);
|
||||
|
||||
/* Yellow */
|
||||
--color-yellow-050: var(--ctp-surface0);
|
||||
--color-yellow-100: var(--ctp-mantle);
|
||||
--color-yellow-200: var(--ctp-crust);
|
||||
--color-yellow-300: var(--ctp-yellow);
|
||||
--color-yellow-400: var(--ctp-yellow);
|
||||
--color-yellow-500: var(--ctp-yellow);
|
||||
--color-yellow-600: var(--ctp-yellow);
|
||||
--color-yellow-700: var(--ctp-yellow);
|
||||
--color-yellow-800: var(--ctp-yellow);
|
||||
--color-yellow-900: var(--ctp-yellow);
|
||||
--color-yellow-950: var(--ctp-yellow);
|
||||
|
||||
/* Green / Success */
|
||||
--color-green-050: var(--ctp-surface0);
|
||||
--color-green-100: var(--ctp-mantle);
|
||||
--color-green-200: var(--ctp-crust);
|
||||
--color-green-300: var(--ctp-green);
|
||||
--color-green-400: var(--ctp-green);
|
||||
--color-green-500: var(--ctp-green);
|
||||
--color-green-600: var(--ctp-green);
|
||||
--color-green-700: var(--ctp-green);
|
||||
--color-green-800: var(--ctp-teal);
|
||||
--color-green-900: var(--ctp-teal);
|
||||
--color-green-950: var(--ctp-teal);
|
||||
|
||||
/* Pink */
|
||||
--color-pink-050: var(--ctp-surface0);
|
||||
--color-pink-100: var(--ctp-mantle);
|
||||
--color-pink-200: var(--ctp-crust);
|
||||
--color-pink-300: var(--ctp-pink);
|
||||
--color-pink-400: var(--ctp-pink);
|
||||
--color-pink-500: var(--ctp-pink);
|
||||
--color-pink-600: var(--ctp-pink);
|
||||
--color-pink-700: var(--ctp-mauve);
|
||||
--color-pink-800: var(--ctp-mauve);
|
||||
--color-pink-900: var(--ctp-mauve);
|
||||
--color-pink-950: var(--ctp-mauve);
|
||||
|
||||
/* Coral (use Peach) */
|
||||
--color-coral-050: var(--ctp-surface0);
|
||||
--color-coral-100: var(--ctp-mantle);
|
||||
--color-coral-200: var(--ctp-crust);
|
||||
--color-coral-300: var(--ctp-peach);
|
||||
--color-coral-400: var(--ctp-peach);
|
||||
--color-coral-500: var(--ctp-peach);
|
||||
--color-coral-600: var(--ctp-peach);
|
||||
--color-coral-700: var(--ctp-peach);
|
||||
--color-coral-800: var(--ctp-peach);
|
||||
--color-coral-900: var(--ctp-peach);
|
||||
--color-coral-950: var(--ctp-peach);
|
||||
|
||||
/* Teal */
|
||||
--color-teal-050: var(--ctp-surface0);
|
||||
--color-teal-100: var(--ctp-mantle);
|
||||
--color-teal-200: var(--ctp-crust);
|
||||
--color-teal-300: var(--ctp-teal);
|
||||
--color-teal-400: var(--ctp-teal);
|
||||
--color-teal-500: var(--ctp-teal);
|
||||
--color-teal-600: var(--ctp-teal);
|
||||
--color-teal-700: var(--ctp-teal);
|
||||
--color-teal-800: var(--ctp-sky);
|
||||
--color-teal-900: var(--ctp-sky);
|
||||
--color-teal-950: var(--ctp-sky);
|
||||
|
||||
/* Purple (use Mauve) */
|
||||
--color-purple-050: var(--ctp-surface0);
|
||||
--color-purple-100: var(--ctp-mantle);
|
||||
--color-purple-200: var(--ctp-crust);
|
||||
--color-purple-300: var(--ctp-mauve);
|
||||
--color-purple-400: var(--ctp-mauve);
|
||||
--color-purple-500: var(--ctp-mauve);
|
||||
--color-purple-600: var(--ctp-mauve);
|
||||
--color-purple-700: var(--ctp-mauve);
|
||||
--color-purple-800: var(--ctp-mauve);
|
||||
--color-purple-900: var(--ctp-mauve);
|
||||
--color-purple-950: var(--ctp-mauve);
|
||||
|
||||
/* Semantic foreground / background aliases */
|
||||
--color-fg-heading: var(--ctp-text);
|
||||
--color-fg-body: var(--ctp-text);
|
||||
--color-fg-body-subtle: var(--ctp-subtext1);
|
||||
--color-fg-disabled: var(--ctp-overlay0);
|
||||
--color-fg-brand: var(--ctp-blue);
|
||||
--color-fg-success: var(--ctp-green);
|
||||
--color-fg-danger: var(--ctp-red);
|
||||
--color-fg-warning: var(--ctp-peach);
|
||||
--color-fg-sensitive: var(--ctp-pink);
|
||||
|
||||
--color-bg-primary: var(--ctp-base);
|
||||
--color-bg-secondary: var(--ctp-mantle);
|
||||
--color-bg-tertiary: var(--ctp-crust);
|
||||
--color-bg-quaternary: var(--ctp-surface0);
|
||||
--color-bg-disabled: var(--ctp-surface0);
|
||||
--color-bg-gray: var(--ctp-surface1);
|
||||
--color-bg-gray-strong: var(--ctp-surface2);
|
||||
--color-bg-contrast-soft: var(--ctp-overlay1);
|
||||
--color-bg-contrast: var(--ctp-overlay2);
|
||||
--color-bg-contrast-strong: var(--ctp-text);
|
||||
|
||||
--color-border-muted: var(--ctp-mantle);
|
||||
--color-border-light: var(--ctp-crust);
|
||||
--color-border-base: var(--ctp-surface0);
|
||||
--color-border-strong: var(--ctp-surface1);
|
||||
--color-border-stronger: var(--ctp-overlay0);
|
||||
|
||||
--color-bg-hover: rgba(var(--color-gray-950-rgb), 0.05);
|
||||
--color-bg-hover-contrast: rgba(255, 255, 255, 0.05);
|
||||
--color-bg-overlay: rgba(2, 6, 24, 0.3); /* keep dark overlay */
|
||||
|
||||
/* Navigation (primary sidebar) */
|
||||
--color-nav-fg-primary: var(--ctp-text);
|
||||
--color-nav-bg-primary: var(--ctp-mantle);
|
||||
--color-nav-bg-primary-strong: var(--ctp-crust);
|
||||
--color-nav-bg-primary-hover: rgba(0,0,0,0.05);
|
||||
--color-nav-bg-primary-hover-strong: rgba(0,0,0,0.1);
|
||||
--color-nav-border-primary: var(--ctp-blue);
|
||||
--color-nav-border-primary-focus: var(--ctp-text);
|
||||
|
||||
/* Misc */
|
||||
--color-transparent-hover: rgb(0 0 0 / 0.02);
|
||||
--color-shadow: 108 111 133; /* subtext0 */
|
||||
--color-background: 239 241 245; /* base */
|
||||
--color-background-alt: 230 233 239; /* mantle */
|
||||
--color-background-alt2: 23 92 219; /* keep as original? We'll set to blue */
|
||||
--color-background-alt3: 33 37 41; /* we map to crust rgb */
|
||||
--color-background-alt4: 16 18 21;
|
||||
--color-primary-100: 219 229 246; /* we map to surface0 */
|
||||
--color-primary-300: 108 117 125;
|
||||
--color-primary-600: 30 102 245; /* blue */
|
||||
--color-primary-700: 13 60 119;
|
||||
--color-secondary-100: 188 192 204;
|
||||
--color-secondary-300: 156 160 176;
|
||||
--color-secondary-500: 124 127 147;
|
||||
--color-secondary-600: 108 111 133;
|
||||
--color-secondary-700: 92 95 119;
|
||||
--color-info-100: 219 229 246;
|
||||
--color-info-600: 30 102 245;
|
||||
--color-info-700: 13 36 123;
|
||||
--color-warning-100: 255 244 212;
|
||||
--color-warning-600: 254 100 11; /* peach */
|
||||
--color-warning-700: 223 142 29; /* yellow */
|
||||
--color-danger-100: 255 236 239;
|
||||
--color-danger-600: 210 15 57; /* red */
|
||||
--color-danger-700: 149 27 42;
|
||||
--color-success-100: 213 243 216;
|
||||
--color-success-600: 64 160 43; /* green */
|
||||
--color-success-700: 8 81 15;
|
||||
--color-notification-100: 255 225 247;
|
||||
--color-notification-600: 192 17 118;
|
||||
--color-text-main: 27 32 41; /* will be overridden by CT-Text */
|
||||
--color-text-muted: 108 111 133;
|
||||
--color-text-contrast: 255 255 255;
|
||||
--color-text-alt2: 255 255 255;
|
||||
--color-text-code: 234 118 203; /* pink */
|
||||
--color-hover-default: rgba(30 102 245 / 0.1);
|
||||
--color-hover-contrast: rgba(255 255 255 / 0.15);
|
||||
}
|
||||
|
||||
/* ===== Dark Theme (Mocha) ===== */
|
||||
html.theme_dark {
|
||||
--ctp-rosewater: #f5e0dc;
|
||||
--ctp-flamingo: #f2cdcd;
|
||||
--ctp-pink: #f5c2e7;
|
||||
--ctp-mauve: #cba6f7;
|
||||
--ctp-red: #f38ba8;
|
||||
--ctp-maroon: #eba0ac;
|
||||
--ctp-peach: #fab387;
|
||||
--ctp-yellow: #f9e2af;
|
||||
--ctp-green: #a6e3a1;
|
||||
--ctp-teal: #94e2d5;
|
||||
--ctp-sky: #89dceb;
|
||||
--ctp-sapphire: #74c7ec;
|
||||
--ctp-blue: #89b4fa;
|
||||
--ctp-lavender: #b4befe;
|
||||
--ctp-text: #cdd6f4;
|
||||
--ctp-subtext1: #bac2de;
|
||||
--ctp-subtext0: #a6adc8;
|
||||
--ctp-overlay2: #9399b2;
|
||||
--ctp-overlay1: #7f849c;
|
||||
--ctp-overlay0: #6c7086;
|
||||
--ctp-surface2: #585b70;
|
||||
--ctp-surface1: #45475a;
|
||||
--ctp-surface0: #313244;
|
||||
--ctp-base: #1e1e2e;
|
||||
--ctp-mantle: #181825;
|
||||
--ctp-crust: #11111b;
|
||||
|
||||
/* Grays */
|
||||
--color-gray-050: var(--ctp-base);
|
||||
--color-gray-100: var(--ctp-mantle);
|
||||
--color-gray-200: var(--ctp-crust);
|
||||
--color-gray-300: var(--ctp-surface0);
|
||||
--color-gray-400: var(--ctp-surface1);
|
||||
--color-gray-500: var(--ctp-surface2);
|
||||
--color-gray-600: var(--ctp-overlay0);
|
||||
--color-gray-700: var(--ctp-overlay1);
|
||||
--color-gray-800: var(--ctp-overlay2);
|
||||
--color-gray-900: var(--ctp-text);
|
||||
--color-gray-950: var(--ctp-subtext0);
|
||||
--color-gray-400-rgb: 69, 71, 90; /* surface1 */
|
||||
--color-gray-950-rgb: 166, 173, 200; /* subtext0 */
|
||||
|
||||
/* Adjust semantic mappings for dark */
|
||||
--color-fg-heading: var(--ctp-text);
|
||||
--color-fg-body: var(--ctp-text);
|
||||
--color-fg-body-subtle: var(--ctp-subtext1);
|
||||
--color-fg-disabled: var(--ctp-overlay0);
|
||||
--color-fg-brand: var(--ctp-blue);
|
||||
--color-fg-success: var(--ctp-green);
|
||||
--color-fg-danger: var(--ctp-red);
|
||||
--color-fg-warning: var(--ctp-peach);
|
||||
--color-fg-sensitive: var(--ctp-pink);
|
||||
|
||||
--color-bg-primary: var(--ctp-base);
|
||||
--color-bg-secondary: var(--ctp-mantle);
|
||||
--color-bg-tertiary: var(--ctp-crust);
|
||||
--color-bg-quaternary: var(--ctp-surface0);
|
||||
--color-bg-disabled: var(--ctp-surface0);
|
||||
--color-bg-gray: var(--ctp-surface1);
|
||||
--color-bg-gray-strong: var(--ctp-surface2);
|
||||
--color-bg-contrast-soft: var(--ctp-overlay1);
|
||||
--color-bg-contrast: var(--ctp-overlay2);
|
||||
--color-bg-contrast-strong: var(--ctp-text);
|
||||
|
||||
--color-border-muted: var(--ctp-mantle);
|
||||
--color-border-light: var(--ctp-crust);
|
||||
--color-border-base: var(--ctp-surface0);
|
||||
--color-border-strong: var(--ctp-surface1);
|
||||
--color-border-stronger: var(--ctp-overlay0);
|
||||
|
||||
--color-bg-hover: rgba(166, 173, 200, 0.1);
|
||||
--color-bg-hover-contrast: rgba(255, 255, 255, 0.05);
|
||||
--color-bg-overlay: rgba(17, 17, 27, 0.7); /* crust with opacity */
|
||||
|
||||
--color-nav-fg-primary: var(--ctp-text);
|
||||
--color-nav-bg-primary: var(--ctp-mantle);
|
||||
--color-nav-bg-primary-strong: var(--ctp-crust);
|
||||
--color-nav-bg-primary-hover: rgba(255,255,255,0.05);
|
||||
--color-nav-bg-primary-hover-strong: rgba(255,255,255,0.1);
|
||||
--color-nav-border-primary: var(--ctp-blue);
|
||||
--color-nav-border-primary-focus: var(--ctp-text);
|
||||
|
||||
/* Misc rgb values */
|
||||
--color-shadow: 166 173 200;
|
||||
--color-background: 30 30 46; /* base */
|
||||
--color-background-alt: 24 24 37; /* mantle */
|
||||
--color-background-alt2: 137 180 250; /* blue */
|
||||
--color-background-alt3: 17 17 27; /* crust */
|
||||
--color-background-alt4: 17 17 27;
|
||||
--color-primary-100: 49 50 68;
|
||||
--color-primary-300: 69 71 90;
|
||||
--color-primary-600: 137 180 250; /* blue */
|
||||
--color-primary-700: 137 180 250;
|
||||
--color-secondary-100: 69 71 90;
|
||||
--color-secondary-300: 88 91 112;
|
||||
--color-secondary-500: 108 112 134;
|
||||
--color-secondary-600: 124 128 150;
|
||||
--color-secondary-700: 147 153 178;
|
||||
--color-info-100: 49 50 68;
|
||||
--color-info-600: 137 180 250;
|
||||
--color-info-700: 137 180 250;
|
||||
--color-warning-100: 49 50 68;
|
||||
--color-warning-600: 250 179 135; /* peach */
|
||||
--color-warning-700: 249 226 175; /* yellow */
|
||||
--color-danger-100: 49 50 68;
|
||||
--color-danger-600: 243 139 168; /* red */
|
||||
--color-danger-700: 235 160 172; /* maroon */
|
||||
--color-success-100: 49 50 68;
|
||||
--color-success-600: 166 227 161; /* green */
|
||||
--color-success-700: 148 226 213; /* teal */
|
||||
--color-notification-100: 49 50 68;
|
||||
--color-notification-600: 245 194 231; /* pink */
|
||||
--color-text-main: 205 214 244; /* text */
|
||||
--color-text-muted: 166 173 200;
|
||||
--color-text-contrast: 30 30 46;
|
||||
--color-text-alt2: 30 30 46;
|
||||
--color-text-code: 245 194 231;
|
||||
--color-hover-default: rgba(137 180 250 / 0.1);
|
||||
--color-hover-contrast: rgba(30 30 46 / 0.15);
|
||||
}
|
||||
+27
-22
@@ -1,38 +1,37 @@
|
||||
{
|
||||
config,
|
||||
pkgs,
|
||||
lib,
|
||||
...
|
||||
}:
|
||||
|
||||
let
|
||||
address = config.systemd.network.networks."10-ethernet".networkConfig.Address;
|
||||
ip = builtins.elemAt (lib.splitString "/" address) 0;
|
||||
port = 8222;
|
||||
userScss = builtins.readFile ./user.vaultwarden.scss.hbs;
|
||||
in
|
||||
{
|
||||
services.vaultwarden = {
|
||||
enable = true;
|
||||
environmentFile = config.sops.secrets.vaultwarden_admin_token.path;
|
||||
backupDir = "/var/local/vaultwarden/backup";
|
||||
|
||||
config = {
|
||||
DOMAIN = "https://vault.cyperpunk.de"; # "http://${ip}:${toString port}";
|
||||
ROCKET_ADDRESS = "0.0.0.0";
|
||||
ROCKET_PORT = port;
|
||||
ROCKET_LOG = "critical";
|
||||
SIGNUPS_ALLOWED = true;
|
||||
WEBSOCKET_ENABLED = true;
|
||||
};
|
||||
};
|
||||
|
||||
sops.secrets.vaultwarden_admin_token = {
|
||||
sops.secrets.vaultwarden_env = {
|
||||
owner = "vaultwarden";
|
||||
group = "vaultwarden";
|
||||
};
|
||||
|
||||
services.vaultwarden = {
|
||||
enable = true;
|
||||
package = pkgs.oidcwarden;
|
||||
environmentFile = config.sops.secrets.vaultwarden_env.path;
|
||||
backupDir = "/var/local/vaultwarden/backup";
|
||||
config = {
|
||||
DOMAIN = "https://vault.cyperpunk.de";
|
||||
ROCKET_ADDRESS = "0.0.0.0";
|
||||
ROCKET_PORT = port;
|
||||
ROCKET_LOG = "critical";
|
||||
SIGNUPS_ALLOWED = false;
|
||||
WEBSOCKET_ENABLED = true;
|
||||
SSO_ENABLED = true;
|
||||
SSO_ONLY = false;
|
||||
SSO_AUTHORITY = "https://auth.cyperpunk.de/oauth2/openid/vaultwarden";
|
||||
SSO_SCOPES = "openid profile email";
|
||||
SSO_PKCE = false;
|
||||
};
|
||||
};
|
||||
networking.firewall.allowedTCPPorts = [ port ];
|
||||
|
||||
systemd = {
|
||||
services.vaultwarden-backup-rotate = {
|
||||
description = "Rotate old Vaultwarden backups";
|
||||
@@ -49,5 +48,11 @@ in
|
||||
Persistent = true;
|
||||
};
|
||||
};
|
||||
|
||||
tmpfiles.rules = [
|
||||
"d /var/lib/vaultwarden/templates 0750 vaultwarden vaultwarden -"
|
||||
"d /var/lib/vaultwarden/templates/scss 0750 vaultwarden vaultwarden -"
|
||||
"L+ /var/lib/vaultwarden/templates/scss/user.vaultwarden.scss.hbs 0640 vaultwarden vaultwarden - ${pkgs.writeText "user.vaultwarden.scss.hbs" userScss}"
|
||||
];
|
||||
};
|
||||
}
|
||||
|
||||
@@ -1,28 +0,0 @@
|
||||
{ pkgs, ... }: {
|
||||
|
||||
# TODO: This need to be tested against the cam and kernel rules need to be refined
|
||||
services.udev.extraRules = ''
|
||||
ACTION=="add", \
|
||||
SUBSYSTEM=="usb", \
|
||||
ATTR{idVendor}=="04a9", \
|
||||
ATTR{idProduct}=="31ea", \
|
||||
RUN+="${pkgs.systemd}/bin/systemctl restart webcam"
|
||||
'';
|
||||
|
||||
systemd.services.webcam = {
|
||||
enable = true;
|
||||
description = "Canon Camera Webcam";
|
||||
script = ''
|
||||
${pkgs.gphoto2}/bin/gphoto2 --stdout --capture-movie | \
|
||||
${pkgs.ffmpeg}/bin/ffmpeg \
|
||||
-i - \
|
||||
-vcodec rawvideo \
|
||||
-pix_fmt yuv420p \
|
||||
-threads 0 \
|
||||
-framerate 30 \
|
||||
-f v4l2 \
|
||||
/dev/video0
|
||||
'';
|
||||
wantedBy = [ "multi-user.target" ];
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
{ nur }:
|
||||
final: prev:
|
||||
(nur.overlays.default final prev)
|
||||
// {
|
||||
gs1200-exporter = final.callPackage ./gs1200-exporter.nix { };
|
||||
oidcwarden = final.callPackage ./oidcwarden.nix {
|
||||
inherit (prev) vaultwarden;
|
||||
};
|
||||
netradiant-custom = final.callPackage ./netradiant-custom.nix { };
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
{
|
||||
lib,
|
||||
buildGoModule,
|
||||
fetchFromGitHub,
|
||||
}:
|
||||
buildGoModule rec {
|
||||
pname = "gs1200-exporter";
|
||||
version = "2.11.12";
|
||||
|
||||
__structuredAttrs = true;
|
||||
|
||||
src = fetchFromGitHub {
|
||||
owner = "robinelfrink";
|
||||
repo = "gs1200-exporter";
|
||||
rev = "v${version}";
|
||||
hash = "sha256-8s2VgaqYXp9PN2oNU/sWpjQjDPSWolbWEVSZcx9Lh3M=";
|
||||
};
|
||||
|
||||
vendorHash = "sha256-204bFaywOolKVNoeH/w72Ba1PYAVgQawEmlaEXgRaRY=";
|
||||
|
||||
meta = {
|
||||
description = "Prometheus exporter for Zyxel GS1200 switches";
|
||||
homepage = "https://github.com/robinelfrink/gs1200-exporter";
|
||||
license = lib.licenses.asl20;
|
||||
maintainers = with lib.maintainers; [ DerGrumpf ];
|
||||
mainProgram = "gs1200-exporter";
|
||||
platforms = lib.platforms.all;
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,100 @@
|
||||
{
|
||||
lib,
|
||||
stdenv,
|
||||
fetchFromGitHub,
|
||||
fetchgit,
|
||||
pkg-config,
|
||||
makeWrapper,
|
||||
subversion,
|
||||
git,
|
||||
unzip,
|
||||
wget,
|
||||
qt5,
|
||||
glib,
|
||||
libxml2,
|
||||
zlib,
|
||||
libpng,
|
||||
assimp,
|
||||
}:
|
||||
let
|
||||
xonoticPack = fetchgit {
|
||||
url = "https://gitlab.com/xonotic/netradiant-xonoticpack.git";
|
||||
rev = "b9b95499e6bd1082a4eaff78664f9243cbcbb2e1";
|
||||
hash = "sha256-boSWipgiQzXHFJ0KGpd8xbwik3hKQK3IKSNByUaUHBk=";
|
||||
};
|
||||
in
|
||||
stdenv.mkDerivation rec {
|
||||
pname = "netradiant-custom";
|
||||
version = "20260114";
|
||||
__structuredAttrs = true;
|
||||
|
||||
src = fetchFromGitHub {
|
||||
owner = "Garux";
|
||||
repo = "netradiant-custom";
|
||||
rev = version;
|
||||
hash = "sha256-dlJn10Y45mx3UwxvB8mzw5Ok8LvvxVpMwDAdHXSt5dk=";
|
||||
};
|
||||
|
||||
nativeBuildInputs = [
|
||||
pkg-config
|
||||
makeWrapper
|
||||
subversion
|
||||
git
|
||||
unzip
|
||||
wget
|
||||
];
|
||||
|
||||
buildInputs = [
|
||||
qt5.qtbase
|
||||
qt5.qtsvg
|
||||
glib
|
||||
libxml2
|
||||
zlib
|
||||
libpng
|
||||
assimp
|
||||
];
|
||||
|
||||
makeFlags = [
|
||||
"DOWNLOAD_GAMEPACKS=no"
|
||||
"DEPENDENCIES_CHECK=off"
|
||||
"BUILD=release"
|
||||
];
|
||||
|
||||
enableParallelBuilding = true;
|
||||
|
||||
dontWrapQtApps = true;
|
||||
|
||||
installPhase = ''
|
||||
runHook preInstall
|
||||
|
||||
mkdir -p $out/opt/netradiant-custom
|
||||
cp -r install/* $out/opt/netradiant-custom/
|
||||
|
||||
# Replicates what upstream's install-gamepack.sh does:
|
||||
# - files in <pack>/games/*.game go into gamepacks/games/
|
||||
# - directories named <pack>/*.game go into gamepacks/ directly
|
||||
mkdir -p $out/opt/netradiant-custom/gamepacks/games
|
||||
if [ -d "${xonoticPack}/games" ]; then
|
||||
cp -r ${xonoticPack}/games/*.game $out/opt/netradiant-custom/gamepacks/games/
|
||||
fi
|
||||
for d in ${xonoticPack}/*.game; do
|
||||
cp -r "$d" $out/opt/netradiant-custom/gamepacks/
|
||||
done
|
||||
|
||||
mkdir -p $out/bin
|
||||
makeWrapper $out/opt/netradiant-custom/radiant.x86_64 $out/bin/netradiant-custom \
|
||||
--chdir "$out/opt/netradiant-custom" \
|
||||
--prefix QT_PLUGIN_PATH : "${qt5.qtbase}/${qt5.qtbase.qtPluginPrefix}" \
|
||||
--set QT_QPA_PLATFORM xcb
|
||||
|
||||
runHook postInstall
|
||||
'';
|
||||
|
||||
meta = {
|
||||
description = "Cross-platform level editor for id Tech based games (NetRadiant fork)";
|
||||
homepage = "https://github.com/Garux/netradiant-custom";
|
||||
license = lib.licenses.gpl2Plus;
|
||||
mainProgram = "netradiant-custom";
|
||||
platforms = lib.platforms.linux;
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
{
|
||||
vaultwarden,
|
||||
rustPlatform,
|
||||
fetchFromGitHub,
|
||||
...
|
||||
}:
|
||||
let
|
||||
src = fetchFromGitHub {
|
||||
owner = "Timshel";
|
||||
repo = "OIDCWarden";
|
||||
rev = "48edfc7ba54372074befa1d62c63c4babfaadc77";
|
||||
hash = "sha256-tHacn9RtoByWpqnWX2/gWwODDSeXJa4mk4MfxHiiJ8A=";
|
||||
};
|
||||
in
|
||||
vaultwarden.overrideAttrs (old: {
|
||||
pname = "oidcwarden";
|
||||
inherit src;
|
||||
cargoDeps = rustPlatform.fetchCargoVendor {
|
||||
inherit src;
|
||||
hash = "sha256-eGsYNaLYRCrTRaoyfhxnoeA2ytYeyGGvHnAbpEIayzs=";
|
||||
};
|
||||
postInstall = (old.postInstall or "") + ''
|
||||
mv $out/bin/oidcwarden $out/bin/vaultwarden
|
||||
'';
|
||||
})
|
||||
+24
-8
@@ -1,26 +1,41 @@
|
||||
zyxel_pass: ENC[AES256_GCM,data:yEqvWjeII7Uk7w==,iv:j7Lj2HCzlPRnVlvd1c0dTd41gdJAGRi+U6jrH0Vm71U=,tag:AvcPhHJVTCubu/YD9RBivg==,type:str]
|
||||
cachix_auth_token: ENC[AES256_GCM,data:nR7e2ZOA3q5DmkrqFEzINpKFEHVD5nyzc3DQ3QgD42fdyABV+r1Ela3iEcbU8SWj5JMRq8T1r7QxqcYW+VSMsT2cjQV2e4ZrpUmkX2QnhfmLqQBdJLhgNKBnu+x8QGJpQ3j7mG23atJ3BDTYBEKlI8y6wLEgpTX8GIVzHJVwfbqewTX4EfFyh3mVMtxAK9II/w==,iv:CSMcUdsqC97fmu1Po3cRrUj9h51Wv+KaUPfEToE7qVs=,tag:s1XHG2eyZYJJ5xd9CZb+Pw==,type:str]
|
||||
GROQ_API_KEY: ENC[AES256_GCM,data:OyuC4jfw67sCDa0XBGr78S6pzPV1ruy7KiIqPMgWWcOCVm3Y/khXEYPMjUTGrq9YLOw1MLso0OE=,iv:0y9klMYVtGsqAaLc2JidjZYSLhhbcbWbnBf8sZiC3rM=,tag:r6G2pzZn2d9JIaS+ozKnmg==,type:str]
|
||||
OPENWEATHER_API_KEY: ENC[AES256_GCM,data:bcuLz70u40nZfNgPTaeNRXdR/zjx0SQjwMbMNNFqROI=,iv:VCzse1a1/k1ZDIpFPL1QhjuS6YaDyohWi61JZaoc0Ws=,tag:UJSNyniNNLfGGRY/uiJcRA==,type:str]
|
||||
smb_passwd: ENC[AES256_GCM,data:+9RYomcnCZSME5DzuJWTLbS3IGJHhIYWZ5SmsgOn6YQ=,iv:VRPVR7DD+swjeUZKe54XYm3wn/KB4RqvQAyYXQbS+A8=,tag:NnA89efo6HVL0scHgyTZMQ==,type:str]
|
||||
grafana_secret_key: ENC[AES256_GCM,data:d6tu4kL7flfbdeOYk21zkSRmVe+NvVwd14jgr9Ds0adfgYetN852G25Z8/g=,iv:uWuwGBZVK1syhEfO9nLZUWwa801759tNJx+Pmnz3xeg=,tag:X6/NcdGZHAdIlOwxNPo/Ew==,type:str]
|
||||
kanidm_grafana_secret: ENC[AES256_GCM,data:rqK3hkpvtg24P4UVV0pFuabUhxoTgtZvK+h8EiSfVyOSrnRy6jtyGvOMMlIOAQDr,iv:I6e++KrpxAFhM8VDQkx8YsrQSvT4brc+Fh1cY5PlwKY=,tag:sEq91Yucb2pUTDbRir+NyA==,type:str]
|
||||
matrix_macaroon_secret: ENC[AES256_GCM,data:a9nMar+p+FXIsxxSqO/to2OJOvD1erfwLwwBeKOcWBu7xykHxqD+pCmrGhg=,iv:rp4ZDVIlZ7SN1RFHB2CfSV5ISPMl9pC4U8Jgqpz48Qs=,tag:LxmWUZE3mG4acagQmlieag==,type:str]
|
||||
matrix_registration_secret: ENC[AES256_GCM,data:KhKkJZqwE8xk4/tuQ7NYTv/Ot1qCAiy8yUbDyVvRa0H5BT4amCBIdATfR4Q=,iv:HBN+GorT1VpWCVkDugk4UxYLEYKJIoDZh2d+oUDLc8g=,tag:hHus458yVnH0qaQ4u37IZg==,type:str]
|
||||
vaultwarden_admin_token: ENC[AES256_GCM,data:yoBs4CaIEJXB5b3PEwTpXFgxpX39hR9A4r9yamwDV7cTSRRp3n3O2VjDKTcI5Vo6RP2QUjcqUqYf98cZ09wDMc+6+oHHJke7+O0FgRgOC0vOQFs4bfZCBJBLxogrGiwtLGkyykR6VYhrT64AN3CbrXflj82OED2Hl8WwEdruBzGIcfnh6FqQowDx6vDR/kXXJHk=,iv:PJQo5V7FaKPQ+GzZNsy3KB+xyjcDKJ1UBHErrqgn/1U=,tag:BRIDJEDOAeToqio/DHMQaA==,type:str]
|
||||
kanidm_synapse_secret: ENC[AES256_GCM,data:F770siYcYLm3RAQ+3epfVTyp5mv0OJfiOdFiHD8CudjceNkkSuXIX7pxQYkhS3VY,iv:hqYMKLS5m+o3leFE0gBS05Npjy9uyqgSe7yJpPzxvQY=,tag:lLjVZ7/iYoIZh06VyF8zSw==,type:str]
|
||||
vaultwarden_env: ENC[AES256_GCM,data:tGAphb8y+9sdo29z1/zRe4IKKKAsKfJZIiRGSDe1Vbpn24ucjnvrDpbuI8AIf145mVckCZ6nsdB88q+XNr4jrywx3b5gGdacZn/wLx6rVpa24VdJOI685nu++CtJjUiPCOiNVRza7MGFStCWTekRGosVWwwjmu8IRHEtywO/+qkVa2tFx9SGxB9ayVHWJVJNI0V3EoWgXp0Sf+gYZvMww0Ew05xeeCdICe9Tz6ExVsI/2feq2QPBgcR4M+g47UrixWf0HmR+WU/HQygSYZ0vxau+88PyfrlOUWBZY0WtETNd0pymVHnvHyFIuBjwa8zg,iv:Oytbdz/9KS21sy2tWAws2DTKTmW8IOJcSso1K1tYm3M=,tag:iWphR6xUegNrCEsqL2o0yQ==,type:str]
|
||||
flame_phil_password: ENC[AES256_GCM,data:Xy2ixMeRlnzC2gjKGrjfSbz/ee4=,iv:WFuBS8jn7WYRxEDG3XBzCMnm4eNkHQpSs5+GUwq/dcg=,tag:1zzj0eB9/4KrmYAqcxJMlg==,type:str]
|
||||
flame_calvin_password: ENC[AES256_GCM,data:P5ppyqTjAJ1TL4hXtx5WyoS9a+g=,iv:sq98P3Oqud2FXfqsD76YS/p5NEF2xlN0MfG+ukCB9B0=,tag:AeKnu4Hg4xQ3tII0y6oNpQ==,type:str]
|
||||
paperless_admin: ENC[AES256_GCM,data:sVvlMQ3dDE2XsDfpwpCTbzPCEKdUMNTFtRXDIuBbgyf1gd6oiJzE23Ytc57plNUGg5h5aEtgxZ7NXeuK5vrhQw==,iv:x+QNAzY9k9t23UYlM9GcAke0urEA5jlV0VzHaBQkm7M=,tag:D/bMtjuwrX6pquZfJLwdkQ==,type:str]
|
||||
livekit_key_sfu: ENC[AES256_GCM,data:3pRAN0Vz134mg/omkSRlC9OAvToQg42aZbXj7TurYYOLUMnW6sWk+eexyIcYAAjCSP5GRES4WySuN/qjGeUDBKr8OYAxTXjR/w==,iv:NYhcfiKlXT3v5R4djkhHusMMRYgc3bCM66VD0G2MyME=,tag:8341ntSCmteTn+6AM0xu8g==,type:str]
|
||||
livekit_key_jwt: ENC[AES256_GCM,data:9cBMJ0AyyWaoUZsXmnGvIL7EPIO8l16TQRBC6iK6h1TQAriOTPicfcE40Itf7cmiplZFtK6z7DhkgggRpG88HT7ZCvcXP0P69A==,iv:GiZb/8Vz4tiLG8kpF93kiFkmmA/KdgWr0ILARsL15oo=,tag:SZxzfFSk125q9sqlRbsxdw==,type:str]
|
||||
paperless_oidc_secret: ENC[AES256_GCM,data:+oCeHlky5FgUR8Toue1iQiTaqVX3ZgenEv74S5Cg6XHBObyDLUgUkZNYKj7p88nR,iv:29CBYlOjpyegGwEl5lSlAirkCWtG0+4oOupOTfeI1yM=,tag:KckKGdFa9tNwigWEukLN3w==,type:str]
|
||||
livekit_key_file: ENC[AES256_GCM,data:wOtJhwDtZNEY+QjHyLL1FTOtkmzkNA5BoTsx0+ZMij9uUaKC28uFIkMAq2ZzIU7Nyvk8+4YjbK/Rrsoy,iv:UTDuItr0XsG+/4HFkEHDpxXy41QiVgPCisHeMMY2dQo=,tag:SkoeLWClO9I/V2sn27Y2uw==,type:str]
|
||||
mjolnir_access_token: ENC[AES256_GCM,data:vvrAY9CAkEIGEzah+TQiwa6PahGuXVvU7wzBpTnqeSLqe3mqtw120GRj,iv:J+/VJ40BsImr832eGUHShhDVWYC7KsEwQUH9AE6Rs9c=,tag:n+y0flxfqY47rB4yv9TnBw==,type:str]
|
||||
coturn_static_auth_secret: ENC[AES256_GCM,data:7AI0E8Hu4WxI5q4j1GqBMSQ+evE006uPMtwIfGn4eFz+XB2JA6fhhiGMPPxSkqOyK+3eZJ5ahiG05JpmBmmAbw==,iv:hQJQQDVo43U7lvV754PC1THeFCpZZEyag+BslXyoDos=,tag:Vkm+IXr1h8ZNpah6UYaKng==,type:str]
|
||||
discord_bot_token: ENC[AES256_GCM,data:j37Qo3FCyRwNFqWSWpnQKCs+AxH5HlQ8U5If7ylHilQoORp8Pb3TtNETTJSjZyvUXllldevAbHrbAEEKnNfoUJx1U8/wl6H0,iv:WQqxFXTE+0LIB2lSvVcnr4LNXPE7uzNc0Kk8NU6Z/aE=,tag:fNeQLhoThEgfa4sSGKLZCw==,type:str]
|
||||
discord_client_id: ENC[AES256_GCM,data:U/iUKXT6Nsl6LRN9lPh1xaIaqw==,iv:k7kQ8rJBrMs3YwD9aDfZ6qhd7H3aVsSPTOwEIxVTw2Y=,tag:2wKhxGbf+P+h3BYeWUSczA==,type:str]
|
||||
discord_pickle_key: ENC[AES256_GCM,data:6j1pBQxmK8kFELSBBeJ0FwzAHz1GTGhxQwrvhlLtiU9+HICBBJqmFra1veZSO4yLchye/yPZ9Ha7oau+SgOI6w==,iv:YcTQQFcfLK33CpZnhEiKkt71e4ziarGKPyt7mmdQ+NA=,tag:AJRD4xYvYOZ0L1Xo+O+aGg==,type:str]
|
||||
meta_as_token: ENC[AES256_GCM,data:WNkfHIRl9bGdzGRgjE2C9fymA0nX/ginNqRldyygaWw=,iv:BTVB+sf46mEQ/+FXCe4SRgmkfpnO2wnWlpKr/4uQbe0=,tag:qP42MN2qm1Tn6physjLK5g==,type:str]
|
||||
meta_hs_token: ENC[AES256_GCM,data:BG7sSy0dIxf8EwjIA3rXxRZ+6IRPc2sJKSFXw+aldvY=,iv:gjk3pl/iV6rivxxrnR0jjEiSkmj0Jl5ojsudepKpxtY=,tag:n+BGaHRD+CqfXCbRPtFmfw==,type:str]
|
||||
instagram_as_token: ENC[AES256_GCM,data:zKAv60IezEYqDEZNOFS5aKgNztBL9JUM9sfTZCD+vkg=,iv:3xCkVfT0S947LzpDzC0N1kuHOBhVaveK3m0cay0DlGc=,tag:NgJq8YN2r6NKj8pwlsgkXA==,type:str]
|
||||
instagram_hs_token: ENC[AES256_GCM,data:+Lp9PQLUxyn/xS+L/hFcsufF0UxQJTiEd/7su8NmobI=,iv:ad9Urc8CwTfLWWRpUL6/TxfTB7LU8XoPq3kp8ifhfr0=,tag:0KkcdDAB/9rcuIgbLBZAkQ==,type:str]
|
||||
pg_replication_password: ENC[AES256_GCM,data:w2h07D+j3LNkcbvoKQ2Qp3HSvC2Wf5HRAPAo/HNhmUkHBOaDyILNxo7IDjqajv0jytpG7q4joCJQhS7tEUlA9Q==,iv:26ZurAq61IDqGdAl0yPpoTJElo93hJJIEUlza4DGDNc=,tag:a46FOKgeqEEZE+rC+H9NbQ==,type:str]
|
||||
kanidm_gitea_secret: ENC[AES256_GCM,data:RavtSb5BaJGwwLB/oGzG/KK2AyV+IzEjihVxnD3/dVnxmxcG+CITIYPLvFUJjmvY,iv:Cg8dAhtJXDvRGULIkpWAyuhhlLEdvN+4lyjHPR/740I=,tag:8kMGrOjXEA4GWSLlP7oIkA==,type:str]
|
||||
gitea:
|
||||
dbPassword: ENC[AES256_GCM,data:S6VvRgkdYk1AzXljyQEEq68UJ9zrFy6+INBMIAspXNcqcM6o+es19o0mcXA=,iv:/pHYpkZZq+9Md+75uSCb2YXfSvaDzUh6mMfH53wb7eg=,tag:ZnbyCQwrK2JnbO5HFqgJYw==,type:str]
|
||||
internalToken: ENC[AES256_GCM,data:7N8TkPNb1YdCk2uAcCvVd2pKRVOf85//DYxAvz0UCg1E8ccEI5630xVyKafDFiSTM4ER7xiYelartzXL0jLWSf3QNOjSHUP8TIAz4bJRAZUJPxO917bURSLGGe7WEOfONzqy3Ts5QhrJ,iv:DiIs1ytlwLvqD/Ejep6m2fmpSqdFZkxBcgLNt6+29jY=,tag:8jsEcOkH0p+1mP9cnVjiDQ==,type:str]
|
||||
lfsJwtSecret: ENC[AES256_GCM,data:L20mFZ6zwsF3ZUoodarTJV+vhUdLlBrUbHz7FpEzJ2/C6AdFc1ZZcioN3g==,iv:E2C3gg1OYQ46Ae2bGnhF+3uw+q77l+yph3Kd2fxwW9M=,tag:VQkQ4R9S8Dr39rSLhL/X1w==,type:str]
|
||||
mailerPassword: ""
|
||||
runnerToken: ENC[AES256_GCM,data:giY3e3oHqWytgIWfnuKxOfrp8R+u7I0lMzEGnLWXnZWL9aQkVsM1kiF1FNKn/A==,iv:YsQrAKU8pncPeSSosOFn9BjU676KCh956FGC2hnCuac=,tag:+eZ1y6P/85XNPD9gVVNMgA==,type:str]
|
||||
ssh_private_key: ENC[AES256_GCM,data:R511mVFVk1ogAd5CKk/2P6rtT4NnHIFfKyqeCen545QgcvDqDFmW0rFBmPJyipaya2srJNoWvKJbnvxWtTYeJh2tPAybRMoUicStIFMUn3FPNfjx/WuQFLhKLoU3UOHHPJnkFqkQ9MBqLq2k5K7MVsNNFTxIDCKS1jPgkTmAWjRZ0EFiRXLa+Gvnz3GP5ltgfjDwdPeb5xp0/AqKPD8jea9w5ClR6ckrRHCLsfXhL2e9IaF4B96JlIv4rICLX3HmeIgM2PKl2MnSt8we5z39bBoLSA0yWG6BvpiMBaFqbo7jeHf1SxI6R404/emHhwW3pwSCDrq2ZE1ATG2UmA5NssFcVuaBPBoQer+n5haVYMNpNUp6rtKZeAIbf5JEOXJ6CJqiInfnnzOMNGhGFkGUYkhsy3p6Ti/lmNMPX/xtY+8ZqMwXf5drssm5KgnQ5nDbVqnTWAhoT/D3t+cJVAaXGTGw88fU0X95dZr8vaL/5nBCj1uUdv5cRBJ8PGhqbBX8PoiXrtGooBGhxf6nHbxIneSzG1++MZGo3e1G,iv:D1lgCnZKm3Gyv6cZpQ7zGW7JXN5RCwoaas+LroTkhPc=,tag:WI6Nr1cX8gm5pjFpu/Ok0w==,type:str]
|
||||
ssh_github_key: ENC[AES256_GCM,data:vZAH4cRDsgGXLAppQKOyUPOvmBJZ27bujMGz4hQ8tt0xhGFUP28llwGZz/VRuU02Yv4alLgVWBAIPuyhZT9f35KnjIR1Mmb7HXk/6oaNM59/lBiISLrnOpC10WmJ9O5krKdxwP8ZDvHA34B0s+oYNkTNXiU0S8AVg3icploax7ylKH5Dorj53kjdYSTjd8KN6ZsgCKmcz97+GnP0IgdmauyNL7e+kv9WIfE8Xx1kGvC8WVnidX2YhSxm6vt8l60eUj9etRigU88oFYTDZ+mIf4lucSpzaLZutz2fM/16D/o9SS7mmTrEllj2S+IXc9ZZTRKKDLbW+yv0XUi0XZi+OHAdZScjS54NZKyT9uWrc/IDJHammGsoHRQpHZtbGhkeFi/KdJsYBsWItslXjM0xJVtFIM2tMnd10kv9UGuXsSl9J4NC0rpz3aXnQqG4ZAhMjN9D/DTJpB4K0pcFyd2FDWdrbKq5iPfnU/V6ecnHPML6wCt6gua/LdK1MWoG3l2SqwMLYj1r7UW5fQZqSw1EK0BAtp9cQMLBL/2w8ykMfWpLekE=,iv:gcinU7xOoXQkFVkLNB3sQYHAcZy3pZN+bDRIq4sspys=,tag:yawgAHBKIkGpnKPHsRId4g==,type:str]
|
||||
sops:
|
||||
age:
|
||||
- recipient: age10pyhca0jy75wtqv5hrn0gf0jcam5272zx9h73a8xwwaxyfq89c0qs5dr9t
|
||||
enc: |
|
||||
- enc: |
|
||||
-----BEGIN AGE ENCRYPTED FILE-----
|
||||
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBMMVVaazhud2paM29JbEJx
|
||||
aUFnajhSd3NxTzB0MndhRk03WjNvV3BVc0NNCnpxR1pjbXVrZ3RPQkppNHJpQ3pX
|
||||
@@ -28,7 +43,8 @@ sops:
|
||||
N3I5dzUwc3JtYzczMUhyT04vSHlZamMKT+FzYcDLmlEFYxm/XoBpJb8XaZzBH1v9
|
||||
6fuez+zApathZfl14w41kAUojPWBznnxDqYtNvzVVLXwnpp3BMx+7w==
|
||||
-----END AGE ENCRYPTED FILE-----
|
||||
lastmodified: "2026-04-30T12:21:26Z"
|
||||
mac: ENC[AES256_GCM,data:sta1qQugWsGS0+g8stmyxHtKOiba6QiVyGfV5krJ688wrW1Ox38RW1cYf9+9Z04hXVQukYguR/k/y7v49oQxoefH5+7zlt/BxzadvPC5f55RsDREC7U4FKcpEEb2Pt1PtscQ3Trx/nDy3x5S8zJ1Uy1QTvSsEccQ+FYel6pcsgQ=,iv:r8spgHthtKoJjlHIpNGpVde1WFVI0xwbE1yJ4W6nHl8=,tag:qXnmmFRDISV3LTmlSlHgvA==,type:str]
|
||||
recipient: age10pyhca0jy75wtqv5hrn0gf0jcam5272zx9h73a8xwwaxyfq89c0qs5dr9t
|
||||
lastmodified: "2026-06-22T18:17:22Z"
|
||||
mac: ENC[AES256_GCM,data:nIGjfBCia9y1+f0dE6TRK6pBLo3B+vqmK88t5xrCY9j+SIzPvCc2Iv6h8AXSfunvIZpxODhn+PmX2FBwa9TtNVePi/Iywu43fRGHz67gSVYTyTBoLRAxqW/7hEvRMXu0ECUfAPzQCq3rd4iWjMXyIYU/FsX9g4NlIno0zcCV5cs=,iv:M4FBoxzojH01hScrRoET3AwmG3qevhkxiET+W94drh0=,tag:rHf7wbkp64FKybjZL0EDDQ==,type:str]
|
||||
unencrypted_suffix: _unencrypted
|
||||
version: 3.12.2
|
||||
version: 3.13.1
|
||||
|
||||
Reference in New Issue
Block a user