delete legacy folder

This commit is contained in:
Ingolf Wagner 2024-06-08 21:41:30 +02:00
parent 3ded20e880
commit 1bc5e3d034
Signed by: palo
GPG key ID: 76BF5F1928B9618B
81 changed files with 0 additions and 6127 deletions

View file

@ -1,81 +0,0 @@
{ config, pkgs, lib, ... }: {
imports = [
../../components
../../modules
./hardware-configuration.nix
./tinc.nix
./syncthing.nix
];
security.wrappers = {
pmount = {
source = "${pkgs.pmount}/bin/pmount";
setuid = true;
owner = "root";
group = "root";
};
pumount = {
source = "${pkgs.pmount}/bin/pumount";
setuid = true;
owner = "root";
group = "root";
};
};
components.gui.enable = true;
configuration.desktop = {
width = 1366;
height = 768;
};
# grub configuraton
# -----------------
boot.loader.grub.enable = true;
boot.loader.grub.efiSupport = true;
boot.loader.grub.device = "/dev/sda";
boot.loader.grub.efiInstallAsRemovable = true;
boot.tmpOnTmpfs = true;
networking.networkmanager.enable = true;
networking.hostName = "bobi";
# Set your time zone.
time.timeZone = "Europe/Berlin";
environment.systemPackages = with pkgs; [
vim
wget
htop
silver-searcher
];
environment.extraInit = ''
# use vi shortcuts
# ----------------
set -o vi
EDITOR=vim
'';
boot.supportedFilesystems = [ "zfs" ];
networking.hostId = "2ed43034";
services.openssh.enable = true;
components.network.sshd.onlyTincAccess = false;
users.users.root.openssh.authorizedKeys.keys = [ "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== contact@ingolf-wagner.de" ];
# This value determines the NixOS release from which the default
# settings for stateful data, like file locations and database versions
# on your system were taken. Its perfectly fine and recommended to leave
# this value at the release version of the first install of this system.
# Before changing this value read the documentation for this option
# (e.g. man configuration.nix or on https://nixos.org/nixos/options.html).
system.stateVersion = "22.05"; # Did you read the comment?
}

View file

@ -1,47 +0,0 @@
# 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, modulesPath, ... }:
{
imports =
[
(modulesPath + "/installer/scan/not-detected.nix")
];
boot.initrd.availableKernelModules = [ "ehci_pci" "ahci" "xhci_pci" "usb_storage" "usbhid" "sd_mod" "sdhci_pci" ];
boot.initrd.kernelModules = [ "dm-snapshot" ];
boot.kernelModules = [ "kvm-intel" ];
boot.extraModulePackages = [ ];
fileSystems."/" =
{
device = "/dev/disk/by-uuid/b3dc4880-fb1b-415d-a5a8-a53b9f0a9ab6";
fsType = "ext4";
};
boot.initrd.luks.devices."root-enc".device = "/dev/disk/by-uuid/c2a56e0f-f831-4d21-8cf4-7ddf3901ea8a";
fileSystems."/boot" =
{
device = "/dev/disk/by-uuid/EBCE-D756";
fsType = "vfat";
};
swapDevices = [ ];
# Enables DHCP on each ethernet and wireless interface. In case of scripted networking
# (the default) this is the recommended approach. When using systemd-networkd it's
# still possible to use this option, but it's recommended to use it in conjunction
# with explicit per-interface declarations with `networking.interfaces.<interface>.useDHCP`.
networking.useDHCP = lib.mkDefault true;
# networking.interfaces.enp0s25.useDHCP = lib.mkDefault true;
# networking.interfaces.tinc.private.useDHCP = lib.mkDefault true;
# networking.interfaces.tinc.retiolum.useDHCP = lib.mkDefault true;
# networking.interfaces.tinc.secret.useDHCP = lib.mkDefault true;
# networking.interfaces.virbr0.useDHCP = lib.mkDefault true;
# networking.interfaces.wlp3s0.useDHCP = lib.mkDefault true;
powerManagement.cpuFreqGovernor = lib.mkDefault "ondemand";
hardware.cpu.intel.updateMicrocode = lib.mkDefault config.hardware.enableRedistributableFirmware;
}

View file

@ -1,37 +0,0 @@
{ config, pkgs, lib, ... }: {
services.syncthing = {
enable = true;
openDefaultPorts = false;
user = "palo";
dataDir = "/home/palo/.syncthing";
configDir = "/home/palo/.syncthing";
overrideFolders = true;
folders = {
# on encrypted drive
# ------------------
private = {
enable = true;
path = "/home/palo/private";
};
desktop = {
enable = true;
path = "/home/palo/desktop";
};
finance = {
enable = true;
path = "/home/palo/finance";
};
password-store = {
enable = true;
path = "/home/palo/.password-store";
};
};
};
services.permown."/home/palo/music-library" = {
owner = "palo";
group = "users";
};
}

View file

@ -1,5 +0,0 @@
{ config, ... }:
{
tinc.private.enable = true;
tinc.private.ipv4 = "10.23.42.25";
}

View file

@ -1,96 +0,0 @@
{ config, lib, ... }:
# borg core setup
# ---------------
# provides an easy interface for all services
# to append it's files to be backuped
{
options = {
backup = {
enable = lib.mkEnableOption "enable borg backup";
dirs = lib.mkOption {
default = [ ];
type = with lib.types; listOf str;
description = ''
folders to backup
'';
};
exclude = lib.mkOption {
default = [ ];
type = with lib.types; listOf str;
description = ''
exclude files and folders matching a pattern.
Theses patterns effect all folders in `backup.dirs`.
see man borg pattern for more information
'';
example = [ ".git" "/home/*/.cache" ".stfolder" ];
};
servers = lib.mkOption {
default = {
robi.host = "144.76.13.147";
pepe.host = "pepe.private";
};
type = with lib.types; attrsOf (submodule {
options = {
host = lib.mkOption {
type = with lib.types; str;
};
user = lib.mkOption {
default = "borg";
type = with lib.types; str;
};
};
});
description = ''
servers to backup to
'';
};
};
};
config =
let
myHostname = config.networking.hostName;
setup = { user, host }: {
paths = config.backup.dirs;
exclude = config.backup.exclude;
doInit = true;
repo = "${user}@${host}:./${myHostname}";
encryption = {
mode = "repokey-blake2";
passCommand = "cat ${config.sops.secrets.backup_repository_passphrase.path}";
};
environment = {
BORG_RSH = "ssh -i ${toString config.sops.secrets.backup_ssh_rsa_private.path}";
BORG_RELOCATED_REPO_ACCESS_IS_OK = "yes";
};
compression = "auto,lzma";
startAt = "daily";
prune.keep = {
within = "10d"; # Keep all backups in the last 10 days.
weekly = 8; # Keep 8 additional end of week archives.
monthly = -1; # Keep end of month archive for every month
};
};
in
lib.mkIf config.backup.enable {
sops.secrets.backup_repository_passphrase = { };
sops.secrets.backup_ssh_rsa_private = { };
services.borgbackup.jobs =
lib.mapAttrs (_: target: setup target) config.backup.servers;
#systemd.services = lib.mapAttrs'
# (name: _: {
# name = "borgbackup-job-${name}";
# value = { enable = config.backup.dirs != [ ]; };
# })
# config.backup.servers;
};
}

View file

@ -1,24 +0,0 @@
{ pkgs, lib, ... }: {
environment.systemPackages =
let
createScript = command: target: repository:
pkgs.writers.writeBashBin
"borg-${command}-on-${target}-for-${repository}" ''
${pkgs.borgbackup}/bin/borg \
${command} \
--rsh='ssh -i ~/.ssh/palo_rsa.pub' ${target}.private:${repository}/. \
"$@"
'';
targets = [ "borg@pepe" "borg@robi" "borg@cream" "removable@cream" ];
repositories = [ "pepe" "sterni" "robi" "cream" ];
commands = [ "list" "mount" ];
in
lib.flatten (map
(command:
map
(target: map (repository: createScript command target repository) repositories)
targets)
commands);
}

View file

@ -1,16 +0,0 @@
{ lib, config, pkgs, ... }: {
backup.enable = true;
# provide repository
services.borgbackup.repos = {
default = {
quota = "300G";
allowSubRepos = true;
authorizedKeys = [
];
};
};
}

View file

@ -1,98 +0,0 @@
{ lib, pkgs, config, ... }:
# a very simple dms setup which.
# I have a brother ADS-1600W scanner, which is configured to send all
# PDFs to this machine in /home/ftp-upload/input
# from there the dms.py scans them and makes them searchable.
let
dms = pkgs.fetchgit {
url = "https://github.com/mrVanDalo/dms.git";
rev = "2f5c44f017bdfd8abfe908d419ef26bac300f809";
sha256 = "0dxhk1ah6wwbsxyk4hd32rz7886w7r5gfy16485gjbvky1qsi8gd";
};
in
{
# setup ftp
services.vsftpd = {
enable = true;
userlist = [ "ftp-upload" ];
userlistEnable = true;
localUsers = true;
writeEnable = true;
extraConfig = ''
# additional ports for directory list and stuff
pasv_min_port=4242
pasv_max_port=4243
'';
};
networking.firewall.allowedTCPPortRanges = [
{
# ftp: additional ports for directory list and stuff
from = 4242;
to = 4243;
}
{
# ftp
from = 20;
to = 21;
}
];
sops.secrets.ftp_password = { };
# create user
users.users.ftp-upload = {
passwordFile = config.sops.secrets.ftp_password.path;
isNormalUser = true;
};
# create dms service
systemd.services.dms = {
enable = true;
wantedBy = [ "multi-user.target" ];
path = [
(pkgs.python3.withPackages (ps: with ps; [ flask ]))
pkgs.imagemagickBig
(pkgs.pdfsandwich.override { imagemagick = pkgs.imagemagickBig; })
pkgs.poppler_utils
pkgs.which
pkgs.netpbm
pkgs.gawk
pkgs.bash
];
serviceConfig = { User = "ftp-upload"; };
preStart = ''
if [[ ! -L /home/ftp-upload/db/SOURCE_DIR ]]
then
rm -rf /home/ftp-upload/db/SOURCE_DIR
mkdir -p /home/ftp-upload/db
mkdir -p /home/ftp-upload/input
ln -s /home/ftp-upload/input /home/ftp-upload/db/SOURCE_DIR
fi
'';
script = ''
DMSDATA=/home/ftp-upload/db \
FLASK_APP=${dms}/dms.py \
flask run --host 0.0.0.0 \
"$@"
'';
};
# host nginx setup
services.nginx = {
enable = true;
virtualHosts = {
"dms.pepe.private" = {
serverAliases =
[ "pdf.pepe.private" "docs.pepe.private" "dms.pepe.lan" ];
locations."/" = { proxyPass = "http://localhost:5000"; };
};
};
};
# add documents to backup
backup.dirs = [ "/home/ftp-upload/db" ];
}

View file

@ -1,58 +0,0 @@
{ lib, config, pkgs, ... }:
let
# find symbols with
# https://www.alphavantage.co/query?function=SYMBOL_SEARCH&apikey=<api_key>&keywords=<keywords>
# as described here : https://www.alphavantage.co/documentation/#symbolsearch
#
# example:
# --------
# stocks = [
# {
# friendly_name = "google";
# symbol = "GOOGL.DEX";
# name = "google";
# currency = "$";
# }
# ];
# results in
# P 2020-01-30 GOOGL $123
stocks = import ../../private_assets/finance/stocks;
stocksFile = toString /home/syncthing/finance/hledger/stocks.journal;
in
{
systemd.services.pull_stocks = {
enable = true;
description = "pull stocks for hledger";
serviceConfig = {
User = "syncthing";
Type = "oneshot";
};
script =
let
command = { symbol, name, currency, ... }: ''
APIKEY=${lib.fileContents ../../private_assets/finance/alphavantage/apiKey}
SYMBOL="${symbol}"
${pkgs.curl}/bin/curl --location --silent \
"https://www.alphavantage.co/query?function=GLOBAL_QUOTE&symbol=$SYMBOL&apikey=$APIKEY" \
| ${pkgs.jq}/bin/jq --raw-output '.["Global Quote"]
| "P \(.["07. latest trading day"]) ${name} ${currency}\(.["05. price"] | tonumber)"' \
>> ${stocksFile}
sleep 1
'';
in
lib.concatStringsSep "\n" (map command stocks);
};
systemd.timers.pull_stocks = {
enable = true;
wantedBy = [ "multi-user.target" ];
timerConfig = {
OnCalendar = "weekly";
Persistent = "true";
};
};
}

View file

@ -1,130 +0,0 @@
{ 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.mongodb.enable = true;
services.elasticsearch = {
enable = true;
listenAddress = "${config.networking.hostName}.private";
extraJavaOptions = [ "-Des.http.cname_in_publish_address=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 ../../private_assets/graylog/password-secret;
# echo -n yourpassword | shasum -a 256
services.graylog.rootPasswordSha2 =
lib.fileContents ../../private_assets/graylog/root-password-hash;
services.graylog.plugins = [ pkgs.graylogPlugins.slack ];
# not working at the moment
#services.geoip-updater.enable = true;
# 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
'';
};
environment.etc."graylog/server/known_servers.csv" = {
enable = true;
text = ''
"ip","host_name"
"95.216.1.150","lassul.us"
'';
};
environment.etc."graylog/systemd/loglevel.csv" = {
enable = true;
text = ''
"value","Servity","Description"
"0","emergency","System is unusable"
"1","alert","Should be corrected immediately"
"2","cirtical","Critical conditions"
"3","error","Error Condition"
"4","warning","May indicate that an error will occur if action is not taken."
"5","notice","Events that are unusual, but not error conditions."
"6","info","Normal operational messages that require no action."
"7","debug","Information useful to developers for debugging the application."
'';
};
}

View file

@ -1,24 +0,0 @@
{ config, lib, pkgs, ... }:
{
#services.grocy = {
# enable = true;
# settings = {
# culture = "de";
# currency = "EUR";
# };
# hostName = "grocy.pepe.private";
# nginx.enableSSL = false;
#};
#backup.dirs = [ config.services.grocy.dataDir ];
services.grocy-scanner = {
enable = true;
host = "https://grocy.ingolf-wagner.de";
device = "/dev/input/by-id/usb-Belon.cn_2.4G_Wireless_Device_Belon_Smart-event-kbd";
apiKeyFile = config.sops.secrets.grocyApiKey.path;
};
sops.secrets.grocyApiKey = { };
}

View file

@ -1,78 +0,0 @@
{ lib, pkgs, config, ... }:
let
# you find this device using `ifconfig -a` or `ip link`
wifi = "wlp3s0";
ipAddress = "10.23.45.1";
prefixLength = 24;
servedAddressRange = "10.23.45.2,10.23.45.150,12h";
ssid = "home/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_psk_file=${config.sops.secrets.hostapd_wpa_psk.path}
''
}";
Restart = "always";
};
};
sops.secrets.hostapd_wpa_psk = { };
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

@ -1,25 +0,0 @@
{ 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

@ -1,22 +0,0 @@
# https://dataswamp.org/~solene/2022-10-06-nixos-kiosk.html
{ pkgs, config, ... }:
{
services.cage = {
enable = true;
user = "kiosk";
program = "${pkgs.firefox}/bin/firefox -kiosk -private-window http://grafana.chungus.private/d/0d1dfFU4k/default-dashboard?orgId=1&kiosk";
};
users = {
users.kiosk = {
isNormalUser = true;
name = "kiosk";
group = config.users.groups.kiosk.name;
};
groups.kiosk = {
name = "kiosk";
};
};
# make sure cage ist starting instead of getty
systemd.defaultUnit = "graphical.target";
}

View file

@ -1,663 +0,0 @@
# fetches mails for me
{ lib, pkgs, config, ... }:
let
junk_filter = [
"from:booking.com"
"subject:Gewinn"
"from:brompton.com"
"from:circleci.com OR (from:noreply@github.com AND to:audio-overlay@googlegroups.com)"
"from:codepen.io"
"from:congstarnews.de"
"from:cronullasurfingacademy.com"
"from:cryptohopper.com"
"from:digitalo.de"
"from:facebook.com OR from:facebookmail.com"
"from:fitnessfirst.de"
"from:flixbus.de"
"from:getdigital.de"
"from:getpocket.com"
"from:ghostinspector.com"
"from:globetrotter.de"
"from:hackster.io"
"from:hostelworld.com"
"from:immobilienscout24.de"
"from:kvraudio.com"
"from:letterboxd.com"
"from:linkedin.com"
"from:magix.net"
"from:mailings.gmx.net"
"from:mailings.web.de"
"from:matrix.org"
"from:menospese.com"
"from:microsoftstoreemail.com"
"from:mixcloudmail.com AND subject:Weekly Update"
"from:oknotify2.com AND NOT subject:New message"
"from:paulaschoice.com"
"from:puppet.com"
"from:runtastic.com"
"from:samplemagic.com OR from:wavealchemy.co.uk OR from:creators.gumroad.com"
"from:ticketmaster.de"
"from:trade4less.de"
"from:tumblr.com"
"from:turners.co.nz"
"from:twitch.tv"
"from:vstbuzz.com"
];
filters = [
{
query = "from:hv-geelen.de";
tags = [ "+wohnung" ];
}
{
query = "from:computerfutures.com OR from:computerfutures.de";
tags = [ "+jobs" "-inbox" ];
}
{
query = "from:seek.com.au or from:seek.co.nz";
tags = [ "+jobs" ];
}
{
query = "from:xing.com";
tags = [ "+jobs" "-inbox" ];
}
{
query = "from:no-reply@backtrace.io OR to:sononym@noreply.github.com";
tags = [ "+sononym" "-inbox" ];
}
{
query = "from:ebay.com OR from:ebay.de OR from:ebay.net";
tags = [ "+ebay" "+shop" "+billing" ];
}
{
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:space-left.org OR to:space-left.org OR subject:/\\[space-left\\]/";
tags = [ "+spaceleft" "+space-left" ];
}
{
query = "from:landr.com";
tags = [ "+landr" "+music" ];
}
{
query = "tag:landr and tag:billing";
tags = [ "+billing" ];
}
{
query = "from:oknotify2.com";
tags = [ "+okcupid" ];
}
{
query = "from:taxback.de OR to:taxback.de";
tags = [ "+steuer" ];
}
{
query = "from:campact.de";
tags = [ "+campact" "+politics" ];
}
{
query = "from:aliexpress.com";
tags = [ "+shop" "+aliexpress" ];
}
{
query = "from:congstar.de";
tags = [ "+billing" "+congstar" "-inbox" "-unread" ];
}
{
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:stadtmobil.de";
tags = [ "+billing" "+stadtmobil" "-inbox" "-unread" ];
}
{
query = "from:drive-now.com";
tags = [ "+billing" "+drivenow" "-inbox" "-unread" ];
}
{
query = "from:data-treuhand.de";
tags = [ "+mindcurv" "+work" "-inbox" "-unread" "-junk" ];
}
{
query = "from:immocation.de";
tags = [ "+immobilien" "-inbox" ];
}
{
query = "from:tinc-vpn.org";
tags = [ "+tinc" ];
}
{
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:notifications@github.com";
tags = [ "+github" ];
}
{
query = "to:NUR@noreply.github.com";
tags = [ "+nur" "+nixos" "+list" ];
}
{
query = "to:nixpkgs@noreply.github.com";
tags = [ "+nixpkgs" "+nixos" "+list" ];
}
{
query = "from:travis-ci.org AND subject:mrVanDalo/navi";
tags = [ "+development" "+navi" ];
}
{
query = "from:travis-ci.org AND subject:nur-packages";
tags = [ "+development" "+nixos" "+nur-packages" ];
}
{
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 = "from:nixos1@discoursemail.com";
tags = [ "+nixos" "+discourse" "+list" ];
}
{
query = "from:nixos1@discoursemail.com AND subject:Development";
tags = [ "+nixos" "+discourse" "+development" ];
}
{
query = "from:nixos1@discoursemail.com AND subject:Français";
tags = [ "+nixos" "+discourse" "-inbox" "-unread" ];
}
{
query = "from:nixos1@discoursemail.com AND subject:Announcements";
tags = [ "+nixos" "+discourse" "+announcements" ];
}
{
query = "from:nixos1@discoursemail.com AND subject:Links";
tags = [ "+nixos" "+discourse" "+links" ];
}
{
query = "from:nixos1@discoursemail.com AND subject:Games";
tags = [ "+nixos" "+discourse" "+games" ];
}
{
query = "from:nixos1@discoursemail.com AND subject:Meta";
tags = [ "+nixos" "+discourse" "+meta" ];
}
{
query = "from:nixos1@discoursemail.com AND subject:Events";
tags = [ "+nixos" "+discourse" "+events" ];
}
{
query = "from:limebike.com AND (subject:Funds OR subject:Receipt)";
tags = [ "-inbox" "-unread" "+billing" "+limebike" ];
}
{
query = "from:freemusicarchive.org";
tags = [ "+FMA" ];
}
{
query = "from:namecheap.com and subject:auto-renewal";
tags = [ "+namecheap" "+billing" ];
}
{
query = "from:namecheap.com and subject:order";
tags = [ "+namecheap" "+billing" ];
}
{
query = "tag:namecheap.com and tag:billing and body:gaykraft.com";
tags = [ "+namecheap" "+billing" ];
}
{
query = "from:nintendo.com";
tags = [ "+nintendo" "+billing" ];
}
{
query = "from:oculus.com AND subject:receipt";
tags = [ "+oculus" "+billing" ];
}
{
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:jobs2web.com";
tags = [ "+newzealand" "+jobs" "-inbox" ];
}
{
query = "from:paypal.de AND subject:Bestätigung";
tags = [ "-unread" "+paypal" "+billing" ];
}
{
query = "to:c-base.org";
tags = [ "+cbase" "+list" ];
}
{
query = "to:c-base.org AND subject=[auto-report]";
tags = [ "-unread" "-inbox" ];
}
{
query = "from:browserstack.com";
tags = [ "+browserstack" ];
}
{
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 = "from:hetzner.com OR from:hetzner.de";
tags = [ "+hetzner" ];
}
{
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" ];
}
{
query = "tag:hetzner and subject:Invoice";
tags = [ "+billing" ];
}
# 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";
}
{
query = "tag:muted";
tags = [ "-inbox" "-unread" ];
}
# remove new tag at the end
{
query = "tag:new";
tags = [ "-new" ];
message = "remove new tag at the end";
}
];
notmuchTagging =
let
template = index:
{ tags, query, message ? "generic", ... }:
let
command = ''
${pkgs.notmuch}/bin/notmuch tag ${lib.concatStringsSep " " tags} -- "${query}"
'';
in
''
echo '${command}'
${command}
'';
junk_template = index: query:
template index {
tags = [ "+junk" "-unread" "-inbox" ];
query = query;
message = "generic junk filter";
};
in
pkgs.writers.writeBash "notmuch-tagging" (lib.concatStringsSep "\n"
((lib.imap0 junk_template junk_filter) ++ (lib.imap0 template filters)));
notmuchTaggingNew =
let
template = index:
{ tags, query, message ? "generic", ... }:
let
command = ''
${pkgs.notmuch}/bin/notmuch tag ${
lib.concatStringsSep " " tags
} -- "${query} AND tag:new"
'';
in
''
echo '${command}'
${command}
'';
junk_template = index: query:
template index {
tags = [ "+junk" "-unread" "-inbox" ];
query = query;
message = "generic junk filter";
};
in
pkgs.writers.writeBash "notmuch-tagging-new" (lib.concatStringsSep "\n"
((lib.imap0 junk_template junk_filter) ++ (lib.imap0 template filters)));
in
{
backup.dirs = [ "/home/mailfetcher" ];
users.users.mailUser = {
isNormalUser = true;
description = "collects mails for me";
hashedPassword = "!";
name = "mailfetcher";
home = "/home/mailfetcher";
openssh.authorizedKeys.keyFiles =
config.users.users.root.openssh.authorizedKeys.keyFiles;
group = "mailfetcher";
};
users.groups.mailUser = {
name = "mailfetcher";
};
sops.secrets.mail_terranix = {
owner = config.users.users.mailUser.name;
group = config.users.users.mailUser.group;
};
sops.secrets.mail_gmail = {
owner = config.users.users.mailUser.name;
group = config.users.users.mailUser.group;
};
sops.secrets.mail_gmx_palo = {
owner = config.users.users.mailUser.name;
group = config.users.users.mailUser.group;
};
sops.secrets.mail_gmx_ingolf = {
owner = config.users.users.mailUser.name;
group = config.users.users.mailUser.group;
};
sops.secrets.mail_web = {
owner = config.users.users.mailUser.name;
group = config.users.users.mailUser.group;
};
sops.secrets.mail_siteground = {
owner = config.users.users.mailUser.name;
group = config.users.users.mailUser.group;
};
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.sops.secrets.mail_gmx_palo.path }";
imap = {
host = "imap.gmx.net";
tls.enable = true;
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.sops.secrets.mail_gmx_ingolf.path }";
imap = {
host = "imap.gmx.net";
tls.enable = true;
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.sops.secrets.mail_web.path }";
imap = {
host = "imap.web.de";
tls.enable = true;
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.sops.secrets.mail_gmail.path }";
imap = {
host = "imap.gmail.com";
tls.enable = true;
port = 993;
};
mbsync = {
enable = true;
create = "both";
};
notmuch.enable = true;
};
terranix_org = {
primary = false;
address = "palo@terranix.org";
aliases = [ ];
realName = "Ingolf Wagner";
userName = "palo@terranix.org";
passwordCommand = "cat ${toString config.sops.secrets.mail_terranix.path }";
imap = {
host = "mail.privateemail.com";
tls.enable = true;
port = 993;
};
mbsync = {
enable = true;
create = "both";
};
notmuch.enable = true;
};
ingolf-wagner-de = {
primary = false;
address = "contact@ingolf-wagner.de";
aliases = [ ];
realName = "Ingolf Wagner";
userName = "contact@ingolf-wagner.de";
passwordCommand =
"cat ${toString config.sops.secrets.mail_siteground.path }";
imap = {
host = "securees5.sgcpanel.com";
port = 993;
tls.enable = true;
#tls.useStartTls = true;
};
# make sure the upstream mail is deleted
getmail = {
enable = true;
delete = true;
readAll = false;
mailboxes = [ "ALL" ];
};
notmuch.enable = true;
};
};
};
home-manager.users.mailUser.home.stateVersion = "22.11";
# configure mbsync
home-manager.users.mailUser.programs.mbsync.enable = true;
# re-tag everything once a day
systemd.services.retagmail = {
enable = true;
serviceConfig = { User = config.users.users.mailUser.name; };
environment.NOTMUCH_CONFIG =
"${config.users.users.mailUser.home}/.config/notmuch/notmuchrc";
script = "${notmuchTagging}";
};
systemd.timers.retagmail = {
enable = true;
timerConfig = {
OnCalendar = "daily";
Persistent = "true";
};
wantedBy = [ "multi-user.target" ];
};
# fetch mails every 10 minutes
systemd.services.fetchmail =
let
threadTag = tag: ''
echo "tag threads with ${tag}"
${pkgs.notmuch}/bin/notmuch tag +${tag} $(${pkgs.notmuch}/bin/notmuch search --output=threads tag:${tag})
'';
in
{
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 \
--all
echo "run getmail"
${pkgs.getmail}/bin/getmail \
--quiet \
--rcfile getmailingolf-wagner-de
echo "run notmuch"
${pkgs.notmuch}/bin/notmuch new
${notmuchTaggingNew}
${threadTag "muted"}
${threadTag "wohnung"}
${threadTag "flagged"}
'';
};
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" ];
};
}

View file

@ -1,414 +0,0 @@
{ config, pkgs, lib, ... }:
let
passcmd = id: "${pkgs.pass}/bin/pass ${id}";
ticks = "''";
in
{
# Maildir <-> Server communication
# --------------------------------
# mbsync: MailDir <-> IMAP
# msmtp: sendmail interface sending mails through your provider.
# client backend
# --------------
# notmuch: Tagdatabase for Emails
# muchsync: notmuch database synctool
# clients
# -------
# neomutt
home-manager.users.mainUser.accounts.email.accounts = {
#palo_van_dalo-gmx = {
# address = "palo_van_dalo@gmx.de";
# aliases = [ ];
# realName = "Ingolf Wagner";
# userName = "palo_van_dalo@gmx.de";
# passwordCommand = passcmd "mail/gmx/palo_van_dalo@gmx.de";
# smtp = {
# host = "smtp.gmx.net";
# port = 465;
# };
# notmuch.enable = true;
# msmtp = { enable = true; };
#};
#ingolf-wagner-gmx = {
# address = "ingolf.wagner@gmx.de";
# aliases = [ ];
# realName = "Ingolf Wagner";
# userName = "ingolf.wagner@gmx.de";
# passwordCommand = passcmd "mail/gmx/ingolf.wagner@gmx.de";
# smtp = {
# host = "smtp.gmx.net";
# port = 465;
# };
# notmuch.enable = true;
# msmtp = { enable = true; };
#};
#pali_palo = {
# address = "pali_palo@web.de";
# aliases = [ ];
# realName = "Ingolf Wagner";
# userName = "pali_palo@web.de";
# passwordCommand = passcmd "mail/web.de/pali_palo@web.de";
# smtp = {
# host = "smtp.web.de";
# port = 465;
# };
# notmuch.enable = true;
# msmtp = { 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 = passcmd "mail/gmail/palipalo9@googlemail.com";
smtp = {
host = "smtp.gmail.com";
port = 465;
};
notmuch.enable = true;
msmtp = {
enable = true;
};
gpg = {
encryptByDefault = true;
signByDefault = true;
key = "42AC51C9482D0834CF488AF1389EC2D64AC71EAC";
};
};
terranix_org = {
address = "palo@terranix.org";
aliases = [ ];
realName = "Ingolf Wagner";
userName = "palo@terranix.org";
passwordCommand = passcmd "mail/namecheap/palo@terranix.org";
smtp = {
host = "mail.privateemail.com";
port = 465;
};
notmuch.enable = true;
msmtp = {
enable = true;
};
};
ingolf-wagner = {
address = "contact@ingolf-wagner.de";
aliases = [ ];
realName = "Ingolf Wagner";
userName = "contact@ingolf-wagner.de";
passwordCommand = passcmd "mail/namecheap/contact@ingolf-wagner.de";
notmuch.enable = true;
gpg = {
encryptByDefault = true;
signByDefault = true;
key = "42AC51C9482D0834CF488AF1389EC2D64AC71EAC";
};
smtp = {
host = "mail.privateemail.com";
port = 465;
};
msmtp = {
enable = true;
# msmtp --serverinfo --tls --tls-certcheck=off -a ingolf-wagner
};
};
};
# install mail programs
home-manager.users.mainUser.programs.msmtp.enable = true;
home-manager.users.mainUser.programs.notmuch.enable = true;
# enable html emails
home-manager.users.mainUser.home.file.".mailcap".text = ''
text/html; ${pkgs.elinks}/bin/elinks -dump ; copiousoutput;
'';
home-manager.users.mainUser.home.file.".muttrc".text =
let
index_format = pkgs.writers.writeDash "index_format" ''
# http://www.mutt.org/doc/manual/#formatstrings
recipent="$(echo $1 | sed 's/[^,]*<\([^>]*\)[^,]*/ \1/g')"
echo "%4C %Z %?GI?%GI& ? %[%y-%m-%d %H:%M] %-20.20a %?M?(%3M)& ? %s %> $recipent %?g?%g?%"
'';
in
''
# gpg
set crypt_use_gpgme=yes
set crypt_autosign=yes
set crypt_verify_sig=yes
set crypt_replysign=yes
set crypt_replyencrypt=yes
set crypt_replysignencrypted=yes
# mutt is not smart enough to see if I have a key or not
#set crypt_autoencrypt = yes
set pgp_check_gpg_decrypt_status_fd
set pgp_use_gpg_agent = yes
set pgp_self_encrypt = yes # needs default key
set pgp_default_key = 42AC51C9482D0834CF488AF1389EC2D64AC71EAC
# read html mails
auto_view text/html
set mailcap_path = ~/.mailcap
# notmuch
set nm_default_uri="notmuch://$HOME/Maildir" # path to the maildir
set nm_record = yes
set nm_record_tags = "-inbox me archive"
set nm_query_type = "threads" # we are not only interessted in messages
set virtual_spoolfile=yes # enable virtual folders
set sendmail=${
pkgs.writers.writeBash "msmtp" ''
${pkgs.coreutils}/bin/tee >(${pkgs.notmuch}/bin/notmuch insert --create-folder +sent) | \
${pkgs.msmtp}/bin/msmtpq "$@"
''
}
set from="contact@ingolf-wagner.de"
#alternates ^.*@ingolf-wagner\.de$ ^.*@.*\.r$
set use_from=yes
set envelope_from=yes
set reverse_name
set sort=threads
set index_format="${index_format} %r |"
folder-hook 'Discourse.*' 'set sort=reverse-date'
virtual-mailboxes "INBOX" "notmuch://?query=(tag:inbox or (tag:sent and not tag:archive)) AND NOT tag:muted AND NOT tag:list AND NOT tag:fraud AND NOT tag:junk"
virtual-mailboxes "Unread" "notmuch://?query=(tag:unread AND NOT tag:muted)"
virtual-mailboxes "Space left" "notmuch://?query=((tag:spaceleft OR tag:space-lef) AND NOT tag:muted)"
virtual-mailboxes "Sononym" "notmuch://?query=(tag:sononym AND NOT tag:muted)"
virtual-mailboxes "c-base" "notmuch://?query=(tag:cbase AND NOT tag:muted)"
virtual-mailboxes "shopping" "notmuch://?query=((tag:billing OR tag:shopping) AND NOT tag:muted)"
virtual-mailboxes "Immobilien" "notmuch://?query=(tag:immobilien AND NOT tag:muted)"
virtual-mailboxes "NixOS Github" "notmuch://?query=(tag:github AND tag:nixos AND NOT tag:muted)"
virtual-mailboxes "Discourse.all" "notmuch://?query=(tag:discourse AND NOT tag:muted)"
virtual-mailboxes "Discourse.development" "notmuch://?query=(tag:discourse AND tag:development AND NOT tag:muted)"
virtual-mailboxes "Discourse.announcements" "notmuch://?query=(tag:discourse AND tag:announcements AND NOT tag:muted)"
virtual-mailboxes "Discourse.links" "notmuch://?query=(tag:discourse AND tag:links AND NOT tag:muted)"
virtual-mailboxes "Discourse.games" "notmuch://?query=(tag:discourse AND tag:games AND NOT tag:muted)"
virtual-mailboxes "Discourse.meta" "notmuch://?query=(tag:discourse AND tag:meta AND NOT tag:muted)"
virtual-mailboxes "Discourse.events" "notmuch://?query=(tag:discourse AND tag:events AND NOT tag:muted)"
virtual-mailboxes "Flagged" "notmuch://?query=tag:flagged"
virtual-mailboxes "Archive" "notmuch://?query=tag:archive"
virtual-mailboxes "Sent" "notmuch://?query=tag:sent"
virtual-mailboxes "Fraud" "notmuch://?query=(tag:fraud)"
virtual-mailboxes "Junk" "notmuch://?query=(tag:junk)"
virtual-mailboxes "All" "notmuch://?query=*"
tag-transforms "junk" "k" \
"unread" "u" \
"replied" "" \
# notmuch bindings
bind index \\\\ noop
bind pager \\ noop
bind pager \\\\ noop
macro index \\\\ "<vfolder-from-query>" # looks up a hand made query
macro pager \\\\ "<vfolder-from-query>" # looks up a hand made query
macro index + "<modify-labels>+flagged\n<sync-mailbox>" # tag as starred
macro pager + "<modify-labels>+flagged\n<sync-mailbox>" # tag as starred
macro index ! "<modify-labels>+flagged\n<sync-mailbox>" # tag as starred
macro pager ! "<modify-labels>+flagged\n<sync-mailbox>" # tag as starred
macro index - "<modify-labels>-flagged\n<sync-mailbox>" # tag as unstarred
macro pager - "<modify-labels>-flagged\n<sync-mailbox>" # tag as unstarred
# Address Book
# ------------
set query_command="${pkgs.notmuch-addrlookup}/bin/notmuch-addrlookup --mutt '%s'"
# keys bindings
# -------------
bind index d noop
bind index D noop
bind pager d noop
bind pager D noop
macro index D "<modify-labels-then-hide>-inbox -unread +deleted\n" # tag as deleted mail
macro index d "<modify-labels>-deleted\n" # tag as deleted mail
macro pager D "<modify-labels-then-hide>-inbox -unread +deleted\n" # tag as deleted mail
macro pager d "<modify-labels>-deleted\n" # tag as deleted mail
bind index S noop
bind index s noop
bind pager S noop
bind pager s noop
macro index S "<modify-labels-then-hide>-inbox -unread +junk\n" # tag as junk mail
macro index s "<modify-labels>-junk\n" # tag as junk mail
macro pager S "<modify-labels-then-hide>-inbox -unread +junk\n" # tag as junk mail
macro pager s "<modify-labels>-junk\n" # tag as junk mail
bind index r noop
bind index R noop
bind pager r noop
bind pager R noop
macro index r "<group-reply>" # reply to all
macro index R "<reply>" # reply
macro pager r "<group-reply>" # reply to all
macro pager R "<reply>" # reply
bind index A noop
bind index a noop
bind pager A noop
bind pager a noop
macro index A "<modify-labels>+archive -unread -inbox\n" # tag as Archived
macro index a "<modify-labels>-archive\n" # tag as Archived
macro pager A "<modify-labels>+archive -unread -inbox\n" # tag as Archived
macro pager a "<modify-labels>-archive\n" # tag as Archived
bind index U noop
bind index u noop
bind pager U noop
bind pager u noop
macro index u "<modify-labels>+unread\n"
macro index U "<modify-labels>-unread\n"
macro pager u "<modify-labels>+unread\n"
macro pager U "<modify-labels>-unread\n"
bind index l noop
bind pager l noop
macro index l "<modify-labels>" # set tags manual
macro pager l "<modify-labels>" # set tags manual
# taskwarrior
# -----------
# from https://www.nixternal.com/mark-e-mails-in-mutt-as-tasks-in-taskwarrior/
bind index t noop
bind pager t noop
bind index T noop
bind pager T noop
macro index T "<pipe-message>${
pkgs.writers.writeDash "mutt2task" ''
${pkgs.taskwarrior}/bin/task add +email scheduled:today E-mail: $( ${pkgs.gnugrep}/bin/grep 'Subject' $* | awk -F: '{print $2}' )
''
}<enter>"
bind index i noop
bind pager i noop
bind index I noop
bind pager I noop
# notmuch config set query.chat <query>
# notmuch search query:chat
# parse From and To, collect all mail addresses and remove my own mail lists, and create a query from it
#From:
#To:
macro index,pager I "<pipe-message>${
pkgs.writers.writeDash "show_query" ''
cat
''
}<enter>"
# top index bar in email view
set pager_index_lines=7
# top_index_bar toggle
macro pager ,@1 "<enter-command> set pager_index_lines=0; macro pager ] ,@2 'Toggle indexbar<Enter>"
macro pager ,@2 "<enter-command> set pager_index_lines=3; macro pager ] ,@3 'Toggle indexbar<Enter>"
macro pager ,@3 "<enter-command> set pager_index_lines=7; macro pager ] ,@1 'Toggle indexbar<Enter>"
macro pager ] ,@1 'Toggle indexbar
# sidebar
# -------
set sidebar_width = 20
set sidebar_visible = yes # set to "no" to disable sidebar view at startup
color sidebar_new yellow default
# sidebar bindings
bind index <left> sidebar-prev # got to previous folder in sidebar
bind index <right> sidebar-next # got to next folder in sidebar
bind index <space> sidebar-open # open selected folder from sidebar
# sidebar toggle
#macro index,pager ,@) "<enter-command> set sidebar_visible=no; macro index,pager [ ,@( 'Toggle sidebar'<Enter>"
#macro index,pager ,@( "<enter-command> set sidebar_visible=yes; macro index,pager [ ,@) 'Toggle sidebar'<Enter>"
#macro index,pager [ ,@( 'Toggle sidebar' # toggle the sidebar
'';
environment.systemPackages =
let
mailSync = pkgs.writers.writeDashBin "mail-sync" ''
${pkgs.muchsync}/bin/muchsync mailfetcher@pepe.private \
--config /home/mailfetcher/.config/notmuch/notmuchrc \
--nonew
'';
mailSend = pkgs.writers.writeDashBin "mail-send" ''
${pkgs.msmtp}/bin/msmtp-queue -r
'';
mailView = pkgs.writers.writeDashBin "mail-view" ''
${pkgs.neomutt}/bin/neomutt"$@"
'';
mutt = pkgs.writers.writeDashBin "mutt" ''
${pkgs.neomutt}/bin/neomutt"$@"
'';
mail = pkgs.writers.writeDashBin "mail" ''
${mailSync}/bin/mail-sync
${mailView}/bin/mail-view
${mailSend}/bin/mail-send
${mailSync}/bin/mail-sync
'';
mailDelete =
let notmuch = "${pkgs.notmuch}/bin/notmuch";
in pkgs.writers.writeBashBin "mail-delete" ''
set -efu
set -o pipefail
if ! ${notmuch} search --exclude=false tag:deleted | tac ; then
echo 'No killed mail.'
exit 1
fi
printf 'want do rm this mail? \[y/N\] '
read REPLY
case "$REPLY" in
y|Y) :;; # continue
*)
echo 'abort.'
exit 2
;;
esac
${notmuch} search --output=files --exclude=false tag:deleted | while read line; do rm -v "$line" ; done
${notmuch} new
'';
plot_maildir =
let
years = [ 2010 2011 2012 2013 2014 2015 2016 2017 2018 2019 2020 2021 2022 ];
file = "~/Maildir/usage.csv";
append_year = year: ''
echo -n "${toString year}," >> ${file}
${pkgs.notmuch}/bin/notmuch count -- date:${toString year} >> ${file}
'';
in
pkgs.writers.writeBashBin "mail-create-statistics" ''
rm ${file}
${lib.concatStringsSep "\n" (map append_year years)}
'';
in
[
pkgs.notmuch
pkgs.muchsync
mail
mailSync
mailView
mailSend
pkgs.neomutt
mutt
mailDelete
plot_maildir
];
}

View file

@ -1,52 +0,0 @@
{ config, lib, pkgs, ... }:
{
# https://docs.tdarr.io/docs/installation/docker/run-compose
virtualisation.oci-containers = {
containers.tdarr = {
volumes = [
"/srv2/tdarr/server:/app/server"
"/srv2/tdarr/configs:/app/configs"
"/srv2/tdarr/logs:/app/logs"
"/srv2/tdarr/transcode_cache:/temp"
"/media:/media"
];
environment = {
serverIP = "0.0.0.0";
serverPort = "8266";
webUIPort = "8265";
internalNode = "false";
inContainer = "true";
nodeName = "ServerNode";
TZ = "Europe/Berlin";
PUID = toString config.users.users.media.uid;
PGID = toString config.users.groups.media.gid;
};
ports = [
"8265:8265" # WebUI
"8266:8266" # server port
];
image = "ghcr.io/haveagitgat/tdarr:latest"; # Warning: if the tag does not change, the image will not be updated
extraOptions = [ "--network=bridge" ];
};
};
networking.firewall.interfaces.wg0.allowedTCPPorts = [ 8266 ];
networking.firewall.interfaces.wg0.allowedUDPPorts = [ 8266 ];
networking.firewall.interfaces.enp0s31f6.allowedTCPPorts = [ 8266 ];
networking.firewall.interfaces.enp0s31f6.allowedUDPPorts = [ 8266 ];
services.nginx.virtualHosts."tdarr.${config.networking.hostName}.private" = {
serverAliases = [ "tdarr.${config.networking.hostName}" ];
extraConfig = ''
allow ${config.tinc.private.subnet};
deny all;
'';
locations."/" = {
proxyPass = "http://localhost:8265";
proxyWebsockets = true;
};
};
}

View file

@ -1,259 +0,0 @@
{ lib, pkgs, config, ... }:
let
hostInterface = "enp3s0";
hostAddress = "192.168.100.30";
containerAddress = "192.168.100.31";
uiPort = 9091;
in
{
sops.secrets.nordvpn = { };
sops.secrets.transmissionPushover = { };
containers.torrent = {
# mount host folders
bindMounts = {
#password = {
# hostPath = "/run/secrets/transmission_password";
# mountPoint = "/run/secrets/transmission_password";
# isReadOnly = true;
#};
transmissionPushover = {
hostPath = "/run/secrets/transmissionPushover";
mountPoint = "/run/secrets/transmissionPushover";
isReadOnly = true;
};
nordvpnPassword = {
hostPath = "/run/secrets/nordvpn";
mountPoint = "/run/secrets/nordvpn";
isReadOnly = true;
};
media = {
hostPath = "/media";
mountPoint = "/media"; # must be here otherwise transmission can't see the folder
isReadOnly = false;
};
lib = {
hostPath = "/media/torrent/torrent1_config";
mountPoint = "/var/lib/transmission/.config";
isReadOnly = false;
};
};
# container network setup
# see also nating on host system.
privateNetwork = true;
hostAddress = hostAddress;
localAddress = containerAddress;
autoStart = true;
# needed for openvpn
enableTun = true;
config = { config, pkgs, lib, ... }: {
system.stateVersion = "21.05";
services.journald.extraConfig = "SystemMaxUse=1G";
# allow transmission to write in syncthing folders
users.groups.syncthing = {
gid = config.ids.gids.syncthing;
members = [ "transmission" ];
};
services.transmission = {
enable = true;
settings = {
download-dir = "/media/torrent/downloads";
incomplete-dir = "/media/torrent/incomplete";
incomplete-dir-enabled = true;
message-level = 1;
umask = 2;
rpc-whitelist-enabled = false;
rpc-host-whitelist-enabled = false;
rpc-port = uiPort;
rpc-enable = true;
rpc-bind-address = "0.0.0.0";
# "normal" speed limits
speed-limit-down-enabled = false;
speed-limit-down = 800;
speed-limit-up-enabled = true;
speed-limit-up = 3000;
upload-slots-per-torrent = 8;
# Queuing
# When true, Transmission will only download
# download-queue-size non-stalled torrents at once.
download-queue-enabled = true;
download-queue-size = 3;
# When true, torrents that have not shared data for
# queue-stalled-minutes are treated as 'stalled'
# and are not counted against the queue-download-size
# and seed-queue-size limits.
queue-stalled-enabled = true;
queue-stalled-minutes = 60;
# When true. Transmission will only seed seed-queue-size
# non-stalled torrents at once.
seed-queue-enabled = false;
seed-queue-size = 10;
# Enable UPnP or NAT-PMP.
peer-port = 51413;
port-forwarding-enabled = false;
# Start torrents as soon as they are added
start-added-torrents = true;
};
};
networking.firewall = {
allowedTCPPorts = [ 51413 ];
allowedUDPPorts = [ 51413 ];
# only allow access via nginx (proxy to localhost)
interfaces.eth0 = {
allowedTCPPorts = [ uiPort ];
allowedUDPPorts = [ uiPort ];
};
};
# bind transmission to openvpn
systemd.services.transmission = {
bindsTo = [ "openvpn-nordvpn.service" ];
after = [ "openvpn-nordvpn.service" ];
serviceConfig = {
Restart = "always";
EnvironmentFile = [
"/run/secrets/transmissionPushover"
];
BindPaths = lib.mkForce [
"/media" # this is needed otherwise cp -l is not working
"/var/lib/transmission/.config/transmission-daemon"
];
};
};
services.openvpn.servers.nordvpn.updateResolvConf = true;
services.openvpn.servers.nordvpn.config = ''
client
dev tun
proto udp
remote 152.89.163.99 1194
dhcp-option DNS 8.8.8.8
remote-random
nobind
tun-mtu 1500
tun-mtu-extra 32
mssfix 1450
persist-key
persist-tun
ping 15
ping-restart 0
ping-timer-rem
reneg-sec 0
comp-lzo no
remote-cert-tls server
auth-user-pass /run/secrets/nordvpn
verb 3
pull
resolv-retry infinite
fast-io
cipher AES-256-CBC
auth SHA512
<ca>
-----BEGIN CERTIFICATE-----
MIIFCjCCAvKgAwIBAgIBATANBgkqhkiG9w0BAQ0FADA5MQswCQYDVQQGEwJQQTEQ
MA4GA1UEChMHTm9yZFZQTjEYMBYGA1UEAxMPTm9yZFZQTiBSb290IENBMB4XDTE2
MDEwMTAwMDAwMFoXDTM1MTIzMTIzNTk1OVowOTELMAkGA1UEBhMCUEExEDAOBgNV
BAoTB05vcmRWUE4xGDAWBgNVBAMTD05vcmRWUE4gUm9vdCBDQTCCAiIwDQYJKoZI
hvcNAQEBBQADggIPADCCAgoCggIBAMkr/BYhyo0F2upsIMXwC6QvkZps3NN2/eQF
kfQIS1gql0aejsKsEnmY0Kaon8uZCTXPsRH1gQNgg5D2gixdd1mJUvV3dE3y9FJr
XMoDkXdCGBodvKJyU6lcfEVF6/UxHcbBguZK9UtRHS9eJYm3rpL/5huQMCppX7kU
eQ8dpCwd3iKITqwd1ZudDqsWaU0vqzC2H55IyaZ/5/TnCk31Q1UP6BksbbuRcwOV
skEDsm6YoWDnn/IIzGOYnFJRzQH5jTz3j1QBvRIuQuBuvUkfhx1FEwhwZigrcxXu
MP+QgM54kezgziJUaZcOM2zF3lvrwMvXDMfNeIoJABv9ljw969xQ8czQCU5lMVmA
37ltv5Ec9U5hZuwk/9QO1Z+d/r6Jx0mlurS8gnCAKJgwa3kyZw6e4FZ8mYL4vpRR
hPdvRTWCMJkeB4yBHyhxUmTRgJHm6YR3D6hcFAc9cQcTEl/I60tMdz33G6m0O42s
Qt/+AR3YCY/RusWVBJB/qNS94EtNtj8iaebCQW1jHAhvGmFILVR9lzD0EzWKHkvy
WEjmUVRgCDd6Ne3eFRNS73gdv/C3l5boYySeu4exkEYVxVRn8DhCxs0MnkMHWFK6
MyzXCCn+JnWFDYPfDKHvpff/kLDobtPBf+Lbch5wQy9quY27xaj0XwLyjOltpiST
LWae/Q4vAgMBAAGjHTAbMAwGA1UdEwQFMAMBAf8wCwYDVR0PBAQDAgEGMA0GCSqG
SIb3DQEBDQUAA4ICAQC9fUL2sZPxIN2mD32VeNySTgZlCEdVmlq471o/bDMP4B8g
nQesFRtXY2ZCjs50Jm73B2LViL9qlREmI6vE5IC8IsRBJSV4ce1WYxyXro5rmVg/
k6a10rlsbK/eg//GHoJxDdXDOokLUSnxt7gk3QKpX6eCdh67p0PuWm/7WUJQxH2S
DxsT9vB/iZriTIEe/ILoOQF0Aqp7AgNCcLcLAmbxXQkXYCCSB35Vp06u+eTWjG0/
pyS5V14stGtw+fA0DJp5ZJV4eqJ5LqxMlYvEZ/qKTEdoCeaXv2QEmN6dVqjDoTAo
k0t5u4YRXzEVCfXAC3ocplNdtCA72wjFJcSbfif4BSC8bDACTXtnPC7nD0VndZLp
+RiNLeiENhk0oTC+UVdSc+n2nJOzkCK0vYu0Ads4JGIB7g8IB3z2t9ICmsWrgnhd
NdcOe15BincrGA8avQ1cWXsfIKEjbrnEuEk9b5jel6NfHtPKoHc9mDpRdNPISeVa
wDBM1mJChneHt59Nh8Gah74+TM1jBsw4fhJPvoc7Atcg740JErb904mZfkIEmojC
VPhBHVQ9LHBAdM8qFI2kRK0IynOmAZhexlP/aT/kpEsEPyaZQlnBn3An1CRz8h0S
PApL8PytggYKeQmRhl499+6jLxcZ2IegLfqq41dzIjwHwTMplg+1pKIOVojpWA==
-----END CERTIFICATE-----
</ca>
key-direction 1
<tls-auth>
#
# 2048 bit OpenVPN static key
#
-----BEGIN OpenVPN Static key V1-----
e685bdaf659a25a200e2b9e39e51ff03
0fc72cf1ce07232bd8b2be5e6c670143
f51e937e670eee09d4f2ea5a6e4e6996
5db852c275351b86fc4ca892d78ae002
d6f70d029bd79c4d1c26cf14e9588033
cf639f8a74809f29f72b9d58f9b8f5fe
fc7938eade40e9fed6cb92184abb2cc1
0eb1a296df243b251df0643d53724cdb
5a92a1d6cb817804c4a9319b57d53be5
80815bcfcb2df55018cc83fc43bc7ff8
2d51f9b88364776ee9d12fc85cc7ea5b
9741c4f598c485316db066d52db4540e
212e1518a9bd4828219e24b20d88f598
a196c9de96012090e333519ae18d3509
9427e7b372d348d352dc4c85e18cd4b9
3f8a56ddb2e64eb67adfc9b337157ff4
-----END OpenVPN Static key V1-----
</tls-auth>
'';
};
};
# give containers internet access
networking.nat.enable = true;
networking.nat.internalInterfaces = [ "ve-torrent" ];
networking.nat.externalInterface = hostInterface;
# open ports for logging
#networking.firewall.interfaces."ve-torrent".allowedTCPPorts =
# [ 5044 12304 12305 ];
#networking.firewall.interfaces."ve-torrent".allowedUDPPorts =
# [ 5044 12304 12305 ];
# host nginx setup
# curl -H "Host: transmission.robi.private" https://robi.private/ < will work
# curl -H "Host: transmission.robi.private" https://144.76.13.147/ < wont work
services.nginx = {
enable = true;
recommendedProxySettings = true;
virtualHosts = {
"transmission.${config.networking.hostName}.private" = {
extraConfig = ''
allow ${config.tinc.private.subnet};
deny all;
'';
locations."/" = {
proxyPass = "http://${containerAddress}:${toString uiPort}";
};
};
};
};
}

View file

@ -1,40 +0,0 @@
{ config, lib, pkgs, ... }:
{
virtualisation.oci-containers = {
containers.unmanic = {
volumes = [
"/media/arr/unmanic/config:/config"
#"/media/arr/unmanic/library:/library"
"/media/arr/unmanic/tmp:/tmp/unmanic"
"/media:/library"
];
environment = {
PUID = toString config.users.users.media.uid;
PGID = toString config.users.groups.media.gid;
};
ports = [
"127.0.0.1:8889:8888"
];
image = "josh5/unmanic:latest";
};
};
#networking.firewall.interfaces.wg0.allowedTCPPorts = [ 8266 ];
#networking.firewall.interfaces.wg0.allowedUDPPorts = [ 8266 ];
#networking.firewall.interfaces.enp0s31f6.allowedTCPPorts = [ 8266 ];
#networking.firewall.interfaces.enp0s31f6.allowedUDPPorts = [ 8266 ];
services.nginx.virtualHosts."unmanic.${config.networking.hostName}.private" = {
extraConfig = ''
allow ${config.tinc.private.subnet};
deny all;
'';
locations."/" = {
proxyPass = "http://localhost:8889";
proxyWebsockets = true;
};
};
}

View file

@ -1,81 +0,0 @@
{ config, pkgs, lib, ... }: {
imports = [
../../components
../../modules
./hardware-configuration.nix
./tinc.nix
./syncthing.nix
];
security.wrappers = {
pmount = {
source = "${pkgs.pmount}/bin/pmount";
setuid = true;
owner = "root";
group = "root";
};
pumount = {
source = "${pkgs.pmount}/bin/pumount";
setuid = true;
owner = "root";
group = "root";
};
};
components.gui.enable = true;
configuration.desktop = {
width = 1366;
height = 768;
};
# grub configuraton
# -----------------
boot.loader.grub.enable = true;
boot.loader.grub.efiSupport = true;
boot.loader.grub.device = "/dev/sda";
boot.loader.grub.efiInstallAsRemovable = true;
boot.tmpOnTmpfs = true;
networking.networkmanager.enable = true;
networking.hostName = "mobi";
# Set your time zone.
time.timeZone = "Europe/Berlin";
environment.systemPackages = with pkgs; [
vim
wget
htop
silver-searcher
];
environment.extraInit = ''
# use vi shortcuts
# ----------------
set -o vi
EDITOR=vim
'';
boot.supportedFilesystems = [ "zfs" ];
networking.hostId = "5794a3f8";
services.openssh.enable = true;
components.network.sshd.onlyTincAccess = false;
users.users.root.openssh.authorizedKeys.keys = [ "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== contact@ingolf-wagner.de" ];
# This value determines the NixOS release from which the default
# settings for stateful data, like file locations and database versions
# on your system were taken. Its perfectly fine and recommended to leave
# this value at the release version of the first install of this system.
# Before changing this value read the documentation for this option
# (e.g. man configuration.nix or on https://nixos.org/nixos/options.html).
system.stateVersion = "22.05"; # Did you read the comment?
}

View file

@ -1,47 +0,0 @@
# 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, modulesPath, ... }:
{
imports =
[
(modulesPath + "/installer/scan/not-detected.nix")
];
boot.initrd.availableKernelModules = [ "ehci_pci" "ahci" "xhci_pci" "usb_storage" "usbhid" "sd_mod" "sdhci_pci" ];
boot.initrd.kernelModules = [ "dm-snapshot" ];
boot.kernelModules = [ "kvm-intel" ];
boot.extraModulePackages = [ ];
fileSystems."/" =
{
device = "/dev/disk/by-uuid/978cfc56-b47d-4d94-adae-18a4209519a5";
fsType = "ext4";
};
boot.initrd.luks.devices."root-enc".device = "/dev/disk/by-uuid/cf30f4a6-578e-418a-9d18-d32fbf992b0c";
fileSystems."/boot" =
{
device = "/dev/disk/by-uuid/AEE5-221F";
fsType = "vfat";
};
swapDevices = [ ];
# Enables DHCP on each ethernet and wireless interface. In case of scripted networking
# (the default) this is the recommended approach. When using systemd-networkd it's
# still possible to use this option, but it's recommended to use it in conjunction
# with explicit per-interface declarations with `networking.interfaces.<interface>.useDHCP`.
networking.useDHCP = lib.mkDefault true;
# networking.interfaces.enp0s25.useDHCP = lib.mkDefault true;
# networking.interfaces.tinc.private.useDHCP = lib.mkDefault true;
# networking.interfaces.tinc.retiolum.useDHCP = lib.mkDefault true;
# networking.interfaces.tinc.secret.useDHCP = lib.mkDefault true;
# networking.interfaces.virbr0.useDHCP = lib.mkDefault true;
# networking.interfaces.wlp3s0.useDHCP = lib.mkDefault true;
powerManagement.cpuFreqGovernor = lib.mkDefault "ondemand";
hardware.cpu.intel.updateMicrocode = lib.mkDefault config.hardware.enableRedistributableFirmware;
}

View file

@ -1,37 +0,0 @@
{ config, pkgs, lib, ... }: {
services.syncthing = {
enable = true;
openDefaultPorts = false;
user = "palo";
dataDir = "/home/palo/.syncthing";
configDir = "/home/palo/.syncthing";
overrideFolders = true;
folders = {
# on encrypted drive
# ------------------
private = {
enable = true;
path = "/home/palo/private";
};
desktop = {
enable = true;
path = "/home/palo/desktop";
};
finance = {
enable = true;
path = "/home/palo/finance";
};
password-store = {
enable = true;
path = "/home/palo/.password-store";
};
};
};
services.permown."/home/palo/music-library" = {
owner = "palo";
group = "users";
};
}

View file

@ -1,5 +0,0 @@
{ config, ... }:
{
tinc.private.enable = true;
tinc.private.ipv4 = "10.23.42.23";
}

View file

@ -1,78 +0,0 @@
{ config, lib, pkgs, ... }:
{
services.mpd = {
enable = true;
network.listenAddress = "any";
musicDirectory = "/media/syncthing/music-library";
playlistDirectory = "/media/syncthing/music-library/playlists";
};
users.groups."syncthing".members = [ "mpd" ];
sound.enable = true;
networking.firewall.allowedTCPPorts = [
6680 # mopidy
6600 # mpd
1234 # zeroconf
];
users.users."spotifyd" = {
isSystemUser = true;
group = "spotifyd";
};
users.groups.spotifyd = { };
sops.secrets.spotify_pass.owner = "spotifyd";
sops.secrets.spotify_user.owner = "spotifyd";
services.spotifyd.enable = true;
services.spotifyd.settings = {
global = {
username_cmd = "cat ${config.sops.secrets.spotify_user.path}";
password_cmd = "cat ${config.sops.secrets.spotify_pass.path}";
backend = "alsa"; # use portaudio for macOS [homebrew]
# The alsa mixer used by `spotifyd`.
mixer = "PCM";
# A script that gets evaluated in the user's shell when the song changes [aliases: onevent]
on-song-change-hook = "${pkgs.mpc_cli}/bin/mpc --host localhost --port 6600 stop";
# The volume controller. Each one behaves different to
# volume increases. For possible values, run
# `spotifyd --help`.
volume_controller = "alsa";
# The name that gets displayed under the connect tab on
# official clients. Spaces are not allowed!
device_name = "DJane";
# The audio bitrate. 96, 160 or 320 kbit/s
bitrate = 320;
# If set to true, audio data does NOT get cached.
no_audio_cache = true;
# Volume on startup between 0 and 100
# NOTE: This variable's type will change in v0.4, to a number (instead of string)
initial_volume = "90";
# If set to true, enables volume normalisation between songs.
volume_normalisation = false;
# The normalisation pregain that is applied for each song.
# normalisation_pregain = -10
# The port `spotifyd` uses to announce its service over the network.
zeroconf_port = 1234;
# The displayed device type in Spotify clients.
# Can be unknown, computer, tablet, smartphone, speaker, t_v,
# a_v_r (Audio/Video Receiver), s_t_b (Set-Top Box), and audio_dongle.
device_type = "computer";
};
};
}

View file

@ -1,20 +0,0 @@
{ pkgs, lib, config, ... }: {
services.mysql = {
enable = true;
package = pkgs.mysql80;
initialScript = pkgs.writeText "initScript" ''
CREATE USER 'admin'@'%' IDENTIFIED BY 'admin';
GRANT ALL PRIVILEGES ON * . * TO 'admin'@'%';
'';
};
services.mysqlBackup = {
enable = true;
databases = [ "property" ];
#user = "admin";
};
backup.dirs = [ config.services.mysqlBackup.location ];
}

View file

@ -1,41 +0,0 @@
{ pkgs, lib, ... }:
let
access_log_sink = "workhorse.private:12304";
error_log_sink = "workhorse.private:12305";
in
{
security.acme.defaults.email = "contact@ingolf-wagner.de";
security.acme.acceptTerms = true;
services.nginx = {
# Use recommended settings
recommendedGzipSettings = lib.mkDefault true;
recommendedOptimisation = lib.mkDefault true;
recommendedProxySettings = lib.mkDefault true;
recommendedTlsSettings = lib.mkDefault true;
# for graylog logging
#commonHttpConfig = ''
# log_format graylog2_json escape=json '{ "timestamp": "$time_iso8601", '
# '"facility": "nginx", '
# '"src_addr": "$remote_addr", '
# '"body_bytes_sent": $body_bytes_sent, '
# '"request_time": $request_time, '
# '"response_status": $status, '
# '"request": "$request", '
# '"request_method": "$request_method", '
# '"host": "$host",'
# '"upstream_cache_status": "$upstream_cache_status",'
# '"upstream_addr": "$upstream_addr",'
# '"http_x_forwarded_for": "$http_x_forwarded_for",'
# '"http_referrer": "$http_referer", '
# '"http_user_agent": "$http_user_agent" }';
# access_log syslog:server=${access_log_sink} graylog2_json;
# error_log syslog:server=${error_log_sink};
#'';
};
services.nginx.package = pkgs.nginxMainline;
}

View file

@ -1,43 +0,0 @@
{ lib, pkgs, config, ... }: {
users.users.property = { isSystemUser = true; };
systemd.services.property = {
enable = true;
wantedBy = [ "multi-user.target" ];
path = [
(pkgs.python3.withPackages (ps:
with ps; [
flask
selenium
beautifulsoup4
urllib3
sqlalchemy
mysqlclient
pytest
dateparser
geopy
nltk
click
]))
];
serviceConfig = { User = "property"; };
script = ''
FLASK_APP=${<property>}/server.py \
FLASK_RUN_PORT=7888 \
flask run --host 0.0.0.0 \
"$@"
'';
};
services.nginx = {
enable = true;
virtualHosts = {
"property.workhorse.private" = {
locations."/" = { proxyPass = "http://localhost:7888"; };
};
};
};
}

View file

@ -1,16 +0,0 @@
{ lib, config, pkgs, ... }: {
backup.enable = true;
# provide repository
services.borgbackup.repos = {
default = {
quota = "300G";
allowSubRepos = true;
authorizedKeys = [
];
};
};
}

View file

@ -1,13 +0,0 @@
{ ... }:
{
services.nix-serve = {
enable = true;
# needed if i want to trust my own build packages and dirivations
# nix-store --generate-binary-cache-key key-name secret-key-file public-key-file
# secretKeyFile = sops.nixServeSecretKeyFile.path
};
}

View file

@ -1,34 +0,0 @@
{ config, lib, pkgs, ... }:
let
domain = "md.ingolf-wagner.de";
in
{
services.nginx.enable = true;
services.nginx.virtualHosts.hedgedoc = {
enableACME = true;
forceSSL = true;
serverName = domain;
locations."/" = {
proxyPass = "http://localhost:${toString config.services.hedgedoc.settings.port}";
proxyWebsockets = true;
};
};
services.hedgedoc = {
enable = true;
settings = {
db = {
dialect = "sqlite";
storage = "/var/lib/hedgedoc/db.sqlite";
useCDN = false;
};
allowFreeURL = true;
domain = domain;
port = 3091;
useCDN = false;
};
};
}

View file

@ -1,102 +0,0 @@
{ lib, config, pkgs, ... }: {
imports = [
# ../../system/all/nginx-ingolf-wagner-de.nix
../../system/all/defaults.nix
../../components
../../modules
./hetzner.nix
./borg.nix
#./codimd.nix
#./gitea.nix
#./nextcloud.nix
./packages.nix
#./taskserver.nix
#./vaultwarden.nix
#./nginx.nix
#./nginx-wkd.nix
./network-tinc.nix
#./network-wireguard.nix
./media-share.nix
#./media-jellyfin.nix
./media-syncthing.nix
#./media-transmission.nix
#./media-transmission2.nix
#./media-arr.nix
./social-jitsi.nix
# matrix
#./social-matrix.nix
# logging
./loki.nix
./loki-promtail.nix
./prometheus.nix
./grafana.nix
./telegraf.nix
./sync-opentracker.nix
./sync-torrent.nix
./cache.nix
];
components.terminal.enable = true;
components.mainUser.enable = true;
components.gui.enable = false;
components.network.enable = true;
components.network.wifi.enable = false;
# 2 hours = 2 * 60 * 60 = 7200 seconds
#services.netdata.config.global.history = 7200;
# 4 hours = 4 * 60 * 60 = 14440 seconds
services.netdata.config.global.history = 14440;
# 24 hours = 24 * 60 * 60 = 86400 seconds
#services.netdata.config.global.history = 86400;
services.sshguard.enable = true;
security.acme.acceptTerms = true;
security.acme.defaults.email = "contact@ingolf-wagner.de";
sops.defaultSopsFile = ../../secrets/robi.yaml;
# virtualisation.docker.enable = false;
services.printing.enable = false;
services.smartd.enable = true;
# chungus rsync
users.users.root.openssh.authorizedKeys.keys = [ "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIJkqVvuJSvRMO5pG2CHNNBxjB7HlJudK4TQs3BhbOWOD" ];
fileSystems."/var/lib/nextcloud" =
{
device = "/dev/vg/nextcloud";
fsType = "ext4";
};
fileSystems."/var/lib/borgbackup" =
{
device = "/dev/vg/borg";
fsType = "ext4";
};
fileSystems."/media" =
{
device = "/dev/vg/media";
fsType = "ext4";
};
# usually part of the wifi.nix module
# because Networkd-wait-online is just failing.
#systemd.services.systemd-networkd-wait-online.enable = false;
systemd.services.NetworkManager-wait-online.enable = false;
}

View file

@ -1,40 +0,0 @@
{ config, lib, pkgs, ... }:
{
services.nginx = {
enable = true;
statusPage = true;
virtualHosts = {
"git.ingolf-wagner.de" = {
forceSSL = true;
enableACME = true;
locations."/" = {
proxyPass = "http://localhost:${toString config.services.gogs.httpPort}";
};
};
};
};
# todo move to forgejo
services.gitea = {
enable = true;
appName = "git.ingolf-wagner.de";
package = pkgs.forgejo;
#cookieSecure = true;
#disableRegistration = true;
settings = {
server.ROOT_URL = "https://git.ingolf-wagner.de/";
server.DOMAIN = "git.ingolf-wagner.de";
service.DISABLE_REGISTRATION = true;
session.COOKIE_SECURE = true;
log.LEVEL = "Warn";
other = {
SHOW_FOOTER_VERSION = false;
};
};
};
backup.dirs = [ "/var/lib/gitea" ];
}

View file

@ -1,24 +0,0 @@
{ config, ... }:
{
services.nginx.virtualHosts.${config.services.grafana.settings.server.domain} = {
extraConfig = ''
allow ${config.tinc.private.subnet};
deny all;
'';
locations."/" = {
proxyPass = "http://localhost:${toString config.services.grafana.settings.server.http_port}";
proxyWebsockets = true;
};
};
services.grafana = {
enable = true;
settings.server = {
domain = "grafana.robi.private";
http_port = 2342;
http_addr = "localhost";
};
};
}

View file

@ -1,16 +0,0 @@
{ config, lib, pkgs, ... }:
{
services.grocy = {
enable = true;
settings = {
culture = "de";
currency = "EUR";
};
hostName = "grocy.ingolf-wagner.de";
nginx.enableSSL = true;
};
backup.dirs = [ config.services.grocy.dataDir ];
}

View file

@ -1,38 +0,0 @@
# 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, modulesPath, ... }:
{
imports =
[
(modulesPath + "/installer/scan/not-detected.nix")
];
boot.initrd.availableKernelModules = [ "ahci" "sd_mod" ];
boot.initrd.kernelModules = [ "dm-snapshot" ];
boot.kernelModules = [ "kvm-intel" ];
boot.extraModulePackages = [ ];
fileSystems."/" =
{
device = "/dev/disk/by-uuid/d6a794d2-1da4-4457-9a9a-a39bf9521ae4";
fsType = "ext4";
};
fileSystems."/boot-1" =
{
device = "/dev/disk/by-uuid/519D-F289";
fsType = "vfat";
};
fileSystems."/boot-2" =
{
device = "/dev/disk/by-uuid/519E-6EF1";
fsType = "vfat";
};
swapDevices = [ ];
powerManagement.cpuFreqGovernor = lib.mkDefault "ondemand";
}

View file

@ -1,123 +0,0 @@
{ config, pkgs, modulesPath, lib, ... }:
let
hostName = "robi";
# apt install -y lshw
# lshw -C network | grep -Poh 'driver=[[:alnum:]]+'
networkInterfaceModule = "r8169";
networkInterface = "enp3s0";
# From the Hetzner control panel
ipv4 = {
address = "144.76.13.147"; # the ip address
gateway = "144.76.13.129"; # the gateway ip address
netmask = "255.255.255.224"; # the netmask -- might not be the same for you!
prefixLength = 27; # must match the netmask, see <https://www.pawprint.net/designresources/netmask-converter.php>
};
ipv6 = {
address = "2a01:4f8:190:9147::1"; # the ipv6 addres
gateway = "fe80::1"; # the ipv6 gateway
prefixLength = 64; # shown in the control panel
};
in
{
imports =
[
# Include the results of the hardware scan.
./hardware-configuration.nix
];
# needed lvm for raid
boot.initrd.kernelModules = [
"dm-snapshot"
"dm_mirror"
"dm_raid"
"dm_region_hash"
];
# Use GRUB2 as the boot loader.
# We don't use systemd-boot because Hetzner uses BIOS legacy boot.
boot.loader.systemd-boot.enable = false;
boot.loader.grub = {
enable = true;
efiSupport = false;
};
# This will mirror all UEFI files, kernels, grub menus and
# things needed to boot to the other drive.
boot.loader.grub.mirroredBoots = [
{ path = "/boot-1"; devices = [ "/dev/sda" ]; }
{ path = "/boot-2"; devices = [ "/dev/sdb" ]; }
];
# We want to still be able to boot without one of these
fileSystems."/boot-1".options = [ "nofail" ];
fileSystems."/boot-2".options = [ "nofail" ];
boot.initrd.luks.reusePassphrases = true;
boot.initrd.luks.devices = {
a_encrypted = {
device = "/dev/sda3";
preLVM = true;
};
b_encrypted = {
device = "/dev/sdb3";
preLVM = true;
};
};
networking.hostName = hostName;
# Network configuration (Hetzner uses static IP assignments, and we don't use DHCP here)
networking.useDHCP = false;
networking.interfaces.${networkInterface} = {
ipv4 = { addresses = [{ address = ipv4.address; prefixLength = ipv4.prefixLength; }]; };
ipv6 = { addresses = [{ address = ipv6.address; prefixLength = ipv6.prefixLength; }]; };
};
networking.defaultGateway = ipv4.gateway;
networking.defaultGateway6 = { address = ipv6.gateway; interface = networkInterface; };
networking.nameservers = [ "8.8.8.8" ];
# Initial empty root password for easy login:
users.users.root.initialHashedPassword = "";
services.openssh.settings.PermitRootLogin = "prohibit-password";
services.openssh.settings.PasswordAuthentication = false;
environment.systemPackages = [ pkgs.mosh ];
users.users.root.openssh.authorizedKeys.keys = [
"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=="
];
services.openssh.enable = true;
system.stateVersion = "21.05";
# enable ssh on init
# ------------------
boot.kernelParams = [
# See <https://www.kernel.org/doc/Documentation/filesystems/nfs/nfsroot.txt> for docs on this
# ip=<client-ip>:<server-ip>:<gw-ip>:<netmask>:<hostname>:<device>:<autoconf>:<dns0-ip>:<dns1-ip>:<ntp0-ip>
# The server ip refers to the NFS server -- we don't need it.
"ip=${ipv4.address}::${ipv4.gateway}:${ipv4.netmask}:${hostName}-initrd:${networkInterface}:off:8.8.8.8"
];
boot.initrd.availableKernelModules = [ networkInterfaceModule ];
boot.initrd.network.enable = true;
boot.initrd.network.ssh = {
enable = true;
authorizedKeys = config.users.users.root.openssh.authorizedKeys.keys;
port = 2222;
hostKeys = [
/etc/secrets/initrd/ssh_host_rsa_key
/etc/secrets/initrd/ssh_host_ed25519_key
];
};
}

View file

@ -1,41 +0,0 @@
{ config, ... }:
{
services.promtail = {
enable = true;
configuration = {
server = {
http_listen_port = 28183;
grpc_listen_port = 0;
};
positions.filename = "/tmp/positions.yaml";
clients = [
{ url = "http://127.0.0.1:3100/loki/api/v1/push"; }
];
scrape_configs = [
{
job_name = "journal";
journal = {
max_age = "12h";
labels = {
job = "systemd-journal";
host = config.networking.hostName;
};
};
relabel_configs = [
{
source_labels = [ "__journal__systemd_unit" ];
target_label = "unit";
}
{
source_labels = [ "__journal__transport" ];
target_label = "transport";
}
];
}
];
};
};
}

View file

@ -1,99 +0,0 @@
{ config, pkgs, ... }:
{
services.loki = {
enable = true;
configuration = {
server = {
http_listen_port = 3100;
log_level = "warn";
};
auth_enabled = false;
ingester = {
lifecycler = {
address = "127.0.0.1";
ring = {
kvstore = {
store = "inmemory";
};
replication_factor = 1;
};
};
chunk_idle_period = "1h";
max_chunk_age = "1h";
chunk_target_size = 999999;
chunk_retain_period = "30s";
max_transfer_retries = 0;
};
schema_config = {
configs = [{
from = "2022-06-06";
store = "boltdb-shipper";
object_store = "filesystem";
schema = "v11";
index = {
prefix = "index_";
period = "24h";
};
}];
};
storage_config = {
boltdb_shipper = {
active_index_directory = "/var/lib/loki/boltdb-shipper-active";
cache_location = "/var/lib/loki/boltdb-shipper-cache";
cache_ttl = "24h";
shared_store = "filesystem";
};
filesystem = {
directory = "/var/lib/loki/chunks";
};
};
limits_config = {
reject_old_samples = true;
reject_old_samples_max_age = "168h";
};
chunk_store_config = {
max_look_back_period = "0s";
};
table_manager = {
retention_deletes_enabled = false;
retention_period = "0s";
};
compactor = {
working_directory = "/var/lib/loki";
shared_store = "filesystem";
compactor_ring = {
kvstore = {
store = "inmemory";
};
};
};
};
# user, group, dataDir, extraFlags, (configFile)
};
#services.nginx = {
# enable = true;
# virtualHosts.loki = {
# serverName = "loki.pepe.private";
# locations."/" = {
# proxyWebsockets = true;
# proxyPass = "http://127.0.0.1:3100";
# #extraConfig = ''
# # access_log off;
# # allow ${config.tinc.private.subnet};
# # deny all;
# #'';
# };
# };
#};
}

View file

@ -1,80 +0,0 @@
{ config, ... }:
{
networking.firewall.interfaces.wg0.allowedTCPPorts = [ 7878 8989 ];
# download series
services.sonarr = {
enable = true;
group = "media";
user = "media";
};
# download movies
services.radarr = {
enable = true;
group = "media";
user = "media";
};
# better indexer apis
services.prowlarr = {
enable = true;
#group = "media";
#user = "media";
};
services.jellyseerr = {
enable = true;
};
services.permown."/media/arr" = {
owner = "media";
group = "media";
directory-mode = "770";
file-mode = "770";
};
services.nginx.virtualHosts = {
"radarr.${config.networking.hostName}.private" = {
extraConfig = ''
allow ${config.tinc.private.subnet};
deny all;
'';
locations."/" = {
proxyPass = "http://localhost:7878";
proxyWebsockets = true;
};
};
"sonarr.${config.networking.hostName}.private" = {
extraConfig = ''
allow ${config.tinc.private.subnet};
deny all;
'';
locations."/" = {
proxyPass = "http://localhost:8989";
proxyWebsockets = true;
};
};
"prowlarr.${config.networking.hostName}.private" = {
extraConfig = ''
allow ${config.tinc.private.subnet};
deny all;
'';
locations."/" = {
proxyPass = "http://localhost:9696";
proxyWebsockets = true;
};
};
"jellyseerr.${config.networking.hostName}.private" = {
extraConfig = ''
allow ${config.tinc.private.subnet};
deny all;
'';
locations."/" = {
proxyPass = "http://localhost:${toString config.services.jellyseerr.port}";
proxyWebsockets = true;
};
};
};
}

View file

@ -1,41 +0,0 @@
{ config, lib, pkgs, ... }:
{
services.jellyfin = {
enable = true;
openFirewall = false;
group = "media";
user = "media";
};
hardware.opengl = {
enable = true;
driSupport = true;
driSupport32Bit = true;
};
services.nginx =
let
flixConfig = {
forceSSL = true;
enableACME = true;
extraConfig = ''
# Security / XSS Mitigation Headers
# NOTE: X-Frame-Options may cause issues with the webOS app
add_header X-Frame-Options "SAMEORIGIN";
add_header X-XSS-Protection "1; mode=block";
add_header X-Content-Type-Options "nosniff";
'';
locations."/" = {
recommendedProxySettings = true;
proxyWebsockets = true;
proxyPass = "http://localhost:8096";
};
};
in
{
enable = true;
virtualHosts. "flix.ingolf-wagner.de" = flixConfig;
virtualHosts. "video.ingolf-wagner.de" = flixConfig;
};
}

View file

@ -1,21 +0,0 @@
{ config, ... }:
{
users.groups."media".gid = config.ids.gids.transmission;
users.users."media" = {
uid = config.ids.uids.transmission;
useDefaultShell = true;
home = "/home/media";
createHome = true;
group = "media";
};
services.permown."/media/media" = {
owner = "media";
group = "media";
directory-mode = "770";
file-mode = "770";
};
}

View file

@ -1,77 +0,0 @@
{ config, pkgs, lib, ... }: {
sops.secrets.syncthing_cert = { };
sops.secrets.syncthing_key = { };
networking.firewall.allowedTCPPorts = [ 22000 ];
networking.firewall.allowedUDPPorts = [ 22000 ];
services.syncthing = {
enable = true;
openDefaultPorts = false;
dataDir = "/media/syncthing/config";
configDir = "/media/syncthing/config";
overrideDevices = true;
overrideFolders = true;
cert = toString config.sops.secrets.syncthing_cert.path;
key = toString config.sops.secrets.syncthing_key.path;
settings.folders = {
# on media hard drive (not encrypted)
# -----------------------------------
#borg-mirror = {
# enable = true;
# path = "/media/syncthing/borg";
# rescanInterval = 36 * 3600;
# type = "sendonly";
#};
#video-material = {
# enable = true;
# path = "/home/syncthing/video-material";
#};
books = {
enable = true;
path = "/media/syncthing/books";
};
lost-fotos = {
enable = true;
path = "/media/syncthing/lost-fotos.ct";
rescanIntervalS = 40 * 24 * 3600;
};
#media = {
# enable = true;
# watch = false;
# type = "sendonly";
# path = "/media/syncthing/media";
# rescanInterval = 27 * 24 * 3600;
#};
music-projects = {
enable = true;
#watch = true;
path = "/media/syncthing/music-projects";
};
nextcloud_backup = {
enable = true;
#watch = true;
path = "/media/syncthing/nextcloud_backup";
rescanIntervalS = 23 * 3600;
};
};
};
services.permown."/media/syncthing" = {
# not managed by syncthing anymore
owner = "syncthing";
group = "syncthing";
umask = "0002";
};
systemd.services."permown._media_syncthing" = {
bindsTo = [ "media.mount" ];
after = [ "media.mount" ];
};
systemd.services."syncthing" = {
bindsTo = [ "media.mount" ];
after = [ "media.mount" ];
};
}

View file

@ -1,54 +0,0 @@
{ config, lib, pkgs, ... }:
{
# https://docs.tdarr.io/docs/installation/docker/run-compose
virtualisation.oci-containers = {
containers.tdarr = {
volumes = [
"/media/arr/tdarr/server:/app/server"
"/media/arr/tdarr/configs:/app/configs"
"/media/arr/tdarr/logs:/app/logs"
"/media/arr/tdarr/transcode_cache:/temp"
"/media:/media"
];
environment = {
serverIP = "0.0.0.0";
serverPort = "8266";
webUIPort = "8265";
internalNode = "true";
inContainer = "true";
nodeName = "robi";
TZ = "Europe/Berlin";
PUID = toString config.users.users.media.uid;
PGID = toString config.users.groups.media.gid;
};
ports = [
"127.0.0.1:8265:8265" # WebUI
# "8266:8266" # server port
];
image = "ghcr.io/haveagitgat/tdarr:latest"; # Warning: if the tag does not change, the image will not be updated
extraOptions = [
#"--network=bridge"
#"--privileged"
];
};
};
#networking.firewall.interfaces.wg0.allowedTCPPorts = [ 8266 ];
#networking.firewall.interfaces.wg0.allowedUDPPorts = [ 8266 ];
#networking.firewall.interfaces.enp0s31f6.allowedTCPPorts = [ 8266 ];
#networking.firewall.interfaces.enp0s31f6.allowedUDPPorts = [ 8266 ];
services.nginx.virtualHosts."tdarr.${config.networking.hostName}.private" = {
extraConfig = ''
allow ${config.tinc.private.subnet};
deny all;
'';
locations."/" = {
proxyPass = "http://localhost:8265";
proxyWebsockets = true;
};
};
}

View file

@ -1,259 +0,0 @@
{ lib, pkgs, config, ... }:
let
hostInterface = "enp3s0";
hostAddress = "192.168.100.30";
containerAddress = "192.168.100.31";
uiPort = 9091;
in
{
sops.secrets.nordvpn = { };
sops.secrets.transmissionPushover = { };
containers.torrent = {
# mount host folders
bindMounts = {
#password = {
# hostPath = "/run/secrets/transmission_password";
# mountPoint = "/run/secrets/transmission_password";
# isReadOnly = true;
#};
transmissionPushover = {
hostPath = "/run/secrets/transmissionPushover";
mountPoint = "/run/secrets/transmissionPushover";
isReadOnly = true;
};
nordvpnPassword = {
hostPath = "/run/secrets/nordvpn";
mountPoint = "/run/secrets/nordvpn";
isReadOnly = true;
};
media = {
hostPath = "/media";
mountPoint = "/media"; # must be here otherwise transmission can't see the folder
isReadOnly = false;
};
lib = {
hostPath = "/media/torrent/torrent1_config";
mountPoint = "/var/lib/transmission/.config";
isReadOnly = false;
};
};
# container network setup
# see also nating on host system.
privateNetwork = true;
hostAddress = hostAddress;
localAddress = containerAddress;
autoStart = true;
# needed for openvpn
enableTun = true;
config = { config, pkgs, lib, ... }: {
system.stateVersion = "21.05";
services.journald.extraConfig = "SystemMaxUse=1G";
# allow transmission to write in syncthing folders
users.groups.syncthing = {
gid = config.ids.gids.syncthing;
members = [ "transmission" ];
};
services.transmission = {
enable = true;
settings = {
download-dir = "/media/torrent/downloads";
incomplete-dir = "/media/torrent/incomplete";
incomplete-dir-enabled = true;
message-level = 1;
umask = 2;
rpc-whitelist-enabled = false;
rpc-host-whitelist-enabled = false;
rpc-port = uiPort;
rpc-enable = true;
rpc-bind-address = "0.0.0.0";
# "normal" speed limits
speed-limit-down-enabled = false;
speed-limit-down = 800;
speed-limit-up-enabled = true;
speed-limit-up = 3000;
upload-slots-per-torrent = 8;
# Queuing
# When true, Transmission will only download
# download-queue-size non-stalled torrents at once.
download-queue-enabled = true;
download-queue-size = 3;
# When true, torrents that have not shared data for
# queue-stalled-minutes are treated as 'stalled'
# and are not counted against the queue-download-size
# and seed-queue-size limits.
queue-stalled-enabled = true;
queue-stalled-minutes = 60;
# When true. Transmission will only seed seed-queue-size
# non-stalled torrents at once.
seed-queue-enabled = false;
seed-queue-size = 10;
# Enable UPnP or NAT-PMP.
peer-port = 51413;
port-forwarding-enabled = false;
# Start torrents as soon as they are added
start-added-torrents = true;
};
};
networking.firewall = {
allowedTCPPorts = [ 51413 ];
allowedUDPPorts = [ 51413 ];
# only allow access via nginx (proxy to localhost)
interfaces.eth0 = {
allowedTCPPorts = [ uiPort ];
allowedUDPPorts = [ uiPort ];
};
};
# bind transmission to openvpn
systemd.services.transmission = {
bindsTo = [ "openvpn-nordvpn.service" ];
after = [ "openvpn-nordvpn.service" ];
serviceConfig = {
Restart = "always";
EnvironmentFile = [
"/run/secrets/transmissionPushover"
];
BindPaths = lib.mkForce [
"/media" # this is needed otherwise cp -l is not working
"/var/lib/transmission/.config/transmission-daemon"
];
};
};
services.openvpn.servers.nordvpn.updateResolvConf = true;
services.openvpn.servers.nordvpn.config = ''
client
dev tun
proto udp
remote 152.89.163.99 1194
dhcp-option DNS 8.8.8.8
remote-random
nobind
tun-mtu 1500
tun-mtu-extra 32
mssfix 1450
persist-key
persist-tun
ping 15
ping-restart 0
ping-timer-rem
reneg-sec 0
comp-lzo no
remote-cert-tls server
auth-user-pass /run/secrets/nordvpn
verb 3
pull
resolv-retry infinite
fast-io
cipher AES-256-CBC
auth SHA512
<ca>
-----BEGIN CERTIFICATE-----
MIIFCjCCAvKgAwIBAgIBATANBgkqhkiG9w0BAQ0FADA5MQswCQYDVQQGEwJQQTEQ
MA4GA1UEChMHTm9yZFZQTjEYMBYGA1UEAxMPTm9yZFZQTiBSb290IENBMB4XDTE2
MDEwMTAwMDAwMFoXDTM1MTIzMTIzNTk1OVowOTELMAkGA1UEBhMCUEExEDAOBgNV
BAoTB05vcmRWUE4xGDAWBgNVBAMTD05vcmRWUE4gUm9vdCBDQTCCAiIwDQYJKoZI
hvcNAQEBBQADggIPADCCAgoCggIBAMkr/BYhyo0F2upsIMXwC6QvkZps3NN2/eQF
kfQIS1gql0aejsKsEnmY0Kaon8uZCTXPsRH1gQNgg5D2gixdd1mJUvV3dE3y9FJr
XMoDkXdCGBodvKJyU6lcfEVF6/UxHcbBguZK9UtRHS9eJYm3rpL/5huQMCppX7kU
eQ8dpCwd3iKITqwd1ZudDqsWaU0vqzC2H55IyaZ/5/TnCk31Q1UP6BksbbuRcwOV
skEDsm6YoWDnn/IIzGOYnFJRzQH5jTz3j1QBvRIuQuBuvUkfhx1FEwhwZigrcxXu
MP+QgM54kezgziJUaZcOM2zF3lvrwMvXDMfNeIoJABv9ljw969xQ8czQCU5lMVmA
37ltv5Ec9U5hZuwk/9QO1Z+d/r6Jx0mlurS8gnCAKJgwa3kyZw6e4FZ8mYL4vpRR
hPdvRTWCMJkeB4yBHyhxUmTRgJHm6YR3D6hcFAc9cQcTEl/I60tMdz33G6m0O42s
Qt/+AR3YCY/RusWVBJB/qNS94EtNtj8iaebCQW1jHAhvGmFILVR9lzD0EzWKHkvy
WEjmUVRgCDd6Ne3eFRNS73gdv/C3l5boYySeu4exkEYVxVRn8DhCxs0MnkMHWFK6
MyzXCCn+JnWFDYPfDKHvpff/kLDobtPBf+Lbch5wQy9quY27xaj0XwLyjOltpiST
LWae/Q4vAgMBAAGjHTAbMAwGA1UdEwQFMAMBAf8wCwYDVR0PBAQDAgEGMA0GCSqG
SIb3DQEBDQUAA4ICAQC9fUL2sZPxIN2mD32VeNySTgZlCEdVmlq471o/bDMP4B8g
nQesFRtXY2ZCjs50Jm73B2LViL9qlREmI6vE5IC8IsRBJSV4ce1WYxyXro5rmVg/
k6a10rlsbK/eg//GHoJxDdXDOokLUSnxt7gk3QKpX6eCdh67p0PuWm/7WUJQxH2S
DxsT9vB/iZriTIEe/ILoOQF0Aqp7AgNCcLcLAmbxXQkXYCCSB35Vp06u+eTWjG0/
pyS5V14stGtw+fA0DJp5ZJV4eqJ5LqxMlYvEZ/qKTEdoCeaXv2QEmN6dVqjDoTAo
k0t5u4YRXzEVCfXAC3ocplNdtCA72wjFJcSbfif4BSC8bDACTXtnPC7nD0VndZLp
+RiNLeiENhk0oTC+UVdSc+n2nJOzkCK0vYu0Ads4JGIB7g8IB3z2t9ICmsWrgnhd
NdcOe15BincrGA8avQ1cWXsfIKEjbrnEuEk9b5jel6NfHtPKoHc9mDpRdNPISeVa
wDBM1mJChneHt59Nh8Gah74+TM1jBsw4fhJPvoc7Atcg740JErb904mZfkIEmojC
VPhBHVQ9LHBAdM8qFI2kRK0IynOmAZhexlP/aT/kpEsEPyaZQlnBn3An1CRz8h0S
PApL8PytggYKeQmRhl499+6jLxcZ2IegLfqq41dzIjwHwTMplg+1pKIOVojpWA==
-----END CERTIFICATE-----
</ca>
key-direction 1
<tls-auth>
#
# 2048 bit OpenVPN static key
#
-----BEGIN OpenVPN Static key V1-----
e685bdaf659a25a200e2b9e39e51ff03
0fc72cf1ce07232bd8b2be5e6c670143
f51e937e670eee09d4f2ea5a6e4e6996
5db852c275351b86fc4ca892d78ae002
d6f70d029bd79c4d1c26cf14e9588033
cf639f8a74809f29f72b9d58f9b8f5fe
fc7938eade40e9fed6cb92184abb2cc1
0eb1a296df243b251df0643d53724cdb
5a92a1d6cb817804c4a9319b57d53be5
80815bcfcb2df55018cc83fc43bc7ff8
2d51f9b88364776ee9d12fc85cc7ea5b
9741c4f598c485316db066d52db4540e
212e1518a9bd4828219e24b20d88f598
a196c9de96012090e333519ae18d3509
9427e7b372d348d352dc4c85e18cd4b9
3f8a56ddb2e64eb67adfc9b337157ff4
-----END OpenVPN Static key V1-----
</tls-auth>
'';
};
};
# give containers internet access
networking.nat.enable = true;
networking.nat.internalInterfaces = [ "ve-torrent" ];
networking.nat.externalInterface = hostInterface;
# open ports for logging
#networking.firewall.interfaces."ve-torrent".allowedTCPPorts =
# [ 5044 12304 12305 ];
#networking.firewall.interfaces."ve-torrent".allowedUDPPorts =
# [ 5044 12304 12305 ];
# host nginx setup
# curl -H "Host: transmission.robi.private" https://robi.private/ < will work
# curl -H "Host: transmission.robi.private" https://144.76.13.147/ < wont work
services.nginx = {
enable = true;
recommendedProxySettings = true;
virtualHosts = {
"transmission.${config.networking.hostName}.private" = {
extraConfig = ''
allow ${config.tinc.private.subnet};
deny all;
'';
locations."/" = {
proxyPass = "http://${containerAddress}:${toString uiPort}";
};
};
};
};
}

View file

@ -1,143 +0,0 @@
{ lib, pkgs, config, ... }:
let
uiPort = 9091;
in
{
containers.torrent2 = {
# mount host folders
bindMounts = {
media = {
hostPath = "/media";
mountPoint = "/media"; # must be here otherwise transmission can't see the folder
isReadOnly = false;
};
lib = {
hostPath = "/media/torrent/torrent2_config";
mountPoint = "/var/lib/transmission/.config";
isReadOnly = false;
};
};
autoStart = true;
config = { config, pkgs, lib, ... }: {
system.stateVersion = "21.05";
services.journald.extraConfig = "SystemMaxUse=1G";
# allow transmission to write in syncthing folders
users.groups.syncthing = {
gid = config.ids.gids.syncthing;
members = [ "transmission" ];
};
services.transmission = {
enable = true;
#extraFlags = [ "--log-info" ];
settings = {
download-dir = "/media/torrent/downloads";
incomplete-dir = "/media/torrent/incomplete";
incomplete-dir-enabled = true;
message-level = 1;
umask = 2;
rpc-whitelist-enabled = false;
rpc-host-whitelist-enabled = false;
rpc-port = uiPort;
rpc-enable = true;
rpc-bind-address = "127.0.0.1";
# "normal" speed limits
speed-limit-down-enabled = false;
speed-limit-down = 800;
speed-limit-up-enabled = true;
speed-limit-up = 3000;
upload-slots-per-torrent = 8;
# Queuing
# When true, Transmission will only download
# download-queue-size non-stalled torrents at once.
download-queue-enabled = true;
download-queue-size = 3;
# When true, torrents that have not shared data for
# queue-stalled-minutes are treated as 'stalled'
# and are not counted against the queue-download-size
# and seed-queue-size limits.
queue-stalled-enabled = true;
queue-stalled-minutes = 60;
# When true. Transmission will only seed seed-queue-size
# non-stalled torrents at once.
seed-queue-enabled = false;
seed-queue-size = 10;
# Enable UPnP or NAT-PMP.
peer-port = 51413;
port-forwarding-enabled = false;
# Start torrents as soon as they are added
start-added-torrents = true;
# Encryption preference.
# 0 = Prefer unencrypted connections,
# 1 = Prefer encrypted connections,
# 2 = Require encrypted connections;
# default = 1
# Encryption may help get around some ISP filtering, but at the cost of slightly
# higher CPU use
encryption = 2;
};
};
networking.firewall = {
allowedTCPPorts = [ 51413 ];
allowedUDPPorts = [ 51413 ];
};
# bind transmission to openvpn
systemd.services.transmission = {
serviceConfig = {
Restart = "always";
BindPaths = lib.mkForce [
"/media" # this is needed otherwise cp -l is not working
"/var/lib/transmission/.config/transmission-daemon"
];
BindReadOnlyPaths = lib.mkForce [ builtins.storeDir "/etc" ];
PrivateMounts = lib.mkForce false;
PrivateUsers = lib.mkForce false;
RootDirectoryStartOnly = lib.mkForce false;
RootDirectory = lib.mkForce "/var/lib";
ExecStartPre = lib.mkForce [ ]; # this prevents configuration creation, but fixes startup problems
};
};
};
};
networking.firewall = {
allowedTCPPorts = [ 51413 ];
allowedUDPPorts = [ 51413 ];
};
# host nginx setup
# ----------------
# curl -H "Host: transmission.robi.private" https://robi.private/ < will work
# curl -H "Host: transmission.robi.private" https://144.76.13.147/ < wont work
services.nginx = {
enable = true;
recommendedProxySettings = true;
virtualHosts = {
"transmission2.${config.networking.hostName}.private" = {
extraConfig = ''
allow ${config.tinc.private.subnet};
deny all;
'';
locations."/" = {
proxyPass = "http://127.0.0.1:${toString uiPort}";
};
};
};
};
}

View file

@ -1,15 +0,0 @@
{
networking.firewall = {
allowedTCPPorts = [ 655 721 ];
allowedUDPPorts = [ 655 721 ];
};
tinc.private.enable = true;
tinc.private.ipv4 = "10.23.42.111";
tinc.secret.enable = true;
tinc.secret.ipv4 = "10.123.42.123";
}

View file

@ -1,60 +0,0 @@
{ pkgs, config, ... }:
{
# networking.firewall.trustedInterfaces = [ "wg0" ];
networking.firewall.allowedUDPPorts = [ 51820 ];
sops.secrets.wireguard_private = { };
boot.kernel.sysctl."net.ipv4.ip_forward" = true;
# Enable WireGuard
networking.wg-quick.interfaces = {
# Hub and Spoke Setup
# https://www.procustodibus.com/blog/2020/11/wireguard-hub-and-spoke-config/
wg0 = {
address = [ "10.100.0.1/32" ];
listenPort = 51820; # to match firewall allowedUDPPorts (without this wg uses random port numbers)
privateKeyFile = config.sops.secrets.wireguard_private.path;
mtu = 1280;
postUp = ''
${pkgs.iptables}/bin/iptables -A FORWARD -i wg0 -j ACCEPT
'';
postDown = ''
${pkgs.iptables}/bin/iptables -D FORWARD -i wg0 -j ACCEPT
'';
# clients
peers = [
{
# chungus
publicKey = "wb54y/fG8ocSH9QrDmfajez/fUcJBZK369xLu37XBHk=";
allowedIPs = [ "10.100.0.2/32" ];
}
{
# sterni
publicKey = "SdMRgC5IM7dywzZxLAHm45cpj9J3IENTMClZm1BxbV4=";
allowedIPs = [ "10.100.0.3/32" ];
}
{
# iphone
publicKey = "XPVzH+wBLsqukTHHjngkGJhYN0nRdQ7esadiimMJQnI=";
allowedIPs = [ "10.100.0.4/32" ];
}
{
# tina
publicKey = "RZsuQfWfAQLMm45ZiuNLBwcpL+GEbPYTRTrASFzMCFQ=";
allowedIPs = [ "10.100.0.5/32" ];
}
{
# cream
publicKey = "R1Vk1DDG/LsVU0HHRDmOJshXOVnNzPVbuv5hP7ZSGEQ=";
allowedIPs = [ "10.100.0.6/32" ];
}
{
# cherry
publicKey = "ZNnlmPdxAGYtaUvOU2V47tcEhcB06LBCXkSxIvWZL2k=";
allowedIPs = [ "10.100.0.7/32" ];
}
];
};
};
}

View file

@ -1,301 +0,0 @@
{ pkgs, config, ... }:
# don't forget the database backup before upgrading
# -------------------------------------------------
# https://docs.nextcloud.com/server/stable/admin_manual/maintenance/backup.html
# https://docs.nextcloud.com/server/stable/admin_manual/maintenance/upgrade.html
#
# ! use lvm snapshots to do rollback !
let
hostInterface = "enp3s0";
hostAddress = "192.168.100.10";
containerAddress = "192.168.100.11";
nextcloudUid = 1000;
borg_backup_folder = "/media/syncthing/nextcloud_backup/robi";
in
{
# Host Setup
# ==========
# give containers internet access
networking.nat.enable = true;
networking.nat.internalInterfaces = [ "ve-nextcloud" ];
networking.nat.externalInterface = hostInterface;
# don't let networkmanager manger container network
networking.networkmanager.unmanaged = [ "interface-name:ve-*" ];
# open ports for logging
#networking.firewall.interfaces."ve-nextcloud".allowedTCPPorts =
# [ 5044 12304 12305 ];
#networking.firewall.interfaces."ve-nextcloud".allowedUDPPorts =
# [ 5044 12304 12305 ];
# host nginx
# ----------
networking.firewall.allowedTCPPorts = [ 80 443 ];
networking.firewall.allowedUDPPorts = [ 80 443 ];
services.nginx = {
enable = true;
recommendedProxySettings = true;
virtualHosts = {
"nextcloud.ingolf-wagner.de" = {
forceSSL = true;
enableACME = true;
locations = {
"/" = {
proxyPass = "http://${containerAddress}";
extraConfig = ''
sub_filter "http://nextcloud.ingolf-wagner.de" "https://nextcloud.ingolf-wagner.de";
# used for view/edit office file via Office Online Server
client_max_body_size 0;
proxy_buffering off; # to download files bigger than 1GB
'';
};
"= /.well-known/carddav" = {
priority = 210;
extraConfig = "return 301 $scheme://$host/remote.php/dav;";
};
"= /.well-known/caldav" = {
priority = 210;
extraConfig = "return 301 $scheme://$host/remote.php/dav;";
};
#"~ .(?:css|js|svg|gif)$" = {
# proxyPass = "http://${containerAddress}$request_uri";
# extraConfig = ''
# expires 6M; # Cache-Control policy borrowed from `.htaccess`
# access_log off; # Optional: Don't log access to assets
# sub_filter "http://nextcloud.ingolf-wagner.de" "https://nextcloud.ingolf-wagner.de";
# sub_filter "nextcloud.workhorse.private" "nextcloud.ingolf-wagner.de";
# # used for view/edit office file via Office Online Server
# client_max_body_size 0;
# '';
#};
#"~ .woff2?$" = {
# proxyPass = "http://${containerAddress}$request_uri";
# extraConfig = ''
# expires 7d; # Cache-Control policy borrowed from `.htaccess`
# access_log off; # Optional: Don't log access to assets
# sub_filter "http://nextcloud.ingolf-wagner.de" "https://nextcloud.ingolf-wagner.de";
# sub_filter "nextcloud.workhorse.private" "nextcloud.ingolf-wagner.de";
# # used for view/edit office file via Office Online Server
# client_max_body_size 0;
# '';
#};
};
};
};
};
sops.secrets.nextcloud_database_password.owner = "nextcloud";
sops.secrets.nextcloud_root_password.owner = "nextcloud";
users.users.nextcloud = {
isSystemUser = true;
uid = nextcloudUid;
group = "nextcloud";
};
users.groups.nextcloud = { };
# Container Setup
# ===============
#
# running:
# * nextcloud (php)
# * mysql
containers.nextcloud = {
# mount host folders
bindMounts = {
rootpassword = {
hostPath = "/run/secrets/nextcloud_root_password";
mountPoint = "/run/secrets/nextcloud_root_password";
isReadOnly = true;
};
databasepassword = {
hostPath = "/run/secrets/nextcloud_database_password";
mountPoint = "/run/secrets/nextcloud_database_password";
isReadOnly = true;
};
home = {
# make sure this folder exist on the host
hostPath = toString "/var/lib/nextcloud";
mountPoint = "/var/lib/nextcloud";
isReadOnly = false;
};
db = {
# make sure this folder exist on the host
hostPath = toString "/var/lib/nextcloud_mysql";
mountPoint = "/var/lib/mysql";
isReadOnly = false;
};
media = {
#mountPoint = toString config.services.syncthing.folders.media.path;
#hostPath = toString config.services.syncthing.folders.media.path;
mountPoint = "/media/syncthing/media";
hostPath = "/media/media";
isReadOnly = true;
};
};
# container network setup
# see also nating on host system.
privateNetwork = true;
hostAddress = hostAddress;
localAddress = containerAddress;
autoStart = true;
config = { config, pkgs, lib, ... }: {
# Configuring nameservers for containers is currently broken.
# Therefore in some cases internet connectivity can be broken inside the containers.
# A temporary workaround is to manually write the /etc/nixos/resolv.conf file like this:
environment.etc."resolv.conf".text = "nameserver 8.8.8.8";
system.stateVersion = "21.05";
users.users.nextcloud.uid = nextcloudUid;
services.nginx = {
# Use recommended settings
recommendedGzipSettings = lib.mkDefault true;
recommendedOptimisation = lib.mkDefault true;
recommendedProxySettings = lib.mkDefault true;
recommendedTlsSettings = lib.mkDefault true;
};
networking.firewall.allowedTCPPorts = [ 80 ];
networking.firewall.allowedUDPPorts = [ 80 ];
# nextcloud database
# ==================
#
# set user password:
# -----------------
# #> mysql
# mysql> ALTER USER 'nextcloud'@'localhost' IDENTIFIED BY 'nextcloud-password';
#
# recreate database:
# ------------------
# mysql> DROP DATABASE nextcloud;
# mysql> CREATE DATABASE nextcloud;
#
# migration:
# ----------
# nextcloud-occ db:convert-type --all-apps mysql nextcloud 127.0.0.1 nextcloud
#
# 4-byte stuff:
# -------------
# https://docs.nextcloud.com/server/18/admin_manual/configuration_database/mysql_4byte_support.html
# if you do this don't forget --default-character-set=utf8mb4 for mysqldump
services.mysql = {
enable = true;
package = pkgs.mysql;
# https://nixos.org/manual/nixos/stable/release-notes.html#sec-release-20.09-incompatibilities
ensureDatabases = [ "nextcloud" ];
ensureUsers = [{
name = "nextcloud";
ensurePermissions = { "nextcloud.*" = "ALL PRIVILEGES"; };
}];
settings.mysqld = {
innodb_large_prefix = true;
innodb_file_format = "barracuda";
innodb_file_per_table = 1;
innodb_read_only_compressed = 0;
};
};
# Backup database
# ---------------
services.mysqlBackup = {
enable = true;
databases = config.services.mysql.ensureDatabases;
singleTransaction = true;
location = "/var/lib/nextcloud/database_backups";
};
systemd.services."mysql-backup".serviceConfig = {
ExecStartPre = [ "+/run/current-system/sw/bin/nextcloud-occ maintenance:mode --on" ];
ExecStopPost = [ "+/run/current-system/sw/bin/nextcloud-occ maintenance:mode --off" ];
};
# in php
services.phpfpm = {
phpPackage = pkgs.php73;
phpOptions = ''
opcache.revalidate_freq = 10
'';
};
# nextcloud setup
services.nextcloud = {
enable = true;
package = pkgs.nextcloud28;
autoUpdateApps.enable = true;
# nginx.enable = true;
# enableBrokenCiphersForSSE = false; # see https://github.com/NixOS/nixpkgs/pull/198470
hostName = "nextcloud.ingolf-wagner.de";
logLevel = 2;
https = true;
config = {
adminpassFile = "/run/secrets/nextcloud_root_password";
overwriteProtocol = "https";
trustedProxies = [ "144.76.13.147" hostAddress ];
dbtype = "mysql";
dbpassFile = "/run/secrets/nextcloud_database_password";
dbhost = "localhost:3306";
defaultPhoneRegion = "DE";
};
};
};
};
# Backup Config
# -------------
#backup.dirs = [
# "/home/nextcloud/config"
# "/home/nextcloud/database_backups" # created by mysqlBackup
#];
# Backup Files
# ------------
services.borgbackup.jobs = {
"nextcloud-to-media" = {
repo = borg_backup_folder;
# make sure syncthing is capable of reading the files
postHook = ''
chown -R syncthing:syncthing ${borg_backup_folder}
'';
compression = "lz4";
paths = [
"/var/lib/nextcloud/data/tina/files"
"/var/lib/nextcloud/data/palo/files"
"/var/lib/nextcloud/data/palo-windows/files"
];
doInit = true;
encryption = {
mode = "repokey-blake2";
passCommand = "cat ${config.sops.secrets.backup_repository_passphrase.path}";
};
startAt = "0/3:00:00";
prune.keep = {
within = "2d"; # Keep all backups in the last 10 days.
daily = 10; # Keep 10 additional end of day archives
weekly = 8; # Keep 8 additional end of week archives.
month = 8; # Keep 8 additional end of month archives.
};
};
};
}

View file

@ -1,30 +0,0 @@
{ config, pkgs, lib, assets, ... }:
let
server_name = "ingolf-wagner.de";
in
{
# check :
# - https://metacode.biz/openpgp/web-key-directory
# - $> gpg --homedir "$(mktemp -d)" -v --auto-key-locate clear,wkd,nodefault --locate-key contact@ingolf-wagner.de
services.nginx.virtualHosts.${server_name}.locations =
let
wkd =
{
extraConfig = ''
default_type application/octet-stream;
add_header Access-Control-Allow-Origin * always;
'';
#alias = pkgs.runCommand "contact@ingolf-wagner.de" { } ''
# cat ${assets}/contact@ingolf-wagner.de.gpg | ${pkgs.gnupg}/bin/gpg --dearmor > $out
#'';
alias = toString "${assets}/contact@ingolf-wagner.de.gpg";
};
in
{
"= /.well-known/openpgpkey/policy".return = "200";
# hashes generated by : gpg --with-wkd-hash --fingerprint contact@ingolf-wagner.de
"= /.well-known/openpgpkey/hu/dj3498u4hyyarh35rkjfnghbjxug6b19" = wkd;
};
# todo openpgpkey.ingolf-wagner.de noch einrichten
}

View file

@ -1,137 +0,0 @@
{ config, lib, pkgs, private_assets, ... }:
let
# todo create flake for this
errorPages = pkgs.fetchFromGitHub {
owner = "mrvandalo";
repo = "http-errors";
rev = "74b8e4c1d9bbba3db6ad858b888e1867318af1f0";
sha256 = "0czdzafx4k76q773lyf3vsjm74g1995iz542dhw15kpy5xbivsrg";
};
error = {
extraConfig = ''
error_page 400 /errors/400.html;
error_page 401 /errors/401.html;
error_page 402 /errors/402.html;
error_page 403 /errors/403.html;
error_page 404 /errors/404.html;
error_page 405 /errors/405.html;
error_page 406 /errors/406.html;
error_page 500 /errors/500.html;
error_page 501 /errors/501.html;
error_page 502 /errors/502.html;
error_page 503 /errors/503.html;
error_page 504 /errors/504.html;
'';
locations."^~ /errors/" = {
extraConfig = "internal;";
root = "${errorPages}/";
};
};
in
{
networking.firewall.allowedTCPPorts = [ 80 443 ];
networking.firewall.allowedUDPPorts = [ 80 443 ];
services.nginx = {
enable = true;
recommendedProxySettings = true;
virtualHosts = {
"${config.networking.hostName}.private".default = false;
"ingolf-wagner.de" = {
default = true;
forceSSL = true;
enableACME = true;
extraConfig = error.extraConfig;
locations = {
"/" = {
root = pkgs.landingpage.override {
jsonConfig = [
{
title = "Ingolf Wagner";
text = ''
I'm a freelancing mathematician, musician and programmer.
My PGP fingerprint is 42AC 51C9 482D 0834 CF48 8AF1 389E C2D6 4AC7 1EAC
'';
}
{
text = ''
Here are some of my projects you might enjoy:
'';
items = [
{
label = "terranix";
href = "https://terranix.org";
image = "https://raw.githubusercontent.com/terranix/terranix-artwork/main/terranix-logo.svg";
}
{
label = "Sononym";
href = "https://www.sononym.net/";
image = "https://www.sononym.net/press/logos/sononym-logo-symbol-black.png";
}
{
label = "LandingPage";
href = "https://github.com/mrVanDalo/landingpage";
image = "https://media.giphy.com/media/2vNGq1w3nsJri/giphy.gif";
}
{
label = "My Blog";
href = "https://tech.ingolf-wagner.de/";
image = "https://media.giphy.com/media/11I8v5lE8uq79C/giphy.gif";
}
];
}
];
title = "Ingolf Wagner";
max-width = "1010px";
background-color = "#FEFAE0";
title-color = "black";
title-background-color = "#E9EDC9";
text-color = "black";
text-background-color = "#FAEDCD";
item-color = "black";
item-background-color = "#E9EDC9";
image-width = "250px";
image-height = "200px";
};
};
};
};
"travel.ingolf-wagner.de" = {
forceSSL = true;
enableACME = true;
extraConfig = error.extraConfig;
locations = {
"/" = {
root = "/srv/www/travel";
extraConfig = ''
if (-d $request_filename) {
rewrite [^/]$ $scheme://$http_host$request_uri/ permanent;
}
'';
};
} // error.locations;
};
"tech.ingolf-wagner.de" = {
forceSSL = true;
enableACME = true;
extraConfig = error.extraConfig;
locations = {
"/" = {
root = "/srv/www/tech";
extraConfig = ''
if (-d $request_filename) {
rewrite [^/]$ $scheme://$http_host$request_uri/ permanent;
}
'';
};
} // error.locations;
};
};
};
}

View file

@ -1,14 +0,0 @@
{ config, pkgs, ... }: {
environment.systemPackages = with pkgs; [
mosh
mediainfo
youtube-dl
ipset # for sshguard
vulnix
(pkgs.writers.writeBashBin "vulnix-system" ''
${pkgs.vulnix}/bin/vulnix --profile /nix/var/nix/profiles/system
'')
];
}

View file

@ -1,70 +0,0 @@
{ config, pkgs, lib, ... }: {
services.nginx = {
enable = true;
statusPage = true;
virtualHosts = {
"prometheus.robi.private" = {
extraConfig = ''
allow ${config.tinc.private.subnet};
deny all;
'';
locations."/" = { proxyPass = "http://localhost:${toString config.services.prometheus.port}"; };
};
};
};
services.prometheus = {
enable = true;
# keep data for 30 days
extraFlags = [ "--storage.tsdb.retention.time=30d" ];
exporters = {
node = {
enable = true;
enabledCollectors = [ "systemd" ];
port = 9002;
};
};
scrapeConfigs = [
{
job_name = "netdata";
metrics_path = "/api/v1/allmetrics";
params.format = [ "prometheus" ];
scrape_interval = "5s";
static_configs = [
{
targets = [ "localhost:19999" ];
labels = {
service = "netdata";
server = "robi";
};
}
];
}
{
job_name = "systemd";
static_configs = [{
targets = [ "localhost:${toString config.services.prometheus.exporters.node.port}" ];
labels = {
service = "node-exporter";
server = "robi";
};
}];
}
{
# see https://www.home-assistant.io/integrations/prometheus/
job_name = "telgraf";
metrics_path = "/metrics";
static_configs = [{
targets = [ "localhost:9273" ];
labels = {
service = "telegraf";
server = "robi";
};
}];
}
];
};
}

View file

@ -1,60 +0,0 @@
{ config, ... }: {
# + +
# | |
# | |
# v v
# 80, 443 TCP 443 TCP, 10000 UDP
# +--------------+ +---------------------+
# | nginx | 5222, 5347 TCP | |
# | jitsi-meet |<-------------------+| jitsi-videobridge |
# | prosody | | | |
# | jicofo | | +---------------------+
# +--------------+ |
# | +---------------------+
# | | |
# +----------+| jitsi-videobridge |
# | | |
# | +---------------------+
# |
# | +---------------------+
# | | |
# +----------+| jitsi-videobridge |
# | |
# +---------------------+
# This is a one server setup
services.jitsi-meet = {
enable = true;
hostName = "meet.ingolf-wagner.de";
# JItsi COnference FOcus is a server side focus component used in Jitsi Meet conferences.
# https://github.com/jitsi/jicofo
jicofo.enable = true;
# Whether to enable nginx virtual host that will serve the javascript application and act as a proxy for the XMPP server.
# Further nginx configuration can be done by adapting services.nginx.virtualHosts.<hostName>. When this is enabled, ACME
# will be used to retrieve a TLS certificate by default. To disable this, set the
# services.nginx.virtualHosts.<hostName>.enableACME to false and if appropriate do the same for
# services.nginx.virtualHosts.<hostName>.forceSSL.
nginx.enable = true;
# https://github.com/jitsi/jitsi-meet/blob/master/config.js
config = {
enableWelcomePage = false;
defaultLang = "en";
};
# https://github.com/jitsi/jitsi-meet/blob/master/interface_config.js
interfaceConfig = {
SHOW_JITSI_WATERMARK = false;
SHOW_WATERMARK_FOR_GUESTS = false;
};
};
networking.firewall = {
allowedTCPPorts = [ 80 443 ];
allowedUDPPorts = [ 10000 ];
};
}

View file

@ -1,57 +0,0 @@
{ config, pkgs, ... }:
let
# 1. create DNS entry `matrix.ingolf-wagner.de A - 95.216.66.212`
# 2. test with : https://federationtester.matrix.org/#ingolf-wagner.de
# 3. info at : https://silvio.github.io/docker-matrix/Example.configs.html
domain = "ingolf-wagner.de";
baseUrl = "https://matrix.${domain}";
clientConfig."m.homeserver".base_url = baseUrl;
serverConfig."m.server" = "matrix.${domain}:443";
mkWellKnown = data: ''
default_type application/json;
add_header Access-Control-Allow-Origin *;
return 200 '${builtins.toJSON data}';
'';
in
{
networking.firewall.allowedTCPPorts = [ 80 443 ];
networking.firewall.allowedUDPPorts = [ 80 443 ];
services.nginx = {
enable = true;
recommendedTlsSettings = true;
recommendedOptimisation = true;
recommendedGzipSettings = true;
recommendedProxySettings = true;
virtualHosts = {
# If the A and AAAA DNS records on example.org do not point on the same host as the
# records for myhostname.example.org, you can easily move the /.well-known
# virtualHost section of the code to the host that is serving example.org, while
# the rest stays on myhostname.example.org with no other changes required.
# This pattern also allows to seamlessly move the homeserver from
# myhostname.example.org to myotherhost.example.org by only changing the
# /.well-known redirection target.
"${domain}" = {
enableACME = true;
forceSSL = true;
# This section is not needed if the server_name of matrix-synapse is equal to
# the domain (i.e. example.org from @foo:example.org) and the federation port
# is 8448.
# Further reference can be found in the docs about delegation under
# https://element-hq.github.io/synapse/latest/delegate.html
locations."= /.well-known/matrix/server".extraConfig = mkWellKnown serverConfig;
# This is usually needed for homeserver discovery (from e.g. other Matrix clients).
# Further reference can be found in the upstream docs at
# https://spec.matrix.org/latest/client-server-api/#getwell-knownmatrixclient
locations."= /.well-known/matrix/client".extraConfig = mkWellKnown clientConfig;
};
};
};
}

View file

@ -1,5 +0,0 @@
{
services.opentracker = {
enable = true;
};
}

View file

@ -1,111 +0,0 @@
{ lib, pkgs, config, ... }:
let
uiPort = 9099;
announceIp = "10.23.42.111";
peerPort = 51433;
in
{
containers.sync-torrent = {
# mount host folders
bindMounts = {
media = {
hostPath = "/media/new";
mountPoint = "/media"; # must be here otherwise transmission can't see the folder
isReadOnly = false;
};
lib = {
hostPath = "/srv/sync-torrent";
mountPoint = "/var/lib/transmission";
isReadOnly = false;
};
};
autoStart = true;
config = { config, pkgs, lib, ... }: {
system.stateVersion = "22.11";
services.journald.extraConfig = "SystemMaxUse=1G";
services.transmission = {
enable = true;
settings = {
download-dir = "/media";
incomplete-dir = "/var/lib/transmission/incomplete"; # todo put this somewhere with frequent snapshots but low keep.
incomplete-dir-enabled = true;
message-level = 1;
umask = 2;
rpc-whitelist-enabled = false;
rpc-host-whitelist-enabled = false;
rpc-port = uiPort;
rpc-enable = true;
rpc-bind-address = "0.0.0.0";
# "normal" speed limits
speed-limit-down-enabled = false;
speed-limit-down = 800;
speed-limit-up-enabled = true;
speed-limit-up = 3000;
upload-slots-per-torrent = 8;
# Queuing
# When true, Transmission will only download
# download-queue-size non-stalled torrents at once.
download-queue-enabled = true;
download-queue-size = 3;
# When true, torrents that have not shared data for
# queue-stalled-minutes are treated as 'stalled'
# and are not counted against the queue-download-size
# and seed-queue-size limits.
queue-stalled-enabled = true;
queue-stalled-minutes = 60;
# When true. Transmission will only seed seed-queue-size
# non-stalled torrents at once.
seed-queue-enabled = false;
seed-queue-size = 10;
# Enable UPnP or NAT-PMP.
peer-port = peerPort;
port-forwarding-enabled = false;
announce-ip = announceIp;
announce-ip-enabled = true;
# Start torrents as soon as they are added
start-added-torrents = true;
};
};
};
};
# open ports for logging
#networking.firewall.interfaces."ve-torrent".allowedTCPPorts =
# [ 5044 12304 12305 ];
#networking.firewall.interfaces."ve-torrent".allowedUDPPorts =
# [ 5044 12304 12305 ];
# host nginx setup
# ----------------
# curl -H "Host: sync.robi.private" https://robi.private/ < will work
# curl -H "Host: sync.robi.private" https://144.76.13.147/ < wont work
services.nginx = {
enable = true;
recommendedProxySettings = true;
virtualHosts = {
"sync.${config.networking.hostName}.private" = {
extraConfig = ''
allow ${config.tinc.private.subnet};
deny all;
'';
locations."/" = {
proxyPass = "http://127.0.0.1:${toString uiPort}";
};
};
};
};
}

View file

@ -1,19 +0,0 @@
{ config, lib, pkgs, ... }: {
services.taskserver = {
enable = true;
fqdn = "taskd.ingolf-wagner.de";
listenHost = "0.0.0.0";
requestLimit = 104857600;
trust = "strict";
dataDir = "/var/lib/taskserver";
organisations."1337".users = [ "palo" "beta" ];
ciphers = "SECURE256";
};
networking.firewall.allowedTCPPorts = [ config.services.taskserver.listenPort ];
networking.firewall.allowedUDPPorts = [ config.services.taskserver.listenPort ];
backup.dirs = [ config.services.taskserver.dataDir ];
}

View file

@ -1,28 +0,0 @@
{
services.telegraf = {
enable = true;
extraConfig = {
outputs.prometheus_client = {
listen = ":9273";
metric_version = 2;
};
# https://github.com/influxdata/telegraf/tree/master/plugins/inputs < all them plugins
inputs = {
cpu = {
percpu = true;
totalcpu = true;
};
disk = { };
diskio = { };
kernel = { };
mem = { };
processes = { };
netstat = { };
net = { };
system = { };
systemd_units = { };
nginx.urls = [ "http://localhost/nginx_status" ];
};
};
};
}

View file

@ -1,35 +0,0 @@
{ config, pkgs, lib, ... }: {
services.vaultwarden = {
enable = true;
# backupDir =
config = {
domain = "https://bitwarden.ingolf-wagner.de";
signupsAllowed = false;
rocketPort = 8222;
rocketLog = "critical";
};
};
backup.dirs = [ "/var/lib/bitwarden_rs" ];
services.nginx = {
enable = true;
recommendedProxySettings = true;
virtualHosts = {
"bitwarden.ingolf-wagner.de" = {
forceSSL = true;
enableACME = true;
locations."/" = {
extraConfig = ''
client_max_body_size 500M;
'';
proxyPass = "http://localhost:${
toString config.services.vaultwarden.config.rocketPort
}";
};
};
};
};
}

View file

@ -1,9 +0,0 @@
{ config, lib, pkgs, ... }:
{
services.grocy-scanner = {
enable = true;
host = "https://grocy.ingolf-wagner.de";
device = "/dev/input/by-id/usb-Belon.cn_2.4G_Wireless_Device_Belon_Smart-event-kbd";
apiKeyFile = toString (pkgs.writeText "key" "my-api-key-not");
};
}

View file

@ -1,73 +0,0 @@
{ config, lib, pkgs, ... }:
with lib;
let
debug = true;
#version = "latest";
# version = "142c079"; # 2 years ago.
# version = "v1.14.0"; # 2 years ago.
version = "v1.13.2"; # 2 years ago.
in
{
virtualisation.oci-containers = {
containers.screeps = {
volumes = [
"/srv/screeps:/screeps"
(optionalString debug "/srv/screeps-tmp:/tmp")
];
environment.TZ = "Europe/Berlin";
image = "screepers/screeps-launcher:${version}";
ports = [ "21025:21025" ];
};
};
systemd.services.docker-screeps =
let
configuration = builtins.toJSON {
steamKey = "keyFromStep3";
version = "latest";
mods = [
#"screepsmod-auth"
#"screepsmod-admin-utils"
#"screepsmod-mongo"
];
bots = {
simplebot = "screepsbot-zeswarm";
};
serverConfig = {
welcomeText = "<h1 style=\"text-align: center;\">My Cool Server</h1>";
constants = {
"TEST_CONSTANT" = 123;
};
tickRate = 1000;
};
};
in
{
unitConfig = {
StartLimitInterval = 200;
StartLimitBurst = 2;
};
serviceConfig = {
Restart = mkForce (if debug then "no" else "always");
RestartSec = 30;
ExecStartPre = [
(toString (pkgs.writers.writeDash "create-screeps-config" ''
mkdir -p /srv/screeps/
chown 1000:1000 -R /srv/screeps
${optionalString debug "mkdir -p /srv/screeps-tmp"}
${optionalString debug "chown 1000:1000 -R /srv/screeps-tmp"}
echo '${configuration}' > /srv/screeps/config.yaml
''))
];
};
};
#networking.firewall.allowedTCPPorts = [ 8123 ];
#networking.firewall.allowedUDPPorts = [ 8123 ];
#networking.firewall.interfaces.wg0.allowedTCPPorts = [ 8123 ];
#networking.firewall.interfaces.wg0.allowedUDPPorts = [ 8123 ];
}

View file

@ -1,84 +0,0 @@
{ config, pkgs, lib, ... }:
let cfg = config.programs.custom.bash;
in {
options.programs.custom.bash.enable = lib.mkEnableOption "enable bash config";
config = lib.mkIf cfg.enable {
programs.bash = {
# BashCompletion
# --------------
enableCompletion = true;
# Configure Shell
# ---------------
interactiveShellInit = # sh
''
# use vi shortcuts
# ----------------
set -o vi
# Configure ls-colors
# -------------------
export LS_COLORS='rs=0:di=01;35:ln=01;36:mh=00:pi=40;33:so=01;35:do=01;35:bd=40;33;01:cd=40;33;01:or=01;05;37;41:mi=01;05;37;41:su=37;41:sg=30;43:ca=30;41:tw=30;42:ow=34;42:st=37;44:ex=01;33:*.tar=01;31:*.tgz=01;31:*.arc=01;31:*.arj=01;31:*.taz=01;31:*.lha=01;31:*.lz4=01;31:*.lzh=01;31:*.lzma=01;31:*.tlz=01;31:*.txz=01;31:*.tzo=01;31:*.t7z=01;31:*.zip=01;31:*.z=01;31:*.Z=01;31:*.dz=01;31:*.gz=01;31:*.lrz=01;31:*.lz=01;31:*.lzo=01;31:*.xz=01;31:*.bz2=01;31:*.bz=01;31:*.tbz=01;31:*.tbz2=01;31:*.tz=01;31:*.deb=01;31:*.rpm=01;31:*.jar=01;31:*.war=01;31:*.ear=01;31:*.sar=01;31:*.rar=01;31:*.alz=01;31:*.ace=01;31:*.zoo=01;31:*.cpio=01;31:*.7z=01;31:*.rz=01;31:*.cab=01;31:*.jpg=01;35:*.jpeg=01;35:*.gif=01;35:*.bmp=01;35:*.pbm=01;35:*.pgm=01;35:*.ppm=01;35:*.tga=01;35:*.xbm=01;35:*.xpm=01;35:*.tif=01;35:*.tiff=01;35:*.png=01;35:*.svg=01;35:*.svgz=01;35:*.mng=01;35:*.pcx=01;35:*.mov=01;35:*.mpg=01;35:*.mpeg=01;35:*.m2v=01;35:*.mkv=01;35:*.webm=01;35:*.ogm=01;35:*.mp4=01;35:*.m4v=01;35:*.mp4v=01;35:*.vob=01;35:*.qt=01;35:*.nuv=01;35:*.wmv=01;35:*.asf=01;35:*.rm=01;35:*.rmvb=01;35:*.flc=01;35:*.avi=01;35:*.fli=01;35:*.flv=01;35:*.gl=01;35:*.dl=01;35:*.xcf=01;35:*.xwd=01;35:*.yuv=01;35:*.cgm=01;35:*.emf=01;35:*.ogv=01;35:*.ogx=01;35::*.aac=00;36:*.au=00;36:*.flac=00;36:*.m4a=00;36:*.mid=00;36:*.midi=00;36:*.mka=00;36:*.mp3=00;36:*.mpc=00;36:*.ogg=00;36:*.ra=00;36:*.wav=00;36:*.oga=00;36:*.opus=00;36:*.spx=00;36:*.xspf=00;36:'
'';
# Configure Prompt
# ----------------
promptInit = # sh
''
# PS1 content functions
# ---------------------
function nonzero_return() {
RETVAL=$?
[ $RETVAL -ne 0 ] && echo "[> $RETVAL <] "
}
# Provide a nice prompt
# ---------------------
case $TERM in
xterm*|rxvt*|Eterm)
# used : http://ezprompt.net/
USER_COLOR="\[\e[36m\]\u\[\e[m\]\[\e[32m\]@\[\e[m\]\[\e[36m\]\h\[\e[m\]"
CURRENT_PATH="\[\e[33m\][\[\e[m\]\[\e[33m\]\w\[\e[m\]\[\e[33m\]]\[\e[m\]"
if [[ $UID -eq 0 ]]
then
USER_COLOR="\[\e[31m\]\u\[\e[m\]\[\e[32m\]@\[\e[m\]\[\e[31m\]\h\[\e[m\]"
fi
export PS1="\[\e[31m\]\`nonzero_return\`\[\e[m\]\[\e[35m\]\A\[\e[m\] $USER_COLOR $CURRENT_PATH\[\e[31m\]\\$\[\e[m\] "
;;
screen)
export PS1="\[\e[31m\]\`nonzero_return\`\[\e[m\]\[\e[35m\]\A\[\e[m\] \[\e[36m\]\u\[\e[m\]\[\e[32m\]@\[\e[m\]\[\e[36m\]\h\[\e[m\] \[\e[33m\][\[\e[m\]\[\e[33m\]\W\[\e[m\]\[\e[33m\]]\[\e[m\]\[\e[31m\]\\$\[\e[m\] "
;;
esac
'';
# Shell Aliases
# -------------
shellAliases = {
ls = "ls --color=tty";
l = "ls -CFh";
la = "ls -Ah";
ll = "ls -lh";
lt = "ls -lct --reverse";
less = "less -S";
top = "htop";
version = "date '+%Y%m%d%H%M%S'";
vclip = "xclip -selection clipboard";
df = "df -h";
nix-search = "nix-env -qaP";
nix-list = ''nix-env -qaP "*" --description'';
nix-list-haskell = ''nix-env -f "<nixpkgs>" -qaP -A haskellPackages'';
nix-show-garbadge-roots = "ls -lh /nix/var/nix/gcroots/auto/";
};
};
};
}

View file

@ -1,43 +0,0 @@
{ config, pkgs, lib, ... }:
with lib;
let
xterm-colors = pkgs.writeShellScriptBin "256-xterm-colors"
# sh
''
for i in {0..255} ; do
printf "\x1b[38;5;%sm%3d\e[0m " "$i" "$i"
if (( i == 15 )) || (( i > 15 )) && (( (i-15) % 6 == 0 )); then
printf "\n";
fi
done
'';
xterm-background-colors = pkgs.writeShellScriptBin
"256-xterm-colors-background"
# sh
''
for i in {0..255} ; do
printf "\x1b[48;5;%sm%3d\e[0m " "$i" "$i"
if (( i == 15 )) || (( i > 15 )) && (( (i-15) % 6 == 0 )); then
printf "\n";
fi
done
'';
cfg = config.programs.custom.shellTools;
in
{
options.programs.custom.shellTools.enable =
mkEnableOption "enable shell tools";
config = mkIf cfg.enable {
environment.systemPackages = [ xterm-colors xterm-background-colors ];
};
}

View file

@ -1,111 +0,0 @@
{ config, pkgs, lib, ... }:
with lib;
let
cfg = config.programs.custom.zsh;
in
{
options.programs.custom.zsh = {
enable = mkEnableOption "enable zsh";
mainUser = mkOption {
type = with types; nullOr str;
default = null;
description = ''
the main User if available
'';
};
};
config = mkIf cfg.enable {
programs.zsh = {
enable = true;
enableCompletion = true;
syntaxHighlighting.enable = true;
ohMyZsh = {
custom = "/etc/zshcustom/";
enable = false;
# powerline themes
# ----------------
theme = "powerlevel9k/powerlevel9k";
plugins = [
"git"
"git-flow"
"screen"
"taskwarrior"
"systemd"
"tmux"
"vi-mode"
"wd"
];
};
#loginShellInit = ''
# export TERM="xterm-256color"
#'';
shellAliases = {
ls = "ls --color=tty";
l = "ls -CFh";
la = "ls -Ah";
ll = "ls -lh";
lt = "ls -lct --reverse";
less = "less -S";
top = "htop";
version = "date '+%Y%m%d%H%M%S'";
vclip = "xclip -selection clipboard";
df = "df -h";
timestamp = "date +%Y%m%d%H%M%S";
#nix-search = "nix-env -qaP";
#nix-list = ''nix-env -qaP "*" --description'';
#nix-list-haskell = ''nix-env -f "<nixpkgs>" -qaP -A haskellPackages'';
#nix-list-node = ''nix-env -f "<nixpkgs>" -qaP -A nodePackages'';
#nix-list-beam = ''nix-env -f "<nixpkgs>" -qaP -A beamPackages'';
#nix-find = "clear ; ${pkgs.nix-index}/bin/nix-locate -1 -w";
nix-show-garbadge-roots = "ls -lh /nix/var/nix/gcroots/auto/";
};
};
# only used to make quick config changes
# --------------------------------------
#environment.etc."zshcustom/mainuser.zsh".source =
# pkgs.writeText "mainuser-zsh" (if (cfg.mainUser != null) then ''
# source ${config.users.users.mainUser.home}/.zshrc
# '' else
# "# programs.custom.zsh.mainUser not set ");
# Theme
# -----
#environment.etc."zshcustom/themes/powerlevel9k".source =
# pkgs.fetchFromGitHub {
# owner = "bhilburn";
# repo = "powerlevel9k";
# rev = "v0.6.4";
# sha256 = "104wvlni3rilpw9v1dk848lnw8cm8qxl64xs70j04ly4s959dyb5";
# };
#environment.etc."zshcustom/powerlevel9kpatch.zsh".source =
# pkgs.writeText "powerlevel9kpatch.zsh" ''
# # prompt elements
# # ---------------
# POWERLEVEL9K_LEFT_PROMPT_ELEMENTS=(vi_mode context dir vcs custom_jail background_jobs time status)
# POWERLEVEL9K_RIGHT_PROMPT_ELEMENTS=()
#
# # root_indicator
# # --------------
# POWERLEVEL9K_ROOT_ICON="#"
# POWERLEVEL9K_ROOT_INDICATOR_FOREGROUND="black"
# POWERLEVEL9K_ROOT_INDICATOR_BACKGROUND="red"
# '';
};
}

View file

@ -1,76 +0,0 @@
{ config, pkgs, lib, ... }: {
imports = [
../../components
../../modules
./hardware-configuration.nix
./packages.nix
./syncthing.nix
./tinc.nix
./wireguard.nix
];
components.gui.enable = true;
components.terminal.enable = true;
components.network.enable = true;
components.network.wifi.enable = true;
components.mainUser.enable = true;
users.users.mainUser.extraGroups = [ "adbusers" "video" ];
services.printing.enable = false;
services.nginx.enable = true;
networking.hostName = "sterni";
services.flatpak.enable = true;
security.wrappers = {
pmount = {
source = "${pkgs.pmount}/bin/pmount";
setuid = true;
owner = "root";
group = "root";
};
pumount = {
source = "${pkgs.pmount}/bin/pumount";
setuid = true;
owner = "root";
group = "root";
};
};
# still needed?
home-manager.users.mainUser.home.stateVersion = "22.11";
virtualisation = {
docker.enable = true;
podman.enable = true;
virtualbox = {
host.enable = false;
guest.enable = false;
};
};
services.xserver.desktopManager.gnome.enable = true;
samba-share = {
enable = false;
folders = {
share = "/home/share";
video = "/home/video-material";
};
};
# for congress and streaming
hardware.opengl = {
enable = true;
driSupport = true;
driSupport32Bit = true;
};
}

View file

@ -1,85 +0,0 @@
# 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, modulesPath, ... }:
{
imports = [ "${modulesPath}/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, not grub
boot.loader.systemd-boot.enable = true;
boot.loader.efi.canTouchEfiVariables = true;
boot.tmpOnTmpfs = true; # make /tmp a tmpfs (performance!)
#zramSwap = {
# enable = true;
# numDevices = 2;
# swapDevices = 1;
# memoryPercent = 50;
#};
fileSystems."/share" = {
device = "none";
fsType = "tmpfs";
};
fileSystems."/browsers" = {
device = "none";
fsType = "tmpfs";
};
nix.settings.max-jobs = lib.mkDefault 4;
# lvm volume group
# ----------------
boot.initrd.luks.devices = {
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

@ -1,96 +0,0 @@
{ config, lib, pkgs, ... }:
let
nextcloudSync = folder:
let
password = "$( ${pkgs.pass}/bin/pass show home/nextcloud/palo/nextcloudcmd-token )";
user = "palo";
in
pkgs.writers.writeBashBin "nextcloud-sync-${folder}" ''
${pkgs.nextcloud-client}/bin/nextcloudcmd \
--path "${folder}" \
~/Nextcloud/${folder} \
"https://${user}:${password}@nextcloud.ingolf-wagner.de"
'';
in
{
environment.systemPackages = with pkgs; [
((ganttproject-bin.override {
jre = pkgs.openjdk11;
}).overrideAttrs (old: {
version = "3.1.3100";
src = pkgs.fetchzip {
url = "https://dl.ganttproject.biz/ganttproject-3.1.3100/ganttproject-3.1.3100.zip";
sha256 = "sha256-hw2paak0P670/kemiuqYHIaN0uUtkVKy+AX2X7OdnJ4=";
};
}))
autorandr
(nextcloudSync "InstantUpload")
(nextcloudSync "Pictures")
(nextcloudSync "Unterlagen")
(nextcloudSync "Nähen")
(nextcloudSync "Video")
(nextcloudSync "Kunstbuch")
(nextcloudSync "AWS-SolutionArchitect-Professional")
#(pkgs.writeShellScriptBin "nixFlakes" ''
# exec ${pkgs.nixUnstable}/bin/nix --experimental-features "nix-command flakes" "$@"
#'')
valentina
signal-desktop
legacy_2311.fluffychat
sweethome3d.application
pkgs.polygon-art.polygon-art
# bluetooth gui
blueberry
nextcloud-client
gimp
inkscape
imagemagick
bitwig-studio3
#sononym-crawler
darktable
#blender
mosquitto
(pkgs.writers.writeBashBin "mqtt-tail" ''
${pkgs.mosquitto}/bin/mosquitto_sub -v \
-h pepe.private \
-u homeassistant \
-P password \
-t "#"
'')
tor-browser-bundle-bin
#(tor-browser-bundle-bin.overrideAttrs (old: rec {
# version = "11.0.1";
# name = "tor-browser-bundle-${version}";
# src = pkgs.fetchurl {
# url =
# "https://dist.torproject.org/torbrowser/10.0.15/tor-browser-linux64-10.0.15_en-US.tar.xz";
# "https://dist.torproject.org/torbrowser/11.0.1/tor-browser-linux64-11.0.1_en-US.tar.xz";
# sha256 = "1ah69jmfgik063f9gkvyv9d4k706pqihmzc4k7cc95zyd17v8wrs";
# };
#}))
sops
bitwarden
];
home-manager.users.mainUser = {
programs.obs-studio.enable = true;
};
}

View file

@ -1,16 +0,0 @@
{ config, lib, pkgs, ... }:
{
virtualisation.libvirtd.enable = true;
virtualisation.libvirtd.onShutdown = "shutdown";
environment.systemPackages = [
pkgs.qemu_kvm
pkgs.virt-manager
];
users.users.mainUser.extraGroups = [ "libvirtd" ];
}

View file

@ -1,9 +0,0 @@
{ config, lib, pkgs, ... }:
{
services.grocy-scanner = {
enable = true;
host = "https://grocy.ingolf-wagner.de";
device = "/dev/input/by-id/usb-Belon.cn_2.4G_Wireless_Device_Belon_Smart-event-kbd";
apiKeyFile = toString (pkgs.writeText "key" "my-api-key-not");
};
}

View file

@ -1,66 +0,0 @@
{ config, pkgs, lib, ... }: {
sops.secrets.syncthing_cert = { };
sops.secrets.syncthing_key = { };
services.syncthing = {
enable = true;
openDefaultPorts = false;
user = "palo";
dataDir = "/home/palo/.syncthing";
configDir = "/home/palo/.syncthing";
cert = toString config.sops.secrets.syncthing_cert.path;
key = toString config.sops.secrets.syncthing_key.path;
overrideFolders = true;
folders = {
# on encrypted drive
# ------------------
password-store = {
enable = true;
path = "/home/palo/.password-store";
};
#private = {
# enable = true;
# path = "/home/palo/private";
#};
art = {
enable = true;
path = "/home/palo/art";
};
desktop = {
enable = true;
path = "/home/palo/desktop";
};
finance = {
enable = true;
path = "/home/palo/finance";
};
# no need to be encrypted
# -----------------------
books = {
enable = true;
path = "/home/palo/books";
};
music-library = {
enable = true;
path = "/home/palo/music-library";
};
#music-projects = {
# enable = true;
# path = "/home/palo/music-projects";
#};
};
};
services.permown."/home/palo/music-library" = {
owner = "palo";
group = "users";
};
services.permown."/home/palo/finance" = {
owner = "palo";
group = "syncthing";
};
}

View file

@ -1,15 +0,0 @@
{ config, ... }:
{
tinc.private.enable = true;
tinc.private.ipv4 = "10.23.42.24";
tinc.secret.enable = true;
tinc.secret.ipv4 = "10.123.42.24";
# retiolum
#networking.retiolum.port = 720;
#sops.secrets.tinc_retiolum_ed25519_key = { };
#services.tinc.networks.retiolum.ed25519PrivateKeyFile = config.sops.secrets.tinc_retiolum_ed25519_key.path;
}

View file

@ -1,27 +0,0 @@
{ config, ... }:
{
networking.firewall.allowedUDPPorts = [ 51820 ];
sops.secrets.wireguard_private = { };
# Enable WireGuard
networking.wg-quick.interfaces = {
# Hub and Spoke Setup
# https://www.procustodibus.com/blog/2020/11/wireguard-hub-and-spoke-config/
wg0 = {
address = [ "10.100.0.3/32" ];
listenPort = 51820; # to match firewall allowedUDPPorts (without this wg uses random port numbers)
privateKeyFile = config.sops.secrets.wireguard_private.path;
mtu = 1280;
peers = [
{
# robi
publicKey = "uWR93xJe5oEbX3DsAYpOS9CuSg1VmXEQxJzdlJpe3DU=";
allowedIPs = [ "10.100.0.1/24" ];
#endpoint = "ingolf-wagner.de:51820";
endpoint = "95.216.66.212:51820";
}
];
};
};
}

View file

@ -1,31 +0,0 @@
{ pkgs, ... }:
{
environment.systemPackages = [
(pkgs.writers.writeBashBin "torrent-sync" ''
set -e
set -x
file_folder=$( realpath "$1" )
folder=$( dirname "$file_folder" )
file=$( basename "$file_folder" )
pushd "$folder"
${pkgs.transmission}/bin/transmission-create \
-t udp://robi.private:6969/announce \
-o ~/last.torrent \
"$file"
popd
${pkgs.transmission}/bin/transmission-remote \
sync.chungus.private:80 \
-a ~/last.torrent \
--download-dir "$folder"
${pkgs.transmission}/bin/transmission-remote \
sync.robi.private:80 \
-a ~/last.torrent \
--download-dir "$folder"
'')
];
}

View file

@ -1,112 +0,0 @@
{ lib, pkgs, config, ... }:
let
uiPort = 9099;
announceIp = "10.23.42.28";
peerPort = 51433;
in
{
containers.sync-torrent = {
# mount host folders
bindMounts = {
media = {
hostPath = "/media";
mountPoint = "/media"; # must be here otherwise transmission can't see the folder
isReadOnly = false;
};
lib = {
hostPath = "/srv/sync-torrent";
mountPoint = "/var/lib/transmission";
isReadOnly = false;
};
};
autoStart = true;
config = { config, pkgs, lib, ... }: {
system.stateVersion = "23.11";
services.journald.extraConfig = "SystemMaxUse=1G";
services.transmission = {
enable = true;
settings = {
download-dir = "/media";
incomplete-dir = "/var/lib/transmission/incomplete"; # todo put this somewhere with frequent snapshots but low keep.
incomplete-dir-enabled = true;
message-level = 1;
umask = 2;
rpc-whitelist-enabled = false;
rpc-host-whitelist-enabled = false;
rpc-port = uiPort;
rpc-enable = true;
rpc-bind-address = "0.0.0.0";
# "normal" speed limits
speed-limit-down-enabled = false;
speed-limit-down = 1000; # in Kib/s
speed-limit-up-enabled = true;
speed-limit-up = 1000; # in Kib/s
upload-slots-per-torrent = 8;
# Queuing
# When true, Transmission will only download
# download-queue-size non-stalled torrents at once.
download-queue-enabled = true;
download-queue-size = 3;
# When true, torrents that have not shared data for
# queue-stalled-minutes are treated as 'stalled'
# and are not counted against the queue-download-size
# and seed-queue-size limits.
queue-stalled-enabled = true;
queue-stalled-minutes = 60;
# When true. Transmission will only seed seed-queue-size
# non-stalled torrents at once.
seed-queue-enabled = false;
seed-queue-size = 10;
# Enable UPnP or NAT-PMP.
peer-port = peerPort;
port-forwarding-enabled = false;
announce-ip = announceIp;
announce-ip-enabled = true;
# Start torrents as soon as they are added
start-added-torrents = true;
};
};
};
};
# open ports for logging
#networking.firewall.interfaces."ve-torrent".allowedTCPPorts =
# [ 5044 12304 12305 ];
#networking.firewall.interfaces."ve-torrent".allowedUDPPorts =
# [ 5044 12304 12305 ];
# host nginx setup
# ----------------
# curl -H "Host: sync.chungus.private" https://robi.private/ < will work
# curl -H "Host: sync.chungus.private" https://144.76.13.147/ < wont work
services.nginx = {
enable = true;
recommendedProxySettings = true;
virtualHosts = {
"sync.${config.networking.hostName}.private" = {
extraConfig = ''
allow ${config.tinc.private.subnet};
deny all;
'';
locations."/" = {
proxyPass = "http://127.0.0.1:${toString uiPort}";
};
};
};
};
}

View file

@ -1,131 +0,0 @@
{ config, pkgs, ... }:
let
inherit (config.services.dendrite.settings.global) server_name;
matrix_host = "matrix.terranix.org";
element_host = "element.terranix.org";
element-web-terranix.org =
pkgs.runCommand "element-web-with-config"
{
nativeBuildInputs = [ pkgs.buildPackages.jq ];
} ''
cp -r ${pkgs.element-web} $out
chmod -R u+w $out
jq '."default_server_config"."m.homeserver" = { "base_url": "https://${matrix_host}:443", "server_name": "${server_name}" }' \
> $out/config.json < ${pkgs.element-web}/config.json
ln -s $out/config.json $out/config.${matrix_host}.json
'';
in
{
# $ nix-shell -p dendrite --run 'generate-keys --private-key /tmp/key'
sops.secrets.matrix-server-key = { };
services.dendrite = {
enable = true;
httpPort = 8043;
settings = {
global = {
server_name = "terranix.org";
# `private_key` has the type `path`
# prefix a `/` to make `path` happy
private_key = "/$CREDENTIALS_DIRECTORY/matrix-server-key";
trusted_third_party_id_servers = [
"matrix.org"
"vector.im"
"xaos.space"
"lassul.us"
"thalheim.io"
"nixos.org"
"chaospott.de"
];
metrics.enabled = false;
};
logging = [
{
type = "std";
level = "warn";
}
];
client_api = {
registration_disabled = true;
rate_limiting.enabled = false;
# set only for the first admin account, than remove.
#registration_shared_secret = ""; # disable once first admin account is created
};
media_api = {
dynamic_thumbnails = true;
};
mscs = {
mscs = [ "msc2836" "msc2946" ];
};
sync_api = {
real_ip_header = "X-Real-IP";
};
federation_api = {
key_perspectives = [
{
server_name = "matrix.org";
keys = [
{
key_id = "ed25519:auto";
public_key = "Noi6WqcDj0QmPxCNQqgezwTlBKrfqehY1u2FyWP9uYw";
}
{
key_id = "ed25519:a_RXGa";
public_key = "l8Hft5qXKn1vfHrg3p4+W8gELQVo8N13JkluMfmn2sQ";
}
];
}
];
prefer_direct_fetch = false;
};
};
};
systemd.services.dendrite.serviceConfig.LoadCredential = [
"matrix-server-key:${config.sops.secrets.matrix-server-key.path}"
];
# Verify if federation works with
# https://federationtester.matrix.org/#terranix.org
services.nginx.virtualHosts.${matrix_host} = {
listen = [
{
addr = "0.0.0.0";
port = 443;
ssl = true;
}
{
addr = "0.0.0.0";
port = 8448;
ssl = true;
extraParameters = [ "default_server" ];
}
];
forceSSL = true;
enableACME = true;
extraConfig = ''
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_read_timeout 600;
'';
locations."/".proxyPass = "http://127.0.0.1:${toString config.services.dendrite.httpPort}";
};
networking.firewall.allowedTCPPorts = [ 8448 ];
networking.firewall.allowedUDPPorts = [ 8448 ];
services.nginx.virtualHosts.${element_host} = {
forceSSL = true;
enableACME = true;
extraConfig = ''
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_read_timeout 600;
'';
locations."/".root = element-web-terranix.org;
};
}

View file

@ -1,21 +0,0 @@
{ config, pkgs, ... }:
{
services.trilium-server = {
enable = true;
dataDir = "/srv/trilium";
instanceName = config.networking.hostName;
host = "10.23.42.28";
#noAuthentication = true;
nginx = {
enable = true;
hostName = "trilium.${config.networking.hostName}.private";
};
};
services.nginx.virtualHosts."${config.services.trilium-server.nginx.hostName}".extraConfig = ''
allow ${config.tinc.private.subnet};
deny all;
'';
}

View file

@ -1,225 +0,0 @@
{ config, lib, pkgs, ... }:
let
cfg = config.programs.custom.vim;
nix-xptemplates = pkgs.writeTextFile {
name = "nix-xptemplates";
destination = "/ftplugin/nix/nix.xpt.vim";
text = # vim
''
XPTemplate priority=personal
XPT option " tips
`name^ = mkOption {
type = with types; `type^;
description = ${"''"}
`cursor^
${"''"};
};
XPT package " tips
{ config, lib, ... }:
{
`cursor^
}
XPT terranix" tips
{ config, lib, pkgs, ... }:
with lib;
let
cfg = config.`name^;
in {
options.`name^ = mkOption {
default = {};
type = with types; attrsOf (submodule ({ name, ... }:{
options = {
enable = mkEnableOption "`name^.name";
};
}));
};
config =
let
allConfigs = cfg
in
mkIf (cfg != {} ){
`cursor^
};
}
XPT module " tips
{ config, lib, pkgs, ... }:
with lib;
let
cfg = config.`name^;
in {
options.`name^ = {
enable = mkEnableOption "enable `name^";
};
config = mkIf cfg.enable {
`cursor^
};
}
XPT shell " tips
{ pkgs ? import <nixpkgs> {} }:
pkgs.mkShell {
# needed pkgs
# -----------
buildInputs = with pkgs; [
`name^
];
# run this on start
# -----------------
shellHook = ${"''"}
HISTFILE=${"$"}{toString ./.}/.history
${"''"};
}
XPT fhsUser " tips
{ pkgs ? import <nixpkgs> {} }:
(pkgs.buildFHSUserEnv {
name = "fhs-user-env";
targetPkgs = pkgs: with pkgs; [
# core stuff
# ----------
vim silver-searcher curl coreutils git tig
# common X dependencies
# ---------------------
atk cairo dbus eudev expat fontconfig freetype gdk_pixbuf glib gnome3.GConf gtk2-x11
mesa_glu nspr nss pango xlibs.libXScrnSaver xlibs.libXcomposite xlibs.libXcursor
xlibs.libXdamage xlibs.libXfixes xlibs.libXi xlibs.libXrender xlibs.libXtst xorg.libX11
xorg.libXext xorg.libXinerama xorg.libxcb
liblo zlib fftw minixml libcxx alsaLib glibc
# new stuff
# ---------
`cursor^
];
# multilib packages
# -----------------
# these are packages compiled 32bit and 64bit
multiPkgs = pkgs: with pkgs; [
];
# environment variables
# ---------------------
profile = ${"''"}
export TERM="xterm"
${"''"};
}).env
'';
};
# active plugins
# --------------
extra-runtimepath = with pkgs;
lib.concatMapStringsSep "," (pkg: "${pkg.outPath}") [
vimPlugins.Syntastic
vimPlugins.ack-vim
vimPlugins.airline
vimPlugins.vim-nix
vimPlugins.xptemplate
];
# the vimrc
# ---------
vimrc = pkgs.writeText "vimrc" ''
" turn on linenumbers
" to turn of :set nonumber
:set number
" show Trailing Whitespaces
:set list listchars=tab:»·,trail:
" Map leader is the key for shortcuts
nnoremap <SPACE> <Nop>
let mapleader = "\<Space>"
" move blocks of text in visual mode
" does not work correctly
vmap <up> xkP`[V`]
vmap <down> xp`[V`]
" search/grep case insensitive
:set ignorecase
" tabs should always be 2 spaces
set et ts=2 sts=2 sw=2
" installed vim-plugins
set runtimepath=${extra-runtimepath},$VIMRUNTIME,$HOME/.vim,${nix-xptemplates}
" syntax highlighting on
syntax off
" xptemplates
" -----------
" a plugin to insert snippets on demand
set nocompatible
filetype plugin on
" enable cursor cross
" -------------------
":hi CursorLine cterm=NONE ctermbg=darkred ctermfg=white guibg=darkred guifg=white
":hi CursorColumn cterm=NONE ctermbg=darkred ctermfg=white guibg=darkred guifg=white
:hi CursorLine cterm=NONE ctermbg=0 guibg=#073642
:hi CursorColumn cterm=NONE ctermbg=0 guibg=#073642
set cursorline
set cursorcolumn
" save view
" ---------
augroup AutoSaveFolds
autocmd!
autocmd BufWinLeave * mkview
autocmd BufWinEnter * silent loadview
augroup END
" some language stuff
" -------------------
:map <leader>s :setlocal spell spelllang=en
'';
in
{
# no options
options.programs.custom.vim.enable = lib.mkEnableOption "vim";
config = lib.mkIf cfg.enable {
# create vimrc
# ------------
# and load it as config for vim
environment.variables.VIMINIT = ":so /etc/vimrc";
environment.etc.vimrc.source = vimrc;
# set vim to the default editor
# -----------------------------
programs.vim.defaultEditor = true;
# install vim
# -----------
environment.systemPackages = [ pkgs.vim ];
};
}

View file

@ -1,45 +0,0 @@
{ config, pkgs, ... }:
# To create a sign at the door
# "Sorry Doorbell is broken, please scan this QR Code
#
# create QR Code with:
# qrencode -o ./test.png http://ring.ingolf-wagner.de
#
# for secure urls check
# https://www.nginx.com/blog/securing-urls-secure-link-module-nginx-plus/
{
sops.secrets.ringPushover = {
owner = config.services.webhook.user;
};
services.webhook = {
enable = true;
hooks = {
ring = {
execute-command =
let
script = pkgs.writers.writeBash "ring-script" ''
. ${config.sops.secrets.ringPushover.path}
${pkgs.curl}/bin/curl -s \
--form-string "token=$API_KEY" \
--form-string "user=$USER_KEY" \
--form-string "title=Klingeling" \
--form-string "message=Jemand an der Tür" \
https://api.pushover.net/1/messages.json
'';
in
toString script;
response-message = "It's ringing";
};
};
};
services.nginx.virtualHosts."ring.ingolf-wagner.de" = {
enableACME = true;
forceSSL = true;
locations."/" = {
proxyPass = "http://localhost:${toString config.services.webhook.port}/${config.services.webhook.urlPrefix}/ring";
};
};
}

View file

@ -1,38 +0,0 @@
{ 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
{
# configure weechat
services.weechat = { enable = true; };
# configure bitlbee
services.bitlbee = {
enable = true;
libpurple_plugins = [
#pkgs.pidgin-otr
#pkgs.purple-facebook
#pkgs.purple-discord
#pkgs.purple-matrix
#pkgs.purple-hangouts
#pkgs.pidgin-latex
#pkgs.pidgin-opensteamworks
#pkgs.pidgin-skypeweb
pkgs.telegram-purple
#pkgs.purple-lurch
];
plugins =
[ pkgs.bitlbee-facebook pkgs.bitlbee-steam pkgs.bitlbee-mastodon ];
};
# otherwise xterm is the only thing that works
environment.systemPackages = [ pkgs.rxvt_unicode ];
backup.dirs = [ config.services.weechat.root ];
}

View file

@ -1,85 +0,0 @@
{ 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

@ -1,45 +0,0 @@
{ pkgs, config, ... }: {
users.users.mainUser.extraGroups = [ "wireshark" ];
programs.wireshark.enable = true;
environment.systemPackages = [
pkgs.wireshark
# alternative packet analyzer (only works with elasticsearch)
pkgs.packetbeat7
];
# elastic search is good for analysing stuff
# https://www.elastic.co/blog/analyzing-network-packets-with-wireshark-elasticsearch-and-kibana
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;
# using tshark with elastic search
# --------------------------------
# tshark -r file.pcap -T ek > packages.json
# curl -XPOST "sterni.private:9200/packets/doc/_bulk" -H 'Content-Type: application/json' --data-binary "@packets.json"
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
}";
};
};
};
};
}