Compare commits

...

5 commits

Author SHA1 Message Date
0e91b2184d
docs: moar 2025-12-08 00:02:15 -08:00
a3eba2f54f
docs: more todos 2025-12-08 00:01:36 -08:00
375c15c0a8
feat: to-dos, clean up 2025-12-08 00:00:34 -08:00
b0b1afc339
fix: battery 2025-12-07 23:47:53 -08:00
1ba98534eb
feat: battery, refactor 2025-12-07 23:37:25 -08:00
25 changed files with 305 additions and 41 deletions

26
TODO.md
View file

@ -2,8 +2,9 @@
- [ ] Make personal homepage o: - [ ] Make personal homepage o:
- [ ] Figure out storing bookmarks, lists, data ... - [ ] Figure out storing bookmarks, lists, data ...
- [ ] Make my own quickshell config
- [ ] Look into Matrix and Fedi accounts and setting up app(s) - [ ] Look into Matrix and Fedi accounts and setting up app(s)
- [ ] matrix.org or nix.dev
- [ ] Desktop
- [ ] Test performance for virtual machines on laptop and desktop - [ ] Test performance for virtual machines on laptop and desktop
## New service deployments ## New service deployments
@ -11,9 +12,30 @@
- [ ] Fauna - [ ] Fauna
- [ ] Jellyfin - [ ] Jellyfin
- [ ] Immich - [ ] Immich
- [ ] Prosody - [x] Prosody
- [x] continuwuation - [x] continuwuation
## Quickshell
- [x] Clock
- [x] Stylix
- [x] Workspaces
- [x] State Colours
- [x] System Tray
- [x] Notification Area
- [x] Active Window Title & Icon
- [x] Battery
- [ ] Pipewire
- [ ] Bluetooth
- [ ] Control Area
- [x] NixOS Logo button
- [ ] User icon & username
- [ ] Media Widgets
- [ ] VRAM usage
- [ ] Lockscreen
- [ ] Konawall / booru API integration?
- [ ] Tooltip type that doesn't suck
## Migrations ## Migrations
- [ ] Move away from flakes to either npins or lon (not that they replied; https://github.com/nikstur/lon/issues/57#issue-3652308987) - [ ] Move away from flakes to either npins or lon (not that they replied; https://github.com/nikstur/lon/issues/57#issue-3652308987)

View file

@ -11,6 +11,7 @@
telegram-desktop # Telegram telegram-desktop # Telegram
signal-desktop signal-desktop
fluffychat fluffychat
dino
mumble mumble
keymapp keymapp
# Archivery # Archivery

46
nixos/servers/prosody.nix Normal file
View file

@ -0,0 +1,46 @@
_: {
services.prosody = {
enable = true;
ssl.cert = "/var/lib/prosody/xmpp-fullchain.pem";
ssl.key = "/var/lib/prosody/xmpp-key.pem";
admins = ["kat@kittywit.ch"];
muc = [{domain = "conference.kittywit.ch";}];
virtualHosts."kittywit.ch" = {
enabled = true;
domain = "kittywit.ch";
ssl.cert = "/var/lib/prosody/xmpp-fullchain.pem";
ssl.key = "/var/lib/prosody/xmpp-key.pem";
};
httpPorts = [5280];
httpFileShare = {
domain = "upload.xmpp.kittywit.ch";
};
};
security.acme.certs."kittywit.ch" = {
postRun = ''
cp key.pem /var/lib/prosody/xmpp-key.pem
chown prosody:prosody /var/lib/prosody/xmpp-key.pem
cp fullchain.pem /var/lib/prosody/xmpp-fullchain.pem
chown prosody:prosody /var/lib/prosody/xmpp-fullchain.pem
systemctl reload prosody
'';
};
services.nginx.virtualHosts."upload.xmpp.kittywit.ch" = {
enableACME = true;
forceSSL = true;
locations = {
"/" = {
proxyPass = "http://127.0.0.1:5280";
proxyWebsockets = true;
};
};
};
networking.firewall.allowedTCPPorts = [
5222
5223
5269
];
}

View file

@ -1,4 +1,4 @@
{config, ...}: { _: {
services.nginx = { services.nginx = {
enable = true; enable = true;
recommendedTlsSettings = true; recommendedTlsSettings = true;
@ -6,32 +6,5 @@
recommendedGzipSettings = true; recommendedGzipSettings = true;
recommendedProxySettings = true; recommendedProxySettings = true;
statusPage = true; statusPage = true;
virtualHosts = let
vHost = {
extraConfig = ''
add_header Content-Type text/plain;
return 200 "meep?";
'';
/*
locations = {
"/" = {
extraConfig = ''
add_header Content-Type text/plain;
return 200 "meep?";
'';
};
};
*/
};
in {
"${config.networking.fqdn}" =
vHost
// {
enableACME = true;
forceSSL = true;
default = true;
};
"localhost" = vHost;
};
}; };
} }

View file

@ -2,6 +2,8 @@ _: let
secretConfig = { secretConfig = {
format = "yaml"; format = "yaml";
sopsFile = ./secrets.yaml; sopsFile = ./secrets.yaml;
owner = "acme";
group = "acme";
}; };
in { in {
sops.secrets.acme_credentials = secretConfig; sops.secrets.acme_credentials = secretConfig;

View file

@ -1,4 +1,4 @@
acme_credentials: ENC[AES256_GCM,data:hYjKLjGWMq9PiCobwo7PCWa/VF0ifJmLOrU4BP+vQMCFn19Ukl1gLnbDrLLzXfg9nAhkMGn5FiQJwl06ZX8E4qELXGkzSuLMvyDioEi6Plev/Wmx9szkCUd5,iv:hplC4l+aVnTLKH+bJZHCU2+NHh6154yPGMyozCUzwjM=,tag:bgOBFauegLvbFWc9sK0rcg==,type:str] acme_credentials: ENC[AES256_GCM,data:lxriLt0fdDp/M/JvzRv73dLjqMRrdwX+AzfxBoX/9p/uT0nusICMxTrV+AuKVxY3lztodT6knGiRjikB7QClyiq6Q4SIjAwtwPOYP3Yybfqh2NwZWBkRIQ==,iv:WLYpKBpZZOEyICM7IPP18ibJKaOA+WdUE8sZM+Vxgh4=,tag:E4b5DR6I0xHI4W2fhSRLcw==,type:str]
sops: sops:
shamir_threshold: 1 shamir_threshold: 1
age: age:
@ -101,8 +101,8 @@ sops:
M0Y5OGtrcEJMUVcrRUdlUnNOUGNYOGsKTk5EolDKBHZPw9FSPdw1I9gs0HMylPnh M0Y5OGtrcEJMUVcrRUdlUnNOUGNYOGsKTk5EolDKBHZPw9FSPdw1I9gs0HMylPnh
bQ2vhwy96O487LbQ+qo29mmd5Ov+zlIvViRLjKl++171xKgj7CQQdA== bQ2vhwy96O487LbQ+qo29mmd5Ov+zlIvViRLjKl++171xKgj7CQQdA==
-----END AGE ENCRYPTED FILE----- -----END AGE ENCRYPTED FILE-----
lastmodified: "2025-07-13T12:22:35Z" lastmodified: "2025-12-07T17:36:09Z"
mac: ENC[AES256_GCM,data:MXKAesYZVdW9N1BOeNqXi8IkBjWLw1VLgXwanaM0cHe63iS17VegEGhZet0WgiMuvcroPKRNzkRSXmv8pgLsaoVMAswgJAEGJjiVDMUKnvuMd7jIs9PYp16k94VRdl/eEmVUhEmXnfpNI4QeASDbxgbRuRFIXUqGYvqYj+FlJcE=,iv:RejxH3dUgj1oxzMnMeYZ5T+XXCbbPzsyAFGyUIKcrz8=,tag:bGaOeEnvqiOAVMLzTIxS5w==,type:str] mac: ENC[AES256_GCM,data:+ZcOBSYxUnwtGGK7/82yiJ0p+zk8xIwe9GkX2ut051kOE9I7lENxxCCURTkO/zAAmlYZgaln287HRBBtMDE24tjUvw9UKNZm9Dfh0IQxzFnIceTQDnMTOwyvhMWXEFiwbzI2rIEihrwTH0jSwasuI9W+pusiDhk4vXkz6DlcIsk=,iv:X6OqsZ4UAcS/B1VuYRPKc2KSJO7P6JUfr6GXkh3j5Tc=,tag:0P78aet5sKwS8hoV6wUpjA==,type:str]
pgp: pgp:
- created_at: "2025-12-04T04:58:12Z" - created_at: "2025-12-04T04:58:12Z"
enc: |- enc: |-
@ -125,4 +125,4 @@ sops:
-----END PGP MESSAGE----- -----END PGP MESSAGE-----
fp: CD8CE78CB0B3BDD4 fp: CD8CE78CB0B3BDD4
unencrypted_suffix: _unencrypted unencrypted_suffix: _unencrypted
version: 3.10.2 version: 3.11.0

View file

@ -0,0 +1,95 @@
import QtQuick
import QtQuick.Controls
import Quickshell
import Quickshell.Widgets
import Quickshell.Services.UPower
import "root:/DataSources"
Loader {
property UPowerDevice mainBat: UPower.displayDevice
active: mainBat.isLaptopBattery
sourceComponent: batIcon
function findClosestIndex(percent) {
return Math.round(percent*10)
}
property list<string> percentIcons: [
"󰂎",
"󰁺",
"󰁼",
"󰁼",
"󰁽",
"󰁾",
"󰁿",
"󰂀",
"󰂁",
"󰂂",
"󰁹"
]
property string chargingIcon: "󰂄"
function getIcon(percent) {
if (mainBat.timeToEmpty == 0) {
return chargingIcon
} else {
var percentIcon = percentIcons[findClosestIndex(percent)];
return percentIcon
}
}
function getTimeLeft(allSeconds, filling) {
const hours = Math.floor(allSeconds / 3600)
const minutes = Math.floor((allSeconds % 3600) / 60)
const fillString = filling ? "full" : "empty"
return `${hours}h${minutes}m remain until ${fillString}`
}
function getTimeLeftT() {
if (mainBat.timeToEmpty != 0) {
return getTimeLeft(mainBat.timeToEmpty, false)
} else if (mainBat.timeToFull != 0) {
return getTimeLeft(mainBat.timeToFull, true)
}
}
function changeRate() {
return `${Math.round(mainBat.changeRate*100)/100}W`
}
function energyLeft() {
return `${Math.round(mainBat.energy*100)/100}Wh total`
}
function getTooltip() {
return `${getTimeLeftT()}, ${energyLeft()}, ${changeRate()}`
}
Component {
id: batIcon
Item {
MarginWrapperManager { margin: 10 }
Text {
color: Stylix.base05
text: `${getIcon(mainBat.percentage)} ${mainBat.percentage*100} %`
ToolTip {
id: dismissTooltip
visible: false
delay: 500
timeout: 5000
text: getTooltip()
}
HoverHandler {
id: dismissHover
onHoveredChanged: {
dismissTooltip.visible = hovered
}
}
}
}
}
}

View file

@ -37,6 +37,7 @@ Item {
MouseArea { MouseArea {
anchors.fill: parent anchors.fill: parent
hoverEnabled: true hoverEnabled: true
acceptedButtons: Qt.LeftButton | Qt.RightButton
onClicked: mouse => { onClicked: mouse => {
modelData.triggered(); modelData.triggered();

View file

@ -33,16 +33,15 @@ Item {
property real clicky property real clicky
id: wrapperPopup id: wrapperPopup
anchor.window: root.QsWindow.window anchor.window: root.QsWindow.window
anchor.rect.y: parentWindow.height anchor.rect.y: parentWindow?.height ?? 0
anchor.rect.x: clicky anchor.rect.x: clicky
implicitWidth: systray.width + 10 implicitWidth: systray.width + 10
implicitHeight: systray.height + 10 implicitHeight: systray?.height + 10
color: "transparent" color: "transparent"
Rectangle { Rectangle {
anchors.fill: parent anchors.fill: parent
color: Stylix.base01 color: Stylix.base01
bottomLeftRadius: 5 radius: 5
bottomRightRadius: 5
SystemTray { SystemTray {
id: systray id: systray
} }

View file

@ -1,11 +1,14 @@
import Quickshell import Quickshell
import Quickshell.Io import Quickshell.Io
import Quickshell.Widgets
import QtQuick import QtQuick
import QtQuick.Layouts import QtQuick.Layouts
import QtQuick.Controls import QtQuick.Controls
import "root:/DataSources" import "root:/DataSources"
import "root:/Components" import "root:/Components"
import "root:/Components/NotificationSystem" import "root:/Components/WorkspaceControl"
import "root:/Components/SystemTray"
import "root:/Components/NotificationArea"
Scope { Scope {
id: root id: root
@ -34,7 +37,13 @@ Scope {
Rectangle { Rectangle {
id: bar id: bar
anchors.fill: parent anchors {
top: parent.top
left: parent.left
bottom: parent.bottom
}
MarginWrapperManager { margin: 10 }
radius: 10 radius: 10
color: Stylix.base00 color: Stylix.base00
@ -54,11 +63,22 @@ Scope {
} }
FocusedWindow {} FocusedWindow {}
} }
}
RowLayout { RowLayout {
anchors.centerIn: parent anchors.centerIn: parent
spacing: 20 spacing: 20
} }
Rectangle {
MarginWrapperManager { margin: 10 }
id: bar3
radius: 10
color: Stylix.base00
anchors {
top: parent.top
right: parent.right
bottom: parent.bottom
}
RowLayout { RowLayout {
anchors { anchors {
@ -71,6 +91,7 @@ Scope {
spacing: 15 spacing: 15
Battery {}
SystemTrayWrapper {} SystemTrayWrapper {}
Clock {} Clock {}
NotificationDisplay {} NotificationDisplay {}

View file

@ -1,6 +1,7 @@
_: let _: let
hostConfig = { hostConfig = {
tree, tree,
config,
modulesPath, modulesPath,
... ...
}: { }: {
@ -53,6 +54,21 @@ _: let
# }; # };
#}; #};
services.nginx.virtualHosts = let
vHost = {
extraConfig = ''
add_header Content-Type text/plain;
return 200 "meep?";
'';
};
in {
${config.networking.fqdn} = {
enableACME = true;
forceSSL = true;
default = true;
};
"localhost" = vHost;
};
security.acme.defaults.email = "acme@inskip.me"; security.acme.defaults.email = "acme@inskip.me";
system.stateVersion = "23.11"; system.stateVersion = "23.11";
}; };

View file

@ -15,6 +15,8 @@ _: let
++ (with tree.nixos.servers; [ ++ (with tree.nixos.servers; [
mail mail
continuwuity continuwuity
prosody
web
]); ]);
boot = { boot = {

View file

@ -199,3 +199,89 @@ resource "cloudflare_record" "dork_mail_imaps_autodiscover" {
} }
zone_id = local.zone_ids.dork zone_id = local.zone_ids.dork
} }
resource "cloudflare_record" "kittywitch_xmpp_server" {
name = "_xmpp-server._tcp"
proxied = false
ttl = 3600
type = "SRV"
data {
service = "_xmpp-server"
proto = "_tcp"
priority = 5
weight = 0
port = 5269
target = "rinnosuke.inskip.me"
}
zone_id = local.zone_ids.kittywitch
}
resource "cloudflare_record" "kittywitch_xmpp_server_ssl" {
name = "_xmpps-server._tcp"
proxied = false
ttl = 3600
type = "SRV"
data {
service = "_xmpps-server"
proto = "_tcp"
priority = 5
weight = 0
port = 5269
target = "rinnosuke.inskip.me"
}
zone_id = local.zone_ids.kittywitch
}
resource "cloudflare_record" "kittywitch_xmpp_client" {
name = "_xmpp-client._tcp"
proxied = false
ttl = 3600
type = "SRV"
data {
service = "_xmpp-server"
proto = "_tcp"
priority = 5
weight = 0
port = 5222
target = "rinnosuke.inskip.me"
}
zone_id = local.zone_ids.kittywitch
}
resource "cloudflare_record" "kittywitch_xmpp_client_ssl" {
name = "_xmpps-client._tcp"
proxied = false
ttl = 3600
type = "SRV"
data {
service = "_xmpps-client"
proto = "_tcp"
priority = 5
weight = 0
port = 5223
target = "rinnosuke.inskip.me"
}
zone_id = local.zone_ids.kittywitch
}
resource "cloudflare_record" "xmpp" {
name = "xmpp"
proxied = false
ttl = 3600
type = "CNAME"
value = "rinnosuke.inskip.me"
zone_id = local.zone_ids.kittywitch
}
resource "cloudflare_record" "xmpp_upload" {
name = "xmpp.upload"
proxied = false
ttl = 3600
type = "CNAME"
value = "rinnosuke.inskip.me"
zone_id = local.zone_ids.kittywitch
}

File diff suppressed because one or more lines are too long