feature/hass
Ingolf Wagner 2019-10-24 02:20:38 +02:00
commit 54bab918d7
Signed by: palo
GPG Key ID: 76BF5F1928B9618B
260 changed files with 18544 additions and 0 deletions

7
.channelStable.json Normal file
View File

@ -0,0 +1,7 @@
{
"url": "https://github.com/NixOS/nixpkgs-channels.git",
"rev": "0e0ee084d6dfc83b5b67b6cbcefe43664114808d",
"date": "2019-10-07T15:48:50+02:00",
"sha256": "1qk0ag4ihfjh9ay28hc9zf9vnrdw096driirv62picyn30j9y0l3",
"fetchSubmodules": false
}

7
.channelUnstable.json Normal file
View File

@ -0,0 +1,7 @@
{
"url": "https://github.com/NixOS/nixpkgs-channels.git",
"rev": "2436c27541b2f52deea3a4c1691216a02152e729",
"date": "2019-09-25T08:02:27+02:00",
"sha256": "0p98dwy3rbvdp6np596sfqnwlra11pif3rbdh02pwdyjmdvkmbvd",
"fetchSubmodules": false
}

7
.gitignore vendored Normal file
View File

@ -0,0 +1,7 @@
*.swp
result
result-*
.history
TAGS
*.tf.json

6
.gitmodules vendored Normal file
View File

@ -0,0 +1,6 @@
[submodule "assets/video-browser"]
path = assets/video-browser
url = ssh://gogs@git.ingolf-wagner.de:443/palo/video-browser.git
[submodule "wetten"]
path = wetten
url = ssh://gogs@git.ingolf-wagner.de:443/palo/wetten.git

7
.krops.json Normal file
View File

@ -0,0 +1,7 @@
{
"url": "https://git.ingolf-wagner.de/krebs/krops.git",
"rev": "2e93a93ac264a480b427acc2684993476732539d",
"date": "2018-09-19T19:57:26+02:00",
"sha256": "1s6b2cs60xa270ynhr32qj1rcy3prvf9pidap0qbbvgg008iafxk",
"fetchSubmodules": false
}

7
.nix-writers.json Normal file
View File

@ -0,0 +1,7 @@
{
"url": "https://cgit.krebsco.de/nix-writers/",
"rev": "fc8a3802a0777a5f43a9a2fe0f5848ecaeb555a1",
"date": "2018-10-27T14:45:48+02:00",
"sha256": "1iy207rcbz9nv9bf64025ypy38x8mwzl6snbmbrq347h6vvs0ksc",
"fetchSubmodules": false
}

7
.nixos-generators.json Normal file
View File

@ -0,0 +1,7 @@
{
"url": "https://github.com/nix-community/nixos-generators.git",
"rev": "ef1e4480cf8af45cfdeac597b2f1b1af33923e93",
"date": "2019-01-18T10:41:01+01:00",
"sha256": "0ymzp4pmpkjjjg5h8d45gv8avy4wh1dj0v238i2cz3jp3j489ik9",
"fetchSubmodules": false
}

35
README.md Normal file
View File

@ -0,0 +1,35 @@
# My NixOS configuration
## Folder Structure
### configs
This should container system specific configurations
### system
Holds system type information like `server` and `desktop`.
### modules
This should container scripts that can be copied across different sources.
### pkgs
My overlay is in here.
### assets
assets, like scripts which I dont want to write in nix-lang.
### terranix
some terranix scripts
### library
some nix-lang functions and tools I use.
### images
some images I use and build via nixos-generators.

105
assets/jack.sh Executable file
View File

@ -0,0 +1,105 @@
set -e
defaultDevice=PCH
start_jack(){
internal_device_number=-1
komplete_device_number=$(aplay -l | grep Vestax | cut -d":" -f1 | cut -d" " -f2)
babyface_device_number=$(aplay -l | grep Babyface | cut -d":" -f1 | cut -d" " -f2)
cmedia_device_number=$(aplay -l | grep C-Media | cut -d":" -f1 | cut -d" " -f2)
h2n_device_number=$(aplay -l | grep H2n | cut -d":" -f1 | cut -d" " -f2)
# this should be more readable some day
if [[ $babyface_device_number == "" ]]; then
if [[ $komplete_device_number == "" ]]; then
if [[ $cmedia_device_number == "" ]]; then
if [[ $h2n_device_number == "" ]]; then
echo "use : default device"
device_number=$internal_device_number
else
echo "use : h2n"
device_number=$h2n_device_number
fi
else
echo "use : c-media"
device_number=$cmedia_device_number
fi
else
echo "use : komplete"
device_number=$komplete_device_number
fi
else
echo "use : babyface"
device_number=$babyface_device_number
fi
# device parameter configuration
# ==============================
#
# to find configuration options do
# jack_control dp
if [[ $device_number -eq -1 ]]
then
# we use alsa in reality, but pulse opens up all the pulse
# sink and source stuff
# jack_control ds pulse # not working for some reason
jack_control ds alsa
jack_control dps device hw:$defaultDevice
else
jack_control ds alsa
jack_control dps device hw:$device_number # use usb card
fi
jack_control dps duplex True # record and playback ports
jack_control dps hwmon False # no hardware monitoring
jack_control dps rate 48000 # use cd sample rate
# nperiods are the splitup of the
# sound-ring-buffer. 2 are ok for internal cards
# but for usb you should use 3 because
# you can have to write in junks to the card
# so there is one backup slice in the middle
if [[ $internal_device_number -ne -1 ]]
then
jack_control dps nperiods 3
fi
# engine parameter configuration
# ==============================
#
# to find configuration options do
# jack_control ep
jack_control eps sync True
# realtime kernel
# set True for using a realtime kernel
jack_control eps realtime False
# set priority if realtime kernel is set True
# jack_control eps realtime-priority 10
jack_control start
}
stop_jack(){
jack_control exit
}
status_jack() {
jack_control dp
jack_control ep
jack_control status
}
case $1 in
start) start_jack
;;
stop) stop_jack
;;
restart) stop_jack ; start_jack
;;
*) status_jack
;;
esac

56
assets/shrink_exports Executable file
View File

@ -0,0 +1,56 @@
#!/usr/bin/env bash
set -e
PROJECTS_FOLDER=~/music-projects/Rendered-Projects
# file separator (needed to handle files with spaces)
IFS="
"
function info_log(){
echo -n ">>> [ "
echo -n $@
echo " ]"
}
function run_ffmpeg(){
local input=$1
local output=$2
info_log "ffmpeg : ${output}"
ffmpeg \
-i "${input}" \
-f mp3 \
-codec:a libmp3lame \
-qscale:a 5 \
-ar 44100 \
-loglevel error \
-af loudnorm \
"${output}"
}
function delete(){
local input=$1
if [[ -e "${input}" ]]
then
info_log "delete : ${input}"
rm "${input}"
fi
}
for file in `ls ${PROJECTS_FOLDER} | grep wav$`
do
filename=`basename ${file} .wav`
mp3="${filename}.mp3"
info_log ${filename}
delete "${PROJECTS_FOLDER}/${mp3}"
run_ffmpeg "${PROJECTS_FOLDER}/${file}" "${PROJECTS_FOLDER}/${mp3}"
delete "${PROJECTS_FOLDER}/${file}"
done

3
assets/sprueche-axel Normal file
View File

@ -0,0 +1,3 @@
"Fernsehen ist für mich der Elektro-Jude" - Dr Axel Stoll
"Der Zellkern ist gleich pures Licht" - Dr Axel Stoll
"Die Sonne ist Kalt!" - Dr Axel Stoll

18
assets/sprueche-siw Normal file
View File

@ -0,0 +1,18 @@
"Also Attracktiv oder net, ich seh hier immer noch am Besten aus" - Reiker
"Hör mal auf dich selber zu bemitleiden, sonst baft das aber echt jetzt! Dummer Lutscher" - Käpten Pika
"Komm Junge is besser du gibs dat jetzt zu, dann haste wenigsten noch ein paar Jahre wat von deinen Zähnen" - Käpten Pika
"Ich sauf doch net mit euch Pennern, echt Ey" - Käpten Pika
"Ja toll dann hab ich ja schon wieder verloren" - Deiter
"Komisch! Mein Vater heißt auch Vater, aber sieht ganz anders aus!" - Reiker
"Sag noch einmal Junge, Junge!" - Käpten Pika
"Häää? Worte, was sind Worte?" - Reiker
"Ich hau dir gleich die Zähne aus deiner fiesen Schnauze!" - Käpten Pika
"Ihr glaubt wohl ich kann keine schlauen Sachen sagen, wa? Schlaue Sachen!!" - Reiker
"Jetzt... also ich raff das jetzt echt net. Ist das so kompliziert?" - Reiker
"Dat is hier die Molekularsymplexion über trivial-komplexive Plasmakonvergenzen, wie? Wat?" - Jordi
"Äh, äh, Junge? Ey, Junge, echt jetz! Weißte?" - Käpten Pika
"Deine Dummheit unterscheidet meinen Datentransfer" - Computer
"Ähh, komisch mein Vadder sieht ganz anders aus, obwohl der auch Vadder heißt." - Reiker
"Aaaaaah, ich kann nimmer" - Reiker
"Also ich hab keine Gummipuppe. Nur Gummibärchen." - Reiker
"Richtig heisser, kochend heisser Kaffee" - Käpten Pika

1
assets/ssh/card_rsa.pub Normal file
View File

@ -0,0 +1 @@
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQC6uza62+Go9sBFs3XZE2OkugBv9PJ7Yv8ebCskE5WYPcahMZIKkQw+zkGI8EGzOPJhQEv2xk+XBf2VOzj0Fto4nh8X5+Llb1nM+YxQPk1SVlwbNAlhh24L1w2vKtBtMy277MF4EP+caGceYP6gki5+DzlPUSdFSAEFFWgN1WPkiyUii15Xi3QuCMR8F18dbwVUYbT11vwNhdiAXWphrQG+yPguALBGR+21JM6fffOln3BhoDUp2poVc5Qe2EBuUbRUV3/fOU4HwWVKZ7KCFvLZBSVFutXCj5HuNWJ5T3RuuxJSmY5lYuFZx9gD+n+DAEJt30iXWcaJlmUqQB5awcB1S2d9pJ141V4vjiCMKUJHIdspFrI23rFNYD9k2ZXDA8VOnQE33BzmgF9xOVh6qr4G0oEpsNqJoKybVTUeSyl4+ifzdQANouvySgLJV/pcqaxX1srSDIUlcM2vDMWAs3ryCa0aAlmAVZIHgRhh6wa+IXW8gIYt+5biPWUuihJ4zGBEwkyVXXf2xsecMWCAGPWPDL0/fBfY9krNfC5M2sqxey2ShFIq+R/wMdaI7yVjUCF2QIUNiIdFbJL6bDrDyHnEXJJN+rAo23jUoTZZRv7Jq3DB/A5H7a73VCcblZyUmwMSlpg3wos7pdw5Ctta3zQPoxoAKGS1uZ+yTeZbPMmdbw== cardno:000611343142

View File

@ -0,0 +1,14 @@
Ed25519PublicKey = LnE+w6ZfNCky4Kad3TBxpFKRJ2PJshkSpW6mC3pcsPI
-----BEGIN RSA PUBLIC KEY-----
MIICCgKCAgEAmAyz71GoQq2Mn4XeUVcN9yfgxeWT57li7i6Te9lq7OVAXQ+CBtD3
puTMrW3/LXOIS678E2iMYPmdQzMZLmADi8+ZrXOqX98uceNv5bPrTJF0z/RA9Tif
kfh78GcJCGHmZz+GGWu1ExtSa5ekBdamEtehW6vAGbrPM6Umu9B2UCn8zaSx+RGe
Y7Z81wO21+ywUorMPTbHeuPYZW+Z8L+QKHO9NdYhzZ9zMPeVMi0x/mwIZqXJ57Wz
57nx0rrPh+e+5cj3Jh+i4HC76mxPGCyCdvf+60d7W87UZxPqRiTLt2SwgltEKf56
jBsVeOb5Fjzb6LcNGWfF8zNh0w6rAQsG4W7l93VlerTd46GtG2XW42JkGhuKb8JJ
L1olPUmbcDbxlQGGUNaI7thAzubszAzinqyat3oU8NjgDJJIueHLmo752RW+yHUY
giyRSBYtDRM9cE3s848WsToO5BtjXLkg/rC4WIWX2MNJFsAZXzfHWDmae+ajpoVy
Gl6tGYbLhjd8KtSWB9kB0OWsV56f4KmWeRxHwTgylMO30l6v+XRdnoRUAp9wj8dV
c6HJHnn5b2q4dk+qwWOYgwvpRFnSixbCCT4PoedEU9xVOzLmzxRtGmkzPsOXEOj5
6r4Jvk0jw2LTkhEVX1CPblTrGpms9NO02SXNHkF/Akw7PGuJu+w3HZUCAwEAAQ==
-----END RSA PUBLIC KEY-----

View File

@ -0,0 +1,14 @@
Ed25519PublicKey = 9JI8y56NWiKMRS6g/k2H3VgTEw0q+8UEDDJdiCjOl8O
-----BEGIN RSA PUBLIC KEY-----
MIICCgKCAgEA4Ff6XRvf83XSuWUkb70Yz+cWo1/dq4LBh5ZG7SJypdIXYnWQpQJc
sLRfAS6nJZ6VixNADx7A03c8TdADVaAgl591rLd4CSzM22EgaOFstU2VO/MfMKHf
v+WUQsrTE6CQ48SW+MDbSZZ7M7FRa/A6hwqZc5qygxdG/tgTei9pmTfqW+ZdQBWl
IeCCINiNSA/fD+FjWXslZIFRZ5sQ7AYZJgL2nFAueY+cKtRZy3tcDL1v6mhDdIrE
h8JjEUiayQDGnWmBlflLqE3ODqEsEKoL6W7epqK6PcwvZQxSNwrZe/wzH3oTC43m
Yg7TQGr0v3SnSziXv3cJvcHfwr9+huo37wTbUJNmozGpI8nLszfUTEIfhbu2ODQv
R2iM7FJcE4wV48y9aybEnESKA0vsjgI23RIQfxkN0oii7L6NAZVHgl/JJBOtCMXf
V5uXAdOtkv9UvfofrrV0uahncvbz5efPTSPF8fS5EiwzWfDUW6KHrp/9+gDcnirn
H8HvmmNVeOGWA1xlrKgi8kiBHv5BxCXfurD0aD6ZIlxdLjJCvGfnLnJZ6gr//GAf
1BJJVei98uZzihNe4VbRF6Iaphns1KezsdygMsEV9gDIJw3IIqTukcUK7AcBXhb4
IJ792j2iRwUOyiAcUYLeVYzAt3xFN6wPNcC/Opdo6TVbdMZu2uS1ZN8CAwEAAQ==
-----END RSA PUBLIC KEY-----

View File

@ -0,0 +1,14 @@
Ed25519PublicKey = kc1SACqsoYjk5GimZfP+eszfJmUzZkMQhWeW42UKjfL
-----BEGIN RSA PUBLIC KEY-----
MIICCgKCAgEA2ACttoosnRZ99o+OyMrxBdUWPqsT5btzSIQ5dU1XWqGjO4nRchCE
8tO0b/4jqVgJVTRZVIUJQESZRlSmclsCAjdM8tsGj74CJrm7tBvgbBn2IObSs5+4
oJWe57VsQaeHPuI2JZuGqv8Z3Esw+B07bQS5VTaC1ISo7vnLG/q5XLCbKHB9JZc/
ztYbk4bEQHwbulfoPjD9FY3heLnTzqPw9Xr3ixao5gbAXfWNJM+iCluMq+Q2g1BD
ozSnyYvaGLQ6h4yksDp+xuK8YCqiRj174EkXySI8Jee1CBMuI8ciX/5Q7yzvzscQ
ZQ/MLVdx3MRW+VeT0ctaRzoA9E09ILqPe+56DjpsKzt4Ne8qeMG5HdpzO9UdNzTu
MuibsCL7CJy5Ytl38PK+LAXHQr3Os1Z4OHjeTZ38vTAZcOUJZEkl6w9nO1XjcyBL
rIaG+20Nx0ZU79MlJZFiG7ovlUiDfIEKNygng8v/yoTMaqMYLxQZ/leQwLMNLujo
sku8+oV4Jvx4SyUjuAS6jgG9CnejLCnHP/yyDGdaMQSzmlzYXacLMfnPZE3r7bj1
EjA6yQbkPixm7xLCyMm5u2leWtqtbg1oRA6Mw3UyYkNy3hiTU+jTvztEI3SCliDH
yjGlESH4/edryKjLNjmYP77VFbM9ZSQ+QGlbMGPvjcn6XCdJGdxm3PUCAwEAAQ==
-----END RSA PUBLIC KEY-----

View File

@ -0,0 +1,14 @@
Ed25519PublicKey = ZK9iznseTpMqjaMgDJ7MdjYaq62QlEOFquLfVxlLpFK
-----BEGIN RSA PUBLIC KEY-----
MIICCgKCAgEAzBU8x9aB7F3sPJlcg9avJiSrsAoTHsMkfk6uRKFVjUjuNJgb3rjW
gyQ7krftLAyxLkTYJzpD+4D+qWiudEgju7W+BU65/hudMIvBmbRYqXmcQlD9B9Pv
0bVAazHJ80wN8GJD060Wq6XTtkrtAJhPmQSyMt0xU4WmWw/39QBX9rWtOTy75813
qrfuv1I11YcVQ3jegPLUIzlZqz6LeouCXiP7IRIa+WUXIwAdAYtO/RJC+tty6zyI
BXNd0Mkvpf0Qaw5joQJRXkdb1sWHOZYh75JW1QWqFMWCclkGG7/Dve4KzuO9N5XZ
ZMs/MCtDkJQpweNDT3aaiqZa8Oj29OXs4HR4FFrvYkY+qqmKCUqS70FYLo45uNx1
sRb7GKX8/dsPyOGHfXDuFTSXsKLh9gNLMlF/kuTQ2yJMfeMKdC5jDClL145Fm0ux
akH/PWSS9DENxSu0GH1sTQnLyhc4mVzOehu1XfR9EALjYY0BNBUir7aAaiLTCbq9
LKwMaF/D467W3j3Zp5xEAsf8xYC2CyMl1Df43zxcxLY+3K8/kUM2rkU7ocl2VT3o
7yNC+JqQz41n4SDOXBZc6cfxUXj2MqqEw9Ywgs+aXZiSCaVOulhyXj0TSE1mX1NI
woDHEzyx7q4AryQOWQsLq5JimI0v2/xN2yz+cNXoetDypjEWnws4e/ECAwEAAQ==
-----END RSA PUBLIC KEY-----

View File

@ -0,0 +1,14 @@
Ed25519PublicKey = Hm+YwSe6XiRNQD4HfJPgTB8UFVMyVi0vy+3ofMnW6jD
-----BEGIN RSA PUBLIC KEY-----
MIICCgKCAgEAu7Ajx9+mEaDK/ASZ5hoVj3X3IkWl+8MAhmj7dwnhqc4YrPrvwKE4
cOnVcEUp4K4pyIHUG8zhsesstfpu/0owLQaz8Cekr4CyQWsjDfi7K/QiAN+v2O2m
DQOjrYzDvRyBa20A2MnO1kZU/aFHE9qcIHefZhQUZyv97j+QcsE/FDuIH/RAua6/
p+br2tfecePGH6f0fMk8dp+YbxcjjVyhJkjyaYF2r+n+YflDl5y3ngxUFJ0UnNE0
RfYJf2NE1wzt4rIdnYobFP3vifDIeYj6M0LGHnURPsT6zP+zStZ81MYZKrNlTJ37
sbZhorVmO6x46xEWaDUd7UqcKJBpb7u8iSAE4S3tHLFRxBs60dPS+3UEraiTvTHr
FvWTq1Q+t/FivTxXEkVt74N5auOKbT5AAkztak21Izx6enspdx6da2aLuJD5I0OU
3F4kd8lW5PqEZubkYziDwcVoNsx88hQzHi5l2aRdzY57o82+ltWw4xXmAFR2o605
SwVJ4AUmORHuIoDYSR+UgbtKHguxVaTLVggdfvHzlDQ1VERwEU58awMwPLU1k+jP
3QW7ehPLKRN+StB6LBlnmRD1ltkaPY5iy+NMXj17hJx0trpz3qoCuv+5TRvsGvQ7
Je/G7c6suIGd4HbA9TvCinW6/JLbJQlDiG7MD2oCOPS1pdayUuB9Jw0CAwEAAQ==
-----END RSA PUBLIC KEY-----

View File

@ -0,0 +1,14 @@
Ed25519PublicKey = sPs48jzCdtTv0Viy2Of3HlXipfxH5Y8bA+KYVkOrSiK
-----BEGIN RSA PUBLIC KEY-----
MIICCgKCAgEA01HJ49zxmnixWC9YMP0c3UFxZc4Hl5UK9nJvhMRBOuxm75kpzZsz
3v6mSy1YrVE9rrGXYjZ76wKrRhchMpvrMKKD8/DRjVqTkuFwtGgUEigzpSFoSLtC
u2Wis7Z6GW3nLgAS79NU9IUUEoeevND1zzglDb0HdERuiImiZVg3I+VXLyA31X3L
Z/B7T4QLmZGIRvFw0y1TawMjFMJZmDBtzMqfO7behkms2O1ORAciGhGxmZ9gd7yk
n/NKCpSSzeC6sJ28i33LRrWF3hRUXAEJFgq8YRxm6mjRoPLsJVsw2S98DvTcxmjN
eyVnqPVQi7JuKrOQsewQvwV2KiqI9ibEYH1zZNXwy+l05b3QSaAcyRtDpwRW7FCY
H4B3S0vjte75D4bEuYTFgT3wCzlAjdB7fPZ4jyZXdrP8G3IfbMmgsdECz5uIMwam
UaSZISlHkSJv+erA8TMJLBnqAO7ERKYI7PRIDdIun0VtX2QjRJpWIdVpxEcL4fZU
w6gzX8lOQe5NnoH/MFUfU0LyBuUH1k6WX7xdwrynUVS087vwaQN+H/VTp0QSX6PQ
oCLYPCGKS2B/St954uaPanzeG7QZQpWbvttaFVmUSkilx78xqqu3zDm9pSofFKCX
08TGlluy8JAwUqAxekQVKey2PdLmKjlMCcoUeNYbJybGplc9gv2hYhsCAwEAAQ==
-----END RSA PUBLIC KEY-----

View File

@ -0,0 +1,14 @@
Ed25519PublicKey = r6mRDc814z2YtyG9ev/XXV2SgquqWR8n53V13xNXb7O
-----BEGIN RSA PUBLIC KEY-----
MIICCgKCAgEA7/bur2JIXzNrsgjQ7kfoaLUVCC9S7HNNdDrlnSdum0sWvN9urdxS
1OfzqG+kjDhQ0sS4fEeYyLMU8W3/aHkSbMjfKBiZS70bg5yHRepUEPZNqDqR3+rO
LTAGWMi/IQQQmnfcN5SjaNY/ZyXoaPd1emlpV2UXBvXo/bQTl+pmOt7AIAh7Z7M6
X5KAwU23kUwrfn/7zFCw98euNEPcCKpdF5oD4+G+S0PGfFvBmE6Xoi2blM1rcjJ4
39IGVCsKAlW1Vg48yj7FypSSjaFvIW+kyRcNNTEZ4V5p50Vm7DfylfW96NqAOeuz
2aSVaLhvmu8fU9z+g95MdGZOJYd57jFt76GbkwcLCF8KBCP9NhMfOQu0i1glk+AP
CcJcDa/Oj7lLQVB2+holJhw5fkHH2Yi+L+UsjIF0iLiOSTjGJp4yRT9Al9pgMCj2
O1JUMYxQ490mSFHBomNv1fq+f5VJnytEwAkJH6AgH+RIcAC5/r+sowfLv+Gy0ga8
jKG6t9d/x6lRNv0x5sUhYkiUD9Naq0NncaZz1GtkBAyu+hUZx2+zg3r8He4XoiXx
zWAQEgcW3X1/9VC7IBvaK9cdLG5pbeGCBaDv8S0Ue332mM0XNDlffjdC7Sg9f/TG
YV8MHpR3RwwUqdi6WFPQqVz5Hv1pE02v/Uw6tby1UgAnzskrufPh+m8CAwEAAQ==
-----END RSA PUBLIC KEY-----

View File

@ -0,0 +1,10 @@
#!/usr/bin/env bash
# collect all network configurations and save them in the store
sudo ls /etc/NetworkManager/system-connections \
| while read file
do
sudo cat /etc/NetworkManager/system-connections/$file \
| pass insert -m desktop/network-manager/system-connections/$file
done

View File

@ -0,0 +1,64 @@
{ config, pkgs, lib, ... }:
{
imports = [
<system/desktop>
./hardware-configuration.nix
./encfs.nix
#./samba.nix
./syncthing.nix
./tinc.nix
#./wifi-access-point.nix
];
custom.samba-share.folders = {
enable = false;
public = "/home/palo/movies";
};
system.custom.wifi.interfaces = ["wlp3s0"];
networking.hostName = "pepe";
security.wrappers = {
pmount.source = "${pkgs.pmount}/bin/pmount";
pumount.source = "${pkgs.pmount}/bin/pumount";
};
# keybase
services.keybase.enable = true;
services.kbfs.enable = true;
programs.custom.steam.enable = false;
programs.custom.video.enable = false;
services.printing.enable = true;
# fonts
# -----
programs.custom.urxvt.fontSize = 12;
programs.custom.xterm.fontSize = 12;
system.custom.fonts.dpi = 100;
virtualisation = {
docker.enable = false;
virtualbox = {
host.enable = false;
guest.x11 = false;
guest.enable = false;
};
};
configuration.desktop = {
width = 1366;
height = 768;
};
}

8
configs/pepe/encfs.nix Normal file
View File

@ -0,0 +1,8 @@
{ config, lib, pkgs, ... }:
{
module.backup.services.encfs = {
"fotos".enable = true;
"desktop".enable = true;
"finance".enable = true;
};
}

View File

@ -0,0 +1,86 @@
# Do not modify this file! It was generated by nixos-generate-config
# and may be overwritten by future invocations. Please make changes
# to /etc/nixos/configuration.nix instead.
{ config, lib, pkgs, ... }:
{
imports =
[ <nixpkgs/nixos/modules/installer/scan/not-detected.nix>
];
boot.initrd.availableKernelModules = [ "ehci_pci" "ahci" "usb_storage" "sd_mod" "sdhci_pci" ];
boot.kernelModules = [ "kvm-intel" ];
boot.extraModulePackages = [ ];
boot.loader.grub = {
enable = true;
version = 2;
device = "/dev/sda";
};
zramSwap = {
enable = true;
numDevices = 2;
swapDevices = 1;
memoryPercent = 50;
};
fileSystems."/share/" = {
device = "/dev/ram1";
fsType = "tmpfs";
};
fileSystems."/browsers/" = {
#device = "/dev/ram2";
#fsType = "tmpfs";
options = [ "noatime" "nodiratime" "discard" ];
device = "/dev/secure_vg/browser";
fsType = "ext4";
};
nix.maxJobs = lib.mkDefault 4;
powerManagement.cpuFreqGovernor = lib.mkDefault "powersave";
# lvm volume group
# ----------------
boot.initrd.luks.devices = [
{
name = "secure_vg";
device = "/dev/sda2";
preLVM = true;
}
];
# NTFS support
# ------------
environment.systemPackages = [
pkgs.ntfs3g
];
# root
# ----
fileSystems."/" = {
options = [ "noatime" "nodiratime" "discard" ];
device = "/dev/secure_vg/root";
fsType = "ext4";
};
# /home/palo/private/.fotos.ct
# ----------------------------
fileSystems."/home/palo/private/.fotos.ct" = {
options = [ "noatime" "nodiratime" "discard" ];
device = "/dev/secure_vg/fotos";
fsType = "ext4";
};
# boot
# ----
fileSystems."/boot" = {
device = "/dev/sda1";
fsType = "ext4";
};
}

5
configs/pepe/samba.nix Normal file
View File

@ -0,0 +1,5 @@
{ config, ... }:
{
}

View File

@ -0,0 +1,32 @@
{ config, pkgs, lib, ... }:
{
test.services.syncthing = {
enable = true;
openDefaultPorts = false;
user = "palo";
dataDir = "/home/palo/.syncthing";
configDir = "/home/palo/.syncthing";
declarative = {
cert = toString <secrets/syncthing/cert.pem>;
key = toString <secrets/syncthing/key.pem>;
overrideFolders = true;
folders = {
book.path = "/home/palo/books";
desktop-encrypted.path = "/home/palo/.desktop.ct";
finance-encrypted.path = "/home/palo/.finance.ct";
fotos-encrypted.path = "/home/palo/private/.fotos.ct";
kruck-pepe.path = "/home/palo/pepe-kruck";
music-library.path = "/home/palo/music-library";
music-projects.path = "/home/palo/music-projects";
porani-pepe.path = "/home/palo/pepe-porani";
schasch-pepe.path = "/home/palo/pepe-schasch";
smartphone-fotos.path = "/home/palo/smartphone-fotos";
workout-pepe.path = "/home/palo/pepe-workout";
};
};
};
}

18
configs/pepe/tinc.nix Normal file
View File

@ -0,0 +1,18 @@
{ config, lib, pkgs, ... }:
with lib;
{
module.cluster.services.tinc = {
"private" = {
enable = true;
openPort = true;
connectTo = [ "sputnik" ];
};
"retiolum" = {
enable = true;
openPort = true;
};
};
}

View File

@ -0,0 +1,77 @@
{lib, pkgs, ... }:
let
wifi = "wlp0s29u1u2";
ipAddress = "10.123.145.1";
prefixLength = 24;
servedAddressRange = "10.123.145.2,10.123.145.150,12h";
ssid="bumbumbum";
wifiPassword=lib.fileContents <secrets/wifi-access-point>;
in
{
# todo only open needed ports
networking.firewall.trustedInterfaces = [ wifi ];
networking.networkmanager.unmanaged = [ wifi ];
networking.dhcpcd.denyInterfaces = [ wifi ];
networking.interfaces."${wifi}".ipv4.addresses = [ {
address = ipAddress;
prefixLength = prefixLength;
}];
# forward traffic coming in trough the access point => provide internet and vpn network access
# todo : forward to own servers
boot.kernel.sysctl = {
"net.ipv4.conf.${wifi}.forwarding" = true;
"net.ipv6.conf.${wifi}.forwarding" = true;
};
systemd.services.hostapd = {
description = "hostapd wireless AP";
path = [ pkgs.hostapd ];
# start manual
# wantedBy = [ "network.target" ];
after = [ "${wifi}-cfg.service" "nat.service" "bind.service" "dhcpd.service" "sys-subsystem-net-devices-${wifi}.device" ];
serviceConfig = {
ExecStart = "${pkgs.hostapd}/bin/hostapd ${pkgs.writeText "hostapd.conf" ''
interface=${wifi}
hw_mode=g
channel=10
ieee80211d=1
country_code=DE
ieee80211n=1
wmm_enabled=1
ssid=${ssid}
auth_algs=1
wpa=2
wpa_key_mgmt=WPA-PSK
rsn_pairwise=CCMP
wpa_passphrase=${wifiPassword}
''}";
Restart = "always";
};
};
services.dnsmasq = {
enable = true;
extraConfig = ''
# Only listen to routers' LAN NIC. Doing so opens up tcp/udp port 53 to
# localhost and udp port 67 to world:
interface=${wifi}
# Explicitly specify the address to listen on
listen-address=${ipAddress}
# Dynamic range of IPs to make available to LAN PC and the lease time.
# Ideally set the lease time to 5m only at first to test everything works okay before you set long-lasting records.
dhcp-range=${servedAddressRange}
'';
};
}

View File

@ -0,0 +1,58 @@
{ pkgs, lib, config, ... }:
{
imports = [
<system/server>
./hardware-configuration.nix
./tinc.nix
./syncthing.nix
#./packages.nix
#./home-assistant.nix
#./wifi-access-point.nix
#./kodi.nix
#./mpd.nix
];
networking.hostName = "porani";
# enable initrd ssh
configuration.init-ssh = {
enable = "enabled";
kernelModules = [ "e1000e" ];
authorizedKeys = config.users.users.root.openssh.authorizedKeys.keyFiles;
hostECDSAKey = <secrets/init-ssh/host_ecdsa_key>;
};
# programs
programs.custom.vim.enable = true;
environment.systemPackages = [ pkgs.mosh ];
# wifi setup
#system.custom.wifi = {
# enable = true;
# configurationFile = <secrets/wpa_supplicant>;
# interfaces = [ "wlp3s0" ];
#};
# nix-shell -p speedtest_cli --run speedtest
#configuration.fireqos = {
# enable = true;
# interface = "wlp3s0";
# input = 2500;
# output = 1200;
# balance = false;
#};
# nix-shell -p speedtest_cli --run speedtest
configuration.fireqos = {
enable = true;
interface = "eth0";
input = 2500;
output = 1200;
balance = false;
};
}

View File

@ -0,0 +1,77 @@
{ config, lib, pkgs, ... }:
{
imports =
[ <nixpkgs/nixos/modules/installer/scan/not-detected.nix>
];
boot.initrd.availableKernelModules = [ "ehci_pci" "ahci" "usb_storage" "sd_mod" "sdhci_pci" ];
boot.initrd.kernelModules = [ "dm-snapshot" ];
boot.kernelModules = [ "kvm-intel" ];
boot.extraModulePackages = [ ];
# grub configuration
# ------------------
boot.loader.grub = {
device = "/dev/sda";
enable = true;
version = 2;
};
# lvm volume group
# ----------------
boot.initrd.luks.devices = [
{
name = "vg";
device = "/dev/sda2";
preLVM = true;
}
];
# NTFS support
# ------------
environment.systemPackages = [
pkgs.ntfs3g
];
# root
# ----
fileSystems."/" = {
options = [ "noatime" "nodiratime" "discard" ];
device = "/dev/vg/root";
fsType = "ext4";
};
# boot
# ----
fileSystems."/boot" = {
device = "/dev/sda1";
fsType = "ext4";
};
# automount
# ---------
fileSystems."/media" = {
device = "/dev/disk/by-uuid/162c2f9e-8baa-4433-99fd-bb7e7b69472f";
fsType = "ext4";
options = [
"nofail"
"noauto"
#"x-systemd.device-timeout=1ms"
];
};
systemd.mounts = [
{
enable = true;
options = "nofail,noauto";
type = "ext4";
wantedBy = ["multi-user.target"];
what = "/dev/disk/by-uuid/162c2f9e-8baa-4433-99fd-bb7e7b69472f";
where = "/media";
}
];
swapDevices = [ ];
nix.maxJobs = lib.mkDefault 4;
powerManagement.cpuFreqGovernor = lib.mkDefault "powersave";
}

View File

@ -0,0 +1,228 @@
{ pkgs, config, lib, ... }:
let
unstablePkgs = import <nixpkgs-unstable> {};
in {
imports = [
./home-assistant/chaospott.nix
./home-assistant/holiday.nix
./home-assistant/mpd.nix
./home-assistant/sonoff.nix
./home-assistant/mqtt.nix
./home-assistant/dayOfWeek.nix
./home-assistant/timer.nix
./home-assistant/kodi.nix
./home-assistant/zigbee2mqtt.nix
];
services.homeAssistantConfig = {
# turn on to edit GUI
# lovelace = {};
homeassistant = {
latitude = 51.444847;
longitude = 6.967006;
elevation = 116;
auth_providers = [
{
type = "trusted_networks";
trusted_networks = [
config.module.cluster.services.tinc."private".networkSubnet
];
}
];
};
prometheus.namespace = "hass";
automation = [
# todo when ich weis ich bin zuhause
#{
# alias = "Licht and wenn Dunkel";
# trigger = {
# platform = "state";
# entity_id = [ "binary_sensor.night" ];
# from = "off";
# to = "on";
# };
# action = [
# {
# service = "switch.turn_on";
# entity_id = "group.kitchen";
# }
# {
# service = "switch.turn_on";
# entity_id = "group.living_room";
# }
# ];
#}
#{
# alias = "Küchen Sensor An";
# trigger = {
# platform = "state";
# entity_id = [ "binary_sensor.motion_1" ];
# to = "on";
# };
# action = {
# service = "switch.turn_on";
# entity_id = "group.kitchen";
# };
#}
#{
# alias = "Küchen Sensor aus";
# trigger = {
# platform = "state";
# entity_id = [ "binary_sensor.motion_1" ];
# to = "off";
# for = "00:00:25";
# };
# action = {
# service = "switch.turn_off";
# entity_id = "group.kitchen";
# };
#}
];
group = {
bed_room = {
name = "Schlafzimmer";
view = false;
};
tv = {
name = "TV";
view = false;
};
living_room = {
name = "Wohnzimmer";
view = false;
};
kitchen = {
name = "Küche";
view = false;
};
today = {
control = "hidden";
name = "Today";
view = false;
entities = [
"sensor.weather_temperature"
"sun.sun"
];
};
all_lights = {
name = "All Lights";
view = false;
};
unknown = {
control = "hidden";
name = "Not Used";
view = false;
};
view_rooms = {
name = "Räume";
view = true;
entities = [
"group.all_lights"
"group.bed_room"
"group.living_room"
"group.kitchen"
"group.tv"
];
};
view_overview = {
name = "Übersicht";
view = true;
entities = [ "group.today" ];
};
};
sun = {};
script.turn_all_off.sequence = [ ];
script.turn_all_on.sequence = [ ];
sensor = [
# Weather prediction
{ platform = "zamg";
name = "Weather";
}
];
# todo: add holidays package to home-assiatnt
binary_sensor = [
{
name = "before_workday";
platform = "workday";
country = "DE";
province = "NW";
workdays = [ "mon" "tue" "wed" "thu" "fri" ];
days_offset = 1;
}
{
name = "workday";
platform = "workday";
country = "DE";
province = "NW";
workdays = [ "mon" "tue" "wed" "thu" "fri" ];
}
];
};
services.home-assistant = {
enable = true;
package = unstablePkgs.home-assistant.override{
python3 = unstablePkgs.python36;
extraPackages = python: [
# todo : check which is still needed
python.netdisco
python.xmltodict
python.mpd2
# for mqtt
python.hbmqtt
python.paho-mqtt
# needed for platform workday
(python.buildPythonPackage rec{
pname = "holidays";
version = "0.9.10";
src = python.fetchPypi {
inherit pname version;
sha256 = "9f06d143eb708e8732230260636938f2f57114e94defd8fa2082408e0d422d6f";
};
doCheck = false;
buildInputs = [ pkgs.dateutils ];
propagatedBuildInputs = [
python."python-dateutil"
python."six"
];
meta = with pkgs.stdenv.lib; {
homepage = "https://github.com/dr-prodigy/python-holidays";
license = licenses.mit;
description = "Generate and work with holidays in Python";
maintainers = with maintainers; [ mrVanDalo ];
};
})
];
};
};
}

View File

@ -0,0 +1,85 @@
{ config, pkgs, ... }:
let
name = "chaospott";
folderPath = config.services.home-assistant.configDir;
filePath = "${folderPath}/${name}.json";
in {
services.homeAssistantConfig = {
sensor = [
{
platform = "file";
name = "${name}_aerie";
file_path = filePath;
value_template = "{{ value_json.aerie }}";
}
{
platform = "file";
name = "${name}_cellar";
file_path = filePath;
value_template = "{{ value_json.cellar }}";
}
];
homeassistant = {
whitelist_external_dirs = [ folderPath ];
customize = {
"sensor.${name}_aerie" = {
icon = "mdi:store";
entity_picture = "https://chaospott.de/images/logo.png";
friendly_name = "ChaosPott Oben";
};
"sensor.${name}_cellar" = {
icon = "mdi:store";
entity_picture = "https://chaospott.de/images/logo.png";
friendly_name = "ChaosPott Unten";
};
};
};
group = {
"${name}" = {
name = "ChaosPott (Essen)";
control = "hidden";
entities = [
"sensor.${name}_aerie"
"sensor.${name}_cellar"
];
};
view_overview.entities = [ "group.${name}" ];
};
};
systemd.services."${name}" = {
enable = true;
before = [ "home-assistant.service" ];
wantedBy = [ "home-assistant.service" ];
serviceConfig = {
User = "hass";
Type = "oneshot";
};
description = "set ${name} for homeassistant";
script = /* sh */ ''
${pkgs.curl}/bin/curl -Ls https://status.chaospott.de/api \
| ${pkgs.jq}/bin/jq --compact-output \
'.sensors.door_locked |
[.[] | { "\(.location)" : (if .value then "closed" else "open" end) }] |
reduce .[] as $item ({}; . + $item) ' \
>> ${filePath}
'';
};
systemd.timers."${name}" = {
enable = true;
wantedBy = [ "multi-user.target" ];
timerConfig = {
OnCalendar = "hourly";
Persistent = "true";
};
};
}

View File

@ -0,0 +1,57 @@
{ config, ... }:
let
folderPath = config.services.home-assistant.configDir;
filePath = "${folderPath}/dayOfWeek.json";
in {
services.homeAssistantConfig = {
sensor = [
{ platform = "file";
name = "day_of_week";
file_path = filePath;
value_template = "{{ value_json.dayOfWeek }}";
}
];
homeassistant = {
whitelist_external_dirs = [ folderPath ];
customize."sensor.day_of_week" = {
icon = "mdi:calendar-today";
friendly_name = "Wochen Tag";
};
};
group = {
overview.entities = [
"sensor.day_of_week"
];
};
};
systemd.services.dayOfWeek = {
enable = true;
before = [ "home-assistant.service" ];
wantedBy = [ "home-assistant.service" ];
serviceConfig = {
User = "hass";
Type = "oneshot";
};
description = "set day of wek for homeassistant";
script = /* sh */ ''
date +'{"dayOfWeek":"%A"}' >> ${filePath}
'';
};
systemd.timers.dayOfWeek = {
enable = true;
wantedBy = [ "multi-user.target" ];
timerConfig = {
OnCalendar = "00:01:00";
Persistent = "true";
};
};
}

View File

@ -0,0 +1,93 @@
{ config, pkgs, ... }:
let
state = "NW"; # NRW
# state = "BE"; # Berlin
name = "holiday";
folderPath = config.services.home-assistant.configDir;
filePath = "${folderPath}/${name}.json";
in {
services.homeAssistantConfig = {
# todo : use the python tool
sensor = [
{ platform = "file";
name = "${name}_date";
file_path = filePath;
value_template = "{{ value_json.date }}";
}
{ platform = "file";
name = "${name}_name";
file_path = filePath;
value_template = "{{ value_json.name }}";
}
];
homeassistant = {
whitelist_external_dirs = [ folderPath ];
customize = {
"sensor.${name}_date" = {
icon = "mdi:calendar";
friendly_name = "Nächster Feiertag";
};
"sensor.${name}_name" = {
icon = "mdi:calendar";
friendly_name = "Nächster Feiertag";
};
};
};
group = {
holidays = {
name = "Feiertage";
view = false;
control = "hidden";
entities = [
"sensor.${name}_date"
"sensor.${name}_name"
];
};
view_overview.entities = [ "group.holidays" ];
};
};
systemd.services."${name}" = {
enable = true;
before = [ "home-assistant.service" ];
wantedBy = [ "home-assistant.service" ];
serviceConfig = {
User = "hass";
Type = "oneshot";
};
description = "set ${name} for homeassistant";
script = /* sh */ ''
${pkgs.curl}/bin/curl \
-Ls "https://feiertage-api.de/api/?jahr=$( date +%Y )&nur_land=${state}" \
| ${pkgs.jq}/bin/jq --compact-output '
map_values( .datum ) |
to_entries |
map( { date: .value, name : .key } ) |
sort_by( .date ) |
map(select ( .date >= "'`date +%Y-%m-%d`'" )) |
.[0]' \
>> ${filePath}
'';
};
systemd.timers."${name}" = {
enable = true;
wantedBy = [ "multi-user.target" ];
timerConfig = {
OnCalendar = "daily";
Persistent = "true";
};
};
}

View File

@ -0,0 +1,85 @@
{ pkgs, config, lib, ... }:
{
services.homeAssistantConfig = {
group.view_overview.entities = [
"media_player.kodi"
];
media_player = [
{
platform = "kodi";
host = "127.0.0.1";
turn_on_action.service = "script.watch_tv";
turn_off_action.service = "script.stop_watch_tv";
}
];
shell_command = {
start_display = "sudo ${pkgs.systemd}/bin/systemctl start display-manager";
stop_display = "sudo ${pkgs.systemd}/bin/systemctl stop display-manager";
};
script = {
turn_all_off.sequence = [
# todo : use the shell_command here
{
alias = "turn off tv";
service = "switch.turn_off";
data.entity_id = "group.tv";
}
{
alias = "stop kodi";
service = "shell_command.stop_display";
}
];
test_display.sequence = [
{ service = "shell_command.start_display"; }
{ delay.seconds = 20; }
{ service = "shell_command.stop_display"; }
];
watch_tv = {
alias = "Watch TV";
sequence = [
{
alias = "turn on tv";
service = "switch.turn_on";
data.entity_id = "group.tv";
}
{ delay.minutes = 1;}
{
alias = "start kodi";
service = "shell_command.start_display";
}
];
};
stop_watch_tv = {
alias = "Stop TV";
sequence = [
{
alias = "turn off tv";
service = "switch.turn_off";
data.entity_id = "group.tv";
}
{
alias = "stop kodi";
service = "shell_command.stop_display";
}
];
};
};
group.tv.entities = [ "script.watch_tv" "script.stop_watch_tv" ];
};
security.sudo.extraConfig = ''
hass ALL= (root) NOPASSWD: ${pkgs.systemd}/bin/systemctl start display-manager
hass ALL= (root) NOPASSWD: ${pkgs.systemd}/bin/systemctl stop display-manager
'';
}

View File

@ -0,0 +1,43 @@
{ lib, ... }:
{
services.homeAssistantConfig = {
group.view_overview.entities = [
"media_player.mpd"
];
media_player = [
{
platform = "mpd";
host = "localhost";
}
];
script.turn_all_off.sequence = [
{
alias = "turn mpd off";
service = "media_player.turn_off";
data.entity_id = "media_player.mpd";
}
];
script.turn_all_on.sequence = [
{
alias = "turn mpd on";
service = "media_player.turn_on";
data.entity_id = "media_player.mpd";
}
{
alias = "Adjust volume";
service = "media_player.volume_set";
data = {
entity_id = "media_player.mpd";
volume_level = "0.90";
};
}
];
};
}

View File

@ -0,0 +1,27 @@
{
services.homeAssistantConfig.mqtt = {
# discovery = false;
# for mosquitto
broker = "127.0.0.1";
username = fileContents <secrets/home-assistant/mqtt-user>;
password = fileContents <secrets/home-assistant/mqtt-password>;
};
services.mosquitto = {
enable = true;
host = "0.0.0.0";
users = {
homeassistant = {
password = lib.fileContents <secrets/mosquitto/password>;
acl = [ "topic readwrite #" ];
};
zigbee = {
password = lib.fileContents <secrets/zigbee/password>;
acl = [ "topic readwrite #" ];
};
};
};
}

View File

@ -0,0 +1,118 @@
{ pkgs, config, lib, ... }:
let
unstablePkgs = import <nixpkgs-unstable> {};
in {
services.homeAssistantConfig =
let
sonoffSwitches = {
"pal01" = { label = "Bett"; icon = "mdi:lightbulb-on"; };
"pal02" = { label = "Lampe"; icon = "mdi:lightbulb-on"; };
"pal03" = { label = "Couche"; icon = "mdi:lightbulb-on"; };
"pal06" = { label = "Küche"; icon = "mdi:lightbulb-on"; };
"pal05" = { label = "TV"; icon = "mdi:television"; };
"pal04" = { label = "Nummer 4"; icon = "mdi:power-plug-off"; };
"pal07" = { label = "Nummer 7"; icon = "mdi:power-plug-off"; };
"pal08" = { label = "Nummer 8"; icon = "mdi:power-plug-off"; };
};
toSwitch = name: "switch.${name}";
in {
homeassistant = {
customize = lib.mapAttrs' (
entity: value:
{
name = toSwitch entity;
value = {
friendly_name = value.label;
icon = value.icon;
};
}
) sonoffSwitches;
};
script.turn_all_off.sequence = [
{
alias = "turn off sonoff";
service = "switch.turn_off";
data.entity_id = "group.all_lights";
}
{
alias = "turn off sonoff";
service = "switch.turn_off";
data.entity_id = "group.tv";
}
];
script.turn_all_on.sequence = [
{
alias = "turn on all lights";
service = "switch.turn_on";
data.entity_id = "group.all_lights";
}
];
group = {
bed_room = {
entities = builtins.map toSwitch [ "pal01" ];
};
living_room = {
entities = builtins.map toSwitch [ "pal03" "pal02" ];
};
tv = {
entities = builtins.map toSwitch [ "pal05" ];
};
kitchen = {
entities = builtins.map toSwitch [ "pal06" ];
};
unknown = {
entities = builtins.map toSwitch [ "pal04" "pal07" "pal08" ];
};
all_lights = {
entities = builtins.map toSwitch [ "pal01" "pal02" "pal03" "pal06" ];
};
};
switch =
let
sonoffConfigurations = builtins.map (name:
{
name = name;
platform = "mqtt";
command_topic = "cmnd/${lib.toUpper name}/POWER";
state_topic = "stat/${lib.toUpper name}/POWER";
payload_on = "ON";
payload_off = "OFF";
state_on = "ON";
state_off = "OFF";
}) (builtins.attrNames sonoffSwitches) ;
in
sonoffConfigurations;
# discover state on init
automation = [
{
alias = "Sonoff initial Power state";
trigger = {
platform = "homeassistant";
event = "start";
};
action = builtins.map ( name:
{
service = "mqtt.publish";
data = {
topic = "cmnd/${lib.toUpper name}/power";
payload = "";
};
})
(builtins.attrNames sonoffSwitches);
}
];
};
}

View File

@ -0,0 +1,274 @@
{ config, ... }:
{
imports = [ ./mpd.nix ];
services.homeAssistantConfig = {
sensor = [
{
platform = "time_date";
display_options = [
"time"
"date"
];
}
];
input_datetime = {
wakeup = {
name = "Arbeitswecker";
has_time = true;
has_date = false;
icon = "mdi:alarm";
};
leave = {
name = "Turn off Time";
has_time = true;
has_date = false;
icon = "mdi:alarm";
};
return = {
name = "Return home";
has_time = true;
has_date = false;
icon = "mdi:alarm";
};
sleep = {
name = "Turn off Time";
has_time = true;
has_date = false;
icon = "mdi:alarm";
};
};
input_boolean = {
wakeup = {
name = "enable";
icon = "mdi:toggle-switch";
};
leave = {
name = "enable";
icon = "mdi:toggle-switch";
};
return = {
name = "enable";
icon = "mdi:toggle-switch";
};
sleep = {
name = "enable";
icon = "mdi:toggle-switch";
};
};
input_select = {
wakeup = {
name = "Playlist";
icon = "mdi:library-music";
options = [ "wakeup" "wakeup1" "wakeup2" ];
};
};
binary_sensor = [
{
platform = "tod";
name = "night";
after = "sunset";
before = "sunrise";
}
{
platform = "tod";
name = "daytime";
after = "sunrise";
before = "sunset";
}
];
group = {
timer_wakeup = {
view = false;
name = "Arbeits Aufwachen";
control = "hidden";
entities = [
"input_boolean.wakeup"
"input_datetime.wakeup"
"input_select.wakeup"
];
};
timer_leave = {
view = false;
name = "Leave Time";
control = "hidden";
entities = [
"input_boolean.leave"
"input_datetime.leave"
];
};
timer_return = {
view = false;
name = "Nach Hause kommen";
control = "hidden";
entities = [
"input_boolean.return"
"input_datetime.return"
];
};
timer_sleep = {
view = false;
name = "Einschlafen";
control = "hidden";
entities = [
"input_boolean.sleep"
"input_datetime.sleep"
];
};
timers.entities = [
"group.timer_wakeup"
"group.timer_leave"
"group.timer_return"
"group.timer_sleep"
"binary_sensor.night"
"binary_sensor.daytime"
];
today.entities = [
"sensor.date"
"sensor.time"
];
view_overview.entities = [
"group.timer_wakeup"
"group.timer_leave"
"group.timer_return"
"group.timer_sleep"
];
};
automation = [
{
alias = "Wecker Arbeiten";
trigger = {
platform = "template";
value_template =
"{{ states('sensor.time') == (states.input_datetime.wakeup.attributes.timestamp | int | timestamp_custom('%H:%M', False)) }}";
};
condition = {
condition = "and";
conditions = [
{
condition = "state";
entity_id = "input_boolean.wakeup";
state = "on";
}
{
condition = "state";
entity_id = "binary_sensor.workday";
state = "on";
}
];
};
action = [
{
alias = "Play wakeup list";
service = "media_player.play_media";
data_template = {
entity_id = "media_player.mpd";
media_content_type = "playlist";
media_content_id = "{{ states('input_select.wakeup') }}";
};
}
{
alias = "turn all on";
service = "script.turn_on";
entity_id = "script.turn_all_on";
}
];
}
{
alias = "Leave Turn all off Timer";
trigger = {
platform = "template";
value_template =
"{{ states('sensor.time') == (states.input_datetime.leave.attributes.timestamp | int | timestamp_custom('%H:%M', False)) }}";
};
condition = {
condition = "and";
conditions = [
{
condition = "state";
entity_id = "input_boolean.leave";
state = "on";
}
];
};
action = [
{
alias = "turn all off";
service = "script.turn_on";
entity_id = "script.turn_all_off";
}
];
}
{
alias = "Return to Home";
trigger = {
platform = "template";
value_template =
"{{ states('sensor.time') == (states.input_datetime.return.attributes.timestamp | int | timestamp_custom('%H:%M', False)) }}";
};
condition = {
condition = "and";
conditions = [
{
condition = "state";
entity_id = "input_boolean.return";
state = "on";
}
];
};
action = [
{
alias = "turn all on";
service = "script.turn_on";
entity_id = "script.turn_all_on";
}
];
}
{
alias = "Sleep Turn all off Timer";
trigger = {
platform = "template";
value_template =
"{{ states('sensor.time') == (states.input_datetime.sleep.attributes.timestamp | int | timestamp_custom('%H:%M', False)) }}";
};
condition = {
condition = "and";
conditions = [
{
condition = "state";
entity_id = "input_boolean.sleep";
state = "on";
}
];
};
action = [
{
alias = "turn all off";
service = "script.turn_on";
entity_id = "script.turn_all_off";
}
];
}
];
};
}

View File

@ -0,0 +1,304 @@
{ pkgs, lib, config , ... }:
let
# allow new devices to join
enablePairing = true;
device = "/dev/ttyACM0";
dataFolder = "/srv/zigbee/data";
sensors = {
buttons = {
"button_1".id = "0x00158d0002b04f65";
"button_2".id = "0x00158d0002b04f09";
"button_3".id = "0x00158d0002b00e04";
};
temperature = {
"temperature_sensor_1".id = "0x00158d0002d79220";
"temperature_sensor_2".id = "0x00158d0002d7913d";
};
motion = {
"motion_sensor_1".id = "0x00158d0002fbd451";
};
};
# todo : rename with allSensors
allSensors = with sensors; buttons // temperature // motion;
zigBee2MqttConfig = {
# Home Assistant integration (MQTT discovery)
homeassistant = false;
# homeassistant = true;
# allow new devices to join
permit_join = enablePairing;
# MQTT settings
mqtt = {
# MQTT base topic for zigbee2mqtt MQTT messages
base_topic = "zigbee2mqtt";
# MQTT server URL
server = "mqtt://127.0.0.1:1883";
# MQTT server authentication, uncomment if required:
user = "zigbee";
password = lib.fileContents <secrets/zigbee/password>;
};
# Serial settings
serial = {
port = "/dev/ttyACM0";
# Optional: disable LED of CC2531 USB sniffer
disable_led = true;
};
devices = lib.mapAttrs' (
name: { id , ... }:
{
name = id;
value = {
retain = false;
friendly_name = name;
};
}
) allSensors;
};
configurationYaml = pkgs.writeText "configuration.yml" (builtins.toJSON zigBee2MqttConfig);
in
{
imports = [ ./mqtt.nix ];
services.homeAssistantConfig = {
# group.unknown.entities = [ "sensor.button_1" ];
sensor = let
buttons = with lib; mapAttrsToList (
name: {...}:
{
platform = "mqtt";
name = name;
icon = "mdi:toggle-switch";
state_topic = "zigbee2mqtt/${name}";
availability_topic = "zigbee2mqtt/bridge/state";
value_template = "{{ value_json.click }}";
}
) sensors.buttons;
temperature = with lib; mapAttrsToList (
name: {...}:
[
{
platform = "mqtt";
name = name;
state_topic = "zigbee2mqtt/${name}";
availability_topic = "zigbee2mqtt/bridge/state";
unit_of_measurement = "°C";
device_class = "temperature";
value_template = "{{ value_json.temperature }}";
}
{
platform = "mqtt";
name = "humidity_${name}";
state_topic = "zigbee2mqtt/${name}";
availability_topic = "zigbee2mqtt/bridge/state";
unit_of_measurement = "%";
device_class = "humidity";
value_template = "{{ value_json.humidity }}";
}
{
platform = "mqtt";
name = "pressure_${name}";
state_topic = "zigbee2mqtt/${name}";
availability_topic = "zigbee2mqtt/bridge/state";
unit_of_measurement = "hPa";
device_class = "pressure";
value_template = "{{ value_json.pressure }}";
}
]
) sensors.temperature;
informations = lib.mapAttrsToList (
name: {...}:
[
{
platform = "mqtt";
name = "battery_${name}";
state_topic = "zigbee2mqtt/${name}";
availability_topic = "zigbee2mqtt/bridge/state";
unit_of_measurement = "%";
device_class = "battery";
value_template = "{{ value_json.battery }}";
}
{
name = "link_${name}";
platform = "mqtt";
state_topic = "zigbee2mqtt/${name}";
availability_topic = "zigbee2mqtt/bridge/state";
unit_of_measurement = "-";
value_template = "{{ value_json.linkquality }}";
}
]
) allSensors;
in
lib.flatten ( buttons ++ temperature ++ informations );
binary_sensor = let
motion = lib.mapAttrsToList (
name: { ... }:
{
name = name;
platform = "mqtt";
device_class = "motion";
#icon = "mdi:motion-sensor";
state_topic = "zigbee2mqtt/${name}";
availability_topic = "zigbee2mqtt/bridge/state";
payload_on = true;
payload_off = false;
value_template = "{{ value_json.occupancy }}";
}
) sensors.motion;
in
lib.flatten ( motion );
group = let
information = name: [ "sensor.battery_${name}" "sensor.link_${name}" ];
sensor = lib.mapAttrs' (
name: {...}:
{
name = name;
value = {
control = "hidden";
entities = ["sensor.${name}"] ++ (information name);
};
}
) (sensors.buttons);
sensorTemperature = lib.mapAttrs' (
name: { ... }:
{
name = name;
value = {
control = "hidden";
entities = [
"sensor.${name}"
"sensor.humidity_${name}"
"sensor.pressure_${name}"
] ++ (information name);
};
}
) (sensors.temperature);
binarySensor = lib.mapAttrs' (
name: { ... }:
{
name = name;
value = {
control = "hidden";
entities = [ "binary_sensor.${name}" ] ++ (information name);
};
}
) (sensors.motion);
views = {
view_sensors = {
name = "Sensoren";
control = "hidden";
view = true;
entities = lib.mapAttrsToList (name: { ... }: "group.${name}") allSensors;
};
};
in
views // sensor // binarySensor // sensorTemperature ;
automation =
let
lights = map (button:
{
alias = "Toggle all lights, on click";
trigger = {
platform = "mqtt";
topic = "zigbee2mqtt/${button}";
};
condition = {
condition = "template";
value_template = ''{{ "single" == trigger.payload_json.click }}'';
};
action = {
service = "switch.toggle";
entity_id = "group.all_lights";
};
}) ["button_1" "button_2" "button_3"];
mpd = map (button:
{
alias = "Toggle mpd, on double click";
trigger = {
platform = "mqtt";
topic = "zigbee2mqtt/${button}";
};
condition = {
condition = "template";
value_template = ''{{ "double" == trigger.payload_json.click }}'';
};
action = {
service = "media_player.toggle";
# todo use a group here
entity_id = "media_player.mpd";
};
}) ["button_1" "button_2" "button_3"];
in
lights ++ mpd;
# click = double => music an aus
# click = hold => film an aus
};
virtualisation.docker.enable = true;
# todo : einen eigenen container bauen mit dockerTool : https://nixos.wiki/wiki/Docker
systemd.services."zigbee2mqtt" = {
enable = true;
description = "Allows you to use your Zigbee devices without the vendors bridge/gateway.";
after = [ "docker.service" ];
requires = [ "docker.service" ];
# todo : udev rule erstellen, die diesen service erst startet, dieses wanted by ist labil
wantedBy = [ "home-assistant.service" ];
preStart = ''
if [ -f ${dataFolder}/configuration.yaml ]
then
rm ${dataFolder}/configuration.yaml
fi
mkdir -p ${dataFolder}
cat ${configurationYaml} | ${pkgs.yq}/bin/yq --yaml-output '.' > ${dataFolder}/configuration.yaml
'';
restartTriggers = [ configurationYaml ];
script = ''
# delete old instance to ensure update
${pkgs.docker}/bin/docker stop zigbee2mqtt || true && ${pkgs.docker}/bin/docker rm -f zigbee2mqtt || true
# start instance
${pkgs.docker}/bin/docker run \
--network="host" \
--name zigbee2mqtt \
-v ${dataFolder}:/app/data \
--device=${device} \
koenkk/zigbee2mqtt
'';
};
}

30
configs/porani/kodi.nix Normal file
View File

@ -0,0 +1,30 @@
{ config, lib, pkgs, ... }:
{
services.xserver = {
enable = true;
autorun = false;
desktopManager = {
kodi.enable = true;
default = "kodi";
xterm.enable = false;
};
displayManager.lightdm = {
enable = true;
autoLogin.enable = true;
autoLogin.user = config.users.users.kodi.name;
};
};
users = {
# mutableUsers = true;
users.kodi= {
isNormalUser = true;
name = "kodi";
uid = 1338;
initialPassword = lib.fileContents <secrets/kodi/password>;
};
};
}

12
configs/porani/mpd.nix Normal file
View File

@ -0,0 +1,12 @@
{ config, lib, ... }:
{
sound.enable = true;
services.mpd = {
enable = true;
network.listenAddress = "any";
musicDirectory = "/media/music-library";
};
}

View File

@ -0,0 +1,7 @@
{ pkgs, ... }:
{
environment.systemPackages = [
];
}

View File

@ -0,0 +1,38 @@
{ config, pkgs, lib, ... }:
{
test.services.syncthing = {
enable = true;
openDefaultPorts = true;
declarative = {
cert = toString <secrets/syncthing/cert.pem>;
key = toString <secrets/syncthing/key.pem>;
overrideFolders = true;
folders = {
movies.path = "/media/movies";
music-library.path = "/media/music-library";
podcasts.path = "/media/podcasts";
series.path = "/media/series";
};
};
};
systemd.services."permown._media" = {
bindsTo = [ "media.mount" ];
after = [ "media.mount" ];
};
system.permown."/media" = {
owner = "syncthing";
group = "syncthing";
umask = "0007";
};
systemd.services."syncthing" = {
bindsTo = [ "media.mount" ];
after = [ "media.mount" ];
};
users.groups."syncthing".members = [ "mpd" "syncthing" "kodi" "palo" ];
}

12
configs/porani/tinc.nix Normal file
View File

@ -0,0 +1,12 @@
{ config, lib, pkgs, ... }:
{
module.cluster.services.tinc = {
"private" = {
enable = true;
openPort = true;
connectTo = [ "sputnik" ];
};
};
}

View File

@ -0,0 +1,67 @@
{lib, pkgs, ... }:
let
wifi = "wlp0s29u1u2";
ipAddress = "10.23.45.1";
prefixLength = 24;
servedAddressRange = "10.23.45.2,10.23.45.150,12h";
ssid="palosiot";
wifiPassword=lib.fileContents <secrets/iot_wifi>;
in
{
# todo only open needed ports
networking.firewall.trustedInterfaces = [ wifi ];
networking.networkmanager.unmanaged = [ wifi ];
networking.dhcpcd.denyInterfaces = [ wifi ];
networking.interfaces."${wifi}".ipv4.addresses = [ {
address = ipAddress; prefixLength = prefixLength;
}];
systemd.services.hostapd = {
description = "hostapd wireless AP";
path = [ pkgs.hostapd ];
wantedBy = [ "network.target" ];
after = [ "${wifi}-cfg.service" "nat.service" "bind.service" "dhcpd.service" "sys-subsystem-net-devices-${wifi}.device" ];
serviceConfig = {
ExecStart = "${pkgs.hostapd}/bin/hostapd ${pkgs.writeText "hostapd.conf" ''
interface=${wifi}
hw_mode=g
channel=10
ieee80211d=1
country_code=DE
ieee80211n=1
wmm_enabled=1
ssid=${ssid}
auth_algs=1
wpa=2
wpa_key_mgmt=WPA-PSK
rsn_pairwise=CCMP
wpa_passphrase=${wifiPassword}
''}";
Restart = "always";
};
};
services.dnsmasq = {
enable = true;
extraConfig = ''
# Only listen to routers' LAN NIC. Doing so opens up tcp/udp port 53 to
# localhost and udp port 67 to world:
interface=${wifi}
# Explicitly specify the address to listen on
listen-address=${ipAddress}
# Dynamic range of IPs to make available to LAN PC and the lease time.
# Ideally set the lease time to 5m only at first to test everything works okay before you set long-lasting records.
dhcp-range=${servedAddressRange}
'';
};
}

View File

@ -0,0 +1,4 @@
{ config, lib, ... }:
{
}

View File

@ -0,0 +1,41 @@
{ config, pkgs, lib, ... }:
{
imports = [
<system/proxy>
./hardware-configuration.nix
./nginx.nix
./tinc.nix
];
networking.hostName = "sputnik";
networking.useDHCP = true;
boot.kernelParams = [ "net.ifnames=0" ];
boot.loader.grub = {
enable = true;
version = 2;
device = "/dev/sda";
};
# nix-shell -p speedtest_cli --run speedtest
configuration.fireqos = {
enable = true;
interface = "eth0";
input = 55000;
output = 4000;
balance = false;
};
services.custom.ssh.sshd.rootKeyFiles = [ (toString <secrets/ssh/jenkins_rsa.pub>) ];
# make sure ssh is only available trough the tinc
networking.firewall.extraCommands = ''
iptables -t nat -A PREROUTING ! -i tinc.private -p tcp -m tcp --dport 22 -j REDIRECT --to-ports 0
'';
}

View File

@ -0,0 +1,23 @@
# Do not modify this file! It was generated by nixos-generate-config
# and may be overwritten by future invocations. Please make changes
# to /etc/nixos/configuration.nix instead.
{ config, lib, pkgs, ... }:
{
imports =
[ <nixpkgs/nixos/modules/profiles/qemu-guest.nix>
];
boot.initrd.availableKernelModules = [ "ata_piix" "uhci_hcd" "virtio_pci" "sd_mod" "sr_mod" ];
boot.kernelModules = [ ];
boot.extraModulePackages = [ ];
fileSystems."/" =
{ device = "/dev/disk/by-uuid/8f2986a3-d2b0-4735-be98-9ec081b87984";
fsType = "ext4";
};
swapDevices = [ ];
nix.maxJobs = lib.mkDefault 1;
}

146
configs/sputnik/nginx.nix Normal file
View File

@ -0,0 +1,146 @@
{ config, lib, pkgs, ... }:
{
networking.firewall.allowedTCPPorts = [ 80 443 ];
services.nginx = {
enable = true;
virtualHosts = {
"git.ingolf-wagner.de" = {
listen = [
{ addr = "0.0.0.0"; port = 4443; ssl = true; }
{ addr = "0.0.0.0"; port = 80; ssl = false; }
];
forceSSL = true;
enableACME = true;
locations."/" = {
proxyPass = "http://workhorse.private:3000";
};
};
"paste.ingolf-wagner.de" = {
listen = [
{ addr = "0.0.0.0"; port = 4443; ssl = true; }
{ addr = "0.0.0.0"; port = 80; ssl = false; }
];
forceSSL = true;
enableACME = true;
locations."/" = {
proxyPass = "http://workhorse.private:8000";
};
};
#"landing.ingolf-wagner.de" = {
# default = true;
# listen = [
# { addr = "0.0.0.0"; port = 4443; ssl = true; }
# { addr = "0.0.0.0"; port = 80; ssl = false; }
# ];
# forceSSL = true;
# enableACME = true;
# locations."/" = {
# root = "/srv/www/ingolf-wagner.de";
# };
#};
"tech.ingolf-wagner.de" = {
listen = [
{ addr = "0.0.0.0"; port = 4443; ssl = true; }
{ addr = "0.0.0.0"; port = 80; ssl = false; }
];
forceSSL = true;
enableACME = true;
locations."/" = {
root = "/srv/www/tech";
extraConfig = ''
if (-d $request_filename) {
rewrite [^/]$ $scheme://$http_host$uri/ permanent;
}
'';
};
};
"terranix.org" = {
listen = [
{ addr = "0.0.0.0"; port = 4443; ssl = true; }
{ addr = "0.0.0.0"; port = 80; ssl = false; }
];
forceSSL = true;
enableACME = true;
locations."/" = {
root = "/srv/www/terranix";
extraConfig = ''
if (-d $request_filename) {
rewrite [^/]$ $scheme://$http_host$uri/ permanent;
}
'';
};
};
"seafile.gaykraft.com" = {
listen = [
{ addr = "0.0.0.0"; port = 4443; ssl = true; }
{ addr = "0.0.0.0"; port = 80; ssl = false; }
];
forceSSL = true;
enableACME = true;
locations."/" = {
proxyPass = "http://workhorse.private:3030";
extraConfig = ''
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Host $server_name;
proxy_set_header X-Forwarded-Proto https;
sub_filter "http://seafile.gaykraft.com" "https://seafile.gaykraft.com";
# used for view/edit office file via Office Online Server
client_max_body_size 0;
'';
};
};
"gaykraft.com" = {
listen = [
{ addr = "0.0.0.0"; port = 4443; ssl = true; }
{ addr = "0.0.0.0"; port = 80; ssl = false; }
];
forceSSL = true;
enableACME = true;
locations."/" = {
root = "/srv/www/gaykraft";
};
};
};
};
services.sslh = {
enable = true;
listenAddress = "0.0.0.0";
port = 443;
verbose = false;
transparent = true;
appendConfig = /* json */ ''
protocols:
(
{ name: "ssh"; service: "ssh"; host: "localhost"; port: "2222"; probe: "builtin"; },
{ name: "ssl"; host: "localhost"; port: "4443"; probe: "builtin"; },
{ name: "tinc"; host: "localhost"; port: "655"; probe: "builtin"; }
);
'';
};
systemd.services."socat-proxy" = {
wantedBy = [ "sslh.service" "multi-user.target" ];
after = [ "sslh.service" ];
script = ''
${pkgs.socat}/bin/socat TCP-LISTEN:2222,fork TCP:workhorse.private:2222
'';
#serviceConfig.User = "sslh";
};
}

10
configs/sputnik/tinc.nix Normal file
View File

@ -0,0 +1,10 @@
{ config, lib, pkgs, ... }:
{
module.cluster.services.tinc = {
"private" = {
enable = true;
openPort = true;
};
};
}

View File

@ -0,0 +1,65 @@
{ config, pkgs, lib, ... }:
{
imports = [
<system/desktop>
./hardware-configuration.nix
./encfs.nix
./packages.nix
./syncthing.nix
./tinc.nix
#./wifi-access-point.nix
];
networking.hostName = "sterni";
system.custom.wifi.interfaces = ["wlp3s0"];
security.wrappers = {
pmount.source = "${pkgs.pmount}/bin/pmount";
pumount.source = "${pkgs.pmount}/bin/pumount";
};
# keybase
services.keybase.enable = true;
services.kbfs.enable = true;
programs.custom.steam.enable = false;
programs.custom.video.enable = false;
services.printing.enable = true;
# fonts
# -----
programs.custom.urxvt.fontSize = 12;
programs.custom.xterm.fontSize = 12;
system.custom.fonts.dpi = 100;
virtualisation = {
docker.enable = false;
virtualbox = {
host.enable = false;
guest.x11 = false;
guest.enable = false;
};
};
configuration.desktop = {
width = 1366;
height = 768;
};
custom.samba-share.folders = {
enable = false;
public = "/home/palo/movies";
};
}

8
configs/sterni/encfs.nix Normal file
View File

@ -0,0 +1,8 @@
{ config, lib, pkgs, ... }:
{
module.backup.services.encfs = {
"fotos".enable = true;
"desktop".enable = true;
"finance".enable = true;
};
}

View File

@ -0,0 +1,92 @@
# Do not modify this file! It was generated by nixos-generate-config
# and may be overwritten by future invocations. Please make changes
# to /etc/nixos/configuration.nix instead.
{ config, lib, pkgs, ... }:
{
imports =
[ <nixpkgs/nixos/modules/installer/scan/not-detected.nix>
];
boot.initrd.availableKernelModules = [ "ehci_pci" "ahci" "xhci_pci" "usb_storage" "sd_mod" "sdhci_pci" ];
boot.initrd.kernelModules = [ "dm-snapshot" ];
boot.kernelModules = [ "kvm-intel" ];
boot.extraModulePackages = [ ];
# Use the systemd-boot EFI boot loader.
boot.loader.systemd-boot.enable = true;
boot.loader.efi.canTouchEfiVariables = true;
zramSwap = {
enable = true;
numDevices = 2;
swapDevices = 1;
memoryPercent = 50;
};
fileSystems."/share/" = {
device = "/dev/ram1";
fsType = "tmpfs";
};
fileSystems."/browsers/" = {
#device = "/dev/ram2";
#fsType = "tmpfs";
options = [ "noatime" "nodiratime" "discard" ];
device = "/dev/vg/browser";
fsType = "ext4";
};
nix.maxJobs = lib.mkDefault 4;
powerManagement.cpuFreqGovernor = lib.mkDefault "powersave";
# lvm volume group
# ----------------
boot.initrd.luks.devices = [
{
name = "vg";
device = "/dev/sda2";
preLVM = true;
}
];
# NTFS support
# ------------
environment.systemPackages = [
pkgs.ntfs3g
];
# root
# ----
fileSystems."/" = {
options = [ "noatime" "nodiratime" "discard" ];
device = "/dev/vg/root";
fsType = "ext4";
};
# home
# ----
fileSystems."/home" = {
options = [ "noatime" "nodiratime" "discard" ];
device = "/dev/vg/home";
fsType = "ext4";
};
# /home/palo/private/.fotos.ct
# --------------------
#fileSystems."/home/palo/private/.fotos.ct" = {
# options = [ "noatime" "nodiratime" "discard" ];
# device = "/dev/vg/fotos";
# fsType = "ext4";
#};
# boot
# ----
fileSystems."/boot" = {
device = "/dev/sda1";
fsType = "vfat";
};
}

View File

@ -0,0 +1,8 @@
{ config, lib, pkgs, ... }:
{
environment.systemPackages = with pkgs ; [
bitwig-studio
];
}

View File

@ -0,0 +1,27 @@
{ config, pkgs, lib, ... }:
{
test.services.syncthing = {
enable = true;
openDefaultPorts = false;
user = "palo";
dataDir = "/home/palo/.syncthing";
configDir = "/home/palo/.syncthing";
declarative = {
cert = toString <secrets/syncthing/cert.pem>;
key = toString <secrets/syncthing/key.pem>;
overrideFolders = true;
folders = {
book.path = "/home/palo/books";
desktop-encrypted.path = "/home/palo/.desktop.ct";
finance-encrypted.path = "/home/palo/.finance.ct";
fotos-encrypted.path = "/home/palo/private/.fotos.ct";
music-library.path = "/home/palo/music-library";
music-projects.path = "/home/palo/music-projects";
};
};
};
}

18
configs/sterni/tinc.nix Normal file
View File

@ -0,0 +1,18 @@
{ config, lib, pkgs, ... }:
with lib;
{
module.cluster.services.tinc = {
"private" = {
enable = true;
openPort = true;
connectTo = [ "sputnik" ];
};
"retiolum" = {
enable = true;
openPort = true;
};
};
}

View File

@ -0,0 +1,77 @@
{lib, pkgs, ... }:
let
wifi = "wlp0s29u1u2";
ipAddress = "10.123.145.1";
prefixLength = 24;
servedAddressRange = "10.123.145.2,10.123.145.150,12h";
ssid="bumbumbum";
wifiPassword=lib.fileContents <secrets/wifi-access-point>;
in
{
# todo only open needed ports
networking.firewall.trustedInterfaces = [ wifi ];
networking.networkmanager.unmanaged = [ wifi ];
networking.dhcpcd.denyInterfaces = [ wifi ];
networking.interfaces."${wifi}".ipv4.addresses = [ {
address = ipAddress;
prefixLength = prefixLength;
}];
# forward traffic coming in trough the access point => provide internet and vpn network access
# todo : forward to own servers
boot.kernel.sysctl = {
"net.ipv4.conf.${wifi}.forwarding" = true;
"net.ipv6.conf.${wifi}.forwarding" = true;
};
systemd.services.hostapd = {
description = "hostapd wireless AP";
path = [ pkgs.hostapd ];
# start manual
# wantedBy = [ "network.target" ];
after = [ "${wifi}-cfg.service" "nat.service" "bind.service" "dhcpd.service" "sys-subsystem-net-devices-${wifi}.device" ];
serviceConfig = {
ExecStart = "${pkgs.hostapd}/bin/hostapd ${pkgs.writeText "hostapd.conf" ''
interface=${wifi}
hw_mode=g
channel=10
ieee80211d=1
country_code=DE
ieee80211n=1
wmm_enabled=1
ssid=${ssid}
auth_algs=1
wpa=2
wpa_key_mgmt=WPA-PSK
rsn_pairwise=CCMP
wpa_passphrase=${wifiPassword}
''}";
Restart = "always";
};
};
services.dnsmasq = {
enable = true;
extraConfig = ''
# Only listen to routers' LAN NIC. Doing so opens up tcp/udp port 53 to
# localhost and udp port 67 to world:
interface=${wifi}
# Explicitly specify the address to listen on
listen-address=${ipAddress}
# Dynamic range of IPs to make available to LAN PC and the lease time.
# Ideally set the lease time to 5m only at first to test everything works okay before you set long-lasting records.
dhcp-range=${servedAddressRange}
'';
};
}

View File

@ -0,0 +1,56 @@
{ config, pkgs, lib, ... }:
with lib;
let
port = 8000;
in {
# configure nginx
services.nginx = {
enable = true;
virtualHosts = {
"paste.workhorse.private" = {
locations."/" = {
proxyPass = "http://localhost:${toString port}";
extraConfig = ''
proxy_set_header Host $host:$server_port;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_read_timeout 90;
proxy_redirect http://localhost:${toString port} https://paste.workhorse.private/;
'';
};
};
};
};
krops.userKeys."bepasty" = {
user = "bepasty";
source = toString <secrets/bepasty-secret-key>;
requiredBy = [ "bepasty-server-ingolf-wagner.de-gunicorn.service" ];
};
services.bepasty = {
enable = true;
servers."ingolf-wagner.de" = {
bind = "0.0.0.0:${toString port}";
secretKeyFile = config.krops.userKeys."bepasty".target;
extraConfig = ''
PERMISSIONS = {
'${lib.fileContents <common_secrets/bepasty/admin-password>}': 'admin,list,create,read,delete',
}
'';
};
};
/* fix bepasty service */
nixpkgs.overlays = let
overlay = self: super:
{
bepasty = super.bepasty.override { python3Packages = pkgs.python27Packages; };
};
in
[ overlay ];
}

View File

@ -0,0 +1,25 @@
{ config, lib, ... }:
let
home = "/home/syncthing/podcasts";
in {
custom.services.castget = {
enable = true;
user = "root";
feeds = {
Alternativlos = {
url = "https://alternativlos.org/alternativlos.rss";
spool = "${home}/alternativlos";
};
LORA_radio = {
url = "https://www.freie-radios.net/portal/podcast.php?radio=19&rss";
spool = "${home}/lora_radio";
};
gegenstandpunkt = {
url = "https://pc.argudiss.de/";
spool = "${home}/GegenStandpunkt";
};
};
};
}

View File

@ -0,0 +1,80 @@
{ lib, config, pkgs, ... }:
{
imports = [
<system/server>
./hardware-configuration.nix
./bepasty.nix
./castget.nix
./gogs.nix
./grafana.nix
./graylog.nix
./jenkins.nix
./kibana.nix
./lektor-gaykraft.nix
./lektor-techblog.nix
./lektor-terranix.nix
./mail-fetcher.nix
./packages.nix
./prometheus.nix
./restic.nix
./seafile.nix
./syncthing.nix
./taskserver.nix
./tinc.nix
./transmission.nix
./weechat.nix
./wetten.nix
];
networking.hostName = "workhorse";
# enable initrd ssh
configuration.init-ssh = {
enable = "enabled";
kernelModules = [ "r8169" ];
authorizedKeys = config.users.users.root.openssh.authorizedKeys.keyFiles;
hostECDSAKey = <secrets/init-ssh/host_ecdsa_key>;
};
# nix-shell -p speedtest_cli --run speedtest
configuration.fireqos = {
enable = true;
interface = "eth0";
input = 30000;
output = 2000;
balance = false;
};
security.wrappers = {
pmount.source = "${pkgs.pmount}/bin/pmount";
pumount.source = "${pkgs.pmount}/bin/pumount";
};
services.logind.lidSwitch = lib.mkForce "ignore";
system.custom.x11.enable = lib.mkForce false;
programs.custom.steam.enable = false;
programs.custom.video.enable = false;
# font
# ----
programs.custom.urxvt.fontSize = 17;
programs.custom.xterm.fontSize = 17;
system.custom.fonts.dpi = 140;
services.printing.enable = true;
nix.useSandbox = true;
virtualisation = {
docker.enable = true;
virtualbox = {
host.enable = true;
guest.x11 = true;
guest.enable = true;
};
};
}

View File

@ -0,0 +1,8 @@
{ config, lib, pkgs, ... }:
{
module.backup.services.encfs = {
"fotos".enable = true;
"desktop".enable = true;
"finance".enable = true;
};
}

View File

@ -0,0 +1,39 @@
{ config, lib, ... }:
{
services.nginx = {
enable = true;
statusPage = true;
virtualHosts = {
"gogs.${config.networking.hostName}.private" = {
serverAliases = ["git.${config.networking.hostName}.private"];
locations."/" = {
proxyPass = "http://${config.networking.hostName}.private:${toString config.services.gogs.httpPort}";
};
};
};
};
services.gogs = {
enable = true;
appName = "Kruck GoGs";
domain = "git.ingolf-wagner.de";
httpPort = 3000;
repositoryRoot = "/home/gogs/repositories";
stateDir = "/home/gogs";
rootUrl = "https://git.ingolf-wagner.de/";
extraConfig = ''
[service]
DISABLE_REGISTRATION = true
SHOW_REGISTRATION_BUTTON = false
[server]
SSH_DOMAIN = "git.ingolf-wagner.de"
SSH_PORT = 443
START_SSH_SERVER = true
SSH_LISTEN_PORT = 2222
'';
};
backup.all.restic.dirs = [ config.services.gogs.repositoryRoot ];
}

View File

@ -0,0 +1,38 @@
{ config, ... }:
{
services.nginx = {
enable = true;
statusPage = true;
virtualHosts = {
"grafana.${config.networking.hostName}.private" = {
serverAliases = [];
locations."/" = {
proxyPass = "http://${config.networking.hostName}.private:${toString config.services.grafana.port}";
};
};
};
};
services.grafana = {
enable = true;
port = 5656;
addr = config.module.cluster.services.tinc."private".hosts."${config.networking.hostName}".tincIp;
auth.anonymous = {
enable = true;
org_role = "Editor";
org_name = "AWESOME";
};
provision = {
enable = true;
datasources = [
{
type = "prometheus";
isDefault = true;
name = "Prometheus Workhorse";
url = "http://workhorse.private:9090";
}
];
};
};
}

View File

@ -0,0 +1,100 @@
{ config, lib, pkgs, ... }:
let
port = 9000;
in
{
# configure nginx
services.nginx = {
enable = true;
virtualHosts = {
"graylog.workhorse.private" = {
locations."/" = {
proxyPass = "http://localhost:${toString port}";
extraConfig = ''
proxy_set_header Host $host:$server_port;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_read_timeout 90;
proxy_redirect http://localhost:${toString port} https://graylog.workhorse.private/;
'';
};
};
};
};
services.elasticsearch.enable = true;
services.mongodb.enable = true;
services.graylog.enable = true;
services.graylog.elasticsearchHosts = [ "http://${config.services.elasticsearch.listenAddress}:9200" ];
# https://docs.graylog.org/en/3.0/pages/configuration/server.conf.html
services.graylog.extraConfig = ''
http_bind_address = 0.0.0.0:${toString port}
http_publish_uri = http://workhorse.private:${toString port}/
'';
# other wise this does not work
services.graylog.nodeIdFile = "/var/lib/graylog/node-id";
# pwgen -N 1 -s 96
services.graylog.passwordSecret = lib.fileContents <secrets/graylog/password-secret>;
# echo -n yourpassword | shasum -a 256
services.graylog.rootPasswordSha2 = lib.fileContents <secrets/graylog/root-password-hash>;
environment.etc."graylog/server/GeoLite2-City.mmdb" = {
enable = true;
source = "${pkgs.geodatabase}/GeoLite2-City.mmdb";
};
# https://wiki.splunk.com/Http_status.csv
environment.etc."graylog/server/httpCodes.csv" = {
enable = true;
text = ''
status,status_description,status_type
100,Continue,Informational
101,Switching Protocols,Informational
200,OK,Successful
201,Created,Successful
202,Accepted,Successful
203,Non-Authoritative Information,Successful
204,No Content,Successful
205,Reset Content,Successful
206,Partial Content,Successful
300,Multiple Choices,Redirection
301,Moved Permanently,Redirection
302,Found,Redirection
303,See Other,Redirection
304,Not Modified,Redirection
305,Use Proxy,Redirection
307,Temporary Redirect,Redirection
400,Bad Request,Client Error
401,Unauthorized,Client Error
402,Payment Required,Client Error
403,Forbidden,Client Error
404,Not Found,Client Error
405,Method Not Allowed,Client Error
406,Not Acceptable,Client Error
407,Proxy Authentication Required,Client Error
408,Request Timeout,Client Error
409,Conflict,Client Error
410,Gone,Client Error
411,Length Required,Client Error
412,Precondition Failed,Client Error
413,Request Entity Too Large,Client Error
414,Request-URI Too Long,Client Error
415,Unsupported Media Type,Client Error
416,Requested Range Not Satisfiable,Client Error
417,Expectation Failed,Client Error
500,Internal Server Error,Server Error
501,Not Implemented,Server Error
502,Bad Gateway,Server Error
503,Service Unavailable,Server Error
504,Gateway Timeout,Server Error
505,HTTP Version Not Supported,Server Error
'';
};
}

View File

@ -0,0 +1,98 @@
{ config, lib, pkgs, ... }:
let
mainUserHome = "/home/palo";
in
{
# grub configuration
# ------------------
boot.loader.grub = {
device = "/dev/sda";
enable = true;
version = 2;
};
# lvm volume group
# ----------------
boot.initrd.luks.devices = [
{
name = "vg";
device = "/dev/sda2";
preLVM = true;
}
];
# NTFS support
# ------------
environment.systemPackages = [
pkgs.ntfs3g
];
# root
# ----
fileSystems."/" = {
options = [ "noatime" "nodiratime" "discard" ];
device = "/dev/vg/root";
fsType = "ext4";
};
# boot
# ----
fileSystems."/boot" = {
device = "/dev/sda1";
fsType = "ext4";
};
# home
# ----
fileSystems."/home" = {
options = [ "noatime" "nodiratime" ];
device = "/dev/mapper/decrypted_home";
fsType = "ext4";
encrypted = {
enable = true;
keyFile = "/mnt-root/root/keys/home.key";
label = "decrypted_home";
blkDev = "/dev/mapper/store-home";
};
};
# var/lib/docker
# --------------
fileSystems."/var/lib/docker" = {
options = [ "noatime" "nodiratime" ];
device = "/dev/mapper/decrypted_docker";
fsType = "ext4";
encrypted = {
enable = true;
keyFile = "/mnt-root/root/keys/docker.key";
label = "decrypted_docker";
blkDev = "/dev/mapper/store-docker";
};
};
# automount
# ---------
fileSystems."/media" = {
device = "/dev/disk/by-uuid/f7fa1c0e-ac9f-4955-b4bd-644c1ddb0d89";
fsType = "ext4";
options = [
"nofail"
"noauto"
#"x-systemd.device-timeout=1ms"
];
};
systemd.mounts = [
{
enable = true;
options = "nofail,noauto";
type = "ext4";
wantedBy = ["multi-user.target"];
what = "/dev/disk/by-uuid/f7fa1c0e-ac9f-4955-b4bd-644c1ddb0d89";
where = "/media";
}
];
}

View File

@ -0,0 +1,239 @@
{ config, lib, pkgs, ... }:
with lib;
let
library = import <library> { inherit pkgs lib; };
sync-repo = library.jenkins.syncJob;
job = library.jenkins.job;
in {
environment.systemPackages = [ pkgs.cabal-install ];
services.nginx = {
enable = true;
virtualHosts = {
"jenkins.${config.networking.hostName}.private" = {
locations."/" = {
proxyPass = "http://localhost:${toString config.services.jenkins.port}";
extraConfig = ''
proxy_set_header Host $host:$server_port;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_read_timeout 90;
proxy_redirect http://localhost:${toString config.services.jenkins.port} https://jenkins.${config.networking.hostName}.private/;
'';
};
};
};
};
krops.userKeys."accessToken" = {
user = "jenkins";
source = toString <secrets/jenkins/accessToken>;
requiredBy = [ "jenkins-job-builder.service" ];
};
services.jenkins = {
enable = true;
home = "/home/jenkins";
port = 10420;
# Plugins to Install:
# - all the plugins recommended at the setup
# - Build pipeline
# - SSH Agent
jobBuilder = {
enable = true;
# create an access token in the admin users panel
accessTokenFile = config.krops.userKeys."accessToken".target;
accessUser = "admin";
# https://docs.openstack.org/infra/jenkins-job-builder/definition.html#modules
nixJobs =
let
# ssh username + key
gogs-id = "bc584c99-0fb7-43fb-af75-4076d64c51b2";
# ssh username + key
github-id = "bc584c99-0fb7-43fb-af75-4076d64c51b2";
# ssh username + key
sshSputnik = "d91eb57c-5bff-434c-b317-68aad46848d7";
sync-to-github =
name: source: target:
sync-repo name
{
url = source;
credentialsId = gogs-id;
}
{
url = target;
credentialsId = github-id;
};
in [
(job "deploy-gaykraft"
{ url = "ssh://gogs@workhorse.private:2222/palo/gaykraft.git";
credentialsId = gogs-id; }
[
{ "build" = [
"nix-shell --run build"
];
}
{ "publish" = [
{
script = "nix-shell --run publish";
credentialsId = sshSputnik;
}
];
}
]
)
(job "deploy-techblock"
{ url = "ssh://gogs@workhorse.private:2222/palo/tech.ingolf-wagner.de.git";
credentialsId = gogs-id; }
[
{ "build" = ["nix-shell --run build"];}
{ "publish" = [
{
script = "nix-shell --run publish";
credentialsId = sshSputnik;
}
];}
])
(job "deploy-terranix"
{ url = "ssh://gogs@workhorse.private:2222/terranix/terranix.org.git";
credentialsId = gogs-id; }
[
{ "build" = ["nix-shell --run build"];}
{ "publish" = [
{
script = "nix-shell --run publish";
credentialsId = sshSputnik;
}
];}
])
(job "sync-retiolum"
{ url = "git@github.com:krebs/retiolum.git";
credentialsId = github-id;
triggers = [ { timed = "H/30 * * * *"; } ];}
[
{ "Download Files" = [
''chmod 755 hosts''
''chmod 755 -R hosts''
''nix-shell -p curl -p gnutar -p bzip2 --run "curl https://lassul.us/retiolum-hosts.tar.bz2 | tar xvjf - || true"''
''chmod 755 -R etc.hosts''
''nix-shell -p curl --run "curl https://lassul.us/retiolum.hosts > etc.hosts || true"''
];}
{ "update repo" = [
''nix-shell -p git --run "git add ."''
''nix-shell -p git --run "git -c user.name=\'Ingolf Wagner\' -c user.email=\'contact@ingolf-wagner.de\' commit -m update-`date +%Y-%m-%dT%H:%M:%S` || exit 0"''
];}
{ Push = [
{ script = ''nix-shell -p git --run "git push origin master"'';
credentialsId = github-id; }
];}
])
(job "test-terranix"
{ url = "ssh://gogs@workhorse.private:2222/terranix/terranix.git";
credentialsId = github-id;
branch = "develop";}
[
{ "run Tests" = [
''nix-shell tests/shell.nix --run "test-terranix"''
];}
])
(job "test-taskninja"
{ url = "ssh://gogs@workhorse.private:2222/palo/taskninja.git";
credentialsId = gogs-id; }
[
{ "Create Shell" = [
''nix-shell -p cabal2nix --run "cabal2nix --shell file://. > jenkins.nix"''
];}
{ Update = [
''nix-shell ./jenkins.nix --run "cabal update"''
];}
{ Configure = [
''nix-shell ./jenkins.nix --run "cabal configure --enable-tests"''
''nix-shell ./jenkins.nix --run "cabal install --only-dependencies"''
];}
{ Build = [
''nix-shell ./jenkins.nix --run "cabal build"''
];}
{ Test = [
''nix-shell ./jenkins.nix --run "cabal test"''
];}
])
# sync to me
# ----------
(sync-to-github "sync-nixwriters"
"https://cgit.krebsco.de/nix-writers/"
"ssh://gogs@workhorse.private:2222/krebs/nix-writers.git")
(sync-to-github "sync-krops"
"https://cgit.krebsco.de/krops/"
"ssh://gogs@workhorse.private:2222/krebs/krops.git")
# sync to github
# --------------
(sync-to-github "sync-radiodj"
"ssh://gogs@workhorse.private:2222/crashburn_radio/radio_dj.git"
"git@github.com:crashburn-radio/radio-dj.git")
(sync-to-github "sync-krops-module"
"ssh://gogs@workhorse.private:2222/nix-modules/krops.git"
"git@github.com:mrVanDalo/module.krops.git")
(sync-to-github "sync-cluster-module"
"ssh://gogs@workhorse.private:2222/nix-modules/cluster.git"
"git@github.com:mrVanDalo/module.cluster.git")
(sync-to-github "sync-backup-module"
"ssh://gogs@workhorse.private:2222/nix-modules/backup.git"
"git@github.com:mrVanDalo/module.backup.git")
(sync-to-github "sync-module-tinc"
"ssh://gogs@workhorse.private:2222/palo/nixos-tinc.git"
"git@github.com:mrVanDalo/nixos-tinc.git")
(sync-to-github "sync-memo"
"ssh://gogs@workhorse.private:2222/palo/memo.git"
"git@github.com:mrVanDalo/memo.git")
(sync-to-github "sync-diagrams-template"
"ssh://gogs@workhorse.private:2222/palo/diagrams-template.git"
"git@github.com:mrVanDalo/diagrams.git")
(sync-to-github "sync-terranix"
"ssh://gogs@workhorse.private:2222/terranix/terranix.git"
"git@github.com:mrVanDalo/terranix.git")
(sync-to-github "sync-plops"
"ssh://gogs@workhorse.private:2222/palo/plops.git"
"git@github.com:mrVanDalo/plops.git")
(sync-to-github "sync-image-generator"
"ssh://gogs@workhorse.private:2222/palo/image-generator.git"
"git@github.com:mrVanDalo/image-generator.git")
];
};
};
}

View File

@ -0,0 +1,24 @@
{ config, ... }:
{
services.nginx = {
enable = true;
statusPage = true;
virtualHosts = {
"kibana.${config.networking.hostName}.private" = {
serverAliases = [];
locations."/" = {
proxyPass = "http://${config.networking.hostName}.private:${toString config.services.kibana.port}";
};
};
};
};
services.elasticsearch.enable = true;
services.elasticsearch.listenAddress = "workhorse.private";
services.kibana.enable = true;
services.kibana.elasticsearch.hosts = [ "http://workhorse.private:9200" ];
services.kibana.listenAddress = "workhorse.private";
services.kibana.port = 5601;
}

View File

@ -0,0 +1,54 @@
{ config, pkgs, lib, ... }:
let
containerName = "gaykraft";
port = 5001;
repository = "ssh://gogs@git.ingolf-wagner.de:443/palo/gaykraft.git";
sshKey = toString <secrets/lektor/gaykraft>;
in {
services.nginx = {
enable = true;
statusPage = true;
virtualHosts = {
"${containerName}.${config.networking.hostName}.private" = {
serverAliases = [];
locations."/" = {
proxyPass = "http://${config.networking.hostName}.private:${toString port}";
};
};
};
};
containers.${containerName} = {
bindMounts = {
"/var/src" = {
hostPath = toString "/var/src/";
isReadOnly = true;
};
};
autoStart = true;
config =
{ config, pkgs, ... }:
{
imports = [ <system/all> ];
services.lektor = {
enable = true;
host = "git.ingolf-wagner.de";
sshKey = sshKey;
repository = repository;
port = port;
additionalScript = pkgs.writeScript "build" "${pkgs.nix}/bin/nix-shell --run build";
};
};
};
# it might take some time will this thing is up
systemd.services."container@${containerName}".serviceConfig.TimeoutStartSec = lib.mkForce "infinity";
}

View File

@ -0,0 +1,54 @@
{ config, pkgs, lib, ... }:
let
containerName = "techblog";
port = 5002;
repository = "ssh://gogs@git.ingolf-wagner.de:443/palo/tech.ingolf-wagner.de.git";
sshKey = toString <secrets/lektor/techblog>;
in {
services.nginx = {
enable = true;
statusPage = true;
virtualHosts = {
"${containerName}.${config.networking.hostName}.private" = {
serverAliases = [];
locations."/" = {
proxyPass = "http://${config.networking.hostName}.private:${toString port}";
};
};
};
};
containers.${containerName} = {
bindMounts = {
"/var/src" = {
hostPath = toString "/var/src/";
isReadOnly = true;
};
};
autoStart = true;
config =
{ config, pkgs, ... }:
{
imports = [ <system/all> ];
services.lektor = {
enable = true;
host = "git.ingolf-wagner.de";
sshKey = sshKey;
repository = repository;
port = port;
additionalScript = pkgs.writeScript "build" "${pkgs.nix}/bin/nix-shell --run build";
};
};
};
# it might take some time will this thing is up
systemd.services."container@${containerName}".serviceConfig.TimeoutStartSec = lib.mkForce "infinity";
}

View File

@ -0,0 +1,54 @@
{ config, pkgs, lib, ... }:
let
containerName = "terranix";
port = 5003;
repository = "ssh://gogs@git.ingolf-wagner.de:443/terranix/terranix.org.git";
sshKey = toString <secrets/lektor/terranix>;
in {
services.nginx = {
enable = true;
statusPage = true;
virtualHosts = {
"${containerName}.${config.networking.hostName}.private" = {
serverAliases = [];
locations."/" = {
proxyPass = "http://${config.networking.hostName}.private:${toString port}";
};
};
};
};
containers.${containerName} = {
bindMounts = {
"/var/src" = {
hostPath = toString "/var/src/";
isReadOnly = true;
};
};
autoStart = true;
config =
{ config, pkgs, ... }:
{
imports = [ <system/all> ];
services.lektor = {
enable = true;
host = "git.ingolf-wagner.de";
sshKey = sshKey;
repository = repository;
port = port;
additionalScript = pkgs.writeScript "build" "${pkgs.nix}/bin/nix-shell --run build";
};
};
};
# it might take some time will this thing is up
systemd.services."container@${containerName}".serviceConfig.TimeoutStartSec = lib.mkForce "infinity";
}

View File

@ -0,0 +1,292 @@
# fetches mails for me
{ lib, pkgs, config, ... }:
{
users.users.mailUser = {
isNormalUser = true;
description = "collects mails for me";
hashedPassword = "!";
name = "mailfetcher";
openssh.authorizedKeys.keyFiles = config.users.users.root.openssh.authorizedKeys.keyFiles;
};
# configure passwords
krops.userKeys = {
"gmail.palipalo9" = {
user = config.users.users.mailUser.name;
source = toString <secrets/mail/gmail/palipalo9>;
requiredBy = ["fetchmail.service"];
};
"gmx.palo_van_dalo" = {
user = config.users.users.mailUser.name;
source = toString <secrets/mail/gmx/palo_van_dalo>;
requiredBy = ["fetchmail.service"];
};
"gmx.ingolf_wagner" = {
user = config.users.users.mailUser.name;
source = toString <secrets/mail/gmx/ingolf.wagner>;
requiredBy = ["fetchmail.service"];
};
"web.pali_palo" = {
user = config.users.users.mailUser.name;
source = toString <secrets/mail/web.de/pali_palo>;
requiredBy = ["fetchmail.service"];
};
"siteground.contact" = {
user = config.users.users.mailUser.name;
source = toString <secrets/mail/siteground/contact>;
requiredBy = ["fetchmail.service"];
};
};
environment.systemPackages = [ pkgs.muchsync ];
# configure accounts
home-manager.users.mailUser.accounts.email = {
accounts = {
palo_van_dalo-gmx = {
primary = false;
address = "palo_van_dalo@gmx.de";
aliases = [ ];
realName = "Ingolf Wagner";
userName = "palo_van_dalo@gmx.de";
passwordCommand = "cat ${toString config.krops.userKeys."gmx.palo_van_dalo".target}";
imap = {
host = "imap.gmx.net";
port = 993;
};
mbsync = {
enable = true;
create = "both";
};
notmuch.enable = true;
};
ingolf-wagner-gmx = {
primary = false;
address = "ingolf.wagner@gmx.de";
aliases = [ ];
realName = "Ingolf Wagner";
userName = "ingolf.wagner@gmx.de";
passwordCommand = "cat ${toString config.krops.userKeys."gmx.ingolf_wagner".target}";
imap = {
host = "imap.gmx.net";
port = 993;
};
mbsync = {
enable = true;
create = "both";
};
notmuch.enable = true;
};
pali_palo = {
primary = false;
address = "pali_palo@web.de";
aliases = [ ];
realName = "Ingolf Wagner";
userName = "pali_palo@web.de";
passwordCommand = "cat ${toString config.krops.userKeys."web.pali_palo".target}";
imap = {
host = "imap.web.de";
port = 993;
};
mbsync = {
enable = true;
create = "both";
};
notmuch.enable = true;
};
gmail = {
# for google accounts you have to allow 'less secure apps' in accounts.google.com
primary = true;
address = "palipalo9@googlemail.com";
aliases = [ ];
realName = "Ingolf Wagner";
userName = "palipalo9@googlemail.com";
passwordCommand = "cat ${toString config.krops.userKeys."gmail.palipalo9".target}";
imap = {
host = "imap.gmail.com";
port = 993;
};
mbsync = {
enable = true;
create = "both";
};
notmuch.enable = true;
};
ingolf-wagner = {
primary = false;
address = "contact@ingolf-wagner.de";
aliases = [ ];
realName = "Ingolf Wagner";
userName = "contact@ingolf-wagner.de";
passwordCommand = "cat ${toString config.krops.userKeys."siteground.contact".target}";
imap = {
host = "securees5.sgcpanel.com";
port = 143;
tls.useStartTls = true;
};
mbsync = {
enable = true;
create = "both";
};
notmuch.enable = true;
};
};
};
# configure mbsync
home-manager.users.mailUser.programs.mbsync.enable = true;
systemd.services.fetchmail = {
enable = true;
serviceConfig = {
User = config.users.users.mailUser.name;
};
environment.NOTMUCH_CONFIG = "${config.users.users.mailUser.home}/.config/notmuch/notmuchrc";
script = ''
echo "run mbsync"
${pkgs.isync}/bin/mbsync \
--verbose \
--all
echo "run notmuch"
${pkgs.notmuch}/bin/notmuch new
echo "run afew"
${pkgs.afew}/bin/afew --new --tag -v
'';
};
systemd.timers.fetchmail = {
enable = true;
# timerConfig.OnCalendar = " *-*-* *:00:00";
timerConfig.OnCalendar = "*:0/10";
wantedBy = ["multi-user.target"];
};
# configure notmuch
home-manager.users.mailUser.programs.notmuch = {
enable = true;
new.tags = [ "unread" "inbox" "new" ];
};
home-manager.users.mailUser.home.file."notmuch" = {
source = "${config.users.users.mailUser.home}/.config/notmuch/notmuchrc";
target = ".notmuch-config";
};
# a few config
home-manager.users.mailUser.programs.afew = {
enable = true;
extraConfig = with lib; let
template = index: { tags, query, message ? "generic", ... }: ''
[Filter.${toString index}]
query = ${query}
tags = ${concatStringsSep ";" tags}
message = ${message}
'';
filters = [
{query = "from:no-reply@backtrace.io"; tags = ["+sononym" "-inbox" "-unread"];}
{query = "from:linkedin.com"; tags = [ "+linked" "+jobs" "-inbox" ];}
{query = "from:computerfutures.com OR from:computerfutures.de"; tags = [ "+jobs" "-inbox" ];}
{query = "from:xing.com"; tags = [ "+jobs" "-inbox" ];}
{query = "from:ebay.com OR from:ebay.de OR from:ebay.net"; tags = [ "+ebay" "+shop" "+billing"];}
{query = "from:seek.com.au"; tags = [ "+jobs" "-inbox" ];}
{query = "from:bahn.de"; tags = [ "+billing" "+bahn" ];}
{query = "from:fysitech.atlassian.net OR to:engiadina-pwa@noreply.github.com"; tags = [ "+mia" "+work" "-unread" "-inbox"];}
{query = "from:circleci.com OR (from:noreply@github.com AND to:audio-overlay@googlegroups.com)"; tags = [ "-inbox" "-unread" "+junk" ];}
{query = "from:getdigital.de"; tags = [ "-inbox" "-unread" "+junk" ];}
{query = "from:digitalo.de"; tags = [ "-inbox" "-unread" "+junk" ];}
{query = "from:puppet.com"; tags = [ "-inbox" "-unread" "+junk" ];}
{query = "from:mixcloudmail.com AND subject:Weekly Update"; tags = [ "-inbox" "-unread" "+junk" ];}
{query = "from:facebook.com OR from:facebookmail.com"; tags = [ "-inbox" "-unread" "+junk" ];}
{query = "from:getpocket.com"; tags = [ "-inbox" "-unread" "+junk" ];}
{query = "from:oknotify2.com"; tags = [ "+okcupid" ];}
{query = "from:oknotify2.com AND NOT subject:New message"; tags = [ "-inbox" "-unread" "+junk" ];}
{query = "from:paulaschoice.com"; tags = [ "-inbox" "-unread" "+junk" ];}
{query = "from:samplemagic.com OR from:wavealchemy.co.uk OR from:creators.gumroad.com"; tags = [ "-inbox" "-unread" "+junk" ];}
{query = "from:immobilienscout24.de"; tags = [ "-inbox" "-unread" "+junk" ];}
{query = "from:magix.net"; tags = [ "-inbox" "-unread" "+junk" ];}
{query = "from:booking.com"; tags = [ "-inbox" "-unread" "+junk" ];}
{query = "from:hackster.io"; tags = [ "-inbox" "-unread" "+junk" ];}
{query = "from:trade4less.de"; tags = [ "-inbox" "-unread" "+junk" ];}
{query = "from:taxback.de OR to:taxback.de"; tags = ["+steuer"] ;}
{query = "from:campact.de"; tags = ["+campact" "+politics"] ;}
{query = "from:menospese.com"; tags = ["+junk" "-unread" "-inbox"] ;}
{query = "from:aliexpress.com"; tags = ["+shop" "+aliexpress"] ;}
{query = "from:congstar.de"; tags = ["+billing" "+congstar" "-inbox" "-unread"] ;}
{query = "from:congstarnews.de"; tags = ["+congstar" "-inbox" "-unread" "+junk"] ;}
{query = "from:fitnessfirst.de"; tags = ["-inbox" "-unread" "+junk"] ;}
{query = "from:steampowered.com AND NOT ( subject:purchase OR subject:received )"; tags = ["-inbox" "-unread" ] ;}
{query = "from:steampowered.com AND ( subject:purchase OR subject:received )"; tags = ["+billing" "+steam" ] ;}
{query = "from:gog.com AND NOT subject:Bestellung"; tags = ["-inbox" "-unread" ] ;}
{query = "from:gog.com AND subject:Bestellung"; tags = ["+billing" "+gog" ] ;}
{query = "from:drive-now.com"; tags = ["+billing" "+drivenow" "-inbox" "-unread"] ;}
{query = "from:mindfactory.de"; tags = ["+shop" "+billing"] ;}
{query = "from:zalando.de"; tags = ["+shop" "+billing" "+zalando"] ;}
{query = "from:ing.de"; tags = ["+bank" "+ingdiba"] ;}
{query = "from:nab.com.au"; tags = ["+bank" "+nab" "-inbox" "-unread"] ;}
{query = "from:dkb.de"; tags = ["+bank" "+dkb"] ;}
{query = "from:o2online.de"; tags = ["+billing" "+o2"] ;}
{query = "from:betfair.com"; tags = ["+work" "+betfair"] ;}
{query = "from:ghostinspector.com"; tags = ["-unread" "-inbox" "+junk"] ;}
{query = "from:travis-ci.org AND subject:csv-to-qif"; tags = ["+development" "+csv-to-qif"] ;}
{query = "to:proaudio@lists.tuxfamily.org"; tags = ["-inbox" "-unread"] ;}
{query = "tag:lists AND from:nixos1@discoursemail.com"; tags = ["+nixos" "+discourse"] ;}
{query = "from:limebike.com AND (subject:Funds OR subject:Receipt)" ; tags = ["-inbox" "-unread" "+billing" "+limebike"] ;}
{query = "from:hetzner.com OR from:hetzner.de" ; tags = ["+hetzner"] ;}
{query = "from:freemusicarchive.org" ; tags = ["+FMA"] ;}
{query = "from:namecheap.com" ; tags = ["+namecheap" "+billing"] ;}
{query = "from:nintendo.com" ; tags = ["+nintendo" "+billing"] ;}
{query = "from:oculus.com AND subject:receipt" ; tags = ["+oculus" "+billing"] ;}
{query = "from:vstbuzz.com" ; tags = ["+junk" "-inbox" ] ;}
{query = "from:runtastic.com" ; tags = ["+junk" "-inbox" ] ;}
{query = "from:letterboxd.com" ; tags = ["+junk" "-inbox" ] ;}
{query = "from::microsoftstoreemail.com" ; tags = ["+junk" "-inbox" ] ;}
{query = "from:car2go.com" ; tags = ["-inbox" "-unread" ] ;}
{query = "from:sixt.de" ; tags = ["-inbox" "-unread" ] ;}
{query = "from:meetup.com" ; tags = ["-inbox" "-unread" "+meetup"] ;}
{query = "from:slack.com" ; tags = ["+slack"] ;}
{query = "from:keybase.io" ; tags = ["+keybase"] ;}
{query = "from:tumblr.com" ; tags = ["+junk" "-inbox" "-unread"];}
{query = "from:jobs2web.com" ; tags = ["+newzealand" "+jobs" "-inbox" ];}
{query = "from:mailings.gmx.net" ; tags = ["+junk" "-inbox" "-unread"];}
{query = "from:paypal.de AND subject:Bestätigung"; tags = ["-unread" "+paypal" "+billing"] ;}
{query = "to:renoise@ingolf-wagner.de OR to:root@renoise.com OR from:renoise.com OR to:admin@renoise.com"; tags = ["+renoise"] ;}
{query = "from:amazon.de OR from:amazon.com AND NOT to:renoise.com"; tags = ["+shop" "+amazon" "+billing"];}
{
query = "to:renoise.com AND NOT ( from:renoise.com OR from:root OR from:hetzner.com OR from:hetzner.de OR from:amazon.com OR from:gmail.com )";
tags = [ "-inbox" "-unread" "+junk" "+renoise" ];
}
# final rules to make imap sync stuff easier
# there can only be one output folder tag, and theses rules are prioritized
{ query = "tag:fraud" ; tags = ["-inbox" "-archive" "-junk" "-unread" ]; message = "clean up tag fraud";}
{ query = "tag:junk" ; tags = ["-inbox" "-archive" "-fraud" "-unread" ]; message = "clean up tag junk";}
{ query = "tag:archive" ; tags = ["-inbox" "-junk" "-fraud" "-unread" ]; message = "clean up tag archive";}
{ query = "tag:inbox" ; tags = ["-archive" "-junk" "-fraud"]; message = "clean up inbox";}
{ query = "tag:killed"; tags = ["-inbox" "-unread"]; message = "clean up tag killed" ;}
# remove new tag at the end
{ query = "tag:new"; tags = ["-new"]; message = "remove new tag at the end" ;}
];
in
''
# Tag mails which are mailing lists
[ListMailsFilter]
# Tag mails as killed if the thread has been marked as "killed"
[KillThreadsFilter]
${concatStringsSep "\n" (imap0 template filters)}
'';
};
}

View File

@ -0,0 +1,7 @@
{ config, pkgs, ... }:
let
unstable = import <nixpkgs-unstable> {};
in {
environment.systemPackages = with pkgs ; [
];
}

View File

@ -0,0 +1,107 @@
{ config, pkgs, lib, ... }:
{
services.nginx = {
enable = true;
statusPage = true;
virtualHosts = {
"prometheus.workhorse.private" = {
locations."/" = {
proxyPass = "http://workhorse.private:9090";
};
};
};
};
services.prometheus2 = {
enable = true;
scrapeConfigs = [
{
job_name = "nginx";
scrape_interval = "8s";
static_configs = [
{
targets = ["sputnik.private:9113"];
labels = {
service = "nginx";
server = "sputnik";
};
}
{
targets = ["sputnik.private:9113"];
labels = {
service = "nginx";
server = "sputnik";
};
}
{
targets = ["workhorse.private:9113"];
labels = {
service = "nginx";
server = "sputnik";
};
}
];
}
{
job_name = "netdata";
metrics_path = "/api/v1/allmetrics";
params.format = [ "prometheus" ];
scrape_interval = "5s";
static_configs = [
{
targets = ["porani.private:19999"];
labels = {
service = "netdata";
server = "porani";
};
}
{
targets = ["sputnik.private:19999"];
labels = {
service = "netdata";
server = "sputnik";
};
}
{
targets = ["workhorse.private:19999"];
labels = {
service = "netdata";
server = "workhorse";
};
}
];
}
{
job_name = "gogs";
metrics_path = "/-/metrics";
params.format = [ "prometheus" ];
scrape_interval = "10s";
static_configs = [
{
targets = ["workhorse.private:3000"];
labels = {
service = "gogs";
server = "kruck";
};
}
];
}
{
job_name = "home-assistant";
scrape_interval = "60s";
metrics_path = "/api/prometheus";
static_configs = [
{
targets = ["porani.private:8123"];
labels = {
service = "hass";
server = "porani";
city = "essen";
};
}
];
}
];
};
}

View File

@ -0,0 +1,9 @@
{config, ... }:
{
backup.services.restic = {
"on-porani".enable = false;
"on-workhorse".enable = true;
};
}

View File

@ -0,0 +1,26 @@
{ config, lib, pkgs, ... }:
{
services.nginx = {
enable = true;
statusPage = true;
virtualHosts = {
"seafile.${config.networking.hostName}.private" = {
serverAliases = [];
locations."/" = {
proxyPass = "http://${config.networking.hostName}.private:${toString config.custom.services.seafile.port}";
};
};
};
};
custom.services.seafile = {
enable = true;
hostname = "seafile.gaykraft.com";
port = 3030;
home = "/home/seafile";
};
virtualisation.docker.enable = lib.mkDefault true;
}

View File

@ -0,0 +1,53 @@
{ config, pkgs, lib, ... }:
{
test.services.syncthing = {
enable = true;
openDefaultPorts = false;
dataDir = "/home/syncthing";
configDir = "/home/syncthing";
declarative = {
cert = toString <secrets/syncthing/cert.pem>;
key = toString <secrets/syncthing/key.pem>;
overrideFolders = true;
folders = {
# todo add podcast here
# on encrypted hard drive
# -----------------------
desktop-encrypted.path = "/home/syncthing/.desktop.ct";
finance-encrypted.path = "/home/syncthing/.finance.ct";
fotos-encrypted.path = "/home/syncthing/private/.fotos.ct";
music-projects.path = "/home/syncthing/music-projects";
video-material.path = "/home/syncthing/video-material";
# on media hard drive (not encrypted)
# -----------------------------------
music-library-free.path = "/media/syncthing/music-library-free";
samples.path = "/media/syncthing/samples";
movies.path = "/media/syncthing/movies";
music-library.path = "/media/syncthing/music-library";
podcasts.path = "/media/syncthing/podcasts";
series.path = "/media/syncthing/series";
};
};
};
systemd.services."permown._media_syncthing" = {
bindsTo = [ "media.mount" ];
after = [ "media.mount" ];
};
system.permown."/media/syncthing" = {
owner = "syncthing";
group = "syncthing";
umask = "0007";
};
systemd.services."syncthing" = {
bindsTo = [ "media.mount" ];
after = [ "media.mount" ];
};
}

View File

@ -0,0 +1,14 @@
{ config, lib, pkgs, ... }:
{
services.taskserver = {
enable = true;
fqdn = "workhorse.private";
listenHost = "0.0.0.0";
requestLimit = 104857600;
trust = "allow all";
dataDir = "/var/lib/taskserver";
organisations."orgie".users = ["palo"];
};
}

View File

@ -0,0 +1,16 @@
{ config, lib, pkgs, ... }:
{
module.cluster.services.tinc = {
"private" = {
enable = true;
openPort = true;
connectTo = [ "sputnik" ];
};
"retiolum" = {
enable = true;
openPort = true;
};
};
}

View File

@ -0,0 +1,45 @@
{ config, lib, ... }:
with lib;
let
allTincNetworks =
builtins.attrNames config.module.cluster.services.tinc;
ipAddresses =
flatten (mapAttrsToList (_: data:
mapAttrsToList (_: hostConfig: hostConfig.tincIp) data.hosts)
config.module.cluster.services.tinc);
in {
services.nginx = {
enable = true;
statusPage = true;
virtualHosts = {
"transmission.${config.networking.hostName}.private" = {
serverAliases = ["torrent.${config.networking.hostName}.private"];
locations."/" = {
proxyPass = "http://${config.networking.hostName}.private:${toString config.services.transmission.port}";
};
};
};
};
networking.firewall = {
allowedTCPPorts = [ config.services.custom.transmission.port ];
allowedUDPPorts = [ config.services.custom.transmission.port ];
};
services.custom.transmission = {
enable = true;
home = "/home/torrent";
store = "/home/torrent";
hosts = concatStringsSep "," (map (name: "${config.networking.hostName}.${name}") allTincNetworks);
whitelist = concatStringsSep "," ipAddresses;
user = "palo";
password = lib.fileContents <secrets/transmission/password>;
};
}

View File

@ -0,0 +1,20 @@
{ config, pkgs, lib, ... }:
# how to setup a relay
# * ssh on the maching
# * sudo -u weechat screen -r
# /set relay.network.password "mypassword"
# /relay add weechat 10000
{
services.weechat = {
enable = true;
};
# otherwise xterm is the only thing that works
environment.systemPackages = [ pkgs.rxvt_unicode ];
backup.all.restic.dirs = [ config.services.weechat.root ];
}

View File

@ -0,0 +1,40 @@
{ config, lib, pkgs , ... }:
{
imports = [
<wetten/nixos>
];
krops.userKeys."wetten_appkey" = {
user = "wetten";
source = toString <secrets/betfair/appkey>;
requiredBy = [ "wetten.service" ];
};
krops.userKeys."wetten_key" = {
user = "wetten";
source = <secrets/betfair/key>;
requiredBy = [ "wetten.service" ];
};
krops.userKeys."wetten_cert" = {
user = "wetten";
source = toString <secrets/betfair/cert>;
requiredBy = [ "wetten.service" ];
};
krops.userKeys."wetten_password" = {
user = "wetten";
source = toString <secrets/betfair/password>;
requiredBy = [ "wetten.service" ];
};
services.wetten = {
enable = true;
username = "palipalo9@googlemail.com";
passwordFile = config.krops.userKeys."wetten_password".target;
appKeyFile = config.krops.userKeys."wetten_appkey".target;
clientCert = config.krops.userKeys."wetten_cert".target;
clientCertKey = config.krops.userKeys."wetten_key".target;
};
}

View File

@ -0,0 +1,62 @@
{ lib, config, pkgs, ... }:
{
imports = [
<system/desktop>
./hardware-configuration.nix
#<system/server/netdata.nix>
./encfs.nix
./kibana.nix
./packages.nix
./slack.nix
./syncthing.nix
./tinc.nix
];
networking.hostName = "workout";
services.logind.lidSwitch = lib.mkForce "ignore";
security.wrappers = {
pmount.source = "${pkgs.pmount}/bin/pmount";
pumount.source = "${pkgs.pmount}/bin/pumount";
};
# nix-shell -p speedtest_cli --run speedtest
configuration.fireqos = {
enable = true;
interface = "wlp1s0";
input = 4200;
output = 1200;
balance = false;
};
programs.custom.steam.enable = true;
programs.custom.video.enable = true;
# font
# ----
programs.custom.urxvt.fontSize = 17;
programs.custom.xterm.fontSize = 17;
system.custom.fonts.dpi = 140;
services.printing.enable = true;
virtualisation = {
docker.enable = true;
virtualbox = {
host.enable = true;
guest.x11 = true;
guest.enable = true;
};
};
configuration.desktop = {
width = 2560;
height = 1440;
};
}

View File

@ -0,0 +1,8 @@
{ config, lib, pkgs, ... }:
{
module.backup.services.encfs = {
"fotos".enable = true;
"desktop".enable = true;
"finance".enable = true;
};
}

View File

@ -0,0 +1,61 @@
{ config, lib, pkgs, ... }:
let
mainUserHome = "/home/palo";
in
{
# fix fileSystems.<name>.encrypted - false overwrite
# --------------------------------------------------
boot.initrd.luks.cryptoModules = [ "aes" "aes_generic" "blowfish" "twofish" "serpent" "cbc" "xts" "lrw" "sha1" "sha256" "sha512" "aes_x86_64" ];
# todo : why should I use this here
boot.initrd.availableKernelModules = [ "xhci_pci" "ahci" "usb_storage" "sd_mod" ];
boot.kernelModules = [ "kvm-intel" ];
nix.maxJobs = lib.mkDefault 8;
# lvm volume group
# ----------------
boot.initrd.luks.devices = [
{
name = "vg";
device = "/dev/sda2";
preLVM = true;
}
];
# NTFS support
# ------------
environment.systemPackages = [
pkgs.ntfs3g
];
# root
# ----
fileSystems."/" = {
options = [ "noatime" "nodiratime" "discard" ];
device = "/dev/vg/root";
fsType = "ext4";
};
# boot
# ----
fileSystems."/boot" = {
device = "/dev/sda1";
fsType = "ext4";
};
boot.loader.grub = {
device = "/dev/sda";
enable = true;
version = 2;
};
# home
# ----
fileSystems."/home" = {
options = [ "noatime" "nodiratime" "discard" ];
device = "/dev/vg/home";
fsType = "ext4";
};
}

View File

@ -0,0 +1,23 @@
{ config, ... }:
{
services.nginx = {
enable = true;
statusPage = true;
virtualHosts = {
"kibana.${config.networking.hostName}.private" = {
serverAliases = [];
locations."/" = {
proxyPass = "http://${config.networking.hostName}.private:${toString config.services.kibana.port}";
};
};
};
};
services.elasticsearch.enable = true;
services.elasticsearch.listenAddress = "${config.networking.hostName}.private";
services.kibana.enable = true;
services.kibana.elasticsearch.hosts = [ "http://${config.networking.hostName}.private:9200" ];
services.kibana.listenAddress = "${config.networking.hostName}.private";
services.kibana.port = 5601;
}

View File

@ -0,0 +1,22 @@
{ config, pkgs, ... }:
let
unstable = import <nixpkgs-unstable> {};
in {
nixpkgs.config.packageOverrides = pkgs: {
nur = import (builtins.fetchTarball "https://github.com/nix-community/NUR/archive/master.tar.gz") {
inherit pkgs;
};
};
environment.systemPackages = with pkgs ; [
bitwig-studio
#unstable.pypi2nix
#nur.repos.mic92.nixos-shell
];
programs.custom.q = {
enableIntelBacklight = false;
enableBattery = false;
};
}

14
configs/workout/slack.nix Normal file
View File

@ -0,0 +1,14 @@
{ config, lib, pkgs, ... }:
{
programs.custom.slack = {
enable = true;
homeBackup = "~/desktop/slack";
};
programs.custom.browser.configList.google-chrome = {
inherit (config.programs.custom.browser.configList.development) home homeBackup user;
sudoUsers = [ "slack" ];
};
}

View File

@ -0,0 +1,40 @@
{ config, pkgs, lib, ... }:
{
test.services.syncthing = {
enable = true;
openDefaultPorts = false;
user = "palo";
dataDir = "/home/palo/.syncthing";
configDir = "/home/palo/.syncthing";
declarative = {
cert = toString <secrets/syncthing/cert.pem>;
key = toString <secrets/syncthing/key.pem>;
overrideFolders = true;
folders = {
book.path = "/home/palo/books";
desktop-encrypted.path = "/home/palo/.desktop.ct";
finance-encrypted.path = "/home/palo/.finance.ct";
fotos-encrypted.path = "/home/palo/private/.fotos.ct";
kruck-workout.path = "/home/palo/workout-kruck";
music-library-free.path = "/home/palo/music-library-free";
music-library.path = "/home/palo/music-library";
music-projects.path = "/home/palo/music-projects";
porani-workout.path = "/home/palo/workout-porani";
samples.path = "/home/palo/samples";
schasch-workout.path = "/home/palo/workout-schasch";
smartphone-fotos.path = "/home/palo/smartphone-fotos";
smartphone-music.path = "/home/palo/smartphone-music";
video-material.path = "/home/palo/video-material";
workout-pepe.path = "/home/palo/workout-pepe";
windows-sync.path = "/home/palo/windows-sync";
};
};
};
}

15
configs/workout/tinc.nix Normal file
View File

@ -0,0 +1,15 @@
{ config, lib, pkgs, ... }:
{
module.cluster.services.tinc = {
"private" = {
enable = true;
openPort = true;
connectTo = [ "sputnik" ];
};
"retiolum" = {
enable = true;
openPort = true;
};
};
}

View File

@ -0,0 +1,19 @@
# remote installation iso
* `./config.nix` : to generate the installation image
* `./remote-service.nix` : tor configuration you have to start on your machine.
## Steps
* import `./remote-service.nix` in your `/etc/nixos/configuration.nix`
* `nixos-rebuild switch`
* run `remote-install-get-hiddenReceiver` and enter the result in `./config.nix` as `hiddenReceiver`
* set the public key in `./config.nix`
* run `nixos-generate -f install-iso -c ./config.nix`
* prepare the usb stick : `sudo if=<path of the iso> of=/dev/<device> bs=4096`
* boot the usb-stick at the new machine
* run `remote-install-start-service`
* after some time you will see a you can use to login to the new machine.
Now you can do the normal installations procedure.

View File

@ -0,0 +1,142 @@
{ config, lib, pkgs, ... }:
let
# cat ~/.ssh/id_rsa.pub
publicSshKey = "";
# remote-install-get-hiddenReceiver
hiddenReceiver = "";
in {
imports = [
{ # system setup
networking.hostName = "liveos";
users.extraUsers = {
root = {
password = "lolhack";
openssh.authorizedKeys.keys = [
publicSshKey
];
};
};
environment.extraInit = ''
EDITOR=vim
'';
}
{ # installed packages
nixpkgs.config.allowUnfree = true;
environment.systemPackages = with pkgs; [
#style
most
rxvt_unicode.terminfo
#monitoring tools
htop
iotop
#network
iptables
iftop
nmap
#stuff for dl
aria2
#neat utils
pciutils
psmisc
tmux
usbutils
git
#unpack stuff
p7zip
unzip
unrar
#data recovery
ddrescue
ntfs3g
dosfstools
];
}
{ # bash configuration
programs.bash = {
enableCompletion = true;
interactiveShellInit = ''
HISTCONTROL='erasedups:ignorespace'
HISTSIZE=65536
HISTFILESIZE=$HISTSIZE
shopt -s checkhash
shopt -s histappend histreedit histverify
shopt -s no_empty_cmd_completion
complete -d cd
'';
promptInit = ''
if test $UID = 0; then
PS1='\[\033[1;31m\]\w\[\033[0m\] '
PROMPT_COMMAND='echo -ne "\033]0;$$ $USER@$PWD\007"'
elif test $UID = 1337; then
PS1='\[\033[1;32m\]\w\[\033[0m\] '
PROMPT_COMMAND='echo -ne "\033]0;$$ $PWD\007"'
else
PS1='\[\033[1;33m\]\u@\w\[\033[0m\] '
PROMPT_COMMAND='echo -ne "\033]0;$$ $USER@$PWD\007"'
fi
if test -n "$SSH_CLIENT"; then
PS1='\[\033[35m\]\h'" $PS1"
PROMPT_COMMAND='echo -ne "\033]0;$$ $HOSTNAME $USER@$PWD\007"'
fi
'';
};
}
{ # ssh configuration
services.openssh.enable = true;
services.openssh.passwordAuthentication = false;
systemd.services.sshd.wantedBy = lib.mkForce [ "multi-user.target" ];
}
{ # network configuration
networking.networkmanager.enable = true;
networking.wireless.enable = lib.mkForce false;
}
{ # hidden ssh announce
config = let
torDirectory = "/var/lib/tor";
hiddenServiceDir = torDirectory + "/liveos";
in {
services.tor = {
enable = true;
client.enable = true;
extraConfig = ''
HiddenServiceDir ${hiddenServiceDir}
HiddenServicePort 22 127.0.0.1:22
'';
};
systemd.services.hidden-ssh-announce = {
description = "irc announce hidden ssh";
after = [ "tor.service" "network-online.target" ];
wants = [ "tor.service" ];
wantedBy = [ "multi-user.target" ];
serviceConfig = {
ExecStart = pkgs.writers.writeDash "irc-announce-ssh" ''
set -efu
until test -e ${hiddenServiceDir}/hostname; do
echo "still waiting for ${hiddenServiceDir}/hostname"
sleep 1
done
until ${pkgs.tor}/bin/torify ${pkgs.netcat-openbsd}/bin/nc -z ${hiddenReceiver} 1337; do sleep 1; done && \
echo "torify ssh root@$(cat ${hiddenServiceDir}/hostname) -i ~/.ssh/id_rsa" | ${pkgs.tor}/bin/torify ${pkgs.nmap}/bin/ncat ${hiddenReceiver} 1337
'';
PrivateTmp = "true";
User = "tor";
Type = "oneshot";
};
};
};
}
];
}

View File

@ -0,0 +1,20 @@
# installs scripts and tor to provide an announcement service for nixos-remote installation.
{
services.tor = {
enable = true;
client.enable = true;
hiddenServices.liveos.map = [
{ port = 1337; }
];
};
environment.systemPackages = [
(pkgs.writeShellScriptBin "remote-install-start-service" ''
echo "starting announcment server to receive remote-install iso onion id"
${pkgs.nmap}/bin/ncat -k -l -p 1337
'')
(pkgs.writeShellScriptBin "remote-install-get-hiddenReceiver" ''
sudo cat /var/lib/tor/onion/liveos/hostname
'')
];
}

64
images/yubikey-image.nix Normal file
View File

@ -0,0 +1,64 @@
# NixOS livesystem to generate yubikeys in an air-gapped manner
# screenshot: https://dl.thalheim.io/wmxIqucOEo2xuLk0Ut45fQ/yubikey-live-system.png
# $ nixos-generator -f iso -c yubikey-image.nix
{ pkgs, ... }: {
environment.interactiveShellInit = ''
export GNUPGHOME=/run/user/$(id -u)/gnupghome
if [ ! -d $GNUPGHOME ]; then
mkdir $GNUPGHOME
fi
cp ${pkgs.fetchurl {
url = "https://raw.githubusercontent.com/drduh/config/662c16404eef04f506a6a208f1253fee2f4895d9/gpg.conf";
sha256 = "118fmrsn28fz629y7wwwcx7r1wfn59h3mqz1snyhf8b5yh0sb8la";
}} "$GNUPGHOME/gpg.conf"
echo "\$GNUPGHOME has been set up for you. Generated keys will be in $GNUPGHOME."
'';
environment.systemPackages = with pkgs; [
yubikey-personalization
cryptsetup
pwgen
midori
paperkey
gnupg
haskellPackages.hopenpgp-tools
ctmg
];
services.udev.packages = with pkgs; [ yubikey-personalization ];
services.pcscd.enable = true;
users.extraUsers.root.initialHashedPassword = "";
# make sure we are air-gapped
networking.wireless.enable = false;
networking.dhcpcd.enable = false;
services.mingetty.helpLine = "The 'root' account has an empty password.";
services.xserver = {
enable = true;
displayManager.auto.enable = true;
desktopManager = let
guide = pkgs.stdenv.mkDerivation {
name = "yubikey-guide-2019-01-21.html";
src = pkgs.fetchFromGitHub {
owner = "drduh";
repo = "YubiKey-Guide";
rev = "035d98ebbed54a0218ccbf23905054d32f97508e";
sha256 = "0rzy06a5xgfjpaklxdgrxml24d0vhk78lb577l3z4x7a2p32dbyq";
};
buildInputs = [ pkgs.pandoc ];
installPhase = "pandoc --highlight-style pygments -s --toc README.md -o $out";
};
in {
default = "xfce";
xterm.enable = false;
xfce.enable = true;
xfce.extraSessionCommands = ''
${pkgs.midori}/bin/midori ${guide} &
${pkgs.xfce.terminal}/bin/xfce4-terminal &
'';
};
};
}

21
library/default.nix Normal file
View File

@ -0,0 +1,21 @@
{ pkgs, lib, ... }:
{
desktopFile = bin: { longName ? "Script", command ? "${bin}/bin/${bin.name}", ... }:
pkgs.writeTextFile {
name = "${bin.name}.desktop" ;
destination = "/share/applications/${bin.name}.desktop";
text = ''
[Desktop Entry]
Type=Application
Exec=${bin}/bin/${command} %U
Comment=An open source web browser from Google
Terminal=false
Name=${bin.name}
GenericName=${longName}
StartupWMClass=${bin.name}
'';
};
jenkins = import ./jenkins.nix { inherit lib; };
}

135
library/jenkins.nix Normal file
View File

@ -0,0 +1,135 @@
{ lib, ... }:
with builtins;
{
# source container url and credentialsId
job = name: {
url,
credentialsId,
branch ? "master",
# https://docs.openstack.org/infra/jenkins-job-builder/triggers.html
triggers ? [
{ pollscm = {
cron = "H/30 * * * *";
ignore-post-commit-hooks = true;
};}
], ... }: config: { job = {
inherit name triggers;
sandbox = true;
project-type = "pipeline";
dsl = let
stage = elem:
let
stageName = head ( attrNames elem );
stateScripts = map ( stage :
lib.getAttr (typeOf stage) {
string = ''
withEnv(['PATH=/run/current-system/sw/bin/','NIX_PATH=/var/src/']) {
sh '${toString stage}'
}'';
set =
let
script = ''
withEnv(['PATH=/run/current-system/sw/bin/','NIX_PATH=/var/src/']) {
sh '${toString stage.script}'
}
'';
in
if (stage.credentialsId != null)
then ''
sshagent(['${stage.credentialsId}']) { ${script} }
''
else script;
}
)( getAttr stageName elem );
in ''
stage('${stageName}') {
steps {
${concatStringsSep "\n" stateScripts}
}
}
'';
stages = map stage config;
in ''
pipeline {
agent any
stages{
stage('Pull') {
steps {
checkout(
[$class: 'GitSCM'
, branches: [[name: '*/${branch}']]
, doGenerateSubmoduleConfigurations: false
, extensions: [[$class: 'LocalBranch', localBranch: 'master']]
, submoduleCfg: []
, userRemoteConfigs:
[[ credentialsId: '${credentialsId}'
, url: '${url}']]
]
)
}
}
${concatStringsSep "\n" stages}
}
}
'';
};};
# creates a sync job
# source and target container url and credentialsId
syncJob = name: source: target: {
job = {
name = name;
sandbox = true;
project-type = "pipeline";
triggers = [ {
pollscm = {
cron = "H/30 * * * *";
ignore-post-commit-hooks = true;
};
} ];
dsl = ''
pipeline {
agent any
stages{
stage('Pull') {
steps {
checkout(
[$class: 'GitSCM'
, branches: [[name: '*/master']]
, doGenerateSubmoduleConfigurations: false
, extensions: [[$class: 'LocalBranch', localBranch: 'master']]
, submoduleCfg: []
, userRemoteConfigs:
[[ credentialsId: '${source.credentialsId}'
, url: '${source.url}']]
]
)
}
}
stage('Push') {
steps {
sshagent(['${target.credentialsId}']) {
withEnv(['PATH=/run/current-system/sw/bin/','NIX_PATH=/var/src/']) {
sh "git push -f ${target.url}"
}
}
}
}
stage('Push Tags') {
steps {
sshagent(['${target.credentialsId}']) {
withEnv(['PATH=/run/current-system/sw/bin/']) {
sh "git push -f ${target.url} --tags"
}
}
}
}
}
}
'';
};
};
}

45
modules/default.nix Normal file
View File

@ -0,0 +1,45 @@
{
imports = [
./later/syncthing.nix
./services/castget.nix
./services/home-assistant.nix
./services/lektor.nix
./services/samba-share.nix
./services/seafile.nix
./services/sshd.nix
./services/transmission.nix
./services/videoencoder.nix
./programs/browser.nix
./programs/citate.nix
./programs/curl-scripts.nix
./programs/easytag.nix
./programs/elm.nix
./programs/espeak.nix
./programs/ffmpeg.nix
./programs/git.nix
./programs/q.nix
./programs/shell-bash.nix
./programs/shell-tools.nix
./programs/shell-zsh.nix
./programs/slack.nix
./programs/steam.nix
./programs/taskwarrior.nix
./programs/urxvt.nix
./programs/video.nix
./programs/vim.nix
./programs/xterm.nix
./system/audio.nix
./system/bluetooth.nix
./system/font.nix
./system/mainUser.nix
./system/permown.nix
./system/wifi.nix
./system/x11.nix
];
}

434
modules/later/syncthing.nix Normal file
View File

@ -0,0 +1,434 @@
{ config, lib, pkgs, ... }:
with lib;
let
cfg = config.test.services.syncthing;
defaultUser = "syncthing";
devices = mapAttrsToList (name: device: {
deviceID = device.id;
inherit (device) name addresses introducer;
}) cfg.declarative.devices;
folders = mapAttrsToList ( _: folder: {
inherit (folder) path id label type;
devices = map (device: { deviceId = cfg.declarative.devices.${device}.id; }) folder.devices;
rescanIntervalS = folder.rescanInterval;
fsWatcherEnabled = folder.watch;
fsWatcherDelayS = folder.watchDelay;
ignorePerms = folder.ignorePerms;
}) (filterAttrs (
_: value:
(value.path != null) && (value.devices != [])
) cfg.declarative.folders);
# get the api key by parsing the config.xml
getApiKey = pkgs.writers.writeDash "getAPIKey" ''
${pkgs.libxml2}/bin/xmllint \
--xpath 'string(configuration/gui/apikey)'\
${cfg.configDir}/config.xml
'';
updateConfig = pkgs.writers.writeDash "merge-syncthing-config" ''
set -efu
# wait for syncthing port to open
until ${pkgs.curl}/bin/curl -Ss ${cfg.guiAddress} -o /dev/null; do
sleep 1
done
API_KEY=$(${getApiKey})
OLD_CFG=$(${pkgs.curl}/bin/curl -Ss \
-H "X-API-Key: $API_KEY" \
${cfg.guiAddress}/rest/system/config)
# generate the new config by merging with the nixos config options
NEW_CFG=$(echo "$OLD_CFG" | ${pkgs.jq}/bin/jq -s '.[] as $in | $in * {
"devices": (${builtins.toJSON devices}${optionalString (! cfg.declarative.overrideDevices) " + $in.devices"}),
"folders": (${builtins.toJSON folders}${optionalString (! cfg.declarative.overrideFolders) " + $in.folders"})
}')
# POST the new config to syncthing
echo "$NEW_CFG" | ${pkgs.curl}/bin/curl -Ss \
-H "X-API-Key: $API_KEY" \
${cfg.guiAddress}/rest/system/config -d @-
# restart syncthing after sending the new config
${pkgs.curl}/bin/curl -Ss \
-H "X-API-Key: $API_KEY" \
-X POST \
${cfg.guiAddress}/rest/system/restart
'';
in {
###### interface
options = {
test.services.syncthing = {
enable = mkEnableOption ''
Syncthing - the self-hosted open-source alternative
to Dropbox and Bittorrent Sync. Initial interface will be
available on http://127.0.0.1:8384/.
'';
declarative = {
cert = mkOption {
type = types.nullOr types.str;
default = null;
description = ''
Path to users cert.pem file, will be copied into the syncthing's
<literal>configDir</literal>
'';
};
key = mkOption {
type = types.nullOr types.str;
default = null;
description = ''
Path to users key.pem file, will be copied into the syncthing's
<literal>configDir</literal>
'';
};
overrideDevices = mkOption {
type = types.bool;
default = true;
description = ''
Whether to delete the devices which are not configured via the
<literal>declarative.devices</literal> option.
If set to false, devices added via the webinterface will
persist but will have to be deleted manually.
'';
};
devices = mkOption {
default = {};
description = ''
Peers/devices which syncthing should communicate with.
'';
example = [
{
name = "bigbox";
id = "7CFNTQM-IMTJBHJ-3UWRDIU-ZGQJFR6-VCXZ3NB-XUH3KZO-N52ITXR-LAIYUAU";
addresses = [ "tcp://192.168.0.10:51820" ];
}
];
type = types.attrsOf (types.submodule ({ config, ... }: {
options = {
name = mkOption {
type = types.str;
default = config._module.args.name;
description = ''
Name of the device
'';
};
addresses = mkOption {
type = types.listOf types.str;
default = [];
description = ''
The addresses used to connect to the device.
If this is let empty, dynamic configuration is attempted
'';
};
id = mkOption {
type = types.str;
description = ''
The id of the other peer, this is mandatory. It's documented at
https://docs.syncthing.net/dev/device-ids.html
'';
};
introducer = mkOption {
type = types.bool;
default = false;
description = ''
If the device should act as an introducer and be allowed
to add folders on this computer.
'';
};
};
}));
};
overrideFolders = mkOption {
type = types.bool;
default = true;
description = ''
Whether to delete the folders which are not configured via the
<literal>declarative.folders</literal> option.
If set to false, folders added via the webinterface will persist
but will have to be deleted manually.
'';
};
folders = mkOption {
default = {};
description = ''
folders which should be shared by syncthing.
'';
type = types.attrsOf (types.submodule ({ config, ... }: {
options = {
path = mkOption {
type = types.nullOr types.str;
default = null;
description = ''
The path to the folder which should be shared.
'';
};
id = mkOption {
type = types.str;
default = config._module.args.name;
description = ''
The id of the folder. Must be the same on all devices.
'';
};
label = mkOption {
type = types.str;
default = config._module.args.name;
description = ''
The label of the folder.
'';
};
devices = mkOption {
type = types.listOf types.str;
default = [];
description = ''
The devices this folder should be shared with. Must be defined
in the <literal>declarative.devices</literal> attribute.
'';
};
rescanInterval = mkOption {
type = types.int;
default = 3600;
description = ''
How often the folders should be rescaned for changes.
'';
};
type = mkOption {
type = types.enum [ "sendreceive" "sendonly" "receiveonly" ];
default = "sendreceive";
description = ''
Whether to send only changes from this folder, only receive them
or propagate both.
'';
};
watch = mkOption {
type = types.bool;
default = true;
description = ''
Whether the folder should be watched for changes by inotify.
'';
};
watchDelay = mkOption {
type = types.int;
default = 10;
description = ''
The delay after an inotify event is triggered.
'';
};
ignorePerms = mkOption {
type = types.bool;
default = true;
description = ''
Whether to propagate permission changes.
'';
};
};
}));
};
};
guiAddress = mkOption {
type = types.str;
default = "127.0.0.1:8384";
description = ''
Address to serve the GUI.
'';
};
systemService = mkOption {
type = types.bool;
default = true;
description = "Auto launch Syncthing as a system service.";
};
user = mkOption {
type = types.str;
default = defaultUser;
description = ''
Syncthing will be run under this user (user will be created if it doesn't exist.
This can be your user name).
'';
};
group = mkOption {
type = types.str;
default = "nogroup";
description = ''
Syncthing will be run under this group (group will not be created if it doesn't exist.
This can be your user name).
'';
};
all_proxy = mkOption {
type = with types; nullOr str;
default = null;
example = "socks5://address.com:1234";
description = ''
Overwrites all_proxy environment variable for the syncthing process to
the given value. This is normaly used to let relay client connect
through SOCKS5 proxy server.
'';
};
dataDir = mkOption {
type = types.path;
default = "/var/lib/syncthing";
description = ''
Path where synced directories will exist.
'';
};
configDir = mkOption {
type = types.path;
description = ''
Path where the settings and keys will exist.
'';
default =
let
nixos = config.system.stateVersion;
cond = versionAtLeast nixos "19.03";
in cfg.dataDir + (optionalString cond "/.config/syncthing");
};
openDefaultPorts = mkOption {
type = types.bool;
default = false;
example = literalExample "true";
description = ''
Open the default ports in the firewall:
- TCP 22000 for transfers
- UDP 21027 for discovery
If multiple users are running syncthing on this machine, you will need to manually open a set of ports for each instance and leave this disabled.
Alternatively, if are running only a single instance on this machine using the default ports, enable this.
'';
};
package = mkOption {
type = types.package;
default = pkgs.syncthing;
defaultText = "pkgs.syncthing";
example = literalExample "pkgs.syncthing";
description = ''
Syncthing package to use.
'';
};
};
};
imports = [
(mkRemovedOptionModule ["services" "syncthing" "useInotify"] ''
This option was removed because syncthing now has the inotify functionality included under the name "fswatcher".
It can be enabled on a per-folder basis through the webinterface.
'')
];
###### implementation
config = mkIf cfg.enable {
networking.firewall = mkIf cfg.openDefaultPorts {
allowedTCPPorts = [ 22000 ];
allowedUDPPorts = [ 21027 ];
};
systemd.packages = [ pkgs.syncthing ];
users = mkIf (cfg.systemService && cfg.user == defaultUser) {
users."${defaultUser}" =
{ group = cfg.group;
home = cfg.dataDir;
createHome = true;
uid = config.ids.uids.syncthing;
description = "Syncthing daemon user";
};
groups."${defaultUser}".gid =
config.ids.gids.syncthing;
};
systemd.services = {
syncthing = mkIf cfg.systemService {
description = "Syncthing service";
after = [ "network.target" ];
environment = {
STNORESTART = "yes";
STNOUPGRADE = "yes";
inherit (cfg) all_proxy;
} // config.networking.proxy.envVars;
wantedBy = [ "multi-user.target" ];
serviceConfig = {
Restart = "on-failure";
SuccessExitStatus = "2 3 4";
RestartForceExitStatus="3 4";
User = cfg.user;
Group = cfg.group;
ExecStartPre = mkIf (cfg.declarative.cert != null || cfg.declarative.key != null)
"+${pkgs.writers.writeBash "syncthing-copy-keys" ''
mkdir -p ${cfg.configDir}
chown ${cfg.user}:${cfg.group} ${cfg.configDir}
chmod 700 ${cfg.configDir}
${optionalString (cfg.declarative.cert != null) ''
cp ${toString cfg.declarative.cert} ${cfg.configDir}/cert.pem
chown ${cfg.user}:${cfg.group} ${cfg.configDir}/cert.pem
chmod 400 ${cfg.configDir}/cert.pem
''}
${optionalString (cfg.declarative.key != null) ''
cp ${toString cfg.declarative.key} ${cfg.configDir}/key.pem
chown ${cfg.user}:${cfg.group} ${cfg.configDir}/key.pem
chmod 400 ${cfg.configDir}/key.pem
''}
''}"
;
ExecStart = ''
${cfg.package}/bin/syncthing \
-no-browser \
-gui-address=${cfg.guiAddress} \
-home=${cfg.configDir}
'';
};
};
syncthing-init = {
after = [ "syncthing.service" ];
wantedBy = [ "multi-user.target" ];
serviceConfig = {
User = cfg.user;
RemainAfterExit = true;
Type = "oneshot";
ExecStart = updateConfig;
};
};
syncthing-resume = {
wantedBy = [ "suspend.target" ];
};
};
};
}

View File

@ -0,0 +1,247 @@
{ config, lib, pkgs, ... }:
# todo : this needs to be cleaned up
with lib;
let
cfg = config.programs.custom.browser;
library = import <library> { inherit pkgs lib; };
chromiumBin = "${pkgs.chromium}/bin/chromium";
chromeBin = "${pkgs.google-chrome}/bin/google-chrome-stable";
firefoxBin = "${pkgs.firefox}/bin/firefox";
tarBin = "${pkgs.gnutar}/bin/tar";
# desktop file
# ------------
# makes it possible to be used by other programs
desktopFile = bin: let
browserName = bin.name;
in pkgs.writeTextFile {
name = "${browserName}.desktop" ;
destination = "/share/applications/${browserName}.desktop";
text = ''
[Desktop Entry]
Type=Application
Exec=${bin}/bin/${browserName} %U
Icon=chromium
Comment=An open source web browser from Google
Terminal=false
Name=${browserName}
GenericName=Web browser
MimeType=text/html;text/xml;application/xhtml+xml;x-scheme-handler/http;x-scheme-handler/https;x-scheme-handler/ftp;x-scheme-handler/webcal;x-scheme-handler/about
Categories=Network;WebBrowser
StartupWMClass=${browserName}
'';
};
cleanBrowser = name: browser: home: homeBackup:
let
backupFile = "${homeBackup}.tar.lzma";
rolloutFile = "${home}.tar.lzma";
lockFile = "${home}-lock";
in
pkgs.writeShellScriptBin "${name}-clean" /* sh */ ''
sudo killall -9 -u ${name}
sudo rm ${lockFile}
sudo rm -rf ${home}
'';
createBrowser = name: user: browser: home: homeBackup:
let
backupFile = "${homeBackup}.tar.lzma";
rolloutFile = "${home}.tar.lzma";
lockFile = "${home}-lock";
in
pkgs.writeShellScriptBin "${name}" /* sh */ ''
# set -x
if [[ ! -e ${lockFile} ]]
then
# rollout backup
if [[ -e ${backupFile} ]]
then
if [[ ! -d ${home} ]]
then
# todo : use make user
sudo mkdir -p ${home}
sudo chown -R ${user}:users ${home}
fi
cp ${backupFile} ${rolloutFile}
sudo -u ${user} ${tarBin} xf ${rolloutFile} --directory ${home}
rm ${rolloutFile}
touch ${lockFile}
fi
fi
sudo -u ${user} ${browser}
'';
browserExecutableList =
let
allBrowser = flip mapAttrsToList cfg.configList (
name: config:
let
browser = if config.browserType == "chrome"
then "${chromiumBin} \"$@\""
else if config.browserType == "google"
then "${chromeBin} \"$@\""
else "${firefoxBin} \"$@\"";
in
createBrowser name config.user browser config.home config.homeBackup
);
xclipBrowser = [
(pkgs.writeShellScriptBin "copy-to-xclip" /* sh */''
echo "$*" | ${pkgs.xclip}/bin/xclip
'')
];
in
allBrowser ++ xclipBrowser;
createBackupScript = name: home: backupHome:
pkgs.writeShellScriptBin "${name}-backup" /* sh */ ''
sudo -u ${name} \
${tarBin} \
--exclude=.cache \
--exclude=Downloads \
--create \
--verbos \
--lzma \
--file ${home}.tar.lzma \
--directory ${home} \
.
cp ${home}.tar.lzma ${backupHome}.tar.lzma
'';
allBackupScripts =
let
filteredConfigs =
filterAttrs
(name: browserConfig: browserConfig.homeBackup != null)
cfg.configList;
in
mapAttrsToList
(name: browserConfig: createBackupScript name browserConfig.home browserConfig.homeBackup)
filteredConfigs;
allCleanScripts =
let
filteredConfigs =
filterAttrs
(name: browserConfig: browserConfig.homeBackup != null)
cfg.configList;
in
mapAttrsToList
(name: browserConfig: cleanBrowser name name browserConfig.home browserConfig.homeBackup)
filteredConfigs;
# browser chooser
# ---------------
browserSelect = pkgs.writeScriptBin "browser-select" ''
# select a browser using dmenu
# ----------------------------
BROWSER=$( echo -e "${lib.concatMapStringsSep "\\n" (bin: bin.name) browserExecutableList}" \
| ${pkgs.rofi}/bin/rofi -dmenu )
# start selected browser
# ----------------------
case $BROWSER in
${lib.concatStringsSep "\n"
(flip map browserExecutableList (bin: "${bin.name}) export BIN=${bin}/bin/${bin.name} ;;"))
}
esac
$BIN "$@"
'';
in {
options.programs.custom.browser = {
enable = mkEnableOption "enable browsers";
configList = mkOption {
type = with types; attrsOf (submodule ({ name , ... }: {
options = {
browserType = mkOption {
type = with types; enum ["firefox" "chrome" "google"];
default = "chrome";
description = ''
the type of browser which is simulated
'';
};
home = mkOption {
type = with types; str;
description = ''
Home of the browser.
'';
};
user = mkOption {
default = name;
type = with types; str;
description = ''
user to run the browser as
'';
};
sudoUsers = mkOption {
default = [ config.users.users.mainUser.name ];
type = with types; listOf str;
description = ''
user allowed to run sudo without password to start the browser
'';
};
homeBackup = mkOption {
type = with types; nullOr str;
default = null;
example = "~/.my-browser-backup";
description = ''
backup of the home, which gets rolled out if the
home does not exists. usefull for homes in tmpfs.
dont use file endings!
'';
};
};
}));
};
};
config = mkIf cfg.enable {
# add sudo rights
security.sudo.extraConfig =
let
extraRules = flip mapAttrsToList cfg.configList (name: values:
concatStringsSep "\n" (map (sudoUser: "${sudoUser} ALL=(${values.user}) NOPASSWD: ALL") values.sudoUsers)) ;
in
lib.concatStringsSep "\n" extraRules;
# create users
users.users = flip mapAttrs cfg.configList (name: config:
{
home = config.home;
createHome = true;
initialPassword = "${name}-browser";
shell = pkgs.bashInteractive;
isNormalUser = true;
group = "users";
# enable video usage
extraGroups = [ "video" "audio" ];
}
);
# add groups to mainUser
system.custom.mainUser.extraGroups = builtins.attrNames cfg.configList;
environment.systemPackages = [
browserSelect
( desktopFile browserSelect )
]
++ browserExecutableList
++ (map (bin: desktopFile bin) browserExecutableList)
++ allBackupScripts
++ allCleanScripts;
};
}

View File

@ -0,0 +1,35 @@
{ config, lib, pkgs, ... }:
with lib;
let
cfg = config.programs.custom.citate;
library = import <library> { inherit pkgs lib; };
xdotool = "${pkgs.xdotool}/bin/xdotool";
dmenu = "${pkgs.dmenu}/bin/dmenu";
citateScript = file: suffix: pkgs.writeShellScriptBin "citate-${suffix}" ''
${xdotool} - <<<"type -- $( cat ${file} | ${dmenu} -l 10 -i | sed -e "s/\(.*\)/'\1'/" )"
'';
scriptAxel = citateScript (toString <assets/sprueche-axel>) "axel";
scriptSiw = citateScript (toString <assets/sprueche-siw>) "siw";
in {
options.programs.custom.citate = {
enable = mkEnableOption "enable programs.custom.citate";
};
config = mkIf cfg.enable {
environment.systemPackages = [
scriptAxel
(library.desktopFile scriptAxel { longName = "Citate Axel"; command = "citate-axel"; })
scriptSiw
(library.desktopFile scriptSiw { longName = "Citate Sinnlos im Weltall"; command = "citate-siw"; })
];
};
}

Some files were not shown because too many files have changed in this diff Show More