Compare commits

...
13 Commits
Author SHA1 Message Date
h7x4 a5dbba9d4e flake.lock: bump 2026-08-10 04:56:46 +09:00
Vegard Bieker Matthey c40972e701 Update README.md 2026-08-07 22:52:31 +02:00
h7x4 6c21e881c0 packages/bluemap: 5.20 -> 5.22 2026-08-06 20:41:18 +09:00
Felix Albrigtsen f6a84fe70e drolsum: unalive 2026-08-03 10:29:28 +02:00
Daniel Olsen e2567e78cf mitigations: patch matrix-synapse 2026-07-28 17:36:31 +02:00
h7x4 6ed3f1d269 flake.lock: bump roowho2 2026-07-28 06:45:28 +09:00
h7x4andoysteikt afc6b3182e ildkule/prometheus/phpfpm: scrape from bekkalokk 2026-07-27 13:58:47 +02:00
h7x4andoysteikt 7ebf1130a9 bekkalokk/prometheus-phpfpm-exporter: init 2026-07-27 13:58:47 +02:00
h7x4andoysteikt f9d39adf53 base/journald-upload: verify server cert against CA bundle 2026-07-27 13:50:39 +02:00
h7x4andoysteikt 65705237ab modules/python-http-handlers: better daemon handling
This commit extends the python http handler template with the following
things:

- Integration with systemd notify
- Named systemd sockets, to avoid depending on expected FD number
- Graceful and customizable handling of SIGHUP reloads
- Graceful shutdown on SIGTERM with timeout
- Multithreaded HTTP server, one thread per request
- Better error message on undefined handler
2026-07-27 13:50:19 +02:00
h7x4andoysteikt ab518714a5 bekkalokk/well-known: advertise TLS SMTP in autoconfig/mail 2026-07-25 23:24:57 +02:00
h7x4 4f6c731d25 flake.lock: bump pvv-nettsiden 2026-07-25 20:51:24 +09:00
h7x4 ee718563c8 bicep/postgresql: don't open udp 5432 in firewall 2026-07-25 07:35:42 +09:00
15 changed files with 239 additions and 72 deletions
+2 -2
View File
@@ -34,12 +34,12 @@ revert the changes on the next nightly rebuild (tends to happen when everybody i
| Name | Type | Description | | Name | Type | Description |
|----------------------------|----------|-----------------------------------------------------------| |----------------------------|----------|-----------------------------------------------------------|
| [bekkalokk][bek] | Physical | Our main web host, webmail, wiki, idp, minecraft map, ... | | [bekkalokk][bek] | Physical | Our main web host, webmail, wiki, idp, ... |
| [bicep][bic] | Virtual | Database host, matrix, git mirrors, ... | | [bicep][bic] | Virtual | Database host, matrix, git mirrors, ... |
| bikkje | Virtual | Experimental login box | | bikkje | Virtual | Experimental login box |
| [brzeczyszczykiewicz][brz] | Physical | Shared music player | | [brzeczyszczykiewicz][brz] | Physical | Shared music player |
| [georg][geo] | Physical | Shared music player | | [georg][geo] | Physical | Shared music player |
| [gluttony][glu] | Virtual | General purpose compute | | [gluttony][glu] | Virtual | General purpose compute, minecraft map |
| [ildkule][ild] | Virtual | Logging and monitoring host, prometheus, grafana, ... | | [ildkule][ild] | Virtual | Logging and monitoring host, prometheus, grafana, ... |
| [kommode][kom] | Virtual | Gitea + Gitea pages | | [kommode][kom] | Virtual | Gitea + Gitea pages |
| [lupine][lup] | Physical | Gitea CI/CD runners | | [lupine][lup] | Physical | Gitea CI/CD runners |
+14
View File
@@ -21,4 +21,18 @@ in
boot.blacklistedKernelModules = modulesToBan; boot.blacklistedKernelModules = modulesToBan;
boot.extraModprobeConfig = lib.concatMapStringsSep "\n" (mod: "install ${mod} ${lib.getExe' pkgs.coreutils "false"}") modulesToBan; boot.extraModprobeConfig = lib.concatMapStringsSep "\n" (mod: "install ${mod} ${lib.getExe' pkgs.coreutils "false"}") modulesToBan;
nixpkgs.overlays = [
(final: prev: {
matrix-synapse-unwrapped = prev.matrix-synapse-unwrapped.overrideAttrs (old: rec {
version = "1.157.2";
src = final.fetchFromGitHub {
owner = "element-hq";
repo = "synapse";
rev = "v${version}";
hash = "sha256-TUHcNAXrV43+J7jqfstlYdrZrwL5kDCh03yxO+vL/gw=";
};
});
})
];
} }
+1 -1
View File
@@ -9,7 +9,7 @@ in
URL = "https://journald.pvv.ntnu.no:${toString config.services.journald.remote.port}"; URL = "https://journald.pvv.ntnu.no:${toString config.services.journald.remote.port}";
ServerKeyFile = "-"; ServerKeyFile = "-";
ServerCertificateFile = "-"; ServerCertificateFile = "-";
TrustedCertificateFile = "-"; TrustedCertificateFile = config.security.pki.caBundle;
}; };
}; };
Generated
+29 -29
View File
@@ -126,11 +126,11 @@
"rust-overlay": "rust-overlay_2" "rust-overlay": "rust-overlay_2"
}, },
"locked": { "locked": {
"lastModified": 1784553736, "lastModified": 1784709844,
"narHash": "sha256-W1pPlTHmp+EvONwf8Qa5NvCiuyV4LC/yNDdc27RSpuA=", "narHash": "sha256-5PW5+UEFFjsru5FiDg9ZRUjQyo7AVyc+nesQlBSqM6c=",
"ref": "main", "ref": "main",
"rev": "e06daaef1f48160254c202c59b060ac6f1da9f38", "rev": "a8fb5df19d1cdcc3ac29cdb8ad192c1d578761f0",
"revCount": 62, "revCount": 63,
"type": "git", "type": "git",
"url": "https://git.pvv.ntnu.no/Grzegorz/greg-ng.git" "url": "https://git.pvv.ntnu.no/Grzegorz/greg-ng.git"
}, },
@@ -253,11 +253,11 @@
] ]
}, },
"locked": { "locked": {
"lastModified": 1770960722, "lastModified": 1786305372,
"narHash": "sha256-IdhPsWFZUKSJh/nLjGLJvGM5d5Uta+k1FlVYPxTZi0E=", "narHash": "sha256-ZKTGJzXQMeskdivpyXmfyonEjR25b42N9tWwx+nvKMM=",
"ref": "main", "ref": "main",
"rev": "c2e4aca7e1ba27cd09eeaeab47010d32a11841b2", "rev": "723a3d8d117bbfa07bda86427afaef1b1b6b7ff5",
"revCount": 15, "revCount": 19,
"type": "git", "type": "git",
"url": "https://git.pvv.ntnu.no/Drift/nix-gitea-themes.git" "url": "https://git.pvv.ntnu.no/Drift/nix-gitea-themes.git"
}, },
@@ -291,11 +291,11 @@
}, },
"nixpkgs": { "nixpkgs": {
"locked": { "locked": {
"lastModified": 1784526640, "lastModified": 1786245335,
"narHash": "sha256-UDnuu3uM64qjfVvsGSislJgP1j15FiFiDiKOjbGTv9Q=", "narHash": "sha256-cAR1Po8rYta0tqfjdotDXYVaPC3oJ1/th2cLcQNQSco=",
"rev": "036c2421db75172aeef4bb83921988891d4773c9", "rev": "33ddeb9e7c03403e17814e8aac1f7affe6d70b21",
"type": "tarball", "type": "tarball",
"url": "https://releases.nixos.org/nixos/26.05-small/nixos-26.05.5692.036c2421db75/nixexprs.tar.xz" "url": "https://releases.nixos.org/nixos/26.05-small/nixos-26.05.7300.33ddeb9e7c03/nixexprs.tar.xz"
}, },
"original": { "original": {
"type": "tarball", "type": "tarball",
@@ -319,11 +319,11 @@
}, },
"nixpkgs-unstable": { "nixpkgs-unstable": {
"locked": { "locked": {
"lastModified": 1784536202, "lastModified": 1786237299,
"narHash": "sha256-7CmHmK10lEXBgymS0DeYj4/4STLpzRWCc/5BfoIxHQo=", "narHash": "sha256-ZNjdCWSLUF0mrPSKXijAm606sfbI6889LCg6doYG3B8=",
"rev": "94f12be79cb7f961726a0157b4168bc722befeac", "rev": "60c768b1d7043edb84f25e2880ab2bd8327f6cfa",
"type": "tarball", "type": "tarball",
"url": "https://releases.nixos.org/nixos/unstable-small/nixos-26.11pre1037880.94f12be79cb7/nixexprs.tar.xz" "url": "https://releases.nixos.org/nixos/unstable-small/nixos-26.11pre1050368.60c768b1d704/nixexprs.tar.xz"
}, },
"original": { "original": {
"type": "tarball", "type": "tarball",
@@ -379,11 +379,11 @@
] ]
}, },
"locked": { "locked": {
"lastModified": 1782759909, "lastModified": 1784979981,
"narHash": "sha256-gktjBeZyoRvVBkm2cO1tD99fdQ34iUDyB6iecRdorm4=", "narHash": "sha256-OnvjEXYU/InjJYH2+iIrvHWIjHnc5J9f84qWhrgAWlY=",
"ref": "main", "ref": "main",
"rev": "ad6c79fb713884a4a2df8aab30914cd0c1c2e6cb", "rev": "ffb8ed0c9df2444727e49f16f7e43ea70184dc4b",
"revCount": 587, "revCount": 590,
"type": "git", "type": "git",
"url": "https://git.pvv.ntnu.no/Projects/nettsiden.git" "url": "https://git.pvv.ntnu.no/Projects/nettsiden.git"
}, },
@@ -447,17 +447,17 @@
"rust-overlay": "rust-overlay_4" "rust-overlay": "rust-overlay_4"
}, },
"locked": { "locked": {
"lastModified": 1784550731, "lastModified": 1785060737,
"narHash": "sha256-KDrBGT98fQWlnEBmTvIijPq4n4sVLcETBu8EuL486SM=", "narHash": "sha256-tlOCUK+X1Um1y/pP/vToGrygn1wmrtUDKrvQquPLVfA=",
"ref": "main", "ref": "main",
"rev": "c0c0e47c8a45673c62462cadf38a489b72fd39ec", "rev": "35fe97baa795d1564c79b013d8a36ee01698f47b",
"revCount": 112, "revCount": 126,
"type": "git", "type": "git",
"url": "https://git.pvv.ntnu.no/Projects/roowho2.git" "url": "https://git.pvv.ntnu.no/Projects/roowho2.git"
}, },
"original": { "original": {
"ref": "main", "ref": "main",
"rev": "c0c0e47c8a45673c62462cadf38a489b72fd39ec", "rev": "35fe97baa795d1564c79b013d8a36ee01698f47b",
"type": "git", "type": "git",
"url": "https://git.pvv.ntnu.no/Projects/roowho2.git" "url": "https://git.pvv.ntnu.no/Projects/roowho2.git"
} }
@@ -575,11 +575,11 @@
] ]
}, },
"locked": { "locked": {
"lastModified": 1780762731, "lastModified": 1785100355,
"narHash": "sha256-EuDaLnasWN0mpi995n+fAQQfPGBhqNW4fNjlQRpHt58=", "narHash": "sha256-wBGnYrF7Kfs4vk3djspT3RdQqsYiqm60fKn7/J3vH4I=",
"ref": "main", "ref": "main",
"rev": "931bd2d63e285e767c8c81c103dda3c0a63f2965", "rev": "611f6ac1a304cc319fc85876d3f0301f49ce458e",
"revCount": 108, "revCount": 120,
"type": "git", "type": "git",
"url": "https://git.pvv.ntnu.no/Projects/worblehat.git" "url": "https://git.pvv.ntnu.no/Projects/worblehat.git"
}, },
+1 -1
View File
@@ -35,7 +35,7 @@
minecraft-heatmap.url = "git+https://git.pvv.ntnu.no/Projects/minecraft-heatmap.git?ref=main"; minecraft-heatmap.url = "git+https://git.pvv.ntnu.no/Projects/minecraft-heatmap.git?ref=main";
minecraft-heatmap.inputs.nixpkgs.follows = "nixpkgs"; minecraft-heatmap.inputs.nixpkgs.follows = "nixpkgs";
roowho2.url = "git+https://git.pvv.ntnu.no/Projects/roowho2.git?ref=main&rev=c0c0e47c8a45673c62462cadf38a489b72fd39ec"; roowho2.url = "git+https://git.pvv.ntnu.no/Projects/roowho2.git?ref=main&rev=35fe97baa795d1564c79b013d8a36ee01698f47b";
roowho2.inputs.nixpkgs.follows = "nixpkgs"; roowho2.inputs.nixpkgs.follows = "nixpkgs";
greg-ng.url = "git+https://git.pvv.ntnu.no/Grzegorz/greg-ng.git?ref=main"; greg-ng.url = "git+https://git.pvv.ntnu.no/Grzegorz/greg-ng.git?ref=main";
+1
View File
@@ -13,6 +13,7 @@
./services/mediawiki ./services/mediawiki
./services/nginx.nix ./services/nginx.nix
./services/phpfpm.nix ./services/phpfpm.nix
./services/prometheus-phpfpm-exporter.nix
./services/vaultwarden.nix ./services/vaultwarden.nix
./services/webmail ./services/webmail
./services/website ./services/website
@@ -0,0 +1,54 @@
{ config, lib, values, ... }:
let
cfg = config.services.prometheus.exporters.php-fpm;
pools = [
"idp"
"mediawiki"
"pvv-nettsiden"
"roundcube"
"snappymail"
];
in
{
services.phpfpm.pools = lib.genAttrs pools (_: {
settings."pm.status_path" = "/status";
});
services.prometheus.exporters.php-fpm = {
enable = true;
listenAddress = "127.0.0.1";
extraFlags = [
"--phpfpm.scrape-uri=${lib.concatMapStringsSep "," (name: "unix://${config.services.phpfpm.pools.${name}.socket};/status") pools}"
];
};
systemd.services.prometheus-php-fpm-exporter.serviceConfig = {
Slice = "system-monitoring.slice";
SupplementaryGroups = [ config.services.nginx.group ];
RestrictAddressFamilies = lib.mkForce [
"AF_INET"
"AF_INET6"
"AF_UNIX"
];
};
services.nginx = lib.mkIf cfg.enable {
virtualHosts."www.pvv.ntnu.no" = lib.mkIf config.services.nginx.enable {
forceSSL = true;
enableACME = true;
kTLS = true;
locations."/prometheus-php-fpm-exporter/metrics" = {
proxyPass = "http://localhost:${toString cfg.port}/metrics";
extraConfig = ''
allow 127.0.0.1;
allow ::1;
allow ${values.hosts.ildkule.ipv4};
allow ${values.hosts.ildkule.ipv6};
deny all;
'';
};
};
};
}
@@ -16,8 +16,8 @@
<outgoingServer type="smtp"> <outgoingServer type="smtp">
<hostname>smtp.pvv.ntnu.no</hostname> <hostname>smtp.pvv.ntnu.no</hostname>
<port>587</port> <port>465</port>
<socketType>STARTTLS</socketType> <socketType>SSL</socketType>
<username>%EMAILLOCALPART%</username> <username>%EMAILLOCALPART%</username>
<authentication>password-cleartext</authentication> <authentication>password-cleartext</authentication>
<useGlobalPreferredServer>true</useGlobalPreferredServer> <useGlobalPreferredServer>true</useGlobalPreferredServer>
@@ -150,7 +150,6 @@ in
}; };
networking.firewall.allowedTCPPorts = lib.mkIf cfg.enable [ 5432 ]; networking.firewall.allowedTCPPorts = lib.mkIf cfg.enable [ 5432 ];
networking.firewall.allowedUDPPorts = lib.mkIf cfg.enable [ 5432 ];
environment.systemPackages = [ environment.systemPackages = [
(pkgs.writeShellApplication { (pkgs.writeShellApplication {
@@ -82,7 +82,6 @@ in
(mkMachine "buskerud") (mkMachine "buskerud")
(mkMachine "buttercup") (mkMachine "buttercup")
(mkMachine "demiurgen") (mkMachine "demiurgen")
(mkMachine "drolsum")
(mkMachine "hildring") (mkMachine "hildring")
(mkMachine "innovation") (mkMachine "innovation")
(mkMachine "isvegg") (mkMachine "isvegg")
@@ -7,6 +7,7 @@ in {
./machines.nix ./machines.nix
./matrix-synapse.nix ./matrix-synapse.nix
./mysqld.nix ./mysqld.nix
./phpfpm.nix
./postgres.nix ./postgres.nix
]; ];
@@ -0,0 +1,15 @@
{ ... }:
{
services.prometheus.scrapeConfigs = [{
job_name = "phpfpm";
scheme = "https";
metrics_path = "/prometheus-php-fpm-exporter/metrics";
static_configs = [
{
labels.hostname = "bekkalokk";
targets = [ "www.pvv.ntnu.no:443" ];
}
];
}];
}
+117 -10
View File
@@ -36,6 +36,9 @@ in
description = '' description = ''
For each item in this list, a `ListenStream` For each item in this list, a `ListenStream`
option in the `[Socket]` section will be created. option in the `[Socket]` section will be created.
Only a single `ListenStream` is currently supported by the handler script; if
you need more than one, you'll have to adjust {option}`handler` accordingly.
''; '';
}; };
@@ -98,8 +101,10 @@ in
"E303" # too many blank lines "E303" # too many blank lines
"E305" # expected 2 blank lines after end of function or class "E305" # expected 2 blank lines after end of function or class
"E306" # expected 1 blank line before a nested definition "E306" # expected 1 blank line before a nested definition
"E402" # module level import not at top of file
"E501" # max line length "E501" # max line length
"E704" # multiple statements on one line (def) "E704" # multiple statements on one line (def)
"F811" # redefined while unused
]; ];
description = '' description = ''
A list of flake8 rules to ignore while linting the python code. A list of flake8 rules to ignore while linting the python code.
@@ -122,6 +127,11 @@ in
self.send_header("Content-Length", str(len(data))) self.send_header("Content-Length", str(len(data)))
self.end_headers() self.end_headers()
self.wfile.write(data) self.wfile.write(data)
def on_reload():
# This function is called when the service receives SIGHUP (e.g. via `systemctl reload`).
# You can use it to clear caches or re-read state. Completely optional
pass
''; '';
description = '' description = ''
Python code including the HTTP handler for the server. Python code including the HTTP handler for the server.
@@ -145,6 +155,7 @@ in
inherit (v) listenStreams; inherit (v) listenStreams;
socketConfig = { socketConfig = {
Accept = false; Accept = false;
FileDescriptorName = v.name;
} // v.socketConfig; } // v.socketConfig;
}; };
})) }))
@@ -157,30 +168,126 @@ in
inherit (v) name; inherit (v) name;
value = { value = {
serviceConfig = { serviceConfig = {
Type = "simple"; Type = "notify-reload";
NotifyAccess = "main";
DynamicUser = true; DynamicUser = true;
TimeoutStopSec = "35s";
ExecStart = let ExecStart = let
package = pkgs.writers.writePython3Bin "${v.name}-bin" { package = pkgs.writers.writePython3Bin "${v.name}-bin" {
inherit (v) libraries flakeIgnore; inherit (v) libraries flakeIgnore;
} '' } ''
import os
import signal
import socket import socket
import socketserver
import threading
import time
from http.server import HTTPServer, BaseHTTPRequestHandler from http.server import HTTPServer, BaseHTTPRequestHandler
${v.handler} SOCKET_NAME = "${v.name}"
SHUTDOWN_TIMEOUT = 30
def sd_notify(message: str):
addr = os.environ.get("NOTIFY_SOCKET")
if not addr:
return
if addr[0] == "@":
addr = "\0" + addr[1:]
with socket.socket(socket.AF_UNIX, socket.SOCK_DGRAM | socket.SOCK_CLOEXEC) as sock:
sock.connect(addr)
sock.sendall(message.encode())
def sd_listen_fd(name: str) -> int:
if os.environ.get("LISTEN_PID") != str(os.getpid()):
raise RuntimeError("No sockets were passed to this service by systemd")
try:
count = int(os.environ.get("LISTEN_FDS", "0"))
except ValueError:
count = 0
raw_names = os.environ.get("LISTEN_FDNAMES")
names = raw_names.split(":") if raw_names else []
for i in range(count):
if i < len(names) and names[i] == name:
return 3 + i
raise RuntimeError(
"No systemd socket named %r was passed to this service; check the "
"FileDescriptorName= of the corresponding .socket unit" % name
)
class Server(socketserver.ThreadingMixIn, HTTPServer):
daemon_threads = True
class NoBindHTTPServer(HTTPServer):
def server_bind(): pass def server_bind(): pass
def server_activate(): pass def server_activate(): pass
def main(): def __init__(self, *args, **kwargs):
httpd = NoBindHTTPServer( super().__init__(*args, **kwargs)
("", 0), self._request_threads = []
Handler, self._request_threads_lock = threading.Lock()
bind_and_activate=False,
def process_request(self, request, client_address):
thread = threading.Thread(
target=self.process_request_thread,
args=(request, client_address),
) )
httpd.socket = socket.fromfd(3, socket.AF_INET, socket.SOCK_STREAM) thread.daemon = self.daemon_threads
httpd.serve_forever() with self._request_threads_lock:
self._request_threads.append(thread)
thread.start()
def join_request_threads(self, timeout):
deadline = time.monotonic() + timeout
with self._request_threads_lock:
threads = list(self._request_threads)
for thread in threads:
thread.join(max(deadline - time.monotonic(), 0))
def handle_reload(signum, frame):
monotonic_usec = time.clock_gettime_ns(time.CLOCK_MONOTONIC) // 1000
sd_notify("RELOADING=1\nMONOTONIC_USEC=%d" % monotonic_usec)
on_reload = globals().get("on_reload")
if callable(on_reload):
on_reload()
sd_notify("READY=1")
shutdown_requested = threading.Event()
def handle_sigterm(signum, frame):
sd_notify("STOPPING=1")
shutdown_requested.set()
${v.handler}
assert "Handler" in globals(), "You must define a class Handler(BaseHTTPRequestHandler) in the handler code"
def main():
signal.signal(signal.SIGHUP, handle_reload)
signal.signal(signal.SIGTERM, handle_sigterm)
fd = sd_listen_fd(SOCKET_NAME)
httpd = Server(("", 0), Handler, bind_and_activate=False)
httpd.socket = socket.socket(fileno=fd)
server_thread = threading.Thread(target=httpd.serve_forever, name="http-server", daemon=True)
server_thread.start()
sd_notify("READY=1")
shutdown_requested.wait()
deadline = time.monotonic() + SHUTDOWN_TIMEOUT
httpd.shutdown()
server_thread.join(max(deadline - time.monotonic(), 0))
httpd.join_request_threads(max(deadline - time.monotonic(), 0))
httpd.server_close()
if __name__ == '__main__': if __name__ == '__main__':
main() main()
+2 -2
View File
@@ -4,11 +4,11 @@ let
in in
stdenvNoCC.mkDerivation rec { stdenvNoCC.mkDerivation rec {
pname = "bluemap"; pname = "bluemap";
version = "5.20"; version = "5.22";
src = fetchurl { src = fetchurl {
url = "https://github.com/BlueMap-Minecraft/BlueMap/releases/download/v${version}/BlueMap-${version}-cli.jar"; url = "https://github.com/BlueMap-Minecraft/BlueMap/releases/download/v${version}/BlueMap-${version}-cli.jar";
hash = "sha256-txDN/vG429BHT09TrSB8uQhmB8irrmvvOXX4OX3OSC0="; hash = "sha256-oiidZJ9qg+BM8iKrzT1PLfTjLmEUcBX5IcBQZvY+77c=";
}; };
dontUnpack = true; dontUnpack = true;
-23
View File
@@ -80,29 +80,6 @@ in {
}; };
}; };
nodes.drolsum = mkDevice "drolsum" {
guestType = "proxmox";
parent = config.nodes.powerpuff-cluster.id;
deviceType = "loginbox";
deviceIcon = "${pkgs.super-tiny-icons}/share/icons/SuperTinyIcons/svg/debian.svg";
# TODO: the interface name is likely wrong
interfaceGroups = [ [ "eth0" ] ];
interfaces.eth0 = {
network = "pvv";
# mac = "";
addresses = [
"129.241.210.217"
"2001:700:300:1900::217"
"2001:700:300:1900::1:217"
];
gateways = [
values.hosts.gateway
values.hosts.gateway6
];
};
};
nodes.microbel = mkDevice "microbel" { nodes.microbel = mkDevice "microbel" {
deviceIcon = "${pkgs.super-tiny-icons}/share/icons/SuperTinyIcons/svg/debian.svg"; deviceIcon = "${pkgs.super-tiny-icons}/share/icons/SuperTinyIcons/svg/debian.svg";