feat: seperate applicatoins
This commit is contained in:
parent
515f422f03
commit
5bc30053d1
9 changed files with 220 additions and 130 deletions
|
|
@ -35,70 +35,6 @@
|
||||||
services.resolved.enable = true;
|
services.resolved.enable = true;
|
||||||
|
|
||||||
networking.firewall.enable = true;
|
networking.firewall.enable = true;
|
||||||
# Required for Tailscale
|
|
||||||
networking.firewall.checkReversePath = "loose";
|
|
||||||
networking.firewall.interfaces."tailscale0".allowedTCPPorts = [ 4096 ];
|
|
||||||
|
|
||||||
services.tailscale = {
|
|
||||||
enable = true;
|
|
||||||
};
|
|
||||||
|
|
||||||
systemd.services.tailscale-set-operator = {
|
|
||||||
description = "Set Tailscale local preferences";
|
|
||||||
after = [ "tailscaled.service" ];
|
|
||||||
requires = [ "tailscaled.service" ];
|
|
||||||
wantedBy = [ "multi-user.target" ];
|
|
||||||
serviceConfig.Type = "oneshot";
|
|
||||||
serviceConfig.RemainAfterExit = true;
|
|
||||||
path = [ pkgs.tailscale ];
|
|
||||||
script = ''
|
|
||||||
tailscale set --operator=jet
|
|
||||||
tailscale set --exit-node-allow-lan-access=true
|
|
||||||
'';
|
|
||||||
};
|
|
||||||
|
|
||||||
systemd.services.opencode-tailnet = {
|
|
||||||
description = "Expose OpenCode on the tailnet";
|
|
||||||
after = [
|
|
||||||
"network-online.target"
|
|
||||||
"tailscaled.service"
|
|
||||||
"tailscale-set-operator.service"
|
|
||||||
];
|
|
||||||
wants = [ "network-online.target" ];
|
|
||||||
requires = [
|
|
||||||
"tailscaled.service"
|
|
||||||
"tailscale-set-operator.service"
|
|
||||||
];
|
|
||||||
wantedBy = [ "multi-user.target" ];
|
|
||||||
path = [
|
|
||||||
pkgs.tailscale
|
|
||||||
pkgs.coreutils
|
|
||||||
pkgs.gnugrep
|
|
||||||
];
|
|
||||||
preStart = ''
|
|
||||||
for attempt in {1..60}; do
|
|
||||||
if tailscale status --json --peers=false | grep -q '"BackendState": *"Running"'; then
|
|
||||||
tailscale serve --bg 4096
|
|
||||||
exit 0
|
|
||||||
fi
|
|
||||||
|
|
||||||
sleep 1
|
|
||||||
done
|
|
||||||
|
|
||||||
echo "Timed out waiting for Tailscale to reach Running state"
|
|
||||||
exit 1
|
|
||||||
'';
|
|
||||||
serviceConfig = {
|
|
||||||
Type = "simple";
|
|
||||||
User = "jet";
|
|
||||||
Environment = [ "OPENCODE_DB=opencode.db" ];
|
|
||||||
Restart = "always";
|
|
||||||
RestartSec = 5;
|
|
||||||
TimeoutStartSec = 75;
|
|
||||||
ExecStart = "/etc/profiles/per-user/jet/bin/o serve --hostname 127.0.0.1 --port 4096";
|
|
||||||
WorkingDirectory = config.users.users.jet.home;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
time.timeZone = "America/Los_Angeles";
|
time.timeZone = "America/Los_Angeles";
|
||||||
i18n.defaultLocale = "en_US.UTF-8";
|
i18n.defaultLocale = "en_US.UTF-8";
|
||||||
|
|
@ -389,12 +325,9 @@
|
||||||
# Enable base suspend/resume hooks.
|
# Enable base suspend/resume hooks.
|
||||||
powerManagement.enable = true;
|
powerManagement.enable = true;
|
||||||
|
|
||||||
# v4l2loopback for OBS Virtual Camera
|
# Framework AMD laptops perform best with the US regulatory domain set explicitly.
|
||||||
boot.extraModulePackages = with config.boot.kernelPackages; [ v4l2loopback ];
|
|
||||||
boot.kernelModules = [ "v4l2loopback" ];
|
|
||||||
boot.extraModprobeConfig = ''
|
boot.extraModprobeConfig = ''
|
||||||
options cfg80211 ieee80211_regdom=US
|
options cfg80211 ieee80211_regdom=US
|
||||||
options v4l2loopback devices=1 video_nr=1 card_label="OBS Virtual Camera" exclusive_caps=1
|
|
||||||
'';
|
'';
|
||||||
|
|
||||||
# RAM optimizations for 96GB system
|
# RAM optimizations for 96GB system
|
||||||
|
|
@ -420,7 +353,6 @@
|
||||||
wget
|
wget
|
||||||
];
|
];
|
||||||
|
|
||||||
programs.steam.enable = true;
|
|
||||||
programs.nix-index-database.comma.enable = true;
|
programs.nix-index-database.comma.enable = true;
|
||||||
|
|
||||||
programs._1password.enable = true;
|
programs._1password.enable = true;
|
||||||
|
|
@ -435,14 +367,8 @@
|
||||||
binfmt = true;
|
binfmt = true;
|
||||||
};
|
};
|
||||||
|
|
||||||
# GameCube adapter udev rules for Slippi/Dolphin
|
|
||||||
# Disable USB autosuspend for Framework's problematic devices (fingerprint reader, USB-C hub)
|
# Disable USB autosuspend for Framework's problematic devices (fingerprint reader, USB-C hub)
|
||||||
services.udev.extraRules = ''
|
services.udev.extraRules = ''
|
||||||
# GameCube adapter USB device (vendor ID 057e, product ID 0337)
|
|
||||||
SUBSYSTEM=="usb", ENV{DEVTYPE}=="usb_device", ATTRS{idVendor}=="057e", ATTRS{idProduct}=="0337", MODE="0666"
|
|
||||||
# GameCube adapter HID device (needed for Dolphin to access controllers)
|
|
||||||
KERNEL=="hidraw*", ATTRS{idVendor}=="057e", ATTRS{idProduct}=="0337", MODE="0666", GROUP="input"
|
|
||||||
# Disable autosuspend for Framework devices that have shown resume issues.
|
|
||||||
ACTION=="add", SUBSYSTEM=="usb", ATTR{idVendor}=="27c6", ATTR{idProduct}=="609c", ATTR{power/control}="on", ATTR{power/autosuspend}="-1"
|
ACTION=="add", SUBSYSTEM=="usb", ATTR{idVendor}=="27c6", ATTR{idProduct}=="609c", ATTR{power/control}="on", ATTR{power/autosuspend}="-1"
|
||||||
ACTION=="add", SUBSYSTEM=="usb", ATTR{idVendor}=="32ac", ATTR{power/control}="on", ATTR{power/autosuspend}="-1"
|
ACTION=="add", SUBSYSTEM=="usb", ATTR{idVendor}=="32ac", ATTR{power/control}="on", ATTR{power/autosuspend}="-1"
|
||||||
ACTION=="add", SUBSYSTEM=="pci", ATTR{vendor}=="0x1022", ATTR{class}=="0x0c0330", ATTR{power/control}="on"
|
ACTION=="add", SUBSYSTEM=="pci", ATTR{vendor}=="0x1022", ATTR{class}=="0x0c0330", ATTR{power/control}="on"
|
||||||
|
|
|
||||||
|
|
@ -105,11 +105,16 @@
|
||||||
sudo -v || exit $?
|
sudo -v || exit $?
|
||||||
nh os switch --hostname "$(${pkgs.hostname}/bin/hostname)" path:. "$@"
|
nh os switch --hostname "$(${pkgs.hostname}/bin/hostname)" path:. "$@"
|
||||||
'';
|
'';
|
||||||
|
nhb = pkgs.writeShellScriptBin "nhb" ''
|
||||||
|
sudo -v || exit $?
|
||||||
|
nh os boot --hostname "$(${pkgs.hostname}/bin/hostname)" path:. "$@"
|
||||||
|
'';
|
||||||
in
|
in
|
||||||
pkgs.mkShell {
|
pkgs.mkShell {
|
||||||
packages = [
|
packages = [
|
||||||
pkgs.nh
|
pkgs.nh
|
||||||
inputs.agenix.packages.x86_64-linux.default
|
inputs.agenix.packages.x86_64-linux.default
|
||||||
|
nhb
|
||||||
nhs
|
nhs
|
||||||
];
|
];
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,9 @@
|
||||||
{ lib, pkgs, ... }:
|
{
|
||||||
|
hostname,
|
||||||
|
lib,
|
||||||
|
pkgs,
|
||||||
|
...
|
||||||
|
}:
|
||||||
|
|
||||||
let
|
let
|
||||||
firefoxApplicationId = "{ec8030f7-c20a-464f-9b0e-13a3a9e97384}";
|
firefoxApplicationId = "{ec8030f7-c20a-464f-9b0e-13a3a9e97384}";
|
||||||
|
|
@ -63,7 +68,7 @@ let
|
||||||
});
|
});
|
||||||
in
|
in
|
||||||
{
|
{
|
||||||
home.packages = [ torBrowser ];
|
home.packages = lib.optionals (hostname == "framework") [ torBrowser ];
|
||||||
|
|
||||||
programs.zen-browser = {
|
programs.zen-browser = {
|
||||||
enable = true;
|
enable = true;
|
||||||
|
|
@ -179,13 +184,21 @@ in
|
||||||
force = true;
|
force = true;
|
||||||
engines = {
|
engines = {
|
||||||
"Google Web" = {
|
"Google Web" = {
|
||||||
urls = [ { template = "https://www.google.com/search?q={searchTerms}&udm=14&pws=0&filter=0&nfpr=1&hl=en&gl=US&safe=active"; } ];
|
urls = [
|
||||||
|
{
|
||||||
|
template = "https://www.google.com/search?q={searchTerms}&udm=14&pws=0&filter=0&nfpr=1&hl=en&gl=US&safe=active";
|
||||||
|
}
|
||||||
|
];
|
||||||
definedAliases = [
|
definedAliases = [
|
||||||
"@g"
|
"@g"
|
||||||
];
|
];
|
||||||
};
|
};
|
||||||
"Google Basic" = {
|
"Google Basic" = {
|
||||||
urls = [ { template = "https://www.google.com/search?gbv=1&q={searchTerms}&udm=14&pws=0&filter=0&nfpr=1&hl=en&gl=US&safe=active"; } ];
|
urls = [
|
||||||
|
{
|
||||||
|
template = "https://www.google.com/search?gbv=1&q={searchTerms}&udm=14&pws=0&filter=0&nfpr=1&hl=en&gl=US&safe=active";
|
||||||
|
}
|
||||||
|
];
|
||||||
definedAliases = [
|
definedAliases = [
|
||||||
"@gb"
|
"@gb"
|
||||||
"@gnj"
|
"@gnj"
|
||||||
|
|
|
||||||
|
|
@ -18,7 +18,9 @@ let
|
||||||
"-${osConfig.age.secrets."nasa-api-env".path}"
|
"-${osConfig.age.secrets."nasa-api-env".path}"
|
||||||
else
|
else
|
||||||
"-%h/.config/nasa-api.env";
|
"-%h/.config/nasa-api.env";
|
||||||
chatDesktopId = if hostname == "framework-work" then "slack.desktop" else "vesktop.desktop";
|
isWork = hostname == "framework-work";
|
||||||
|
isPersonal = hostname == "framework";
|
||||||
|
chatDesktopId = if isWork then "slack.desktop" else "vesktop.desktop";
|
||||||
favoriteApps = [
|
favoriteApps = [
|
||||||
"zen-beta.desktop"
|
"zen-beta.desktop"
|
||||||
"com.mitchellh.ghostty.desktop"
|
"com.mitchellh.ghostty.desktop"
|
||||||
|
|
@ -26,13 +28,13 @@ let
|
||||||
"betterbird.desktop"
|
"betterbird.desktop"
|
||||||
]
|
]
|
||||||
++ (
|
++ (
|
||||||
if hostname == "framework-work" then
|
if isPersonal then
|
||||||
[ ]
|
|
||||||
else
|
|
||||||
[
|
[
|
||||||
"signal.desktop"
|
"signal.desktop"
|
||||||
"zulip.desktop"
|
"zulip.desktop"
|
||||||
]
|
]
|
||||||
|
else
|
||||||
|
[ ]
|
||||||
);
|
);
|
||||||
autoMoveApplications = [
|
autoMoveApplications = [
|
||||||
"zen-beta.desktop:1"
|
"zen-beta.desktop:1"
|
||||||
|
|
@ -41,32 +43,38 @@ let
|
||||||
"betterbird.desktop:4"
|
"betterbird.desktop:4"
|
||||||
]
|
]
|
||||||
++ (
|
++ (
|
||||||
if hostname == "framework-work" then
|
if isPersonal then
|
||||||
[ ]
|
|
||||||
else
|
|
||||||
[
|
[
|
||||||
"signal.desktop:5"
|
"signal.desktop:5"
|
||||||
"zulip.desktop:6"
|
"zulip.desktop:6"
|
||||||
]
|
]
|
||||||
|
else
|
||||||
|
[ ]
|
||||||
);
|
);
|
||||||
autostartEntries = [
|
autostartEntries = [
|
||||||
"${homeLib.zenStartup}/share/applications/zen-startup.desktop"
|
"${homeLib.zenStartup}/share/applications/zen-startup.desktop"
|
||||||
"${homeLib.ghosttyZellijStartup}/share/applications/ghostty-zellij-startup.desktop"
|
"${homeLib.ghosttyZellijStartup}/share/applications/ghostty-zellij-startup.desktop"
|
||||||
]
|
]
|
||||||
++ (
|
++ (
|
||||||
if hostname == "framework-work" then
|
if isWork then
|
||||||
[
|
[
|
||||||
"${pkgs.slack}/share/applications/slack.desktop"
|
"${pkgs.slack}/share/applications/slack.desktop"
|
||||||
"${homeLib.betterbirdStartup}/share/applications/betterbird-startup.desktop"
|
"${homeLib.betterbirdStartup}/share/applications/betterbird-startup.desktop"
|
||||||
]
|
]
|
||||||
else
|
else if isPersonal then
|
||||||
[
|
[
|
||||||
"${homeLib.vesktopStartup}/share/applications/vesktop-startup.desktop"
|
"${homeLib.vesktopStartup}/share/applications/vesktop-startup.desktop"
|
||||||
"${homeLib.betterbirdStartup}/share/applications/betterbird-startup.desktop"
|
"${homeLib.betterbirdStartup}/share/applications/betterbird-startup.desktop"
|
||||||
"${homeLib.signalStartup}/share/applications/signal-startup.desktop"
|
"${homeLib.signalStartup}/share/applications/signal-startup.desktop"
|
||||||
"${homeLib.zulipStartup}/share/applications/zulip-startup.desktop"
|
"${homeLib.zulipStartup}/share/applications/zulip-startup.desktop"
|
||||||
]
|
]
|
||||||
|
else
|
||||||
|
[ ]
|
||||||
);
|
);
|
||||||
|
personalEnabledExtensions = pkgs.lib.optionals isPersonal [
|
||||||
|
"tailscale-gnome-qs@tailscale-qs.github.io"
|
||||||
|
"evil-bit-toggle@jetpham.github.com"
|
||||||
|
];
|
||||||
vlcDesktop = "vlc.desktop";
|
vlcDesktop = "vlc.desktop";
|
||||||
vlcVideoMimeTypes = [
|
vlcVideoMimeTypes = [
|
||||||
"application/mxf"
|
"application/mxf"
|
||||||
|
|
@ -121,6 +129,18 @@ let
|
||||||
"x-content/video-svcd"
|
"x-content/video-svcd"
|
||||||
"x-content/video-vcd"
|
"x-content/video-vcd"
|
||||||
];
|
];
|
||||||
|
personalMimeDefaults =
|
||||||
|
pkgs.lib.optionalAttrs isPersonal {
|
||||||
|
"x-content/image-dcf" = "net.damonlynch.RapidPhotoDownloader.desktop";
|
||||||
|
}
|
||||||
|
// pkgs.lib.optionalAttrs isPersonal (
|
||||||
|
builtins.listToAttrs (
|
||||||
|
map (mimeType: {
|
||||||
|
name = mimeType;
|
||||||
|
value = vlcDesktop;
|
||||||
|
}) vlcVideoMimeTypes
|
||||||
|
)
|
||||||
|
);
|
||||||
in
|
in
|
||||||
|
|
||||||
{
|
{
|
||||||
|
|
@ -146,7 +166,7 @@ in
|
||||||
autorun-never = false;
|
autorun-never = false;
|
||||||
autorun-x-content-ignore = [ ];
|
autorun-x-content-ignore = [ ];
|
||||||
autorun-x-content-open-folder = [ ];
|
autorun-x-content-open-folder = [ ];
|
||||||
autorun-x-content-start-app = [ "x-content/image-dcf" ];
|
autorun-x-content-start-app = pkgs.lib.optionals isPersonal [ "x-content/image-dcf" ];
|
||||||
};
|
};
|
||||||
"org/gnome/settings-daemon/plugins/power" = {
|
"org/gnome/settings-daemon/plugins/power" = {
|
||||||
sleep-inactive-ac-type = "nothing";
|
sleep-inactive-ac-type = "nothing";
|
||||||
|
|
@ -183,14 +203,13 @@ in
|
||||||
"wifiqrcode@glerro.pm.me"
|
"wifiqrcode@glerro.pm.me"
|
||||||
"system-monitor-next@paradoxxx.zero.gmail.com"
|
"system-monitor-next@paradoxxx.zero.gmail.com"
|
||||||
"clipboard-indicator@tudmotu.com"
|
"clipboard-indicator@tudmotu.com"
|
||||||
"tailscale-gnome-qs@tailscale-qs.github.io"
|
|
||||||
"auto-move-windows@gnome-shell-extensions.gcampax.github.com"
|
"auto-move-windows@gnome-shell-extensions.gcampax.github.com"
|
||||||
"gnome-shell-extension-maximized-by-default@stiggimy.github.com"
|
"gnome-shell-extension-maximized-by-default@stiggimy.github.com"
|
||||||
"no-titlebar-when-maximized@alec.ninja"
|
"no-titlebar-when-maximized@alec.ninja"
|
||||||
"opencode-token-usage@jetpham.github.com"
|
"opencode-token-usage@jetpham.github.com"
|
||||||
"evil-bit-toggle@jetpham.github.com"
|
|
||||||
"reduced-motion-toggle@jetpham.github.com"
|
"reduced-motion-toggle@jetpham.github.com"
|
||||||
];
|
]
|
||||||
|
++ personalEnabledExtensions;
|
||||||
favorite-apps = favoriteApps;
|
favorite-apps = favoriteApps;
|
||||||
};
|
};
|
||||||
"org/gnome/shell/extensions/auto-move-windows" = {
|
"org/gnome/shell/extensions/auto-move-windows" = {
|
||||||
|
|
@ -305,7 +324,7 @@ in
|
||||||
Install.WantedBy = [ "timers.target" ];
|
Install.WantedBy = [ "timers.target" ];
|
||||||
};
|
};
|
||||||
|
|
||||||
xdg.desktopEntries."net.damonlynch.RapidPhotoDownloader" = {
|
xdg.desktopEntries."net.damonlynch.RapidPhotoDownloader" = pkgs.lib.mkIf isPersonal {
|
||||||
name = "Rapid Photo Downloader";
|
name = "Rapid Photo Downloader";
|
||||||
genericName = "Photo Downloader";
|
genericName = "Photo Downloader";
|
||||||
comment = "Download, rename, and back up photos and videos from cameras and cards";
|
comment = "Download, rename, and back up photos and videos from cameras and cards";
|
||||||
|
|
@ -333,7 +352,6 @@ in
|
||||||
"x-scheme-handler/unknown" = "zen-beta.desktop";
|
"x-scheme-handler/unknown" = "zen-beta.desktop";
|
||||||
"x-scheme-handler/mailto" = "betterbird.desktop";
|
"x-scheme-handler/mailto" = "betterbird.desktop";
|
||||||
"inode/directory" = "org.gnome.Nautilus.desktop";
|
"inode/directory" = "org.gnome.Nautilus.desktop";
|
||||||
"x-content/image-dcf" = "net.damonlynch.RapidPhotoDownloader.desktop";
|
|
||||||
"image/x-canon-cr2" = "gimp.desktop";
|
"image/x-canon-cr2" = "gimp.desktop";
|
||||||
"application/zip" = "org.gnome.FileRoller.desktop";
|
"application/zip" = "org.gnome.FileRoller.desktop";
|
||||||
"application/x-tar" = "org.gnome.FileRoller.desktop";
|
"application/x-tar" = "org.gnome.FileRoller.desktop";
|
||||||
|
|
@ -346,11 +364,6 @@ in
|
||||||
"application/x-rar" = "org.gnome.FileRoller.desktop";
|
"application/x-rar" = "org.gnome.FileRoller.desktop";
|
||||||
"application/x-rar-compressed" = "org.gnome.FileRoller.desktop";
|
"application/x-rar-compressed" = "org.gnome.FileRoller.desktop";
|
||||||
}
|
}
|
||||||
// builtins.listToAttrs (
|
// personalMimeDefaults;
|
||||||
map (mimeType: {
|
|
||||||
name = mimeType;
|
|
||||||
value = vlcDesktop;
|
|
||||||
}) vlcVideoMimeTypes
|
|
||||||
);
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,9 @@
|
||||||
{ homeLib, pkgs, ... }:
|
{
|
||||||
|
homeLib,
|
||||||
|
hostname,
|
||||||
|
pkgs,
|
||||||
|
...
|
||||||
|
}:
|
||||||
|
|
||||||
let
|
let
|
||||||
chromeDevtoolsMcpShell = pkgs.runCommand "chrome-devtools-mcp-shell-path" { } ''
|
chromeDevtoolsMcpShell = pkgs.runCommand "chrome-devtools-mcp-shell-path" { } ''
|
||||||
|
|
@ -41,12 +46,12 @@ in
|
||||||
mcp.linear = {
|
mcp.linear = {
|
||||||
type = "remote";
|
type = "remote";
|
||||||
url = "https://mcp.linear.app/mcp";
|
url = "https://mcp.linear.app/mcp";
|
||||||
enabled = true;
|
enabled = hostname == "framework-work";
|
||||||
};
|
};
|
||||||
mcp.heytea = {
|
mcp.heytea = {
|
||||||
type = "remote";
|
type = "remote";
|
||||||
url = "https://mcp.heytea.dev/mcp";
|
url = "https://mcp.heytea.dev/mcp";
|
||||||
enabled = true;
|
enabled = hostname == "framework";
|
||||||
};
|
};
|
||||||
mcp.cloudflare-api = {
|
mcp.cloudflare-api = {
|
||||||
type = "remote";
|
type = "remote";
|
||||||
|
|
|
||||||
|
|
@ -2,10 +2,14 @@
|
||||||
inputs,
|
inputs,
|
||||||
pkgs,
|
pkgs,
|
||||||
homeLib,
|
homeLib,
|
||||||
|
hostname,
|
||||||
...
|
...
|
||||||
}:
|
}:
|
||||||
|
|
||||||
let
|
let
|
||||||
|
isWork = hostname == "framework-work";
|
||||||
|
isPersonal = hostname == "framework";
|
||||||
|
|
||||||
evilBitCtl = pkgs.writeShellApplication {
|
evilBitCtl = pkgs.writeShellApplication {
|
||||||
name = "evil-bitctl";
|
name = "evil-bitctl";
|
||||||
runtimeInputs = [
|
runtimeInputs = [
|
||||||
|
|
@ -118,10 +122,8 @@ let
|
||||||
runHook postInstall
|
runHook postInstall
|
||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
in
|
|
||||||
|
|
||||||
{
|
sharedPackages = with pkgs; [
|
||||||
home.packages = with pkgs; [
|
|
||||||
bat
|
bat
|
||||||
bun
|
bun
|
||||||
claude-code
|
claude-code
|
||||||
|
|
@ -153,10 +155,8 @@ in
|
||||||
typescript-language-server
|
typescript-language-server
|
||||||
nil
|
nil
|
||||||
|
|
||||||
element-desktop
|
|
||||||
file-roller
|
file-roller
|
||||||
font-manager
|
font-manager
|
||||||
foliate
|
|
||||||
(gimp-with-plugins.override {
|
(gimp-with-plugins.override {
|
||||||
plugins = with gimpPlugins; [
|
plugins = with gimpPlugins; [
|
||||||
gmic
|
gmic
|
||||||
|
|
@ -166,26 +166,11 @@ in
|
||||||
google-chrome
|
google-chrome
|
||||||
handbrake
|
handbrake
|
||||||
inkscape
|
inkscape
|
||||||
kdePackages.kdenlive
|
|
||||||
libreoffice
|
libreoffice
|
||||||
logseq
|
|
||||||
nufraw-thumbnailer
|
|
||||||
obs-studio
|
|
||||||
pavucontrol
|
pavucontrol
|
||||||
prismlauncher
|
|
||||||
qpwgraph
|
qpwgraph
|
||||||
signal-desktop
|
|
||||||
slack
|
|
||||||
vesktop
|
|
||||||
vlc
|
|
||||||
zulip
|
|
||||||
linphone
|
|
||||||
lmstudio
|
lmstudio
|
||||||
homeLib.betterbird
|
homeLib.betterbird
|
||||||
darktable
|
|
||||||
digikam
|
|
||||||
exiftool
|
|
||||||
rapid-photo-downloader
|
|
||||||
brightnessctl
|
brightnessctl
|
||||||
nautilus
|
nautilus
|
||||||
playerctl
|
playerctl
|
||||||
|
|
@ -200,12 +185,43 @@ in
|
||||||
gnomeExtensions.maximized-by-default-actually-reborn
|
gnomeExtensions.maximized-by-default-actually-reborn
|
||||||
gnomeExtensions.no-titlebar-when-maximized
|
gnomeExtensions.no-titlebar-when-maximized
|
||||||
gnomeExtensions.system-monitor-next
|
gnomeExtensions.system-monitor-next
|
||||||
gnomeExtensions.tailscale-qs
|
|
||||||
gnomeExtensions.wifi-qrcode
|
gnomeExtensions.wifi-qrcode
|
||||||
evilBitToggleExtension
|
|
||||||
opencodeTokenUsageExtension
|
opencodeTokenUsageExtension
|
||||||
reducedMotionToggleExtension
|
reducedMotionToggleExtension
|
||||||
|
|
||||||
nerd-fonts.commit-mono
|
nerd-fonts.commit-mono
|
||||||
];
|
];
|
||||||
|
|
||||||
|
workPackages = with pkgs; [
|
||||||
|
slack
|
||||||
|
];
|
||||||
|
|
||||||
|
personalPackages = with pkgs; [
|
||||||
|
element-desktop
|
||||||
|
foliate
|
||||||
|
kdePackages.kdenlive
|
||||||
|
logseq
|
||||||
|
nufraw-thumbnailer
|
||||||
|
obs-studio
|
||||||
|
prismlauncher
|
||||||
|
signal-desktop
|
||||||
|
vesktop
|
||||||
|
vlc
|
||||||
|
zulip
|
||||||
|
linphone
|
||||||
|
darktable
|
||||||
|
digikam
|
||||||
|
exiftool
|
||||||
|
rapid-photo-downloader
|
||||||
|
|
||||||
|
gnomeExtensions.tailscale-qs
|
||||||
|
evilBitToggleExtension
|
||||||
|
];
|
||||||
|
in
|
||||||
|
|
||||||
|
{
|
||||||
|
home.packages =
|
||||||
|
sharedPackages
|
||||||
|
++ pkgs.lib.optionals isWork workPackages
|
||||||
|
++ pkgs.lib.optionals isPersonal personalPackages;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,14 @@
|
||||||
{ config, pkgs, ... }:
|
{
|
||||||
|
config,
|
||||||
|
hostname,
|
||||||
|
lib,
|
||||||
|
pkgs,
|
||||||
|
...
|
||||||
|
}:
|
||||||
|
|
||||||
let
|
let
|
||||||
|
isPersonal = hostname == "framework";
|
||||||
|
|
||||||
configureQbittorrentTailscale = pkgs.writeShellApplication {
|
configureQbittorrentTailscale = pkgs.writeShellApplication {
|
||||||
name = "configure-qbittorrent-tailscale";
|
name = "configure-qbittorrent-tailscale";
|
||||||
runtimeInputs = [
|
runtimeInputs = [
|
||||||
|
|
@ -24,6 +32,7 @@ let
|
||||||
postBuild = ''
|
postBuild = ''
|
||||||
rm -f "$out/bin/qbittorrent"
|
rm -f "$out/bin/qbittorrent"
|
||||||
# Enforce qBittorrent's bind settings, then add a systemd interface allowlist.
|
# Enforce qBittorrent's bind settings, then add a systemd interface allowlist.
|
||||||
|
# RestrictNetworkInterfaces works for transient services, not transient scopes.
|
||||||
cat > "$out/bin/qbittorrent" <<'EOF'
|
cat > "$out/bin/qbittorrent" <<'EOF'
|
||||||
#!${pkgs.runtimeShell}
|
#!${pkgs.runtimeShell}
|
||||||
set -eu
|
set -eu
|
||||||
|
|
@ -37,7 +46,6 @@ let
|
||||||
|
|
||||||
exec ${pkgs.systemd}/bin/systemd-run \
|
exec ${pkgs.systemd}/bin/systemd-run \
|
||||||
--user \
|
--user \
|
||||||
--scope \
|
|
||||||
--quiet \
|
--quiet \
|
||||||
--collect \
|
--collect \
|
||||||
--property='RestrictNetworkInterfaces=lo tailscale0' \
|
--property='RestrictNetworkInterfaces=lo tailscale0' \
|
||||||
|
|
@ -57,10 +65,27 @@ let
|
||||||
};
|
};
|
||||||
in
|
in
|
||||||
|
|
||||||
{
|
lib.mkIf isPersonal {
|
||||||
home.activation.configureQbittorrentTailscale = config.lib.dag.entryAfter [ "writeBoundary" ] ''
|
home.activation.configureQbittorrentTailscale = config.lib.dag.entryAfter [ "writeBoundary" ] ''
|
||||||
${configureQbittorrentTailscale}/bin/configure-qbittorrent-tailscale
|
${configureQbittorrentTailscale}/bin/configure-qbittorrent-tailscale
|
||||||
'';
|
'';
|
||||||
|
|
||||||
|
home.file.".local/share/applications/org.qbittorrent.qBittorrent.desktop".text = ''
|
||||||
|
[Desktop Entry]
|
||||||
|
Categories=Network;FileTransfer;P2P;Qt;
|
||||||
|
Exec=${qbittorrentTailscale}/bin/qbittorrent %U
|
||||||
|
GenericName=BitTorrent client
|
||||||
|
Comment=Download and share files over BitTorrent
|
||||||
|
Icon=qbittorrent
|
||||||
|
MimeType=application/x-bittorrent;x-scheme-handler/magnet;
|
||||||
|
Name=qBittorrent
|
||||||
|
Terminal=false
|
||||||
|
Type=Application
|
||||||
|
StartupNotify=false
|
||||||
|
StartupWMClass=qbittorrent
|
||||||
|
Keywords=bittorrent;torrent;magnet;download;p2p;
|
||||||
|
SingleMainWindow=true
|
||||||
|
'';
|
||||||
|
|
||||||
home.packages = [ qbittorrentTailscale ];
|
home.packages = [ qbittorrentTailscale ];
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -57,6 +57,8 @@ let
|
||||||
"${pkgs.wl-clipboard}/bin/wl-paste --type image --watch ${pkgs.cliphist}/bin/cliphist store"
|
"${pkgs.wl-clipboard}/bin/wl-paste --type image --watch ${pkgs.cliphist}/bin/cliphist store"
|
||||||
"${pkgs.swayidle}/bin/swayidle -w timeout 300 '${lockCommand}' before-sleep '${lockCommand}'"
|
"${pkgs.swayidle}/bin/swayidle -w timeout 300 '${lockCommand}' before-sleep '${lockCommand}'"
|
||||||
];
|
];
|
||||||
|
isWork = hostname == "framework-work";
|
||||||
|
isPersonal = hostname == "framework";
|
||||||
workStartup = [
|
workStartup = [
|
||||||
"${config.programs.zen-browser.package}/bin/zen-beta"
|
"${config.programs.zen-browser.package}/bin/zen-beta"
|
||||||
"${pkgs.ghostty}/bin/ghostty --fullscreen=true -e ${homeLib.zellijPersistentSession}/bin/zellij-persistent-session"
|
"${pkgs.ghostty}/bin/ghostty --fullscreen=true -e ${homeLib.zellijPersistentSession}/bin/zellij-persistent-session"
|
||||||
|
|
@ -71,7 +73,13 @@ let
|
||||||
"${pkgs.signal-desktop}/bin/signal-desktop --start-fullscreen"
|
"${pkgs.signal-desktop}/bin/signal-desktop --start-fullscreen"
|
||||||
"${pkgs.zulip}/bin/zulip --start-fullscreen"
|
"${pkgs.zulip}/bin/zulip --start-fullscreen"
|
||||||
];
|
];
|
||||||
appStartup = if hostname == "framework-work" then workStartup else personalStartup;
|
appStartup =
|
||||||
|
if isWork then
|
||||||
|
workStartup
|
||||||
|
else if isPersonal then
|
||||||
|
personalStartup
|
||||||
|
else
|
||||||
|
[ ];
|
||||||
in
|
in
|
||||||
|
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
{ ... }:
|
{ config, pkgs, ... }:
|
||||||
|
|
||||||
{
|
{
|
||||||
imports = [
|
imports = [
|
||||||
|
|
@ -8,6 +8,85 @@
|
||||||
|
|
||||||
networking.hostName = "framework";
|
networking.hostName = "framework";
|
||||||
|
|
||||||
|
# Tailscale and tailnet exposure are personal-laptop only.
|
||||||
|
networking.firewall.checkReversePath = "loose";
|
||||||
|
networking.firewall.interfaces."tailscale0".allowedTCPPorts = [ 4096 ];
|
||||||
|
|
||||||
|
services.tailscale.enable = true;
|
||||||
|
|
||||||
|
systemd.services.tailscale-set-operator = {
|
||||||
|
description = "Set Tailscale local preferences";
|
||||||
|
after = [ "tailscaled.service" ];
|
||||||
|
requires = [ "tailscaled.service" ];
|
||||||
|
wantedBy = [ "multi-user.target" ];
|
||||||
|
serviceConfig.Type = "oneshot";
|
||||||
|
serviceConfig.RemainAfterExit = true;
|
||||||
|
path = [ pkgs.tailscale ];
|
||||||
|
script = ''
|
||||||
|
tailscale set --operator=jet
|
||||||
|
tailscale set --exit-node-allow-lan-access=true
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
systemd.services.opencode-tailnet = {
|
||||||
|
description = "Expose OpenCode on the tailnet";
|
||||||
|
after = [
|
||||||
|
"network-online.target"
|
||||||
|
"tailscaled.service"
|
||||||
|
"tailscale-set-operator.service"
|
||||||
|
];
|
||||||
|
wants = [ "network-online.target" ];
|
||||||
|
requires = [
|
||||||
|
"tailscaled.service"
|
||||||
|
"tailscale-set-operator.service"
|
||||||
|
];
|
||||||
|
wantedBy = [ "multi-user.target" ];
|
||||||
|
path = [
|
||||||
|
pkgs.tailscale
|
||||||
|
pkgs.coreutils
|
||||||
|
pkgs.gnugrep
|
||||||
|
];
|
||||||
|
preStart = ''
|
||||||
|
for attempt in {1..60}; do
|
||||||
|
if tailscale status --json --peers=false | grep -q '"BackendState": *"Running"'; then
|
||||||
|
tailscale serve --bg 4096
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
sleep 1
|
||||||
|
done
|
||||||
|
|
||||||
|
echo "Timed out waiting for Tailscale to reach Running state"
|
||||||
|
exit 1
|
||||||
|
'';
|
||||||
|
serviceConfig = {
|
||||||
|
Type = "simple";
|
||||||
|
User = "jet";
|
||||||
|
Environment = [ "OPENCODE_DB=opencode.db" ];
|
||||||
|
Restart = "always";
|
||||||
|
RestartSec = 5;
|
||||||
|
TimeoutStartSec = 75;
|
||||||
|
ExecStart = "/etc/profiles/per-user/jet/bin/o serve --hostname 127.0.0.1 --port 4096";
|
||||||
|
WorkingDirectory = config.users.users.jet.home;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
programs.steam.enable = true;
|
||||||
|
|
||||||
|
# Personal media/gaming hardware support.
|
||||||
|
boot.extraModulePackages = with config.boot.kernelPackages; [ v4l2loopback ];
|
||||||
|
boot.kernelModules = [ "v4l2loopback" ];
|
||||||
|
boot.extraModprobeConfig = ''
|
||||||
|
options v4l2loopback devices=1 video_nr=1 card_label="OBS Virtual Camera" exclusive_caps=1
|
||||||
|
'';
|
||||||
|
|
||||||
|
services.udev.extraRules = ''
|
||||||
|
# GameCube adapter USB device (vendor ID 057e, product ID 0337)
|
||||||
|
SUBSYSTEM=="usb", ENV{DEVTYPE}=="usb_device", ATTRS{idVendor}=="057e", ATTRS{idProduct}=="0337", MODE="0666"
|
||||||
|
# GameCube adapter HID device (needed for Dolphin to access controllers)
|
||||||
|
KERNEL=="hidraw*", ATTRS{idVendor}=="057e", ATTRS{idProduct}=="0337", MODE="0666", GROUP="input"
|
||||||
|
'';
|
||||||
|
|
||||||
fileSystems."/tmp" = {
|
fileSystems."/tmp" = {
|
||||||
device = "tmpfs";
|
device = "tmpfs";
|
||||||
fsType = "tmpfs";
|
fsType = "tmpfs";
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue