Merge remote-tracking branch 'lass/master'

This commit is contained in:
makefu 2020-04-21 21:50:59 +02:00
commit c96504d9a0
No known key found for this signature in database
GPG Key ID: 36F7711F3FC0F225
51 changed files with 1082 additions and 498 deletions

View File

@ -4,7 +4,7 @@ let
pkgsWithOverlay = import <nixpkgs-unstable> {
overlays = [
(import (builtins.fetchTarball {
url = https://github.com/nix-community/emacs-overlay/archive/master.tar.gz;
url = https://github.com/nix-community/emacs-overlay/archive/403c14c23be188b58c0b1bc197b428041d8a0cea.tar.gz;
}))
];
};

View File

@ -26,14 +26,12 @@
"http://cgit.hotdog.r/krops"
"http://cgit.ni.r/krops"
"http://cgit.prism.r/krops"
"https://git.ingolf-wagner.de/krebs/krops.git"
"https://github.com/krebs/krops.git"
];
nix_writers.urls = [
"http://cgit.hotdog.r/nix-writers"
"http://cgit.ni.r/nix-writers"
"http://cgit.prism.r/nix-writers"
"https://git.ingolf-wagner.de/krebs/nix-writers.git"
];
stockholm.urls = [
"http://cgit.enklave.r/stockholm"

View File

@ -52,7 +52,7 @@ let
"${url}",
workdir='${name}-${elemAt(splitString "." url) 1}', branches=True,
project='${name}',
pollinterval=10
pollinterval=100
)
)
'') repo.urls)

View File

@ -50,7 +50,6 @@ let
./secret.nix
./setuid.nix
./shadow.nix
./syncthing.nix
./tinc.nix
./tinc_graphs.nix
./urlwatch.nix

View File

@ -373,6 +373,30 @@ in {
syncthing.id = "22NLFY5-QMRM3BH-76QIBYI-OPMKVGM-DU4FNZI-3KN2POF-V4WIC6M-2SFFUAC";
nets = {};
};
catalonia = {
owner = config.krebs.users.xkey;
nets = {
retiolum = {
ip4.addr = "10.243.13.12";
aliases = [ "catalonia.r" ];
tinc.pubkey = ''
-----BEGIN RSA PUBLIC KEY-----
MIICCgKCAgEAug+nej8/spuRHdzcfBYAuzUVoiq4YufmJqXSshvgf4aqjeVEt91Y
gT6iBN8IKnMjYk3bAS7MxmgiyVE17MQlaQi0RSYY47M8I9TvCYtWX/FcXuP9e6CA
VcalDUNpy2qNB+yEE8gMa8vDA3smKk/iK47jTtpWoPtvejLK/SCi8RdlYjKlOErE
Yl9mCniGD1WEYgdrjf6Nl7av6uuGYNibivIMkB2JyGwGGmzvP+oBFi2Cwarw8K2e
FK2VGrAfkgiP5rTPACHseoeCsJtRLozgzYzmS5M9XhP5ZoPkbtR/pL5btCwoCTlZ
HotmLVg4DezbPjNOBB9gtJF4UuzQjSPNY6K1VvvLOhDwXdyln82LuNcm9l+cy9y3
mGeSvqOouBugDqie6OpkF0KrRwlGQVwzwtnDohGd/5f7TbiPf1QjC+JP/m4mxZl3
zE0BCOct9b4hUc/CFto71CPlytSbTsMhfJAn8JxttGvsWIAj+dQ0iuLXfLDflWt6
sImmnOo28YInvFx6pKoxTwcV1AVrPWn5TSePhZM50dmzs0exltOISFECDhpPabU3
ZymRCze8fH9Z3SHxfxTlTZV7IaW2kpyyBe1KsWpM46gLPk5icX+Xc6mdGwbdGBpf
vDZ+BoHCjq9FfQrAu1+E83yCYyu+3fWrLSgYyrqjg0gPcCcnb1g6hqECAwEAAQ==
-----END RSA PUBLIC KEY-----
'';
};
};
};
};
users = {
ciko = {
@ -421,6 +445,7 @@ in {
mail = "xq@shackspace.de";
pubkey = ssh-for "xq";
};
xkey = {};
miaoski = {
};
filly = {

View File

@ -144,24 +144,24 @@ in {
};
};
};
idontcare = {
herbert = {
owner = config.krebs.users.Mic92;
nets = rec {
retiolum = {
addrs = [
config.krebs.hosts.idontcare.nets.retiolum.ip4.addr
config.krebs.hosts.idontcare.nets.retiolum.ip6.addr
config.krebs.hosts.herbert.nets.retiolum.ip4.addr
config.krebs.hosts.herbert.nets.retiolum.ip6.addr
];
ip4.addr = "10.243.29.177";
aliases = [ "idontcare.r" ];
aliases = [ "herbert.r" ];
tinc.pubkey = ''
-----BEGIN RSA PUBLIC KEY-----
MIIBCgKCAQEAxmmbQLVXcnCU9Vg9TCoJxfq/RyNfzaTj8XJsn4Kpo3CvQOwFzL6O
qZnbG55WjPjPumuFgtUdHA/G8mgtrTVaIRbVE9ck2l2wWFzMWxORzuvDbMh5xP8A
OW2Z2qjlH6O9GTBCzpYyHuyBWCjtiN4x9zEqxkIsBARKOylAoy3zQIiiQF0d72An
lqKFi9vYUU90zo9rP8BTzx2ZsEWb28xhHUlwf1+vgaOHI1jI99gnr12dVYl/i/Hb
O28gDUogfpP/5pWFAHJ+53ZscHo8/Y7imjiKgGXmOHywoXOsKQ67M6ROEU/0xPnw
jKmq2p7zTJk2mDhphjePi5idd5yKNX5Q3wIDAQAB
MIIBCgKCAQEA7ZINr8YxVwHtcOR+ySpc9UjnJWsFXlOyu3CnrJ8IrY+mPA25UmNZ
stXd8QbJuxpad9HyPs294uW8UmXttEZzIwAlikVHasM5IQHVltudTTFvv7s3YFWd
/lgpHbo8zOA2mafx+Sr02Fy/lHjk6BTf8IOzdJIpUHZL/P+FUl9baBwGLmtbEvPh
fbvtf5QryBjJ9nRnb+wsPVpeFE/LncIMK/bYQsyE01T5QDu/muAaeYPbgm6FqaQH
OJ4oEHsarWBvU1qzgz/IRz0BHHeTrbbP3AG/glTwL02Z1mtTXSjME7cfk7ZRM5Cj
jXAqnqu2m1B08Kii+zYp4BPZDmPLT5gq+QIDAQAB
-----END RSA PUBLIC KEY-----
'';
};

View File

@ -19,6 +19,10 @@ let
type = types.str;
default = "irc.freenode.org";
};
message = mkOption {
type = types.str;
default = "SSH Hidden Service at ";
};
};
imp = let
@ -50,7 +54,7 @@ let
${pkgs.irc-announce}/bin/irc-announce \
${cfg.server} 6667 ${config.krebs.build.host.name}-ssh \
\${cfg.channel} \
"SSH Hidden Service at $(cat ${hiddenServiceDir}/hostname)"
"${cfg.message}$(cat ${hiddenServiceDir}/hostname)"
'';
PrivateTmp = "true";
User = "tor";

View File

@ -45,6 +45,10 @@ with import <stockholm/lib>;
default = self.config.port == "6697";
type = types.bool;
};
API.listen = mkOption {
default = null;
type = types.nullOr types.str;
};
};
}));
};
@ -65,9 +69,11 @@ with import <stockholm/lib>;
ExecStart = let
configFile = pkgs.writeJSON configFileName configValue;
configFileName = "${cfg.systemd-service-name}.config.json";
configValue = recursiveUpdate {
logTime = false;
} (removeAttrs cfg ["_module"]);
configValue = stripAttr (
recursiveUpdate {
logTime = false;
} (removeAttrs cfg ["_module"])
);
in "${pkgs.reaktor2}/bin/reaktor ${configFile}";
Restart = "always";
RestartSec = "30";

View File

@ -17,21 +17,6 @@ let
default = "/var/realwallpaper/";
};
nightmap = mkOption {
type = types.str;
default = "http://eoimages.gsfc.nasa.gov/images/imagerecords/55000/55167/earth_lights_lrg.jpg";
};
daymap = mkOption {
type = types.str;
default = "https://www.nnvl.noaa.gov/images/globaldata/SnowIceCover_Daily.png";
};
cloudmap = mkOption {
type = types.str;
default = "http://home.megapass.co.kr/~holywatr/cloud_data/clouds_2048.jpg";
};
marker = mkOption {
type = types.str;
default = "http://graph.r/marker.json";
@ -60,6 +45,7 @@ let
path = with pkgs; [
xplanet
imagemagick
inkscape
curl
file
jq
@ -67,9 +53,6 @@ let
environment = {
working_dir = cfg.workingDir;
nightmap_url = cfg.nightmap;
daymap_url = cfg.daymap;
cloudmap_url = cfg.cloudmap;
marker_url = cfg.marker;
};

View File

@ -1,206 +0,0 @@
{ config, pkgs, ... }: with import <stockholm/lib>;
let
kcfg = config.krebs.syncthing;
scfg = config.services.syncthing;
devices = mapAttrsToList (name: peer: {
name = name;
deviceID = peer.id;
addresses = peer.addresses;
}) kcfg.peers;
folders = mapAttrsToList ( _: folder: {
inherit (folder) path id type;
devices = map (peer: { deviceId = kcfg.peers.${peer}.id; }) folder.peers;
rescanIntervalS = folder.rescanInterval;
fsWatcherEnabled = folder.watch;
fsWatcherDelayS = folder.watchDelay;
ignoreDelete = folder.ignoreDelete;
ignorePerms = folder.ignorePerms;
}) kcfg.folders;
getApiKey = pkgs.writeDash "getAPIKey" ''
${pkgs.libxml2}/bin/xmllint \
--xpath 'string(configuration/gui/apikey)'\
${scfg.configDir}/config.xml
'';
updateConfig = pkgs.writeDash "merge-syncthing-config" ''
set -efu
# XXX this assumes the GUI address to be "IPv4 address and port"
host=${shell.escape (elemAt (splitString ":" scfg.guiAddress) 0)}
port=${shell.escape (elemAt (splitString ":" scfg.guiAddress) 1)}
# wait for service to restart
${pkgs.untilport}/bin/untilport "$host" "$port"
API_KEY=$(${getApiKey})
_curl() {
${pkgs.curl}/bin/curl \
-Ss \
-H "X-API-Key: $API_KEY" \
"http://$host:$port/rest""$@"
}
old_config=$(_curl /system/config)
new_config=${shell.escape (toJSON {
inherit devices folders;
})}
new_config=$(${pkgs.jq}/bin/jq -en \
--argjson old_config "$old_config" \
--argjson new_config "$new_config" \
'
$old_config * $new_config
${optionalString (!kcfg.overridePeers) ''
* { devices: $old_config.devices }
''}
${optionalString (!kcfg.overrideFolders) ''
* { folders: $old_config.folders }
''}
'
)
echo $new_config | _curl /system/config -d @-
_curl /system/restart -X POST
'';
in
{
options.krebs.syncthing = {
enable = mkEnableOption "syncthing-init";
cert = mkOption {
type = types.nullOr types.absolute-pathname;
default = null;
};
key = mkOption {
type = types.nullOr types.absolute-pathname;
default = null;
};
overridePeers = mkOption {
type = types.bool;
default = true;
description = ''
Whether to delete the peers which are not configured via the peers option
'';
};
peers = mkOption {
default = {};
type = types.attrsOf (types.submodule ({
options = {
# TODO make into addr + port submodule
addresses = mkOption {
type = types.listOf types.str;
default = [];
};
#TODO check
id = mkOption {
type = types.str;
};
};
}));
};
overrideFolders = mkOption {
type = types.bool;
default = true;
description = ''
Whether to delete the folders which are not configured via the peers option
'';
};
folders = mkOption {
default = {};
type = types.attrsOf (types.submodule ({ config, ... }: {
options = {
path = mkOption {
type = types.absolute-pathname;
default = config._module.args.name;
};
id = mkOption {
type = types.str;
default = config._module.args.name;
};
peers = mkOption {
type = types.listOf types.str;
default = [];
};
rescanInterval = mkOption {
type = types.int;
default = 3600;
};
type = mkOption {
type = types.enum [ "sendreceive" "sendonly" "receiveonly" ];
default = "sendreceive";
};
watch = mkOption {
type = types.bool;
default = true;
};
watchDelay = mkOption {
type = types.int;
default = 10;
};
ignoreDelete = mkOption {
type = types.bool;
default = false;
};
ignorePerms = mkOption {
type = types.bool;
default = true;
};
};
}));
};
};
config = mkIf kcfg.enable {
systemd.services.syncthing = mkIf (kcfg.cert != null || kcfg.key != null) {
serviceConfig.PermissionsStartOnly = mkDefault true;
preStart = ''
${optionalString (kcfg.cert != null) ''
cp ${toString kcfg.cert} ${scfg.configDir}/cert.pem
chown ${scfg.user}:${scfg.group} ${scfg.configDir}/cert.pem
chmod 400 ${scfg.configDir}/cert.pem
''}
${optionalString (kcfg.key != null) ''
cp ${toString kcfg.key} ${scfg.configDir}/key.pem
chown ${scfg.user}:${scfg.group} ${scfg.configDir}/key.pem
chmod 400 ${scfg.configDir}/key.pem
''}
'';
};
systemd.services.syncthing-init = {
after = [ "syncthing.service" ];
wantedBy = [ "multi-user.target" ];
serviceConfig = {
User = scfg.user;
RemainAfterExit = true;
Type = "oneshot";
ExecStart = updateConfig;
};
};
};
}

View File

@ -1,17 +1,18 @@
{ mkDerivation, aeson, async, attoparsec, base, blessings
, bytestring, containers, data-default, fetchgit, filepath
, hashable, lens, lens-aeson, network, network-simple
, network-simple-tls, pcre-light, process, random, stdenv
, string-conversions, stringsearch, text, time, transformers
, unagi-chan, unix, unordered-containers, vector
, network-simple-tls, network-uri, pcre-light, process, random
, servant-server, stdenv, string-conversions, stringsearch, text
, time, transformers, unagi-chan, unix, unordered-containers
, vector, wai, warp
}:
mkDerivation {
pname = "reaktor2";
version = "0.2.2";
version = "0.3.0";
src = fetchgit {
url = "https://cgit.krebsco.de/reaktor2";
sha256 = "1kyr5i5zdzvc7fcyac1i1yvi88kcxafrgp8p79c1b9l4g9sjnv78";
rev = "9f4e2644188f985d7cd806c13e2c0dee1688b9f0";
sha256 = "02hqpq8wcfd6rvi8qk10zy3f3lrzzqnjwqal4cbvksjn3vahz36h";
rev = "a6893c00f78a8acd0a4bfe7da87ab6889eabcf21";
fetchSubmodules = true;
};
isLibrary = false;
@ -19,9 +20,9 @@ mkDerivation {
executableHaskellDepends = [
aeson async attoparsec base blessings bytestring containers
data-default filepath hashable lens lens-aeson network
network-simple network-simple-tls pcre-light process random
string-conversions stringsearch text time transformers unagi-chan
unix unordered-containers vector
network-simple network-simple-tls network-uri pcre-light process
random servant-server string-conversions stringsearch text time
transformers unagi-chan unix unordered-containers vector wai warp
];
license = stdenv.lib.licenses.mit;
}

View File

@ -0,0 +1,19 @@
{ stdenv, fetchzip, makeWrapper, jre }:
stdenv.mkDerivation {
name = "grib2json";
src = fetchzip {
url = "https://github.com/krebs/grib2json-bin/archive/31efe677b40fe491c988d50f96b59b1b7e2d46f7.zip";
sha256 = "1h3yxg270bvac7kaqsbsv4f8nln1i03rfz4cm8cp7llhjj3s6a6b";
};
installPhase = ''
mkdir -p $out/bin
cp -r lib $out/
cat > $out/bin/grib2json << EOF
#!/bin/sh
set -x
${jre}/bin/java -jar $out/lib/grib2json-0.8.0-SNAPSHOT.jar "\$@"
EOF
chmod +x $out/bin/grib2json
'';
}

View File

@ -25,10 +25,10 @@ pkgs.writeDashBin "irc-announce" ''
# This is used to see what we send to the irc server. (debug output)
echo2() { echo "$*"; echo "$*" >&2; }
cat2() {
while read -r line; do
echo "$line"
echo "$line" >&2
done
awk '{
print $0
print $0 > "/dev/stderr"
}'
}
# privmsg_cat transforms stdin to a privmsg

View File

@ -0,0 +1,43 @@
{ writers, coreutils, grib2json, curl, jq, findutils, imagemagick }:
writers.writeDashBin "nomads-cloud" ''
prefix=$(mktemp -d)
grib_path=$prefix.grib
json_path=$prefix.json
pgm_path=$prefix.pgm
png_path="$1"
mkdir -p "$prefix"
date=$(${coreutils}/bin/date +%Y%m%d)
for hour in 18 12 06 00; do
url="https://nomads.ncep.noaa.gov/cgi-bin/filter_gfs_0p25_1hr.pl?file=gfs.t''${hour}z.pgrb2.0p25.anl&lev_entire_atmosphere_%5C%28considered_as_a_single_layer%5C%29=on&var_CWAT=on&leftlon=-180&rightlon=180&toplat=90&bottomlat=-90&dir=%2Fgfs.$date%2F$hour"
${curl}/bin/curl -fsS "$url" > "$grib_path"
if [ "$?" -eq 0 ]; then
break
fi
done
${grib2json}/bin/grib2json --data "$grib_path" > "$json_path"
width=$(${jq}/bin/jq '.[0].header.nx' < "$json_path")
height=$(${jq}/bin/jq '.[0].header.ny' < "$json_path")
# The maximum gray value. Must be bigger than 0 and less than 65536.
maxval=1000
# pgm - Netpbm grayscale image format
# http://netpbm.sourceforge.net/doc/pgm.html
{
echo P2
echo "$width $height"
echo "$maxval"
cat "$json_path" |
${jq}/bin/jq --argjson maxval "$maxval" -c '
((.[0].data[]) * $maxval | round)
' |
${findutils}/bin/xargs -n "$width"
} > "$pgm_path"
${imagemagick}/bin/convert -roll +50% "$pgm_path" "$png_path"
rm -r "$prefix"
''

View File

@ -1,5 +1,5 @@
{ pkgs, ... }:
pkgs.writeDashBin "generate-wallpaper" ''
pkgs.writers.writeDashBin "generate-wallpaper" ''
set -euf
# usage: getimg FILENAME URL
@ -17,24 +17,28 @@ pkgs.writeDashBin "generate-wallpaper" ''
fi
}
# usage: image_size FILENAME
image_size() {
identify "$1" | awk '{print$3}'
# check if file exists and fetch only if missing
fetch_once() {
name=$1
url=$2
test -e "$name" || fetch "$name" "$url"
}
# usage: make_mask DST SRC MASK
make_layer() {
if needs_rebuild "$@"; then
echo "make $1 (apply mask)" >&2
convert "$2" "$3" -alpha off -compose copy_opacity -composite "$1"
fetch_older_min() {
min=$1
name=$2
url=$3
if ! test "$(find $name -mmin -$min)"; then
fetch "$name" "$url"
fi
}
# usage: flatten DST HILAYER LOLAYER
flatten() {
if needs_rebuild "$@"; then
echo "make $1 (flatten)" >&2
composite "$2" "$3" "$1"
fetch_older_days() {
days=$1
name=$2
url=$3
if ! test "$(find $name -mtime -$days)"; then
fetch "$name" "$url"
fi
}
@ -48,9 +52,11 @@ pkgs.writeDashBin "generate-wallpaper" ''
else
result=1
for b; do
if test "$b" -nt "$a"; then
#echo " $b is newer than $a" >&2
result=0
if check_type "$b" image; then
if test "$b" -nt "$a"; then
#echo " $b is newer than $a" >&2
result=0
fi
fi
done
fi
@ -60,34 +66,67 @@ pkgs.writeDashBin "generate-wallpaper" ''
return $result
}
get_neo_url() {
url=$1
curl -Ss "$url" | grep '3600 x 1800' | sed 's/.*href="\([^"]*\)".*/\1/'
}
main() {
cd "$working_dir"
# fetch source images in parallel
fetch nightmap-raw.jpg \
"$nightmap_url" &
fetch daymap-raw.png \
"$daymap_url" &
fetch clouds-raw.jpg \
"$cloudmap_url" &
fetch marker.json \
"$marker_url" &
fetch_once nightmap-raw.jpg \
'https://eoimages.gsfc.nasa.gov/images/imagerecords/144000/144898/BlackMarble_2016_3km.jpg' &
fetch_once daymap-raw.tif \
'https://eoimages.gsfc.nasa.gov/images/imagerecords/57000/57752/land_shallow_topo_8192.tif' &
fetch_once mercury-raw.svg \
'https://upload.wikimedia.org/wikipedia/commons/2/2e/Mercury_symbol.svg' &
fetch_once venus-raw.svg \
'https://upload.wikimedia.org/wikipedia/commons/6/66/Venus_symbol.svg' &
fetch_once mars-raw.svg \
'https://upload.wikimedia.org/wikipedia/commons/b/b7/Mars_symbol.svg' &
fetch_once jupiter-raw.svg \
'https://upload.wikimedia.org/wikipedia/commons/2/26/Jupiter_symbol.svg' &
fetch_once saturn-raw.svg \
'https://upload.wikimedia.org/wikipedia/commons/7/74/Saturn_symbol.svg' &
fetch_once uranus-raw.svg \
'https://upload.wikimedia.org/wikipedia/commons/f/f1/Uranus_symbol.svg' &
fetch_once neptune-raw.svg \
'https://upload.wikimedia.org/wikipedia/commons/4/47/Neptune_symbol.svg' &
fetch_once krebs-raw.svg \
'https://raw.githubusercontent.com/krebs/painload/master/cholerab/bling/krebs_aquarium.svg' &
fetch_older_min 720 ice-raw.jpg $(get_neo_url \
'https://neo.sci.gsfc.nasa.gov/view.php?datasetId=NISE_D') &
fetch_older_days 3 snow-raw.jpg $(get_neo_url \
'https://neo.sci.gsfc.nasa.gov/view.php?datasetId=MOD10C1_E_SNOW') &
fetch_older_days 7 chlora-raw.jpg $(get_neo_url \
'https://neo.sci.gsfc.nasa.gov/view.php?datasetId=MY1DMM_CHLORA') &
fetch_older_days 3 fire-raw.jpg $(get_neo_url \
'https://neo.sci.gsfc.nasa.gov/view.php?datasetId=MOD14A1_E_FIRE') &
# regular fetches
fetch marker.json "$marker_url" &
fetch sun-raw.jpg 'https://sdo.gsfc.nasa.gov/assets/img/latest/latest_512_0171.jpg' &
wait
check_type nightmap-raw.jpg image
check_type daymap-raw.png image
check_type clouds-raw.jpg image
# fetch clouds if they are older than 3h
if ! test "$(find clouds-raw.png -mmin -180)"; then
${pkgs.nomads-cloud}/bin/nomads-cloud clouds-raw.png
fi
in_size=2048x1024
xplanet_out_size=1466x1200
out_geometry=1366x768+100+160
nightsnow_color='#0c1a49' # nightmap
in_size=3600x1800
xplanet_out_size=3200x2500
out_geometry=3200x1800+0+350
for raw in \
nightmap-raw.jpg \
daymap-raw.png \
clouds-raw.jpg \
daymap-raw.tif \
chlora-raw.jpg \
clouds-raw.png \
;
do
normal=''${raw%-raw.*}.png
@ -97,49 +136,79 @@ pkgs.writeDashBin "generate-wallpaper" ''
fi
done
# create nightmap-fullsnow
if needs_rebuild nightmap-fullsnow.png; then
convert -size $in_size xc:$nightsnow_color nightmap-fullsnow.png
# remove snow from ice map
if needs_rebuild ice.png ice-raw.jpg; then
convert ice-raw.jpg -fuzz 20% -fill black -opaque white -colorspace gray -blur 0x6 -scale "$in_size" ice.png
fi
# extract daymap-snowmask from daymap-final
if needs_rebuild daymap-snowmask.png daymap.png; then
convert daymap.png -threshold 95% daymap-snowmask.png
if needs_rebuild snow.png snow-raw.jpg; then
convert snow-raw.jpg -fuzz 20% -fill '#DEDEDE' -opaque white -scale "$in_size" snow.png
fi
# extract nightmap-lightmask from nightmap
if needs_rebuild nightmap-lightmask.png nightmap.png; then
convert nightmap.png -threshold 25% nightmap-lightmask.png
# make fire more red
if needs_rebuild fire.png fire-raw.jpg; then
convert fire-raw.jpg -fuzz 20% -fill '#ef840c' -opaque white -scale "$in_size" fire.png
fi
# create layers
make_layer nightmap-snowlayer.png nightmap-fullsnow.png daymap-snowmask.png
make_layer nightmap-lightlayer.png nightmap.png nightmap-lightmask.png
# cut out sun with alpha transparency
if needs_rebuild sun.png sun-raw.jpg; then
convert sun-raw.jpg \
\( +clone -colorspace HSB -fill white -draw "circle 256,256 256,54" -separate -delete 0,1 \) \
-compose copyopacity -composite -crop 512x472+0+20 -scale "100x100" sun.png
fi
# apply layers
flatten nightmap-lightsnowlayer.png \
nightmap-lightlayer.png \
nightmap-snowlayer.png
if needs_rebuild krebs.png krebs-raw.svg; then
inkscape -z -e krebs.png -w 16 -h 16 krebs-raw.svg
fi
flatten nightmap-final.png \
nightmap-lightsnowlayer.png \
nightmap.png
# -- Planets --
for planet in mercury venus mars jupiter saturn uranus neptune; do
if needs_rebuild "$planet".png "$planet"-raw.svg; then
sed -i 's/#000/#FE8019/g' "$planet"-raw.svg
inkscape -z -e "$planet".png -w 40 -h 40 "$planet"-raw.svg
fi
done
# -- Daymap --
# merge with water chlora layer
if needs_rebuild daymap-final.png daymap.png fire.png snow.png ice.png chlora.png; then
convert daymap.png fire.png -compose lighten -composite daymap-1.png
convert daymap-1.png ice.png -compose lighten -composite daymap-2.png
convert daymap-2.png snow.png -compose lighten -composite daymap-3.png
convert daymap-3.png chlora.png -compose lighten -composite daymap-final.png
fi
# -- Nightmap --
if needs_rebuild nightmap-final.png nightmap.png fire.png snow.png ice.png chlora.png; then
convert nightmap.png fire.png -compose lighten -composite nightmap-1.png
convert nightmap-1.png \( -fill black -colorize 70% ice.png \) -compose lighten -composite nightmap-2.png
convert nightmap-2.png \( -fill black -colorize 70% snow.png \) -compose lighten -composite nightmap-3.png
convert nightmap-3.png \( -fill black -colorize 70% chlora.png \) -compose lighten -composite nightmap-final.png
fi
# create marker file from json
if [ -s marker.json ]; then
jq -r 'to_entries[] | @json "\(.value.latitude) \(.value.longitude)"' marker.json > marker_file
jq -r 'to_entries[] | @json "\(.value.latitude) \(.value.longitude) image=krebs.png"' marker.json > marker_file
echo 'position=sun image=sun.png' >> marker_file
echo 'position=moon image=moon.png' >> marker_file
echo 'position=mercury image=mercury.png' >> marker_file
echo 'position=venus image=venus.png' >> marker_file
echo 'position=mars image=mars.png' >> marker_file
echo 'position=jupiter image=jupiter.png' >> marker_file
echo 'position=saturn image=saturn.png' >> marker_file
echo 'position=uranus image=uranus.png' >> marker_file
echo 'position=neptune image=neptune.png' >> marker_file
fi
# make all unmodified files as final
for normal in \
daymap.png \
clouds.png \
;
do
final=''${normal%.png}-final.png
needs_rebuild $final &&
ln $normal $final
done
# generate moon
xplanet -body moon --num_times 1 -origin earth \
--transpng moon.png --geometry 50x50 \
-config ${pkgs.writeText "moon.config" ''
[moon]
shade=10
''}
# rebuild every time to update shadow
xplanet --num_times 1 --geometry $xplanet_out_size \
@ -149,8 +218,9 @@ pkgs.writeDashBin "generate-wallpaper" ''
"Earth"
map=daymap-final.png
night_map=nightmap-final.png
cloud_map=clouds-final.png
cloud_threshold=10
cloud_map=clouds.png
cloud_threshold=1
cloud_gamma=10
shade=15
''}
@ -161,8 +231,9 @@ pkgs.writeDashBin "generate-wallpaper" ''
"Earth"
map=daymap-final.png
night_map=nightmap-final.png
cloud_map=clouds-final.png
cloud_threshold=10
cloud_map=clouds.png
cloud_threshold=1
cloud_gamma=10
marker_file=marker_file
shade=15
''}
@ -178,6 +249,8 @@ pkgs.writeDashBin "generate-wallpaper" ''
convert xplanet-krebs-output.png -crop $out_geometry \
realwallpaper-krebs-tmp.png
mv realwallpaper-krebs-tmp.png realwallpaper-krebs.png
mkdir -p archive
convert realwallpaper-krebs.png archive/"$(date -Is)".jpg
fi
}

View File

@ -1,7 +1,7 @@
{
"url": "https://github.com/NixOS/nixpkgs-channels",
"rev": "55beed9922c2f6b030af61ca7e33bd47850c68f2",
"date": "2020-02-26T03:53:16-05:00",
"sha256": "0jxkb3bl7axa6vmfsfdfx4mxv6wx0pc8iiwgrw2qh8wxhlhbylks",
"rev": "b61999e4ad60c351b4da63ae3ff43aae3c0bbdfb",
"date": "2020-04-16T08:43:36-04:00",
"sha256": "0cggpdks4qscyirqwfprgdl91mlhjlw24wkg0riapk5f2g2llbpq",
"fetchSubmodules": false
}

View File

@ -1,7 +1,7 @@
{
"url": "https://github.com/NixOS/nixpkgs-channels",
"rev": "b7bbc6d37878ed00b6467b574b02e840279f7d3d",
"date": "2020-02-26T11:51:29+01:00",
"sha256": "02q10jgi6m0vak3amb50ifw1pj82i17hs0npdkig7lsp8w3is7jq",
"rev": "b67bc34d4e3de1e89b8bb7cd6e375ba44f1ae8ca",
"date": "2020-04-15T22:11:06+01:00",
"sha256": "1q9a64bl5afflgpa2iaw1q7z7s08c8xq9w6lndlnc5c3siajrp8v",
"fetchSubmodules": false
}

View File

@ -33,4 +33,6 @@
services.logind.lidSwitch = "ignore";
services.logind.lidSwitchDocked = "ignore";
boot.tmpOnTmpfs = true;
}

View File

@ -46,6 +46,15 @@
'';
services.thinkfan.enable = true;
services.thinkfan.levels = ''
(0, 0, 55)
(1, 48, 60)
(2, 50, 61)
(3, 52, 63)
(6, 60, 65)
(7, 80, 85)
(127, 90, 32767)
'';
services.logind.lidSwitch = "ignore";
services.logind.lidSwitchDocked = "ignore";

View File

@ -49,17 +49,17 @@ with import <stockholm/lib>;
];
}
{
krebs.syncthing = {
peers.schasch.addresses = [ "schasch.r:22000" ];
services.syncthing.declarative = {
devices.schasch.addresses = [ "schasch.r:22000" ];
folders = {
the_playlist = {
path = "/home/lass/tmp/the_playlist";
peers = [ "mors" "phone" "prism" "xerxes" ];
devices = [ "mors" "phone" "prism" "xerxes" ];
};
free_music = {
id = "mu9mn-zgvsw";
path = "/home/lass/tmp/free_music";
peers = [ "mors" "schasch" ];
devices = [ "mors" "schasch" ];
};
};
};

View File

@ -263,8 +263,6 @@ with import <stockholm/lib>;
}
{
users.users.download.openssh.authorizedKeys.keys = [
"ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQDB0d0JA20Vqn7I4lCte6Ne2EOmLZyMJyS9yIKJYXNLjbLwkQ4AYoQKantPBkTxR75M09E7d3j5heuWnCjWH45TrfQfe1EOSSC3ppCI6C6aIVlaNs+KhAYZS0m2Y8WkKn+TT5JLEa8yybYVN/RlZPOilpj/1QgjU6CQK+eJ1k/kK+QFXcwN82GDVh5kbTVcKUNp2tiyxFA+z9LY0xFDg/JHif2ROpjJVLQBJ+YPuOXZN5LDnVcuyLWKThjxy5srQ8iDjoxBg7dwLHjby5Mv41K4W61Gq6xM53gDEgfXk4cQhJnmx7jA/pUnsn2ZQDeww3hcc7vRf8soogXXz2KC9maiq0M/svaATsa9Ul4hrKnqPZP9Q8ScSEAUX+VI+x54iWrnW0p/yqBiRAzwsczdPzaQroUFTBxrq8R/n5TFdSHRMX7fYNOeVMjhfNca/gtfw9dYBVquCvuqUuFiRc0I7yK44rrMjjVQRcAbw6F8O7+04qWCmaJ8MPlmApwu2c05VMv9hiJo5p6PnzterRSLCqF6rIdhSnuOwrUIt1s/V+EEZXHCwSaNLaQJnYL0H9YjaIuGz4c8kVzxw4c0B6nl+hqW5y5/B2cuHiumnlRIDKOIzlv8ufhh21iN7QpIsPizahPezGoT1XqvzeXfH4qryo8O4yTN/PWoA+f7o9POU7L6hQ== lhebendanz@nixos"
config.krebs.users.palo.pubkey
];
}
{
@ -338,30 +336,36 @@ with import <stockholm/lib>;
localAddress = "10.233.2.14";
};
services.nginx.virtualHosts."lassul.us".locations."^~ /flix/".extraConfig = ''
if ($scheme != "https") {
rewrite ^ https://$host$request_uri permanent;
}
auth_basic "Restricted Content";
auth_basic_user_file ${pkgs.writeText "flix-user-pass" ''
krebs:$apr1$1Fwt/4T0$YwcUn3OBmtmsGiEPlYWyq0
''};
proxy_pass http://10.233.2.14:80/;
proxy_set_header Accept-Encoding "";
sub_filter "https://lassul.us/" "https://lassul.us/flix/";
sub_filter_once off;
'';
services.nginx.virtualHosts."lassul.us".locations."^~ /transmission".extraConfig = ''
if ($scheme != "https") {
rewrite ^ https://$host$request_uri permanent;
}
auth_basic "Restricted Content";
auth_basic_user_file ${pkgs.writeText "transmission-user-pass" ''
krebs:$apr1$1Fwt/4T0$YwcUn3OBmtmsGiEPlYWyq0
''};
proxy_pass_header X-Transmission-Session-Id;
proxy_pass http://10.233.2.14:9091;
'';
services.nginx.virtualHosts."lassul.us" = {
locations."^~ /flix/".extraConfig = ''
if ($scheme != "https") {
rewrite ^ https://$host$request_uri permanent;
}
auth_basic "Restricted Content";
auth_basic_user_file ${pkgs.writeText "flix-user-pass" ''
krebs:$apr1$1Fwt/4T0$YwcUn3OBmtmsGiEPlYWyq0
''};
proxy_pass http://10.233.2.14:80/;
proxy_set_header Accept-Encoding "";
sub_filter "https://lassul.us/" "https://lassul.us/flix/";
sub_filter_once off;
'';
locations."^~ /chatty/".extraConfig = ''
rewrite ^ https://$host/flix/$request_uri permanent;
'';
#locations."^~ /transmission".return = "301 https://$host/transmission/web/";
locations."^~ /transmission/".extraConfig = ''
if ($scheme != "https") {
rewrite ^ https://$host$request_uri permanent;
}
auth_basic "Restricted Content";
auth_basic_user_file ${pkgs.writeText "transmission-user-pass" ''
krebs:$apr1$1Fwt/4T0$YwcUn3OBmtmsGiEPlYWyq0
''};
proxy_pass_header X-Transmission-Session-Id;
proxy_pass http://10.233.2.14:9091;
'';
};
users.groups.download = {};
users.users = {
@ -376,6 +380,9 @@ with import <stockholm/lib>;
lass.pubkey
lass-android.pubkey
makefu.pubkey
palo.pubkey
"ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQDB0d0JA20Vqn7I4lCte6Ne2EOmLZyMJyS9yIKJYXNLjbLwkQ4AYoQKantPBkTxR75M09E7d3j5heuWnCjWH45TrfQfe1EOSSC3ppCI6C6aIVlaNs+KhAYZS0m2Y8WkKn+TT5JLEa8yybYVN/RlZPOilpj/1QgjU6CQK+eJ1k/kK+QFXcwN82GDVh5kbTVcKUNp2tiyxFA+z9LY0xFDg/JHif2ROpjJVLQBJ+YPuOXZN5LDnVcuyLWKThjxy5srQ8iDjoxBg7dwLHjby5Mv41K4W61Gq6xM53gDEgfXk4cQhJnmx7jA/pUnsn2ZQDeww3hcc7vRf8soogXXz2KC9maiq0M/svaATsa9Ul4hrKnqPZP9Q8ScSEAUX+VI+x54iWrnW0p/yqBiRAzwsczdPzaQroUFTBxrq8R/n5TFdSHRMX7fYNOeVMjhfNca/gtfw9dYBVquCvuqUuFiRc0I7yK44rrMjjVQRcAbw6F8O7+04qWCmaJ8MPlmApwu2c05VMv9hiJo5p6PnzterRSLCqF6rIdhSnuOwrUIt1s/V+EEZXHCwSaNLaQJnYL0H9YjaIuGz4c8kVzxw4c0B6nl+hqW5y5/B2cuHiumnlRIDKOIzlv8ufhh21iN7QpIsPizahPezGoT1XqvzeXfH4qryo8O4yTN/PWoA+f7o9POU7L6hQ== lhebendanz@nixos"
"AAAAB3NzaC1yc2EAAAADAQABAAABgQC4ECL9NSCWqs4KVe+FF+2BPtl5Bv5aQPHqnXllCyiESZykwRKLx6/AbF5SbUAUMVZtp9oDSdp28m3BvVeWJ/q7hAbIxUtfd/jp+JBRZ8Kj6K5GzUO7Bhgl/o0A7xEjAeOKHiYuLjdPMcFUyl6Ah4ey/mcQYf6AdU0+hYUDeUlKe/YxxYD6202W0GJq2xGdIqs/TbopT9iaX+sv0wdXDVfFY72nFqOUwJW3u6O2viKKRugrz/eo50Eo3ts7pYz/FpDXExrUvV9Vu/bQ34pa8nKgF3/AKQHgmzljNQSVZKyAV8OY0UFonjBMXCBg2tXtwfnlzdx2SyuQVv55x+0AuRKsi85G2xLpXu1A3921pseBTW6Q6kbYK9eqxAay2c/kNbwNqFnO+nCvQ6Ier/hvGddOtItMu96IuU2E7mPN6WgvM8/3fjJRFWnZxFxqu/k7iH+yYT8qwRgdiSqZc76qvkYEuabdk2itstTRY0A3SpI3hFMZDw/7bxgMZtqpfyoRk5s= philip@shiki11:15 <Profpatsch> AAAAB3NzaC1yc2EAAAADAQABAAABgQC4ECL9NSCWqs4KVe+FF+2BPtl5Bv5aQPHqnXllCyiESZykwRKLx6/AbF5SbUAUMVZtp9oDSdp28m3BvVeWJ/q7hAbIxUtfd/jp+JBRZ8Kj6K5GzUO7Bhgl/o0A7xEjAeOKHiYuLjdPMcFUyl6Ah4ey/mcQYf6AdU0+hYUDeUlKe/YxxYD6202W0GJq2xGdIqs/TbopT9iaX+sv0wdXDVfFY72nFqOUwJW3u6O2viKKRugrz/eo50Eo3ts7pYz/FpDXExrUvV9Vu/bQ34pa8nKgF3/AKQHgmzljNQSVZKyAV8OY0UFonjBMXCBg2tXtwfnlzdx2SyuQVv55x+0AuRKsi85G2xLpXu1A3921pseBTW6Q6kbYK9eqxAay2c/kNbwNqFnO+nCvQ6Ier/hvGddOtItMu96IuU2E7mPN6WgvM8/3fjJRFWnZxFxqu/k7iH+yYT8qwRgdiSqZc76qvkYEuabdk2itstTRY0A3SpI3hFMZDw/7bxgMZtqpfyoRk5s= philip@shiki"
];
};
};

View File

@ -19,7 +19,9 @@ with import <stockholm/lib>;
<stockholm/lass/2configs/ssh-cryptsetup.nix>
<stockholm/lass/2configs/nfs-dl.nix>
<stockholm/lass/2configs/gg23.nix>
<stockholm/lass/2configs/hass>
<stockholm/lass/2configs/br.nix>
<stockholm/lass/2configs/fetchWallpaper.nix>
];
krebs.build.host = config.krebs.hosts.shodan;

View File

@ -41,11 +41,11 @@
displayManager.lightdm.autoLogin.user = "lass";
};
krebs.syncthing = {
services.syncthing.declarative = {
folders = {
the_playlist = {
path = "/home/lass/tmp/the_playlist";
peers = [ "mors" "phone" "prism" "xerxes" ];
devices = [ "mors" "phone" "prism" "xerxes" ];
};
};
};

View File

@ -54,12 +54,107 @@ with import <stockholm/lib>;
root = "/var/download/finished";
extraConfig = ''
fancyindex on;
dav_methods PUT DELETE MKCOL COPY MOVE;
fancyindex_footer "/fancy.html";
include ${pkgs.nginx}/conf/mime.types;
include ${pkgs.writeText "extrMime" ''
types {
video/webm mkv;
}
''};
create_full_put_path on;
dav_access all:r;
'';
};
locations."/chatty" = {
proxyPass = "http://localhost:3000";
extraConfig = ''
rewrite /chatty/(.*) /$1 break;
proxy_set_header Host $host;
'';
};
locations."= /fancy.html".extraConfig = ''
alias ${pkgs.writeText "nginx_footer" ''
<div id="mydiv">
<!-- Include a header DIV with the same name as the draggable DIV, followed by "header" -->
<div id="mydivheader">Click here to move</div>
<iframe src="/chatty/index.html"></iframe>
</div>
<style>
#mydiv {
position: absolute;
z-index: 9;
background-color: #f1f1f1;
border: 1px solid #d3d3d3;
text-align: center;
}
#mydivheader {
padding: 10px;
cursor: move;
z-index: 10;
background-color: #2196F3;
color: #fff;
}
</style>
<script>
// Make the DIV element draggable:
dragElement(document.getElementById("mydiv"));
function dragElement(elmnt) {
var pos1 = 0, pos2 = 0, pos3 = 0, pos4 = 0;
if (document.getElementById(elmnt.id + "header")) {
// if present, the header is where you move the DIV from:
document.getElementById(elmnt.id + "header").onmousedown = dragMouseDown;
} else {
// otherwise, move the DIV from anywhere inside the DIV:
elmnt.onmousedown = dragMouseDown;
}
function dragMouseDown(e) {
e = e || window.event;
e.preventDefault();
// get the mouse cursor position at startup:
pos3 = e.clientX;
pos4 = e.clientY;
document.onmouseup = closeDragElement;
// call a function whenever the cursor moves:
document.onmousemove = elementDrag;
}
function elementDrag(e) {
e = e || window.event;
e.preventDefault();
// calculate the new cursor position:
pos1 = pos3 - e.clientX;
pos2 = pos4 - e.clientY;
pos3 = e.clientX;
pos4 = e.clientY;
// set the element's new position:
elmnt.style.top = (elmnt.offsetTop - pos2) + "px";
elmnt.style.left = (elmnt.offsetLeft - pos1) + "px";
}
function closeDragElement() {
// stop moving when mouse button is released:
document.onmouseup = null;
document.onmousemove = null;
}
}
</script>
''};
'';
};
};
systemd.services.bruellwuerfel = {
wantedBy = [ "multi-user.target" ];
environment = {
IRC_CHANNEL = "#flix";
IRC_NICK = "bruelli";
IRC_SERVER = "irc.r";
IRC_HISTORY_FILE = "/tmp/bruelli.history";
};
serviceConfig = {
ExecStart = "${pkgs.bruellwuerfel}/bin/bruellwuerfel";
};
};

View File

@ -71,12 +71,14 @@ in {
gitAndTools.qgit
git-preview
gnome3.dconf
iodine
lm_sensors
ncdu
nix-index
nix-review
nmap
pavucontrol
ponymix
powertop
rxvt_unicode-with-plugins
sxiv

View File

@ -19,6 +19,7 @@ with (import <stockholm/lib>);
];
services.tor.enable = true;
services.tor.client.enable = true;
krebs.iptables.tables.filter.INPUT.rules = [
{ predicate = "-i retiolum -p udp --dport 60000:61000"; target = "ACCEPT";}

View File

@ -102,9 +102,19 @@
"microsoft@lassul.us"
"stickers@lassul.us"
"nextbike@lassul.us"
"mytello@lassul.us"
"camp@lassul.us"
"urlwatch@lassul.us"
"lidl@lassul.us"
"geizhals@lassul.us"
"auschein@lassul.us"
"tleech@lassul.us"
"durstexpress@lassul.us"
];
in {
environment.systemPackages = [ pkgs.review-mail-queue ];
krebs.exim-smarthost = {
enable = true;
dkim = [

View File

@ -20,12 +20,13 @@ with import <stockholm/lib>;
}
'';
machines = [
{ ethernetAddress = "c8:3d:d4:2c:40:ae"; hostName = "tv"; ipAddress = "10.42.0.3"; }
{ ethernetAddress = "a8:a6:48:65:ce:4c"; hostName = "tv"; ipAddress = "10.42.0.3"; }
{ ethernetAddress = "3c:2a:f4:22:28:37"; hostName = "drucker"; ipAddress = "10.42.0.4"; }
{ ethernetAddress = "80:7d:3a:67:b7:01"; hostName = "s20-bett"; ipAddress = "10.42.0.10"; }
{ ethernetAddress = "80:7d:3a:67:b7:01"; hostName = "s20-tv"; ipAddress = "10.42.0.10"; }
{ ethernetAddress = "80:7d:3a:68:04:f0"; hostName = "s20-drucker"; ipAddress = "10.42.0.11"; }
{ ethernetAddress = "80:7d:3a:68:11:a5"; hostName = "s20-kueche"; ipAddress = "10.42.0.12"; }
{ ethernetAddress = "80:7d:3a:68:11:a5"; hostName = "s20-wasch"; ipAddress = "10.42.0.12"; }
{ ethernetAddress = "80:7d:3a:67:bb:69"; hostName = "s20-stereo"; ipAddress = "10.42.0.13"; }
{ ethernetAddress = "ec:b5:fa:07:78:16"; hostName = "hue-bridge"; ipAddress = "10.42.0.21"; }
{ ethernetAddress = "80:8d:b7:c5:80:dc"; hostName = "arubaAP"; ipAddress = "10.42.0.99"; }
];
};
@ -45,9 +46,6 @@ with import <stockholm/lib>;
boot.kernel.sysctl."net.ipv4.ip_forward" = 1;
krebs.iptables.tables.filter.INPUT.rules = [
{ predicate = "-i int0 -p tcp --dport 8123"; target = "ACCEPT"; } # hass
{ predicate = "-i retiolum -p tcp --dport 8123"; target = "ACCEPT"; } # hass
{ predicate = "-i int0 -p tcp --dport 1883"; target = "ACCEPT"; } # mosquitto
{ predicate = "-i int0 -p udp --dport 53"; target = "ACCEPT"; } # dns
];
krebs.iptables.tables.filter.FORWARD.rules = [
@ -62,72 +60,5 @@ with import <stockholm/lib>;
krebs.iptables.tables.nat.POSTROUTING.rules = [
{ v6 = false; predicate = "-s 10.42.0.0/24 ! -d 10.42.0.0/24"; target = "MASQUERADE"; }
];
services.home-assistant = let
tasmota_s20 = name: topic: {
platform = "mqtt";
inherit name;
state_topic = "stat/${topic}/POWER";
command_topic = "cmnd/${topic}/POWER";
payload_on = "ON";
payload_off = "OFF";
};
in {
enable = true;
package = pkgs.home-assistant.override {
#extraComponents = [
# (pkgs.fetchgit {
# url = "https://github.com/marcschumacher/dwd_pollen";
# rev = "0.1";
# sha256 = "12vldwsds27c9l15ffc6svk9mj17jhypcz736pvpmpqbsymllz2p";
# })
#];
};
config = {
homeassistant = {
name = "Home"; time_zone = "Europe/Berlin";
latitude = "48.7687";
longitude = "9.2478";
elevation = 247;
};
sun.elevation = 66;
discovery = {};
frontend = { };
mqtt = {
broker = "localhost";
port = 1883;
client_id = "home-assistant";
username = "gg23";
password = "gg23-mqtt";
keepalive = 60;
protocol = 3.1;
};
sensor = [
];
switch = [
(tasmota_s20 "Drucker Strom" "drucker")
(tasmota_s20 "Bett Licht" "bett")
(tasmota_s20 "Kueche Licht" "kueche")
];
device_tracker = [
{
platform = "luci";
}
];
};
};
services.mosquitto = {
enable = true;
host = "0.0.0.0";
allowAnonymous = false;
checkPasswords = true;
users.gg23 = {
password = "gg23-mqtt";
acl = [ "topic readwrite #" ];
};
};
environment.systemPackages = [ pkgs.mosquitto ];
}

View File

@ -20,7 +20,7 @@ with import <stockholm/lib>;
}
];
krebs.syncthing.folders."/var/lib/sync-containers".peers = [ "icarus" "skynet" "littleT" "shodan" ];
services.syncthing.declarative.folders."/var/lib/sync-containers".devices = [ "icarus" "skynet" "littleT" "shodan" ];
krebs.permown."/var/lib/sync-containers" = {
owner = "root";
group = "syncthing";

View File

@ -0,0 +1,86 @@
{ config, lib, pkgs, ... }:
{
imports = [
./zigbee.nix
./rooms/bett.nix
];
krebs.iptables.tables.filter.INPUT.rules = [
{ predicate = "-i int0 -p tcp --dport 1883"; target = "ACCEPT"; } # mosquitto
{ predicate = "-i docker0 -p tcp --dport 1883"; target = "ACCEPT"; } # mosquitto
{ predicate = "-i int0 -p tcp --dport 8123"; target = "ACCEPT"; } # hass
{ predicate = "-i retiolum -p tcp --dport 8123"; target = "ACCEPT"; } # hass
];
services.home-assistant = {
enable = true;
package = pkgs.home-assistant.override {
# extraComponents = [ "hue" ];
};
configWritable = true;
};
lass.hass.config = let
tasmota_s20 = name: topic: {
platform = "mqtt";
inherit name;
state_topic = "stat/${topic}/POWER";
command_topic = "cmnd/${topic}/POWER";
payload_on = "ON";
payload_off = "OFF";
};
in {
homeassistant = {
name = "Home";
time_zone = "Europe/Berlin";
latitude = "48.7687";
longitude = "9.2478";
elevation = 247;
};
config = {};
sun.elevation = 66;
discovery = {};
frontend = {};
mqtt = {
broker = "localhost";
port = 1883;
client_id = "home-assistant";
username = "gg23";
password = "gg23-mqtt";
keepalive = 60;
protocol = 3.1;
discovery = true;
birth_message = {
topic = "/hass/status";
payload = "online";
};
will_message = {
topic = "/hass/status";
payload = "offline";
};
};
sensor = [
];
switch = [
(tasmota_s20 "TV" "tv")
(tasmota_s20 "Drucker Strom" "drucker")
(tasmota_s20 "Waschmaschine" "wasch")
(tasmota_s20 "Stereo Anlage" "stereo")
];
mobile_app = {};
};
services.mosquitto = {
enable = true;
host = "0.0.0.0";
allowAnonymous = false;
checkPasswords = true;
users.gg23 = {
password = "gg23-mqtt";
acl = [ "topic readwrite #" ];
};
};
environment.systemPackages = [ pkgs.mosquitto ];
}

View File

@ -0,0 +1,83 @@
{
lights = {
bett = "light.0x0017880106ed3bd8_light";
essen = "light.0x0017880108327622_light";
arbeit = "light.0x0017880106ee2865_light";
nass = "light.0x00178801082e9f2f_light";
};
sensors = {
bett = "0x00178801086ac38c";
};
lightswitch = switch: light: {
automation = [
{
trigger = {
platform = "mqtt";
topic = "zigbee/${switch}";
};
condition = {
condition = "or";
conditions = [
{
condition = "template";
value_template = "{{ trigger.payload_json.action == 'on-press' }}";
}
{
condition = "template";
value_template = "{{ trigger.payload_json.action == 'up-press' }}";
}
{
condition = "and";
conditions = [
{
condition = "template";
value_template = "{{ trigger.payload_json.action == 'down-press' }}";
}
{
condition = "template";
value_template = "{{ trigger.payload_json.brightness > 30 }}";
}
];
}
];
};
action = [
{
service = "light.turn_on";
data_template = {
entity_id = light;
brightness = "{{ trigger.payload_json.brightness }}";
};
}
];
}
{
trigger = {
platform = "mqtt";
topic = "zigbee/${switch}";
};
condition = {
condition = "or";
conditions = [
{
condition = "template";
value_template = "{{ trigger.payload_json.action == 'off-press' }}";
}
{
condition = "template";
value_template = "{{ trigger.payload_json.brightness < 30 }}";
}
];
};
action = {
service = "light.turn_off";
data_template = {
entity_id = light;
};
};
}
];
};
}

View File

@ -0,0 +1,27 @@
{ lib, ... }:
with import ../lib.nix;
{
lass.hass.config = lib.lists.fold lib.recursiveUpdate {} [
{
#automation = [{
# trigger = {
# platform = "mqtt";
# topic = "zigbee/0x00178801086ac38c/action";
# payload = "on-press";
# };
# action = {
# service = "light.turn_on";
# data = {
# brightness = 150;
# rgb_color = [ 255 0 0 ];
# entity_id = [
# "light.0x0017880108327622_light"
# ];
# };
# };
#}];
}
(lightswitch sensors.bett lights.bett)
];
}

View File

@ -0,0 +1,152 @@
{config, pkgs, lib, ...}: let
zigbee2mqtt_cfg = pkgs.writeText "zigbee2mqtt.json" (builtins.toJSON {
homeassistant = true;
permit_join = true;
mqtt = {
discovery = true;
base_topic = "zigbee";
server = "mqtt://10.42.0.1";
user = "gg23";
password = "gg23-mqtt";
};
serial.port = "/dev/cc2531";
});
in {
# symlink the zigbee controller
services.udev.extraRules = ''
SUBSYSTEM=="tty", ATTRS{idVendor}=="0451", ATTRS{idProduct}=="16a8", SYMLINK+="cc2531", MODE="0660", GROUP="dailout"
'';
system.activationScripts.installZigbee = ''
install -d /var/lib/zigbee2mqtt
install ${zigbee2mqtt_cfg} /var/lib/zigbee2mqtt/configuration.yaml
'';
# hack to restart docker container on config change
systemd.services.docker-zigbee2mqtt.environment.cfg = zigbee2mqtt_cfg;
docker-containers.zigbee2mqtt = {
image = "koenkk/zigbee2mqtt";
extraDockerOptions = [
"--device=/dev/cc2531:/dev/cc2531"
];
volumes = ["/var/lib/zigbee2mqtt:/app/data"];
};
lass.hass.config = {
sensor = [
# Sensor for monitoring the bridge state
{
platform = "mqtt";
name = "Zigbee2mqtt Bridge state";
state_topic = "/zigbee/bridge/state";
icon = "mdi:router-wireless";
}
# Sensor for Showing the Zigbee2mqtt Version
{
platform = "mqtt";
name = "Zigbee2mqtt Version";
state_topic = "/zigbee/bridge/config";
value_template = "{{ value_json.version }}";
icon = "mdi:zigbee";
}
# Sensor for Showing the Coordinator Version
{
platform = "mqtt";
name = "Coordinator Version";
state_topic = "/zigbee/bridge/config";
value_template = "{{ value_json.coordinator }}";
icon = "mdi:chip";
}
];
switch = [
{
platform = "mqtt";
name = "Zigbee2mqtt Main join";
state_topic = "/zigbee/bridge/config/permit_join";
command_topic = "/zigbee/bridge/config/permit_join";
payload_on = "true";
payload_off = "false";
}
];
automation = [
{
alias = "Zigbee2mqtt Log Level";
initial_state = "on";
trigger = {
platform = "state";
entity_id = "input_select.zigbee2mqtt_log_level";
};
action = [
{
service = "mqtt.publish";
data = {
payload_template = "{{ states('input_select.zigbee2mqtt_log_level') }}";
topic = "/zigbee/bridge/config/log_level";
};
}
];
}
# Automation to start timer when enable join is turned on
{
id = "zigbee_join_enabled";
alias = "Zigbee Join Enabled";
hide_entity = "true";
trigger = {
platform = "state";
entity_id = "switch.zigbee2mqtt_main_join";
to = "on";
};
action = {
service = "timer.start";
entity_id = "timer.zigbee_permit_join";
};
}
# Automation to stop timer when switch turned off and turn off switch when timer finished
{
id = "zigbee_join_disabled";
alias = "Zigbee Join Disabled";
hide_entity = "true";
trigger = [
{
platform = "event";
event_type = "timer.finished";
event_data.entity_id = "timer.zigbee_permit_join";
}
{
platform = "state";
entity_id = "switch.zigbee2mqtt_main_join";
to = "off";
}
];
action = [
{ service = "timer.cancel";
data.entity_id = "timer.zigbee_permit_join";
}
{ service = "switch.turn_off";
entity_id = "switch.zigbee2mqtt_main_join";
}
];
}
];
input_select.zigbee2mqtt_log_level = {
name = "Zigbee2mqtt Log Level";
options = [
"debug"
"info"
"warn"
"error"
];
initial = "info";
icon = "mdi:format-list-bulleted";
};
timer.zigbee_permit_join = {
name = "Zigbee Time remaining";
duration = 120;
};
};
}

View File

@ -12,14 +12,17 @@ let
video_filename = sys.argv[1]
vid = scan_video(video_filename)
sub = download_best_subtitles([vid], {Language('eng')})[vid][0]
try:
sub = download_best_subtitles([vid], {Language('eng')})[vid][0]
filename = '/tmp/' + vid.title + '.srt'
filename = '/tmp/' + vid.title + '.srt'
with open(filename, 'wb+') as file:
file.write(sub.content)
with open(filename, 'wb+') as file:
file.write(sub.content)
print(filename)
print(filename)
except: # noqa
print("/dev/null")
'';
autosub = pkgs.writeText "autosub.lua" ''
@ -70,7 +73,6 @@ let
download()
end
mp.register_event('file-loaded', control_download)
mp.add_key_binding('S', "download_subs", download)
'';
@ -79,7 +81,6 @@ let
paths = [
(pkgs.writeDashBin "mpv" ''
exec ${pkgs.mpv}/bin/mpv --no-config --script=${autosub} "$@"
# exec ${pkgs.mpv}/bin/mpv --no-config "$@"
'')
pkgs.mpv
];

View File

@ -26,7 +26,11 @@
users.users.mainUser = {
extraGroups = [ "networkmanager" ];
packages = with pkgs; [
gnome3.gnome_keyring gnome3.dconf
gnome3.gnome_keyring
gnome3.dconf
];
};
environment.systemPackages = [
pkgs.nm-dmenu
];
}

View File

@ -9,20 +9,76 @@ let
admin-password = import <secrets/icecast-admin-pw>;
source-password = import <secrets/icecast-source-pw>;
music_dir = "/home/radio/music";
add_random = pkgs.writeDashBin "add_random" ''
${pkgs.mpc_cli}/bin/mpc add "$(${pkgs.mpc_cli}/bin/mpc ls the_playlist/music | grep '\.ogg$' | shuf -n1)"
${pkgs.mpc_cli}/bin/mpc add "$(${pkgs.findutils}/bin/find "${music_dir}/the_playlist" | grep -v '/other/' | grep '\.ogg$' | shuf -n1 | sed 's,${music_dir}/,,')"
'';
skip_track = pkgs.writeDashBin "skip_track" ''
skip_track = pkgs.writeBashBin "skip_track" ''
set -eu
${add_random}/bin/add_random
echo skipping: "$(${print_current}/bin/print_current)"
music_dir=${escapeShellArg music_dir}
current_track=$(${pkgs.mpc_cli}/bin/mpc current -f %file%)
track_infos=$(${print_current}/bin/print_current)
skip_count=$(${pkgs.attr}/bin/getfattr -n user.skip_count --only-values "$music_dir"/"$current_track" || echo 0)
if [[ "$current_track" =~ ^the_playlist/music/.* ]] && [ "$skip_count" -le 2 ]; then
skip_count=$((skip_count+1))
${pkgs.attr}/bin/setfattr -n user.skip_count -v "$skip_count" "$music_dir"/"$current_track"
echo skipping: "$track_infos" skip_count: "$skip_count"
else
mkdir -p "$music_dir"/.graveyard/
mv "$music_dir"/"$current_track" "$music_dir"/.graveyard/
echo killing: "$track_infos"
fi
${pkgs.mpc_cli}/bin/mpc -q next
'';
good_track = pkgs.writeBashBin "good_track" ''
set -eu
music_dir=${escapeShellArg music_dir}
current_track=$(${pkgs.mpc_cli}/bin/mpc current -f %file%)
track_infos=$(${print_current}/bin/print_current)
if [[ "$current_track" =~ ^the_playlist/music/.* ]]; then
${pkgs.attr}/bin/setfattr -n user.skip_count -v 0 "$music_dir"/"$current_track"
else
mv "$music_dir"/"$current_track" "$music_dir"/the_playlist/music/ || :
fi
echo good: "$track_infos"
'';
track_youtube_link = pkgs.writeDash "track_youtube_link" ''
${pkgs.mpc_cli}/bin/mpc current -f %file% \
| ${pkgs.gnused}/bin/sed 's@.*\(.\{11\}\)\.ogg@https://www.youtube.com/watch?v=\1@'
'';
print_current = pkgs.writeDashBin "print_current" ''
echo "$(${pkgs.mpc_cli}/bin/mpc current -f %file%) \
$(${pkgs.mpc_cli}/bin/mpc current -f %file% \
| ${pkgs.gnused}/bin/sed 's@.*\(.\{11\}\)\.ogg@http://www.youtube.com/watch?v=\1@')"
$(${track_youtube_link})"
'';
print_current_json = pkgs.writeDashBin "print_current_json" ''
${pkgs.jq}/bin/jq -n -c \
--arg name "$(${pkgs.mpc_cli}/bin/mpc current)" \
--arg filename "$(${pkgs.mpc_cli}/bin/mpc current -f %file%)" \
--arg youtube "$(${track_youtube_link})" '{
name: $name,
filename: $filename,
youtube: $youtube
}'
'';
write_to_irc = pkgs.writeDash "write_to_irc" ''
${pkgs.curl}/bin/curl -fsSv --unix-socket /home/radio/reaktor.sock http://z/ \
-H content-type:application/json \
-d "$(${pkgs.jq}/bin/jq -n \
--arg text "$1" '{
command:"PRIVMSG",
params:["#the_playlist",$text]
}'
)"
'';
in {
@ -48,8 +104,10 @@ in {
krebs.per-user.${name}.packages = with pkgs; [
add_random
good_track
skip_track
print_current
print_current_json
ncmpcpp
mpc_cli
];
@ -57,7 +115,7 @@ in {
services.mpd = {
enable = true;
group = "radio";
musicDirectory = "/home/radio/music";
musicDirectory = "${music_dir}";
extraConfig = ''
log_level "default"
auto_update "yes"
@ -115,6 +173,7 @@ in {
tables = {
filter.INPUT.rules = [
{ predicate = "-p tcp --dport 8000"; target = "ACCEPT"; }
{ predicate = "-i retiolum -p tcp --dport 8001"; target = "ACCEPT"; }
];
};
};
@ -164,6 +223,7 @@ in {
done | while read track; do
echo "$(date -Is)" "$track" | tee -a "$HISTORY_FILE"
echo "$(tail -$LIMIT "$HISTORY_FILE")" > "$HISTORY_FILE"
${write_to_irc} "playing: $track"
done
'';
in {
@ -175,14 +235,20 @@ in {
serviceConfig = {
ExecStart = recentlyPlayed;
User = "radio";
};
};
# allow reaktor2 to modify files
systemd.services."reaktor2-the_playlist".serviceConfig.DynamicUser = mkForce false;
krebs.reaktor2.the_playlist = {
hostname = "irc.freenode.org";
port = "6697";
useTLS = true;
nick = "the_playlist";
username = "radio";
API.listen = "unix:/home/radio/reaktor.sock";
plugins = [
{
plugin = "register";
@ -199,12 +265,19 @@ in {
workdir = config.krebs.reaktor2.the_playlist.stateDir;
hooks.PRIVMSG = [
{
#activate = "match";
pattern = "^\\s*([0-9A-Za-z._][0-9A-Za-z._-]*)(?:\\s+(.*\\S))?\\s*$";
activate = "match";
pattern = "^(?:.*\\s)?\\s*the_playlist:\\s*([0-9A-Za-z._][0-9A-Za-z._-]*)(?:\\s+(.*\\S))?\\s*$";
command = 1;
arguments = [2];
commands = {
skip.filename = "${skip_track}/bin/skip_track";
next.filename = "${skip_track}/bin/skip_track";
bad.filename = "${skip_track}/bin/skip_track";
good.filename = "${good_track}/bin/good_track";
nice.filename = "${good_track}/bin/good_track";
like.filename = "${good_track}/bin/good_track";
current.filename = "${print_current}/bin/print_current";
suggest.filename = pkgs.writeDash "suggest" ''
echo "$@" >> playlist_suggest
@ -217,6 +290,42 @@ in {
];
};
krebs.htgen.radio = {
port = 8001;
user = {
name = "radio";
};
script = ''
case "$Method $Request_URI" in
"GET /current")
printf 'HTTP/1.1 200 OK\r\n'
printf 'Connection: close\r\n'
printf '\r\n'
${print_current_json}/bin/print_current_json
exit
;;
"POST /skip")
printf 'HTTP/1.1 200 OK\r\n'
printf 'Connection: close\r\n'
printf '\r\n'
msg=$(${skip_track}/bin/skip_track)
${write_to_irc} "$msg"
echo "$msg"
exit
;;
"POST /good")
printf 'HTTP/1.1 200 OK\r\n'
printf 'Connection: close\r\n'
printf '\r\n'
msg=$(${good_track}/bin/good_track)
${write_to_irc} "$msg"
echo "$msg"
exit
;;
esac
'';
};
services.nginx = {
enable = true;
virtualHosts."radio.lassul.us" = {
@ -258,9 +367,9 @@ in {
alias ${html};
'';
};
krebs.syncthing.folders."the_playlist" = {
services.syncthing.declarative.folders."the_playlist" = {
path = "/home/radio/music/the_playlist";
peers = [ "mors" "phone" "prism" "xerxes" ];
devices = [ "mors" "phone" "prism" "xerxes" ];
};
krebs.permown."/home/radio/music/the_playlist" = {
owner = "radio";

View File

@ -1,7 +1,7 @@
{
krebs.syncthing.folders.decsync = {
services.syncthing.declarative.folders.decsync = {
path = "/home/lass/decsync";
peers = [ "mors" "blue" "green" "phone" ];
devices = [ "mors" "blue" "green" "phone" ];
};
krebs.permown."/home/lass/decsync" = {
owner = "lass";

View File

@ -1,5 +1,5 @@
{
krebs.syncthing.folders."/home/lass/.weechat".peers = [ "blue" "green" "mors" ];
services.syncthing.declarative.folders."/home/lass/.weechat".devices = [ "blue" "green" "mors" ];
krebs.permown."/home/lass/.weechat" = {
owner = "lass";
group = "syncthing";

View File

@ -7,18 +7,20 @@ in {
enable = true;
group = "syncthing";
configDir = "/var/lib/syncthing";
declarative = {
key = toString <secrets/syncthing.key>;
cert = toString <secrets/syncthing.cert>;
devices = mk_peers all_peers;
folders."/home/lass/sync" = {
devices = attrNames (filterAttrs (n: v: n != "phone") own_peers);
# ignorePerms = false;
};
};
};
krebs.iptables.tables.filter.INPUT.rules = [
{ predicate = "-p tcp --dport 22000"; target = "ACCEPT";}
{ predicate = "-p udp --dport 21027"; target = "ACCEPT";}
];
krebs.syncthing = {
enable = true;
cert = toString <secrets/syncthing.cert>;
key = toString <secrets/syncthing.key>;
peers = mk_peers all_peers;
folders."/home/lass/sync".peers = attrNames (filterAttrs (n: v: n != "phone") own_peers);
};
system.activationScripts.syncthing-home = ''
${pkgs.coreutils}/bin/chmod a+x /home/lass

View File

@ -270,14 +270,14 @@ in {
};
boot.kernel.sysctl."fs.inotify.max_user_watches" = "1048576";
krebs.syncthing.folders = {
services.syncthing.declarative.folders = {
domsen-backups = {
path = "/backups/domsen";
peers = [ "domsen-backup" ];
devices = [ "domsen-backup" ];
};
domsen-backup-srv-http = {
path = "/srv/http";
peers = [ "domsen-backup" ];
devices = [ "domsen-backup" ];
};
};

View File

@ -4,6 +4,7 @@ _:
./dnsmasq.nix
./ejabberd
./folderPerms.nix
./hass.nix
./hosts.nix
./mysql-backup.nix
./news.nix

34
lass/3modules/hass.nix Normal file
View File

@ -0,0 +1,34 @@
{ config, lib, pkgs, ... }:
with import <stockholm/lib>;
let
cfg = config.lass.hass;
in {
options.lass.hass = {
config = mkOption {
default = {};
type = with lib.types; let
valueType = nullOr (oneOf [
bool
int
float
str
(attrsOf valueType)
(listOf valueType)
]) // {
description = "Yaml value";
emptyValue.value = {};
};
in valueType;
};
};
config =
assert versionOlder version "20.09";
mkIf (cfg.config != {})
{
services.home-assistant.config = cfg.config;
};
}

View File

@ -0,0 +1,26 @@
{ yarn2nix-moretea, fetchFromGitHub, nodePackages, nodejs }: let
#src = ~/src/bruellwuerfel;
src = fetchFromGitHub {
owner = "krebs";
repo = "bruellwuerfel";
rev = "57e20e630f732ce4e15b495ec5f9bf72a121b959";
sha256 = "08zwwl24sq21r497a03lqpy2x10az8frrsh6d38xm92snd1yf85b";
};
in yarn2nix-moretea.mkYarnModules rec {
pname = "bruellwuerfel";
version = "1.0";
name = "${pname}-${version}";
packageJSON = "${src}/package.json";
yarnLock = "${src}/yarn.lock";
postBuild = ''
cp -r ${src}/{src,tsconfig.json} $out/
cd $out
${nodePackages.typescript}/bin/tsc || :
mkdir -p $out/bin
echo '#!/bin/sh' > $out/bin/bruellwuerfel
echo "export NODE_PATH=$out/dist" >> $out/bin/bruellwuerfel
echo "${nodejs}/bin/node $out/dist/index.js" >> $out/bin/bruellwuerfel
chmod +x $out/bin/bruellwuerfel
'';
}

View File

@ -1,16 +1,10 @@
{ config, pkgs, ... }:
pkgs.writeHaskellPackage "xmonad-lass" {
executables.xmonad = {
extra-depends = [
"containers"
"extra"
"unix"
"X11"
"xmonad"
"xmonad-contrib"
"xmonad-stockholm"
];
text = /* haskell */ ''
pkgs.writers.writeHaskellBin "xmonad" {
libraries = with pkgs.haskellPackages; [
extra
xmonad-stockholm
];
} /* haskell */ ''
{-# LANGUAGE LambdaCase #-}
@ -150,10 +144,7 @@ myKeyMap =
, ("M4-<F2>", windows copyToAll)
, ("M4-<F4>", spawn "${pkgs.writeDash "nm-dmenu" ''
export PATH=$PATH:${pkgs.dmenu}/bin:${pkgs.networkmanagerapplet}/bin
exec ${pkgs.networkmanager_dmenu}/bin/networkmanager_dmenu "$@"
''}")
, ("M4-<F4>", spawn "${pkgs.nm-dmenu}/bin/nm-dmenu")
, ("M4-<Insert>", spawn "${pkgs.writeDash "paste" ''
${pkgs.coreutils}/bin/sleep 0.1
${pkgs.xclip}/bin/xclip -o | ${pkgs.xdotool}/bin/xdotool type -f -
@ -223,6 +214,4 @@ gridConfig = def
allWorkspaceNames :: W.StackSet i l a sid sd -> X [i]
allWorkspaceNames ws =
return $ map W.tag (W.hidden ws ++ (map W.workspace $ W.visible ws)) ++ [W.tag $ W.workspace $ W.current ws]
'';
};
}
''

View File

@ -18,6 +18,9 @@
ζ | zeta
(°° | table flip
() | why woot
(___) | gloom I see you
| sad
(\/) (°,,,,°) (\/) | krebs
'';
in

View File

@ -32,14 +32,24 @@ pkgs.writeDashBin "fzfmenu" ''
done
INPUT=$(${pkgs.coreutils}/bin/cat)
OUTPUT="$(${pkgs.coreutils}/bin/mktemp)"
${pkgs.rxvt_unicode}/bin/urxvt \
-name fzfmenu -title fzfmenu \
-e ${pkgs.dash}/bin/dash -c \
"echo \"$INPUT\" | ${pkgs.fzf}/bin/fzf \
--history=/dev/null \
--print-query \
--prompt=\"$PROMPT\" \
> \"$OUTPUT\"" 2>/dev/null
if [ -z ''${TERM+x} ]; then #check if we can print fzf in the shell
${pkgs.rxvt_unicode}/bin/urxvt \
-name fzfmenu -title fzfmenu \
-e ${pkgs.dash}/bin/dash -c \
"echo \"$INPUT\" | ${pkgs.fzf}/bin/fzf \
--history=/dev/null \
--print-query \
--prompt=\"$PROMPT\" \
--reverse \
> \"$OUTPUT\"" 2>/dev/null
else
echo "$INPUT" | ${pkgs.fzf}/bin/fzf \
--history=/dev/null \
--print-query \
--prompt="$PROMPT" \
--reverse \
> "$OUTPUT"
fi
${pkgs.coreutils}/bin/tail -1 "$OUTPUT"
${pkgs.coreutils}/bin/rm "$OUTPUT"
''

View File

@ -0,0 +1,6 @@
{ pkgs, ... }:
pkgs.writeDashBin "nm-dmenu" ''
export PATH=$PATH:${pkgs.dmenu}/bin:${pkgs.networkmanagerapplet}/bin
exec ${pkgs.networkmanager_dmenu}/bin/networkmanager_dmenu "$@"
''

View File

@ -0,0 +1,39 @@
{ pkgs }: let
review = pkgs.writers.writeBash "review-mail" ''
mail="$1"
${pkgs.exim}/bin/exim -Mvc "$mail" | grep -E 'Subject:|To:'
${pkgs.exim}/bin/exim -Mvl "$mail"
while :; do
read -p 'delete?' key
case "$key" in
v*)
${pkgs.exim}/bin/exim -Mvc "$mail"
;;
d*)
${pkgs.exim}/bin/exim -Mrm "$mail"
break
;;
r*)
${pkgs.exim}/bin/exim -Mt "$mail"
break
;;
n*)
break
;;
esac
done
echo '-------------------'
echo '-------------------'
echo '-------------------'
echo '-------------------'
echo '-------------------'
'';
in pkgs.writers.writeBashBin "review-mail" ''
for mail in $(${pkgs.exim}/bin/exim -bp \
| ${pkgs.gnugrep}/bin/grep frozen \
| ${pkgs.gawk}/bin/awk '{print $3}'); do
${review} "$mail"
done
''

View File

@ -49,6 +49,8 @@ let
indent = replaceChars ["\n"] ["\n "];
stripAttr = converge (filterAttrsRecursive (n: v: v != {} && v != null));
mapNixDir = f: x: {
list = foldl' mergeAttrs {} (map (mapNixDir1 f) x);
path = mapNixDir1 f x;

View File

@ -12,6 +12,9 @@ pactl = findExecutable "pactl"
passmenu :: FilePath
passmenu = findExecutable "passmenu"
pavucontrol :: FilePath
pavucontrol = findExecutable "pavucontrol"
slock :: FilePath
slock = findExecutable "slock"

View File

@ -160,6 +160,7 @@ myKeys conf = Map.fromList $
, ((0, xF86XK_AudioLowerVolume), audioLowerVolume)
, ((0, xF86XK_AudioRaiseVolume), audioRaiseVolume)
, ((0, xF86XK_AudioMute), audioMute)
, ((_4, xF86XK_AudioMute), pavucontrol [])
, ((_4, xK_Prior), forkFile Paths.xcalib ["-invert", "-alter"] Nothing)
]
@ -175,6 +176,8 @@ myKeys conf = Map.fromList $
_4SM = _4 .|. _S .|. _M
pactl args = forkFile Paths.pactl args Nothing
pavucontrol args = forkFile Paths.pavucontrol args Nothing
audioLowerVolume = pactl ["--", "set-sink-volume", "@DEFAULT_SINK@", "-5%"]
audioRaiseVolume = pactl ["--", "set-sink-volume", "@DEFAULT_SINK@", "+5%"]
audioMute = pactl ["--", "set-sink-mute", "@DEFAULT_SINK@", "toggle"]