update robi and started with orbi
This commit is contained in:
parent
3366e9e65e
commit
2a2edf13f9
46 changed files with 3525 additions and 8 deletions
|
@ -84,7 +84,7 @@ in
|
|||
#fractal
|
||||
#legacy_2205.mirage-im
|
||||
#cinny-desktop
|
||||
#fluffychat
|
||||
fluffychat
|
||||
#(fluffychat.overrideAttrs
|
||||
# (old: rec {
|
||||
# version = "1.13.0";
|
||||
|
|
18
nixos/machines/orbi/borg.nix
Normal file
18
nixos/machines/orbi/borg.nix
Normal file
|
@ -0,0 +1,18 @@
|
|||
{ lib, config, pkgs, ... }: {
|
||||
|
||||
backup.enable = true;
|
||||
|
||||
# provide repository
|
||||
services.borgbackup.repos = {
|
||||
default = {
|
||||
quota = "300G";
|
||||
allowSubRepos = true;
|
||||
authorizedKeys = [
|
||||
(lib.fileContents ../../assets/ssh/borg_access.pub)
|
||||
(lib.fileContents ../../assets/ssh/palo_rsa.pub)
|
||||
];
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
}
|
13
nixos/machines/orbi/cache.nix
Normal file
13
nixos/machines/orbi/cache.nix
Normal file
|
@ -0,0 +1,13 @@
|
|||
{ ... }:
|
||||
{
|
||||
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
|
||||
|
||||
};
|
||||
|
||||
|
||||
}
|
34
nixos/machines/orbi/codimd.nix
Normal file
34
nixos/machines/orbi/codimd.nix
Normal file
|
@ -0,0 +1,34 @@
|
|||
{ 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;
|
||||
};
|
||||
};
|
||||
|
||||
}
|
||||
|
112
nixos/machines/orbi/configuration.nix
Normal file
112
nixos/machines/orbi/configuration.nix
Normal file
|
@ -0,0 +1,112 @@
|
|||
{ lib, config, pkgs, ... }: {
|
||||
imports = [
|
||||
|
||||
../../system/all/nginx.nix
|
||||
../../system/all/borg-jobs.nix
|
||||
../../system/all/defaults.nix
|
||||
../../system/all/syncthing.nix
|
||||
../../system/server/netdata.nix
|
||||
../../system/server/packages.nix
|
||||
|
||||
../../components
|
||||
|
||||
../../modules
|
||||
|
||||
./hetzner.nix
|
||||
|
||||
# services
|
||||
./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
|
||||
#./media-tdarr.nix
|
||||
#./media-unmanic.nix
|
||||
|
||||
./sync-opentracker.nix
|
||||
./sync-torrent.nix
|
||||
|
||||
#./social-jitsi.nix
|
||||
|
||||
# matrix
|
||||
./terranix-dendrite.nix
|
||||
|
||||
# logging
|
||||
./loki.nix
|
||||
./loki-promtail.nix
|
||||
./prometheus.nix
|
||||
./grafana.nix
|
||||
./telegraf.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;
|
||||
|
||||
# Shell configuration
|
||||
# -------------------
|
||||
#programs.custom. zsh.enable = true;
|
||||
users.users.root.shell = pkgs.zsh;
|
||||
|
||||
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;
|
||||
|
||||
}
|
150
nixos/machines/orbi/disko-config.nix
Normal file
150
nixos/machines/orbi/disko-config.nix
Normal file
|
@ -0,0 +1,150 @@
|
|||
# nix run github:nix-community/disko -- --mode zap_create_mount ./disko-config.nix
|
||||
# nixos-generate-config --no-filesystems --root /mnt
|
||||
# vim /mnt/configuration.nix
|
||||
# nixos-install
|
||||
{ config, lib, ... }:
|
||||
let
|
||||
disks = [ "sda" "sdb" ];
|
||||
in
|
||||
{
|
||||
# ZFS already has its own scheduler. Without this my(@Artturin) computer froze for a second when i nix build something.
|
||||
# copied from : https://github.com/numtide/srvos/blob/main/nixos/common/zfs.nix
|
||||
|
||||
services.udev.extraRules = lib.optionalString (config.boot.zfs.enabled) ''
|
||||
ACTION=="add|change", KERNEL=="sd[a-z]*[0-9]*|mmcblk[0-9]*p[0-9]*|nvme[0-9]*n[0-9]*p[0-9]*", ENV{ID_FS_TYPE}=="zfs_member", ATTR{../queue/scheduler}="none"
|
||||
'';
|
||||
|
||||
disko.devices = {
|
||||
disk =
|
||||
lib.genAttrs disks (disk: {
|
||||
name = disk;
|
||||
type = "disk";
|
||||
device = "/dev/${disk}";
|
||||
content = {
|
||||
type = "table";
|
||||
format = "gpt";
|
||||
partitions = [
|
||||
{
|
||||
name = "ESP";
|
||||
start = "0";
|
||||
end = "500MiB";
|
||||
bootable = true;
|
||||
content = {
|
||||
type = "filesystem";
|
||||
format = "vfat";
|
||||
mountpoint = "/boot_${disk}";
|
||||
mountOptions = [ "defaults" ];
|
||||
};
|
||||
}
|
||||
{
|
||||
name = "zfs";
|
||||
start = "500MiB";
|
||||
size = "500GB";
|
||||
content = {
|
||||
type = "luks";
|
||||
name = "root_${disk}";
|
||||
settings = {
|
||||
# if you want to use the key for interactive login be sure there is no trailing newline
|
||||
# for example use `echo -n "password" > /tmp/secret.key`
|
||||
keyFile = "/tmp/secret.key";
|
||||
allowDiscards = true;
|
||||
};
|
||||
content = {
|
||||
type = "zfs";
|
||||
pool = "zroot";
|
||||
};
|
||||
};
|
||||
}
|
||||
{
|
||||
name = "zfs";
|
||||
size = "100%";
|
||||
content = {
|
||||
type = "luks";
|
||||
settings = {
|
||||
# if you want to use the key for interactive login be sure there is no trailing newline
|
||||
# for example use `echo -n "password" > /tmp/secret.key`
|
||||
keyFile = "/tmp/secret.key";
|
||||
allowDiscards = true;
|
||||
};
|
||||
name = "media_${disk}";
|
||||
content = {
|
||||
type = "zfs";
|
||||
pool = "zmedia";
|
||||
};
|
||||
};
|
||||
}
|
||||
];
|
||||
};
|
||||
}
|
||||
);
|
||||
|
||||
|
||||
zpool = {
|
||||
|
||||
zroot = {
|
||||
type = "zpool";
|
||||
mode = "mirror";
|
||||
rootFsOptions = {
|
||||
mountpoint = "none";
|
||||
canmount = "off";
|
||||
compression = "lz4";
|
||||
};
|
||||
datasets = {
|
||||
"root" = {
|
||||
type = "zfs_fs";
|
||||
mountpoint = "/";
|
||||
options = {
|
||||
mountpoint = "legacy";
|
||||
compression = "lz4";
|
||||
};
|
||||
};
|
||||
"store" = {
|
||||
type = "zfs_fs";
|
||||
mountpoint = "/nix/store";
|
||||
options = {
|
||||
mountpoint = "legacy";
|
||||
compression = "lz4";
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
# `zpool import -f zraid` once on the first boot and reboot
|
||||
zmedia = {
|
||||
type = "zpool";
|
||||
rootFsOptions = {
|
||||
mountpoint = "none";
|
||||
canmount = "off";
|
||||
};
|
||||
datasets = {
|
||||
"media" = {
|
||||
type = "zfs_fs";
|
||||
mountpoint = "/media";
|
||||
options = {
|
||||
mountpoint = "legacy";
|
||||
compression = "lz4";
|
||||
"com.sun:auto-snapshot:daily" = false;
|
||||
"com.sun:auto-snapshot:weekly" = false;
|
||||
"com.sun:auto-snapshot:monthly" = false;
|
||||
};
|
||||
};
|
||||
# todo make sure this disk has some minimum space
|
||||
"nextcloud" = {
|
||||
type = "zfs_fs";
|
||||
mountpoint = "/var/lib/nextcloud/";
|
||||
options = {
|
||||
mountpoint = "legacy";
|
||||
compression = "lz4";
|
||||
"com.sun:auto-snapshot:hourly" = true;
|
||||
"com.sun:auto-snapshot:daily" = true;
|
||||
"com.sun:auto-snapshot:weekly" = false;
|
||||
"com.sun:auto-snapshot:monthly" = false;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
}
|
||||
|
58
nixos/machines/orbi/finance.nix
Normal file
58
nixos/machines/orbi/finance.nix
Normal file
|
@ -0,0 +1,58 @@
|
|||
{ 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";
|
||||
};
|
||||
};
|
||||
}
|
37
nixos/machines/orbi/gitea.nix
Normal file
37
nixos/machines/orbi/gitea.nix
Normal file
|
@ -0,0 +1,37 @@
|
|||
{ 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}";
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
services.gitea = {
|
||||
enable = true;
|
||||
appName = "git.ingolf-wagner.de";
|
||||
#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" ];
|
||||
|
||||
}
|
24
nixos/machines/orbi/grafana.nix
Normal file
24
nixos/machines/orbi/grafana.nix
Normal file
|
@ -0,0 +1,24 @@
|
|||
{ 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";
|
||||
};
|
||||
};
|
||||
|
||||
}
|
130
nixos/machines/orbi/graylog.nix
Normal file
130
nixos/machines/orbi/graylog.nix
Normal file
|
@ -0,0 +1,130 @@
|
|||
{ 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."
|
||||
'';
|
||||
};
|
||||
|
||||
}
|
16
nixos/machines/orbi/grocy.nix
Normal file
16
nixos/machines/orbi/grocy.nix
Normal file
|
@ -0,0 +1,16 @@
|
|||
{ 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 ];
|
||||
|
||||
}
|
38
nixos/machines/orbi/hardware-configuration.nix
Normal file
38
nixos/machines/orbi/hardware-configuration.nix
Normal file
|
@ -0,0 +1,38 @@
|
|||
# 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";
|
||||
}
|
123
nixos/machines/orbi/hetzner.nix
Normal file
123
nixos/machines/orbi/hetzner.nix
Normal file
|
@ -0,0 +1,123 @@
|
|||
{ 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
|
||||
];
|
||||
};
|
||||
|
||||
}
|
25
nixos/machines/orbi/kibana.nix
Normal file
25
nixos/machines/orbi/kibana.nix
Normal file
|
@ -0,0 +1,25 @@
|
|||
{ 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;
|
||||
|
||||
}
|
41
nixos/machines/orbi/loki-promtail.nix
Normal file
41
nixos/machines/orbi/loki-promtail.nix
Normal file
|
@ -0,0 +1,41 @@
|
|||
{ 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";
|
||||
}
|
||||
];
|
||||
}
|
||||
];
|
||||
|
||||
};
|
||||
|
||||
};
|
||||
}
|
99
nixos/machines/orbi/loki.nix
Normal file
99
nixos/machines/orbi/loki.nix
Normal file
|
@ -0,0 +1,99 @@
|
|||
{ 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;
|
||||
# #'';
|
||||
# };
|
||||
# };
|
||||
#};
|
||||
|
||||
}
|
663
nixos/machines/orbi/mail-fetcher.nix
Normal file
663
nixos/machines/orbi/mail-fetcher.nix
Normal file
|
@ -0,0 +1,663 @@
|
|||
# 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" ];
|
||||
};
|
||||
|
||||
}
|
80
nixos/machines/orbi/media-arr.nix
Normal file
80
nixos/machines/orbi/media-arr.nix
Normal file
|
@ -0,0 +1,80 @@
|
|||
{ 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;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
}
|
41
nixos/machines/orbi/media-jellyfin.nix
Normal file
41
nixos/machines/orbi/media-jellyfin.nix
Normal file
|
@ -0,0 +1,41 @@
|
|||
{ config, lib, pkgs, ... }:
|
||||
{
|
||||
|
||||
services.jellyfin = {
|
||||
enable = true;
|
||||
openFirewall = true;
|
||||
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;
|
||||
};
|
||||
}
|
21
nixos/machines/orbi/media-share.nix
Normal file
21
nixos/machines/orbi/media-share.nix
Normal file
|
@ -0,0 +1,21 @@
|
|||
{ 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";
|
||||
};
|
||||
|
||||
|
||||
}
|
79
nixos/machines/orbi/media-syncthing.nix
Normal file
79
nixos/machines/orbi/media-syncthing.nix
Normal file
|
@ -0,0 +1,79 @@
|
|||
{ config, pkgs, lib, ... }: {
|
||||
|
||||
imports = [ ../../system/all/syncthing.nix ];
|
||||
|
||||
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" ];
|
||||
};
|
||||
|
||||
}
|
54
nixos/machines/orbi/media-tdarr.nix
Normal file
54
nixos/machines/orbi/media-tdarr.nix
Normal file
|
@ -0,0 +1,54 @@
|
|||
{ 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.wq0.allowedTCPPorts = [ 8266 ];
|
||||
#networking.firewall.interfaces.wq0.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;
|
||||
};
|
||||
};
|
||||
|
||||
}
|
259
nixos/machines/orbi/media-transmission.nix
Normal file
259
nixos/machines/orbi/media-transmission.nix
Normal file
|
@ -0,0 +1,259 @@
|
|||
{ 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}";
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
}
|
136
nixos/machines/orbi/media-transmission2.nix
Normal file
136
nixos/machines/orbi/media-transmission2.nix
Normal file
|
@ -0,0 +1,136 @@
|
|||
{ 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;
|
||||
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"
|
||||
];
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
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}";
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
}
|
40
nixos/machines/orbi/media-unmanic.nix
Normal file
40
nixos/machines/orbi/media-unmanic.nix
Normal file
|
@ -0,0 +1,40 @@
|
|||
{ 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.wq0.allowedTCPPorts = [ 8266 ];
|
||||
#networking.firewall.interfaces.wq0.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;
|
||||
};
|
||||
};
|
||||
|
||||
}
|
20
nixos/machines/orbi/mysql.nix
Normal file
20
nixos/machines/orbi/mysql.nix
Normal file
|
@ -0,0 +1,20 @@
|
|||
{ 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 ];
|
||||
|
||||
}
|
15
nixos/machines/orbi/network-tinc.nix
Normal file
15
nixos/machines/orbi/network-tinc.nix
Normal file
|
@ -0,0 +1,15 @@
|
|||
{
|
||||
|
||||
|
||||
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";
|
||||
|
||||
}
|
55
nixos/machines/orbi/network-wireguard.nix
Normal file
55
nixos/machines/orbi/network-wireguard.nix
Normal file
|
@ -0,0 +1,55 @@
|
|||
{ 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" ];
|
||||
}
|
||||
];
|
||||
};
|
||||
};
|
||||
}
|
301
nixos/machines/orbi/nextcloud.nix
Normal file
301
nixos/machines/orbi/nextcloud.nix
Normal file
|
@ -0,0 +1,301 @@
|
|||
{ 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.nextcloud27;
|
||||
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";
|
||||
dbport = 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.
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
}
|
30
nixos/machines/orbi/nginx-wkd.nix
Normal file
30
nixos/machines/orbi/nginx-wkd.nix
Normal file
|
@ -0,0 +1,30 @@
|
|||
{ 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
|
||||
}
|
158
nixos/machines/orbi/nginx.nix
Normal file
158
nixos/machines/orbi/nginx.nix
Normal file
|
@ -0,0 +1,158 @@
|
|||
{ 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 = {
|
||||
|
||||
"ingolf-wagner.de" = {
|
||||
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";
|
||||
};
|
||||
};
|
||||
"= /palo.pgp" = {
|
||||
root = pkgs.writeText "key" (lib.fileContents ../../assets/pgp.key);
|
||||
};
|
||||
"= /palo.gpg" = {
|
||||
root = pkgs.writeText "key" (lib.fileContents ../../assets/pgp.key);
|
||||
};
|
||||
"= /palo_rsa.pub" = {
|
||||
root = pkgs.writeText "key" (lib.fileContents ../../assets/ssh/palo_rsa.pub);
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
"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;
|
||||
};
|
||||
"terranix.org" = {
|
||||
forceSSL = true;
|
||||
enableACME = true;
|
||||
extraConfig = error.extraConfig;
|
||||
locations = {
|
||||
"/" = {
|
||||
root = "/srv/www/terranix";
|
||||
extraConfig = ''
|
||||
if (-d $request_filename) {
|
||||
rewrite [^/]$ $scheme://$http_host$request_uri/ permanent;
|
||||
}
|
||||
'';
|
||||
};
|
||||
} // error.locations;
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
14
nixos/machines/orbi/packages.nix
Normal file
14
nixos/machines/orbi/packages.nix
Normal file
|
@ -0,0 +1,14 @@
|
|||
{ config, pkgs, ... }: {
|
||||
environment.systemPackages = with pkgs; [
|
||||
mosh
|
||||
mediainfo
|
||||
youtube-dl
|
||||
ipset # for sshguard
|
||||
|
||||
unstable.vulnix
|
||||
(pkgs.writers.writeBashBin "vulnix-system" ''
|
||||
${pkgs.unstable.vulnix}/bin/vulnix --profile /nix/var/nix/profiles/system
|
||||
'')
|
||||
|
||||
];
|
||||
}
|
70
nixos/machines/orbi/prometheus.nix
Normal file
70
nixos/machines/orbi/prometheus.nix
Normal file
|
@ -0,0 +1,70 @@
|
|||
{ 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";
|
||||
};
|
||||
}];
|
||||
}
|
||||
];
|
||||
};
|
||||
}
|
43
nixos/machines/orbi/property.nix
Normal file
43
nixos/machines/orbi/property.nix
Normal file
|
@ -0,0 +1,43 @@
|
|||
{ 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"; };
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
}
|
73
nixos/machines/orbi/screeps.nix
Normal file
73
nixos/machines/orbi/screeps.nix
Normal file
|
@ -0,0 +1,73 @@
|
|||
{ 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 ];
|
||||
|
||||
}
|
60
nixos/machines/orbi/social-jitsi.nix
Normal file
60
nixos/machines/orbi/social-jitsi.nix
Normal file
|
@ -0,0 +1,60 @@
|
|||
{ 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 ];
|
||||
};
|
||||
|
||||
}
|
5
nixos/machines/orbi/sync-opentracker.nix
Normal file
5
nixos/machines/orbi/sync-opentracker.nix
Normal file
|
@ -0,0 +1,5 @@
|
|||
{
|
||||
services.opentracker = {
|
||||
enable = true;
|
||||
};
|
||||
}
|
111
nixos/machines/orbi/sync-torrent.nix
Normal file
111
nixos/machines/orbi/sync-torrent.nix
Normal file
|
@ -0,0 +1,111 @@
|
|||
{ 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}";
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
}
|
19
nixos/machines/orbi/taskserver.nix
Normal file
19
nixos/machines/orbi/taskserver.nix
Normal file
|
@ -0,0 +1,19 @@
|
|||
{ 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 ];
|
||||
|
||||
}
|
28
nixos/machines/orbi/telegraf.nix
Normal file
28
nixos/machines/orbi/telegraf.nix
Normal file
|
@ -0,0 +1,28 @@
|
|||
{
|
||||
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" ];
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
109
nixos/machines/orbi/terranix-dendrite.nix
Normal file
109
nixos/machines/orbi/terranix-dendrite.nix
Normal file
|
@ -0,0 +1,109 @@
|
|||
{ config, pkgs, ... }:
|
||||
let
|
||||
|
||||
inherit (config.services.dendrite.settings.global) server_name;
|
||||
|
||||
nginx-vhost = "matrix.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://${nginx-vhost}:443", "server_name": "${server_name}" }' \
|
||||
> $out/config.json < ${pkgs.element-web}/config.json
|
||||
ln -s $out/config.json $out/config.${nginx-vhost}.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"
|
||||
];
|
||||
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}"
|
||||
];
|
||||
|
||||
services.nginx.virtualHosts.${nginx-vhost} = {
|
||||
forceSSL = true;
|
||||
enableACME = true;
|
||||
extraConfig = ''
|
||||
proxy_set_header Host $host;
|
||||
proxy_set_header X-Real-IP $remote_addr;
|
||||
proxy_read_timeout 600;
|
||||
'';
|
||||
locations."/_matrix".proxyPass = "http://127.0.0.1:${toString config.services.dendrite.httpPort}";
|
||||
# for remote admin access
|
||||
locations."/_synapse".proxyPass = "http://127.0.0.1:${toString config.services.dendrite.httpPort}";
|
||||
locations."/".root = element-web-terranix.org;
|
||||
};
|
||||
|
||||
services.nginx.virtualHosts.${server_name} = {
|
||||
locations."= /.well-known/matrix/server".alias =
|
||||
pkgs.writeText "matrix-server" (builtins.toJSON { "m.server" = "${nginx-vhost}:443"; });
|
||||
locations."= /.well-known/matrix/client".alias =
|
||||
pkgs.writeText "matrix-client" (builtins.toJSON { "m.homeserver".base_url = "https://${nginx-vhost}"; });
|
||||
};
|
||||
}
|
32
nixos/machines/orbi/vaultwarden.nix
Normal file
32
nixos/machines/orbi/vaultwarden.nix
Normal file
|
@ -0,0 +1,32 @@
|
|||
{ 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."/" = {
|
||||
proxyPass = "http://localhost:${
|
||||
toString config.services.vaultwarden.config.rocketPort
|
||||
}";
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
}
|
45
nixos/machines/orbi/webhook-ring.nix
Normal file
45
nixos/machines/orbi/webhook-ring.nix
Normal file
|
@ -0,0 +1,45 @@
|
|||
{ 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";
|
||||
};
|
||||
};
|
||||
}
|
38
nixos/machines/orbi/weechat.nix
Normal file
38
nixos/machines/orbi/weechat.nix
Normal file
|
@ -0,0 +1,38 @@
|
|||
{ 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 ];
|
||||
|
||||
}
|
|
@ -18,7 +18,7 @@
|
|||
cert = toString config.sops.secrets.syncthing_cert.path;
|
||||
key = toString config.sops.secrets.syncthing_key.path;
|
||||
|
||||
folders = {
|
||||
settings.folders = {
|
||||
# on media hard drive (not encrypted)
|
||||
# -----------------------------------
|
||||
#borg-mirror = {
|
||||
|
@ -38,7 +38,7 @@
|
|||
lost-fotos = {
|
||||
enable = true;
|
||||
path = "/media/syncthing/lost-fotos.ct";
|
||||
rescanInterval = 40 * 24 * 3600;
|
||||
rescanIntervalS = 40 * 24 * 3600;
|
||||
};
|
||||
#media = {
|
||||
# enable = true;
|
||||
|
@ -49,14 +49,14 @@
|
|||
#};
|
||||
music-projects = {
|
||||
enable = true;
|
||||
watch = true;
|
||||
#watch = true;
|
||||
path = "/media/syncthing/music-projects";
|
||||
};
|
||||
nextcloud_backup = {
|
||||
enable = true;
|
||||
watch = true;
|
||||
#watch = true;
|
||||
path = "/media/syncthing/nextcloud_backup";
|
||||
rescanInterval = 23 * 3600;
|
||||
rescanIntervalS = 23 * 3600;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
|
|
@ -242,8 +242,8 @@ in
|
|||
enable = true;
|
||||
package = pkgs.nextcloud27;
|
||||
autoUpdateApps.enable = true;
|
||||
#nginx.enable = true;
|
||||
enableBrokenCiphersForSSE = false; # see https://github.com/NixOS/nixpkgs/pull/198470
|
||||
# nginx.enable = true;
|
||||
# enableBrokenCiphersForSSE = false; # see https://github.com/NixOS/nixpkgs/pull/198470
|
||||
hostName = "nextcloud.ingolf-wagner.de";
|
||||
logLevel = 2;
|
||||
https = true;
|
||||
|
|
Loading…
Reference in a new issue