This commit is contained in:
stupidcomputer 2024-06-25 20:14:15 -05:00
commit 3f85eab3ba
54 changed files with 272 additions and 532 deletions

4
.mailmap Normal file
View File

@ -0,0 +1,4 @@
stupidcomputer <ryan@beepboop.systems> <randomuser@tilde.club>
stupidcomputer <ryan@beepboop.systems>
stupidcomputer <ryan@beepboop.systems> <rndusr@beepboop.systems>
stupidcomputer <ryan@beepboop.systems> <Unixsys@github.com>

View File

@ -14,6 +14,13 @@
../../modules/rbw.nix ../../modules/rbw.nix
]; ];
virtualisation.docker.enable = true;
users.users.usr.extraGroups = [
"docker"
];
environment.systemPackages = with pkgs; [ environment.systemPackages = with pkgs; [
wine wine
xdotool xdotool

View File

@ -5,7 +5,17 @@
[ [
./hardware-configuration.nix ./hardware-configuration.nix
../../modules/bootstrap.nix ../../modules/bootstrap.nix
../../builds/gmail_mail_bridge.nix
./radicale.nix
./ssh.nix
./gitea.nix
./radicale.nix
./vaultwarden.nix
./sslh.nix
./rss2email.nix
./fail2ban.nix
./nginx.nix
./franklincce.nix
]; ];
# nix optimization # nix optimization
@ -14,7 +24,6 @@
dates = [ "03:45" ]; dates = [ "03:45" ];
}; };
networking.networkmanager.enable = true;
time.timeZone = "America/Chicago"; time.timeZone = "America/Chicago";
@ -35,100 +44,14 @@
neovim neovim
]; ];
services.gmail_mail_bridge.enable = true; system = {
copySystemConfiguration = true;
system.copySystemConfiguration = true; stateVersion = "23.05"; # don't change this, lol
system.stateVersion = "23.05"; # don't change this, lol
boot.loader.grub.enable = true;
boot.loader.grub.device = "/dev/vda";
services.sslh = {
enable = true;
settings.protocols = [
{
host = "localhost";
name = "ssh";
port = "55555";
service = "ssh";
}
{
host = "localhost";
name = "tls";
port = "442";
}
];
}; };
networking.hostName = "netbox"; boot.loader = {
grub.enable = true;
services.radicale = { grub.device = "/dev/vda";
enable = true;
settings = {
auth = {
type = "htpasswd";
htpasswd_filename = "radicale-passwd";
htpasswd_encryption = "plain";
};
};
};
services.rss2email = {
enable = true;
to = "ryan@beepboop.systems";
feeds = {
"eff" = {
url = "https://www.eff.org/rss/updates.xml";
};
"nixos" = {
url = "https://nixos.org/blog/announcements-rss.xml";
};
"drewdevault" = {
url = "https://drewdevault.com/blog/index.xml";
};
"nullprogram" = {
url = "https://nullprogram.com/feed/";
};
};
};
services.fail2ban = {
enable = true;
ignoreIP = [
"192.168.1.0/24"
];
extraPackages = [pkgs.ipset];
banaction = "iptables-ipset-proto6-allports";
jails = {
"nginx-bruteforce" = ''
enabled = true
filter = nginx-bruteforce
logpath = /var/log/nginx/access.log
backend = auto
maxretry = 6
findtime = 600
'';
"postfix-bruteforce" = ''
enabled = true
filter = postfix-bruteforce
maxretry = 6
findtime = 600
'';
};
};
environment.etc = {
"fail2ban/filter.d/nginx-bruteforce.conf".text = ''
[Definition]
failregex = ^<HOST>.*GET.*(matrix/server|\.php|admin|wp\-).* HTTP/\d.\d\" 404.*$
'';
"fail2ban/filter.d/postfix-bruteforce.conf".text = ''
[Definition]
failregex = warning: [\w\.\-]+\[<HOST>\]: SASL LOGIN authentication failed.*$
journalmatch = _SYSTEMD_UNIT=postfix.service
'';
}; };
users.users.ryan = { users.users.ryan = {
@ -141,119 +64,14 @@
extraGroups = [ "wheel" "docker" ]; extraGroups = [ "wheel" "docker" ];
}; };
services.openssh = { networking = {
enable = true; usePredictableInterfaceNames = false;
ports = [55555]; networkmanager.enable = true;
}; hostName = "netbox";
services.vaultwarden.enable = true; firewall = {
services.vaultwarden.config = {
DOMAIN = "https://bitwarden.beepboop.systems";
SIGNUPS_ALLOWED = false;
};
networking.usePredictableInterfaceNames = false;
services.gitea = {
enable = true;
appName = "beepboop.systems"; # Give the site a name
database = {
type = "postgres";
passwordFile = "/etc/gittea-pass";
};
settings.security.INSTALL_LOCK = true;
settings.service.SHOW_REGISTRATION_BUTTON = false;
settings.ui.DEFAULT_THEME = "arc-green";
settings.api.ENABLE_SWAGGER = false;
settings.server = {
DOMAIN = "git.beepboop.systems";
ROOT_URL = "https://git.beepboop.systems/";
LANDING_PAGE = "explore";
HTTP_PORT = 3001;
};
};
services.postgresql = {
enable = true; # Ensure postgresql is enabled
authentication = ''
local gitea all ident map=gitea-users
'';
identMap = # Map the gitea user to postgresql
''
gitea-users gitea gitea
'';
};
services.nginx.enable = true;
services.nginx.clientMaxBodySize = "100m";
services.nginx.defaultSSLListenPort = 442;
services.nginx.virtualHosts."beepboop.systems" = {
forceSSL = true;
enableACME = true;
root = "/var/www/beepboop.systems";
locations."/" = {
extraConfig = ''
port_in_redirect off;
absolute_redirect off;
'';
};
};
services.nginx.virtualHosts."git.beepboop.systems" = {
forceSSL = true;
enableACME = true;
locations."/" = {
proxyPass = "http://localhost:3001";
};
};
services.nginx.virtualHosts."bit.beepboop.systems" = {
forceSSL = true;
enableACME = true;
globalRedirect = "bitwarden.beepboop.systems";
};
services.nginx.virtualHosts."bitwarden.beepboop.systems" = {
forceSSL = true;
enableACME = true;
locations."/" = {
proxyPass = "http://127.0.0.1:8000";
};
};
services.nginx.virtualHosts."radicale.beepboop.systems" = {
forceSSL = true;
enableACME = true;
locations."/" = {
proxyPass = "http://127.0.0.1:5232";
extraConfig = ''
proxy_set_header X-Script-Name /;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_pass_header Authorization;
'';
};
};
services.nginx.virtualHosts."calendar.beepboop.systems" = {
forceSSL = true;
enableACME = true;
globalRedirect = "radicale.beepboop.systems";
};
services.nginx.virtualHosts."cal.beepboop.systems" = {
forceSSL = true;
enableACME = true;
globalRedirect = "radicale.beepboop.systems";
};
security.acme = {
acceptTerms = true;
defaults.email = "nickforanick@protonmail.com";
};
networking.firewall = {
enable = true; enable = true;
allowedTCPPorts = [ 80 443 ]; allowedTCPPorts = [ 80 443 ];
}; };
};
} }

42
boxes/netbox/fail2ban.nix Normal file
View File

@ -0,0 +1,42 @@
{ lib, config, pkgs, ... }:
{
services.fail2ban = {
enable = true;
ignoreIP = [
"192.168.1.0/24"
];
extraPackages = [pkgs.ipset];
banaction = "iptables-ipset-proto6-allports";
jails = {
"nginx-bruteforce" = ''
enabled = true
filter = nginx-bruteforce
logpath = /var/log/nginx/access.log
backend = auto
maxretry = 6
findtime = 600
'';
"postfix-bruteforce" = ''
enabled = true
filter = postfix-bruteforce
maxretry = 6
findtime = 600
'';
};
};
environment.etc = {
"fail2ban/filter.d/nginx-bruteforce.conf".text = ''
[Definition]
failregex = ^<HOST>.*GET.*(matrix/server|\.php|admin|wp\-).* HTTP/\d.\d\" 404.*$
'';
"fail2ban/filter.d/postfix-bruteforce.conf".text = ''
[Definition]
failregex = warning: [\w\.\-]+\[<HOST>\]: SASL LOGIN authentication failed.*$
journalmatch = _SYSTEMD_UNIT=postfix.service
'';
};
}

View File

@ -0,0 +1,12 @@
{ lib, config, pkgs, ... }:
{
virtualisation.docker.enable = true;
services.nginx.virtualHosts."franklincce.beepboop.systems" = {
forceSSL = true;
enableACME = true;
locations."/" = {
proxyPass = "http://localhost:1337";
};
};
}

43
boxes/netbox/gitea.nix Normal file
View File

@ -0,0 +1,43 @@
{ lib, config, pkgs, ... }:
{
services.gitea = {
enable = true;
appName = "beepboop.systems"; # Give the site a name
database = {
type = "postgres";
passwordFile = "/etc/gittea-pass";
};
settings.security.INSTALL_LOCK = true;
settings.service = {
SHOW_REGISTRATION_BUTTON = false;
DISABLE_REGISTRATION = true;
};
settings.ui.DEFAULT_THEME = "arc-green";
settings.api.ENABLE_SWAGGER = false;
settings.server = {
DOMAIN = "git.beepboop.systems";
ROOT_URL = "https://git.beepboop.systems/";
LANDING_PAGE = "explore";
HTTP_PORT = 3001;
};
};
services.postgresql = {
enable = true; # Ensure postgresql is enabled
authentication = ''
local gitea all ident map=gitea-users
'';
identMap = # Map the gitea user to postgresql
''
gitea-users gitea gitea
'';
};
services.nginx.virtualHosts."git.beepboop.systems" = {
forceSSL = true;
enableACME = true;
locations."/" = {
proxyPass = "http://localhost:3001";
};
};
}

23
boxes/netbox/nginx.nix Normal file
View File

@ -0,0 +1,23 @@
{ lib, config, pkgs, ... }:
{
services.nginx.enable = true;
services.nginx.clientMaxBodySize = "100m";
services.nginx.defaultSSLListenPort = 442;
services.nginx.virtualHosts."beepboop.systems" = {
forceSSL = true;
enableACME = true;
root = "/var/www/beepboop.systems";
locations."/" = {
extraConfig = ''
port_in_redirect off;
absolute_redirect off;
'';
};
};
security.acme = {
acceptTerms = true;
defaults.email = "nickforanick@protonmail.com";
};
}

38
boxes/netbox/radicale.nix Normal file
View File

@ -0,0 +1,38 @@
{ lib, config, pkgs, ... }:
{
services.radicale = {
enable = true;
settings = {
auth = {
type = "htpasswd";
htpasswd_filename = "radicale-passwd";
htpasswd_encryption = "plain";
};
};
};
services.nginx.virtualHosts."radicale.beepboop.systems" = {
forceSSL = true;
enableACME = true;
locations."/" = {
proxyPass = "http://127.0.0.1:5232";
extraConfig = ''
proxy_set_header X-Script-Name /;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_pass_header Authorization;
'';
};
};
services.nginx.virtualHosts."calendar.beepboop.systems" = {
forceSSL = true;
enableACME = true;
globalRedirect = "radicale.beepboop.systems";
};
services.nginx.virtualHosts."cal.beepboop.systems" = {
forceSSL = true;
enableACME = true;
globalRedirect = "radicale.beepboop.systems";
};
}

View File

@ -0,0 +1,21 @@
{ lib, config, pkgs, ... }:
{
services.rss2email = {
enable = true;
to = "ryan@beepboop.systems";
feeds = {
"eff" = {
url = "https://www.eff.org/rss/updates.xml";
};
"nixos" = {
url = "https://nixos.org/blog/announcements-rss.xml";
};
"drewdevault" = {
url = "https://drewdevault.com/blog/index.xml";
};
"nullprogram" = {
url = "https://nullprogram.com/feed/";
};
};
};
}

13
boxes/netbox/ssh.nix Normal file
View File

@ -0,0 +1,13 @@
{ lib, config, pkgs, ... }:
{
services.openssh = {
enable = true;
ports = [55555];
settings = {
X11Forwarding = false;
PermitRootLogin = "no";
PasswordAuthentication = false;
};
};
}

19
boxes/netbox/sslh.nix Normal file
View File

@ -0,0 +1,19 @@
{ lib, config, pkgs, ... }:
{
services.sslh = {
enable = true;
settings.protocols = [
{
host = "localhost";
name = "ssh";
port = "55555";
service = "ssh";
}
{
host = "localhost";
name = "tls";
port = "442";
}
];
};
}

View File

@ -0,0 +1,22 @@
{ lib, config, pkgs, ... }:
{
services.vaultwarden.enable = true;
services.vaultwarden.config = {
DOMAIN = "https://bitwarden.beepboop.systems";
SIGNUPS_ALLOWED = false;
};
services.nginx.virtualHosts."bit.beepboop.systems" = {
forceSSL = true;
enableACME = true;
globalRedirect = "bitwarden.beepboop.systems";
};
services.nginx.virtualHosts."bitwarden.beepboop.systems" = {
forceSSL = true;
enableACME = true;
locations."/" = {
proxyPass = "http://127.0.0.1:8000";
};
};
}

View File

@ -1,19 +0,0 @@
{ lib, pkgs, config, ... }:
let
cfg = config.services.gmail_mail_bridge;
appEnv = pkgs.python3.withPackages (p: with p; [ waitress (callPackage ./gmail_mail_bridge/default.nix {}) ]);
in {
options.services.gmail_mail_bridge = {
enable = lib.mkEnableOption "Enable the gmail_mail_bridge";
};
config = lib.mkIf cfg.enable {
systemd.services.gmail_mail_bridge = {
wantedBy = [ "multi-user.target" ];
serviceConfig = {
ExecStart = "${appEnv}/bin/waitress-serve --port=8041 gmail_mail_bridge:app";
StandardOutput = "journal";
};
};
};
}

View File

@ -1 +0,0 @@
__pycache_/

View File

@ -1,10 +0,0 @@
synchronize email from gmail accounts whose OAuth access is heavily restricted
background
----------
my school district disabled external OAuth access to email, which is not cool. this script gets around this and creates a bridge so you can recieve emails from your school email.
do note that this is heavily unpolished and most definately insecure. there are some hardcoded credentials (which you can change, it just takes a little technical know-how)
have fun!

View File

@ -1,20 +0,0 @@
{ pkgs, pythonPackages ? (import <nixpkgs> {}).python3Packages }:
pythonPackages.buildPythonPackage {
name = "gmail_mail_bridge";
src = ./gmail_mail_bridge;
propagatedBuildInputs = [ pythonPackages.flask pkgs.system-sendmail ];
installPhase = ''
runHook preInstall
mkdir -p $out/${pythonPackages.python.sitePackages}
cp -r . $out/${pythonPackages.python.sitePackages}/gmail_mail_bridge
runHook postInstall
'';
shellHook = "export FLASK_APP=gmail_mail_bridge";
format = "other";
}

View File

@ -1,37 +0,0 @@
from flask import Flask
from flask import request
from flask import redirect
from flask import abort
import logging
import smtplib
import email
from subprocess import Popen, PIPE, STDOUT
pre_shared_secret = "amongus sussy imposter"
to = "ryan@beepboop.systems"
app = Flask(__name__)
def handle_post(request):
msg = email.message_from_string(request.form["payload"])
del msg["To"]
msg["To"] = to
if not msg["From"]:
msg["From"] = "unknown-sender@mail.beepboop.systems"
s = smtplib.SMTP('localhost')
s.send_message(msg)
s.quit()
@app.route("/bridge-submit", methods = ["GET", "POST"])
def testing():
if request.method == 'POST':
data = request.form
if data['auth'] == pre_shared_secret:
handle_post(request)
else:
return 'you didn\'t use post'
return "default answer"

View File

@ -1,12 +0,0 @@
{ pkgs ? import (fetchTarball "https://github.com/NixOS/nixpkgs/tarball/nixos-23.11") {} }:
pkgs.mkShell {
packages = [
(pkgs.python3.withPackages (ps: [
ps.flask
]))
pkgs.curl
pkgs.jq
];
}

View File

@ -1,23 +0,0 @@
// google-side synchronization
// add a minute-wise trigger for mail synchronization
// go to the sidebar, select triggers, add a new one, configure it
// to run syncMail every minute
function syncMail() {
var threads = GmailApp.search("label:need_processing");
var label = GmailApp.getUserLabelByName("need_processing");
for (var thread of threads) {
for (var message of GmailApp.getMessagesForThread(thread)) {
var formData = {
auth: 'amongus sussy imposter',
payload: message.getRawContent(),
};
var options = {
'method' : 'POST',
'payload' : formData
};
var resp = UrlFetchApp.fetch('https://mail.beepboop.systems/bridge-submit', options);
}
thread.removeLabel(label);
}
}

View File

@ -34,8 +34,8 @@ stdenv.mkDerivation rec {
installPhase = '' installPhase = ''
mkdir -p $out/bin mkdir -p $out/bin
for i in $(ls $src/sh); do for i in $(ls $src/); do
cp $src/sh/$i $out/bin cp $src/$i $out/bin
ln -sf $out/bin/tmenu_run $out/bin/regenerate ln -sf $out/bin/tmenu_run $out/bin/regenerate
wrapProgram $out/bin/$i --prefix PATH : ${lib.makeBinPath [ sxhkd bash feh xrandr jq figlet curl fzy xkbset ytfzf sshuttle svkbd scrcpy xrectsel ffcast ]} wrapProgram $out/bin/$i --prefix PATH : ${lib.makeBinPath [ sxhkd bash feh xrandr jq figlet curl fzy xkbset ytfzf sshuttle svkbd scrcpy xrectsel ffcast ]}
done done

View File

@ -1,5 +0,0 @@
TODO LIST
---------
- fix paste
- make the c programs less buggy and let them not suck as much

View File

@ -1,26 +0,0 @@
import httplib2
import json
import math
import time
# fun fact: i got bored so made this on a southwest flight
while True:
request = httplib2.Http()
# you have to look in the network tab in 'inspect element', and find the '_' parameter, and paste that in
# of course, you have to be connected to southwest's onboard wifi
_param = "fill this in"
data = request.request("https://getconnected.southwestwifi.com/fp3d_fcgi-php/portal/public/index.php?_url=/index/getFile&path=last&_=" + _param)
data = json.loads(data[1])
print("-- Update --")
print("Nautical Miles: " + str(data["distanceToDestinationNauticalMiles"]))
print("Phase: " + data["presentPhase"])
print("Speed: " + str(data["groundSpeedKnots"]) + "kts")
seconds = data['timeToDestination']
minutes = math.floor(seconds / 60)
seconds = seconds % 60
print("Minutes: " + str(minutes) + " Seconds: " + str(seconds))
print("Flight Number: " + data["flightNumber"] + " Registration: " + data["tailNumber"])
time.sleep(3)
print('\033[H\033[2J')

View File

@ -1,32 +0,0 @@
.TH COLORS 1 colors
.SH NAME
colors \- generate colorscheme and run hooks
.SH SYNOPSIS
.B colors [-hefc] [-w path]
.SH OPTIONS
.TP
.B -h
disable running hooks (implies -e)
.TP
.B -e
echo colors to stdout
.TP
.B -c
check colors using color checking algorithm
.TP
.B -f
print wallpaper filename to stdout
.TP
.B -w
provide wallpaper path
.SH HOOKS
When -h is not used, a program at ~/.config/cwal/handler is executed. The first sixteen arguments are the colors in the colorscheme, and the seventeenth argument is the filename.
.SH EXIT CODES
.TP
.B 0
Normal exit code
.TP
.B 1
check_colors(...) failed.
.SH AUTHOR
randomuser

View File

@ -1,11 +0,0 @@
.TH RNDUTILS 1 rndutils
.SH NAME
rndutils \- simple shell script utilities
.SH INSTALLATION
.B make install
.SH LICENSE
The author, randomuser (randomuser at tilde dot club) hereby
releases the software in this distribution and all
accompanying texts into the public domain, thereby relieving
him of any warranty of any kind.

View File

@ -1,87 +0,0 @@
.TH TIMER 1 timer
.SH NAME
timer \- simple command line timer program
.SH SYNOPSIS
.B timer [-evdbft] [-h int] [-m int] [-s int]
.SH OPTIONS
.TP
.B -e
enable usage of vt100 escape sequences for timer rendering (overrides -v)
.TP
.B -v
enable printing of timer status
.TP
.B -d
count down; when timer reaches 00:00, finish (use -h, -m, -s to set ending time)
.TP
.B -b
ASCII BEL when timer finish state reached
.TP
.B -f
timer display contains hour slot
.TP
.B -t
use a tomato timer (use -h, -m, -s to set work cycle time, rest cycle time is assumed to be half of the working time)
.TP
.B -p
disable pausing after finishing tomato timer cycle (required -t to work)
.TP
.B -z
enable build-specific runtime settings (default -ebf)
.TP
.B "-h int"
specify number of hours for timer parameters
.TP
.B "-m int"
specify number of minutes for timer parameters
.TP
.B "-s int"
specify number of seconds for timer parameters
.SH INTERACTIVE USAGE
.TP
.B pausing
a timer is paused when an astrisk prefixes the display (with -e) and/or when the timer ceases to update, e.g. count up or down. you can use the enter key to pause/unpause it (refer to the below example)
.nf
$ timer -e
* 05:45
.fi
.TP
.B stopping a timer
should you wish to stop a timer prematurely, or a timer which has no specified end condition, you may press the key combination that sends a killing signal to the program (e.g. a la SIGTERM) in your shell, which is usually ^C. the timer has no major places to clean up. however, memory leaks might occur on some operating systems due to no free()ing of resources.
.SH EXIT CODES/TERMINATION SIGNALS
.TP
.B 0
timer finished successfully
.TP
.B 1 / SIGABRT
error parsing arguments
.SH EXAMPLES
.B start a ten minute timer, counting up:
.nf
$ timer -m 10
.fi
.B show the vt100 interface, too:
.nf
$ timer -em 10
.fi
.B start a one hour sixty-two minute fourty-nine second timer counting down (with vt100 interface):
.nf
$ timer -edh 1 -m 62 -s 49
.fi
.B start a tomato timer with a work interval of fourty minutes and a rest interval of twenty minutes:
.nf
$ timer -etm 40
.fi
.SH REQUIRED HEADERS
.nf
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <poll.h>
#include <string.h>
.fi
.SH BUGS
- when passing -p each tomato timer cycle is cut short one second
send email to random user at-sign tilde dot club
.SH AUTHOR
randomuser

View File

@ -1,30 +0,0 @@
.TH TRSS 1 trss
.SH NAME
trss \- command oriented feed reader powered by sfeed
.SH SYNOPSIS
.B trss
.SH INTERFACE
.TP
.B ls
list all feed names in the 'feed home', or within a feed, list all items within
.TP
.B cd
focus another feed. in order to go back to the 'feed home', use 'cd' or 'cd ..'
.TP
.B sync
with no arguments and in the 'feed home', syncs all feeds. if in a specific feed, syncs that feed. a feed can be specified in an argument.
.TP
.B cat
open all feeds whose titles contain text as specified by an argument in 'lynx'
.SH trss-yt-id
this script is designed to allow one to obtain an rss feed for the uploads of a youtube channel. this command takes the homepage of the youtube channel in question as an argument and then returns the rss feed for that channel.
.SH BUGS
- when in a feed, you can't cd to another directly, you must go to to the 'feed home' and then cd
.SH DEPENDS
sfeed
.SH AUTHOR
randomuser <random user at tilde dot club>

View File

@ -1,10 +0,0 @@
.TH XGETNEWWINDOW 1 xgetnewwindow
.SH NAME
xgetnewwindow
.SH SYNOPSIS
xgetnewwindow blocks until it recieves a CreateNotify event; that is, until a new window is created within the current Xorg instance. Once a new window is created, xgetnewwindow prints the window id (in hexadecimal) to stdout and exits.
.SH EXIT CODES
1 for abnormal termination, 0 for success.
.SH AUTHOR
randomuser

View File

@ -4,6 +4,8 @@
environment.systemPackages = with pkgs; [ environment.systemPackages = with pkgs; [
git git
neovim neovim
(pkgs.callPackage ../builds/rebuild.nix {})
]; ];
nix.settings.experimental-features = [ "nix-command" "flakes" ]; nix.settings.experimental-features = [ "nix-command" "flakes" ];

View File

@ -6,7 +6,6 @@
]; ];
environment.systemPackages = [ environment.systemPackages = [
(pkgs.callPackage ../builds/rebuild.nix {})
(pkgs.callPackage ../builds/st.nix { lightMode = false; }) (pkgs.callPackage ../builds/st.nix { lightMode = false; })
(pkgs.callPackage ../builds/utils.nix {}) (pkgs.callPackage ../builds/utils.nix {})
(pkgs.callPackage ../builds/statusbar {}) (pkgs.callPackage ../builds/statusbar {})